summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--.mailmap3
-rw-r--r--CREDITS12
-rw-r--r--Documentation/ABI/testing/configfs-usb-gadget-uvc64
-rw-r--r--Documentation/ABI/testing/sysfs-bus-event_source-devices-vpa-pmu15
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio32
-rw-r--r--Documentation/ABI/testing/sysfs-bus-iio-adc-ad413046
-rw-r--r--Documentation/ABI/testing/sysfs-class-typec27
-rw-r--r--Documentation/ABI/testing/sysfs-class-watchdog2
-rw-r--r--Documentation/Makefile2
-rw-r--r--Documentation/admin-guide/LSM/apparmor.rst7
-rw-r--r--Documentation/admin-guide/kernel-parameters.txt5
-rw-r--r--Documentation/admin-guide/laptops/thinkpad-acpi.rst10
-rw-r--r--Documentation/admin-guide/mm/transhuge.rst2
-rw-r--r--Documentation/admin-guide/pm/amd-pstate.rst4
-rw-r--r--Documentation/arch/arm64/silicon-errata.rst7
-rw-r--r--Documentation/arch/x86/boot.rst17
-rw-r--r--Documentation/core-api/packing.rst118
-rw-r--r--Documentation/core-api/symbol-namespaces.rst8
-rw-r--r--Documentation/dev-tools/autofdo.rst168
-rw-r--r--Documentation/dev-tools/coccinelle.rst22
-rw-r--r--Documentation/dev-tools/index.rst2
-rw-r--r--Documentation/dev-tools/propeller.rst162
-rw-r--r--Documentation/devicetree/bindings/connector/usb-connector.yaml46
-rw-r--r--Documentation/devicetree/bindings/crypto/fsl,sec-v4.0.yaml10
-rw-r--r--Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adc.yaml4
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml3
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml120
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml199
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml176
-rw-r--r--Documentation/devicetree/bindings/iio/adc/adi,ad7779.yaml110
-rw-r--r--Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml1
-rw-r--r--Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml86
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml9
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml39
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml164
-rw-r--r--Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml69
-rw-r--r--Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml79
-rw-r--r--Documentation/devicetree/bindings/iio/imu/bosch,smi240.yaml51
-rw-r--r--Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml2
-rw-r--r--Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml7
-rw-r--r--Documentation/devicetree/bindings/iio/light/ti,opt3001.yaml4
-rw-r--r--Documentation/devicetree/bindings/iio/light/veml6030.yaml64
-rw-r--r--Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml107
-rw-r--r--Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml21
-rw-r--r--Documentation/devicetree/bindings/iio/magnetometer/allegromicro,als31300.yaml46
-rw-r--r--Documentation/devicetree/bindings/iio/pressure/bmp085.yaml22
-rw-r--r--Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml6
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml2
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml73
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml72
-rw-r--r--Documentation/devicetree/bindings/interconnect/qcom,sar2130p-rpmh.yaml117
-rw-r--r--Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml14
-rw-r--r--Documentation/devicetree/bindings/net/asix,ax88178.yaml4
-rw-r--r--Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml32
-rw-r--r--Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.yaml50
-rw-r--r--Documentation/devicetree/bindings/net/can/bosch,c_can.yaml10
-rw-r--r--Documentation/devicetree/bindings/net/can/microchip,mcp2510.yaml18
-rw-r--r--Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml18
-rw-r--r--Documentation/devicetree/bindings/net/nxp,s32-dwmac.yaml105
-rw-r--r--Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/qcom,ipa.yaml2
-rw-r--r--Documentation/devicetree/bindings/net/snps,dwmac.yaml1
-rw-r--r--Documentation/devicetree/bindings/net/stm32-dwmac.yaml94
-rw-r--r--Documentation/devicetree/bindings/net/ti,davinci-mdio.yaml10
-rw-r--r--Documentation/devicetree/bindings/net/ti,dp83822.yaml27
-rw-r--r--Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml20
-rw-r--r--Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml38
-rw-r--r--Documentation/devicetree/bindings/net/wireless/marvell,sd8787.yaml19
-rw-r--r--Documentation/devicetree/bindings/nvmem/renesas,rcar-efuse.yaml (renamed from Documentation/devicetree/bindings/fuse/renesas,rcar-efuse.yaml)35
-rw-r--r--Documentation/devicetree/bindings/nvmem/renesas,rcar-otp.yaml (renamed from Documentation/devicetree/bindings/fuse/renesas,rcar-otp.yaml)17
-rw-r--r--Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt52
-rw-r--r--Documentation/devicetree/bindings/nvmem/sprd,sc2731-efuse.yaml68
-rw-r--r--Documentation/devicetree/bindings/nvmem/sprd,ums312-efuse.yaml61
-rw-r--r--Documentation/devicetree/bindings/nvmem/sprd-efuse.txt39
-rw-r--r--Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt40
-rw-r--r--Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.yaml54
-rw-r--r--Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml39
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml2
-rw-r--r--Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml1
-rw-r--r--Documentation/devicetree/bindings/power/mediatek,power-controller.yaml4
-rw-r--r--Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml27
-rw-r--r--Documentation/devicetree/bindings/riscv/extensions.yaml28
-rw-r--r--Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml4
-rw-r--r--Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml63
-rw-r--r--Documentation/devicetree/bindings/rtc/microchip,mpfs-rtc.yaml (renamed from Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml)10
-rw-r--r--Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml84
-rw-r--r--Documentation/devicetree/bindings/serial/rs485.yaml19
-rw-r--r--Documentation/devicetree/bindings/serial/samsung_uart.yaml14
-rw-r--r--Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml13
-rw-r--r--Documentation/devicetree/bindings/serial/sprd-uart.yaml1
-rw-r--r--Documentation/devicetree/bindings/soc/fsl/fsl,qman-portal.yaml2
-rw-r--r--Documentation/devicetree/bindings/sound/realtek,rt5645.yaml2
-rw-r--r--Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml1
-rw-r--r--Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml6
-rw-r--r--Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml1
-rw-r--r--Documentation/devicetree/bindings/usb/cypress,cypd4226.yaml5
-rw-r--r--Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml6
-rw-r--r--Documentation/devicetree/bindings/usb/generic-ehci.yaml1
-rw-r--r--Documentation/devicetree/bindings/usb/generic-ohci.yaml1
-rw-r--r--Documentation/devicetree/bindings/usb/genesys,gl850g.yaml9
-rw-r--r--Documentation/devicetree/bindings/usb/maxim,max33359.yaml1
-rw-r--r--Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml7
-rw-r--r--Documentation/devicetree/bindings/usb/qcom,dwc3.yaml2
-rw-r--r--Documentation/devicetree/bindings/usb/renesas,usbhs.yaml4
-rw-r--r--Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml6
-rw-r--r--Documentation/devicetree/bindings/usb/ti,tusb1046.yaml49
-rw-r--r--Documentation/devicetree/bindings/usb/ti,tusb73x0-pci.yaml55
-rw-r--r--Documentation/devicetree/bindings/vendor-prefixes.yaml4
-rw-r--r--Documentation/devicetree/bindings/watchdog/airoha,en7581-wdt.yaml47
-rw-r--r--Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.yaml14
-rw-r--r--Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml2
-rw-r--r--Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml3
-rw-r--r--Documentation/driver-api/auxiliary_bus.rst1
-rw-r--r--Documentation/iio/ad7380.rst16
-rw-r--r--Documentation/iio/ad7606.rst144
-rw-r--r--Documentation/iio/ad7625.rst91
-rw-r--r--Documentation/iio/bno055.rst2
-rw-r--r--Documentation/iio/index.rst2
-rw-r--r--Documentation/kbuild/kbuild.rst8
-rw-r--r--Documentation/kbuild/kconfig-language.rst4
-rw-r--r--Documentation/kbuild/llvm.rst3
-rw-r--r--Documentation/kbuild/makefiles.rst14
-rw-r--r--Documentation/kbuild/modules.rst29
-rw-r--r--Documentation/mm/process_addrs.rst850
-rw-r--r--Documentation/netlink/genetlink-c.yaml3
-rw-r--r--Documentation/netlink/genetlink-legacy.yaml3
-rw-r--r--Documentation/netlink/netlink-raw.yaml2
-rw-r--r--Documentation/netlink/specs/ethtool.yaml434
-rw-r--r--Documentation/netlink/specs/mptcp_pm.yaml60
-rw-r--r--Documentation/netlink/specs/rt_link.yaml96
-rw-r--r--Documentation/netlink/specs/rt_route.yaml7
-rw-r--r--Documentation/netlink/specs/rt_rule.yaml12
-rw-r--r--Documentation/networking/bareudp.rst11
-rw-r--r--Documentation/networking/bonding.rst8
-rw-r--r--Documentation/networking/device_drivers/ethernet/intel/i40e.rst12
-rw-r--r--Documentation/networking/ethtool-netlink.rst82
-rw-r--r--Documentation/networking/ieee802154.rst16
-rw-r--r--Documentation/networking/index.rst1
-rw-r--r--Documentation/networking/ip-sysctl.rst20
-rw-r--r--Documentation/networking/multi-pf-netdev.rst4
-rw-r--r--Documentation/networking/napi.rst4
-rw-r--r--Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst1
-rw-r--r--Documentation/networking/netdevices.rst10
-rw-r--r--Documentation/networking/netlink_spec/readme.txt2
-rw-r--r--Documentation/networking/netmem.rst79
-rw-r--r--Documentation/networking/timestamping.rst38
-rw-r--r--Documentation/networking/tls.rst36
-rw-r--r--Documentation/power/runtime_pm.rst4
-rw-r--r--Documentation/sound/hd-audio/notes.rst2
-rw-r--r--Documentation/sound/soc/dapm.rst3
-rw-r--r--Documentation/trace/ftrace.rst4
-rw-r--r--Documentation/translations/it_IT/core-api/symbol-namespaces.rst8
-rw-r--r--Documentation/translations/zh_CN/core-api/symbol-namespaces.rst8
-rw-r--r--Documentation/userspace-api/netlink/c-code-gen.rst4
-rw-r--r--Documentation/userspace-api/netlink/intro-specs.rst8
-rw-r--r--Documentation/watchdog/watchdog-parameters.rst10
-rw-r--r--MAINTAINERS201
-rw-r--r--Makefile231
-rw-r--r--arch/Kconfig39
-rw-r--r--arch/alpha/include/uapi/asm/socket.h2
-rw-r--r--arch/alpha/kernel/pci-sysfs.c6
-rw-r--r--arch/arc/Kconfig5
-rw-r--r--arch/arc/Makefile2
-rw-r--r--arch/arc/boot/dts/axc001.dtsi2
-rw-r--r--arch/arc/boot/dts/axc003.dtsi2
-rw-r--r--arch/arc/boot/dts/axc003_idu.dtsi2
-rw-r--r--arch/arc/boot/dts/axs10x_mb.dtsi12
-rw-r--r--arch/arc/boot/dts/hsdk.dts2
-rw-r--r--arch/arc/include/asm/arcregs.h2
-rw-r--r--arch/arc/include/asm/cachetype.h8
-rw-r--r--arch/arc/include/asm/cmpxchg.h2
-rw-r--r--arch/arc/include/asm/mmu-arcv2.h2
-rw-r--r--arch/arc/net/bpf_jit_arcv2.c2
-rw-r--r--arch/arm/Makefile4
-rw-r--r--arch/arm/common/locomo.c2
-rw-r--r--arch/arm/common/sa1111.c2
-rw-r--r--arch/arm/common/scoop.c2
-rw-r--r--arch/arm/kernel/entry-armv.S8
-rw-r--r--arch/arm/mach-imx/Kconfig1
-rw-r--r--arch/arm/mach-imx/mmdc.c2
-rw-r--r--arch/arm/mach-omap1/omap-dma.c2
-rw-r--r--arch/arm/mach-pxa/sharpsl_pm.c2
-rw-r--r--arch/arm/mach-sa1100/jornada720_ssp.c2
-rw-r--r--arch/arm/mach-sa1100/neponset.c2
-rw-r--r--arch/arm/mm/ioremap.c35
-rw-r--r--arch/arm/vfp/vfpmodule.c74
-rw-r--r--arch/arm64/Kconfig12
-rw-r--r--arch/arm64/Makefile2
-rw-r--r--arch/arm64/boot/dts/arm/fvp-base-revc.dts2
-rw-r--r--arch/arm64/boot/dts/broadcom/bcm2712.dtsi8
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi14
-rw-r--r--arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi4
-rw-r--r--arch/arm64/crypto/aes-ce-ccm-glue.c2
-rw-r--r--arch/arm64/crypto/aes-glue.c2
-rw-r--r--arch/arm64/include/asm/cpucaps.h2
-rw-r--r--arch/arm64/include/asm/cpufeature.h3
-rw-r--r--arch/arm64/include/asm/el2_setup.h4
-rw-r--r--arch/arm64/include/asm/mman.h3
-rw-r--r--arch/arm64/kernel/hyp-stub.S4
-rw-r--r--arch/arm64/kernel/patching.c25
-rw-r--r--arch/arm64/kernel/ptrace.c36
-rw-r--r--arch/arm64/kernel/signal.c83
-rw-r--r--arch/arm64/kernel/stacktrace.c32
-rw-r--r--arch/arm64/kvm/at.c11
-rw-r--r--arch/arm64/kvm/hyp/nvhe/pkvm.c4
-rw-r--r--arch/arm64/kvm/nested.c2
-rw-r--r--arch/arm64/kvm/pmu-emul.c62
-rw-r--r--arch/arm64/kvm/sys_regs.c3
-rw-r--r--arch/arm64/kvm/vgic/vgic-debug.c5
-rw-r--r--arch/arm64/kvm/vgic/vgic-init.c2
-rw-r--r--arch/arm64/kvm/vgic/vgic-its.c89
-rw-r--r--arch/arm64/kvm/vgic/vgic-mmio-v2.c12
-rw-r--r--arch/arm64/kvm/vgic/vgic-mmio-v3.c13
-rw-r--r--arch/arm64/kvm/vgic/vgic-mmio.c38
-rw-r--r--arch/arm64/kvm/vgic/vgic-v2.c2
-rw-r--r--arch/arm64/kvm/vgic/vgic-v3.c2
-rw-r--r--arch/arm64/kvm/vgic/vgic-v4.c4
-rw-r--r--arch/arm64/kvm/vgic/vgic.c43
-rw-r--r--arch/arm64/kvm/vgic/vgic.h27
-rw-r--r--arch/arm64/mm/context.c4
-rw-r--r--arch/arm64/mm/copypage.c8
-rw-r--r--arch/arm64/mm/init.c17
-rw-r--r--arch/hexagon/Makefile6
-rw-r--r--arch/loongarch/include/asm/hugetlb.h10
-rw-r--r--arch/loongarch/include/asm/inst.h12
-rw-r--r--arch/loongarch/kernel/efi.c2
-rw-r--r--arch/loongarch/kernel/inst.c2
-rw-r--r--arch/loongarch/kernel/smp.c2
-rw-r--r--arch/loongarch/kvm/exit.c31
-rw-r--r--arch/loongarch/kvm/intc/ipi.c6
-rw-r--r--arch/loongarch/kvm/vcpu.c4
-rw-r--r--arch/loongarch/net/bpf_jit.c6
-rw-r--r--arch/m68k/configs/multi_defconfig1
-rw-r--r--arch/m68k/configs/mvme147_defconfig1
-rw-r--r--arch/m68k/configs/mvme16x_defconfig1
-rw-r--r--arch/m68k/include/asm/mvme147hw.h19
-rw-r--r--arch/m68k/include/asm/mvme16xhw.h18
-rw-r--r--arch/m68k/mvme147/config.c55
-rw-r--r--arch/m68k/mvme16x/Makefile2
-rw-r--r--arch/m68k/mvme16x/config.c57
-rw-r--r--arch/m68k/mvme16x/rtc.c165
-rw-r--r--arch/mips/boot/dts/loongson/ls7a-pch.dtsi73
-rw-r--r--arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi270
-rw-r--r--arch/mips/boot/dts/mobileye/eyeq5.dtsi30
-rw-r--r--arch/mips/boot/dts/mobileye/eyeq6h-fixed-clocks.dtsi52
-rw-r--r--arch/mips/boot/dts/mobileye/eyeq6h.dtsi73
-rw-r--r--arch/mips/boot/dts/realtek/rtl930x.dtsi13
-rw-r--r--arch/mips/include/uapi/asm/socket.h2
-rw-r--r--arch/mips/kernel/head.S1
-rw-r--r--arch/mips/kernel/vmlinux.lds.S1
-rw-r--r--arch/mips/pci/pci-xtalk-bridge.c2
-rw-r--r--arch/nios2/kernel/cpuinfo.c10
-rw-r--r--arch/openrisc/kernel/entry.S2
-rw-r--r--arch/openrisc/kernel/head.S32
-rw-r--r--arch/openrisc/kernel/vmlinux.lds.S3
-rw-r--r--arch/parisc/include/uapi/asm/socket.h2
-rw-r--r--arch/powerpc/Makefile6
-rw-r--r--arch/powerpc/configs/pmac32_defconfig1
-rw-r--r--arch/powerpc/configs/ppc6xx_defconfig1
-rw-r--r--arch/powerpc/crypto/vmx.c2
-rw-r--r--arch/powerpc/kernel/prom_init.c29
-rw-r--r--arch/powerpc/platforms/book3s/vas-api.c36
-rw-r--r--arch/powerpc/platforms/pseries/svm.c1
-rw-r--r--arch/riscv/Kconfig1
-rw-r--r--arch/riscv/Makefile2
-rw-r--r--arch/riscv/include/asm/csr.h1
-rw-r--r--arch/riscv/include/asm/hwcap.h2
-rw-r--r--arch/riscv/include/asm/kfence.h4
-rw-r--r--arch/riscv/include/asm/pgtable.h13
-rw-r--r--arch/riscv/include/uapi/asm/kvm.h2
-rw-r--r--arch/riscv/kernel/cpufeature.c12
-rw-r--r--arch/riscv/kernel/jump_label.c12
-rw-r--r--arch/riscv/kernel/setup.c2
-rw-r--r--arch/riscv/kvm/aia.c2
-rw-r--r--arch/riscv/kvm/vcpu.c4
-rw-r--r--arch/riscv/kvm/vcpu_onereg.c15
-rw-r--r--arch/riscv/mm/init.c7
-rw-r--r--arch/s390/Kconfig2
-rw-r--r--arch/s390/boot/startup.c2
-rw-r--r--arch/s390/boot/vmem.c6
-rw-r--r--arch/s390/crypto/aes_s390.c2
-rw-r--r--arch/s390/include/asm/debug.h8
-rw-r--r--arch/s390/include/asm/gmap.h4
-rw-r--r--arch/s390/include/asm/hugetlb.h4
-rw-r--r--arch/s390/include/asm/kvm_host.h15
-rw-r--r--arch/s390/include/asm/pgtable.h117
-rw-r--r--arch/s390/include/asm/preempt.h22
-rw-r--r--arch/s390/include/asm/spinlock.h7
-rw-r--r--arch/s390/include/asm/thread_info.h21
-rw-r--r--arch/s390/include/asm/tlbflush.h5
-rw-r--r--arch/s390/kernel/debug.c83
-rw-r--r--arch/s390/kernel/entry.S4
-rw-r--r--arch/s390/kernel/ipl.c2
-rw-r--r--arch/s390/kernel/kprobes.c6
-rw-r--r--arch/s390/kernel/perf_cpum_sf.c38
-rw-r--r--arch/s390/kernel/stacktrace.c2
-rw-r--r--arch/s390/kvm/gaccess.c16
-rw-r--r--arch/s390/kvm/interrupt.c25
-rw-r--r--arch/s390/kvm/kvm-s390.c4
-rw-r--r--arch/s390/kvm/pci.c5
-rw-r--r--arch/s390/lib/spinlock.c34
-rw-r--r--arch/s390/mm/fault.c3
-rw-r--r--arch/s390/mm/gmap.c12
-rw-r--r--arch/s390/mm/hugetlbpage.c31
-rw-r--r--arch/s390/pci/pci.c55
-rw-r--r--arch/s390/pci/pci_event.c10
-rw-r--r--arch/sh/drivers/push-switch.c2
-rw-r--r--arch/sh/kernel/cpu/proc.c2
-rw-r--r--arch/sparc/Makefile4
-rw-r--r--arch/sparc/include/asm/hvtramp.h2
-rw-r--r--arch/sparc/include/asm/parport_64.h2
-rw-r--r--arch/sparc/include/uapi/asm/socket.h2
-rw-r--r--arch/sparc/kernel/chmc.c2
-rw-r--r--arch/sparc/kernel/smp_64.c4
-rw-r--r--arch/sparc/kernel/time_32.c1
-rw-r--r--arch/sparc/kernel/time_64.c1
-rw-r--r--arch/sparc/kernel/vmlinux.lds.S5
-rw-r--r--arch/sparc/vdso/Makefile2
-rw-r--r--arch/sparc/vdso/vclock_gettime.c28
-rw-r--r--arch/um/Kconfig24
-rw-r--r--arch/um/Makefile7
-rw-r--r--arch/um/Makefile-skas14
-rw-r--r--arch/um/configs/i386_defconfig1
-rw-r--r--arch/um/drivers/chan_user.c2
-rw-r--r--arch/um/drivers/hostaudio_kern.c2
-rw-r--r--arch/um/drivers/net_kern.c2
-rw-r--r--arch/um/drivers/rtc_kern.c2
-rw-r--r--arch/um/drivers/ubd_kern.c5
-rw-r--r--arch/um/drivers/vector_kern.c3
-rw-r--r--arch/um/drivers/vhost_user.h4
-rw-r--r--arch/um/drivers/virtio_uml.c53
-rw-r--r--arch/um/include/asm/Kbuild1
-rw-r--r--arch/um/include/asm/current.h23
-rw-r--r--arch/um/include/asm/page.h34
-rw-r--r--arch/um/include/asm/pgalloc.h11
-rw-r--r--arch/um/include/asm/pgtable-2level.h2
-rw-r--r--arch/um/include/asm/pgtable-4level.h (renamed from arch/um/include/asm/pgtable-3level.h)59
-rw-r--r--arch/um/include/asm/pgtable.h83
-rw-r--r--arch/um/include/asm/processor-generic.h7
-rw-r--r--arch/um/include/asm/thread_info.h18
-rw-r--r--arch/um/include/asm/tlbflush.h4
-rw-r--r--arch/um/include/shared/as-layout.h10
-rw-r--r--arch/um/include/shared/common-offsets.h15
-rw-r--r--arch/um/include/shared/kern_util.h1
-rw-r--r--arch/um/include/shared/mem_user.h5
-rw-r--r--arch/um/include/shared/os.h15
-rw-r--r--arch/um/include/shared/registers.h6
-rw-r--r--arch/um/include/shared/skas/stub-data.h12
-rw-r--r--arch/um/include/shared/timetravel.h5
-rw-r--r--arch/um/include/shared/user.h2
-rw-r--r--arch/um/kernel/dtb.c1
-rw-r--r--arch/um/kernel/dyn.lds.S5
-rw-r--r--arch/um/kernel/initrd.c1
-rw-r--r--arch/um/kernel/irq.c112
-rw-r--r--arch/um/kernel/mem.c20
-rw-r--r--arch/um/kernel/physmem.c39
-rw-r--r--arch/um/kernel/process.c24
-rw-r--r--arch/um/kernel/skas/.gitignore2
-rw-r--r--arch/um/kernel/skas/Makefile38
-rw-r--r--arch/um/kernel/skas/mmu.c28
-rw-r--r--arch/um/kernel/skas/process.c4
-rw-r--r--arch/um/kernel/skas/stub.c10
-rw-r--r--arch/um/kernel/skas/stub_exe.c95
-rw-r--r--arch/um/kernel/skas/stub_exe_embed.S11
-rw-r--r--arch/um/kernel/sysrq.c8
-rw-r--r--arch/um/kernel/time.c20
-rw-r--r--arch/um/kernel/tlb.c74
-rw-r--r--arch/um/kernel/trap.c16
-rw-r--r--arch/um/kernel/um_arch.c75
-rw-r--r--arch/um/kernel/uml.lds.S2
-rw-r--r--arch/um/os-Linux/Makefile2
-rw-r--r--arch/um/os-Linux/file.c6
-rw-r--r--arch/um/os-Linux/main.c23
-rw-r--r--arch/um/os-Linux/mem.c14
-rw-r--r--arch/um/os-Linux/process.c88
-rw-r--r--arch/um/os-Linux/registers.c11
-rw-r--r--arch/um/os-Linux/sigio.c1
-rw-r--r--arch/um/os-Linux/signal.c55
-rw-r--r--arch/um/os-Linux/skas/mem.c21
-rw-r--r--arch/um/os-Linux/skas/process.c231
-rw-r--r--arch/um/os-Linux/umid.c2
-rw-r--r--arch/um/os-Linux/util.c4
-rw-r--r--arch/x86/Kconfig2
-rw-r--r--arch/x86/events/intel/core.c13
-rw-r--r--arch/x86/events/intel/ds.c3
-rw-r--r--arch/x86/events/intel/uncore.c1
-rw-r--r--arch/x86/include/asm/cpufeatures.h1
-rw-r--r--arch/x86/include/asm/pgtable_types.h8
-rw-r--r--arch/x86/include/asm/processor.h2
-rw-r--r--arch/x86/include/asm/static_call.h15
-rw-r--r--arch/x86/include/asm/sync_core.h6
-rw-r--r--arch/x86/include/asm/tlb.h4
-rw-r--r--arch/x86/include/asm/xen/hypercall.h36
-rw-r--r--arch/x86/kernel/callthunks.c5
-rw-r--r--arch/x86/kernel/cet.c30
-rw-r--r--arch/x86/kernel/cpu/amd.c3
-rw-r--r--arch/x86/kernel/cpu/cacheinfo.c43
-rw-r--r--arch/x86/kernel/cpu/common.c40
-rw-r--r--arch/x86/kernel/cpu/intel.c4
-rw-r--r--arch/x86/kernel/cpu/microcode/amd.c25
-rw-r--r--arch/x86/kernel/cpu/mshyperv.c58
-rw-r--r--arch/x86/kernel/cpu/topology.c6
-rw-r--r--arch/x86/kernel/fpu/signal.c20
-rw-r--r--arch/x86/kernel/fpu/xstate.h27
-rw-r--r--arch/x86/kernel/relocate_kernel_64.S8
-rw-r--r--arch/x86/kernel/static_call.c9
-rw-r--r--arch/x86/kernel/vmlinux.lds.S8
-rw-r--r--arch/x86/kvm/cpuid.c31
-rw-r--r--arch/x86/kvm/cpuid.h1
-rw-r--r--arch/x86/kvm/mmu/mmu.c12
-rw-r--r--arch/x86/kvm/mmu/spte.h17
-rw-r--r--arch/x86/kvm/mmu/tdp_mmu.c5
-rw-r--r--arch/x86/kvm/svm/avic.c6
-rw-r--r--arch/x86/kvm/svm/svm.c9
-rw-r--r--arch/x86/kvm/vmx/posted_intr.h2
-rw-r--r--arch/x86/kvm/x86.c11
-rw-r--r--arch/x86/mm/ident_map.c6
-rw-r--r--arch/x86/mm/pat/set_memory.c4
-rw-r--r--arch/x86/mm/pti.c2
-rw-r--r--arch/x86/mm/tlb.c3
-rw-r--r--arch/x86/um/Kconfig12
-rw-r--r--arch/x86/um/Makefile2
-rw-r--r--arch/x86/um/asm/elf.h2
-rw-r--r--arch/x86/um/asm/ptrace.h10
-rw-r--r--arch/x86/um/os-Linux/Makefile2
-rw-r--r--arch/x86/um/os-Linux/registers.c145
-rw-r--r--arch/x86/um/os-Linux/task_size.c151
-rw-r--r--arch/x86/um/ptrace.c267
-rw-r--r--arch/x86/um/ptrace_32.c84
-rw-r--r--arch/x86/um/ptrace_64.c43
-rw-r--r--arch/x86/um/shared/sysdep/ptrace.h8
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_32.h4
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_64.h4
-rw-r--r--arch/x86/um/shared/sysdep/ptrace_user.h6
-rw-r--r--arch/x86/um/shared/sysdep/stub_32.h18
-rw-r--r--arch/x86/um/shared/sysdep/stub_64.h27
-rw-r--r--arch/x86/um/signal.c336
-rw-r--r--arch/x86/um/user-offsets.c8
-rw-r--r--arch/x86/um/vdso/Makefile5
-rw-r--r--arch/x86/um/vdso/checkundef.sh11
-rw-r--r--arch/x86/xen/enlighten.c65
-rw-r--r--arch/x86/xen/enlighten_hvm.c13
-rw-r--r--arch/x86/xen/enlighten_pv.c4
-rw-r--r--arch/x86/xen/enlighten_pvh.c7
-rw-r--r--arch/x86/xen/xen-asm.S50
-rw-r--r--arch/x86/xen/xen-head.S107
-rw-r--r--arch/x86/xen/xen-ops.h9
-rw-r--r--block/bdev.c3
-rw-r--r--block/bfq-cgroup.c1
-rw-r--r--block/bfq-iosched.c43
-rw-r--r--block/bio.c2
-rw-r--r--block/blk-cgroup.c6
-rw-r--r--block/blk-iocost.c9
-rw-r--r--block/blk-map.c2
-rw-r--r--block/blk-merge.c35
-rw-r--r--block/blk-mq.c143
-rw-r--r--block/blk-settings.c141
-rw-r--r--block/blk-sysfs.c8
-rw-r--r--block/blk-zoned.c522
-rw-r--r--block/fops.c5
-rw-r--r--block/genhd.c9
-rw-r--r--block/mq-deadline.c18
-rw-r--r--crypto/adiantum.c2
-rw-r--r--crypto/ansi_cprng.c2
-rw-r--r--crypto/ccm.c2
-rw-r--r--crypto/cipher.c6
-rw-r--r--crypto/cmac.c2
-rw-r--r--crypto/ctr.c2
-rw-r--r--crypto/drbg.c2
-rw-r--r--crypto/ecb.c2
-rw-r--r--crypto/essiv.c2
-rw-r--r--crypto/hctr2.c2
-rw-r--r--crypto/keywrap.c2
-rw-r--r--crypto/pcbc.c2
-rw-r--r--crypto/rsassa-pkcs1.c45
-rw-r--r--crypto/skcipher.c2
-rw-r--r--crypto/testmgr.c2
-rw-r--r--crypto/vmac.c2
-rw-r--r--crypto/xcbc.c2
-rw-r--r--crypto/xctr.c2
-rw-r--r--crypto/xts.c2
-rw-r--r--drivers/accel/habanalabs/common/memory.c2
-rw-r--r--drivers/accel/ivpu/ivpu_gem.c2
-rw-r--r--drivers/accel/ivpu/ivpu_mmu_context.c10
-rw-r--r--drivers/accel/ivpu/ivpu_pm.c2
-rw-r--r--drivers/accel/qaic/qaic_drv.c2
-rw-r--r--drivers/accessibility/speakup/Makefile4
-rw-r--r--drivers/acpi/Kconfig4
-rw-r--r--drivers/acpi/acpica/evxfregn.c2
-rw-r--r--drivers/acpi/apei/einj-cxl.c8
-rw-r--r--drivers/acpi/apei/ghes.c6
-rw-r--r--drivers/acpi/arm64/iort.c2
-rw-r--r--drivers/acpi/nfit/core.c7
-rw-r--r--drivers/acpi/numa/hmat.c2
-rw-r--r--drivers/acpi/resource.c6
-rw-r--r--drivers/acpi/thermal.c2
-rw-r--r--drivers/acpi/thermal_lib.c8
-rw-r--r--drivers/amba/bus.c6
-rw-r--r--drivers/android/binder.c64
-rw-r--r--drivers/ata/sata_highbank.c1
-rw-r--r--drivers/atm/fore200e.c2
-rw-r--r--drivers/auxdisplay/Kconfig2
-rw-r--r--drivers/auxdisplay/cfag12864bfb.c2
-rw-r--r--drivers/auxdisplay/hd44780.c2
-rw-r--r--drivers/auxdisplay/ht16k33.c2
-rw-r--r--drivers/auxdisplay/img-ascii-lcd.c4
-rw-r--r--drivers/auxdisplay/line-display.c4
-rw-r--r--drivers/auxdisplay/max6959.c2
-rw-r--r--drivers/auxdisplay/seg-led-gpio.c4
-rw-r--r--drivers/base/arch_numa.c4
-rw-r--r--drivers/base/auxiliary.c31
-rw-r--r--drivers/base/cacheinfo.c29
-rw-r--r--drivers/base/class.c4
-rw-r--r--drivers/base/core.c63
-rw-r--r--drivers/base/firmware_loader/builtin/main.c2
-rw-r--r--drivers/base/firmware_loader/fallback_table.c6
-rw-r--r--drivers/base/firmware_loader/main.c7
-rw-r--r--drivers/base/firmware_loader/sysfs.h2
-rw-r--r--drivers/base/node.c12
-rw-r--r--drivers/base/power/sysfs.c17
-rw-r--r--drivers/base/regmap/regmap.c16
-rw-r--r--drivers/base/topology.c40
-rw-r--r--drivers/base/trace.h6
-rw-r--r--drivers/bcma/host_soc.c2
-rw-r--r--drivers/block/brd.c4
-rw-r--r--drivers/block/loop.c30
-rw-r--r--drivers/block/rnull.rs1
-rw-r--r--drivers/block/swim.c2
-rw-r--r--drivers/block/ublk_drv.c28
-rw-r--r--drivers/block/virtio_blk.c7
-rw-r--r--drivers/block/zram/zram_drv.c15
-rw-r--r--drivers/bluetooth/btmtk.c27
-rw-r--r--drivers/bluetooth/btnxpuart.c1
-rw-r--r--drivers/bluetooth/btqcomsmd.c2
-rw-r--r--drivers/bluetooth/hci_bcm.c2
-rw-r--r--drivers/bluetooth/hci_intel.c2
-rw-r--r--drivers/bus/mhi/host/boot.c4
-rw-r--r--drivers/bus/mhi/host/internal.h2
-rw-r--r--drivers/bus/mhi/host/pci_generic.c6
-rw-r--r--drivers/bus/mhi/host/trace.h25
-rw-r--r--drivers/cdrom/cdrom.c2
-rw-r--r--drivers/cdrom/gdrom.c2
-rw-r--r--drivers/cdx/Makefile2
-rw-r--r--drivers/cdx/cdx.c10
-rw-r--r--drivers/cdx/cdx_msi.c2
-rw-r--r--drivers/cdx/controller/cdx_controller.c4
-rw-r--r--drivers/char/ipmi/bt-bmc.c2
-rw-r--r--drivers/char/ipmi/ipmi_powernv.c2
-rw-r--r--drivers/char/ipmi/ipmi_si_platform.c2
-rw-r--r--drivers/char/ipmi/ipmi_ssif.c2
-rw-r--r--drivers/char/ipmi/kcs_bmc_aspeed.c2
-rw-r--r--drivers/char/ipmi/kcs_bmc_npcm7xx.c2
-rw-r--r--drivers/char/powernv-op-panel.c2
-rw-r--r--drivers/char/sonypi.c2
-rw-r--r--drivers/char/tpm/tpm_ftpm_tee.c2
-rw-r--r--drivers/char/tpm/tpm_tis.c2
-rw-r--r--drivers/char/tpm/tpm_tis_synquacer.c2
-rw-r--r--drivers/char/xilinx_hwicap/xilinx_hwicap.c2
-rw-r--r--drivers/char/xillybus/xillybus_of.c2
-rw-r--r--drivers/clk/clk-en7523.c9
-rw-r--r--drivers/clk/clk.c2
-rw-r--r--drivers/clk/imx/clk-imx8mp-audiomix.c3
-rw-r--r--drivers/clk/meson/Kconfig2
-rw-r--r--drivers/clk/meson/a1-peripherals.c2
-rw-r--r--drivers/clk/meson/a1-pll.c2
-rw-r--r--drivers/clk/meson/axg-aoclk.c2
-rw-r--r--drivers/clk/meson/axg-audio.c111
-rw-r--r--drivers/clk/meson/axg.c2
-rw-r--r--drivers/clk/meson/c3-peripherals.c2
-rw-r--r--drivers/clk/meson/c3-pll.c2
-rw-r--r--drivers/clk/meson/clk-cpu-dyndiv.c4
-rw-r--r--drivers/clk/meson/clk-dualdiv.c6
-rw-r--r--drivers/clk/meson/clk-mpll.c6
-rw-r--r--drivers/clk/meson/clk-phase.c8
-rw-r--r--drivers/clk/meson/clk-pll.c8
-rw-r--r--drivers/clk/meson/clk-regmap.c14
-rw-r--r--drivers/clk/meson/g12a-aoclk.c2
-rw-r--r--drivers/clk/meson/g12a.c2
-rw-r--r--drivers/clk/meson/gxbb-aoclk.c2
-rw-r--r--drivers/clk/meson/gxbb.c2
-rw-r--r--drivers/clk/meson/meson-aoclk.c4
-rw-r--r--drivers/clk/meson/meson-clkc-utils.c4
-rw-r--r--drivers/clk/meson/meson-eeclk.c4
-rw-r--r--drivers/clk/meson/s4-peripherals.c2
-rw-r--r--drivers/clk/meson/s4-pll.c2
-rw-r--r--drivers/clk/meson/sclk-div.c4
-rw-r--r--drivers/clk/meson/vclk.c6
-rw-r--r--drivers/clk/meson/vid-pll-div.c4
-rw-r--r--drivers/clk/microchip/clk-mpfs.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun20i-d1.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun4i-a10.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a100.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-a64.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-h6.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun50i-h616.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun6i-a31.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun6i-rtc.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-a23.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-a33.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-a83t.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-de2.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-h3.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-r.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-r40.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun8i-v3s.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-sun9i-a80.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_common.c8
-rw-r--r--drivers/clk/sunxi-ng/ccu_div.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_frac.c12
-rw-r--r--drivers/clk/sunxi-ng/ccu_gate.c8
-rw-r--r--drivers/clk/sunxi-ng/ccu_mp.c4
-rw-r--r--drivers/clk/sunxi-ng/ccu_mult.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_mux.c12
-rw-r--r--drivers/clk/sunxi-ng/ccu_nk.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_nkm.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_nkmp.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_nm.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_phase.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_reset.c2
-rw-r--r--drivers/clk/sunxi-ng/ccu_sdm.c12
-rw-r--r--drivers/clk/thead/clk-th1520-ap.c13
-rw-r--r--drivers/clocksource/hyperv_timer.c14
-rw-r--r--drivers/clocksource/timer-sun5i.c2
-rw-r--r--drivers/clocksource/timer-tegra186.c2
-rw-r--r--drivers/clocksource/timer-ti-dm.c2
-rw-r--r--drivers/comedi/comedi_fops.c12
-rw-r--r--drivers/counter/104-quad-8.c2
-rw-r--r--drivers/counter/counter-chrdev.c2
-rw-r--r--drivers/counter/counter-core.c14
-rw-r--r--drivers/counter/ftm-quaddec.c3
-rw-r--r--drivers/counter/i8254.c4
-rw-r--r--drivers/counter/intel-qep.c12
-rw-r--r--drivers/counter/interrupt-cnt.c2
-rw-r--r--drivers/counter/microchip-tcb-capture.c2
-rw-r--r--drivers/counter/rz-mtu3-cnt.c2
-rw-r--r--drivers/counter/stm32-lptimer-cnt.c2
-rw-r--r--drivers/counter/stm32-timer-cnt.c19
-rw-r--r--drivers/counter/ti-ecap-capture.c11
-rw-r--r--drivers/counter/ti-eqep.c4
-rw-r--r--drivers/cpufreq/amd-pstate.c50
-rw-r--r--drivers/cpuidle/cpuidle-kirkwood.c2
-rw-r--r--drivers/crypto/geode-aes.c2
-rw-r--r--drivers/crypto/hisilicon/debugfs.c4
-rw-r--r--drivers/crypto/inside-secure/safexcel.c2
-rw-r--r--drivers/crypto/intel/iaa/Makefile2
-rw-r--r--drivers/crypto/intel/iaa/iaa_crypto_main.c2
-rw-r--r--drivers/crypto/intel/qat/qat_420xx/adf_drv.c2
-rw-r--r--drivers/crypto/intel/qat/qat_4xxx/adf_drv.c2
-rw-r--r--drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c2
-rw-r--r--drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c2
-rw-r--r--drivers/crypto/intel/qat/qat_c62x/adf_drv.c2
-rw-r--r--drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c2
-rw-r--r--drivers/crypto/intel/qat/qat_common/Makefile2
-rw-r--r--drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c2
-rw-r--r--drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c2
-rw-r--r--drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c2
-rw-r--r--drivers/crypto/marvell/octeontx2/cn10k_cpt.c14
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c20
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptlf.c20
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c2
-rw-r--r--drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c2
-rw-r--r--drivers/cxl/acpi.c4
-rw-r--r--drivers/cxl/core/cdat.c6
-rw-r--r--drivers/cxl/core/hdm.c12
-rw-r--r--drivers/cxl/core/mbox.c22
-rw-r--r--drivers/cxl/core/memdev.c20
-rw-r--r--drivers/cxl/core/pci.c18
-rw-r--r--drivers/cxl/core/pmem.c14
-rw-r--r--drivers/cxl/core/pmu.c2
-rw-r--r--drivers/cxl/core/port.c72
-rw-r--r--drivers/cxl/core/region.c39
-rw-r--r--drivers/cxl/core/regs.c22
-rw-r--r--drivers/cxl/core/suspend.c4
-rw-r--r--drivers/cxl/mem.c2
-rw-r--r--drivers/cxl/pci.c8
-rw-r--r--drivers/cxl/pmem.c2
-rw-r--r--drivers/cxl/port.c4
-rw-r--r--drivers/dax/cxl.c2
-rw-r--r--drivers/devfreq/event/exynos-nocp.c2
-rw-r--r--drivers/devfreq/event/exynos-ppmu.c2
-rw-r--r--drivers/devfreq/mtk-cci-devfreq.c2
-rw-r--r--drivers/devfreq/rk3399_dmc.c2
-rw-r--r--drivers/devfreq/sun8i-a33-mbus.c2
-rw-r--r--drivers/dma-buf/dma-buf.c44
-rw-r--r--drivers/dma-buf/dma-fence-array.c28
-rw-r--r--drivers/dma-buf/dma-fence-unwrap.c126
-rw-r--r--drivers/dma-buf/udmabuf.c43
-rw-r--r--drivers/dma/amd/qdma/qdma.c28
-rw-r--r--drivers/dma/apple-admac.c7
-rw-r--r--drivers/dma/at_xdmac.c2
-rw-r--r--drivers/dma/dw/acpi.c6
-rw-r--r--drivers/dma/dw/internal.h8
-rw-r--r--drivers/dma/dw/pci.c4
-rw-r--r--drivers/dma/fsl-edma-common.h1
-rw-r--r--drivers/dma/fsl-edma-main.c41
-rw-r--r--drivers/dma/idxd/Makefile2
-rw-r--r--drivers/dma/idxd/compat.c2
-rw-r--r--drivers/dma/idxd/device.c14
-rw-r--r--drivers/dma/idxd/init.c2
-rw-r--r--drivers/dma/idxd/submit.c6
-rw-r--r--drivers/dma/loongson2-apb-dma.c2
-rw-r--r--drivers/dma/mv_xor.c2
-rw-r--r--drivers/dma/tegra186-gpc-dma.c10
-rw-r--r--drivers/edac/altera_edac.c4
-rw-r--r--drivers/edac/amd64_edac.c32
-rw-r--r--drivers/edac/armada_xp_edac.c4
-rw-r--r--drivers/edac/aspeed_edac.c2
-rw-r--r--drivers/edac/bluefield_edac.c2
-rw-r--r--drivers/edac/cell_edac.c2
-rw-r--r--drivers/edac/cpc925_edac.c2
-rw-r--r--drivers/edac/dmc520_edac.c2
-rw-r--r--drivers/edac/highbank_l2_edac.c2
-rw-r--r--drivers/edac/highbank_mc_edac.c2
-rw-r--r--drivers/edac/layerscape_edac.c2
-rw-r--r--drivers/edac/mpc85xx_edac.c6
-rw-r--r--drivers/edac/npcm_edac.c2
-rw-r--r--drivers/edac/octeon_edac-l2c.c2
-rw-r--r--drivers/edac/octeon_edac-lmc.c2
-rw-r--r--drivers/edac/octeon_edac-pc.c2
-rw-r--r--drivers/edac/octeon_edac-pci.c2
-rw-r--r--drivers/edac/qcom_edac.c2
-rw-r--r--drivers/edac/synopsys_edac.c2
-rw-r--r--drivers/edac/ti_edac.c2
-rw-r--r--drivers/edac/versal_edac.c2
-rw-r--r--drivers/edac/xgene_edac.c2
-rw-r--r--drivers/edac/zynqmp_edac.c2
-rw-r--r--drivers/extcon/extcon-adc-jack.c2
-rw-r--r--drivers/extcon/extcon-intel-cht-wc.c2
-rw-r--r--drivers/extcon/extcon-intel-mrfld.c2
-rw-r--r--drivers/extcon/extcon-max3355.c2
-rw-r--r--drivers/extcon/extcon-max77843.c2
-rw-r--r--drivers/extcon/extcon-rtk-type-c.c2
-rw-r--r--drivers/extcon/extcon-usb-gpio.c2
-rw-r--r--drivers/extcon/extcon-usbc-cros-ec.c2
-rw-r--r--drivers/firmware/arm_ffa/bus.c15
-rw-r--r--drivers/firmware/arm_ffa/driver.c7
-rw-r--r--drivers/firmware/arm_scmi/driver.c2
-rw-r--r--drivers/firmware/arm_scmi/vendors/imx/Kconfig1
-rw-r--r--drivers/firmware/arm_scpi.c2
-rw-r--r--drivers/firmware/cirrus/cs_dsp.c68
-rw-r--r--drivers/firmware/efi/Kconfig4
-rw-r--r--drivers/firmware/efi/efi-pstore.c2
-rw-r--r--drivers/firmware/efi/embedded-firmware.c4
-rw-r--r--drivers/firmware/efi/esrt.c2
-rw-r--r--drivers/firmware/efi/libstub/Makefile.zboot18
-rw-r--r--drivers/firmware/efi/vars.c16
-rw-r--r--drivers/firmware/google/coreboot_table.c2
-rw-r--r--drivers/firmware/imx/Kconfig1
-rw-r--r--drivers/firmware/imx/imx-dsp.c2
-rw-r--r--drivers/firmware/memmap.c2
-rw-r--r--drivers/firmware/microchip/mpfs-auto-update.c6
-rw-r--r--drivers/firmware/mtk-adsp-ipc.c9
-rw-r--r--drivers/firmware/qemu_fw_cfg.c2
-rw-r--r--drivers/firmware/raspberrypi.c2
-rw-r--r--drivers/firmware/stratix10-rsu.c2
-rw-r--r--drivers/firmware/stratix10-svc.c2
-rw-r--r--drivers/firmware/xilinx/zynqmp.c2
-rw-r--r--drivers/fpga/altera-fpga2sdram.c2
-rw-r--r--drivers/fpga/altera-freeze-bridge.c2
-rw-r--r--drivers/fpga/altera-hps2fpga.c2
-rw-r--r--drivers/fpga/dfl-afu-main.c8
-rw-r--r--drivers/fpga/dfl-fme-br.c8
-rw-r--r--drivers/fpga/dfl-fme-main.c8
-rw-r--r--drivers/fpga/dfl-fme-region.c8
-rw-r--r--drivers/fpga/intel-m10-bmc-sec-update.c4
-rw-r--r--drivers/fpga/of-fpga-region.c2
-rw-r--r--drivers/fpga/socfpga-a10.c2
-rw-r--r--drivers/fpga/stratix10-soc.c2
-rw-r--r--drivers/fpga/xilinx-pr-decoupler.c2
-rw-r--r--drivers/fpga/zynq-fpga.c2
-rw-r--r--drivers/fsi/fsi-master-aspeed.c2
-rw-r--r--drivers/fsi/fsi-master-ast-cf.c2
-rw-r--r--drivers/fsi/fsi-master-gpio.c2
-rw-r--r--drivers/fsi/fsi-occ.c2
-rw-r--r--drivers/gpio/Kconfig3
-rw-r--r--drivers/gpio/gpio-104-dio-48e.c4
-rw-r--r--drivers/gpio/gpio-104-idio-16.c2
-rw-r--r--drivers/gpio/gpio-aspeed-sgpio.c2
-rw-r--r--drivers/gpio/gpio-aspeed.c2
-rw-r--r--drivers/gpio/gpio-elkhartlake.c2
-rw-r--r--drivers/gpio/gpio-ep93xx.c2
-rw-r--r--drivers/gpio/gpio-gpio-mm.c2
-rw-r--r--drivers/gpio/gpio-graniterapids.c52
-rw-r--r--drivers/gpio/gpio-hlwd.c2
-rw-r--r--drivers/gpio/gpio-i8255.c2
-rw-r--r--drivers/gpio/gpio-idio-16.c5
-rw-r--r--drivers/gpio/gpio-ljca.c4
-rw-r--r--drivers/gpio/gpio-menz127.c2
-rw-r--r--drivers/gpio/gpio-merrifield.c2
-rw-r--r--drivers/gpio/gpio-mlxbf2.c2
-rw-r--r--drivers/gpio/gpio-omap.c2
-rw-r--r--drivers/gpio/gpio-pca953x.c2
-rw-r--r--drivers/gpio/gpio-pci-idio-16.c2
-rw-r--r--drivers/gpio/gpio-pl061.c2
-rw-r--r--drivers/gpio/gpio-tangier.c2
-rw-r--r--drivers/gpio/gpio-tegra.c2
-rw-r--r--drivers/gpio/gpio-tegra186.c2
-rw-r--r--drivers/gpio/gpio-tqmx86.c2
-rw-r--r--drivers/gpio/gpio-visconti.c2
-rw-r--r--drivers/gpio/gpio-xgs-iproc.c2
-rw-r--r--drivers/gpio/gpiolib-swnode.c2
-rw-r--r--drivers/gpu/drm/Kconfig4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/aldebaran.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu.h1
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c17
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_device.c122
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c8
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_job.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c3
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c5
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c37
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c20
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c41
-rw-r--r--drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/df_v3_6.c4
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c10
-rw-r--r--drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c18
-rw-r--r--drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c12
-rw-r--r--drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c7
-rw-r--r--drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c6
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c11
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c2
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c9
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c39
-rw-r--r--drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c10
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_crat.c30
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device.c3
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c15
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c7
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_migrate.c4
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process.c23
-rw-r--r--drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c12
-rw-r--r--drivers/gpu/drm/amd/display/Kconfig15
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c2
-rw-r--r--drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc.c25
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/core/dc_resource.c50
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc.h6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dc_spl_translate.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c15
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c48
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c13
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h8
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h1
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c24
-rw-r--r--drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h7
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c6
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c20
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/core_types.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h2
-rw-r--r--drivers/gpu/drm/amd/display/dc/link/link_dpms.c3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c23
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c7
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c2
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c1
-rw-r--r--drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h3
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl.c97
-rw-r--r--drivers/gpu/drm/amd/display/dc/spl/dc_spl.h2
-rw-r--r--drivers/gpu/drm/amd/display/modules/freesync/freesync.c13
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h2
-rw-r--r--drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h13
-rw-r--r--drivers/gpu/drm/amd/include/kgd_pp_interface.h119
-rw-r--r--drivers/gpu/drm/amd/pm/amdgpu_pm.c6
-rw-r--r--drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c24
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c189
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h17
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c173
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c170
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c171
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c41
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c43
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c175
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c12
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c142
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c2
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c200
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c36
-rw-r--r--drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h6
-rw-r--r--drivers/gpu/drm/arm/display/komeda/komeda_drv.c2
-rw-r--r--drivers/gpu/drm/arm/hdlcd_drv.c2
-rw-r--r--drivers/gpu/drm/arm/malidp_drv.c2
-rw-r--r--drivers/gpu/drm/armada/armada_crtc.c2
-rw-r--r--drivers/gpu/drm/armada/armada_drv.c2
-rw-r--r--drivers/gpu/drm/armada/armada_gem.c2
-rw-r--r--drivers/gpu/drm/aspeed/aspeed_gfx_drv.c2
-rw-r--r--drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c2
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_audio.c14
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7511_drv.c10
-rw-r--r--drivers/gpu/drm/bridge/adv7511/adv7533.c4
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c2
-rw-r--r--drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c2
-rw-r--r--drivers/gpu/drm/bridge/display-connector.c2
-rw-r--r--drivers/gpu/drm/bridge/fsl-ldb.c2
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c2
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx.c2
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qm-ldb.c2
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c2
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c2
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c2
-rw-r--r--drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c2
-rw-r--r--drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c2
-rw-r--r--drivers/gpu/drm/bridge/lvds-codec.c2
-rw-r--r--drivers/gpu/drm/bridge/nwl-dsi.c2
-rw-r--r--drivers/gpu/drm/bridge/samsung-dsim.c2
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c2
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c2
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c2
-rw-r--r--drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c2
-rw-r--r--drivers/gpu/drm/bridge/thc63lvd1024.c2
-rw-r--r--drivers/gpu/drm/bridge/ti-tfp410.c2
-rw-r--r--drivers/gpu/drm/bridge/ti-tpd12s015.c2
-rw-r--r--drivers/gpu/drm/display/drm_dp_aux_bus.c2
-rw-r--r--drivers/gpu/drm/display/drm_dp_mst_topology.c107
-rw-r--r--drivers/gpu/drm/display/drm_dp_tunnel.c10
-rw-r--r--drivers/gpu/drm/drm_gem_dma_helper.c2
-rw-r--r--drivers/gpu/drm/drm_gem_framebuffer_helper.c2
-rw-r--r--drivers/gpu/drm/drm_gem_shmem_helper.c4
-rw-r--r--drivers/gpu/drm/drm_modes.c11
-rw-r--r--drivers/gpu/drm/drm_panic_qr.rs1
-rw-r--r--drivers/gpu/drm/drm_prime.c2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_drv.c2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c2
-rw-r--r--drivers/gpu/drm/etnaviv/etnaviv_gpu.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos5433_drm_decon.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos7_drm_decon.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_dp.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_drv.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_dsi.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimc.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_fimd.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_g2d.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gsc.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_mic.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_rotator.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_scaler.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_vidi.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_hdmi.c2
-rw-r--r--drivers/gpu/drm/exynos/exynos_mixer.c2
-rw-r--r--drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c2
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c2
-rw-r--r--drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c2
-rw-r--r--drivers/gpu/drm/i915/display/intel_color.c81
-rw-r--r--drivers/gpu/drm/i915/display/intel_cx0_phy.c12
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.c19
-rw-r--r--drivers/gpu/drm/i915/display/intel_dsb.h2
-rw-r--r--drivers/gpu/drm/i915/display/intel_hdcp.c32
-rw-r--r--drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c2
-rw-r--r--drivers/gpu/drm/i915/gt/intel_engine_types.h5
-rw-r--r--drivers/gpu/drm/i915/gt/intel_rc6.c2
-rw-r--r--drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c41
-rw-r--r--drivers/gpu/drm/i915/gvt/kvmgt.c4
-rw-r--r--drivers/gpu/drm/i915/i915_gpu_error.c18
-rw-r--r--drivers/gpu/drm/i915/i915_scheduler.c2
-rw-r--r--drivers/gpu/drm/i915/intel_gvt.c74
-rw-r--r--drivers/gpu/drm/i915/intel_gvt_mmio_table.c2
-rw-r--r--drivers/gpu/drm/imagination/pvr_drv.c4
-rw-r--r--drivers/gpu/drm/imx/dcss/dcss-drv.c2
-rw-r--r--drivers/gpu/drm/imx/ipuv3/dw_hdmi-imx.c2
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-drm-core.c2
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-ldb.c2
-rw-r--r--drivers/gpu/drm/imx/ipuv3/imx-tve.c2
-rw-r--r--drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c2
-rw-r--r--drivers/gpu/drm/imx/ipuv3/parallel-display.c2
-rw-r--r--drivers/gpu/drm/imx/lcdc/imx-lcdc.c2
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-drm-drv.c2
-rw-r--r--drivers/gpu/drm/ingenic/ingenic-ipu.c2
-rw-r--r--drivers/gpu/drm/kmb/kmb_drv.c2
-rw-r--r--drivers/gpu/drm/lima/lima_drv.c2
-rw-r--r--drivers/gpu/drm/logicvc/logicvc_drm.c2
-rw-r--r--drivers/gpu/drm/mcde/mcde_drv.c2
-rw-r--r--drivers/gpu/drm/mcde/mcde_dsi.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_cec.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_aal.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ccorr.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_color.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_gamma.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_merge.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ovl.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_disp_rdma.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dp.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dpi.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_drm_drv.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_dsi.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_ethdr.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_mdp_rdma.c2
-rw-r--r--drivers/gpu/drm/mediatek/mtk_padding.c2
-rw-r--r--drivers/gpu/drm/meson/meson_drv.c2
-rw-r--r--drivers/gpu/drm/meson/meson_dw_hdmi.c2
-rw-r--r--drivers/gpu/drm/meson/meson_dw_mipi_dsi.c2
-rw-r--r--drivers/gpu/drm/msm/adreno/adreno_device.c2
-rw-r--r--drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c2
-rw-r--r--drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c2
-rw-r--r--drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c2
-rw-r--r--drivers/gpu/drm/msm/dp/dp_display.c2
-rw-r--r--drivers/gpu/drm/msm/dsi/dsi.c2
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi.c2
-rw-r--r--drivers/gpu/drm/msm/hdmi/hdmi_phy.c2
-rw-r--r--drivers/gpu/drm/msm/msm_drv.c2
-rw-r--r--drivers/gpu/drm/msm/msm_mdss.c2
-rw-r--r--drivers/gpu/drm/mxsfb/lcdif_drv.c2
-rw-r--r--drivers/gpu/drm/mxsfb/mxsfb_drv.c2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_platform.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dispc.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dsi.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/dss.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi4.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/hdmi5.c2
-rw-r--r--drivers/gpu/drm/omapdrm/dss/venc.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_dmm_tiler.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_drv.c2
-rw-r--r--drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c2
-rw-r--r--drivers/gpu/drm/panel/panel-edp.c2
-rw-r--r--drivers/gpu/drm/panel/panel-himax-hx83102.c2
-rw-r--r--drivers/gpu/drm/panel/panel-lvds.c2
-rw-r--r--drivers/gpu/drm/panel/panel-novatek-nt35950.c4
-rw-r--r--drivers/gpu/drm/panel/panel-seiko-43wvf1g.c2
-rw-r--r--drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c2
-rw-r--r--drivers/gpu/drm/panel/panel-simple.c2
-rw-r--r--drivers/gpu/drm/panel/panel-sitronix-st7701.c1
-rw-r--r--drivers/gpu/drm/panel/panel-synaptics-r63353.c2
-rw-r--r--drivers/gpu/drm/panfrost/panfrost_drv.c2
-rw-r--r--drivers/gpu/drm/panthor/panthor_drv.c2
-rw-r--r--drivers/gpu/drm/radeon/radeon_audio.c12
-rw-r--r--drivers/gpu/drm/radeon/radeon_connectors.c10
-rw-r--r--drivers/gpu/drm/radeon/radeon_drv.c3
-rw-r--r--drivers/gpu/drm/radeon/radeon_ttm.c3
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c2
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c2
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c2
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c2
-rw-r--r--drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c2
-rw-r--r--drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c2
-rw-r--r--drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c2
-rw-r--r--drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c2
-rw-r--r--drivers/gpu/drm/rockchip/analogix_dp-rockchip.c2
-rw-r--r--drivers/gpu/drm/rockchip/cdn-dp-core.c2
-rw-r--r--drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c2
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c2
-rw-r--r--drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c2
-rw-r--r--drivers/gpu/drm/rockchip/inno_hdmi.c2
-rw-r--r--drivers/gpu/drm/rockchip/rk3066_hdmi.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_drm_drv.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_lvds.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop2_reg.c2
-rw-r--r--drivers/gpu/drm/rockchip/rockchip_vop_reg.c2
-rw-r--r--drivers/gpu/drm/scheduler/sched_main.c3
-rw-r--r--drivers/gpu/drm/solomon/ssd130x-i2c.c2
-rw-r--r--drivers/gpu/drm/solomon/ssd130x-spi.c2
-rw-r--r--drivers/gpu/drm/solomon/ssd130x.c2
-rw-r--r--drivers/gpu/drm/sprd/sprd_dpu.c2
-rw-r--r--drivers/gpu/drm/sprd/sprd_drm.c2
-rw-r--r--drivers/gpu/drm/sprd/sprd_dsi.c2
-rw-r--r--drivers/gpu/drm/sti/sti_compositor.c2
-rw-r--r--drivers/gpu/drm/sti/sti_drv.c2
-rw-r--r--drivers/gpu/drm/sti/sti_dvo.c2
-rw-r--r--drivers/gpu/drm/sti/sti_hda.c2
-rw-r--r--drivers/gpu/drm/sti/sti_hdmi.c2
-rw-r--r--drivers/gpu/drm/sti/sti_hqvdp.c2
-rw-r--r--drivers/gpu/drm/sti/sti_mixer.c2
-rw-r--r--drivers/gpu/drm/sti/sti_tvout.c2
-rw-r--r--drivers/gpu/drm/stm/drv.c2
-rw-r--r--drivers/gpu/drm/stm/dw_mipi_dsi-stm.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_backend.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_drv.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_frontend.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tcon.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun4i_tv.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun6i_drc.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_mixer.c2
-rw-r--r--drivers/gpu/drm/sun4i/sun8i_tcon_top.c2
-rw-r--r--drivers/gpu/drm/tegra/dc.c2
-rw-r--r--drivers/gpu/drm/tegra/dpaux.c2
-rw-r--r--drivers/gpu/drm/tegra/dsi.c2
-rw-r--r--drivers/gpu/drm/tegra/gem.c2
-rw-r--r--drivers/gpu/drm/tegra/gr2d.c2
-rw-r--r--drivers/gpu/drm/tegra/gr3d.c2
-rw-r--r--drivers/gpu/drm/tegra/hdmi.c2
-rw-r--r--drivers/gpu/drm/tegra/hub.c2
-rw-r--r--drivers/gpu/drm/tegra/nvdec.c2
-rw-r--r--drivers/gpu/drm/tegra/sor.c2
-rw-r--r--drivers/gpu/drm/tegra/vic.c2
-rw-r--r--drivers/gpu/drm/tidss/tidss_drv.c2
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_drv.c2
-rw-r--r--drivers/gpu/drm/tilcdc/tilcdc_panel.c2
-rw-r--r--drivers/gpu/drm/tiny/arcpgu.c2
-rw-r--r--drivers/gpu/drm/tiny/ofdrm.c2
-rw-r--r--drivers/gpu/drm/tiny/simpledrm.c2
-rw-r--r--drivers/gpu/drm/tve200/tve200_drv.c2
-rw-r--r--drivers/gpu/drm/v3d/v3d_drv.c2
-rw-r--r--drivers/gpu/drm/v3d/v3d_perfmon.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_crtc.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_dpi.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_drv.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_dsi.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_hdmi.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_hvs.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_txp.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_v3d.c2
-rw-r--r--drivers/gpu/drm/vc4/vc4_vec.c2
-rw-r--r--drivers/gpu/drm/vmwgfx/ttm_object.c2
-rw-r--r--drivers/gpu/drm/xe/tests/xe_live_test_mod.c2
-rw-r--r--drivers/gpu/drm/xe/tests/xe_migrate.c4
-rw-r--r--drivers/gpu/drm/xe/tests/xe_test_mod.c2
-rw-r--r--drivers/gpu/drm/xe/xe_bo.c12
-rw-r--r--drivers/gpu/drm/xe/xe_devcoredump.c84
-rw-r--r--drivers/gpu/drm/xe/xe_device.c3
-rw-r--r--drivers/gpu/drm/xe/xe_dma_buf.c2
-rw-r--r--drivers/gpu/drm/xe/xe_exec_queue.c9
-rw-r--r--drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c2
-rw-r--r--drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c8
-rw-r--r--drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h1
-rw-r--r--drivers/gpu/drm/xe/xe_guc_capture.c77
-rw-r--r--drivers/gpu/drm/xe/xe_guc_submit.c34
-rw-r--r--drivers/gpu/drm/xe/xe_migrate.c6
-rw-r--r--drivers/gpu/drm/xe/xe_oa.c134
-rw-r--r--drivers/gpu/drm/xe/xe_pci.c2
-rw-r--r--drivers/gpu/drm/xe/xe_pt.c3
-rw-r--r--drivers/gpu/drm/xe/xe_reg_sr.c31
-rw-r--r--drivers/gpu/drm/xe/xe_reg_sr_types.h6
-rw-r--r--drivers/gpu/drm/xe/xe_ring_ops.c5
-rw-r--r--drivers/gpu/drm/xe/xe_sched_job_types.h2
-rw-r--r--drivers/gpu/drm/xe/xe_sync.c6
-rw-r--r--drivers/gpu/drm/xlnx/zynqmp_dpsub.c2
-rw-r--r--drivers/gpu/host1x/dev.c2
-rw-r--r--drivers/gpu/ipu-v3/ipu-common.c2
-rw-r--r--drivers/gpu/ipu-v3/ipu-pre.c2
-rw-r--r--drivers/gpu/ipu-v3/ipu-prg.c2
-rw-r--r--drivers/greybus/interface.c2
-rw-r--r--drivers/hid/bpf/hid_bpf_dispatch.c17
-rw-r--r--drivers/hid/hid-core.c2
-rw-r--r--drivers/hid/hid-google-hammer.c2
-rw-r--r--drivers/hid/hid-sensor-custom.c2
-rw-r--r--drivers/hid/hid-uclogic-rdesc-test.c2
-rw-r--r--drivers/hid/i2c-hid/i2c-hid-core.c20
-rw-r--r--drivers/hid/surface-hid/surface_kbd.c2
-rw-r--r--drivers/hid/wacom_sys.c3
-rw-r--r--drivers/hsi/controllers/omap_ssi_core.c2
-rw-r--r--drivers/hsi/controllers/omap_ssi_port.c2
-rw-r--r--drivers/hte/hte-tegra194-test.c2
-rw-r--r--drivers/hv/hv_balloon.c9
-rw-r--r--drivers/hv/hv_kvp.c10
-rw-r--r--drivers/hv/hv_snapshot.c9
-rw-r--r--drivers/hv/hv_util.c13
-rw-r--r--drivers/hv/hyperv_vmbus.h2
-rw-r--r--drivers/hv/vmbus_drv.c4
-rw-r--r--drivers/hwmon/hwmon.c2
-rw-r--r--drivers/hwmon/intel-m10-bmc-hwmon.c2
-rw-r--r--drivers/hwmon/nct6775-core.c2
-rw-r--r--drivers/hwmon/nct6775-i2c.c2
-rw-r--r--drivers/hwmon/nct6775-platform.c2
-rw-r--r--drivers/hwmon/peci/cputemp.c2
-rw-r--r--drivers/hwmon/peci/dimmtemp.c2
-rw-r--r--drivers/hwmon/pmbus/acbel-fsg032.c2
-rw-r--r--drivers/hwmon/pmbus/adm1266.c2
-rw-r--r--drivers/hwmon/pmbus/adm1275.c2
-rw-r--r--drivers/hwmon/pmbus/adp1050.c2
-rw-r--r--drivers/hwmon/pmbus/bel-pfe.c2
-rw-r--r--drivers/hwmon/pmbus/bpa-rs600.c2
-rw-r--r--drivers/hwmon/pmbus/delta-ahe50dc-fan.c2
-rw-r--r--drivers/hwmon/pmbus/dps920ab.c2
-rw-r--r--drivers/hwmon/pmbus/fsp-3y.c2
-rw-r--r--drivers/hwmon/pmbus/ibm-cffps.c2
-rw-r--r--drivers/hwmon/pmbus/inspur-ipsps.c2
-rw-r--r--drivers/hwmon/pmbus/ir35221.c2
-rw-r--r--drivers/hwmon/pmbus/ir36021.c2
-rw-r--r--drivers/hwmon/pmbus/ir38064.c2
-rw-r--r--drivers/hwmon/pmbus/irps5401.c2
-rw-r--r--drivers/hwmon/pmbus/isl68137.c2
-rw-r--r--drivers/hwmon/pmbus/lm25066.c2
-rw-r--r--drivers/hwmon/pmbus/lt7182s.c2
-rw-r--r--drivers/hwmon/pmbus/ltc2978.c2
-rw-r--r--drivers/hwmon/pmbus/ltc3815.c2
-rw-r--r--drivers/hwmon/pmbus/max15301.c2
-rw-r--r--drivers/hwmon/pmbus/max16064.c2
-rw-r--r--drivers/hwmon/pmbus/max16601.c2
-rw-r--r--drivers/hwmon/pmbus/max20730.c2
-rw-r--r--drivers/hwmon/pmbus/max20751.c2
-rw-r--r--drivers/hwmon/pmbus/max31785.c2
-rw-r--r--drivers/hwmon/pmbus/max34440.c2
-rw-r--r--drivers/hwmon/pmbus/max8688.c2
-rw-r--r--drivers/hwmon/pmbus/mp2856.c2
-rw-r--r--drivers/hwmon/pmbus/mp2888.c2
-rw-r--r--drivers/hwmon/pmbus/mp2891.c2
-rw-r--r--drivers/hwmon/pmbus/mp2975.c2
-rw-r--r--drivers/hwmon/pmbus/mp2993.c2
-rw-r--r--drivers/hwmon/pmbus/mp5023.c2
-rw-r--r--drivers/hwmon/pmbus/mp5920.c2
-rw-r--r--drivers/hwmon/pmbus/mp5990.c2
-rw-r--r--drivers/hwmon/pmbus/mp9941.c2
-rw-r--r--drivers/hwmon/pmbus/mpq7932.c2
-rw-r--r--drivers/hwmon/pmbus/mpq8785.c2
-rw-r--r--drivers/hwmon/pmbus/pim4328.c2
-rw-r--r--drivers/hwmon/pmbus/pli1209bc.c2
-rw-r--r--drivers/hwmon/pmbus/pm6764tr.c2
-rw-r--r--drivers/hwmon/pmbus/pmbus.c2
-rw-r--r--drivers/hwmon/pmbus/pmbus_core.c42
-rw-r--r--drivers/hwmon/pmbus/pxe1610.c2
-rw-r--r--drivers/hwmon/pmbus/q54sj108a2.c2
-rw-r--r--drivers/hwmon/pmbus/stpddc60.c2
-rw-r--r--drivers/hwmon/pmbus/tda38640.c2
-rw-r--r--drivers/hwmon/pmbus/tps40422.c2
-rw-r--r--drivers/hwmon/pmbus/tps53679.c2
-rw-r--r--drivers/hwmon/pmbus/tps546d24.c2
-rw-r--r--drivers/hwmon/pmbus/ucd9000.c2
-rw-r--r--drivers/hwmon/pmbus/ucd9200.c2
-rw-r--r--drivers/hwmon/pmbus/xdp710.c2
-rw-r--r--drivers/hwmon/pmbus/xdpe12284.c2
-rw-r--r--drivers/hwmon/pmbus/xdpe152c4.c2
-rw-r--r--drivers/hwmon/pmbus/zl6100.c2
-rw-r--r--drivers/hwmon/tmp513.c10
-rw-r--r--drivers/hwspinlock/u8500_hsem.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-catu.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-cpu-debug.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-dummy.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x-core.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-funnel.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-replicator.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-stm.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-tmc-core.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-tpiu.c2
-rw-r--r--drivers/hwtracing/coresight/coresight-trbe.c2
-rw-r--r--drivers/hwtracing/coresight/ultrasoc-smb.c2
-rw-r--r--drivers/hwtracing/intel_th/acpi.c2
-rw-r--r--drivers/i2c/Makefile1
-rw-r--r--drivers/i2c/busses/i2c-amd-asf-plat.c2
-rw-r--r--drivers/i2c/busses/i2c-cgbc.c2
-rw-r--r--drivers/i2c/busses/i2c-designware-common.c2
-rw-r--r--drivers/i2c/busses/i2c-designware-master.c4
-rw-r--r--drivers/i2c/busses/i2c-designware-pcidrv.c4
-rw-r--r--drivers/i2c/busses/i2c-designware-platdrv.c4
-rw-r--r--drivers/i2c/busses/i2c-designware-slave.c4
-rw-r--r--drivers/i2c/busses/i2c-imx.c9
-rw-r--r--drivers/i2c/busses/i2c-ljca.c2
-rw-r--r--drivers/i2c/busses/i2c-microchip-corei2c.c122
-rw-r--r--drivers/i2c/busses/i2c-nomadik.c1
-rw-r--r--drivers/i2c/busses/i2c-piix4.c8
-rw-r--r--drivers/i2c/busses/i2c-pnx.c4
-rw-r--r--drivers/i2c/busses/i2c-riic.c2
-rw-r--r--drivers/i2c/i2c-atr.c12
-rw-r--r--drivers/i2c/i2c-core-of-prober.c415
-rw-r--r--drivers/i2c/i2c-core-smbus.c2
-rw-r--r--drivers/i3c/master/ast2600-i3c-master.c2
-rw-r--r--drivers/i3c/master/dw-i3c-master.c2
-rw-r--r--drivers/i3c/master/i3c-master-cdns.c2
-rw-r--r--drivers/i3c/master/mipi-i3c-hci/core.c2
-rw-r--r--drivers/i3c/master/svc-i3c-master.c2
-rw-r--r--drivers/iio/accel/adis16201.c2
-rw-r--r--drivers/iio/accel/adis16209.c2
-rw-r--r--drivers/iio/accel/adxl313_core.c16
-rw-r--r--drivers/iio/accel/adxl313_i2c.c2
-rw-r--r--drivers/iio/accel/adxl313_spi.c2
-rw-r--r--drivers/iio/accel/adxl345_core.c2
-rw-r--r--drivers/iio/accel/adxl345_i2c.c2
-rw-r--r--drivers/iio/accel/adxl345_spi.c2
-rw-r--r--drivers/iio/accel/adxl355_core.c10
-rw-r--r--drivers/iio/accel/adxl355_i2c.c2
-rw-r--r--drivers/iio/accel/adxl355_spi.c2
-rw-r--r--drivers/iio/accel/adxl367.c4
-rw-r--r--drivers/iio/accel/adxl367_i2c.c2
-rw-r--r--drivers/iio/accel/adxl367_spi.c2
-rw-r--r--drivers/iio/accel/adxl372.c6
-rw-r--r--drivers/iio/accel/adxl372_i2c.c2
-rw-r--r--drivers/iio/accel/adxl372_spi.c2
-rw-r--r--drivers/iio/accel/adxl380.c19
-rw-r--r--drivers/iio/accel/adxl380_i2c.c2
-rw-r--r--drivers/iio/accel/adxl380_spi.c2
-rw-r--r--drivers/iio/accel/bma180.c3
-rw-r--r--drivers/iio/accel/bma220_spi.c1
-rw-r--r--drivers/iio/accel/bma400_core.c8
-rw-r--r--drivers/iio/accel/bma400_i2c.c2
-rw-r--r--drivers/iio/accel/bma400_spi.c2
-rw-r--r--drivers/iio/accel/bmc150-accel-core.c10
-rw-r--r--drivers/iio/accel/bmc150-accel-i2c.c2
-rw-r--r--drivers/iio/accel/bmc150-accel-spi.c2
-rw-r--r--drivers/iio/accel/bmc150-accel.h3
-rw-r--r--drivers/iio/accel/bmi088-accel-core.c6
-rw-r--r--drivers/iio/accel/bmi088-accel-i2c.c2
-rw-r--r--drivers/iio/accel/bmi088-accel-spi.c2
-rw-r--r--drivers/iio/accel/fxls8962af-core.c14
-rw-r--r--drivers/iio/accel/fxls8962af-i2c.c2
-rw-r--r--drivers/iio/accel/fxls8962af-spi.c2
-rw-r--r--drivers/iio/accel/hid-sensor-accel-3d.c11
-rw-r--r--drivers/iio/accel/kionix-kx022a-i2c.c2
-rw-r--r--drivers/iio/accel/kionix-kx022a-spi.c2
-rw-r--r--drivers/iio/accel/kionix-kx022a.c13
-rw-r--r--drivers/iio/accel/kxcjk-1013.c442
-rw-r--r--drivers/iio/accel/kxsd9-i2c.c2
-rw-r--r--drivers/iio/accel/kxsd9-spi.c2
-rw-r--r--drivers/iio/accel/kxsd9.c7
-rw-r--r--drivers/iio/accel/mma7455_core.c9
-rw-r--r--drivers/iio/accel/mma7455_i2c.c2
-rw-r--r--drivers/iio/accel/mma7455_spi.c2
-rw-r--r--drivers/iio/accel/mma8452.c5
-rw-r--r--drivers/iio/accel/mma9551.c29
-rw-r--r--drivers/iio/accel/mma9551_core.c36
-rw-r--r--drivers/iio/accel/mma9553.c48
-rw-r--r--drivers/iio/accel/msa311.c3
-rw-r--r--drivers/iio/accel/mxc4005.c3
-rw-r--r--drivers/iio/accel/sca3000.c6
-rw-r--r--drivers/iio/accel/ssp_accel_sensor.c2
-rw-r--r--drivers/iio/accel/st_accel_core.c6
-rw-r--r--drivers/iio/accel/st_accel_i2c.c2
-rw-r--r--drivers/iio/accel/st_accel_spi.c2
-rw-r--r--drivers/iio/accel/stk8312.c3
-rw-r--r--drivers/iio/accel/stk8ba50.c3
-rw-r--r--drivers/iio/adc/Kconfig43
-rw-r--r--drivers/iio/adc/Makefile3
-rw-r--r--drivers/iio/adc/ab8500-gpadc.c2
-rw-r--r--drivers/iio/adc/ad4000.c6
-rw-r--r--drivers/iio/adc/ad7091r-base.c11
-rw-r--r--drivers/iio/adc/ad7091r-base.h2
-rw-r--r--drivers/iio/adc/ad7091r5.c2
-rw-r--r--drivers/iio/adc/ad7091r8.c2
-rw-r--r--drivers/iio/adc/ad7124.c2
-rw-r--r--drivers/iio/adc/ad7173.c40
-rw-r--r--drivers/iio/adc/ad7192.c5
-rw-r--r--drivers/iio/adc/ad7266.c2
-rw-r--r--drivers/iio/adc/ad7280a.c14
-rw-r--r--drivers/iio/adc/ad7291.c2
-rw-r--r--drivers/iio/adc/ad7380.c178
-rw-r--r--drivers/iio/adc/ad7606.c1062
-rw-r--r--drivers/iio/adc/ad7606.h134
-rw-r--r--drivers/iio/adc/ad7606_par.c135
-rw-r--r--drivers/iio/adc/ad7606_spi.c197
-rw-r--r--drivers/iio/adc/ad7625.c684
-rw-r--r--drivers/iio/adc/ad7779.c914
-rw-r--r--drivers/iio/adc/ad7780.c4
-rw-r--r--drivers/iio/adc/ad7791.c6
-rw-r--r--drivers/iio/adc/ad7793.c4
-rw-r--r--drivers/iio/adc/ad7887.c4
-rw-r--r--drivers/iio/adc/ad7923.c4
-rw-r--r--drivers/iio/adc/ad7944.c4
-rw-r--r--drivers/iio/adc/ad799x.c2
-rw-r--r--drivers/iio/adc/ad9467.c2
-rw-r--r--drivers/iio/adc/ad_sigma_delta.c24
-rw-r--r--drivers/iio/adc/adi-axi-adc.c4
-rw-r--r--drivers/iio/adc/at91-sama5d2_adc.c2
-rw-r--r--drivers/iio/adc/at91_adc.c2
-rw-r--r--drivers/iio/adc/axp20x_adc.c62
-rw-r--r--drivers/iio/adc/axp288_adc.c2
-rw-r--r--drivers/iio/adc/bcm_iproc_adc.c8
-rw-r--r--drivers/iio/adc/da9150-gpadc.c26
-rw-r--r--drivers/iio/adc/dln2-adc.c2
-rw-r--r--drivers/iio/adc/ep93xx_adc.c2
-rw-r--r--drivers/iio/adc/exynos_adc.c2
-rw-r--r--drivers/iio/adc/gehc-pmc-adc.c228
-rw-r--r--drivers/iio/adc/hi8435.c2
-rw-r--r--drivers/iio/adc/imx8qxp-adc.c2
-rw-r--r--drivers/iio/adc/imx93_adc.c2
-rw-r--r--drivers/iio/adc/intel_mrfld_adc.c2
-rw-r--r--drivers/iio/adc/lp8788_adc.c18
-rw-r--r--drivers/iio/adc/ltc2497-core.c19
-rw-r--r--drivers/iio/adc/ltc2497.h2
-rw-r--r--drivers/iio/adc/max11205.c2
-rw-r--r--drivers/iio/adc/max1363.c5
-rw-r--r--drivers/iio/adc/max34408.c2
-rw-r--r--drivers/iio/adc/men_z188_adc.c2
-rw-r--r--drivers/iio/adc/meson_saradc.c2
-rw-r--r--drivers/iio/adc/mp2629_adc.c4
-rw-r--r--drivers/iio/adc/mt6360-adc.c2
-rw-r--r--drivers/iio/adc/mxs-lradc-adc.c6
-rw-r--r--drivers/iio/adc/npcm_adc.c2
-rw-r--r--drivers/iio/adc/pac1921.c48
-rw-r--r--drivers/iio/adc/pac1934.c2
-rw-r--r--drivers/iio/adc/palmas_gpadc.c4
-rw-r--r--drivers/iio/adc/qcom-pm8xxx-xoadc.c10
-rw-r--r--drivers/iio/adc/qcom-spmi-adc5.c4
-rw-r--r--drivers/iio/adc/qcom-spmi-vadc.c7
-rw-r--r--drivers/iio/adc/rcar-gyroadc.c2
-rw-r--r--drivers/iio/adc/rn5t618-adc.c2
-rw-r--r--drivers/iio/adc/sd_adc_modulator.c2
-rw-r--r--drivers/iio/adc/stm32-adc-core.c2
-rw-r--r--drivers/iio/adc/stm32-adc.c2
-rw-r--r--drivers/iio/adc/stm32-dfsdm-adc.c4
-rw-r--r--drivers/iio/adc/stm32-dfsdm-core.c2
-rw-r--r--drivers/iio/adc/sun20i-gpadc-iio.c7
-rw-r--r--drivers/iio/adc/sun4i-gpadc-iio.c9
-rw-r--r--drivers/iio/adc/ti-ads1015.c5
-rw-r--r--drivers/iio/adc/ti-ads1119.c2
-rw-r--r--drivers/iio/adc/ti-ads1298.c2
-rw-r--r--drivers/iio/adc/ti_am335x_adc.c10
-rw-r--r--drivers/iio/adc/twl4030-madc.c4
-rw-r--r--drivers/iio/adc/twl6030-gpadc.c2
-rw-r--r--drivers/iio/adc/vf610_adc.c2
-rw-r--r--drivers/iio/adc/xilinx-ams.c2
-rw-r--r--drivers/iio/adc/xilinx-xadc-events.c4
-rw-r--r--drivers/iio/adc/xilinx-xadc.h2
-rw-r--r--drivers/iio/addac/ad74115.c18
-rw-r--r--drivers/iio/addac/ad74413r.c102
-rw-r--r--drivers/iio/addac/stx104.c2
-rw-r--r--drivers/iio/afe/iio-rescale.c4
-rw-r--r--drivers/iio/buffer/industrialio-buffer-dma.c36
-rw-r--r--drivers/iio/buffer/industrialio-buffer-dmaengine.c8
-rw-r--r--drivers/iio/cdc/ad7150.c2
-rw-r--r--drivers/iio/chemical/Kconfig2
-rw-r--r--drivers/iio/chemical/bme680.h11
-rw-r--r--drivers/iio/chemical/bme680_core.c370
-rw-r--r--drivers/iio/chemical/bme680_i2c.c2
-rw-r--r--drivers/iio/chemical/bme680_spi.c2
-rw-r--r--drivers/iio/chemical/ens160_core.c2
-rw-r--r--drivers/iio/chemical/ens160_i2c.c2
-rw-r--r--drivers/iio/chemical/ens160_spi.c2
-rw-r--r--drivers/iio/chemical/scd30_core.c2
-rw-r--r--drivers/iio/chemical/scd30_i2c.c2
-rw-r--r--drivers/iio/chemical/scd30_serial.c2
-rw-r--r--drivers/iio/chemical/sps30.c2
-rw-r--r--drivers/iio/chemical/sps30_i2c.c2
-rw-r--r--drivers/iio/chemical/sps30_serial.c2
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-attributes.c26
-rw-r--r--drivers/iio/common/hid-sensors/hid-sensor-trigger.c10
-rw-r--r--drivers/iio/common/inv_sensors/inv_sensors_timestamp.c12
-rw-r--r--drivers/iio/common/ms_sensors/ms_sensors_i2c.c24
-rw-r--r--drivers/iio/common/ssp_sensors/ssp_dev.c10
-rw-r--r--drivers/iio/common/ssp_sensors/ssp_iio.c8
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_buffer.c2
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_core.c28
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_i2c.c2
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_spi.c2
-rw-r--r--drivers/iio/common/st_sensors/st_sensors_trigger.c6
-rw-r--r--drivers/iio/dac/Kconfig32
-rw-r--r--drivers/iio/dac/Makefile3
-rw-r--r--drivers/iio/dac/ad3552r-common.c249
-rw-r--r--drivers/iio/dac/ad3552r-hs.c529
-rw-r--r--drivers/iio/dac/ad3552r-hs.h19
-rw-r--r--drivers/iio/dac/ad3552r.c557
-rw-r--r--drivers/iio/dac/ad3552r.h228
-rw-r--r--drivers/iio/dac/ad5380.c85
-rw-r--r--drivers/iio/dac/ad5421.c2
-rw-r--r--drivers/iio/dac/ad5446.c77
-rw-r--r--drivers/iio/dac/ad5504.c61
-rw-r--r--drivers/iio/dac/ad5592r-base.c4
-rw-r--r--drivers/iio/dac/ad5592r.c2
-rw-r--r--drivers/iio/dac/ad5593r.c2
-rw-r--r--drivers/iio/dac/ad5624r.h1
-rw-r--r--drivers/iio/dac/ad5624r_spi.c71
-rw-r--r--drivers/iio/dac/ad5686-spi.c2
-rw-r--r--drivers/iio/dac/ad5686.c4
-rw-r--r--drivers/iio/dac/ad5696-i2c.c2
-rw-r--r--drivers/iio/dac/ad5755.c11
-rw-r--r--drivers/iio/dac/ad5761.c109
-rw-r--r--drivers/iio/dac/ad5770r.c44
-rw-r--r--drivers/iio/dac/ad5791.c205
-rw-r--r--drivers/iio/dac/ad8460.c951
-rw-r--r--drivers/iio/dac/ad9739a.c2
-rw-r--r--drivers/iio/dac/adi-axi-dac.c453
-rw-r--r--drivers/iio/dac/dpot-dac.c2
-rw-r--r--drivers/iio/dac/lpc18xx_dac.c6
-rw-r--r--drivers/iio/dac/m62332.c2
-rw-r--r--drivers/iio/dac/max517.c2
-rw-r--r--drivers/iio/dac/stm32-dac-core.c2
-rw-r--r--drivers/iio/dac/stm32-dac.c2
-rw-r--r--drivers/iio/dac/vf610_dac.c2
-rw-r--r--drivers/iio/dummy/iio_simple_dummy.h2
-rw-r--r--drivers/iio/dummy/iio_simple_dummy_events.c32
-rw-r--r--drivers/iio/frequency/ad9523.c2
-rw-r--r--drivers/iio/frequency/adf4350.c2
-rw-r--r--drivers/iio/frequency/adf4371.c63
-rw-r--r--drivers/iio/gyro/Kconfig2
-rw-r--r--drivers/iio/gyro/adis16136.c2
-rw-r--r--drivers/iio/gyro/adis16260.c2
-rw-r--r--drivers/iio/gyro/bmg160_core.c19
-rw-r--r--drivers/iio/gyro/bmg160_i2c.c6
-rw-r--r--drivers/iio/gyro/fxas21002c_core.c7
-rw-r--r--drivers/iio/gyro/fxas21002c_i2c.c2
-rw-r--r--drivers/iio/gyro/fxas21002c_spi.c2
-rw-r--r--drivers/iio/gyro/hid-sensor-gyro-3d.c10
-rw-r--r--drivers/iio/gyro/mpu3050-core.c2
-rw-r--r--drivers/iio/gyro/ssp_gyro_sensor.c2
-rw-r--r--drivers/iio/gyro/st_gyro_core.c6
-rw-r--r--drivers/iio/gyro/st_gyro_i2c.c2
-rw-r--r--drivers/iio/gyro/st_gyro_spi.c2
-rw-r--r--drivers/iio/humidity/hid-sensor-humidity.c6
-rw-r--r--drivers/iio/humidity/hts221_buffer.c3
-rw-r--r--drivers/iio/humidity/hts221_core.c2
-rw-r--r--drivers/iio/humidity/hts221_i2c.c2
-rw-r--r--drivers/iio/humidity/hts221_spi.c2
-rw-r--r--drivers/iio/humidity/htu21.c2
-rw-r--r--drivers/iio/imu/Kconfig15
-rw-r--r--drivers/iio/imu/Makefile3
-rw-r--r--drivers/iio/imu/adis.c20
-rw-r--r--drivers/iio/imu/adis16400.c2
-rw-r--r--drivers/iio/imu/adis16460.c2
-rw-r--r--drivers/iio/imu/adis16475.c2
-rw-r--r--drivers/iio/imu/adis16480.c2
-rw-r--r--drivers/iio/imu/adis_buffer.c4
-rw-r--r--drivers/iio/imu/adis_trigger.c2
-rw-r--r--drivers/iio/imu/bmi160/bmi160_core.c17
-rw-r--r--drivers/iio/imu/bmi160/bmi160_i2c.c2
-rw-r--r--drivers/iio/imu/bmi160/bmi160_spi.c2
-rw-r--r--drivers/iio/imu/bmi270/Kconfig33
-rw-r--r--drivers/iio/imu/bmi270/Makefile7
-rw-r--r--drivers/iio/imu/bmi270/bmi270.h38
-rw-r--r--drivers/iio/imu/bmi270/bmi270_core.c734
-rw-r--r--drivers/iio/imu/bmi270/bmi270_i2c.c66
-rw-r--r--drivers/iio/imu/bmi270/bmi270_spi.c92
-rw-r--r--drivers/iio/imu/bmi323/bmi323.h1
-rw-r--r--drivers/iio/imu/bmi323/bmi323_core.c22
-rw-r--r--drivers/iio/imu/bmi323/bmi323_i2c.c2
-rw-r--r--drivers/iio/imu/bmi323/bmi323_spi.c2
-rw-r--r--drivers/iio/imu/bno055/bno055.c4
-rw-r--r--drivers/iio/imu/bno055/bno055_i2c.c2
-rw-r--r--drivers/iio/imu/bno055/bno055_ser_core.c2
-rw-r--r--drivers/iio/imu/fxos8700_core.c1
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c2
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_core.c16
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c3
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c19
-rw-r--r--drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c19
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c11
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_core.c42
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c12
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h4
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c12
-rw-r--r--drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c1
-rw-r--r--drivers/iio/imu/kmx61.c27
-rw-r--r--drivers/iio/imu/smi240.c621
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h2
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c24
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c2
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c2
-rw-r--r--drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c2
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c4
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c2
-rw-r--r--drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c2
-rw-r--r--drivers/iio/industrialio-acpi.c48
-rw-r--r--drivers/iio/industrialio-backend.c130
-rw-r--r--drivers/iio/industrialio-buffer.c2
-rw-r--r--drivers/iio/industrialio-core.c3
-rw-r--r--drivers/iio/industrialio-gts-helper.c30
-rw-r--r--drivers/iio/inkern.c9
-rw-r--r--drivers/iio/light/Kconfig18
-rw-r--r--drivers/iio/light/Makefile1
-rw-r--r--drivers/iio/light/adux1020.c12
-rw-r--r--drivers/iio/light/al3010.c11
-rw-r--r--drivers/iio/light/apds9300.c20
-rw-r--r--drivers/iio/light/apds9306.c9
-rw-r--r--drivers/iio/light/apds9960.c10
-rw-r--r--drivers/iio/light/bh1745.c52
-rw-r--r--drivers/iio/light/cm32181.c3
-rw-r--r--drivers/iio/light/cm3605.c2
-rw-r--r--drivers/iio/light/cm36651.c2
-rw-r--r--drivers/iio/light/gp2ap002.c2
-rw-r--r--drivers/iio/light/gp2ap020a00f.c2
-rw-r--r--drivers/iio/light/hid-sensor-als.c10
-rw-r--r--drivers/iio/light/hid-sensor-prox.c203
-rw-r--r--drivers/iio/light/iqs621-als.c2
-rw-r--r--drivers/iio/light/isl29018.c38
-rw-r--r--drivers/iio/light/lm3533-als.c8
-rw-r--r--drivers/iio/light/ltr390.c362
-rw-r--r--drivers/iio/light/ltr501.c35
-rw-r--r--drivers/iio/light/ltrf216a.c1
-rw-r--r--drivers/iio/light/max44009.c2
-rw-r--r--drivers/iio/light/opt3001.c191
-rw-r--r--drivers/iio/light/rohm-bu27008.c2
-rw-r--r--drivers/iio/light/rohm-bu27034.c2
-rw-r--r--drivers/iio/light/rpr0521.c14
-rw-r--r--drivers/iio/light/st_uvis25_core.c5
-rw-r--r--drivers/iio/light/st_uvis25_i2c.c2
-rw-r--r--drivers/iio/light/st_uvis25_spi.c2
-rw-r--r--drivers/iio/light/stk3310.c5
-rw-r--r--drivers/iio/light/tcs3472.c2
-rw-r--r--drivers/iio/light/tsl2563.c2
-rw-r--r--drivers/iio/light/tsl2591.c2
-rw-r--r--drivers/iio/light/tsl2772.c6
-rw-r--r--drivers/iio/light/us5182d.c2
-rw-r--r--drivers/iio/light/vcnl4000.c5
-rw-r--r--drivers/iio/light/veml3235.c495
-rw-r--r--drivers/iio/light/veml6030.c537
-rw-r--r--drivers/iio/light/veml6070.c201
-rw-r--r--drivers/iio/light/vl6180.c255
-rw-r--r--drivers/iio/magnetometer/Kconfig13
-rw-r--r--drivers/iio/magnetometer/Makefile1
-rw-r--r--drivers/iio/magnetometer/ak8974.c2
-rw-r--r--drivers/iio/magnetometer/als31300.c494
-rw-r--r--drivers/iio/magnetometer/bmc150_magn.c23
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_i2c.c11
-rw-r--r--drivers/iio/magnetometer/bmc150_magn_spi.c11
-rw-r--r--drivers/iio/magnetometer/hid-sensor-magn-3d.c8
-rw-r--r--drivers/iio/magnetometer/hmc5843_core.c4
-rw-r--r--drivers/iio/magnetometer/hmc5843_i2c.c2
-rw-r--r--drivers/iio/magnetometer/hmc5843_spi.c2
-rw-r--r--drivers/iio/magnetometer/rm3100-core.c8
-rw-r--r--drivers/iio/magnetometer/rm3100-i2c.c2
-rw-r--r--drivers/iio/magnetometer/rm3100-spi.c2
-rw-r--r--drivers/iio/magnetometer/st_magn_core.c6
-rw-r--r--drivers/iio/magnetometer/st_magn_i2c.c2
-rw-r--r--drivers/iio/magnetometer/st_magn_spi.c2
-rw-r--r--drivers/iio/magnetometer/yamaha-yas530.c13
-rw-r--r--drivers/iio/orientation/hid-sensor-incl-3d.c10
-rw-r--r--drivers/iio/orientation/hid-sensor-rotation.c10
-rw-r--r--drivers/iio/position/hid-sensor-custom-intel-hinge.c10
-rw-r--r--drivers/iio/position/iqs624-pos.c2
-rw-r--r--drivers/iio/pressure/bmp280-core.c725
-rw-r--r--drivers/iio/pressure/bmp280-i2c.c6
-rw-r--r--drivers/iio/pressure/bmp280-regmap.c10
-rw-r--r--drivers/iio/pressure/bmp280-spi.c6
-rw-r--r--drivers/iio/pressure/bmp280.h56
-rw-r--r--drivers/iio/pressure/hid-sensor-press.c10
-rw-r--r--drivers/iio/pressure/hsc030pa.c2
-rw-r--r--drivers/iio/pressure/hsc030pa_i2c.c2
-rw-r--r--drivers/iio/pressure/hsc030pa_spi.c2
-rw-r--r--drivers/iio/pressure/mpl115.c2
-rw-r--r--drivers/iio/pressure/mpl115_i2c.c2
-rw-r--r--drivers/iio/pressure/mpl115_spi.c2
-rw-r--r--drivers/iio/pressure/mprls0025pa.c2
-rw-r--r--drivers/iio/pressure/mprls0025pa_i2c.c2
-rw-r--r--drivers/iio/pressure/mprls0025pa_spi.c2
-rw-r--r--drivers/iio/pressure/ms5611_core.c2
-rw-r--r--drivers/iio/pressure/ms5611_i2c.c2
-rw-r--r--drivers/iio/pressure/ms5611_spi.c2
-rw-r--r--drivers/iio/pressure/ms5637.c2
-rw-r--r--drivers/iio/pressure/rohm-bm1390.c3
-rw-r--r--drivers/iio/pressure/st_pressure_core.c6
-rw-r--r--drivers/iio/pressure/st_pressure_i2c.c2
-rw-r--r--drivers/iio/pressure/st_pressure_spi.c2
-rw-r--r--drivers/iio/pressure/zpa2326.c12
-rw-r--r--drivers/iio/pressure/zpa2326_i2c.c2
-rw-r--r--drivers/iio/pressure/zpa2326_spi.c2
-rw-r--r--drivers/iio/proximity/aw96103.c2
-rw-r--r--drivers/iio/proximity/cros_ec_mkbp_proximity.c4
-rw-r--r--drivers/iio/proximity/hx9023s.c4
-rw-r--r--drivers/iio/proximity/irsd200.c5
-rw-r--r--drivers/iio/proximity/srf04.c2
-rw-r--r--drivers/iio/proximity/sx9310.c2
-rw-r--r--drivers/iio/proximity/sx9324.c22
-rw-r--r--drivers/iio/proximity/sx9360.c3
-rw-r--r--drivers/iio/proximity/sx9500.c6
-rw-r--r--drivers/iio/proximity/sx_common.c33
-rw-r--r--drivers/iio/proximity/sx_common.h6
-rw-r--r--drivers/iio/proximity/vcnl3020.c2
-rw-r--r--drivers/iio/proximity/vl53l0x-i2c.c174
-rw-r--r--drivers/iio/temperature/Kconfig2
-rw-r--r--drivers/iio/temperature/hid-sensor-temperature.c6
-rw-r--r--drivers/iio/temperature/mcp9600.c2
-rw-r--r--drivers/iio/temperature/tmp006.c134
-rw-r--r--drivers/iio/temperature/tmp007.c2
-rw-r--r--drivers/iio/temperature/tsys01.c2
-rw-r--r--drivers/iio/temperature/tsys02d.c2
-rw-r--r--drivers/iio/test/iio-test-gts.c2
-rw-r--r--drivers/iio/test/iio-test-rescale.c2
-rw-r--r--drivers/iio/trigger/iio-trig-interrupt.c2
-rw-r--r--drivers/iio/trigger/stm32-timer-trigger.c2
-rw-r--r--drivers/infiniband/core/cma.c16
-rw-r--r--drivers/infiniband/core/nldev.c2
-rw-r--r--drivers/infiniband/core/umem_dmabuf.c2
-rw-r--r--drivers/infiniband/core/uverbs_cmd.c16
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.c50
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.h4
-rw-r--r--drivers/infiniband/hw/bnxt_re/main.c8
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_fp.c79
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_fp.h4
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_rcfw.c5
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.h5
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_sp.c18
-rw-r--r--drivers/infiniband/hw/bnxt_re/roce_hsi.h1
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hem.c43
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_hw_v2.c11
-rw-r--r--drivers/infiniband/hw/hns/hns_roce_mr.c5
-rw-r--r--drivers/infiniband/hw/mana/device.c2
-rw-r--r--drivers/infiniband/hw/mlx5/fs.c37
-rw-r--r--drivers/infiniband/hw/mlx5/main.c8
-rw-r--r--drivers/infiniband/hw/qib/qib_sysfs.c2
-rw-r--r--drivers/infiniband/sw/rxe/rxe.c23
-rw-r--r--drivers/infiniband/sw/rxe/rxe.h3
-rw-r--r--drivers/infiniband/sw/rxe/rxe_mcast.c22
-rw-r--r--drivers/infiniband/sw/rxe/rxe_net.c24
-rw-r--r--drivers/infiniband/sw/rxe/rxe_verbs.c26
-rw-r--r--drivers/infiniband/sw/rxe/rxe_verbs.h11
-rw-r--r--drivers/infiniband/sw/siw/siw.h7
-rw-r--r--drivers/infiniband/sw/siw/siw_cm.c27
-rw-r--r--drivers/infiniband/sw/siw/siw_main.c15
-rw-r--r--drivers/infiniband/sw/siw/siw_verbs.c35
-rw-r--r--drivers/infiniband/ulp/rtrs/rtrs-srv.c2
-rw-r--r--drivers/interconnect/core.c4
-rw-r--r--drivers/interconnect/imx/imx8mm.c2
-rw-r--r--drivers/interconnect/imx/imx8mn.c2
-rw-r--r--drivers/interconnect/imx/imx8mp.c2
-rw-r--r--drivers/interconnect/imx/imx8mq.c2
-rw-r--r--drivers/interconnect/mediatek/mt8183.c2
-rw-r--r--drivers/interconnect/mediatek/mt8195.c2
-rw-r--r--drivers/interconnect/qcom/Kconfig29
-rw-r--r--drivers/interconnect/qcom/Makefile6
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.c5
-rw-r--r--drivers/interconnect/qcom/icc-rpmh.h2
-rw-r--r--drivers/interconnect/qcom/msm8909.c2
-rw-r--r--drivers/interconnect/qcom/msm8916.c2
-rw-r--r--drivers/interconnect/qcom/msm8937.c10
-rw-r--r--drivers/interconnect/qcom/msm8939.c2
-rw-r--r--drivers/interconnect/qcom/msm8953.c2
-rw-r--r--drivers/interconnect/qcom/msm8974.c2
-rw-r--r--drivers/interconnect/qcom/msm8976.c2
-rw-r--r--drivers/interconnect/qcom/msm8996.c2
-rw-r--r--drivers/interconnect/qcom/osm-l3.c2
-rw-r--r--drivers/interconnect/qcom/qcm2290.c2
-rw-r--r--drivers/interconnect/qcom/qcs404.c2
-rw-r--r--drivers/interconnect/qcom/qcs615.c1563
-rw-r--r--drivers/interconnect/qcom/qcs615.h128
-rw-r--r--drivers/interconnect/qcom/qcs8300.c2088
-rw-r--r--drivers/interconnect/qcom/qcs8300.h177
-rw-r--r--drivers/interconnect/qcom/qdu1000.c2
-rw-r--r--drivers/interconnect/qcom/sa8775p.c2
-rw-r--r--drivers/interconnect/qcom/sar2130p.c1930
-rw-r--r--drivers/interconnect/qcom/sc7180.c2
-rw-r--r--drivers/interconnect/qcom/sc7280.c6
-rw-r--r--drivers/interconnect/qcom/sc8180x.c2
-rw-r--r--drivers/interconnect/qcom/sc8280xp.c2
-rw-r--r--drivers/interconnect/qcom/sdm660.c2
-rw-r--r--drivers/interconnect/qcom/sdm670.c2
-rw-r--r--drivers/interconnect/qcom/sdm845.c2
-rw-r--r--drivers/interconnect/qcom/sdx55.c2
-rw-r--r--drivers/interconnect/qcom/sdx65.c2
-rw-r--r--drivers/interconnect/qcom/sdx75.c2
-rw-r--r--drivers/interconnect/qcom/sm6115.c2
-rw-r--r--drivers/interconnect/qcom/sm6350.c2
-rw-r--r--drivers/interconnect/qcom/sm7150.c2
-rw-r--r--drivers/interconnect/qcom/sm8150.c2
-rw-r--r--drivers/interconnect/qcom/sm8250.c2
-rw-r--r--drivers/interconnect/qcom/sm8350.c2
-rw-r--r--drivers/interconnect/qcom/sm8450.c2
-rw-r--r--drivers/interconnect/qcom/sm8550.c2
-rw-r--r--drivers/interconnect/qcom/sm8650.c2
-rw-r--r--drivers/interconnect/qcom/smd-rpm.c2
-rw-r--r--drivers/interconnect/qcom/x1e80100.c2
-rw-r--r--drivers/interconnect/samsung/exynos.c2
-rw-r--r--drivers/iommu/amd/iommu.c10
-rw-r--r--drivers/iommu/apple-dart.c2
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c2
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c2
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c2
-rw-r--r--drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c2
-rw-r--r--drivers/iommu/arm/arm-smmu/arm-smmu.c2
-rw-r--r--drivers/iommu/arm/arm-smmu/qcom_iommu.c4
-rw-r--r--drivers/iommu/intel/cache.c34
-rw-r--r--drivers/iommu/intel/iommu.c4
-rw-r--r--drivers/iommu/intel/pasid.c3
-rw-r--r--drivers/iommu/iommu.c10
-rw-r--r--drivers/iommu/iommufd/device.c32
-rw-r--r--drivers/iommu/iommufd/driver.c4
-rw-r--r--drivers/iommu/iommufd/fault.c2
-rw-r--r--drivers/iommu/iommufd/iova_bitmap.c8
-rw-r--r--drivers/iommu/iommufd/main.c12
-rw-r--r--drivers/iommu/iommufd/vfio_compat.c6
-rw-r--r--drivers/iommu/ipmmu-vmsa.c2
-rw-r--r--drivers/iommu/msm_iommu.c2
-rw-r--r--drivers/iommu/mtk_iommu.c2
-rw-r--r--drivers/iommu/mtk_iommu_v1.c2
-rw-r--r--drivers/iommu/omap-iommu.c2
-rw-r--r--drivers/iommu/riscv/iommu-platform.c2
-rw-r--r--drivers/iommu/sprd-iommu.c2
-rw-r--r--drivers/irqchip/Kconfig2
-rw-r--r--drivers/irqchip/irq-bcm2836.c3
-rw-r--r--drivers/irqchip/irq-gic-v3-its.c50
-rw-r--r--drivers/irqchip/irq-gic-v3.c19
-rw-r--r--drivers/irqchip/irq-gic.c4
-rw-r--r--drivers/irqchip/irq-imgpdc.c2
-rw-r--r--drivers/irqchip/irq-imx-intmux.c2
-rw-r--r--drivers/irqchip/irq-imx-irqsteer.c2
-rw-r--r--drivers/irqchip/irq-keystone.c2
-rw-r--r--drivers/irqchip/irq-ls-scfg-msi.c2
-rw-r--r--drivers/irqchip/irq-madera.c2
-rw-r--r--drivers/irqchip/irq-mvebu-pic.c4
-rw-r--r--drivers/irqchip/irq-mvebu-sei.c2
-rw-r--r--drivers/irqchip/irq-pruss-intc.c2
-rw-r--r--drivers/irqchip/irq-renesas-intc-irqpin.c2
-rw-r--r--drivers/irqchip/irq-renesas-irqc.c2
-rw-r--r--drivers/irqchip/irq-renesas-rza1.c2
-rw-r--r--drivers/irqchip/irq-ts4800.c2
-rw-r--r--drivers/irqchip/irq-versatile-fpga.c2
-rw-r--r--drivers/isdn/mISDN/core.c14
-rw-r--r--drivers/isdn/mISDN/core.h1
-rw-r--r--drivers/leds/flash/leds-ktd2692.c2
-rw-r--r--drivers/leds/leds-expresswire.c12
-rw-r--r--drivers/macintosh/Kconfig1
-rw-r--r--drivers/macintosh/therm_windtunnel.c2
-rw-r--r--drivers/macintosh/windfarm_pm112.c2
-rw-r--r--drivers/macintosh/windfarm_pm121.c2
-rw-r--r--drivers/macintosh/windfarm_pm72.c2
-rw-r--r--drivers/macintosh/windfarm_pm81.c2
-rw-r--r--drivers/macintosh/windfarm_pm91.c2
-rw-r--r--drivers/macintosh/windfarm_rm31.c2
-rw-r--r--drivers/mailbox/omap-mailbox.c1
-rw-r--r--drivers/mcb/mcb-core.c28
-rw-r--r--drivers/mcb/mcb-lpc.c4
-rw-r--r--drivers/mcb/mcb-parse.c2
-rw-r--r--drivers/mcb/mcb-pci.c2
-rw-r--r--drivers/md/bcache/super.c2
-rw-r--r--drivers/md/dm-ebs-target.c2
-rw-r--r--drivers/md/dm-thin.c5
-rw-r--r--drivers/md/dm-verity-fec.c59
-rw-r--r--drivers/md/dm-zoned-reclaim.c6
-rw-r--r--drivers/md/persistent-data/dm-array.c19
-rw-r--r--drivers/md/raid0.c1
-rw-r--r--drivers/md/raid1.c20
-rw-r--r--drivers/md/raid10.c20
-rw-r--r--drivers/media/common/videobuf2/videobuf2-core.c2
-rw-r--r--drivers/media/common/videobuf2/videobuf2-dma-contig.c2
-rw-r--r--drivers/media/common/videobuf2/videobuf2-dma-sg.c2
-rw-r--r--drivers/media/common/videobuf2/videobuf2-vmalloc.c2
-rw-r--r--drivers/media/dvb-frontends/dib3000mb.c2
-rw-r--r--drivers/media/i2c/ds90ub913.c2
-rw-r--r--drivers/media/i2c/ds90ub953.c2
-rw-r--r--drivers/media/i2c/ds90ub960.c2
-rw-r--r--drivers/media/pci/intel/ipu-bridge.c6
-rw-r--r--drivers/media/pci/intel/ipu3/ipu3-cio2.c2
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-buttress.c12
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-cpd.c4
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-dma.c18
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-fw-com.c18
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-isys.c4
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6-mmu.c4
-rw-r--r--drivers/media/pci/intel/ipu6/ipu6.c4
-rw-r--r--drivers/media/pci/intel/ivsc/mei_csi.c2
-rw-r--r--drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c3
-rw-r--r--drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c2
-rw-r--r--drivers/memory/brcmstb_dpfe.c2
-rw-r--r--drivers/memory/brcmstb_memc.c2
-rw-r--r--drivers/memory/emif.c2
-rw-r--r--drivers/memory/fsl-corenet-cf.c2
-rw-r--r--drivers/memory/fsl_ifc.c2
-rw-r--r--drivers/memory/jz4780-nemc.c2
-rw-r--r--drivers/memory/mtk-smi.c4
-rw-r--r--drivers/memory/omap-gpmc.c2
-rw-r--r--drivers/memory/renesas-rpc-if.c2
-rw-r--r--drivers/memory/samsung/exynos5422-dmc.c2
-rw-r--r--drivers/memory/stm32-fmc2-ebi.c2
-rw-r--r--drivers/memory/tegra/tegra186-emc.c2
-rw-r--r--drivers/memory/tegra/tegra210-emc-core.c2
-rw-r--r--drivers/memory/ti-emif-pm.c2
-rw-r--r--drivers/memstick/host/rtsx_usb_ms.c2
-rw-r--r--drivers/message/fusion/mptfc.c2
-rw-r--r--drivers/message/fusion/mptsas.c2
-rw-r--r--drivers/message/fusion/mptspi.c2
-rw-r--r--drivers/mfd/cs40l50-core.c2
-rw-r--r--drivers/mfd/cs42l43-i2c.c2
-rw-r--r--drivers/mfd/cs42l43-sdw.c2
-rw-r--r--drivers/mfd/cs42l43.c12
-rw-r--r--drivers/mfd/intel-lpss-acpi.c2
-rw-r--r--drivers/mfd/intel-lpss-pci.c2
-rw-r--r--drivers/mfd/intel-lpss.c4
-rw-r--r--drivers/mfd/intel-m10-bmc-core.c10
-rw-r--r--drivers/mfd/intel-m10-bmc-pmci.c2
-rw-r--r--drivers/mfd/intel-m10-bmc-spi.c2
-rw-r--r--drivers/mfd/ocelot-core.c6
-rw-r--r--drivers/mfd/ocelot-spi.c4
-rw-r--r--drivers/misc/Kconfig1
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/apds990x.c12
-rw-r--r--drivers/misc/atmel-ssc.c6
-rw-r--r--drivers/misc/cardreader/alcor_pci.c2
-rw-r--r--drivers/misc/cardreader/rtsx_usb.c6
-rw-r--r--drivers/misc/cxl/of.c2
-rw-r--r--drivers/misc/eeprom/Kconfig4
-rw-r--r--drivers/misc/eeprom/eeprom_93cx6.c15
-rw-r--r--drivers/misc/eeprom/eeprom_93xx46.c2
-rw-r--r--drivers/misc/fastrpc.c4
-rw-r--r--drivers/misc/hisi_hikey_usb.c2
-rw-r--r--drivers/misc/isl29020.c2
-rw-r--r--drivers/misc/keba/Kconfig13
-rw-r--r--drivers/misc/keba/Makefile1
-rw-r--r--drivers/misc/keba/cp500.c558
-rw-r--r--drivers/misc/keba/lan9252.c359
-rw-r--r--drivers/misc/mei/bus.c2
-rw-r--r--drivers/misc/mei/platform-vsc.c6
-rw-r--r--drivers/misc/mei/vsc-fw-loader.c28
-rw-r--r--drivers/misc/mei/vsc-tp.c20
-rw-r--r--drivers/misc/ocxl/sysfs.c2
-rw-r--r--drivers/misc/open-dice.c2
-rw-r--r--drivers/misc/rpmb-core.c9
-rw-r--r--drivers/misc/sram.c2
-rw-r--r--drivers/misc/ti-st/Kconfig19
-rw-r--r--drivers/misc/ti-st/Makefile7
-rw-r--r--drivers/misc/ti-st/st_core.c918
-rw-r--r--drivers/misc/ti-st/st_kim.c839
-rw-r--r--drivers/misc/ti-st/st_ll.c156
-rw-r--r--drivers/misc/tps6594-esm.c2
-rw-r--r--drivers/misc/tps6594-pfsm.c2
-rw-r--r--drivers/misc/vcpu_stall_detector.c2
-rw-r--r--drivers/misc/xilinx_sdfec.c2
-rw-r--r--drivers/misc/xilinx_tmr_inject.c2
-rw-r--r--drivers/mmc/core/bus.c2
-rw-r--r--drivers/mmc/core/core.c3
-rw-r--r--drivers/mmc/host/mtk-sd.c2
-rw-r--r--drivers/mmc/host/sdhci-msm.c16
-rw-r--r--drivers/mmc/host/sdhci-pci-core.c72
-rw-r--r--drivers/mmc/host/sdhci-pci.h1
-rw-r--r--drivers/mmc/host/sdhci-tegra.c1
-rw-r--r--drivers/mtd/nand/raw/arasan-nand-controller.c11
-rw-r--r--drivers/mtd/nand/raw/atmel/pmecc.c4
-rw-r--r--drivers/mtd/nand/raw/diskonchip.c2
-rw-r--r--drivers/mtd/nand/raw/omap2.c16
-rw-r--r--drivers/mtd/spi-nor/sysfs.c2
-rw-r--r--drivers/mtd/ubi/attach.c12
-rw-r--r--drivers/mtd/ubi/fastmap-wl.c19
-rw-r--r--drivers/mtd/ubi/nvmem.c2
-rw-r--r--drivers/mtd/ubi/ubi.h3
-rw-r--r--drivers/mtd/ubi/vmt.c2
-rw-r--r--drivers/mtd/ubi/wl.c32
-rw-r--r--drivers/mtd/ubi/wl.h3
-rw-r--r--drivers/net/bareudp.c16
-rw-r--r--drivers/net/bonding/bond_main.c10
-rw-r--r--drivers/net/can/c_can/c_can_main.c26
-rw-r--r--drivers/net/can/dev/dev.c2
-rw-r--r--drivers/net/can/ifi_canfd/ifi_canfd.c58
-rw-r--r--drivers/net/can/m_can/m_can.c69
-rw-r--r--drivers/net/can/m_can/m_can.h1
-rw-r--r--drivers/net/can/m_can/m_can_pci.c1
-rw-r--r--drivers/net/can/sja1000/sja1000.c67
-rw-r--r--drivers/net/can/sja1000/sja1000_platform.c15
-rw-r--r--drivers/net/can/spi/hi311x.c55
-rw-r--r--drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c29
-rw-r--r--drivers/net/can/sun4i_can.c22
-rw-r--r--drivers/net/can/usb/ems_usb.c58
-rw-r--r--drivers/net/can/usb/f81604.c10
-rw-r--r--drivers/net/can/usb/gs_usb.c25
-rw-r--r--drivers/net/can/vxcan.c10
-rw-r--r--drivers/net/dsa/b53/b53_common.c14
-rw-r--r--drivers/net/dsa/b53/b53_priv.h2
-rw-r--r--drivers/net/dsa/bcm_sf2.c2
-rw-r--r--drivers/net/dsa/microchip/ksz9477.c47
-rw-r--r--drivers/net/dsa/microchip/ksz9477_i2c.c4
-rw-r--r--drivers/net/dsa/microchip/ksz9477_reg.h4
-rw-r--r--drivers/net/dsa/microchip/ksz_common.c160
-rw-r--r--drivers/net/dsa/microchip/ksz_common.h3
-rw-r--r--drivers/net/dsa/microchip/ksz_spi.c4
-rw-r--r--drivers/net/dsa/microchip/lan937x_main.c62
-rw-r--r--drivers/net/dsa/microchip/lan937x_reg.h9
-rw-r--r--drivers/net/dsa/mt7530.c14
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.c58
-rw-r--r--drivers/net/dsa/mv88e6xxx/chip.h1
-rw-r--r--drivers/net/dsa/ocelot/felix_vsc9959.c17
-rw-r--r--drivers/net/dsa/ocelot/ocelot_ext.c2
-rw-r--r--drivers/net/dsa/qca/qca8k-8xxx.c8
-rw-r--r--drivers/net/dsa/qca/qca8k-common.c7
-rw-r--r--drivers/net/dsa/qca/qca8k.h3
-rw-r--r--drivers/net/dsa/realtek/realtek-mdio.c6
-rw-r--r--drivers/net/dsa/realtek/realtek-smi.c6
-rw-r--r--drivers/net/dsa/realtek/rtl8365mb.c2
-rw-r--r--drivers/net/dsa/realtek/rtl8366-core.c22
-rw-r--r--drivers/net/dsa/realtek/rtl8366rb.c2
-rw-r--r--drivers/net/dsa/realtek/rtl83xx.c16
-rw-r--r--drivers/net/dsa/sja1105/sja1105_static_config.c8
-rw-r--r--drivers/net/ethernet/Kconfig2
-rw-r--r--drivers/net/ethernet/amazon/ena/ena_netdev.c2
-rw-r--r--drivers/net/ethernet/amd/pds_core/devlink.c2
-rw-r--r--drivers/net/ethernet/apm/xgene/xgene_enet_hw.c16
-rw-r--r--drivers/net/ethernet/broadcom/bcmsysport.c21
-rw-r--r--drivers/net/ethernet/broadcom/bgmac-platform.c5
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.c332
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt.h22
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c52
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c5
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h2
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c14
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4.h2
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c7
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/t4_hw.c5
-rw-r--r--drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c5
-rw-r--r--drivers/net/ethernet/cisco/enic/enic_main.c64
-rw-r--r--drivers/net/ethernet/freescale/Kconfig3
-rw-r--r--drivers/net/ethernet/freescale/dpaa/dpaa_eth.c2
-rw-r--r--drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c3
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.c340
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc.h29
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc4_hw.h23
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_hw.h37
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf.c19
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_pf_common.c13
-rw-r--r--drivers/net/ethernet/freescale/enetc/enetc_vf.c7
-rw-r--r--drivers/net/ethernet/freescale/fec.h2
-rw-r--r--drivers/net/ethernet/freescale/fec_main.c16
-rw-r--r--drivers/net/ethernet/freescale/fman/fman.c35
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.c604
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth.h22
-rw-r--r--drivers/net/ethernet/freescale/ucc_geth_ethtool.c74
-rw-r--r--drivers/net/ethernet/google/gve/gve.h1
-rw-r--r--drivers/net/ethernet/google/gve/gve_adminq.c14
-rw-r--r--drivers/net/ethernet/google/gve/gve_adminq.h1
-rw-r--r--drivers/net/ethernet/google/gve/gve_main.c77
-rw-r--r--drivers/net/ethernet/google/gve/gve_tx.c46
-rw-r--r--drivers/net/ethernet/google/gve/gve_tx_dqo.c6
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/Makefile3
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h29
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c160
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.h12
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c134
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_err.h13
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c181
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c48
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h6
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c199
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c15
-rw-r--r--drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h39
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c109
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h28
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c67
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c5
-rw-r--r--drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h1
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hnae3.h3
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c96
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3_enet.c1
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c45
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c3
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c9
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c41
-rw-r--r--drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c9
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_main.c2
-rw-r--r--drivers/net/ethernet/huawei/hinic/hinic_port.c2
-rw-r--r--drivers/net/ethernet/intel/Kconfig1
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pf.c120
-rw-r--r--drivers/net/ethernet/intel/fm10k/fm10k_pf.h2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e.h7
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_adminq.c10
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_common.c458
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_dcb.c13
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_dcb.h1
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_debugfs.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_main.c233
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_prototype.h40
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c2
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h11
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_xsk.c30
-rw-r--r--drivers/net/ethernet/intel/iavf/iavf_main.c4
-rw-r--r--drivers/net/ethernet/intel/ice/Makefile3
-rw-r--r--drivers/net/ethernet/intel/ice/devlink/devlink.c2
-rw-r--r--drivers/net/ethernet/intel/ice/devlink/health.c269
-rw-r--r--drivers/net/ethernet/intel/ice/devlink/health.h58
-rw-r--r--drivers/net/ethernet/intel/ice/devlink/port.c (renamed from drivers/net/ethernet/intel/ice/devlink/devlink_port.c)2
-rw-r--r--drivers/net/ethernet/intel/ice/devlink/port.h (renamed from drivers/net/ethernet/intel/ice/devlink/devlink_port.h)0
-rw-r--r--drivers/net/ethernet/intel/ice/ice.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_adminq_cmd.h13
-rw-r--r--drivers/net/ethernet/intel/ice/ice_base.c6
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.c318
-rw-r--r--drivers/net/ethernet/intel/ice/ice_common.h5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_dpll.c35
-rw-r--r--drivers/net/ethernet/intel/ice/ice_eswitch.h2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h49
-rw-r--r--drivers/net/ethernet/intel/ice/ice_main.c36
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_consts.h4
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_hw.c3
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ptp_hw.h5
-rw-r--r--drivers/net/ethernet/intel/ice/ice_repr.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_sf_eth.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_virtchnl.c6
-rw-r--r--drivers/net/ethernet/intel/ice/ice_xsk.c32
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_dev.c3
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_main.c2
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_txrx.c30
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_txrx.h8
-rw-r--r--drivers/net/ethernet/intel/idpf/idpf_vf_dev.c3
-rw-r--r--drivers/net/ethernet/intel/igb/Makefile2
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h58
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c274
-rw-r--r--drivers/net/ethernet/intel/igb/igb_xsk.c562
-rw-r--r--drivers/net/ethernet/intel/igc/igc.h2
-rw-r--r--drivers/net/ethernet/intel/igc/igc_base.c6
-rw-r--r--drivers/net/ethernet/intel/igc/igc_hw.h5
-rw-r--r--drivers/net/ethernet/intel/igc/igc_main.c118
-rw-r--r--drivers/net/ethernet/intel/igc/igc_nvm.c50
-rw-r--r--drivers/net/ethernet/intel/igc/igc_nvm.h2
-rw-r--r--drivers/net/ethernet/intel/igc/igc_xdp.c8
-rw-r--r--drivers/net/ethernet/intel/ixgbe/Makefile4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe.h13
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.c25
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_common.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c2658
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h81
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c6
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c3
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c459
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c4
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c5
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h72
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h1074
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c12
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h7
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c29
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x550.h20
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/defines.h5
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ipsec.c1
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf.h7
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c35
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/mbx.c12
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.c12
-rw-r--r--drivers/net/ethernet/intel/ixgbevf/vf.h4
-rw-r--r--drivers/net/ethernet/intel/libeth/rx.c8
-rw-r--r--drivers/net/ethernet/intel/libie/rx.c4
-rw-r--r--drivers/net/ethernet/lantiq_etop.c25
-rw-r--r--drivers/net/ethernet/marvell/mv643xx_eth.c14
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_main.c39
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_main.h1
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c23
-rw-r--r--drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h6
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/common.h1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/mbox.h4
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c71
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c18
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/Makefile1
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c1056
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h265
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c4
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c114
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h28
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c19
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c66
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h3
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c10
-rw-r--r--drivers/net/ethernet/marvell/octeontx2/nic/rep.c5
-rw-r--r--drivers/net/ethernet/marvell/sky2.c1
-rw-r--r--drivers/net/ethernet/mediatek/airoha_eth.c551
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/Makefile3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/cmd.c1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c13
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_main.c52
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_rep.c15
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c20
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch.h3
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c5
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_core.c12
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c293
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_pool.c194
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/fs_pool.h54
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c13
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c365
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h17
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c77
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c16
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c55
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c24
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/main.c8
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/rl.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c159
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.h9
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.c54
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h18
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c95
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h13
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.c35
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.h10
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.c36
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c36
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/prm.h42
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c23
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.h6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c22
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_domain.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h19
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v0.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c207
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h147
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c169
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.h168
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c221
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr.h40
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5dr.h2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/core.h1
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/pci.c4
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c2
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c10
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c2
-rw-r--r--drivers/net/ethernet/meta/fbnic/Makefile1
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic.h20
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_csr.c2
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c543
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_fw.h7
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c81
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_irq.c53
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_mac.c22
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_mac.h7
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_netdev.c12
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_netdev.h7
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_pci.c5
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_rpc.c7
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_txrx.c238
-rw-r--r--drivers/net/ethernet/meta/fbnic/fbnic_txrx.h16
-rw-r--r--drivers/net/ethernet/microchip/Kconfig1
-rw-r--r--drivers/net/ethernet/microchip/Makefile1
-rw-r--r--drivers/net/ethernet/microchip/lan969x/Kconfig5
-rw-r--r--drivers/net/ethernet/microchip/lan969x/Makefile13
-rw-r--r--drivers/net/ethernet/microchip/sparx5/Kconfig6
-rw-r--r--drivers/net/ethernet/microchip/sparx5/Makefile7
-rw-r--r--drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c (renamed from drivers/net/ethernet/microchip/lan969x/lan969x.c)14
-rw-r--r--drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.h (renamed from drivers/net/ethernet/microchip/lan969x/lan969x.h)10
-rw-r--r--drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_calendar.c (renamed from drivers/net/ethernet/microchip/lan969x/lan969x_calendar.c)0
-rw-r--r--drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_regs.c (renamed from drivers/net/ethernet/microchip/lan969x/lan969x_regs.c)0
-rw-r--r--drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_rgmii.c224
-rw-r--r--drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_vcap_ag_api.c (renamed from drivers/net/ethernet/microchip/lan969x/lan969x_vcap_ag_api.c)0
-rw-r--r--drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_vcap_impl.c (renamed from drivers/net/ethernet/microchip/lan969x/lan969x_vcap_impl.c)0
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c2
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_main.c44
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_main.h3
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h145
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_mirror.c3
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c14
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_port.c59
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_port.h5
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c1
-rw-r--r--drivers/net/ethernet/microsoft/mana/gdma_main.c18
-rw-r--r--drivers/net/ethernet/microsoft/mana/mana_en.c11
-rw-r--r--drivers/net/ethernet/mscc/ocelot.c2
-rw-r--r--drivers/net/ethernet/mscc/ocelot_net.c3
-rw-r--r--drivers/net/ethernet/mscc/ocelot_ptp.c209
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c2
-rw-r--r--drivers/net/ethernet/oa_tc6.c11
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic.h3
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_dev.c5
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_ethtool.c44
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_if.h22
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_lif.c13
-rw-r--r--drivers/net/ethernet/pensando/ionic/ionic_main.c3
-rw-r--r--drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c20
-rw-r--r--drivers/net/ethernet/qlogic/qed/qed_mcp.c5
-rw-r--r--drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c69
-rw-r--r--drivers/net/ethernet/qualcomm/qca_spi.c26
-rw-r--r--drivers/net/ethernet/qualcomm/qca_spi.h1
-rw-r--r--drivers/net/ethernet/realtek/r8169.h2
-rw-r--r--drivers/net/ethernet/realtek/r8169_main.c98
-rw-r--r--drivers/net/ethernet/realtek/r8169_phy_config.c28
-rw-r--r--drivers/net/ethernet/realtek/rtase/rtase_main.c14
-rw-r--r--drivers/net/ethernet/renesas/rswitch.c274
-rw-r--r--drivers/net/ethernet/renesas/rswitch.h75
-rw-r--r--drivers/net/ethernet/sfc/io.h24
-rw-r--r--drivers/net/ethernet/sfc/net_driver.h2
-rw-r--r--drivers/net/ethernet/sfc/rx_common.c5
-rw-r--r--drivers/net/ethernet/sfc/siena/net_driver.h2
-rw-r--r--drivers/net/ethernet/sfc/siena/rx_common.c5
-rw-r--r--drivers/net/ethernet/sfc/tc_conntrack.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Kconfig12
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/Makefile1
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/common.h16
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c11
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c27
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c22
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c30
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c202
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c19
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c18
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c14
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h5
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/hwif.h17
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/mmc.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac.h10
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_est.h2
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c39
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_main.c89
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c45
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h3
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c11
-rw-r--r--drivers/net/ethernet/sun/niu.c22
-rw-r--r--drivers/net/ethernet/ti/am65-cpsw-nuss.c2
-rw-r--r--drivers/net/ethernet/ti/cpsw.c3
-rw-r--r--drivers/net/ethernet/ti/cpsw_ethtool.c12
-rw-r--r--drivers/net/ethernet/ti/cpsw_new.c3
-rw-r--r--drivers/net/ethernet/ti/cpsw_priv.h1
-rw-r--r--drivers/net/ethernet/ti/icssg/icss_iep.c8
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_common.c25
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_config.c41
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_config.h1
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_prueth.c261
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_prueth.h5
-rw-r--r--drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c24
-rw-r--r--drivers/net/ethernet/wangxun/libwx/wx_hw.c24
-rw-r--r--drivers/net/geneve.c14
-rw-r--r--drivers/net/ieee802154/ca8210.c6
-rw-r--r--drivers/net/mctp/mctp-i3c.c4
-rw-r--r--drivers/net/mdio/fwnode_mdio.c13
-rw-r--r--drivers/net/mdio/mdio-octeon.c25
-rw-r--r--drivers/net/netconsole.c2
-rw-r--r--drivers/net/netdevsim/health.c2
-rw-r--r--drivers/net/netdevsim/netdev.c263
-rw-r--r--drivers/net/netdevsim/netdevsim.h5
-rw-r--r--drivers/net/netkit.c77
-rw-r--r--drivers/net/pcs/pcs-lynx.c35
-rw-r--r--drivers/net/pcs/pcs-mtk-lynxi.c21
-rw-r--r--drivers/net/pcs/pcs-xpcs.c33
-rw-r--r--drivers/net/phy/Kconfig9
-rw-r--r--drivers/net/phy/Makefile1
-rw-r--r--drivers/net/phy/aquantia/aquantia_leds.c2
-rw-r--r--drivers/net/phy/dp83822.c106
-rw-r--r--drivers/net/phy/intel-xway.c2
-rw-r--r--drivers/net/phy/marvell.c4
-rw-r--r--drivers/net/phy/micrel.c116
-rw-r--r--drivers/net/phy/microchip.c21
-rw-r--r--drivers/net/phy/microchip_rds_ptp.c1039
-rw-r--r--drivers/net/phy/microchip_rds_ptp.h223
-rw-r--r--drivers/net/phy/microchip_t1.c41
-rw-r--r--drivers/net/phy/mxl-gpy.c2
-rw-r--r--drivers/net/phy/phy-c45.c14
-rw-r--r--drivers/net/phy/phy.c9
-rw-r--r--drivers/net/phy/phy_device.c27
-rw-r--r--drivers/net/phy/phylink.c18
-rw-r--r--drivers/net/phy/spi_ks8995.c8
-rw-r--r--drivers/net/pse-pd/tps23881.c16
-rw-r--r--drivers/net/tap.c6
-rw-r--r--drivers/net/team/team_core.c24
-rw-r--r--drivers/net/tun.c22
-rw-r--r--drivers/net/usb/lan78xx.c938
-rw-r--r--drivers/net/usb/qmi_wwan.c4
-rw-r--r--drivers/net/veth.c16
-rw-r--r--drivers/net/virtio_net.c31
-rw-r--r--drivers/net/vrf.c49
-rw-r--r--drivers/net/vxlan/vxlan_core.c187
-rw-r--r--drivers/net/vxlan/vxlan_mdb.c2
-rw-r--r--drivers/net/wan/framer/framer-core.c23
-rw-r--r--drivers/net/wireless/ath/ath11k/core.c132
-rw-r--r--drivers/net/wireless/ath/ath11k/core.h4
-rw-r--r--drivers/net/wireless/ath/ath11k/dp.h1
-rw-r--r--drivers/net/wireless/ath/ath11k/dp_rx.c14
-rw-r--r--drivers/net/wireless/ath/ath11k/hal.h6
-rw-r--r--drivers/net/wireless/ath/ath11k/hal_rx.c3
-rw-r--r--drivers/net/wireless/ath/ath11k/hw.h1
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c7
-rw-r--r--drivers/net/wireless/ath/ath11k/mhi.c1
-rw-r--r--drivers/net/wireless/ath/ath11k/pci.c3
-rw-r--r--drivers/net/wireless/ath/ath11k/pcic.c13
-rw-r--r--drivers/net/wireless/ath/ath11k/qmi.c8
-rw-r--r--drivers/net/wireless/ath/ath11k/wow.c6
-rw-r--r--drivers/net/wireless/ath/ath12k/core.c482
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h134
-rw-r--r--drivers/net/wireless/ath/ath12k/debug.c6
-rw-r--r--drivers/net/wireless/ath/ath12k/debug.h5
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c681
-rw-r--r--drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h218
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.c70
-rw-r--r--drivers/net/wireless/ath/ath12k/dp.h3
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.c96
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.h6
-rw-r--r--drivers/net/wireless/ath/ath12k/hal_desc.h2
-rw-r--r--drivers/net/wireless/ath/ath12k/hal_rx.c12
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c1959
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.h16
-rw-r--r--drivers/net/wireless/ath/ath12k/pci.c10
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.c223
-rw-r--r--drivers/net/wireless/ath/ath12k/peer.h23
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.c167
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.h20
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.c207
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.h115
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/antenna.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_hw.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_hw.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mci.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/common-spectral.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hif_usb.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/link.c33
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/wow.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c2
-rw-r--r--drivers/net/wireless/ath/wcn36xx/main.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bca/module.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c5
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c8
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c4
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/module.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/module.c2
-rw-r--r--drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c3
-rw-r--r--drivers/net/wireless/intel/iwlwifi/cfg/bz.c1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/dvm/main.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-config.h1
-rw-r--r--drivers/net/wireless/intel/iwlwifi/iwl-drv.h2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/d3.c14
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/ops.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c2
-rw-r--r--drivers/net/wireless/intel/iwlwifi/mvm/vendor-cmd.c6
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/drv.c37
-rw-r--r--drivers/net/wireless/intel/iwlwifi/tests/devinfo.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/cfg80211.c2
-rw-r--r--drivers/net/wireless/marvell/mwifiex/sta_ioctl.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mac80211.c2
-rw-r--r--drivers/net/wireless/mediatek/mt76/mt76.h2
-rw-r--r--drivers/net/wireless/microchip/wilc1000/cfg80211.c2
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/cfg80211.c2
-rw-r--r--drivers/net/wireless/quantenna/qtnfmac/core.h2
-rw-r--r--drivers/net/wireless/realtek/rtl8xxxu/core.c20
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.c13
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/base.h1
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/pci.c61
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c7
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c4
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/usb.c12
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/wifi.h12
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8812au.c68
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8821au.c52
-rw-r--r--drivers/net/wireless/realtek/rtw88/rtw8822bu.c6
-rw-r--r--drivers/net/wireless/realtek/rtw88/usb.c72
-rw-r--r--drivers/net/wireless/realtek/rtw89/acpi.c47
-rw-r--r--drivers/net/wireless/realtek/rtw89/acpi.h9
-rw-r--r--drivers/net/wireless/realtek/rtw89/cam.c32
-rw-r--r--drivers/net/wireless/realtek/rtw89/cam.h5
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.c164
-rw-r--r--drivers/net/wireless/realtek/rtw89/core.h145
-rw-r--r--drivers/net/wireless/realtek/rtw89/debug.c4
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.c266
-rw-r--r--drivers/net/wireless/realtek/rtw89/fw.h69
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.c79
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac.h43
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac80211.c289
-rw-r--r--drivers/net/wireless/realtek/rtw89/mac_be.c15
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.c16
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci.h9
-rw-r--r--drivers/net/wireless/realtek/rtw89/pci_be.c1
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.c313
-rw-r--r--drivers/net/wireless/realtek/rtw89/phy.h33
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.c42
-rw-r--r--drivers/net/wireless/realtek/rtw89/ps.h4
-rw-r--r--drivers/net/wireless/realtek/rtw89/reg.h4
-rw-r--r--drivers/net/wireless/realtek/rtw89/regd.c57
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b.c6
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c2
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852a.c7
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b.c3
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852b_common.c50
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852bt.c3
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c.c54
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c6
-rw-r--r--drivers/net/wireless/realtek/rtw89/rtw8922a.c21
-rw-r--r--drivers/net/wireless/realtek/rtw89/sar.c57
-rw-r--r--drivers/net/wireless/realtek/rtw89/ser.c1
-rw-r--r--drivers/net/wireless/realtek/rtw89/txrx.h3
-rw-r--r--drivers/net/wireless/realtek/rtw89/wow.c11
-rw-r--r--drivers/net/wireless/st/cw1200/cw1200_spi.c2
-rw-r--r--drivers/net/wireless/ti/wlcore/sysfs.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/testmode.c2
-rw-r--r--drivers/net/wireless/virtual/mac80211_hwsim.c39
-rw-r--r--drivers/net/wwan/iosm/iosm_ipc_mmio.c2
-rw-r--r--drivers/net/wwan/t7xx/t7xx_pci.c23
-rw-r--r--drivers/net/wwan/t7xx/t7xx_state_monitor.c26
-rw-r--r--drivers/net/wwan/t7xx/t7xx_state_monitor.h5
-rw-r--r--drivers/net/xen-netfront.c5
-rw-r--r--drivers/nfc/st21nfca/dep.c18
-rw-r--r--drivers/nvdimm/e820.c2
-rw-r--r--drivers/nvdimm/of_pmem.c2
-rw-r--r--drivers/nvdimm/region_devs.c2
-rw-r--r--drivers/nvme/host/apple.c2
-rw-r--r--drivers/nvme/host/core.c46
-rw-r--r--drivers/nvme/host/ioctl.c12
-rw-r--r--drivers/nvme/host/multipath.c21
-rw-r--r--drivers/nvme/host/nvme.h15
-rw-r--r--drivers/nvme/host/pci.c163
-rw-r--r--drivers/nvme/host/pr.c122
-rw-r--r--drivers/nvme/host/rdma.c12
-rw-r--r--drivers/nvme/host/tcp.c35
-rw-r--r--drivers/nvme/target/admin-cmd.c25
-rw-r--r--drivers/nvme/target/configfs.c23
-rw-r--r--drivers/nvme/target/core.c108
-rw-r--r--drivers/nvme/target/io-cmd-bdev.c2
-rw-r--r--drivers/nvme/target/nvmet.h7
-rw-r--r--drivers/nvme/target/passthru.c2
-rw-r--r--drivers/nvme/target/pr.c11
-rw-r--r--drivers/nvmem/Kconfig11
-rw-r--r--drivers/nvmem/Makefile2
-rw-r--r--drivers/nvmem/brcm_nvram.c2
-rw-r--r--drivers/nvmem/core.c22
-rw-r--r--drivers/nvmem/imx-iim.c10
-rw-r--r--drivers/nvmem/lpc18xx_eeprom.c2
-rw-r--r--drivers/nvmem/lpc18xx_otp.c2
-rw-r--r--drivers/nvmem/microchip-otpc.c2
-rw-r--r--drivers/nvmem/mtk-efuse.c2
-rw-r--r--drivers/nvmem/rcar-efuse.c142
-rw-r--r--drivers/of/Kconfig6
-rw-r--r--drivers/of/address.c5
-rw-r--r--drivers/of/base.c54
-rw-r--r--drivers/of/dynamic.c44
-rw-r--r--drivers/of/empty_root.dts9
-rw-r--r--drivers/of/irq.c2
-rw-r--r--drivers/of/property.c2
-rw-r--r--drivers/of/unittest-data/tests-address.dtsi2
-rw-r--r--drivers/of/unittest.c45
-rw-r--r--drivers/parisc/led.c2
-rw-r--r--drivers/parport/parport_amiga.c2
-rw-r--r--drivers/parport/parport_sunbpp.c2
-rw-r--r--drivers/pci/msi/irqdomain.c7
-rw-r--r--drivers/pci/msi/msi.c4
-rw-r--r--drivers/pci/p2pdma.c2
-rw-r--r--drivers/pci/pci-sysfs.c42
-rw-r--r--drivers/pci/pci.c6
-rw-r--r--drivers/pci/pcie/aer.c4
-rw-r--r--drivers/pci/pcie/portdrv.c4
-rw-r--r--drivers/pci/remove.c9
-rw-r--r--drivers/pci/vpd.c2
-rw-r--r--drivers/pcmcia/bcm63xx_pcmcia.c2
-rw-r--r--drivers/pcmcia/db1xxx_ss.c2
-rw-r--r--drivers/pcmcia/electra_cf.c2
-rw-r--r--drivers/pcmcia/omap_cf.c2
-rw-r--r--drivers/pcmcia/pxa2xx_base.c2
-rw-r--r--drivers/pcmcia/sa1100_generic.c2
-rw-r--r--drivers/pcmcia/xxs1500_ss.c2
-rw-r--r--drivers/peci/controller/peci-aspeed.c2
-rw-r--r--drivers/peci/controller/peci-npcm.c4
-rw-r--r--drivers/peci/core.c2
-rw-r--r--drivers/peci/cpu.c12
-rw-r--r--drivers/peci/device.c4
-rw-r--r--drivers/peci/request.c30
-rw-r--r--drivers/perf/arm-cmn.c4
-rw-r--r--drivers/perf/arm-ni.c1
-rw-r--r--drivers/perf/arm_smmuv3_pmu.c19
-rw-r--r--drivers/perf/cxl_pmu.c2
-rw-r--r--drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c6
-rw-r--r--drivers/phy/freescale/phy-fsl-samsung-hdmi.c3
-rw-r--r--drivers/phy/mediatek/Kconfig1
-rw-r--r--drivers/phy/phy-core.c21
-rw-r--r--drivers/phy/qualcomm/phy-qcom-qmp-usb.c2
-rw-r--r--drivers/phy/realtek/phy-rtk-usb2.c2
-rw-r--r--drivers/phy/realtek/phy-rtk-usb3.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-naneng-combphy.c2
-rw-r--r--drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c3
-rw-r--r--drivers/phy/st/phy-stm32-combophy.c21
-rw-r--r--drivers/phy/tegra/xusb.c2
-rw-r--r--drivers/pinctrl/bcm/pinctrl-iproc-gpio.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-alderlake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-baytrail.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-broxton.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-cannonlake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-cedarfork.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-cherryview.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-denverton.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-elkhartlake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-emmitsburg.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-geminilake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-icelake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel-platform.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-intel.c22
-rw-r--r--drivers/pinctrl/intel/pinctrl-jasperlake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-lakefield.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-lewisburg.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-lynxpoint.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-merrifield.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-meteorlake.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-meteorpoint.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-moorefield.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-sunrisepoint.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-tangier.c2
-rw-r--r--drivers/pinctrl/intel/pinctrl-tigerlake.c2
-rw-r--r--drivers/pinctrl/mvebu/pinctrl-armada-37xx.c2
-rw-r--r--drivers/pinctrl/pinctrl-mcp23s08.c8
-rw-r--r--drivers/pinctrl/pinctrl-stmfx.c2
-rw-r--r--drivers/pinctrl/pinctrl-sx150x.c2
-rw-r--r--drivers/pinctrl/renesas/pinctrl-rzg2l.c2
-rw-r--r--drivers/platform/chrome/Kconfig11
-rw-r--r--drivers/platform/chrome/Makefile1
-rw-r--r--drivers/platform/chrome/chromeos_of_hw_prober.c154
-rw-r--r--drivers/platform/chrome/cros_ec_lpc.c4
-rw-r--r--drivers/platform/goldfish/goldfish_pipe.c5
-rw-r--r--drivers/platform/loongarch/Kconfig2
-rw-r--r--drivers/platform/mellanox/mlxbf-bootctl.c2
-rw-r--r--drivers/platform/mellanox/mlxbf-tmfifo.c2
-rw-r--r--drivers/platform/mellanox/mlxreg-hotplug.c2
-rw-r--r--drivers/platform/mellanox/mlxreg-io.c2
-rw-r--r--drivers/platform/mellanox/mlxreg-lc.c2
-rw-r--r--drivers/platform/mellanox/nvsw-sn2201.c2
-rw-r--r--drivers/platform/surface/surface3-wmi.c2
-rw-r--r--drivers/platform/surface/surface_acpi_notify.c2
-rw-r--r--drivers/platform/surface/surface_aggregator_cdev.c2
-rw-r--r--drivers/platform/surface/surface_aggregator_registry.c2
-rw-r--r--drivers/platform/surface/surface_dtx.c2
-rw-r--r--drivers/platform/surface/surface_gpe.c2
-rw-r--r--drivers/platform/surface/surface_hotplug.c2
-rw-r--r--drivers/platform/x86/amd/hsmp/acpi.c4
-rw-r--r--drivers/platform/x86/amd/hsmp/hsmp.c16
-rw-r--r--drivers/platform/x86/amd/hsmp/plat.c4
-rw-r--r--drivers/platform/x86/asus-nb-wmi.c1
-rw-r--r--drivers/platform/x86/asus-wmi.c11
-rw-r--r--drivers/platform/x86/dell/alienware-wmi.c24
-rw-r--r--drivers/platform/x86/hp/hp-wmi.c4
-rw-r--r--drivers/platform/x86/ideapad-laptop.c6
-rw-r--r--drivers/platform/x86/intel/ifs/core.c1
-rw-r--r--drivers/platform/x86/intel/plr_tpmi.c4
-rw-r--r--drivers/platform/x86/intel/pmc/core_ssram.c4
-rw-r--r--drivers/platform/x86/intel/pmt/class.c10
-rw-r--r--drivers/platform/x86/intel/pmt/crashlog.c2
-rw-r--r--drivers/platform/x86/intel/pmt/telemetry.c16
-rw-r--r--drivers/platform/x86/intel/sdsi.c2
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_tpmi.c2
-rw-r--r--drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c16
-rw-r--r--drivers/platform/x86/intel/tpmi_power_domains.c8
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c8
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c4
-rw-r--r--drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c2
-rw-r--r--drivers/platform/x86/intel/vsec.c6
-rw-r--r--drivers/platform/x86/intel/vsec_tpmi.c12
-rw-r--r--drivers/platform/x86/lenovo-ymc.c2
-rw-r--r--drivers/platform/x86/mlx-platform.c2
-rw-r--r--drivers/platform/x86/p2sb.c77
-rw-r--r--drivers/platform/x86/samsung-laptop.c2
-rw-r--r--drivers/platform/x86/thinkpad_acpi.c4
-rw-r--r--drivers/platform/x86/touchscreen_dmi.c26
-rw-r--r--drivers/pmdomain/core.c43
-rw-r--r--drivers/pmdomain/imx/gpc.c4
-rw-r--r--drivers/pmdomain/imx/gpcv2.c8
-rw-r--r--drivers/pmdomain/imx/imx8m-blk-ctrl.c2
-rw-r--r--drivers/pmdomain/imx/imx8mp-blk-ctrl.c2
-rw-r--r--drivers/pmdomain/imx/imx93-blk-ctrl.c2
-rw-r--r--drivers/pmdomain/imx/imx93-pd.c2
-rw-r--r--drivers/pmdomain/qcom/cpr.c2
-rw-r--r--drivers/pmdomain/xilinx/zynqmp-pm-domains.c2
-rw-r--r--drivers/power/supply/bq24190_charger.c12
-rw-r--r--drivers/power/supply/cros_charge-control.c36
-rw-r--r--drivers/power/supply/gpio-charger.c8
-rw-r--r--drivers/powercap/idle_inject.c16
-rw-r--r--drivers/powercap/intel_rapl_msr.c2
-rw-r--r--drivers/powercap/intel_rapl_tpmi.c2
-rw-r--r--drivers/pps/clients/pps-gpio.c2
-rw-r--r--drivers/ptp/ptp_clock.c3
-rw-r--r--drivers/ptp/ptp_clockmatrix.c2
-rw-r--r--drivers/ptp/ptp_dte.c2
-rw-r--r--drivers/ptp/ptp_fc3.c2
-rw-r--r--drivers/ptp/ptp_idt82p33.c2
-rw-r--r--drivers/ptp/ptp_ines.c2
-rw-r--r--drivers/ptp/ptp_kvm_x86.c6
-rw-r--r--drivers/ptp/ptp_ocp.c16
-rw-r--r--drivers/ptp/ptp_qoriq.c2
-rw-r--r--drivers/ptp/ptp_vmclock.c2
-rw-r--r--drivers/pwm/core.c2
-rw-r--r--drivers/pwm/pwm-dwc-core.c2
-rw-r--r--drivers/pwm/pwm-dwc.h2
-rw-r--r--drivers/pwm/pwm-lpss-pci.c2
-rw-r--r--drivers/pwm/pwm-lpss-platform.c2
-rw-r--r--drivers/pwm/pwm-lpss.c2
-rw-r--r--drivers/pwm/pwm-stm32.c2
-rw-r--r--drivers/regulator/axp20x-regulator.c36
-rw-r--r--drivers/regulator/of_regulator.c2
-rw-r--r--drivers/reset/amlogic/reset-meson-audio-arb.c2
-rw-r--r--drivers/reset/amlogic/reset-meson-aux.c2
-rw-r--r--drivers/reset/amlogic/reset-meson-common.c8
-rw-r--r--drivers/reset/amlogic/reset-meson.c2
-rw-r--r--drivers/reset/reset-mpfs.c4
-rw-r--r--drivers/reset/reset-rzg2l-usbphy-ctrl.c2
-rw-r--r--drivers/reset/reset-ti-sci.c2
-rw-r--r--drivers/rpmsg/qcom_glink_rpm.c2
-rw-r--r--drivers/rpmsg/qcom_smd.c2
-rw-r--r--drivers/rtc/Kconfig33
-rw-r--r--drivers/rtc/Makefile5
-rw-r--r--drivers/rtc/interface.c7
-rw-r--r--drivers/rtc/rtc-88pm80x.c2
-rw-r--r--drivers/rtc/rtc-88pm860x.c2
-rw-r--r--drivers/rtc/rtc-88pm886.c97
-rw-r--r--drivers/rtc/rtc-ab-eoz9.c11
-rw-r--r--drivers/rtc/rtc-ab8500.c2
-rw-r--r--drivers/rtc/rtc-abx80x.c2
-rw-r--r--drivers/rtc/rtc-ac100.c2
-rw-r--r--drivers/rtc/rtc-amlogic-a4.c465
-rw-r--r--drivers/rtc/rtc-asm9260.c2
-rw-r--r--drivers/rtc/rtc-at91rm9200.c2
-rw-r--r--drivers/rtc/rtc-at91sam9.c2
-rw-r--r--drivers/rtc/rtc-brcmstb-waketimer.c3
-rw-r--r--drivers/rtc/rtc-cadence.c2
-rw-r--r--drivers/rtc/rtc-cmos.c33
-rw-r--r--drivers/rtc/rtc-cros-ec.c2
-rw-r--r--drivers/rtc/rtc-ds1685.c2
-rw-r--r--drivers/rtc/rtc-ftrtc010.c2
-rw-r--r--drivers/rtc/rtc-hid-sensor-time.c4
-rw-r--r--drivers/rtc/rtc-imxdi.c2
-rw-r--r--drivers/rtc/rtc-isl12022.c269
-rw-r--r--drivers/rtc/rtc-loongson.c2
-rw-r--r--drivers/rtc/rtc-lpc24xx.c2
-rw-r--r--drivers/rtc/rtc-m48t59.c26
-rw-r--r--drivers/rtc/rtc-max77686.c2
-rw-r--r--drivers/rtc/rtc-mc13xxx.c2
-rw-r--r--drivers/rtc/rtc-mc146818-lib.c6
-rw-r--r--drivers/rtc/rtc-mpc5121.c2
-rw-r--r--drivers/rtc/rtc-mpfs.c2
-rw-r--r--drivers/rtc/rtc-mt6397.c29
-rw-r--r--drivers/rtc/rtc-mt7622.c2
-rw-r--r--drivers/rtc/rtc-mv.c2
-rw-r--r--drivers/rtc/rtc-mxc_v2.c2
-rw-r--r--drivers/rtc/rtc-nxp-bbnsm.c20
-rw-r--r--drivers/rtc/rtc-omap.c2
-rw-r--r--drivers/rtc/rtc-palmas.c2
-rw-r--r--drivers/rtc/rtc-pcf50633.c2
-rw-r--r--drivers/rtc/rtc-pcf8563.c212
-rw-r--r--drivers/rtc/rtc-pic32.c2
-rw-r--r--drivers/rtc/rtc-pm8xxx.c2
-rw-r--r--drivers/rtc/rtc-pxa.c2
-rw-r--r--drivers/rtc/rtc-rc5t583.c2
-rw-r--r--drivers/rtc/rtc-renesas-rtca3.c900
-rw-r--r--drivers/rtc/rtc-rtd119x.c2
-rw-r--r--drivers/rtc/rtc-rv3028.c6
-rw-r--r--drivers/rtc/rtc-rzn1.c92
-rw-r--r--drivers/rtc/rtc-s3c.c2
-rw-r--r--drivers/rtc/rtc-sa1100.c2
-rw-r--r--drivers/rtc/rtc-sh.c2
-rw-r--r--drivers/rtc/rtc-spear.c2
-rw-r--r--drivers/rtc/rtc-st-lpc.c5
-rw-r--r--drivers/rtc/rtc-stm32.c2
-rw-r--r--drivers/rtc/rtc-stmp3xxx.c2
-rw-r--r--drivers/rtc/rtc-sunplus.c2
-rw-r--r--drivers/rtc/rtc-tegra.c2
-rw-r--r--drivers/rtc/rtc-tps6586x.c2
-rw-r--r--drivers/rtc/rtc-twl.c2
-rw-r--r--drivers/rtc/rtc-vt8500.c2
-rw-r--r--drivers/rtc/rtc-wm8350.c2
-rw-r--r--drivers/rtc/rtc-xgene.c2
-rw-r--r--drivers/rtc/rtc-zynqmp.c2
-rw-r--r--drivers/s390/char/con3215.c1
-rw-r--r--drivers/s390/crypto/ap_bus.c2
-rw-r--r--drivers/s390/crypto/vfio_ap_ops.c32
-rw-r--r--drivers/sbus/char/bbc_i2c.c2
-rw-r--r--drivers/sbus/char/display7seg.c2
-rw-r--r--drivers/sbus/char/envctrl.c2
-rw-r--r--drivers/sbus/char/flash.c2
-rw-r--r--drivers/sbus/char/uctrl.c2
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.c482
-rw-r--r--drivers/scsi/bfa/bfa_fcbuild.h72
-rw-r--r--drivers/scsi/lpfc/lpfc_nvme.c2
-rw-r--r--drivers/scsi/lpfc/lpfc_nvmet.c2
-rw-r--r--drivers/scsi/megaraid/megaraid_sas_base.c5
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr.h13
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_app.c36
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_fw.c121
-rw-r--r--drivers/scsi/mpi3mr/mpi3mr_os.c2
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.c7
-rw-r--r--drivers/scsi/mpt3sas/mpt3sas_base.h8
-rw-r--r--drivers/scsi/qla1280.h12
-rw-r--r--drivers/scsi/qla2xxx/qla_attr.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_bsg.c124
-rw-r--r--drivers/scsi/qla2xxx/qla_mid.c1
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c15
-rw-r--r--drivers/scsi/qla2xxx/qla_version.h4
-rw-r--r--drivers/scsi/scsi_debug.c2
-rw-r--r--drivers/scsi/scsi_sysfs.c2
-rw-r--r--drivers/scsi/sg.c2
-rw-r--r--drivers/scsi/storvsc_drv.c7
-rw-r--r--drivers/sh/intc/core.c2
-rw-r--r--drivers/slimbus/qcom-ctrl.c2
-rw-r--r--drivers/slimbus/qcom-ngd-ctrl.c4
-rw-r--r--drivers/soundwire/amd_init.c6
-rw-r--r--drivers/soundwire/amd_manager.c2
-rw-r--r--drivers/soundwire/intel.c2
-rw-r--r--drivers/soundwire/intel_ace2x.c4
-rw-r--r--drivers/soundwire/intel_init.c10
-rw-r--r--drivers/soundwire/qcom.c2
-rw-r--r--drivers/soundwire/slave.c2
-rw-r--r--drivers/spi/spi-apple.c1
-rw-r--r--drivers/spi/spi-aspeed-smc.c10
-rw-r--r--drivers/spi/spi-cadence-quadspi.c10
-rw-r--r--drivers/spi/spi-cs42l43.c2
-rw-r--r--drivers/spi/spi-dw-bt1.c2
-rw-r--r--drivers/spi/spi-dw-core.c14
-rw-r--r--drivers/spi/spi-dw-dma.c4
-rw-r--r--drivers/spi/spi-dw-mmio.c2
-rw-r--r--drivers/spi/spi-dw-pci.c2
-rw-r--r--drivers/spi/spi-intel-pci.c2
-rw-r--r--drivers/spi/spi-ljca.c2
-rw-r--r--drivers/spi/spi-loongson-core.c4
-rw-r--r--drivers/spi/spi-loongson-pci.c2
-rw-r--r--drivers/spi/spi-loongson-plat.c2
-rw-r--r--drivers/spi/spi-mpc52xx.c1
-rw-r--r--drivers/spi/spi-omap2-mcspi.c6
-rw-r--r--drivers/spi/spi-pxa2xx-pci.c2
-rw-r--r--drivers/spi/spi-pxa2xx-platform.c2
-rw-r--r--drivers/spi/spi-pxa2xx.c4
-rw-r--r--drivers/spi/spi-rockchip-sfc.c4
-rw-r--r--drivers/spi/spi-rockchip.c14
-rw-r--r--drivers/spmi/spmi-mtk-pmif.c2
-rw-r--r--drivers/spmi/spmi-pmic-arb.c5
-rw-r--r--drivers/staging/Kconfig16
-rw-r--r--drivers/staging/Makefile8
-rw-r--r--drivers/staging/axis-fifo/axis-fifo.c2
-rw-r--r--drivers/staging/fbtft/Kconfig1
-rw-r--r--drivers/staging/fbtft/fbtft.h2
-rw-r--r--drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev31
-rw-r--r--drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev62
-rw-r--r--drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt71
-rw-r--r--drivers/staging/fieldbus/Documentation/fieldbus_dev.txt66
-rw-r--r--drivers/staging/fieldbus/Kconfig19
-rw-r--r--drivers/staging/fieldbus/Makefile7
-rw-r--r--drivers/staging/fieldbus/TODO5
-rw-r--r--drivers/staging/fieldbus/anybuss/Kconfig41
-rw-r--r--drivers/staging/fieldbus/anybuss/Makefile10
-rw-r--r--drivers/staging/fieldbus/anybuss/anybuss-client.h95
-rw-r--r--drivers/staging/fieldbus/anybuss/anybuss-controller.h47
-rw-r--r--drivers/staging/fieldbus/anybuss/arcx-anybus.c379
-rw-r--r--drivers/staging/fieldbus/anybuss/hms-profinet.c224
-rw-r--r--drivers/staging/fieldbus/anybuss/host.c1452
-rw-r--r--drivers/staging/fieldbus/dev_core.c344
-rw-r--r--drivers/staging/fieldbus/fieldbus_dev.h114
-rw-r--r--drivers/staging/gdm724x/Kconfig16
-rw-r--r--drivers/staging/gdm724x/Makefile8
-rw-r--r--drivers/staging/gdm724x/TODO16
-rw-r--r--drivers/staging/gdm724x/gdm_endian.c37
-rw-r--r--drivers/staging/gdm724x/gdm_endian.h30
-rw-r--r--drivers/staging/gdm724x/gdm_lte.c937
-rw-r--r--drivers/staging/gdm724x/gdm_lte.h71
-rw-r--r--drivers/staging/gdm724x/gdm_mux.c668
-rw-r--r--drivers/staging/gdm724x/gdm_mux.h85
-rw-r--r--drivers/staging/gdm724x/gdm_tty.c316
-rw-r--r--drivers/staging/gdm724x/gdm_tty.h60
-rw-r--r--drivers/staging/gdm724x/gdm_usb.c1012
-rw-r--r--drivers/staging/gdm724x/gdm_usb.h99
-rw-r--r--drivers/staging/gdm724x/hci.h45
-rw-r--r--drivers/staging/gdm724x/hci_packet.h82
-rw-r--r--drivers/staging/gdm724x/netlink_k.c128
-rw-r--r--drivers/staging/gdm724x/netlink_k.h16
-rw-r--r--drivers/staging/gpib/Kconfig256
-rw-r--r--drivers/staging/gpib/Makefile20
-rw-r--r--drivers/staging/gpib/TODO21
-rw-r--r--drivers/staging/gpib/agilent_82350b/Makefile2
-rw-r--r--drivers/staging/gpib/agilent_82350b/agilent_82350b.c932
-rw-r--r--drivers/staging/gpib/agilent_82350b/agilent_82350b.h209
-rw-r--r--drivers/staging/gpib/agilent_82357a/Makefile4
-rw-r--r--drivers/staging/gpib/agilent_82357a/agilent_82357a.c1712
-rw-r--r--drivers/staging/gpib/agilent_82357a/agilent_82357a.h182
-rw-r--r--drivers/staging/gpib/cb7210/Makefile4
-rw-r--r--drivers/staging/gpib/cb7210/cb7210.c1556
-rw-r--r--drivers/staging/gpib/cb7210/cb7210.h251
-rw-r--r--drivers/staging/gpib/cec/Makefile3
-rw-r--r--drivers/staging/gpib/cec/cec.h53
-rw-r--r--drivers/staging/gpib/cec/cec_gpib.c385
-rw-r--r--drivers/staging/gpib/common/Makefile6
-rw-r--r--drivers/staging/gpib/common/gpib_os.c2328
-rw-r--r--drivers/staging/gpib/common/iblib.c740
-rw-r--r--drivers/staging/gpib/common/ibsys.h31
-rw-r--r--drivers/staging/gpib/eastwood/Makefile3
-rw-r--r--drivers/staging/gpib/eastwood/fluke_gpib.c1179
-rw-r--r--drivers/staging/gpib/eastwood/fluke_gpib.h143
-rw-r--r--drivers/staging/gpib/fmh_gpib/Makefile2
-rw-r--r--drivers/staging/gpib/fmh_gpib/fmh_gpib.c1725
-rw-r--r--drivers/staging/gpib/fmh_gpib/fmh_gpib.h177
-rw-r--r--drivers/staging/gpib/gpio/Makefile4
-rw-r--r--drivers/staging/gpib/gpio/gpib_bitbang.c1476
-rw-r--r--drivers/staging/gpib/hp_82335/Makefile4
-rw-r--r--drivers/staging/gpib/hp_82335/hp82335.c360
-rw-r--r--drivers/staging/gpib/hp_82335/hp82335.h85
-rw-r--r--drivers/staging/gpib/hp_82341/Makefile2
-rw-r--r--drivers/staging/gpib/hp_82341/hp_82341.c895
-rw-r--r--drivers/staging/gpib/hp_82341/hp_82341.h207
-rw-r--r--drivers/staging/gpib/include/amcc5920.h49
-rw-r--r--drivers/staging/gpib/include/amccs5933.h59
-rw-r--r--drivers/staging/gpib/include/gpibP.h50
-rw-r--r--drivers/staging/gpib/include/gpib_pci_ids.h23
-rw-r--r--drivers/staging/gpib/include/gpib_proto.h56
-rw-r--r--drivers/staging/gpib/include/gpib_state_machines.h23
-rw-r--r--drivers/staging/gpib/include/gpib_types.h353
-rw-r--r--drivers/staging/gpib/include/nec7210.h138
-rw-r--r--drivers/staging/gpib/include/nec7210_registers.h217
-rw-r--r--drivers/staging/gpib/include/plx9050.h72
-rw-r--r--drivers/staging/gpib/include/quancom_pci.h22
-rw-r--r--drivers/staging/gpib/include/tms9914.h274
-rw-r--r--drivers/staging/gpib/include/tnt4882_registers.h192
-rw-r--r--drivers/staging/gpib/ines/Makefile4
-rw-r--r--drivers/staging/gpib/ines/ines.h215
-rw-r--r--drivers/staging/gpib/ines/ines_gpib.c1464
-rw-r--r--drivers/staging/gpib/lpvo_usb_gpib/Makefile3
-rw-r--r--drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c2136
-rw-r--r--drivers/staging/gpib/nec7210/Makefile4
-rw-r--r--drivers/staging/gpib/nec7210/board.h19
-rw-r--r--drivers/staging/gpib/nec7210/nec7210.c1134
-rw-r--r--drivers/staging/gpib/ni_usb/Makefile4
-rw-r--r--drivers/staging/gpib/ni_usb/ni_usb_gpib.c2640
-rw-r--r--drivers/staging/gpib/ni_usb/ni_usb_gpib.h216
-rw-r--r--drivers/staging/gpib/pc2/Makefile5
-rw-r--r--drivers/staging/gpib/pc2/pc2_gpib.c656
-rw-r--r--drivers/staging/gpib/tms9914/Makefile6
-rw-r--r--drivers/staging/gpib/tms9914/tms9914.c910
-rw-r--r--drivers/staging/gpib/tnt4882/Makefile7
-rw-r--r--drivers/staging/gpib/tnt4882/mite.c219
-rw-r--r--drivers/staging/gpib/tnt4882/mite.h243
-rw-r--r--drivers/staging/gpib/tnt4882/tnt4882_gpib.c1874
-rw-r--r--drivers/staging/gpib/uapi/gpib_ioctl.h169
-rw-r--r--drivers/staging/gpib/uapi/gpib_user.h363
-rw-r--r--drivers/staging/greybus/arche-apb-ctrl.c2
-rw-r--r--drivers/staging/greybus/arche-platform.c2
-rw-r--r--drivers/staging/greybus/gpio.c33
-rw-r--r--drivers/staging/greybus/uart.c2
-rw-r--r--drivers/staging/iio/TODO5
-rw-r--r--drivers/staging/iio/accel/adis16203.c2
-rw-r--r--drivers/staging/iio/accel/adis16240.c2
-rw-r--r--drivers/staging/iio/impedance-analyzer/ad5933.c6
-rw-r--r--drivers/staging/media/atomisp/pci/atomisp_v4l2.c2
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c2
-rw-r--r--drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c2
-rw-r--r--drivers/staging/media/imx/imx-media-csi.c2
-rw-r--r--drivers/staging/media/imx/imx-media-dev.c2
-rw-r--r--drivers/staging/media/imx/imx6-mipi-csi2.c2
-rw-r--r--drivers/staging/media/meson/vdec/vdec.c2
-rw-r--r--drivers/staging/media/rkvdec/rkvdec.c2
-rw-r--r--drivers/staging/media/starfive/camss/stf-camss.c2
-rw-r--r--drivers/staging/media/sunxi/cedrus/cedrus.c2
-rw-r--r--drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c2
-rw-r--r--drivers/staging/media/tegra-video/csi.c2
-rw-r--r--drivers/staging/media/tegra-video/vi.c2
-rw-r--r--drivers/staging/media/tegra-video/vip.c2
-rw-r--r--drivers/staging/most/TODO7
-rw-r--r--drivers/staging/most/dim2/dim2.c2
-rw-r--r--drivers/staging/most/i2c/i2c.c4
-rw-r--r--drivers/staging/nvec/nvec.c2
-rw-r--r--drivers/staging/nvec/nvec_kbd.c2
-rw-r--r--drivers/staging/nvec/nvec_power.c2
-rw-r--r--drivers/staging/nvec/nvec_ps2.c2
-rw-r--r--drivers/staging/octeon/ethernet-tx.c6
-rw-r--r--drivers/staging/octeon/ethernet.c2
-rw-r--r--drivers/staging/olpc_dcon/Kconfig17
-rw-r--r--drivers/staging/olpc_dcon/Makefile5
-rw-r--r--drivers/staging/olpc_dcon/TODO15
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.c807
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon.h112
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon_xo_1.c201
-rw-r--r--drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c204
-rw-r--r--drivers/staging/rtl8712/Kconfig21
-rw-r--r--drivers/staging/rtl8712/Makefile35
-rw-r--r--drivers/staging/rtl8712/TODO12
-rw-r--r--drivers/staging/rtl8712/basic_types.h28
-rw-r--r--drivers/staging/rtl8712/drv_types.h175
-rw-r--r--drivers/staging/rtl8712/ethernet.h21
-rw-r--r--drivers/staging/rtl8712/hal_init.c401
-rw-r--r--drivers/staging/rtl8712/ieee80211.c415
-rw-r--r--drivers/staging/rtl8712/ieee80211.h165
-rw-r--r--drivers/staging/rtl8712/mlme_linux.c160
-rw-r--r--drivers/staging/rtl8712/mlme_osdep.h31
-rw-r--r--drivers/staging/rtl8712/mp_custom_oid.h287
-rw-r--r--drivers/staging/rtl8712/os_intfs.c482
-rw-r--r--drivers/staging/rtl8712/osdep_intf.h32
-rw-r--r--drivers/staging/rtl8712/osdep_service.h60
-rw-r--r--drivers/staging/rtl8712/recv_linux.c139
-rw-r--r--drivers/staging/rtl8712/recv_osdep.h39
-rw-r--r--drivers/staging/rtl8712/rtl8712_bitdef.h26
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.c409
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmd.h231
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h95
-rw-r--r--drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h19
-rw-r--r--drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h41
-rw-r--r--drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h32
-rw-r--r--drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h65
-rw-r--r--drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h24
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.c563
-rw-r--r--drivers/staging/rtl8712/rtl8712_efuse.h44
-rw-r--r--drivers/staging/rtl8712/rtl8712_event.h86
-rw-r--r--drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h131
-rw-r--r--drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h61
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_bitdef.h68
-rw-r--r--drivers/staging/rtl8712/rtl8712_gp_regdef.h29
-rw-r--r--drivers/staging/rtl8712/rtl8712_hal.h142
-rw-r--r--drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h44
-rw-r--r--drivers/staging/rtl8712/rtl8712_io.c99
-rw-r--r--drivers/staging/rtl8712/rtl8712_led.c1830
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h31
-rw-r--r--drivers/staging/rtl8712/rtl8712_macsetting_regdef.h20
-rw-r--r--drivers/staging/rtl8712/rtl8712_powersave_bitdef.h39
-rw-r--r--drivers/staging/rtl8712/rtl8712_powersave_regdef.h26
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h36
-rw-r--r--drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h43
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.c1075
-rw-r--r--drivers/staging/rtl8712/rtl8712_recv.h145
-rw-r--r--drivers/staging/rtl8712/rtl8712_regdef.h32
-rw-r--r--drivers/staging/rtl8712/rtl8712_security_bitdef.h34
-rw-r--r--drivers/staging/rtl8712/rtl8712_spec.h121
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h163
-rw-r--r--drivers/staging/rtl8712/rtl8712_syscfg_regdef.h42
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h49
-rw-r--r--drivers/staging/rtl8712/rtl8712_timectrl_regdef.h26
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_bitdef.h49
-rw-r--r--drivers/staging/rtl8712/rtl8712_wmac_regdef.h36
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.c732
-rw-r--r--drivers/staging/rtl8712/rtl8712_xmit.h108
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.c750
-rw-r--r--drivers/staging/rtl8712/rtl871x_cmd.h750
-rw-r--r--drivers/staging/rtl8712/rtl871x_debug.h130
-rw-r--r--drivers/staging/rtl8712/rtl871x_eeprom.c220
-rw-r--r--drivers/staging/rtl8712/rtl871x_eeprom.h88
-rw-r--r--drivers/staging/rtl8712/rtl871x_event.h109
-rw-r--r--drivers/staging/rtl8712/rtl871x_ht.h33
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.c147
-rw-r--r--drivers/staging/rtl8712/rtl871x_io.h236
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl.h94
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_linux.c2275
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_rtl.c519
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_rtl.h109
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.c354
-rw-r--r--drivers/staging/rtl8712/rtl871x_ioctl_set.h45
-rw-r--r--drivers/staging/rtl8712/rtl871x_led.h118
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.c1710
-rw-r--r--drivers/staging/rtl8712/rtl871x_mlme.h205
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.c724
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp.h275
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.c883
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_ioctl.h328
-rw-r--r--drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h1034
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.c234
-rw-r--r--drivers/staging/rtl8712/rtl871x_pwrctrl.h113
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.c671
-rw-r--r--drivers/staging/rtl8712/rtl871x_recv.h208
-rw-r--r--drivers/staging/rtl8712/rtl871x_rf.h55
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.c1386
-rw-r--r--drivers/staging/rtl8712/rtl871x_security.h218
-rw-r--r--drivers/staging/rtl8712/rtl871x_sta_mgt.c263
-rw-r--r--drivers/staging/rtl8712/rtl871x_wlan_sme.h35
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.c1056
-rw-r--r--drivers/staging/rtl8712/rtl871x_xmit.h287
-rw-r--r--drivers/staging/rtl8712/sta_info.h132
-rw-r--r--drivers/staging/rtl8712/usb_halinit.c307
-rw-r--r--drivers/staging/rtl8712/usb_intf.c638
-rw-r--r--drivers/staging/rtl8712/usb_ops.c195
-rw-r--r--drivers/staging/rtl8712/usb_ops.h38
-rw-r--r--drivers/staging/rtl8712/usb_ops_linux.c508
-rw-r--r--drivers/staging/rtl8712/usb_osintf.h35
-rw-r--r--drivers/staging/rtl8712/wifi.h196
-rw-r--r--drivers/staging/rtl8712/wlan_bssdef.h223
-rw-r--r--drivers/staging/rtl8712/xmit_linux.c181
-rw-r--r--drivers/staging/rtl8712/xmit_osdep.h52
-rw-r--r--drivers/staging/rtl8723bs/TODO3
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_cmd.c6
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_efuse.c94
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme.c6
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_mlme_ext.c11
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_pwrctrl.c7
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_wlan_util.c68
-rw-r--r--drivers/staging/rtl8723bs/core/rtw_xmit.c2
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_com.c42
-rw-r--r--drivers/staging/rtl8723bs/hal/hal_intf.c137
-rw-r--r--drivers/staging/rtl8723bs/hal/odm.c14
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c550
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c15
-rw-r--r--drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c4
-rw-r--r--drivers/staging/rtl8723bs/hal/sdio_halinit.c59
-rw-r--r--drivers/staging/rtl8723bs/include/drv_types.h10
-rw-r--r--drivers/staging/rtl8723bs/include/hal_com.h4
-rw-r--r--drivers/staging/rtl8723bs/include/hal_intf.h95
-rw-r--r--drivers/staging/rtl8723bs/include/hal_phy_cfg.h5
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_intf.h3
-rw-r--r--drivers/staging/rtl8723bs/include/osdep_service.h5
-rw-r--r--drivers/staging/rtl8723bs/include/rtl8723b_recv.h5
-rw-r--r--drivers/staging/rtl8723bs/include/rtl8723b_xmit.h2
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_efuse.h4
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_mlme_ext.h5
-rw-r--r--drivers/staging/rtl8723bs/include/rtw_mp.h4
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c15
-rw-r--r--drivers/staging/rtl8723bs/os_dep/ioctl_linux.c17
-rw-r--r--drivers/staging/rtl8723bs/os_dep/os_intfs.c31
-rw-r--r--drivers/staging/rtl8723bs/os_dep/sdio_intf.c17
-rw-r--r--drivers/staging/rts5208/Kconfig9
-rw-r--r--drivers/staging/rts5208/Makefile5
-rw-r--r--drivers/staging/rts5208/TODO7
-rw-r--r--drivers/staging/rts5208/general.c25
-rw-r--r--drivers/staging/rts5208/general.h19
-rw-r--r--drivers/staging/rts5208/ms.c4311
-rw-r--r--drivers/staging/rts5208/ms.h214
-rw-r--r--drivers/staging/rts5208/rtsx.c987
-rw-r--r--drivers/staging/rts5208/rtsx.h164
-rw-r--r--drivers/staging/rts5208/rtsx_card.c1151
-rw-r--r--drivers/staging/rts5208/rtsx_card.h1087
-rw-r--r--drivers/staging/rts5208/rtsx_chip.c2161
-rw-r--r--drivers/staging/rts5208/rtsx_chip.h987
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.c3279
-rw-r--r--drivers/staging/rts5208/rtsx_scsi.h131
-rw-r--r--drivers/staging/rts5208/rtsx_sys.h36
-rw-r--r--drivers/staging/rts5208/rtsx_transport.c768
-rw-r--r--drivers/staging/rts5208/rtsx_transport.h57
-rw-r--r--drivers/staging/rts5208/sd.c4717
-rw-r--r--drivers/staging/rts5208/sd.h289
-rw-r--r--drivers/staging/rts5208/spi.c906
-rw-r--r--drivers/staging/rts5208/spi.h52
-rw-r--r--drivers/staging/rts5208/xd.c2145
-rw-r--r--drivers/staging/rts5208/xd.h176
-rw-r--r--drivers/staging/sm750fb/TODO5
-rw-r--r--drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c3
-rw-r--r--drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h7
-rw-r--r--drivers/staging/vc04_services/interface/TESTING4
-rw-r--r--drivers/staging/vc04_services/interface/TODO13
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c526
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h3
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c696
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h55
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h3
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c44
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h2
-rw-r--r--drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h21
-rw-r--r--drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c7
-rw-r--r--drivers/staging/vme_user/vme_bridge.h56
-rw-r--r--drivers/staging/vt6655/Kconfig6
-rw-r--r--drivers/staging/vt6655/Makefile15
-rw-r--r--drivers/staging/vt6655/TODO20
-rw-r--r--drivers/staging/vt6655/baseband.c2257
-rw-r--r--drivers/staging/vt6655/baseband.h72
-rw-r--r--drivers/staging/vt6655/card.c836
-rw-r--r--drivers/staging/vt6655/card.h62
-rw-r--r--drivers/staging/vt6655/channel.c135
-rw-r--r--drivers/staging/vt6655/channel.h17
-rw-r--r--drivers/staging/vt6655/desc.h249
-rw-r--r--drivers/staging/vt6655/device.h292
-rw-r--r--drivers/staging/vt6655/device_cfg.h44
-rw-r--r--drivers/staging/vt6655/device_main.c1868
-rw-r--r--drivers/staging/vt6655/dpc.c145
-rw-r--r--drivers/staging/vt6655/dpc.h21
-rw-r--r--drivers/staging/vt6655/key.c143
-rw-r--r--drivers/staging/vt6655/key.h51
-rw-r--r--drivers/staging/vt6655/mac.c851
-rw-r--r--drivers/staging/vt6655/mac.h580
-rw-r--r--drivers/staging/vt6655/power.c144
-rw-r--r--drivers/staging/vt6655/power.h29
-rw-r--r--drivers/staging/vt6655/rf.c535
-rw-r--r--drivers/staging/vt6655/rf.h71
-rw-r--r--drivers/staging/vt6655/rxtx.c1462
-rw-r--r--drivers/staging/vt6655/rxtx.h184
-rw-r--r--drivers/staging/vt6655/srom.c139
-rw-r--r--drivers/staging/vt6655/srom.h85
-rw-r--r--drivers/staging/vt6655/test9
-rw-r--r--drivers/staging/vt6656/Kconfig7
-rw-r--r--drivers/staging/vt6656/Makefile15
-rw-r--r--drivers/staging/vt6656/TODO17
-rw-r--r--drivers/staging/vt6656/baseband.c455
-rw-r--r--drivers/staging/vt6656/baseband.h75
-rw-r--r--drivers/staging/vt6656/card.c456
-rw-r--r--drivers/staging/vt6656/card.h44
-rw-r--r--drivers/staging/vt6656/channel.c77
-rw-r--r--drivers/staging/vt6656/channel.h21
-rw-r--r--drivers/staging/vt6656/desc.h91
-rw-r--r--drivers/staging/vt6656/device.h386
-rw-r--r--drivers/staging/vt6656/key.c142
-rw-r--r--drivers/staging/vt6656/key.h40
-rw-r--r--drivers/staging/vt6656/mac.c183
-rw-r--r--drivers/staging/vt6656/mac.h373
-rw-r--r--drivers/staging/vt6656/main_usb.c1121
-rw-r--r--drivers/staging/vt6656/power.c112
-rw-r--r--drivers/staging/vt6656/power.h23
-rw-r--r--drivers/staging/vt6656/rf.c443
-rw-r--r--drivers/staging/vt6656/rf.h46
-rw-r--r--drivers/staging/vt6656/rxtx.c730
-rw-r--r--drivers/staging/vt6656/rxtx.h178
-rw-r--r--drivers/staging/vt6656/usbpipe.c506
-rw-r--r--drivers/staging/vt6656/usbpipe.h67
-rw-r--r--drivers/staging/vt6656/wcmd.c185
-rw-r--r--drivers/staging/vt6656/wcmd.h48
-rw-r--r--drivers/target/target_core_user.c4
-rw-r--r--drivers/tee/optee/smc_abi.c2
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device.c4
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c2
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c6
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c12
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c2
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c10
-rw-r--r--drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c2
-rw-r--r--drivers/thermal/intel/intel_powerclamp.c2
-rw-r--r--drivers/thermal/intel/intel_soc_dts_iosf.c2
-rw-r--r--drivers/thermal/intel/intel_tcc.c10
-rw-r--r--drivers/thermal/intel/intel_tcc_cooling.c2
-rw-r--r--drivers/thermal/intel/x86_pkg_temp_thermal.c2
-rw-r--r--drivers/thermal/thermal_hwmon.c2
-rw-r--r--drivers/thermal/thermal_thresholds.c68
-rw-r--r--drivers/thunderbolt/debugfs.c504
-rw-r--r--drivers/thunderbolt/nhi.c20
-rw-r--r--drivers/thunderbolt/nhi.h4
-rw-r--r--drivers/thunderbolt/retimer.c19
-rw-r--r--drivers/thunderbolt/sb_regs.h32
-rw-r--r--drivers/thunderbolt/tb.c41
-rw-r--r--drivers/thunderbolt/tb.h16
-rw-r--r--drivers/thunderbolt/usb4.c18
-rw-r--r--drivers/tty/amiserial.c2
-rw-r--r--drivers/tty/goldfish.c2
-rw-r--r--drivers/tty/hvc/hvc_opal.c2
-rw-r--r--drivers/tty/serial/8250/8250_aspeed_vuart.c2
-rw-r--r--drivers/tty/serial/8250/8250_bcm2835aux.c2
-rw-r--r--drivers/tty/serial/8250/8250_bcm7271.c4
-rw-r--r--drivers/tty/serial/8250/8250_dw.c7
-rw-r--r--drivers/tty/serial/8250/8250_em.c2
-rw-r--r--drivers/tty/serial/8250/8250_exar.c136
-rw-r--r--drivers/tty/serial/8250/8250_fintek.c16
-rw-r--r--drivers/tty/serial/8250/8250_fsl.c2
-rw-r--r--drivers/tty/serial/8250/8250_ingenic.c2
-rw-r--r--drivers/tty/serial/8250/8250_ioc3.c2
-rw-r--r--drivers/tty/serial/8250/8250_lpc18xx.c2
-rw-r--r--drivers/tty/serial/8250/8250_men_mcb.c2
-rw-r--r--drivers/tty/serial/8250/8250_mtk.c6
-rw-r--r--drivers/tty/serial/8250/8250_of.c2
-rw-r--r--drivers/tty/serial/8250/8250_omap.c10
-rw-r--r--drivers/tty/serial/8250/8250_pci.c2
-rw-r--r--drivers/tty/serial/8250/8250_pci1xxxx.c2
-rw-r--r--drivers/tty/serial/8250/8250_pcilib.c4
-rw-r--r--drivers/tty/serial/8250/8250_platform.c2
-rw-r--r--drivers/tty/serial/8250/8250_port.c3
-rw-r--r--drivers/tty/serial/8250/8250_pxa.c2
-rw-r--r--drivers/tty/serial/8250/8250_tegra.c2
-rw-r--r--drivers/tty/serial/8250/8250_uniphier.c2
-rw-r--r--drivers/tty/serial/8250/Kconfig1
-rw-r--r--drivers/tty/serial/altera_jtaguart.c6
-rw-r--r--drivers/tty/serial/altera_uart.c6
-rw-r--r--drivers/tty/serial/amba-pl011.c9
-rw-r--r--drivers/tty/serial/ar933x_uart.c2
-rw-r--r--drivers/tty/serial/atmel_serial.c16
-rw-r--r--drivers/tty/serial/bcm63xx_uart.c2
-rw-r--r--drivers/tty/serial/clps711x.c2
-rw-r--r--drivers/tty/serial/cpm_uart.c2
-rw-r--r--drivers/tty/serial/digicolor-usart.c2
-rw-r--r--drivers/tty/serial/esp32_acm.c2
-rw-r--r--drivers/tty/serial/esp32_uart.c2
-rw-r--r--drivers/tty/serial/fsl_linflexuart.c2
-rw-r--r--drivers/tty/serial/fsl_lpuart.c23
-rw-r--r--drivers/tty/serial/imx.c137
-rw-r--r--drivers/tty/serial/lantiq.c2
-rw-r--r--drivers/tty/serial/liteuart.c2
-rw-r--r--drivers/tty/serial/lpc32xx_hs.c2
-rw-r--r--drivers/tty/serial/ma35d1_serial.c2
-rw-r--r--drivers/tty/serial/mcf.c2
-rw-r--r--drivers/tty/serial/men_z135_uart.c2
-rw-r--r--drivers/tty/serial/meson_uart.c2
-rw-r--r--drivers/tty/serial/milbeaut_usio.c2
-rw-r--r--drivers/tty/serial/mpc52xx_uart.c2
-rw-r--r--drivers/tty/serial/msm_serial.c2
-rw-r--r--drivers/tty/serial/mxs-auart.c2
-rw-r--r--drivers/tty/serial/omap-serial.c2
-rw-r--r--drivers/tty/serial/owl-uart.c2
-rw-r--r--drivers/tty/serial/pic32_uart.c2
-rw-r--r--drivers/tty/serial/pmac_zilog.c2
-rw-r--r--drivers/tty/serial/qcom_geni_serial.c2
-rw-r--r--drivers/tty/serial/rda-uart.c2
-rw-r--r--drivers/tty/serial/sa1100.c2
-rw-r--r--drivers/tty/serial/samsung_tty.c15
-rw-r--r--drivers/tty/serial/sc16is7xx.c4
-rw-r--r--drivers/tty/serial/sc16is7xx_i2c.c2
-rw-r--r--drivers/tty/serial/sc16is7xx_spi.c2
-rw-r--r--drivers/tty/serial/sccnxp.c2
-rw-r--r--drivers/tty/serial/serial-tegra.c2
-rw-r--r--drivers/tty/serial/serial_txx9.c2
-rw-r--r--drivers/tty/serial/sh-sci.c31
-rw-r--r--drivers/tty/serial/sifive.c2
-rw-r--r--drivers/tty/serial/sprd_serial.c43
-rw-r--r--drivers/tty/serial/st-asc.c2
-rw-r--r--drivers/tty/serial/stm32-usart.c2
-rw-r--r--drivers/tty/serial/sunhv.c2
-rw-r--r--drivers/tty/serial/sunplus-uart.c2
-rw-r--r--drivers/tty/serial/sunsab.c2
-rw-r--r--drivers/tty/serial/sunsu.c2
-rw-r--r--drivers/tty/serial/sunzilog.c2
-rw-r--r--drivers/tty/serial/tegra-tcu.c2
-rw-r--r--drivers/tty/serial/timbuart.c2
-rw-r--r--drivers/tty/serial/uartlite.c2
-rw-r--r--drivers/tty/serial/ucc_uart.c2
-rw-r--r--drivers/tty/serial/xilinx_uartps.c2
-rw-r--r--drivers/tty/tty_io.c2
-rw-r--r--drivers/ufs/core/ufs-sysfs.c6
-rw-r--r--drivers/ufs/core/ufs_bsg.c2
-rw-r--r--drivers/ufs/core/ufshcd-priv.h7
-rw-r--r--drivers/ufs/core/ufshcd.c55
-rw-r--r--drivers/ufs/host/cdns-pltfrm.c6
-rw-r--r--drivers/ufs/host/tc-dwc-g210-pltfrm.c7
-rw-r--r--drivers/ufs/host/ti-j721e-ufs.c2
-rw-r--r--drivers/ufs/host/ufs-exynos.c5
-rw-r--r--drivers/ufs/host/ufs-hisi.c6
-rw-r--r--drivers/ufs/host/ufs-mediatek.c7
-rw-r--r--drivers/ufs/host/ufs-qcom.c40
-rw-r--r--drivers/ufs/host/ufs-qcom.h5
-rw-r--r--drivers/ufs/host/ufs-renesas.c6
-rw-r--r--drivers/ufs/host/ufs-sprd.c7
-rw-r--r--drivers/ufs/host/ufshcd-pltfrm.c16
-rw-r--r--drivers/ufs/host/ufshcd-pltfrm.h1
-rw-r--r--drivers/uio/uio_dmem_genirq.c5
-rw-r--r--drivers/uio/uio_fsl_elbc_gpcm.c2
-rw-r--r--drivers/uio/uio_hv_generic.c2
-rw-r--r--drivers/uio/uio_pdrv_genirq.c5
-rw-r--r--drivers/usb/atm/ueagle-atm.c6
-rw-r--r--drivers/usb/atm/usbatm.c2
-rw-r--r--drivers/usb/c67x00/c67x00-drv.c2
-rw-r--r--drivers/usb/cdns3/cdns3-imx.c2
-rw-r--r--drivers/usb/cdns3/cdns3-pci-wrap.c4
-rw-r--r--drivers/usb/cdns3/cdns3-plat.c2
-rw-r--r--drivers/usb/cdns3/cdns3-starfive.c2
-rw-r--r--drivers/usb/cdns3/cdns3-ti.c2
-rw-r--r--drivers/usb/cdns3/cdnsp-pci.c26
-rw-r--r--drivers/usb/chipidea/ci.h2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_imx.c3
-rw-r--r--drivers/usb/chipidea/ci_hdrc_msm.c2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_npcm.c2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_tegra.c2
-rw-r--r--drivers/usb/chipidea/ci_hdrc_usb2.c2
-rw-r--r--drivers/usb/chipidea/core.c6
-rw-r--r--drivers/usb/chipidea/udc.c178
-rw-r--r--drivers/usb/chipidea/udc.h2
-rw-r--r--drivers/usb/chipidea/usbmisc_imx.c4
-rw-r--r--drivers/usb/common/common.c3
-rw-r--r--drivers/usb/common/usb-conn-gpio.c2
-rw-r--r--drivers/usb/core/config.c2
-rw-r--r--drivers/usb/core/devio.c5
-rw-r--r--drivers/usb/core/driver.c24
-rw-r--r--drivers/usb/core/endpoint.c11
-rw-r--r--drivers/usb/core/hcd.c8
-rw-r--r--drivers/usb/core/ledtrig-usbport.c3
-rw-r--r--drivers/usb/core/port.c11
-rw-r--r--drivers/usb/core/sysfs.c2
-rw-r--r--drivers/usb/core/usb.h2
-rw-r--r--drivers/usb/dwc2/Kconfig2
-rw-r--r--drivers/usb/dwc2/hcd.c19
-rw-r--r--drivers/usb/dwc2/platform.c2
-rw-r--r--drivers/usb/dwc3/Kconfig2
-rw-r--r--drivers/usb/dwc3/core.c16
-rw-r--r--drivers/usb/dwc3/core.h14
-rw-r--r--drivers/usb/dwc3/dwc3-am62.c2
-rw-r--r--drivers/usb/dwc3/dwc3-exynos.c2
-rw-r--r--drivers/usb/dwc3/dwc3-imx8mp.c32
-rw-r--r--drivers/usb/dwc3/dwc3-keystone.c2
-rw-r--r--drivers/usb/dwc3/dwc3-meson-g12a.c2
-rw-r--r--drivers/usb/dwc3/dwc3-octeon.c2
-rw-r--r--drivers/usb/dwc3/dwc3-of-simple.c2
-rw-r--r--drivers/usb/dwc3/dwc3-omap.c4
-rw-r--r--drivers/usb/dwc3/dwc3-qcom.c4
-rw-r--r--drivers/usb/dwc3/dwc3-rtk.c2
-rw-r--r--drivers/usb/dwc3/dwc3-st.c2
-rw-r--r--drivers/usb/dwc3/dwc3-xilinx.c7
-rw-r--r--drivers/usb/dwc3/ep0.c4
-rw-r--r--drivers/usb/dwc3/gadget.c152
-rw-r--r--drivers/usb/dwc3/host.c2
-rw-r--r--drivers/usb/fotg210/fotg210-core.c2
-rw-r--r--drivers/usb/gadget/composite.c30
-rw-r--r--drivers/usb/gadget/config.c4
-rw-r--r--drivers/usb/gadget/configfs.c2
-rw-r--r--drivers/usb/gadget/function/Makefile4
-rw-r--r--drivers/usb/gadget/function/f_fs.c8
-rw-r--r--drivers/usb/gadget/function/f_mass_storage.c8
-rw-r--r--drivers/usb/gadget/function/f_midi.c8
-rw-r--r--drivers/usb/gadget/function/f_midi2.c10
-rw-r--r--drivers/usb/gadget/function/f_uvc.c4
-rw-r--r--drivers/usb/gadget/function/u_serial.c9
-rw-r--r--drivers/usb/gadget/function/uvc.h13
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.c348
-rw-r--r--drivers/usb/gadget/function/uvc_configfs.h16
-rw-r--r--drivers/usb/gadget/function/uvc_queue.c26
-rw-r--r--drivers/usb/gadget/function/uvc_queue.h2
-rw-r--r--drivers/usb/gadget/function/uvc_trace.c11
-rw-r--r--drivers/usb/gadget/function/uvc_trace.h60
-rw-r--r--drivers/usb/gadget/function/uvc_v4l2.c66
-rw-r--r--drivers/usb/gadget/function/uvc_video.c268
-rw-r--r--drivers/usb/gadget/legacy/hid.c2
-rw-r--r--drivers/usb/gadget/legacy/raw_gadget.c4
-rw-r--r--drivers/usb/gadget/udc/aspeed-vhub/core.c2
-rw-r--r--drivers/usb/gadget/udc/aspeed_udc.c4
-rw-r--r--drivers/usb/gadget/udc/at91_udc.c2
-rw-r--r--drivers/usb/gadget/udc/atmel_usba_udc.c2
-rw-r--r--drivers/usb/gadget/udc/bcm63xx_udc.c2
-rw-r--r--drivers/usb/gadget/udc/bdc/bdc_core.c2
-rw-r--r--drivers/usb/gadget/udc/cdns2/cdns2-pci.c3
-rw-r--r--drivers/usb/gadget/udc/dummy_hcd.c6
-rw-r--r--drivers/usb/gadget/udc/fsl_qe_udc.c8
-rw-r--r--drivers/usb/gadget/udc/fsl_udc_core.c2
-rw-r--r--drivers/usb/gadget/udc/fusb300_udc.c4
-rw-r--r--drivers/usb/gadget/udc/gr_udc.c2
-rw-r--r--drivers/usb/gadget/udc/lpc32xx_udc.c2
-rw-r--r--drivers/usb/gadget/udc/m66592-udc.c2
-rw-r--r--drivers/usb/gadget/udc/mv_u3d_core.c2
-rw-r--r--drivers/usb/gadget/udc/mv_udc_core.c2
-rw-r--r--drivers/usb/gadget/udc/net2272.c4
-rw-r--r--drivers/usb/gadget/udc/omap_udc.c6
-rw-r--r--drivers/usb/gadget/udc/pxa25x_udc.c2
-rw-r--r--drivers/usb/gadget/udc/pxa27x_udc.c2
-rw-r--r--drivers/usb/gadget/udc/r8a66597-udc.c2
-rw-r--r--drivers/usb/gadget/udc/renesas_usb3.c2
-rw-r--r--drivers/usb/gadget/udc/renesas_usbf.c4
-rw-r--r--drivers/usb/gadget/udc/rzv2m_usb3drd.c2
-rw-r--r--drivers/usb/gadget/udc/snps_udc_core.c2
-rw-r--r--drivers/usb/gadget/udc/snps_udc_plat.c2
-rw-r--r--drivers/usb/gadget/udc/tegra-xudc.c2
-rw-r--r--drivers/usb/gadget/udc/udc-xilinx.c2
-rw-r--r--drivers/usb/gadget/usbstring.c2
-rw-r--r--drivers/usb/host/bcma-hcd.c1
-rw-r--r--drivers/usb/host/ehci-atmel.c2
-rw-r--r--drivers/usb/host/ehci-brcm.c2
-rw-r--r--drivers/usb/host/ehci-exynos.c2
-rw-r--r--drivers/usb/host/ehci-fsl.c2
-rw-r--r--drivers/usb/host/ehci-grlib.c2
-rw-r--r--drivers/usb/host/ehci-hcd.c2
-rw-r--r--drivers/usb/host/ehci-mv.c2
-rw-r--r--drivers/usb/host/ehci-npcm7xx.c2
-rw-r--r--drivers/usb/host/ehci-omap.c2
-rw-r--r--drivers/usb/host/ehci-orion.c2
-rw-r--r--drivers/usb/host/ehci-platform.c2
-rw-r--r--drivers/usb/host/ehci-ppc-of.c2
-rw-r--r--drivers/usb/host/ehci-sh.c11
-rw-r--r--drivers/usb/host/ehci-spear.c9
-rw-r--r--drivers/usb/host/ehci-st.c2
-rw-r--r--drivers/usb/host/ehci-xilinx-of.c2
-rw-r--r--drivers/usb/host/fhci-hcd.c2
-rw-r--r--drivers/usb/host/fhci-sched.c4
-rw-r--r--drivers/usb/host/fsl-mph-dr-of.c2
-rw-r--r--drivers/usb/host/isp116x-hcd.c2
-rw-r--r--drivers/usb/host/isp1362-hcd.c2
-rw-r--r--drivers/usb/host/max3421-hcd.c16
-rw-r--r--drivers/usb/host/octeon-hcd.c6
-rw-r--r--drivers/usb/host/ohci-at91.c2
-rw-r--r--drivers/usb/host/ohci-da8xx.c2
-rw-r--r--drivers/usb/host/ohci-exynos.c2
-rw-r--r--drivers/usb/host/ohci-nxp.c2
-rw-r--r--drivers/usb/host/ohci-omap.c4
-rw-r--r--drivers/usb/host/ohci-platform.c2
-rw-r--r--drivers/usb/host/ohci-ppc-of.c2
-rw-r--r--drivers/usb/host/ohci-pxa27x.c2
-rw-r--r--drivers/usb/host/ohci-s3c2410.c2
-rw-r--r--drivers/usb/host/ohci-sm501.c2
-rw-r--r--drivers/usb/host/ohci-spear.c2
-rw-r--r--drivers/usb/host/ohci-st.c2
-rw-r--r--drivers/usb/host/oxu210hp-hcd.c8
-rw-r--r--drivers/usb/host/r8a66597-hcd.c6
-rw-r--r--drivers/usb/host/sl811-hcd.c2
-rw-r--r--drivers/usb/host/uhci-grlib.c2
-rw-r--r--drivers/usb/host/uhci-platform.c2
-rw-r--r--drivers/usb/host/xhci-dbgcap.c13
-rw-r--r--drivers/usb/host/xhci-debugfs.c10
-rw-r--r--drivers/usb/host/xhci-histb.c2
-rw-r--r--drivers/usb/host/xhci-hub.c6
-rw-r--r--drivers/usb/host/xhci-mem.c235
-rw-r--r--drivers/usb/host/xhci-mtk.c2
-rw-r--r--drivers/usb/host/xhci-pci-renesas.c2
-rw-r--r--drivers/usb/host/xhci-pci.c49
-rw-r--r--drivers/usb/host/xhci-plat.c2
-rw-r--r--drivers/usb/host/xhci-rcar.c2
-rw-r--r--drivers/usb/host/xhci-ring.c302
-rw-r--r--drivers/usb/host/xhci-tegra.c2
-rw-r--r--drivers/usb/host/xhci-trace.h79
-rw-r--r--drivers/usb/host/xhci.c123
-rw-r--r--drivers/usb/host/xhci.h51
-rw-r--r--drivers/usb/isp1760/Kconfig2
-rw-r--r--drivers/usb/isp1760/isp1760-if.c2
-rw-r--r--drivers/usb/misc/chaoskey.c35
-rw-r--r--drivers/usb/misc/iowarrior.c50
-rw-r--r--drivers/usb/misc/onboard_usb_dev.c6
-rw-r--r--drivers/usb/misc/qcom_eud.c2
-rw-r--r--drivers/usb/misc/usb-ljca.c28
-rw-r--r--drivers/usb/misc/usb3503.c2
-rw-r--r--drivers/usb/misc/usbtest.c3
-rw-r--r--drivers/usb/misc/yurex.c5
-rw-r--r--drivers/usb/mon/mon_bin.c2
-rw-r--r--drivers/usb/mtu3/Kconfig2
-rw-r--r--drivers/usb/mtu3/mtu3_plat.c4
-rw-r--r--drivers/usb/musb/Kconfig2
-rw-r--r--drivers/usb/musb/da8xx.c2
-rw-r--r--drivers/usb/musb/jz4740.c2
-rw-r--r--drivers/usb/musb/mediatek.c2
-rw-r--r--drivers/usb/musb/mpfs.c2
-rw-r--r--drivers/usb/musb/musb_core.c4
-rw-r--r--drivers/usb/musb/musb_dsps.c2
-rw-r--r--drivers/usb/musb/musb_gadget.c13
-rw-r--r--drivers/usb/musb/musb_gadget_ep0.c2
-rw-r--r--drivers/usb/musb/musb_host.c5
-rw-r--r--drivers/usb/musb/omap2430.c2
-rw-r--r--drivers/usb/musb/sunxi.c2
-rw-r--r--drivers/usb/musb/tusb6010.c2
-rw-r--r--drivers/usb/musb/ux500.c2
-rw-r--r--drivers/usb/phy/phy-ab8500-usb.c2
-rw-r--r--drivers/usb/phy/phy-am335x.c2
-rw-r--r--drivers/usb/phy/phy-fsl-usb.c2
-rw-r--r--drivers/usb/phy/phy-generic.c2
-rw-r--r--drivers/usb/phy/phy-gpio-vbus-usb.c2
-rw-r--r--drivers/usb/phy/phy-isp1301.c2
-rw-r--r--drivers/usb/phy/phy-keystone.c2
-rw-r--r--drivers/usb/phy/phy-mv-usb.c2
-rw-r--r--drivers/usb/phy/phy-mxs-usb.c2
-rw-r--r--drivers/usb/phy/phy-tahvo.c2
-rw-r--r--drivers/usb/phy/phy-tegra-usb.c2
-rw-r--r--drivers/usb/phy/phy-twl6030-usb.c2
-rw-r--r--drivers/usb/phy/phy.c2
-rw-r--r--drivers/usb/renesas_usbhs/common.c4
-rw-r--r--drivers/usb/roles/intel-xhci-usb-role-switch.c2
-rw-r--r--drivers/usb/serial/bus.c4
-rw-r--r--drivers/usb/serial/ftdi_sio.c2
-rw-r--r--drivers/usb/serial/io_edgeport.c2
-rw-r--r--drivers/usb/serial/option.c27
-rw-r--r--drivers/usb/serial/pl2303.c38
-rw-r--r--drivers/usb/serial/sierra.c2
-rw-r--r--drivers/usb/serial/usb-serial.c4
-rw-r--r--drivers/usb/storage/Makefile2
-rw-r--r--drivers/usb/storage/alauda.c2
-rw-r--r--drivers/usb/storage/cypress_atacb.c2
-rw-r--r--drivers/usb/storage/datafab.c2
-rw-r--r--drivers/usb/storage/ene_ub6250.c10
-rw-r--r--drivers/usb/storage/freecom.c2
-rw-r--r--drivers/usb/storage/isd200.c2
-rw-r--r--drivers/usb/storage/jumpshot.c2
-rw-r--r--drivers/usb/storage/karma.c2
-rw-r--r--drivers/usb/storage/onetouch.c2
-rw-r--r--drivers/usb/storage/realtek_cr.c6
-rw-r--r--drivers/usb/storage/sddr09.c6
-rw-r--r--drivers/usb/storage/sddr55.c10
-rw-r--r--drivers/usb/storage/shuttle_usbat.c2
-rw-r--r--drivers/usb/storage/transport.c2
-rw-r--r--drivers/usb/storage/uas.c2
-rw-r--r--drivers/usb/typec/altmodes/displayport.c2
-rw-r--r--drivers/usb/typec/anx7411.c66
-rw-r--r--drivers/usb/typec/class.c205
-rw-r--r--drivers/usb/typec/class.h3
-rw-r--r--drivers/usb/typec/mux/Kconfig9
-rw-r--r--drivers/usb/typec/mux/Makefile1
-rw-r--r--drivers/usb/typec/mux/gpio-sbu-mux.c2
-rw-r--r--drivers/usb/typec/mux/intel_pmc_mux.c2
-rw-r--r--drivers/usb/typec/mux/tusb1046.c196
-rw-r--r--drivers/usb/typec/stusb160x.c7
-rw-r--r--drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpci_mt6360.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpci_mt6370.c2
-rw-r--r--drivers/usb/typec/tcpm/tcpm.c96
-rw-r--r--drivers/usb/typec/tcpm/wcove.c2
-rw-r--r--drivers/usb/typec/ucsi/debugfs.c1
-rw-r--r--drivers/usb/typec/ucsi/psy.c28
-rw-r--r--drivers/usb/typec/ucsi/trace.h28
-rw-r--r--drivers/usb/typec/ucsi/ucsi.c160
-rw-r--r--drivers/usb/typec/ucsi/ucsi.h241
-rw-r--r--drivers/usb/typec/ucsi/ucsi_acpi.c65
-rw-r--r--drivers/usb/typec/ucsi/ucsi_ccg.c5
-rw-r--r--drivers/usb/typec/ucsi/ucsi_glink.c21
-rw-r--r--drivers/usb/usbip/vhci_hcd.c2
-rw-r--r--drivers/usb/usbip/vudc_main.c2
-rw-r--r--drivers/vdpa/mlx5/net/mlx5_vnet.c4
-rw-r--r--drivers/vfio/cdx/main.c2
-rw-r--r--drivers/vfio/iommufd.c4
-rw-r--r--drivers/vfio/pci/mlx5/cmd.c47
-rw-r--r--drivers/vfio/pci/mlx5/main.c2
-rw-r--r--drivers/vfio/pci/pds/pci_drv.c2
-rw-r--r--drivers/vfio/pci/qat/main.c2
-rw-r--r--drivers/vfio/pci/vfio_pci_core.c17
-rw-r--r--drivers/vfio/platform/vfio_platform.c2
-rw-r--r--drivers/vfio/vfio_main.c2
-rw-r--r--drivers/video/backlight/aat2870_bl.c2
-rw-r--r--drivers/video/backlight/adp5520_bl.c2
-rw-r--r--drivers/video/backlight/da9052_bl.c2
-rw-r--r--drivers/video/backlight/hp680_bl.c2
-rw-r--r--drivers/video/backlight/ktd2801-backlight.c2
-rw-r--r--drivers/video/backlight/led_bl.c2
-rw-r--r--drivers/video/backlight/lm3533_bl.c2
-rw-r--r--drivers/video/backlight/lp8788_bl.c2
-rw-r--r--drivers/video/backlight/mt6370-backlight.c2
-rw-r--r--drivers/video/backlight/pwm_bl.c2
-rw-r--r--drivers/video/backlight/qcom-wled.c2
-rw-r--r--drivers/video/backlight/rt4831-backlight.c2
-rw-r--r--drivers/video/backlight/sky81452-backlight.c2
-rw-r--r--drivers/video/fbdev/Kconfig18
-rw-r--r--drivers/video/fbdev/core/Kconfig3
-rw-r--r--drivers/virt/coco/arm-cca-guest/Kconfig1
-rw-r--r--drivers/virt/coco/efi_secret/efi_secret.c2
-rw-r--r--drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c6
-rw-r--r--drivers/virt/coco/sev-guest/sev-guest.c2
-rw-r--r--drivers/virt/coco/tdx-guest/tdx-guest.c4
-rw-r--r--drivers/virtio/virtio_dma_buf.c2
-rw-r--r--drivers/virtio/virtio_mmio.c2
-rw-r--r--drivers/virtio/virtio_ring.c12
-rw-r--r--drivers/w1/masters/amd_axi_w1.c2
-rw-r--r--drivers/w1/masters/mxc_w1.c2
-rw-r--r--drivers/w1/masters/omap_hdq.c2
-rw-r--r--drivers/w1/masters/sgi_w1.c2
-rw-r--r--drivers/w1/masters/w1-gpio.c2
-rw-r--r--drivers/watchdog/Kconfig17
-rw-r--r--drivers/watchdog/Makefile2
-rw-r--r--drivers/watchdog/acquirewdt.c2
-rw-r--r--drivers/watchdog/advantechwdt.c2
-rw-r--r--drivers/watchdog/airoha_wdt.c216
-rw-r--r--drivers/watchdog/apple_wdt.c8
-rw-r--r--drivers/watchdog/armada_37xx_wdt.c10
-rw-r--r--drivers/watchdog/at91rm9200_wdt.c2
-rw-r--r--drivers/watchdog/at91sam9_wdt.c2
-rw-r--r--drivers/watchdog/ath79_wdt.c2
-rw-r--r--drivers/watchdog/bcm2835_wdt.c2
-rw-r--r--drivers/watchdog/bcm_kona_wdt.c2
-rw-r--r--drivers/watchdog/cpu5wdt.c284
-rw-r--r--drivers/watchdog/cpwd.c2
-rw-r--r--drivers/watchdog/da9055_wdt.c7
-rw-r--r--drivers/watchdog/da9063_wdt.c19
-rw-r--r--drivers/watchdog/dw_wdt.c2
-rw-r--r--drivers/watchdog/gef_wdt.c2
-rw-r--r--drivers/watchdog/geodewdt.c2
-rw-r--r--drivers/watchdog/gxp-wdt.c4
-rw-r--r--drivers/watchdog/iTCO_wdt.c25
-rw-r--r--drivers/watchdog/ib700wdt.c2
-rw-r--r--drivers/watchdog/ie6xx_wdt.c2
-rw-r--r--drivers/watchdog/it87_wdt.c43
-rw-r--r--drivers/watchdog/lpc18xx_wdt.c2
-rw-r--r--drivers/watchdog/menz69_wdt.c2
-rw-r--r--drivers/watchdog/mtk_wdt.c12
-rw-r--r--drivers/watchdog/mtx-1_wdt.c2
-rw-r--r--drivers/watchdog/nic7018_wdt.c2
-rw-r--r--drivers/watchdog/nv_tco.c2
-rw-r--r--drivers/watchdog/octeon-wdt-main.c4
-rw-r--r--drivers/watchdog/omap_wdt.c2
-rw-r--r--drivers/watchdog/orion_wdt.c2
-rw-r--r--drivers/watchdog/pcwd.c2
-rw-r--r--drivers/watchdog/rc32434_wdt.c2
-rw-r--r--drivers/watchdog/rdc321x_wdt.c2
-rw-r--r--drivers/watchdog/renesas_wdt.c2
-rw-r--r--drivers/watchdog/riowd.c2
-rw-r--r--drivers/watchdog/rti_wdt.c9
-rw-r--r--drivers/watchdog/rza_wdt.c7
-rw-r--r--drivers/watchdog/rzg2l_wdt.c20
-rw-r--r--drivers/watchdog/rzn1_wdt.c2
-rw-r--r--drivers/watchdog/s3c2410_wdt.c45
-rw-r--r--drivers/watchdog/sa1100_wdt.c4
-rw-r--r--drivers/watchdog/sch311x_wdt.c2
-rw-r--r--drivers/watchdog/shwdt.c2
-rw-r--r--drivers/watchdog/sl28cpld_wdt.c4
-rw-r--r--drivers/watchdog/smsc37b787_wdt.c2
-rw-r--r--drivers/watchdog/st_lpc_wdt.c2
-rw-r--r--drivers/watchdog/starfive-wdt.c4
-rw-r--r--drivers/watchdog/stm32_iwdg.c95
-rw-r--r--drivers/watchdog/stmp3xxx_rtc_wdt.c2
-rw-r--r--drivers/watchdog/txx9wdt.c2
-rw-r--r--drivers/watchdog/watchdog_core.c26
-rw-r--r--drivers/watchdog/xilinx_wwdt.c75
-rw-r--r--drivers/watchdog/ziirave_wdt.c2
-rw-r--r--drivers/xen/gntdev-dmabuf.c2
-rw-r--r--drivers/xen/grant-dma-iommu.c2
-rw-r--r--fs/9p/v9fs.c21
-rw-r--r--fs/9p/vfs_addr.c6
-rw-r--r--fs/afs/write.c5
-rw-r--r--fs/btrfs/bio.c33
-rw-r--r--fs/btrfs/ctree.c17
-rw-r--r--fs/btrfs/ctree.h19
-rw-r--r--fs/btrfs/disk-io.c9
-rw-r--r--fs/btrfs/extent-tree.c8
-rw-r--r--fs/btrfs/file.c1
-rw-r--r--fs/btrfs/inode.c171
-rw-r--r--fs/btrfs/ioctl.c132
-rw-r--r--fs/btrfs/locking.h10
-rw-r--r--fs/btrfs/qgroup.c3
-rw-r--r--fs/btrfs/ref-verify.c1
-rw-r--r--fs/btrfs/relocation.c6
-rw-r--r--fs/btrfs/scrub.c4
-rw-r--r--fs/btrfs/send.c6
-rw-r--r--fs/btrfs/super.c66
-rw-r--r--fs/btrfs/sysfs.c10
-rw-r--r--fs/btrfs/tree-checker.c27
-rw-r--r--fs/btrfs/zlib.c4
-rw-r--r--fs/btrfs/zoned.c5
-rw-r--r--fs/cachefiles/daemon.c14
-rw-r--r--fs/cachefiles/internal.h3
-rw-r--r--fs/cachefiles/security.c6
-rw-r--r--fs/ceph/addr.c2
-rw-r--r--fs/ceph/caps.c63
-rw-r--r--fs/ceph/crypto.h2
-rw-r--r--fs/ceph/debugfs.c2
-rw-r--r--fs/ceph/dir.c4
-rw-r--r--fs/ceph/export.c12
-rw-r--r--fs/ceph/file.c77
-rw-r--r--fs/ceph/inode.c2
-rw-r--r--fs/ceph/mds_client.c36
-rw-r--r--fs/ceph/mds_client.h2
-rw-r--r--fs/ceph/super.c14
-rw-r--r--fs/ceph/super.h3
-rw-r--r--fs/ceph/xattr.c2
-rw-r--r--fs/efivarfs/inode.c2
-rw-r--r--fs/efivarfs/internal.h1
-rw-r--r--fs/efivarfs/super.c3
-rw-r--r--fs/efivarfs/vars.c2
-rw-r--r--fs/erofs/data.c36
-rw-r--r--fs/erofs/fileio.c9
-rw-r--r--fs/erofs/fscache.c10
-rw-r--r--fs/erofs/internal.h15
-rw-r--r--fs/erofs/super.c78
-rw-r--r--fs/erofs/zdata.c4
-rw-r--r--fs/erofs/zutil.c7
-rw-r--r--fs/exfat/dir.c3
-rw-r--r--fs/exfat/fatent.c10
-rw-r--r--fs/exfat/file.c6
-rw-r--r--fs/exfat/namei.c4
-rw-r--r--fs/file.c1
-rw-r--r--fs/fuse/dir.c2
-rw-r--r--fs/hfs/super.c4
-rw-r--r--fs/hostfs/hostfs_kern.c5
-rw-r--r--fs/hugetlbfs/inode.c4
-rw-r--r--fs/iomap/buffered-io.c66
-rw-r--r--fs/jbd2/commit.c4
-rw-r--r--fs/jbd2/revoke.c2
-rw-r--r--fs/jffs2/compr_rtime.c3
-rw-r--r--fs/jffs2/compr_rubin.c5
-rw-r--r--fs/jffs2/erase.c7
-rw-r--r--fs/jffs2/gc.c2
-rw-r--r--fs/jffs2/nodemgmt.c17
-rw-r--r--fs/jffs2/readinode.c2
-rw-r--r--fs/namespace.c10
-rw-r--r--fs/netfs/buffered_read.c28
-rw-r--r--fs/netfs/direct_write.c1
-rw-r--r--fs/netfs/read_collect.c33
-rw-r--r--fs/netfs/read_pgpriv2.c4
-rw-r--r--fs/netfs/read_retry.c8
-rw-r--r--fs/netfs/write_collect.c14
-rw-r--r--fs/netfs/write_issue.c2
-rw-r--r--fs/nfs/blocklayout/blocklayout.c15
-rw-r--r--fs/nfs/blocklayout/dev.c6
-rw-r--r--fs/nfs/client.c64
-rw-r--r--fs/nfs/direct.c21
-rw-r--r--fs/nfs/file.c14
-rw-r--r--fs/nfs/fs_context.c6
-rw-r--r--fs/nfs/fscache.c9
-rw-r--r--fs/nfs/internal.h9
-rw-r--r--fs/nfs/io.c44
-rw-r--r--fs/nfs/localio.c96
-rw-r--r--fs/nfs/namespace.c2
-rw-r--r--fs/nfs/nfs.h4
-rw-r--r--fs/nfs/nfs4proc.c8
-rw-r--r--fs/nfs/nfs4state.c10
-rw-r--r--fs/nfs/pnfs.c2
-rw-r--r--fs/nfs/super.c1
-rw-r--r--fs/nfs/write.c55
-rw-r--r--fs/nfsd/export.c31
-rw-r--r--fs/nfsd/export.h4
-rw-r--r--fs/nfsd/nfs4callback.c4
-rw-r--r--fs/nfsd/nfs4proc.c13
-rw-r--r--fs/nilfs2/btnode.c1
-rw-r--r--fs/nilfs2/dir.c2
-rw-r--r--fs/nilfs2/gcinode.c2
-rw-r--r--fs/nilfs2/inode.c13
-rw-r--r--fs/nilfs2/namei.c5
-rw-r--r--fs/nilfs2/nilfs.h1
-rw-r--r--fs/notify/fdinfo.c4
-rw-r--r--fs/ocfs2/dlmglue.c1
-rw-r--r--fs/ocfs2/localalloc.c27
-rw-r--r--fs/ocfs2/namei.c4
-rw-r--r--fs/ocfs2/quota_global.c2
-rw-r--r--fs/ocfs2/quota_local.c1
-rw-r--r--fs/overlayfs/copy_up.c16
-rw-r--r--fs/overlayfs/export.c49
-rw-r--r--fs/overlayfs/namei.c4
-rw-r--r--fs/overlayfs/overlayfs.h2
-rw-r--r--fs/proc/task_mmu.c2
-rw-r--r--fs/proc/vmcore.c56
-rw-r--r--fs/pstore/ram.c2
-rw-r--r--fs/qnx6/inode.c11
-rw-r--r--fs/quota/dquot.c2
-rw-r--r--fs/smb/client/Kconfig1
-rw-r--r--fs/smb/client/cached_dir.c170
-rw-r--r--fs/smb/client/cached_dir.h6
-rw-r--r--fs/smb/client/cifsfs.c15
-rw-r--r--fs/smb/client/cifsfs.h4
-rw-r--r--fs/smb/client/cifsglob.h4
-rw-r--r--fs/smb/client/cifsproto.h7
-rw-r--r--fs/smb/client/cifssmb.c28
-rw-r--r--fs/smb/client/connect.c106
-rw-r--r--fs/smb/client/dfs.c193
-rw-r--r--fs/smb/client/dfs_cache.c4
-rw-r--r--fs/smb/client/file.c6
-rw-r--r--fs/smb/client/fs_context.c85
-rw-r--r--fs/smb/client/fs_context.h1
-rw-r--r--fs/smb/client/inode.c103
-rw-r--r--fs/smb/client/readdir.c54
-rw-r--r--fs/smb/client/reparse.c241
-rw-r--r--fs/smb/client/reparse.h4
-rw-r--r--fs/smb/client/sess.c34
-rw-r--r--fs/smb/client/smb1ops.c4
-rw-r--r--fs/smb/client/smb2file.c21
-rw-r--r--fs/smb/client/smb2inode.c9
-rw-r--r--fs/smb/client/smb2ops.c14
-rw-r--r--fs/smb/client/smb2pdu.c34
-rw-r--r--fs/smb/client/smb2proto.h9
-rw-r--r--fs/smb/client/trace.h3
-rw-r--r--fs/smb/common/smb2pdu.h9
-rw-r--r--fs/smb/server/asn1.c6
-rw-r--r--fs/smb/server/auth.c21
-rw-r--r--fs/smb/server/connection.c25
-rw-r--r--fs/smb/server/connection.h1
-rw-r--r--fs/smb/server/crypto_ctx.c6
-rw-r--r--fs/smb/server/glob.h2
-rw-r--r--fs/smb/server/ksmbd_work.c10
-rw-r--r--fs/smb/server/mgmt/ksmbd_ida.c11
-rw-r--r--fs/smb/server/mgmt/share_config.c10
-rw-r--r--fs/smb/server/mgmt/tree_connect.c5
-rw-r--r--fs/smb/server/mgmt/user_config.c8
-rw-r--r--fs/smb/server/mgmt/user_session.c16
-rw-r--r--fs/smb/server/misc.c11
-rw-r--r--fs/smb/server/ndr.c10
-rw-r--r--fs/smb/server/oplock.c12
-rw-r--r--fs/smb/server/server.c19
-rw-r--r--fs/smb/server/server.h1
-rw-r--r--fs/smb/server/smb2pdu.c133
-rw-r--r--fs/smb/server/smb_common.c8
-rw-r--r--fs/smb/server/smbacl.c23
-rw-r--r--fs/smb/server/transport_ipc.c11
-rw-r--r--fs/smb/server/transport_rdma.c13
-rw-r--r--fs/smb/server/transport_tcp.c18
-rw-r--r--fs/smb/server/unicode.c4
-rw-r--r--fs/smb/server/vfs.c12
-rw-r--r--fs/smb/server/vfs.h1
-rw-r--r--fs/smb/server/vfs_cache.c10
-rw-r--r--fs/sysfs/file.c30
-rw-r--r--fs/sysfs/group.c5
-rw-r--r--fs/sysfs/sysfs.h2
-rw-r--r--fs/ubifs/ioctl.c6
-rw-r--r--fs/ubifs/journal.c13
-rw-r--r--fs/ubifs/lpt_commit.c4
-rw-r--r--fs/ubifs/orphan.c2
-rw-r--r--fs/ubifs/super.c8
-rw-r--r--fs/ubifs/tnc.c2
-rw-r--r--fs/ubifs/tnc_commit.c2
-rw-r--r--fs/ubifs/ubifs.h3
-rw-r--r--fs/ubifs/xattr.c45
-rw-r--r--fs/udf/namei.c16
-rw-r--r--fs/unicode/mkutf8data.c70
-rw-r--r--fs/unicode/utf8data.c_shipped6703
-rw-r--r--fs/xfs/libxfs/xfs_bmap.c6
-rw-r--r--fs/xfs/libxfs/xfs_btree.c33
-rw-r--r--fs/xfs/libxfs/xfs_btree.h2
-rw-r--r--fs/xfs/libxfs/xfs_ialloc.c16
-rw-r--r--fs/xfs/libxfs/xfs_ialloc_btree.c4
-rw-r--r--fs/xfs/libxfs/xfs_rtgroup.c2
-rw-r--r--fs/xfs/libxfs/xfs_sb.c18
-rw-r--r--fs/xfs/libxfs/xfs_symlink_remote.c4
-rw-r--r--fs/xfs/scrub/agheader.c77
-rw-r--r--fs/xfs/scrub/agheader_repair.c6
-rw-r--r--fs/xfs/scrub/fscounters.c2
-rw-r--r--fs/xfs/scrub/health.c57
-rw-r--r--fs/xfs/scrub/ialloc.c4
-rw-r--r--fs/xfs/scrub/metapath.c68
-rw-r--r--fs/xfs/scrub/refcount.c2
-rw-r--r--fs/xfs/scrub/scrub.h6
-rw-r--r--fs/xfs/scrub/symlink_repair.c3
-rw-r--r--fs/xfs/scrub/tempfile.c22
-rw-r--r--fs/xfs/scrub/trace.h2
-rw-r--r--fs/xfs/xfs_attr_list.c3
-rw-r--r--fs/xfs/xfs_bmap_util.c2
-rw-r--r--fs/xfs/xfs_dquot.c195
-rw-r--r--fs/xfs/xfs_dquot.h6
-rw-r--r--fs/xfs/xfs_dquot_item.c51
-rw-r--r--fs/xfs/xfs_dquot_item.h7
-rw-r--r--fs/xfs/xfs_exchrange.c14
-rw-r--r--fs/xfs/xfs_file.c8
-rw-r--r--fs/xfs/xfs_fsmap.c38
-rw-r--r--fs/xfs/xfs_inode.h2
-rw-r--r--fs/xfs/xfs_log.c11
-rw-r--r--fs/xfs/xfs_log_cil.c5
-rw-r--r--fs/xfs/xfs_log_priv.h1
-rw-r--r--fs/xfs/xfs_qm.c102
-rw-r--r--fs/xfs/xfs_qm.h1
-rw-r--r--fs/xfs/xfs_qm_syscalls.c13
-rw-r--r--fs/xfs/xfs_quota.h5
-rw-r--r--fs/xfs/xfs_rtalloc.c2
-rw-r--r--fs/xfs/xfs_trans.c56
-rw-r--r--fs/xfs/xfs_trans_ail.c2
-rw-r--r--fs/xfs/xfs_trans_dquot.c31
-rw-r--r--include/asm-generic/delay.h4
-rw-r--r--include/asm-generic/vmlinux.lds.h53
-rw-r--r--include/clocksource/hyperv_timer.h2
-rw-r--r--include/drm/display/drm_dp_mst_helper.h7
-rw-r--r--include/dt-bindings/iio/adc/gehc,pmc-adc.h10
-rw-r--r--include/dt-bindings/interconnect/qcom,qcs615-rpmh.h136
-rw-r--r--include/dt-bindings/interconnect/qcom,qcs8300-rpmh.h189
-rw-r--r--include/dt-bindings/interconnect/qcom,sar2130p-rpmh.h137
-rw-r--r--include/kunit/visibility.h5
-rw-r--r--include/kvm/arm_vgic.h1
-rw-r--r--include/linux/acpi.h2
-rw-r--r--include/linux/alcor_pci.h1
-rw-r--r--include/linux/alloc_tag.h9
-rw-r--r--include/linux/amba/bus.h5
-rw-r--r--include/linux/arm_ffa.h13
-rw-r--r--include/linux/auxiliary_bus.h4
-rw-r--r--include/linux/bio.h2
-rw-r--r--include/linux/blkdev.h25
-rw-r--r--include/linux/bpf.h32
-rw-r--r--include/linux/bpf_verifier.h1
-rw-r--r--include/linux/cacheinfo.h6
-rw-r--r--include/linux/ceph/ceph_fs.h4
-rw-r--r--include/linux/ceph/libceph.h6
-rw-r--r--include/linux/ceph/osd_client.h2
-rw-r--r--include/linux/ceph/pagelist.h12
-rw-r--r--include/linux/cleanup.h14
-rw-r--r--include/linux/clocksource.h2
-rw-r--r--include/linux/compiler.h37
-rw-r--r--include/linux/dmaengine.h13
-rw-r--r--include/linux/dsa/ocelot.h1
-rw-r--r--include/linux/eeprom_93cx6.h11
-rw-r--r--include/linux/etherdevice.h18
-rw-r--r--include/linux/ethtool.h10
-rw-r--r--include/linux/export.h6
-rw-r--r--include/linux/filter.h11
-rw-r--r--include/linux/fortify-string.h14
-rw-r--r--include/linux/fw_table.h2
-rw-r--r--include/linux/hid-sensor-ids.h2
-rw-r--r--include/linux/hid_bpf.h2
-rw-r--r--include/linux/highmem.h8
-rw-r--r--include/linux/hyperv.h1
-rw-r--r--include/linux/i2c-of-prober.h140
-rw-r--r--include/linux/if_vlan.h57
-rw-r--r--include/linux/igmp.h2
-rw-r--r--include/linux/iio/backend.h17
-rw-r--r--include/linux/iio/driver.h5
-rw-r--r--include/linux/iio/events.h31
-rw-r--r--include/linux/iio/iio-opaque.h2
-rw-r--r--include/linux/iio/iio.h36
-rw-r--r--include/linux/io_uring.h4
-rw-r--r--include/linux/io_uring/cmd.h14
-rw-r--r--include/linux/io_uring_types.h3
-rw-r--r--include/linux/iomap.h2
-rw-r--r--include/linux/kfifo.h1
-rw-r--r--include/linux/ktime.h5
-rw-r--r--include/linux/list.h8
-rw-r--r--include/linux/memfd.h14
-rw-r--r--include/linux/mfd/88pm886.h9
-rw-r--r--include/linux/mfd/da9063/core.h1
-rw-r--r--include/linux/misc/keba.h47
-rw-r--r--include/linux/mlx5/driver.h8
-rw-r--r--include/linux/mlx5/fs.h4
-rw-r--r--include/linux/mlx5/mlx5_ifc.h63
-rw-r--r--include/linux/mm.h90
-rw-r--r--include/linux/mm_types.h30
-rw-r--r--include/linux/mmdebug.h6
-rw-r--r--include/linux/module.h4
-rw-r--r--include/linux/net_tstamp.h29
-rw-r--r--include/linux/netdev_features.h7
-rw-r--r--include/linux/netdevice.h69
-rw-r--r--include/linux/netfilter/x_tables.h2
-rw-r--r--include/linux/netfilter_netdev.h3
-rw-r--r--include/linux/netfs.h7
-rw-r--r--include/linux/nfs_xdr.h2
-rw-r--r--include/linux/nvme.h14
-rw-r--r--include/linux/of.h13
-rw-r--r--include/linux/once.h4
-rw-r--r--include/linux/once_lite.h2
-rw-r--r--include/linux/packing.h425
-rw-r--r--include/linux/page-flags.h16
-rw-r--r--include/linux/pci.h14
-rw-r--r--include/linux/pci_ids.h4
-rw-r--r--include/linux/pcs/pcs-xpcs.h1
-rw-r--r--include/linux/percpu-defs.h5
-rw-r--r--include/linux/pgalloc_tag.h4
-rw-r--r--include/linux/phy.h26
-rw-r--r--include/linux/phylink.h3
-rw-r--r--include/linux/platform_data/amd_qdma.h2
-rw-r--r--include/linux/platform_data/sa11x0-serial.h1
-rw-r--r--include/linux/platform_device.h12
-rw-r--r--include/linux/pm.h2
-rw-r--r--include/linux/ptp_clock_kernel.h4
-rw-r--r--include/linux/ptr_ring.h21
-rw-r--r--include/linux/pwm.h2
-rw-r--r--include/linux/rcupdate.h2
-rw-r--r--include/linux/rcupdate_trace.h5
-rw-r--r--include/linux/rfkill.h2
-rw-r--r--include/linux/rtc/m48t59.h3
-rw-r--r--include/linux/rtnetlink.h14
-rw-r--r--include/linux/rtsx_common.h1
-rw-r--r--include/linux/rtsx_usb.h4
-rw-r--r--include/linux/scatterlist.h2
-rw-r--r--include/linux/sched.h10
-rw-r--r--include/linux/skb_array.h17
-rw-r--r--include/linux/skbuff.h65
-rw-r--r--include/linux/skmsg.h11
-rw-r--r--include/linux/stackdepot.h6
-rw-r--r--include/linux/static_call.h6
-rw-r--r--include/linux/stmmac.h10
-rw-r--r--include/linux/string.h1
-rw-r--r--include/linux/sysfs.h99
-rw-r--r--include/linux/trace_events.h9
-rw-r--r--include/linux/tracepoint.h82
-rw-r--r--include/linux/types.h3
-rw-r--r--include/linux/usb.h7
-rw-r--r--include/linux/usb/chipidea.h1
-rw-r--r--include/linux/usb/storage.h2
-rw-r--r--include/linux/usb/typec.h22
-rw-r--r--include/linux/vermagic.h6
-rw-r--r--include/linux/virtio.h6
-rw-r--r--include/linux/vmstat.h2
-rw-r--r--include/linux/ww_mutex.h4
-rw-r--r--include/linux/wwan.h2
-rw-r--r--include/net/addrconf.h24
-rw-r--r--include/net/ax25.h10
-rw-r--r--include/net/bluetooth/bluetooth.h10
-rw-r--r--include/net/bluetooth/hci_core.h108
-rw-r--r--include/net/cfg80211.h8
-rw-r--r--include/net/devlink.h24
-rw-r--r--include/net/dropreason-core.h54
-rw-r--r--include/net/dsa.h4
-rw-r--r--include/net/dst.h11
-rw-r--r--include/net/genetlink.h6
-rw-r--r--include/net/inet_connection_sock.h2
-rw-r--r--include/net/inet_sock.h8
-rw-r--r--include/net/inet_timewait_sock.h6
-rw-r--r--include/net/inetpeer.h12
-rw-r--r--include/net/ip.h2
-rw-r--r--include/net/ipv6.h2
-rw-r--r--include/net/iucv/iucv.h30
-rw-r--r--include/net/lapb.h2
-rw-r--r--include/net/mac80211.h9
-rw-r--r--include/net/net_debug.h2
-rw-r--r--include/net/net_namespace.h6
-rw-r--r--include/net/netfilter/nf_tables.h11
-rw-r--r--include/net/netfilter/nf_tables_core.h1
-rw-r--r--include/net/netfilter/nf_tproxy.h4
-rw-r--r--include/net/netlink.h44
-rw-r--r--include/net/netmem.h78
-rw-r--r--include/net/netns/ipv4.h1
-rw-r--r--include/net/page_pool/helpers.h82
-rw-r--r--include/net/page_pool/types.h11
-rw-r--r--include/net/pkt_cls.h4
-rw-r--r--include/net/route.h42
-rw-r--r--include/net/sch_generic.h8
-rw-r--r--include/net/sock.h18
-rw-r--r--include/net/tcp.h2
-rw-r--r--include/net/tls.h3
-rw-r--r--include/net/vxlan.h1
-rw-r--r--include/net/xdp.h193
-rw-r--r--include/net/xdp_sock_drv.h29
-rw-r--r--include/net/xsk_buff_pool.h4
-rw-r--r--include/soc/arc/arc_aux.h (renamed from include/soc/arc/aux.h)0
-rw-r--r--include/soc/arc/mcip.h2
-rw-r--r--include/soc/arc/timers.h2
-rw-r--r--include/soc/mscc/ocelot.h2
-rw-r--r--include/sound/cs35l56.h6
-rw-r--r--include/sound/tas2781.h1
-rw-r--r--include/trace/events/damon.h2
-rw-r--r--include/trace/events/fib6.h8
-rw-r--r--include/trace/events/rxrpc.h878
-rw-r--r--include/trace/events/sunrpc.h4
-rw-r--r--include/uapi/asm-generic/socket.h2
-rw-r--r--include/uapi/linux/ethtool_netlink.h893
-rw-r--r--include/uapi/linux/ethtool_netlink_generated.h818
-rw-r--r--include/uapi/linux/fib_rules.h2
-rw-r--r--include/uapi/linux/if_link.h3
-rw-r--r--include/uapi/linux/iio/types.h1
-rw-r--r--include/uapi/linux/io_uring.h14
-rw-r--r--include/uapi/linux/iommufd.h31
-rw-r--r--include/uapi/linux/mptcp_pm.h50
-rw-r--r--include/uapi/linux/net_tstamp.h11
-rw-r--r--include/uapi/linux/rtnetlink.h19
-rw-r--r--include/uapi/linux/snmp.h5
-rw-r--r--include/uapi/linux/stddef.h13
-rw-r--r--include/uapi/linux/thermal.h4
-rw-r--r--include/uapi/linux/types.h1
-rw-r--r--include/uapi/linux/usb/video.h58
-rw-r--r--include/ufs/ufshcd.h12
-rw-r--r--io_uring/io_uring.c94
-rw-r--r--io_uring/io_uring.h9
-rw-r--r--io_uring/kbuf.c4
-rw-r--r--io_uring/memmap.c13
-rw-r--r--io_uring/net.c1
-rw-r--r--io_uring/nop.c6
-rw-r--r--io_uring/opdef.c3
-rw-r--r--io_uring/register.c6
-rw-r--r--io_uring/rsrc.c6
-rw-r--r--io_uring/rw.c2
-rw-r--r--io_uring/sqpoll.c6
-rw-r--r--io_uring/tctx.c13
-rw-r--r--io_uring/timeout.c85
-rw-r--r--io_uring/uring_cmd.c25
-rw-r--r--io_uring/uring_cmd.h4
-rw-r--r--kernel/auditsc.c4
-rw-r--r--kernel/bpf/Makefile6
-rw-r--r--kernel/bpf/bpf_lsm.c2
-rw-r--r--kernel/bpf/btf.c149
-rw-r--r--kernel/bpf/core.c8
-rw-r--r--kernel/bpf/cpumap.c2
-rw-r--r--kernel/bpf/devmap.c14
-rw-r--r--kernel/bpf/lpm_trie.c133
-rw-r--r--kernel/bpf/verifier.c193
-rw-r--r--kernel/cpu.c3
-rw-r--r--kernel/dma/debug.c20
-rw-r--r--kernel/fork.c13
-rw-r--r--kernel/futex/futex.h4
-rwxr-xr-xkernel/gen_kheaders.sh1
-rw-r--r--kernel/irq/proc.c7
-rw-r--r--kernel/kcov.c2
-rw-r--r--kernel/locking/rtmutex.c21
-rw-r--r--kernel/locking/rtmutex_api.c2
-rw-r--r--kernel/module/Kconfig2
-rw-r--r--kernel/resource.c2
-rw-r--r--kernel/sched/core.c6
-rw-r--r--kernel/sched/deadline.c11
-rw-r--r--kernel/sched/debug.c1
-rw-r--r--kernel/sched/ext.c4
-rw-r--r--kernel/sched/fair.c87
-rw-r--r--kernel/sched/pelt.c2
-rw-r--r--kernel/sched/sched.h13
-rw-r--r--kernel/sched/syscalls.c2
-rw-r--r--kernel/signal.c7
-rw-r--r--kernel/softirq.c15
-rw-r--r--kernel/static_call_inline.c2
-rw-r--r--kernel/time/clocksource.c11
-rw-r--r--kernel/time/ntp.c2
-rw-r--r--kernel/time/timekeeping.c6
-rw-r--r--kernel/time/timekeeping_internal.h8
-rw-r--r--kernel/trace/bpf_trace.c11
-rw-r--r--kernel/trace/fgraph.c10
-rw-r--r--kernel/trace/ftrace.c8
-rw-r--r--kernel/trace/ring_buffer.c6
-rw-r--r--kernel/trace/trace.c269
-rw-r--r--kernel/trace/trace.h6
-rw-r--r--kernel/trace/trace_eprobe.c5
-rw-r--r--kernel/trace/trace_events.c237
-rw-r--r--kernel/trace/trace_functions.c3
-rw-r--r--kernel/trace/trace_kprobe.c2
-rw-r--r--kernel/trace/trace_output.c20
-rw-r--r--kernel/trace/trace_preemptirq.c43
-rw-r--r--kernel/trace/trace_uprobe.c6
-rw-r--r--kernel/trace/tracing_map.c6
-rw-r--r--kernel/workqueue.c23
-rw-r--r--lib/Kconfig.debug32
-rw-r--r--lib/alloc_tag.c77
-rw-r--r--lib/devres.c6
-rw-r--r--lib/kunit/user_alloc.c2
-rw-r--r--lib/locking-selftest.c4
-rw-r--r--lib/maple_tree.c1
-rw-r--r--lib/packing.c293
-rw-r--r--lib/packing_test.c61
-rw-r--r--lib/stackdepot.c10
-rw-r--r--lib/stackinit_kunit.c1
-rw-r--r--lib/string.c23
-rw-r--r--lib/test_firmware.c2
-rw-r--r--lib/tests/module/Makefile17
-rwxr-xr-xlib/tests/module/gen_test_kallsyms.sh9
-rw-r--r--lib/vsprintf.c23
-rw-r--r--lib/win_minmax.c1
-rw-r--r--mm/damon/core.c10
-rw-r--r--mm/debug.c7
-rw-r--r--mm/filemap.c13
-rw-r--r--mm/gup.c11
-rw-r--r--mm/huge_memory.c19
-rw-r--r--mm/hugetlb.c21
-rw-r--r--mm/internal.h14
-rw-r--r--mm/kasan/kasan_test_c.c2
-rw-r--r--mm/kasan/report.c6
-rw-r--r--mm/khugepaged.c3
-rw-r--r--mm/kmemleak.c2
-rw-r--r--mm/list_lru.c2
-rw-r--r--mm/memblock.c4
-rw-r--r--mm/memcontrol-v1.h2
-rw-r--r--mm/memfd.c2
-rw-r--r--mm/memory.c18
-rw-r--r--mm/mempolicy.c4
-rw-r--r--mm/migrate.c2
-rw-r--r--mm/mmap.c7
-rw-r--r--mm/page_alloc.c6
-rw-r--r--mm/pgtable-generic.c2
-rw-r--r--mm/readahead.c11
-rw-r--r--mm/shmem.c29
-rw-r--r--mm/slub.c21
-rw-r--r--mm/util.c7
-rw-r--r--mm/vma.c7
-rw-r--r--mm/vmalloc.c9
-rw-r--r--mm/vmscan.c9
-rw-r--r--mm/zswap.c19
-rw-r--r--net/802/psnap.c4
-rw-r--r--net/9p/Kconfig4
-rw-r--r--net/9p/trans_usbg.c4
-rw-r--r--net/9p/trans_xen.c9
-rw-r--r--net/ax25/af_ax25.c12
-rw-r--r--net/ax25/ax25_dev.c4
-rw-r--r--net/ax25/ax25_ip.c3
-rw-r--r--net/ax25/ax25_out.c22
-rw-r--r--net/ax25/ax25_route.c2
-rw-r--r--net/batman-adv/translation-table.c58
-rw-r--r--net/bluetooth/hci_core.c10
-rw-r--r--net/bluetooth/hci_event.c33
-rw-r--r--net/bluetooth/hci_sock.c14
-rw-r--r--net/bluetooth/hci_sync.c11
-rw-r--r--net/bluetooth/iso.c75
-rw-r--r--net/bluetooth/l2cap_core.c12
-rw-r--r--net/bluetooth/l2cap_sock.c20
-rw-r--r--net/bluetooth/mgmt.c38
-rw-r--r--net/bluetooth/rfcomm/core.c6
-rw-r--r--net/bluetooth/rfcomm/sock.c9
-rw-r--r--net/bluetooth/rfcomm/tty.c4
-rw-r--r--net/bluetooth/sco.c52
-rw-r--r--net/bpf/test_run.c4
-rw-r--r--net/bridge/br.c7
-rw-r--r--net/bridge/br_arp_nd_proxy.c2
-rw-r--r--net/bridge/br_fdb.c3
-rw-r--r--net/bridge/br_forward.c16
-rw-r--r--net/bridge/br_input.c20
-rw-r--r--net/bridge/br_private.h11
-rw-r--r--net/bridge/br_sysfs_br.c6
-rw-r--r--net/bridge/br_vlan.c44
-rw-r--r--net/can/j1939/transport.c2
-rw-r--r--net/can/raw.c2
-rw-r--r--net/ceph/crypto.c12
-rw-r--r--net/ceph/crypto.h1
-rw-r--r--net/ceph/osd_client.c36
-rw-r--r--net/ceph/pagelist.c38
-rw-r--r--net/ceph/pagevec.c52
-rw-r--r--net/core/dev.c190
-rw-r--r--net/core/dev.h6
-rw-r--r--net/core/dev_ioctl.c47
-rw-r--r--net/core/devmem.c10
-rw-r--r--net/core/fib_rules.c2
-rw-r--r--net/core/filter.c132
-rw-r--r--net/core/link_watch.c11
-rw-r--r--net/core/net_namespace.c20
-rw-r--r--net/core/netdev-genl.c36
-rw-r--r--net/core/netdev_rx_queue.c1
-rw-r--r--net/core/page_pool.c137
-rw-r--r--net/core/pktgen.c7
-rw-r--r--net/core/rtnetlink.c166
-rw-r--r--net/core/skbuff.c2
-rw-r--r--net/core/skmsg.c11
-rw-r--r--net/core/sock.c31
-rw-r--r--net/core/sock_map.c6
-rw-r--r--net/core/timestamping.c52
-rw-r--r--net/core/xdp.c327
-rw-r--r--net/dccp/feat.c6
-rw-r--r--net/devlink/health.c67
-rw-r--r--net/devlink/port.c11
-rw-r--r--net/dsa/port.c16
-rw-r--r--net/dsa/tag.h16
-rw-r--r--net/dsa/tag_ocelot_8021q.c2
-rw-r--r--net/dsa/user.c23
-rw-r--r--net/ethtool/Makefile2
-rw-r--r--net/ethtool/bitset.c48
-rw-r--r--net/ethtool/common.c151
-rw-r--r--net/ethtool/common.h13
-rw-r--r--net/ethtool/ioctl.c3
-rw-r--r--net/ethtool/netlink.c24
-rw-r--r--net/ethtool/netlink.h8
-rw-r--r--net/ethtool/ts.h20
-rw-r--r--net/ethtool/tsconfig.c444
-rw-r--r--net/ethtool/tsinfo.c358
-rw-r--r--net/handshake/handshake-test.c2
-rw-r--r--net/hsr/hsr_device.c19
-rw-r--r--net/hsr/hsr_forward.c2
-rw-r--r--net/hsr/hsr_main.h1
-rw-r--r--net/hsr/hsr_slave.c5
-rw-r--r--net/ipv4/af_inet.c14
-rw-r--r--net/ipv4/datagram.c19
-rw-r--r--net/ipv4/fib_rules.c6
-rw-r--r--net/ipv4/fib_trie.c4
-rw-r--r--net/ipv4/icmp.c12
-rw-r--r--net/ipv4/igmp.c66
-rw-r--r--net/ipv4/inet_connection_sock.c11
-rw-r--r--net/ipv4/inetpeer.c49
-rw-r--r--net/ipv4/ip_fragment.c15
-rw-r--r--net/ipv4/ip_gre.c17
-rw-r--r--net/ipv4/ip_input.c11
-rw-r--r--net/ipv4/ip_output.c20
-rw-r--r--net/ipv4/ip_sockglue.c2
-rw-r--r--net/ipv4/ip_tunnel.c6
-rw-r--r--net/ipv4/ipmr.c2
-rw-r--r--net/ipv4/raw.c2
-rw-r--r--net/ipv4/route.c20
-rw-r--r--net/ipv4/sysctl_net_ipv4.c10
-rw-r--r--net/ipv4/tcp_bpf.c25
-rw-r--r--net/ipv4/tcp_input.c1
-rw-r--r--net/ipv4/tcp_ipv4.c9
-rw-r--r--net/ipv4/tcp_minisocks.c11
-rw-r--r--net/ipv4/tcp_output.c6
-rw-r--r--net/ipv4/udp.c70
-rw-r--r--net/ipv6/addrconf.c47
-rw-r--r--net/ipv6/anycast.c35
-rw-r--r--net/ipv6/fib6_rules.c57
-rw-r--r--net/ipv6/icmp.c6
-rw-r--r--net/ipv6/ila/ila_xlat.c16
-rw-r--r--net/ipv6/ioam6_iptunnel.c73
-rw-r--r--net/ipv6/ip6_output.c9
-rw-r--r--net/ipv6/ip6mr.c2
-rw-r--r--net/ipv6/mcast.c100
-rw-r--r--net/ipv6/ndisc.c8
-rw-r--r--net/ipv6/ping.c1
-rw-r--r--net/ipv6/raw.c3
-rw-r--r--net/ipv6/route.c26
-rw-r--r--net/ipv6/rpl_iptunnel.c46
-rw-r--r--net/ipv6/seg6_iptunnel.c85
-rw-r--r--net/ipv6/udp.c51
-rw-r--r--net/l2tp/l2tp_eth.c9
-rw-r--r--net/l2tp/l2tp_ip.c19
-rw-r--r--net/llc/llc_input.c2
-rw-r--r--net/mac80211/cfg.c33
-rw-r--r--net/mac80211/debugfs.c4
-rw-r--r--net/mac80211/driver-ops.h7
-rw-r--r--net/mac80211/ethtool.c22
-rw-r--r--net/mac80211/ieee80211_i.h51
-rw-r--r--net/mac80211/iface.c48
-rw-r--r--net/mac80211/main.c9
-rw-r--r--net/mac80211/mesh.c6
-rw-r--r--net/mac80211/mlme.c2
-rw-r--r--net/mac80211/rx.c4
-rw-r--r--net/mac80211/tests/elems.c2
-rw-r--r--net/mac80211/tests/mfp.c2
-rw-r--r--net/mac80211/tests/tpe.c2
-rw-r--r--net/mac80211/trace.h10
-rw-r--r--net/mac80211/util.c55
-rw-r--r--net/mac802154/ieee802154_i.h3
-rw-r--r--net/mac802154/iface.c4
-rw-r--r--net/mac802154/tx.c13
-rw-r--r--net/mctp/device.c50
-rw-r--r--net/mctp/route.c36
-rw-r--r--net/mctp/test/route-test.c86
-rw-r--r--net/mptcp/ctrl.c17
-rw-r--r--net/mptcp/options.c7
-rw-r--r--net/mptcp/pm_netlink.c46
-rw-r--r--net/mptcp/pm_userspace.c297
-rw-r--r--net/mptcp/protocol.c23
-rw-r--r--net/mptcp/protocol.h7
-rw-r--r--net/netfilter/ipset/ip_set_core.c5
-rw-r--r--net/netfilter/ipset/ip_set_list_set.c3
-rw-r--r--net/netfilter/ipvs/ip_vs_conn.c4
-rw-r--r--net/netfilter/ipvs/ip_vs_proto.c4
-rw-r--r--net/netfilter/nf_conntrack_core.c5
-rw-r--r--net/netfilter/nf_tables_api.c47
-rw-r--r--net/netfilter/nft_inner.c57
-rw-r--r--net/netfilter/nft_set_hash.c16
-rw-r--r--net/netfilter/nft_socket.c2
-rw-r--r--net/netfilter/xt_IDLETIMER.c52
-rw-r--r--net/netfilter/xt_LED.c4
-rw-r--r--net/netlink/af_netlink.c1
-rw-r--r--net/netrom/nr_route.c6
-rw-r--r--net/packet/af_packet.c30
-rw-r--r--net/psample/psample.c9
-rw-r--r--net/rds/tcp.c39
-rw-r--r--net/rfkill/rfkill-gpio.c2
-rw-r--r--net/rxrpc/Makefile1
-rw-r--r--net/rxrpc/af_rxrpc.c4
-rw-r--r--net/rxrpc/ar-internal.h342
-rw-r--r--net/rxrpc/call_accept.c22
-rw-r--r--net/rxrpc/call_event.c385
-rw-r--r--net/rxrpc/call_object.c66
-rw-r--r--net/rxrpc/conn_client.c26
-rw-r--r--net/rxrpc/conn_event.c40
-rw-r--r--net/rxrpc/conn_object.c14
-rw-r--r--net/rxrpc/input.c706
-rw-r--r--net/rxrpc/input_rack.c418
-rw-r--r--net/rxrpc/insecure.c5
-rw-r--r--net/rxrpc/io_thread.c113
-rw-r--r--net/rxrpc/local_object.c3
-rw-r--r--net/rxrpc/misc.c4
-rw-r--r--net/rxrpc/output.c568
-rw-r--r--net/rxrpc/peer_event.c114
-rw-r--r--net/rxrpc/peer_object.c30
-rw-r--r--net/rxrpc/proc.c61
-rw-r--r--net/rxrpc/protocol.h13
-rw-r--r--net/rxrpc/recvmsg.c18
-rw-r--r--net/rxrpc/rtt.c103
-rw-r--r--net/rxrpc/rxkad.c59
-rw-r--r--net/rxrpc/rxperf.c2
-rw-r--r--net/rxrpc/security.c4
-rw-r--r--net/rxrpc/sendmsg.c100
-rw-r--r--net/rxrpc/sysctl.c6
-rw-r--r--net/rxrpc/txbuf.c127
-rw-r--r--net/sched/cls_flow.c3
-rw-r--r--net/sched/cls_flower.c5
-rw-r--r--net/sched/sch_cake.c185
-rw-r--r--net/sched/sch_choke.c2
-rw-r--r--net/sched/sch_codel.c5
-rw-r--r--net/sched/sch_fq.c14
-rw-r--r--net/sched/sch_fq_codel.c3
-rw-r--r--net/sched/sch_fq_pie.c6
-rw-r--r--net/sched/sch_generic.c37
-rw-r--r--net/sched/sch_gred.c4
-rw-r--r--net/sched/sch_netem.c22
-rw-r--r--net/sched/sch_pie.c5
-rw-r--r--net/sched/sch_red.c4
-rw-r--r--net/sched/sch_sfb.c4
-rw-r--r--net/sched/sch_sfq.c4
-rw-r--r--net/sched/sch_tbf.c18
-rw-r--r--net/sctp/associola.c3
-rw-r--r--net/sctp/protocol.c10
-rw-r--r--net/sctp/sysctl.c14
-rw-r--r--net/smc/af_smc.c29
-rw-r--r--net/smc/smc_clc.c17
-rw-r--r--net/smc/smc_clc.h22
-rw-r--r--net/smc/smc_core.c14
-rw-r--r--net/smc/smc_core.h11
-rw-r--r--net/smc/smc_ib.c3
-rw-r--r--net/smc/smc_llc.c21
-rw-r--r--net/smc/smc_wr.c42
-rw-r--r--net/socket.c11
-rw-r--r--net/sunrpc/auth_gss/gss_krb5_test.c2
-rw-r--r--net/sunrpc/svcsock.c4
-rw-r--r--net/sunrpc/xprtsock.c18
-rw-r--r--net/tipc/name_table.c4
-rw-r--r--net/tipc/name_table.h2
-rw-r--r--net/tipc/udp_media.c7
-rw-r--r--net/tls/tls.h3
-rw-r--r--net/tls/tls_device.c2
-rw-r--r--net/tls/tls_main.c71
-rw-r--r--net/tls/tls_proc.c5
-rw-r--r--net/tls/tls_sw.c142
-rw-r--r--net/unix/Kconfig4
-rw-r--r--net/unix/af_unix.c197
-rw-r--r--net/vmw_vsock/af_vsock.c70
-rw-r--r--net/wireless/chan.c4
-rw-r--r--net/wireless/core.c42
-rw-r--r--net/wireless/mlme.c8
-rw-r--r--net/wireless/nl80211.c205
-rw-r--r--net/wireless/pmsr.c4
-rw-r--r--net/wireless/rdev-ops.h7
-rw-r--r--net/wireless/reg.c55
-rw-r--r--net/wireless/scan.c40
-rw-r--r--net/wireless/sme.c13
-rw-r--r--net/wireless/tests/chan.c2
-rw-r--r--net/wireless/tests/scan.c4
-rw-r--r--net/wireless/trace.h44
-rw-r--r--net/wireless/util.c10
-rw-r--r--net/wireless/wext-compat.c317
-rw-r--r--net/wireless/wext-sme.c43
-rw-r--r--net/xdp/xsk_buff_pool.c5
-rw-r--r--net/xdp/xskmap.c2
-rw-r--r--rust/Makefile19
-rw-r--r--rust/bindings/bindings_helper.h1
-rw-r--r--rust/kernel/block/mq/gen_disk.rs2
-rw-r--r--rust/kernel/device.rs319
-rw-r--r--rust/kernel/lib.rs24
-rw-r--r--rust/kernel/miscdevice.rs256
-rw-r--r--rust/kernel/net/phy.rs8
-rw-r--r--rust/kernel/prelude.rs2
-rw-r--r--rust/kernel/types.rs16
-rw-r--r--rust/kernel/workqueue.rs18
-rw-r--r--rust/macros/module.rs28
-rw-r--r--samples/bpf/Makefile13
-rw-r--r--samples/kfifo/dma-example.c1
-rw-r--r--samples/qmi/qmi_sample_client.c2
-rw-r--r--samples/vfio-mdev/mbochs.c2
-rw-r--r--scripts/.gitignore1
-rw-r--r--scripts/Kbuild.include2
-rw-r--r--scripts/Makefile2
-rw-r--r--scripts/Makefile.autofdo24
-rw-r--r--scripts/Makefile.build59
-rw-r--r--scripts/Makefile.clang1
-rw-r--r--scripts/Makefile.clean2
-rw-r--r--scripts/Makefile.compiler2
-rw-r--r--scripts/Makefile.host8
-rw-r--r--scripts/Makefile.lib62
-rw-r--r--scripts/Makefile.modfinal31
-rw-r--r--scripts/Makefile.modinst8
-rw-r--r--scripts/Makefile.modpost24
-rw-r--r--scripts/Makefile.propeller39
-rw-r--r--scripts/Makefile.vmlinux51
-rwxr-xr-xscripts/checkpatch.pl2
-rwxr-xr-xscripts/coccicheck6
-rwxr-xr-xscripts/depmod.sh4
-rw-r--r--scripts/gen_packed_field_checks.c37
-rw-r--r--scripts/genksyms/genksyms.c73
-rw-r--r--scripts/head-object-list.txt2
-rw-r--r--scripts/kconfig/conf.c5
-rw-r--r--scripts/kconfig/lkc_proto.h1
-rw-r--r--scripts/kconfig/nconf.c2
-rw-r--r--scripts/kconfig/nconf.gui.c9
-rw-r--r--scripts/kconfig/parser.y28
-rw-r--r--scripts/kconfig/qconf.cc204
-rw-r--r--scripts/kconfig/qconf.h19
-rwxr-xr-xscripts/kconfig/streamline_config.pl18
-rw-r--r--scripts/kconfig/symbol.c26
-rwxr-xr-xscripts/kernel-doc2
-rwxr-xr-xscripts/link-vmlinux.sh16
-rwxr-xr-xscripts/mksysmap4
-rw-r--r--scripts/mod/file2alias.c815
-rw-r--r--scripts/mod/modpost.c74
-rw-r--r--scripts/mod/modpost.h38
-rw-r--r--scripts/nsdeps12
-rw-r--r--scripts/package/PKGBUILD2
-rwxr-xr-xscripts/package/builddeb28
-rwxr-xr-xscripts/package/install-extmod-build11
-rwxr-xr-xscripts/package/mkdebian9
-rwxr-xr-xscripts/setlocalversion58
-rw-r--r--scripts/sorttable.h5
-rwxr-xr-xscripts/tags.sh40
-rw-r--r--security/apparmor/apparmorfs.c1
-rw-r--r--security/apparmor/capability.c19
-rw-r--r--security/apparmor/domain.c66
-rw-r--r--security/apparmor/include/label.h28
-rw-r--r--security/apparmor/include/lib.h1
-rw-r--r--security/apparmor/include/match.h8
-rw-r--r--security/apparmor/include/perms.h3
-rw-r--r--security/apparmor/include/policy.h1
-rw-r--r--security/apparmor/include/secid.h1
-rw-r--r--security/apparmor/label.c33
-rw-r--r--security/apparmor/lib.c84
-rw-r--r--security/apparmor/match.c99
-rw-r--r--security/apparmor/path.c2
-rw-r--r--security/apparmor/policy.c9
-rw-r--r--security/apparmor/policy_unpack.c5
-rw-r--r--security/apparmor/policy_unpack_test.c8
-rw-r--r--security/apparmor/secid.c14
-rw-r--r--security/integrity/ima/ima_policy.c9
-rw-r--r--security/selinux/avc.c61
-rw-r--r--security/selinux/hooks.c8
-rw-r--r--security/selinux/include/avc.h5
-rw-r--r--security/selinux/include/security.h3
-rw-r--r--security/selinux/ss/services.c36
-rw-r--r--sound/ac97/bus.c5
-rw-r--r--sound/core/compress_offload.c43
-rw-r--r--sound/core/control_led.c14
-rw-r--r--sound/core/memalloc.c2
-rw-r--r--sound/core/pcm_native.c6
-rw-r--r--sound/core/rawmidi.c4
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c2
-rw-r--r--sound/core/seq/seq_clientmgr.c14
-rw-r--r--sound/core/seq/seq_ump_client.c6
-rw-r--r--sound/core/sound_kunit.c11
-rw-r--r--sound/core/ump.c33
-rw-r--r--sound/hda/intel-dsp-config.c2
-rw-r--r--sound/hda/intel-sdw-acpi.c2
-rw-r--r--sound/pci/asihpi/asihpi.c2
-rw-r--r--sound/pci/hda/cirrus_scodec.c2
-rw-r--r--sound/pci/hda/cirrus_scodec_test.c2
-rw-r--r--sound/pci/hda/cs35l41_hda.c12
-rw-r--r--sound/pci/hda/cs35l41_hda_i2c.c2
-rw-r--r--sound/pci/hda/cs35l41_hda_spi.c2
-rw-r--r--sound/pci/hda/cs35l56_hda.c24
-rw-r--r--sound/pci/hda/cs35l56_hda_i2c.c4
-rw-r--r--sound/pci/hda/cs35l56_hda_spi.c4
-rw-r--r--sound/pci/hda/hda_auto_parser.c20
-rw-r--r--sound/pci/hda/hda_component.c14
-rw-r--r--sound/pci/hda/hda_cs_dsp_ctl.c12
-rw-r--r--sound/pci/hda/patch_ca0132.c37
-rw-r--r--sound/pci/hda/patch_conexant.c28
-rw-r--r--sound/pci/hda/patch_realtek.c204
-rw-r--r--sound/pci/hda/tas2781_hda_i2c.c70
-rw-r--r--sound/sh/sh_dac_audio.c5
-rw-r--r--sound/soc/amd/Kconfig1
-rw-r--r--sound/soc/amd/acp/acp-i2s.c2
-rw-r--r--sound/soc/amd/acp/acp-legacy-common.c18
-rw-r--r--sound/soc/amd/acp/acp-legacy-mach.c2
-rw-r--r--sound/soc/amd/acp/acp-mach-common.c4
-rw-r--r--sound/soc/amd/acp/acp-pci.c2
-rw-r--r--sound/soc/amd/acp/acp-pdm.c2
-rw-r--r--sound/soc/amd/acp/acp-platform.c10
-rw-r--r--sound/soc/amd/acp/acp-rembrandt.c2
-rw-r--r--sound/soc/amd/acp/acp-renoir.c2
-rw-r--r--sound/soc/amd/acp/acp-sdw-legacy-mach.c4
-rw-r--r--sound/soc/amd/acp/acp-sdw-mach-common.c2
-rw-r--r--sound/soc/amd/acp/acp-sdw-sof-mach.c4
-rw-r--r--sound/soc/amd/acp/acp-sof-mach.c2
-rw-r--r--sound/soc/amd/acp/acp63.c2
-rw-r--r--sound/soc/amd/acp/acp70.c2
-rw-r--r--sound/soc/amd/acp/amd-sdw-acpi.c2
-rw-r--r--sound/soc/amd/ps/pci-ps.c21
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c44
-rw-r--r--sound/soc/apple/mca.c2
-rw-r--r--sound/soc/codecs/cs-amp-lib-test.c2
-rw-r--r--sound/soc/codecs/cs-amp-lib.c8
-rw-r--r--sound/soc/codecs/cs35l45-i2c.c2
-rw-r--r--sound/soc/codecs/cs35l45-spi.c2
-rw-r--r--sound/soc/codecs/cs35l45-tables.c8
-rw-r--r--sound/soc/codecs/cs35l45.c4
-rw-r--r--sound/soc/codecs/cs35l56-i2c.c4
-rw-r--r--sound/soc/codecs/cs35l56-sdw.c4
-rw-r--r--sound/soc/codecs/cs35l56-shared.c52
-rw-r--r--sound/soc/codecs/cs35l56-spi.c4
-rw-r--r--sound/soc/codecs/cs35l56.c10
-rw-r--r--sound/soc/codecs/cs42l42-i2c.c2
-rw-r--r--sound/soc/codecs/cs42l42-sdw.c2
-rw-r--r--sound/soc/codecs/cs42l42.c32
-rw-r--r--sound/soc/codecs/cs42l43-sdw.c6
-rw-r--r--sound/soc/codecs/cs42l43.c2
-rw-r--r--sound/soc/codecs/cs42l83-i2c.c2
-rw-r--r--sound/soc/codecs/cs530x-i2c.c2
-rw-r--r--sound/soc/codecs/cs530x.c4
-rw-r--r--sound/soc/codecs/rt712-sdca-sdw.c2
-rw-r--r--sound/soc/codecs/rt722-sdca.c7
-rw-r--r--sound/soc/codecs/tas2781-fmwlib.c20
-rw-r--r--sound/soc/codecs/tas2781-i2c.c4
-rw-r--r--sound/soc/codecs/wm_adsp.c2
-rw-r--r--sound/soc/fsl/Kconfig2
-rw-r--r--sound/soc/fsl/fsl_spdif.c2
-rw-r--r--sound/soc/fsl/fsl_xcvr.c2
-rw-r--r--sound/soc/fsl/imx-audmix.c3
-rw-r--r--sound/soc/generic/audio-graph-card2.c2
-rw-r--r--sound/soc/intel/avs/boards/da7219.c17
-rw-r--r--sound/soc/intel/boards/ehl_rt5660.c2
-rw-r--r--sound/soc/intel/boards/hda_dsp_common.c2
-rw-r--r--sound/soc/intel/boards/skl_hda_dsp_generic.c2
-rw-r--r--sound/soc/intel/boards/sof_board_helpers.c10
-rw-r--r--sound/soc/intel/boards/sof_cirrus_common.c4
-rw-r--r--sound/soc/intel/boards/sof_cs42l42.c4
-rw-r--r--sound/soc/intel/boards/sof_da7219.c4
-rw-r--r--sound/soc/intel/boards/sof_es8336.c2
-rw-r--r--sound/soc/intel/boards/sof_maxim_common.c12
-rw-r--r--sound/soc/intel/boards/sof_nau8825.c8
-rw-r--r--sound/soc/intel/boards/sof_nuvoton_common.c2
-rw-r--r--sound/soc/intel/boards/sof_pcm512x.c2
-rw-r--r--sound/soc/intel/boards/sof_realtek_common.c16
-rw-r--r--sound/soc/intel/boards/sof_rt5682.c6
-rw-r--r--sound/soc/intel/boards/sof_sdw.c35
-rw-r--r--sound/soc/intel/boards/sof_ssp_amp.c6
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c2
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c4
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-ssp-common.c10
-rw-r--r--sound/soc/mediatek/common/mtk-afe-platform-driver.c4
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-mt6359.c13
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c4
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-mt6359.c9
-rw-r--r--sound/soc/sdca/sdca_device.c4
-rw-r--r--sound/soc/sdca/sdca_functions.c2
-rw-r--r--sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c6
-rw-r--r--sound/soc/sdw_utils/soc_sdw_cs42l42.c2
-rw-r--r--sound/soc/sdw_utils/soc_sdw_cs42l43.c8
-rw-r--r--sound/soc/sdw_utils/soc_sdw_cs_amp.c4
-rw-r--r--sound/soc/sdw_utils/soc_sdw_dmic.c2
-rw-r--r--sound/soc/sdw_utils/soc_sdw_maxim.c4
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt5682.c2
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt700.c2
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt711.c6
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt_amp.c8
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt_dmic.c2
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c2
-rw-r--r--sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c6
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c42
-rw-r--r--sound/soc/sof/amd/acp-common.c8
-rw-r--r--sound/soc/sof/amd/acp-ipc.c16
-rw-r--r--sound/soc/sof/amd/acp-loader.c12
-rw-r--r--sound/soc/sof/amd/acp-pcm.c8
-rw-r--r--sound/soc/sof/amd/acp-probes.c6
-rw-r--r--sound/soc/sof/amd/acp-stream.c6
-rw-r--r--sound/soc/sof/amd/acp-trace.c4
-rw-r--r--sound/soc/sof/amd/acp.c12
-rw-r--r--sound/soc/sof/amd/acp63.c2
-rw-r--r--sound/soc/sof/amd/acp70.c2
-rw-r--r--sound/soc/sof/amd/pci-acp63.c4
-rw-r--r--sound/soc/sof/amd/pci-acp70.c4
-rw-r--r--sound/soc/sof/amd/pci-rmb.c4
-rw-r--r--sound/soc/sof/amd/pci-rn.c4
-rw-r--r--sound/soc/sof/amd/pci-vangogh.c4
-rw-r--r--sound/soc/sof/amd/rembrandt.c2
-rw-r--r--sound/soc/sof/amd/renoir.c2
-rw-r--r--sound/soc/sof/amd/vangogh.c2
-rw-r--r--sound/soc/sof/core.c2
-rw-r--r--sound/soc/sof/imx/imx8.c2
-rw-r--r--sound/soc/sof/imx/imx8m.c2
-rw-r--r--sound/soc/sof/imx/imx8ulp.c2
-rw-r--r--sound/soc/sof/intel/atom.c22
-rw-r--r--sound/soc/sof/intel/bdw.c6
-rw-r--r--sound/soc/sof/intel/byt.c8
-rw-r--r--sound/soc/sof/intel/cnl.c18
-rw-r--r--sound/soc/sof/intel/hda-bus.c4
-rw-r--r--sound/soc/sof/intel/hda-codec.c32
-rw-r--r--sound/soc/sof/intel/hda-common-ops.c2
-rw-r--r--sound/soc/sof/intel/hda-ctrl.c16
-rw-r--r--sound/soc/sof/intel/hda-dai.c39
-rw-r--r--sound/soc/sof/intel/hda-dsp.c62
-rw-r--r--sound/soc/sof/intel/hda-ipc.c34
-rw-r--r--sound/soc/sof/intel/hda-loader.c16
-rw-r--r--sound/soc/sof/intel/hda-mlink.c68
-rw-r--r--sound/soc/sof/intel/hda-pcm.c12
-rw-r--r--sound/soc/sof/intel/hda-probes.c6
-rw-r--r--sound/soc/sof/intel/hda-stream.c18
-rw-r--r--sound/soc/sof/intel/hda-trace.c6
-rw-r--r--sound/soc/sof/intel/hda.c40
-rw-r--r--sound/soc/sof/intel/hda.h2
-rw-r--r--sound/soc/sof/intel/lnl.c6
-rw-r--r--sound/soc/sof/intel/mtl.c30
-rw-r--r--sound/soc/sof/intel/pci-apl.c6
-rw-r--r--sound/soc/sof/intel/pci-cnl.c6
-rw-r--r--sound/soc/sof/intel/pci-icl.c8
-rw-r--r--sound/soc/sof/intel/pci-lnl.c10
-rw-r--r--sound/soc/sof/intel/pci-mtl.c6
-rw-r--r--sound/soc/sof/intel/pci-ptl.c12
-rw-r--r--sound/soc/sof/intel/pci-skl.c6
-rw-r--r--sound/soc/sof/intel/pci-tgl.c8
-rw-r--r--sound/soc/sof/intel/pci-tng.c8
-rw-r--r--sound/soc/sof/intel/skl.c6
-rw-r--r--sound/soc/sof/intel/telemetry.c2
-rw-r--r--sound/soc/sof/ipc3-topology.c31
-rw-r--r--sound/soc/sof/mediatek/mt8186/mt8186.c4
-rw-r--r--sound/soc/sof/mediatek/mt8195/mt8195.c4
-rw-r--r--sound/soc/sof/sof-acpi-dev.c6
-rw-r--r--sound/soc/sof/sof-client-ipc-flood-test.c2
-rw-r--r--sound/soc/sof/sof-client-ipc-kernel-injector.c2
-rw-r--r--sound/soc/sof/sof-client-ipc-msg-injector.c2
-rw-r--r--sound/soc/sof/sof-client-probes.c2
-rw-r--r--sound/soc/sof/sof-client.c40
-rw-r--r--sound/soc/sof/sof-pci-dev.c8
-rw-r--r--sound/soc/sof/xtensa/core.c2
-rw-r--r--sound/usb/clock.c24
-rw-r--r--sound/usb/endpoint.c14
-rw-r--r--sound/usb/format.c7
-rw-r--r--sound/usb/mixer_maps.c10
-rw-r--r--sound/usb/mixer_quirks.c1
-rw-r--r--sound/usb/mixer_us16x08.c2
-rw-r--r--sound/usb/quirks-table.h341
-rw-r--r--sound/usb/quirks.c45
-rw-r--r--tools/arch/arm64/include/uapi/asm/kvm.h6
-rw-r--r--tools/arch/x86/include/asm/cpufeatures.h11
-rw-r--r--tools/arch/x86/include/uapi/asm/kvm.h1
-rw-r--r--tools/bpf/bpftool/prog.c17
-rw-r--r--tools/hv/.gitignore3
-rw-r--r--tools/hv/hv_fcopy_uio_daemon.c12
-rwxr-xr-xtools/hv/hv_get_dns_info.sh4
-rw-r--r--tools/hv/hv_kvp_daemon.c9
-rwxr-xr-xtools/hv/hv_set_ifconfig.sh2
-rw-r--r--tools/iio/iio_event_monitor.c3
-rw-r--r--tools/include/uapi/asm-generic/mman.h4
-rw-r--r--tools/include/uapi/asm-generic/socket.h2
-rw-r--r--tools/include/uapi/asm-generic/unistd.h11
-rw-r--r--tools/include/uapi/drm/drm.h17
-rw-r--r--tools/include/uapi/linux/if_link.h2
-rw-r--r--tools/include/uapi/linux/kvm.h8
-rw-r--r--tools/include/uapi/linux/perf_event.h11
-rw-r--r--tools/include/uapi/linux/stddef.h15
-rw-r--r--tools/lib/perf/evlist.c18
-rw-r--r--tools/net/ynl/Makefile29
-rw-r--r--tools/net/ynl/generated/.gitignore1
-rw-r--r--tools/net/ynl/generated/Makefile51
-rw-r--r--tools/net/ynl/lib/.gitignore1
-rw-r--r--tools/net/ynl/lib/Makefile1
-rw-r--r--tools/net/ynl/pyproject.toml24
-rw-r--r--tools/net/ynl/pyynl/.gitignore2
-rw-r--r--tools/net/ynl/pyynl/__init__.py0
-rwxr-xr-xtools/net/ynl/pyynl/cli.py (renamed from tools/net/ynl/cli.py)0
-rwxr-xr-xtools/net/ynl/pyynl/ethtool.py (renamed from tools/net/ynl/ethtool.py)0
-rw-r--r--tools/net/ynl/pyynl/lib/__init__.py (renamed from tools/net/ynl/lib/__init__.py)0
-rw-r--r--tools/net/ynl/pyynl/lib/nlspec.py (renamed from tools/net/ynl/lib/nlspec.py)5
-rw-r--r--tools/net/ynl/pyynl/lib/ynl.py (renamed from tools/net/ynl/lib/ynl.py)80
-rwxr-xr-xtools/net/ynl/pyynl/ynl_gen_c.py (renamed from tools/net/ynl/ynl-gen-c.py)185
-rwxr-xr-xtools/net/ynl/pyynl/ynl_gen_rst.py (renamed from tools/net/ynl/ynl-gen-rst.py)0
-rwxr-xr-xtools/net/ynl/ynl-regen.sh2
-rw-r--r--tools/objtool/check.c11
-rw-r--r--tools/objtool/elf.c15
-rw-r--r--tools/objtool/noreturns.h1
-rw-r--r--tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl4
-rw-r--r--tools/perf/arch/powerpc/entry/syscalls/syscall.tbl4
-rw-r--r--tools/perf/arch/s390/entry/syscalls/syscall.tbl4
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_32.tbl4
-rw-r--r--tools/perf/arch/x86/entry/syscalls/syscall_64.tbl4
-rw-r--r--tools/perf/builtin-ftrace.c3
-rw-r--r--tools/perf/tests/builtin-test.c2
-rw-r--r--tools/perf/tests/expr.c19
-rw-r--r--tools/perf/tests/hwmon_pmu.c29
-rwxr-xr-xtools/perf/trace/beauty/fs_at_flags.sh3
-rw-r--r--tools/perf/trace/beauty/include/uapi/linux/fcntl.h5
-rw-r--r--tools/perf/trace/beauty/include/uapi/linux/mount.h14
-rw-r--r--tools/perf/trace/beauty/include/uapi/linux/prctl.h27
-rw-r--r--tools/perf/util/build-id.c4
-rw-r--r--tools/perf/util/evsel.c6
-rw-r--r--tools/perf/util/hwmon_pmu.c15
-rw-r--r--tools/perf/util/machine.c2
-rw-r--r--tools/perf/util/probe-event.c2
-rw-r--r--tools/power/x86/turbostat/turbostat.827
-rw-r--r--tools/power/x86/turbostat/turbostat.c425
-rw-r--r--tools/sched_ext/include/scx/common.bpf.h6
-rw-r--r--tools/sched_ext/scx_central.c2
-rw-r--r--tools/scripts/Makefile.arch4
-rw-r--r--tools/testing/cxl/cxl_core_exports.c2
-rw-r--r--tools/testing/cxl/test/cxl.c4
-rw-r--r--tools/testing/cxl/test/mem.c2
-rw-r--r--tools/testing/cxl/test/mock.c28
-rw-r--r--tools/testing/nvdimm/test/ndtest.c2
-rw-r--r--tools/testing/selftests/alsa/.gitignore2
-rw-r--r--tools/testing/selftests/alsa/Makefile2
-rw-r--r--tools/testing/selftests/arm64/abi/syscall-abi-asm.S32
-rw-r--r--tools/testing/selftests/bpf/.gitignore1
-rw-r--r--tools/testing/selftests/bpf/Makefile3
-rw-r--r--tools/testing/selftests/bpf/map_tests/lpm_trie_map_basic_ops.c (renamed from tools/testing/selftests/bpf/test_lpm_map.c)405
-rw-r--r--tools/testing/selftests/bpf/map_tests/task_storage_map.c4
-rw-r--r--tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c107
-rw-r--r--tools/testing/selftests/bpf/prog_tests/raw_tp_null.c3
-rw-r--r--tools/testing/selftests/bpf/prog_tests/socket_helpers.h394
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sockmap_basic.c136
-rw-r--r--tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h385
-rw-r--r--tools/testing/selftests/bpf/prog_tests/task_local_storage.c2
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tc_change_tail.c62
-rw-r--r--tools/testing/selftests/bpf/prog_tests/tc_netkit.c49
-rw-r--r--tools/testing/selftests/bpf/prog_tests/verifier.c19
-rw-r--r--tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c87
-rw-r--r--tools/testing/selftests/bpf/progs/bpf_misc.h12
-rw-r--r--tools/testing/selftests/bpf/progs/changes_pkt_data.c39
-rw-r--r--tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c18
-rw-r--r--tools/testing/selftests/bpf/progs/dynptr_fail.c22
-rw-r--r--tools/testing/selftests/bpf/progs/iters.c26
-rw-r--r--tools/testing/selftests/bpf/progs/iters_state_safety.c14
-rw-r--r--tools/testing/selftests/bpf/progs/iters_testmod_seq.c4
-rw-r--r--tools/testing/selftests/bpf/progs/raw_tp_null.c19
-rw-r--r--tools/testing/selftests/bpf/progs/raw_tp_null_fail.c24
-rw-r--r--tools/testing/selftests/bpf/progs/read_bpf_task_storage_busy.c4
-rw-r--r--tools/testing/selftests/bpf/progs/task_storage_nodeadlock.c4
-rw-r--r--tools/testing/selftests/bpf/progs/tc_bpf2bpf.c2
-rw-r--r--tools/testing/selftests/bpf/progs/test_kfunc_dynptr_param.c2
-rw-r--r--tools/testing/selftests/bpf/progs/test_sockmap_change_tail.c40
-rw-r--r--tools/testing/selftests/bpf/progs/test_tc_change_tail.c106
-rw-r--r--tools/testing/selftests/bpf/progs/test_tc_link.c15
-rw-r--r--tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c6
-rw-r--r--tools/testing/selftests/bpf/progs/test_xdp_meta.c4
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_bits_iter.c8
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_btf_ctx_access.c40
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_d_path.c4
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_mtu.c4
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_sock.c56
-rw-r--r--tools/testing/selftests/bpf/progs/verifier_spill_fill.c35
-rw-r--r--tools/testing/selftests/bpf/sdt.h2
-rw-r--r--tools/testing/selftests/bpf/test_loader.c46
-rw-r--r--tools/testing/selftests/bpf/test_sockmap.c6
-rwxr-xr-xtools/testing/selftests/bpf/test_xdp_meta.sh58
-rw-r--r--tools/testing/selftests/bpf/trace_helpers.c4
-rw-r--r--tools/testing/selftests/bpf/xdp_hw_metadata.c3
-rw-r--r--tools/testing/selftests/damon/Makefile2
-rw-r--r--tools/testing/selftests/drivers/net/Makefile2
-rw-r--r--tools/testing/selftests/drivers/net/hw/ncdevmem.c3
-rwxr-xr-xtools/testing/selftests/drivers/net/hw/rss_ctx.py12
-rw-r--r--tools/testing/selftests/drivers/net/lib/py/env.py10
-rw-r--r--tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh225
-rwxr-xr-xtools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh55
-rwxr-xr-xtools/testing/selftests/drivers/net/netcons_basic.sh218
-rwxr-xr-xtools/testing/selftests/drivers/net/netcons_overflow.sh67
-rwxr-xr-xtools/testing/selftests/drivers/net/queues.py51
-rwxr-xr-xtools/testing/selftests/drivers/net/stats.py113
-rw-r--r--tools/testing/selftests/filesystems/binderfs/binderfs_test.c1
-rw-r--r--tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc2
-rw-r--r--tools/testing/selftests/hid/progs/hid_bpf_helpers.h19
-rwxr-xr-xtools/testing/selftests/hid/run-hid-tools-tests.sh16
-rw-r--r--tools/testing/selftests/iommu/iommufd_fail_nth.c14
-rw-r--r--tools/testing/selftests/kselftest/ktap_helpers.sh15
-rw-r--r--tools/testing/selftests/kvm/riscv/get-reg-list.c8
-rw-r--r--tools/testing/selftests/memfd/memfd_test.c57
-rw-r--r--tools/testing/selftests/mm/hugetlb_dio.c14
-rwxr-xr-xtools/testing/selftests/module/find_symbol.sh4
-rw-r--r--tools/testing/selftests/net/Makefile2
-rw-r--r--tools/testing/selftests/net/busy_poller.c88
-rw-r--r--tools/testing/selftests/net/cmsg_sender.c11
-rwxr-xr-xtools/testing/selftests/net/cmsg_so_priority.sh151
-rwxr-xr-xtools/testing/selftests/net/fdb_notify.sh6
-rwxr-xr-xtools/testing/selftests/net/fib_rule_tests.sh31
-rw-r--r--tools/testing/selftests/net/forwarding/Makefile1
-rwxr-xr-xtools/testing/selftests/net/forwarding/bridge_vlan_unaware.sh25
-rw-r--r--tools/testing/selftests/net/forwarding/lib.sh7
-rwxr-xr-xtools/testing/selftests/net/forwarding/local_termination.sh1
-rwxr-xr-xtools/testing/selftests/net/forwarding/vxlan_reserved.sh352
-rw-r--r--tools/testing/selftests/net/lib.sh68
-rw-r--r--tools/testing/selftests/net/lib/py/ksft.py5
-rw-r--r--tools/testing/selftests/net/lib/py/utils.py6
-rw-r--r--tools/testing/selftests/net/lib/py/ynl.py20
-rwxr-xr-xtools/testing/selftests/net/netfilter/rpath.sh18
-rwxr-xr-xtools/testing/selftests/net/nl_netdev.py19
-rwxr-xr-xtools/testing/selftests/net/openvswitch/openvswitch.sh6
-rwxr-xr-xtools/testing/selftests/net/packetdrill/ksft_runner.sh23
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-accept.pkt18
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-connect.pkt13
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-read.pkt29
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-write.pkt35
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_close_close-local-close-then-remote-fin.pkt23
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_close_close-on-syn-sent.pkt21
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_close_close-remote-fin-then-close.pkt36
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_ecn_ecn-uses-ect0.pkt21
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-large.pkt38
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-retrans.pkt72
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-small.pkt36
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-subsequent.pkt66
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-10pkt-lost-1.pkt72
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-30pkt-lost-1_4-11_16.pkt50
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-30pkt-lost1_4.pkt43
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-ack-below-snd_una-cubic.pkt41
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_limited_transmit_limited-transmit-no-sack.pkt53
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_limited_transmit_limited-transmit-sack.pkt50
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_nagle_https_client.pkt40
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_nagle_sendmsg_msg_more.pkt66
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_nagle_sockopt_cork_nodelay.pkt43
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_sack_sack-route-refresh-ip-tos.pkt37
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-2-6-8-3-9-nofack.pkt64
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-7-3-4-8-9-fack.pkt66
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-7-5-6-8-9-fack.pkt62
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_sendfile_sendfile-simple.pkt26
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_splice_tcp_splice_loop_test.pkt20
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_fastopen-invalid-buf-ptr.pkt42
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_sendmsg-empty-iov.pkt30
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_syscall-invalid-buf-ptr.pkt25
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-last_data_recv.pkt20
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-rwnd-limited.pkt54
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-sndbuf-limited.pkt38
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_timestamping_client-only-last-byte.pkt92
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_timestamping_partial.pkt91
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_timestamping_server.pkt145
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_ts_recent_fin_tsval.pkt23
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_ts_recent_invalid_ack.pkt25
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_ts_recent_reset_tsval.pkt25
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_user_timeout_user-timeout-probe.pkt37
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_user_timeout_user_timeout.pkt32
-rw-r--r--tools/testing/selftests/net/packetdrill/tcp_validate_validate-established-no-flags.pkt24
-rw-r--r--tools/testing/selftests/net/tls.c478
-rwxr-xr-xtools/testing/selftests/net/vlan_bridge_binding.sh256
-rw-r--r--tools/testing/selftests/net/ynl.mk3
-rw-r--r--tools/testing/selftests/sched_ext/ddsp_bogus_dsq_fail.bpf.c2
-rw-r--r--tools/testing/selftests/sched_ext/ddsp_vtimelocal_fail.bpf.c4
-rw-r--r--tools/testing/selftests/sched_ext/dsp_local_on.bpf.c7
-rw-r--r--tools/testing/selftests/sched_ext/dsp_local_on.c5
-rw-r--r--tools/testing/selftests/sched_ext/enq_select_cpu_fails.bpf.c2
-rw-r--r--tools/testing/selftests/sched_ext/exit.bpf.c4
-rw-r--r--tools/testing/selftests/sched_ext/maximal.bpf.c8
-rw-r--r--tools/testing/selftests/sched_ext/select_cpu_dfl.bpf.c2
-rw-r--r--tools/testing/selftests/sched_ext/select_cpu_dfl_nodispatch.bpf.c2
-rw-r--r--tools/testing/selftests/sched_ext/select_cpu_dispatch.bpf.c2
-rw-r--r--tools/testing/selftests/sched_ext/select_cpu_dispatch_bad_dsq.bpf.c2
-rw-r--r--tools/testing/selftests/sched_ext/select_cpu_dispatch_dbl_dsp.bpf.c4
-rw-r--r--tools/testing/selftests/sched_ext/select_cpu_vtime.bpf.c8
-rwxr-xr-xtools/testing/selftests/tc-testing/scripts/sfq_rejects_limit_1.py21
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/filters/flow.json4
-rw-r--r--tools/testing/selftests/tc-testing/tc-tests/qdiscs/sfq.json20
-rw-r--r--tools/testing/vsock/README15
-rw-r--r--tools/testing/vsock/control.c9
-rw-r--r--tools/testing/vsock/msg_zerocopy_common.c10
-rw-r--r--tools/testing/vsock/msg_zerocopy_common.h1
-rw-r--r--tools/testing/vsock/util.c175
-rw-r--r--tools/testing/vsock/util.h9
-rw-r--r--tools/testing/vsock/vsock_perf.c20
-rw-r--r--tools/testing/vsock/vsock_test.c340
-rw-r--r--tools/testing/vsock/vsock_test_zerocopy.c2
-rw-r--r--tools/testing/vsock/vsock_uring_test.c2
-rw-r--r--tools/tracing/rtla/src/timerlat_hist.c177
-rw-r--r--usr/include/Makefile2
-rwxr-xr-xusr/include/headers_check.pl9
4973 files changed, 125993 insertions, 115953 deletions
diff --git a/.gitignore b/.gitignore
index a61e4778d011..6839cf84acda 100644
--- a/.gitignore
+++ b/.gitignore
@@ -129,6 +129,7 @@ series
# ctags files
tags
+!tags/
TAGS
# cscope files
diff --git a/.mailmap b/.mailmap
index 5ff0e5d681e7..f5f97f947020 100644
--- a/.mailmap
+++ b/.mailmap
@@ -435,7 +435,7 @@ 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> <othacehe@gnu.org>
+Mathieu Othacehe <othacehe@gnu.org> <m.othacehe@gmail.com>
Mat Martineau <martineau@kernel.org> <mathew.j.martineau@linux.intel.com>
Mat Martineau <martineau@kernel.org> <mathewm@codeaurora.org>
Matthew Wilcox <willy@infradead.org> <matthew.r.wilcox@intel.com>
@@ -735,6 +735,7 @@ Wolfram Sang <wsa@kernel.org> <w.sang@pengutronix.de>
Wolfram Sang <wsa@kernel.org> <wsa@the-dreams.de>
Yakir Yang <kuankuan.y@gmail.com> <ykk@rock-chips.com>
Yanteng Si <si.yanteng@linux.dev> <siyanteng@loongson.cn>
+Ying Huang <huang.ying.caritas@gmail.com> <ying.huang@intel.com>
Yusuke Goda <goda.yusuke@renesas.com>
Zack Rusin <zack.rusin@broadcom.com> <zackr@vmware.com>
Zhu Yanjun <zyjzyj2000@gmail.com> <yanjunz@nvidia.com>
diff --git a/CREDITS b/CREDITS
index b1777b53c63a..cda68f04d5f1 100644
--- a/CREDITS
+++ b/CREDITS
@@ -20,6 +20,10 @@ N: Thomas Abraham
E: thomas.ab@samsung.com
D: Samsung pin controller driver
+N: Jose Abreu
+E: jose.abreu@synopsys.com
+D: Synopsys DesignWare XPCS MDIO/PCS driver.
+
N: Dragos Acostachioaie
E: dragos@iname.com
W: http://www.arbornet.org/~dragos
@@ -1428,6 +1432,10 @@ S: 8124 Constitution Apt. 7
S: Sterling Heights, Michigan 48313
S: USA
+N: Andy Gospodarek
+E: andy@greyhouse.net
+D: Maintenance and contributions to the network interface bonding driver.
+
N: Wolfgang Grandegger
E: wg@grandegger.com
D: Controller Area Network (device drivers)
@@ -1812,6 +1820,10 @@ D: Author/maintainer of most DRM drivers (especially ATI, MGA)
D: Core DRM templates, general DRM and 3D-related hacking
S: No fixed address
+N: Woojung Huh
+E: woojung.huh@microchip.com
+D: Microchip LAN78XX USB Ethernet driver
+
N: Kenn Humborg
E: kenn@wombat.ie
D: Mods to loop device to support sparse backing files
diff --git a/Documentation/ABI/testing/configfs-usb-gadget-uvc b/Documentation/ABI/testing/configfs-usb-gadget-uvc
index 4feb692c4c1d..b6720768d63d 100644
--- a/Documentation/ABI/testing/configfs-usb-gadget-uvc
+++ b/Documentation/ABI/testing/configfs-usb-gadget-uvc
@@ -342,6 +342,70 @@ Description: Specific uncompressed frame descriptors
support
========================= =====================================
+What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased
+Date: Sept 2024
+KernelVersion: 5.15
+Description: Framebased format descriptors
+
+What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased/name
+Date: Sept 2024
+KernelVersion: 5.15
+Description: Specific framebased format descriptors
+
+ ================== =======================================
+ bFormatIndex unique id for this format descriptor;
+ only defined after parent header is
+ linked into the streaming class;
+ read-only
+ bmaControls this format's data for bmaControls in
+ the streaming header
+ bmInterlaceFlags specifies interlace information,
+ read-only
+ bAspectRatioY the X dimension of the picture aspect
+ ratio, read-only
+ bAspectRatioX the Y dimension of the picture aspect
+ ratio, read-only
+ bDefaultFrameIndex optimum frame index for this stream
+ bBitsPerPixel number of bits per pixel used to
+ specify color in the decoded video
+ frame
+ guidFormat globally unique id used to identify
+ stream-encoding format
+ ================== =======================================
+
+What: /config/usb-gadget/gadget/functions/uvc.name/streaming/framebased/name/name
+Date: Sept 2024
+KernelVersion: 5.15
+Description: Specific framebased frame descriptors
+
+ ========================= =====================================
+ bFrameIndex unique id for this framedescriptor;
+ only defined after parent format is
+ linked into the streaming header;
+ read-only
+ dwFrameInterval indicates how frame interval can be
+ programmed; a number of values
+ separated by newline can be specified
+ dwDefaultFrameInterval the frame interval the device would
+ like to use as default
+ dwBytesPerLine Specifies the number of bytes per line
+ of video for packed fixed frame size
+ formats, allowing the receiver to
+ perform stride alignment of the video.
+ If the bVariableSize value (above) is
+ TRUE (1), or if the format does not
+ permit such alignment, this value shall
+ be set to zero (0).
+ dwMaxBitRate the maximum bit rate at the shortest
+ frame interval in bps
+ dwMinBitRate the minimum bit rate at the longest
+ frame interval in bps
+ wHeight height of decoded bitmap frame in px
+ wWidth width of decoded bitmam frame in px
+ bmCapabilities still image support, fixed frame-rate
+ support
+ ========================= =====================================
+
What: /config/usb-gadget/gadget/functions/uvc.name/streaming/header
Date: Dec 2014
KernelVersion: 4.0
diff --git a/Documentation/ABI/testing/sysfs-bus-event_source-devices-vpa-pmu b/Documentation/ABI/testing/sysfs-bus-event_source-devices-vpa-pmu
index 8285263ff78d..a116aee9709a 100644
--- a/Documentation/ABI/testing/sysfs-bus-event_source-devices-vpa-pmu
+++ b/Documentation/ABI/testing/sysfs-bus-event_source-devices-vpa-pmu
@@ -8,17 +8,18 @@ Description: Read-only. Attribute group to describe the magic bits
Each attribute under this group defines a bit range of the
perf_event_attr.config. Supported attribute are listed
below::
- event = "config:0-31" - event ID
- For example::
+ event = "config:0-31" - event ID
- l1_to_l2_lat = "event=0x1"
+ For example::
+
+ l1_to_l2_lat = "event=0x1"
What: /sys/bus/event_source/devices/vpa_pmu/events
Date: November 2024
Contact: Linux on PowerPC Developer List <linuxppc-dev@lists.ozlabs.org>
-Description: Read-only. Attribute group to describe performance monitoring
+Description: Read-only. Attribute group to describe performance monitoring
events for the Virtual Processor Area events. Each attribute
- in this group describes a single performance monitoring event
- supported by vpa_pmu. The name of the file is the name of
- the event (See ABI/testing/sysfs-bus-event_source-devices-events).
+ in this group describes a single performance monitoring event
+ supported by vpa_pmu. The name of the file is the name of
+ the event (See ABI/testing/sysfs-bus-event_source-devices-events).
diff --git a/Documentation/ABI/testing/sysfs-bus-iio b/Documentation/ABI/testing/sysfs-bus-iio
index 89943c2d54e8..f83bd6829285 100644
--- a/Documentation/ABI/testing/sysfs-bus-iio
+++ b/Documentation/ABI/testing/sysfs-bus-iio
@@ -2268,6 +2268,30 @@ Description:
An example format is 16-bytes, 2-digits-per-byte, HEX-string
representing the sensor unique ID number.
+What: /sys/bus/iio/devices/iio:deviceX/filter_type_available
+What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_filter_mode_available
+KernelVersion: 6.1
+Contact: linux-iio@vger.kernel.org
+Description:
+ Reading returns a list with the possible filter modes. Options
+ for the attribute:
+
+ * "sinc3" - The digital sinc3 filter. Moderate 1st
+ conversion time. Good noise performance.
+ * "sinc4" - Sinc 4. Excellent noise performance. Long
+ 1st conversion time.
+ * "sinc5" - The digital sinc5 filter. Excellent noise
+ performance
+ * "sinc4+sinc1" - Sinc4 + averaging by 8. Low 1st conversion
+ time.
+ * "sinc3+rej60" - Sinc3 + 60Hz rejection.
+ * "sinc3+sinc1" - Sinc3 + averaging by 8. Low 1st conversion
+ time.
+ * "sinc3+pf1" - Sinc3 + device specific Post Filter 1.
+ * "sinc3+pf2" - Sinc3 + device specific Post Filter 2.
+ * "sinc3+pf3" - Sinc3 + device specific Post Filter 3.
+ * "sinc3+pf4" - Sinc3 + device specific Post Filter 4.
+
What: /sys/.../events/in_proximity_thresh_either_runningperiod
KernelVersion: 6.6
Contact: linux-iio@vger.kernel.org
@@ -2339,3 +2363,11 @@ KernelVersion: 6.10
Contact: linux-iio@vger.kernel.org
Description:
The value of current sense resistor in Ohms.
+
+What: /sys/.../iio:deviceX/in_attention_input
+KernelVersion: 6.13
+Contact: linux-iio@vger.kernel.org
+Description:
+ Value representing the user's attention to the system expressed
+ in units as percentage. This usually means if the user is
+ looking at the screen or not.
diff --git a/Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130 b/Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
deleted file mode 100644
index f24ed6687e90..000000000000
--- a/Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
+++ /dev/null
@@ -1,46 +0,0 @@
-What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_filter_mode_available
-KernelVersion: 6.2
-Contact: linux-iio@vger.kernel.org
-Description:
- Reading returns a list with the possible filter modes.
-
- * "sinc4" - Sinc 4. Excellent noise performance. Long
- 1st conversion time. No natural 50/60Hz rejection.
-
- * "sinc4+sinc1" - Sinc4 + averaging by 8. Low 1st conversion
- time.
-
- * "sinc3" - Sinc3. Moderate 1st conversion time.
- Good noise performance.
-
- * "sinc3+rej60" - Sinc3 + 60Hz rejection. At a sampling
- frequency of 50Hz, achieves simultaneous 50Hz and 60Hz
- rejection.
-
- * "sinc3+sinc1" - Sinc3 + averaging by 8. Low 1st conversion
- time. Best used with a sampling frequency of at least
- 216.19Hz.
-
- * "sinc3+pf1" - Sinc3 + Post Filter 1. 53dB rejection @
- 50Hz, 58dB rejection @ 60Hz.
-
- * "sinc3+pf2" - Sinc3 + Post Filter 2. 70dB rejection @
- 50Hz, 70dB rejection @ 60Hz.
-
- * "sinc3+pf3" - Sinc3 + Post Filter 3. 99dB rejection @
- 50Hz, 103dB rejection @ 60Hz.
-
- * "sinc3+pf4" - Sinc3 + Post Filter 4. 103dB rejection @
- 50Hz, 109dB rejection @ 60Hz.
-
-What: /sys/bus/iio/devices/iio:deviceX/in_voltageY-voltageZ_filter_mode
-KernelVersion: 6.2
-Contact: linux-iio@vger.kernel.org
-Description:
- Set the filter mode of the differential channel. When the filter
- mode changes, the in_voltageY-voltageZ_sampling_frequency and
- in_voltageY-voltageZ_sampling_frequency_available attributes
- might also change to accommodate the new filter mode.
- If the current sampling frequency is out of range for the new
- filter mode, the sampling frequency will be changed to the
- closest valid one.
diff --git a/Documentation/ABI/testing/sysfs-class-typec b/Documentation/ABI/testing/sysfs-class-typec
index 281b995beb05..38e101c17a00 100644
--- a/Documentation/ABI/testing/sysfs-class-typec
+++ b/Documentation/ABI/testing/sysfs-class-typec
@@ -149,6 +149,19 @@ Description:
advertise to the partner. The currently used capabilities are in
brackets. Selection happens by writing to the file.
+What: /sys/class/typec/<port>/usb_capability
+Date: November 2024
+Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description: Lists the supported USB Modes. The default USB mode that is used
+ next time with the Enter_USB Message is in brackets. The default
+ mode can be changed by writing to the file when supported by the
+ driver.
+
+ Valid values:
+ - usb2 (USB 2.0)
+ - usb3 (USB 3.2)
+ - usb4 (USB4)
+
USB Type-C partner devices (eg. /sys/class/typec/port0-partner/)
What: /sys/class/typec/<port>-partner/accessory_mode
@@ -220,6 +233,20 @@ Description:
directory exists, it will have an attribute file for every VDO
in Discover Identity command result.
+What: /sys/class/typec/<port>-partner/usb_mode
+Date: November 2024
+Contact: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Description: The USB Modes that the partner device supports. The active mode
+ is displayed in brackets. The active USB mode can be changed by
+ writing to this file when the port driver is able to send Data
+ Reset Message to the partner. That requires USB Power Delivery
+ contract between the partner and the port.
+
+ Valid values:
+ - usb2 (USB 2.0)
+ - usb3 (USB 3.2)
+ - usb4 (USB4)
+
USB Type-C cable devices (eg. /sys/class/typec/port0-cable/)
Note: Electronically Marked Cables will have a device also for one cable plug
diff --git a/Documentation/ABI/testing/sysfs-class-watchdog b/Documentation/ABI/testing/sysfs-class-watchdog
index 94fb74615951..70eabccf0557 100644
--- a/Documentation/ABI/testing/sysfs-class-watchdog
+++ b/Documentation/ABI/testing/sysfs-class-watchdog
@@ -76,7 +76,7 @@ Description:
timeout when the pretimeout interrupt is delivered. Pretimeout
is an optional feature.
-What: /sys/class/watchdog/watchdogn/pretimeout_avaialable_governors
+What: /sys/class/watchdog/watchdogn/pretimeout_available_governors
Date: February 2017
Contact: Wim Van Sebroeck <wim@iguana.be>
Description:
diff --git a/Documentation/Makefile b/Documentation/Makefile
index fa71602ec961..52c6c5a3efa9 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -104,7 +104,7 @@ quiet_cmd_sphinx = SPHINX $@ --> file://$(abspath $(BUILDDIR)/$3/$4)
YNL_INDEX:=$(srctree)/Documentation/networking/netlink_spec/index.rst
YNL_RST_DIR:=$(srctree)/Documentation/networking/netlink_spec
YNL_YAML_DIR:=$(srctree)/Documentation/netlink/specs
-YNL_TOOL:=$(srctree)/tools/net/ynl/ynl-gen-rst.py
+YNL_TOOL:=$(srctree)/tools/net/ynl/pyynl/ynl_gen_rst.py
YNL_RST_FILES_TMP := $(patsubst %.yaml,%.rst,$(wildcard $(YNL_YAML_DIR)/*.yaml))
YNL_RST_FILES := $(patsubst $(YNL_YAML_DIR)%,$(YNL_RST_DIR)%, $(YNL_RST_FILES_TMP))
diff --git a/Documentation/admin-guide/LSM/apparmor.rst b/Documentation/admin-guide/LSM/apparmor.rst
index 6cf81bbd7ce8..47939ee89d74 100644
--- a/Documentation/admin-guide/LSM/apparmor.rst
+++ b/Documentation/admin-guide/LSM/apparmor.rst
@@ -18,8 +18,11 @@ set ``CONFIG_SECURITY_APPARMOR=y``
If AppArmor should be selected as the default security module then set::
- CONFIG_DEFAULT_SECURITY="apparmor"
- CONFIG_SECURITY_APPARMOR_BOOTPARAM_VALUE=1
+ CONFIG_DEFAULT_SECURITY_APPARMOR=y
+
+The CONFIG_LSM parameter manages the order and selection of LSMs.
+Specify apparmor as the first "major" module (e.g. AppArmor, SELinux, Smack)
+in the list.
Build the kernel
diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index dc663c0ca670..3872bc6ec49d 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -4822,6 +4822,11 @@
can be preempted anytime. Tasks will also yield
contended spinlocks (if the critical section isn't
explicitly preempt disabled beyond the lock itself).
+ lazy - Scheduler controlled. Similar to full but instead
+ of preempting the task immediately, the task gets
+ one HZ tick time to yield itself before the
+ preemption will be forced. One preemption is when the
+ task returns to user space.
print-fatal-signals=
[KNL] debug: print fatal signals
diff --git a/Documentation/admin-guide/laptops/thinkpad-acpi.rst b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
index 7f674a6cfa8a..4ab0fef7d440 100644
--- a/Documentation/admin-guide/laptops/thinkpad-acpi.rst
+++ b/Documentation/admin-guide/laptops/thinkpad-acpi.rst
@@ -445,8 +445,10 @@ event code Key Notes
0x1008 0x07 FN+F8 IBM: toggle screen expand
Lenovo: configure UltraNav,
or toggle screen expand.
- On newer platforms (2024+)
- replaced by 0x131f (see below)
+ On 2024 platforms replaced by
+ 0x131f (see below) and on newer
+ platforms (2025 +) keycode is
+ replaced by 0x1401 (see below).
0x1009 0x08 FN+F9 -
@@ -506,9 +508,11 @@ event code Key Notes
0x1019 0x18 unknown
-0x131f ... FN+F8 Platform Mode change.
+0x131f ... FN+F8 Platform Mode change (2024 systems).
Implemented in driver.
+0x1401 ... FN+F8 Platform Mode change (2025 + systems).
+ Implemented in driver.
... ... ...
0x1020 0x1F unknown
diff --git a/Documentation/admin-guide/mm/transhuge.rst b/Documentation/admin-guide/mm/transhuge.rst
index 5034915f4e8e..8872203df088 100644
--- a/Documentation/admin-guide/mm/transhuge.rst
+++ b/Documentation/admin-guide/mm/transhuge.rst
@@ -436,7 +436,7 @@ AnonHugePmdMapped).
The number of file transparent huge pages mapped to userspace is available
by reading ShmemPmdMapped and ShmemHugePages fields in ``/proc/meminfo``.
To identify what applications are mapping file transparent huge pages, it
-is necessary to read ``/proc/PID/smaps`` and count the FileHugeMapped fields
+is necessary to read ``/proc/PID/smaps`` and count the FilePmdMapped fields
for each mapping.
Note that reading the smaps file is expensive and reading it
diff --git a/Documentation/admin-guide/pm/amd-pstate.rst b/Documentation/admin-guide/pm/amd-pstate.rst
index 210a808b74ec..412423c54f25 100644
--- a/Documentation/admin-guide/pm/amd-pstate.rst
+++ b/Documentation/admin-guide/pm/amd-pstate.rst
@@ -251,9 +251,7 @@ performance supported in `AMD CPPC Performance Capability <perf_cap_>`_).
In some ASICs, the highest CPPC performance is not the one in the ``_CPC``
table, so we need to expose it to sysfs. If boost is not active, but
still supported, this maximum frequency will be larger than the one in
-``cpuinfo``. On systems that support preferred core, the driver will have
-different values for some cores than others and this will reflect the values
-advertised by the platform at bootup.
+``cpuinfo``.
This attribute is read-only.
``amd_pstate_lowest_nonlinear_freq``
diff --git a/Documentation/arch/arm64/silicon-errata.rst b/Documentation/arch/arm64/silicon-errata.rst
index 65bfab1b1861..b42fea07c5ce 100644
--- a/Documentation/arch/arm64/silicon-errata.rst
+++ b/Documentation/arch/arm64/silicon-errata.rst
@@ -255,8 +255,11 @@ stable kernels.
+----------------+-----------------+-----------------+-----------------------------+
| Hisilicon | Hip08 SMMU PMCG | #162001800 | N/A |
+----------------+-----------------+-----------------+-----------------------------+
-| Hisilicon | Hip{08,09,10,10C| #162001900 | N/A |
-| | ,11} SMMU PMCG | | |
+| Hisilicon | Hip{08,09,09A,10| #162001900 | N/A |
+| | ,10C,11} | | |
+| | SMMU PMCG | | |
++----------------+-----------------+-----------------+-----------------------------+
+| Hisilicon | Hip09 | #162100801 | HISILICON_ERRATUM_162100801 |
+----------------+-----------------+-----------------+-----------------------------+
+----------------+-----------------+-----------------+-----------------------------+
| Qualcomm Tech. | Kryo/Falkor v1 | E1003 | QCOM_FALKOR_ERRATUM_1003 |
diff --git a/Documentation/arch/x86/boot.rst b/Documentation/arch/x86/boot.rst
index 4fd492cb4970..ad2d8ddad27f 100644
--- a/Documentation/arch/x86/boot.rst
+++ b/Documentation/arch/x86/boot.rst
@@ -896,10 +896,19 @@ Offset/size: 0x260/4
The kernel runtime start address is determined by the following algorithm::
- if (relocatable_kernel)
- runtime_start = align_up(load_address, kernel_alignment)
- else
- runtime_start = pref_address
+ if (relocatable_kernel) {
+ if (load_address < pref_address)
+ load_address = pref_address;
+ runtime_start = align_up(load_address, kernel_alignment);
+ } else {
+ runtime_start = pref_address;
+ }
+
+Hence the necessary memory window location and size can be estimated by
+a boot loader as::
+
+ memory_window_start = runtime_start;
+ memory_window_size = init_size;
============ ===============
Field name: handover_offset
diff --git a/Documentation/core-api/packing.rst b/Documentation/core-api/packing.rst
index 821691f23c54..0ce2078c8e13 100644
--- a/Documentation/core-api/packing.rst
+++ b/Documentation/core-api/packing.rst
@@ -227,11 +227,119 @@ Intended use
Drivers that opt to use this API first need to identify which of the above 3
quirk combinations (for a total of 8) match what the hardware documentation
-describes. Then they should wrap the packing() function, creating a new
-xxx_packing() that calls it using the proper QUIRK_* one-hot bits set.
+describes.
+
+There are 3 supported usage patterns, detailed below.
+
+packing()
+^^^^^^^^^
+
+This API function is deprecated.
The packing() function returns an int-encoded error code, which protects the
programmer against incorrect API use. The errors are not expected to occur
-during runtime, therefore it is reasonable for xxx_packing() to return void
-and simply swallow those errors. Optionally it can dump stack or print the
-error description.
+during runtime, therefore it is reasonable to wrap packing() into a custom
+function which returns void and swallows those errors. Optionally it can
+dump stack or print the error description.
+
+.. code-block:: c
+
+ void my_packing(void *buf, u64 *val, int startbit, int endbit,
+ size_t len, enum packing_op op)
+ {
+ int err;
+
+ /* Adjust quirks accordingly */
+ err = packing(buf, val, startbit, endbit, len, op, QUIRK_LSW32_IS_FIRST);
+ if (likely(!err))
+ return;
+
+ if (err == -EINVAL) {
+ pr_err("Start bit (%d) expected to be larger than end (%d)\n",
+ startbit, endbit);
+ } else if (err == -ERANGE) {
+ if ((startbit - endbit + 1) > 64)
+ pr_err("Field %d-%d too large for 64 bits!\n",
+ startbit, endbit);
+ else
+ pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
+ *val, startbit, endbit);
+ }
+ dump_stack();
+ }
+
+pack() and unpack()
+^^^^^^^^^^^^^^^^^^^
+
+These are const-correct variants of packing(), and eliminate the last "enum
+packing_op op" argument.
+
+Calling pack(...) is equivalent, and preferred, to calling packing(..., PACK).
+
+Calling unpack(...) is equivalent, and preferred, to calling packing(..., UNPACK).
+
+pack_fields() and unpack_fields()
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+The library exposes optimized functions for the scenario where there are many
+fields represented in a buffer, and it encourages consumer drivers to avoid
+repetitive calls to pack() and unpack() for each field, but instead use
+pack_fields() and unpack_fields(), which reduces the code footprint.
+
+These APIs use field definitions in arrays of ``struct packed_field_u8`` or
+``struct packed_field_u16``, allowing consumer drivers to minimize the size
+of these arrays according to their custom requirements.
+
+The pack_fields() and unpack_fields() API functions are actually macros which
+automatically select the appropriate function at compile time, based on the
+type of the fields array passed in.
+
+An additional benefit over pack() and unpack() is that sanity checks on the
+field definitions are handled at compile time with ``BUILD_BUG_ON`` rather
+than only when the offending code is executed. These functions return void and
+wrapping them to handle unexpected errors is not necessary.
+
+It is recommended, but not required, that you wrap your packed buffer into a
+structured type with a fixed size. This generally makes it easier for the
+compiler to enforce that the correct size buffer is used.
+
+Here is an example of how to use the fields APIs:
+
+.. code-block:: c
+
+ /* Ordering inside the unpacked structure is flexible and can be different
+ * from the packed buffer. Here, it is optimized to reduce padding.
+ */
+ struct data {
+ u64 field3;
+ u32 field4;
+ u16 field1;
+ u8 field2;
+ };
+
+ #define SIZE 13
+
+ typdef struct __packed { u8 buf[SIZE]; } packed_buf_t;
+
+ static const struct packed_field_u8 fields[] = {
+ PACKED_FIELD(100, 90, struct data, field1),
+ PACKED_FIELD(90, 87, struct data, field2),
+ PACKED_FIELD(86, 30, struct data, field3),
+ PACKED_FIELD(29, 0, struct data, field4),
+ };
+
+ void unpack_your_data(const packed_buf_t *buf, struct data *unpacked)
+ {
+ BUILD_BUG_ON(sizeof(*buf) != SIZE;
+
+ unpack_fields(buf, sizeof(*buf), unpacked, fields,
+ QUIRK_LITTLE_ENDIAN);
+ }
+
+ void pack_your_data(const struct data *unpacked, packed_buf_t *buf)
+ {
+ BUILD_BUG_ON(sizeof(*buf) != SIZE;
+
+ pack_fields(buf, sizeof(*buf), unpacked, fields,
+ QUIRK_LITTLE_ENDIAN);
+ }
diff --git a/Documentation/core-api/symbol-namespaces.rst b/Documentation/core-api/symbol-namespaces.rst
index 12e4aecdae94..27a9cccc792c 100644
--- a/Documentation/core-api/symbol-namespaces.rst
+++ b/Documentation/core-api/symbol-namespaces.rst
@@ -46,7 +46,7 @@ Please note that due to macro expansion that argument needs to be a
preprocessor symbol. E.g. to export the symbol ``usb_stor_suspend`` into the
namespace ``USB_STORAGE``, use::
- EXPORT_SYMBOL_NS(usb_stor_suspend, USB_STORAGE);
+ EXPORT_SYMBOL_NS(usb_stor_suspend, "USB_STORAGE");
The corresponding ksymtab entry struct ``kernel_symbol`` will have the member
``namespace`` set accordingly. A symbol that is exported without a namespace will
@@ -68,7 +68,7 @@ is to define the default namespace in the ``Makefile`` of the subsystem. E.g. to
export all symbols defined in usb-common into the namespace USB_COMMON, add a
line like this to drivers/usb/common/Makefile::
- ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON
+ ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE='"USB_COMMON"'
That will affect all EXPORT_SYMBOL() and EXPORT_SYMBOL_GPL() statements. A
symbol exported with EXPORT_SYMBOL_NS() while this definition is present, will
@@ -79,7 +79,7 @@ A second option to define the default namespace is directly in the compilation
unit as preprocessor statement. The above example would then read::
#undef DEFAULT_SYMBOL_NAMESPACE
- #define DEFAULT_SYMBOL_NAMESPACE USB_COMMON
+ #define DEFAULT_SYMBOL_NAMESPACE "USB_COMMON"
within the corresponding compilation unit before any EXPORT_SYMBOL macro is
used.
@@ -94,7 +94,7 @@ for the namespaces it uses symbols from. E.g. a module using the
usb_stor_suspend symbol from above, needs to import the namespace USB_STORAGE
using a statement like::
- MODULE_IMPORT_NS(USB_STORAGE);
+ MODULE_IMPORT_NS("USB_STORAGE");
This will create a ``modinfo`` tag in the module for each imported namespace.
This has the side effect, that the imported namespaces of a module can be
diff --git a/Documentation/dev-tools/autofdo.rst b/Documentation/dev-tools/autofdo.rst
new file mode 100644
index 000000000000..1f0a451e9ccd
--- /dev/null
+++ b/Documentation/dev-tools/autofdo.rst
@@ -0,0 +1,168 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+===================================
+Using AutoFDO with the Linux kernel
+===================================
+
+This enables AutoFDO build support for the kernel when using
+the Clang compiler. AutoFDO (Auto-Feedback-Directed Optimization)
+is a type of profile-guided optimization (PGO) used to enhance the
+performance of binary executables. It gathers information about the
+frequency of execution of various code paths within a binary using
+hardware sampling. This data is then used to guide the compiler's
+optimization decisions, resulting in a more efficient binary. AutoFDO
+is a powerful optimization technique, and data indicates that it can
+significantly improve kernel performance. It's especially beneficial
+for workloads affected by front-end stalls.
+
+For AutoFDO builds, unlike non-FDO builds, the user must supply a
+profile. Acquiring an AutoFDO profile can be done in several ways.
+AutoFDO profiles are created by converting hardware sampling using
+the "perf" tool. It is crucial that the workload used to create these
+perf files is representative; they must exhibit runtime
+characteristics similar to the workloads that are intended to be
+optimized. Failure to do so will result in the compiler optimizing
+for the wrong objective.
+
+The AutoFDO profile often encapsulates the program's behavior. If the
+performance-critical codes are architecture-independent, the profile
+can be applied across platforms to achieve performance gains. For
+instance, using the profile generated on Intel architecture to build
+a kernel for AMD architecture can also yield performance improvements.
+
+There are two methods for acquiring a representative profile:
+(1) Sample real workloads using a production environment.
+(2) Generate the profile using a representative load test.
+When enabling the AutoFDO build configuration without providing an
+AutoFDO profile, the compiler only modifies the dwarf information in
+the kernel without impacting runtime performance. It's advisable to
+use a kernel binary built with the same AutoFDO configuration to
+collect the perf profile. While it's possible to use a kernel built
+with different options, it may result in inferior performance.
+
+One can collect profiles using AutoFDO build for the previous kernel.
+AutoFDO employs relative line numbers to match the profiles, offering
+some tolerance for source changes. This mode is commonly used in a
+production environment for profile collection.
+
+In a profile collection based on a load test, the AutoFDO collection
+process consists of the following steps:
+
+#. Initial build: The kernel is built with AutoFDO options
+ without a profile.
+
+#. Profiling: The above kernel is then run with a representative
+ workload to gather execution frequency data. This data is
+ collected using hardware sampling, via perf. AutoFDO is most
+ effective on platforms supporting advanced PMU features like
+ LBR on Intel machines.
+
+#. AutoFDO profile generation: Perf output file is converted to
+ the AutoFDO profile via offline tools.
+
+The support requires a Clang compiler LLVM 17 or later.
+
+Preparation
+===========
+
+Configure the kernel with::
+
+ CONFIG_AUTOFDO_CLANG=y
+
+Customization
+=============
+
+The default CONFIG_AUTOFDO_CLANG setting covers kernel space objects for
+AutoFDO builds. One can, however, enable or disable AutoFDO build for
+individual files and directories by adding a line similar to the following
+to the respective kernel Makefile:
+
+- For enabling a single file (e.g. foo.o) ::
+
+ AUTOFDO_PROFILE_foo.o := y
+
+- For enabling all files in one directory ::
+
+ AUTOFDO_PROFILE := y
+
+- For disabling one file ::
+
+ AUTOFDO_PROFILE_foo.o := n
+
+- For disabling all files in one directory ::
+
+ AUTOFDO_PROFILE := n
+
+Workflow
+========
+
+Here is an example workflow for AutoFDO kernel:
+
+1) Build the kernel on the host machine with LLVM enabled,
+ for example, ::
+
+ $ make menuconfig LLVM=1
+
+ Turn on AutoFDO build config::
+
+ CONFIG_AUTOFDO_CLANG=y
+
+ With a configuration that with LLVM enabled, use the following command::
+
+ $ scripts/config -e AUTOFDO_CLANG
+
+ After getting the config, build with ::
+
+ $ make LLVM=1
+
+2) Install the kernel on the test machine.
+
+3) Run the load tests. The '-c' option in perf specifies the sample
+ event period. We suggest using a suitable prime number, like 500009,
+ for this purpose.
+
+ - For Intel platforms::
+
+ $ perf record -e BR_INST_RETIRED.NEAR_TAKEN:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
+
+ - For AMD platforms:
+
+ The supported systems are: Zen3 with BRS, or Zen4 with amd_lbr_v2. To check,
+
+ For Zen3::
+
+ $ cat proc/cpuinfo | grep " brs"
+
+ For Zen4::
+
+ $ cat proc/cpuinfo | grep amd_lbr_v2
+
+ The following command generated the perf data file::
+
+ $ perf record --pfm-events RETIRED_TAKEN_BRANCH_INSTRUCTIONS:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
+
+4) (Optional) Download the raw perf file to the host machine.
+
+5) To generate an AutoFDO profile, two offline tools are available:
+ create_llvm_prof and llvm_profgen. The create_llvm_prof tool is part
+ of the AutoFDO project and can be found on GitHub
+ (https://github.com/google/autofdo), version v0.30.1 or later.
+ The llvm_profgen tool is included in the LLVM compiler itself. It's
+ important to note that the version of llvm_profgen doesn't need to match
+ the version of Clang. It needs to be the LLVM 19 release of Clang
+ or later, or just from the LLVM trunk. ::
+
+ $ llvm-profgen --kernel --binary=<vmlinux> --perfdata=<perf_file> -o <profile_file>
+
+ or ::
+
+ $ create_llvm_prof --binary=<vmlinux> --profile=<perf_file> --format=extbinary --out=<profile_file>
+
+ Note that multiple AutoFDO profile files can be merged into one via::
+
+ $ llvm-profdata merge -o <profile_file> <profile_1> <profile_2> ... <profile_n>
+
+6) Rebuild the kernel using the AutoFDO profile file with the same config as step 1,
+ (Note CONFIG_AUTOFDO_CLANG needs to be enabled)::
+
+ $ make LLVM=1 CLANG_AUTOFDO_PROFILE=<profile_file>
diff --git a/Documentation/dev-tools/coccinelle.rst b/Documentation/dev-tools/coccinelle.rst
index 535ce126fb4f..6e70a1e9a3c0 100644
--- a/Documentation/dev-tools/coccinelle.rst
+++ b/Documentation/dev-tools/coccinelle.rst
@@ -250,25 +250,17 @@ variables for .cocciconfig is as follows:
- Your directory from which spatch is called is processed next
- The directory provided with the ``--dir`` option is processed last, if used
-Since coccicheck runs through make, it naturally runs from the kernel
-proper dir; as such the second rule above would be implied for picking up a
-.cocciconfig when using ``make coccicheck``.
-
``make coccicheck`` also supports using M= targets. If you do not supply
any M= target, it is assumed you want to target the entire kernel.
The kernel coccicheck script has::
- if [ "$KBUILD_EXTMOD" = "" ] ; then
- OPTIONS="--dir $srctree $COCCIINCLUDE"
- else
- OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
- fi
-
-KBUILD_EXTMOD is set when an explicit target with M= is used. For both cases
-the spatch ``--dir`` argument is used, as such third rule applies when whether
-M= is used or not, and when M= is used the target directory can have its own
-.cocciconfig file. When M= is not passed as an argument to coccicheck the
-target directory is the same as the directory from where spatch was called.
+ OPTIONS="--dir $srcroot $COCCIINCLUDE"
+
+Here, $srcroot refers to the source directory of the target: it points to the
+external module's source directory when M= used, and otherwise, to the kernel
+source directory. The third rule ensures the spatch reads the .cocciconfig from
+the target directory, allowing external modules to have their own .cocciconfig
+file.
If not using the kernel's coccicheck target, keep the above precedence
order logic of .cocciconfig reading. If using the kernel's coccicheck target,
diff --git a/Documentation/dev-tools/index.rst b/Documentation/dev-tools/index.rst
index 53d4d124f9c5..3c0ac08b2709 100644
--- a/Documentation/dev-tools/index.rst
+++ b/Documentation/dev-tools/index.rst
@@ -34,6 +34,8 @@ Documentation/dev-tools/testing-overview.rst
ktap
checkuapi
gpio-sloppy-logic-analyzer
+ autofdo
+ propeller
.. only:: subproject and html
diff --git a/Documentation/dev-tools/propeller.rst b/Documentation/dev-tools/propeller.rst
new file mode 100644
index 000000000000..92195958e3db
--- /dev/null
+++ b/Documentation/dev-tools/propeller.rst
@@ -0,0 +1,162 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+=====================================
+Using Propeller with the Linux kernel
+=====================================
+
+This enables Propeller build support for the kernel when using Clang
+compiler. Propeller is a profile-guided optimization (PGO) method used
+to optimize binary executables. Like AutoFDO, it utilizes hardware
+sampling to gather information about the frequency of execution of
+different code paths within a binary. Unlike AutoFDO, this information
+is then used right before linking phase to optimize (among others)
+block layout within and across functions.
+
+A few important notes about adopting Propeller optimization:
+
+#. Although it can be used as a standalone optimization step, it is
+ strongly recommended to apply Propeller on top of AutoFDO,
+ AutoFDO+ThinLTO or Instrument FDO. The rest of this document
+ assumes this paradigm.
+
+#. Propeller uses another round of profiling on top of
+ AutoFDO/AutoFDO+ThinLTO/iFDO. The whole build process involves
+ "build-afdo - train-afdo - build-propeller - train-propeller -
+ build-optimized".
+
+#. Propeller requires LLVM 19 release or later for Clang/Clang++
+ and the linker(ld.lld).
+
+#. In addition to LLVM toolchain, Propeller requires a profiling
+ conversion tool: https://github.com/google/autofdo with a release
+ after v0.30.1: https://github.com/google/autofdo/releases/tag/v0.30.1.
+
+The Propeller optimization process involves the following steps:
+
+#. Initial building: Build the AutoFDO or AutoFDO+ThinLTO binary as
+ you would normally do, but with a set of compile-time / link-time
+ flags, so that a special metadata section is created within the
+ kernel binary. The special section is only intend to be used by the
+ profiling tool, it is not part of the runtime image, nor does it
+ change kernel run time text sections.
+
+#. Profiling: The above kernel is then run with a representative
+ workload to gather execution frequency data. This data is collected
+ using hardware sampling, via perf. Propeller is most effective on
+ platforms supporting advanced PMU features like LBR on Intel
+ machines. This step is the same as profiling the kernel for AutoFDO
+ (the exact perf parameters can be different).
+
+#. Propeller profile generation: Perf output file is converted to a
+ pair of Propeller profiles via an offline tool.
+
+#. Optimized build: Build the AutoFDO or AutoFDO+ThinLTO optimized
+ binary as you would normally do, but with a compile-time /
+ link-time flag to pick up the Propeller compile time and link time
+ profiles. This build step uses 3 profiles - the AutoFDO profile,
+ the Propeller compile-time profile and the Propeller link-time
+ profile.
+
+#. Deployment: The optimized kernel binary is deployed and used
+ in production environments, providing improved performance
+ and reduced latency.
+
+Preparation
+===========
+
+Configure the kernel with::
+
+ CONFIG_AUTOFDO_CLANG=y
+ CONFIG_PROPELLER_CLANG=y
+
+Customization
+=============
+
+The default CONFIG_PROPELLER_CLANG setting covers kernel space objects
+for Propeller builds. One can, however, enable or disable Propeller build
+for individual files and directories by adding a line similar to the
+following to the respective kernel Makefile:
+
+- For enabling a single file (e.g. foo.o)::
+
+ PROPELLER_PROFILE_foo.o := y
+
+- For enabling all files in one directory::
+
+ PROPELLER_PROFILE := y
+
+- For disabling one file::
+
+ PROPELLER_PROFILE_foo.o := n
+
+- For disabling all files in one directory::
+
+ PROPELLER__PROFILE := n
+
+
+Workflow
+========
+
+Here is an example workflow for building an AutoFDO+Propeller kernel:
+
+1) Assuming an AutoFDO profile is already collected following
+ instructions in the AutoFDO document, build the kernel on the host
+ machine, with AutoFDO and Propeller build configs ::
+
+ CONFIG_AUTOFDO_CLANG=y
+ CONFIG_PROPELLER_CLANG=y
+
+ and ::
+
+ $ make LLVM=1 CLANG_AUTOFDO_PROFILE=<autofdo-profile-name>
+
+2) Install the kernel on the test machine.
+
+3) Run the load tests. The '-c' option in perf specifies the sample
+ event period. We suggest using a suitable prime number, like 500009,
+ for this purpose.
+
+ - For Intel platforms::
+
+ $ perf record -e BR_INST_RETIRED.NEAR_TAKEN:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
+
+ - For AMD platforms::
+
+ $ perf record --pfm-event RETIRED_TAKEN_BRANCH_INSTRUCTIONS:k -a -N -b -c <count> -o <perf_file> -- <loadtest>
+
+ Note you can repeat the above steps to collect multiple <perf_file>s.
+
+4) (Optional) Download the raw perf file(s) to the host machine.
+
+5) Use the create_llvm_prof tool (https://github.com/google/autofdo) to
+ generate Propeller profile. ::
+
+ $ create_llvm_prof --binary=<vmlinux> --profile=<perf_file>
+ --format=propeller --propeller_output_module_name
+ --out=<propeller_profile_prefix>_cc_profile.txt
+ --propeller_symorder=<propeller_profile_prefix>_ld_profile.txt
+
+ "<propeller_profile_prefix>" can be something like "/home/user/dir/any_string".
+
+ This command generates a pair of Propeller profiles:
+ "<propeller_profile_prefix>_cc_profile.txt" and
+ "<propeller_profile_prefix>_ld_profile.txt".
+
+ If there are more than 1 perf_file collected in the previous step,
+ you can create a temp list file "<perf_file_list>" with each line
+ containing one perf file name and run::
+
+ $ create_llvm_prof --binary=<vmlinux> --profile=@<perf_file_list>
+ --format=propeller --propeller_output_module_name
+ --out=<propeller_profile_prefix>_cc_profile.txt
+ --propeller_symorder=<propeller_profile_prefix>_ld_profile.txt
+
+6) Rebuild the kernel using the AutoFDO and Propeller
+ profiles. ::
+
+ CONFIG_AUTOFDO_CLANG=y
+ CONFIG_PROPELLER_CLANG=y
+
+ and ::
+
+ $ make LLVM=1 CLANG_AUTOFDO_PROFILE=<profile_file> CLANG_PROPELLER_PROFILE_PREFIX=<propeller_profile_prefix>
diff --git a/Documentation/devicetree/bindings/connector/usb-connector.yaml b/Documentation/devicetree/bindings/connector/usb-connector.yaml
index fb216ce68bb3..67700440e23b 100644
--- a/Documentation/devicetree/bindings/connector/usb-connector.yaml
+++ b/Documentation/devicetree/bindings/connector/usb-connector.yaml
@@ -253,6 +253,46 @@ properties:
additionalProperties: false
+ sink-wait-cap-time-ms:
+ description: Represents the max time in ms that USB Type-C port (in sink
+ role) should wait for the port partner (source role) to send source caps.
+ SinkWaitCap timer starts when port in sink role attaches to the source.
+ This timer will stop when sink receives PD source cap advertisement before
+ timeout in which case it'll move to capability negotiation stage. A
+ timeout leads to a hard reset message by the port.
+ minimum: 310
+ maximum: 620
+ default: 310
+
+ ps-source-off-time-ms:
+ description: Represents the max time in ms that a DRP in source role should
+ take to turn off power after the PsSourceOff timer starts. PsSourceOff
+ timer starts when a sink's PHY layer receives EOP of the GoodCRC message
+ (corresponding to an Accept message sent in response to a PR_Swap or a
+ FR_Swap request). This timer stops when last bit of GoodCRC EOP
+ corresponding to the received PS_RDY message is transmitted by the PHY
+ layer. A timeout shall lead to error recovery in the type-c port.
+ minimum: 750
+ maximum: 920
+ default: 920
+
+ cc-debounce-time-ms:
+ description: Represents the max time in ms that a port shall wait to
+ determine if it's attached to a partner.
+ minimum: 100
+ maximum: 200
+ default: 200
+
+ sink-bc12-completion-time-ms:
+ description: Represents the max time in ms that a port in sink role takes
+ to complete Battery Charger (BC1.2) Detection. BC1.2 detection is a
+ hardware mechanism, which in some TCPC implementations, can run in
+ parallel once the Type-C connection state machine reaches the "potential
+ connect as sink" state. In TCPCs where this causes delays to respond to
+ the incoming PD messages, sink-bc12-completion-time-ms is used to delay
+ PD negotiation till BC1.2 detection completes.
+ default: 0
+
dependencies:
sink-vdos-v1: [ sink-vdos ]
sink-vdos: [ sink-vdos-v1 ]
@@ -380,7 +420,7 @@ examples:
};
# USB-C connector attached to a typec port controller(ptn5110), which has
- # power delivery support and enables drp.
+ # power delivery support, explicitly defines time properties and enables drp.
- |
#include <dt-bindings/usb/pd.h>
typec: ptn5110 {
@@ -393,6 +433,10 @@ examples:
sink-pdos = <PDO_FIXED(5000, 2000, PDO_FIXED_USB_COMM)
PDO_VAR(5000, 12000, 2000)>;
op-sink-microwatt = <10000000>;
+ sink-wait-cap-time-ms = <465>;
+ ps-source-off-time-ms = <835>;
+ cc-debounce-time-ms = <101>;
+ sink-bc12-completion-time-ms = <500>;
};
};
diff --git a/Documentation/devicetree/bindings/crypto/fsl,sec-v4.0.yaml b/Documentation/devicetree/bindings/crypto/fsl,sec-v4.0.yaml
index 9c8c9991f29a..f0c4a7c83568 100644
--- a/Documentation/devicetree/bindings/crypto/fsl,sec-v4.0.yaml
+++ b/Documentation/devicetree/bindings/crypto/fsl,sec-v4.0.yaml
@@ -114,8 +114,9 @@ patternProperties:
table that specifies the PPID to LIODN mapping. Needed if the PAMU is
used. Value is a 12 bit value where value is a LIODN ID for this JR.
This property is normally set by boot firmware.
- $ref: /schemas/types.yaml#/definitions/uint32
- maximum: 0xfff
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ items:
+ - maximum: 0xfff
'^rtic@[0-9a-f]+$':
type: object
@@ -186,8 +187,9 @@ patternProperties:
Needed if the PAMU is used. Value is a 12 bit value where value
is a LIODN ID for this JR. This property is normally set by boot
firmware.
- $ref: /schemas/types.yaml#/definitions/uint32
- maximum: 0xfff
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ items:
+ - maximum: 0xfff
fsl,rtic-region:
description:
diff --git a/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml b/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml
index df20a3c9c744..ec89115c74e4 100644
--- a/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml
+++ b/Documentation/devicetree/bindings/display/bridge/adi,adv7533.yaml
@@ -90,7 +90,7 @@ properties:
adi,dsi-lanes:
description: Number of DSI data lanes connected to the DSI host.
$ref: /schemas/types.yaml#/definitions/uint32
- enum: [ 1, 2, 3, 4 ]
+ enum: [ 2, 3, 4 ]
"#sound-dai-cells":
const: 0
diff --git a/Documentation/devicetree/bindings/iio/adc/adc.yaml b/Documentation/devicetree/bindings/iio/adc/adc.yaml
index 8e7835cf36fd..b9bc02b5b07a 100644
--- a/Documentation/devicetree/bindings/iio/adc/adc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adc.yaml
@@ -37,6 +37,10 @@ properties:
to both the positive and negative inputs of a differential ADC.
The first value specifies the positive input pin, the second
specifies the negative input pin.
+ There are also some ADCs, where the differential channel has dedicated
+ positive and negative inputs which can be used to measure differential
+ voltage levels. For those setups, this property can be configured with
+ the 'reg' property for both inputs (i.e. diff-channels = <reg reg>).
single-channel:
$ref: /schemas/types.yaml#/definitions/uint32
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml
index 17c5d39cc2c1..ad15cf9bc2ff 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7173.yaml
@@ -28,6 +28,7 @@ description: |
Datasheets for supported chips:
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4111.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4112.pdf
+ <AD4113: not released yet>
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4114.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4115.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD4116.pdf
@@ -44,6 +45,7 @@ properties:
enum:
- adi,ad4111
- adi,ad4112
+ - adi,ad4113
- adi,ad4114
- adi,ad4115
- adi,ad4116
@@ -331,6 +333,7 @@ allOf:
enum:
- adi,ad4111
- adi,ad4112
+ - adi,ad4113
- adi,ad4114
- adi,ad4115
- adi,ad4116
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
index 0065d6508824..ada08005b3cd 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7380.yaml
@@ -25,6 +25,8 @@ description: |
* https://www.analog.com/en/products/ad7386-4.html
* https://www.analog.com/en/products/ad7387-4.html
* https://www.analog.com/en/products/ad7388-4.html
+ * https://www.analog.com/en/products/adaq4370-4.html
+ * https://www.analog.com/en/products/adaq4380-4.html
$ref: /schemas/spi/spi-peripheral-props.yaml#
@@ -46,6 +48,8 @@ properties:
- adi,ad7386-4
- adi,ad7387-4
- adi,ad7388-4
+ - adi,adaq4370-4
+ - adi,adaq4380-4
reg:
maxItems: 1
@@ -70,6 +74,20 @@ properties:
refin-supply:
description:
A 2.5V to 3.3V supply for external reference voltage, for ad7380-4 only.
+ For adaq devices, a 5V supply voltage. A 3.3V internal reference is
+ derived from it. Connect to vs-p-supply for normal operation.
+
+ vs-p-supply:
+ description:
+ Amplifiers positive supply.
+
+ vs-n-supply:
+ description:
+ Amplifiers negative supply.
+
+ ldo-supply:
+ description:
+ LDO supply. Connect to vs-p-supply or a 3.6 to 5.5 V supply.
aina-supply:
description:
@@ -97,12 +115,45 @@ properties:
specify the ALERT interrupt.
maxItems: 1
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
required:
- compatible
- reg
- vcc-supply
- vlogic-supply
+patternProperties:
+ "^channel@[0-3]$":
+ $ref: adc.yaml
+ type: object
+
+ properties:
+ reg:
+ description:
+ The channel number. From 0 to 3 corresponding to channels A,B,C,D
+ minimum: 0
+ maximum: 3
+
+ adi,gain-milli:
+ description:
+ The hardware gain applied to the ADC input (in milli units).
+ If not present, default to 1000 (no actual gain applied).
+ Refer to the typical connection diagrams section of the datasheet for
+ pin wiring.
+ $ref: /schemas/types.yaml#/definitions/uint16
+ enum: [300, 600, 1000, 1600]
+ default: 1000
+
+ required:
+ - reg
+
+ additionalProperties: false
+
unevaluatedProperties: false
allOf:
@@ -140,6 +191,7 @@ allOf:
aind-supply: false
# ad7380-4 uses refin-supply as external reference.
+ # adaq devices use internal reference only, derived from refin-supply
# All other chips from ad738x family use refio as optional external reference.
# When refio-supply is omitted, internal reference is used.
- if:
@@ -147,6 +199,8 @@ allOf:
compatible:
enum:
- adi,ad7380-4
+ - adi,adaq4370-4
+ - adi,adaq4380-4
then:
properties:
refio-supply: false
@@ -156,6 +210,27 @@ allOf:
properties:
refin-supply: false
+ # adaq devices need more supplies and using channel to declare gain property
+ # only applies to adaq devices
+ - if:
+ properties:
+ compatible:
+ enum:
+ - adi,adaq4370-4
+ - adi,adaq4380-4
+ then:
+ required:
+ - vs-p-supply
+ - vs-n-supply
+ - ldo-supply
+ else:
+ properties:
+ vs-p-supply: false
+ vs-n-supply: false
+ ldo-supply: false
+ patternProperties:
+ "^channel@[0-3]$": false
+
examples:
- |
#include <dt-bindings/interrupt-controller/irq.h>
@@ -180,3 +255,48 @@ examples:
refio-supply = <&supply_2_5V>;
};
};
+
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "adi,adaq4380-4";
+ reg = <0>;
+
+ spi-cpol;
+ spi-cpha;
+ spi-max-frequency = <80000000>;
+
+ interrupts = <27 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-parent = <&gpio0>;
+
+ vcc-supply = <&supply_3_3V>;
+ vlogic-supply = <&supply_3_3V>;
+ refin-supply = <&supply_5V>;
+ vs-p-supply = <&supply_5V>;
+ vs-n-supply = <&supply_0V>;
+ ldo-supply = <&supply_5V>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@0 {
+ reg = <0>;
+ adi,gain-milli = /bits/ 16 <300>;
+ };
+
+ channel@2 {
+ reg = <2>;
+ adi,gain-milli = /bits/ 16 <600>;
+ };
+
+ channel@3 {
+ reg = <3>;
+ adi,gain-milli = /bits/ 16 <1000>;
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
index 69408cae3db9..ab5881d0d017 100644
--- a/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7606.yaml
@@ -14,6 +14,11 @@ description: |
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7605-4.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606_7606-6_7606-4.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7606B.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606c-16.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7606c-18.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7607.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7608.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7609.pdf
https://www.analog.com/media/en/technical-documentation/data-sheets/AD7616.pdf
properties:
@@ -24,11 +29,27 @@ properties:
- adi,ad7606-6
- adi,ad7606-8 # Referred to as AD7606 (without -8) in the datasheet
- adi,ad7606b
+ - adi,ad7606c-16
+ - adi,ad7606c-18
+ - adi,ad7607
+ - adi,ad7608
+ - adi,ad7609
- adi,ad7616
reg:
maxItems: 1
+ "#address-cells":
+ const: 1
+
+ "#size-cells":
+ const: 0
+
+ # According to the datasheet, "Data is clocked in from SDI on the falling
+ # edge of SCLK, while data is clocked out on DOUTA on the rising edge of
+ # SCLK". Also, even if not stated textually in the datasheet, it is made
+ # clear on the diagrams that sclk idles at high. Subsequently, in case SPI
+ # interface is used, the correct way is to only set spi-cpol.
spi-cpha: true
spi-cpol: true
@@ -114,18 +135,91 @@ properties:
assumed that the pins are hardwired to VDD.
type: boolean
+ pwms:
+ description:
+ In case the conversion is triggered by a PWM instead of a GPIO plugged to
+ the CONVST pin, the PWM must be referenced.
+ The first is the PWM connected to CONVST or CONVST1 for the chips with the
+ 2nd PWM connected to CONVST2, if CONVST2 is available and not shorted to
+ CONVST1.
+ minItems: 1
+ maxItems: 2
+
+ pwm-names:
+ items:
+ - const: convst1
+ - const: convst2
+
+ io-backends:
+ description:
+ A reference to the iio-backend, which is responsible handling the BUSY
+ pin's falling edge and communication.
+ An example of backend can be found at
+ http://analogdevicesinc.github.io/hdl/library/axi_ad7606x/index.html
+
+
+patternProperties:
+ "^channel@[1-8]$":
+ type: object
+ $ref: adc.yaml
+ unevaluatedProperties: false
+
+ properties:
+ reg:
+ description:
+ The channel number, as specified in the datasheet (from 1 to 8).
+ minimum: 1
+ maximum: 8
+
+ diff-channels:
+ description:
+ Each channel can be configured as a bipolar differential channel.
+ The ADC uses the same positive and negative inputs for this.
+ This property must be specified as 'reg' (or the channel number) for
+ both positive and negative inputs (i.e. diff-channels = <reg reg>).
+ Since the configuration is bipolar differential, the 'bipolar'
+ property is required.
+ items:
+ minimum: 1
+ maximum: 8
+
+ bipolar:
+ description:
+ The ADC channels can be configured as
+ * Bipolar single-ended
+ * Unipolar single-ended
+ * Bipolar differential
+ Therefore in the DT, if no channel node is specified, it is considered
+ 'unipolar single-ended'. So for the other configurations the 'bipolar'
+ property must be specified. If 'diff-channels' is specified, it is
+ considered a bipolar differential channel. Otherwise it is bipolar
+ single-ended.
+
+ required:
+ - reg
+ - bipolar
+
required:
- compatible
- reg
- - spi-cpha
- avcc-supply
- vdrive-supply
- - interrupts
- - adi,conversion-start-gpios
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
+ - oneOf:
+ - required:
+ - adi,conversion-start-gpios
+ - required:
+ - pwms
+
+ - oneOf:
+ - required:
+ - interrupts
+ - required:
+ - io-backends
+
- if:
properties:
compatible:
@@ -162,19 +256,68 @@ allOf:
- adi,ad7606-4
- adi,ad7606-6
- adi,ad7606-8
+ - adi,ad7607
+ - adi,ad7608
+ - adi,ad7609
then:
properties:
adi,sw-mode: false
else:
properties:
+ pwms:
+ maxItems: 1
+ pwm-names:
+ maxItems: 1
adi,conversion-start-gpios:
maxItems: 1
+ - if:
+ not:
+ required:
+ - adi,sw-mode
+ then:
+ patternProperties:
+ "^channel@[1-8]$": false
+
+ - if:
+ not:
+ properties:
+ compatible:
+ enum:
+ - adi,ad7606c-16
+ - adi,ad7606c-18
+ then:
+ patternProperties:
+ "^channel@[1-8]$": false
+
unevaluatedProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
+ iio-backend {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ adi_adc@0 {
+ compatible = "adi,ad7606b";
+ reg = <0>;
+ pwms = <&axi_pwm_gen 0 0>;
+
+ avcc-supply = <&adc_vref>;
+ vdrive-supply = <&vdd_supply>;
+
+ reset-gpios = <&gpio0 91 GPIO_ACTIVE_HIGH>;
+ standby-gpios = <&gpio0 90 GPIO_ACTIVE_LOW>;
+ adi,range-gpios = <&gpio0 89 GPIO_ACTIVE_HIGH>;
+ adi,oversampling-ratio-gpios = <&gpio0 88 GPIO_ACTIVE_HIGH
+ &gpio0 87 GPIO_ACTIVE_HIGH
+ &gpio0 86 GPIO_ACTIVE_HIGH>;
+ io-backends = <&iio_backend>;
+ };
+ };
+
+ - |
+ #include <dt-bindings/gpio/gpio.h>
#include <dt-bindings/interrupt-controller/irq.h>
spi {
#address-cells = <1>;
@@ -185,7 +328,6 @@ examples:
reg = <0>;
spi-max-frequency = <1000000>;
spi-cpol;
- spi-cpha;
avcc-supply = <&adc_vref>;
vdrive-supply = <&vdd_supply>;
@@ -202,4 +344,53 @@ examples:
standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>;
};
};
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "adi,ad7606c-18";
+ reg = <0>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ spi-max-frequency = <1000000>;
+ spi-cpol;
+
+ avcc-supply = <&adc_vref>;
+ vdrive-supply = <&vdd_supply>;
+
+ interrupts = <25 IRQ_TYPE_EDGE_FALLING>;
+ interrupt-parent = <&gpio>;
+
+ adi,conversion-start-gpios = <&gpio 17 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio 27 GPIO_ACTIVE_HIGH>;
+ adi,first-data-gpios = <&gpio 22 GPIO_ACTIVE_HIGH>;
+ standby-gpios = <&gpio 24 GPIO_ACTIVE_LOW>;
+
+ adi,sw-mode;
+
+ channel@1 {
+ reg = <1>;
+ diff-channels = <1 1>;
+ bipolar;
+ };
+
+ channel@3 {
+ reg = <3>;
+ bipolar;
+ };
+
+ channel@8 {
+ reg = <8>;
+ diff-channels = <8 8>;
+ bipolar;
+ };
+
+ };
+ };
...
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml
new file mode 100644
index 000000000000..8848562af28f
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml
@@ -0,0 +1,176 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/adi,ad7625.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices Fast PulSAR Analog to Digital Converters
+
+maintainers:
+ - Michael Hennerich <Michael.Hennerich@analog.com>
+ - Nuno Sá <nuno.sa@analog.com>
+
+description: |
+ A family of single channel differential analog to digital converters.
+
+ * https://www.analog.com/en/products/ad7625.html
+ * https://www.analog.com/en/products/ad7626.html
+ * https://www.analog.com/en/products/ad7960.html
+ * https://www.analog.com/en/products/ad7961.html
+
+properties:
+ compatible:
+ enum:
+ - adi,ad7625
+ - adi,ad7626
+ - adi,ad7960
+ - adi,ad7961
+
+ vdd1-supply: true
+ vdd2-supply: true
+ vio-supply: true
+
+ ref-supply:
+ description:
+ Voltage regulator for the external reference voltage (REF).
+
+ refin-supply:
+ description:
+ Voltage regulator for the reference buffer input (REFIN).
+
+ clocks:
+ description:
+ The clock connected to the CLK pins, gated by the clk_gate PWM.
+ maxItems: 1
+
+ pwms:
+ items:
+ - description: PWM connected to the CNV input on the ADC.
+ - description: PWM that gates the clock connected to the ADC's CLK input.
+
+ pwm-names:
+ items:
+ - const: cnv
+ - const: clk_gate
+
+ io-backends:
+ description:
+ The AXI ADC IP block connected to the D+/- and DCO+/- lines of the
+ ADC. An example backend can be found at
+ http://analogdevicesinc.github.io/hdl/projects/pulsar_lvds/index.html.
+ maxItems: 1
+
+ adi,no-dco:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicates the wiring of the DCO+/- lines. If true, then they are
+ grounded and the device is in self-clocked mode. If this is not
+ present, then the device is in echoed clock mode.
+
+ adi,en0-always-on:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicates if EN0 is hard-wired to the high state. If neither this
+ nor en0-gpios are present, then EN0 is hard-wired low.
+
+ adi,en1-always-on:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicates if EN1 is hard-wired to the high state. If neither this
+ nor en1-gpios are present, then EN1 is hard-wired low.
+
+ adi,en2-always-on:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicates if EN2 is hard-wired to the high state. If neither this
+ nor en2-gpios are present, then EN2 is hard-wired low.
+
+ adi,en3-always-on:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Indicates if EN3 is hard-wired to the high state. If neither this
+ nor en3-gpios are present, then EN3 is hard-wired low.
+
+ en0-gpios:
+ description:
+ Configurable EN0 pin.
+
+ en1-gpios:
+ description:
+ Configurable EN1 pin.
+
+ en2-gpios:
+ description:
+ Configurable EN2 pin.
+
+ en3-gpios:
+ description:
+ Configurable EN3 pin.
+
+required:
+ - compatible
+ - vdd1-supply
+ - vdd2-supply
+ - vio-supply
+ - clocks
+ - pwms
+ - pwm-names
+ - io-backends
+
+allOf:
+ - if:
+ required:
+ - ref-supply
+ then:
+ properties:
+ refin-supply: false
+ - if:
+ required:
+ - refin-supply
+ then:
+ properties:
+ ref-supply: false
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad7625
+ - adi,ad7626
+ then:
+ properties:
+ en2-gpios: false
+ en3-gpios: false
+ adi,en2-always-on: false
+ adi,en3-always-on: false
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - adi,ad7960
+ - adi,ad7961
+ then:
+ # ad796x parts must have one of the two supplies
+ oneOf:
+ - required: [ref-supply]
+ - required: [refin-supply]
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ adc {
+ compatible = "adi,ad7625";
+ vdd1-supply = <&supply_5V>;
+ vdd2-supply = <&supply_2_5V>;
+ vio-supply = <&supply_2_5V>;
+ io-backends = <&axi_adc>;
+ clocks = <&ref_clk>;
+ pwms = <&axi_pwm_gen 0 0>, <&axi_pwm_gen 1 0>;
+ pwm-names = "cnv", "clk_gate";
+ en0-gpios = <&gpio0 86 GPIO_ACTIVE_HIGH>;
+ en1-gpios = <&gpio0 87 GPIO_ACTIVE_HIGH>;
+ };
diff --git a/Documentation/devicetree/bindings/iio/adc/adi,ad7779.yaml b/Documentation/devicetree/bindings/iio/adc/adi,ad7779.yaml
new file mode 100644
index 000000000000..044f92f39cfa
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/adi,ad7779.yaml
@@ -0,0 +1,110 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/adi,ad7779.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD777X family 8-Channel, 24-Bit, Simultaneous Sampling ADCs
+
+maintainers:
+ - Ramona Nechita <ramona.nechita@analog.com>
+
+description: |
+ The AD777X family consist of 8-channel, simultaneous sampling analog-to-
+ digital converter (ADC). Eight full Σ-Δ ADCs are on-chip. The
+ AD7771 provides an ultralow input current to allow direct sensor
+ connection. Each input channel has a programmable gain stage
+ allowing gains of 1, 2, 4, and 8 to map lower amplitude sensor
+ outputs into the full-scale ADC input range, maximizing the
+ dynamic range of the signal chain.
+
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7770.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7771.pdf
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad7779.pdf
+
+$ref: /schemas/spi/spi-peripheral-props.yaml#
+
+properties:
+ compatible:
+ enum:
+ - adi,ad7770
+ - adi,ad7771
+ - adi,ad7779
+
+ reg:
+ maxItems: 1
+
+ '#address-cells':
+ const: 1
+
+ '#size-cells':
+ const: 0
+
+ clocks:
+ maxItems: 1
+
+ avdd1-supply:
+ description: Front-End analog supply AVDD1. Can be used as conversion ref.
+
+ avdd2-supply:
+ description: AVDD2 Analog Supply from 2.2 V to 3.6 V.
+
+ avdd4-supply:
+ description: AVDD4 SAR Analog Supply and Reference Source.
+
+ interrupts:
+ minItems: 1
+ items:
+ - description: |
+ adc_rdy: Interrupt line for DRDY signal which indicates the end of
+ conversion independently of the interface selected to read back the
+ Σ-∆ conversion.
+ - description: |
+ Alert: The chip includes self diagnostic features to guarantee the
+ correct operation. If an error is detected, the ALERT pin is pulled
+ high to generate an external interruption to the controller.
+
+ interrupt-names:
+ minItems: 1
+ maxItems: 2
+ items:
+ enum:
+ - adc_rdy
+ - alert
+
+ start-gpios:
+ description:
+ Pin that controls start synchronization pulse.
+ maxItems: 1
+
+ reset-gpios:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - interrupts
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@0 {
+ compatible = "adi,ad7779";
+ reg = <0>;
+ start-gpios = <&gpio0 87 GPIO_ACTIVE_LOW>;
+ reset-gpios = <&gpio0 93 GPIO_ACTIVE_LOW>;
+ interrupt-parent = <&intc>;
+ interrupts = <0 56 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "adc_rdy";
+ clocks = <&adc_clk>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml
index f748f3a60b35..b0962a4583ac 100644
--- a/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml
+++ b/Documentation/devicetree/bindings/iio/adc/amlogic,meson-saradc.yaml
@@ -98,6 +98,7 @@ allOf:
compatible:
contains:
enum:
+ - amlogic,meson8-saradc
- amlogic,meson8b-saradc
- amlogic,meson8m2-saradc
then:
diff --git a/Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml b/Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml
new file mode 100644
index 000000000000..2cea7c104a26
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml
@@ -0,0 +1,86 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/adc/gehc,pmc-adc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: GE HealthCare PMC Analog to Digital Converter (ADC)
+
+maintainers:
+ - Herve Codina <herve.codina@bootlin.com>
+
+description:
+ The GE HealthCare PMC ADC is a 16-Channel (voltage and current), 16-Bit ADC
+ with an I2C Interface.
+
+properties:
+ compatible:
+ const: gehc,pmc-adc
+
+ reg:
+ maxItems: 1
+
+ vdd-supply:
+ description:
+ Regulator for the VDD power supply.
+
+ vdda-supply:
+ description:
+ Regulator for the VDD analog (VDDA) power supply.
+
+ vddio-supply:
+ description:
+ Regulator for the VDD IO (VDDIO) power supply.
+
+ vref-supply:
+ description:
+ Regulator for the voltage reference power supply.
+
+ clocks:
+ maxItems: 1
+ description:
+ The component uses an external oscillator (osc) if an external oscillator
+ is connected to its clock pins. Otherwise, it uses an internal reference
+ clock.
+
+ clock-names:
+ items:
+ - const: osc
+
+ "#io-channel-cells":
+ const: 2
+ description: |
+ The first cell is the channel type (dt-bindings/iio/adc/gehc,pmc-adc.h
+ defines these values):
+ - 0: voltage
+ - 1: current
+ The second cell is the channel number from 0 to 15.
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+ - vdda-supply
+ - vddio-supply
+ - vref-supply
+ - '#io-channel-cells'
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ adc@14 {
+ compatible = "gehc,pmc-adc";
+ reg = <0x14>;
+ vdd-supply = <&reg_vdd>;
+ vdda-supply = <&reg_vdda>;
+ vddio-supply = <&reg_vddio>;
+ vref-supply = <&reg_vref>;
+ #io-channel-cells = <2>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
index fc8b97f82077..2d2561a52683 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad3552r.yaml
@@ -30,7 +30,7 @@ properties:
maxItems: 1
spi-max-frequency:
- maximum: 30000000
+ maximum: 66000000
reset-gpios:
maxItems: 1
@@ -60,6 +60,12 @@ properties:
$ref: /schemas/types.yaml#/definitions/uint32
enum: [0, 1, 2, 3]
+ io-backends:
+ description: The iio backend reference.
+ Device can be optionally connected to the "axi-ad3552r IP" fpga-based
+ QSPI + DDR (Double Data Rate) controller to reach high speed transfers.
+ maxItems: 1
+
'#address-cells':
const: 1
@@ -128,6 +134,7 @@ patternProperties:
- custom-output-range-config
allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
- if:
properties:
compatible:
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml
index c81285d84db7..79cb4b78a88a 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad5791.yaml
@@ -26,16 +26,47 @@ properties:
vdd-supply: true
vss-supply: true
+ vcc-supply:
+ description:
+ Supply that powers the chip.
+
+ iovcc-supply:
+ description:
+ Supply for the digital interface.
+
+ vrefp-supply:
+ description:
+ Positive referance input voltage range. From 5v to (vdd - 2.5)
+
+ vrefn-supply:
+ description:
+ Negative referance input voltage range. From (vss + 2.5) to 0.
+
adi,rbuf-gain2-en:
description: Specify to allow an external amplifier to be connected in a
gain of two configuration.
type: boolean
+ reset-gpios:
+ maxItems: 1
+
+ clear-gpios:
+ maxItems: 1
+
+ ldac-gpios:
+ description:
+ LDAC pin to be used as a hardware trigger to update the DAC channels.
+ maxItems: 1
+
required:
- compatible
- reg
- vdd-supply
- vss-supply
+ - vcc-supply
+ - iovcc-supply
+ - vrefp-supply
+ - vrefn-supply
allOf:
- $ref: /schemas/spi/spi-peripheral-props.yaml#
@@ -44,6 +75,7 @@ unevaluatedProperties: false
examples:
- |
+ #include <dt-bindings/gpio/gpio.h>
spi {
#address-cells = <1>;
#size-cells = <0>;
@@ -53,6 +85,13 @@ examples:
reg = <0>;
vss-supply = <&dac_vss>;
vdd-supply = <&dac_vdd>;
+ vcc-supply = <&dac_vcc>;
+ iovcc-supply = <&dac_iovcc>;
+ vrefp-supply = <&dac_vrefp>;
+ vrefn-supply = <&dac_vrefn>;
+ reset-gpios = <&gpio_bd 16 GPIO_ACTIVE_LOW>;
+ clear-gpios = <&gpio_bd 17 GPIO_ACTIVE_LOW>;
+ ldac-gpios = <&gpio_bd 18 GPIO_ACTIVE_HIGH>;
};
};
...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml b/Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml
new file mode 100644
index 000000000000..b65928024e12
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml
@@ -0,0 +1,164 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+# Copyright 2024 Analog Devices Inc.
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/dac/adi,ad8460.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Analog Devices AD8460 DAC
+
+maintainers:
+ - Mariel Tinaco <mariel.tinaco@analog.com>
+
+description: |
+ Analog Devices AD8460 110 V High Voltage, 1 A High Current,
+ Arbitrary Waveform Generator with Integrated 14-Bit High Speed DAC
+ https://www.analog.com/media/en/technical-documentation/data-sheets/ad8460.pdf
+
+properties:
+ compatible:
+ enum:
+ - adi,ad8460
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ dmas:
+ maxItems: 1
+
+ dma-names:
+ items:
+ - const: tx
+
+ spi-max-frequency:
+ maximum: 20000000
+
+ hvcc-supply:
+ description: Positive high voltage power supply line
+
+ hvee-supply:
+ description: Negative high voltage power supply line
+
+ vcc-5v-supply:
+ description: Low voltage power supply
+
+ vref-5v-supply:
+ description: Reference voltage for analog low voltage
+
+ dvdd-3p3v-supply:
+ description: Digital supply bypass
+
+ avdd-3p3v-supply:
+ description: Analog supply bypass
+
+ refio-1p2v-supply:
+ description: Drive voltage in the range of 1.2V maximum to as low as
+ low as 0.12V through the REF_IO pin to adjust full scale output span
+
+ adi,external-resistor-ohms:
+ description: Specify value of external resistor connected to FS_ADJ pin
+ to establish internal HVDAC's reference current I_REF
+ minimum: 2000
+ maximum: 20000
+ default: 2000
+
+ adi,range-microvolt:
+ description: Voltage output range specified as <minimum, maximum>
+ items:
+ - minimum: -55000000
+ maximum: 0
+ default: 0
+ - minimum: 0
+ maximum: 55000000
+ default: 0
+
+ adi,range-microamp:
+ description: Current output range specified as <minimum, maximum>
+ items:
+ - minimum: -1000000
+ maximum: 0
+ default: 0
+ - minimum: 0
+ maximum: 1000000
+ default: 0
+
+ adi,max-millicelsius:
+ description: Overtemperature threshold
+ minimum: 0
+ maximum: 150000
+ default: 0
+
+ shutdown-reset-gpios:
+ description: Corresponds to SDN_RESET pin. To exit shutdown
+ or sleep mode, pulse SDN_RESET HIGH, then leave LOW.
+ maxItems: 1
+
+ reset-gpios:
+ description: Manual Power On Reset (POR). Pull this GPIO pin
+ LOW and then HIGH to reset all digital registers to default
+ maxItems: 1
+
+ shutdown-gpios:
+ description: Corresponds to SDN_IO pin. Shutdown may be
+ initiated by the user, by pulsing SDN_IO high. To exit shutdown,
+ pulse SDN_IO low, then float.
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - hvcc-supply
+ - hvee-supply
+ - vcc-5v-supply
+ - vref-5v-supply
+ - dvdd-3p3v-supply
+ - avdd-3p3v-supply
+ - refio-1p2v-supply
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@0 {
+ compatible = "adi,ad8460";
+ reg = <0>;
+ spi-max-frequency = <8000000>;
+
+ dmas = <&tx_dma 0>;
+ dma-names = "tx";
+
+ shutdown-reset-gpios = <&gpio 86 GPIO_ACTIVE_HIGH>;
+ reset-gpios = <&gpio 91 GPIO_ACTIVE_LOW>;
+ shutdown-gpios = <&gpio 88 GPIO_ACTIVE_HIGH>;
+
+ clocks = <&sync_ext_clk>;
+
+ hvcc-supply = <&hvcc>;
+ hvee-supply = <&hvee>;
+ vcc-5v-supply = <&vcc_5>;
+ vref-5v-supply = <&vref_5>;
+ dvdd-3p3v-supply = <&dvdd_3_3>;
+ avdd-3p3v-supply = <&avdd_3_3>;
+ refio-1p2v-supply = <&refio_1_2>;
+
+ adi,external-resistor-ohms = <2000>;
+ adi,range-microvolt = <(-40000000) 40000000>;
+ adi,range-microamp = <0 50000>;
+ adi,max-millicelsius = <50000>;
+ };
+ };
+
+...
diff --git a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
index a55e9bfc66d7..1adba9aceeb1 100644
--- a/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
+++ b/Documentation/devicetree/bindings/iio/dac/adi,axi-dac.yaml
@@ -19,11 +19,13 @@ description: |
memory via DMA into the DAC.
https://wiki.analog.com/resources/fpga/docs/axi_dac_ip
+ https://analogdevicesinc.github.io/hdl/library/axi_ad3552r/index.html
properties:
compatible:
enum:
- adi,axi-dac-9.1.b
+ - adi,axi-ad3552r
reg:
maxItems: 1
@@ -36,7 +38,14 @@ properties:
- const: tx
clocks:
- maxItems: 1
+ minItems: 1
+ maxItems: 2
+
+ clock-names:
+ items:
+ - const: s_axi_aclk
+ - const: dac_clk
+ minItems: 1
'#io-backend-cells':
const: 0
@@ -47,7 +56,29 @@ required:
- reg
- clocks
-additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ const: adi,axi-ad3552r
+ then:
+ $ref: /schemas/spi/spi-controller.yaml#
+ properties:
+ clocks:
+ minItems: 2
+ clock-names:
+ minItems: 2
+ required:
+ - clock-names
+ else:
+ properties:
+ clocks:
+ maxItems: 1
+ clock-names:
+ maxItems: 1
+
+unevaluatedProperties: false
examples:
- |
@@ -57,6 +88,38 @@ examples:
dmas = <&tx_dma 0>;
dma-names = "tx";
#io-backend-cells = <0>;
- clocks = <&axi_clk>;
+ clocks = <&clkc 15>;
+ clock-names = "s_axi_aclk";
+ };
+
+ - |
+ #include <dt-bindings/gpio/gpio.h>
+ axi_dac: spi@44a70000 {
+ compatible = "adi,axi-ad3552r";
+ reg = <0x44a70000 0x1000>;
+ dmas = <&dac_tx_dma 0>;
+ dma-names = "tx";
+ #io-backend-cells = <0>;
+ clocks = <&clkc 15>, <&ref_clk>;
+ clock-names = "s_axi_aclk", "dac_clk";
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ dac@0 {
+ compatible = "adi,ad3552r";
+ reg = <0>;
+ reset-gpios = <&gpio0 92 GPIO_ACTIVE_HIGH>;
+ io-backends = <&axi_dac>;
+ spi-max-frequency = <20000000>;
+
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ channel@0 {
+ reg = <0>;
+ adi,output-range-microvolt = <(-10000000) (10000000)>;
+ };
+ };
};
...
diff --git a/Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml b/Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml
new file mode 100644
index 000000000000..7b0cde1c9b0a
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml
@@ -0,0 +1,79 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/imu/bosch,bmi270.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Bosch BMI270 6-Axis IMU
+
+maintainers:
+ - Alex Lanzano <lanzano.alex@gmail.com>
+
+description: |
+ BMI270 is a 6-axis inertial measurement unit that can measure acceleration and
+ angular velocity. The sensor also supports configurable interrupt events such
+ as motion, step counter, and wrist motion gestures. The sensor can communicate
+ I2C or SPI.
+ https://www.bosch-sensortec.com/products/motion-sensors/imus/bmi270/
+
+properties:
+ compatible:
+ enum:
+ - bosch,bmi260
+ - bosch,bmi270
+
+ reg:
+ maxItems: 1
+
+ vdd-supply: true
+ vddio-supply: true
+
+ interrupts:
+ minItems: 1
+ maxItems: 2
+
+ interrupt-names:
+ minItems: 1
+ maxItems: 2
+ items:
+ enum:
+ - INT1
+ - INT2
+
+ drive-open-drain:
+ description:
+ set if the specified interrupt pins should be configured as
+ open drain. If not set, defaults to push-pull.
+
+ mount-matrix:
+ description:
+ an optional 3x3 mounting rotation matrix.
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+ - vddio-supply
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ imu@68 {
+ compatible = "bosch,bmi270";
+ reg = <0x68>;
+ vdd-supply = <&vdd>;
+ vddio-supply = <&vddio>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <16 IRQ_TYPE_EDGE_RISING>;
+ interrupt-names = "INT1";
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/imu/bosch,smi240.yaml b/Documentation/devicetree/bindings/iio/imu/bosch,smi240.yaml
new file mode 100644
index 000000000000..58f1411728f6
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/imu/bosch,smi240.yaml
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/imu/bosch,smi240.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Bosch smi240 imu
+
+maintainers:
+ - Jianping Shen <Jianping.Shen@de.bosch.com>
+
+description:
+ Inertial Measurement Unit with Accelerometer and Gyroscope
+ with a measurement range of +/-300°/s and up to 16g.
+ https://www.bosch-semiconductors.com/mems-sensors/highly-automated-driving/smi240/
+
+properties:
+ compatible:
+ const: bosch,smi240
+
+ reg:
+ maxItems: 1
+
+ vdd-supply: true
+ vddio-supply: true
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+ - vddio-supply
+
+allOf:
+ - $ref: /schemas/spi/spi-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ spi {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ imu@0 {
+ compatible = "bosch,smi240";
+ reg = <0>;
+ vdd-supply = <&vdd>;
+ vddio-supply = <&vddio>;
+ spi-max-frequency = <10000000>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
index 3769f8e8e98c..7e4492bbd027 100644
--- a/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,icm42600.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: InvenSense ICM-426xx Inertial Measurement Unit
maintainers:
- - Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
+ - Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
description: |
6-axis MotionTracking device that combines a 3-axis gyroscope and a 3-axis
diff --git a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
index 587ff2bced2d..f91954870a44 100644
--- a/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
+++ b/Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
@@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
title: InvenSense MPU-6050 Six-Axis (Gyro + Accelerometer) MEMS MotionTracking Device
maintainers:
- - Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
+ - Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
description: |
These devices support both I2C and SPI bus interfaces.
@@ -36,6 +36,11 @@ properties:
- items:
- const: invensense,icm20608d
- const: invensense,icm20608
+ - items:
+ - enum:
+ - invensense,iam20680hp
+ - invensense,iam20680ht
+ - const: invensense,iam20680
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/light/ti,opt3001.yaml b/Documentation/devicetree/bindings/iio/light/ti,opt3001.yaml
index 441e9343fc97..67ca8d08256a 100644
--- a/Documentation/devicetree/bindings/iio/light/ti,opt3001.yaml
+++ b/Documentation/devicetree/bindings/iio/light/ti,opt3001.yaml
@@ -15,7 +15,9 @@ description: |
properties:
compatible:
- const: ti,opt3001
+ enum:
+ - ti,opt3001
+ - ti,opt3002
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/iio/light/veml6030.yaml b/Documentation/devicetree/bindings/iio/light/veml6030.yaml
deleted file mode 100644
index fb19a2d7a849..000000000000
--- a/Documentation/devicetree/bindings/iio/light/veml6030.yaml
+++ /dev/null
@@ -1,64 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0+
-%YAML 1.2
----
-$id: http://devicetree.org/schemas/iio/light/veml6030.yaml#
-$schema: http://devicetree.org/meta-schemas/core.yaml#
-
-title: VEML6030 Ambient Light Sensor (ALS)
-
-maintainers:
- - Rishi Gupta <gupt21@gmail.com>
-
-description: |
- Bindings for the ambient light sensor veml6030 from Vishay
- Semiconductors over an i2c interface.
-
- Irrespective of whether interrupt is used or not, application
- can get the ALS and White channel reading from IIO raw interface.
-
- If the interrupts are used, application will receive an IIO event
- whenever configured threshold is crossed.
-
- Specifications about the sensor can be found at:
- https://www.vishay.com/docs/84366/veml6030.pdf
-
-properties:
- compatible:
- enum:
- - vishay,veml6030
-
- reg:
- description:
- I2C address of the device.
- enum:
- - 0x10 # ADDR pin pulled down
- - 0x48 # ADDR pin pulled up
-
- interrupts:
- description:
- interrupt mapping for IRQ. Configure with IRQ_TYPE_LEVEL_LOW.
- Refer to interrupt-controller/interrupts.txt for generic
- interrupt client node bindings.
- maxItems: 1
-
-required:
- - compatible
- - reg
-
-additionalProperties: false
-
-examples:
- - |
- #include <dt-bindings/interrupt-controller/irq.h>
-
- i2c {
- #address-cells = <1>;
- #size-cells = <0>;
-
- light-sensor@10 {
- compatible = "vishay,veml6030";
- reg = <0x10>;
- interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
- };
- };
-...
diff --git a/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml b/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml
new file mode 100644
index 000000000000..4ea69f1fdd63
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml
@@ -0,0 +1,107 @@
+# SPDX-License-Identifier: GPL-2.0+
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/light/vishay,veml6030.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: VEML3235, VEML6030, VEML6035 and VEML7700 Ambient Light Sensors (ALS)
+
+maintainers:
+ - Rishi Gupta <gupt21@gmail.com>
+
+description: |
+ Bindings for the ambient light sensors veml6030 and veml6035 from
+ Vishay Semiconductors over an i2c interface.
+
+ Irrespective of whether interrupt is used or not, application
+ can get the ALS and White channel reading from IIO raw interface.
+
+ If the interrupts are used, application will receive an IIO event
+ whenever configured threshold is crossed.
+
+ Specifications about the sensors can be found at:
+ https://www.vishay.com/docs/80131/veml3235.pdf
+ https://www.vishay.com/docs/84366/veml6030.pdf
+ https://www.vishay.com/docs/84889/veml6035.pdf
+ https://www.vishay.com/docs/84286/veml7700.pdf
+
+properties:
+ compatible:
+ enum:
+ - vishay,veml3235
+ - vishay,veml6030
+ - vishay,veml6035
+ - vishay,veml7700
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ description:
+ interrupt mapping for IRQ. Configure with IRQ_TYPE_LEVEL_LOW.
+ Refer to interrupt-controller/interrupts.txt for generic
+ interrupt client node bindings.
+ maxItems: 1
+
+ vdd-supply: true
+
+required:
+ - compatible
+ - reg
+ - vdd-supply
+
+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - vishay,veml6030
+ then:
+ properties:
+ reg:
+ enum:
+ - 0x10 # ADDR pin pulled down
+ - 0x48 # ADDR pin pulled up
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - vishay,veml6035
+ then:
+ properties:
+ reg:
+ enum:
+ - 0x29
+
+ - if:
+ properties:
+ compatible:
+ enum:
+ - vishay,veml3235
+ - vishay,veml7700
+ then:
+ properties:
+ reg:
+ enum:
+ - 0x10
+ interrupts: false
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ light-sensor@10 {
+ compatible = "vishay,veml6030";
+ reg = <0x10>;
+ interrupts = <12 IRQ_TYPE_LEVEL_LOW>;
+ vdd-supply = <&vdd>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml b/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml
index ecf2339e02f6..d2effccbfb56 100644
--- a/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml
+++ b/Documentation/devicetree/bindings/iio/light/vishay,veml6075.yaml
@@ -4,7 +4,7 @@
$id: http://devicetree.org/schemas/iio/light/vishay,veml6075.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
-title: Vishay VEML6075 UVA/B and VEML6040 RGBW sensors
+title: Vishay VEML6070 UVA, VEML6075 UVA/B and VEML6040 RGBW sensors
maintainers:
- Javier Carrasco <javier.carrasco.cruz@gmail.com>
@@ -16,11 +16,19 @@ properties:
compatible:
enum:
- vishay,veml6040
+ - vishay,veml6070
- vishay,veml6075
reg:
maxItems: 1
+ vishay,rset-ohms:
+ description:
+ Resistor used to select the integration time.
+ default: 270000
+ minimum: 75000
+ maximum: 1200000
+
vdd-supply: true
required:
@@ -28,6 +36,17 @@ required:
- reg
- vdd-supply
+allOf:
+ - if:
+ properties:
+ compatible:
+ enum:
+ - vishay,veml6040
+ - vishay,veml6075
+ then:
+ properties:
+ vishay,rset-ohms: false
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/iio/magnetometer/allegromicro,als31300.yaml b/Documentation/devicetree/bindings/iio/magnetometer/allegromicro,als31300.yaml
new file mode 100644
index 000000000000..52e3781834ee
--- /dev/null
+++ b/Documentation/devicetree/bindings/iio/magnetometer/allegromicro,als31300.yaml
@@ -0,0 +1,46 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/iio/magnetometer/allegromicro,als31300.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Allegro MicroSystems ALS31300 3-D Linear Hall Effect sensor
+
+maintainers:
+ - Neil Armstrong <neil.armstrong@linaro.org>
+
+properties:
+ $nodename:
+ pattern: '^magnetometer@[0-9a-f]+$'
+
+ compatible:
+ enum:
+ - allegromicro,als31300-500 # Factory configured at 500 Gauss input range
+ - allegromicro,als31300-1000 # Factory configured at 1000 Gauss input range
+ - allegromicro,als31300-2000 # Factory configured at 2000 Gauss input range
+
+ reg:
+ maxItems: 1
+
+ vcc-supply:
+ description: 5.5V supply
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+
+additionalProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ magnetometer@61 {
+ compatible = "allegromicro,als31300-500";
+ reg = <0x61>;
+ vcc-supply = <&hall_vcc>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
index 6fda887ee9d4..cb201cecfa1a 100644
--- a/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
+++ b/Documentation/devicetree/bindings/iio/pressure/bmp085.yaml
@@ -47,15 +47,33 @@ properties:
maxItems: 1
interrupts:
- description:
- interrupt mapping for IRQ (BMP085 only)
maxItems: 1
+ drive-open-drain:
+ description:
+ set if the interrupt pin should be configured as open drain.
+ If not set, defaults to push-pull configuration.
+ type: boolean
+
required:
- compatible
- vddd-supply
- vdda-supply
+allOf:
+ - if:
+ properties:
+ compatible:
+ not:
+ contains:
+ enum:
+ - bosch,bmp085
+ - bosch,bmp380
+ - bosch,bmp580
+ then:
+ properties:
+ interrupts: false
+
additionalProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml b/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml
index d43002b9bfdc..590f50ba3a31 100644
--- a/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml
+++ b/Documentation/devicetree/bindings/iio/temperature/ti,tmp006.yaml
@@ -23,6 +23,9 @@ properties:
vdd-supply:
description: provide VDD power to the sensor.
+ interrupts:
+ maxItems: 1
+
required:
- compatible
- reg
@@ -31,6 +34,7 @@ additionalProperties: false
examples:
- |
+ #include <dt-bindings/interrupt-controller/irq.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
@@ -38,5 +42,7 @@ examples:
compatible = "ti,tmp006";
reg = <0x40>;
vdd-supply = <&ldo4_reg>;
+ interrupt-parent = <&gpio1>;
+ interrupts = <4 IRQ_TYPE_EDGE_FALLING>;
};
};
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
index 189f5900ee50..251410aabf38 100644
--- a/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
+++ b/Documentation/devicetree/bindings/interconnect/qcom,msm8998-bwmon.yaml
@@ -26,6 +26,7 @@ properties:
- items:
- enum:
- qcom,qcm2290-cpu-bwmon
+ - qcom,qcs8300-cpu-bwmon
- qcom,sa8775p-cpu-bwmon
- qcom,sc7180-cpu-bwmon
- qcom,sc7280-cpu-bwmon
@@ -40,6 +41,7 @@ properties:
- const: qcom,sdm845-bwmon # BWMON v4, unified register space
- items:
- enum:
+ - qcom,qcs8300-llcc-bwmon
- qcom,sa8775p-llcc-bwmon
- qcom,sc7180-llcc-bwmon
- qcom,sc8280xp-llcc-bwmon
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml
new file mode 100644
index 000000000000..9d762b2a1fcf
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,qcs615-rpmh.yaml
@@ -0,0 +1,73 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,qcs615-rpmh.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm RPMh Network-On-Chip Interconnect on QCS615
+
+maintainers:
+ - Raviteja Laggyshetty <quic_rlaggysh@quicinc.com>
+
+description: |
+ RPMh interconnect providers support system bandwidth requirements through
+ RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is
+ able to communicate with the BCM through the Resource State Coordinator (RSC)
+ associated with each execution environment. Provider nodes must point to at
+ least one RPMh device child node pertaining to their RSC and each provider
+ can map to multiple RPMh resources.
+
+ See also: include/dt-bindings/interconnect/qcom,qcs615-rpmh.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,qcs615-aggre1-noc
+ - qcom,qcs615-camnoc-virt
+ - qcom,qcs615-config-noc
+ - qcom,qcs615-dc-noc
+ - qcom,qcs615-gem-noc
+ - qcom,qcs615-ipa-virt
+ - qcom,qcs615-mc-virt
+ - qcom,qcs615-mmss-noc
+ - qcom,qcs615-system-noc
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+
+allOf:
+ - $ref: qcom,rpmh-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcs615-camnoc-virt
+ - qcom,qcs615-ipa-virt
+ - qcom,qcs615-mc-virt
+ then:
+ properties:
+ reg: false
+ else:
+ required:
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ gem_noc: interconnect@9680000 {
+ compatible = "qcom,qcs615-gem-noc";
+ reg = <0x9680000 0x3e200>;
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
+
+ mc_virt: interconnect-2 {
+ compatible = "qcom,qcs615-mc-virt";
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml
new file mode 100644
index 000000000000..e9f528d6d9a8
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,qcs8300-rpmh.yaml
@@ -0,0 +1,72 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,qcs8300-rpmh.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm RPMh Network-On-Chip Interconnect on QCS8300
+
+maintainers:
+ - Raviteja Laggyshetty <quic_rlaggysh@quicinc.com>
+
+description: |
+ RPMh interconnect providers support system bandwidth requirements through
+ RPMh hardware accelerators known as Bus Clock Manager (BCM).
+
+ See also: include/dt-bindings/interconnect/qcom,qcs8300-rpmh.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,qcs8300-aggre1-noc
+ - qcom,qcs8300-aggre2-noc
+ - qcom,qcs8300-clk-virt
+ - qcom,qcs8300-config-noc
+ - qcom,qcs8300-dc-noc
+ - qcom,qcs8300-gem-noc
+ - qcom,qcs8300-gpdsp-anoc
+ - qcom,qcs8300-lpass-ag-noc
+ - qcom,qcs8300-mc-virt
+ - qcom,qcs8300-mmss-noc
+ - qcom,qcs8300-nspa-noc
+ - qcom,qcs8300-pcie-anoc
+ - qcom,qcs8300-system-noc
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+
+allOf:
+ - $ref: qcom,rpmh-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,qcs8300-clk-virt
+ - qcom,qcs8300-mc-virt
+ then:
+ properties:
+ reg: false
+ else:
+ required:
+ - reg
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ gem_noc: interconnect@9100000 {
+ compatible = "qcom,qcs8300-gem-noc";
+ reg = <0x9100000 0xf7080>;
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
+
+ clk_virt: interconnect-0 {
+ compatible = "qcom,qcs8300-clk-virt";
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
diff --git a/Documentation/devicetree/bindings/interconnect/qcom,sar2130p-rpmh.yaml b/Documentation/devicetree/bindings/interconnect/qcom,sar2130p-rpmh.yaml
new file mode 100644
index 000000000000..4647dac740e9
--- /dev/null
+++ b/Documentation/devicetree/bindings/interconnect/qcom,sar2130p-rpmh.yaml
@@ -0,0 +1,117 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/interconnect/qcom,sar2130p-rpmh.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm RPMh Network-On-Chip Interconnect on SAR2130P
+
+maintainers:
+ - Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+ - Georgi Djakov <djakov@kernel.org>
+
+description: |
+ RPMh interconnect providers support system bandwidth requirements through
+ RPMh hardware accelerators known as Bus Clock Manager (BCM). The provider is
+ able to communicate with the BCM through the Resource State Coordinator (RSC)
+ associated with each execution environment. Provider nodes must point to at
+ least one RPMh device child node pertaining to their RSC and each provider
+ can map to multiple RPMh resources.
+
+ See also:: include/dt-bindings/interconnect/qcom,sar2130p-rpmh.h
+
+properties:
+ compatible:
+ enum:
+ - qcom,sar2130p-clk-virt
+ - qcom,sar2130p-config-noc
+ - qcom,sar2130p-gem-noc
+ - qcom,sar2130p-lpass-ag-noc
+ - qcom,sar2130p-mc-virt
+ - qcom,sar2130p-mmss-noc
+ - qcom,sar2130p-nsp-noc
+ - qcom,sar2130p-pcie-anoc
+ - qcom,sar2130p-system-noc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ minItems: 1
+ maxItems: 2
+
+required:
+ - compatible
+
+allOf:
+ - $ref: qcom,rpmh-common.yaml#
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sar2130p-clk-virt
+ - qcom,sar2130p-mc-virt
+ then:
+ properties:
+ reg: false
+ else:
+ required:
+ - reg
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sar2130p-pcie-anoc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: aggre-NOC PCIe AXI clock
+ - description: cfg-NOC PCIe a-NOC AHB clock
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sar2130p-system-noc
+ then:
+ properties:
+ clocks:
+ items:
+ - description: aggre USB3 PRIM AXI clock
+
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - qcom,sar2130p-system-noc
+ - qcom,sar2130p-pcie-anoc
+ then:
+ required:
+ - clocks
+ else:
+ properties:
+ clocks: false
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ clk_virt: interconnect-0 {
+ compatible = "qcom,sar2130p-clk-virt";
+ #interconnect-cells = <2>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
+
+ aggre1_noc: interconnect@1680000 {
+ compatible = "qcom,sar2130p-system-noc";
+ reg = <0x01680000 0x29080>;
+ #interconnect-cells = <2>;
+ clocks = <&gcc_prim_axi_clk>;
+ qcom,bcm-voters = <&apps_bcm_voter>;
+ };
diff --git a/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
index 058253d6d889..62086366837c 100644
--- a/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
+++ b/Documentation/devicetree/bindings/mtd/partitions/fixed-partitions.yaml
@@ -82,7 +82,7 @@ examples:
uimage@100000 {
reg = <0x0100000 0x200000>;
- compress = "lzma";
+ compression = "lzma";
};
};
diff --git a/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml b/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml
index d1e2bca3c503..798a4c19f18c 100644
--- a/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/amlogic,meson-dwmac.yaml
@@ -166,11 +166,11 @@ unevaluatedProperties: false
examples:
- |
ethmac: ethernet@c9410000 {
- compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
- reg = <0xc9410000 0x10000>, <0xc8834540 0x8>;
- interrupts = <8>;
- interrupt-names = "macirq";
- clocks = <&clk_eth>, <&clk_fclk_div2>, <&clk_mpll2>, <&clk_fclk_div2>;
- clock-names = "stmmaceth", "clkin0", "clkin1", "timing-adjustment";
- phy-mode = "rgmii";
+ compatible = "amlogic,meson-gxbb-dwmac", "snps,dwmac";
+ reg = <0xc9410000 0x10000>, <0xc8834540 0x8>;
+ interrupts = <8>;
+ interrupt-names = "macirq";
+ clocks = <&clk_eth>, <&clk_fclk_div2>, <&clk_mpll2>, <&clk_fclk_div2>;
+ clock-names = "stmmaceth", "clkin0", "clkin1", "timing-adjustment";
+ phy-mode = "rgmii";
};
diff --git a/Documentation/devicetree/bindings/net/asix,ax88178.yaml b/Documentation/devicetree/bindings/net/asix,ax88178.yaml
index 768504ccbf74..03341b7438d5 100644
--- a/Documentation/devicetree/bindings/net/asix,ax88178.yaml
+++ b/Documentation/devicetree/bindings/net/asix,ax88178.yaml
@@ -63,8 +63,8 @@ examples:
#size-cells = <0>;
ethernet@1 {
- compatible = "usbb95,772b";
- reg = <1>;
+ compatible = "usbb95,772b";
+ reg = <1>;
};
};
};
diff --git a/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml b/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml
index 7c90a4390531..0e3fb4e42e3f 100644
--- a/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml
+++ b/Documentation/devicetree/bindings/net/brcm,bcmgenet.yaml
@@ -85,16 +85,16 @@ examples:
#size-cells = <1>;
mdio0: mdio@e14 {
- compatible = "brcm,genet-mdio-v4";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0xe14 0x8>;
+ compatible = "brcm,genet-mdio-v4";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xe14 0x8>;
- phy1: ethernet-phy@1 {
+ phy1: ethernet-phy@1 {
max-speed = <1000>;
reg = <1>;
compatible = "ethernet-phy-ieee802.3-c22";
- };
+ };
};
};
@@ -110,10 +110,10 @@ examples:
interrupts = <0x0 0x16 0x0>, <0x0 0x17 0x0>;
mdio1: mdio@e14 {
- compatible = "brcm,genet-mdio-v4";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0xe14 0x8>;
+ compatible = "brcm,genet-mdio-v4";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xe14 0x8>;
};
};
@@ -129,15 +129,15 @@ examples:
interrupts = <0x0 0x18 0x0>, <0x0 0x19 0x0>;
mdio2: mdio@e14 {
- compatible = "brcm,genet-mdio-v4";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0xe14 0x8>;
+ compatible = "brcm,genet-mdio-v4";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0xe14 0x8>;
- phy0: ethernet-phy@0 {
+ phy0: ethernet-phy@0 {
max-speed = <1000>;
reg = <0>;
compatible = "ethernet-phy-ieee802.3-c22";
- };
+ };
};
};
diff --git a/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.yaml b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.yaml
index af96b4fd89d5..3f27746d9a56 100644
--- a/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.yaml
+++ b/Documentation/devicetree/bindings/net/brcm,mdio-mux-iproc.yaml
@@ -38,43 +38,43 @@ unevaluatedProperties: false
examples:
- |
- mdio_mux_iproc: mdio-mux@66020000 {
+ mdio-mux@66020000 {
compatible = "brcm,mdio-mux-iproc";
reg = <0x66020000 0x250>;
#address-cells = <1>;
#size-cells = <0>;
mdio@0 {
- reg = <0x0>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- pci_phy0: pci-phy@0 {
- compatible = "brcm,ns2-pcie-phy";
- reg = <0x0>;
- #phy-cells = <0>;
- };
+ reg = <0x0>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pci-phy@0 {
+ compatible = "brcm,ns2-pcie-phy";
+ reg = <0x0>;
+ #phy-cells = <0>;
+ };
};
mdio@7 {
- reg = <0x7>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- pci_phy1: pci-phy@0 {
- compatible = "brcm,ns2-pcie-phy";
- reg = <0x0>;
- #phy-cells = <0>;
- };
+ reg = <0x7>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ pci-phy@0 {
+ compatible = "brcm,ns2-pcie-phy";
+ reg = <0x0>;
+ #phy-cells = <0>;
+ };
};
mdio@10 {
- reg = <0x10>;
- #address-cells = <1>;
- #size-cells = <0>;
+ reg = <0x10>;
+ #address-cells = <1>;
+ #size-cells = <0>;
- gphy0: eth-phy@10 {
- reg = <0x10>;
- };
+ eth-phy@10 {
+ reg = <0x10>;
+ };
};
};
diff --git a/Documentation/devicetree/bindings/net/can/bosch,c_can.yaml b/Documentation/devicetree/bindings/net/can/bosch,c_can.yaml
index 4d7d67ee175a..ff1b59a0294e 100644
--- a/Documentation/devicetree/bindings/net/can/bosch,c_can.yaml
+++ b/Documentation/devicetree/bindings/net/can/bosch,c_can.yaml
@@ -99,11 +99,11 @@ examples:
#include <dt-bindings/reset/altr,rst-mgr.h>
can@ffc00000 {
- compatible = "bosch,d_can";
- reg = <0xffc00000 0x1000>;
- interrupts = <0 131 4>, <0 132 4>, <0 133 4>, <0 134 4>;
- clocks = <&can0_clk>;
- resets = <&rst CAN0_RESET>;
+ compatible = "bosch,d_can";
+ reg = <0xffc00000 0x1000>;
+ interrupts = <0 131 4>, <0 132 4>, <0 133 4>, <0 134 4>;
+ clocks = <&can0_clk>;
+ resets = <&rst CAN0_RESET>;
};
- |
can@0 {
diff --git a/Documentation/devicetree/bindings/net/can/microchip,mcp2510.yaml b/Documentation/devicetree/bindings/net/can/microchip,mcp2510.yaml
index db446dde6842..e0ec53bc10c6 100644
--- a/Documentation/devicetree/bindings/net/can/microchip,mcp2510.yaml
+++ b/Documentation/devicetree/bindings/net/can/microchip,mcp2510.yaml
@@ -56,15 +56,15 @@ examples:
#size-cells = <0>;
can@1 {
- compatible = "microchip,mcp2515";
- reg = <1>;
- clocks = <&clk24m>;
- interrupt-parent = <&gpio4>;
- interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
- vdd-supply = <&reg5v0>;
- xceiver-supply = <&reg5v0>;
- gpio-controller;
- #gpio-cells = <2>;
+ compatible = "microchip,mcp2515";
+ reg = <1>;
+ clocks = <&clk24m>;
+ interrupt-parent = <&gpio4>;
+ interrupts = <13 IRQ_TYPE_LEVEL_LOW>;
+ vdd-supply = <&reg5v0>;
+ xceiver-supply = <&reg5v0>;
+ gpio-controller;
+ #gpio-cells = <2>;
};
};
diff --git a/Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml b/Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml
index dedfad526666..a73fc5036905 100644
--- a/Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml
+++ b/Documentation/devicetree/bindings/net/microchip,sparx5-switch.yaml
@@ -129,6 +129,24 @@ properties:
minimum: 0
maximum: 383
+ rx-internal-delay-ps:
+ description:
+ RGMII Receive Clock Delay defined in pico seconds, used to select
+ the DLL phase shift between 1000 ps (45 degree shift at 1Gbps) and
+ 3300 ps (147 degree shift at 1Gbps). A value of 0 ps will disable
+ any delay. The Default is no delay.
+ enum: [0, 1000, 1700, 2000, 2500, 3000, 3300]
+ default: 0
+
+ tx-internal-delay-ps:
+ description:
+ RGMII Transmit Clock Delay defined in pico seconds, used to select
+ the DLL phase shift between 1000 ps (45 degree shift at 1Gbps) and
+ 3300 ps (147 degree shift at 1Gbps). A value of 0 ps will disable
+ any delay. The Default is no delay.
+ enum: [0, 1000, 1700, 2000, 2500, 3000, 3300]
+ default: 0
+
required:
- reg
- phys
diff --git a/Documentation/devicetree/bindings/net/nxp,s32-dwmac.yaml b/Documentation/devicetree/bindings/net/nxp,s32-dwmac.yaml
new file mode 100644
index 000000000000..2b8b74c5feec
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/nxp,s32-dwmac.yaml
@@ -0,0 +1,105 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright 2021-2024 NXP
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/nxp,s32-dwmac.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP S32G2xx/S32G3xx/S32R45 GMAC ethernet controller
+
+maintainers:
+ - Jan Petrous (OSS) <jan.petrous@oss.nxp.com>
+
+description:
+ This device is a Synopsys DWC IP, integrated on NXP S32G/R SoCs.
+ The SoC series S32G2xx and S32G3xx feature one DWMAC instance,
+ the SoC S32R45 has two instances. The devices can use RGMII/RMII/MII
+ interface over Pinctrl device or the output can be routed
+ to the embedded SerDes for SGMII connectivity.
+
+properties:
+ compatible:
+ oneOf:
+ - const: nxp,s32g2-dwmac
+ - items:
+ - enum:
+ - nxp,s32g3-dwmac
+ - nxp,s32r45-dwmac
+ - const: nxp,s32g2-dwmac
+
+ reg:
+ items:
+ - description: Main GMAC registers
+ - description: GMAC PHY mode control register
+
+ interrupts:
+ maxItems: 1
+
+ interrupt-names:
+ const: macirq
+
+ clocks:
+ items:
+ - description: Main GMAC clock
+ - description: Transmit clock
+ - description: Receive clock
+ - description: PTP reference clock
+
+ clock-names:
+ items:
+ - const: stmmaceth
+ - const: tx
+ - const: rx
+ - const: ptp_ref
+
+required:
+ - clocks
+ - clock-names
+
+allOf:
+ - $ref: snps,dwmac.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+ #include <dt-bindings/phy/phy.h>
+ bus {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ ethernet@4033c000 {
+ compatible = "nxp,s32g2-dwmac";
+ reg = <0x0 0x4033c000 0x0 0x2000>, /* gmac IP */
+ <0x0 0x4007c004 0x0 0x4>; /* GMAC_0_CTRL_STS */
+ interrupt-parent = <&gic>;
+ interrupts = <GIC_SPI 57 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ snps,mtl-rx-config = <&mtl_rx_setup>;
+ snps,mtl-tx-config = <&mtl_tx_setup>;
+ clocks = <&clks 24>, <&clks 17>, <&clks 16>, <&clks 15>;
+ clock-names = "stmmaceth", "tx", "rx", "ptp_ref";
+ phy-mode = "rgmii-id";
+ phy-handle = <&phy0>;
+
+ mtl_rx_setup: rx-queues-config {
+ snps,rx-queues-to-use = <5>;
+ };
+
+ mtl_tx_setup: tx-queues-config {
+ snps,tx-queues-to-use = <5>;
+ };
+
+ mdio {
+ #address-cells = <1>;
+ #size-cells = <0>;
+ compatible = "snps,dwmac-mdio";
+
+ phy0: ethernet-phy@0 {
+ reg = <0>;
+ };
+ };
+ };
+ };
diff --git a/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml b/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml
index a12cda8aa764..cd09560e0aea 100644
--- a/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml
+++ b/Documentation/devicetree/bindings/net/pse-pd/pse-controller.yaml
@@ -81,7 +81,7 @@ properties:
List of phandles, each pointing to the power supply for the
corresponding pairset named in 'pairset-names'. This property
aligns with IEEE 802.3-2022, Section 33.2.3 and 145.2.4.
- PSE Pinout Alternatives (as per IEEE 802.3-2022 Table 145\u20133)
+ PSE Pinout Alternatives (as per IEEE 802.3-2022 Table 145-3)
|-----------|---------------|---------------|---------------|---------------|
| Conductor | Alternative A | Alternative A | Alternative B | Alternative B |
| | (MDI-X) | (MDI) | (X) | (S) |
diff --git a/Documentation/devicetree/bindings/net/qcom,ipa.yaml b/Documentation/devicetree/bindings/net/qcom,ipa.yaml
index 53cae71d9957..1a46d80a66e8 100644
--- a/Documentation/devicetree/bindings/net/qcom,ipa.yaml
+++ b/Documentation/devicetree/bindings/net/qcom,ipa.yaml
@@ -239,7 +239,7 @@ examples:
qcom,gsi-loader = "self";
memory-region = <&ipa_fw_mem>;
- firmware-name = "qcom/sc7180-trogdor/modem/modem.mdt";
+ firmware-name = "qcom/sc7180-trogdor/modem/modem.mbn";
iommus = <&apps_smmu 0x440 0x0>,
<&apps_smmu 0x442 0x0>;
diff --git a/Documentation/devicetree/bindings/net/snps,dwmac.yaml b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
index eb1f3ae41ab9..91e75eb3f329 100644
--- a/Documentation/devicetree/bindings/net/snps,dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/snps,dwmac.yaml
@@ -67,6 +67,7 @@ properties:
- ingenic,x2000-mac
- loongson,ls2k-dwmac
- loongson,ls7a-dwmac
+ - nxp,s32g2-dwmac
- qcom,qcs404-ethqos
- qcom,sa8775p-ethqos
- qcom,sc8280xp-ethqos
diff --git a/Documentation/devicetree/bindings/net/stm32-dwmac.yaml b/Documentation/devicetree/bindings/net/stm32-dwmac.yaml
index bf23838fe6e8..85cea9966a27 100644
--- a/Documentation/devicetree/bindings/net/stm32-dwmac.yaml
+++ b/Documentation/devicetree/bindings/net/stm32-dwmac.yaml
@@ -154,56 +154,56 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/stm32mp1-clks.h>
//Example 1
- ethernet0: ethernet@5800a000 {
- compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
- reg = <0x5800a000 0x2000>;
- reg-names = "stmmaceth";
- interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "macirq";
- clock-names = "stmmaceth",
- "mac-clk-tx",
- "mac-clk-rx",
- "ethstp",
- "eth-ck";
- clocks = <&rcc ETHMAC>,
- <&rcc ETHTX>,
- <&rcc ETHRX>,
- <&rcc ETHSTP>,
- <&rcc ETHCK_K>;
- st,syscon = <&syscfg 0x4>;
- snps,pbl = <2>;
- snps,axi-config = <&stmmac_axi_config_0>;
- snps,tso;
- phy-mode = "rgmii";
- };
+ ethernet0: ethernet@5800a000 {
+ compatible = "st,stm32mp1-dwmac", "snps,dwmac-4.20a";
+ reg = <0x5800a000 0x2000>;
+ reg-names = "stmmaceth";
+ interrupts = <GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "macirq";
+ clock-names = "stmmaceth",
+ "mac-clk-tx",
+ "mac-clk-rx",
+ "ethstp",
+ "eth-ck";
+ clocks = <&rcc ETHMAC>,
+ <&rcc ETHTX>,
+ <&rcc ETHRX>,
+ <&rcc ETHSTP>,
+ <&rcc ETHCK_K>;
+ st,syscon = <&syscfg 0x4>;
+ snps,pbl = <2>;
+ snps,axi-config = <&stmmac_axi_config_0>;
+ snps,tso;
+ phy-mode = "rgmii";
+ };
- |
//Example 2 (MCU example)
- ethernet1: ethernet@40028000 {
- compatible = "st,stm32-dwmac", "snps,dwmac-3.50a";
- reg = <0x40028000 0x8000>;
- reg-names = "stmmaceth";
- interrupts = <0 61 0>, <0 62 0>;
- interrupt-names = "macirq", "eth_wake_irq";
- clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
- clocks = <&rcc 0 25>, <&rcc 0 26>, <&rcc 0 27>;
- st,syscon = <&syscfg 0x4>;
- snps,pbl = <8>;
- snps,mixed-burst;
- phy-mode = "mii";
- };
+ ethernet1: ethernet@40028000 {
+ compatible = "st,stm32-dwmac", "snps,dwmac-3.50a";
+ reg = <0x40028000 0x8000>;
+ reg-names = "stmmaceth";
+ interrupts = <0 61 0>, <0 62 0>;
+ interrupt-names = "macirq", "eth_wake_irq";
+ clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
+ clocks = <&rcc 0 25>, <&rcc 0 26>, <&rcc 0 27>;
+ st,syscon = <&syscfg 0x4>;
+ snps,pbl = <8>;
+ snps,mixed-burst;
+ phy-mode = "mii";
+ };
- |
//Example 3
- ethernet2: ethernet@40027000 {
- compatible = "st,stm32-dwmac", "snps,dwmac-4.10a";
- reg = <0x40028000 0x8000>;
- reg-names = "stmmaceth";
- interrupts = <61>;
- interrupt-names = "macirq";
- clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
- clocks = <&rcc 62>, <&rcc 61>, <&rcc 60>;
- st,syscon = <&syscfg 0x4>;
- snps,pbl = <8>;
- phy-mode = "mii";
- };
+ ethernet2: ethernet@40027000 {
+ compatible = "st,stm32-dwmac", "snps,dwmac-4.10a";
+ reg = <0x40028000 0x8000>;
+ reg-names = "stmmaceth";
+ interrupts = <61>;
+ interrupt-names = "macirq";
+ clock-names = "stmmaceth", "mac-clk-tx", "mac-clk-rx";
+ clocks = <&rcc 62>, <&rcc 61>, <&rcc 60>;
+ st,syscon = <&syscfg 0x4>;
+ snps,pbl = <8>;
+ phy-mode = "mii";
+ };
diff --git a/Documentation/devicetree/bindings/net/ti,davinci-mdio.yaml b/Documentation/devicetree/bindings/net/ti,davinci-mdio.yaml
index 53604fab0b73..08119b6880ee 100644
--- a/Documentation/devicetree/bindings/net/ti,davinci-mdio.yaml
+++ b/Documentation/devicetree/bindings/net/ti,davinci-mdio.yaml
@@ -72,9 +72,9 @@ unevaluatedProperties: false
examples:
- |
davinci_mdio: mdio@4a101000 {
- compatible = "ti,davinci_mdio";
- #address-cells = <1>;
- #size-cells = <0>;
- reg = <0x4a101000 0x1000>;
- bus_freq = <1000000>;
+ compatible = "ti,davinci_mdio";
+ #address-cells = <1>;
+ #size-cells = <0>;
+ reg = <0x4a101000 0x1000>;
+ bus_freq = <1000000>;
};
diff --git a/Documentation/devicetree/bindings/net/ti,dp83822.yaml b/Documentation/devicetree/bindings/net/ti,dp83822.yaml
index 784866ea392b..50c24248df26 100644
--- a/Documentation/devicetree/bindings/net/ti,dp83822.yaml
+++ b/Documentation/devicetree/bindings/net/ti,dp83822.yaml
@@ -96,6 +96,32 @@ properties:
- master
- slave
+ ti,gpio2-clk-out:
+ description: |
+ DP83822 PHY only.
+ The GPIO2 pin on the DP83822 can be configured as clock output. When
+ omitted, the PHY's default will be left as is.
+
+ - 'mac-if': In MII mode the clock frequency is 25-MHz, in RMII Mode the
+ clock frequency is 50-MHz and in RGMII Mode the clock frequency is
+ 25-MHz.
+ - 'xi': XI clock(pass-through clock from XI pin).
+ - 'int-ref': Internal reference clock 25-MHz.
+ - 'rmii-master-mode-ref': RMII master mode reference clock 50-MHz. RMII
+ master mode reference clock is identical to MAC IF clock in RMII master
+ mode.
+ - 'free-running': Free running clock 125-MHz.
+ - 'recovered': Recovered clock is a 125-MHz recovered clock from a
+ connected link partner.
+ $ref: /schemas/types.yaml#/definitions/string
+ enum:
+ - mac-if
+ - xi
+ - int-ref
+ - rmii-master-mode-ref
+ - free-running
+ - recovered
+
required:
- reg
@@ -110,6 +136,7 @@ examples:
reg = <0>;
rx-internal-delay-ps = <1>;
tx-internal-delay-ps = <1>;
+ ti,gpio2-clk-out = "xi";
};
};
diff --git a/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml b/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml
index 02b6d32003cc..b11894fbaec4 100644
--- a/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml
+++ b/Documentation/devicetree/bindings/net/ti,k3-am654-cpsw-nuss.yaml
@@ -302,16 +302,16 @@ examples:
ti,fifo-depth = <DP83867_PHYCR_FIFO_DEPTH_4_B_NIB>;
};
};
- };
- cpts@3d000 {
- compatible = "ti,am65-cpts";
- reg = <0x0 0x3d000 0x0 0x400>;
- clocks = <&k3_clks 18 2>;
- clock-names = "cpts";
- interrupts-extended = <&gic500 GIC_SPI 858 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cpts";
- ti,cpts-ext-ts-inputs = <4>;
- ti,cpts-periodic-outputs = <2>;
+ cpts@3d000 {
+ compatible = "ti,am65-cpts";
+ reg = <0x0 0x3d000 0x0 0x400>;
+ clocks = <&k3_clks 18 2>;
+ clock-names = "cpts";
+ interrupts-extended = <&gic500 GIC_SPI 858 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cpts";
+ ti,cpts-ext-ts-inputs = <4>;
+ ti,cpts-periodic-outputs = <2>;
+ };
};
};
diff --git a/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml b/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml
index 3888692275ad..3572749147fb 100644
--- a/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml
+++ b/Documentation/devicetree/bindings/net/ti,k3-am654-cpts.yaml
@@ -131,23 +131,23 @@ examples:
#include <dt-bindings/interrupt-controller/arm-gic.h>
cpts@310d0000 {
- compatible = "ti,am65-cpts";
- reg = <0x310d0000 0x400>;
- reg-names = "cpts";
- clocks = <&main_cpts_mux>;
- clock-names = "cpts";
- interrupts-extended = <&k3_irq 163 0 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-names = "cpts";
- ti,cpts-periodic-outputs = <6>;
- ti,cpts-ext-ts-inputs = <8>;
-
- main_cpts_mux: refclk-mux {
- #clock-cells = <0>;
- clocks = <&k3_clks 118 5>, <&k3_clks 118 11>,
- <&k3_clks 157 91>, <&k3_clks 157 77>,
- <&k3_clks 157 102>, <&k3_clks 157 80>,
- <&k3_clks 120 3>, <&k3_clks 121 3>;
- assigned-clocks = <&main_cpts_mux>;
- assigned-clock-parents = <&k3_clks 118 11>;
- };
+ compatible = "ti,am65-cpts";
+ reg = <0x310d0000 0x400>;
+ reg-names = "cpts";
+ clocks = <&main_cpts_mux>;
+ clock-names = "cpts";
+ interrupts-extended = <&k3_irq 163 0 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "cpts";
+ ti,cpts-periodic-outputs = <6>;
+ ti,cpts-ext-ts-inputs = <8>;
+
+ main_cpts_mux: refclk-mux {
+ #clock-cells = <0>;
+ clocks = <&k3_clks 118 5>, <&k3_clks 118 11>,
+ <&k3_clks 157 91>, <&k3_clks 157 77>,
+ <&k3_clks 157 102>, <&k3_clks 157 80>,
+ <&k3_clks 120 3>, <&k3_clks 121 3>;
+ assigned-clocks = <&main_cpts_mux>;
+ assigned-clock-parents = <&k3_clks 118 11>;
+ };
};
diff --git a/Documentation/devicetree/bindings/net/wireless/marvell,sd8787.yaml b/Documentation/devicetree/bindings/net/wireless/marvell,sd8787.yaml
index 1715b22e0dcf..930b700b73d0 100644
--- a/Documentation/devicetree/bindings/net/wireless/marvell,sd8787.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/marvell,sd8787.yaml
@@ -79,15 +79,14 @@ examples:
#include <dt-bindings/interrupt-controller/irq.h>
mmc {
- #address-cells = <1>;
- #size-cells = <0>;
-
- wifi@1 {
- compatible = "marvell,sd8897";
- reg = <1>;
- interrupt-parent = <&pio>;
- interrupts = <38 IRQ_TYPE_LEVEL_LOW>;
- marvell,wakeup-pin = <3>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ wifi@1 {
+ compatible = "marvell,sd8897";
+ reg = <1>;
+ interrupt-parent = <&pio>;
+ interrupts = <38 IRQ_TYPE_LEVEL_LOW>;
+ marvell,wakeup-pin = <3>;
};
};
-
diff --git a/Documentation/devicetree/bindings/fuse/renesas,rcar-efuse.yaml b/Documentation/devicetree/bindings/nvmem/renesas,rcar-efuse.yaml
index d7e289244e72..ce7d65afa460 100644
--- a/Documentation/devicetree/bindings/fuse/renesas,rcar-efuse.yaml
+++ b/Documentation/devicetree/bindings/nvmem/renesas,rcar-efuse.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/fuse/renesas,rcar-efuse.yaml#
+$id: http://devicetree.org/schemas/nvmem/renesas,rcar-efuse.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: R-Car E-FUSE connected to PFC
@@ -13,6 +13,9 @@ description:
The E-FUSE is a type of non-volatile memory, which is accessible through the
Pin Function Controller (PFC) on some R-Car Gen4 SoCs.
+allOf:
+ - $ref: nvmem.yaml#
+
properties:
compatible:
enum:
@@ -39,17 +42,27 @@ required:
- power-domains
- resets
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
- #include <dt-bindings/clock/r8a779a0-cpg-mssr.h>
- #include <dt-bindings/power/r8a779a0-sysc.h>
-
- fuse: fuse@e6078800 {
- compatible = "renesas,r8a779a0-efuse";
- reg = <0xe6078800 0x100>;
- clocks = <&cpg CPG_MOD 916>;
- power-domains = <&sysc R8A779A0_PD_ALWAYS_ON>;
- resets = <&cpg 916>;
+ #include <dt-bindings/clock/r8a779f0-cpg-mssr.h>
+ #include <dt-bindings/power/r8a779f0-sysc.h>
+
+ fuse@e6078800 {
+ compatible = "renesas,r8a779f0-efuse";
+ reg = <0xe6078800 0x200>;
+ clocks = <&cpg CPG_MOD 915>;
+ power-domains = <&sysc R8A779F0_PD_ALWAYS_ON>;
+ resets = <&cpg 915>;
+
+ nvmem-layout {
+ compatible = "fixed-layout";
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ calib@144 {
+ reg = <0x144 0x08>;
+ };
+ };
};
diff --git a/Documentation/devicetree/bindings/fuse/renesas,rcar-otp.yaml b/Documentation/devicetree/bindings/nvmem/renesas,rcar-otp.yaml
index d74872ae9ff3..3313c03ea68d 100644
--- a/Documentation/devicetree/bindings/fuse/renesas,rcar-otp.yaml
+++ b/Documentation/devicetree/bindings/nvmem/renesas,rcar-otp.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/fuse/renesas,rcar-otp.yaml#
+$id: http://devicetree.org/schemas/nvmem/renesas,rcar-otp.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: R-Car E-FUSE connected to OTP_MEM
@@ -13,6 +13,9 @@ description:
The E-FUSE is a type of non-volatile memory, which is accessible through the
One-Time Programmable Memory (OTP_MEM) module on some R-Car Gen4 SoCs.
+allOf:
+ - $ref: nvmem.yaml#
+
properties:
compatible:
enum:
@@ -22,17 +25,19 @@ properties:
reg:
items:
- description: OTP_MEM_0
- - description: OTP_MEM_1
+ - description: OTP_MEM_1.
+ The addresses of cells defined under the optional nvmem-layout
+ subnode are relative to this register bank.
required:
- compatible
- reg
-additionalProperties: false
+unevaluatedProperties: false
examples:
- |
- otp: otp@e61be000 {
- compatible = "renesas,r8a779g0-otp";
- reg = <0xe61be000 0x1000>, <0xe61bf000 0x1000>;
+ otp@e61be000 {
+ compatible = "renesas,r8a779g0-otp";
+ reg = <0xe61be000 0x1000>, <0xe61bf000 0x1000>;
};
diff --git a/Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt b/Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt
deleted file mode 100644
index 586c08286aa9..000000000000
--- a/Documentation/devicetree/bindings/nvmem/sc27xx-efuse.txt
+++ /dev/null
@@ -1,52 +0,0 @@
-= Spreadtrum SC27XX PMIC eFuse device tree bindings =
-
-Required properties:
-- compatible: Should be one of the following.
- "sprd,sc2720-efuse"
- "sprd,sc2721-efuse"
- "sprd,sc2723-efuse"
- "sprd,sc2730-efuse"
- "sprd,sc2731-efuse"
-- reg: Specify the address offset of efuse controller.
-- hwlocks: Reference to a phandle of a hwlock provider node.
-
-= Data cells =
-Are child nodes of eFuse, bindings of which as described in
-bindings/nvmem/nvmem.txt
-
-Example:
-
- sc2731_pmic: pmic@0 {
- compatible = "sprd,sc2731";
- reg = <0>;
- spi-max-frequency = <26000000>;
- interrupts = <GIC_SPI 31 IRQ_TYPE_LEVEL_HIGH>;
- interrupt-controller;
- #interrupt-cells = <2>;
- #address-cells = <1>;
- #size-cells = <0>;
-
- efuse@380 {
- compatible = "sprd,sc2731-efuse";
- reg = <0x380>;
- #address-cells = <1>;
- #size-cells = <1>;
- hwlocks = <&hwlock 12>;
-
- /* Data cells */
- thermal_calib: calib@10 {
- reg = <0x10 0x2>;
- };
- };
- };
-
-= Data consumers =
-Are device nodes which consume nvmem data cells.
-
-Example:
-
- thermal {
- ...
- nvmem-cells = <&thermal_calib>;
- nvmem-cell-names = "calibration";
- };
diff --git a/Documentation/devicetree/bindings/nvmem/sprd,sc2731-efuse.yaml b/Documentation/devicetree/bindings/nvmem/sprd,sc2731-efuse.yaml
new file mode 100644
index 000000000000..dc25fe3d1841
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/sprd,sc2731-efuse.yaml
@@ -0,0 +1,68 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/sprd,sc2731-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spreadtrum SC27XX PMIC eFuse
+
+maintainers:
+ - Orson Zhai <orsonzhai@gmail.com>
+ - Baolin Wang <baolin.wang7@gmail.com>
+ - Chunyan Zhang <zhang.lyra@gmail.com>
+
+properties:
+ compatible:
+ enum:
+ - sprd,sc2720-efuse
+ - sprd,sc2721-efuse
+ - sprd,sc2723-efuse
+ - sprd,sc2730-efuse
+ - sprd,sc2731-efuse
+
+ reg:
+ maxItems: 1
+
+ hwlocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - hwlocks
+
+allOf:
+ - $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ pmic {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ efuse@380 {
+ compatible = "sprd,sc2731-efuse";
+ reg = <0x380>;
+ hwlocks = <&hwlock 12>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Data cells */
+ fgu_calib: calib@6 {
+ reg = <0x6 0x2>;
+ bits = <0 9>;
+ };
+
+ adc_big_scale: calib@24 {
+ reg = <0x24 0x2>;
+ };
+
+ adc_small_scale: calib@26 {
+ reg = <0x26 0x2>;
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/nvmem/sprd,ums312-efuse.yaml b/Documentation/devicetree/bindings/nvmem/sprd,ums312-efuse.yaml
new file mode 100644
index 000000000000..00e0fd1353a3
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/sprd,ums312-efuse.yaml
@@ -0,0 +1,61 @@
+# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/sprd,ums312-efuse.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Spreadtrum UMS312 eFuse
+
+maintainers:
+ - Orson Zhai <orsonzhai@gmail.com>
+ - Baolin Wang <baolin.wang7@gmail.com>
+ - Chunyan Zhang <zhang.lyra@gmail.com>
+
+properties:
+ compatible:
+ const: sprd,ums312-efuse
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ maxItems: 1
+
+ clock-names:
+ const: enable
+
+ hwlocks:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - hwlocks
+
+allOf:
+ - $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/sprd,ums512-clk.h>
+
+ efuse@32240000 {
+ compatible = "sprd,ums312-efuse";
+ reg = <0x32240000 0x10000>;
+ clocks = <&aonapb_gate CLK_EFUSE_EB>;
+ clock-names = "enable";
+ hwlocks = <&hwlock 8>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+
+ /* Data cells */
+ thermal_calib: calib@10 {
+ reg = <0x10 0x2>;
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/nvmem/sprd-efuse.txt b/Documentation/devicetree/bindings/nvmem/sprd-efuse.txt
deleted file mode 100644
index 96b6feec27f0..000000000000
--- a/Documentation/devicetree/bindings/nvmem/sprd-efuse.txt
+++ /dev/null
@@ -1,39 +0,0 @@
-= Spreadtrum eFuse device tree bindings =
-
-Required properties:
-- compatible: Should be "sprd,ums312-efuse".
-- reg: Specify the address offset of efuse controller.
-- clock-names: Should be "enable".
-- clocks: The phandle and specifier referencing the controller's clock.
-- hwlocks: Reference to a phandle of a hwlock provider node.
-
-= Data cells =
-Are child nodes of eFuse, bindings of which as described in
-bindings/nvmem/nvmem.txt
-
-Example:
-
- ap_efuse: efuse@32240000 {
- compatible = "sprd,ums312-efuse";
- reg = <0 0x32240000 0 0x10000>;
- clock-names = "enable";
- hwlocks = <&hwlock 8>;
- clocks = <&aonapb_gate CLK_EFUSE_EB>;
-
- /* Data cells */
- thermal_calib: calib@10 {
- reg = <0x10 0x2>;
- };
- };
-
-= Data consumers =
-Are device nodes which consume nvmem data cells.
-
-Example:
-
- thermal {
- ...
-
- nvmem-cells = <&thermal_calib>;
- nvmem-cell-names = "calibration";
- };
diff --git a/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt b/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt
deleted file mode 100644
index 0df79d9e07ec..000000000000
--- a/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.txt
+++ /dev/null
@@ -1,40 +0,0 @@
-Zodiac Inflight Innovations RAVE EEPROM Bindings
-
-RAVE SP EEPROM device is a "MFD cell" device exposing physical EEPROM
-attached to RAVE Supervisory Processor. It is expected that its Device
-Tree node is specified as a child of the node corresponding to the
-parent RAVE SP device (as documented in
-Documentation/devicetree/bindings/mfd/zii,rave-sp.txt)
-
-Required properties:
-
-- compatible: Should be "zii,rave-sp-eeprom"
-
-Optional properties:
-
-- zii,eeprom-name: Unique EEPROM identifier describing its function in the
- system. Will be used as created NVMEM deivce's name.
-
-Data cells:
-
-Data cells are child nodes of eerpom node, bindings for which are
-documented in Documentation/devicetree/bindings/nvmem/nvmem.txt
-
-Example:
-
- rave-sp {
- compatible = "zii,rave-sp-rdu1";
- current-speed = <38400>;
-
- eeprom@a4 {
- compatible = "zii,rave-sp-eeprom";
- reg = <0xa4 0x4000>;
- #address-cells = <1>;
- #size-cells = <1>;
- zii,eeprom-name = "main-eeprom";
-
- wdt_timeout: wdt-timeout@81 {
- reg = <0x81 2>;
- };
- };
- }
diff --git a/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.yaml b/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.yaml
new file mode 100644
index 000000000000..d073c51c2b9a
--- /dev/null
+++ b/Documentation/devicetree/bindings/nvmem/zii,rave-sp-eeprom.yaml
@@ -0,0 +1,54 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/nvmem/zii,rave-sp-eeprom.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Zodiac Inflight Innovations RAVE EEPROM
+
+maintainers:
+ - Frank Li <Frank.Li@nxp.com>
+
+description:
+ RAVE SP EEPROM device is a "MFD cell" device exposing physical EEPROM
+ attached to RAVE Supervisory Processor. It is expected that its Device
+ Tree node is specified as a child of the node corresponding to the
+ parent RAVE SP device (as documented in
+ Documentation/devicetree/bindings/mfd/zii,rave-sp.yaml)
+
+properties:
+ compatible:
+ const: zii,rave-sp-eeprom
+
+ reg:
+ maxItems: 1
+
+ zii,eeprom-name:
+ $ref: /schemas/types.yaml#/definitions/string
+ description:
+ Unique EEPROM identifier describing its function in the
+ system. Will be used as created NVMEM deivce's name.
+
+required:
+ - compatible
+
+allOf:
+ - $ref: nvmem.yaml#
+ - $ref: nvmem-deprecated-cells.yaml#
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ eeprom@a4 {
+ compatible = "zii,rave-sp-eeprom";
+ reg = <0xa4 0x4000>;
+ #address-cells = <1>;
+ #size-cells = <1>;
+ zii,eeprom-name = "main-eeprom";
+
+ wdt-timeout@81 {
+ reg = <0x81 2>;
+ };
+ };
+
diff --git a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml
index dc3a3f709fea..daee0c0fc915 100644
--- a/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/fsl,imx8mq-usb-phy.yaml
@@ -11,12 +11,17 @@ maintainers:
properties:
compatible:
- enum:
- - fsl,imx8mq-usb-phy
- - fsl,imx8mp-usb-phy
+ oneOf:
+ - enum:
+ - fsl,imx8mq-usb-phy
+ - fsl,imx8mp-usb-phy
+ - items:
+ - const: fsl,imx95-usb-phy
+ - const: fsl,imx8mp-usb-phy
reg:
- maxItems: 1
+ minItems: 1
+ maxItems: 2
"#phy-cells":
const: 0
@@ -89,7 +94,31 @@ required:
- clocks
- clock-names
-additionalProperties: false
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,imx95-usb-phy
+ then:
+ properties:
+ reg:
+ items:
+ - description: USB PHY Control range
+ - description: USB PHY TCA Block range
+ else:
+ properties:
+ reg:
+ maxItems: 1
+
+ - if:
+ required:
+ - orientation-switch
+ then:
+ $ref: /schemas/usb/usb-switch.yaml#
+
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml
index f1f4e4f83352..1636285fbe53 100644
--- a/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,msm8998-qmp-usb3-phy.yaml
@@ -18,6 +18,7 @@ properties:
enum:
- qcom,msm8998-qmp-usb3-phy
- qcom,qcm2290-qmp-usb3-phy
+ - qcom,qcs615-qmp-usb3-phy
- qcom,sdm660-qmp-usb3-phy
- qcom,sm6115-qmp-usb3-phy
@@ -96,6 +97,7 @@ allOf:
contains:
enum:
- qcom,msm8998-qmp-usb3-phy
+ - qcom,qcs615-qmp-usb3-phy
- qcom,sdm660-qmp-usb3-phy
then:
properties:
diff --git a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
index 95eecbaef05c..4aed4b5d65ec 100644
--- a/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
+++ b/Documentation/devicetree/bindings/phy/qcom,qusb2-phy.yaml
@@ -25,6 +25,7 @@ properties:
- qcom,msm8996-qusb2-phy
- qcom,msm8998-qusb2-phy
- qcom,qcm2290-qusb2-phy
+ - qcom,qcs615-qusb2-phy
- qcom,sdm660-qusb2-phy
- qcom,sm4250-qusb2-phy
- qcom,sm6115-qusb2-phy
diff --git a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
index 6d37c06b2f65..591a080ca3ff 100644
--- a/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
+++ b/Documentation/devicetree/bindings/power/mediatek,power-controller.yaml
@@ -55,6 +55,10 @@ patternProperties:
patternProperties:
"^power-domain@[0-9a-f]+$":
$ref: "#/$defs/power-domain-node"
+ patternProperties:
+ "^power-domain@[0-9a-f]+$":
+ $ref: "#/$defs/power-domain-node"
+ unevaluatedProperties: false
unevaluatedProperties: false
unevaluatedProperties: false
unevaluatedProperties: false
diff --git a/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml b/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
index ca401a209cca..47c425c9fff1 100644
--- a/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
+++ b/Documentation/devicetree/bindings/regulator/qcom,qca6390-pmu.yaml
@@ -18,6 +18,7 @@ properties:
compatible:
enum:
- qcom,qca6390-pmu
+ - qcom,wcn6750-pmu
- qcom,wcn6855-pmu
- qcom,wcn7850-pmu
@@ -27,6 +28,9 @@ properties:
vddaon-supply:
description: VDD_AON supply regulator handle
+ vddasd-supply:
+ description: VDD_ASD supply regulator handle
+
vdddig-supply:
description: VDD_DIG supply regulator handle
@@ -42,6 +46,9 @@ properties:
vddio1p2-supply:
description: VDD_IO_1P2 supply regulator handle
+ vddrfa0p8-supply:
+ description: VDD_RFA_0P8 supply regulator handle
+
vddrfa0p95-supply:
description: VDD_RFA_0P95 supply regulator handle
@@ -51,12 +58,18 @@ properties:
vddrfa1p3-supply:
description: VDD_RFA_1P3 supply regulator handle
+ vddrfa1p7-supply:
+ description: VDD_RFA_1P7 supply regulator handle
+
vddrfa1p8-supply:
description: VDD_RFA_1P8 supply regulator handle
vddrfa1p9-supply:
description: VDD_RFA_1P9 supply regulator handle
+ vddrfa2p2-supply:
+ description: VDD_RFA_2P2 supply regulator handle
+
vddpcie1p3-supply:
description: VDD_PCIE_1P3 supply regulator handle
@@ -123,6 +136,20 @@ allOf:
properties:
compatible:
contains:
+ const: qcom,wcn6750-pmu
+ then:
+ required:
+ - vddaon-supply
+ - vddasd-supply
+ - vddpmu-supply
+ - vddrfa0p8-supply
+ - vddrfa1p2-supply
+ - vddrfa1p7-supply
+ - vddrfa2p2-supply
+ - if:
+ properties:
+ compatible:
+ contains:
const: qcom,wcn6855-pmu
then:
required:
diff --git a/Documentation/devicetree/bindings/riscv/extensions.yaml b/Documentation/devicetree/bindings/riscv/extensions.yaml
index af7e5237b2c0..9c7dd7e75e0c 100644
--- a/Documentation/devicetree/bindings/riscv/extensions.yaml
+++ b/Documentation/devicetree/bindings/riscv/extensions.yaml
@@ -171,6 +171,34 @@ properties:
ratified at commit 3f9ed34 ("Add ability to manually trigger
workflow. (#2)") of riscv-time-compare.
+ - const: svade
+ description: |
+ The standard Svade supervisor-level extension for SW-managed PTE A/D
+ bit updates as ratified in the 20240213 version of the privileged
+ ISA specification.
+
+ Both Svade and Svadu extensions control the hardware behavior when
+ the PTE A/D bits need to be set. The default behavior for the four
+ possible combinations of these extensions in the device tree are:
+ 1) Neither Svade nor Svadu present in DT => It is technically
+ unknown whether the platform uses Svade or Svadu. Supervisor
+ software should be prepared to handle either hardware updating
+ of the PTE A/D bits or page faults when they need updated.
+ 2) Only Svade present in DT => Supervisor must assume Svade to be
+ always enabled.
+ 3) Only Svadu present in DT => Supervisor must assume Svadu to be
+ always enabled.
+ 4) Both Svade and Svadu present in DT => Supervisor must assume
+ Svadu turned-off at boot time. To use Svadu, supervisor must
+ explicitly enable it using the SBI FWFT extension.
+
+ - const: svadu
+ description: |
+ The standard Svadu supervisor-level extension for hardware updating
+ of PTE A/D bits as ratified in the 20240528 version of the
+ privileged ISA specification. Please refer to Svade dt-binding
+ description for more details.
+
- const: svinval
description:
The standard Svinval supervisor-level extension for fine-grained
diff --git a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
index 4531eec568a6..9df5cdb6f63f 100644
--- a/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/allwinner,sun6i-a31-rtc.yaml
@@ -30,7 +30,9 @@ properties:
- const: allwinner,sun50i-a64-rtc
- const: allwinner,sun8i-h3-rtc
- items:
- - const: allwinner,sun20i-d1-rtc
+ - enum:
+ - allwinner,sun20i-d1-rtc
+ - allwinner,sun55i-a523-rtc
- const: allwinner,sun50i-r329-rtc
reg:
diff --git a/Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml b/Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml
new file mode 100644
index 000000000000..5d3ac737abcb
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml
@@ -0,0 +1,63 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+# Copyright (C) 2024 Amlogic, Inc. All rights reserved
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/amlogic,a4-rtc.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Amlogic A4 and A5 RTC
+
+maintainers:
+ - Yiting Deng <yiting.deng@amlogic.com>
+ - Xianwei Zhao <xianwei.zhao@amlogic.com>
+
+allOf:
+ - $ref: rtc.yaml#
+
+properties:
+ compatible:
+ enum:
+ - amlogic,a4-rtc
+ - amlogic,a5-rtc
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ items:
+ - description: RTC clock source, available 24M or 32K crystal
+ oscillator source. when using 24M, need to divide 24M into 32K.
+ - description: RTC module accesses the clock of the apb bus.
+
+ clock-names:
+ items:
+ - const: osc
+ - const: sys
+
+ interrupts:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+ - interrupts
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ apb {
+ #address-cells = <2>;
+ #size-cells = <2>;
+
+ rtc@8e600 {
+ compatible = "amlogic,a4-rtc";
+ reg = <0x0 0x8e600 0x0 0x38>;
+ clocks = <&xtal_32k>, <&clkc_periphs 1>;
+ clock-names = "osc", "sys";
+ interrupts = <GIC_SPI 131 IRQ_TYPE_EDGE_RISING>;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml b/Documentation/devicetree/bindings/rtc/microchip,mpfs-rtc.yaml
index 7742465b9383..a3e60d9f8399 100644
--- a/Documentation/devicetree/bindings/rtc/microchip,mfps-rtc.yaml
+++ b/Documentation/devicetree/bindings/rtc/microchip,mpfs-rtc.yaml
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
-$id: http://devicetree.org/schemas/rtc/microchip,mfps-rtc.yaml#
+$id: http://devicetree.org/schemas/rtc/microchip,mpfs-rtc.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
@@ -12,12 +12,14 @@ allOf:
maintainers:
- Daire McNamara <daire.mcnamara@microchip.com>
- - Lewis Hanly <lewis.hanly@microchip.com>
properties:
compatible:
- enum:
- - microchip,mpfs-rtc
+ oneOf:
+ - items:
+ - const: microchip,pic64gx-rtc
+ - const: microchip,mpfs-rtc
+ - const: microchip,mpfs-rtc
reg:
maxItems: 1
diff --git a/Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml b/Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml
new file mode 100644
index 000000000000..e70eeb66aa64
--- /dev/null
+++ b/Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml
@@ -0,0 +1,84 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/rtc/renesas,rz-rtca3.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Renesas RTCA-3 Real Time Clock
+
+maintainers:
+ - Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+
+allOf:
+ - $ref: rtc.yaml#
+
+properties:
+ compatible:
+ items:
+ - enum:
+ - renesas,r9a08g045-rtca3 # RZ/G3S
+ - const: renesas,rz-rtca3
+
+ reg:
+ maxItems: 1
+
+ interrupts:
+ items:
+ - description: Alarm interrupt
+ - description: Periodic interrupt
+ - description: Carry interrupt
+
+ interrupt-names:
+ items:
+ - const: alarm
+ - const: period
+ - const: carry
+
+ clocks:
+ items:
+ - description: RTC bus clock
+ - description: RTC counter clock
+
+ clock-names:
+ items:
+ - const: bus
+ - const: counter
+
+ power-domains:
+ maxItems: 1
+
+ resets:
+ items:
+ - description: VBATTB module reset
+
+required:
+ - compatible
+ - reg
+ - interrupts
+ - interrupt-names
+ - clocks
+ - clock-names
+ - power-domains
+ - resets
+
+additionalProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/r9a08g045-cpg.h>
+ #include <dt-bindings/clock/renesas,r9a08g045-vbattb.h>
+ #include <dt-bindings/interrupt-controller/arm-gic.h>
+ #include <dt-bindings/interrupt-controller/irq.h>
+
+ rtc@1004ec00 {
+ compatible = "renesas,r9a08g045-rtca3", "renesas,rz-rtca3";
+ reg = <0x1004ec00 0x400>;
+ interrupts = <GIC_SPI 315 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 316 IRQ_TYPE_LEVEL_HIGH>,
+ <GIC_SPI 317 IRQ_TYPE_LEVEL_HIGH>;
+ interrupt-names = "alarm", "period", "carry";
+ clocks = <&cpg CPG_MOD R9A08G045_VBAT_BCLK>, <&vbattclk VBATTB_VBATTCLK>;
+ clock-names = "bus", "counter";
+ power-domains = <&cpg>;
+ resets = <&cpg R9A08G045_VBAT_BRESETN>;
+ };
diff --git a/Documentation/devicetree/bindings/serial/rs485.yaml b/Documentation/devicetree/bindings/serial/rs485.yaml
index 9418fd66a8e9..b93254ad2a28 100644
--- a/Documentation/devicetree/bindings/serial/rs485.yaml
+++ b/Documentation/devicetree/bindings/serial/rs485.yaml
@@ -18,16 +18,15 @@ properties:
description: prop-encoded-array <a b>
$ref: /schemas/types.yaml#/definitions/uint32-array
items:
- items:
- - description: Delay between rts signal and beginning of data sent in
- milliseconds. It corresponds to the delay before sending data.
- default: 0
- maximum: 100
- - description: Delay between end of data sent and rts signal in milliseconds.
- It corresponds to the delay after sending data and actual release
- of the line.
- default: 0
- maximum: 100
+ - description: Delay between rts signal and beginning of data sent in
+ milliseconds. It corresponds to the delay before sending data.
+ default: 0
+ maximum: 100
+ - description: Delay between end of data sent and rts signal in milliseconds.
+ It corresponds to the delay after sending data and actual release
+ of the line.
+ default: 0
+ maximum: 100
rs485-rts-active-high:
description: drive RTS high when sending (this is the default).
diff --git a/Documentation/devicetree/bindings/serial/samsung_uart.yaml b/Documentation/devicetree/bindings/serial/samsung_uart.yaml
index 788c80e47831..070eba9f19d3 100644
--- a/Documentation/devicetree/bindings/serial/samsung_uart.yaml
+++ b/Documentation/devicetree/bindings/serial/samsung_uart.yaml
@@ -27,6 +27,7 @@ properties:
- samsung,exynos4210-uart
- samsung,exynos5433-uart
- samsung,exynos850-uart
+ - samsung,exynos8895-uart
- items:
- enum:
- samsung,exynos7-uart
@@ -160,18 +161,27 @@ allOf:
contains:
enum:
- google,gs101-uart
+ - samsung,exynos8895-uart
then:
required:
- samsung,uart-fifosize
properties:
- reg-io-width: false
-
clocks:
maxItems: 2
clock-names:
maxItems: 2
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - google,gs101-uart
+ then:
+ properties:
+ reg-io-width: false
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
index 4cdb0dcaccf3..1c163cb5dff1 100644
--- a/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/snps-dw-apb-uart.yaml
@@ -37,6 +37,8 @@ properties:
- const: renesas,rzn1-uart
- items:
- enum:
+ - brcm,bcm11351-dw-apb-uart
+ - brcm,bcm21664-dw-apb-uart
- rockchip,px30-uart
- rockchip,rk1808-uart
- rockchip,rk3036-uart
@@ -48,18 +50,13 @@ properties:
- rockchip,rk3328-uart
- rockchip,rk3368-uart
- rockchip,rk3399-uart
+ - rockchip,rk3528-uart
- rockchip,rk3568-uart
+ - rockchip,rk3576-uart
- rockchip,rk3588-uart
- rockchip,rv1108-uart
- rockchip,rv1126-uart
- - const: snps,dw-apb-uart
- - items:
- - enum:
- - brcm,bcm11351-dw-apb-uart
- - brcm,bcm21664-dw-apb-uart
- - const: snps,dw-apb-uart
- - items:
- - enum:
+ - sophgo,sg2044-uart
- starfive,jh7100-hsuart
- starfive,jh7100-uart
- starfive,jh7110-uart
diff --git a/Documentation/devicetree/bindings/serial/sprd-uart.yaml b/Documentation/devicetree/bindings/serial/sprd-uart.yaml
index f4dbb6dc2b6e..a2a5056eba04 100644
--- a/Documentation/devicetree/bindings/serial/sprd-uart.yaml
+++ b/Documentation/devicetree/bindings/serial/sprd-uart.yaml
@@ -17,6 +17,7 @@ properties:
oneOf:
- items:
- enum:
+ - sprd,sc9632-uart
- sprd,sc9860-uart
- sprd,sc9863a-uart
- sprd,ums512-uart
diff --git a/Documentation/devicetree/bindings/soc/fsl/fsl,qman-portal.yaml b/Documentation/devicetree/bindings/soc/fsl/fsl,qman-portal.yaml
index 17016184143f..e459fec02ba8 100644
--- a/Documentation/devicetree/bindings/soc/fsl/fsl,qman-portal.yaml
+++ b/Documentation/devicetree/bindings/soc/fsl/fsl,qman-portal.yaml
@@ -35,6 +35,7 @@ properties:
fsl,liodn:
$ref: /schemas/types.yaml#/definitions/uint32-array
+ maxItems: 2
description: See pamu.txt. Two LIODN(s). DQRR LIODN (DLIODN) and Frame LIODN
(FLIODN)
@@ -69,6 +70,7 @@ patternProperties:
type: object
properties:
fsl,liodn:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
description: See pamu.txt, PAMU property used for static LIODN assignment
fsl,iommu-parent:
diff --git a/Documentation/devicetree/bindings/sound/realtek,rt5645.yaml b/Documentation/devicetree/bindings/sound/realtek,rt5645.yaml
index 13f09f1bc800..0a698798c22b 100644
--- a/Documentation/devicetree/bindings/sound/realtek,rt5645.yaml
+++ b/Documentation/devicetree/bindings/sound/realtek,rt5645.yaml
@@ -51,7 +51,7 @@ properties:
description: Power supply for AVDD, providing 1.8V.
cpvdd-supply:
- description: Power supply for CPVDD, providing 3.5V.
+ description: Power supply for CPVDD, providing 1.8V.
hp-detect-gpios:
description:
diff --git a/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml b/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml
index ac99883a3f29..7f0be0ac644a 100644
--- a/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml
+++ b/Documentation/devicetree/bindings/spmi/mtk,spmi-mtk-pmif.yaml
@@ -25,6 +25,7 @@ properties:
- items:
- enum:
- mediatek,mt8186-spmi
+ - mediatek,mt8188-spmi
- const: mediatek,mt8195-spmi
reg:
diff --git a/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml b/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml
index a28b70fb330a..7c3cc20a80d6 100644
--- a/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml
+++ b/Documentation/devicetree/bindings/spmi/qcom,x1e80100-spmi-pmic-arb.yaml
@@ -19,7 +19,11 @@ description: |
properties:
compatible:
- const: qcom,x1e80100-spmi-pmic-arb
+ oneOf:
+ - items:
+ - const: qcom,sar2130p-spmi-pmic-arb
+ - const: qcom,x1e80100-spmi-pmic-arb
+ - const: qcom,x1e80100-spmi-pmic-arb
reg:
items:
diff --git a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
index bb5010dcefe1..7ffcd236d7bb 100644
--- a/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
+++ b/Documentation/devicetree/bindings/usb/allwinner,sun4i-a10-musb.yaml
@@ -25,6 +25,7 @@ properties:
- allwinner,sun20i-d1-musb
- allwinner,sun50i-a100-musb
- allwinner,sun50i-h6-musb
+ - allwinner,sun55i-a523-musb
- const: allwinner,sun8i-a33-musb
- items:
- const: allwinner,sun50i-h616-musb
diff --git a/Documentation/devicetree/bindings/usb/cypress,cypd4226.yaml b/Documentation/devicetree/bindings/usb/cypress,cypd4226.yaml
index 89fc9a434d05..0620d82508c1 100644
--- a/Documentation/devicetree/bindings/usb/cypress,cypd4226.yaml
+++ b/Documentation/devicetree/bindings/usb/cypress,cypd4226.yaml
@@ -61,18 +61,15 @@ additionalProperties: false
examples:
- |
- #include <dt-bindings/gpio/tegra194-gpio.h>
#include <dt-bindings/interrupt-controller/arm-gic.h>
i2c {
#address-cells = <1>;
#size-cells = <0>;
- #interrupt-cells = <2>;
typec@8 {
compatible = "cypress,cypd4226";
reg = <0x08>;
- interrupt-parent = <&gpio_aon>;
- interrupts = <TEGRA194_AON_GPIO(BB, 2) IRQ_TYPE_LEVEL_LOW>;
+ interrupts = <2 IRQ_TYPE_LEVEL_LOW>;
firmware-name = "nvidia,jetson-agx-xavier";
#address-cells = <1>;
#size-cells = <0>;
diff --git a/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml b/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
index 9ea1e4cd0709..baf130669c38 100644
--- a/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/fsl,imx8mp-dwc3.yaml
@@ -12,7 +12,11 @@ maintainers:
properties:
compatible:
- const: fsl,imx8mp-dwc3
+ oneOf:
+ - items:
+ - const: fsl,imx95-dwc3
+ - const: fsl,imx8mp-dwc3
+ - const: fsl,imx8mp-dwc3
reg:
items:
diff --git a/Documentation/devicetree/bindings/usb/generic-ehci.yaml b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
index 0d797e01fc0b..223f2abd5e59 100644
--- a/Documentation/devicetree/bindings/usb/generic-ehci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ehci.yaml
@@ -32,6 +32,7 @@ properties:
- allwinner,sun50i-a64-ehci
- allwinner,sun50i-h6-ehci
- allwinner,sun50i-h616-ehci
+ - allwinner,sun55i-a523-ehci
- allwinner,sun5i-a13-ehci
- allwinner,sun6i-a31-ehci
- allwinner,sun7i-a20-ehci
diff --git a/Documentation/devicetree/bindings/usb/generic-ohci.yaml b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
index cf33764553fa..3ee1586fc8b9 100644
--- a/Documentation/devicetree/bindings/usb/generic-ohci.yaml
+++ b/Documentation/devicetree/bindings/usb/generic-ohci.yaml
@@ -19,6 +19,7 @@ properties:
- allwinner,sun50i-a64-ohci
- allwinner,sun50i-h6-ohci
- allwinner,sun50i-h616-ohci
+ - allwinner,sun55i-a523-ohci
- allwinner,sun5i-a13-ohci
- allwinner,sun6i-a31-ohci
- allwinner,sun7i-a20-ohci
diff --git a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml
index fc833363cfb4..6fe2d356dcbd 100644
--- a/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml
+++ b/Documentation/devicetree/bindings/usb/genesys,gl850g.yaml
@@ -62,7 +62,14 @@ allOf:
peer-hub: true
vdd-supply: true
-additionalProperties: false
+patternProperties:
+ "^.*@[0-9a-f]{1,2}$":
+ description: The hard wired USB devices
+ type: object
+ $ref: /schemas/usb/usb-device.yaml
+ additionalProperties: true
+
+unevaluatedProperties: false
examples:
- |
diff --git a/Documentation/devicetree/bindings/usb/maxim,max33359.yaml b/Documentation/devicetree/bindings/usb/maxim,max33359.yaml
index 276bf7554215..20b62228371b 100644
--- a/Documentation/devicetree/bindings/usb/maxim,max33359.yaml
+++ b/Documentation/devicetree/bindings/usb/maxim,max33359.yaml
@@ -69,6 +69,7 @@ examples:
PDO_FIXED_DATA_SWAP |
PDO_FIXED_DUAL_ROLE)
PDO_FIXED(9000, 2000, 0)>;
+ sink-bc12-completion-time-ms = <500>;
};
};
};
diff --git a/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml b/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml
index 27b909de4992..a812317d8089 100644
--- a/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml
+++ b/Documentation/devicetree/bindings/usb/microchip,mpfs-musb.yaml
@@ -14,8 +14,11 @@ maintainers:
properties:
compatible:
- enum:
- - microchip,mpfs-musb
+ oneOf:
+ - items:
+ - const: microchip,pic64gx-musb
+ - const: microchip,mpfs-musb
+ - const: microchip,mpfs-musb
dr_mode: true
diff --git a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
index f7be05641930..935e204b607b 100644
--- a/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/qcom,dwc3.yaml
@@ -29,6 +29,7 @@ properties:
- qcom,qcs8300-dwc3
- qcom,qdu1000-dwc3
- qcom,sa8775p-dwc3
+ - qcom,sar2130p-dwc3
- qcom,sc7180-dwc3
- qcom,sc7280-dwc3
- qcom,sc8180x-dwc3
@@ -340,6 +341,7 @@ allOf:
contains:
enum:
- qcom,qcm2290-dwc3
+ - qcom,sar2130p-dwc3
- qcom,sc8180x-dwc3
- qcom,sc8180x-dwc3-mp
- qcom,sm6115-dwc3
diff --git a/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml b/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml
index c63db3ebd07b..b23ef29bf794 100644
--- a/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml
+++ b/Documentation/devicetree/bindings/usb/renesas,usbhs.yaml
@@ -76,6 +76,10 @@ properties:
Integer to use BUSWAIT register.
renesas,enable-gpio:
+ deprecated: true
+ maxItems: 1
+
+ renesas,enable-gpios:
maxItems: 1
description: |
gpio specifier to check GPIO determining if USB function should be
diff --git a/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml b/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
index c4924113f9bd..a21cc098542d 100644
--- a/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
+++ b/Documentation/devicetree/bindings/usb/rockchip,dwc3.yaml
@@ -27,6 +27,7 @@ select:
enum:
- rockchip,rk3328-dwc3
- rockchip,rk3568-dwc3
+ - rockchip,rk3576-dwc3
- rockchip,rk3588-dwc3
required:
- compatible
@@ -37,6 +38,7 @@ properties:
- enum:
- rockchip,rk3328-dwc3
- rockchip,rk3568-dwc3
+ - rockchip,rk3576-dwc3
- rockchip,rk3588-dwc3
- const: snps,dwc3
@@ -113,7 +115,9 @@ allOf:
properties:
compatible:
contains:
- const: rockchip,rk3568-dwc3
+ enum:
+ - rockchip,rk3568-dwc3
+ - rockchip,rk3576-dwc3
then:
properties:
clocks:
diff --git a/Documentation/devicetree/bindings/usb/ti,tusb1046.yaml b/Documentation/devicetree/bindings/usb/ti,tusb1046.yaml
new file mode 100644
index 000000000000..f713cac4a8ac
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ti,tusb1046.yaml
@@ -0,0 +1,49 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/ti,tusb1046.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Texas Instruments TUSB1046-DCI Type-C crosspoint switch
+
+maintainers:
+ - Romain Gantois <romain.gantois@bootlin.com>
+
+allOf:
+ - $ref: usb-switch.yaml#
+
+properties:
+ compatible:
+ const: ti,tusb1046
+
+ reg:
+ maxItems: 1
+
+required:
+ - compatible
+ - reg
+ - port
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ i2c {
+ #address-cells = <1>;
+ #size-cells = <0>;
+
+ typec-mux@44 {
+ compatible = "ti,tusb1046";
+ reg = <0x44>;
+
+ mode-switch;
+ orientation-switch;
+
+ port {
+ endpoint {
+ remote-endpoint = <&typec_controller>;
+ };
+ };
+ };
+ };
+...
diff --git a/Documentation/devicetree/bindings/usb/ti,tusb73x0-pci.yaml b/Documentation/devicetree/bindings/usb/ti,tusb73x0-pci.yaml
new file mode 100644
index 000000000000..ddda734f36fb
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/ti,tusb73x0-pci.yaml
@@ -0,0 +1,55 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/usb/ti,tusb73x0-pci.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: TUSB73x0 USB 3.0 xHCI Host Controller (PCIe)
+
+maintainers:
+ - Francesco Dolcini <francesco.dolcini@toradex.com>
+
+description:
+ TUSB73x0 USB 3.0 xHCI Host Controller via PCIe x1 Gen2 interface.
+ The TUSB7320 supports up to two downstream ports, the TUSB7340 supports up
+ to four downstream ports, both variants share the same PCI device ID.
+
+properties:
+ compatible:
+ const: pci104c,8241
+
+ reg:
+ maxItems: 1
+
+ ti,pwron-active-high:
+ $ref: /schemas/types.yaml#/definitions/flag
+ description:
+ Configure the polarity of the PWRONx# signals. When this is present, the
+ PWRONx# pins are active high and their internal pull-down resistors are
+ disabled. When this is absent, the PWRONx# pins are active low (default)
+ and their internal pull-down resistors are enabled.
+
+required:
+ - compatible
+ - reg
+
+allOf:
+ - $ref: usb-xhci.yaml
+
+additionalProperties: false
+
+examples:
+ - |
+ pcie@0 {
+ reg = <0x0 0x1000>;
+ ranges = <0x02000000 0x0 0x100000 0x10000000 0x0 0x0>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
+
+ usb@0 {
+ compatible = "pci104c,8241";
+ reg = <0x0 0x0 0x0 0x0 0x0>;
+ ti,pwron-active-high;
+ };
+ };
diff --git a/Documentation/devicetree/bindings/vendor-prefixes.yaml b/Documentation/devicetree/bindings/vendor-prefixes.yaml
index 715663b450f8..da01616802c7 100644
--- a/Documentation/devicetree/bindings/vendor-prefixes.yaml
+++ b/Documentation/devicetree/bindings/vendor-prefixes.yaml
@@ -83,6 +83,8 @@ patternProperties:
description: ALFA Network Inc.
"^allegro,.*":
description: Allegro DVT
+ "^allegromicro,.*":
+ description: Allegro MicroSystems, Inc.
"^alliedvision,.*":
description: Allied Vision Technologies GmbH
"^allo,.*":
@@ -565,6 +567,8 @@ patternProperties:
description: GE Fanuc Intelligent Platforms Embedded Systems, Inc.
"^GEFanuc,.*":
description: GE Fanuc Intelligent Platforms Embedded Systems, Inc.
+ "^gehc,.*":
+ description: GE HealthCare
"^gemei,.*":
description: Gemei Digital Technology Co., Ltd.
"^gemtek,.*":
diff --git a/Documentation/devicetree/bindings/watchdog/airoha,en7581-wdt.yaml b/Documentation/devicetree/bindings/watchdog/airoha,en7581-wdt.yaml
new file mode 100644
index 000000000000..6bbab3cb28e5
--- /dev/null
+++ b/Documentation/devicetree/bindings/watchdog/airoha,en7581-wdt.yaml
@@ -0,0 +1,47 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/watchdog/airoha,en7581-wdt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Airoha EN7581 Watchdog Timer
+
+maintainers:
+ - Christian Marangi <ansuelsmth@gmail.com>
+
+allOf:
+ - $ref: watchdog.yaml#
+
+properties:
+ compatible:
+ const: airoha,en7581-wdt
+
+ reg:
+ maxItems: 1
+
+ clocks:
+ description: BUS clock (timer ticks at half the BUS clock)
+ maxItems: 1
+
+ clock-names:
+ const: bus
+
+required:
+ - compatible
+ - reg
+ - clocks
+ - clock-names
+
+unevaluatedProperties: false
+
+examples:
+ - |
+ #include <dt-bindings/clock/en7523-clk.h>
+
+ watchdog@1fbf0100 {
+ compatible = "airoha,en7581-wdt";
+ reg = <0x1fbf0100 0x3c>;
+
+ clocks = <&scuclk EN7523_CLK_BUS>;
+ clock-names = "bus";
+ };
diff --git a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.yaml b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.yaml
index 36b836d0620c..0da953cb7127 100644
--- a/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/fsl-imx-wdt.yaml
@@ -48,6 +48,8 @@ properties:
clocks:
maxItems: 1
+ big-endian: true
+
fsl,ext-reset-output:
$ref: /schemas/types.yaml#/definitions/flag
description: |
@@ -93,6 +95,18 @@ allOf:
properties:
fsl,suspend-in-wait: false
+ - if:
+ not:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - fsl,ls1012a-wdt
+ - fsl,ls1043a-wdt
+ then:
+ properties:
+ big-endian: false
+
unevaluatedProperties: false
examples:
diff --git a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml
index 932393f8c649..34896a39fa91 100644
--- a/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/qcom-wdt.yaml
@@ -26,6 +26,8 @@ properties:
- qcom,apss-wdt-msm8994
- qcom,apss-wdt-qcm2290
- qcom,apss-wdt-qcs404
+ - qcom,apss-wdt-qcs615
+ - qcom,apss-wdt-qcs8300
- qcom,apss-wdt-sa8255p
- qcom,apss-wdt-sa8775p
- qcom,apss-wdt-sc7180
diff --git a/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml b/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml
index 77a5ddd0426e..d175ae968336 100644
--- a/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml
+++ b/Documentation/devicetree/bindings/watchdog/samsung-wdt.yaml
@@ -26,6 +26,7 @@ properties:
- samsung,exynos7-wdt # for Exynos7
- samsung,exynos850-wdt # for Exynos850
- samsung,exynosautov9-wdt # for Exynosautov9
+ - samsung,exynosautov920-wdt # for Exynosautov920
- items:
- enum:
- tesla,fsd-wdt
@@ -77,6 +78,7 @@ allOf:
- samsung,exynos7-wdt
- samsung,exynos850-wdt
- samsung,exynosautov9-wdt
+ - samsung,exynosautov920-wdt
then:
required:
- samsung,syscon-phandle
@@ -88,6 +90,7 @@ allOf:
- google,gs101-wdt
- samsung,exynos850-wdt
- samsung,exynosautov9-wdt
+ - samsung,exynosautov920-wdt
then:
properties:
clocks:
diff --git a/Documentation/driver-api/auxiliary_bus.rst b/Documentation/driver-api/auxiliary_bus.rst
index cec84908fbc0..b236de773e1d 100644
--- a/Documentation/driver-api/auxiliary_bus.rst
+++ b/Documentation/driver-api/auxiliary_bus.rst
@@ -24,7 +24,6 @@ Auxiliary Device Creation
.. kernel-doc:: drivers/base/auxiliary.c
:identifiers: auxiliary_device_init __auxiliary_device_add
- auxiliary_find_device
Auxiliary Device Memory Model and Lifespan
------------------------------------------
diff --git a/Documentation/iio/ad7380.rst b/Documentation/iio/ad7380.rst
index 6f70b49b9ef2..c46127700e14 100644
--- a/Documentation/iio/ad7380.rst
+++ b/Documentation/iio/ad7380.rst
@@ -27,6 +27,8 @@ The following chips are supported by this driver:
* `AD7386-4 <https://www.analog.com/en/products/ad7386-4.html>`_
* `AD7387-4 <https://www.analog.com/en/products/ad7387-4.html>`_
* `AD7388-4 <https://www.analog.com/en/products/ad7388-4.html>`_
+* `ADAQ4370-4 <https://www.analog.com/en/products/adaq4370-4.html>`_
+* `ADAQ4380-4 <https://www.analog.com/en/products/adaq4380-4.html>`_
Supported features
@@ -47,6 +49,12 @@ ad7380-4
ad7380-4 supports only an external reference voltage (2.5V to 3.3V). It must be
declared in the device tree as ``refin-supply``.
+ADAQ devices
+~~~~~~~~~~~~
+
+adaq4370-4 and adaq4380-4 don't have an external reference, but use a 3.3V
+internal reference derived from one of its supplies (``refin-supply``)
+
All other devices from ad738x family
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -121,6 +129,14 @@ Example for AD7386/7/8 (2 channels parts):
When enabling sequencer mode, the effective sampling rate is divided by two.
+Gain (ADAQ devices only)
+~~~~~~~~~~~~~~~~~~~~~~~~
+
+ADAQ devices have a pin selectable gain in front of each ADC. The appropriate
+gain is selectable from device tree using the ``adi,gain-milli`` property.
+Refer to the typical connection diagrams section of the datasheet for pin
+wiring.
+
Unimplemented features
----------------------
diff --git a/Documentation/iio/ad7606.rst b/Documentation/iio/ad7606.rst
new file mode 100644
index 000000000000..930199e03c67
--- /dev/null
+++ b/Documentation/iio/ad7606.rst
@@ -0,0 +1,144 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+=============
+AD7606 driver
+=============
+
+ADC driver for Analog Devices Inc. AD7606 and similar devices. The module name
+is ``ad7606``.
+
+Supported devices
+=================
+
+The following chips are supported by this driver:
+
+* `AD7605 <https://www.analog.com/en/products/ad7605.html>`_
+* `AD7606 <https://www.analog.com/en/products/ad7606.html>`_
+* `AD7606B <https://www.analog.com/en/products/ad7606b.html>`_
+* `AD7616 <https://www.analog.com/en/products/ad7616.html>`_
+
+Supported features
+==================
+
+SPI wiring modes
+----------------
+
+These ADCs can output data on several SDO lines (1/2/4/8). The driver
+currently supports only 1 SDO line.
+
+Parallel wiring mode
+--------------------
+
+There is also a parallel interface, with 16 lines (that can be reduced to 8 in
+byte mode). The parallel interface is selected by declaring the device as
+platform in the device tree (with no io-backends node defined, see below).
+
+IIO-backend mode
+----------------
+
+This mode allows to reach the best sample rates, but it requires an external
+hardware (eg HDL or APU) to handle the low level communication.
+The backend mode is enabled when through the definition of the "io-backends"
+property in the device tree.
+
+The reference configuration for the current implementation of IIO-backend mode
+is the HDL reference provided by ADI:
+https://wiki.analog.com/resources/eval/user-guides/ad7606x-fmc/hdl
+
+This implementation embeds an IIO-backend compatible IP (adi-axi-adc) and a PWM
+connected to the conversion trigger pin.
+
+.. code-block::
+
+ +---+ +----------------------------
+ | | +-------+ |AD76xx
+ | A | controls | | |
+ | D |-------------->| PWM |-------------->| cnvst
+ | 7 | | | |
+ | 6 | +-------+ |
+ | 0 | controls +-----------+-----------+ |
+ | 6 |---------->| | |<--| frstdata
+ | | | Backend | Backend |<--| busy
+ | D | | Driver | | |
+ | R | | | |-->| clk
+ | I | requests |+---------+| DMA | |
+ | V |----------->| Buffer ||<---- |<=>| DATA
+ | E | |+---------+| | |
+ | R | +-----------+-----------+ |
+ | |-------------------------------------->| reset/configuration gpios
+ +---+ +-----------------------------
+
+
+Software and hardware modes
+---------------------------
+
+While all the AD7606/AD7616 series parts can be configured using GPIOs, some of
+them can be configured using register.
+
+The chips that support software mode have more values available for configuring
+the device, as well as more settings, and allow to control the range and
+calibration per channel.
+
+The following settings are available per channel in software mode:
+ - Scale
+
+Also, there is a broader choice of oversampling ratios in software mode.
+
+Conversion triggering
+---------------------
+
+The conversion can be triggered by two distinct ways:
+
+ - A GPIO is connected to the conversion trigger pin, and this GPIO is controlled
+ by the driver directly. In this configuration, the driver sets back the
+ conversion trigger pin to high as soon as it has read all the conversions.
+
+ - An external source is connected to the conversion trigger pin. In the
+ current implementation, it must be a PWM. In this configuration, the driver
+ does not control directly the conversion trigger pin. Instead, it can
+ control the PWM's frequency. This trigger is enabled only for iio-backend.
+
+Reference voltage
+-----------------
+
+2 possible reference voltage sources are supported:
+
+ - Internal reference (2.5V)
+ - External reference (2.5V)
+
+The source is determined by the device tree. If ``refin-supply`` is present,
+then the external reference is used, otherwise the internal reference is used.
+
+Oversampling
+------------
+
+This family supports oversampling to improve SNR.
+In software mode, the following ratios are available:
+1 (oversampling disabled)/2/4/8/16/32/64/128/256.
+
+Unimplemented features
+----------------------
+
+- 2/4/8 SDO lines
+- CRC indication
+- Calibration
+
+Device buffers
+==============
+
+IIO triggered buffer
+--------------------
+
+This driver supports IIO triggered buffers, with a "built in" trigger, i.e the
+trigger is allocated and linked by the driver, and a new conversion is triggered
+as soon as the samples are transferred, and a timestamp channel is added to make
+up for the potential jitter induced by the delays in the interrupt handling.
+
+IIO backend buffer
+------------------
+
+When IIO backend is used, the trigger is not needed, and the sample rate is
+considered as stable. There is no timestamp channel. The communication is
+delegated to an external logic, called a backend, and the backend's driver
+handles the buffer. When this mode is enabled, the driver cannot control the
+conversion pin, because the busy pin is bound to the backend.
diff --git a/Documentation/iio/ad7625.rst b/Documentation/iio/ad7625.rst
new file mode 100644
index 000000000000..61761e3b75c3
--- /dev/null
+++ b/Documentation/iio/ad7625.rst
@@ -0,0 +1,91 @@
+.. SPDX-License-Identifier: GPL-2.0-only
+
+====================
+AD7625 driver
+====================
+
+ADC driver for Analog Devices Inc. AD7625, AD7626, AD7960, and AD7961
+devices. The module name is ``ad7625``.
+
+Supported devices
+=================
+
+The following chips are supported by this driver:
+
+* `AD7625 <https://www.analog.com/AD7625>`_
+* `AD7626 <https://www.analog.com/AD7626>`_
+* `AD7960 <https://www.analog.com/AD7960>`_
+* `AD7961 <https://www.analog.com/AD7961>`_
+
+The driver requires use of the Pulsar LVDS HDL project:
+
+* `Pulsar LVDS HDL <http://analogdevicesinc.github.io/hdl/projects/pulsar_lvds/index.html>`_
+
+To trigger conversions and enable subsequent data transfer, the devices
+require coupled PWM signals with a phase offset.
+
+Supported features
+==================
+
+Conversion control modes
+------------------------
+
+The driver currently supports one of two possible LVDS conversion control methods.
+
+Echoed-Clock interface mode
+^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block::
+
+ +----------------+
+ +xxxxxxxxxxxxxxxxxxxxxxxxxx| CNV |
+ X | |
+ v | HOST |
+ +----------------------------+ | |
+ | CNV+/CNV- DCO+/DCO- |xxxxxxx>| CLK_IN |
+ | | | |
+ | | | |
+ | AD7625 D+/D- |xxxxxxx>| DATA_IN |
+ | | | |
+ | | | |
+ | CLK+/CLK- |<xxxxxxx| CLK & CLK_GATE |
+ +----------------------------+ | |
+ +----------------+
+
+Reference voltage
+-----------------
+
+Three possible reference voltage sources are supported:
+
+- Internal reference (only available on AD7625 and AD7626)
+- External reference and internal buffer
+- External reference
+
+The source is determined by the device tree. If ``ref-supply`` is present, then
+the external reference is used. If ``refin-supply`` is present, then the internal
+buffer is used. If neither is present, then the internal reference is used.
+
+Unimplemented features
+----------------------
+
+- Self-clocked mode
+
+
+Device attributes
+=================
+
+The AD762x is a fully-differential ADC and has the following attributes:
+
++---------------------------------------+--------------------------------------------------------------+
+| Attribute | Description |
++=======================================+==============================================================+
+| ``scale`` | Scale factor to convert raw value from buffered reads to mV. |
++---------------------------------------+--------------------------------------------------------------+
+
+
+Device buffers
+==============
+
+This driver supports IIO triggered buffers.
+
+See :doc:`iio_devbuf` for more information.
diff --git a/Documentation/iio/bno055.rst b/Documentation/iio/bno055.rst
index 9a489a79d8f5..f1111ff3fe2e 100644
--- a/Documentation/iio/bno055.rst
+++ b/Documentation/iio/bno055.rst
@@ -22,7 +22,7 @@ This driver supports also IIO buffers.
The IMU continuously performs an autocalibration procedure if (and only if)
operating in fusion mode. The magnetometer autocalibration can however be
-disabled writing 0 in the sysfs in_magn_calibration_fast_enable attribute.
+disabled by writing 0 in the sysfs in_magn_calibration_fast_enable attribute.
The driver provides access to autocalibration flags (i.e. you can known if
the IMU has successfully autocalibrated) and to the calibration data blob.
diff --git a/Documentation/iio/index.rst b/Documentation/iio/index.rst
index dfcf9618568a..074dbbf7ba0a 100644
--- a/Documentation/iio/index.rst
+++ b/Documentation/iio/index.rst
@@ -21,6 +21,8 @@ Industrial I/O Kernel Drivers
ad4000
ad4695
ad7380
+ ad7606
+ ad7625
ad7944
adis16475
adis16480
diff --git a/Documentation/kbuild/kbuild.rst b/Documentation/kbuild/kbuild.rst
index 1796b3eba37b..17c9f920f03d 100644
--- a/Documentation/kbuild/kbuild.rst
+++ b/Documentation/kbuild/kbuild.rst
@@ -137,12 +137,18 @@ Specify the output directory when building the kernel.
This variable can also be used to point to the kernel output directory when
building external modules against a pre-built kernel in a separate build
directory. Please note that this does NOT specify the output directory for the
-external modules themselves.
+external modules themselves. (Use KBUILD_EXTMOD_OUTPUT for that purpose.)
The output directory can also be specified using "O=...".
Setting "O=..." takes precedence over KBUILD_OUTPUT.
+KBUILD_EXTMOD_OUTPUT
+--------------------
+Specify the output directory for external modules.
+
+Setting "MO=..." takes precedence over KBUILD_EXTMOD_OUTPUT.
+
KBUILD_EXTRA_WARN
-----------------
Specify the extra build checks. The same value can be assigned by passing
diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst
index 43037be96a16..2619fdf56e68 100644
--- a/Documentation/kbuild/kconfig-language.rst
+++ b/Documentation/kbuild/kconfig-language.rst
@@ -412,8 +412,8 @@ choices::
<choice block>
"endchoice"
-This defines a choice group and accepts any of the above attributes as
-options.
+This defines a choice group and accepts "prompt", "default", "depends on", and
+"help" attributes as options.
A choice only allows a single config entry to be selected.
diff --git a/Documentation/kbuild/llvm.rst b/Documentation/kbuild/llvm.rst
index 6dc66b4f31a7..bc8a283bc44b 100644
--- a/Documentation/kbuild/llvm.rst
+++ b/Documentation/kbuild/llvm.rst
@@ -179,6 +179,9 @@ yet. Bug reports are always welcome at the issue tracker below!
* - s390
- Maintained
- ``LLVM=1`` (LLVM >= 18.1.0), ``CC=clang`` (LLVM < 18.1.0)
+ * - sparc (sparc64 only)
+ - Maintained
+ - ``CC=clang LLVM_IAS=0`` (LLVM >= 20)
* - um (User Mode)
- Maintained
- ``LLVM=1``
diff --git a/Documentation/kbuild/makefiles.rst b/Documentation/kbuild/makefiles.rst
index 7964e0c245ae..d36519f194dc 100644
--- a/Documentation/kbuild/makefiles.rst
+++ b/Documentation/kbuild/makefiles.rst
@@ -449,6 +449,20 @@ $(obj)
to prerequisites are referenced with $(src) (because they are not
generated files).
+$(srcroot)
+ $(srcroot) refers to the root of the source you are building, which can be
+ either the kernel source or the external modules source, depending on whether
+ KBUILD_EXTMOD is set. This can be either a relative or an absolute path, but
+ if KBUILD_ABS_SRCTREE=1 is set, it is always an absolute path.
+
+$(srctree)
+ $(srctree) refers to the root of the kernel source tree. When building the
+ kernel, this is the same as $(srcroot).
+
+$(objtree)
+ $(objtree) refers to the root of the kernel object tree. It is ``.`` when
+ building the kernel, but it is different when building external modules.
+
$(kecho)
echoing information to user in a rule is often a good practice
but when execution ``make -s`` one does not expect to see any output
diff --git a/Documentation/kbuild/modules.rst b/Documentation/kbuild/modules.rst
index cd5a54d91e6d..101de236cd0c 100644
--- a/Documentation/kbuild/modules.rst
+++ b/Documentation/kbuild/modules.rst
@@ -59,6 +59,12 @@ Command Syntax
$ make -C /lib/modules/`uname -r`/build M=$PWD modules_install
+ Starting from Linux 6.13, you can use the -f option instead of -C. This
+ will avoid unnecessary change of the working directory. The external
+ module will be output to the directory where you invoke make.
+
+ $ make -f /lib/modules/`uname -r`/build/Makefile M=$PWD
+
Options
-------
@@ -66,7 +72,10 @@ Options
of the kernel output directory if the kernel was built in a separate
build directory.)
- make -C $KDIR M=$PWD
+ You can optionally pass MO= option if you want to build the modules in
+ a separate directory.
+
+ make -C $KDIR M=$PWD [MO=$BUILD_DIR]
-C $KDIR
The directory that contains the kernel and relevant build
@@ -80,6 +89,9 @@ Options
directory where the external module (kbuild file) is
located.
+ MO=$BUILD_DIR
+ Specifies a separate output directory for the external module.
+
Targets
-------
@@ -215,6 +227,21 @@ Separate Kbuild File and Makefile
consisting of several hundred lines, and here it really pays
off to separate the kbuild part from the rest.
+ Linux 6.13 and later support another way. The external module Makefile
+ can include the kernel Makefile directly, rather than invoking sub Make.
+
+ Example 3::
+
+ --> filename: Kbuild
+ obj-m := 8123.o
+ 8123-y := 8123_if.o 8123_pci.o
+
+ --> filename: Makefile
+ KDIR ?= /lib/modules/$(shell uname -r)/build
+ export KBUILD_EXTMOD := $(realpath $(dir $(lastword $(MAKEFILE_LIST))))
+ include $(KDIR)/Makefile
+
+
Building Multiple Modules
-------------------------
diff --git a/Documentation/mm/process_addrs.rst b/Documentation/mm/process_addrs.rst
index e8618fbc62c9..1d416658d7f5 100644
--- a/Documentation/mm/process_addrs.rst
+++ b/Documentation/mm/process_addrs.rst
@@ -3,3 +3,853 @@
=================
Process Addresses
=================
+
+.. toctree::
+ :maxdepth: 3
+
+
+Userland memory ranges are tracked by the kernel via Virtual Memory Areas or
+'VMA's of type :c:struct:`!struct vm_area_struct`.
+
+Each VMA describes a virtually contiguous memory range with identical
+attributes, each described by a :c:struct:`!struct vm_area_struct`
+object. Userland access outside of VMAs is invalid except in the case where an
+adjacent stack VMA could be extended to contain the accessed address.
+
+All VMAs are contained within one and only one virtual address space, described
+by a :c:struct:`!struct mm_struct` object which is referenced by all tasks (that is,
+threads) which share the virtual address space. We refer to this as the
+:c:struct:`!mm`.
+
+Each mm object contains a maple tree data structure which describes all VMAs
+within the virtual address space.
+
+.. note:: An exception to this is the 'gate' VMA which is provided by
+ architectures which use :c:struct:`!vsyscall` and is a global static
+ object which does not belong to any specific mm.
+
+-------
+Locking
+-------
+
+The kernel is designed to be highly scalable against concurrent read operations
+on VMA **metadata** so a complicated set of locks are required to ensure memory
+corruption does not occur.
+
+.. note:: Locking VMAs for their metadata does not have any impact on the memory
+ they describe nor the page tables that map them.
+
+Terminology
+-----------
+
+* **mmap locks** - Each MM has a read/write semaphore :c:member:`!mmap_lock`
+ which locks at a process address space granularity which can be acquired via
+ :c:func:`!mmap_read_lock`, :c:func:`!mmap_write_lock` and variants.
+* **VMA locks** - The VMA lock is at VMA granularity (of course) which behaves
+ as a read/write semaphore in practice. A VMA read lock is obtained via
+ :c:func:`!lock_vma_under_rcu` (and unlocked via :c:func:`!vma_end_read`) and a
+ write lock via :c:func:`!vma_start_write` (all VMA write locks are unlocked
+ automatically when the mmap write lock is released). To take a VMA write lock
+ you **must** have already acquired an :c:func:`!mmap_write_lock`.
+* **rmap locks** - When trying to access VMAs through the reverse mapping via a
+ :c:struct:`!struct address_space` or :c:struct:`!struct anon_vma` object
+ (reachable from a folio via :c:member:`!folio->mapping`). VMAs must be stabilised via
+ :c:func:`!anon_vma_[try]lock_read` or :c:func:`!anon_vma_[try]lock_write` for
+ anonymous memory and :c:func:`!i_mmap_[try]lock_read` or
+ :c:func:`!i_mmap_[try]lock_write` for file-backed memory. We refer to these
+ locks as the reverse mapping locks, or 'rmap locks' for brevity.
+
+We discuss page table locks separately in the dedicated section below.
+
+The first thing **any** of these locks achieve is to **stabilise** the VMA
+within the MM tree. That is, guaranteeing that the VMA object will not be
+deleted from under you nor modified (except for some specific fields
+described below).
+
+Stabilising a VMA also keeps the address space described by it around.
+
+Lock usage
+----------
+
+If you want to **read** VMA metadata fields or just keep the VMA stable, you
+must do one of the following:
+
+* Obtain an mmap read lock at the MM granularity via :c:func:`!mmap_read_lock` (or a
+ suitable variant), unlocking it with a matching :c:func:`!mmap_read_unlock` when
+ you're done with the VMA, *or*
+* Try to obtain a VMA read lock via :c:func:`!lock_vma_under_rcu`. This tries to
+ acquire the lock atomically so might fail, in which case fall-back logic is
+ required to instead obtain an mmap read lock if this returns :c:macro:`!NULL`,
+ *or*
+* Acquire an rmap lock before traversing the locked interval tree (whether
+ anonymous or file-backed) to obtain the required VMA.
+
+If you want to **write** VMA metadata fields, then things vary depending on the
+field (we explore each VMA field in detail below). For the majority you must:
+
+* Obtain an mmap write lock at the MM granularity via :c:func:`!mmap_write_lock` (or a
+ suitable variant), unlocking it with a matching :c:func:`!mmap_write_unlock` when
+ you're done with the VMA, *and*
+* Obtain a VMA write lock via :c:func:`!vma_start_write` for each VMA you wish to
+ modify, which will be released automatically when :c:func:`!mmap_write_unlock` is
+ called.
+* If you want to be able to write to **any** field, you must also hide the VMA
+ from the reverse mapping by obtaining an **rmap write lock**.
+
+VMA locks are special in that you must obtain an mmap **write** lock **first**
+in order to obtain a VMA **write** lock. A VMA **read** lock however can be
+obtained without any other lock (:c:func:`!lock_vma_under_rcu` will acquire then
+release an RCU lock to lookup the VMA for you).
+
+This constrains the impact of writers on readers, as a writer can interact with
+one VMA while a reader interacts with another simultaneously.
+
+.. note:: The primary users of VMA read locks are page fault handlers, which
+ means that without a VMA write lock, page faults will run concurrent with
+ whatever you are doing.
+
+Examining all valid lock states:
+
+.. table::
+
+ ========= ======== ========= ======= ===== =========== ==========
+ mmap lock VMA lock rmap lock Stable? Read? Write most? Write all?
+ ========= ======== ========= ======= ===== =========== ==========
+ \- \- \- N N N N
+ \- R \- Y Y N N
+ \- \- R/W Y Y N N
+ R/W \-/R \-/R/W Y Y N N
+ W W \-/R Y Y Y N
+ W W W Y Y Y Y
+ ========= ======== ========= ======= ===== =========== ==========
+
+.. warning:: While it's possible to obtain a VMA lock while holding an mmap read lock,
+ attempting to do the reverse is invalid as it can result in deadlock - if
+ another task already holds an mmap write lock and attempts to acquire a VMA
+ write lock that will deadlock on the VMA read lock.
+
+All of these locks behave as read/write semaphores in practice, so you can
+obtain either a read or a write lock for each of these.
+
+.. note:: Generally speaking, a read/write semaphore is a class of lock which
+ permits concurrent readers. However a write lock can only be obtained
+ once all readers have left the critical region (and pending readers
+ made to wait).
+
+ This renders read locks on a read/write semaphore concurrent with other
+ readers and write locks exclusive against all others holding the semaphore.
+
+VMA fields
+^^^^^^^^^^
+
+We can subdivide :c:struct:`!struct vm_area_struct` fields by their purpose, which makes it
+easier to explore their locking characteristics:
+
+.. note:: We exclude VMA lock-specific fields here to avoid confusion, as these
+ are in effect an internal implementation detail.
+
+.. table:: Virtual layout fields
+
+ ===================== ======================================== ===========
+ Field Description Write lock
+ ===================== ======================================== ===========
+ :c:member:`!vm_start` Inclusive start virtual address of range mmap write,
+ VMA describes. VMA write,
+ rmap write.
+ :c:member:`!vm_end` Exclusive end virtual address of range mmap write,
+ VMA describes. VMA write,
+ rmap write.
+ :c:member:`!vm_pgoff` Describes the page offset into the file, mmap write,
+ the original page offset within the VMA write,
+ virtual address space (prior to any rmap write.
+ :c:func:`!mremap`), or PFN if a PFN map
+ and the architecture does not support
+ :c:macro:`!CONFIG_ARCH_HAS_PTE_SPECIAL`.
+ ===================== ======================================== ===========
+
+These fields describes the size, start and end of the VMA, and as such cannot be
+modified without first being hidden from the reverse mapping since these fields
+are used to locate VMAs within the reverse mapping interval trees.
+
+.. table:: Core fields
+
+ ============================ ======================================== =========================
+ Field Description Write lock
+ ============================ ======================================== =========================
+ :c:member:`!vm_mm` Containing mm_struct. None - written once on
+ initial map.
+ :c:member:`!vm_page_prot` Architecture-specific page table mmap write, VMA write.
+ protection bits determined from VMA
+ flags.
+ :c:member:`!vm_flags` Read-only access to VMA flags describing N/A
+ attributes of the VMA, in union with
+ private writable
+ :c:member:`!__vm_flags`.
+ :c:member:`!__vm_flags` Private, writable access to VMA flags mmap write, VMA write.
+ field, updated by
+ :c:func:`!vm_flags_*` functions.
+ :c:member:`!vm_file` If the VMA is file-backed, points to a None - written once on
+ struct file object describing the initial map.
+ underlying file, if anonymous then
+ :c:macro:`!NULL`.
+ :c:member:`!vm_ops` If the VMA is file-backed, then either None - Written once on
+ the driver or file-system provides a initial map by
+ :c:struct:`!struct vm_operations_struct` :c:func:`!f_ops->mmap()`.
+ object describing callbacks to be
+ invoked on VMA lifetime events.
+ :c:member:`!vm_private_data` A :c:member:`!void *` field for Handled by driver.
+ driver-specific metadata.
+ ============================ ======================================== =========================
+
+These are the core fields which describe the MM the VMA belongs to and its attributes.
+
+.. table:: Config-specific fields
+
+ ================================= ===================== ======================================== ===============
+ Field Configuration option Description Write lock
+ ================================= ===================== ======================================== ===============
+ :c:member:`!anon_name` CONFIG_ANON_VMA_NAME A field for storing a mmap write,
+ :c:struct:`!struct anon_vma_name` VMA write.
+ object providing a name for anonymous
+ mappings, or :c:macro:`!NULL` if none
+ is set or the VMA is file-backed. The
+ underlying object is reference counted
+ and can be shared across multiple VMAs
+ for scalability.
+ :c:member:`!swap_readahead_info` CONFIG_SWAP Metadata used by the swap mechanism mmap read,
+ to perform readahead. This field is swap-specific
+ accessed atomically. lock.
+ :c:member:`!vm_policy` CONFIG_NUMA :c:type:`!mempolicy` object which mmap write,
+ describes the NUMA behaviour of the VMA write.
+ VMA. The underlying object is reference
+ counted.
+ :c:member:`!numab_state` CONFIG_NUMA_BALANCING :c:type:`!vma_numab_state` object which mmap read,
+ describes the current state of numab-specific
+ NUMA balancing in relation to this VMA. lock.
+ Updated under mmap read lock by
+ :c:func:`!task_numa_work`.
+ :c:member:`!vm_userfaultfd_ctx` CONFIG_USERFAULTFD Userfaultfd context wrapper object of mmap write,
+ type :c:type:`!vm_userfaultfd_ctx`, VMA write.
+ either of zero size if userfaultfd is
+ disabled, or containing a pointer
+ to an underlying
+ :c:type:`!userfaultfd_ctx` object which
+ describes userfaultfd metadata.
+ ================================= ===================== ======================================== ===============
+
+These fields are present or not depending on whether the relevant kernel
+configuration option is set.
+
+.. table:: Reverse mapping fields
+
+ =================================== ========================================= ============================
+ Field Description Write lock
+ =================================== ========================================= ============================
+ :c:member:`!shared.rb` A red/black tree node used, if the mmap write, VMA write,
+ mapping is file-backed, to place the VMA i_mmap write.
+ in the
+ :c:member:`!struct address_space->i_mmap`
+ red/black interval tree.
+ :c:member:`!shared.rb_subtree_last` Metadata used for management of the mmap write, VMA write,
+ interval tree if the VMA is file-backed. i_mmap write.
+ :c:member:`!anon_vma_chain` List of pointers to both forked/CoW’d mmap read, anon_vma write.
+ :c:type:`!anon_vma` objects and
+ :c:member:`!vma->anon_vma` if it is
+ non-:c:macro:`!NULL`.
+ :c:member:`!anon_vma` :c:type:`!anon_vma` object used by When :c:macro:`NULL` and
+ anonymous folios mapped exclusively to setting non-:c:macro:`NULL`:
+ this VMA. Initially set by mmap read, page_table_lock.
+ :c:func:`!anon_vma_prepare` serialised
+ by the :c:macro:`!page_table_lock`. This When non-:c:macro:`NULL` and
+ is set as soon as any page is faulted in. setting :c:macro:`NULL`:
+ mmap write, VMA write,
+ anon_vma write.
+ =================================== ========================================= ============================
+
+These fields are used to both place the VMA within the reverse mapping, and for
+anonymous mappings, to be able to access both related :c:struct:`!struct anon_vma` objects
+and the :c:struct:`!struct anon_vma` in which folios mapped exclusively to this VMA should
+reside.
+
+.. note:: If a file-backed mapping is mapped with :c:macro:`!MAP_PRIVATE` set
+ then it can be in both the :c:type:`!anon_vma` and :c:type:`!i_mmap`
+ trees at the same time, so all of these fields might be utilised at
+ once.
+
+Page tables
+-----------
+
+We won't speak exhaustively on the subject but broadly speaking, page tables map
+virtual addresses to physical ones through a series of page tables, each of
+which contain entries with physical addresses for the next page table level
+(along with flags), and at the leaf level the physical addresses of the
+underlying physical data pages or a special entry such as a swap entry,
+migration entry or other special marker. Offsets into these pages are provided
+by the virtual address itself.
+
+In Linux these are divided into five levels - PGD, P4D, PUD, PMD and PTE. Huge
+pages might eliminate one or two of these levels, but when this is the case we
+typically refer to the leaf level as the PTE level regardless.
+
+.. note:: In instances where the architecture supports fewer page tables than
+ five the kernel cleverly 'folds' page table levels, that is stubbing
+ out functions related to the skipped levels. This allows us to
+ conceptually act as if there were always five levels, even if the
+ compiler might, in practice, eliminate any code relating to missing
+ ones.
+
+There are four key operations typically performed on page tables:
+
+1. **Traversing** page tables - Simply reading page tables in order to traverse
+ them. This only requires that the VMA is kept stable, so a lock which
+ establishes this suffices for traversal (there are also lockless variants
+ which eliminate even this requirement, such as :c:func:`!gup_fast`).
+2. **Installing** page table mappings - Whether creating a new mapping or
+ modifying an existing one in such a way as to change its identity. This
+ requires that the VMA is kept stable via an mmap or VMA lock (explicitly not
+ rmap locks).
+3. **Zapping/unmapping** page table entries - This is what the kernel calls
+ clearing page table mappings at the leaf level only, whilst leaving all page
+ tables in place. This is a very common operation in the kernel performed on
+ file truncation, the :c:macro:`!MADV_DONTNEED` operation via
+ :c:func:`!madvise`, and others. This is performed by a number of functions
+ including :c:func:`!unmap_mapping_range` and :c:func:`!unmap_mapping_pages`.
+ The VMA need only be kept stable for this operation.
+4. **Freeing** page tables - When finally the kernel removes page tables from a
+ userland process (typically via :c:func:`!free_pgtables`) extreme care must
+ be taken to ensure this is done safely, as this logic finally frees all page
+ tables in the specified range, ignoring existing leaf entries (it assumes the
+ caller has both zapped the range and prevented any further faults or
+ modifications within it).
+
+.. note:: Modifying mappings for reclaim or migration is performed under rmap
+ lock as it, like zapping, does not fundamentally modify the identity
+ of what is being mapped.
+
+**Traversing** and **zapping** ranges can be performed holding any one of the
+locks described in the terminology section above - that is the mmap lock, the
+VMA lock or either of the reverse mapping locks.
+
+That is - as long as you keep the relevant VMA **stable** - you are good to go
+ahead and perform these operations on page tables (though internally, kernel
+operations that perform writes also acquire internal page table locks to
+serialise - see the page table implementation detail section for more details).
+
+When **installing** page table entries, the mmap or VMA lock must be held to
+keep the VMA stable. We explore why this is in the page table locking details
+section below.
+
+.. warning:: Page tables are normally only traversed in regions covered by VMAs.
+ If you want to traverse page tables in areas that might not be
+ covered by VMAs, heavier locking is required.
+ See :c:func:`!walk_page_range_novma` for details.
+
+**Freeing** page tables is an entirely internal memory management operation and
+has special requirements (see the page freeing section below for more details).
+
+.. warning:: When **freeing** page tables, it must not be possible for VMAs
+ containing the ranges those page tables map to be accessible via
+ the reverse mapping.
+
+ The :c:func:`!free_pgtables` function removes the relevant VMAs
+ from the reverse mappings, but no other VMAs can be permitted to be
+ accessible and span the specified range.
+
+Lock ordering
+-------------
+
+As we have multiple locks across the kernel which may or may not be taken at the
+same time as explicit mm or VMA locks, we have to be wary of lock inversion, and
+the **order** in which locks are acquired and released becomes very important.
+
+.. note:: Lock inversion occurs when two threads need to acquire multiple locks,
+ but in doing so inadvertently cause a mutual deadlock.
+
+ For example, consider thread 1 which holds lock A and tries to acquire lock B,
+ while thread 2 holds lock B and tries to acquire lock A.
+
+ Both threads are now deadlocked on each other. However, had they attempted to
+ acquire locks in the same order, one would have waited for the other to
+ complete its work and no deadlock would have occurred.
+
+The opening comment in :c:macro:`!mm/rmap.c` describes in detail the required
+ordering of locks within memory management code:
+
+.. code-block::
+
+ inode->i_rwsem (while writing or truncating, not reading or faulting)
+ mm->mmap_lock
+ mapping->invalidate_lock (in filemap_fault)
+ folio_lock
+ hugetlbfs_i_mmap_rwsem_key (in huge_pmd_share, see hugetlbfs below)
+ vma_start_write
+ mapping->i_mmap_rwsem
+ anon_vma->rwsem
+ mm->page_table_lock or pte_lock
+ swap_lock (in swap_duplicate, swap_info_get)
+ mmlist_lock (in mmput, drain_mmlist and others)
+ mapping->private_lock (in block_dirty_folio)
+ i_pages lock (widely used)
+ lruvec->lru_lock (in folio_lruvec_lock_irq)
+ inode->i_lock (in set_page_dirty's __mark_inode_dirty)
+ bdi.wb->list_lock (in set_page_dirty's __mark_inode_dirty)
+ sb_lock (within inode_lock in fs/fs-writeback.c)
+ i_pages lock (widely used, in set_page_dirty,
+ in arch-dependent flush_dcache_mmap_lock,
+ within bdi.wb->list_lock in __sync_single_inode)
+
+There is also a file-system specific lock ordering comment located at the top of
+:c:macro:`!mm/filemap.c`:
+
+.. code-block::
+
+ ->i_mmap_rwsem (truncate_pagecache)
+ ->private_lock (__free_pte->block_dirty_folio)
+ ->swap_lock (exclusive_swap_page, others)
+ ->i_pages lock
+
+ ->i_rwsem
+ ->invalidate_lock (acquired by fs in truncate path)
+ ->i_mmap_rwsem (truncate->unmap_mapping_range)
+
+ ->mmap_lock
+ ->i_mmap_rwsem
+ ->page_table_lock or pte_lock (various, mainly in memory.c)
+ ->i_pages lock (arch-dependent flush_dcache_mmap_lock)
+
+ ->mmap_lock
+ ->invalidate_lock (filemap_fault)
+ ->lock_page (filemap_fault, access_process_vm)
+
+ ->i_rwsem (generic_perform_write)
+ ->mmap_lock (fault_in_readable->do_page_fault)
+
+ bdi->wb.list_lock
+ sb_lock (fs/fs-writeback.c)
+ ->i_pages lock (__sync_single_inode)
+
+ ->i_mmap_rwsem
+ ->anon_vma.lock (vma_merge)
+
+ ->anon_vma.lock
+ ->page_table_lock or pte_lock (anon_vma_prepare and various)
+
+ ->page_table_lock or pte_lock
+ ->swap_lock (try_to_unmap_one)
+ ->private_lock (try_to_unmap_one)
+ ->i_pages lock (try_to_unmap_one)
+ ->lruvec->lru_lock (follow_page_mask->mark_page_accessed)
+ ->lruvec->lru_lock (check_pte_range->folio_isolate_lru)
+ ->private_lock (folio_remove_rmap_pte->set_page_dirty)
+ ->i_pages lock (folio_remove_rmap_pte->set_page_dirty)
+ bdi.wb->list_lock (folio_remove_rmap_pte->set_page_dirty)
+ ->inode->i_lock (folio_remove_rmap_pte->set_page_dirty)
+ bdi.wb->list_lock (zap_pte_range->set_page_dirty)
+ ->inode->i_lock (zap_pte_range->set_page_dirty)
+ ->private_lock (zap_pte_range->block_dirty_folio)
+
+Please check the current state of these comments which may have changed since
+the time of writing of this document.
+
+------------------------------
+Locking Implementation Details
+------------------------------
+
+.. warning:: Locking rules for PTE-level page tables are very different from
+ locking rules for page tables at other levels.
+
+Page table locking details
+--------------------------
+
+In addition to the locks described in the terminology section above, we have
+additional locks dedicated to page tables:
+
+* **Higher level page table locks** - Higher level page tables, that is PGD, P4D
+ and PUD each make use of the process address space granularity
+ :c:member:`!mm->page_table_lock` lock when modified.
+
+* **Fine-grained page table locks** - PMDs and PTEs each have fine-grained locks
+ either kept within the folios describing the page tables or allocated
+ separated and pointed at by the folios if :c:macro:`!ALLOC_SPLIT_PTLOCKS` is
+ set. The PMD spin lock is obtained via :c:func:`!pmd_lock`, however PTEs are
+ mapped into higher memory (if a 32-bit system) and carefully locked via
+ :c:func:`!pte_offset_map_lock`.
+
+These locks represent the minimum required to interact with each page table
+level, but there are further requirements.
+
+Importantly, note that on a **traversal** of page tables, sometimes no such
+locks are taken. However, at the PTE level, at least concurrent page table
+deletion must be prevented (using RCU) and the page table must be mapped into
+high memory, see below.
+
+Whether care is taken on reading the page table entries depends on the
+architecture, see the section on atomicity below.
+
+Locking rules
+^^^^^^^^^^^^^
+
+We establish basic locking rules when interacting with page tables:
+
+* When changing a page table entry the page table lock for that page table
+ **must** be held, except if you can safely assume nobody can access the page
+ tables concurrently (such as on invocation of :c:func:`!free_pgtables`).
+* Reads from and writes to page table entries must be *appropriately*
+ atomic. See the section on atomicity below for details.
+* Populating previously empty entries requires that the mmap or VMA locks are
+ held (read or write), doing so with only rmap locks would be dangerous (see
+ the warning below).
+* As mentioned previously, zapping can be performed while simply keeping the VMA
+ stable, that is holding any one of the mmap, VMA or rmap locks.
+
+.. warning:: Populating previously empty entries is dangerous as, when unmapping
+ VMAs, :c:func:`!vms_clear_ptes` has a window of time between
+ zapping (via :c:func:`!unmap_vmas`) and freeing page tables (via
+ :c:func:`!free_pgtables`), where the VMA is still visible in the
+ rmap tree. :c:func:`!free_pgtables` assumes that the zap has
+ already been performed and removes PTEs unconditionally (along with
+ all other page tables in the freed range), so installing new PTE
+ entries could leak memory and also cause other unexpected and
+ dangerous behaviour.
+
+There are additional rules applicable when moving page tables, which we discuss
+in the section on this topic below.
+
+PTE-level page tables are different from page tables at other levels, and there
+are extra requirements for accessing them:
+
+* On 32-bit architectures, they may be in high memory (meaning they need to be
+ mapped into kernel memory to be accessible).
+* When empty, they can be unlinked and RCU-freed while holding an mmap lock or
+ rmap lock for reading in combination with the PTE and PMD page table locks.
+ In particular, this happens in :c:func:`!retract_page_tables` when handling
+ :c:macro:`!MADV_COLLAPSE`.
+ So accessing PTE-level page tables requires at least holding an RCU read lock;
+ but that only suffices for readers that can tolerate racing with concurrent
+ page table updates such that an empty PTE is observed (in a page table that
+ has actually already been detached and marked for RCU freeing) while another
+ new page table has been installed in the same location and filled with
+ entries. Writers normally need to take the PTE lock and revalidate that the
+ PMD entry still refers to the same PTE-level page table.
+
+To access PTE-level page tables, a helper like :c:func:`!pte_offset_map_lock` or
+:c:func:`!pte_offset_map` can be used depending on stability requirements.
+These map the page table into kernel memory if required, take the RCU lock, and
+depending on variant, may also look up or acquire the PTE lock.
+See the comment on :c:func:`!__pte_offset_map_lock`.
+
+Atomicity
+^^^^^^^^^
+
+Regardless of page table locks, the MMU hardware concurrently updates accessed
+and dirty bits (perhaps more, depending on architecture). Additionally, page
+table traversal operations in parallel (though holding the VMA stable) and
+functionality like GUP-fast locklessly traverses (that is reads) page tables,
+without even keeping the VMA stable at all.
+
+When performing a page table traversal and keeping the VMA stable, whether a
+read must be performed once and only once or not depends on the architecture
+(for instance x86-64 does not require any special precautions).
+
+If a write is being performed, or if a read informs whether a write takes place
+(on an installation of a page table entry say, for instance in
+:c:func:`!__pud_install`), special care must always be taken. In these cases we
+can never assume that page table locks give us entirely exclusive access, and
+must retrieve page table entries once and only once.
+
+If we are reading page table entries, then we need only ensure that the compiler
+does not rearrange our loads. This is achieved via :c:func:`!pXXp_get`
+functions - :c:func:`!pgdp_get`, :c:func:`!p4dp_get`, :c:func:`!pudp_get`,
+:c:func:`!pmdp_get`, and :c:func:`!ptep_get`.
+
+Each of these uses :c:func:`!READ_ONCE` to guarantee that the compiler reads
+the page table entry only once.
+
+However, if we wish to manipulate an existing page table entry and care about
+the previously stored data, we must go further and use an hardware atomic
+operation as, for example, in :c:func:`!ptep_get_and_clear`.
+
+Equally, operations that do not rely on the VMA being held stable, such as
+GUP-fast (see :c:func:`!gup_fast` and its various page table level handlers like
+:c:func:`!gup_fast_pte_range`), must very carefully interact with page table
+entries, using functions such as :c:func:`!ptep_get_lockless` and equivalent for
+higher level page table levels.
+
+Writes to page table entries must also be appropriately atomic, as established
+by :c:func:`!set_pXX` functions - :c:func:`!set_pgd`, :c:func:`!set_p4d`,
+:c:func:`!set_pud`, :c:func:`!set_pmd`, and :c:func:`!set_pte`.
+
+Equally functions which clear page table entries must be appropriately atomic,
+as in :c:func:`!pXX_clear` functions - :c:func:`!pgd_clear`,
+:c:func:`!p4d_clear`, :c:func:`!pud_clear`, :c:func:`!pmd_clear`, and
+:c:func:`!pte_clear`.
+
+Page table installation
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Page table installation is performed with the VMA held stable explicitly by an
+mmap or VMA lock in read or write mode (see the warning in the locking rules
+section for details as to why).
+
+When allocating a P4D, PUD or PMD and setting the relevant entry in the above
+PGD, P4D or PUD, the :c:member:`!mm->page_table_lock` must be held. This is
+acquired in :c:func:`!__p4d_alloc`, :c:func:`!__pud_alloc` and
+:c:func:`!__pmd_alloc` respectively.
+
+.. note:: :c:func:`!__pmd_alloc` actually invokes :c:func:`!pud_lock` and
+ :c:func:`!pud_lockptr` in turn, however at the time of writing it ultimately
+ references the :c:member:`!mm->page_table_lock`.
+
+Allocating a PTE will either use the :c:member:`!mm->page_table_lock` or, if
+:c:macro:`!USE_SPLIT_PMD_PTLOCKS` is defined, a lock embedded in the PMD
+physical page metadata in the form of a :c:struct:`!struct ptdesc`, acquired by
+:c:func:`!pmd_ptdesc` called from :c:func:`!pmd_lock` and ultimately
+:c:func:`!__pte_alloc`.
+
+Finally, modifying the contents of the PTE requires special treatment, as the
+PTE page table lock must be acquired whenever we want stable and exclusive
+access to entries contained within a PTE, especially when we wish to modify
+them.
+
+This is performed via :c:func:`!pte_offset_map_lock` which carefully checks to
+ensure that the PTE hasn't changed from under us, ultimately invoking
+:c:func:`!pte_lockptr` to obtain a spin lock at PTE granularity contained within
+the :c:struct:`!struct ptdesc` associated with the physical PTE page. The lock
+must be released via :c:func:`!pte_unmap_unlock`.
+
+.. note:: There are some variants on this, such as
+ :c:func:`!pte_offset_map_rw_nolock` when we know we hold the PTE stable but
+ for brevity we do not explore this. See the comment for
+ :c:func:`!__pte_offset_map_lock` for more details.
+
+When modifying data in ranges we typically only wish to allocate higher page
+tables as necessary, using these locks to avoid races or overwriting anything,
+and set/clear data at the PTE level as required (for instance when page faulting
+or zapping).
+
+A typical pattern taken when traversing page table entries to install a new
+mapping is to optimistically determine whether the page table entry in the table
+above is empty, if so, only then acquiring the page table lock and checking
+again to see if it was allocated underneath us.
+
+This allows for a traversal with page table locks only being taken when
+required. An example of this is :c:func:`!__pud_alloc`.
+
+At the leaf page table, that is the PTE, we can't entirely rely on this pattern
+as we have separate PMD and PTE locks and a THP collapse for instance might have
+eliminated the PMD entry as well as the PTE from under us.
+
+This is why :c:func:`!__pte_offset_map_lock` locklessly retrieves the PMD entry
+for the PTE, carefully checking it is as expected, before acquiring the
+PTE-specific lock, and then *again* checking that the PMD entry is as expected.
+
+If a THP collapse (or similar) were to occur then the lock on both pages would
+be acquired, so we can ensure this is prevented while the PTE lock is held.
+
+Installing entries this way ensures mutual exclusion on write.
+
+Page table freeing
+^^^^^^^^^^^^^^^^^^
+
+Tearing down page tables themselves is something that requires significant
+care. There must be no way that page tables designated for removal can be
+traversed or referenced by concurrent tasks.
+
+It is insufficient to simply hold an mmap write lock and VMA lock (which will
+prevent racing faults, and rmap operations), as a file-backed mapping can be
+truncated under the :c:struct:`!struct address_space->i_mmap_rwsem` alone.
+
+As a result, no VMA which can be accessed via the reverse mapping (either
+through the :c:struct:`!struct anon_vma->rb_root` or the :c:member:`!struct
+address_space->i_mmap` interval trees) can have its page tables torn down.
+
+The operation is typically performed via :c:func:`!free_pgtables`, which assumes
+either the mmap write lock has been taken (as specified by its
+:c:member:`!mm_wr_locked` parameter), or that the VMA is already unreachable.
+
+It carefully removes the VMA from all reverse mappings, however it's important
+that no new ones overlap these or any route remain to permit access to addresses
+within the range whose page tables are being torn down.
+
+Additionally, it assumes that a zap has already been performed and steps have
+been taken to ensure that no further page table entries can be installed between
+the zap and the invocation of :c:func:`!free_pgtables`.
+
+Since it is assumed that all such steps have been taken, page table entries are
+cleared without page table locks (in the :c:func:`!pgd_clear`, :c:func:`!p4d_clear`,
+:c:func:`!pud_clear`, and :c:func:`!pmd_clear` functions.
+
+.. note:: It is possible for leaf page tables to be torn down independent of
+ the page tables above it as is done by
+ :c:func:`!retract_page_tables`, which is performed under the i_mmap
+ read lock, PMD, and PTE page table locks, without this level of care.
+
+Page table moving
+^^^^^^^^^^^^^^^^^
+
+Some functions manipulate page table levels above PMD (that is PUD, P4D and PGD
+page tables). Most notable of these is :c:func:`!mremap`, which is capable of
+moving higher level page tables.
+
+In these instances, it is required that **all** locks are taken, that is
+the mmap lock, the VMA lock and the relevant rmap locks.
+
+You can observe this in the :c:func:`!mremap` implementation in the functions
+:c:func:`!take_rmap_locks` and :c:func:`!drop_rmap_locks` which perform the rmap
+side of lock acquisition, invoked ultimately by :c:func:`!move_page_tables`.
+
+VMA lock internals
+------------------
+
+Overview
+^^^^^^^^
+
+VMA read locking is entirely optimistic - if the lock is contended or a competing
+write has started, then we do not obtain a read lock.
+
+A VMA **read** lock is obtained by :c:func:`!lock_vma_under_rcu`, which first
+calls :c:func:`!rcu_read_lock` to ensure that the VMA is looked up in an RCU
+critical section, then attempts to VMA lock it via :c:func:`!vma_start_read`,
+before releasing the RCU lock via :c:func:`!rcu_read_unlock`.
+
+VMA read locks hold the read lock on the :c:member:`!vma->vm_lock` semaphore for
+their duration and the caller of :c:func:`!lock_vma_under_rcu` must release it
+via :c:func:`!vma_end_read`.
+
+VMA **write** locks are acquired via :c:func:`!vma_start_write` in instances where a
+VMA is about to be modified, unlike :c:func:`!vma_start_read` the lock is always
+acquired. An mmap write lock **must** be held for the duration of the VMA write
+lock, releasing or downgrading the mmap write lock also releases the VMA write
+lock so there is no :c:func:`!vma_end_write` function.
+
+Note that a semaphore write lock is not held across a VMA lock. Rather, a
+sequence number is used for serialisation, and the write semaphore is only
+acquired at the point of write lock to update this.
+
+This ensures the semantics we require - VMA write locks provide exclusive write
+access to the VMA.
+
+Implementation details
+^^^^^^^^^^^^^^^^^^^^^^
+
+The VMA lock mechanism is designed to be a lightweight means of avoiding the use
+of the heavily contended mmap lock. It is implemented using a combination of a
+read/write semaphore and sequence numbers belonging to the containing
+:c:struct:`!struct mm_struct` and the VMA.
+
+Read locks are acquired via :c:func:`!vma_start_read`, which is an optimistic
+operation, i.e. it tries to acquire a read lock but returns false if it is
+unable to do so. At the end of the read operation, :c:func:`!vma_end_read` is
+called to release the VMA read lock.
+
+Invoking :c:func:`!vma_start_read` requires that :c:func:`!rcu_read_lock` has
+been called first, establishing that we are in an RCU critical section upon VMA
+read lock acquisition. Once acquired, the RCU lock can be released as it is only
+required for lookup. This is abstracted by :c:func:`!lock_vma_under_rcu` which
+is the interface a user should use.
+
+Writing requires the mmap to be write-locked and the VMA lock to be acquired via
+:c:func:`!vma_start_write`, however the write lock is released by the termination or
+downgrade of the mmap write lock so no :c:func:`!vma_end_write` is required.
+
+All this is achieved by the use of per-mm and per-VMA sequence counts, which are
+used in order to reduce complexity, especially for operations which write-lock
+multiple VMAs at once.
+
+If the mm sequence count, :c:member:`!mm->mm_lock_seq` is equal to the VMA
+sequence count :c:member:`!vma->vm_lock_seq` then the VMA is write-locked. If
+they differ, then it is not.
+
+Each time the mmap write lock is released in :c:func:`!mmap_write_unlock` or
+:c:func:`!mmap_write_downgrade`, :c:func:`!vma_end_write_all` is invoked which
+also increments :c:member:`!mm->mm_lock_seq` via
+:c:func:`!mm_lock_seqcount_end`.
+
+This way, we ensure that, regardless of the VMA's sequence number, a write lock
+is never incorrectly indicated and that when we release an mmap write lock we
+efficiently release **all** VMA write locks contained within the mmap at the
+same time.
+
+Since the mmap write lock is exclusive against others who hold it, the automatic
+release of any VMA locks on its release makes sense, as you would never want to
+keep VMAs locked across entirely separate write operations. It also maintains
+correct lock ordering.
+
+Each time a VMA read lock is acquired, we acquire a read lock on the
+:c:member:`!vma->vm_lock` read/write semaphore and hold it, while checking that
+the sequence count of the VMA does not match that of the mm.
+
+If it does, the read lock fails. If it does not, we hold the lock, excluding
+writers, but permitting other readers, who will also obtain this lock under RCU.
+
+Importantly, maple tree operations performed in :c:func:`!lock_vma_under_rcu`
+are also RCU safe, so the whole read lock operation is guaranteed to function
+correctly.
+
+On the write side, we acquire a write lock on the :c:member:`!vma->vm_lock`
+read/write semaphore, before setting the VMA's sequence number under this lock,
+also simultaneously holding the mmap write lock.
+
+This way, if any read locks are in effect, :c:func:`!vma_start_write` will sleep
+until these are finished and mutual exclusion is achieved.
+
+After setting the VMA's sequence number, the lock is released, avoiding
+complexity with a long-term held write lock.
+
+This clever combination of a read/write semaphore and sequence count allows for
+fast RCU-based per-VMA lock acquisition (especially on page fault, though
+utilised elsewhere) with minimal complexity around lock ordering.
+
+mmap write lock downgrading
+---------------------------
+
+When an mmap write lock is held one has exclusive access to resources within the
+mmap (with the usual caveats about requiring VMA write locks to avoid races with
+tasks holding VMA read locks).
+
+It is then possible to **downgrade** from a write lock to a read lock via
+:c:func:`!mmap_write_downgrade` which, similar to :c:func:`!mmap_write_unlock`,
+implicitly terminates all VMA write locks via :c:func:`!vma_end_write_all`, but
+importantly does not relinquish the mmap lock while downgrading, therefore
+keeping the locked virtual address space stable.
+
+An interesting consequence of this is that downgraded locks are exclusive
+against any other task possessing a downgraded lock (since a racing task would
+have to acquire a write lock first to downgrade it, and the downgraded lock
+prevents a new write lock from being obtained until the original lock is
+released).
+
+For clarity, we map read (R)/downgraded write (D)/write (W) locks against one
+another showing which locks exclude the others:
+
+.. list-table:: Lock exclusivity
+ :widths: 5 5 5 5
+ :header-rows: 1
+ :stub-columns: 1
+
+ * -
+ - R
+ - D
+ - W
+ * - R
+ - N
+ - N
+ - Y
+ * - D
+ - N
+ - Y
+ - Y
+ * - W
+ - Y
+ - Y
+ - Y
+
+Here a Y indicates the locks in the matching row/column are mutually exclusive,
+and N indicates that they are not.
+
+Stack expansion
+---------------
+
+Stack expansion throws up additional complexities in that we cannot permit there
+to be racing page faults, as a result we invoke :c:func:`!vma_start_write` to
+prevent this in :c:func:`!expand_downwards` or :c:func:`!expand_upwards`.
diff --git a/Documentation/netlink/genetlink-c.yaml b/Documentation/netlink/genetlink-c.yaml
index 4f803eaac6d8..9660ffb1ed6a 100644
--- a/Documentation/netlink/genetlink-c.yaml
+++ b/Documentation/netlink/genetlink-c.yaml
@@ -106,6 +106,9 @@ properties:
name-prefix:
description: For enum the prefix of the values, optional.
type: string
+ enum-cnt-name:
+ description: Name of the render-max counter enum entry.
+ type: string
# End genetlink-c
attribute-sets:
diff --git a/Documentation/netlink/genetlink-legacy.yaml b/Documentation/netlink/genetlink-legacy.yaml
index 8db0e22fa72c..16380e12cabe 100644
--- a/Documentation/netlink/genetlink-legacy.yaml
+++ b/Documentation/netlink/genetlink-legacy.yaml
@@ -117,6 +117,9 @@ properties:
name-prefix:
description: For enum the prefix of the values, optional.
type: string
+ enum-cnt-name:
+ description: Name of the render-max counter enum entry.
+ type: string
# End genetlink-c
# Start genetlink-legacy
members:
diff --git a/Documentation/netlink/netlink-raw.yaml b/Documentation/netlink/netlink-raw.yaml
index 914aa1c0a273..1b0772c8e333 100644
--- a/Documentation/netlink/netlink-raw.yaml
+++ b/Documentation/netlink/netlink-raw.yaml
@@ -221,7 +221,7 @@ properties:
type: &attr-type
description: The netlink attribute type
enum: [ unused, pad, flag, binary, bitfield32,
- u8, u16, u32, u64, s8, s16, s32, s64,
+ uint, sint, u8, u16, u32, u64, s8, s16, s32, s64,
string, nest, indexed-array, nest-type-value,
sub-message ]
doc:
diff --git a/Documentation/netlink/specs/ethtool.yaml b/Documentation/netlink/specs/ethtool.yaml
index 93369f0eb816..60f85fbf4156 100644
--- a/Documentation/netlink/specs/ethtool.yaml
+++ b/Documentation/netlink/specs/ethtool.yaml
@@ -5,6 +5,7 @@ name: ethtool
protocol: genetlink-legacy
doc: Partial family for Ethtool Netlink.
+uapi-header: linux/ethtool_netlink_generated.h
definitions:
-
@@ -12,44 +13,100 @@ definitions:
enum-name:
type: enum
entries: [ vxlan, geneve, vxlan-gpe ]
+ enum-cnt-name: __ethtool-udp-tunnel-type-cnt
+ render-max: true
-
name: stringset
type: enum
entries: []
+ header: linux/ethtool.h # skip rendering, no actual definition
-
name: header-flags
type: flags
- entries: [ compact-bitsets, omit-reply, stats ]
+ name-prefix: ethtool-flag-
+ doc: common ethtool header flags
+ entries:
+ -
+ name: compact-bitsets
+ doc: use compact bitsets in reply
+ -
+ name: omit-reply
+ doc: provide optional reply for SET or ACT requests
+ -
+ name: stats
+ doc: request statistics, if supported by the driver
-
name: module-fw-flash-status
type: enum
- entries: [ started, in_progress, completed, error ]
+ doc: plug-in module firmware flashing status
+ header: linux/ethtool.h
+ entries:
+ -
+ name: started
+ doc: The firmware flashing process has started.
+ -
+ name: in_progress
+ doc: The firmware flashing process is in progress.
+ -
+ name: completed
+ doc: The firmware flashing process was completed successfully.
+ -
+ name: error
+ doc: The firmware flashing process was stopped due to an error.
-
name: c33-pse-ext-state
- enum-name:
+ doc: "groups of PSE extended states functions. IEEE 802.3-2022 33.2.4.4 Variables"
type: enum
name-prefix: ethtool-c33-pse-ext-state-
+ header: linux/ethtool.h
entries:
- - none
- - error-condition
- - mr-mps-valid
- - mr-pse-enable
- - option-detect-ted
- - option-vport-lim
- - ovld-detected
- - power-not-available
- - short-detected
+ -
+ name: none
+ doc: none
+ -
+ name: error-condition
+ doc: Group of error_condition states
+ -
+ name: mr-mps-valid
+ doc: Group of mr_mps_valid states
+ -
+ name: mr-pse-enable
+ doc: Group of mr_pse_enable states
+ -
+ name: option-detect-ted
+ doc: Group of option_detect_ted states
+ -
+ name: option-vport-lim
+ doc: Group of option_vport_lim states
+ -
+ name: ovld-detected
+ doc: Group of ovld_detected states
+ -
+ name: power-not-available
+ doc: Group of power_not_available states
+ -
+ name: short-detected
+ doc: Group of short_detected states
-
name: phy-upstream-type
enum-name:
type: enum
entries: [ mac, phy ]
+ -
+ name: tcp-data-split
+ type: enum
+ entries: [ unknown, disabled, enabled ]
attribute-sets:
-
name: header
+ attr-cnt-name: __ethtool-a-header-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: dev-index
type: u32
-
@@ -65,8 +122,13 @@ attribute-sets:
-
name: bitset-bit
+ attr-cnt-name: __ethtool-a-bitset-bit-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: index
type: u32
-
@@ -77,16 +139,26 @@ attribute-sets:
type: flag
-
name: bitset-bits
+ attr-cnt-name: __ethtool-a-bitset-bits-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: bit
type: nest
multi-attr: true
nested-attributes: bitset-bit
-
name: bitset
+ attr-cnt-name: __ethtool-a-bitset-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: nomask
type: flag
-
@@ -104,8 +176,13 @@ attribute-sets:
type: binary
-
name: string
+ attr-cnt-name: __ethtool-a-string-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: index
type: u32
-
@@ -113,16 +190,30 @@ attribute-sets:
type: string
-
name: strings
+ attr-cnt-name: __ethtool-a-strings-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
+ name: unspec
+ type: unused
+ value: 0
+ -
name: string
type: nest
multi-attr: true
nested-attributes: string
-
name: stringset
+ attr-cnt-name: __ethtool-a-stringset-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: id
type: u32
-
@@ -135,16 +226,26 @@ attribute-sets:
nested-attributes: strings
-
name: stringsets
+ attr-cnt-name: __ethtool-a-stringsets-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: stringset
type: nest
multi-attr: true
nested-attributes: stringset
-
name: strset
+ attr-cnt-name: __ethtool-a-strset-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -158,8 +259,13 @@ attribute-sets:
-
name: privflags
+ attr-cnt-name: __ethtool-a-privflags-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -170,8 +276,13 @@ attribute-sets:
-
name: rings
+ attr-cnt-name: __ethtool-a-rings-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -205,6 +316,7 @@ attribute-sets:
-
name: tcp-data-split
type: u8
+ enum: tcp-data-split
-
name: cqe-size
type: u32
@@ -223,32 +335,49 @@ attribute-sets:
-
name: mm-stat
+ attr-cnt-name: __ethtool-a-mm-stat-cnt
+ doc: MAC Merge (802.3)
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: pad
type: pad
-
name: reassembly-errors
+ doc: aMACMergeFrameAssErrorCount
type: u64
-
name: smd-errors
+ doc: aMACMergeFrameSmdErrorCount
type: u64
-
name: reassembly-ok
+ doc: aMACMergeFrameAssOkCount
type: u64
-
name: rx-frag-count
+ doc: aMACMergeFragCountRx
type: u64
-
name: tx-frag-count
+ doc: aMACMergeFragCountTx
type: u64
-
name: hold-count
+ doc: aMACMergeHoldCount
type: u64
-
name: mm
+ attr-cnt-name: __ethtool-a-mm-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -285,8 +414,13 @@ attribute-sets:
nested-attributes: mm-stat
-
name: linkinfo
+ attr-cnt-name: __ethtool-a-linkinfo-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -307,8 +441,13 @@ attribute-sets:
type: u8
-
name: linkmodes
+ attr-cnt-name: __ethtool-a-linkmodes-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -343,8 +482,13 @@ attribute-sets:
type: u8
-
name: linkstate
+ attr-cnt-name: __ethtool-a-linkstate-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -368,8 +512,13 @@ attribute-sets:
type: u32
-
name: debug
+ attr-cnt-name: __ethtool-a-debug-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -379,8 +528,13 @@ attribute-sets:
nested-attributes: bitset
-
name: wol
+ attr-cnt-name: __ethtool-a-wol-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -393,8 +547,13 @@ attribute-sets:
type: binary
-
name: features
+ attr-cnt-name: __ethtool-a-features-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -416,8 +575,13 @@ attribute-sets:
nested-attributes: bitset
-
name: channels
+ attr-cnt-name: __ethtool-a-channels-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -448,8 +612,13 @@ attribute-sets:
-
name: irq-moderation
+ attr-cnt-name: __ethtool-a-irq-moderation-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: usec
type: u32
-
@@ -460,16 +629,26 @@ attribute-sets:
type: u32
-
name: profile
+ attr-cnt-name: __ethtool-a-profile-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: irq-moderation
type: nest
multi-attr: true
nested-attributes: irq-moderation
-
name: coalesce
+ attr-cnt-name: __ethtool-a-coalesce-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -565,8 +744,13 @@ attribute-sets:
-
name: pause-stat
+ attr-cnt-name: __ethtool-a-pause-stat-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: pad
type: pad
-
@@ -577,8 +761,13 @@ attribute-sets:
type: u64
-
name: pause
+ attr-cnt-name: __ethtool-a-pause-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -600,8 +789,13 @@ attribute-sets:
type: u32
-
name: eee
+ attr-cnt-name: __ethtool-a-eee-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -627,8 +821,13 @@ attribute-sets:
type: u32
-
name: ts-stat
+ attr-cnt-name: __ethtool-a-ts-stat-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: tx-pkts
type: uint
-
@@ -638,9 +837,28 @@ attribute-sets:
name: tx-err
type: uint
-
+ name: ts-hwtstamp-provider
+ attr-cnt-name: __ethtool-a-ts-hwtstamp-provider-cnt
+ attributes:
+ -
+ name: unspec
+ type: unused
+ value: 0
+ -
+ name: index
+ type: u32
+ -
+ name: qualifier
+ type: u32
+ -
name: tsinfo
+ attr-cnt-name: __ethtool-a-tsinfo-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -663,22 +881,39 @@ attribute-sets:
name: stats
type: nest
nested-attributes: ts-stat
+ -
+ name: hwtstamp-provider
+ type: nest
+ nested-attributes: ts-hwtstamp-provider
-
name: cable-result
+ attr-cnt-name: __ethtool-a-cable-result-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: pair
+ doc: ETHTOOL_A_CABLE_PAIR
type: u8
-
name: code
+ doc: ETHTOOL_A_CABLE_RESULT_CODE
type: u8
-
name: src
+ doc: ETHTOOL_A_CABLE_INF_SRC
type: u32
-
name: cable-fault-length
+ attr-cnt-name: __ethtool-a-cable-fault-length-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: pair
type: u8
-
@@ -689,8 +924,13 @@ attribute-sets:
type: u32
-
name: cable-nest
+ attr-cnt-name: __ethtool-a-cable-nest-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: result
type: nest
nested-attributes: cable-result
@@ -700,20 +940,31 @@ attribute-sets:
nested-attributes: cable-fault-length
-
name: cable-test
+ attr-cnt-name: __ethtool-a-cable-test-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
-
name: cable-test-ntf
+ attr-cnt-name: __ethtool-a-cable-test-ntf-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
-
name: status
+ doc: _STARTED/_COMPLETE
type: u8
-
name: nest
@@ -721,8 +972,13 @@ attribute-sets:
nested-attributes: cable-nest
-
name: cable-test-tdr-cfg
+ attr-cnt-name: __ethtool-a-cable-test-tdr-cfg-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: first
type: u32
-
@@ -736,8 +992,13 @@ attribute-sets:
type: u8
-
name: cable-test-tdr-ntf
+ attr-cnt-name: __ethtool-a-cable-test-tdr-ntf-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -750,8 +1011,13 @@ attribute-sets:
nested-attributes: cable-nest
-
name: cable-test-tdr
+ attr-cnt-name: __ethtool-a-cable-test-tdr-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -761,8 +1027,13 @@ attribute-sets:
nested-attributes: cable-test-tdr-cfg
-
name: tunnel-udp-entry
+ attr-cnt-name: __ethtool-a-tunnel-udp-entry-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: port
type: u16
byte-order: big-endian
@@ -772,8 +1043,13 @@ attribute-sets:
enum: udp-tunnel-type
-
name: tunnel-udp-table
+ attr-cnt-name: __ethtool-a-tunnel-udp-table-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: size
type: u32
-
@@ -787,15 +1063,25 @@ attribute-sets:
nested-attributes: tunnel-udp-entry
-
name: tunnel-udp
+ attr-cnt-name: __ethtool-a-tunnel-udp-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: table
type: nest
nested-attributes: tunnel-udp-table
-
name: tunnel-info
+ attr-cnt-name: __ethtool-a-tunnel-info-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -805,8 +1091,13 @@ attribute-sets:
nested-attributes: tunnel-udp
-
name: fec-stat
+ attr-cnt-name: __ethtool-a-fec-stat-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: pad
type: pad
-
@@ -823,8 +1114,13 @@ attribute-sets:
sub-type: u64
-
name: fec
+ attr-cnt-name: __ethtool-a-fec-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -844,8 +1140,13 @@ attribute-sets:
nested-attributes: fec-stat
-
name: module-eeprom
+ attr-cnt-name: __ethtool-a-module-eeprom-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -869,8 +1170,13 @@ attribute-sets:
type: binary
-
name: stats-grp
+ attr-cnt-name: __ethtool-a-stats-grp-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: pad
type: pad
-
@@ -912,8 +1218,13 @@ attribute-sets:
name: hist-val
-
name: stats
+ attr-cnt-name: __ethtool-a-stats-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: pad
type: pad
-
@@ -933,8 +1244,13 @@ attribute-sets:
type: u32
-
name: phc-vclocks
+ attr-cnt-name: __ethtool-a-phc-vclocks-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -947,8 +1263,13 @@ attribute-sets:
sub-type: s32
-
name: module
+ attr-cnt-name: __ethtool-a-module-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -960,8 +1281,14 @@ attribute-sets:
type: u8
-
name: c33-pse-pw-limit
+ attr-cnt-name: __ethtool-a-c33-pse-pw-limit-cnt
+ attr-max-name: __ethtool-a-c33-pse-pw-limit-max
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: min
type: u32
-
@@ -969,8 +1296,13 @@ attribute-sets:
type: u32
-
name: pse
+ attr-cnt-name: __ethtool-a-pse-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -1027,8 +1359,13 @@ attribute-sets:
nested-attributes: c33-pse-pw-limit
-
name: rss
+ attr-cnt-name: __ethtool-a-rss-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -1053,8 +1390,13 @@ attribute-sets:
type: u32
-
name: plca
+ attr-cnt-name: __ethtool-a-plca-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -1084,8 +1426,13 @@ attribute-sets:
type: u32
-
name: module-fw-flash
+ attr-cnt-name: __ethtool-a-module-fw-flash-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -1110,8 +1457,13 @@ attribute-sets:
type: uint
-
name: phy
+ attr-cnt-name: __ethtool-a-phy-cnt
attributes:
-
+ name: unspec
+ type: unused
+ value: 0
+ -
name: header
type: nest
nested-attributes: header
@@ -1137,6 +1489,33 @@ attribute-sets:
-
name: downstream-sfp-name
type: string
+ -
+ name: tsconfig
+ attr-cnt-name: __ethtool-a-tsconfig-cnt
+ attributes:
+ -
+ name: unspec
+ type: unused
+ value: 0
+ -
+ name: header
+ type: nest
+ nested-attributes: header
+ -
+ name: hwtstamp-provider
+ type: nest
+ nested-attributes: ts-hwtstamp-provider
+ -
+ name: tx-types
+ type: nest
+ nested-attributes: bitset
+ -
+ name: rx-filters
+ type: nest
+ nested-attributes: bitset
+ -
+ name: hwtstamp-flags
+ type: u32
operations:
enum-model: directional
@@ -1578,6 +1957,7 @@ operations:
request:
attributes:
- header
+ - hwtstamp-provider
reply:
attributes:
- header
@@ -1586,6 +1966,7 @@ operations:
- rx-filters
- phc-index
- stats
+ - hwtstamp-provider
dump: *tsinfo-get-op
-
name: cable-test-act
@@ -1960,3 +2341,32 @@ operations:
name: phy-ntf
doc: Notification for change in PHY devices.
notify: phy-get
+ -
+ name: tsconfig-get
+ doc: Get hwtstamp config.
+
+ attribute-set: tsconfig
+
+ do: &tsconfig-get-op
+ request:
+ attributes:
+ - header
+ reply:
+ attributes: &tsconfig
+ - header
+ - hwtstamp-provider
+ - tx-types
+ - rx-filters
+ - hwtstamp-flags
+ dump: *tsconfig-get-op
+ -
+ name: tsconfig-set
+ doc: Set hwtstamp config.
+
+ attribute-set: tsconfig
+
+ do:
+ request:
+ attributes: *tsconfig
+ reply:
+ attributes: *tsconfig
diff --git a/Documentation/netlink/specs/mptcp_pm.yaml b/Documentation/netlink/specs/mptcp_pm.yaml
index dc190bf838fe..dfd017780d2f 100644
--- a/Documentation/netlink/specs/mptcp_pm.yaml
+++ b/Documentation/netlink/specs/mptcp_pm.yaml
@@ -22,65 +22,67 @@ definitions:
doc: unused event
-
name: created
- doc:
- token, family, saddr4 | saddr6, daddr4 | daddr6, sport, dport
+ doc: >-
A new MPTCP connection has been created. It is the good time to
allocate memory and send ADD_ADDR if needed. Depending on the
traffic-patterns it can take a long time until the
MPTCP_EVENT_ESTABLISHED is sent.
+ Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport,
+ dport, server-side.
-
name: established
- doc:
- token, family, saddr4 | saddr6, daddr4 | daddr6, sport, dport
+ doc: >-
A MPTCP connection is established (can start new subflows).
+ Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6, sport,
+ dport, server-side.
-
name: closed
- doc:
- token
+ doc: >-
A MPTCP connection has stopped.
+ Attribute: token.
-
name: announced
value: 6
- doc:
- token, rem_id, family, daddr4 | daddr6 [, dport]
+ doc: >-
A new address has been announced by the peer.
+ Attributes: token, rem_id, family, daddr4 | daddr6 [, dport].
-
name: removed
- doc:
- token, rem_id
+ doc: >-
An address has been lost by the peer.
+ Attributes: token, rem_id.
-
name: sub-established
value: 10
- doc:
- token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | daddr6, sport,
- dport, backup, if_idx [, error]
+ doc: >-
A new subflow has been established. 'error' should not be set.
+ Attributes: token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 |
+ daddr6, sport, dport, backup, if_idx [, error].
-
name: sub-closed
- doc:
- token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | daddr6, sport,
- dport, backup, if_idx [, error]
+ doc: >-
A subflow has been closed. An error (copy of sk_err) could be set if an
error has been detected for this subflow.
+ Attributes: token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 |
+ daddr6, sport, dport, backup, if_idx [, error].
-
name: sub-priority
value: 13
- doc:
- token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 | daddr6, sport,
- dport, backup, if_idx [, error]
+ doc: >-
The priority of a subflow has changed. 'error' should not be set.
+ Attributes: token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 |
+ daddr6, sport, dport, backup, if_idx [, error].
-
name: listener-created
value: 15
- doc:
- family, sport, saddr4 | saddr6
+ doc: >-
A new PM listener is created.
+ Attributes: family, sport, saddr4 | saddr6.
-
name: listener-closed
- doc:
- family, sport, saddr4 | saddr6
+ doc: >-
A PM listener is closed.
+ Attributes: family, sport, saddr4 | saddr6.
attribute-sets:
-
@@ -306,8 +308,8 @@ operations:
attributes:
- addr
-
- name: flush-addrs
- doc: flush addresses
+ name: flush-addrs
+ doc: Flush addresses
attribute-set: endpoint
dont-validate: [ strict ]
flags: [ uns-admin-perm ]
@@ -351,7 +353,7 @@ operations:
- addr-remote
-
name: announce
- doc: announce new sf
+ doc: Announce new address
attribute-set: attr
dont-validate: [ strict ]
flags: [ uns-admin-perm ]
@@ -362,7 +364,7 @@ operations:
- token
-
name: remove
- doc: announce removal
+ doc: Announce removal
attribute-set: attr
dont-validate: [ strict ]
flags: [ uns-admin-perm ]
@@ -373,7 +375,7 @@ operations:
- loc-id
-
name: subflow-create
- doc: todo
+ doc: Create subflow
attribute-set: attr
dont-validate: [ strict ]
flags: [ uns-admin-perm ]
@@ -385,7 +387,7 @@ operations:
- addr-remote
-
name: subflow-destroy
- doc: todo
+ doc: Destroy subflow
attribute-set: attr
dont-validate: [ strict ]
flags: [ uns-admin-perm ]
diff --git a/Documentation/netlink/specs/rt_link.yaml b/Documentation/netlink/specs/rt_link.yaml
index 9ffa13b77dcf..0d492500c7e5 100644
--- a/Documentation/netlink/specs/rt_link.yaml
+++ b/Documentation/netlink/specs/rt_link.yaml
@@ -1826,6 +1826,48 @@ attribute-sets:
name: erspan-hwid
type: u16
-
+ name: linkinfo-vti-attrs
+ name-prefix: ifla-vti-
+ attributes:
+ -
+ name: link
+ type: u32
+ -
+ name: ikey
+ type: u32
+ -
+ name: okey
+ type: u32
+ -
+ name: local
+ type: binary
+ display-hint: ipv4
+ -
+ name: remote
+ type: binary
+ display-hint: ipv4
+ -
+ name: fwmark
+ type: u32
+ -
+ name: linkinfo-vti6-attrs
+ subset-of: linkinfo-vti-attrs
+ attributes:
+ -
+ name: link
+ -
+ name: ikey
+ -
+ name: okey
+ -
+ name: local
+ display-hint: ipv6
+ -
+ name: remote
+ display-hint: ipv6
+ -
+ name: fwmark
+ -
name: linkinfo-geneve-attrs
name-prefix: ifla-geneve-
attributes:
@@ -1942,6 +1984,42 @@ attribute-sets:
name: fwmark
type: u32
-
+ name: linkinfo-ip6tnl-attrs
+ subset-of: linkinfo-iptun-attrs
+ attributes:
+ -
+ name: link
+ -
+ name: local
+ display-hint: ipv6
+ -
+ name: remote
+ display-hint: ipv6
+ -
+ name: ttl
+ -
+ name: encap-limit
+ -
+ name: flowinfo
+ -
+ name: flags
+ # ip6tnl unlike ipip and sit has 32b flags
+ type: u32
+ -
+ name: proto
+ -
+ name: encap-type
+ -
+ name: encap-flags
+ -
+ name: encap-sport
+ -
+ name: encap-dport
+ -
+ name: collect-metadata
+ -
+ name: fwmark
+ -
name: linkinfo-tun-attrs
name-prefix: ifla-tun-
attributes:
@@ -2086,6 +2164,9 @@ attribute-sets:
-
name: mctp-net
type: u32
+ -
+ name: phys-binding
+ type: u8
-
name: stats-attrs
name-prefix: ifla-stats-
@@ -2166,6 +2247,12 @@ attribute-sets:
name: peer-scrub
type: u32
enum: netkit-scrub
+ -
+ name: headroom
+ type: u16
+ -
+ name: tailroom
+ type: u16
sub-messages:
-
@@ -2193,6 +2280,9 @@ sub-messages:
value: ipip
attribute-set: linkinfo-iptun-attrs
-
+ value: ip6tnl
+ attribute-set: linkinfo-ip6tnl-attrs
+ -
value: sit
attribute-set: linkinfo-iptun-attrs
-
@@ -2205,6 +2295,12 @@ sub-messages:
value: vrf
attribute-set: linkinfo-vrf-attrs
-
+ value: vti
+ attribute-set: linkinfo-vti-attrs
+ -
+ value: vti6
+ attribute-set: linkinfo-vti6-attrs
+ -
value: netkit
attribute-set: linkinfo-netkit-attrs
-
diff --git a/Documentation/netlink/specs/rt_route.yaml b/Documentation/netlink/specs/rt_route.yaml
index f4368be0caed..a674103e5bc4 100644
--- a/Documentation/netlink/specs/rt_route.yaml
+++ b/Documentation/netlink/specs/rt_route.yaml
@@ -177,6 +177,11 @@ attribute-sets:
-
name: rta-nh-id
type: u32
+ -
+ name: rta-flowlabel
+ type: u32
+ byte-order: big-endian
+ display-hint: hex
-
name: rta-metrics
attributes:
@@ -260,6 +265,7 @@ operations:
- rta-dport
- rta-mark
- rta-uid
+ - rta-flowlabel
reply:
value: 24
attributes: &all-route-attrs
@@ -299,6 +305,7 @@ operations:
- rta-sport
- rta-dport
- rta-nh-id
+ - rta-flowlabel
dump:
request:
value: 26
diff --git a/Documentation/netlink/specs/rt_rule.yaml b/Documentation/netlink/specs/rt_rule.yaml
index 03a8eef7952e..a9debac3058a 100644
--- a/Documentation/netlink/specs/rt_rule.yaml
+++ b/Documentation/netlink/specs/rt_rule.yaml
@@ -172,6 +172,16 @@ attribute-sets:
-
name: dscp
type: u8
+ -
+ name: flowlabel
+ type: u32
+ byte-order: big-endian
+ display-hint: hex
+ -
+ name: flowlabel-mask
+ type: u32
+ byte-order: big-endian
+ display-hint: hex
operations:
enum-model: directional
@@ -203,6 +213,8 @@ operations:
- sport-range
- dport-range
- dscp
+ - flowlabel
+ - flowlabel-mask
-
name: newrule-ntf
doc: Notify a rule creation
diff --git a/Documentation/networking/bareudp.rst b/Documentation/networking/bareudp.rst
index b9d04ee6dac1..621cb9575c8f 100644
--- a/Documentation/networking/bareudp.rst
+++ b/Documentation/networking/bareudp.rst
@@ -6,16 +6,17 @@ Bare UDP Tunnelling Module Documentation
There are various L3 encapsulation standards using UDP being discussed to
leverage the UDP based load balancing capability of different networks.
-MPLSoUDP (__ https://tools.ietf.org/html/rfc7510) is one among them.
+MPLSoUDP (https://tools.ietf.org/html/rfc7510) is one among them.
The Bareudp tunnel module provides a generic L3 encapsulation support for
tunnelling different L3 protocols like MPLS, IP, NSH etc. inside a UDP tunnel.
Special Handling
----------------
+
The bareudp device supports special handling for MPLS & IP as they can have
multiple ethertypes.
-MPLS procotcol can have ethertypes ETH_P_MPLS_UC (unicast) & ETH_P_MPLS_MC (multicast).
+The MPLS protocol can have ethertypes ETH_P_MPLS_UC (unicast) & ETH_P_MPLS_MC (multicast).
IP protocol can have ethertypes ETH_P_IP (v4) & ETH_P_IPV6 (v6).
This special handling can be enabled only for ethertypes ETH_P_IP & ETH_P_MPLS_UC
with a flag called multiproto mode.
@@ -52,7 +53,7 @@ be enabled explicitly with the "multiproto" flag.
3) Device Usage
The bareudp device could be used along with OVS or flower filter in TC.
-The OVS or TC flower layer must set the tunnel information in SKB dst field before
-sending packet buffer to the bareudp device for transmission. On reception the
-bareudp device extracts and stores the tunnel information in SKB dst field before
+The OVS or TC flower layer must set the tunnel information in the SKB dst field before
+sending the packet buffer to the bareudp device for transmission. On reception, the
+bareUDP device extracts and stores the tunnel information in the SKB dst field before
passing the packet buffer to the network stack.
diff --git a/Documentation/networking/bonding.rst b/Documentation/networking/bonding.rst
index 7c8d22d68682..a4c1291d2561 100644
--- a/Documentation/networking/bonding.rst
+++ b/Documentation/networking/bonding.rst
@@ -1963,7 +1963,7 @@ obtain its hardware address from the first slave, which might not
match the hardware address of the VLAN interfaces (which was
ultimately copied from an earlier slave).
-There are two methods to insure that the VLAN device operates
+There are two methods to ensure that the VLAN device operates
with the correct hardware address if all slaves are removed from a
bond interface:
@@ -2078,7 +2078,7 @@ as an unsolicited ARP reply (because ARP matches replies on an
interface basis), and is discarded. The MII monitor is not affected
by the state of the routing table.
-The solution here is simply to insure that slaves do not have
+The solution here is simply to ensure that slaves do not have
routes of their own, and if for some reason they must, those routes do
not supersede routes of their master. This should generally be the
case, but unusual configurations or errant manual or automatic static
@@ -2295,7 +2295,7 @@ active-backup:
the switches have an ISL and play together well. If the
network configuration is such that one switch is specifically
a backup switch (e.g., has lower capacity, higher cost, etc),
- then the primary option can be used to insure that the
+ then the primary option can be used to ensure that the
preferred link is always used when it is available.
broadcast:
@@ -2322,7 +2322,7 @@ monitor can provide a higher level of reliability in detecting end to
end connectivity failures (which may be caused by the failure of any
individual component to pass traffic for any reason). Additionally,
the ARP monitor should be configured with multiple targets (at least
-one for each switch in the network). This will insure that,
+one for each switch in the network). This will ensure that,
regardless of which switch is active, the ARP monitor has a suitable
target to query.
diff --git a/Documentation/networking/device_drivers/ethernet/intel/i40e.rst b/Documentation/networking/device_drivers/ethernet/intel/i40e.rst
index 4fbaa1a2d674..53d9d5829d69 100644
--- a/Documentation/networking/device_drivers/ethernet/intel/i40e.rst
+++ b/Documentation/networking/device_drivers/ethernet/intel/i40e.rst
@@ -299,6 +299,18 @@ Use ethtool to view and set link-down-on-close, as follows::
ethtool --show-priv-flags ethX
ethtool --set-priv-flags ethX link-down-on-close [on|off]
+Setting the mdd-auto-reset-vf Private Flag
+------------------------------------------
+
+When the mdd-auto-reset-vf private flag is set to "on", the problematic VF will
+be automatically reset if a malformed descriptor is detected. If the flag is
+set to "off", the problematic VF will be disabled.
+
+Use ethtool to view and set mdd-auto-reset-vf, as follows::
+
+ ethtool --show-priv-flags ethX
+ ethtool --set-priv-flags ethX mdd-auto-reset-vf [on|off]
+
Viewing Link Messages
---------------------
Link messages will not be displayed to the console if the distribution is
diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst
index b25926071ece..a7ba6368a4d5 100644
--- a/Documentation/networking/ethtool-netlink.rst
+++ b/Documentation/networking/ethtool-netlink.rst
@@ -237,6 +237,8 @@ Userspace to kernel:
``ETHTOOL_MSG_MM_SET`` set MAC merge layer parameters
``ETHTOOL_MSG_MODULE_FW_FLASH_ACT`` flash transceiver module firmware
``ETHTOOL_MSG_PHY_GET`` get Ethernet PHY information
+ ``ETHTOOL_MSG_TSCONFIG_GET`` get hw timestamping configuration
+ ``ETHTOOL_MSG_TSCONFIG_SET`` set hw timestamping configuration
===================================== =================================
Kernel to userspace:
@@ -286,6 +288,8 @@ Kernel to userspace:
``ETHTOOL_MSG_MODULE_FW_FLASH_NTF`` transceiver module flash updates
``ETHTOOL_MSG_PHY_GET_REPLY`` Ethernet PHY information
``ETHTOOL_MSG_PHY_NTF`` Ethernet PHY information change
+ ``ETHTOOL_MSG_TSCONFIG_GET_REPLY`` hw timestamping configuration
+ ``ETHTOOL_MSG_TSCONFIG_SET_REPLY`` new hw timestamping configuration
======================================== =================================
``GET`` requests are sent by userspace applications to retrieve device
@@ -1245,9 +1249,10 @@ Gets timestamping information like ``ETHTOOL_GET_TS_INFO`` ioctl request.
Request contents:
- ===================================== ====== ==========================
- ``ETHTOOL_A_TSINFO_HEADER`` nested request header
- ===================================== ====== ==========================
+ ======================================== ====== ============================
+ ``ETHTOOL_A_TSINFO_HEADER`` nested request header
+ ``ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER`` nested PTP hw clock provider
+ ======================================== ====== ============================
Kernel response contents:
@@ -2243,6 +2248,75 @@ Kernel response contents:
When ``ETHTOOL_A_PHY_UPSTREAM_TYPE`` is PHY_UPSTREAM_PHY, the PHY's parent is
another PHY.
+TSCONFIG_GET
+============
+
+Retrieves the information about the current hardware timestamping source and
+configuration.
+
+It is similar to the deprecated ``SIOCGHWTSTAMP`` ioctl request.
+
+Request contents:
+
+ ==================================== ====== ==========================
+ ``ETHTOOL_A_TSCONFIG_HEADER`` nested request header
+ ==================================== ====== ==========================
+
+Kernel response contents:
+
+ ======================================== ====== ============================
+ ``ETHTOOL_A_TSCONFIG_HEADER`` nested request header
+ ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` nested PTP hw clock provider
+ ``ETHTOOL_A_TSCONFIG_TX_TYPES`` bitset hwtstamp Tx type
+ ``ETHTOOL_A_TSCONFIG_RX_FILTERS`` bitset hwtstamp Rx filter
+ ``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` u32 hwtstamp flags
+ ======================================== ====== ============================
+
+When set the ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` attribute identifies the
+source of the hw timestamping provider. It is composed by
+``ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX`` attribute which describe the index of
+the PTP device and ``ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER`` which describe
+the qualifier of the timestamp.
+
+When set the ``ETHTOOL_A_TSCONFIG_TX_TYPES``, ``ETHTOOL_A_TSCONFIG_RX_FILTERS``
+and the ``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` attributes identify the Tx
+type, the Rx filter and the flags configured for the current hw timestamping
+provider. The attributes are propagated to the driver through the following
+structure:
+
+.. kernel-doc:: include/linux/net_tstamp.h
+ :identifiers: kernel_hwtstamp_config
+
+TSCONFIG_SET
+============
+
+Set the information about the current hardware timestamping source and
+configuration.
+
+It is similar to the deprecated ``SIOCSHWTSTAMP`` ioctl request.
+
+Request contents:
+
+ ======================================== ====== ============================
+ ``ETHTOOL_A_TSCONFIG_HEADER`` nested request header
+ ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` nested PTP hw clock provider
+ ``ETHTOOL_A_TSCONFIG_TX_TYPES`` bitset hwtstamp Tx type
+ ``ETHTOOL_A_TSCONFIG_RX_FILTERS`` bitset hwtstamp Rx filter
+ ``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` u32 hwtstamp flags
+ ======================================== ====== ============================
+
+Kernel response contents:
+
+ ======================================== ====== ============================
+ ``ETHTOOL_A_TSCONFIG_HEADER`` nested request header
+ ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` nested PTP hw clock provider
+ ``ETHTOOL_A_TSCONFIG_TX_TYPES`` bitset hwtstamp Tx type
+ ``ETHTOOL_A_TSCONFIG_RX_FILTERS`` bitset hwtstamp Rx filter
+ ``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` u32 hwtstamp flags
+ ======================================== ====== ============================
+
+For a description of each attribute, see ``TSCONFIG_GET``.
+
Request translation
===================
@@ -2351,4 +2425,6 @@ are netlink only.
n/a ``ETHTOOL_MSG_MM_SET``
n/a ``ETHTOOL_MSG_MODULE_FW_FLASH_ACT``
n/a ``ETHTOOL_MSG_PHY_GET``
+ ``SIOCGHWTSTAMP`` ``ETHTOOL_MSG_TSCONFIG_GET``
+ ``SIOCSHWTSTAMP`` ``ETHTOOL_MSG_TSCONFIG_SET``
=================================== =====================================
diff --git a/Documentation/networking/ieee802154.rst b/Documentation/networking/ieee802154.rst
index c652d383fe10..743c0a80e309 100644
--- a/Documentation/networking/ieee802154.rst
+++ b/Documentation/networking/ieee802154.rst
@@ -72,7 +72,8 @@ exports a management (e.g. MLME) and data API.
possibly with some kinds of acceleration like automatic CRC computation and
comparison, automagic ACK handling, address matching, etc.
-Those types of devices require different approach to be hooked into Linux kernel.
+Each type of device requires a different approach to be hooked into the Linux
+kernel.
HardMAC
-------
@@ -81,10 +82,10 @@ See the header include/net/ieee802154_netdev.h. You have to implement Linux
net_device, with .type = ARPHRD_IEEE802154. Data is exchanged with socket family
code via plain sk_buffs. On skb reception skb->cb must contain additional
info as described in the struct ieee802154_mac_cb. During packet transmission
-the skb->cb is used to provide additional data to device's header_ops->create
-function. Be aware that this data can be overridden later (when socket code
-submits skb to qdisc), so if you need something from that cb later, you should
-store info in the skb->data on your own.
+the skb->cb is used to provide additional data to the device's
+header_ops->create function. Be aware that this data can be overridden later
+(when socket code submits skb to qdisc), so if you need something from that cb
+later, you should store info in the skb->data on your own.
To hook the MLME interface you have to populate the ml_priv field of your
net_device with a pointer to struct ieee802154_mlme_ops instance. The fields
@@ -94,8 +95,9 @@ All other fields are required.
SoftMAC
-------
-The MAC is the middle layer in the IEEE 802.15.4 Linux stack. This moment it
-provides interface for drivers registration and management of slave interfaces.
+The MAC is the middle layer in the IEEE 802.15.4 Linux stack. At the moment, it
+provides an interface for driver registration and management of slave
+interfaces.
NOTE: Currently the only monitor device type is supported - it's IEEE 802.15.4
stack interface for network sniffers (e.g. WireShark).
diff --git a/Documentation/networking/index.rst b/Documentation/networking/index.rst
index 46c178e564b3..058193ed2eeb 100644
--- a/Documentation/networking/index.rst
+++ b/Documentation/networking/index.rst
@@ -86,6 +86,7 @@ Contents:
netdevices
netfilter-sysctl
netif-msg
+ netmem
nexthop-group-resilient
nf_conntrack-sysctl
nf_flowtable
diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst
index eacf8983e230..363b4950d542 100644
--- a/Documentation/networking/ip-sysctl.rst
+++ b/Documentation/networking/ip-sysctl.rst
@@ -1000,6 +1000,20 @@ tcp_tw_reuse - INTEGER
Default: 2
+tcp_tw_reuse_delay - UNSIGNED INTEGER
+ The delay in milliseconds before a TIME-WAIT socket can be reused by a
+ new connection, if TIME-WAIT socket reuse is enabled. The actual reuse
+ threshold is within [N, N+1] range, where N is the requested delay in
+ milliseconds, to ensure the delay interval is never shorter than the
+ configured value.
+
+ This setting contains an assumption about the other TCP timestamp clock
+ tick interval. It should not be set to a value lower than the peer's
+ clock tick for PAWS (Protection Against Wrapped Sequence numbers)
+ mechanism work correctly for the reused connection.
+
+ Default: 1000 (milliseconds)
+
tcp_window_scaling - BOOLEAN
Enable window scaling as defined in RFC1323.
@@ -2170,6 +2184,12 @@ nexthop_compat_mode - BOOLEAN
understands the new API, this sysctl can be disabled to achieve full
performance benefits of the new API by disabling the nexthop expansion
and extraneous notifications.
+
+ Note that as a backward-compatible mode, dumping of modern features
+ might be incomplete or wrong. For example, resilient groups will not be
+ shown as such, but rather as just a list of next hops. Also weights that
+ do not fit into 8 bits will show incorrectly.
+
Default: true (backward compat mode)
fib_notify_on_flag_change - INTEGER
diff --git a/Documentation/networking/multi-pf-netdev.rst b/Documentation/networking/multi-pf-netdev.rst
index 2cd25d81aaa7..2f5a5bb3ca9a 100644
--- a/Documentation/networking/multi-pf-netdev.rst
+++ b/Documentation/networking/multi-pf-netdev.rst
@@ -89,7 +89,7 @@ Observability
=============
The relation between PF, irq, napi, and queue can be observed via netlink spec::
- $ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump queue-get --json='{"ifindex": 13}'
+ $ ./tools/net/ynl/pyynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump queue-get --json='{"ifindex": 13}'
[{'id': 0, 'ifindex': 13, 'napi-id': 539, 'type': 'rx'},
{'id': 1, 'ifindex': 13, 'napi-id': 540, 'type': 'rx'},
{'id': 2, 'ifindex': 13, 'napi-id': 541, 'type': 'rx'},
@@ -101,7 +101,7 @@ The relation between PF, irq, napi, and queue can be observed via netlink spec::
{'id': 3, 'ifindex': 13, 'napi-id': 542, 'type': 'tx'},
{'id': 4, 'ifindex': 13, 'napi-id': 543, 'type': 'tx'}]
- $ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump napi-get --json='{"ifindex": 13}'
+ $ ./tools/net/ynl/pyynl/cli.py --spec Documentation/netlink/specs/netdev.yaml --dump napi-get --json='{"ifindex": 13}'
[{'id': 543, 'ifindex': 13, 'irq': 42},
{'id': 542, 'ifindex': 13, 'irq': 41},
{'id': 541, 'ifindex': 13, 'irq': 40},
diff --git a/Documentation/networking/napi.rst b/Documentation/networking/napi.rst
index 02720dd71a76..6083210ab2a4 100644
--- a/Documentation/networking/napi.rst
+++ b/Documentation/networking/napi.rst
@@ -199,13 +199,13 @@ parameters mentioned above use hyphens instead of underscores:
Per-NAPI configuration can be done programmatically in a user application
or by using a script included in the kernel source tree:
-``tools/net/ynl/cli.py``.
+``tools/net/ynl/pyynl/cli.py``.
For example, using the script:
.. code-block:: bash
- $ kernel-source/tools/net/ynl/cli.py \
+ $ kernel-source/tools/net/ynl/pyynl/cli.py \
--spec Documentation/netlink/specs/netdev.yaml \
--do napi-set \
--json='{"id": 345,
diff --git a/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst b/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst
index 629da6dc6d74..de0263302f16 100644
--- a/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst
+++ b/Documentation/networking/net_cachelines/netns_ipv4_sysctl.rst
@@ -79,6 +79,7 @@ u8 sysctl_tcp_retries1
u8 sysctl_tcp_retries2
u8 sysctl_tcp_orphan_retries
u8 sysctl_tcp_tw_reuse timewait_sock_ops
+unsigned_int sysctl_tcp_tw_reuse_delay timewait_sock_ops
int sysctl_tcp_fin_timeout TCP_LAST_ACK/tcp_rcv_state_process
unsigned_int sysctl_tcp_notsent_lowat read_mostly tcp_notsent_lowat/tcp_stream_memory_free
u8 sysctl_tcp_sack tcp_syn_options
diff --git a/Documentation/networking/netdevices.rst b/Documentation/networking/netdevices.rst
index 857c9784f87e..1d37038e9fbe 100644
--- a/Documentation/networking/netdevices.rst
+++ b/Documentation/networking/netdevices.rst
@@ -297,3 +297,13 @@ napi->poll:
Context:
softirq
will be called with interrupts disabled by netconsole.
+
+NETDEV_INTERNAL symbol namespace
+================================
+
+Symbols exported as NETDEV_INTERNAL can only be used in networking
+core and drivers which exclusively flow via the main networking list and trees.
+Note that the inverse is not true, most symbols outside of NETDEV_INTERNAL
+are not expected to be used by random code outside netdev either.
+Symbols may lack the designation because they predate the namespaces,
+or simply due to an oversight.
diff --git a/Documentation/networking/netlink_spec/readme.txt b/Documentation/networking/netlink_spec/readme.txt
index 6763f99d216c..030b44aca4e6 100644
--- a/Documentation/networking/netlink_spec/readme.txt
+++ b/Documentation/networking/netlink_spec/readme.txt
@@ -1,4 +1,4 @@
SPDX-License-Identifier: GPL-2.0
This file is populated during the build of the documentation (htmldocs) by the
-tools/net/ynl/ynl-gen-rst.py script.
+tools/net/ynl/pyynl/ynl_gen_rst.py script.
diff --git a/Documentation/networking/netmem.rst b/Documentation/networking/netmem.rst
new file mode 100644
index 000000000000..7de21ddb5412
--- /dev/null
+++ b/Documentation/networking/netmem.rst
@@ -0,0 +1,79 @@
+.. SPDX-License-Identifier: GPL-2.0
+
+==================================
+Netmem Support for Network Drivers
+==================================
+
+This document outlines the requirements for network drivers to support netmem,
+an abstract memory type that enables features like device memory TCP. By
+supporting netmem, drivers can work with various underlying memory types
+with little to no modification.
+
+Benefits of Netmem :
+
+* Flexibility: Netmem can be backed by different memory types (e.g., struct
+ page, DMA-buf), allowing drivers to support various use cases such as device
+ memory TCP.
+* Future-proof: Drivers with netmem support are ready for upcoming
+ features that rely on it.
+* Simplified Development: Drivers interact with a consistent API,
+ regardless of the underlying memory implementation.
+
+Driver Requirements
+===================
+
+1. The driver must support page_pool.
+
+2. The driver must support the tcp-data-split ethtool option.
+
+3. The driver must use the page_pool netmem APIs for payload memory. The netmem
+ APIs currently 1-to-1 correspond with page APIs. Conversion to netmem should
+ be achievable by switching the page APIs to netmem APIs and tracking memory
+ via netmem_refs in the driver rather than struct page * :
+
+ - page_pool_alloc -> page_pool_alloc_netmem
+ - page_pool_get_dma_addr -> page_pool_get_dma_addr_netmem
+ - page_pool_put_page -> page_pool_put_netmem
+
+ Not all page APIs have netmem equivalents at the moment. If your driver
+ relies on a missing netmem API, feel free to add and propose to netdev@, or
+ reach out to the maintainers and/or almasrymina@google.com for help adding
+ the netmem API.
+
+4. The driver must use the following PP_FLAGS:
+
+ - PP_FLAG_DMA_MAP: netmem is not dma-mappable by the driver. The driver
+ must delegate the dma mapping to the page_pool, which knows when
+ dma-mapping is (or is not) appropriate.
+ - PP_FLAG_DMA_SYNC_DEV: netmem dma addr is not necessarily dma-syncable
+ by the driver. The driver must delegate the dma syncing to the page_pool,
+ which knows when dma-syncing is (or is not) appropriate.
+ - PP_FLAG_ALLOW_UNREADABLE_NETMEM. The driver must specify this flag iff
+ tcp-data-split is enabled.
+
+5. The driver must not assume the netmem is readable and/or backed by pages.
+ The netmem returned by the page_pool may be unreadable, in which case
+ netmem_address() will return NULL. The driver must correctly handle
+ unreadable netmem, i.e. don't attempt to handle its contents when
+ netmem_address() is NULL.
+
+ Ideally, drivers should not have to check the underlying netmem type via
+ helpers like netmem_is_net_iov() or convert the netmem to any of its
+ underlying types via netmem_to_page() or netmem_to_net_iov(). In most cases,
+ netmem or page_pool helpers that abstract this complexity are provided
+ (and more can be added).
+
+6. The driver must use page_pool_dma_sync_netmem_for_cpu() in lieu of
+ dma_sync_single_range_for_cpu(). For some memory providers, dma_syncing for
+ CPU will be done by the page_pool, for others (particularly dmabuf memory
+ provider), dma syncing for CPU is the responsibility of the userspace using
+ dmabuf APIs. The driver must delegate the entire dma-syncing operation to
+ the page_pool which will do it correctly.
+
+7. Avoid implementing driver-specific recycling on top of the page_pool. Drivers
+ cannot hold onto a struct page to do their own recycling as the netmem may
+ not be backed by a struct page. However, you may hold onto a page_pool
+ reference with page_pool_fragment_netmem() or page_pool_ref_netmem() for
+ that purpose, but be mindful that some netmem types might have longer
+ circulation times, such as when userspace holds a reference in zerocopy
+ scenarios.
diff --git a/Documentation/networking/timestamping.rst b/Documentation/networking/timestamping.rst
index b37bfbfc7d79..61ef9da10e28 100644
--- a/Documentation/networking/timestamping.rst
+++ b/Documentation/networking/timestamping.rst
@@ -525,8 +525,8 @@ implicitly defined. ts[0] holds a software timestamp if set, ts[1]
is again deprecated and ts[2] holds a hardware timestamp if set.
-3. Hardware Timestamping configuration: SIOCSHWTSTAMP and SIOCGHWTSTAMP
-=======================================================================
+3. Hardware Timestamping configuration: ETHTOOL_MSG_TSCONFIG_SET/GET
+====================================================================
Hardware time stamping must also be initialized for each device driver
that is expected to do hardware time stamping. The parameter is defined in
@@ -539,12 +539,14 @@ include/uapi/linux/net_tstamp.h as::
};
Desired behavior is passed into the kernel and to a specific device by
-calling ioctl(SIOCSHWTSTAMP) with a pointer to a struct ifreq whose
-ifr_data points to a struct hwtstamp_config. The tx_type and
-rx_filter are hints to the driver what it is expected to do. If
-the requested fine-grained filtering for incoming packets is not
-supported, the driver may time stamp more than just the requested types
-of packets.
+calling the tsconfig netlink socket ``ETHTOOL_MSG_TSCONFIG_SET``.
+The ``ETHTOOL_A_TSCONFIG_TX_TYPES``, ``ETHTOOL_A_TSCONFIG_RX_FILTERS`` and
+``ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS`` netlink attributes are then used to set
+the struct hwtstamp_config accordingly.
+
+The ``ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER`` netlink nested attribute is used
+to select the source of the hardware time stamping. It is composed of an index
+for the device source and a qualifier for the type of time stamping.
Drivers are free to use a more permissive configuration than the requested
configuration. It is expected that drivers should only implement directly the
@@ -563,9 +565,16 @@ Only a processes with admin rights may change the configuration. User
space is responsible to ensure that multiple processes don't interfere
with each other and that the settings are reset.
-Any process can read the actual configuration by passing this
-structure to ioctl(SIOCGHWTSTAMP) in the same way. However, this has
-not been implemented in all drivers.
+Any process can read the actual configuration by requesting tsconfig netlink
+socket ``ETHTOOL_MSG_TSCONFIG_GET``.
+
+The legacy configuration is the use of the ioctl(SIOCSHWTSTAMP) with a pointer
+to a struct ifreq whose ifr_data points to a struct hwtstamp_config.
+The tx_type and rx_filter are hints to the driver what it is expected to do.
+If the requested fine-grained filtering for incoming packets is not
+supported, the driver may time stamp more than just the requested types
+of packets. ioctl(SIOCGHWTSTAMP) is used in the same way as the
+ioctl(SIOCSHWTSTAMP). However, this has not been implemented in all drivers.
::
@@ -610,9 +619,10 @@ not been implemented in all drivers.
--------------------------------------------------------
A driver which supports hardware time stamping must support the
-SIOCSHWTSTAMP ioctl and update the supplied struct hwtstamp_config with
-the actual values as described in the section on SIOCSHWTSTAMP. It
-should also support SIOCGHWTSTAMP.
+ndo_hwtstamp_set NDO or the legacy SIOCSHWTSTAMP ioctl and update the
+supplied struct hwtstamp_config with the actual values as described in
+the section on SIOCSHWTSTAMP. It should also support ndo_hwtstamp_get or
+the legacy SIOCGHWTSTAMP.
Time stamps for received packets must be stored in the skb. To get a pointer
to the shared time stamp structure of the skb call skb_hwtstamps(). Then
diff --git a/Documentation/networking/tls.rst b/Documentation/networking/tls.rst
index 658ed3a71e1b..c7904a1bc167 100644
--- a/Documentation/networking/tls.rst
+++ b/Documentation/networking/tls.rst
@@ -200,6 +200,32 @@ received without a cmsg buffer set.
recv will never return data from mixed types of TLS records.
+TLS 1.3 Key Updates
+-------------------
+
+In TLS 1.3, KeyUpdate handshake messages signal that the sender is
+updating its TX key. Any message sent after a KeyUpdate will be
+encrypted using the new key. The userspace library can pass the new
+key to the kernel using the TLS_TX and TLS_RX socket options, as for
+the initial keys. TLS version and cipher cannot be changed.
+
+To prevent attempting to decrypt incoming records using the wrong key,
+decryption will be paused when a KeyUpdate message is received by the
+kernel, until the new key has been provided using the TLS_RX socket
+option. Any read occurring after the KeyUpdate has been read and
+before the new key is provided will fail with EKEYEXPIRED. poll() will
+not report any read events from the socket until the new key is
+provided. There is no pausing on the transmit side.
+
+Userspace should make sure that the crypto_info provided has been set
+properly. In particular, the kernel will not check for key/nonce
+reuse.
+
+The number of successful and failed key updates is tracked in the
+``TlsTxRekeyOk``, ``TlsRxRekeyOk``, ``TlsTxRekeyError``,
+``TlsRxRekeyError`` statistics. The ``TlsRxRekeyReceived`` statistic
+counts KeyUpdate handshake messages that have been received.
+
Integrating in to userspace TLS library
---------------------------------------
@@ -286,3 +312,13 @@ TLS implementation exposes the following per-namespace statistics
- ``TlsRxNoPadViolation`` -
number of data RX records which had to be re-decrypted due to
``TLS_RX_EXPECT_NO_PAD`` mis-prediction.
+
+- ``TlsTxRekeyOk``, ``TlsRxRekeyOk`` -
+ number of successful rekeys on existing sessions for TX and RX
+
+- ``TlsTxRekeyError``, ``TlsRxRekeyError`` -
+ number of failed rekeys on existing sessions for TX and RX
+
+- ``TlsRxRekeyReceived`` -
+ number of received KeyUpdate handshake messages, requiring userspace
+ to provide a new RX key
diff --git a/Documentation/power/runtime_pm.rst b/Documentation/power/runtime_pm.rst
index 53d1996460ab..12f429359a82 100644
--- a/Documentation/power/runtime_pm.rst
+++ b/Documentation/power/runtime_pm.rst
@@ -347,7 +347,9 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
`int pm_runtime_resume_and_get(struct device *dev);`
- run pm_runtime_resume(dev) and if successful, increment the device's
- usage counter; return the result of pm_runtime_resume
+ usage counter; returns 0 on success (whether or not the device's
+ runtime PM status was already 'active') or the error code from
+ pm_runtime_resume() on failure.
`int pm_request_idle(struct device *dev);`
- submit a request to execute the subsystem-level idle callback for the
diff --git a/Documentation/sound/hd-audio/notes.rst b/Documentation/sound/hd-audio/notes.rst
index e199131bf5ab..f81e94d8f145 100644
--- a/Documentation/sound/hd-audio/notes.rst
+++ b/Documentation/sound/hd-audio/notes.rst
@@ -42,7 +42,7 @@ If you are interested in the deep debugging of HD-audio, read the
HD-audio specification at first. The specification is found on
Intel's web page, for example:
-* https://www.intel.com/standards/hdaudio/
+* https://www.intel.com/content/www/us/en/standards/high-definition-audio-specification.html
HD-Audio Controller
diff --git a/Documentation/sound/soc/dapm.rst b/Documentation/sound/soc/dapm.rst
index 14c4dc026e6b..73a42d5a9f30 100644
--- a/Documentation/sound/soc/dapm.rst
+++ b/Documentation/sound/soc/dapm.rst
@@ -35,6 +35,9 @@ The graph for the STM32MP1-DK1 sound card is shown in picture:
:alt: Example DAPM graph
:align: center
+You can also generate compatible graph for your sound card using
+`tools/sound/dapm-graph` utility.
+
DAPM power domains
==================
diff --git a/Documentation/trace/ftrace.rst b/Documentation/trace/ftrace.rst
index 74d5bd801b1a..272464bb7c60 100644
--- a/Documentation/trace/ftrace.rst
+++ b/Documentation/trace/ftrace.rst
@@ -1033,9 +1033,13 @@ explains which is which.
irqs-off: 'd' interrupts are disabled. '.' otherwise.
need-resched:
+ - 'B' all, TIF_NEED_RESCHED, PREEMPT_NEED_RESCHED and TIF_RESCHED_LAZY is set,
- 'N' both TIF_NEED_RESCHED and PREEMPT_NEED_RESCHED is set,
- 'n' only TIF_NEED_RESCHED is set,
- 'p' only PREEMPT_NEED_RESCHED is set,
+ - 'L' both PREEMPT_NEED_RESCHED and TIF_RESCHED_LAZY is set,
+ - 'b' both TIF_NEED_RESCHED and TIF_RESCHED_LAZY is set,
+ - 'l' only TIF_RESCHED_LAZY is set
- '.' otherwise.
hardirq/softirq:
diff --git a/Documentation/translations/it_IT/core-api/symbol-namespaces.rst b/Documentation/translations/it_IT/core-api/symbol-namespaces.rst
index 17abc25ee4c1..6ee713988531 100644
--- a/Documentation/translations/it_IT/core-api/symbol-namespaces.rst
+++ b/Documentation/translations/it_IT/core-api/symbol-namespaces.rst
@@ -43,7 +43,7 @@ Tenete presente che per via dell'espansione delle macro questo argomento deve
essere un simbolo di preprocessore. Per esempio per esportare il
simbolo ``usb_stor_suspend`` nello spazio dei nomi ``USB_STORAGE`` usate::
- EXPORT_SYMBOL_NS(usb_stor_suspend, USB_STORAGE);
+ EXPORT_SYMBOL_NS(usb_stor_suspend, "USB_STORAGE");
Di conseguenza, nella tabella dei simboli del kernel ci sarà una voce
rappresentata dalla struttura ``kernel_symbol`` che avrà il campo
@@ -69,7 +69,7 @@ Per esempio per esportare tutti i simboli definiti in usb-common nello spazio
dei nomi USB_COMMON, si può aggiungere la seguente linea in
drivers/usb/common/Makefile::
- ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON
+ ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE='"USB_COMMON"'
Questo cambierà tutte le macro EXPORT_SYMBOL() ed EXPORT_SYMBOL_GPL(). Invece,
un simbolo esportato con EXPORT_SYMBOL_NS() non verrà cambiato e il simbolo
@@ -79,7 +79,7 @@ Una seconda possibilità è quella di definire il simbolo di preprocessore
direttamente nei file da compilare. L'esempio precedente diventerebbe::
#undef DEFAULT_SYMBOL_NAMESPACE
- #define DEFAULT_SYMBOL_NAMESPACE USB_COMMON
+ #define DEFAULT_SYMBOL_NAMESPACE "USB_COMMON"
Questo va messo prima di un qualsiasi uso di EXPORT_SYMBOL.
@@ -94,7 +94,7 @@ dei nomi che contiene i simboli desiderati. Per esempio un modulo che
usa il simbolo usb_stor_suspend deve importare lo spazio dei nomi
USB_STORAGE usando la seguente dichiarazione::
- MODULE_IMPORT_NS(USB_STORAGE);
+ MODULE_IMPORT_NS("USB_STORAGE");
Questo creerà un'etichetta ``modinfo`` per ogni spazio dei nomi
importato. Un risvolto di questo fatto è che gli spazi dei
diff --git a/Documentation/translations/zh_CN/core-api/symbol-namespaces.rst b/Documentation/translations/zh_CN/core-api/symbol-namespaces.rst
index bb16f0611046..b1bec219912d 100644
--- a/Documentation/translations/zh_CN/core-api/symbol-namespaces.rst
+++ b/Documentation/translations/zh_CN/core-api/symbol-namespaces.rst
@@ -48,7 +48,7 @@
要是一个预处理器符号。例如,要把符号 ``usb_stor_suspend`` 导出到命名空间 ``USB_STORAGE``,
请使用::
- EXPORT_SYMBOL_NS(usb_stor_suspend, USB_STORAGE);
+ EXPORT_SYMBOL_NS(usb_stor_suspend, "USB_STORAGE");
相应的 ksymtab 条目结构体 ``kernel_symbol`` 将有相应的成员 ``命名空间`` 集。
导出时未指明命名空间的符号将指向 ``NULL`` 。如果没有定义命名空间,则默认没有。
@@ -66,7 +66,7 @@
子系统的 ``Makefile`` 中定义默认命名空间。例如,如果要将usb-common中定义的所有符号导
出到USB_COMMON命名空间,可以在drivers/usb/common/Makefile中添加这样一行::
- ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_COMMON
+ ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE='"USB_COMMON"'
这将影响所有 EXPORT_SYMBOL() 和 EXPORT_SYMBOL_GPL() 语句。当这个定义存在时,
用EXPORT_SYMBOL_NS()导出的符号仍然会被导出到作为命名空间参数传递的命名空间中,
@@ -76,7 +76,7 @@
成::
#undef DEFAULT_SYMBOL_NAMESPACE
- #define DEFAULT_SYMBOL_NAMESPACE USB_COMMON
+ #define DEFAULT_SYMBOL_NAMESPACE "USB_COMMON"
应置于相关编译单元中任何 EXPORT_SYMBOL 宏之前
@@ -88,7 +88,7 @@
表示它所使用的命名空间的符号。例如,一个使用usb_stor_suspend符号的
模块,需要使用如下语句导入命名空间USB_STORAGE::
- MODULE_IMPORT_NS(USB_STORAGE);
+ MODULE_IMPORT_NS("USB_STORAGE");
这将在模块中为每个导入的命名空间创建一个 ``modinfo`` 标签。这也顺带
使得可以用modinfo检查模块已导入的命名空间::
diff --git a/Documentation/userspace-api/netlink/c-code-gen.rst b/Documentation/userspace-api/netlink/c-code-gen.rst
index 89de42c13350..46415e6d646d 100644
--- a/Documentation/userspace-api/netlink/c-code-gen.rst
+++ b/Documentation/userspace-api/netlink/c-code-gen.rst
@@ -56,7 +56,9 @@ If ``name-prefix`` is specified it replaces the ``$family-$enum``
portion of the entry name.
Boolean ``render-max`` controls creation of the max values
-(which are enabled by default for attribute enums).
+(which are enabled by default for attribute enums). These max
+values are named ``__$pfx-MAX`` and ``$pfx-MAX``. The name
+of the first value can be overridden via ``enum-cnt-name`` property.
Attributes
==========
diff --git a/Documentation/userspace-api/netlink/intro-specs.rst b/Documentation/userspace-api/netlink/intro-specs.rst
index bada89699455..a4435ae4628d 100644
--- a/Documentation/userspace-api/netlink/intro-specs.rst
+++ b/Documentation/userspace-api/netlink/intro-specs.rst
@@ -15,7 +15,7 @@ developing Netlink related code. The tool is implemented in Python
and can use a YAML specification to issue Netlink requests
to the kernel. Only Generic Netlink is supported.
-The tool is located at ``tools/net/ynl/cli.py``. It accepts
+The tool is located at ``tools/net/ynl/pyynl/cli.py``. It accepts
a handul of arguments, the most important ones are:
- ``--spec`` - point to the spec file
@@ -27,7 +27,7 @@ YAML specs can be found under ``Documentation/netlink/specs/``.
Example use::
- $ ./tools/net/ynl/cli.py --spec Documentation/netlink/specs/ethtool.yaml \
+ $ ./tools/net/ynl/pyynl/cli.py --spec Documentation/netlink/specs/ethtool.yaml \
--do rings-get \
--json '{"header":{"dev-index": 18}}'
{'header': {'dev-index': 18, 'dev-name': 'eni1np1'},
@@ -75,7 +75,7 @@ the two marker lines like above to a file, add that file to git,
and run the regeneration tool. Grep the tree for ``YNL-GEN``
to see other examples.
-The code generation itself is performed by ``tools/net/ynl/ynl-gen-c.py``
+The code generation itself is performed by ``tools/net/ynl/pyynl/ynl_gen_c.py``
but it takes a few arguments so calling it directly for each file
quickly becomes tedious.
@@ -84,7 +84,7 @@ YNL lib
``tools/net/ynl/lib/`` contains an implementation of a C library
(based on libmnl) which integrates with code generated by
-``tools/net/ynl/ynl-gen-c.py`` to create easy to use netlink wrappers.
+``tools/net/ynl/pyynl/ynl_gen_c.py`` to create easy to use netlink wrappers.
YNL basics
----------
diff --git a/Documentation/watchdog/watchdog-parameters.rst b/Documentation/watchdog/watchdog-parameters.rst
index 29153eed6689..0a0119edfa82 100644
--- a/Documentation/watchdog/watchdog-parameters.rst
+++ b/Documentation/watchdog/watchdog-parameters.rst
@@ -120,16 +120,6 @@ coh901327_wdt:
-------------------------------------------------
-cpu5wdt:
- port:
- base address of watchdog card, default is 0x91
- verbose:
- be verbose, default is 0 (no)
- ticks:
- count down ticks, default is 10000
-
--------------------------------------------------
-
cpwd:
wd0_timeout:
Default watchdog0 timeout in 1/10secs
diff --git a/MAINTAINERS b/MAINTAINERS
index 0456a33ef657..3f3e289b391c 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -949,7 +949,6 @@ AMAZON ETHERNET DRIVERS
M: Shay Agroskin <shayagr@amazon.com>
M: Arthur Kiyanovski <akiyano@amazon.com>
R: David Arinzon <darinzon@amazon.com>
-R: Noam Dagan <ndagan@amazon.com>
R: Saeed Bishara <saeedb@amazon.com>
L: netdev@vger.kernel.org
S: Supported
@@ -1218,6 +1217,14 @@ F: Documentation/devicetree/bindings/perf/amlogic,g12-ddr-pmu.yaml
F: drivers/perf/amlogic/
F: include/soc/amlogic/
+AMLOGIC RTC DRIVER
+M: Yiting Deng <yiting.deng@amlogic.com>
+M: Xianwei Zhao <xianwei.zhao@amlogic.com>
+L: linux-amlogic@lists.infradead.org
+S: Maintained
+F: Documentation/devicetree/bindings/rtc/amlogic,a4-rtc.yaml
+F: drivers/rtc/rtc-amlogic-a4.c
+
AMPHENOL CHIPCAP 2 HUMIDITY-TEMPERATURE IIO DRIVER
M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
L: linux-hwmon@vger.kernel.org
@@ -1271,7 +1278,6 @@ M: Cosmin Tanislav <cosmin.tanislav@analog.com>
L: linux-iio@vger.kernel.org
S: Supported
W: https://ez.analog.com/linux-software-drivers
-F: Documentation/ABI/testing/sysfs-bus-iio-adc-ad4130
F: Documentation/devicetree/bindings/iio/adc/adi,ad4130.yaml
F: drivers/iio/adc/ad4130.c
@@ -1336,6 +1342,17 @@ F: Documentation/devicetree/bindings/iio/addac/adi,ad74413r.yaml
F: drivers/iio/addac/ad74413r.c
F: include/dt-bindings/iio/addac/adi,ad74413r.h
+ANALOG DEVICES INC AD7625 DRIVER
+M: Michael Hennerich <Michael.Hennerich@analog.com>
+M: Nuno Sá <nuno.sa@analog.com>
+R: Trevor Gamblin <tgamblin@baylibre.com>
+S: Supported
+W: https://ez.analog.com/linux-software-drivers
+W: http://analogdevicesinc.github.io/hdl/projects/pulsar_lvds/index.html
+F: Documentation/devicetree/bindings/iio/adc/adi,ad7625.yaml
+F: Documentation/iio/ad7625.rst
+F: drivers/iio/adc/ad7625.c
+
ANALOG DEVICES INC AD7768-1 DRIVER
M: Michael Hennerich <Michael.Hennerich@analog.com>
L: linux-iio@vger.kernel.org
@@ -1363,6 +1380,14 @@ F: Documentation/ABI/testing/debugfs-iio-ad9467
F: Documentation/devicetree/bindings/iio/adc/adi,ad9467.yaml
F: drivers/iio/adc/ad9467.c
+ANALOG DEVICES INC AD8460 DRIVER
+M: Mariel Tinaco <Mariel.Tinaco@analog.com>
+L: linux-iio@vger.kernel.org
+S: Supported
+W: https://ez.analog.com/linux-software-drivers
+F: Documentation/devicetree/bindings/iio/dac/adi,ad8460.yaml
+F: drivers/iio/dac/ad8460.c
+
ANALOG DEVICES INC AD9739a DRIVER
M: Nuno Sa <nuno.sa@analog.com>
M: Dragos Bogdan <dragos.bogdan@analog.com>
@@ -1563,6 +1588,7 @@ F: Documentation/ABI/testing/sysfs-bus-iio-frequency-adf4350
F: Documentation/devicetree/bindings/iio/*/adi,*
F: Documentation/devicetree/bindings/iio/adc/lltc,ltc2496.yaml
F: Documentation/devicetree/bindings/iio/adc/lltc,ltc2497.yaml
+F: Documentation/iio/ad7606.rst
F: drivers/iio/*/ad*
F: drivers/iio/adc/ltc249*
F: drivers/iio/amplifiers/hmc425a.c
@@ -1770,7 +1796,6 @@ F: include/uapi/linux/if_arcnet.h
ARM AND ARM64 SoC SUB-ARCHITECTURES (COMMON PARTS)
M: Arnd Bergmann <arnd@arndb.de>
-M: Olof Johansson <olof@lixom.net>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: soc@lists.linux.dev
S: Maintained
@@ -2664,7 +2689,6 @@ N: at91
N: atmel
ARM/Microchip Sparx5 SoC support
-M: Lars Povlsen <lars.povlsen@microchip.com>
M: Steen Hegelund <Steen.Hegelund@microchip.com>
M: Daniel Machon <daniel.machon@microchip.com>
M: UNGLinuxDriver@microchip.com
@@ -2809,6 +2833,13 @@ S: Maintained
F: arch/arm64/boot/dts/freescale/s32g*.dts*
F: drivers/pinctrl/nxp/
+ARM/NXP S32G/S32R DWMAC ETHERNET DRIVER
+M: Jan Petrous <jan.petrous@oss.nxp.com>
+L: NXP S32 Linux Team <s32@nxp.com>
+S: Maintained
+F: Documentation/devicetree/bindings/net/nxp,s32-dwmac.yaml
+F: drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
+
ARM/Orion SoC/Technologic Systems TS-78xx platform support
M: Alexander Clouter <alex@digriz.org.uk>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
@@ -2924,6 +2955,7 @@ Q: http://patchwork.kernel.org/project/linux-renesas-soc/list/
C: irc://irc.libera.chat/renesas-soc
T: git git://git.kernel.org/pub/scm/linux/kernel/git/geert/renesas-devel.git next
F: Documentation/devicetree/bindings/hwinfo/renesas,prr.yaml
+F: Documentation/devicetree/bindings/nvmem/renesas,*
F: Documentation/devicetree/bindings/soc/renesas/
F: arch/arm/boot/dts/renesas/
F: arch/arm/configs/shmobile_defconfig
@@ -2931,6 +2963,7 @@ F: arch/arm/include/debug/renesas-scif.S
F: arch/arm/mach-shmobile/
F: arch/arm64/boot/dts/renesas/
F: arch/riscv/boot/dts/renesas/
+F: drivers/nvmem/rcar-efuse.c
F: drivers/pmdomain/renesas/
F: drivers/soc/renesas/
F: include/linux/soc/renesas/
@@ -3347,6 +3380,8 @@ S: Maintained
T: git git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux.git
F: Documentation/arch/arm64/
F: arch/arm64/
+F: drivers/virt/coco/arm-cca-guest/
+F: drivers/virt/coco/pkvm-guest/
F: tools/testing/selftests/arm64/
X: arch/arm64/boot/dts/
@@ -3577,6 +3612,7 @@ F: drivers/phy/qualcomm/phy-ath79-usb.c
ATHEROS ATH GENERIC UTILITIES
M: Kalle Valo <kvalo@kernel.org>
+M: Jeff Johnson <jjohnson@kernel.org>
L: linux-wireless@vger.kernel.org
S: Supported
F: drivers/net/wireless/ath/*
@@ -3686,6 +3722,13 @@ F: kernel/audit*
F: lib/*audit.c
K: \baudit_[a-z_0-9]\+\b
+AUTOFDO BUILD
+M: Rong Xu <xur@google.com>
+M: Han Shen <shenhan@google.com>
+S: Supported
+F: Documentation/dev-tools/autofdo.rst
+F: scripts/Makefile.autofdo
+
AUXILIARY BUS DRIVER
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
R: Dave Ertman <david.m.ertman@intel.com>
@@ -3855,7 +3898,7 @@ W: http://www.baycom.org/~tom/ham/ham.html
F: drivers/net/hamradio/baycom*
BCACHE (BLOCK LAYER CACHE)
-M: Coly Li <colyli@suse.de>
+M: Coly Li <colyli@kernel.org>
M: Kent Overstreet <kent.overstreet@linux.dev>
L: linux-bcache@vger.kernel.org
S: Maintained
@@ -4020,7 +4063,6 @@ F: net/bluetooth/
BONDING DRIVER
M: Jay Vosburgh <jv@jvosburgh.net>
-M: Andy Gospodarek <andy@greyhouse.net>
L: netdev@vger.kernel.org
S: Maintained
F: Documentation/networking/bonding.rst
@@ -4036,6 +4078,13 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/accel/bosch,bma400.yaml
F: drivers/iio/accel/bma400*
+BOSCH SENSORTEC BMI270 IMU IIO DRIVER
+M: Alex Lanzano <lanzano.alex@gmail.com>
+L: linux-iio@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/imu/bosch,bmi270.yaml
+F: drivers/iio/imu/bmi270/
+
BOSCH SENSORTEC BMI323 IMU IIO DRIVER
M: Jagath Jog J <jagathjog1996@gmail.com>
L: linux-iio@vger.kernel.org
@@ -4559,6 +4608,7 @@ F: drivers/net/ethernet/broadcom/bnx2x/
BROADCOM BNXT_EN 50 GIGABIT ETHERNET DRIVER
M: Michael Chan <michael.chan@broadcom.com>
+M: Pavan Chebbi <pavan.chebbi@broadcom.com>
L: netdev@vger.kernel.org
S: Supported
F: drivers/firmware/broadcom/tee_bnxt_fw.c
@@ -7302,7 +7352,7 @@ F: drivers/gpu/drm/panel/panel-novatek-nt36672a.c
DRM DRIVER FOR NVIDIA GEFORCE/QUADRO GPUS
M: Karol Herbst <kherbst@redhat.com>
M: Lyude Paul <lyude@redhat.com>
-M: Danilo Krummrich <dakr@redhat.com>
+M: Danilo Krummrich <dakr@kernel.org>
L: dri-devel@lists.freedesktop.org
L: nouveau@lists.freedesktop.org
S: Supported
@@ -8408,7 +8458,7 @@ F: include/video/s1d13xxxfb.h
EROFS FILE SYSTEM
M: Gao Xiang <xiang@kernel.org>
M: Chao Yu <chao@kernel.org>
-R: Yue Hu <huyue2@coolpad.com>
+R: Yue Hu <zbestahu@gmail.com>
R: Jeffle Xu <jefflexu@linux.alibaba.com>
R: Sandeep Dhavale <dhavale@google.com>
L: linux-erofs@lists.ozlabs.org
@@ -8879,7 +8929,7 @@ F: include/linux/arm_ffa.h
FIRMWARE LOADER (request_firmware)
M: Luis Chamberlain <mcgrof@kernel.org>
M: Russ Weight <russ.weight@linux.dev>
-M: Danilo Krummrich <dakr@redhat.com>
+M: Danilo Krummrich <dakr@kernel.org>
L: linux-kernel@vger.kernel.org
S: Maintained
F: Documentation/firmware_class/
@@ -9483,6 +9533,14 @@ M: Kieran Bingham <kbingham@kernel.org>
S: Supported
F: scripts/gdb/
+GE HEALTHCARE PMC ADC DRIVER
+M: Herve Codina <herve.codina@bootlin.com>
+L: linux-iio@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/iio/adc/gehc,pmc-adc.yaml
+F: drivers/iio/adc/gehc-pmc-adc.c
+F: include/dt-bindings/iio/adc/gehc,pmc-adc.h
+
GEMINI CRYPTO DRIVER
M: Corentin Labbe <clabbe@baylibre.com>
L: linux-crypto@vger.kernel.org
@@ -9718,6 +9776,11 @@ L: platform-driver-x86@vger.kernel.org
S: Maintained
F: drivers/platform/x86/gpd-pocket-fan.c
+GPIB DRIVERS
+M: Dave Penkler <dpenkler@gmail.com>
+S: Maintained
+F: drivers/staging/gpib/
+
GPIO ACPI SUPPORT
M: Mika Westerberg <mika.westerberg@linux.intel.com>
M: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
@@ -10222,7 +10285,6 @@ F: drivers/input/touchscreen/himax_hx83112b.c
HIPPI
M: Jes Sorensen <jes@trained-monkey.org>
-L: linux-hippi@sunsite.dk
S: Maintained
F: drivers/net/hippi/
F: include/linux/hippidevice.h
@@ -10702,6 +10764,14 @@ S: Maintained
F: Documentation/devicetree/bindings/i2c/marvell,mv64xxx-i2c.yaml
F: drivers/i2c/busses/i2c-mv64xxx.c
+I2C OF COMPONENT PROBER
+M: Chen-Yu Tsai <wenst@chromium.org>
+L: linux-i2c@vger.kernel.org
+L: devicetree@vger.kernel.org
+S: Maintained
+F: drivers/i2c/i2c-core-of-prober.c
+F: include/linux/i2c-of-prober.h
+
I2C OVER PARALLEL PORT
M: Jean Delvare <jdelvare@suse.com>
L: linux-i2c@vger.kernel.org
@@ -11641,7 +11711,7 @@ F: drivers/usb/misc/usb-ljca.c
F: include/linux/usb/ljca.h
INTEL MANAGEMENT ENGINE (mei)
-M: Tomas Winkler <tomas.winkler@intel.com>
+M: Alexander Usyskin <alexander.usyskin@intel.com>
L: linux-kernel@vger.kernel.org
S: Supported
F: Documentation/driver-api/mei/*
@@ -11922,7 +11992,7 @@ F: Documentation/devicetree/bindings/media/i2c/isil,isl79987.yaml
F: drivers/media/i2c/isl7998x.c
INVENSENSE ICM-426xx IMU DRIVER
-M: Jean-Baptiste Maneyrol <jmaneyrol@invensense.com>
+M: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
L: linux-iio@vger.kernel.org
S: Maintained
W: https://invensense.tdk.com/
@@ -11937,6 +12007,14 @@ S: Maintained
F: Documentation/devicetree/bindings/iio/gyroscope/invensense,mpu3050.yaml
F: drivers/iio/gyro/mpu3050*
+INVENSENSE MPU-6050 IMU DRIVER
+M: Jean-Baptiste Maneyrol <jean-baptiste.maneyrol@tdk.com>
+L: linux-iio@vger.kernel.org
+S: Maintained
+W: https://invensense.tdk.com/
+F: Documentation/devicetree/bindings/iio/imu/invensense,mpu6050.yaml
+F: drivers/iio/imu/inv_mpu6050/
+
IOC3 ETHERNET DRIVER
M: Thomas Bogendoerfer <tsbogend@alpha.franken.de>
L: linux-mips@vger.kernel.org
@@ -13745,6 +13823,7 @@ F: Documentation/devicetree/bindings/mfd/marvell,88pm886-a1.yaml
F: drivers/input/misc/88pm886-onkey.c
F: drivers/mfd/88pm886.c
F: drivers/regulator/88pm886-regulator.c
+F: drivers/rtc/rtc-88pm886.c
F: include/linux/mfd/88pm886.h
MARVELL ARMADA 3700 PHY DRIVERS
@@ -13869,6 +13948,7 @@ M: Sunil Goutham <sgoutham@marvell.com>
M: Geetha sowjanya <gakula@marvell.com>
M: Subbaraya Sundeep <sbhatta@marvell.com>
M: hariprasad <hkelam@marvell.com>
+M: Bharat Bhushan <bbhushan2@marvell.com>
L: netdev@vger.kernel.org
S: Supported
F: drivers/net/ethernet/marvell/octeontx2/nic/
@@ -14491,7 +14571,6 @@ F: drivers/dma/mediatek/
MEDIATEK ETHERNET DRIVER
M: Felix Fietkau <nbd@nbd.name>
M: Sean Wang <sean.wang@mediatek.com>
-M: Mark Lee <Mark-MC.Lee@mediatek.com>
M: Lorenzo Bianconi <lorenzo@kernel.org>
L: netdev@vger.kernel.org
S: Maintained
@@ -14681,7 +14760,7 @@ F: drivers/memory/mtk-smi.c
F: include/soc/mediatek/smi.h
MEDIATEK SWITCH DRIVER
-M: Arınç ÜNAL <arinc.unal@arinc9.com>
+M: Chester A. Unal <chester.a.unal@arinc9.com>
M: Daniel Golle <daniel@makrotopia.org>
M: DENG Qingfang <dqfext@gmail.com>
M: Sean Wang <sean.wang@mediatek.com>
@@ -15270,7 +15349,7 @@ M: Daniel Machon <daniel.machon@microchip.com>
M: UNGLinuxDriver@microchip.com
L: netdev@vger.kernel.org
S: Maintained
-F: drivers/net/ethernet/microchip/lan969x/*
+F: drivers/net/ethernet/microchip/sparx5/lan969x/*
MICROCHIP LCDFB DRIVER
M: Nicolas Ferre <nicolas.ferre@microchip.com>
@@ -16091,7 +16170,8 @@ M: Breno Leitao <leitao@debian.org>
S: Maintained
F: Documentation/networking/netconsole.rst
F: drivers/net/netconsole.c
-F: tools/testing/selftests/drivers/net/netcons_basic.sh
+F: tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
+F: tools/testing/selftests/drivers/net/netcons\*
NETDEVSIM
M: Jakub Kicinski <kuba@kernel.org>
@@ -16194,6 +16274,7 @@ F: Documentation/devicetree/bindings/net/
F: Documentation/networking/net_cachelines/net_device.rst
F: drivers/connector/
F: drivers/net/
+F: drivers/ptp/
F: include/dt-bindings/net/
F: include/linux/cn_proc.h
F: include/linux/etherdevice.h
@@ -16206,7 +16287,7 @@ F: include/linux/inetdevice.h
F: include/linux/netdev*
F: include/linux/platform_data/wiznet.h
F: include/uapi/linux/cn_proc.h
-F: include/uapi/linux/ethtool_netlink.h
+F: include/uapi/linux/ethtool_netlink*
F: include/uapi/linux/if_*
F: include/uapi/linux/net_shaper.h
F: include/uapi/linux/netdev*
@@ -16261,6 +16342,7 @@ F: Documentation/networking/
F: Documentation/networking/net_cachelines/
F: Documentation/process/maintainer-netdev.rst
F: Documentation/userspace-api/netlink/
+F: include/linux/ethtool.h
F: include/linux/framer/framer-provider.h
F: include/linux/framer/framer.h
F: include/linux/in.h
@@ -16275,6 +16357,7 @@ F: include/linux/rtnetlink.h
F: include/linux/seq_file_net.h
F: include/linux/skbuff*
F: include/net/
+F: include/uapi/linux/ethtool.h
F: include/uapi/linux/genetlink.h
F: include/uapi/linux/hsr_netlink.h
F: include/uapi/linux/in.h
@@ -16304,6 +16387,7 @@ X: include/net/wext.h
X: net/9p/
X: net/bluetooth/
X: net/can/
+X: net/ceph/
X: net/mac80211/
X: net/rfkill/
X: net/wireless/
@@ -17561,6 +17645,7 @@ F: Documentation/core-api/packing.rst
F: include/linux/packing.h
F: lib/packing.c
F: lib/packing_test.c
+F: scripts/gen_packed_field_checks.c
PADATA PARALLEL EXECUTION MECHANISM
M: Steffen Klassert <steffen.klassert@secunet.com>
@@ -18381,7 +18466,7 @@ F: Documentation/devicetree/bindings/pinctrl/mediatek,mt8183-pinctrl.yaml
F: drivers/pinctrl/mediatek/
PIN CONTROLLER - MEDIATEK MIPS
-M: Arınç ÜNAL <arinc.unal@arinc9.com>
+M: Chester A. Unal <chester.a.unal@arinc9.com>
M: Sergio Paracuellos <sergio.paracuellos@gmail.com>
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
L: linux-mips@vger.kernel.org
@@ -18649,6 +18734,13 @@ S: Maintained
F: include/linux/psi*
F: kernel/sched/psi.c
+PROPELLER BUILD
+M: Rong Xu <xur@google.com>
+M: Han Shen <shenhan@google.com>
+S: Supported
+F: Documentation/dev-tools/propeller.rst
+F: scripts/Makefile.propeller
+
PRINTK
M: Petr Mladek <pmladek@suse.com>
R: Steven Rostedt <rostedt@goodmis.org>
@@ -19418,7 +19510,7 @@ S: Maintained
F: arch/mips/ralink
RALINK MT7621 MIPS ARCHITECTURE
-M: Arınç ÜNAL <arinc.unal@arinc9.com>
+M: Chester A. Unal <chester.a.unal@arinc9.com>
M: Sergio Paracuellos <sergio.paracuellos@gmail.com>
L: linux-mips@vger.kernel.org
S: Maintained
@@ -19865,6 +19957,14 @@ S: Supported
F: Documentation/devicetree/bindings/timer/renesas,rz-mtu3.yaml
F: drivers/counter/rz-mtu3-cnt.c
+RENESAS RTCA-3 RTC DRIVER
+M: Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>
+L: linux-rtc@vger.kernel.org
+L: linux-renesas-soc@vger.kernel.org
+S: Supported
+F: Documentation/devicetree/bindings/rtc/renesas,rz-rtca3.yaml
+F: drivers/rtc/rtc-renesas-rtca3.c
+
RENESAS RZ/N1 A5PSW SWITCH DRIVER
M: Clément Léger <clement.leger@bootlin.com>
L: linux-renesas-soc@vger.kernel.org
@@ -20813,6 +20913,8 @@ F: kernel/sched/
SCHEDULER - SCHED_EXT
R: Tejun Heo <tj@kernel.org>
R: David Vernet <void@manifault.com>
+R: Andrea Righi <arighi@nvidia.com>
+R: Changwoo Min <changwoo@igalia.com>
L: linux-kernel@vger.kernel.org
S: Maintained
W: https://github.com/sched-ext/scx
@@ -22135,17 +22237,6 @@ L: linux-media@vger.kernel.org
S: Maintained
F: drivers/staging/media/atomisp/
-STAGING - FIELDBUS SUBSYSTEM
-M: Sven Van Asbroeck <TheSven73@gmail.com>
-S: Maintained
-F: drivers/staging/fieldbus/*
-F: drivers/staging/fieldbus/Documentation/
-
-STAGING - HMS ANYBUS-S BUS
-M: Sven Van Asbroeck <TheSven73@gmail.com>
-S: Maintained
-F: drivers/staging/fieldbus/anybuss/
-
STAGING - INDUSTRIAL IO
M: Jonathan Cameron <jic23@kernel.org>
L: linux-iio@vger.kernel.org
@@ -22160,18 +22251,6 @@ L: linux-tegra@vger.kernel.org
S: Maintained
F: drivers/staging/nvec/
-STAGING - OLPC SECONDARY DISPLAY CONTROLLER (DCON)
-M: Jens Frederich <jfrederich@gmail.com>
-M: Jon Nettleton <jon.nettleton@gmail.com>
-S: Maintained
-W: http://wiki.laptop.org/go/DCON
-F: drivers/staging/olpc_dcon/
-
-STAGING - REALTEK RTL8712U DRIVERS
-M: Florian Schilhabel <florian.c.schilhabel@googlemail.com>.
-S: Odd Fixes
-F: drivers/staging/rtl8712/
-
STAGING - SEPS525 LCD CONTROLLER DRIVERS
M: Michael Hennerich <michael.hennerich@analog.com>
L: linux-fbdev@vger.kernel.org
@@ -22187,11 +22266,6 @@ L: linux-fbdev@vger.kernel.org
S: Maintained
F: drivers/staging/sm750fb/
-STAGING - VIA VT665X DRIVERS
-M: Philipp Hortmann <philipp.g.hortmann@gmail.com>
-S: Odd Fixes
-F: drivers/staging/vt665?/
-
STAGING SUBSYSTEM
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-staging@lists.linux.dev
@@ -22346,7 +22420,7 @@ F: drivers/char/hw_random/jh7110-trng.c
STARFIVE WATCHDOG DRIVER
M: Xingyu Wu <xingyu.wu@starfivetech.com>
-M: Samin Guo <samin.guo@starfivetech.com>
+M: Ziv Xu <ziv.xu@starfivetech.com>
S: Supported
F: Documentation/devicetree/bindings/watchdog/starfive*
F: drivers/watchdog/starfive-wdt.c
@@ -22435,11 +22509,8 @@ F: Documentation/devicetree/bindings/phy/st,stm32mp25-combophy.yaml
F: drivers/phy/st/phy-stm32-combophy.c
STMMAC ETHERNET DRIVER
-M: Alexandre Torgue <alexandre.torgue@foss.st.com>
-M: Jose Abreu <joabreu@synopsys.com>
L: netdev@vger.kernel.org
-S: Supported
-W: http://www.stlinux.com
+S: Orphan
F: Documentation/networking/device_drivers/ethernet/stmicro/
F: drivers/net/ethernet/stmicro/stmmac/
@@ -22671,9 +22742,8 @@ S: Supported
F: drivers/net/ethernet/synopsys/
SYNOPSYS DESIGNWARE ETHERNET XPCS DRIVER
-M: Jose Abreu <Jose.Abreu@synopsys.com>
L: netdev@vger.kernel.org
-S: Supported
+S: Orphan
F: drivers/net/pcs/pcs-xpcs.c
F: drivers/net/pcs/pcs-xpcs.h
F: include/linux/pcs/pcs-xpcs.h
@@ -23581,7 +23651,6 @@ F: tools/testing/selftests/timers/
TIPC NETWORK LAYER
M: Jon Maloy <jmaloy@redhat.com>
-M: Ying Xue <ying.xue@windriver.com>
L: netdev@vger.kernel.org (core kernel code)
L: tipc-discussion@lists.sourceforge.net (user apps, general discussion)
S: Maintained
@@ -24187,7 +24256,8 @@ F: Documentation/devicetree/bindings/usb/nxp,isp1760.yaml
F: drivers/usb/isp1760/*
USB LAN78XX ETHERNET DRIVER
-M: Woojung Huh <woojung.huh@microchip.com>
+M: Thangaraj Samynathan <Thangaraj.S@microchip.com>
+M: Rengarajan Sundararajan <Rengarajan.S@microchip.com>
M: UNGLinuxDriver@microchip.com
L: netdev@vger.kernel.org
S: Maintained
@@ -24352,6 +24422,13 @@ L: linux-usb@vger.kernel.org
S: Orphan
F: drivers/usb/typec/tcpm/
+USB TYPEC TUSB1046 MUX DRIVER
+M: Romain Gantois <romain.gantois@bootlin.com>
+L: linux-usb@vger.kernel.org
+S: Maintained
+F: Documentation/devicetree/bindings/usb/ti,tusb1046.yaml
+F: drivers/usb/typec/mux/tusb1046.c
+
USB UHCI DRIVER
M: Alan Stern <stern@rowland.harvard.edu>
L: linux-usb@vger.kernel.org
@@ -24905,6 +24982,18 @@ S: Maintained
F: drivers/input/serio/userio.c
F: include/uapi/linux/userio.h
+VISHAY VEML3235 AMBIENT LIGHT SENSOR DRIVER
+M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+S: Maintained
+F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml
+F: drivers/iio/light/veml3235.c
+
+VISHAY VEML6030 AMBIENT LIGHT SENSOR DRIVER
+M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
+S: Maintained
+F: Documentation/devicetree/bindings/iio/light/vishay,veml6030.yaml
+F: drivers/iio/light/veml6030.c
+
VISHAY VEML6075 UVA AND UVB LIGHT SENSOR DRIVER
M: Javier Carrasco <javier.carrasco.cruz@gmail.com>
S: Maintained
diff --git a/Makefile b/Makefile
index 8129de0b214f..b11454a2233a 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
VERSION = 6
-PATCHLEVEL = 12
+PATCHLEVEL = 13
SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc6
NAME = Baby Opossum Posse
# *DOCUMENTATION*
@@ -40,7 +40,7 @@ __all:
this-makefile := $(lastword $(MAKEFILE_LIST))
abs_srctree := $(realpath $(dir $(this-makefile)))
-abs_objtree := $(CURDIR)
+abs_output := $(CURDIR)
ifneq ($(sub_make_done),1)
@@ -134,6 +134,10 @@ ifeq ("$(origin M)", "command line")
KBUILD_EXTMOD := $(M)
endif
+ifeq ("$(origin MO)", "command line")
+ KBUILD_EXTMOD_OUTPUT := $(MO)
+endif
+
$(if $(word 2, $(KBUILD_EXTMOD)), \
$(error building multiple external modules is not supported))
@@ -176,18 +180,41 @@ export KBUILD_EXTRA_WARN
# The O= assignment takes precedence over the KBUILD_OUTPUT environment
# variable.
-# Do we want to change the working directory?
ifeq ("$(origin O)", "command line")
KBUILD_OUTPUT := $(O)
endif
-ifneq ($(KBUILD_OUTPUT),)
+ifdef KBUILD_EXTMOD
+ ifdef KBUILD_OUTPUT
+ objtree := $(realpath $(KBUILD_OUTPUT))
+ $(if $(objtree),,$(error specified kernel directory "$(KBUILD_OUTPUT)" does not exist))
+ else
+ objtree := $(abs_srctree)
+ endif
+ # If Make is invoked from the kernel directory (either kernel
+ # source directory or kernel build directory), external modules
+ # are built in $(KBUILD_EXTMOD) for backward compatibility,
+ # otherwise, built in the current directory.
+ output := $(or $(KBUILD_EXTMOD_OUTPUT),$(if $(filter $(CURDIR),$(objtree) $(abs_srctree)),$(KBUILD_EXTMOD)))
+ # KBUILD_EXTMOD might be a relative path. Remember its absolute path before
+ # Make changes the working directory.
+ srcroot := $(realpath $(KBUILD_EXTMOD))
+ $(if $(srcroot),,$(error specified external module directory "$(KBUILD_EXTMOD)" does not exist))
+else
+ objtree := .
+ output := $(KBUILD_OUTPUT)
+endif
+
+export objtree srcroot
+
+# Do we want to change the working directory?
+ifneq ($(output),)
# $(realpath ...) gets empty if the path does not exist. Run 'mkdir -p' first.
-$(shell mkdir -p "$(KBUILD_OUTPUT)")
+$(shell mkdir -p "$(output)")
# $(realpath ...) resolves symlinks
-abs_objtree := $(realpath $(KBUILD_OUTPUT))
-$(if $(abs_objtree),,$(error failed to create output directory "$(KBUILD_OUTPUT)"))
-endif # ifneq ($(KBUILD_OUTPUT),)
+abs_output := $(realpath $(output))
+$(if $(abs_output),,$(error failed to create output directory "$(output)"))
+endif
ifneq ($(words $(subst :, ,$(abs_srctree))), 1)
$(error source directory cannot contain spaces or colons)
@@ -197,7 +224,7 @@ export sub_make_done := 1
endif # sub_make_done
-ifeq ($(abs_objtree),$(CURDIR))
+ifeq ($(abs_output),$(CURDIR))
# Suppress "Entering directory ..." if we are at the final work directory.
no-print-directory := --no-print-directory
else
@@ -221,43 +248,41 @@ $(filter-out $(this-makefile), $(MAKECMDGOALS)) __all: __sub-make
# Invoke a second make in the output directory, passing relevant variables
__sub-make:
- $(Q)$(MAKE) $(no-print-directory) -C $(abs_objtree) \
+ $(Q)$(MAKE) $(no-print-directory) -C $(abs_output) \
-f $(abs_srctree)/Makefile $(MAKECMDGOALS)
else # need-sub-make
# We process the rest of the Makefile if this is the final invocation of make
-ifeq ($(abs_srctree),$(abs_objtree))
- # building in the source tree
- srctree := .
- building_out_of_srctree :=
-else
- ifeq ($(abs_srctree)/,$(dir $(abs_objtree)))
- # building in a subdirectory of the source tree
- srctree := ..
- else
- srctree := $(abs_srctree)
- endif
- building_out_of_srctree := 1
+ifndef KBUILD_EXTMOD
+srcroot := $(abs_srctree)
endif
-ifneq ($(KBUILD_ABS_SRCTREE),)
-srctree := $(abs_srctree)
+ifeq ($(srcroot),$(CURDIR))
+building_out_of_srctree :=
+else
+export building_out_of_srctree := 1
endif
-objtree := .
+ifdef KBUILD_ABS_SRCTREE
+ # Do nothing. Use the absolute path.
+else ifeq ($(srcroot),$(CURDIR))
+ # Building in the source.
+ srcroot := .
+else ifeq ($(srcroot)/,$(dir $(CURDIR)))
+ # Building in a subdirectory of the source.
+ srcroot := ..
+endif
-VPATH :=
+export srctree := $(if $(KBUILD_EXTMOD),$(abs_srctree),$(srcroot))
-ifeq ($(KBUILD_EXTMOD),)
ifdef building_out_of_srctree
-VPATH := $(srctree)
-endif
+export VPATH := $(srcroot)
+else
+VPATH :=
endif
-export building_out_of_srctree srctree objtree VPATH
-
# To make sure we do not include .config for any of the *config targets
# catch them early, and hand them over to scripts/kconfig/Makefile
# It is allowed to specify more targets when calling make, including
@@ -276,7 +301,7 @@ no-dot-config-targets := $(clean-targets) \
outputmakefile rustavailable rustfmt rustfmtcheck
no-sync-config-targets := $(no-dot-config-targets) %install modules_sign kernelrelease \
image_name
-single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.rsi %.s %.symtypes %/
+single-targets := %.a %.i %.ko %.lds %.ll %.lst %.mod %.o %.rsi %.s %/
config-build :=
mixed-build :=
@@ -354,7 +379,7 @@ else # !mixed-build
include $(srctree)/scripts/Kbuild.include
# Read KERNELRELEASE from include/config/kernel.release (if it exists)
-KERNELRELEASE = $(call read-file, include/config/kernel.release)
+KERNELRELEASE = $(call read-file, $(objtree)/include/config/kernel.release)
KERNELVERSION = $(VERSION)$(if $(PATCHLEVEL),.$(PATCHLEVEL)$(if $(SUBLEVEL),.$(SUBLEVEL)))$(EXTRAVERSION)
export VERSION PATCHLEVEL SUBLEVEL KERNELRELEASE KERNELVERSION
@@ -513,7 +538,7 @@ KGZIP = gzip
KBZIP2 = bzip2
KLZOP = lzop
LZMA = lzma
-LZ4 = lz4c
+LZ4 = lz4
XZ = xz
ZSTD = zstd
@@ -543,7 +568,7 @@ USERINCLUDE := \
LINUXINCLUDE := \
-I$(srctree)/arch/$(SRCARCH)/include \
-I$(objtree)/arch/$(SRCARCH)/include/generated \
- $(if $(building_out_of_srctree),-I$(srctree)/include) \
+ -I$(srctree)/include \
-I$(objtree)/include \
$(USERINCLUDE)
@@ -629,13 +654,25 @@ ifdef building_out_of_srctree
# At the same time when output Makefile generated, generate .gitignore to
# ignore whole output directory
+ifdef KBUILD_EXTMOD
+print_env_for_makefile = \
+ echo "export KBUILD_OUTPUT = $(objtree)"; \
+ echo "export KBUILD_EXTMOD = $(realpath $(srcroot))" ; \
+ echo "export KBUILD_EXTMOD_OUTPUT = $(CURDIR)"
+else
+print_env_for_makefile = \
+ echo "export KBUILD_OUTPUT = $(CURDIR)"
+endif
+
quiet_cmd_makefile = GEN Makefile
cmd_makefile = { \
- echo "\# Automatically generated by $(srctree)/Makefile: don't edit"; \
- echo "include $(srctree)/Makefile"; \
+ echo "\# Automatically generated by $(abs_srctree)/Makefile: don't edit"; \
+ $(print_env_for_makefile); \
+ echo "include $(abs_srctree)/Makefile"; \
} > Makefile
outputmakefile:
+ifeq ($(KBUILD_EXTMOD),)
@if [ -f $(srctree)/.config -o \
-d $(srctree)/include/config -o \
-d $(srctree)/arch/$(SRCARCH)/include/generated ]; then \
@@ -645,7 +682,16 @@ outputmakefile:
echo >&2 "***"; \
false; \
fi
- $(Q)ln -fsn $(srctree) source
+else
+ @if [ -f $(srcroot)/modules.order ]; then \
+ echo >&2 "***"; \
+ echo >&2 "*** The external module source tree is not clean."; \
+ echo >&2 "*** Please run 'make -C $(abs_srctree) M=$(realpath $(srcroot)) clean'"; \
+ echo >&2 "***"; \
+ false; \
+ fi
+endif
+ $(Q)ln -fsn $(srcroot) source
$(call cmd,makefile)
$(Q)test -e .gitignore || \
{ echo "# this is build directory, ignore it"; echo "*"; } > .gitignore
@@ -717,7 +763,7 @@ endif
# in addition to whatever we do anyway.
# Just "make" or "make all" shall build modules as well
-ifneq ($(filter all modules nsdeps %compile_commands.json clang-%,$(MAKECMDGOALS)),)
+ifneq ($(filter all modules nsdeps compile_commands.json clang-%,$(MAKECMDGOALS)),)
KBUILD_MODULES := 1
endif
@@ -728,7 +774,7 @@ endif
export KBUILD_MODULES KBUILD_BUILTIN
ifdef need-config
-include include/config/auto.conf
+include $(objtree)/include/config/auto.conf
endif
ifeq ($(KBUILD_EXTMOD),)
@@ -789,17 +835,22 @@ $(KCONFIG_CONFIG):
else # !may-sync-config
# External modules and some install targets need include/generated/autoconf.h
# and include/config/auto.conf but do not care if they are up-to-date.
-# Use auto.conf to trigger the test
-PHONY += include/config/auto.conf
-
-include/config/auto.conf:
- @test -e include/generated/autoconf.h -a -e $@ || ( \
- echo >&2; \
- echo >&2 " ERROR: Kernel configuration is invalid."; \
- echo >&2 " include/generated/autoconf.h or $@ are missing.";\
- echo >&2 " Run 'make oldconfig && make prepare' on kernel src to fix it."; \
- echo >&2 ; \
- /bin/false)
+# Use auto.conf to show the error message
+
+checked-configs := $(addprefix $(objtree)/, include/generated/autoconf.h include/generated/rustc_cfg include/config/auto.conf)
+missing-configs := $(filter-out $(wildcard $(checked-configs)), $(checked-configs))
+
+ifdef missing-configs
+PHONY += $(objtree)/include/config/auto.conf
+
+$(objtree)/include/config/auto.conf:
+ @echo >&2 '***'
+ @echo >&2 '*** ERROR: Kernel configuration is invalid. The following files are missing:'
+ @printf >&2 '*** - %s\n' $(missing-configs)
+ @echo >&2 '*** Run "make oldconfig && make prepare" on kernel source to fix it.'
+ @echo >&2 '***'
+ @/bin/false
+endif
endif # may-sync-config
endif # need-config
@@ -1013,8 +1064,10 @@ ifdef CONFIG_CC_IS_GCC
KBUILD_CFLAGS += -fconserve-stack
endif
-# change __FILE__ to the relative path from the srctree
-KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srctree)/=)
+# change __FILE__ to the relative path to the source directory
+ifdef building_out_of_srctree
+KBUILD_CPPFLAGS += $(call cc-option,-fmacro-prefix-map=$(srcroot)/=)
+endif
# include additional Makefiles when needed
include-y := scripts/Makefile.extrawarn
@@ -1026,6 +1079,8 @@ include-$(CONFIG_KMSAN) += scripts/Makefile.kmsan
include-$(CONFIG_UBSAN) += scripts/Makefile.ubsan
include-$(CONFIG_KCOV) += scripts/Makefile.kcov
include-$(CONFIG_RANDSTRUCT) += scripts/Makefile.randstruct
+include-$(CONFIG_AUTOFDO_CLANG) += scripts/Makefile.autofdo
+include-$(CONFIG_PROPELLER_CLANG) += scripts/Makefile.propeller
include-$(CONFIG_GCC_PLUGINS) += scripts/Makefile.gcc-plugins
include $(addprefix $(srctree)/, $(include-y))
@@ -1106,10 +1161,6 @@ export MODLIB
PHONY += prepare0
-export extmod_prefix = $(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD)/)
-export MODORDER := $(extmod_prefix)modules.order
-export MODULES_NSDEPS := $(extmod_prefix)modules.nsdeps
-
ifeq ($(KBUILD_EXTMOD),)
build-dir := .
@@ -1204,7 +1255,8 @@ PHONY += prepare archprepare
archprepare: outputmakefile archheaders archscripts scripts include/config/kernel.release \
asm-generic $(version_h) include/generated/utsrelease.h \
- include/generated/compile.h include/generated/autoconf.h remove-stale-files
+ include/generated/compile.h include/generated/autoconf.h \
+ include/generated/rustc_cfg remove-stale-files
prepare0: archprepare
$(Q)$(MAKE) $(build)=scripts/mod
@@ -1315,6 +1367,10 @@ PHONY += scripts_unifdef
scripts_unifdef: scripts_basic
$(Q)$(MAKE) $(build)=scripts scripts/unifdef
+PHONY += scripts_gen_packed_field_checks
+scripts_gen_packed_field_checks: scripts_basic
+ $(Q)$(MAKE) $(build)=scripts scripts/gen_packed_field_checks
+
# ---------------------------------------------------------------------------
# Install
@@ -1435,6 +1491,10 @@ ifdef CONFIG_OF_EARLY_FLATTREE
all: dtbs
endif
+ifdef CONFIG_GENERIC_BUILTIN_DTB
+vmlinux: dtbs
+endif
+
endif
PHONY += scripts_dtc
@@ -1502,7 +1562,8 @@ CLEAN_FILES += vmlinux.symvers modules-only.symvers \
modules.builtin modules.builtin.modinfo modules.nsdeps \
modules.builtin.ranges vmlinux.o.map \
compile_commands.json rust/test \
- rust-project.json .vmlinux.objs .vmlinux.export.c
+ rust-project.json .vmlinux.objs .vmlinux.export.c \
+ .builtin-dtbs-list .builtin-dtb.S
# Directories & files removed with 'make mrproper'
MRPROPER_FILES += include/config include/generated \
@@ -1750,18 +1811,9 @@ rusttest: prepare
# Formatting targets
PHONY += rustfmt rustfmtcheck
-# We skip `rust/alloc` since we want to minimize the diff w.r.t. upstream.
-#
-# We match using absolute paths since `find` does not resolve them
-# when matching, which is a problem when e.g. `srctree` is `..`.
-# We `grep` afterwards in order to remove the directory entry itself.
rustfmt:
- $(Q)find $(abs_srctree) -type f -name '*.rs' \
- -o -path $(abs_srctree)/rust/alloc -prune \
- -o -path $(abs_objtree)/rust/test -prune \
- | grep -Fv $(abs_srctree)/rust/alloc \
- | grep -Fv $(abs_objtree)/rust/test \
- | grep -Fv generated \
+ $(Q)find $(srctree) $(RCS_FIND_IGNORE) \
+ -type f -a -name '*.rs' -a ! -name '*generated*' -print \
| xargs $(RUSTFMT) $(rustfmt_flags)
rustfmtcheck: rustfmt_flags = --check
@@ -1800,14 +1852,10 @@ filechk_kernel.release = echo $(KERNELRELEASE)
KBUILD_BUILTIN :=
KBUILD_MODULES := 1
-build-dir := $(KBUILD_EXTMOD)
+build-dir := .
-compile_commands.json: $(extmod_prefix)compile_commands.json
-PHONY += compile_commands.json
-
-clean-dirs := $(KBUILD_EXTMOD)
-clean: private rm-files := $(KBUILD_EXTMOD)/Module.symvers $(KBUILD_EXTMOD)/modules.nsdeps \
- $(KBUILD_EXTMOD)/compile_commands.json
+clean-dirs := .
+clean: private rm-files := Module.symvers modules.nsdeps compile_commands.json
PHONY += prepare
# now expand this into a simple variable to reduce the cost of shell evaluations
@@ -1866,7 +1914,7 @@ endif
ifdef CONFIG_MODULES
-$(MODORDER): $(build-dir)
+modules.order: $(build-dir)
@:
# KBUILD_MODPOST_NOFINAL can be set to skip the final link of modules.
@@ -1877,7 +1925,7 @@ ifneq ($(KBUILD_MODPOST_NOFINAL),1)
endif
PHONY += modules_check
-modules_check: $(MODORDER)
+modules_check: modules.order
$(Q)$(CONFIG_SHELL) $(srctree)/scripts/modules-check.sh $<
else # CONFIG_MODULES
@@ -1918,15 +1966,15 @@ $(single-ko): single_modules
$(single-no-ko): $(build-dir)
@:
-# Remove MODORDER when done because it is not the real one.
+# Remove modules.order when done because it is not the real one.
PHONY += single_modules
single_modules: $(single-no-ko) modules_prepare
- $(Q){ $(foreach m, $(single-ko), echo $(extmod_prefix)$(m:%.ko=%.o);) } > $(MODORDER)
+ $(Q){ $(foreach m, $(single-ko), echo $(m:%.ko=%.o);) } > modules.order
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
ifneq ($(KBUILD_MODPOST_NOFINAL),1)
$(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modfinal
endif
- $(Q)rm -f $(MODORDER)
+ $(Q)rm -f modules.order
single-goals := $(addprefix $(build-dir)/, $(single-no-ko))
@@ -1934,6 +1982,8 @@ KBUILD_MODULES := 1
endif
+prepare: outputmakefile
+
# Preset locale variables to speed up the build process. Limit locale
# tweaks to this spot to avoid wrong language settings when running
# make menuconfig etc.
@@ -1949,7 +1999,7 @@ $(clean-dirs):
clean: $(clean-dirs)
$(call cmd,rmfiles)
- @find $(or $(KBUILD_EXTMOD), .) $(RCS_FIND_IGNORE) \
+ @find . $(RCS_FIND_IGNORE) \
\( -name '*.[aios]' -o -name '*.rsi' -o -name '*.ko' -o -name '.*.cmd' \
-o -name '*.ko.*' \
-o -name '*.dtb' -o -name '*.dtbo' \
@@ -1982,7 +2032,12 @@ tags TAGS cscope gtags: FORCE
PHONY += rust-analyzer
rust-analyzer:
+$(Q)$(CONFIG_SHELL) $(srctree)/scripts/rust_is_available.sh
+ifdef KBUILD_EXTMOD
+# FIXME: external modules must not descend into a sub-directory of the kernel
+ $(Q)$(MAKE) $(build)=$(objtree)/rust src=$(srctree)/rust $@
+else
$(Q)$(MAKE) $(build)=rust $@
+endif
# Script to generate missing namespace dependencies
# ---------------------------------------------------------------------------
@@ -1998,12 +2053,12 @@ nsdeps: modules
quiet_cmd_gen_compile_commands = GEN $@
cmd_gen_compile_commands = $(PYTHON3) $< -a $(AR) -o $@ $(filter-out $<, $(real-prereqs))
-$(extmod_prefix)compile_commands.json: $(srctree)/scripts/clang-tools/gen_compile_commands.py \
+compile_commands.json: $(srctree)/scripts/clang-tools/gen_compile_commands.py \
$(if $(KBUILD_EXTMOD),, vmlinux.a $(KBUILD_VMLINUX_LIBS)) \
- $(if $(CONFIG_MODULES), $(MODORDER)) FORCE
+ $(if $(CONFIG_MODULES), modules.order) FORCE
$(call if_changed,gen_compile_commands)
-targets += $(extmod_prefix)compile_commands.json
+targets += compile_commands.json
PHONY += clang-tidy clang-analyzer
@@ -2011,7 +2066,7 @@ ifdef CONFIG_CC_IS_CLANG
quiet_cmd_clang_tools = CHECK $<
cmd_clang_tools = $(PYTHON3) $(srctree)/scripts/clang-tools/run-clang-tools.py $@ $<
-clang-tidy clang-analyzer: $(extmod_prefix)compile_commands.json
+clang-tidy clang-analyzer: compile_commands.json
$(call cmd,clang_tools)
else
clang-tidy clang-analyzer:
diff --git a/arch/Kconfig b/arch/Kconfig
index 832f68af7c77..6682b2a53e34 100644
--- a/arch/Kconfig
+++ b/arch/Kconfig
@@ -812,6 +812,45 @@ config LTO_CLANG_THIN
If unsure, say Y.
endchoice
+config ARCH_SUPPORTS_AUTOFDO_CLANG
+ bool
+
+config AUTOFDO_CLANG
+ bool "Enable Clang's AutoFDO build (EXPERIMENTAL)"
+ depends on ARCH_SUPPORTS_AUTOFDO_CLANG
+ depends on CC_IS_CLANG && CLANG_VERSION >= 170000
+ help
+ This option enables Clang’s AutoFDO build. When
+ an AutoFDO profile is specified in variable
+ CLANG_AUTOFDO_PROFILE during the build process,
+ Clang uses the profile to optimize the kernel.
+
+ If no profile is specified, AutoFDO options are
+ still passed to Clang to facilitate the collection
+ of perf data for creating an AutoFDO profile in
+ subsequent builds.
+
+ If unsure, say N.
+
+config ARCH_SUPPORTS_PROPELLER_CLANG
+ bool
+
+config PROPELLER_CLANG
+ bool "Enable Clang's Propeller build"
+ depends on ARCH_SUPPORTS_PROPELLER_CLANG
+ depends on CC_IS_CLANG && CLANG_VERSION >= 190000
+ help
+ This option enables Clang’s Propeller build. When the Propeller
+ profiles is specified in variable CLANG_PROPELLER_PROFILE_PREFIX
+ during the build process, Clang uses the profiles to optimize
+ the kernel.
+
+ If no profile is specified, Propeller options are still passed
+ to Clang to facilitate the collection of perf data for creating
+ the Propeller profiles in subsequent builds.
+
+ If unsure, say N.
+
config ARCH_SUPPORTS_CFI_CLANG
bool
help
diff --git a/arch/alpha/include/uapi/asm/socket.h b/arch/alpha/include/uapi/asm/socket.h
index 302507bf9b5d..3df5f2dd4c0f 100644
--- a/arch/alpha/include/uapi/asm/socket.h
+++ b/arch/alpha/include/uapi/asm/socket.h
@@ -148,6 +148,8 @@
#define SCM_TS_OPT_ID 81
+#define SO_RCVPRIORITY 82
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
diff --git a/arch/alpha/kernel/pci-sysfs.c b/arch/alpha/kernel/pci-sysfs.c
index 5808a66e2a81..3048758304b5 100644
--- a/arch/alpha/kernel/pci-sysfs.c
+++ b/arch/alpha/kernel/pci-sysfs.c
@@ -64,7 +64,7 @@ static int __pci_mmap_fits(struct pci_dev *pdev, int num,
* Return: %0 on success, negative error code otherwise
*/
static int pci_mmap_resource(struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma, int sparse)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
@@ -93,14 +93,14 @@ static int pci_mmap_resource(struct kobject *kobj,
}
static int pci_mmap_resource_sparse(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
return pci_mmap_resource(kobj, attr, vma, 1);
}
static int pci_mmap_resource_dense(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
return pci_mmap_resource(kobj, attr, vma, 0);
diff --git a/arch/arc/Kconfig b/arch/arc/Kconfig
index 5b2488142041..4f2eeda907ec 100644
--- a/arch/arc/Kconfig
+++ b/arch/arc/Kconfig
@@ -6,6 +6,7 @@
config ARC
def_bool y
select ARC_TIMERS
+ select ARCH_HAS_CPU_CACHE_ALIASING
select ARCH_HAS_CACHE_LINE_SIZE
select ARCH_HAS_DEBUG_VM_PGTABLE
select ARCH_HAS_DMA_PREP_COHERENT
@@ -297,7 +298,6 @@ config ARC_PAGE_SIZE_16K
config ARC_PAGE_SIZE_4K
bool "4KB"
select HAVE_PAGE_SIZE_4KB
- depends on ARC_MMU_V3 || ARC_MMU_V4
endchoice
@@ -474,7 +474,8 @@ config HIGHMEM
config ARC_HAS_PAE40
bool "Support for the 40-bit Physical Address Extension"
- depends on ISA_ARCV2
+ depends on ARC_MMU_V4
+ depends on !ARC_PAGE_SIZE_4K
select HIGHMEM
select PHYS_ADDR_T_64BIT
help
diff --git a/arch/arc/Makefile b/arch/arc/Makefile
index 2390dd042e36..fb98478ed1ab 100644
--- a/arch/arc/Makefile
+++ b/arch/arc/Makefile
@@ -6,7 +6,7 @@
KBUILD_DEFCONFIG := haps_hs_smp_defconfig
ifeq ($(CROSS_COMPILE),)
-CROSS_COMPILE := $(call cc-cross-prefix, arc-linux- arceb-linux-)
+CROSS_COMPILE := $(call cc-cross-prefix, arc-linux- arceb-linux- arc-linux-gnu-)
endif
cflags-y += -fno-common -pipe -fno-builtin -mmedium-calls -D__linux__
diff --git a/arch/arc/boot/dts/axc001.dtsi b/arch/arc/boot/dts/axc001.dtsi
index 2a151607b080..88bcc7ab6f5a 100644
--- a/arch/arc/boot/dts/axc001.dtsi
+++ b/arch/arc/boot/dts/axc001.dtsi
@@ -54,7 +54,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <30>;
+ ngpios = <30>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arc/boot/dts/axc003.dtsi b/arch/arc/boot/dts/axc003.dtsi
index c0a812674ce9..9a2dc39a5cff 100644
--- a/arch/arc/boot/dts/axc003.dtsi
+++ b/arch/arc/boot/dts/axc003.dtsi
@@ -62,7 +62,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <30>;
+ ngpios = <30>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arc/boot/dts/axc003_idu.dtsi b/arch/arc/boot/dts/axc003_idu.dtsi
index 67556f4b7057..f31382cb8be4 100644
--- a/arch/arc/boot/dts/axc003_idu.dtsi
+++ b/arch/arc/boot/dts/axc003_idu.dtsi
@@ -69,7 +69,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <30>;
+ ngpios = <30>;
reg = <0>;
interrupt-controller;
#interrupt-cells = <2>;
diff --git a/arch/arc/boot/dts/axs10x_mb.dtsi b/arch/arc/boot/dts/axs10x_mb.dtsi
index b64435385304..3add2fe257f8 100644
--- a/arch/arc/boot/dts/axs10x_mb.dtsi
+++ b/arch/arc/boot/dts/axs10x_mb.dtsi
@@ -250,7 +250,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <32>;
+ ngpios = <32>;
reg = <0>;
};
@@ -258,7 +258,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <8>;
+ ngpios = <8>;
reg = <1>;
};
@@ -266,7 +266,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <8>;
+ ngpios = <8>;
reg = <2>;
};
};
@@ -281,7 +281,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <30>;
+ ngpios = <30>;
reg = <0>;
};
@@ -289,7 +289,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <10>;
+ ngpios = <10>;
reg = <1>;
};
@@ -297,7 +297,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <8>;
+ ngpios = <8>;
reg = <2>;
};
};
diff --git a/arch/arc/boot/dts/hsdk.dts b/arch/arc/boot/dts/hsdk.dts
index 41b980df862b..98bb850722a4 100644
--- a/arch/arc/boot/dts/hsdk.dts
+++ b/arch/arc/boot/dts/hsdk.dts
@@ -308,7 +308,7 @@
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
#gpio-cells = <2>;
- snps,nr-gpios = <24>;
+ ngpios = <24>;
reg = <0>;
};
};
diff --git a/arch/arc/include/asm/arcregs.h b/arch/arc/include/asm/arcregs.h
index 4b13f60fe7ca..005d9e4d187a 100644
--- a/arch/arc/include/asm/arcregs.h
+++ b/arch/arc/include/asm/arcregs.h
@@ -146,7 +146,7 @@
#ifndef __ASSEMBLY__
-#include <soc/arc/aux.h>
+#include <soc/arc/arc_aux.h>
/* Helpers */
#define TO_KB(bytes) ((bytes) >> 10)
diff --git a/arch/arc/include/asm/cachetype.h b/arch/arc/include/asm/cachetype.h
new file mode 100644
index 000000000000..acd3b6cb4bf5
--- /dev/null
+++ b/arch/arc/include/asm/cachetype.h
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_ARC_CACHETYPE_H
+#define __ASM_ARC_CACHETYPE_H
+
+#define cpu_dcache_is_aliasing() false
+#define cpu_icache_is_aliasing() true
+
+#endif
diff --git a/arch/arc/include/asm/cmpxchg.h b/arch/arc/include/asm/cmpxchg.h
index 58045c898340..76f43db0890f 100644
--- a/arch/arc/include/asm/cmpxchg.h
+++ b/arch/arc/include/asm/cmpxchg.h
@@ -48,7 +48,7 @@
\
switch(sizeof((_p_))) { \
case 1: \
- _prev_ = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *)_p_, (uintptr_t)_o_, (uintptr_t)_n_); \
+ _prev_ = (__typeof__(*(ptr)))cmpxchg_emu_u8((volatile u8 *__force)_p_, (uintptr_t)_o_, (uintptr_t)_n_); \
break; \
case 4: \
_prev_ = __cmpxchg(_p_, _o_, _n_); \
diff --git a/arch/arc/include/asm/mmu-arcv2.h b/arch/arc/include/asm/mmu-arcv2.h
index d85dc0721907..41412642f279 100644
--- a/arch/arc/include/asm/mmu-arcv2.h
+++ b/arch/arc/include/asm/mmu-arcv2.h
@@ -9,7 +9,7 @@
#ifndef _ASM_ARC_MMU_ARCV2_H
#define _ASM_ARC_MMU_ARCV2_H
-#include <soc/arc/aux.h>
+#include <soc/arc/arc_aux.h>
/*
* TLB Management regs
diff --git a/arch/arc/net/bpf_jit_arcv2.c b/arch/arc/net/bpf_jit_arcv2.c
index 4458e409ca0a..6d989b6d88c6 100644
--- a/arch/arc/net/bpf_jit_arcv2.c
+++ b/arch/arc/net/bpf_jit_arcv2.c
@@ -2916,7 +2916,7 @@ bool check_jmp_32(u32 curr_off, u32 targ_off, u8 cond)
addendum = (cond == ARC_CC_AL) ? 0 : INSN_len_normal;
disp = get_displacement(curr_off + addendum, targ_off);
- if (ARC_CC_AL)
+ if (cond == ARC_CC_AL)
return is_valid_far_disp(disp);
else
return is_valid_near_disp(disp);
diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index aafebf145738..00ca7886b18e 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -264,13 +264,13 @@ stack_protector_prepare: prepare0
-mstack-protector-guard=tls \
-mstack-protector-guard-offset=$(shell \
awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}'\
- include/generated/asm-offsets.h))
+ $(objtree)/include/generated/asm-offsets.h))
else
stack_protector_prepare: prepare0
$(eval SSP_PLUGIN_CFLAGS := \
-fplugin-arg-arm_ssp_per_task_plugin-offset=$(shell \
awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}'\
- include/generated/asm-offsets.h))
+ $(objtree)/include/generated/asm-offsets.h))
$(eval KBUILD_CFLAGS += $(SSP_PLUGIN_CFLAGS))
$(eval GCC_PLUGINS_CFLAGS += $(SSP_PLUGIN_CFLAGS))
endif
diff --git a/arch/arm/common/locomo.c b/arch/arm/common/locomo.c
index 06b0e5fd54a6..cb6ef449b987 100644
--- a/arch/arm/common/locomo.c
+++ b/arch/arm/common/locomo.c
@@ -516,7 +516,7 @@ static void locomo_remove(struct platform_device *dev)
*/
static struct platform_driver locomo_device_driver = {
.probe = locomo_probe,
- .remove_new = locomo_remove,
+ .remove = locomo_remove,
#ifdef CONFIG_PM
.suspend = locomo_suspend,
.resume = locomo_resume,
diff --git a/arch/arm/common/sa1111.c b/arch/arm/common/sa1111.c
index 550978dc3c50..9846f30990f7 100644
--- a/arch/arm/common/sa1111.c
+++ b/arch/arm/common/sa1111.c
@@ -1154,7 +1154,7 @@ static struct dev_pm_ops sa1111_pm_ops = {
*/
static struct platform_driver sa1111_device_driver = {
.probe = sa1111_probe,
- .remove_new = sa1111_remove,
+ .remove = sa1111_remove,
.driver = {
.name = "sa1111",
.pm = &sa1111_pm_ops,
diff --git a/arch/arm/common/scoop.c b/arch/arm/common/scoop.c
index 9018c7240166..0b08b6621878 100644
--- a/arch/arm/common/scoop.c
+++ b/arch/arm/common/scoop.c
@@ -250,7 +250,7 @@ static void scoop_remove(struct platform_device *pdev)
static struct platform_driver scoop_driver = {
.probe = scoop_probe,
- .remove_new = scoop_remove,
+ .remove = scoop_remove,
.suspend = scoop_suspend,
.resume = scoop_resume,
.driver = {
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index 1dfae1af8e31..ef6a657c8d13 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -25,6 +25,7 @@
#include <asm/tls.h>
#include <asm/system_info.h>
#include <asm/uaccess-asm.h>
+#include <asm/kasan_def.h>
#include "entry-header.S"
#include <asm/probes.h>
@@ -561,6 +562,13 @@ ENTRY(__switch_to)
@ entries covering the vmalloc region.
@
ldr r2, [ip]
+#ifdef CONFIG_KASAN_VMALLOC
+ @ Also dummy read from the KASAN shadow memory for the new stack if we
+ @ are using KASAN
+ mov_l r2, KASAN_SHADOW_OFFSET
+ add r2, r2, ip, lsr #KASAN_SHADOW_SCALE_SHIFT
+ ldr r2, [r2]
+#endif
#endif
@ When CONFIG_THREAD_INFO_IN_TASK=n, the update of SP itself is what
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index e4fe059cd861..dc47b2312127 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -6,6 +6,7 @@ menuconfig ARCH_MXC
select CLKSRC_IMX_GPT
select GENERIC_IRQ_CHIP
select GPIOLIB
+ select PINCTRL
select PM_OPP if PM
select SOC_BUS
select SRAM
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
index b68cb86dbe4c..e898f7c2733e 100644
--- a/arch/arm/mach-imx/mmdc.c
+++ b/arch/arm/mach-imx/mmdc.c
@@ -596,7 +596,7 @@ static struct platform_driver imx_mmdc_driver = {
.of_match_table = imx_mmdc_dt_ids,
},
.probe = imx_mmdc_probe,
- .remove_new = imx_mmdc_remove,
+ .remove = imx_mmdc_remove,
};
static int __init imx_mmdc_init(void)
diff --git a/arch/arm/mach-omap1/omap-dma.c b/arch/arm/mach-omap1/omap-dma.c
index f091f78631d0..aebe5e55ff60 100644
--- a/arch/arm/mach-omap1/omap-dma.c
+++ b/arch/arm/mach-omap1/omap-dma.c
@@ -832,7 +832,7 @@ static void omap_system_dma_remove(struct platform_device *pdev)
static struct platform_driver omap_system_dma_driver = {
.probe = omap_system_dma_probe,
- .remove_new = omap_system_dma_remove,
+ .remove = omap_system_dma_remove,
.driver = {
.name = "omap_dma_system"
},
diff --git a/arch/arm/mach-pxa/sharpsl_pm.c b/arch/arm/mach-pxa/sharpsl_pm.c
index 72fa2e3fd353..0c8d9000df5a 100644
--- a/arch/arm/mach-pxa/sharpsl_pm.c
+++ b/arch/arm/mach-pxa/sharpsl_pm.c
@@ -919,7 +919,7 @@ static void sharpsl_pm_remove(struct platform_device *pdev)
static struct platform_driver sharpsl_pm_driver = {
.probe = sharpsl_pm_probe,
- .remove_new = sharpsl_pm_remove,
+ .remove = sharpsl_pm_remove,
.suspend = sharpsl_pm_suspend,
.resume = sharpsl_pm_resume,
.driver = {
diff --git a/arch/arm/mach-sa1100/jornada720_ssp.c b/arch/arm/mach-sa1100/jornada720_ssp.c
index 1956b095e699..d94810217095 100644
--- a/arch/arm/mach-sa1100/jornada720_ssp.c
+++ b/arch/arm/mach-sa1100/jornada720_ssp.c
@@ -188,7 +188,7 @@ static void jornada_ssp_remove(struct platform_device *dev)
struct platform_driver jornadassp_driver = {
.probe = jornada_ssp_probe,
- .remove_new = jornada_ssp_remove,
+ .remove = jornada_ssp_remove,
.driver = {
.name = "jornada_ssp",
},
diff --git a/arch/arm/mach-sa1100/neponset.c b/arch/arm/mach-sa1100/neponset.c
index 0ef0ebbf31ac..88fe79f0a4ed 100644
--- a/arch/arm/mach-sa1100/neponset.c
+++ b/arch/arm/mach-sa1100/neponset.c
@@ -423,7 +423,7 @@ static const struct dev_pm_ops neponset_pm_ops = {
static struct platform_driver neponset_device_driver = {
.probe = neponset_probe,
- .remove_new = neponset_remove,
+ .remove = neponset_remove,
.driver = {
.name = "neponset",
.pm = PM_OPS,
diff --git a/arch/arm/mm/ioremap.c b/arch/arm/mm/ioremap.c
index 794cfea9f9d4..89f1c97f3079 100644
--- a/arch/arm/mm/ioremap.c
+++ b/arch/arm/mm/ioremap.c
@@ -23,6 +23,7 @@
*/
#include <linux/module.h>
#include <linux/errno.h>
+#include <linux/kasan.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#include <linux/io.h>
@@ -115,16 +116,40 @@ int ioremap_page(unsigned long virt, unsigned long phys,
}
EXPORT_SYMBOL(ioremap_page);
+#ifdef CONFIG_KASAN
+static unsigned long arm_kasan_mem_to_shadow(unsigned long addr)
+{
+ return (unsigned long)kasan_mem_to_shadow((void *)addr);
+}
+#else
+static unsigned long arm_kasan_mem_to_shadow(unsigned long addr)
+{
+ return 0;
+}
+#endif
+
+static void memcpy_pgd(struct mm_struct *mm, unsigned long start,
+ unsigned long end)
+{
+ end = ALIGN(end, PGDIR_SIZE);
+ memcpy(pgd_offset(mm, start), pgd_offset_k(start),
+ sizeof(pgd_t) * (pgd_index(end) - pgd_index(start)));
+}
+
void __check_vmalloc_seq(struct mm_struct *mm)
{
int seq;
do {
- seq = atomic_read(&init_mm.context.vmalloc_seq);
- memcpy(pgd_offset(mm, VMALLOC_START),
- pgd_offset_k(VMALLOC_START),
- sizeof(pgd_t) * (pgd_index(VMALLOC_END) -
- pgd_index(VMALLOC_START)));
+ seq = atomic_read_acquire(&init_mm.context.vmalloc_seq);
+ memcpy_pgd(mm, VMALLOC_START, VMALLOC_END);
+ if (IS_ENABLED(CONFIG_KASAN_VMALLOC)) {
+ unsigned long start =
+ arm_kasan_mem_to_shadow(VMALLOC_START);
+ unsigned long end =
+ arm_kasan_mem_to_shadow(VMALLOC_END);
+ memcpy_pgd(mm, start, end);
+ }
/*
* Use a store-release so that other CPUs that observe the
* counter's new value are guaranteed to see the results of the
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index b68efe643a12..d44867fc0c5e 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -56,6 +56,34 @@ extern unsigned int VFP_arch_feroceon __alias(VFP_arch);
union vfp_state *vfp_current_hw_state[NR_CPUS];
/*
+ * Claim ownership of the VFP unit.
+ *
+ * The caller may change VFP registers until vfp_state_release() is called.
+ *
+ * local_bh_disable() is used to disable preemption and to disable VFP
+ * processing in softirq context. On PREEMPT_RT kernels local_bh_disable() is
+ * not sufficient because it only serializes soft interrupt related sections
+ * via a local lock, but stays preemptible. Disabling preemption is the right
+ * choice here as bottom half processing is always in thread context on RT
+ * kernels so it implicitly prevents bottom half processing as well.
+ */
+static void vfp_state_hold(void)
+{
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
+ local_bh_disable();
+ else
+ preempt_disable();
+}
+
+static void vfp_state_release(void)
+{
+ if (!IS_ENABLED(CONFIG_PREEMPT_RT))
+ local_bh_enable();
+ else
+ preempt_enable();
+}
+
+/*
* Is 'thread's most up to date state stored in this CPUs hardware?
* Must be called from non-preemptible context.
*/
@@ -240,7 +268,7 @@ static void vfp_panic(char *reason, u32 inst)
/*
* Process bitmask of exception conditions.
*/
-static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs)
+static int vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr)
{
int si_code = 0;
@@ -248,8 +276,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
if (exceptions == VFP_EXCEPTION_ERROR) {
vfp_panic("unhandled bounce", inst);
- vfp_raise_sigfpe(FPE_FLTINV, regs);
- return;
+ return FPE_FLTINV;
}
/*
@@ -277,8 +304,7 @@ static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_
RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF);
RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV);
- if (si_code)
- vfp_raise_sigfpe(si_code, regs);
+ return si_code;
}
/*
@@ -324,6 +350,8 @@ static u32 vfp_emulate_instruction(u32 inst, u32 fpscr, struct pt_regs *regs)
static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
{
u32 fpscr, orig_fpscr, fpsid, exceptions;
+ int si_code2 = 0;
+ int si_code = 0;
pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc);
@@ -369,8 +397,8 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
* unallocated VFP instruction but with FPSCR.IXE set and not
* on VFP subarch 1.
*/
- vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs);
- return;
+ si_code = vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr);
+ goto exit;
}
/*
@@ -394,14 +422,14 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
*/
exceptions = vfp_emulate_instruction(trigger, fpscr, regs);
if (exceptions)
- vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
+ si_code2 = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
/*
* If there isn't a second FP instruction, exit now. Note that
* the FPEXC.FP2V bit is valid only if FPEXC.EX is 1.
*/
if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V))
- return;
+ goto exit;
/*
* The barrier() here prevents fpinst2 being read
@@ -413,7 +441,13 @@ static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
emulate:
exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs);
if (exceptions)
- vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs);
+ si_code = vfp_raise_exceptions(exceptions, trigger, orig_fpscr);
+exit:
+ vfp_state_release();
+ if (si_code2)
+ vfp_raise_sigfpe(si_code2, regs);
+ if (si_code)
+ vfp_raise_sigfpe(si_code, regs);
}
static void vfp_enable(void *unused)
@@ -512,11 +546,9 @@ static inline void vfp_pm_init(void) { }
*/
void vfp_sync_hwstate(struct thread_info *thread)
{
- unsigned int cpu = get_cpu();
+ vfp_state_hold();
- local_bh_disable();
-
- if (vfp_state_in_hw(cpu, thread)) {
+ if (vfp_state_in_hw(raw_smp_processor_id(), thread)) {
u32 fpexc = fmrx(FPEXC);
/*
@@ -527,8 +559,7 @@ void vfp_sync_hwstate(struct thread_info *thread)
fmxr(FPEXC, fpexc);
}
- local_bh_enable();
- put_cpu();
+ vfp_state_release();
}
/* Ensure that the thread reloads the hardware VFP state on the next use. */
@@ -683,7 +714,7 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
if (!user_mode(regs))
return vfp_kmode_exception(regs, trigger);
- local_bh_disable();
+ vfp_state_hold();
fpexc = fmrx(FPEXC);
/*
@@ -748,6 +779,7 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
* replay the instruction that trapped.
*/
fmxr(FPEXC, fpexc);
+ vfp_state_release();
} else {
/* Check for synchronous or asynchronous exceptions */
if (!(fpexc & (FPEXC_EX | FPEXC_DEX))) {
@@ -762,17 +794,17 @@ static int vfp_support_entry(struct pt_regs *regs, u32 trigger)
if (!(fpscr & FPSCR_IXE)) {
if (!(fpscr & FPSCR_LENGTH_MASK)) {
pr_debug("not VFP\n");
- local_bh_enable();
+ vfp_state_release();
return -ENOEXEC;
}
fpexc |= FPEXC_DEX;
}
}
bounce: regs->ARM_pc += 4;
+ /* VFP_bounce() will invoke vfp_state_release() */
VFP_bounce(trigger, fpexc, regs);
}
- local_bh_enable();
return 0;
}
@@ -837,7 +869,7 @@ void kernel_neon_begin(void)
unsigned int cpu;
u32 fpexc;
- local_bh_disable();
+ vfp_state_hold();
/*
* Kernel mode NEON is only allowed outside of hardirq context with
@@ -868,7 +900,7 @@ void kernel_neon_end(void)
{
/* Disable the NEON/VFP unit. */
fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN);
- local_bh_enable();
+ vfp_state_release();
}
EXPORT_SYMBOL(kernel_neon_end);
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index d743737bf9ce..100570a048c5 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -14,7 +14,6 @@ config ARM64
select ARCH_HAS_DEBUG_WX
select ARCH_BINFMT_ELF_EXTRA_PHDRS
select ARCH_BINFMT_ELF_STATE
- select ARCH_CORRECT_STACKTRACE_ON_KRETPROBE
select ARCH_ENABLE_HUGEPAGE_MIGRATION if HUGETLB_PAGE && MIGRATION
select ARCH_ENABLE_MEMORY_HOTPLUG
select ARCH_ENABLE_MEMORY_HOTREMOVE
@@ -1236,6 +1235,17 @@ config HISILICON_ERRATUM_161600802
If unsure, say Y.
+config HISILICON_ERRATUM_162100801
+ bool "Hip09 162100801 erratum support"
+ default y
+ help
+ When enabling GICv4.1 in hip09, VMAPP will fail to clear some caches
+ during unmapping operation, which will cause some vSGIs lost.
+ To fix the issue, invalidate related vPE cache through GICR_INVALLR
+ after VMOVP.
+
+ If unsure, say Y.
+
config QCOM_FALKOR_ERRATUM_1003
bool "Falkor E1003: Incorrect translation due to ASID change"
default y
diff --git a/arch/arm64/Makefile b/arch/arm64/Makefile
index 9efd3f37c2fd..358c68565bfd 100644
--- a/arch/arm64/Makefile
+++ b/arch/arm64/Makefile
@@ -71,7 +71,7 @@ stack_protector_prepare: prepare0
-mstack-protector-guard-reg=sp_el0 \
-mstack-protector-guard-offset=$(shell \
awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}' \
- include/generated/asm-offsets.h))
+ $(objtree)/include/generated/asm-offsets.h))
endif
ifeq ($(CONFIG_ARM64_BTI_KERNEL),y)
diff --git a/arch/arm64/boot/dts/arm/fvp-base-revc.dts b/arch/arm64/boot/dts/arm/fvp-base-revc.dts
index 19973ab4ea6b..9e10d7a6b5a2 100644
--- a/arch/arm64/boot/dts/arm/fvp-base-revc.dts
+++ b/arch/arm64/boot/dts/arm/fvp-base-revc.dts
@@ -233,7 +233,7 @@
#interrupt-cells = <0x1>;
compatible = "pci-host-ecam-generic";
device_type = "pci";
- bus-range = <0x0 0x1>;
+ bus-range = <0x0 0xff>;
reg = <0x0 0x40000000 0x0 0x10000000>;
ranges = <0x2000000 0x0 0x50000000 0x0 0x50000000 0x0 0x10000000>;
interrupt-map = <0 0 0 1 &gic 0 0 GIC_SPI 168 IRQ_TYPE_LEVEL_HIGH>,
diff --git a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
index 6e5a984c1d4e..26a29e5e5078 100644
--- a/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
+++ b/arch/arm64/boot/dts/broadcom/bcm2712.dtsi
@@ -67,7 +67,7 @@
l2_cache_l0: l2-cache-l0 {
compatible = "cache";
cache-size = <0x80000>;
- cache-line-size = <128>;
+ cache-line-size = <64>;
cache-sets = <1024>; //512KiB(size)/64(line-size)=8192ways/8-way set
cache-level = <2>;
cache-unified;
@@ -91,7 +91,7 @@
l2_cache_l1: l2-cache-l1 {
compatible = "cache";
cache-size = <0x80000>;
- cache-line-size = <128>;
+ cache-line-size = <64>;
cache-sets = <1024>; //512KiB(size)/64(line-size)=8192ways/8-way set
cache-level = <2>;
cache-unified;
@@ -115,7 +115,7 @@
l2_cache_l2: l2-cache-l2 {
compatible = "cache";
cache-size = <0x80000>;
- cache-line-size = <128>;
+ cache-line-size = <64>;
cache-sets = <1024>; //512KiB(size)/64(line-size)=8192ways/8-way set
cache-level = <2>;
cache-unified;
@@ -139,7 +139,7 @@
l2_cache_l3: l2-cache-l3 {
compatible = "cache";
cache-size = <0x80000>;
- cache-line-size = <128>;
+ cache-line-size = <64>;
cache-sets = <1024>; //512KiB(size)/64(line-size)=8192ways/8-way set
cache-level = <2>;
cache-unified;
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
index ae0379fd42a9..dfc5c2f0ddef 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm-hana.dtsi
@@ -14,6 +14,7 @@
compatible = "melfas,mip4_ts";
reg = <0x34>;
interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>;
+ status = "fail-needs-probe";
};
/*
@@ -26,6 +27,7 @@
reg = <0x20>;
hid-descr-addr = <0x0020>;
interrupts-extended = <&pio 88 IRQ_TYPE_LEVEL_LOW>;
+ status = "fail-needs-probe";
};
/* Lenovo Ideapad C330 uses G2Touch touchscreen as a 2nd source touchscreen */
@@ -35,6 +37,7 @@
hid-descr-addr = <0x0001>;
interrupt-parent = <&pio>;
interrupts = <88 IRQ_TYPE_LEVEL_LOW>;
+ status = "fail-needs-probe";
};
};
@@ -47,6 +50,8 @@
trackpad2: trackpad@2c {
compatible = "hid-over-i2c";
interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&trackpad_irq>;
reg = <0x2c>;
hid-descr-addr = <0x0020>;
/*
@@ -58,6 +63,7 @@
*/
vdd-supply = <&mt6397_vgp6_reg>;
wakeup-source;
+ status = "fail-needs-probe";
};
};
@@ -82,3 +88,11 @@
};
};
};
+
+&touchscreen {
+ status = "fail-needs-probe";
+};
+
+&trackpad {
+ status = "fail-needs-probe";
+};
diff --git a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
index b4d85147b77b..eee64461421f 100644
--- a/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
+++ b/arch/arm64/boot/dts/mediatek/mt8173-elm.dtsi
@@ -358,12 +358,12 @@
&i2c4 {
clock-frequency = <400000>;
status = "okay";
- pinctrl-names = "default";
- pinctrl-0 = <&trackpad_irq>;
trackpad: trackpad@15 {
compatible = "elan,ekth3000";
interrupts-extended = <&pio 117 IRQ_TYPE_LEVEL_LOW>;
+ pinctrl-names = "default";
+ pinctrl-0 = <&trackpad_irq>;
reg = <0x15>;
vcc-supply = <&mt6397_vgp6_reg>;
wakeup-source;
diff --git a/arch/arm64/crypto/aes-ce-ccm-glue.c b/arch/arm64/crypto/aes-ce-ccm-glue.c
index a523b519700f..a2b5d6f20f4d 100644
--- a/arch/arm64/crypto/aes-ce-ccm-glue.c
+++ b/arch/arm64/crypto/aes-ce-ccm-glue.c
@@ -18,7 +18,7 @@
#include "aes-ce-setkey.h"
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
static int num_rounds(struct crypto_aes_ctx *ctx)
{
diff --git a/arch/arm64/crypto/aes-glue.c b/arch/arm64/crypto/aes-glue.c
index a147e847a5a1..b0150999743f 100644
--- a/arch/arm64/crypto/aes-glue.c
+++ b/arch/arm64/crypto/aes-glue.c
@@ -1048,7 +1048,7 @@ unregister_ciphers:
#ifdef USE_V8_CRYPTO_EXTENSIONS
module_cpu_feature_match(AES, aes_init);
-EXPORT_SYMBOL_NS(ce_aes_mac_update, CRYPTO_INTERNAL);
+EXPORT_SYMBOL_NS(ce_aes_mac_update, "CRYPTO_INTERNAL");
#else
module_init(aes_init);
EXPORT_SYMBOL(neon_aes_ecb_encrypt);
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index 201a46efd918..cbbf70e0f204 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -44,6 +44,8 @@ cpucap_is_possible(const unsigned int cap)
return IS_ENABLED(CONFIG_ARM64_TLB_RANGE);
case ARM64_HAS_S1POE:
return IS_ENABLED(CONFIG_ARM64_POE);
+ case ARM64_HAS_GCS:
+ return IS_ENABLED(CONFIG_ARM64_GCS);
case ARM64_UNMAP_KERNEL_AT_EL0:
return IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0);
case ARM64_WORKAROUND_843419:
diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h
index b64e49bd9d10..8b4e5a3cd24c 100644
--- a/arch/arm64/include/asm/cpufeature.h
+++ b/arch/arm64/include/asm/cpufeature.h
@@ -847,8 +847,7 @@ static inline bool system_supports_poe(void)
static inline bool system_supports_gcs(void)
{
- return IS_ENABLED(CONFIG_ARM64_GCS) &&
- alternative_has_cap_unlikely(ARM64_HAS_GCS);
+ return alternative_has_cap_unlikely(ARM64_HAS_GCS);
}
static inline bool system_supports_haft(void)
diff --git a/arch/arm64/include/asm/el2_setup.h b/arch/arm64/include/asm/el2_setup.h
index 85ef966c08cd..4ef52d7245bb 100644
--- a/arch/arm64/include/asm/el2_setup.h
+++ b/arch/arm64/include/asm/el2_setup.h
@@ -87,7 +87,7 @@
1 << PMSCR_EL2_PA_SHIFT)
msr_s SYS_PMSCR_EL2, x0 // addresses and physical counter
.Lskip_spe_el2_\@:
- mov x0, #(MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT)
+ mov x0, #MDCR_EL2_E2PB_MASK
orr x2, x2, x0 // If we don't have VHE, then
// use EL1&0 translation.
@@ -100,7 +100,7 @@
and x0, x0, TRBIDR_EL1_P
cbnz x0, .Lskip_trace_\@ // If TRBE is available at EL2
- mov x0, #(MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT)
+ mov x0, #MDCR_EL2_E2TB_MASK
orr x2, x2, x0 // allow the EL1&0 translation
// to own it.
diff --git a/arch/arm64/include/asm/mman.h b/arch/arm64/include/asm/mman.h
index 1d53022fc7e1..21df8bbd2668 100644
--- a/arch/arm64/include/asm/mman.h
+++ b/arch/arm64/include/asm/mman.h
@@ -7,6 +7,7 @@
#ifndef BUILD_VDSO
#include <linux/compiler.h>
#include <linux/fs.h>
+#include <linux/hugetlb.h>
#include <linux/shmem_fs.h>
#include <linux/types.h>
@@ -44,7 +45,7 @@ static inline unsigned long arch_calc_vm_flag_bits(struct file *file,
if (system_supports_mte()) {
if (flags & (MAP_ANONYMOUS | MAP_HUGETLB))
return VM_MTE_ALLOWED;
- if (shmem_file(file))
+ if (shmem_file(file) || is_file_hugepages(file))
return VM_MTE_ALLOWED;
}
diff --git a/arch/arm64/kernel/hyp-stub.S b/arch/arm64/kernel/hyp-stub.S
index 65f76064c86b..ae990da1eae5 100644
--- a/arch/arm64/kernel/hyp-stub.S
+++ b/arch/arm64/kernel/hyp-stub.S
@@ -114,8 +114,8 @@ SYM_CODE_START_LOCAL(__finalise_el2)
// Use EL2 translations for SPE & TRBE and disable access from EL1
mrs x0, mdcr_el2
- bic x0, x0, #(MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT)
- bic x0, x0, #(MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT)
+ bic x0, x0, #MDCR_EL2_E2PB_MASK
+ bic x0, x0, #MDCR_EL2_E2TB_MASK
msr mdcr_el2, x0
// Transfer the MM state from EL1 to EL2
diff --git a/arch/arm64/kernel/patching.c b/arch/arm64/kernel/patching.c
index 7f99723fbb8c..1041bc67a3ee 100644
--- a/arch/arm64/kernel/patching.c
+++ b/arch/arm64/kernel/patching.c
@@ -30,20 +30,17 @@ static bool is_image_text(unsigned long addr)
static void __kprobes *patch_map(void *addr, int fixmap)
{
- unsigned long uintaddr = (uintptr_t) addr;
- bool image = is_image_text(uintaddr);
- struct page *page;
-
- if (image)
- page = phys_to_page(__pa_symbol(addr));
- else if (IS_ENABLED(CONFIG_EXECMEM))
- page = vmalloc_to_page(addr);
- else
- return addr;
-
- BUG_ON(!page);
- return (void *)set_fixmap_offset(fixmap, page_to_phys(page) +
- (uintaddr & ~PAGE_MASK));
+ phys_addr_t phys;
+
+ if (is_image_text((unsigned long)addr)) {
+ phys = __pa_symbol(addr);
+ } else {
+ struct page *page = vmalloc_to_page(addr);
+ BUG_ON(!page);
+ phys = page_to_phys(page) + offset_in_page(addr);
+ }
+
+ return (void *)set_fixmap_offset(fixmap, phys);
}
static void __kprobes patch_unmap(int fixmap)
diff --git a/arch/arm64/kernel/ptrace.c b/arch/arm64/kernel/ptrace.c
index e4437f62a2cd..f79b0d5f71ac 100644
--- a/arch/arm64/kernel/ptrace.c
+++ b/arch/arm64/kernel/ptrace.c
@@ -720,6 +720,8 @@ static int fpmr_set(struct task_struct *target, const struct user_regset *regset
if (!system_supports_fpmr())
return -EINVAL;
+ fpmr = target->thread.uw.fpmr;
+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &fpmr, 0, count);
if (ret)
return ret;
@@ -1427,7 +1429,7 @@ static int tagged_addr_ctrl_get(struct task_struct *target,
{
long ctrl = get_tagged_addr_ctrl(target);
- if (IS_ERR_VALUE(ctrl))
+ if (WARN_ON_ONCE(IS_ERR_VALUE(ctrl)))
return ctrl;
return membuf_write(&to, &ctrl, sizeof(ctrl));
@@ -1441,6 +1443,10 @@ static int tagged_addr_ctrl_set(struct task_struct *target, const struct
int ret;
long ctrl;
+ ctrl = get_tagged_addr_ctrl(target);
+ if (WARN_ON_ONCE(IS_ERR_VALUE(ctrl)))
+ return ctrl;
+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, 0, -1);
if (ret)
return ret;
@@ -1472,6 +1478,8 @@ static int poe_set(struct task_struct *target, const struct
if (!system_supports_poe())
return -EINVAL;
+ ctrl = target->thread.por_el0;
+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &ctrl, 0, -1);
if (ret)
return ret;
@@ -1483,6 +1491,22 @@ static int poe_set(struct task_struct *target, const struct
#endif
#ifdef CONFIG_ARM64_GCS
+static void task_gcs_to_user(struct user_gcs *user_gcs,
+ const struct task_struct *target)
+{
+ user_gcs->features_enabled = target->thread.gcs_el0_mode;
+ user_gcs->features_locked = target->thread.gcs_el0_locked;
+ user_gcs->gcspr_el0 = target->thread.gcspr_el0;
+}
+
+static void task_gcs_from_user(struct task_struct *target,
+ const struct user_gcs *user_gcs)
+{
+ target->thread.gcs_el0_mode = user_gcs->features_enabled;
+ target->thread.gcs_el0_locked = user_gcs->features_locked;
+ target->thread.gcspr_el0 = user_gcs->gcspr_el0;
+}
+
static int gcs_get(struct task_struct *target,
const struct user_regset *regset,
struct membuf to)
@@ -1495,9 +1519,7 @@ static int gcs_get(struct task_struct *target,
if (target == current)
gcs_preserve_current_state();
- user_gcs.features_enabled = target->thread.gcs_el0_mode;
- user_gcs.features_locked = target->thread.gcs_el0_locked;
- user_gcs.gcspr_el0 = target->thread.gcspr_el0;
+ task_gcs_to_user(&user_gcs, target);
return membuf_write(&to, &user_gcs, sizeof(user_gcs));
}
@@ -1513,6 +1535,8 @@ static int gcs_set(struct task_struct *target, const struct
if (!system_supports_gcs())
return -EINVAL;
+ task_gcs_to_user(&user_gcs, target);
+
ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, &user_gcs, 0, -1);
if (ret)
return ret;
@@ -1520,9 +1544,7 @@ static int gcs_set(struct task_struct *target, const struct
if (user_gcs.features_enabled & ~PR_SHADOW_STACK_SUPPORTED_STATUS_MASK)
return -EINVAL;
- target->thread.gcs_el0_mode = user_gcs.features_enabled;
- target->thread.gcs_el0_locked = user_gcs.features_locked;
- target->thread.gcspr_el0 = user_gcs.gcspr_el0;
+ task_gcs_from_user(target, &user_gcs);
return 0;
}
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index 14ac6fdb872b..99ea26d400ff 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -36,15 +36,8 @@
#include <asm/traps.h>
#include <asm/vdso.h>
-#ifdef CONFIG_ARM64_GCS
#define GCS_SIGNAL_CAP(addr) (((unsigned long)addr) & GCS_CAP_ADDR_MASK)
-static bool gcs_signal_cap_valid(u64 addr, u64 val)
-{
- return val == GCS_SIGNAL_CAP(addr);
-}
-#endif
-
/*
* Do a signal return; undo the signal stack. These are aligned to 128-bit.
*/
@@ -1062,8 +1055,7 @@ static int restore_sigframe(struct pt_regs *regs,
#ifdef CONFIG_ARM64_GCS
static int gcs_restore_signal(void)
{
- unsigned long __user *gcspr_el0;
- u64 cap;
+ u64 gcspr_el0, cap;
int ret;
if (!system_supports_gcs())
@@ -1072,7 +1064,7 @@ static int gcs_restore_signal(void)
if (!(current->thread.gcs_el0_mode & PR_SHADOW_STACK_ENABLE))
return 0;
- gcspr_el0 = (unsigned long __user *)read_sysreg_s(SYS_GCSPR_EL0);
+ gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0);
/*
* Ensure that any changes to the GCS done via GCS operations
@@ -1087,22 +1079,23 @@ static int gcs_restore_signal(void)
* then faults will be generated on GCS operations - the main
* concern is to protect GCS pages.
*/
- ret = copy_from_user(&cap, gcspr_el0, sizeof(cap));
+ ret = copy_from_user(&cap, (unsigned long __user *)gcspr_el0,
+ sizeof(cap));
if (ret)
return -EFAULT;
/*
* Check that the cap is the actual GCS before replacing it.
*/
- if (!gcs_signal_cap_valid((u64)gcspr_el0, cap))
+ if (cap != GCS_SIGNAL_CAP(gcspr_el0))
return -EINVAL;
/* Invalidate the token to prevent reuse */
- put_user_gcs(0, (__user void*)gcspr_el0, &ret);
+ put_user_gcs(0, (unsigned long __user *)gcspr_el0, &ret);
if (ret != 0)
return -EFAULT;
- write_sysreg_s(gcspr_el0 + 1, SYS_GCSPR_EL0);
+ write_sysreg_s(gcspr_el0 + 8, SYS_GCSPR_EL0);
return 0;
}
@@ -1421,7 +1414,7 @@ static int get_sigframe(struct rt_sigframe_user_layout *user,
static int gcs_signal_entry(__sigrestore_t sigtramp, struct ksignal *ksig)
{
- unsigned long __user *gcspr_el0;
+ u64 gcspr_el0;
int ret = 0;
if (!system_supports_gcs())
@@ -1434,18 +1427,20 @@ static int gcs_signal_entry(__sigrestore_t sigtramp, struct ksignal *ksig)
* We are entering a signal handler, current register state is
* active.
*/
- gcspr_el0 = (unsigned long __user *)read_sysreg_s(SYS_GCSPR_EL0);
+ gcspr_el0 = read_sysreg_s(SYS_GCSPR_EL0);
/*
* Push a cap and the GCS entry for the trampoline onto the GCS.
*/
- put_user_gcs((unsigned long)sigtramp, gcspr_el0 - 2, &ret);
- put_user_gcs(GCS_SIGNAL_CAP(gcspr_el0 - 1), gcspr_el0 - 1, &ret);
+ put_user_gcs((unsigned long)sigtramp,
+ (unsigned long __user *)(gcspr_el0 - 16), &ret);
+ put_user_gcs(GCS_SIGNAL_CAP(gcspr_el0 - 8),
+ (unsigned long __user *)(gcspr_el0 - 8), &ret);
if (ret != 0)
return ret;
- gcspr_el0 -= 2;
- write_sysreg_s((unsigned long)gcspr_el0, SYS_GCSPR_EL0);
+ gcspr_el0 -= 16;
+ write_sysreg_s(gcspr_el0, SYS_GCSPR_EL0);
return 0;
}
@@ -1462,10 +1457,33 @@ static int setup_return(struct pt_regs *regs, struct ksignal *ksig,
struct rt_sigframe_user_layout *user, int usig)
{
__sigrestore_t sigtramp;
+ int err;
+
+ if (ksig->ka.sa.sa_flags & SA_RESTORER)
+ sigtramp = ksig->ka.sa.sa_restorer;
+ else
+ sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
+
+ err = gcs_signal_entry(sigtramp, ksig);
+ if (err)
+ return err;
+
+ /*
+ * We must not fail from this point onwards. We are going to update
+ * registers, including SP, in order to invoke the signal handler. If
+ * we failed and attempted to deliver a nested SIGSEGV to a handler
+ * after that point, the subsequent sigreturn would end up restoring
+ * the (partial) state for the original signal handler.
+ */
regs->regs[0] = usig;
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
+ regs->regs[1] = (unsigned long)&user->sigframe->info;
+ regs->regs[2] = (unsigned long)&user->sigframe->uc;
+ }
regs->sp = (unsigned long)user->sigframe;
regs->regs[29] = (unsigned long)&user->next_frame->fp;
+ regs->regs[30] = (unsigned long)sigtramp;
regs->pc = (unsigned long)ksig->ka.sa.sa_handler;
/*
@@ -1506,14 +1524,7 @@ static int setup_return(struct pt_regs *regs, struct ksignal *ksig,
sme_smstop();
}
- if (ksig->ka.sa.sa_flags & SA_RESTORER)
- sigtramp = ksig->ka.sa.sa_restorer;
- else
- sigtramp = VDSO_SYMBOL(current->mm->context.vdso, sigtramp);
-
- regs->regs[30] = (unsigned long)sigtramp;
-
- return gcs_signal_entry(sigtramp, ksig);
+ return 0;
}
static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
@@ -1537,14 +1548,16 @@ static int setup_rt_frame(int usig, struct ksignal *ksig, sigset_t *set,
err |= __save_altstack(&frame->uc.uc_stack, regs->sp);
err |= setup_sigframe(&user, regs, set, &ua_state);
- if (err == 0) {
+ if (ksig->ka.sa.sa_flags & SA_SIGINFO)
+ err |= copy_siginfo_to_user(&frame->info, &ksig->info);
+
+ if (err == 0)
err = setup_return(regs, ksig, &user, usig);
- if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
- err |= copy_siginfo_to_user(&frame->info, &ksig->info);
- regs->regs[1] = (unsigned long)&frame->info;
- regs->regs[2] = (unsigned long)&frame->uc;
- }
- }
+
+ /*
+ * We must not fail if setup_return() succeeded - see comment at the
+ * beginning of setup_return().
+ */
if (err == 0)
set_handler_user_access_state();
diff --git a/arch/arm64/kernel/stacktrace.c b/arch/arm64/kernel/stacktrace.c
index caef85462acb..1d9d51d7627f 100644
--- a/arch/arm64/kernel/stacktrace.c
+++ b/arch/arm64/kernel/stacktrace.c
@@ -26,7 +26,6 @@ enum kunwind_source {
KUNWIND_SOURCE_CALLER,
KUNWIND_SOURCE_TASK,
KUNWIND_SOURCE_REGS_PC,
- KUNWIND_SOURCE_REGS_LR,
};
union unwind_flags {
@@ -138,8 +137,10 @@ kunwind_recover_return_address(struct kunwind_state *state)
orig_pc = ftrace_graph_ret_addr(state->task, &state->graph_idx,
state->common.pc,
(void *)state->common.fp);
- if (WARN_ON_ONCE(state->common.pc == orig_pc))
+ if (state->common.pc == orig_pc) {
+ WARN_ON_ONCE(state->task == current);
return -EINVAL;
+ }
state->common.pc = orig_pc;
state->flags.fgraph = 1;
}
@@ -178,23 +179,8 @@ int kunwind_next_regs_pc(struct kunwind_state *state)
state->regs = regs;
state->common.pc = regs->pc;
state->common.fp = regs->regs[29];
- state->source = KUNWIND_SOURCE_REGS_PC;
- return 0;
-}
-
-static __always_inline int
-kunwind_next_regs_lr(struct kunwind_state *state)
-{
- /*
- * The stack for the regs was consumed by kunwind_next_regs_pc(), so we
- * cannot consume that again here, but we know the regs are safe to
- * access.
- */
- state->common.pc = state->regs->regs[30];
- state->common.fp = state->regs->regs[29];
state->regs = NULL;
- state->source = KUNWIND_SOURCE_REGS_LR;
-
+ state->source = KUNWIND_SOURCE_REGS_PC;
return 0;
}
@@ -215,12 +201,12 @@ kunwind_next_frame_record_meta(struct kunwind_state *state)
case FRAME_META_TYPE_FINAL:
if (meta == &task_pt_regs(tsk)->stackframe)
return -ENOENT;
- WARN_ON_ONCE(1);
+ WARN_ON_ONCE(tsk == current);
return -EINVAL;
case FRAME_META_TYPE_PT_REGS:
return kunwind_next_regs_pc(state);
default:
- WARN_ON_ONCE(1);
+ WARN_ON_ONCE(tsk == current);
return -EINVAL;
}
}
@@ -274,11 +260,8 @@ kunwind_next(struct kunwind_state *state)
case KUNWIND_SOURCE_FRAME:
case KUNWIND_SOURCE_CALLER:
case KUNWIND_SOURCE_TASK:
- case KUNWIND_SOURCE_REGS_LR:
- err = kunwind_next_frame_record(state);
- break;
case KUNWIND_SOURCE_REGS_PC:
- err = kunwind_next_regs_lr(state);
+ err = kunwind_next_frame_record(state);
break;
default:
err = -EINVAL;
@@ -436,7 +419,6 @@ static const char *state_source_string(const struct kunwind_state *state)
case KUNWIND_SOURCE_CALLER: return "C";
case KUNWIND_SOURCE_TASK: return "T";
case KUNWIND_SOURCE_REGS_PC: return "P";
- case KUNWIND_SOURCE_REGS_LR: return "L";
default: return "U";
}
}
diff --git a/arch/arm64/kvm/at.c b/arch/arm64/kvm/at.c
index 8c5d7990e5b3..3d7eb395e33d 100644
--- a/arch/arm64/kvm/at.c
+++ b/arch/arm64/kvm/at.c
@@ -739,8 +739,15 @@ static u64 compute_par_s12(struct kvm_vcpu *vcpu, u64 s1_par,
final_attr = s1_parattr;
break;
default:
- /* MemAttr[2]=0, Device from S2 */
- final_attr = s2_memattr & GENMASK(1,0) << 2;
+ /*
+ * MemAttr[2]=0, Device from S2.
+ *
+ * FWB does not influence the way that stage 1
+ * memory types and attributes are combined
+ * with stage 2 Device type and attributes.
+ */
+ final_attr = min(s2_memattr_to_attr(s2_memattr),
+ s1_parattr);
}
} else {
/* Combination of R_HMNDG, R_TNHFM and R_GQFSF */
diff --git a/arch/arm64/kvm/hyp/nvhe/pkvm.c b/arch/arm64/kvm/hyp/nvhe/pkvm.c
index 01616c39a810..071993c16de8 100644
--- a/arch/arm64/kvm/hyp/nvhe/pkvm.c
+++ b/arch/arm64/kvm/hyp/nvhe/pkvm.c
@@ -126,7 +126,7 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
/* Trap SPE */
if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_PMSVer), feature_ids)) {
mdcr_set |= MDCR_EL2_TPMS;
- mdcr_clear |= MDCR_EL2_E2PB_MASK << MDCR_EL2_E2PB_SHIFT;
+ mdcr_clear |= MDCR_EL2_E2PB_MASK;
}
/* Trap Trace Filter */
@@ -143,7 +143,7 @@ static void pvm_init_traps_aa64dfr0(struct kvm_vcpu *vcpu)
/* Trap External Trace */
if (!FIELD_GET(ARM64_FEATURE_MASK(ID_AA64DFR0_EL1_ExtTrcBuff), feature_ids))
- mdcr_clear |= MDCR_EL2_E2TB_MASK << MDCR_EL2_E2TB_SHIFT;
+ mdcr_clear |= MDCR_EL2_E2TB_MASK;
vcpu->arch.mdcr_el2 |= mdcr_set;
vcpu->arch.mdcr_el2 &= ~mdcr_clear;
diff --git a/arch/arm64/kvm/nested.c b/arch/arm64/kvm/nested.c
index aeaa6017ffd8..9b36218b48de 100644
--- a/arch/arm64/kvm/nested.c
+++ b/arch/arm64/kvm/nested.c
@@ -951,7 +951,7 @@ u64 kvm_vcpu_apply_reg_masks(const struct kvm_vcpu *vcpu,
return v;
}
-static void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1)
+static __always_inline void set_sysreg_masks(struct kvm *kvm, int sr, u64 res0, u64 res1)
{
int i = sr - __SANITISED_REG_START__;
diff --git a/arch/arm64/kvm/pmu-emul.c b/arch/arm64/kvm/pmu-emul.c
index 8ad62284fa23..456102bc0b55 100644
--- a/arch/arm64/kvm/pmu-emul.c
+++ b/arch/arm64/kvm/pmu-emul.c
@@ -274,12 +274,23 @@ void kvm_pmu_vcpu_destroy(struct kvm_vcpu *vcpu)
irq_work_sync(&vcpu->arch.pmu.overflow_work);
}
-bool kvm_pmu_counter_is_hyp(struct kvm_vcpu *vcpu, unsigned int idx)
+static u64 kvm_pmu_hyp_counter_mask(struct kvm_vcpu *vcpu)
{
- unsigned int hpmn;
+ unsigned int hpmn, n;
- if (!vcpu_has_nv(vcpu) || idx == ARMV8_PMU_CYCLE_IDX)
- return false;
+ if (!vcpu_has_nv(vcpu))
+ return 0;
+
+ hpmn = SYS_FIELD_GET(MDCR_EL2, HPMN, __vcpu_sys_reg(vcpu, MDCR_EL2));
+ n = vcpu->kvm->arch.pmcr_n;
+
+ /*
+ * Programming HPMN to a value greater than PMCR_EL0.N is
+ * CONSTRAINED UNPREDICTABLE. Make the implementation choice that an
+ * UNKNOWN number of counters (in our case, zero) are reserved for EL2.
+ */
+ if (hpmn >= n)
+ return 0;
/*
* Programming HPMN=0 is CONSTRAINED UNPREDICTABLE if FEAT_HPMN0 isn't
@@ -288,20 +299,22 @@ bool kvm_pmu_counter_is_hyp(struct kvm_vcpu *vcpu, unsigned int idx)
* implementation choice that all counters are included in the second
* range reserved for EL2/EL3.
*/
- hpmn = SYS_FIELD_GET(MDCR_EL2, HPMN, __vcpu_sys_reg(vcpu, MDCR_EL2));
- return idx >= hpmn;
+ return GENMASK(n - 1, hpmn);
+}
+
+bool kvm_pmu_counter_is_hyp(struct kvm_vcpu *vcpu, unsigned int idx)
+{
+ return kvm_pmu_hyp_counter_mask(vcpu) & BIT(idx);
}
u64 kvm_pmu_accessible_counter_mask(struct kvm_vcpu *vcpu)
{
u64 mask = kvm_pmu_implemented_counter_mask(vcpu);
- u64 hpmn;
if (!vcpu_has_nv(vcpu) || vcpu_is_el2(vcpu))
return mask;
- hpmn = SYS_FIELD_GET(MDCR_EL2, HPMN, __vcpu_sys_reg(vcpu, MDCR_EL2));
- return mask & ~GENMASK(vcpu->kvm->arch.pmcr_n - 1, hpmn);
+ return mask & ~kvm_pmu_hyp_counter_mask(vcpu);
}
u64 kvm_pmu_implemented_counter_mask(struct kvm_vcpu *vcpu)
@@ -375,15 +388,30 @@ void kvm_pmu_disable_counter_mask(struct kvm_vcpu *vcpu, u64 val)
}
}
-static u64 kvm_pmu_overflow_status(struct kvm_vcpu *vcpu)
+/*
+ * Returns the PMU overflow state, which is true if there exists an event
+ * counter where the values of the global enable control, PMOVSSET_EL0[n], and
+ * PMINTENSET_EL1[n] are all 1.
+ */
+static bool kvm_pmu_overflow_status(struct kvm_vcpu *vcpu)
{
- u64 reg = 0;
+ u64 reg = __vcpu_sys_reg(vcpu, PMOVSSET_EL0);
- if ((kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E)) {
- reg = __vcpu_sys_reg(vcpu, PMOVSSET_EL0);
- reg &= __vcpu_sys_reg(vcpu, PMCNTENSET_EL0);
- reg &= __vcpu_sys_reg(vcpu, PMINTENSET_EL1);
- }
+ reg &= __vcpu_sys_reg(vcpu, PMINTENSET_EL1);
+
+ /*
+ * PMCR_EL0.E is the global enable control for event counters available
+ * to EL0 and EL1.
+ */
+ if (!(kvm_vcpu_read_pmcr(vcpu) & ARMV8_PMU_PMCR_E))
+ reg &= kvm_pmu_hyp_counter_mask(vcpu);
+
+ /*
+ * Otherwise, MDCR_EL2.HPME is the global enable control for event
+ * counters reserved for EL2.
+ */
+ if (!(vcpu_read_sys_reg(vcpu, MDCR_EL2) & MDCR_EL2_HPME))
+ reg &= ~kvm_pmu_hyp_counter_mask(vcpu);
return reg;
}
@@ -396,7 +424,7 @@ static void kvm_pmu_update_state(struct kvm_vcpu *vcpu)
if (!kvm_vcpu_has_pmu(vcpu))
return;
- overflow = !!kvm_pmu_overflow_status(vcpu);
+ overflow = kvm_pmu_overflow_status(vcpu);
if (pmu->irq_level == overflow)
return;
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 83c6b4a07ef5..e2a5c2918d9e 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -2618,7 +2618,8 @@ static const struct sys_reg_desc sys_reg_descs[] = {
ID_WRITABLE(ID_AA64MMFR0_EL1, ~(ID_AA64MMFR0_EL1_RES0 |
ID_AA64MMFR0_EL1_TGRAN4_2 |
ID_AA64MMFR0_EL1_TGRAN64_2 |
- ID_AA64MMFR0_EL1_TGRAN16_2)),
+ ID_AA64MMFR0_EL1_TGRAN16_2 |
+ ID_AA64MMFR0_EL1_ASIDBITS)),
ID_WRITABLE(ID_AA64MMFR1_EL1, ~(ID_AA64MMFR1_EL1_RES0 |
ID_AA64MMFR1_EL1_HCX |
ID_AA64MMFR1_EL1_TWED |
diff --git a/arch/arm64/kvm/vgic/vgic-debug.c b/arch/arm64/kvm/vgic/vgic-debug.c
index e1397ab2072a..afb018528bc3 100644
--- a/arch/arm64/kvm/vgic/vgic-debug.c
+++ b/arch/arm64/kvm/vgic/vgic-debug.c
@@ -287,7 +287,10 @@ static int vgic_debug_show(struct seq_file *s, void *v)
* Expect this to succeed, as iter_mark_lpis() takes a reference on
* every LPI to be visited.
*/
- irq = vgic_get_irq(kvm, vcpu, iter->intid);
+ if (iter->intid < VGIC_NR_PRIVATE_IRQS)
+ irq = vgic_get_vcpu_irq(vcpu, iter->intid);
+ else
+ irq = vgic_get_irq(kvm, iter->intid);
if (WARN_ON_ONCE(!irq))
return -EINVAL;
diff --git a/arch/arm64/kvm/vgic/vgic-init.c b/arch/arm64/kvm/vgic/vgic-init.c
index 48c952563e85..bc7e22ab5d81 100644
--- a/arch/arm64/kvm/vgic/vgic-init.c
+++ b/arch/arm64/kvm/vgic/vgic-init.c
@@ -322,7 +322,7 @@ int vgic_init(struct kvm *kvm)
goto out;
for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
- struct vgic_irq *irq = vgic_get_irq(kvm, vcpu, i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, i);
switch (dist->vgic_model) {
case KVM_DEV_TYPE_ARM_VGIC_V3:
diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c
index 198296933e7e..fb96802799c6 100644
--- a/arch/arm64/kvm/vgic/vgic-its.c
+++ b/arch/arm64/kvm/vgic/vgic-its.c
@@ -31,6 +31,41 @@ static int vgic_its_commit_v0(struct vgic_its *its);
static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
struct kvm_vcpu *filter_vcpu, bool needs_inv);
+#define vgic_its_read_entry_lock(i, g, valp, t) \
+ ({ \
+ int __sz = vgic_its_get_abi(i)->t##_esz; \
+ struct kvm *__k = (i)->dev->kvm; \
+ int __ret; \
+ \
+ BUILD_BUG_ON(NR_ITS_ABIS == 1 && \
+ sizeof(*(valp)) != ABI_0_ESZ); \
+ if (NR_ITS_ABIS > 1 && \
+ KVM_BUG_ON(__sz != sizeof(*(valp)), __k)) \
+ __ret = -EINVAL; \
+ else \
+ __ret = kvm_read_guest_lock(__k, (g), \
+ valp, __sz); \
+ __ret; \
+ })
+
+#define vgic_its_write_entry_lock(i, g, val, t) \
+ ({ \
+ int __sz = vgic_its_get_abi(i)->t##_esz; \
+ struct kvm *__k = (i)->dev->kvm; \
+ typeof(val) __v = (val); \
+ int __ret; \
+ \
+ BUILD_BUG_ON(NR_ITS_ABIS == 1 && \
+ sizeof(__v) != ABI_0_ESZ); \
+ if (NR_ITS_ABIS > 1 && \
+ KVM_BUG_ON(__sz != sizeof(__v), __k)) \
+ __ret = -EINVAL; \
+ else \
+ __ret = vgic_write_guest_lock(__k, (g), \
+ &__v, __sz); \
+ __ret; \
+ })
+
/*
* Creates a new (reference to a) struct vgic_irq for a given LPI.
* If this LPI is already mapped on another ITS, we increase its refcount
@@ -42,7 +77,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
struct kvm_vcpu *vcpu)
{
struct vgic_dist *dist = &kvm->arch.vgic;
- struct vgic_irq *irq = vgic_get_irq(kvm, NULL, intid), *oldirq;
+ struct vgic_irq *irq = vgic_get_irq(kvm, intid), *oldirq;
unsigned long flags;
int ret;
@@ -419,7 +454,7 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
last_byte_offset = byte_offset;
}
- irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+ irq = vgic_get_irq(vcpu->kvm, intid);
if (!irq)
continue;
@@ -573,12 +608,22 @@ static void vgic_its_cache_translation(struct kvm *kvm, struct vgic_its *its,
lockdep_assert_held(&its->its_lock);
vgic_get_irq_kref(irq);
+ old = xa_store(&its->translation_cache, cache_key, irq, GFP_KERNEL_ACCOUNT);
+
+ /*
+ * Put the reference taken on @irq if the store fails. Intentionally do
+ * not return the error as the translation cache is best effort.
+ */
+ if (xa_is_err(old)) {
+ vgic_put_irq(kvm, irq);
+ return;
+ }
+
/*
* We could have raced with another CPU caching the same
* translation behind our back, ensure we don't leak a
* reference if that is the case.
*/
- old = xa_store(&its->translation_cache, cache_key, irq, GFP_KERNEL_ACCOUNT);
if (old)
vgic_put_irq(kvm, old);
}
@@ -794,7 +839,7 @@ static int vgic_its_cmd_handle_discard(struct kvm *kvm, struct vgic_its *its,
its_free_ite(kvm, ite);
- return vgic_its_write_entry_lock(its, gpa, 0, ite_esz);
+ return vgic_its_write_entry_lock(its, gpa, 0ULL, ite);
}
return E_ITS_DISCARD_UNMAPPED_INTERRUPT;
@@ -1143,7 +1188,6 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
bool valid = its_cmd_get_validbit(its_cmd);
u8 num_eventid_bits = its_cmd_get_size(its_cmd);
gpa_t itt_addr = its_cmd_get_ittaddr(its_cmd);
- int dte_esz = vgic_its_get_abi(its)->dte_esz;
struct its_device *device;
gpa_t gpa;
@@ -1168,7 +1212,7 @@ static int vgic_its_cmd_handle_mapd(struct kvm *kvm, struct vgic_its *its,
* is an error, so we are done in any case.
*/
if (!valid)
- return vgic_its_write_entry_lock(its, gpa, 0, dte_esz);
+ return vgic_its_write_entry_lock(its, gpa, 0ULL, dte);
device = vgic_its_alloc_device(its, device_id, itt_addr,
num_eventid_bits);
@@ -1288,7 +1332,7 @@ int vgic_its_invall(struct kvm_vcpu *vcpu)
unsigned long intid;
xa_for_each(&dist->lpi_xa, intid, irq) {
- irq = vgic_get_irq(kvm, NULL, intid);
+ irq = vgic_get_irq(kvm, intid);
if (!irq)
continue;
@@ -1354,7 +1398,7 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
return 0;
xa_for_each(&dist->lpi_xa, intid, irq) {
- irq = vgic_get_irq(kvm, NULL, intid);
+ irq = vgic_get_irq(kvm, intid);
if (!irq)
continue;
@@ -2090,7 +2134,7 @@ static int scan_its_table(struct vgic_its *its, gpa_t base, int size, u32 esz,
* vgic_its_save_ite - Save an interrupt translation entry at @gpa
*/
static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
- struct its_ite *ite, gpa_t gpa, int ite_esz)
+ struct its_ite *ite, gpa_t gpa)
{
u32 next_offset;
u64 val;
@@ -2101,7 +2145,7 @@ static int vgic_its_save_ite(struct vgic_its *its, struct its_device *dev,
ite->collection->collection_id;
val = cpu_to_le64(val);
- return vgic_its_write_entry_lock(its, gpa, val, ite_esz);
+ return vgic_its_write_entry_lock(its, gpa, val, ite);
}
/**
@@ -2201,7 +2245,7 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
if (ite->irq->hw && !kvm_vgic_global_state.has_gicv4_1)
return -EACCES;
- ret = vgic_its_save_ite(its, device, ite, gpa, ite_esz);
+ ret = vgic_its_save_ite(its, device, ite, gpa);
if (ret)
return ret;
}
@@ -2240,10 +2284,9 @@ static int vgic_its_restore_itt(struct vgic_its *its, struct its_device *dev)
* @its: ITS handle
* @dev: ITS device
* @ptr: GPA
- * @dte_esz: device table entry size
*/
static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
- gpa_t ptr, int dte_esz)
+ gpa_t ptr)
{
u64 val, itt_addr_field;
u32 next_offset;
@@ -2256,7 +2299,7 @@ static int vgic_its_save_dte(struct vgic_its *its, struct its_device *dev,
(dev->num_eventid_bits - 1));
val = cpu_to_le64(val);
- return vgic_its_write_entry_lock(its, ptr, val, dte_esz);
+ return vgic_its_write_entry_lock(its, ptr, val, dte);
}
/**
@@ -2332,10 +2375,8 @@ static int vgic_its_device_cmp(void *priv, const struct list_head *a,
*/
static int vgic_its_save_device_tables(struct vgic_its *its)
{
- const struct vgic_its_abi *abi = vgic_its_get_abi(its);
u64 baser = its->baser_device_table;
struct its_device *dev;
- int dte_esz = abi->dte_esz;
if (!(baser & GITS_BASER_VALID))
return 0;
@@ -2354,7 +2395,7 @@ static int vgic_its_save_device_tables(struct vgic_its *its)
if (ret)
return ret;
- ret = vgic_its_save_dte(its, dev, eaddr, dte_esz);
+ ret = vgic_its_save_dte(its, dev, eaddr);
if (ret)
return ret;
}
@@ -2435,7 +2476,7 @@ static int vgic_its_restore_device_tables(struct vgic_its *its)
static int vgic_its_save_cte(struct vgic_its *its,
struct its_collection *collection,
- gpa_t gpa, int esz)
+ gpa_t gpa)
{
u64 val;
@@ -2444,7 +2485,7 @@ static int vgic_its_save_cte(struct vgic_its *its,
collection->collection_id);
val = cpu_to_le64(val);
- return vgic_its_write_entry_lock(its, gpa, val, esz);
+ return vgic_its_write_entry_lock(its, gpa, val, cte);
}
/*
@@ -2452,7 +2493,7 @@ static int vgic_its_save_cte(struct vgic_its *its,
* Return +1 on success, 0 if the entry was invalid (which should be
* interpreted as end-of-table), and a negative error value for generic errors.
*/
-static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
+static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa)
{
struct its_collection *collection;
struct kvm *kvm = its->dev->kvm;
@@ -2460,7 +2501,7 @@ static int vgic_its_restore_cte(struct vgic_its *its, gpa_t gpa, int esz)
u64 val;
int ret;
- ret = vgic_its_read_entry_lock(its, gpa, &val, esz);
+ ret = vgic_its_read_entry_lock(its, gpa, &val, cte);
if (ret)
return ret;
val = le64_to_cpu(val);
@@ -2507,7 +2548,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
list_for_each_entry(collection, &its->collection_list, coll_list) {
- ret = vgic_its_save_cte(its, collection, gpa, cte_esz);
+ ret = vgic_its_save_cte(its, collection, gpa);
if (ret)
return ret;
gpa += cte_esz;
@@ -2521,7 +2562,7 @@ static int vgic_its_save_collection_table(struct vgic_its *its)
* table is not fully filled, add a last dummy element
* with valid bit unset
*/
- return vgic_its_write_entry_lock(its, gpa, 0, cte_esz);
+ return vgic_its_write_entry_lock(its, gpa, 0ULL, cte);
}
/*
@@ -2546,7 +2587,7 @@ static int vgic_its_restore_collection_table(struct vgic_its *its)
max_size = GITS_BASER_NR_PAGES(baser) * SZ_64K;
while (read < max_size) {
- ret = vgic_its_restore_cte(its, gpa, cte_esz);
+ ret = vgic_its_restore_cte(its, gpa);
if (ret <= 0)
break;
gpa += cte_esz;
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v2.c b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
index e070cda86e12..f25fccb1f8e6 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v2.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v2.c
@@ -148,7 +148,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
if (!(targets & (1U << c)))
continue;
- irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
+ irq = vgic_get_vcpu_irq(vcpu, intid);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
irq->pending_latch = true;
@@ -167,7 +167,7 @@ static unsigned long vgic_mmio_read_target(struct kvm_vcpu *vcpu,
u64 val = 0;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
val |= (u64)irq->targets << (i * 8);
@@ -191,7 +191,7 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
return;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
+ struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, intid + i);
int target;
raw_spin_lock_irqsave(&irq->irq_lock, flags);
@@ -213,7 +213,7 @@ static unsigned long vgic_mmio_read_sgipend(struct kvm_vcpu *vcpu,
u64 val = 0;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
val |= (u64)irq->source << (i * 8);
@@ -231,7 +231,7 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
unsigned long flags;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
@@ -253,7 +253,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
unsigned long flags;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
diff --git a/arch/arm64/kvm/vgic/vgic-mmio-v3.c b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
index 9e50928f5d7d..ae4c0593d114 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio-v3.c
@@ -194,7 +194,7 @@ static unsigned long vgic_mmio_read_irouter(struct kvm_vcpu *vcpu,
gpa_t addr, unsigned int len)
{
int intid = VGIC_ADDR_TO_INTID(addr, 64);
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+ struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, intid);
unsigned long ret = 0;
if (!irq)
@@ -220,7 +220,7 @@ static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
if (addr & 4)
return;
- irq = vgic_get_irq(vcpu->kvm, NULL, intid);
+ irq = vgic_get_irq(vcpu->kvm, intid);
if (!irq)
return;
@@ -530,6 +530,7 @@ static void vgic_mmio_write_invlpi(struct kvm_vcpu *vcpu,
unsigned long val)
{
struct vgic_irq *irq;
+ u32 intid;
/*
* If the guest wrote only to the upper 32bit part of the
@@ -541,9 +542,13 @@ static void vgic_mmio_write_invlpi(struct kvm_vcpu *vcpu,
if ((addr & 4) || !vgic_lpis_enabled(vcpu))
return;
+ intid = lower_32_bits(val);
+ if (intid < VGIC_MIN_LPI)
+ return;
+
vgic_set_rdist_busy(vcpu, true);
- irq = vgic_get_irq(vcpu->kvm, NULL, lower_32_bits(val));
+ irq = vgic_get_irq(vcpu->kvm, intid);
if (irq) {
vgic_its_inv_lpi(vcpu->kvm, irq);
vgic_put_irq(vcpu->kvm, irq);
@@ -1020,7 +1025,7 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
static void vgic_v3_queue_sgi(struct kvm_vcpu *vcpu, u32 sgi, bool allow_group1)
{
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, sgi);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, sgi);
unsigned long flags;
raw_spin_lock_irqsave(&irq->irq_lock, flags);
diff --git a/arch/arm64/kvm/vgic/vgic-mmio.c b/arch/arm64/kvm/vgic/vgic-mmio.c
index cf76523a2194..e416e433baff 100644
--- a/arch/arm64/kvm/vgic/vgic-mmio.c
+++ b/arch/arm64/kvm/vgic/vgic-mmio.c
@@ -50,7 +50,7 @@ unsigned long vgic_mmio_read_group(struct kvm_vcpu *vcpu,
/* Loop over all IRQs affected by this read */
for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
if (irq->group)
value |= BIT(i);
@@ -74,7 +74,7 @@ void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
unsigned long flags;
for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
irq->group = !!(val & BIT(i));
@@ -102,7 +102,7 @@ unsigned long vgic_mmio_read_enable(struct kvm_vcpu *vcpu,
/* Loop over all IRQs affected by this read */
for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
if (irq->enabled)
value |= (1U << i);
@@ -122,7 +122,7 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
@@ -171,7 +171,7 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (irq->hw && vgic_irq_is_sgi(irq->intid) && irq->enabled)
@@ -193,7 +193,7 @@ int vgic_uaccess_write_senable(struct kvm_vcpu *vcpu,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
irq->enabled = true;
@@ -214,7 +214,7 @@ int vgic_uaccess_write_cenable(struct kvm_vcpu *vcpu,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
irq->enabled = false;
@@ -236,7 +236,7 @@ static unsigned long __read_pending(struct kvm_vcpu *vcpu,
/* Loop over all IRQs affected by this read */
for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
unsigned long flags;
bool val;
@@ -309,7 +309,7 @@ static void __set_pending(struct kvm_vcpu *vcpu, gpa_t addr, unsigned int len,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
/* GICD_ISPENDR0 SGI bits are WI when written from the guest. */
if (is_vgic_v2_sgi(vcpu, irq) && !is_user) {
@@ -395,7 +395,7 @@ static void __clear_pending(struct kvm_vcpu *vcpu,
unsigned long flags;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
/* GICD_ICPENDR0 SGI bits are WI when written from the guest. */
if (is_vgic_v2_sgi(vcpu, irq) && !is_user) {
@@ -494,7 +494,7 @@ static unsigned long __vgic_mmio_read_active(struct kvm_vcpu *vcpu,
/* Loop over all IRQs affected by this read */
for (i = 0; i < len * 8; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
/*
* Even for HW interrupts, don't evaluate the HW state as
@@ -598,7 +598,7 @@ static void __vgic_mmio_write_cactive(struct kvm_vcpu *vcpu,
int i;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
vgic_mmio_change_active(vcpu, irq, false);
vgic_put_irq(vcpu->kvm, irq);
}
@@ -635,7 +635,7 @@ static void __vgic_mmio_write_sactive(struct kvm_vcpu *vcpu,
int i;
for_each_set_bit(i, &val, len * 8) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
vgic_mmio_change_active(vcpu, irq, true);
vgic_put_irq(vcpu->kvm, irq);
}
@@ -672,7 +672,7 @@ unsigned long vgic_mmio_read_priority(struct kvm_vcpu *vcpu,
u64 val = 0;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
val |= (u64)irq->priority << (i * 8);
@@ -698,7 +698,7 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
unsigned long flags;
for (i = 0; i < len; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
/* Narrow the priority range to what we actually support */
@@ -719,7 +719,7 @@ unsigned long vgic_mmio_read_config(struct kvm_vcpu *vcpu,
int i;
for (i = 0; i < len * 4; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, intid + i);
if (irq->config == VGIC_CONFIG_EDGE)
value |= (2U << (i * 2));
@@ -750,7 +750,7 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
if (intid + i < VGIC_NR_PRIVATE_IRQS)
continue;
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ irq = vgic_get_irq(vcpu->kvm, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (test_bit(i * 2 + 1, &val))
@@ -775,7 +775,7 @@ u32 vgic_read_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid)
if ((intid + i) < VGIC_NR_SGIS || (intid + i) >= nr_irqs)
continue;
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ irq = vgic_get_vcpu_irq(vcpu, intid + i);
if (irq->config == VGIC_CONFIG_LEVEL && irq->line_level)
val |= (1U << i);
@@ -799,7 +799,7 @@ void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
if ((intid + i) < VGIC_NR_SGIS || (intid + i) >= nr_irqs)
continue;
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
+ irq = vgic_get_vcpu_irq(vcpu, intid + i);
/*
* Line level is set irrespective of irq type
diff --git a/arch/arm64/kvm/vgic/vgic-v2.c b/arch/arm64/kvm/vgic/vgic-v2.c
index ae5a44d5702d..381673f03c39 100644
--- a/arch/arm64/kvm/vgic/vgic-v2.c
+++ b/arch/arm64/kvm/vgic/vgic-v2.c
@@ -72,7 +72,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
kvm_notify_acked_irq(vcpu->kvm, 0,
intid - VGIC_NR_PRIVATE_IRQS);
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+ irq = vgic_get_vcpu_irq(vcpu, intid);
raw_spin_lock(&irq->irq_lock);
diff --git a/arch/arm64/kvm/vgic/vgic-v3.c b/arch/arm64/kvm/vgic/vgic-v3.c
index b217b256853c..f267bc2486a1 100644
--- a/arch/arm64/kvm/vgic/vgic-v3.c
+++ b/arch/arm64/kvm/vgic/vgic-v3.c
@@ -65,7 +65,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
kvm_notify_acked_irq(vcpu->kvm, 0,
intid - VGIC_NR_PRIVATE_IRQS);
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+ irq = vgic_get_vcpu_irq(vcpu, intid);
if (!irq) /* An LPI could have been unmapped. */
continue;
diff --git a/arch/arm64/kvm/vgic/vgic-v4.c b/arch/arm64/kvm/vgic/vgic-v4.c
index 74a67ad87f29..eedecbbbcf31 100644
--- a/arch/arm64/kvm/vgic/vgic-v4.c
+++ b/arch/arm64/kvm/vgic/vgic-v4.c
@@ -123,7 +123,7 @@ static void vgic_v4_enable_vsgis(struct kvm_vcpu *vcpu)
* IRQ. The SGI code will do its magic.
*/
for (i = 0; i < VGIC_NR_SGIS; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, i);
struct irq_desc *desc;
unsigned long flags;
int ret;
@@ -160,7 +160,7 @@ static void vgic_v4_disable_vsgis(struct kvm_vcpu *vcpu)
int i;
for (i = 0; i < VGIC_NR_SGIS; i++) {
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, i);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, i);
struct irq_desc *desc;
unsigned long flags;
int ret;
diff --git a/arch/arm64/kvm/vgic/vgic.c b/arch/arm64/kvm/vgic/vgic.c
index f50274fd5581..cc8c6b9b5dd8 100644
--- a/arch/arm64/kvm/vgic/vgic.c
+++ b/arch/arm64/kvm/vgic/vgic.c
@@ -84,17 +84,11 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
* struct vgic_irq. It also increases the refcount, so any caller is expected
* to call vgic_put_irq() once it's finished with this IRQ.
*/
-struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
- u32 intid)
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, u32 intid)
{
- /* SGIs and PPIs */
- if (intid <= VGIC_MAX_PRIVATE) {
- intid = array_index_nospec(intid, VGIC_MAX_PRIVATE + 1);
- return &vcpu->arch.vgic_cpu.private_irqs[intid];
- }
-
/* SPIs */
- if (intid < (kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS)) {
+ if (intid >= VGIC_NR_PRIVATE_IRQS &&
+ intid < (kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS)) {
intid = array_index_nospec(intid, kvm->arch.vgic.nr_spis + VGIC_NR_PRIVATE_IRQS);
return &kvm->arch.vgic.spis[intid - VGIC_NR_PRIVATE_IRQS];
}
@@ -106,6 +100,20 @@ struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
return NULL;
}
+struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid)
+{
+ if (WARN_ON(!vcpu))
+ return NULL;
+
+ /* SGIs and PPIs */
+ if (intid < VGIC_NR_PRIVATE_IRQS) {
+ intid = array_index_nospec(intid, VGIC_NR_PRIVATE_IRQS);
+ return &vcpu->arch.vgic_cpu.private_irqs[intid];
+ }
+
+ return vgic_get_irq(vcpu->kvm, intid);
+}
+
/*
* We can't do anything in here, because we lack the kvm pointer to
* lock and remove the item from the lpi_list. So we keep this function
@@ -437,7 +445,10 @@ int kvm_vgic_inject_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
trace_vgic_update_irq_pending(vcpu ? vcpu->vcpu_idx : 0, intid, level);
- irq = vgic_get_irq(kvm, vcpu, intid);
+ if (intid < VGIC_NR_PRIVATE_IRQS)
+ irq = vgic_get_vcpu_irq(vcpu, intid);
+ else
+ irq = vgic_get_irq(kvm, intid);
if (!irq)
return -EINVAL;
@@ -499,7 +510,7 @@ static inline void kvm_vgic_unmap_irq(struct vgic_irq *irq)
int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
u32 vintid, struct irq_ops *ops)
{
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, vintid);
unsigned long flags;
int ret;
@@ -524,7 +535,7 @@ int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
*/
void kvm_vgic_reset_mapped_irq(struct kvm_vcpu *vcpu, u32 vintid)
{
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, vintid);
unsigned long flags;
if (!irq->hw)
@@ -547,7 +558,7 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
if (!vgic_initialized(vcpu->kvm))
return -EAGAIN;
- irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+ irq = vgic_get_vcpu_irq(vcpu, vintid);
BUG_ON(!irq);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
@@ -560,7 +571,7 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
int kvm_vgic_get_map(struct kvm_vcpu *vcpu, unsigned int vintid)
{
- struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+ struct vgic_irq *irq = vgic_get_vcpu_irq(vcpu, vintid);
unsigned long flags;
int ret = -1;
@@ -596,7 +607,7 @@ int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner)
if (!irq_is_ppi(intid) && !vgic_valid_spi(vcpu->kvm, intid))
return -EINVAL;
- irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
+ irq = vgic_get_vcpu_irq(vcpu, intid);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
if (irq->owner && irq->owner != owner)
ret = -EEXIST;
@@ -1008,7 +1019,7 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
if (!vgic_initialized(vcpu->kvm))
return false;
- irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+ irq = vgic_get_vcpu_irq(vcpu, vintid);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
map_is_active = irq->hw && irq->active;
raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
diff --git a/arch/arm64/kvm/vgic/vgic.h b/arch/arm64/kvm/vgic/vgic.h
index 309295f5e1b0..122d95b4e284 100644
--- a/arch/arm64/kvm/vgic/vgic.h
+++ b/arch/arm64/kvm/vgic/vgic.h
@@ -146,29 +146,6 @@ static inline int vgic_write_guest_lock(struct kvm *kvm, gpa_t gpa,
return ret;
}
-static inline int vgic_its_read_entry_lock(struct vgic_its *its, gpa_t eaddr,
- u64 *eval, unsigned long esize)
-{
- struct kvm *kvm = its->dev->kvm;
-
- if (KVM_BUG_ON(esize != sizeof(*eval), kvm))
- return -EINVAL;
-
- return kvm_read_guest_lock(kvm, eaddr, eval, esize);
-
-}
-
-static inline int vgic_its_write_entry_lock(struct vgic_its *its, gpa_t eaddr,
- u64 eval, unsigned long esize)
-{
- struct kvm *kvm = its->dev->kvm;
-
- if (KVM_BUG_ON(esize != sizeof(eval), kvm))
- return -EINVAL;
-
- return vgic_write_guest_lock(kvm, eaddr, &eval, esize);
-}
-
/*
* This struct provides an intermediate representation of the fields contained
* in the GICH_VMCR and ICH_VMCR registers, such that code exporting the GIC
@@ -202,8 +179,8 @@ int vgic_v2_parse_attr(struct kvm_device *dev, struct kvm_device_attr *attr,
const struct vgic_register_region *
vgic_get_mmio_region(struct kvm_vcpu *vcpu, struct vgic_io_device *iodev,
gpa_t addr, int len);
-struct vgic_irq *vgic_get_irq(struct kvm *kvm, struct kvm_vcpu *vcpu,
- u32 intid);
+struct vgic_irq *vgic_get_irq(struct kvm *kvm, u32 intid);
+struct vgic_irq *vgic_get_vcpu_irq(struct kvm_vcpu *vcpu, u32 intid);
void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq);
bool vgic_get_phys_line_level(struct vgic_irq *irq);
void vgic_irq_set_phys_pending(struct vgic_irq *irq, bool pending);
diff --git a/arch/arm64/mm/context.c b/arch/arm64/mm/context.c
index 188197590fc9..b2ac06246327 100644
--- a/arch/arm64/mm/context.c
+++ b/arch/arm64/mm/context.c
@@ -32,9 +32,9 @@ static unsigned long nr_pinned_asids;
static unsigned long *pinned_asid_map;
#define ASID_MASK (~GENMASK(asid_bits - 1, 0))
-#define ASID_FIRST_VERSION (1UL << asid_bits)
+#define ASID_FIRST_VERSION (1UL << 16)
-#define NUM_USER_ASIDS ASID_FIRST_VERSION
+#define NUM_USER_ASIDS (1UL << asid_bits)
#define ctxid2asid(asid) ((asid) & ~ASID_MASK)
#define asid2ctxid(asid, genid) ((asid) | (genid))
diff --git a/arch/arm64/mm/copypage.c b/arch/arm64/mm/copypage.c
index 87b3f1a25535..a86c897017df 100644
--- a/arch/arm64/mm/copypage.c
+++ b/arch/arm64/mm/copypage.c
@@ -30,11 +30,13 @@ void copy_highpage(struct page *to, struct page *from)
if (!system_supports_mte())
return;
- if (folio_test_hugetlb(src) &&
- folio_test_hugetlb_mte_tagged(src)) {
- if (!folio_try_hugetlb_mte_tagging(dst))
+ if (folio_test_hugetlb(src)) {
+ if (!folio_test_hugetlb_mte_tagged(src) ||
+ from != folio_page(src, 0))
return;
+ WARN_ON_ONCE(!folio_try_hugetlb_mte_tagging(dst));
+
/*
* Populate tags for all subpages.
*
diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c
index d21f67d67cf5..ccdef53872a0 100644
--- a/arch/arm64/mm/init.c
+++ b/arch/arm64/mm/init.c
@@ -117,15 +117,6 @@ static void __init arch_reserve_crashkernel(void)
static phys_addr_t __init max_zone_phys(phys_addr_t zone_limit)
{
- /**
- * Information we get from firmware (e.g. DT dma-ranges) describe DMA
- * bus constraints. Devices using DMA might have their own limitations.
- * Some of them rely on DMA zone in low 32-bit memory. Keep low RAM
- * DMA zone on platforms that have RAM there.
- */
- if (memblock_start_of_DRAM() < U32_MAX)
- zone_limit = min(zone_limit, U32_MAX);
-
return min(zone_limit, memblock_end_of_DRAM() - 1) + 1;
}
@@ -141,6 +132,14 @@ static void __init zone_sizes_init(void)
acpi_zone_dma_limit = acpi_iort_dma_get_max_cpu_address();
dt_zone_dma_limit = of_dma_get_max_cpu_address(NULL);
zone_dma_limit = min(dt_zone_dma_limit, acpi_zone_dma_limit);
+ /*
+ * Information we get from firmware (e.g. DT dma-ranges) describe DMA
+ * bus constraints. Devices using DMA might have their own limitations.
+ * Some of them rely on DMA zone in low 32-bit memory. Keep low RAM
+ * DMA zone on platforms that have RAM there.
+ */
+ if (memblock_start_of_DRAM() < U32_MAX)
+ zone_dma_limit = min(zone_dma_limit, U32_MAX);
arm64_dma_phys_limit = max_zone_phys(zone_dma_limit);
max_zone_pfns[ZONE_DMA] = PFN_DOWN(arm64_dma_phys_limit);
#endif
diff --git a/arch/hexagon/Makefile b/arch/hexagon/Makefile
index 92d005958dfb..ff172cbe5881 100644
--- a/arch/hexagon/Makefile
+++ b/arch/hexagon/Makefile
@@ -32,3 +32,9 @@ KBUILD_LDFLAGS += $(ldflags-y)
TIR_NAME := r19
KBUILD_CFLAGS += -ffixed-$(TIR_NAME) -DTHREADINFO_REG=$(TIR_NAME) -D__linux__
KBUILD_AFLAGS += -DTHREADINFO_REG=$(TIR_NAME)
+
+# Disable HexagonConstExtenders pass for LLVM versions prior to 19.1.0
+# https://github.com/llvm/llvm-project/issues/99714
+ifneq ($(call clang-min-version, 190100),y)
+KBUILD_CFLAGS += -mllvm -hexagon-cext=false
+endif
diff --git a/arch/loongarch/include/asm/hugetlb.h b/arch/loongarch/include/asm/hugetlb.h
index b837c65a4894..c8e4057734d0 100644
--- a/arch/loongarch/include/asm/hugetlb.h
+++ b/arch/loongarch/include/asm/hugetlb.h
@@ -24,6 +24,16 @@ static inline int prepare_hugepage_range(struct file *file,
return 0;
}
+#define __HAVE_ARCH_HUGE_PTE_CLEAR
+static inline void huge_pte_clear(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, unsigned long sz)
+{
+ pte_t clear;
+
+ pte_val(clear) = (unsigned long)invalid_pte_table;
+ set_pte_at(mm, addr, ptep, clear);
+}
+
#define __HAVE_ARCH_HUGE_PTEP_GET_AND_CLEAR
static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
unsigned long addr, pte_t *ptep)
diff --git a/arch/loongarch/include/asm/inst.h b/arch/loongarch/include/asm/inst.h
index 944482063f14..3089785ca97e 100644
--- a/arch/loongarch/include/asm/inst.h
+++ b/arch/loongarch/include/asm/inst.h
@@ -683,7 +683,17 @@ DEF_EMIT_REG2I16_FORMAT(blt, blt_op)
DEF_EMIT_REG2I16_FORMAT(bge, bge_op)
DEF_EMIT_REG2I16_FORMAT(bltu, bltu_op)
DEF_EMIT_REG2I16_FORMAT(bgeu, bgeu_op)
-DEF_EMIT_REG2I16_FORMAT(jirl, jirl_op)
+
+static inline void emit_jirl(union loongarch_instruction *insn,
+ enum loongarch_gpr rd,
+ enum loongarch_gpr rj,
+ int offset)
+{
+ insn->reg2i16_format.opcode = jirl_op;
+ insn->reg2i16_format.immediate = offset;
+ insn->reg2i16_format.rd = rd;
+ insn->reg2i16_format.rj = rj;
+}
#define DEF_EMIT_REG2BSTRD_FORMAT(NAME, OP) \
static inline void emit_##NAME(union loongarch_instruction *insn, \
diff --git a/arch/loongarch/kernel/efi.c b/arch/loongarch/kernel/efi.c
index 2bf86aeda874..de21e72759ee 100644
--- a/arch/loongarch/kernel/efi.c
+++ b/arch/loongarch/kernel/efi.c
@@ -95,7 +95,7 @@ static void __init init_screen_info(void)
memset(si, 0, sizeof(*si));
early_memunmap(si, sizeof(*si));
- memblock_reserve(screen_info.lfb_base, screen_info.lfb_size);
+ memblock_reserve(__screen_info_lfb_base(&screen_info), screen_info.lfb_size);
}
void __init efi_init(void)
diff --git a/arch/loongarch/kernel/inst.c b/arch/loongarch/kernel/inst.c
index 3050329556d1..14d7d700bcb9 100644
--- a/arch/loongarch/kernel/inst.c
+++ b/arch/loongarch/kernel/inst.c
@@ -332,7 +332,7 @@ u32 larch_insn_gen_jirl(enum loongarch_gpr rd, enum loongarch_gpr rj, int imm)
return INSN_BREAK;
}
- emit_jirl(&insn, rj, rd, imm >> 2);
+ emit_jirl(&insn, rd, rj, imm >> 2);
return insn.word;
}
diff --git a/arch/loongarch/kernel/smp.c b/arch/loongarch/kernel/smp.c
index 5d59e9ce2772..fbf747447f13 100644
--- a/arch/loongarch/kernel/smp.c
+++ b/arch/loongarch/kernel/smp.c
@@ -82,7 +82,7 @@ void show_ipi_list(struct seq_file *p, int prec)
for (i = 0; i < NR_IPI; i++) {
seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i, prec >= 4 ? " " : "");
for_each_online_cpu(cpu)
- seq_printf(p, "%10u ", per_cpu(irq_stat, cpu).ipi_irqs[i]);
+ seq_put_decimal_ull_width(p, " ", per_cpu(irq_stat, cpu).ipi_irqs[i], 10);
seq_printf(p, " LoongArch %d %s\n", i + 1, ipi_types[i]);
}
}
diff --git a/arch/loongarch/kvm/exit.c b/arch/loongarch/kvm/exit.c
index 69f3e3782cc9..a7893bd01e73 100644
--- a/arch/loongarch/kvm/exit.c
+++ b/arch/loongarch/kvm/exit.c
@@ -156,7 +156,7 @@ static int kvm_handle_csr(struct kvm_vcpu *vcpu, larch_inst inst)
int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
{
- int ret;
+ int idx, ret;
unsigned long *val;
u32 addr, rd, rj, opcode;
@@ -167,7 +167,6 @@ int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
rj = inst.reg2_format.rj;
opcode = inst.reg2_format.opcode;
addr = vcpu->arch.gprs[rj];
- ret = EMULATE_DO_IOCSR;
run->iocsr_io.phys_addr = addr;
run->iocsr_io.is_write = 0;
val = &vcpu->arch.gprs[rd];
@@ -207,20 +206,28 @@ int kvm_emu_iocsr(larch_inst inst, struct kvm_run *run, struct kvm_vcpu *vcpu)
}
if (run->iocsr_io.is_write) {
- if (!kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val))
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
+ ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val);
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
+ if (ret == 0)
ret = EMULATE_DONE;
- else
+ else {
+ ret = EMULATE_DO_IOCSR;
/* Save data and let user space to write it */
memcpy(run->iocsr_io.data, val, run->iocsr_io.len);
-
+ }
trace_kvm_iocsr(KVM_TRACE_IOCSR_WRITE, run->iocsr_io.len, addr, val);
} else {
- if (!kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val))
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
+ ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, run->iocsr_io.len, val);
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
+ if (ret == 0)
ret = EMULATE_DONE;
- else
+ else {
+ ret = EMULATE_DO_IOCSR;
/* Save register id for iocsr read completion */
vcpu->arch.io_gpr = rd;
-
+ }
trace_kvm_iocsr(KVM_TRACE_IOCSR_READ, run->iocsr_io.len, addr, NULL);
}
@@ -359,7 +366,7 @@ static int kvm_handle_gspr(struct kvm_vcpu *vcpu)
int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst)
{
- int ret;
+ int idx, ret;
unsigned int op8, opcode, rd;
struct kvm_run *run = vcpu->run;
@@ -464,8 +471,10 @@ int kvm_emu_mmio_read(struct kvm_vcpu *vcpu, larch_inst inst)
* it need not return to user space to handle the mmio
* exception.
*/
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
ret = kvm_io_bus_read(vcpu, KVM_MMIO_BUS, vcpu->arch.badv,
run->mmio.len, &vcpu->arch.gprs[rd]);
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
if (!ret) {
update_pc(&vcpu->arch);
vcpu->mmio_needed = 0;
@@ -531,7 +540,7 @@ int kvm_complete_mmio_read(struct kvm_vcpu *vcpu, struct kvm_run *run)
int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst)
{
- int ret;
+ int idx, ret;
unsigned int rd, op8, opcode;
unsigned long curr_pc, rd_val = 0;
struct kvm_run *run = vcpu->run;
@@ -631,7 +640,9 @@ int kvm_emu_mmio_write(struct kvm_vcpu *vcpu, larch_inst inst)
* it need not return to user space to handle the mmio
* exception.
*/
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
ret = kvm_io_bus_write(vcpu, KVM_MMIO_BUS, vcpu->arch.badv, run->mmio.len, data);
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
if (!ret)
return EMULATE_DONE;
diff --git a/arch/loongarch/kvm/intc/ipi.c b/arch/loongarch/kvm/intc/ipi.c
index a233a323e295..93f4acd44523 100644
--- a/arch/loongarch/kvm/intc/ipi.c
+++ b/arch/loongarch/kvm/intc/ipi.c
@@ -98,7 +98,7 @@ static void write_mailbox(struct kvm_vcpu *vcpu, int offset, uint64_t data, int
static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
{
- int i, ret;
+ int i, idx, ret;
uint32_t val = 0, mask = 0;
/*
@@ -107,7 +107,9 @@ static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
*/
if ((data >> 27) & 0xf) {
/* Read the old val */
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
ret = kvm_io_bus_read(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val);
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
if (unlikely(ret)) {
kvm_err("%s: : read date from addr %llx failed\n", __func__, addr);
return ret;
@@ -121,7 +123,9 @@ static int send_ipi_data(struct kvm_vcpu *vcpu, gpa_t addr, uint64_t data)
val &= mask;
}
val |= ((uint32_t)(data >> 32) & ~mask);
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
ret = kvm_io_bus_write(vcpu, KVM_IOCSR_BUS, addr, sizeof(val), &val);
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
if (unlikely(ret))
kvm_err("%s: : write date to addr %llx failed\n", __func__, addr);
diff --git a/arch/loongarch/kvm/vcpu.c b/arch/loongarch/kvm/vcpu.c
index cab1818be68d..d18a4a270415 100644
--- a/arch/loongarch/kvm/vcpu.c
+++ b/arch/loongarch/kvm/vcpu.c
@@ -240,7 +240,7 @@ static void kvm_late_check_requests(struct kvm_vcpu *vcpu)
*/
static int kvm_enter_guest_check(struct kvm_vcpu *vcpu)
{
- int ret;
+ int idx, ret;
/*
* Check conditions before entering the guest
@@ -249,7 +249,9 @@ static int kvm_enter_guest_check(struct kvm_vcpu *vcpu)
if (ret < 0)
return ret;
+ idx = srcu_read_lock(&vcpu->kvm->srcu);
ret = kvm_check_requests(vcpu);
+ srcu_read_unlock(&vcpu->kvm->srcu, idx);
return ret;
}
diff --git a/arch/loongarch/net/bpf_jit.c b/arch/loongarch/net/bpf_jit.c
index dd350cba1252..ea357a3edc09 100644
--- a/arch/loongarch/net/bpf_jit.c
+++ b/arch/loongarch/net/bpf_jit.c
@@ -181,13 +181,13 @@ static void __build_epilogue(struct jit_ctx *ctx, bool is_tail_call)
/* Set return value */
emit_insn(ctx, addiw, LOONGARCH_GPR_A0, regmap[BPF_REG_0], 0);
/* Return to the caller */
- emit_insn(ctx, jirl, LOONGARCH_GPR_RA, LOONGARCH_GPR_ZERO, 0);
+ emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_RA, 0);
} else {
/*
* Call the next bpf prog and skip the first instruction
* of TCC initialization.
*/
- emit_insn(ctx, jirl, LOONGARCH_GPR_T3, LOONGARCH_GPR_ZERO, 1);
+ emit_insn(ctx, jirl, LOONGARCH_GPR_ZERO, LOONGARCH_GPR_T3, 1);
}
}
@@ -904,7 +904,7 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx, bool ext
return ret;
move_addr(ctx, t1, func_addr);
- emit_insn(ctx, jirl, t1, LOONGARCH_GPR_RA, 0);
+ emit_insn(ctx, jirl, LOONGARCH_GPR_RA, t1, 0);
move_reg(ctx, regmap[BPF_REG_0], LOONGARCH_GPR_A0);
break;
diff --git a/arch/m68k/configs/multi_defconfig b/arch/m68k/configs/multi_defconfig
index f8edc9082724..20d877cb4e30 100644
--- a/arch/m68k/configs/multi_defconfig
+++ b/arch/m68k/configs/multi_defconfig
@@ -503,6 +503,7 @@ CONFIG_UHID=m
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
# CONFIG_RTC_NVMEM is not set
+CONFIG_RTC_DRV_M48T59=m
CONFIG_RTC_DRV_MSM6242=m
CONFIG_RTC_DRV_RP5C01=m
CONFIG_RTC_DRV_GENERIC=m
diff --git a/arch/m68k/configs/mvme147_defconfig b/arch/m68k/configs/mvme147_defconfig
index 71fc71bb660e..5e1c8d0d3da5 100644
--- a/arch/m68k/configs/mvme147_defconfig
+++ b/arch/m68k/configs/mvme147_defconfig
@@ -391,6 +391,7 @@ CONFIG_UHID=m
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
# CONFIG_RTC_NVMEM is not set
+CONFIG_RTC_DRV_M48T59=y
CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
diff --git a/arch/m68k/configs/mvme16x_defconfig b/arch/m68k/configs/mvme16x_defconfig
index 41072e68028e..5d1409e6a137 100644
--- a/arch/m68k/configs/mvme16x_defconfig
+++ b/arch/m68k/configs/mvme16x_defconfig
@@ -392,6 +392,7 @@ CONFIG_UHID=m
# CONFIG_USB_SUPPORT is not set
CONFIG_RTC_CLASS=y
# CONFIG_RTC_NVMEM is not set
+CONFIG_RTC_DRV_M48T59=y
CONFIG_RTC_DRV_GENERIC=m
# CONFIG_VIRTIO_MENU is not set
# CONFIG_VHOST_MENU is not set
diff --git a/arch/m68k/include/asm/mvme147hw.h b/arch/m68k/include/asm/mvme147hw.h
index dbf88059e47a..6ad93bac06f9 100644
--- a/arch/m68k/include/asm/mvme147hw.h
+++ b/arch/m68k/include/asm/mvme147hw.h
@@ -4,24 +4,7 @@
#include <asm/irq.h>
-typedef struct {
- unsigned char
- ctrl,
- bcd_sec,
- bcd_min,
- bcd_hr,
- bcd_dow,
- bcd_dom,
- bcd_mth,
- bcd_year;
-} MK48T02;
-
-#define RTC_WRITE 0x80
-#define RTC_READ 0x40
-#define RTC_STOP 0x20
-
-#define m147_rtc ((MK48T02 * volatile)0xfffe07f8)
-
+#define MVME147_RTC_BASE 0xfffe0000
struct pcc_regs {
volatile u_long dma_tadr;
diff --git a/arch/m68k/include/asm/mvme16xhw.h b/arch/m68k/include/asm/mvme16xhw.h
index cc7f5ae1220f..ff1126a51fbe 100644
--- a/arch/m68k/include/asm/mvme16xhw.h
+++ b/arch/m68k/include/asm/mvme16xhw.h
@@ -24,23 +24,7 @@ typedef struct {
#define mvmelp ((*(volatile MVMElpPtr)(MVME_LPR_BASE)))
-typedef struct {
- unsigned char
- ctrl,
- bcd_sec,
- bcd_min,
- bcd_hr,
- bcd_dow,
- bcd_dom,
- bcd_mth,
- bcd_year;
-} MK48T08_t, *MK48T08ptr_t;
-
-#define RTC_WRITE 0x80
-#define RTC_READ 0x40
-#define RTC_STOP 0x20
-
-#define MVME_RTC_BASE 0xfffc1ff8
+#define MVME_RTC_BASE 0xfffc0000
#define MVME_I596_BASE 0xfff46000
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index 824c42a302c6..3054d3857efa 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -19,8 +19,9 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/major.h>
-#include <linux/rtc.h>
#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/rtc/m48t59.h>
#include <asm/bootinfo.h>
#include <asm/bootinfo-vme.h>
@@ -36,13 +37,9 @@
static void mvme147_get_model(char *model);
static void __init mvme147_sched_init(void);
-extern int mvme147_hwclk (int, struct rtc_time *);
extern void mvme147_reset (void);
-static int bcd2int (unsigned char b);
-
-
int __init mvme147_parse_bootinfo(const struct bi_record *bi)
{
uint16_t tag = be16_to_cpu(bi->tag);
@@ -80,7 +77,6 @@ void __init config_mvme147(void)
{
mach_sched_init = mvme147_sched_init;
mach_init_IRQ = mvme147_init_IRQ;
- mach_hwclk = mvme147_hwclk;
mach_reset = mvme147_reset;
mach_get_model = mvme147_get_model;
@@ -89,6 +85,28 @@ void __init config_mvme147(void)
vme_brdtype = VME_TYPE_MVME147;
}
+static struct resource m48t59_rsrc[] = {
+ DEFINE_RES_MEM(MVME147_RTC_BASE, 0x800),
+};
+
+static struct m48t59_plat_data m48t59_data = {
+ .type = M48T59RTC_TYPE_M48T02,
+ .yy_offset = 70,
+};
+
+static int __init mvme147_platform_init(void)
+{
+ if (!MACH_IS_MVME147)
+ return 0;
+
+ platform_device_register_resndata(NULL, "rtc-m48t59", -1,
+ m48t59_rsrc, ARRAY_SIZE(m48t59_rsrc),
+ &m48t59_data, sizeof(m48t59_data));
+ return 0;
+}
+
+arch_initcall(mvme147_platform_init);
+
static u64 mvme147_read_clk(struct clocksource *cs);
static struct clocksource mvme147_clk = {
@@ -162,31 +180,6 @@ static u64 mvme147_read_clk(struct clocksource *cs)
return ticks;
}
-static int bcd2int (unsigned char b)
-{
- return ((b>>4)*10 + (b&15));
-}
-
-int mvme147_hwclk(int op, struct rtc_time *t)
-{
- if (!op) {
- m147_rtc->ctrl = RTC_READ;
- t->tm_year = bcd2int (m147_rtc->bcd_year);
- t->tm_mon = bcd2int(m147_rtc->bcd_mth) - 1;
- t->tm_mday = bcd2int (m147_rtc->bcd_dom);
- t->tm_hour = bcd2int (m147_rtc->bcd_hr);
- t->tm_min = bcd2int (m147_rtc->bcd_min);
- t->tm_sec = bcd2int (m147_rtc->bcd_sec);
- m147_rtc->ctrl = 0;
- if (t->tm_year < 70)
- t->tm_year += 100;
- } else {
- /* FIXME Setting the time is not yet supported */
- return -EOPNOTSUPP;
- }
- return 0;
-}
-
static void scc_delay(void)
{
__asm__ __volatile__ ("nop; nop;");
diff --git a/arch/m68k/mvme16x/Makefile b/arch/m68k/mvme16x/Makefile
index a8a368c2cbea..02f9e4ad8209 100644
--- a/arch/m68k/mvme16x/Makefile
+++ b/arch/m68k/mvme16x/Makefile
@@ -3,4 +3,4 @@
# Makefile for Linux arch/m68k/mvme16x source directory
#
-obj-y := config.o rtc.o
+obj-y := config.o
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index d1fbd1704d65..99768fe8da73 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -21,9 +21,10 @@
#include <linux/linkage.h>
#include <linux/init.h>
#include <linux/major.h>
-#include <linux/rtc.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/rtc/m48t59.h>
#include <asm/bootinfo.h>
#include <asm/bootinfo-vme.h>
@@ -39,16 +40,10 @@
extern t_bdid mvme_bdid;
-static MK48T08ptr_t volatile rtc = (MK48T08ptr_t)MVME_RTC_BASE;
-
static void mvme16x_get_model(char *model);
extern void mvme16x_sched_init(void);
-extern int mvme16x_hwclk (int, struct rtc_time *);
extern void mvme16x_reset (void);
-int bcd2int (unsigned char b);
-
-
unsigned short mvme16x_config;
EXPORT_SYMBOL(mvme16x_config);
@@ -268,7 +263,6 @@ void __init config_mvme16x(void)
mach_sched_init = mvme16x_sched_init;
mach_init_IRQ = mvme16x_init_IRQ;
- mach_hwclk = mvme16x_hwclk;
mach_reset = mvme16x_reset;
mach_get_model = mvme16x_get_model;
mach_get_hardware_list = mvme16x_get_hardware_list;
@@ -312,6 +306,28 @@ void __init config_mvme16x(void)
}
}
+static struct resource m48t59_rsrc[] = {
+ DEFINE_RES_MEM(MVME_RTC_BASE, 0x2000),
+};
+
+static struct m48t59_plat_data m48t59_data = {
+ .type = M48T59RTC_TYPE_M48T08,
+ .yy_offset = 70,
+};
+
+static int __init mvme16x_platform_init(void)
+{
+ if (!MACH_IS_MVME16x)
+ return 0;
+
+ platform_device_register_resndata(NULL, "rtc-m48t59", -1,
+ m48t59_rsrc, ARRAY_SIZE(m48t59_rsrc),
+ &m48t59_data, sizeof(m48t59_data));
+ return 0;
+}
+
+arch_initcall(mvme16x_platform_init);
+
static irqreturn_t mvme16x_abort_int (int irq, void *dev_id)
{
unsigned long *new = (unsigned long *)vectors;
@@ -426,28 +442,3 @@ static u64 mvme16x_read_clk(struct clocksource *cs)
return ticks;
}
-
-int bcd2int (unsigned char b)
-{
- return ((b>>4)*10 + (b&15));
-}
-
-int mvme16x_hwclk(int op, struct rtc_time *t)
-{
- if (!op) {
- rtc->ctrl = RTC_READ;
- t->tm_year = bcd2int (rtc->bcd_year);
- t->tm_mon = bcd2int(rtc->bcd_mth) - 1;
- t->tm_mday = bcd2int (rtc->bcd_dom);
- t->tm_hour = bcd2int (rtc->bcd_hr);
- t->tm_min = bcd2int (rtc->bcd_min);
- t->tm_sec = bcd2int (rtc->bcd_sec);
- rtc->ctrl = 0;
- if (t->tm_year < 70)
- t->tm_year += 100;
- } else {
- /* FIXME Setting the time is not yet supported */
- return -EOPNOTSUPP;
- }
- return 0;
-}
diff --git a/arch/m68k/mvme16x/rtc.c b/arch/m68k/mvme16x/rtc.c
deleted file mode 100644
index ccbaae1125e6..000000000000
--- a/arch/m68k/mvme16x/rtc.c
+++ /dev/null
@@ -1,165 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Real Time Clock interface for Linux on the MVME16x
- *
- * Based on the PC driver by Paul Gortmaker.
- */
-
-#define RTC_VERSION "1.00"
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/ioport.h>
-#include <linux/capability.h>
-#include <linux/fcntl.h>
-#include <linux/init.h>
-#include <linux/poll.h>
-#include <linux/rtc.h> /* For struct rtc_time and ioctls, etc */
-#include <linux/bcd.h>
-#include <asm/mvme16xhw.h>
-
-#include <asm/io.h>
-#include <linux/uaccess.h>
-#include <asm/setup.h>
-
-/*
- * We sponge a minor off of the misc major. No need slurping
- * up another valuable major dev number for this. If you add
- * an ioctl, make sure you don't conflict with SPARC's RTC
- * ioctls.
- */
-
-static const unsigned char days_in_mo[] =
-{0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
-
-static atomic_t rtc_ready = ATOMIC_INIT(1);
-
-static long rtc_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
- volatile MK48T08ptr_t rtc = (MK48T08ptr_t)MVME_RTC_BASE;
- unsigned long flags;
- struct rtc_time wtime;
- void __user *argp = (void __user *)arg;
-
- switch (cmd) {
- case RTC_RD_TIME: /* Read the time/date from RTC */
- {
- local_irq_save(flags);
- /* Ensure clock and real-time-mode-register are accessible */
- rtc->ctrl = RTC_READ;
- memset(&wtime, 0, sizeof(struct rtc_time));
- wtime.tm_sec = bcd2bin(rtc->bcd_sec);
- wtime.tm_min = bcd2bin(rtc->bcd_min);
- wtime.tm_hour = bcd2bin(rtc->bcd_hr);
- wtime.tm_mday = bcd2bin(rtc->bcd_dom);
- wtime.tm_mon = bcd2bin(rtc->bcd_mth)-1;
- wtime.tm_year = bcd2bin(rtc->bcd_year);
- if (wtime.tm_year < 70)
- wtime.tm_year += 100;
- wtime.tm_wday = bcd2bin(rtc->bcd_dow)-1;
- rtc->ctrl = 0;
- local_irq_restore(flags);
- return copy_to_user(argp, &wtime, sizeof wtime) ?
- -EFAULT : 0;
- }
- case RTC_SET_TIME: /* Set the RTC */
- {
- struct rtc_time rtc_tm;
- unsigned char mon, day, hrs, min, sec, leap_yr;
- unsigned int yrs;
-
- if (!capable(CAP_SYS_ADMIN))
- return -EACCES;
-
- if (copy_from_user(&rtc_tm, argp, sizeof(struct rtc_time)))
- return -EFAULT;
-
- yrs = rtc_tm.tm_year;
- if (yrs < 1900)
- yrs += 1900;
- mon = rtc_tm.tm_mon + 1; /* tm_mon starts at zero */
- day = rtc_tm.tm_mday;
- hrs = rtc_tm.tm_hour;
- min = rtc_tm.tm_min;
- sec = rtc_tm.tm_sec;
-
- leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
-
- if ((mon > 12) || (day == 0))
- return -EINVAL;
-
- if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
- return -EINVAL;
-
- if ((hrs >= 24) || (min >= 60) || (sec >= 60))
- return -EINVAL;
-
- if (yrs >= 2070)
- return -EINVAL;
-
- local_irq_save(flags);
- rtc->ctrl = RTC_WRITE;
-
- rtc->bcd_sec = bin2bcd(sec);
- rtc->bcd_min = bin2bcd(min);
- rtc->bcd_hr = bin2bcd(hrs);
- rtc->bcd_dom = bin2bcd(day);
- rtc->bcd_mth = bin2bcd(mon);
- rtc->bcd_year = bin2bcd(yrs%100);
-
- rtc->ctrl = 0;
- local_irq_restore(flags);
- return 0;
- }
- default:
- return -EINVAL;
- }
-}
-
-/*
- * We enforce only one user at a time here with the open/close.
- */
-static int rtc_open(struct inode *inode, struct file *file)
-{
- if( !atomic_dec_and_test(&rtc_ready) )
- {
- atomic_inc( &rtc_ready );
- return -EBUSY;
- }
- return 0;
-}
-
-static int rtc_release(struct inode *inode, struct file *file)
-{
- atomic_inc( &rtc_ready );
- return 0;
-}
-
-/*
- * The various file operations we support.
- */
-
-static const struct file_operations rtc_fops = {
- .unlocked_ioctl = rtc_ioctl,
- .open = rtc_open,
- .release = rtc_release,
- .llseek = noop_llseek,
-};
-
-static struct miscdevice rtc_dev=
-{
- .minor = RTC_MINOR,
- .name = "rtc",
- .fops = &rtc_fops
-};
-
-static int __init rtc_MK48T08_init(void)
-{
- if (!MACH_IS_MVME16x)
- return -ENODEV;
-
- pr_info("MK48T08 Real Time Clock Driver v%s\n", RTC_VERSION);
- return misc_register(&rtc_dev);
-}
-device_initcall(rtc_MK48T08_init);
diff --git a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
index cce9428afc41..ee71045883e7 100644
--- a/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
+++ b/arch/mips/boot/dts/loongson/ls7a-pch.dtsi
@@ -70,7 +70,6 @@
device_type = "pci";
#address-cells = <3>;
#size-cells = <2>;
- #interrupt-cells = <2>;
msi-parent = <&msi>;
reg = <0 0x1a000000 0 0x02000000>,
@@ -234,7 +233,7 @@
};
};
- pci_bridge@9,0 {
+ pcie@9,0 {
compatible = "pci0014,7a19.1",
"pci0014,7a19",
"pciclass060400",
@@ -244,12 +243,16 @@
interrupts = <32 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 32 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@a,0 {
+ pcie@a,0 {
compatible = "pci0014,7a09.1",
"pci0014,7a09",
"pciclass060400",
@@ -259,12 +262,16 @@
interrupts = <33 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 33 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@b,0 {
+ pcie@b,0 {
compatible = "pci0014,7a09.1",
"pci0014,7a09",
"pciclass060400",
@@ -274,12 +281,16 @@
interrupts = <34 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 34 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@c,0 {
+ pcie@c,0 {
compatible = "pci0014,7a09.1",
"pci0014,7a09",
"pciclass060400",
@@ -289,12 +300,16 @@
interrupts = <35 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 35 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@d,0 {
+ pcie@d,0 {
compatible = "pci0014,7a19.1",
"pci0014,7a19",
"pciclass060400",
@@ -304,12 +319,16 @@
interrupts = <36 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 36 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@e,0 {
+ pcie@e,0 {
compatible = "pci0014,7a09.1",
"pci0014,7a09",
"pciclass060400",
@@ -319,12 +338,16 @@
interrupts = <37 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 37 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@f,0 {
+ pcie@f,0 {
compatible = "pci0014,7a29.1",
"pci0014,7a29",
"pciclass060400",
@@ -334,12 +357,16 @@
interrupts = <40 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 40 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@10,0 {
+ pcie@10,0 {
compatible = "pci0014,7a19.1",
"pci0014,7a19",
"pciclass060400",
@@ -349,12 +376,16 @@
interrupts = <41 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 41 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@11,0 {
+ pcie@11,0 {
compatible = "pci0014,7a29.1",
"pci0014,7a29",
"pciclass060400",
@@ -364,12 +395,16 @@
interrupts = <42 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 42 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@12,0 {
+ pcie@12,0 {
compatible = "pci0014,7a19.1",
"pci0014,7a19",
"pciclass060400",
@@ -379,12 +414,16 @@
interrupts = <43 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 43 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@13,0 {
+ pcie@13,0 {
compatible = "pci0014,7a29.1",
"pci0014,7a29",
"pciclass060400",
@@ -394,12 +433,16 @@
interrupts = <38 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 38 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
- pci_bridge@14,0 {
+ pcie@14,0 {
compatible = "pci0014,7a19.1",
"pci0014,7a19",
"pciclass060400",
@@ -409,9 +452,13 @@
interrupts = <39 IRQ_TYPE_LEVEL_HIGH>;
interrupt-parent = <&pic>;
+ #address-cells = <3>;
+ #size-cells = <2>;
+ device_type = "pci";
#interrupt-cells = <1>;
interrupt-map-mask = <0 0 0 0>;
interrupt-map = <0 0 0 0 &pic 39 IRQ_TYPE_LEVEL_HIGH>;
+ ranges;
};
};
diff --git a/arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi b/arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi
deleted file mode 100644
index 17a342cc744e..000000000000
--- a/arch/mips/boot/dts/mobileye/eyeq5-clocks.dtsi
+++ /dev/null
@@ -1,270 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-/*
- * Copyright 2023 Mobileye Vision Technologies Ltd.
- */
-
-#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
-
-/ {
- /* Fixed clock */
- xtal: xtal {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <30000000>;
- };
-
-/* PLL_CPU derivatives */
- occ_cpu: occ-cpu {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_CPU>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- si_css0_ref_clk: si-css0-ref-clk { /* gate ClkRstGen_si_css0_ref */
- compatible = "fixed-factor-clock";
- clocks = <&occ_cpu>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- cpc_clk: cpc-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- core0_clk: core0-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- core1_clk: core1-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- core2_clk: core2-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- core3_clk: core3-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- cm_clk: cm-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- mem_clk: mem-clk {
- compatible = "fixed-factor-clock";
- clocks = <&si_css0_ref_clk>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- occ_isram: occ-isram {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_CPU>;
- #clock-cells = <0>;
- clock-div = <2>;
- clock-mult = <1>;
- };
- isram_clk: isram-clk { /* gate ClkRstGen_isram */
- compatible = "fixed-factor-clock";
- clocks = <&occ_isram>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- occ_dbu: occ-dbu {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_CPU>;
- #clock-cells = <0>;
- clock-div = <10>;
- clock-mult = <1>;
- };
- si_dbu_tp_pclk: si-dbu-tp-pclk { /* gate ClkRstGen_dbu */
- compatible = "fixed-factor-clock";
- clocks = <&occ_dbu>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
-/* PLL_VDI derivatives */
- occ_vdi: occ-vdi {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_VDI>;
- #clock-cells = <0>;
- clock-div = <2>;
- clock-mult = <1>;
- };
- vdi_clk: vdi-clk { /* gate ClkRstGen_vdi */
- compatible = "fixed-factor-clock";
- clocks = <&occ_vdi>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- occ_can_ser: occ-can-ser {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_VDI>;
- #clock-cells = <0>;
- clock-div = <16>;
- clock-mult = <1>;
- };
- can_ser_clk: can-ser-clk { /* gate ClkRstGen_can_ser */
- compatible = "fixed-factor-clock";
- clocks = <&occ_can_ser>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- i2c_ser_clk: i2c-ser-clk {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_VDI>;
- #clock-cells = <0>;
- clock-div = <20>;
- clock-mult = <1>;
- };
-/* PLL_PER derivatives */
- occ_periph: occ-periph {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <16>;
- clock-mult = <1>;
- };
- periph_clk: periph-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- can_clk: can-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- spi_clk: spi-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- uart_clk: uart-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
- i2c_clk: i2c-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- clock-output-names = "i2c_clk";
- };
- timer_clk: timer-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- clock-output-names = "timer_clk";
- };
- gpio_clk: gpio-clk {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- clock-output-names = "gpio_clk";
- };
- emmc_sys_clk: emmc-sys-clk {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <10>;
- clock-mult = <1>;
- clock-output-names = "emmc_sys_clk";
- };
- ccf_ctrl_clk: ccf-ctrl-clk {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <4>;
- clock-mult = <1>;
- clock-output-names = "ccf_ctrl_clk";
- };
- occ_mjpeg_core: occ-mjpeg-core {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <2>;
- clock-mult = <1>;
- clock-output-names = "occ_mjpeg_core";
- };
- hsm_clk: hsm-clk { /* gate ClkRstGen_hsm */
- compatible = "fixed-factor-clock";
- clocks = <&occ_mjpeg_core>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- clock-output-names = "hsm_clk";
- };
- mjpeg_core_clk: mjpeg-core-clk { /* gate ClkRstGen_mjpeg_gen */
- compatible = "fixed-factor-clock";
- clocks = <&occ_mjpeg_core>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- clock-output-names = "mjpeg_core_clk";
- };
- fcmu_a_clk: fcmu-a-clk {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <20>;
- clock-mult = <1>;
- clock-output-names = "fcmu_a_clk";
- };
- occ_pci_sys: occ-pci-sys {
- compatible = "fixed-factor-clock";
- clocks = <&olb EQ5C_PLL_PER>;
- #clock-cells = <0>;
- clock-div = <8>;
- clock-mult = <1>;
- clock-output-names = "occ_pci_sys";
- };
- pclk: pclk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <250000000>; /* 250MHz */
- };
- tsu_clk: tsu-clk {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <125000000>; /* 125MHz */
- };
-};
diff --git a/arch/mips/boot/dts/mobileye/eyeq5.dtsi b/arch/mips/boot/dts/mobileye/eyeq5.dtsi
index 0708771c193d..5d73e8320b8e 100644
--- a/arch/mips/boot/dts/mobileye/eyeq5.dtsi
+++ b/arch/mips/boot/dts/mobileye/eyeq5.dtsi
@@ -5,7 +5,7 @@
#include <dt-bindings/interrupt-controller/mips-gic.h>
-#include "eyeq5-clocks.dtsi"
+#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
/ {
#address-cells = <2>;
@@ -17,7 +17,7 @@
device_type = "cpu";
compatible = "img,i6500";
reg = <0>;
- clocks = <&core0_clk>;
+ clocks = <&olb EQ5C_CPU_CORE0>;
};
};
@@ -64,6 +64,24 @@
#interrupt-cells = <1>;
};
+ xtal: xtal {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <30000000>;
+ };
+
+ pclk: pclk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <250000000>; /* 250MHz */
+ };
+
+ tsu_clk: tsu-clk {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <125000000>; /* 125MHz */
+ };
+
soc: soc {
#address-cells = <2>;
#size-cells = <2>;
@@ -76,7 +94,7 @@
reg-io-width = <4>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&uart_clk>, <&occ_periph>;
+ clocks = <&olb EQ5C_PER_UART>, <&olb EQ5C_PER_OCC>;
clock-names = "uartclk", "apb_pclk";
resets = <&olb 0 10>;
pinctrl-names = "default";
@@ -89,7 +107,7 @@
reg-io-width = <4>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&uart_clk>, <&occ_periph>;
+ clocks = <&olb EQ5C_PER_UART>, <&olb EQ5C_PER_OCC>;
clock-names = "uartclk", "apb_pclk";
resets = <&olb 0 11>;
pinctrl-names = "default";
@@ -102,7 +120,7 @@
reg-io-width = <4>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 6 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&uart_clk>, <&occ_periph>;
+ clocks = <&olb EQ5C_PER_UART>, <&olb EQ5C_PER_OCC>;
clock-names = "uartclk", "apb_pclk";
resets = <&olb 0 12>;
pinctrl-names = "default";
@@ -135,7 +153,7 @@
timer {
compatible = "mti,gic-timer";
interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
- clocks = <&core0_clk>;
+ clocks = <&olb EQ5C_CPU_CORE0>;
};
};
};
diff --git a/arch/mips/boot/dts/mobileye/eyeq6h-fixed-clocks.dtsi b/arch/mips/boot/dts/mobileye/eyeq6h-fixed-clocks.dtsi
deleted file mode 100644
index 5fa99e06fde7..000000000000
--- a/arch/mips/boot/dts/mobileye/eyeq6h-fixed-clocks.dtsi
+++ /dev/null
@@ -1,52 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
-/*
- * Copyright 2023 Mobileye Vision Technologies Ltd.
- */
-
-#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
-
-/ {
- xtal: clock-30000000 {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <30000000>;
- };
-
- pll_west: clock-2000000000-west {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <2000000000>;
- };
-
- pll_cpu: clock-2000000000-cpu {
- compatible = "fixed-clock";
- #clock-cells = <0>;
- clock-frequency = <2000000000>;
- };
-
- /* pll-cpu derivatives */
- occ_cpu: clock-2000000000-occ-cpu {
- compatible = "fixed-factor-clock";
- clocks = <&pll_cpu>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
-
- /* pll-west derivatives */
- occ_periph_w: clock-200000000 {
- compatible = "fixed-factor-clock";
- clocks = <&pll_west>;
- #clock-cells = <0>;
- clock-div = <10>;
- clock-mult = <1>;
- };
- uart_clk: clock-200000000-uart {
- compatible = "fixed-factor-clock";
- clocks = <&occ_periph_w>;
- #clock-cells = <0>;
- clock-div = <1>;
- clock-mult = <1>;
- };
-
-};
diff --git a/arch/mips/boot/dts/mobileye/eyeq6h.dtsi b/arch/mips/boot/dts/mobileye/eyeq6h.dtsi
index 1db3c3cda2e3..4a1a43f351d3 100644
--- a/arch/mips/boot/dts/mobileye/eyeq6h.dtsi
+++ b/arch/mips/boot/dts/mobileye/eyeq6h.dtsi
@@ -5,7 +5,7 @@
#include <dt-bindings/interrupt-controller/mips-gic.h>
-#include "eyeq6h-fixed-clocks.dtsi"
+#include <dt-bindings/clock/mobileye,eyeq5-clk.h>
/ {
#address-cells = <2>;
@@ -17,7 +17,7 @@
device_type = "cpu";
compatible = "img,i6500";
reg = <0>;
- clocks = <&occ_cpu>;
+ clocks = <&olb_central EQ6HC_CENTRAL_CPU_OCC>;
};
};
@@ -32,19 +32,42 @@
#interrupt-cells = <1>;
};
+ xtal: clock-30000000 {
+ compatible = "fixed-clock";
+ #clock-cells = <0>;
+ clock-frequency = <30000000>;
+ };
+
soc: soc {
compatible = "simple-bus";
#address-cells = <2>;
#size-cells = <2>;
ranges;
+ olb_acc: system-controller@d2003000 {
+ compatible = "mobileye,eyeq6h-acc-olb", "syscon";
+ reg = <0x0 0xd2003000 0x0 0x1000>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
+ olb_central: system-controller@d3100000 {
+ compatible = "mobileye,eyeq6h-central-olb", "syscon";
+ reg = <0x0 0xd3100000 0x0 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
uart0: serial@d3331000 {
compatible = "arm,pl011", "arm,primecell";
reg = <0 0xd3331000 0x0 0x1000>;
reg-io-width = <4>;
interrupt-parent = <&gic>;
interrupts = <GIC_SHARED 43 IRQ_TYPE_LEVEL_HIGH>;
- clocks = <&occ_periph_w>, <&occ_periph_w>;
+ clocks = <&olb_west EQ6HC_WEST_PER_UART>, <&olb_west EQ6HC_WEST_PER_OCC>;
clock-names = "uartclk", "apb_pclk";
};
@@ -56,6 +79,15 @@
pinctrl-single,function-mask = <0xffff>;
};
+ olb_west: system-controller@d3338000 {
+ compatible = "mobileye,eyeq6h-west-olb", "syscon";
+ reg = <0x0 0xd3338000 0x0 0x1000>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
pinctrl_east: pinctrl@d3357000 {
compatible = "pinctrl-single";
reg = <0x0 0xd3357000 0x0 0xb0>;
@@ -64,6 +96,23 @@
pinctrl-single,function-mask = <0xffff>;
};
+ olb_east: system-controller@d3358000 {
+ compatible = "mobileye,eyeq6h-east-olb", "syscon";
+ reg = <0x0 0xd3358000 0x0 0x1000>;
+ #reset-cells = <1>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
+ olb_south: system-controller@d8013000 {
+ compatible = "mobileye,eyeq6h-south-olb", "syscon";
+ reg = <0x0 0xd8013000 0x0 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
pinctrl_south: pinctrl@d8014000 {
compatible = "pinctrl-single";
reg = <0x0 0xd8014000 0x0 0xf8>;
@@ -72,6 +121,22 @@
pinctrl-single,function-mask = <0xffff>;
};
+ olb_ddr0: system-controller@e4080000 {
+ compatible = "mobileye,eyeq6h-ddr0-olb", "syscon";
+ reg = <0x0 0xe4080000 0x0 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
+ olb_ddr1: system-controller@e4081000 {
+ compatible = "mobileye,eyeq6h-ddr1-olb", "syscon";
+ reg = <0x0 0xe4081000 0x0 0x1000>;
+ #clock-cells = <1>;
+ clocks = <&xtal>;
+ clock-names = "ref";
+ };
+
gic: interrupt-controller@f0920000 {
compatible = "mti,gic";
reg = <0x0 0xf0920000 0x0 0x20000>;
@@ -89,7 +154,7 @@
timer {
compatible = "mti,gic-timer";
interrupts = <GIC_LOCAL 1 IRQ_TYPE_NONE>;
- clocks = <&occ_cpu>;
+ clocks = <&olb_central EQ6HC_CENTRAL_CPU_OCC>;
};
};
};
diff --git a/arch/mips/boot/dts/realtek/rtl930x.dtsi b/arch/mips/boot/dts/realtek/rtl930x.dtsi
index 6a6f3f3fe389..17577457d159 100644
--- a/arch/mips/boot/dts/realtek/rtl930x.dtsi
+++ b/arch/mips/boot/dts/realtek/rtl930x.dtsi
@@ -61,6 +61,8 @@
};
&soc {
+ ranges = <0x0 0x18000000 0x20000>;
+
intc: interrupt-controller@3000 {
compatible = "realtek,rtl9300-intc", "realtek,rtl-intc";
reg = <0x3000 0x18>, <0x3018 0x18>;
@@ -88,6 +90,17 @@
interrupts = <7>, <8>, <9>, <10>, <11>;
clocks = <&lx_clk>;
};
+
+ snand: spi@1a400 {
+ compatible = "realtek,rtl9301-snand";
+ reg = <0x1a400 0x44>;
+ interrupt-parent = <&intc>;
+ interrupts = <19>;
+ clocks = <&lx_clk>;
+ #address-cells = <1>;
+ #size-cells = <0>;
+ status = "disabled";
+ };
};
&uart0 {
diff --git a/arch/mips/include/uapi/asm/socket.h b/arch/mips/include/uapi/asm/socket.h
index d118d4731580..22fa8f19924a 100644
--- a/arch/mips/include/uapi/asm/socket.h
+++ b/arch/mips/include/uapi/asm/socket.h
@@ -159,6 +159,8 @@
#define SCM_TS_OPT_ID 81
+#define SO_RCVPRIORITY 82
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
diff --git a/arch/mips/kernel/head.S b/arch/mips/kernel/head.S
index b825ed4476c7..e3ff6179c99f 100644
--- a/arch/mips/kernel/head.S
+++ b/arch/mips/kernel/head.S
@@ -59,6 +59,7 @@
#endif
.endm
+ __HEAD
#ifndef CONFIG_NO_EXCEPT_FILL
/*
* Reserved space for exception handlers.
diff --git a/arch/mips/kernel/vmlinux.lds.S b/arch/mips/kernel/vmlinux.lds.S
index 9ff55cb80a64..2b708fac8d2c 100644
--- a/arch/mips/kernel/vmlinux.lds.S
+++ b/arch/mips/kernel/vmlinux.lds.S
@@ -61,6 +61,7 @@ SECTIONS
/* read-only */
_text = .; /* Text and read-only data */
.text : {
+ HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/mips/pci/pci-xtalk-bridge.c b/arch/mips/pci/pci-xtalk-bridge.c
index 45ddbaa6c123..dae856fb3e5b 100644
--- a/arch/mips/pci/pci-xtalk-bridge.c
+++ b/arch/mips/pci/pci-xtalk-bridge.c
@@ -749,7 +749,7 @@ static void bridge_remove(struct platform_device *pdev)
static struct platform_driver bridge_driver = {
.probe = bridge_probe,
- .remove_new = bridge_remove,
+ .remove = bridge_remove,
.driver = {
.name = "xtalk-bridge",
}
diff --git a/arch/nios2/kernel/cpuinfo.c b/arch/nios2/kernel/cpuinfo.c
index 338849c430a5..7b1e8f9128e9 100644
--- a/arch/nios2/kernel/cpuinfo.c
+++ b/arch/nios2/kernel/cpuinfo.c
@@ -143,11 +143,11 @@ static int show_cpuinfo(struct seq_file *m, void *v)
" DIV:\t\t%s\n"
" BMX:\t\t%s\n"
" CDX:\t\t%s\n",
- cpuinfo.has_mul ? "yes" : "no",
- cpuinfo.has_mulx ? "yes" : "no",
- cpuinfo.has_div ? "yes" : "no",
- cpuinfo.has_bmx ? "yes" : "no",
- cpuinfo.has_cdx ? "yes" : "no");
+ str_yes_no(cpuinfo.has_mul),
+ str_yes_no(cpuinfo.has_mulx),
+ str_yes_no(cpuinfo.has_div),
+ str_yes_no(cpuinfo.has_bmx),
+ str_yes_no(cpuinfo.has_cdx));
seq_printf(m,
"Icache:\t\t%ukB, line length: %u\n",
diff --git a/arch/openrisc/kernel/entry.S b/arch/openrisc/kernel/entry.S
index 440711d7bf40..ce6f2b08a35e 100644
--- a/arch/openrisc/kernel/entry.S
+++ b/arch/openrisc/kernel/entry.S
@@ -239,6 +239,8 @@ handler: ;\
/* =====================================================[ exceptions] === */
+ __REF
+
/* ---[ 0x100: RESET exception ]----------------------------------------- */
EXCEPTION_ENTRY(_tng_kernel_start)
diff --git a/arch/openrisc/kernel/head.S b/arch/openrisc/kernel/head.S
index 439e00f81e5d..bd760066f1cd 100644
--- a/arch/openrisc/kernel/head.S
+++ b/arch/openrisc/kernel/head.S
@@ -26,15 +26,15 @@
#include <asm/asm-offsets.h>
#include <linux/of_fdt.h>
-#define tophys(rd,rs) \
- l.movhi rd,hi(-KERNELBASE) ;\
+#define tophys(rd,rs) \
+ l.movhi rd,hi(-KERNELBASE) ;\
l.add rd,rd,rs
-#define CLEAR_GPR(gpr) \
+#define CLEAR_GPR(gpr) \
l.movhi gpr,0x0
-#define LOAD_SYMBOL_2_GPR(gpr,symbol) \
- l.movhi gpr,hi(symbol) ;\
+#define LOAD_SYMBOL_2_GPR(gpr,symbol) \
+ l.movhi gpr,hi(symbol) ;\
l.ori gpr,gpr,lo(symbol)
@@ -326,21 +326,21 @@
l.addi r1,r1,-(INT_FRAME_SIZE) ;\
/* r1 is KSP, r30 is __pa(KSP) */ ;\
tophys (r30,r1) ;\
- l.sw PT_GPR12(r30),r12 ;\
+ l.sw PT_GPR12(r30),r12 ;\
l.mfspr r12,r0,SPR_EPCR_BASE ;\
l.sw PT_PC(r30),r12 ;\
l.mfspr r12,r0,SPR_ESR_BASE ;\
l.sw PT_SR(r30),r12 ;\
/* save r31 */ ;\
EXCEPTION_T_LOAD_GPR30(r12) ;\
- l.sw PT_GPR30(r30),r12 ;\
+ l.sw PT_GPR30(r30),r12 ;\
/* save r10 as was prior to exception */ ;\
EXCEPTION_T_LOAD_GPR10(r12) ;\
- l.sw PT_GPR10(r30),r12 ;\
- /* save PT_SP as was prior to exception */ ;\
+ l.sw PT_GPR10(r30),r12 ;\
+ /* save PT_SP as was prior to exception */ ;\
EXCEPTION_T_LOAD_SP(r12) ;\
l.sw PT_SP(r30),r12 ;\
- l.sw PT_GPR13(r30),r13 ;\
+ l.sw PT_GPR13(r30),r13 ;\
/* --> */ ;\
/* save exception r4, set r4 = EA */ ;\
l.sw PT_GPR4(r30),r4 ;\
@@ -357,6 +357,8 @@
/* =====================================================[ exceptions] === */
+ __HEAD
+
/* ---[ 0x100: RESET exception ]----------------------------------------- */
.org 0x100
/* Jump to .init code at _start which lives in the .head section
@@ -394,7 +396,7 @@ _dispatch_do_ipage_fault:
.org 0x500
EXCEPTION_HANDLE(_timer_handler)
-/* ---[ 0x600: Alignment exception ]-------------------------------------- */
+/* ---[ 0x600: Alignment exception ]------------------------------------- */
.org 0x600
EXCEPTION_HANDLE(_alignment_handler)
@@ -424,7 +426,7 @@ _dispatch_do_ipage_fault:
.org 0xc00
EXCEPTION_HANDLE(_sys_call_handler)
-/* ---[ 0xd00: Floating point exception ]--------------------------------- */
+/* ---[ 0xd00: Floating point exception ]-------------------------------- */
.org 0xd00
EXCEPTION_HANDLE(_fpe_trap_handler)
@@ -506,10 +508,10 @@ _dispatch_do_ipage_fault:
/* .text*/
-/* This early stuff belongs in HEAD, but some of the functions below definitely
+/* This early stuff belongs in the .init.text section, but some of the functions below definitely
* don't... */
- __HEAD
+ __INIT
.global _start
_start:
/* Init r0 to zero as per spec */
@@ -816,7 +818,7 @@ secondary_start:
#endif
-/* ========================================[ cache ]=== */
+/* ==========================================================[ cache ]=== */
/* alignment here so we don't change memory offsets with
* memory controller defined
diff --git a/arch/openrisc/kernel/vmlinux.lds.S b/arch/openrisc/kernel/vmlinux.lds.S
index bc1306047837..049bff45f612 100644
--- a/arch/openrisc/kernel/vmlinux.lds.S
+++ b/arch/openrisc/kernel/vmlinux.lds.S
@@ -50,6 +50,7 @@ SECTIONS
.text : AT(ADDR(.text) - LOAD_OFFSET)
{
_stext = .;
+ HEAD_TEXT
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
@@ -83,8 +84,6 @@ SECTIONS
. = ALIGN(PAGE_SIZE);
__init_begin = .;
- HEAD_TEXT_SECTION
-
/* Page aligned */
INIT_TEXT_SECTION(PAGE_SIZE)
diff --git a/arch/parisc/include/uapi/asm/socket.h b/arch/parisc/include/uapi/asm/socket.h
index d268d69bfcd2..aa9cd4b951fe 100644
--- a/arch/parisc/include/uapi/asm/socket.h
+++ b/arch/parisc/include/uapi/asm/socket.h
@@ -140,6 +140,8 @@
#define SCM_TS_OPT_ID 0x404C
+#define SO_RCVPRIORITY 0x404D
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64
diff --git a/arch/powerpc/Makefile b/arch/powerpc/Makefile
index 41489483a602..f3804103c56c 100644
--- a/arch/powerpc/Makefile
+++ b/arch/powerpc/Makefile
@@ -403,10 +403,12 @@ PHONY += stack_protector_prepare
stack_protector_prepare: prepare0
ifdef CONFIG_PPC64
$(eval KBUILD_CFLAGS += -mstack-protector-guard=tls -mstack-protector-guard-reg=r13 \
- -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "PACA_CANARY") print $$3;}' include/generated/asm-offsets.h))
+ -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "PACA_CANARY") print $$3;}' \
+ $(objtree)/include/generated/asm-offsets.h))
else
$(eval KBUILD_CFLAGS += -mstack-protector-guard=tls -mstack-protector-guard-reg=r2 \
- -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' include/generated/asm-offsets.h))
+ -mstack-protector-guard-offset=$(shell awk '{if ($$2 == "TASK_CANARY") print $$3;}' \
+ $(objtree)/include/generated/asm-offsets.h))
endif
endif
diff --git a/arch/powerpc/configs/pmac32_defconfig b/arch/powerpc/configs/pmac32_defconfig
index 57ded82c2840..e8b3f67bf3f5 100644
--- a/arch/powerpc/configs/pmac32_defconfig
+++ b/arch/powerpc/configs/pmac32_defconfig
@@ -208,6 +208,7 @@ CONFIG_FB_ATY=y
CONFIG_FB_ATY_CT=y
CONFIG_FB_ATY_GX=y
CONFIG_FB_3DFX=y
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
# CONFIG_VGA_CONSOLE is not set
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_LOGO=y
diff --git a/arch/powerpc/configs/ppc6xx_defconfig b/arch/powerpc/configs/ppc6xx_defconfig
index 4d77e17541e9..ca0c90e95837 100644
--- a/arch/powerpc/configs/ppc6xx_defconfig
+++ b/arch/powerpc/configs/ppc6xx_defconfig
@@ -716,6 +716,7 @@ CONFIG_FB_TRIDENT=m
CONFIG_FB_SM501=m
CONFIG_FB_IBM_GXT4500=y
CONFIG_LCD_PLATFORM=m
+CONFIG_BACKLIGHT_CLASS_DEVICE=y
CONFIG_FRAMEBUFFER_CONSOLE=y
CONFIG_FRAMEBUFFER_CONSOLE_ROTATION=y
CONFIG_LOGO=y
diff --git a/arch/powerpc/crypto/vmx.c b/arch/powerpc/crypto/vmx.c
index 7eb713cc87c8..0b725e826388 100644
--- a/arch/powerpc/crypto/vmx.c
+++ b/arch/powerpc/crypto/vmx.c
@@ -74,4 +74,4 @@ MODULE_DESCRIPTION("IBM VMX cryptographic acceleration instructions "
"support on Power 8");
MODULE_LICENSE("GPL");
MODULE_VERSION("1.0.0");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/arch/powerpc/kernel/prom_init.c b/arch/powerpc/kernel/prom_init.c
index 73210e5bcfa7..8e776ba39497 100644
--- a/arch/powerpc/kernel/prom_init.c
+++ b/arch/powerpc/kernel/prom_init.c
@@ -2848,7 +2848,7 @@ static void __init fixup_device_tree_chrp(void)
#endif
#if defined(CONFIG_PPC64) && defined(CONFIG_PPC_PMAC)
-static void __init fixup_device_tree_pmac(void)
+static void __init fixup_device_tree_pmac64(void)
{
phandle u3, i2c, mpic;
u32 u3_rev;
@@ -2888,7 +2888,31 @@ static void __init fixup_device_tree_pmac(void)
&parent, sizeof(parent));
}
#else
-#define fixup_device_tree_pmac()
+#define fixup_device_tree_pmac64()
+#endif
+
+#ifdef CONFIG_PPC_PMAC
+static void __init fixup_device_tree_pmac(void)
+{
+ __be32 val = 1;
+ char type[8];
+ phandle node;
+
+ // Some pmacs are missing #size-cells on escc nodes
+ for (node = 0; prom_next_node(&node); ) {
+ type[0] = '\0';
+ prom_getprop(node, "device_type", type, sizeof(type));
+ if (prom_strcmp(type, "escc"))
+ continue;
+
+ if (prom_getproplen(node, "#size-cells") != PROM_ERROR)
+ continue;
+
+ prom_setprop(node, NULL, "#size-cells", &val, sizeof(val));
+ }
+}
+#else
+static inline void fixup_device_tree_pmac(void) { }
#endif
#ifdef CONFIG_PPC_EFIKA
@@ -3111,6 +3135,7 @@ static void __init fixup_device_tree(void)
{
fixup_device_tree_chrp();
fixup_device_tree_pmac();
+ fixup_device_tree_pmac64();
fixup_device_tree_efika();
fixup_device_tree_pasemi();
}
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index f381b177ea06..0b6365d85d11 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -464,7 +464,43 @@ static vm_fault_t vas_mmap_fault(struct vm_fault *vmf)
return VM_FAULT_SIGBUS;
}
+/*
+ * During mmap() paste address, mapping VMA is saved in VAS window
+ * struct which is used to unmap during migration if the window is
+ * still open. But the user space can remove this mapping with
+ * munmap() before closing the window and the VMA address will
+ * be invalid. Set VAS window VMA to NULL in this function which
+ * is called before VMA free.
+ */
+static void vas_mmap_close(struct vm_area_struct *vma)
+{
+ struct file *fp = vma->vm_file;
+ struct coproc_instance *cp_inst = fp->private_data;
+ struct vas_window *txwin;
+
+ /* Should not happen */
+ if (!cp_inst || !cp_inst->txwin) {
+ pr_err("No attached VAS window for the paste address mmap\n");
+ return;
+ }
+
+ txwin = cp_inst->txwin;
+ /*
+ * task_ref.vma is set in coproc_mmap() during mmap paste
+ * address. So it has to be the same VMA that is getting freed.
+ */
+ if (WARN_ON(txwin->task_ref.vma != vma)) {
+ pr_err("Invalid paste address mmaping\n");
+ return;
+ }
+
+ mutex_lock(&txwin->task_ref.mmap_mutex);
+ txwin->task_ref.vma = NULL;
+ mutex_unlock(&txwin->task_ref.mmap_mutex);
+}
+
static const struct vm_operations_struct vas_vm_ops = {
+ .close = vas_mmap_close,
.fault = vas_mmap_fault,
};
diff --git a/arch/powerpc/platforms/pseries/svm.c b/arch/powerpc/platforms/pseries/svm.c
index c5d0f92c7969..384c9dc1899a 100644
--- a/arch/powerpc/platforms/pseries/svm.c
+++ b/arch/powerpc/platforms/pseries/svm.c
@@ -10,7 +10,6 @@
#include <linux/memblock.h>
#include <linux/mem_encrypt.h>
#include <linux/cc_platform.h>
-#include <linux/mem_encrypt.h>
#include <asm/machdep.h>
#include <asm/svm.h>
#include <asm/swiotlb.h>
diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig
index cc63aef41e94..d4a7ca0388c0 100644
--- a/arch/riscv/Kconfig
+++ b/arch/riscv/Kconfig
@@ -32,6 +32,7 @@ config RISCV
select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
select ARCH_HAS_GIGANTIC_PAGE
+ select ARCH_HAS_HW_PTE_YOUNG
select ARCH_HAS_KCOV
select ARCH_HAS_KERNEL_FPU_SUPPORT if 64BIT && FPU
select ARCH_HAS_MEMBARRIER_CALLBACKS
diff --git a/arch/riscv/Makefile b/arch/riscv/Makefile
index 9fe1ee740dda..13fbc0f94238 100644
--- a/arch/riscv/Makefile
+++ b/arch/riscv/Makefile
@@ -135,7 +135,7 @@ stack_protector_prepare: prepare0
-mstack-protector-guard-reg=tp \
-mstack-protector-guard-offset=$(shell \
awk '{if ($$2 == "TSK_STACK_CANARY") print $$3;}' \
- include/generated/asm-offsets.h))
+ $(objtree)/include/generated/asm-offsets.h))
endif
# arch specific predefines for sparse
diff --git a/arch/riscv/include/asm/csr.h b/arch/riscv/include/asm/csr.h
index fe5d4eb9adea..37bdea65bbd8 100644
--- a/arch/riscv/include/asm/csr.h
+++ b/arch/riscv/include/asm/csr.h
@@ -199,6 +199,7 @@
/* xENVCFG flags */
#define ENVCFG_STCE (_AC(1, ULL) << 63)
#define ENVCFG_PBMTE (_AC(1, ULL) << 62)
+#define ENVCFG_ADUE (_AC(1, ULL) << 61)
#define ENVCFG_PMM (_AC(0x3, ULL) << 32)
#define ENVCFG_PMM_PMLEN_0 (_AC(0x0, ULL) << 32)
#define ENVCFG_PMM_PMLEN_7 (_AC(0x2, ULL) << 32)
diff --git a/arch/riscv/include/asm/hwcap.h b/arch/riscv/include/asm/hwcap.h
index 08d2a5697466..869da082252a 100644
--- a/arch/riscv/include/asm/hwcap.h
+++ b/arch/riscv/include/asm/hwcap.h
@@ -98,6 +98,8 @@
#define RISCV_ISA_EXT_SSNPM 89
#define RISCV_ISA_EXT_ZABHA 90
#define RISCV_ISA_EXT_ZICCRSE 91
+#define RISCV_ISA_EXT_SVADE 92
+#define RISCV_ISA_EXT_SVADU 93
#define RISCV_ISA_EXT_XLINUXENVCFG 127
diff --git a/arch/riscv/include/asm/kfence.h b/arch/riscv/include/asm/kfence.h
index 7388edd88986..d08bf7fb3aee 100644
--- a/arch/riscv/include/asm/kfence.h
+++ b/arch/riscv/include/asm/kfence.h
@@ -22,7 +22,9 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect)
else
set_pte(pte, __pte(pte_val(ptep_get(pte)) | _PAGE_PRESENT));
- flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+ preempt_disable();
+ local_flush_tlb_kernel_range(addr, addr + PAGE_SIZE);
+ preempt_enable();
return true;
}
diff --git a/arch/riscv/include/asm/pgtable.h b/arch/riscv/include/asm/pgtable.h
index 5d7f3e8c2e50..d4e99eef90ac 100644
--- a/arch/riscv/include/asm/pgtable.h
+++ b/arch/riscv/include/asm/pgtable.h
@@ -113,6 +113,7 @@
#include <asm/tlbflush.h>
#include <linux/mm_types.h>
#include <asm/compat.h>
+#include <asm/cpufeature.h>
#define __page_val_to_pfn(_val) (((_val) & _PAGE_PFN_MASK) >> _PAGE_PFN_SHIFT)
@@ -284,7 +285,6 @@ static inline pte_t pud_pte(pud_t pud)
}
#ifdef CONFIG_RISCV_ISA_SVNAPOT
-#include <asm/cpufeature.h>
static __always_inline bool has_svnapot(void)
{
@@ -656,6 +656,17 @@ static inline pgprot_t pgprot_writecombine(pgprot_t _prot)
}
/*
+ * Both Svade and Svadu control the hardware behavior when the PTE A/D bits need to be set. By
+ * default the M-mode firmware enables the hardware updating scheme when only Svadu is present in
+ * DT.
+ */
+#define arch_has_hw_pte_young arch_has_hw_pte_young
+static inline bool arch_has_hw_pte_young(void)
+{
+ return riscv_has_extension_unlikely(RISCV_ISA_EXT_SVADU);
+}
+
+/*
* THP functions
*/
static inline pmd_t pte_pmd(pte_t pte)
diff --git a/arch/riscv/include/uapi/asm/kvm.h b/arch/riscv/include/uapi/asm/kvm.h
index 4f24201376b1..3482c9a73d1b 100644
--- a/arch/riscv/include/uapi/asm/kvm.h
+++ b/arch/riscv/include/uapi/asm/kvm.h
@@ -177,6 +177,8 @@ enum KVM_RISCV_ISA_EXT_ID {
KVM_RISCV_ISA_EXT_ZAWRS,
KVM_RISCV_ISA_EXT_SMNPM,
KVM_RISCV_ISA_EXT_SSNPM,
+ KVM_RISCV_ISA_EXT_SVADE,
+ KVM_RISCV_ISA_EXT_SVADU,
KVM_RISCV_ISA_EXT_MAX,
};
diff --git a/arch/riscv/kernel/cpufeature.c b/arch/riscv/kernel/cpufeature.c
index 467c5c735bf5..c0916ed318c2 100644
--- a/arch/riscv/kernel/cpufeature.c
+++ b/arch/riscv/kernel/cpufeature.c
@@ -136,6 +136,16 @@ static int riscv_ext_zcf_validate(const struct riscv_isa_ext_data *data,
return -EPROBE_DEFER;
}
+static int riscv_ext_svadu_validate(const struct riscv_isa_ext_data *data,
+ const unsigned long *isa_bitmap)
+{
+ /* SVADE has already been detected, use SVADE only */
+ if (__riscv_isa_extension_available(isa_bitmap, RISCV_ISA_EXT_SVADE))
+ return -EOPNOTSUPP;
+
+ return 0;
+}
+
static const unsigned int riscv_zk_bundled_exts[] = {
RISCV_ISA_EXT_ZBKB,
RISCV_ISA_EXT_ZBKC,
@@ -387,6 +397,8 @@ const struct riscv_isa_ext_data riscv_isa_ext[] = {
__RISCV_ISA_EXT_DATA(sscofpmf, RISCV_ISA_EXT_SSCOFPMF),
__RISCV_ISA_EXT_SUPERSET(ssnpm, RISCV_ISA_EXT_SSNPM, riscv_xlinuxenvcfg_exts),
__RISCV_ISA_EXT_DATA(sstc, RISCV_ISA_EXT_SSTC),
+ __RISCV_ISA_EXT_DATA(svade, RISCV_ISA_EXT_SVADE),
+ __RISCV_ISA_EXT_DATA_VALIDATE(svadu, RISCV_ISA_EXT_SVADU, riscv_ext_svadu_validate),
__RISCV_ISA_EXT_DATA(svinval, RISCV_ISA_EXT_SVINVAL),
__RISCV_ISA_EXT_DATA(svnapot, RISCV_ISA_EXT_SVNAPOT),
__RISCV_ISA_EXT_DATA(svpbmt, RISCV_ISA_EXT_SVPBMT),
diff --git a/arch/riscv/kernel/jump_label.c b/arch/riscv/kernel/jump_label.c
index 6eee6f736f68..654ed159c830 100644
--- a/arch/riscv/kernel/jump_label.c
+++ b/arch/riscv/kernel/jump_label.c
@@ -36,9 +36,15 @@ bool arch_jump_label_transform_queue(struct jump_entry *entry,
insn = RISCV_INSN_NOP;
}
- mutex_lock(&text_mutex);
- patch_insn_write(addr, &insn, sizeof(insn));
- mutex_unlock(&text_mutex);
+ if (early_boot_irqs_disabled) {
+ riscv_patch_in_stop_machine = 1;
+ patch_insn_write(addr, &insn, sizeof(insn));
+ riscv_patch_in_stop_machine = 0;
+ } else {
+ mutex_lock(&text_mutex);
+ patch_insn_write(addr, &insn, sizeof(insn));
+ mutex_unlock(&text_mutex);
+ }
return true;
}
diff --git a/arch/riscv/kernel/setup.c b/arch/riscv/kernel/setup.c
index 016b48fcd6f2..45010e71df86 100644
--- a/arch/riscv/kernel/setup.c
+++ b/arch/riscv/kernel/setup.c
@@ -227,7 +227,7 @@ static void __init init_resources(void)
static void __init parse_dtb(void)
{
/* Early scan of device tree from init memory */
- if (early_init_dt_scan(dtb_early_va, __pa(dtb_early_va))) {
+ if (early_init_dt_scan(dtb_early_va, dtb_early_pa)) {
const char *name = of_flat_dt_get_machine_name();
if (name) {
diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c
index dcced4db7fe8..19afd1f23537 100644
--- a/arch/riscv/kvm/aia.c
+++ b/arch/riscv/kvm/aia.c
@@ -590,7 +590,7 @@ void kvm_riscv_aia_enable(void)
csr_set(CSR_HIE, BIT(IRQ_S_GEXT));
/* Enable IRQ filtering for overflow interrupt only if sscofpmf is present */
if (__riscv_isa_extension_available(NULL, RISCV_ISA_EXT_SSCOFPMF))
- csr_write(CSR_HVIEN, BIT(IRQ_PMU_OVF));
+ csr_set(CSR_HVIEN, BIT(IRQ_PMU_OVF));
}
void kvm_riscv_aia_disable(void)
diff --git a/arch/riscv/kvm/vcpu.c b/arch/riscv/kvm/vcpu.c
index dc3f76f6e46c..e048dcc6e65e 100644
--- a/arch/riscv/kvm/vcpu.c
+++ b/arch/riscv/kvm/vcpu.c
@@ -551,6 +551,10 @@ static void kvm_riscv_vcpu_setup_config(struct kvm_vcpu *vcpu)
if (riscv_isa_extension_available(isa, ZICBOZ))
cfg->henvcfg |= ENVCFG_CBZE;
+ if (riscv_isa_extension_available(isa, SVADU) &&
+ !riscv_isa_extension_available(isa, SVADE))
+ cfg->henvcfg |= ENVCFG_ADUE;
+
if (riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN)) {
cfg->hstateen0 |= SMSTATEEN0_HSENVCFG;
if (riscv_isa_extension_available(isa, SSAIA))
diff --git a/arch/riscv/kvm/vcpu_onereg.c b/arch/riscv/kvm/vcpu_onereg.c
index 5b68490ad9b7..753f66c8b70a 100644
--- a/arch/riscv/kvm/vcpu_onereg.c
+++ b/arch/riscv/kvm/vcpu_onereg.c
@@ -15,6 +15,7 @@
#include <asm/cacheflush.h>
#include <asm/cpufeature.h>
#include <asm/kvm_vcpu_vector.h>
+#include <asm/pgtable.h>
#include <asm/vector.h>
#define KVM_RISCV_BASE_ISA_MASK GENMASK(25, 0)
@@ -40,6 +41,8 @@ static const unsigned long kvm_isa_ext_arr[] = {
KVM_ISA_EXT_ARR(SSCOFPMF),
KVM_ISA_EXT_ARR(SSNPM),
KVM_ISA_EXT_ARR(SSTC),
+ KVM_ISA_EXT_ARR(SVADE),
+ KVM_ISA_EXT_ARR(SVADU),
KVM_ISA_EXT_ARR(SVINVAL),
KVM_ISA_EXT_ARR(SVNAPOT),
KVM_ISA_EXT_ARR(SVPBMT),
@@ -112,6 +115,12 @@ static bool kvm_riscv_vcpu_isa_enable_allowed(unsigned long ext)
case KVM_RISCV_ISA_EXT_SSCOFPMF:
/* Sscofpmf depends on interrupt filtering defined in ssaia */
return __riscv_isa_extension_available(NULL, RISCV_ISA_EXT_SSAIA);
+ case KVM_RISCV_ISA_EXT_SVADU:
+ /*
+ * The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
+ * Guest OS can use Svadu only when host OS enable Svadu.
+ */
+ return arch_has_hw_pte_young();
case KVM_RISCV_ISA_EXT_V:
return riscv_v_vstate_ctrl_user_allowed();
default:
@@ -185,6 +194,12 @@ static bool kvm_riscv_vcpu_isa_disable_allowed(unsigned long ext)
/* Extensions which can be disabled using Smstateen */
case KVM_RISCV_ISA_EXT_SSAIA:
return riscv_has_extension_unlikely(RISCV_ISA_EXT_SMSTATEEN);
+ case KVM_RISCV_ISA_EXT_SVADE:
+ /*
+ * The henvcfg.ADUE is read-only zero if menvcfg.ADUE is zero.
+ * Svade is not allowed to disable when the platform use Svade.
+ */
+ return arch_has_hw_pte_young();
default:
break;
}
diff --git a/arch/riscv/mm/init.c b/arch/riscv/mm/init.c
index 0e8c20adcd98..fc53ce748c80 100644
--- a/arch/riscv/mm/init.c
+++ b/arch/riscv/mm/init.c
@@ -1566,7 +1566,7 @@ static void __meminit free_pte_table(pte_t *pte_start, pmd_t *pmd)
pmd_clear(pmd);
}
-static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
+static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud, bool is_vmemmap)
{
struct page *page = pud_page(*pud);
struct ptdesc *ptdesc = page_ptdesc(page);
@@ -1579,7 +1579,8 @@ static void __meminit free_pmd_table(pmd_t *pmd_start, pud_t *pud)
return;
}
- pagetable_pmd_dtor(ptdesc);
+ if (!is_vmemmap)
+ pagetable_pmd_dtor(ptdesc);
if (PageReserved(page))
free_reserved_page(page);
else
@@ -1703,7 +1704,7 @@ static void __meminit remove_pud_mapping(pud_t *pud_base, unsigned long addr, un
remove_pmd_mapping(pmd_base, addr, next, is_vmemmap, altmap);
if (pgtable_l4_enabled)
- free_pmd_table(pmd_base, pudp);
+ free_pmd_table(pmd_base, pudp, is_vmemmap);
}
}
diff --git a/arch/s390/Kconfig b/arch/s390/Kconfig
index c64b2987d108..0077969170e8 100644
--- a/arch/s390/Kconfig
+++ b/arch/s390/Kconfig
@@ -87,6 +87,7 @@ config S390
select ARCH_HAS_MEMBARRIER_SYNC_CORE
select ARCH_HAS_MEM_ENCRYPT
select ARCH_HAS_NMI_SAFE_THIS_CPU_OPS
+ select ARCH_HAS_PREEMPT_LAZY
select ARCH_HAS_PTE_SPECIAL
select ARCH_HAS_SCALED_CPUTIME
select ARCH_HAS_SET_DIRECT_MAP
@@ -218,6 +219,7 @@ config S390
select HAVE_PERF_EVENTS
select HAVE_PERF_REGS
select HAVE_PERF_USER_STACK_DUMP
+ select HAVE_PREEMPT_DYNAMIC_KEY
select HAVE_REGS_AND_STACK_ACCESS_API
select HAVE_RELIABLE_STACKTRACE
select HAVE_RETHOOK
diff --git a/arch/s390/boot/startup.c b/arch/s390/boot/startup.c
index abe6e6c0ab98..6087d38c7235 100644
--- a/arch/s390/boot/startup.c
+++ b/arch/s390/boot/startup.c
@@ -234,6 +234,8 @@ static unsigned long get_vmem_size(unsigned long identity_size,
vsize = round_up(SZ_2G + max_mappable, rte_size) +
round_up(vmemmap_size, rte_size) +
FIXMAP_SIZE + MODULES_LEN + KASLR_LEN;
+ if (IS_ENABLED(CONFIG_KMSAN))
+ vsize += MODULES_LEN * 2;
return size_add(vsize, vmalloc_size);
}
diff --git a/arch/s390/boot/vmem.c b/arch/s390/boot/vmem.c
index 145035f84a0e..3fa28db2fe59 100644
--- a/arch/s390/boot/vmem.c
+++ b/arch/s390/boot/vmem.c
@@ -306,7 +306,7 @@ static void pgtable_pte_populate(pmd_t *pmd, unsigned long addr, unsigned long e
pages++;
}
}
- if (mode == POPULATE_DIRECT)
+ if (mode == POPULATE_IDENTITY)
update_page_count(PG_DIRECT_MAP_4K, pages);
}
@@ -339,7 +339,7 @@ static void pgtable_pmd_populate(pud_t *pud, unsigned long addr, unsigned long e
}
pgtable_pte_populate(pmd, addr, next, mode);
}
- if (mode == POPULATE_DIRECT)
+ if (mode == POPULATE_IDENTITY)
update_page_count(PG_DIRECT_MAP_1M, pages);
}
@@ -372,7 +372,7 @@ static void pgtable_pud_populate(p4d_t *p4d, unsigned long addr, unsigned long e
}
pgtable_pmd_populate(pud, addr, next, mode);
}
- if (mode == POPULATE_DIRECT)
+ if (mode == POPULATE_IDENTITY)
update_page_count(PG_DIRECT_MAP_2G, pages);
}
diff --git a/arch/s390/crypto/aes_s390.c b/arch/s390/crypto/aes_s390.c
index 8cc02d6e0d0f..9c46b1b630b1 100644
--- a/arch/s390/crypto/aes_s390.c
+++ b/arch/s390/crypto/aes_s390.c
@@ -1168,4 +1168,4 @@ MODULE_ALIAS_CRYPTO("aes-all");
MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/arch/s390/include/asm/debug.h b/arch/s390/include/asm/debug.h
index ccd4e148b5ed..a7f7bdc9e19c 100644
--- a/arch/s390/include/asm/debug.h
+++ b/arch/s390/include/asm/debug.h
@@ -66,14 +66,15 @@ typedef int (debug_header_proc_t) (debug_info_t *id,
struct debug_view *view,
int area,
debug_entry_t *entry,
- char *out_buf);
+ char *out_buf, size_t out_buf_size);
typedef int (debug_format_proc_t) (debug_info_t *id,
struct debug_view *view, char *out_buf,
+ size_t out_buf_size,
const char *in_buf);
typedef int (debug_prolog_proc_t) (debug_info_t *id,
struct debug_view *view,
- char *out_buf);
+ char *out_buf, size_t out_buf_size);
typedef int (debug_input_proc_t) (debug_info_t *id,
struct debug_view *view,
struct file *file,
@@ -81,7 +82,8 @@ typedef int (debug_input_proc_t) (debug_info_t *id,
size_t in_buf_size, loff_t *offset);
int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
- int area, debug_entry_t *entry, char *out_buf);
+ int area, debug_entry_t *entry,
+ char *out_buf, size_t out_buf_size);
struct debug_view {
char name[DEBUG_MAX_NAME_LEN];
diff --git a/arch/s390/include/asm/gmap.h b/arch/s390/include/asm/gmap.h
index 64761c78f774..13f51a6a5bb1 100644
--- a/arch/s390/include/asm/gmap.h
+++ b/arch/s390/include/asm/gmap.h
@@ -17,8 +17,8 @@
#define GMAP_NOTIFY_MPROT 0x1
/* Status bits only for huge segment entries */
-#define _SEGMENT_ENTRY_GMAP_IN 0x8000 /* invalidation notify bit */
-#define _SEGMENT_ENTRY_GMAP_UC 0x4000 /* dirty (migration) */
+#define _SEGMENT_ENTRY_GMAP_IN 0x0800 /* invalidation notify bit */
+#define _SEGMENT_ENTRY_GMAP_UC 0x0002 /* dirty (migration) */
/**
* struct gmap_struct - guest address space
diff --git a/arch/s390/include/asm/hugetlb.h b/arch/s390/include/asm/hugetlb.h
index 6f815d4ba0ca..a40664b236e9 100644
--- a/arch/s390/include/asm/hugetlb.h
+++ b/arch/s390/include/asm/hugetlb.h
@@ -10,6 +10,8 @@
#define _ASM_S390_HUGETLB_H
#include <linux/pgtable.h>
+#include <linux/swap.h>
+#include <linux/swapops.h>
#include <asm/page.h>
#define hugepages_supported() (MACHINE_HAS_EDAT1)
@@ -78,7 +80,7 @@ static inline int huge_pte_none(pte_t pte)
#define __HAVE_ARCH_HUGE_PTE_NONE_MOSTLY
static inline int huge_pte_none_mostly(pte_t pte)
{
- return huge_pte_none(pte);
+ return huge_pte_none(pte) || is_pte_marker(pte);
}
#define __HAVE_ARCH_HUGE_PTE_MKUFFD_WP
diff --git a/arch/s390/include/asm/kvm_host.h b/arch/s390/include/asm/kvm_host.h
index 1cd8eaebd3c0..97c7c8127543 100644
--- a/arch/s390/include/asm/kvm_host.h
+++ b/arch/s390/include/asm/kvm_host.h
@@ -94,11 +94,16 @@ union ipte_control {
};
};
+/*
+ * Utility is defined as two bytes but having it four bytes wide
+ * generates more efficient code. Since the following bytes are
+ * reserved this makes no functional difference.
+ */
union sca_utility {
- __u16 val;
+ __u32 val;
struct {
- __u16 mtcr : 1;
- __u16 reserved : 15;
+ __u32 mtcr : 1;
+ __u32 : 31;
};
};
@@ -107,7 +112,7 @@ struct bsca_block {
__u64 reserved[5];
__u64 mcn;
union sca_utility utility;
- __u8 reserved2[6];
+ __u8 reserved2[4];
struct bsca_entry cpu[KVM_S390_BSCA_CPU_SLOTS];
};
@@ -115,7 +120,7 @@ struct esca_block {
union ipte_control ipte_control;
__u64 reserved1[6];
union sca_utility utility;
- __u8 reserved2[6];
+ __u8 reserved2[4];
__u64 mcn[4];
__u64 reserved3[20];
struct esca_entry cpu[KVM_S390_ESCA_CPU_SLOTS];
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index 8b67036edb69..48268095b0a3 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -277,7 +277,8 @@ static inline int is_module_addr(void *addr)
#define _REGION1_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R1 | _REGION_ENTRY_INVALID)
#define _REGION2_ENTRY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_LENGTH)
#define _REGION2_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R2 | _REGION_ENTRY_INVALID)
-#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH)
+#define _REGION3_ENTRY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_LENGTH | \
+ _REGION3_ENTRY_PRESENT)
#define _REGION3_ENTRY_EMPTY (_REGION_ENTRY_TYPE_R3 | _REGION_ENTRY_INVALID)
#define _REGION3_ENTRY_HARDWARE_BITS 0xfffffffffffff6ffUL
@@ -285,18 +286,27 @@ static inline int is_module_addr(void *addr)
#define _REGION3_ENTRY_ORIGIN_LARGE ~0x7fffffffUL /* large page address */
#define _REGION3_ENTRY_DIRTY 0x2000 /* SW region dirty bit */
#define _REGION3_ENTRY_YOUNG 0x1000 /* SW region young bit */
+#define _REGION3_ENTRY_COMM 0x0010 /* Common-Region, marks swap entry */
#define _REGION3_ENTRY_LARGE 0x0400 /* RTTE-format control, large page */
-#define _REGION3_ENTRY_WRITE 0x0002 /* SW region write bit */
-#define _REGION3_ENTRY_READ 0x0001 /* SW region read bit */
+#define _REGION3_ENTRY_WRITE 0x8000 /* SW region write bit */
+#define _REGION3_ENTRY_READ 0x4000 /* SW region read bit */
#ifdef CONFIG_MEM_SOFT_DIRTY
-#define _REGION3_ENTRY_SOFT_DIRTY 0x4000 /* SW region soft dirty bit */
+#define _REGION3_ENTRY_SOFT_DIRTY 0x0002 /* SW region soft dirty bit */
#else
#define _REGION3_ENTRY_SOFT_DIRTY 0x0000 /* SW region soft dirty bit */
#endif
#define _REGION_ENTRY_BITS 0xfffffffffffff22fUL
+/*
+ * SW region present bit. For non-leaf region-third-table entries, bits 62-63
+ * indicate the TABLE LENGTH and both must be set to 1. But such entries
+ * would always be considered as present, so it is safe to use bit 63 as
+ * PRESENT bit for PUD.
+ */
+#define _REGION3_ENTRY_PRESENT 0x0001
+
/* Bits in the segment table entry */
#define _SEGMENT_ENTRY_BITS 0xfffffffffffffe3fUL
#define _SEGMENT_ENTRY_HARDWARE_BITS 0xfffffffffffffe3cUL
@@ -308,21 +318,29 @@ static inline int is_module_addr(void *addr)
#define _SEGMENT_ENTRY_INVALID 0x20 /* invalid segment table entry */
#define _SEGMENT_ENTRY_TYPE_MASK 0x0c /* segment table type mask */
-#define _SEGMENT_ENTRY (0)
+#define _SEGMENT_ENTRY (_SEGMENT_ENTRY_PRESENT)
#define _SEGMENT_ENTRY_EMPTY (_SEGMENT_ENTRY_INVALID)
#define _SEGMENT_ENTRY_DIRTY 0x2000 /* SW segment dirty bit */
#define _SEGMENT_ENTRY_YOUNG 0x1000 /* SW segment young bit */
+
+#define _SEGMENT_ENTRY_COMM 0x0010 /* Common-Segment, marks swap entry */
#define _SEGMENT_ENTRY_LARGE 0x0400 /* STE-format control, large page */
-#define _SEGMENT_ENTRY_WRITE 0x0002 /* SW segment write bit */
-#define _SEGMENT_ENTRY_READ 0x0001 /* SW segment read bit */
+#define _SEGMENT_ENTRY_WRITE 0x8000 /* SW segment write bit */
+#define _SEGMENT_ENTRY_READ 0x4000 /* SW segment read bit */
#ifdef CONFIG_MEM_SOFT_DIRTY
-#define _SEGMENT_ENTRY_SOFT_DIRTY 0x4000 /* SW segment soft dirty bit */
+#define _SEGMENT_ENTRY_SOFT_DIRTY 0x0002 /* SW segment soft dirty bit */
#else
#define _SEGMENT_ENTRY_SOFT_DIRTY 0x0000 /* SW segment soft dirty bit */
#endif
+#define _SEGMENT_ENTRY_PRESENT 0x0001 /* SW segment present bit */
+
+/* Common bits in region and segment table entries, for swap entries */
+#define _RST_ENTRY_COMM 0x0010 /* Common-Region/Segment, marks swap entry */
+#define _RST_ENTRY_INVALID 0x0020 /* invalid region/segment table entry */
+
#define _CRST_ENTRIES 2048 /* number of region/segment table entries */
#define _PAGE_ENTRIES 256 /* number of page table entries */
@@ -454,17 +472,22 @@ static inline int is_module_addr(void *addr)
/*
* Segment entry (large page) protection definitions.
*/
-#define SEGMENT_NONE __pgprot(_SEGMENT_ENTRY_INVALID | \
+#define SEGMENT_NONE __pgprot(_SEGMENT_ENTRY_PRESENT | \
+ _SEGMENT_ENTRY_INVALID | \
_SEGMENT_ENTRY_PROTECT)
-#define SEGMENT_RO __pgprot(_SEGMENT_ENTRY_PROTECT | \
+#define SEGMENT_RO __pgprot(_SEGMENT_ENTRY_PRESENT | \
+ _SEGMENT_ENTRY_PROTECT | \
_SEGMENT_ENTRY_READ | \
_SEGMENT_ENTRY_NOEXEC)
-#define SEGMENT_RX __pgprot(_SEGMENT_ENTRY_PROTECT | \
+#define SEGMENT_RX __pgprot(_SEGMENT_ENTRY_PRESENT | \
+ _SEGMENT_ENTRY_PROTECT | \
_SEGMENT_ENTRY_READ)
-#define SEGMENT_RW __pgprot(_SEGMENT_ENTRY_READ | \
+#define SEGMENT_RW __pgprot(_SEGMENT_ENTRY_PRESENT | \
+ _SEGMENT_ENTRY_READ | \
_SEGMENT_ENTRY_WRITE | \
_SEGMENT_ENTRY_NOEXEC)
-#define SEGMENT_RWX __pgprot(_SEGMENT_ENTRY_READ | \
+#define SEGMENT_RWX __pgprot(_SEGMENT_ENTRY_PRESENT | \
+ _SEGMENT_ENTRY_READ | \
_SEGMENT_ENTRY_WRITE)
#define SEGMENT_KERNEL __pgprot(_SEGMENT_ENTRY | \
_SEGMENT_ENTRY_LARGE | \
@@ -491,6 +514,7 @@ static inline int is_module_addr(void *addr)
*/
#define REGION3_KERNEL __pgprot(_REGION_ENTRY_TYPE_R3 | \
+ _REGION3_ENTRY_PRESENT | \
_REGION3_ENTRY_LARGE | \
_REGION3_ENTRY_READ | \
_REGION3_ENTRY_WRITE | \
@@ -498,12 +522,14 @@ static inline int is_module_addr(void *addr)
_REGION3_ENTRY_DIRTY | \
_REGION_ENTRY_NOEXEC)
#define REGION3_KERNEL_RO __pgprot(_REGION_ENTRY_TYPE_R3 | \
+ _REGION3_ENTRY_PRESENT | \
_REGION3_ENTRY_LARGE | \
_REGION3_ENTRY_READ | \
_REGION3_ENTRY_YOUNG | \
_REGION_ENTRY_PROTECT | \
_REGION_ENTRY_NOEXEC)
#define REGION3_KERNEL_EXEC __pgprot(_REGION_ENTRY_TYPE_R3 | \
+ _REGION3_ENTRY_PRESENT | \
_REGION3_ENTRY_LARGE | \
_REGION3_ENTRY_READ | \
_REGION3_ENTRY_WRITE | \
@@ -746,7 +772,7 @@ static inline int pud_present(pud_t pud)
{
if (pud_folded(pud))
return 1;
- return (pud_val(pud) & _REGION_ENTRY_ORIGIN) != 0UL;
+ return (pud_val(pud) & _REGION3_ENTRY_PRESENT) != 0;
}
static inline int pud_none(pud_t pud)
@@ -761,13 +787,18 @@ static inline bool pud_leaf(pud_t pud)
{
if ((pud_val(pud) & _REGION_ENTRY_TYPE_MASK) != _REGION_ENTRY_TYPE_R3)
return 0;
- return !!(pud_val(pud) & _REGION3_ENTRY_LARGE);
+ return (pud_present(pud) && (pud_val(pud) & _REGION3_ENTRY_LARGE) != 0);
+}
+
+static inline int pmd_present(pmd_t pmd)
+{
+ return (pmd_val(pmd) & _SEGMENT_ENTRY_PRESENT) != 0;
}
#define pmd_leaf pmd_leaf
static inline bool pmd_leaf(pmd_t pmd)
{
- return (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0;
+ return (pmd_present(pmd) && (pmd_val(pmd) & _SEGMENT_ENTRY_LARGE) != 0);
}
static inline int pmd_bad(pmd_t pmd)
@@ -799,11 +830,6 @@ static inline int p4d_bad(p4d_t p4d)
return (p4d_val(p4d) & ~_REGION_ENTRY_BITS) != 0;
}
-static inline int pmd_present(pmd_t pmd)
-{
- return pmd_val(pmd) != _SEGMENT_ENTRY_EMPTY;
-}
-
static inline int pmd_none(pmd_t pmd)
{
return pmd_val(pmd) == _SEGMENT_ENTRY_EMPTY;
@@ -1851,7 +1877,7 @@ static inline pmd_t pmdp_collapse_flush(struct vm_area_struct *vma,
static inline int pmd_trans_huge(pmd_t pmd)
{
- return pmd_val(pmd) & _SEGMENT_ENTRY_LARGE;
+ return pmd_leaf(pmd);
}
#define has_transparent_hugepage has_transparent_hugepage
@@ -1911,6 +1937,53 @@ static inline swp_entry_t __swp_entry(unsigned long type, unsigned long offset)
#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) })
#define __swp_entry_to_pte(x) ((pte_t) { (x).val })
+/*
+ * 64 bit swap entry format for REGION3 and SEGMENT table entries (RSTE)
+ * Bits 59 and 63 are used to indicate the swap entry. Bit 58 marks the rste
+ * as invalid.
+ * A swap entry is indicated by bit pattern (rste & 0x011) == 0x010
+ * | offset |Xtype |11TT|S0|
+ * |0000000000111111111122222222223333333333444444444455|555555|5566|66|
+ * |0123456789012345678901234567890123456789012345678901|234567|8901|23|
+ *
+ * Bits 0-51 store the offset.
+ * Bits 53-57 store the type.
+ * Bit 62 (S) is used for softdirty tracking.
+ * Bits 60-61 (TT) indicate the table type: 0x01 for REGION3 and 0x00 for SEGMENT.
+ * Bit 52 (X) is unused.
+ */
+
+#define __SWP_OFFSET_MASK_RSTE ((1UL << 52) - 1)
+#define __SWP_OFFSET_SHIFT_RSTE 12
+#define __SWP_TYPE_MASK_RSTE ((1UL << 5) - 1)
+#define __SWP_TYPE_SHIFT_RSTE 6
+
+/*
+ * TT bits set to 0x00 == SEGMENT. For REGION3 entries, caller must add R3
+ * bits 0x01. See also __set_huge_pte_at().
+ */
+static inline unsigned long mk_swap_rste(unsigned long type, unsigned long offset)
+{
+ unsigned long rste;
+
+ rste = _RST_ENTRY_INVALID | _RST_ENTRY_COMM;
+ rste |= (offset & __SWP_OFFSET_MASK_RSTE) << __SWP_OFFSET_SHIFT_RSTE;
+ rste |= (type & __SWP_TYPE_MASK_RSTE) << __SWP_TYPE_SHIFT_RSTE;
+ return rste;
+}
+
+static inline unsigned long __swp_type_rste(swp_entry_t entry)
+{
+ return (entry.val >> __SWP_TYPE_SHIFT_RSTE) & __SWP_TYPE_MASK_RSTE;
+}
+
+static inline unsigned long __swp_offset_rste(swp_entry_t entry)
+{
+ return (entry.val >> __SWP_OFFSET_SHIFT_RSTE) & __SWP_OFFSET_MASK_RSTE;
+}
+
+#define __rste_to_swp_entry(rste) ((swp_entry_t) { rste })
+
extern int vmem_add_mapping(unsigned long start, unsigned long size);
extern void vmem_remove_mapping(unsigned long start, unsigned long size);
extern int __vmem_map_4k_page(unsigned long addr, unsigned long phys, pgprot_t prot, bool alloc);
diff --git a/arch/s390/include/asm/preempt.h b/arch/s390/include/asm/preempt.h
index 0cde7e240373..2c29bdf12127 100644
--- a/arch/s390/include/asm/preempt.h
+++ b/arch/s390/include/asm/preempt.h
@@ -130,10 +130,24 @@ static __always_inline bool should_resched(int preempt_offset)
#define init_idle_preempt_count(p, cpu) do { } while (0)
#ifdef CONFIG_PREEMPTION
-extern void preempt_schedule(void);
-#define __preempt_schedule() preempt_schedule()
-extern void preempt_schedule_notrace(void);
-#define __preempt_schedule_notrace() preempt_schedule_notrace()
+
+void preempt_schedule(void);
+void preempt_schedule_notrace(void);
+
+#ifdef CONFIG_PREEMPT_DYNAMIC
+
+void dynamic_preempt_schedule(void);
+void dynamic_preempt_schedule_notrace(void);
+#define __preempt_schedule() dynamic_preempt_schedule()
+#define __preempt_schedule_notrace() dynamic_preempt_schedule_notrace()
+
+#else /* CONFIG_PREEMPT_DYNAMIC */
+
+#define __preempt_schedule() preempt_schedule()
+#define __preempt_schedule_notrace() preempt_schedule_notrace()
+
+#endif /* CONFIG_PREEMPT_DYNAMIC */
+
#endif /* CONFIG_PREEMPTION */
#endif /* __ASM_PREEMPT_H */
diff --git a/arch/s390/include/asm/spinlock.h b/arch/s390/include/asm/spinlock.h
index ac868a9bb0d1..f87dd0a84855 100644
--- a/arch/s390/include/asm/spinlock.h
+++ b/arch/s390/include/asm/spinlock.h
@@ -82,9 +82,10 @@ static inline void arch_spin_unlock(arch_spinlock_t *lp)
kcsan_release();
asm_inline volatile(
ALTERNATIVE("nop", ".insn rre,0xb2fa0000,7,0", ALT_FACILITY(49)) /* NIAI 7 */
- " sth %1,%0\n"
- : "=R" (((unsigned short *) &lp->lock)[1])
- : "d" (0) : "cc", "memory");
+ " mvhhi %[lock],0\n"
+ : [lock] "=Q" (((unsigned short *)&lp->lock)[1])
+ :
+ : "memory");
}
/*
diff --git a/arch/s390/include/asm/thread_info.h b/arch/s390/include/asm/thread_info.h
index 00ac01874a12..c33f7144d1b9 100644
--- a/arch/s390/include/asm/thread_info.h
+++ b/arch/s390/include/asm/thread_info.h
@@ -61,44 +61,45 @@ void arch_setup_new_exec(void);
/*
* thread information flags bit numbers
*/
-/* _TIF_WORK bits */
#define TIF_NOTIFY_RESUME 0 /* callback before returning to user */
#define TIF_SIGPENDING 1 /* signal pending */
#define TIF_NEED_RESCHED 2 /* rescheduling necessary */
-#define TIF_UPROBE 3 /* breakpointed or single-stepping */
-#define TIF_GUARDED_STORAGE 4 /* load guarded storage control block */
+#define TIF_NEED_RESCHED_LAZY 3 /* lazy rescheduling needed */
+#define TIF_UPROBE 4 /* breakpointed or single-stepping */
#define TIF_PATCH_PENDING 5 /* pending live patching update */
#define TIF_PGSTE 6 /* New mm's will use 4K page tables */
#define TIF_NOTIFY_SIGNAL 7 /* signal notifications exist */
+#define TIF_GUARDED_STORAGE 8 /* load guarded storage control block */
#define TIF_ISOLATE_BP_GUEST 9 /* Run KVM guests with isolated BP */
#define TIF_PER_TRAP 10 /* Need to handle PER trap on exit to usermode */
-
#define TIF_31BIT 16 /* 32bit process */
#define TIF_MEMDIE 17 /* is terminating due to OOM killer */
#define TIF_RESTORE_SIGMASK 18 /* restore signal mask in do_signal() */
#define TIF_SINGLE_STEP 19 /* This task is single stepped */
#define TIF_BLOCK_STEP 20 /* This task is block stepped */
#define TIF_UPROBE_SINGLESTEP 21 /* This task is uprobe single stepped */
-
-/* _TIF_TRACE bits */
#define TIF_SYSCALL_TRACE 24 /* syscall trace active */
#define TIF_SYSCALL_AUDIT 25 /* syscall auditing active */
#define TIF_SECCOMP 26 /* secure computing */
#define TIF_SYSCALL_TRACEPOINT 27 /* syscall tracepoint instrumentation */
#define _TIF_NOTIFY_RESUME BIT(TIF_NOTIFY_RESUME)
-#define _TIF_NOTIFY_SIGNAL BIT(TIF_NOTIFY_SIGNAL)
#define _TIF_SIGPENDING BIT(TIF_SIGPENDING)
#define _TIF_NEED_RESCHED BIT(TIF_NEED_RESCHED)
+#define _TIF_NEED_RESCHED_LAZY BIT(TIF_NEED_RESCHED_LAZY)
#define _TIF_UPROBE BIT(TIF_UPROBE)
-#define _TIF_GUARDED_STORAGE BIT(TIF_GUARDED_STORAGE)
#define _TIF_PATCH_PENDING BIT(TIF_PATCH_PENDING)
+#define _TIF_PGSTE BIT(TIF_PGSTE)
+#define _TIF_NOTIFY_SIGNAL BIT(TIF_NOTIFY_SIGNAL)
+#define _TIF_GUARDED_STORAGE BIT(TIF_GUARDED_STORAGE)
#define _TIF_ISOLATE_BP_GUEST BIT(TIF_ISOLATE_BP_GUEST)
#define _TIF_PER_TRAP BIT(TIF_PER_TRAP)
-
#define _TIF_31BIT BIT(TIF_31BIT)
+#define _TIF_MEMDIE BIT(TIF_MEMDIE)
+#define _TIF_RESTORE_SIGMASK BIT(TIF_RESTORE_SIGMASK)
#define _TIF_SINGLE_STEP BIT(TIF_SINGLE_STEP)
-
+#define _TIF_BLOCK_STEP BIT(TIF_BLOCK_STEP)
+#define _TIF_UPROBE_SINGLESTEP BIT(TIF_UPROBE_SINGLESTEP)
#define _TIF_SYSCALL_TRACE BIT(TIF_SYSCALL_TRACE)
#define _TIF_SYSCALL_AUDIT BIT(TIF_SYSCALL_AUDIT)
#define _TIF_SECCOMP BIT(TIF_SECCOMP)
diff --git a/arch/s390/include/asm/tlbflush.h b/arch/s390/include/asm/tlbflush.h
index a6e2cd89b609..9dfd46dd03c6 100644
--- a/arch/s390/include/asm/tlbflush.h
+++ b/arch/s390/include/asm/tlbflush.h
@@ -46,11 +46,6 @@ static inline void __tlb_flush_mm(struct mm_struct *mm)
{
unsigned long gmap_asce;
- /*
- * If the machine has IDTE we prefer to do a per mm flush
- * on all cpus instead of doing a local flush if the mm
- * only ran on the local cpu.
- */
preempt_disable();
atomic_inc(&mm->context.flush_count);
/* Reset TLB flush mask */
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index b3f2103694e4..de19fd8a6a95 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -77,12 +77,14 @@ static debug_info_t *debug_info_create(const char *name, int pages_per_area,
static void debug_info_get(debug_info_t *);
static void debug_info_put(debug_info_t *);
static int debug_prolog_level_fn(debug_info_t *id,
- struct debug_view *view, char *out_buf);
+ struct debug_view *view, char *out_buf,
+ size_t out_buf_size);
static int debug_input_level_fn(debug_info_t *id, struct debug_view *view,
struct file *file, const char __user *user_buf,
size_t user_buf_size, loff_t *offset);
static int debug_prolog_pages_fn(debug_info_t *id,
- struct debug_view *view, char *out_buf);
+ struct debug_view *view, char *out_buf,
+ size_t out_buf_size);
static int debug_input_pages_fn(debug_info_t *id, struct debug_view *view,
struct file *file, const char __user *user_buf,
size_t user_buf_size, loff_t *offset);
@@ -90,9 +92,11 @@ static int debug_input_flush_fn(debug_info_t *id, struct debug_view *view,
struct file *file, const char __user *user_buf,
size_t user_buf_size, loff_t *offset);
static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf, const char *in_buf);
+ char *out_buf, size_t out_buf_size,
+ const char *in_buf);
static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf, const char *inbuf);
+ char *out_buf, size_t out_buf_size,
+ const char *inbuf);
static void debug_areas_swap(debug_info_t *a, debug_info_t *b);
static void debug_events_append(debug_info_t *dest, debug_info_t *src);
@@ -391,8 +395,10 @@ static int debug_format_entry(file_private_info_t *p_info)
if (p_info->act_entry == DEBUG_PROLOG_ENTRY) {
/* print prolog */
- if (view->prolog_proc)
- len += view->prolog_proc(id_snap, view, p_info->temp_buf);
+ if (view->prolog_proc) {
+ len += view->prolog_proc(id_snap, view, p_info->temp_buf,
+ sizeof(p_info->temp_buf));
+ }
goto out;
}
if (!id_snap->areas) /* this is true, if we have a prolog only view */
@@ -402,12 +408,16 @@ static int debug_format_entry(file_private_info_t *p_info)
if (act_entry->clock == 0LL)
goto out; /* empty entry */
- if (view->header_proc)
+ if (view->header_proc) {
len += view->header_proc(id_snap, view, p_info->act_area,
- act_entry, p_info->temp_buf + len);
- if (view->format_proc)
+ act_entry, p_info->temp_buf + len,
+ sizeof(p_info->temp_buf) - len);
+ }
+ if (view->format_proc) {
len += view->format_proc(id_snap, view, p_info->temp_buf + len,
+ sizeof(p_info->temp_buf) - len,
DEBUG_DATA(act_entry));
+ }
out:
return len;
}
@@ -1292,9 +1302,9 @@ static inline int debug_get_uint(char *buf)
*/
static int debug_prolog_pages_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf)
+ char *out_buf, size_t out_buf_size)
{
- return sprintf(out_buf, "%i\n", id->pages_per_area);
+ return scnprintf(out_buf, out_buf_size, "%i\n", id->pages_per_area);
}
/*
@@ -1341,14 +1351,14 @@ out:
* prints out actual debug level
*/
static int debug_prolog_level_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf)
+ char *out_buf, size_t out_buf_size)
{
int rc = 0;
if (id->level == DEBUG_OFF_LEVEL)
- rc = sprintf(out_buf, "-\n");
+ rc = scnprintf(out_buf, out_buf_size, "-\n");
else
- rc = sprintf(out_buf, "%i\n", id->level);
+ rc = scnprintf(out_buf, out_buf_size, "%i\n", id->level);
return rc;
}
@@ -1465,22 +1475,24 @@ out:
* prints debug data in hex/ascii format
*/
static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf, const char *in_buf)
+ char *out_buf, size_t out_buf_size, const char *in_buf)
{
int i, rc = 0;
- for (i = 0; i < id->buf_size; i++)
- rc += sprintf(out_buf + rc, "%02x ", ((unsigned char *) in_buf)[i]);
- rc += sprintf(out_buf + rc, "| ");
+ for (i = 0; i < id->buf_size; i++) {
+ rc += scnprintf(out_buf + rc, out_buf_size - rc,
+ "%02x ", ((unsigned char *)in_buf)[i]);
+ }
+ rc += scnprintf(out_buf + rc, out_buf_size - rc, "| ");
for (i = 0; i < id->buf_size; i++) {
unsigned char c = in_buf[i];
if (isascii(c) && isprint(c))
- rc += sprintf(out_buf + rc, "%c", c);
+ rc += scnprintf(out_buf + rc, out_buf_size - rc, "%c", c);
else
- rc += sprintf(out_buf + rc, ".");
+ rc += scnprintf(out_buf + rc, out_buf_size - rc, ".");
}
- rc += sprintf(out_buf + rc, "\n");
+ rc += scnprintf(out_buf + rc, out_buf_size - rc, "\n");
return rc;
}
@@ -1488,7 +1500,8 @@ static int debug_hex_ascii_format_fn(debug_info_t *id, struct debug_view *view,
* prints header for debug entry
*/
int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
- int area, debug_entry_t *entry, char *out_buf)
+ int area, debug_entry_t *entry, char *out_buf,
+ size_t out_buf_size)
{
unsigned long sec, usec;
unsigned long caller;
@@ -1505,9 +1518,9 @@ int debug_dflt_header_fn(debug_info_t *id, struct debug_view *view,
else
except_str = "-";
caller = (unsigned long) entry->caller;
- rc += sprintf(out_buf, "%02i %011ld:%06lu %1u %1s %04u %px ",
- area, sec, usec, level, except_str,
- entry->cpu, (void *)caller);
+ rc += scnprintf(out_buf, out_buf_size, "%02i %011ld:%06lu %1u %1s %04u %px ",
+ area, sec, usec, level, except_str,
+ entry->cpu, (void *)caller);
return rc;
}
EXPORT_SYMBOL(debug_dflt_header_fn);
@@ -1520,7 +1533,7 @@ EXPORT_SYMBOL(debug_dflt_header_fn);
#define DEBUG_SPRINTF_MAX_ARGS 10
static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
- char *out_buf, const char *inbuf)
+ char *out_buf, size_t out_buf_size, const char *inbuf)
{
debug_sprintf_entry_t *curr_event = (debug_sprintf_entry_t *)inbuf;
int num_longs, num_used_args = 0, i, rc = 0;
@@ -1533,8 +1546,9 @@ static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
goto out; /* bufsize of entry too small */
if (num_longs == 1) {
/* no args, we use only the string */
- strcpy(out_buf, curr_event->string);
- rc = strlen(curr_event->string);
+ rc = strscpy(out_buf, curr_event->string, out_buf_size);
+ if (rc == -E2BIG)
+ rc = out_buf_size;
goto out;
}
@@ -1546,12 +1560,13 @@ static int debug_sprintf_format_fn(debug_info_t *id, struct debug_view *view,
for (i = 0; i < num_used_args; i++)
index[i] = i;
- rc = sprintf(out_buf, curr_event->string, curr_event->args[index[0]],
- curr_event->args[index[1]], curr_event->args[index[2]],
- curr_event->args[index[3]], curr_event->args[index[4]],
- curr_event->args[index[5]], curr_event->args[index[6]],
- curr_event->args[index[7]], curr_event->args[index[8]],
- curr_event->args[index[9]]);
+ rc = scnprintf(out_buf, out_buf_size,
+ curr_event->string, curr_event->args[index[0]],
+ curr_event->args[index[1]], curr_event->args[index[2]],
+ curr_event->args[index[3]], curr_event->args[index[4]],
+ curr_event->args[index[5]], curr_event->args[index[6]],
+ curr_event->args[index[7]], curr_event->args[index[8]],
+ curr_event->args[index[9]]);
out:
return rc;
}
diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S
index 1ff13239d4e5..960c08700cf6 100644
--- a/arch/s390/kernel/entry.S
+++ b/arch/s390/kernel/entry.S
@@ -430,9 +430,13 @@ SYM_CODE_START(\name)
SYM_CODE_END(\name)
.endm
+ .section .irqentry.text, "ax"
+
INT_HANDLER ext_int_handler,__LC_EXT_OLD_PSW,do_ext_irq
INT_HANDLER io_int_handler,__LC_IO_OLD_PSW,do_io_irq
+ .section .kprobes.text, "ax"
+
/*
* Machine check handler routines
*/
diff --git a/arch/s390/kernel/ipl.c b/arch/s390/kernel/ipl.c
index edbb52ce3f1e..7d12a1305fc9 100644
--- a/arch/s390/kernel/ipl.c
+++ b/arch/s390/kernel/ipl.c
@@ -270,7 +270,7 @@ static ssize_t sys_##_prefix##_##_name##_store(struct kobject *kobj, \
if (len >= sizeof(_value)) \
return -E2BIG; \
len = strscpy(_value, buf, sizeof(_value)); \
- if (len < 0) \
+ if ((ssize_t)len < 0) \
return len; \
strim(_value); \
return len; \
diff --git a/arch/s390/kernel/kprobes.c b/arch/s390/kernel/kprobes.c
index 6295faf0987d..8b80ea57125f 100644
--- a/arch/s390/kernel/kprobes.c
+++ b/arch/s390/kernel/kprobes.c
@@ -489,6 +489,12 @@ int __init arch_init_kprobes(void)
return 0;
}
+int __init arch_populate_kprobe_blacklist(void)
+{
+ return kprobe_add_area_blacklist((unsigned long)__irqentry_text_start,
+ (unsigned long)__irqentry_text_end);
+}
+
int arch_trampoline_kprobe(struct kprobe *p)
{
return 0;
diff --git a/arch/s390/kernel/perf_cpum_sf.c b/arch/s390/kernel/perf_cpum_sf.c
index 0cde42f8af6e..1e99514fb7ae 100644
--- a/arch/s390/kernel/perf_cpum_sf.c
+++ b/arch/s390/kernel/perf_cpum_sf.c
@@ -180,39 +180,27 @@ static int sf_buffer_available(struct cpu_hw_sf *cpuhw)
*/
static void free_sampling_buffer(struct sf_buffer *sfb)
{
- unsigned long *sdbt, *curr;
-
- if (!sfb->sdbt)
- return;
+ unsigned long *sdbt, *curr, *head;
sdbt = sfb->sdbt;
- curr = sdbt;
-
+ if (!sdbt)
+ return;
+ sfb->sdbt = NULL;
/* Free the SDBT after all SDBs are processed... */
- while (1) {
- if (!*curr || !sdbt)
- break;
-
- /* Process table-link entries */
+ head = sdbt;
+ curr = sdbt;
+ do {
if (is_link_entry(curr)) {
+ /* Process table-link entries */
curr = get_next_sdbt(curr);
- if (sdbt)
- free_page((unsigned long)sdbt);
-
- /* If the origin is reached, sampling buffer is freed */
- if (curr == sfb->sdbt)
- break;
- else
- sdbt = curr;
+ free_page((unsigned long)sdbt);
+ sdbt = curr;
} else {
/* Process SDB pointer */
- if (*curr) {
- free_page((unsigned long)phys_to_virt(*curr));
- curr++;
- }
+ free_page((unsigned long)phys_to_virt(*curr));
+ curr++;
}
- }
-
+ } while (curr != head);
memset(sfb, 0, sizeof(*sfb));
}
diff --git a/arch/s390/kernel/stacktrace.c b/arch/s390/kernel/stacktrace.c
index 9f59837d159e..40edfde25f5b 100644
--- a/arch/s390/kernel/stacktrace.c
+++ b/arch/s390/kernel/stacktrace.c
@@ -151,7 +151,7 @@ void arch_stack_walk_user_common(stack_trace_consume_fn consume_entry, void *coo
break;
}
if (!store_ip(consume_entry, cookie, entry, perf, ip))
- return;
+ break;
first = false;
}
pagefault_enable();
diff --git a/arch/s390/kvm/gaccess.c b/arch/s390/kvm/gaccess.c
index a688351f4ab5..9816b0060fbe 100644
--- a/arch/s390/kvm/gaccess.c
+++ b/arch/s390/kvm/gaccess.c
@@ -129,8 +129,8 @@ static void ipte_lock_simple(struct kvm *kvm)
retry:
read_lock(&kvm->arch.sca_lock);
ic = kvm_s390_get_ipte_control(kvm);
+ old = READ_ONCE(*ic);
do {
- old = READ_ONCE(*ic);
if (old.k) {
read_unlock(&kvm->arch.sca_lock);
cond_resched();
@@ -138,7 +138,7 @@ retry:
}
new = old;
new.k = 1;
- } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
+ } while (!try_cmpxchg(&ic->val, &old.val, new.val));
read_unlock(&kvm->arch.sca_lock);
out:
mutex_unlock(&kvm->arch.ipte_mutex);
@@ -154,11 +154,11 @@ static void ipte_unlock_simple(struct kvm *kvm)
goto out;
read_lock(&kvm->arch.sca_lock);
ic = kvm_s390_get_ipte_control(kvm);
+ old = READ_ONCE(*ic);
do {
- old = READ_ONCE(*ic);
new = old;
new.k = 0;
- } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
+ } while (!try_cmpxchg(&ic->val, &old.val, new.val));
read_unlock(&kvm->arch.sca_lock);
wake_up(&kvm->arch.ipte_wq);
out:
@@ -172,8 +172,8 @@ static void ipte_lock_siif(struct kvm *kvm)
retry:
read_lock(&kvm->arch.sca_lock);
ic = kvm_s390_get_ipte_control(kvm);
+ old = READ_ONCE(*ic);
do {
- old = READ_ONCE(*ic);
if (old.kg) {
read_unlock(&kvm->arch.sca_lock);
cond_resched();
@@ -182,7 +182,7 @@ retry:
new = old;
new.k = 1;
new.kh++;
- } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
+ } while (!try_cmpxchg(&ic->val, &old.val, new.val));
read_unlock(&kvm->arch.sca_lock);
}
@@ -192,13 +192,13 @@ static void ipte_unlock_siif(struct kvm *kvm)
read_lock(&kvm->arch.sca_lock);
ic = kvm_s390_get_ipte_control(kvm);
+ old = READ_ONCE(*ic);
do {
- old = READ_ONCE(*ic);
new = old;
new.kh--;
if (!new.kh)
new.k = 0;
- } while (cmpxchg(&ic->val, old.val, new.val) != old.val);
+ } while (!try_cmpxchg(&ic->val, &old.val, new.val));
read_unlock(&kvm->arch.sca_lock);
if (!new.kh)
wake_up(&kvm->arch.ipte_wq);
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index 4f0e7f61edf7..ea8dce299954 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -118,8 +118,6 @@ static int sca_inject_ext_call(struct kvm_vcpu *vcpu, int src_id)
static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
{
- int rc, expect;
-
if (!kvm_s390_use_sca_entries())
return;
kvm_s390_clear_cpuflags(vcpu, CPUSTAT_ECALL_PEND);
@@ -128,23 +126,16 @@ static void sca_clear_ext_call(struct kvm_vcpu *vcpu)
struct esca_block *sca = vcpu->kvm->arch.sca;
union esca_sigp_ctrl *sigp_ctrl =
&(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
- union esca_sigp_ctrl old;
- old = READ_ONCE(*sigp_ctrl);
- expect = old.value;
- rc = cmpxchg(&sigp_ctrl->value, old.value, 0);
+ WRITE_ONCE(sigp_ctrl->value, 0);
} else {
struct bsca_block *sca = vcpu->kvm->arch.sca;
union bsca_sigp_ctrl *sigp_ctrl =
&(sca->cpu[vcpu->vcpu_id].sigp_ctrl);
- union bsca_sigp_ctrl old;
- old = READ_ONCE(*sigp_ctrl);
- expect = old.value;
- rc = cmpxchg(&sigp_ctrl->value, old.value, 0);
+ WRITE_ONCE(sigp_ctrl->value, 0);
}
read_unlock(&vcpu->kvm->arch.sca_lock);
- WARN_ON(rc != expect); /* cannot clear? */
}
int psw_extint_disabled(struct kvm_vcpu *vcpu)
@@ -247,12 +238,12 @@ static inline int gisa_set_iam(struct kvm_s390_gisa *gisa, u8 iam)
{
u64 word, _word;
+ word = READ_ONCE(gisa->u64.word[0]);
do {
- word = READ_ONCE(gisa->u64.word[0]);
if ((u64)gisa != word >> 32)
return -EBUSY;
_word = (word & ~0xffUL) | iam;
- } while (cmpxchg(&gisa->u64.word[0], word, _word) != word);
+ } while (!try_cmpxchg(&gisa->u64.word[0], &word, _word));
return 0;
}
@@ -270,10 +261,10 @@ static inline void gisa_clear_ipm(struct kvm_s390_gisa *gisa)
{
u64 word, _word;
+ word = READ_ONCE(gisa->u64.word[0]);
do {
- word = READ_ONCE(gisa->u64.word[0]);
_word = word & ~(0xffUL << 24);
- } while (cmpxchg(&gisa->u64.word[0], word, _word) != word);
+ } while (!try_cmpxchg(&gisa->u64.word[0], &word, _word));
}
/**
@@ -291,14 +282,14 @@ static inline u8 gisa_get_ipm_or_restore_iam(struct kvm_s390_gisa_interrupt *gi)
u8 pending_mask, alert_mask;
u64 word, _word;
+ word = READ_ONCE(gi->origin->u64.word[0]);
do {
- word = READ_ONCE(gi->origin->u64.word[0]);
alert_mask = READ_ONCE(gi->alert.mask);
pending_mask = (u8)(word >> 24) & alert_mask;
if (pending_mask)
return pending_mask;
_word = (word & ~0xffUL) | alert_mask;
- } while (cmpxchg(&gi->origin->u64.word[0], word, _word) != word);
+ } while (!try_cmpxchg(&gi->origin->u64.word[0], &word, _word));
return 0;
}
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 442d4a227c0e..d8080c27d45b 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -1937,11 +1937,11 @@ static void kvm_s390_update_topology_change_report(struct kvm *kvm, bool val)
read_lock(&kvm->arch.sca_lock);
sca = kvm->arch.sca;
+ old = READ_ONCE(sca->utility);
do {
- old = READ_ONCE(sca->utility);
new = old;
new.mtcr = val;
- } while (cmpxchg(&sca->utility.val, old.val, new.val) != old.val);
+ } while (!try_cmpxchg(&sca->utility.val, &old.val, new.val));
read_unlock(&kvm->arch.sca_lock);
}
diff --git a/arch/s390/kvm/pci.c b/arch/s390/kvm/pci.c
index a61518b549f0..9b9e7fdd5380 100644
--- a/arch/s390/kvm/pci.c
+++ b/arch/s390/kvm/pci.c
@@ -208,13 +208,12 @@ static inline int account_mem(unsigned long nr_pages)
page_limit = rlimit(RLIMIT_MEMLOCK) >> PAGE_SHIFT;
+ cur_pages = atomic_long_read(&user->locked_vm);
do {
- cur_pages = atomic_long_read(&user->locked_vm);
new_pages = cur_pages + nr_pages;
if (new_pages > page_limit)
return -ENOMEM;
- } while (atomic_long_cmpxchg(&user->locked_vm, cur_pages,
- new_pages) != cur_pages);
+ } while (!atomic_long_try_cmpxchg(&user->locked_vm, &cur_pages, new_pages));
atomic64_add(nr_pages, &current->mm->pinned_vm);
diff --git a/arch/s390/lib/spinlock.c b/arch/s390/lib/spinlock.c
index 09d735010ee1..a81a01c44927 100644
--- a/arch/s390/lib/spinlock.c
+++ b/arch/s390/lib/spinlock.c
@@ -15,6 +15,7 @@
#include <linux/percpu.h>
#include <linux/io.h>
#include <asm/alternative.h>
+#include <asm/asm.h>
int spin_retry = -1;
@@ -76,24 +77,43 @@ static inline int arch_load_niai4(int *lock)
asm_inline volatile(
ALTERNATIVE("nop", ".insn rre,0xb2fa0000,4,0", ALT_FACILITY(49)) /* NIAI 4 */
- " l %0,%1\n"
- : "=d" (owner) : "Q" (*lock) : "memory");
+ " l %[owner],%[lock]\n"
+ : [owner] "=d" (owner) : [lock] "R" (*lock) : "memory");
return owner;
}
-static inline int arch_cmpxchg_niai8(int *lock, int old, int new)
+#ifdef __HAVE_ASM_FLAG_OUTPUTS__
+
+static inline int arch_try_cmpxchg_niai8(int *lock, int old, int new)
+{
+ int cc;
+
+ asm_inline volatile(
+ ALTERNATIVE("nop", ".insn rre,0xb2fa0000,8,0", ALT_FACILITY(49)) /* NIAI 8 */
+ " cs %[old],%[new],%[lock]\n"
+ : [old] "+d" (old), [lock] "+Q" (*lock), "=@cc" (cc)
+ : [new] "d" (new)
+ : "memory");
+ return cc == 0;
+}
+
+#else /* __HAVE_ASM_FLAG_OUTPUTS__ */
+
+static inline int arch_try_cmpxchg_niai8(int *lock, int old, int new)
{
int expected = old;
asm_inline volatile(
ALTERNATIVE("nop", ".insn rre,0xb2fa0000,8,0", ALT_FACILITY(49)) /* NIAI 8 */
- " cs %0,%3,%1\n"
- : "=d" (old), "=Q" (*lock)
- : "0" (old), "d" (new), "Q" (*lock)
+ " cs %[old],%[new],%[lock]\n"
+ : [old] "+d" (old), [lock] "+Q" (*lock)
+ : [new] "d" (new)
: "cc", "memory");
return expected == old;
}
+#endif /* __HAVE_ASM_FLAG_OUTPUTS__ */
+
static inline struct spin_wait *arch_spin_decode_tail(int lock)
{
int ix, cpu;
@@ -226,7 +246,7 @@ static inline void arch_spin_lock_classic(arch_spinlock_t *lp)
/* Try to get the lock if it is free. */
if (!owner) {
new = (old & _Q_TAIL_MASK) | lockval;
- if (arch_cmpxchg_niai8(&lp->lock, old, new)) {
+ if (arch_try_cmpxchg_niai8(&lp->lock, old, new)) {
/* Got the lock */
return;
}
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 646326fa0fad..9b681f74dccc 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -338,7 +338,8 @@ done:
handle_fault_error_nolock(regs, 0);
else
do_sigsegv(regs, SEGV_MAPERR);
- } else if (fault & (VM_FAULT_SIGBUS | VM_FAULT_HWPOISON)) {
+ } else if (fault & (VM_FAULT_SIGBUS | VM_FAULT_HWPOISON |
+ VM_FAULT_HWPOISON_LARGE)) {
if (!user_mode(regs))
handle_fault_error_nolock(regs, 0);
else
diff --git a/arch/s390/mm/gmap.c b/arch/s390/mm/gmap.c
index 643e47bfaddc..16b8a36c56de 100644
--- a/arch/s390/mm/gmap.c
+++ b/arch/s390/mm/gmap.c
@@ -587,7 +587,8 @@ int __gmap_link(struct gmap *gmap, unsigned long gaddr, unsigned long vmaddr)
if (pmd_leaf(*pmd)) {
*table = (pmd_val(*pmd) &
_SEGMENT_ENTRY_HARDWARE_BITS_LARGE)
- | _SEGMENT_ENTRY_GMAP_UC;
+ | _SEGMENT_ENTRY_GMAP_UC
+ | _SEGMENT_ENTRY;
} else
*table = pmd_val(*pmd) &
_SEGMENT_ENTRY_HARDWARE_BITS;
@@ -2396,7 +2397,8 @@ static void gmap_pmdp_clear(struct mm_struct *mm, unsigned long vmaddr,
gaddr = __gmap_segment_gaddr((unsigned long *)pmdp);
pmdp_notify_gmap(gmap, pmdp, gaddr);
WARN_ON(pmd_val(*pmdp) & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE |
- _SEGMENT_ENTRY_GMAP_UC));
+ _SEGMENT_ENTRY_GMAP_UC |
+ _SEGMENT_ENTRY));
if (purge)
__pmdp_csp(pmdp);
set_pmd(pmdp, __pmd(_SEGMENT_ENTRY_EMPTY));
@@ -2450,7 +2452,8 @@ void gmap_pmdp_idte_local(struct mm_struct *mm, unsigned long vmaddr)
gaddr = __gmap_segment_gaddr(entry);
pmdp_notify_gmap(gmap, pmdp, gaddr);
WARN_ON(*entry & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE |
- _SEGMENT_ENTRY_GMAP_UC));
+ _SEGMENT_ENTRY_GMAP_UC |
+ _SEGMENT_ENTRY));
if (MACHINE_HAS_TLB_GUEST)
__pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE,
gmap->asce, IDTE_LOCAL);
@@ -2485,7 +2488,8 @@ void gmap_pmdp_idte_global(struct mm_struct *mm, unsigned long vmaddr)
gaddr = __gmap_segment_gaddr(entry);
pmdp_notify_gmap(gmap, pmdp, gaddr);
WARN_ON(*entry & ~(_SEGMENT_ENTRY_HARDWARE_BITS_LARGE |
- _SEGMENT_ENTRY_GMAP_UC));
+ _SEGMENT_ENTRY_GMAP_UC |
+ _SEGMENT_ENTRY));
if (MACHINE_HAS_TLB_GUEST)
__pmdp_idte(gaddr, pmdp, IDTE_GUEST_ASCE,
gmap->asce, IDTE_GLOBAL);
diff --git a/arch/s390/mm/hugetlbpage.c b/arch/s390/mm/hugetlbpage.c
index 7c79cf1bc7d7..d9ce199953de 100644
--- a/arch/s390/mm/hugetlbpage.c
+++ b/arch/s390/mm/hugetlbpage.c
@@ -24,6 +24,7 @@
static inline unsigned long __pte_to_rste(pte_t pte)
{
+ swp_entry_t arch_entry;
unsigned long rste;
/*
@@ -48,6 +49,7 @@ static inline unsigned long __pte_to_rste(pte_t pte)
*/
if (pte_present(pte)) {
rste = pte_val(pte) & PAGE_MASK;
+ rste |= _SEGMENT_ENTRY_PRESENT;
rste |= move_set_bit(pte_val(pte), _PAGE_READ,
_SEGMENT_ENTRY_READ);
rste |= move_set_bit(pte_val(pte), _PAGE_WRITE,
@@ -66,6 +68,10 @@ static inline unsigned long __pte_to_rste(pte_t pte)
#endif
rste |= move_set_bit(pte_val(pte), _PAGE_NOEXEC,
_SEGMENT_ENTRY_NOEXEC);
+ } else if (!pte_none(pte)) {
+ /* swap pte */
+ arch_entry = __pte_to_swp_entry(pte);
+ rste = mk_swap_rste(__swp_type(arch_entry), __swp_offset(arch_entry));
} else
rste = _SEGMENT_ENTRY_EMPTY;
return rste;
@@ -73,13 +79,18 @@ static inline unsigned long __pte_to_rste(pte_t pte)
static inline pte_t __rste_to_pte(unsigned long rste)
{
+ swp_entry_t arch_entry;
unsigned long pteval;
- int present;
+ int present, none;
+ pte_t pte;
- if ((rste & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3)
+ if ((rste & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) {
present = pud_present(__pud(rste));
- else
+ none = pud_none(__pud(rste));
+ } else {
present = pmd_present(__pmd(rste));
+ none = pmd_none(__pmd(rste));
+ }
/*
* Convert encoding pmd / pud bits pte bits
@@ -114,6 +125,11 @@ static inline pte_t __rste_to_pte(unsigned long rste)
pteval |= move_set_bit(rste, _SEGMENT_ENTRY_SOFT_DIRTY, _PAGE_SOFT_DIRTY);
#endif
pteval |= move_set_bit(rste, _SEGMENT_ENTRY_NOEXEC, _PAGE_NOEXEC);
+ } else if (!none) {
+ /* swap rste */
+ arch_entry = __rste_to_swp_entry(rste);
+ pte = mk_swap_pte(__swp_type_rste(arch_entry), __swp_offset_rste(arch_entry));
+ pteval = pte_val(pte);
} else
pteval = _PAGE_INVALID;
return __pte(pteval);
@@ -148,8 +164,6 @@ void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
unsigned long rste;
rste = __pte_to_rste(pte);
- if (!MACHINE_HAS_NX)
- rste &= ~_SEGMENT_ENTRY_NOEXEC;
/* Set correct table type for 2G hugepages */
if ((pte_val(*ptep) & _REGION_ENTRY_TYPE_MASK) == _REGION_ENTRY_TYPE_R3) {
@@ -223,11 +237,10 @@ pte_t *huge_pte_offset(struct mm_struct *mm,
p4dp = p4d_offset(pgdp, addr);
if (p4d_present(*p4dp)) {
pudp = pud_offset(p4dp, addr);
- if (pud_present(*pudp)) {
- if (pud_leaf(*pudp))
- return (pte_t *) pudp;
+ if (sz == PUD_SIZE)
+ return (pte_t *)pudp;
+ if (pud_present(*pudp))
pmdp = pmd_offset(pudp, addr);
- }
}
}
return (pte_t *) pmdp;
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index cbff587dc4e3..88f72745fa59 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -779,8 +779,9 @@ int zpci_hot_reset_device(struct zpci_dev *zdev)
* @fh: Current Function Handle of the device to be created
* @state: Initial state after creation either Standby or Configured
*
- * Creates a new zpci device and adds it to its, possibly newly created, zbus
- * as well as zpci_list.
+ * Allocates a new struct zpci_dev and queries the platform for its details.
+ * If successful the device can subsequently be added to the zPCI subsystem
+ * using zpci_add_device().
*
* Returns: the zdev on success or an error pointer otherwise
*/
@@ -803,7 +804,6 @@ struct zpci_dev *zpci_create_device(u32 fid, u32 fh, enum zpci_state state)
goto error;
zdev->state = state;
- kref_init(&zdev->kref);
mutex_init(&zdev->state_lock);
mutex_init(&zdev->fmb_lock);
mutex_init(&zdev->kzdev_lock);
@@ -816,6 +816,17 @@ error:
return ERR_PTR(rc);
}
+/**
+ * zpci_add_device() - Add a previously created zPCI device to the zPCI subsystem
+ * @zdev: The zPCI device to be added
+ *
+ * A struct zpci_dev is added to the zPCI subsystem and to a virtual PCI bus creating
+ * a new one as necessary. A hotplug slot is created and events start to be handled.
+ * If successful from this point on zpci_zdev_get() and zpci_zdev_put() must be used.
+ * If adding the struct zpci_dev fails the device was not added and should be freed.
+ *
+ * Return: 0 on success, or an error code otherwise
+ */
int zpci_add_device(struct zpci_dev *zdev)
{
int rc;
@@ -829,6 +840,7 @@ int zpci_add_device(struct zpci_dev *zdev)
if (rc)
goto error_destroy_iommu;
+ kref_init(&zdev->kref);
spin_lock(&zpci_list_lock);
list_add_tail(&zdev->entry, &zpci_list);
spin_unlock(&zpci_list_lock);
@@ -928,10 +940,8 @@ void zpci_device_reserved(struct zpci_dev *zdev)
void zpci_release_device(struct kref *kref)
{
struct zpci_dev *zdev = container_of(kref, struct zpci_dev, kref);
- int ret;
- if (zdev->has_hp_slot)
- zpci_exit_slot(zdev);
+ WARN_ON(zdev->state != ZPCI_FN_STATE_RESERVED);
if (zdev->zbus->bus)
zpci_bus_remove_device(zdev, false);
@@ -939,28 +949,14 @@ void zpci_release_device(struct kref *kref)
if (zdev_enabled(zdev))
zpci_disable_device(zdev);
- switch (zdev->state) {
- case ZPCI_FN_STATE_CONFIGURED:
- ret = sclp_pci_deconfigure(zdev->fid);
- zpci_dbg(3, "deconf fid:%x, rc:%d\n", zdev->fid, ret);
- fallthrough;
- case ZPCI_FN_STATE_STANDBY:
- if (zdev->has_hp_slot)
- zpci_exit_slot(zdev);
- spin_lock(&zpci_list_lock);
- list_del(&zdev->entry);
- spin_unlock(&zpci_list_lock);
- zpci_dbg(3, "rsv fid:%x\n", zdev->fid);
- fallthrough;
- case ZPCI_FN_STATE_RESERVED:
- if (zdev->has_resources)
- zpci_cleanup_bus_resources(zdev);
- zpci_bus_device_unregister(zdev);
- zpci_destroy_iommu(zdev);
- fallthrough;
- default:
- break;
- }
+ if (zdev->has_hp_slot)
+ zpci_exit_slot(zdev);
+
+ if (zdev->has_resources)
+ zpci_cleanup_bus_resources(zdev);
+
+ zpci_bus_device_unregister(zdev);
+ zpci_destroy_iommu(zdev);
zpci_dbg(3, "rem fid:%x\n", zdev->fid);
kfree_rcu(zdev, rcu);
}
@@ -1121,7 +1117,8 @@ static void zpci_add_devices(struct list_head *scan_list)
list_sort(NULL, scan_list, &zpci_cmp_rid);
list_for_each_entry_safe(zdev, tmp, scan_list, entry) {
list_del_init(&zdev->entry);
- zpci_add_device(zdev);
+ if (zpci_add_device(zdev))
+ kfree(zdev);
}
}
diff --git a/arch/s390/pci/pci_event.c b/arch/s390/pci/pci_event.c
index 47f934f4e828..7f7b732b3f3e 100644
--- a/arch/s390/pci/pci_event.c
+++ b/arch/s390/pci/pci_event.c
@@ -340,7 +340,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_CONFIGURED);
if (IS_ERR(zdev))
break;
- zpci_add_device(zdev);
+ if (zpci_add_device(zdev)) {
+ kfree(zdev);
+ break;
+ }
} else {
/* the configuration request may be stale */
if (zdev->state != ZPCI_FN_STATE_STANDBY)
@@ -354,7 +357,10 @@ static void __zpci_event_availability(struct zpci_ccdf_avail *ccdf)
zdev = zpci_create_device(ccdf->fid, ccdf->fh, ZPCI_FN_STATE_STANDBY);
if (IS_ERR(zdev))
break;
- zpci_add_device(zdev);
+ if (zpci_add_device(zdev)) {
+ kfree(zdev);
+ break;
+ }
} else {
zpci_update_fh(zdev, ccdf->fh);
}
diff --git a/arch/sh/drivers/push-switch.c b/arch/sh/drivers/push-switch.c
index 1dea43381b5a..2b51ad9d5586 100644
--- a/arch/sh/drivers/push-switch.c
+++ b/arch/sh/drivers/push-switch.c
@@ -110,7 +110,7 @@ static void switch_drv_remove(struct platform_device *pdev)
static struct platform_driver switch_driver = {
.probe = switch_drv_probe,
- .remove_new = switch_drv_remove,
+ .remove = switch_drv_remove,
.driver = {
.name = DRV_NAME,
},
diff --git a/arch/sh/kernel/cpu/proc.c b/arch/sh/kernel/cpu/proc.c
index a306bcd6b341..5f6d0e827bae 100644
--- a/arch/sh/kernel/cpu/proc.c
+++ b/arch/sh/kernel/cpu/proc.c
@@ -132,7 +132,7 @@ static int show_cpuinfo(struct seq_file *m, void *v)
static void *c_start(struct seq_file *m, loff_t *pos)
{
- return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+ return *pos < nr_cpu_ids ? cpu_data + *pos : NULL;
}
static void *c_next(struct seq_file *m, void *v, loff_t *pos)
{
diff --git a/arch/sparc/Makefile b/arch/sparc/Makefile
index 757451c3ea1d..0400078076e5 100644
--- a/arch/sparc/Makefile
+++ b/arch/sparc/Makefile
@@ -29,7 +29,7 @@ UTS_MACHINE := sparc
# versions of gcc. Some gcc versions won't pass -Av8 to binutils when you
# give -mcpu=v8. This silently worked with older bintutils versions but
# does not any more.
-KBUILD_CFLAGS += -m32 -mcpu=v8 -pipe -mno-fpu -fcall-used-g5 -fcall-used-g7
+KBUILD_CFLAGS += -m32 -mcpu=v8 -pipe -mno-fpu $(call cc-option,-fcall-used-g5) $(call cc-option,-fcall-used-g7)
KBUILD_CFLAGS += -Wa,-Av8
KBUILD_AFLAGS += -m32 -Wa,-Av8
@@ -45,7 +45,7 @@ export BITS := 64
UTS_MACHINE := sparc64
KBUILD_CFLAGS += -m64 -pipe -mno-fpu -mcpu=ultrasparc -mcmodel=medlow
-KBUILD_CFLAGS += -ffixed-g4 -ffixed-g5 -fcall-used-g7 -Wno-sign-compare
+KBUILD_CFLAGS += -ffixed-g4 -ffixed-g5 $(call cc-option,-fcall-used-g7) -Wno-sign-compare
KBUILD_CFLAGS += -Wa,--undeclared-regs
KBUILD_CFLAGS += $(call cc-option,-mtune=ultrasparc3)
KBUILD_AFLAGS += -m64 -mcpu=ultrasparc -Wa,--undeclared-regs
diff --git a/arch/sparc/include/asm/hvtramp.h b/arch/sparc/include/asm/hvtramp.h
index 688ea43af0f5..ce2453ea4f2b 100644
--- a/arch/sparc/include/asm/hvtramp.h
+++ b/arch/sparc/include/asm/hvtramp.h
@@ -17,7 +17,7 @@ struct hvtramp_descr {
__u64 fault_info_va;
__u64 fault_info_pa;
__u64 thread_reg;
- struct hvtramp_mapping maps[1];
+ struct hvtramp_mapping maps[];
};
void hv_cpu_startup(unsigned long hvdescr_pa);
diff --git a/arch/sparc/include/asm/parport_64.h b/arch/sparc/include/asm/parport_64.h
index 4f530a270760..3068809ef9ad 100644
--- a/arch/sparc/include/asm/parport_64.h
+++ b/arch/sparc/include/asm/parport_64.h
@@ -243,7 +243,7 @@ static struct platform_driver ecpp_driver = {
.of_match_table = ecpp_match,
},
.probe = ecpp_probe,
- .remove_new = ecpp_remove,
+ .remove = ecpp_remove,
};
static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
diff --git a/arch/sparc/include/uapi/asm/socket.h b/arch/sparc/include/uapi/asm/socket.h
index 113cd9f353e3..5b464a568664 100644
--- a/arch/sparc/include/uapi/asm/socket.h
+++ b/arch/sparc/include/uapi/asm/socket.h
@@ -141,6 +141,8 @@
#define SCM_TS_OPT_ID 0x005a
+#define SO_RCVPRIORITY 0x005b
+
#if !defined(__KERNEL__)
diff --git a/arch/sparc/kernel/chmc.c b/arch/sparc/kernel/chmc.c
index e02074062001..d4c74d6b2e1b 100644
--- a/arch/sparc/kernel/chmc.c
+++ b/arch/sparc/kernel/chmc.c
@@ -814,7 +814,7 @@ static struct platform_driver us3mc_driver = {
.of_match_table = us3mc_match,
},
.probe = us3mc_probe,
- .remove_new = us3mc_remove,
+ .remove = us3mc_remove,
};
static inline bool us3mc_platform(void)
diff --git a/arch/sparc/kernel/smp_64.c b/arch/sparc/kernel/smp_64.c
index e40c395db202..5cbd6ed5ef6f 100644
--- a/arch/sparc/kernel/smp_64.c
+++ b/arch/sparc/kernel/smp_64.c
@@ -297,9 +297,7 @@ static void ldom_startcpu_cpuid(unsigned int cpu, unsigned long thread_reg,
unsigned long hv_err;
int i;
- hdesc = kzalloc(sizeof(*hdesc) +
- (sizeof(struct hvtramp_mapping) *
- num_kernel_image_mappings - 1),
+ hdesc = kzalloc(struct_size(hdesc, maps, num_kernel_image_mappings),
GFP_KERNEL);
if (!hdesc) {
printk(KERN_ERR "ldom_startcpu_cpuid: Cannot allocate "
diff --git a/arch/sparc/kernel/time_32.c b/arch/sparc/kernel/time_32.c
index 08bbdc458596..578fd0d49f30 100644
--- a/arch/sparc/kernel/time_32.c
+++ b/arch/sparc/kernel/time_32.c
@@ -255,6 +255,7 @@ static void mostek_write_byte(struct device *dev, u32 ofs, u8 val)
static struct m48t59_plat_data m48t59_data = {
.read_byte = mostek_read_byte,
.write_byte = mostek_write_byte,
+ .yy_offset = 68,
};
/* resource is set at runtime */
diff --git a/arch/sparc/kernel/time_64.c b/arch/sparc/kernel/time_64.c
index 60f1c8cc5363..b32f27f929d1 100644
--- a/arch/sparc/kernel/time_64.c
+++ b/arch/sparc/kernel/time_64.c
@@ -544,6 +544,7 @@ static void mostek_write_byte(struct device *dev, u32 ofs, u8 val)
static struct m48t59_plat_data m48t59_data = {
.read_byte = mostek_read_byte,
.write_byte = mostek_write_byte,
+ .yy_offset = 68,
};
static struct platform_device m48t59_rtc = {
diff --git a/arch/sparc/kernel/vmlinux.lds.S b/arch/sparc/kernel/vmlinux.lds.S
index d317a843f7ea..f1b86eb30340 100644
--- a/arch/sparc/kernel/vmlinux.lds.S
+++ b/arch/sparc/kernel/vmlinux.lds.S
@@ -48,6 +48,11 @@ SECTIONS
{
_text = .;
HEAD_TEXT
+ ALIGN_FUNCTION();
+#ifdef CONFIG_SPARC64
+ /* Match text section symbols in head_64.S first */
+ *head_64.o(.text)
+#endif
TEXT_TEXT
SCHED_TEXT
LOCK_TEXT
diff --git a/arch/sparc/vdso/Makefile b/arch/sparc/vdso/Makefile
index 243dbfc4609d..50ec2978cda5 100644
--- a/arch/sparc/vdso/Makefile
+++ b/arch/sparc/vdso/Makefile
@@ -46,7 +46,7 @@ CFL := $(PROFILING) -mcmodel=medlow -fPIC -O2 -fasynchronous-unwind-tables -m64
-fno-omit-frame-pointer -foptimize-sibling-calls \
-DDISABLE_BRANCH_PROFILING -DBUILD_VDSO
-SPARC_REG_CFLAGS = -ffixed-g4 -ffixed-g5 -fcall-used-g5 -fcall-used-g7
+SPARC_REG_CFLAGS = -ffixed-g4 -ffixed-g5 $(call cc-option,-fcall-used-g5) $(call cc-option,-fcall-used-g7)
$(vobjs): KBUILD_CFLAGS := $(filter-out $(RANDSTRUCT_CFLAGS) $(GCC_PLUGINS_CFLAGS) $(SPARC_REG_CFLAGS),$(KBUILD_CFLAGS)) $(CFL)
diff --git a/arch/sparc/vdso/vclock_gettime.c b/arch/sparc/vdso/vclock_gettime.c
index e794edde6755..79607804ea1b 100644
--- a/arch/sparc/vdso/vclock_gettime.c
+++ b/arch/sparc/vdso/vclock_gettime.c
@@ -86,6 +86,11 @@ notrace static long vdso_fallback_gettimeofday(struct __kernel_old_timeval *tv,
}
#ifdef CONFIG_SPARC64
+notrace static __always_inline u64 __shr64(u64 val, int amt)
+{
+ return val >> amt;
+}
+
notrace static __always_inline u64 vread_tick(void)
{
u64 ret;
@@ -102,6 +107,21 @@ notrace static __always_inline u64 vread_tick_stick(void)
return ret;
}
#else
+notrace static __always_inline u64 __shr64(u64 val, int amt)
+{
+ u64 ret;
+
+ __asm__ __volatile__("sllx %H1, 32, %%g1\n\t"
+ "srl %L1, 0, %L1\n\t"
+ "or %%g1, %L1, %%g1\n\t"
+ "srlx %%g1, %2, %L0\n\t"
+ "srlx %L0, 32, %H0"
+ : "=r" (ret)
+ : "r" (val), "r" (amt)
+ : "g1");
+ return ret;
+}
+
notrace static __always_inline u64 vread_tick(void)
{
register unsigned long long ret asm("o4");
@@ -154,7 +174,7 @@ notrace static __always_inline int do_realtime(struct vvar_data *vvar,
ts->tv_sec = vvar->wall_time_sec;
ns = vvar->wall_time_snsec;
ns += vgetsns(vvar);
- ns >>= vvar->clock.shift;
+ ns = __shr64(ns, vvar->clock.shift);
} while (unlikely(vvar_read_retry(vvar, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
@@ -174,7 +194,7 @@ notrace static __always_inline int do_realtime_stick(struct vvar_data *vvar,
ts->tv_sec = vvar->wall_time_sec;
ns = vvar->wall_time_snsec;
ns += vgetsns_stick(vvar);
- ns >>= vvar->clock.shift;
+ ns = __shr64(ns, vvar->clock.shift);
} while (unlikely(vvar_read_retry(vvar, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
@@ -194,7 +214,7 @@ notrace static __always_inline int do_monotonic(struct vvar_data *vvar,
ts->tv_sec = vvar->monotonic_time_sec;
ns = vvar->monotonic_time_snsec;
ns += vgetsns(vvar);
- ns >>= vvar->clock.shift;
+ ns = __shr64(ns, vvar->clock.shift);
} while (unlikely(vvar_read_retry(vvar, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
@@ -214,7 +234,7 @@ notrace static __always_inline int do_monotonic_stick(struct vvar_data *vvar,
ts->tv_sec = vvar->monotonic_time_sec;
ns = vvar->monotonic_time_snsec;
ns += vgetsns_stick(vvar);
- ns >>= vvar->clock.shift;
+ ns = __shr64(ns, vvar->clock.shift);
} while (unlikely(vvar_read_retry(vvar, seq)));
ts->tv_sec += __iter_div_u64_rem(ns, NSEC_PER_SEC, &ns);
diff --git a/arch/um/Kconfig b/arch/um/Kconfig
index c89575d05021..18051b1cfce0 100644
--- a/arch/um/Kconfig
+++ b/arch/um/Kconfig
@@ -5,6 +5,7 @@ menu "UML-specific options"
config UML
bool
default y
+ select ARCH_WANTS_DYNAMIC_TASK_STRUCT
select ARCH_HAS_CPU_FINALIZE_INIT
select ARCH_HAS_FORTIFY_SOURCE
select ARCH_HAS_GCOV_PROFILE_ALL
@@ -32,6 +33,8 @@ config UML
select HAVE_ARCH_VMAP_STACK
select HAVE_RUST
select ARCH_HAS_UBSAN
+ select HAVE_ARCH_TRACEHOOK
+ select THREAD_INFO_IN_TASK
config MMU
bool
@@ -94,7 +97,7 @@ config MAY_HAVE_RUNTIME_DEPS
config STATIC_LINK
bool "Force a static link"
- depends on CC_CAN_LINK_STATIC_NO_RUNTIME_DEPS || !MAY_HAVE_RUNTIME_DEPS
+ depends on !MAY_HAVE_RUNTIME_DEPS
help
This option gives you the ability to force a static link of UML.
Normally, UML is linked as a shared binary. This is inconvenient for
@@ -209,8 +212,8 @@ config MMAPPER
config PGTABLE_LEVELS
int
- default 3 if 3_LEVEL_PGTABLES
- default 2
+ default 4 if 64BIT
+ default 2 if !64BIT
config UML_TIME_TRAVEL_SUPPORT
bool
@@ -227,6 +230,21 @@ config UML_TIME_TRAVEL_SUPPORT
It is safe to say Y, but you probably don't need this.
+config UML_MAX_USERSPACE_ITERATIONS
+ int
+ prompt "Maximum number of unscheduled userspace iterations"
+ default 10000
+ depends on UML_TIME_TRAVEL_SUPPORT
+ help
+ In UML inf-cpu and ext time-travel mode userspace can run without being
+ interrupted. This will eventually overwhelm the kernel and create OOM
+ situations (mainly RCU not running). This setting specifies the number
+ of kernel/userspace switches (minor/major page fault, signal or syscall)
+ for the same userspace thread before the sched_clock is advanced by a
+ jiffie to trigger scheduling.
+
+ Setting it to zero disables the feature.
+
config KASAN_SHADOW_OFFSET
hex
depends on KASAN
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 00b63bac5eff..1d36a613aad8 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -61,7 +61,8 @@ KBUILD_CFLAGS += $(CFLAGS) $(CFLAGS-y) -D__arch_um__ \
$(ARCH_INCLUDE) $(MODE_INCLUDE) -Dvmap=kernel_vmap \
-Dlongjmp=kernel_longjmp -Dsetjmp=kernel_setjmp \
-Din6addr_loopback=kernel_in6addr_loopback \
- -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr
+ -Din6addr_any=kernel_in6addr_any -Dstrrchr=kernel_strrchr \
+ -D__close_range=kernel__close_range
KBUILD_RUSTFLAGS += -Crelocation-model=pie
@@ -70,7 +71,9 @@ KBUILD_AFLAGS += $(ARCH_INCLUDE)
USER_CFLAGS = $(patsubst $(KERNEL_DEFINES),,$(patsubst -I%,,$(KBUILD_CFLAGS))) \
$(ARCH_INCLUDE) $(MODE_INCLUDE) $(filter -I%,$(CFLAGS)) \
-D_FILE_OFFSET_BITS=64 -idirafter $(srctree)/include \
- -idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__
+ -idirafter $(objtree)/include -D__KERNEL__ -D__UM_HOST__ \
+ -include $(srctree)/include/linux/compiler-version.h \
+ -include $(srctree)/include/linux/kconfig.h
#This will adjust *FLAGS accordingly to the platform.
include $(srctree)/$(ARCH_DIR)/Makefile-os-Linux
diff --git a/arch/um/Makefile-skas b/arch/um/Makefile-skas
index 67323b028999..1a27e65bcb9c 100644
--- a/arch/um/Makefile-skas
+++ b/arch/um/Makefile-skas
@@ -3,15 +3,15 @@
# Licensed under the GPL
#
-GPROF_OPT += -pg
+export UM_GPROF_OPT += -pg
ifdef CONFIG_CC_IS_CLANG
-GCOV_OPT += -fprofile-instr-generate -fcoverage-mapping
+export UM_GCOV_OPT += -fprofile-instr-generate -fcoverage-mapping
else
-GCOV_OPT += -fprofile-arcs -ftest-coverage
+export UM_GCOV_OPT += -fprofile-arcs -ftest-coverage
endif
-CFLAGS-$(CONFIG_GCOV) += $(GCOV_OPT)
-CFLAGS-$(CONFIG_GPROF) += $(GPROF_OPT)
-LINK-$(CONFIG_GCOV) += $(GCOV_OPT)
-LINK-$(CONFIG_GPROF) += $(GPROF_OPT)
+CFLAGS-$(CONFIG_GCOV) += $(UM_GCOV_OPT)
+CFLAGS-$(CONFIG_GPROF) += $(UM_GPROF_OPT)
+LINK-$(CONFIG_GCOV) += $(UM_GCOV_OPT)
+LINK-$(CONFIG_GPROF) += $(UM_GPROF_OPT)
diff --git a/arch/um/configs/i386_defconfig b/arch/um/configs/i386_defconfig
index 9c9c77f1255a..1ffa088739f4 100644
--- a/arch/um/configs/i386_defconfig
+++ b/arch/um/configs/i386_defconfig
@@ -1,4 +1,3 @@
-CONFIG_3_LEVEL_PGTABLES=y
# CONFIG_COMPACTION is not set
CONFIG_BINFMT_MISC=m
CONFIG_HOSTFS=y
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index a66e556012c4..35f9beeb19b3 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -161,6 +161,8 @@ static __noreturn int winch_thread(void *arg)
int count;
char c = 1;
+ os_set_pdeathsig();
+
pty_fd = data->pty_fd;
pipe_fd = data->pipe_fd;
count = write(pipe_fd, &c, sizeof(c));
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 9d228878cea2..0ac149de1ac0 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -48,6 +48,7 @@ MODULE_PARM_DESC(mixer, MIXER_HELP);
#ifndef MODULE
static int set_dsp(char *name, int *add)
{
+ *add = 0;
dsp = name;
return 0;
}
@@ -56,6 +57,7 @@ __uml_setup("dsp=", set_dsp, "dsp=<dsp device>\n" DSP_HELP);
static int set_mixer(char *name, int *add)
{
+ *add = 0;
mixer = name;
return 0;
}
diff --git a/arch/um/drivers/net_kern.c b/arch/um/drivers/net_kern.c
index 77c4afb8ab90..75d04fb4994a 100644
--- a/arch/um/drivers/net_kern.c
+++ b/arch/um/drivers/net_kern.c
@@ -336,7 +336,7 @@ static struct platform_driver uml_net_driver = {
static void net_device_release(struct device *dev)
{
- struct uml_net *device = dev_get_drvdata(dev);
+ struct uml_net *device = container_of(dev, struct uml_net, pdev.dev);
struct net_device *netdev = device->dev;
struct uml_net_private *lp = netdev_priv(netdev);
diff --git a/arch/um/drivers/rtc_kern.c b/arch/um/drivers/rtc_kern.c
index 3a1582219c4b..134a58f93c85 100644
--- a/arch/um/drivers/rtc_kern.c
+++ b/arch/um/drivers/rtc_kern.c
@@ -176,7 +176,7 @@ static void uml_rtc_remove(struct platform_device *pdev)
static struct platform_driver uml_rtc_driver = {
.probe = uml_rtc_probe,
- .remove_new = uml_rtc_remove,
+ .remove = uml_rtc_remove,
.driver = {
.name = "uml-rtc",
},
diff --git a/arch/um/drivers/ubd_kern.c b/arch/um/drivers/ubd_kern.c
index 7f28ec1929dc..66c1a8835e36 100644
--- a/arch/um/drivers/ubd_kern.c
+++ b/arch/um/drivers/ubd_kern.c
@@ -779,7 +779,7 @@ static int ubd_open_dev(struct ubd *ubd_dev)
static void ubd_device_release(struct device *dev)
{
- struct ubd *ubd_dev = dev_get_drvdata(dev);
+ struct ubd *ubd_dev = container_of(dev, struct ubd, pdev.dev);
blk_mq_free_tag_set(&ubd_dev->tag_set);
*ubd_dev = ((struct ubd) DEFAULT_UBD);
@@ -898,6 +898,8 @@ static int ubd_add(int n, char **error_out)
if (err)
goto out_cleanup_disk;
+ ubd_dev->disk = disk;
+
return 0;
out_cleanup_disk:
@@ -1499,6 +1501,7 @@ int io_thread(void *arg)
{
int n, count, written, res;
+ os_set_pdeathsig();
os_fix_helper_signals();
while(1){
diff --git a/arch/um/drivers/vector_kern.c b/arch/um/drivers/vector_kern.c
index c992da83268d..64c09db392c1 100644
--- a/arch/um/drivers/vector_kern.c
+++ b/arch/um/drivers/vector_kern.c
@@ -815,7 +815,8 @@ static struct platform_driver uml_net_driver = {
static void vector_device_release(struct device *dev)
{
- struct vector_device *device = dev_get_drvdata(dev);
+ struct vector_device *device =
+ container_of(dev, struct vector_device, pdev.dev);
struct net_device *netdev = device->dev;
list_del(&device->list);
diff --git a/arch/um/drivers/vhost_user.h b/arch/um/drivers/vhost_user.h
index 6f147cd3c9f7..fcfa3b7e021b 100644
--- a/arch/um/drivers/vhost_user.h
+++ b/arch/um/drivers/vhost_user.h
@@ -10,6 +10,7 @@
/* Feature bits */
#define VHOST_USER_F_PROTOCOL_FEATURES 30
/* Protocol feature bits */
+#define VHOST_USER_PROTOCOL_F_MQ 0
#define VHOST_USER_PROTOCOL_F_REPLY_ACK 3
#define VHOST_USER_PROTOCOL_F_SLAVE_REQ 5
#define VHOST_USER_PROTOCOL_F_CONFIG 9
@@ -23,7 +24,8 @@
/* Supported transport features */
#define VHOST_USER_SUPPORTED_F BIT_ULL(VHOST_USER_F_PROTOCOL_FEATURES)
/* Supported protocol features */
-#define VHOST_USER_SUPPORTED_PROTOCOL_F (BIT_ULL(VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
+#define VHOST_USER_SUPPORTED_PROTOCOL_F (BIT_ULL(VHOST_USER_PROTOCOL_F_MQ) | \
+ BIT_ULL(VHOST_USER_PROTOCOL_F_REPLY_ACK) | \
BIT_ULL(VHOST_USER_PROTOCOL_F_SLAVE_REQ) | \
BIT_ULL(VHOST_USER_PROTOCOL_F_CONFIG) | \
BIT_ULL(VHOST_USER_PROTOCOL_F_INBAND_NOTIFICATIONS))
diff --git a/arch/um/drivers/virtio_uml.c b/arch/um/drivers/virtio_uml.c
index 2b6e701776b6..65df43fa9be5 100644
--- a/arch/um/drivers/virtio_uml.c
+++ b/arch/um/drivers/virtio_uml.c
@@ -56,6 +56,7 @@ struct virtio_uml_device {
int sock, req_fd, irq;
u64 features;
u64 protocol_features;
+ u64 max_vqs;
u8 status;
u8 registered:1;
u8 suspended:1;
@@ -72,8 +73,6 @@ struct virtio_uml_vq_info {
bool suspended;
};
-extern unsigned long long physmem_size, highmem;
-
#define vu_err(vu_dev, ...) dev_err(&(vu_dev)->pdev->dev, ##__VA_ARGS__)
/* Vhost-user protocol */
@@ -343,6 +342,17 @@ static int vhost_user_set_protocol_features(struct virtio_uml_device *vu_dev,
protocol_features);
}
+static int vhost_user_get_queue_num(struct virtio_uml_device *vu_dev,
+ u64 *queue_num)
+{
+ int rc = vhost_user_send_no_payload(vu_dev, true,
+ VHOST_USER_GET_QUEUE_NUM);
+
+ if (rc)
+ return rc;
+ return vhost_user_recv_u64(vu_dev, queue_num);
+}
+
static void vhost_user_reply(struct virtio_uml_device *vu_dev,
struct vhost_user_msg *msg, int response)
{
@@ -516,6 +526,15 @@ static int vhost_user_init(struct virtio_uml_device *vu_dev)
return rc;
}
+ if (vu_dev->protocol_features &
+ BIT_ULL(VHOST_USER_PROTOCOL_F_MQ)) {
+ rc = vhost_user_get_queue_num(vu_dev, &vu_dev->max_vqs);
+ if (rc)
+ return rc;
+ } else {
+ vu_dev->max_vqs = U64_MAX;
+ }
+
return 0;
}
@@ -625,7 +644,7 @@ static int vhost_user_set_mem_table(struct virtio_uml_device *vu_dev)
{
struct vhost_user_msg msg = {
.header.request = VHOST_USER_SET_MEM_TABLE,
- .header.size = sizeof(msg.payload.mem_regions),
+ .header.size = offsetof(typeof(msg.payload.mem_regions), regions[1]),
.payload.mem_regions.num = 1,
};
unsigned long reserved = uml_reserved - uml_physmem;
@@ -673,13 +692,6 @@ static int vhost_user_set_mem_table(struct virtio_uml_device *vu_dev)
if (rc < 0)
return rc;
- if (highmem) {
- msg.payload.mem_regions.num++;
- rc = vhost_user_init_mem_region(__pa(end_iomem), highmem,
- &fds[1], &msg.payload.mem_regions.regions[1]);
- if (rc < 0)
- return rc;
- }
return vhost_user_send(vu_dev, false, &msg, fds,
msg.payload.mem_regions.num);
@@ -897,7 +909,7 @@ static int vu_setup_vq_call_fd(struct virtio_uml_device *vu_dev,
{
struct virtio_uml_vq_info *info = vq->priv;
int call_fds[2];
- int rc;
+ int rc, irq;
/* no call FD needed/desired in this case */
if (vu_dev->protocol_features &
@@ -914,19 +926,23 @@ static int vu_setup_vq_call_fd(struct virtio_uml_device *vu_dev,
return rc;
info->call_fd = call_fds[0];
- rc = um_request_irq(vu_dev->irq, info->call_fd, IRQ_READ,
- vu_interrupt, IRQF_SHARED, info->name, vq);
- if (rc < 0)
+ irq = um_request_irq(vu_dev->irq, info->call_fd, IRQ_READ,
+ vu_interrupt, IRQF_SHARED, info->name, vq);
+ if (irq < 0) {
+ rc = irq;
goto close_both;
+ }
rc = vhost_user_set_vring_call(vu_dev, vq->index, call_fds[1]);
if (rc)
goto release_irq;
+ vu_dev->irq = irq;
+
goto out;
release_irq:
- um_free_irq(vu_dev->irq, vq);
+ um_free_irq(irq, vq);
close_both:
os_close_file(call_fds[0]);
out:
@@ -1023,7 +1039,9 @@ static int vu_find_vqs(struct virtio_device *vdev, unsigned nvqs,
struct virtqueue *vq;
/* not supported for now */
- if (WARN_ON(nvqs > 64))
+ if (WARN(nvqs > 64 || nvqs > vu_dev->max_vqs,
+ "%d VQs requested, only up to 64 or %lld supported\n",
+ nvqs, vu_dev->max_vqs))
return -EINVAL;
rc = vhost_user_set_mem_table(vu_dev);
@@ -1210,6 +1228,7 @@ static int virtio_uml_probe(struct platform_device *pdev)
vu_dev->vdev.id.vendor = VIRTIO_DEV_ANY_ID;
vu_dev->pdev = pdev;
vu_dev->req_fd = -1;
+ vu_dev->irq = UM_IRQ_ALLOC;
time_travel_propagate_time();
@@ -1446,7 +1465,7 @@ static int virtio_uml_resume(struct platform_device *pdev)
static struct platform_driver virtio_uml_driver = {
.probe = virtio_uml_probe,
- .remove_new = virtio_uml_remove,
+ .remove = virtio_uml_remove,
.driver = {
.name = "virtio-uml",
.of_match_table = virtio_uml_match,
diff --git a/arch/um/include/asm/Kbuild b/arch/um/include/asm/Kbuild
index 18f902da8e99..428f2c5158c2 100644
--- a/arch/um/include/asm/Kbuild
+++ b/arch/um/include/asm/Kbuild
@@ -1,7 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
generic-y += bug.h
generic-y += compat.h
-generic-y += current.h
generic-y += device.h
generic-y += dma-mapping.h
generic-y += emergency-restart.h
diff --git a/arch/um/include/asm/current.h b/arch/um/include/asm/current.h
new file mode 100644
index 000000000000..de64e032d66c
--- /dev/null
+++ b/arch/um/include/asm/current.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_CURRENT_H
+#define __ASM_CURRENT_H
+
+#include <linux/compiler.h>
+#include <linux/threads.h>
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+extern struct task_struct *cpu_tasks[NR_CPUS];
+
+static __always_inline struct task_struct *get_current(void)
+{
+ return cpu_tasks[0];
+}
+
+
+#define current get_current()
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* __ASM_CURRENT_H */
diff --git a/arch/um/include/asm/page.h b/arch/um/include/asm/page.h
index 834313ecd3d6..3d516f3ca9c7 100644
--- a/arch/um/include/asm/page.h
+++ b/arch/um/include/asm/page.h
@@ -29,51 +29,35 @@ struct page;
#define clear_user_page(page, vaddr, pg) clear_page(page)
#define copy_user_page(to, from, vaddr, pg) copy_page(to, from)
-#if defined(CONFIG_3_LEVEL_PGTABLES) && !defined(CONFIG_64BIT)
-
typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pmd; } pmd_t;
typedef struct { unsigned long pgd; } pgd_t;
-#define pte_val(p) ((p).pte)
-#define pte_get_bits(p, bits) ((p).pte & (bits))
-#define pte_set_bits(p, bits) ((p).pte |= (bits))
-#define pte_clear_bits(p, bits) ((p).pte &= ~(bits))
-#define pte_copy(to, from) ({ (to).pte = (from).pte; })
-#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE))
-#define pte_set_val(p, phys, prot) \
- ({ (p).pte = (phys) | pgprot_val(prot); })
+#if CONFIG_PGTABLE_LEVELS > 2
+typedef struct { unsigned long pmd; } pmd_t;
#define pmd_val(x) ((x).pmd)
#define __pmd(x) ((pmd_t) { (x) } )
-typedef unsigned long long phys_t;
+#if CONFIG_PGTABLE_LEVELS > 3
-#else
-
-typedef struct { unsigned long pte; } pte_t;
-typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pud; } pud_t;
+#define pud_val(x) ((x).pud)
+#define __pud(x) ((pud_t) { (x) } )
-#ifdef CONFIG_3_LEVEL_PGTABLES
-typedef struct { unsigned long pmd; } pmd_t;
-#define pmd_val(x) ((x).pmd)
-#define __pmd(x) ((pmd_t) { (x) } )
-#endif
+#endif /* CONFIG_PGTABLE_LEVELS > 3 */
+#endif /* CONFIG_PGTABLE_LEVELS > 2 */
#define pte_val(x) ((x).pte)
-
#define pte_get_bits(p, bits) ((p).pte & (bits))
#define pte_set_bits(p, bits) ((p).pte |= (bits))
#define pte_clear_bits(p, bits) ((p).pte &= ~(bits))
#define pte_copy(to, from) ((to).pte = (from).pte)
-#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEWPAGE))
+#define pte_is_zero(p) (!((p).pte & ~_PAGE_NEEDSYNC))
#define pte_set_val(p, phys, prot) (p).pte = (phys | pgprot_val(prot))
typedef unsigned long phys_t;
-#endif
-
typedef struct { unsigned long pgprot; } pgprot_t;
typedef struct page *pgtable_t;
diff --git a/arch/um/include/asm/pgalloc.h b/arch/um/include/asm/pgalloc.h
index de5e31c64793..04fb4e6969a4 100644
--- a/arch/um/include/asm/pgalloc.h
+++ b/arch/um/include/asm/pgalloc.h
@@ -31,7 +31,7 @@ do { \
tlb_remove_page_ptdesc((tlb), (page_ptdesc(pte))); \
} while (0)
-#ifdef CONFIG_3_LEVEL_PGTABLES
+#if CONFIG_PGTABLE_LEVELS > 2
#define __pmd_free_tlb(tlb, pmd, address) \
do { \
@@ -39,6 +39,15 @@ do { \
tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pmd)); \
} while (0)
+#if CONFIG_PGTABLE_LEVELS > 3
+
+#define __pud_free_tlb(tlb, pud, address) \
+do { \
+ pagetable_pud_dtor(virt_to_ptdesc(pud)); \
+ tlb_remove_page_ptdesc((tlb), virt_to_ptdesc(pud)); \
+} while (0)
+
+#endif
#endif
#endif
diff --git a/arch/um/include/asm/pgtable-2level.h b/arch/um/include/asm/pgtable-2level.h
index 8256ecc5b919..ab0c8dd86564 100644
--- a/arch/um/include/asm/pgtable-2level.h
+++ b/arch/um/include/asm/pgtable-2level.h
@@ -31,7 +31,7 @@
printk("%s:%d: bad pgd %p(%08lx).\n", __FILE__, __LINE__, &(e), \
pgd_val(e))
-static inline int pgd_newpage(pgd_t pgd) { return 0; }
+static inline int pgd_needsync(pgd_t pgd) { return 0; }
static inline void pgd_mkuptodate(pgd_t pgd) { }
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
diff --git a/arch/um/include/asm/pgtable-3level.h b/arch/um/include/asm/pgtable-4level.h
index 8a5032ec231f..0d279caee93c 100644
--- a/arch/um/include/asm/pgtable-3level.h
+++ b/arch/um/include/asm/pgtable-4level.h
@@ -4,21 +4,25 @@
* Derived from include/asm-i386/pgtable.h
*/
-#ifndef __UM_PGTABLE_3LEVEL_H
-#define __UM_PGTABLE_3LEVEL_H
+#ifndef __UM_PGTABLE_4LEVEL_H
+#define __UM_PGTABLE_4LEVEL_H
-#include <asm-generic/pgtable-nopud.h>
+#include <asm-generic/pgtable-nop4d.h>
-/* PGDIR_SHIFT determines what a third-level page table entry can map */
+/* PGDIR_SHIFT determines what a fourth-level page table entry can map */
-#ifdef CONFIG_64BIT
-#define PGDIR_SHIFT 30
-#else
-#define PGDIR_SHIFT 31
-#endif
+#define PGDIR_SHIFT 39
#define PGDIR_SIZE (1UL << PGDIR_SHIFT)
#define PGDIR_MASK (~(PGDIR_SIZE-1))
+/* PUD_SHIFT determines the size of the area a third-level page table can
+ * map
+ */
+
+#define PUD_SHIFT 30
+#define PUD_SIZE (1UL << PUD_SHIFT)
+#define PUD_MASK (~(PUD_SIZE-1))
+
/* PMD_SHIFT determines the size of the area a second-level page table can
* map
*/
@@ -32,13 +36,9 @@
*/
#define PTRS_PER_PTE 512
-#ifdef CONFIG_64BIT
#define PTRS_PER_PMD 512
+#define PTRS_PER_PUD 512
#define PTRS_PER_PGD 512
-#else
-#define PTRS_PER_PMD 1024
-#define PTRS_PER_PGD 1024
-#endif
#define USER_PTRS_PER_PGD ((TASK_SIZE + (PGDIR_SIZE - 1)) / PGDIR_SIZE)
@@ -48,11 +48,14 @@
#define pmd_ERROR(e) \
printk("%s:%d: bad pmd %p(%016lx).\n", __FILE__, __LINE__, &(e), \
pmd_val(e))
+#define pud_ERROR(e) \
+ printk("%s:%d: bad pud %p(%016lx).\n", __FILE__, __LINE__, &(e), \
+ pud_val(e))
#define pgd_ERROR(e) \
printk("%s:%d: bad pgd %p(%016lx).\n", __FILE__, __LINE__, &(e), \
pgd_val(e))
-#define pud_none(x) (!(pud_val(x) & ~_PAGE_NEWPAGE))
+#define pud_none(x) (!(pud_val(x) & ~_PAGE_NEEDSYNC))
#define pud_bad(x) ((pud_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
#define pud_present(x) (pud_val(x) & _PAGE_PRESENT)
#define pud_populate(mm, pud, pmd) \
@@ -60,23 +63,40 @@
#define set_pud(pudptr, pudval) (*(pudptr) = (pudval))
-static inline int pgd_newpage(pgd_t pgd)
+#define p4d_none(x) (!(p4d_val(x) & ~_PAGE_NEEDSYNC))
+#define p4d_bad(x) ((p4d_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
+#define p4d_present(x) (p4d_val(x) & _PAGE_PRESENT)
+#define p4d_populate(mm, p4d, pud) \
+ set_p4d(p4d, __p4d(_PAGE_TABLE + __pa(pud)))
+
+#define set_p4d(p4dptr, p4dval) (*(p4dptr) = (p4dval))
+
+
+static inline int pgd_needsync(pgd_t pgd)
{
- return(pgd_val(pgd) & _PAGE_NEWPAGE);
+ return pgd_val(pgd) & _PAGE_NEEDSYNC;
}
-static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEWPAGE; }
+static inline void pgd_mkuptodate(pgd_t pgd) { pgd_val(pgd) &= ~_PAGE_NEEDSYNC; }
#define set_pmd(pmdptr, pmdval) (*(pmdptr) = (pmdval))
static inline void pud_clear (pud_t *pud)
{
- set_pud(pud, __pud(_PAGE_NEWPAGE));
+ set_pud(pud, __pud(_PAGE_NEEDSYNC));
+}
+
+static inline void p4d_clear (p4d_t *p4d)
+{
+ set_p4d(p4d, __p4d(_PAGE_NEEDSYNC));
}
#define pud_page(pud) phys_to_page(pud_val(pud) & PAGE_MASK)
#define pud_pgtable(pud) ((pmd_t *) __va(pud_val(pud) & PAGE_MASK))
+#define p4d_page(p4d) phys_to_page(p4d_val(p4d) & PAGE_MASK)
+#define p4d_pgtable(p4d) ((pud_t *) __va(p4d_val(p4d) & PAGE_MASK))
+
static inline unsigned long pte_pfn(pte_t pte)
{
return phys_to_pfn(pte_val(pte));
@@ -97,4 +117,3 @@ static inline pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot)
}
#endif
-
diff --git a/arch/um/include/asm/pgtable.h b/arch/um/include/asm/pgtable.h
index faab5a2a4b06..0bd60afcc37d 100644
--- a/arch/um/include/asm/pgtable.h
+++ b/arch/um/include/asm/pgtable.h
@@ -11,8 +11,7 @@
#include <asm/fixmap.h>
#define _PAGE_PRESENT 0x001
-#define _PAGE_NEWPAGE 0x002
-#define _PAGE_NEWPROT 0x004
+#define _PAGE_NEEDSYNC 0x002
#define _PAGE_RW 0x020
#define _PAGE_USER 0x040
#define _PAGE_ACCESSED 0x080
@@ -24,10 +23,12 @@
/* We borrow bit 10 to store the exclusive marker in swap PTEs. */
#define _PAGE_SWP_EXCLUSIVE 0x400
-#ifdef CONFIG_3_LEVEL_PGTABLES
-#include <asm/pgtable-3level.h>
-#else
+#if CONFIG_PGTABLE_LEVELS == 4
+#include <asm/pgtable-4level.h>
+#elif CONFIG_PGTABLE_LEVELS == 2
#include <asm/pgtable-2level.h>
+#else
+#error "Unsupported number of page table levels"
#endif
extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
@@ -78,22 +79,22 @@ extern unsigned long end_iomem;
*/
#define ZERO_PAGE(vaddr) virt_to_page(empty_zero_page)
-#define pte_clear(mm,addr,xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEWPAGE))
+#define pte_clear(mm, addr, xp) pte_set_val(*(xp), (phys_t) 0, __pgprot(_PAGE_NEEDSYNC))
-#define pmd_none(x) (!((unsigned long)pmd_val(x) & ~_PAGE_NEWPAGE))
+#define pmd_none(x) (!((unsigned long)pmd_val(x) & ~_PAGE_NEEDSYNC))
#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
#define pmd_present(x) (pmd_val(x) & _PAGE_PRESENT)
-#define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEWPAGE; } while (0)
+#define pmd_clear(xp) do { pmd_val(*(xp)) = _PAGE_NEEDSYNC; } while (0)
-#define pmd_newpage(x) (pmd_val(x) & _PAGE_NEWPAGE)
-#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEWPAGE)
+#define pmd_needsync(x) (pmd_val(x) & _PAGE_NEEDSYNC)
+#define pmd_mkuptodate(x) (pmd_val(x) &= ~_PAGE_NEEDSYNC)
-#define pud_newpage(x) (pud_val(x) & _PAGE_NEWPAGE)
-#define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEWPAGE)
+#define pud_needsync(x) (pud_val(x) & _PAGE_NEEDSYNC)
+#define pud_mkuptodate(x) (pud_val(x) &= ~_PAGE_NEEDSYNC)
-#define p4d_newpage(x) (p4d_val(x) & _PAGE_NEWPAGE)
-#define p4d_mkuptodate(x) (p4d_val(x) &= ~_PAGE_NEWPAGE)
+#define p4d_needsync(x) (p4d_val(x) & _PAGE_NEEDSYNC)
+#define p4d_mkuptodate(x) (p4d_val(x) &= ~_PAGE_NEEDSYNC)
#define pmd_pfn(pmd) (pmd_val(pmd) >> PAGE_SHIFT)
#define pmd_page(pmd) phys_to_page(pmd_val(pmd) & PAGE_MASK)
@@ -144,14 +145,9 @@ static inline int pte_young(pte_t pte)
return pte_get_bits(pte, _PAGE_ACCESSED);
}
-static inline int pte_newpage(pte_t pte)
+static inline int pte_needsync(pte_t pte)
{
- return pte_get_bits(pte, _PAGE_NEWPAGE);
-}
-
-static inline int pte_newprot(pte_t pte)
-{
- return(pte_present(pte) && (pte_get_bits(pte, _PAGE_NEWPROT)));
+ return pte_get_bits(pte, _PAGE_NEEDSYNC);
}
/*
@@ -160,12 +156,6 @@ static inline int pte_newprot(pte_t pte)
* =================================
*/
-static inline pte_t pte_mknewprot(pte_t pte)
-{
- pte_set_bits(pte, _PAGE_NEWPROT);
- return(pte);
-}
-
static inline pte_t pte_mkclean(pte_t pte)
{
pte_clear_bits(pte, _PAGE_DIRTY);
@@ -180,19 +170,14 @@ static inline pte_t pte_mkold(pte_t pte)
static inline pte_t pte_wrprotect(pte_t pte)
{
- if (likely(pte_get_bits(pte, _PAGE_RW)))
- pte_clear_bits(pte, _PAGE_RW);
- else
- return pte;
- return(pte_mknewprot(pte));
+ pte_clear_bits(pte, _PAGE_RW);
+ return pte;
}
static inline pte_t pte_mkread(pte_t pte)
{
- if (unlikely(pte_get_bits(pte, _PAGE_USER)))
- return pte;
pte_set_bits(pte, _PAGE_USER);
- return(pte_mknewprot(pte));
+ return pte;
}
static inline pte_t pte_mkdirty(pte_t pte)
@@ -209,23 +194,19 @@ static inline pte_t pte_mkyoung(pte_t pte)
static inline pte_t pte_mkwrite_novma(pte_t pte)
{
- if (unlikely(pte_get_bits(pte, _PAGE_RW)))
- return pte;
pte_set_bits(pte, _PAGE_RW);
- return(pte_mknewprot(pte));
+ return pte;
}
static inline pte_t pte_mkuptodate(pte_t pte)
{
- pte_clear_bits(pte, _PAGE_NEWPAGE);
- if(pte_present(pte))
- pte_clear_bits(pte, _PAGE_NEWPROT);
- return(pte);
+ pte_clear_bits(pte, _PAGE_NEEDSYNC);
+ return pte;
}
-static inline pte_t pte_mknewpage(pte_t pte)
+static inline pte_t pte_mkneedsync(pte_t pte)
{
- pte_set_bits(pte, _PAGE_NEWPAGE);
+ pte_set_bits(pte, _PAGE_NEEDSYNC);
return(pte);
}
@@ -233,13 +214,11 @@ static inline void set_pte(pte_t *pteptr, pte_t pteval)
{
pte_copy(*pteptr, pteval);
- /* If it's a swap entry, it needs to be marked _PAGE_NEWPAGE so
- * fix_range knows to unmap it. _PAGE_NEWPROT is specific to
- * mapped pages.
+ /* If it's a swap entry, it needs to be marked _PAGE_NEEDSYNC so
+ * update_pte_range knows to unmap it.
*/
- *pteptr = pte_mknewpage(*pteptr);
- if(pte_present(*pteptr)) *pteptr = pte_mknewprot(*pteptr);
+ *pteptr = pte_mkneedsync(*pteptr);
}
#define PFN_PTE_SHIFT PAGE_SHIFT
@@ -279,7 +258,7 @@ static inline void set_ptes(struct mm_struct *mm, unsigned long addr,
#define __HAVE_ARCH_PTE_SAME
static inline int pte_same(pte_t pte_a, pte_t pte_b)
{
- return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEWPAGE);
+ return !((pte_val(pte_a) ^ pte_val(pte_b)) & ~_PAGE_NEEDSYNC);
}
/*
@@ -294,8 +273,6 @@ static inline int pte_same(pte_t pte_a, pte_t pte_b)
({ pte_t pte; \
\
pte_set_val(pte, page_to_phys(page), (pgprot)); \
- if (pte_present(pte)) \
- pte_mknewprot(pte_mknewpage(pte)); \
pte;})
static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
@@ -329,7 +306,7 @@ extern pte_t *virt_to_pte(struct mm_struct *mm, unsigned long addr);
* <--------------- offset ----------------> E < type -> 0 0 0 1 0
*
* E is the exclusive marker that is not stored in swap entries.
- * _PAGE_NEWPAGE (bit 1) is always set to 1 in set_pte().
+ * _PAGE_NEEDSYNC (bit 1) is always set to 1 in set_pte().
*/
#define __swp_type(x) (((x).val >> 5) & 0x1f)
#define __swp_offset(x) ((x).val >> 11)
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h
index bce4595798da..5d6356eafffe 100644
--- a/arch/um/include/asm/processor-generic.h
+++ b/arch/um/include/asm/processor-generic.h
@@ -20,10 +20,7 @@ struct task_struct;
struct mm_struct;
struct thread_struct {
- struct pt_regs regs;
struct pt_regs *segv_regs;
- void *fault_addr;
- jmp_buf *fault_catcher;
struct task_struct *prev_sched;
struct arch_thread arch;
jmp_buf switch_buf;
@@ -33,12 +30,14 @@ struct thread_struct {
void *arg;
} thread;
} request;
+
+ /* Contains variable sized FP registers */
+ struct pt_regs regs;
};
#define INIT_THREAD \
{ \
.regs = EMPTY_REGS, \
- .fault_addr = NULL, \
.prev_sched = NULL, \
.arch = INIT_ARCH_THREAD, \
.request = { } \
diff --git a/arch/um/include/asm/thread_info.h b/arch/um/include/asm/thread_info.h
index c7b4b49826a2..f9ad06fcc991 100644
--- a/arch/um/include/asm/thread_info.h
+++ b/arch/um/include/asm/thread_info.h
@@ -17,35 +17,17 @@
#include <sysdep/ptrace_user.h>
struct thread_info {
- struct task_struct *task; /* main task structure */
unsigned long flags; /* low level flags */
__u32 cpu; /* current CPU */
int preempt_count; /* 0 => preemptable,
<0 => BUG */
- struct thread_info *real_thread; /* Points to non-IRQ stack */
- unsigned long aux_fp_regs[FP_SIZE]; /* auxiliary fp_regs to save/restore
- them out-of-band */
};
#define INIT_THREAD_INFO(tsk) \
{ \
- .task = &tsk, \
.flags = 0, \
.cpu = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \
- .real_thread = NULL, \
-}
-
-/* how to get the thread information struct from C */
-static inline struct thread_info *current_thread_info(void)
-{
- struct thread_info *ti;
- unsigned long mask = THREAD_SIZE - 1;
- void *p;
-
- asm volatile ("" : "=r" (p) : "0" (&ti));
- ti = (struct thread_info *) (((unsigned long)p) & ~mask);
- return ti;
}
#endif
diff --git a/arch/um/include/asm/tlbflush.h b/arch/um/include/asm/tlbflush.h
index db997976b6ea..13a3009942be 100644
--- a/arch/um/include/asm/tlbflush.h
+++ b/arch/um/include/asm/tlbflush.h
@@ -9,8 +9,8 @@
#include <linux/mm.h>
/*
- * In UML, we need to sync the TLB over by using mmap/munmap/mprotect syscalls
- * from the process handling the MM (which can be the kernel itself).
+ * In UML, we need to sync the TLB over by using mmap/munmap syscalls from
+ * the process handling the MM (which can be the kernel itself).
*
* To track updates, we can hook into set_ptes and flush_tlb_*. With set_ptes
* we catch all PTE transitions where memory that was unusable becomes usable.
diff --git a/arch/um/include/shared/as-layout.h b/arch/um/include/shared/as-layout.h
index 06292fca5a4d..ea65f151bf48 100644
--- a/arch/um/include/shared/as-layout.h
+++ b/arch/um/include/shared/as-layout.h
@@ -30,25 +30,23 @@
#include <sysdep/ptrace.h>
-struct cpu_task {
- void *task;
-};
+struct task_struct;
+extern struct task_struct *cpu_tasks[];
-extern struct cpu_task cpu_tasks[];
+extern unsigned long long physmem_size;
extern unsigned long high_physmem;
extern unsigned long uml_physmem;
extern unsigned long uml_reserved;
extern unsigned long end_vm;
extern unsigned long start_vm;
-extern unsigned long long highmem;
extern unsigned long brk_start;
extern unsigned long host_task_size;
extern unsigned long stub_start;
-extern int linux_main(int argc, char **argv);
+extern int linux_main(int argc, char **argv, char **envp);
extern void uml_finishsetup(void);
struct siginfo;
diff --git a/arch/um/include/shared/common-offsets.h b/arch/um/include/shared/common-offsets.h
index 579ed946a3a9..73f3a4792ed8 100644
--- a/arch/um/include/shared/common-offsets.h
+++ b/arch/um/include/shared/common-offsets.h
@@ -6,7 +6,6 @@ DEFINE(KERNEL_MADV_REMOVE, MADV_REMOVE);
DEFINE(UM_KERN_PAGE_SIZE, PAGE_SIZE);
DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT);
-DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
DEFINE(UM_GFP_KERNEL, GFP_KERNEL);
DEFINE(UM_GFP_ATOMIC, GFP_ATOMIC);
@@ -15,17 +14,3 @@ DEFINE(UM_THREAD_SIZE, THREAD_SIZE);
DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
DEFINE(UM_NSEC_PER_USEC, NSEC_PER_USEC);
-
-#ifdef CONFIG_PRINTK
-DEFINE(UML_CONFIG_PRINTK, CONFIG_PRINTK);
-#endif
-#ifdef CONFIG_UML_X86
-DEFINE(UML_CONFIG_UML_X86, CONFIG_UML_X86);
-#endif
-#ifdef CONFIG_64BIT
-DEFINE(UML_CONFIG_64BIT, CONFIG_64BIT);
-#endif
-#ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
-DEFINE(UML_CONFIG_UML_TIME_TRAVEL_SUPPORT, CONFIG_UML_TIME_TRAVEL_SUPPORT);
-#endif
-
diff --git a/arch/um/include/shared/kern_util.h b/arch/um/include/shared/kern_util.h
index d8ffd2db168e..f21dc8517538 100644
--- a/arch/um/include/shared/kern_util.h
+++ b/arch/um/include/shared/kern_util.h
@@ -60,7 +60,6 @@ extern unsigned long from_irq_stack(int nested);
extern int singlestepping(void);
extern void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs);
-extern void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs);
extern void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs);
extern void fatal_sigsegv(void) __attribute__ ((noreturn));
diff --git a/arch/um/include/shared/mem_user.h b/arch/um/include/shared/mem_user.h
index 11a723a58545..adfa08062f88 100644
--- a/arch/um/include/shared/mem_user.h
+++ b/arch/um/include/shared/mem_user.h
@@ -47,10 +47,9 @@ extern int iomem_size;
#define ROUND_4M(n) ((((unsigned long) (n)) + (1 << 22)) & ~((1 << 22) - 1))
extern unsigned long find_iomem(char *driver, unsigned long *len_out);
-extern void mem_total_pages(unsigned long physmem, unsigned long iomem,
- unsigned long highmem);
+extern void mem_total_pages(unsigned long physmem, unsigned long iomem);
extern void setup_physmem(unsigned long start, unsigned long usable,
- unsigned long len, unsigned long long highmem);
+ unsigned long len);
extern void map_memory(unsigned long virt, unsigned long phys,
unsigned long len, int r, int w, int x);
diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
index 9a039d6f1f74..5babad8c5f75 100644
--- a/arch/um/include/shared/os.h
+++ b/arch/um/include/shared/os.h
@@ -145,7 +145,6 @@ extern int os_ioctl_generic(int fd, unsigned int cmd, unsigned long arg);
extern int os_get_ifname(int fd, char *namebuf);
extern int os_set_slip(int fd);
extern int os_mode_fd(int fd, int mode);
-extern int os_fsync_file(int fd);
extern int os_seek_file(int fd, unsigned long long offset);
extern int os_open_file(const char *file, struct openflags flags, int mode);
@@ -199,15 +198,11 @@ extern int create_mem_file(unsigned long long len);
extern void report_enomem(void);
/* process.c */
-extern unsigned long os_process_pc(int pid);
-extern int os_process_parent(int pid);
extern void os_alarm_process(int pid);
-extern void os_stop_process(int pid);
extern void os_kill_process(int pid, int reap_child);
extern void os_kill_ptraced_process(int pid, int reap_child);
extern int os_getpid(void);
-extern int os_getpgrp(void);
extern void init_new_thread_signals(void);
@@ -220,6 +215,8 @@ extern int os_drop_memory(void *addr, int length);
extern int can_drop_memory(void);
extern int os_mincore(void *addr, unsigned long len);
+void os_set_pdeathsig(void);
+
/* execvp.c */
extern int execvp_noalloc(char *buf, const char *file, char *const argv[]);
/* helper.c */
@@ -244,7 +241,6 @@ extern void block_signals(void);
extern void unblock_signals(void);
extern int um_set_signals(int enable);
extern int um_set_signals_trace(int enable);
-extern int os_is_signal_stack(void);
extern void deliver_alarm(void);
extern void register_pm_wake_signal(void);
extern void block_signals_hard(void);
@@ -283,13 +279,11 @@ int map(struct mm_id *mm_idp, unsigned long virt,
unsigned long len, int prot, int phys_fd,
unsigned long long offset);
int unmap(struct mm_id *mm_idp, unsigned long addr, unsigned long len);
-int protect(struct mm_id *mm_idp, unsigned long addr,
- unsigned long len, unsigned int prot);
/* skas/process.c */
extern int is_skas_winch(int pid, int fd, void *data);
extern int start_userspace(unsigned long stub_stack);
-extern void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs);
+extern void userspace(struct uml_pt_regs *regs);
extern void new_thread(void *stack, jmp_buf *buf, void (*handler)(void));
extern void switch_threads(jmp_buf *me, jmp_buf *you);
extern int start_idle_thread(void *stack, jmp_buf *switch_buf);
@@ -329,9 +323,6 @@ extern int __ignore_sigio_fd(int fd);
/* tty.c */
extern int get_pty(void);
-/* sys-$ARCH/task_size.c */
-extern unsigned long os_get_top_address(void);
-
long syscall(long number, ...);
/* irqflags tracing */
diff --git a/arch/um/include/shared/registers.h b/arch/um/include/shared/registers.h
index a0450326521c..7d81b2339a48 100644
--- a/arch/um/include/shared/registers.h
+++ b/arch/um/include/shared/registers.h
@@ -8,12 +8,6 @@
#include <sysdep/ptrace.h>
-extern int save_i387_registers(int pid, unsigned long *fp_regs);
-extern int restore_i387_registers(int pid, unsigned long *fp_regs);
-extern int save_fp_registers(int pid, unsigned long *fp_regs);
-extern int restore_fp_registers(int pid, unsigned long *fp_regs);
-extern int save_fpx_registers(int pid, unsigned long *fp_regs);
-extern int restore_fpx_registers(int pid, unsigned long *fp_regs);
extern int init_pid_registers(int pid);
extern void get_safe_registers(unsigned long *regs, unsigned long *fp_regs);
extern int get_fp_registers(int pid, unsigned long *regs);
diff --git a/arch/um/include/shared/skas/stub-data.h b/arch/um/include/shared/skas/stub-data.h
index 2b6b44759dfa..81a4cace032c 100644
--- a/arch/um/include/shared/skas/stub-data.h
+++ b/arch/um/include/shared/skas/stub-data.h
@@ -12,6 +12,17 @@
#include <as-layout.h>
#include <sysdep/tls.h>
+struct stub_init_data {
+ unsigned long stub_start;
+
+ int stub_code_fd;
+ unsigned long stub_code_offset;
+ int stub_data_fd;
+ unsigned long stub_data_offset;
+
+ unsigned long segv_handler;
+};
+
#define STUB_NEXT_SYSCALL(s) \
((struct stub_syscall *) (((unsigned long) s) + (s)->cmd_len))
@@ -19,7 +30,6 @@ enum stub_syscall_type {
STUB_SYSCALL_UNSET = 0,
STUB_SYSCALL_MMAP,
STUB_SYSCALL_MUNMAP,
- STUB_SYSCALL_MPROTECT,
};
struct stub_syscall {
diff --git a/arch/um/include/shared/timetravel.h b/arch/um/include/shared/timetravel.h
index c8db2f213dba..7c2b277b7eb0 100644
--- a/arch/um/include/shared/timetravel.h
+++ b/arch/um/include/shared/timetravel.h
@@ -12,14 +12,13 @@ enum time_travel_mode {
TT_MODE_EXTERNAL,
};
-#if defined(UML_CONFIG_UML_TIME_TRAVEL_SUPPORT) || \
- defined(CONFIG_UML_TIME_TRAVEL_SUPPORT)
+#if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT)
extern enum time_travel_mode time_travel_mode;
extern int time_travel_should_print_bc_msg;
#else
#define time_travel_mode TT_MODE_OFF
#define time_travel_should_print_bc_msg 0
-#endif /* (UML_)CONFIG_UML_TIME_TRAVEL_SUPPORT */
+#endif /* CONFIG_UML_TIME_TRAVEL_SUPPORT */
void _time_travel_print_bc_msg(void);
static inline void time_travel_print_bc_msg(void)
diff --git a/arch/um/include/shared/user.h b/arch/um/include/shared/user.h
index bbab79c0c074..139eb78a4767 100644
--- a/arch/um/include/shared/user.h
+++ b/arch/um/include/shared/user.h
@@ -38,7 +38,7 @@ extern void panic(const char *fmt, ...)
#define UM_KERN_DEBUG KERN_DEBUG
#define UM_KERN_CONT KERN_CONT
-#ifdef UML_CONFIG_PRINTK
+#if IS_ENABLED(CONFIG_PRINTK)
#define printk(...) _printk(__VA_ARGS__)
extern int _printk(const char *fmt, ...)
__attribute__ ((format (printf, 1, 2)));
diff --git a/arch/um/kernel/dtb.c b/arch/um/kernel/dtb.c
index 8d78ced9e08f..15c342426489 100644
--- a/arch/um/kernel/dtb.c
+++ b/arch/um/kernel/dtb.c
@@ -31,6 +31,7 @@ void uml_dtb_init(void)
static int __init uml_dtb_setup(char *line, int *add)
{
+ *add = 0;
dtb = line;
return 0;
}
diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S
index 3385d653ebd0..a36b7918a011 100644
--- a/arch/um/kernel/dyn.lds.S
+++ b/arch/um/kernel/dyn.lds.S
@@ -116,8 +116,6 @@ SECTIONS
.fini_array : { *(.fini_array) }
.data : {
INIT_TASK_DATA(KERNEL_STACK_SIZE)
- . = ALIGN(KERNEL_STACK_SIZE);
- *(.data..init_irqstack)
DATA_DATA
*(.data.* .gnu.linkonce.d.*)
SORT(CONSTRUCTORS)
@@ -178,3 +176,6 @@ SECTIONS
DISCARDS
}
+
+ASSERT(__syscall_stub_end - __syscall_stub_start <= PAGE_SIZE,
+ "STUB code must not be larger than one page");
diff --git a/arch/um/kernel/initrd.c b/arch/um/kernel/initrd.c
index 47b8cb1a1156..99dba827461c 100644
--- a/arch/um/kernel/initrd.c
+++ b/arch/um/kernel/initrd.c
@@ -34,6 +34,7 @@ int __init read_initrd(void)
static int __init uml_initrd_setup(char *line, int *add)
{
+ *add = 0;
initrd = line;
return 0;
}
diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c
index 534e91797f89..338450741aac 100644
--- a/arch/um/kernel/irq.c
+++ b/arch/um/kernel/irq.c
@@ -674,115 +674,3 @@ void __init init_IRQ(void)
/* Initialize EPOLL Loop */
os_setup_epoll();
}
-
-/*
- * IRQ stack entry and exit:
- *
- * Unlike i386, UML doesn't receive IRQs on the normal kernel stack
- * and switch over to the IRQ stack after some preparation. We use
- * sigaltstack to receive signals on a separate stack from the start.
- * These two functions make sure the rest of the kernel won't be too
- * upset by being on a different stack. The IRQ stack has a
- * thread_info structure at the bottom so that current et al continue
- * to work.
- *
- * to_irq_stack copies the current task's thread_info to the IRQ stack
- * thread_info and sets the tasks's stack to point to the IRQ stack.
- *
- * from_irq_stack copies the thread_info struct back (flags may have
- * been modified) and resets the task's stack pointer.
- *
- * Tricky bits -
- *
- * What happens when two signals race each other? UML doesn't block
- * signals with sigprocmask, SA_DEFER, or sa_mask, so a second signal
- * could arrive while a previous one is still setting up the
- * thread_info.
- *
- * There are three cases -
- * The first interrupt on the stack - sets up the thread_info and
- * handles the interrupt
- * A nested interrupt interrupting the copying of the thread_info -
- * can't handle the interrupt, as the stack is in an unknown state
- * A nested interrupt not interrupting the copying of the
- * thread_info - doesn't do any setup, just handles the interrupt
- *
- * The first job is to figure out whether we interrupted stack setup.
- * This is done by xchging the signal mask with thread_info->pending.
- * If the value that comes back is zero, then there is no setup in
- * progress, and the interrupt can be handled. If the value is
- * non-zero, then there is stack setup in progress. In order to have
- * the interrupt handled, we leave our signal in the mask, and it will
- * be handled by the upper handler after it has set up the stack.
- *
- * Next is to figure out whether we are the outer handler or a nested
- * one. As part of setting up the stack, thread_info->real_thread is
- * set to non-NULL (and is reset to NULL on exit). This is the
- * nesting indicator. If it is non-NULL, then the stack is already
- * set up and the handler can run.
- */
-
-static unsigned long pending_mask;
-
-unsigned long to_irq_stack(unsigned long *mask_out)
-{
- struct thread_info *ti;
- unsigned long mask, old;
- int nested;
-
- mask = xchg(&pending_mask, *mask_out);
- if (mask != 0) {
- /*
- * If any interrupts come in at this point, we want to
- * make sure that their bits aren't lost by our
- * putting our bit in. So, this loop accumulates bits
- * until xchg returns the same value that we put in.
- * When that happens, there were no new interrupts,
- * and pending_mask contains a bit for each interrupt
- * that came in.
- */
- old = *mask_out;
- do {
- old |= mask;
- mask = xchg(&pending_mask, old);
- } while (mask != old);
- return 1;
- }
-
- ti = current_thread_info();
- nested = (ti->real_thread != NULL);
- if (!nested) {
- struct task_struct *task;
- struct thread_info *tti;
-
- task = cpu_tasks[ti->cpu].task;
- tti = task_thread_info(task);
-
- *ti = *tti;
- ti->real_thread = tti;
- task->stack = ti;
- }
-
- mask = xchg(&pending_mask, 0);
- *mask_out |= mask | nested;
- return 0;
-}
-
-unsigned long from_irq_stack(int nested)
-{
- struct thread_info *ti, *to;
- unsigned long mask;
-
- ti = current_thread_info();
-
- pending_mask = 1;
-
- to = ti->real_thread;
- current->stack = to;
- ti->real_thread = NULL;
- *to = *ti;
-
- mask = xchg(&pending_mask, 0);
- return mask & ~1;
-}
-
diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c
index a5b4fe2ad931..53248ed04771 100644
--- a/arch/um/kernel/mem.c
+++ b/arch/um/kernel/mem.c
@@ -6,7 +6,6 @@
#include <linux/stddef.h>
#include <linux/module.h>
#include <linux/memblock.h>
-#include <linux/highmem.h>
#include <linux/mm.h>
#include <linux/swap.h>
#include <linux/slab.h>
@@ -51,8 +50,6 @@ EXPORT_SYMBOL(empty_zero_page);
pgd_t swapper_pg_dir[PTRS_PER_PGD];
/* Initialized at boot time, and readonly after that */
-unsigned long long highmem;
-EXPORT_SYMBOL(highmem);
int kmalloc_ok = 0;
/* Used during early boot */
@@ -98,7 +95,7 @@ static void __init one_page_table_init(pmd_t *pmd)
static void __init one_md_table_init(pud_t *pud)
{
-#ifdef CONFIG_3_LEVEL_PGTABLES
+#if CONFIG_PGTABLE_LEVELS > 2
pmd_t *pmd_table = (pmd_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
if (!pmd_table)
panic("%s: Failed to allocate %lu bytes align=%lx\n",
@@ -109,6 +106,19 @@ static void __init one_md_table_init(pud_t *pud)
#endif
}
+static void __init one_ud_table_init(p4d_t *p4d)
+{
+#if CONFIG_PGTABLE_LEVELS > 3
+ pud_t *pud_table = (pud_t *) memblock_alloc_low(PAGE_SIZE, PAGE_SIZE);
+ if (!pud_table)
+ panic("%s: Failed to allocate %lu bytes align=%lx\n",
+ __func__, PAGE_SIZE, PAGE_SIZE);
+
+ set_p4d(p4d, __p4d(_KERNPG_TABLE + (unsigned long) __pa(pud_table)));
+ BUG_ON(pud_table != pud_offset(p4d, 0));
+#endif
+}
+
static void __init fixrange_init(unsigned long start, unsigned long end,
pgd_t *pgd_base)
{
@@ -126,6 +136,8 @@ static void __init fixrange_init(unsigned long start, unsigned long end,
for ( ; (i < PTRS_PER_PGD) && (vaddr < end); pgd++, i++) {
p4d = p4d_offset(pgd, vaddr);
+ if (p4d_none(*p4d))
+ one_ud_table_init(p4d);
pud = pud_offset(p4d, vaddr);
if (pud_none(*pud))
one_md_table_init(pud);
diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c
index fb2adfb49945..a74f17b033c4 100644
--- a/arch/um/kernel/physmem.c
+++ b/arch/um/kernel/physmem.c
@@ -22,19 +22,14 @@ static int physmem_fd = -1;
unsigned long high_physmem;
EXPORT_SYMBOL(high_physmem);
-extern unsigned long long physmem_size;
-
-void __init mem_total_pages(unsigned long physmem, unsigned long iomem,
- unsigned long highmem)
+void __init mem_total_pages(unsigned long physmem, unsigned long iomem)
{
- unsigned long phys_pages, highmem_pages;
- unsigned long iomem_pages, total_pages;
+ unsigned long phys_pages, iomem_pages, total_pages;
- phys_pages = physmem >> PAGE_SHIFT;
- iomem_pages = iomem >> PAGE_SHIFT;
- highmem_pages = highmem >> PAGE_SHIFT;
+ phys_pages = physmem >> PAGE_SHIFT;
+ iomem_pages = iomem >> PAGE_SHIFT;
- total_pages = phys_pages + iomem_pages + highmem_pages;
+ total_pages = phys_pages + iomem_pages;
max_mapnr = total_pages;
}
@@ -64,13 +59,12 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
* @reserve_end: end address of the physical kernel memory.
* @len: Length of total physical memory that should be mapped/made
* available, in bytes.
- * @highmem: Number of highmem bytes that should be mapped/made available.
*
- * Creates an unlinked temporary file of size (len + highmem) and memory maps
+ * Creates an unlinked temporary file of size (len) and memory maps
* it on the last executable image address (uml_reserved).
*
* The offset is needed as the length of the total physical memory
- * (len + highmem) includes the size of the memory used be the executable image,
+ * (len) includes the size of the memory used be the executable image,
* but the mapped-to address is the last address of the executable image
* (uml_reserved == end address of executable image).
*
@@ -78,24 +72,24 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len,
* of all user space processes/kernel tasks.
*/
void __init setup_physmem(unsigned long start, unsigned long reserve_end,
- unsigned long len, unsigned long long highmem)
+ unsigned long len)
{
unsigned long reserve = reserve_end - start;
- long map_size = len - reserve;
+ unsigned long map_size = len - reserve;
int err;
- if(map_size <= 0) {
+ if (len <= reserve) {
os_warn("Too few physical memory! Needed=%lu, given=%lu\n",
reserve, len);
exit(1);
}
- physmem_fd = create_mem_file(len + highmem);
+ physmem_fd = create_mem_file(len);
err = os_map_memory((void *) reserve_end, physmem_fd, reserve,
map_size, 1, 1, 1);
if (err < 0) {
- os_warn("setup_physmem - mapping %ld bytes of memory at 0x%p "
+ os_warn("setup_physmem - mapping %lu bytes of memory at 0x%p "
"failed - errno = %d\n", map_size,
(void *) reserve_end, err);
exit(1);
@@ -107,9 +101,8 @@ void __init setup_physmem(unsigned long start, unsigned long reserve_end,
*/
os_seek_file(physmem_fd, __pa(__syscall_stub_start));
os_write_file(physmem_fd, __syscall_stub_start, PAGE_SIZE);
- os_fsync_file(physmem_fd);
- memblock_add(__pa(start), len + highmem);
+ memblock_add(__pa(start), len);
memblock_reserve(__pa(start), reserve);
min_low_pfn = PFN_UP(__pa(reserve_end));
@@ -137,10 +130,6 @@ int phys_mapping(unsigned long phys, unsigned long long *offset_out)
region = region->next;
}
}
- else if (phys < __pa(end_iomem) + highmem) {
- fd = physmem_fd;
- *offset_out = phys - iomem_size;
- }
return fd;
}
@@ -149,6 +138,8 @@ EXPORT_SYMBOL(phys_mapping);
static int __init uml_mem_setup(char *line, int *add)
{
char *retptr;
+
+ *add = 0;
physmem_size = memparse(line,&retptr);
return 0;
}
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index be2856af6d4c..30bdc0a87dc8 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -43,7 +43,8 @@
* cares about its entry, so it's OK if another processor is modifying its
* entry.
*/
-struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { NULL } };
+struct task_struct *cpu_tasks[NR_CPUS];
+EXPORT_SYMBOL(cpu_tasks);
void free_stack(unsigned long stack, int order)
{
@@ -64,7 +65,7 @@ unsigned long alloc_stack(int order, int atomic)
static inline void set_current(struct task_struct *task)
{
- cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) { task });
+ cpu_tasks[task_thread_info(task)->cpu] = task;
}
struct task_struct *__switch_to(struct task_struct *from, struct task_struct *to)
@@ -116,7 +117,7 @@ void new_thread_handler(void)
* callback returns only if the kernel thread execs a process
*/
fn(arg);
- userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
+ userspace(&current->thread.regs.regs);
}
/* Called magically, see new_thread_handler above */
@@ -133,7 +134,7 @@ static void fork_handler(void)
current->thread.prev_sched = NULL;
- userspace(&current->thread.regs.regs, current_thread_info()->aux_fp_regs);
+ userspace(&current->thread.regs.regs);
}
int copy_thread(struct task_struct * p, const struct kernel_clone_args *args)
@@ -187,6 +188,13 @@ void initial_thread_cb(void (*proc)(void *), void *arg)
kmalloc_ok = save_kmalloc_ok;
}
+int arch_dup_task_struct(struct task_struct *dst,
+ struct task_struct *src)
+{
+ memcpy(dst, src, arch_task_struct_size);
+ return 0;
+}
+
void um_idle_sleep(void)
{
if (time_travel_mode != TT_MODE_OFF)
@@ -287,11 +295,3 @@ unsigned long __get_wchan(struct task_struct *p)
return 0;
}
-
-int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
-{
- int cpu = current_thread_info()->cpu;
-
- return save_i387_registers(userspace_pid[cpu], (unsigned long *) fpu);
-}
-
diff --git a/arch/um/kernel/skas/.gitignore b/arch/um/kernel/skas/.gitignore
new file mode 100644
index 000000000000..c3409ced0f38
--- /dev/null
+++ b/arch/um/kernel/skas/.gitignore
@@ -0,0 +1,2 @@
+stub_exe
+stub_exe.dbg
diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile
index 6f86d53e3d69..3384be42691f 100644
--- a/arch/um/kernel/skas/Makefile
+++ b/arch/um/kernel/skas/Makefile
@@ -3,14 +3,48 @@
# Copyright (C) 2002 - 2007 Jeff Dike (jdike@{addtoit,linux.intel}.com)
#
-obj-y := stub.o mmu.o process.o syscall.o uaccess.o
+obj-y := stub.o mmu.o process.o syscall.o uaccess.o \
+ stub_exe_embed.o
+
+# Stub executable
+
+stub_exe_objs-y := stub_exe.o
+
+stub_exe_objs := $(foreach F,$(stub_exe_objs-y),$(obj)/$F)
+
+# Object file containing the ELF executable
+$(obj)/stub_exe_embed.o: $(src)/stub_exe_embed.S $(obj)/stub_exe
+
+$(obj)/stub_exe.dbg: $(stub_exe_objs) FORCE
+ $(call if_changed,stub_exe)
+
+$(obj)/stub_exe: OBJCOPYFLAGS := -S
+$(obj)/stub_exe: $(obj)/stub_exe.dbg FORCE
+ $(call if_changed,objcopy)
+
+quiet_cmd_stub_exe = STUB_EXE $@
+ cmd_stub_exe = $(CC) -nostdlib -o $@ \
+ $(filter-out $(UM_GPROF_OPT) $(UM_GCOV_OPT),$(KBUILD_CFLAGS)) $(STUB_EXE_LDFLAGS) \
+ $(filter %.o,$^)
+
+STUB_EXE_LDFLAGS = -Wl,-n -static
+
+targets += stub_exe.dbg stub_exe $(stub_exe_objs-y)
+
+# end
# stub.o is in the stub, so it can't be built with profiling
# GCC hardened also auto-enables -fpic, but we need %ebx so it can't work ->
# disable it
CFLAGS_stub.o := $(CFLAGS_NO_HARDENING)
-UNPROFILE_OBJS := stub.o
+CFLAGS_stub_exe.o := $(CFLAGS_NO_HARDENING)
+
+# Clang will call memset() from __builtin_alloca() when stack variable
+# initialization is enabled, which is used in stub_exe.c.
+CFLAGS_stub_exe.o += $(call cc-option, -ftrivial-auto-var-init=uninitialized)
+
+UNPROFILE_OBJS := stub.o stub_exe.o
KCOV_INSTRUMENT := n
include $(srctree)/arch/um/scripts/Makefile.rules
diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c
index 886ed5e65674..0eb5a1d3ba70 100644
--- a/arch/um/kernel/skas/mmu.c
+++ b/arch/um/kernel/skas/mmu.c
@@ -40,35 +40,13 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm)
goto out_free;
}
- /*
- * Ensure the new MM is clean and nothing unwanted is mapped.
- *
- * TODO: We should clear the memory up to STUB_START to ensure there is
- * nothing mapped there, i.e. we (currently) have:
- *
- * |- user memory -|- unused -|- stub -|- unused -|
- * ^ TASK_SIZE ^ STUB_START
- *
- * Meaning we have two unused areas where we may still have valid
- * mappings from our internal clone(). That isn't really a problem as
- * userspace is not going to access them, but it is definitely not
- * correct.
- *
- * However, we are "lucky" and if rseq is configured, then on 32 bit
- * it will fall into the first empty range while on 64 bit it is going
- * to use an anonymous mapping in the second range. As such, things
- * continue to work for now as long as we don't start unmapping these
- * areas.
- *
- * Change this to STUB_START once we have a clean userspace.
- */
- unmap(new_id, 0, TASK_SIZE);
+ /* Ensure the new MM is clean and nothing unwanted is mapped */
+ unmap(new_id, 0, STUB_START);
return 0;
out_free:
- if (new_id->stack != 0)
- free_pages(new_id->stack, ilog2(STUB_DATA_PAGES));
+ free_pages(new_id->stack, ilog2(STUB_DATA_PAGES));
out:
return ret;
}
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 68657988c8d1..05dcdc057af9 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -22,15 +22,13 @@ static int __init start_kernel_proc(void *unused)
{
block_signals_trace();
- cpu_tasks[0].task = current;
-
start_kernel();
return 0;
}
extern int userspace_pid[];
-extern char cpu0_irqstack[];
+static char cpu0_irqstack[THREAD_SIZE] __aligned(THREAD_SIZE);
int __init start_uml(void)
{
diff --git a/arch/um/kernel/skas/stub.c b/arch/um/kernel/skas/stub.c
index 5d52ffa682dc..796fc266d3bb 100644
--- a/arch/um/kernel/skas/stub.c
+++ b/arch/um/kernel/skas/stub.c
@@ -35,16 +35,6 @@ static __always_inline int syscall_handler(struct stub_data *d)
return -1;
}
break;
- case STUB_SYSCALL_MPROTECT:
- res = stub_syscall3(__NR_mprotect,
- sc->mem.addr, sc->mem.length,
- sc->mem.prot);
- if (res) {
- d->err = res;
- d->syscall_data_len = i;
- return -1;
- }
- break;
default:
d->err = -95; /* EOPNOTSUPP */
d->syscall_data_len = i;
diff --git a/arch/um/kernel/skas/stub_exe.c b/arch/um/kernel/skas/stub_exe.c
new file mode 100644
index 000000000000..23c99b285e82
--- /dev/null
+++ b/arch/um/kernel/skas/stub_exe.c
@@ -0,0 +1,95 @@
+#include <sys/ptrace.h>
+#include <sys/prctl.h>
+#include <asm/unistd.h>
+#include <sysdep/stub.h>
+#include <stub-data.h>
+
+void _start(void);
+
+noinline static void real_init(void)
+{
+ struct stub_init_data init_data;
+ unsigned long res;
+ struct {
+ void *ss_sp;
+ int ss_flags;
+ size_t ss_size;
+ } stack = {
+ .ss_size = STUB_DATA_PAGES * UM_KERN_PAGE_SIZE,
+ };
+ struct {
+ void *sa_handler_;
+ unsigned long sa_flags;
+ void *sa_restorer;
+ unsigned long long sa_mask;
+ } sa = {
+ /* Need to set SA_RESTORER (but the handler never returns) */
+ .sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO | 0x04000000,
+ /* no need to mask any signals */
+ .sa_mask = 0,
+ };
+
+ /* set a nice name */
+ stub_syscall2(__NR_prctl, PR_SET_NAME, (unsigned long)"uml-userspace");
+
+ /* Make sure this process dies if the kernel dies */
+ stub_syscall2(__NR_prctl, PR_SET_PDEATHSIG, SIGKILL);
+
+ /* read information from STDIN and close it */
+ res = stub_syscall3(__NR_read, 0,
+ (unsigned long)&init_data, sizeof(init_data));
+ if (res != sizeof(init_data))
+ stub_syscall1(__NR_exit, 10);
+
+ stub_syscall1(__NR_close, 0);
+
+ /* map stub code + data */
+ res = stub_syscall6(STUB_MMAP_NR,
+ init_data.stub_start, UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_EXEC, MAP_FIXED | MAP_SHARED,
+ init_data.stub_code_fd, init_data.stub_code_offset);
+ if (res != init_data.stub_start)
+ stub_syscall1(__NR_exit, 11);
+
+ res = stub_syscall6(STUB_MMAP_NR,
+ init_data.stub_start + UM_KERN_PAGE_SIZE,
+ STUB_DATA_PAGES * UM_KERN_PAGE_SIZE,
+ PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED,
+ init_data.stub_data_fd, init_data.stub_data_offset);
+ if (res != init_data.stub_start + UM_KERN_PAGE_SIZE)
+ stub_syscall1(__NR_exit, 12);
+
+ /* setup signal stack inside stub data */
+ stack.ss_sp = (void *)init_data.stub_start + UM_KERN_PAGE_SIZE;
+ stub_syscall2(__NR_sigaltstack, (unsigned long)&stack, 0);
+
+ /* register SIGSEGV handler */
+ sa.sa_handler_ = (void *) init_data.segv_handler;
+ res = stub_syscall4(__NR_rt_sigaction, SIGSEGV, (unsigned long)&sa, 0,
+ sizeof(sa.sa_mask));
+ if (res != 0)
+ stub_syscall1(__NR_exit, 13);
+
+ stub_syscall4(__NR_ptrace, PTRACE_TRACEME, 0, 0, 0);
+
+ stub_syscall2(__NR_kill, stub_syscall0(__NR_getpid), SIGSTOP);
+
+ stub_syscall1(__NR_exit, 14);
+
+ __builtin_unreachable();
+}
+
+__attribute__((naked)) void _start(void)
+{
+ /*
+ * Since the stack after exec() starts at the top-most address,
+ * but that's exactly where we also want to map the stub data
+ * and code, this must:
+ * - push the stack by 1 code and STUB_DATA_PAGES data pages
+ * - call real_init()
+ * This way, real_init() can use the stack normally, while the
+ * original stack further down (higher address) will become
+ * inaccessible after the mmap() calls above.
+ */
+ stub_start(real_init);
+}
diff --git a/arch/um/kernel/skas/stub_exe_embed.S b/arch/um/kernel/skas/stub_exe_embed.S
new file mode 100644
index 000000000000..6d8914fbe8f1
--- /dev/null
+++ b/arch/um/kernel/skas/stub_exe_embed.S
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#include <linux/init.h>
+#include <linux/linkage.h>
+
+__INITDATA
+
+SYM_DATA_START(stub_exe_start)
+ .incbin "arch/um/kernel/skas/stub_exe"
+SYM_DATA_END_LABEL(stub_exe_start, SYM_L_GLOBAL, stub_exe_end)
+
+__FINIT
diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c
index 4bb8622dc512..13ee5666668d 100644
--- a/arch/um/kernel/sysrq.c
+++ b/arch/um/kernel/sysrq.c
@@ -32,12 +32,6 @@ void show_stack(struct task_struct *task, unsigned long *stack,
struct pt_regs *segv_regs = current->thread.segv_regs;
int i;
- if (!segv_regs && os_is_signal_stack()) {
- pr_err("Received SIGSEGV in SIGSEGV handler,"
- " aborting stack trace!\n");
- return;
- }
-
if (!stack)
stack = get_stack_pointer(task, segv_regs);
@@ -52,5 +46,5 @@ void show_stack(struct task_struct *task, unsigned long *stack,
}
printk("%sCall Trace:\n", loglvl);
- dump_trace(current, &stackops, (void *)loglvl);
+ dump_trace(task ?: current, &stackops, (void *)loglvl);
}
diff --git a/arch/um/kernel/time.c b/arch/um/kernel/time.c
index 29b27b90581f..1394568c0210 100644
--- a/arch/um/kernel/time.c
+++ b/arch/um/kernel/time.c
@@ -25,6 +25,8 @@
#include <shared/init.h>
#ifdef CONFIG_UML_TIME_TRAVEL_SUPPORT
+#include <linux/sched/clock.h>
+
enum time_travel_mode time_travel_mode;
EXPORT_SYMBOL_GPL(time_travel_mode);
@@ -47,6 +49,15 @@ static u16 time_travel_shm_id;
static struct um_timetravel_schedshm *time_travel_shm;
static union um_timetravel_schedshm_client *time_travel_shm_client;
+unsigned long tt_extra_sched_jiffies;
+
+notrace unsigned long long sched_clock(void)
+{
+ return (unsigned long long)(jiffies - INITIAL_JIFFIES +
+ tt_extra_sched_jiffies)
+ * (NSEC_PER_SEC / HZ);
+}
+
static void time_travel_set_time(unsigned long long ns)
{
if (unlikely(ns < time_travel_time))
@@ -443,6 +454,11 @@ static void time_travel_periodic_timer(struct time_travel_event *e)
{
time_travel_add_event(&time_travel_timer_event,
time_travel_time + time_travel_timer_interval);
+
+ /* clock tick; decrease extra jiffies by keeping sched_clock constant */
+ if (tt_extra_sched_jiffies > 0)
+ tt_extra_sched_jiffies -= 1;
+
deliver_alarm();
}
@@ -594,6 +610,10 @@ EXPORT_SYMBOL_GPL(time_travel_add_irq_event);
static void time_travel_oneshot_timer(struct time_travel_event *e)
{
+ /* clock tick; decrease extra jiffies by keeping sched_clock constant */
+ if (tt_extra_sched_jiffies > 0)
+ tt_extra_sched_jiffies -= 1;
+
deliver_alarm();
}
diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c
index 548af31d4111..cf7e0d4407f2 100644
--- a/arch/um/kernel/tlb.c
+++ b/arch/um/kernel/tlb.c
@@ -23,9 +23,6 @@ struct vm_ops {
int phys_fd, unsigned long long offset);
int (*unmap)(struct mm_id *mm_idp,
unsigned long virt, unsigned long len);
- int (*mprotect)(struct mm_id *mm_idp,
- unsigned long virt, unsigned long len,
- unsigned int prot);
};
static int kern_map(struct mm_id *mm_idp,
@@ -44,15 +41,6 @@ static int kern_unmap(struct mm_id *mm_idp,
return os_unmap_memory((void *)virt, len);
}
-static int kern_mprotect(struct mm_id *mm_idp,
- unsigned long virt, unsigned long len,
- unsigned int prot)
-{
- return os_protect_memory((void *)virt, len,
- prot & UM_PROT_READ, prot & UM_PROT_WRITE,
- 1);
-}
-
void report_enomem(void)
{
printk(KERN_ERR "UML ran out of memory on the host side! "
@@ -65,33 +53,37 @@ static inline int update_pte_range(pmd_t *pmd, unsigned long addr,
struct vm_ops *ops)
{
pte_t *pte;
- int r, w, x, prot, ret = 0;
+ int ret = 0;
pte = pte_offset_kernel(pmd, addr);
do {
- r = pte_read(*pte);
- w = pte_write(*pte);
- x = pte_exec(*pte);
- if (!pte_young(*pte)) {
- r = 0;
- w = 0;
- } else if (!pte_dirty(*pte))
- w = 0;
-
- prot = ((r ? UM_PROT_READ : 0) | (w ? UM_PROT_WRITE : 0) |
- (x ? UM_PROT_EXEC : 0));
- if (pte_newpage(*pte)) {
- if (pte_present(*pte)) {
- __u64 offset;
- unsigned long phys = pte_val(*pte) & PAGE_MASK;
- int fd = phys_mapping(phys, &offset);
-
- ret = ops->mmap(ops->mm_idp, addr, PAGE_SIZE,
- prot, fd, offset);
- } else
- ret = ops->unmap(ops->mm_idp, addr, PAGE_SIZE);
- } else if (pte_newprot(*pte))
- ret = ops->mprotect(ops->mm_idp, addr, PAGE_SIZE, prot);
+ if (!pte_needsync(*pte))
+ continue;
+
+ if (pte_present(*pte)) {
+ __u64 offset;
+ unsigned long phys = pte_val(*pte) & PAGE_MASK;
+ int fd = phys_mapping(phys, &offset);
+ int r, w, x, prot;
+
+ r = pte_read(*pte);
+ w = pte_write(*pte);
+ x = pte_exec(*pte);
+ if (!pte_young(*pte)) {
+ r = 0;
+ w = 0;
+ } else if (!pte_dirty(*pte))
+ w = 0;
+
+ prot = (r ? UM_PROT_READ : 0) |
+ (w ? UM_PROT_WRITE : 0) |
+ (x ? UM_PROT_EXEC : 0);
+
+ ret = ops->mmap(ops->mm_idp, addr, PAGE_SIZE,
+ prot, fd, offset);
+ } else
+ ret = ops->unmap(ops->mm_idp, addr, PAGE_SIZE);
+
*pte = pte_mkuptodate(*pte);
} while (pte++, addr += PAGE_SIZE, ((addr < end) && !ret));
return ret;
@@ -109,7 +101,7 @@ static inline int update_pmd_range(pud_t *pud, unsigned long addr,
do {
next = pmd_addr_end(addr, end);
if (!pmd_present(*pmd)) {
- if (pmd_newpage(*pmd)) {
+ if (pmd_needsync(*pmd)) {
ret = ops->unmap(ops->mm_idp, addr,
next - addr);
pmd_mkuptodate(*pmd);
@@ -132,7 +124,7 @@ static inline int update_pud_range(p4d_t *p4d, unsigned long addr,
do {
next = pud_addr_end(addr, end);
if (!pud_present(*pud)) {
- if (pud_newpage(*pud)) {
+ if (pud_needsync(*pud)) {
ret = ops->unmap(ops->mm_idp, addr,
next - addr);
pud_mkuptodate(*pud);
@@ -155,7 +147,7 @@ static inline int update_p4d_range(pgd_t *pgd, unsigned long addr,
do {
next = p4d_addr_end(addr, end);
if (!p4d_present(*p4d)) {
- if (p4d_newpage(*p4d)) {
+ if (p4d_needsync(*p4d)) {
ret = ops->unmap(ops->mm_idp, addr,
next - addr);
p4d_mkuptodate(*p4d);
@@ -180,18 +172,16 @@ int um_tlb_sync(struct mm_struct *mm)
if (mm == &init_mm) {
ops.mmap = kern_map;
ops.unmap = kern_unmap;
- ops.mprotect = kern_mprotect;
} else {
ops.mmap = map;
ops.unmap = unmap;
- ops.mprotect = protect;
}
pgd = pgd_offset(mm, addr);
do {
next = pgd_addr_end(addr, mm->context.sync_tlb_range_to);
if (!pgd_present(*pgd)) {
- if (pgd_newpage(*pgd)) {
+ if (pgd_needsync(*pgd)) {
ret = ops.unmap(ops.mm_idp, addr,
next - addr);
pgd_mkuptodate(*pgd);
diff --git a/arch/um/kernel/trap.c b/arch/um/kernel/trap.c
index 97c8df9c4401..cdaee3e94273 100644
--- a/arch/um/kernel/trap.c
+++ b/arch/um/kernel/trap.c
@@ -201,7 +201,6 @@ void segv_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
struct uml_pt_regs *regs)
{
- jmp_buf *catcher;
int si_code;
int err;
int is_write = FAULT_WRITE(fi);
@@ -246,15 +245,8 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user,
address = 0;
}
- catcher = current->thread.fault_catcher;
if (!err)
goto out;
- else if (catcher != NULL) {
- current->thread.fault_addr = (void *) address;
- UML_LONGJMP(catcher, 1);
- }
- else if (current->thread.fault_addr != NULL)
- panic("fault_addr set but no fault catcher");
else if (!is_user && arch_fixup(ip, regs))
goto out;
@@ -310,14 +302,6 @@ void relay_signal(int sig, struct siginfo *si, struct uml_pt_regs *regs)
}
}
-void bus_handler(int sig, struct siginfo *si, struct uml_pt_regs *regs)
-{
- if (current->thread.fault_catcher != NULL)
- UML_LONGJMP(current->thread.fault_catcher, 1);
- else
- relay_signal(sig, si, regs);
-}
-
void winch(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs)
{
do_IRQ(WINCH_IRQ, regs);
diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
index e8e8b54b3037..8037a967225d 100644
--- a/arch/um/kernel/um_arch.c
+++ b/arch/um/kernel/um_arch.c
@@ -65,9 +65,6 @@ struct cpuinfo_um boot_cpu_data = {
EXPORT_SYMBOL(boot_cpu_data);
-union thread_union cpu0_irqstack
- __section(".data..init_irqstack") =
- { .thread_info = INIT_THREAD_INFO(init_task) };
/* Changed in setup_arch, which is called in early boot */
static char host_info[(__NEW_UTS_LEN + 1) * 5];
@@ -131,7 +128,7 @@ static int have_root __initdata;
static int have_console __initdata;
/* Set in uml_mem_setup and modified in linux_main */
-long long physmem_size = 64 * 1024 * 1024;
+unsigned long long physmem_size = 64 * 1024 * 1024;
EXPORT_SYMBOL(physmem_size);
static const char *usage_string =
@@ -167,19 +164,6 @@ __uml_setup("root=", uml_root_setup,
" root=/dev/ubd5\n\n"
);
-static int __init no_skas_debug_setup(char *line, int *add)
-{
- os_warn("'debug' is not necessary to gdb UML in skas mode - run\n");
- os_warn("'gdb linux'\n");
-
- return 0;
-}
-
-__uml_setup("debug", no_skas_debug_setup,
-"debug\n"
-" this flag is not needed to run gdb on UML in skas mode\n\n"
-);
-
static int __init uml_console_setup(char *line, int *add)
{
have_console = 1;
@@ -257,6 +241,8 @@ static struct notifier_block panic_exit_notifier = {
void uml_finishsetup(void)
{
+ cpu_tasks[0] = &init_task;
+
atomic_notifier_chain_register(&panic_notifier_list,
&panic_exit_notifier);
@@ -302,7 +288,24 @@ static void parse_cache_line(char *line)
}
}
-int __init linux_main(int argc, char **argv)
+static unsigned long get_top_address(char **envp)
+{
+ unsigned long top_addr = (unsigned long) &top_addr;
+ int i;
+
+ /* The earliest variable should be after the program name in ELF */
+ for (i = 0; envp[i]; i++) {
+ if ((unsigned long) envp[i] > top_addr)
+ top_addr = (unsigned long) envp[i];
+ }
+
+ top_addr &= ~(UM_KERN_PAGE_SIZE - 1);
+ top_addr += UM_KERN_PAGE_SIZE;
+
+ return top_addr;
+}
+
+int __init linux_main(int argc, char **argv, char **envp)
{
unsigned long avail, diff;
unsigned long virtmem_size, max_physmem;
@@ -324,20 +327,23 @@ int __init linux_main(int argc, char **argv)
if (have_console == 0)
add_arg(DEFAULT_COMMAND_LINE_CONSOLE);
- host_task_size = os_get_top_address();
- /* reserve a few pages for the stubs (taking care of data alignment) */
- /* align the data portion */
- BUILD_BUG_ON(!is_power_of_2(STUB_DATA_PAGES));
- stub_start = (host_task_size - 1) & ~(STUB_DATA_PAGES * PAGE_SIZE - 1);
+ host_task_size = get_top_address(envp);
+ /* reserve a few pages for the stubs */
+ stub_start = host_task_size - STUB_DATA_PAGES * PAGE_SIZE;
/* another page for the code portion */
stub_start -= PAGE_SIZE;
host_task_size = stub_start;
+ /* Limit TASK_SIZE to what is addressable by the page table */
+ task_size = host_task_size;
+ if (task_size > (unsigned long long) PTRS_PER_PGD * PGDIR_SIZE)
+ task_size = PTRS_PER_PGD * PGDIR_SIZE;
+
/*
* TASK_SIZE needs to be PGDIR_SIZE aligned or else exit_mmap craps
* out
*/
- task_size = host_task_size & PGDIR_MASK;
+ task_size = task_size & PGDIR_MASK;
/* OS sanity checks that need to happen before the kernel runs */
os_early_checks();
@@ -366,18 +372,15 @@ int __init linux_main(int argc, char **argv)
setup_machinename(init_utsname()->machine);
- highmem = 0;
+ physmem_size = (physmem_size + PAGE_SIZE - 1) & PAGE_MASK;
iomem_size = (iomem_size + PAGE_SIZE - 1) & PAGE_MASK;
+
max_physmem = TASK_SIZE - uml_physmem - iomem_size - MIN_VMALLOC;
- /*
- * Zones have to begin on a 1 << MAX_PAGE_ORDER page boundary,
- * so this makes sure that's true for highmem
- */
- max_physmem &= ~((1 << (PAGE_SHIFT + MAX_PAGE_ORDER)) - 1);
if (physmem_size + iomem_size > max_physmem) {
- highmem = physmem_size + iomem_size - max_physmem;
- physmem_size -= highmem;
+ physmem_size = max_physmem - iomem_size;
+ os_info("Physical memory size shrunk to %llu bytes\n",
+ physmem_size);
}
high_physmem = uml_physmem + physmem_size;
@@ -398,6 +401,8 @@ int __init linux_main(int argc, char **argv)
os_info("Kernel virtual memory size shrunk to %lu bytes\n",
virtmem_size);
+ arch_task_struct_size = sizeof(struct task_struct) + host_fp_size;
+
os_flush_stdout();
return start_uml();
@@ -412,9 +417,9 @@ void __init setup_arch(char **cmdline_p)
{
u8 rng_seed[32];
- stack_protections((unsigned long) &init_thread_info);
- setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
- mem_total_pages(physmem_size, iomem_size, highmem);
+ stack_protections((unsigned long) init_task.stack);
+ setup_physmem(uml_physmem, uml_reserved, physmem_size);
+ mem_total_pages(physmem_size, iomem_size);
uml_dtb_init();
read_initrd();
diff --git a/arch/um/kernel/uml.lds.S b/arch/um/kernel/uml.lds.S
index 5c92d58a78e8..a409d4b66114 100644
--- a/arch/um/kernel/uml.lds.S
+++ b/arch/um/kernel/uml.lds.S
@@ -77,8 +77,6 @@ SECTIONS
.data :
{
INIT_TASK_DATA(KERNEL_STACK_SIZE)
- . = ALIGN(KERNEL_STACK_SIZE);
- *(.data..init_irqstack)
DATA_DATA
*(.gnu.linkonce.d*)
CONSTRUCTORS
diff --git a/arch/um/os-Linux/Makefile b/arch/um/os-Linux/Makefile
index 544e0b344c75..049dfa5bc9c6 100644
--- a/arch/um/os-Linux/Makefile
+++ b/arch/um/os-Linux/Makefile
@@ -12,6 +12,8 @@ obj-y = execvp.o file.o helper.o irq.o main.o mem.o process.o \
CFLAGS_signal.o += -Wframe-larger-than=4096
+CFLAGS_main.o += -Wno-frame-larger-than
+
obj-$(CONFIG_ARCH_REUSE_HOST_VSYSCALL_AREA) += elf_aux.o
USER_OBJS := $(user-objs-y) elf_aux.o execvp.o file.o helper.o irq.o \
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index f1d03cf3957f..a0d01c68ce3e 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -255,12 +255,6 @@ void os_close_file(int fd)
{
close(fd);
}
-int os_fsync_file(int fd)
-{
- if (fsync(fd) < 0)
- return -errno;
- return 0;
-}
int os_seek_file(int fd, unsigned long long offset)
{
diff --git a/arch/um/os-Linux/main.c b/arch/um/os-Linux/main.c
index f98ff79cdbf7..0afcdeb8995b 100644
--- a/arch/um/os-Linux/main.c
+++ b/arch/um/os-Linux/main.c
@@ -11,6 +11,7 @@
#include <signal.h>
#include <string.h>
#include <sys/resource.h>
+#include <sys/personality.h>
#include <as-layout.h>
#include <init.h>
#include <kern_util.h>
@@ -108,6 +109,21 @@ int __init main(int argc, char **argv, char **envp)
char **new_argv;
int ret, i, err;
+ /* Disable randomization and re-exec if it was changed successfully */
+ ret = personality(PER_LINUX | ADDR_NO_RANDOMIZE);
+ if (ret >= 0 && (ret & (PER_LINUX | ADDR_NO_RANDOMIZE)) !=
+ (PER_LINUX | ADDR_NO_RANDOMIZE)) {
+ char buf[4096] = {};
+ ssize_t ret;
+
+ ret = readlink("/proc/self/exe", buf, sizeof(buf));
+ if (ret < 0 || ret >= sizeof(buf)) {
+ perror("readlink failure");
+ exit(1);
+ }
+ execve(buf, argv, envp);
+ }
+
set_stklim();
setup_env_path();
@@ -140,7 +156,7 @@ int __init main(int argc, char **argv, char **envp)
#endif
change_sig(SIGPIPE, 0);
- ret = linux_main(argc, argv);
+ ret = linux_main(argc, argv, envp);
/*
* Disable SIGPROF - I have no idea why libc doesn't do this or turn
@@ -182,6 +198,7 @@ int __init main(int argc, char **argv, char **envp)
}
extern void *__real_malloc(int);
+extern void __real_free(void *);
/* workaround for -Wmissing-prototypes warnings */
void *__wrap_malloc(int size);
@@ -219,10 +236,6 @@ void *__wrap_calloc(int n, int size)
return ptr;
}
-extern void __real_free(void *);
-
-extern unsigned long high_physmem;
-
void __wrap_free(void *ptr)
{
unsigned long addr = (unsigned long) ptr;
diff --git a/arch/um/os-Linux/mem.c b/arch/um/os-Linux/mem.c
index cf44d386f23c..72f302f4d197 100644
--- a/arch/um/os-Linux/mem.c
+++ b/arch/um/os-Linux/mem.c
@@ -39,10 +39,22 @@ void kasan_map_memory(void *start, size_t len)
strerror(errno));
exit(1);
}
+
+ if (madvise(start, len, MADV_DONTDUMP)) {
+ os_info("Couldn't set MAD_DONTDUMP on shadow memory: %s\n.",
+ strerror(errno));
+ exit(1);
+ }
+
+ if (madvise(start, len, MADV_DONTFORK)) {
+ os_info("Couldn't set MADV_DONTFORK on shadow memory: %s\n.",
+ strerror(errno));
+ exit(1);
+ }
}
/* Set by make_tempfile() during early boot. */
-static char *tempdir = NULL;
+char *tempdir = NULL;
/* Check if dir is on tmpfs. Return 0 if yes, -1 if no or error. */
static int __init check_tmpfs(const char *dir)
diff --git a/arch/um/os-Linux/process.c b/arch/um/os-Linux/process.c
index e52dd37ddadc..9f086f939420 100644
--- a/arch/um/os-Linux/process.c
+++ b/arch/um/os-Linux/process.c
@@ -12,94 +12,18 @@
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/ptrace.h>
+#include <sys/prctl.h>
#include <sys/wait.h>
#include <asm/unistd.h>
#include <init.h>
#include <longjmp.h>
#include <os.h>
-#define ARBITRARY_ADDR -1
-#define FAILURE_PID -1
-
-#define STAT_PATH_LEN sizeof("/proc/#######/stat\0")
-#define COMM_SCANF "%*[^)])"
-
-unsigned long os_process_pc(int pid)
-{
- char proc_stat[STAT_PATH_LEN], buf[256];
- unsigned long pc = ARBITRARY_ADDR;
- int fd, err;
-
- sprintf(proc_stat, "/proc/%d/stat", pid);
- fd = open(proc_stat, O_RDONLY, 0);
- if (fd < 0) {
- printk(UM_KERN_ERR "os_process_pc - couldn't open '%s', "
- "errno = %d\n", proc_stat, errno);
- goto out;
- }
- CATCH_EINTR(err = read(fd, buf, sizeof(buf)));
- if (err < 0) {
- printk(UM_KERN_ERR "os_process_pc - couldn't read '%s', "
- "err = %d\n", proc_stat, errno);
- goto out_close;
- }
- os_close_file(fd);
- pc = ARBITRARY_ADDR;
- if (sscanf(buf, "%*d " COMM_SCANF " %*c %*d %*d %*d %*d %*d %*d %*d "
- "%*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d %*d "
- "%*d %*d %*d %*d %*d %lu", &pc) != 1)
- printk(UM_KERN_ERR "os_process_pc - couldn't find pc in '%s'\n",
- buf);
- out_close:
- close(fd);
- out:
- return pc;
-}
-
-int os_process_parent(int pid)
-{
- char stat[STAT_PATH_LEN];
- char data[256];
- int parent = FAILURE_PID, n, fd;
-
- if (pid == -1)
- return parent;
-
- snprintf(stat, sizeof(stat), "/proc/%d/stat", pid);
- fd = open(stat, O_RDONLY, 0);
- if (fd < 0) {
- printk(UM_KERN_ERR "Couldn't open '%s', errno = %d\n", stat,
- errno);
- return parent;
- }
-
- CATCH_EINTR(n = read(fd, data, sizeof(data)));
- close(fd);
-
- if (n < 0) {
- printk(UM_KERN_ERR "Couldn't read '%s', errno = %d\n", stat,
- errno);
- return parent;
- }
-
- parent = FAILURE_PID;
- n = sscanf(data, "%*d " COMM_SCANF " %*c %d", &parent);
- if (n != 1)
- printk(UM_KERN_ERR "Failed to scan '%s'\n", data);
-
- return parent;
-}
-
void os_alarm_process(int pid)
{
kill(pid, SIGALRM);
}
-void os_stop_process(int pid)
-{
- kill(pid, SIGSTOP);
-}
-
void os_kill_process(int pid, int reap_child)
{
kill(pid, SIGKILL);
@@ -130,11 +54,6 @@ int os_getpid(void)
return syscall(__NR_getpid);
}
-int os_getpgrp(void)
-{
- return getpgrp();
-}
-
int os_map_memory(void *virt, int fd, unsigned long long off, unsigned long len,
int r, int w, int x)
{
@@ -285,3 +204,8 @@ void init_new_thread_signals(void)
set_handler(SIGIO);
signal(SIGWINCH, SIG_IGN);
}
+
+void os_set_pdeathsig(void)
+{
+ prctl(PR_SET_PDEATHSIG, SIGKILL);
+}
diff --git a/arch/um/os-Linux/registers.c b/arch/um/os-Linux/registers.c
index bd80b921add0..d7ca148807b2 100644
--- a/arch/um/os-Linux/registers.c
+++ b/arch/um/os-Linux/registers.c
@@ -10,11 +10,12 @@
#include <sysdep/ptrace.h>
#include <sysdep/ptrace_user.h>
#include <registers.h>
+#include <stdlib.h>
/* This is set once at boot time and not changed thereafter */
static unsigned long exec_regs[MAX_REG_NR];
-static unsigned long exec_fp_regs[FP_SIZE];
+static unsigned long *exec_fp_regs;
int init_pid_registers(int pid)
{
@@ -24,7 +25,11 @@ int init_pid_registers(int pid)
if (err < 0)
return -errno;
- arch_init_registers(pid);
+ err = arch_init_registers(pid);
+ if (err < 0)
+ return err;
+
+ exec_fp_regs = malloc(host_fp_size);
get_fp_registers(pid, exec_fp_regs);
return 0;
}
@@ -34,5 +39,5 @@ void get_safe_registers(unsigned long *regs, unsigned long *fp_regs)
memcpy(regs, exec_regs, sizeof(exec_regs));
if (fp_regs)
- memcpy(fp_regs, exec_fp_regs, sizeof(exec_fp_regs));
+ memcpy(fp_regs, exec_fp_regs, host_fp_size);
}
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 9e71794839e8..9aac8def4d63 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -55,6 +55,7 @@ static int write_sigio_thread(void *unused)
int i, n, respond_fd;
char c;
+ os_set_pdeathsig();
os_fix_helper_signals();
fds = &current_poll;
while (1) {
diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
index b11ed66c8bb0..9ea7269ffb77 100644
--- a/arch/um/os-Linux/signal.c
+++ b/arch/um/os-Linux/signal.c
@@ -26,7 +26,7 @@ void (*sig_info[NSIG])(int, struct siginfo *, struct uml_pt_regs *) = {
[SIGFPE] = relay_signal,
[SIGILL] = relay_signal,
[SIGWINCH] = winch,
- [SIGBUS] = bus_handler,
+ [SIGBUS] = relay_signal,
[SIGSEGV] = segv_handler,
[SIGIO] = sigio_handler,
};
@@ -65,7 +65,7 @@ static void sig_handler_common(int sig, struct siginfo *si, mcontext_t *mc)
#define SIGALRM_MASK (1 << SIGALRM_BIT)
int signals_enabled;
-#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
+#if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT)
static int signals_blocked, signals_blocked_pending;
#endif
static unsigned int signals_pending;
@@ -75,7 +75,7 @@ static void sig_handler(int sig, struct siginfo *si, mcontext_t *mc)
{
int enabled = signals_enabled;
-#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
+#if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT)
if ((signals_blocked ||
__atomic_load_n(&signals_blocked_pending, __ATOMIC_SEQ_CST)) &&
(sig == SIGIO)) {
@@ -190,43 +190,8 @@ static void hard_handler(int sig, siginfo_t *si, void *p)
{
ucontext_t *uc = p;
mcontext_t *mc = &uc->uc_mcontext;
- unsigned long pending = 1UL << sig;
- do {
- int nested, bail;
-
- /*
- * pending comes back with one bit set for each
- * interrupt that arrived while setting up the stack,
- * plus a bit for this interrupt, plus the zero bit is
- * set if this is a nested interrupt.
- * If bail is true, then we interrupted another
- * handler setting up the stack. In this case, we
- * have to return, and the upper handler will deal
- * with this interrupt.
- */
- bail = to_irq_stack(&pending);
- if (bail)
- return;
-
- nested = pending & 1;
- pending &= ~1;
-
- while ((sig = ffs(pending)) != 0){
- sig--;
- pending &= ~(1 << sig);
- (*handlers[sig])(sig, (struct siginfo *)si, mc);
- }
-
- /*
- * Again, pending comes back with a mask of signals
- * that arrived while tearing down the stack. If this
- * is non-zero, we just go back, set up the stack
- * again, and handle the new interrupts.
- */
- if (!nested)
- pending = from_irq_stack(nested);
- } while (pending);
+ (*handlers[sig])(sig, (struct siginfo *)si, mc);
}
void set_handler(int sig)
@@ -297,7 +262,7 @@ void unblock_signals(void)
return;
signals_enabled = 1;
-#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
+#if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT)
deliver_time_travel_irqs();
#endif
@@ -389,7 +354,7 @@ int um_set_signals_trace(int enable)
return ret;
}
-#ifdef UML_CONFIG_UML_TIME_TRAVEL_SUPPORT
+#if IS_ENABLED(CONFIG_UML_TIME_TRAVEL_SUPPORT)
void mark_sigio_pending(void)
{
/*
@@ -487,11 +452,3 @@ void unblock_signals_hard(void)
unblocking = false;
}
#endif
-
-int os_is_signal_stack(void)
-{
- stack_t ss;
- sigaltstack(NULL, &ss);
-
- return ss.ss_flags & SS_ONSTACK;
-}
diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c
index 9a13ac23c606..d7f1814b0e5a 100644
--- a/arch/um/os-Linux/skas/mem.c
+++ b/arch/um/os-Linux/skas/mem.c
@@ -217,24 +217,3 @@ int unmap(struct mm_id *mm_idp, unsigned long addr, unsigned long len)
return 0;
}
-
-int protect(struct mm_id *mm_idp, unsigned long addr, unsigned long len,
- unsigned int prot)
-{
- struct stub_syscall *sc;
-
- /* Compress with previous syscall if that is possible */
- sc = syscall_stub_get_previous(mm_idp, STUB_SYSCALL_MPROTECT, addr);
- if (sc && sc->mem.prot == prot) {
- sc->mem.length += len;
- return 0;
- }
-
- sc = syscall_stub_alloc(mm_idp);
- sc->syscall = STUB_SYSCALL_MPROTECT;
- sc->mem.addr = addr;
- sc->mem.length = len;
- sc->mem.prot = prot;
-
- return 0;
-}
diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c
index b6f656bcffb1..f683cfc9e51a 100644
--- a/arch/um/os-Linux/skas/process.c
+++ b/arch/um/os-Linux/skas/process.c
@@ -10,8 +10,11 @@
#include <sched.h>
#include <errno.h>
#include <string.h>
+#include <fcntl.h>
+#include <mem_user.h>
#include <sys/mman.h>
#include <sys/wait.h>
+#include <sys/stat.h>
#include <asm/unistd.h>
#include <as-layout.h>
#include <init.h>
@@ -141,16 +144,10 @@ bad_wait:
extern unsigned long current_stub_stack(void);
-static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux_fp_regs)
+static void get_skas_faultinfo(int pid, struct faultinfo *fi)
{
int err;
- err = get_fp_registers(pid, aux_fp_regs);
- if (err < 0) {
- printk(UM_KERN_ERR "save_fp_registers returned %d\n",
- err);
- fatal_sigsegv();
- }
err = ptrace(PTRACE_CONT, pid, 0, SIGSEGV);
if (err) {
printk(UM_KERN_ERR "Failed to continue stub, pid = %d, "
@@ -164,18 +161,11 @@ static void get_skas_faultinfo(int pid, struct faultinfo *fi, unsigned long *aux
* the stub stack page. We just have to copy it.
*/
memcpy(fi, (void *)current_stub_stack(), sizeof(*fi));
-
- err = put_fp_registers(pid, aux_fp_regs);
- if (err < 0) {
- printk(UM_KERN_ERR "put_fp_registers returned %d\n",
- err);
- fatal_sigsegv();
- }
}
-static void handle_segv(int pid, struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
+static void handle_segv(int pid, struct uml_pt_regs *regs)
{
- get_skas_faultinfo(pid, &regs->faultinfo, aux_fp_regs);
+ get_skas_faultinfo(pid, &regs->faultinfo);
segv(regs->faultinfo, 0, 1, NULL);
}
@@ -189,69 +179,131 @@ static void handle_trap(int pid, struct uml_pt_regs *regs)
extern char __syscall_stub_start[];
-/**
- * userspace_tramp() - userspace trampoline
- * @stack: pointer to the new userspace stack page
- *
- * The userspace trampoline is used to setup a new userspace process in start_userspace() after it was clone()'ed.
- * This function will run on a temporary stack page.
- * It ptrace()'es itself, then
- * Two pages are mapped into the userspace address space:
- * - STUB_CODE (with EXEC), which contains the skas stub code
- * - STUB_DATA (with R/W), which contains a data page that is used to transfer certain data between the UML userspace process and the UML kernel.
- * Also for the userspace process a SIGSEGV handler is installed to catch pagefaults in the userspace process.
- * And last the process stops itself to give control to the UML kernel for this userspace process.
- *
- * Return: Always zero, otherwise the current userspace process is ended with non null exit() call
- */
+static int stub_exe_fd;
+
static int userspace_tramp(void *stack)
{
- struct sigaction sa;
- void *addr;
- int fd;
+ char *const argv[] = { "uml-userspace", NULL };
+ int pipe_fds[2];
unsigned long long offset;
- unsigned long segv_handler = STUB_CODE +
- (unsigned long) stub_segv_handler -
- (unsigned long) __syscall_stub_start;
-
- ptrace(PTRACE_TRACEME, 0, 0, 0);
-
- signal(SIGTERM, SIG_DFL);
- signal(SIGWINCH, SIG_IGN);
-
- fd = phys_mapping(uml_to_phys(__syscall_stub_start), &offset);
- addr = mmap64((void *) STUB_CODE, UM_KERN_PAGE_SIZE,
- PROT_EXEC, MAP_FIXED | MAP_PRIVATE, fd, offset);
- if (addr == MAP_FAILED) {
- os_info("mapping mmap stub at 0x%lx failed, errno = %d\n",
- STUB_CODE, errno);
- exit(1);
+ struct stub_init_data init_data = {
+ .stub_start = STUB_START,
+ .segv_handler = STUB_CODE +
+ (unsigned long) stub_segv_handler -
+ (unsigned long) __syscall_stub_start,
+ };
+ struct iomem_region *iomem;
+ int ret;
+
+ init_data.stub_code_fd = phys_mapping(uml_to_phys(__syscall_stub_start),
+ &offset);
+ init_data.stub_code_offset = MMAP_OFFSET(offset);
+
+ init_data.stub_data_fd = phys_mapping(uml_to_phys(stack), &offset);
+ init_data.stub_data_offset = MMAP_OFFSET(offset);
+
+ /* Set CLOEXEC on all FDs and then unset on all memory related FDs */
+ close_range(0, ~0U, CLOSE_RANGE_CLOEXEC);
+
+ fcntl(init_data.stub_data_fd, F_SETFD, 0);
+ for (iomem = iomem_regions; iomem; iomem = iomem->next)
+ fcntl(iomem->fd, F_SETFD, 0);
+
+ /* Create a pipe for init_data (no CLOEXEC) and dup2 to STDIN */
+ if (pipe(pipe_fds))
+ exit(2);
+
+ if (dup2(pipe_fds[0], 0) < 0)
+ exit(3);
+ close(pipe_fds[0]);
+
+ /* Write init_data and close write side */
+ ret = write(pipe_fds[1], &init_data, sizeof(init_data));
+ close(pipe_fds[1]);
+
+ if (ret != sizeof(init_data))
+ exit(4);
+
+ execveat(stub_exe_fd, "", argv, NULL, AT_EMPTY_PATH);
+
+ exit(5);
+}
+
+extern char stub_exe_start[];
+extern char stub_exe_end[];
+
+extern char *tempdir;
+
+#define STUB_EXE_NAME_TEMPLATE "/uml-userspace-XXXXXX"
+
+#ifndef MFD_EXEC
+#define MFD_EXEC 0x0010U
+#endif
+
+static int __init init_stub_exe_fd(void)
+{
+ size_t written = 0;
+ char *tmpfile = NULL;
+
+ stub_exe_fd = memfd_create("uml-userspace",
+ MFD_EXEC | MFD_CLOEXEC | MFD_ALLOW_SEALING);
+
+ if (stub_exe_fd < 0) {
+ printk(UM_KERN_INFO "Could not create executable memfd, using temporary file!");
+
+ tmpfile = malloc(strlen(tempdir) +
+ strlen(STUB_EXE_NAME_TEMPLATE) + 1);
+ if (tmpfile == NULL)
+ panic("Failed to allocate memory for stub binary name");
+
+ strcpy(tmpfile, tempdir);
+ strcat(tmpfile, STUB_EXE_NAME_TEMPLATE);
+
+ stub_exe_fd = mkstemp(tmpfile);
+ if (stub_exe_fd < 0)
+ panic("Could not create temporary file for stub binary: %d",
+ -errno);
}
- fd = phys_mapping(uml_to_phys(stack), &offset);
- addr = mmap((void *) STUB_DATA,
- STUB_DATA_PAGES * UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE,
- MAP_FIXED | MAP_SHARED, fd, offset);
- if (addr == MAP_FAILED) {
- os_info("mapping segfault stack at 0x%lx failed, errno = %d\n",
- STUB_DATA, errno);
- exit(1);
+ while (written < stub_exe_end - stub_exe_start) {
+ ssize_t res = write(stub_exe_fd, stub_exe_start + written,
+ stub_exe_end - stub_exe_start - written);
+ if (res < 0) {
+ if (errno == EINTR)
+ continue;
+
+ if (tmpfile)
+ unlink(tmpfile);
+ panic("Failed write stub binary: %d", -errno);
+ }
+
+ written += res;
}
- set_sigstack((void *) STUB_DATA, STUB_DATA_PAGES * UM_KERN_PAGE_SIZE);
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_ONSTACK | SA_NODEFER | SA_SIGINFO;
- sa.sa_sigaction = (void *) segv_handler;
- sa.sa_restorer = NULL;
- if (sigaction(SIGSEGV, &sa, NULL) < 0) {
- os_info("%s - setting SIGSEGV handler failed - errno = %d\n",
- __func__, errno);
- exit(1);
+ if (!tmpfile) {
+ fcntl(stub_exe_fd, F_ADD_SEALS,
+ F_SEAL_WRITE | F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_SEAL);
+ } else {
+ if (fchmod(stub_exe_fd, 00500) < 0) {
+ unlink(tmpfile);
+ panic("Could not make stub binary executable: %d",
+ -errno);
+ }
+
+ close(stub_exe_fd);
+ stub_exe_fd = open(tmpfile, O_RDONLY | O_CLOEXEC | O_NOFOLLOW);
+ if (stub_exe_fd < 0) {
+ unlink(tmpfile);
+ panic("Could not reopen stub binary: %d", -errno);
+ }
+
+ unlink(tmpfile);
+ free(tmpfile);
}
- kill(os_getpid(), SIGSTOP);
return 0;
}
+__initcall(init_stub_exe_fd);
int userspace_pid[NR_CPUS];
@@ -270,7 +322,7 @@ int start_userspace(unsigned long stub_stack)
{
void *stack;
unsigned long sp;
- int pid, status, n, flags, err;
+ int pid, status, n, err;
/* setup a temporary stack page */
stack = mmap(NULL, UM_KERN_PAGE_SIZE,
@@ -286,10 +338,10 @@ int start_userspace(unsigned long stub_stack)
/* set stack pointer to the end of the stack page, so it can grow downwards */
sp = (unsigned long)stack + UM_KERN_PAGE_SIZE;
- flags = CLONE_FILES | SIGCHLD;
-
/* clone into new userspace process */
- pid = clone(userspace_tramp, (void *) sp, flags, (void *) stub_stack);
+ pid = clone(userspace_tramp, (void *) sp,
+ CLONE_VFORK | CLONE_VM | SIGCHLD,
+ (void *)stub_stack);
if (pid < 0) {
err = -errno;
printk(UM_KERN_ERR "%s : clone failed, errno = %d\n",
@@ -336,7 +388,10 @@ int start_userspace(unsigned long stub_stack)
return err;
}
-void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
+int unscheduled_userspace_iterations;
+extern unsigned long tt_extra_sched_jiffies;
+
+void userspace(struct uml_pt_regs *regs)
{
int err, status, op, pid = userspace_pid[0];
siginfo_t si;
@@ -345,6 +400,29 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
interrupt_end();
while (1) {
+ /*
+ * When we are in time-travel mode, userspace can theoretically
+ * do a *lot* of work without being scheduled. The problem with
+ * this is that it will prevent kernel bookkeeping (primarily
+ * the RCU) from running and this can for example cause OOM
+ * situations.
+ *
+ * This code accounts a jiffie against the scheduling clock
+ * after the defined userspace iterations in the same thread.
+ * By doing so the situation is effectively prevented.
+ */
+ if (time_travel_mode == TT_MODE_INFCPU ||
+ time_travel_mode == TT_MODE_EXTERNAL) {
+#ifdef CONFIG_UML_MAX_USERSPACE_ITERATIONS
+ if (CONFIG_UML_MAX_USERSPACE_ITERATIONS &&
+ unscheduled_userspace_iterations++ >
+ CONFIG_UML_MAX_USERSPACE_ITERATIONS) {
+ tt_extra_sched_jiffies += 1;
+ unscheduled_userspace_iterations = 0;
+ }
+#endif
+ }
+
time_travel_print_bc_msg();
current_mm_sync();
@@ -435,11 +513,11 @@ void userspace(struct uml_pt_regs *regs, unsigned long *aux_fp_regs)
case SIGSEGV:
if (PTRACE_FULL_FAULTINFO) {
get_skas_faultinfo(pid,
- &regs->faultinfo, aux_fp_regs);
+ &regs->faultinfo);
(*sig_info[SIGSEGV])(SIGSEGV, (struct siginfo *)&si,
regs);
}
- else handle_segv(pid, regs, aux_fp_regs);
+ else handle_segv(pid, regs);
break;
case SIGTRAP + 0x80:
handle_trap(pid, regs);
@@ -487,6 +565,8 @@ void new_thread(void *stack, jmp_buf *buf, void (*handler)(void))
void switch_threads(jmp_buf *me, jmp_buf *you)
{
+ unscheduled_userspace_iterations = 0;
+
if (UML_SETJMP(me) == 0)
UML_LONGJMP(you, 1);
}
@@ -570,6 +650,7 @@ static bool noreboot;
static int __init noreboot_cmd_param(char *str, int *add)
{
+ *add = 0;
noreboot = true;
return 0;
}
diff --git a/arch/um/os-Linux/umid.c b/arch/um/os-Linux/umid.c
index e09d65b05d1c..eb523ab1e218 100644
--- a/arch/um/os-Linux/umid.c
+++ b/arch/um/os-Linux/umid.c
@@ -358,6 +358,8 @@ char *get_umid(void)
static int __init set_uml_dir(char *name, int *add)
{
+ *add = 0;
+
if (*name == '\0') {
os_warn("uml_dir can't be an empty string\n");
return 0;
diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
index 1dca4ffbd572..4193e04d7e4a 100644
--- a/arch/um/os-Linux/util.c
+++ b/arch/um/os-Linux/util.c
@@ -52,8 +52,8 @@ void setup_machinename(char *machine_out)
struct utsname host;
uname(&host);
-#ifdef UML_CONFIG_UML_X86
-# ifndef UML_CONFIG_64BIT
+#if IS_ENABLED(CONFIG_UML_X86)
+# if !IS_ENABLED(CONFIG_64BIT)
if (!strcmp(host.machine, "x86_64")) {
strcpy(machine_out, "i686");
return;
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 6c633d93c639..9d7bd0ae48c4 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -128,6 +128,8 @@ config X86
select ARCH_SUPPORTS_LTO_CLANG
select ARCH_SUPPORTS_LTO_CLANG_THIN
select ARCH_SUPPORTS_RT
+ select ARCH_SUPPORTS_AUTOFDO_CLANG
+ select ARCH_SUPPORTS_PROPELLER_CLANG if X86_64
select ARCH_USE_BUILTIN_BSWAP
select ARCH_USE_CMPXCHG_LOCKREF if X86_CMPXCHG64
select ARCH_USE_MEMTEST
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index bb284aff7bfd..99c590da0ae2 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -429,6 +429,16 @@ static struct event_constraint intel_lnc_event_constraints[] = {
EVENT_CONSTRAINT_END
};
+static struct extra_reg intel_lnc_extra_regs[] __read_mostly = {
+ INTEL_UEVENT_EXTRA_REG(0x012a, MSR_OFFCORE_RSP_0, 0xfffffffffffull, RSP_0),
+ INTEL_UEVENT_EXTRA_REG(0x012b, MSR_OFFCORE_RSP_1, 0xfffffffffffull, RSP_1),
+ INTEL_UEVENT_PEBS_LDLAT_EXTRA_REG(0x01cd),
+ INTEL_UEVENT_EXTRA_REG(0x02c6, MSR_PEBS_FRONTEND, 0x9, FE),
+ INTEL_UEVENT_EXTRA_REG(0x03c6, MSR_PEBS_FRONTEND, 0x7fff1f, FE),
+ INTEL_UEVENT_EXTRA_REG(0x40ad, MSR_PEBS_FRONTEND, 0xf, FE),
+ INTEL_UEVENT_EXTRA_REG(0x04c2, MSR_PEBS_FRONTEND, 0x8, FE),
+ EVENT_EXTRA_END
+};
EVENT_ATTR_STR(mem-loads, mem_ld_nhm, "event=0x0b,umask=0x10,ldlat=3");
EVENT_ATTR_STR(mem-loads, mem_ld_snb, "event=0xcd,umask=0x1,ldlat=3");
@@ -6422,7 +6432,7 @@ static __always_inline void intel_pmu_init_lnc(struct pmu *pmu)
intel_pmu_init_glc(pmu);
hybrid(pmu, event_constraints) = intel_lnc_event_constraints;
hybrid(pmu, pebs_constraints) = intel_lnc_pebs_event_constraints;
- hybrid(pmu, extra_regs) = intel_rwc_extra_regs;
+ hybrid(pmu, extra_regs) = intel_lnc_extra_regs;
}
static __always_inline void intel_pmu_init_skt(struct pmu *pmu)
@@ -7135,6 +7145,7 @@ __init int intel_pmu_init(void)
case INTEL_METEORLAKE:
case INTEL_METEORLAKE_L:
+ case INTEL_ARROWLAKE_U:
intel_pmu_init_hybrid(hybrid_big_small);
x86_pmu.pebs_latency_data = cmt_latency_data;
diff --git a/arch/x86/events/intel/ds.c b/arch/x86/events/intel/ds.c
index 8afc4ad3cd16..6ba6549f26fa 100644
--- a/arch/x86/events/intel/ds.c
+++ b/arch/x86/events/intel/ds.c
@@ -1489,7 +1489,7 @@ void intel_pmu_pebs_enable(struct perf_event *event)
* hence we need to drain when changing said
* size.
*/
- intel_pmu_drain_large_pebs(cpuc);
+ intel_pmu_drain_pebs_buffer();
adaptive_pebs_record_size_update();
wrmsrl(MSR_PEBS_DATA_CFG, pebs_data_cfg);
cpuc->active_pebs_data_cfg = pebs_data_cfg;
@@ -2517,6 +2517,7 @@ void __init intel_ds_init(void)
x86_pmu.large_pebs_flags |= PERF_SAMPLE_TIME;
break;
+ case 6:
case 5:
x86_pmu.pebs_ept = 1;
fallthrough;
diff --git a/arch/x86/events/intel/uncore.c b/arch/x86/events/intel/uncore.c
index d98fac567684..e7aba7349231 100644
--- a/arch/x86/events/intel/uncore.c
+++ b/arch/x86/events/intel/uncore.c
@@ -1910,6 +1910,7 @@ static const struct x86_cpu_id intel_uncore_match[] __initconst = {
X86_MATCH_VFM(INTEL_ATOM_GRACEMONT, &adl_uncore_init),
X86_MATCH_VFM(INTEL_ATOM_CRESTMONT_X, &gnr_uncore_init),
X86_MATCH_VFM(INTEL_ATOM_CRESTMONT, &gnr_uncore_init),
+ X86_MATCH_VFM(INTEL_ATOM_DARKMONT_X, &gnr_uncore_init),
{},
};
MODULE_DEVICE_TABLE(x86cpu, intel_uncore_match);
diff --git a/arch/x86/include/asm/cpufeatures.h b/arch/x86/include/asm/cpufeatures.h
index 17b6590748c0..645aa360628d 100644
--- a/arch/x86/include/asm/cpufeatures.h
+++ b/arch/x86/include/asm/cpufeatures.h
@@ -452,6 +452,7 @@
#define X86_FEATURE_SME_COHERENT (19*32+10) /* AMD hardware-enforced cache coherency */
#define X86_FEATURE_DEBUG_SWAP (19*32+14) /* "debug_swap" AMD SEV-ES full debug state swap support */
#define X86_FEATURE_SVSM (19*32+28) /* "svsm" SVSM present */
+#define X86_FEATURE_HV_INUSE_WR_ALLOWED (19*32+30) /* Allow Write to in-use hypervisor-owned pages */
/* AMD-defined Extended Feature 2 EAX, CPUID level 0x80000021 (EAX), word 20 */
#define X86_FEATURE_NO_NESTED_DATA_BP (20*32+ 0) /* No Nested Data Breakpoints */
diff --git a/arch/x86/include/asm/pgtable_types.h b/arch/x86/include/asm/pgtable_types.h
index 6f82e75b6149..4b804531b03c 100644
--- a/arch/x86/include/asm/pgtable_types.h
+++ b/arch/x86/include/asm/pgtable_types.h
@@ -36,10 +36,12 @@
#define _PAGE_BIT_DEVMAP _PAGE_BIT_SOFTW4
#ifdef CONFIG_X86_64
-#define _PAGE_BIT_SAVED_DIRTY _PAGE_BIT_SOFTW5 /* Saved Dirty bit */
+#define _PAGE_BIT_SAVED_DIRTY _PAGE_BIT_SOFTW5 /* Saved Dirty bit (leaf) */
+#define _PAGE_BIT_NOPTISHADOW _PAGE_BIT_SOFTW5 /* No PTI shadow (root PGD) */
#else
/* Shared with _PAGE_BIT_UFFD_WP which is not supported on 32 bit */
-#define _PAGE_BIT_SAVED_DIRTY _PAGE_BIT_SOFTW2 /* Saved Dirty bit */
+#define _PAGE_BIT_SAVED_DIRTY _PAGE_BIT_SOFTW2 /* Saved Dirty bit (leaf) */
+#define _PAGE_BIT_NOPTISHADOW _PAGE_BIT_SOFTW2 /* No PTI shadow (root PGD) */
#endif
/* If _PAGE_BIT_PRESENT is clear, we use these: */
@@ -139,6 +141,8 @@
#define _PAGE_PROTNONE (_AT(pteval_t, 1) << _PAGE_BIT_PROTNONE)
+#define _PAGE_NOPTISHADOW (_AT(pteval_t, 1) << _PAGE_BIT_NOPTISHADOW)
+
/*
* Set of bits not changed in pte_modify. The pte's
* protection key is treated like _PAGE_RW, for
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index c0975815980c..20e6009381ed 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -230,6 +230,8 @@ static inline unsigned long long l1tf_pfn_limit(void)
return BIT_ULL(boot_cpu_data.x86_cache_bits - 1 - PAGE_SHIFT);
}
+void init_cpu_devs(void);
+void get_cpu_vendor(struct cpuinfo_x86 *c);
extern void early_cpu_init(void);
extern void identify_secondary_cpu(struct cpuinfo_x86 *);
extern void print_cpu_info(struct cpuinfo_x86 *);
diff --git a/arch/x86/include/asm/static_call.h b/arch/x86/include/asm/static_call.h
index 125c407e2abe..41502bd2afd6 100644
--- a/arch/x86/include/asm/static_call.h
+++ b/arch/x86/include/asm/static_call.h
@@ -65,4 +65,19 @@
extern bool __static_call_fixup(void *tramp, u8 op, void *dest);
+extern void __static_call_update_early(void *tramp, void *func);
+
+#define static_call_update_early(name, _func) \
+({ \
+ typeof(&STATIC_CALL_TRAMP(name)) __F = (_func); \
+ if (static_call_initialized) { \
+ __static_call_update(&STATIC_CALL_KEY(name), \
+ STATIC_CALL_TRAMP_ADDR(name), __F);\
+ } else { \
+ WRITE_ONCE(STATIC_CALL_KEY(name).func, _func); \
+ __static_call_update_early(STATIC_CALL_TRAMP_ADDR(name),\
+ __F); \
+ } \
+})
+
#endif /* _ASM_STATIC_CALL_H */
diff --git a/arch/x86/include/asm/sync_core.h b/arch/x86/include/asm/sync_core.h
index ab7382f92aff..96bda43538ee 100644
--- a/arch/x86/include/asm/sync_core.h
+++ b/arch/x86/include/asm/sync_core.h
@@ -8,7 +8,7 @@
#include <asm/special_insns.h>
#ifdef CONFIG_X86_32
-static inline void iret_to_self(void)
+static __always_inline void iret_to_self(void)
{
asm volatile (
"pushfl\n\t"
@@ -19,7 +19,7 @@ static inline void iret_to_self(void)
: ASM_CALL_CONSTRAINT : : "memory");
}
#else
-static inline void iret_to_self(void)
+static __always_inline void iret_to_self(void)
{
unsigned int tmp;
@@ -55,7 +55,7 @@ static inline void iret_to_self(void)
* Like all of Linux's memory ordering operations, this is a
* compiler barrier as well.
*/
-static inline void sync_core(void)
+static __always_inline void sync_core(void)
{
/*
* The SERIALIZE instruction is the most straightforward way to
diff --git a/arch/x86/include/asm/tlb.h b/arch/x86/include/asm/tlb.h
index 580636cdc257..4d3c9d00d6b6 100644
--- a/arch/x86/include/asm/tlb.h
+++ b/arch/x86/include/asm/tlb.h
@@ -34,4 +34,8 @@ static inline void __tlb_remove_table(void *table)
free_page_and_swap_cache(table);
}
+static inline void invlpg(unsigned long addr)
+{
+ asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
+}
#endif /* _ASM_X86_TLB_H */
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h
index a2dd24947eb8..97771b9d33af 100644
--- a/arch/x86/include/asm/xen/hypercall.h
+++ b/arch/x86/include/asm/xen/hypercall.h
@@ -39,9 +39,11 @@
#include <linux/string.h>
#include <linux/types.h>
#include <linux/pgtable.h>
+#include <linux/instrumentation.h>
#include <trace/events/xen.h>
+#include <asm/alternative.h>
#include <asm/page.h>
#include <asm/smap.h>
#include <asm/nospec-branch.h>
@@ -86,11 +88,20 @@ struct xen_dm_op_buf;
* there aren't more than 5 arguments...)
*/
-extern struct { char _entry[32]; } hypercall_page[];
+void xen_hypercall_func(void);
+DECLARE_STATIC_CALL(xen_hypercall, xen_hypercall_func);
-#define __HYPERCALL "call hypercall_page+%c[offset]"
-#define __HYPERCALL_ENTRY(x) \
- [offset] "i" (__HYPERVISOR_##x * sizeof(hypercall_page[0]))
+#ifdef MODULE
+#define __ADDRESSABLE_xen_hypercall
+#else
+#define __ADDRESSABLE_xen_hypercall __ADDRESSABLE_ASM_STR(__SCK__xen_hypercall)
+#endif
+
+#define __HYPERCALL \
+ __ADDRESSABLE_xen_hypercall \
+ "call __SCT__xen_hypercall"
+
+#define __HYPERCALL_ENTRY(x) "a" (x)
#ifdef CONFIG_X86_32
#define __HYPERCALL_RETREG "eax"
@@ -148,7 +159,7 @@ extern struct { char _entry[32]; } hypercall_page[];
__HYPERCALL_0ARG(); \
asm volatile (__HYPERCALL \
: __HYPERCALL_0PARAM \
- : __HYPERCALL_ENTRY(name) \
+ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
: __HYPERCALL_CLOBBER0); \
(type)__res; \
})
@@ -159,7 +170,7 @@ extern struct { char _entry[32]; } hypercall_page[];
__HYPERCALL_1ARG(a1); \
asm volatile (__HYPERCALL \
: __HYPERCALL_1PARAM \
- : __HYPERCALL_ENTRY(name) \
+ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
: __HYPERCALL_CLOBBER1); \
(type)__res; \
})
@@ -170,7 +181,7 @@ extern struct { char _entry[32]; } hypercall_page[];
__HYPERCALL_2ARG(a1, a2); \
asm volatile (__HYPERCALL \
: __HYPERCALL_2PARAM \
- : __HYPERCALL_ENTRY(name) \
+ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
: __HYPERCALL_CLOBBER2); \
(type)__res; \
})
@@ -181,7 +192,7 @@ extern struct { char _entry[32]; } hypercall_page[];
__HYPERCALL_3ARG(a1, a2, a3); \
asm volatile (__HYPERCALL \
: __HYPERCALL_3PARAM \
- : __HYPERCALL_ENTRY(name) \
+ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
: __HYPERCALL_CLOBBER3); \
(type)__res; \
})
@@ -192,7 +203,7 @@ extern struct { char _entry[32]; } hypercall_page[];
__HYPERCALL_4ARG(a1, a2, a3, a4); \
asm volatile (__HYPERCALL \
: __HYPERCALL_4PARAM \
- : __HYPERCALL_ENTRY(name) \
+ : __HYPERCALL_ENTRY(__HYPERVISOR_ ## name) \
: __HYPERCALL_CLOBBER4); \
(type)__res; \
})
@@ -206,12 +217,9 @@ xen_single_call(unsigned int call,
__HYPERCALL_DECLS;
__HYPERCALL_5ARG(a1, a2, a3, a4, a5);
- if (call >= PAGE_SIZE / sizeof(hypercall_page[0]))
- return -EINVAL;
-
- asm volatile(CALL_NOSPEC
+ asm volatile(__HYPERCALL
: __HYPERCALL_5PARAM
- : [thunk_target] "a" (&hypercall_page[call])
+ : __HYPERCALL_ENTRY(call)
: __HYPERCALL_CLOBBER5);
return (long)__res;
diff --git a/arch/x86/kernel/callthunks.c b/arch/x86/kernel/callthunks.c
index 465647456753..f17d16607882 100644
--- a/arch/x86/kernel/callthunks.c
+++ b/arch/x86/kernel/callthunks.c
@@ -143,11 +143,6 @@ static bool skip_addr(void *dest)
dest < (void*)relocate_kernel + KEXEC_CONTROL_CODE_MAX_SIZE)
return true;
#endif
-#ifdef CONFIG_XEN
- if (dest >= (void *)hypercall_page &&
- dest < (void*)hypercall_page + PAGE_SIZE)
- return true;
-#endif
return false;
}
diff --git a/arch/x86/kernel/cet.c b/arch/x86/kernel/cet.c
index d2c732a34e5d..303bf74d175b 100644
--- a/arch/x86/kernel/cet.c
+++ b/arch/x86/kernel/cet.c
@@ -81,6 +81,34 @@ static void do_user_cp_fault(struct pt_regs *regs, unsigned long error_code)
static __ro_after_init bool ibt_fatal = true;
+/*
+ * By definition, all missing-ENDBRANCH #CPs are a result of WFE && !ENDBR.
+ *
+ * For the kernel IBT no ENDBR selftest where #CPs are deliberately triggered,
+ * the WFE state of the interrupted context needs to be cleared to let execution
+ * continue. Otherwise when the CPU resumes from the instruction that just
+ * caused the previous #CP, another missing-ENDBRANCH #CP is raised and the CPU
+ * enters a dead loop.
+ *
+ * This is not a problem with IDT because it doesn't preserve WFE and IRET doesn't
+ * set WFE. But FRED provides space on the entry stack (in an expanded CS area)
+ * to save and restore the WFE state, thus the WFE state is no longer clobbered,
+ * so software must clear it.
+ */
+static void ibt_clear_fred_wfe(struct pt_regs *regs)
+{
+ /*
+ * No need to do any FRED checks.
+ *
+ * For IDT event delivery, the high-order 48 bits of CS are pushed
+ * as 0s into the stack, and later IRET ignores these bits.
+ *
+ * For FRED, a test to check if fred_cs.wfe is set would be dropped
+ * by compilers.
+ */
+ regs->fred_cs.wfe = 0;
+}
+
static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
{
if ((error_code & CP_EC) != CP_ENDBR) {
@@ -90,6 +118,7 @@ static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
if (unlikely(regs->ip == (unsigned long)&ibt_selftest_noendbr)) {
regs->ax = 0;
+ ibt_clear_fred_wfe(regs);
return;
}
@@ -97,6 +126,7 @@ static void do_kernel_cp_fault(struct pt_regs *regs, unsigned long error_code)
if (!ibt_fatal) {
printk(KERN_DEFAULT CUT_HERE);
__warn(__FILE__, __LINE__, (void *)regs->ip, TAINT_WARN, regs, NULL);
+ ibt_clear_fred_wfe(regs);
return;
}
BUG();
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index 823f44f7bc94..79d2e17f6582 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -798,6 +798,7 @@ static void init_amd_bd(struct cpuinfo_x86 *c)
static const struct x86_cpu_desc erratum_1386_microcode[] = {
AMD_CPU_DESC(0x17, 0x1, 0x2, 0x0800126e),
AMD_CPU_DESC(0x17, 0x31, 0x0, 0x08301052),
+ {},
};
static void fix_erratum_1386(struct cpuinfo_x86 *c)
@@ -1064,7 +1065,7 @@ static void init_amd(struct cpuinfo_x86 *c)
*/
if (spectre_v2_in_eibrs_mode(spectre_v2_enabled) &&
cpu_has(c, X86_FEATURE_AUTOIBRS))
- WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS));
+ WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS) < 0);
/* AMD CPUs don't need fencing after x2APIC/TSC_DEADLINE MSR writes. */
clear_cpu_cap(c, X86_FEATURE_APIC_MSRS_FENCE);
diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index 392d09c936d6..e6fa03ed9172 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -178,8 +178,6 @@ struct _cpuid4_info_regs {
struct amd_northbridge *nb;
};
-static unsigned short num_cache_leaves;
-
/* AMD doesn't have CPUID4. Emulate it here to report the same
information to the user. This makes some assumptions about the machine:
L2 not shared, no SMT etc. that is currently true on AMD CPUs.
@@ -717,20 +715,23 @@ void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c)
void init_amd_cacheinfo(struct cpuinfo_x86 *c)
{
+ struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
- num_cache_leaves = find_num_cache_leaves(c);
+ ci->num_leaves = find_num_cache_leaves(c);
} else if (c->extended_cpuid_level >= 0x80000006) {
if (cpuid_edx(0x80000006) & 0xf000)
- num_cache_leaves = 4;
+ ci->num_leaves = 4;
else
- num_cache_leaves = 3;
+ ci->num_leaves = 3;
}
}
void init_hygon_cacheinfo(struct cpuinfo_x86 *c)
{
- num_cache_leaves = find_num_cache_leaves(c);
+ struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
+
+ ci->num_leaves = find_num_cache_leaves(c);
}
void init_intel_cacheinfo(struct cpuinfo_x86 *c)
@@ -740,21 +741,21 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c)
unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
+ struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
if (c->cpuid_level > 3) {
- static int is_initialized;
-
- if (is_initialized == 0) {
- /* Init num_cache_leaves from boot CPU */
- num_cache_leaves = find_num_cache_leaves(c);
- is_initialized++;
- }
+ /*
+ * There should be at least one leaf. A non-zero value means
+ * that the number of leaves has been initialized.
+ */
+ if (!ci->num_leaves)
+ ci->num_leaves = find_num_cache_leaves(c);
/*
* Whenever possible use cpuid(4), deterministic cache
* parameters cpuid leaf to find the cache details
*/
- for (i = 0; i < num_cache_leaves; i++) {
+ for (i = 0; i < ci->num_leaves; i++) {
struct _cpuid4_info_regs this_leaf = {};
int retval;
@@ -790,14 +791,14 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c)
* Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for
* trace cache
*/
- if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) {
+ if ((!ci->num_leaves || c->x86 == 15) && c->cpuid_level > 1) {
/* supports eax=2 call */
int j, n;
unsigned int regs[4];
unsigned char *dp = (unsigned char *)regs;
int only_trace = 0;
- if (num_cache_leaves != 0 && c->x86 == 15)
+ if (ci->num_leaves && c->x86 == 15)
only_trace = 1;
/* Number of times to iterate */
@@ -991,14 +992,12 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
int init_cache_level(unsigned int cpu)
{
- struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
+ struct cpu_cacheinfo *ci = get_cpu_cacheinfo(cpu);
- if (!num_cache_leaves)
+ /* There should be at least one leaf. */
+ if (!ci->num_leaves)
return -ENOENT;
- if (!this_cpu_ci)
- return -EINVAL;
- this_cpu_ci->num_levels = 3;
- this_cpu_ci->num_leaves = num_cache_leaves;
+
return 0;
}
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index ca327cfa42ae..3e9037690814 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -169,7 +169,7 @@ static void ppin_init(struct cpuinfo_x86 *c)
}
clear_ppin:
- clear_cpu_cap(c, info->feature);
+ setup_clear_cpu_cap(info->feature);
}
static void default_init(struct cpuinfo_x86 *c)
@@ -867,7 +867,7 @@ static void cpu_detect_tlb(struct cpuinfo_x86 *c)
tlb_lld_4m[ENTRIES], tlb_lld_1g[ENTRIES]);
}
-static void get_cpu_vendor(struct cpuinfo_x86 *c)
+void get_cpu_vendor(struct cpuinfo_x86 *c)
{
char *v = c->x86_vendor_id;
int i;
@@ -1649,15 +1649,11 @@ static void __init early_identify_cpu(struct cpuinfo_x86 *c)
detect_nopl();
}
-void __init early_cpu_init(void)
+void __init init_cpu_devs(void)
{
const struct cpu_dev *const *cdev;
int count = 0;
-#ifdef CONFIG_PROCESSOR_SELECT
- pr_info("KERNEL supported cpus:\n");
-#endif
-
for (cdev = __x86_cpu_dev_start; cdev < __x86_cpu_dev_end; cdev++) {
const struct cpu_dev *cpudev = *cdev;
@@ -1665,20 +1661,30 @@ void __init early_cpu_init(void)
break;
cpu_devs[count] = cpudev;
count++;
+ }
+}
+void __init early_cpu_init(void)
+{
#ifdef CONFIG_PROCESSOR_SELECT
- {
- unsigned int j;
-
- for (j = 0; j < 2; j++) {
- if (!cpudev->c_ident[j])
- continue;
- pr_info(" %s %s\n", cpudev->c_vendor,
- cpudev->c_ident[j]);
- }
- }
+ unsigned int i, j;
+
+ pr_info("KERNEL supported cpus:\n");
#endif
+
+ init_cpu_devs();
+
+#ifdef CONFIG_PROCESSOR_SELECT
+ for (i = 0; i < X86_VENDOR_NUM && cpu_devs[i]; i++) {
+ for (j = 0; j < 2; j++) {
+ if (!cpu_devs[i]->c_ident[j])
+ continue;
+ pr_info(" %s %s\n", cpu_devs[i]->c_vendor,
+ cpu_devs[i]->c_ident[j]);
+ }
}
+#endif
+
early_identify_cpu(&boot_cpu_data);
}
diff --git a/arch/x86/kernel/cpu/intel.c b/arch/x86/kernel/cpu/intel.c
index d1de300af173..8ded9f859a3a 100644
--- a/arch/x86/kernel/cpu/intel.c
+++ b/arch/x86/kernel/cpu/intel.c
@@ -555,7 +555,9 @@ static void init_intel(struct cpuinfo_x86 *c)
c->x86_vfm == INTEL_WESTMERE_EX))
set_cpu_bug(c, X86_BUG_CLFLUSH_MONITOR);
- if (boot_cpu_has(X86_FEATURE_MWAIT) && c->x86_vfm == INTEL_ATOM_GOLDMONT)
+ if (boot_cpu_has(X86_FEATURE_MWAIT) &&
+ (c->x86_vfm == INTEL_ATOM_GOLDMONT ||
+ c->x86_vfm == INTEL_LUNARLAKE_M))
set_cpu_bug(c, X86_BUG_MONITOR);
#ifdef CONFIG_X86_64
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index 31a73715d755..fb5d0c67fbab 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -34,6 +34,7 @@
#include <asm/setup.h>
#include <asm/cpu.h>
#include <asm/msr.h>
+#include <asm/tlb.h>
#include "internal.h"
@@ -483,11 +484,25 @@ static void scan_containers(u8 *ucode, size_t size, struct cont_desc *desc)
}
}
-static int __apply_microcode_amd(struct microcode_amd *mc)
+static int __apply_microcode_amd(struct microcode_amd *mc, unsigned int psize)
{
+ unsigned long p_addr = (unsigned long)&mc->hdr.data_code;
u32 rev, dummy;
- native_wrmsrl(MSR_AMD64_PATCH_LOADER, (u64)(long)&mc->hdr.data_code);
+ native_wrmsrl(MSR_AMD64_PATCH_LOADER, p_addr);
+
+ if (x86_family(bsp_cpuid_1_eax) == 0x17) {
+ unsigned long p_addr_end = p_addr + psize - 1;
+
+ invlpg(p_addr);
+
+ /*
+ * Flush next page too if patch image is crossing a page
+ * boundary.
+ */
+ if (p_addr >> PAGE_SHIFT != p_addr_end >> PAGE_SHIFT)
+ invlpg(p_addr_end);
+ }
/* verify patch application was successful */
native_rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
@@ -529,7 +544,7 @@ static bool early_apply_microcode(u32 old_rev, void *ucode, size_t size)
if (old_rev > mc->hdr.patch_id)
return ret;
- return !__apply_microcode_amd(mc);
+ return !__apply_microcode_amd(mc, desc.psize);
}
static bool get_builtin_microcode(struct cpio_data *cp)
@@ -745,7 +760,7 @@ void reload_ucode_amd(unsigned int cpu)
rdmsr(MSR_AMD64_PATCH_LEVEL, rev, dummy);
if (rev < mc->hdr.patch_id) {
- if (!__apply_microcode_amd(mc))
+ if (!__apply_microcode_amd(mc, p->size))
pr_info_once("reload revision: 0x%08x\n", mc->hdr.patch_id);
}
}
@@ -798,7 +813,7 @@ static enum ucode_state apply_microcode_amd(int cpu)
goto out;
}
- if (__apply_microcode_amd(mc_amd)) {
+ if (__apply_microcode_amd(mc_amd, p->size)) {
pr_err("CPU%d: update failed for patch_level=0x%08x\n",
cpu, mc_amd->hdr.patch_id);
return UCODE_ERROR;
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c
index d18078834ded..dc12fe5ef3ca 100644
--- a/arch/x86/kernel/cpu/mshyperv.c
+++ b/arch/x86/kernel/cpu/mshyperv.c
@@ -223,6 +223,63 @@ static void hv_machine_crash_shutdown(struct pt_regs *regs)
hyperv_cleanup();
}
#endif /* CONFIG_CRASH_DUMP */
+
+static u64 hv_ref_counter_at_suspend;
+static void (*old_save_sched_clock_state)(void);
+static void (*old_restore_sched_clock_state)(void);
+
+/*
+ * Hyper-V clock counter resets during hibernation. Save and restore clock
+ * offset during suspend/resume, while also considering the time passed
+ * before suspend. This is to make sure that sched_clock using hv tsc page
+ * based clocksource, proceeds from where it left off during suspend and
+ * it shows correct time for the timestamps of kernel messages after resume.
+ */
+static void save_hv_clock_tsc_state(void)
+{
+ hv_ref_counter_at_suspend = hv_read_reference_counter();
+}
+
+static void restore_hv_clock_tsc_state(void)
+{
+ /*
+ * Adjust the offsets used by hv tsc clocksource to
+ * account for the time spent before hibernation.
+ * adjusted value = reference counter (time) at suspend
+ * - reference counter (time) now.
+ */
+ hv_adj_sched_clock_offset(hv_ref_counter_at_suspend - hv_read_reference_counter());
+}
+
+/*
+ * Functions to override save_sched_clock_state and restore_sched_clock_state
+ * functions of x86_platform. The Hyper-V clock counter is reset during
+ * suspend-resume and the offset used to measure time needs to be
+ * corrected, post resume.
+ */
+static void hv_save_sched_clock_state(void)
+{
+ old_save_sched_clock_state();
+ save_hv_clock_tsc_state();
+}
+
+static void hv_restore_sched_clock_state(void)
+{
+ restore_hv_clock_tsc_state();
+ old_restore_sched_clock_state();
+}
+
+static void __init x86_setup_ops_for_tsc_pg_clock(void)
+{
+ if (!(ms_hyperv.features & HV_MSR_REFERENCE_TSC_AVAILABLE))
+ return;
+
+ old_save_sched_clock_state = x86_platform.save_sched_clock_state;
+ x86_platform.save_sched_clock_state = hv_save_sched_clock_state;
+
+ old_restore_sched_clock_state = x86_platform.restore_sched_clock_state;
+ x86_platform.restore_sched_clock_state = hv_restore_sched_clock_state;
+}
#endif /* CONFIG_HYPERV */
static uint32_t __init ms_hyperv_platform(void)
@@ -579,6 +636,7 @@ static void __init ms_hyperv_init_platform(void)
/* Register Hyper-V specific clocksource */
hv_init_clocksource();
+ x86_setup_ops_for_tsc_pg_clock();
hv_vtl_init_platform();
#endif
/*
diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c
index 621a151ccf7d..b2e313ea17bf 100644
--- a/arch/x86/kernel/cpu/topology.c
+++ b/arch/x86/kernel/cpu/topology.c
@@ -428,8 +428,8 @@ void __init topology_apply_cmdline_limits_early(void)
{
unsigned int possible = nr_cpu_ids;
- /* 'maxcpus=0' 'nosmp' 'nolapic' 'disableapic' 'noapic' */
- if (!setup_max_cpus || ioapic_is_disabled || apic_is_disabled)
+ /* 'maxcpus=0' 'nosmp' 'nolapic' 'disableapic' */
+ if (!setup_max_cpus || apic_is_disabled)
possible = 1;
/* 'possible_cpus=N' */
@@ -443,7 +443,7 @@ void __init topology_apply_cmdline_limits_early(void)
static __init bool restrict_to_up(void)
{
- if (!smp_found_config || ioapic_is_disabled)
+ if (!smp_found_config)
return true;
/*
* XEN PV is special as it does not advertise the local APIC
diff --git a/arch/x86/kernel/fpu/signal.c b/arch/x86/kernel/fpu/signal.c
index 1065ab995305..8f62e0666dea 100644
--- a/arch/x86/kernel/fpu/signal.c
+++ b/arch/x86/kernel/fpu/signal.c
@@ -64,16 +64,6 @@ setfx:
}
/*
- * Update the value of PKRU register that was already pushed onto the signal frame.
- */
-static inline int update_pkru_in_sigframe(struct xregs_state __user *buf, u32 pkru)
-{
- if (unlikely(!cpu_feature_enabled(X86_FEATURE_OSPKE)))
- return 0;
- return __put_user(pkru, (unsigned int __user *)get_xsave_addr_user(buf, XFEATURE_PKRU));
-}
-
-/*
* Signal frame handlers.
*/
static inline bool save_fsave_header(struct task_struct *tsk, void __user *buf)
@@ -168,14 +158,8 @@ static inline bool save_xstate_epilog(void __user *buf, int ia32_frame,
static inline int copy_fpregs_to_sigframe(struct xregs_state __user *buf, u32 pkru)
{
- int err = 0;
-
- if (use_xsave()) {
- err = xsave_to_user_sigframe(buf);
- if (!err)
- err = update_pkru_in_sigframe(buf, pkru);
- return err;
- }
+ if (use_xsave())
+ return xsave_to_user_sigframe(buf, pkru);
if (use_fxsr())
return fxsave_to_user_sigframe((struct fxregs_state __user *) buf);
diff --git a/arch/x86/kernel/fpu/xstate.h b/arch/x86/kernel/fpu/xstate.h
index 0b86a5002c84..aa16f1a1bbcf 100644
--- a/arch/x86/kernel/fpu/xstate.h
+++ b/arch/x86/kernel/fpu/xstate.h
@@ -69,6 +69,28 @@ static inline u64 xfeatures_mask_independent(void)
return fpu_kernel_cfg.independent_features;
}
+/*
+ * Update the value of PKRU register that was already pushed onto the signal frame.
+ */
+static inline int update_pkru_in_sigframe(struct xregs_state __user *buf, u64 mask, u32 pkru)
+{
+ u64 xstate_bv;
+ int err;
+
+ if (unlikely(!cpu_feature_enabled(X86_FEATURE_OSPKE)))
+ return 0;
+
+ /* Mark PKRU as in-use so that it is restored correctly. */
+ xstate_bv = (mask & xfeatures_in_use()) | XFEATURE_MASK_PKRU;
+
+ err = __put_user(xstate_bv, &buf->header.xfeatures);
+ if (err)
+ return err;
+
+ /* Update PKRU value in the userspace xsave buffer. */
+ return __put_user(pkru, (unsigned int __user *)get_xsave_addr_user(buf, XFEATURE_PKRU));
+}
+
/* XSAVE/XRSTOR wrapper functions */
#ifdef CONFIG_X86_64
@@ -256,7 +278,7 @@ static inline u64 xfeatures_need_sigframe_write(void)
* The caller has to zero buf::header before calling this because XSAVE*
* does not touch the reserved fields in the header.
*/
-static inline int xsave_to_user_sigframe(struct xregs_state __user *buf)
+static inline int xsave_to_user_sigframe(struct xregs_state __user *buf, u32 pkru)
{
/*
* Include the features which are not xsaved/rstored by the kernel
@@ -281,6 +303,9 @@ static inline int xsave_to_user_sigframe(struct xregs_state __user *buf)
XSTATE_OP(XSAVE, buf, lmask, hmask, err);
clac();
+ if (!err)
+ err = update_pkru_in_sigframe(buf, mask, pkru);
+
return err;
}
diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S
index e9e88c342f75..540443d699e3 100644
--- a/arch/x86/kernel/relocate_kernel_64.S
+++ b/arch/x86/kernel/relocate_kernel_64.S
@@ -13,6 +13,7 @@
#include <asm/pgtable_types.h>
#include <asm/nospec-branch.h>
#include <asm/unwind_hints.h>
+#include <asm/asm-offsets.h>
/*
* Must be relocatable PIC code callable as a C function, in particular
@@ -242,6 +243,13 @@ SYM_CODE_START_LOCAL_NOALIGN(virtual_mapped)
movq CR0(%r8), %r8
movq %rax, %cr3
movq %r8, %cr0
+
+#ifdef CONFIG_KEXEC_JUMP
+ /* Saved in save_processor_state. */
+ movq $saved_context, %rax
+ lgdt saved_context_gdt_desc(%rax)
+#endif
+
movq %rbp, %rax
popf
diff --git a/arch/x86/kernel/static_call.c b/arch/x86/kernel/static_call.c
index 4eefaac64c6c..9eed0c144dad 100644
--- a/arch/x86/kernel/static_call.c
+++ b/arch/x86/kernel/static_call.c
@@ -172,6 +172,15 @@ void arch_static_call_transform(void *site, void *tramp, void *func, bool tail)
}
EXPORT_SYMBOL_GPL(arch_static_call_transform);
+noinstr void __static_call_update_early(void *tramp, void *func)
+{
+ BUG_ON(system_state != SYSTEM_BOOTING);
+ BUG_ON(!early_boot_irqs_disabled);
+ BUG_ON(static_call_initialized);
+ __text_gen_insn(tramp, JMP32_INSN_OPCODE, tramp, func, JMP32_INSN_SIZE);
+ sync_core();
+}
+
#ifdef CONFIG_MITIGATION_RETHUNK
/*
* This is called by apply_returns() to fix up static call trampolines,
diff --git a/arch/x86/kernel/vmlinux.lds.S b/arch/x86/kernel/vmlinux.lds.S
index 68efd8cd8bf1..6a17396c8174 100644
--- a/arch/x86/kernel/vmlinux.lds.S
+++ b/arch/x86/kernel/vmlinux.lds.S
@@ -420,6 +420,10 @@ SECTIONS
STABS_DEBUG
DWARF_DEBUG
+#ifdef CONFIG_PROPELLER_CLANG
+ .llvm_bb_addr_map : { *(.llvm_bb_addr_map) }
+#endif
+
ELF_DETAILS
DISCARDS
@@ -515,14 +519,10 @@ INIT_PER_CPU(irq_stack_backing_store);
* linker will never mark as relocatable. (Using just ABSOLUTE() is not
* sufficient for that).
*/
-#ifdef CONFIG_XEN
#ifdef CONFIG_XEN_PV
xen_elfnote_entry_value =
ABSOLUTE(xen_elfnote_entry) + ABSOLUTE(startup_xen);
#endif
-xen_elfnote_hypercall_page_value =
- ABSOLUTE(xen_elfnote_hypercall_page) + ABSOLUTE(hypercall_page);
-#endif
#ifdef CONFIG_PVH
xen_elfnote_phys32_entry_value =
ABSOLUTE(xen_elfnote_phys32_entry) + ABSOLUTE(pvh_start_xen - LOAD_OFFSET);
diff --git a/arch/x86/kvm/cpuid.c b/arch/x86/kvm/cpuid.c
index 097bdc022d0f..ae0b438a2c99 100644
--- a/arch/x86/kvm/cpuid.c
+++ b/arch/x86/kvm/cpuid.c
@@ -36,6 +36,26 @@
u32 kvm_cpu_caps[NR_KVM_CPU_CAPS] __read_mostly;
EXPORT_SYMBOL_GPL(kvm_cpu_caps);
+struct cpuid_xstate_sizes {
+ u32 eax;
+ u32 ebx;
+ u32 ecx;
+};
+
+static struct cpuid_xstate_sizes xstate_sizes[XFEATURE_MAX] __ro_after_init;
+
+void __init kvm_init_xstate_sizes(void)
+{
+ u32 ign;
+ int i;
+
+ for (i = XFEATURE_YMM; i < ARRAY_SIZE(xstate_sizes); i++) {
+ struct cpuid_xstate_sizes *xs = &xstate_sizes[i];
+
+ cpuid_count(0xD, i, &xs->eax, &xs->ebx, &xs->ecx, &ign);
+ }
+}
+
u32 xstate_required_size(u64 xstate_bv, bool compacted)
{
int feature_bit = 0;
@@ -44,14 +64,15 @@ u32 xstate_required_size(u64 xstate_bv, bool compacted)
xstate_bv &= XFEATURE_MASK_EXTEND;
while (xstate_bv) {
if (xstate_bv & 0x1) {
- u32 eax, ebx, ecx, edx, offset;
- cpuid_count(0xD, feature_bit, &eax, &ebx, &ecx, &edx);
+ struct cpuid_xstate_sizes *xs = &xstate_sizes[feature_bit];
+ u32 offset;
+
/* ECX[1]: 64B alignment in compacted form */
if (compacted)
- offset = (ecx & 0x2) ? ALIGN(ret, 64) : ret;
+ offset = (xs->ecx & 0x2) ? ALIGN(ret, 64) : ret;
else
- offset = ebx;
- ret = max(ret, offset + eax);
+ offset = xs->ebx;
+ ret = max(ret, offset + xs->eax);
}
xstate_bv >>= 1;
diff --git a/arch/x86/kvm/cpuid.h b/arch/x86/kvm/cpuid.h
index c8dc66eddefd..f16a7b2c2adc 100644
--- a/arch/x86/kvm/cpuid.h
+++ b/arch/x86/kvm/cpuid.h
@@ -31,6 +31,7 @@ int kvm_vcpu_ioctl_get_cpuid2(struct kvm_vcpu *vcpu,
bool kvm_cpuid(struct kvm_vcpu *vcpu, u32 *eax, u32 *ebx,
u32 *ecx, u32 *edx, bool exact_only);
+void __init kvm_init_xstate_sizes(void);
u32 xstate_required_size(u64 xstate_bv, bool compacted);
int cpuid_query_maxphyaddr(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c
index 22e7ad235123..2401606db260 100644
--- a/arch/x86/kvm/mmu/mmu.c
+++ b/arch/x86/kvm/mmu/mmu.c
@@ -3364,18 +3364,6 @@ static bool fast_pf_fix_direct_spte(struct kvm_vcpu *vcpu,
return true;
}
-static bool is_access_allowed(struct kvm_page_fault *fault, u64 spte)
-{
- if (fault->exec)
- return is_executable_pte(spte);
-
- if (fault->write)
- return is_writable_pte(spte);
-
- /* Fault was on Read access */
- return spte & PT_PRESENT_MASK;
-}
-
/*
* Returns the last level spte pointer of the shadow page walk for the given
* gpa, and sets *spte to the spte value. This spte may be non-preset. If no
diff --git a/arch/x86/kvm/mmu/spte.h b/arch/x86/kvm/mmu/spte.h
index f332b33bc817..af10bc0380a3 100644
--- a/arch/x86/kvm/mmu/spte.h
+++ b/arch/x86/kvm/mmu/spte.h
@@ -462,6 +462,23 @@ static inline bool is_mmu_writable_spte(u64 spte)
}
/*
+ * Returns true if the access indicated by @fault is allowed by the existing
+ * SPTE protections. Note, the caller is responsible for checking that the
+ * SPTE is a shadow-present, leaf SPTE (either before or after).
+ */
+static inline bool is_access_allowed(struct kvm_page_fault *fault, u64 spte)
+{
+ if (fault->exec)
+ return is_executable_pte(spte);
+
+ if (fault->write)
+ return is_writable_pte(spte);
+
+ /* Fault was on Read access */
+ return spte & PT_PRESENT_MASK;
+}
+
+/*
* If the MMU-writable flag is cleared, i.e. the SPTE is write-protected for
* write-tracking, remote TLBs must be flushed, even if the SPTE was read-only,
* as KVM allows stale Writable TLB entries to exist. When dirty logging, KVM
diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c
index 4508d868f1cd..2f15e0e33903 100644
--- a/arch/x86/kvm/mmu/tdp_mmu.c
+++ b/arch/x86/kvm/mmu/tdp_mmu.c
@@ -985,6 +985,11 @@ static int tdp_mmu_map_handle_target_level(struct kvm_vcpu *vcpu,
if (fault->prefetch && is_shadow_present_pte(iter->old_spte))
return RET_PF_SPURIOUS;
+ if (is_shadow_present_pte(iter->old_spte) &&
+ is_access_allowed(fault, iter->old_spte) &&
+ is_last_spte(iter->old_spte, iter->level))
+ return RET_PF_SPURIOUS;
+
if (unlikely(!fault->slot))
new_spte = make_mmio_spte(vcpu, iter->gfn, ACC_ALL);
else
diff --git a/arch/x86/kvm/svm/avic.c b/arch/x86/kvm/svm/avic.c
index 4b74ea91f4e6..65fd245a9953 100644
--- a/arch/x86/kvm/svm/avic.c
+++ b/arch/x86/kvm/svm/avic.c
@@ -1199,6 +1199,12 @@ bool avic_hardware_setup(void)
return false;
}
+ if (cc_platform_has(CC_ATTR_HOST_SEV_SNP) &&
+ !boot_cpu_has(X86_FEATURE_HV_INUSE_WR_ALLOWED)) {
+ pr_warn("AVIC disabled: missing HvInUseWrAllowed on SNP-enabled system\n");
+ return false;
+ }
+
if (boot_cpu_has(X86_FEATURE_AVIC)) {
pr_info("AVIC enabled\n");
} else if (force_avic) {
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index dd15cc635655..21dacd312779 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -3201,15 +3201,6 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
if (data & ~supported_de_cfg)
return 1;
- /*
- * Don't let the guest change the host-programmed value. The
- * MSR is very model specific, i.e. contains multiple bits that
- * are completely unknown to KVM, and the one bit known to KVM
- * is simply a reflection of hardware capabilities.
- */
- if (!msr->host_initiated && data != svm->msr_decfg)
- return 1;
-
svm->msr_decfg = data;
break;
}
diff --git a/arch/x86/kvm/vmx/posted_intr.h b/arch/x86/kvm/vmx/posted_intr.h
index 1715d2ab07be..ad9116a99bcc 100644
--- a/arch/x86/kvm/vmx/posted_intr.h
+++ b/arch/x86/kvm/vmx/posted_intr.h
@@ -2,7 +2,7 @@
#ifndef __KVM_X86_VMX_POSTED_INTR_H
#define __KVM_X86_VMX_POSTED_INTR_H
-#include <linux/find.h>
+#include <linux/bitmap.h>
#include <asm/posted_intr.h>
void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 2e713480933a..c79a8cc57ba4 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9976,7 +9976,7 @@ static int complete_hypercall_exit(struct kvm_vcpu *vcpu)
{
u64 ret = vcpu->run->hypercall.ret;
- if (!is_64_bit_mode(vcpu))
+ if (!is_64_bit_hypercall(vcpu))
ret = (u32)ret;
kvm_rax_write(vcpu, ret);
++vcpu->stat.hypercalls;
@@ -12724,6 +12724,13 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
kvm_hv_init_vm(kvm);
kvm_xen_init_vm(kvm);
+ if (ignore_msrs && !report_ignored_msrs) {
+ pr_warn_once("Running KVM with ignore_msrs=1 and report_ignored_msrs=0 is not a\n"
+ "a supported configuration. Lying to the guest about the existence of MSRs\n"
+ "may cause the guest operating system to hang or produce errors. If a guest\n"
+ "does not run without ignore_msrs=1, please report it to kvm@vger.kernel.org.\n");
+ }
+
return 0;
out_uninit_mmu:
@@ -13997,6 +14004,8 @@ EXPORT_TRACEPOINT_SYMBOL_GPL(kvm_rmp_fault);
static int __init kvm_x86_init(void)
{
+ kvm_init_xstate_sizes();
+
kvm_mmu_x86_module_init();
mitigate_smt_rsb &= boot_cpu_has_bug(X86_BUG_SMT_RSB) && cpu_smt_possible();
return 0;
diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c
index 437e96fb4977..5ab7bd2f1983 100644
--- a/arch/x86/mm/ident_map.c
+++ b/arch/x86/mm/ident_map.c
@@ -174,7 +174,7 @@ static int ident_p4d_init(struct x86_mapping_info *info, p4d_t *p4d_page,
if (result)
return result;
- set_p4d(p4d, __p4d(__pa(pud) | info->kernpg_flag));
+ set_p4d(p4d, __p4d(__pa(pud) | info->kernpg_flag | _PAGE_NOPTISHADOW));
}
return 0;
@@ -218,14 +218,14 @@ int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
if (result)
return result;
if (pgtable_l5_enabled()) {
- set_pgd(pgd, __pgd(__pa(p4d) | info->kernpg_flag));
+ set_pgd(pgd, __pgd(__pa(p4d) | info->kernpg_flag | _PAGE_NOPTISHADOW));
} else {
/*
* With p4d folded, pgd is equal to p4d.
* The pgd entry has to point to the pud page table in this case.
*/
pud_t *pud = pud_offset(p4d, 0);
- set_pgd(pgd, __pgd(__pa(pud) | info->kernpg_flag));
+ set_pgd(pgd, __pgd(__pa(pud) | info->kernpg_flag | _PAGE_NOPTISHADOW));
}
}
diff --git a/arch/x86/mm/pat/set_memory.c b/arch/x86/mm/pat/set_memory.c
index 069e421c2247..95bc50a8541c 100644
--- a/arch/x86/mm/pat/set_memory.c
+++ b/arch/x86/mm/pat/set_memory.c
@@ -354,7 +354,7 @@ bool cpu_cache_has_invalidate_memregion(void)
{
return !cpu_feature_enabled(X86_FEATURE_HYPERVISOR);
}
-EXPORT_SYMBOL_NS_GPL(cpu_cache_has_invalidate_memregion, DEVMEM);
+EXPORT_SYMBOL_NS_GPL(cpu_cache_has_invalidate_memregion, "DEVMEM");
int cpu_cache_invalidate_memregion(int res_desc)
{
@@ -363,7 +363,7 @@ int cpu_cache_invalidate_memregion(int res_desc)
wbinvd_on_all_cpus();
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cpu_cache_invalidate_memregion, DEVMEM);
+EXPORT_SYMBOL_NS_GPL(cpu_cache_invalidate_memregion, "DEVMEM");
#endif
static void __cpa_flush_all(void *arg)
diff --git a/arch/x86/mm/pti.c b/arch/x86/mm/pti.c
index 851ec8f1363a..5f0d579932c6 100644
--- a/arch/x86/mm/pti.c
+++ b/arch/x86/mm/pti.c
@@ -132,7 +132,7 @@ pgd_t __pti_set_user_pgtbl(pgd_t *pgdp, pgd_t pgd)
* Top-level entries added to init_mm's usermode pgd after boot
* will not be automatically propagated to other mms.
*/
- if (!pgdp_maps_userspace(pgdp))
+ if (!pgdp_maps_userspace(pgdp) || (pgd.pgd & _PAGE_NOPTISHADOW))
return pgd;
/*
diff --git a/arch/x86/mm/tlb.c b/arch/x86/mm/tlb.c
index b0d5a644fc84..a2becb85bea7 100644
--- a/arch/x86/mm/tlb.c
+++ b/arch/x86/mm/tlb.c
@@ -20,6 +20,7 @@
#include <asm/cacheflush.h>
#include <asm/apic.h>
#include <asm/perf_event.h>
+#include <asm/tlb.h>
#include "mm_internal.h"
@@ -1140,7 +1141,7 @@ STATIC_NOPV void native_flush_tlb_one_user(unsigned long addr)
bool cpu_pcide;
/* Flush 'addr' from the kernel PCID: */
- asm volatile("invlpg (%0)" ::"r" (addr) : "memory");
+ invlpg(addr);
/* If PTI is off there is no user PCID and nothing to flush. */
if (!static_cpu_has(X86_FEATURE_PTI))
diff --git a/arch/x86/um/Kconfig b/arch/x86/um/Kconfig
index 186f13268401..986045d5e638 100644
--- a/arch/x86/um/Kconfig
+++ b/arch/x86/um/Kconfig
@@ -10,6 +10,7 @@ config UML_X86
def_bool y
select ARCH_BINFMT_ELF_EXTRA_PHDRS if X86_32
select DCACHE_WORD_ACCESS
+ select HAVE_EFFICIENT_UNALIGNED_ACCESS
config 64BIT
bool "64-bit kernel" if "$(SUBARCH)" = "x86"
@@ -28,17 +29,6 @@ config X86_64
def_bool 64BIT
select MODULES_USE_ELF_RELA
-config 3_LEVEL_PGTABLES
- bool "Three-level pagetables" if !64BIT
- default 64BIT
- help
- Three-level pagetables will let UML have more than 4G of physical
- memory. All the memory that can't be mapped directly will be treated
- as high memory.
-
- However, this it experimental on 32-bit architectures, so if unsure say
- N (on x86-64 it's automatically enabled, instead, as it's safe there).
-
config ARCH_HAS_SC_SIGNALS
def_bool !64BIT
diff --git a/arch/x86/um/Makefile b/arch/x86/um/Makefile
index 36e67fc97c22..b42c31cd2390 100644
--- a/arch/x86/um/Makefile
+++ b/arch/x86/um/Makefile
@@ -10,7 +10,7 @@ else
endif
obj-y = bugs_$(BITS).o delay.o fault.o \
- ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \
+ ptrace.o ptrace_$(BITS).o ptrace_user.o setjmp_$(BITS).o signal.o \
stub_segv.o \
sys_call_table_$(BITS).o sysrq_$(BITS).o tls_$(BITS).o \
mem_$(BITS).o subarch.o os-Linux/
diff --git a/arch/x86/um/asm/elf.h b/arch/x86/um/asm/elf.h
index 6052200fe925..62ed5d68a978 100644
--- a/arch/x86/um/asm/elf.h
+++ b/arch/x86/um/asm/elf.h
@@ -8,6 +8,8 @@
#include <asm/user.h>
#include <skas.h>
+#define CORE_DUMP_USE_REGSET
+
#ifdef CONFIG_X86_32
#define R_386_NONE 0
diff --git a/arch/x86/um/asm/ptrace.h b/arch/x86/um/asm/ptrace.h
index 2fef3da55533..2641d28d115c 100644
--- a/arch/x86/um/asm/ptrace.h
+++ b/arch/x86/um/asm/ptrace.h
@@ -2,6 +2,16 @@
#ifndef __UM_X86_PTRACE_H
#define __UM_X86_PTRACE_H
+/* This is here because signal.c needs the REGSET_FP_LEGACY definition */
+enum {
+ REGSET_GENERAL,
+#ifdef CONFIG_X86_32
+ REGSET_FP_LEGACY,
+#endif
+ REGSET_FP,
+ REGSET_XSTATE,
+};
+
#include <linux/compiler.h>
#ifndef CONFIG_X86_32
#define __FRAME_OFFSETS /* Needed to get the R* macros */
diff --git a/arch/x86/um/os-Linux/Makefile b/arch/x86/um/os-Linux/Makefile
index 5249bbc30dcd..77a308aaa5ec 100644
--- a/arch/x86/um/os-Linux/Makefile
+++ b/arch/x86/um/os-Linux/Makefile
@@ -3,7 +3,7 @@
# Licensed under the GPL
#
-obj-y = registers.o task_size.o mcontext.o
+obj-y = registers.o mcontext.o
obj-$(CONFIG_X86_32) += tls.o
diff --git a/arch/x86/um/os-Linux/registers.c b/arch/x86/um/os-Linux/registers.c
index f3638dd09cec..76eaeb93928c 100644
--- a/arch/x86/um/os-Linux/registers.c
+++ b/arch/x86/um/os-Linux/registers.c
@@ -16,133 +16,58 @@
#include <asm/sigcontext.h>
#include <linux/elf.h>
#include <registers.h>
+#include <sys/mman.h>
-static int have_xstate_support;
+unsigned long host_fp_size;
-int save_i387_registers(int pid, unsigned long *fp_regs)
-{
- if (ptrace(PTRACE_GETFPREGS, pid, 0, fp_regs) < 0)
- return -errno;
- return 0;
-}
-
-int save_fp_registers(int pid, unsigned long *fp_regs)
+int get_fp_registers(int pid, unsigned long *regs)
{
-#ifdef PTRACE_GETREGSET
- struct iovec iov;
+ struct iovec iov = {
+ .iov_base = regs,
+ .iov_len = host_fp_size,
+ };
- if (have_xstate_support) {
- iov.iov_base = fp_regs;
- iov.iov_len = FP_SIZE * sizeof(unsigned long);
- if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
- return -errno;
- return 0;
- } else
-#endif
- return save_i387_registers(pid, fp_regs);
-}
-
-int restore_i387_registers(int pid, unsigned long *fp_regs)
-{
- if (ptrace(PTRACE_SETFPREGS, pid, 0, fp_regs) < 0)
+ if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
return -errno;
return 0;
}
-int restore_fp_registers(int pid, unsigned long *fp_regs)
-{
-#ifdef PTRACE_SETREGSET
- struct iovec iov;
- if (have_xstate_support) {
- iov.iov_base = fp_regs;
- iov.iov_len = FP_SIZE * sizeof(unsigned long);
- if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
- return -errno;
- return 0;
- } else
-#endif
- return restore_i387_registers(pid, fp_regs);
-}
-
-#ifdef __i386__
-int have_fpx_regs = 1;
-int save_fpx_registers(int pid, unsigned long *fp_regs)
+int put_fp_registers(int pid, unsigned long *regs)
{
- if (ptrace(PTRACE_GETFPXREGS, pid, 0, fp_regs) < 0)
- return -errno;
- return 0;
-}
+ struct iovec iov = {
+ .iov_base = regs,
+ .iov_len = host_fp_size,
+ };
-int restore_fpx_registers(int pid, unsigned long *fp_regs)
-{
- if (ptrace(PTRACE_SETFPXREGS, pid, 0, fp_regs) < 0)
+ if (ptrace(PTRACE_SETREGSET, pid, NT_X86_XSTATE, &iov) < 0)
return -errno;
return 0;
}
-int get_fp_registers(int pid, unsigned long *regs)
-{
- if (have_fpx_regs)
- return save_fpx_registers(pid, regs);
- else
- return save_fp_registers(pid, regs);
-}
-
-int put_fp_registers(int pid, unsigned long *regs)
-{
- if (have_fpx_regs)
- return restore_fpx_registers(pid, regs);
- else
- return restore_fp_registers(pid, regs);
-}
-
-void arch_init_registers(int pid)
-{
- struct user_fpxregs_struct fpx_regs;
- int err;
-
- err = ptrace(PTRACE_GETFPXREGS, pid, 0, &fpx_regs);
- if (!err)
- return;
-
- if (errno != EIO)
- panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d",
- errno);
-
- have_fpx_regs = 0;
-}
-#else
-
-int get_fp_registers(int pid, unsigned long *regs)
+int arch_init_registers(int pid)
{
- return save_fp_registers(pid, regs);
+ struct iovec iov = {
+ /* Just use plenty of space, it does not cost us anything */
+ .iov_len = 2 * 1024 * 1024,
+ };
+ int ret;
+
+ iov.iov_base = mmap(NULL, iov.iov_len, PROT_WRITE | PROT_READ,
+ MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+ if (iov.iov_base == MAP_FAILED)
+ return -ENOMEM;
+
+ /* GDB has x86_xsave_length, which uses x86_cpuid_count */
+ ret = ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov);
+ if (ret)
+ ret = -errno;
+ munmap(iov.iov_base, 2 * 1024 * 1024);
+
+ host_fp_size = iov.iov_len;
+
+ return ret;
}
-int put_fp_registers(int pid, unsigned long *regs)
-{
- return restore_fp_registers(pid, regs);
-}
-
-void arch_init_registers(int pid)
-{
-#ifdef PTRACE_GETREGSET
- void * fp_regs;
- struct iovec iov;
-
- fp_regs = malloc(FP_SIZE * sizeof(unsigned long));
- if(fp_regs == NULL)
- return;
-
- iov.iov_base = fp_regs;
- iov.iov_len = FP_SIZE * sizeof(unsigned long);
- if (ptrace(PTRACE_GETREGSET, pid, NT_X86_XSTATE, &iov) == 0)
- have_xstate_support = 1;
-
- free(fp_regs);
-#endif
-}
-#endif
-
unsigned long get_thread_reg(int reg, jmp_buf *buf)
{
switch (reg) {
diff --git a/arch/x86/um/os-Linux/task_size.c b/arch/x86/um/os-Linux/task_size.c
deleted file mode 100644
index 1dc9adc20b1c..000000000000
--- a/arch/x86/um/os-Linux/task_size.c
+++ /dev/null
@@ -1,151 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-#include <stdio.h>
-#include <stdlib.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <longjmp.h>
-
-#ifdef __i386__
-
-static jmp_buf buf;
-
-static void segfault(int sig)
-{
- longjmp(buf, 1);
-}
-
-static int page_ok(unsigned long page)
-{
- unsigned long *address = (unsigned long *) (page << UM_KERN_PAGE_SHIFT);
- unsigned long n = ~0UL;
- void *mapped = NULL;
- int ok = 0;
-
- /*
- * First see if the page is readable. If it is, it may still
- * be a VDSO, so we go on to see if it's writable. If not
- * then try mapping memory there. If that fails, then we're
- * still in the kernel area. As a sanity check, we'll fail if
- * the mmap succeeds, but gives us an address different from
- * what we wanted.
- */
- if (setjmp(buf) == 0)
- n = *address;
- else {
- mapped = mmap(address, UM_KERN_PAGE_SIZE,
- PROT_READ | PROT_WRITE,
- MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- if (mapped == MAP_FAILED)
- return 0;
- if (mapped != address)
- goto out;
- }
-
- /*
- * Now, is it writeable? If so, then we're in user address
- * space. If not, then try mprotecting it and try the write
- * again.
- */
- if (setjmp(buf) == 0) {
- *address = n;
- ok = 1;
- goto out;
- } else if (mprotect(address, UM_KERN_PAGE_SIZE,
- PROT_READ | PROT_WRITE) != 0)
- goto out;
-
- if (setjmp(buf) == 0) {
- *address = n;
- ok = 1;
- }
-
- out:
- if (mapped != NULL)
- munmap(mapped, UM_KERN_PAGE_SIZE);
- return ok;
-}
-
-unsigned long os_get_top_address(void)
-{
- struct sigaction sa, old;
- unsigned long bottom = 0;
- /*
- * A 32-bit UML on a 64-bit host gets confused about the VDSO at
- * 0xffffe000. It is mapped, is readable, can be reprotected writeable
- * and written. However, exec discovers later that it can't be
- * unmapped. So, just set the highest address to be checked to just
- * below it. This might waste some address space on 4G/4G 32-bit
- * hosts, but shouldn't hurt otherwise.
- */
- unsigned long top = 0xffffd000 >> UM_KERN_PAGE_SHIFT;
- unsigned long test, original;
-
- printf("Locating the bottom of the address space ... ");
- fflush(stdout);
-
- /*
- * We're going to be longjmping out of the signal handler, so
- * SA_DEFER needs to be set.
- */
- sa.sa_handler = segfault;
- sigemptyset(&sa.sa_mask);
- sa.sa_flags = SA_NODEFER;
- if (sigaction(SIGSEGV, &sa, &old)) {
- perror("os_get_top_address");
- exit(1);
- }
-
- /* Manually scan the address space, bottom-up, until we find
- * the first valid page (or run out of them).
- */
- for (bottom = 0; bottom < top; bottom++) {
- if (page_ok(bottom))
- break;
- }
-
- /* If we've got this far, we ran out of pages. */
- if (bottom == top) {
- fprintf(stderr, "Unable to determine bottom of address "
- "space.\n");
- exit(1);
- }
-
- printf("0x%lx\n", bottom << UM_KERN_PAGE_SHIFT);
- printf("Locating the top of the address space ... ");
- fflush(stdout);
-
- original = bottom;
-
- /* This could happen with a 4G/4G split */
- if (page_ok(top))
- goto out;
-
- do {
- test = bottom + (top - bottom) / 2;
- if (page_ok(test))
- bottom = test;
- else
- top = test;
- } while (top - bottom > 1);
-
-out:
- /* Restore the old SIGSEGV handling */
- if (sigaction(SIGSEGV, &old, NULL)) {
- perror("os_get_top_address");
- exit(1);
- }
- top <<= UM_KERN_PAGE_SHIFT;
- printf("0x%lx\n", top);
-
- return top;
-}
-
-#else
-
-unsigned long os_get_top_address(void)
-{
- /* The old value of CONFIG_TOP_ADDR */
- return 0x7fc0002000;
-}
-
-#endif
diff --git a/arch/x86/um/ptrace.c b/arch/x86/um/ptrace.c
new file mode 100644
index 000000000000..57c504fd5626
--- /dev/null
+++ b/arch/x86/um/ptrace.c
@@ -0,0 +1,267 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/sched.h>
+#include <linux/elf.h>
+#include <linux/regset.h>
+#include <asm/user32.h>
+#include <asm/sigcontext.h>
+
+#ifdef CONFIG_X86_32
+/*
+ * FPU tag word conversions.
+ */
+
+static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
+{
+ unsigned int tmp; /* to avoid 16 bit prefixes in the code */
+
+ /* Transform each pair of bits into 01 (valid) or 00 (empty) */
+ tmp = ~twd;
+ tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
+ /* and move the valid bits to the lower byte. */
+ tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
+ tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
+ tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
+ return tmp;
+}
+
+static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
+{
+ struct _fpxreg *st = NULL;
+ unsigned long twd = (unsigned long) fxsave->twd;
+ unsigned long tag;
+ unsigned long ret = 0xffff0000;
+ int i;
+
+#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16)
+
+ for (i = 0; i < 8; i++) {
+ if (twd & 0x1) {
+ st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
+
+ switch (st->exponent & 0x7fff) {
+ case 0x7fff:
+ tag = 2; /* Special */
+ break;
+ case 0x0000:
+ if (!st->significand[0] &&
+ !st->significand[1] &&
+ !st->significand[2] &&
+ !st->significand[3]) {
+ tag = 1; /* Zero */
+ } else {
+ tag = 2; /* Special */
+ }
+ break;
+ default:
+ if (st->significand[3] & 0x8000)
+ tag = 0; /* Valid */
+ else
+ tag = 2; /* Special */
+ break;
+ }
+ } else {
+ tag = 3; /* Empty */
+ }
+ ret |= (tag << (2 * i));
+ twd = twd >> 1;
+ }
+ return ret;
+}
+
+/* Get/set the old 32bit i387 registers (pre-FPX) */
+static int fpregs_legacy_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ struct user_fxsr_struct *fxsave = (void *)target->thread.regs.regs.fp;
+ int i;
+
+ membuf_store(&to, (unsigned long)fxsave->cwd | 0xffff0000ul);
+ membuf_store(&to, (unsigned long)fxsave->swd | 0xffff0000ul);
+ membuf_store(&to, twd_fxsr_to_i387(fxsave));
+ membuf_store(&to, fxsave->fip);
+ membuf_store(&to, fxsave->fcs | ((unsigned long)fxsave->fop << 16));
+ membuf_store(&to, fxsave->foo);
+ membuf_store(&to, fxsave->fos);
+
+ for (i = 0; i < 8; i++)
+ membuf_write(&to, (void *)fxsave->st_space + i * 16, 10);
+
+ return 0;
+}
+
+static int fpregs_legacy_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ struct user_fxsr_struct *fxsave = (void *)target->thread.regs.regs.fp;
+ const struct user_i387_struct *from;
+ struct user_i387_struct buf;
+ int i;
+
+ if (ubuf) {
+ if (copy_from_user(&buf, ubuf, sizeof(buf)))
+ return -EFAULT;
+ from = &buf;
+ } else {
+ from = kbuf;
+ }
+
+ fxsave->cwd = (unsigned short)(from->cwd & 0xffff);
+ fxsave->swd = (unsigned short)(from->swd & 0xffff);
+ fxsave->twd = twd_i387_to_fxsr((unsigned short)(from->twd & 0xffff));
+ fxsave->fip = from->fip;
+ fxsave->fop = (unsigned short)((from->fcs & 0xffff0000ul) >> 16);
+ fxsave->fcs = (from->fcs & 0xffff);
+ fxsave->foo = from->foo;
+ fxsave->fos = from->fos;
+
+ for (i = 0; i < 8; i++) {
+ memcpy((void *)fxsave->st_space + i * 16,
+ (void *)from->st_space + i * 10, 10);
+ }
+
+ return 0;
+}
+#endif
+
+static int genregs_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ int reg;
+
+ for (reg = 0; to.left; reg++)
+ membuf_store(&to, getreg(target, reg * sizeof(unsigned long)));
+ return 0;
+}
+
+static int genregs_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ int ret = 0;
+
+ if (kbuf) {
+ const unsigned long *k = kbuf;
+
+ while (count >= sizeof(*k) && !ret) {
+ ret = putreg(target, pos, *k++);
+ count -= sizeof(*k);
+ pos += sizeof(*k);
+ }
+ } else {
+ const unsigned long __user *u = ubuf;
+
+ while (count >= sizeof(*u) && !ret) {
+ unsigned long word;
+
+ ret = __get_user(word, u++);
+ if (ret)
+ break;
+ ret = putreg(target, pos, word);
+ count -= sizeof(*u);
+ pos += sizeof(*u);
+ }
+ }
+ return ret;
+}
+
+static int generic_fpregs_active(struct task_struct *target, const struct user_regset *regset)
+{
+ return regset->n;
+}
+
+static int generic_fpregs_get(struct task_struct *target,
+ const struct user_regset *regset,
+ struct membuf to)
+{
+ void *fpregs = task_pt_regs(target)->regs.fp;
+
+ membuf_write(&to, fpregs, regset->size * regset->n);
+ return 0;
+}
+
+static int generic_fpregs_set(struct task_struct *target,
+ const struct user_regset *regset,
+ unsigned int pos, unsigned int count,
+ const void *kbuf, const void __user *ubuf)
+{
+ void *fpregs = task_pt_regs(target)->regs.fp;
+
+ return user_regset_copyin(&pos, &count, &kbuf, &ubuf,
+ fpregs, 0, regset->size * regset->n);
+}
+
+static struct user_regset uml_regsets[] __ro_after_init = {
+ [REGSET_GENERAL] = {
+ .core_note_type = NT_PRSTATUS,
+ .n = sizeof(struct user_regs_struct) / sizeof(long),
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .regset_get = genregs_get,
+ .set = genregs_set
+ },
+#ifdef CONFIG_X86_32
+ /* Old FP registers, they are needed in signal frames */
+ [REGSET_FP_LEGACY] = {
+ .core_note_type = NT_PRFPREG,
+ .n = sizeof(struct user_i387_ia32_struct) / sizeof(long),
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .active = generic_fpregs_active,
+ .regset_get = fpregs_legacy_get,
+ .set = fpregs_legacy_set,
+ },
+#endif
+ [REGSET_FP] = {
+#ifdef CONFIG_X86_32
+ .core_note_type = NT_PRXFPREG,
+ .n = sizeof(struct user32_fxsr_struct) / sizeof(long),
+#else
+ .core_note_type = NT_PRFPREG,
+ .n = sizeof(struct user_i387_struct) / sizeof(long),
+#endif
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .active = generic_fpregs_active,
+ .regset_get = generic_fpregs_get,
+ .set = generic_fpregs_set,
+ },
+ [REGSET_XSTATE] = {
+ .core_note_type = NT_X86_XSTATE,
+ .size = sizeof(long),
+ .align = sizeof(long),
+ .active = generic_fpregs_active,
+ .regset_get = generic_fpregs_get,
+ .set = generic_fpregs_set,
+ },
+ /* TODO: Add TLS regset for 32bit */
+};
+
+static const struct user_regset_view user_uml_view = {
+#ifdef CONFIG_X86_32
+ .name = "i386", .e_machine = EM_386,
+#else
+ .name = "x86_64", .e_machine = EM_X86_64,
+#endif
+ .regsets = uml_regsets, .n = ARRAY_SIZE(uml_regsets)
+};
+
+const struct user_regset_view *
+task_user_regset_view(struct task_struct *tsk)
+{
+ return &user_uml_view;
+}
+
+static int __init init_regset_xstate_info(void)
+{
+ uml_regsets[REGSET_XSTATE].n =
+ host_fp_size / uml_regsets[REGSET_XSTATE].size;
+
+ return 0;
+}
+arch_initcall(init_regset_xstate_info);
diff --git a/arch/x86/um/ptrace_32.c b/arch/x86/um/ptrace_32.c
index b0a71c6cdc6e..3af3cb821524 100644
--- a/arch/x86/um/ptrace_32.c
+++ b/arch/x86/um/ptrace_32.c
@@ -6,6 +6,7 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
+#include <linux/regset.h>
#include <asm/ptrace-abi.h>
#include <registers.h>
#include <skas.h>
@@ -168,65 +169,6 @@ int peek_user(struct task_struct *child, long addr, long data)
return put_user(tmp, (unsigned long __user *) data);
}
-static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
- int err, n, cpu = task_cpu(child);
- struct user_i387_struct fpregs;
-
- err = save_i387_registers(userspace_pid[cpu],
- (unsigned long *) &fpregs);
- if (err)
- return err;
-
- n = copy_to_user(buf, &fpregs, sizeof(fpregs));
- if(n > 0)
- return -EFAULT;
-
- return n;
-}
-
-static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
- int n, cpu = task_cpu(child);
- struct user_i387_struct fpregs;
-
- n = copy_from_user(&fpregs, buf, sizeof(fpregs));
- if (n > 0)
- return -EFAULT;
-
- return restore_i387_registers(userspace_pid[cpu],
- (unsigned long *) &fpregs);
-}
-
-static int get_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
-{
- int err, n, cpu = task_cpu(child);
- struct user_fxsr_struct fpregs;
-
- err = save_fpx_registers(userspace_pid[cpu], (unsigned long *) &fpregs);
- if (err)
- return err;
-
- n = copy_to_user(buf, &fpregs, sizeof(fpregs));
- if(n > 0)
- return -EFAULT;
-
- return n;
-}
-
-static int set_fpxregs(struct user_fxsr_struct __user *buf, struct task_struct *child)
-{
- int n, cpu = task_cpu(child);
- struct user_fxsr_struct fpregs;
-
- n = copy_from_user(&fpregs, buf, sizeof(fpregs));
- if (n > 0)
- return -EFAULT;
-
- return restore_fpx_registers(userspace_pid[cpu],
- (unsigned long *) &fpregs);
-}
-
long subarch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
@@ -234,17 +176,25 @@ long subarch_ptrace(struct task_struct *child, long request,
void __user *datap = (void __user *) data;
switch (request) {
case PTRACE_GETFPREGS: /* Get the child FPU state. */
- ret = get_fpregs(datap, child);
- break;
+ return copy_regset_to_user(child, task_user_regset_view(child),
+ REGSET_FP_LEGACY,
+ 0, sizeof(struct user_i387_struct),
+ datap);
case PTRACE_SETFPREGS: /* Set the child FPU state. */
- ret = set_fpregs(datap, child);
- break;
+ return copy_regset_from_user(child, task_user_regset_view(child),
+ REGSET_FP_LEGACY,
+ 0, sizeof(struct user_i387_struct),
+ datap);
case PTRACE_GETFPXREGS: /* Get the child FPU state. */
- ret = get_fpxregs(datap, child);
- break;
+ return copy_regset_to_user(child, task_user_regset_view(child),
+ REGSET_FP,
+ 0, sizeof(struct user_fxsr_struct),
+ datap);
case PTRACE_SETFPXREGS: /* Set the child FPU state. */
- ret = set_fpxregs(datap, child);
- break;
+ return copy_regset_from_user(child, task_user_regset_view(child),
+ REGSET_FP,
+ 0, sizeof(struct user_fxsr_struct),
+ datap);
default:
ret = -EIO;
}
diff --git a/arch/x86/um/ptrace_64.c b/arch/x86/um/ptrace_64.c
index aa68d83d3f44..e0d4120a45c8 100644
--- a/arch/x86/um/ptrace_64.c
+++ b/arch/x86/um/ptrace_64.c
@@ -8,6 +8,7 @@
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/errno.h>
+#include <linux/regset.h>
#define __FRAME_OFFSETS
#include <asm/ptrace.h>
#include <linux/uaccess.h>
@@ -188,36 +189,6 @@ int peek_user(struct task_struct *child, long addr, long data)
return put_user(tmp, (unsigned long *) data);
}
-static int get_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
- int err, n, cpu = ((struct thread_info *) child->stack)->cpu;
- struct user_i387_struct fpregs;
-
- err = save_i387_registers(userspace_pid[cpu],
- (unsigned long *) &fpregs);
- if (err)
- return err;
-
- n = copy_to_user(buf, &fpregs, sizeof(fpregs));
- if (n > 0)
- return -EFAULT;
-
- return n;
-}
-
-static int set_fpregs(struct user_i387_struct __user *buf, struct task_struct *child)
-{
- int n, cpu = ((struct thread_info *) child->stack)->cpu;
- struct user_i387_struct fpregs;
-
- n = copy_from_user(&fpregs, buf, sizeof(fpregs));
- if (n > 0)
- return -EFAULT;
-
- return restore_i387_registers(userspace_pid[cpu],
- (unsigned long *) &fpregs);
-}
-
long subarch_ptrace(struct task_struct *child, long request,
unsigned long addr, unsigned long data)
{
@@ -226,11 +197,15 @@ long subarch_ptrace(struct task_struct *child, long request,
switch (request) {
case PTRACE_GETFPREGS: /* Get the child FPU state. */
- ret = get_fpregs(datap, child);
- break;
+ return copy_regset_to_user(child, task_user_regset_view(child),
+ REGSET_FP,
+ 0, sizeof(struct user_i387_struct),
+ datap);
case PTRACE_SETFPREGS: /* Set the child FPU state. */
- ret = set_fpregs(datap, child);
- break;
+ return copy_regset_from_user(child, task_user_regset_view(child),
+ REGSET_FP,
+ 0, sizeof(struct user_i387_struct),
+ datap);
case PTRACE_ARCH_PRCTL:
/* XXX Calls ptrace on the host - needs some SMP thinking */
ret = arch_prctl(child, data, (void __user *) addr);
diff --git a/arch/x86/um/shared/sysdep/ptrace.h b/arch/x86/um/shared/sysdep/ptrace.h
index 6ca4ecabc55b..2dd4ca6713f8 100644
--- a/arch/x86/um/shared/sysdep/ptrace.h
+++ b/arch/x86/um/shared/sysdep/ptrace.h
@@ -56,12 +56,16 @@ struct syscall_args {
UPT_SYSCALL_ARG5(r), \
UPT_SYSCALL_ARG6(r) } } )
+extern unsigned long host_fp_size;
+
struct uml_pt_regs {
unsigned long gp[MAX_REG_NR];
- unsigned long fp[MAX_FP_NR];
struct faultinfo faultinfo;
long syscall;
int is_user;
+
+ /* Dynamically sized FP registers (holds an XSTATE) */
+ unsigned long fp[];
};
#define EMPTY_UML_PT_REGS { }
@@ -72,4 +76,6 @@ struct uml_pt_regs {
extern int user_context(unsigned long sp);
+extern int arch_init_registers(int pid);
+
#endif /* __SYSDEP_X86_PTRACE_H */
diff --git a/arch/x86/um/shared/sysdep/ptrace_32.h b/arch/x86/um/shared/sysdep/ptrace_32.h
index 0c4989842fbe..2392470cac4d 100644
--- a/arch/x86/um/shared/sysdep/ptrace_32.h
+++ b/arch/x86/um/shared/sysdep/ptrace_32.h
@@ -6,8 +6,6 @@
#ifndef __SYSDEP_I386_PTRACE_H
#define __SYSDEP_I386_PTRACE_H
-#define MAX_FP_NR HOST_FPX_SIZE
-
#define UPT_SYSCALL_ARG1(r) UPT_BX(r)
#define UPT_SYSCALL_ARG2(r) UPT_CX(r)
#define UPT_SYSCALL_ARG3(r) UPT_DX(r)
@@ -15,6 +13,4 @@
#define UPT_SYSCALL_ARG5(r) UPT_DI(r)
#define UPT_SYSCALL_ARG6(r) UPT_BP(r)
-extern void arch_init_registers(int pid);
-
#endif
diff --git a/arch/x86/um/shared/sysdep/ptrace_64.h b/arch/x86/um/shared/sysdep/ptrace_64.h
index 0dc223aa1c2d..e73573ac871f 100644
--- a/arch/x86/um/shared/sysdep/ptrace_64.h
+++ b/arch/x86/um/shared/sysdep/ptrace_64.h
@@ -8,8 +8,6 @@
#ifndef __SYSDEP_X86_64_PTRACE_H
#define __SYSDEP_X86_64_PTRACE_H
-#define MAX_FP_NR HOST_FP_SIZE
-
#define REGS_R8(r) ((r)[HOST_R8])
#define REGS_R9(r) ((r)[HOST_R9])
#define REGS_R10(r) ((r)[HOST_R10])
@@ -57,6 +55,4 @@
#define UPT_SYSCALL_ARG5(r) UPT_R8(r)
#define UPT_SYSCALL_ARG6(r) UPT_R9(r)
-extern void arch_init_registers(int pid);
-
#endif
diff --git a/arch/x86/um/shared/sysdep/ptrace_user.h b/arch/x86/um/shared/sysdep/ptrace_user.h
index 1d1a824fa652..98da23120538 100644
--- a/arch/x86/um/shared/sysdep/ptrace_user.h
+++ b/arch/x86/um/shared/sysdep/ptrace_user.h
@@ -11,12 +11,6 @@
#define REGS_IP_INDEX HOST_IP
#define REGS_SP_INDEX HOST_SP
-#ifdef __i386__
-#define FP_SIZE ((HOST_FPX_SIZE > HOST_FP_SIZE) ? HOST_FPX_SIZE : HOST_FP_SIZE)
-#else
-#define FP_SIZE HOST_FP_SIZE
-#endif
-
/*
* glibc before 2.27 does not include PTRACE_SYSEMU_SINGLESTEP in its enum,
* ensure we have a definition by (re-)defining it here.
diff --git a/arch/x86/um/shared/sysdep/stub_32.h b/arch/x86/um/shared/sysdep/stub_32.h
index 0b44a86dd346..390988132c0a 100644
--- a/arch/x86/um/shared/sysdep/stub_32.h
+++ b/arch/x86/um/shared/sysdep/stub_32.h
@@ -112,11 +112,23 @@ static __always_inline void *get_stub_data(void)
unsigned long ret;
asm volatile (
- "movl %%esp,%0 ;"
- "andl %1,%0"
+ "call _here_%=;"
+ "_here_%=:"
+ "popl %0;"
+ "andl %1, %0 ;"
+ "addl %2, %0 ;"
: "=a" (ret)
- : "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)));
+ : "g" (~(UM_KERN_PAGE_SIZE - 1)),
+ "g" (UM_KERN_PAGE_SIZE));
return (void *)ret;
}
+
+#define stub_start(fn) \
+ asm volatile ( \
+ "subl %0,%%esp ;" \
+ "movl %1, %%eax ; " \
+ "call *%%eax ;" \
+ :: "i" ((1 + STUB_DATA_PAGES) * UM_KERN_PAGE_SIZE), \
+ "i" (&fn))
#endif
diff --git a/arch/x86/um/shared/sysdep/stub_64.h b/arch/x86/um/shared/sysdep/stub_64.h
index 67f44284f1aa..294affbec742 100644
--- a/arch/x86/um/shared/sysdep/stub_64.h
+++ b/arch/x86/um/shared/sysdep/stub_64.h
@@ -28,6 +28,17 @@ static __always_inline long stub_syscall0(long syscall)
return ret;
}
+static __always_inline long stub_syscall1(long syscall, long arg1)
+{
+ long ret;
+
+ __asm__ volatile (__syscall
+ : "=a" (ret)
+ : "0" (syscall), "D" (arg1) : __syscall_clobber );
+
+ return ret;
+}
+
static __always_inline long stub_syscall2(long syscall, long arg1, long arg2)
{
long ret;
@@ -106,11 +117,21 @@ static __always_inline void *get_stub_data(void)
unsigned long ret;
asm volatile (
- "movq %%rsp,%0 ;"
- "andq %1,%0"
+ "lea 0(%%rip), %0;"
+ "andq %1, %0 ;"
+ "addq %2, %0 ;"
: "=a" (ret)
- : "g" (~(STUB_DATA_PAGES * UM_KERN_PAGE_SIZE - 1)));
+ : "g" (~(UM_KERN_PAGE_SIZE - 1)),
+ "g" (UM_KERN_PAGE_SIZE));
return (void *)ret;
}
+
+#define stub_start(fn) \
+ asm volatile ( \
+ "subq %0,%%rsp ;" \
+ "movq %1,%%rax ;" \
+ "call *%%rax ;" \
+ :: "i" ((1 + STUB_DATA_PAGES) * UM_KERN_PAGE_SIZE), \
+ "i" (&fn))
#endif
diff --git a/arch/x86/um/signal.c b/arch/x86/um/signal.c
index 2cc8c2309022..75087e85b6fd 100644
--- a/arch/x86/um/signal.c
+++ b/arch/x86/um/signal.c
@@ -16,145 +16,24 @@
#include <registers.h>
#include <skas.h>
-#ifdef CONFIG_X86_32
-
-/*
- * FPU tag word conversions.
- */
-
-static inline unsigned short twd_i387_to_fxsr(unsigned short twd)
-{
- unsigned int tmp; /* to avoid 16 bit prefixes in the code */
-
- /* Transform each pair of bits into 01 (valid) or 00 (empty) */
- tmp = ~twd;
- tmp = (tmp | (tmp>>1)) & 0x5555; /* 0V0V0V0V0V0V0V0V */
- /* and move the valid bits to the lower byte. */
- tmp = (tmp | (tmp >> 1)) & 0x3333; /* 00VV00VV00VV00VV */
- tmp = (tmp | (tmp >> 2)) & 0x0f0f; /* 0000VVVV0000VVVV */
- tmp = (tmp | (tmp >> 4)) & 0x00ff; /* 00000000VVVVVVVV */
- return tmp;
-}
-
-static inline unsigned long twd_fxsr_to_i387(struct user_fxsr_struct *fxsave)
-{
- struct _fpxreg *st = NULL;
- unsigned long twd = (unsigned long) fxsave->twd;
- unsigned long tag;
- unsigned long ret = 0xffff0000;
- int i;
-
-#define FPREG_ADDR(f, n) ((char *)&(f)->st_space + (n) * 16)
-
- for (i = 0; i < 8; i++) {
- if (twd & 0x1) {
- st = (struct _fpxreg *) FPREG_ADDR(fxsave, i);
-
- switch (st->exponent & 0x7fff) {
- case 0x7fff:
- tag = 2; /* Special */
- break;
- case 0x0000:
- if ( !st->significand[0] &&
- !st->significand[1] &&
- !st->significand[2] &&
- !st->significand[3] ) {
- tag = 1; /* Zero */
- } else {
- tag = 2; /* Special */
- }
- break;
- default:
- if (st->significand[3] & 0x8000) {
- tag = 0; /* Valid */
- } else {
- tag = 2; /* Special */
- }
- break;
- }
- } else {
- tag = 3; /* Empty */
- }
- ret |= (tag << (2 * i));
- twd = twd >> 1;
- }
- return ret;
-}
-
-static int convert_fxsr_to_user(struct _fpstate __user *buf,
- struct user_fxsr_struct *fxsave)
-{
- unsigned long env[7];
- struct _fpreg __user *to;
- struct _fpxreg *from;
- int i;
-
- env[0] = (unsigned long)fxsave->cwd | 0xffff0000ul;
- env[1] = (unsigned long)fxsave->swd | 0xffff0000ul;
- env[2] = twd_fxsr_to_i387(fxsave);
- env[3] = fxsave->fip;
- env[4] = fxsave->fcs | ((unsigned long)fxsave->fop << 16);
- env[5] = fxsave->foo;
- env[6] = fxsave->fos;
-
- if (__copy_to_user(buf, env, 7 * sizeof(unsigned long)))
- return 1;
-
- to = &buf->_st[0];
- from = (struct _fpxreg *) &fxsave->st_space[0];
- for (i = 0; i < 8; i++, to++, from++) {
- unsigned long __user *t = (unsigned long __user *)to;
- unsigned long *f = (unsigned long *)from;
-
- if (__put_user(*f, t) ||
- __put_user(*(f + 1), t + 1) ||
- __put_user(from->exponent, &to->exponent))
- return 1;
- }
- return 0;
-}
-
-static int convert_fxsr_from_user(struct user_fxsr_struct *fxsave,
- struct _fpstate __user *buf)
-{
- unsigned long env[7];
- struct _fpxreg *to;
- struct _fpreg __user *from;
- int i;
-
- if (copy_from_user( env, buf, 7 * sizeof(long)))
- return 1;
-
- fxsave->cwd = (unsigned short)(env[0] & 0xffff);
- fxsave->swd = (unsigned short)(env[1] & 0xffff);
- fxsave->twd = twd_i387_to_fxsr((unsigned short)(env[2] & 0xffff));
- fxsave->fip = env[3];
- fxsave->fop = (unsigned short)((env[4] & 0xffff0000ul) >> 16);
- fxsave->fcs = (env[4] & 0xffff);
- fxsave->foo = env[5];
- fxsave->fos = env[6];
-
- to = (struct _fpxreg *) &fxsave->st_space[0];
- from = &buf->_st[0];
- for (i = 0; i < 8; i++, to++, from++) {
- unsigned long *t = (unsigned long *)to;
- unsigned long __user *f = (unsigned long __user *)from;
-
- if (__get_user(*t, f) ||
- __get_user(*(t + 1), f + 1) ||
- __get_user(to->exponent, &from->exponent))
- return 1;
- }
- return 0;
-}
-
-extern int have_fpx_regs;
+#include <linux/regset.h>
+#include <asm/sigframe.h>
+#ifdef CONFIG_X86_32
+struct _xstate_64 {
+ struct _fpstate_64 fpstate;
+ struct _header xstate_hdr;
+ struct _ymmh_state ymmh;
+ /* New processor state extensions go here: */
+};
+#else
+#define _xstate_64 _xstate
#endif
static int copy_sc_from_user(struct pt_regs *regs,
struct sigcontext __user *from)
{
+ struct _xstate_64 __user *from_fp64;
struct sigcontext sc;
int err;
@@ -203,35 +82,27 @@ static int copy_sc_from_user(struct pt_regs *regs,
#undef GETREG
#ifdef CONFIG_X86_32
- if (have_fpx_regs) {
- struct user_fxsr_struct fpx;
- int pid = userspace_pid[current_thread_info()->cpu];
+ from_fp64 = ((void __user *)sc.fpstate) +
+ offsetof(struct _fpstate_32, _fxsr_env);
+#else
+ from_fp64 = (void __user *)sc.fpstate;
+#endif
- err = copy_from_user(&fpx,
- &((struct _fpstate __user *)sc.fpstate)->_fxsr_env[0],
- sizeof(struct user_fxsr_struct));
- if (err)
- return 1;
+ err = copy_from_user(regs->regs.fp, from_fp64, host_fp_size);
+ if (err)
+ return 1;
- err = convert_fxsr_from_user(&fpx, (void *)sc.fpstate);
- if (err)
- return 1;
-
- err = restore_fpx_registers(pid, (unsigned long *) &fpx);
- if (err < 0) {
- printk(KERN_ERR "copy_sc_from_user - "
- "restore_fpx_registers failed, errno = %d\n",
- -err);
- return 1;
- }
- } else
+#ifdef CONFIG_X86_32
+ /* Data is duplicated and this copy is the important one */
+ err = copy_regset_from_user(current,
+ task_user_regset_view(current),
+ REGSET_FP_LEGACY, 0,
+ sizeof(struct user_i387_struct),
+ (void __user *)sc.fpstate);
+ if (err < 0)
+ return err;
#endif
- {
- err = copy_from_user(regs->regs.fp, (void *)sc.fpstate,
- sizeof(struct _xstate));
- if (err)
- return 1;
- }
+
return 0;
}
@@ -239,6 +110,7 @@ static int copy_sc_to_user(struct sigcontext __user *to,
struct _xstate __user *to_fp, struct pt_regs *regs,
unsigned long mask)
{
+ struct _xstate_64 __user *to_fp64;
struct sigcontext sc;
struct faultinfo * fi = &current->thread.arch.faultinfo;
int err;
@@ -290,35 +162,46 @@ static int copy_sc_to_user(struct sigcontext __user *to,
return 1;
#ifdef CONFIG_X86_32
- if (have_fpx_regs) {
- int pid = userspace_pid[current_thread_info()->cpu];
- struct user_fxsr_struct fpx;
-
- err = save_fpx_registers(pid, (unsigned long *) &fpx);
- if (err < 0){
- printk(KERN_ERR "copy_sc_to_user - save_fpx_registers "
- "failed, errno = %d\n", err);
- return 1;
- }
-
- err = convert_fxsr_to_user(&to_fp->fpstate, &fpx);
- if (err)
- return 1;
+ err = copy_regset_to_user(current,
+ task_user_regset_view(current),
+ REGSET_FP_LEGACY, 0,
+ sizeof(struct _fpstate_32), to_fp);
+ if (err < 0)
+ return err;
- err |= __put_user(fpx.swd, &to_fp->fpstate.status);
- err |= __put_user(X86_FXSR_MAGIC, &to_fp->fpstate.magic);
- if (err)
- return 1;
+ __put_user(X86_FXSR_MAGIC, &to_fp->fpstate.magic);
+
+ BUILD_BUG_ON(offsetof(struct _xstate, xstate_hdr) !=
+ offsetof(struct _xstate_64, xstate_hdr) +
+ offsetof(struct _fpstate_32, _fxsr_env));
+ to_fp64 = (void __user *)to_fp +
+ offsetof(struct _fpstate_32, _fxsr_env);
+#else
+ to_fp64 = to_fp;
+#endif /* CONFIG_X86_32 */
+
+ if (copy_to_user(to_fp64, regs->regs.fp, host_fp_size))
+ return 1;
- if (copy_to_user(&to_fp->fpstate._fxsr_env[0], &fpx,
- sizeof(struct user_fxsr_struct)))
- return 1;
- } else
+ /*
+ * Put magic/size values for userspace. We do not bother to verify them
+ * later on, however, userspace needs them should it try to read the
+ * XSTATE data. And ptrace does not fill in these parts.
+ */
+ BUILD_BUG_ON(sizeof(int) != FP_XSTATE_MAGIC2_SIZE);
+#ifdef CONFIG_X86_32
+ __put_user(offsetof(struct _fpstate_32, _fxsr_env) +
+ host_fp_size + FP_XSTATE_MAGIC2_SIZE,
+ &to_fp64->fpstate.sw_reserved.extended_size);
+#else
+ __put_user(host_fp_size + FP_XSTATE_MAGIC2_SIZE,
+ &to_fp64->fpstate.sw_reserved.extended_size);
#endif
- {
- if (copy_to_user(to_fp, regs->regs.fp, sizeof(struct _xstate)))
- return 1;
- }
+ __put_user(host_fp_size, &to_fp64->fpstate.sw_reserved.xstate_size);
+
+ __put_user(FP_XSTATE_MAGIC1, &to_fp64->fpstate.sw_reserved.magic1);
+ __put_user(FP_XSTATE_MAGIC2,
+ (int __user *)((void __user *)to_fp64 + host_fp_size));
return 0;
}
@@ -336,34 +219,15 @@ static int copy_ucontext_to_user(struct ucontext __user *uc,
return err;
}
-struct sigframe
-{
- char __user *pretcode;
- int sig;
- struct sigcontext sc;
- struct _xstate fpstate;
- unsigned long extramask[_NSIG_WORDS-1];
- char retcode[8];
-};
-
-struct rt_sigframe
-{
- char __user *pretcode;
- int sig;
- struct siginfo __user *pinfo;
- void __user *puc;
- struct siginfo info;
- struct ucontext uc;
- struct _xstate fpstate;
- char retcode[8];
-};
-
int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *mask)
{
+ size_t math_size = offsetof(struct _fpstate_32, _fxsr_env) +
+ host_fp_size + FP_XSTATE_MAGIC2_SIZE;
struct sigframe __user *frame;
void __user *restorer;
int err = 0, sig = ksig->sig;
+ unsigned long fp_to;
/* This is the same calculation as i386 - ((sp + 4) & 15) == 0 */
stack_top = ((stack_top + 4) & -16UL) - 4;
@@ -371,13 +235,21 @@ int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
if (!access_ok(frame, sizeof(*frame)))
return 1;
+ /* Add required space for math frame */
+ frame = (struct sigframe __user *)((unsigned long)frame - math_size);
+
restorer = frame->retcode;
if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = ksig->ka.sa.sa_restorer;
- err |= __put_user(restorer, &frame->pretcode);
+ err |= __put_user(restorer, (void __user * __user *)&frame->pretcode);
err |= __put_user(sig, &frame->sig);
- err |= copy_sc_to_user(&frame->sc, &frame->fpstate, regs, mask->sig[0]);
+
+ fp_to = (unsigned long)frame + sizeof(*frame);
+
+ err |= copy_sc_to_user(&frame->sc,
+ (struct _xstate __user *)fp_to,
+ regs, mask->sig[0]);
if (_NSIG_WORDS > 1)
err |= __copy_to_user(&frame->extramask, &mask->sig[1],
sizeof(frame->extramask));
@@ -407,26 +279,35 @@ int setup_signal_stack_sc(unsigned long stack_top, struct ksignal *ksig,
int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *mask)
{
+ size_t math_size = offsetof(struct _fpstate_32, _fxsr_env) +
+ host_fp_size + FP_XSTATE_MAGIC2_SIZE;
struct rt_sigframe __user *frame;
void __user *restorer;
int err = 0, sig = ksig->sig;
+ unsigned long fp_to;
stack_top &= -8UL;
frame = (struct rt_sigframe __user *) stack_top - 1;
if (!access_ok(frame, sizeof(*frame)))
return 1;
+ /* Add required space for math frame */
+ frame = (struct rt_sigframe __user *)((unsigned long)frame - math_size);
+
restorer = frame->retcode;
if (ksig->ka.sa.sa_flags & SA_RESTORER)
restorer = ksig->ka.sa.sa_restorer;
- err |= __put_user(restorer, &frame->pretcode);
+ err |= __put_user(restorer, (void __user * __user *)&frame->pretcode);
err |= __put_user(sig, &frame->sig);
- err |= __put_user(&frame->info, &frame->pinfo);
- err |= __put_user(&frame->uc, &frame->puc);
+ err |= __put_user(&frame->info, (void __user * __user *)&frame->pinfo);
+ err |= __put_user(&frame->uc, (void __user * __user *)&frame->puc);
err |= copy_siginfo_to_user(&frame->info, &ksig->info);
- err |= copy_ucontext_to_user(&frame->uc, &frame->fpstate, mask,
- PT_REGS_SP(regs));
+
+ fp_to = (unsigned long)frame + sizeof(*frame);
+
+ err |= copy_ucontext_to_user(&frame->uc, (struct _xstate __user *)fp_to,
+ mask, PT_REGS_SP(regs));
/*
* This is movl $,%eax ; int $0x80
@@ -478,27 +359,24 @@ SYSCALL_DEFINE0(sigreturn)
#else
-struct rt_sigframe
-{
- char __user *pretcode;
- struct ucontext uc;
- struct siginfo info;
- struct _xstate fpstate;
-};
-
int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
struct pt_regs *regs, sigset_t *set)
{
+ unsigned long math_size = host_fp_size + FP_XSTATE_MAGIC2_SIZE;
struct rt_sigframe __user *frame;
int err = 0, sig = ksig->sig;
unsigned long fp_to;
frame = (struct rt_sigframe __user *)
round_down(stack_top - sizeof(struct rt_sigframe), 16);
+
+ /* Add required space for math frame */
+ frame = (struct rt_sigframe __user *)((unsigned long)frame - math_size);
+
/* Subtract 128 for a red zone and 8 for proper alignment */
frame = (struct rt_sigframe __user *) ((unsigned long) frame - 128 - 8);
- if (!access_ok(frame, sizeof(*frame)))
+ if (!access_ok(frame, sizeof(*frame) + math_size))
goto out;
if (ksig->ka.sa.sa_flags & SA_SIGINFO) {
@@ -509,12 +387,14 @@ int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
/* Create the ucontext. */
err |= __put_user(0, &frame->uc.uc_flags);
- err |= __put_user(0, &frame->uc.uc_link);
+ err |= __put_user(NULL, &frame->uc.uc_link);
err |= __save_altstack(&frame->uc.uc_stack, PT_REGS_SP(regs));
- err |= copy_sc_to_user(&frame->uc.uc_mcontext, &frame->fpstate, regs,
- set->sig[0]);
- fp_to = (unsigned long)&frame->fpstate;
+ fp_to = (unsigned long)frame + sizeof(*frame);
+
+ err |= copy_sc_to_user(&frame->uc.uc_mcontext,
+ (struct _xstate __user *)fp_to,
+ regs, set->sig[0]);
err |= __put_user(fp_to, &frame->uc.uc_mcontext.fpstate);
if (sizeof(*set) == 16) {
@@ -531,7 +411,7 @@ int setup_signal_stack_si(unsigned long stack_top, struct ksignal *ksig,
*/
/* x86-64 should always use SA_RESTORER. */
if (ksig->ka.sa.sa_flags & SA_RESTORER)
- err |= __put_user((void *)ksig->ka.sa.sa_restorer,
+ err |= __put_user((void __user *)ksig->ka.sa.sa_restorer,
&frame->pretcode);
else
/* could use a vstub here */
diff --git a/arch/x86/um/user-offsets.c b/arch/x86/um/user-offsets.c
index 1c77d9946199..d6e1cd9956bf 100644
--- a/arch/x86/um/user-offsets.c
+++ b/arch/x86/um/user-offsets.c
@@ -20,9 +20,6 @@ void foo(void);
void foo(void)
{
#ifdef __i386__
- DEFINE_LONGS(HOST_FP_SIZE, sizeof(struct user_fpregs_struct));
- DEFINE_LONGS(HOST_FPX_SIZE, sizeof(struct user_fpxregs_struct));
-
DEFINE(HOST_IP, EIP);
DEFINE(HOST_SP, UESP);
DEFINE(HOST_EFLAGS, EFL);
@@ -41,11 +38,6 @@ void foo(void)
DEFINE(HOST_GS, GS);
DEFINE(HOST_ORIG_AX, ORIG_EAX);
#else
-#ifdef FP_XSTATE_MAGIC1
- DEFINE_LONGS(HOST_FP_SIZE, 2696);
-#else
- DEFINE(HOST_FP_SIZE, sizeof(struct _fpstate) / sizeof(unsigned long));
-#endif
DEFINE_LONGS(HOST_BX, RBX);
DEFINE_LONGS(HOST_CX, RCX);
DEFINE_LONGS(HOST_DI, RDI);
diff --git a/arch/x86/um/vdso/Makefile b/arch/x86/um/vdso/Makefile
index 6a77ea6434ff..7478d11dacb7 100644
--- a/arch/x86/um/vdso/Makefile
+++ b/arch/x86/um/vdso/Makefile
@@ -56,7 +56,6 @@ CFLAGS_REMOVE_um_vdso.o = -pg -fprofile-arcs -ftest-coverage
quiet_cmd_vdso = VDSO $@
cmd_vdso = $(CC) -nostdlib -o $@ \
$(CC_FLAGS_LTO) $(VDSO_LDFLAGS) $(VDSO_LDFLAGS_$(filter %.lds,$(^F))) \
- -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^) && \
- sh $(src)/checkundef.sh '$(NM)' '$@'
+ -Wl,-T,$(filter %.lds,$^) $(filter %.o,$^)
-VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv -z noexecstack
+VDSO_LDFLAGS = -fPIC -shared -Wl,--hash-style=sysv -z noexecstack -Wl,--no-undefined
diff --git a/arch/x86/um/vdso/checkundef.sh b/arch/x86/um/vdso/checkundef.sh
deleted file mode 100644
index 8e3ea6bb956f..000000000000
--- a/arch/x86/um/vdso/checkundef.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/bin/sh
-# SPDX-License-Identifier: GPL-2.0
-nm="$1"
-file="$2"
-$nm "$file" | grep '^ *U' > /dev/null 2>&1
-if [ $? -eq 1 ]; then
- exit 0
-else
- echo "$file: undefined symbols found" >&2
- exit 1
-fi
diff --git a/arch/x86/xen/enlighten.c b/arch/x86/xen/enlighten.c
index 84e5adbd0925..43dcd8c7badc 100644
--- a/arch/x86/xen/enlighten.c
+++ b/arch/x86/xen/enlighten.c
@@ -2,6 +2,7 @@
#include <linux/console.h>
#include <linux/cpu.h>
+#include <linux/instrumentation.h>
#include <linux/kexec.h>
#include <linux/memblock.h>
#include <linux/slab.h>
@@ -21,7 +22,8 @@
#include "xen-ops.h"
-EXPORT_SYMBOL_GPL(hypercall_page);
+DEFINE_STATIC_CALL(xen_hypercall, xen_hypercall_hvm);
+EXPORT_STATIC_CALL_TRAMP(xen_hypercall);
/*
* Pointer to the xen_vcpu_info structure or
@@ -68,6 +70,67 @@ EXPORT_SYMBOL(xen_start_flags);
*/
struct shared_info *HYPERVISOR_shared_info = &xen_dummy_shared_info;
+static __ref void xen_get_vendor(void)
+{
+ init_cpu_devs();
+ cpu_detect(&boot_cpu_data);
+ get_cpu_vendor(&boot_cpu_data);
+}
+
+void xen_hypercall_setfunc(void)
+{
+ if (static_call_query(xen_hypercall) != xen_hypercall_hvm)
+ return;
+
+ if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
+ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON))
+ static_call_update(xen_hypercall, xen_hypercall_amd);
+ else
+ static_call_update(xen_hypercall, xen_hypercall_intel);
+}
+
+/*
+ * Evaluate processor vendor in order to select the correct hypercall
+ * function for HVM/PVH guests.
+ * Might be called very early in boot before vendor has been set by
+ * early_cpu_init().
+ */
+noinstr void *__xen_hypercall_setfunc(void)
+{
+ void (*func)(void);
+
+ /*
+ * Xen is supported only on CPUs with CPUID, so testing for
+ * X86_FEATURE_CPUID is a test for early_cpu_init() having been
+ * run.
+ *
+ * Note that __xen_hypercall_setfunc() is noinstr only due to a nasty
+ * dependency chain: it is being called via the xen_hypercall static
+ * call when running as a PVH or HVM guest. Hypercalls need to be
+ * noinstr due to PV guests using hypercalls in noinstr code. So we
+ * can safely tag the function body as "instrumentation ok", since
+ * the PV guest requirement is not of interest here (xen_get_vendor()
+ * calls noinstr functions, and static_call_update_early() might do
+ * so, too).
+ */
+ instrumentation_begin();
+
+ if (!boot_cpu_has(X86_FEATURE_CPUID))
+ xen_get_vendor();
+
+ if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD ||
+ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON))
+ func = xen_hypercall_amd;
+ else
+ func = xen_hypercall_intel;
+
+ static_call_update_early(xen_hypercall, func);
+
+ instrumentation_end();
+
+ return func;
+}
+
static int xen_cpu_up_online(unsigned int cpu)
{
xen_init_lock_cpu(cpu);
diff --git a/arch/x86/xen/enlighten_hvm.c b/arch/x86/xen/enlighten_hvm.c
index 24d2957a4726..fe57ff85d004 100644
--- a/arch/x86/xen/enlighten_hvm.c
+++ b/arch/x86/xen/enlighten_hvm.c
@@ -106,15 +106,8 @@ static void __init init_hvm_pv_info(void)
/* PVH set up hypercall page in xen_prepare_pvh(). */
if (xen_pvh_domain())
pv_info.name = "Xen PVH";
- else {
- u64 pfn;
- uint32_t msr;
-
+ else
pv_info.name = "Xen HVM";
- msr = cpuid_ebx(base + 2);
- pfn = __pa(hypercall_page);
- wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
- }
xen_setup_features();
@@ -300,6 +293,10 @@ static uint32_t __init xen_platform_hvm(void)
if (xen_pv_domain())
return 0;
+ /* Set correct hypercall function. */
+ if (xen_domain)
+ xen_hypercall_setfunc();
+
if (xen_pvh_domain() && nopv) {
/* Guest booting via the Xen-PVH boot entry goes here */
pr_info("\"nopv\" parameter is ignored in PVH guest\n");
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
index d6818c6cafda..a8eb7e0c473c 100644
--- a/arch/x86/xen/enlighten_pv.c
+++ b/arch/x86/xen/enlighten_pv.c
@@ -1341,6 +1341,9 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
xen_domain_type = XEN_PV_DOMAIN;
xen_start_flags = xen_start_info->flags;
+ /* Interrupts are guaranteed to be off initially. */
+ early_boot_irqs_disabled = true;
+ static_call_update_early(xen_hypercall, xen_hypercall_pv);
xen_setup_features();
@@ -1431,7 +1434,6 @@ asmlinkage __visible void __init xen_start_kernel(struct start_info *si)
WARN_ON(xen_cpuhp_setup(xen_cpu_up_prepare_pv, xen_cpu_dead_pv));
local_irq_disable();
- early_boot_irqs_disabled = true;
xen_raw_console_write("mapping kernel into physical memory\n");
xen_setup_kernel_pagetable((pgd_t *)xen_start_info->pt_base,
diff --git a/arch/x86/xen/enlighten_pvh.c b/arch/x86/xen/enlighten_pvh.c
index bf68c329fc01..0e3d930bcb89 100644
--- a/arch/x86/xen/enlighten_pvh.c
+++ b/arch/x86/xen/enlighten_pvh.c
@@ -129,17 +129,10 @@ static void __init pvh_arch_setup(void)
void __init xen_pvh_init(struct boot_params *boot_params)
{
- u32 msr;
- u64 pfn;
-
xen_pvh = 1;
xen_domain_type = XEN_HVM_DOMAIN;
xen_start_flags = pvh_start_info.flags;
- msr = cpuid_ebx(xen_cpuid_base() + 2);
- pfn = __pa(hypercall_page);
- wrmsr_safe(msr, (u32)pfn, (u32)(pfn >> 32));
-
x86_init.oem.arch_setup = pvh_arch_setup;
x86_init.oem.banner = xen_banner;
diff --git a/arch/x86/xen/xen-asm.S b/arch/x86/xen/xen-asm.S
index 83189cf5cdce..b518f36d1ca2 100644
--- a/arch/x86/xen/xen-asm.S
+++ b/arch/x86/xen/xen-asm.S
@@ -20,10 +20,33 @@
#include <linux/init.h>
#include <linux/linkage.h>
+#include <linux/objtool.h>
#include <../entry/calling.h>
.pushsection .noinstr.text, "ax"
/*
+ * PV hypercall interface to the hypervisor.
+ *
+ * Called via inline asm(), so better preserve %rcx and %r11.
+ *
+ * Input:
+ * %eax: hypercall number
+ * %rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall
+ * Output: %rax
+ */
+SYM_FUNC_START(xen_hypercall_pv)
+ ANNOTATE_NOENDBR
+ push %rcx
+ push %r11
+ UNWIND_HINT_SAVE
+ syscall
+ UNWIND_HINT_RESTORE
+ pop %r11
+ pop %rcx
+ RET
+SYM_FUNC_END(xen_hypercall_pv)
+
+/*
* Disabling events is simply a matter of making the event mask
* non-zero.
*/
@@ -176,7 +199,6 @@ SYM_CODE_START(xen_early_idt_handler_array)
SYM_CODE_END(xen_early_idt_handler_array)
__FINIT
-hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
/*
* Xen64 iret frame:
*
@@ -186,17 +208,28 @@ hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
* cs
* rip <-- standard iret frame
*
- * flags
+ * flags <-- xen_iret must push from here on
*
- * rcx }
- * r11 }<-- pushed by hypercall page
- * rsp->rax }
+ * rcx
+ * r11
+ * rsp->rax
*/
+.macro xen_hypercall_iret
+ pushq $0 /* Flags */
+ push %rcx
+ push %r11
+ push %rax
+ mov $__HYPERVISOR_iret, %eax
+ syscall /* Do the IRET. */
+#ifdef CONFIG_MITIGATION_SLS
+ int3
+#endif
+.endm
+
SYM_CODE_START(xen_iret)
UNWIND_HINT_UNDEFINED
ANNOTATE_NOENDBR
- pushq $0
- jmp hypercall_iret
+ xen_hypercall_iret
SYM_CODE_END(xen_iret)
/*
@@ -301,8 +334,7 @@ SYM_CODE_START(xen_entry_SYSENTER_compat)
ENDBR
lea 16(%rsp), %rsp /* strip %rcx, %r11 */
mov $-ENOSYS, %rax
- pushq $0
- jmp hypercall_iret
+ xen_hypercall_iret
SYM_CODE_END(xen_entry_SYSENTER_compat)
SYM_CODE_END(xen_entry_SYSCALL_compat)
diff --git a/arch/x86/xen/xen-head.S b/arch/x86/xen/xen-head.S
index 7f6c69dbb816..9252652afe59 100644
--- a/arch/x86/xen/xen-head.S
+++ b/arch/x86/xen/xen-head.S
@@ -6,9 +6,11 @@
#include <linux/elfnote.h>
#include <linux/init.h>
+#include <linux/instrumentation.h>
#include <asm/boot.h>
#include <asm/asm.h>
+#include <asm/frame.h>
#include <asm/msr.h>
#include <asm/page_types.h>
#include <asm/percpu.h>
@@ -20,28 +22,6 @@
#include <xen/interface/xen-mca.h>
#include <asm/xen/interface.h>
-.pushsection .noinstr.text, "ax"
- .balign PAGE_SIZE
-SYM_CODE_START(hypercall_page)
- .rept (PAGE_SIZE / 32)
- UNWIND_HINT_FUNC
- ANNOTATE_NOENDBR
- ANNOTATE_UNRET_SAFE
- ret
- /*
- * Xen will write the hypercall page, and sort out ENDBR.
- */
- .skip 31, 0xcc
- .endr
-
-#define HYPERCALL(n) \
- .equ xen_hypercall_##n, hypercall_page + __HYPERVISOR_##n * 32; \
- .type xen_hypercall_##n, @function; .size xen_hypercall_##n, 32
-#include <asm/xen-hypercalls.h>
-#undef HYPERCALL
-SYM_CODE_END(hypercall_page)
-.popsection
-
#ifdef CONFIG_XEN_PV
__INIT
SYM_CODE_START(startup_xen)
@@ -87,6 +67,87 @@ SYM_CODE_END(xen_cpu_bringup_again)
#endif
#endif
+ .pushsection .noinstr.text, "ax"
+/*
+ * Xen hypercall interface to the hypervisor.
+ *
+ * Input:
+ * %eax: hypercall number
+ * 32-bit:
+ * %ebx, %ecx, %edx, %esi, %edi: args 1..5 for the hypercall
+ * 64-bit:
+ * %rdi, %rsi, %rdx, %r10, %r8: args 1..5 for the hypercall
+ * Output: %[er]ax
+ */
+SYM_FUNC_START(xen_hypercall_hvm)
+ ENDBR
+ FRAME_BEGIN
+ /* Save all relevant registers (caller save and arguments). */
+#ifdef CONFIG_X86_32
+ push %eax
+ push %ebx
+ push %ecx
+ push %edx
+ push %esi
+ push %edi
+#else
+ push %rax
+ push %rcx
+ push %rdx
+ push %rdi
+ push %rsi
+ push %r11
+ push %r10
+ push %r9
+ push %r8
+#ifdef CONFIG_FRAME_POINTER
+ pushq $0 /* Dummy push for stack alignment. */
+#endif
+#endif
+ /* Set the vendor specific function. */
+ call __xen_hypercall_setfunc
+ /* Set ZF = 1 if AMD, Restore saved registers. */
+#ifdef CONFIG_X86_32
+ lea xen_hypercall_amd, %ebx
+ cmp %eax, %ebx
+ pop %edi
+ pop %esi
+ pop %edx
+ pop %ecx
+ pop %ebx
+ pop %eax
+#else
+ lea xen_hypercall_amd(%rip), %rbx
+ cmp %rax, %rbx
+#ifdef CONFIG_FRAME_POINTER
+ pop %rax /* Dummy pop. */
+#endif
+ pop %r8
+ pop %r9
+ pop %r10
+ pop %r11
+ pop %rsi
+ pop %rdi
+ pop %rdx
+ pop %rcx
+ pop %rax
+#endif
+ /* Use correct hypercall function. */
+ jz xen_hypercall_amd
+ jmp xen_hypercall_intel
+SYM_FUNC_END(xen_hypercall_hvm)
+
+SYM_FUNC_START(xen_hypercall_amd)
+ vmmcall
+ RET
+SYM_FUNC_END(xen_hypercall_amd)
+
+SYM_FUNC_START(xen_hypercall_intel)
+ vmcall
+ RET
+SYM_FUNC_END(xen_hypercall_intel)
+ .popsection
+
ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS, .asciz "linux")
ELFNOTE(Xen, XEN_ELFNOTE_GUEST_VERSION, .asciz "2.6")
ELFNOTE(Xen, XEN_ELFNOTE_XEN_VERSION, .asciz "xen-3.0")
@@ -116,8 +177,6 @@ SYM_CODE_END(xen_cpu_bringup_again)
#else
# define FEATURES_DOM0 0
#endif
- ELFNOTE(Xen, XEN_ELFNOTE_HYPERCALL_PAGE, .globl xen_elfnote_hypercall_page;
- xen_elfnote_hypercall_page: _ASM_PTR xen_elfnote_hypercall_page_value - .)
ELFNOTE(Xen, XEN_ELFNOTE_SUPPORTED_FEATURES,
.long FEATURES_PV | FEATURES_PVH | FEATURES_DOM0)
ELFNOTE(Xen, XEN_ELFNOTE_LOADER, .asciz "generic")
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
index e1b782e823e6..63c13a2ccf55 100644
--- a/arch/x86/xen/xen-ops.h
+++ b/arch/x86/xen/xen-ops.h
@@ -326,4 +326,13 @@ static inline void xen_smp_intr_free_pv(unsigned int cpu) {}
static inline void xen_smp_count_cpus(void) { }
#endif /* CONFIG_SMP */
+#ifdef CONFIG_XEN_PV
+void xen_hypercall_pv(void);
+#endif
+void xen_hypercall_hvm(void);
+void xen_hypercall_amd(void);
+void xen_hypercall_intel(void);
+void xen_hypercall_setfunc(void);
+void *__xen_hypercall_setfunc(void);
+
#endif /* XEN_OPS_H */
diff --git a/block/bdev.c b/block/bdev.c
index 738e3c8457e7..9d73a8fbf7f9 100644
--- a/block/bdev.c
+++ b/block/bdev.c
@@ -155,8 +155,7 @@ int set_blocksize(struct file *file, int size)
struct inode *inode = file->f_mapping->host;
struct block_device *bdev = I_BDEV(inode);
- /* Size must be a power of two, and between 512 and PAGE_SIZE */
- if (size > PAGE_SIZE || size < 512 || !is_power_of_2(size))
+ if (blk_validate_block_size(size))
return -EINVAL;
/* Size cannot be smaller than the size supported by the device */
diff --git a/block/bfq-cgroup.c b/block/bfq-cgroup.c
index e831aedb4643..9fb9f3533150 100644
--- a/block/bfq-cgroup.c
+++ b/block/bfq-cgroup.c
@@ -736,6 +736,7 @@ static void bfq_sync_bfqq_move(struct bfq_data *bfqd,
*/
bfq_put_cooperator(sync_bfqq);
bic_set_bfqq(bic, NULL, true, act_idx);
+ bfq_release_process_ref(bfqd, sync_bfqq);
}
}
diff --git a/block/bfq-iosched.c b/block/bfq-iosched.c
index 0747d9d0e48c..95dd7b795935 100644
--- a/block/bfq-iosched.c
+++ b/block/bfq-iosched.c
@@ -582,23 +582,31 @@ static struct request *bfq_choose_req(struct bfq_data *bfqd,
#define BFQ_LIMIT_INLINE_DEPTH 16
#ifdef CONFIG_BFQ_GROUP_IOSCHED
-static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
+static bool bfqq_request_over_limit(struct bfq_data *bfqd,
+ struct bfq_io_cq *bic, blk_opf_t opf,
+ unsigned int act_idx, int limit)
{
- struct bfq_data *bfqd = bfqq->bfqd;
- struct bfq_entity *entity = &bfqq->entity;
struct bfq_entity *inline_entities[BFQ_LIMIT_INLINE_DEPTH];
struct bfq_entity **entities = inline_entities;
- int depth, level, alloc_depth = BFQ_LIMIT_INLINE_DEPTH;
- int class_idx = bfqq->ioprio_class - 1;
+ int alloc_depth = BFQ_LIMIT_INLINE_DEPTH;
struct bfq_sched_data *sched_data;
+ struct bfq_entity *entity;
+ struct bfq_queue *bfqq;
unsigned long wsum;
bool ret = false;
-
- if (!entity->on_st_or_in_serv)
- return false;
+ int depth;
+ int level;
retry:
spin_lock_irq(&bfqd->lock);
+ bfqq = bic_to_bfqq(bic, op_is_sync(opf), act_idx);
+ if (!bfqq)
+ goto out;
+
+ entity = &bfqq->entity;
+ if (!entity->on_st_or_in_serv)
+ goto out;
+
/* +1 for bfqq entity, root cgroup not included */
depth = bfqg_to_blkg(bfqq_group(bfqq))->blkcg->css.cgroup->level + 1;
if (depth > alloc_depth) {
@@ -643,7 +651,7 @@ retry:
* class.
*/
wsum = 0;
- for (i = 0; i <= class_idx; i++) {
+ for (i = 0; i <= bfqq->ioprio_class - 1; i++) {
wsum = wsum * IOPRIO_BE_NR +
sched_data->service_tree[i].wsum;
}
@@ -666,7 +674,9 @@ out:
return ret;
}
#else
-static bool bfqq_request_over_limit(struct bfq_queue *bfqq, int limit)
+static bool bfqq_request_over_limit(struct bfq_data *bfqd,
+ struct bfq_io_cq *bic, blk_opf_t opf,
+ unsigned int act_idx, int limit)
{
return false;
}
@@ -704,8 +714,9 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
}
for (act_idx = 0; bic && act_idx < bfqd->num_actuators; act_idx++) {
- struct bfq_queue *bfqq =
- bic_to_bfqq(bic, op_is_sync(opf), act_idx);
+ /* Fast path to check if bfqq is already allocated. */
+ if (!bic_to_bfqq(bic, op_is_sync(opf), act_idx))
+ continue;
/*
* Does queue (or any parent entity) exceed number of
@@ -713,7 +724,7 @@ static void bfq_limit_depth(blk_opf_t opf, struct blk_mq_alloc_data *data)
* limit depth so that it cannot consume more
* available requests and thus starve other entities.
*/
- if (bfqq && bfqq_request_over_limit(bfqq, limit)) {
+ if (bfqq_request_over_limit(bfqd, bic, opf, act_idx, limit)) {
depth = 1;
break;
}
@@ -5434,8 +5445,6 @@ void bfq_put_cooperator(struct bfq_queue *bfqq)
bfq_put_queue(__bfqq);
__bfqq = next;
}
-
- bfq_release_process_ref(bfqq->bfqd, bfqq);
}
static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
@@ -5448,6 +5457,8 @@ static void bfq_exit_bfqq(struct bfq_data *bfqd, struct bfq_queue *bfqq)
bfq_log_bfqq(bfqd, bfqq, "exit_bfqq: %p, %d", bfqq, bfqq->ref);
bfq_put_cooperator(bfqq);
+
+ bfq_release_process_ref(bfqd, bfqq);
}
static void bfq_exit_icq_bfqq(struct bfq_io_cq *bic, bool is_sync,
@@ -6734,6 +6745,8 @@ bfq_split_bfqq(struct bfq_io_cq *bic, struct bfq_queue *bfqq)
bic_set_bfqq(bic, NULL, true, bfqq->actuator_idx);
bfq_put_cooperator(bfqq);
+
+ bfq_release_process_ref(bfqq->bfqd, bfqq);
return NULL;
}
diff --git a/block/bio.c b/block/bio.c
index 699a78c85c75..d5bdc31d88d3 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -1171,7 +1171,7 @@ void __bio_release_pages(struct bio *bio, bool mark_dirty)
}
EXPORT_SYMBOL_GPL(__bio_release_pages);
-void bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter)
+void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter)
{
WARN_ON_ONCE(bio->bi_max_vecs);
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index e68c725cf8d9..45a395862fbc 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -1324,10 +1324,14 @@ void blkcg_unpin_online(struct cgroup_subsys_state *blkcg_css)
struct blkcg *blkcg = css_to_blkcg(blkcg_css);
do {
+ struct blkcg *parent;
+
if (!refcount_dec_and_test(&blkcg->online_pin))
break;
+
+ parent = blkcg_parent(blkcg);
blkcg_destroy_blkgs(blkcg);
- blkcg = blkcg_parent(blkcg);
+ blkcg = parent;
} while (blkcg);
}
diff --git a/block/blk-iocost.c b/block/blk-iocost.c
index 384aa15e8260..a5894ec9696e 100644
--- a/block/blk-iocost.c
+++ b/block/blk-iocost.c
@@ -1098,7 +1098,14 @@ static void __propagate_weights(struct ioc_gq *iocg, u32 active, u32 inuse,
inuse = DIV64_U64_ROUND_UP(active * iocg->child_inuse_sum,
iocg->child_active_sum);
} else {
- inuse = clamp_t(u32, inuse, 1, active);
+ /*
+ * It may be tempting to turn this into a clamp expression with
+ * a lower limit of 1 but active may be 0, which cannot be used
+ * as an upper limit in that situation. This expression allows
+ * active to clamp inuse unless it is 0, in which case inuse
+ * becomes 1.
+ */
+ inuse = min(inuse, active) ?: 1;
}
iocg->last_inuse = iocg->inuse;
diff --git a/block/blk-map.c b/block/blk-map.c
index b5fd1d857461..894009b2d881 100644
--- a/block/blk-map.c
+++ b/block/blk-map.c
@@ -574,7 +574,7 @@ static int blk_rq_map_user_bvec(struct request *rq, const struct iov_iter *iter)
bio = blk_rq_map_bio_alloc(rq, 0, GFP_KERNEL);
if (!bio)
return -ENOMEM;
- bio_iov_bvec_set(bio, (struct iov_iter *)iter);
+ bio_iov_bvec_set(bio, iter);
/* check that the data layout matches the hardware restrictions */
ret = bio_split_rw_at(bio, lim, &nsegs, max_bytes);
diff --git a/block/blk-merge.c b/block/blk-merge.c
index e0b28e9298c9..e01383c6e534 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -864,17 +864,10 @@ static struct request *attempt_merge(struct request_queue *q,
if (req_op(req) != req_op(next))
return NULL;
- if (rq_data_dir(req) != rq_data_dir(next))
+ if (req->bio->bi_write_hint != next->bio->bi_write_hint)
+ return NULL;
+ if (req->bio->bi_ioprio != next->bio->bi_ioprio)
return NULL;
-
- if (req->bio && next->bio) {
- /* Don't merge requests with different write hints. */
- if (req->bio->bi_write_hint != next->bio->bi_write_hint)
- return NULL;
- if (req->bio->bi_ioprio != next->bio->bi_ioprio)
- return NULL;
- }
-
if (!blk_atomic_write_mergeable_rqs(req, next))
return NULL;
@@ -986,30 +979,16 @@ bool blk_rq_merge_ok(struct request *rq, struct bio *bio)
if (req_op(rq) != bio_op(bio))
return false;
- /* different data direction or already started, don't merge */
- if (bio_data_dir(bio) != rq_data_dir(rq))
- return false;
-
- /* don't merge across cgroup boundaries */
if (!blk_cgroup_mergeable(rq, bio))
return false;
-
- /* only merge integrity protected bio into ditto rq */
if (blk_integrity_merge_bio(rq->q, rq, bio) == false)
return false;
-
- /* Only merge if the crypt contexts are compatible */
if (!bio_crypt_rq_ctx_compatible(rq, bio))
return false;
-
- if (rq->bio) {
- /* Don't merge requests with different write hints. */
- if (rq->bio->bi_write_hint != bio->bi_write_hint)
- return false;
- if (rq->bio->bi_ioprio != bio->bi_ioprio)
- return false;
- }
-
+ if (rq->bio->bi_write_hint != bio->bi_write_hint)
+ return false;
+ if (rq->bio->bi_ioprio != bio->bi_ioprio)
+ return false;
if (blk_atomic_write_mergeable_rq_bio(rq, bio) == false)
return false;
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 270cfd9fc6b0..8ac19d4ae3c0 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -43,6 +43,7 @@
static DEFINE_PER_CPU(struct llist_head, blk_cpu_done);
static DEFINE_PER_CPU(call_single_data_t, blk_cpu_csd);
+static DEFINE_MUTEX(blk_mq_cpuhp_lock);
static void blk_mq_insert_request(struct request *rq, blk_insert_t flags);
static void blk_mq_request_bypass_insert(struct request *rq,
@@ -388,7 +389,6 @@ void blk_rq_init(struct request_queue *q, struct request *rq)
rq->tag = BLK_MQ_NO_TAG;
rq->internal_tag = BLK_MQ_NO_TAG;
rq->start_time_ns = blk_time_get_ns();
- rq->part = NULL;
blk_crypto_rq_set_defaults(rq);
}
EXPORT_SYMBOL(blk_rq_init);
@@ -1544,19 +1544,17 @@ static void blk_mq_requeue_work(struct work_struct *work)
while (!list_empty(&rq_list)) {
rq = list_entry(rq_list.next, struct request, queuelist);
+ list_del_init(&rq->queuelist);
/*
- * If RQF_DONTPREP ist set, the request has been started by the
+ * If RQF_DONTPREP is set, the request has been started by the
* driver already and might have driver-specific data allocated
* already. Insert it into the hctx dispatch list to avoid
* block layer merges for the request.
*/
- if (rq->rq_flags & RQF_DONTPREP) {
- list_del_init(&rq->queuelist);
+ if (rq->rq_flags & RQF_DONTPREP)
blk_mq_request_bypass_insert(rq, 0);
- } else {
- list_del_init(&rq->queuelist);
+ else
blk_mq_insert_request(rq, BLK_MQ_INSERT_AT_HEAD);
- }
}
while (!list_empty(&flush_list)) {
@@ -3273,19 +3271,21 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
int (*bio_ctr)(struct bio *, struct bio *, void *),
void *data)
{
- struct bio *bio, *bio_src;
+ struct bio *bio_src;
if (!bs)
bs = &fs_bio_set;
__rq_for_each_bio(bio_src, rq_src) {
- bio = bio_alloc_clone(rq->q->disk->part0, bio_src, gfp_mask,
- bs);
+ struct bio *bio = bio_alloc_clone(rq->q->disk->part0, bio_src,
+ gfp_mask, bs);
if (!bio)
goto free_and_out;
- if (bio_ctr && bio_ctr(bio, bio_src, data))
+ if (bio_ctr && bio_ctr(bio, bio_src, data)) {
+ bio_put(bio);
goto free_and_out;
+ }
if (rq->bio) {
rq->biotail->bi_next = bio;
@@ -3293,7 +3293,6 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
} else {
rq->bio = rq->biotail = bio;
}
- bio = NULL;
}
/* Copy attributes of the original request to the clone request. */
@@ -3311,8 +3310,6 @@ int blk_rq_prep_clone(struct request *rq, struct request *rq_src,
return 0;
free_and_out:
- if (bio)
- bio_put(bio);
blk_rq_unprep_clone(rq);
return -ENOMEM;
@@ -3741,13 +3738,91 @@ static int blk_mq_hctx_notify_dead(unsigned int cpu, struct hlist_node *node)
return 0;
}
-static void blk_mq_remove_cpuhp(struct blk_mq_hw_ctx *hctx)
+static void __blk_mq_remove_cpuhp(struct blk_mq_hw_ctx *hctx)
{
- if (!(hctx->flags & BLK_MQ_F_STACKING))
+ lockdep_assert_held(&blk_mq_cpuhp_lock);
+
+ if (!(hctx->flags & BLK_MQ_F_STACKING) &&
+ !hlist_unhashed(&hctx->cpuhp_online)) {
cpuhp_state_remove_instance_nocalls(CPUHP_AP_BLK_MQ_ONLINE,
&hctx->cpuhp_online);
- cpuhp_state_remove_instance_nocalls(CPUHP_BLK_MQ_DEAD,
- &hctx->cpuhp_dead);
+ INIT_HLIST_NODE(&hctx->cpuhp_online);
+ }
+
+ if (!hlist_unhashed(&hctx->cpuhp_dead)) {
+ cpuhp_state_remove_instance_nocalls(CPUHP_BLK_MQ_DEAD,
+ &hctx->cpuhp_dead);
+ INIT_HLIST_NODE(&hctx->cpuhp_dead);
+ }
+}
+
+static void blk_mq_remove_cpuhp(struct blk_mq_hw_ctx *hctx)
+{
+ mutex_lock(&blk_mq_cpuhp_lock);
+ __blk_mq_remove_cpuhp(hctx);
+ mutex_unlock(&blk_mq_cpuhp_lock);
+}
+
+static void __blk_mq_add_cpuhp(struct blk_mq_hw_ctx *hctx)
+{
+ lockdep_assert_held(&blk_mq_cpuhp_lock);
+
+ if (!(hctx->flags & BLK_MQ_F_STACKING) &&
+ hlist_unhashed(&hctx->cpuhp_online))
+ cpuhp_state_add_instance_nocalls(CPUHP_AP_BLK_MQ_ONLINE,
+ &hctx->cpuhp_online);
+
+ if (hlist_unhashed(&hctx->cpuhp_dead))
+ cpuhp_state_add_instance_nocalls(CPUHP_BLK_MQ_DEAD,
+ &hctx->cpuhp_dead);
+}
+
+static void __blk_mq_remove_cpuhp_list(struct list_head *head)
+{
+ struct blk_mq_hw_ctx *hctx;
+
+ lockdep_assert_held(&blk_mq_cpuhp_lock);
+
+ list_for_each_entry(hctx, head, hctx_list)
+ __blk_mq_remove_cpuhp(hctx);
+}
+
+/*
+ * Unregister cpuhp callbacks from exited hw queues
+ *
+ * Safe to call if this `request_queue` is live
+ */
+static void blk_mq_remove_hw_queues_cpuhp(struct request_queue *q)
+{
+ LIST_HEAD(hctx_list);
+
+ spin_lock(&q->unused_hctx_lock);
+ list_splice_init(&q->unused_hctx_list, &hctx_list);
+ spin_unlock(&q->unused_hctx_lock);
+
+ mutex_lock(&blk_mq_cpuhp_lock);
+ __blk_mq_remove_cpuhp_list(&hctx_list);
+ mutex_unlock(&blk_mq_cpuhp_lock);
+
+ spin_lock(&q->unused_hctx_lock);
+ list_splice(&hctx_list, &q->unused_hctx_list);
+ spin_unlock(&q->unused_hctx_lock);
+}
+
+/*
+ * Register cpuhp callbacks from all hw queues
+ *
+ * Safe to call if this `request_queue` is live
+ */
+static void blk_mq_add_hw_queues_cpuhp(struct request_queue *q)
+{
+ struct blk_mq_hw_ctx *hctx;
+ unsigned long i;
+
+ mutex_lock(&blk_mq_cpuhp_lock);
+ queue_for_each_hw_ctx(q, hctx, i)
+ __blk_mq_add_cpuhp(hctx);
+ mutex_unlock(&blk_mq_cpuhp_lock);
}
/*
@@ -3798,8 +3873,6 @@ static void blk_mq_exit_hctx(struct request_queue *q,
if (set->ops->exit_hctx)
set->ops->exit_hctx(hctx, hctx_idx);
- blk_mq_remove_cpuhp(hctx);
-
xa_erase(&q->hctx_table, hctx_idx);
spin_lock(&q->unused_hctx_lock);
@@ -3816,6 +3889,7 @@ static void blk_mq_exit_hw_queues(struct request_queue *q,
queue_for_each_hw_ctx(q, hctx, i) {
if (i == nr_queue)
break;
+ blk_mq_remove_cpuhp(hctx);
blk_mq_exit_hctx(q, set, hctx, i);
}
}
@@ -3826,16 +3900,11 @@ static int blk_mq_init_hctx(struct request_queue *q,
{
hctx->queue_num = hctx_idx;
- if (!(hctx->flags & BLK_MQ_F_STACKING))
- cpuhp_state_add_instance_nocalls(CPUHP_AP_BLK_MQ_ONLINE,
- &hctx->cpuhp_online);
- cpuhp_state_add_instance_nocalls(CPUHP_BLK_MQ_DEAD, &hctx->cpuhp_dead);
-
hctx->tags = set->tags[hctx_idx];
if (set->ops->init_hctx &&
set->ops->init_hctx(hctx, set->driver_data, hctx_idx))
- goto unregister_cpu_notifier;
+ goto fail;
if (blk_mq_init_request(set, hctx->fq->flush_rq, hctx_idx,
hctx->numa_node))
@@ -3852,8 +3921,7 @@ static int blk_mq_init_hctx(struct request_queue *q,
exit_hctx:
if (set->ops->exit_hctx)
set->ops->exit_hctx(hctx, hctx_idx);
- unregister_cpu_notifier:
- blk_mq_remove_cpuhp(hctx);
+ fail:
return -1;
}
@@ -3879,6 +3947,8 @@ blk_mq_alloc_hctx(struct request_queue *q, struct blk_mq_tag_set *set,
INIT_DELAYED_WORK(&hctx->run_work, blk_mq_run_work_fn);
spin_lock_init(&hctx->lock);
INIT_LIST_HEAD(&hctx->dispatch);
+ INIT_HLIST_NODE(&hctx->cpuhp_dead);
+ INIT_HLIST_NODE(&hctx->cpuhp_online);
hctx->queue = q;
hctx->flags = set->flags & ~BLK_MQ_F_TAG_QUEUE_SHARED;
@@ -4342,6 +4412,15 @@ struct gendisk *blk_mq_alloc_disk_for_queue(struct request_queue *q,
}
EXPORT_SYMBOL(blk_mq_alloc_disk_for_queue);
+/*
+ * Only hctx removed from cpuhp list can be reused
+ */
+static bool blk_mq_hctx_is_reusable(struct blk_mq_hw_ctx *hctx)
+{
+ return hlist_unhashed(&hctx->cpuhp_online) &&
+ hlist_unhashed(&hctx->cpuhp_dead);
+}
+
static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx(
struct blk_mq_tag_set *set, struct request_queue *q,
int hctx_idx, int node)
@@ -4351,7 +4430,7 @@ static struct blk_mq_hw_ctx *blk_mq_alloc_and_init_hctx(
/* reuse dead hctx first */
spin_lock(&q->unused_hctx_lock);
list_for_each_entry(tmp, &q->unused_hctx_list, hctx_list) {
- if (tmp->numa_node == node) {
+ if (tmp->numa_node == node && blk_mq_hctx_is_reusable(tmp)) {
hctx = tmp;
break;
}
@@ -4417,6 +4496,12 @@ static void blk_mq_realloc_hw_ctxs(struct blk_mq_tag_set *set,
xa_for_each_start(&q->hctx_table, j, hctx, j)
blk_mq_exit_hctx(q, set, hctx, j);
mutex_unlock(&q->sysfs_lock);
+
+ /* unregister cpuhp callbacks for exited hctxs */
+ blk_mq_remove_hw_queues_cpuhp(q);
+
+ /* register cpuhp for new initialized hctxs */
+ blk_mq_add_hw_queues_cpuhp(q);
}
int blk_mq_init_allocated_queue(struct blk_mq_tag_set *set,
diff --git a/block/blk-settings.c b/block/blk-settings.c
index f1d4dfdc37a7..8f09e33f41f6 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -178,9 +178,26 @@ static void blk_validate_atomic_write_limits(struct queue_limits *lim)
if (!lim->atomic_write_hw_max)
goto unsupported;
+ if (WARN_ON_ONCE(!is_power_of_2(lim->atomic_write_hw_unit_min)))
+ goto unsupported;
+
+ if (WARN_ON_ONCE(!is_power_of_2(lim->atomic_write_hw_unit_max)))
+ goto unsupported;
+
+ if (WARN_ON_ONCE(lim->atomic_write_hw_unit_min >
+ lim->atomic_write_hw_unit_max))
+ goto unsupported;
+
+ if (WARN_ON_ONCE(lim->atomic_write_hw_unit_max >
+ lim->atomic_write_hw_max))
+ goto unsupported;
+
boundary_sectors = lim->atomic_write_hw_boundary >> SECTOR_SHIFT;
if (boundary_sectors) {
+ if (WARN_ON_ONCE(lim->atomic_write_hw_max >
+ lim->atomic_write_hw_boundary))
+ goto unsupported;
/*
* A feature of boundary support is that it disallows bios to
* be merged which would result in a merged request which
@@ -249,6 +266,13 @@ int blk_validate_limits(struct queue_limits *lim)
lim->io_min = lim->physical_block_size;
/*
+ * The optimal I/O size may not be aligned to physical block size
+ * (because it may be limited by dma engines which have no clue about
+ * block size of the disks attached to them), so we round it down here.
+ */
+ lim->io_opt = round_down(lim->io_opt, lim->physical_block_size);
+
+ /*
* max_hw_sectors has a somewhat weird default for historical reason,
* but driver really should set their own instead of relying on this
* value.
@@ -458,8 +482,6 @@ static unsigned int queue_limit_discard_alignment(
/* Why are these in bytes, not sectors? */
alignment = lim->discard_alignment >> SECTOR_SHIFT;
granularity = lim->discard_granularity >> SECTOR_SHIFT;
- if (!granularity)
- return 0;
/* Offset of the partition start in 'granularity' sectors */
offset = sector_div(sector, granularity);
@@ -479,6 +501,119 @@ static unsigned int blk_round_down_sectors(unsigned int sectors, unsigned int lb
return sectors;
}
+/* Check if second and later bottom devices are compliant */
+static bool blk_stack_atomic_writes_tail(struct queue_limits *t,
+ struct queue_limits *b)
+{
+ /* We're not going to support different boundary sizes.. yet */
+ if (t->atomic_write_hw_boundary != b->atomic_write_hw_boundary)
+ return false;
+
+ /* Can't support this */
+ if (t->atomic_write_hw_unit_min > b->atomic_write_hw_unit_max)
+ return false;
+
+ /* Or this */
+ if (t->atomic_write_hw_unit_max < b->atomic_write_hw_unit_min)
+ return false;
+
+ t->atomic_write_hw_max = min(t->atomic_write_hw_max,
+ b->atomic_write_hw_max);
+ t->atomic_write_hw_unit_min = max(t->atomic_write_hw_unit_min,
+ b->atomic_write_hw_unit_min);
+ t->atomic_write_hw_unit_max = min(t->atomic_write_hw_unit_max,
+ b->atomic_write_hw_unit_max);
+ return true;
+}
+
+/* Check for valid boundary of first bottom device */
+static bool blk_stack_atomic_writes_boundary_head(struct queue_limits *t,
+ struct queue_limits *b)
+{
+ /*
+ * Ensure atomic write boundary is aligned with chunk sectors. Stacked
+ * devices store chunk sectors in t->io_min.
+ */
+ if (b->atomic_write_hw_boundary > t->io_min &&
+ b->atomic_write_hw_boundary % t->io_min)
+ return false;
+ if (t->io_min > b->atomic_write_hw_boundary &&
+ t->io_min % b->atomic_write_hw_boundary)
+ return false;
+
+ t->atomic_write_hw_boundary = b->atomic_write_hw_boundary;
+ return true;
+}
+
+
+/* Check stacking of first bottom device */
+static bool blk_stack_atomic_writes_head(struct queue_limits *t,
+ struct queue_limits *b)
+{
+ if (b->atomic_write_hw_boundary &&
+ !blk_stack_atomic_writes_boundary_head(t, b))
+ return false;
+
+ if (t->io_min <= SECTOR_SIZE) {
+ /* No chunk sectors, so use bottom device values directly */
+ t->atomic_write_hw_unit_max = b->atomic_write_hw_unit_max;
+ t->atomic_write_hw_unit_min = b->atomic_write_hw_unit_min;
+ t->atomic_write_hw_max = b->atomic_write_hw_max;
+ return true;
+ }
+
+ /*
+ * Find values for limits which work for chunk size.
+ * b->atomic_write_hw_unit_{min, max} may not be aligned with chunk
+ * size (t->io_min), as chunk size is not restricted to a power-of-2.
+ * So we need to find highest power-of-2 which works for the chunk
+ * size.
+ * As an example scenario, we could have b->unit_max = 16K and
+ * t->io_min = 24K. For this case, reduce t->unit_max to a value
+ * aligned with both limits, i.e. 8K in this example.
+ */
+ t->atomic_write_hw_unit_max = b->atomic_write_hw_unit_max;
+ while (t->io_min % t->atomic_write_hw_unit_max)
+ t->atomic_write_hw_unit_max /= 2;
+
+ t->atomic_write_hw_unit_min = min(b->atomic_write_hw_unit_min,
+ t->atomic_write_hw_unit_max);
+ t->atomic_write_hw_max = min(b->atomic_write_hw_max, t->io_min);
+
+ return true;
+}
+
+static void blk_stack_atomic_writes_limits(struct queue_limits *t,
+ struct queue_limits *b)
+{
+ if (!(t->features & BLK_FEAT_ATOMIC_WRITES_STACKED))
+ goto unsupported;
+
+ if (!b->atomic_write_unit_min)
+ goto unsupported;
+
+ /*
+ * If atomic_write_hw_max is set, we have already stacked 1x bottom
+ * device, so check for compliance.
+ */
+ if (t->atomic_write_hw_max) {
+ if (!blk_stack_atomic_writes_tail(t, b))
+ goto unsupported;
+ return;
+ }
+
+ if (!blk_stack_atomic_writes_head(t, b))
+ goto unsupported;
+ return;
+
+unsupported:
+ t->atomic_write_hw_max = 0;
+ t->atomic_write_hw_unit_max = 0;
+ t->atomic_write_hw_unit_min = 0;
+ t->atomic_write_hw_boundary = 0;
+ t->features &= ~BLK_FEAT_ATOMIC_WRITES_STACKED;
+}
+
/**
* blk_stack_limits - adjust queue_limits for stacked devices
* @t: the stacking driver limits (top device)
@@ -639,6 +774,8 @@ int blk_stack_limits(struct queue_limits *t, struct queue_limits *b,
t->zone_write_granularity = 0;
t->max_zone_append_sectors = 0;
}
+ blk_stack_atomic_writes_limits(t, b);
+
return ret;
}
EXPORT_SYMBOL(blk_stack_limits);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index d80a202cd170..767598e719ab 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -263,7 +263,7 @@ static ssize_t queue_nr_zones_show(struct gendisk *disk, char *page)
static ssize_t queue_iostats_passthrough_show(struct gendisk *disk, char *page)
{
- return queue_var_show(blk_queue_passthrough_stat(disk->queue), page);
+ return queue_var_show(!!blk_queue_passthrough_stat(disk->queue), page);
}
static ssize_t queue_iostats_passthrough_store(struct gendisk *disk,
@@ -810,10 +810,8 @@ int blk_register_queue(struct gendisk *disk)
* faster to shut down and is made fully functional here as
* request_queues for non-existent devices never get registered.
*/
- if (!blk_queue_init_done(q)) {
- blk_queue_flag_set(QUEUE_FLAG_INIT_DONE, q);
- percpu_ref_switch_to_percpu(&q->q_usage_counter);
- }
+ blk_queue_flag_set(QUEUE_FLAG_INIT_DONE, q);
+ percpu_ref_switch_to_percpu(&q->q_usage_counter);
return ret;
diff --git a/block/blk-zoned.c b/block/blk-zoned.c
index 70211751df16..84da1eadff64 100644
--- a/block/blk-zoned.c
+++ b/block/blk-zoned.c
@@ -41,7 +41,6 @@ static const char *const zone_cond_name[] = {
/*
* Per-zone write plug.
* @node: hlist_node structure for managing the plug using a hash table.
- * @link: To list the plug in the zone write plug error list of the disk.
* @ref: Zone write plug reference counter. A zone write plug reference is
* always at least 1 when the plug is hashed in the disk plug hash table.
* The reference is incremented whenever a new BIO needing plugging is
@@ -63,7 +62,6 @@ static const char *const zone_cond_name[] = {
*/
struct blk_zone_wplug {
struct hlist_node node;
- struct list_head link;
refcount_t ref;
spinlock_t lock;
unsigned int flags;
@@ -80,8 +78,8 @@ struct blk_zone_wplug {
* - BLK_ZONE_WPLUG_PLUGGED: Indicates that the zone write plug is plugged,
* that is, that write BIOs are being throttled due to a write BIO already
* being executed or the zone write plug bio list is not empty.
- * - BLK_ZONE_WPLUG_ERROR: Indicates that a write error happened which will be
- * recovered with a report zone to update the zone write pointer offset.
+ * - BLK_ZONE_WPLUG_NEED_WP_UPDATE: Indicates that we lost track of a zone
+ * write pointer offset and need to update it.
* - BLK_ZONE_WPLUG_UNHASHED: Indicates that the zone write plug was removed
* from the disk hash table and that the initial reference to the zone
* write plug set when the plug was first added to the hash table has been
@@ -91,11 +89,9 @@ struct blk_zone_wplug {
* freed once all remaining references from BIOs or functions are dropped.
*/
#define BLK_ZONE_WPLUG_PLUGGED (1U << 0)
-#define BLK_ZONE_WPLUG_ERROR (1U << 1)
+#define BLK_ZONE_WPLUG_NEED_WP_UPDATE (1U << 1)
#define BLK_ZONE_WPLUG_UNHASHED (1U << 2)
-#define BLK_ZONE_WPLUG_BUSY (BLK_ZONE_WPLUG_PLUGGED | BLK_ZONE_WPLUG_ERROR)
-
/**
* blk_zone_cond_str - Return string XXX in BLK_ZONE_COND_XXX.
* @zone_cond: BLK_ZONE_COND_XXX.
@@ -115,6 +111,30 @@ const char *blk_zone_cond_str(enum blk_zone_cond zone_cond)
}
EXPORT_SYMBOL_GPL(blk_zone_cond_str);
+struct disk_report_zones_cb_args {
+ struct gendisk *disk;
+ report_zones_cb user_cb;
+ void *user_data;
+};
+
+static void disk_zone_wplug_sync_wp_offset(struct gendisk *disk,
+ struct blk_zone *zone);
+
+static int disk_report_zones_cb(struct blk_zone *zone, unsigned int idx,
+ void *data)
+{
+ struct disk_report_zones_cb_args *args = data;
+ struct gendisk *disk = args->disk;
+
+ if (disk->zone_wplugs_hash)
+ disk_zone_wplug_sync_wp_offset(disk, zone);
+
+ if (!args->user_cb)
+ return 0;
+
+ return args->user_cb(zone, idx, args->user_data);
+}
+
/**
* blkdev_report_zones - Get zones information
* @bdev: Target block device
@@ -139,6 +159,11 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector,
{
struct gendisk *disk = bdev->bd_disk;
sector_t capacity = get_capacity(disk);
+ struct disk_report_zones_cb_args args = {
+ .disk = disk,
+ .user_cb = cb,
+ .user_data = data,
+ };
if (!bdev_is_zoned(bdev) || WARN_ON_ONCE(!disk->fops->report_zones))
return -EOPNOTSUPP;
@@ -146,7 +171,8 @@ int blkdev_report_zones(struct block_device *bdev, sector_t sector,
if (!nr_zones || sector >= capacity)
return 0;
- return disk->fops->report_zones(disk, sector, nr_zones, cb, data);
+ return disk->fops->report_zones(disk, sector, nr_zones,
+ disk_report_zones_cb, &args);
}
EXPORT_SYMBOL_GPL(blkdev_report_zones);
@@ -427,7 +453,7 @@ static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug)
{
if (refcount_dec_and_test(&zwplug->ref)) {
WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list));
- WARN_ON_ONCE(!list_empty(&zwplug->link));
+ WARN_ON_ONCE(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED);
WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_UNHASHED));
call_rcu(&zwplug->rcu_head, disk_free_zone_wplug_rcu);
@@ -441,8 +467,8 @@ static inline bool disk_should_remove_zone_wplug(struct gendisk *disk,
if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED)
return false;
- /* If the zone write plug is still busy, it cannot be removed. */
- if (zwplug->flags & BLK_ZONE_WPLUG_BUSY)
+ /* If the zone write plug is still plugged, it cannot be removed. */
+ if (zwplug->flags & BLK_ZONE_WPLUG_PLUGGED)
return false;
/*
@@ -525,12 +551,11 @@ again:
return NULL;
INIT_HLIST_NODE(&zwplug->node);
- INIT_LIST_HEAD(&zwplug->link);
refcount_set(&zwplug->ref, 2);
spin_lock_init(&zwplug->lock);
zwplug->flags = 0;
zwplug->zone_no = zno;
- zwplug->wp_offset = sector & (disk->queue->limits.chunk_sectors - 1);
+ zwplug->wp_offset = bdev_offset_from_zone_start(disk->part0, sector);
bio_list_init(&zwplug->bio_list);
INIT_WORK(&zwplug->bio_work, blk_zone_wplug_bio_work);
zwplug->disk = disk;
@@ -574,124 +599,81 @@ static void disk_zone_wplug_abort(struct blk_zone_wplug *zwplug)
}
/*
- * Abort (fail) all plugged BIOs of a zone write plug that are not aligned
- * with the assumed write pointer location of the zone when the BIO will
- * be unplugged.
+ * Set a zone write plug write pointer offset to the specified value.
+ * This aborts all plugged BIOs, which is fine as this function is called for
+ * a zone reset operation, a zone finish operation or if the zone needs a wp
+ * update from a report zone after a write error.
*/
-static void disk_zone_wplug_abort_unaligned(struct gendisk *disk,
- struct blk_zone_wplug *zwplug)
-{
- unsigned int wp_offset = zwplug->wp_offset;
- struct bio_list bl = BIO_EMPTY_LIST;
- struct bio *bio;
-
- while ((bio = bio_list_pop(&zwplug->bio_list))) {
- if (disk_zone_is_full(disk, zwplug->zone_no, wp_offset) ||
- (bio_op(bio) != REQ_OP_ZONE_APPEND &&
- bio_offset_from_zone_start(bio) != wp_offset)) {
- blk_zone_wplug_bio_io_error(zwplug, bio);
- continue;
- }
-
- wp_offset += bio_sectors(bio);
- bio_list_add(&bl, bio);
- }
-
- bio_list_merge(&zwplug->bio_list, &bl);
-}
-
-static inline void disk_zone_wplug_set_error(struct gendisk *disk,
- struct blk_zone_wplug *zwplug)
+static void disk_zone_wplug_set_wp_offset(struct gendisk *disk,
+ struct blk_zone_wplug *zwplug,
+ unsigned int wp_offset)
{
- unsigned long flags;
+ lockdep_assert_held(&zwplug->lock);
- if (zwplug->flags & BLK_ZONE_WPLUG_ERROR)
- return;
+ /* Update the zone write pointer and abort all plugged BIOs. */
+ zwplug->flags &= ~BLK_ZONE_WPLUG_NEED_WP_UPDATE;
+ zwplug->wp_offset = wp_offset;
+ disk_zone_wplug_abort(zwplug);
/*
- * At this point, we already have a reference on the zone write plug.
- * However, since we are going to add the plug to the disk zone write
- * plugs work list, increase its reference count. This reference will
- * be dropped in disk_zone_wplugs_work() once the error state is
- * handled, or in disk_zone_wplug_clear_error() if the zone is reset or
- * finished.
+ * The zone write plug now has no BIO plugged: remove it from the
+ * hash table so that it cannot be seen. The plug will be freed
+ * when the last reference is dropped.
*/
- zwplug->flags |= BLK_ZONE_WPLUG_ERROR;
- refcount_inc(&zwplug->ref);
-
- spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
- list_add_tail(&zwplug->link, &disk->zone_wplugs_err_list);
- spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+ if (disk_should_remove_zone_wplug(disk, zwplug))
+ disk_remove_zone_wplug(disk, zwplug);
}
-static inline void disk_zone_wplug_clear_error(struct gendisk *disk,
- struct blk_zone_wplug *zwplug)
+static unsigned int blk_zone_wp_offset(struct blk_zone *zone)
{
- unsigned long flags;
-
- if (!(zwplug->flags & BLK_ZONE_WPLUG_ERROR))
- return;
-
- /*
- * We are racing with the error handling work which drops the reference
- * on the zone write plug after handling the error state. So remove the
- * plug from the error list and drop its reference count only if the
- * error handling has not yet started, that is, if the zone write plug
- * is still listed.
- */
- spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
- if (!list_empty(&zwplug->link)) {
- list_del_init(&zwplug->link);
- zwplug->flags &= ~BLK_ZONE_WPLUG_ERROR;
- disk_put_zone_wplug(zwplug);
+ switch (zone->cond) {
+ case BLK_ZONE_COND_IMP_OPEN:
+ case BLK_ZONE_COND_EXP_OPEN:
+ case BLK_ZONE_COND_CLOSED:
+ return zone->wp - zone->start;
+ case BLK_ZONE_COND_FULL:
+ return zone->len;
+ case BLK_ZONE_COND_EMPTY:
+ return 0;
+ case BLK_ZONE_COND_NOT_WP:
+ case BLK_ZONE_COND_OFFLINE:
+ case BLK_ZONE_COND_READONLY:
+ default:
+ /*
+ * Conventional, offline and read-only zones do not have a valid
+ * write pointer.
+ */
+ return UINT_MAX;
}
- spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
}
-/*
- * Set a zone write plug write pointer offset to either 0 (zone reset case)
- * or to the zone size (zone finish case). This aborts all plugged BIOs, which
- * is fine to do as doing a zone reset or zone finish while writes are in-flight
- * is a mistake from the user which will most likely cause all plugged BIOs to
- * fail anyway.
- */
-static void disk_zone_wplug_set_wp_offset(struct gendisk *disk,
- struct blk_zone_wplug *zwplug,
- unsigned int wp_offset)
+static void disk_zone_wplug_sync_wp_offset(struct gendisk *disk,
+ struct blk_zone *zone)
{
+ struct blk_zone_wplug *zwplug;
unsigned long flags;
- spin_lock_irqsave(&zwplug->lock, flags);
-
- /*
- * Make sure that a BIO completion or another zone reset or finish
- * operation has not already removed the plug from the hash table.
- */
- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) {
- spin_unlock_irqrestore(&zwplug->lock, flags);
+ zwplug = disk_get_zone_wplug(disk, zone->start);
+ if (!zwplug)
return;
- }
- /* Update the zone write pointer and abort all plugged BIOs. */
- zwplug->wp_offset = wp_offset;
- disk_zone_wplug_abort(zwplug);
+ spin_lock_irqsave(&zwplug->lock, flags);
+ if (zwplug->flags & BLK_ZONE_WPLUG_NEED_WP_UPDATE)
+ disk_zone_wplug_set_wp_offset(disk, zwplug,
+ blk_zone_wp_offset(zone));
+ spin_unlock_irqrestore(&zwplug->lock, flags);
- /*
- * Updating the write pointer offset puts back the zone
- * in a good state. So clear the error flag and decrement the
- * error count if we were in error state.
- */
- disk_zone_wplug_clear_error(disk, zwplug);
+ disk_put_zone_wplug(zwplug);
+}
- /*
- * The zone write plug now has no BIO plugged: remove it from the
- * hash table so that it cannot be seen. The plug will be freed
- * when the last reference is dropped.
- */
- if (disk_should_remove_zone_wplug(disk, zwplug))
- disk_remove_zone_wplug(disk, zwplug);
+static int disk_zone_sync_wp_offset(struct gendisk *disk, sector_t sector)
+{
+ struct disk_report_zones_cb_args args = {
+ .disk = disk,
+ };
- spin_unlock_irqrestore(&zwplug->lock, flags);
+ return disk->fops->report_zones(disk, sector, 1,
+ disk_report_zones_cb, &args);
}
static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
@@ -700,6 +682,7 @@ static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
struct gendisk *disk = bio->bi_bdev->bd_disk;
sector_t sector = bio->bi_iter.bi_sector;
struct blk_zone_wplug *zwplug;
+ unsigned long flags;
/* Conventional zones cannot be reset nor finished. */
if (!bdev_zone_is_seq(bio->bi_bdev, sector)) {
@@ -708,6 +691,15 @@ static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
}
/*
+ * No-wait reset or finish BIOs do not make much sense as the callers
+ * issue these as blocking operations in most cases. To avoid issues
+ * the BIO execution potentially failing with BLK_STS_AGAIN, warn about
+ * REQ_NOWAIT being set and ignore that flag.
+ */
+ if (WARN_ON_ONCE(bio->bi_opf & REQ_NOWAIT))
+ bio->bi_opf &= ~REQ_NOWAIT;
+
+ /*
* If we have a zone write plug, set its write pointer offset to 0
* (reset case) or to the zone size (finish case). This will abort all
* BIOs plugged for the target zone. It is fine as resetting or
@@ -716,7 +708,9 @@ static bool blk_zone_wplug_handle_reset_or_finish(struct bio *bio,
*/
zwplug = disk_get_zone_wplug(disk, sector);
if (zwplug) {
+ spin_lock_irqsave(&zwplug->lock, flags);
disk_zone_wplug_set_wp_offset(disk, zwplug, wp_offset);
+ spin_unlock_irqrestore(&zwplug->lock, flags);
disk_put_zone_wplug(zwplug);
}
@@ -727,6 +721,7 @@ static bool blk_zone_wplug_handle_reset_all(struct bio *bio)
{
struct gendisk *disk = bio->bi_bdev->bd_disk;
struct blk_zone_wplug *zwplug;
+ unsigned long flags;
sector_t sector;
/*
@@ -738,7 +733,9 @@ static bool blk_zone_wplug_handle_reset_all(struct bio *bio)
sector += disk->queue->limits.chunk_sectors) {
zwplug = disk_get_zone_wplug(disk, sector);
if (zwplug) {
+ spin_lock_irqsave(&zwplug->lock, flags);
disk_zone_wplug_set_wp_offset(disk, zwplug, 0);
+ spin_unlock_irqrestore(&zwplug->lock, flags);
disk_put_zone_wplug(zwplug);
}
}
@@ -746,10 +743,26 @@ static bool blk_zone_wplug_handle_reset_all(struct bio *bio)
return false;
}
-static inline void blk_zone_wplug_add_bio(struct blk_zone_wplug *zwplug,
- struct bio *bio, unsigned int nr_segs)
+static void disk_zone_wplug_schedule_bio_work(struct gendisk *disk,
+ struct blk_zone_wplug *zwplug)
{
/*
+ * Take a reference on the zone write plug and schedule the submission
+ * of the next plugged BIO. blk_zone_wplug_bio_work() will release the
+ * reference we take here.
+ */
+ WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED));
+ refcount_inc(&zwplug->ref);
+ queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
+}
+
+static inline void disk_zone_wplug_add_bio(struct gendisk *disk,
+ struct blk_zone_wplug *zwplug,
+ struct bio *bio, unsigned int nr_segs)
+{
+ bool schedule_bio_work = false;
+
+ /*
* Grab an extra reference on the BIO request queue usage counter.
* This reference will be reused to submit a request for the BIO for
* blk-mq devices and dropped when the BIO is failed and after
@@ -765,6 +778,16 @@ static inline void blk_zone_wplug_add_bio(struct blk_zone_wplug *zwplug,
bio_clear_polled(bio);
/*
+ * REQ_NOWAIT BIOs are always handled using the zone write plug BIO
+ * work, which can block. So clear the REQ_NOWAIT flag and schedule the
+ * work if this is the first BIO we are plugging.
+ */
+ if (bio->bi_opf & REQ_NOWAIT) {
+ schedule_bio_work = !(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED);
+ bio->bi_opf &= ~REQ_NOWAIT;
+ }
+
+ /*
* Reuse the poll cookie field to store the number of segments when
* split to the hardware limits.
*/
@@ -777,6 +800,11 @@ static inline void blk_zone_wplug_add_bio(struct blk_zone_wplug *zwplug,
* at the tail of the list to preserve the sequential write order.
*/
bio_list_add(&zwplug->bio_list, bio);
+
+ zwplug->flags |= BLK_ZONE_WPLUG_PLUGGED;
+
+ if (schedule_bio_work)
+ disk_zone_wplug_schedule_bio_work(disk, zwplug);
}
/*
@@ -890,12 +918,22 @@ static bool blk_zone_wplug_prepare_bio(struct blk_zone_wplug *zwplug,
struct gendisk *disk = bio->bi_bdev->bd_disk;
/*
+ * If we lost track of the zone write pointer due to a write error,
+ * the user must either execute a report zones, reset the zone or finish
+ * the to recover a reliable write pointer position. Fail BIOs if the
+ * user did not do that as we cannot handle emulated zone append
+ * otherwise.
+ */
+ if (zwplug->flags & BLK_ZONE_WPLUG_NEED_WP_UPDATE)
+ return false;
+
+ /*
* Check that the user is not attempting to write to a full zone.
* We know such BIO will fail, and that would potentially overflow our
* write pointer offset beyond the end of the zone.
*/
if (disk_zone_wplug_is_full(disk, zwplug))
- goto err;
+ return false;
if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
/*
@@ -914,24 +952,18 @@ static bool blk_zone_wplug_prepare_bio(struct blk_zone_wplug *zwplug,
bio_set_flag(bio, BIO_EMULATES_ZONE_APPEND);
} else {
/*
- * Check for non-sequential writes early because we avoid a
- * whole lot of error handling trouble if we don't send it off
- * to the driver.
+ * Check for non-sequential writes early as we know that BIOs
+ * with a start sector not unaligned to the zone write pointer
+ * will fail.
*/
if (bio_offset_from_zone_start(bio) != zwplug->wp_offset)
- goto err;
+ return false;
}
/* Advance the zone write pointer offset. */
zwplug->wp_offset += bio_sectors(bio);
return true;
-
-err:
- /* We detected an invalid write BIO: schedule error recovery. */
- disk_zone_wplug_set_error(disk, zwplug);
- kblockd_schedule_work(&disk->zone_wplugs_work);
- return false;
}
static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
@@ -970,7 +1002,10 @@ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
zwplug = disk_get_and_lock_zone_wplug(disk, sector, gfp_mask, &flags);
if (!zwplug) {
- bio_io_error(bio);
+ if (bio->bi_opf & REQ_NOWAIT)
+ bio_wouldblock_error(bio);
+ else
+ bio_io_error(bio);
return true;
}
@@ -978,18 +1013,20 @@ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
bio_set_flag(bio, BIO_ZONE_WRITE_PLUGGING);
/*
- * If the zone is already plugged or has a pending error, add the BIO
- * to the plug BIO list. Otherwise, plug and let the BIO execute.
+ * If the zone is already plugged, add the BIO to the plug BIO list.
+ * Do the same for REQ_NOWAIT BIOs to ensure that we will not see a
+ * BLK_STS_AGAIN failure if we let the BIO execute.
+ * Otherwise, plug and let the BIO execute.
*/
- if (zwplug->flags & BLK_ZONE_WPLUG_BUSY)
+ if ((zwplug->flags & BLK_ZONE_WPLUG_PLUGGED) ||
+ (bio->bi_opf & REQ_NOWAIT))
goto plug;
- /*
- * If an error is detected when preparing the BIO, add it to the BIO
- * list so that error recovery can deal with it.
- */
- if (!blk_zone_wplug_prepare_bio(zwplug, bio))
- goto plug;
+ if (!blk_zone_wplug_prepare_bio(zwplug, bio)) {
+ spin_unlock_irqrestore(&zwplug->lock, flags);
+ bio_io_error(bio);
+ return true;
+ }
zwplug->flags |= BLK_ZONE_WPLUG_PLUGGED;
@@ -998,8 +1035,7 @@ static bool blk_zone_wplug_handle_write(struct bio *bio, unsigned int nr_segs)
return false;
plug:
- zwplug->flags |= BLK_ZONE_WPLUG_PLUGGED;
- blk_zone_wplug_add_bio(zwplug, bio, nr_segs);
+ disk_zone_wplug_add_bio(disk, zwplug, bio, nr_segs);
spin_unlock_irqrestore(&zwplug->lock, flags);
@@ -1083,19 +1119,6 @@ bool blk_zone_plug_bio(struct bio *bio, unsigned int nr_segs)
}
EXPORT_SYMBOL_GPL(blk_zone_plug_bio);
-static void disk_zone_wplug_schedule_bio_work(struct gendisk *disk,
- struct blk_zone_wplug *zwplug)
-{
- /*
- * Take a reference on the zone write plug and schedule the submission
- * of the next plugged BIO. blk_zone_wplug_bio_work() will release the
- * reference we take here.
- */
- WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED));
- refcount_inc(&zwplug->ref);
- queue_work(disk->zone_wplugs_wq, &zwplug->bio_work);
-}
-
static void disk_zone_wplug_unplug_bio(struct gendisk *disk,
struct blk_zone_wplug *zwplug)
{
@@ -1103,16 +1126,6 @@ static void disk_zone_wplug_unplug_bio(struct gendisk *disk,
spin_lock_irqsave(&zwplug->lock, flags);
- /*
- * If we had an error, schedule error recovery. The recovery work
- * will restart submission of plugged BIOs.
- */
- if (zwplug->flags & BLK_ZONE_WPLUG_ERROR) {
- spin_unlock_irqrestore(&zwplug->lock, flags);
- kblockd_schedule_work(&disk->zone_wplugs_work);
- return;
- }
-
/* Schedule submission of the next plugged BIO if we have one. */
if (!bio_list_empty(&zwplug->bio_list)) {
disk_zone_wplug_schedule_bio_work(disk, zwplug);
@@ -1155,12 +1168,13 @@ void blk_zone_write_plug_bio_endio(struct bio *bio)
}
/*
- * If the BIO failed, mark the plug as having an error to trigger
- * recovery.
+ * If the BIO failed, abort all plugged BIOs and mark the plug as
+ * needing a write pointer update.
*/
if (bio->bi_status != BLK_STS_OK) {
spin_lock_irqsave(&zwplug->lock, flags);
- disk_zone_wplug_set_error(disk, zwplug);
+ disk_zone_wplug_abort(zwplug);
+ zwplug->flags |= BLK_ZONE_WPLUG_NEED_WP_UPDATE;
spin_unlock_irqrestore(&zwplug->lock, flags);
}
@@ -1216,6 +1230,7 @@ static void blk_zone_wplug_bio_work(struct work_struct *work)
*/
spin_lock_irqsave(&zwplug->lock, flags);
+again:
bio = bio_list_pop(&zwplug->bio_list);
if (!bio) {
zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED;
@@ -1224,10 +1239,8 @@ static void blk_zone_wplug_bio_work(struct work_struct *work)
}
if (!blk_zone_wplug_prepare_bio(zwplug, bio)) {
- /* Error recovery will decide what to do with the BIO. */
- bio_list_add_head(&zwplug->bio_list, bio);
- spin_unlock_irqrestore(&zwplug->lock, flags);
- goto put_zwplug;
+ blk_zone_wplug_bio_io_error(zwplug, bio);
+ goto again;
}
spin_unlock_irqrestore(&zwplug->lock, flags);
@@ -1249,120 +1262,6 @@ put_zwplug:
disk_put_zone_wplug(zwplug);
}
-static unsigned int blk_zone_wp_offset(struct blk_zone *zone)
-{
- switch (zone->cond) {
- case BLK_ZONE_COND_IMP_OPEN:
- case BLK_ZONE_COND_EXP_OPEN:
- case BLK_ZONE_COND_CLOSED:
- return zone->wp - zone->start;
- case BLK_ZONE_COND_FULL:
- return zone->len;
- case BLK_ZONE_COND_EMPTY:
- return 0;
- case BLK_ZONE_COND_NOT_WP:
- case BLK_ZONE_COND_OFFLINE:
- case BLK_ZONE_COND_READONLY:
- default:
- /*
- * Conventional, offline and read-only zones do not have a valid
- * write pointer.
- */
- return UINT_MAX;
- }
-}
-
-static int blk_zone_wplug_report_zone_cb(struct blk_zone *zone,
- unsigned int idx, void *data)
-{
- struct blk_zone *zonep = data;
-
- *zonep = *zone;
- return 0;
-}
-
-static void disk_zone_wplug_handle_error(struct gendisk *disk,
- struct blk_zone_wplug *zwplug)
-{
- sector_t zone_start_sector =
- bdev_zone_sectors(disk->part0) * zwplug->zone_no;
- unsigned int noio_flag;
- struct blk_zone zone;
- unsigned long flags;
- int ret;
-
- /* Get the current zone information from the device. */
- noio_flag = memalloc_noio_save();
- ret = disk->fops->report_zones(disk, zone_start_sector, 1,
- blk_zone_wplug_report_zone_cb, &zone);
- memalloc_noio_restore(noio_flag);
-
- spin_lock_irqsave(&zwplug->lock, flags);
-
- /*
- * A zone reset or finish may have cleared the error already. In such
- * case, do nothing as the report zones may have seen the "old" write
- * pointer value before the reset/finish operation completed.
- */
- if (!(zwplug->flags & BLK_ZONE_WPLUG_ERROR))
- goto unlock;
-
- zwplug->flags &= ~BLK_ZONE_WPLUG_ERROR;
-
- if (ret != 1) {
- /*
- * We failed to get the zone information, meaning that something
- * is likely really wrong with the device. Abort all remaining
- * plugged BIOs as otherwise we could endup waiting forever on
- * plugged BIOs to complete if there is a queue freeze on-going.
- */
- disk_zone_wplug_abort(zwplug);
- goto unplug;
- }
-
- /* Update the zone write pointer offset. */
- zwplug->wp_offset = blk_zone_wp_offset(&zone);
- disk_zone_wplug_abort_unaligned(disk, zwplug);
-
- /* Restart BIO submission if we still have any BIO left. */
- if (!bio_list_empty(&zwplug->bio_list)) {
- disk_zone_wplug_schedule_bio_work(disk, zwplug);
- goto unlock;
- }
-
-unplug:
- zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED;
- if (disk_should_remove_zone_wplug(disk, zwplug))
- disk_remove_zone_wplug(disk, zwplug);
-
-unlock:
- spin_unlock_irqrestore(&zwplug->lock, flags);
-}
-
-static void disk_zone_wplugs_work(struct work_struct *work)
-{
- struct gendisk *disk =
- container_of(work, struct gendisk, zone_wplugs_work);
- struct blk_zone_wplug *zwplug;
- unsigned long flags;
-
- spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
-
- while (!list_empty(&disk->zone_wplugs_err_list)) {
- zwplug = list_first_entry(&disk->zone_wplugs_err_list,
- struct blk_zone_wplug, link);
- list_del_init(&zwplug->link);
- spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
-
- disk_zone_wplug_handle_error(disk, zwplug);
- disk_put_zone_wplug(zwplug);
-
- spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
- }
-
- spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
-}
-
static inline unsigned int disk_zone_wplugs_hash_size(struct gendisk *disk)
{
return 1U << disk->zone_wplugs_hash_bits;
@@ -1371,8 +1270,6 @@ static inline unsigned int disk_zone_wplugs_hash_size(struct gendisk *disk)
void disk_init_zone_resources(struct gendisk *disk)
{
spin_lock_init(&disk->zone_wplugs_lock);
- INIT_LIST_HEAD(&disk->zone_wplugs_err_list);
- INIT_WORK(&disk->zone_wplugs_work, disk_zone_wplugs_work);
}
/*
@@ -1471,8 +1368,6 @@ void disk_free_zone_resources(struct gendisk *disk)
if (!disk->zone_wplugs_pool)
return;
- cancel_work_sync(&disk->zone_wplugs_work);
-
if (disk->zone_wplugs_wq) {
destroy_workqueue(disk->zone_wplugs_wq);
disk->zone_wplugs_wq = NULL;
@@ -1551,6 +1446,7 @@ static int disk_update_zone_resources(struct gendisk *disk,
unsigned int nr_seq_zones, nr_conv_zones;
unsigned int pool_size;
struct queue_limits lim;
+ int ret;
disk->nr_zones = args->nr_zones;
disk->zone_capacity = args->zone_capacity;
@@ -1601,7 +1497,11 @@ static int disk_update_zone_resources(struct gendisk *disk,
}
commit:
- return queue_limits_commit_update(q, &lim);
+ blk_mq_freeze_queue(q);
+ ret = queue_limits_commit_update(q, &lim);
+ blk_mq_unfreeze_queue(q);
+
+ return ret;
}
static int blk_revalidate_conv_zone(struct blk_zone *zone, unsigned int idx,
@@ -1664,6 +1564,8 @@ static int blk_revalidate_seq_zone(struct blk_zone *zone, unsigned int idx,
if (!disk->zone_wplugs_hash)
return 0;
+ disk_zone_wplug_sync_wp_offset(disk, zone);
+
wp_offset = blk_zone_wp_offset(zone);
if (!wp_offset || wp_offset >= zone->capacity)
return 0;
@@ -1794,6 +1696,7 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
memalloc_noio_restore(noio_flag);
return ret;
}
+
ret = disk->fops->report_zones(disk, 0, UINT_MAX,
blk_revalidate_zone_cb, &args);
if (!ret) {
@@ -1816,19 +1719,62 @@ int blk_revalidate_disk_zones(struct gendisk *disk)
* Set the new disk zone parameters only once the queue is frozen and
* all I/Os are completed.
*/
- blk_mq_freeze_queue(q);
if (ret > 0)
ret = disk_update_zone_resources(disk, &args);
else
pr_warn("%s: failed to revalidate zones\n", disk->disk_name);
- if (ret)
+ if (ret) {
+ blk_mq_freeze_queue(q);
disk_free_zone_resources(disk);
- blk_mq_unfreeze_queue(q);
+ blk_mq_unfreeze_queue(q);
+ }
return ret;
}
EXPORT_SYMBOL_GPL(blk_revalidate_disk_zones);
+/**
+ * blk_zone_issue_zeroout - zero-fill a block range in a zone
+ * @bdev: blockdev to write
+ * @sector: start sector
+ * @nr_sects: number of sectors to write
+ * @gfp_mask: memory allocation flags (for bio_alloc)
+ *
+ * Description:
+ * Zero-fill a block range in a zone (@sector must be equal to the zone write
+ * pointer), handling potential errors due to the (initially unknown) lack of
+ * hardware offload (See blkdev_issue_zeroout()).
+ */
+int blk_zone_issue_zeroout(struct block_device *bdev, sector_t sector,
+ sector_t nr_sects, gfp_t gfp_mask)
+{
+ int ret;
+
+ if (WARN_ON_ONCE(!bdev_is_zoned(bdev)))
+ return -EIO;
+
+ ret = blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask,
+ BLKDEV_ZERO_NOFALLBACK);
+ if (ret != -EOPNOTSUPP)
+ return ret;
+
+ /*
+ * The failed call to blkdev_issue_zeroout() advanced the zone write
+ * pointer. Undo this using a report zone to update the zone write
+ * pointer to the correct current value.
+ */
+ ret = disk_zone_sync_wp_offset(bdev->bd_disk, sector);
+ if (ret != 1)
+ return ret < 0 ? ret : -EIO;
+
+ /*
+ * Retry without BLKDEV_ZERO_NOFALLBACK to force the fallback to a
+ * regular write with zero-pages.
+ */
+ return blkdev_issue_zeroout(bdev, sector, nr_sects, gfp_mask, 0);
+}
+EXPORT_SYMBOL_GPL(blk_zone_issue_zeroout);
+
#ifdef CONFIG_BLK_DEBUG_FS
int queue_zone_wplugs_show(void *data, struct seq_file *m)
diff --git a/block/fops.c b/block/fops.c
index 2d01c9007681..13a67940d040 100644
--- a/block/fops.c
+++ b/block/fops.c
@@ -677,6 +677,7 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
struct file *file = iocb->ki_filp;
struct inode *bd_inode = bdev_file_inode(file);
struct block_device *bdev = I_BDEV(bd_inode);
+ bool atomic = iocb->ki_flags & IOCB_ATOMIC;
loff_t size = bdev_nr_bytes(bdev);
size_t shorted = 0;
ssize_t ret;
@@ -696,7 +697,7 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
if ((iocb->ki_flags & (IOCB_NOWAIT | IOCB_DIRECT)) == IOCB_NOWAIT)
return -EOPNOTSUPP;
- if (iocb->ki_flags & IOCB_ATOMIC) {
+ if (atomic) {
ret = generic_atomic_write_valid(iocb, from);
if (ret)
return ret;
@@ -704,6 +705,8 @@ static ssize_t blkdev_write_iter(struct kiocb *iocb, struct iov_iter *from)
size -= iocb->ki_pos;
if (iov_iter_count(from) > size) {
+ if (atomic)
+ return -EINVAL;
shorted = iov_iter_count(from) - size;
iov_iter_truncate(from, size);
}
diff --git a/block/genhd.c b/block/genhd.c
index 9130e163e191..79230c109fca 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -742,13 +742,10 @@ void del_gendisk(struct gendisk *disk)
* If the disk does not own the queue, allow using passthrough requests
* again. Else leave the queue frozen to fail all I/O.
*/
- if (!test_bit(GD_OWNS_QUEUE, &disk->state)) {
- blk_queue_flag_clear(QUEUE_FLAG_INIT_DONE, q);
+ if (!test_bit(GD_OWNS_QUEUE, &disk->state))
__blk_mq_unfreeze_queue(q, true);
- } else {
- if (queue_is_mq(q))
- blk_mq_exit_queue(q);
- }
+ else if (queue_is_mq(q))
+ blk_mq_exit_queue(q);
if (start_drain)
blk_unfreeze_release_lock(q, true, queue_dying);
diff --git a/block/mq-deadline.c b/block/mq-deadline.c
index acdc28756d9d..5528347b5fcf 100644
--- a/block/mq-deadline.c
+++ b/block/mq-deadline.c
@@ -685,10 +685,9 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
prio = ioprio_class_to_prio[ioprio_class];
per_prio = &dd->per_prio[prio];
- if (!rq->elv.priv[0]) {
+ if (!rq->elv.priv[0])
per_prio->stats.inserted++;
- rq->elv.priv[0] = (void *)(uintptr_t)1;
- }
+ rq->elv.priv[0] = per_prio;
if (blk_mq_sched_try_insert_merge(q, rq, free))
return;
@@ -699,8 +698,6 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
list_add(&rq->queuelist, &per_prio->dispatch);
rq->fifo_time = jiffies;
} else {
- struct list_head *insert_before;
-
deadline_add_rq_rb(per_prio, rq);
if (rq_mergeable(rq)) {
@@ -713,8 +710,7 @@ static void dd_insert_request(struct blk_mq_hw_ctx *hctx, struct request *rq,
* set expire time and add to fifo list
*/
rq->fifo_time = jiffies + dd->fifo_expire[data_dir];
- insert_before = &per_prio->fifo_list[data_dir];
- list_add_tail(&rq->queuelist, insert_before);
+ list_add_tail(&rq->queuelist, &per_prio->fifo_list[data_dir]);
}
}
@@ -753,18 +749,14 @@ static void dd_prepare_request(struct request *rq)
*/
static void dd_finish_request(struct request *rq)
{
- struct request_queue *q = rq->q;
- struct deadline_data *dd = q->elevator->elevator_data;
- const u8 ioprio_class = dd_rq_ioclass(rq);
- const enum dd_prio prio = ioprio_class_to_prio[ioprio_class];
- struct dd_per_prio *per_prio = &dd->per_prio[prio];
+ struct dd_per_prio *per_prio = rq->elv.priv[0];
/*
* The block layer core may call dd_finish_request() without having
* called dd_insert_requests(). Skip requests that bypassed I/O
* scheduling. See also blk_mq_request_bypass_insert().
*/
- if (rq->elv.priv[0])
+ if (per_prio)
atomic_inc(&per_prio->stats.completed);
}
diff --git a/crypto/adiantum.c b/crypto/adiantum.c
index 60f3883b736a..c3ef583598b4 100644
--- a/crypto/adiantum.c
+++ b/crypto/adiantum.c
@@ -646,4 +646,4 @@ MODULE_DESCRIPTION("Adiantum length-preserving encryption mode");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Eric Biggers <ebiggers@google.com>");
MODULE_ALIAS_CRYPTO("adiantum");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/ansi_cprng.c b/crypto/ansi_cprng.c
index 3f512efaba3a..64f57c4c4b06 100644
--- a/crypto/ansi_cprng.c
+++ b/crypto/ansi_cprng.c
@@ -471,4 +471,4 @@ subsys_initcall(prng_mod_init);
module_exit(prng_mod_fini);
MODULE_ALIAS_CRYPTO("stdrng");
MODULE_ALIAS_CRYPTO("ansi_cprng");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/ccm.c b/crypto/ccm.c
index 36f0acec32e1..06476b53b491 100644
--- a/crypto/ccm.c
+++ b/crypto/ccm.c
@@ -949,4 +949,4 @@ MODULE_ALIAS_CRYPTO("ccm_base");
MODULE_ALIAS_CRYPTO("rfc4309");
MODULE_ALIAS_CRYPTO("ccm");
MODULE_ALIAS_CRYPTO("cbcmac");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/cipher.c b/crypto/cipher.c
index 40cae908788e..1fe62bf79656 100644
--- a/crypto/cipher.c
+++ b/crypto/cipher.c
@@ -53,7 +53,7 @@ int crypto_cipher_setkey(struct crypto_cipher *tfm,
return cia->cia_setkey(crypto_cipher_tfm(tfm), key, keylen);
}
-EXPORT_SYMBOL_NS_GPL(crypto_cipher_setkey, CRYPTO_INTERNAL);
+EXPORT_SYMBOL_NS_GPL(crypto_cipher_setkey, "CRYPTO_INTERNAL");
static inline void cipher_crypt_one(struct crypto_cipher *tfm,
u8 *dst, const u8 *src, bool enc)
@@ -81,14 +81,14 @@ void crypto_cipher_encrypt_one(struct crypto_cipher *tfm,
{
cipher_crypt_one(tfm, dst, src, true);
}
-EXPORT_SYMBOL_NS_GPL(crypto_cipher_encrypt_one, CRYPTO_INTERNAL);
+EXPORT_SYMBOL_NS_GPL(crypto_cipher_encrypt_one, "CRYPTO_INTERNAL");
void crypto_cipher_decrypt_one(struct crypto_cipher *tfm,
u8 *dst, const u8 *src)
{
cipher_crypt_one(tfm, dst, src, false);
}
-EXPORT_SYMBOL_NS_GPL(crypto_cipher_decrypt_one, CRYPTO_INTERNAL);
+EXPORT_SYMBOL_NS_GPL(crypto_cipher_decrypt_one, "CRYPTO_INTERNAL");
struct crypto_cipher *crypto_clone_cipher(struct crypto_cipher *cipher)
{
diff --git a/crypto/cmac.c b/crypto/cmac.c
index c7aa3665b076..c66a0f4d8808 100644
--- a/crypto/cmac.c
+++ b/crypto/cmac.c
@@ -313,4 +313,4 @@ module_exit(crypto_cmac_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CMAC keyed hash algorithm");
MODULE_ALIAS_CRYPTO("cmac");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/ctr.c b/crypto/ctr.c
index 1420496062d5..73c0d6e53b2f 100644
--- a/crypto/ctr.c
+++ b/crypto/ctr.c
@@ -357,4 +357,4 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("CTR block cipher mode of operation");
MODULE_ALIAS_CRYPTO("rfc3686");
MODULE_ALIAS_CRYPTO("ctr");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/drbg.c b/crypto/drbg.c
index c323f40bed4f..f28dfc2511a2 100644
--- a/crypto/drbg.c
+++ b/crypto/drbg.c
@@ -2151,4 +2151,4 @@ MODULE_DESCRIPTION("NIST SP800-90A Deterministic Random Bit Generator (DRBG) "
CRYPTO_DRBG_HMAC_STRING
CRYPTO_DRBG_CTR_STRING);
MODULE_ALIAS_CRYPTO("stdrng");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/ecb.c b/crypto/ecb.c
index e3a67789050e..95d7e972865a 100644
--- a/crypto/ecb.c
+++ b/crypto/ecb.c
@@ -225,4 +225,4 @@ module_exit(crypto_ecb_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ECB block cipher mode of operation");
MODULE_ALIAS_CRYPTO("ecb");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/essiv.c b/crypto/essiv.c
index e63fc6442e32..1c00c3324058 100644
--- a/crypto/essiv.c
+++ b/crypto/essiv.c
@@ -649,4 +649,4 @@ module_exit(essiv_module_exit);
MODULE_DESCRIPTION("ESSIV skcipher/aead wrapper for block encryption");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("essiv");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/hctr2.c b/crypto/hctr2.c
index 87e7547ad186..cbcd673be481 100644
--- a/crypto/hctr2.c
+++ b/crypto/hctr2.c
@@ -576,4 +576,4 @@ module_exit(hctr2_module_exit);
MODULE_DESCRIPTION("HCTR2 length-preserving encryption mode");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS_CRYPTO("hctr2");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/keywrap.c b/crypto/keywrap.c
index 054d9a216fc9..385ffdfd5a9b 100644
--- a/crypto/keywrap.c
+++ b/crypto/keywrap.c
@@ -317,4 +317,4 @@ MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Stephan Mueller <smueller@chronox.de>");
MODULE_DESCRIPTION("Key Wrapping (RFC3394 / NIST SP800-38F)");
MODULE_ALIAS_CRYPTO("kw");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/pcbc.c b/crypto/pcbc.c
index ab469ba50c13..cbfb3ac14b3a 100644
--- a/crypto/pcbc.c
+++ b/crypto/pcbc.c
@@ -192,4 +192,4 @@ module_exit(crypto_pcbc_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("PCBC block cipher mode of operation");
MODULE_ALIAS_CRYPTO("pcbc");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/rsassa-pkcs1.c b/crypto/rsassa-pkcs1.c
index 4d077fc96076..f68ffd338f48 100644
--- a/crypto/rsassa-pkcs1.c
+++ b/crypto/rsassa-pkcs1.c
@@ -163,10 +163,6 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
struct rsassa_pkcs1_inst_ctx *ictx = sig_instance_ctx(inst);
const struct hash_prefix *hash_prefix = ictx->hash_prefix;
struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
- unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
- struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
- struct scatterlist in_sg[3], out_sg;
- struct crypto_wait cwait;
unsigned int pad_len;
unsigned int ps_end;
unsigned int len;
@@ -187,37 +183,25 @@ static int rsassa_pkcs1_sign(struct crypto_sig *tfm,
pad_len = ctx->key_size - slen - hash_prefix->size - 1;
- child_req = kmalloc(sizeof(*child_req) + child_reqsize + pad_len,
- GFP_KERNEL);
- if (!child_req)
- return -ENOMEM;
-
/* RFC 8017 sec 8.2.1 step 1 - EMSA-PKCS1-v1_5 encoding generation */
- in_buf = (u8 *)(child_req + 1) + child_reqsize;
+ in_buf = dst;
+ memmove(in_buf + pad_len + hash_prefix->size, src, slen);
+ memcpy(in_buf + pad_len, hash_prefix->data, hash_prefix->size);
+
ps_end = pad_len - 1;
in_buf[0] = 0x01;
memset(in_buf + 1, 0xff, ps_end - 1);
in_buf[ps_end] = 0x00;
- /* RFC 8017 sec 8.2.1 step 2 - RSA signature */
- crypto_init_wait(&cwait);
- sg_init_table(in_sg, 3);
- sg_set_buf(&in_sg[0], in_buf, pad_len);
- sg_set_buf(&in_sg[1], hash_prefix->data, hash_prefix->size);
- sg_set_buf(&in_sg[2], src, slen);
- sg_init_one(&out_sg, dst, dlen);
- akcipher_request_set_tfm(child_req, ctx->child);
- akcipher_request_set_crypt(child_req, in_sg, &out_sg,
- ctx->key_size - 1, dlen);
- akcipher_request_set_callback(child_req, CRYPTO_TFM_REQ_MAY_SLEEP,
- crypto_req_done, &cwait);
- err = crypto_akcipher_decrypt(child_req);
- err = crypto_wait_req(err, &cwait);
- if (err)
+ /* RFC 8017 sec 8.2.1 step 2 - RSA signature */
+ err = crypto_akcipher_sync_decrypt(ctx->child, in_buf,
+ ctx->key_size - 1, in_buf,
+ ctx->key_size);
+ if (err < 0)
return err;
- len = child_req->dst_len;
+ len = err;
pad_len = ctx->key_size - len;
/* Four billion to one */
@@ -239,8 +223,8 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
struct rsassa_pkcs1_ctx *ctx = crypto_sig_ctx(tfm);
unsigned int child_reqsize = crypto_akcipher_reqsize(ctx->child);
struct akcipher_request *child_req __free(kfree_sensitive) = NULL;
- struct scatterlist in_sg, out_sg;
struct crypto_wait cwait;
+ struct scatterlist sg;
unsigned int dst_len;
unsigned int pos;
u8 *out_buf;
@@ -259,13 +243,12 @@ static int rsassa_pkcs1_verify(struct crypto_sig *tfm,
return -ENOMEM;
out_buf = (u8 *)(child_req + 1) + child_reqsize;
+ memcpy(out_buf, src, slen);
crypto_init_wait(&cwait);
- sg_init_one(&in_sg, src, slen);
- sg_init_one(&out_sg, out_buf, ctx->key_size);
+ sg_init_one(&sg, out_buf, slen);
akcipher_request_set_tfm(child_req, ctx->child);
- akcipher_request_set_crypt(child_req, &in_sg, &out_sg,
- slen, ctx->key_size);
+ akcipher_request_set_crypt(child_req, &sg, &sg, slen, slen);
akcipher_request_set_callback(child_req, CRYPTO_TFM_REQ_MAY_SLEEP,
crypto_req_done, &cwait);
diff --git a/crypto/skcipher.c b/crypto/skcipher.c
index ceed7f33a67b..f74e4d0d87a2 100644
--- a/crypto/skcipher.c
+++ b/crypto/skcipher.c
@@ -1085,4 +1085,4 @@ EXPORT_SYMBOL_GPL(skcipher_alloc_instance_simple);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Symmetric key cipher type");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/testmgr.c b/crypto/testmgr.c
index 3fc908bac21a..1f5f48ab18c7 100644
--- a/crypto/testmgr.c
+++ b/crypto/testmgr.c
@@ -39,7 +39,7 @@
#include "internal.h"
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
static bool notests;
module_param(notests, bool, 0644);
diff --git a/crypto/vmac.c b/crypto/vmac.c
index bd9d70eac22e..2ea384645ecf 100644
--- a/crypto/vmac.c
+++ b/crypto/vmac.c
@@ -693,4 +693,4 @@ module_exit(vmac_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VMAC hash algorithm");
MODULE_ALIAS_CRYPTO("vmac64");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/xcbc.c b/crypto/xcbc.c
index a9e8ee9c1949..fc785667b134 100644
--- a/crypto/xcbc.c
+++ b/crypto/xcbc.c
@@ -261,4 +261,4 @@ module_exit(crypto_xcbc_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("XCBC keyed hash algorithm");
MODULE_ALIAS_CRYPTO("xcbc");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/xctr.c b/crypto/xctr.c
index 5c00147e8ec4..6ed9c85ededa 100644
--- a/crypto/xctr.c
+++ b/crypto/xctr.c
@@ -188,4 +188,4 @@ module_exit(crypto_xctr_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("XCTR block cipher mode of operation");
MODULE_ALIAS_CRYPTO("xctr");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/crypto/xts.c b/crypto/xts.c
index 672e1a3f0b0c..821060ede2cf 100644
--- a/crypto/xts.c
+++ b/crypto/xts.c
@@ -472,5 +472,5 @@ module_exit(xts_module_exit);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("XTS block cipher mode");
MODULE_ALIAS_CRYPTO("xts");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
MODULE_SOFTDEP("pre: ecb");
diff --git a/drivers/accel/habanalabs/common/memory.c b/drivers/accel/habanalabs/common/memory.c
index 3348ad12c237..601fdbe70179 100644
--- a/drivers/accel/habanalabs/common/memory.c
+++ b/drivers/accel/habanalabs/common/memory.c
@@ -14,7 +14,7 @@
#include <linux/vmalloc.h>
#include <linux/pci-p2pdma.h>
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
#define HL_MMU_DEBUG 0
diff --git a/drivers/accel/ivpu/ivpu_gem.c b/drivers/accel/ivpu/ivpu_gem.c
index d8e97a760fbc..16178054e629 100644
--- a/drivers/accel/ivpu/ivpu_gem.c
+++ b/drivers/accel/ivpu/ivpu_gem.c
@@ -409,7 +409,7 @@ static void ivpu_bo_print_info(struct ivpu_bo *bo, struct drm_printer *p)
mutex_lock(&bo->lock);
drm_printf(p, "%-9p %-3u 0x%-12llx %-10lu 0x%-8x %-4u",
- bo, bo->ctx->id, bo->vpu_addr, bo->base.base.size,
+ bo, bo->ctx ? bo->ctx->id : 0, bo->vpu_addr, bo->base.base.size,
bo->flags, kref_read(&bo->base.base.refcount));
if (bo->base.pages)
diff --git a/drivers/accel/ivpu/ivpu_mmu_context.c b/drivers/accel/ivpu/ivpu_mmu_context.c
index 891967a95bc3..0af614dfb6f9 100644
--- a/drivers/accel/ivpu/ivpu_mmu_context.c
+++ b/drivers/accel/ivpu/ivpu_mmu_context.c
@@ -612,18 +612,22 @@ int ivpu_mmu_reserved_context_init(struct ivpu_device *vdev)
if (!ivpu_mmu_ensure_pgd(vdev, &vdev->rctx.pgtable)) {
ivpu_err(vdev, "Failed to allocate root page table for reserved context\n");
ret = -ENOMEM;
- goto unlock;
+ goto err_ctx_fini;
}
ret = ivpu_mmu_cd_set(vdev, vdev->rctx.id, &vdev->rctx.pgtable);
if (ret) {
ivpu_err(vdev, "Failed to set context descriptor for reserved context\n");
- goto unlock;
+ goto err_ctx_fini;
}
-unlock:
mutex_unlock(&vdev->rctx.lock);
return ret;
+
+err_ctx_fini:
+ mutex_unlock(&vdev->rctx.lock);
+ ivpu_mmu_context_fini(vdev, &vdev->rctx);
+ return ret;
}
void ivpu_mmu_reserved_context_fini(struct ivpu_device *vdev)
diff --git a/drivers/accel/ivpu/ivpu_pm.c b/drivers/accel/ivpu/ivpu_pm.c
index dbc0711e28d1..949f4233946c 100644
--- a/drivers/accel/ivpu/ivpu_pm.c
+++ b/drivers/accel/ivpu/ivpu_pm.c
@@ -378,6 +378,7 @@ void ivpu_pm_init(struct ivpu_device *vdev)
pm_runtime_use_autosuspend(dev);
pm_runtime_set_autosuspend_delay(dev, delay);
+ pm_runtime_set_active(dev);
ivpu_dbg(vdev, PM, "Autosuspend delay = %d\n", delay);
}
@@ -392,7 +393,6 @@ void ivpu_pm_enable(struct ivpu_device *vdev)
{
struct device *dev = vdev->drm.dev;
- pm_runtime_set_active(dev);
pm_runtime_allow(dev);
pm_runtime_mark_last_busy(dev);
pm_runtime_put_autosuspend(dev);
diff --git a/drivers/accel/qaic/qaic_drv.c b/drivers/accel/qaic/qaic_drv.c
index 3575e0c984d6..4ddf89308ff5 100644
--- a/drivers/accel/qaic/qaic_drv.c
+++ b/drivers/accel/qaic/qaic_drv.c
@@ -32,7 +32,7 @@
#include "qaic_timesync.h"
#include "sahara.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
#define PCI_DEV_AIC080 0xa080
#define PCI_DEV_AIC100 0xa100
diff --git a/drivers/accessibility/speakup/Makefile b/drivers/accessibility/speakup/Makefile
index 6f6a83565c0d..14ba1cca87f4 100644
--- a/drivers/accessibility/speakup/Makefile
+++ b/drivers/accessibility/speakup/Makefile
@@ -40,9 +40,7 @@ hostprogs += makemapdata
makemapdata-objs := makemapdata.o
quiet_cmd_mkmap = MKMAP $@
- cmd_mkmap = TOPDIR=$(srctree) \
- SPKDIR=$(if $(KBUILD_EXTMOD),$(KBUILD_EXTMOD),$(srctree)/drivers/accessibility/speakup) \
- $(obj)/makemapdata > $@
+ cmd_mkmap = TOPDIR=$(srctree) SPKDIR=$(src) $(obj)/makemapdata > $@
$(obj)/mapdata.h: $(obj)/makemapdata
$(call cmd,mkmap)
diff --git a/drivers/acpi/Kconfig b/drivers/acpi/Kconfig
index d65cd08ba8e1..d81b55f5068c 100644
--- a/drivers/acpi/Kconfig
+++ b/drivers/acpi/Kconfig
@@ -135,10 +135,10 @@ config ACPI_REV_OVERRIDE_POSSIBLE
config ACPI_EC
bool "Embedded Controller"
depends on HAS_IOPORT
- default X86
+ default X86 || LOONGARCH
help
This driver handles communication with the microcontroller
- on many x86 laptops and other machines.
+ on many x86/LoongArch laptops and other machines.
config ACPI_EC_DEBUGFS
tristate "EC read/write access through /sys/kernel/debug/ec"
diff --git a/drivers/acpi/acpica/evxfregn.c b/drivers/acpi/acpica/evxfregn.c
index 95f78383bbdb..bff2d099f469 100644
--- a/drivers/acpi/acpica/evxfregn.c
+++ b/drivers/acpi/acpica/evxfregn.c
@@ -232,8 +232,6 @@ acpi_remove_address_space_handler(acpi_handle device,
/* Now we can delete the handler object */
- acpi_os_release_mutex(handler_obj->address_space.
- context_mutex);
acpi_ut_remove_reference(handler_obj);
goto unlock_and_exit;
}
diff --git a/drivers/acpi/apei/einj-cxl.c b/drivers/acpi/apei/einj-cxl.c
index a4e709937236..78da9ae543a2 100644
--- a/drivers/acpi/apei/einj-cxl.c
+++ b/drivers/acpi/apei/einj-cxl.c
@@ -45,7 +45,7 @@ int einj_cxl_available_error_type_show(struct seq_file *m, void *v)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(einj_cxl_available_error_type_show, CXL);
+EXPORT_SYMBOL_NS_GPL(einj_cxl_available_error_type_show, "CXL");
static int cxl_dport_get_sbdf(struct pci_dev *dport_dev, u64 *sbdf)
{
@@ -83,7 +83,7 @@ int einj_cxl_inject_rch_error(u64 rcrb, u64 type)
return einj_cxl_rch_error_inject(type, 0x2, rcrb, GENMASK_ULL(63, 0),
0, 0);
}
-EXPORT_SYMBOL_NS_GPL(einj_cxl_inject_rch_error, CXL);
+EXPORT_SYMBOL_NS_GPL(einj_cxl_inject_rch_error, "CXL");
int einj_cxl_inject_error(struct pci_dev *dport, u64 type)
{
@@ -104,10 +104,10 @@ int einj_cxl_inject_error(struct pci_dev *dport, u64 type)
return einj_error_inject(type, 0x4, 0, 0, 0, param4);
}
-EXPORT_SYMBOL_NS_GPL(einj_cxl_inject_error, CXL);
+EXPORT_SYMBOL_NS_GPL(einj_cxl_inject_error, "CXL");
bool einj_cxl_is_initialized(void)
{
return einj_initialized;
}
-EXPORT_SYMBOL_NS_GPL(einj_cxl_is_initialized, CXL);
+EXPORT_SYMBOL_NS_GPL(einj_cxl_is_initialized, "CXL");
diff --git a/drivers/acpi/apei/ghes.c b/drivers/acpi/apei/ghes.c
index a2491905f165..07789f0b59bc 100644
--- a/drivers/acpi/apei/ghes.c
+++ b/drivers/acpi/apei/ghes.c
@@ -726,7 +726,7 @@ int cxl_cper_register_work(struct work_struct *work)
cxl_cper_work = work;
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_cper_register_work, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_cper_register_work, "CXL");
int cxl_cper_unregister_work(struct work_struct *work)
{
@@ -737,13 +737,13 @@ int cxl_cper_unregister_work(struct work_struct *work)
cxl_cper_work = NULL;
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_cper_unregister_work, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_cper_unregister_work, "CXL");
int cxl_cper_kfifo_get(struct cxl_cper_work_data *wd)
{
return kfifo_get(&cxl_cper_fifo, wd);
}
-EXPORT_SYMBOL_NS_GPL(cxl_cper_kfifo_get, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_cper_kfifo_get, "CXL");
static bool ghes_do_proc(struct ghes *ghes,
const struct acpi_hest_generic_status *estatus)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 1f7e4c691d9e..98759d6199d3 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -1716,6 +1716,8 @@ static struct acpi_platform_list pmcg_plat_info[] __initdata = {
/* HiSilicon Hip09 Platform */
{"HISI ", "HIP09 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
"Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
+ {"HISI ", "HIP09A ", 0, ACPI_SIG_IORT, greater_than_or_equal,
+ "Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
/* HiSilicon Hip10/11 Platform uses the same SMMU IP with Hip09 */
{"HISI ", "HIP10 ", 0, ACPI_SIG_IORT, greater_than_or_equal,
"Erratum #162001900", IORT_SMMU_V3_PMCG_HISI_HIP09},
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index 5429ec9ef06f..a5d47819b3a4 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -454,8 +454,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
if (cmd_rc)
*cmd_rc = -EINVAL;
- if (cmd == ND_CMD_CALL)
+ if (cmd == ND_CMD_CALL) {
+ if (!buf || buf_len < sizeof(*call_pkg))
+ return -EINVAL;
+
call_pkg = buf;
+ }
+
func = cmd_to_func(nfit_mem, cmd, call_pkg, &family);
if (func < 0)
return func;
diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c
index 1a902a02390f..80a3481c0470 100644
--- a/drivers/acpi/numa/hmat.c
+++ b/drivers/acpi/numa/hmat.c
@@ -151,7 +151,7 @@ int acpi_get_genport_coordinates(u32 uid,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acpi_get_genport_coordinates, CXL);
+EXPORT_SYMBOL_NS_GPL(acpi_get_genport_coordinates, "CXL");
static __init void alloc_memory_initiator(unsigned int cpu_pxm)
{
diff --git a/drivers/acpi/resource.c b/drivers/acpi/resource.c
index 7fe842dae1ec..821867de43be 100644
--- a/drivers/acpi/resource.c
+++ b/drivers/acpi/resource.c
@@ -250,6 +250,9 @@ static bool acpi_decode_space(struct resource_win *win,
switch (addr->resource_type) {
case ACPI_MEMORY_RANGE:
acpi_dev_memresource_flags(res, len, wp);
+
+ if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
+ res->flags |= IORESOURCE_PREFETCH;
break;
case ACPI_IO_RANGE:
acpi_dev_ioresource_flags(res, len, iodec,
@@ -265,9 +268,6 @@ static bool acpi_decode_space(struct resource_win *win,
if (addr->producer_consumer == ACPI_PRODUCER)
res->flags |= IORESOURCE_WINDOW;
- if (addr->info.mem.caching == ACPI_PREFETCHABLE_MEMORY)
- res->flags |= IORESOURCE_PREFETCH;
-
return !(res->flags & IORESOURCE_DISABLED);
}
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 6671537cb4b7..95982c098d5b 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -1082,7 +1082,7 @@ static void __exit acpi_thermal_exit(void)
module_init(acpi_thermal_init);
module_exit(acpi_thermal_exit);
-MODULE_IMPORT_NS(ACPI_THERMAL);
+MODULE_IMPORT_NS("ACPI_THERMAL");
MODULE_AUTHOR("Paul Diefenbaugh");
MODULE_DESCRIPTION("ACPI Thermal Zone Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/acpi/thermal_lib.c b/drivers/acpi/thermal_lib.c
index 6214d6ebe1fa..f81591927e86 100644
--- a/drivers/acpi/thermal_lib.c
+++ b/drivers/acpi/thermal_lib.c
@@ -53,25 +53,25 @@ int acpi_active_trip_temp(struct acpi_device *adev, int id, int *ret_temp)
return acpi_trip_temp(adev, obj_name, ret_temp);
}
-EXPORT_SYMBOL_NS_GPL(acpi_active_trip_temp, ACPI_THERMAL);
+EXPORT_SYMBOL_NS_GPL(acpi_active_trip_temp, "ACPI_THERMAL");
int acpi_passive_trip_temp(struct acpi_device *adev, int *ret_temp)
{
return acpi_trip_temp(adev, "_PSV", ret_temp);
}
-EXPORT_SYMBOL_NS_GPL(acpi_passive_trip_temp, ACPI_THERMAL);
+EXPORT_SYMBOL_NS_GPL(acpi_passive_trip_temp, "ACPI_THERMAL");
int acpi_hot_trip_temp(struct acpi_device *adev, int *ret_temp)
{
return acpi_trip_temp(adev, "_HOT", ret_temp);
}
-EXPORT_SYMBOL_NS_GPL(acpi_hot_trip_temp, ACPI_THERMAL);
+EXPORT_SYMBOL_NS_GPL(acpi_hot_trip_temp, "ACPI_THERMAL");
int acpi_critical_trip_temp(struct acpi_device *adev, int *ret_temp)
{
return acpi_trip_temp(adev, "_CRT", ret_temp);
}
-EXPORT_SYMBOL_NS_GPL(acpi_critical_trip_temp, ACPI_THERMAL);
+EXPORT_SYMBOL_NS_GPL(acpi_critical_trip_temp, "ACPI_THERMAL");
static int thermal_temp(int error, int temp_decik, int *ret_temp)
{
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index 0230c43377c1..8ef259b4d037 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -449,6 +449,12 @@ const struct bus_type amba_bustype = {
};
EXPORT_SYMBOL_GPL(amba_bustype);
+bool dev_is_amba(const struct device *dev)
+{
+ return dev->bus == &amba_bustype;
+}
+EXPORT_SYMBOL_GPL(dev_is_amba);
+
static int __init amba_init(void)
{
return bus_register(&amba_bustype);
diff --git a/drivers/android/binder.c b/drivers/android/binder.c
index 978740537a1a..ef353ca13c35 100644
--- a/drivers/android/binder.c
+++ b/drivers/android/binder.c
@@ -1225,6 +1225,12 @@ static void binder_cleanup_ref_olocked(struct binder_ref *ref)
binder_dequeue_work(ref->proc, &ref->death->work);
binder_stats_deleted(BINDER_STAT_DEATH);
}
+
+ if (ref->freeze) {
+ binder_dequeue_work(ref->proc, &ref->freeze->work);
+ binder_stats_deleted(BINDER_STAT_FREEZE);
+ }
+
binder_stats_deleted(BINDER_STAT_REF);
}
@@ -3850,7 +3856,6 @@ binder_request_freeze_notification(struct binder_proc *proc,
{
struct binder_ref_freeze *freeze;
struct binder_ref *ref;
- bool is_frozen;
freeze = kzalloc(sizeof(*freeze), GFP_KERNEL);
if (!freeze)
@@ -3866,32 +3871,31 @@ binder_request_freeze_notification(struct binder_proc *proc,
}
binder_node_lock(ref->node);
-
- if (ref->freeze || !ref->node->proc) {
- binder_user_error("%d:%d invalid BC_REQUEST_FREEZE_NOTIFICATION %s\n",
- proc->pid, thread->pid,
- ref->freeze ? "already set" : "dead node");
+ if (ref->freeze) {
+ binder_user_error("%d:%d BC_REQUEST_FREEZE_NOTIFICATION already set\n",
+ proc->pid, thread->pid);
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
kfree(freeze);
return -EINVAL;
}
- binder_inner_proc_lock(ref->node->proc);
- is_frozen = ref->node->proc->is_frozen;
- binder_inner_proc_unlock(ref->node->proc);
binder_stats_created(BINDER_STAT_FREEZE);
INIT_LIST_HEAD(&freeze->work.entry);
freeze->cookie = handle_cookie->cookie;
freeze->work.type = BINDER_WORK_FROZEN_BINDER;
- freeze->is_frozen = is_frozen;
-
ref->freeze = freeze;
- binder_inner_proc_lock(proc);
- binder_enqueue_work_ilocked(&ref->freeze->work, &proc->todo);
- binder_wakeup_proc_ilocked(proc);
- binder_inner_proc_unlock(proc);
+ if (ref->node->proc) {
+ binder_inner_proc_lock(ref->node->proc);
+ freeze->is_frozen = ref->node->proc->is_frozen;
+ binder_inner_proc_unlock(ref->node->proc);
+
+ binder_inner_proc_lock(proc);
+ binder_enqueue_work_ilocked(&freeze->work, &proc->todo);
+ binder_wakeup_proc_ilocked(proc);
+ binder_inner_proc_unlock(proc);
+ }
binder_node_unlock(ref->node);
binder_proc_unlock(proc);
@@ -5151,6 +5155,16 @@ static void binder_release_work(struct binder_proc *proc,
} break;
case BINDER_WORK_NODE:
break;
+ case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION: {
+ struct binder_ref_freeze *freeze;
+
+ freeze = container_of(w, struct binder_ref_freeze, work);
+ binder_debug(BINDER_DEBUG_DEAD_TRANSACTION,
+ "undelivered freeze notification, %016llx\n",
+ (u64)freeze->cookie);
+ kfree(freeze);
+ binder_stats_deleted(BINDER_STAT_FREEZE);
+ } break;
default:
pr_err("unexpected work type, %d, not freed\n",
wtype);
@@ -5552,6 +5566,7 @@ static bool binder_txns_pending_ilocked(struct binder_proc *proc)
static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
{
+ struct binder_node *prev = NULL;
struct rb_node *n;
struct binder_ref *ref;
@@ -5560,7 +5575,10 @@ static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
struct binder_node *node;
node = rb_entry(n, struct binder_node, rb_node);
+ binder_inc_node_tmpref_ilocked(node);
binder_inner_proc_unlock(proc);
+ if (prev)
+ binder_put_node(prev);
binder_node_lock(node);
hlist_for_each_entry(ref, &node->refs, node_entry) {
/*
@@ -5586,10 +5604,15 @@ static void binder_add_freeze_work(struct binder_proc *proc, bool is_frozen)
}
binder_inner_proc_unlock(ref->proc);
}
+ prev = node;
binder_node_unlock(node);
binder_inner_proc_lock(proc);
+ if (proc->is_dead)
+ break;
}
binder_inner_proc_unlock(proc);
+ if (prev)
+ binder_put_node(prev);
}
static int binder_ioctl_freeze(struct binder_freeze_info *info,
@@ -6260,6 +6283,7 @@ static void binder_deferred_release(struct binder_proc *proc)
binder_release_work(proc, &proc->todo);
binder_release_work(proc, &proc->delivered_death);
+ binder_release_work(proc, &proc->delivered_freeze);
binder_debug(BINDER_DEBUG_OPEN_CLOSE,
"%s: %d threads %d, nodes %d (ref %d), refs %d, active transactions %d\n",
@@ -6393,6 +6417,12 @@ static void print_binder_work_ilocked(struct seq_file *m,
case BINDER_WORK_CLEAR_DEATH_NOTIFICATION:
seq_printf(m, "%shas cleared death notification\n", prefix);
break;
+ case BINDER_WORK_FROZEN_BINDER:
+ seq_printf(m, "%shas frozen binder\n", prefix);
+ break;
+ case BINDER_WORK_CLEAR_FREEZE_NOTIFICATION:
+ seq_printf(m, "%shas cleared freeze notification\n", prefix);
+ break;
default:
seq_printf(m, "%sunknown work: type %d\n", prefix, w->type);
break;
@@ -6539,6 +6569,10 @@ static void print_binder_proc(struct seq_file *m,
seq_puts(m, " has delivered dead binder\n");
break;
}
+ list_for_each_entry(w, &proc->delivered_freeze, entry) {
+ seq_puts(m, " has delivered freeze binder\n");
+ break;
+ }
binder_inner_proc_unlock(proc);
if (!print_all && m->count == header_pos)
m->count = start_pos;
diff --git a/drivers/ata/sata_highbank.c b/drivers/ata/sata_highbank.c
index b1b40e9551de..c8c817c51230 100644
--- a/drivers/ata/sata_highbank.c
+++ b/drivers/ata/sata_highbank.c
@@ -348,6 +348,7 @@ static int highbank_initialize_phys(struct device *dev, void __iomem *addr)
phy_nodes[phy] = phy_data.np;
cphy_base[phy] = of_iomap(phy_nodes[phy], 0);
if (cphy_base[phy] == NULL) {
+ of_node_put(phy_data.np);
return 0;
}
phy_count += 1;
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c
index cb00f8244e41..4fea1149e003 100644
--- a/drivers/atm/fore200e.c
+++ b/drivers/atm/fore200e.c
@@ -2569,7 +2569,7 @@ static struct platform_driver fore200e_sba_driver = {
.of_match_table = fore200e_sba_match,
},
.probe = fore200e_sba_probe,
- .remove_new = fore200e_sba_remove,
+ .remove = fore200e_sba_remove,
};
#endif
diff --git a/drivers/auxdisplay/Kconfig b/drivers/auxdisplay/Kconfig
index 21545ffba065..8934e6ad5772 100644
--- a/drivers/auxdisplay/Kconfig
+++ b/drivers/auxdisplay/Kconfig
@@ -489,7 +489,7 @@ config IMG_ASCII_LCD
config HT16K33
tristate "Holtek Ht16K33 LED controller with keyscan"
- depends on FB && I2C && INPUT
+ depends on FB && I2C && INPUT && BACKLIGHT_CLASS_DEVICE
select FB_SYSMEM_HELPERS
select INPUT_MATRIXKMAP
select FB_BACKLIGHT
diff --git a/drivers/auxdisplay/cfag12864bfb.c b/drivers/auxdisplay/cfag12864bfb.c
index 2b74dabe7e17..24baf6b2c587 100644
--- a/drivers/auxdisplay/cfag12864bfb.c
+++ b/drivers/auxdisplay/cfag12864bfb.c
@@ -108,7 +108,7 @@ static void cfag12864bfb_remove(struct platform_device *device)
static struct platform_driver cfag12864bfb_driver = {
.probe = cfag12864bfb_probe,
- .remove_new = cfag12864bfb_remove,
+ .remove = cfag12864bfb_remove,
.driver = {
.name = CFAG12864BFB_NAME,
},
diff --git a/drivers/auxdisplay/hd44780.c b/drivers/auxdisplay/hd44780.c
index 025dc6855cb2..0526f0d90a79 100644
--- a/drivers/auxdisplay/hd44780.c
+++ b/drivers/auxdisplay/hd44780.c
@@ -339,7 +339,7 @@ MODULE_DEVICE_TABLE(of, hd44780_of_match);
static struct platform_driver hd44780_driver = {
.probe = hd44780_probe,
- .remove_new = hd44780_remove,
+ .remove = hd44780_remove,
.driver = {
.name = "hd44780",
.of_match_table = hd44780_of_match,
diff --git a/drivers/auxdisplay/ht16k33.c b/drivers/auxdisplay/ht16k33.c
index 09deb864b27a..0b8ba754b343 100644
--- a/drivers/auxdisplay/ht16k33.c
+++ b/drivers/auxdisplay/ht16k33.c
@@ -780,5 +780,5 @@ module_i2c_driver(ht16k33_driver);
MODULE_DESCRIPTION("Holtek HT16K33 driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(LINEDISP);
+MODULE_IMPORT_NS("LINEDISP");
MODULE_AUTHOR("Robin van der Gracht <robin@protonic.nl>");
diff --git a/drivers/auxdisplay/img-ascii-lcd.c b/drivers/auxdisplay/img-ascii-lcd.c
index 9ba132dc6143..a802678a6f74 100644
--- a/drivers/auxdisplay/img-ascii-lcd.c
+++ b/drivers/auxdisplay/img-ascii-lcd.c
@@ -291,11 +291,11 @@ static struct platform_driver img_ascii_lcd_driver = {
.of_match_table = img_ascii_lcd_matches,
},
.probe = img_ascii_lcd_probe,
- .remove_new = img_ascii_lcd_remove,
+ .remove = img_ascii_lcd_remove,
};
module_platform_driver(img_ascii_lcd_driver);
MODULE_DESCRIPTION("Imagination Technologies ASCII LCD Display");
MODULE_AUTHOR("Paul Burton <paul.burton@mips.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(LINEDISP);
+MODULE_IMPORT_NS("LINEDISP");
diff --git a/drivers/auxdisplay/line-display.c b/drivers/auxdisplay/line-display.c
index 731ffdfafc4e..fcec77f100ce 100644
--- a/drivers/auxdisplay/line-display.c
+++ b/drivers/auxdisplay/line-display.c
@@ -381,7 +381,7 @@ out_put_device:
put_device(&linedisp->dev);
return err;
}
-EXPORT_SYMBOL_NS_GPL(linedisp_register, LINEDISP);
+EXPORT_SYMBOL_NS_GPL(linedisp_register, "LINEDISP");
/**
* linedisp_unregister - unregister a character line display
@@ -394,7 +394,7 @@ void linedisp_unregister(struct linedisp *linedisp)
del_timer_sync(&linedisp->timer);
put_device(&linedisp->dev);
}
-EXPORT_SYMBOL_NS_GPL(linedisp_unregister, LINEDISP);
+EXPORT_SYMBOL_NS_GPL(linedisp_unregister, "LINEDISP");
MODULE_DESCRIPTION("Character line display core support");
MODULE_LICENSE("GPL");
diff --git a/drivers/auxdisplay/max6959.c b/drivers/auxdisplay/max6959.c
index 5519c014bd29..962488197b9e 100644
--- a/drivers/auxdisplay/max6959.c
+++ b/drivers/auxdisplay/max6959.c
@@ -191,4 +191,4 @@ module_i2c_driver(max6959_i2c_driver);
MODULE_DESCRIPTION("MAX6958/6959 7-segment LED controller");
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(LINEDISP);
+MODULE_IMPORT_NS("LINEDISP");
diff --git a/drivers/auxdisplay/seg-led-gpio.c b/drivers/auxdisplay/seg-led-gpio.c
index 183ab3011cbb..f10c25e6bf12 100644
--- a/drivers/auxdisplay/seg-led-gpio.c
+++ b/drivers/auxdisplay/seg-led-gpio.c
@@ -97,7 +97,7 @@ MODULE_DEVICE_TABLE(of, seg_led_of_match);
static struct platform_driver seg_led_driver = {
.probe = seg_led_probe,
- .remove_new = seg_led_remove,
+ .remove = seg_led_remove,
.driver = {
.name = "seg-led-gpio",
.of_match_table = seg_led_of_match,
@@ -108,4 +108,4 @@ module_platform_driver(seg_led_driver);
MODULE_AUTHOR("Chris Packham <chris.packham@alliedtelesis.co.nz>");
MODULE_DESCRIPTION("7 segment LED driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(LINEDISP);
+MODULE_IMPORT_NS("LINEDISP");
diff --git a/drivers/base/arch_numa.c b/drivers/base/arch_numa.c
index e18701676426..c99f2ab105e5 100644
--- a/drivers/base/arch_numa.c
+++ b/drivers/base/arch_numa.c
@@ -208,6 +208,10 @@ static int __init numa_register_nodes(void)
{
int nid;
+ /* Check the validity of the memblock/node mapping */
+ if (!memblock_validate_numa_coverage(0))
+ return -EINVAL;
+
/* Finally register nodes. */
for_each_node_mask(nid, numa_nodes_parsed) {
unsigned long start_pfn, end_pfn;
diff --git a/drivers/base/auxiliary.c b/drivers/base/auxiliary.c
index 7823888af4f6..afa4df4c5a3f 100644
--- a/drivers/base/auxiliary.c
+++ b/drivers/base/auxiliary.c
@@ -92,7 +92,7 @@
* Auxiliary devices are created and registered by a subsystem-level core
* device that needs to break up its functionality into smaller fragments. One
* way to extend the scope of an auxiliary_device is to encapsulate it within a
- * domain- pecific structure defined by the parent device. This structure
+ * domain-specific structure defined by the parent device. This structure
* contains the auxiliary_device and any associated shared data/callbacks
* needed to establish the connection with the parent.
*
@@ -336,35 +336,6 @@ int __auxiliary_device_add(struct auxiliary_device *auxdev, const char *modname)
EXPORT_SYMBOL_GPL(__auxiliary_device_add);
/**
- * auxiliary_find_device - auxiliary device iterator for locating a particular device.
- * @start: Device to begin with
- * @data: Data to pass to match function
- * @match: Callback function to check device
- *
- * This function returns a reference to a device that is 'found'
- * for later use, as determined by the @match callback.
- *
- * The reference returned should be released with put_device().
- *
- * The callback should return 0 if the device doesn't match and non-zero
- * if it does. If the callback returns non-zero, this function will
- * return to the caller and not iterate over any more devices.
- */
-struct auxiliary_device *auxiliary_find_device(struct device *start,
- const void *data,
- device_match_t match)
-{
- struct device *dev;
-
- dev = bus_find_device(&auxiliary_bus_type, start, data, match);
- if (!dev)
- return NULL;
-
- return to_auxiliary_dev(dev);
-}
-EXPORT_SYMBOL_GPL(auxiliary_find_device);
-
-/**
* __auxiliary_driver_register - register a driver for auxiliary bus devices
* @auxdrv: auxiliary_driver structure
* @owner: owning module/driver
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c
index 7a7609298e18..cf0d455209d7 100644
--- a/drivers/base/cacheinfo.c
+++ b/drivers/base/cacheinfo.c
@@ -58,7 +58,7 @@ bool last_level_cache_is_valid(unsigned int cpu)
{
struct cacheinfo *llc;
- if (!cache_leaves(cpu))
+ if (!cache_leaves(cpu) || !per_cpu_cacheinfo(cpu))
return false;
llc = per_cpu_cacheinfo_idx(cpu, cache_leaves(cpu) - 1);
@@ -254,11 +254,11 @@ static int of_count_cache_leaves(struct device_node *np)
{
unsigned int leaves = 0;
- if (of_property_read_bool(np, "cache-size"))
+ if (of_property_present(np, "cache-size"))
++leaves;
- if (of_property_read_bool(np, "i-cache-size"))
+ if (of_property_present(np, "i-cache-size"))
++leaves;
- if (of_property_read_bool(np, "d-cache-size"))
+ if (of_property_present(np, "d-cache-size"))
++leaves;
if (!leaves) {
@@ -367,9 +367,7 @@ static int cache_shared_cpu_map_setup(unsigned int cpu)
cpumask_set_cpu(cpu, &this_leaf->shared_cpu_map);
for_each_online_cpu(i) {
- struct cpu_cacheinfo *sib_cpu_ci = get_cpu_cacheinfo(i);
-
- if (i == cpu || !sib_cpu_ci->info_list)
+ if (i == cpu || !per_cpu_cacheinfo(i))
continue;/* skip if itself or no cacheinfo */
for (sib_index = 0; sib_index < cache_leaves(i); sib_index++) {
sib_leaf = per_cpu_cacheinfo_idx(i, sib_index);
@@ -409,10 +407,7 @@ static void cache_shared_cpu_map_remove(unsigned int cpu)
for (index = 0; index < cache_leaves(cpu); index++) {
this_leaf = per_cpu_cacheinfo_idx(cpu, index);
for_each_cpu(sibling, &this_leaf->shared_cpu_map) {
- struct cpu_cacheinfo *sib_cpu_ci =
- get_cpu_cacheinfo(sibling);
-
- if (sibling == cpu || !sib_cpu_ci->info_list)
+ if (sibling == cpu || !per_cpu_cacheinfo(sibling))
continue;/* skip if itself or no cacheinfo */
for (sib_index = 0; sib_index < cache_leaves(sibling); sib_index++) {
@@ -463,11 +458,9 @@ int __weak populate_cache_leaves(unsigned int cpu)
return -ENOENT;
}
-static inline
-int allocate_cache_info(int cpu)
+static inline int allocate_cache_info(int cpu)
{
- per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu),
- sizeof(struct cacheinfo), GFP_ATOMIC);
+ per_cpu_cacheinfo(cpu) = kcalloc(cache_leaves(cpu), sizeof(struct cacheinfo), GFP_ATOMIC);
if (!per_cpu_cacheinfo(cpu)) {
cache_leaves(cpu) = 0;
return -ENOMEM;
@@ -539,7 +532,11 @@ static inline int init_level_allocate_ci(unsigned int cpu)
*/
ci_cacheinfo(cpu)->early_ci_levels = false;
- if (cache_leaves(cpu) <= early_leaves)
+ /*
+ * Some architectures (e.g., x86) do not use early initialization.
+ * Allocate memory now in such case.
+ */
+ if (cache_leaves(cpu) <= early_leaves && per_cpu_cacheinfo(cpu))
return 0;
kfree(per_cpu_cacheinfo(cpu));
diff --git a/drivers/base/class.c b/drivers/base/class.c
index cb5359235c70..582b5a02a5c4 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -405,7 +405,7 @@ int class_for_each_device(const struct class *class, const struct device *start,
if (!class)
return -EINVAL;
if (!sp) {
- WARN(1, "%s called for class '%s' before it was initialized",
+ WARN(1, "%s called for class '%s' before it was registered",
__func__, class->name);
return -EINVAL;
}
@@ -453,7 +453,7 @@ struct device *class_find_device(const struct class *class, const struct device
if (!class)
return NULL;
if (!sp) {
- WARN(1, "%s called for class '%s' before it was initialized",
+ WARN(1, "%s called for class '%s' before it was registered",
__func__, class->name);
return NULL;
}
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 529af59e25ff..94865c9d8adc 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -552,7 +552,7 @@ void device_link_wait_removal(void)
}
EXPORT_SYMBOL_GPL(device_link_wait_removal);
-static struct class devlink_class = {
+static const struct class devlink_class = {
.name = "devlink",
.dev_groups = devlink_groups,
.dev_release = devlink_dev_release,
@@ -1971,7 +1971,7 @@ static struct device *fwnode_get_next_parent_dev(const struct fwnode_handle *fwn
/**
* __fw_devlink_relax_cycles - Relax and mark dependency cycles.
- * @con: Potential consumer device.
+ * @con_handle: Potential consumer device fwnode.
* @sup_handle: Potential supplier's fwnode.
*
* Needs to be called with fwnode_lock and device link lock held.
@@ -1989,10 +1989,10 @@ static struct device *fwnode_get_next_parent_dev(const struct fwnode_handle *fwn
*
* Return true if one or more cycles were found. Otherwise, return false.
*/
-static bool __fw_devlink_relax_cycles(struct device *con,
+static bool __fw_devlink_relax_cycles(struct fwnode_handle *con_handle,
struct fwnode_handle *sup_handle)
{
- struct device *sup_dev = NULL, *par_dev = NULL;
+ struct device *sup_dev = NULL, *par_dev = NULL, *con_dev = NULL;
struct fwnode_link *link;
struct device_link *dev_link;
bool ret = false;
@@ -2009,22 +2009,22 @@ static bool __fw_devlink_relax_cycles(struct device *con,
sup_handle->flags |= FWNODE_FLAG_VISITED;
- sup_dev = get_dev_from_fwnode(sup_handle);
-
/* Termination condition. */
- if (sup_dev == con) {
+ if (sup_handle == con_handle) {
pr_debug("----- cycle: start -----\n");
ret = true;
goto out;
}
+ sup_dev = get_dev_from_fwnode(sup_handle);
+ con_dev = get_dev_from_fwnode(con_handle);
/*
* If sup_dev is bound to a driver and @con hasn't started binding to a
* driver, sup_dev can't be a consumer of @con. So, no need to check
* further.
*/
if (sup_dev && sup_dev->links.status == DL_DEV_DRIVER_BOUND &&
- con->links.status == DL_DEV_NO_DRIVER) {
+ con_dev && con_dev->links.status == DL_DEV_NO_DRIVER) {
ret = false;
goto out;
}
@@ -2033,7 +2033,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
if (link->flags & FWLINK_FLAG_IGNORE)
continue;
- if (__fw_devlink_relax_cycles(con, link->supplier)) {
+ if (__fw_devlink_relax_cycles(con_handle, link->supplier)) {
__fwnode_link_cycle(link);
ret = true;
}
@@ -2048,7 +2048,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
else
par_dev = fwnode_get_next_parent_dev(sup_handle);
- if (par_dev && __fw_devlink_relax_cycles(con, par_dev->fwnode)) {
+ if (par_dev && __fw_devlink_relax_cycles(con_handle, par_dev->fwnode)) {
pr_debug("%pfwf: cycle: child of %pfwf\n", sup_handle,
par_dev->fwnode);
ret = true;
@@ -2066,7 +2066,7 @@ static bool __fw_devlink_relax_cycles(struct device *con,
!(dev_link->flags & DL_FLAG_CYCLE))
continue;
- if (__fw_devlink_relax_cycles(con,
+ if (__fw_devlink_relax_cycles(con_handle,
dev_link->supplier->fwnode)) {
pr_debug("%pfwf: cycle: depends on %pfwf\n", sup_handle,
dev_link->supplier->fwnode);
@@ -2114,11 +2114,6 @@ static int fw_devlink_create_devlink(struct device *con,
if (link->flags & FWLINK_FLAG_IGNORE)
return 0;
- if (con->fwnode == link->consumer)
- flags = fw_devlink_get_flags(link->flags);
- else
- flags = FW_DEVLINK_FLAGS_PERMISSIVE;
-
/*
* In some cases, a device P might also be a supplier to its child node
* C. However, this would defer the probe of C until the probe of P
@@ -2139,25 +2134,23 @@ static int fw_devlink_create_devlink(struct device *con,
return -EINVAL;
/*
- * SYNC_STATE_ONLY device links don't block probing and supports cycles.
- * So, one might expect that cycle detection isn't necessary for them.
- * However, if the device link was marked as SYNC_STATE_ONLY because
- * it's part of a cycle, then we still need to do cycle detection. This
- * is because the consumer and supplier might be part of multiple cycles
- * and we need to detect all those cycles.
+ * Don't try to optimize by not calling the cycle detection logic under
+ * certain conditions. There's always some corner case that won't get
+ * detected.
*/
- if (!device_link_flag_is_sync_state_only(flags) ||
- flags & DL_FLAG_CYCLE) {
- device_links_write_lock();
- if (__fw_devlink_relax_cycles(con, sup_handle)) {
- __fwnode_link_cycle(link);
- flags = fw_devlink_get_flags(link->flags);
- pr_debug("----- cycle: end -----\n");
- dev_info(con, "Fixed dependency cycle(s) with %pfwf\n",
- sup_handle);
- }
- device_links_write_unlock();
+ device_links_write_lock();
+ if (__fw_devlink_relax_cycles(link->consumer, sup_handle)) {
+ __fwnode_link_cycle(link);
+ pr_debug("----- cycle: end -----\n");
+ pr_info("%pfwf: Fixed dependency cycle(s) with %pfwf\n",
+ link->consumer, sup_handle);
}
+ device_links_write_unlock();
+
+ if (con->fwnode == link->consumer)
+ flags = fw_devlink_get_flags(link->flags);
+ else
+ flags = FW_DEVLINK_FLAGS_PERMISSIVE;
if (sup_handle->flags & FWNODE_FLAG_NOT_DEVICE)
sup_dev = fwnode_get_next_parent_dev(sup_handle);
@@ -2180,8 +2173,8 @@ static int fw_devlink_create_devlink(struct device *con,
}
if (con != sup_dev && !device_link_add(con, sup_dev, flags)) {
- dev_err(con, "Failed to create device link (0x%x) with %s\n",
- flags, dev_name(sup_dev));
+ dev_err(con, "Failed to create device link (0x%x) with supplier %s for %pfwf\n",
+ flags, dev_name(sup_dev), link->consumer);
ret = -EINVAL;
}
diff --git a/drivers/base/firmware_loader/builtin/main.c b/drivers/base/firmware_loader/builtin/main.c
index a065c3150897..d36befebb1b9 100644
--- a/drivers/base/firmware_loader/builtin/main.c
+++ b/drivers/base/firmware_loader/builtin/main.c
@@ -61,7 +61,7 @@ bool firmware_request_builtin(struct firmware *fw, const char *name)
return false;
}
-EXPORT_SYMBOL_NS_GPL(firmware_request_builtin, TEST_FIRMWARE);
+EXPORT_SYMBOL_NS_GPL(firmware_request_builtin, "TEST_FIRMWARE");
/**
* firmware_request_builtin_buf() - load builtin firmware into optional buffer
diff --git a/drivers/base/firmware_loader/fallback_table.c b/drivers/base/firmware_loader/fallback_table.c
index 8432ab2c3b3c..ddb70e29eb42 100644
--- a/drivers/base/firmware_loader/fallback_table.c
+++ b/drivers/base/firmware_loader/fallback_table.c
@@ -22,7 +22,7 @@ struct firmware_fallback_config fw_fallback_config = {
.loading_timeout = 60,
.old_timeout = 60,
};
-EXPORT_SYMBOL_NS_GPL(fw_fallback_config, FIRMWARE_LOADER_PRIVATE);
+EXPORT_SYMBOL_NS_GPL(fw_fallback_config, "FIRMWARE_LOADER_PRIVATE");
#ifdef CONFIG_SYSCTL
static struct ctl_table firmware_config_table[] = {
@@ -56,13 +56,13 @@ int register_firmware_config_sysctl(void)
return -ENOMEM;
return 0;
}
-EXPORT_SYMBOL_NS_GPL(register_firmware_config_sysctl, FIRMWARE_LOADER_PRIVATE);
+EXPORT_SYMBOL_NS_GPL(register_firmware_config_sysctl, "FIRMWARE_LOADER_PRIVATE");
void unregister_firmware_config_sysctl(void)
{
unregister_sysctl_table(firmware_config_sysct_table_header);
firmware_config_sysct_table_header = NULL;
}
-EXPORT_SYMBOL_NS_GPL(unregister_firmware_config_sysctl, FIRMWARE_LOADER_PRIVATE);
+EXPORT_SYMBOL_NS_GPL(unregister_firmware_config_sysctl, "FIRMWARE_LOADER_PRIVATE");
#endif /* CONFIG_SYSCTL */
diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c
index 324a9a3c087a..cb0912ea3e62 100644
--- a/drivers/base/firmware_loader/main.c
+++ b/drivers/base/firmware_loader/main.c
@@ -829,19 +829,18 @@ static void fw_log_firmware_info(const struct firmware *fw, const char *name, st
shash->tfm = alg;
if (crypto_shash_digest(shash, fw->data, fw->size, sha256buf) < 0)
- goto out_shash;
+ goto out_free;
for (int i = 0; i < SHA256_DIGEST_SIZE; i++)
sprintf(&outbuf[i * 2], "%02x", sha256buf[i]);
outbuf[SHA256_BLOCK_SIZE] = 0;
dev_dbg(device, "Loaded FW: %s, sha256: %s\n", name, outbuf);
-out_shash:
- crypto_free_shash(alg);
out_free:
kfree(shash);
kfree(outbuf);
kfree(sha256buf);
+ crypto_free_shash(alg);
}
#else
static void fw_log_firmware_info(const struct firmware *fw, const char *name,
@@ -1075,8 +1074,8 @@ EXPORT_SYMBOL_GPL(firmware_request_platform);
/**
* firmware_request_cache() - cache firmware for suspend so resume can use it
- * @name: name of firmware file
* @device: device for which firmware should be cached for
+ * @name: name of firmware file
*
* There are some devices with an optimization that enables the device to not
* require loading firmware on system reboot. This optimization may still
diff --git a/drivers/base/firmware_loader/sysfs.h b/drivers/base/firmware_loader/sysfs.h
index 2060add8ef81..1cabea544a40 100644
--- a/drivers/base/firmware_loader/sysfs.h
+++ b/drivers/base/firmware_loader/sysfs.h
@@ -6,7 +6,7 @@
#include "firmware.h"
-MODULE_IMPORT_NS(FIRMWARE_LOADER_PRIVATE);
+MODULE_IMPORT_NS("FIRMWARE_LOADER_PRIVATE");
extern struct firmware_fallback_config fw_fallback_config;
extern struct device_attribute dev_attr_loading;
diff --git a/drivers/base/node.c b/drivers/base/node.c
index eb72580288e6..0ea653fa3433 100644
--- a/drivers/base/node.c
+++ b/drivers/base/node.c
@@ -27,7 +27,7 @@ static const struct bus_type node_subsys = {
};
static inline ssize_t cpumap_read(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -45,10 +45,10 @@ static inline ssize_t cpumap_read(struct file *file, struct kobject *kobj,
return n;
}
-static BIN_ATTR_RO(cpumap, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cpumap, CPUMAP_FILE_MAX_BYTES);
static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -66,7 +66,7 @@ static inline ssize_t cpulist_read(struct file *file, struct kobject *kobj,
return n;
}
-static BIN_ATTR_RO(cpulist, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cpulist, CPULIST_FILE_MAX_BYTES);
/**
* struct node_access_nodes - Access class device to hold user visible
@@ -578,7 +578,7 @@ static struct attribute *node_dev_attrs[] = {
NULL
};
-static struct bin_attribute *node_dev_bin_attrs[] = {
+static const struct bin_attribute *node_dev_bin_attrs[] = {
&bin_attr_cpumap,
&bin_attr_cpulist,
NULL
@@ -586,7 +586,7 @@ static struct bin_attribute *node_dev_bin_attrs[] = {
static const struct attribute_group node_dev_group = {
.attrs = node_dev_attrs,
- .bin_attrs = node_dev_bin_attrs
+ .bin_attrs_new = node_dev_bin_attrs,
};
static const struct attribute_group *node_dev_groups[] = {
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index a1474fb67db9..f8163b559bf9 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -509,14 +509,6 @@ static ssize_t wakeup_last_time_ms_show(struct device *dev,
return sysfs_emit(buf, "%lld\n", msec);
}
-static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
- kgid_t kgid)
-{
- if (dev->power.wakeup && dev->power.wakeup->dev)
- return device_change_owner(dev->power.wakeup->dev, kuid, kgid);
- return 0;
-}
-
static DEVICE_ATTR_RO(wakeup_last_time_ms);
#ifdef CONFIG_PM_AUTOSLEEP
@@ -541,6 +533,15 @@ static ssize_t wakeup_prevent_sleep_time_ms_show(struct device *dev,
static DEVICE_ATTR_RO(wakeup_prevent_sleep_time_ms);
#endif /* CONFIG_PM_AUTOSLEEP */
+
+static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
+ kgid_t kgid)
+{
+ if (dev->power.wakeup && dev->power.wakeup->dev)
+ return device_change_owner(dev->power.wakeup->dev, kuid, kgid);
+ return 0;
+}
+
#else /* CONFIG_PM_SLEEP */
static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
kgid_t kgid)
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 53131a7ede0a..5962ea1230a1 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -598,6 +598,17 @@ int regmap_attach_dev(struct device *dev, struct regmap *map,
}
EXPORT_SYMBOL_GPL(regmap_attach_dev);
+static int dev_get_regmap_match(struct device *dev, void *res, void *data);
+
+static int regmap_detach_dev(struct device *dev, struct regmap *map)
+{
+ if (!dev)
+ return 0;
+
+ return devres_release(dev, dev_get_regmap_release,
+ dev_get_regmap_match, (void *)map->name);
+}
+
static enum regmap_endian regmap_get_reg_endian(const struct regmap_bus *bus,
const struct regmap_config *config)
{
@@ -1052,13 +1063,13 @@ skip_format_initialization:
/* Sanity check */
if (range_cfg->range_max < range_cfg->range_min) {
- dev_err(map->dev, "Invalid range %d: %d < %d\n", i,
+ dev_err(map->dev, "Invalid range %d: %u < %u\n", i,
range_cfg->range_max, range_cfg->range_min);
goto err_range;
}
if (range_cfg->range_max > map->max_register) {
- dev_err(map->dev, "Invalid range %d: %d > %d\n", i,
+ dev_err(map->dev, "Invalid range %d: %u > %u\n", i,
range_cfg->range_max, map->max_register);
goto err_range;
}
@@ -1445,6 +1456,7 @@ void regmap_exit(struct regmap *map)
{
struct regmap_async *async;
+ regmap_detach_dev(map->dev, map);
regcache_exit(map);
regmap_debugfs_exit(map);
diff --git a/drivers/base/topology.c b/drivers/base/topology.c
index 89f98be5c5b9..cf160dd2c27b 100644
--- a/drivers/base/topology.c
+++ b/drivers/base/topology.c
@@ -23,7 +23,7 @@ static ssize_t name##_show(struct device *dev, \
#define define_siblings_read_func(name, mask) \
static ssize_t name##_read(struct file *file, struct kobject *kobj, \
- struct bin_attribute *attr, char *buf, \
+ const struct bin_attribute *attr, char *buf, \
loff_t off, size_t count) \
{ \
struct device *dev = kobj_to_dev(kobj); \
@@ -33,7 +33,7 @@ static ssize_t name##_read(struct file *file, struct kobject *kobj, \
} \
\
static ssize_t name##_list_read(struct file *file, struct kobject *kobj, \
- struct bin_attribute *attr, char *buf, \
+ const struct bin_attribute *attr, char *buf, \
loff_t off, size_t count) \
{ \
struct device *dev = kobj_to_dev(kobj); \
@@ -62,50 +62,50 @@ define_id_show_func(ppin, "0x%llx");
static DEVICE_ATTR_ADMIN_RO(ppin);
define_siblings_read_func(thread_siblings, sibling_cpumask);
-static BIN_ATTR_RO(thread_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(thread_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(thread_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(thread_siblings_list, CPULIST_FILE_MAX_BYTES);
define_siblings_read_func(core_cpus, sibling_cpumask);
-static BIN_ATTR_RO(core_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(core_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_cpus_list, CPULIST_FILE_MAX_BYTES);
define_siblings_read_func(core_siblings, core_cpumask);
-static BIN_ATTR_RO(core_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(core_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(core_siblings_list, CPULIST_FILE_MAX_BYTES);
#ifdef TOPOLOGY_CLUSTER_SYSFS
define_siblings_read_func(cluster_cpus, cluster_cpumask);
-static BIN_ATTR_RO(cluster_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(cluster_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cluster_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(cluster_cpus_list, CPULIST_FILE_MAX_BYTES);
#endif
#ifdef TOPOLOGY_DIE_SYSFS
define_siblings_read_func(die_cpus, die_cpumask);
-static BIN_ATTR_RO(die_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(die_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(die_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(die_cpus_list, CPULIST_FILE_MAX_BYTES);
#endif
define_siblings_read_func(package_cpus, core_cpumask);
-static BIN_ATTR_RO(package_cpus, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(package_cpus_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(package_cpus, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(package_cpus_list, CPULIST_FILE_MAX_BYTES);
#ifdef TOPOLOGY_BOOK_SYSFS
define_id_show_func(book_id, "%d");
static DEVICE_ATTR_RO(book_id);
define_siblings_read_func(book_siblings, book_cpumask);
-static BIN_ATTR_RO(book_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(book_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(book_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(book_siblings_list, CPULIST_FILE_MAX_BYTES);
#endif
#ifdef TOPOLOGY_DRAWER_SYSFS
define_id_show_func(drawer_id, "%d");
static DEVICE_ATTR_RO(drawer_id);
define_siblings_read_func(drawer_siblings, drawer_cpumask);
-static BIN_ATTR_RO(drawer_siblings, CPUMAP_FILE_MAX_BYTES);
-static BIN_ATTR_RO(drawer_siblings_list, CPULIST_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(drawer_siblings, CPUMAP_FILE_MAX_BYTES);
+static const BIN_ATTR_RO(drawer_siblings_list, CPULIST_FILE_MAX_BYTES);
#endif
-static struct bin_attribute *bin_attrs[] = {
+static const struct bin_attribute *const bin_attrs[] = {
&bin_attr_core_cpus,
&bin_attr_core_cpus_list,
&bin_attr_thread_siblings,
@@ -163,7 +163,7 @@ static umode_t topology_is_visible(struct kobject *kobj,
static const struct attribute_group topology_attr_group = {
.attrs = default_attrs,
- .bin_attrs = bin_attrs,
+ .bin_attrs_new = bin_attrs,
.is_visible = topology_is_visible,
.name = "topology"
};
diff --git a/drivers/base/trace.h b/drivers/base/trace.h
index e52b6eae060d..3b83b13a57ff 100644
--- a/drivers/base/trace.h
+++ b/drivers/base/trace.h
@@ -24,18 +24,18 @@ DECLARE_EVENT_CLASS(devres,
__field(struct device *, dev)
__field(const char *, op)
__field(void *, node)
- __field(const char *, name)
+ __string(name, name)
__field(size_t, size)
),
TP_fast_assign(
__assign_str(devname);
__entry->op = op;
__entry->node = node;
- __entry->name = name;
+ __assign_str(name);
__entry->size = size;
),
TP_printk("%s %3s %p %s (%zu bytes)", __get_str(devname),
- __entry->op, __entry->node, __entry->name, __entry->size)
+ __entry->op, __entry->node, __get_str(name), __entry->size)
);
DEFINE_EVENT(devres, devres_log,
diff --git a/drivers/bcma/host_soc.c b/drivers/bcma/host_soc.c
index 8ae0b918e740..20b1816c570b 100644
--- a/drivers/bcma/host_soc.c
+++ b/drivers/bcma/host_soc.c
@@ -261,7 +261,7 @@ static struct platform_driver bcma_host_soc_driver = {
.of_match_table = bcma_host_soc_of_match,
},
.probe = bcma_host_soc_probe,
- .remove_new = bcma_host_soc_remove,
+ .remove = bcma_host_soc_remove,
};
int __init bcma_host_soc_register_driver(void)
diff --git a/drivers/block/brd.c b/drivers/block/brd.c
index 5a95671d8151..292f127cae0a 100644
--- a/drivers/block/brd.c
+++ b/drivers/block/brd.c
@@ -231,8 +231,10 @@ static void brd_do_discard(struct brd_device *brd, sector_t sector, u32 size)
xa_lock(&brd->brd_pages);
while (size >= PAGE_SIZE && aligned_sector < rd_size * 2) {
page = __xa_erase(&brd->brd_pages, aligned_sector >> PAGE_SECTORS_SHIFT);
- if (page)
+ if (page) {
__free_page(page);
+ brd->brd_nr_pages--;
+ }
aligned_sector += PAGE_SECTORS;
size -= PAGE_SIZE;
}
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index fe9bb4fb5f1b..8f6761c27c68 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -770,12 +770,11 @@ static void loop_sysfs_exit(struct loop_device *lo)
&loop_attribute_group);
}
-static void loop_config_discard(struct loop_device *lo,
- struct queue_limits *lim)
+static void loop_get_discard_config(struct loop_device *lo,
+ u32 *granularity, u32 *max_discard_sectors)
{
struct file *file = lo->lo_backing_file;
struct inode *inode = file->f_mapping->host;
- u32 granularity = 0, max_discard_sectors = 0;
struct kstatfs sbuf;
/*
@@ -788,24 +787,17 @@ static void loop_config_discard(struct loop_device *lo,
if (S_ISBLK(inode->i_mode)) {
struct block_device *bdev = I_BDEV(inode);
- max_discard_sectors = bdev_write_zeroes_sectors(bdev);
- granularity = bdev_discard_granularity(bdev);
+ *max_discard_sectors = bdev_write_zeroes_sectors(bdev);
+ *granularity = bdev_discard_granularity(bdev);
/*
* We use punch hole to reclaim the free space used by the
* image a.k.a. discard.
*/
} else if (file->f_op->fallocate && !vfs_statfs(&file->f_path, &sbuf)) {
- max_discard_sectors = UINT_MAX >> 9;
- granularity = sbuf.f_bsize;
+ *max_discard_sectors = UINT_MAX >> 9;
+ *granularity = sbuf.f_bsize;
}
-
- lim->max_hw_discard_sectors = max_discard_sectors;
- lim->max_write_zeroes_sectors = max_discard_sectors;
- if (max_discard_sectors)
- lim->discard_granularity = granularity;
- else
- lim->discard_granularity = 0;
}
struct loop_worker {
@@ -991,6 +983,7 @@ static int loop_reconfigure_limits(struct loop_device *lo, unsigned int bsize)
struct inode *inode = file->f_mapping->host;
struct block_device *backing_bdev = NULL;
struct queue_limits lim;
+ u32 granularity = 0, max_discard_sectors = 0;
if (S_ISBLK(inode->i_mode))
backing_bdev = I_BDEV(inode);
@@ -1000,6 +993,8 @@ static int loop_reconfigure_limits(struct loop_device *lo, unsigned int bsize)
if (!bsize)
bsize = loop_default_blocksize(lo, backing_bdev);
+ loop_get_discard_config(lo, &granularity, &max_discard_sectors);
+
lim = queue_limits_start_update(lo->lo_queue);
lim.logical_block_size = bsize;
lim.physical_block_size = bsize;
@@ -1009,7 +1004,12 @@ static int loop_reconfigure_limits(struct loop_device *lo, unsigned int bsize)
lim.features |= BLK_FEAT_WRITE_CACHE;
if (backing_bdev && !bdev_nonrot(backing_bdev))
lim.features |= BLK_FEAT_ROTATIONAL;
- loop_config_discard(lo, &lim);
+ lim.max_hw_discard_sectors = max_discard_sectors;
+ lim.max_write_zeroes_sectors = max_discard_sectors;
+ if (max_discard_sectors)
+ lim.discard_granularity = granularity;
+ else
+ lim.discard_granularity = 0;
return queue_limits_commit_update(lo->lo_queue, &lim);
}
diff --git a/drivers/block/rnull.rs b/drivers/block/rnull.rs
index 5de7223beb4d..9cca05dcf772 100644
--- a/drivers/block/rnull.rs
+++ b/drivers/block/rnull.rs
@@ -28,6 +28,7 @@ module! {
type: NullBlkModule,
name: "rnull_mod",
author: "Andreas Hindborg",
+ description: "Rust implementation of the C null block driver",
license: "GPL v2",
}
diff --git a/drivers/block/swim.c b/drivers/block/swim.c
index 126f151c4f2c..be4ac58afe41 100644
--- a/drivers/block/swim.c
+++ b/drivers/block/swim.c
@@ -944,7 +944,7 @@ static void swim_remove(struct platform_device *dev)
static struct platform_driver swim_driver = {
.probe = swim_probe,
- .remove_new = swim_remove,
+ .remove = swim_remove,
.driver = {
.name = CARDNAME,
},
diff --git a/drivers/block/ublk_drv.c b/drivers/block/ublk_drv.c
index c6d18cd8af44..934ab9332c80 100644
--- a/drivers/block/ublk_drv.c
+++ b/drivers/block/ublk_drv.c
@@ -1618,6 +1618,21 @@ static void ublk_unquiesce_dev(struct ublk_device *ub)
blk_mq_kick_requeue_list(ub->ub_disk->queue);
}
+static struct gendisk *ublk_detach_disk(struct ublk_device *ub)
+{
+ struct gendisk *disk;
+
+ /* Sync with ublk_abort_queue() by holding the lock */
+ spin_lock(&ub->lock);
+ disk = ub->ub_disk;
+ ub->dev_info.state = UBLK_S_DEV_DEAD;
+ ub->dev_info.ublksrv_pid = -1;
+ ub->ub_disk = NULL;
+ spin_unlock(&ub->lock);
+
+ return disk;
+}
+
static void ublk_stop_dev(struct ublk_device *ub)
{
struct gendisk *disk;
@@ -1631,14 +1646,7 @@ static void ublk_stop_dev(struct ublk_device *ub)
ublk_unquiesce_dev(ub);
}
del_gendisk(ub->ub_disk);
-
- /* Sync with ublk_abort_queue() by holding the lock */
- spin_lock(&ub->lock);
- disk = ub->ub_disk;
- ub->dev_info.state = UBLK_S_DEV_DEAD;
- ub->dev_info.ublksrv_pid = -1;
- ub->ub_disk = NULL;
- spin_unlock(&ub->lock);
+ disk = ublk_detach_disk(ub);
put_disk(disk);
unlock:
mutex_unlock(&ub->mutex);
@@ -2336,7 +2344,7 @@ static int ublk_ctrl_start_dev(struct ublk_device *ub, struct io_uring_cmd *cmd)
out_put_cdev:
if (ret) {
- ub->dev_info.state = UBLK_S_DEV_DEAD;
+ ublk_detach_disk(ub);
ublk_put_device(ub);
}
if (ret)
@@ -3041,7 +3049,7 @@ static int ublk_ctrl_uring_cmd(struct io_uring_cmd *cmd,
ret = ublk_ctrl_end_recovery(ub, cmd);
break;
default:
- ret = -ENOTSUPP;
+ ret = -EOPNOTSUPP;
break;
}
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index c0cdba71f436..3efe378f1386 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -1586,9 +1586,12 @@ static void virtblk_remove(struct virtio_device *vdev)
static int virtblk_freeze(struct virtio_device *vdev)
{
struct virtio_blk *vblk = vdev->priv;
+ struct request_queue *q = vblk->disk->queue;
/* Ensure no requests in virtqueues before deleting vqs. */
- blk_mq_freeze_queue(vblk->disk->queue);
+ blk_mq_freeze_queue(q);
+ blk_mq_quiesce_queue_nowait(q);
+ blk_mq_unfreeze_queue(q);
/* Ensure we don't receive any more interrupts */
virtio_reset_device(vdev);
@@ -1612,8 +1615,8 @@ static int virtblk_restore(struct virtio_device *vdev)
return ret;
virtio_device_ready(vdev);
+ blk_mq_unquiesce_queue(vblk->disk->queue);
- blk_mq_unfreeze_queue(vblk->disk->queue);
return 0;
}
#endif
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 3dee026988dc..45df5eeabc5e 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -614,6 +614,12 @@ static ssize_t backing_dev_store(struct device *dev,
}
nr_pages = i_size_read(inode) >> PAGE_SHIFT;
+ /* Refuse to use zero sized device (also prevents self reference) */
+ if (!nr_pages) {
+ err = -EINVAL;
+ goto out;
+ }
+
bitmap_sz = BITS_TO_LONGS(nr_pages) * sizeof(long);
bitmap = kvzalloc(bitmap_sz, GFP_KERNEL);
if (!bitmap) {
@@ -1438,12 +1444,16 @@ static void zram_meta_free(struct zram *zram, u64 disksize)
size_t num_pages = disksize >> PAGE_SHIFT;
size_t index;
+ if (!zram->table)
+ return;
+
/* Free all pages that are still in this zram device */
for (index = 0; index < num_pages; index++)
zram_free_page(zram, index);
zs_destroy_pool(zram->mem_pool);
vfree(zram->table);
+ zram->table = NULL;
}
static bool zram_meta_alloc(struct zram *zram, u64 disksize)
@@ -2320,11 +2330,6 @@ static void zram_reset_device(struct zram *zram)
zram->limit_pages = 0;
- if (!init_done(zram)) {
- up_write(&zram->init_lock);
- return;
- }
-
set_capacity_and_notify(zram->disk, 0);
part_stat_set_all(zram->disk->part0, 0);
diff --git a/drivers/bluetooth/btmtk.c b/drivers/bluetooth/btmtk.c
index 8a3f7c3fcfec..224eafc27dbe 100644
--- a/drivers/bluetooth/btmtk.c
+++ b/drivers/bluetooth/btmtk.c
@@ -395,6 +395,7 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
{
struct btmtk_data *data = hci_get_priv(hdev);
int err;
+ bool complete = false;
if (!IS_ENABLED(CONFIG_DEV_COREDUMP)) {
kfree_skb(skb);
@@ -416,19 +417,22 @@ int btmtk_process_coredump(struct hci_dev *hdev, struct sk_buff *skb)
fallthrough;
case HCI_DEVCOREDUMP_ACTIVE:
default:
+ /* Mediatek coredump data would be more than MTK_COREDUMP_NUM */
+ if (data->cd_info.cnt >= MTK_COREDUMP_NUM &&
+ skb->len > MTK_COREDUMP_END_LEN)
+ if (!memcmp((char *)&skb->data[skb->len - MTK_COREDUMP_END_LEN],
+ MTK_COREDUMP_END, MTK_COREDUMP_END_LEN - 1))
+ complete = true;
+
err = hci_devcd_append(hdev, skb);
if (err < 0)
break;
data->cd_info.cnt++;
- /* Mediatek coredump data would be more than MTK_COREDUMP_NUM */
- if (data->cd_info.cnt > MTK_COREDUMP_NUM &&
- skb->len > MTK_COREDUMP_END_LEN)
- if (!memcmp((char *)&skb->data[skb->len - MTK_COREDUMP_END_LEN],
- MTK_COREDUMP_END, MTK_COREDUMP_END_LEN - 1)) {
- bt_dev_info(hdev, "Mediatek coredump end");
- hci_devcd_complete(hdev);
- }
+ if (complete) {
+ bt_dev_info(hdev, "Mediatek coredump end");
+ hci_devcd_complete(hdev);
+ }
break;
}
@@ -1468,10 +1472,15 @@ EXPORT_SYMBOL_GPL(btmtk_usb_setup);
int btmtk_usb_shutdown(struct hci_dev *hdev)
{
+ struct btmtk_data *data = hci_get_priv(hdev);
struct btmtk_hci_wmt_params wmt_params;
u8 param = 0;
int err;
+ err = usb_autopm_get_interface(data->intf);
+ if (err < 0)
+ return err;
+
/* Disable the device */
wmt_params.op = BTMTK_WMT_FUNC_CTRL;
wmt_params.flag = 0;
@@ -1482,9 +1491,11 @@ int btmtk_usb_shutdown(struct hci_dev *hdev)
err = btmtk_usb_hci_wmt_sync(hdev, &wmt_params);
if (err < 0) {
bt_dev_err(hdev, "Failed to send wmt func ctrl (%d)", err);
+ usb_autopm_put_interface(data->intf);
return err;
}
+ usb_autopm_put_interface(data->intf);
return 0;
}
EXPORT_SYMBOL_GPL(btmtk_usb_shutdown);
diff --git a/drivers/bluetooth/btnxpuart.c b/drivers/bluetooth/btnxpuart.c
index 569f5b7d6e46..1230045d78a5 100644
--- a/drivers/bluetooth/btnxpuart.c
+++ b/drivers/bluetooth/btnxpuart.c
@@ -1381,6 +1381,7 @@ static void btnxpuart_tx_work(struct work_struct *work)
while ((skb = nxp_dequeue(nxpdev))) {
len = serdev_device_write_buf(serdev, skb->data, skb->len);
+ serdev_device_wait_until_sent(serdev, 0);
hdev->stat.byte_tx += len;
skb_pull(skb, len);
diff --git a/drivers/bluetooth/btqcomsmd.c b/drivers/bluetooth/btqcomsmd.c
index 88dbb2f3fabf..c0eb71d6ffd3 100644
--- a/drivers/bluetooth/btqcomsmd.c
+++ b/drivers/bluetooth/btqcomsmd.c
@@ -216,7 +216,7 @@ MODULE_DEVICE_TABLE(of, btqcomsmd_of_match);
static struct platform_driver btqcomsmd_driver = {
.probe = btqcomsmd_probe,
- .remove_new = btqcomsmd_remove,
+ .remove = btqcomsmd_remove,
.driver = {
.name = "btqcomsmd",
.of_match_table = btqcomsmd_of_match,
diff --git a/drivers/bluetooth/hci_bcm.c b/drivers/bluetooth/hci_bcm.c
index 521b785f2908..9684eb16059b 100644
--- a/drivers/bluetooth/hci_bcm.c
+++ b/drivers/bluetooth/hci_bcm.c
@@ -1498,7 +1498,7 @@ static const struct dev_pm_ops bcm_pm_ops = {
static struct platform_driver bcm_driver = {
.probe = bcm_probe,
- .remove_new = bcm_remove,
+ .remove = bcm_remove,
.driver = {
.name = "hci_bcm",
.acpi_match_table = ACPI_PTR(bcm_acpi_match),
diff --git a/drivers/bluetooth/hci_intel.c b/drivers/bluetooth/hci_intel.c
index 999ccd5bb4f2..811f33701f84 100644
--- a/drivers/bluetooth/hci_intel.c
+++ b/drivers/bluetooth/hci_intel.c
@@ -1206,7 +1206,7 @@ static void intel_remove(struct platform_device *pdev)
static struct platform_driver intel_driver = {
.probe = intel_probe,
- .remove_new = intel_remove,
+ .remove = intel_remove,
.driver = {
.name = "hci_intel",
.acpi_match_table = ACPI_PTR(intel_acpi_match),
diff --git a/drivers/bus/mhi/host/boot.c b/drivers/bus/mhi/host/boot.c
index dedd29ca8db3..e8c92972f9df 100644
--- a/drivers/bus/mhi/host/boot.c
+++ b/drivers/bus/mhi/host/boot.c
@@ -82,9 +82,9 @@ static int __mhi_download_rddm_in_panic(struct mhi_controller *mhi_cntrl)
* other cores to shutdown while we're collecting RDDM buffer. After
* returning from this function, we expect the device to reset.
*
- * Normaly, we read/write pm_state only after grabbing the
+ * Normally, we read/write pm_state only after grabbing the
* pm_lock, since we're in a panic, skipping it. Also there is no
- * gurantee that this state change would take effect since
+ * guarantee that this state change would take effect since
* we're setting it w/o grabbing pm_lock
*/
mhi_cntrl->pm_state = MHI_PM_LD_ERR_FATAL_DETECT;
diff --git a/drivers/bus/mhi/host/internal.h b/drivers/bus/mhi/host/internal.h
index d057e877932e..3134f111be35 100644
--- a/drivers/bus/mhi/host/internal.h
+++ b/drivers/bus/mhi/host/internal.h
@@ -255,7 +255,7 @@ struct mhi_chan {
/*
* Important: When consuming, increment tre_ring first and when
* releasing, decrement buf_ring first. If tre_ring has space, buf_ring
- * is guranteed to have space so we do not need to check both rings.
+ * is guaranteed to have space so we do not need to check both rings.
*/
struct mhi_ring buf_ring;
struct mhi_ring tre_ring;
diff --git a/drivers/bus/mhi/host/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
index 9938bb034c1c..07645ce2119a 100644
--- a/drivers/bus/mhi/host/pci_generic.c
+++ b/drivers/bus/mhi/host/pci_generic.c
@@ -917,12 +917,12 @@ static int mhi_pci_claim(struct mhi_controller *mhi_cntrl,
return err;
}
- err = pcim_iomap_regions(pdev, 1 << bar_num, pci_name(pdev));
- if (err) {
+ mhi_cntrl->regs = pcim_iomap_region(pdev, 1 << bar_num, pci_name(pdev));
+ if (IS_ERR(mhi_cntrl->regs)) {
+ err = PTR_ERR(mhi_cntrl->regs);
dev_err(&pdev->dev, "failed to map pci region: %d\n", err);
return err;
}
- mhi_cntrl->regs = pcim_iomap_table(pdev)[bar_num];
mhi_cntrl->reg_len = pci_resource_len(pdev, bar_num);
err = dma_set_mask_and_coherent(&pdev->dev, dma_mask);
diff --git a/drivers/bus/mhi/host/trace.h b/drivers/bus/mhi/host/trace.h
index 95613c8ebe06..3e0c41777429 100644
--- a/drivers/bus/mhi/host/trace.h
+++ b/drivers/bus/mhi/host/trace.h
@@ -9,6 +9,7 @@
#if !defined(_TRACE_EVENT_MHI_HOST_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_EVENT_MHI_HOST_H
+#include <linux/byteorder/generic.h>
#include <linux/tracepoint.h>
#include <linux/trace_seq.h>
#include "../common.h"
@@ -97,18 +98,18 @@ TRACE_EVENT(mhi_gen_tre,
__string(name, mhi_cntrl->mhi_dev->name)
__field(int, ch_num)
__field(void *, wp)
- __field(__le64, tre_ptr)
- __field(__le32, dword0)
- __field(__le32, dword1)
+ __field(uint64_t, tre_ptr)
+ __field(uint32_t, dword0)
+ __field(uint32_t, dword1)
),
TP_fast_assign(
__assign_str(name);
__entry->ch_num = mhi_chan->chan;
__entry->wp = mhi_tre;
- __entry->tre_ptr = mhi_tre->ptr;
- __entry->dword0 = mhi_tre->dword[0];
- __entry->dword1 = mhi_tre->dword[1];
+ __entry->tre_ptr = le64_to_cpu(mhi_tre->ptr);
+ __entry->dword0 = le32_to_cpu(mhi_tre->dword[0]);
+ __entry->dword1 = le32_to_cpu(mhi_tre->dword[1]);
),
TP_printk("%s: Chan: %d TRE: 0x%p TRE buf: 0x%llx DWORD0: 0x%08x DWORD1: 0x%08x\n",
@@ -176,19 +177,19 @@ DECLARE_EVENT_CLASS(mhi_process_event_ring,
TP_STRUCT__entry(
__string(name, mhi_cntrl->mhi_dev->name)
- __field(__le32, dword0)
- __field(__le32, dword1)
+ __field(uint32_t, dword0)
+ __field(uint32_t, dword1)
__field(int, state)
- __field(__le64, ptr)
+ __field(uint64_t, ptr)
__field(void *, rp)
),
TP_fast_assign(
__assign_str(name);
__entry->rp = rp;
- __entry->ptr = rp->ptr;
- __entry->dword0 = rp->dword[0];
- __entry->dword1 = rp->dword[1];
+ __entry->ptr = le64_to_cpu(rp->ptr);
+ __entry->dword0 = le32_to_cpu(rp->dword[0]);
+ __entry->dword1 = le32_to_cpu(rp->dword[1]);
__entry->state = MHI_TRE_GET_EV_STATE(rp);
),
diff --git a/drivers/cdrom/cdrom.c b/drivers/cdrom/cdrom.c
index 6a99a459b80b..51745ed1bbab 100644
--- a/drivers/cdrom/cdrom.c
+++ b/drivers/cdrom/cdrom.c
@@ -1106,7 +1106,7 @@ int open_for_data(struct cdrom_device_info *cdi)
}
}
- cd_dbg(CD_OPEN, "all seems well, opening the devicen");
+ cd_dbg(CD_OPEN, "all seems well, opening the device\n");
/* all seems well, we can open the device */
ret = cdo->open(cdi, 0); /* open for data */
diff --git a/drivers/cdrom/gdrom.c b/drivers/cdrom/gdrom.c
index 71cfe7a85913..64b097e830d4 100644
--- a/drivers/cdrom/gdrom.c
+++ b/drivers/cdrom/gdrom.c
@@ -847,7 +847,7 @@ static void remove_gdrom(struct platform_device *devptr)
static struct platform_driver gdrom_driver = {
.probe = probe_gdrom,
- .remove_new = remove_gdrom,
+ .remove = remove_gdrom,
.driver = {
.name = GDROM_DEV_NAME,
},
diff --git a/drivers/cdx/Makefile b/drivers/cdx/Makefile
index 749a3295c2bd..3ca7068a3052 100644
--- a/drivers/cdx/Makefile
+++ b/drivers/cdx/Makefile
@@ -5,7 +5,7 @@
# Copyright (C) 2022-2023, Advanced Micro Devices, Inc.
#
-ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=CDX_BUS
+ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE='"CDX_BUS"'
obj-$(CONFIG_CDX_BUS) += cdx.o controller/
diff --git a/drivers/cdx/cdx.c b/drivers/cdx/cdx.c
index 07371cb653d3..76eac3653b1c 100644
--- a/drivers/cdx/cdx.c
+++ b/drivers/cdx/cdx.c
@@ -707,7 +707,7 @@ static const struct vm_operations_struct cdx_phys_vm_ops = {
* Return: true on success, false otherwise.
*/
static int cdx_mmap_resource(struct file *fp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct cdx_device *cdx_dev = to_cdx_device(kobj_to_dev(kobj));
@@ -868,7 +868,7 @@ fail:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cdx_device_add, CDX_BUS_CONTROLLER);
+EXPORT_SYMBOL_NS_GPL(cdx_device_add, "CDX_BUS_CONTROLLER");
struct device *cdx_bus_add(struct cdx_controller *cdx, u8 bus_num)
{
@@ -915,7 +915,7 @@ device_add_fail:
return NULL;
}
-EXPORT_SYMBOL_NS_GPL(cdx_bus_add, CDX_BUS_CONTROLLER);
+EXPORT_SYMBOL_NS_GPL(cdx_bus_add, "CDX_BUS_CONTROLLER");
int cdx_register_controller(struct cdx_controller *cdx)
{
@@ -940,7 +940,7 @@ int cdx_register_controller(struct cdx_controller *cdx)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cdx_register_controller, CDX_BUS_CONTROLLER);
+EXPORT_SYMBOL_NS_GPL(cdx_register_controller, "CDX_BUS_CONTROLLER");
void cdx_unregister_controller(struct cdx_controller *cdx)
{
@@ -955,7 +955,7 @@ void cdx_unregister_controller(struct cdx_controller *cdx)
mutex_unlock(&cdx_controller_lock);
}
-EXPORT_SYMBOL_NS_GPL(cdx_unregister_controller, CDX_BUS_CONTROLLER);
+EXPORT_SYMBOL_NS_GPL(cdx_unregister_controller, "CDX_BUS_CONTROLLER");
static int __init cdx_bus_init(void)
{
diff --git a/drivers/cdx/cdx_msi.c b/drivers/cdx/cdx_msi.c
index e55f1716cfcb..06d723978232 100644
--- a/drivers/cdx/cdx_msi.c
+++ b/drivers/cdx/cdx_msi.c
@@ -189,4 +189,4 @@ struct irq_domain *cdx_msi_domain_init(struct device *dev)
return cdx_msi_domain;
}
-EXPORT_SYMBOL_NS_GPL(cdx_msi_domain_init, CDX_BUS_CONTROLLER);
+EXPORT_SYMBOL_NS_GPL(cdx_msi_domain_init, "CDX_BUS_CONTROLLER");
diff --git a/drivers/cdx/controller/cdx_controller.c b/drivers/cdx/controller/cdx_controller.c
index 201f9a6fbde7..d623f9c7517a 100644
--- a/drivers/cdx/controller/cdx_controller.c
+++ b/drivers/cdx/controller/cdx_controller.c
@@ -250,7 +250,7 @@ static struct platform_driver cdx_pdriver = {
.of_match_table = cdx_match_table,
},
.probe = xlnx_cdx_probe,
- .remove_new = xlnx_cdx_remove,
+ .remove = xlnx_cdx_remove,
};
static int __init cdx_controller_init(void)
@@ -275,4 +275,4 @@ module_exit(cdx_controller_exit);
MODULE_AUTHOR("AMD Inc.");
MODULE_DESCRIPTION("CDX controller for AMD devices");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CDX_BUS_CONTROLLER);
+MODULE_IMPORT_NS("CDX_BUS_CONTROLLER");
diff --git a/drivers/char/ipmi/bt-bmc.c b/drivers/char/ipmi/bt-bmc.c
index b8b9c07d3b5d..009e32033b17 100644
--- a/drivers/char/ipmi/bt-bmc.c
+++ b/drivers/char/ipmi/bt-bmc.c
@@ -481,7 +481,7 @@ static struct platform_driver bt_bmc_driver = {
.of_match_table = bt_bmc_match,
},
.probe = bt_bmc_probe,
- .remove_new = bt_bmc_remove,
+ .remove = bt_bmc_remove,
};
module_platform_driver(bt_bmc_driver);
diff --git a/drivers/char/ipmi/ipmi_powernv.c b/drivers/char/ipmi/ipmi_powernv.c
index c59a86eb58c7..4a2efafcd1f8 100644
--- a/drivers/char/ipmi/ipmi_powernv.c
+++ b/drivers/char/ipmi/ipmi_powernv.c
@@ -302,7 +302,7 @@ static struct platform_driver powernv_ipmi_driver = {
.of_match_table = ipmi_powernv_match,
},
.probe = ipmi_powernv_probe,
- .remove_new = ipmi_powernv_remove,
+ .remove = ipmi_powernv_remove,
};
diff --git a/drivers/char/ipmi/ipmi_si_platform.c b/drivers/char/ipmi/ipmi_si_platform.c
index 96ba85648120..550cabd43ae6 100644
--- a/drivers/char/ipmi/ipmi_si_platform.c
+++ b/drivers/char/ipmi/ipmi_si_platform.c
@@ -445,7 +445,7 @@ struct platform_driver ipmi_platform_driver = {
.acpi_match_table = ACPI_PTR(acpi_ipmi_match),
},
.probe = ipmi_probe,
- .remove_new = ipmi_remove,
+ .remove = ipmi_remove,
.id_table = si_plat_ids
};
diff --git a/drivers/char/ipmi/ipmi_ssif.c b/drivers/char/ipmi/ipmi_ssif.c
index d04b391048fb..506d9988721e 100644
--- a/drivers/char/ipmi/ipmi_ssif.c
+++ b/drivers/char/ipmi/ipmi_ssif.c
@@ -2114,7 +2114,7 @@ static struct platform_driver ipmi_driver = {
.name = DEVICE_NAME,
},
.probe = ssif_platform_probe,
- .remove_new = ssif_platform_remove,
+ .remove = ssif_platform_remove,
.id_table = ssif_plat_ids
};
diff --git a/drivers/char/ipmi/kcs_bmc_aspeed.c b/drivers/char/ipmi/kcs_bmc_aspeed.c
index 227bf06c7ca4..c03bc1ec593a 100644
--- a/drivers/char/ipmi/kcs_bmc_aspeed.c
+++ b/drivers/char/ipmi/kcs_bmc_aspeed.c
@@ -672,7 +672,7 @@ static struct platform_driver ast_kcs_bmc_driver = {
.of_match_table = ast_kcs_bmc_match,
},
.probe = aspeed_kcs_probe,
- .remove_new = aspeed_kcs_remove,
+ .remove = aspeed_kcs_remove,
};
module_platform_driver(ast_kcs_bmc_driver);
diff --git a/drivers/char/ipmi/kcs_bmc_npcm7xx.c b/drivers/char/ipmi/kcs_bmc_npcm7xx.c
index 07710198233a..4808a61bf273 100644
--- a/drivers/char/ipmi/kcs_bmc_npcm7xx.c
+++ b/drivers/char/ipmi/kcs_bmc_npcm7xx.c
@@ -241,7 +241,7 @@ static struct platform_driver npcm_kcs_bmc_driver = {
.of_match_table = npcm_kcs_bmc_match,
},
.probe = npcm7xx_kcs_probe,
- .remove_new = npcm7xx_kcs_remove,
+ .remove = npcm7xx_kcs_remove,
};
module_platform_driver(npcm_kcs_bmc_driver);
diff --git a/drivers/char/powernv-op-panel.c b/drivers/char/powernv-op-panel.c
index f2cff1a6fed5..53467b0a6187 100644
--- a/drivers/char/powernv-op-panel.c
+++ b/drivers/char/powernv-op-panel.c
@@ -213,7 +213,7 @@ static struct platform_driver oppanel_driver = {
.of_match_table = oppanel_match,
},
.probe = oppanel_probe,
- .remove_new = oppanel_remove,
+ .remove = oppanel_remove,
};
module_platform_driver(oppanel_driver);
diff --git a/drivers/char/sonypi.c b/drivers/char/sonypi.c
index 0f8185e541ed..f887569fd3d0 100644
--- a/drivers/char/sonypi.c
+++ b/drivers/char/sonypi.c
@@ -1467,7 +1467,7 @@ static struct platform_driver sonypi_driver = {
.pm = SONYPI_PM,
},
.probe = sonypi_probe,
- .remove_new = sonypi_remove,
+ .remove = sonypi_remove,
.shutdown = sonypi_shutdown,
};
diff --git a/drivers/char/tpm/tpm_ftpm_tee.c b/drivers/char/tpm/tpm_ftpm_tee.c
index 2ea4882251cf..139556b21cc6 100644
--- a/drivers/char/tpm/tpm_ftpm_tee.c
+++ b/drivers/char/tpm/tpm_ftpm_tee.c
@@ -366,7 +366,7 @@ static struct platform_driver ftpm_tee_plat_driver = {
},
.shutdown = ftpm_plat_tee_shutdown,
.probe = ftpm_plat_tee_probe,
- .remove_new = ftpm_plat_tee_remove,
+ .remove = ftpm_plat_tee_remove,
};
/* UUID of the fTPM TA */
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 2f7326d297ad..9aa230a63616 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -356,7 +356,7 @@ MODULE_DEVICE_TABLE(of, tis_of_platform_match);
static struct platform_driver tis_drv = {
.probe = tpm_tis_plat_probe,
- .remove_new = tpm_tis_plat_remove,
+ .remove = tpm_tis_plat_remove,
.driver = {
.name = "tpm_tis",
.pm = &tpm_tis_pm,
diff --git a/drivers/char/tpm/tpm_tis_synquacer.c b/drivers/char/tpm/tpm_tis_synquacer.c
index 0621ebec530b..4927714d277a 100644
--- a/drivers/char/tpm/tpm_tis_synquacer.c
+++ b/drivers/char/tpm/tpm_tis_synquacer.c
@@ -152,7 +152,7 @@ MODULE_DEVICE_TABLE(acpi, tpm_synquacer_acpi_tbl);
static struct platform_driver tis_synquacer_drv = {
.probe = tpm_tis_synquacer_probe,
- .remove_new = tpm_tis_synquacer_remove,
+ .remove = tpm_tis_synquacer_remove,
.driver = {
.name = "tpm_tis_synquacer",
.pm = &tpm_tis_synquacer_pm,
diff --git a/drivers/char/xilinx_hwicap/xilinx_hwicap.c b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
index 4f6c3cb8aa41..34a345dc5e72 100644
--- a/drivers/char/xilinx_hwicap/xilinx_hwicap.c
+++ b/drivers/char/xilinx_hwicap/xilinx_hwicap.c
@@ -738,7 +738,7 @@ MODULE_DEVICE_TABLE(of, hwicap_of_match);
static struct platform_driver hwicap_platform_driver = {
.probe = hwicap_drv_probe,
- .remove_new = hwicap_drv_remove,
+ .remove = hwicap_drv_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = hwicap_of_match,
diff --git a/drivers/char/xillybus/xillybus_of.c b/drivers/char/xillybus/xillybus_of.c
index 8802e2a6fd20..1a1e64133315 100644
--- a/drivers/char/xillybus/xillybus_of.c
+++ b/drivers/char/xillybus/xillybus_of.c
@@ -74,7 +74,7 @@ static void xilly_drv_remove(struct platform_device *op)
static struct platform_driver xillybus_platform_driver = {
.probe = xilly_drv_probe,
- .remove_new = xilly_drv_remove,
+ .remove = xilly_drv_remove,
.driver = {
.name = xillyname,
.of_match_table = xillybus_of_match,
diff --git a/drivers/clk/clk-en7523.c b/drivers/clk/clk-en7523.c
index e52c5460e927..495c0d607c7d 100644
--- a/drivers/clk/clk-en7523.c
+++ b/drivers/clk/clk-en7523.c
@@ -87,6 +87,7 @@ static const u32 slic_base[] = { 100000000, 3125000 };
static const u32 npu_base[] = { 333000000, 400000000, 500000000 };
/* EN7581 */
static const u32 emi7581_base[] = { 540000000, 480000000, 400000000, 300000000 };
+static const u32 bus7581_base[] = { 600000000, 540000000 };
static const u32 npu7581_base[] = { 800000000, 750000000, 720000000, 600000000 };
static const u32 crypto_base[] = { 540000000, 480000000 };
@@ -222,8 +223,8 @@ static const struct en_clk_desc en7581_base_clks[] = {
.base_reg = REG_BUS_CLK_DIV_SEL,
.base_bits = 1,
.base_shift = 8,
- .base_values = bus_base,
- .n_base_values = ARRAY_SIZE(bus_base),
+ .base_values = bus7581_base,
+ .n_base_values = ARRAY_SIZE(bus7581_base),
.div_bits = 3,
.div_shift = 0,
@@ -503,6 +504,8 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
u32 rate;
int i;
+ clk_data->num = EN7523_NUM_CLOCKS;
+
for (i = 0; i < ARRAY_SIZE(en7523_base_clks); i++) {
const struct en_clk_desc *desc = &en7523_base_clks[i];
u32 reg = desc->div_reg ? desc->div_reg : desc->base_reg;
@@ -524,8 +527,6 @@ static void en7523_register_clocks(struct device *dev, struct clk_hw_onecell_dat
hw = en7523_register_pcie_clk(dev, np_base);
clk_data->hws[EN7523_CLK_PCIE] = hw;
-
- clk_data->num = EN7523_NUM_CLOCKS;
}
static int en7523_clk_hw_init(struct platform_device *pdev,
diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c
index bdc6e5b90da5..9b45fa005030 100644
--- a/drivers/clk/clk.c
+++ b/drivers/clk/clk.c
@@ -2530,7 +2530,7 @@ static int clk_core_set_rate_nolock(struct clk_core *core,
rate = clk_core_req_round_rate_nolock(core, req_rate);
/* bail early if nothing to do */
- if (rate == clk_core_get_rate_recalc(core))
+ if (rate == clk_core_get_rate_nolock(core))
return 0;
/* fail on a direct rate set of a protected provider */
diff --git a/drivers/clk/imx/clk-imx8mp-audiomix.c b/drivers/clk/imx/clk-imx8mp-audiomix.c
index b2cb157703c5..c409fc7e0618 100644
--- a/drivers/clk/imx/clk-imx8mp-audiomix.c
+++ b/drivers/clk/imx/clk-imx8mp-audiomix.c
@@ -278,7 +278,8 @@ static int clk_imx8mp_audiomix_reset_controller_register(struct device *dev,
#else /* !CONFIG_RESET_CONTROLLER */
-static int clk_imx8mp_audiomix_reset_controller_register(struct clk_imx8mp_audiomix_priv *priv)
+static int clk_imx8mp_audiomix_reset_controller_register(struct device *dev,
+ struct clk_imx8mp_audiomix_priv *priv)
{
return 0;
}
diff --git a/drivers/clk/meson/Kconfig b/drivers/clk/meson/Kconfig
index febb5d7348ff..be2e3a5f8336 100644
--- a/drivers/clk/meson/Kconfig
+++ b/drivers/clk/meson/Kconfig
@@ -106,7 +106,7 @@ config COMMON_CLK_AXG_AUDIO
select COMMON_CLK_MESON_SCLK_DIV
select COMMON_CLK_MESON_CLKC_UTILS
select REGMAP_MMIO
- depends on RESET_MESON_AUX
+ select RESET_CONTROLLER
help
Support for the audio clock controller on AmLogic A113D devices,
aka axg, Say Y if you want audio subsystem to work.
diff --git a/drivers/clk/meson/a1-peripherals.c b/drivers/clk/meson/a1-peripherals.c
index 7aa6abb2eb1f..36489e0f948a 100644
--- a/drivers/clk/meson/a1-peripherals.c
+++ b/drivers/clk/meson/a1-peripherals.c
@@ -2246,4 +2246,4 @@ MODULE_DESCRIPTION("Amlogic A1 Peripherals Clock Controller driver");
MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/a1-pll.c b/drivers/clk/meson/a1-pll.c
index 8e5a42d1afbb..8d7c7b4493c4 100644
--- a/drivers/clk/meson/a1-pll.c
+++ b/drivers/clk/meson/a1-pll.c
@@ -360,4 +360,4 @@ MODULE_DESCRIPTION("Amlogic S4 PLL Clock Controller driver");
MODULE_AUTHOR("Jian Hu <jian.hu@amlogic.com>");
MODULE_AUTHOR("Dmitry Rokosov <ddrokosov@sberdevices.ru>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/axg-aoclk.c b/drivers/clk/meson/axg-aoclk.c
index 1dabc81535a6..f44091ffb57d 100644
--- a/drivers/clk/meson/axg-aoclk.c
+++ b/drivers/clk/meson/axg-aoclk.c
@@ -342,4 +342,4 @@ module_platform_driver(axg_aoclkc_driver);
MODULE_DESCRIPTION("Amlogic AXG Always-ON Clock Controller driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/axg-audio.c b/drivers/clk/meson/axg-audio.c
index 7714bde5ffc0..9df627b142f8 100644
--- a/drivers/clk/meson/axg-audio.c
+++ b/drivers/clk/meson/axg-audio.c
@@ -15,8 +15,6 @@
#include <linux/reset-controller.h>
#include <linux/slab.h>
-#include <soc/amlogic/reset-meson-aux.h>
-
#include "meson-clkc-utils.h"
#include "axg-audio.h"
#include "clk-regmap.h"
@@ -1680,6 +1678,84 @@ static struct clk_regmap *const sm1_clk_regmaps[] = {
&sm1_earcrx_dmac_clk,
};
+struct axg_audio_reset_data {
+ struct reset_controller_dev rstc;
+ struct regmap *map;
+ unsigned int offset;
+};
+
+static void axg_audio_reset_reg_and_bit(struct axg_audio_reset_data *rst,
+ unsigned long id,
+ unsigned int *reg,
+ unsigned int *bit)
+{
+ unsigned int stride = regmap_get_reg_stride(rst->map);
+
+ *reg = (id / (stride * BITS_PER_BYTE)) * stride;
+ *reg += rst->offset;
+ *bit = id % (stride * BITS_PER_BYTE);
+}
+
+static int axg_audio_reset_update(struct reset_controller_dev *rcdev,
+ unsigned long id, bool assert)
+{
+ struct axg_audio_reset_data *rst =
+ container_of(rcdev, struct axg_audio_reset_data, rstc);
+ unsigned int offset, bit;
+
+ axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
+
+ regmap_update_bits(rst->map, offset, BIT(bit),
+ assert ? BIT(bit) : 0);
+
+ return 0;
+}
+
+static int axg_audio_reset_status(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ struct axg_audio_reset_data *rst =
+ container_of(rcdev, struct axg_audio_reset_data, rstc);
+ unsigned int val, offset, bit;
+
+ axg_audio_reset_reg_and_bit(rst, id, &offset, &bit);
+
+ regmap_read(rst->map, offset, &val);
+
+ return !!(val & BIT(bit));
+}
+
+static int axg_audio_reset_assert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return axg_audio_reset_update(rcdev, id, true);
+}
+
+static int axg_audio_reset_deassert(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ return axg_audio_reset_update(rcdev, id, false);
+}
+
+static int axg_audio_reset_toggle(struct reset_controller_dev *rcdev,
+ unsigned long id)
+{
+ int ret;
+
+ ret = axg_audio_reset_assert(rcdev, id);
+ if (ret)
+ return ret;
+
+ return axg_audio_reset_deassert(rcdev, id);
+}
+
+static const struct reset_control_ops axg_audio_rstc_ops = {
+ .assert = axg_audio_reset_assert,
+ .deassert = axg_audio_reset_deassert,
+ .reset = axg_audio_reset_toggle,
+ .status = axg_audio_reset_status,
+};
+
static struct regmap_config axg_audio_regmap_cfg = {
.reg_bits = 32,
.val_bits = 32,
@@ -1690,14 +1766,16 @@ struct audioclk_data {
struct clk_regmap *const *regmap_clks;
unsigned int regmap_clk_num;
struct meson_clk_hw_data hw_clks;
+ unsigned int reset_offset;
+ unsigned int reset_num;
unsigned int max_register;
- const char *rst_drvname;
};
static int axg_audio_clkc_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
const struct audioclk_data *data;
+ struct axg_audio_reset_data *rst;
struct regmap *map;
void __iomem *regs;
struct clk_hw *hw;
@@ -1756,11 +1834,22 @@ static int axg_audio_clkc_probe(struct platform_device *pdev)
if (ret)
return ret;
- /* Register auxiliary reset driver when applicable */
- if (data->rst_drvname)
- ret = devm_meson_rst_aux_register(dev, map, data->rst_drvname);
+ /* Stop here if there is no reset */
+ if (!data->reset_num)
+ return 0;
+
+ rst = devm_kzalloc(dev, sizeof(*rst), GFP_KERNEL);
+ if (!rst)
+ return -ENOMEM;
+
+ rst->map = map;
+ rst->offset = data->reset_offset;
+ rst->rstc.nr_resets = data->reset_num;
+ rst->rstc.ops = &axg_audio_rstc_ops;
+ rst->rstc.of_node = dev->of_node;
+ rst->rstc.owner = THIS_MODULE;
- return ret;
+ return devm_reset_controller_register(dev, &rst->rstc);
}
static const struct audioclk_data axg_audioclk_data = {
@@ -1780,8 +1869,9 @@ static const struct audioclk_data g12a_audioclk_data = {
.hws = g12a_audio_hw_clks,
.num = ARRAY_SIZE(g12a_audio_hw_clks),
},
+ .reset_offset = AUDIO_SW_RESET,
+ .reset_num = 26,
.max_register = AUDIO_CLK_SPDIFOUT_B_CTRL,
- .rst_drvname = "rst-g12a",
};
static const struct audioclk_data sm1_audioclk_data = {
@@ -1791,8 +1881,9 @@ static const struct audioclk_data sm1_audioclk_data = {
.hws = sm1_audio_hw_clks,
.num = ARRAY_SIZE(sm1_audio_hw_clks),
},
+ .reset_offset = AUDIO_SM1_SW_RESET0,
+ .reset_num = 39,
.max_register = AUDIO_EARCRX_DMAC_CLK_CTRL,
- .rst_drvname = "rst-sm1",
};
static const struct of_device_id clkc_match_table[] = {
@@ -1821,4 +1912,4 @@ module_platform_driver(axg_audio_driver);
MODULE_DESCRIPTION("Amlogic AXG/G12A/SM1 Audio Clock driver");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/axg.c b/drivers/clk/meson/axg.c
index 1b08daf579b2..448eece246ca 100644
--- a/drivers/clk/meson/axg.c
+++ b/drivers/clk/meson/axg.c
@@ -2181,4 +2181,4 @@ module_platform_driver(axg_driver);
MODULE_DESCRIPTION("Amlogic AXG Main Clock Controller driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/c3-peripherals.c b/drivers/clk/meson/c3-peripherals.c
index 7dcbf4ebee07..2075668ed306 100644
--- a/drivers/clk/meson/c3-peripherals.c
+++ b/drivers/clk/meson/c3-peripherals.c
@@ -2364,4 +2364,4 @@ module_platform_driver(c3_peripherals_driver);
MODULE_DESCRIPTION("Amlogic C3 Peripherals Clock Controller driver");
MODULE_AUTHOR("Chuan Liu <chuan.liu@amlogic.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/c3-pll.c b/drivers/clk/meson/c3-pll.c
index 35fda31a19e2..ed4bc495862e 100644
--- a/drivers/clk/meson/c3-pll.c
+++ b/drivers/clk/meson/c3-pll.c
@@ -746,4 +746,4 @@ module_platform_driver(c3_pll_driver);
MODULE_DESCRIPTION("Amlogic C3 PLL Clock Controller driver");
MODULE_AUTHOR("Chuan Liu <chuan.liu@amlogic.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/clk-cpu-dyndiv.c b/drivers/clk/meson/clk-cpu-dyndiv.c
index 6c1f58826e24..cb043b52b65d 100644
--- a/drivers/clk/meson/clk-cpu-dyndiv.c
+++ b/drivers/clk/meson/clk-cpu-dyndiv.c
@@ -65,9 +65,9 @@ const struct clk_ops meson_clk_cpu_dyndiv_ops = {
.determine_rate = meson_clk_cpu_dyndiv_determine_rate,
.set_rate = meson_clk_cpu_dyndiv_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(meson_clk_cpu_dyndiv_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_cpu_dyndiv_ops, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic CPU Dynamic Clock divider");
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/clk-dualdiv.c b/drivers/clk/meson/clk-dualdiv.c
index 913bf25d3771..c896cf29b318 100644
--- a/drivers/clk/meson/clk-dualdiv.c
+++ b/drivers/clk/meson/clk-dualdiv.c
@@ -130,15 +130,15 @@ const struct clk_ops meson_clk_dualdiv_ops = {
.determine_rate = meson_clk_dualdiv_determine_rate,
.set_rate = meson_clk_dualdiv_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(meson_clk_dualdiv_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_dualdiv_ops, "CLK_MESON");
const struct clk_ops meson_clk_dualdiv_ro_ops = {
.recalc_rate = meson_clk_dualdiv_recalc_rate,
};
-EXPORT_SYMBOL_NS_GPL(meson_clk_dualdiv_ro_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_dualdiv_ro_ops, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic dual divider driver");
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/clk-mpll.c b/drivers/clk/meson/clk-mpll.c
index aa9abd06ae65..ee91e32b4050 100644
--- a/drivers/clk/meson/clk-mpll.c
+++ b/drivers/clk/meson/clk-mpll.c
@@ -154,7 +154,7 @@ const struct clk_ops meson_clk_mpll_ro_ops = {
.recalc_rate = mpll_recalc_rate,
.determine_rate = mpll_determine_rate,
};
-EXPORT_SYMBOL_NS_GPL(meson_clk_mpll_ro_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_mpll_ro_ops, "CLK_MESON");
const struct clk_ops meson_clk_mpll_ops = {
.recalc_rate = mpll_recalc_rate,
@@ -162,9 +162,9 @@ const struct clk_ops meson_clk_mpll_ops = {
.set_rate = mpll_set_rate,
.init = mpll_init,
};
-EXPORT_SYMBOL_NS_GPL(meson_clk_mpll_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_mpll_ops, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic MPLL driver");
MODULE_AUTHOR("Michael Turquette <mturquette@baylibre.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/clk-phase.c b/drivers/clk/meson/clk-phase.c
index c1526fbfb6c4..701211120610 100644
--- a/drivers/clk/meson/clk-phase.c
+++ b/drivers/clk/meson/clk-phase.c
@@ -61,7 +61,7 @@ const struct clk_ops meson_clk_phase_ops = {
.get_phase = meson_clk_phase_get_phase,
.set_phase = meson_clk_phase_set_phase,
};
-EXPORT_SYMBOL_NS_GPL(meson_clk_phase_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_phase_ops, "CLK_MESON");
/*
* This is a special clock for the audio controller.
@@ -123,7 +123,7 @@ const struct clk_ops meson_clk_triphase_ops = {
.get_phase = meson_clk_triphase_get_phase,
.set_phase = meson_clk_triphase_set_phase,
};
-EXPORT_SYMBOL_NS_GPL(meson_clk_triphase_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_triphase_ops, "CLK_MESON");
/*
* This is a special clock for the audio controller.
@@ -178,9 +178,9 @@ const struct clk_ops meson_sclk_ws_inv_ops = {
.get_phase = meson_sclk_ws_inv_get_phase,
.set_phase = meson_sclk_ws_inv_set_phase,
};
-EXPORT_SYMBOL_NS_GPL(meson_sclk_ws_inv_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_sclk_ws_inv_ops, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic phase driver");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/clk-pll.c b/drivers/clk/meson/clk-pll.c
index 89f0f04a16ab..e8e53855b00a 100644
--- a/drivers/clk/meson/clk-pll.c
+++ b/drivers/clk/meson/clk-pll.c
@@ -474,7 +474,7 @@ const struct clk_ops meson_clk_pcie_pll_ops = {
.enable = meson_clk_pcie_pll_enable,
.disable = meson_clk_pll_disable
};
-EXPORT_SYMBOL_NS_GPL(meson_clk_pcie_pll_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_pcie_pll_ops, "CLK_MESON");
const struct clk_ops meson_clk_pll_ops = {
.init = meson_clk_pll_init,
@@ -485,16 +485,16 @@ const struct clk_ops meson_clk_pll_ops = {
.enable = meson_clk_pll_enable,
.disable = meson_clk_pll_disable
};
-EXPORT_SYMBOL_NS_GPL(meson_clk_pll_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_pll_ops, "CLK_MESON");
const struct clk_ops meson_clk_pll_ro_ops = {
.recalc_rate = meson_clk_pll_recalc_rate,
.is_enabled = meson_clk_pll_is_enabled,
};
-EXPORT_SYMBOL_NS_GPL(meson_clk_pll_ro_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_pll_ro_ops, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic PLL driver");
MODULE_AUTHOR("Carlo Caione <carlo@endlessm.com>");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/clk-regmap.c b/drivers/clk/meson/clk-regmap.c
index 07f7e441b916..f3e504f67571 100644
--- a/drivers/clk/meson/clk-regmap.c
+++ b/drivers/clk/meson/clk-regmap.c
@@ -49,12 +49,12 @@ const struct clk_ops clk_regmap_gate_ops = {
.disable = clk_regmap_gate_disable,
.is_enabled = clk_regmap_gate_is_enabled,
};
-EXPORT_SYMBOL_NS_GPL(clk_regmap_gate_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(clk_regmap_gate_ops, "CLK_MESON");
const struct clk_ops clk_regmap_gate_ro_ops = {
.is_enabled = clk_regmap_gate_is_enabled,
};
-EXPORT_SYMBOL_NS_GPL(clk_regmap_gate_ro_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(clk_regmap_gate_ro_ops, "CLK_MESON");
static unsigned long clk_regmap_div_recalc_rate(struct clk_hw *hw,
unsigned long prate)
@@ -125,13 +125,13 @@ const struct clk_ops clk_regmap_divider_ops = {
.determine_rate = clk_regmap_div_determine_rate,
.set_rate = clk_regmap_div_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(clk_regmap_divider_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(clk_regmap_divider_ops, "CLK_MESON");
const struct clk_ops clk_regmap_divider_ro_ops = {
.recalc_rate = clk_regmap_div_recalc_rate,
.determine_rate = clk_regmap_div_determine_rate,
};
-EXPORT_SYMBOL_NS_GPL(clk_regmap_divider_ro_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(clk_regmap_divider_ro_ops, "CLK_MESON");
static u8 clk_regmap_mux_get_parent(struct clk_hw *hw)
{
@@ -174,14 +174,14 @@ const struct clk_ops clk_regmap_mux_ops = {
.set_parent = clk_regmap_mux_set_parent,
.determine_rate = clk_regmap_mux_determine_rate,
};
-EXPORT_SYMBOL_NS_GPL(clk_regmap_mux_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(clk_regmap_mux_ops, "CLK_MESON");
const struct clk_ops clk_regmap_mux_ro_ops = {
.get_parent = clk_regmap_mux_get_parent,
};
-EXPORT_SYMBOL_NS_GPL(clk_regmap_mux_ro_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(clk_regmap_mux_ro_ops, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic regmap backed clock driver");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/g12a-aoclk.c b/drivers/clk/meson/g12a-aoclk.c
index f0a18d8c9fc2..71c758ffa493 100644
--- a/drivers/clk/meson/g12a-aoclk.c
+++ b/drivers/clk/meson/g12a-aoclk.c
@@ -477,4 +477,4 @@ module_platform_driver(g12a_aoclkc_driver);
MODULE_DESCRIPTION("Amlogic G12A Always-ON Clock Controller driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
index d3539fe9f7af..cfffd434e998 100644
--- a/drivers/clk/meson/g12a.c
+++ b/drivers/clk/meson/g12a.c
@@ -5610,4 +5610,4 @@ module_platform_driver(g12a_driver);
MODULE_DESCRIPTION("Amlogic G12/SM1 Main Clock Controller driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/gxbb-aoclk.c b/drivers/clk/meson/gxbb-aoclk.c
index 83b034157b35..43940232f718 100644
--- a/drivers/clk/meson/gxbb-aoclk.c
+++ b/drivers/clk/meson/gxbb-aoclk.c
@@ -303,4 +303,4 @@ module_platform_driver(gxbb_aoclkc_driver);
MODULE_DESCRIPTION("Amlogic GXBB Always-ON Clock Controller driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/gxbb.c b/drivers/clk/meson/gxbb.c
index 262c318edbd5..8575b8485385 100644
--- a/drivers/clk/meson/gxbb.c
+++ b/drivers/clk/meson/gxbb.c
@@ -3565,4 +3565,4 @@ module_platform_driver(gxbb_driver);
MODULE_DESCRIPTION("Amlogic GXBB Main Clock Controller driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/meson-aoclk.c b/drivers/clk/meson/meson-aoclk.c
index 053940ee8940..995be51987f4 100644
--- a/drivers/clk/meson/meson-aoclk.c
+++ b/drivers/clk/meson/meson-aoclk.c
@@ -88,8 +88,8 @@ int meson_aoclkc_probe(struct platform_device *pdev)
return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get, (void *)&data->hw_clks);
}
-EXPORT_SYMBOL_NS_GPL(meson_aoclkc_probe, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_aoclkc_probe, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic Always-ON Clock Controller helpers");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/meson-clkc-utils.c b/drivers/clk/meson/meson-clkc-utils.c
index a8cd2c21fab7..6937d1482719 100644
--- a/drivers/clk/meson/meson-clkc-utils.c
+++ b/drivers/clk/meson/meson-clkc-utils.c
@@ -20,8 +20,8 @@ struct clk_hw *meson_clk_hw_get(struct of_phandle_args *clkspec, void *clk_hw_da
return data->hws[idx];
}
-EXPORT_SYMBOL_NS_GPL(meson_clk_hw_get, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_clk_hw_get, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic Clock Controller Utilities");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/meson-eeclk.c b/drivers/clk/meson/meson-eeclk.c
index 66f79e384fe5..3053ee7425eb 100644
--- a/drivers/clk/meson/meson-eeclk.c
+++ b/drivers/clk/meson/meson-eeclk.c
@@ -57,8 +57,8 @@ int meson_eeclkc_probe(struct platform_device *pdev)
return devm_of_clk_add_hw_provider(dev, meson_clk_hw_get, (void *)&data->hw_clks);
}
-EXPORT_SYMBOL_NS_GPL(meson_eeclkc_probe, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_eeclkc_probe, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic Main Clock Controller Helpers");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/s4-peripherals.c b/drivers/clk/meson/s4-peripherals.c
index c930cf0614a0..8a4037377787 100644
--- a/drivers/clk/meson/s4-peripherals.c
+++ b/drivers/clk/meson/s4-peripherals.c
@@ -3814,4 +3814,4 @@ module_platform_driver(s4_driver);
MODULE_DESCRIPTION("Amlogic S4 Peripherals Clock Controller driver");
MODULE_AUTHOR("Yu Tu <yu.tu@amlogic.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/s4-pll.c b/drivers/clk/meson/s4-pll.c
index d8e621e79428..f9cc05a506e3 100644
--- a/drivers/clk/meson/s4-pll.c
+++ b/drivers/clk/meson/s4-pll.c
@@ -872,4 +872,4 @@ module_platform_driver(s4_driver);
MODULE_DESCRIPTION("Amlogic S4 PLL Clock Controller driver");
MODULE_AUTHOR("Yu Tu <yu.tu@amlogic.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/sclk-div.c b/drivers/clk/meson/sclk-div.c
index ae03b048182f..9c4945234f26 100644
--- a/drivers/clk/meson/sclk-div.c
+++ b/drivers/clk/meson/sclk-div.c
@@ -247,9 +247,9 @@ const struct clk_ops meson_sclk_div_ops = {
.set_duty_cycle = sclk_div_set_duty_cycle,
.init = sclk_div_init,
};
-EXPORT_SYMBOL_NS_GPL(meson_sclk_div_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_sclk_div_ops, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic Sample divider driver");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/vclk.c b/drivers/clk/meson/vclk.c
index 36f637d2d01b..6a167ebdc8d7 100644
--- a/drivers/clk/meson/vclk.c
+++ b/drivers/clk/meson/vclk.c
@@ -49,7 +49,7 @@ const struct clk_ops meson_vclk_gate_ops = {
.disable = meson_vclk_gate_disable,
.is_enabled = meson_vclk_gate_is_enabled,
};
-EXPORT_SYMBOL_NS_GPL(meson_vclk_gate_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_vclk_gate_ops, "CLK_MESON");
/* The VCLK Divider has supplementary reset & enable bits */
@@ -134,9 +134,9 @@ const struct clk_ops meson_vclk_div_ops = {
.disable = meson_vclk_div_disable,
.is_enabled = meson_vclk_div_is_enabled,
};
-EXPORT_SYMBOL_NS_GPL(meson_vclk_div_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_vclk_div_ops, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic vclk clock driver");
MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/meson/vid-pll-div.c b/drivers/clk/meson/vid-pll-div.c
index 486cf68fc97a..965ed7281f57 100644
--- a/drivers/clk/meson/vid-pll-div.c
+++ b/drivers/clk/meson/vid-pll-div.c
@@ -92,9 +92,9 @@ static unsigned long meson_vid_pll_div_recalc_rate(struct clk_hw *hw,
const struct clk_ops meson_vid_pll_div_ro_ops = {
.recalc_rate = meson_vid_pll_div_recalc_rate,
};
-EXPORT_SYMBOL_NS_GPL(meson_vid_pll_div_ro_ops, CLK_MESON);
+EXPORT_SYMBOL_NS_GPL(meson_vid_pll_div_ro_ops, "CLK_MESON");
MODULE_DESCRIPTION("Amlogic video pll divider driver");
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CLK_MESON);
+MODULE_IMPORT_NS("CLK_MESON");
diff --git a/drivers/clk/microchip/clk-mpfs.c b/drivers/clk/microchip/clk-mpfs.c
index 28ec0da88cb3..c22632a7439c 100644
--- a/drivers/clk/microchip/clk-mpfs.c
+++ b/drivers/clk/microchip/clk-mpfs.c
@@ -443,4 +443,4 @@ MODULE_DESCRIPTION("Microchip PolarFire SoC Clock Driver");
MODULE_AUTHOR("Padmarao Begari <padmarao.begari@microchip.com>");
MODULE_AUTHOR("Daire McNamara <daire.mcnamara@microchip.com>");
MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
-MODULE_IMPORT_NS(MCHP_CLK_MPFS);
+MODULE_IMPORT_NS("MCHP_CLK_MPFS");
diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c
index 4084714adb15..44b2ebdebdac 100644
--- a/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1-r.c
@@ -137,6 +137,6 @@ static struct platform_driver sun20i_d1_r_ccu_driver = {
};
module_platform_driver(sun20i_d1_r_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner D1/R528/T113 PRCM CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c
index c80ac2dfbb60..bb66c906ebbb 100644
--- a/drivers/clk/sunxi-ng/ccu-sun20i-d1.c
+++ b/drivers/clk/sunxi-ng/ccu-sun20i-d1.c
@@ -1406,6 +1406,6 @@ static struct platform_driver sun20i_d1_ccu_driver = {
};
module_platform_driver(sun20i_d1_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner D1/R528/T113 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
index 54c794c50828..409feb085021 100644
--- a/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
+++ b/drivers/clk/sunxi-ng/ccu-sun4i-a10.c
@@ -1493,6 +1493,6 @@ static struct platform_driver sun4i_a10_ccu_driver = {
};
module_platform_driver(sun4i_a10_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A10/A20 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
index cdd9721f9e7d..cb0f8d110c32 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100-r.c
@@ -214,6 +214,6 @@ static struct platform_driver sun50i_a100_r_ccu_driver = {
};
module_platform_driver(sun50i_a100_r_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A100 PRCM CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
index 1b6a49bc7184..7133377d4163 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a100.c
@@ -1276,6 +1276,6 @@ static struct platform_driver sun50i_a100_ccu_driver = {
};
module_platform_driver(sun50i_a100_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A100 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
index 82d7dcbca1cc..3a7d61c81667 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-a64.c
@@ -994,6 +994,6 @@ static struct platform_driver sun50i_a64_ccu_driver = {
};
module_platform_driver(sun50i_a64_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A64 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
index d0ce2779c550..acb4e8b9b1ba 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6-r.c
@@ -256,6 +256,6 @@ static struct platform_driver sun50i_h6_r_ccu_driver = {
};
module_platform_driver(sun50i_h6_r_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner H6 and H616 PRCM CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
index bd6fc3df911d..7fccda96d444 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h6.c
@@ -1286,6 +1286,6 @@ static struct platform_driver sun50i_h6_ccu_driver = {
};
module_platform_driver(sun50i_h6_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner H6 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
index b001d0c03534..1086669b91da 100644
--- a/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
+++ b/drivers/clk/sunxi-ng/ccu-sun50i-h616.c
@@ -1185,6 +1185,6 @@ static struct platform_driver sun50i_h616_ccu_driver = {
};
module_platform_driver(sun50i_h616_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner H616 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
index c2ad1209633e..bab65cfe9501 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-a31.c
@@ -1283,6 +1283,6 @@ static struct platform_driver sun6i_a31_ccu_driver = {
};
module_platform_driver(sun6i_a31_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A31/A31s CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
index 724b202863a8..0536e880b80f 100644
--- a/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
+++ b/drivers/clk/sunxi-ng/ccu-sun6i-rtc.c
@@ -381,6 +381,6 @@ int sun6i_rtc_ccu_probe(struct device *dev, void __iomem *reg)
return devm_sunxi_ccu_probe(dev, reg, &sun6i_rtc_ccu_desc);
}
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner H616/R329 RTC CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
index 9433dbac038e..78cf3818ab09 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a23.c
@@ -763,6 +763,6 @@ static struct platform_driver sun8i_a23_ccu_driver = {
};
module_platform_driver(sun8i_a23_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A23 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
index 1ffc5ab9bc3c..b039d419512c 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a33.c
@@ -835,6 +835,6 @@ static struct platform_driver sun8i_a33_ccu_driver = {
};
module_platform_driver(sun8i_a33_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A33 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
index a51fb2c10c94..60e918965a72 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-a83t.c
@@ -923,6 +923,6 @@ static struct platform_driver sun8i_a83t_ccu_driver = {
};
module_platform_driver(sun8i_a83t_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A83T CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
index a742f83746d1..f2aa71206bc2 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-de2.c
@@ -348,6 +348,6 @@ static struct platform_driver sunxi_de2_clk_driver = {
};
module_platform_driver(sunxi_de2_clk_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner SoCs DE2 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
index 74da5d27af72..740c4c97331c 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-h3.c
@@ -1094,6 +1094,6 @@ static struct platform_driver sun8i_h3_ccu_driver = {
};
module_platform_driver(sun8i_h3_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner H3 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r.c b/drivers/clk/sunxi-ng/ccu-sun8i-r.c
index 2b3e094a32cb..0e324344673b 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-r.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r.c
@@ -274,6 +274,6 @@ static struct platform_driver sun8i_r_ccu_driver = {
};
module_platform_driver(sun8i_r_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for Allwinner SoCs' PRCM CCUs");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
index a374aeeca3f4..8b729c9b3545 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-r40.c
@@ -1375,6 +1375,6 @@ static struct platform_driver sun8i_r40_ccu_driver = {
};
module_platform_driver(sun8i_r40_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner R40 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
index 00d04f7ad94d..579a81bb46df 100644
--- a/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
+++ b/drivers/clk/sunxi-ng/ccu-sun8i-v3s.c
@@ -780,6 +780,6 @@ static struct platform_driver sun8i_v3s_ccu_driver = {
};
module_platform_driver(sun8i_v3s_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner V3s CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
index d561c15f5122..91e5dc448bc0 100644
--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-de.c
@@ -266,6 +266,6 @@ static struct platform_driver sun9i_a80_de_clk_driver = {
};
module_platform_driver(sun9i_a80_de_clk_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A80 Display Engine CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
index 9e2b8d47fc54..62063f525616 100644
--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80-usb.c
@@ -138,6 +138,6 @@ static struct platform_driver sun9i_a80_usb_clk_driver = {
};
module_platform_driver(sun9i_a80_usb_clk_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A80 USB CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
index 5da9a16b4ec7..337751998005 100644
--- a/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
+++ b/drivers/clk/sunxi-ng/ccu-sun9i-a80.c
@@ -1248,6 +1248,6 @@ static struct platform_driver sun9i_a80_ccu_driver = {
};
module_platform_driver(sun9i_a80_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner A80 CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
index fb37c0fc4fde..35935423145e 100644
--- a/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
+++ b/drivers/clk/sunxi-ng/ccu-suniv-f1c100s.c
@@ -577,6 +577,6 @@ static struct platform_driver suniv_f1c100s_ccu_driver = {
};
module_platform_driver(suniv_f1c100s_ccu_driver);
-MODULE_IMPORT_NS(SUNXI_CCU);
+MODULE_IMPORT_NS("SUNXI_CCU");
MODULE_DESCRIPTION("Support for the Allwinner newer F1C100s CCU");
MODULE_LICENSE("GPL");
diff --git a/drivers/clk/sunxi-ng/ccu_common.c b/drivers/clk/sunxi-ng/ccu_common.c
index 4117b0bea267..88ed89658d45 100644
--- a/drivers/clk/sunxi-ng/ccu_common.c
+++ b/drivers/clk/sunxi-ng/ccu_common.c
@@ -37,7 +37,7 @@ void ccu_helper_wait_for_lock(struct ccu_common *common, u32 lock)
WARN_ON(readl_relaxed_poll_timeout(addr, reg, reg & lock, 100, 70000));
}
-EXPORT_SYMBOL_NS_GPL(ccu_helper_wait_for_lock, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_helper_wait_for_lock, "SUNXI_CCU");
bool ccu_is_better_rate(struct ccu_common *common,
unsigned long target_rate,
@@ -59,7 +59,7 @@ bool ccu_is_better_rate(struct ccu_common *common,
return current_rate <= target_rate && current_rate > best_rate;
}
-EXPORT_SYMBOL_NS_GPL(ccu_is_better_rate, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_is_better_rate, "SUNXI_CCU");
/*
* This clock notifier is called when the frequency of a PLL clock is
@@ -107,7 +107,7 @@ int ccu_pll_notifier_register(struct ccu_pll_nb *pll_nb)
return clk_notifier_register(pll_nb->common->hw.clk,
&pll_nb->clk_nb);
}
-EXPORT_SYMBOL_NS_GPL(ccu_pll_notifier_register, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_pll_notifier_register, "SUNXI_CCU");
static int sunxi_ccu_probe(struct sunxi_ccu *ccu, struct device *dev,
struct device_node *node, void __iomem *reg,
@@ -234,7 +234,7 @@ int devm_sunxi_ccu_probe(struct device *dev, void __iomem *reg,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(devm_sunxi_ccu_probe, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(devm_sunxi_ccu_probe, "SUNXI_CCU");
void of_sunxi_ccu_probe(struct device_node *node, void __iomem *reg,
const struct sunxi_ccu_desc *desc)
diff --git a/drivers/clk/sunxi-ng/ccu_div.c b/drivers/clk/sunxi-ng/ccu_div.c
index cb10a3ea23f9..7f4691f09e01 100644
--- a/drivers/clk/sunxi-ng/ccu_div.c
+++ b/drivers/clk/sunxi-ng/ccu_div.c
@@ -141,4 +141,4 @@ const struct clk_ops ccu_div_ops = {
.recalc_rate = ccu_div_recalc_rate,
.set_rate = ccu_div_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(ccu_div_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_div_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_frac.c b/drivers/clk/sunxi-ng/ccu_frac.c
index b31f3ad946d6..75323912608a 100644
--- a/drivers/clk/sunxi-ng/ccu_frac.c
+++ b/drivers/clk/sunxi-ng/ccu_frac.c
@@ -18,7 +18,7 @@ bool ccu_frac_helper_is_enabled(struct ccu_common *common,
return !(readl(common->base + common->reg) & cf->enable);
}
-EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_is_enabled, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_is_enabled, "SUNXI_CCU");
void ccu_frac_helper_enable(struct ccu_common *common,
struct ccu_frac_internal *cf)
@@ -34,7 +34,7 @@ void ccu_frac_helper_enable(struct ccu_common *common,
writel(reg & ~cf->enable, common->base + common->reg);
spin_unlock_irqrestore(common->lock, flags);
}
-EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_enable, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_enable, "SUNXI_CCU");
void ccu_frac_helper_disable(struct ccu_common *common,
struct ccu_frac_internal *cf)
@@ -50,7 +50,7 @@ void ccu_frac_helper_disable(struct ccu_common *common,
writel(reg | cf->enable, common->base + common->reg);
spin_unlock_irqrestore(common->lock, flags);
}
-EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_disable, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_disable, "SUNXI_CCU");
bool ccu_frac_helper_has_rate(struct ccu_common *common,
struct ccu_frac_internal *cf,
@@ -61,7 +61,7 @@ bool ccu_frac_helper_has_rate(struct ccu_common *common,
return (cf->rates[0] == rate) || (cf->rates[1] == rate);
}
-EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_has_rate, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_has_rate, "SUNXI_CCU");
unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
struct ccu_frac_internal *cf)
@@ -83,7 +83,7 @@ unsigned long ccu_frac_helper_read_rate(struct ccu_common *common,
return (reg & cf->select) ? cf->rates[1] : cf->rates[0];
}
-EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_read_rate, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_read_rate, "SUNXI_CCU");
int ccu_frac_helper_set_rate(struct ccu_common *common,
struct ccu_frac_internal *cf,
@@ -112,4 +112,4 @@ int ccu_frac_helper_set_rate(struct ccu_common *common,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_set_rate, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_frac_helper_set_rate, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_gate.c b/drivers/clk/sunxi-ng/ccu_gate.c
index a2115a21807d..ac52fd6bff67 100644
--- a/drivers/clk/sunxi-ng/ccu_gate.c
+++ b/drivers/clk/sunxi-ng/ccu_gate.c
@@ -24,7 +24,7 @@ void ccu_gate_helper_disable(struct ccu_common *common, u32 gate)
spin_unlock_irqrestore(common->lock, flags);
}
-EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_disable, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_disable, "SUNXI_CCU");
static void ccu_gate_disable(struct clk_hw *hw)
{
@@ -50,7 +50,7 @@ int ccu_gate_helper_enable(struct ccu_common *common, u32 gate)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_enable, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_enable, "SUNXI_CCU");
static int ccu_gate_enable(struct clk_hw *hw)
{
@@ -66,7 +66,7 @@ int ccu_gate_helper_is_enabled(struct ccu_common *common, u32 gate)
return readl(common->base + common->reg) & gate;
}
-EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_is_enabled, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_gate_helper_is_enabled, "SUNXI_CCU");
static int ccu_gate_is_enabled(struct clk_hw *hw)
{
@@ -127,4 +127,4 @@ const struct clk_ops ccu_gate_ops = {
.set_rate = ccu_gate_set_rate,
.recalc_rate = ccu_gate_recalc_rate,
};
-EXPORT_SYMBOL_NS_GPL(ccu_gate_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_gate_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_mp.c b/drivers/clk/sunxi-ng/ccu_mp.c
index cc94a694cb67..2bb8987ddcc2 100644
--- a/drivers/clk/sunxi-ng/ccu_mp.c
+++ b/drivers/clk/sunxi-ng/ccu_mp.c
@@ -246,7 +246,7 @@ const struct clk_ops ccu_mp_ops = {
.recalc_rate = ccu_mp_recalc_rate,
.set_rate = ccu_mp_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(ccu_mp_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_mp_ops, "SUNXI_CCU");
/*
* Support for MMC timing mode switching
@@ -327,4 +327,4 @@ const struct clk_ops ccu_mp_mmc_ops = {
.recalc_rate = ccu_mp_mmc_recalc_rate,
.set_rate = ccu_mp_mmc_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(ccu_mp_mmc_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_mp_mmc_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_mult.c b/drivers/clk/sunxi-ng/ccu_mult.c
index 7bee217ef111..8d5720f3dec1 100644
--- a/drivers/clk/sunxi-ng/ccu_mult.c
+++ b/drivers/clk/sunxi-ng/ccu_mult.c
@@ -170,4 +170,4 @@ const struct clk_ops ccu_mult_ops = {
.recalc_rate = ccu_mult_recalc_rate,
.set_rate = ccu_mult_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(ccu_mult_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_mult_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_mux.c b/drivers/clk/sunxi-ng/ccu_mux.c
index 5edc63b46651..d7ffbdeee9e0 100644
--- a/drivers/clk/sunxi-ng/ccu_mux.c
+++ b/drivers/clk/sunxi-ng/ccu_mux.c
@@ -66,7 +66,7 @@ unsigned long ccu_mux_helper_apply_prediv(struct ccu_common *common,
{
return parent_rate / ccu_mux_get_prediv(common, cm, parent_index);
}
-EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_apply_prediv, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_apply_prediv, "SUNXI_CCU");
static unsigned long ccu_mux_helper_unapply_prediv(struct ccu_common *common,
struct ccu_mux_internal *cm,
@@ -155,7 +155,7 @@ out:
req->rate = best_rate;
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_determine_rate, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_determine_rate, "SUNXI_CCU");
u8 ccu_mux_helper_get_parent(struct ccu_common *common,
struct ccu_mux_internal *cm)
@@ -178,7 +178,7 @@ u8 ccu_mux_helper_get_parent(struct ccu_common *common,
return parent;
}
-EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_get_parent, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_get_parent, "SUNXI_CCU");
int ccu_mux_helper_set_parent(struct ccu_common *common,
struct ccu_mux_internal *cm,
@@ -205,7 +205,7 @@ int ccu_mux_helper_set_parent(struct ccu_common *common,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_set_parent, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_mux_helper_set_parent, "SUNXI_CCU");
static void ccu_mux_disable(struct clk_hw *hw)
{
@@ -273,7 +273,7 @@ const struct clk_ops ccu_mux_ops = {
.determine_rate = ccu_mux_determine_rate,
.recalc_rate = ccu_mux_recalc_rate,
};
-EXPORT_SYMBOL_NS_GPL(ccu_mux_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_mux_ops, "SUNXI_CCU");
/*
* This clock notifier is called when the frequency of the of the parent
@@ -308,4 +308,4 @@ int ccu_mux_notifier_register(struct clk *clk, struct ccu_mux_nb *mux_nb)
return clk_notifier_register(clk, &mux_nb->clk_nb);
}
-EXPORT_SYMBOL_NS_GPL(ccu_mux_notifier_register, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_mux_notifier_register, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_nk.c b/drivers/clk/sunxi-ng/ccu_nk.c
index 8aa35d5804f3..555e99de2cc6 100644
--- a/drivers/clk/sunxi-ng/ccu_nk.c
+++ b/drivers/clk/sunxi-ng/ccu_nk.c
@@ -158,4 +158,4 @@ const struct clk_ops ccu_nk_ops = {
.round_rate = ccu_nk_round_rate,
.set_rate = ccu_nk_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(ccu_nk_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_nk_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_nkm.c b/drivers/clk/sunxi-ng/ccu_nkm.c
index 1168d894d636..784eec9ac997 100644
--- a/drivers/clk/sunxi-ng/ccu_nkm.c
+++ b/drivers/clk/sunxi-ng/ccu_nkm.c
@@ -267,4 +267,4 @@ const struct clk_ops ccu_nkm_ops = {
.recalc_rate = ccu_nkm_recalc_rate,
.set_rate = ccu_nkm_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(ccu_nkm_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_nkm_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_nkmp.c b/drivers/clk/sunxi-ng/ccu_nkmp.c
index 99359a06892d..6e03b69d4028 100644
--- a/drivers/clk/sunxi-ng/ccu_nkmp.c
+++ b/drivers/clk/sunxi-ng/ccu_nkmp.c
@@ -230,4 +230,4 @@ const struct clk_ops ccu_nkmp_ops = {
.round_rate = ccu_nkmp_round_rate,
.set_rate = ccu_nkmp_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(ccu_nkmp_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_nkmp_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_nm.c b/drivers/clk/sunxi-ng/ccu_nm.c
index ffac3deb89d6..a4e2243b8d6b 100644
--- a/drivers/clk/sunxi-ng/ccu_nm.c
+++ b/drivers/clk/sunxi-ng/ccu_nm.c
@@ -236,4 +236,4 @@ const struct clk_ops ccu_nm_ops = {
.round_rate = ccu_nm_round_rate,
.set_rate = ccu_nm_set_rate,
};
-EXPORT_SYMBOL_NS_GPL(ccu_nm_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_nm_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_phase.c b/drivers/clk/sunxi-ng/ccu_phase.c
index e4cae2afe9db..ca43cf448666 100644
--- a/drivers/clk/sunxi-ng/ccu_phase.c
+++ b/drivers/clk/sunxi-ng/ccu_phase.c
@@ -121,4 +121,4 @@ const struct clk_ops ccu_phase_ops = {
.get_phase = ccu_phase_get_phase,
.set_phase = ccu_phase_set_phase,
};
-EXPORT_SYMBOL_NS_GPL(ccu_phase_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_phase_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_reset.c b/drivers/clk/sunxi-ng/ccu_reset.c
index 6577aa18cb01..55bc7c7cda0f 100644
--- a/drivers/clk/sunxi-ng/ccu_reset.c
+++ b/drivers/clk/sunxi-ng/ccu_reset.c
@@ -75,4 +75,4 @@ const struct reset_control_ops ccu_reset_ops = {
.reset = ccu_reset_reset,
.status = ccu_reset_status,
};
-EXPORT_SYMBOL_NS_GPL(ccu_reset_ops, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_reset_ops, "SUNXI_CCU");
diff --git a/drivers/clk/sunxi-ng/ccu_sdm.c b/drivers/clk/sunxi-ng/ccu_sdm.c
index 41937ed0766d..c564e5f9e610 100644
--- a/drivers/clk/sunxi-ng/ccu_sdm.c
+++ b/drivers/clk/sunxi-ng/ccu_sdm.c
@@ -20,7 +20,7 @@ bool ccu_sdm_helper_is_enabled(struct ccu_common *common,
return !!(readl(common->base + sdm->tuning_reg) & sdm->tuning_enable);
}
-EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_is_enabled, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_is_enabled, "SUNXI_CCU");
void ccu_sdm_helper_enable(struct ccu_common *common,
struct ccu_sdm_internal *sdm,
@@ -50,7 +50,7 @@ void ccu_sdm_helper_enable(struct ccu_common *common,
writel(reg | sdm->enable, common->base + common->reg);
spin_unlock_irqrestore(common->lock, flags);
}
-EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_enable, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_enable, "SUNXI_CCU");
void ccu_sdm_helper_disable(struct ccu_common *common,
struct ccu_sdm_internal *sdm)
@@ -71,7 +71,7 @@ void ccu_sdm_helper_disable(struct ccu_common *common,
writel(reg & ~sdm->tuning_enable, common->base + sdm->tuning_reg);
spin_unlock_irqrestore(common->lock, flags);
}
-EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_disable, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_disable, "SUNXI_CCU");
/*
* Sigma delta modulation provides a way to do fractional-N frequency
@@ -105,7 +105,7 @@ bool ccu_sdm_helper_has_rate(struct ccu_common *common,
return false;
}
-EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_has_rate, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_has_rate, "SUNXI_CCU");
unsigned long ccu_sdm_helper_read_rate(struct ccu_common *common,
struct ccu_sdm_internal *sdm,
@@ -136,7 +136,7 @@ unsigned long ccu_sdm_helper_read_rate(struct ccu_common *common,
/* We can't calculate the effective clock rate, so just fail. */
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_read_rate, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_read_rate, "SUNXI_CCU");
int ccu_sdm_helper_get_factors(struct ccu_common *common,
struct ccu_sdm_internal *sdm,
@@ -158,4 +158,4 @@ int ccu_sdm_helper_get_factors(struct ccu_common *common,
/* nothing found */
return -EINVAL;
}
-EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_get_factors, SUNXI_CCU);
+EXPORT_SYMBOL_NS_GPL(ccu_sdm_helper_get_factors, "SUNXI_CCU");
diff --git a/drivers/clk/thead/clk-th1520-ap.c b/drivers/clk/thead/clk-th1520-ap.c
index 17e32ae08720..1015fab95251 100644
--- a/drivers/clk/thead/clk-th1520-ap.c
+++ b/drivers/clk/thead/clk-th1520-ap.c
@@ -779,6 +779,13 @@ static struct ccu_div dpu1_clk = {
},
};
+static CLK_FIXED_FACTOR_HW(emmc_sdio_ref_clk, "emmc-sdio-ref",
+ &video_pll_clk.common.hw, 4, 1, 0);
+
+static const struct clk_parent_data emmc_sdio_ref_clk_pd[] = {
+ { .hw = &emmc_sdio_ref_clk.hw },
+};
+
static CCU_GATE(CLK_BROM, brom_clk, "brom", ahb2_cpusys_hclk_pd, 0x100, BIT(4), 0);
static CCU_GATE(CLK_BMU, bmu_clk, "bmu", axi4_cpusys2_aclk_pd, 0x100, BIT(5), 0);
static CCU_GATE(CLK_AON2CPU_A2X, aon2cpu_a2x_clk, "aon2cpu-a2x", axi4_cpusys2_aclk_pd,
@@ -798,7 +805,7 @@ static CCU_GATE(CLK_PERISYS_APB4_HCLK, perisys_apb4_hclk, "perisys-apb4-hclk", p
0x150, BIT(12), 0);
static CCU_GATE(CLK_NPU_AXI, npu_axi_clk, "npu-axi", axi_aclk_pd, 0x1c8, BIT(5), 0);
static CCU_GATE(CLK_CPU2VP, cpu2vp_clk, "cpu2vp", axi_aclk_pd, 0x1e0, BIT(13), 0);
-static CCU_GATE(CLK_EMMC_SDIO, emmc_sdio_clk, "emmc-sdio", video_pll_clk_pd, 0x204, BIT(30), 0);
+static CCU_GATE(CLK_EMMC_SDIO, emmc_sdio_clk, "emmc-sdio", emmc_sdio_ref_clk_pd, 0x204, BIT(30), 0);
static CCU_GATE(CLK_GMAC1, gmac1_clk, "gmac1", gmac_pll_clk_pd, 0x204, BIT(26), 0);
static CCU_GATE(CLK_PADCTRL1, padctrl1_clk, "padctrl1", perisys_apb_pclk_pd, 0x204, BIT(24), 0);
static CCU_GATE(CLK_DSMART, dsmart_clk, "dsmart", perisys_apb_pclk_pd, 0x204, BIT(23), 0);
@@ -1059,6 +1066,10 @@ static int th1520_clk_probe(struct platform_device *pdev)
return ret;
priv->hws[CLK_PLL_GMAC_100M] = &gmac_pll_clk_100m.hw;
+ ret = devm_clk_hw_register(dev, &emmc_sdio_ref_clk.hw);
+ if (ret)
+ return ret;
+
ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, priv);
if (ret)
return ret;
diff --git a/drivers/clocksource/hyperv_timer.c b/drivers/clocksource/hyperv_timer.c
index 99177835cade..b39dee7b93af 100644
--- a/drivers/clocksource/hyperv_timer.c
+++ b/drivers/clocksource/hyperv_timer.c
@@ -27,7 +27,8 @@
#include <asm/mshyperv.h>
static struct clock_event_device __percpu *hv_clock_event;
-static u64 hv_sched_clock_offset __ro_after_init;
+/* Note: offset can hold negative values after hibernation. */
+static u64 hv_sched_clock_offset __read_mostly;
/*
* If false, we're using the old mechanism for stimer0 interrupts
@@ -470,6 +471,17 @@ static void resume_hv_clock_tsc(struct clocksource *arg)
hv_set_msr(HV_MSR_REFERENCE_TSC, tsc_msr.as_uint64);
}
+/*
+ * Called during resume from hibernation, from overridden
+ * x86_platform.restore_sched_clock_state routine. This is to adjust offsets
+ * used to calculate time for hv tsc page based sched_clock, to account for
+ * time spent before hibernation.
+ */
+void hv_adj_sched_clock_offset(u64 offset)
+{
+ hv_sched_clock_offset -= offset;
+}
+
#ifdef HAVE_VDSO_CLOCKMODE_HVCLOCK
static int hv_cs_enable(struct clocksource *cs)
{
diff --git a/drivers/clocksource/timer-sun5i.c b/drivers/clocksource/timer-sun5i.c
index 0d229a9058da..6b48a9006444 100644
--- a/drivers/clocksource/timer-sun5i.c
+++ b/drivers/clocksource/timer-sun5i.c
@@ -318,7 +318,7 @@ MODULE_DEVICE_TABLE(of, sun5i_timer_of_match);
static struct platform_driver sun5i_timer_driver = {
.probe = sun5i_timer_probe,
- .remove_new = sun5i_timer_remove,
+ .remove = sun5i_timer_remove,
.driver = {
.name = "sun5i-timer",
.of_match_table = sun5i_timer_of_match,
diff --git a/drivers/clocksource/timer-tegra186.c b/drivers/clocksource/timer-tegra186.c
index 304537dadf2c..5d4cf5237a11 100644
--- a/drivers/clocksource/timer-tegra186.c
+++ b/drivers/clocksource/timer-tegra186.c
@@ -502,7 +502,7 @@ static struct platform_driver tegra186_wdt_driver = {
.of_match_table = tegra186_timer_of_match,
},
.probe = tegra186_timer_probe,
- .remove_new = tegra186_timer_remove,
+ .remove = tegra186_timer_remove,
};
module_platform_driver(tegra186_wdt_driver);
diff --git a/drivers/clocksource/timer-ti-dm.c b/drivers/clocksource/timer-ti-dm.c
index 3666d94cc8dd..e9e32df6b566 100644
--- a/drivers/clocksource/timer-ti-dm.c
+++ b/drivers/clocksource/timer-ti-dm.c
@@ -1295,7 +1295,7 @@ MODULE_DEVICE_TABLE(of, omap_timer_match);
static struct platform_driver omap_dm_timer_driver = {
.probe = omap_dm_timer_probe,
- .remove_new = omap_dm_timer_remove,
+ .remove = omap_dm_timer_remove,
.driver = {
.name = "omap_timer",
.of_match_table = omap_timer_match,
diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
index 1b481731df96..b9df9b19d4bd 100644
--- a/drivers/comedi/comedi_fops.c
+++ b/drivers/comedi/comedi_fops.c
@@ -2407,6 +2407,18 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
start += PAGE_SIZE;
}
+
+#ifdef CONFIG_MMU
+ /*
+ * Leaving behind a partial mapping of a buffer we're about to
+ * drop is unsafe, see remap_pfn_range_notrack().
+ * We need to zap the range here ourselves instead of relying
+ * on the automatic zapping in remap_pfn_range() because we call
+ * remap_pfn_range() in a loop.
+ */
+ if (retval)
+ zap_vma_ptes(vma, vma->vm_start, size);
+#endif
}
if (retval == 0) {
diff --git a/drivers/counter/104-quad-8.c b/drivers/counter/104-quad-8.c
index 4a6868b8f58b..ce81fc4e1ae7 100644
--- a/drivers/counter/104-quad-8.c
+++ b/drivers/counter/104-quad-8.c
@@ -1360,4 +1360,4 @@ module_isa_driver_with_irq(quad8_driver, num_quad8, num_irq);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES 104-QUAD-8 driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/counter/counter-chrdev.c b/drivers/counter/counter-chrdev.c
index 3ee75e1a78cd..23fdf0caf712 100644
--- a/drivers/counter/counter-chrdev.c
+++ b/drivers/counter/counter-chrdev.c
@@ -672,4 +672,4 @@ exit_early:
if (copied)
wake_up_poll(&counter->events_wait, EPOLLIN);
}
-EXPORT_SYMBOL_NS_GPL(counter_push_event, COUNTER);
+EXPORT_SYMBOL_NS_GPL(counter_push_event, "COUNTER");
diff --git a/drivers/counter/counter-core.c b/drivers/counter/counter-core.c
index 893b4f0726d2..50bd30ba3d03 100644
--- a/drivers/counter/counter-core.c
+++ b/drivers/counter/counter-core.c
@@ -74,7 +74,7 @@ void *counter_priv(const struct counter_device *const counter)
return &ch->privdata;
}
-EXPORT_SYMBOL_NS_GPL(counter_priv, COUNTER);
+EXPORT_SYMBOL_NS_GPL(counter_priv, "COUNTER");
/**
* counter_alloc - allocate a counter_device
@@ -134,13 +134,13 @@ err_ida_alloc:
return NULL;
}
-EXPORT_SYMBOL_NS_GPL(counter_alloc, COUNTER);
+EXPORT_SYMBOL_NS_GPL(counter_alloc, "COUNTER");
void counter_put(struct counter_device *counter)
{
put_device(&counter->dev);
}
-EXPORT_SYMBOL_NS_GPL(counter_put, COUNTER);
+EXPORT_SYMBOL_NS_GPL(counter_put, "COUNTER");
/**
* counter_add - complete registration of a counter
@@ -167,7 +167,7 @@ int counter_add(struct counter_device *counter)
/* implies device_add(dev) */
return cdev_device_add(&counter->chrdev, dev);
}
-EXPORT_SYMBOL_NS_GPL(counter_add, COUNTER);
+EXPORT_SYMBOL_NS_GPL(counter_add, "COUNTER");
/**
* counter_unregister - unregister Counter from the system
@@ -189,7 +189,7 @@ void counter_unregister(struct counter_device *const counter)
mutex_unlock(&counter->ops_exist_lock);
}
-EXPORT_SYMBOL_NS_GPL(counter_unregister, COUNTER);
+EXPORT_SYMBOL_NS_GPL(counter_unregister, "COUNTER");
static void devm_counter_release(void *counter)
{
@@ -224,7 +224,7 @@ struct counter_device *devm_counter_alloc(struct device *dev, size_t sizeof_priv
return counter;
}
-EXPORT_SYMBOL_NS_GPL(devm_counter_alloc, COUNTER);
+EXPORT_SYMBOL_NS_GPL(devm_counter_alloc, "COUNTER");
/**
* devm_counter_add - complete registration of a counter
@@ -245,7 +245,7 @@ int devm_counter_add(struct device *dev,
return devm_add_action_or_reset(dev, devm_counter_release, counter);
}
-EXPORT_SYMBOL_NS_GPL(devm_counter_add, COUNTER);
+EXPORT_SYMBOL_NS_GPL(devm_counter_add, "COUNTER");
#define COUNTER_DEV_MAX 256
diff --git a/drivers/counter/ftm-quaddec.c b/drivers/counter/ftm-quaddec.c
index 200876f3ec04..c47741292ae1 100644
--- a/drivers/counter/ftm-quaddec.c
+++ b/drivers/counter/ftm-quaddec.c
@@ -311,6 +311,7 @@ static const struct of_device_id ftm_quaddec_match[] = {
{ .compatible = "fsl,ftm-quaddec" },
{},
};
+MODULE_DEVICE_TABLE(of, ftm_quaddec_match);
static struct platform_driver ftm_quaddec_driver = {
.driver = {
@@ -326,4 +327,4 @@ MODULE_DESCRIPTION("Flex Timer Module Quadrature decoder");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kjeld Flarup <kfa@deif.com>");
MODULE_AUTHOR("Patrick Havelange <patrick.havelange@essensium.com>");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/counter/i8254.c b/drivers/counter/i8254.c
index 6d74e8ef92f0..95ad928725ec 100644
--- a/drivers/counter/i8254.c
+++ b/drivers/counter/i8254.c
@@ -439,9 +439,9 @@ int devm_i8254_regmap_register(struct device *const dev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(devm_i8254_regmap_register, I8254);
+EXPORT_SYMBOL_NS_GPL(devm_i8254_regmap_register, "I8254");
MODULE_AUTHOR("William Breathitt Gray");
MODULE_DESCRIPTION("Intel 8254 Programmable Interval Timer");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/counter/intel-qep.c b/drivers/counter/intel-qep.c
index af5942e66f7d..c49c178056f4 100644
--- a/drivers/counter/intel-qep.c
+++ b/drivers/counter/intel-qep.c
@@ -408,13 +408,9 @@ static int intel_qep_probe(struct pci_dev *pci, const struct pci_device_id *id)
pci_set_master(pci);
- ret = pcim_iomap_regions(pci, BIT(0), pci_name(pci));
- if (ret)
- return ret;
-
- regs = pcim_iomap_table(pci)[0];
- if (!regs)
- return -ENOMEM;
+ regs = pcim_iomap_region(pci, 0, pci_name(pci));
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
qep->dev = dev;
qep->regs = regs;
@@ -523,4 +519,4 @@ MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@linux.intel.com>");
MODULE_AUTHOR("Raymond Tan <raymond.tan@intel.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Intel Quadrature Encoder Peripheral driver");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/counter/interrupt-cnt.c b/drivers/counter/interrupt-cnt.c
index 229473855c5b..949598d51575 100644
--- a/drivers/counter/interrupt-cnt.c
+++ b/drivers/counter/interrupt-cnt.c
@@ -253,4 +253,4 @@ MODULE_ALIAS("platform:interrupt-counter");
MODULE_AUTHOR("Oleksij Rempel <o.rempel@pengutronix.de>");
MODULE_DESCRIPTION("Interrupt counter driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/counter/microchip-tcb-capture.c b/drivers/counter/microchip-tcb-capture.c
index b3e615cbd2ca..2f096a5b973d 100644
--- a/drivers/counter/microchip-tcb-capture.c
+++ b/drivers/counter/microchip-tcb-capture.c
@@ -403,4 +403,4 @@ module_platform_driver(mchp_tc_driver);
MODULE_AUTHOR("Kamel Bouhara <kamel.bouhara@bootlin.com>");
MODULE_DESCRIPTION("Microchip TCB Capture driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/counter/rz-mtu3-cnt.c b/drivers/counter/rz-mtu3-cnt.c
index ee821493b166..e755d54dfece 100644
--- a/drivers/counter/rz-mtu3-cnt.c
+++ b/drivers/counter/rz-mtu3-cnt.c
@@ -903,4 +903,4 @@ MODULE_AUTHOR("Biju Das <biju.das.jz@bp.renesas.com>");
MODULE_ALIAS("platform:rz-mtu3-counter");
MODULE_DESCRIPTION("Renesas RZ/G2L MTU3a counter driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/counter/stm32-lptimer-cnt.c b/drivers/counter/stm32-lptimer-cnt.c
index 8439755559b2..cf73f65baf60 100644
--- a/drivers/counter/stm32-lptimer-cnt.c
+++ b/drivers/counter/stm32-lptimer-cnt.c
@@ -520,4 +520,4 @@ MODULE_AUTHOR("Fabrice Gasnier <fabrice.gasnier@st.com>");
MODULE_ALIAS("platform:stm32-lptimer-counter");
MODULE_DESCRIPTION("STMicroelectronics STM32 LPTIM counter driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/counter/stm32-timer-cnt.c b/drivers/counter/stm32-timer-cnt.c
index 186e73d6ccb4..e75b69476a00 100644
--- a/drivers/counter/stm32-timer-cnt.c
+++ b/drivers/counter/stm32-timer-cnt.c
@@ -214,11 +214,17 @@ static int stm32_count_enable_write(struct counter_device *counter,
{
struct stm32_timer_cnt *const priv = counter_priv(counter);
u32 cr1;
+ int ret;
if (enable) {
regmap_read(priv->regmap, TIM_CR1, &cr1);
- if (!(cr1 & TIM_CR1_CEN))
- clk_enable(priv->clk);
+ if (!(cr1 & TIM_CR1_CEN)) {
+ ret = clk_enable(priv->clk);
+ if (ret) {
+ dev_err(counter->parent, "Cannot enable clock %d\n", ret);
+ return ret;
+ }
+ }
regmap_update_bits(priv->regmap, TIM_CR1, TIM_CR1_CEN,
TIM_CR1_CEN);
@@ -694,6 +700,7 @@ static int stm32_timer_cnt_probe_encoder(struct device *dev,
}
ret = of_property_read_u32(tnode, "reg", &idx);
+ of_node_put(tnode);
if (ret) {
dev_err(dev, "Can't get index (%d)\n", ret);
return ret;
@@ -816,7 +823,11 @@ static int __maybe_unused stm32_timer_cnt_resume(struct device *dev)
return ret;
if (priv->enabled) {
- clk_enable(priv->clk);
+ ret = clk_enable(priv->clk);
+ if (ret) {
+ dev_err(dev, "Cannot enable clock %d\n", ret);
+ return ret;
+ }
/* Restore registers that may have been lost */
regmap_write(priv->regmap, TIM_SMCR, priv->bak.smcr);
@@ -853,4 +864,4 @@ MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
MODULE_ALIAS("platform:stm32-timer-counter");
MODULE_DESCRIPTION("STMicroelectronics STM32 TIMER counter driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/counter/ti-ecap-capture.c b/drivers/counter/ti-ecap-capture.c
index 675447315caf..3faaf7f60539 100644
--- a/drivers/counter/ti-ecap-capture.c
+++ b/drivers/counter/ti-ecap-capture.c
@@ -574,8 +574,13 @@ static int ecap_cnt_resume(struct device *dev)
{
struct counter_device *counter_dev = dev_get_drvdata(dev);
struct ecap_cnt_dev *ecap_dev = counter_priv(counter_dev);
+ int ret;
- clk_enable(ecap_dev->clk);
+ ret = clk_enable(ecap_dev->clk);
+ if (ret) {
+ dev_err(dev, "Cannot enable clock %d\n", ret);
+ return ret;
+ }
ecap_cnt_capture_set_evmode(counter_dev, ecap_dev->pm_ctx.ev_mode);
@@ -598,7 +603,7 @@ MODULE_DEVICE_TABLE(of, ecap_cnt_of_match);
static struct platform_driver ecap_cnt_driver = {
.probe = ecap_cnt_probe,
- .remove_new = ecap_cnt_remove,
+ .remove = ecap_cnt_remove,
.driver = {
.name = "ecap-capture",
.of_match_table = ecap_cnt_of_match,
@@ -610,4 +615,4 @@ module_platform_driver(ecap_cnt_driver);
MODULE_DESCRIPTION("ECAP Capture driver");
MODULE_AUTHOR("Julien Panis <jpanis@baylibre.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/counter/ti-eqep.c b/drivers/counter/ti-eqep.c
index 313b91456f26..bc586eff0dae 100644
--- a/drivers/counter/ti-eqep.c
+++ b/drivers/counter/ti-eqep.c
@@ -548,7 +548,7 @@ MODULE_DEVICE_TABLE(of, ti_eqep_of_match);
static struct platform_driver ti_eqep_driver = {
.probe = ti_eqep_probe,
- .remove_new = ti_eqep_remove,
+ .remove = ti_eqep_remove,
.driver = {
.name = "ti-eqep-cnt",
.of_match_table = ti_eqep_of_match,
@@ -559,4 +559,4 @@ module_platform_driver(ti_eqep_driver);
MODULE_AUTHOR("David Lechner <david@lechnology.com>");
MODULE_DESCRIPTION("TI eQEP counter driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(COUNTER);
+MODULE_IMPORT_NS("COUNTER");
diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c
index d7630bab2516..66e5dfc711c0 100644
--- a/drivers/cpufreq/amd-pstate.c
+++ b/drivers/cpufreq/amd-pstate.c
@@ -374,15 +374,19 @@ static inline int amd_pstate_cppc_enable(bool enable)
static int msr_init_perf(struct amd_cpudata *cpudata)
{
- u64 cap1;
+ u64 cap1, numerator;
int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1,
&cap1);
if (ret)
return ret;
- WRITE_ONCE(cpudata->highest_perf, AMD_CPPC_HIGHEST_PERF(cap1));
- WRITE_ONCE(cpudata->max_limit_perf, AMD_CPPC_HIGHEST_PERF(cap1));
+ ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
+ if (ret)
+ return ret;
+
+ WRITE_ONCE(cpudata->highest_perf, numerator);
+ WRITE_ONCE(cpudata->max_limit_perf, numerator);
WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1));
WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1));
WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1));
@@ -394,13 +398,18 @@ static int msr_init_perf(struct amd_cpudata *cpudata)
static int shmem_init_perf(struct amd_cpudata *cpudata)
{
struct cppc_perf_caps cppc_perf;
+ u64 numerator;
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
if (ret)
return ret;
- WRITE_ONCE(cpudata->highest_perf, cppc_perf.highest_perf);
- WRITE_ONCE(cpudata->max_limit_perf, cppc_perf.highest_perf);
+ ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
+ if (ret)
+ return ret;
+
+ WRITE_ONCE(cpudata->highest_perf, numerator);
+ WRITE_ONCE(cpudata->max_limit_perf, numerator);
WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
WRITE_ONCE(cpudata->lowest_nonlinear_perf,
cppc_perf.lowest_nonlinear_perf);
@@ -561,16 +570,13 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy_data)
static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy)
{
- u32 max_limit_perf, min_limit_perf, lowest_perf, max_perf;
+ u32 max_limit_perf, min_limit_perf, lowest_perf, max_perf, max_freq;
struct amd_cpudata *cpudata = policy->driver_data;
- if (cpudata->boost_supported && !policy->boost_enabled)
- max_perf = READ_ONCE(cpudata->nominal_perf);
- else
- max_perf = READ_ONCE(cpudata->highest_perf);
-
- max_limit_perf = div_u64(policy->max * max_perf, policy->cpuinfo.max_freq);
- min_limit_perf = div_u64(policy->min * max_perf, policy->cpuinfo.max_freq);
+ max_perf = READ_ONCE(cpudata->highest_perf);
+ max_freq = READ_ONCE(cpudata->max_freq);
+ max_limit_perf = div_u64(policy->max * max_perf, max_freq);
+ min_limit_perf = div_u64(policy->min * max_perf, max_freq);
lowest_perf = READ_ONCE(cpudata->lowest_perf);
if (min_limit_perf < lowest_perf)
@@ -889,7 +895,6 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
{
int ret;
u32 min_freq, max_freq;
- u64 numerator;
u32 nominal_perf, nominal_freq;
u32 lowest_nonlinear_perf, lowest_nonlinear_freq;
u32 boost_ratio, lowest_nonlinear_ratio;
@@ -911,10 +916,7 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
nominal_perf = READ_ONCE(cpudata->nominal_perf);
- ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
- if (ret)
- return ret;
- boost_ratio = div_u64(numerator << SCHED_CAPACITY_SHIFT, nominal_perf);
+ boost_ratio = div_u64(cpudata->highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000;
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
@@ -1869,18 +1871,18 @@ static int __init amd_pstate_init(void)
static_call_update(amd_pstate_update_perf, shmem_update_perf);
}
- ret = amd_pstate_register_driver(cppc_state);
- if (ret) {
- pr_err("failed to register with return %d\n", ret);
- return ret;
- }
-
if (amd_pstate_prefcore) {
ret = amd_detect_prefcore(&amd_pstate_prefcore);
if (ret)
return ret;
}
+ ret = amd_pstate_register_driver(cppc_state);
+ if (ret) {
+ pr_err("failed to register with return %d\n", ret);
+ return ret;
+ }
+
dev_root = bus_get_dev_root(&cpu_subsys);
if (dev_root) {
ret = sysfs_create_group(&dev_root->kobj, &amd_pstate_global_attr_group);
diff --git a/drivers/cpuidle/cpuidle-kirkwood.c b/drivers/cpuidle/cpuidle-kirkwood.c
index 602c4dfdd7e2..5235e6e8f360 100644
--- a/drivers/cpuidle/cpuidle-kirkwood.c
+++ b/drivers/cpuidle/cpuidle-kirkwood.c
@@ -66,7 +66,7 @@ static void kirkwood_cpuidle_remove(struct platform_device *pdev)
static struct platform_driver kirkwood_cpuidle_driver = {
.probe = kirkwood_cpuidle_probe,
- .remove_new = kirkwood_cpuidle_remove,
+ .remove = kirkwood_cpuidle_remove,
.driver = {
.name = "kirkwood_cpuidle",
},
diff --git a/drivers/crypto/geode-aes.c b/drivers/crypto/geode-aes.c
index fa5a9f207bc9..d933f26aeb3a 100644
--- a/drivers/crypto/geode-aes.c
+++ b/drivers/crypto/geode-aes.c
@@ -433,4 +433,4 @@ module_pci_driver(geode_aes_driver);
MODULE_AUTHOR("Advanced Micro Devices, Inc.");
MODULE_DESCRIPTION("Geode LX Hardware AES driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/drivers/crypto/hisilicon/debugfs.c b/drivers/crypto/hisilicon/debugfs.c
index 1b9b7bccdeff..45e130b901eb 100644
--- a/drivers/crypto/hisilicon/debugfs.c
+++ b/drivers/crypto/hisilicon/debugfs.c
@@ -192,7 +192,7 @@ static int qm_sqc_dump(struct hisi_qm *qm, char *s, char *name)
down_read(&qm->qps_lock);
if (qm->sqc) {
- memcpy(&sqc, qm->sqc + qp_id * sizeof(struct qm_sqc), sizeof(struct qm_sqc));
+ memcpy(&sqc, qm->sqc + qp_id, sizeof(struct qm_sqc));
sqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
sqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
dump_show(qm, &sqc, sizeof(struct qm_sqc), "SOFT SQC");
@@ -229,7 +229,7 @@ static int qm_cqc_dump(struct hisi_qm *qm, char *s, char *name)
down_read(&qm->qps_lock);
if (qm->cqc) {
- memcpy(&cqc, qm->cqc + qp_id * sizeof(struct qm_cqc), sizeof(struct qm_cqc));
+ memcpy(&cqc, qm->cqc + qp_id, sizeof(struct qm_cqc));
cqc.base_h = cpu_to_le32(QM_XQC_ADDR_MASK);
cqc.base_l = cpu_to_le32(QM_XQC_ADDR_MASK);
dump_show(qm, &cqc, sizeof(struct qm_cqc), "SOFT CQC");
diff --git a/drivers/crypto/inside-secure/safexcel.c b/drivers/crypto/inside-secure/safexcel.c
index 45758c7aa80e..9ca80d082c4f 100644
--- a/drivers/crypto/inside-secure/safexcel.c
+++ b/drivers/crypto/inside-secure/safexcel.c
@@ -2031,7 +2031,7 @@ MODULE_AUTHOR("Ofer Heifetz <oferh@marvell.com>");
MODULE_AUTHOR("Igal Liberman <igall@marvell.com>");
MODULE_DESCRIPTION("Support for SafeXcel cryptographic engines: EIP97 & EIP197");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
MODULE_FIRMWARE("ifpp.bin");
MODULE_FIRMWARE("ipue.bin");
diff --git a/drivers/crypto/intel/iaa/Makefile b/drivers/crypto/intel/iaa/Makefile
index b64b208d2344..55bda7770fac 100644
--- a/drivers/crypto/intel/iaa/Makefile
+++ b/drivers/crypto/intel/iaa/Makefile
@@ -3,7 +3,7 @@
# Makefile for IAA crypto device drivers
#
-ccflags-y += -I $(srctree)/drivers/dma/idxd -DDEFAULT_SYMBOL_NAMESPACE=IDXD
+ccflags-y += -I $(srctree)/drivers/dma/idxd -DDEFAULT_SYMBOL_NAMESPACE='"IDXD"'
obj-$(CONFIG_CRYPTO_DEV_IAA_CRYPTO) := iaa_crypto.o
diff --git a/drivers/crypto/intel/iaa/iaa_crypto_main.c b/drivers/crypto/intel/iaa/iaa_crypto_main.c
index 8fced88d3d06..9e557649e5d0 100644
--- a/drivers/crypto/intel/iaa/iaa_crypto_main.c
+++ b/drivers/crypto/intel/iaa/iaa_crypto_main.c
@@ -2094,7 +2094,7 @@ static void __exit iaa_crypto_cleanup_module(void)
pr_debug("cleaned up\n");
}
-MODULE_IMPORT_NS(IDXD);
+MODULE_IMPORT_NS("IDXD");
MODULE_LICENSE("GPL");
MODULE_ALIAS_IDXD_DEVICE(0);
MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c
index 788a11cdb34b..9589d60fb281 100644
--- a/drivers/crypto/intel/qat/qat_420xx/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_420xx/adf_drv.c
@@ -204,4 +204,4 @@ MODULE_FIRMWARE(ADF_420XX_MMP);
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
MODULE_SOFTDEP("pre: crypto-intel_qat");
-MODULE_IMPORT_NS(CRYPTO_QAT);
+MODULE_IMPORT_NS("CRYPTO_QAT");
diff --git a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
index 115eabfd1f6b..d7de1cad1335 100644
--- a/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_4xxx/adf_drv.c
@@ -208,4 +208,4 @@ MODULE_FIRMWARE(ADF_402XX_MMP);
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
MODULE_SOFTDEP("pre: crypto-intel_qat");
-MODULE_IMPORT_NS(CRYPTO_QAT);
+MODULE_IMPORT_NS("CRYPTO_QAT");
diff --git a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c
index 4d18057745d4..caa53882fda6 100644
--- a/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c3xxx/adf_drv.c
@@ -252,4 +252,4 @@ MODULE_FIRMWARE(ADF_C3XXX_FW);
MODULE_FIRMWARE(ADF_C3XXX_MMP);
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
-MODULE_IMPORT_NS(CRYPTO_QAT);
+MODULE_IMPORT_NS("CRYPTO_QAT");
diff --git a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c
index f0023cfb234c..c622793e94a8 100644
--- a/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c3xxxvf/adf_drv.c
@@ -226,4 +226,4 @@ MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Intel");
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
-MODULE_IMPORT_NS(CRYPTO_QAT);
+MODULE_IMPORT_NS("CRYPTO_QAT");
diff --git a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c
index e6b5de55434e..b7398fee19ed 100644
--- a/drivers/crypto/intel/qat/qat_c62x/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c62x/adf_drv.c
@@ -252,4 +252,4 @@ MODULE_FIRMWARE(ADF_C62X_FW);
MODULE_FIRMWARE(ADF_C62X_MMP);
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
-MODULE_IMPORT_NS(CRYPTO_QAT);
+MODULE_IMPORT_NS("CRYPTO_QAT");
diff --git a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c
index 2bd5b0ff00e3..4840d44bbd5b 100644
--- a/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_c62xvf/adf_drv.c
@@ -226,4 +226,4 @@ MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Intel");
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
-MODULE_IMPORT_NS(CRYPTO_QAT);
+MODULE_IMPORT_NS("CRYPTO_QAT");
diff --git a/drivers/crypto/intel/qat/qat_common/Makefile b/drivers/crypto/intel/qat/qat_common/Makefile
index eac73cbfdd38..7acf9c576149 100644
--- a/drivers/crypto/intel/qat/qat_common/Makefile
+++ b/drivers/crypto/intel/qat/qat_common/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_CRYPTO_DEV_QAT) += intel_qat.o
-ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=CRYPTO_QAT
+ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE='"CRYPTO_QAT"'
intel_qat-objs := adf_cfg.o \
adf_isr.o \
adf_ctl_drv.o \
diff --git a/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c b/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c
index 70fa0f6497a9..48c62a14a6a7 100644
--- a/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c
+++ b/drivers/crypto/intel/qat/qat_common/adf_ctl_drv.c
@@ -475,4 +475,4 @@ MODULE_AUTHOR("Intel");
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_ALIAS_CRYPTO("intel_qat");
MODULE_VERSION(ADF_DRV_VERSION);
-MODULE_IMPORT_NS(CRYPTO_INTERNAL);
+MODULE_IMPORT_NS("CRYPTO_INTERNAL");
diff --git a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c
index 2a50cce41515..3137fc3b5cf6 100644
--- a/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_dh895xcc/adf_drv.c
@@ -252,4 +252,4 @@ MODULE_FIRMWARE(ADF_DH895XCC_FW);
MODULE_FIRMWARE(ADF_DH895XCC_MMP);
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
-MODULE_IMPORT_NS(CRYPTO_QAT);
+MODULE_IMPORT_NS("CRYPTO_QAT");
diff --git a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c
index 7cb015b55122..7cd528ee31e7 100644
--- a/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c
+++ b/drivers/crypto/intel/qat/qat_dh895xccvf/adf_drv.c
@@ -226,4 +226,4 @@ MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("Intel");
MODULE_DESCRIPTION("Intel(R) QuickAssist Technology");
MODULE_VERSION(ADF_DRV_VERSION);
-MODULE_IMPORT_NS(CRYPTO_QAT);
+MODULE_IMPORT_NS("CRYPTO_QAT");
diff --git a/drivers/crypto/marvell/octeontx2/cn10k_cpt.c b/drivers/crypto/marvell/octeontx2/cn10k_cpt.c
index 6bfc59e67747..5cae8fafa151 100644
--- a/drivers/crypto/marvell/octeontx2/cn10k_cpt.c
+++ b/drivers/crypto/marvell/octeontx2/cn10k_cpt.c
@@ -73,7 +73,7 @@ int cn10k_cptpf_lmtst_init(struct otx2_cptpf_dev *cptpf)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cn10k_cptpf_lmtst_init, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(cn10k_cptpf_lmtst_init, "CRYPTO_DEV_OCTEONTX2_CPT");
int cn10k_cptvf_lmtst_init(struct otx2_cptvf_dev *cptvf)
{
@@ -94,7 +94,7 @@ int cn10k_cptvf_lmtst_init(struct otx2_cptvf_dev *cptvf)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cn10k_cptvf_lmtst_init, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(cn10k_cptvf_lmtst_init, "CRYPTO_DEV_OCTEONTX2_CPT");
void cn10k_cpt_hw_ctx_clear(struct pci_dev *pdev,
struct cn10k_cpt_errata_ctx *er_ctx)
@@ -110,7 +110,7 @@ void cn10k_cpt_hw_ctx_clear(struct pci_dev *pdev,
DMA_BIDIRECTIONAL);
kfree(er_ctx->hw_ctx);
}
-EXPORT_SYMBOL_NS_GPL(cn10k_cpt_hw_ctx_clear, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(cn10k_cpt_hw_ctx_clear, "CRYPTO_DEV_OCTEONTX2_CPT");
void cn10k_cpt_hw_ctx_set(union cn10k_cpt_hw_ctx *hctx, u16 ctx_sz)
{
@@ -119,7 +119,7 @@ void cn10k_cpt_hw_ctx_set(union cn10k_cpt_hw_ctx *hctx, u16 ctx_sz)
hctx->w0.ctx_sz = ctx_sz;
hctx->w0.ctx_push_sz = 1;
}
-EXPORT_SYMBOL_NS_GPL(cn10k_cpt_hw_ctx_set, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(cn10k_cpt_hw_ctx_set, "CRYPTO_DEV_OCTEONTX2_CPT");
int cn10k_cpt_hw_ctx_init(struct pci_dev *pdev,
struct cn10k_cpt_errata_ctx *er_ctx)
@@ -149,7 +149,7 @@ int cn10k_cpt_hw_ctx_init(struct pci_dev *pdev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cn10k_cpt_hw_ctx_init, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(cn10k_cpt_hw_ctx_init, "CRYPTO_DEV_OCTEONTX2_CPT");
void cn10k_cpt_ctx_flush(struct pci_dev *pdev, u64 cptr, bool inval)
{
@@ -168,7 +168,7 @@ void cn10k_cpt_ctx_flush(struct pci_dev *pdev, u64 cptr, bool inval)
otx2_cpt_read64(lfs->reg_base, lfs->blkaddr, lfs->lf[0].slot,
OTX2_CPT_LF_CTX_ERR);
}
-EXPORT_SYMBOL_NS_GPL(cn10k_cpt_ctx_flush, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(cn10k_cpt_ctx_flush, "CRYPTO_DEV_OCTEONTX2_CPT");
void cptvf_hw_ops_get(struct otx2_cptvf_dev *cptvf)
{
@@ -177,4 +177,4 @@ void cptvf_hw_ops_get(struct otx2_cptvf_dev *cptvf)
else
cptvf->lfs.ops = &otx2_hw_ops;
}
-EXPORT_SYMBOL_NS_GPL(cptvf_hw_ops_get, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(cptvf_hw_ops_get, "CRYPTO_DEV_OCTEONTX2_CPT");
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c b/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c
index 5be0103c1fb8..b8b7c8a3c0ca 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cpt_mbox_common.c
@@ -19,7 +19,7 @@ int otx2_cpt_send_mbox_msg(struct otx2_mbox *mbox, struct pci_dev *pdev)
}
return ret;
}
-EXPORT_SYMBOL_NS_GPL(otx2_cpt_send_mbox_msg, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_send_mbox_msg, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cpt_send_ready_msg(struct otx2_mbox *mbox, struct pci_dev *pdev)
{
@@ -37,13 +37,13 @@ int otx2_cpt_send_ready_msg(struct otx2_mbox *mbox, struct pci_dev *pdev)
return otx2_cpt_send_mbox_msg(mbox, pdev);
}
-EXPORT_SYMBOL_NS_GPL(otx2_cpt_send_ready_msg, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_send_ready_msg, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cpt_send_af_reg_requests(struct otx2_mbox *mbox, struct pci_dev *pdev)
{
return otx2_cpt_send_mbox_msg(mbox, pdev);
}
-EXPORT_SYMBOL_NS_GPL(otx2_cpt_send_af_reg_requests, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_send_af_reg_requests, "CRYPTO_DEV_OCTEONTX2_CPT");
static int otx2_cpt_add_read_af_reg(struct otx2_mbox *mbox,
struct pci_dev *pdev, u64 reg,
@@ -95,7 +95,7 @@ int otx2_cpt_add_write_af_reg(struct otx2_mbox *mbox, struct pci_dev *pdev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(otx2_cpt_add_write_af_reg, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_add_write_af_reg, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cpt_read_af_reg(struct otx2_mbox *mbox, struct pci_dev *pdev,
u64 reg, u64 *val, int blkaddr)
@@ -108,7 +108,7 @@ int otx2_cpt_read_af_reg(struct otx2_mbox *mbox, struct pci_dev *pdev,
return otx2_cpt_send_mbox_msg(mbox, pdev);
}
-EXPORT_SYMBOL_NS_GPL(otx2_cpt_read_af_reg, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_read_af_reg, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cpt_write_af_reg(struct otx2_mbox *mbox, struct pci_dev *pdev,
u64 reg, u64 val, int blkaddr)
@@ -121,7 +121,7 @@ int otx2_cpt_write_af_reg(struct otx2_mbox *mbox, struct pci_dev *pdev,
return otx2_cpt_send_mbox_msg(mbox, pdev);
}
-EXPORT_SYMBOL_NS_GPL(otx2_cpt_write_af_reg, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_write_af_reg, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cpt_attach_rscrs_msg(struct otx2_cptlfs_info *lfs)
{
@@ -180,7 +180,7 @@ int otx2_cpt_detach_rsrcs_msg(struct otx2_cptlfs_info *lfs)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(otx2_cpt_detach_rsrcs_msg, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_detach_rsrcs_msg, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cpt_msix_offset_msg(struct otx2_cptlfs_info *lfs)
{
@@ -213,7 +213,7 @@ int otx2_cpt_msix_offset_msg(struct otx2_cptlfs_info *lfs)
}
return ret;
}
-EXPORT_SYMBOL_NS_GPL(otx2_cpt_msix_offset_msg, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_msix_offset_msg, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cpt_sync_mbox_msg(struct otx2_mbox *mbox)
{
@@ -228,7 +228,7 @@ int otx2_cpt_sync_mbox_msg(struct otx2_mbox *mbox)
return otx2_mbox_check_rsp_msgs(mbox, 0);
}
-EXPORT_SYMBOL_NS_GPL(otx2_cpt_sync_mbox_msg, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_sync_mbox_msg, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cpt_lf_reset_msg(struct otx2_cptlfs_info *lfs, int slot)
{
@@ -254,4 +254,4 @@ int otx2_cpt_lf_reset_msg(struct otx2_cptlfs_info *lfs, int slot)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(otx2_cpt_lf_reset_msg, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cpt_lf_reset_msg, "CRYPTO_DEV_OCTEONTX2_CPT");
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptlf.c b/drivers/crypto/marvell/octeontx2/otx2_cptlf.c
index b52728e3c0d1..b5d66afcc030 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptlf.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptlf.c
@@ -288,8 +288,7 @@ void otx2_cptlf_unregister_misc_interrupts(struct otx2_cptlfs_info *lfs)
cptlf_set_misc_intrs(lfs, false);
}
-EXPORT_SYMBOL_NS_GPL(otx2_cptlf_unregister_misc_interrupts,
- CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cptlf_unregister_misc_interrupts, "CRYPTO_DEV_OCTEONTX2_CPT");
void otx2_cptlf_unregister_done_interrupts(struct otx2_cptlfs_info *lfs)
{
@@ -308,8 +307,7 @@ void otx2_cptlf_unregister_done_interrupts(struct otx2_cptlfs_info *lfs)
cptlf_set_done_intrs(lfs, false);
}
-EXPORT_SYMBOL_NS_GPL(otx2_cptlf_unregister_done_interrupts,
- CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cptlf_unregister_done_interrupts, "CRYPTO_DEV_OCTEONTX2_CPT");
static int cptlf_do_register_interrrupts(struct otx2_cptlfs_info *lfs,
int lf_num, int irq_offset,
@@ -351,8 +349,7 @@ free_irq:
otx2_cptlf_unregister_misc_interrupts(lfs);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(otx2_cptlf_register_misc_interrupts,
- CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cptlf_register_misc_interrupts, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cptlf_register_done_interrupts(struct otx2_cptlfs_info *lfs)
{
@@ -375,8 +372,7 @@ free_irq:
otx2_cptlf_unregister_done_interrupts(lfs);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(otx2_cptlf_register_done_interrupts,
- CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cptlf_register_done_interrupts, "CRYPTO_DEV_OCTEONTX2_CPT");
void otx2_cptlf_free_irqs_affinity(struct otx2_cptlfs_info *lfs)
{
@@ -390,7 +386,7 @@ void otx2_cptlf_free_irqs_affinity(struct otx2_cptlfs_info *lfs)
free_cpumask_var(lfs->lf[slot].affinity_mask);
}
}
-EXPORT_SYMBOL_NS_GPL(otx2_cptlf_free_irqs_affinity, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cptlf_free_irqs_affinity, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cptlf_set_irqs_affinity(struct otx2_cptlfs_info *lfs)
{
@@ -423,7 +419,7 @@ free_affinity_mask:
otx2_cptlf_free_irqs_affinity(lfs);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(otx2_cptlf_set_irqs_affinity, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cptlf_set_irqs_affinity, "CRYPTO_DEV_OCTEONTX2_CPT");
int otx2_cptlf_init(struct otx2_cptlfs_info *lfs, u8 eng_grp_mask, int pri,
int lfs_num)
@@ -486,7 +482,7 @@ clear_lfs_num:
lfs->lfs_num = 0;
return ret;
}
-EXPORT_SYMBOL_NS_GPL(otx2_cptlf_init, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cptlf_init, "CRYPTO_DEV_OCTEONTX2_CPT");
void otx2_cptlf_shutdown(struct otx2_cptlfs_info *lfs)
{
@@ -498,7 +494,7 @@ void otx2_cptlf_shutdown(struct otx2_cptlfs_info *lfs)
otx2_cpt_detach_rsrcs_msg(lfs);
lfs->lfs_num = 0;
}
-EXPORT_SYMBOL_NS_GPL(otx2_cptlf_shutdown, CRYPTO_DEV_OCTEONTX2_CPT);
+EXPORT_SYMBOL_NS_GPL(otx2_cptlf_shutdown, "CRYPTO_DEV_OCTEONTX2_CPT");
MODULE_AUTHOR("Marvell");
MODULE_DESCRIPTION("Marvell RVU CPT Common module");
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
index 94d0e73e42de..12971300296d 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptpf_main.c
@@ -868,7 +868,7 @@ static struct pci_driver otx2_cpt_pci_driver = {
module_pci_driver(otx2_cpt_pci_driver);
-MODULE_IMPORT_NS(CRYPTO_DEV_OCTEONTX2_CPT);
+MODULE_IMPORT_NS("CRYPTO_DEV_OCTEONTX2_CPT");
MODULE_AUTHOR("Marvell");
MODULE_DESCRIPTION(OTX2_CPT_DRV_STRING);
diff --git a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
index d0b6ee901f62..d84eebdf2fa8 100644
--- a/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
+++ b/drivers/crypto/marvell/octeontx2/otx2_cptvf_main.c
@@ -453,7 +453,7 @@ static struct pci_driver otx2_cptvf_pci_driver = {
module_pci_driver(otx2_cptvf_pci_driver);
-MODULE_IMPORT_NS(CRYPTO_DEV_OCTEONTX2_CPT);
+MODULE_IMPORT_NS("CRYPTO_DEV_OCTEONTX2_CPT");
MODULE_AUTHOR("Marvell");
MODULE_DESCRIPTION("Marvell RVU CPT Virtual Function Driver");
diff --git a/drivers/cxl/acpi.c b/drivers/cxl/acpi.c
index 432b7cfd12a8..cb14829bb9be 100644
--- a/drivers/cxl/acpi.c
+++ b/drivers/cxl/acpi.c
@@ -934,5 +934,5 @@ MODULE_SOFTDEP("pre: cxl_port");
module_exit(cxl_acpi_exit);
MODULE_DESCRIPTION("CXL ACPI: Platform Support");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(CXL);
-MODULE_IMPORT_NS(ACPI);
+MODULE_IMPORT_NS("CXL");
+MODULE_IMPORT_NS("ACPI");
diff --git a/drivers/cxl/core/cdat.c b/drivers/cxl/core/cdat.c
index 2a1f164db98e..8153f8d83a16 100644
--- a/drivers/cxl/core/cdat.c
+++ b/drivers/cxl/core/cdat.c
@@ -416,7 +416,7 @@ void cxl_endpoint_parse_cdat(struct cxl_port *port)
cxl_qos_class_verify(cxlmd);
cxl_memdev_update_perf(cxlmd);
}
-EXPORT_SYMBOL_NS_GPL(cxl_endpoint_parse_cdat, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_endpoint_parse_cdat, "CXL");
static int cdat_sslbis_handler(union acpi_subtable_headers *header, void *arg,
const unsigned long end)
@@ -513,7 +513,7 @@ void cxl_switch_parse_cdat(struct cxl_port *port)
if (rc)
dev_dbg(&port->dev, "Failed to parse SSLBIS: %d\n", rc);
}
-EXPORT_SYMBOL_NS_GPL(cxl_switch_parse_cdat, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_switch_parse_cdat, "CXL");
static void __cxl_coordinates_combine(struct access_coordinate *out,
struct access_coordinate *c1,
@@ -545,7 +545,7 @@ void cxl_coordinates_combine(struct access_coordinate *out,
__cxl_coordinates_combine(&out[i], &c1[i], &c2[i]);
}
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("CXL");
static void cxl_bandwidth_add(struct access_coordinate *coord,
struct access_coordinate *c1,
diff --git a/drivers/cxl/core/hdm.c b/drivers/cxl/core/hdm.c
index ff0c96ade241..28edd5822486 100644
--- a/drivers/cxl/core/hdm.c
+++ b/drivers/cxl/core/hdm.c
@@ -73,7 +73,7 @@ int devm_cxl_add_passthrough_decoder(struct cxl_port *port)
return add_hdm_decoder(port, &cxlsd->cxld, single_port_map);
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_passthrough_decoder, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_passthrough_decoder, "CXL");
static void parse_hdm_decoder_caps(struct cxl_hdm *cxlhdm)
{
@@ -199,7 +199,7 @@ struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
return cxlhdm;
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_hdm, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_hdm, "CXL");
static void __cxl_dpa_debug(struct seq_file *file, struct resource *r, int depth)
{
@@ -221,7 +221,7 @@ void cxl_dpa_debug(struct seq_file *file, struct cxl_dev_state *cxlds)
}
up_read(&cxl_dpa_rwsem);
}
-EXPORT_SYMBOL_NS_GPL(cxl_dpa_debug, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_dpa_debug, "CXL");
/*
* Must be called in a context that synchronizes against this decoder's
@@ -358,7 +358,7 @@ int devm_cxl_dpa_reserve(struct cxl_endpoint_decoder *cxled,
return devm_add_action_or_reset(&port->dev, cxl_dpa_release, cxled);
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_dpa_reserve, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_dpa_reserve, "CXL");
resource_size_t cxl_dpa_size(struct cxl_endpoint_decoder *cxled)
{
@@ -738,7 +738,7 @@ void cxl_port_commit_reap(struct cxl_decoder *cxld)
device_for_each_child_reverse_from(&port->dev, &cxld->dev, NULL,
commit_reap);
}
-EXPORT_SYMBOL_NS_GPL(cxl_port_commit_reap, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_port_commit_reap, "CXL");
static void cxl_decoder_reset(struct cxl_decoder *cxld)
{
@@ -1064,4 +1064,4 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_decoders, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_decoders, "CXL");
diff --git a/drivers/cxl/core/mbox.c b/drivers/cxl/core/mbox.c
index 5175138c4fb7..548564c770c0 100644
--- a/drivers/cxl/core/mbox.c
+++ b/drivers/cxl/core/mbox.c
@@ -281,7 +281,7 @@ int cxl_internal_send_cmd(struct cxl_mailbox *cxl_mbox,
return -EIO;
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_internal_send_cmd, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_internal_send_cmd, "CXL");
static bool cxl_mem_raw_command_allowed(u16 opcode)
{
@@ -854,7 +854,7 @@ out:
kvfree(gsl);
return rc;
}
-EXPORT_SYMBOL_NS_GPL(cxl_enumerate_cmds, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_enumerate_cmds, "CXL");
void cxl_event_trace_record(const struct cxl_memdev *cxlmd,
enum cxl_event_log_type type,
@@ -894,7 +894,7 @@ void cxl_event_trace_record(const struct cxl_memdev *cxlmd,
trace_cxl_dram(cxlmd, type, cxlr, hpa, &evt->dram);
}
}
-EXPORT_SYMBOL_NS_GPL(cxl_event_trace_record, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_event_trace_record, "CXL");
static void __cxl_event_trace_record(const struct cxl_memdev *cxlmd,
enum cxl_event_log_type type,
@@ -1063,7 +1063,7 @@ void cxl_mem_get_event_records(struct cxl_memdev_state *mds, u32 status)
if (status & CXLDEV_EVENT_STATUS_INFO)
cxl_mem_get_records_log(mds, CXL_EVENT_TYPE_INFO);
}
-EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_mem_get_event_records, "CXL");
/**
* cxl_mem_get_partition_info - Get partition info
@@ -1155,7 +1155,7 @@ int cxl_dev_state_identify(struct cxl_memdev_state *mds)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_dev_state_identify, "CXL");
static int __cxl_mem_sanitize(struct cxl_memdev_state *mds, u16 cmd)
{
@@ -1306,7 +1306,7 @@ int cxl_mem_create_range_info(struct cxl_memdev_state *mds)
mds->active_volatile_bytes,
mds->active_persistent_bytes, "pmem");
}
-EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_mem_create_range_info, "CXL");
int cxl_set_timestamp(struct cxl_memdev_state *mds)
{
@@ -1333,7 +1333,7 @@ int cxl_set_timestamp(struct cxl_memdev_state *mds)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_set_timestamp, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_set_timestamp, "CXL");
int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
struct cxl_region *cxlr)
@@ -1384,7 +1384,7 @@ int cxl_mem_get_poison(struct cxl_memdev *cxlmd, u64 offset, u64 len,
mutex_unlock(&mds->poison.lock);
return rc;
}
-EXPORT_SYMBOL_NS_GPL(cxl_mem_get_poison, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_mem_get_poison, "CXL");
static void free_poison_buf(void *buf)
{
@@ -1420,7 +1420,7 @@ int cxl_poison_state_init(struct cxl_memdev_state *mds)
mutex_init(&mds->poison.lock);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_poison_state_init, "CXL");
int cxl_mailbox_init(struct cxl_mailbox *cxl_mbox, struct device *host)
{
@@ -1433,7 +1433,7 @@ int cxl_mailbox_init(struct cxl_mailbox *cxl_mbox, struct device *host)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_mailbox_init, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_mailbox_init, "CXL");
struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
{
@@ -1455,7 +1455,7 @@ struct cxl_memdev_state *cxl_memdev_state_create(struct device *dev)
return mds;
}
-EXPORT_SYMBOL_NS_GPL(cxl_memdev_state_create, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_memdev_state_create, "CXL");
void __init cxl_mbox_init(void)
{
diff --git a/drivers/cxl/core/memdev.c b/drivers/cxl/core/memdev.c
index 84fefb76dafa..ae3dfcbe8938 100644
--- a/drivers/cxl/core/memdev.c
+++ b/drivers/cxl/core/memdev.c
@@ -250,7 +250,7 @@ int cxl_trigger_poison_list(struct cxl_memdev *cxlmd)
return rc;
}
-EXPORT_SYMBOL_NS_GPL(cxl_trigger_poison_list, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_trigger_poison_list, "CXL");
static int cxl_validate_poison_dpa(struct cxl_memdev *cxlmd, u64 dpa)
{
@@ -329,7 +329,7 @@ out:
return rc;
}
-EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_inject_poison, "CXL");
int cxl_clear_poison(struct cxl_memdev *cxlmd, u64 dpa)
{
@@ -393,7 +393,7 @@ out:
return rc;
}
-EXPORT_SYMBOL_NS_GPL(cxl_clear_poison, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_clear_poison, "CXL");
static struct attribute *cxl_memdev_attributes[] = {
&dev_attr_serial.attr,
@@ -537,7 +537,7 @@ void cxl_memdev_update_perf(struct cxl_memdev *cxlmd)
sysfs_update_group(&cxlmd->dev.kobj, &cxl_memdev_ram_attribute_group);
sysfs_update_group(&cxlmd->dev.kobj, &cxl_memdev_pmem_attribute_group);
}
-EXPORT_SYMBOL_NS_GPL(cxl_memdev_update_perf, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_memdev_update_perf, "CXL");
static const struct device_type cxl_memdev_type = {
.name = "cxl_memdev",
@@ -550,7 +550,7 @@ bool is_cxl_memdev(const struct device *dev)
{
return dev->type == &cxl_memdev_type;
}
-EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, CXL);
+EXPORT_SYMBOL_NS_GPL(is_cxl_memdev, "CXL");
/**
* set_exclusive_cxl_commands() - atomically disable user cxl commands
@@ -569,7 +569,7 @@ void set_exclusive_cxl_commands(struct cxl_memdev_state *mds,
CXL_MEM_COMMAND_ID_MAX);
up_write(&cxl_memdev_rwsem);
}
-EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, CXL);
+EXPORT_SYMBOL_NS_GPL(set_exclusive_cxl_commands, "CXL");
/**
* clear_exclusive_cxl_commands() - atomically enable user cxl commands
@@ -584,7 +584,7 @@ void clear_exclusive_cxl_commands(struct cxl_memdev_state *mds,
CXL_MEM_COMMAND_ID_MAX);
up_write(&cxl_memdev_rwsem);
}
-EXPORT_SYMBOL_NS_GPL(clear_exclusive_cxl_commands, CXL);
+EXPORT_SYMBOL_NS_GPL(clear_exclusive_cxl_commands, "CXL");
static void cxl_memdev_shutdown(struct device *dev)
{
@@ -1006,7 +1006,7 @@ int devm_cxl_setup_fw_upload(struct device *host, struct cxl_memdev_state *mds)
return PTR_ERR(fwl);
return devm_add_action_or_reset(host, cxl_remove_fw_upload, fwl);
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_fw_upload, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_setup_fw_upload, "CXL");
static const struct file_operations cxl_memdev_fops = {
.owner = THIS_MODULE,
@@ -1060,7 +1060,7 @@ err:
put_device(dev);
return ERR_PTR(rc);
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_memdev, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_memdev, "CXL");
static void sanitize_teardown_notifier(void *data)
{
@@ -1105,7 +1105,7 @@ int devm_cxl_sanitize_setup_notifier(struct device *host,
return devm_add_action_or_reset(host, sanitize_teardown_notifier, mds);
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_sanitize_setup_notifier, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_sanitize_setup_notifier, "CXL");
__init int cxl_memdev_init(void)
{
diff --git a/drivers/cxl/core/pci.c b/drivers/cxl/core/pci.c
index 5b46bc46aaa9..9d58ab9d33c5 100644
--- a/drivers/cxl/core/pci.c
+++ b/drivers/cxl/core/pci.c
@@ -101,7 +101,7 @@ int devm_cxl_port_enumerate_dports(struct cxl_port *port)
return ctx.error;
return ctx.count;
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_port_enumerate_dports, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_port_enumerate_dports, "CXL");
static int cxl_dvsec_mem_range_valid(struct cxl_dev_state *cxlds, int id)
{
@@ -209,7 +209,7 @@ int cxl_await_media_ready(struct cxl_dev_state *cxlds)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_await_media_ready, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_await_media_ready, "CXL");
static int cxl_set_mem_enable(struct cxl_dev_state *cxlds, u16 val)
{
@@ -386,7 +386,7 @@ int cxl_dvsec_rr_decode(struct device *dev, struct cxl_port *port,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_dvsec_rr_decode, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_dvsec_rr_decode, "CXL");
/**
* cxl_hdm_decode_init() - Setup HDM decoding for the endpoint
@@ -464,7 +464,7 @@ int cxl_hdm_decode_init(struct cxl_dev_state *cxlds, struct cxl_hdm *cxlhdm,
*/
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_hdm_decode_init, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_hdm_decode_init, "CXL");
#define CXL_DOE_TABLE_ACCESS_REQ_CODE 0x000000ff
#define CXL_DOE_TABLE_ACCESS_REQ_CODE_READ 0
@@ -648,7 +648,7 @@ err:
devm_kfree(dev, buf);
dev_err(dev, "Failed to read/validate CDAT.\n");
}
-EXPORT_SYMBOL_NS_GPL(read_cdat_data, CXL);
+EXPORT_SYMBOL_NS_GPL(read_cdat_data, "CXL");
static void __cxl_handle_cor_ras(struct cxl_dev_state *cxlds,
void __iomem *ras_base)
@@ -805,7 +805,7 @@ void cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
cxl_disable_rch_root_ints(dport);
}
}
-EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_dport_init_ras_reporting, "CXL");
static void cxl_handle_rdport_cor_ras(struct cxl_dev_state *cxlds,
struct cxl_dport *dport)
@@ -916,7 +916,7 @@ void cxl_cor_error_detected(struct pci_dev *pdev)
cxl_handle_endpoint_cor_ras(cxlds);
}
}
-EXPORT_SYMBOL_NS_GPL(cxl_cor_error_detected, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_cor_error_detected, "CXL");
pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
pci_channel_state_t state)
@@ -966,7 +966,7 @@ pci_ers_result_t cxl_error_detected(struct pci_dev *pdev,
}
return PCI_ERS_RESULT_NEED_RESET;
}
-EXPORT_SYMBOL_NS_GPL(cxl_error_detected, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_error_detected, "CXL");
static int cxl_flit_size(struct pci_dev *pdev)
{
@@ -1030,7 +1030,7 @@ bool cxl_endpoint_decoder_reset_detected(struct cxl_port *port)
return device_for_each_child(&port->dev, port,
__cxl_endpoint_decoder_reset_detected);
}
-EXPORT_SYMBOL_NS_GPL(cxl_endpoint_decoder_reset_detected, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_endpoint_decoder_reset_detected, "CXL");
int cxl_pci_get_bandwidth(struct pci_dev *pdev, struct access_coordinate *c)
{
diff --git a/drivers/cxl/core/pmem.c b/drivers/cxl/core/pmem.c
index c00f3a933164..b3378d3f6acb 100644
--- a/drivers/cxl/core/pmem.c
+++ b/drivers/cxl/core/pmem.c
@@ -49,13 +49,13 @@ struct cxl_nvdimm_bridge *to_cxl_nvdimm_bridge(struct device *dev)
return NULL;
return container_of(dev, struct cxl_nvdimm_bridge, dev);
}
-EXPORT_SYMBOL_NS_GPL(to_cxl_nvdimm_bridge, CXL);
+EXPORT_SYMBOL_NS_GPL(to_cxl_nvdimm_bridge, "CXL");
bool is_cxl_nvdimm_bridge(struct device *dev)
{
return dev->type == &cxl_nvdimm_bridge_type;
}
-EXPORT_SYMBOL_NS_GPL(is_cxl_nvdimm_bridge, CXL);
+EXPORT_SYMBOL_NS_GPL(is_cxl_nvdimm_bridge, "CXL");
static int match_nvdimm_bridge(struct device *dev, void *data)
{
@@ -82,7 +82,7 @@ struct cxl_nvdimm_bridge *cxl_find_nvdimm_bridge(struct cxl_port *port)
return to_cxl_nvdimm_bridge(dev);
}
-EXPORT_SYMBOL_NS_GPL(cxl_find_nvdimm_bridge, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_find_nvdimm_bridge, "CXL");
static struct lock_class_key cxl_nvdimm_bridge_key;
@@ -164,7 +164,7 @@ err:
put_device(dev);
return ERR_PTR(rc);
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_nvdimm_bridge, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_nvdimm_bridge, "CXL");
static void cxl_nvdimm_release(struct device *dev)
{
@@ -188,7 +188,7 @@ bool is_cxl_nvdimm(struct device *dev)
{
return dev->type == &cxl_nvdimm_type;
}
-EXPORT_SYMBOL_NS_GPL(is_cxl_nvdimm, CXL);
+EXPORT_SYMBOL_NS_GPL(is_cxl_nvdimm, "CXL");
struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev)
{
@@ -197,7 +197,7 @@ struct cxl_nvdimm *to_cxl_nvdimm(struct device *dev)
return NULL;
return container_of(dev, struct cxl_nvdimm, dev);
}
-EXPORT_SYMBOL_NS_GPL(to_cxl_nvdimm, CXL);
+EXPORT_SYMBOL_NS_GPL(to_cxl_nvdimm, "CXL");
static struct lock_class_key cxl_nvdimm_key;
@@ -293,4 +293,4 @@ err_alloc:
return rc;
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_nvdimm, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_nvdimm, "CXL");
diff --git a/drivers/cxl/core/pmu.c b/drivers/cxl/core/pmu.c
index 5d8e06b0ba6e..b3136d7664ab 100644
--- a/drivers/cxl/core/pmu.c
+++ b/drivers/cxl/core/pmu.c
@@ -65,4 +65,4 @@ err:
put_device(&pmu->dev);
return rc;
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_pmu_add, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_pmu_add, "CXL");
diff --git a/drivers/cxl/core/port.c b/drivers/cxl/core/port.c
index af92c67bc954..78a5c2c25982 100644
--- a/drivers/cxl/core/port.c
+++ b/drivers/cxl/core/port.c
@@ -437,7 +437,7 @@ struct cxl_root_decoder *to_cxl_root_decoder(struct device *dev)
return NULL;
return container_of(dev, struct cxl_root_decoder, cxlsd.cxld.dev);
}
-EXPORT_SYMBOL_NS_GPL(to_cxl_root_decoder, CXL);
+EXPORT_SYMBOL_NS_GPL(to_cxl_root_decoder, "CXL");
static void cxl_root_decoder_release(struct device *dev)
{
@@ -471,19 +471,19 @@ bool is_endpoint_decoder(struct device *dev)
{
return dev->type == &cxl_decoder_endpoint_type;
}
-EXPORT_SYMBOL_NS_GPL(is_endpoint_decoder, CXL);
+EXPORT_SYMBOL_NS_GPL(is_endpoint_decoder, "CXL");
bool is_root_decoder(struct device *dev)
{
return dev->type == &cxl_decoder_root_type;
}
-EXPORT_SYMBOL_NS_GPL(is_root_decoder, CXL);
+EXPORT_SYMBOL_NS_GPL(is_root_decoder, "CXL");
bool is_switch_decoder(struct device *dev)
{
return is_root_decoder(dev) || dev->type == &cxl_decoder_switch_type;
}
-EXPORT_SYMBOL_NS_GPL(is_switch_decoder, CXL);
+EXPORT_SYMBOL_NS_GPL(is_switch_decoder, "CXL");
struct cxl_decoder *to_cxl_decoder(struct device *dev)
{
@@ -493,7 +493,7 @@ struct cxl_decoder *to_cxl_decoder(struct device *dev)
return NULL;
return container_of(dev, struct cxl_decoder, dev);
}
-EXPORT_SYMBOL_NS_GPL(to_cxl_decoder, CXL);
+EXPORT_SYMBOL_NS_GPL(to_cxl_decoder, "CXL");
struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev)
{
@@ -502,7 +502,7 @@ struct cxl_endpoint_decoder *to_cxl_endpoint_decoder(struct device *dev)
return NULL;
return container_of(dev, struct cxl_endpoint_decoder, cxld.dev);
}
-EXPORT_SYMBOL_NS_GPL(to_cxl_endpoint_decoder, CXL);
+EXPORT_SYMBOL_NS_GPL(to_cxl_endpoint_decoder, "CXL");
struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev)
{
@@ -511,7 +511,7 @@ struct cxl_switch_decoder *to_cxl_switch_decoder(struct device *dev)
return NULL;
return container_of(dev, struct cxl_switch_decoder, cxld.dev);
}
-EXPORT_SYMBOL_NS_GPL(to_cxl_switch_decoder, CXL);
+EXPORT_SYMBOL_NS_GPL(to_cxl_switch_decoder, "CXL");
static void cxl_ep_release(struct cxl_ep *ep)
{
@@ -585,7 +585,7 @@ bool is_cxl_port(const struct device *dev)
{
return dev->type == &cxl_port_type;
}
-EXPORT_SYMBOL_NS_GPL(is_cxl_port, CXL);
+EXPORT_SYMBOL_NS_GPL(is_cxl_port, "CXL");
struct cxl_port *to_cxl_port(const struct device *dev)
{
@@ -594,7 +594,7 @@ struct cxl_port *to_cxl_port(const struct device *dev)
return NULL;
return container_of(dev, struct cxl_port, dev);
}
-EXPORT_SYMBOL_NS_GPL(to_cxl_port, CXL);
+EXPORT_SYMBOL_NS_GPL(to_cxl_port, "CXL");
static void unregister_port(void *_port)
{
@@ -942,7 +942,7 @@ struct cxl_port *devm_cxl_add_port(struct device *host,
return port;
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_port, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_port, "CXL");
struct cxl_root *devm_cxl_add_root(struct device *host,
const struct cxl_root_ops *ops)
@@ -958,7 +958,7 @@ struct cxl_root *devm_cxl_add_root(struct device *host,
cxl_root->ops = ops;
return cxl_root;
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_root, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_root, "CXL");
struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port)
{
@@ -974,7 +974,7 @@ struct pci_bus *cxl_port_to_pci_bus(struct cxl_port *port)
return xa_load(&cxl_root_buses, (unsigned long)port->uport_dev);
}
-EXPORT_SYMBOL_NS_GPL(cxl_port_to_pci_bus, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_port_to_pci_bus, "CXL");
static void unregister_pci_bus(void *uport_dev)
{
@@ -995,7 +995,7 @@ int devm_cxl_register_pci_bus(struct device *host, struct device *uport_dev,
return rc;
return devm_add_action_or_reset(host, unregister_pci_bus, uport_dev);
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_register_pci_bus, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_register_pci_bus, "CXL");
static bool dev_is_cxl_root_child(struct device *dev)
{
@@ -1027,7 +1027,7 @@ struct cxl_root *find_cxl_root(struct cxl_port *port)
get_device(&iter->dev);
return to_cxl_root(iter);
}
-EXPORT_SYMBOL_NS_GPL(find_cxl_root, CXL);
+EXPORT_SYMBOL_NS_GPL(find_cxl_root, "CXL");
void put_cxl_root(struct cxl_root *cxl_root)
{
@@ -1036,7 +1036,7 @@ void put_cxl_root(struct cxl_root *cxl_root)
put_device(&cxl_root->port.dev);
}
-EXPORT_SYMBOL_NS_GPL(put_cxl_root, CXL);
+EXPORT_SYMBOL_NS_GPL(put_cxl_root, "CXL");
static struct cxl_dport *find_dport(struct cxl_port *port, int id)
{
@@ -1230,7 +1230,7 @@ struct cxl_dport *devm_cxl_add_dport(struct cxl_port *port,
return dport;
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_dport, "CXL");
/**
* devm_cxl_add_rch_dport - append RCH downstream port data to a cxl_port
@@ -1264,7 +1264,7 @@ struct cxl_dport *devm_cxl_add_rch_dport(struct cxl_port *port,
return dport;
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_add_rch_dport, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_add_rch_dport, "CXL");
static int add_ep(struct cxl_ep *new)
{
@@ -1421,7 +1421,7 @@ int cxl_endpoint_autoremove(struct cxl_memdev *cxlmd, struct cxl_port *endpoint)
cxlmd->depth = endpoint->depth;
return devm_add_action_or_reset(dev, delete_endpoint, cxlmd);
}
-EXPORT_SYMBOL_NS_GPL(cxl_endpoint_autoremove, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_endpoint_autoremove, "CXL");
/*
* The natural end of life of a non-root 'cxl_port' is when its parent port goes
@@ -1692,21 +1692,21 @@ retry:
return 0;
}
-EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_ports, CXL);
+EXPORT_SYMBOL_NS_GPL(devm_cxl_enumerate_ports, "CXL");
struct cxl_port *cxl_pci_find_port(struct pci_dev *pdev,
struct cxl_dport **dport)
{
return find_cxl_port(pdev->dev.parent, dport);
}
-EXPORT_SYMBOL_NS_GPL(cxl_pci_find_port, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_pci_find_port, "CXL");
struct cxl_port *cxl_mem_find_port(struct cxl_memdev *cxlmd,
struct cxl_dport **dport)
{
return find_cxl_port(grandparent(&cxlmd->dev), dport);
}
-EXPORT_SYMBOL_NS_GPL(cxl_mem_find_port, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_mem_find_port, "CXL");
static int decoder_populate_targets(struct cxl_switch_decoder *cxlsd,
struct cxl_port *port, int *target_map)
@@ -1840,7 +1840,7 @@ struct cxl_root_decoder *cxl_root_decoder_alloc(struct cxl_port *port,
cxlrd->qos_class = CXL_QOS_CLASS_INVALID;
return cxlrd;
}
-EXPORT_SYMBOL_NS_GPL(cxl_root_decoder_alloc, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_root_decoder_alloc, "CXL");
/**
* cxl_switch_decoder_alloc - Allocate a switch level decoder
@@ -1877,7 +1877,7 @@ struct cxl_switch_decoder *cxl_switch_decoder_alloc(struct cxl_port *port,
cxld->dev.type = &cxl_decoder_switch_type;
return cxlsd;
}
-EXPORT_SYMBOL_NS_GPL(cxl_switch_decoder_alloc, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_switch_decoder_alloc, "CXL");
/**
* cxl_endpoint_decoder_alloc - Allocate an endpoint decoder
@@ -1909,7 +1909,7 @@ struct cxl_endpoint_decoder *cxl_endpoint_decoder_alloc(struct cxl_port *port)
cxld->dev.type = &cxl_decoder_endpoint_type;
return cxled;
}
-EXPORT_SYMBOL_NS_GPL(cxl_endpoint_decoder_alloc, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_endpoint_decoder_alloc, "CXL");
/**
* cxl_decoder_add_locked - Add a decoder with targets
@@ -1965,7 +1965,7 @@ int cxl_decoder_add_locked(struct cxl_decoder *cxld, int *target_map)
return device_add(dev);
}
-EXPORT_SYMBOL_NS_GPL(cxl_decoder_add_locked, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_decoder_add_locked, "CXL");
/**
* cxl_decoder_add - Add a decoder with targets
@@ -1995,7 +1995,7 @@ int cxl_decoder_add(struct cxl_decoder *cxld, int *target_map)
guard(device)(&port->dev);
return cxl_decoder_add_locked(cxld, target_map);
}
-EXPORT_SYMBOL_NS_GPL(cxl_decoder_add, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_decoder_add, "CXL");
static void cxld_unregister(void *dev)
{
@@ -2013,7 +2013,7 @@ int cxl_decoder_autoremove(struct device *host, struct cxl_decoder *cxld)
{
return devm_add_action_or_reset(host, cxld_unregister, &cxld->dev);
}
-EXPORT_SYMBOL_NS_GPL(cxl_decoder_autoremove, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_decoder_autoremove, "CXL");
/**
* __cxl_driver_register - register a driver for the cxl bus
@@ -2046,13 +2046,13 @@ int __cxl_driver_register(struct cxl_driver *cxl_drv, struct module *owner,
return driver_register(&cxl_drv->drv);
}
-EXPORT_SYMBOL_NS_GPL(__cxl_driver_register, CXL);
+EXPORT_SYMBOL_NS_GPL(__cxl_driver_register, "CXL");
void cxl_driver_unregister(struct cxl_driver *cxl_drv)
{
driver_unregister(&cxl_drv->drv);
}
-EXPORT_SYMBOL_NS_GPL(cxl_driver_unregister, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_driver_unregister, "CXL");
static int cxl_bus_uevent(const struct device *dev, struct kobj_uevent_env *env)
{
@@ -2104,19 +2104,19 @@ void cxl_bus_rescan(void)
queue_work(cxl_bus_wq, &rescan_work);
}
-EXPORT_SYMBOL_NS_GPL(cxl_bus_rescan, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_bus_rescan, "CXL");
void cxl_bus_drain(void)
{
drain_workqueue(cxl_bus_wq);
}
-EXPORT_SYMBOL_NS_GPL(cxl_bus_drain, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_bus_drain, "CXL");
bool schedule_cxl_memdev_detach(struct cxl_memdev *cxlmd)
{
return queue_work(cxl_bus_wq, &cxlmd->detach_work);
}
-EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, CXL);
+EXPORT_SYMBOL_NS_GPL(schedule_cxl_memdev_detach, "CXL");
static void add_latency(struct access_coordinate *c, long latency)
{
@@ -2242,7 +2242,7 @@ int cxl_endpoint_get_perf_coordinates(struct cxl_port *port,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_endpoint_get_perf_coordinates, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_endpoint_get_perf_coordinates, "CXL");
int cxl_port_get_switch_dport_bandwidth(struct cxl_port *port,
struct access_coordinate *c)
@@ -2299,7 +2299,7 @@ struct bus_type cxl_bus_type = {
.remove = cxl_bus_remove,
.bus_groups = cxl_bus_attribute_groups,
};
-EXPORT_SYMBOL_NS_GPL(cxl_bus_type, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_bus_type, "CXL");
static struct dentry *cxl_debugfs;
@@ -2307,7 +2307,7 @@ struct dentry *cxl_debugfs_create_dir(const char *dir)
{
return debugfs_create_dir(dir, cxl_debugfs);
}
-EXPORT_SYMBOL_NS_GPL(cxl_debugfs_create_dir, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_debugfs_create_dir, "CXL");
static __init int cxl_core_init(void)
{
@@ -2363,4 +2363,4 @@ subsys_initcall(cxl_core_init);
module_exit(cxl_core_exit);
MODULE_DESCRIPTION("CXL: Core Compute Express Link support");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("CXL");
diff --git a/drivers/cxl/core/region.c b/drivers/cxl/core/region.c
index 70d0a017e99c..b98b1ccffd1c 100644
--- a/drivers/cxl/core/region.c
+++ b/drivers/cxl/core/region.c
@@ -1295,6 +1295,7 @@ static int cxl_port_setup_targets(struct cxl_port *port,
struct cxl_region_params *p = &cxlr->params;
struct cxl_decoder *cxld = cxl_rr->decoder;
struct cxl_switch_decoder *cxlsd;
+ struct cxl_port *iter = port;
u16 eig, peig;
u8 eiw, peiw;
@@ -1311,16 +1312,26 @@ static int cxl_port_setup_targets(struct cxl_port *port,
cxlsd = to_cxl_switch_decoder(&cxld->dev);
if (cxl_rr->nr_targets_set) {
- int i, distance;
+ int i, distance = 1;
+ struct cxl_region_ref *cxl_rr_iter;
/*
- * Passthrough decoders impose no distance requirements between
- * peers
+ * The "distance" between peer downstream ports represents which
+ * endpoint positions in the region interleave a given port can
+ * host.
+ *
+ * For example, at the root of a hierarchy the distance is
+ * always 1 as every index targets a different host-bridge. At
+ * each subsequent switch level those ports map every Nth region
+ * position where N is the width of the switch == distance.
*/
- if (cxl_rr->nr_targets == 1)
- distance = 0;
- else
- distance = p->nr_targets / cxl_rr->nr_targets;
+ do {
+ cxl_rr_iter = cxl_rr_load(iter, cxlr);
+ distance *= cxl_rr_iter->nr_targets;
+ iter = to_cxl_port(iter->dev.parent);
+ } while (!is_cxl_root(iter));
+ distance *= cxlrd->cxlsd.cxld.interleave_ways;
+
for (i = 0; i < cxl_rr->nr_targets_set; i++)
if (ep->dport == cxlsd->target[i]) {
rc = check_last_peer(cxled, ep, cxl_rr,
@@ -2299,7 +2310,7 @@ bool is_cxl_region(struct device *dev)
{
return dev->type == &cxl_region_type;
}
-EXPORT_SYMBOL_NS_GPL(is_cxl_region, CXL);
+EXPORT_SYMBOL_NS_GPL(is_cxl_region, "CXL");
static struct cxl_region *to_cxl_region(struct device *dev)
{
@@ -2652,7 +2663,7 @@ bool is_cxl_pmem_region(struct device *dev)
{
return dev->type == &cxl_pmem_region_type;
}
-EXPORT_SYMBOL_NS_GPL(is_cxl_pmem_region, CXL);
+EXPORT_SYMBOL_NS_GPL(is_cxl_pmem_region, "CXL");
struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev)
{
@@ -2661,7 +2672,7 @@ struct cxl_pmem_region *to_cxl_pmem_region(struct device *dev)
return NULL;
return container_of(dev, struct cxl_pmem_region, dev);
}
-EXPORT_SYMBOL_NS_GPL(to_cxl_pmem_region, CXL);
+EXPORT_SYMBOL_NS_GPL(to_cxl_pmem_region, "CXL");
struct cxl_poison_context {
struct cxl_port *port;
@@ -3015,7 +3026,7 @@ struct cxl_dax_region *to_cxl_dax_region(struct device *dev)
return NULL;
return container_of(dev, struct cxl_dax_region, dev);
}
-EXPORT_SYMBOL_NS_GPL(to_cxl_dax_region, CXL);
+EXPORT_SYMBOL_NS_GPL(to_cxl_dax_region, "CXL");
static struct lock_class_key cxl_dax_region_key;
@@ -3359,7 +3370,7 @@ out:
put_device(cxlrd_dev);
return rc;
}
-EXPORT_SYMBOL_NS_GPL(cxl_add_to_region, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_add_to_region, "CXL");
static int is_system_ram(struct resource *res, void *arg)
{
@@ -3462,6 +3473,6 @@ void cxl_region_exit(void)
cxl_driver_unregister(&cxl_region_driver);
}
-MODULE_IMPORT_NS(CXL);
-MODULE_IMPORT_NS(DEVMEM);
+MODULE_IMPORT_NS("CXL");
+MODULE_IMPORT_NS("DEVMEM");
MODULE_ALIAS_CXL(CXL_DEVICE_REGION);
diff --git a/drivers/cxl/core/regs.c b/drivers/cxl/core/regs.c
index 429973a2165b..59cb35b40c7e 100644
--- a/drivers/cxl/core/regs.c
+++ b/drivers/cxl/core/regs.c
@@ -106,7 +106,7 @@ void cxl_probe_component_regs(struct device *dev, void __iomem *base,
rmap->size = length;
}
}
-EXPORT_SYMBOL_NS_GPL(cxl_probe_component_regs, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_probe_component_regs, "CXL");
/**
* cxl_probe_device_regs() - Detect CXL Device register blocks
@@ -174,7 +174,7 @@ void cxl_probe_device_regs(struct device *dev, void __iomem *base,
rmap->size = length;
}
}
-EXPORT_SYMBOL_NS_GPL(cxl_probe_device_regs, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_probe_device_regs, "CXL");
void __iomem *devm_cxl_iomap_block(struct device *dev, resource_size_t addr,
resource_size_t length)
@@ -232,7 +232,7 @@ int cxl_map_component_regs(const struct cxl_register_map *map,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_map_component_regs, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_map_component_regs, "CXL");
int cxl_map_device_regs(const struct cxl_register_map *map,
struct cxl_device_regs *regs)
@@ -266,7 +266,7 @@ int cxl_map_device_regs(const struct cxl_register_map *map,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_map_device_regs, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_map_device_regs, "CXL");
static bool cxl_decode_regblock(struct pci_dev *pdev, u32 reg_lo, u32 reg_hi,
struct cxl_register_map *map)
@@ -344,7 +344,7 @@ int cxl_find_regblock_instance(struct pci_dev *pdev, enum cxl_regloc_type type,
map->resource = CXL_RESOURCE_NONE;
return -ENODEV;
}
-EXPORT_SYMBOL_NS_GPL(cxl_find_regblock_instance, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_find_regblock_instance, "CXL");
/**
* cxl_find_regblock() - Locate register blocks by type
@@ -362,7 +362,7 @@ int cxl_find_regblock(struct pci_dev *pdev, enum cxl_regloc_type type,
{
return cxl_find_regblock_instance(pdev, type, map, 0);
}
-EXPORT_SYMBOL_NS_GPL(cxl_find_regblock, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_find_regblock, "CXL");
/**
* cxl_count_regblock() - Count instances of a given regblock type.
@@ -385,7 +385,7 @@ int cxl_count_regblock(struct pci_dev *pdev, enum cxl_regloc_type type)
count++;
}
}
-EXPORT_SYMBOL_NS_GPL(cxl_count_regblock, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_count_regblock, "CXL");
int cxl_map_pmu_regs(struct cxl_register_map *map, struct cxl_pmu_regs *regs)
{
@@ -399,7 +399,7 @@ int cxl_map_pmu_regs(struct cxl_register_map *map, struct cxl_pmu_regs *regs)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_map_pmu_regs, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_map_pmu_regs, "CXL");
static int cxl_map_regblock(struct cxl_register_map *map)
{
@@ -468,7 +468,7 @@ int cxl_setup_regs(struct cxl_register_map *map)
return rc;
}
-EXPORT_SYMBOL_NS_GPL(cxl_setup_regs, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_setup_regs, "CXL");
u16 cxl_rcrb_to_aer(struct device *dev, resource_size_t rcrb)
{
@@ -560,7 +560,7 @@ int cxl_dport_map_rcd_linkcap(struct pci_dev *pdev, struct cxl_dport *dport)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cxl_dport_map_rcd_linkcap, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_dport_map_rcd_linkcap, "CXL");
resource_size_t __rcrb_to_component(struct device *dev, struct cxl_rcrb_info *ri,
enum cxl_rcrb which)
@@ -633,4 +633,4 @@ resource_size_t cxl_rcd_component_reg_phys(struct device *dev,
return CXL_RESOURCE_NONE;
return __rcrb_to_component(dev, &dport->rcrb, CXL_RCRB_UPSTREAM);
}
-EXPORT_SYMBOL_NS_GPL(cxl_rcd_component_reg_phys, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_rcd_component_reg_phys, "CXL");
diff --git a/drivers/cxl/core/suspend.c b/drivers/cxl/core/suspend.c
index a5984d96ea1d..29aa5cc5e565 100644
--- a/drivers/cxl/core/suspend.c
+++ b/drivers/cxl/core/suspend.c
@@ -15,10 +15,10 @@ void cxl_mem_active_inc(void)
{
atomic_inc(&mem_active);
}
-EXPORT_SYMBOL_NS_GPL(cxl_mem_active_inc, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_mem_active_inc, "CXL");
void cxl_mem_active_dec(void)
{
atomic_dec(&mem_active);
}
-EXPORT_SYMBOL_NS_GPL(cxl_mem_active_dec, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_mem_active_dec, "CXL");
diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c
index a9fd5cd5a0d2..2f03a4d5606e 100644
--- a/drivers/cxl/mem.c
+++ b/drivers/cxl/mem.c
@@ -252,7 +252,7 @@ module_cxl_driver(cxl_mem_driver);
MODULE_DESCRIPTION("CXL: Memory Expansion");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("CXL");
MODULE_ALIAS_CXL(CXL_DEVICE_MEMORY_EXPANDER);
/*
* create_endpoint() wants to validate port driver attach immediately after
diff --git a/drivers/cxl/pci.c b/drivers/cxl/pci.c
index b2cb81f6d9e7..6d94ff4a4f1a 100644
--- a/drivers/cxl/pci.c
+++ b/drivers/cxl/pci.c
@@ -836,6 +836,9 @@ static ssize_t rcd_pcie_cap_emit(struct device *dev, u16 offset, char *buf, size
if (!root_dev)
return -ENXIO;
+ if (!dport->regs.rcd_pcie_cap)
+ return -ENXIO;
+
guard(device)(root_dev);
if (!root_dev->driver)
return -ENXIO;
@@ -1032,8 +1035,7 @@ static int cxl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
return rc;
- rc = cxl_pci_ras_unmask(pdev);
- if (rc)
+ if (cxl_pci_ras_unmask(pdev))
dev_dbg(&pdev->dev, "No RAS reporting unmasked\n");
pci_save_state(pdev);
@@ -1184,4 +1186,4 @@ module_init(cxl_pci_driver_init);
module_exit(cxl_pci_driver_exit);
MODULE_DESCRIPTION("CXL: PCI manageability");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("CXL");
diff --git a/drivers/cxl/pmem.c b/drivers/cxl/pmem.c
index d2d43a4fc053..f9c95996e937 100644
--- a/drivers/cxl/pmem.c
+++ b/drivers/cxl/pmem.c
@@ -459,7 +459,7 @@ MODULE_DESCRIPTION("CXL PMEM: Persistent Memory Support");
MODULE_LICENSE("GPL v2");
module_init(cxl_pmem_init);
module_exit(cxl_pmem_exit);
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("CXL");
MODULE_ALIAS_CXL(CXL_DEVICE_NVDIMM_BRIDGE);
MODULE_ALIAS_CXL(CXL_DEVICE_NVDIMM);
MODULE_ALIAS_CXL(CXL_DEVICE_PMEM_REGION);
diff --git a/drivers/cxl/port.c b/drivers/cxl/port.c
index 9dc394295e1f..4c83f6a22e58 100644
--- a/drivers/cxl/port.c
+++ b/drivers/cxl/port.c
@@ -173,7 +173,7 @@ static ssize_t CDAT_read(struct file *filp, struct kobject *kobj,
static BIN_ATTR_ADMIN_RO(CDAT, 0);
static umode_t cxl_port_bin_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr, int i)
+ const struct bin_attribute *attr, int i)
{
struct device *dev = kobj_to_dev(kobj);
struct cxl_port *port = to_cxl_port(dev);
@@ -226,5 +226,5 @@ module_exit(cxl_port_exit);
MODULE_DESCRIPTION("CXL: Port enumeration and services");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("CXL");
MODULE_ALIAS_CXL(CXL_DEVICE_PORT);
diff --git a/drivers/dax/cxl.c b/drivers/dax/cxl.c
index 9b29e732b39a..13cd94d32ff7 100644
--- a/drivers/dax/cxl.c
+++ b/drivers/dax/cxl.c
@@ -46,4 +46,4 @@ MODULE_ALIAS_CXL(CXL_DEVICE_DAX_REGION);
MODULE_DESCRIPTION("CXL DAX: direct access to CXL regions");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Intel Corporation");
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("CXL");
diff --git a/drivers/devfreq/event/exynos-nocp.c b/drivers/devfreq/event/exynos-nocp.c
index 5edc522f715c..6a3efd782ad0 100644
--- a/drivers/devfreq/event/exynos-nocp.c
+++ b/drivers/devfreq/event/exynos-nocp.c
@@ -284,7 +284,7 @@ static void exynos_nocp_remove(struct platform_device *pdev)
static struct platform_driver exynos_nocp_driver = {
.probe = exynos_nocp_probe,
- .remove_new = exynos_nocp_remove,
+ .remove = exynos_nocp_remove,
.driver = {
.name = "exynos-nocp",
.of_match_table = exynos_nocp_id_match,
diff --git a/drivers/devfreq/event/exynos-ppmu.c b/drivers/devfreq/event/exynos-ppmu.c
index 7002df20a49e..88cd4dfe87e1 100644
--- a/drivers/devfreq/event/exynos-ppmu.c
+++ b/drivers/devfreq/event/exynos-ppmu.c
@@ -701,7 +701,7 @@ static void exynos_ppmu_remove(struct platform_device *pdev)
static struct platform_driver exynos_ppmu_driver = {
.probe = exynos_ppmu_probe,
- .remove_new = exynos_ppmu_remove,
+ .remove = exynos_ppmu_remove,
.driver = {
.name = "exynos-ppmu",
.of_match_table = exynos_ppmu_id_match,
diff --git a/drivers/devfreq/mtk-cci-devfreq.c b/drivers/devfreq/mtk-cci-devfreq.c
index 7ad5225b0381..22fe9e631f8a 100644
--- a/drivers/devfreq/mtk-cci-devfreq.c
+++ b/drivers/devfreq/mtk-cci-devfreq.c
@@ -430,7 +430,7 @@ MODULE_DEVICE_TABLE(of, mtk_ccifreq_machines);
static struct platform_driver mtk_ccifreq_platdrv = {
.probe = mtk_ccifreq_probe,
- .remove_new = mtk_ccifreq_remove,
+ .remove = mtk_ccifreq_remove,
.driver = {
.name = "mtk-ccifreq",
.of_match_table = mtk_ccifreq_machines,
diff --git a/drivers/devfreq/rk3399_dmc.c b/drivers/devfreq/rk3399_dmc.c
index d405cee92c25..dbdce7636ca5 100644
--- a/drivers/devfreq/rk3399_dmc.c
+++ b/drivers/devfreq/rk3399_dmc.c
@@ -474,7 +474,7 @@ MODULE_DEVICE_TABLE(of, rk3399dmc_devfreq_of_match);
static struct platform_driver rk3399_dmcfreq_driver = {
.probe = rk3399_dmcfreq_probe,
- .remove_new = rk3399_dmcfreq_remove,
+ .remove = rk3399_dmcfreq_remove,
.driver = {
.name = "rk3399-dmc-freq",
.pm = &rk3399_dmcfreq_pm,
diff --git a/drivers/devfreq/sun8i-a33-mbus.c b/drivers/devfreq/sun8i-a33-mbus.c
index bcf654f4ff96..7c6ae91ede1f 100644
--- a/drivers/devfreq/sun8i-a33-mbus.c
+++ b/drivers/devfreq/sun8i-a33-mbus.c
@@ -495,7 +495,7 @@ static SIMPLE_DEV_PM_OPS(sun8i_a33_mbus_pm_ops,
static struct platform_driver sun8i_a33_mbus_driver = {
.probe = sun8i_a33_mbus_probe,
- .remove_new = sun8i_a33_mbus_remove,
+ .remove = sun8i_a33_mbus_remove,
.driver = {
.name = "sun8i-a33-mbus",
.of_match_table = sun8i_a33_mbus_of_match,
diff --git a/drivers/dma-buf/dma-buf.c b/drivers/dma-buf/dma-buf.c
index 5ad0e9e2e1b9..5baa83b85515 100644
--- a/drivers/dma-buf/dma-buf.c
+++ b/drivers/dma-buf/dma-buf.c
@@ -60,7 +60,7 @@ static void __dma_buf_debugfs_list_add(struct dma_buf *dmabuf)
{
}
-static void __dma_buf_debugfs_list_del(struct file *file)
+static void __dma_buf_debugfs_list_del(struct dma_buf *dmabuf)
{
}
#endif
@@ -703,7 +703,7 @@ err_module:
module_put(exp_info->owner);
return ERR_PTR(ret);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_export, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_export, "DMA_BUF");
/**
* dma_buf_fd - returns a file descriptor for the given struct dma_buf
@@ -727,7 +727,7 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags)
return fd;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_fd, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_fd, "DMA_BUF");
/**
* dma_buf_get - returns the struct dma_buf related to an fd
@@ -753,7 +753,7 @@ struct dma_buf *dma_buf_get(int fd)
return file->private_data;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_get, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_get, "DMA_BUF");
/**
* dma_buf_put - decreases refcount of the buffer
@@ -772,7 +772,7 @@ void dma_buf_put(struct dma_buf *dmabuf)
fput(dmabuf->file);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_put, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_put, "DMA_BUF");
static void mangle_sg_table(struct sg_table *sg_table)
{
@@ -978,7 +978,7 @@ err_unlock:
dma_buf_detach(dmabuf, attach);
return ERR_PTR(ret);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_dynamic_attach, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_dynamic_attach, "DMA_BUF");
/**
* dma_buf_attach - Wrapper for dma_buf_dynamic_attach
@@ -993,7 +993,7 @@ struct dma_buf_attachment *dma_buf_attach(struct dma_buf *dmabuf,
{
return dma_buf_dynamic_attach(dmabuf, dev, NULL, NULL);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_attach, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_attach, "DMA_BUF");
static void __unmap_dma_buf(struct dma_buf_attachment *attach,
struct sg_table *sg_table,
@@ -1037,7 +1037,7 @@ void dma_buf_detach(struct dma_buf *dmabuf, struct dma_buf_attachment *attach)
kfree(attach);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_detach, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_detach, "DMA_BUF");
/**
* dma_buf_pin - Lock down the DMA-buf
@@ -1067,7 +1067,7 @@ int dma_buf_pin(struct dma_buf_attachment *attach)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_pin, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_pin, "DMA_BUF");
/**
* dma_buf_unpin - Unpin a DMA-buf
@@ -1088,7 +1088,7 @@ void dma_buf_unpin(struct dma_buf_attachment *attach)
if (dmabuf->ops->unpin)
dmabuf->ops->unpin(attach);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_unpin, "DMA_BUF");
/**
* dma_buf_map_attachment - Returns the scatterlist table of the attachment;
@@ -1176,7 +1176,7 @@ struct sg_table *dma_buf_map_attachment(struct dma_buf_attachment *attach,
#endif /* CONFIG_DMA_API_DEBUG */
return sg_table;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment, "DMA_BUF");
/**
* dma_buf_map_attachment_unlocked - Returns the scatterlist table of the attachment;
@@ -1204,7 +1204,7 @@ dma_buf_map_attachment_unlocked(struct dma_buf_attachment *attach,
return sg_table;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment_unlocked, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_map_attachment_unlocked, "DMA_BUF");
/**
* dma_buf_unmap_attachment - unmaps and decreases usecount of the buffer;might
@@ -1236,7 +1236,7 @@ void dma_buf_unmap_attachment(struct dma_buf_attachment *attach,
!IS_ENABLED(CONFIG_DMABUF_MOVE_NOTIFY))
dma_buf_unpin(attach);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment, "DMA_BUF");
/**
* dma_buf_unmap_attachment_unlocked - unmaps and decreases usecount of the buffer;might
@@ -1261,7 +1261,7 @@ void dma_buf_unmap_attachment_unlocked(struct dma_buf_attachment *attach,
dma_buf_unmap_attachment(attach, sg_table, direction);
dma_resv_unlock(attach->dmabuf->resv);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment_unlocked, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_unmap_attachment_unlocked, "DMA_BUF");
/**
* dma_buf_move_notify - notify attachments that DMA-buf is moving
@@ -1281,7 +1281,7 @@ void dma_buf_move_notify(struct dma_buf *dmabuf)
if (attach->importer_ops)
attach->importer_ops->move_notify(attach);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_move_notify, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_move_notify, "DMA_BUF");
/**
* DOC: cpu access
@@ -1429,7 +1429,7 @@ int dma_buf_begin_cpu_access(struct dma_buf *dmabuf,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_begin_cpu_access, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_begin_cpu_access, "DMA_BUF");
/**
* dma_buf_end_cpu_access - Must be called after accessing a dma_buf from the
@@ -1457,7 +1457,7 @@ int dma_buf_end_cpu_access(struct dma_buf *dmabuf,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_end_cpu_access, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_end_cpu_access, "DMA_BUF");
/**
@@ -1499,7 +1499,7 @@ int dma_buf_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma,
return dmabuf->ops->mmap(dmabuf, vma);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_mmap, "DMA_BUF");
/**
* dma_buf_vmap - Create virtual mapping for the buffer object into kernel
@@ -1552,7 +1552,7 @@ int dma_buf_vmap(struct dma_buf *dmabuf, struct iosys_map *map)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_vmap, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_vmap, "DMA_BUF");
/**
* dma_buf_vmap_unlocked - Create virtual mapping for the buffer object into kernel
@@ -1579,7 +1579,7 @@ int dma_buf_vmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_vmap_unlocked, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_vmap_unlocked, "DMA_BUF");
/**
* dma_buf_vunmap - Unmap a vmap obtained by dma_buf_vmap.
@@ -1603,7 +1603,7 @@ void dma_buf_vunmap(struct dma_buf *dmabuf, struct iosys_map *map)
iosys_map_clear(&dmabuf->vmap_ptr);
}
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap, "DMA_BUF");
/**
* dma_buf_vunmap_unlocked - Unmap a vmap obtained by dma_buf_vmap.
@@ -1619,7 +1619,7 @@ void dma_buf_vunmap_unlocked(struct dma_buf *dmabuf, struct iosys_map *map)
dma_buf_vunmap(dmabuf, map);
dma_resv_unlock(dmabuf->resv);
}
-EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap_unlocked, DMA_BUF);
+EXPORT_SYMBOL_NS_GPL(dma_buf_vunmap_unlocked, "DMA_BUF");
#ifdef CONFIG_DEBUG_FS
static int dma_buf_debug_show(struct seq_file *s, void *unused)
diff --git a/drivers/dma-buf/dma-fence-array.c b/drivers/dma-buf/dma-fence-array.c
index 8a08ffde31e7..6657d4b30af9 100644
--- a/drivers/dma-buf/dma-fence-array.c
+++ b/drivers/dma-buf/dma-fence-array.c
@@ -103,10 +103,36 @@ static bool dma_fence_array_enable_signaling(struct dma_fence *fence)
static bool dma_fence_array_signaled(struct dma_fence *fence)
{
struct dma_fence_array *array = to_dma_fence_array(fence);
+ int num_pending;
+ unsigned int i;
- if (atomic_read(&array->num_pending) > 0)
+ /*
+ * We need to read num_pending before checking the enable_signal bit
+ * to avoid racing with the enable_signaling() implementation, which
+ * might decrement the counter, and cause a partial check.
+ * atomic_read_acquire() pairs with atomic_dec_and_test() in
+ * dma_fence_array_enable_signaling()
+ *
+ * The !--num_pending check is here to account for the any_signaled case
+ * if we race with enable_signaling(), that means the !num_pending check
+ * in the is_signalling_enabled branch might be outdated (num_pending
+ * might have been decremented), but that's fine. The user will get the
+ * right value when testing again later.
+ */
+ num_pending = atomic_read_acquire(&array->num_pending);
+ if (test_bit(DMA_FENCE_FLAG_ENABLE_SIGNAL_BIT, &array->base.flags)) {
+ if (num_pending <= 0)
+ goto signal;
return false;
+ }
+
+ for (i = 0; i < array->num_fences; ++i) {
+ if (dma_fence_is_signaled(array->fences[i]) && !--num_pending)
+ goto signal;
+ }
+ return false;
+signal:
dma_fence_array_clear_pending_error(array);
return true;
}
diff --git a/drivers/dma-buf/dma-fence-unwrap.c b/drivers/dma-buf/dma-fence-unwrap.c
index 628af51c81af..6345062731f1 100644
--- a/drivers/dma-buf/dma-fence-unwrap.c
+++ b/drivers/dma-buf/dma-fence-unwrap.c
@@ -12,6 +12,7 @@
#include <linux/dma-fence-chain.h>
#include <linux/dma-fence-unwrap.h>
#include <linux/slab.h>
+#include <linux/sort.h>
/* Internal helper to start new array iteration, don't use directly */
static struct dma_fence *
@@ -59,6 +60,25 @@ struct dma_fence *dma_fence_unwrap_next(struct dma_fence_unwrap *cursor)
}
EXPORT_SYMBOL_GPL(dma_fence_unwrap_next);
+
+static int fence_cmp(const void *_a, const void *_b)
+{
+ struct dma_fence *a = *(struct dma_fence **)_a;
+ struct dma_fence *b = *(struct dma_fence **)_b;
+
+ if (a->context < b->context)
+ return -1;
+ else if (a->context > b->context)
+ return 1;
+
+ if (dma_fence_is_later(b, a))
+ return 1;
+ else if (dma_fence_is_later(a, b))
+ return -1;
+
+ return 0;
+}
+
/* Implementation for the dma_fence_merge() marco, don't use directly */
struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
struct dma_fence **fences,
@@ -67,8 +87,7 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
struct dma_fence_array *result;
struct dma_fence *tmp, **array;
ktime_t timestamp;
- unsigned int i;
- size_t count;
+ int i, j, count;
count = 0;
timestamp = ns_to_ktime(0);
@@ -96,78 +115,55 @@ struct dma_fence *__dma_fence_unwrap_merge(unsigned int num_fences,
if (!array)
return NULL;
- /*
- * This trashes the input fence array and uses it as position for the
- * following merge loop. This works because the dma_fence_merge()
- * wrapper macro is creating this temporary array on the stack together
- * with the iterators.
- */
- for (i = 0; i < num_fences; ++i)
- fences[i] = dma_fence_unwrap_first(fences[i], &iter[i]);
-
count = 0;
- do {
- unsigned int sel;
-
-restart:
- tmp = NULL;
- for (i = 0; i < num_fences; ++i) {
- struct dma_fence *next;
-
- while (fences[i] && dma_fence_is_signaled(fences[i]))
- fences[i] = dma_fence_unwrap_next(&iter[i]);
-
- next = fences[i];
- if (!next)
- continue;
-
- /*
- * We can't guarantee that inpute fences are ordered by
- * context, but it is still quite likely when this
- * function is used multiple times. So attempt to order
- * the fences by context as we pass over them and merge
- * fences with the same context.
- */
- if (!tmp || tmp->context > next->context) {
- tmp = next;
- sel = i;
-
- } else if (tmp->context < next->context) {
- continue;
-
- } else if (dma_fence_is_later(tmp, next)) {
- fences[i] = dma_fence_unwrap_next(&iter[i]);
- goto restart;
+ for (i = 0; i < num_fences; ++i) {
+ dma_fence_unwrap_for_each(tmp, &iter[i], fences[i]) {
+ if (!dma_fence_is_signaled(tmp)) {
+ array[count++] = dma_fence_get(tmp);
} else {
- fences[sel] = dma_fence_unwrap_next(&iter[sel]);
- goto restart;
+ ktime_t t = dma_fence_timestamp(tmp);
+
+ if (ktime_after(t, timestamp))
+ timestamp = t;
}
}
+ }
- if (tmp) {
- array[count++] = dma_fence_get(tmp);
- fences[sel] = dma_fence_unwrap_next(&iter[sel]);
- }
- } while (tmp);
+ if (count == 0 || count == 1)
+ goto return_fastpath;
- if (count == 0) {
- tmp = dma_fence_allocate_private_stub(ktime_get());
- goto return_tmp;
- }
+ sort(array, count, sizeof(*array), fence_cmp, NULL);
- if (count == 1) {
- tmp = array[0];
- goto return_tmp;
+ /*
+ * Only keep the most recent fence for each context.
+ */
+ j = 0;
+ for (i = 1; i < count; i++) {
+ if (array[i]->context == array[j]->context)
+ dma_fence_put(array[i]);
+ else
+ array[++j] = array[i];
}
-
- result = dma_fence_array_create(count, array,
- dma_fence_context_alloc(1),
- 1, false);
- if (!result) {
- tmp = NULL;
- goto return_tmp;
+ count = ++j;
+
+ if (count > 1) {
+ result = dma_fence_array_create(count, array,
+ dma_fence_context_alloc(1),
+ 1, false);
+ if (!result) {
+ for (i = 0; i < count; i++)
+ dma_fence_put(array[i]);
+ tmp = NULL;
+ goto return_tmp;
+ }
+ return &result->base;
}
- return &result->base;
+
+return_fastpath:
+ if (count == 0)
+ tmp = dma_fence_allocate_private_stub(timestamp);
+ else
+ tmp = array[0];
return_tmp:
kfree(array);
diff --git a/drivers/dma-buf/udmabuf.c b/drivers/dma-buf/udmabuf.c
index 8ce1f074c2d3..cc7398cc17d6 100644
--- a/drivers/dma-buf/udmabuf.c
+++ b/drivers/dma-buf/udmabuf.c
@@ -297,7 +297,7 @@ static const struct dma_buf_ops udmabuf_ops = {
};
#define SEALS_WANTED (F_SEAL_SHRINK)
-#define SEALS_DENIED (F_SEAL_WRITE)
+#define SEALS_DENIED (F_SEAL_WRITE|F_SEAL_FUTURE_WRITE)
static int check_memfd_seals(struct file *memfd)
{
@@ -317,12 +317,10 @@ static int check_memfd_seals(struct file *memfd)
return 0;
}
-static int export_udmabuf(struct udmabuf *ubuf,
- struct miscdevice *device,
- u32 flags)
+static struct dma_buf *export_udmabuf(struct udmabuf *ubuf,
+ struct miscdevice *device)
{
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
- struct dma_buf *buf;
ubuf->device = device;
exp_info.ops = &udmabuf_ops;
@@ -330,11 +328,7 @@ static int export_udmabuf(struct udmabuf *ubuf,
exp_info.priv = ubuf;
exp_info.flags = O_RDWR;
- buf = dma_buf_export(&exp_info);
- if (IS_ERR(buf))
- return PTR_ERR(buf);
-
- return dma_buf_fd(buf, flags);
+ return dma_buf_export(&exp_info);
}
static long udmabuf_pin_folios(struct udmabuf *ubuf, struct file *memfd,
@@ -391,6 +385,7 @@ static long udmabuf_create(struct miscdevice *device,
struct folio **folios = NULL;
pgoff_t pgcnt = 0, pglimit;
struct udmabuf *ubuf;
+ struct dma_buf *dmabuf;
long ret = -EINVAL;
u32 i, flags;
@@ -436,23 +431,39 @@ static long udmabuf_create(struct miscdevice *device,
goto err;
}
+ /*
+ * Take the inode lock to protect against concurrent
+ * memfd_add_seals(), which takes this lock in write mode.
+ */
+ inode_lock_shared(file_inode(memfd));
ret = check_memfd_seals(memfd);
- if (ret < 0) {
- fput(memfd);
- goto err;
- }
+ if (ret)
+ goto out_unlock;
ret = udmabuf_pin_folios(ubuf, memfd, list[i].offset,
list[i].size, folios);
+out_unlock:
+ inode_unlock_shared(file_inode(memfd));
fput(memfd);
if (ret)
goto err;
}
flags = head->flags & UDMABUF_FLAGS_CLOEXEC ? O_CLOEXEC : 0;
- ret = export_udmabuf(ubuf, device, flags);
- if (ret < 0)
+ dmabuf = export_udmabuf(ubuf, device);
+ if (IS_ERR(dmabuf)) {
+ ret = PTR_ERR(dmabuf);
goto err;
+ }
+ /*
+ * Ownership of ubuf is held by the dmabuf from here.
+ * If the following dma_buf_fd() fails, dma_buf_put() cleans up both the
+ * dmabuf and the ubuf (through udmabuf_ops.release).
+ */
+
+ ret = dma_buf_fd(dmabuf, flags);
+ if (ret < 0)
+ dma_buf_put(dmabuf);
kvfree(folios);
return ret;
diff --git a/drivers/dma/amd/qdma/qdma.c b/drivers/dma/amd/qdma/qdma.c
index 6d9079458fe9..66f00ad67351 100644
--- a/drivers/dma/amd/qdma/qdma.c
+++ b/drivers/dma/amd/qdma/qdma.c
@@ -7,9 +7,9 @@
#include <linux/bitfield.h>
#include <linux/bitops.h>
#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
-#include <linux/dma-map-ops.h>
#include <linux/platform_device.h>
#include <linux/platform_data/amd_qdma.h>
#include <linux/regmap.h>
@@ -492,18 +492,9 @@ static int qdma_device_verify(struct qdma_device *qdev)
static int qdma_device_setup(struct qdma_device *qdev)
{
- struct device *dev = &qdev->pdev->dev;
u32 ring_sz = QDMA_DEFAULT_RING_SIZE;
int ret = 0;
- while (dev && get_dma_ops(dev))
- dev = dev->parent;
- if (!dev) {
- qdma_err(qdev, "dma device not found");
- return -EINVAL;
- }
- set_dma_ops(&qdev->pdev->dev, get_dma_ops(dev));
-
ret = qdma_setup_fmap_context(qdev);
if (ret) {
qdma_err(qdev, "Failed setup fmap context");
@@ -548,11 +539,12 @@ static void qdma_free_queue_resources(struct dma_chan *chan)
{
struct qdma_queue *queue = to_qdma_queue(chan);
struct qdma_device *qdev = queue->qdev;
- struct device *dev = qdev->dma_dev.dev;
+ struct qdma_platdata *pdata;
qdma_clear_queue_context(queue);
vchan_free_chan_resources(&queue->vchan);
- dma_free_coherent(dev, queue->ring_size * QDMA_MM_DESC_SIZE,
+ pdata = dev_get_platdata(&qdev->pdev->dev);
+ dma_free_coherent(pdata->dma_dev, queue->ring_size * QDMA_MM_DESC_SIZE,
queue->desc_base, queue->dma_desc_base);
}
@@ -565,6 +557,7 @@ static int qdma_alloc_queue_resources(struct dma_chan *chan)
struct qdma_queue *queue = to_qdma_queue(chan);
struct qdma_device *qdev = queue->qdev;
struct qdma_ctxt_sw_desc desc;
+ struct qdma_platdata *pdata;
size_t size;
int ret;
@@ -572,8 +565,9 @@ static int qdma_alloc_queue_resources(struct dma_chan *chan)
if (ret)
return ret;
+ pdata = dev_get_platdata(&qdev->pdev->dev);
size = queue->ring_size * QDMA_MM_DESC_SIZE;
- queue->desc_base = dma_alloc_coherent(qdev->dma_dev.dev, size,
+ queue->desc_base = dma_alloc_coherent(pdata->dma_dev, size,
&queue->dma_desc_base,
GFP_KERNEL);
if (!queue->desc_base) {
@@ -588,7 +582,7 @@ static int qdma_alloc_queue_resources(struct dma_chan *chan)
if (ret) {
qdma_err(qdev, "Failed to setup SW desc ctxt for %s",
chan->name);
- dma_free_coherent(qdev->dma_dev.dev, size, queue->desc_base,
+ dma_free_coherent(pdata->dma_dev, size, queue->desc_base,
queue->dma_desc_base);
return ret;
}
@@ -948,8 +942,9 @@ static int qdma_init_error_irq(struct qdma_device *qdev)
static int qdmam_alloc_qintr_rings(struct qdma_device *qdev)
{
- u32 ctxt[QDMA_CTXT_REGMAP_LEN];
+ struct qdma_platdata *pdata = dev_get_platdata(&qdev->pdev->dev);
struct device *dev = &qdev->pdev->dev;
+ u32 ctxt[QDMA_CTXT_REGMAP_LEN];
struct qdma_intr_ring *ring;
struct qdma_ctxt_intr intr_ctxt;
u32 vector;
@@ -969,7 +964,8 @@ static int qdmam_alloc_qintr_rings(struct qdma_device *qdev)
ring->msix_id = qdev->err_irq_idx + i + 1;
ring->ridx = i;
ring->color = 1;
- ring->base = dmam_alloc_coherent(dev, QDMA_INTR_RING_SIZE,
+ ring->base = dmam_alloc_coherent(pdata->dma_dev,
+ QDMA_INTR_RING_SIZE,
&ring->dev_base, GFP_KERNEL);
if (!ring->base) {
qdma_err(qdev, "Failed to alloc intr ring %d", i);
diff --git a/drivers/dma/apple-admac.c b/drivers/dma/apple-admac.c
index c499173d80b2..bd49f0374291 100644
--- a/drivers/dma/apple-admac.c
+++ b/drivers/dma/apple-admac.c
@@ -153,6 +153,8 @@ static int admac_alloc_sram_carveout(struct admac_data *ad,
{
struct admac_sram *sram;
int i, ret = 0, nblocks;
+ ad->txcache.size = readl_relaxed(ad->base + REG_TX_SRAM_SIZE);
+ ad->rxcache.size = readl_relaxed(ad->base + REG_RX_SRAM_SIZE);
if (dir == DMA_MEM_TO_DEV)
sram = &ad->txcache;
@@ -912,12 +914,7 @@ static int admac_probe(struct platform_device *pdev)
goto free_irq;
}
- ad->txcache.size = readl_relaxed(ad->base + REG_TX_SRAM_SIZE);
- ad->rxcache.size = readl_relaxed(ad->base + REG_RX_SRAM_SIZE);
-
dev_info(&pdev->dev, "Audio DMA Controller\n");
- dev_info(&pdev->dev, "imprint %x TX cache %u RX cache %u\n",
- readl_relaxed(ad->base + REG_IMPRINT), ad->txcache.size, ad->rxcache.size);
return 0;
diff --git a/drivers/dma/at_xdmac.c b/drivers/dma/at_xdmac.c
index 9c7b40220004..ba25c23164e7 100644
--- a/drivers/dma/at_xdmac.c
+++ b/drivers/dma/at_xdmac.c
@@ -1363,6 +1363,8 @@ at_xdmac_prep_dma_memset(struct dma_chan *chan, dma_addr_t dest, int value,
return NULL;
desc = at_xdmac_memset_create_desc(chan, atchan, dest, len, value);
+ if (!desc)
+ return NULL;
list_add_tail(&desc->desc_node, &desc->descs_list);
desc->tx_dma_desc.cookie = -EBUSY;
diff --git a/drivers/dma/dw/acpi.c b/drivers/dma/dw/acpi.c
index c510c109d2c3..b6452fffa657 100644
--- a/drivers/dma/dw/acpi.c
+++ b/drivers/dma/dw/acpi.c
@@ -8,13 +8,15 @@
static bool dw_dma_acpi_filter(struct dma_chan *chan, void *param)
{
+ struct dw_dma *dw = to_dw_dma(chan->device);
+ struct dw_dma_chip_pdata *data = dev_get_drvdata(dw->dma.dev);
struct acpi_dma_spec *dma_spec = param;
struct dw_dma_slave slave = {
.dma_dev = dma_spec->dev,
.src_id = dma_spec->slave_id,
.dst_id = dma_spec->slave_id,
- .m_master = 0,
- .p_master = 1,
+ .m_master = data->m_master,
+ .p_master = data->p_master,
};
return dw_dma_filter(chan, &slave);
diff --git a/drivers/dma/dw/internal.h b/drivers/dma/dw/internal.h
index 563ce73488db..f1bd06a20cd6 100644
--- a/drivers/dma/dw/internal.h
+++ b/drivers/dma/dw/internal.h
@@ -51,11 +51,15 @@ struct dw_dma_chip_pdata {
int (*probe)(struct dw_dma_chip *chip);
int (*remove)(struct dw_dma_chip *chip);
struct dw_dma_chip *chip;
+ u8 m_master;
+ u8 p_master;
};
static __maybe_unused const struct dw_dma_chip_pdata dw_dma_chip_pdata = {
.probe = dw_dma_probe,
.remove = dw_dma_remove,
+ .m_master = 0,
+ .p_master = 1,
};
static const struct dw_dma_platform_data idma32_pdata = {
@@ -72,6 +76,8 @@ static __maybe_unused const struct dw_dma_chip_pdata idma32_chip_pdata = {
.pdata = &idma32_pdata,
.probe = idma32_dma_probe,
.remove = idma32_dma_remove,
+ .m_master = 0,
+ .p_master = 0,
};
static const struct dw_dma_platform_data xbar_pdata = {
@@ -88,6 +94,8 @@ static __maybe_unused const struct dw_dma_chip_pdata xbar_chip_pdata = {
.pdata = &xbar_pdata,
.probe = idma32_dma_probe,
.remove = idma32_dma_remove,
+ .m_master = 0,
+ .p_master = 0,
};
#endif /* _DMA_DW_INTERNAL_H */
diff --git a/drivers/dma/dw/pci.c b/drivers/dma/dw/pci.c
index ad2d4d012cf7..e8a0eb81726a 100644
--- a/drivers/dma/dw/pci.c
+++ b/drivers/dma/dw/pci.c
@@ -56,10 +56,10 @@ static int dw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *pid)
if (ret)
return ret;
- dw_dma_acpi_controller_register(chip->dw);
-
pci_set_drvdata(pdev, data);
+ dw_dma_acpi_controller_register(chip->dw);
+
return 0;
}
diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
index ce37e1ee9c46..fe8f103d4a63 100644
--- a/drivers/dma/fsl-edma-common.h
+++ b/drivers/dma/fsl-edma-common.h
@@ -166,6 +166,7 @@ struct fsl_edma_chan {
struct work_struct issue_worker;
struct platform_device *pdev;
struct device *pd_dev;
+ struct device_link *pd_dev_link;
u32 srcid;
struct clk *clk;
int priority;
diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
index 60de1003193a..1a613236b3e4 100644
--- a/drivers/dma/fsl-edma-main.c
+++ b/drivers/dma/fsl-edma-main.c
@@ -417,10 +417,33 @@ static const struct of_device_id fsl_edma_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, fsl_edma_dt_ids);
+static void fsl_edma3_detach_pd(struct fsl_edma_engine *fsl_edma)
+{
+ struct fsl_edma_chan *fsl_chan;
+ int i;
+
+ for (i = 0; i < fsl_edma->n_chans; i++) {
+ if (fsl_edma->chan_masked & BIT(i))
+ continue;
+ fsl_chan = &fsl_edma->chans[i];
+ if (fsl_chan->pd_dev_link)
+ device_link_del(fsl_chan->pd_dev_link);
+ if (fsl_chan->pd_dev) {
+ dev_pm_domain_detach(fsl_chan->pd_dev, false);
+ pm_runtime_dont_use_autosuspend(fsl_chan->pd_dev);
+ pm_runtime_set_suspended(fsl_chan->pd_dev);
+ }
+ }
+}
+
+static void devm_fsl_edma3_detach_pd(void *data)
+{
+ fsl_edma3_detach_pd(data);
+}
+
static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_engine *fsl_edma)
{
struct fsl_edma_chan *fsl_chan;
- struct device_link *link;
struct device *pd_chan;
struct device *dev;
int i;
@@ -436,15 +459,16 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
pd_chan = dev_pm_domain_attach_by_id(dev, i);
if (IS_ERR_OR_NULL(pd_chan)) {
dev_err(dev, "Failed attach pd %d\n", i);
- return -EINVAL;
+ goto detach;
}
- link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
+ fsl_chan->pd_dev_link = device_link_add(dev, pd_chan, DL_FLAG_STATELESS |
DL_FLAG_PM_RUNTIME |
DL_FLAG_RPM_ACTIVE);
- if (!link) {
+ if (!fsl_chan->pd_dev_link) {
dev_err(dev, "Failed to add device_link to %d\n", i);
- return -EINVAL;
+ dev_pm_domain_detach(pd_chan, false);
+ goto detach;
}
fsl_chan->pd_dev = pd_chan;
@@ -455,6 +479,10 @@ static int fsl_edma3_attach_pd(struct platform_device *pdev, struct fsl_edma_eng
}
return 0;
+
+detach:
+ fsl_edma3_detach_pd(fsl_edma);
+ return -EINVAL;
}
static int fsl_edma_probe(struct platform_device *pdev)
@@ -544,6 +572,9 @@ static int fsl_edma_probe(struct platform_device *pdev)
ret = fsl_edma3_attach_pd(pdev, fsl_edma);
if (ret)
return ret;
+ ret = devm_add_action_or_reset(&pdev->dev, devm_fsl_edma3_detach_pd, fsl_edma);
+ if (ret)
+ return ret;
}
if (drvdata->flags & FSL_EDMA_DRV_TCD64)
diff --git a/drivers/dma/idxd/Makefile b/drivers/dma/idxd/Makefile
index 2b4a0d406e1e..9ff9d7b87b64 100644
--- a/drivers/dma/idxd/Makefile
+++ b/drivers/dma/idxd/Makefile
@@ -1,4 +1,4 @@
-ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=IDXD
+ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE='"IDXD"'
obj-$(CONFIG_INTEL_IDXD_BUS) += idxd_bus.o
idxd_bus-y := bus.o
diff --git a/drivers/dma/idxd/compat.c b/drivers/dma/idxd/compat.c
index a4adb0c17995..eff9943f1a42 100644
--- a/drivers/dma/idxd/compat.c
+++ b/drivers/dma/idxd/compat.c
@@ -103,4 +103,4 @@ struct idxd_device_driver dsa_drv = {
};
module_idxd_driver(dsa_drv);
-MODULE_IMPORT_NS(IDXD);
+MODULE_IMPORT_NS("IDXD");
diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c
index c41ef195eeb9..5cf419fe6b46 100644
--- a/drivers/dma/idxd/device.c
+++ b/drivers/dma/idxd/device.c
@@ -161,7 +161,7 @@ int idxd_wq_alloc_resources(struct idxd_wq *wq)
free_hw_descs(wq);
return rc;
}
-EXPORT_SYMBOL_NS_GPL(idxd_wq_alloc_resources, IDXD);
+EXPORT_SYMBOL_NS_GPL(idxd_wq_alloc_resources, "IDXD");
void idxd_wq_free_resources(struct idxd_wq *wq)
{
@@ -175,7 +175,7 @@ void idxd_wq_free_resources(struct idxd_wq *wq)
dma_free_coherent(dev, wq->compls_size, wq->compls, wq->compls_addr);
sbitmap_queue_free(&wq->sbq);
}
-EXPORT_SYMBOL_NS_GPL(idxd_wq_free_resources, IDXD);
+EXPORT_SYMBOL_NS_GPL(idxd_wq_free_resources, "IDXD");
int idxd_wq_enable(struct idxd_wq *wq)
{
@@ -407,7 +407,7 @@ int idxd_wq_init_percpu_ref(struct idxd_wq *wq)
reinit_completion(&wq->wq_resurrect);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(idxd_wq_init_percpu_ref, IDXD);
+EXPORT_SYMBOL_NS_GPL(idxd_wq_init_percpu_ref, "IDXD");
void __idxd_wq_quiesce(struct idxd_wq *wq)
{
@@ -417,7 +417,7 @@ void __idxd_wq_quiesce(struct idxd_wq *wq)
complete_all(&wq->wq_resurrect);
wait_for_completion(&wq->wq_dead);
}
-EXPORT_SYMBOL_NS_GPL(__idxd_wq_quiesce, IDXD);
+EXPORT_SYMBOL_NS_GPL(__idxd_wq_quiesce, "IDXD");
void idxd_wq_quiesce(struct idxd_wq *wq)
{
@@ -425,7 +425,7 @@ void idxd_wq_quiesce(struct idxd_wq *wq)
__idxd_wq_quiesce(wq);
mutex_unlock(&wq->wq_lock);
}
-EXPORT_SYMBOL_NS_GPL(idxd_wq_quiesce, IDXD);
+EXPORT_SYMBOL_NS_GPL(idxd_wq_quiesce, "IDXD");
/* Device control bits */
static inline bool idxd_is_enabled(struct idxd_device *idxd)
@@ -1494,7 +1494,7 @@ err_map_portal:
err:
return rc;
}
-EXPORT_SYMBOL_NS_GPL(idxd_drv_enable_wq, IDXD);
+EXPORT_SYMBOL_NS_GPL(idxd_drv_enable_wq, "IDXD");
void idxd_drv_disable_wq(struct idxd_wq *wq)
{
@@ -1516,7 +1516,7 @@ void idxd_drv_disable_wq(struct idxd_wq *wq)
wq->type = IDXD_WQT_NONE;
wq->client_count = 0;
}
-EXPORT_SYMBOL_NS_GPL(idxd_drv_disable_wq, IDXD);
+EXPORT_SYMBOL_NS_GPL(idxd_drv_disable_wq, "IDXD");
int idxd_device_drv_probe(struct idxd_dev *idxd_dev)
{
diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c
index 234c1c658ec7..140f8d772bee 100644
--- a/drivers/dma/idxd/init.c
+++ b/drivers/dma/idxd/init.c
@@ -25,7 +25,7 @@ MODULE_VERSION(IDXD_DRIVER_VERSION);
MODULE_DESCRIPTION("Intel Data Streaming Accelerator and In-Memory Analytics Accelerator common driver");
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Intel Corporation");
-MODULE_IMPORT_NS(IDXD);
+MODULE_IMPORT_NS("IDXD");
static bool sva = true;
module_param(sva, bool, 0644);
diff --git a/drivers/dma/idxd/submit.c b/drivers/dma/idxd/submit.c
index 94eca25ae9b9..6db1c5fcedc5 100644
--- a/drivers/dma/idxd/submit.c
+++ b/drivers/dma/idxd/submit.c
@@ -61,7 +61,7 @@ struct idxd_desc *idxd_alloc_desc(struct idxd_wq *wq, enum idxd_op_type optype)
return __get_desc(wq, idx, cpu);
}
-EXPORT_SYMBOL_NS_GPL(idxd_alloc_desc, IDXD);
+EXPORT_SYMBOL_NS_GPL(idxd_alloc_desc, "IDXD");
void idxd_free_desc(struct idxd_wq *wq, struct idxd_desc *desc)
{
@@ -70,7 +70,7 @@ void idxd_free_desc(struct idxd_wq *wq, struct idxd_desc *desc)
desc->cpu = -1;
sbitmap_queue_clear(&wq->sbq, desc->id, cpu);
}
-EXPORT_SYMBOL_NS_GPL(idxd_free_desc, IDXD);
+EXPORT_SYMBOL_NS_GPL(idxd_free_desc, "IDXD");
static struct idxd_desc *list_abort_desc(struct idxd_wq *wq, struct idxd_irq_entry *ie,
struct idxd_desc *desc)
@@ -219,4 +219,4 @@ int idxd_submit_desc(struct idxd_wq *wq, struct idxd_desc *desc)
percpu_ref_put(&wq->wq_active);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(idxd_submit_desc, IDXD);
+EXPORT_SYMBOL_NS_GPL(idxd_submit_desc, "IDXD");
diff --git a/drivers/dma/loongson2-apb-dma.c b/drivers/dma/loongson2-apb-dma.c
index 367ed34ce4da..c528f02b9f84 100644
--- a/drivers/dma/loongson2-apb-dma.c
+++ b/drivers/dma/loongson2-apb-dma.c
@@ -31,7 +31,7 @@
#define LDMA_ASK_VALID BIT(2)
#define LDMA_START BIT(3) /* DMA start operation */
#define LDMA_STOP BIT(4) /* DMA stop operation */
-#define LDMA_CONFIG_MASK GENMASK(4, 0) /* DMA controller config bits mask */
+#define LDMA_CONFIG_MASK GENMASK_ULL(4, 0) /* DMA controller config bits mask */
/* Bitfields in ndesc_addr field of HW descriptor */
#define LDMA_DESC_EN BIT(0) /*1: The next descriptor is valid */
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index 43efce77bb57..40b76b40bc30 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -1388,6 +1388,7 @@ static int mv_xor_probe(struct platform_device *pdev)
irq = irq_of_parse_and_map(np, 0);
if (!irq) {
ret = -ENODEV;
+ of_node_put(np);
goto err_channel_add;
}
@@ -1396,6 +1397,7 @@ static int mv_xor_probe(struct platform_device *pdev)
if (IS_ERR(chan)) {
ret = PTR_ERR(chan);
irq_dispose_mapping(irq);
+ of_node_put(np);
goto err_channel_add;
}
diff --git a/drivers/dma/tegra186-gpc-dma.c b/drivers/dma/tegra186-gpc-dma.c
index cacf3757adc2..4d6fe0efa76e 100644
--- a/drivers/dma/tegra186-gpc-dma.c
+++ b/drivers/dma/tegra186-gpc-dma.c
@@ -231,6 +231,7 @@ struct tegra_dma_channel {
bool config_init;
char name[30];
enum dma_transfer_direction sid_dir;
+ enum dma_status status;
int id;
int irq;
int slave_id;
@@ -393,6 +394,8 @@ static int tegra_dma_pause(struct tegra_dma_channel *tdc)
tegra_dma_dump_chan_regs(tdc);
}
+ tdc->status = DMA_PAUSED;
+
return ret;
}
@@ -419,6 +422,8 @@ static void tegra_dma_resume(struct tegra_dma_channel *tdc)
val = tdc_read(tdc, TEGRA_GPCDMA_CHAN_CSRE);
val &= ~TEGRA_GPCDMA_CHAN_CSRE_PAUSE;
tdc_write(tdc, TEGRA_GPCDMA_CHAN_CSRE, val);
+
+ tdc->status = DMA_IN_PROGRESS;
}
static int tegra_dma_device_resume(struct dma_chan *dc)
@@ -544,6 +549,7 @@ static void tegra_dma_xfer_complete(struct tegra_dma_channel *tdc)
tegra_dma_sid_free(tdc);
tdc->dma_desc = NULL;
+ tdc->status = DMA_COMPLETE;
}
static void tegra_dma_chan_decode_error(struct tegra_dma_channel *tdc,
@@ -716,6 +722,7 @@ static int tegra_dma_terminate_all(struct dma_chan *dc)
tdc->dma_desc = NULL;
}
+ tdc->status = DMA_COMPLETE;
tegra_dma_sid_free(tdc);
vchan_get_all_descriptors(&tdc->vc, &head);
spin_unlock_irqrestore(&tdc->vc.lock, flags);
@@ -769,6 +776,9 @@ static enum dma_status tegra_dma_tx_status(struct dma_chan *dc,
if (ret == DMA_COMPLETE)
return ret;
+ if (tdc->status == DMA_PAUSED)
+ ret = DMA_PAUSED;
+
spin_lock_irqsave(&tdc->vc.lock, flags);
vd = vchan_find_desc(&tdc->vc, cookie);
if (vd) {
diff --git a/drivers/edac/altera_edac.c b/drivers/edac/altera_edac.c
index fe89f5c4837f..3e971f902363 100644
--- a/drivers/edac/altera_edac.c
+++ b/drivers/edac/altera_edac.c
@@ -482,7 +482,7 @@ static const struct dev_pm_ops altr_sdram_pm_ops = {
static struct platform_driver altr_sdram_edac_driver = {
.probe = altr_sdram_probe,
- .remove_new = altr_sdram_remove,
+ .remove = altr_sdram_remove,
.driver = {
.name = "altr_sdram_edac",
#ifdef CONFIG_PM
@@ -816,7 +816,7 @@ static void altr_edac_device_remove(struct platform_device *pdev)
static struct platform_driver altr_edac_device_driver = {
.probe = altr_edac_device_probe,
- .remove_new = altr_edac_device_remove,
+ .remove = altr_edac_device_remove,
.driver = {
.name = "altr_edac_device",
.of_match_table = altr_edac_device_of_match,
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index ddfbdb66b794..5d356b7c4589 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -3362,36 +3362,24 @@ static bool dct_ecc_enabled(struct amd64_pvt *pvt)
static bool umc_ecc_enabled(struct amd64_pvt *pvt)
{
- u8 umc_en_mask = 0, ecc_en_mask = 0;
- u16 nid = pvt->mc_node_id;
struct amd64_umc *umc;
- u8 ecc_en = 0, i;
+ bool ecc_en = false;
+ int i;
+ /* Check whether at least one UMC is enabled: */
for_each_umc(i) {
umc = &pvt->umc[i];
- /* Only check enabled UMCs. */
- if (!(umc->sdp_ctrl & UMC_SDP_INIT))
- continue;
-
- umc_en_mask |= BIT(i);
-
- if (umc->umc_cap_hi & UMC_ECC_ENABLED)
- ecc_en_mask |= BIT(i);
+ if (umc->sdp_ctrl & UMC_SDP_INIT &&
+ umc->umc_cap_hi & UMC_ECC_ENABLED) {
+ ecc_en = true;
+ break;
+ }
}
- /* Check whether at least one UMC is enabled: */
- if (umc_en_mask)
- ecc_en = umc_en_mask == ecc_en_mask;
- else
- edac_dbg(0, "Node %d: No enabled UMCs.\n", nid);
-
- edac_dbg(3, "Node %d: DRAM ECC %s.\n", nid, (ecc_en ? "enabled" : "disabled"));
+ edac_dbg(3, "Node %d: DRAM ECC %s.\n", pvt->mc_node_id, (ecc_en ? "enabled" : "disabled"));
- if (!ecc_en)
- return false;
- else
- return true;
+ return ecc_en;
}
static inline void
diff --git a/drivers/edac/armada_xp_edac.c b/drivers/edac/armada_xp_edac.c
index 589bc81f1249..d64248fcf4c0 100644
--- a/drivers/edac/armada_xp_edac.c
+++ b/drivers/edac/armada_xp_edac.c
@@ -364,7 +364,7 @@ static void axp_mc_remove(struct platform_device *pdev)
static struct platform_driver axp_mc_driver = {
.probe = axp_mc_probe,
- .remove_new = axp_mc_remove,
+ .remove = axp_mc_remove,
.driver = {
.name = "armada_xp_mc_edac",
.of_match_table = of_match_ptr(axp_mc_of_match),
@@ -579,7 +579,7 @@ static void aurora_l2_remove(struct platform_device *pdev)
static struct platform_driver aurora_l2_driver = {
.probe = aurora_l2_probe,
- .remove_new = aurora_l2_remove,
+ .remove = aurora_l2_remove,
.driver = {
.name = "aurora_l2_edac",
.of_match_table = of_match_ptr(aurora_l2_of_match),
diff --git a/drivers/edac/aspeed_edac.c b/drivers/edac/aspeed_edac.c
index 157a480eb761..dadb8acbee3d 100644
--- a/drivers/edac/aspeed_edac.c
+++ b/drivers/edac/aspeed_edac.c
@@ -387,7 +387,7 @@ static struct platform_driver aspeed_driver = {
.of_match_table = aspeed_of_match
},
.probe = aspeed_probe,
- .remove_new = aspeed_remove
+ .remove = aspeed_remove
};
module_platform_driver(aspeed_driver);
diff --git a/drivers/edac/bluefield_edac.c b/drivers/edac/bluefield_edac.c
index 739132e5ed8a..4942a240c30f 100644
--- a/drivers/edac/bluefield_edac.c
+++ b/drivers/edac/bluefield_edac.c
@@ -474,7 +474,7 @@ static struct platform_driver bluefield_edac_mc_driver = {
.acpi_match_table = bluefield_mc_acpi_ids,
},
.probe = bluefield_edac_mc_probe,
- .remove_new = bluefield_edac_mc_remove,
+ .remove = bluefield_edac_mc_remove,
};
module_platform_driver(bluefield_edac_mc_driver);
diff --git a/drivers/edac/cell_edac.c b/drivers/edac/cell_edac.c
index 2000f66fbf5c..c2420e2287ff 100644
--- a/drivers/edac/cell_edac.c
+++ b/drivers/edac/cell_edac.c
@@ -246,7 +246,7 @@ static struct platform_driver cell_edac_driver = {
.name = "cbe-mic",
},
.probe = cell_edac_probe,
- .remove_new = cell_edac_remove,
+ .remove = cell_edac_remove,
};
static int __init cell_edac_init(void)
diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c
index eb702bc3aa29..9c9e4369c041 100644
--- a/drivers/edac/cpc925_edac.c
+++ b/drivers/edac/cpc925_edac.c
@@ -1027,7 +1027,7 @@ static void cpc925_remove(struct platform_device *pdev)
static struct platform_driver cpc925_edac_driver = {
.probe = cpc925_probe,
- .remove_new = cpc925_remove,
+ .remove = cpc925_remove,
.driver = {
.name = "cpc925_edac",
}
diff --git a/drivers/edac/dmc520_edac.c b/drivers/edac/dmc520_edac.c
index 5e52d31db3b8..64a4d0a07032 100644
--- a/drivers/edac/dmc520_edac.c
+++ b/drivers/edac/dmc520_edac.c
@@ -640,7 +640,7 @@ static struct platform_driver dmc520_edac_driver = {
},
.probe = dmc520_edac_probe,
- .remove_new = dmc520_edac_remove
+ .remove = dmc520_edac_remove
};
module_platform_driver(dmc520_edac_driver);
diff --git a/drivers/edac/highbank_l2_edac.c b/drivers/edac/highbank_l2_edac.c
index 282ca6535f8f..24f163ff323f 100644
--- a/drivers/edac/highbank_l2_edac.c
+++ b/drivers/edac/highbank_l2_edac.c
@@ -128,7 +128,7 @@ static void highbank_l2_err_remove(struct platform_device *pdev)
static struct platform_driver highbank_l2_edac_driver = {
.probe = highbank_l2_err_probe,
- .remove_new = highbank_l2_err_remove,
+ .remove = highbank_l2_err_remove,
.driver = {
.name = "hb_l2_edac",
.of_match_table = hb_l2_err_of_match,
diff --git a/drivers/edac/highbank_mc_edac.c b/drivers/edac/highbank_mc_edac.c
index 1c5b888ab11d..a8879d72d064 100644
--- a/drivers/edac/highbank_mc_edac.c
+++ b/drivers/edac/highbank_mc_edac.c
@@ -261,7 +261,7 @@ static void highbank_mc_remove(struct platform_device *pdev)
static struct platform_driver highbank_mc_edac_driver = {
.probe = highbank_mc_probe,
- .remove_new = highbank_mc_remove,
+ .remove = highbank_mc_remove,
.driver = {
.name = "hb_mc_edac",
.of_match_table = hb_ddr_ctrl_of_match,
diff --git a/drivers/edac/layerscape_edac.c b/drivers/edac/layerscape_edac.c
index 9a0c92ebbc3c..a2caa7fc5412 100644
--- a/drivers/edac/layerscape_edac.c
+++ b/drivers/edac/layerscape_edac.c
@@ -28,7 +28,7 @@ MODULE_DEVICE_TABLE(of, fsl_ddr_mc_err_of_match);
static struct platform_driver fsl_ddr_mc_err_driver = {
.probe = fsl_mc_err_probe,
- .remove_new = fsl_mc_err_remove,
+ .remove = fsl_mc_err_remove,
.driver = {
.name = "fsl_ddr_mc_err",
.of_match_table = fsl_ddr_mc_err_of_match,
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c
index d0266cbcbeda..a45dc6b35ede 100644
--- a/drivers/edac/mpc85xx_edac.c
+++ b/drivers/edac/mpc85xx_edac.c
@@ -323,7 +323,7 @@ static const struct platform_device_id mpc85xx_pci_err_match[] = {
static struct platform_driver mpc85xx_pci_err_driver = {
.probe = mpc85xx_pci_err_probe,
- .remove_new = mpc85xx_pci_err_remove,
+ .remove = mpc85xx_pci_err_remove,
.id_table = mpc85xx_pci_err_match,
.driver = {
.name = "mpc85xx_pci_err",
@@ -627,7 +627,7 @@ MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match);
static struct platform_driver mpc85xx_l2_err_driver = {
.probe = mpc85xx_l2_err_probe,
- .remove_new = mpc85xx_l2_err_remove,
+ .remove = mpc85xx_l2_err_remove,
.driver = {
.name = "mpc85xx_l2_err",
.of_match_table = mpc85xx_l2_err_of_match,
@@ -656,7 +656,7 @@ MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
static struct platform_driver mpc85xx_mc_err_driver = {
.probe = fsl_mc_err_probe,
- .remove_new = fsl_mc_err_remove,
+ .remove = fsl_mc_err_remove,
.driver = {
.name = "mpc85xx_mc_err",
.of_match_table = mpc85xx_mc_err_of_match,
diff --git a/drivers/edac/npcm_edac.c b/drivers/edac/npcm_edac.c
index 2e2133b784e9..e60a99eb8cfb 100644
--- a/drivers/edac/npcm_edac.c
+++ b/drivers/edac/npcm_edac.c
@@ -531,7 +531,7 @@ static struct platform_driver npcm_edac_driver = {
.of_match_table = npcm_edac_of_match,
},
.probe = edac_probe,
- .remove_new = edac_remove,
+ .remove = edac_remove,
};
module_platform_driver(npcm_edac_driver);
diff --git a/drivers/edac/octeon_edac-l2c.c b/drivers/edac/octeon_edac-l2c.c
index 2adb9c8093f8..e6b1595a3cb5 100644
--- a/drivers/edac/octeon_edac-l2c.c
+++ b/drivers/edac/octeon_edac-l2c.c
@@ -194,7 +194,7 @@ static void octeon_l2c_remove(struct platform_device *pdev)
static struct platform_driver octeon_l2c_driver = {
.probe = octeon_l2c_probe,
- .remove_new = octeon_l2c_remove,
+ .remove = octeon_l2c_remove,
.driver = {
.name = "octeon_l2c_edac",
}
diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c
index 4112c2ee34b8..f7176b95b4fe 100644
--- a/drivers/edac/octeon_edac-lmc.c
+++ b/drivers/edac/octeon_edac-lmc.c
@@ -312,7 +312,7 @@ static void octeon_lmc_edac_remove(struct platform_device *pdev)
static struct platform_driver octeon_lmc_edac_driver = {
.probe = octeon_lmc_edac_probe,
- .remove_new = octeon_lmc_edac_remove,
+ .remove = octeon_lmc_edac_remove,
.driver = {
.name = "octeon_lmc_edac",
}
diff --git a/drivers/edac/octeon_edac-pc.c b/drivers/edac/octeon_edac-pc.c
index d9eeb40d2784..aa1219db0b17 100644
--- a/drivers/edac/octeon_edac-pc.c
+++ b/drivers/edac/octeon_edac-pc.c
@@ -130,7 +130,7 @@ static void co_cache_error_remove(struct platform_device *pdev)
static struct platform_driver co_cache_error_driver = {
.probe = co_cache_error_probe,
- .remove_new = co_cache_error_remove,
+ .remove = co_cache_error_remove,
.driver = {
.name = "octeon_pc_edac",
}
diff --git a/drivers/edac/octeon_edac-pci.c b/drivers/edac/octeon_edac-pci.c
index 4d368af2c5f0..c4f3bc33a971 100644
--- a/drivers/edac/octeon_edac-pci.c
+++ b/drivers/edac/octeon_edac-pci.c
@@ -97,7 +97,7 @@ static void octeon_pci_remove(struct platform_device *pdev)
static struct platform_driver octeon_pci_driver = {
.probe = octeon_pci_probe,
- .remove_new = octeon_pci_remove,
+ .remove = octeon_pci_remove,
.driver = {
.name = "octeon_pci_edac",
}
diff --git a/drivers/edac/qcom_edac.c b/drivers/edac/qcom_edac.c
index a9a8ba067007..04c42c83a2ba 100644
--- a/drivers/edac/qcom_edac.c
+++ b/drivers/edac/qcom_edac.c
@@ -407,7 +407,7 @@ MODULE_DEVICE_TABLE(platform, qcom_llcc_edac_id_table);
static struct platform_driver qcom_llcc_edac_driver = {
.probe = qcom_llcc_edac_probe,
- .remove_new = qcom_llcc_edac_remove,
+ .remove = qcom_llcc_edac_remove,
.driver = {
.name = "qcom_llcc_edac",
},
diff --git a/drivers/edac/synopsys_edac.c b/drivers/edac/synopsys_edac.c
index d7416166fd8a..5ed32a3299c4 100644
--- a/drivers/edac/synopsys_edac.c
+++ b/drivers/edac/synopsys_edac.c
@@ -1488,7 +1488,7 @@ static struct platform_driver synps_edac_mc_driver = {
.of_match_table = synps_edac_match,
},
.probe = mc_probe,
- .remove_new = mc_remove,
+ .remove = mc_remove,
};
module_platform_driver(synps_edac_mc_driver);
diff --git a/drivers/edac/ti_edac.c b/drivers/edac/ti_edac.c
index 29723c9592f7..39cc2ef9cac4 100644
--- a/drivers/edac/ti_edac.c
+++ b/drivers/edac/ti_edac.c
@@ -322,7 +322,7 @@ static void ti_edac_remove(struct platform_device *pdev)
static struct platform_driver ti_edac_driver = {
.probe = ti_edac_probe,
- .remove_new = ti_edac_remove,
+ .remove = ti_edac_remove,
.driver = {
.name = EDAC_MOD_NAME,
.of_match_table = ti_edac_of_match,
diff --git a/drivers/edac/versal_edac.c b/drivers/edac/versal_edac.c
index a556d23e8261..5a43b5d43ca2 100644
--- a/drivers/edac/versal_edac.c
+++ b/drivers/edac/versal_edac.c
@@ -1186,7 +1186,7 @@ static struct platform_driver xilinx_ddr_edac_mc_driver = {
.of_match_table = xlnx_edac_match,
},
.probe = mc_probe,
- .remove_new = mc_remove,
+ .remove = mc_remove,
};
module_platform_driver(xilinx_ddr_edac_mc_driver);
diff --git a/drivers/edac/xgene_edac.c b/drivers/edac/xgene_edac.c
index fd87f1b2c145..699c7d29d80c 100644
--- a/drivers/edac/xgene_edac.c
+++ b/drivers/edac/xgene_edac.c
@@ -1989,7 +1989,7 @@ MODULE_DEVICE_TABLE(of, xgene_edac_of_match);
static struct platform_driver xgene_edac_driver = {
.probe = xgene_edac_probe,
- .remove_new = xgene_edac_remove,
+ .remove = xgene_edac_remove,
.driver = {
.name = "xgene-edac",
.of_match_table = xgene_edac_of_match,
diff --git a/drivers/edac/zynqmp_edac.c b/drivers/edac/zynqmp_edac.c
index c9dc78d8c824..cdffc9e4194d 100644
--- a/drivers/edac/zynqmp_edac.c
+++ b/drivers/edac/zynqmp_edac.c
@@ -455,7 +455,7 @@ static struct platform_driver zynqmp_ocm_edac_driver = {
.of_match_table = zynqmp_ocm_edac_match,
},
.probe = edac_probe,
- .remove_new = edac_remove,
+ .remove = edac_remove,
};
module_platform_driver(zynqmp_ocm_edac_driver);
diff --git a/drivers/extcon/extcon-adc-jack.c b/drivers/extcon/extcon-adc-jack.c
index 125016da7fde..46c40d85c2ac 100644
--- a/drivers/extcon/extcon-adc-jack.c
+++ b/drivers/extcon/extcon-adc-jack.c
@@ -196,7 +196,7 @@ static SIMPLE_DEV_PM_OPS(adc_jack_pm_ops,
static struct platform_driver adc_jack_driver = {
.probe = adc_jack_probe,
- .remove_new = adc_jack_remove,
+ .remove = adc_jack_remove,
.driver = {
.name = "adc-jack",
.pm = &adc_jack_pm_ops,
diff --git a/drivers/extcon/extcon-intel-cht-wc.c b/drivers/extcon/extcon-intel-cht-wc.c
index 93552dc3c895..8131a3d7d562 100644
--- a/drivers/extcon/extcon-intel-cht-wc.c
+++ b/drivers/extcon/extcon-intel-cht-wc.c
@@ -627,7 +627,7 @@ MODULE_DEVICE_TABLE(platform, cht_wc_extcon_table);
static struct platform_driver cht_wc_extcon_driver = {
.probe = cht_wc_extcon_probe,
- .remove_new = cht_wc_extcon_remove,
+ .remove = cht_wc_extcon_remove,
.id_table = cht_wc_extcon_table,
.driver = {
.name = "cht_wcove_pwrsrc",
diff --git a/drivers/extcon/extcon-intel-mrfld.c b/drivers/extcon/extcon-intel-mrfld.c
index a1f737f13d49..9219f4328d70 100644
--- a/drivers/extcon/extcon-intel-mrfld.c
+++ b/drivers/extcon/extcon-intel-mrfld.c
@@ -275,7 +275,7 @@ static struct platform_driver mrfld_extcon_driver = {
.name = "mrfld_bcove_pwrsrc",
},
.probe = mrfld_extcon_probe,
- .remove_new = mrfld_extcon_remove,
+ .remove = mrfld_extcon_remove,
.id_table = mrfld_extcon_id_table,
};
module_platform_driver(mrfld_extcon_driver);
diff --git a/drivers/extcon/extcon-max3355.c b/drivers/extcon/extcon-max3355.c
index e62ce7a8d131..b2ee4ff8b04d 100644
--- a/drivers/extcon/extcon-max3355.c
+++ b/drivers/extcon/extcon-max3355.c
@@ -127,7 +127,7 @@ MODULE_DEVICE_TABLE(of, max3355_match_table);
static struct platform_driver max3355_driver = {
.probe = max3355_probe,
- .remove_new = max3355_remove,
+ .remove = max3355_remove,
.driver = {
.name = "extcon-max3355",
.of_match_table = max3355_match_table,
diff --git a/drivers/extcon/extcon-max77843.c b/drivers/extcon/extcon-max77843.c
index 9849e3b8327e..2ae9f7f1a67f 100644
--- a/drivers/extcon/extcon-max77843.c
+++ b/drivers/extcon/extcon-max77843.c
@@ -956,7 +956,7 @@ static struct platform_driver max77843_muic_driver = {
.of_match_table = of_max77843_muic_dt_match,
},
.probe = max77843_muic_probe,
- .remove_new = max77843_muic_remove,
+ .remove = max77843_muic_remove,
.id_table = max77843_muic_id,
};
diff --git a/drivers/extcon/extcon-rtk-type-c.c b/drivers/extcon/extcon-rtk-type-c.c
index 19a01e663733..bdc2b7b3a246 100644
--- a/drivers/extcon/extcon-rtk-type-c.c
+++ b/drivers/extcon/extcon-rtk-type-c.c
@@ -1778,7 +1778,7 @@ static const struct dev_pm_ops extcon_rtk_type_c_pm_ops = {
static struct platform_driver extcon_rtk_type_c_driver = {
.probe = extcon_rtk_type_c_probe,
- .remove_new = extcon_rtk_type_c_remove,
+ .remove = extcon_rtk_type_c_remove,
.driver = {
.name = "extcon-rtk-type_c",
.of_match_table = extcon_rtk_type_c_match,
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
index 9b61eb99b7dc..5e8ad21ad206 100644
--- a/drivers/extcon/extcon-usb-gpio.c
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -279,7 +279,7 @@ MODULE_DEVICE_TABLE(platform, usb_extcon_platform_ids);
static struct platform_driver usb_extcon_driver = {
.probe = usb_extcon_probe,
- .remove_new = usb_extcon_remove,
+ .remove = usb_extcon_remove,
.driver = {
.name = "extcon-usb-gpio",
.pm = &usb_extcon_pm_ops,
diff --git a/drivers/extcon/extcon-usbc-cros-ec.c b/drivers/extcon/extcon-usbc-cros-ec.c
index 805a47230689..1fb627ea8b50 100644
--- a/drivers/extcon/extcon-usbc-cros-ec.c
+++ b/drivers/extcon/extcon-usbc-cros-ec.c
@@ -529,7 +529,7 @@ static struct platform_driver extcon_cros_ec_driver = {
.of_match_table = of_match_ptr(extcon_cros_ec_of_match),
.pm = DEV_PM_OPS,
},
- .remove_new = extcon_cros_ec_remove,
+ .remove = extcon_cros_ec_remove,
.probe = extcon_cros_ec_probe,
};
diff --git a/drivers/firmware/arm_ffa/bus.c b/drivers/firmware/arm_ffa/bus.c
index eb17d03b66fe..dfda5ffc14db 100644
--- a/drivers/firmware/arm_ffa/bus.c
+++ b/drivers/firmware/arm_ffa/bus.c
@@ -187,13 +187,18 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev)
return valid;
}
-struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
- const struct ffa_ops *ops)
+struct ffa_device *
+ffa_device_register(const struct ffa_partition_info *part_info,
+ const struct ffa_ops *ops)
{
int id, ret;
+ uuid_t uuid;
struct device *dev;
struct ffa_device *ffa_dev;
+ if (!part_info)
+ return NULL;
+
id = ida_alloc_min(&ffa_bus_id, 1, GFP_KERNEL);
if (id < 0)
return NULL;
@@ -210,9 +215,11 @@ struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
dev_set_name(&ffa_dev->dev, "arm-ffa-%d", id);
ffa_dev->id = id;
- ffa_dev->vm_id = vm_id;
+ ffa_dev->vm_id = part_info->id;
+ ffa_dev->properties = part_info->properties;
ffa_dev->ops = ops;
- uuid_copy(&ffa_dev->uuid, uuid);
+ import_uuid(&uuid, (u8 *)part_info->uuid);
+ uuid_copy(&ffa_dev->uuid, &uuid);
ret = device_register(&ffa_dev->dev);
if (ret) {
diff --git a/drivers/firmware/arm_ffa/driver.c b/drivers/firmware/arm_ffa/driver.c
index b14cbdae94e8..2c2ec3c35f15 100644
--- a/drivers/firmware/arm_ffa/driver.c
+++ b/drivers/firmware/arm_ffa/driver.c
@@ -1387,7 +1387,6 @@ static struct notifier_block ffa_bus_nb = {
static int ffa_setup_partitions(void)
{
int count, idx, ret;
- uuid_t uuid;
struct ffa_device *ffa_dev;
struct ffa_dev_part_info *info;
struct ffa_partition_info *pbuf, *tpbuf;
@@ -1406,23 +1405,19 @@ static int ffa_setup_partitions(void)
xa_init(&drv_info->partition_info);
for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++) {
- import_uuid(&uuid, (u8 *)tpbuf->uuid);
-
/* Note that if the UUID will be uuid_null, that will require
* ffa_bus_notifier() to find the UUID of this partition id
* with help of ffa_device_match_uuid(). FF-A v1.1 and above
* provides UUID here for each partition as part of the
* discovery API and the same is passed.
*/
- ffa_dev = ffa_device_register(&uuid, tpbuf->id, &ffa_drv_ops);
+ ffa_dev = ffa_device_register(tpbuf, &ffa_drv_ops);
if (!ffa_dev) {
pr_err("%s: failed to register partition ID 0x%x\n",
__func__, tpbuf->id);
continue;
}
- ffa_dev->properties = tpbuf->properties;
-
if (drv_info->version > FFA_VERSION_1_0 &&
!(tpbuf->properties & FFA_PARTITION_AARCH64_EXEC))
ffa_mode_32bit_set(ffa_dev);
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index 1f53ca1f87e3..1b5fb2c4ce86 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -3333,7 +3333,7 @@ static struct platform_driver scmi_driver = {
.dev_groups = versions_groups,
},
.probe = scmi_probe,
- .remove_new = scmi_remove,
+ .remove = scmi_remove,
};
static struct dentry *scmi_debugfs_init(void)
diff --git a/drivers/firmware/arm_scmi/vendors/imx/Kconfig b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
index 2883ed24a84d..a01bf5e47301 100644
--- a/drivers/firmware/arm_scmi/vendors/imx/Kconfig
+++ b/drivers/firmware/arm_scmi/vendors/imx/Kconfig
@@ -15,6 +15,7 @@ config IMX_SCMI_BBM_EXT
config IMX_SCMI_MISC_EXT
tristate "i.MX SCMI MISC EXTENSION"
depends on ARM_SCMI_PROTOCOL || (COMPILE_TEST && OF)
+ depends on IMX_SCMI_MISC_DRV
default y if ARCH_MXC
help
This enables i.MX System MISC control logic such as gpio expander
diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
index f4d47577f83e..87c323de17b9 100644
--- a/drivers/firmware/arm_scpi.c
+++ b/drivers/firmware/arm_scpi.c
@@ -1049,7 +1049,7 @@ static struct platform_driver scpi_driver = {
.dev_groups = versions_groups,
},
.probe = scpi_probe,
- .remove_new = scpi_remove,
+ .remove = scpi_remove,
};
module_platform_driver(scpi_driver);
diff --git a/drivers/firmware/cirrus/cs_dsp.c b/drivers/firmware/cirrus/cs_dsp.c
index 419220fa42fd..5365e9a43000 100644
--- a/drivers/firmware/cirrus/cs_dsp.c
+++ b/drivers/firmware/cirrus/cs_dsp.c
@@ -378,7 +378,7 @@ const char *cs_dsp_mem_region_name(unsigned int type)
return NULL;
}
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_mem_region_name, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_mem_region_name, "FW_CS_DSP");
#ifdef CONFIG_DEBUG_FS
static void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp, const char *s)
@@ -519,7 +519,7 @@ void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root)
dsp->debugfs_root = root;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, "FW_CS_DSP");
/**
* cs_dsp_cleanup_debugfs() - Removes DSP representation from debugfs
@@ -531,17 +531,17 @@ void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp)
debugfs_remove_recursive(dsp->debugfs_root);
dsp->debugfs_root = ERR_PTR(-ENODEV);
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_cleanup_debugfs, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_cleanup_debugfs, "FW_CS_DSP");
#else
void cs_dsp_init_debugfs(struct cs_dsp *dsp, struct dentry *debugfs_root)
{
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_init_debugfs, "FW_CS_DSP");
void cs_dsp_cleanup_debugfs(struct cs_dsp *dsp)
{
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_cleanup_debugfs, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_cleanup_debugfs, "FW_CS_DSP");
static inline void cs_dsp_debugfs_save_wmfwname(struct cs_dsp *dsp,
const char *s)
@@ -749,7 +749,7 @@ int cs_dsp_coeff_write_acked_control(struct cs_dsp_coeff_ctl *ctl, unsigned int
return -ETIMEDOUT;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_acked_control, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_acked_control, "FW_CS_DSP");
static int cs_dsp_coeff_write_ctrl_raw(struct cs_dsp_coeff_ctl *ctl,
unsigned int off, const void *buf, size_t len)
@@ -827,7 +827,7 @@ int cs_dsp_coeff_write_ctrl(struct cs_dsp_coeff_ctl *ctl,
return 1;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_ctrl, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_write_ctrl, "FW_CS_DSP");
/**
* cs_dsp_coeff_lock_and_write_ctrl() - Writes the given buffer to the given coefficient control
@@ -926,7 +926,7 @@ int cs_dsp_coeff_read_ctrl(struct cs_dsp_coeff_ctl *ctl,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_read_ctrl, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_coeff_read_ctrl, "FW_CS_DSP");
/**
* cs_dsp_coeff_lock_and_read_ctrl() - Reads the given coefficient control into the given buffer
@@ -1679,7 +1679,7 @@ struct cs_dsp_coeff_ctl *cs_dsp_get_ctl(struct cs_dsp *dsp, const char *name, in
return rslt;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_get_ctl, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_get_ctl, "FW_CS_DSP");
static void cs_dsp_ctl_fixup_base(struct cs_dsp *dsp,
const struct cs_dsp_alg_region *alg_region)
@@ -1769,7 +1769,7 @@ struct cs_dsp_alg_region *cs_dsp_find_alg_region(struct cs_dsp *dsp,
return NULL;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_find_alg_region, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_find_alg_region, "FW_CS_DSP");
static struct cs_dsp_alg_region *cs_dsp_create_region(struct cs_dsp *dsp,
int type, __be32 id,
@@ -2404,7 +2404,7 @@ int cs_dsp_adsp1_init(struct cs_dsp *dsp)
return cs_dsp_common_init(dsp);
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_init, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_init, "FW_CS_DSP");
/**
* cs_dsp_adsp1_power_up() - Load and start the named firmware
@@ -2496,7 +2496,7 @@ err_mutex:
mutex_unlock(&dsp->pwr_lock);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_power_up, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_power_up, "FW_CS_DSP");
/**
* cs_dsp_adsp1_power_down() - Halts the DSP
@@ -2528,7 +2528,7 @@ void cs_dsp_adsp1_power_down(struct cs_dsp *dsp)
mutex_unlock(&dsp->pwr_lock);
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_power_down, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp1_power_down, "FW_CS_DSP");
static int cs_dsp_adsp2v2_enable_core(struct cs_dsp *dsp)
{
@@ -2680,7 +2680,7 @@ int cs_dsp_set_dspclk(struct cs_dsp *dsp, unsigned int freq)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_set_dspclk, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_set_dspclk, "FW_CS_DSP");
static void cs_dsp_stop_watchdog(struct cs_dsp *dsp)
{
@@ -2770,7 +2770,7 @@ err_mutex:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_power_up, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_power_up, "FW_CS_DSP");
/**
* cs_dsp_power_down() - Powers-down the DSP
@@ -2804,7 +2804,7 @@ void cs_dsp_power_down(struct cs_dsp *dsp)
cs_dsp_dbg(dsp, "Shutdown complete\n");
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_power_down, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_power_down, "FW_CS_DSP");
static int cs_dsp_adsp2_start_core(struct cs_dsp *dsp)
{
@@ -2890,7 +2890,7 @@ err:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_run, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_run, "FW_CS_DSP");
/**
* cs_dsp_stop() - Stops the firmware
@@ -2929,7 +2929,7 @@ void cs_dsp_stop(struct cs_dsp *dsp)
cs_dsp_dbg(dsp, "Execution stopped\n");
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_stop, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_stop, "FW_CS_DSP");
static int cs_dsp_halo_start_core(struct cs_dsp *dsp)
{
@@ -2991,7 +2991,7 @@ int cs_dsp_adsp2_init(struct cs_dsp *dsp)
return cs_dsp_common_init(dsp);
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_init, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_init, "FW_CS_DSP");
/**
* cs_dsp_halo_init() - Initialise a cs_dsp structure representing a HALO Core DSP
@@ -3008,7 +3008,7 @@ int cs_dsp_halo_init(struct cs_dsp *dsp)
return cs_dsp_common_init(dsp);
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_init, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_init, "FW_CS_DSP");
/**
* cs_dsp_remove() - Clean a cs_dsp before deletion
@@ -3028,7 +3028,7 @@ void cs_dsp_remove(struct cs_dsp *dsp)
cs_dsp_free_ctl_blk(ctl);
}
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_remove, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_remove, "FW_CS_DSP");
/**
* cs_dsp_read_raw_data_block() - Reads a block of data from DSP memory
@@ -3065,7 +3065,7 @@ int cs_dsp_read_raw_data_block(struct cs_dsp *dsp, int mem_type, unsigned int me
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_read_raw_data_block, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_read_raw_data_block, "FW_CS_DSP");
/**
* cs_dsp_read_data_word() - Reads a word from DSP memory
@@ -3089,7 +3089,7 @@ int cs_dsp_read_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_add
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_read_data_word, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_read_data_word, "FW_CS_DSP");
/**
* cs_dsp_write_data_word() - Writes a word to DSP memory
@@ -3115,7 +3115,7 @@ int cs_dsp_write_data_word(struct cs_dsp *dsp, int mem_type, unsigned int mem_ad
return regmap_raw_write(dsp->regmap, reg, &val, sizeof(val));
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_write_data_word, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_write_data_word, "FW_CS_DSP");
/**
* cs_dsp_remove_padding() - Convert unpacked words to packed bytes
@@ -3139,7 +3139,7 @@ void cs_dsp_remove_padding(u32 *buf, int nwords)
*pack_out++ = (u8)(word >> 16);
}
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_remove_padding, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_remove_padding, "FW_CS_DSP");
/**
* cs_dsp_adsp2_bus_error() - Handle a DSP bus error interrupt
@@ -3209,7 +3209,7 @@ void cs_dsp_adsp2_bus_error(struct cs_dsp *dsp)
error:
mutex_unlock(&dsp->pwr_lock);
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_bus_error, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_adsp2_bus_error, "FW_CS_DSP");
/**
* cs_dsp_halo_bus_error() - Handle a DSP bus error interrupt
@@ -3269,7 +3269,7 @@ void cs_dsp_halo_bus_error(struct cs_dsp *dsp)
exit_unlock:
mutex_unlock(&dsp->pwr_lock);
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_bus_error, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_bus_error, "FW_CS_DSP");
/**
* cs_dsp_halo_wdt_expire() - Handle DSP watchdog expiry
@@ -3289,7 +3289,7 @@ void cs_dsp_halo_wdt_expire(struct cs_dsp *dsp)
mutex_unlock(&dsp->pwr_lock);
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_wdt_expire, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_halo_wdt_expire, "FW_CS_DSP");
static const struct cs_dsp_ops cs_dsp_adsp1_ops = {
.validate_version = cs_dsp_validate_version,
@@ -3419,7 +3419,7 @@ int cs_dsp_chunk_write(struct cs_dsp_chunk *ch, int nbits, u32 val)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_write, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_write, "FW_CS_DSP");
/**
* cs_dsp_chunk_flush() - Pad remaining data with zero and commit to chunk
@@ -3438,7 +3438,7 @@ int cs_dsp_chunk_flush(struct cs_dsp_chunk *ch)
return cs_dsp_chunk_write(ch, CS_DSP_DATA_WORD_BITS - ch->cachebits, 0);
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_flush, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_flush, "FW_CS_DSP");
/**
* cs_dsp_chunk_read() - Parse data from a DSP memory chunk
@@ -3480,7 +3480,7 @@ int cs_dsp_chunk_read(struct cs_dsp_chunk *ch, int nbits)
return result;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_read, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_chunk_read, "FW_CS_DSP");
struct cs_dsp_wseq_op {
@@ -3605,7 +3605,7 @@ int cs_dsp_wseq_init(struct cs_dsp *dsp, struct cs_dsp_wseq *wseqs, unsigned int
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_wseq_init, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_wseq_init, "FW_CS_DSP");
static struct cs_dsp_wseq_op *cs_dsp_wseq_find_op(u32 addr, u8 op_code,
struct list_head *wseq_ops)
@@ -3720,7 +3720,7 @@ op_new_free:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_wseq_write, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_wseq_write, "FW_CS_DSP");
/**
* cs_dsp_wseq_multi_write() - Add or update multiple entries in a write sequence
@@ -3752,7 +3752,7 @@ int cs_dsp_wseq_multi_write(struct cs_dsp *dsp, struct cs_dsp_wseq *wseq,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs_dsp_wseq_multi_write, FW_CS_DSP);
+EXPORT_SYMBOL_NS_GPL(cs_dsp_wseq_multi_write, "FW_CS_DSP");
MODULE_DESCRIPTION("Cirrus Logic DSP Support");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
diff --git a/drivers/firmware/efi/Kconfig b/drivers/firmware/efi/Kconfig
index e312d731f4a3..5fe61b9ab5f9 100644
--- a/drivers/firmware/efi/Kconfig
+++ b/drivers/firmware/efi/Kconfig
@@ -76,10 +76,6 @@ config EFI_ZBOOT
bool "Enable the generic EFI decompressor"
depends on EFI_GENERIC_STUB && !ARM
select HAVE_KERNEL_GZIP
- select HAVE_KERNEL_LZ4
- select HAVE_KERNEL_LZMA
- select HAVE_KERNEL_LZO
- select HAVE_KERNEL_XZ
select HAVE_KERNEL_ZSTD
help
Create the bootable image as an EFI application that carries the
diff --git a/drivers/firmware/efi/efi-pstore.c b/drivers/firmware/efi/efi-pstore.c
index 552c78f5f059..a253b6144945 100644
--- a/drivers/firmware/efi/efi-pstore.c
+++ b/drivers/firmware/efi/efi-pstore.c
@@ -6,7 +6,7 @@
#include <linux/slab.h>
#include <linux/ucs2_string.h>
-MODULE_IMPORT_NS(EFIVAR);
+MODULE_IMPORT_NS("EFIVAR");
#define DUMP_NAME_LEN 66
diff --git a/drivers/firmware/efi/embedded-firmware.c b/drivers/firmware/efi/embedded-firmware.c
index f5be8e22305b..b49a09d7e665 100644
--- a/drivers/firmware/efi/embedded-firmware.c
+++ b/drivers/firmware/efi/embedded-firmware.c
@@ -16,9 +16,9 @@
/* Exported for use by lib/test_firmware.c only */
LIST_HEAD(efi_embedded_fw_list);
-EXPORT_SYMBOL_NS_GPL(efi_embedded_fw_list, TEST_FIRMWARE);
+EXPORT_SYMBOL_NS_GPL(efi_embedded_fw_list, "TEST_FIRMWARE");
bool efi_embedded_fw_checked;
-EXPORT_SYMBOL_NS_GPL(efi_embedded_fw_checked, TEST_FIRMWARE);
+EXPORT_SYMBOL_NS_GPL(efi_embedded_fw_checked, "TEST_FIRMWARE");
static const struct dmi_system_id * const embedded_fw_table[] = {
#ifdef CONFIG_TOUCHSCREEN_DMI
diff --git a/drivers/firmware/efi/esrt.c b/drivers/firmware/efi/esrt.c
index 7a81c0ce4780..4bb7b0584bc9 100644
--- a/drivers/firmware/efi/esrt.c
+++ b/drivers/firmware/efi/esrt.c
@@ -75,8 +75,6 @@ static LIST_HEAD(entry_list);
struct esre_attribute {
struct attribute attr;
ssize_t (*show)(struct esre_entry *entry, char *buf);
- ssize_t (*store)(struct esre_entry *entry,
- const char *buf, size_t count);
};
static struct esre_entry *to_entry(struct kobject *kobj)
diff --git a/drivers/firmware/efi/libstub/Makefile.zboot b/drivers/firmware/efi/libstub/Makefile.zboot
index 65ffd0b760b2..48842b5c106b 100644
--- a/drivers/firmware/efi/libstub/Makefile.zboot
+++ b/drivers/firmware/efi/libstub/Makefile.zboot
@@ -12,22 +12,16 @@ quiet_cmd_copy_and_pad = PAD $@
$(obj)/vmlinux.bin: $(obj)/$(EFI_ZBOOT_PAYLOAD) FORCE
$(call if_changed,copy_and_pad)
-comp-type-$(CONFIG_KERNEL_GZIP) := gzip
-comp-type-$(CONFIG_KERNEL_LZ4) := lz4
-comp-type-$(CONFIG_KERNEL_LZMA) := lzma
-comp-type-$(CONFIG_KERNEL_LZO) := lzo
-comp-type-$(CONFIG_KERNEL_XZ) := xzkern
-comp-type-$(CONFIG_KERNEL_ZSTD) := zstd22
-
# in GZIP, the appended le32 carrying the uncompressed size is part of the
# format, but in other cases, we just append it at the end for convenience,
# causing the original tools to complain when checking image integrity.
-# So disregard it when calculating the payload size in the zimage header.
-zboot-method-y := $(comp-type-y)_with_size
-zboot-size-len-y := 4
+comp-type-y := gzip
+zboot-method-y := gzip
+zboot-size-len-y := 0
-zboot-method-$(CONFIG_KERNEL_GZIP) := gzip
-zboot-size-len-$(CONFIG_KERNEL_GZIP) := 0
+comp-type-$(CONFIG_KERNEL_ZSTD) := zstd
+zboot-method-$(CONFIG_KERNEL_ZSTD) := zstd22_with_size
+zboot-size-len-$(CONFIG_KERNEL_ZSTD) := 4
$(obj)/vmlinuz: $(obj)/vmlinux.bin FORCE
$(call if_changed,$(zboot-method-y))
diff --git a/drivers/firmware/efi/vars.c b/drivers/firmware/efi/vars.c
index 4056ba7f3440..3700e9869767 100644
--- a/drivers/firmware/efi/vars.c
+++ b/drivers/firmware/efi/vars.c
@@ -149,7 +149,7 @@ int efivar_lock(void)
}
return 0;
}
-EXPORT_SYMBOL_NS_GPL(efivar_lock, EFIVAR);
+EXPORT_SYMBOL_NS_GPL(efivar_lock, "EFIVAR");
/*
* efivar_lock() - obtain the efivar lock if it is free
@@ -165,7 +165,7 @@ int efivar_trylock(void)
}
return 0;
}
-EXPORT_SYMBOL_NS_GPL(efivar_trylock, EFIVAR);
+EXPORT_SYMBOL_NS_GPL(efivar_trylock, "EFIVAR");
/*
* efivar_unlock() - release the efivar lock
@@ -174,7 +174,7 @@ void efivar_unlock(void)
{
up(&efivars_lock);
}
-EXPORT_SYMBOL_NS_GPL(efivar_unlock, EFIVAR);
+EXPORT_SYMBOL_NS_GPL(efivar_unlock, "EFIVAR");
/*
* efivar_get_variable() - retrieve a variable identified by name/vendor
@@ -186,7 +186,7 @@ efi_status_t efivar_get_variable(efi_char16_t *name, efi_guid_t *vendor,
{
return __efivars->ops->get_variable(name, vendor, attr, size, data);
}
-EXPORT_SYMBOL_NS_GPL(efivar_get_variable, EFIVAR);
+EXPORT_SYMBOL_NS_GPL(efivar_get_variable, "EFIVAR");
/*
* efivar_get_next_variable() - enumerate the next name/vendor pair
@@ -198,7 +198,7 @@ efi_status_t efivar_get_next_variable(unsigned long *name_size,
{
return __efivars->ops->get_next_variable(name_size, name, vendor);
}
-EXPORT_SYMBOL_NS_GPL(efivar_get_next_variable, EFIVAR);
+EXPORT_SYMBOL_NS_GPL(efivar_get_next_variable, "EFIVAR");
/*
* efivar_set_variable_locked() - set a variable identified by name/vendor
@@ -230,7 +230,7 @@ efi_status_t efivar_set_variable_locked(efi_char16_t *name, efi_guid_t *vendor,
return setvar(name, vendor, attr, data_size, data);
}
-EXPORT_SYMBOL_NS_GPL(efivar_set_variable_locked, EFIVAR);
+EXPORT_SYMBOL_NS_GPL(efivar_set_variable_locked, "EFIVAR");
/*
* efivar_set_variable() - set a variable identified by name/vendor
@@ -252,7 +252,7 @@ efi_status_t efivar_set_variable(efi_char16_t *name, efi_guid_t *vendor,
efivar_unlock();
return status;
}
-EXPORT_SYMBOL_NS_GPL(efivar_set_variable, EFIVAR);
+EXPORT_SYMBOL_NS_GPL(efivar_set_variable, "EFIVAR");
efi_status_t efivar_query_variable_info(u32 attr,
u64 *storage_space,
@@ -264,4 +264,4 @@ efi_status_t efivar_query_variable_info(u32 attr,
return __efivars->ops->query_variable_info(attr, storage_space,
remaining_space, max_variable_size);
}
-EXPORT_SYMBOL_NS_GPL(efivar_query_variable_info, EFIVAR);
+EXPORT_SYMBOL_NS_GPL(efivar_query_variable_info, "EFIVAR");
diff --git a/drivers/firmware/google/coreboot_table.c b/drivers/firmware/google/coreboot_table.c
index 208652a8087c..882db32e51be 100644
--- a/drivers/firmware/google/coreboot_table.c
+++ b/drivers/firmware/google/coreboot_table.c
@@ -220,7 +220,7 @@ MODULE_DEVICE_TABLE(of, coreboot_of_match);
static struct platform_driver coreboot_table_driver = {
.probe = coreboot_table_probe,
- .remove_new = coreboot_table_remove,
+ .remove = coreboot_table_remove,
.driver = {
.name = "coreboot_table",
.acpi_match_table = ACPI_PTR(cros_coreboot_acpi_match),
diff --git a/drivers/firmware/imx/Kconfig b/drivers/firmware/imx/Kconfig
index 477d3f32d99a..907cd149c40a 100644
--- a/drivers/firmware/imx/Kconfig
+++ b/drivers/firmware/imx/Kconfig
@@ -25,7 +25,6 @@ config IMX_SCU
config IMX_SCMI_MISC_DRV
tristate "IMX SCMI MISC Protocol driver"
- depends on IMX_SCMI_MISC_EXT || COMPILE_TEST
default y if ARCH_MXC
help
The System Controller Management Interface firmware (SCMI FW) is
diff --git a/drivers/firmware/imx/imx-dsp.c b/drivers/firmware/imx/imx-dsp.c
index 01c8ef14eaec..ed79e823157a 100644
--- a/drivers/firmware/imx/imx-dsp.c
+++ b/drivers/firmware/imx/imx-dsp.c
@@ -180,7 +180,7 @@ static struct platform_driver imx_dsp_driver = {
.name = "imx-dsp",
},
.probe = imx_dsp_probe,
- .remove_new = imx_dsp_remove,
+ .remove = imx_dsp_remove,
};
builtin_platform_driver(imx_dsp_driver);
diff --git a/drivers/firmware/memmap.c b/drivers/firmware/memmap.c
index 8e59be3782cb..55b9cfad8a04 100644
--- a/drivers/firmware/memmap.c
+++ b/drivers/firmware/memmap.c
@@ -116,7 +116,7 @@ static void __meminit release_firmware_map_entry(struct kobject *kobj)
kfree(entry);
}
-static struct kobj_type __refdata memmap_ktype = {
+static const struct kobj_type memmap_ktype = {
.release = release_firmware_map_entry,
.sysfs_ops = &memmap_attr_ops,
.default_groups = def_groups,
diff --git a/drivers/firmware/microchip/mpfs-auto-update.c b/drivers/firmware/microchip/mpfs-auto-update.c
index 0f7ec8848202..e194f7acb2a9 100644
--- a/drivers/firmware/microchip/mpfs-auto-update.c
+++ b/drivers/firmware/microchip/mpfs-auto-update.c
@@ -402,10 +402,10 @@ static int mpfs_auto_update_available(struct mpfs_auto_update_priv *priv)
return -EIO;
/*
- * Bit 5 of byte 1 is "UL_Auto Update" & if it is set, Auto Update is
+ * Bit 5 of byte 1 is "UL_IAP" & if it is set, Auto Update is
* not possible.
*/
- if (response_msg[1] & AUTO_UPDATE_FEATURE_ENABLED)
+ if ((((u8 *)response_msg)[1] & AUTO_UPDATE_FEATURE_ENABLED))
return -EPERM;
return 0;
@@ -458,7 +458,7 @@ static struct platform_driver mpfs_auto_update_driver = {
.name = "mpfs-auto-update",
},
.probe = mpfs_auto_update_probe,
- .remove_new = mpfs_auto_update_remove,
+ .remove = mpfs_auto_update_remove,
};
module_platform_driver(mpfs_auto_update_driver);
diff --git a/drivers/firmware/mtk-adsp-ipc.c b/drivers/firmware/mtk-adsp-ipc.c
index a762302978de..2b79371c61c9 100644
--- a/drivers/firmware/mtk-adsp-ipc.c
+++ b/drivers/firmware/mtk-adsp-ipc.c
@@ -95,10 +95,9 @@ static int mtk_adsp_ipc_probe(struct platform_device *pdev)
adsp_chan->idx = i;
adsp_chan->ch = mbox_request_channel_byname(cl, adsp_mbox_ch_names[i]);
if (IS_ERR(adsp_chan->ch)) {
- ret = PTR_ERR(adsp_chan->ch);
- if (ret != -EPROBE_DEFER)
- dev_err(dev, "Failed to request mbox chan %s ret %d\n",
- adsp_mbox_ch_names[i], ret);
+ ret = dev_err_probe(dev, PTR_ERR(adsp_chan->ch),
+ "Failed to request mbox channel %s\n",
+ adsp_mbox_ch_names[i]);
for (j = 0; j < i; j++) {
adsp_chan = &adsp_ipc->chans[j];
@@ -133,7 +132,7 @@ static struct platform_driver mtk_adsp_ipc_driver = {
.name = "mtk-adsp-ipc",
},
.probe = mtk_adsp_ipc_probe,
- .remove_new = mtk_adsp_ipc_remove,
+ .remove = mtk_adsp_ipc_remove,
};
builtin_platform_driver(mtk_adsp_ipc_driver);
diff --git a/drivers/firmware/qemu_fw_cfg.c b/drivers/firmware/qemu_fw_cfg.c
index 85c525745b31..d58da3e4500a 100644
--- a/drivers/firmware/qemu_fw_cfg.c
+++ b/drivers/firmware/qemu_fw_cfg.c
@@ -757,7 +757,7 @@ MODULE_DEVICE_TABLE(acpi, fw_cfg_sysfs_acpi_match);
static struct platform_driver fw_cfg_sysfs_driver = {
.probe = fw_cfg_sysfs_probe,
- .remove_new = fw_cfg_sysfs_remove,
+ .remove = fw_cfg_sysfs_remove,
.driver = {
.name = "fw_cfg",
.of_match_table = fw_cfg_sysfs_mmio_match,
diff --git a/drivers/firmware/raspberrypi.c b/drivers/firmware/raspberrypi.c
index 18cc34987108..7ecde6921a0a 100644
--- a/drivers/firmware/raspberrypi.c
+++ b/drivers/firmware/raspberrypi.c
@@ -406,7 +406,7 @@ static struct platform_driver rpi_firmware_driver = {
},
.probe = rpi_firmware_probe,
.shutdown = rpi_firmware_shutdown,
- .remove_new = rpi_firmware_remove,
+ .remove = rpi_firmware_remove,
};
module_platform_driver(rpi_firmware_driver);
diff --git a/drivers/firmware/stratix10-rsu.c b/drivers/firmware/stratix10-rsu.c
index e20cee9c2d32..1ea39a0a76c7 100644
--- a/drivers/firmware/stratix10-rsu.c
+++ b/drivers/firmware/stratix10-rsu.c
@@ -802,7 +802,7 @@ static void stratix10_rsu_remove(struct platform_device *pdev)
static struct platform_driver stratix10_rsu_driver = {
.probe = stratix10_rsu_probe,
- .remove_new = stratix10_rsu_remove,
+ .remove = stratix10_rsu_remove,
.driver = {
.name = "stratix10-rsu",
.dev_groups = rsu_groups,
diff --git a/drivers/firmware/stratix10-svc.c b/drivers/firmware/stratix10-svc.c
index 528f37417aea..c5c78b869561 100644
--- a/drivers/firmware/stratix10-svc.c
+++ b/drivers/firmware/stratix10-svc.c
@@ -1271,7 +1271,7 @@ static void stratix10_svc_drv_remove(struct platform_device *pdev)
static struct platform_driver stratix10_svc_driver = {
.probe = stratix10_svc_drv_probe,
- .remove_new = stratix10_svc_drv_remove,
+ .remove = stratix10_svc_drv_remove,
.driver = {
.name = "stratix10-svc",
.of_match_table = stratix10_svc_drv_match,
diff --git a/drivers/firmware/xilinx/zynqmp.c b/drivers/firmware/xilinx/zynqmp.c
index cdb565c41119..720fa8b5d8e9 100644
--- a/drivers/firmware/xilinx/zynqmp.c
+++ b/drivers/firmware/xilinx/zynqmp.c
@@ -2118,6 +2118,6 @@ static struct platform_driver zynqmp_firmware_driver = {
.dev_groups = zynqmp_firmware_groups,
},
.probe = zynqmp_firmware_probe,
- .remove_new = zynqmp_firmware_remove,
+ .remove = zynqmp_firmware_remove,
};
module_platform_driver(zynqmp_firmware_driver);
diff --git a/drivers/fpga/altera-fpga2sdram.c b/drivers/fpga/altera-fpga2sdram.c
index f4de3fea0b2d..e41492988dd6 100644
--- a/drivers/fpga/altera-fpga2sdram.c
+++ b/drivers/fpga/altera-fpga2sdram.c
@@ -152,7 +152,7 @@ MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
static struct platform_driver altera_fpga_driver = {
.probe = alt_fpga_bridge_probe,
- .remove_new = alt_fpga_bridge_remove,
+ .remove = alt_fpga_bridge_remove,
.driver = {
.name = "altera_fpga2sdram_bridge",
.of_match_table = of_match_ptr(altera_fpga_of_match),
diff --git a/drivers/fpga/altera-freeze-bridge.c b/drivers/fpga/altera-freeze-bridge.c
index 44061cb16f87..594693ff786e 100644
--- a/drivers/fpga/altera-freeze-bridge.c
+++ b/drivers/fpga/altera-freeze-bridge.c
@@ -262,7 +262,7 @@ static void altera_freeze_br_remove(struct platform_device *pdev)
static struct platform_driver altera_freeze_br_driver = {
.probe = altera_freeze_br_probe,
- .remove_new = altera_freeze_br_remove,
+ .remove = altera_freeze_br_remove,
.driver = {
.name = "altera_freeze_br",
.of_match_table = altera_freeze_br_of_match,
diff --git a/drivers/fpga/altera-hps2fpga.c b/drivers/fpga/altera-hps2fpga.c
index 6f8e24be19c6..f2f1250689cb 100644
--- a/drivers/fpga/altera-hps2fpga.c
+++ b/drivers/fpga/altera-hps2fpga.c
@@ -205,7 +205,7 @@ MODULE_DEVICE_TABLE(of, altera_fpga_of_match);
static struct platform_driver alt_fpga_bridge_driver = {
.probe = alt_fpga_bridge_probe,
- .remove_new = alt_fpga_bridge_remove,
+ .remove = alt_fpga_bridge_remove,
.driver = {
.name = "altera_hps2fpga_bridge",
.of_match_table = of_match_ptr(altera_fpga_of_match),
diff --git a/drivers/fpga/dfl-afu-main.c b/drivers/fpga/dfl-afu-main.c
index 6b97c073849e..2fd4f07ed081 100644
--- a/drivers/fpga/dfl-afu-main.c
+++ b/drivers/fpga/dfl-afu-main.c
@@ -947,12 +947,12 @@ static const struct attribute_group *afu_dev_groups[] = {
};
static struct platform_driver afu_driver = {
- .driver = {
- .name = DFL_FPGA_FEATURE_DEV_PORT,
+ .driver = {
+ .name = DFL_FPGA_FEATURE_DEV_PORT,
.dev_groups = afu_dev_groups,
},
- .probe = afu_probe,
- .remove_new = afu_remove,
+ .probe = afu_probe,
+ .remove = afu_remove,
};
static int __init afu_init(void)
diff --git a/drivers/fpga/dfl-fme-br.c b/drivers/fpga/dfl-fme-br.c
index 0b01b3895277..950c606c59d4 100644
--- a/drivers/fpga/dfl-fme-br.c
+++ b/drivers/fpga/dfl-fme-br.c
@@ -92,11 +92,11 @@ static void fme_br_remove(struct platform_device *pdev)
}
static struct platform_driver fme_br_driver = {
- .driver = {
- .name = DFL_FPGA_FME_BRIDGE,
+ .driver = {
+ .name = DFL_FPGA_FME_BRIDGE,
},
- .probe = fme_br_probe,
- .remove_new = fme_br_remove,
+ .probe = fme_br_probe,
+ .remove = fme_br_remove,
};
module_platform_driver(fme_br_driver);
diff --git a/drivers/fpga/dfl-fme-main.c b/drivers/fpga/dfl-fme-main.c
index 864924f68f5e..f8d89a4a6ccb 100644
--- a/drivers/fpga/dfl-fme-main.c
+++ b/drivers/fpga/dfl-fme-main.c
@@ -742,12 +742,12 @@ static const struct attribute_group *fme_dev_groups[] = {
};
static struct platform_driver fme_driver = {
- .driver = {
- .name = DFL_FPGA_FEATURE_DEV_FME,
+ .driver = {
+ .name = DFL_FPGA_FEATURE_DEV_FME,
.dev_groups = fme_dev_groups,
},
- .probe = fme_probe,
- .remove_new = fme_remove,
+ .probe = fme_probe,
+ .remove = fme_remove,
};
module_platform_driver(fme_driver);
diff --git a/drivers/fpga/dfl-fme-region.c b/drivers/fpga/dfl-fme-region.c
index 71616f8b4982..c6cd63063c82 100644
--- a/drivers/fpga/dfl-fme-region.c
+++ b/drivers/fpga/dfl-fme-region.c
@@ -71,11 +71,11 @@ static void fme_region_remove(struct platform_device *pdev)
}
static struct platform_driver fme_region_driver = {
- .driver = {
- .name = DFL_FPGA_FME_REGION,
+ .driver = {
+ .name = DFL_FPGA_FME_REGION,
},
- .probe = fme_region_probe,
- .remove_new = fme_region_remove,
+ .probe = fme_region_probe,
+ .remove = fme_region_remove,
};
module_platform_driver(fme_region_driver);
diff --git a/drivers/fpga/intel-m10-bmc-sec-update.c b/drivers/fpga/intel-m10-bmc-sec-update.c
index 7ac9f9f5af12..10f678b9ed36 100644
--- a/drivers/fpga/intel-m10-bmc-sec-update.c
+++ b/drivers/fpga/intel-m10-bmc-sec-update.c
@@ -759,7 +759,7 @@ MODULE_DEVICE_TABLE(platform, intel_m10bmc_sec_ids);
static struct platform_driver intel_m10bmc_sec_driver = {
.probe = m10bmc_sec_probe,
- .remove_new = m10bmc_sec_remove,
+ .remove = m10bmc_sec_remove,
.driver = {
.name = "intel-m10bmc-sec-update",
.dev_groups = m10bmc_sec_attr_groups,
@@ -771,4 +771,4 @@ module_platform_driver(intel_m10bmc_sec_driver);
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION("Intel MAX10 BMC Secure Update");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(INTEL_M10_BMC_CORE);
+MODULE_IMPORT_NS("INTEL_M10_BMC_CORE");
diff --git a/drivers/fpga/of-fpga-region.c b/drivers/fpga/of-fpga-region.c
index 8526a5a86f0c..43db4bb77138 100644
--- a/drivers/fpga/of-fpga-region.c
+++ b/drivers/fpga/of-fpga-region.c
@@ -436,7 +436,7 @@ static void of_fpga_region_remove(struct platform_device *pdev)
static struct platform_driver of_fpga_region_driver = {
.probe = of_fpga_region_probe,
- .remove_new = of_fpga_region_remove,
+ .remove = of_fpga_region_remove,
.driver = {
.name = "of-fpga-region",
.of_match_table = of_match_ptr(fpga_region_of_match),
diff --git a/drivers/fpga/socfpga-a10.c b/drivers/fpga/socfpga-a10.c
index 4c03513b8f03..0165a3c86932 100644
--- a/drivers/fpga/socfpga-a10.c
+++ b/drivers/fpga/socfpga-a10.c
@@ -535,7 +535,7 @@ MODULE_DEVICE_TABLE(of, socfpga_a10_fpga_of_match);
static struct platform_driver socfpga_a10_fpga_driver = {
.probe = socfpga_a10_fpga_probe,
- .remove_new = socfpga_a10_fpga_remove,
+ .remove = socfpga_a10_fpga_remove,
.driver = {
.name = "socfpga_a10_fpga_manager",
.of_match_table = socfpga_a10_fpga_of_match,
diff --git a/drivers/fpga/stratix10-soc.c b/drivers/fpga/stratix10-soc.c
index 2c0def7d7cbb..0a295ccf1644 100644
--- a/drivers/fpga/stratix10-soc.c
+++ b/drivers/fpga/stratix10-soc.c
@@ -455,7 +455,7 @@ MODULE_DEVICE_TABLE(of, s10_of_match);
static struct platform_driver s10_driver = {
.probe = s10_probe,
- .remove_new = s10_remove,
+ .remove = s10_remove,
.driver = {
.name = "Stratix10 SoC FPGA manager",
.of_match_table = of_match_ptr(s10_of_match),
diff --git a/drivers/fpga/xilinx-pr-decoupler.c b/drivers/fpga/xilinx-pr-decoupler.c
index 788dd2f63a65..822751fad18a 100644
--- a/drivers/fpga/xilinx-pr-decoupler.c
+++ b/drivers/fpga/xilinx-pr-decoupler.c
@@ -162,7 +162,7 @@ static void xlnx_pr_decoupler_remove(struct platform_device *pdev)
static struct platform_driver xlnx_pr_decoupler_driver = {
.probe = xlnx_pr_decoupler_probe,
- .remove_new = xlnx_pr_decoupler_remove,
+ .remove = xlnx_pr_decoupler_remove,
.driver = {
.name = "xlnx_pr_decoupler",
.of_match_table = xlnx_pr_decoupler_of_match,
diff --git a/drivers/fpga/zynq-fpga.c b/drivers/fpga/zynq-fpga.c
index 4db3d80e10b0..f7e08f7ea9ef 100644
--- a/drivers/fpga/zynq-fpga.c
+++ b/drivers/fpga/zynq-fpga.c
@@ -642,7 +642,7 @@ MODULE_DEVICE_TABLE(of, zynq_fpga_of_match);
static struct platform_driver zynq_fpga_driver = {
.probe = zynq_fpga_probe,
- .remove_new = zynq_fpga_remove,
+ .remove = zynq_fpga_remove,
.driver = {
.name = "zynq_fpga_manager",
.of_match_table = of_match_ptr(zynq_fpga_of_match),
diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
index 6f5e1bdf7e40..bff897f77fe5 100644
--- a/drivers/fsi/fsi-master-aspeed.c
+++ b/drivers/fsi/fsi-master-aspeed.c
@@ -666,7 +666,7 @@ static struct platform_driver fsi_master_aspeed_driver = {
.of_match_table = fsi_master_aspeed_match,
},
.probe = fsi_master_aspeed_probe,
- .remove_new = fsi_master_aspeed_remove,
+ .remove = fsi_master_aspeed_remove,
};
module_platform_driver(fsi_master_aspeed_driver);
diff --git a/drivers/fsi/fsi-master-ast-cf.c b/drivers/fsi/fsi-master-ast-cf.c
index a4c37ff8edd6..9f2fd444ceb6 100644
--- a/drivers/fsi/fsi-master-ast-cf.c
+++ b/drivers/fsi/fsi-master-ast-cf.c
@@ -1434,7 +1434,7 @@ static struct platform_driver fsi_master_acf = {
.of_match_table = fsi_master_acf_match,
},
.probe = fsi_master_acf_probe,
- .remove_new = fsi_master_acf_remove,
+ .remove = fsi_master_acf_remove,
};
module_platform_driver(fsi_master_acf);
diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
index f761344f4873..69de0b5b9cbd 100644
--- a/drivers/fsi/fsi-master-gpio.c
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -888,7 +888,7 @@ static struct platform_driver fsi_master_gpio_driver = {
.of_match_table = fsi_master_gpio_match,
},
.probe = fsi_master_gpio_probe,
- .remove_new = fsi_master_gpio_remove,
+ .remove = fsi_master_gpio_remove,
};
module_platform_driver(fsi_master_gpio_driver);
diff --git a/drivers/fsi/fsi-occ.c b/drivers/fsi/fsi-occ.c
index a6d4c8f123a5..d3e6bf37878a 100644
--- a/drivers/fsi/fsi-occ.c
+++ b/drivers/fsi/fsi-occ.c
@@ -740,7 +740,7 @@ static struct platform_driver occ_driver = {
.of_match_table = occ_match,
},
.probe = occ_probe,
- .remove_new = occ_remove,
+ .remove = occ_remove,
};
static int occ_init(void)
diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
index 56fee58e281e..93ee3aa092f8 100644
--- a/drivers/gpio/Kconfig
+++ b/drivers/gpio/Kconfig
@@ -482,8 +482,9 @@ config GPIO_MT7621
Say yes here to support the Mediatek MT7621 SoC GPIO device.
config GPIO_MVEBU
- def_bool y
+ bool "Marvell Orion and EBU GPIO support" if COMPILE_TEST
depends on PLAT_ORION || ARCH_MVEBU || COMPILE_TEST
+ default PLAT_ORION || ARCH_MVEBU
select GENERIC_IRQ_CHIP
select REGMAP_MMIO
diff --git a/drivers/gpio/gpio-104-dio-48e.c b/drivers/gpio/gpio-104-dio-48e.c
index 4df9becaf349..cf5a50102d49 100644
--- a/drivers/gpio/gpio-104-dio-48e.c
+++ b/drivers/gpio/gpio-104-dio-48e.c
@@ -22,7 +22,7 @@
#include "gpio-i8255.h"
-MODULE_IMPORT_NS(I8255);
+MODULE_IMPORT_NS("I8255");
#define DIO48E_EXTENT 16
#define MAX_NUM_DIO48E max_num_isa_dev(DIO48E_EXTENT)
@@ -339,4 +339,4 @@ module_isa_driver_with_irq(dio48e_driver, num_dio48e, num_irq);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES 104-DIO-48E GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(I8254);
+MODULE_IMPORT_NS("I8254");
diff --git a/drivers/gpio/gpio-104-idio-16.c b/drivers/gpio/gpio-104-idio-16.c
index f03ccd0f534c..ffe7e1cb6b23 100644
--- a/drivers/gpio/gpio-104-idio-16.c
+++ b/drivers/gpio/gpio-104-idio-16.c
@@ -126,4 +126,4 @@ module_isa_driver_with_irq(idio_16_driver, num_idio_16, num_irq);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES 104-IDIO-16 GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(GPIO_IDIO_16);
+MODULE_IMPORT_NS("GPIO_IDIO_16");
diff --git a/drivers/gpio/gpio-aspeed-sgpio.c b/drivers/gpio/gpio-aspeed-sgpio.c
index 72755fee6478..34eb26298e32 100644
--- a/drivers/gpio/gpio-aspeed-sgpio.c
+++ b/drivers/gpio/gpio-aspeed-sgpio.c
@@ -420,7 +420,7 @@ static void aspeed_sgpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
int offset;
irqd_to_aspeed_sgpio_data(d, &gpio, &bank, &bit, &offset);
- seq_printf(p, dev_name(gpio->dev));
+ seq_puts(p, dev_name(gpio->dev));
}
static const struct irq_chip aspeed_sgpio_irq_chip = {
diff --git a/drivers/gpio/gpio-aspeed.c b/drivers/gpio/gpio-aspeed.c
index 208f95fb585e..40c1bd80f8b0 100644
--- a/drivers/gpio/gpio-aspeed.c
+++ b/drivers/gpio/gpio-aspeed.c
@@ -1049,7 +1049,7 @@ static void aspeed_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
if (rc)
return;
- seq_printf(p, dev_name(gpio->dev));
+ seq_puts(p, dev_name(gpio->dev));
}
static const struct irq_chip aspeed_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-elkhartlake.c b/drivers/gpio/gpio-elkhartlake.c
index 887c0fe99d39..95de52d2cc63 100644
--- a/drivers/gpio/gpio-elkhartlake.c
+++ b/drivers/gpio/gpio-elkhartlake.c
@@ -75,4 +75,4 @@ MODULE_AUTHOR("Pandith N <pandith.n@intel.com>");
MODULE_AUTHOR("Raag Jadav <raag.jadav@intel.com>");
MODULE_DESCRIPTION("Intel Elkhart Lake PSE GPIO driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(GPIO_TANGIER);
+MODULE_IMPORT_NS("GPIO_TANGIER");
diff --git a/drivers/gpio/gpio-ep93xx.c b/drivers/gpio/gpio-ep93xx.c
index ab798c848215..58d2464c07bc 100644
--- a/drivers/gpio/gpio-ep93xx.c
+++ b/drivers/gpio/gpio-ep93xx.c
@@ -249,7 +249,7 @@ static void ep93xx_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip gpio_eic_irq_chip = {
diff --git a/drivers/gpio/gpio-gpio-mm.c b/drivers/gpio/gpio-gpio-mm.c
index 43d823a56e59..fb7c510bf2fa 100644
--- a/drivers/gpio/gpio-gpio-mm.c
+++ b/drivers/gpio/gpio-gpio-mm.c
@@ -18,7 +18,7 @@
#include "gpio-i8255.h"
-MODULE_IMPORT_NS(I8255);
+MODULE_IMPORT_NS("I8255");
#define GPIOMM_EXTENT 8
#define MAX_NUM_GPIOMM max_num_isa_dev(GPIOMM_EXTENT)
diff --git a/drivers/gpio/gpio-graniterapids.c b/drivers/gpio/gpio-graniterapids.c
index f2e911a3d2ca..ad6a045fd3d2 100644
--- a/drivers/gpio/gpio-graniterapids.c
+++ b/drivers/gpio/gpio-graniterapids.c
@@ -32,12 +32,14 @@
#define GNR_PINS_PER_REG 32
#define GNR_NUM_REGS DIV_ROUND_UP(GNR_NUM_PINS, GNR_PINS_PER_REG)
-#define GNR_CFG_BAR 0x00
+#define GNR_CFG_PADBAR 0x00
#define GNR_CFG_LOCK_OFFSET 0x04
-#define GNR_GPI_STATUS_OFFSET 0x20
+#define GNR_GPI_STATUS_OFFSET 0x14
#define GNR_GPI_ENABLE_OFFSET 0x24
-#define GNR_CFG_DW_RX_MASK GENMASK(25, 22)
+#define GNR_CFG_DW_HOSTSW_MODE BIT(27)
+#define GNR_CFG_DW_RX_MASK GENMASK(23, 22)
+#define GNR_CFG_DW_INTSEL_MASK GENMASK(21, 14)
#define GNR_CFG_DW_RX_DISABLE FIELD_PREP(GNR_CFG_DW_RX_MASK, 2)
#define GNR_CFG_DW_RX_EDGE FIELD_PREP(GNR_CFG_DW_RX_MASK, 1)
#define GNR_CFG_DW_RX_LEVEL FIELD_PREP(GNR_CFG_DW_RX_MASK, 0)
@@ -50,6 +52,7 @@
* struct gnr_gpio - Intel Granite Rapids-D vGPIO driver state
* @gc: GPIO controller interface
* @reg_base: base address of the GPIO registers
+ * @pad_base: base address of the vGPIO pad configuration registers
* @ro_bitmap: bitmap of read-only pins
* @lock: guard the registers
* @pad_backup: backup of the register state for suspend
@@ -57,6 +60,7 @@
struct gnr_gpio {
struct gpio_chip gc;
void __iomem *reg_base;
+ void __iomem *pad_base;
DECLARE_BITMAP(ro_bitmap, GNR_NUM_PINS);
raw_spinlock_t lock;
u32 pad_backup[];
@@ -65,7 +69,7 @@ struct gnr_gpio {
static void __iomem *gnr_gpio_get_padcfg_addr(const struct gnr_gpio *priv,
unsigned int gpio)
{
- return priv->reg_base + gpio * sizeof(u32);
+ return priv->pad_base + gpio * sizeof(u32);
}
static int gnr_gpio_configure_line(struct gpio_chip *gc, unsigned int gpio,
@@ -88,6 +92,20 @@ static int gnr_gpio_configure_line(struct gpio_chip *gc, unsigned int gpio,
return 0;
}
+static int gnr_gpio_request(struct gpio_chip *gc, unsigned int gpio)
+{
+ struct gnr_gpio *priv = gpiochip_get_data(gc);
+ u32 dw;
+
+ dw = readl(gnr_gpio_get_padcfg_addr(priv, gpio));
+ if (!(dw & GNR_CFG_DW_HOSTSW_MODE)) {
+ dev_warn(gc->parent, "GPIO %u is not owned by host", gpio);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static int gnr_gpio_get(struct gpio_chip *gc, unsigned int gpio)
{
const struct gnr_gpio *priv = gpiochip_get_data(gc);
@@ -139,6 +157,7 @@ static int gnr_gpio_direction_output(struct gpio_chip *gc, unsigned int gpio, in
static const struct gpio_chip gnr_gpio_chip = {
.owner = THIS_MODULE,
+ .request = gnr_gpio_request,
.get = gnr_gpio_get,
.set = gnr_gpio_set,
.get_direction = gnr_gpio_get_direction,
@@ -166,7 +185,7 @@ static void gnr_gpio_irq_ack(struct irq_data *d)
guard(raw_spinlock_irqsave)(&priv->lock);
reg = readl(addr);
- reg &= ~BIT(bit_idx);
+ reg |= BIT(bit_idx);
writel(reg, addr);
}
@@ -209,10 +228,18 @@ static void gnr_gpio_irq_unmask(struct irq_data *d)
static int gnr_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- irq_hw_number_t pin = irqd_to_hwirq(d);
- u32 mask = GNR_CFG_DW_RX_MASK;
+ struct gnr_gpio *priv = gpiochip_get_data(gc);
+ irq_hw_number_t hwirq = irqd_to_hwirq(d);
+ u32 reg;
u32 set;
+ /* Allow interrupts only if Interrupt Select field is non-zero */
+ reg = readl(gnr_gpio_get_padcfg_addr(priv, hwirq));
+ if (!(reg & GNR_CFG_DW_INTSEL_MASK)) {
+ dev_dbg(gc->parent, "GPIO %lu cannot be used as IRQ", hwirq);
+ return -EPERM;
+ }
+
/* Falling edge and level low triggers not supported by the GPIO controller */
switch (type) {
case IRQ_TYPE_NONE:
@@ -230,10 +257,11 @@ static int gnr_gpio_irq_set_type(struct irq_data *d, unsigned int type)
return -EINVAL;
}
- return gnr_gpio_configure_line(gc, pin, mask, set);
+ return gnr_gpio_configure_line(gc, hwirq, GNR_CFG_DW_RX_MASK, set);
}
static const struct irq_chip gnr_gpio_irq_chip = {
+ .name = "gpio-graniterapids",
.irq_ack = gnr_gpio_irq_ack,
.irq_mask = gnr_gpio_irq_mask,
.irq_unmask = gnr_gpio_irq_unmask,
@@ -291,6 +319,7 @@ static int gnr_gpio_probe(struct platform_device *pdev)
struct gnr_gpio *priv;
void __iomem *regs;
int irq, ret;
+ u32 offset;
priv = devm_kzalloc(dev, struct_size(priv, pad_backup, num_backup_pins), GFP_KERNEL);
if (!priv)
@@ -302,6 +331,10 @@ static int gnr_gpio_probe(struct platform_device *pdev)
if (IS_ERR(regs))
return PTR_ERR(regs);
+ priv->reg_base = regs;
+ offset = readl(priv->reg_base + GNR_CFG_PADBAR);
+ priv->pad_base = priv->reg_base + offset;
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@@ -311,8 +344,6 @@ static int gnr_gpio_probe(struct platform_device *pdev)
if (ret)
return dev_err_probe(dev, ret, "failed to request interrupt\n");
- priv->reg_base = regs + readl(regs + GNR_CFG_BAR);
-
gnr_gpio_init_pin_ro_bits(dev, priv->reg_base + GNR_CFG_LOCK_OFFSET,
priv->ro_bitmap);
@@ -324,7 +355,6 @@ static int gnr_gpio_probe(struct platform_device *pdev)
girq = &priv->gc.irq;
gpio_irq_chip_set_chip(girq, &gnr_gpio_irq_chip);
- girq->chip->name = dev_name(dev);
girq->parent_handler = NULL;
girq->num_parents = 0;
girq->parents = NULL;
diff --git a/drivers/gpio/gpio-hlwd.c b/drivers/gpio/gpio-hlwd.c
index 1bcfc1835dae..0580f6712bea 100644
--- a/drivers/gpio/gpio-hlwd.c
+++ b/drivers/gpio/gpio-hlwd.c
@@ -210,7 +210,7 @@ static void hlwd_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p)
struct hlwd_gpio *hlwd =
gpiochip_get_data(irq_data_get_irq_chip_data(data));
- seq_printf(p, dev_name(hlwd->dev));
+ seq_puts(p, dev_name(hlwd->dev));
}
static const struct irq_chip hlwd_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-i8255.c b/drivers/gpio/gpio-i8255.c
index 64ab80fc4a1e..953018bfa2b1 100644
--- a/drivers/gpio/gpio-i8255.c
+++ b/drivers/gpio/gpio-i8255.c
@@ -134,7 +134,7 @@ int devm_i8255_regmap_register(struct device *const dev,
return PTR_ERR_OR_ZERO(devm_gpio_regmap_register(dev, &gpio_config));
}
-EXPORT_SYMBOL_NS_GPL(devm_i8255_regmap_register, I8255);
+EXPORT_SYMBOL_NS_GPL(devm_i8255_regmap_register, "I8255");
MODULE_AUTHOR("William Breathitt Gray");
MODULE_DESCRIPTION("Intel 8255 Programmable Peripheral Interface");
diff --git a/drivers/gpio/gpio-idio-16.c b/drivers/gpio/gpio-idio-16.c
index 53b1eb876a12..0103be977c66 100644
--- a/drivers/gpio/gpio-idio-16.c
+++ b/drivers/gpio/gpio-idio-16.c
@@ -3,6 +3,9 @@
* GPIO library for the ACCES IDIO-16 family
* Copyright (C) 2022 William Breathitt Gray
*/
+
+#define DEFAULT_SYMBOL_NAMESPACE "GPIO_IDIO_16"
+
#include <linux/bits.h>
#include <linux/device.h>
#include <linux/err.h>
@@ -14,8 +17,6 @@
#include "gpio-idio-16.h"
-#define DEFAULT_SYMBOL_NAMESPACE GPIO_IDIO_16
-
#define IDIO_16_DAT_BASE 0x0
#define IDIO_16_OUT_BASE IDIO_16_DAT_BASE
#define IDIO_16_IN_BASE (IDIO_16_DAT_BASE + 1)
diff --git a/drivers/gpio/gpio-ljca.c b/drivers/gpio/gpio-ljca.c
index d67b912d884d..817ecb12d550 100644
--- a/drivers/gpio/gpio-ljca.c
+++ b/drivers/gpio/gpio-ljca.c
@@ -82,9 +82,9 @@ static int ljca_gpio_config(struct ljca_gpio_dev *ljca_gpio, u8 gpio_id,
int ret;
mutex_lock(&ljca_gpio->trans_lock);
+ packet->num = 1;
packet->item[0].index = gpio_id;
packet->item[0].value = config | ljca_gpio->connect_mode[gpio_id];
- packet->num = 1;
ret = ljca_transfer(ljca_gpio->ljca, LJCA_GPIO_CONFIG, (u8 *)packet,
struct_size(packet, item, packet->num), NULL, 0);
@@ -492,4 +492,4 @@ MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>");
MODULE_AUTHOR("Lixu Zhang <lixu.zhang@intel.com>");
MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB-GPIO driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(LJCA);
+MODULE_IMPORT_NS("LJCA");
diff --git a/drivers/gpio/gpio-menz127.c b/drivers/gpio/gpio-menz127.c
index 3ccd2cb35b9c..ebe5da4933bc 100644
--- a/drivers/gpio/gpio-menz127.c
+++ b/drivers/gpio/gpio-menz127.c
@@ -201,4 +201,4 @@ MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
MODULE_DESCRIPTION("MEN 16z127 GPIO Controller");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("mcb:16z127");
-MODULE_IMPORT_NS(MCB);
+MODULE_IMPORT_NS("MCB");
diff --git a/drivers/gpio/gpio-merrifield.c b/drivers/gpio/gpio-merrifield.c
index cd20604f26de..4335a5d8e4f6 100644
--- a/drivers/gpio/gpio-merrifield.c
+++ b/drivers/gpio/gpio-merrifield.c
@@ -142,4 +142,4 @@ module_pci_driver(mrfld_gpio_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Merrifield SoC GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(GPIO_TANGIER);
+MODULE_IMPORT_NS("GPIO_TANGIER");
diff --git a/drivers/gpio/gpio-mlxbf2.c b/drivers/gpio/gpio-mlxbf2.c
index 6abe01bc39c3..6f3dda6b635f 100644
--- a/drivers/gpio/gpio-mlxbf2.c
+++ b/drivers/gpio/gpio-mlxbf2.c
@@ -331,7 +331,7 @@ static void mlxbf2_gpio_irq_print_chip(struct irq_data *irqd,
struct gpio_chip *gc = irq_data_get_irq_chip_data(irqd);
struct mlxbf2_gpio_context *gs = gpiochip_get_data(gc);
- seq_printf(p, dev_name(gs->dev));
+ seq_puts(p, dev_name(gs->dev));
}
static const struct irq_chip mlxbf2_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 7ad453405496..54c4bfdccf56 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -715,7 +715,7 @@ static void omap_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
struct gpio_bank *bank = omap_irq_data_get_bank(d);
- seq_printf(p, dev_name(bank->dev));
+ seq_puts(p, dev_name(bank->dev));
}
static const struct irq_chip omap_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-pca953x.c b/drivers/gpio/gpio-pca953x.c
index 3f2d33ee20cc..272febc3230e 100644
--- a/drivers/gpio/gpio-pca953x.c
+++ b/drivers/gpio/gpio-pca953x.c
@@ -815,7 +815,7 @@ static void pca953x_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip pca953x_irq_chip = {
diff --git a/drivers/gpio/gpio-pci-idio-16.c b/drivers/gpio/gpio-pci-idio-16.c
index 64f332c80550..476cea1b5ed7 100644
--- a/drivers/gpio/gpio-pci-idio-16.c
+++ b/drivers/gpio/gpio-pci-idio-16.c
@@ -112,4 +112,4 @@ module_pci_driver(idio_16_driver);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("ACCES PCI-IDIO-16 GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(GPIO_IDIO_16);
+MODULE_IMPORT_NS("GPIO_IDIO_16");
diff --git a/drivers/gpio/gpio-pl061.c b/drivers/gpio/gpio-pl061.c
index a211a02d4b4a..1c273727ffa3 100644
--- a/drivers/gpio/gpio-pl061.c
+++ b/drivers/gpio/gpio-pl061.c
@@ -291,7 +291,7 @@ static void pl061_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip pl061_irq_chip = {
diff --git a/drivers/gpio/gpio-tangier.c b/drivers/gpio/gpio-tangier.c
index 4b29abafecf6..a415e6d36173 100644
--- a/drivers/gpio/gpio-tangier.c
+++ b/drivers/gpio/gpio-tangier.c
@@ -459,7 +459,7 @@ int devm_tng_gpio_probe(struct device *dev, struct tng_gpio *gpio)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(devm_tng_gpio_probe, GPIO_TANGIER);
+EXPORT_SYMBOL_NS_GPL(devm_tng_gpio_probe, "GPIO_TANGIER");
static int tng_gpio_suspend(struct device *dev)
{
diff --git a/drivers/gpio/gpio-tegra.c b/drivers/gpio/gpio-tegra.c
index 6d3a39a03f58..9ad286adf263 100644
--- a/drivers/gpio/gpio-tegra.c
+++ b/drivers/gpio/gpio-tegra.c
@@ -600,7 +600,7 @@ static void tegra_gpio_irq_print_chip(struct irq_data *d, struct seq_file *s)
{
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
- seq_printf(s, dev_name(chip->parent));
+ seq_puts(s, dev_name(chip->parent));
}
static const struct irq_chip tegra_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-tegra186.c b/drivers/gpio/gpio-tegra186.c
index 1ecb733a5e88..6895b65c86af 100644
--- a/drivers/gpio/gpio-tegra186.c
+++ b/drivers/gpio/gpio-tegra186.c
@@ -610,7 +610,7 @@ static void tegra186_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static const struct irq_chip tegra186_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-tqmx86.c b/drivers/gpio/gpio-tqmx86.c
index f2e7e8754d95..5e26eb3adabb 100644
--- a/drivers/gpio/gpio-tqmx86.c
+++ b/drivers/gpio/gpio-tqmx86.c
@@ -275,7 +275,7 @@ static void tqmx86_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
- seq_printf(p, gc->label);
+ seq_puts(p, gc->label);
}
static const struct irq_chip tqmx86_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-visconti.c b/drivers/gpio/gpio-visconti.c
index ebc71ecdb6cf..5bd965c18a46 100644
--- a/drivers/gpio/gpio-visconti.c
+++ b/drivers/gpio/gpio-visconti.c
@@ -142,7 +142,7 @@ static void visconti_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct visconti_gpio *priv = gpiochip_get_data(gc);
- seq_printf(p, dev_name(priv->dev));
+ seq_puts(p, dev_name(priv->dev));
}
static const struct irq_chip visconti_gpio_irq_chip = {
diff --git a/drivers/gpio/gpio-xgs-iproc.c b/drivers/gpio/gpio-xgs-iproc.c
index 0f9d1f61fee3..93544e98ccbd 100644
--- a/drivers/gpio/gpio-xgs-iproc.c
+++ b/drivers/gpio/gpio-xgs-iproc.c
@@ -198,7 +198,7 @@ static void iproc_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct iproc_gpio_chip *chip = to_iproc_gpio(gc);
- seq_printf(p, dev_name(chip->dev));
+ seq_puts(p, dev_name(chip->dev));
}
static const struct irq_chip iproc_gpio_irq_chip = {
diff --git a/drivers/gpio/gpiolib-swnode.c b/drivers/gpio/gpiolib-swnode.c
index 51d2475c05c5..f21dbc28cf2c 100644
--- a/drivers/gpio/gpiolib-swnode.c
+++ b/drivers/gpio/gpiolib-swnode.c
@@ -141,7 +141,7 @@ int swnode_gpio_count(const struct fwnode_handle *fwnode, const char *con_id)
const struct software_node swnode_gpio_undefined = {
.name = GPIOLIB_SWNODE_UNDEFINED_NAME,
};
-EXPORT_SYMBOL_NS_GPL(swnode_gpio_undefined, GPIO_SWNODE);
+EXPORT_SYMBOL_NS_GPL(swnode_gpio_undefined, "GPIO_SWNODE");
static int __init swnode_gpio_init(void)
{
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig
index 5504721007cc..772fc7625639 100644
--- a/drivers/gpu/drm/Kconfig
+++ b/drivers/gpu/drm/Kconfig
@@ -99,6 +99,7 @@ config DRM_KUNIT_TEST
config DRM_KMS_HELPER
tristate
depends on DRM
+ select FB_CORE if DRM_FBDEV_EMULATION
help
CRTC helpers for KMS drivers.
@@ -358,6 +359,7 @@ config DRM_TTM_HELPER
tristate
depends on DRM
select DRM_TTM
+ select FB_CORE if DRM_FBDEV_EMULATION
select FB_SYSMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION
help
Helpers for ttm-based gem objects
@@ -365,6 +367,7 @@ config DRM_TTM_HELPER
config DRM_GEM_DMA_HELPER
tristate
depends on DRM
+ select FB_CORE if DRM_FBDEV_EMULATION
select FB_DMAMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION
help
Choose this if you need the GEM DMA helper functions
@@ -372,6 +375,7 @@ config DRM_GEM_DMA_HELPER
config DRM_GEM_SHMEM_HELPER
tristate
depends on DRM && MMU
+ select FB_CORE if DRM_FBDEV_EMULATION
select FB_SYSMEM_HELPERS_DEFERRED if DRM_FBDEV_EMULATION
help
Choose this if you need the GEM shmem helper functions
diff --git a/drivers/gpu/drm/amd/amdgpu/aldebaran.c b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
index 3a588fecb0c5..f44de9d4b6a1 100644
--- a/drivers/gpu/drm/amd/amdgpu/aldebaran.c
+++ b/drivers/gpu/drm/amd/amdgpu/aldebaran.c
@@ -330,6 +330,8 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
}
list_for_each_entry(tmp_adev, reset_device_list, reset_list) {
+ amdgpu_set_init_level(tmp_adev,
+ AMDGPU_INIT_LEVEL_RESET_RECOVERY);
dev_info(tmp_adev->dev,
"GPU reset succeeded, trying to resume\n");
r = aldebaran_mode2_restore_ip(tmp_adev);
@@ -375,6 +377,8 @@ aldebaran_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
tmp_adev);
if (!r) {
+ amdgpu_set_init_level(tmp_adev,
+ AMDGPU_INIT_LEVEL_DEFAULT);
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
r = amdgpu_ib_ring_tests(tmp_adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index d8bc6da50016..4653a8d2823a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -839,6 +839,7 @@ struct amdgpu_mqd {
enum amdgpu_init_lvl_id {
AMDGPU_INIT_LEVEL_DEFAULT,
AMDGPU_INIT_LEVEL_MINIMAL_XGMI,
+ AMDGPU_INIT_LEVEL_RESET_RECOVERY,
};
struct amdgpu_init_level {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
index d891ab779ca7..5df21529b3b1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c
@@ -1801,13 +1801,18 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
if (dma_resv_locking_ctx((*bo)->tbo.base.resv) != &parser->exec.ticket)
return -EINVAL;
+ /* Make sure VRAM is allocated contigiously */
(*bo)->flags |= AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS;
- amdgpu_bo_placement_from_domain(*bo, (*bo)->allowed_domains);
- for (i = 0; i < (*bo)->placement.num_placement; i++)
- (*bo)->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
- r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, &ctx);
- if (r)
- return r;
+ if ((*bo)->tbo.resource->mem_type == TTM_PL_VRAM &&
+ !((*bo)->tbo.resource->placement & TTM_PL_FLAG_CONTIGUOUS)) {
+
+ amdgpu_bo_placement_from_domain(*bo, (*bo)->allowed_domains);
+ for (i = 0; i < (*bo)->placement.num_placement; i++)
+ (*bo)->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
+ r = ttm_bo_validate(&(*bo)->tbo, &(*bo)->placement, &ctx);
+ if (r)
+ return r;
+ }
return amdgpu_ttm_alloc_gart(&(*bo)->tbo);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
index 946c48829f19..824f9da5b6ce 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_dev_coredump.c
@@ -343,11 +343,10 @@ void amdgpu_coredump(struct amdgpu_device *adev, bool skip_vram_check,
coredump->skip_vram_check = skip_vram_check;
coredump->reset_vram_lost = vram_lost;
- if (job && job->vm) {
- struct amdgpu_vm *vm = job->vm;
+ if (job && job->pasid) {
struct amdgpu_task_info *ti;
- ti = amdgpu_vm_get_task_info_vm(vm);
+ ti = amdgpu_vm_get_task_info_pasid(adev, job->pasid);
if (ti) {
coredump->reset_task_info = *ti;
amdgpu_vm_put_task_info(ti);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index 0171d240fcb0..cd4fac120834 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -145,7 +145,7 @@ const char *amdgpu_asic_name[] = {
"LAST",
};
-#define AMDGPU_IP_BLK_MASK_ALL GENMASK(AMDGPU_MAX_IP_NUM - 1, 0)
+#define AMDGPU_IP_BLK_MASK_ALL GENMASK(AMD_IP_BLOCK_TYPE_NUM - 1, 0)
/*
* Default init level where all blocks are expected to be initialized. This is
* the level of initialization expected by default and also after a full reset
@@ -156,6 +156,11 @@ struct amdgpu_init_level amdgpu_init_default = {
.hwini_ip_block_mask = AMDGPU_IP_BLK_MASK_ALL,
};
+struct amdgpu_init_level amdgpu_init_recovery = {
+ .level = AMDGPU_INIT_LEVEL_RESET_RECOVERY,
+ .hwini_ip_block_mask = AMDGPU_IP_BLK_MASK_ALL,
+};
+
/*
* Minimal blocks needed to be initialized before a XGMI hive can be reset. This
* is used for cases like reset on initialization where the entire hive needs to
@@ -182,6 +187,9 @@ void amdgpu_set_init_level(struct amdgpu_device *adev,
case AMDGPU_INIT_LEVEL_MINIMAL_XGMI:
adev->init_lvl = &amdgpu_init_minimal_xgmi;
break;
+ case AMDGPU_INIT_LEVEL_RESET_RECOVERY:
+ adev->init_lvl = &amdgpu_init_recovery;
+ break;
case AMDGPU_INIT_LEVEL_DEFAULT:
fallthrough;
default:
@@ -409,6 +417,9 @@ bool amdgpu_device_supports_boco(struct drm_device *dev)
{
struct amdgpu_device *adev = drm_to_adev(dev);
+ if (!IS_ENABLED(CONFIG_HOTPLUG_PCI_PCIE))
+ return false;
+
if (adev->has_pr3 ||
((adev->flags & AMD_IS_PX) && amdgpu_is_atpx_hybrid()))
return true;
@@ -3250,7 +3261,7 @@ static int amdgpu_device_ip_late_init(struct amdgpu_device *adev)
return r;
}
- if (!amdgpu_in_reset(adev))
+ if (!amdgpu_reset_in_recovery(adev))
amdgpu_ras_set_error_query_ready(adev, true);
amdgpu_device_set_cg_state(adev, AMD_CG_STATE_GATE);
@@ -3662,9 +3673,11 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev)
continue;
r = block->version->funcs->hw_init(&adev->ip_blocks[i]);
- DRM_INFO("RE-INIT-early: %s %s\n", block->version->funcs->name, r?"failed":"succeeded");
- if (r)
+ if (r) {
+ dev_err(adev->dev, "RE-INIT-early: %s failed\n",
+ block->version->funcs->name);
return r;
+ }
block->status.hw = true;
}
}
@@ -3674,7 +3687,8 @@ static int amdgpu_device_ip_reinit_early_sriov(struct amdgpu_device *adev)
static int amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device *adev)
{
- int i, r;
+ struct amdgpu_ip_block *block;
+ int i, r = 0;
static enum amd_ip_block_type ip_order[] = {
AMD_IP_BLOCK_TYPE_SMC,
@@ -3689,34 +3703,28 @@ static int amdgpu_device_ip_reinit_late_sriov(struct amdgpu_device *adev)
};
for (i = 0; i < ARRAY_SIZE(ip_order); i++) {
- int j;
- struct amdgpu_ip_block *block;
+ block = amdgpu_device_ip_get_ip_block(adev, ip_order[i]);
- for (j = 0; j < adev->num_ip_blocks; j++) {
- block = &adev->ip_blocks[j];
-
- if (block->version->type != ip_order[i] ||
- !block->status.valid ||
- block->status.hw)
- continue;
+ if (!block)
+ continue;
+ if (block->status.valid && !block->status.hw) {
if (block->version->type == AMD_IP_BLOCK_TYPE_SMC) {
- r = amdgpu_ip_block_resume(&adev->ip_blocks[i]);
- if (r)
- return r;
+ r = amdgpu_ip_block_resume(block);
} else {
- r = block->version->funcs->hw_init(&adev->ip_blocks[i]);
- if (r) {
- DRM_ERROR("hw_init of IP block <%s> failed %d\n",
- adev->ip_blocks[i].version->funcs->name, r);
- return r;
- }
- block->status.hw = true;
+ r = block->version->funcs->hw_init(block);
+ }
+
+ if (r) {
+ dev_err(adev->dev, "RE-INIT-late: %s failed\n",
+ block->version->funcs->name);
+ break;
}
+ block->status.hw = true;
}
}
- return 0;
+ return r;
}
/**
@@ -3757,7 +3765,7 @@ static int amdgpu_device_ip_resume_phase1(struct amdgpu_device *adev)
*
* @adev: amdgpu_device pointer
*
- * First resume function for hardware IPs. The list of all the hardware
+ * Second resume function for hardware IPs. The list of all the hardware
* IPs that make up the asic is walked and the resume callbacks are run for
* all blocks except COMMON, GMC, and IH. resume puts the hardware into a
* functional state after a suspend and updates the software state as
@@ -3775,6 +3783,7 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_COMMON ||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_GMC ||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_IH ||
+ adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE ||
adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_PSP)
continue;
r = amdgpu_ip_block_resume(&adev->ip_blocks[i]);
@@ -3786,6 +3795,36 @@ static int amdgpu_device_ip_resume_phase2(struct amdgpu_device *adev)
}
/**
+ * amdgpu_device_ip_resume_phase3 - run resume for hardware IPs
+ *
+ * @adev: amdgpu_device pointer
+ *
+ * Third resume function for hardware IPs. The list of all the hardware
+ * IPs that make up the asic is walked and the resume callbacks are run for
+ * all DCE. resume puts the hardware into a functional state after a suspend
+ * and updates the software state as necessary. This function is also used
+ * for restoring the GPU after a GPU reset.
+ *
+ * Returns 0 on success, negative error code on failure.
+ */
+static int amdgpu_device_ip_resume_phase3(struct amdgpu_device *adev)
+{
+ int i, r;
+
+ for (i = 0; i < adev->num_ip_blocks; i++) {
+ if (!adev->ip_blocks[i].status.valid || adev->ip_blocks[i].status.hw)
+ continue;
+ if (adev->ip_blocks[i].version->type == AMD_IP_BLOCK_TYPE_DCE) {
+ r = amdgpu_ip_block_resume(&adev->ip_blocks[i]);
+ if (r)
+ return r;
+ }
+ }
+
+ return 0;
+}
+
+/**
* amdgpu_device_ip_resume - run resume for hardware IPs
*
* @adev: amdgpu_device pointer
@@ -3814,6 +3853,13 @@ static int amdgpu_device_ip_resume(struct amdgpu_device *adev)
if (adev->mman.buffer_funcs_ring->sched.ready)
amdgpu_ttm_set_buffer_funcs_status(adev, true);
+ if (r)
+ return r;
+
+ amdgpu_fence_driver_hw_init(adev);
+
+ r = amdgpu_device_ip_resume_phase3(adev);
+
return r;
}
@@ -4669,8 +4715,8 @@ void amdgpu_device_fini_sw(struct amdgpu_device *adev)
int idx;
bool px;
- amdgpu_fence_driver_sw_fini(adev);
amdgpu_device_ip_fini(adev);
+ amdgpu_fence_driver_sw_fini(adev);
amdgpu_ucode_release(&adev->firmware.gpu_info_fw);
adev->accel_working = false;
dma_fence_put(rcu_dereference_protected(adev->gang_submit, true));
@@ -4894,7 +4940,6 @@ int amdgpu_device_resume(struct drm_device *dev, bool notify_clients)
dev_err(adev->dev, "amdgpu_device_ip_resume failed (%d).\n", r);
goto exit;
}
- amdgpu_fence_driver_hw_init(adev);
if (!adev->in_s0ix) {
r = amdgpu_amdkfd_resume(adev, adev->in_runpm);
@@ -5419,7 +5464,7 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
struct list_head *device_list_handle;
bool full_reset, vram_lost = false;
struct amdgpu_device *tmp_adev;
- int r;
+ int r, init_level;
device_list_handle = reset_context->reset_device_list;
@@ -5428,10 +5473,18 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
full_reset = test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
+ /**
+ * If it's reset on init, it's default init level, otherwise keep level
+ * as recovery level.
+ */
+ if (reset_context->method == AMD_RESET_METHOD_ON_INIT)
+ init_level = AMDGPU_INIT_LEVEL_DEFAULT;
+ else
+ init_level = AMDGPU_INIT_LEVEL_RESET_RECOVERY;
+
r = 0;
list_for_each_entry(tmp_adev, device_list_handle, reset_list) {
- /* After reset, it's default init level */
- amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_DEFAULT);
+ amdgpu_set_init_level(tmp_adev, init_level);
if (full_reset) {
/* post card */
amdgpu_ras_set_fed(tmp_adev, false);
@@ -5471,6 +5524,10 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
if (tmp_adev->mman.buffer_funcs_ring->sched.ready)
amdgpu_ttm_set_buffer_funcs_status(tmp_adev, true);
+ r = amdgpu_device_ip_resume_phase3(tmp_adev);
+ if (r)
+ goto out;
+
if (vram_lost)
amdgpu_device_fill_reset_magic(tmp_adev);
@@ -5518,6 +5575,9 @@ int amdgpu_device_reinit_after_reset(struct amdgpu_reset_context *reset_context)
out:
if (!r) {
+ /* IP init is complete now, set level as default */
+ amdgpu_set_init_level(tmp_adev,
+ AMDGPU_INIT_LEVEL_DEFAULT);
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
r = amdgpu_ib_ring_tests(tmp_adev);
if (r) {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
index f57cc72c43cf..69a6b6dba0a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gfx.c
@@ -1778,9 +1778,11 @@ int amdgpu_gfx_sysfs_init(struct amdgpu_device *adev)
void amdgpu_gfx_sysfs_fini(struct amdgpu_device *adev)
{
- amdgpu_gfx_sysfs_xcp_fini(adev);
- amdgpu_gfx_sysfs_isolation_shader_fini(adev);
- amdgpu_gfx_sysfs_reset_mask_fini(adev);
+ if (adev->dev->kobj.sd) {
+ amdgpu_gfx_sysfs_xcp_fini(adev);
+ amdgpu_gfx_sysfs_isolation_shader_fini(adev);
+ amdgpu_gfx_sysfs_reset_mask_fini(adev);
+ }
}
int amdgpu_gfx_cleaner_shader_sw_init(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index b9d08bc96581..a21c510c408e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -255,7 +255,6 @@ void amdgpu_job_set_resources(struct amdgpu_job *job, struct amdgpu_bo *gds,
void amdgpu_job_free_resources(struct amdgpu_job *job)
{
- struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched);
struct dma_fence *f;
unsigned i;
@@ -268,7 +267,7 @@ void amdgpu_job_free_resources(struct amdgpu_job *job)
f = NULL;
for (i = 0; i < job->num_ibs; ++i)
- amdgpu_ib_free(ring->adev, &job->ibs[i], f);
+ amdgpu_ib_free(NULL, &job->ibs[i], f);
}
static void amdgpu_job_free_cb(struct drm_sched_job *s_job)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
index 04eb51674596..b6d2eb049f54 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_jpeg.c
@@ -447,6 +447,8 @@ int amdgpu_jpeg_sysfs_reset_mask_init(struct amdgpu_device *adev)
void amdgpu_jpeg_sysfs_reset_mask_fini(struct amdgpu_device *adev)
{
- if (adev->jpeg.num_jpeg_inst)
- device_remove_file(adev->dev, &dev_attr_jpeg_reset_mask);
+ if (adev->dev->kobj.sd) {
+ if (adev->jpeg.num_jpeg_inst)
+ device_remove_file(adev->dev, &dev_attr_jpeg_reset_mask);
+ }
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
index e8adfd0a570a..34b5e22b44e5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_preempt_mgr.c
@@ -137,7 +137,8 @@ void amdgpu_preempt_mgr_fini(struct amdgpu_device *adev)
if (ret)
return;
- device_remove_file(adev->dev, &dev_attr_mem_info_preempt_used);
+ if (adev->dev->kobj.sd)
+ device_remove_file(adev->dev, &dev_attr_mem_info_preempt_used);
ttm_resource_manager_cleanup(man);
ttm_set_driver_manager(&adev->mman.bdev, AMDGPU_PL_PREEMPT, NULL);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
index 17cf10c0b72b..448f9e742983 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
@@ -4112,7 +4112,7 @@ static umode_t amdgpu_flash_attr_is_visible(struct kobject *kobj, struct attribu
}
static umode_t amdgpu_bin_flash_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
int idx)
{
struct device *dev = kobj_to_dev(kobj);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
index 1bc95b0cdbb8..4c9fa24dd972 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ras.c
@@ -1298,7 +1298,7 @@ int amdgpu_ras_bind_aca(struct amdgpu_device *adev, enum amdgpu_ras_block blk,
struct ras_manager *obj;
/* in resume phase, no need to create aca fs node */
- if (adev->in_suspend || amdgpu_in_reset(adev))
+ if (adev->in_suspend || amdgpu_reset_in_recovery(adev))
return 0;
obj = get_ras_manager(adev, blk);
@@ -3610,7 +3610,7 @@ static void amdgpu_ras_event_mgr_init(struct amdgpu_device *adev)
ras->event_mgr = hive ? &hive->event_mgr : &ras->__event_mgr;
/* init event manager with node 0 on xgmi system */
- if (!amdgpu_in_reset(adev)) {
+ if (!amdgpu_reset_in_recovery(adev)) {
if (!hive || adev->gmc.xgmi.node_id == 0)
ras_event_mgr_init(ras->event_mgr);
}
@@ -3825,7 +3825,7 @@ int amdgpu_ras_block_late_init(struct amdgpu_device *adev,
r = amdgpu_ras_feature_enable_on_boot(adev, ras_block, 1);
if (r) {
- if (adev->in_suspend || amdgpu_in_reset(adev)) {
+ if (adev->in_suspend || amdgpu_reset_in_recovery(adev)) {
/* in resume phase, if fail to enable ras,
* clean up all ras fs nodes, and disable ras */
goto cleanup;
@@ -3837,7 +3837,7 @@ int amdgpu_ras_block_late_init(struct amdgpu_device *adev,
amdgpu_persistent_edc_harvesting(adev, ras_block);
/* in resume phase, no need to create ras fs node */
- if (adev->in_suspend || amdgpu_in_reset(adev))
+ if (adev->in_suspend || amdgpu_reset_in_recovery(adev))
return 0;
ras_obj = container_of(ras_block, struct amdgpu_ras_block_object, ras_comm);
@@ -3967,7 +3967,7 @@ int amdgpu_ras_late_init(struct amdgpu_device *adev)
amdgpu_ras_event_mgr_init(adev);
if (amdgpu_ras_aca_is_supported(adev)) {
- if (amdgpu_in_reset(adev)) {
+ if (amdgpu_reset_in_recovery(adev)) {
if (amdgpu_aca_is_enabled(adev))
r = amdgpu_aca_reset(adev);
else
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
index 24dae7cdbe95..a0acb65f4b40 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.c
@@ -342,3 +342,8 @@ void amdgpu_reset_get_desc(struct amdgpu_reset_context *rst_ctxt, char *buf,
strscpy(buf, "unknown", len);
}
}
+
+bool amdgpu_reset_in_recovery(struct amdgpu_device *adev)
+{
+ return (adev->init_lvl->level == AMDGPU_INIT_LEVEL_RESET_RECOVERY);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
index f8628bc898df..4d9b9701139b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_reset.h
@@ -158,4 +158,6 @@ extern struct amdgpu_reset_handler xgmi_reset_on_init_handler;
int amdgpu_reset_do_xgmi_reset_on_init(
struct amdgpu_reset_context *reset_context);
+bool amdgpu_reset_in_recovery(struct amdgpu_device *adev);
+
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index 8c89b69edc20..113f0d242618 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -451,6 +451,8 @@ void amdgpu_sdma_sysfs_reset_mask_fini(struct amdgpu_device *adev)
if (!amdgpu_gpu_recovery)
return;
- if (adev->sdma.num_instances)
- device_remove_file(adev->dev, &dev_attr_sdma_reset_mask);
+ if (adev->dev->kobj.sd) {
+ if (adev->sdma.num_instances)
+ device_remove_file(adev->dev, &dev_attr_sdma_reset_mask);
+ }
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
index 9f922ec50ea2..c8180cad0abd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c
@@ -61,7 +61,7 @@
#include "amdgpu_res_cursor.h"
#include "bif/bif_4_1_d.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
#define AMDGPU_TTM_VRAM_MAX_DW_READ ((size_t)128)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 31fd30dcd593..65bb26215e86 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -551,6 +551,8 @@ static void amdgpu_uvd_force_into_uvd_segment(struct amdgpu_bo *abo)
for (i = 0; i < abo->placement.num_placement; ++i) {
abo->placements[i].fpfn = 0 >> PAGE_SHIFT;
abo->placements[i].lpfn = (256 * 1024 * 1024) >> PAGE_SHIFT;
+ if (abo->placements[i].mem_type == TTM_PL_VRAM)
+ abo->placements[i].flags |= TTM_PL_FLAG_CONTIGUOUS;
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
index 74fdbf71d95b..599d3ca4e0ef 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vce.c
@@ -214,15 +214,15 @@ int amdgpu_vce_sw_fini(struct amdgpu_device *adev)
drm_sched_entity_destroy(&adev->vce.entity);
- amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
- (void **)&adev->vce.cpu_addr);
-
for (i = 0; i < adev->vce.num_rings; i++)
amdgpu_ring_fini(&adev->vce.ring[i]);
amdgpu_ucode_release(&adev->vce.fw);
mutex_destroy(&adev->vce.idle_mutex);
+ amdgpu_bo_free_kernel(&adev->vce.vcpu_bo, &adev->vce.gpu_addr,
+ (void **)&adev->vce.cpu_addr);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index aecb78e0519f..3e94c3ba1ba2 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -1283,3 +1283,40 @@ int amdgpu_vcn_psp_update_sram(struct amdgpu_device *adev, int inst_idx,
return psp_execute_ip_fw_load(&adev->psp, &ucode);
}
+
+static ssize_t amdgpu_get_vcn_reset_mask(struct device *dev,
+ struct device_attribute *attr,
+ char *buf)
+{
+ struct drm_device *ddev = dev_get_drvdata(dev);
+ struct amdgpu_device *adev = drm_to_adev(ddev);
+
+ if (!adev)
+ return -ENODEV;
+
+ return amdgpu_show_reset_mask(buf, adev->vcn.supported_reset);
+}
+
+static DEVICE_ATTR(vcn_reset_mask, 0444,
+ amdgpu_get_vcn_reset_mask, NULL);
+
+int amdgpu_vcn_sysfs_reset_mask_init(struct amdgpu_device *adev)
+{
+ int r = 0;
+
+ if (adev->vcn.num_vcn_inst) {
+ r = device_create_file(adev->dev, &dev_attr_vcn_reset_mask);
+ if (r)
+ return r;
+ }
+
+ return r;
+}
+
+void amdgpu_vcn_sysfs_reset_mask_fini(struct amdgpu_device *adev)
+{
+ if (adev->dev->kobj.sd) {
+ if (adev->vcn.num_vcn_inst)
+ device_remove_file(adev->dev, &dev_attr_vcn_reset_mask);
+ }
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 765b809d48a2..1e32311c1dff 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -333,6 +333,8 @@ struct amdgpu_vcn {
/* IP reg dump */
uint32_t *ip_dump;
+
+ uint32_t supported_reset;
};
struct amdgpu_fw_shared_rb_ptrs_struct {
@@ -519,5 +521,7 @@ int amdgpu_vcn_ras_sw_init(struct amdgpu_device *adev);
int amdgpu_vcn_psp_update_sram(struct amdgpu_device *adev, int inst_idx,
enum AMDGPU_UCODE_ID ucode_id);
int amdgpu_vcn_save_vcpu_bo(struct amdgpu_device *adev);
+int amdgpu_vcn_sysfs_reset_mask_init(struct amdgpu_device *adev);
+void amdgpu_vcn_sysfs_reset_mask_fini(struct amdgpu_device *adev);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 8d9bf7a0857f..c9c48b782ec1 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -674,12 +674,8 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
pasid_mapping_needed &= adev->gmc.gmc_funcs->emit_pasid_mapping &&
ring->funcs->emit_wreg;
- if (adev->gfx.enable_cleaner_shader &&
- ring->funcs->emit_cleaner_shader &&
- job->enforce_isolation)
- ring->funcs->emit_cleaner_shader(ring);
-
- if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync)
+ if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync &&
+ !(job->enforce_isolation && !job->vmid))
return 0;
amdgpu_ring_ib_begin(ring);
@@ -690,6 +686,11 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
if (need_pipe_sync)
amdgpu_ring_emit_pipeline_sync(ring);
+ if (adev->gfx.enable_cleaner_shader &&
+ ring->funcs->emit_cleaner_shader &&
+ job->enforce_isolation)
+ ring->funcs->emit_cleaner_shader(ring);
+
if (vm_flush_needed) {
trace_amdgpu_vm_flush(ring, job->vmid, job->vm_pd_addr);
amdgpu_ring_emit_vm_flush(ring, job->vmid, job->vm_pd_addr);
@@ -1265,10 +1266,9 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va,
* next command submission.
*/
if (amdgpu_vm_is_bo_always_valid(vm, bo)) {
- uint32_t mem_type = bo->tbo.resource->mem_type;
-
- if (!(bo->preferred_domains &
- amdgpu_mem_type_to_domain(mem_type)))
+ if (bo->tbo.resource &&
+ !(bo->preferred_domains &
+ amdgpu_mem_type_to_domain(bo->tbo.resource->mem_type)))
amdgpu_vm_bo_evicted(&bo_va->base);
else
amdgpu_vm_bo_idle(&bo_va->base);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
index 3e6f9dfb61bb..110b120d7375 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vpe.c
@@ -904,8 +904,10 @@ int amdgpu_vpe_sysfs_reset_mask_init(struct amdgpu_device *adev)
void amdgpu_vpe_sysfs_reset_mask_fini(struct amdgpu_device *adev)
{
- if (adev->vpe.num_instances)
- device_remove_file(adev->dev, &dev_attr_vpe_reset_mask);
+ if (adev->dev->kobj.sd) {
+ if (adev->vpe.num_instances)
+ device_remove_file(adev->dev, &dev_attr_vpe_reset_mask);
+ }
}
static const struct amdgpu_ring_funcs vpe_ring_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
index b47422b0b5b1..74b4349e345a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.c
@@ -40,6 +40,11 @@
#define smnPCS_GOPX1_PCS_ERROR_STATUS 0x12200210
#define smnPCS_GOPX1_PCS_ERROR_NONCORRECTABLE_MASK 0x12200218
+#define XGMI_STATE_DISABLE 0xD1
+#define XGMI_STATE_LS0 0x81
+#define XGMI_LINK_ACTIVE 1
+#define XGMI_LINK_INACTIVE 0
+
static DEFINE_MUTEX(xgmi_mutex);
#define AMDGPU_MAX_XGMI_DEVICE_PER_HIVE 4
@@ -289,6 +294,42 @@ static const struct amdgpu_pcs_ras_field xgmi3x16_pcs_ras_fields[] = {
SOC15_REG_FIELD(PCS_XGMI3X16_PCS_ERROR_STATUS, RxCMDPktErr)},
};
+static u32 xgmi_v6_4_get_link_status(struct amdgpu_device *adev, int global_link_num)
+{
+ const u32 smnpcs_xgmi3x16_pcs_state_hist1 = 0x11a00070;
+ const int xgmi_inst = 2;
+ u32 link_inst;
+ u64 addr;
+
+ link_inst = global_link_num % xgmi_inst;
+
+ addr = (smnpcs_xgmi3x16_pcs_state_hist1 | (link_inst << 20)) +
+ adev->asic_funcs->encode_ext_smn_addressing(global_link_num / xgmi_inst);
+
+ return RREG32_PCIE_EXT(addr);
+}
+
+int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev, int global_link_num)
+{
+ u32 xgmi_state_reg_val;
+
+ switch (amdgpu_ip_version(adev, XGMI_HWIP, 0)) {
+ case IP_VERSION(6, 4, 0):
+ xgmi_state_reg_val = xgmi_v6_4_get_link_status(adev, global_link_num);
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ if ((xgmi_state_reg_val & 0xFF) == XGMI_STATE_DISABLE)
+ return -ENOLINK;
+
+ if ((xgmi_state_reg_val & 0xFF) == XGMI_STATE_LS0)
+ return XGMI_LINK_ACTIVE;
+
+ return XGMI_LINK_INACTIVE;
+}
+
/**
* DOC: AMDGPU XGMI Support
*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
index 8cc7ab38db7c..d1282b4c6348 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_xgmi.h
@@ -84,5 +84,7 @@ int amdgpu_xgmi_reset_on_init(struct amdgpu_device *adev);
int amdgpu_xgmi_request_nps_change(struct amdgpu_device *adev,
struct amdgpu_hive_info *hive,
int req_nps_mode);
+int amdgpu_get_xgmi_link_status(struct amdgpu_device *adev,
+ int global_link_num);
#endif
diff --git a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
index 483a441b46aa..621aeca53880 100644
--- a/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
+++ b/drivers/gpu/drm/amd/amdgpu/df_v3_6.c
@@ -254,8 +254,8 @@ static void df_v3_6_sw_init(struct amdgpu_device *adev)
static void df_v3_6_sw_fini(struct amdgpu_device *adev)
{
-
- device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
+ if (adev->dev->kobj.sd)
+ device_remove_file(adev->dev, &dev_attr_df_cntr_avail);
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index fe7c48f2fb2a..da327ab48a57 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -4123,7 +4123,7 @@ static int gfx_v12_0_set_clockgating_state(void *handle,
if (amdgpu_sriov_vf(adev))
return 0;
- switch (adev->ip_versions[GC_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, GC_HWIP, 0)) {
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
gfx_v12_0_update_gfx_clock_gating(adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
index e2b3dda57030..54459254bd37 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -45,6 +45,8 @@ MODULE_FIRMWARE("amdgpu/gc_9_4_3_mec.bin");
MODULE_FIRMWARE("amdgpu/gc_9_4_4_mec.bin");
MODULE_FIRMWARE("amdgpu/gc_9_4_3_rlc.bin");
MODULE_FIRMWARE("amdgpu/gc_9_4_4_rlc.bin");
+MODULE_FIRMWARE("amdgpu/gc_9_4_3_sjt_mec.bin");
+MODULE_FIRMWARE("amdgpu/gc_9_4_4_sjt_mec.bin");
#define GFX9_MEC_HPD_SIZE 4096
#define RLCG_UCODE_LOADING_START_ADDRESS 0x00002000L
@@ -574,8 +576,12 @@ static int gfx_v9_4_3_init_cp_compute_microcode(struct amdgpu_device *adev,
{
int err;
- err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
- "amdgpu/%s_mec.bin", chip_name);
+ if (amdgpu_sriov_vf(adev))
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_sjt_mec.bin", chip_name);
+ else
+ err = amdgpu_ucode_request(adev, &adev->gfx.mec_fw,
+ "amdgpu/%s_mec.bin", chip_name);
if (err)
goto out;
amdgpu_gfx_cp_init_microcode(adev, AMDGPU_UCODE_ID_CP_MEC1);
diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
index 07f45f1a503a..b6016f11956e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c
@@ -87,9 +87,14 @@ static void gmc_v7_0_init_golden_registers(struct amdgpu_device *adev)
static void gmc_v7_0_mc_stop(struct amdgpu_device *adev)
{
+ struct amdgpu_ip_block *ip_block;
u32 blackout;
- gmc_v7_0_wait_for_idle((void *)adev);
+ ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GMC);
+ if (!ip_block)
+ return;
+
+ gmc_v7_0_wait_for_idle(ip_block);
blackout = RREG32(mmMC_SHARED_BLACKOUT_CNTL);
if (REG_GET_FIELD(blackout, MC_SHARED_BLACKOUT_CNTL, BLACKOUT_MODE) != 1) {
@@ -251,9 +256,14 @@ static void gmc_v7_0_vram_gtt_location(struct amdgpu_device *adev,
*/
static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
{
+ struct amdgpu_ip_block *ip_block;
u32 tmp;
int i, j;
+ ip_block = amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_GMC);
+ if (!ip_block)
+ return;
+
/* Initialize HDP */
for (i = 0, j = 0; i < 32; i++, j += 0x6) {
WREG32((0xb05 + j), 0x00000000);
@@ -264,7 +274,7 @@ static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
}
WREG32(mmHDP_REG_COHERENCY_FLUSH_CNTL, 0);
- if (gmc_v7_0_wait_for_idle((void *)adev))
+ if (gmc_v7_0_wait_for_idle(ip_block))
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
if (adev->mode_info.num_crtc) {
@@ -288,7 +298,7 @@ static void gmc_v7_0_mc_program(struct amdgpu_device *adev)
WREG32(mmMC_VM_AGP_BASE, 0);
WREG32(mmMC_VM_AGP_TOP, adev->gmc.agp_end >> 22);
WREG32(mmMC_VM_AGP_BOT, adev->gmc.agp_start >> 22);
- if (gmc_v7_0_wait_for_idle((void *)adev))
+ if (gmc_v7_0_wait_for_idle(ip_block))
dev_warn(adev->dev, "Wait for MC idle timedout !\n");
WREG32(mmBIF_FB_EN, BIF_FB_EN__FB_READ_EN_MASK | BIF_FB_EN__FB_WRITE_EN_MASK);
@@ -1183,7 +1193,7 @@ static int gmc_v7_0_soft_reset(struct amdgpu_ip_block *ip_block)
if (srbm_soft_reset) {
gmc_v7_0_mc_stop(adev);
- if (gmc_v7_0_wait_for_idle((void *)adev))
+ if (gmc_v7_0_wait_for_idle(ip_block))
dev_warn(adev->dev, "Wait for GMC idle timed out !\n");
tmp = RREG32(mmSRBM_SOFT_RESET);
diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c
index e019249883fb..194026e9be33 100644
--- a/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/hdp_v4_0.c
@@ -40,10 +40,12 @@
static void hdp_v4_0_flush_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
- if (!ring || !ring->funcs->emit_wreg)
+ if (!ring || !ring->funcs->emit_wreg) {
WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
- else
+ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
+ } else {
amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
+ }
}
static void hdp_v4_0_invalidate_hdp(struct amdgpu_device *adev,
@@ -54,11 +56,13 @@ static void hdp_v4_0_invalidate_hdp(struct amdgpu_device *adev,
amdgpu_ip_version(adev, HDP_HWIP, 0) == IP_VERSION(4, 4, 5))
return;
- if (!ring || !ring->funcs->emit_wreg)
+ if (!ring || !ring->funcs->emit_wreg) {
WREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE, 1);
- else
+ RREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE);
+ } else {
amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET(
HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1);
+ }
}
static void hdp_v4_0_query_ras_error_count(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c
index ed7facacf2fe..d3962d469088 100644
--- a/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/hdp_v5_0.c
@@ -31,10 +31,12 @@
static void hdp_v5_0_flush_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
- if (!ring || !ring->funcs->emit_wreg)
+ if (!ring || !ring->funcs->emit_wreg) {
WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
- else
+ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
+ } else {
amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
+ }
}
static void hdp_v5_0_invalidate_hdp(struct amdgpu_device *adev,
@@ -42,6 +44,7 @@ static void hdp_v5_0_invalidate_hdp(struct amdgpu_device *adev,
{
if (!ring || !ring->funcs->emit_wreg) {
WREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE, 1);
+ RREG32_SOC15_NO_KIQ(HDP, 0, mmHDP_READ_CACHE_INVALIDATE);
} else {
amdgpu_ring_emit_wreg(ring, SOC15_REG_OFFSET(
HDP, 0, mmHDP_READ_CACHE_INVALIDATE), 1);
diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c b/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c
index 29c3484ae1f1..f52552c5fa27 100644
--- a/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/hdp_v5_2.c
@@ -31,13 +31,15 @@
static void hdp_v5_2_flush_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
- if (!ring || !ring->funcs->emit_wreg)
+ if (!ring || !ring->funcs->emit_wreg) {
WREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2,
0);
- else
+ RREG32_NO_KIQ((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
+ } else {
amdgpu_ring_emit_wreg(ring,
(adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2,
0);
+ }
}
static void hdp_v5_2_update_mem_power_gating(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c
index 33736d361dd0..6948fe9956ce 100644
--- a/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/hdp_v6_0.c
@@ -34,10 +34,12 @@
static void hdp_v6_0_flush_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
- if (!ring || !ring->funcs->emit_wreg)
+ if (!ring || !ring->funcs->emit_wreg) {
WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
- else
+ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
+ } else {
amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
+ }
}
static void hdp_v6_0_update_clock_gating(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c b/drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c
index 1c99bb09e2a1..63820329f67e 100644
--- a/drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/hdp_v7_0.c
@@ -31,10 +31,12 @@
static void hdp_v7_0_flush_hdp(struct amdgpu_device *adev,
struct amdgpu_ring *ring)
{
- if (!ring || !ring->funcs->emit_wreg)
+ if (!ring || !ring->funcs->emit_wreg) {
WREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
- else
+ RREG32((adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2);
+ } else {
amdgpu_ring_emit_wreg(ring, (adev->rmmio_remap.reg_offset + KFD_MMIO_REMAP_HDP_MEM_FLUSH_CNTL) >> 2, 0);
+ }
}
static void hdp_v7_0_update_clock_gating(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
index d6823fb45d32..6e29b69894a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
@@ -150,7 +150,7 @@ static int jpeg_v2_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index 5063a38801d6..9ac421486f05 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -211,7 +211,7 @@ static int jpeg_v2_5_hw_fini(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
int i;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
if (adev->jpeg.harvest_config & (1 << i))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
index 10adbb7cbf53..e0df6800502c 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
@@ -164,7 +164,7 @@ static int jpeg_v3_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, mmUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index 193dfac5dc76..eca1963c33b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -202,7 +202,7 @@ static int jpeg_v4_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (!amdgpu_sriov_vf(adev)) {
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
index b48e2412e6cc..1d9e3b101c3a 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
@@ -227,7 +227,7 @@ static int jpeg_v4_0_5_hw_fini(struct amdgpu_ip_block *ip_block)
struct amdgpu_device *adev = ip_block->adev;
int i;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
for (i = 0; i < adev->jpeg.num_jpeg_inst; ++i) {
if (adev->jpeg.harvest_config & (1 << i))
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
index 686f9605239d..58fb1e5fa89c 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
@@ -168,7 +168,7 @@ static int jpeg_v5_0_0_hw_fini(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
- cancel_delayed_work_sync(&adev->vcn.idle_work);
+ cancel_delayed_work_sync(&adev->jpeg.idle_work);
if (adev->jpeg.cur_state != AMD_PG_STATE_GATE &&
RREG32_SOC15(JPEG, 0, regUVD_JRBC_STATUS))
diff --git a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c
index 0fbc3be81f14..f2ab5001b492 100644
--- a/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/mmhub_v4_1_0.c
@@ -108,7 +108,7 @@ mmhub_v4_1_0_print_l2_protection_fault_status(struct amdgpu_device *adev,
dev_err(adev->dev,
"MMVM_L2_PROTECTION_FAULT_STATUS_LO32:0x%08X\n",
status);
- switch (adev->ip_versions[MMHUB_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, MMHUB_HWIP, 0)) {
case IP_VERSION(4, 1, 0):
mmhub_cid = mmhub_client_ids_v4_1_0[cid][rw];
break;
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c
index b1b57dcc5a73..d1032e9992b4 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_0.c
@@ -271,8 +271,19 @@ const struct nbio_hdp_flush_reg nbio_v7_0_hdp_flush_reg = {
.ref_and_mask_sdma1 = GPU_HDP_FLUSH_DONE__SDMA1_MASK,
};
+#define regRCC_DEV0_EPF6_STRAP4 0xd304
+#define regRCC_DEV0_EPF6_STRAP4_BASE_IDX 5
+
static void nbio_v7_0_init_registers(struct amdgpu_device *adev)
{
+ uint32_t data;
+
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
+ case IP_VERSION(2, 5, 0):
+ data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF6_STRAP4) & ~BIT(23);
+ WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF6_STRAP4, data);
+ break;
+ }
}
#define MMIO_REG_HOLE_OFFSET (0x80000 - PAGE_SIZE)
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
index 7a9adfda5814..41421da63a08 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_11.c
@@ -275,6 +275,15 @@ static void nbio_v7_11_init_registers(struct amdgpu_device *adev)
if (def != data)
WREG32_SOC15(NBIO, 0, regBIF_BIF256_CI256_RC3X4_USB4_PCIE_MST_CTRL_3, data);
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
+ case IP_VERSION(7, 11, 0):
+ case IP_VERSION(7, 11, 1):
+ case IP_VERSION(7, 11, 2):
+ case IP_VERSION(7, 11, 3):
+ data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4) & ~BIT(23);
+ WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4, data);
+ break;
+ }
}
static void nbio_v7_11_update_medium_grain_clock_gating(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c b/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
index 1ac730328516..3fb6d2aa7e3b 100644
--- a/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
+++ b/drivers/gpu/drm/amd/amdgpu/nbio_v7_7.c
@@ -247,7 +247,7 @@ static void nbio_v7_7_init_registers(struct amdgpu_device *adev)
if (def != data)
WREG32_SOC15(NBIO, 0, regBIF0_PCIE_MST_CTRL_3, data);
- switch (adev->ip_versions[NBIO_HWIP][0]) {
+ switch (amdgpu_ip_version(adev, NBIO_HWIP, 0)) {
case IP_VERSION(7, 7, 0):
data = RREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4) & ~BIT(23);
WREG32_SOC15(NBIO, 0, regRCC_DEV0_EPF5_STRAP4, data);
diff --git a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
index 9b01e074af47..2594467bdd87 100644
--- a/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
+++ b/drivers/gpu/drm/amd/amdgpu/sienna_cichlid.c
@@ -220,6 +220,7 @@ sienna_cichlid_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
int r;
struct amdgpu_device *tmp_adev = (struct amdgpu_device *)reset_ctl->handle;
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_RESET_RECOVERY);
dev_info(tmp_adev->dev,
"GPU reset succeeded, trying to resume\n");
r = sienna_cichlid_mode2_restore_ip(tmp_adev);
@@ -237,6 +238,7 @@ sienna_cichlid_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_DEFAULT);
r = amdgpu_ib_ring_tests(tmp_adev);
if (r) {
dev_err(tmp_adev->dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c b/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
index e70ebad3f9fa..70569ea906bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
+++ b/drivers/gpu/drm/amd/amdgpu/smu_v13_0_10.c
@@ -221,6 +221,7 @@ smu_v13_0_10_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
int r;
struct amdgpu_device *tmp_adev = (struct amdgpu_device *)reset_ctl->handle;
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_RESET_RECOVERY);
dev_info(tmp_adev->dev,
"GPU reset succeeded, trying to resume\n");
r = smu_v13_0_10_mode2_restore_ip(tmp_adev);
@@ -234,6 +235,7 @@ smu_v13_0_10_mode2_restore_hwcontext(struct amdgpu_reset_control *reset_ctl,
amdgpu_irq_gpu_reset_resume_helper(tmp_adev);
+ amdgpu_set_init_level(tmp_adev, AMDGPU_INIT_LEVEL_DEFAULT);
r = amdgpu_ib_ring_tests(tmp_adev);
if (r) {
dev_err(tmp_adev->dev,
diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
index 079131aeb2f7..3c8ab8698af8 100644
--- a/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/uvd_v7_0.c
@@ -1288,7 +1288,7 @@ static int uvd_v7_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
struct amdgpu_job *job,
struct amdgpu_ib *ib)
{
- struct amdgpu_ring *ring = to_amdgpu_ring(job->base.sched);
+ struct amdgpu_ring *ring = amdgpu_job_ring(job);
unsigned i;
/* No patching necessary for the first instance */
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 5512259cac79..fcc8511e91ee 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -225,6 +225,10 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
vcn_v4_0_fw_shared_init(adev, i);
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vcn.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
+
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
@@ -247,6 +251,10 @@ static int vcn_v4_0_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.ip_dump = ptr;
}
+ r = amdgpu_vcn_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -284,6 +292,7 @@ static int vcn_v4_0_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_vcn_sysfs_reset_mask_fini(adev);
r = amdgpu_vcn_sw_fini(adev);
kfree(adev->vcn.ip_dump);
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index cf808a153fce..3f69b9b2bcd0 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -123,6 +123,20 @@ static int vcn_v4_0_3_early_init(struct amdgpu_ip_block *ip_block)
return amdgpu_vcn_early_init(adev);
}
+static int vcn_v4_0_3_fw_shared_init(struct amdgpu_device *adev, int inst_idx)
+{
+ struct amdgpu_vcn4_fw_shared *fw_shared;
+
+ fw_shared = adev->vcn.inst[inst_idx].fw_shared.cpu_addr;
+ fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
+ fw_shared->sq.is_enabled = 1;
+
+ if (amdgpu_vcnfw_log)
+ amdgpu_vcn_fwlog_init(&adev->vcn.inst[inst_idx]);
+
+ return 0;
+}
+
/**
* vcn_v4_0_3_sw_init - sw init for VCN block
*
@@ -155,8 +169,6 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
return r;
for (i = 0; i < adev->vcn.num_vcn_inst; i++) {
- volatile struct amdgpu_vcn4_fw_shared *fw_shared;
-
vcn_inst = GET_INST(VCN, i);
ring = &adev->vcn.inst[i].ring_enc[0];
@@ -179,14 +191,13 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
if (r)
return r;
- fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
- fw_shared->present_flag_0 = cpu_to_le32(AMDGPU_FW_SHARED_FLAG_0_UNIFIED_QUEUE);
- fw_shared->sq.is_enabled = true;
-
- if (amdgpu_vcnfw_log)
- amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
+ vcn_v4_0_3_fw_shared_init(adev, i);
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vcn.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
+
if (amdgpu_sriov_vf(adev)) {
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
@@ -213,6 +224,10 @@ static int vcn_v4_0_3_sw_init(struct amdgpu_ip_block *ip_block)
adev->vcn.ip_dump = ptr;
}
+ r = amdgpu_vcn_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -246,6 +261,7 @@ static int vcn_v4_0_3_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_vcn_sysfs_reset_mask_fini(adev);
r = amdgpu_vcn_sw_fini(adev);
kfree(adev->vcn.ip_dump);
@@ -280,6 +296,8 @@ static int vcn_v4_0_3_hw_init(struct amdgpu_ip_block *ip_block)
}
} else {
for (i = 0; i < adev->vcn.num_vcn_inst; ++i) {
+ struct amdgpu_vcn4_fw_shared *fw_shared;
+
vcn_inst = GET_INST(VCN, i);
ring = &adev->vcn.inst[i].ring_enc[0];
@@ -303,6 +321,11 @@ static int vcn_v4_0_3_hw_init(struct amdgpu_ip_block *ip_block)
regVCN_RB1_DB_CTRL);
}
+ /* Re-init fw_shared when RAS fatal error occurred */
+ fw_shared = adev->vcn.inst[i].fw_shared.cpu_addr;
+ if (!fw_shared->sq.is_enabled)
+ vcn_v4_0_3_fw_shared_init(adev, i);
+
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index fe2cc1a80c13..bd3d2bbdc16b 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -170,6 +170,10 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
amdgpu_vcn_fwlog_init(&adev->vcn.inst[i]);
}
+ /* TODO: Add queue reset mask when FW fully supports it */
+ adev->vcn.supported_reset =
+ amdgpu_get_soft_full_reset_mask(&adev->vcn.inst[0].ring_enc[0]);
+
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
adev->vcn.pause_dpg_mode = vcn_v5_0_0_pause_dpg_mode;
@@ -181,6 +185,11 @@ static int vcn_v5_0_0_sw_init(struct amdgpu_ip_block *ip_block)
} else {
adev->vcn.ip_dump = ptr;
}
+
+ r = amdgpu_vcn_sysfs_reset_mask_init(adev);
+ if (r)
+ return r;
+
return 0;
}
@@ -215,6 +224,7 @@ static int vcn_v5_0_0_sw_fini(struct amdgpu_ip_block *ip_block)
if (r)
return r;
+ amdgpu_vcn_sysfs_reset_mask_fini(adev);
r = amdgpu_vcn_sw_fini(adev);
kfree(adev->vcn.ip_dump);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
index 723f1220e1cc..e5324c5bc6c7 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_crat.c
@@ -1423,6 +1423,7 @@ err:
static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
+ bool cache_line_size_missing,
struct kfd_gpu_cache_info *pcache_info)
{
struct amdgpu_device *adev = kdev->adev;
@@ -1437,6 +1438,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_tcp_per_wpg / 2;
pcache_info[i].cache_line_size = adev->gfx.config.gc_tcp_cache_line_size;
+ if (cache_line_size_missing && !pcache_info[i].cache_line_size)
+ pcache_info[i].cache_line_size = 128;
i++;
}
/* Scalar L1 Instruction Cache per SQC */
@@ -1449,6 +1452,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_sqc_per_wgp * 2;
pcache_info[i].cache_line_size = adev->gfx.config.gc_instruction_cache_line_size;
+ if (cache_line_size_missing && !pcache_info[i].cache_line_size)
+ pcache_info[i].cache_line_size = 128;
i++;
}
/* Scalar L1 Data Cache per SQC */
@@ -1460,6 +1465,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = adev->gfx.config.gc_num_sqc_per_wgp * 2;
pcache_info[i].cache_line_size = adev->gfx.config.gc_scalar_data_cache_line_size;
+ if (cache_line_size_missing && !pcache_info[i].cache_line_size)
+ pcache_info[i].cache_line_size = 64;
i++;
}
/* GL1 Data Cache per SA */
@@ -1472,7 +1479,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
- pcache_info[i].cache_line_size = 0;
+ if (cache_line_size_missing)
+ pcache_info[i].cache_line_size = 128;
i++;
}
/* L2 Data Cache per GPU (Total Tex Cache) */
@@ -1484,6 +1492,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
pcache_info[i].cache_line_size = adev->gfx.config.gc_tcc_cache_line_size;
+ if (cache_line_size_missing && !pcache_info[i].cache_line_size)
+ pcache_info[i].cache_line_size = 128;
i++;
}
/* L3 Data Cache per GPU */
@@ -1494,7 +1504,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config(struct kfd_dev *kdev,
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
pcache_info[i].num_cu_shared = adev->gfx.config.max_cu_per_sh;
- pcache_info[i].cache_line_size = 0;
+ pcache_info[i].cache_line_size = 64;
i++;
}
return i;
@@ -1510,6 +1520,8 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev,
if (adev->gfx.config.gc_tcp_size_per_cu) {
pcache_info[i].cache_size = adev->gfx.config.gc_tcp_size_per_cu;
pcache_info[i].cache_level = 1;
+ /* Cacheline size not available in IP discovery for gc943,gc944 */
+ pcache_info[i].cache_line_size = 128;
pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
@@ -1521,6 +1533,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev,
pcache_info[i].cache_size =
adev->gfx.config.gc_l1_instruction_cache_size_per_sqc;
pcache_info[i].cache_level = 1;
+ pcache_info[i].cache_line_size = 64;
pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_INST_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
@@ -1531,6 +1544,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev,
if (adev->gfx.config.gc_l1_data_cache_size_per_sqc) {
pcache_info[i].cache_size = adev->gfx.config.gc_l1_data_cache_size_per_sqc;
pcache_info[i].cache_level = 1;
+ pcache_info[i].cache_line_size = 64;
pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
@@ -1541,6 +1555,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev,
if (adev->gfx.config.gc_tcc_size) {
pcache_info[i].cache_size = adev->gfx.config.gc_tcc_size;
pcache_info[i].cache_level = 2;
+ pcache_info[i].cache_line_size = 128;
pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
@@ -1551,6 +1566,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev,
if (adev->gmc.mall_size) {
pcache_info[i].cache_size = adev->gmc.mall_size / 1024;
pcache_info[i].cache_level = 3;
+ pcache_info[i].cache_line_size = 64;
pcache_info[i].flags = (CRAT_CACHE_FLAGS_ENABLED |
CRAT_CACHE_FLAGS_DATA_CACHE |
CRAT_CACHE_FLAGS_SIMD_CACHE);
@@ -1563,6 +1579,7 @@ static int kfd_fill_gpu_cache_info_from_gfx_config_v2(struct kfd_dev *kdev,
int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pcache_info)
{
int num_of_cache_types = 0;
+ bool cache_line_size_missing = false;
switch (kdev->adev->asic_type) {
case CHIP_KAVERI:
@@ -1686,10 +1703,17 @@ int kfd_get_gpu_cache_info(struct kfd_node *kdev, struct kfd_gpu_cache_info **pc
case IP_VERSION(11, 5, 0):
case IP_VERSION(11, 5, 1):
case IP_VERSION(11, 5, 2):
+ /* Cacheline size not available in IP discovery for gc11.
+ * kfd_fill_gpu_cache_info_from_gfx_config to hard code it
+ */
+ cache_line_size_missing = true;
+ fallthrough;
case IP_VERSION(12, 0, 0):
case IP_VERSION(12, 0, 1):
num_of_cache_types =
- kfd_fill_gpu_cache_info_from_gfx_config(kdev->kfd, *pcache_info);
+ kfd_fill_gpu_cache_info_from_gfx_config(kdev->kfd,
+ cache_line_size_missing,
+ *pcache_info);
break;
default:
*pcache_info = dummy_cache_info;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
index 956198da7859..9b51dd75fefc 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c
@@ -235,6 +235,9 @@ static void kfd_device_info_init(struct kfd_dev *kfd,
*/
kfd->device_info.needs_pci_atomics = true;
kfd->device_info.no_atomic_fw_version = kfd->adev->gfx.rs64_enable ? 509 : 0;
+ } else if (gc_version < IP_VERSION(13, 0, 0)) {
+ kfd->device_info.needs_pci_atomics = true;
+ kfd->device_info.no_atomic_fw_version = 2090;
} else {
kfd->device_info.needs_pci_atomics = true;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
index c79fe9069e22..16b5daaa272f 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c
@@ -207,6 +207,21 @@ static int add_queue_mes(struct device_queue_manager *dqm, struct queue *q,
if (!down_read_trylock(&adev->reset_domain->sem))
return -EIO;
+ if (!pdd->proc_ctx_cpu_ptr) {
+ r = amdgpu_amdkfd_alloc_gtt_mem(adev,
+ AMDGPU_MES_PROC_CTX_SIZE,
+ &pdd->proc_ctx_bo,
+ &pdd->proc_ctx_gpu_addr,
+ &pdd->proc_ctx_cpu_ptr,
+ false);
+ if (r) {
+ dev_err(adev->dev,
+ "failed to allocate process context bo\n");
+ return r;
+ }
+ memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE);
+ }
+
memset(&queue_input, 0x0, sizeof(struct mes_add_queue_input));
queue_input.process_id = qpd->pqm->process->pasid;
queue_input.page_table_base_addr = qpd->page_table_base;
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
index 4843dcb9a5f7..2b0a830f5b29 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_kernel_queue.c
@@ -125,7 +125,7 @@ static bool kq_initialize(struct kernel_queue *kq, struct kfd_node *dev,
memset(kq->pq_kernel_addr, 0, queue_size);
memset(kq->rptr_kernel, 0, sizeof(*kq->rptr_kernel));
- memset(kq->wptr_kernel, 0, sizeof(*kq->wptr_kernel));
+ memset(kq->wptr_kernel, 0, dev->kfd->device_info.doorbell_size);
prop.queue_size = queue_size;
prop.is_interop = false;
@@ -306,12 +306,17 @@ int kq_submit_packet(struct kernel_queue *kq)
if (amdgpu_amdkfd_is_fed(kq->dev->adev))
return -EIO;
+ /* Make sure ring buffer is updated before wptr updated */
+ mb();
+
if (kq->dev->kfd->device_info.doorbell_size == 8) {
*kq->wptr64_kernel = kq->pending_wptr64;
+ mb(); /* Make sure wptr updated before ring doorbell */
write_kernel_doorbell64(kq->queue->properties.doorbell_ptr,
kq->pending_wptr64);
} else {
*kq->wptr_kernel = kq->pending_wptr;
+ mb(); /* Make sure wptr updated before ring doorbell */
write_kernel_doorbell(kq->queue->properties.doorbell_ptr,
kq->pending_wptr);
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
index eacfeb32f35d..4b275937d05e 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_migrate.c
@@ -306,7 +306,7 @@ svm_migrate_copy_to_vram(struct kfd_node *node, struct svm_range *prange,
spage = migrate_pfn_to_page(migrate->src[i]);
if (spage && !is_zone_device_page(spage)) {
src[i] = dma_map_page(dev, spage, 0, PAGE_SIZE,
- DMA_TO_DEVICE);
+ DMA_BIDIRECTIONAL);
r = dma_mapping_error(dev, src[i]);
if (r) {
dev_err(dev, "%s: fail %d dma_map_page\n",
@@ -629,7 +629,7 @@ svm_migrate_copy_to_ram(struct amdgpu_device *adev, struct svm_range *prange,
goto out_oom;
}
- dst[i] = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_FROM_DEVICE);
+ dst[i] = dma_map_page(dev, dpage, 0, PAGE_SIZE, DMA_BIDIRECTIONAL);
r = dma_mapping_error(dev, dst[i]);
if (r) {
dev_err(adev->dev, "%s: fail %d dma_map_page\n", __func__, r);
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
index 87cd52cf4ee9..d0ee173acf82 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c
@@ -1076,7 +1076,8 @@ static void kfd_process_destroy_pdds(struct kfd_process *p)
kfd_free_process_doorbells(pdd->dev->kfd, pdd);
- if (pdd->dev->kfd->shared_resources.enable_mes)
+ if (pdd->dev->kfd->shared_resources.enable_mes &&
+ pdd->proc_ctx_cpu_ptr)
amdgpu_amdkfd_free_gtt_mem(pdd->dev->adev,
&pdd->proc_ctx_bo);
/*
@@ -1608,7 +1609,6 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev,
struct kfd_process *p)
{
struct kfd_process_device *pdd = NULL;
- int retval = 0;
if (WARN_ON_ONCE(p->n_pdds >= MAX_GPU_INSTANCE))
return NULL;
@@ -1632,21 +1632,6 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev,
pdd->user_gpu_id = dev->id;
atomic64_set(&pdd->evict_duration_counter, 0);
- if (dev->kfd->shared_resources.enable_mes) {
- retval = amdgpu_amdkfd_alloc_gtt_mem(dev->adev,
- AMDGPU_MES_PROC_CTX_SIZE,
- &pdd->proc_ctx_bo,
- &pdd->proc_ctx_gpu_addr,
- &pdd->proc_ctx_cpu_ptr,
- false);
- if (retval) {
- dev_err(dev->adev->dev,
- "failed to allocate process context bo\n");
- goto err_free_pdd;
- }
- memset(pdd->proc_ctx_cpu_ptr, 0, AMDGPU_MES_PROC_CTX_SIZE);
- }
-
p->pdds[p->n_pdds++] = pdd;
if (kfd_dbg_is_per_vmid_supported(pdd->dev))
pdd->spi_dbg_override = pdd->dev->kfd2kgd->disable_debug_trap(
@@ -1658,10 +1643,6 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_node *dev,
idr_init(&pdd->alloc_idr);
return pdd;
-
-err_free_pdd:
- kfree(pdd);
- return NULL;
}
/**
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
index c76db22a1000..59b92d66e958 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_process_queue_manager.c
@@ -212,13 +212,17 @@ static void pqm_clean_queue_resource(struct process_queue_manager *pqm,
void pqm_uninit(struct process_queue_manager *pqm)
{
struct process_queue_node *pqn, *next;
- struct kfd_process_device *pdd;
list_for_each_entry_safe(pqn, next, &pqm->queues, process_queue_list) {
if (pqn->q) {
- pdd = kfd_get_process_device_data(pqn->q->device, pqm->process);
- kfd_queue_unref_bo_vas(pdd, &pqn->q->properties);
- kfd_queue_release_buffers(pdd, &pqn->q->properties);
+ struct kfd_process_device *pdd = kfd_get_process_device_data(pqn->q->device,
+ pqm->process);
+ if (pdd) {
+ kfd_queue_unref_bo_vas(pdd, &pqn->q->properties);
+ kfd_queue_release_buffers(pdd, &pqn->q->properties);
+ } else {
+ WARN_ON(!pdd);
+ }
pqm_clean_queue_resource(pqm, pqn);
}
diff --git a/drivers/gpu/drm/amd/display/Kconfig b/drivers/gpu/drm/amd/display/Kconfig
index df17e79c45c7..11e3f2f3b174 100644
--- a/drivers/gpu/drm/amd/display/Kconfig
+++ b/drivers/gpu/drm/amd/display/Kconfig
@@ -7,20 +7,21 @@ menu "Display Engine Configuration"
config DRM_AMD_DC
bool "AMD DC - Enable new display engine"
default y
- depends on BROKEN || !CC_IS_CLANG || ARM64 || RISCV || SPARC64 || X86_64
+ depends on BROKEN || !CC_IS_CLANG || ARM64 || LOONGARCH || RISCV || SPARC64 || X86_64
select SND_HDA_COMPONENT if SND_HDA_CORE
# !CC_IS_CLANG: https://github.com/ClangBuiltLinux/linux/issues/1752
- select DRM_AMD_DC_FP if ARCH_HAS_KERNEL_FPU_SUPPORT && !(CC_IS_CLANG && (ARM64 || RISCV))
+ select DRM_AMD_DC_FP if ARCH_HAS_KERNEL_FPU_SUPPORT && !(CC_IS_CLANG && (ARM64 || LOONGARCH || RISCV))
help
Choose this option if you want to use the new display engine
support for AMDGPU. This adds required support for Vega and
Raven ASICs.
- calculate_bandwidth() is presently broken on all !(X86_64 || SPARC64 || ARM64)
- architectures built with Clang (all released versions), whereby the stack
- frame gets blown up to well over 5k. This would cause an immediate kernel
- panic on most architectures. We'll revert this when the following bug report
- has been resolved: https://github.com/llvm/llvm-project/issues/41896.
+ calculate_bandwidth() is presently broken on all !(X86_64 || SPARC64 ||
+ ARM64 || LOONGARCH || RISCV) architectures built with Clang (all released
+ versions), whereby the stack frame gets blown up to well over 5k. This
+ would cause an immediate kernel panic on most architectures. We'll revert
+ this when the following bug report has been resolved:
+ https://github.com/llvm/llvm-project/issues/41896.
config DRM_AMD_DC_FP
def_bool n
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
index f0a6816709ca..48be917e7bc5 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
@@ -3481,6 +3481,8 @@ static void update_connector_ext_caps(struct amdgpu_dm_connector *aconnector)
caps->aux_support = false;
else if (amdgpu_backlight == 1)
caps->aux_support = true;
+ if (caps->aux_support)
+ aconnector->dc_link->backlight_control_type = BACKLIGHT_CONTROL_AMD_AUX;
luminance_range = &conn_base->display_info.luminance_range;
diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
index b0fea0856866..6cbbb71d752b 100644
--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_helpers.c
@@ -907,14 +907,14 @@ dm_helpers_probe_acpi_edid(void *data, u8 *buf, unsigned int block, size_t len)
struct drm_connector *connector = data;
struct acpi_device *acpidev = ACPI_COMPANION(connector->dev->dev);
unsigned char start = block * EDID_LENGTH;
- void *edid;
+ struct edid *edid;
int r;
if (!acpidev)
return -ENODEV;
/* fetch the entire edid from BIOS */
- r = acpi_video_get_edid(acpidev, ACPI_VIDEO_DISPLAY_LCD, -1, &edid);
+ r = acpi_video_get_edid(acpidev, ACPI_VIDEO_DISPLAY_LCD, -1, (void *)&edid);
if (r < 0) {
drm_dbg(connector->dev, "Failed to get EDID from ACPI: %d\n", r);
return r;
@@ -924,7 +924,14 @@ dm_helpers_probe_acpi_edid(void *data, u8 *buf, unsigned int block, size_t len)
goto cleanup;
}
- memcpy(buf, edid + start, len);
+ /* sanity check */
+ if (edid->revision < 4 || !(edid->input & DRM_EDID_INPUT_DIGITAL) ||
+ (edid->input & DRM_EDID_DIGITAL_TYPE_MASK) == DRM_EDID_DIGITAL_TYPE_UNDEF) {
+ r = -EINVAL;
+ goto cleanup;
+ }
+
+ memcpy(buf, (void *)edid + start, len);
r = 0;
cleanup:
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc.c b/drivers/gpu/drm/amd/display/dc/core/dc.c
index 7872c6cabb14..49fe7dcf9372 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc.c
@@ -3141,7 +3141,10 @@ static void restore_planes_and_stream_state(
return;
for (i = 0; i < status->plane_count; i++) {
+ /* refcount will always be valid, restore everything else */
+ struct kref refcount = status->plane_states[i]->refcount;
*status->plane_states[i] = scratch->plane_states[i];
+ status->plane_states[i]->refcount = refcount;
}
*stream = scratch->stream_state;
}
@@ -6097,12 +6100,30 @@ struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state
{
struct dc_power_profile profile = { 0 };
- if (!context || !context->clk_mgr || !context->clk_mgr->ctx || !context->clk_mgr->ctx->dc)
+ profile.power_level = !context->bw_ctx.bw.dcn.clk.p_state_change_support;
+ if (!context->clk_mgr || !context->clk_mgr->ctx || !context->clk_mgr->ctx->dc)
return profile;
struct dc *dc = context->clk_mgr->ctx->dc;
-
if (dc->res_pool->funcs->get_power_profile)
profile.power_level = dc->res_pool->funcs->get_power_profile(context);
return profile;
}
+
+/*
+ **********************************************************************************
+ * dc_get_det_buffer_size_from_state() - extracts detile buffer size from dc state
+ *
+ * Called when DM wants to log detile buffer size from dc_state
+ *
+ **********************************************************************************
+ */
+unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context)
+{
+ struct dc *dc = context->clk_mgr->ctx->dc;
+
+ if (dc->res_pool->funcs->get_det_buffer_size)
+ return dc->res_pool->funcs->get_det_buffer_size(context);
+ else
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
index 0419ee7f22a5..252af83e34a5 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_hw_sequencer.c
@@ -898,6 +898,9 @@ void hwss_setup_dpp(union block_sequence_params *params)
struct dpp *dpp = pipe_ctx->plane_res.dpp;
struct dc_plane_state *plane_state = pipe_ctx->plane_state;
+ if (!plane_state)
+ return;
+
if (dpp && dpp->funcs->dpp_setup) {
// program the input csc
dpp->funcs->dpp_setup(dpp,
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
index 33125b95c3a1..626f75b6ad00 100644
--- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c
@@ -1501,6 +1501,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
res = spl_calculate_scaler_params(spl_in, spl_out);
// Convert respective out params from SPL to scaler data
translate_SPL_out_params_to_pipe_ctx(pipe_ctx, spl_out);
+
+ /* Ignore scaler failure if pipe context plane is phantom plane */
+ if (!res && plane_state->is_phantom)
+ res = true;
} else {
#endif
/* depends on h_active */
@@ -1571,6 +1575,10 @@ bool resource_build_scaling_params(struct pipe_ctx *pipe_ctx)
&plane_state->scaling_quality);
}
+ /* Ignore scaler failure if pipe context plane is phantom plane */
+ if (!res && plane_state->is_phantom)
+ res = true;
+
if (res && (pipe_ctx->plane_res.scl_data.taps.v_taps != temp.v_taps ||
pipe_ctx->plane_res.scl_data.taps.h_taps != temp.h_taps ||
pipe_ctx->plane_res.scl_data.taps.v_taps_c != temp.v_taps_c ||
@@ -2086,7 +2094,8 @@ int resource_get_odm_slice_dst_width(struct pipe_ctx *otg_master,
count = resource_get_odm_slice_count(otg_master);
h_active = timing->h_addressable +
timing->h_border_left +
- timing->h_border_right;
+ timing->h_border_right +
+ otg_master->hblank_borrow;
width = h_active / count;
if (otg_master->stream_res.tg)
@@ -4019,6 +4028,41 @@ fail:
}
/**
+ * decide_hblank_borrow - Decides the horizontal blanking borrow value for a given pipe context.
+ * @pipe_ctx: Pointer to the pipe context structure.
+ *
+ * This function calculates the horizontal blanking borrow value for a given pipe context based on the
+ * display stream compression (DSC) configuration. If the horizontal active pixels (hactive) are less
+ * than the total width of the DSC slices, it sets the hblank_borrow value to the difference. If the
+ * total horizontal timing minus the hblank_borrow value is less than 32, it resets the hblank_borrow
+ * value to 0.
+ */
+static void decide_hblank_borrow(struct pipe_ctx *pipe_ctx)
+{
+ uint32_t hactive;
+ uint32_t ceil_slice_width;
+ struct dc_stream_state *stream = NULL;
+
+ if (!pipe_ctx)
+ return;
+
+ stream = pipe_ctx->stream;
+
+ if (stream->timing.flags.DSC) {
+ hactive = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
+
+ /* Assume if determined slices does not divide Hactive evenly, Hborrow is needed for padding*/
+ if (hactive % stream->timing.dsc_cfg.num_slices_h != 0) {
+ ceil_slice_width = (hactive / stream->timing.dsc_cfg.num_slices_h) + 1;
+ pipe_ctx->hblank_borrow = ceil_slice_width * stream->timing.dsc_cfg.num_slices_h - hactive;
+
+ if (stream->timing.h_total - hactive - pipe_ctx->hblank_borrow < 32)
+ pipe_ctx->hblank_borrow = 0;
+ }
+ }
+}
+
+/**
* dc_validate_global_state() - Determine if hardware can support a given state
*
* @dc: dc struct for this driver
@@ -4056,6 +4100,10 @@ enum dc_status dc_validate_global_state(
if (pipe_ctx->stream != stream)
continue;
+ /* Decide whether hblank borrow is needed and save it in pipe_ctx */
+ if (dc->debug.enable_hblank_borrow)
+ decide_hblank_borrow(pipe_ctx);
+
if (dc->res_pool->funcs->patch_unknown_plane_state &&
pipe_ctx->plane_state &&
pipe_ctx->plane_state->tiling_info.gfx9.swizzle == DC_SW_UNKNOWN) {
diff --git a/drivers/gpu/drm/amd/display/dc/dc.h b/drivers/gpu/drm/amd/display/dc/dc.h
index e143fab00a86..e9b9126c0401 100644
--- a/drivers/gpu/drm/amd/display/dc/dc.h
+++ b/drivers/gpu/drm/amd/display/dc/dc.h
@@ -55,7 +55,7 @@ struct aux_payload;
struct set_config_cmd_payload;
struct dmub_notification;
-#define DC_VER "3.2.309"
+#define DC_VER "3.2.310"
#define MAX_SURFACES 3
#define MAX_PLANES 6
@@ -290,6 +290,7 @@ struct dc_caps {
uint16_t subvp_vertical_int_margin_us;
bool seamless_odm;
uint32_t max_v_total;
+ bool vtotal_limited_by_fp2;
uint32_t max_disp_clock_khz_at_vmin;
uint8_t subvp_drr_vblank_start_margin_us;
bool cursor_not_scaled;
@@ -1068,6 +1069,7 @@ struct dc_debug_options {
unsigned int scale_to_sharpness_policy;
bool skip_full_updated_if_possible;
unsigned int enable_oled_edp_power_up_opt;
+ bool enable_hblank_borrow;
};
@@ -2550,6 +2552,8 @@ struct dc_power_profile {
struct dc_power_profile dc_get_power_profile_for_dc_state(const struct dc_state *context);
+unsigned int dc_get_det_buffer_size_from_state(const struct dc_state *context);
+
/* DSC Interfaces */
#include "dc_dsc.h"
diff --git a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
index c8d8e335fa37..0e310fd48b5c 100644
--- a/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
+++ b/drivers/gpu/drm/amd/display/dc/dc_spl_translate.c
@@ -120,7 +120,7 @@ void translate_SPL_in_params_from_pipe_ctx(struct pipe_ctx *pipe_ctx, struct spl
spl_in->odm_slice_index = resource_get_odm_slice_index(pipe_ctx);
// Make spl input basic out info output_size width point to stream h active
spl_in->basic_out.output_size.width =
- stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
+ stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right + pipe_ctx->hblank_borrow;
// Make spl input basic out info output_size height point to v active
spl_in->basic_out.output_size.height =
stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
diff --git a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
index 838d72eaa87f..b363f5360818 100644
--- a/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
+++ b/drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c
@@ -1392,10 +1392,10 @@ static void dccg35_set_dtbclk_dto(
/* The recommended programming sequence to enable DTBCLK DTO to generate
* valid pixel HPO DPSTREAM ENCODER, specifies that DTO source select should
- * be set only after DTO is enabled
+ * be set only after DTO is enabled.
+ * PIPEx_DTO_SRC_SEL should not be programmed during DTBCLK update since OTG may still be on, and the
+ * programming is handled in program_pix_clk() regardless, so it can be removed from here.
*/
- REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
- PIPE_DTO_SRC_SEL[params->otg_inst], 2);
} else {
switch (params->otg_inst) {
case 0:
@@ -1412,9 +1412,12 @@ static void dccg35_set_dtbclk_dto(
break;
}
- REG_UPDATE_2(OTG_PIXEL_RATE_CNTL[params->otg_inst],
- DTBCLK_DTO_ENABLE[params->otg_inst], 0,
- PIPE_DTO_SRC_SEL[params->otg_inst], params->is_hdmi ? 0 : 1);
+ /**
+ * PIPEx_DTO_SRC_SEL should not be programmed during DTBCLK update since OTG may still be on, and the
+ * programming is handled in program_pix_clk() regardless, so it can be removed from here.
+ */
+ REG_UPDATE(OTG_PIXEL_RATE_CNTL[params->otg_inst],
+ DTBCLK_DTO_ENABLE[params->otg_inst], 0);
REG_WRITE(DTBCLK_DTO_MODULO[params->otg_inst], 0);
REG_WRITE(DTBCLK_DTO_PHASE[params->otg_inst], 0);
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
index d851c081e376..8dabb1ac0b68 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/display_mode_core.c
@@ -1222,6 +1222,7 @@ static dml_bool_t CalculatePrefetchSchedule(struct display_mode_lib_scratch_st *
s->dst_y_prefetch_oto = s->Tvm_oto_lines + 2 * s->Tr0_oto_lines + s->Lsw_oto;
s->dst_y_prefetch_equ = p->VStartup - (*p->TSetup + dml_max(p->TWait + p->TCalc, *p->Tdmdl)) / s->LineTime - (*p->DSTYAfterScaler + (dml_float_t) *p->DSTXAfterScaler / (dml_float_t)p->myPipe->HTotal);
+ s->dst_y_prefetch_equ = dml_min(s->dst_y_prefetch_equ, 63.75); // limit to the reg limit of U6.2 for DST_Y_PREFETCH
#ifdef __DML_VBA_DEBUG__
dml_print("DML::%s: HTotal = %u\n", __func__, p->myPipe->HTotal);
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
index 138b4b1e42ed..c6a5a8614679 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/dml21_translation_helper.c
@@ -339,11 +339,22 @@ void dml21_apply_soc_bb_overrides(struct dml2_initialize_instance_in_out *dml_in
// }
}
+static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
+{
+ unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total;
+
+ if (stream->ctx->dc->caps.vtotal_limited_by_fp2) {
+ max_hw_v_total -= stream->timing.v_front_porch + 1;
+ }
+
+ return max_hw_v_total;
+}
+
static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cfg *timing,
struct dc_stream_state *stream,
struct dml2_context *dml_ctx)
{
- unsigned int hblank_start, vblank_start;
+ unsigned int hblank_start, vblank_start, min_hardware_refresh_in_uhz;
timing->h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
timing->v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
@@ -371,11 +382,23 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
- stream->timing.v_border_top - stream->timing.v_border_bottom;
timing->drr_config.enabled = stream->ignore_msa_timing_param;
- timing->drr_config.min_refresh_uhz = stream->timing.min_refresh_in_uhz;
timing->drr_config.drr_active_variable = stream->vrr_active_variable;
timing->drr_config.drr_active_fixed = stream->vrr_active_fixed;
timing->drr_config.disallowed = !stream->allow_freesync;
+ /* limit min refresh rate to DC cap */
+ min_hardware_refresh_in_uhz = stream->timing.min_refresh_in_uhz;
+ if (stream->ctx->dc->caps.max_v_total != 0) {
+ min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL),
+ (stream->timing.h_total * (long long)calc_max_hardware_v_total(stream)));
+ }
+
+ if (stream->timing.min_refresh_in_uhz > min_hardware_refresh_in_uhz) {
+ timing->drr_config.min_refresh_uhz = stream->timing.min_refresh_in_uhz;
+ } else {
+ timing->drr_config.min_refresh_uhz = min_hardware_refresh_in_uhz;
+ }
+
if (dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase &&
stream->ctx->dc->config.enable_fpo_flicker_detection == 1)
timing->drr_config.max_instant_vtotal_delta = dml_ctx->config.callbacks.get_max_flickerless_instant_vtotal_increase(stream, false);
@@ -422,6 +445,21 @@ static void populate_dml21_timing_config_from_stream_state(struct dml2_timing_cf
timing->vblank_nom = timing->v_total - timing->v_active;
}
+/**
+ * adjust_dml21_hblank_timing_config_from_pipe_ctx - Adjusts the horizontal blanking timing configuration
+ * based on the pipe context.
+ * @timing: Pointer to the dml2_timing_cfg structure to be adjusted.
+ * @pipe: Pointer to the pipe_ctx structure containing the horizontal blanking borrow value.
+ *
+ * This function modifies the horizontal active and blank end timings by adding and subtracting
+ * the horizontal blanking borrow value from the pipe context, respectively.
+ */
+static void adjust_dml21_hblank_timing_config_from_pipe_ctx(struct dml2_timing_cfg *timing, struct pipe_ctx *pipe)
+{
+ timing->h_active += pipe->hblank_borrow;
+ timing->h_blank_end -= pipe->hblank_borrow;
+}
+
static void populate_dml21_output_config_from_stream_state(struct dml2_link_output_cfg *output,
struct dc_stream_state *stream, const struct pipe_ctx *pipe)
{
@@ -709,6 +747,7 @@ static const struct scaler_data *get_scaler_data_for_plane(
temp_pipe->plane_state = pipe->plane_state;
temp_pipe->plane_res.scl_data.taps = pipe->plane_res.scl_data.taps;
temp_pipe->stream_res = pipe->stream_res;
+ temp_pipe->hblank_borrow = pipe->hblank_borrow;
dml_ctx->config.callbacks.build_scaling_params(temp_pipe);
break;
}
@@ -973,6 +1012,7 @@ bool dml21_map_dc_state_into_dml_display_cfg(const struct dc *in_dc, struct dc_s
ASSERT(disp_cfg_stream_location >= 0 && disp_cfg_stream_location <= __DML2_WRAPPER_MAX_STREAMS_PLANES__);
populate_dml21_timing_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, context->streams[stream_index], dml_ctx);
+ adjust_dml21_hblank_timing_config_from_pipe_ctx(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].timing, &context->res_ctx.pipe_ctx[stream_index]);
populate_dml21_output_config_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location].output, context->streams[stream_index], &context->res_ctx.pipe_ctx[stream_index]);
populate_dml21_stream_overrides_from_stream_state(&dml_dispcfg->stream_descriptors[disp_cfg_stream_location], context->streams[stream_index]);
@@ -1111,12 +1151,12 @@ void dml21_populate_pipe_ctx_dlg_params(struct dml2_context *dml_ctx, struct dc_
struct dc_crtc_timing *timing = &pipe_ctx->stream->timing;
union dml2_global_sync_programming *global_sync = &stream_programming->global_sync;
- hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right;
+ hactive = timing->h_addressable + timing->h_border_left + timing->h_border_right + pipe_ctx->hblank_borrow;
vactive = timing->v_addressable + timing->v_border_bottom + timing->v_border_top;
hblank_start = pipe_ctx->stream->timing.h_total - pipe_ctx->stream->timing.h_front_porch;
vblank_start = pipe_ctx->stream->timing.v_total - pipe_ctx->stream->timing.v_front_porch;
- hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right;
+ hblank_end = hblank_start - timing->h_addressable - timing->h_border_left - timing->h_border_right - pipe_ctx->hblank_borrow;
vblank_end = vblank_start - timing->v_addressable - timing->v_border_top - timing->v_border_bottom;
if (dml_ctx->config.svp_pstate.callbacks.get_pipe_subvp_type(context, pipe_ctx) == SUBVP_PHANTOM) {
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
index 92e43a1e4dd4..601320b1be81 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml21/src/dml2_core/dml2_core_dcn4_calcs.c
@@ -11,6 +11,7 @@
#define DML2_MAX_FMT_420_BUFFER_WIDTH 4096
#define DML_MAX_NUM_OF_SLICES_PER_DSC 4
+#define ALLOW_SDPIF_RATE_LIMIT_PRE_CSTATE
const char *dml2_core_internal_bw_type_str(enum dml2_core_internal_bw_type bw_type)
{
@@ -3886,6 +3887,10 @@ static void CalculateSwathAndDETConfiguration(struct dml2_core_internal_scratch
#endif
*p->hw_debug5 = false;
+#ifdef ALLOW_SDPIF_RATE_LIMIT_PRE_CSTATE
+ if (p->NumberOfActiveSurfaces > 1)
+ *p->hw_debug5 = true;
+#else
for (unsigned int k = 0; k < p->NumberOfActiveSurfaces; ++k) {
if (!(p->mrq_present) && (!(*p->UnboundedRequestEnabled)) && (TotalActiveDPP == 1)
&& p->display_cfg->plane_descriptors[k].surface.dcc.enable
@@ -3901,6 +3906,7 @@ static void CalculateSwathAndDETConfiguration(struct dml2_core_internal_scratch
dml2_printf("DML::%s: k=%u hw_debug5 = %u\n", __func__, k, *p->hw_debug5);
#endif
}
+#endif
}
static enum dml2_odm_mode DecideODMMode(unsigned int HActive,
diff --git a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
index 6eccf0241d85..1ed21c1b86a5 100644
--- a/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
+++ b/drivers/gpu/drm/amd/display/dc/dml2/dml2_dc_resource_mgmt.c
@@ -258,12 +258,25 @@ static unsigned int find_preferred_pipe_candidates(const struct dc_state *existi
* However this condition comes with a caveat. We need to ignore pipes that will
* require a change in OPP but still have the same stream id. For example during
* an MPC to ODM transiton.
+ *
+ * Adding check to avoid pipe select on the head pipe by utilizing dc resource
+ * helper function resource_get_primary_dpp_pipe and comparing the pipe index.
*/
if (existing_state) {
for (i = 0; i < pipe_count; i++) {
if (existing_state->res_ctx.pipe_ctx[i].stream && existing_state->res_ctx.pipe_ctx[i].stream->stream_id == stream_id) {
+ struct pipe_ctx *head_pipe =
+ resource_is_pipe_type(&existing_state->res_ctx.pipe_ctx[i], DPP_PIPE) ?
+ resource_get_primary_dpp_pipe(&existing_state->res_ctx.pipe_ctx[i]) :
+ NULL;
+
+ // we should always respect the head pipe from selection
+ if (head_pipe && head_pipe->pipe_idx == i)
+ continue;
if (existing_state->res_ctx.pipe_ctx[i].plane_res.hubp &&
- existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i)
+ existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i &&
+ (existing_state->res_ctx.pipe_ctx[i].prev_odm_pipe ||
+ existing_state->res_ctx.pipe_ctx[i].next_odm_pipe))
continue;
preferred_pipe_candidates[num_preferred_candidates++] = i;
@@ -292,6 +305,14 @@ static unsigned int find_last_resort_pipe_candidates(const struct dc_state *exis
*/
if (existing_state) {
for (i = 0; i < pipe_count; i++) {
+ struct pipe_ctx *head_pipe =
+ resource_is_pipe_type(&existing_state->res_ctx.pipe_ctx[i], DPP_PIPE) ?
+ resource_get_primary_dpp_pipe(&existing_state->res_ctx.pipe_ctx[i]) :
+ NULL;
+
+ // we should always respect the head pipe from selection
+ if (head_pipe && head_pipe->pipe_idx == i)
+ continue;
if ((existing_state->res_ctx.pipe_ctx[i].plane_res.hubp &&
existing_state->res_ctx.pipe_ctx[i].plane_res.hubp->opp_id != i) ||
existing_state->res_ctx.pipe_ctx[i].stream_res.tg)
diff --git a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
index ebd5df1a36e8..d9aaebfa3a0a 100644
--- a/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
+++ b/drivers/gpu/drm/amd/display/dc/dsc/dc_dsc.c
@@ -1093,14 +1093,11 @@ static bool setup_dsc_config(
if (!is_dsc_possible)
goto done;
- // Final decission: can we do DSC or not?
- if (is_dsc_possible) {
- // Fill out the rest of DSC settings
- dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported;
- dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth;
- dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4;
- dsc_cfg->is_dp = dsc_sink_caps->is_dp;
- }
+ /* Fill out the rest of DSC settings */
+ dsc_cfg->block_pred_enable = dsc_common_caps.is_block_pred_supported;
+ dsc_cfg->linebuf_depth = dsc_common_caps.lb_bit_depth;
+ dsc_cfg->version_minor = (dsc_common_caps.dsc_version & 0xf0) >> 4;
+ dsc_cfg->is_dp = dsc_sink_caps->is_dp;
done:
if (!is_dsc_possible)
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
index 4bd1dda07719..9fbd45c7dfef 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn10/dcn10_hubbub.h
@@ -200,6 +200,7 @@ struct dcn_hubbub_registers {
uint32_t DCHUBBUB_ARB_FRAC_URG_BW_MALL_B;
uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL1;
uint32_t DCHUBBUB_TIMEOUT_DETECTION_CTRL2;
+ uint32_t DCHUBBUB_CTRL_STATUS;
};
#define HUBBUB_REG_FIELD_LIST_DCN32(type) \
@@ -320,7 +321,12 @@ struct dcn_hubbub_registers {
type DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD;\
type DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD;\
type DCHUBBUB_TIMEOUT_DETECTION_EN;\
- type DCHUBBUB_TIMEOUT_TIMER_RESET
+ type DCHUBBUB_TIMEOUT_TIMER_RESET;\
+ type ROB_UNDERFLOW_STATUS;\
+ type ROB_OVERFLOW_STATUS;\
+ type ROB_OVERFLOW_CLEAR;\
+ type DCHUBBUB_HW_DEBUG;\
+ type CSTATE_SWATH_CHK_GOOD_MODE
#define HUBBUB_STUTTER_REG_FIELD_LIST(type) \
type DCHUBBUB_ARB_ALLOW_SR_ENTER_WATERMARK_A;\
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h
index 036bb3e6c957..46d8f5c70750 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn20/dcn20_hubbub.h
@@ -96,6 +96,7 @@ struct dcn20_hubbub {
unsigned int det1_size;
unsigned int det2_size;
unsigned int det3_size;
+ bool allow_sdpif_rate_limit_when_cstate_req;
};
void hubbub2_construct(struct dcn20_hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
index 5d658e9bef64..92fab471b183 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.c
@@ -1192,15 +1192,35 @@ static void dcn401_wait_for_det_update(struct hubbub *hubbub, int hubp_inst)
}
}
-static void dcn401_program_timeout_thresholds(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs)
+static bool dcn401_program_arbiter(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower)
{
struct dcn20_hubbub *hubbub2 = TO_DCN20_HUBBUB(hubbub);
+ bool wm_pending = false;
+ uint32_t temp;
+
/* request backpressure and outstanding return threshold (unused)*/
//REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, arb_regs->req_stall_threshold);
/* P-State stall threshold */
REG_UPDATE(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, arb_regs->pstate_stall_threshold);
+
+ if (safe_to_lower || arb_regs->allow_sdpif_rate_limit_when_cstate_req > hubbub2->allow_sdpif_rate_limit_when_cstate_req) {
+ hubbub2->allow_sdpif_rate_limit_when_cstate_req = arb_regs->allow_sdpif_rate_limit_when_cstate_req;
+
+ /* only update the required bits */
+ REG_GET(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, &temp);
+ if (hubbub2->allow_sdpif_rate_limit_when_cstate_req) {
+ temp |= (1 << 5);
+ } else {
+ temp &= ~(1 << 5);
+ }
+ REG_UPDATE(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, temp);
+ } else {
+ wm_pending = true;
+ }
+
+ return wm_pending;
}
static const struct hubbub_funcs hubbub4_01_funcs = {
@@ -1226,7 +1246,7 @@ static const struct hubbub_funcs hubbub4_01_funcs = {
.program_det_segments = dcn401_program_det_segments,
.program_compbuf_segments = dcn401_program_compbuf_segments,
.wait_for_det_update = dcn401_wait_for_det_update,
- .program_timeout_thresholds = dcn401_program_timeout_thresholds,
+ .program_arbiter = dcn401_program_arbiter,
};
void hubbub401_construct(struct dcn20_hubbub *hubbub2,
diff --git a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
index 5f1960722ebd..b1d9ea9d1c3d 100644
--- a/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/hubbub/dcn401/dcn401_hubbub.h
@@ -128,7 +128,12 @@
HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL1, DCHUBBUB_TIMEOUT_REQ_STALL_THRESHOLD, mask_sh),\
HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_PSTATE_STALL_THRESHOLD, mask_sh),\
HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_DETECTION_EN, mask_sh),\
- HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_TIMER_RESET, mask_sh)
+ HUBBUB_SF(DCHUBBUB_TIMEOUT_DETECTION_CTRL2, DCHUBBUB_TIMEOUT_TIMER_RESET, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_UNDERFLOW_STATUS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_STATUS, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, ROB_OVERFLOW_CLEAR, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, DCHUBBUB_HW_DEBUG, mask_sh),\
+ HUBBUB_SF(DCHUBBUB_CTRL_STATUS, CSTATE_SWATH_CHK_GOOD_MODE, mask_sh)
bool hubbub401_program_urgent_watermarks(
struct hubbub *hubbub,
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index 05424a9af58b..b029ec1b26d3 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -1925,9 +1925,9 @@ static void dcn20_program_pipe(
dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size);
}
- if (pipe_ctx->update_flags.raw ||
- (pipe_ctx->plane_state && pipe_ctx->plane_state->update_flags.raw) ||
- pipe_ctx->stream->update_flags.raw)
+ if (pipe_ctx->plane_state && (pipe_ctx->update_flags.raw ||
+ pipe_ctx->plane_state->update_flags.raw ||
+ pipe_ctx->stream->update_flags.raw))
dcn20_update_dchubp_dpp(dc, pipe_ctx, context);
if (pipe_ctx->plane_state && (pipe_ctx->update_flags.bits.enable ||
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
index d7f8b2dcaa6b..fa11f075d1f9 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
@@ -1049,7 +1049,8 @@ void dcn32_update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
}
/* Enable DSC hw block */
- dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
+ dsc_cfg.pic_width = (stream->timing.h_addressable + pipe_ctx->hblank_borrow +
+ stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
dsc_cfg.color_depth = stream->timing.display_color_depth;
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
index e8cc1bfa73f3..307782592789 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c
@@ -820,6 +820,7 @@ enum dc_status dcn401_enable_stream_timing(
int opp_cnt = 1;
int opp_inst[MAX_PIPES] = {0};
struct pipe_ctx *opp_heads[MAX_PIPES] = {0};
+ struct dc_crtc_timing patched_crtc_timing = stream->timing;
bool manual_mode;
unsigned int tmds_div = PIXEL_RATE_DIV_NA;
unsigned int unused_div = PIXEL_RATE_DIV_NA;
@@ -874,9 +875,13 @@ enum dc_status dcn401_enable_stream_timing(
if (dc->hwseq->funcs.PLAT_58856_wa && (!dc_is_dp_signal(stream->signal)))
dc->hwseq->funcs.PLAT_58856_wa(context, pipe_ctx);
+ /* if we are borrowing from hblank, h_addressable needs to be adjusted */
+ if (dc->debug.enable_hblank_borrow)
+ patched_crtc_timing.h_addressable = patched_crtc_timing.h_addressable + pipe_ctx->hblank_borrow;
+
pipe_ctx->stream_res.tg->funcs->program_timing(
pipe_ctx->stream_res.tg,
- &stream->timing,
+ &patched_crtc_timing,
pipe_ctx->pipe_dlg_param.vready_offset,
pipe_ctx->pipe_dlg_param.vstartup_start,
pipe_ctx->pipe_dlg_param.vupdate_offset,
@@ -1488,6 +1493,10 @@ void dcn401_prepare_bandwidth(struct dc *dc,
&context->bw_ctx.bw.dcn.watermarks,
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
false);
+ /* update timeout thresholds */
+ if (hubbub->funcs->program_arbiter) {
+ dc->wm_optimized_required |= hubbub->funcs->program_arbiter(hubbub, &context->bw_ctx.bw.dcn.arb_regs, false);
+ }
/* decrease compbuf size */
if (hubbub->funcs->program_compbuf_segments) {
@@ -1529,6 +1538,10 @@ void dcn401_optimize_bandwidth(
&context->bw_ctx.bw.dcn.watermarks,
dc->res_pool->ref_clocks.dchub_ref_clock_inKhz / 1000,
true);
+ /* update timeout thresholds */
+ if (hubbub->funcs->program_arbiter) {
+ hubbub->funcs->program_arbiter(hubbub, &context->bw_ctx.bw.dcn.arb_regs, true);
+ }
if (dc->clk_mgr->dc_mode_softmax_enabled)
if (dc->clk_mgr->clks.dramclk_khz > dc->clk_mgr->bw_params->dc_mode_softmax_memclk * 1000 &&
@@ -1554,11 +1567,6 @@ void dcn401_optimize_bandwidth(
pipe_ctx->dlg_regs.min_dst_y_next_start);
}
}
-
- /* update timeout thresholds */
- if (hubbub->funcs->program_timeout_thresholds) {
- hubbub->funcs->program_timeout_thresholds(hubbub, &context->bw_ctx.bw.dcn.arb_regs);
- }
}
void dcn401_fams2_global_control_lock(struct dc *dc,
diff --git a/drivers/gpu/drm/amd/display/dc/inc/core_types.h b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
index 8597e866bfe6..2edd5b38ce4f 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/core_types.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/core_types.h
@@ -219,6 +219,7 @@ struct resource_funcs {
* Get indicator of power from a context that went through full validation
*/
int (*get_power_profile)(const struct dc_state *context);
+ unsigned int (*get_det_buffer_size)(const struct dc_state *context);
};
struct audio_support{
@@ -477,6 +478,8 @@ struct pipe_ctx {
/* subvp_index: only valid if the pipe is a SUBVP_MAIN*/
uint8_t subvp_index;
struct pixel_rate_divider pixel_rate_divider;
+ /* pixels borrowed from hblank to hactive */
+ uint8_t hblank_borrow;
};
/* Data used for dynamic link encoder assignment.
diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
index 6c1d41c0f099..52b745667ef7 100644
--- a/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
+++ b/drivers/gpu/drm/amd/display/dc/inc/hw/dchubbub.h
@@ -228,7 +228,7 @@ struct hubbub_funcs {
void (*program_det_segments)(struct hubbub *hubbub, int hubp_inst, unsigned det_buffer_size_seg);
void (*program_compbuf_segments)(struct hubbub *hubbub, unsigned compbuf_size_seg, bool safe_to_increase);
void (*wait_for_det_update)(struct hubbub *hubbub, int hubp_inst);
- void (*program_timeout_thresholds)(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs);
+ bool (*program_arbiter)(struct hubbub *hubbub, struct dml2_display_arb_regs *arb_regs, bool safe_to_lower);
};
struct hubbub {
diff --git a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
index 41cab9ad6885..5d66bfc7fe6e 100644
--- a/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
+++ b/drivers/gpu/drm/amd/display/dc/link/link_dpms.c
@@ -808,7 +808,8 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
enum optc_dsc_mode optc_dsc_mode;
/* Enable DSC hw block */
- dsc_cfg.pic_width = (stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
+ dsc_cfg.pic_width = (stream->timing.h_addressable + pipe_ctx->hblank_borrow +
+ stream->timing.h_border_left + stream->timing.h_border_right) / opp_cnt;
dsc_cfg.pic_height = stream->timing.v_addressable + stream->timing.v_border_top + stream->timing.v_border_bottom;
dsc_cfg.pixel_encoding = stream->timing.pixel_encoding;
dsc_cfg.color_depth = stream->timing.display_color_depth;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
index 189d0c85872e..7a5b9aa5292c 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn20/dcn20_resource.c
@@ -1510,6 +1510,7 @@ bool dcn20_split_stream_for_odm(
if (prev_odm_pipe->plane_state) {
struct scaler_data *sd = &prev_odm_pipe->plane_res.scl_data;
+ struct output_pixel_processor *opp = next_odm_pipe->stream_res.opp;
int new_width;
/* HACTIVE halved for odm combine */
@@ -1543,7 +1544,28 @@ bool dcn20_split_stream_for_odm(
sd->viewport_c.x += dc_fixpt_floor(dc_fixpt_mul_int(
sd->ratios.horz_c, sd->h_active - sd->recout.x));
sd->recout.x = 0;
+
+ /*
+ * When odm is used in YcbCr422 or 420 colour space, a split screen
+ * will be seen with the previous calculations since the extra left
+ * edge pixel is accounted for in fmt but not in viewport.
+ *
+ * Below are calculations which fix the split by fixing the calculations
+ * if there is an extra left edge pixel.
+ */
+ if (opp && opp->funcs->opp_get_left_edge_extra_pixel_count
+ && opp->funcs->opp_get_left_edge_extra_pixel_count(
+ opp, next_odm_pipe->stream->timing.pixel_encoding,
+ resource_is_pipe_type(next_odm_pipe, OTG_MASTER)) == 1) {
+ sd->h_active += 1;
+ sd->recout.width += 1;
+ sd->viewport.x -= dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
+ sd->viewport_c.x -= dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
+ sd->viewport_c.width += dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
+ sd->viewport.width += dc_fixpt_ceil(dc_fixpt_mul_int(sd->ratios.horz, 1));
+ }
}
+
if (!next_odm_pipe->top_pipe)
next_odm_pipe->stream_res.opp = pool->opps[next_odm_pipe->pipe_idx];
else
@@ -2132,6 +2154,7 @@ bool dcn20_fast_validate_bw(
ASSERT(0);
}
}
+
/* Actual dsc count per stream dsc validation*/
if (!dcn20_validate_dsc(dc, context)) {
context->bw_ctx.dml.vba.ValidationStatus[context->bw_ctx.dml.vba.soc.num_states] =
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
index cd31e4f16c14..bfd0eccbed28 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn30/dcn30_resource.c
@@ -2353,6 +2353,7 @@ static bool dcn30_resource_construct(
dc->caps.dp_hdmi21_pcon_support = true;
dc->caps.max_v_total = (1 << 15) - 1;
+ dc->caps.vtotal_limited_by_fp2 = true;
/* read VBIOS LTTPR caps */
{
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
index 02af8b8f4d27..7baefc910a3d 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn302/dcn302_resource.c
@@ -1233,6 +1233,7 @@ static bool dcn302_resource_construct(
dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true;
dc->caps.max_v_total = (1 << 15) - 1;
+ dc->caps.vtotal_limited_by_fp2 = true;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
index 7002a8dd358a..8a57d46ad15f 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn303/dcn303_resource.c
@@ -1178,6 +1178,7 @@ static bool dcn303_resource_construct(
dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true;
dc->caps.max_v_total = (1 << 15) - 1;
+ dc->caps.vtotal_limited_by_fp2 = true;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
index c16cf1c8f7f9..54ec3d8e920c 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.c
@@ -1720,6 +1720,12 @@ int dcn31_populate_dml_pipes_from_context(
return pipe_cnt;
}
+unsigned int dcn31_get_det_buffer_size(
+ const struct dc_state *context)
+{
+ return context->bw_ctx.dml.ip.det_buffer_size_kbytes;
+}
+
void dcn31_calculate_wm_and_dlg(
struct dc *dc, struct dc_state *context,
display_e2e_pipe_params_st *pipes,
@@ -1842,6 +1848,7 @@ static struct resource_funcs dcn31_res_pool_funcs = {
.update_bw_bounding_box = dcn31_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn31_get_panel_config_defaults,
+ .get_det_buffer_size = dcn31_get_det_buffer_size,
};
static struct clock_source *dcn30_clock_source_create(
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h
index 901436591ed4..551ad912f7be 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn31/dcn31_resource.h
@@ -63,6 +63,9 @@ struct resource_pool *dcn31_create_resource_pool(
const struct dc_init_data *init_data,
struct dc *dc);
+unsigned int dcn31_get_det_buffer_size(
+ const struct dc_state *context);
+
/*temp: B0 specific before switch to dcn313 headers*/
#ifndef regPHYPLLF_PIXCLK_RESYNC_CNTL
#define regPHYPLLF_PIXCLK_RESYNC_CNTL 0x007e
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
index c0f48c78e968..2794473f2aff 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn314/dcn314_resource.c
@@ -1777,6 +1777,7 @@ static struct resource_funcs dcn314_res_pool_funcs = {
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn314_get_panel_config_defaults,
.get_preferred_eng_id_dpia = dcn314_get_preferred_eng_id_dpia,
+ .get_det_buffer_size = dcn31_get_det_buffer_size,
};
static struct clock_source *dcn30_clock_source_create(
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
index 6c3295259a81..4ee33eb3381d 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn315/dcn315_resource.c
@@ -1845,6 +1845,7 @@ static struct resource_funcs dcn315_res_pool_funcs = {
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn315_get_panel_config_defaults,
.get_power_profile = dcn315_get_power_profile,
+ .get_det_buffer_size = dcn31_get_det_buffer_size,
};
static bool dcn315_resource_construct(
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
index 6edaaadcb173..79eddbafe3c2 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn316/dcn316_resource.c
@@ -1719,6 +1719,7 @@ static struct resource_funcs dcn316_res_pool_funcs = {
.update_bw_bounding_box = dcn316_update_bw_bounding_box,
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn316_get_panel_config_defaults,
+ .get_det_buffer_size = dcn31_get_det_buffer_size,
};
static bool dcn316_resource_construct(
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
index 01d1a11d5545..12d247a7ec45 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn32/dcn32_resource.c
@@ -2189,6 +2189,7 @@ static bool dcn32_resource_construct(
dc->caps.dmcub_support = true;
dc->caps.seamless_odm = true;
dc->caps.max_v_total = (1 << 15) - 1;
+ dc->caps.vtotal_limited_by_fp2 = true;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
@@ -2803,6 +2804,7 @@ struct pipe_ctx *dcn32_acquire_free_pipe_as_secondary_opp_head(
free_pipe->plane_res.xfm = pool->transforms[free_pipe_idx];
free_pipe->plane_res.dpp = pool->dpps[free_pipe_idx];
free_pipe->plane_res.mpcc_inst = pool->dpps[free_pipe_idx]->inst;
+ free_pipe->hblank_borrow = otg_master->hblank_borrow;
if (free_pipe->stream->timing.flags.DSC == 1) {
dcn20_acquire_dsc(free_pipe->stream->ctx->dc,
&new_ctx->res_ctx,
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
index 5cb74fd9cb7d..06b9479c8bd3 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn321/dcn321_resource.c
@@ -1742,6 +1742,7 @@ static bool dcn321_resource_construct(
dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true;
dc->caps.max_v_total = (1 << 15) - 1;
+ dc->caps.vtotal_limited_by_fp2 = true;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
index 6cc2960b6104..89e2adcf2a28 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn35/dcn35_resource.c
@@ -1778,6 +1778,7 @@ static struct resource_funcs dcn35_res_pool_funcs = {
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
.get_preferred_eng_id_dpia = dcn35_get_preferred_eng_id_dpia,
+ .get_det_buffer_size = dcn31_get_det_buffer_size,
};
static bool dcn35_resource_construct(
@@ -1849,6 +1850,7 @@ static bool dcn35_resource_construct(
dc->caps.zstate_support = true;
dc->caps.ips_support = true;
dc->caps.max_v_total = (1 << 15) - 1;
+ dc->caps.vtotal_limited_by_fp2 = true;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
index d87e2641cda1..263a37c1cd3a 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn351/dcn351_resource.c
@@ -1757,6 +1757,7 @@ static struct resource_funcs dcn351_res_pool_funcs = {
.patch_unknown_plane_state = dcn20_patch_unknown_plane_state,
.get_panel_config_defaults = dcn35_get_panel_config_defaults,
.get_preferred_eng_id_dpia = dcn351_get_preferred_eng_id_dpia,
+ .get_det_buffer_size = dcn31_get_det_buffer_size,
};
static bool dcn351_resource_construct(
@@ -1828,6 +1829,7 @@ static bool dcn351_resource_construct(
dc->caps.zstate_support = true;
dc->caps.ips_support = true;
dc->caps.max_v_total = (1 << 15) - 1;
+ dc->caps.vtotal_limited_by_fp2 = true;
/* Color pipeline capabilities */
dc->caps.color.dpp.dcn_arch = 1;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
index db93bac247c0..2a3dabfe3cea 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.c
@@ -1864,6 +1864,7 @@ static bool dcn401_resource_construct(
dc->caps.extended_aux_timeout_support = true;
dc->caps.dmcub_support = true;
dc->caps.max_v_total = (1 << 15) - 1;
+ dc->caps.vtotal_limited_by_fp2 = true;
if (ASICREV_IS_GC_12_0_1_A0(dc->ctx->asic_id.hw_internal_rev))
dc->caps.dcc_plane_width_limit = 7680;
diff --git a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
index 7c8d61db153d..19568c359669 100644
--- a/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
+++ b/drivers/gpu/drm/amd/display/dc/resource/dcn401/dcn401_resource.h
@@ -612,7 +612,8 @@ void dcn401_prepare_mcache_programming(struct dc *dc, struct dc_state *context);
SR(DCHUBBUB_SDPIF_CFG1), \
SR(DCHUBBUB_MEM_PWR_MODE_CTRL), \
SR(DCHUBBUB_TIMEOUT_DETECTION_CTRL1), \
- SR(DCHUBBUB_TIMEOUT_DETECTION_CTRL2)
+ SR(DCHUBBUB_TIMEOUT_DETECTION_CTRL2), \
+ SR(DCHUBBUB_CTRL_STATUS)
/* DCCG */
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
index 614276200aa0..73a65913cb12 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.c
@@ -99,7 +99,7 @@ static struct spl_rect calculate_plane_rec_in_timing_active(
*
* recout_x = 128 + round(plane_x * 2304 / 1920)
* recout_w = 128 + round((plane_x + plane_w) * 2304 / 1920) - recout_x
- * recout_y = 0 + round(plane_y * 1440 / 1280)
+ * recout_y = 0 + round(plane_y * 1440 / 1200)
* recout_h = 0 + round((plane_y + plane_h) * 1440 / 1200) - recout_y
*
* NOTE: fixed point division is not error free. To reduce errors
@@ -739,14 +739,13 @@ static enum scl_mode spl_get_dscl_mode(const struct spl_in *spl_in,
return SCL_MODE_SCALING_444_RGB_ENABLE;
}
- /* Bypass YUV if at 1:1 with no ISHARP or if doing 2:1 YUV
- * downscale without EASF
+ /*
+ * Bypass YUV if Y is 1:1 with no ISHARP
+ * Do not bypass UV at 1:1 for cositing to be applied
*/
- if ((!enable_isharp) && (!enable_easf)) {
+ if (!enable_isharp) {
if (data->ratios.horz.value == one && data->ratios.vert.value == one)
return SCL_MODE_SCALING_420_LUMA_BYPASS;
- if (data->ratios.horz_c.value == one && data->ratios.vert_c.value == one)
- return SCL_MODE_SCALING_420_CHROMA_BYPASS;
}
return SCL_MODE_SCALING_420_YCBCR_ENABLE;
@@ -933,6 +932,7 @@ static bool spl_get_optimal_number_of_taps(
int min_taps_y, min_taps_c;
enum lb_memory_config lb_config;
bool skip_easf = false;
+ bool is_ycbcr = spl_dscl_is_video_format(spl_in->basic_in.format);
if (spl_scratch->scl_data.viewport.width > spl_scratch->scl_data.h_active &&
max_downscale_src_width != 0 &&
@@ -1074,10 +1074,9 @@ static bool spl_get_optimal_number_of_taps(
/* Sharpener requires scaler to be enabled, including for 1:1
* Check if ISHARP can be enabled
- * If ISHARP is not enabled, for 1:1, set taps to 1 and disable
- * EASF
- * For case of 2:1 YUV where chroma is 1:1, set taps to 1 if
- * EASF is not enabled
+ * If ISHARP is not enabled, set taps to 1 if ratio is 1:1
+ * except for chroma taps. Keep previous taps so it can
+ * handle cositing
*/
*enable_isharp = spl_get_isharp_en(spl_in, spl_scratch);
@@ -1087,20 +1086,28 @@ static bool spl_get_optimal_number_of_taps(
spl_scratch->scl_data.taps.h_taps = 1;
spl_scratch->scl_data.taps.v_taps = 1;
- if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c))
+ if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c) && !is_ycbcr)
spl_scratch->scl_data.taps.h_taps_c = 1;
- if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c))
+ if (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c) && !is_ycbcr)
spl_scratch->scl_data.taps.v_taps_c = 1;
*enable_easf_v = false;
*enable_easf_h = false;
} else {
if ((!*enable_easf_h) &&
+ (IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz)))
+ spl_scratch->scl_data.taps.h_taps = 1;
+
+ if ((!*enable_easf_v) &&
+ (IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert)))
+ spl_scratch->scl_data.taps.v_taps = 1;
+
+ if ((!*enable_easf_h) && !is_ycbcr &&
(IDENTITY_RATIO(spl_scratch->scl_data.ratios.horz_c)))
spl_scratch->scl_data.taps.h_taps_c = 1;
- if ((!*enable_easf_v) &&
+ if ((!*enable_easf_v) && !is_ycbcr &&
(IDENTITY_RATIO(spl_scratch->scl_data.ratios.vert_c)))
spl_scratch->scl_data.taps.v_taps_c = 1;
}
@@ -1111,8 +1118,7 @@ static bool spl_get_optimal_number_of_taps(
static void spl_set_black_color_data(enum spl_pixel_format format,
struct scl_black_color *scl_black_color)
{
- bool ycbcr = format >= SPL_PIXEL_FORMAT_VIDEO_BEGIN
- && format <= SPL_PIXEL_FORMAT_VIDEO_END;
+ bool ycbcr = spl_dscl_is_video_format(format);
if (ycbcr) {
scl_black_color->offset_rgb_y = BLACK_OFFSET_RGB_Y;
scl_black_color->offset_rgb_cbcr = BLACK_OFFSET_CBCR;
@@ -1746,6 +1752,32 @@ static void spl_set_isharp_data(struct dscl_prog_data *dscl_prog_data,
spl_set_blur_scale_data(dscl_prog_data, data);
}
+/* Calculate recout, scaling ratio, and viewport, then get optimal number of taps */
+static bool spl_calculate_number_of_taps(struct spl_in *spl_in, struct spl_scratch *spl_scratch, struct spl_out *spl_out,
+ bool *enable_easf_v, bool *enable_easf_h, bool *enable_isharp)
+{
+ bool res = false;
+
+ memset(spl_scratch, 0, sizeof(struct spl_scratch));
+ spl_scratch->scl_data.h_active = spl_in->h_active;
+ spl_scratch->scl_data.v_active = spl_in->v_active;
+
+ // All SPL calls
+ /* recout calculation */
+ /* depends on h_active */
+ spl_calculate_recout(spl_in, spl_scratch, spl_out);
+ /* depends on pixel format */
+ spl_calculate_scaling_ratios(spl_in, spl_scratch, spl_out);
+ /* depends on scaling ratios and recout, does not calculate offset yet */
+ spl_calculate_viewport_size(spl_in, spl_scratch);
+
+ res = spl_get_optimal_number_of_taps(
+ spl_in->basic_out.max_downscale_src_width, spl_in,
+ spl_scratch, &spl_in->scaling_quality, enable_easf_v,
+ enable_easf_h, enable_isharp);
+ return res;
+}
+
/* Calculate scaler parameters */
bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)
{
@@ -1760,23 +1792,9 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)
bool enable_isharp = false;
const struct spl_scaler_data *data = &spl_scratch.scl_data;
- memset(&spl_scratch, 0, sizeof(struct spl_scratch));
- spl_scratch.scl_data.h_active = spl_in->h_active;
- spl_scratch.scl_data.v_active = spl_in->v_active;
+ res = spl_calculate_number_of_taps(spl_in, &spl_scratch, spl_out,
+ &enable_easf_v, &enable_easf_h, &enable_isharp);
- // All SPL calls
- /* recout calculation */
- /* depends on h_active */
- spl_calculate_recout(spl_in, &spl_scratch, spl_out);
- /* depends on pixel format */
- spl_calculate_scaling_ratios(spl_in, &spl_scratch, spl_out);
- /* depends on scaling ratios and recout, does not calculate offset yet */
- spl_calculate_viewport_size(spl_in, &spl_scratch);
-
- res = spl_get_optimal_number_of_taps(
- spl_in->basic_out.max_downscale_src_width, spl_in,
- &spl_scratch, &spl_in->scaling_quality, &enable_easf_v,
- &enable_easf_h, &enable_isharp);
/*
* Depends on recout, scaling ratios, h_active and taps
* May need to re-check lb size after this in some obscure scenario
@@ -1824,3 +1842,20 @@ bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out)
return res;
}
+
+/* External interface to get number of taps only */
+bool spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out *spl_out)
+{
+ bool res = false;
+ bool enable_easf_v = false;
+ bool enable_easf_h = false;
+ bool enable_isharp = false;
+ struct spl_scratch spl_scratch;
+ struct dscl_prog_data *dscl_prog_data = spl_out->dscl_prog_data;
+ const struct spl_scaler_data *data = &spl_scratch.scl_data;
+
+ res = spl_calculate_number_of_taps(spl_in, &spl_scratch, spl_out,
+ &enable_easf_v, &enable_easf_h, &enable_isharp);
+ spl_set_taps_data(dscl_prog_data, data);
+ return res;
+}
diff --git a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h
index 205e59a2a8ee..02a2d6725ed5 100644
--- a/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h
+++ b/drivers/gpu/drm/amd/display/dc/spl/dc_spl.h
@@ -13,4 +13,6 @@
bool spl_calculate_scaler_params(struct spl_in *spl_in, struct spl_out *spl_out);
+bool spl_get_number_of_taps(struct spl_in *spl_in, struct spl_out *spl_out);
+
#endif /* __DC_SPL_H__ */
diff --git a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
index f980a84dceef..2b3964529539 100644
--- a/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
+++ b/drivers/gpu/drm/amd/display/modules/freesync/freesync.c
@@ -122,6 +122,17 @@ static unsigned int calc_duration_in_us_from_v_total(
return duration_in_us;
}
+static unsigned int calc_max_hardware_v_total(const struct dc_stream_state *stream)
+{
+ unsigned int max_hw_v_total = stream->ctx->dc->caps.max_v_total;
+
+ if (stream->ctx->dc->caps.vtotal_limited_by_fp2) {
+ max_hw_v_total -= stream->timing.v_front_porch + 1;
+ }
+
+ return max_hw_v_total;
+}
+
unsigned int mod_freesync_calc_v_total_from_refresh(
const struct dc_stream_state *stream,
unsigned int refresh_in_uhz)
@@ -1016,7 +1027,7 @@ void mod_freesync_build_vrr_params(struct mod_freesync *mod_freesync,
if (stream->ctx->dc->caps.max_v_total != 0 && stream->timing.h_total != 0) {
min_hardware_refresh_in_uhz = div64_u64((stream->timing.pix_clk_100hz * 100000000ULL),
- (stream->timing.h_total * (long long)stream->ctx->dc->caps.max_v_total));
+ (stream->timing.h_total * (long long)calc_max_hardware_v_total(stream)));
}
/* Limit minimum refresh rate to what can be supported by hardware */
min_refresh_in_uhz = min_hardware_refresh_in_uhz > in_config->min_refresh_in_uhz ?
diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h
index 5ebe4cb40f9d..c38a01742d6f 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_offset.h
@@ -7571,6 +7571,8 @@
// base address: 0x10100000
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0 0xd000
#define regRCC_STRAP0_RCC_DEV0_EPF0_STRAP0_BASE_IDX 5
+#define regRCC_DEV0_EPF5_STRAP4 0xd284
+#define regRCC_DEV0_EPF5_STRAP4_BASE_IDX 5
// addressBlock: nbio_nbif0_bif_rst_bif_rst_regblk
diff --git a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h
index eb8c556d9c93..3b96f1e5a180 100644
--- a/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h
+++ b/drivers/gpu/drm/amd/include/asic_reg/nbio/nbio_7_11_0_sh_mask.h
@@ -50665,6 +50665,19 @@
#define RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_D1_SUPPORT_DEV0_F0_MASK 0x40000000L
#define RCC_STRAP0_RCC_DEV0_EPF0_STRAP0__STRAP_D2_SUPPORT_DEV0_F0_MASK 0x80000000L
+//RCC_DEV0_EPF5_STRAP4
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_64BIT_EN_DEV0_F5__SHIFT 0x14
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_EN_DEV0_F5__SHIFT 0x15
+#define RCC_DEV0_EPF5_STRAP4__STRAP_FLR_EN_DEV0_F5__SHIFT 0x16
+#define RCC_DEV0_EPF5_STRAP4__STRAP_PME_SUPPORT_DEV0_F5__SHIFT 0x17
+#define RCC_DEV0_EPF5_STRAP4__STRAP_INTERRUPT_PIN_DEV0_F5__SHIFT 0x1c
+#define RCC_DEV0_EPF5_STRAP4__STRAP_AUXPWR_SUPPORT_DEV0_F5__SHIFT 0x1f
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_64BIT_EN_DEV0_F5_MASK 0x00100000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_ATOMIC_EN_DEV0_F5_MASK 0x00200000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_FLR_EN_DEV0_F5_MASK 0x00400000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_PME_SUPPORT_DEV0_F5_MASK 0x0F800000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_INTERRUPT_PIN_DEV0_F5_MASK 0x70000000L
+#define RCC_DEV0_EPF5_STRAP4__STRAP_AUXPWR_SUPPORT_DEV0_F5_MASK 0x80000000L
// addressBlock: nbio_nbif0_bif_rst_bif_rst_regblk
//HARD_RST_CTRL
diff --git a/drivers/gpu/drm/amd/include/kgd_pp_interface.h b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
index bb27c0d2a9ae..d7acdd42d80f 100644
--- a/drivers/gpu/drm/amd/include/kgd_pp_interface.h
+++ b/drivers/gpu/drm/amd/include/kgd_pp_interface.h
@@ -164,6 +164,7 @@ enum amd_pp_task {
};
enum PP_SMC_POWER_PROFILE {
+ PP_SMC_POWER_PROFILE_UNKNOWN = -1,
PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT = 0x0,
PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x1,
PP_SMC_POWER_PROFILE_POWERSAVING = 0x2,
@@ -357,11 +358,22 @@ struct dpm_clocks;
struct amdgpu_xcp_metrics {
/* Utilization Instantaneous (%) */
- u32 gfx_busy_inst[MAX_XCC];
- u16 jpeg_busy[NUM_JPEG_ENG];
- u16 vcn_busy[NUM_VCN];
+ uint32_t gfx_busy_inst[MAX_XCC];
+ uint16_t jpeg_busy[NUM_JPEG_ENG];
+ uint16_t vcn_busy[NUM_VCN];
/* Utilization Accumulated (%) */
- u64 gfx_busy_acc[MAX_XCC];
+ uint64_t gfx_busy_acc[MAX_XCC];
+};
+
+struct amdgpu_xcp_metrics_v1_1 {
+ /* Utilization Instantaneous (%) */
+ uint32_t gfx_busy_inst[MAX_XCC];
+ uint16_t jpeg_busy[NUM_JPEG_ENG];
+ uint16_t vcn_busy[NUM_VCN];
+ /* Utilization Accumulated (%) */
+ uint64_t gfx_busy_acc[MAX_XCC];
+ /* Total App Clock Counter Accumulated */
+ uint64_t gfx_below_host_limit_acc[MAX_XCC];
};
struct amd_pm_funcs {
@@ -977,6 +989,105 @@ struct gpu_metrics_v1_6 {
uint32_t pcie_lc_perf_other_end_recovery;
};
+struct gpu_metrics_v1_7 {
+ struct metrics_table_header common_header;
+
+ /* Temperature (Celsius) */
+ uint16_t temperature_hotspot;
+ uint16_t temperature_mem;
+ uint16_t temperature_vrsoc;
+
+ /* Power (Watts) */
+ uint16_t curr_socket_power;
+
+ /* Utilization (%) */
+ uint16_t average_gfx_activity;
+ uint16_t average_umc_activity; // memory controller
+
+ /* VRAM max bandwidthi (in GB/sec) at max memory clock */
+ uint64_t mem_max_bandwidth;
+
+ /* Energy (15.259uJ (2^-16) units) */
+ uint64_t energy_accumulator;
+
+ /* Driver attached timestamp (in ns) */
+ uint64_t system_clock_counter;
+
+ /* Accumulation cycle counter */
+ uint32_t accumulation_counter;
+
+ /* Accumulated throttler residencies */
+ uint32_t prochot_residency_acc;
+ uint32_t ppt_residency_acc;
+ uint32_t socket_thm_residency_acc;
+ uint32_t vr_thm_residency_acc;
+ uint32_t hbm_thm_residency_acc;
+
+ /* Clock Lock Status. Each bit corresponds to clock instance */
+ uint32_t gfxclk_lock_status;
+
+ /* Link width (number of lanes) and speed (in 0.1 GT/s) */
+ uint16_t pcie_link_width;
+ uint16_t pcie_link_speed;
+
+ /* XGMI bus width and bitrate (in Gbps) */
+ uint16_t xgmi_link_width;
+ uint16_t xgmi_link_speed;
+
+ /* Utilization Accumulated (%) */
+ uint32_t gfx_activity_acc;
+ uint32_t mem_activity_acc;
+
+ /*PCIE accumulated bandwidth (GB/sec) */
+ uint64_t pcie_bandwidth_acc;
+
+ /*PCIE instantaneous bandwidth (GB/sec) */
+ uint64_t pcie_bandwidth_inst;
+
+ /* PCIE L0 to recovery state transition accumulated count */
+ uint64_t pcie_l0_to_recov_count_acc;
+
+ /* PCIE replay accumulated count */
+ uint64_t pcie_replay_count_acc;
+
+ /* PCIE replay rollover accumulated count */
+ uint64_t pcie_replay_rover_count_acc;
+
+ /* PCIE NAK sent accumulated count */
+ uint32_t pcie_nak_sent_count_acc;
+
+ /* PCIE NAK received accumulated count */
+ uint32_t pcie_nak_rcvd_count_acc;
+
+ /* XGMI accumulated data transfer size(KiloBytes) */
+ uint64_t xgmi_read_data_acc[NUM_XGMI_LINKS];
+ uint64_t xgmi_write_data_acc[NUM_XGMI_LINKS];
+
+ /* XGMI link status(active/inactive) */
+ uint16_t xgmi_link_status[NUM_XGMI_LINKS];
+
+ uint16_t padding;
+
+ /* PMFW attached timestamp (10ns resolution) */
+ uint64_t firmware_timestamp;
+
+ /* Current clocks (Mhz) */
+ uint16_t current_gfxclk[MAX_GFX_CLKS];
+ uint16_t current_socclk[MAX_CLKS];
+ uint16_t current_vclk0[MAX_CLKS];
+ uint16_t current_dclk0[MAX_CLKS];
+ uint16_t current_uclk;
+
+ /* Number of current partition */
+ uint16_t num_partition;
+
+ /* XCP metrics stats */
+ struct amdgpu_xcp_metrics_v1_1 xcp_stats[NUM_XCP];
+
+ /* PCIE other end recovery counter */
+ uint32_t pcie_lc_perf_other_end_recovery;
+};
+
/*
* gpu_metrics_v2_0 is not recommended as it's not naturally aligned.
* Use gpu_metrics_v2_1 or later instead.
diff --git a/drivers/gpu/drm/amd/pm/amdgpu_pm.c b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
index 136e8193867c..e8ae7681bf0a 100644
--- a/drivers/gpu/drm/amd/pm/amdgpu_pm.c
+++ b/drivers/gpu/drm/amd/pm/amdgpu_pm.c
@@ -1361,7 +1361,11 @@ static ssize_t amdgpu_set_pp_mclk_od(struct device *dev,
* create a custom set of heuristics, write a string of numbers to the file
* starting with the number of the custom profile along with a setting
* for each heuristic parameter. Due to differences across asic families
- * the heuristic parameters vary from family to family.
+ * the heuristic parameters vary from family to family. Additionally,
+ * you can apply the custom heuristics to different clock domains. Each
+ * clock domain is considered a distinct operation so if you modify the
+ * gfxclk heuristics and then the memclk heuristics, the all of the
+ * custom heuristics will be retained until you switch to another profile.
*
*/
diff --git a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c
index b52ce135d84d..d3ff6a831ed5 100644
--- a/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c
+++ b/drivers/gpu/drm/amd/pm/powerplay/smumgr/vega12_smumgr.c
@@ -257,20 +257,18 @@ static int vega12_smu_init(struct pp_hwmgr *hwmgr)
priv->smu_tables.entry[TABLE_WATERMARKS].size = sizeof(Watermarks_t);
tools_size = 0x19000;
- if (tools_size) {
- ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
- tools_size,
- PAGE_SIZE,
- AMDGPU_GEM_DOMAIN_VRAM,
- &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
- &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
- &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
- if (ret)
- goto err1;
+ ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
+ tools_size,
+ PAGE_SIZE,
+ AMDGPU_GEM_DOMAIN_VRAM,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].handle,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].mc_addr,
+ &priv->smu_tables.entry[TABLE_PMSTATUSLOG].table);
+ if (ret)
+ goto err1;
- priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
- priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
- }
+ priv->smu_tables.entry[TABLE_PMSTATUSLOG].version = 0x01;
+ priv->smu_tables.entry[TABLE_PMSTATUSLOG].size = tools_size;
/* allocate space for AVFS Fuse table */
ret = amdgpu_bo_create_kernel((struct amdgpu_device *)hwmgr->adev,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
index 64f917959576..21bd635bcdfc 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/amdgpu_smu.c
@@ -72,6 +72,10 @@ static int smu_set_power_limit(void *handle, uint32_t limit);
static int smu_set_fan_speed_rpm(void *handle, uint32_t speed);
static int smu_set_gfx_cgpg(struct smu_context *smu, bool enabled);
static int smu_set_mp1_state(void *handle, enum pp_mp1_state mp1_state);
+static void smu_power_profile_mode_get(struct smu_context *smu,
+ enum PP_SMC_POWER_PROFILE profile_mode);
+static void smu_power_profile_mode_put(struct smu_context *smu,
+ enum PP_SMC_POWER_PROFILE profile_mode);
static int smu_sys_get_pp_feature_mask(void *handle,
char *buf)
@@ -760,6 +764,7 @@ static int smu_early_init(struct amdgpu_ip_block *ip_block)
smu->smu_baco.platform_support = false;
smu->smu_baco.maco_support = false;
smu->user_dpm_profile.fan_mode = -1;
+ smu->power_profile_mode = PP_SMC_POWER_PROFILE_UNKNOWN;
mutex_init(&smu->message_lock);
@@ -1244,6 +1249,21 @@ static bool smu_is_workload_profile_available(struct smu_context *smu,
return smu->workload_map && smu->workload_map[profile].valid_mapping;
}
+static void smu_init_power_profile(struct smu_context *smu)
+{
+ if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_UNKNOWN) {
+ if (smu->is_apu ||
+ !smu_is_workload_profile_available(
+ smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D))
+ smu->power_profile_mode =
+ PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+ else
+ smu->power_profile_mode =
+ PP_SMC_POWER_PROFILE_FULLSCREEN3D;
+ }
+ smu_power_profile_mode_get(smu, smu->power_profile_mode);
+}
+
static int smu_sw_init(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
@@ -1259,42 +1279,13 @@ static int smu_sw_init(struct amdgpu_ip_block *ip_block)
INIT_WORK(&smu->interrupt_work, smu_interrupt_work_fn);
atomic64_set(&smu->throttle_int_counter, 0);
smu->watermarks_bitmap = 0;
- smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
- smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
- smu->user_dpm_profile.user_workload_mask = 0;
atomic_set(&smu->smu_power.power_gate.vcn_gated, 1);
atomic_set(&smu->smu_power.power_gate.jpeg_gated, 1);
atomic_set(&smu->smu_power.power_gate.vpe_gated, 1);
atomic_set(&smu->smu_power.power_gate.umsch_mm_gated, 1);
- smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
- smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
- smu->workload_priority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
- smu->workload_priority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
- smu->workload_priority[PP_SMC_POWER_PROFILE_VR] = 4;
- smu->workload_priority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
- smu->workload_priority[PP_SMC_POWER_PROFILE_CUSTOM] = 6;
-
- if (smu->is_apu ||
- !smu_is_workload_profile_available(smu, PP_SMC_POWER_PROFILE_FULLSCREEN3D)) {
- smu->driver_workload_mask =
- 1 << smu->workload_priority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
- } else {
- smu->driver_workload_mask =
- 1 << smu->workload_priority[PP_SMC_POWER_PROFILE_FULLSCREEN3D];
- smu->default_power_profile_mode = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
- }
-
- smu->workload_mask = smu->driver_workload_mask |
- smu->user_dpm_profile.user_workload_mask;
- smu->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
- smu->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
- smu->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
- smu->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO;
- smu->workload_setting[4] = PP_SMC_POWER_PROFILE_VR;
- smu->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE;
- smu->workload_setting[6] = PP_SMC_POWER_PROFILE_CUSTOM;
+ smu_init_power_profile(smu);
smu->display_config = &adev->pm.pm_display_cfg;
smu->smu_dpm.dpm_level = AMD_DPM_FORCED_LEVEL_AUTO;
@@ -1347,6 +1338,11 @@ static int smu_sw_fini(struct amdgpu_ip_block *ip_block)
return ret;
}
+ if (smu->custom_profile_params) {
+ kfree(smu->custom_profile_params);
+ smu->custom_profile_params = NULL;
+ }
+
smu_fini_microcode(smu);
return 0;
@@ -1704,7 +1700,9 @@ static int smu_smc_hw_setup(struct smu_context *smu)
return ret;
}
- if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
+ if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN5)
+ pcie_gen = 4;
+ else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN4)
pcie_gen = 3;
else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3)
pcie_gen = 2;
@@ -1717,7 +1715,9 @@ static int smu_smc_hw_setup(struct smu_context *smu)
* Bit 15:8: PCIE GEN, 0 to 3 corresponds to GEN1 to GEN4
* Bit 7:0: PCIE lane width, 1 to 7 corresponds is x1 to x32
*/
- if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
+ if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X32)
+ pcie_width = 7;
+ else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X16)
pcie_width = 6;
else if (adev->pm.pcie_mlw_mask & CAIL_PCIE_LINK_WIDTH_SUPPORT_X12)
pcie_width = 5;
@@ -2127,6 +2127,9 @@ static int smu_suspend(struct amdgpu_ip_block *ip_block)
if (!ret)
adev->gfx.gfx_off_entrycount = count;
+ /* clear this on suspend so it will get reprogrammed on resume */
+ smu->workload_mask = 0;
+
return 0;
}
@@ -2239,25 +2242,49 @@ static int smu_enable_umd_pstate(void *handle,
}
static int smu_bump_power_profile_mode(struct smu_context *smu,
- long *param,
- uint32_t param_size)
+ long *custom_params,
+ u32 custom_params_max_idx)
{
- int ret = 0;
+ u32 workload_mask = 0;
+ int i, ret = 0;
+
+ for (i = 0; i < PP_SMC_POWER_PROFILE_COUNT; i++) {
+ if (smu->workload_refcount[i])
+ workload_mask |= 1 << i;
+ }
+
+ if (smu->workload_mask == workload_mask)
+ return 0;
if (smu->ppt_funcs->set_power_profile_mode)
- ret = smu->ppt_funcs->set_power_profile_mode(smu, param, param_size);
+ ret = smu->ppt_funcs->set_power_profile_mode(smu, workload_mask,
+ custom_params,
+ custom_params_max_idx);
+
+ if (!ret)
+ smu->workload_mask = workload_mask;
return ret;
}
+static void smu_power_profile_mode_get(struct smu_context *smu,
+ enum PP_SMC_POWER_PROFILE profile_mode)
+{
+ smu->workload_refcount[profile_mode]++;
+}
+
+static void smu_power_profile_mode_put(struct smu_context *smu,
+ enum PP_SMC_POWER_PROFILE profile_mode)
+{
+ if (smu->workload_refcount[profile_mode])
+ smu->workload_refcount[profile_mode]--;
+}
+
static int smu_adjust_power_state_dynamic(struct smu_context *smu,
enum amd_dpm_forced_level level,
- bool skip_display_settings,
- bool init)
+ bool skip_display_settings)
{
int ret = 0;
- int index = 0;
- long workload[1];
struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
if (!skip_display_settings) {
@@ -2294,14 +2321,8 @@ static int smu_adjust_power_state_dynamic(struct smu_context *smu,
}
if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
- smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {
- index = fls(smu->workload_mask);
- index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
- workload[0] = smu->workload_setting[index];
-
- if (init || smu->power_profile_mode != workload[0])
- smu_bump_power_profile_mode(smu, workload, 0);
- }
+ smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
+ smu_bump_power_profile_mode(smu, NULL, 0);
return ret;
}
@@ -2320,13 +2341,13 @@ static int smu_handle_task(struct smu_context *smu,
ret = smu_pre_display_config_changed(smu);
if (ret)
return ret;
- ret = smu_adjust_power_state_dynamic(smu, level, false, false);
+ ret = smu_adjust_power_state_dynamic(smu, level, false);
break;
case AMD_PP_TASK_COMPLETE_INIT:
- ret = smu_adjust_power_state_dynamic(smu, level, true, true);
+ ret = smu_adjust_power_state_dynamic(smu, level, true);
break;
case AMD_PP_TASK_READJUST_POWER_STATE:
- ret = smu_adjust_power_state_dynamic(smu, level, true, false);
+ ret = smu_adjust_power_state_dynamic(smu, level, true);
break;
default:
break;
@@ -2348,12 +2369,11 @@ static int smu_handle_dpm_task(void *handle,
static int smu_switch_power_profile(void *handle,
enum PP_SMC_POWER_PROFILE type,
- bool en)
+ bool enable)
{
struct smu_context *smu = handle;
struct smu_dpm_context *smu_dpm_ctx = &(smu->smu_dpm);
- long workload[1];
- uint32_t index;
+ int ret;
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled)
return -EOPNOTSUPP;
@@ -2361,24 +2381,21 @@ static int smu_switch_power_profile(void *handle,
if (!(type < PP_SMC_POWER_PROFILE_CUSTOM))
return -EINVAL;
- if (!en) {
- smu->driver_workload_mask &= ~(1 << smu->workload_priority[type]);
- index = fls(smu->workload_mask);
- index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
- workload[0] = smu->workload_setting[index];
- } else {
- smu->driver_workload_mask |= (1 << smu->workload_priority[type]);
- index = fls(smu->workload_mask);
- index = index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
- workload[0] = smu->workload_setting[index];
- }
-
- smu->workload_mask = smu->driver_workload_mask |
- smu->user_dpm_profile.user_workload_mask;
-
if (smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_MANUAL &&
- smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM)
- smu_bump_power_profile_mode(smu, workload, 0);
+ smu_dpm_ctx->dpm_level != AMD_DPM_FORCED_LEVEL_PERF_DETERMINISM) {
+ if (enable)
+ smu_power_profile_mode_get(smu, type);
+ else
+ smu_power_profile_mode_put(smu, type);
+ ret = smu_bump_power_profile_mode(smu, NULL, 0);
+ if (ret) {
+ if (enable)
+ smu_power_profile_mode_put(smu, type);
+ else
+ smu_power_profile_mode_get(smu, type);
+ return ret;
+ }
+ }
return 0;
}
@@ -3070,21 +3087,33 @@ static int smu_set_power_profile_mode(void *handle,
uint32_t param_size)
{
struct smu_context *smu = handle;
- int ret;
+ bool custom = false;
+ int ret = 0;
if (!smu->pm_enabled || !smu->adev->pm.dpm_enabled ||
!smu->ppt_funcs->set_power_profile_mode)
return -EOPNOTSUPP;
- if (smu->user_dpm_profile.user_workload_mask &
- (1 << smu->workload_priority[param[param_size]]))
- return 0;
+ if (param[param_size] == PP_SMC_POWER_PROFILE_CUSTOM) {
+ custom = true;
+ /* clear frontend mask so custom changes propogate */
+ smu->workload_mask = 0;
+ }
- smu->user_dpm_profile.user_workload_mask =
- (1 << smu->workload_priority[param[param_size]]);
- smu->workload_mask = smu->user_dpm_profile.user_workload_mask |
- smu->driver_workload_mask;
- ret = smu_bump_power_profile_mode(smu, param, param_size);
+ if ((param[param_size] != smu->power_profile_mode) || custom) {
+ /* clear the old user preference */
+ smu_power_profile_mode_put(smu, smu->power_profile_mode);
+ /* set the new user preference */
+ smu_power_profile_mode_get(smu, param[param_size]);
+ ret = smu_bump_power_profile_mode(smu,
+ custom ? param : NULL,
+ custom ? param_size : 0);
+ if (ret)
+ smu_power_profile_mode_put(smu, param[param_size]);
+ else
+ /* store the user's preference */
+ smu->power_profile_mode = param[param_size];
+ }
return ret;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
index d665c47f19b7..3925815358ce 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/amdgpu_smu.h
@@ -240,7 +240,6 @@ struct smu_user_dpm_profile {
/* user clock state information */
uint32_t clk_mask[SMU_CLK_COUNT];
uint32_t clk_dependency;
- uint32_t user_workload_mask;
};
#define SMU_TABLE_INIT(tables, table_id, s, a, d) \
@@ -557,12 +556,13 @@ struct smu_context {
uint32_t hard_min_uclk_req_from_dal;
bool disable_uclk_switch;
+ /* asic agnostic workload mask */
uint32_t workload_mask;
- uint32_t driver_workload_mask;
- uint32_t workload_priority[WORKLOAD_POLICY_MAX];
- uint32_t workload_setting[WORKLOAD_POLICY_MAX];
+ /* default/user workload preference */
uint32_t power_profile_mode;
- uint32_t default_power_profile_mode;
+ uint32_t workload_refcount[PP_SMC_POWER_PROFILE_COUNT];
+ /* backend specific custom workload settings */
+ long *custom_profile_params;
bool pm_enabled;
bool is_apu;
@@ -733,9 +733,12 @@ struct pptable_funcs {
* @set_power_profile_mode: Set a power profile mode. Also used to
* create/set custom power profile modes.
* &input: Power profile mode parameters.
- * &size: Size of &input.
+ * &workload_mask: mask of workloads to enable
+ * &custom_params: custom profile parameters
+ * &custom_params_max_idx: max valid idx into custom_params
*/
- int (*set_power_profile_mode)(struct smu_context *smu, long *input, uint32_t size);
+ int (*set_power_profile_mode)(struct smu_context *smu, u32 workload_mask,
+ long *custom_params, u32 custom_params_max_idx);
/**
* @dpm_set_vcn_enable: Enable/disable VCN engine dynamic power
diff --git a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
index 0546b02e198d..29a4583db873 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/inc/smu_v14_0.h
@@ -53,7 +53,7 @@
#define CTF_OFFSET_MEM 5
extern const int decoded_link_speed[5];
-extern const int decoded_link_width[7];
+extern const int decoded_link_width[8];
#define DECODE_GEN_SPEED(gen_speed_idx) (decoded_link_speed[gen_speed_idx])
#define DECODE_LANE_WIDTH(lane_width_idx) (decoded_link_width[lane_width_idx])
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
index 4b36c230e43a..8aa61a9f7778 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/arcturus_ppt.c
@@ -1344,8 +1344,12 @@ static int arcturus_get_power_limit(struct smu_context *smu,
*default_power_limit = power_limit;
if (max_power_limit)
*max_power_limit = power_limit;
+ /**
+ * No lower bound is imposed on the limit. Any unreasonable limit set
+ * will result in frequent throttling.
+ */
if (min_power_limit)
- *min_power_limit = power_limit;
+ *min_power_limit = 0;
return 0;
}
@@ -1441,97 +1445,120 @@ static int arcturus_get_power_profile_mode(struct smu_context *smu,
return size;
}
-static int arcturus_set_power_profile_mode(struct smu_context *smu,
- long *input,
- uint32_t size)
+#define ARCTURUS_CUSTOM_PARAMS_COUNT 10
+#define ARCTURUS_CUSTOM_PARAMS_CLOCK_COUNT 2
+#define ARCTURUS_CUSTOM_PARAMS_SIZE (ARCTURUS_CUSTOM_PARAMS_CLOCK_COUNT * ARCTURUS_CUSTOM_PARAMS_COUNT * sizeof(long))
+
+static int arcturus_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input)
{
DpmActivityMonitorCoeffInt_t activity_monitor;
- int workload_type = 0;
- uint32_t profile_mode = input[size];
- int ret = 0;
+ int ret, idx;
- if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
- dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
- return -EINVAL;
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor),
+ false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
}
- if ((profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) &&
- (smu->smc_fw_version >= 0x360d00)) {
- if (size != 10)
- return -EINVAL;
+ idx = 0 * ARCTURUS_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Gfxclk */
+ activity_monitor.Gfx_FPS = input[idx + 1];
+ activity_monitor.Gfx_UseRlcBusy = input[idx + 2];
+ activity_monitor.Gfx_MinActiveFreqType = input[idx + 3];
+ activity_monitor.Gfx_MinActiveFreq = input[idx + 4];
+ activity_monitor.Gfx_BoosterFreqType = input[idx + 5];
+ activity_monitor.Gfx_BoosterFreq = input[idx + 6];
+ activity_monitor.Gfx_PD_Data_limit_c = input[idx + 7];
+ activity_monitor.Gfx_PD_Data_error_coeff = input[idx + 8];
+ activity_monitor.Gfx_PD_Data_error_rate_coeff = input[idx + 9];
+ }
+ idx = 1 * ARCTURUS_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Uclk */
+ activity_monitor.Mem_FPS = input[idx + 1];
+ activity_monitor.Mem_UseRlcBusy = input[idx + 2];
+ activity_monitor.Mem_MinActiveFreqType = input[idx + 3];
+ activity_monitor.Mem_MinActiveFreq = input[idx + 4];
+ activity_monitor.Mem_BoosterFreqType = input[idx + 5];
+ activity_monitor.Mem_BoosterFreq = input[idx + 6];
+ activity_monitor.Mem_PD_Data_limit_c = input[idx + 7];
+ activity_monitor.Mem_PD_Data_error_coeff = input[idx + 8];
+ activity_monitor.Mem_PD_Data_error_rate_coeff = input[idx + 9];
+ }
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor),
- false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor),
+ true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor.Gfx_FPS = input[1];
- activity_monitor.Gfx_UseRlcBusy = input[2];
- activity_monitor.Gfx_MinActiveFreqType = input[3];
- activity_monitor.Gfx_MinActiveFreq = input[4];
- activity_monitor.Gfx_BoosterFreqType = input[5];
- activity_monitor.Gfx_BoosterFreq = input[6];
- activity_monitor.Gfx_PD_Data_limit_c = input[7];
- activity_monitor.Gfx_PD_Data_error_coeff = input[8];
- activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
- break;
- case 1: /* Uclk */
- activity_monitor.Mem_FPS = input[1];
- activity_monitor.Mem_UseRlcBusy = input[2];
- activity_monitor.Mem_MinActiveFreqType = input[3];
- activity_monitor.Mem_MinActiveFreq = input[4];
- activity_monitor.Mem_BoosterFreqType = input[5];
- activity_monitor.Mem_BoosterFreq = input[6];
- activity_monitor.Mem_PD_Data_limit_c = input[7];
- activity_monitor.Mem_PD_Data_error_coeff = input[8];
- activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
- break;
- default:
+ return ret;
+}
+
+static int arcturus_set_power_profile_mode(struct smu_context *smu,
+ u32 workload_mask,
+ long *custom_params,
+ u32 custom_params_max_idx)
+{
+ u32 backend_workload_mask = 0;
+ int ret, idx = -1, i;
+
+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
+ &backend_workload_mask);
+
+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
+ if (smu->smc_fw_version < 0x360d00)
return -EINVAL;
+ if (!smu->custom_profile_params) {
+ smu->custom_profile_params =
+ kzalloc(ARCTURUS_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
+ if (!smu->custom_profile_params)
+ return -ENOMEM;
}
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor),
- true);
+ if (custom_params && custom_params_max_idx) {
+ if (custom_params_max_idx != ARCTURUS_CUSTOM_PARAMS_COUNT)
+ return -EINVAL;
+ if (custom_params[0] >= ARCTURUS_CUSTOM_PARAMS_CLOCK_COUNT)
+ return -EINVAL;
+ idx = custom_params[0] * ARCTURUS_CUSTOM_PARAMS_COUNT;
+ smu->custom_profile_params[idx] = 1;
+ for (i = 1; i < custom_params_max_idx; i++)
+ smu->custom_profile_params[idx + i] = custom_params[i];
+ }
+ ret = arcturus_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_params);
if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
return ret;
}
- }
-
- /*
- * Conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT
- * Not all profile modes are supported on arcturus.
- */
- workload_type = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_WORKLOAD,
- profile_mode);
- if (workload_type < 0) {
- dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on arcturus\n", profile_mode);
- return -EINVAL;
+ } else if (smu->custom_profile_params) {
+ memset(smu->custom_profile_params, 0, ARCTURUS_CUSTOM_PARAMS_SIZE);
}
ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetWorkloadMask,
- smu->workload_mask,
- NULL);
+ SMU_MSG_SetWorkloadMask,
+ backend_workload_mask,
+ NULL);
if (ret) {
- dev_err(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
+ workload_mask);
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
return ret;
}
- smu_cmn_assign_power_profile(smu);
-
- return 0;
+ return ret;
}
static int arcturus_set_performance_level(struct smu_context *smu,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
index 211635dabed8..7fad5dfb39c4 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/navi10_ppt.c
@@ -2006,90 +2006,122 @@ static int navi10_get_power_profile_mode(struct smu_context *smu, char *buf)
return size;
}
-static int navi10_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
+#define NAVI10_CUSTOM_PARAMS_COUNT 10
+#define NAVI10_CUSTOM_PARAMS_CLOCKS_COUNT 3
+#define NAVI10_CUSTOM_PARAMS_SIZE (NAVI10_CUSTOM_PARAMS_CLOCKS_COUNT * NAVI10_CUSTOM_PARAMS_COUNT * sizeof(long))
+
+static int navi10_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input)
{
DpmActivityMonitorCoeffInt_t activity_monitor;
- int workload_type, ret = 0;
+ int ret, idx;
- smu->power_profile_mode = input[size];
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor), false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
- if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
- dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
- return -EINVAL;
+ idx = 0 * NAVI10_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Gfxclk */
+ activity_monitor.Gfx_FPS = input[idx + 1];
+ activity_monitor.Gfx_MinFreqStep = input[idx + 2];
+ activity_monitor.Gfx_MinActiveFreqType = input[idx + 3];
+ activity_monitor.Gfx_MinActiveFreq = input[idx + 4];
+ activity_monitor.Gfx_BoosterFreqType = input[idx + 5];
+ activity_monitor.Gfx_BoosterFreq = input[idx + 6];
+ activity_monitor.Gfx_PD_Data_limit_c = input[idx + 7];
+ activity_monitor.Gfx_PD_Data_error_coeff = input[idx + 8];
+ activity_monitor.Gfx_PD_Data_error_rate_coeff = input[idx + 9];
+ }
+ idx = 1 * NAVI10_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Socclk */
+ activity_monitor.Soc_FPS = input[idx + 1];
+ activity_monitor.Soc_MinFreqStep = input[idx + 2];
+ activity_monitor.Soc_MinActiveFreqType = input[idx + 3];
+ activity_monitor.Soc_MinActiveFreq = input[idx + 4];
+ activity_monitor.Soc_BoosterFreqType = input[idx + 5];
+ activity_monitor.Soc_BoosterFreq = input[idx + 6];
+ activity_monitor.Soc_PD_Data_limit_c = input[idx + 7];
+ activity_monitor.Soc_PD_Data_error_coeff = input[idx + 8];
+ activity_monitor.Soc_PD_Data_error_rate_coeff = input[idx + 9];
+ }
+ idx = 2 * NAVI10_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Memclk */
+ activity_monitor.Mem_FPS = input[idx + 1];
+ activity_monitor.Mem_MinFreqStep = input[idx + 2];
+ activity_monitor.Mem_MinActiveFreqType = input[idx + 3];
+ activity_monitor.Mem_MinActiveFreq = input[idx + 4];
+ activity_monitor.Mem_BoosterFreqType = input[idx + 5];
+ activity_monitor.Mem_BoosterFreq = input[idx + 6];
+ activity_monitor.Mem_PD_Data_limit_c = input[idx + 7];
+ activity_monitor.Mem_PD_Data_error_coeff = input[idx + 8];
+ activity_monitor.Mem_PD_Data_error_rate_coeff = input[idx + 9];
+ }
+
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor), true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
}
- if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
- if (size != 10)
- return -EINVAL;
+ return ret;
+}
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor), false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
+static int navi10_set_power_profile_mode(struct smu_context *smu,
+ u32 workload_mask,
+ long *custom_params,
+ u32 custom_params_max_idx)
+{
+ u32 backend_workload_mask = 0;
+ int ret, idx = -1, i;
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor.Gfx_FPS = input[1];
- activity_monitor.Gfx_MinFreqStep = input[2];
- activity_monitor.Gfx_MinActiveFreqType = input[3];
- activity_monitor.Gfx_MinActiveFreq = input[4];
- activity_monitor.Gfx_BoosterFreqType = input[5];
- activity_monitor.Gfx_BoosterFreq = input[6];
- activity_monitor.Gfx_PD_Data_limit_c = input[7];
- activity_monitor.Gfx_PD_Data_error_coeff = input[8];
- activity_monitor.Gfx_PD_Data_error_rate_coeff = input[9];
- break;
- case 1: /* Socclk */
- activity_monitor.Soc_FPS = input[1];
- activity_monitor.Soc_MinFreqStep = input[2];
- activity_monitor.Soc_MinActiveFreqType = input[3];
- activity_monitor.Soc_MinActiveFreq = input[4];
- activity_monitor.Soc_BoosterFreqType = input[5];
- activity_monitor.Soc_BoosterFreq = input[6];
- activity_monitor.Soc_PD_Data_limit_c = input[7];
- activity_monitor.Soc_PD_Data_error_coeff = input[8];
- activity_monitor.Soc_PD_Data_error_rate_coeff = input[9];
- break;
- case 2: /* Memclk */
- activity_monitor.Mem_FPS = input[1];
- activity_monitor.Mem_MinFreqStep = input[2];
- activity_monitor.Mem_MinActiveFreqType = input[3];
- activity_monitor.Mem_MinActiveFreq = input[4];
- activity_monitor.Mem_BoosterFreqType = input[5];
- activity_monitor.Mem_BoosterFreq = input[6];
- activity_monitor.Mem_PD_Data_limit_c = input[7];
- activity_monitor.Mem_PD_Data_error_coeff = input[8];
- activity_monitor.Mem_PD_Data_error_rate_coeff = input[9];
- break;
- default:
- return -EINVAL;
- }
+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
+ &backend_workload_mask);
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor), true);
+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
+ if (!smu->custom_profile_params) {
+ smu->custom_profile_params = kzalloc(NAVI10_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
+ if (!smu->custom_profile_params)
+ return -ENOMEM;
+ }
+ if (custom_params && custom_params_max_idx) {
+ if (custom_params_max_idx != NAVI10_CUSTOM_PARAMS_COUNT)
+ return -EINVAL;
+ if (custom_params[0] >= NAVI10_CUSTOM_PARAMS_CLOCKS_COUNT)
+ return -EINVAL;
+ idx = custom_params[0] * NAVI10_CUSTOM_PARAMS_COUNT;
+ smu->custom_profile_params[idx] = 1;
+ for (i = 1; i < custom_params_max_idx; i++)
+ smu->custom_profile_params[idx + i] = custom_params[i];
+ }
+ ret = navi10_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_params);
if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
return ret;
}
+ } else if (smu->custom_profile_params) {
+ memset(smu->custom_profile_params, 0, NAVI10_CUSTOM_PARAMS_SIZE);
}
- /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
- workload_type = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_WORKLOAD,
- smu->power_profile_mode);
- if (workload_type < 0)
- return -EINVAL;
-
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
- smu->workload_mask, NULL);
- if (ret)
- dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
- else
- smu_cmn_assign_power_profile(smu);
+ backend_workload_mask, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
+ workload_mask);
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
+ return ret;
+ }
return ret;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
index d0ed0d060a8a..286777ada1df 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/sienna_cichlid_ppt.c
@@ -1708,93 +1708,126 @@ static int sienna_cichlid_get_power_profile_mode(struct smu_context *smu, char *
return size;
}
-static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
+#define SIENNA_CICHLID_CUSTOM_PARAMS_COUNT 10
+#define SIENNA_CICHLID_CUSTOM_PARAMS_CLOCK_COUNT 3
+#define SIENNA_CICHLID_CUSTOM_PARAMS_SIZE (SIENNA_CICHLID_CUSTOM_PARAMS_CLOCK_COUNT * SIENNA_CICHLID_CUSTOM_PARAMS_COUNT * sizeof(long))
+
+static int sienna_cichlid_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input)
{
DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
DpmActivityMonitorCoeffInt_t *activity_monitor =
&(activity_monitor_external.DpmActivityMonitorCoeffInt);
- int workload_type, ret = 0;
+ int ret, idx;
- smu->power_profile_mode = input[size];
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external), false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
- if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
- dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
- return -EINVAL;
+ idx = 0 * SIENNA_CICHLID_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Gfxclk */
+ activity_monitor->Gfx_FPS = input[idx + 1];
+ activity_monitor->Gfx_MinFreqStep = input[idx + 2];
+ activity_monitor->Gfx_MinActiveFreqType = input[idx + 3];
+ activity_monitor->Gfx_MinActiveFreq = input[idx + 4];
+ activity_monitor->Gfx_BoosterFreqType = input[idx + 5];
+ activity_monitor->Gfx_BoosterFreq = input[idx + 6];
+ activity_monitor->Gfx_PD_Data_limit_c = input[idx + 7];
+ activity_monitor->Gfx_PD_Data_error_coeff = input[idx + 8];
+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[idx + 9];
+ }
+ idx = 1 * SIENNA_CICHLID_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Socclk */
+ activity_monitor->Fclk_FPS = input[idx + 1];
+ activity_monitor->Fclk_MinFreqStep = input[idx + 2];
+ activity_monitor->Fclk_MinActiveFreqType = input[idx + 3];
+ activity_monitor->Fclk_MinActiveFreq = input[idx + 4];
+ activity_monitor->Fclk_BoosterFreqType = input[idx + 5];
+ activity_monitor->Fclk_BoosterFreq = input[idx + 6];
+ activity_monitor->Fclk_PD_Data_limit_c = input[idx + 7];
+ activity_monitor->Fclk_PD_Data_error_coeff = input[idx + 8];
+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[idx + 9];
+ }
+ idx = 2 * SIENNA_CICHLID_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Memclk */
+ activity_monitor->Mem_FPS = input[idx + 1];
+ activity_monitor->Mem_MinFreqStep = input[idx + 2];
+ activity_monitor->Mem_MinActiveFreqType = input[idx + 3];
+ activity_monitor->Mem_MinActiveFreq = input[idx + 4];
+ activity_monitor->Mem_BoosterFreqType = input[idx + 5];
+ activity_monitor->Mem_BoosterFreq = input[idx + 6];
+ activity_monitor->Mem_PD_Data_limit_c = input[idx + 7];
+ activity_monitor->Mem_PD_Data_error_coeff = input[idx + 8];
+ activity_monitor->Mem_PD_Data_error_rate_coeff = input[idx + 9];
}
- if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
- if (size != 10)
- return -EINVAL;
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external), true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external), false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
+ return ret;
+}
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor->Gfx_FPS = input[1];
- activity_monitor->Gfx_MinFreqStep = input[2];
- activity_monitor->Gfx_MinActiveFreqType = input[3];
- activity_monitor->Gfx_MinActiveFreq = input[4];
- activity_monitor->Gfx_BoosterFreqType = input[5];
- activity_monitor->Gfx_BoosterFreq = input[6];
- activity_monitor->Gfx_PD_Data_limit_c = input[7];
- activity_monitor->Gfx_PD_Data_error_coeff = input[8];
- activity_monitor->Gfx_PD_Data_error_rate_coeff = input[9];
- break;
- case 1: /* Socclk */
- activity_monitor->Fclk_FPS = input[1];
- activity_monitor->Fclk_MinFreqStep = input[2];
- activity_monitor->Fclk_MinActiveFreqType = input[3];
- activity_monitor->Fclk_MinActiveFreq = input[4];
- activity_monitor->Fclk_BoosterFreqType = input[5];
- activity_monitor->Fclk_BoosterFreq = input[6];
- activity_monitor->Fclk_PD_Data_limit_c = input[7];
- activity_monitor->Fclk_PD_Data_error_coeff = input[8];
- activity_monitor->Fclk_PD_Data_error_rate_coeff = input[9];
- break;
- case 2: /* Memclk */
- activity_monitor->Mem_FPS = input[1];
- activity_monitor->Mem_MinFreqStep = input[2];
- activity_monitor->Mem_MinActiveFreqType = input[3];
- activity_monitor->Mem_MinActiveFreq = input[4];
- activity_monitor->Mem_BoosterFreqType = input[5];
- activity_monitor->Mem_BoosterFreq = input[6];
- activity_monitor->Mem_PD_Data_limit_c = input[7];
- activity_monitor->Mem_PD_Data_error_coeff = input[8];
- activity_monitor->Mem_PD_Data_error_rate_coeff = input[9];
- break;
- default:
- return -EINVAL;
- }
+static int sienna_cichlid_set_power_profile_mode(struct smu_context *smu,
+ u32 workload_mask,
+ long *custom_params,
+ u32 custom_params_max_idx)
+{
+ u32 backend_workload_mask = 0;
+ int ret, idx = -1, i;
+
+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
+ &backend_workload_mask);
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external), true);
+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
+ if (!smu->custom_profile_params) {
+ smu->custom_profile_params =
+ kzalloc(SIENNA_CICHLID_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
+ if (!smu->custom_profile_params)
+ return -ENOMEM;
+ }
+ if (custom_params && custom_params_max_idx) {
+ if (custom_params_max_idx != SIENNA_CICHLID_CUSTOM_PARAMS_COUNT)
+ return -EINVAL;
+ if (custom_params[0] >= SIENNA_CICHLID_CUSTOM_PARAMS_CLOCK_COUNT)
+ return -EINVAL;
+ idx = custom_params[0] * SIENNA_CICHLID_CUSTOM_PARAMS_COUNT;
+ smu->custom_profile_params[idx] = 1;
+ for (i = 1; i < custom_params_max_idx; i++)
+ smu->custom_profile_params[idx + i] = custom_params[i];
+ }
+ ret = sienna_cichlid_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_params);
if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
return ret;
}
+ } else if (smu->custom_profile_params) {
+ memset(smu->custom_profile_params, 0, SIENNA_CICHLID_CUSTOM_PARAMS_SIZE);
}
- /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
- workload_type = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_WORKLOAD,
- smu->power_profile_mode);
- if (workload_type < 0)
- return -EINVAL;
-
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
- smu->workload_mask, NULL);
- if (ret)
- dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
- else
- smu_cmn_assign_power_profile(smu);
+ backend_workload_mask, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
+ workload_mask);
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
+ return ret;
+ }
return ret;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
index f89c487dce72..a55ea76d7399 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c
@@ -1056,42 +1056,27 @@ static int vangogh_get_power_profile_mode(struct smu_context *smu,
return size;
}
-static int vangogh_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
+static int vangogh_set_power_profile_mode(struct smu_context *smu,
+ u32 workload_mask,
+ long *custom_params,
+ u32 custom_params_max_idx)
{
- int workload_type, ret;
- uint32_t profile_mode = input[size];
+ u32 backend_workload_mask = 0;
+ int ret;
- if (profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
- dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
- return -EINVAL;
- }
-
- if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT ||
- profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)
- return 0;
-
- /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
- workload_type = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_WORKLOAD,
- profile_mode);
- if (workload_type < 0) {
- dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on VANGOGH\n",
- profile_mode);
- return -EINVAL;
- }
+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
+ &backend_workload_mask);
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
- smu->workload_mask,
- NULL);
+ backend_workload_mask,
+ NULL);
if (ret) {
- dev_err_once(smu->adev->dev, "Fail to set workload type %d\n",
- workload_type);
+ dev_err_once(smu->adev->dev, "Fail to set workload mask 0x%08x\n",
+ workload_mask);
return ret;
}
- smu_cmn_assign_power_profile(smu);
-
- return 0;
+ return ret;
}
static int vangogh_set_soft_freq_limited_range(struct smu_context *smu,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
index 75a9ea87f419..37d82a71a2d7 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu12/renoir_ppt.c
@@ -864,44 +864,27 @@ static int renoir_force_clk_levels(struct smu_context *smu,
return ret;
}
-static int renoir_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
+static int renoir_set_power_profile_mode(struct smu_context *smu,
+ u32 workload_mask,
+ long *custom_params,
+ u32 custom_params_max_idx)
{
- int workload_type, ret;
- uint32_t profile_mode = input[size];
+ int ret;
+ u32 backend_workload_mask = 0;
- if (profile_mode > PP_SMC_POWER_PROFILE_CUSTOM) {
- dev_err(smu->adev->dev, "Invalid power profile mode %d\n", profile_mode);
- return -EINVAL;
- }
-
- if (profile_mode == PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT ||
- profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING)
- return 0;
-
- /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
- workload_type = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_WORKLOAD,
- profile_mode);
- if (workload_type < 0) {
- /*
- * TODO: If some case need switch to powersave/default power mode
- * then can consider enter WORKLOAD_COMPUTE/WORKLOAD_CUSTOM for power saving.
- */
- dev_dbg(smu->adev->dev, "Unsupported power profile mode %d on RENOIR\n", profile_mode);
- return -EINVAL;
- }
+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
+ &backend_workload_mask);
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_ActiveProcessNotify,
- smu->workload_mask,
- NULL);
+ backend_workload_mask,
+ NULL);
if (ret) {
- dev_err_once(smu->adev->dev, "Fail to set workload type %d\n", workload_type);
+ dev_err_once(smu->adev->dev, "Failed to set workload mask 0x08%x\n",
+ workload_mask);
return ret;
}
- smu_cmn_assign_power_profile(smu);
-
- return 0;
+ return ret;
}
static int renoir_set_peak_clock_by_device(struct smu_context *smu)
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
index 80c6b1e523aa..3aa705aae4c0 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_0_ppt.c
@@ -2571,82 +2571,76 @@ static int smu_v13_0_0_get_power_profile_mode(struct smu_context *smu,
return size;
}
-static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
- long *input,
- uint32_t size)
+#define SMU_13_0_0_CUSTOM_PARAMS_COUNT 9
+#define SMU_13_0_0_CUSTOM_PARAMS_CLOCK_COUNT 2
+#define SMU_13_0_0_CUSTOM_PARAMS_SIZE (SMU_13_0_0_CUSTOM_PARAMS_CLOCK_COUNT * SMU_13_0_0_CUSTOM_PARAMS_COUNT * sizeof(long))
+
+static int smu_v13_0_0_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input)
{
DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
DpmActivityMonitorCoeffInt_t *activity_monitor =
&(activity_monitor_external.DpmActivityMonitorCoeffInt);
- int workload_type, ret = 0;
- u32 workload_mask;
-
- smu->power_profile_mode = input[size];
+ int ret, idx;
- if (smu->power_profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
- dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
- return -EINVAL;
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external),
+ false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
}
- if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
- if (size != 9)
- return -EINVAL;
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external),
- false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
-
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor->Gfx_FPS = input[1];
- activity_monitor->Gfx_MinActiveFreqType = input[2];
- activity_monitor->Gfx_MinActiveFreq = input[3];
- activity_monitor->Gfx_BoosterFreqType = input[4];
- activity_monitor->Gfx_BoosterFreq = input[5];
- activity_monitor->Gfx_PD_Data_limit_c = input[6];
- activity_monitor->Gfx_PD_Data_error_coeff = input[7];
- activity_monitor->Gfx_PD_Data_error_rate_coeff = input[8];
- break;
- case 1: /* Fclk */
- activity_monitor->Fclk_FPS = input[1];
- activity_monitor->Fclk_MinActiveFreqType = input[2];
- activity_monitor->Fclk_MinActiveFreq = input[3];
- activity_monitor->Fclk_BoosterFreqType = input[4];
- activity_monitor->Fclk_BoosterFreq = input[5];
- activity_monitor->Fclk_PD_Data_limit_c = input[6];
- activity_monitor->Fclk_PD_Data_error_coeff = input[7];
- activity_monitor->Fclk_PD_Data_error_rate_coeff = input[8];
- break;
- default:
- return -EINVAL;
- }
+ idx = 0 * SMU_13_0_0_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Gfxclk */
+ activity_monitor->Gfx_FPS = input[idx + 1];
+ activity_monitor->Gfx_MinActiveFreqType = input[idx + 2];
+ activity_monitor->Gfx_MinActiveFreq = input[idx + 3];
+ activity_monitor->Gfx_BoosterFreqType = input[idx + 4];
+ activity_monitor->Gfx_BoosterFreq = input[idx + 5];
+ activity_monitor->Gfx_PD_Data_limit_c = input[idx + 6];
+ activity_monitor->Gfx_PD_Data_error_coeff = input[idx + 7];
+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[idx + 8];
+ }
+ idx = 1 * SMU_13_0_0_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Fclk */
+ activity_monitor->Fclk_FPS = input[idx + 1];
+ activity_monitor->Fclk_MinActiveFreqType = input[idx + 2];
+ activity_monitor->Fclk_MinActiveFreq = input[idx + 3];
+ activity_monitor->Fclk_BoosterFreqType = input[idx + 4];
+ activity_monitor->Fclk_BoosterFreq = input[idx + 5];
+ activity_monitor->Fclk_PD_Data_limit_c = input[idx + 6];
+ activity_monitor->Fclk_PD_Data_error_coeff = input[idx + 7];
+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[idx + 8];
+ }
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external),
- true);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
- return ret;
- }
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external),
+ true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
}
- /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
- workload_type = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_WORKLOAD,
- smu->power_profile_mode);
+ return ret;
+}
- if (workload_type < 0)
- return -EINVAL;
+static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
+ u32 workload_mask,
+ long *custom_params,
+ u32 custom_params_max_idx)
+{
+ u32 backend_workload_mask = 0;
+ int workload_type, ret, idx = -1, i;
- workload_mask = 1 << workload_type;
+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
+ &backend_workload_mask);
/* Add optimizations for SMU13.0.0/10. Reuse the power saving profile */
if ((amdgpu_ip_version(smu->adev, MP1_HWIP, 0) == IP_VERSION(13, 0, 0) &&
@@ -2658,24 +2652,47 @@ static int smu_v13_0_0_set_power_profile_mode(struct smu_context *smu,
CMN2ASIC_MAPPING_WORKLOAD,
PP_SMC_POWER_PROFILE_POWERSAVING);
if (workload_type >= 0)
- workload_mask |= 1 << workload_type;
+ backend_workload_mask |= 1 << workload_type;
}
- smu->workload_mask |= workload_mask;
- ret = smu_cmn_send_smc_msg_with_param(smu,
- SMU_MSG_SetWorkloadMask,
- smu->workload_mask,
- NULL);
- if (!ret) {
- smu_cmn_assign_power_profile(smu);
- if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_POWERSAVING) {
- workload_type = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_WORKLOAD,
- PP_SMC_POWER_PROFILE_FULLSCREEN3D);
- smu->power_profile_mode = smu->workload_mask & (1 << workload_type)
- ? PP_SMC_POWER_PROFILE_FULLSCREEN3D
- : PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
+ if (!smu->custom_profile_params) {
+ smu->custom_profile_params =
+ kzalloc(SMU_13_0_0_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
+ if (!smu->custom_profile_params)
+ return -ENOMEM;
}
+ if (custom_params && custom_params_max_idx) {
+ if (custom_params_max_idx != SMU_13_0_0_CUSTOM_PARAMS_COUNT)
+ return -EINVAL;
+ if (custom_params[0] >= SMU_13_0_0_CUSTOM_PARAMS_CLOCK_COUNT)
+ return -EINVAL;
+ idx = custom_params[0] * SMU_13_0_0_CUSTOM_PARAMS_COUNT;
+ smu->custom_profile_params[idx] = 1;
+ for (i = 1; i < custom_params_max_idx; i++)
+ smu->custom_profile_params[idx + i] = custom_params[i];
+ }
+ ret = smu_v13_0_0_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_params);
+ if (ret) {
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
+ return ret;
+ }
+ } else if (smu->custom_profile_params) {
+ memset(smu->custom_profile_params, 0, SMU_13_0_0_CUSTOM_PARAMS_SIZE);
+ }
+
+ ret = smu_cmn_send_smc_msg_with_param(smu,
+ SMU_MSG_SetWorkloadMask,
+ backend_workload_mask,
+ NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
+ workload_mask);
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
+ return ret;
}
return ret;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
index fa30a9e1f27a..ab3c93ddce46 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_6_ppt.c
@@ -96,7 +96,6 @@ MODULE_FIRMWARE("amdgpu/smu_13_0_14.bin");
#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK 0xE0
#define PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT 0x5
#define LINK_SPEED_MAX 4
-
#define SMU_13_0_6_DSCLK_THRESHOLD 140
#define MCA_BANK_IPID(_ip, _hwid, _type) \
@@ -370,7 +369,7 @@ static int smu_v13_0_6_tables_init(struct smu_context *smu)
return -ENOMEM;
smu_table->metrics_time = 0;
- smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_6);
+ smu_table->gpu_metrics_table_size = sizeof(struct gpu_metrics_v1_7);
smu_table->gpu_metrics_table =
kzalloc(smu_table->gpu_metrics_table_size, GFP_KERNEL);
if (!smu_table->gpu_metrics_table) {
@@ -2321,8 +2320,8 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
{
bool per_inst, smu_13_0_6_per_inst, smu_13_0_14_per_inst, apu_per_inst;
struct smu_table_context *smu_table = &smu->smu_table;
- struct gpu_metrics_v1_6 *gpu_metrics =
- (struct gpu_metrics_v1_6 *)smu_table->gpu_metrics_table;
+ struct gpu_metrics_v1_7 *gpu_metrics =
+ (struct gpu_metrics_v1_7 *)smu_table->gpu_metrics_table;
bool flag = smu_v13_0_6_is_unified_metrics(smu);
int ret = 0, xcc_id, inst, i, j, k, idx;
struct amdgpu_device *adev = smu->adev;
@@ -2341,7 +2340,7 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
metrics_a = (MetricsTableA_t *)metrics_x;
- smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 6);
+ smu_cmn_init_soft_gpu_metrics(gpu_metrics, 1, 7);
gpu_metrics->temperature_hotspot =
SMUQ10_ROUND(GET_METRIC_FIELD(MaxSocketTemperature, flag));
@@ -2448,6 +2447,9 @@ static ssize_t smu_v13_0_6_get_gpu_metrics(struct smu_context *smu, void **table
SMUQ10_ROUND(GET_METRIC_FIELD(XgmiReadDataSizeAcc, flag)[i]);
gpu_metrics->xgmi_write_data_acc[i] =
SMUQ10_ROUND(GET_METRIC_FIELD(XgmiWriteDataSizeAcc, flag)[i]);
+ ret = amdgpu_get_xgmi_link_status(adev, i);
+ if (ret >= 0)
+ gpu_metrics->xgmi_link_status[i] = ret;
}
gpu_metrics->num_partition = adev->xcp_mgr->num_xcps;
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
index c5d3e25cc967..aabb94796005 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu13/smu_v13_0_7_ppt.c
@@ -2147,6 +2147,8 @@ static ssize_t smu_v13_0_7_get_gpu_metrics(struct smu_context *smu,
gpu_metrics->average_dclk1_frequency = metrics->AverageDclk1Frequency;
gpu_metrics->current_gfxclk = metrics->CurrClock[PPCLK_GFXCLK];
+ gpu_metrics->current_socclk = metrics->CurrClock[PPCLK_SOCCLK];
+ gpu_metrics->current_uclk = metrics->CurrClock[PPCLK_UCLK];
gpu_metrics->current_vclk0 = metrics->CurrClock[PPCLK_VCLK_0];
gpu_metrics->current_dclk0 = metrics->CurrClock[PPCLK_DCLK_0];
gpu_metrics->current_vclk1 = metrics->CurrClock[PPCLK_VCLK_1];
@@ -2528,79 +2530,110 @@ out:
return result;
}
-static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu, long *input, uint32_t size)
+#define SMU_13_0_7_CUSTOM_PARAMS_COUNT 8
+#define SMU_13_0_7_CUSTOM_PARAMS_CLOCK_COUNT 2
+#define SMU_13_0_7_CUSTOM_PARAMS_SIZE (SMU_13_0_7_CUSTOM_PARAMS_CLOCK_COUNT * SMU_13_0_7_CUSTOM_PARAMS_COUNT * sizeof(long))
+
+static int smu_v13_0_7_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input)
{
DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
DpmActivityMonitorCoeffInt_t *activity_monitor =
&(activity_monitor_external.DpmActivityMonitorCoeffInt);
- int workload_type, ret = 0;
+ int ret, idx;
- smu->power_profile_mode = input[size];
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external), false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
+ }
- if (smu->power_profile_mode > PP_SMC_POWER_PROFILE_WINDOW3D) {
- dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
- return -EINVAL;
+ idx = 0 * SMU_13_0_7_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Gfxclk */
+ activity_monitor->Gfx_ActiveHystLimit = input[idx + 1];
+ activity_monitor->Gfx_IdleHystLimit = input[idx + 2];
+ activity_monitor->Gfx_FPS = input[idx + 3];
+ activity_monitor->Gfx_MinActiveFreqType = input[idx + 4];
+ activity_monitor->Gfx_BoosterFreqType = input[idx + 5];
+ activity_monitor->Gfx_MinActiveFreq = input[idx + 6];
+ activity_monitor->Gfx_BoosterFreq = input[idx + 7];
+ }
+ idx = 1 * SMU_13_0_7_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Fclk */
+ activity_monitor->Fclk_ActiveHystLimit = input[idx + 1];
+ activity_monitor->Fclk_IdleHystLimit = input[idx + 2];
+ activity_monitor->Fclk_FPS = input[idx + 3];
+ activity_monitor->Fclk_MinActiveFreqType = input[idx + 4];
+ activity_monitor->Fclk_BoosterFreqType = input[idx + 5];
+ activity_monitor->Fclk_MinActiveFreq = input[idx + 6];
+ activity_monitor->Fclk_BoosterFreq = input[idx + 7];
}
- if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
- if (size != 8)
- return -EINVAL;
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external), true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external), false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
+ return ret;
+}
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor->Gfx_ActiveHystLimit = input[1];
- activity_monitor->Gfx_IdleHystLimit = input[2];
- activity_monitor->Gfx_FPS = input[3];
- activity_monitor->Gfx_MinActiveFreqType = input[4];
- activity_monitor->Gfx_BoosterFreqType = input[5];
- activity_monitor->Gfx_MinActiveFreq = input[6];
- activity_monitor->Gfx_BoosterFreq = input[7];
- break;
- case 1: /* Fclk */
- activity_monitor->Fclk_ActiveHystLimit = input[1];
- activity_monitor->Fclk_IdleHystLimit = input[2];
- activity_monitor->Fclk_FPS = input[3];
- activity_monitor->Fclk_MinActiveFreqType = input[4];
- activity_monitor->Fclk_BoosterFreqType = input[5];
- activity_monitor->Fclk_MinActiveFreq = input[6];
- activity_monitor->Fclk_BoosterFreq = input[7];
- break;
- default:
- return -EINVAL;
+static int smu_v13_0_7_set_power_profile_mode(struct smu_context *smu,
+ u32 workload_mask,
+ long *custom_params,
+ u32 custom_params_max_idx)
+{
+ u32 backend_workload_mask = 0;
+ int ret, idx = -1, i;
+
+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
+ &backend_workload_mask);
+
+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
+ if (!smu->custom_profile_params) {
+ smu->custom_profile_params =
+ kzalloc(SMU_13_0_7_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
+ if (!smu->custom_profile_params)
+ return -ENOMEM;
}
-
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF, WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external), true);
+ if (custom_params && custom_params_max_idx) {
+ if (custom_params_max_idx != SMU_13_0_7_CUSTOM_PARAMS_COUNT)
+ return -EINVAL;
+ if (custom_params[0] >= SMU_13_0_7_CUSTOM_PARAMS_CLOCK_COUNT)
+ return -EINVAL;
+ idx = custom_params[0] * SMU_13_0_7_CUSTOM_PARAMS_COUNT;
+ smu->custom_profile_params[idx] = 1;
+ for (i = 1; i < custom_params_max_idx; i++)
+ smu->custom_profile_params[idx + i] = custom_params[i];
+ }
+ ret = smu_v13_0_7_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_params);
if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
return ret;
}
+ } else if (smu->custom_profile_params) {
+ memset(smu->custom_profile_params, 0, SMU_13_0_7_CUSTOM_PARAMS_SIZE);
}
- /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
- workload_type = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_WORKLOAD,
- smu->power_profile_mode);
- if (workload_type < 0)
- return -EINVAL;
-
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
- smu->workload_mask, NULL);
+ backend_workload_mask, NULL);
- if (ret)
- dev_err(smu->adev->dev, "[%s] Failed to set work load mask!", __func__);
- else
- smu_cmn_assign_power_profile(smu);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
+ workload_mask);
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
+ return ret;
+ }
return ret;
}
@@ -2777,4 +2810,5 @@ void smu_v13_0_7_set_ppt_funcs(struct smu_context *smu)
smu->workload_map = smu_v13_0_7_workload_map;
smu->smc_driver_if_version = SMU13_0_7_DRIVER_IF_VERSION;
smu_v13_0_set_smu_mailbox_registers(smu);
+ smu->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
index ecb0164d533e..a87040cb2f2e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0.c
@@ -49,7 +49,7 @@
#define regMP1_SMN_IH_SW_INT_CTRL_mp1_14_0_0_BASE_IDX 0
const int decoded_link_speed[5] = {1, 2, 3, 4, 5};
-const int decoded_link_width[7] = {0, 1, 2, 4, 8, 12, 16};
+const int decoded_link_width[8] = {0, 1, 2, 4, 8, 12, 16, 32};
/*
* DO NOT use these for err/warn/info/debug messages.
* Use dev_err, dev_warn, dev_info and dev_dbg instead.
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
index 59b369eff30f..5cad09c5f2ff 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu14/smu_v14_0_2_ppt.c
@@ -1173,13 +1173,15 @@ static int smu_v14_0_2_print_clk_levels(struct smu_context *smu,
(pcie_table->pcie_gen[i] == 0) ? "2.5GT/s," :
(pcie_table->pcie_gen[i] == 1) ? "5.0GT/s," :
(pcie_table->pcie_gen[i] == 2) ? "8.0GT/s," :
- (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," : "",
+ (pcie_table->pcie_gen[i] == 3) ? "16.0GT/s," :
+ (pcie_table->pcie_gen[i] == 4) ? "32.0GT/s," : "",
(pcie_table->pcie_lane[i] == 1) ? "x1" :
(pcie_table->pcie_lane[i] == 2) ? "x2" :
(pcie_table->pcie_lane[i] == 3) ? "x4" :
(pcie_table->pcie_lane[i] == 4) ? "x8" :
(pcie_table->pcie_lane[i] == 5) ? "x12" :
- (pcie_table->pcie_lane[i] == 6) ? "x16" : "",
+ (pcie_table->pcie_lane[i] == 6) ? "x16" :
+ (pcie_table->pcie_lane[i] == 7) ? "x32" : "",
pcie_table->clk_freq[i],
(gen_speed == DECODE_GEN_SPEED(pcie_table->pcie_gen[i])) &&
(lane_width == DECODE_LANE_WIDTH(pcie_table->pcie_lane[i])) ?
@@ -1463,15 +1465,35 @@ static int smu_v14_0_2_update_pcie_parameters(struct smu_context *smu,
struct smu_14_0_dpm_context *dpm_context = smu->smu_dpm.dpm_context;
struct smu_14_0_pcie_table *pcie_table =
&dpm_context->dpm_tables.pcie_table;
+ int num_of_levels = pcie_table->num_of_link_levels;
uint32_t smu_pcie_arg;
int ret, i;
- for (i = 0; i < pcie_table->num_of_link_levels; i++) {
- if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+ if (!num_of_levels)
+ return 0;
+
+ if (!(smu->adev->pm.pp_feature & PP_PCIE_DPM_MASK)) {
+ if (pcie_table->pcie_gen[num_of_levels - 1] < pcie_gen_cap)
+ pcie_gen_cap = pcie_table->pcie_gen[num_of_levels - 1];
+
+ if (pcie_table->pcie_lane[num_of_levels - 1] < pcie_width_cap)
+ pcie_width_cap = pcie_table->pcie_lane[num_of_levels - 1];
+
+ /* Force all levels to use the same settings */
+ for (i = 0; i < num_of_levels; i++) {
pcie_table->pcie_gen[i] = pcie_gen_cap;
- if (pcie_table->pcie_lane[i] > pcie_width_cap)
pcie_table->pcie_lane[i] = pcie_width_cap;
+ }
+ } else {
+ for (i = 0; i < num_of_levels; i++) {
+ if (pcie_table->pcie_gen[i] > pcie_gen_cap)
+ pcie_table->pcie_gen[i] = pcie_gen_cap;
+ if (pcie_table->pcie_lane[i] > pcie_width_cap)
+ pcie_table->pcie_lane[i] = pcie_width_cap;
+ }
+ }
+ for (i = 0; i < num_of_levels; i++) {
smu_pcie_arg = i << 16;
smu_pcie_arg |= pcie_table->pcie_gen[i] << 8;
smu_pcie_arg |= pcie_table->pcie_lane[i];
@@ -1717,89 +1739,120 @@ static int smu_v14_0_2_get_power_profile_mode(struct smu_context *smu,
return size;
}
-static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
- long *input,
- uint32_t size)
+#define SMU_14_0_2_CUSTOM_PARAMS_COUNT 9
+#define SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT 2
+#define SMU_14_0_2_CUSTOM_PARAMS_SIZE (SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT * SMU_14_0_2_CUSTOM_PARAMS_COUNT * sizeof(long))
+
+static int smu_v14_0_2_set_power_profile_mode_coeff(struct smu_context *smu,
+ long *input)
{
DpmActivityMonitorCoeffIntExternal_t activity_monitor_external;
DpmActivityMonitorCoeffInt_t *activity_monitor =
&(activity_monitor_external.DpmActivityMonitorCoeffInt);
- int workload_type, ret = 0;
- uint32_t current_profile_mode = smu->power_profile_mode;
- smu->power_profile_mode = input[size];
+ int ret, idx;
- if (smu->power_profile_mode >= PP_SMC_POWER_PROFILE_COUNT) {
- dev_err(smu->adev->dev, "Invalid power profile mode %d\n", smu->power_profile_mode);
- return -EINVAL;
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external),
+ false);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
+ return ret;
}
- if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_CUSTOM) {
- if (size != 9)
- return -EINVAL;
+ idx = 0 * SMU_14_0_2_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Gfxclk */
+ activity_monitor->Gfx_FPS = input[idx + 1];
+ activity_monitor->Gfx_MinActiveFreqType = input[idx + 2];
+ activity_monitor->Gfx_MinActiveFreq = input[idx + 3];
+ activity_monitor->Gfx_BoosterFreqType = input[idx + 4];
+ activity_monitor->Gfx_BoosterFreq = input[idx + 5];
+ activity_monitor->Gfx_PD_Data_limit_c = input[idx + 6];
+ activity_monitor->Gfx_PD_Data_error_coeff = input[idx + 7];
+ activity_monitor->Gfx_PD_Data_error_rate_coeff = input[idx + 8];
+ }
+ idx = 1 * SMU_14_0_2_CUSTOM_PARAMS_COUNT;
+ if (input[idx]) {
+ /* Fclk */
+ activity_monitor->Fclk_FPS = input[idx + 1];
+ activity_monitor->Fclk_MinActiveFreqType = input[idx + 2];
+ activity_monitor->Fclk_MinActiveFreq = input[idx + 3];
+ activity_monitor->Fclk_BoosterFreqType = input[idx + 4];
+ activity_monitor->Fclk_BoosterFreq = input[idx + 5];
+ activity_monitor->Fclk_PD_Data_limit_c = input[idx + 6];
+ activity_monitor->Fclk_PD_Data_error_coeff = input[idx + 7];
+ activity_monitor->Fclk_PD_Data_error_rate_coeff = input[idx + 8];
+ }
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external),
- false);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to get activity monitor!", __func__);
- return ret;
- }
+ ret = smu_cmn_update_table(smu,
+ SMU_TABLE_ACTIVITY_MONITOR_COEFF,
+ WORKLOAD_PPLIB_CUSTOM_BIT,
+ (void *)(&activity_monitor_external),
+ true);
+ if (ret) {
+ dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
+ return ret;
+ }
- switch (input[0]) {
- case 0: /* Gfxclk */
- activity_monitor->Gfx_FPS = input[1];
- activity_monitor->Gfx_MinActiveFreqType = input[2];
- activity_monitor->Gfx_MinActiveFreq = input[3];
- activity_monitor->Gfx_BoosterFreqType = input[4];
- activity_monitor->Gfx_BoosterFreq = input[5];
- activity_monitor->Gfx_PD_Data_limit_c = input[6];
- activity_monitor->Gfx_PD_Data_error_coeff = input[7];
- activity_monitor->Gfx_PD_Data_error_rate_coeff = input[8];
- break;
- case 1: /* Fclk */
- activity_monitor->Fclk_FPS = input[1];
- activity_monitor->Fclk_MinActiveFreqType = input[2];
- activity_monitor->Fclk_MinActiveFreq = input[3];
- activity_monitor->Fclk_BoosterFreqType = input[4];
- activity_monitor->Fclk_BoosterFreq = input[5];
- activity_monitor->Fclk_PD_Data_limit_c = input[6];
- activity_monitor->Fclk_PD_Data_error_coeff = input[7];
- activity_monitor->Fclk_PD_Data_error_rate_coeff = input[8];
- break;
- default:
- return -EINVAL;
- }
+ return ret;
+}
- ret = smu_cmn_update_table(smu,
- SMU_TABLE_ACTIVITY_MONITOR_COEFF,
- WORKLOAD_PPLIB_CUSTOM_BIT,
- (void *)(&activity_monitor_external),
- true);
- if (ret) {
- dev_err(smu->adev->dev, "[%s] Failed to set activity monitor!", __func__);
- return ret;
- }
- }
+static int smu_v14_0_2_set_power_profile_mode(struct smu_context *smu,
+ u32 workload_mask,
+ long *custom_params,
+ u32 custom_params_max_idx)
+{
+ u32 backend_workload_mask = 0;
+ int ret, idx = -1, i;
+
+ smu_cmn_get_backend_workload_mask(smu, workload_mask,
+ &backend_workload_mask);
- if (smu->power_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE)
+ /* disable deep sleep if compute is enabled */
+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_COMPUTE))
smu_v14_0_deep_sleep_control(smu, false);
- else if (current_profile_mode == PP_SMC_POWER_PROFILE_COMPUTE)
+ else
smu_v14_0_deep_sleep_control(smu, true);
- /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
- workload_type = smu_cmn_to_asic_specific_index(smu,
- CMN2ASIC_MAPPING_WORKLOAD,
- smu->power_profile_mode);
- if (workload_type < 0)
- return -EINVAL;
+ if (workload_mask & (1 << PP_SMC_POWER_PROFILE_CUSTOM)) {
+ if (!smu->custom_profile_params) {
+ smu->custom_profile_params =
+ kzalloc(SMU_14_0_2_CUSTOM_PARAMS_SIZE, GFP_KERNEL);
+ if (!smu->custom_profile_params)
+ return -ENOMEM;
+ }
+ if (custom_params && custom_params_max_idx) {
+ if (custom_params_max_idx != SMU_14_0_2_CUSTOM_PARAMS_COUNT)
+ return -EINVAL;
+ if (custom_params[0] >= SMU_14_0_2_CUSTOM_PARAMS_CLOCK_COUNT)
+ return -EINVAL;
+ idx = custom_params[0] * SMU_14_0_2_CUSTOM_PARAMS_COUNT;
+ smu->custom_profile_params[idx] = 1;
+ for (i = 1; i < custom_params_max_idx; i++)
+ smu->custom_profile_params[idx + i] = custom_params[i];
+ }
+ ret = smu_v14_0_2_set_power_profile_mode_coeff(smu,
+ smu->custom_profile_params);
+ if (ret) {
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
+ return ret;
+ }
+ } else if (smu->custom_profile_params) {
+ memset(smu->custom_profile_params, 0, SMU_14_0_2_CUSTOM_PARAMS_SIZE);
+ }
ret = smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_SetWorkloadMask,
- smu->workload_mask, NULL);
-
- if (!ret)
- smu_cmn_assign_power_profile(smu);
+ backend_workload_mask, NULL);
+ if (ret) {
+ dev_err(smu->adev->dev, "Failed to set workload mask 0x%08x\n",
+ workload_mask);
+ if (idx != -1)
+ smu->custom_profile_params[idx] = 0;
+ return ret;
+ }
return ret;
}
@@ -2043,7 +2096,7 @@ static int smu_v14_0_2_enable_gfx_features(struct smu_context *smu)
{
struct amdgpu_device *adev = smu->adev;
- if (adev->ip_versions[MP1_HWIP][0] == IP_VERSION(14, 0, 2))
+ if (amdgpu_ip_version(adev, MP1_HWIP, 0) == IP_VERSION(14, 0, 2))
return smu_cmn_send_smc_msg_with_param(smu, SMU_MSG_EnableAllSmuFeatures,
FEATURE_PWR_GFX, NULL);
else
@@ -2753,7 +2806,6 @@ static const struct pptable_funcs smu_v14_0_2_ppt_funcs = {
.get_unique_id = smu_v14_0_2_get_unique_id,
.get_power_limit = smu_v14_0_2_get_power_limit,
.set_power_limit = smu_v14_0_2_set_power_limit,
- .set_power_source = smu_v14_0_set_power_source,
.get_power_profile_mode = smu_v14_0_2_get_power_profile_mode,
.set_power_profile_mode = smu_v14_0_2_set_power_profile_mode,
.run_btc = smu_v14_0_run_btc,
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
index f1ab1a6bb467..9f55207ea9bc 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.c
@@ -1081,6 +1081,9 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev)
case METRICS_VERSION(1, 6):
structure_size = sizeof(struct gpu_metrics_v1_6);
break;
+ case METRICS_VERSION(1, 7):
+ structure_size = sizeof(struct gpu_metrics_v1_7);
+ break;
case METRICS_VERSION(2, 0):
structure_size = sizeof(struct gpu_metrics_v2_0);
break;
@@ -1141,14 +1144,6 @@ int smu_cmn_set_mp1_state(struct smu_context *smu,
return ret;
}
-void smu_cmn_assign_power_profile(struct smu_context *smu)
-{
- uint32_t index;
- index = fls(smu->workload_mask);
- index = index > 0 && index <= WORKLOAD_POLICY_MAX ? index - 1 : 0;
- smu->power_profile_mode = smu->workload_setting[index];
-}
-
bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev)
{
struct pci_dev *p = NULL;
@@ -1226,3 +1221,28 @@ void smu_cmn_generic_plpd_policy_desc(struct smu_dpm_policy *policy)
{
policy->desc = &xgmi_plpd_policy_desc;
}
+
+void smu_cmn_get_backend_workload_mask(struct smu_context *smu,
+ u32 workload_mask,
+ u32 *backend_workload_mask)
+{
+ int workload_type;
+ u32 profile_mode;
+
+ *backend_workload_mask = 0;
+
+ for (profile_mode = 0; profile_mode < PP_SMC_POWER_PROFILE_COUNT; profile_mode++) {
+ if (!(workload_mask & (1 << profile_mode)))
+ continue;
+
+ /* conv PP_SMC_POWER_PROFILE* to WORKLOAD_PPLIB_*_BIT */
+ workload_type = smu_cmn_to_asic_specific_index(smu,
+ CMN2ASIC_MAPPING_WORKLOAD,
+ profile_mode);
+
+ if (workload_type < 0)
+ continue;
+
+ *backend_workload_mask |= 1 << workload_type;
+ }
+}
diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
index 8a801e389659..a020277dec3e 100644
--- a/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
+++ b/drivers/gpu/drm/amd/pm/swsmu/smu_cmn.h
@@ -130,8 +130,6 @@ void smu_cmn_init_soft_gpu_metrics(void *table, uint8_t frev, uint8_t crev);
int smu_cmn_set_mp1_state(struct smu_context *smu,
enum pp_mp1_state mp1_state);
-void smu_cmn_assign_power_profile(struct smu_context *smu);
-
/*
* Helper function to make sysfs_emit_at() happy. Align buf to
* the current page boundary and record the offset.
@@ -149,5 +147,9 @@ bool smu_cmn_is_audio_func_enabled(struct amdgpu_device *adev);
void smu_cmn_generic_soc_policy_desc(struct smu_dpm_policy *policy);
void smu_cmn_generic_plpd_policy_desc(struct smu_dpm_policy *policy);
+void smu_cmn_get_backend_workload_mask(struct smu_context *smu,
+ u32 workload_mask,
+ u32 *backend_workload_mask);
+
#endif
#endif
diff --git a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
index 6d475bb34002..d981d721e796 100644
--- a/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
+++ b/drivers/gpu/drm/arm/display/komeda/komeda_drv.c
@@ -153,7 +153,7 @@ static const struct dev_pm_ops komeda_pm_ops = {
static struct platform_driver komeda_platform_driver = {
.probe = komeda_platform_probe,
- .remove_new = komeda_platform_remove,
+ .remove = komeda_platform_remove,
.shutdown = komeda_platform_shutdown,
.driver = {
.name = "komeda",
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c b/drivers/gpu/drm/arm/hdlcd_drv.c
index cd4389809d42..191b806624df 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -405,7 +405,7 @@ static SIMPLE_DEV_PM_OPS(hdlcd_pm_ops, hdlcd_pm_suspend, hdlcd_pm_resume);
static struct platform_driver hdlcd_platform_driver = {
.probe = hdlcd_probe,
- .remove_new = hdlcd_remove,
+ .remove = hdlcd_remove,
.shutdown = hdlcd_shutdown,
.driver = {
.name = "hdlcd",
diff --git a/drivers/gpu/drm/arm/malidp_drv.c b/drivers/gpu/drm/arm/malidp_drv.c
index 4cb25004b84f..fd2be80f3bf5 100644
--- a/drivers/gpu/drm/arm/malidp_drv.c
+++ b/drivers/gpu/drm/arm/malidp_drv.c
@@ -988,7 +988,7 @@ static const struct dev_pm_ops malidp_pm_ops = {
static struct platform_driver malidp_platform_driver = {
.probe = malidp_platform_probe,
- .remove_new = malidp_platform_remove,
+ .remove = malidp_platform_remove,
.shutdown = malidp_platform_shutdown,
.driver = {
.name = "mali-dp",
diff --git a/drivers/gpu/drm/armada/armada_crtc.c b/drivers/gpu/drm/armada/armada_crtc.c
index c78687c755a8..0900e4466ffb 100644
--- a/drivers/gpu/drm/armada/armada_crtc.c
+++ b/drivers/gpu/drm/armada/armada_crtc.c
@@ -1084,7 +1084,7 @@ MODULE_DEVICE_TABLE(platform, armada_lcd_platform_ids);
struct platform_driver armada_lcd_platform_driver = {
.probe = armada_lcd_probe,
- .remove_new = armada_lcd_remove,
+ .remove = armada_lcd_remove,
.driver = {
.name = "armada-lcd",
.owner = THIS_MODULE,
diff --git a/drivers/gpu/drm/armada/armada_drv.c b/drivers/gpu/drm/armada/armada_drv.c
index 5c26f0409478..650e450cc19b 100644
--- a/drivers/gpu/drm/armada/armada_drv.c
+++ b/drivers/gpu/drm/armada/armada_drv.c
@@ -250,7 +250,7 @@ MODULE_DEVICE_TABLE(platform, armada_drm_platform_ids);
static struct platform_driver armada_drm_platform_driver = {
.probe = armada_drm_probe,
- .remove_new = armada_drm_remove,
+ .remove = armada_drm_remove,
.shutdown = armada_drm_shutdown,
.driver = {
.name = "armada-drm",
diff --git a/drivers/gpu/drm/armada/armada_gem.c b/drivers/gpu/drm/armada/armada_gem.c
index 26d10065d534..1a1680d71486 100644
--- a/drivers/gpu/drm/armada/armada_gem.c
+++ b/drivers/gpu/drm/armada/armada_gem.c
@@ -15,7 +15,7 @@
#include "armada_gem.h"
#include "armada_ioctlP.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
static vm_fault_t armada_gem_vm_fault(struct vm_fault *vmf)
{
diff --git a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
index 109023815fa2..b7e608ba6194 100644
--- a/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
+++ b/drivers/gpu/drm/aspeed/aspeed_gfx_drv.c
@@ -368,7 +368,7 @@ static void aspeed_gfx_shutdown(struct platform_device *pdev)
static struct platform_driver aspeed_gfx_platform_driver = {
.probe = aspeed_gfx_probe,
- .remove_new = aspeed_gfx_remove,
+ .remove = aspeed_gfx_remove,
.shutdown = aspeed_gfx_shutdown,
.driver = {
.name = "aspeed_gfx",
diff --git a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
index 792dcc19e8e7..7b209af7cf45 100644
--- a/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
+++ b/drivers/gpu/drm/atmel-hlcdc/atmel_hlcdc_dc.c
@@ -937,7 +937,7 @@ static const struct of_device_id atmel_hlcdc_dc_of_match[] = {
static struct platform_driver atmel_hlcdc_dc_platform_driver = {
.probe = atmel_hlcdc_dc_drm_probe,
- .remove_new = atmel_hlcdc_dc_drm_remove,
+ .remove = atmel_hlcdc_dc_drm_remove,
.shutdown = atmel_hlcdc_dc_drm_shutdown,
.driver = {
.name = "atmel-hlcdc-display-controller",
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
index 61f4a38e7d2b..8f786592143b 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_audio.c
@@ -153,7 +153,16 @@ static int adv7511_hdmi_hw_params(struct device *dev, void *data,
ADV7511_AUDIO_CFG3_LEN_MASK, len);
regmap_update_bits(adv7511->regmap, ADV7511_REG_I2C_FREQ_ID_CFG,
ADV7511_I2C_FREQ_ID_CFG_RATE_MASK, rate << 4);
- regmap_write(adv7511->regmap, 0x73, 0x1);
+
+ /* send current Audio infoframe values while updating */
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
+ BIT(5), BIT(5));
+
+ regmap_write(adv7511->regmap, ADV7511_REG_AUDIO_INFOFRAME(0), 0x1);
+
+ /* use Audio infoframe updated info */
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
+ BIT(5), 0);
return 0;
}
@@ -184,8 +193,9 @@ static int audio_startup(struct device *dev, void *data)
regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(0),
BIT(7) | BIT(6), BIT(7));
/* use Audio infoframe updated info */
- regmap_update_bits(adv7511->regmap, ADV7511_REG_GC(1),
+ regmap_update_bits(adv7511->regmap, ADV7511_REG_INFOFRAME_UPDATE,
BIT(5), 0);
+
/* enable SPDIF receiver */
if (adv7511->audio_source == ADV7511_AUDIO_SOURCE_SPDIF)
regmap_update_bits(adv7511->regmap, ADV7511_REG_AUDIO_CONFIG,
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index eb5919b38263..a13b3d8ab6ac 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -1241,8 +1241,10 @@ static int adv7511_probe(struct i2c_client *i2c)
return ret;
ret = adv7511_init_regulators(adv7511);
- if (ret)
- return dev_err_probe(dev, ret, "failed to init regulators\n");
+ if (ret) {
+ dev_err_probe(dev, ret, "failed to init regulators\n");
+ goto err_of_node_put;
+ }
/*
* The power down GPIO is optional. If present, toggle it from active to
@@ -1363,6 +1365,8 @@ err_i2c_unregister_edid:
i2c_unregister_device(adv7511->i2c_edid);
uninit_regulators:
adv7511_uninit_regulators(adv7511);
+err_of_node_put:
+ of_node_put(adv7511->host_node);
return ret;
}
@@ -1371,6 +1375,8 @@ static void adv7511_remove(struct i2c_client *i2c)
{
struct adv7511 *adv7511 = i2c_get_clientdata(i2c);
+ of_node_put(adv7511->host_node);
+
adv7511_uninit_regulators(adv7511);
drm_bridge_remove(&adv7511->bridge);
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7533.c b/drivers/gpu/drm/bridge/adv7511/adv7533.c
index 4481489aaf5e..122ad91e8a32 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7533.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7533.c
@@ -172,7 +172,7 @@ int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
of_property_read_u32(np, "adi,dsi-lanes", &num_lanes);
- if (num_lanes < 1 || num_lanes > 4)
+ if (num_lanes < 2 || num_lanes > 4)
return -EINVAL;
adv->num_dsi_lanes = num_lanes;
@@ -181,8 +181,6 @@ int adv7533_parse_dt(struct device_node *np, struct adv7511 *adv)
if (!adv->host_node)
return -ENODEV;
- of_node_put(adv->host_node);
-
adv->use_timing_gen = !of_property_read_bool(np,
"adi,disable-timing-generator");
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
index 7457d38622b0..c7a0247e06ad 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-dsi-core.c
@@ -1300,7 +1300,7 @@ MODULE_DEVICE_TABLE(of, cdns_dsi_of_match);
static struct platform_driver cdns_dsi_platform_driver = {
.probe = cdns_dsi_drm_probe,
- .remove_new = cdns_dsi_drm_remove,
+ .remove = cdns_dsi_drm_remove,
.driver = {
.name = "cdns-dsi",
.of_match_table = cdns_dsi_of_match,
diff --git a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
index 41f72d458487..d081850e3c03 100644
--- a/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
+++ b/drivers/gpu/drm/bridge/cadence/cdns-mhdp8546-core.c
@@ -2656,7 +2656,7 @@ static struct platform_driver mhdp_driver = {
.of_match_table = mhdp_ids,
},
.probe = cdns_mhdp_probe,
- .remove_new = cdns_mhdp_remove,
+ .remove = cdns_mhdp_remove,
};
module_platform_driver(mhdp_driver);
diff --git a/drivers/gpu/drm/bridge/display-connector.c b/drivers/gpu/drm/bridge/display-connector.c
index aab9ce7be94c..72bc508d4e6e 100644
--- a/drivers/gpu/drm/bridge/display-connector.c
+++ b/drivers/gpu/drm/bridge/display-connector.c
@@ -427,7 +427,7 @@ MODULE_DEVICE_TABLE(of, display_connector_match);
static struct platform_driver display_connector_driver = {
.probe = display_connector_probe,
- .remove_new = display_connector_remove,
+ .remove = display_connector_remove,
.driver = {
.name = "display-connector",
.of_match_table = display_connector_match,
diff --git a/drivers/gpu/drm/bridge/fsl-ldb.c b/drivers/gpu/drm/bridge/fsl-ldb.c
index 0e4bac7dd04f..0fc8a14fd800 100644
--- a/drivers/gpu/drm/bridge/fsl-ldb.c
+++ b/drivers/gpu/drm/bridge/fsl-ldb.c
@@ -393,7 +393,7 @@ MODULE_DEVICE_TABLE(of, fsl_ldb_match);
static struct platform_driver fsl_ldb_driver = {
.probe = fsl_ldb_probe,
- .remove_new = fsl_ldb_remove,
+ .remove = fsl_ldb_remove,
.driver = {
.name = "fsl-ldb",
.of_match_table = fsl_ldb_match,
diff --git a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c
index 073e64dc200c..0d1ac3edcab4 100644
--- a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c
+++ b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-pvi.c
@@ -193,7 +193,7 @@ MODULE_DEVICE_TABLE(of, imx8mp_hdmi_pvi_match);
static struct platform_driver imx8mp_hdmi_pvi_driver = {
.probe = imx8mp_hdmi_pvi_probe,
- .remove_new = imx8mp_hdmi_pvi_remove,
+ .remove = imx8mp_hdmi_pvi_remove,
.driver = {
.name = "imx-hdmi-pvi",
.of_match_table = imx8mp_hdmi_pvi_match,
diff --git a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx.c b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx.c
index 8fcc6d18f4ab..1e7a789ec289 100644
--- a/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx.c
+++ b/drivers/gpu/drm/bridge/imx/imx8mp-hdmi-tx.c
@@ -144,7 +144,7 @@ MODULE_DEVICE_TABLE(of, imx8mp_dw_hdmi_of_table);
static struct platform_driver imx8mp_dw_hdmi_platform_driver = {
.probe = imx8mp_dw_hdmi_probe,
- .remove_new = imx8mp_dw_hdmi_remove,
+ .remove = imx8mp_dw_hdmi_remove,
.driver = {
.name = "imx8mp-dw-hdmi-tx",
.of_match_table = imx8mp_dw_hdmi_of_table,
diff --git a/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c
index c879e37f5811..dd5823f04c70 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qm-ldb.c
@@ -570,7 +570,7 @@ MODULE_DEVICE_TABLE(of, imx8qm_ldb_dt_ids);
static struct platform_driver imx8qm_ldb_driver = {
.probe = imx8qm_ldb_probe,
- .remove_new = imx8qm_ldb_remove,
+ .remove = imx8qm_ldb_remove,
.driver = {
.pm = pm_ptr(&imx8qm_ldb_pm_ops),
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
index b33011f397f0..7bce2305d676 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-ldb.c
@@ -706,7 +706,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_ldb_dt_ids);
static struct platform_driver imx8qxp_ldb_driver = {
.probe = imx8qxp_ldb_probe,
- .remove_new = imx8qxp_ldb_remove,
+ .remove = imx8qxp_ldb_remove,
.driver = {
.pm = pm_ptr(&imx8qxp_ldb_pm_ops),
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c
index ce43e4069e21..1812bd106261 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-combiner.c
@@ -427,7 +427,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_pc_dt_ids);
static struct platform_driver imx8qxp_pc_bridge_driver = {
.probe = imx8qxp_pc_bridge_probe,
- .remove_new = imx8qxp_pc_bridge_remove,
+ .remove = imx8qxp_pc_bridge_remove,
.driver = {
.pm = pm_ptr(&imx8qxp_pc_pm_ops),
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c
index 1d11cc1df43c..4b0715ed6f38 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pixel-link.c
@@ -409,7 +409,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_pixel_link_dt_ids);
static struct platform_driver imx8qxp_pixel_link_bridge_driver = {
.probe = imx8qxp_pixel_link_bridge_probe,
- .remove_new = imx8qxp_pixel_link_bridge_remove,
+ .remove = imx8qxp_pixel_link_bridge_remove,
.driver = {
.of_match_table = imx8qxp_pixel_link_dt_ids,
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
index fb7cf4369bb8..65cf3a6c8ec6 100644
--- a/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
+++ b/drivers/gpu/drm/bridge/imx/imx8qxp-pxl2dpi.c
@@ -467,7 +467,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_pxl2dpi_dt_ids);
static struct platform_driver imx8qxp_pxl2dpi_bridge_driver = {
.probe = imx8qxp_pxl2dpi_bridge_probe,
- .remove_new = imx8qxp_pxl2dpi_bridge_remove,
+ .remove = imx8qxp_pxl2dpi_bridge_remove,
.driver = {
.of_match_table = imx8qxp_pxl2dpi_dt_ids,
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
index 2347f8dd632f..bea8346515b8 100644
--- a/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
+++ b/drivers/gpu/drm/bridge/imx/imx93-mipi-dsi.c
@@ -904,7 +904,7 @@ MODULE_DEVICE_TABLE(of, imx93_dsi_dt_ids);
static struct platform_driver imx93_dsi_driver = {
.probe = imx93_dsi_probe,
- .remove_new = imx93_dsi_remove,
+ .remove = imx93_dsi_remove,
.driver = {
.of_match_table = imx93_dsi_dt_ids,
.name = "imx93_mipi_dsi",
diff --git a/drivers/gpu/drm/bridge/lvds-codec.c b/drivers/gpu/drm/bridge/lvds-codec.c
index 991732c4b629..389af0233fcd 100644
--- a/drivers/gpu/drm/bridge/lvds-codec.c
+++ b/drivers/gpu/drm/bridge/lvds-codec.c
@@ -236,7 +236,7 @@ MODULE_DEVICE_TABLE(of, lvds_codec_match);
static struct platform_driver lvds_codec_driver = {
.probe = lvds_codec_probe,
- .remove_new = lvds_codec_remove,
+ .remove = lvds_codec_remove,
.driver = {
.name = "lvds-codec",
.of_match_table = lvds_codec_match,
diff --git a/drivers/gpu/drm/bridge/nwl-dsi.c b/drivers/gpu/drm/bridge/nwl-dsi.c
index 5f05647a3bea..1e5b2a37cb8c 100644
--- a/drivers/gpu/drm/bridge/nwl-dsi.c
+++ b/drivers/gpu/drm/bridge/nwl-dsi.c
@@ -1211,7 +1211,7 @@ static void nwl_dsi_remove(struct platform_device *pdev)
static struct platform_driver nwl_dsi_driver = {
.probe = nwl_dsi_probe,
- .remove_new = nwl_dsi_remove,
+ .remove = nwl_dsi_remove,
.driver = {
.of_match_table = nwl_dsi_dt_ids,
.name = DRV_NAME,
diff --git a/drivers/gpu/drm/bridge/samsung-dsim.c b/drivers/gpu/drm/bridge/samsung-dsim.c
index 4416d0be7272..f8b4fb835765 100644
--- a/drivers/gpu/drm/bridge/samsung-dsim.c
+++ b/drivers/gpu/drm/bridge/samsung-dsim.c
@@ -2139,7 +2139,7 @@ MODULE_DEVICE_TABLE(of, samsung_dsim_of_match);
static struct platform_driver samsung_dsim_driver = {
.probe = samsung_dsim_probe,
- .remove_new = samsung_dsim_remove,
+ .remove = samsung_dsim_remove,
.driver = {
.name = "samsung-dsim",
.pm = pm_ptr(&samsung_dsim_pm_ops),
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
index 221e9a4edb40..cf1f66b7b192 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
@@ -645,7 +645,7 @@ static SIMPLE_DEV_PM_OPS(snd_dw_hdmi_pm, snd_dw_hdmi_suspend,
static struct platform_driver snd_dw_hdmi_driver = {
.probe = snd_dw_hdmi_probe,
- .remove_new = snd_dw_hdmi_remove,
+ .remove = snd_dw_hdmi_remove,
.driver = {
.name = DRIVER_NAME,
.pm = PM_OPS,
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
index d4614de1ae1e..9549dabde941 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-cec.c
@@ -346,7 +346,7 @@ static const struct dev_pm_ops dw_hdmi_cec_pm = {
static struct platform_driver dw_hdmi_cec_driver = {
.probe = dw_hdmi_cec_probe,
- .remove_new = dw_hdmi_cec_remove,
+ .remove = dw_hdmi_cec_remove,
.driver = {
.name = "dw-hdmi-cec",
.pm = pm_ptr(&dw_hdmi_cec_pm),
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c
index 423762da2ab4..ab18f9a3bf23 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-gp-audio.c
@@ -181,7 +181,7 @@ static void snd_dw_hdmi_remove(struct platform_device *pdev)
static struct platform_driver snd_dw_hdmi_driver = {
.probe = snd_dw_hdmi_probe,
- .remove_new = snd_dw_hdmi_remove,
+ .remove = snd_dw_hdmi_remove,
.driver = {
.name = DRIVER_NAME,
},
diff --git a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
index 26c187d20d97..f1c5a8d0fa90 100644
--- a/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
+++ b/drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
@@ -225,7 +225,7 @@ static void snd_dw_hdmi_remove(struct platform_device *pdev)
static struct platform_driver snd_dw_hdmi_driver = {
.probe = snd_dw_hdmi_probe,
- .remove_new = snd_dw_hdmi_remove,
+ .remove = snd_dw_hdmi_remove,
.driver = {
.name = DRIVER_NAME,
},
diff --git a/drivers/gpu/drm/bridge/thc63lvd1024.c b/drivers/gpu/drm/bridge/thc63lvd1024.c
index 674efc489e3a..bba10cf9b4f9 100644
--- a/drivers/gpu/drm/bridge/thc63lvd1024.c
+++ b/drivers/gpu/drm/bridge/thc63lvd1024.c
@@ -230,7 +230,7 @@ MODULE_DEVICE_TABLE(of, thc63_match);
static struct platform_driver thc63_driver = {
.probe = thc63_probe,
- .remove_new = thc63_remove,
+ .remove = thc63_remove,
.driver = {
.name = "thc63lvd1024",
.of_match_table = thc63_match,
diff --git a/drivers/gpu/drm/bridge/ti-tfp410.c b/drivers/gpu/drm/bridge/ti-tfp410.c
index b1b1e4d5a24a..107a2c0b96c9 100644
--- a/drivers/gpu/drm/bridge/ti-tfp410.c
+++ b/drivers/gpu/drm/bridge/ti-tfp410.c
@@ -406,7 +406,7 @@ MODULE_DEVICE_TABLE(of, tfp410_match);
static struct platform_driver tfp410_platform_driver = {
.probe = tfp410_probe,
- .remove_new = tfp410_remove,
+ .remove = tfp410_remove,
.driver = {
.name = "tfp410-bridge",
.of_match_table = tfp410_match,
diff --git a/drivers/gpu/drm/bridge/ti-tpd12s015.c b/drivers/gpu/drm/bridge/ti-tpd12s015.c
index f9fb35683a27..47b74cb25b14 100644
--- a/drivers/gpu/drm/bridge/ti-tpd12s015.c
+++ b/drivers/gpu/drm/bridge/ti-tpd12s015.c
@@ -195,7 +195,7 @@ MODULE_DEVICE_TABLE(of, tpd12s015_of_match);
static struct platform_driver tpd12s015_driver = {
.probe = tpd12s015_probe,
- .remove_new = tpd12s015_remove,
+ .remove = tpd12s015_remove,
.driver = {
.name = "tpd12s015",
.of_match_table = tpd12s015_of_match,
diff --git a/drivers/gpu/drm/display/drm_dp_aux_bus.c b/drivers/gpu/drm/display/drm_dp_aux_bus.c
index d810529ebfb6..ec7eac6b595f 100644
--- a/drivers/gpu/drm/display/drm_dp_aux_bus.c
+++ b/drivers/gpu/drm/display/drm_dp_aux_bus.c
@@ -292,7 +292,7 @@ int of_dp_aux_populate_bus(struct drm_dp_aux *aux,
aux_ep->dev.parent = aux->dev;
aux_ep->dev.bus = &dp_aux_bus_type;
aux_ep->dev.type = &dp_aux_device_type_type;
- aux_ep->dev.of_node = of_node_get(np);
+ device_set_node(&aux_ep->dev, of_fwnode_handle(of_node_get(np)));
dev_set_name(&aux_ep->dev, "aux-%s", dev_name(aux->dev));
ret = device_register(&aux_ep->dev);
diff --git a/drivers/gpu/drm/display/drm_dp_mst_topology.c b/drivers/gpu/drm/display/drm_dp_mst_topology.c
index ac90118b9e7a..dc4446d589e7 100644
--- a/drivers/gpu/drm/display/drm_dp_mst_topology.c
+++ b/drivers/gpu/drm/display/drm_dp_mst_topology.c
@@ -320,6 +320,9 @@ static bool drm_dp_decode_sideband_msg_hdr(const struct drm_dp_mst_topology_mgr
hdr->broadcast = (buf[idx] >> 7) & 0x1;
hdr->path_msg = (buf[idx] >> 6) & 0x1;
hdr->msg_len = buf[idx] & 0x3f;
+ if (hdr->msg_len < 1) /* min space for body CRC */
+ return false;
+
idx++;
hdr->somt = (buf[idx] >> 7) & 0x1;
hdr->eomt = (buf[idx] >> 6) & 0x1;
@@ -3697,8 +3700,7 @@ int drm_dp_mst_topology_mgr_set_mst(struct drm_dp_mst_topology_mgr *mgr, bool ms
ret = 0;
mgr->payload_id_table_cleared = false;
- memset(&mgr->down_rep_recv, 0, sizeof(mgr->down_rep_recv));
- memset(&mgr->up_req_recv, 0, sizeof(mgr->up_req_recv));
+ mgr->reset_rx_state = true;
}
out_unlock:
@@ -3856,6 +3858,11 @@ out_fail:
}
EXPORT_SYMBOL(drm_dp_mst_topology_mgr_resume);
+static void reset_msg_rx_state(struct drm_dp_sideband_msg_rx *msg)
+{
+ memset(msg, 0, sizeof(*msg));
+}
+
static bool
drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
struct drm_dp_mst_branch **mstb)
@@ -3934,6 +3941,34 @@ drm_dp_get_one_sb_msg(struct drm_dp_mst_topology_mgr *mgr, bool up,
return true;
}
+static int get_msg_request_type(u8 data)
+{
+ return data & 0x7f;
+}
+
+static bool verify_rx_request_type(struct drm_dp_mst_topology_mgr *mgr,
+ const struct drm_dp_sideband_msg_tx *txmsg,
+ const struct drm_dp_sideband_msg_rx *rxmsg)
+{
+ const struct drm_dp_sideband_msg_hdr *hdr = &rxmsg->initial_hdr;
+ const struct drm_dp_mst_branch *mstb = txmsg->dst;
+ int tx_req_type = get_msg_request_type(txmsg->msg[0]);
+ int rx_req_type = get_msg_request_type(rxmsg->msg[0]);
+ char rad_str[64];
+
+ if (tx_req_type == rx_req_type)
+ return true;
+
+ drm_dp_mst_rad_to_str(mstb->rad, mstb->lct, rad_str, sizeof(rad_str));
+ drm_dbg_kms(mgr->dev,
+ "Got unexpected MST reply, mstb: %p seqno: %d lct: %d rad: %s rx_req_type: %s (%02x) != tx_req_type: %s (%02x)\n",
+ mstb, hdr->seqno, mstb->lct, rad_str,
+ drm_dp_mst_req_type_str(rx_req_type), rx_req_type,
+ drm_dp_mst_req_type_str(tx_req_type), tx_req_type);
+
+ return false;
+}
+
static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
{
struct drm_dp_sideband_msg_tx *txmsg;
@@ -3949,9 +3984,9 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
/* find the message */
mutex_lock(&mgr->qlock);
+
txmsg = list_first_entry_or_null(&mgr->tx_msg_downq,
struct drm_dp_sideband_msg_tx, next);
- mutex_unlock(&mgr->qlock);
/* Were we actually expecting a response, and from this mstb? */
if (!txmsg || txmsg->dst != mstb) {
@@ -3960,6 +3995,15 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
hdr = &msg->initial_hdr;
drm_dbg_kms(mgr->dev, "Got MST reply with no msg %p %d %d %02x %02x\n",
mstb, hdr->seqno, hdr->lct, hdr->rad[0], msg->msg[0]);
+
+ mutex_unlock(&mgr->qlock);
+
+ goto out_clear_reply;
+ }
+
+ if (!verify_rx_request_type(mgr, txmsg, msg)) {
+ mutex_unlock(&mgr->qlock);
+
goto out_clear_reply;
}
@@ -3975,20 +4019,15 @@ static int drm_dp_mst_handle_down_rep(struct drm_dp_mst_topology_mgr *mgr)
txmsg->reply.u.nak.nak_data);
}
- memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx));
- drm_dp_mst_topology_put_mstb(mstb);
-
- mutex_lock(&mgr->qlock);
txmsg->state = DRM_DP_SIDEBAND_TX_RX;
list_del(&txmsg->next);
+
mutex_unlock(&mgr->qlock);
wake_up_all(&mgr->tx_waitq);
- return 0;
-
out_clear_reply:
- memset(msg, 0, sizeof(struct drm_dp_sideband_msg_rx));
+ reset_msg_rx_state(msg);
out:
if (mstb)
drm_dp_mst_topology_put_mstb(mstb);
@@ -4070,16 +4109,20 @@ static void drm_dp_mst_up_req_work(struct work_struct *work)
static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
{
struct drm_dp_pending_up_req *up_req;
+ struct drm_dp_mst_branch *mst_primary;
+ int ret = 0;
if (!drm_dp_get_one_sb_msg(mgr, true, NULL))
- goto out;
+ goto out_clear_reply;
if (!mgr->up_req_recv.have_eomt)
return 0;
up_req = kzalloc(sizeof(*up_req), GFP_KERNEL);
- if (!up_req)
- return -ENOMEM;
+ if (!up_req) {
+ ret = -ENOMEM;
+ goto out_clear_reply;
+ }
INIT_LIST_HEAD(&up_req->next);
@@ -4090,10 +4133,19 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
drm_dbg_kms(mgr->dev, "Received unknown up req type, ignoring: %x\n",
up_req->msg.req_type);
kfree(up_req);
- goto out;
+ goto out_clear_reply;
}
- drm_dp_send_up_ack_reply(mgr, mgr->mst_primary, up_req->msg.req_type,
+ mutex_lock(&mgr->lock);
+ mst_primary = mgr->mst_primary;
+ if (!mst_primary || !drm_dp_mst_topology_try_get_mstb(mst_primary)) {
+ mutex_unlock(&mgr->lock);
+ kfree(up_req);
+ goto out_clear_reply;
+ }
+ mutex_unlock(&mgr->lock);
+
+ drm_dp_send_up_ack_reply(mgr, mst_primary, up_req->msg.req_type,
false);
if (up_req->msg.req_type == DP_CONNECTION_STATUS_NOTIFY) {
@@ -4110,13 +4162,13 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
conn_stat->peer_device_type);
mutex_lock(&mgr->probe_lock);
- handle_csn = mgr->mst_primary->link_address_sent;
+ handle_csn = mst_primary->link_address_sent;
mutex_unlock(&mgr->probe_lock);
if (!handle_csn) {
drm_dbg_kms(mgr->dev, "Got CSN before finish topology probing. Skip it.");
kfree(up_req);
- goto out;
+ goto out_put_primary;
}
} else if (up_req->msg.req_type == DP_RESOURCE_STATUS_NOTIFY) {
const struct drm_dp_resource_status_notify *res_stat =
@@ -4133,9 +4185,22 @@ static int drm_dp_mst_handle_up_req(struct drm_dp_mst_topology_mgr *mgr)
mutex_unlock(&mgr->up_req_lock);
queue_work(system_long_wq, &mgr->up_req_work);
-out:
- memset(&mgr->up_req_recv, 0, sizeof(struct drm_dp_sideband_msg_rx));
- return 0;
+out_put_primary:
+ drm_dp_mst_topology_put_mstb(mst_primary);
+out_clear_reply:
+ reset_msg_rx_state(&mgr->up_req_recv);
+ return ret;
+}
+
+static void update_msg_rx_state(struct drm_dp_mst_topology_mgr *mgr)
+{
+ mutex_lock(&mgr->lock);
+ if (mgr->reset_rx_state) {
+ mgr->reset_rx_state = false;
+ reset_msg_rx_state(&mgr->down_rep_recv);
+ reset_msg_rx_state(&mgr->up_req_recv);
+ }
+ mutex_unlock(&mgr->lock);
}
/**
@@ -4172,6 +4237,8 @@ int drm_dp_mst_hpd_irq_handle_event(struct drm_dp_mst_topology_mgr *mgr, const u
*handled = true;
}
+ update_msg_rx_state(mgr);
+
if (esi[1] & DP_DOWN_REP_MSG_RDY) {
ret = drm_dp_mst_handle_down_rep(mgr);
*handled = true;
diff --git a/drivers/gpu/drm/display/drm_dp_tunnel.c b/drivers/gpu/drm/display/drm_dp_tunnel.c
index 48b2df120086..90fe07a89260 100644
--- a/drivers/gpu/drm/display/drm_dp_tunnel.c
+++ b/drivers/gpu/drm/display/drm_dp_tunnel.c
@@ -1896,8 +1896,8 @@ static void destroy_mgr(struct drm_dp_tunnel_mgr *mgr)
*
* Creates a DP tunnel manager for @dev.
*
- * Returns a pointer to the tunnel manager if created successfully or NULL in
- * case of an error.
+ * Returns a pointer to the tunnel manager if created successfully or error
+ * pointer in case of failure.
*/
struct drm_dp_tunnel_mgr *
drm_dp_tunnel_mgr_create(struct drm_device *dev, int max_group_count)
@@ -1907,7 +1907,7 @@ drm_dp_tunnel_mgr_create(struct drm_device *dev, int max_group_count)
mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
if (!mgr)
- return NULL;
+ return ERR_PTR(-ENOMEM);
mgr->dev = dev;
init_waitqueue_head(&mgr->bw_req_queue);
@@ -1916,7 +1916,7 @@ drm_dp_tunnel_mgr_create(struct drm_device *dev, int max_group_count)
if (!mgr->groups) {
kfree(mgr);
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
#ifdef CONFIG_DRM_DISPLAY_DP_TUNNEL_STATE_DEBUG
@@ -1927,7 +1927,7 @@ drm_dp_tunnel_mgr_create(struct drm_device *dev, int max_group_count)
if (!init_group(mgr, &mgr->groups[i])) {
destroy_mgr(mgr);
- return NULL;
+ return ERR_PTR(-ENOMEM);
}
mgr->group_count++;
diff --git a/drivers/gpu/drm/drm_gem_dma_helper.c b/drivers/gpu/drm/drm_gem_dma_helper.c
index 870b90b78bc4..16988d316a6d 100644
--- a/drivers/gpu/drm/drm_gem_dma_helper.c
+++ b/drivers/gpu/drm/drm_gem_dma_helper.c
@@ -600,5 +600,5 @@ drm_gem_dma_prime_import_sg_table_vmap(struct drm_device *dev,
EXPORT_SYMBOL(drm_gem_dma_prime_import_sg_table_vmap);
MODULE_DESCRIPTION("DRM DMA memory-management helpers");
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
MODULE_LICENSE("GPL");
diff --git a/drivers/gpu/drm/drm_gem_framebuffer_helper.c b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
index 3bdb6ba37ff4..185534f56bab 100644
--- a/drivers/gpu/drm/drm_gem_framebuffer_helper.c
+++ b/drivers/gpu/drm/drm_gem_framebuffer_helper.c
@@ -18,7 +18,7 @@
#include "drm_internal.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
#define AFBC_HEADER_SIZE 16
#define AFBC_TH_LAYOUT_ALIGNMENT 8
diff --git a/drivers/gpu/drm/drm_gem_shmem_helper.c b/drivers/gpu/drm/drm_gem_shmem_helper.c
index 8508060a1a95..5ab351409312 100644
--- a/drivers/gpu/drm/drm_gem_shmem_helper.c
+++ b/drivers/gpu/drm/drm_gem_shmem_helper.c
@@ -22,7 +22,7 @@
#include <drm/drm_prime.h>
#include <drm/drm_print.h>
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
/**
* DOC: overview
@@ -800,5 +800,5 @@ drm_gem_shmem_prime_import_sg_table(struct drm_device *dev,
EXPORT_SYMBOL_GPL(drm_gem_shmem_prime_import_sg_table);
MODULE_DESCRIPTION("DRM SHMEM memory-management helpers");
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/drm_modes.c b/drivers/gpu/drm/drm_modes.c
index 6ba167a33461..71573b85d924 100644
--- a/drivers/gpu/drm/drm_modes.c
+++ b/drivers/gpu/drm/drm_modes.c
@@ -1287,14 +1287,11 @@ EXPORT_SYMBOL(drm_mode_set_name);
*/
int drm_mode_vrefresh(const struct drm_display_mode *mode)
{
- unsigned int num, den;
+ unsigned int num = 1, den = 1;
if (mode->htotal == 0 || mode->vtotal == 0)
return 0;
- num = mode->clock;
- den = mode->htotal * mode->vtotal;
-
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
num *= 2;
if (mode->flags & DRM_MODE_FLAG_DBLSCAN)
@@ -1302,6 +1299,12 @@ int drm_mode_vrefresh(const struct drm_display_mode *mode)
if (mode->vscan > 1)
den *= mode->vscan;
+ if (check_mul_overflow(mode->clock, num, &num))
+ return 0;
+
+ if (check_mul_overflow(mode->htotal * mode->vtotal, den, &den))
+ return 0;
+
return DIV_ROUND_CLOSEST_ULL(mul_u32_u32(num, 1000), den);
}
EXPORT_SYMBOL(drm_mode_vrefresh);
diff --git a/drivers/gpu/drm/drm_panic_qr.rs b/drivers/gpu/drm/drm_panic_qr.rs
index 09500cddc009..ef2d490965ba 100644
--- a/drivers/gpu/drm/drm_panic_qr.rs
+++ b/drivers/gpu/drm/drm_panic_qr.rs
@@ -929,7 +929,6 @@ impl QrImage<'_> {
/// * `tmp` must be valid for reading and writing for `tmp_size` bytes.
///
/// They must remain valid for the duration of the function call.
-
#[no_mangle]
pub unsafe extern "C" fn drm_panic_qr_generate(
url: *const i8,
diff --git a/drivers/gpu/drm/drm_prime.c b/drivers/gpu/drm/drm_prime.c
index 0e3f8adf162f..32a8781cfd67 100644
--- a/drivers/gpu/drm/drm_prime.c
+++ b/drivers/gpu/drm/drm_prime.c
@@ -40,7 +40,7 @@
#include "drm_internal.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
/**
* DOC: overview and lifetime rules
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_drv.c b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
index 9b4e2f4b1bc7..a46f9e4ac09a 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_drv.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_drv.c
@@ -669,7 +669,7 @@ static void etnaviv_pdev_remove(struct platform_device *pdev)
static struct platform_driver etnaviv_platform_driver = {
.probe = etnaviv_pdev_probe,
- .remove_new = etnaviv_pdev_remove,
+ .remove = etnaviv_pdev_remove,
.driver = {
.name = "etnaviv",
},
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
index 6b98200068e4..42e57d142554 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gem_prime.c
@@ -10,7 +10,7 @@
#include "etnaviv_drv.h"
#include "etnaviv_gem.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
static struct lock_class_key etnaviv_prime_lock_class;
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
index c7d59c06ccd1..2d4c112ce033 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_gpu.c
@@ -1985,6 +1985,6 @@ struct platform_driver etnaviv_gpu_driver = {
.of_match_table = etnaviv_gpu_match,
},
.probe = etnaviv_gpu_platform_probe,
- .remove_new = etnaviv_gpu_platform_remove,
+ .remove = etnaviv_gpu_platform_remove,
.id_table = gpu_ids,
};
diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
index 0ef7bc8848b0..b9e206303b48 100644
--- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c
@@ -871,7 +871,7 @@ static void exynos5433_decon_remove(struct platform_device *pdev)
struct platform_driver exynos5433_decon_driver = {
.probe = exynos5433_decon_probe,
- .remove_new = exynos5433_decon_remove,
+ .remove = exynos5433_decon_remove,
.driver = {
.name = "exynos5433-decon",
.pm = pm_ptr(&exynos5433_decon_pm_ops),
diff --git a/drivers/gpu/drm/exynos/exynos7_drm_decon.c b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
index c65364087fac..5170f72b0830 100644
--- a/drivers/gpu/drm/exynos/exynos7_drm_decon.c
+++ b/drivers/gpu/drm/exynos/exynos7_drm_decon.c
@@ -874,7 +874,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(exynos7_decon_pm_ops, exynos7_decon_suspend,
struct platform_driver decon_driver = {
.probe = decon_probe,
- .remove_new = decon_remove,
+ .remove = decon_remove,
.driver = {
.name = "exynos-decon",
.pm = pm_ptr(&exynos7_decon_pm_ops),
diff --git a/drivers/gpu/drm/exynos/exynos_dp.c b/drivers/gpu/drm/exynos/exynos_dp.c
index 22142b293279..5bcf41e0bd04 100644
--- a/drivers/gpu/drm/exynos/exynos_dp.c
+++ b/drivers/gpu/drm/exynos/exynos_dp.c
@@ -279,7 +279,7 @@ MODULE_DEVICE_TABLE(of, exynos_dp_match);
struct platform_driver dp_driver = {
.probe = exynos_dp_probe,
- .remove_new = exynos_dp_remove,
+ .remove = exynos_dp_remove,
.driver = {
.name = "exynos-dp",
.pm = pm_ptr(&exynos_dp_pm_ops),
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.c b/drivers/gpu/drm/exynos/exynos_drm_drv.c
index 2a466d8179f4..1c44f85c5f54 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.c
@@ -363,7 +363,7 @@ static void exynos_drm_platform_shutdown(struct platform_device *pdev)
static struct platform_driver exynos_drm_platform_driver = {
.probe = exynos_drm_platform_probe,
- .remove_new = exynos_drm_platform_remove,
+ .remove = exynos_drm_platform_remove,
.shutdown = exynos_drm_platform_shutdown,
.driver = {
.name = "exynos-drm",
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dsi.c b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
index bf16deaae68b..896a03639e2d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dsi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dsi.c
@@ -181,7 +181,7 @@ MODULE_DEVICE_TABLE(of, exynos_dsi_of_match);
struct platform_driver dsi_driver = {
.probe = samsung_dsim_probe,
- .remove_new = samsung_dsim_remove,
+ .remove = samsung_dsim_remove,
.driver = {
.name = "exynos-dsi",
.pm = &samsung_dsim_pm_ops,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimc.c b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
index 4d7ea65b7dd8..b150cfd92f6e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimc.c
@@ -1408,7 +1408,7 @@ MODULE_DEVICE_TABLE(of, fimc_of_match);
struct platform_driver fimc_driver = {
.probe = fimc_probe,
- .remove_new = fimc_remove,
+ .remove = fimc_remove,
.driver = {
.of_match_table = fimc_of_match,
.name = "exynos-drm-fimc",
diff --git a/drivers/gpu/drm/exynos/exynos_drm_fimd.c b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
index f57df8c48139..1ad87584b1c2 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_fimd.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_fimd.c
@@ -1323,7 +1323,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(exynos_fimd_pm_ops, exynos_fimd_suspend,
struct platform_driver fimd_driver = {
.probe = fimd_probe,
- .remove_new = fimd_remove,
+ .remove = fimd_remove,
.driver = {
.name = "exynos4-fb",
.pm = pm_ptr(&exynos_fimd_pm_ops),
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 3a3b2c00e400..d32f2474cbaa 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -1607,7 +1607,7 @@ MODULE_DEVICE_TABLE(of, exynos_g2d_match);
struct platform_driver g2d_driver = {
.probe = g2d_probe,
- .remove_new = g2d_remove,
+ .remove = g2d_remove,
.driver = {
.name = "exynos-drm-g2d",
.pm = pm_ptr(&g2d_pm_ops),
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 638ca96830e9..4787fee4696f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -18,7 +18,7 @@
#include "exynos_drm_drv.h"
#include "exynos_drm_gem.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
static int exynos_drm_gem_mmap(struct drm_gem_object *obj, struct vm_area_struct *vma);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gsc.c b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
index 1ae90ef1fc23..e6d516e1976d 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gsc.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gsc.c
@@ -1420,7 +1420,7 @@ MODULE_DEVICE_TABLE(of, exynos_drm_gsc_of_match);
struct platform_driver gsc_driver = {
.probe = gsc_probe,
- .remove_new = gsc_remove,
+ .remove = gsc_remove,
.driver = {
.name = "exynos-drm-gsc",
.pm = &gsc_pm_ops,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_mic.c b/drivers/gpu/drm/exynos/exynos_drm_mic.c
index d61ec451807c..b34ec6728337 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_mic.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_mic.c
@@ -460,7 +460,7 @@ MODULE_DEVICE_TABLE(of, exynos_mic_of_match);
struct platform_driver mic_driver = {
.probe = exynos_mic_probe,
- .remove_new = exynos_mic_remove,
+ .remove = exynos_mic_remove,
.driver = {
.name = "exynos-mic",
.pm = pm_ptr(&exynos_mic_pm_ops),
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index 2eb0b701672f..7b0f4a98a70a 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -451,7 +451,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(rotator_pm_ops, rotator_runtime_suspend,
struct platform_driver rotator_driver = {
.probe = rotator_probe,
- .remove_new = rotator_remove,
+ .remove = rotator_remove,
.driver = {
.name = "exynos-rotator",
.pm = pm_ptr(&rotator_pm_ops),
diff --git a/drivers/gpu/drm/exynos/exynos_drm_scaler.c b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
index 2788105ac780..c8a1b6b0a29c 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_scaler.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_scaler.c
@@ -719,7 +719,7 @@ MODULE_DEVICE_TABLE(of, exynos_scaler_match);
struct platform_driver scaler_driver = {
.probe = scaler_probe,
- .remove_new = scaler_remove,
+ .remove = scaler_remove,
.driver = {
.name = "exynos-scaler",
.pm = pm_ptr(&scaler_pm_ops),
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index 6de0cced6c9d..fd388b1dbe68 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -467,7 +467,7 @@ static void vidi_remove(struct platform_device *pdev)
struct platform_driver vidi_driver = {
.probe = vidi_probe,
- .remove_new = vidi_remove,
+ .remove = vidi_remove,
.driver = {
.name = "exynos-drm-vidi",
.dev_groups = vidi_groups,
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index c9d4b9146df9..466a9e514aa1 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -2126,7 +2126,7 @@ static const struct dev_pm_ops exynos_hdmi_pm_ops = {
struct platform_driver hdmi_driver = {
.probe = hdmi_probe,
- .remove_new = hdmi_remove,
+ .remove = hdmi_remove,
.driver = {
.name = "exynos-hdmi",
.pm = &exynos_hdmi_pm_ops,
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index 1db955f00044..a3670d2eaab2 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -1335,5 +1335,5 @@ struct platform_driver mixer_driver = {
.of_match_table = mixer_match_types,
},
.probe = mixer_probe,
- .remove_new = mixer_remove,
+ .remove = mixer_remove,
};
diff --git a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
index 91a48d774cf7..be1ab673e49e 100644
--- a/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
+++ b/drivers/gpu/drm/fsl-dcu/fsl_dcu_drm_drv.c
@@ -378,7 +378,7 @@ static void fsl_dcu_drm_shutdown(struct platform_device *pdev)
static struct platform_driver fsl_dcu_drm_platform_driver = {
.probe = fsl_dcu_drm_probe,
- .remove_new = fsl_dcu_drm_remove,
+ .remove = fsl_dcu_drm_remove,
.shutdown = fsl_dcu_drm_shutdown,
.driver = {
.name = "fsl-dcu",
diff --git a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
index a39cc549c20b..2eea9fb0e76b 100644
--- a/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
+++ b/drivers/gpu/drm/hisilicon/kirin/dw_drm_dsi.c
@@ -889,7 +889,7 @@ MODULE_DEVICE_TABLE(of, dsi_of_match);
static struct platform_driver dsi_driver = {
.probe = dsi_probe,
- .remove_new = dsi_remove,
+ .remove = dsi_remove,
.driver = {
.name = "dw-dsi",
.of_match_table = dsi_of_match,
diff --git a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
index 86a3a1faff49..b3ab944652a6 100644
--- a/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/kirin/kirin_drm_drv.c
@@ -302,7 +302,7 @@ MODULE_DEVICE_TABLE(of, kirin_drm_dt_ids);
static struct platform_driver kirin_drm_platform_driver = {
.probe = kirin_drm_platform_probe,
- .remove_new = kirin_drm_platform_remove,
+ .remove = kirin_drm_platform_remove,
.shutdown = kirin_drm_platform_shutdown,
.driver = {
.name = "kirin-drm",
diff --git a/drivers/gpu/drm/i915/display/intel_color.c b/drivers/gpu/drm/i915/display/intel_color.c
index 174753625bca..7cd902bbd244 100644
--- a/drivers/gpu/drm/i915/display/intel_color.c
+++ b/drivers/gpu/drm/i915/display/intel_color.c
@@ -1343,6 +1343,17 @@ static void ilk_lut_write(const struct intel_crtc_state *crtc_state,
intel_de_write_fw(display, reg, val);
}
+static void ilk_lut_write_indexed(const struct intel_crtc_state *crtc_state,
+ i915_reg_t reg, u32 val)
+{
+ struct intel_display *display = to_intel_display(crtc_state);
+
+ if (crtc_state->dsb_color_vblank)
+ intel_dsb_reg_write_indexed(crtc_state->dsb_color_vblank, reg, val);
+ else
+ intel_de_write_fw(display, reg, val);
+}
+
static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
const struct drm_property_blob *blob)
{
@@ -1357,19 +1368,29 @@ static void ilk_load_lut_8(const struct intel_crtc_state *crtc_state,
lut = blob->data;
/*
- * DSB fails to correctly load the legacy LUT
- * unless we either write each entry twice,
- * or use non-posted writes
+ * DSB fails to correctly load the legacy LUT unless
+ * we either write each entry twice when using posted
+ * writes, or we use non-posted writes.
+ *
+ * If palette anti-collision is active during LUT
+ * register writes:
+ * - posted writes simply get dropped and thus the LUT
+ * contents may not be correctly updated
+ * - non-posted writes are blocked and thus the LUT
+ * contents are always correct, but simultaneous CPU
+ * MMIO access will start to fail
+ *
+ * Choose the lesser of two evils and use posted writes.
+ * Using posted writes is also faster, even when having
+ * to write each register twice.
*/
- if (crtc_state->dsb_color_vblank)
- intel_dsb_nonpost_start(crtc_state->dsb_color_vblank);
-
- for (i = 0; i < 256; i++)
+ for (i = 0; i < 256; i++) {
ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
i9xx_lut_8(&lut[i]));
-
- if (crtc_state->dsb_color_vblank)
- intel_dsb_nonpost_end(crtc_state->dsb_color_vblank);
+ if (crtc_state->dsb_color_vblank)
+ ilk_lut_write(crtc_state, LGC_PALETTE(pipe, i),
+ i9xx_lut_8(&lut[i]));
+ }
}
static void ilk_load_lut_10(const struct intel_crtc_state *crtc_state,
@@ -1458,8 +1479,8 @@ static void bdw_load_lut_10(const struct intel_crtc_state *crtc_state,
prec_index);
for (i = 0; i < lut_size; i++)
- ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
- ilk_lut_10(&lut[i]));
+ ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
+ ilk_lut_10(&lut[i]));
/*
* Reset the index, otherwise it prevents the legacy palette to be
@@ -1612,16 +1633,16 @@ static void glk_load_degamma_lut(const struct intel_crtc_state *crtc_state,
* ToDo: Extend to max 7.0. Enable 32 bit input value
* as compared to just 16 to achieve this.
*/
- ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
- DISPLAY_VER(display) >= 14 ?
- mtl_degamma_lut(&lut[i]) : glk_degamma_lut(&lut[i]));
+ ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe),
+ DISPLAY_VER(display) >= 14 ?
+ mtl_degamma_lut(&lut[i]) : glk_degamma_lut(&lut[i]));
}
/* Clamp values > 1.0. */
while (i++ < glk_degamma_lut_size(display))
- ilk_lut_write(crtc_state, PRE_CSC_GAMC_DATA(pipe),
- DISPLAY_VER(display) >= 14 ?
- 1 << 24 : 1 << 16);
+ ilk_lut_write_indexed(crtc_state, PRE_CSC_GAMC_DATA(pipe),
+ DISPLAY_VER(display) >= 14 ?
+ 1 << 24 : 1 << 16);
ilk_lut_write(crtc_state, PRE_CSC_GAMC_INDEX(pipe), 0);
}
@@ -1687,10 +1708,10 @@ icl_program_gamma_superfine_segment(const struct intel_crtc_state *crtc_state)
for (i = 0; i < 9; i++) {
const struct drm_color_lut *entry = &lut[i];
- ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
- ilk_lut_12p4_ldw(entry));
- ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
- ilk_lut_12p4_udw(entry));
+ ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
+ ilk_lut_12p4_ldw(entry));
+ ilk_lut_write_indexed(crtc_state, PREC_PAL_MULTI_SEG_DATA(pipe),
+ ilk_lut_12p4_udw(entry));
}
ilk_lut_write(crtc_state, PREC_PAL_MULTI_SEG_INDEX(pipe),
@@ -1726,10 +1747,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
for (i = 1; i < 257; i++) {
entry = &lut[i * 8];
- ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
- ilk_lut_12p4_ldw(entry));
- ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
- ilk_lut_12p4_udw(entry));
+ ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
+ ilk_lut_12p4_ldw(entry));
+ ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
+ ilk_lut_12p4_udw(entry));
}
/*
@@ -1747,10 +1768,10 @@ icl_program_gamma_multi_segment(const struct intel_crtc_state *crtc_state)
for (i = 0; i < 256; i++) {
entry = &lut[i * 8 * 128];
- ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
- ilk_lut_12p4_ldw(entry));
- ilk_lut_write(crtc_state, PREC_PAL_DATA(pipe),
- ilk_lut_12p4_udw(entry));
+ ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
+ ilk_lut_12p4_ldw(entry));
+ ilk_lut_write_indexed(crtc_state, PREC_PAL_DATA(pipe),
+ ilk_lut_12p4_udw(entry));
}
ilk_lut_write(crtc_state, PREC_PAL_INDEX(pipe),
diff --git a/drivers/gpu/drm/i915/display/intel_cx0_phy.c b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
index 71dc659228ab..0c7aee13495a 100644
--- a/drivers/gpu/drm/i915/display/intel_cx0_phy.c
+++ b/drivers/gpu/drm/i915/display/intel_cx0_phy.c
@@ -2115,14 +2115,6 @@ static void intel_c10_pll_program(struct intel_display *display,
0, C10_VDR_CTRL_MSGBUS_ACCESS,
MB_WRITE_COMMITTED);
- /* Custom width needs to be programmed to 0 for both the phy lanes */
- intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH,
- C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10,
- MB_WRITE_COMMITTED);
- intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CONTROL(1),
- 0, C10_VDR_CTRL_UPDATE_CFG,
- MB_WRITE_COMMITTED);
-
/* Program the pll values only for the master lane */
for (i = 0; i < ARRAY_SIZE(pll_state->pll); i++)
intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_PLL(i),
@@ -2132,6 +2124,10 @@ static void intel_c10_pll_program(struct intel_display *display,
intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CMN(0), pll_state->cmn, MB_WRITE_COMMITTED);
intel_cx0_write(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_TX(0), pll_state->tx, MB_WRITE_COMMITTED);
+ /* Custom width needs to be programmed to 0 for both the phy lanes */
+ intel_cx0_rmw(encoder, INTEL_CX0_BOTH_LANES, PHY_C10_VDR_CUSTOM_WIDTH,
+ C10_VDR_CUSTOM_WIDTH_MASK, C10_VDR_CUSTOM_WIDTH_8_10,
+ MB_WRITE_COMMITTED);
intel_cx0_rmw(encoder, INTEL_CX0_LANE0, PHY_C10_VDR_CONTROL(1),
0, C10_VDR_CTRL_MASTER_LANE | C10_VDR_CTRL_UPDATE_CFG,
MB_WRITE_COMMITTED);
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.c b/drivers/gpu/drm/i915/display/intel_dsb.c
index b7b44399adaa..4d3785f5cb52 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.c
+++ b/drivers/gpu/drm/i915/display/intel_dsb.c
@@ -273,16 +273,20 @@ static bool intel_dsb_prev_ins_is_indexed_write(struct intel_dsb *dsb, i915_reg_
}
/**
- * intel_dsb_reg_write() - Emit register wriite to the DSB context
+ * intel_dsb_reg_write_indexed() - Emit register wriite to the DSB context
* @dsb: DSB context
* @reg: register address.
* @val: value.
*
* This function is used for writing register-value pair in command
* buffer of DSB.
+ *
+ * Note that indexed writes are slower than normal MMIO writes
+ * for a small number (less than 5 or so) of writes to the same
+ * register.
*/
-void intel_dsb_reg_write(struct intel_dsb *dsb,
- i915_reg_t reg, u32 val)
+void intel_dsb_reg_write_indexed(struct intel_dsb *dsb,
+ i915_reg_t reg, u32 val)
{
/*
* For example the buffer will look like below for 3 dwords for auto
@@ -340,6 +344,15 @@ void intel_dsb_reg_write(struct intel_dsb *dsb,
}
}
+void intel_dsb_reg_write(struct intel_dsb *dsb,
+ i915_reg_t reg, u32 val)
+{
+ intel_dsb_emit(dsb, val,
+ (DSB_OPCODE_MMIO_WRITE << DSB_OPCODE_SHIFT) |
+ (DSB_BYTE_EN << DSB_BYTE_EN_SHIFT) |
+ i915_mmio_reg_offset(reg));
+}
+
static u32 intel_dsb_mask_to_byte_en(u32 mask)
{
return (!!(mask & 0xff000000) << 3 |
diff --git a/drivers/gpu/drm/i915/display/intel_dsb.h b/drivers/gpu/drm/i915/display/intel_dsb.h
index 33e0fc2ab380..da6df07a3c83 100644
--- a/drivers/gpu/drm/i915/display/intel_dsb.h
+++ b/drivers/gpu/drm/i915/display/intel_dsb.h
@@ -34,6 +34,8 @@ void intel_dsb_finish(struct intel_dsb *dsb);
void intel_dsb_cleanup(struct intel_dsb *dsb);
void intel_dsb_reg_write(struct intel_dsb *dsb,
i915_reg_t reg, u32 val);
+void intel_dsb_reg_write_indexed(struct intel_dsb *dsb,
+ i915_reg_t reg, u32 val);
void intel_dsb_reg_write_masked(struct intel_dsb *dsb,
i915_reg_t reg, u32 mask, u32 val);
void intel_dsb_noop(struct intel_dsb *dsb, int count);
diff --git a/drivers/gpu/drm/i915/display/intel_hdcp.c b/drivers/gpu/drm/i915/display/intel_hdcp.c
index f6d42ec6949e..f57e4dba2873 100644
--- a/drivers/gpu/drm/i915/display/intel_hdcp.c
+++ b/drivers/gpu/drm/i915/display/intel_hdcp.c
@@ -1503,6 +1503,8 @@ static int hdcp2_deauthenticate_port(struct intel_connector *connector)
static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
{
struct intel_display *display = to_intel_display(connector);
+ struct intel_digital_port *dig_port =
+ intel_attached_dig_port(connector);
struct intel_hdcp *hdcp = &connector->hdcp;
union {
struct hdcp2_ake_init ake_init;
@@ -1513,30 +1515,36 @@ static int hdcp2_authentication_key_exchange(struct intel_connector *connector)
} msgs;
const struct intel_hdcp_shim *shim = hdcp->shim;
size_t size;
- int ret, i;
+ int ret, i, max_retries;
/* Init for seq_num */
hdcp->seq_num_v = 0;
hdcp->seq_num_m = 0;
+ if (intel_encoder_is_dp(&dig_port->base) ||
+ intel_encoder_is_mst(&dig_port->base))
+ max_retries = 10;
+ else
+ max_retries = 1;
+
ret = hdcp2_prepare_ake_init(connector, &msgs.ake_init);
if (ret < 0)
return ret;
/*
* Retry the first read and write to downstream at least 10 times
- * with a 50ms delay if not hdcp2 capable(dock decides to stop advertising
- * hdcp2 capability for some reason). The reason being that
- * during suspend resume dock usually keeps the HDCP2 registers inaccesible
- * causing AUX error. This wouldn't be a big problem if the userspace
- * just kept retrying with some delay while it continues to play low
- * value content but most userpace applications end up throwing an error
- * when it receives one from KMD. This makes sure we give the dock
- * and the sink devices to complete its power cycle and then try HDCP
- * authentication. The values of 10 and delay of 50ms was decided based
- * on multiple trial and errors.
+ * with a 50ms delay if not hdcp2 capable for DP/DPMST encoders
+ * (dock decides to stop advertising hdcp2 capability for some reason).
+ * The reason being that during suspend resume dock usually keeps the
+ * HDCP2 registers inaccesible causing AUX error. This wouldn't be a
+ * big problem if the userspace just kept retrying with some delay while
+ * it continues to play low value content but most userpace applications
+ * end up throwing an error when it receives one from KMD. This makes
+ * sure we give the dock and the sink devices to complete its power cycle
+ * and then try HDCP authentication. The values of 10 and delay of 50ms
+ * was decided based on multiple trial and errors.
*/
- for (i = 0; i < 10; i++) {
+ for (i = 0; i < max_retries; i++) {
if (!intel_hdcp2_get_capability(connector)) {
msleep(50);
continue;
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
index 1df74f7aa3dc..9473050ac842 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_dmabuf.c
@@ -16,7 +16,7 @@
#include "i915_gem_object.h"
#include "i915_scatterlist.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
I915_SELFTEST_DECLARE(static bool force_different_devices;)
diff --git a/drivers/gpu/drm/i915/gt/intel_engine_types.h b/drivers/gpu/drm/i915/gt/intel_engine_types.h
index ba55c059063d..fe1f85e5dda3 100644
--- a/drivers/gpu/drm/i915/gt/intel_engine_types.h
+++ b/drivers/gpu/drm/i915/gt/intel_engine_types.h
@@ -343,6 +343,11 @@ struct intel_engine_guc_stats {
* @start_gt_clk: GT clock time of last idle to active transition.
*/
u64 start_gt_clk;
+
+ /**
+ * @total: The last value of total returned
+ */
+ u64 total;
};
union intel_engine_tlb_inv_reg {
diff --git a/drivers/gpu/drm/i915/gt/intel_rc6.c b/drivers/gpu/drm/i915/gt/intel_rc6.c
index c864d101faf9..9378d5901c49 100644
--- a/drivers/gpu/drm/i915/gt/intel_rc6.c
+++ b/drivers/gpu/drm/i915/gt/intel_rc6.c
@@ -133,7 +133,7 @@ static void gen11_rc6_enable(struct intel_rc6 *rc6)
GEN9_MEDIA_PG_ENABLE |
GEN11_MEDIA_SAMPLER_PG_ENABLE;
- if (GRAPHICS_VER(gt->i915) >= 12) {
+ if (GRAPHICS_VER(gt->i915) >= 12 && !IS_DG1(gt->i915)) {
for (i = 0; i < I915_MAX_VCS; i++)
if (HAS_ENGINE(gt, _VCS(i)))
pg_enable |= (VDN_HCP_POWERGATE_ENABLE(i) |
diff --git a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
index 9ede6f240d79..c0bd730383f2 100644
--- a/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc_submission.c
@@ -1243,6 +1243,21 @@ static void __get_engine_usage_record(struct intel_engine_cs *engine,
} while (++i < 6);
}
+static void __set_engine_usage_record(struct intel_engine_cs *engine,
+ u32 last_in, u32 id, u32 total)
+{
+ struct iosys_map rec_map = intel_guc_engine_usage_record_map(engine);
+
+#define record_write(map_, field_, val_) \
+ iosys_map_wr_field(map_, 0, struct guc_engine_usage_record, field_, val_)
+
+ record_write(&rec_map, last_switch_in_stamp, last_in);
+ record_write(&rec_map, current_context_index, id);
+ record_write(&rec_map, total_runtime, total);
+
+#undef record_write
+}
+
static void guc_update_engine_gt_clks(struct intel_engine_cs *engine)
{
struct intel_engine_guc_stats *stats = &engine->stats.guc;
@@ -1363,9 +1378,12 @@ static ktime_t guc_engine_busyness(struct intel_engine_cs *engine, ktime_t *now)
total += intel_gt_clock_interval_to_ns(gt, clk);
}
+ if (total > stats->total)
+ stats->total = total;
+
spin_unlock_irqrestore(&guc->timestamp.lock, flags);
- return ns_to_ktime(total);
+ return ns_to_ktime(stats->total);
}
static void guc_enable_busyness_worker(struct intel_guc *guc)
@@ -1431,8 +1449,21 @@ static void __reset_guc_busyness_stats(struct intel_guc *guc)
guc_update_pm_timestamp(guc, &unused);
for_each_engine(engine, gt, id) {
+ struct intel_engine_guc_stats *stats = &engine->stats.guc;
+
guc_update_engine_gt_clks(engine);
- engine->stats.guc.prev_total = 0;
+
+ /*
+ * If resetting a running context, accumulate the active
+ * time as well since there will be no context switch.
+ */
+ if (stats->running) {
+ u64 clk = guc->timestamp.gt_stamp - stats->start_gt_clk;
+
+ stats->total_gt_clks += clk;
+ }
+ stats->prev_total = 0;
+ stats->running = 0;
}
spin_unlock_irqrestore(&guc->timestamp.lock, flags);
@@ -1543,6 +1574,9 @@ err_trylock:
static int guc_action_enable_usage_stats(struct intel_guc *guc)
{
+ struct intel_gt *gt = guc_to_gt(guc);
+ struct intel_engine_cs *engine;
+ enum intel_engine_id id;
u32 offset = intel_guc_engine_usage_offset(guc);
u32 action[] = {
INTEL_GUC_ACTION_SET_ENG_UTIL_BUFF,
@@ -1550,6 +1584,9 @@ static int guc_action_enable_usage_stats(struct intel_guc *guc)
0,
};
+ for_each_engine(engine, gt, id)
+ __set_engine_usage_record(engine, 0, 0xffffffff, 0);
+
return intel_guc_send(guc, action, ARRAY_SIZE(action));
}
diff --git a/drivers/gpu/drm/i915/gvt/kvmgt.c b/drivers/gpu/drm/i915/gvt/kvmgt.c
index ca0fb126b02d..b27ff77bfb50 100644
--- a/drivers/gpu/drm/i915/gvt/kvmgt.c
+++ b/drivers/gpu/drm/i915/gvt/kvmgt.c
@@ -53,8 +53,8 @@
#include "intel_gvt.h"
#include "gvt.h"
-MODULE_IMPORT_NS(DMA_BUF);
-MODULE_IMPORT_NS(I915_GVT);
+MODULE_IMPORT_NS("DMA_BUF");
+MODULE_IMPORT_NS("I915_GVT");
/* helper macros copied from vfio-pci */
#define VFIO_PCI_OFFSET_SHIFT 40
diff --git a/drivers/gpu/drm/i915/i915_gpu_error.c b/drivers/gpu/drm/i915/i915_gpu_error.c
index 4eb58887819a..71c0daef1996 100644
--- a/drivers/gpu/drm/i915/i915_gpu_error.c
+++ b/drivers/gpu/drm/i915/i915_gpu_error.c
@@ -1643,9 +1643,21 @@ capture_engine(struct intel_engine_cs *engine,
return NULL;
intel_engine_get_hung_entity(engine, &ce, &rq);
- if (rq && !i915_request_started(rq))
- drm_info(&engine->gt->i915->drm, "Got hung context on %s with active request %lld:%lld [0x%04X] not yet started\n",
- engine->name, rq->fence.context, rq->fence.seqno, ce->guc_id.id);
+ if (rq && !i915_request_started(rq)) {
+ /*
+ * We want to know also what is the guc_id of the context,
+ * but if we don't have the context reference, then skip
+ * printing it.
+ */
+ if (ce)
+ drm_info(&engine->gt->i915->drm,
+ "Got hung context on %s with active request %lld:%lld [0x%04X] not yet started\n",
+ engine->name, rq->fence.context, rq->fence.seqno, ce->guc_id.id);
+ else
+ drm_info(&engine->gt->i915->drm,
+ "Got hung context on %s with active request %lld:%lld not yet started\n",
+ engine->name, rq->fence.context, rq->fence.seqno);
+ }
if (rq) {
capture = intel_engine_coredump_add_request(ee, rq, ATOMIC_MAYFAIL);
diff --git a/drivers/gpu/drm/i915/i915_scheduler.c b/drivers/gpu/drm/i915/i915_scheduler.c
index 762127dd56c5..70a854557e6e 100644
--- a/drivers/gpu/drm/i915/i915_scheduler.c
+++ b/drivers/gpu/drm/i915/i915_scheduler.c
@@ -506,6 +506,6 @@ int __init i915_scheduler_module_init(void)
return 0;
err_priorities:
- kmem_cache_destroy(slab_priorities);
+ kmem_cache_destroy(slab_dependencies);
return -ENOMEM;
}
diff --git a/drivers/gpu/drm/i915/intel_gvt.c b/drivers/gpu/drm/i915/intel_gvt.c
index 5a01d60e5186..a5383a2bc64b 100644
--- a/drivers/gpu/drm/i915/intel_gvt.c
+++ b/drivers/gpu/drm/i915/intel_gvt.c
@@ -204,7 +204,7 @@ int intel_gvt_set_ops(const struct intel_vgpu_ops *ops)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(intel_gvt_set_ops, I915_GVT);
+EXPORT_SYMBOL_NS_GPL(intel_gvt_set_ops, "I915_GVT");
void intel_gvt_clear_ops(const struct intel_vgpu_ops *ops)
{
@@ -222,7 +222,7 @@ void intel_gvt_clear_ops(const struct intel_vgpu_ops *ops)
intel_gvt_ops = NULL;
mutex_unlock(&intel_gvt_mutex);
}
-EXPORT_SYMBOL_NS_GPL(intel_gvt_clear_ops, I915_GVT);
+EXPORT_SYMBOL_NS_GPL(intel_gvt_clear_ops, "I915_GVT");
/**
* intel_gvt_init - initialize GVT components
@@ -284,40 +284,40 @@ void intel_gvt_resume(struct drm_i915_private *dev_priv)
* Exported here so that the exports only get created when GVT support is
* actually enabled.
*/
-EXPORT_SYMBOL_NS_GPL(i915_gem_object_alloc, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_gem_object_create_shmem, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_gem_object_init, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_gem_object_ggtt_pin_ww, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_gem_object_pin_map, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_gem_object_set_to_cpu_domain, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(__i915_gem_object_flush_map, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(__i915_gem_object_set_pages, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_gem_gtt_insert, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_gem_prime_export, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_init, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_backoff, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_fini, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_ppgtt_create, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_request_add, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_request_create, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_request_wait, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_reserve_fence, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_unreserve_fence, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_vm_release, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(_i915_vma_move_to_active, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(intel_context_create, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(__intel_context_do_pin, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(__intel_context_do_unpin, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(intel_ring_begin, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_get, I915_GVT);
+EXPORT_SYMBOL_NS_GPL(i915_gem_object_alloc, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_gem_object_create_shmem, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_gem_object_init, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_gem_object_ggtt_pin_ww, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_gem_object_pin_map, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_gem_object_set_to_cpu_domain, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(__i915_gem_object_flush_map, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(__i915_gem_object_set_pages, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_gem_gtt_insert, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_gem_prime_export, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_init, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_backoff, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_gem_ww_ctx_fini, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_ppgtt_create, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_request_add, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_request_create, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_request_wait, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_reserve_fence, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_unreserve_fence, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_vm_release, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(_i915_vma_move_to_active, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(intel_context_create, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(__intel_context_do_pin, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(__intel_context_do_unpin, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(intel_ring_begin, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_get, "I915_GVT");
#if IS_ENABLED(CONFIG_DRM_I915_DEBUG_RUNTIME_PM)
-EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put, I915_GVT);
+EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put, "I915_GVT");
#endif
-EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put_unchecked, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_for_reg, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_get, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_put, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(shmem_pin_map, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(shmem_unpin_map, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(__px_dma, I915_GVT);
-EXPORT_SYMBOL_NS_GPL(i915_fence_ops, I915_GVT);
+EXPORT_SYMBOL_NS_GPL(intel_runtime_pm_put_unchecked, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_for_reg, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_get, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(intel_uncore_forcewake_put, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(shmem_pin_map, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(shmem_unpin_map, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(__px_dma, "I915_GVT");
+EXPORT_SYMBOL_NS_GPL(i915_fence_ops, "I915_GVT");
diff --git a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c
index 955c9a33212a..aa51f366626c 100644
--- a/drivers/gpu/drm/i915/intel_gvt_mmio_table.c
+++ b/drivers/gpu/drm/i915/intel_gvt_mmio_table.c
@@ -1308,4 +1308,4 @@ int intel_gvt_iterate_mmio_table(struct intel_gvt_mmio_table_iter *iter)
err:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(intel_gvt_iterate_mmio_table, I915_GVT);
+EXPORT_SYMBOL_NS_GPL(intel_gvt_iterate_mmio_table, "I915_GVT");
diff --git a/drivers/gpu/drm/imagination/pvr_drv.c b/drivers/gpu/drm/imagination/pvr_drv.c
index 36c0e768698e..85ee9abd1811 100644
--- a/drivers/gpu/drm/imagination/pvr_drv.c
+++ b/drivers/gpu/drm/imagination/pvr_drv.c
@@ -1485,7 +1485,7 @@ static const struct dev_pm_ops pvr_pm_ops = {
static struct platform_driver pvr_driver = {
.probe = pvr_probe,
- .remove_new = pvr_remove,
+ .remove = pvr_remove,
.driver = {
.name = PVR_DRIVER_NAME,
.pm = &pvr_pm_ops,
@@ -1497,5 +1497,5 @@ module_platform_driver(pvr_driver);
MODULE_AUTHOR("Imagination Technologies Ltd.");
MODULE_DESCRIPTION(PVR_DRIVER_DESC);
MODULE_LICENSE("Dual MIT/GPL");
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
MODULE_FIRMWARE("powervr/rogue_33.15.11.3_v1.fw");
diff --git a/drivers/gpu/drm/imx/dcss/dcss-drv.c b/drivers/gpu/drm/imx/dcss/dcss-drv.c
index d881f5a34760..19b027cc1dc4 100644
--- a/drivers/gpu/drm/imx/dcss/dcss-drv.c
+++ b/drivers/gpu/drm/imx/dcss/dcss-drv.c
@@ -112,7 +112,7 @@ MODULE_DEVICE_TABLE(of, dcss_of_match);
static struct platform_driver dcss_platform_driver = {
.probe = dcss_drv_platform_probe,
- .remove_new = dcss_drv_platform_remove,
+ .remove = dcss_drv_platform_remove,
.shutdown = dcss_drv_platform_shutdown,
.driver = {
.name = "imx-dcss",
diff --git a/drivers/gpu/drm/imx/ipuv3/dw_hdmi-imx.c b/drivers/gpu/drm/imx/ipuv3/dw_hdmi-imx.c
index 0006ea52b83c..8333c4bf7369 100644
--- a/drivers/gpu/drm/imx/ipuv3/dw_hdmi-imx.c
+++ b/drivers/gpu/drm/imx/ipuv3/dw_hdmi-imx.c
@@ -265,7 +265,7 @@ static void dw_hdmi_imx_remove(struct platform_device *pdev)
static struct platform_driver dw_hdmi_imx_platform_driver = {
.probe = dw_hdmi_imx_probe,
- .remove_new = dw_hdmi_imx_remove,
+ .remove = dw_hdmi_imx_remove,
.driver = {
.name = "dwhdmi-imx",
.of_match_table = dw_hdmi_imx_dt_ids,
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
index ced06bd8eae8..5f2c93c3c288 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-drm-core.c
@@ -325,7 +325,7 @@ MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);
static struct platform_driver imx_drm_pdrv = {
.probe = imx_drm_platform_probe,
- .remove_new = imx_drm_platform_remove,
+ .remove = imx_drm_platform_remove,
.shutdown = imx_drm_platform_shutdown,
.driver = {
.name = "imx-drm",
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
index ff74018ac5cd..6be7a57ad03d 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-ldb.c
@@ -632,7 +632,7 @@ static void imx_ldb_remove(struct platform_device *pdev)
static struct platform_driver imx_ldb_driver = {
.probe = imx_ldb_probe,
- .remove_new = imx_ldb_remove,
+ .remove = imx_ldb_remove,
.driver = {
.of_match_table = imx_ldb_dt_ids,
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/imx/ipuv3/imx-tve.c b/drivers/gpu/drm/imx/ipuv3/imx-tve.c
index d46d07d25f51..3a3c8a195119 100644
--- a/drivers/gpu/drm/imx/ipuv3/imx-tve.c
+++ b/drivers/gpu/drm/imx/ipuv3/imx-tve.c
@@ -662,7 +662,7 @@ MODULE_DEVICE_TABLE(of, imx_tve_dt_ids);
static struct platform_driver imx_tve_driver = {
.probe = imx_tve_probe,
- .remove_new = imx_tve_remove,
+ .remove = imx_tve_remove,
.driver = {
.of_match_table = imx_tve_dt_ids,
.name = "imx-tve",
diff --git a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
index 99db53e167bd..cf7b02b2d52c 100644
--- a/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
+++ b/drivers/gpu/drm/imx/ipuv3/ipuv3-crtc.c
@@ -449,5 +449,5 @@ struct platform_driver ipu_drm_driver = {
.name = "imx-ipuv3-crtc",
},
.probe = ipu_drm_probe,
- .remove_new = ipu_drm_remove,
+ .remove = ipu_drm_remove,
};
diff --git a/drivers/gpu/drm/imx/ipuv3/parallel-display.c b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
index 70f62e89622e..9e66eb77b1eb 100644
--- a/drivers/gpu/drm/imx/ipuv3/parallel-display.c
+++ b/drivers/gpu/drm/imx/ipuv3/parallel-display.c
@@ -273,7 +273,7 @@ MODULE_DEVICE_TABLE(of, imx_pd_dt_ids);
static struct platform_driver imx_pd_driver = {
.probe = imx_pd_probe,
- .remove_new = imx_pd_remove,
+ .remove = imx_pd_remove,
.driver = {
.of_match_table = imx_pd_dt_ids,
.name = "imx-parallel-display",
diff --git a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
index 3215c4acd675..fa7d44623c52 100644
--- a/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
+++ b/drivers/gpu/drm/imx/lcdc/imx-lcdc.c
@@ -527,7 +527,7 @@ static struct platform_driver imx_lcdc_driver = {
.of_match_table = imx_lcdc_of_dev_id,
},
.probe = imx_lcdc_probe,
- .remove_new = imx_lcdc_remove,
+ .remove = imx_lcdc_remove,
.shutdown = imx_lcdc_shutdown,
};
module_platform_driver(imx_lcdc_driver);
diff --git a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
index 056b70b63554..8469e1e5e582 100644
--- a/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
+++ b/drivers/gpu/drm/ingenic/ingenic-drm-drv.c
@@ -1632,7 +1632,7 @@ static struct platform_driver ingenic_drm_driver = {
.of_match_table = of_match_ptr(ingenic_drm_of_match),
},
.probe = ingenic_drm_probe,
- .remove_new = ingenic_drm_remove,
+ .remove = ingenic_drm_remove,
.shutdown = ingenic_drm_shutdown,
};
diff --git a/drivers/gpu/drm/ingenic/ingenic-ipu.c b/drivers/gpu/drm/ingenic/ingenic-ipu.c
index 5bd9072352b5..26ebf424d63e 100644
--- a/drivers/gpu/drm/ingenic/ingenic-ipu.c
+++ b/drivers/gpu/drm/ingenic/ingenic-ipu.c
@@ -991,7 +991,7 @@ static struct platform_driver ingenic_ipu_driver = {
.of_match_table = ingenic_ipu_of_match,
},
.probe = ingenic_ipu_probe,
- .remove_new = ingenic_ipu_remove,
+ .remove = ingenic_ipu_remove,
};
struct platform_driver *ingenic_ipu_driver_ptr = &ingenic_ipu_driver;
diff --git a/drivers/gpu/drm/kmb/kmb_drv.c b/drivers/gpu/drm/kmb/kmb_drv.c
index 0274ab9caa85..a3d31de761cb 100644
--- a/drivers/gpu/drm/kmb/kmb_drv.c
+++ b/drivers/gpu/drm/kmb/kmb_drv.c
@@ -622,7 +622,7 @@ static SIMPLE_DEV_PM_OPS(kmb_pm_ops, kmb_pm_suspend, kmb_pm_resume);
static struct platform_driver kmb_platform_driver = {
.probe = kmb_probe,
- .remove_new = kmb_remove,
+ .remove = kmb_remove,
.driver = {
.name = "kmb-drm",
.pm = &kmb_pm_ops,
diff --git a/drivers/gpu/drm/lima/lima_drv.c b/drivers/gpu/drm/lima/lima_drv.c
index 10bce18b7c31..fb3062c872b3 100644
--- a/drivers/gpu/drm/lima/lima_drv.c
+++ b/drivers/gpu/drm/lima/lima_drv.c
@@ -488,7 +488,7 @@ static const struct dev_pm_ops lima_pm_ops = {
static struct platform_driver lima_platform_driver = {
.probe = lima_pdev_probe,
- .remove_new = lima_pdev_remove,
+ .remove = lima_pdev_remove,
.driver = {
.name = "lima",
.pm = &lima_pm_ops,
diff --git a/drivers/gpu/drm/logicvc/logicvc_drm.c b/drivers/gpu/drm/logicvc/logicvc_drm.c
index e4d90701b29d..fb9de5e0bc0e 100644
--- a/drivers/gpu/drm/logicvc/logicvc_drm.c
+++ b/drivers/gpu/drm/logicvc/logicvc_drm.c
@@ -491,7 +491,7 @@ MODULE_DEVICE_TABLE(of, logicvc_drm_of_table);
static struct platform_driver logicvc_drm_platform_driver = {
.probe = logicvc_drm_probe,
- .remove_new = logicvc_drm_remove,
+ .remove = logicvc_drm_remove,
.shutdown = logicvc_drm_shutdown,
.driver = {
.name = "logicvc-drm",
diff --git a/drivers/gpu/drm/mcde/mcde_drv.c b/drivers/gpu/drm/mcde/mcde_drv.c
index f60bdd7b6c13..c4d51f5f038d 100644
--- a/drivers/gpu/drm/mcde/mcde_drv.c
+++ b/drivers/gpu/drm/mcde/mcde_drv.c
@@ -483,7 +483,7 @@ static struct platform_driver mcde_driver = {
.of_match_table = mcde_of_match,
},
.probe = mcde_probe,
- .remove_new = mcde_remove,
+ .remove = mcde_remove,
.shutdown = mcde_shutdown,
};
diff --git a/drivers/gpu/drm/mcde/mcde_dsi.c b/drivers/gpu/drm/mcde/mcde_dsi.c
index e2fad1a048b5..395449a72f0a 100644
--- a/drivers/gpu/drm/mcde/mcde_dsi.c
+++ b/drivers/gpu/drm/mcde/mcde_dsi.c
@@ -1229,5 +1229,5 @@ struct platform_driver mcde_dsi_driver = {
.of_match_table = mcde_dsi_of_match,
},
.probe = mcde_dsi_probe,
- .remove_new = mcde_dsi_remove,
+ .remove = mcde_dsi_remove,
};
diff --git a/drivers/gpu/drm/mediatek/mtk_cec.c b/drivers/gpu/drm/mediatek/mtk_cec.c
index 2de248443147..b42c0d87eba3 100644
--- a/drivers/gpu/drm/mediatek/mtk_cec.c
+++ b/drivers/gpu/drm/mediatek/mtk_cec.c
@@ -241,7 +241,7 @@ MODULE_DEVICE_TABLE(of, mtk_cec_of_ids);
struct platform_driver mtk_cec_driver = {
.probe = mtk_cec_probe,
- .remove_new = mtk_cec_remove,
+ .remove = mtk_cec_remove,
.driver = {
.name = "mediatek-cec",
.of_match_table = mtk_cec_of_ids,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_aal.c b/drivers/gpu/drm/mediatek/mtk_disp_aal.c
index 59fb9a08d54b..abc9e5525d03 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_aal.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_aal.c
@@ -218,7 +218,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_aal_driver_dt_match);
struct platform_driver mtk_disp_aal_driver = {
.probe = mtk_disp_aal_probe,
- .remove_new = mtk_disp_aal_remove,
+ .remove = mtk_disp_aal_remove,
.driver = {
.name = "mediatek-disp-aal",
.of_match_table = mtk_disp_aal_driver_dt_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c b/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
index 9b75727e0861..10d60d2c2a56 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ccorr.c
@@ -209,7 +209,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_ccorr_driver_dt_match);
struct platform_driver mtk_disp_ccorr_driver = {
.probe = mtk_disp_ccorr_probe,
- .remove_new = mtk_disp_ccorr_remove,
+ .remove = mtk_disp_ccorr_remove,
.driver = {
.name = "mediatek-disp-ccorr",
.of_match_table = mtk_disp_ccorr_driver_dt_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_color.c b/drivers/gpu/drm/mediatek/mtk_disp_color.c
index 2fd5e7dc9e24..dd8433a38282 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_color.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_color.c
@@ -159,7 +159,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_color_driver_dt_match);
struct platform_driver mtk_disp_color_driver = {
.probe = mtk_disp_color_probe,
- .remove_new = mtk_disp_color_remove,
+ .remove = mtk_disp_color_remove,
.driver = {
.name = "mediatek-disp-color",
.of_match_table = mtk_disp_color_driver_dt_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
index f0b38817ba6c..b17b11d93846 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_gamma.c
@@ -329,7 +329,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_gamma_driver_dt_match);
struct platform_driver mtk_disp_gamma_driver = {
.probe = mtk_disp_gamma_probe,
- .remove_new = mtk_disp_gamma_remove,
+ .remove = mtk_disp_gamma_remove,
.driver = {
.name = "mediatek-disp-gamma",
.of_match_table = mtk_disp_gamma_driver_dt_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_merge.c b/drivers/gpu/drm/mediatek/mtk_disp_merge.c
index 435e5d9c8520..563b1b248fbb 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_merge.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_merge.c
@@ -370,7 +370,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_merge_driver_dt_match);
struct platform_driver mtk_disp_merge_driver = {
.probe = mtk_disp_merge_probe,
- .remove_new = mtk_disp_merge_remove,
+ .remove = mtk_disp_merge_remove,
.driver = {
.name = "mediatek-disp-merge",
.of_match_table = mtk_disp_merge_driver_dt_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
index e0c0bb01f65a..f731d4fbe8b6 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl.c
@@ -746,7 +746,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_ovl_driver_dt_match);
struct platform_driver mtk_disp_ovl_driver = {
.probe = mtk_disp_ovl_probe,
- .remove_new = mtk_disp_ovl_remove,
+ .remove = mtk_disp_ovl_remove,
.driver = {
.name = "mediatek-disp-ovl",
.of_match_table = mtk_disp_ovl_driver_dt_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
index 187855d83590..fa0e95dd29a0 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_ovl_adaptor.c
@@ -665,7 +665,7 @@ static void mtk_disp_ovl_adaptor_remove(struct platform_device *pdev)
struct platform_driver mtk_disp_ovl_adaptor_driver = {
.probe = mtk_disp_ovl_adaptor_probe,
- .remove_new = mtk_disp_ovl_adaptor_remove,
+ .remove = mtk_disp_ovl_adaptor_remove,
.driver = {
.name = "mediatek-disp-ovl-adaptor",
},
diff --git a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
index 07243f372260..bf47790e4d6b 100644
--- a/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_disp_rdma.c
@@ -417,7 +417,7 @@ MODULE_DEVICE_TABLE(of, mtk_disp_rdma_driver_dt_match);
struct platform_driver mtk_disp_rdma_driver = {
.probe = mtk_disp_rdma_probe,
- .remove_new = mtk_disp_rdma_remove,
+ .remove = mtk_disp_rdma_remove,
.driver = {
.name = "mediatek-disp-rdma",
.of_match_table = mtk_disp_rdma_driver_dt_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_dp.c b/drivers/gpu/drm/mediatek/mtk_dp.c
index 1cc916b16471..36713c176cfc 100644
--- a/drivers/gpu/drm/mediatek/mtk_dp.c
+++ b/drivers/gpu/drm/mediatek/mtk_dp.c
@@ -2899,7 +2899,7 @@ MODULE_DEVICE_TABLE(of, mtk_dp_of_match);
static struct platform_driver mtk_dp_driver = {
.probe = mtk_dp_probe,
- .remove_new = mtk_dp_remove,
+ .remove = mtk_dp_remove,
.driver = {
.name = "mediatek-drm-dp",
.of_match_table = mtk_dp_of_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_dpi.c b/drivers/gpu/drm/mediatek/mtk_dpi.c
index 20a9d589fd75..1864eb02dbf5 100644
--- a/drivers/gpu/drm/mediatek/mtk_dpi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dpi.c
@@ -1108,7 +1108,7 @@ MODULE_DEVICE_TABLE(of, mtk_dpi_of_ids);
struct platform_driver mtk_dpi_driver = {
.probe = mtk_dpi_probe,
- .remove_new = mtk_dpi_remove,
+ .remove = mtk_dpi_remove,
.driver = {
.name = "mediatek-dpi",
.of_match_table = mtk_dpi_of_ids,
diff --git a/drivers/gpu/drm/mediatek/mtk_drm_drv.c b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
index 9a8ef8558da9..0829ceb9967c 100644
--- a/drivers/gpu/drm/mediatek/mtk_drm_drv.c
+++ b/drivers/gpu/drm/mediatek/mtk_drm_drv.c
@@ -1251,7 +1251,7 @@ static const struct dev_pm_ops mtk_drm_pm_ops = {
static struct platform_driver mtk_drm_platform_driver = {
.probe = mtk_drm_probe,
- .remove_new = mtk_drm_remove,
+ .remove = mtk_drm_remove,
.shutdown = mtk_drm_shutdown,
.driver = {
.name = "mediatek-drm",
diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
index 33ceeb8d6925..e61b9bc68e9a 100644
--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
+++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
@@ -1301,7 +1301,7 @@ MODULE_DEVICE_TABLE(of, mtk_dsi_of_match);
struct platform_driver mtk_dsi_driver = {
.probe = mtk_dsi_probe,
- .remove_new = mtk_dsi_remove,
+ .remove = mtk_dsi_remove,
.driver = {
.name = "mtk-dsi",
.of_match_table = mtk_dsi_of_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_ethdr.c b/drivers/gpu/drm/mediatek/mtk_ethdr.c
index 0f22e7d337cb..96832d0cca37 100644
--- a/drivers/gpu/drm/mediatek/mtk_ethdr.c
+++ b/drivers/gpu/drm/mediatek/mtk_ethdr.c
@@ -388,7 +388,7 @@ MODULE_DEVICE_TABLE(of, mtk_ethdr_driver_dt_match);
struct platform_driver mtk_ethdr_driver = {
.probe = mtk_ethdr_probe,
- .remove_new = mtk_ethdr_remove,
+ .remove = mtk_ethdr_remove,
.driver = {
.name = "mediatek-disp-ethdr",
.of_match_table = mtk_ethdr_driver_dt_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
index 7687f673964e..70dc1d4460ad 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -1795,7 +1795,7 @@ MODULE_DEVICE_TABLE(of, mtk_hdmi_of_ids);
static struct platform_driver mtk_hdmi_driver = {
.probe = mtk_hdmi_probe,
- .remove_new = mtk_hdmi_remove,
+ .remove = mtk_hdmi_remove,
.driver = {
.name = "mediatek-drm-hdmi",
.of_match_table = mtk_hdmi_of_ids,
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
index 8e60631d4cd2..07db68067844 100644
--- a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
@@ -331,7 +331,7 @@ MODULE_DEVICE_TABLE(of, mtk_hdmi_ddc_match);
struct platform_driver mtk_hdmi_ddc_driver = {
.probe = mtk_hdmi_ddc_probe,
- .remove_new = mtk_hdmi_ddc_remove,
+ .remove = mtk_hdmi_ddc_remove,
.driver = {
.name = "mediatek-hdmi-ddc",
.of_match_table = mtk_hdmi_ddc_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
index 7c1a8c796833..fc69ee38ce7d 100644
--- a/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
+++ b/drivers/gpu/drm/mediatek/mtk_mdp_rdma.c
@@ -341,7 +341,7 @@ MODULE_DEVICE_TABLE(of, mtk_mdp_rdma_driver_dt_match);
struct platform_driver mtk_mdp_rdma_driver = {
.probe = mtk_mdp_rdma_probe,
- .remove_new = mtk_mdp_rdma_remove,
+ .remove = mtk_mdp_rdma_remove,
.driver = {
.name = "mediatek-mdp-rdma",
.of_match_table = mtk_mdp_rdma_driver_dt_match,
diff --git a/drivers/gpu/drm/mediatek/mtk_padding.c b/drivers/gpu/drm/mediatek/mtk_padding.c
index 4bebd13a07bd..b4e3e5a3428b 100644
--- a/drivers/gpu/drm/mediatek/mtk_padding.c
+++ b/drivers/gpu/drm/mediatek/mtk_padding.c
@@ -146,7 +146,7 @@ MODULE_DEVICE_TABLE(of, mtk_padding_driver_dt_match);
struct platform_driver mtk_padding_driver = {
.probe = mtk_padding_probe,
- .remove_new = mtk_padding_remove,
+ .remove = mtk_padding_remove,
.driver = {
.name = "mediatek-disp-padding",
.of_match_table = mtk_padding_driver_dt_match,
diff --git a/drivers/gpu/drm/meson/meson_drv.c b/drivers/gpu/drm/meson/meson_drv.c
index 7cace75a38af..0f5a1a54544e 100644
--- a/drivers/gpu/drm/meson/meson_drv.c
+++ b/drivers/gpu/drm/meson/meson_drv.c
@@ -559,7 +559,7 @@ static const struct dev_pm_ops meson_drv_pm_ops = {
static struct platform_driver meson_drm_platform_driver = {
.probe = meson_drv_probe,
- .remove_new = meson_drv_remove,
+ .remove = meson_drv_remove,
.shutdown = meson_drv_shutdown,
.driver = {
.name = "meson-drm",
diff --git a/drivers/gpu/drm/meson/meson_dw_hdmi.c b/drivers/gpu/drm/meson/meson_dw_hdmi.c
index b75db829b1da..0d7c68b29dff 100644
--- a/drivers/gpu/drm/meson/meson_dw_hdmi.c
+++ b/drivers/gpu/drm/meson/meson_dw_hdmi.c
@@ -856,7 +856,7 @@ MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
static struct platform_driver meson_dw_hdmi_platform_driver = {
.probe = meson_dw_hdmi_probe,
- .remove_new = meson_dw_hdmi_remove,
+ .remove = meson_dw_hdmi_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = meson_dw_hdmi_of_table,
diff --git a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
index a10cff3ca1fe..66c73c512b0e 100644
--- a/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
+++ b/drivers/gpu/drm/meson/meson_dw_mipi_dsi.c
@@ -345,7 +345,7 @@ MODULE_DEVICE_TABLE(of, meson_dw_mipi_dsi_of_table);
static struct platform_driver meson_dw_mipi_dsi_platform_driver = {
.probe = meson_dw_mipi_dsi_probe,
- .remove_new = meson_dw_mipi_dsi_remove,
+ .remove = meson_dw_mipi_dsi_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = meson_dw_mipi_dsi_of_table,
diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c b/drivers/gpu/drm/msm/adreno/adreno_device.c
index 9ffe91920fbf..236b25c094cd 100644
--- a/drivers/gpu/drm/msm/adreno/adreno_device.c
+++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
@@ -393,7 +393,7 @@ static const struct dev_pm_ops adreno_pm_ops = {
static struct platform_driver adreno_driver = {
.probe = adreno_probe,
- .remove_new = adreno_remove,
+ .remove = adreno_remove,
.shutdown = adreno_shutdown,
.driver = {
.name = "adreno",
diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
index ca4847b2b738..8b251f87a052 100644
--- a/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
+++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c
@@ -1494,7 +1494,7 @@ MODULE_DEVICE_TABLE(of, dpu_dt_match);
static struct platform_driver dpu_driver = {
.probe = dpu_dev_probe,
- .remove_new = dpu_dev_remove,
+ .remove = dpu_dev_remove,
.shutdown = msm_kms_shutdown,
.driver = {
.name = "msm_dpu",
diff --git a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
index 6e4e74f9d63d..c469e66cfc11 100644
--- a/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp4/mdp4_kms.c
@@ -568,7 +568,7 @@ MODULE_DEVICE_TABLE(of, mdp4_dt_match);
static struct platform_driver mdp4_platform_driver = {
.probe = mdp4_probe,
- .remove_new = mdp4_remove,
+ .remove = mdp4_remove,
.shutdown = msm_kms_shutdown,
.driver = {
.name = "mdp4",
diff --git a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
index 374704cce656..3fcca7a3d82e 100644
--- a/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
+++ b/drivers/gpu/drm/msm/disp/mdp5/mdp5_kms.c
@@ -908,7 +908,7 @@ MODULE_DEVICE_TABLE(of, mdp5_dt_match);
static struct platform_driver mdp5_driver = {
.probe = mdp5_dev_probe,
- .remove_new = mdp5_dev_remove,
+ .remove = mdp5_dev_remove,
.shutdown = msm_kms_shutdown,
.driver = {
.name = "msm_mdp",
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index aba925aab7ad..aff51bb973eb 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -1397,7 +1397,7 @@ static const struct dev_pm_ops msm_dp_pm_ops = {
static struct platform_driver msm_dp_display_driver = {
.probe = msm_dp_display_probe,
- .remove_new = msm_dp_display_remove,
+ .remove = msm_dp_display_remove,
.driver = {
.name = "msm-dp-display",
.of_match_table = msm_dp_dt_match,
diff --git a/drivers/gpu/drm/msm/dsi/dsi.c b/drivers/gpu/drm/msm/dsi/dsi.c
index efd7c23b662f..296215877613 100644
--- a/drivers/gpu/drm/msm/dsi/dsi.c
+++ b/drivers/gpu/drm/msm/dsi/dsi.c
@@ -207,7 +207,7 @@ static const struct dev_pm_ops dsi_pm_ops = {
static struct platform_driver dsi_driver = {
.probe = dsi_dev_probe,
- .remove_new = dsi_dev_remove,
+ .remove = dsi_dev_remove,
.driver = {
.name = "msm_dsi",
.of_match_table = dt_match,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi.c b/drivers/gpu/drm/msm/hdmi/hdmi.c
index 0bfee41c2e71..37b3809c6bdd 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi.c
@@ -561,7 +561,7 @@ static const struct of_device_id msm_hdmi_dt_match[] = {
static struct platform_driver msm_hdmi_driver = {
.probe = msm_hdmi_dev_probe,
- .remove_new = msm_hdmi_dev_remove,
+ .remove = msm_hdmi_dev_remove,
.driver = {
.name = "hdmi_msm",
.of_match_table = msm_hdmi_dt_match,
diff --git a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
index 95b3f7535d84..03120c54ced6 100644
--- a/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
+++ b/drivers/gpu/drm/msm/hdmi/hdmi_phy.c
@@ -203,7 +203,7 @@ static const struct of_device_id msm_hdmi_phy_dt_match[] = {
static struct platform_driver msm_hdmi_phy_platform_driver = {
.probe = msm_hdmi_phy_probe,
- .remove_new = msm_hdmi_phy_remove,
+ .remove = msm_hdmi_phy_remove,
.driver = {
.name = "msm_hdmi_phy",
.of_match_table = msm_hdmi_phy_dt_match,
diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
index c2dd8ef6d6dc..ffbcc97b5018 100644
--- a/drivers/gpu/drm/msm/msm_drv.c
+++ b/drivers/gpu/drm/msm/msm_drv.c
@@ -1111,7 +1111,7 @@ static void msm_pdev_remove(struct platform_device *pdev)
static struct platform_driver msm_platform_driver = {
.probe = msm_pdev_probe,
- .remove_new = msm_pdev_remove,
+ .remove = msm_pdev_remove,
.driver = {
.name = "msm",
},
diff --git a/drivers/gpu/drm/msm/msm_mdss.c b/drivers/gpu/drm/msm/msm_mdss.c
index b7bd899ead44..76b6ae35a3cb 100644
--- a/drivers/gpu/drm/msm/msm_mdss.c
+++ b/drivers/gpu/drm/msm/msm_mdss.c
@@ -740,7 +740,7 @@ MODULE_DEVICE_TABLE(of, mdss_dt_match);
static struct platform_driver mdss_platform_driver = {
.probe = mdss_probe,
- .remove_new = mdss_remove,
+ .remove = mdss_remove,
.driver = {
.name = "msm-mdss",
.of_match_table = mdss_dt_match,
diff --git a/drivers/gpu/drm/mxsfb/lcdif_drv.c b/drivers/gpu/drm/mxsfb/lcdif_drv.c
index 58ccad9c425d..51ae0b51b1e8 100644
--- a/drivers/gpu/drm/mxsfb/lcdif_drv.c
+++ b/drivers/gpu/drm/mxsfb/lcdif_drv.c
@@ -368,7 +368,7 @@ static const struct dev_pm_ops lcdif_pm_ops = {
static struct platform_driver lcdif_platform_driver = {
.probe = lcdif_probe,
- .remove_new = lcdif_remove,
+ .remove = lcdif_remove,
.shutdown = lcdif_shutdown,
.driver = {
.name = "imx-lcdif",
diff --git a/drivers/gpu/drm/mxsfb/mxsfb_drv.c b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
index 34a98717b72c..6b95e4eb3e4e 100644
--- a/drivers/gpu/drm/mxsfb/mxsfb_drv.c
+++ b/drivers/gpu/drm/mxsfb/mxsfb_drv.c
@@ -417,7 +417,7 @@ static const struct dev_pm_ops mxsfb_pm_ops = {
static struct platform_driver mxsfb_platform_driver = {
.probe = mxsfb_probe,
- .remove_new = mxsfb_remove,
+ .remove = mxsfb_remove,
.shutdown = mxsfb_shutdown,
.driver = {
.name = "mxsfb",
diff --git a/drivers/gpu/drm/nouveau/nouveau_platform.c b/drivers/gpu/drm/nouveau/nouveau_platform.c
index 829fdc6e4031..a5ce8eb4a3be 100644
--- a/drivers/gpu/drm/nouveau/nouveau_platform.c
+++ b/drivers/gpu/drm/nouveau/nouveau_platform.c
@@ -86,5 +86,5 @@ struct platform_driver nouveau_platform_driver = {
.of_match_table = of_match_ptr(nouveau_platform_match),
},
.probe = nouveau_platform_probe,
- .remove_new = nouveau_platform_remove,
+ .remove = nouveau_platform_remove,
};
diff --git a/drivers/gpu/drm/omapdrm/dss/dispc.c b/drivers/gpu/drm/omapdrm/dss/dispc.c
index 9344855c4887..533f70e8a4a6 100644
--- a/drivers/gpu/drm/omapdrm/dss/dispc.c
+++ b/drivers/gpu/drm/omapdrm/dss/dispc.c
@@ -4766,7 +4766,7 @@ static const struct dev_pm_ops dispc_pm_ops = {
struct platform_driver omap_dispchw_driver = {
.probe = dispc_probe,
- .remove_new = dispc_remove,
+ .remove = dispc_remove,
.driver = {
.name = "omapdss_dispc",
.pm = &dispc_pm_ops,
diff --git a/drivers/gpu/drm/omapdrm/dss/dsi.c b/drivers/gpu/drm/omapdrm/dss/dsi.c
index ea63c64d3a1a..59d20eb8a7e0 100644
--- a/drivers/gpu/drm/omapdrm/dss/dsi.c
+++ b/drivers/gpu/drm/omapdrm/dss/dsi.c
@@ -5093,7 +5093,7 @@ static const struct dev_pm_ops dsi_pm_ops = {
struct platform_driver omap_dsihw_driver = {
.probe = dsi_probe,
- .remove_new = dsi_remove,
+ .remove = dsi_remove,
.driver = {
.name = "omapdss_dsi",
.pm = &dsi_pm_ops,
diff --git a/drivers/gpu/drm/omapdrm/dss/dss.c b/drivers/gpu/drm/omapdrm/dss/dss.c
index 988888e164d7..7b2df3185de4 100644
--- a/drivers/gpu/drm/omapdrm/dss/dss.c
+++ b/drivers/gpu/drm/omapdrm/dss/dss.c
@@ -1606,7 +1606,7 @@ static const struct dev_pm_ops dss_pm_ops = {
struct platform_driver omap_dsshw_driver = {
.probe = dss_probe,
- .remove_new = dss_remove,
+ .remove = dss_remove,
.shutdown = dss_shutdown,
.driver = {
.name = "omapdss_dss",
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi4.c b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
index 9b8747d83ee8..4435f0027c78 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi4.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi4.c
@@ -852,7 +852,7 @@ static const struct of_device_id hdmi_of_match[] = {
struct platform_driver omapdss_hdmi4hw_driver = {
.probe = hdmi4_probe,
- .remove_new = hdmi4_remove,
+ .remove = hdmi4_remove,
.driver = {
.name = "omapdss_hdmi",
.of_match_table = hdmi_of_match,
diff --git a/drivers/gpu/drm/omapdrm/dss/hdmi5.c b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
index c7ae2235ae99..a8c740df3146 100644
--- a/drivers/gpu/drm/omapdrm/dss/hdmi5.c
+++ b/drivers/gpu/drm/omapdrm/dss/hdmi5.c
@@ -819,7 +819,7 @@ static const struct of_device_id hdmi_of_match[] = {
struct platform_driver omapdss_hdmi5hw_driver = {
.probe = hdmi5_probe,
- .remove_new = hdmi5_remove,
+ .remove = hdmi5_remove,
.driver = {
.name = "omapdss_hdmi5",
.of_match_table = hdmi_of_match,
diff --git a/drivers/gpu/drm/omapdrm/dss/venc.c b/drivers/gpu/drm/omapdrm/dss/venc.c
index f163d52a7c7d..aaeef603682c 100644
--- a/drivers/gpu/drm/omapdrm/dss/venc.c
+++ b/drivers/gpu/drm/omapdrm/dss/venc.c
@@ -912,7 +912,7 @@ static const struct of_device_id venc_of_match[] = {
struct platform_driver omap_venchw_driver = {
.probe = venc_probe,
- .remove_new = venc_remove,
+ .remove = venc_remove,
.driver = {
.name = "omapdss_venc",
.pm = &venc_pm_ops,
diff --git a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
index fcd600024136..3fff32c000a6 100644
--- a/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
+++ b/drivers/gpu/drm/omapdrm/omap_dmm_tiler.c
@@ -1210,7 +1210,7 @@ static const struct of_device_id dmm_of_match[] = {
struct platform_driver omap_dmm_driver = {
.probe = omap_dmm_probe,
- .remove_new = omap_dmm_remove,
+ .remove = omap_dmm_remove,
.driver = {
.name = DMM_DRIVER_NAME,
.of_match_table = of_match_ptr(dmm_of_match),
diff --git a/drivers/gpu/drm/omapdrm/omap_drv.c b/drivers/gpu/drm/omapdrm/omap_drv.c
index 1796cd20a877..e27376121606 100644
--- a/drivers/gpu/drm/omapdrm/omap_drv.c
+++ b/drivers/gpu/drm/omapdrm/omap_drv.c
@@ -857,7 +857,7 @@ static struct platform_driver pdev = {
.pm = &omapdrm_pm_ops,
},
.probe = pdev_probe,
- .remove_new = pdev_remove,
+ .remove = pdev_remove,
.shutdown = pdev_shutdown,
};
diff --git a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
index 36f9ee4baad3..30cf1cdc1aa3 100644
--- a/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
+++ b/drivers/gpu/drm/omapdrm/omap_gem_dmabuf.c
@@ -11,7 +11,7 @@
#include "omap_drv.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
/* -----------------------------------------------------------------------------
* DMABUF Export
diff --git a/drivers/gpu/drm/panel/panel-edp.c b/drivers/gpu/drm/panel/panel-edp.c
index 8566e9cf2f82..94a46241dece 100644
--- a/drivers/gpu/drm/panel/panel-edp.c
+++ b/drivers/gpu/drm/panel/panel-edp.c
@@ -2049,7 +2049,7 @@ static struct platform_driver panel_edp_platform_driver = {
.pm = &panel_edp_pm_ops,
},
.probe = panel_edp_platform_probe,
- .remove_new = panel_edp_platform_remove,
+ .remove = panel_edp_platform_remove,
.shutdown = panel_edp_platform_shutdown,
};
diff --git a/drivers/gpu/drm/panel/panel-himax-hx83102.c b/drivers/gpu/drm/panel/panel-himax-hx83102.c
index 8b48bba18131..3644a7544b93 100644
--- a/drivers/gpu/drm/panel/panel-himax-hx83102.c
+++ b/drivers/gpu/drm/panel/panel-himax-hx83102.c
@@ -565,6 +565,8 @@ static int hx83102_get_modes(struct drm_panel *panel,
struct drm_display_mode *mode;
mode = drm_mode_duplicate(connector->dev, m);
+ if (!mode)
+ return -ENOMEM;
mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED;
drm_mode_set_name(mode);
diff --git a/drivers/gpu/drm/panel/panel-lvds.c b/drivers/gpu/drm/panel/panel-lvds.c
index 1b8e3156914c..ba6c015aabba 100644
--- a/drivers/gpu/drm/panel/panel-lvds.c
+++ b/drivers/gpu/drm/panel/panel-lvds.c
@@ -246,7 +246,7 @@ MODULE_DEVICE_TABLE(of, panel_lvds_of_table);
static struct platform_driver panel_lvds_driver = {
.probe = panel_lvds_probe,
- .remove_new = panel_lvds_remove,
+ .remove = panel_lvds_remove,
.driver = {
.name = "panel-lvds",
.of_match_table = panel_lvds_of_table,
diff --git a/drivers/gpu/drm/panel/panel-novatek-nt35950.c b/drivers/gpu/drm/panel/panel-novatek-nt35950.c
index b036208f9356..08b22b592ab0 100644
--- a/drivers/gpu/drm/panel/panel-novatek-nt35950.c
+++ b/drivers/gpu/drm/panel/panel-novatek-nt35950.c
@@ -481,9 +481,9 @@ static int nt35950_probe(struct mipi_dsi_device *dsi)
return dev_err_probe(dev, -EPROBE_DEFER, "Cannot get secondary DSI host\n");
nt->dsi[1] = mipi_dsi_device_register_full(dsi_r_host, info);
- if (!nt->dsi[1]) {
+ if (IS_ERR(nt->dsi[1])) {
dev_err(dev, "Cannot get secondary DSI node\n");
- return -ENODEV;
+ return PTR_ERR(nt->dsi[1]);
}
num_dsis++;
}
diff --git a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
index 8a3fe531c641..7d1b421ea9dd 100644
--- a/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
+++ b/drivers/gpu/drm/panel/panel-seiko-43wvf1g.c
@@ -297,7 +297,7 @@ static struct platform_driver seiko_panel_platform_driver = {
.of_match_table = platform_of_match,
},
.probe = seiko_panel_platform_probe,
- .remove_new = seiko_panel_remove,
+ .remove = seiko_panel_remove,
};
module_platform_driver(seiko_panel_platform_driver);
diff --git a/drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c b/drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c
index 76bd9e810827..a9673a52b861 100644
--- a/drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c
+++ b/drivers/gpu/drm/panel/panel-sharp-ls037v7dw01.c
@@ -207,7 +207,7 @@ MODULE_DEVICE_TABLE(of, ls037v7dw01_of_match);
static struct platform_driver ls037v7dw01_driver = {
.probe = ls037v7dw01_probe,
- .remove_new = ls037v7dw01_remove,
+ .remove = ls037v7dw01_remove,
.driver = {
.name = "panel-sharp-ls037v7dw01",
.of_match_table = ls037v7dw01_of_match,
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c
index 06381c628209..222c170dde8b 100644
--- a/drivers/gpu/drm/panel/panel-simple.c
+++ b/drivers/gpu/drm/panel/panel-simple.c
@@ -5120,7 +5120,7 @@ static struct platform_driver panel_simple_platform_driver = {
.pm = &panel_simple_pm_ops,
},
.probe = panel_simple_platform_probe,
- .remove_new = panel_simple_platform_remove,
+ .remove = panel_simple_platform_remove,
.shutdown = panel_simple_platform_shutdown,
};
diff --git a/drivers/gpu/drm/panel/panel-sitronix-st7701.c b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
index eef03d04e0cd..1f72ef7ca74c 100644
--- a/drivers/gpu/drm/panel/panel-sitronix-st7701.c
+++ b/drivers/gpu/drm/panel/panel-sitronix-st7701.c
@@ -1177,6 +1177,7 @@ static int st7701_probe(struct device *dev, int connector_type)
return dev_err_probe(dev, ret, "Failed to get orientation\n");
drm_panel_init(&st7701->panel, dev, &st7701_funcs, connector_type);
+ st7701->panel.prepare_prev_first = true;
/**
* Once sleep out has been issued, ST7701 IC required to wait 120ms
diff --git a/drivers/gpu/drm/panel/panel-synaptics-r63353.c b/drivers/gpu/drm/panel/panel-synaptics-r63353.c
index 169c629746c7..17349825543f 100644
--- a/drivers/gpu/drm/panel/panel-synaptics-r63353.c
+++ b/drivers/gpu/drm/panel/panel-synaptics-r63353.c
@@ -325,7 +325,7 @@ static void r63353_panel_shutdown(struct mipi_dsi_device *dsi)
{
struct r63353_panel *rpanel = mipi_dsi_get_drvdata(dsi);
- r63353_panel_unprepare(&rpanel->base);
+ drm_panel_unprepare(&rpanel->base);
}
static const struct r63353_desc sharp_ls068b3sx02_data = {
diff --git a/drivers/gpu/drm/panfrost/panfrost_drv.c b/drivers/gpu/drm/panfrost/panfrost_drv.c
index 04d615df5259..ee3864476eb9 100644
--- a/drivers/gpu/drm/panfrost/panfrost_drv.c
+++ b/drivers/gpu/drm/panfrost/panfrost_drv.c
@@ -866,7 +866,7 @@ MODULE_DEVICE_TABLE(of, dt_match);
static struct platform_driver panfrost_driver = {
.probe = panfrost_probe,
- .remove_new = panfrost_remove,
+ .remove = panfrost_remove,
.driver = {
.name = "panfrost",
.pm = pm_ptr(&panfrost_pm_ops),
diff --git a/drivers/gpu/drm/panthor/panthor_drv.c b/drivers/gpu/drm/panthor/panthor_drv.c
index ac7e53f6e3f0..0b3fbee3d37a 100644
--- a/drivers/gpu/drm/panthor/panthor_drv.c
+++ b/drivers/gpu/drm/panthor/panthor_drv.c
@@ -1589,7 +1589,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(panthor_pm_ops,
static struct platform_driver panthor_driver = {
.probe = panthor_probe,
- .remove_new = panthor_remove,
+ .remove = panthor_remove,
.driver = {
.name = "panthor",
.pm = pm_ptr(&panthor_pm_ops),
diff --git a/drivers/gpu/drm/radeon/radeon_audio.c b/drivers/gpu/drm/radeon/radeon_audio.c
index 47aa06a9a942..5b69cc8011b4 100644
--- a/drivers/gpu/drm/radeon/radeon_audio.c
+++ b/drivers/gpu/drm/radeon/radeon_audio.c
@@ -760,16 +760,20 @@ static int radeon_audio_component_get_eld(struct device *kdev, int port,
if (!rdev->audio.enabled || !rdev->mode_info.mode_config_initialized)
return 0;
- list_for_each_entry(encoder, &rdev_to_drm(rdev)->mode_config.encoder_list, head) {
+ list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
+ const struct drm_connector_helper_funcs *connector_funcs =
+ connector->helper_private;
+ encoder = connector_funcs->best_encoder(connector);
+
+ if (!encoder)
+ continue;
+
if (!radeon_encoder_is_digital(encoder))
continue;
radeon_encoder = to_radeon_encoder(encoder);
dig = radeon_encoder->enc_priv;
if (!dig->pin || dig->pin->id != port)
continue;
- connector = radeon_get_connector_for_encoder(encoder);
- if (!connector)
- continue;
*enabled = true;
ret = drm_eld_size(connector->eld);
memcpy(buf, connector->eld, min(max_bytes, ret));
diff --git a/drivers/gpu/drm/radeon/radeon_connectors.c b/drivers/gpu/drm/radeon/radeon_connectors.c
index f9c73c55f04f..f9996304d943 100644
--- a/drivers/gpu/drm/radeon/radeon_connectors.c
+++ b/drivers/gpu/drm/radeon/radeon_connectors.c
@@ -1255,16 +1255,6 @@ radeon_dvi_detect(struct drm_connector *connector, bool force)
goto exit;
}
}
-
- if (dret && radeon_connector->hpd.hpd != RADEON_HPD_NONE &&
- !radeon_hpd_sense(rdev, radeon_connector->hpd.hpd) &&
- connector->connector_type == DRM_MODE_CONNECTOR_HDMIA) {
- DRM_DEBUG_KMS("EDID is readable when HPD disconnected\n");
- schedule_delayed_work(&rdev->hotplug_work, msecs_to_jiffies(1000));
- ret = connector_status_disconnected;
- goto exit;
- }
-
if (dret) {
radeon_connector->detected_by_load = false;
radeon_connector_free_edid(connector);
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 23d6d1a2586d..5e958cc223f4 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -248,10 +248,9 @@ int radeon_cik_support = 1;
MODULE_PARM_DESC(cik_support, "CIK support (1 = enabled (default), 0 = disabled)");
module_param_named(cik_support, radeon_cik_support, int, 0444);
-static struct pci_device_id pciidlist[] = {
+static const struct pci_device_id pciidlist[] = {
radeon_PCI_IDS
};
-
MODULE_DEVICE_TABLE(pci, pciidlist);
static const struct drm_driver kms_driver;
diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c
index 69d0c12fa419..616d25c8c2de 100644
--- a/drivers/gpu/drm/radeon/radeon_ttm.c
+++ b/drivers/gpu/drm/radeon/radeon_ttm.c
@@ -219,8 +219,7 @@ static int radeon_bo_move(struct ttm_buffer_object *bo, bool evict,
if (old_mem->mem_type == TTM_PL_TT &&
new_mem->mem_type == TTM_PL_SYSTEM) {
radeon_ttm_tt_unbind(bo->bdev, bo->ttm);
- ttm_resource_free(bo, &bo->resource);
- ttm_bo_assign_mem(bo, new_mem);
+ ttm_bo_move_null(bo, new_mem);
goto out;
}
if (rdev->ring[radeon_copy_ring_index(rdev)].ready &&
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c b/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c
index 26a2f5ad8ee5..79b67c406bd6 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_cmm.c
@@ -201,7 +201,7 @@ MODULE_DEVICE_TABLE(of, rcar_cmm_of_table);
static struct platform_driver rcar_cmm_platform_driver = {
.probe = rcar_cmm_probe,
- .remove_new = rcar_cmm_remove,
+ .remove = rcar_cmm_remove,
.driver = {
.name = "rcar-cmm",
.of_match_table = rcar_cmm_of_table,
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
index 4e0bafc86f50..f9ecc334c024 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_du_drv.c
@@ -729,7 +729,7 @@ error:
static struct platform_driver rcar_du_platform_driver = {
.probe = rcar_du_probe,
- .remove_new = rcar_du_remove,
+ .remove = rcar_du_remove,
.shutdown = rcar_du_shutdown,
.driver = {
.name = "rcar-du",
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c
index 119d69d20b23..c0176e5de9a8 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_dw_hdmi.c
@@ -108,7 +108,7 @@ MODULE_DEVICE_TABLE(of, rcar_dw_hdmi_of_table);
static struct platform_driver rcar_dw_hdmi_platform_driver = {
.probe = rcar_dw_hdmi_probe,
- .remove_new = rcar_dw_hdmi_remove,
+ .remove = rcar_dw_hdmi_remove,
.driver = {
.name = "rcar-dw-hdmi",
.of_match_table = rcar_dw_hdmi_of_table,
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c
index 92ba43a6fe38..e8d64583e3bd 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_lvds.c
@@ -1018,7 +1018,7 @@ static const struct dev_pm_ops rcar_lvds_pm_ops = {
static struct platform_driver rcar_lvds_platform_driver = {
.probe = rcar_lvds_probe,
- .remove_new = rcar_lvds_remove,
+ .remove = rcar_lvds_remove,
.driver = {
.name = "rcar-lvds",
.pm = &rcar_lvds_pm_ops,
diff --git a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
index 2dba7c5ffd2c..8180625d5866 100644
--- a/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rcar-du/rcar_mipi_dsi.c
@@ -1088,7 +1088,7 @@ MODULE_DEVICE_TABLE(of, rcar_mipi_dsi_of_table);
static struct platform_driver rcar_mipi_dsi_platform_driver = {
.probe = rcar_mipi_dsi_probe,
- .remove_new = rcar_mipi_dsi_remove,
+ .remove = rcar_mipi_dsi_remove,
.driver = {
.name = "rcar-mipi-dsi",
.of_match_table = rcar_mipi_dsi_of_table,
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
index bbd7003335da..b069efd8ffc3 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_du_drv.c
@@ -173,7 +173,7 @@ error:
static struct platform_driver rzg2l_du_platform_driver = {
.probe = rzg2l_du_probe,
- .remove_new = rzg2l_du_remove,
+ .remove = rzg2l_du_remove,
.shutdown = rzg2l_du_shutdown,
.driver = {
.name = "rzg2l-du",
diff --git a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
index 10febea473cd..fa7a1ae22aa3 100644
--- a/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
+++ b/drivers/gpu/drm/renesas/rz-du/rzg2l_mipi_dsi.c
@@ -798,7 +798,7 @@ MODULE_DEVICE_TABLE(of, rzg2l_mipi_dsi_of_table);
static struct platform_driver rzg2l_mipi_dsi_platform_driver = {
.probe = rzg2l_mipi_dsi_probe,
- .remove_new = rzg2l_mipi_dsi_remove,
+ .remove = rzg2l_mipi_dsi_remove,
.driver = {
.name = "rzg2l-mipi-dsi",
.pm = &rzg2l_mipi_pm_ops,
diff --git a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
index 8d3effe3f598..76ee3e16077c 100644
--- a/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
+++ b/drivers/gpu/drm/renesas/shmobile/shmob_drm_drv.c
@@ -282,7 +282,7 @@ static const struct of_device_id shmob_drm_of_table[] __maybe_unused = {
static struct platform_driver shmob_drm_platform_driver = {
.probe = shmob_drm_probe,
- .remove_new = shmob_drm_remove,
+ .remove = shmob_drm_remove,
.shutdown = shmob_drm_shutdown,
.driver = {
.name = "shmob-drm",
diff --git a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
index d3341edfe4f4..546d13f19f9b 100644
--- a/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/analogix_dp-rockchip.c
@@ -470,7 +470,7 @@ MODULE_DEVICE_TABLE(of, rockchip_dp_dt_ids);
struct platform_driver rockchip_dp_driver = {
.probe = rockchip_dp_probe,
- .remove_new = rockchip_dp_remove,
+ .remove = rockchip_dp_remove,
.driver = {
.name = "rockchip-dp",
.pm = pm_ptr(&rockchip_dp_pm_ops),
diff --git a/drivers/gpu/drm/rockchip/cdn-dp-core.c b/drivers/gpu/drm/rockchip/cdn-dp-core.c
index b04538907f95..ff9d95e2c4d4 100644
--- a/drivers/gpu/drm/rockchip/cdn-dp-core.c
+++ b/drivers/gpu/drm/rockchip/cdn-dp-core.c
@@ -1254,7 +1254,7 @@ static const struct dev_pm_ops cdn_dp_pm_ops = {
struct platform_driver cdn_dp_driver = {
.probe = cdn_dp_probe,
- .remove_new = cdn_dp_remove,
+ .remove = cdn_dp_remove,
.shutdown = cdn_dp_shutdown,
.driver = {
.name = "cdn-dp",
diff --git a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
index 58a44af0e9ad..1b64b6e39cc8 100644
--- a/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw-mipi-dsi-rockchip.c
@@ -1709,7 +1709,7 @@ MODULE_DEVICE_TABLE(of, dw_mipi_dsi_rockchip_dt_ids);
struct platform_driver dw_mipi_dsi_rockchip_driver = {
.probe = dw_mipi_dsi_rockchip_probe,
- .remove_new = dw_mipi_dsi_rockchip_remove,
+ .remove = dw_mipi_dsi_rockchip_remove,
.driver = {
.of_match_table = dw_mipi_dsi_rockchip_dt_ids,
.pm = &dw_mipi_dsi_rockchip_pm_ops,
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
index 96e1097f993d..42bda4ffbbbd 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi-rockchip.c
@@ -666,7 +666,7 @@ static const struct dev_pm_ops dw_hdmi_rockchip_pm = {
struct platform_driver dw_hdmi_rockchip_pltfm_driver = {
.probe = dw_hdmi_rockchip_probe,
- .remove_new = dw_hdmi_rockchip_remove,
+ .remove = dw_hdmi_rockchip_remove,
.driver = {
.name = "dwhdmi-rockchip",
.pm = &dw_hdmi_rockchip_pm,
diff --git a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
index 9c796ee4c303..c8b362cc2b95 100644
--- a/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
+++ b/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c
@@ -82,7 +82,7 @@ static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
* comment in rk_hdptx_phy_power_on() from
* drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
*/
- phy_set_bus_width(hdmi->phy, rate / 100);
+ phy_set_bus_width(hdmi->phy, div_u64(rate, 100));
}
}
diff --git a/drivers/gpu/drm/rockchip/inno_hdmi.c b/drivers/gpu/drm/rockchip/inno_hdmi.c
index 42ef62aa0a1e..b58e2a29294b 100644
--- a/drivers/gpu/drm/rockchip/inno_hdmi.c
+++ b/drivers/gpu/drm/rockchip/inno_hdmi.c
@@ -1017,7 +1017,7 @@ MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
struct platform_driver inno_hdmi_driver = {
.probe = inno_hdmi_probe,
- .remove_new = inno_hdmi_remove,
+ .remove = inno_hdmi_remove,
.driver = {
.name = "innohdmi-rockchip",
.of_match_table = inno_hdmi_dt_ids,
diff --git a/drivers/gpu/drm/rockchip/rk3066_hdmi.c b/drivers/gpu/drm/rockchip/rk3066_hdmi.c
index 784de990da1b..b0fc8ace2e41 100644
--- a/drivers/gpu/drm/rockchip/rk3066_hdmi.c
+++ b/drivers/gpu/drm/rockchip/rk3066_hdmi.c
@@ -858,7 +858,7 @@ MODULE_DEVICE_TABLE(of, rk3066_hdmi_dt_ids);
struct platform_driver rk3066_hdmi_driver = {
.probe = rk3066_hdmi_probe,
- .remove_new = rk3066_hdmi_remove,
+ .remove = rk3066_hdmi_remove,
.driver = {
.name = "rockchip-rk3066-hdmi",
.of_match_table = rk3066_hdmi_dt_ids,
diff --git a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
index 585355de696b..32d8394c4c49 100644
--- a/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
+++ b/drivers/gpu/drm/rockchip/rockchip_drm_drv.c
@@ -500,7 +500,7 @@ MODULE_DEVICE_TABLE(of, rockchip_drm_dt_ids);
static struct platform_driver rockchip_drm_platform_driver = {
.probe = rockchip_drm_platform_probe,
- .remove_new = rockchip_drm_platform_remove,
+ .remove = rockchip_drm_platform_remove,
.shutdown = rockchip_drm_platform_shutdown,
.driver = {
.name = "rockchip-drm",
diff --git a/drivers/gpu/drm/rockchip/rockchip_lvds.c b/drivers/gpu/drm/rockchip/rockchip_lvds.c
index 9a01aa450741..aba733736ff7 100644
--- a/drivers/gpu/drm/rockchip/rockchip_lvds.c
+++ b/drivers/gpu/drm/rockchip/rockchip_lvds.c
@@ -746,7 +746,7 @@ static void rockchip_lvds_remove(struct platform_device *pdev)
struct platform_driver rockchip_lvds_driver = {
.probe = rockchip_lvds_probe,
- .remove_new = rockchip_lvds_remove,
+ .remove = rockchip_lvds_remove,
.driver = {
.name = "rockchip-lvds",
.of_match_table = rockchip_lvds_dt_ids,
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
index 18efb3fe1c00..f9d87a0abc8b 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop2_reg.c
@@ -501,7 +501,7 @@ static void vop2_remove(struct platform_device *pdev)
struct platform_driver vop2_platform_driver = {
.probe = vop2_probe,
- .remove_new = vop2_remove,
+ .remove = vop2_remove,
.driver = {
.name = "rockchip-vop2",
.of_match_table = vop2_dt_match,
diff --git a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
index e2c6ba26f437..8998967f0c00 100644
--- a/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
+++ b/drivers/gpu/drm/rockchip/rockchip_vop_reg.c
@@ -1284,7 +1284,7 @@ static void vop_remove(struct platform_device *pdev)
struct platform_driver vop_platform_driver = {
.probe = vop_probe,
- .remove_new = vop_remove,
+ .remove = vop_remove,
.driver = {
.name = "rockchip-vop",
.of_match_table = vop_driver_dt_match,
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 7ce25281c74c..57da84908752 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -1355,7 +1355,8 @@ EXPORT_SYMBOL(drm_sched_init);
* drm_sched_backend_ops.run_job(). Consequently, drm_sched_backend_ops.free_job()
* will not be called for all jobs still in drm_gpu_scheduler.pending_list.
* There is no solution for this currently. Thus, it is up to the driver to make
- * sure that
+ * sure that:
+ *
* a) drm_sched_fini() is only called after for all submitted jobs
* drm_sched_backend_ops.free_job() has been called or that
* b) the jobs for which drm_sched_backend_ops.free_job() has not been called
diff --git a/drivers/gpu/drm/solomon/ssd130x-i2c.c b/drivers/gpu/drm/solomon/ssd130x-i2c.c
index f2ccab9c06d9..941a2eb44c57 100644
--- a/drivers/gpu/drm/solomon/ssd130x-i2c.c
+++ b/drivers/gpu/drm/solomon/ssd130x-i2c.c
@@ -123,4 +123,4 @@ module_i2c_driver(ssd130x_i2c_driver);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(DRM_SSD130X);
+MODULE_IMPORT_NS("DRM_SSD130X");
diff --git a/drivers/gpu/drm/solomon/ssd130x-spi.c b/drivers/gpu/drm/solomon/ssd130x-spi.c
index 84bfde31d172..08334be38694 100644
--- a/drivers/gpu/drm/solomon/ssd130x-spi.c
+++ b/drivers/gpu/drm/solomon/ssd130x-spi.c
@@ -192,4 +192,4 @@ module_spi_driver(ssd130x_spi_driver);
MODULE_DESCRIPTION(DRIVER_DESC);
MODULE_AUTHOR("Javier Martinez Canillas <javierm@redhat.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(DRM_SSD130X);
+MODULE_IMPORT_NS("DRM_SSD130X");
diff --git a/drivers/gpu/drm/solomon/ssd130x.c b/drivers/gpu/drm/solomon/ssd130x.c
index 29b2f82d81f8..486d8f5282f9 100644
--- a/drivers/gpu/drm/solomon/ssd130x.c
+++ b/drivers/gpu/drm/solomon/ssd130x.c
@@ -209,7 +209,7 @@ const struct ssd130x_deviceinfo ssd130x_variants[] = {
.family_id = SSD133X_FAMILY,
}
};
-EXPORT_SYMBOL_NS_GPL(ssd130x_variants, DRM_SSD130X);
+EXPORT_SYMBOL_NS_GPL(ssd130x_variants, "DRM_SSD130X");
struct ssd130x_crtc_state {
struct drm_crtc_state base;
diff --git a/drivers/gpu/drm/sprd/sprd_dpu.c b/drivers/gpu/drm/sprd/sprd_dpu.c
index deb3bb96e2a8..cb2816985305 100644
--- a/drivers/gpu/drm/sprd/sprd_dpu.c
+++ b/drivers/gpu/drm/sprd/sprd_dpu.c
@@ -866,7 +866,7 @@ static void sprd_dpu_remove(struct platform_device *pdev)
struct platform_driver sprd_dpu_driver = {
.probe = sprd_dpu_probe,
- .remove_new = sprd_dpu_remove,
+ .remove = sprd_dpu_remove,
.driver = {
.name = "sprd-dpu-drv",
.of_match_table = dpu_match_table,
diff --git a/drivers/gpu/drm/sprd/sprd_drm.c b/drivers/gpu/drm/sprd/sprd_drm.c
index a74cd0caf645..bc1c747d3ea4 100644
--- a/drivers/gpu/drm/sprd/sprd_drm.c
+++ b/drivers/gpu/drm/sprd/sprd_drm.c
@@ -163,7 +163,7 @@ MODULE_DEVICE_TABLE(of, drm_match_table);
static struct platform_driver sprd_drm_driver = {
.probe = sprd_drm_probe,
- .remove_new = sprd_drm_remove,
+ .remove = sprd_drm_remove,
.shutdown = sprd_drm_shutdown,
.driver = {
.name = "sprd-drm-drv",
diff --git a/drivers/gpu/drm/sprd/sprd_dsi.c b/drivers/gpu/drm/sprd/sprd_dsi.c
index 44a7a579660f..8fc26479bb6b 100644
--- a/drivers/gpu/drm/sprd/sprd_dsi.c
+++ b/drivers/gpu/drm/sprd/sprd_dsi.c
@@ -1060,7 +1060,7 @@ static void sprd_dsi_remove(struct platform_device *pdev)
struct platform_driver sprd_dsi_driver = {
.probe = sprd_dsi_probe,
- .remove_new = sprd_dsi_remove,
+ .remove = sprd_dsi_remove,
.driver = {
.name = "sprd-dsi-drv",
.of_match_table = dsi_match_table,
diff --git a/drivers/gpu/drm/sti/sti_compositor.c b/drivers/gpu/drm/sti/sti_compositor.c
index 33487a1fed8f..063f82d23d80 100644
--- a/drivers/gpu/drm/sti/sti_compositor.c
+++ b/drivers/gpu/drm/sti/sti_compositor.c
@@ -269,7 +269,7 @@ struct platform_driver sti_compositor_driver = {
.of_match_table = compositor_of_match,
},
.probe = sti_compositor_probe,
- .remove_new = sti_compositor_remove,
+ .remove = sti_compositor_remove,
};
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
diff --git a/drivers/gpu/drm/sti/sti_drv.c b/drivers/gpu/drm/sti/sti_drv.c
index 65f180c8e8e2..61ceff9aee7e 100644
--- a/drivers/gpu/drm/sti/sti_drv.c
+++ b/drivers/gpu/drm/sti/sti_drv.c
@@ -270,7 +270,7 @@ MODULE_DEVICE_TABLE(of, sti_dt_ids);
static struct platform_driver sti_platform_driver = {
.probe = sti_platform_probe,
- .remove_new = sti_platform_remove,
+ .remove = sti_platform_remove,
.shutdown = sti_platform_shutdown,
.driver = {
.name = DRIVER_NAME,
diff --git a/drivers/gpu/drm/sti/sti_dvo.c b/drivers/gpu/drm/sti/sti_dvo.c
index 68b8197b3dd1..c6c2abaa1891 100644
--- a/drivers/gpu/drm/sti/sti_dvo.c
+++ b/drivers/gpu/drm/sti/sti_dvo.c
@@ -585,7 +585,7 @@ struct platform_driver sti_dvo_driver = {
.of_match_table = dvo_of_match,
},
.probe = sti_dvo_probe,
- .remove_new = sti_dvo_remove,
+ .remove = sti_dvo_remove,
};
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
diff --git a/drivers/gpu/drm/sti/sti_hda.c b/drivers/gpu/drm/sti/sti_hda.c
index f18faad974aa..b12863bea955 100644
--- a/drivers/gpu/drm/sti/sti_hda.c
+++ b/drivers/gpu/drm/sti/sti_hda.c
@@ -810,7 +810,7 @@ struct platform_driver sti_hda_driver = {
.of_match_table = hda_of_match,
},
.probe = sti_hda_probe,
- .remove_new = sti_hda_remove,
+ .remove = sti_hda_remove,
};
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c
index 847470f747c0..21b46a6465f0 100644
--- a/drivers/gpu/drm/sti/sti_hdmi.c
+++ b/drivers/gpu/drm/sti/sti_hdmi.c
@@ -1492,7 +1492,7 @@ struct platform_driver sti_hdmi_driver = {
.of_match_table = hdmi_of_match,
},
.probe = sti_hdmi_probe,
- .remove_new = sti_hdmi_remove,
+ .remove = sti_hdmi_remove,
};
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
diff --git a/drivers/gpu/drm/sti/sti_hqvdp.c b/drivers/gpu/drm/sti/sti_hqvdp.c
index 5793cf2cb897..0f658709c9d0 100644
--- a/drivers/gpu/drm/sti/sti_hqvdp.c
+++ b/drivers/gpu/drm/sti/sti_hqvdp.c
@@ -1420,7 +1420,7 @@ struct platform_driver sti_hqvdp_driver = {
.of_match_table = hqvdp_of_match,
},
.probe = sti_hqvdp_probe,
- .remove_new = sti_hqvdp_remove,
+ .remove = sti_hqvdp_remove,
};
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
diff --git a/drivers/gpu/drm/sti/sti_mixer.c b/drivers/gpu/drm/sti/sti_mixer.c
index 7e5f14646625..06c1b81912f7 100644
--- a/drivers/gpu/drm/sti/sti_mixer.c
+++ b/drivers/gpu/drm/sti/sti_mixer.c
@@ -137,7 +137,7 @@ static void mixer_dbg_crb(struct seq_file *s, int val)
}
}
-static void mixer_dbg_mxn(struct seq_file *s, void *addr)
+static void mixer_dbg_mxn(struct seq_file *s, void __iomem *addr)
{
int i;
diff --git a/drivers/gpu/drm/sti/sti_tvout.c b/drivers/gpu/drm/sti/sti_tvout.c
index e714c232026c..af6c06f448c4 100644
--- a/drivers/gpu/drm/sti/sti_tvout.c
+++ b/drivers/gpu/drm/sti/sti_tvout.c
@@ -889,7 +889,7 @@ struct platform_driver sti_tvout_driver = {
.of_match_table = tvout_of_match,
},
.probe = sti_tvout_probe,
- .remove_new = sti_tvout_remove,
+ .remove = sti_tvout_remove,
};
MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
diff --git a/drivers/gpu/drm/stm/drv.c b/drivers/gpu/drm/stm/drv.c
index 478dc129d5c2..bf090a354989 100644
--- a/drivers/gpu/drm/stm/drv.c
+++ b/drivers/gpu/drm/stm/drv.c
@@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, drv_dt_ids);
static struct platform_driver stm_drm_platform_driver = {
.probe = stm_drm_platform_probe,
- .remove_new = stm_drm_platform_remove,
+ .remove = stm_drm_platform_remove,
.shutdown = stm_drm_platform_shutdown,
.driver = {
.name = "stm32-display",
diff --git a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
index b20123854c4a..2c7bc064bc66 100644
--- a/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
+++ b/drivers/gpu/drm/stm/dw_mipi_dsi-stm.c
@@ -783,7 +783,7 @@ static const struct dev_pm_ops dw_mipi_dsi_stm_pm_ops = {
static struct platform_driver dw_mipi_dsi_stm_driver = {
.probe = dw_mipi_dsi_stm_probe,
- .remove_new = dw_mipi_dsi_stm_remove,
+ .remove = dw_mipi_dsi_stm_remove,
.driver = {
.of_match_table = dw_mipi_dsi_stm_dt_ids,
.name = "stm32-display-dsi",
diff --git a/drivers/gpu/drm/sun4i/sun4i_backend.c b/drivers/gpu/drm/sun4i/sun4i_backend.c
index e89eb96d3131..2dded3b828df 100644
--- a/drivers/gpu/drm/sun4i/sun4i_backend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_backend.c
@@ -1028,7 +1028,7 @@ MODULE_DEVICE_TABLE(of, sun4i_backend_of_table);
static struct platform_driver sun4i_backend_platform_driver = {
.probe = sun4i_backend_probe,
- .remove_new = sun4i_backend_remove,
+ .remove = sun4i_backend_remove,
.driver = {
.name = "sun4i-backend",
.of_match_table = sun4i_backend_of_table,
diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c b/drivers/gpu/drm/sun4i/sun4i_drv.c
index 3f880d8a5666..5eccf58f2e17 100644
--- a/drivers/gpu/drm/sun4i/sun4i_drv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
@@ -443,7 +443,7 @@ MODULE_DEVICE_TABLE(of, sun4i_drv_of_table);
static struct platform_driver sun4i_drv_platform_driver = {
.probe = sun4i_drv_probe,
- .remove_new = sun4i_drv_remove,
+ .remove = sun4i_drv_remove,
.shutdown = sun4i_drv_shutdown,
.driver = {
.name = "sun4i-drm",
diff --git a/drivers/gpu/drm/sun4i/sun4i_frontend.c b/drivers/gpu/drm/sun4i/sun4i_frontend.c
index 280d444dbb66..5ab1604f12dd 100644
--- a/drivers/gpu/drm/sun4i/sun4i_frontend.c
+++ b/drivers/gpu/drm/sun4i/sun4i_frontend.c
@@ -717,7 +717,7 @@ MODULE_DEVICE_TABLE(of, sun4i_frontend_of_table);
static struct platform_driver sun4i_frontend_driver = {
.probe = sun4i_frontend_probe,
- .remove_new = sun4i_frontend_remove,
+ .remove = sun4i_frontend_remove,
.driver = {
.name = "sun4i-frontend",
.of_match_table = sun4i_frontend_of_table,
diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
index b3649449de30..453f19f16ab7 100644
--- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
+++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c
@@ -741,7 +741,7 @@ MODULE_DEVICE_TABLE(of, sun4i_hdmi_of_table);
static struct platform_driver sun4i_hdmi_driver = {
.probe = sun4i_hdmi_probe,
- .remove_new = sun4i_hdmi_remove,
+ .remove = sun4i_hdmi_remove,
.driver = {
.name = "sun4i-hdmi",
.of_match_table = sun4i_hdmi_of_table,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c b/drivers/gpu/drm/sun4i/sun4i_tcon.c
index a1a2c845ade0..960e83c8291d 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
@@ -1568,7 +1568,7 @@ EXPORT_SYMBOL(sun4i_tcon_of_table);
static struct platform_driver sun4i_tcon_platform_driver = {
.probe = sun4i_tcon_probe,
- .remove_new = sun4i_tcon_remove,
+ .remove = sun4i_tcon_remove,
.driver = {
.name = "sun4i-tcon",
.of_match_table = sun4i_tcon_of_table,
diff --git a/drivers/gpu/drm/sun4i/sun4i_tv.c b/drivers/gpu/drm/sun4i/sun4i_tv.c
index ec65d9d59de7..cce4e38789b9 100644
--- a/drivers/gpu/drm/sun4i/sun4i_tv.c
+++ b/drivers/gpu/drm/sun4i/sun4i_tv.c
@@ -559,7 +559,7 @@ MODULE_DEVICE_TABLE(of, sun4i_tv_of_table);
static struct platform_driver sun4i_tv_platform_driver = {
.probe = sun4i_tv_probe,
- .remove_new = sun4i_tv_remove,
+ .remove = sun4i_tv_remove,
.driver = {
.name = "sun4i-tve",
.of_match_table = sun4i_tv_of_table,
diff --git a/drivers/gpu/drm/sun4i/sun6i_drc.c b/drivers/gpu/drm/sun4i/sun6i_drc.c
index 0d342f43fa93..310c7e0daede 100644
--- a/drivers/gpu/drm/sun4i/sun6i_drc.c
+++ b/drivers/gpu/drm/sun4i/sun6i_drc.c
@@ -112,7 +112,7 @@ MODULE_DEVICE_TABLE(of, sun6i_drc_of_table);
static struct platform_driver sun6i_drc_platform_driver = {
.probe = sun6i_drc_probe,
- .remove_new = sun6i_drc_remove,
+ .remove = sun6i_drc_remove,
.driver = {
.name = "sun6i-drc",
.of_match_table = sun6i_drc_of_table,
diff --git a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
index 4abf4f102007..c35b70d83e53 100644
--- a/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
+++ b/drivers/gpu/drm/sun4i/sun6i_mipi_dsi.c
@@ -1244,7 +1244,7 @@ MODULE_DEVICE_TABLE(of, sun6i_dsi_of_table);
static struct platform_driver sun6i_dsi_platform_driver = {
.probe = sun6i_dsi_probe,
- .remove_new = sun6i_dsi_remove,
+ .remove = sun6i_dsi_remove,
.driver = {
.name = "sun6i-mipi-dsi",
.of_match_table = sun6i_dsi_of_table,
diff --git a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
index 4727dfaa8fb9..96532709c2a7 100644
--- a/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
+++ b/drivers/gpu/drm/sun4i/sun8i_dw_hdmi.c
@@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(of, sun8i_dw_hdmi_dt_ids);
static struct platform_driver sun8i_dw_hdmi_pltfm_driver = {
.probe = sun8i_dw_hdmi_probe,
- .remove_new = sun8i_dw_hdmi_remove,
+ .remove = sun8i_dw_hdmi_remove,
.driver = {
.name = "sun8i-dw-hdmi",
.of_match_table = sun8i_dw_hdmi_dt_ids,
diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c b/drivers/gpu/drm/sun4i/sun8i_mixer.c
index bd0fe2c6624e..8b41d33baa30 100644
--- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
+++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
@@ -775,7 +775,7 @@ MODULE_DEVICE_TABLE(of, sun8i_mixer_of_table);
static struct platform_driver sun8i_mixer_platform_driver = {
.probe = sun8i_mixer_probe,
- .remove_new = sun8i_mixer_remove,
+ .remove = sun8i_mixer_remove,
.driver = {
.name = "sun8i-mixer",
.of_match_table = sun8i_mixer_of_table,
diff --git a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
index a1ca3916f42b..8adda578c51b 100644
--- a/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
+++ b/drivers/gpu/drm/sun4i/sun8i_tcon_top.c
@@ -299,7 +299,7 @@ EXPORT_SYMBOL(sun8i_tcon_top_of_table);
static struct platform_driver sun8i_tcon_top_platform_driver = {
.probe = sun8i_tcon_top_probe,
- .remove_new = sun8i_tcon_top_remove,
+ .remove = sun8i_tcon_top_remove,
.driver = {
.name = "sun8i-tcon-top",
.of_match_table = sun8i_tcon_top_of_table,
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index be61c9d1a4f0..430b2eededb2 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -3286,5 +3286,5 @@ struct platform_driver tegra_dc_driver = {
.of_match_table = tegra_dc_of_match,
},
.probe = tegra_dc_probe,
- .remove_new = tegra_dc_remove,
+ .remove = tegra_dc_remove,
};
diff --git a/drivers/gpu/drm/tegra/dpaux.c b/drivers/gpu/drm/tegra/dpaux.c
index ae12d001a04b..2cd8dcb959c0 100644
--- a/drivers/gpu/drm/tegra/dpaux.c
+++ b/drivers/gpu/drm/tegra/dpaux.c
@@ -697,7 +697,7 @@ struct platform_driver tegra_dpaux_driver = {
.pm = pm_ptr(&tegra_dpaux_pm_ops),
},
.probe = tegra_dpaux_probe,
- .remove_new = tegra_dpaux_remove,
+ .remove = tegra_dpaux_remove,
};
struct drm_dp_aux *drm_dp_aux_find_by_of_node(struct device_node *np)
diff --git a/drivers/gpu/drm/tegra/dsi.c b/drivers/gpu/drm/tegra/dsi.c
index db606e151afc..4a8cd9ed0a94 100644
--- a/drivers/gpu/drm/tegra/dsi.c
+++ b/drivers/gpu/drm/tegra/dsi.c
@@ -1713,5 +1713,5 @@ struct platform_driver tegra_dsi_driver = {
.of_match_table = tegra_dsi_of_match,
},
.probe = tegra_dsi_probe,
- .remove_new = tegra_dsi_remove,
+ .remove = tegra_dsi_remove,
};
diff --git a/drivers/gpu/drm/tegra/gem.c b/drivers/gpu/drm/tegra/gem.c
index d275404ad0e9..ace3e5a805cf 100644
--- a/drivers/gpu/drm/tegra/gem.c
+++ b/drivers/gpu/drm/tegra/gem.c
@@ -22,7 +22,7 @@
#include "drm.h"
#include "gem.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
static unsigned int sg_dma_count_chunks(struct scatterlist *sgl, unsigned int nents)
{
diff --git a/drivers/gpu/drm/tegra/gr2d.c b/drivers/gpu/drm/tegra/gr2d.c
index a160d01f26e1..21f4dd0fa6af 100644
--- a/drivers/gpu/drm/tegra/gr2d.c
+++ b/drivers/gpu/drm/tegra/gr2d.c
@@ -394,5 +394,5 @@ struct platform_driver tegra_gr2d_driver = {
.pm = &tegra_gr2d_pm,
},
.probe = gr2d_probe,
- .remove_new = gr2d_remove,
+ .remove = gr2d_remove,
};
diff --git a/drivers/gpu/drm/tegra/gr3d.c b/drivers/gpu/drm/tegra/gr3d.c
index caee824832b3..42e9656ab80c 100644
--- a/drivers/gpu/drm/tegra/gr3d.c
+++ b/drivers/gpu/drm/tegra/gr3d.c
@@ -605,5 +605,5 @@ struct platform_driver tegra_gr3d_driver = {
.pm = &tegra_gr3d_pm,
},
.probe = gr3d_probe,
- .remove_new = gr3d_remove,
+ .remove = gr3d_remove,
};
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index 6bf2dae82ca0..e705f8590c13 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -1919,5 +1919,5 @@ struct platform_driver tegra_hdmi_driver = {
.of_match_table = tegra_hdmi_of_match,
},
.probe = tegra_hdmi_probe,
- .remove_new = tegra_hdmi_remove,
+ .remove = tegra_hdmi_remove,
};
diff --git a/drivers/gpu/drm/tegra/hub.c b/drivers/gpu/drm/tegra/hub.c
index e0c2019a591b..fa6140fc37fb 100644
--- a/drivers/gpu/drm/tegra/hub.c
+++ b/drivers/gpu/drm/tegra/hub.c
@@ -1218,5 +1218,5 @@ struct platform_driver tegra_display_hub_driver = {
.of_match_table = tegra_display_hub_of_match,
},
.probe = tegra_display_hub_probe,
- .remove_new = tegra_display_hub_remove,
+ .remove = tegra_display_hub_remove,
};
diff --git a/drivers/gpu/drm/tegra/nvdec.c b/drivers/gpu/drm/tegra/nvdec.c
index 4860790666af..2d9a0a3f6c38 100644
--- a/drivers/gpu/drm/tegra/nvdec.c
+++ b/drivers/gpu/drm/tegra/nvdec.c
@@ -566,7 +566,7 @@ struct platform_driver tegra_nvdec_driver = {
.pm = &nvdec_pm_ops
},
.probe = nvdec_probe,
- .remove_new = nvdec_remove,
+ .remove = nvdec_remove,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_210_SOC)
diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c
index bad3b8fcc726..802d2db7007a 100644
--- a/drivers/gpu/drm/tegra/sor.c
+++ b/drivers/gpu/drm/tegra/sor.c
@@ -4040,5 +4040,5 @@ struct platform_driver tegra_sor_driver = {
.pm = &tegra_sor_pm_ops,
},
.probe = tegra_sor_probe,
- .remove_new = tegra_sor_remove,
+ .remove = tegra_sor_remove,
};
diff --git a/drivers/gpu/drm/tegra/vic.c b/drivers/gpu/drm/tegra/vic.c
index 73c356f1c901..332c9b563d3f 100644
--- a/drivers/gpu/drm/tegra/vic.c
+++ b/drivers/gpu/drm/tegra/vic.c
@@ -553,7 +553,7 @@ struct platform_driver tegra_vic_driver = {
.pm = &vic_pm_ops
},
.probe = vic_probe,
- .remove_new = vic_remove,
+ .remove = vic_remove,
};
#if IS_ENABLED(CONFIG_ARCH_TEGRA_124_SOC)
diff --git a/drivers/gpu/drm/tidss/tidss_drv.c b/drivers/gpu/drm/tidss/tidss_drv.c
index 2428b9aaa003..7c8fd6407d82 100644
--- a/drivers/gpu/drm/tidss/tidss_drv.c
+++ b/drivers/gpu/drm/tidss/tidss_drv.c
@@ -252,7 +252,7 @@ MODULE_DEVICE_TABLE(of, tidss_of_table);
static struct platform_driver tidss_platform_driver = {
.probe = tidss_probe,
- .remove_new = tidss_remove,
+ .remove = tidss_remove,
.shutdown = tidss_shutdown,
.driver = {
.name = "tidss",
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 8c9f3705aa6c..6f0df8d6b90c 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -590,7 +590,7 @@ MODULE_DEVICE_TABLE(of, tilcdc_of_match);
static struct platform_driver tilcdc_platform_driver = {
.probe = tilcdc_pdev_probe,
- .remove_new = tilcdc_pdev_remove,
+ .remove = tilcdc_pdev_remove,
.shutdown = tilcdc_pdev_shutdown,
.driver = {
.name = "tilcdc",
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
index 5f2d1b6f9ee9..262f290d85d9 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c
@@ -390,7 +390,7 @@ static const struct of_device_id panel_of_match[] = {
static struct platform_driver panel_driver = {
.probe = panel_probe,
- .remove_new = panel_remove,
+ .remove = panel_remove,
.driver = {
.name = "tilcdc-panel",
.of_match_table = panel_of_match,
diff --git a/drivers/gpu/drm/tiny/arcpgu.c b/drivers/gpu/drm/tiny/arcpgu.c
index 81abedec435d..0cc68042a6d6 100644
--- a/drivers/gpu/drm/tiny/arcpgu.c
+++ b/drivers/gpu/drm/tiny/arcpgu.c
@@ -423,7 +423,7 @@ MODULE_DEVICE_TABLE(of, arcpgu_of_table);
static struct platform_driver arcpgu_platform_driver = {
.probe = arcpgu_probe,
- .remove_new = arcpgu_remove,
+ .remove = arcpgu_remove,
.driver = {
.name = "arcpgu",
.of_match_table = arcpgu_of_table,
diff --git a/drivers/gpu/drm/tiny/ofdrm.c b/drivers/gpu/drm/tiny/ofdrm.c
index 220c1244b3c0..9898eab5e9e2 100644
--- a/drivers/gpu/drm/tiny/ofdrm.c
+++ b/drivers/gpu/drm/tiny/ofdrm.c
@@ -1398,7 +1398,7 @@ static struct platform_driver ofdrm_platform_driver = {
.of_match_table = ofdrm_of_match_display,
},
.probe = ofdrm_probe,
- .remove_new = ofdrm_remove,
+ .remove = ofdrm_remove,
};
module_platform_driver(ofdrm_platform_driver);
diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c
index 3182d32f1b8f..4d4f05dee244 100644
--- a/drivers/gpu/drm/tiny/simpledrm.c
+++ b/drivers/gpu/drm/tiny/simpledrm.c
@@ -1066,7 +1066,7 @@ static struct platform_driver simpledrm_platform_driver = {
.of_match_table = simpledrm_of_match_table,
},
.probe = simpledrm_probe,
- .remove_new = simpledrm_remove,
+ .remove = simpledrm_remove,
};
module_platform_driver(simpledrm_platform_driver);
diff --git a/drivers/gpu/drm/tve200/tve200_drv.c b/drivers/gpu/drm/tve200/tve200_drv.c
index b30340a2141d..c341aee37dd9 100644
--- a/drivers/gpu/drm/tve200/tve200_drv.c
+++ b/drivers/gpu/drm/tve200/tve200_drv.c
@@ -267,7 +267,7 @@ static struct platform_driver tve200_driver = {
.of_match_table = tve200_of_match,
},
.probe = tve200_probe,
- .remove_new = tve200_remove,
+ .remove = tve200_remove,
.shutdown = tve200_shutdown,
};
drm_module_platform_driver(tve200_driver);
diff --git a/drivers/gpu/drm/v3d/v3d_drv.c b/drivers/gpu/drm/v3d/v3d_drv.c
index fb35c5c3f1a7..bee51c942a56 100644
--- a/drivers/gpu/drm/v3d/v3d_drv.c
+++ b/drivers/gpu/drm/v3d/v3d_drv.c
@@ -391,7 +391,7 @@ static void v3d_platform_drm_remove(struct platform_device *pdev)
static struct platform_driver v3d_platform_driver = {
.probe = v3d_platform_drm_probe,
- .remove_new = v3d_platform_drm_remove,
+ .remove = v3d_platform_drm_remove,
.driver = {
.name = "v3d",
.of_match_table = v3d_of_match,
diff --git a/drivers/gpu/drm/v3d/v3d_perfmon.c b/drivers/gpu/drm/v3d/v3d_perfmon.c
index 156be13ab2ef..924814cab46a 100644
--- a/drivers/gpu/drm/v3d/v3d_perfmon.c
+++ b/drivers/gpu/drm/v3d/v3d_perfmon.c
@@ -254,9 +254,9 @@ void v3d_perfmon_start(struct v3d_dev *v3d, struct v3d_perfmon *perfmon)
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_SRC_X(source), channel);
}
+ V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);
V3D_CORE_WRITE(0, V3D_V4_PCTR_0_CLR, mask);
V3D_CORE_WRITE(0, V3D_PCTR_0_OVERFLOW, mask);
- V3D_CORE_WRITE(0, V3D_V4_PCTR_0_EN, mask);
v3d->active_perfmon = perfmon;
}
diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c
index 575900ee67a5..ee82a959d279 100644
--- a/drivers/gpu/drm/vc4/vc4_crtc.c
+++ b/drivers/gpu/drm/vc4/vc4_crtc.c
@@ -1465,7 +1465,7 @@ static void vc4_crtc_dev_remove(struct platform_device *pdev)
struct platform_driver vc4_crtc_driver = {
.probe = vc4_crtc_dev_probe,
- .remove_new = vc4_crtc_dev_remove,
+ .remove = vc4_crtc_dev_remove,
.driver = {
.name = "vc4_crtc",
.of_match_table = vc4_crtc_dt_match,
diff --git a/drivers/gpu/drm/vc4/vc4_dpi.c b/drivers/gpu/drm/vc4/vc4_dpi.c
index a382dc4654bd..960550c166d9 100644
--- a/drivers/gpu/drm/vc4/vc4_dpi.c
+++ b/drivers/gpu/drm/vc4/vc4_dpi.c
@@ -395,7 +395,7 @@ static void vc4_dpi_dev_remove(struct platform_device *pdev)
struct platform_driver vc4_dpi_driver = {
.probe = vc4_dpi_dev_probe,
- .remove_new = vc4_dpi_dev_remove,
+ .remove = vc4_dpi_dev_remove,
.driver = {
.name = "vc4_dpi",
.of_match_table = vc4_dpi_dt_match,
diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
index d47e5967592f..2c60d37275b0 100644
--- a/drivers/gpu/drm/vc4/vc4_drv.c
+++ b/drivers/gpu/drm/vc4/vc4_drv.c
@@ -471,7 +471,7 @@ MODULE_DEVICE_TABLE(of, vc4_of_match);
static struct platform_driver vc4_platform_driver = {
.probe = vc4_platform_drm_probe,
- .remove_new = vc4_platform_drm_remove,
+ .remove = vc4_platform_drm_remove,
.shutdown = vc4_platform_drm_shutdown,
.driver = {
.name = "vc4-drm",
diff --git a/drivers/gpu/drm/vc4/vc4_dsi.c b/drivers/gpu/drm/vc4/vc4_dsi.c
index f5ccc1bf7a63..5eb293bdb363 100644
--- a/drivers/gpu/drm/vc4/vc4_dsi.c
+++ b/drivers/gpu/drm/vc4/vc4_dsi.c
@@ -1841,7 +1841,7 @@ static void vc4_dsi_dev_remove(struct platform_device *pdev)
struct platform_driver vc4_dsi_driver = {
.probe = vc4_dsi_dev_probe,
- .remove_new = vc4_dsi_dev_remove,
+ .remove = vc4_dsi_dev_remove,
.driver = {
.name = "vc4_dsi",
.of_match_table = vc4_dsi_dt_match,
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c
index 62b82b1eeb36..e3818c48c9b8 100644
--- a/drivers/gpu/drm/vc4/vc4_hdmi.c
+++ b/drivers/gpu/drm/vc4/vc4_hdmi.c
@@ -3422,7 +3422,7 @@ static const struct dev_pm_ops vc4_hdmi_pm_ops = {
struct platform_driver vc4_hdmi_driver = {
.probe = vc4_hdmi_dev_probe,
- .remove_new = vc4_hdmi_dev_remove,
+ .remove = vc4_hdmi_dev_remove,
.driver = {
.name = "vc4_hdmi",
.of_match_table = vc4_hdmi_dt_match,
diff --git a/drivers/gpu/drm/vc4/vc4_hvs.c b/drivers/gpu/drm/vc4/vc4_hvs.c
index 1edf6e3fa7e6..70623e6b91e9 100644
--- a/drivers/gpu/drm/vc4/vc4_hvs.c
+++ b/drivers/gpu/drm/vc4/vc4_hvs.c
@@ -1153,7 +1153,7 @@ static const struct of_device_id vc4_hvs_dt_match[] = {
struct platform_driver vc4_hvs_driver = {
.probe = vc4_hvs_dev_probe,
- .remove_new = vc4_hvs_dev_remove,
+ .remove = vc4_hvs_dev_remove,
.driver = {
.name = "vc4_hvs",
.of_match_table = vc4_hvs_dt_match,
diff --git a/drivers/gpu/drm/vc4/vc4_txp.c b/drivers/gpu/drm/vc4/vc4_txp.c
index ffe1f7d1b911..3e38a1d2d55e 100644
--- a/drivers/gpu/drm/vc4/vc4_txp.c
+++ b/drivers/gpu/drm/vc4/vc4_txp.c
@@ -585,7 +585,7 @@ static const struct of_device_id vc4_txp_dt_match[] = {
struct platform_driver vc4_txp_driver = {
.probe = vc4_txp_probe,
- .remove_new = vc4_txp_remove,
+ .remove = vc4_txp_remove,
.driver = {
.name = "vc4_txp",
.of_match_table = vc4_txp_dt_match,
diff --git a/drivers/gpu/drm/vc4/vc4_v3d.c b/drivers/gpu/drm/vc4/vc4_v3d.c
index 2423826c89eb..bb09df5000bd 100644
--- a/drivers/gpu/drm/vc4/vc4_v3d.c
+++ b/drivers/gpu/drm/vc4/vc4_v3d.c
@@ -534,7 +534,7 @@ const struct of_device_id vc4_v3d_dt_match[] = {
struct platform_driver vc4_v3d_driver = {
.probe = vc4_v3d_dev_probe,
- .remove_new = vc4_v3d_dev_remove,
+ .remove = vc4_v3d_dev_remove,
.driver = {
.name = "vc4_v3d",
.of_match_table = vc4_v3d_dt_match,
diff --git a/drivers/gpu/drm/vc4/vc4_vec.c b/drivers/gpu/drm/vc4/vc4_vec.c
index eb64e881051e..06d702e879b0 100644
--- a/drivers/gpu/drm/vc4/vc4_vec.c
+++ b/drivers/gpu/drm/vc4/vc4_vec.c
@@ -848,7 +848,7 @@ static void vc4_vec_dev_remove(struct platform_device *pdev)
struct platform_driver vc4_vec_driver = {
.probe = vc4_vec_dev_probe,
- .remove_new = vc4_vec_dev_remove,
+ .remove = vc4_vec_dev_remove,
.driver = {
.name = "vc4_vec",
.of_match_table = vc4_vec_dt_match,
diff --git a/drivers/gpu/drm/vmwgfx/ttm_object.c b/drivers/gpu/drm/vmwgfx/ttm_object.c
index a17e62867f3b..36d46b79562a 100644
--- a/drivers/gpu/drm/vmwgfx/ttm_object.c
+++ b/drivers/gpu/drm/vmwgfx/ttm_object.c
@@ -54,7 +54,7 @@
#include <linux/module.h>
#include <linux/hashtable.h>
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
#define VMW_TTM_OBJECT_REF_HT_ORDER 10
diff --git a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c
index 5f14737c8210..0d36ab864ec0 100644
--- a/drivers/gpu/drm/xe/tests/xe_live_test_mod.c
+++ b/drivers/gpu/drm/xe/tests/xe_live_test_mod.c
@@ -18,4 +18,4 @@ kunit_test_suite(xe_mocs_test_suite);
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("xe live kunit tests");
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
diff --git a/drivers/gpu/drm/xe/tests/xe_migrate.c b/drivers/gpu/drm/xe/tests/xe_migrate.c
index 1a192a2a941b..3bbdb362d6f0 100644
--- a/drivers/gpu/drm/xe/tests/xe_migrate.c
+++ b/drivers/gpu/drm/xe/tests/xe_migrate.c
@@ -224,8 +224,8 @@ static void xe_migrate_sanity_test(struct xe_migrate *m, struct kunit *test)
XE_BO_FLAG_VRAM_IF_DGFX(tile) |
XE_BO_FLAG_PINNED);
if (IS_ERR(tiny)) {
- KUNIT_FAIL(test, "Failed to allocate fake pt: %li\n",
- PTR_ERR(pt));
+ KUNIT_FAIL(test, "Failed to allocate tiny fake pt: %li\n",
+ PTR_ERR(tiny));
goto free_pt;
}
diff --git a/drivers/gpu/drm/xe/tests/xe_test_mod.c b/drivers/gpu/drm/xe/tests/xe_test_mod.c
index 875f3e6f965e..93081bcf2ab0 100644
--- a/drivers/gpu/drm/xe/tests/xe_test_mod.c
+++ b/drivers/gpu/drm/xe/tests/xe_test_mod.c
@@ -7,4 +7,4 @@
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("xe kunit tests");
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
diff --git a/drivers/gpu/drm/xe/xe_bo.c b/drivers/gpu/drm/xe/xe_bo.c
index ae6b337cdc54..f61a8ef38094 100644
--- a/drivers/gpu/drm/xe/xe_bo.c
+++ b/drivers/gpu/drm/xe/xe_bo.c
@@ -724,7 +724,7 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict,
new_mem->mem_type == XE_PL_SYSTEM) {
long timeout = dma_resv_wait_timeout(ttm_bo->base.resv,
DMA_RESV_USAGE_BOOKKEEP,
- true,
+ false,
MAX_SCHEDULE_TIMEOUT);
if (timeout < 0) {
ret = timeout;
@@ -848,8 +848,16 @@ static int xe_bo_move(struct ttm_buffer_object *ttm_bo, bool evict,
out:
if ((!ttm_bo->resource || ttm_bo->resource->mem_type == XE_PL_SYSTEM) &&
- ttm_bo->ttm)
+ ttm_bo->ttm) {
+ long timeout = dma_resv_wait_timeout(ttm_bo->base.resv,
+ DMA_RESV_USAGE_KERNEL,
+ false,
+ MAX_SCHEDULE_TIMEOUT);
+ if (timeout < 0)
+ ret = timeout;
+
xe_tt_unmap_sg(ttm_bo->ttm);
+ }
return ret;
}
diff --git a/drivers/gpu/drm/xe/xe_devcoredump.c b/drivers/gpu/drm/xe/xe_devcoredump.c
index d2679c5d976b..21a50d539426 100644
--- a/drivers/gpu/drm/xe/xe_devcoredump.c
+++ b/drivers/gpu/drm/xe/xe_devcoredump.c
@@ -23,6 +23,7 @@
#include "xe_guc_submit.h"
#include "xe_hw_engine.h"
#include "xe_module.h"
+#include "xe_pm.h"
#include "xe_sched_job.h"
#include "xe_vm.h"
@@ -108,7 +109,11 @@ static ssize_t __xe_devcoredump_read(char *buffer, size_t count,
drm_puts(&p, "\n**** GuC CT ****\n");
xe_guc_ct_snapshot_print(ss->guc.ct, &p);
- drm_puts(&p, "\n**** Contexts ****\n");
+ /*
+ * Don't add a new section header here because the mesa debug decoder
+ * tool expects the context information to be in the 'GuC CT' section.
+ */
+ /* drm_puts(&p, "\n**** Contexts ****\n"); */
xe_guc_exec_queue_snapshot_print(ss->ge, &p);
drm_puts(&p, "\n**** Job ****\n");
@@ -154,31 +159,6 @@ static void xe_devcoredump_snapshot_free(struct xe_devcoredump_snapshot *ss)
ss->vm = NULL;
}
-static void xe_devcoredump_deferred_snap_work(struct work_struct *work)
-{
- struct xe_devcoredump_snapshot *ss = container_of(work, typeof(*ss), work);
- struct xe_devcoredump *coredump = container_of(ss, typeof(*coredump), snapshot);
- unsigned int fw_ref;
-
- /* keep going if fw fails as we still want to save the memory and SW data */
- fw_ref = xe_force_wake_get(gt_to_fw(ss->gt), XE_FORCEWAKE_ALL);
- if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
- xe_gt_info(ss->gt, "failed to get forcewake for coredump capture\n");
- xe_vm_snapshot_capture_delayed(ss->vm);
- xe_guc_exec_queue_snapshot_capture_delayed(ss->ge);
- xe_force_wake_put(gt_to_fw(ss->gt), fw_ref);
-
- /* Calculate devcoredump size */
- ss->read.size = __xe_devcoredump_read(NULL, INT_MAX, coredump);
-
- ss->read.buffer = kvmalloc(ss->read.size, GFP_USER);
- if (!ss->read.buffer)
- return;
-
- __xe_devcoredump_read(ss->read.buffer, ss->read.size, coredump);
- xe_devcoredump_snapshot_free(ss);
-}
-
static ssize_t xe_devcoredump_read(char *buffer, loff_t offset,
size_t count, void *data, size_t datalen)
{
@@ -228,6 +208,45 @@ static void xe_devcoredump_free(void *data)
"Xe device coredump has been deleted.\n");
}
+static void xe_devcoredump_deferred_snap_work(struct work_struct *work)
+{
+ struct xe_devcoredump_snapshot *ss = container_of(work, typeof(*ss), work);
+ struct xe_devcoredump *coredump = container_of(ss, typeof(*coredump), snapshot);
+ struct xe_device *xe = coredump_to_xe(coredump);
+ unsigned int fw_ref;
+
+ /*
+ * NB: Despite passing a GFP_ flags parameter here, more allocations are done
+ * internally using GFP_KERNEL expliictly. Hence this call must be in the worker
+ * thread and not in the initial capture call.
+ */
+ dev_coredumpm_timeout(gt_to_xe(ss->gt)->drm.dev, THIS_MODULE, coredump, 0, GFP_KERNEL,
+ xe_devcoredump_read, xe_devcoredump_free,
+ XE_COREDUMP_TIMEOUT_JIFFIES);
+
+ xe_pm_runtime_get(xe);
+
+ /* keep going if fw fails as we still want to save the memory and SW data */
+ fw_ref = xe_force_wake_get(gt_to_fw(ss->gt), XE_FORCEWAKE_ALL);
+ if (!xe_force_wake_ref_has_domain(fw_ref, XE_FORCEWAKE_ALL))
+ xe_gt_info(ss->gt, "failed to get forcewake for coredump capture\n");
+ xe_vm_snapshot_capture_delayed(ss->vm);
+ xe_guc_exec_queue_snapshot_capture_delayed(ss->ge);
+ xe_force_wake_put(gt_to_fw(ss->gt), fw_ref);
+
+ xe_pm_runtime_put(xe);
+
+ /* Calculate devcoredump size */
+ ss->read.size = __xe_devcoredump_read(NULL, INT_MAX, coredump);
+
+ ss->read.buffer = kvmalloc(ss->read.size, GFP_USER);
+ if (!ss->read.buffer)
+ return;
+
+ __xe_devcoredump_read(ss->read.buffer, ss->read.size, coredump);
+ xe_devcoredump_snapshot_free(ss);
+}
+
static void devcoredump_snapshot(struct xe_devcoredump *coredump,
struct xe_sched_job *job)
{
@@ -304,10 +323,6 @@ void xe_devcoredump(struct xe_sched_job *job)
drm_info(&xe->drm, "Xe device coredump has been created\n");
drm_info(&xe->drm, "Check your /sys/class/drm/card%d/device/devcoredump/data\n",
xe->drm.primary->index);
-
- dev_coredumpm_timeout(xe->drm.dev, THIS_MODULE, coredump, 0, GFP_KERNEL,
- xe_devcoredump_read, xe_devcoredump_free,
- XE_COREDUMP_TIMEOUT_JIFFIES);
}
static void xe_driver_devcoredump_fini(void *arg)
@@ -352,6 +367,15 @@ void xe_print_blob_ascii85(struct drm_printer *p, const char *prefix,
char buff[ASCII85_BUFSZ], *line_buff;
size_t line_pos = 0;
+ /*
+ * Splitting blobs across multiple lines is not compatible with the mesa
+ * debug decoder tool. Note that even dropping the explicit '\n' below
+ * doesn't help because the GuC log is so big some underlying implementation
+ * still splits the lines at 512K characters. So just bail completely for
+ * the moment.
+ */
+ return;
+
#define DMESG_MAX_LINE_LEN 800
#define MIN_SPACE (ASCII85_BUFSZ + 2) /* 85 + "\n\0" */
diff --git a/drivers/gpu/drm/xe/xe_device.c b/drivers/gpu/drm/xe/xe_device.c
index 0e2dd691bdae..06d6db8b50f9 100644
--- a/drivers/gpu/drm/xe/xe_device.c
+++ b/drivers/gpu/drm/xe/xe_device.c
@@ -350,7 +350,8 @@ struct xe_device *xe_device_create(struct pci_dev *pdev,
INIT_LIST_HEAD(&xe->pinned.external_vram);
INIT_LIST_HEAD(&xe->pinned.evicted);
- xe->preempt_fence_wq = alloc_ordered_workqueue("xe-preempt-fence-wq", 0);
+ xe->preempt_fence_wq = alloc_ordered_workqueue("xe-preempt-fence-wq",
+ WQ_MEM_RECLAIM);
xe->ordered_wq = alloc_ordered_workqueue("xe-ordered-wq", 0);
xe->unordered_wq = alloc_workqueue("xe-unordered-wq", 0, 0);
xe->destroy_wq = alloc_workqueue("xe-destroy-wq", 0, 0);
diff --git a/drivers/gpu/drm/xe/xe_dma_buf.c b/drivers/gpu/drm/xe/xe_dma_buf.c
index 68f309f5e981..c5b95470fa32 100644
--- a/drivers/gpu/drm/xe/xe_dma_buf.c
+++ b/drivers/gpu/drm/xe/xe_dma_buf.c
@@ -20,7 +20,7 @@
#include "xe_ttm_vram_mgr.h"
#include "xe_vm.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
static int xe_dma_buf_attach(struct dma_buf *dmabuf,
struct dma_buf_attachment *attach)
diff --git a/drivers/gpu/drm/xe/xe_exec_queue.c b/drivers/gpu/drm/xe/xe_exec_queue.c
index fd0f3b3c9101..268cd3123be9 100644
--- a/drivers/gpu/drm/xe/xe_exec_queue.c
+++ b/drivers/gpu/drm/xe/xe_exec_queue.c
@@ -8,6 +8,7 @@
#include <linux/nospec.h>
#include <drm/drm_device.h>
+#include <drm/drm_drv.h>
#include <drm/drm_file.h>
#include <uapi/drm/xe_drm.h>
@@ -762,9 +763,11 @@ bool xe_exec_queue_is_idle(struct xe_exec_queue *q)
*/
void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q)
{
+ struct xe_device *xe = gt_to_xe(q->gt);
struct xe_file *xef;
struct xe_lrc *lrc;
u32 old_ts, new_ts;
+ int idx;
/*
* Jobs that are run during driver load may use an exec_queue, but are
@@ -774,6 +777,10 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q)
if (!q->vm || !q->vm->xef)
return;
+ /* Synchronize with unbind while holding the xe file open */
+ if (!drm_dev_enter(&xe->drm, &idx))
+ return;
+
xef = q->vm->xef;
/*
@@ -787,6 +794,8 @@ void xe_exec_queue_update_run_ticks(struct xe_exec_queue *q)
lrc = q->lrc[0];
new_ts = xe_lrc_update_timestamp(lrc, &old_ts);
xef->run_ticks[q->class] += (new_ts - old_ts) * q->width;
+
+ drm_dev_exit(idx);
}
/**
diff --git a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
index 192643d63d22..ca49860168f6 100644
--- a/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
+++ b/drivers/gpu/drm/xe/xe_gt_sriov_pf_config.c
@@ -2046,7 +2046,7 @@ static int pf_validate_vf_config(struct xe_gt *gt, unsigned int vfid)
valid_any = valid_any || (valid_ggtt && is_primary);
if (IS_DGFX(xe)) {
- bool valid_lmem = pf_get_vf_config_ggtt(primary_gt, vfid);
+ bool valid_lmem = pf_get_vf_config_lmem(primary_gt, vfid);
valid_any = valid_any || (valid_lmem && is_primary);
valid_all = valid_all && valid_lmem;
diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
index 3cb228c773cd..6146d1776bda 100644
--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
+++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.c
@@ -65,6 +65,14 @@ invalidation_fence_signal(struct xe_device *xe, struct xe_gt_tlb_invalidation_fe
__invalidation_fence_signal(xe, fence);
}
+void xe_gt_tlb_invalidation_fence_signal(struct xe_gt_tlb_invalidation_fence *fence)
+{
+ if (WARN_ON_ONCE(!fence->gt))
+ return;
+
+ __invalidation_fence_signal(gt_to_xe(fence->gt), fence);
+}
+
static void xe_gt_tlb_fence_timeout(struct work_struct *work)
{
struct xe_gt *gt = container_of(work, struct xe_gt,
diff --git a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
index f430d5797af7..00b1c6c01e8d 100644
--- a/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
+++ b/drivers/gpu/drm/xe/xe_gt_tlb_invalidation.h
@@ -28,6 +28,7 @@ int xe_guc_tlb_invalidation_done_handler(struct xe_guc *guc, u32 *msg, u32 len);
void xe_gt_tlb_invalidation_fence_init(struct xe_gt *gt,
struct xe_gt_tlb_invalidation_fence *fence,
bool stack);
+void xe_gt_tlb_invalidation_fence_signal(struct xe_gt_tlb_invalidation_fence *fence);
static inline void
xe_gt_tlb_invalidation_fence_wait(struct xe_gt_tlb_invalidation_fence *fence)
diff --git a/drivers/gpu/drm/xe/xe_guc_capture.c b/drivers/gpu/drm/xe/xe_guc_capture.c
index cc72446a5de1..d63912d28246 100644
--- a/drivers/gpu/drm/xe/xe_guc_capture.c
+++ b/drivers/gpu/drm/xe/xe_guc_capture.c
@@ -102,6 +102,7 @@ struct __guc_capture_parsed_output {
* A 64 bit register define requires 2 consecutive entries,
* with low dword first and hi dword the second.
* 2. Register name: null for incompleted define
+ * 3. Incorrect order will trigger XE_WARN.
*/
#define COMMON_XELP_BASE_GLOBAL \
{ FORCEWAKE_GT, REG_32BIT, 0, 0, "FORCEWAKE_GT"}
@@ -1675,10 +1676,10 @@ snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_
struct xe_devcoredump *devcoredump = &xe->devcoredump;
struct xe_devcoredump_snapshot *devcore_snapshot = &devcoredump->snapshot;
struct gcap_reg_list_info *reginfo = NULL;
- u32 last_value, i;
- bool is_ext;
+ u32 i, last_value = 0;
+ bool is_ext, low32_ready = false;
- if (!list || list->num_regs == 0)
+ if (!list || !list->list || list->num_regs == 0)
return;
XE_WARN_ON(!devcore_snapshot->matched_node);
@@ -1701,29 +1702,75 @@ snapshot_print_by_list_order(struct xe_hw_engine_snapshot *snapshot, struct drm_
continue;
value = reg->value;
- if (reg_desc->data_type == REG_64BIT_LOW_DW) {
+ switch (reg_desc->data_type) {
+ case REG_64BIT_LOW_DW:
last_value = value;
+
+ /*
+ * A 64 bit register define requires 2 consecutive
+ * entries in register list, with low dword first
+ * and hi dword the second, like:
+ * { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
+ * { XXX_REG_HI(0), REG_64BIT_HI_DW, 0, 0, "XXX_REG"},
+ *
+ * Incorrect order will trigger XE_WARN.
+ *
+ * Possible double low here, for example:
+ * { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
+ * { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
+ */
+ XE_WARN_ON(low32_ready);
+ low32_ready = true;
/* Low 32 bit dword saved, continue for high 32 bit */
- continue;
- } else if (reg_desc->data_type == REG_64BIT_HI_DW) {
+ break;
+
+ case REG_64BIT_HI_DW: {
u64 value_qw = ((u64)value << 32) | last_value;
+ /*
+ * Incorrect 64bit register order. Possible missing low.
+ * for example:
+ * { XXX_REG(0), REG_32BIT, 0, 0, NULL},
+ * { XXX_REG_HI(0), REG_64BIT_HI_DW, 0, 0, NULL},
+ */
+ XE_WARN_ON(!low32_ready);
+ low32_ready = false;
+
drm_printf(p, "\t%s: 0x%016llx\n", reg_desc->regname, value_qw);
- continue;
+ break;
}
- if (is_ext) {
- int dss, group, instance;
+ case REG_32BIT:
+ /*
+ * Incorrect 64bit register order. Possible missing high.
+ * for example:
+ * { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
+ * { XXX_REG(0), REG_32BIT, 0, 0, "XXX_REG"},
+ */
+ XE_WARN_ON(low32_ready);
+
+ if (is_ext) {
+ int dss, group, instance;
- group = FIELD_GET(GUC_REGSET_STEERING_GROUP, reg_desc->flags);
- instance = FIELD_GET(GUC_REGSET_STEERING_INSTANCE, reg_desc->flags);
- dss = xe_gt_mcr_steering_info_to_dss_id(gt, group, instance);
+ group = FIELD_GET(GUC_REGSET_STEERING_GROUP, reg_desc->flags);
+ instance = FIELD_GET(GUC_REGSET_STEERING_INSTANCE, reg_desc->flags);
+ dss = xe_gt_mcr_steering_info_to_dss_id(gt, group, instance);
- drm_printf(p, "\t%s[%u]: 0x%08x\n", reg_desc->regname, dss, value);
- } else {
- drm_printf(p, "\t%s: 0x%08x\n", reg_desc->regname, value);
+ drm_printf(p, "\t%s[%u]: 0x%08x\n", reg_desc->regname, dss, value);
+ } else {
+ drm_printf(p, "\t%s: 0x%08x\n", reg_desc->regname, value);
+ }
+ break;
}
}
+
+ /*
+ * Incorrect 64bit register order. Possible missing high.
+ * for example:
+ * { XXX_REG_LO(0), REG_64BIT_LOW_DW, 0, 0, NULL},
+ * } // <- Register list end
+ */
+ XE_WARN_ON(low32_ready);
}
/**
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 9a8564ea06b5..6f4a9812b4f4 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -767,17 +767,19 @@ static void disable_scheduling_deregister(struct xe_guc *guc,
struct xe_exec_queue *q)
{
MAKE_SCHED_CONTEXT_ACTION(q, DISABLE);
- struct xe_device *xe = guc_to_xe(guc);
int ret;
set_min_preemption_timeout(guc, q);
smp_rmb();
- ret = wait_event_timeout(guc->ct.wq, !exec_queue_pending_enable(q) ||
- xe_guc_read_stopped(guc), HZ * 5);
+ ret = wait_event_timeout(guc->ct.wq,
+ (!exec_queue_pending_enable(q) &&
+ !exec_queue_pending_disable(q)) ||
+ xe_guc_read_stopped(guc),
+ HZ * 5);
if (!ret) {
struct xe_gpu_scheduler *sched = &q->guc->sched;
- drm_warn(&xe->drm, "Pending enable failed to respond");
+ xe_gt_warn(q->gt, "Pending enable/disable failed to respond\n");
xe_sched_submission_start(sched);
xe_gt_reset_async(q->gt);
xe_sched_tdr_queue_imm(sched);
@@ -1099,7 +1101,8 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
* modifying state
*/
ret = wait_event_timeout(guc->ct.wq,
- !exec_queue_pending_enable(q) ||
+ (!exec_queue_pending_enable(q) &&
+ !exec_queue_pending_disable(q)) ||
xe_guc_read_stopped(guc), HZ * 5);
if (!ret || xe_guc_read_stopped(guc))
goto trigger_reset;
@@ -1328,8 +1331,8 @@ static void __guc_exec_queue_process_msg_suspend(struct xe_sched_msg *msg)
if (guc_exec_queue_allowed_to_change_state(q) && !exec_queue_suspended(q) &&
exec_queue_enabled(q)) {
- wait_event(guc->ct.wq, q->guc->resume_time != RESUME_PENDING ||
- xe_guc_read_stopped(guc));
+ wait_event(guc->ct.wq, (q->guc->resume_time != RESUME_PENDING ||
+ xe_guc_read_stopped(guc)) && !exec_queue_pending_disable(q));
if (!xe_guc_read_stopped(guc)) {
s64 since_resume_ms =
@@ -1866,16 +1869,29 @@ static void handle_sched_done(struct xe_guc *guc, struct xe_exec_queue *q,
xe_gt_assert(guc_to_gt(guc), runnable_state == 0);
xe_gt_assert(guc_to_gt(guc), exec_queue_pending_disable(q));
- clear_exec_queue_pending_disable(q);
if (q->guc->suspend_pending) {
suspend_fence_signal(q);
+ clear_exec_queue_pending_disable(q);
} else {
if (exec_queue_banned(q) || check_timeout) {
smp_wmb();
wake_up_all(&guc->ct.wq);
}
- if (!check_timeout)
+ if (!check_timeout && exec_queue_destroyed(q)) {
+ /*
+ * Make sure to clear the pending_disable only
+ * after sampling the destroyed state. We want
+ * to ensure we don't trigger the unregister too
+ * early with something intending to only
+ * disable scheduling. The caller doing the
+ * destroy must wait for an ongoing
+ * pending_disable before marking as destroyed.
+ */
+ clear_exec_queue_pending_disable(q);
deregister_exec_queue(guc, q);
+ } else {
+ clear_exec_queue_pending_disable(q);
+ }
}
}
}
diff --git a/drivers/gpu/drm/xe/xe_migrate.c b/drivers/gpu/drm/xe/xe_migrate.c
index cfd31ae49cc1..1b97d90aadda 100644
--- a/drivers/gpu/drm/xe/xe_migrate.c
+++ b/drivers/gpu/drm/xe/xe_migrate.c
@@ -209,7 +209,8 @@ static int xe_migrate_prepare_vm(struct xe_tile *tile, struct xe_migrate *m,
num_entries * XE_PAGE_SIZE,
ttm_bo_type_kernel,
XE_BO_FLAG_VRAM_IF_DGFX(tile) |
- XE_BO_FLAG_PINNED);
+ XE_BO_FLAG_PINNED |
+ XE_BO_FLAG_PAGETABLE);
if (IS_ERR(bo))
return PTR_ERR(bo);
@@ -1350,6 +1351,7 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
/* For sysmem PTE's, need to map them in our hole.. */
if (!IS_DGFX(xe)) {
+ u16 pat_index = xe->pat.idx[XE_CACHE_WB];
u32 ptes, ofs;
ppgtt_ofs = NUM_KERNEL_PDE - 1;
@@ -1409,7 +1411,7 @@ __xe_migrate_update_pgtables(struct xe_migrate *m,
pt_bo->update_index = current_update;
addr = vm->pt_ops->pte_encode_bo(pt_bo, 0,
- XE_CACHE_WB, 0);
+ pat_index, 0);
bb->cs[bb->len++] = lower_32_bits(addr);
bb->cs[bb->len++] = upper_32_bits(addr);
}
diff --git a/drivers/gpu/drm/xe/xe_oa.c b/drivers/gpu/drm/xe/xe_oa.c
index 8dd55798ab31..5cc0f6f9bc11 100644
--- a/drivers/gpu/drm/xe/xe_oa.c
+++ b/drivers/gpu/drm/xe/xe_oa.c
@@ -74,12 +74,6 @@ struct xe_oa_config {
struct rcu_head rcu;
};
-struct flex {
- struct xe_reg reg;
- u32 offset;
- u32 value;
-};
-
struct xe_oa_open_param {
struct xe_file *xef;
u32 oa_unit_id;
@@ -596,19 +590,38 @@ static __poll_t xe_oa_poll(struct file *file, poll_table *wait)
return ret;
}
+static void xe_oa_lock_vma(struct xe_exec_queue *q)
+{
+ if (q->vm) {
+ down_read(&q->vm->lock);
+ xe_vm_lock(q->vm, false);
+ }
+}
+
+static void xe_oa_unlock_vma(struct xe_exec_queue *q)
+{
+ if (q->vm) {
+ xe_vm_unlock(q->vm);
+ up_read(&q->vm->lock);
+ }
+}
+
static struct dma_fence *xe_oa_submit_bb(struct xe_oa_stream *stream, enum xe_oa_submit_deps deps,
struct xe_bb *bb)
{
+ struct xe_exec_queue *q = stream->exec_q ?: stream->k_exec_q;
struct xe_sched_job *job;
struct dma_fence *fence;
int err = 0;
- /* Kernel configuration is issued on stream->k_exec_q, not stream->exec_q */
- job = xe_bb_create_job(stream->k_exec_q, bb);
+ xe_oa_lock_vma(q);
+
+ job = xe_bb_create_job(q, bb);
if (IS_ERR(job)) {
err = PTR_ERR(job);
goto exit;
}
+ job->ggtt = true;
if (deps == XE_OA_SUBMIT_ADD_DEPS) {
for (int i = 0; i < stream->num_syncs && !err; i++)
@@ -623,10 +636,13 @@ static struct dma_fence *xe_oa_submit_bb(struct xe_oa_stream *stream, enum xe_oa
fence = dma_fence_get(&job->drm.s_fence->finished);
xe_sched_job_push(job);
+ xe_oa_unlock_vma(q);
+
return fence;
err_put_job:
xe_sched_job_put(job);
exit:
+ xe_oa_unlock_vma(q);
return ERR_PTR(err);
}
@@ -675,63 +691,19 @@ static void xe_oa_free_configs(struct xe_oa_stream *stream)
dma_fence_put(stream->last_fence);
}
-static void xe_oa_store_flex(struct xe_oa_stream *stream, struct xe_lrc *lrc,
- struct xe_bb *bb, const struct flex *flex, u32 count)
-{
- u32 offset = xe_bo_ggtt_addr(lrc->bo);
-
- do {
- bb->cs[bb->len++] = MI_STORE_DATA_IMM | MI_SDI_GGTT | MI_SDI_NUM_DW(1);
- bb->cs[bb->len++] = offset + flex->offset * sizeof(u32);
- bb->cs[bb->len++] = 0;
- bb->cs[bb->len++] = flex->value;
-
- } while (flex++, --count);
-}
-
-static int xe_oa_modify_ctx_image(struct xe_oa_stream *stream, struct xe_lrc *lrc,
- const struct flex *flex, u32 count)
-{
- struct dma_fence *fence;
- struct xe_bb *bb;
- int err;
-
- bb = xe_bb_new(stream->gt, 4 * count, false);
- if (IS_ERR(bb)) {
- err = PTR_ERR(bb);
- goto exit;
- }
-
- xe_oa_store_flex(stream, lrc, bb, flex, count);
-
- fence = xe_oa_submit_bb(stream, XE_OA_SUBMIT_NO_DEPS, bb);
- if (IS_ERR(fence)) {
- err = PTR_ERR(fence);
- goto free_bb;
- }
- xe_bb_free(bb, fence);
- dma_fence_put(fence);
-
- return 0;
-free_bb:
- xe_bb_free(bb, NULL);
-exit:
- return err;
-}
-
-static int xe_oa_load_with_lri(struct xe_oa_stream *stream, struct xe_oa_reg *reg_lri)
+static int xe_oa_load_with_lri(struct xe_oa_stream *stream, struct xe_oa_reg *reg_lri, u32 count)
{
struct dma_fence *fence;
struct xe_bb *bb;
int err;
- bb = xe_bb_new(stream->gt, 3, false);
+ bb = xe_bb_new(stream->gt, 2 * count + 1, false);
if (IS_ERR(bb)) {
err = PTR_ERR(bb);
goto exit;
}
- write_cs_mi_lri(bb, reg_lri, 1);
+ write_cs_mi_lri(bb, reg_lri, count);
fence = xe_oa_submit_bb(stream, XE_OA_SUBMIT_NO_DEPS, bb);
if (IS_ERR(fence)) {
@@ -751,71 +723,55 @@ exit:
static int xe_oa_configure_oar_context(struct xe_oa_stream *stream, bool enable)
{
const struct xe_oa_format *format = stream->oa_buffer.format;
- struct xe_lrc *lrc = stream->exec_q->lrc[0];
- u32 regs_offset = xe_lrc_regs_offset(lrc) / sizeof(u32);
u32 oacontrol = __format_to_oactrl(format, OAR_OACONTROL_COUNTER_SEL_MASK) |
(enable ? OAR_OACONTROL_COUNTER_ENABLE : 0);
- struct flex regs_context[] = {
+ struct xe_oa_reg reg_lri[] = {
{
OACTXCONTROL(stream->hwe->mmio_base),
- stream->oa->ctx_oactxctrl_offset[stream->hwe->class] + 1,
enable ? OA_COUNTER_RESUME : 0,
},
{
+ OAR_OACONTROL,
+ oacontrol,
+ },
+ {
RING_CONTEXT_CONTROL(stream->hwe->mmio_base),
- regs_offset + CTX_CONTEXT_CONTROL,
- _MASKED_BIT_ENABLE(CTX_CTRL_OAC_CONTEXT_ENABLE),
+ _MASKED_FIELD(CTX_CTRL_OAC_CONTEXT_ENABLE,
+ enable ? CTX_CTRL_OAC_CONTEXT_ENABLE : 0)
},
};
- struct xe_oa_reg reg_lri = { OAR_OACONTROL, oacontrol };
- int err;
-
- /* Modify stream hwe context image with regs_context */
- err = xe_oa_modify_ctx_image(stream, stream->exec_q->lrc[0],
- regs_context, ARRAY_SIZE(regs_context));
- if (err)
- return err;
- /* Apply reg_lri using LRI */
- return xe_oa_load_with_lri(stream, &reg_lri);
+ return xe_oa_load_with_lri(stream, reg_lri, ARRAY_SIZE(reg_lri));
}
static int xe_oa_configure_oac_context(struct xe_oa_stream *stream, bool enable)
{
const struct xe_oa_format *format = stream->oa_buffer.format;
- struct xe_lrc *lrc = stream->exec_q->lrc[0];
- u32 regs_offset = xe_lrc_regs_offset(lrc) / sizeof(u32);
u32 oacontrol = __format_to_oactrl(format, OAR_OACONTROL_COUNTER_SEL_MASK) |
(enable ? OAR_OACONTROL_COUNTER_ENABLE : 0);
- struct flex regs_context[] = {
+ struct xe_oa_reg reg_lri[] = {
{
OACTXCONTROL(stream->hwe->mmio_base),
- stream->oa->ctx_oactxctrl_offset[stream->hwe->class] + 1,
enable ? OA_COUNTER_RESUME : 0,
},
{
+ OAC_OACONTROL,
+ oacontrol
+ },
+ {
RING_CONTEXT_CONTROL(stream->hwe->mmio_base),
- regs_offset + CTX_CONTEXT_CONTROL,
- _MASKED_BIT_ENABLE(CTX_CTRL_OAC_CONTEXT_ENABLE) |
+ _MASKED_FIELD(CTX_CTRL_OAC_CONTEXT_ENABLE,
+ enable ? CTX_CTRL_OAC_CONTEXT_ENABLE : 0) |
_MASKED_FIELD(CTX_CTRL_RUN_ALONE, enable ? CTX_CTRL_RUN_ALONE : 0),
},
};
- struct xe_oa_reg reg_lri = { OAC_OACONTROL, oacontrol };
- int err;
/* Set ccs select to enable programming of OAC_OACONTROL */
xe_mmio_write32(&stream->gt->mmio, __oa_regs(stream)->oa_ctrl,
__oa_ccs_select(stream));
- /* Modify stream hwe context image with regs_context */
- err = xe_oa_modify_ctx_image(stream, stream->exec_q->lrc[0],
- regs_context, ARRAY_SIZE(regs_context));
- if (err)
- return err;
-
- /* Apply reg_lri using LRI */
- return xe_oa_load_with_lri(stream, &reg_lri);
+ return xe_oa_load_with_lri(stream, reg_lri, ARRAY_SIZE(reg_lri));
}
static int xe_oa_configure_oa_context(struct xe_oa_stream *stream, bool enable)
@@ -2066,8 +2022,8 @@ int xe_oa_stream_open_ioctl(struct drm_device *dev, u64 data, struct drm_file *f
if (XE_IOCTL_DBG(oa->xe, !param.exec_q))
return -ENOENT;
- if (param.exec_q->width > 1)
- drm_dbg(&oa->xe->drm, "exec_q->width > 1, programming only exec_q->lrc[0]\n");
+ if (XE_IOCTL_DBG(oa->xe, param.exec_q->width > 1))
+ return -EOPNOTSUPP;
}
/*
diff --git a/drivers/gpu/drm/xe/xe_pci.c b/drivers/gpu/drm/xe/xe_pci.c
index e6640283893f..6b7f77425c7f 100644
--- a/drivers/gpu/drm/xe/xe_pci.c
+++ b/drivers/gpu/drm/xe/xe_pci.c
@@ -174,7 +174,7 @@ static const struct xe_graphics_desc graphics_xelpg = {
GENMASK(XE_HW_ENGINE_CCS3, XE_HW_ENGINE_CCS0)
static const struct xe_graphics_desc graphics_xe2 = {
- .name = "Xe2_LPG / Xe2_HPG",
+ .name = "Xe2_LPG / Xe2_HPG / Xe3_LPG",
XE2_GFX_FEATURES,
};
diff --git a/drivers/gpu/drm/xe/xe_pt.c b/drivers/gpu/drm/xe/xe_pt.c
index f27f579f4d85..797576690356 100644
--- a/drivers/gpu/drm/xe/xe_pt.c
+++ b/drivers/gpu/drm/xe/xe_pt.c
@@ -1333,8 +1333,7 @@ static void invalidation_fence_cb(struct dma_fence *fence,
queue_work(system_wq, &ifence->work);
} else {
ifence->base.base.error = ifence->fence->error;
- dma_fence_signal(&ifence->base.base);
- dma_fence_put(&ifence->base.base);
+ xe_gt_tlb_invalidation_fence_signal(&ifence->base);
}
dma_fence_put(ifence->fence);
}
diff --git a/drivers/gpu/drm/xe/xe_reg_sr.c b/drivers/gpu/drm/xe/xe_reg_sr.c
index e1a0e27cda14..c13123008e90 100644
--- a/drivers/gpu/drm/xe/xe_reg_sr.c
+++ b/drivers/gpu/drm/xe/xe_reg_sr.c
@@ -27,46 +27,27 @@
#include "xe_reg_whitelist.h"
#include "xe_rtp_types.h"
-#define XE_REG_SR_GROW_STEP_DEFAULT 16
-
static void reg_sr_fini(struct drm_device *drm, void *arg)
{
struct xe_reg_sr *sr = arg;
+ struct xe_reg_sr_entry *entry;
+ unsigned long reg;
+
+ xa_for_each(&sr->xa, reg, entry)
+ kfree(entry);
xa_destroy(&sr->xa);
- kfree(sr->pool.arr);
- memset(&sr->pool, 0, sizeof(sr->pool));
}
int xe_reg_sr_init(struct xe_reg_sr *sr, const char *name, struct xe_device *xe)
{
xa_init(&sr->xa);
- memset(&sr->pool, 0, sizeof(sr->pool));
- sr->pool.grow_step = XE_REG_SR_GROW_STEP_DEFAULT;
sr->name = name;
return drmm_add_action_or_reset(&xe->drm, reg_sr_fini, sr);
}
EXPORT_SYMBOL_IF_KUNIT(xe_reg_sr_init);
-static struct xe_reg_sr_entry *alloc_entry(struct xe_reg_sr *sr)
-{
- if (sr->pool.used == sr->pool.allocated) {
- struct xe_reg_sr_entry *arr;
-
- arr = krealloc_array(sr->pool.arr,
- ALIGN(sr->pool.allocated + 1, sr->pool.grow_step),
- sizeof(*arr), GFP_KERNEL);
- if (!arr)
- return NULL;
-
- sr->pool.arr = arr;
- sr->pool.allocated += sr->pool.grow_step;
- }
-
- return &sr->pool.arr[sr->pool.used++];
-}
-
static bool compatible_entries(const struct xe_reg_sr_entry *e1,
const struct xe_reg_sr_entry *e2)
{
@@ -112,7 +93,7 @@ int xe_reg_sr_add(struct xe_reg_sr *sr,
return 0;
}
- pentry = alloc_entry(sr);
+ pentry = kmalloc(sizeof(*pentry), GFP_KERNEL);
if (!pentry) {
ret = -ENOMEM;
goto fail;
diff --git a/drivers/gpu/drm/xe/xe_reg_sr_types.h b/drivers/gpu/drm/xe/xe_reg_sr_types.h
index ad48a52b824a..ebe11f237fa2 100644
--- a/drivers/gpu/drm/xe/xe_reg_sr_types.h
+++ b/drivers/gpu/drm/xe/xe_reg_sr_types.h
@@ -20,12 +20,6 @@ struct xe_reg_sr_entry {
};
struct xe_reg_sr {
- struct {
- struct xe_reg_sr_entry *arr;
- unsigned int used;
- unsigned int allocated;
- unsigned int grow_step;
- } pool;
struct xarray xa;
const char *name;
diff --git a/drivers/gpu/drm/xe/xe_ring_ops.c b/drivers/gpu/drm/xe/xe_ring_ops.c
index 0be4f489d3e1..9f327f27c072 100644
--- a/drivers/gpu/drm/xe/xe_ring_ops.c
+++ b/drivers/gpu/drm/xe/xe_ring_ops.c
@@ -221,7 +221,10 @@ static int emit_pipe_imm_ggtt(u32 addr, u32 value, bool stall_only, u32 *dw,
static u32 get_ppgtt_flag(struct xe_sched_job *job)
{
- return job->q->vm ? BIT(8) : 0;
+ if (job->q->vm && !job->ggtt)
+ return BIT(8);
+
+ return 0;
}
static int emit_copy_timestamp(struct xe_lrc *lrc, u32 *dw, int i)
diff --git a/drivers/gpu/drm/xe/xe_sched_job_types.h b/drivers/gpu/drm/xe/xe_sched_job_types.h
index f13f333f00be..d942b20a9f29 100644
--- a/drivers/gpu/drm/xe/xe_sched_job_types.h
+++ b/drivers/gpu/drm/xe/xe_sched_job_types.h
@@ -56,6 +56,8 @@ struct xe_sched_job {
u32 migrate_flush_flags;
/** @ring_ops_flush_tlb: The ring ops need to flush TLB before payload. */
bool ring_ops_flush_tlb;
+ /** @ggtt: mapped in ggtt. */
+ bool ggtt;
/** @ptrs: per instance pointers. */
struct xe_job_ptrs ptrs[];
};
diff --git a/drivers/gpu/drm/xe/xe_sync.c b/drivers/gpu/drm/xe/xe_sync.c
index a90480c6aecf..42f5bebd09e5 100644
--- a/drivers/gpu/drm/xe/xe_sync.c
+++ b/drivers/gpu/drm/xe/xe_sync.c
@@ -87,8 +87,12 @@ static void user_fence_worker(struct work_struct *w)
drm_dbg(&ufence->xe->drm, "mmget_not_zero() failed, ufence wasn't signaled\n");
}
- wake_up_all(&ufence->xe->ufence_wq);
+ /*
+ * Wake up waiters only after updating the ufence state, allowing the UMD
+ * to safely reuse the same ufence without encountering -EBUSY errors.
+ */
WRITE_ONCE(ufence->signalled, 1);
+ wake_up_all(&ufence->xe->ufence_wq);
user_fence_put(ufence);
}
diff --git a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
index f5781939de9c..07c4d184e7a1 100644
--- a/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
+++ b/drivers/gpu/drm/xlnx/zynqmp_dpsub.c
@@ -320,7 +320,7 @@ MODULE_DEVICE_TABLE(of, zynqmp_dpsub_of_match);
static struct platform_driver zynqmp_dpsub_driver = {
.probe = zynqmp_dpsub_probe,
- .remove_new = zynqmp_dpsub_remove,
+ .remove = zynqmp_dpsub_remove,
.shutdown = zynqmp_dpsub_shutdown,
.driver = {
.name = "zynqmp-dpsub",
diff --git a/drivers/gpu/host1x/dev.c b/drivers/gpu/host1x/dev.c
index be2ad7203d7b..7b1d091f3c09 100644
--- a/drivers/gpu/host1x/dev.c
+++ b/drivers/gpu/host1x/dev.c
@@ -769,7 +769,7 @@ static struct platform_driver tegra_host1x_driver = {
.pm = &host1x_pm_ops,
},
.probe = host1x_probe,
- .remove_new = host1x_remove,
+ .remove = host1x_remove,
};
static struct platform_driver * const drivers[] = {
diff --git a/drivers/gpu/ipu-v3/ipu-common.c b/drivers/gpu/ipu-v3/ipu-common.c
index 3535be9daa1f..947323f4a234 100644
--- a/drivers/gpu/ipu-v3/ipu-common.c
+++ b/drivers/gpu/ipu-v3/ipu-common.c
@@ -1467,7 +1467,7 @@ static struct platform_driver imx_ipu_driver = {
.of_match_table = imx_ipu_dt_ids,
},
.probe = ipu_probe,
- .remove_new = ipu_remove,
+ .remove = ipu_remove,
};
static struct platform_driver * const drivers[] = {
diff --git a/drivers/gpu/ipu-v3/ipu-pre.c b/drivers/gpu/ipu-v3/ipu-pre.c
index 41bd5dbd7356..7aac70368b00 100644
--- a/drivers/gpu/ipu-v3/ipu-pre.c
+++ b/drivers/gpu/ipu-v3/ipu-pre.c
@@ -374,7 +374,7 @@ static const struct of_device_id ipu_pre_dt_ids[] = {
struct platform_driver ipu_pre_drv = {
.probe = ipu_pre_probe,
- .remove_new = ipu_pre_remove,
+ .remove = ipu_pre_remove,
.driver = {
.name = "imx-ipu-pre",
.of_match_table = ipu_pre_dt_ids,
diff --git a/drivers/gpu/ipu-v3/ipu-prg.c b/drivers/gpu/ipu-v3/ipu-prg.c
index afb2d72e9175..d38d3ba54d72 100644
--- a/drivers/gpu/ipu-v3/ipu-prg.c
+++ b/drivers/gpu/ipu-v3/ipu-prg.c
@@ -469,7 +469,7 @@ static const struct of_device_id ipu_prg_dt_ids[] = {
struct platform_driver ipu_prg_drv = {
.probe = ipu_prg_probe,
- .remove_new = ipu_prg_remove,
+ .remove = ipu_prg_remove,
.driver = {
.name = "imx-ipu-prg",
.pm = &prg_pm_ops,
diff --git a/drivers/greybus/interface.c b/drivers/greybus/interface.c
index d022bfb5e95d..a0f3e9422721 100644
--- a/drivers/greybus/interface.c
+++ b/drivers/greybus/interface.c
@@ -780,7 +780,7 @@ const struct device_type greybus_interface_type = {
* The position of interface within the Endo is encoded in "interface_id"
* argument.
*
- * Returns a pointer to the new interfce or a null pointer if a
+ * Returns a pointer to the new interface or a null pointer if a
* failure occurs due to memory exhaustion.
*/
struct gb_interface *gb_interface_create(struct gb_module *module,
diff --git a/drivers/hid/bpf/hid_bpf_dispatch.c b/drivers/hid/bpf/hid_bpf_dispatch.c
index 961b7f35aa67..2e96ec6a3073 100644
--- a/drivers/hid/bpf/hid_bpf_dispatch.c
+++ b/drivers/hid/bpf/hid_bpf_dispatch.c
@@ -19,7 +19,7 @@
#include <linux/module.h>
#include "hid_bpf_dispatch.h"
-struct hid_ops *hid_ops;
+const struct hid_ops *hid_ops;
EXPORT_SYMBOL(hid_ops);
u8 *
@@ -352,7 +352,6 @@ __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
{
struct hid_report_enum *report_enum;
struct hid_report *report;
- struct hid_device *hdev;
u32 report_len;
/* check arguments */
@@ -371,9 +370,7 @@ __hid_bpf_hw_check_params(struct hid_bpf_ctx *ctx, __u8 *buf, size_t *buf__sz,
if (*buf__sz < 1)
return -EINVAL;
- hdev = (struct hid_device *)ctx->hid; /* discard const */
-
- report_enum = hdev->report_enum + rtype;
+ report_enum = ctx->hid->report_enum + rtype;
report = hid_ops->hid_get_report(report_enum, buf);
if (!report)
return -EINVAL;
@@ -402,7 +399,6 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
enum hid_report_type rtype, enum hid_class_request reqtype)
{
struct hid_bpf_ctx_kern *ctx_kern;
- struct hid_device *hdev;
size_t size = buf__sz;
u8 *dma_data;
int ret;
@@ -429,13 +425,11 @@ hid_bpf_hw_request(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz,
return -EINVAL;
}
- hdev = (struct hid_device *)ctx->hid; /* discard const */
-
dma_data = kmemdup(buf, size, GFP_KERNEL);
if (!dma_data)
return -ENOMEM;
- ret = hid_ops->hid_hw_raw_request(hdev,
+ ret = hid_ops->hid_hw_raw_request(ctx->hid,
dma_data[0],
dma_data,
size,
@@ -464,7 +458,6 @@ __bpf_kfunc int
hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
{
struct hid_bpf_ctx_kern *ctx_kern;
- struct hid_device *hdev;
size_t size = buf__sz;
u8 *dma_data;
int ret;
@@ -478,13 +471,11 @@ hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx, __u8 *buf, size_t buf__sz)
if (ret)
return ret;
- hdev = (struct hid_device *)ctx->hid; /* discard const */
-
dma_data = kmemdup(buf, size, GFP_KERNEL);
if (!dma_data)
return -ENOMEM;
- ret = hid_ops->hid_hw_output_report(hdev, dma_data, size, (u64)(long)ctx, true);
+ ret = hid_ops->hid_hw_output_report(ctx->hid, dma_data, size, (u64)(long)ctx, true);
kfree(dma_data);
return ret;
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index 98bef39642a9..33a191973324 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -3064,7 +3064,7 @@ int hid_check_keys_pressed(struct hid_device *hid)
EXPORT_SYMBOL_GPL(hid_check_keys_pressed);
#ifdef CONFIG_HID_BPF
-static struct hid_ops __hid_ops = {
+static const struct hid_ops __hid_ops = {
.hid_get_report = hid_get_report,
.hid_hw_raw_request = __hid_hw_raw_request,
.hid_hw_output_report = __hid_hw_output_report,
diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c
index 22683ec819aa..0f292b5d3e26 100644
--- a/drivers/hid/hid-google-hammer.c
+++ b/drivers/hid/hid-google-hammer.c
@@ -284,7 +284,7 @@ MODULE_DEVICE_TABLE(of, cbas_ec_of_match);
static struct platform_driver cbas_ec_driver = {
.probe = cbas_ec_probe,
- .remove_new = cbas_ec_remove,
+ .remove = cbas_ec_remove,
.driver = {
.name = "cbas_ec",
.acpi_match_table = ACPI_PTR(cbas_ec_acpi_ids),
diff --git a/drivers/hid/hid-sensor-custom.c b/drivers/hid/hid-sensor-custom.c
index 617ae240396d..761760668f6d 100644
--- a/drivers/hid/hid-sensor-custom.c
+++ b/drivers/hid/hid-sensor-custom.c
@@ -1065,7 +1065,7 @@ static struct platform_driver hid_sensor_custom_platform_driver = {
.name = KBUILD_MODNAME,
},
.probe = hid_sensor_custom_probe,
- .remove_new = hid_sensor_custom_remove,
+ .remove = hid_sensor_custom_remove,
};
module_platform_driver(hid_sensor_custom_platform_driver);
diff --git a/drivers/hid/hid-uclogic-rdesc-test.c b/drivers/hid/hid-uclogic-rdesc-test.c
index d6b18213f45f..066df622b6f2 100644
--- a/drivers/hid/hid-uclogic-rdesc-test.c
+++ b/drivers/hid/hid-uclogic-rdesc-test.c
@@ -9,7 +9,7 @@
#include <kunit/test.h>
#include "./hid-uclogic-rdesc.h"
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
struct uclogic_template_case {
const char *name;
diff --git a/drivers/hid/i2c-hid/i2c-hid-core.c b/drivers/hid/i2c-hid/i2c-hid-core.c
index 43664a24176f..4e87380d3edd 100644
--- a/drivers/hid/i2c-hid/i2c-hid-core.c
+++ b/drivers/hid/i2c-hid/i2c-hid-core.c
@@ -414,7 +414,19 @@ static int i2c_hid_set_power(struct i2c_hid *ihid, int power_state)
i2c_hid_dbg(ihid, "%s\n", __func__);
+ /*
+ * Some STM-based devices need 400µs after a rising clock edge to wake
+ * from deep sleep, in which case the first request will fail due to
+ * the address not being acknowledged. Try after a short sleep to see
+ * if the device came alive on the bus. Certain Weida Tech devices also
+ * need this.
+ */
ret = i2c_hid_set_power_command(ihid, power_state);
+ if (ret && power_state == I2C_HID_PWR_ON) {
+ usleep_range(400, 500);
+ ret = i2c_hid_set_power_command(ihid, I2C_HID_PWR_ON);
+ }
+
if (ret)
dev_err(&ihid->client->dev,
"failed to change power setting.\n");
@@ -976,14 +988,6 @@ static int i2c_hid_core_resume(struct i2c_hid *ihid)
enable_irq(client->irq);
- /* Make sure the device is awake on the bus */
- ret = i2c_hid_probe_address(ihid);
- if (ret < 0) {
- dev_err(&client->dev, "nothing at address after resume: %d\n",
- ret);
- return -ENXIO;
- }
-
/* On Goodix 27c6:0d42 wait extra time before device wakeup.
* It's not clear why but if we send wakeup too early, the device will
* never trigger input interrupts.
diff --git a/drivers/hid/surface-hid/surface_kbd.c b/drivers/hid/surface-hid/surface_kbd.c
index 383200d9121a..0be01b5e7425 100644
--- a/drivers/hid/surface-hid/surface_kbd.c
+++ b/drivers/hid/surface-hid/surface_kbd.c
@@ -284,7 +284,7 @@ MODULE_DEVICE_TABLE(acpi, surface_kbd_match);
static struct platform_driver surface_kbd_driver = {
.probe = surface_kbd_probe,
- .remove_new = surface_kbd_remove,
+ .remove = surface_kbd_remove,
.driver = {
.name = "surface_keyboard",
.acpi_match_table = surface_kbd_match,
diff --git a/drivers/hid/wacom_sys.c b/drivers/hid/wacom_sys.c
index 2bc45b24075c..9843b52bd017 100644
--- a/drivers/hid/wacom_sys.c
+++ b/drivers/hid/wacom_sys.c
@@ -2241,7 +2241,8 @@ static void wacom_update_name(struct wacom *wacom, const char *suffix)
if (hid_is_usb(wacom->hdev)) {
struct usb_interface *intf = to_usb_interface(wacom->hdev->dev.parent);
struct usb_device *dev = interface_to_usbdev(intf);
- product_name = dev->product;
+ if (dev->product != NULL)
+ product_name = dev->product;
}
if (wacom->hdev->bus == BUS_I2C) {
diff --git a/drivers/hsi/controllers/omap_ssi_core.c b/drivers/hsi/controllers/omap_ssi_core.c
index 15cb759151e6..eeacc427fd65 100644
--- a/drivers/hsi/controllers/omap_ssi_core.c
+++ b/drivers/hsi/controllers/omap_ssi_core.c
@@ -607,7 +607,7 @@ MODULE_DEVICE_TABLE(of, omap_ssi_of_match);
static struct platform_driver ssi_pdriver = {
.probe = ssi_probe,
- .remove_new = ssi_remove,
+ .remove = ssi_remove,
.driver = {
.name = "omap_ssi",
.pm = DEV_PM_OPS,
diff --git a/drivers/hsi/controllers/omap_ssi_port.c b/drivers/hsi/controllers/omap_ssi_port.c
index f0b3eca7376e..aeb92b803a17 100644
--- a/drivers/hsi/controllers/omap_ssi_port.c
+++ b/drivers/hsi/controllers/omap_ssi_port.c
@@ -1385,7 +1385,7 @@ MODULE_DEVICE_TABLE(of, omap_ssi_port_of_match);
struct platform_driver ssi_port_pdriver = {
.probe = ssi_port_probe,
- .remove_new = ssi_port_remove,
+ .remove = ssi_port_remove,
.driver = {
.name = "omap_ssi_port",
.of_match_table = omap_ssi_port_of_match,
diff --git a/drivers/hte/hte-tegra194-test.c b/drivers/hte/hte-tegra194-test.c
index df631b5100d2..f890b79723af 100644
--- a/drivers/hte/hte-tegra194-test.c
+++ b/drivers/hte/hte-tegra194-test.c
@@ -226,7 +226,7 @@ static void tegra_hte_test_remove(struct platform_device *pdev)
static struct platform_driver tegra_hte_test_driver = {
.probe = tegra_hte_test_probe,
- .remove_new = tegra_hte_test_remove,
+ .remove = tegra_hte_test_remove,
.driver = {
.name = "tegra_hte_test",
.of_match_table = tegra_hte_test_of_match,
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index c38dcdfcb914..a99112e6f0b8 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -756,7 +756,7 @@ static void hv_mem_hot_add(unsigned long start, unsigned long size,
* adding succeeded, it is ok to proceed even if the memory was
* not onlined in time.
*/
- wait_for_completion_timeout(&dm_device.ol_waitevent, 5 * HZ);
+ wait_for_completion_timeout(&dm_device.ol_waitevent, secs_to_jiffies(5));
post_status(&dm_device);
}
}
@@ -1373,7 +1373,8 @@ static int dm_thread_func(void *dm_dev)
struct hv_dynmem_device *dm = dm_dev;
while (!kthread_should_stop()) {
- wait_for_completion_interruptible_timeout(&dm_device.config_event, 1 * HZ);
+ wait_for_completion_interruptible_timeout(&dm_device.config_event,
+ secs_to_jiffies(1));
/*
* The host expects us to post information on the memory
* pressure every second.
@@ -1748,7 +1749,7 @@ static int balloon_connect_vsp(struct hv_device *dev)
if (ret)
goto out;
- t = wait_for_completion_timeout(&dm_device.host_event, 5 * HZ);
+ t = wait_for_completion_timeout(&dm_device.host_event, secs_to_jiffies(5));
if (t == 0) {
ret = -ETIMEDOUT;
goto out;
@@ -1806,7 +1807,7 @@ static int balloon_connect_vsp(struct hv_device *dev)
if (ret)
goto out;
- t = wait_for_completion_timeout(&dm_device.host_event, 5 * HZ);
+ t = wait_for_completion_timeout(&dm_device.host_event, secs_to_jiffies(5));
if (t == 0) {
ret = -ETIMEDOUT;
goto out;
diff --git a/drivers/hv/hv_kvp.c b/drivers/hv/hv_kvp.c
index d35b60c06114..7400a5a4d2bd 100644
--- a/drivers/hv/hv_kvp.c
+++ b/drivers/hv/hv_kvp.c
@@ -655,7 +655,7 @@ void hv_kvp_onchannelcallback(void *context)
if (host_negotiatied == NEGO_NOT_STARTED) {
host_negotiatied = NEGO_IN_PROGRESS;
schedule_delayed_work(&kvp_host_handshake_work,
- HV_UTIL_NEGO_TIMEOUT * HZ);
+ secs_to_jiffies(HV_UTIL_NEGO_TIMEOUT));
}
return;
}
@@ -724,7 +724,7 @@ void hv_kvp_onchannelcallback(void *context)
*/
schedule_work(&kvp_sendkey_work);
schedule_delayed_work(&kvp_timeout_work,
- HV_UTIL_TIMEOUT * HZ);
+ secs_to_jiffies(HV_UTIL_TIMEOUT));
return;
@@ -767,6 +767,12 @@ hv_kvp_init(struct hv_util_service *srv)
*/
kvp_transaction.state = HVUTIL_DEVICE_INIT;
+ return 0;
+}
+
+int
+hv_kvp_init_transport(void)
+{
hvt = hvutil_transport_init(kvp_devname, CN_KVP_IDX, CN_KVP_VAL,
kvp_on_msg, kvp_on_reset);
if (!hvt)
diff --git a/drivers/hv/hv_snapshot.c b/drivers/hv/hv_snapshot.c
index 0d2184be1691..bde637a96c37 100644
--- a/drivers/hv/hv_snapshot.c
+++ b/drivers/hv/hv_snapshot.c
@@ -193,7 +193,8 @@ static void vss_send_op(void)
vss_transaction.state = HVUTIL_USERSPACE_REQ;
schedule_delayed_work(&vss_timeout_work, op == VSS_OP_FREEZE ?
- VSS_FREEZE_TIMEOUT * HZ : HV_UTIL_TIMEOUT * HZ);
+ secs_to_jiffies(VSS_FREEZE_TIMEOUT) :
+ secs_to_jiffies(HV_UTIL_TIMEOUT));
rc = hvutil_transport_send(hvt, vss_msg, sizeof(*vss_msg), NULL);
if (rc) {
@@ -388,6 +389,12 @@ hv_vss_init(struct hv_util_service *srv)
*/
vss_transaction.state = HVUTIL_DEVICE_INIT;
+ return 0;
+}
+
+int
+hv_vss_init_transport(void)
+{
hvt = hvutil_transport_init(vss_devname, CN_VSS_IDX, CN_VSS_VAL,
vss_on_msg, vss_on_reset);
if (!hvt) {
diff --git a/drivers/hv/hv_util.c b/drivers/hv/hv_util.c
index c4f525325790..36ee89c0358b 100644
--- a/drivers/hv/hv_util.c
+++ b/drivers/hv/hv_util.c
@@ -141,6 +141,7 @@ static struct hv_util_service util_heartbeat = {
static struct hv_util_service util_kvp = {
.util_cb = hv_kvp_onchannelcallback,
.util_init = hv_kvp_init,
+ .util_init_transport = hv_kvp_init_transport,
.util_pre_suspend = hv_kvp_pre_suspend,
.util_pre_resume = hv_kvp_pre_resume,
.util_deinit = hv_kvp_deinit,
@@ -149,6 +150,7 @@ static struct hv_util_service util_kvp = {
static struct hv_util_service util_vss = {
.util_cb = hv_vss_onchannelcallback,
.util_init = hv_vss_init,
+ .util_init_transport = hv_vss_init_transport,
.util_pre_suspend = hv_vss_pre_suspend,
.util_pre_resume = hv_vss_pre_resume,
.util_deinit = hv_vss_deinit,
@@ -590,10 +592,8 @@ static int util_probe(struct hv_device *dev,
srv->channel = dev->channel;
if (srv->util_init) {
ret = srv->util_init(srv);
- if (ret) {
- ret = -ENODEV;
+ if (ret)
goto error1;
- }
}
/*
@@ -613,6 +613,13 @@ static int util_probe(struct hv_device *dev,
if (ret)
goto error;
+ if (srv->util_init_transport) {
+ ret = srv->util_init_transport();
+ if (ret) {
+ vmbus_close(dev->channel);
+ goto error;
+ }
+ }
return 0;
error:
diff --git a/drivers/hv/hyperv_vmbus.h b/drivers/hv/hyperv_vmbus.h
index d2856023d53c..52cb744b4d7f 100644
--- a/drivers/hv/hyperv_vmbus.h
+++ b/drivers/hv/hyperv_vmbus.h
@@ -370,12 +370,14 @@ void vmbus_on_event(unsigned long data);
void vmbus_on_msg_dpc(unsigned long data);
int hv_kvp_init(struct hv_util_service *srv);
+int hv_kvp_init_transport(void);
void hv_kvp_deinit(void);
int hv_kvp_pre_suspend(void);
int hv_kvp_pre_resume(void);
void hv_kvp_onchannelcallback(void *context);
int hv_vss_init(struct hv_util_service *srv);
+int hv_vss_init_transport(void);
void hv_vss_deinit(void);
int hv_vss_pre_suspend(void);
int hv_vss_pre_resume(void);
diff --git a/drivers/hv/vmbus_drv.c b/drivers/hv/vmbus_drv.c
index 9b15f7daf505..2892b8da20a5 100644
--- a/drivers/hv/vmbus_drv.c
+++ b/drivers/hv/vmbus_drv.c
@@ -2507,7 +2507,7 @@ static int vmbus_bus_resume(struct device *dev)
vmbus_request_offers();
if (wait_for_completion_timeout(
- &vmbus_connection.ready_for_resume_event, 10 * HZ) == 0)
+ &vmbus_connection.ready_for_resume_event, secs_to_jiffies(10)) == 0)
pr_err("Some vmbus device is missing after suspending?\n");
/* Reset the event for the next suspend. */
@@ -2560,7 +2560,7 @@ static const struct dev_pm_ops vmbus_bus_pm = {
static struct platform_driver vmbus_platform_driver = {
.probe = vmbus_platform_driver_probe,
- .remove_new = vmbus_platform_driver_remove,
+ .remove = vmbus_platform_driver_remove,
.driver = {
.name = "vmbus",
.acpi_match_table = ACPI_PTR(vmbus_acpi_device_ids),
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index 49b366254529..bbb9cc44e29f 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -1074,7 +1074,7 @@ hwmon_device_register_for_thermal(struct device *dev, const char *name,
return __hwmon_device_register(dev, name, drvdata, NULL, NULL);
}
-EXPORT_SYMBOL_NS_GPL(hwmon_device_register_for_thermal, HWMON_THERMAL);
+EXPORT_SYMBOL_NS_GPL(hwmon_device_register_for_thermal, "HWMON_THERMAL");
/**
* hwmon_device_register - register w/ hwmon
diff --git a/drivers/hwmon/intel-m10-bmc-hwmon.c b/drivers/hwmon/intel-m10-bmc-hwmon.c
index e221f2c1f332..aa01a4bedc21 100644
--- a/drivers/hwmon/intel-m10-bmc-hwmon.c
+++ b/drivers/hwmon/intel-m10-bmc-hwmon.c
@@ -787,4 +787,4 @@ MODULE_DEVICE_TABLE(platform, intel_m10bmc_hwmon_ids);
MODULE_AUTHOR("Intel Corporation");
MODULE_DESCRIPTION("Intel MAX 10 BMC hardware monitor");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(INTEL_M10_BMC_CORE);
+MODULE_IMPORT_NS("INTEL_M10_BMC_CORE");
diff --git a/drivers/hwmon/nct6775-core.c b/drivers/hwmon/nct6775-core.c
index ee04795b98aa..c243b51837d2 100644
--- a/drivers/hwmon/nct6775-core.c
+++ b/drivers/hwmon/nct6775-core.c
@@ -57,7 +57,7 @@
#include "nct6775.h"
#undef DEFAULT_SYMBOL_NAMESPACE
-#define DEFAULT_SYMBOL_NAMESPACE HWMON_NCT6775
+#define DEFAULT_SYMBOL_NAMESPACE "HWMON_NCT6775"
#define USE_ALTERNATE
diff --git a/drivers/hwmon/nct6775-i2c.c b/drivers/hwmon/nct6775-i2c.c
index aff69fa50461..ba71d776a291 100644
--- a/drivers/hwmon/nct6775-i2c.c
+++ b/drivers/hwmon/nct6775-i2c.c
@@ -184,4 +184,4 @@ module_i2c_driver(nct6775_i2c_driver);
MODULE_AUTHOR("Zev Weiss <zev@bewilderbeest.net>");
MODULE_DESCRIPTION("I2C driver for NCT6775F and compatible chips");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(HWMON_NCT6775);
+MODULE_IMPORT_NS("HWMON_NCT6775");
diff --git a/drivers/hwmon/nct6775-platform.c b/drivers/hwmon/nct6775-platform.c
index 1218a3b449a8..0a040364b512 100644
--- a/drivers/hwmon/nct6775-platform.c
+++ b/drivers/hwmon/nct6775-platform.c
@@ -1622,7 +1622,7 @@ static void __exit sensors_nct6775_platform_exit(void)
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
MODULE_DESCRIPTION("Platform driver for NCT6775F and compatible chips");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(HWMON_NCT6775);
+MODULE_IMPORT_NS("HWMON_NCT6775");
module_init(sensors_nct6775_platform_init);
module_exit(sensors_nct6775_platform_exit);
diff --git a/drivers/hwmon/peci/cputemp.c b/drivers/hwmon/peci/cputemp.c
index 5a682195b98f..c7112dbf008b 100644
--- a/drivers/hwmon/peci/cputemp.c
+++ b/drivers/hwmon/peci/cputemp.c
@@ -607,4 +607,4 @@ MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
MODULE_AUTHOR("Iwona Winiarska <iwona.winiarska@intel.com>");
MODULE_DESCRIPTION("PECI cputemp driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PECI_CPU);
+MODULE_IMPORT_NS("PECI_CPU");
diff --git a/drivers/hwmon/peci/dimmtemp.c b/drivers/hwmon/peci/dimmtemp.c
index 4a72e9712408..d6762259dd69 100644
--- a/drivers/hwmon/peci/dimmtemp.c
+++ b/drivers/hwmon/peci/dimmtemp.c
@@ -666,4 +666,4 @@ MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
MODULE_AUTHOR("Iwona Winiarska <iwona.winiarska@intel.com>");
MODULE_DESCRIPTION("PECI dimmtemp driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PECI_CPU);
+MODULE_IMPORT_NS("PECI_CPU");
diff --git a/drivers/hwmon/pmbus/acbel-fsg032.c b/drivers/hwmon/pmbus/acbel-fsg032.c
index e0c55fd8f3a6..9f07fb4abaff 100644
--- a/drivers/hwmon/pmbus/acbel-fsg032.c
+++ b/drivers/hwmon/pmbus/acbel-fsg032.c
@@ -120,4 +120,4 @@ module_i2c_driver(acbel_fsg032_driver);
MODULE_AUTHOR("Lakshmi Yadlapati");
MODULE_DESCRIPTION("PMBus driver for AcBel Power System power supplies");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/adm1266.c b/drivers/hwmon/pmbus/adm1266.c
index 2c4d94cc8729..d90f8f80be8e 100644
--- a/drivers/hwmon/pmbus/adm1266.c
+++ b/drivers/hwmon/pmbus/adm1266.c
@@ -509,4 +509,4 @@ module_i2c_driver(adm1266_driver);
MODULE_AUTHOR("Alexandru Tachici <alexandru.tachici@analog.com>");
MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1266");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/adm1275.c b/drivers/hwmon/pmbus/adm1275.c
index 59ffc08289bd..127593e10a03 100644
--- a/drivers/hwmon/pmbus/adm1275.c
+++ b/drivers/hwmon/pmbus/adm1275.c
@@ -866,4 +866,4 @@ module_i2c_driver(adm1275_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Analog Devices ADM1275 and compatibles");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/adp1050.c b/drivers/hwmon/pmbus/adp1050.c
index 20f22730fc01..ef46c880b168 100644
--- a/drivers/hwmon/pmbus/adp1050.c
+++ b/drivers/hwmon/pmbus/adp1050.c
@@ -53,4 +53,4 @@ module_i2c_driver(adp1050_driver);
MODULE_AUTHOR("Radu Sabau <radu.sabau@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADP1050 HWMON PMBus Driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/bel-pfe.c b/drivers/hwmon/pmbus/bel-pfe.c
index 7c5f4b10a7c1..ddf9d9a2958c 100644
--- a/drivers/hwmon/pmbus/bel-pfe.c
+++ b/drivers/hwmon/pmbus/bel-pfe.c
@@ -129,4 +129,4 @@ module_i2c_driver(pfe_pmbus_driver);
MODULE_AUTHOR("Tao Ren <rentao.bupt@gmail.com>");
MODULE_DESCRIPTION("PMBus driver for BEL PFE Family Power Supplies");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/bpa-rs600.c b/drivers/hwmon/pmbus/bpa-rs600.c
index 0dce26c35556..6c3875ba37a0 100644
--- a/drivers/hwmon/pmbus/bpa-rs600.c
+++ b/drivers/hwmon/pmbus/bpa-rs600.c
@@ -205,4 +205,4 @@ module_i2c_driver(bpa_rs600_driver);
MODULE_AUTHOR("Chris Packham");
MODULE_DESCRIPTION("PMBus driver for BluTek BPA-RS600");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/delta-ahe50dc-fan.c b/drivers/hwmon/pmbus/delta-ahe50dc-fan.c
index 4dd3b6686d6a..3850eaea75da 100644
--- a/drivers/hwmon/pmbus/delta-ahe50dc-fan.c
+++ b/drivers/hwmon/pmbus/delta-ahe50dc-fan.c
@@ -127,4 +127,4 @@ module_i2c_driver(ahe50dc_fan_driver);
MODULE_AUTHOR("Zev Weiss <zev@bewilderbeest.net>");
MODULE_DESCRIPTION("Driver for Delta AHE-50DC power shelf fan control module");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/dps920ab.c b/drivers/hwmon/pmbus/dps920ab.c
index 04e0d598a6e5..cc5aac9dfdb3 100644
--- a/drivers/hwmon/pmbus/dps920ab.c
+++ b/drivers/hwmon/pmbus/dps920ab.c
@@ -203,4 +203,4 @@ module_i2c_driver(dps920ab_driver);
MODULE_AUTHOR("Robert Marko <robert.marko@sartura.hr>");
MODULE_DESCRIPTION("PMBus driver for Delta DPS920AB PSU");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/fsp-3y.c b/drivers/hwmon/pmbus/fsp-3y.c
index 72a7c261ef06..a4dc09e2ef75 100644
--- a/drivers/hwmon/pmbus/fsp-3y.c
+++ b/drivers/hwmon/pmbus/fsp-3y.c
@@ -291,4 +291,4 @@ module_i2c_driver(fsp3y_driver);
MODULE_AUTHOR("Václav Kubernát");
MODULE_DESCRIPTION("PMBus driver for FSP/3Y-Power power supplies");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/ibm-cffps.c b/drivers/hwmon/pmbus/ibm-cffps.c
index 1ba4c5e95820..d05ef7a968a9 100644
--- a/drivers/hwmon/pmbus/ibm-cffps.c
+++ b/drivers/hwmon/pmbus/ibm-cffps.c
@@ -614,4 +614,4 @@ module_i2c_driver(ibm_cffps_driver);
MODULE_AUTHOR("Eddie James");
MODULE_DESCRIPTION("PMBus driver for IBM Common Form Factor power supplies");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/inspur-ipsps.c b/drivers/hwmon/pmbus/inspur-ipsps.c
index 3e3cc9a0f116..074e0f164ee1 100644
--- a/drivers/hwmon/pmbus/inspur-ipsps.c
+++ b/drivers/hwmon/pmbus/inspur-ipsps.c
@@ -224,4 +224,4 @@ module_i2c_driver(ipsps_driver);
MODULE_AUTHOR("John Wang");
MODULE_DESCRIPTION("PMBus driver for Inspur Power System power supplies");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/ir35221.c b/drivers/hwmon/pmbus/ir35221.c
index 503be59c6c7f..46d8f334d49a 100644
--- a/drivers/hwmon/pmbus/ir35221.c
+++ b/drivers/hwmon/pmbus/ir35221.c
@@ -145,4 +145,4 @@ module_i2c_driver(ir35221_driver);
MODULE_AUTHOR("Samuel Mendoza-Jonas <sam@mendozajonas.com");
MODULE_DESCRIPTION("PMBus driver for IR35221");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/ir36021.c b/drivers/hwmon/pmbus/ir36021.c
index 5148c9187c9e..34ce15fc708b 100644
--- a/drivers/hwmon/pmbus/ir36021.c
+++ b/drivers/hwmon/pmbus/ir36021.c
@@ -76,4 +76,4 @@ module_i2c_driver(ir36021_driver);
MODULE_AUTHOR("Chris Packham <chris.packham@alliedtelesis.co.nz>");
MODULE_DESCRIPTION("PMBus driver for Infineon IR36021");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/ir38064.c b/drivers/hwmon/pmbus/ir38064.c
index d4bcc9c39774..7b4188e8bf48 100644
--- a/drivers/hwmon/pmbus/ir38064.c
+++ b/drivers/hwmon/pmbus/ir38064.c
@@ -87,4 +87,4 @@ module_i2c_driver(ir38064_driver);
MODULE_AUTHOR("Maxim Sloyko <maxims@google.com>");
MODULE_DESCRIPTION("PMBus driver for Infineon IR38064 and compatible chips");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/irps5401.c b/drivers/hwmon/pmbus/irps5401.c
index f0bdf55c95bf..43674c64841d 100644
--- a/drivers/hwmon/pmbus/irps5401.c
+++ b/drivers/hwmon/pmbus/irps5401.c
@@ -63,4 +63,4 @@ module_i2c_driver(irps5401_driver);
MODULE_AUTHOR("Robert Hancock");
MODULE_DESCRIPTION("PMBus driver for Infineon IRPS5401");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/isl68137.c b/drivers/hwmon/pmbus/isl68137.c
index 97cc951a13a4..2af921039309 100644
--- a/drivers/hwmon/pmbus/isl68137.c
+++ b/drivers/hwmon/pmbus/isl68137.c
@@ -532,4 +532,4 @@ module_i2c_driver(isl68137_driver);
MODULE_AUTHOR("Maxim Sloyko <maxims@google.com>");
MODULE_DESCRIPTION("PMBus driver for Renesas digital multiphase voltage regulators");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/lm25066.c b/drivers/hwmon/pmbus/lm25066.c
index c36c124d1a2d..40b0dda32ea6 100644
--- a/drivers/hwmon/pmbus/lm25066.c
+++ b/drivers/hwmon/pmbus/lm25066.c
@@ -569,4 +569,4 @@ module_i2c_driver(lm25066_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for LM25066 and compatible chips");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/lt7182s.c b/drivers/hwmon/pmbus/lt7182s.c
index aebd97af2741..9d6d50f39bd6 100644
--- a/drivers/hwmon/pmbus/lt7182s.c
+++ b/drivers/hwmon/pmbus/lt7182s.c
@@ -192,4 +192,4 @@ module_i2c_driver(lt7182s_driver);
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
MODULE_DESCRIPTION("PMBus driver for Analog Devices LT7182S");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/ltc2978.c b/drivers/hwmon/pmbus/ltc2978.c
index a6eb4d4b5487..4c306943383a 100644
--- a/drivers/hwmon/pmbus/ltc2978.c
+++ b/drivers/hwmon/pmbus/ltc2978.c
@@ -952,4 +952,4 @@ module_i2c_driver(ltc2978_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for LTC2978 and compatible chips");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/ltc3815.c b/drivers/hwmon/pmbus/ltc3815.c
index f58a8cedb0d7..824c16a75e2c 100644
--- a/drivers/hwmon/pmbus/ltc3815.c
+++ b/drivers/hwmon/pmbus/ltc3815.c
@@ -208,4 +208,4 @@ module_i2c_driver(ltc3815_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for LTC3815");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/max15301.c b/drivers/hwmon/pmbus/max15301.c
index f5367a7bc0f5..50dfd477772f 100644
--- a/drivers/hwmon/pmbus/max15301.c
+++ b/drivers/hwmon/pmbus/max15301.c
@@ -97,4 +97,4 @@ module_i2c_driver(max15301_driver);
MODULE_AUTHOR("Erik Rosen <erik.rosen@metormote.com>");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX15301");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/max16064.c b/drivers/hwmon/pmbus/max16064.c
index 98e2b5dd5841..eb84915c2a83 100644
--- a/drivers/hwmon/pmbus/max16064.c
+++ b/drivers/hwmon/pmbus/max16064.c
@@ -111,4 +111,4 @@ module_i2c_driver(max16064_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX16064");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/max16601.c b/drivers/hwmon/pmbus/max16601.c
index 3ab219504600..d696e506aafb 100644
--- a/drivers/hwmon/pmbus/max16601.c
+++ b/drivers/hwmon/pmbus/max16601.c
@@ -366,4 +366,4 @@ module_i2c_driver(max16601_driver);
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX16601");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/max20730.c b/drivers/hwmon/pmbus/max20730.c
index d56ec24764fd..95869d198ecf 100644
--- a/drivers/hwmon/pmbus/max20730.c
+++ b/drivers/hwmon/pmbus/max20730.c
@@ -787,4 +787,4 @@ module_i2c_driver(max20730_driver);
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX20710 / MAX20730 / MAX20734 / MAX20743");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/max20751.c b/drivers/hwmon/pmbus/max20751.c
index 8f23c1eb559e..ac8c43122133 100644
--- a/drivers/hwmon/pmbus/max20751.c
+++ b/drivers/hwmon/pmbus/max20751.c
@@ -51,4 +51,4 @@ module_i2c_driver(max20751_driver);
MODULE_AUTHOR("Guenter Roeck <linux@roeck-us.net>");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX20751");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/max31785.c b/drivers/hwmon/pmbus/max31785.c
index 09218dba8965..1f94d38a1637 100644
--- a/drivers/hwmon/pmbus/max31785.c
+++ b/drivers/hwmon/pmbus/max31785.c
@@ -549,4 +549,4 @@ module_i2c_driver(max31785_driver);
MODULE_AUTHOR("Andrew Jeffery <andrew@aj.id.au>");
MODULE_DESCRIPTION("PMBus driver for the Maxim MAX31785");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/max34440.c b/drivers/hwmon/pmbus/max34440.c
index fe7f6b1b0985..c9dda33831ff 100644
--- a/drivers/hwmon/pmbus/max34440.c
+++ b/drivers/hwmon/pmbus/max34440.c
@@ -529,4 +529,4 @@ module_i2c_driver(max34440_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/max8688.c b/drivers/hwmon/pmbus/max8688.c
index 5d5b6aeefa80..b3a2a7492bbf 100644
--- a/drivers/hwmon/pmbus/max8688.c
+++ b/drivers/hwmon/pmbus/max8688.c
@@ -191,4 +191,4 @@ module_i2c_driver(max8688_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mp2856.c b/drivers/hwmon/pmbus/mp2856.c
index 41bb86667091..e83c70a3583f 100644
--- a/drivers/hwmon/pmbus/mp2856.c
+++ b/drivers/hwmon/pmbus/mp2856.c
@@ -463,4 +463,4 @@ module_i2c_driver(mp2856_driver);
MODULE_AUTHOR("Peter Yin <peter.yin@quantatw.com>");
MODULE_DESCRIPTION("PMBus driver for MPS MP2856/MP2857 device");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mp2888.c b/drivers/hwmon/pmbus/mp2888.c
index 3b45f126b611..772a623ca7d0 100644
--- a/drivers/hwmon/pmbus/mp2888.c
+++ b/drivers/hwmon/pmbus/mp2888.c
@@ -404,4 +404,4 @@ module_i2c_driver(mp2888_driver);
MODULE_AUTHOR("Vadim Pasternak <vadimp@nvidia.com>");
MODULE_DESCRIPTION("PMBus driver for MPS MP2888 device");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mp2891.c b/drivers/hwmon/pmbus/mp2891.c
index 94ab4ae5fba0..f8f4c91ec23c 100644
--- a/drivers/hwmon/pmbus/mp2891.c
+++ b/drivers/hwmon/pmbus/mp2891.c
@@ -597,4 +597,4 @@ module_i2c_driver(mp2891_driver);
MODULE_AUTHOR("Noah Wang <noahwang.wang@outlook.com>");
MODULE_DESCRIPTION("PMBus driver for MPS MP2891");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mp2975.c b/drivers/hwmon/pmbus/mp2975.c
index 280bb12f762c..c31982d85196 100644
--- a/drivers/hwmon/pmbus/mp2975.c
+++ b/drivers/hwmon/pmbus/mp2975.c
@@ -1101,4 +1101,4 @@ module_i2c_driver(mp2975_driver);
MODULE_AUTHOR("Vadim Pasternak <vadimp@nvidia.com>");
MODULE_DESCRIPTION("PMBus driver for MPS MP2975 device");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mp2993.c b/drivers/hwmon/pmbus/mp2993.c
index 63691dac2281..81c84fc8ed47 100644
--- a/drivers/hwmon/pmbus/mp2993.c
+++ b/drivers/hwmon/pmbus/mp2993.c
@@ -258,4 +258,4 @@ module_i2c_driver(mp2993_driver);
MODULE_AUTHOR("Noah Wang <noahwang.wang@outlook.com>");
MODULE_DESCRIPTION("PMBus driver for MPS MP2993");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mp5023.c b/drivers/hwmon/pmbus/mp5023.c
index 21acb7fd9a1a..c466d67e9a8f 100644
--- a/drivers/hwmon/pmbus/mp5023.c
+++ b/drivers/hwmon/pmbus/mp5023.c
@@ -64,4 +64,4 @@ module_i2c_driver(mp5023_driver);
MODULE_AUTHOR("Howard Chiu <howard.chiu@quantatw.com>");
MODULE_DESCRIPTION("PMBus driver for MPS MP5023 HSC");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mp5920.c b/drivers/hwmon/pmbus/mp5920.c
index f6d7527ade7d..319ae2721bcf 100644
--- a/drivers/hwmon/pmbus/mp5920.c
+++ b/drivers/hwmon/pmbus/mp5920.c
@@ -87,4 +87,4 @@ MODULE_AUTHOR("Tony Ao <tony_ao@wiwynn.com>");
MODULE_AUTHOR("Alex Vdovydchenko <xzeol@yahoo.com>");
MODULE_DESCRIPTION("PMBus driver for MP5920 HSC");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mp5990.c b/drivers/hwmon/pmbus/mp5990.c
index 5d1d5eac89da..4ce381a39480 100644
--- a/drivers/hwmon/pmbus/mp5990.c
+++ b/drivers/hwmon/pmbus/mp5990.c
@@ -176,4 +176,4 @@ module_i2c_driver(mp5990_driver);
MODULE_AUTHOR("Peter Yin <peter.yin@quantatw.com>");
MODULE_DESCRIPTION("PMBus driver for MP5990 HSC");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mp9941.c b/drivers/hwmon/pmbus/mp9941.c
index 8ab5fc4d4092..42ca6748777a 100644
--- a/drivers/hwmon/pmbus/mp9941.c
+++ b/drivers/hwmon/pmbus/mp9941.c
@@ -316,4 +316,4 @@ module_i2c_driver(mp9941_driver);
MODULE_AUTHOR("Noah Wang <noahwang.wang@outlook.com>");
MODULE_DESCRIPTION("PMBus driver for MPS MP9941");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mpq7932.c b/drivers/hwmon/pmbus/mpq7932.c
index 2dcb6da853bd..c1e2d0cb2fd0 100644
--- a/drivers/hwmon/pmbus/mpq7932.c
+++ b/drivers/hwmon/pmbus/mpq7932.c
@@ -164,4 +164,4 @@ module_i2c_driver(mpq7932_regulator_driver);
MODULE_AUTHOR("Saravanan Sekar <saravanan@linumiz.com>");
MODULE_DESCRIPTION("MPQ7932 PMIC regulator driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/mpq8785.c b/drivers/hwmon/pmbus/mpq8785.c
index 0d16491cd770..331c274ca892 100644
--- a/drivers/hwmon/pmbus/mpq8785.c
+++ b/drivers/hwmon/pmbus/mpq8785.c
@@ -87,4 +87,4 @@ module_i2c_driver(mpq8785_driver);
MODULE_AUTHOR("Charles Hsu <ythsu0511@gmail.com>");
MODULE_DESCRIPTION("PMBus driver for MPS MPQ8785");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/pim4328.c b/drivers/hwmon/pmbus/pim4328.c
index 31d9ae06379a..aa98284bbdd8 100644
--- a/drivers/hwmon/pmbus/pim4328.c
+++ b/drivers/hwmon/pmbus/pim4328.c
@@ -230,4 +230,4 @@ module_i2c_driver(pim4328_driver);
MODULE_AUTHOR("Erik Rosen <erik.rosen@metormote.com>");
MODULE_DESCRIPTION("PMBus driver for PIM4006, PIM4328, PIM4820 power interface modules");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/pli1209bc.c b/drivers/hwmon/pmbus/pli1209bc.c
index 178e0cdb7887..569b61dc1a32 100644
--- a/drivers/hwmon/pmbus/pli1209bc.c
+++ b/drivers/hwmon/pmbus/pli1209bc.c
@@ -145,4 +145,4 @@ module_i2c_driver(pli1209bc_driver);
MODULE_AUTHOR("Marcello Sylvester Bauer <sylv@sylv.io>");
MODULE_DESCRIPTION("PMBus driver for Vicor PLI1209BC");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/pm6764tr.c b/drivers/hwmon/pmbus/pm6764tr.c
index 23f15b608dcf..c96c0aecb920 100644
--- a/drivers/hwmon/pmbus/pm6764tr.c
+++ b/drivers/hwmon/pmbus/pm6764tr.c
@@ -73,4 +73,4 @@ module_i2c_driver(pm6764tr_driver);
MODULE_AUTHOR("Charles Hsu");
MODULE_DESCRIPTION("PMBus driver for ST PM6764TR");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/pmbus.c b/drivers/hwmon/pmbus/pmbus.c
index ec40c5c59954..77cf268e7d2d 100644
--- a/drivers/hwmon/pmbus/pmbus.c
+++ b/drivers/hwmon/pmbus/pmbus.c
@@ -261,4 +261,4 @@ module_i2c_driver(pmbus_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("Generic PMBus driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/pmbus_core.c b/drivers/hwmon/pmbus/pmbus_core.c
index a0109296a994..a1375cb6b648 100644
--- a/drivers/hwmon/pmbus/pmbus_core.c
+++ b/drivers/hwmon/pmbus/pmbus_core.c
@@ -150,7 +150,7 @@ void pmbus_clear_cache(struct i2c_client *client)
for (sensor = data->sensors; sensor; sensor = sensor->next)
sensor->data = -ENODATA;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_clear_cache, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_clear_cache, "PMBUS");
void pmbus_set_update(struct i2c_client *client, u8 reg, bool update)
{
@@ -161,7 +161,7 @@ void pmbus_set_update(struct i2c_client *client, u8 reg, bool update)
if (sensor->reg == reg)
sensor->update = update;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_set_update, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_set_update, "PMBUS");
/* Some chips need a delay between accesses. */
static void pmbus_wait(struct i2c_client *client)
@@ -236,7 +236,7 @@ int pmbus_set_page(struct i2c_client *client, int page, int phase)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_set_page, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_set_page, "PMBUS");
int pmbus_write_byte(struct i2c_client *client, int page, u8 value)
{
@@ -252,7 +252,7 @@ int pmbus_write_byte(struct i2c_client *client, int page, u8 value)
return rv;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_write_byte, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_write_byte, "PMBUS");
/*
* _pmbus_write_byte() is similar to pmbus_write_byte(), but checks if
@@ -287,7 +287,7 @@ int pmbus_write_word_data(struct i2c_client *client, int page, u8 reg,
return rv;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_write_word_data, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_write_word_data, "PMBUS");
static int pmbus_write_virt_reg(struct i2c_client *client, int page, int reg,
@@ -393,7 +393,7 @@ int pmbus_update_fan(struct i2c_client *client, int page, int id,
return _pmbus_write_word_data(client, page,
pmbus_fan_command_registers[id], command);
}
-EXPORT_SYMBOL_NS_GPL(pmbus_update_fan, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_update_fan, "PMBUS");
int pmbus_read_word_data(struct i2c_client *client, int page, int phase, u8 reg)
{
@@ -409,7 +409,7 @@ int pmbus_read_word_data(struct i2c_client *client, int page, int phase, u8 reg)
return rv;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_read_word_data, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_read_word_data, "PMBUS");
static int pmbus_read_virt_reg(struct i2c_client *client, int page, int reg)
{
@@ -472,7 +472,7 @@ int pmbus_read_byte_data(struct i2c_client *client, int page, u8 reg)
return rv;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_read_byte_data, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_read_byte_data, "PMBUS");
int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, u8 value)
{
@@ -488,7 +488,7 @@ int pmbus_write_byte_data(struct i2c_client *client, int page, u8 reg, u8 value)
return rv;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_write_byte_data, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_write_byte_data, "PMBUS");
int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
u8 mask, u8 value)
@@ -507,7 +507,7 @@ int pmbus_update_byte_data(struct i2c_client *client, int page, u8 reg,
return rv;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_update_byte_data, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_update_byte_data, "PMBUS");
static int pmbus_read_block_data(struct i2c_client *client, int page, u8 reg,
char *data_buf)
@@ -578,14 +578,14 @@ int pmbus_get_fan_rate_device(struct i2c_client *client, int page, int id,
{
return pmbus_get_fan_rate(client, page, id, mode, false);
}
-EXPORT_SYMBOL_NS_GPL(pmbus_get_fan_rate_device, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_get_fan_rate_device, "PMBUS");
int pmbus_get_fan_rate_cached(struct i2c_client *client, int page, int id,
enum pmbus_fan_mode mode)
{
return pmbus_get_fan_rate(client, page, id, mode, true);
}
-EXPORT_SYMBOL_NS_GPL(pmbus_get_fan_rate_cached, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_get_fan_rate_cached, "PMBUS");
static void pmbus_clear_fault_page(struct i2c_client *client, int page)
{
@@ -600,7 +600,7 @@ void pmbus_clear_faults(struct i2c_client *client)
for (i = 0; i < data->info->pages; i++)
pmbus_clear_fault_page(client, i);
}
-EXPORT_SYMBOL_NS_GPL(pmbus_clear_faults, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_clear_faults, "PMBUS");
static int pmbus_check_status_cml(struct i2c_client *client)
{
@@ -655,13 +655,13 @@ bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg)
{
return pmbus_check_register(client, _pmbus_read_byte_data, page, reg);
}
-EXPORT_SYMBOL_NS_GPL(pmbus_check_byte_register, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_check_byte_register, "PMBUS");
bool pmbus_check_word_register(struct i2c_client *client, int page, int reg)
{
return pmbus_check_register(client, __pmbus_read_word_data, page, reg);
}
-EXPORT_SYMBOL_NS_GPL(pmbus_check_word_register, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_check_word_register, "PMBUS");
static bool __maybe_unused pmbus_check_block_register(struct i2c_client *client,
int page, int reg)
@@ -685,7 +685,7 @@ const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client)
return data->info;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_get_driver_info, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_get_driver_info, "PMBUS");
static int pmbus_get_status(struct i2c_client *client, int page, int reg)
{
@@ -3217,7 +3217,7 @@ const struct regulator_ops pmbus_regulator_ops = {
.set_voltage = pmbus_regulator_set_voltage,
.list_voltage = pmbus_regulator_list_voltage,
};
-EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_regulator_ops, "PMBUS");
static int pmbus_regulator_register(struct pmbus_data *data)
{
@@ -3743,7 +3743,7 @@ int pmbus_do_probe(struct i2c_client *client, struct pmbus_driver_info *info)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_do_probe, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_do_probe, "PMBUS");
struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client)
{
@@ -3751,7 +3751,7 @@ struct dentry *pmbus_get_debugfs_dir(struct i2c_client *client)
return data->debugfs;
}
-EXPORT_SYMBOL_NS_GPL(pmbus_get_debugfs_dir, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_get_debugfs_dir, "PMBUS");
int pmbus_lock_interruptible(struct i2c_client *client)
{
@@ -3759,7 +3759,7 @@ int pmbus_lock_interruptible(struct i2c_client *client)
return mutex_lock_interruptible(&data->update_lock);
}
-EXPORT_SYMBOL_NS_GPL(pmbus_lock_interruptible, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_lock_interruptible, "PMBUS");
void pmbus_unlock(struct i2c_client *client)
{
@@ -3767,7 +3767,7 @@ void pmbus_unlock(struct i2c_client *client)
mutex_unlock(&data->update_lock);
}
-EXPORT_SYMBOL_NS_GPL(pmbus_unlock, PMBUS);
+EXPORT_SYMBOL_NS_GPL(pmbus_unlock, "PMBUS");
static int __init pmbus_core_init(void)
{
diff --git a/drivers/hwmon/pmbus/pxe1610.c b/drivers/hwmon/pmbus/pxe1610.c
index 5ac476d3cdd2..6a4a978eca7e 100644
--- a/drivers/hwmon/pmbus/pxe1610.c
+++ b/drivers/hwmon/pmbus/pxe1610.c
@@ -148,4 +148,4 @@ module_i2c_driver(pxe1610_driver);
MODULE_AUTHOR("Vijay Khemka <vijaykhemka@fb.com>");
MODULE_DESCRIPTION("PMBus driver for Infineon PXE1610, PXE1110 and PXM1310");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/q54sj108a2.c b/drivers/hwmon/pmbus/q54sj108a2.c
index a235c1cdf4fe..4d7086d83aa3 100644
--- a/drivers/hwmon/pmbus/q54sj108a2.c
+++ b/drivers/hwmon/pmbus/q54sj108a2.c
@@ -421,4 +421,4 @@ module_i2c_driver(q54sj108a2_driver);
MODULE_AUTHOR("Xiao.Ma <xiao.mx.ma@deltaww.com>");
MODULE_DESCRIPTION("PMBus driver for Delta Q54SJ108A2 series modules");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/stpddc60.c b/drivers/hwmon/pmbus/stpddc60.c
index 34d0f06f4845..5cb905ed8ae5 100644
--- a/drivers/hwmon/pmbus/stpddc60.c
+++ b/drivers/hwmon/pmbus/stpddc60.c
@@ -246,4 +246,4 @@ module_i2c_driver(stpddc60_driver);
MODULE_AUTHOR("Erik Rosen <erik.rosen@metormote.com>");
MODULE_DESCRIPTION("PMBus driver for ST STPDDC60");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/tda38640.c b/drivers/hwmon/pmbus/tda38640.c
index 044d5fbdf9eb..07fe58c24485 100644
--- a/drivers/hwmon/pmbus/tda38640.c
+++ b/drivers/hwmon/pmbus/tda38640.c
@@ -221,4 +221,4 @@ module_i2c_driver(tda38640_driver);
MODULE_AUTHOR("Patrick Rudolph <patrick.rudolph@9elements.com>");
MODULE_DESCRIPTION("PMBus driver for Infineon TDA38640");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/tps40422.c b/drivers/hwmon/pmbus/tps40422.c
index d99b9850ea36..7c9fedaa068c 100644
--- a/drivers/hwmon/pmbus/tps40422.c
+++ b/drivers/hwmon/pmbus/tps40422.c
@@ -51,4 +51,4 @@ module_i2c_driver(tps40422_driver);
MODULE_AUTHOR("Zhu Laiwen <richard.zhu@nsn.com>");
MODULE_DESCRIPTION("PMBus driver for TI TPS40422");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/tps53679.c b/drivers/hwmon/pmbus/tps53679.c
index 5c9466244d70..63524dff5e75 100644
--- a/drivers/hwmon/pmbus/tps53679.c
+++ b/drivers/hwmon/pmbus/tps53679.c
@@ -308,4 +308,4 @@ module_i2c_driver(tps53679_driver);
MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
MODULE_DESCRIPTION("PMBus driver for Texas Instruments TPS53679");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/tps546d24.c b/drivers/hwmon/pmbus/tps546d24.c
index 520ca37269f7..44d7a6df1dbd 100644
--- a/drivers/hwmon/pmbus/tps546d24.c
+++ b/drivers/hwmon/pmbus/tps546d24.c
@@ -68,4 +68,4 @@ module_i2c_driver(tps546d24_driver);
MODULE_AUTHOR("Duke Du <dukedu83@gmail.com>");
MODULE_DESCRIPTION("PMBus driver for TI tps546d24");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/ucd9000.c b/drivers/hwmon/pmbus/ucd9000.c
index 5d3d1773bf52..9b0eadc81a2e 100644
--- a/drivers/hwmon/pmbus/ucd9000.c
+++ b/drivers/hwmon/pmbus/ucd9000.c
@@ -642,4 +642,4 @@ module_i2c_driver(ucd9000_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for TI UCD90xxx");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/ucd9200.c b/drivers/hwmon/pmbus/ucd9200.c
index 7920d1c06df0..f68adaf4a110 100644
--- a/drivers/hwmon/pmbus/ucd9200.c
+++ b/drivers/hwmon/pmbus/ucd9200.c
@@ -209,4 +209,4 @@ module_i2c_driver(ucd9200_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for TI UCD922x, UCD924x");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/xdp710.c b/drivers/hwmon/pmbus/xdp710.c
index dd107e83f612..660bbfe16e1e 100644
--- a/drivers/hwmon/pmbus/xdp710.c
+++ b/drivers/hwmon/pmbus/xdp710.c
@@ -128,4 +128,4 @@ module_i2c_driver(xdp710_driver);
MODULE_AUTHOR("Peter Yin <peter.yin@quantatw.com>");
MODULE_DESCRIPTION("PMBus driver for XDP710 HSC");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/xdpe12284.c b/drivers/hwmon/pmbus/xdpe12284.c
index facb1201aa43..f3aa6339d60d 100644
--- a/drivers/hwmon/pmbus/xdpe12284.c
+++ b/drivers/hwmon/pmbus/xdpe12284.c
@@ -194,4 +194,4 @@ module_i2c_driver(xdpe122_driver);
MODULE_AUTHOR("Vadim Pasternak <vadimp@mellanox.com>");
MODULE_DESCRIPTION("PMBus driver for Infineon XDPE122 family");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/xdpe152c4.c b/drivers/hwmon/pmbus/xdpe152c4.c
index 7f3b31d4f033..67a3d5fe1daf 100644
--- a/drivers/hwmon/pmbus/xdpe152c4.c
+++ b/drivers/hwmon/pmbus/xdpe152c4.c
@@ -72,4 +72,4 @@ module_i2c_driver(xdpe152_driver);
MODULE_AUTHOR("Greg Schwendimann <greg.schwendimann@infineon.com>");
MODULE_DESCRIPTION("PMBus driver for Infineon XDPE152 family");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/pmbus/zl6100.c b/drivers/hwmon/pmbus/zl6100.c
index 7920a16203e1..97be69630cfb 100644
--- a/drivers/hwmon/pmbus/zl6100.c
+++ b/drivers/hwmon/pmbus/zl6100.c
@@ -420,4 +420,4 @@ module_i2c_driver(zl6100_driver);
MODULE_AUTHOR("Guenter Roeck");
MODULE_DESCRIPTION("PMBus driver for ZL6100 and compatibles");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PMBUS);
+MODULE_IMPORT_NS("PMBUS");
diff --git a/drivers/hwmon/tmp513.c b/drivers/hwmon/tmp513.c
index 926d28cd3fab..1c2cb12071b8 100644
--- a/drivers/hwmon/tmp513.c
+++ b/drivers/hwmon/tmp513.c
@@ -182,7 +182,7 @@ struct tmp51x_data {
struct regmap *regmap;
};
-// Set the shift based on the gain 8=4, 4=3, 2=2, 1=1
+// Set the shift based on the gain: 8 -> 1, 4 -> 2, 2 -> 3, 1 -> 4
static inline u8 tmp51x_get_pga_shift(struct tmp51x_data *data)
{
return 5 - ffs(data->pga_gain);
@@ -204,7 +204,9 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
* 2's complement number shifted by one to four depending
* on the pga gain setting. 1lsb = 10uV
*/
- *val = sign_extend32(regval, 17 - tmp51x_get_pga_shift(data));
+ *val = sign_extend32(regval,
+ reg == TMP51X_SHUNT_CURRENT_RESULT ?
+ 16 - tmp51x_get_pga_shift(data) : 15);
*val = DIV_ROUND_CLOSEST(*val * 10 * MILLI, data->shunt_uohms);
break;
case TMP51X_BUS_VOLTAGE_RESULT:
@@ -220,7 +222,7 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
break;
case TMP51X_BUS_CURRENT_RESULT:
// Current = (ShuntVoltage * CalibrationRegister) / 4096
- *val = sign_extend32(regval, 16) * data->curr_lsb_ua;
+ *val = sign_extend32(regval, 15) * (long)data->curr_lsb_ua;
*val = DIV_ROUND_CLOSEST(*val, MILLI);
break;
case TMP51X_LOCAL_TEMP_RESULT:
@@ -232,7 +234,7 @@ static int tmp51x_get_value(struct tmp51x_data *data, u8 reg, u8 pos,
case TMP51X_REMOTE_TEMP_LIMIT_2:
case TMP513_REMOTE_TEMP_LIMIT_3:
// 1lsb = 0.0625 degrees centigrade
- *val = sign_extend32(regval, 16) >> TMP51X_TEMP_SHIFT;
+ *val = sign_extend32(regval, 15) >> TMP51X_TEMP_SHIFT;
*val = DIV_ROUND_CLOSEST(*val * 625, 10);
break;
case TMP51X_N_FACTOR_AND_HYST_1:
diff --git a/drivers/hwspinlock/u8500_hsem.c b/drivers/hwspinlock/u8500_hsem.c
index 1edca1092f29..5a2d8c3e0d80 100644
--- a/drivers/hwspinlock/u8500_hsem.c
+++ b/drivers/hwspinlock/u8500_hsem.c
@@ -131,7 +131,7 @@ static void u8500_hsem_remove(struct platform_device *pdev)
static struct platform_driver u8500_hsem_driver = {
.probe = u8500_hsem_probe,
- .remove_new = u8500_hsem_remove,
+ .remove = u8500_hsem_remove,
.driver = {
.name = "u8500_hsem",
},
diff --git a/drivers/hwtracing/coresight/coresight-catu.c b/drivers/hwtracing/coresight/coresight-catu.c
index bfea880d6dfb..275cc0d9f505 100644
--- a/drivers/hwtracing/coresight/coresight-catu.c
+++ b/drivers/hwtracing/coresight/coresight-catu.c
@@ -689,7 +689,7 @@ MODULE_DEVICE_TABLE(acpi, catu_acpi_ids);
static struct platform_driver catu_platform_driver = {
.probe = catu_platform_probe,
- .remove_new = catu_platform_remove,
+ .remove = catu_platform_remove,
.driver = {
.name = "coresight-catu-platform",
.acpi_match_table = ACPI_PTR(catu_acpi_ids),
diff --git a/drivers/hwtracing/coresight/coresight-cpu-debug.c b/drivers/hwtracing/coresight/coresight-cpu-debug.c
index 75962dae9aa1..342c3aaf414d 100644
--- a/drivers/hwtracing/coresight/coresight-cpu-debug.c
+++ b/drivers/hwtracing/coresight/coresight-cpu-debug.c
@@ -763,7 +763,7 @@ static const struct dev_pm_ops debug_dev_pm_ops = {
static struct platform_driver debug_platform_driver = {
.probe = debug_platform_probe,
- .remove_new = debug_platform_remove,
+ .remove = debug_platform_remove,
.driver = {
.name = "coresight-debug-platform",
.acpi_match_table = ACPI_PTR(debug_platform_ids),
diff --git a/drivers/hwtracing/coresight/coresight-dummy.c b/drivers/hwtracing/coresight/coresight-dummy.c
index bb85fa663ffc..02ef2b945a0c 100644
--- a/drivers/hwtracing/coresight/coresight-dummy.c
+++ b/drivers/hwtracing/coresight/coresight-dummy.c
@@ -144,7 +144,7 @@ static const struct of_device_id dummy_match[] = {
static struct platform_driver dummy_driver = {
.probe = dummy_probe,
- .remove_new = dummy_remove,
+ .remove = dummy_remove,
.driver = {
.name = "coresight-dummy",
.of_match_table = dummy_match,
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 66d44a404ad0..dd8c74f893db 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -2399,7 +2399,7 @@ MODULE_DEVICE_TABLE(acpi, etm4x_acpi_ids);
static struct platform_driver etm4_platform_driver = {
.probe = etm4_probe_platform_dev,
- .remove_new = etm4_remove_platform_dev,
+ .remove = etm4_remove_platform_dev,
.driver = {
.name = "coresight-etm4x",
.of_match_table = etm4_sysreg_match,
diff --git a/drivers/hwtracing/coresight/coresight-funnel.c b/drivers/hwtracing/coresight/coresight-funnel.c
index 5a819c8970fb..33efe1acbef7 100644
--- a/drivers/hwtracing/coresight/coresight-funnel.c
+++ b/drivers/hwtracing/coresight/coresight-funnel.c
@@ -377,7 +377,7 @@ MODULE_DEVICE_TABLE(acpi, funnel_acpi_ids);
static struct platform_driver funnel_driver = {
.probe = funnel_platform_probe,
- .remove_new = funnel_platform_remove,
+ .remove = funnel_platform_remove,
.driver = {
.name = "coresight-funnel",
/* THIS_MODULE is taken care of by platform_driver_register() */
diff --git a/drivers/hwtracing/coresight/coresight-replicator.c b/drivers/hwtracing/coresight/coresight-replicator.c
index 3e55be9c8418..0fba87de6d1a 100644
--- a/drivers/hwtracing/coresight/coresight-replicator.c
+++ b/drivers/hwtracing/coresight/coresight-replicator.c
@@ -389,7 +389,7 @@ MODULE_DEVICE_TABLE(acpi, replicator_acpi_ids);
static struct platform_driver replicator_driver = {
.probe = replicator_platform_probe,
- .remove_new = replicator_platform_remove,
+ .remove = replicator_platform_remove,
.driver = {
.name = "coresight-replicator",
/* THIS_MODULE is taken care of by platform_driver_register() */
diff --git a/drivers/hwtracing/coresight/coresight-stm.c b/drivers/hwtracing/coresight/coresight-stm.c
index cb3e04755c99..b581a30a1cd9 100644
--- a/drivers/hwtracing/coresight/coresight-stm.c
+++ b/drivers/hwtracing/coresight/coresight-stm.c
@@ -1036,7 +1036,7 @@ MODULE_DEVICE_TABLE(acpi, stm_acpi_ids);
static struct platform_driver stm_platform_driver = {
.probe = stm_platform_probe,
- .remove_new = stm_platform_remove,
+ .remove = stm_platform_remove,
.driver = {
.name = "coresight-stm-platform",
.acpi_match_table = ACPI_PTR(stm_acpi_ids),
diff --git a/drivers/hwtracing/coresight/coresight-tmc-core.c b/drivers/hwtracing/coresight/coresight-tmc-core.c
index 3a482fd2cb22..e9876252a789 100644
--- a/drivers/hwtracing/coresight/coresight-tmc-core.c
+++ b/drivers/hwtracing/coresight/coresight-tmc-core.c
@@ -730,7 +730,7 @@ MODULE_DEVICE_TABLE(acpi, tmc_acpi_ids);
static struct platform_driver tmc_platform_driver = {
.probe = tmc_platform_probe,
- .remove_new = tmc_platform_remove,
+ .remove = tmc_platform_remove,
.driver = {
.name = "coresight-tmc-platform",
.acpi_match_table = ACPI_PTR(tmc_acpi_ids),
diff --git a/drivers/hwtracing/coresight/coresight-tpiu.c b/drivers/hwtracing/coresight/coresight-tpiu.c
index b048e146fbb1..97ef36f03ec2 100644
--- a/drivers/hwtracing/coresight/coresight-tpiu.c
+++ b/drivers/hwtracing/coresight/coresight-tpiu.c
@@ -307,7 +307,7 @@ MODULE_DEVICE_TABLE(acpi, tpiu_acpi_ids);
static struct platform_driver tpiu_platform_driver = {
.probe = tpiu_platform_probe,
- .remove_new = tpiu_platform_remove,
+ .remove = tpiu_platform_remove,
.driver = {
.name = "coresight-tpiu-platform",
.acpi_match_table = ACPI_PTR(tpiu_acpi_ids),
diff --git a/drivers/hwtracing/coresight/coresight-trbe.c b/drivers/hwtracing/coresight/coresight-trbe.c
index 96a32b213669..919804b12a67 100644
--- a/drivers/hwtracing/coresight/coresight-trbe.c
+++ b/drivers/hwtracing/coresight/coresight-trbe.c
@@ -1562,7 +1562,7 @@ static struct platform_driver arm_trbe_driver = {
.suppress_bind_attrs = true,
},
.probe = arm_trbe_device_probe,
- .remove_new = arm_trbe_device_remove,
+ .remove = arm_trbe_device_remove,
};
static int __init arm_trbe_init(void)
diff --git a/drivers/hwtracing/coresight/ultrasoc-smb.c b/drivers/hwtracing/coresight/ultrasoc-smb.c
index ef7f560f0ffa..dc3c9504dd7c 100644
--- a/drivers/hwtracing/coresight/ultrasoc-smb.c
+++ b/drivers/hwtracing/coresight/ultrasoc-smb.c
@@ -600,7 +600,7 @@ static struct platform_driver smb_driver = {
.suppress_bind_attrs = true,
},
.probe = smb_probe,
- .remove_new = smb_remove,
+ .remove = smb_remove,
};
module_platform_driver(smb_driver);
diff --git a/drivers/hwtracing/intel_th/acpi.c b/drivers/hwtracing/intel_th/acpi.c
index 503620e9fd10..d229324978bd 100644
--- a/drivers/hwtracing/intel_th/acpi.c
+++ b/drivers/hwtracing/intel_th/acpi.c
@@ -69,7 +69,7 @@ static void intel_th_acpi_remove(struct platform_device *pdev)
static struct platform_driver intel_th_acpi_driver = {
.probe = intel_th_acpi_probe,
- .remove_new = intel_th_acpi_remove,
+ .remove = intel_th_acpi_remove,
.driver = {
.name = DRIVER_NAME,
.acpi_match_table = intel_th_acpi_ids,
diff --git a/drivers/i2c/Makefile b/drivers/i2c/Makefile
index af95d6e7f004..d27de18de46f 100644
--- a/drivers/i2c/Makefile
+++ b/drivers/i2c/Makefile
@@ -9,6 +9,7 @@ i2c-core-y := i2c-core-base.o i2c-core-smbus.o
i2c-core-$(CONFIG_ACPI) += i2c-core-acpi.o
i2c-core-$(CONFIG_I2C_SLAVE) += i2c-core-slave.o
i2c-core-$(CONFIG_OF) += i2c-core-of.o
+i2c-core-$(CONFIG_OF_DYNAMIC) += i2c-core-of-prober.o
obj-$(CONFIG_I2C_SMBUS) += i2c-smbus.o
obj-$(CONFIG_I2C_CHARDEV) += i2c-dev.o
diff --git a/drivers/i2c/busses/i2c-amd-asf-plat.c b/drivers/i2c/busses/i2c-amd-asf-plat.c
index ba47df5370c7..7512614bf4b7 100644
--- a/drivers/i2c/busses/i2c-amd-asf-plat.c
+++ b/drivers/i2c/busses/i2c-amd-asf-plat.c
@@ -364,6 +364,6 @@ static struct platform_driver amd_asf_driver = {
};
module_platform_driver(amd_asf_driver);
-MODULE_IMPORT_NS(PIIX4_SMBUS);
+MODULE_IMPORT_NS("PIIX4_SMBUS");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("AMD Alert Standard Format Driver");
diff --git a/drivers/i2c/busses/i2c-cgbc.c b/drivers/i2c/busses/i2c-cgbc.c
index eba0b205de11..f054d167ac47 100644
--- a/drivers/i2c/busses/i2c-cgbc.c
+++ b/drivers/i2c/busses/i2c-cgbc.c
@@ -395,7 +395,7 @@ static struct platform_driver cgbc_i2c_driver = {
.name = "cgbc-i2c",
},
.probe = cgbc_i2c_probe,
- .remove_new = cgbc_i2c_remove,
+ .remove = cgbc_i2c_remove,
};
module_platform_driver(cgbc_i2c_driver);
diff --git a/drivers/i2c/busses/i2c-designware-common.c b/drivers/i2c/busses/i2c-designware-common.c
index 857783d458fb..183a35038eef 100644
--- a/drivers/i2c/busses/i2c-designware-common.c
+++ b/drivers/i2c/busses/i2c-designware-common.c
@@ -29,7 +29,7 @@
#include <linux/types.h>
#include <linux/units.h>
-#define DEFAULT_SYMBOL_NAMESPACE I2C_DW_COMMON
+#define DEFAULT_SYMBOL_NAMESPACE "I2C_DW_COMMON"
#include "i2c-designware-core.h"
diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c
index eca8998d640f..c8cbe5b1aeb1 100644
--- a/drivers/i2c/busses/i2c-designware-master.c
+++ b/drivers/i2c/busses/i2c-designware-master.c
@@ -22,7 +22,7 @@
#include <linux/regmap.h>
#include <linux/reset.h>
-#define DEFAULT_SYMBOL_NAMESPACE I2C_DW
+#define DEFAULT_SYMBOL_NAMESPACE "I2C_DW"
#include "i2c-designware-core.h"
@@ -1094,4 +1094,4 @@ EXPORT_SYMBOL_GPL(i2c_dw_probe_master);
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus master adapter");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(I2C_DW_COMMON);
+MODULE_IMPORT_NS("I2C_DW_COMMON");
diff --git a/drivers/i2c/busses/i2c-designware-pcidrv.c b/drivers/i2c/busses/i2c-designware-pcidrv.c
index 38265c3dc454..8e0267c7cc29 100644
--- a/drivers/i2c/busses/i2c-designware-pcidrv.c
+++ b/drivers/i2c/busses/i2c-designware-pcidrv.c
@@ -368,5 +368,5 @@ module_pci_driver(dw_i2c_driver);
MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
MODULE_DESCRIPTION("Synopsys DesignWare PCI I2C bus adapter");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(I2C_DW);
-MODULE_IMPORT_NS(I2C_DW_COMMON);
+MODULE_IMPORT_NS("I2C_DW");
+MODULE_IMPORT_NS("I2C_DW_COMMON");
diff --git a/drivers/i2c/busses/i2c-designware-platdrv.c b/drivers/i2c/busses/i2c-designware-platdrv.c
index 3e12aab6bf2d..d6e1ee935399 100644
--- a/drivers/i2c/busses/i2c-designware-platdrv.c
+++ b/drivers/i2c/busses/i2c-designware-platdrv.c
@@ -397,5 +397,5 @@ module_exit(dw_i2c_exit_driver);
MODULE_AUTHOR("Baruch Siach <baruch@tkos.co.il>");
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(I2C_DW);
-MODULE_IMPORT_NS(I2C_DW_COMMON);
+MODULE_IMPORT_NS("I2C_DW");
+MODULE_IMPORT_NS("I2C_DW_COMMON");
diff --git a/drivers/i2c/busses/i2c-designware-slave.c b/drivers/i2c/busses/i2c-designware-slave.c
index fad568e3523b..dc2b788eac5b 100644
--- a/drivers/i2c/busses/i2c-designware-slave.c
+++ b/drivers/i2c/busses/i2c-designware-slave.c
@@ -16,7 +16,7 @@
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
-#define DEFAULT_SYMBOL_NAMESPACE I2C_DW
+#define DEFAULT_SYMBOL_NAMESPACE "I2C_DW"
#include "i2c-designware-core.h"
@@ -282,4 +282,4 @@ EXPORT_SYMBOL_GPL(i2c_dw_probe_slave);
MODULE_AUTHOR("Luis Oliveira <lolivei@synopsys.com>");
MODULE_DESCRIPTION("Synopsys DesignWare I2C bus slave adapter");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(I2C_DW_COMMON);
+MODULE_IMPORT_NS("I2C_DW_COMMON");
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index f751d231ded8..5c9a8dfbc4a0 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -335,6 +335,7 @@ static const struct of_device_id i2c_imx_dt_ids[] = {
{ .compatible = "fsl,imx6sll-i2c", .data = &imx6_i2c_hwdata, },
{ .compatible = "fsl,imx6sx-i2c", .data = &imx6_i2c_hwdata, },
{ .compatible = "fsl,imx6ul-i2c", .data = &imx6_i2c_hwdata, },
+ { .compatible = "fsl,imx7d-i2c", .data = &imx6_i2c_hwdata, },
{ .compatible = "fsl,imx7s-i2c", .data = &imx6_i2c_hwdata, },
{ .compatible = "fsl,imx8mm-i2c", .data = &imx6_i2c_hwdata, },
{ .compatible = "fsl,imx8mn-i2c", .data = &imx6_i2c_hwdata, },
@@ -532,22 +533,20 @@ static void i2c_imx_dma_free(struct imx_i2c_struct *i2c_imx)
static int i2c_imx_bus_busy(struct imx_i2c_struct *i2c_imx, int for_busy, bool atomic)
{
+ bool multi_master = i2c_imx->multi_master;
unsigned long orig_jiffies = jiffies;
unsigned int temp;
- if (!i2c_imx->multi_master)
- return 0;
-
while (1) {
temp = imx_i2c_read_reg(i2c_imx, IMX_I2C_I2SR);
/* check for arbitration lost */
- if (temp & I2SR_IAL) {
+ if (multi_master && (temp & I2SR_IAL)) {
i2c_imx_clear_irq(i2c_imx, I2SR_IAL);
return -EAGAIN;
}
- if (for_busy && (temp & I2SR_IBB)) {
+ if (for_busy && (!multi_master || (temp & I2SR_IBB))) {
i2c_imx->stopped = 0;
break;
}
diff --git a/drivers/i2c/busses/i2c-ljca.c b/drivers/i2c/busses/i2c-ljca.c
index 1dc516ef0fdd..93274f0c2d72 100644
--- a/drivers/i2c/busses/i2c-ljca.c
+++ b/drivers/i2c/busses/i2c-ljca.c
@@ -340,4 +340,4 @@ MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>");
MODULE_AUTHOR("Lixu Zhang <lixu.zhang@intel.com>");
MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB-I2C driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(LJCA);
+MODULE_IMPORT_NS("LJCA");
diff --git a/drivers/i2c/busses/i2c-microchip-corei2c.c b/drivers/i2c/busses/i2c-microchip-corei2c.c
index d1543e7d8380..5db73429125c 100644
--- a/drivers/i2c/busses/i2c-microchip-corei2c.c
+++ b/drivers/i2c/busses/i2c-microchip-corei2c.c
@@ -93,27 +93,35 @@
* @base: pointer to register struct
* @dev: device reference
* @i2c_clk: clock reference for i2c input clock
+ * @msg_queue: pointer to the messages requiring sending
* @buf: pointer to msg buffer for easier use
* @msg_complete: xfer completion object
* @adapter: core i2c abstraction
* @msg_err: error code for completed message
* @bus_clk_rate: current i2c bus clock rate
* @isr_status: cached copy of local ISR status
+ * @total_num: total number of messages to be sent/received
+ * @current_num: index of the current message being sent/received
* @msg_len: number of bytes transferred in msg
* @addr: address of the current slave
+ * @restart_needed: whether or not a repeated start is required after current message
*/
struct mchp_corei2c_dev {
void __iomem *base;
struct device *dev;
struct clk *i2c_clk;
+ struct i2c_msg *msg_queue;
u8 *buf;
struct completion msg_complete;
struct i2c_adapter adapter;
int msg_err;
+ int total_num;
+ int current_num;
u32 bus_clk_rate;
u32 isr_status;
u16 msg_len;
u8 addr;
+ bool restart_needed;
};
static void mchp_corei2c_core_disable(struct mchp_corei2c_dev *idev)
@@ -222,6 +230,47 @@ static int mchp_corei2c_fill_tx(struct mchp_corei2c_dev *idev)
return 0;
}
+static void mchp_corei2c_next_msg(struct mchp_corei2c_dev *idev)
+{
+ struct i2c_msg *this_msg;
+ u8 ctrl;
+
+ if (idev->current_num >= idev->total_num) {
+ complete(&idev->msg_complete);
+ return;
+ }
+
+ /*
+ * If there's been an error, the isr needs to return control
+ * to the "main" part of the driver, so as not to keep sending
+ * messages once it completes and clears the SI bit.
+ */
+ if (idev->msg_err) {
+ complete(&idev->msg_complete);
+ return;
+ }
+
+ this_msg = idev->msg_queue++;
+
+ if (idev->current_num < (idev->total_num - 1)) {
+ struct i2c_msg *next_msg = idev->msg_queue;
+
+ idev->restart_needed = next_msg->flags & I2C_M_RD;
+ } else {
+ idev->restart_needed = false;
+ }
+
+ idev->addr = i2c_8bit_addr_from_msg(this_msg);
+ idev->msg_len = this_msg->len;
+ idev->buf = this_msg->buf;
+
+ ctrl = readb(idev->base + CORE_I2C_CTRL);
+ ctrl |= CTRL_STA;
+ writeb(ctrl, idev->base + CORE_I2C_CTRL);
+
+ idev->current_num++;
+}
+
static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
{
u32 status = idev->isr_status;
@@ -238,8 +287,6 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
ctrl &= ~CTRL_STA;
writeb(idev->addr, idev->base + CORE_I2C_DATA);
writeb(ctrl, idev->base + CORE_I2C_CTRL);
- if (idev->msg_len == 0)
- finished = true;
break;
case STATUS_M_ARB_LOST:
idev->msg_err = -EAGAIN;
@@ -247,10 +294,14 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
break;
case STATUS_M_SLAW_ACK:
case STATUS_M_TX_DATA_ACK:
- if (idev->msg_len > 0)
+ if (idev->msg_len > 0) {
mchp_corei2c_fill_tx(idev);
- else
- last_byte = true;
+ } else {
+ if (idev->restart_needed)
+ finished = true;
+ else
+ last_byte = true;
+ }
break;
case STATUS_M_TX_DATA_NACK:
case STATUS_M_SLAR_NACK:
@@ -287,7 +338,7 @@ static irqreturn_t mchp_corei2c_handle_isr(struct mchp_corei2c_dev *idev)
mchp_corei2c_stop(idev);
if (last_byte || finished)
- complete(&idev->msg_complete);
+ mchp_corei2c_next_msg(idev);
return IRQ_HANDLED;
}
@@ -311,21 +362,48 @@ static irqreturn_t mchp_corei2c_isr(int irq, void *_dev)
return ret;
}
-static int mchp_corei2c_xfer_msg(struct mchp_corei2c_dev *idev,
- struct i2c_msg *msg)
+static int mchp_corei2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
+ int num)
{
- u8 ctrl;
+ struct mchp_corei2c_dev *idev = i2c_get_adapdata(adap);
+ struct i2c_msg *this_msg = msgs;
unsigned long time_left;
+ u8 ctrl;
+
+ mchp_corei2c_core_enable(idev);
+
+ /*
+ * The isr controls the flow of a transfer, this info needs to be saved
+ * to a location that it can access the queue information from.
+ */
+ idev->restart_needed = false;
+ idev->msg_queue = msgs;
+ idev->total_num = num;
+ idev->current_num = 0;
- idev->addr = i2c_8bit_addr_from_msg(msg);
- idev->msg_len = msg->len;
- idev->buf = msg->buf;
+ /*
+ * But the first entry to the isr is triggered by the start in this
+ * function, so the first message needs to be "dequeued".
+ */
+ idev->addr = i2c_8bit_addr_from_msg(this_msg);
+ idev->msg_len = this_msg->len;
+ idev->buf = this_msg->buf;
idev->msg_err = 0;
- reinit_completion(&idev->msg_complete);
+ if (idev->total_num > 1) {
+ struct i2c_msg *next_msg = msgs + 1;
- mchp_corei2c_core_enable(idev);
+ idev->restart_needed = next_msg->flags & I2C_M_RD;
+ }
+ idev->current_num++;
+ idev->msg_queue++;
+
+ reinit_completion(&idev->msg_complete);
+
+ /*
+ * Send the first start to pass control to the isr
+ */
ctrl = readb(idev->base + CORE_I2C_CTRL);
ctrl |= CTRL_STA;
writeb(ctrl, idev->base + CORE_I2C_CTRL);
@@ -335,20 +413,8 @@ static int mchp_corei2c_xfer_msg(struct mchp_corei2c_dev *idev,
if (!time_left)
return -ETIMEDOUT;
- return idev->msg_err;
-}
-
-static int mchp_corei2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
- int num)
-{
- struct mchp_corei2c_dev *idev = i2c_get_adapdata(adap);
- int i, ret;
-
- for (i = 0; i < num; i++) {
- ret = mchp_corei2c_xfer_msg(idev, msgs++);
- if (ret)
- return ret;
- }
+ if (idev->msg_err)
+ return idev->msg_err;
return num;
}
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c
index efb33802804f..d2877e4cc28d 100644
--- a/drivers/i2c/busses/i2c-nomadik.c
+++ b/drivers/i2c/busses/i2c-nomadik.c
@@ -1075,6 +1075,7 @@ static const struct of_device_id nmk_i2c_eyeq_match_table[] = {
.compatible = "mobileye,eyeq6h-i2c",
.data = (void *)NMK_I2C_EYEQ_FLAG_32B_BUS,
},
+ { /* sentinel */ }
};
static int nmk_i2c_probe(struct amba_device *adev, const struct amba_id *id)
diff --git a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
index 9402fa3811c5..dd75916157f0 100644
--- a/drivers/i2c/busses/i2c-piix4.c
+++ b/drivers/i2c/busses/i2c-piix4.c
@@ -195,7 +195,7 @@ int piix4_sb800_region_request(struct device *dev, struct sb800_mmio_cfg *mmio_c
return 0;
}
-EXPORT_SYMBOL_NS_GPL(piix4_sb800_region_request, PIIX4_SMBUS);
+EXPORT_SYMBOL_NS_GPL(piix4_sb800_region_request, "PIIX4_SMBUS");
void piix4_sb800_region_release(struct device *dev, struct sb800_mmio_cfg *mmio_cfg)
{
@@ -208,7 +208,7 @@ void piix4_sb800_region_release(struct device *dev, struct sb800_mmio_cfg *mmio_
release_region(SB800_PIIX4_SMB_IDX, SB800_PIIX4_SMB_MAP_SIZE);
}
-EXPORT_SYMBOL_NS_GPL(piix4_sb800_region_release, PIIX4_SMBUS);
+EXPORT_SYMBOL_NS_GPL(piix4_sb800_region_release, "PIIX4_SMBUS");
static bool piix4_sb800_use_mmio(struct pci_dev *PIIX4_dev)
{
@@ -591,7 +591,7 @@ int piix4_transaction(struct i2c_adapter *piix4_adapter, unsigned short piix4_sm
inb_p(SMBHSTDAT1));
return result;
}
-EXPORT_SYMBOL_NS_GPL(piix4_transaction, PIIX4_SMBUS);
+EXPORT_SYMBOL_NS_GPL(piix4_transaction, "PIIX4_SMBUS");
/* Return negative errno on error. */
static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
@@ -767,7 +767,7 @@ int piix4_sb800_port_sel(u8 port, struct sb800_mmio_cfg *mmio_cfg)
return (smba_en_lo & piix4_port_mask_sb800);
}
-EXPORT_SYMBOL_NS_GPL(piix4_sb800_port_sel, PIIX4_SMBUS);
+EXPORT_SYMBOL_NS_GPL(piix4_sb800_port_sel, "PIIX4_SMBUS");
/*
* Handles access to multiple SMBus ports on the SB800.
diff --git a/drivers/i2c/busses/i2c-pnx.c b/drivers/i2c/busses/i2c-pnx.c
index d4d139b97513..9a1af5bbd604 100644
--- a/drivers/i2c/busses/i2c-pnx.c
+++ b/drivers/i2c/busses/i2c-pnx.c
@@ -95,7 +95,7 @@ enum {
static inline int wait_timeout(struct i2c_pnx_algo_data *data)
{
- long timeout = data->timeout;
+ long timeout = jiffies_to_msecs(data->timeout);
while (timeout > 0 &&
(ioread32(I2C_REG_STS(data)) & mstatus_active)) {
mdelay(1);
@@ -106,7 +106,7 @@ static inline int wait_timeout(struct i2c_pnx_algo_data *data)
static inline int wait_reset(struct i2c_pnx_algo_data *data)
{
- long timeout = data->timeout;
+ long timeout = jiffies_to_msecs(data->timeout);
while (timeout > 0 &&
(ioread32(I2C_REG_CTL(data)) & mcntrl_reset)) {
mdelay(1);
diff --git a/drivers/i2c/busses/i2c-riic.c b/drivers/i2c/busses/i2c-riic.c
index c218f73c3650..9264adc97ca9 100644
--- a/drivers/i2c/busses/i2c-riic.c
+++ b/drivers/i2c/busses/i2c-riic.c
@@ -352,7 +352,7 @@ static int riic_init_hw(struct riic_dev *riic)
if (brl <= (0x1F + 3))
break;
- total_ticks /= 2;
+ total_ticks = DIV_ROUND_UP(total_ticks, 2);
rate /= 2;
}
diff --git a/drivers/i2c/i2c-atr.c b/drivers/i2c/i2c-atr.c
index f21475ae5921..b7c10ced5a43 100644
--- a/drivers/i2c/i2c-atr.c
+++ b/drivers/i2c/i2c-atr.c
@@ -547,7 +547,7 @@ err_destroy_mutex:
return ERR_PTR(ret);
}
-EXPORT_SYMBOL_NS_GPL(i2c_atr_new, I2C_ATR);
+EXPORT_SYMBOL_NS_GPL(i2c_atr_new, "I2C_ATR");
void i2c_atr_delete(struct i2c_atr *atr)
{
@@ -562,7 +562,7 @@ void i2c_atr_delete(struct i2c_atr *atr)
mutex_destroy(&atr->lock);
kfree(atr);
}
-EXPORT_SYMBOL_NS_GPL(i2c_atr_delete, I2C_ATR);
+EXPORT_SYMBOL_NS_GPL(i2c_atr_delete, "I2C_ATR");
int i2c_atr_add_adapter(struct i2c_atr *atr, u32 chan_id,
struct device *adapter_parent,
@@ -657,7 +657,7 @@ err_fwnode_put:
kfree(chan);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(i2c_atr_add_adapter, I2C_ATR);
+EXPORT_SYMBOL_NS_GPL(i2c_atr_add_adapter, "I2C_ATR");
void i2c_atr_del_adapter(struct i2c_atr *atr, u32 chan_id)
{
@@ -690,19 +690,19 @@ void i2c_atr_del_adapter(struct i2c_atr *atr, u32 chan_id)
kfree(chan->orig_addrs);
kfree(chan);
}
-EXPORT_SYMBOL_NS_GPL(i2c_atr_del_adapter, I2C_ATR);
+EXPORT_SYMBOL_NS_GPL(i2c_atr_del_adapter, "I2C_ATR");
void i2c_atr_set_driver_data(struct i2c_atr *atr, void *data)
{
atr->priv = data;
}
-EXPORT_SYMBOL_NS_GPL(i2c_atr_set_driver_data, I2C_ATR);
+EXPORT_SYMBOL_NS_GPL(i2c_atr_set_driver_data, "I2C_ATR");
void *i2c_atr_get_driver_data(struct i2c_atr *atr)
{
return atr->priv;
}
-EXPORT_SYMBOL_NS_GPL(i2c_atr_get_driver_data, I2C_ATR);
+EXPORT_SYMBOL_NS_GPL(i2c_atr_get_driver_data, "I2C_ATR");
MODULE_AUTHOR("Luca Ceresoli <luca.ceresoli@bootlin.com>");
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
diff --git a/drivers/i2c/i2c-core-of-prober.c b/drivers/i2c/i2c-core-of-prober.c
new file mode 100644
index 000000000000..0a66267e4836
--- /dev/null
+++ b/drivers/i2c/i2c-core-of-prober.c
@@ -0,0 +1,415 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * Linux I2C core OF component prober code
+ *
+ * Copyright (C) 2024 Google LLC
+ */
+
+#include <linux/cleanup.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dev_printk.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/i2c.h>
+#include <linux/i2c-of-prober.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/stddef.h>
+
+/*
+ * Some devices, such as Google Hana Chromebooks, are produced by multiple
+ * vendors each using their preferred components. Such components are all
+ * in the device tree. Instead of having all of them enabled and having each
+ * driver separately try and probe its device while fighting over shared
+ * resources, they can be marked as "fail-needs-probe" and have a prober
+ * figure out which one is actually used beforehand.
+ *
+ * This prober assumes such drop-in parts are on the same I2C bus, have
+ * non-conflicting addresses, and can be directly probed by seeing which
+ * address responds.
+ *
+ * TODO:
+ * - Support I2C muxes
+ */
+
+static struct device_node *i2c_of_probe_get_i2c_node(struct device *dev, const char *type)
+{
+ struct device_node *node __free(device_node) = of_find_node_by_name(NULL, type);
+ if (!node) {
+ dev_err(dev, "Could not find %s device node\n", type);
+ return NULL;
+ }
+
+ struct device_node *i2c_node __free(device_node) = of_get_parent(node);
+ if (!of_node_name_eq(i2c_node, "i2c")) {
+ dev_err(dev, "%s device isn't on I2C bus\n", type);
+ return NULL;
+ }
+
+ if (!of_device_is_available(i2c_node)) {
+ dev_err(dev, "I2C controller not available\n");
+ return NULL;
+ }
+
+ return no_free_ptr(i2c_node);
+}
+
+static int i2c_of_probe_enable_node(struct device *dev, struct device_node *node)
+{
+ int ret;
+
+ dev_dbg(dev, "Enabling %pOF\n", node);
+
+ struct of_changeset *ocs __free(kfree) = kzalloc(sizeof(*ocs), GFP_KERNEL);
+ if (!ocs)
+ return -ENOMEM;
+
+ of_changeset_init(ocs);
+ ret = of_changeset_update_prop_string(ocs, node, "status", "okay");
+ if (ret)
+ return ret;
+
+ ret = of_changeset_apply(ocs);
+ if (ret) {
+ /* ocs needs to be explicitly cleaned up before being freed. */
+ of_changeset_destroy(ocs);
+ } else {
+ /*
+ * ocs is intentionally kept around as it needs to
+ * exist as long as the change is applied.
+ */
+ void *ptr __always_unused = no_free_ptr(ocs);
+ }
+
+ return ret;
+}
+
+static const struct i2c_of_probe_ops i2c_of_probe_dummy_ops;
+
+/**
+ * i2c_of_probe_component() - probe for devices of "type" on the same i2c bus
+ * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages.
+ * @cfg: Pointer to the &struct i2c_of_probe_cfg containing callbacks and other options
+ * for the prober.
+ * @ctx: Context data for callbacks.
+ *
+ * Probe for possible I2C components of the same "type" (&i2c_of_probe_cfg->type)
+ * on the same I2C bus that have their status marked as "fail-needs-probe".
+ *
+ * Assumes that across the entire device tree the only instances of nodes
+ * with "type" prefixed node names (not including the address portion) are
+ * the ones that need handling for second source components. In other words,
+ * if "type" is "touchscreen", then all device nodes named "touchscreen*"
+ * are the ones that need probing. There cannot be another "touchscreen*"
+ * node that is already enabled.
+ *
+ * Assumes that for each "type" of component, only one actually exists. In
+ * other words, only one matching and existing device will be enabled.
+ *
+ * Context: Process context only. Does non-atomic I2C transfers.
+ * Should only be used from a driver probe function, as the function
+ * can return -EPROBE_DEFER if the I2C adapter or other resources
+ * are unavailable.
+ * Return: 0 on success or no-op, error code otherwise.
+ * A no-op can happen when it seems like the device tree already
+ * has components of the type to be probed already enabled. This
+ * can happen when the device tree had not been updated to mark
+ * the status of the to-be-probed components as "fail-needs-probe".
+ * Or this function was already run with the same parameters and
+ * succeeded in enabling a component. The latter could happen if
+ * the user had multiple types of components to probe, and one of
+ * them down the list caused a deferred probe. This is expected
+ * behavior.
+ */
+int i2c_of_probe_component(struct device *dev, const struct i2c_of_probe_cfg *cfg, void *ctx)
+{
+ const struct i2c_of_probe_ops *ops;
+ const char *type;
+ struct i2c_adapter *i2c;
+ int ret;
+
+ ops = cfg->ops ?: &i2c_of_probe_dummy_ops;
+ type = cfg->type;
+
+ struct device_node *i2c_node __free(device_node) = i2c_of_probe_get_i2c_node(dev, type);
+ if (!i2c_node)
+ return -ENODEV;
+
+ /*
+ * If any devices of the given "type" are already enabled then this function is a no-op.
+ * Either the device tree hasn't been modified to work with this probe function, or the
+ * function had already run before and enabled some component.
+ */
+ for_each_child_of_node_with_prefix(i2c_node, node, type)
+ if (of_device_is_available(node))
+ return 0;
+
+ i2c = of_get_i2c_adapter_by_node(i2c_node);
+ if (!i2c)
+ return dev_err_probe(dev, -EPROBE_DEFER, "Couldn't get I2C adapter\n");
+
+ /* Grab and enable resources */
+ ret = 0;
+ if (ops->enable)
+ ret = ops->enable(dev, i2c_node, ctx);
+ if (ret)
+ goto out_put_i2c_adapter;
+
+ for_each_child_of_node_with_prefix(i2c_node, node, type) {
+ union i2c_smbus_data data;
+ u32 addr;
+
+ if (of_property_read_u32(node, "reg", &addr))
+ continue;
+ if (i2c_smbus_xfer(i2c, addr, 0, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data) < 0)
+ continue;
+
+ /* Found a device that is responding */
+ if (ops->cleanup_early)
+ ops->cleanup_early(dev, ctx);
+ ret = i2c_of_probe_enable_node(dev, node);
+ break;
+ }
+
+ if (ops->cleanup)
+ ops->cleanup(dev, ctx);
+out_put_i2c_adapter:
+ i2c_put_adapter(i2c);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(i2c_of_probe_component, "I2C_OF_PROBER");
+
+static int i2c_of_probe_simple_get_supply(struct device *dev, struct device_node *node,
+ struct i2c_of_probe_simple_ctx *ctx)
+{
+ const char *supply_name;
+ struct regulator *supply;
+
+ /*
+ * It's entirely possible for the component's device node to not have the
+ * regulator supplies. While it does not make sense from a hardware perspective,
+ * the supplies could be always on or otherwise not modeled in the device tree,
+ * but the device would still work.
+ */
+ supply_name = ctx->opts->supply_name;
+ if (!supply_name)
+ return 0;
+
+ supply = of_regulator_get_optional(dev, node, supply_name);
+ if (IS_ERR(supply)) {
+ return dev_err_probe(dev, PTR_ERR(supply),
+ "Failed to get regulator supply \"%s\" from %pOF\n",
+ supply_name, node);
+ }
+
+ ctx->supply = supply;
+
+ return 0;
+}
+
+static void i2c_of_probe_simple_put_supply(struct i2c_of_probe_simple_ctx *ctx)
+{
+ regulator_put(ctx->supply);
+ ctx->supply = NULL;
+}
+
+static int i2c_of_probe_simple_enable_regulator(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
+{
+ int ret;
+
+ if (!ctx->supply)
+ return 0;
+
+ dev_dbg(dev, "Enabling regulator supply \"%s\"\n", ctx->opts->supply_name);
+
+ ret = regulator_enable(ctx->supply);
+ if (ret)
+ return ret;
+
+ if (ctx->opts->post_power_on_delay_ms)
+ msleep(ctx->opts->post_power_on_delay_ms);
+
+ return 0;
+}
+
+static void i2c_of_probe_simple_disable_regulator(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
+{
+ if (!ctx->supply)
+ return;
+
+ dev_dbg(dev, "Disabling regulator supply \"%s\"\n", ctx->opts->supply_name);
+
+ regulator_disable(ctx->supply);
+}
+
+static int i2c_of_probe_simple_get_gpiod(struct device *dev, struct device_node *node,
+ struct i2c_of_probe_simple_ctx *ctx)
+{
+ struct fwnode_handle *fwnode = of_fwnode_handle(node);
+ struct gpio_desc *gpiod;
+ const char *con_id;
+
+ /* NULL signals no GPIO needed */
+ if (!ctx->opts->gpio_name)
+ return 0;
+
+ /* An empty string signals an unnamed GPIO */
+ if (!ctx->opts->gpio_name[0])
+ con_id = NULL;
+ else
+ con_id = ctx->opts->gpio_name;
+
+ gpiod = fwnode_gpiod_get_index(fwnode, con_id, 0, GPIOD_ASIS, "i2c-of-prober");
+ if (IS_ERR(gpiod))
+ return PTR_ERR(gpiod);
+
+ ctx->gpiod = gpiod;
+
+ return 0;
+}
+
+static void i2c_of_probe_simple_put_gpiod(struct i2c_of_probe_simple_ctx *ctx)
+{
+ gpiod_put(ctx->gpiod);
+ ctx->gpiod = NULL;
+}
+
+static int i2c_of_probe_simple_set_gpio(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
+{
+ int ret;
+
+ if (!ctx->gpiod)
+ return 0;
+
+ dev_dbg(dev, "Configuring GPIO\n");
+
+ ret = gpiod_direction_output(ctx->gpiod, ctx->opts->gpio_assert_to_enable);
+ if (ret)
+ return ret;
+
+ if (ctx->opts->post_gpio_config_delay_ms)
+ msleep(ctx->opts->post_gpio_config_delay_ms);
+
+ return 0;
+}
+
+static void i2c_of_probe_simple_disable_gpio(struct device *dev, struct i2c_of_probe_simple_ctx *ctx)
+{
+ gpiod_set_value(ctx->gpiod, !ctx->opts->gpio_assert_to_enable);
+}
+
+/**
+ * i2c_of_probe_simple_enable - Simple helper for I2C OF prober to get and enable resources
+ * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages
+ * @bus_node: Pointer to the &struct device_node of the I2C adapter.
+ * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
+ *
+ * If &i2c_of_probe_simple_opts->supply_name is given, request the named regulator supply.
+ * If &i2c_of_probe_simple_opts->gpio_name is given, request the named GPIO. Or if it is
+ * the empty string, request the unnamed GPIO.
+ * If a regulator supply was found, enable that regulator.
+ * If a GPIO line was found, configure the GPIO line to output and set value
+ * according to given options.
+ *
+ * Return: %0 on success or no-op, or a negative error number on failure.
+ */
+int i2c_of_probe_simple_enable(struct device *dev, struct device_node *bus_node, void *data)
+{
+ struct i2c_of_probe_simple_ctx *ctx = data;
+ struct device_node *node;
+ const char *compat;
+ int ret;
+
+ dev_dbg(dev, "Requesting resources for components under I2C bus %pOF\n", bus_node);
+
+ if (!ctx || !ctx->opts)
+ return -EINVAL;
+
+ compat = ctx->opts->res_node_compatible;
+ if (!compat)
+ return -EINVAL;
+
+ node = of_get_compatible_child(bus_node, compat);
+ if (!node)
+ return dev_err_probe(dev, -ENODEV, "No device compatible with \"%s\" found\n",
+ compat);
+
+ ret = i2c_of_probe_simple_get_supply(dev, node, ctx);
+ if (ret)
+ goto out_put_node;
+
+ ret = i2c_of_probe_simple_get_gpiod(dev, node, ctx);
+ if (ret)
+ goto out_put_supply;
+
+ ret = i2c_of_probe_simple_enable_regulator(dev, ctx);
+ if (ret)
+ goto out_put_gpiod;
+
+ ret = i2c_of_probe_simple_set_gpio(dev, ctx);
+ if (ret)
+ goto out_disable_regulator;
+
+ return 0;
+
+out_disable_regulator:
+ i2c_of_probe_simple_disable_regulator(dev, ctx);
+out_put_gpiod:
+ i2c_of_probe_simple_put_gpiod(ctx);
+out_put_supply:
+ i2c_of_probe_simple_put_supply(ctx);
+out_put_node:
+ of_node_put(node);
+ return ret;
+}
+EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_enable, "I2C_OF_PROBER");
+
+/**
+ * i2c_of_probe_simple_cleanup_early - \
+ * Simple helper for I2C OF prober to release GPIOs before component is enabled
+ * @dev: Pointer to the &struct device of the caller; unused.
+ * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
+ *
+ * GPIO descriptors are exclusive and have to be released before the
+ * actual driver probes so that the latter can acquire them.
+ */
+void i2c_of_probe_simple_cleanup_early(struct device *dev, void *data)
+{
+ struct i2c_of_probe_simple_ctx *ctx = data;
+
+ i2c_of_probe_simple_put_gpiod(ctx);
+}
+EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_cleanup_early, "I2C_OF_PROBER");
+
+/**
+ * i2c_of_probe_simple_cleanup - Clean up and release resources for I2C OF prober simple helpers
+ * @dev: Pointer to the &struct device of the caller, only used for dev_printk() messages
+ * @data: Pointer to &struct i2c_of_probe_simple_ctx helper context.
+ *
+ * * If a GPIO line was found and not yet released, set its value to the opposite of that
+ * set in i2c_of_probe_simple_enable() and release it.
+ * * If a regulator supply was found, disable that regulator and release it.
+ */
+void i2c_of_probe_simple_cleanup(struct device *dev, void *data)
+{
+ struct i2c_of_probe_simple_ctx *ctx = data;
+
+ /* GPIO operations here are no-ops if i2c_of_probe_simple_cleanup_early was called. */
+ i2c_of_probe_simple_disable_gpio(dev, ctx);
+ i2c_of_probe_simple_put_gpiod(ctx);
+
+ i2c_of_probe_simple_disable_regulator(dev, ctx);
+ i2c_of_probe_simple_put_supply(ctx);
+}
+EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_cleanup, "I2C_OF_PROBER");
+
+struct i2c_of_probe_ops i2c_of_probe_simple_ops = {
+ .enable = i2c_of_probe_simple_enable,
+ .cleanup_early = i2c_of_probe_simple_cleanup_early,
+ .cleanup = i2c_of_probe_simple_cleanup,
+};
+EXPORT_SYMBOL_NS_GPL(i2c_of_probe_simple_ops, "I2C_OF_PROBER");
diff --git a/drivers/i2c/i2c-core-smbus.c b/drivers/i2c/i2c-core-smbus.c
index 0a6bdc6df172..e73afbefe222 100644
--- a/drivers/i2c/i2c-core-smbus.c
+++ b/drivers/i2c/i2c-core-smbus.c
@@ -122,7 +122,7 @@ EXPORT_SYMBOL(i2c_smbus_read_byte);
s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value)
{
return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
- I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
+ I2C_SMBUS_WRITE, value, I2C_SMBUS_BYTE, NULL);
}
EXPORT_SYMBOL(i2c_smbus_write_byte);
diff --git a/drivers/i3c/master/ast2600-i3c-master.c b/drivers/i3c/master/ast2600-i3c-master.c
index 84942dbb6f80..e05e83812c71 100644
--- a/drivers/i3c/master/ast2600-i3c-master.c
+++ b/drivers/i3c/master/ast2600-i3c-master.c
@@ -174,7 +174,7 @@ MODULE_DEVICE_TABLE(of, ast2600_i3c_master_of_match);
static struct platform_driver ast2600_i3c_driver = {
.probe = ast2600_i3c_probe,
- .remove_new = ast2600_i3c_remove,
+ .remove = ast2600_i3c_remove,
.driver = {
.name = "ast2600-i3c-master",
.of_match_table = ast2600_i3c_master_of_match,
diff --git a/drivers/i3c/master/dw-i3c-master.c b/drivers/i3c/master/dw-i3c-master.c
index 5b5c2e4bdc51..d4b80eb8cecd 100644
--- a/drivers/i3c/master/dw-i3c-master.c
+++ b/drivers/i3c/master/dw-i3c-master.c
@@ -1783,7 +1783,7 @@ MODULE_DEVICE_TABLE(acpi, amd_i3c_device_match);
static struct platform_driver dw_i3c_driver = {
.probe = dw_i3c_probe,
- .remove_new = dw_i3c_remove,
+ .remove = dw_i3c_remove,
.driver = {
.name = "dw-i3c-master",
.of_match_table = dw_i3c_master_of_match,
diff --git a/drivers/i3c/master/i3c-master-cdns.c b/drivers/i3c/master/i3c-master-cdns.c
index fe4d59833ad5..06c0592487d3 100644
--- a/drivers/i3c/master/i3c-master-cdns.c
+++ b/drivers/i3c/master/i3c-master-cdns.c
@@ -1676,7 +1676,7 @@ static void cdns_i3c_master_remove(struct platform_device *pdev)
static struct platform_driver cdns_i3c_master = {
.probe = cdns_i3c_master_probe,
- .remove_new = cdns_i3c_master_remove,
+ .remove = cdns_i3c_master_remove,
.driver = {
.name = "cdns-i3c-master",
.of_match_table = cdns_i3c_master_of_ids,
diff --git a/drivers/i3c/master/mipi-i3c-hci/core.c b/drivers/i3c/master/mipi-i3c-hci/core.c
index e6e482a259b4..648c501407ce 100644
--- a/drivers/i3c/master/mipi-i3c-hci/core.c
+++ b/drivers/i3c/master/mipi-i3c-hci/core.c
@@ -844,7 +844,7 @@ MODULE_DEVICE_TABLE(acpi, i3c_hci_acpi_match);
static struct platform_driver i3c_hci_driver = {
.probe = i3c_hci_probe,
- .remove_new = i3c_hci_remove,
+ .remove = i3c_hci_remove,
.driver = {
.name = "mipi-i3c-hci",
.of_match_table = of_match_ptr(i3c_hci_of_match),
diff --git a/drivers/i3c/master/svc-i3c-master.c b/drivers/i3c/master/svc-i3c-master.c
index c1ee3828e7ee..d6057d8c7dec 100644
--- a/drivers/i3c/master/svc-i3c-master.c
+++ b/drivers/i3c/master/svc-i3c-master.c
@@ -1966,7 +1966,7 @@ MODULE_DEVICE_TABLE(of, svc_i3c_master_of_match_tbl);
static struct platform_driver svc_i3c_master = {
.probe = svc_i3c_master_probe,
- .remove_new = svc_i3c_master_remove,
+ .remove = svc_i3c_master_remove,
.driver = {
.name = "silvaco-i3c-master",
.of_match_table = svc_i3c_master_of_match_tbl,
diff --git a/drivers/iio/accel/adis16201.c b/drivers/iio/accel/adis16201.c
index d054721859b3..8601b9a8b8e7 100644
--- a/drivers/iio/accel/adis16201.c
+++ b/drivers/iio/accel/adis16201.c
@@ -300,4 +300,4 @@ MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16201 Dual-Axis Digital Inclinometer and Accelerometer");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:adis16201");
-MODULE_IMPORT_NS(IIO_ADISLIB);
+MODULE_IMPORT_NS("IIO_ADISLIB");
diff --git a/drivers/iio/accel/adis16209.c b/drivers/iio/accel/adis16209.c
index 0035e4f4db63..41ffd92f27fd 100644
--- a/drivers/iio/accel/adis16209.c
+++ b/drivers/iio/accel/adis16209.c
@@ -310,4 +310,4 @@ MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16209 Dual-Axis Digital Inclinometer and Accelerometer");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:adis16209");
-MODULE_IMPORT_NS(IIO_ADISLIB);
+MODULE_IMPORT_NS("IIO_ADISLIB");
diff --git a/drivers/iio/accel/adxl313_core.c b/drivers/iio/accel/adxl313_core.c
index 4de0a41bd679..46cca10e776f 100644
--- a/drivers/iio/accel/adxl313_core.c
+++ b/drivers/iio/accel/adxl313_core.c
@@ -32,19 +32,19 @@ const struct regmap_access_table adxl312_readable_regs_table = {
.yes_ranges = adxl312_readable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl312_readable_reg_range),
};
-EXPORT_SYMBOL_NS_GPL(adxl312_readable_regs_table, IIO_ADXL313);
+EXPORT_SYMBOL_NS_GPL(adxl312_readable_regs_table, "IIO_ADXL313");
const struct regmap_access_table adxl313_readable_regs_table = {
.yes_ranges = adxl313_readable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl313_readable_reg_range),
};
-EXPORT_SYMBOL_NS_GPL(adxl313_readable_regs_table, IIO_ADXL313);
+EXPORT_SYMBOL_NS_GPL(adxl313_readable_regs_table, "IIO_ADXL313");
const struct regmap_access_table adxl314_readable_regs_table = {
.yes_ranges = adxl312_readable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl312_readable_reg_range),
};
-EXPORT_SYMBOL_NS_GPL(adxl314_readable_regs_table, IIO_ADXL313);
+EXPORT_SYMBOL_NS_GPL(adxl314_readable_regs_table, "IIO_ADXL313");
static int adxl312_check_id(struct device *dev,
struct adxl313_data *data)
@@ -121,7 +121,7 @@ const struct adxl313_chip_info adxl31x_chip_info[] = {
.check_id = &adxl312_check_id,
},
};
-EXPORT_SYMBOL_NS_GPL(adxl31x_chip_info, IIO_ADXL313);
+EXPORT_SYMBOL_NS_GPL(adxl31x_chip_info, "IIO_ADXL313");
static const struct regmap_range adxl312_writable_reg_range[] = {
regmap_reg_range(ADXL313_REG_OFS_AXIS(0), ADXL313_REG_OFS_AXIS(2)),
@@ -144,19 +144,19 @@ const struct regmap_access_table adxl312_writable_regs_table = {
.yes_ranges = adxl312_writable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl312_writable_reg_range),
};
-EXPORT_SYMBOL_NS_GPL(adxl312_writable_regs_table, IIO_ADXL313);
+EXPORT_SYMBOL_NS_GPL(adxl312_writable_regs_table, "IIO_ADXL313");
const struct regmap_access_table adxl313_writable_regs_table = {
.yes_ranges = adxl313_writable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl313_writable_reg_range),
};
-EXPORT_SYMBOL_NS_GPL(adxl313_writable_regs_table, IIO_ADXL313);
+EXPORT_SYMBOL_NS_GPL(adxl313_writable_regs_table, "IIO_ADXL313");
const struct regmap_access_table adxl314_writable_regs_table = {
.yes_ranges = adxl312_writable_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl312_writable_reg_range),
};
-EXPORT_SYMBOL_NS_GPL(adxl314_writable_regs_table, IIO_ADXL313);
+EXPORT_SYMBOL_NS_GPL(adxl314_writable_regs_table, "IIO_ADXL313");
static const int adxl313_odr_freqs[][2] = {
[0] = { 6, 250000 },
@@ -417,7 +417,7 @@ int adxl313_core_probe(struct device *dev,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(adxl313_core_probe, IIO_ADXL313);
+EXPORT_SYMBOL_NS_GPL(adxl313_core_probe, "IIO_ADXL313");
MODULE_AUTHOR("Lucas Stankus <lucas.p.stankus@gmail.com>");
MODULE_DESCRIPTION("ADXL313 3-Axis Digital Accelerometer core driver");
diff --git a/drivers/iio/accel/adxl313_i2c.c b/drivers/iio/accel/adxl313_i2c.c
index a4cf0cf2c5aa..dfa51860cd83 100644
--- a/drivers/iio/accel/adxl313_i2c.c
+++ b/drivers/iio/accel/adxl313_i2c.c
@@ -92,4 +92,4 @@ module_i2c_driver(adxl313_i2c_driver);
MODULE_AUTHOR("Lucas Stankus <lucas.p.stankus@gmail.com>");
MODULE_DESCRIPTION("ADXL313 3-Axis Digital Accelerometer I2C driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADXL313);
+MODULE_IMPORT_NS("IIO_ADXL313");
diff --git a/drivers/iio/accel/adxl313_spi.c b/drivers/iio/accel/adxl313_spi.c
index 6f8d73f6e5a9..ebc5d09f108d 100644
--- a/drivers/iio/accel/adxl313_spi.c
+++ b/drivers/iio/accel/adxl313_spi.c
@@ -119,4 +119,4 @@ module_spi_driver(adxl313_spi_driver);
MODULE_AUTHOR("Lucas Stankus <lucas.p.stankus@gmail.com>");
MODULE_DESCRIPTION("ADXL313 3-Axis Digital Accelerometer SPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADXL313);
+MODULE_IMPORT_NS("IIO_ADXL313");
diff --git a/drivers/iio/accel/adxl345_core.c b/drivers/iio/accel/adxl345_core.c
index 006ce66c0aa3..b1efab0f6404 100644
--- a/drivers/iio/accel/adxl345_core.c
+++ b/drivers/iio/accel/adxl345_core.c
@@ -248,7 +248,7 @@ int adxl345_core_probe(struct device *dev, struct regmap *regmap,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(adxl345_core_probe, IIO_ADXL345);
+EXPORT_SYMBOL_NS_GPL(adxl345_core_probe, "IIO_ADXL345");
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer core driver");
diff --git a/drivers/iio/accel/adxl345_i2c.c b/drivers/iio/accel/adxl345_i2c.c
index 4065b8f7c8a8..cb23fb11fcd7 100644
--- a/drivers/iio/accel/adxl345_i2c.c
+++ b/drivers/iio/accel/adxl345_i2c.c
@@ -74,4 +74,4 @@ module_i2c_driver(adxl345_i2c_driver);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer I2C driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADXL345);
+MODULE_IMPORT_NS("IIO_ADXL345");
diff --git a/drivers/iio/accel/adxl345_spi.c b/drivers/iio/accel/adxl345_spi.c
index 57e16b441702..968e7b390d4b 100644
--- a/drivers/iio/accel/adxl345_spi.c
+++ b/drivers/iio/accel/adxl345_spi.c
@@ -88,4 +88,4 @@ module_spi_driver(adxl345_spi_driver);
MODULE_AUTHOR("Eva Rachel Retuya <eraretuya@gmail.com>");
MODULE_DESCRIPTION("ADXL345 3-Axis Digital Accelerometer SPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADXL345);
+MODULE_IMPORT_NS("IIO_ADXL345");
diff --git a/drivers/iio/accel/adxl355_core.c b/drivers/iio/accel/adxl355_core.c
index eabaefa92f19..e8cd21fa77a6 100644
--- a/drivers/iio/accel/adxl355_core.c
+++ b/drivers/iio/accel/adxl355_core.c
@@ -72,7 +72,7 @@ const struct regmap_access_table adxl355_readable_regs_tbl = {
.yes_ranges = adxl355_read_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl355_read_reg_range),
};
-EXPORT_SYMBOL_NS_GPL(adxl355_readable_regs_tbl, IIO_ADXL355);
+EXPORT_SYMBOL_NS_GPL(adxl355_readable_regs_tbl, "IIO_ADXL355");
static const struct regmap_range adxl355_write_reg_range[] = {
regmap_reg_range(ADXL355_OFFSET_X_H_REG, ADXL355_RESET_REG),
@@ -82,7 +82,7 @@ const struct regmap_access_table adxl355_writeable_regs_tbl = {
.yes_ranges = adxl355_write_reg_range,
.n_yes_ranges = ARRAY_SIZE(adxl355_write_reg_range),
};
-EXPORT_SYMBOL_NS_GPL(adxl355_writeable_regs_tbl, IIO_ADXL355);
+EXPORT_SYMBOL_NS_GPL(adxl355_writeable_regs_tbl, "IIO_ADXL355");
const struct adxl355_chip_info adxl35x_chip_info[] = {
[ADXL355] = {
@@ -136,7 +136,7 @@ const struct adxl355_chip_info adxl35x_chip_info[] = {
},
},
};
-EXPORT_SYMBOL_NS_GPL(adxl35x_chip_info, IIO_ADXL355);
+EXPORT_SYMBOL_NS_GPL(adxl35x_chip_info, "IIO_ADXL355");
enum adxl355_op_mode {
ADXL355_MEASUREMENT,
@@ -643,7 +643,7 @@ static irqreturn_t adxl355_trigger_handler(int irq, void *p)
* The acceleration data is 24 bits and big endian. It has to be saved
* in 32 bits, hence, it is saved in the 2nd byte of the 4 byte buffer.
* The buf array is 14 bytes as it includes 3x4=12 bytes for
- * accelaration data of x, y, and z axis. It also includes 2 bytes for
+ * acceleration data of x, y, and z axis. It also includes 2 bytes for
* temperature data.
*/
ret = regmap_bulk_read(data->regmap, ADXL355_XDATA3_REG,
@@ -801,7 +801,7 @@ int adxl355_core_probe(struct device *dev, struct regmap *regmap,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(adxl355_core_probe, IIO_ADXL355);
+EXPORT_SYMBOL_NS_GPL(adxl355_core_probe, "IIO_ADXL355");
MODULE_AUTHOR("Puranjay Mohan <puranjay12@gmail.com>");
MODULE_DESCRIPTION("ADXL355 3-Axis Digital Accelerometer core driver");
diff --git a/drivers/iio/accel/adxl355_i2c.c b/drivers/iio/accel/adxl355_i2c.c
index 32398cde9608..1a512c7b792b 100644
--- a/drivers/iio/accel/adxl355_i2c.c
+++ b/drivers/iio/accel/adxl355_i2c.c
@@ -67,4 +67,4 @@ module_i2c_driver(adxl355_i2c_driver);
MODULE_AUTHOR("Puranjay Mohan <puranjay12@gmail.com>");
MODULE_DESCRIPTION("ADXL355 3-Axis Digital Accelerometer I2C driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADXL355);
+MODULE_IMPORT_NS("IIO_ADXL355");
diff --git a/drivers/iio/accel/adxl355_spi.c b/drivers/iio/accel/adxl355_spi.c
index 5153ac815e4b..869e3e57d6f7 100644
--- a/drivers/iio/accel/adxl355_spi.c
+++ b/drivers/iio/accel/adxl355_spi.c
@@ -70,4 +70,4 @@ module_spi_driver(adxl355_spi_driver);
MODULE_AUTHOR("Puranjay Mohan <puranjay12@gmail.com>");
MODULE_DESCRIPTION("ADXL355 3-Axis Digital Accelerometer SPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADXL355);
+MODULE_IMPORT_NS("IIO_ADXL355");
diff --git a/drivers/iio/accel/adxl367.c b/drivers/iio/accel/adxl367.c
index e790a66d86c7..a48ac0d7bd96 100644
--- a/drivers/iio/accel/adxl367.c
+++ b/drivers/iio/accel/adxl367.c
@@ -1073,7 +1073,7 @@ static int adxl367_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
enum adxl367_activity_type act;
@@ -1475,7 +1475,7 @@ int adxl367_probe(struct device *dev, const struct adxl367_ops *ops,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(adxl367_probe, IIO_ADXL367);
+EXPORT_SYMBOL_NS_GPL(adxl367_probe, "IIO_ADXL367");
MODULE_AUTHOR("Cosmin Tanislav <cosmin.tanislav@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADXL367 3-axis accelerometer driver");
diff --git a/drivers/iio/accel/adxl367_i2c.c b/drivers/iio/accel/adxl367_i2c.c
index deb82a43ec36..80f0b642b9b0 100644
--- a/drivers/iio/accel/adxl367_i2c.c
+++ b/drivers/iio/accel/adxl367_i2c.c
@@ -83,7 +83,7 @@ static struct i2c_driver adxl367_i2c_driver = {
module_i2c_driver(adxl367_i2c_driver);
-MODULE_IMPORT_NS(IIO_ADXL367);
+MODULE_IMPORT_NS("IIO_ADXL367");
MODULE_AUTHOR("Cosmin Tanislav <cosmin.tanislav@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADXL367 3-axis accelerometer I2C driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/accel/adxl367_spi.c b/drivers/iio/accel/adxl367_spi.c
index b70117265791..49d7c8fbe8ed 100644
--- a/drivers/iio/accel/adxl367_spi.c
+++ b/drivers/iio/accel/adxl367_spi.c
@@ -160,7 +160,7 @@ static struct spi_driver adxl367_spi_driver = {
module_spi_driver(adxl367_spi_driver);
-MODULE_IMPORT_NS(IIO_ADXL367);
+MODULE_IMPORT_NS("IIO_ADXL367");
MODULE_AUTHOR("Cosmin Tanislav <cosmin.tanislav@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADXL367 3-axis accelerometer SPI driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/accel/adxl372.c b/drivers/iio/accel/adxl372.c
index ef8dd557877b..8ba5fbe6e1f5 100644
--- a/drivers/iio/accel/adxl372.c
+++ b/drivers/iio/accel/adxl372.c
@@ -940,7 +940,7 @@ static int adxl372_read_event_config(struct iio_dev *indio_dev, const struct iio
static int adxl372_write_event_config(struct iio_dev *indio_dev, const struct iio_chan_spec *chan,
enum iio_event_type type, enum iio_event_direction dir,
- int state)
+ bool state)
{
struct adxl372_state *st = iio_priv(indio_dev);
@@ -1176,7 +1176,7 @@ bool adxl372_readable_noinc_reg(struct device *dev, unsigned int reg)
{
return (reg == ADXL372_FIFO_DATA);
}
-EXPORT_SYMBOL_NS_GPL(adxl372_readable_noinc_reg, IIO_ADXL372);
+EXPORT_SYMBOL_NS_GPL(adxl372_readable_noinc_reg, "IIO_ADXL372");
int adxl372_probe(struct device *dev, struct regmap *regmap,
int irq, const char *name)
@@ -1260,7 +1260,7 @@ int adxl372_probe(struct device *dev, struct regmap *regmap,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(adxl372_probe, IIO_ADXL372);
+EXPORT_SYMBOL_NS_GPL(adxl372_probe, "IIO_ADXL372");
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer driver");
diff --git a/drivers/iio/accel/adxl372_i2c.c b/drivers/iio/accel/adxl372_i2c.c
index 3571cfde1c0e..43d5fd921be7 100644
--- a/drivers/iio/accel/adxl372_i2c.c
+++ b/drivers/iio/accel/adxl372_i2c.c
@@ -67,4 +67,4 @@ module_i2c_driver(adxl372_i2c_driver);
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer I2C driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_ADXL372);
+MODULE_IMPORT_NS("IIO_ADXL372");
diff --git a/drivers/iio/accel/adxl372_spi.c b/drivers/iio/accel/adxl372_spi.c
index 787699773f96..1ab1997a55b1 100644
--- a/drivers/iio/accel/adxl372_spi.c
+++ b/drivers/iio/accel/adxl372_spi.c
@@ -58,4 +58,4 @@ module_spi_driver(adxl372_spi_driver);
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADXL372 3-axis accelerometer SPI driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_ADXL372);
+MODULE_IMPORT_NS("IIO_ADXL372");
diff --git a/drivers/iio/accel/adxl380.c b/drivers/iio/accel/adxl380.c
index f80527d899be..90340f134722 100644
--- a/drivers/iio/accel/adxl380.c
+++ b/drivers/iio/accel/adxl380.c
@@ -194,7 +194,7 @@ const struct adxl380_chip_info adxl380_chip_info = {
.temp_offset = 25 * 102 / 10 - 470,
};
-EXPORT_SYMBOL_NS_GPL(adxl380_chip_info, IIO_ADXL380);
+EXPORT_SYMBOL_NS_GPL(adxl380_chip_info, "IIO_ADXL380");
const struct adxl380_chip_info adxl382_chip_info = {
.name = "adxl382",
@@ -211,7 +211,7 @@ const struct adxl380_chip_info adxl382_chip_info = {
*/
.temp_offset = 25 * 102 / 10 - 570,
};
-EXPORT_SYMBOL_NS_GPL(adxl382_chip_info, IIO_ADXL380);
+EXPORT_SYMBOL_NS_GPL(adxl382_chip_info, "IIO_ADXL380");
static const unsigned int adxl380_th_reg_high_addr[2] = {
[ADXL380_ACTIVITY] = ADXL380_THRESH_ACT_H_REG,
@@ -263,7 +263,7 @@ bool adxl380_readable_noinc_reg(struct device *dev, unsigned int reg)
{
return reg == ADXL380_FIFO_DATA;
}
-EXPORT_SYMBOL_NS_GPL(adxl380_readable_noinc_reg, IIO_ADXL380);
+EXPORT_SYMBOL_NS_GPL(adxl380_readable_noinc_reg, "IIO_ADXL380");
static int adxl380_set_measure_en(struct adxl380_state *st, bool en)
{
@@ -1181,7 +1181,7 @@ static int adxl380_read_raw(struct iio_dev *indio_dev,
ret = adxl380_read_chn(st, chan->address);
iio_device_release_direct_mode(indio_dev);
- if (ret)
+ if (ret < 0)
return ret;
*val = sign_extend32(ret >> chan->scan_type.shift,
@@ -1386,7 +1386,7 @@ static int adxl380_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct adxl380_state *st = iio_priv(indio_dev);
enum adxl380_axis axis;
@@ -1719,7 +1719,6 @@ static int adxl380_config_irq(struct iio_dev *indio_dev)
{
struct adxl380_state *st = iio_priv(indio_dev);
unsigned long irq_flag;
- struct irq_data *desc;
u32 irq_type;
u8 polarity;
int ret;
@@ -1737,11 +1736,7 @@ static int adxl380_config_irq(struct iio_dev *indio_dev)
st->int_map[1] = ADXL380_INT1_MAP1_REG;
}
- desc = irq_get_irq_data(st->irq);
- if (!desc)
- return dev_err_probe(st->dev, -EINVAL, "Could not find IRQ %d\n", st->irq);
-
- irq_type = irqd_get_trigger_type(desc);
+ irq_type = irq_get_trigger_type(st->irq);
if (irq_type == IRQ_TYPE_LEVEL_HIGH) {
polarity = 0;
irq_flag = IRQF_TRIGGER_HIGH | IRQF_ONESHOT;
@@ -1897,7 +1892,7 @@ int adxl380_probe(struct device *dev, struct regmap *regmap,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(adxl380_probe, IIO_ADXL380);
+EXPORT_SYMBOL_NS_GPL(adxl380_probe, "IIO_ADXL380");
MODULE_AUTHOR("Ramona Gradinariu <ramona.gradinariu@analog.com>");
MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
diff --git a/drivers/iio/accel/adxl380_i2c.c b/drivers/iio/accel/adxl380_i2c.c
index 1dc1e77be815..b4f86f972361 100644
--- a/drivers/iio/accel/adxl380_i2c.c
+++ b/drivers/iio/accel/adxl380_i2c.c
@@ -61,4 +61,4 @@ MODULE_AUTHOR("Ramona Gradinariu <ramona.gradinariu@analog.com>");
MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADXL380 3-axis accelerometer I2C driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_ADXL380);
+MODULE_IMPORT_NS("IIO_ADXL380");
diff --git a/drivers/iio/accel/adxl380_spi.c b/drivers/iio/accel/adxl380_spi.c
index e7b5778cb6cf..6edd0d211ffa 100644
--- a/drivers/iio/accel/adxl380_spi.c
+++ b/drivers/iio/accel/adxl380_spi.c
@@ -63,4 +63,4 @@ MODULE_AUTHOR("Ramona Gradinariu <ramona.gradinariu@analog.com>");
MODULE_AUTHOR("Antoniu Miclaus <antoniu.miclaus@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADXL380 3-axis accelerometer SPI driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_ADXL380);
+MODULE_IMPORT_NS("IIO_ADXL380");
diff --git a/drivers/iio/accel/bma180.c b/drivers/iio/accel/bma180.c
index 2445a0f7bc2b..128db14ba726 100644
--- a/drivers/iio/accel/bma180.c
+++ b/drivers/iio/accel/bma180.c
@@ -21,6 +21,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/types.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/buffer.h>
@@ -144,7 +145,7 @@ struct bma180_data {
/* Ensure timestamp is naturally aligned */
struct {
s16 chan[4];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
};
diff --git a/drivers/iio/accel/bma220_spi.c b/drivers/iio/accel/bma220_spi.c
index fcbd695e4654..009e6243c6cb 100644
--- a/drivers/iio/accel/bma220_spi.c
+++ b/drivers/iio/accel/bma220_spi.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
+#include <linux/types.h>
#include <linux/spi/spi.h>
#include <linux/iio/buffer.h>
diff --git a/drivers/iio/accel/bma400_core.c b/drivers/iio/accel/bma400_core.c
index e4fe36768216..ae806ed60271 100644
--- a/drivers/iio/accel/bma400_core.c
+++ b/drivers/iio/accel/bma400_core.c
@@ -115,7 +115,7 @@ struct bma400_data {
struct {
__le16 buff[3];
u8 temperature;
- s64 ts __aligned(8);
+ aligned_s64 ts;
} buffer __aligned(IIO_DMA_MINALIGN);
__le16 status;
__be16 duration;
@@ -194,7 +194,7 @@ const struct regmap_config bma400_regmap_config = {
.writeable_reg = bma400_is_writable_reg,
.volatile_reg = bma400_is_volatile_reg,
};
-EXPORT_SYMBOL_NS(bma400_regmap_config, IIO_BMA400);
+EXPORT_SYMBOL_NS(bma400_regmap_config, "IIO_BMA400");
static const struct iio_mount_matrix *
bma400_accel_get_mount_matrix(const struct iio_dev *indio_dev,
@@ -1293,7 +1293,7 @@ static int bma400_disable_adv_interrupt(struct bma400_data *data)
static int bma400_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct bma400_data *data = iio_priv(indio_dev);
int ret;
@@ -1763,7 +1763,7 @@ int bma400_probe(struct device *dev, struct regmap *regmap, int irq,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS(bma400_probe, IIO_BMA400);
+EXPORT_SYMBOL_NS(bma400_probe, "IIO_BMA400");
MODULE_AUTHOR("Dan Robertson <dan@dlrobertson.com>");
MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>");
diff --git a/drivers/iio/accel/bma400_i2c.c b/drivers/iio/accel/bma400_i2c.c
index c1c72f577295..24a390c3ae66 100644
--- a/drivers/iio/accel/bma400_i2c.c
+++ b/drivers/iio/accel/bma400_i2c.c
@@ -53,4 +53,4 @@ module_i2c_driver(bma400_i2c_driver);
MODULE_AUTHOR("Dan Robertson <dan@dlrobertson.com>");
MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor (I2C)");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_BMA400);
+MODULE_IMPORT_NS("IIO_BMA400");
diff --git a/drivers/iio/accel/bma400_spi.c b/drivers/iio/accel/bma400_spi.c
index 765d8c4a4c4d..d386f643515b 100644
--- a/drivers/iio/accel/bma400_spi.c
+++ b/drivers/iio/accel/bma400_spi.c
@@ -112,4 +112,4 @@ module_spi_driver(bma400_spi_driver);
MODULE_AUTHOR("Dan Robertson <dan@dlrobertson.com>");
MODULE_DESCRIPTION("Bosch BMA400 triaxial acceleration sensor (SPI)");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_BMA400);
+MODULE_IMPORT_NS("IIO_BMA400");
diff --git a/drivers/iio/accel/bmc150-accel-core.c b/drivers/iio/accel/bmc150-accel-core.c
index 0f32c1e92b4d..744a034bb8b5 100644
--- a/drivers/iio/accel/bmc150-accel-core.c
+++ b/drivers/iio/accel/bmc150-accel-core.c
@@ -203,7 +203,7 @@ const struct regmap_config bmc150_regmap_conf = {
.val_bits = 8,
.max_register = 0x3f,
};
-EXPORT_SYMBOL_NS_GPL(bmc150_regmap_conf, IIO_BMC150);
+EXPORT_SYMBOL_NS_GPL(bmc150_regmap_conf, "IIO_BMC150");
static int bmc150_accel_set_mode(struct bmc150_accel_data *data,
enum bmc150_power_modes mode,
@@ -804,7 +804,7 @@ static int bmc150_accel_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct bmc150_accel_data *data = iio_priv(indio_dev);
int ret;
@@ -1760,7 +1760,7 @@ err_disable_regulators:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(bmc150_accel_core_probe, IIO_BMC150);
+EXPORT_SYMBOL_NS_GPL(bmc150_accel_core_probe, "IIO_BMC150");
void bmc150_accel_core_remove(struct device *dev)
{
@@ -1783,7 +1783,7 @@ void bmc150_accel_core_remove(struct device *dev)
regulator_bulk_disable(ARRAY_SIZE(data->regulators),
data->regulators);
}
-EXPORT_SYMBOL_NS_GPL(bmc150_accel_core_remove, IIO_BMC150);
+EXPORT_SYMBOL_NS_GPL(bmc150_accel_core_remove, "IIO_BMC150");
#ifdef CONFIG_PM_SLEEP
static int bmc150_accel_suspend(struct device *dev)
@@ -1858,7 +1858,7 @@ const struct dev_pm_ops bmc150_accel_pm_ops = {
SET_RUNTIME_PM_OPS(bmc150_accel_runtime_suspend,
bmc150_accel_runtime_resume, NULL)
};
-EXPORT_SYMBOL_NS_GPL(bmc150_accel_pm_ops, IIO_BMC150);
+EXPORT_SYMBOL_NS_GPL(bmc150_accel_pm_ops, "IIO_BMC150");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/accel/bmc150-accel-i2c.c b/drivers/iio/accel/bmc150-accel-i2c.c
index 1c2e40369839..0d4ce6c38931 100644
--- a/drivers/iio/accel/bmc150-accel-i2c.c
+++ b/drivers/iio/accel/bmc150-accel-i2c.c
@@ -291,4 +291,4 @@ module_i2c_driver(bmc150_accel_driver);
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("BMC150 I2C accelerometer driver");
-MODULE_IMPORT_NS(IIO_BMC150);
+MODULE_IMPORT_NS("IIO_BMC150");
diff --git a/drivers/iio/accel/bmc150-accel-spi.c b/drivers/iio/accel/bmc150-accel-spi.c
index a6b9f599eb7b..70b3642656ab 100644
--- a/drivers/iio/accel/bmc150-accel-spi.c
+++ b/drivers/iio/accel/bmc150-accel-spi.c
@@ -81,4 +81,4 @@ module_spi_driver(bmc150_accel_driver);
MODULE_AUTHOR("Markus Pargmann <mpa@pengutronix.de>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("BMC150 SPI accelerometer driver");
-MODULE_IMPORT_NS(IIO_BMC150);
+MODULE_IMPORT_NS("IIO_BMC150");
diff --git a/drivers/iio/accel/bmc150-accel.h b/drivers/iio/accel/bmc150-accel.h
index 7775c5edaeef..7a7baf52e595 100644
--- a/drivers/iio/accel/bmc150-accel.h
+++ b/drivers/iio/accel/bmc150-accel.h
@@ -6,6 +6,7 @@
#include <linux/iio/iio.h>
#include <linux/mutex.h>
#include <linux/regulator/consumer.h>
+#include <linux/types.h>
#include <linux/workqueue.h>
struct regmap;
@@ -69,7 +70,7 @@ struct bmc150_accel_data {
*/
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
u8 bw_bits;
u32 slope_dur;
diff --git a/drivers/iio/accel/bmi088-accel-core.c b/drivers/iio/accel/bmi088-accel-core.c
index fc1c1613d673..9206fbdbf520 100644
--- a/drivers/iio/accel/bmi088-accel-core.c
+++ b/drivers/iio/accel/bmi088-accel-core.c
@@ -147,7 +147,7 @@ const struct regmap_config bmi088_regmap_conf = {
.volatile_table = &bmi088_volatile_table,
.cache_type = REGCACHE_RBTREE,
};
-EXPORT_SYMBOL_NS_GPL(bmi088_regmap_conf, IIO_BMI088);
+EXPORT_SYMBOL_NS_GPL(bmi088_regmap_conf, "IIO_BMI088");
static int bmi088_accel_power_up(struct bmi088_accel_data *data)
{
@@ -587,7 +587,7 @@ int bmi088_accel_core_probe(struct device *dev, struct regmap *regmap,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(bmi088_accel_core_probe, IIO_BMI088);
+EXPORT_SYMBOL_NS_GPL(bmi088_accel_core_probe, "IIO_BMI088");
void bmi088_accel_core_remove(struct device *dev)
@@ -601,7 +601,7 @@ void bmi088_accel_core_remove(struct device *dev)
pm_runtime_set_suspended(dev);
bmi088_accel_power_down(data);
}
-EXPORT_SYMBOL_NS_GPL(bmi088_accel_core_remove, IIO_BMI088);
+EXPORT_SYMBOL_NS_GPL(bmi088_accel_core_remove, "IIO_BMI088");
static int bmi088_accel_runtime_suspend(struct device *dev)
{
diff --git a/drivers/iio/accel/bmi088-accel-i2c.c b/drivers/iio/accel/bmi088-accel-i2c.c
index 17e9156bbe89..bd22bd0d3c25 100644
--- a/drivers/iio/accel/bmi088-accel-i2c.c
+++ b/drivers/iio/accel/bmi088-accel-i2c.c
@@ -67,4 +67,4 @@ module_i2c_driver(bmi088_accel_driver);
MODULE_AUTHOR("Jun Yan <jerrysteve1101@gmail.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("BMI088 accelerometer driver (I2C)");
-MODULE_IMPORT_NS(IIO_BMI088);
+MODULE_IMPORT_NS("IIO_BMI088");
diff --git a/drivers/iio/accel/bmi088-accel-spi.c b/drivers/iio/accel/bmi088-accel-spi.c
index df1adc059aa9..c9d51a74c07f 100644
--- a/drivers/iio/accel/bmi088-accel-spi.c
+++ b/drivers/iio/accel/bmi088-accel-spi.c
@@ -94,4 +94,4 @@ module_spi_driver(bmi088_accel_driver);
MODULE_AUTHOR("Niek van Agt <niek.van.agt@topicproducts.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("BMI088 accelerometer driver (SPI)");
-MODULE_IMPORT_NS(IIO_BMI088);
+MODULE_IMPORT_NS("IIO_BMI088");
diff --git a/drivers/iio/accel/fxls8962af-core.c b/drivers/iio/accel/fxls8962af-core.c
index acadabec4df7..65aac60f1245 100644
--- a/drivers/iio/accel/fxls8962af-core.c
+++ b/drivers/iio/accel/fxls8962af-core.c
@@ -22,6 +22,7 @@
#include <linux/property.h>
#include <linux/regulator/consumer.h>
#include <linux/regmap.h>
+#include <linux/types.h>
#include <linux/iio/buffer.h>
#include <linux/iio/events.h>
@@ -163,7 +164,7 @@ struct fxls8962af_data {
const struct fxls8962af_chip_info *chip_info;
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
int64_t timestamp, old_timestamp; /* Only used in hw fifo mode. */
struct iio_mount_matrix orientation;
@@ -179,7 +180,7 @@ const struct regmap_config fxls8962af_i2c_regmap_conf = {
.val_bits = 8,
.max_register = FXLS8962AF_MAX_REG,
};
-EXPORT_SYMBOL_NS_GPL(fxls8962af_i2c_regmap_conf, IIO_FXLS8962AF);
+EXPORT_SYMBOL_NS_GPL(fxls8962af_i2c_regmap_conf, "IIO_FXLS8962AF");
const struct regmap_config fxls8962af_spi_regmap_conf = {
.reg_bits = 8,
@@ -187,7 +188,7 @@ const struct regmap_config fxls8962af_spi_regmap_conf = {
.val_bits = 8,
.max_register = FXLS8962AF_MAX_REG,
};
-EXPORT_SYMBOL_NS_GPL(fxls8962af_spi_regmap_conf, IIO_FXLS8962AF);
+EXPORT_SYMBOL_NS_GPL(fxls8962af_spi_regmap_conf, "IIO_FXLS8962AF");
enum {
fxls8962af_idx_x,
@@ -616,7 +617,7 @@ static int
fxls8962af_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct fxls8962af_data *data = iio_priv(indio_dev);
u8 enable_event, enable_bits;
@@ -1103,8 +1104,7 @@ static int fxls8962af_irq_setup(struct iio_dev *indio_dev, int irq)
if (ret)
return ret;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(irq));
-
+ irq_type = irq_get_trigger_type(irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
@@ -1220,7 +1220,7 @@ int fxls8962af_core_probe(struct device *dev, struct regmap *regmap, int irq)
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(fxls8962af_core_probe, IIO_FXLS8962AF);
+EXPORT_SYMBOL_NS_GPL(fxls8962af_core_probe, "IIO_FXLS8962AF");
static int fxls8962af_runtime_suspend(struct device *dev)
{
diff --git a/drivers/iio/accel/fxls8962af-i2c.c b/drivers/iio/accel/fxls8962af-i2c.c
index 160124673308..2e1bb43ef2a1 100644
--- a/drivers/iio/accel/fxls8962af-i2c.c
+++ b/drivers/iio/accel/fxls8962af-i2c.c
@@ -55,4 +55,4 @@ module_i2c_driver(fxls8962af_driver);
MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.com>");
MODULE_DESCRIPTION("NXP FXLS8962AF/FXLS8964AF accelerometer i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_FXLS8962AF);
+MODULE_IMPORT_NS("IIO_FXLS8962AF");
diff --git a/drivers/iio/accel/fxls8962af-spi.c b/drivers/iio/accel/fxls8962af-spi.c
index a0d192211839..46fc6e002714 100644
--- a/drivers/iio/accel/fxls8962af-spi.c
+++ b/drivers/iio/accel/fxls8962af-spi.c
@@ -55,4 +55,4 @@ module_spi_driver(fxls8962af_driver);
MODULE_AUTHOR("Sean Nyekjaer <sean@geanix.com>");
MODULE_DESCRIPTION("NXP FXLS8962AF/FXLS8964AF accelerometer spi driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_FXLS8962AF);
+MODULE_IMPORT_NS("IIO_FXLS8962AF");
diff --git a/drivers/iio/accel/hid-sensor-accel-3d.c b/drivers/iio/accel/hid-sensor-accel-3d.c
index 9b7a73a4c48a..078fab2abb68 100644
--- a/drivers/iio/accel/hid-sensor-accel-3d.c
+++ b/drivers/iio/accel/hid-sensor-accel-3d.c
@@ -28,7 +28,7 @@ struct accel_3d_state {
/* Ensure timestamp is naturally aligned */
struct {
u32 accel_val[3];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -328,6 +328,7 @@ static int accel_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_accel_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
const char *name;
struct iio_dev *indio_dev;
@@ -335,8 +336,6 @@ static int hid_accel_3d_probe(struct platform_device *pdev)
const struct iio_chan_spec *channel_spec;
int channel_size;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
-
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct accel_3d_state));
if (indio_dev == NULL)
@@ -424,7 +423,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_accel_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct accel_3d_state *accel_state = iio_priv(indio_dev);
@@ -452,11 +451,11 @@ static struct platform_driver hid_accel_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_accel_3d_probe,
- .remove_new = hid_accel_3d_remove,
+ .remove = hid_accel_3d_remove,
};
module_platform_driver(hid_accel_3d_platform_driver);
MODULE_DESCRIPTION("HID Sensor Accel 3D");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/accel/kionix-kx022a-i2c.c b/drivers/iio/accel/kionix-kx022a-i2c.c
index 8a1d4fc28ddd..b39a43ecadff 100644
--- a/drivers/iio/accel/kionix-kx022a-i2c.c
+++ b/drivers/iio/accel/kionix-kx022a-i2c.c
@@ -65,4 +65,4 @@ module_i2c_driver(kx022a_i2c_driver);
MODULE_DESCRIPTION("ROHM/Kionix KX022A accelerometer driver");
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_KX022A);
+MODULE_IMPORT_NS("IIO_KX022A");
diff --git a/drivers/iio/accel/kionix-kx022a-spi.c b/drivers/iio/accel/kionix-kx022a-spi.c
index f798b964d0b5..c38a47806a00 100644
--- a/drivers/iio/accel/kionix-kx022a-spi.c
+++ b/drivers/iio/accel/kionix-kx022a-spi.c
@@ -65,4 +65,4 @@ module_spi_driver(kx022a_spi_driver);
MODULE_DESCRIPTION("ROHM/Kionix kx022A accelerometer driver");
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_KX022A);
+MODULE_IMPORT_NS("IIO_KX022A");
diff --git a/drivers/iio/accel/kionix-kx022a.c b/drivers/iio/accel/kionix-kx022a.c
index 53d59a04ae15..670bac21965b 100644
--- a/drivers/iio/accel/kionix-kx022a.c
+++ b/drivers/iio/accel/kionix-kx022a.c
@@ -16,6 +16,7 @@
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/string_choices.h>
+#include <linux/types.h>
#include <linux/units.h>
#include <linux/iio/iio.h>
@@ -292,7 +293,7 @@ struct kx022a_data {
__le16 buffer[8] __aligned(IIO_DMA_MINALIGN);
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
};
@@ -594,7 +595,7 @@ static int kx022a_get_axis(struct kx022a_data *data,
if (ret)
return ret;
- *val = le16_to_cpu(data->buffer[0]);
+ *val = (s16)le16_to_cpu(data->buffer[0]);
return IIO_VAL_INT;
}
@@ -1175,7 +1176,7 @@ const struct kx022a_chip_info kx022a_chip_info = {
.xout_l = KX022A_REG_XOUT_L,
.get_fifo_bytes_available = kx022a_get_fifo_bytes_available,
};
-EXPORT_SYMBOL_NS_GPL(kx022a_chip_info, IIO_KX022A);
+EXPORT_SYMBOL_NS_GPL(kx022a_chip_info, "IIO_KX022A");
const struct kx022a_chip_info kx132_chip_info = {
.name = "kx132-1211",
@@ -1201,7 +1202,7 @@ const struct kx022a_chip_info kx132_chip_info = {
.xout_l = KX132_REG_XOUT_L,
.get_fifo_bytes_available = kx132_get_fifo_bytes_available,
};
-EXPORT_SYMBOL_NS_GPL(kx132_chip_info, IIO_KX022A);
+EXPORT_SYMBOL_NS_GPL(kx132_chip_info, "IIO_KX022A");
/*
* Despite the naming, KX132ACR-LBZ is not similar to KX132-1211 but it is
@@ -1233,7 +1234,7 @@ const struct kx022a_chip_info kx132acr_chip_info = {
.xout_l = KX022A_REG_XOUT_L,
.get_fifo_bytes_available = kx022a_get_fifo_bytes_available,
};
-EXPORT_SYMBOL_NS_GPL(kx132acr_chip_info, IIO_KX022A);
+EXPORT_SYMBOL_NS_GPL(kx132acr_chip_info, "IIO_KX022A");
int kx022a_probe_internal(struct device *dev, const struct kx022a_chip_info *chip_info)
{
@@ -1371,7 +1372,7 @@ int kx022a_probe_internal(struct device *dev, const struct kx022a_chip_info *chi
return ret;
}
-EXPORT_SYMBOL_NS_GPL(kx022a_probe_internal, IIO_KX022A);
+EXPORT_SYMBOL_NS_GPL(kx022a_probe_internal, "IIO_KX022A");
MODULE_DESCRIPTION("ROHM/Kionix KX022A accelerometer driver");
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
diff --git a/drivers/iio/accel/kxcjk-1013.c b/drivers/iio/accel/kxcjk-1013.c
index b76df8816323..f2496cad8ec2 100644
--- a/drivers/iio/accel/kxcjk-1013.c
+++ b/drivers/iio/accel/kxcjk-1013.c
@@ -4,13 +4,15 @@
* Copyright (c) 2014, Intel Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/bitops.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/types.h>
#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
@@ -168,14 +170,73 @@
#define KXCJK1013_DEFAULT_WAKE_THRES 1
-enum kx_chipset {
- KXCJK1013,
- KXCJ91008,
- KXTJ21009,
- KXTF9,
- KX0221020,
- KX0231025,
- KX_MAX_CHIPS /* this must be last */
+/* Refer to section 4 of the specification */
+struct kx_odr_start_up_time {
+ int odr_bits;
+ int usec;
+};
+
+/* KXCJK-1013 */
+static const struct kx_odr_start_up_time kxcjk1013_odr_start_up_times[] = {
+ { 0x08, 100000 },
+ { 0x09, 100000 },
+ { 0x0A, 100000 },
+ { 0x0B, 100000 },
+ { 0x00, 80000 },
+ { 0x01, 41000 },
+ { 0x02, 21000 },
+ { 0x03, 11000 },
+ { 0x04, 6400 },
+ { 0x05, 3900 },
+ { 0x06, 2700 },
+ { 0x07, 2100 },
+ { }
+};
+
+/* KXCTJ2-1009 */
+static const struct kx_odr_start_up_time kxtj21009_odr_start_up_times[] = {
+ { 0x08, 1240000 },
+ { 0x09, 621000 },
+ { 0x0A, 309000 },
+ { 0x0B, 151000 },
+ { 0x00, 80000 },
+ { 0x01, 41000 },
+ { 0x02, 21000 },
+ { 0x03, 11000 },
+ { 0x04, 6000 },
+ { 0x05, 4000 },
+ { 0x06, 3000 },
+ { 0x07, 2000 },
+ { }
+};
+
+/* KXTF9 */
+static const struct kx_odr_start_up_time kxtf9_odr_start_up_times[] = {
+ { 0x01, 81000 },
+ { 0x02, 41000 },
+ { 0x03, 21000 },
+ { 0x04, 11000 },
+ { 0x05, 5100 },
+ { 0x06, 2700 },
+ { }
+};
+
+/* KX023-1025 */
+static const struct kx_odr_start_up_time kx0231025_odr_start_up_times[] = {
+ /* First 4 are not in datasheet, taken from KXCTJ2-1009 */
+ { 0x08, 1240000 },
+ { 0x09, 621000 },
+ { 0x0A, 309000 },
+ { 0x0B, 151000 },
+ { 0x00, 81000 },
+ { 0x01, 40000 },
+ { 0x02, 22000 },
+ { 0x03, 12000 },
+ { 0x04, 7000 },
+ { 0x05, 4400 },
+ { 0x06, 3000 },
+ { 0x07, 3000 },
+ { }
};
enum kx_acpi_type {
@@ -234,6 +295,55 @@ static const struct kx_chipset_regs kx0231025_regs = {
.wake_thres = KX023_REG_ATH,
};
+struct kx_chipset_info {
+ const struct kx_chipset_regs *regs;
+ const struct kx_odr_start_up_time *times;
+ enum kx_acpi_type acpi_type;
+};
+
+static const struct kx_chipset_info kxcjk1013_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kxcj91008_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kxcj91008_kiox010a_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+ .acpi_type = ACPI_KIOX010A,
+};
+
+static const struct kx_chipset_info kxcj91008_kiox020a_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+ .acpi_type = ACPI_GENERIC,
+};
+
+static const struct kx_chipset_info kxcj91008_smo8500_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxcjk1013_odr_start_up_times),
+ .acpi_type = ACPI_SMO8500,
+};
+
+static const struct kx_chipset_info kxtj21009_info = {
+ .regs = &kxcjk1013_regs,
+ .times = pm_ptr(kxtj21009_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kxtf9_info = {
+ .regs = &kxtf9_regs,
+ .times = pm_ptr(kxtf9_odr_start_up_times),
+};
+
+static const struct kx_chipset_info kx0231025_info = {
+ .regs = &kx0231025_regs,
+ .times = pm_ptr(kx0231025_odr_start_up_times),
+};
+
enum kxcjk1013_axis {
AXIS_X,
AXIS_Y,
@@ -250,7 +360,7 @@ struct kxcjk1013_data {
/* Ensure timestamp naturally aligned */
struct {
s16 chans[AXIS_MAX];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
u8 odr_bits;
u8 range;
@@ -261,9 +371,7 @@ struct kxcjk1013_data {
int ev_enable_state;
bool motion_trigger_on;
int64_t timestamp;
- enum kx_chipset chipset;
- enum kx_acpi_type acpi_type;
- const struct kx_chipset_regs *regs;
+ const struct kx_chipset_info *info;
};
enum kxcjk1013_mode {
@@ -314,83 +422,6 @@ static const struct kx_odr_map kxtf9_samp_freq_table[] = {
static const char *const kxtf9_samp_freq_avail =
"25 50 100 200 400 800";
-/* Refer to section 4 of the specification */
-static __maybe_unused const struct {
- int odr_bits;
- int usec;
-} odr_start_up_times[KX_MAX_CHIPS][12] = {
- /* KXCJK-1013 */
- {
- {0x08, 100000},
- {0x09, 100000},
- {0x0A, 100000},
- {0x0B, 100000},
- {0, 80000},
- {0x01, 41000},
- {0x02, 21000},
- {0x03, 11000},
- {0x04, 6400},
- {0x05, 3900},
- {0x06, 2700},
- {0x07, 2100},
- },
- /* KXCJ9-1008 */
- {
- {0x08, 100000},
- {0x09, 100000},
- {0x0A, 100000},
- {0x0B, 100000},
- {0, 80000},
- {0x01, 41000},
- {0x02, 21000},
- {0x03, 11000},
- {0x04, 6400},
- {0x05, 3900},
- {0x06, 2700},
- {0x07, 2100},
- },
- /* KXCTJ2-1009 */
- {
- {0x08, 1240000},
- {0x09, 621000},
- {0x0A, 309000},
- {0x0B, 151000},
- {0, 80000},
- {0x01, 41000},
- {0x02, 21000},
- {0x03, 11000},
- {0x04, 6000},
- {0x05, 4000},
- {0x06, 3000},
- {0x07, 2000},
- },
- /* KXTF9 */
- {
- {0x01, 81000},
- {0x02, 41000},
- {0x03, 21000},
- {0x04, 11000},
- {0x05, 5100},
- {0x06, 2700},
- },
- /* KX023-1025 */
- {
- /* First 4 are not in datasheet, taken from KXCTJ2-1009 */
- {0x08, 1240000},
- {0x09, 621000},
- {0x0A, 309000},
- {0x0B, 151000},
- {0, 81000},
- {0x01, 40000},
- {0x02, 22000},
- {0x03, 12000},
- {0x04, 7000},
- {0x05, 4400},
- {0x06, 3000},
- {0x07, 3000},
- },
-};
-
static const struct {
u16 scale;
u8 gsel_0;
@@ -424,30 +455,15 @@ static int kiox010a_dsm(struct device *dev, int fn_index)
return 0;
}
-static const struct acpi_device_id kx_acpi_match[] = {
- {"KXCJ1013", KXCJK1013},
- {"KXCJ1008", KXCJ91008},
- {"KXCJ9000", KXCJ91008},
- {"KIOX0008", KXCJ91008},
- {"KIOX0009", KXTJ21009},
- {"KIOX000A", KXCJ91008},
- {"KIOX010A", KXCJ91008}, /* KXCJ91008 in the display of a yoga 2-in-1 */
- {"KIOX020A", KXCJ91008}, /* KXCJ91008 in the base of a yoga 2-in-1 */
- {"KXTJ1009", KXTJ21009},
- {"KXJ2109", KXTJ21009},
- {"SMO8500", KXCJ91008},
- { }
-};
-MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
-
#endif
static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
enum kxcjk1013_mode mode)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -458,7 +474,7 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
else
ret |= KXCJK1013_REG_CTRL1_BIT_PC1;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -470,9 +486,10 @@ static int kxcjk1013_set_mode(struct kxcjk1013_data *data,
static int kxcjk1013_get_mode(struct kxcjk1013_data *data,
enum kxcjk1013_mode *mode)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -488,9 +505,10 @@ static int kxcjk1013_get_mode(struct kxcjk1013_data *data,
static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -501,7 +519,7 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
ret |= (KXCJK1013_scale_table[range_index].gsel_0 << 3);
ret |= (KXCJK1013_scale_table[range_index].gsel_1 << 4);
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -514,10 +532,11 @@ static int kxcjk1013_set_range(struct kxcjk1013_data *data, int range_index)
static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
#ifdef CONFIG_ACPI
- if (data->acpi_type == ACPI_KIOX010A) {
+ if (data->info->acpi_type == ACPI_KIOX010A) {
/* Make sure the kbd and touchpad on 2-in-1s using 2 KXCJ91008-s work */
kiox010a_dsm(&data->client->dev, KIOX010A_SET_LAPTOP_MODE);
}
@@ -535,7 +554,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -544,7 +563,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
/* Set 12 bit mode */
ret |= KXCJK1013_REG_CTRL1_BIT_RES;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl\n");
return ret;
@@ -555,7 +574,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->data_ctrl);
+ ret = i2c_smbus_read_byte_data(data->client, regs->data_ctrl);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_data_ctrl\n");
return ret;
@@ -564,7 +583,7 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
data->odr_bits = ret;
/* Set up INT polarity */
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
return ret;
@@ -575,14 +594,14 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEA;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
return ret;
}
- /* On KX023 and KX022, route all used interrupts to INT1 for now */
- if ((data->chipset == KX0231025 || data->chipset == KX0221020) && data->client->irq > 0) {
+ /* On KX023, route all used interrupts to INT1 for now */
+ if (data->info == &kx0231025_info && data->client->irq > 0) {
ret = i2c_smbus_write_byte_data(data->client, KX023_REG_INC4,
KX023_REG_INC4_DRDY1 |
KX023_REG_INC4_WUFI1);
@@ -601,20 +620,17 @@ static int kxcjk1013_chip_init(struct kxcjk1013_data *data)
return 0;
}
-#ifdef CONFIG_PM
static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data)
{
- int i;
- int idx = data->chipset;
+ const struct kx_odr_start_up_time *times;
- for (i = 0; i < ARRAY_SIZE(odr_start_up_times[idx]); ++i) {
- if (odr_start_up_times[idx][i].odr_bits == data->odr_bits)
- return odr_start_up_times[idx][i].usec;
+ for (times = data->info->times; times->usec; times++) {
+ if (times->odr_bits == data->odr_bits)
+ return times->usec;
}
return KXCJK1013_MAX_STARTUP_TIME_US;
}
-#endif
static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
{
@@ -639,18 +655,17 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_timer,
- data->wake_dur);
+ ret = i2c_smbus_write_byte_data(data->client, regs->wake_timer, data->wake_dur);
if (ret < 0) {
dev_err(&data->client->dev,
"Error writing reg_wake_timer\n");
return ret;
}
- ret = i2c_smbus_write_byte_data(data->client, data->regs->wake_thres,
- data->wake_thres);
+ ret = i2c_smbus_write_byte_data(data->client, regs->wake_thres, data->wake_thres);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_wake_thres\n");
return ret;
@@ -662,6 +677,7 @@ static int kxcjk1013_chip_update_thresholds(struct kxcjk1013_data *data)
static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
bool status)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
enum kxcjk1013_mode store_mode;
@@ -678,7 +694,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
return ret;
@@ -689,13 +705,13 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
return ret;
}
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -706,7 +722,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_CTRL1_BIT_WUFE;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -724,6 +740,7 @@ static int kxcjk1013_setup_any_motion_interrupt(struct kxcjk1013_data *data,
static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
bool status)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
enum kxcjk1013_mode store_mode;
@@ -736,7 +753,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
if (ret < 0)
return ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_ctrl1\n");
return ret;
@@ -747,13 +764,13 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_INT_CTRL1_BIT_IEN;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->int_ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->int_ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_int_ctrl1\n");
return ret;
}
- ret = i2c_smbus_read_byte_data(data->client, data->regs->ctrl1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->ctrl1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_ctrl1\n");
return ret;
@@ -764,7 +781,7 @@ static int kxcjk1013_setup_new_data_interrupt(struct kxcjk1013_data *data,
else
ret &= ~KXCJK1013_REG_CTRL1_BIT_DRDY;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->ctrl1, ret);
+ ret = i2c_smbus_write_byte_data(data->client, regs->ctrl1, ret);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl1\n");
return ret;
@@ -811,6 +828,7 @@ static int kxcjk1013_convert_odr_value(const struct kx_odr_map *map,
static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
{
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
enum kxcjk1013_mode store_mode;
const struct kx_odr_map *odr_setting;
@@ -819,7 +837,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
if (ret < 0)
return ret;
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
odr_setting = kxcjk1013_find_odr_value(kxtf9_samp_freq_table,
ARRAY_SIZE(kxtf9_samp_freq_table),
val, val2);
@@ -836,7 +854,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
if (ret < 0)
return ret;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->data_ctrl,
+ ret = i2c_smbus_write_byte_data(data->client, regs->data_ctrl,
odr_setting->odr_bits);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing data_ctrl\n");
@@ -845,7 +863,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
data->odr_bits = odr_setting->odr_bits;
- ret = i2c_smbus_write_byte_data(data->client, data->regs->wuf_ctrl,
+ ret = i2c_smbus_write_byte_data(data->client, regs->wuf_ctrl,
odr_setting->wuf_bits);
if (ret < 0) {
dev_err(&data->client->dev, "Error writing reg_ctrl2\n");
@@ -863,7 +881,7 @@ static int kxcjk1013_set_odr(struct kxcjk1013_data *data, int val, int val2)
static int kxcjk1013_get_odr(struct kxcjk1013_data *data, int *val, int *val2)
{
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
return kxcjk1013_convert_odr_value(kxtf9_samp_freq_table,
ARRAY_SIZE(kxtf9_samp_freq_table),
data->odr_bits, val, val2);
@@ -1063,7 +1081,7 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct kxcjk1013_data *data = iio_priv(indio_dev);
int ret;
@@ -1130,7 +1148,7 @@ static ssize_t kxcjk1013_get_samp_freq_avail(struct device *dev,
struct kxcjk1013_data *data = iio_priv(indio_dev);
const char *str;
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
str = kxtf9_samp_freq_avail;
else
str = kxcjk1013_samp_freq_avail;
@@ -1207,7 +1225,7 @@ static const struct iio_buffer_setup_ops kxcjk1013_buffer_setup_ops = {
.postdisable = kxcjk1013_buffer_postdisable,
};
-static const struct iio_info kxcjk1013_info = {
+static const struct iio_info kxcjk1013_iio_info = {
.attrs = &kxcjk1013_attrs_group,
.read_raw = kxcjk1013_read_raw,
.write_raw = kxcjk1013_write_raw,
@@ -1247,9 +1265,10 @@ static void kxcjk1013_trig_reen(struct iio_trigger *trig)
{
struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
struct kxcjk1013_data *data = iio_priv(indio_dev);
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_rel);
if (ret < 0)
dev_err(&data->client->dev, "Error reading reg_int_rel\n");
}
@@ -1301,8 +1320,9 @@ static const struct iio_trigger_ops kxcjk1013_trigger_ops = {
static void kxcjk1013_report_motion_event(struct iio_dev *indio_dev)
{
struct kxcjk1013_data *data = iio_priv(indio_dev);
+ const struct kx_chipset_regs *regs = data->info->regs;
- int ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src2);
+ int ret = i2c_smbus_read_byte_data(data->client, regs->int_src2);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_src2\n");
return;
@@ -1367,16 +1387,17 @@ static irqreturn_t kxcjk1013_event_handler(int irq, void *private)
{
struct iio_dev *indio_dev = private;
struct kxcjk1013_data *data = iio_priv(indio_dev);
+ const struct kx_chipset_regs *regs = data->info->regs;
int ret;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_src1);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_src1);
if (ret < 0) {
dev_err(&data->client->dev, "Error reading reg_int_src1\n");
goto ack_intr;
}
if (ret & KXCJK1013_REG_INT_SRC1_BIT_WUFS) {
- if (data->chipset == KXTF9)
+ if (data->info == &kxtf9_info)
iio_push_event(indio_dev,
IIO_MOD_EVENT_CODE(IIO_ACCEL,
0,
@@ -1392,7 +1413,7 @@ ack_intr:
if (data->dready_trigger_on)
return IRQ_HANDLED;
- ret = i2c_smbus_read_byte_data(data->client, data->regs->int_rel);
+ ret = i2c_smbus_read_byte_data(data->client, regs->int_rel);
if (ret < 0)
dev_err(&data->client->dev, "Error reading reg_int_rel\n");
@@ -1417,31 +1438,6 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
return IRQ_HANDLED;
}
-static const char *kxcjk1013_match_acpi_device(struct device *dev,
- enum kx_chipset *chipset,
- enum kx_acpi_type *acpi_type,
- const char **label)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- if (strcmp(id->id, "SMO8500") == 0) {
- *acpi_type = ACPI_SMO8500;
- } else if (strcmp(id->id, "KIOX010A") == 0) {
- *acpi_type = ACPI_KIOX010A;
- *label = "accel-display";
- } else if (strcmp(id->id, "KIOX020A") == 0) {
- *label = "accel-base";
- }
-
- *chipset = (enum kx_chipset)id->driver_data;
-
- return dev_name(dev);
-}
-
static int kxcjk1013_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -1449,6 +1445,7 @@ static int kxcjk1013_probe(struct i2c_client *client)
struct kxcjk1013_data *data;
struct iio_dev *indio_dev;
struct kxcjk_1013_platform_data *pdata;
+ const void *ddata = NULL;
const char *name;
int ret;
@@ -1489,32 +1486,18 @@ static int kxcjk1013_probe(struct i2c_client *client)
msleep(20);
if (id) {
- data->chipset = (enum kx_chipset)(id->driver_data);
name = id->name;
- } else if (ACPI_HANDLE(&client->dev)) {
- name = kxcjk1013_match_acpi_device(&client->dev,
- &data->chipset,
- &data->acpi_type,
- &indio_dev->label);
- } else
- return -ENODEV;
-
- switch (data->chipset) {
- case KXCJK1013:
- case KXCJ91008:
- case KXTJ21009:
- data->regs = &kxcjk1013_regs;
- break;
- case KXTF9:
- data->regs = &kxtf9_regs;
- break;
- case KX0221020:
- case KX0231025:
- data->regs = &kx0231025_regs;
- break;
- default:
- return -EINVAL;
+ data->info = (const struct kx_chipset_info *)(id->driver_data);
+ } else {
+ name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
+ data->info = ddata;
+ if (data->info == &kxcj91008_kiox010a_info)
+ indio_dev->label = "accel-display";
+ else if (data->info == &kxcj91008_kiox020a_info)
+ indio_dev->label = "accel-base";
}
+ if (!name)
+ return -ENODEV;
ret = kxcjk1013_chip_init(data);
if (ret < 0)
@@ -1527,9 +1510,9 @@ static int kxcjk1013_probe(struct i2c_client *client)
indio_dev->available_scan_masks = kxcjk1013_scan_masks;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->info = &kxcjk1013_info;
+ indio_dev->info = &kxcjk1013_iio_info;
- if (client->irq > 0 && data->acpi_type != ACPI_SMO8500) {
+ if (client->irq > 0 && data->info->acpi_type != ACPI_SMO8500) {
ret = devm_request_threaded_irq(&client->dev, client->irq,
kxcjk1013_data_rdy_trig_poll,
kxcjk1013_event_handler,
@@ -1637,7 +1620,6 @@ static void kxcjk1013_remove(struct i2c_client *client)
mutex_unlock(&data->mutex);
}
-#ifdef CONFIG_PM_SLEEP
static int kxcjk1013_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
@@ -1665,9 +1647,7 @@ static int kxcjk1013_resume(struct device *dev)
return ret;
}
-#endif
-#ifdef CONFIG_PM
static int kxcjk1013_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
@@ -1701,44 +1681,56 @@ static int kxcjk1013_runtime_resume(struct device *dev)
return 0;
}
-#endif
static const struct dev_pm_ops kxcjk1013_pm_ops = {
- SET_SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume)
- SET_RUNTIME_PM_OPS(kxcjk1013_runtime_suspend,
- kxcjk1013_runtime_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(kxcjk1013_suspend, kxcjk1013_resume)
+ RUNTIME_PM_OPS(kxcjk1013_runtime_suspend, kxcjk1013_runtime_resume, NULL)
};
static const struct i2c_device_id kxcjk1013_id[] = {
- {"kxcjk1013", KXCJK1013},
- {"kxcj91008", KXCJ91008},
- {"kxtj21009", KXTJ21009},
- {"kxtf9", KXTF9},
- {"kx022-1020", KX0221020},
- {"kx023-1025", KX0231025},
- {"SMO8500", KXCJ91008},
- {}
+ { "kxcjk1013", (kernel_ulong_t)&kxcjk1013_info },
+ { "kxcj91008", (kernel_ulong_t)&kxcj91008_info },
+ { "kxtj21009", (kernel_ulong_t)&kxtj21009_info },
+ { "kxtf9", (kernel_ulong_t)&kxtf9_info },
+ { "kx023-1025", (kernel_ulong_t)&kx0231025_info },
+ { }
};
-
MODULE_DEVICE_TABLE(i2c, kxcjk1013_id);
static const struct of_device_id kxcjk1013_of_match[] = {
- { .compatible = "kionix,kxcjk1013", },
- { .compatible = "kionix,kxcj91008", },
- { .compatible = "kionix,kxtj21009", },
- { .compatible = "kionix,kxtf9", },
- { .compatible = "kionix,kx022-1020", },
- { .compatible = "kionix,kx023-1025", },
+ { .compatible = "kionix,kxcjk1013", &kxcjk1013_info },
+ { .compatible = "kionix,kxcj91008", &kxcj91008_info },
+ { .compatible = "kionix,kxtj21009", &kxtj21009_info },
+ { .compatible = "kionix,kxtf9", &kxtf9_info },
+ { .compatible = "kionix,kx023-1025", &kx0231025_info },
{ }
};
MODULE_DEVICE_TABLE(of, kxcjk1013_of_match);
+static const struct acpi_device_id kx_acpi_match[] = {
+ { "KIOX0008", (kernel_ulong_t)&kxcj91008_info },
+ { "KIOX0009", (kernel_ulong_t)&kxtj21009_info },
+ { "KIOX000A", (kernel_ulong_t)&kxcj91008_info },
+ /* KXCJ91008 in the display of a yoga 2-in-1 */
+ { "KIOX010A", (kernel_ulong_t)&kxcj91008_kiox010a_info },
+ /* KXCJ91008 in the base of a yoga 2-in-1 */
+ { "KIOX020A", (kernel_ulong_t)&kxcj91008_kiox020a_info },
+ { "KXCJ1008", (kernel_ulong_t)&kxcj91008_info },
+ { "KXCJ1013", (kernel_ulong_t)&kxcjk1013_info },
+ { "KXCJ9000", (kernel_ulong_t)&kxcj91008_info },
+ { "KXJ2109", (kernel_ulong_t)&kxtj21009_info },
+ { "KXTJ1009", (kernel_ulong_t)&kxtj21009_info },
+ { "SMO8500", (kernel_ulong_t)&kxcj91008_smo8500_info },
+ { }
+};
+MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
+
static struct i2c_driver kxcjk1013_driver = {
.driver = {
.name = KXCJK1013_DRV_NAME,
- .acpi_match_table = ACPI_PTR(kx_acpi_match),
+ .acpi_match_table = kx_acpi_match,
.of_match_table = kxcjk1013_of_match,
- .pm = &kxcjk1013_pm_ops,
+ .pm = pm_ptr(&kxcjk1013_pm_ops),
},
.probe = kxcjk1013_probe,
.remove = kxcjk1013_remove,
diff --git a/drivers/iio/accel/kxsd9-i2c.c b/drivers/iio/accel/kxsd9-i2c.c
index c4c7e2d4e98a..3857d2edf250 100644
--- a/drivers/iio/accel/kxsd9-i2c.c
+++ b/drivers/iio/accel/kxsd9-i2c.c
@@ -62,4 +62,4 @@ module_i2c_driver(kxsd9_i2c_driver);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("KXSD9 accelerometer I2C interface");
-MODULE_IMPORT_NS(IIO_KXSD9);
+MODULE_IMPORT_NS("IIO_KXSD9");
diff --git a/drivers/iio/accel/kxsd9-spi.c b/drivers/iio/accel/kxsd9-spi.c
index 4414670dfb43..a05f4467d94a 100644
--- a/drivers/iio/accel/kxsd9-spi.c
+++ b/drivers/iio/accel/kxsd9-spi.c
@@ -63,4 +63,4 @@ module_spi_driver(kxsd9_spi_driver);
MODULE_AUTHOR("Jonathan Cameron <jic23@kernel.org>");
MODULE_DESCRIPTION("Kionix KXSD9 SPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_KXSD9);
+MODULE_IMPORT_NS("IIO_KXSD9");
diff --git a/drivers/iio/accel/kxsd9.c b/drivers/iio/accel/kxsd9.c
index 70dfd6e354db..0ededf8cfdca 100644
--- a/drivers/iio/accel/kxsd9.c
+++ b/drivers/iio/accel/kxsd9.c
@@ -15,6 +15,7 @@
#include <linux/kernel.h>
#include <linux/sysfs.h>
#include <linux/slab.h>
+#include <linux/types.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/bitops.h>
@@ -215,7 +216,7 @@ static irqreturn_t kxsd9_trigger_handler(int irq, void *p)
*/
struct {
__be16 chan[4];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} hw_values;
int ret;
@@ -473,7 +474,7 @@ err_power_down:
return ret;
}
-EXPORT_SYMBOL_NS(kxsd9_common_probe, IIO_KXSD9);
+EXPORT_SYMBOL_NS(kxsd9_common_probe, "IIO_KXSD9");
void kxsd9_common_remove(struct device *dev)
{
@@ -487,7 +488,7 @@ void kxsd9_common_remove(struct device *dev)
pm_runtime_disable(dev);
kxsd9_power_down(st);
}
-EXPORT_SYMBOL_NS(kxsd9_common_remove, IIO_KXSD9);
+EXPORT_SYMBOL_NS(kxsd9_common_remove, "IIO_KXSD9");
static int kxsd9_runtime_suspend(struct device *dev)
{
diff --git a/drivers/iio/accel/mma7455_core.c b/drivers/iio/accel/mma7455_core.c
index a34195b3215d..30746621052c 100644
--- a/drivers/iio/accel/mma7455_core.c
+++ b/drivers/iio/accel/mma7455_core.c
@@ -19,6 +19,7 @@
#include <linux/iio/triggered_buffer.h>
#include <linux/module.h>
#include <linux/regmap.h>
+#include <linux/types.h>
#include "mma7455.h"
@@ -58,7 +59,7 @@ struct mma7455_data {
*/
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan;
};
@@ -238,7 +239,7 @@ const struct regmap_config mma7455_core_regmap = {
.val_bits = 8,
.max_register = MMA7455_REG_TW,
};
-EXPORT_SYMBOL_NS_GPL(mma7455_core_regmap, IIO_MMA7455);
+EXPORT_SYMBOL_NS_GPL(mma7455_core_regmap, "IIO_MMA7455");
int mma7455_core_probe(struct device *dev, struct regmap *regmap,
const char *name)
@@ -293,7 +294,7 @@ int mma7455_core_probe(struct device *dev, struct regmap *regmap,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(mma7455_core_probe, IIO_MMA7455);
+EXPORT_SYMBOL_NS_GPL(mma7455_core_probe, "IIO_MMA7455");
void mma7455_core_remove(struct device *dev)
{
@@ -306,7 +307,7 @@ void mma7455_core_remove(struct device *dev)
regmap_write(mma7455->regmap, MMA7455_REG_MCTL,
MMA7455_MCTL_MODE_STANDBY);
}
-EXPORT_SYMBOL_NS_GPL(mma7455_core_remove, IIO_MMA7455);
+EXPORT_SYMBOL_NS_GPL(mma7455_core_remove, "IIO_MMA7455");
MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
MODULE_DESCRIPTION("Freescale MMA7455L core accelerometer driver");
diff --git a/drivers/iio/accel/mma7455_i2c.c b/drivers/iio/accel/mma7455_i2c.c
index 36a357c8e9ed..2ff8eb1f9ce9 100644
--- a/drivers/iio/accel/mma7455_i2c.c
+++ b/drivers/iio/accel/mma7455_i2c.c
@@ -59,4 +59,4 @@ module_i2c_driver(mma7455_i2c_driver);
MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
MODULE_DESCRIPTION("Freescale MMA7455L I2C accelerometer driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_MMA7455);
+MODULE_IMPORT_NS("IIO_MMA7455");
diff --git a/drivers/iio/accel/mma7455_spi.c b/drivers/iio/accel/mma7455_spi.c
index fcdde2e8a84b..aca02e83f789 100644
--- a/drivers/iio/accel/mma7455_spi.c
+++ b/drivers/iio/accel/mma7455_spi.c
@@ -47,4 +47,4 @@ module_spi_driver(mma7455_spi_driver);
MODULE_AUTHOR("Joachim Eastwood <manabian@gmail.com>");
MODULE_DESCRIPTION("Freescale MMA7455L SPI accelerometer driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_MMA7455);
+MODULE_IMPORT_NS("IIO_MMA7455");
diff --git a/drivers/iio/accel/mma8452.c b/drivers/iio/accel/mma8452.c
index 62e6369e2269..962d289065ab 100644
--- a/drivers/iio/accel/mma8452.c
+++ b/drivers/iio/accel/mma8452.c
@@ -32,6 +32,7 @@
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <linux/regulator/consumer.h>
+#include <linux/types.h>
#define MMA8452_STATUS 0x00
#define MMA8452_STATUS_DRDY (BIT(2) | BIT(1) | BIT(0))
@@ -115,7 +116,7 @@ struct mma8452_data {
/* Ensure correct alignment of time stamp when present */
struct {
__be16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} buffer;
};
@@ -973,7 +974,7 @@ static int mma8452_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct mma8452_data *data = iio_priv(indio_dev);
int val, ret;
diff --git a/drivers/iio/accel/mma9551.c b/drivers/iio/accel/mma9551.c
index fa1799b0b0df..1b96687da01a 100644
--- a/drivers/iio/accel/mma9551.c
+++ b/drivers/iio/accel/mma9551.c
@@ -4,11 +4,11 @@
* Copyright (c) 2014, Intel Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/iio/iio.h>
@@ -45,7 +45,7 @@ enum mma9551_tilt_axis {
struct mma9551_data {
struct i2c_client *client;
struct mutex mutex;
- int event_enabled[3];
+ bool event_enabled[3];
int irqs[MMA9551_GPIO_COUNT];
};
@@ -162,7 +162,7 @@ static int mma9551_read_event_config(struct iio_dev *indio_dev,
static int mma9551_config_incli_event(struct iio_dev *indio_dev,
enum iio_modifier axis,
- int state)
+ bool state)
{
struct mma9551_data *data = iio_priv(indio_dev);
enum mma9551_tilt_axis mma_axis;
@@ -174,7 +174,7 @@ static int mma9551_config_incli_event(struct iio_dev *indio_dev,
if (data->event_enabled[mma_axis] == state)
return 0;
- if (state == 0) {
+ if (!state) {
ret = mma9551_gpio_config(data->client,
(enum mma9551_gpio_pin)mma_axis,
MMA9551_APPID_NONE, 0, 0);
@@ -225,7 +225,7 @@ static int mma9551_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct mma9551_data *data = iio_priv(indio_dev);
int ret;
@@ -435,17 +435,6 @@ static int mma9551_gpio_probe(struct iio_dev *indio_dev)
return 0;
}
-static const char *mma9551_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
static int mma9551_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -464,8 +453,8 @@ static int mma9551_probe(struct i2c_client *client)
if (id)
name = id->name;
- else if (ACPI_HANDLE(&client->dev))
- name = mma9551_match_acpi_device(&client->dev);
+ else
+ name = iio_get_acpi_device_name(&client->dev);
ret = mma9551_init(data);
if (ret < 0)
@@ -618,4 +607,4 @@ MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MMA9551L motion-sensing platform driver");
-MODULE_IMPORT_NS(IIO_MMA9551);
+MODULE_IMPORT_NS("IIO_MMA9551");
diff --git a/drivers/iio/accel/mma9551_core.c b/drivers/iio/accel/mma9551_core.c
index b898f865fb87..3e7d9b79ed0e 100644
--- a/drivers/iio/accel/mma9551_core.c
+++ b/drivers/iio/accel/mma9551_core.c
@@ -219,7 +219,7 @@ int mma9551_read_config_byte(struct i2c_client *client, u8 app_id,
return mma9551_transfer(client, app_id, MMA9551_CMD_READ_CONFIG,
reg, NULL, 0, val, 1);
}
-EXPORT_SYMBOL_NS(mma9551_read_config_byte, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_read_config_byte, "IIO_MMA9551");
/**
* mma9551_write_config_byte() - write 1 configuration byte
@@ -244,7 +244,7 @@ int mma9551_write_config_byte(struct i2c_client *client, u8 app_id,
return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg,
&val, 1, NULL, 0);
}
-EXPORT_SYMBOL_NS(mma9551_write_config_byte, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_write_config_byte, "IIO_MMA9551");
/**
* mma9551_read_status_byte() - read 1 status byte
@@ -269,7 +269,7 @@ int mma9551_read_status_byte(struct i2c_client *client, u8 app_id,
return mma9551_transfer(client, app_id, MMA9551_CMD_READ_STATUS,
reg, NULL, 0, val, 1);
}
-EXPORT_SYMBOL_NS(mma9551_read_status_byte, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_read_status_byte, "IIO_MMA9551");
/**
* mma9551_read_config_word() - read 1 config word
@@ -303,7 +303,7 @@ int mma9551_read_config_word(struct i2c_client *client, u8 app_id,
return 0;
}
-EXPORT_SYMBOL_NS(mma9551_read_config_word, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_read_config_word, "IIO_MMA9551");
/**
* mma9551_write_config_word() - write 1 config word
@@ -330,7 +330,7 @@ int mma9551_write_config_word(struct i2c_client *client, u8 app_id,
return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG, reg,
(u8 *)&v, 2, NULL, 0);
}
-EXPORT_SYMBOL_NS(mma9551_write_config_word, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_write_config_word, "IIO_MMA9551");
/**
* mma9551_read_status_word() - read 1 status word
@@ -364,7 +364,7 @@ int mma9551_read_status_word(struct i2c_client *client, u8 app_id,
return 0;
}
-EXPORT_SYMBOL_NS(mma9551_read_status_word, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_read_status_word, "IIO_MMA9551");
/**
* mma9551_read_config_words() - read multiple config words
@@ -403,7 +403,7 @@ int mma9551_read_config_words(struct i2c_client *client, u8 app_id,
return 0;
}
-EXPORT_SYMBOL_NS(mma9551_read_config_words, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_read_config_words, "IIO_MMA9551");
/**
* mma9551_read_status_words() - read multiple status words
@@ -442,7 +442,7 @@ int mma9551_read_status_words(struct i2c_client *client, u8 app_id,
return 0;
}
-EXPORT_SYMBOL_NS(mma9551_read_status_words, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_read_status_words, "IIO_MMA9551");
/**
* mma9551_write_config_words() - write multiple config words
@@ -477,7 +477,7 @@ int mma9551_write_config_words(struct i2c_client *client, u8 app_id,
return mma9551_transfer(client, app_id, MMA9551_CMD_WRITE_CONFIG,
reg, (u8 *)be_buf, len * sizeof(u16), NULL, 0);
}
-EXPORT_SYMBOL_NS(mma9551_write_config_words, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_write_config_words, "IIO_MMA9551");
/**
* mma9551_update_config_bits() - update bits in register
@@ -513,7 +513,7 @@ int mma9551_update_config_bits(struct i2c_client *client, u8 app_id,
return mma9551_write_config_byte(client, app_id, reg, tmp);
}
-EXPORT_SYMBOL_NS(mma9551_update_config_bits, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_update_config_bits, "IIO_MMA9551");
/**
* mma9551_gpio_config() - configure gpio
@@ -592,7 +592,7 @@ int mma9551_gpio_config(struct i2c_client *client, enum mma9551_gpio_pin pin,
return ret;
}
-EXPORT_SYMBOL_NS(mma9551_gpio_config, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_gpio_config, "IIO_MMA9551");
/**
* mma9551_read_version() - read device version information
@@ -622,7 +622,7 @@ int mma9551_read_version(struct i2c_client *client)
return 0;
}
-EXPORT_SYMBOL_NS(mma9551_read_version, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_read_version, "IIO_MMA9551");
/**
* mma9551_set_device_state() - sets HW power mode
@@ -652,7 +652,7 @@ int mma9551_set_device_state(struct i2c_client *client, bool enable)
MMA9551_SLEEP_CFG_FLEEN :
MMA9551_SLEEP_CFG_SNCEN);
}
-EXPORT_SYMBOL_NS(mma9551_set_device_state, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_set_device_state, "IIO_MMA9551");
/**
* mma9551_set_power_state() - sets runtime PM state
@@ -686,7 +686,7 @@ int mma9551_set_power_state(struct i2c_client *client, bool on)
return 0;
}
-EXPORT_SYMBOL_NS(mma9551_set_power_state, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_set_power_state, "IIO_MMA9551");
/**
* mma9551_sleep() - sleep
@@ -705,7 +705,7 @@ void mma9551_sleep(int freq)
else
msleep_interruptible(sleep_val);
}
-EXPORT_SYMBOL_NS(mma9551_sleep, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_sleep, "IIO_MMA9551");
/**
* mma9551_read_accel_chan() - read accelerometer channel
@@ -761,7 +761,7 @@ out_poweroff:
mma9551_set_power_state(client, false);
return ret;
}
-EXPORT_SYMBOL_NS(mma9551_read_accel_chan, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_read_accel_chan, "IIO_MMA9551");
/**
* mma9551_read_accel_scale() - read accelerometer scale
@@ -779,7 +779,7 @@ int mma9551_read_accel_scale(int *val, int *val2)
return IIO_VAL_INT_PLUS_MICRO;
}
-EXPORT_SYMBOL_NS(mma9551_read_accel_scale, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_read_accel_scale, "IIO_MMA9551");
/**
* mma9551_app_reset() - reset application
@@ -798,7 +798,7 @@ int mma9551_app_reset(struct i2c_client *client, u32 app_mask)
MMA9551_RSC_OFFSET(app_mask),
MMA9551_RSC_VAL(app_mask));
}
-EXPORT_SYMBOL_NS(mma9551_app_reset, IIO_MMA9551);
+EXPORT_SYMBOL_NS(mma9551_app_reset, "IIO_MMA9551");
MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
diff --git a/drivers/iio/accel/mma9553.c b/drivers/iio/accel/mma9553.c
index 86543f34ef17..00e224efc8ed 100644
--- a/drivers/iio/accel/mma9553.c
+++ b/drivers/iio/accel/mma9553.c
@@ -4,11 +4,11 @@
* Copyright (c) 2014, Intel Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
@@ -725,7 +725,8 @@ static int mma9553_read_event_config(struct iio_dev *indio_dev,
static int mma9553_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct mma9553_data *data = iio_priv(indio_dev);
struct mma9553_event *event;
@@ -1030,9 +1031,9 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
if (ev_step_detect->enabled && (stepcnt != data->stepcnt)) {
data->stepcnt = stepcnt;
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
- IIO_EV_DIR_NONE,
- IIO_EV_TYPE_CHANGE, 0, 0, 0),
+ IIO_UNMOD_EVENT_CODE(IIO_STEPS, 0,
+ IIO_EV_TYPE_CHANGE,
+ IIO_EV_DIR_NONE),
data->timestamp);
}
@@ -1041,20 +1042,18 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
/* ev_activity can be NULL if activity == ACTIVITY_UNKNOWN */
if (ev_prev_activity && ev_prev_activity->enabled)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- ev_prev_activity->info->mod,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH, 0, 0,
- 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ ev_prev_activity->info->mod,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
data->timestamp);
if (ev_activity && ev_activity->enabled)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- ev_activity->info->mod,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH, 0, 0,
- 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ ev_activity->info->mod,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
data->timestamp);
}
mutex_unlock(&data->mutex);
@@ -1062,17 +1061,6 @@ static irqreturn_t mma9553_event_handler(int irq, void *private)
return IRQ_HANDLED;
}
-static const char *mma9553_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
static int mma9553_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -1091,9 +1079,9 @@ static int mma9553_probe(struct i2c_client *client)
if (id)
name = id->name;
- else if (ACPI_HANDLE(&client->dev))
- name = mma9553_match_acpi_device(&client->dev);
else
+ name = iio_get_acpi_device_name(&client->dev);
+ if (!name)
return -ENOSYS;
mutex_init(&data->mutex);
@@ -1256,4 +1244,4 @@ module_i2c_driver(mma9553_driver);
MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MMA9553L pedometer platform driver");
-MODULE_IMPORT_NS(IIO_MMA9551);
+MODULE_IMPORT_NS("IIO_MMA9551");
diff --git a/drivers/iio/accel/msa311.c b/drivers/iio/accel/msa311.c
index 57025354c7cd..e7fb860f3233 100644
--- a/drivers/iio/accel/msa311.c
+++ b/drivers/iio/accel/msa311.c
@@ -34,6 +34,7 @@
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/string_choices.h>
+#include <linux/types.h>
#include <linux/units.h>
#include <linux/iio/buffer.h>
@@ -893,7 +894,7 @@ static irqreturn_t msa311_buffer_thread(int irq, void *p)
__le16 axis;
struct {
__le16 channels[MSA311_SI_Z + 1];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} buf;
memset(&buf, 0, sizeof(buf));
diff --git a/drivers/iio/accel/mxc4005.c b/drivers/iio/accel/mxc4005.c
index fc54a2a4693c..cb5c4e354fc0 100644
--- a/drivers/iio/accel/mxc4005.c
+++ b/drivers/iio/accel/mxc4005.c
@@ -11,6 +11,7 @@
#include <linux/iio/iio.h>
#include <linux/mod_devicetable.h>
#include <linux/regmap.h>
+#include <linux/types.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/buffer.h>
@@ -69,7 +70,7 @@ struct mxc4005_data {
/* Ensure timestamp is naturally aligned */
struct {
__be16 chans[3];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
bool trigger_enabled;
unsigned int control;
diff --git a/drivers/iio/accel/sca3000.c b/drivers/iio/accel/sca3000.c
index 87c54e41f6cc..3fb0f386c3db 100644
--- a/drivers/iio/accel/sca3000.c
+++ b/drivers/iio/accel/sca3000.c
@@ -1158,7 +1158,7 @@ error_ret:
return ret;
}
-static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state)
+static int sca3000_freefall_set_state(struct iio_dev *indio_dev, bool state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
@@ -1181,7 +1181,7 @@ static int sca3000_freefall_set_state(struct iio_dev *indio_dev, int state)
}
static int sca3000_motion_detect_set_state(struct iio_dev *indio_dev, int axis,
- int state)
+ bool state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret, ctrlval;
@@ -1253,7 +1253,7 @@ static int sca3000_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct sca3000_state *st = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/accel/ssp_accel_sensor.c b/drivers/iio/accel/ssp_accel_sensor.c
index 7ca9d0d543e0..3e572af2ec03 100644
--- a/drivers/iio/accel/ssp_accel_sensor.c
+++ b/drivers/iio/accel/ssp_accel_sensor.c
@@ -141,4 +141,4 @@ module_platform_driver(ssp_accel_driver);
MODULE_AUTHOR("Karol Wrona <k.wrona@samsung.com>");
MODULE_DESCRIPTION("Samsung sensorhub accelerometers driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_SSP_SENSORS);
+MODULE_IMPORT_NS("IIO_SSP_SENSORS");
diff --git a/drivers/iio/accel/st_accel_core.c b/drivers/iio/accel/st_accel_core.c
index 0e371efbda70..99cb661fabb2 100644
--- a/drivers/iio/accel/st_accel_core.c
+++ b/drivers/iio/accel/st_accel_core.c
@@ -1490,7 +1490,7 @@ const struct st_sensor_settings *st_accel_get_settings(const char *name)
return &st_accel_sensors_settings[index];
}
-EXPORT_SYMBOL_NS(st_accel_get_settings, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_accel_get_settings, "IIO_ST_SENSORS");
int st_accel_common_probe(struct iio_dev *indio_dev)
{
@@ -1544,9 +1544,9 @@ int st_accel_common_probe(struct iio_dev *indio_dev)
return devm_iio_device_register(parent, indio_dev);
}
-EXPORT_SYMBOL_NS(st_accel_common_probe, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_accel_common_probe, "IIO_ST_SENSORS");
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics accelerometers driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/accel/st_accel_i2c.c b/drivers/iio/accel/st_accel_i2c.c
index 329a4d6fb2ec..ab4fdba75a0a 100644
--- a/drivers/iio/accel/st_accel_i2c.c
+++ b/drivers/iio/accel/st_accel_i2c.c
@@ -216,4 +216,4 @@ module_i2c_driver(st_accel_driver);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics accelerometers i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/accel/st_accel_spi.c b/drivers/iio/accel/st_accel_spi.c
index 825adab37105..6146754fe47f 100644
--- a/drivers/iio/accel/st_accel_spi.c
+++ b/drivers/iio/accel/st_accel_spi.c
@@ -184,4 +184,4 @@ module_spi_driver(st_accel_driver);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics accelerometers spi driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/accel/stk8312.c b/drivers/iio/accel/stk8312.c
index abead190254b..471c154c3631 100644
--- a/drivers/iio/accel/stk8312.c
+++ b/drivers/iio/accel/stk8312.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
+#include <linux/types.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -105,7 +106,7 @@ struct stk8312_data {
/* Ensure timestamp is naturally aligned */
struct {
s8 chans[3];
- s64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
};
diff --git a/drivers/iio/accel/stk8ba50.c b/drivers/iio/accel/stk8ba50.c
index a32a77324e92..cab592a68622 100644
--- a/drivers/iio/accel/stk8ba50.c
+++ b/drivers/iio/accel/stk8ba50.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/mod_devicetable.h>
+#include <linux/types.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -94,7 +95,7 @@ struct stk8ba50_data {
/* Ensure timestamp is naturally aligned */
struct {
s16 chans[3];
- s64 timetamp __aligned(8);
+ aligned_s64 timetamp;
} scan;
};
diff --git a/drivers/iio/adc/Kconfig b/drivers/iio/adc/Kconfig
index 6c4e74420fd2..849c90203071 100644
--- a/drivers/iio/adc/Kconfig
+++ b/drivers/iio/adc/Kconfig
@@ -226,12 +226,14 @@ config AD7606_IFACE_PARALLEL
tristate "Analog Devices AD7606 ADC driver with parallel interface support"
depends on HAS_IOPORT
select AD7606
+ select IIO_BACKEND
help
Say yes here to build parallel interface support for Analog Devices:
ad7605-4, ad7606, ad7606-6, ad7606-4 analog to digital converters (ADC).
+ It also support iio_backended devices for AD7606B.
To compile this driver as a module, choose M here: the
- module will be called ad7606_parallel.
+ module will be called ad7606_par.
config AD7606_IFACE_SPI
tristate "Analog Devices AD7606 ADC driver with spi interface support"
@@ -244,6 +246,22 @@ config AD7606_IFACE_SPI
To compile this driver as a module, choose M here: the
module will be called ad7606_spi.
+config AD7625
+ tristate "Analog Devices AD7625/AD7626 High Speed ADC driver"
+ depends on PWM
+ select IIO_BACKEND
+ help
+ Say yes here to build support for Analog Devices:
+ * AD7625 16-Bit, 6 MSPS PulSAR Analog-to-Digital Converter
+ * AD7626 16-Bit, 10 MSPS PulSAR Analog-to-Digital Converter
+ * AD7960 18-Bit, 5 MSPS PulSAR Analog-to-Digital Converter
+ * AD7961 16-Bit, 5 MSPS PulSAR Analog-to-Digital Converter
+
+ The driver requires the assistance of the AXI ADC IP core to operate.
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7625.
+
config AD7766
tristate "Analog Devices AD7766/AD7767 ADC driver"
depends on SPI_MASTER
@@ -269,6 +287,18 @@ config AD7768_1
To compile this driver as a module, choose M here: the module will be
called ad7768-1.
+config AD7779
+ tristate "Analog Devices AD7779 ADC driver"
+ depends on SPI
+ select CRC8
+ select IIO_BUFFER
+ help
+ Say yes here to build support for Analog Devices AD777X family
+ (AD7770, AD7771, AD7779) analog to digital converter (ADC).
+
+ To compile this driver as a module, choose M here: the module will be
+ called ad7779.
+
config AD7780
tristate "Analog Devices AD7780 and similar ADCs driver"
depends on SPI
@@ -575,6 +605,16 @@ config FSL_MX25_ADC
Generic Conversion Queue driver used for general purpose ADC in the
MX25. This driver supports single measurements using the MX25 ADC.
+config GEHC_PMC_ADC
+ tristate "GE HealthCare PMC ADC driver"
+ depends on I2C
+ help
+ Say yes here to build support for the GE HealthCare PMC 16-bit
+ 16-Channel ADC.
+
+ To compile this driver as a module, choose M here: the module will be
+ called gehc-pmc-adc.
+
config HI8435
tristate "Holt Integrated Circuits HI-8435 threshold detector"
select IIO_TRIGGERED_EVENT
@@ -1580,7 +1620,6 @@ config TWL4030_MADC
config TWL6030_GPADC
tristate "TWL6030 GPADC (General Purpose A/D Converter) Support"
depends on TWL4030_CORE
- default n
help
Say yes here if you want support for the TWL6030/TWL6032 General
Purpose A/D Converter. This will add support for battery type
diff --git a/drivers/iio/adc/Makefile b/drivers/iio/adc/Makefile
index 7b91cd98c0e0..ee19afba62b7 100644
--- a/drivers/iio/adc/Makefile
+++ b/drivers/iio/adc/Makefile
@@ -25,8 +25,10 @@ obj-$(CONFIG_AD7476) += ad7476.o
obj-$(CONFIG_AD7606_IFACE_PARALLEL) += ad7606_par.o
obj-$(CONFIG_AD7606_IFACE_SPI) += ad7606_spi.o
obj-$(CONFIG_AD7606) += ad7606.o
+obj-$(CONFIG_AD7625) += ad7625.o
obj-$(CONFIG_AD7766) += ad7766.o
obj-$(CONFIG_AD7768_1) += ad7768-1.o
+obj-$(CONFIG_AD7779) += ad7779.o
obj-$(CONFIG_AD7780) += ad7780.o
obj-$(CONFIG_AD7791) += ad7791.o
obj-$(CONFIG_AD7793) += ad7793.o
@@ -52,6 +54,7 @@ obj-$(CONFIG_ENVELOPE_DETECTOR) += envelope-detector.o
obj-$(CONFIG_EP93XX_ADC) += ep93xx_adc.o
obj-$(CONFIG_EXYNOS_ADC) += exynos_adc.o
obj-$(CONFIG_FSL_MX25_ADC) += fsl-imx25-gcq.o
+obj-$(CONFIG_GEHC_PMC_ADC) += gehc-pmc-adc.o
obj-$(CONFIG_HI8435) += hi8435.o
obj-$(CONFIG_HX711) += hx711.o
obj-$(CONFIG_IMX7D_ADC) += imx7d_adc.o
diff --git a/drivers/iio/adc/ab8500-gpadc.c b/drivers/iio/adc/ab8500-gpadc.c
index 59f66e9cb0e8..f3b057f92310 100644
--- a/drivers/iio/adc/ab8500-gpadc.c
+++ b/drivers/iio/adc/ab8500-gpadc.c
@@ -1194,7 +1194,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(ab8500_gpadc_pm_ops,
static struct platform_driver ab8500_gpadc_driver = {
.probe = ab8500_gpadc_probe,
- .remove_new = ab8500_gpadc_remove,
+ .remove = ab8500_gpadc_remove,
.driver = {
.name = "ab8500-gpadc",
.pm = pm_ptr(&ab8500_gpadc_pm_ops),
diff --git a/drivers/iio/adc/ad4000.c b/drivers/iio/adc/ad4000.c
index 6ea491245084..b3b82535f5c1 100644
--- a/drivers/iio/adc/ad4000.c
+++ b/drivers/iio/adc/ad4000.c
@@ -344,6 +344,8 @@ static int ad4000_single_conversion(struct iio_dev *indio_dev,
if (chan->scan_type.sign == 's')
*val = sign_extend32(sample, chan->scan_type.realbits - 1);
+ else
+ *val = sample;
return IIO_VAL_INT;
}
@@ -637,7 +639,9 @@ static int ad4000_probe(struct spi_device *spi)
indio_dev->name = chip->dev_name;
indio_dev->num_channels = 1;
- devm_mutex_init(dev, &st->lock);
+ ret = devm_mutex_init(dev, &st->lock);
+ if (ret)
+ return ret;
st->gain_milli = 1000;
if (chip->has_hardware_gain) {
diff --git a/drivers/iio/adc/ad7091r-base.c b/drivers/iio/adc/ad7091r-base.c
index d6876259ad14..606486c4dfe8 100644
--- a/drivers/iio/adc/ad7091r-base.c
+++ b/drivers/iio/adc/ad7091r-base.c
@@ -35,7 +35,7 @@ const struct iio_event_spec ad7091r_events[] = {
.mask_separate = BIT(IIO_EV_INFO_HYSTERESIS),
},
};
-EXPORT_SYMBOL_NS_GPL(ad7091r_events, IIO_AD7091R);
+EXPORT_SYMBOL_NS_GPL(ad7091r_events, "IIO_AD7091R");
static int ad7091r_set_channel(struct ad7091r_state *st, unsigned int channel)
{
@@ -150,7 +150,8 @@ static int ad7091r_read_event_config(struct iio_dev *indio_dev,
static int ad7091r_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct ad7091r_state *st = iio_priv(indio_dev);
@@ -369,7 +370,7 @@ int ad7091r_probe(struct device *dev, const struct ad7091r_init_info *init_info,
return devm_iio_device_register(dev, iio_dev);
}
-EXPORT_SYMBOL_NS_GPL(ad7091r_probe, IIO_AD7091R);
+EXPORT_SYMBOL_NS_GPL(ad7091r_probe, "IIO_AD7091R");
bool ad7091r_writeable_reg(struct device *dev, unsigned int reg)
{
@@ -381,7 +382,7 @@ bool ad7091r_writeable_reg(struct device *dev, unsigned int reg)
return true;
}
}
-EXPORT_SYMBOL_NS_GPL(ad7091r_writeable_reg, IIO_AD7091R);
+EXPORT_SYMBOL_NS_GPL(ad7091r_writeable_reg, "IIO_AD7091R");
bool ad7091r_volatile_reg(struct device *dev, unsigned int reg)
{
@@ -393,7 +394,7 @@ bool ad7091r_volatile_reg(struct device *dev, unsigned int reg)
return false;
}
}
-EXPORT_SYMBOL_NS_GPL(ad7091r_volatile_reg, IIO_AD7091R);
+EXPORT_SYMBOL_NS_GPL(ad7091r_volatile_reg, "IIO_AD7091R");
MODULE_AUTHOR("Beniamin Bia <beniamin.bia@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7091Rx multi-channel converters");
diff --git a/drivers/iio/adc/ad7091r-base.h b/drivers/iio/adc/ad7091r-base.h
index 696bf7a897bb..092ddea0f395 100644
--- a/drivers/iio/adc/ad7091r-base.h
+++ b/drivers/iio/adc/ad7091r-base.h
@@ -65,7 +65,7 @@ struct ad7091r_state {
struct regulator *vref;
const struct ad7091r_chip_info *chip_info;
enum ad7091r_mode mode;
- struct mutex lock; /*lock to prevent concurent reads */
+ struct mutex lock; /*lock to prevent concurrent reads */
__be16 tx_buf __aligned(IIO_DMA_MINALIGN);
__be16 rx_buf;
};
diff --git a/drivers/iio/adc/ad7091r5.c b/drivers/iio/adc/ad7091r5.c
index 1b59708abf30..b472b9498fd1 100644
--- a/drivers/iio/adc/ad7091r5.c
+++ b/drivers/iio/adc/ad7091r5.c
@@ -135,4 +135,4 @@ module_i2c_driver(ad7091r5_driver);
MODULE_AUTHOR("Beniamin Bia <beniamin.bia@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7091R5 multi-channel ADC driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD7091R);
+MODULE_IMPORT_NS("IIO_AD7091R");
diff --git a/drivers/iio/adc/ad7091r8.c b/drivers/iio/adc/ad7091r8.c
index c9e014d6a77c..cebade4c2d49 100644
--- a/drivers/iio/adc/ad7091r8.c
+++ b/drivers/iio/adc/ad7091r8.c
@@ -269,4 +269,4 @@ module_spi_driver(ad7091r8_driver);
MODULE_AUTHOR("Marcelo Schmitt <marcelo.schmitt@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7091R8 ADC driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_AD7091R);
+MODULE_IMPORT_NS("IIO_AD7091R");
diff --git a/drivers/iio/adc/ad7124.c b/drivers/iio/adc/ad7124.c
index b79c48d46ccc..7314fb32bdec 100644
--- a/drivers/iio/adc/ad7124.c
+++ b/drivers/iio/adc/ad7124.c
@@ -1036,4 +1036,4 @@ module_spi_driver(ad71124_driver);
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7124 SPI driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA);
+MODULE_IMPORT_NS("IIO_AD_SIGMA_DELTA");
diff --git a/drivers/iio/adc/ad7173.c b/drivers/iio/adc/ad7173.c
index 0702ec71aa29..8a0c931ca83a 100644
--- a/drivers/iio/adc/ad7173.c
+++ b/drivers/iio/adc/ad7173.c
@@ -3,7 +3,7 @@
* AD717x and AD411x family SPI ADC driver
*
* Supported devices:
- * AD4111/AD4112/AD4114/AD4115/AD4116
+ * AD4111/AD4112/AD4113/AD4114/AD4115/AD4116
* AD7172-2/AD7172-4/AD7173-8/AD7175-2
* AD7175-8/AD7176-2/AD7177-2
*
@@ -76,14 +76,15 @@
(x) == AD7173_AIN_REF_NEG)
#define AD7172_2_ID 0x00d0
-#define AD7175_ID 0x0cd0
#define AD7176_ID 0x0c90
+#define AD7175_ID 0x0cd0
#define AD7175_2_ID 0x0cd0
#define AD7172_4_ID 0x2050
#define AD7173_ID 0x30d0
#define AD4111_ID AD7173_ID
#define AD4112_ID AD7173_ID
#define AD4114_ID AD7173_ID
+#define AD4113_ID 0x31d0
#define AD4116_ID 0x34d0
#define AD4115_ID 0x38d0
#define AD7175_8_ID 0x3cd0
@@ -170,6 +171,7 @@ struct ad7173_device_info {
bool has_temp;
/* ((AVDD1 − AVSS)/5) */
bool has_pow_supply_monitoring;
+ bool data_reg_only_16bit;
bool has_input_buf;
bool has_int_ref;
bool has_ref2;
@@ -294,6 +296,24 @@ static const struct ad7173_device_info ad4112_device_info = {
.num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
};
+static const struct ad7173_device_info ad4113_device_info = {
+ .name = "ad4113",
+ .id = AD4113_ID,
+ .num_voltage_in_div = 8,
+ .num_channels = 16,
+ .num_configs = 8,
+ .num_voltage_in = 8,
+ .num_gpios = 2,
+ .data_reg_only_16bit = true,
+ .higher_gpio_bits = true,
+ .has_vincom_input = true,
+ .has_input_buf = true,
+ .has_int_ref = true,
+ .clock = 2 * HZ_PER_MHZ,
+ .sinc5_data_rates = ad7173_sinc5_data_rates,
+ .num_sinc5_data_rates = ARRAY_SIZE(ad7173_sinc5_data_rates),
+};
+
static const struct ad7173_device_info ad4114_device_info = {
.name = "ad4114",
.id = AD4114_ID,
@@ -985,6 +1005,13 @@ static const struct iio_info ad7173_info = {
.update_scan_mode = ad7173_update_scan_mode,
};
+static const struct iio_scan_type ad4113_scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_BE,
+};
+
static const struct iio_chan_spec ad7173_channel_template = {
.type = IIO_VOLTAGE,
.indexed = 1,
@@ -1226,6 +1253,8 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
chan_st_priv->cfg.input_buf = st->info->has_input_buf;
chan_st_priv->cfg.ref_sel = AD7173_SETUP_REF_SEL_INT_REF;
st->adc_mode |= AD7173_ADC_MODE_REF_EN;
+ if (st->info->data_reg_only_16bit)
+ chan_arr[chan_index].scan_type = ad4113_scan_type;
chan_index++;
}
@@ -1306,6 +1335,9 @@ static int ad7173_fw_parse_channel_config(struct iio_dev *indio_dev)
chan_st_priv->ain = AD7173_CH_ADDRESS(ain[0], ain[1]);
}
+ if (st->info->data_reg_only_16bit)
+ chan_arr[chan_index].scan_type = ad4113_scan_type;
+
chan_index++;
}
return 0;
@@ -1434,6 +1466,7 @@ static int ad7173_probe(struct spi_device *spi)
static const struct of_device_id ad7173_of_match[] = {
{ .compatible = "adi,ad4111", .data = &ad4111_device_info },
{ .compatible = "adi,ad4112", .data = &ad4112_device_info },
+ { .compatible = "adi,ad4113", .data = &ad4113_device_info },
{ .compatible = "adi,ad4114", .data = &ad4114_device_info },
{ .compatible = "adi,ad4115", .data = &ad4115_device_info },
{ .compatible = "adi,ad4116", .data = &ad4116_device_info },
@@ -1451,6 +1484,7 @@ MODULE_DEVICE_TABLE(of, ad7173_of_match);
static const struct spi_device_id ad7173_id_table[] = {
{ "ad4111", (kernel_ulong_t)&ad4111_device_info },
{ "ad4112", (kernel_ulong_t)&ad4112_device_info },
+ { "ad4113", (kernel_ulong_t)&ad4113_device_info },
{ "ad4114", (kernel_ulong_t)&ad4114_device_info },
{ "ad4115", (kernel_ulong_t)&ad4115_device_info },
{ "ad4116", (kernel_ulong_t)&ad4116_device_info },
@@ -1475,7 +1509,7 @@ static struct spi_driver ad7173_driver = {
};
module_spi_driver(ad7173_driver);
-MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA);
+MODULE_IMPORT_NS("IIO_AD_SIGMA_DELTA");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafo.de>");
MODULE_AUTHOR("Dumitru Ceclan <dumitru.ceclan@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7173 and similar ADC driver");
diff --git a/drivers/iio/adc/ad7192.c b/drivers/iio/adc/ad7192.c
index 7042ddfdfc03..1c87db0e0460 100644
--- a/drivers/iio/adc/ad7192.c
+++ b/drivers/iio/adc/ad7192.c
@@ -1394,6 +1394,9 @@ static int ad7192_probe(struct spi_device *spi)
st->int_vref_mv = ret == -ENODEV ? avdd_mv : ret / MILLI;
st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return -ENODEV;
+
indio_dev->name = st->chip_info->name;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = st->chip_info->info;
@@ -1458,4 +1461,4 @@ module_spi_driver(ad7192_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7192 and similar ADC");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA);
+MODULE_IMPORT_NS("IIO_AD_SIGMA_DELTA");
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 7949b076fb87..858c8be2ff1a 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -383,7 +383,7 @@ static const char * const ad7266_gpio_labels[] = {
static int ad7266_probe(struct spi_device *spi)
{
- struct ad7266_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7266_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad7266_state *st;
unsigned int i;
diff --git a/drivers/iio/adc/ad7280a.c b/drivers/iio/adc/ad7280a.c
index 35aa39fe4bde..f9f32737db80 100644
--- a/drivers/iio/adc/ad7280a.c
+++ b/drivers/iio/adc/ad7280a.c
@@ -822,17 +822,15 @@ static irqreturn_t ad7280_event_handler(int irq, void *private)
if (FIELD_GET(AD7280A_TRANS_READ_CONV_CHANADDR_MSK, channels[i]) <=
AD7280A_CELL_VOLTAGE_6_REG) {
if (val >= st->cell_threshhigh) {
- u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0);
+ u64 tmp = IIO_DIFF_EVENT_CODE(IIO_VOLTAGE, 0, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING);
iio_push_event(indio_dev, tmp,
iio_get_time_ns(indio_dev));
} else if (val <= st->cell_threshlow) {
- u64 tmp = IIO_EVENT_CODE(IIO_VOLTAGE, 1, 0,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0);
+ u64 tmp = IIO_DIFF_EVENT_CODE(IIO_VOLTAGE, 0, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING);
iio_push_event(indio_dev, tmp,
iio_get_time_ns(indio_dev));
}
diff --git a/drivers/iio/adc/ad7291.c b/drivers/iio/adc/ad7291.c
index 4c7f887adbbf..60e12faa3207 100644
--- a/drivers/iio/adc/ad7291.c
+++ b/drivers/iio/adc/ad7291.c
@@ -269,7 +269,7 @@ static int ad7291_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
int ret = 0;
struct ad7291_chip_info *chip = iio_priv(indio_dev);
diff --git a/drivers/iio/adc/ad7380.c b/drivers/iio/adc/ad7380.c
index fb728570debe..4f32cb22f140 100644
--- a/drivers/iio/adc/ad7380.c
+++ b/drivers/iio/adc/ad7380.c
@@ -13,6 +13,8 @@
* ad7381-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7381-4.pdf
* ad7383/4-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7383-4-ad7384-4.pdf
* ad7386/7/8-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/ad7386-4-7387-4-7388-4.pdf
+ * adaq4370-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4370-4.pdf
+ * adaq4380-4 : https://www.analog.com/media/en/technical-documentation/data-sheets/adaq4380-4.pdf
*/
#include <linux/align.h>
@@ -22,11 +24,14 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
+#include <linux/math.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
+#include <linux/units.h>
+#include <linux/util_macros.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
@@ -36,6 +41,8 @@
#define MAX_NUM_CHANNELS 8
/* 2.5V internal reference voltage */
#define AD7380_INTERNAL_REF_MV 2500
+/* 3.3V internal reference voltage for ADAQ */
+#define ADAQ4380_INTERNAL_REF_MV 3300
/* reading and writing registers is more reliable at lower than max speed */
#define AD7380_REG_WR_SPEED_HZ 10000000
@@ -77,6 +84,13 @@
#define T_CONVERT_X_NS 500 /* xth conversion start time (oversampling) */
#define T_POWERUP_US 5000 /* Power up */
+/*
+ * AD738x support several SDO lines to increase throughput, but driver currently
+ * supports only 1 SDO line (standard SPI transaction)
+ */
+#define AD7380_NUM_SDO_LINES 1
+#define AD7380_DEFAULT_GAIN_MILLI 1000
+
struct ad7380_timing_specs {
const unsigned int t_csh_ns; /* CS minimum high time */
};
@@ -86,10 +100,12 @@ struct ad7380_chip_info {
const struct iio_chan_spec *channels;
unsigned int num_channels;
unsigned int num_simult_channels;
+ bool has_hardware_gain;
bool has_mux;
const char * const *supplies;
unsigned int num_supplies;
bool external_ref_only;
+ bool adaq_internal_ref_only;
const char * const *vcm_supplies;
unsigned int num_vcm_supplies;
const unsigned long *available_scan_masks;
@@ -181,11 +197,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
},
};
-#define AD7380_CHANNEL(index, bits, diff, sign) { \
+#define _AD7380_CHANNEL(index, bits, diff, sign, gain) { \
.type = IIO_VOLTAGE, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ ((gain) ? BIT(IIO_CHAN_INFO_SCALE) : 0) | \
((diff) ? 0 : BIT(IIO_CHAN_INFO_OFFSET)), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ .info_mask_shared_by_type = ((gain) ? 0 : BIT(IIO_CHAN_INFO_SCALE)) | \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
.info_mask_shared_by_type_available = \
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
@@ -199,6 +216,12 @@ static const struct iio_scan_type ad7380_scan_type_16_u[] = {
.num_ext_scan_type = ARRAY_SIZE(ad7380_scan_type_##bits##_##sign), \
}
+#define AD7380_CHANNEL(index, bits, diff, sign) \
+ _AD7380_CHANNEL(index, bits, diff, sign, false)
+
+#define ADAQ4380_CHANNEL(index, bits, diff, sign) \
+ _AD7380_CHANNEL(index, bits, diff, sign, true)
+
#define DEFINE_AD7380_2_CHANNEL(name, bits, diff, sign) \
static const struct iio_chan_spec name[] = { \
AD7380_CHANNEL(0, bits, diff, sign), \
@@ -215,6 +238,15 @@ static const struct iio_chan_spec name[] = { \
IIO_CHAN_SOFT_TIMESTAMP(4), \
}
+#define DEFINE_ADAQ4380_4_CHANNEL(name, bits, diff, sign) \
+static const struct iio_chan_spec name[] = { \
+ ADAQ4380_CHANNEL(0, bits, diff, sign), \
+ ADAQ4380_CHANNEL(1, bits, diff, sign), \
+ ADAQ4380_CHANNEL(2, bits, diff, sign), \
+ ADAQ4380_CHANNEL(3, bits, diff, sign), \
+ IIO_CHAN_SOFT_TIMESTAMP(4), \
+}
+
#define DEFINE_AD7380_8_CHANNEL(name, bits, diff, sign) \
static const struct iio_chan_spec name[] = { \
AD7380_CHANNEL(0, bits, diff, sign), \
@@ -233,6 +265,7 @@ DEFINE_AD7380_2_CHANNEL(ad7380_channels, 16, 1, s);
DEFINE_AD7380_2_CHANNEL(ad7381_channels, 14, 1, s);
DEFINE_AD7380_4_CHANNEL(ad7380_4_channels, 16, 1, s);
DEFINE_AD7380_4_CHANNEL(ad7381_4_channels, 14, 1, s);
+DEFINE_ADAQ4380_4_CHANNEL(adaq4380_4_channels, 16, 1, s);
/* pseudo differential */
DEFINE_AD7380_2_CHANNEL(ad7383_channels, 16, 0, s);
DEFINE_AD7380_2_CHANNEL(ad7384_channels, 14, 0, s);
@@ -251,6 +284,10 @@ static const char * const ad7380_supplies[] = {
"vcc", "vlogic",
};
+static const char * const adaq4380_supplies[] = {
+ "ldo", "vcc", "vlogic", "vs-p", "vs-n", "refin",
+};
+
static const char * const ad7380_2_channel_vcm_supplies[] = {
"aina", "ainb",
};
@@ -341,6 +378,11 @@ static const int ad7380_oversampling_ratios[] = {
1, 2, 4, 8, 16, 32,
};
+/* Gains stored as fractions of 1000 so they can be expressed by integers. */
+static const int ad7380_gains[] = {
+ 300, 600, 1000, 1600,
+};
+
static const struct ad7380_chip_info ad7380_chip_info = {
.name = "ad7380",
.channels = ad7380_channels,
@@ -510,6 +552,32 @@ static const struct ad7380_chip_info ad7388_4_chip_info = {
.timing_specs = &ad7380_4_timing,
};
+static const struct ad7380_chip_info adaq4370_4_chip_info = {
+ .name = "adaq4370-4",
+ .channels = adaq4380_4_channels,
+ .num_channels = ARRAY_SIZE(adaq4380_4_channels),
+ .num_simult_channels = 4,
+ .supplies = adaq4380_supplies,
+ .num_supplies = ARRAY_SIZE(adaq4380_supplies),
+ .adaq_internal_ref_only = true,
+ .has_hardware_gain = true,
+ .available_scan_masks = ad7380_4_channel_scan_masks,
+ .timing_specs = &ad7380_4_timing,
+};
+
+static const struct ad7380_chip_info adaq4380_4_chip_info = {
+ .name = "adaq4380-4",
+ .channels = adaq4380_4_channels,
+ .num_channels = ARRAY_SIZE(adaq4380_4_channels),
+ .num_simult_channels = 4,
+ .supplies = adaq4380_supplies,
+ .num_supplies = ARRAY_SIZE(adaq4380_supplies),
+ .adaq_internal_ref_only = true,
+ .has_hardware_gain = true,
+ .available_scan_masks = ad7380_4_channel_scan_masks,
+ .timing_specs = &ad7380_4_timing,
+};
+
struct ad7380_state {
const struct ad7380_chip_info *chip_info;
struct spi_device *spi;
@@ -520,6 +588,7 @@ struct ad7380_state {
bool seq;
unsigned int vref_mv;
unsigned int vcm_mv[MAX_NUM_CHANNELS];
+ unsigned int gain_milli[MAX_NUM_CHANNELS];
/* xfers, message an buffer for reading sample data */
struct spi_transfer normal_xfer[2];
struct spi_message normal_msg;
@@ -649,7 +718,8 @@ static int ad7380_set_ch(struct ad7380_state *st, unsigned int ch)
if (st->oversampling_ratio > 1)
xfer.delay.value = T_CONVERT_0_NS +
- T_CONVERT_X_NS * (st->oversampling_ratio - 1);
+ T_CONVERT_X_NS * (st->oversampling_ratio - 1) *
+ st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
return spi_sync_transfer(st->spi, &xfer, 1);
}
@@ -672,7 +742,8 @@ static void ad7380_update_xfers(struct ad7380_state *st,
*/
if (st->oversampling_ratio > 1)
t_convert = T_CONVERT_0_NS + T_CONVERT_X_NS *
- (st->oversampling_ratio - 1);
+ (st->oversampling_ratio - 1) *
+ st->chip_info->num_simult_channels / AD7380_NUM_SDO_LINES;
if (st->seq) {
xfer[0].delay.value = xfer[1].delay.value = t_convert;
@@ -868,8 +939,15 @@ static int ad7380_read_raw(struct iio_dev *indio_dev,
* * (2 × VREF) / 2^N, for differential chips
* * VREF / 2^N, for pseudo-differential chips
* where N is the ADC resolution (i.e realbits)
+ *
+ * The gain is stored as a fraction of 1000 and, as we need to
+ * divide vref_mv by the gain, we invert the gain/1000 fraction.
*/
- *val = st->vref_mv;
+ if (st->chip_info->has_hardware_gain)
+ *val = mult_frac(st->vref_mv, MILLI,
+ st->gain_milli[chan->scan_index]);
+ else
+ *val = st->vref_mv;
*val2 = scan_type->realbits - chan->differential;
return IIO_VAL_FRACTIONAL_LOG2;
@@ -1021,17 +1099,19 @@ static int ad7380_init(struct ad7380_state *st, bool external_ref_en)
/* SPI 1-wire mode */
return regmap_update_bits(st->regmap, AD7380_REG_ADDR_CONFIG2,
AD7380_CONFIG2_SDO,
- FIELD_PREP(AD7380_CONFIG2_SDO, 1));
+ FIELD_PREP(AD7380_CONFIG2_SDO,
+ AD7380_NUM_SDO_LINES));
}
static int ad7380_probe(struct spi_device *spi)
{
+ struct device *dev = &spi->dev;
struct iio_dev *indio_dev;
struct ad7380_state *st;
bool external_ref_en;
int ret, i;
- indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
@@ -1039,21 +1119,32 @@ static int ad7380_probe(struct spi_device *spi)
st->spi = spi;
st->chip_info = spi_get_device_match_data(spi);
if (!st->chip_info)
- return dev_err_probe(&spi->dev, -EINVAL, "missing match data\n");
+ return dev_err_probe(dev, -EINVAL, "missing match data\n");
- ret = devm_regulator_bulk_get_enable(&spi->dev, st->chip_info->num_supplies,
+ ret = devm_regulator_bulk_get_enable(dev, st->chip_info->num_supplies,
st->chip_info->supplies);
if (ret)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to enable power supplies\n");
fsleep(T_POWERUP_US);
- if (st->chip_info->external_ref_only) {
- ret = devm_regulator_get_enable_read_voltage(&spi->dev,
- "refin");
+ if (st->chip_info->adaq_internal_ref_only) {
+ /*
+ * ADAQ chips use fixed internal reference but still
+ * require a specific reference supply to power it.
+ * "refin" is already enabled with other power supplies
+ * in bulk_get_enable().
+ */
+
+ st->vref_mv = ADAQ4380_INTERNAL_REF_MV;
+
+ /* these chips don't have a register bit for this */
+ external_ref_en = false;
+ } else if (st->chip_info->external_ref_only) {
+ ret = devm_regulator_get_enable_read_voltage(dev, "refin");
if (ret < 0)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to get refin regulator\n");
st->vref_mv = ret / 1000;
@@ -1065,10 +1156,9 @@ static int ad7380_probe(struct spi_device *spi)
* If there is no REFIO supply, then it means that we are using
* the internal reference, otherwise REFIO is reference voltage.
*/
- ret = devm_regulator_get_enable_read_voltage(&spi->dev,
- "refio");
+ ret = devm_regulator_get_enable_read_voltage(dev, "refio");
if (ret < 0 && ret != -ENODEV)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to get refio regulator\n");
external_ref_en = ret != -ENODEV;
@@ -1076,7 +1166,7 @@ static int ad7380_probe(struct spi_device *spi)
}
if (st->chip_info->num_vcm_supplies > ARRAY_SIZE(st->vcm_mv))
- return dev_err_probe(&spi->dev, -EINVAL,
+ return dev_err_probe(dev, -EINVAL,
"invalid number of VCM supplies\n");
/*
@@ -1086,18 +1176,54 @@ static int ad7380_probe(struct spi_device *spi)
for (i = 0; i < st->chip_info->num_vcm_supplies; i++) {
const char *vcm = st->chip_info->vcm_supplies[i];
- ret = devm_regulator_get_enable_read_voltage(&spi->dev, vcm);
+ ret = devm_regulator_get_enable_read_voltage(dev, vcm);
if (ret < 0)
- return dev_err_probe(&spi->dev, ret,
+ return dev_err_probe(dev, ret,
"Failed to get %s regulator\n",
vcm);
st->vcm_mv[i] = ret / 1000;
}
- st->regmap = devm_regmap_init(&spi->dev, NULL, st, &ad7380_regmap_config);
+ for (i = 0; i < MAX_NUM_CHANNELS; i++)
+ st->gain_milli[i] = AD7380_DEFAULT_GAIN_MILLI;
+
+ if (st->chip_info->has_hardware_gain) {
+ device_for_each_child_node_scoped(dev, node) {
+ unsigned int channel, gain;
+ int gain_idx;
+
+ ret = fwnode_property_read_u32(node, "reg", &channel);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to read reg property\n");
+
+ if (channel >= st->chip_info->num_channels - 1)
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid channel number %i\n",
+ channel);
+
+ ret = fwnode_property_read_u32(node, "adi,gain-milli",
+ &gain);
+ if (ret && ret != -EINVAL)
+ return dev_err_probe(dev, ret,
+ "Failed to read gain for channel %i\n",
+ channel);
+ if (ret != -EINVAL) {
+ /*
+ * Match gain value from dt to one of supported
+ * gains
+ */
+ gain_idx = find_closest(gain, ad7380_gains,
+ ARRAY_SIZE(ad7380_gains));
+ st->gain_milli[channel] = ad7380_gains[gain_idx];
+ }
+ }
+ }
+
+ st->regmap = devm_regmap_init(dev, NULL, st, &ad7380_regmap_config);
if (IS_ERR(st->regmap))
- return dev_err_probe(&spi->dev, PTR_ERR(st->regmap),
+ return dev_err_probe(dev, PTR_ERR(st->regmap),
"failed to allocate register map\n");
/*
@@ -1148,7 +1274,7 @@ static int ad7380_probe(struct spi_device *spi)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->available_scan_masks = st->chip_info->available_scan_masks;
- ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
iio_pollfunc_store_time,
ad7380_trigger_handler,
&ad7380_buffer_setup_ops);
@@ -1159,7 +1285,7 @@ static int ad7380_probe(struct spi_device *spi)
if (ret)
return ret;
- return devm_iio_device_register(&spi->dev, indio_dev);
+ return devm_iio_device_register(dev, indio_dev);
}
static const struct of_device_id ad7380_of_match_table[] = {
@@ -1177,6 +1303,8 @@ static const struct of_device_id ad7380_of_match_table[] = {
{ .compatible = "adi,ad7386-4", .data = &ad7386_4_chip_info },
{ .compatible = "adi,ad7387-4", .data = &ad7387_4_chip_info },
{ .compatible = "adi,ad7388-4", .data = &ad7388_4_chip_info },
+ { .compatible = "adi,adaq4370-4", .data = &adaq4370_4_chip_info },
+ { .compatible = "adi,adaq4380-4", .data = &adaq4380_4_chip_info },
{ }
};
@@ -1195,6 +1323,8 @@ static const struct spi_device_id ad7380_id_table[] = {
{ "ad7386-4", (kernel_ulong_t)&ad7386_4_chip_info },
{ "ad7387-4", (kernel_ulong_t)&ad7387_4_chip_info },
{ "ad7388-4", (kernel_ulong_t)&ad7388_4_chip_info },
+ { "adaq4370-4", (kernel_ulong_t)&adaq4370_4_chip_info },
+ { "adaq4380-4", (kernel_ulong_t)&adaq4380_4_chip_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ad7380_id_table);
diff --git a/drivers/iio/adc/ad7606.c b/drivers/iio/adc/ad7606.c
index 9b457472d49c..e35d55d03d86 100644
--- a/drivers/iio/adc/ad7606.c
+++ b/drivers/iio/adc/ad7606.c
@@ -13,14 +13,17 @@
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/property.h>
+#include <linux/pwm.h>
#include <linux/regulator/consumer.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/sysfs.h>
+#include <linux/units.h>
#include <linux/util_macros.h>
-#include <linux/iio/iio.h>
+#include <linux/iio/backend.h>
#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/triggered_buffer.h>
@@ -30,15 +33,52 @@
/*
* Scales are computed as 5000/32768 and 10000/32768 respectively,
- * so that when applied to the raw values they provide mV values
+ * so that when applied to the raw values they provide mV values.
+ * The scale arrays are kept as IIO_VAL_INT_PLUS_MICRO, so index
+ * X is the integer part and X + 1 is the fractional part.
*/
-static const unsigned int ad7606_scale_avail[2] = {
- 152588, 305176
+static const unsigned int ad7606_16bit_hw_scale_avail[2][2] = {
+ { 0, 152588 }, { 0, 305176 }
+};
+
+static const unsigned int ad7606_18bit_hw_scale_avail[2][2] = {
+ { 0, 38147 }, { 0, 76294 }
+};
+
+static const unsigned int ad7606c_16bit_single_ended_unipolar_scale_avail[3][2] = {
+ { 0, 76294 }, { 0, 152588 }, { 0, 190735 }
+};
+
+static const unsigned int ad7606c_16bit_single_ended_bipolar_scale_avail[5][2] = {
+ { 0, 76294 }, { 0, 152588 }, { 0, 190735 }, { 0, 305176 }, { 0, 381470 }
+};
+
+static const unsigned int ad7606c_16bit_differential_bipolar_scale_avail[4][2] = {
+ { 0, 152588 }, { 0, 305176 }, { 0, 381470 }, { 0, 610352 }
+};
+
+static const unsigned int ad7606c_18bit_single_ended_unipolar_scale_avail[3][2] = {
+ { 0, 19073 }, { 0, 38147 }, { 0, 47684 }
+};
+
+static const unsigned int ad7606c_18bit_single_ended_bipolar_scale_avail[5][2] = {
+ { 0, 19073 }, { 0, 38147 }, { 0, 47684 }, { 0, 76294 }, { 0, 95367 }
};
+static const unsigned int ad7606c_18bit_differential_bipolar_scale_avail[4][2] = {
+ { 0, 38147 }, { 0, 76294 }, { 0, 95367 }, { 0, 152588 }
+};
+
+static const unsigned int ad7606_16bit_sw_scale_avail[3][2] = {
+ { 0, 76293 }, { 0, 152588 }, { 0, 305176 }
+};
-static const unsigned int ad7616_sw_scale_avail[3] = {
- 76293, 152588, 305176
+static const unsigned int ad7607_hw_scale_avail[2][2] = {
+ { 0, 610352 }, { 1, 220703 }
+};
+
+static const unsigned int ad7609_hw_scale_avail[2][2] = {
+ { 0, 152588 }, { 0, 305176 }
};
static const unsigned int ad7606_oversampling_avail[7] = {
@@ -49,6 +89,227 @@ static const unsigned int ad7616_oversampling_avail[8] = {
1, 2, 4, 8, 16, 32, 64, 128,
};
+static const struct iio_chan_spec ad7605_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ AD7605_CHANNEL(0),
+ AD7605_CHANNEL(1),
+ AD7605_CHANNEL(2),
+ AD7605_CHANNEL(3),
+};
+
+static const struct iio_chan_spec ad7606_channels_16bit[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 16),
+ AD7606_CHANNEL(1, 16),
+ AD7606_CHANNEL(2, 16),
+ AD7606_CHANNEL(3, 16),
+ AD7606_CHANNEL(4, 16),
+ AD7606_CHANNEL(5, 16),
+ AD7606_CHANNEL(6, 16),
+ AD7606_CHANNEL(7, 16),
+};
+
+static const struct iio_chan_spec ad7606_channels_18bit[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 18),
+ AD7606_CHANNEL(1, 18),
+ AD7606_CHANNEL(2, 18),
+ AD7606_CHANNEL(3, 18),
+ AD7606_CHANNEL(4, 18),
+ AD7606_CHANNEL(5, 18),
+ AD7606_CHANNEL(6, 18),
+ AD7606_CHANNEL(7, 18),
+};
+
+static const struct iio_chan_spec ad7607_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 14),
+ AD7606_CHANNEL(1, 14),
+ AD7606_CHANNEL(2, 14),
+ AD7606_CHANNEL(3, 14),
+ AD7606_CHANNEL(4, 14),
+ AD7606_CHANNEL(5, 14),
+ AD7606_CHANNEL(6, 14),
+ AD7606_CHANNEL(7, 14),
+};
+
+static const struct iio_chan_spec ad7608_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_CHANNEL(0, 18),
+ AD7606_CHANNEL(1, 18),
+ AD7606_CHANNEL(2, 18),
+ AD7606_CHANNEL(3, 18),
+ AD7606_CHANNEL(4, 18),
+ AD7606_CHANNEL(5, 18),
+ AD7606_CHANNEL(6, 18),
+ AD7606_CHANNEL(7, 18),
+};
+
+/*
+ * The current assumption that this driver makes for AD7616, is that it's
+ * working in Hardware Mode with Serial, Burst and Sequencer modes activated.
+ * To activate them, following pins must be pulled high:
+ * -SER/PAR
+ * -SEQEN
+ * And following pins must be pulled low:
+ * -WR/BURST
+ * -DB4/SER1W
+ */
+static const struct iio_chan_spec ad7616_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(16),
+ AD7606_CHANNEL(0, 16),
+ AD7606_CHANNEL(1, 16),
+ AD7606_CHANNEL(2, 16),
+ AD7606_CHANNEL(3, 16),
+ AD7606_CHANNEL(4, 16),
+ AD7606_CHANNEL(5, 16),
+ AD7606_CHANNEL(6, 16),
+ AD7606_CHANNEL(7, 16),
+ AD7606_CHANNEL(8, 16),
+ AD7606_CHANNEL(9, 16),
+ AD7606_CHANNEL(10, 16),
+ AD7606_CHANNEL(11, 16),
+ AD7606_CHANNEL(12, 16),
+ AD7606_CHANNEL(13, 16),
+ AD7606_CHANNEL(14, 16),
+ AD7606_CHANNEL(15, 16),
+};
+
+static int ad7606c_18bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7606c_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7606_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7607_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7608_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+static int ad7609_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
+
+const struct ad7606_chip_info ad7605_4_info = {
+ .channels = ad7605_channels,
+ .name = "ad7605-4",
+ .num_adc_channels = 4,
+ .num_channels = 5,
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7605_4_info, "IIO_AD7606");
+
+const struct ad7606_chip_info ad7606_8_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606-8",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606_8_info, "IIO_AD7606");
+
+const struct ad7606_chip_info ad7606_6_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606-6",
+ .num_adc_channels = 6,
+ .num_channels = 7,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606_6_info, "IIO_AD7606");
+
+const struct ad7606_chip_info ad7606_4_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606-4",
+ .num_adc_channels = 4,
+ .num_channels = 5,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606_4_info, "IIO_AD7606");
+
+const struct ad7606_chip_info ad7606b_info = {
+ .channels = ad7606_channels_16bit,
+ .max_samplerate = 800 * KILO,
+ .name = "ad7606b",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606b_info, "IIO_AD7606");
+
+const struct ad7606_chip_info ad7606c_16_info = {
+ .channels = ad7606_channels_16bit,
+ .name = "ad7606c16",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606c_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606c_16_info, "IIO_AD7606");
+
+const struct ad7606_chip_info ad7607_info = {
+ .channels = ad7607_channels,
+ .name = "ad7607",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7607_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7607_info, "IIO_AD7606");
+
+const struct ad7606_chip_info ad7608_info = {
+ .channels = ad7608_channels,
+ .name = "ad7608",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7608_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7608_info, "IIO_AD7606");
+
+const struct ad7606_chip_info ad7609_info = {
+ .channels = ad7608_channels,
+ .name = "ad7609",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7609_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7609_info, "IIO_AD7606");
+
+const struct ad7606_chip_info ad7606c_18_info = {
+ .channels = ad7606_channels_18bit,
+ .name = "ad7606c18",
+ .num_adc_channels = 8,
+ .num_channels = 9,
+ .oversampling_avail = ad7606_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
+ .scale_setup_cb = ad7606c_18bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7606c_18_info, "IIO_AD7606");
+
+const struct ad7606_chip_info ad7616_info = {
+ .channels = ad7616_channels,
+ .init_delay_ms = 15,
+ .name = "ad7616",
+ .num_adc_channels = 16,
+ .num_channels = 17,
+ .oversampling_avail = ad7616_oversampling_avail,
+ .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail),
+ .os_req_reset = true,
+ .scale_setup_cb = ad7606_16bit_chan_scale_setup,
+};
+EXPORT_SYMBOL_NS_GPL(ad7616_info, "IIO_AD7606");
+
int ad7606_reset(struct ad7606_state *st)
{
if (st->gpio_reset) {
@@ -60,7 +321,229 @@ int ad7606_reset(struct ad7606_state *st)
return -ENODEV;
}
-EXPORT_SYMBOL_NS_GPL(ad7606_reset, IIO_AD7606);
+EXPORT_SYMBOL_NS_GPL(ad7606_reset, "IIO_AD7606");
+
+static int ad7606_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ if (!st->sw_mode_en) {
+ /* tied to logic low, analog input range is +/- 5V */
+ cs->range = 0;
+ cs->scale_avail = ad7606_16bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_16bit_hw_scale_avail);
+ return 0;
+ }
+
+ /* Scale of 0.076293 is only available in sw mode */
+ /* After reset, in software mode, ±10 V is set by default */
+ cs->range = 2;
+ cs->scale_avail = ad7606_16bit_sw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_16bit_sw_scale_avail);
+
+ return 0;
+}
+
+static int ad7606_get_chan_config(struct ad7606_state *st, int ch,
+ bool *bipolar, bool *differential)
+{
+ unsigned int num_channels = st->chip_info->num_channels - 1;
+ struct device *dev = st->dev;
+ int ret;
+
+ *bipolar = false;
+ *differential = false;
+
+ device_for_each_child_node_scoped(dev, child) {
+ u32 pins[2];
+ int reg;
+
+ ret = fwnode_property_read_u32(child, "reg", &reg);
+ if (ret)
+ continue;
+
+ /* channel number (here) is from 1 to num_channels */
+ if (reg == 0 || reg > num_channels) {
+ dev_warn(dev,
+ "Invalid channel number (ignoring): %d\n", reg);
+ continue;
+ }
+
+ if (reg != (ch + 1))
+ continue;
+
+ *bipolar = fwnode_property_read_bool(child, "bipolar");
+
+ ret = fwnode_property_read_u32_array(child, "diff-channels",
+ pins, ARRAY_SIZE(pins));
+ /* Channel is differential, if pins are the same as 'reg' */
+ if (ret == 0 && (pins[0] != reg || pins[1] != reg)) {
+ dev_err(dev,
+ "Differential pins must be the same as 'reg'");
+ return -EINVAL;
+ }
+
+ *differential = (ret == 0);
+
+ if (*differential && !*bipolar) {
+ dev_err(dev,
+ "'bipolar' must be added for diff channel %d\n",
+ reg);
+ return -EINVAL;
+ }
+
+ return 0;
+ }
+
+ return 0;
+}
+
+static int ad7606c_18bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ bool bipolar, differential;
+ int ret;
+
+ if (!st->sw_mode_en) {
+ cs->range = 0;
+ cs->scale_avail = ad7606_18bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_18bit_hw_scale_avail);
+ return 0;
+ }
+
+ ret = ad7606_get_chan_config(st, ch, &bipolar, &differential);
+ if (ret)
+ return ret;
+
+ if (differential) {
+ cs->scale_avail = ad7606c_18bit_differential_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_18bit_differential_bipolar_scale_avail);
+ /* Bipolar differential ranges start at 8 (b1000) */
+ cs->reg_offset = 8;
+ cs->range = 1;
+ chan->differential = 1;
+ chan->channel2 = chan->channel;
+
+ return 0;
+ }
+
+ chan->differential = 0;
+
+ if (bipolar) {
+ cs->scale_avail = ad7606c_18bit_single_ended_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_18bit_single_ended_bipolar_scale_avail);
+ /* Bipolar single-ended ranges start at 0 (b0000) */
+ cs->reg_offset = 0;
+ cs->range = 3;
+ chan->scan_type.sign = 's';
+
+ return 0;
+ }
+
+ cs->scale_avail = ad7606c_18bit_single_ended_unipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_18bit_single_ended_unipolar_scale_avail);
+ /* Unipolar single-ended ranges start at 5 (b0101) */
+ cs->reg_offset = 5;
+ cs->range = 1;
+ chan->scan_type.sign = 'u';
+
+ return 0;
+}
+
+static int ad7606c_16bit_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+ bool bipolar, differential;
+ int ret;
+
+ if (!st->sw_mode_en) {
+ cs->range = 0;
+ cs->scale_avail = ad7606_16bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_16bit_hw_scale_avail);
+ return 0;
+ }
+
+ ret = ad7606_get_chan_config(st, ch, &bipolar, &differential);
+ if (ret)
+ return ret;
+
+ if (differential) {
+ cs->scale_avail = ad7606c_16bit_differential_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_16bit_differential_bipolar_scale_avail);
+ /* Bipolar differential ranges start at 8 (b1000) */
+ cs->reg_offset = 8;
+ cs->range = 1;
+ chan->differential = 1;
+ chan->channel2 = chan->channel;
+ chan->scan_type.sign = 's';
+
+ return 0;
+ }
+
+ chan->differential = 0;
+
+ if (bipolar) {
+ cs->scale_avail = ad7606c_16bit_single_ended_bipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_16bit_single_ended_bipolar_scale_avail);
+ /* Bipolar single-ended ranges start at 0 (b0000) */
+ cs->reg_offset = 0;
+ cs->range = 3;
+ chan->scan_type.sign = 's';
+
+ return 0;
+ }
+
+ cs->scale_avail = ad7606c_16bit_single_ended_unipolar_scale_avail;
+ cs->num_scales =
+ ARRAY_SIZE(ad7606c_16bit_single_ended_unipolar_scale_avail);
+ /* Unipolar single-ended ranges start at 5 (b0101) */
+ cs->reg_offset = 5;
+ cs->range = 1;
+ chan->scan_type.sign = 'u';
+
+ return 0;
+}
+
+static int ad7607_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ cs->range = 0;
+ cs->scale_avail = ad7607_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7607_hw_scale_avail);
+ return 0;
+}
+
+static int ad7608_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ cs->range = 0;
+ cs->scale_avail = ad7606_18bit_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7606_18bit_hw_scale_avail);
+ return 0;
+}
+
+static int ad7609_chan_scale_setup(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch)
+{
+ struct ad7606_chan_scale *cs = &st->chan_scales[ch];
+
+ cs->range = 0;
+ cs->scale_avail = ad7609_hw_scale_avail;
+ cs->num_scales = ARRAY_SIZE(ad7609_hw_scale_avail);
+ return 0;
+}
static int ad7606_reg_access(struct iio_dev *indio_dev,
unsigned int reg,
@@ -83,12 +566,85 @@ static int ad7606_reg_access(struct iio_dev *indio_dev,
}
}
+static int ad7606_pwm_set_high(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+ int ret;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ cnvst_pwm_state.enabled = true;
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period;
+
+ ret = pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+
+ return ret;
+}
+
+static int ad7606_pwm_set_low(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+ int ret;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ cnvst_pwm_state.enabled = true;
+ cnvst_pwm_state.duty_cycle = 0;
+
+ ret = pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+
+ return ret;
+}
+
+static int ad7606_pwm_set_swing(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ cnvst_pwm_state.enabled = true;
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period / 2;
+
+ return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+}
+
+static bool ad7606_pwm_is_swinging(struct ad7606_state *st)
+{
+ struct pwm_state cnvst_pwm_state;
+
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+
+ return cnvst_pwm_state.duty_cycle != cnvst_pwm_state.period &&
+ cnvst_pwm_state.duty_cycle != 0;
+}
+
+static int ad7606_set_sampling_freq(struct ad7606_state *st, unsigned long freq)
+{
+ struct pwm_state cnvst_pwm_state;
+ bool is_swinging = ad7606_pwm_is_swinging(st);
+ bool is_high;
+
+ if (freq == 0)
+ return -EINVAL;
+
+ /* Retrieve the previous state. */
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ is_high = cnvst_pwm_state.duty_cycle == cnvst_pwm_state.period;
+
+ cnvst_pwm_state.period = DIV_ROUND_UP_ULL(NSEC_PER_SEC, freq);
+ cnvst_pwm_state.polarity = PWM_POLARITY_NORMAL;
+ if (is_high)
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period;
+ else if (is_swinging)
+ cnvst_pwm_state.duty_cycle = cnvst_pwm_state.period / 2;
+ else
+ cnvst_pwm_state.duty_cycle = 0;
+
+ return pwm_apply_might_sleep(st->cnvst_pwm, &cnvst_pwm_state);
+}
+
static int ad7606_read_samples(struct ad7606_state *st)
{
- unsigned int num = st->chip_info->num_channels - 1;
- u16 *data = st->data;
+ unsigned int num = st->chip_info->num_adc_channels;
- return st->bops->read_block(st->dev, num, data);
+ return st->bops->read_block(st->dev, num, &st->data);
}
static irqreturn_t ad7606_trigger_handler(int irq, void *p)
@@ -104,7 +660,7 @@ static irqreturn_t ad7606_trigger_handler(int irq, void *p)
if (ret)
goto error_ret;
- iio_push_to_buffers_with_timestamp(indio_dev, st->data,
+ iio_push_to_buffers_with_timestamp(indio_dev, &st->data,
iio_get_time_ns(indio_dev));
error_ret:
iio_trigger_notify_done(indio_dev->trig);
@@ -114,24 +670,62 @@ error_ret:
return IRQ_HANDLED;
}
-static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch)
+static int ad7606_scan_direct(struct iio_dev *indio_dev, unsigned int ch,
+ int *val)
{
struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int realbits = st->chip_info->channels[1].scan_type.realbits;
+ const struct iio_chan_spec *chan;
int ret;
- gpiod_set_value(st->gpio_convst, 1);
- ret = wait_for_completion_timeout(&st->completion,
- msecs_to_jiffies(1000));
- if (!ret) {
- ret = -ETIMEDOUT;
- goto error_ret;
+ if (st->gpio_convst) {
+ gpiod_set_value(st->gpio_convst, 1);
+ } else {
+ ret = ad7606_pwm_set_high(st);
+ if (ret < 0)
+ return ret;
+ }
+
+ /*
+ * If no backend, wait for the interruption on busy pin, otherwise just add
+ * a delay to leave time for the data to be available. For now, the latter
+ * will not happen because IIO_CHAN_INFO_RAW is not supported for the backend.
+ * TODO: Add support for reading a single value when the backend is used.
+ */
+ if (!st->back) {
+ ret = wait_for_completion_timeout(&st->completion,
+ msecs_to_jiffies(1000));
+ if (!ret) {
+ ret = -ETIMEDOUT;
+ goto error_ret;
+ }
+ } else {
+ fsleep(1);
}
ret = ad7606_read_samples(st);
- if (ret == 0)
- ret = st->data[ch];
+ if (ret)
+ goto error_ret;
+
+ chan = &indio_dev->channels[ch + 1];
+ if (chan->scan_type.sign == 'u') {
+ if (realbits > 16)
+ *val = st->data.buf32[ch];
+ else
+ *val = st->data.buf16[ch];
+ } else {
+ if (realbits > 16)
+ *val = sign_extend32(st->data.buf32[ch], realbits - 1);
+ else
+ *val = sign_extend32(st->data.buf16[ch], realbits - 1);
+ }
error_ret:
+ if (!st->gpio_convst) {
+ ret = ad7606_pwm_set_low(st);
+ if (ret < 0)
+ return ret;
+ }
gpiod_set_value(st->gpio_convst, 0);
return ret;
@@ -145,53 +739,57 @@ static int ad7606_read_raw(struct iio_dev *indio_dev,
{
int ret, ch = 0;
struct ad7606_state *st = iio_priv(indio_dev);
+ struct ad7606_chan_scale *cs;
+ struct pwm_state cnvst_pwm_state;
switch (m) {
case IIO_CHAN_INFO_RAW:
iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
- ret = ad7606_scan_direct(indio_dev, chan->address);
+ ret = ad7606_scan_direct(indio_dev, chan->address, val);
if (ret < 0)
return ret;
- *val = (short) ret;
return IIO_VAL_INT;
}
unreachable();
case IIO_CHAN_INFO_SCALE:
if (st->sw_mode_en)
ch = chan->address;
- *val = 0;
- *val2 = st->scale_avail[st->range[ch]];
+ cs = &st->chan_scales[ch];
+ *val = cs->scale_avail[cs->range][0];
+ *val2 = cs->scale_avail[cs->range][1];
return IIO_VAL_INT_PLUS_MICRO;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
*val = st->oversampling;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ /*
+ * TODO: return the real frequency intead of the requested one once
+ * pwm_get_state_hw comes upstream.
+ */
+ pwm_get_state(st->cnvst_pwm, &cnvst_pwm_state);
+ *val = DIV_ROUND_CLOSEST_ULL(NSEC_PER_SEC, cnvst_pwm_state.period);
+ return IIO_VAL_INT;
}
return -EINVAL;
}
-static ssize_t ad7606_show_avail(char *buf, const unsigned int *vals,
- unsigned int n, bool micros)
-{
- size_t len = 0;
- int i;
-
- for (i = 0; i < n; i++) {
- len += scnprintf(buf + len, PAGE_SIZE - len,
- micros ? "0.%06u " : "%u ", vals[i]);
- }
- buf[len - 1] = '\n';
-
- return len;
-}
-
static ssize_t in_voltage_scale_available_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7606_state *st = iio_priv(indio_dev);
+ struct ad7606_chan_scale *cs = &st->chan_scales[0];
+ const unsigned int (*vals)[2] = cs->scale_avail;
+ unsigned int i;
+ size_t len = 0;
+
+ for (i = 0; i < cs->num_scales; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%u.%06u ",
+ vals[i][0], vals[i][1]);
+ buf[len - 1] = '\n';
- return ad7606_show_avail(buf, st->scale_avail, st->num_scales, true);
+ return len;
}
static IIO_DEVICE_ATTR_RO(in_voltage_scale_available, 0);
@@ -229,19 +827,27 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int scale_avail_uv[AD760X_MAX_SCALES];
+ struct ad7606_chan_scale *cs;
int i, ret, ch = 0;
guard(mutex)(&st->lock);
switch (mask) {
case IIO_CHAN_INFO_SCALE:
- i = find_closest(val2, st->scale_avail, st->num_scales);
if (st->sw_mode_en)
ch = chan->address;
- ret = st->write_scale(indio_dev, ch, i);
+ cs = &st->chan_scales[ch];
+ for (i = 0; i < cs->num_scales; i++) {
+ scale_avail_uv[i] = cs->scale_avail[i][0] * MICRO +
+ cs->scale_avail[i][1];
+ }
+ val = (val * MICRO) + val2;
+ i = find_closest(val, scale_avail_uv, cs->num_scales);
+ ret = st->write_scale(indio_dev, ch, i + cs->reg_offset);
if (ret < 0)
return ret;
- st->range[ch] = i;
+ cs->range = i;
return 0;
case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
@@ -252,8 +858,13 @@ static int ad7606_write_raw(struct iio_dev *indio_dev,
ret = st->write_os(indio_dev, i);
if (ret < 0)
return ret;
+ st->oversampling = st->oversampling_avail[i];
return 0;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val < 0 && val2 != 0)
+ return -EINVAL;
+ return ad7606_set_sampling_freq(st, val);
default:
return -EINVAL;
}
@@ -265,9 +876,15 @@ static ssize_t ad7606_oversampling_ratio_avail(struct device *dev,
{
struct iio_dev *indio_dev = dev_to_iio_dev(dev);
struct ad7606_state *st = iio_priv(indio_dev);
+ const unsigned int *vals = st->oversampling_avail;
+ unsigned int i;
+ size_t len = 0;
- return ad7606_show_avail(buf, st->oversampling_avail,
- st->num_os_ratios, false);
+ for (i = 0; i < st->num_os_ratios; i++)
+ len += scnprintf(buf + len, PAGE_SIZE - len, "%u ", vals[i]);
+ buf[len - 1] = '\n';
+
+ return len;
}
static IIO_DEVICE_ATTR(oversampling_ratio_available, 0444,
@@ -301,102 +918,13 @@ static const struct attribute_group ad7606_attribute_group_range = {
.attrs = ad7606_attributes_range,
};
-static const struct iio_chan_spec ad7605_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(4),
- AD7605_CHANNEL(0),
- AD7605_CHANNEL(1),
- AD7605_CHANNEL(2),
- AD7605_CHANNEL(3),
-};
-
-static const struct iio_chan_spec ad7606_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7606_CHANNEL(0),
- AD7606_CHANNEL(1),
- AD7606_CHANNEL(2),
- AD7606_CHANNEL(3),
- AD7606_CHANNEL(4),
- AD7606_CHANNEL(5),
- AD7606_CHANNEL(6),
- AD7606_CHANNEL(7),
-};
-
-/*
- * The current assumption that this driver makes for AD7616, is that it's
- * working in Hardware Mode with Serial, Burst and Sequencer modes activated.
- * To activate them, following pins must be pulled high:
- * -SER/PAR
- * -SEQEN
- * And following pins must be pulled low:
- * -WR/BURST
- * -DB4/SER1W
- */
-static const struct iio_chan_spec ad7616_channels[] = {
- IIO_CHAN_SOFT_TIMESTAMP(16),
- AD7606_CHANNEL(0),
- AD7606_CHANNEL(1),
- AD7606_CHANNEL(2),
- AD7606_CHANNEL(3),
- AD7606_CHANNEL(4),
- AD7606_CHANNEL(5),
- AD7606_CHANNEL(6),
- AD7606_CHANNEL(7),
- AD7606_CHANNEL(8),
- AD7606_CHANNEL(9),
- AD7606_CHANNEL(10),
- AD7606_CHANNEL(11),
- AD7606_CHANNEL(12),
- AD7606_CHANNEL(13),
- AD7606_CHANNEL(14),
- AD7606_CHANNEL(15),
-};
-
-static const struct ad7606_chip_info ad7606_chip_info_tbl[] = {
- /* More devices added in future */
- [ID_AD7605_4] = {
- .channels = ad7605_channels,
- .num_channels = 5,
- },
- [ID_AD7606_8] = {
- .channels = ad7606_channels,
- .num_channels = 9,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7606_6] = {
- .channels = ad7606_channels,
- .num_channels = 7,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7606_4] = {
- .channels = ad7606_channels,
- .num_channels = 5,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7606B] = {
- .channels = ad7606_channels,
- .num_channels = 9,
- .oversampling_avail = ad7606_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7606_oversampling_avail),
- },
- [ID_AD7616] = {
- .channels = ad7616_channels,
- .num_channels = 17,
- .oversampling_avail = ad7616_oversampling_avail,
- .oversampling_num = ARRAY_SIZE(ad7616_oversampling_avail),
- .os_req_reset = true,
- .init_delay_ms = 15,
- },
-};
-
static int ad7606_request_gpios(struct ad7606_state *st)
{
struct device *dev = st->dev;
- st->gpio_convst = devm_gpiod_get(dev, "adi,conversion-start",
- GPIOD_OUT_LOW);
+ st->gpio_convst = devm_gpiod_get_optional(dev, "adi,conversion-start",
+ GPIOD_OUT_LOW);
+
if (IS_ERR(st->gpio_convst))
return PTR_ERR(st->gpio_convst);
@@ -438,14 +966,24 @@ static irqreturn_t ad7606_interrupt(int irq, void *dev_id)
{
struct iio_dev *indio_dev = dev_id;
struct ad7606_state *st = iio_priv(indio_dev);
+ int ret;
if (iio_buffer_enabled(indio_dev)) {
- gpiod_set_value(st->gpio_convst, 0);
+ if (st->gpio_convst) {
+ gpiod_set_value(st->gpio_convst, 0);
+ } else {
+ ret = ad7606_pwm_set_low(st);
+ if (ret < 0) {
+ dev_err(st->dev, "PWM set low failed");
+ goto done;
+ }
+ }
iio_trigger_poll_nested(st->trig);
} else {
complete(&st->completion);
}
+done:
return IRQ_HANDLED;
};
@@ -478,14 +1016,81 @@ static int ad7606_buffer_predisable(struct iio_dev *indio_dev)
return 0;
}
+static int ad7606_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long info)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+ struct ad7606_chan_scale *cs;
+ unsigned int ch = 0;
+
+ switch (info) {
+ case IIO_CHAN_INFO_OVERSAMPLING_RATIO:
+ *vals = st->oversampling_avail;
+ *length = st->num_os_ratios;
+ *type = IIO_VAL_INT;
+
+ return IIO_AVAIL_LIST;
+
+ case IIO_CHAN_INFO_SCALE:
+ if (st->sw_mode_en)
+ ch = chan->address;
+
+ cs = &st->chan_scales[ch];
+ *vals = (int *)cs->scale_avail;
+ *length = cs->num_scales;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+
+ return IIO_AVAIL_LIST;
+ }
+ return -EINVAL;
+}
+
+static int ad7606_backend_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ return ad7606_pwm_set_swing(st);
+}
+
+static int ad7606_backend_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ return ad7606_pwm_set_low(st);
+}
+
+static int ad7606_update_scan_mode(struct iio_dev *indio_dev,
+ const unsigned long *scan_mask)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ /*
+ * The update scan mode is only for iio backend compatible drivers.
+ * If the specific update_scan_mode is not defined in the bus ops,
+ * just do nothing and return 0.
+ */
+ if (!st->bops->update_scan_mode)
+ return 0;
+
+ return st->bops->update_scan_mode(indio_dev, scan_mask);
+}
+
static const struct iio_buffer_setup_ops ad7606_buffer_ops = {
.postenable = &ad7606_buffer_postenable,
.predisable = &ad7606_buffer_predisable,
};
+static const struct iio_buffer_setup_ops ad7606_backend_buffer_ops = {
+ .postenable = &ad7606_backend_buffer_postenable,
+ .predisable = &ad7606_backend_buffer_predisable,
+};
+
static const struct iio_info ad7606_info_no_os_or_range = {
.read_raw = &ad7606_read_raw,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_info ad7606_info_os_and_range = {
@@ -493,14 +1098,16 @@ static const struct iio_info ad7606_info_os_and_range = {
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_os_and_range,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
-static const struct iio_info ad7606_info_os_range_and_debug = {
+static const struct iio_info ad7606_info_sw_mode = {
.read_raw = &ad7606_read_raw,
.write_raw = &ad7606_write_raw,
+ .read_avail = &ad7606_read_avail,
.debugfs_reg_access = &ad7606_reg_access,
- .attrs = &ad7606_attribute_group_os_and_range,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_info ad7606_info_os = {
@@ -508,6 +1115,7 @@ static const struct iio_info ad7606_info_os = {
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_os,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_info ad7606_info_range = {
@@ -515,14 +1123,60 @@ static const struct iio_info ad7606_info_range = {
.write_raw = &ad7606_write_raw,
.attrs = &ad7606_attribute_group_range,
.validate_trigger = &ad7606_validate_trigger,
+ .update_scan_mode = &ad7606_update_scan_mode,
};
static const struct iio_trigger_ops ad7606_trigger_ops = {
.validate_device = iio_trigger_validate_own_device,
};
+static int ad7606_sw_mode_setup(struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+
+ st->sw_mode_en = st->bops->sw_mode_config &&
+ device_property_present(st->dev, "adi,sw-mode");
+ if (!st->sw_mode_en)
+ return 0;
+
+ indio_dev->info = &ad7606_info_sw_mode;
+
+ return st->bops->sw_mode_config(indio_dev);
+}
+
+static int ad7606_chan_scales_setup(struct iio_dev *indio_dev)
+{
+ unsigned int num_channels = indio_dev->num_channels - 1;
+ struct ad7606_state *st = iio_priv(indio_dev);
+ struct iio_chan_spec *chans;
+ size_t size;
+ int ch, ret;
+
+ /* Clone IIO channels, since some may be differential */
+ size = indio_dev->num_channels * sizeof(*indio_dev->channels);
+ chans = devm_kzalloc(st->dev, size, GFP_KERNEL);
+ if (!chans)
+ return -ENOMEM;
+
+ memcpy(chans, indio_dev->channels, size);
+ indio_dev->channels = chans;
+
+ for (ch = 0; ch < num_channels; ch++) {
+ ret = st->chip_info->scale_setup_cb(st, &chans[ch + 1], ch);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void ad7606_pwm_disable(void *data)
+{
+ pwm_disable(data);
+}
+
int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
- const char *name, unsigned int id,
+ const struct ad7606_chip_info *chip_info,
const struct ad7606_bus_ops *bops)
{
struct ad7606_state *st;
@@ -540,18 +1194,14 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
mutex_init(&st->lock);
st->bops = bops;
st->base_address = base_address;
- /* tied to logic low, analog input range is +/- 5V */
- st->range[0] = 0;
st->oversampling = 1;
- st->scale_avail = ad7606_scale_avail;
- st->num_scales = ARRAY_SIZE(ad7606_scale_avail);
ret = devm_regulator_get_enable(dev, "avcc");
if (ret)
return dev_err_probe(dev, ret,
"Failed to enable specified AVcc supply\n");
- st->chip_info = &ad7606_chip_info_tbl[id];
+ st->chip_info = chip_info;
if (st->chip_info->oversampling_num) {
st->oversampling_avail = st->chip_info->oversampling_avail;
@@ -574,12 +1224,10 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
indio_dev->info = &ad7606_info_no_os_or_range;
}
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->name = name;
+ indio_dev->name = chip_info->name;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
- init_completion(&st->completion);
-
ret = ad7606_reset(st);
if (ret)
dev_warn(st->dev, "failed to RESET: no RESET GPIO specified\n");
@@ -593,56 +1241,94 @@ int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
st->write_scale = ad7606_write_scale_hw;
st->write_os = ad7606_write_os_hw;
- if (st->bops->sw_mode_config)
- st->sw_mode_en = device_property_present(st->dev,
- "adi,sw-mode");
+ ret = ad7606_sw_mode_setup(indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad7606_chan_scales_setup(indio_dev);
+ if (ret)
+ return ret;
+
+ /* If convst pin is not defined, setup PWM. */
+ if (!st->gpio_convst) {
+ st->cnvst_pwm = devm_pwm_get(dev, NULL);
+ if (IS_ERR(st->cnvst_pwm))
+ return PTR_ERR(st->cnvst_pwm);
- if (st->sw_mode_en) {
- /* Scale of 0.076293 is only available in sw mode */
- st->scale_avail = ad7616_sw_scale_avail;
- st->num_scales = ARRAY_SIZE(ad7616_sw_scale_avail);
+ /* The PWM is initialized at 1MHz to have a fast enough GPIO emulation. */
+ ret = ad7606_set_sampling_freq(st, 1 * MEGA);
+ if (ret)
+ return ret;
- /* After reset, in software mode, ±10 V is set by default */
- memset32(st->range, 2, ARRAY_SIZE(st->range));
- indio_dev->info = &ad7606_info_os_range_and_debug;
+ ret = ad7606_pwm_set_low(st);
+ if (ret)
+ return ret;
- ret = st->bops->sw_mode_config(indio_dev);
- if (ret < 0)
+ /*
+ * PWM is not disabled when sampling stops, but instead its duty cycle is set
+ * to 0% to be sure we have a "low" state. After we unload the driver, let's
+ * disable the PWM.
+ */
+ ret = devm_add_action_or_reset(dev, ad7606_pwm_disable,
+ st->cnvst_pwm);
+ if (ret)
return ret;
}
- st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
- indio_dev->name,
- iio_device_id(indio_dev));
- if (!st->trig)
- return -ENOMEM;
+ if (st->bops->iio_backend_config) {
+ /*
+ * If there is a backend, the PWM should not overpass the maximum sampling
+ * frequency the chip supports.
+ */
+ ret = ad7606_set_sampling_freq(st,
+ chip_info->max_samplerate ? : 2 * KILO);
+ if (ret)
+ return ret;
- st->trig->ops = &ad7606_trigger_ops;
- iio_trigger_set_drvdata(st->trig, indio_dev);
- ret = devm_iio_trigger_register(dev, st->trig);
- if (ret)
- return ret;
+ ret = st->bops->iio_backend_config(dev, indio_dev);
+ if (ret)
+ return ret;
- indio_dev->trig = iio_trigger_get(st->trig);
+ indio_dev->setup_ops = &ad7606_backend_buffer_ops;
+ } else {
- ret = devm_request_threaded_irq(dev, irq,
- NULL,
- &ad7606_interrupt,
- IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
- name, indio_dev);
- if (ret)
- return ret;
+ /* Reserve the PWM use only for backend (force gpio_convst definition) */
+ if (!st->gpio_convst)
+ return dev_err_probe(dev, -EINVAL,
+ "No backend, connect convst to a GPIO");
+
+ init_completion(&st->completion);
+ st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!st->trig)
+ return -ENOMEM;
+
+ st->trig->ops = &ad7606_trigger_ops;
+ iio_trigger_set_drvdata(st->trig, indio_dev);
+ ret = devm_iio_trigger_register(dev, st->trig);
+ if (ret)
+ return ret;
- ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
- &iio_pollfunc_store_time,
- &ad7606_trigger_handler,
- &ad7606_buffer_ops);
- if (ret)
- return ret;
+ indio_dev->trig = iio_trigger_get(st->trig);
+
+ ret = devm_request_threaded_irq(dev, irq, NULL, &ad7606_interrupt,
+ IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+ chip_info->name, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ &iio_pollfunc_store_time,
+ &ad7606_trigger_handler,
+ &ad7606_buffer_ops);
+ if (ret)
+ return ret;
+ }
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(ad7606_probe, IIO_AD7606);
+EXPORT_SYMBOL_NS_GPL(ad7606_probe, "IIO_AD7606");
#ifdef CONFIG_PM_SLEEP
@@ -665,7 +1351,7 @@ static int ad7606_resume(struct device *dev)
struct ad7606_state *st = iio_priv(indio_dev);
if (st->gpio_standby) {
- gpiod_set_value(st->gpio_range, st->range[0]);
+ gpiod_set_value(st->gpio_range, st->chan_scales[0].range);
gpiod_set_value(st->gpio_standby, 1);
ad7606_reset(st);
}
@@ -674,7 +1360,7 @@ static int ad7606_resume(struct device *dev)
}
SIMPLE_DEV_PM_OPS(ad7606_pm_ops, ad7606_suspend, ad7606_resume);
-EXPORT_SYMBOL_NS_GPL(ad7606_pm_ops, IIO_AD7606);
+EXPORT_SYMBOL_NS_GPL(ad7606_pm_ops, "IIO_AD7606");
#endif
diff --git a/drivers/iio/adc/ad7606.h b/drivers/iio/adc/ad7606.h
index 6649e84d25de..998814a92b82 100644
--- a/drivers/iio/adc/ad7606.h
+++ b/drivers/iio/adc/ad7606.h
@@ -8,7 +8,9 @@
#ifndef IIO_ADC_AD7606_H_
#define IIO_ADC_AD7606_H_
-#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all) { \
+#define AD760X_MAX_CHANNELS 16
+
+#define AD760X_CHANNEL(num, mask_sep, mask_type, mask_all, bits) { \
.type = IIO_VOLTAGE, \
.indexed = 1, \
.channel = num, \
@@ -19,39 +21,79 @@
.scan_index = num, \
.scan_type = { \
.sign = 's', \
- .realbits = 16, \
- .storagebits = 16, \
+ .realbits = (bits), \
+ .storagebits = (bits) > 16 ? 32 : 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+#define AD7606_SW_CHANNEL(num, bits) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = num, \
+ .address = num, \
+ .info_mask_separate = \
+ BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_separate_available = \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+ .info_mask_shared_by_all_available = \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), \
+ .scan_index = num, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = (bits), \
+ .storagebits = (bits) > 16 ? 32 : 16, \
.endianness = IIO_CPU, \
}, \
}
#define AD7605_CHANNEL(num) \
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
- BIT(IIO_CHAN_INFO_SCALE), 0)
+ BIT(IIO_CHAN_INFO_SCALE), 0, 16)
-#define AD7606_CHANNEL(num) \
+#define AD7606_CHANNEL(num, bits) \
AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW), \
BIT(IIO_CHAN_INFO_SCALE), \
- BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), bits)
+
+#define AD7616_CHANNEL(num) AD7606_SW_CHANNEL(num, 16)
+
+#define AD7606_BI_CHANNEL(num) \
+ AD760X_CHANNEL(num, 0, \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO), 16)
-#define AD7616_CHANNEL(num) \
- AD760X_CHANNEL(num, BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),\
- 0, BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO))
+struct ad7606_state;
+
+typedef int (*ad7606_scale_setup_cb_t)(struct ad7606_state *st,
+ struct iio_chan_spec *chan, int ch);
/**
* struct ad7606_chip_info - chip specific information
* @channels: channel specification
+ * @max_samplerate: maximum supported samplerate
+ * @name device name
* @num_channels: number of channels
+ * @num_adc_channels the number of channels the ADC actually inputs.
+ * @scale_setup_cb: callback to setup the scales for each channel
* @oversampling_avail pointer to the array which stores the available
* oversampling ratios.
* @oversampling_num number of elements stored in oversampling_avail array
* @os_req_reset some devices require a reset to update oversampling
- * @init_delay_ms required delay in miliseconds for initialization
+ * @init_delay_ms required delay in milliseconds for initialization
* after a restart
*/
struct ad7606_chip_info {
const struct iio_chan_spec *channels;
+ unsigned int max_samplerate;
+ const char *name;
+ unsigned int num_adc_channels;
unsigned int num_channels;
+ ad7606_scale_setup_cb_t scale_setup_cb;
const unsigned int *oversampling_avail;
unsigned int oversampling_num;
bool os_req_reset;
@@ -59,16 +101,31 @@ struct ad7606_chip_info {
};
/**
+ * struct ad7606_chan_scale - channel scale configuration
+ * @scale_avail pointer to the array which stores the available scales
+ * @num_scales number of elements stored in the scale_avail array
+ * @range voltage range selection, selects which scale to apply
+ * @reg_offset offset for the register value, to be applied when
+ * writing the value of 'range' to the register value
+ */
+struct ad7606_chan_scale {
+#define AD760X_MAX_SCALES 16
+ const unsigned int (*scale_avail)[2];
+ unsigned int num_scales;
+ unsigned int range;
+ unsigned int reg_offset;
+};
+
+/**
* struct ad7606_state - driver instance specific data
* @dev pointer to kernel device
* @chip_info entry in the table of chips that describes this device
* @bops bus operations (SPI or parallel)
- * @range voltage range selection, selects which scale to apply
+ * @chan_scales scale configuration for channels
* @oversampling oversampling selection
+ * @cnvst_pwm pointer to the PWM device connected to the cnvst pin
* @base_address address from where to read data in parallel operation
* @sw_mode_en software mode enabled
- * @scale_avail pointer to the array which stores the available scales
- * @num_scales number of elements stored in the scale_avail array
* @oversampling_avail pointer to the array which stores the available
* oversampling ratios.
* @num_os_ratios number of elements stored in oversampling_avail array
@@ -92,14 +149,14 @@ struct ad7606_state {
struct device *dev;
const struct ad7606_chip_info *chip_info;
const struct ad7606_bus_ops *bops;
- unsigned int range[16];
+ struct ad7606_chan_scale chan_scales[AD760X_MAX_CHANNELS];
unsigned int oversampling;
+ struct pwm_device *cnvst_pwm;
void __iomem *base_address;
bool sw_mode_en;
- const unsigned int *scale_avail;
- unsigned int num_scales;
const unsigned int *oversampling_avail;
unsigned int num_os_ratios;
+ struct iio_backend *back;
int (*write_scale)(struct iio_dev *indio_dev, int ch, int val);
int (*write_os)(struct iio_dev *indio_dev, int val);
@@ -116,24 +173,33 @@ struct ad7606_state {
/*
* DMA (thus cache coherency maintenance) may require the
* transfer buffers to live in their own cache lines.
- * 16 * 16-bit samples + 64-bit timestamp
+ * 16 * 16-bit samples + 64-bit timestamp - for AD7616
+ * 8 * 32-bit samples + 64-bit timestamp - for AD7616C-18 (and similar)
*/
- unsigned short data[20] __aligned(IIO_DMA_MINALIGN);
+ union {
+ u16 buf16[20];
+ u32 buf32[10];
+ } data __aligned(IIO_DMA_MINALIGN);
__be16 d16[2];
};
/**
* struct ad7606_bus_ops - driver bus operations
+ * @iio_backend_config function pointer for configuring the iio_backend for
+ * the compatibles that use it
* @read_block function pointer for reading blocks of data
* @sw_mode_config: pointer to a function which configured the device
* for software mode
* @reg_read function pointer for reading spi register
* @reg_write function pointer for writing spi register
* @write_mask function pointer for write spi register with mask
+ * @update_scan_mode function pointer for handling the calls to iio_info's update_scan
+ * mode when enabling/disabling channels.
* @rd_wr_cmd pointer to the function which calculates the spi address
*/
struct ad7606_bus_ops {
/* more methods added in future? */
+ int (*iio_backend_config)(struct device *dev, struct iio_dev *indio_dev);
int (*read_block)(struct device *dev, int num, void *data);
int (*sw_mode_config)(struct iio_dev *indio_dev);
int (*reg_read)(struct ad7606_state *st, unsigned int addr);
@@ -144,23 +210,37 @@ struct ad7606_bus_ops {
unsigned int addr,
unsigned long mask,
unsigned int val);
+ int (*update_scan_mode)(struct iio_dev *indio_dev, const unsigned long *scan_mask);
u16 (*rd_wr_cmd)(int addr, char isWriteOp);
};
+/**
+ * struct ad7606_bus_info - agregate ad7606_chip_info and ad7606_bus_ops
+ * @chip_info entry in the table of chips that describes this device
+ * @bops bus operations (SPI or parallel)
+ */
+struct ad7606_bus_info {
+ const struct ad7606_chip_info *chip_info;
+ const struct ad7606_bus_ops *bops;
+};
+
int ad7606_probe(struct device *dev, int irq, void __iomem *base_address,
- const char *name, unsigned int id,
+ const struct ad7606_chip_info *info,
const struct ad7606_bus_ops *bops);
int ad7606_reset(struct ad7606_state *st);
-enum ad7606_supported_device_ids {
- ID_AD7605_4,
- ID_AD7606_8,
- ID_AD7606_6,
- ID_AD7606_4,
- ID_AD7606B,
- ID_AD7616,
-};
+extern const struct ad7606_chip_info ad7605_4_info;
+extern const struct ad7606_chip_info ad7606_8_info;
+extern const struct ad7606_chip_info ad7606_6_info;
+extern const struct ad7606_chip_info ad7606_4_info;
+extern const struct ad7606_chip_info ad7606b_info;
+extern const struct ad7606_chip_info ad7606c_16_info;
+extern const struct ad7606_chip_info ad7606c_18_info;
+extern const struct ad7606_chip_info ad7607_info;
+extern const struct ad7606_chip_info ad7608_info;
+extern const struct ad7606_chip_info ad7609_info;
+extern const struct ad7606_chip_info ad7616_info;
#ifdef CONFIG_PM_SLEEP
extern const struct dev_pm_ops ad7606_pm_ops;
diff --git a/drivers/iio/adc/ad7606_par.c b/drivers/iio/adc/ad7606_par.c
index 02d8c309304e..64733b607aa8 100644
--- a/drivers/iio/adc/ad7606_par.c
+++ b/drivers/iio/adc/ad7606_par.c
@@ -2,20 +2,95 @@
/*
* AD7606 Parallel Interface ADC driver
*
- * Copyright 2011 Analog Devices Inc.
+ * Copyright 2011 - 2024 Analog Devices Inc.
+ * Copyright 2024 BayLibre SAS.
*/
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/io.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
-#include <linux/gpio/consumer.h>
#include <linux/platform_device.h>
+#include <linux/property.h>
#include <linux/types.h>
-#include <linux/err.h>
-#include <linux/io.h>
+#include <linux/iio/backend.h>
#include <linux/iio/iio.h>
+
#include "ad7606.h"
+static const struct iio_chan_spec ad7606b_bi_channels[] = {
+ AD7606_BI_CHANNEL(0),
+ AD7606_BI_CHANNEL(1),
+ AD7606_BI_CHANNEL(2),
+ AD7606_BI_CHANNEL(3),
+ AD7606_BI_CHANNEL(4),
+ AD7606_BI_CHANNEL(5),
+ AD7606_BI_CHANNEL(6),
+ AD7606_BI_CHANNEL(7),
+};
+
+static int ad7606_bi_update_scan_mode(struct iio_dev *indio_dev, const unsigned long *scan_mask)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int c, ret;
+
+ for (c = 0; c < indio_dev->num_channels; c++) {
+ if (test_bit(c, scan_mask))
+ ret = iio_backend_chan_enable(st->back, c);
+ else
+ ret = iio_backend_chan_disable(st->back, c);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ad7606_bi_setup_iio_backend(struct device *dev, struct iio_dev *indio_dev)
+{
+ struct ad7606_state *st = iio_priv(indio_dev);
+ unsigned int ret, c;
+ struct iio_backend_data_fmt data = {
+ .sign_extend = true,
+ .enable = true,
+ };
+
+ st->back = devm_iio_backend_get(dev, NULL);
+ if (IS_ERR(st->back))
+ return PTR_ERR(st->back);
+
+ /* If the device is iio_backend powered the PWM is mandatory */
+ if (!st->cnvst_pwm)
+ return dev_err_probe(st->dev, -EINVAL,
+ "A PWM is mandatory when using backend.\n");
+
+ ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_backend_enable(dev, st->back);
+ if (ret)
+ return ret;
+
+ for (c = 0; c < indio_dev->num_channels; c++) {
+ ret = iio_backend_data_format_set(st->back, c, &data);
+ if (ret)
+ return ret;
+ }
+
+ indio_dev->channels = ad7606b_bi_channels;
+ indio_dev->num_channels = 8;
+
+ return 0;
+}
+
+static const struct ad7606_bus_ops ad7606_bi_bops = {
+ .iio_backend_config = ad7606_bi_setup_iio_backend,
+ .update_scan_mode = ad7606_bi_update_scan_mode,
+};
+
static int ad7606_par16_read_block(struct device *dev,
int count, void *buf)
{
@@ -89,12 +164,32 @@ static const struct ad7606_bus_ops ad7606_par8_bops = {
static int ad7606_par_probe(struct platform_device *pdev)
{
- const struct platform_device_id *id = platform_get_device_id(pdev);
+ const struct ad7606_chip_info *chip_info;
+ const struct platform_device_id *id;
struct resource *res;
void __iomem *addr;
resource_size_t remap_size;
int irq;
+ /*
+ * If a firmware node is available (ACPI or DT), platform_device_id is null
+ * and we must use get_match_data.
+ */
+ if (dev_fwnode(&pdev->dev)) {
+ chip_info = device_get_match_data(&pdev->dev);
+ if (device_property_present(&pdev->dev, "io-backends"))
+ /*
+ * If a backend is available ,call the core probe with backend
+ * bops, otherwise use the former bops.
+ */
+ return ad7606_probe(&pdev->dev, 0, NULL,
+ chip_info,
+ &ad7606_bi_bops);
+ } else {
+ id = platform_get_device_id(pdev);
+ chip_info = (const struct ad7606_chip_info *)id->driver_data;
+ }
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@@ -105,26 +200,33 @@ static int ad7606_par_probe(struct platform_device *pdev)
remap_size = resource_size(res);
- return ad7606_probe(&pdev->dev, irq, addr,
- id->name, id->driver_data,
+ return ad7606_probe(&pdev->dev, irq, addr, chip_info,
remap_size > 1 ? &ad7606_par16_bops :
&ad7606_par8_bops);
}
static const struct platform_device_id ad7606_driver_ids[] = {
- { .name = "ad7605-4", .driver_data = ID_AD7605_4, },
- { .name = "ad7606-4", .driver_data = ID_AD7606_4, },
- { .name = "ad7606-6", .driver_data = ID_AD7606_6, },
- { .name = "ad7606-8", .driver_data = ID_AD7606_8, },
+ { .name = "ad7605-4", .driver_data = (kernel_ulong_t)&ad7605_4_info, },
+ { .name = "ad7606-4", .driver_data = (kernel_ulong_t)&ad7606_4_info, },
+ { .name = "ad7606-6", .driver_data = (kernel_ulong_t)&ad7606_6_info, },
+ { .name = "ad7606-8", .driver_data = (kernel_ulong_t)&ad7606_8_info, },
+ { .name = "ad7606b", .driver_data = (kernel_ulong_t)&ad7606b_info, },
+ { .name = "ad7607", .driver_data = (kernel_ulong_t)&ad7607_info, },
+ { .name = "ad7608", .driver_data = (kernel_ulong_t)&ad7608_info, },
+ { .name = "ad7609", .driver_data = (kernel_ulong_t)&ad7609_info, },
{ }
};
MODULE_DEVICE_TABLE(platform, ad7606_driver_ids);
static const struct of_device_id ad7606_of_match[] = {
- { .compatible = "adi,ad7605-4" },
- { .compatible = "adi,ad7606-4" },
- { .compatible = "adi,ad7606-6" },
- { .compatible = "adi,ad7606-8" },
+ { .compatible = "adi,ad7605-4", .data = &ad7605_4_info },
+ { .compatible = "adi,ad7606-4", .data = &ad7606_4_info },
+ { .compatible = "adi,ad7606-6", .data = &ad7606_6_info },
+ { .compatible = "adi,ad7606-8", .data = &ad7606_8_info },
+ { .compatible = "adi,ad7606b", .data = &ad7606b_info },
+ { .compatible = "adi,ad7607", .data = &ad7607_info },
+ { .compatible = "adi,ad7608", .data = &ad7608_info },
+ { .compatible = "adi,ad7609", .data = &ad7609_info },
{ }
};
MODULE_DEVICE_TABLE(of, ad7606_of_match);
@@ -143,4 +245,5 @@ module_platform_driver(ad7606_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD7606);
+MODULE_IMPORT_NS("IIO_AD7606");
+MODULE_IMPORT_NS("IIO_BACKEND");
diff --git a/drivers/iio/adc/ad7606_spi.c b/drivers/iio/adc/ad7606_spi.c
index 62ec12195307..e2c147525706 100644
--- a/drivers/iio/adc/ad7606_spi.c
+++ b/drivers/iio/adc/ad7606_spi.c
@@ -5,10 +5,10 @@
* Copyright 2011 Analog Devices Inc.
*/
+#include <linux/err.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/types.h>
-#include <linux/err.h>
#include <linux/iio/iio.h>
#include "ad7606.h"
@@ -67,14 +67,26 @@ static const struct iio_chan_spec ad7616_sw_channels[] = {
static const struct iio_chan_spec ad7606b_sw_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(8),
- AD7616_CHANNEL(0),
- AD7616_CHANNEL(1),
- AD7616_CHANNEL(2),
- AD7616_CHANNEL(3),
- AD7616_CHANNEL(4),
- AD7616_CHANNEL(5),
- AD7616_CHANNEL(6),
- AD7616_CHANNEL(7),
+ AD7606_SW_CHANNEL(0, 16),
+ AD7606_SW_CHANNEL(1, 16),
+ AD7606_SW_CHANNEL(2, 16),
+ AD7606_SW_CHANNEL(3, 16),
+ AD7606_SW_CHANNEL(4, 16),
+ AD7606_SW_CHANNEL(5, 16),
+ AD7606_SW_CHANNEL(6, 16),
+ AD7606_SW_CHANNEL(7, 16),
+};
+
+static const struct iio_chan_spec ad7606c_18_sw_channels[] = {
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+ AD7606_SW_CHANNEL(0, 18),
+ AD7606_SW_CHANNEL(1, 18),
+ AD7606_SW_CHANNEL(2, 18),
+ AD7606_SW_CHANNEL(3, 18),
+ AD7606_SW_CHANNEL(4, 18),
+ AD7606_SW_CHANNEL(5, 18),
+ AD7606_SW_CHANNEL(6, 18),
+ AD7606_SW_CHANNEL(7, 18),
};
static const unsigned int ad7606B_oversampling_avail[9] = {
@@ -120,6 +132,32 @@ static int ad7606_spi_read_block(struct device *dev,
return 0;
}
+static int ad7606_spi_read_block14to16(struct device *dev,
+ int count, void *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct spi_transfer xfer = {
+ .bits_per_word = 14,
+ .len = count * sizeof(u16),
+ .rx_buf = buf,
+ };
+
+ return spi_sync_transfer(spi, &xfer, 1);
+}
+
+static int ad7606_spi_read_block18to32(struct device *dev,
+ int count, void *buf)
+{
+ struct spi_device *spi = to_spi_device(dev);
+ struct spi_transfer xfer = {
+ .bits_per_word = 18,
+ .len = count * sizeof(u32),
+ .rx_buf = buf,
+ };
+
+ return spi_sync_transfer(spi, &xfer, 1);
+}
+
static int ad7606_spi_reg_read(struct ad7606_state *st, unsigned int addr)
{
struct spi_device *spi = to_spi_device(st->dev);
@@ -283,10 +321,31 @@ static int ad7606B_sw_mode_config(struct iio_dev *indio_dev)
return 0;
}
+static int ad7606c_18_sw_mode_config(struct iio_dev *indio_dev)
+{
+ int ret;
+
+ ret = ad7606B_sw_mode_config(indio_dev);
+ if (ret)
+ return ret;
+
+ indio_dev->channels = ad7606c_18_sw_channels;
+
+ return 0;
+}
+
static const struct ad7606_bus_ops ad7606_spi_bops = {
.read_block = ad7606_spi_read_block,
};
+static const struct ad7606_bus_ops ad7607_spi_bops = {
+ .read_block = ad7606_spi_read_block14to16,
+};
+
+static const struct ad7606_bus_ops ad7608_spi_bops = {
+ .read_block = ad7606_spi_read_block18to32,
+};
+
static const struct ad7606_bus_ops ad7616_spi_bops = {
.read_block = ad7606_spi_read_block,
.reg_read = ad7606_spi_reg_read,
@@ -296,7 +355,7 @@ static const struct ad7606_bus_ops ad7616_spi_bops = {
.sw_mode_config = ad7616_sw_mode_config,
};
-static const struct ad7606_bus_ops ad7606B_spi_bops = {
+static const struct ad7606_bus_ops ad7606b_spi_bops = {
.read_block = ad7606_spi_read_block,
.reg_read = ad7606_spi_reg_read,
.reg_write = ad7606_spi_reg_write,
@@ -305,46 +364,106 @@ static const struct ad7606_bus_ops ad7606B_spi_bops = {
.sw_mode_config = ad7606B_sw_mode_config,
};
+static const struct ad7606_bus_ops ad7606c_18_spi_bops = {
+ .read_block = ad7606_spi_read_block18to32,
+ .reg_read = ad7606_spi_reg_read,
+ .reg_write = ad7606_spi_reg_write,
+ .write_mask = ad7606_spi_write_mask,
+ .rd_wr_cmd = ad7606B_spi_rd_wr_cmd,
+ .sw_mode_config = ad7606c_18_sw_mode_config,
+};
+
+static const struct ad7606_bus_info ad7605_4_bus_info = {
+ .chip_info = &ad7605_4_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606_8_bus_info = {
+ .chip_info = &ad7606_8_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606_6_bus_info = {
+ .chip_info = &ad7606_6_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606_4_bus_info = {
+ .chip_info = &ad7606_4_info,
+ .bops = &ad7606_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606b_bus_info = {
+ .chip_info = &ad7606b_info,
+ .bops = &ad7606b_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606c_16_bus_info = {
+ .chip_info = &ad7606c_16_info,
+ .bops = &ad7606b_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7606c_18_bus_info = {
+ .chip_info = &ad7606c_18_info,
+ .bops = &ad7606c_18_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7607_bus_info = {
+ .chip_info = &ad7607_info,
+ .bops = &ad7607_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7608_bus_info = {
+ .chip_info = &ad7608_info,
+ .bops = &ad7608_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7609_bus_info = {
+ .chip_info = &ad7609_info,
+ .bops = &ad7608_spi_bops,
+};
+
+static const struct ad7606_bus_info ad7616_bus_info = {
+ .chip_info = &ad7616_info,
+ .bops = &ad7616_spi_bops,
+};
+
static int ad7606_spi_probe(struct spi_device *spi)
{
- const struct spi_device_id *id = spi_get_device_id(spi);
- const struct ad7606_bus_ops *bops;
-
- switch (id->driver_data) {
- case ID_AD7616:
- bops = &ad7616_spi_bops;
- break;
- case ID_AD7606B:
- bops = &ad7606B_spi_bops;
- break;
- default:
- bops = &ad7606_spi_bops;
- break;
- }
+ const struct ad7606_bus_info *bus_info = spi_get_device_match_data(spi);
return ad7606_probe(&spi->dev, spi->irq, NULL,
- id->name, id->driver_data,
- bops);
+ bus_info->chip_info, bus_info->bops);
}
static const struct spi_device_id ad7606_id_table[] = {
- { "ad7605-4", ID_AD7605_4 },
- { "ad7606-4", ID_AD7606_4 },
- { "ad7606-6", ID_AD7606_6 },
- { "ad7606-8", ID_AD7606_8 },
- { "ad7606b", ID_AD7606B },
- { "ad7616", ID_AD7616 },
+ { "ad7605-4", (kernel_ulong_t)&ad7605_4_bus_info },
+ { "ad7606-4", (kernel_ulong_t)&ad7606_4_bus_info },
+ { "ad7606-6", (kernel_ulong_t)&ad7606_6_bus_info },
+ { "ad7606-8", (kernel_ulong_t)&ad7606_8_bus_info },
+ { "ad7606b", (kernel_ulong_t)&ad7606b_bus_info },
+ { "ad7606c-16", (kernel_ulong_t)&ad7606c_16_bus_info },
+ { "ad7606c-18", (kernel_ulong_t)&ad7606c_18_bus_info },
+ { "ad7607", (kernel_ulong_t)&ad7607_bus_info },
+ { "ad7608", (kernel_ulong_t)&ad7608_bus_info },
+ { "ad7609", (kernel_ulong_t)&ad7609_bus_info },
+ { "ad7616", (kernel_ulong_t)&ad7616_bus_info },
{ }
};
MODULE_DEVICE_TABLE(spi, ad7606_id_table);
static const struct of_device_id ad7606_of_match[] = {
- { .compatible = "adi,ad7605-4" },
- { .compatible = "adi,ad7606-4" },
- { .compatible = "adi,ad7606-6" },
- { .compatible = "adi,ad7606-8" },
- { .compatible = "adi,ad7606b" },
- { .compatible = "adi,ad7616" },
+ { .compatible = "adi,ad7605-4", .data = &ad7605_4_bus_info },
+ { .compatible = "adi,ad7606-4", .data = &ad7606_4_bus_info },
+ { .compatible = "adi,ad7606-6", .data = &ad7606_6_bus_info },
+ { .compatible = "adi,ad7606-8", .data = &ad7606_8_bus_info },
+ { .compatible = "adi,ad7606b", .data = &ad7606b_bus_info },
+ { .compatible = "adi,ad7606c-16", .data = &ad7606c_16_bus_info },
+ { .compatible = "adi,ad7606c-18", .data = &ad7606c_18_bus_info },
+ { .compatible = "adi,ad7607", .data = &ad7607_bus_info },
+ { .compatible = "adi,ad7608", .data = &ad7608_bus_info },
+ { .compatible = "adi,ad7609", .data = &ad7609_bus_info },
+ { .compatible = "adi,ad7616", .data = &ad7616_bus_info },
{ }
};
MODULE_DEVICE_TABLE(of, ad7606_of_match);
@@ -363,4 +482,4 @@ module_spi_driver(ad7606_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7606 ADC");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD7606);
+MODULE_IMPORT_NS("IIO_AD7606");
diff --git a/drivers/iio/adc/ad7625.c b/drivers/iio/adc/ad7625.c
new file mode 100644
index 000000000000..aefe3bf75c91
--- /dev/null
+++ b/drivers/iio/adc/ad7625.c
@@ -0,0 +1,684 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
+/*
+ * Analog Devices Inc. AD7625 ADC driver
+ *
+ * Copyright 2024 Analog Devices Inc.
+ * Copyright 2024 BayLibre, SAS
+ *
+ * Note that this driver requires the AXI ADC IP block configured for
+ * LVDS to function. See Documentation/iio/ad7625.rst for more
+ * information.
+ */
+
+#include <linux/clk.h>
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/backend.h>
+#include <linux/iio/iio.h>
+#include <linux/kernel.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pwm.h>
+#include <linux/regulator/consumer.h>
+#include <linux/units.h>
+
+#define AD7625_INTERNAL_REF_MV 4096
+#define AD7960_MAX_NBW_FREQ (2 * MEGA)
+
+struct ad7625_timing_spec {
+ /* Max conversion high time (t_{CNVH}). */
+ unsigned int conv_high_ns;
+ /* Max conversion to MSB delay (t_{MSB}). */
+ unsigned int conv_msb_ns;
+};
+
+struct ad7625_chip_info {
+ const char *name;
+ const unsigned int max_sample_freq_hz;
+ const struct ad7625_timing_spec *timing_spec;
+ const struct iio_chan_spec chan_spec;
+ const bool has_power_down_state;
+ const bool has_bandwidth_control;
+ const bool has_internal_vref;
+};
+
+/* AD7625_CHAN_SPEC - Define a chan spec structure for a specific chip */
+#define AD7625_CHAN_SPEC(_bits) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .differential = 1, \
+ .channel = 0, \
+ .channel2 = 1, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_SCALE), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = 0, \
+ .scan_type.sign = 's', \
+ .scan_type.storagebits = (_bits) > 16 ? 32 : 16, \
+ .scan_type.realbits = (_bits), \
+}
+
+struct ad7625_state {
+ const struct ad7625_chip_info *info;
+ struct iio_backend *back;
+ /* rate of the clock gated by the "clk_gate" PWM */
+ u32 ref_clk_rate_hz;
+ /* PWM burst signal for transferring acquired data to the host */
+ struct pwm_device *clk_gate_pwm;
+ /*
+ * PWM control signal for initiating data conversion. Analog
+ * inputs are sampled beginning on this signal's rising edge.
+ */
+ struct pwm_device *cnv_pwm;
+ /*
+ * Waveforms containing the last-requested and rounded
+ * properties for the clk_gate and cnv PWMs
+ */
+ struct pwm_waveform clk_gate_wf;
+ struct pwm_waveform cnv_wf;
+ unsigned int vref_mv;
+ u32 sampling_freq_hz;
+ /*
+ * Optional GPIOs for controlling device state. EN0 and EN1
+ * determine voltage reference configuration and on/off state.
+ * EN2 controls the device -3dB bandwidth (and by extension, max
+ * sample rate). EN3 controls the VCM reference output. EN2 and
+ * EN3 are only present for the AD796x devices.
+ */
+ struct gpio_desc *en_gpios[4];
+ bool can_power_down;
+ bool can_refin;
+ bool can_ref_4v096;
+ /*
+ * Indicate whether the bandwidth can be narrow (9MHz).
+ * When true, device sample rate must also be < 2MSPS.
+ */
+ bool can_narrow_bandwidth;
+ /* Indicate whether the bandwidth can be wide (28MHz). */
+ bool can_wide_bandwidth;
+ bool can_ref_5v;
+ bool can_snooze;
+ bool can_test_pattern;
+ /* Indicate whether there is a REFIN supply connected */
+ bool have_refin;
+};
+
+static const struct ad7625_timing_spec ad7625_timing_spec = {
+ .conv_high_ns = 40,
+ .conv_msb_ns = 145,
+};
+
+static const struct ad7625_timing_spec ad7626_timing_spec = {
+ .conv_high_ns = 40,
+ .conv_msb_ns = 80,
+};
+
+/*
+ * conv_msb_ns is set to 0 instead of the datasheet maximum of 200ns to
+ * avoid exceeding the minimum conversion time, i.e. it is effectively
+ * modulo 200 and offset by a full period. Values greater than or equal
+ * to the period would be rejected by the PWM API.
+ */
+static const struct ad7625_timing_spec ad7960_timing_spec = {
+ .conv_high_ns = 80,
+ .conv_msb_ns = 0,
+};
+
+static const struct ad7625_chip_info ad7625_chip_info = {
+ .name = "ad7625",
+ .max_sample_freq_hz = 6 * MEGA,
+ .timing_spec = &ad7625_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(16),
+ .has_power_down_state = false,
+ .has_bandwidth_control = false,
+ .has_internal_vref = true,
+};
+
+static const struct ad7625_chip_info ad7626_chip_info = {
+ .name = "ad7626",
+ .max_sample_freq_hz = 10 * MEGA,
+ .timing_spec = &ad7626_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(16),
+ .has_power_down_state = true,
+ .has_bandwidth_control = false,
+ .has_internal_vref = true,
+};
+
+static const struct ad7625_chip_info ad7960_chip_info = {
+ .name = "ad7960",
+ .max_sample_freq_hz = 5 * MEGA,
+ .timing_spec = &ad7960_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(18),
+ .has_power_down_state = true,
+ .has_bandwidth_control = true,
+ .has_internal_vref = false,
+};
+
+static const struct ad7625_chip_info ad7961_chip_info = {
+ .name = "ad7961",
+ .max_sample_freq_hz = 5 * MEGA,
+ .timing_spec = &ad7960_timing_spec,
+ .chan_spec = AD7625_CHAN_SPEC(16),
+ .has_power_down_state = true,
+ .has_bandwidth_control = true,
+ .has_internal_vref = false,
+};
+
+enum ad7960_mode {
+ AD7960_MODE_POWER_DOWN,
+ AD7960_MODE_SNOOZE,
+ AD7960_MODE_NARROW_BANDWIDTH,
+ AD7960_MODE_WIDE_BANDWIDTH,
+ AD7960_MODE_TEST_PATTERN,
+};
+
+static int ad7625_set_sampling_freq(struct ad7625_state *st, u32 freq)
+{
+ u32 target;
+ struct pwm_waveform clk_gate_wf = { }, cnv_wf = { };
+ int ret;
+
+ target = DIV_ROUND_UP(NSEC_PER_SEC, freq);
+ cnv_wf.period_length_ns = clamp(target, 100, 10 * KILO);
+
+ /*
+ * Use the maximum conversion time t_CNVH from the datasheet as
+ * the duty_cycle for ref_clk, cnv, and clk_gate
+ */
+ cnv_wf.duty_length_ns = st->info->timing_spec->conv_high_ns;
+
+ ret = pwm_round_waveform_might_sleep(st->cnv_pwm, &cnv_wf);
+ if (ret)
+ return ret;
+
+ /*
+ * Set up the burst signal for transferring data. period and
+ * offset should mirror the CNV signal
+ */
+ clk_gate_wf.period_length_ns = cnv_wf.period_length_ns;
+
+ clk_gate_wf.duty_length_ns = DIV_ROUND_UP_ULL((u64)NSEC_PER_SEC *
+ st->info->chan_spec.scan_type.realbits,
+ st->ref_clk_rate_hz);
+
+ /* max t_MSB from datasheet */
+ clk_gate_wf.duty_offset_ns = st->info->timing_spec->conv_msb_ns;
+
+ ret = pwm_round_waveform_might_sleep(st->clk_gate_pwm, &clk_gate_wf);
+ if (ret)
+ return ret;
+
+ st->cnv_wf = cnv_wf;
+ st->clk_gate_wf = clk_gate_wf;
+
+ /* TODO: Add a rounding API for PWMs that can simplify this */
+ target = DIV_ROUND_CLOSEST(st->ref_clk_rate_hz, freq);
+ st->sampling_freq_hz = DIV_ROUND_CLOSEST(st->ref_clk_rate_hz,
+ target);
+
+ return 0;
+}
+
+static int ad7625_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ int *val, int *val2, long info)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = st->sampling_freq_hz;
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ *val = st->vref_mv;
+ *val2 = chan->scan_type.realbits - 1;
+
+ return IIO_VAL_FRACTIONAL_LOG2;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7625_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long info)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+
+ switch (info) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
+ return ad7625_set_sampling_freq(st, val);
+ unreachable();
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7625_parse_mode(struct device *dev, struct ad7625_state *st,
+ int num_gpios)
+{
+ bool en_always_on[4], en_always_off[4];
+ bool en_may_be_on[4], en_may_be_off[4];
+ char en_gpio_buf[4];
+ char always_on_buf[18];
+ int i;
+
+ for (i = 0; i < num_gpios; i++) {
+ snprintf(en_gpio_buf, sizeof(en_gpio_buf), "en%d", i);
+ snprintf(always_on_buf, sizeof(always_on_buf),
+ "adi,en%d-always-on", i);
+ /* Set the device to 0b0000 (power-down mode) by default */
+ st->en_gpios[i] = devm_gpiod_get_optional(dev, en_gpio_buf,
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->en_gpios[i]))
+ return dev_err_probe(dev, PTR_ERR(st->en_gpios[i]),
+ "failed to get EN%d GPIO\n", i);
+
+ en_always_on[i] = device_property_read_bool(dev, always_on_buf);
+ if (st->en_gpios[i] && en_always_on[i])
+ return dev_err_probe(dev, -EINVAL,
+ "cannot have adi,en%d-always-on and en%d-gpios\n", i, i);
+
+ en_may_be_off[i] = !en_always_on[i];
+ en_may_be_on[i] = en_always_on[i] || st->en_gpios[i];
+ en_always_off[i] = !en_always_on[i] && !st->en_gpios[i];
+ }
+
+ /*
+ * Power down is mode 0bXX00, but not all devices have a valid
+ * power down state.
+ */
+ st->can_power_down = en_may_be_off[1] && en_may_be_off[0] &&
+ st->info->has_power_down_state;
+ /*
+ * The REFIN pin can take a 1.2V (AD762x) or 2.048V (AD796x)
+ * external reference when the mode is 0bXX01.
+ */
+ st->can_refin = en_may_be_off[1] && en_may_be_on[0];
+ /* 4.096V can be applied to REF when the EN mode is 0bXX10. */
+ st->can_ref_4v096 = en_may_be_on[1] && en_may_be_off[0];
+
+ /* Avoid AD796x-specific setup if the part is an AD762x */
+ if (num_gpios == 2)
+ return 0;
+
+ /* mode 0b1100 (AD796x) is invalid */
+ if (en_always_on[3] && en_always_on[2] &&
+ en_always_off[1] && en_always_off[0])
+ return dev_err_probe(dev, -EINVAL,
+ "EN GPIOs set to invalid mode 0b1100\n");
+ /*
+ * 5V can be applied to the AD796x REF pin when the EN mode is
+ * the same (0bX001 or 0bX101) as for can_refin, and REFIN is
+ * 0V.
+ */
+ st->can_ref_5v = st->can_refin;
+ /*
+ * Bandwidth (AD796x) is controlled solely by EN2. If it's
+ * specified and not hard-wired, then we can configure it to
+ * change the bandwidth between 28MHz and 9MHz.
+ */
+ st->can_narrow_bandwidth = en_may_be_on[2];
+ /* Wide bandwidth mode is possible if EN2 can be 0. */
+ st->can_wide_bandwidth = en_may_be_off[2];
+ /* Snooze mode (AD796x) is 0bXX11 when REFIN = 0V. */
+ st->can_snooze = en_may_be_on[1] && en_may_be_on[0];
+ /* Test pattern mode (AD796x) is 0b0100. */
+ st->can_test_pattern = en_may_be_off[3] && en_may_be_on[2] &&
+ en_may_be_off[1] && en_may_be_off[0];
+
+ return 0;
+}
+
+/* Set EN1 and EN0 based on reference voltage source */
+static void ad7625_set_en_gpios_for_vref(struct ad7625_state *st,
+ bool have_refin, int ref_mv)
+{
+ if (have_refin || ref_mv == 5000) {
+ gpiod_set_value_cansleep(st->en_gpios[1], 0);
+ gpiod_set_value_cansleep(st->en_gpios[0], 1);
+ } else if (ref_mv == 4096) {
+ gpiod_set_value_cansleep(st->en_gpios[1], 1);
+ gpiod_set_value_cansleep(st->en_gpios[0], 0);
+ } else {
+ /*
+ * Unreachable by AD796x, since the driver will error if
+ * neither REF nor REFIN is provided
+ */
+ gpiod_set_value_cansleep(st->en_gpios[1], 1);
+ gpiod_set_value_cansleep(st->en_gpios[0], 1);
+ }
+}
+
+static int ad7960_set_mode(struct ad7625_state *st, enum ad7960_mode mode,
+ bool have_refin, int ref_mv)
+{
+ switch (mode) {
+ case AD7960_MODE_POWER_DOWN:
+ if (!st->can_power_down)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[2], 0);
+ gpiod_set_value_cansleep(st->en_gpios[1], 0);
+ gpiod_set_value_cansleep(st->en_gpios[0], 0);
+
+ return 0;
+
+ case AD7960_MODE_SNOOZE:
+ if (!st->can_snooze)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[1], 1);
+ gpiod_set_value_cansleep(st->en_gpios[0], 1);
+
+ return 0;
+
+ case AD7960_MODE_NARROW_BANDWIDTH:
+ if (!st->can_narrow_bandwidth)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[2], 1);
+ ad7625_set_en_gpios_for_vref(st, have_refin, ref_mv);
+
+ return 0;
+
+ case AD7960_MODE_WIDE_BANDWIDTH:
+ if (!st->can_wide_bandwidth)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[2], 0);
+ ad7625_set_en_gpios_for_vref(st, have_refin, ref_mv);
+
+ return 0;
+
+ case AD7960_MODE_TEST_PATTERN:
+ if (!st->can_test_pattern)
+ return -EINVAL;
+
+ gpiod_set_value_cansleep(st->en_gpios[3], 0);
+ gpiod_set_value_cansleep(st->en_gpios[2], 1);
+ gpiod_set_value_cansleep(st->en_gpios[1], 0);
+ gpiod_set_value_cansleep(st->en_gpios[0], 0);
+
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad7625_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = pwm_set_waveform_might_sleep(st->cnv_pwm, &st->cnv_wf, false);
+ if (ret)
+ return ret;
+
+ ret = pwm_set_waveform_might_sleep(st->clk_gate_pwm,
+ &st->clk_gate_wf, false);
+ if (ret) {
+ /* Disable cnv PWM if clk_gate setup failed */
+ pwm_disable(st->cnv_pwm);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ad7625_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad7625_state *st = iio_priv(indio_dev);
+
+ pwm_disable(st->clk_gate_pwm);
+ pwm_disable(st->cnv_pwm);
+
+ return 0;
+}
+
+static const struct iio_info ad7625_info = {
+ .read_raw = ad7625_read_raw,
+ .write_raw = ad7625_write_raw,
+};
+
+static const struct iio_buffer_setup_ops ad7625_buffer_setup_ops = {
+ .preenable = &ad7625_buffer_preenable,
+ .postdisable = &ad7625_buffer_postdisable,
+};
+
+static int devm_ad7625_pwm_get(struct device *dev,
+ struct ad7625_state *st)
+{
+ struct clk *ref_clk;
+ u32 ref_clk_rate_hz;
+
+ st->cnv_pwm = devm_pwm_get(dev, "cnv");
+ if (IS_ERR(st->cnv_pwm))
+ return dev_err_probe(dev, PTR_ERR(st->cnv_pwm),
+ "failed to get cnv pwm\n");
+
+ /* Preemptively disable the PWM in case it was enabled at boot */
+ pwm_disable(st->cnv_pwm);
+
+ st->clk_gate_pwm = devm_pwm_get(dev, "clk_gate");
+ if (IS_ERR(st->clk_gate_pwm))
+ return dev_err_probe(dev, PTR_ERR(st->clk_gate_pwm),
+ "failed to get clk_gate pwm\n");
+
+ /* Preemptively disable the PWM in case it was enabled at boot */
+ pwm_disable(st->clk_gate_pwm);
+
+ ref_clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(ref_clk))
+ return dev_err_probe(dev, PTR_ERR(ref_clk),
+ "failed to get ref_clk");
+
+ ref_clk_rate_hz = clk_get_rate(ref_clk);
+ if (!ref_clk_rate_hz)
+ return dev_err_probe(dev, -EINVAL,
+ "failed to get ref_clk rate");
+
+ st->ref_clk_rate_hz = ref_clk_rate_hz;
+
+ return 0;
+}
+
+/*
+ * There are three required input voltages for each device, plus two
+ * conditionally-optional (depending on part) REF and REFIN voltages
+ * where their validity depends upon the EN pin configuration.
+ *
+ * Power-up info for the device says to bring up vio, then vdd2, then
+ * vdd1, so list them in that order in the regulator_names array.
+ *
+ * The reference voltage source is determined like so:
+ * - internal reference: neither REF or REFIN is connected (invalid for
+ * AD796x)
+ * - internal buffer, external reference: REF not connected, REFIN
+ * connected
+ * - external reference: REF connected, REFIN not connected
+ */
+static int devm_ad7625_regulator_setup(struct device *dev,
+ struct ad7625_state *st)
+{
+ static const char * const regulator_names[] = { "vio", "vdd2", "vdd1" };
+ int ret, ref_mv;
+
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(regulator_names),
+ regulator_names);
+ if (ret)
+ return ret;
+
+ ret = devm_regulator_get_enable_read_voltage(dev, "ref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "failed to get REF voltage\n");
+
+ ref_mv = ret == -ENODEV ? 0 : ret / 1000;
+
+ ret = devm_regulator_get_enable_optional(dev, "refin");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "failed to get REFIN voltage\n");
+
+ st->have_refin = ret != -ENODEV;
+
+ if (st->have_refin && !st->can_refin)
+ return dev_err_probe(dev, -EINVAL,
+ "REFIN provided in unsupported mode\n");
+
+ if (!st->info->has_internal_vref && !st->have_refin && !ref_mv)
+ return dev_err_probe(dev, -EINVAL,
+ "Need either REFIN or REF");
+
+ if (st->have_refin && ref_mv)
+ return dev_err_probe(dev, -EINVAL,
+ "cannot have both REFIN and REF supplies\n");
+
+ if (ref_mv == 4096 && !st->can_ref_4v096)
+ return dev_err_probe(dev, -EINVAL,
+ "REF is 4.096V in unsupported mode\n");
+
+ if (ref_mv == 5000 && !st->can_ref_5v)
+ return dev_err_probe(dev, -EINVAL,
+ "REF is 5V in unsupported mode\n");
+
+ st->vref_mv = ref_mv ?: AD7625_INTERNAL_REF_MV;
+
+ return 0;
+}
+
+static int ad7625_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct iio_dev *indio_dev;
+ struct ad7625_state *st;
+ int ret;
+ u32 default_sample_freq;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ st->info = device_get_match_data(dev);
+ if (!st->info)
+ return dev_err_probe(dev, -EINVAL, "no chip info\n");
+
+ if (device_property_read_bool(dev, "adi,no-dco"))
+ return dev_err_probe(dev, -EINVAL,
+ "self-clocked mode not supported\n");
+
+ if (st->info->has_bandwidth_control)
+ ret = ad7625_parse_mode(dev, st, 4);
+ else
+ ret = ad7625_parse_mode(dev, st, 2);
+
+ if (ret)
+ return ret;
+
+ ret = devm_ad7625_regulator_setup(dev, st);
+ if (ret)
+ return ret;
+
+ /* Set the device mode based on detected EN configuration. */
+ if (!st->info->has_bandwidth_control) {
+ ad7625_set_en_gpios_for_vref(st, st->have_refin, st->vref_mv);
+ } else {
+ /*
+ * If neither sampling mode is available, then report an error,
+ * since the other modes are not useful defaults.
+ */
+ if (st->can_wide_bandwidth) {
+ ret = ad7960_set_mode(st, AD7960_MODE_WIDE_BANDWIDTH,
+ st->have_refin, st->vref_mv);
+ } else if (st->can_narrow_bandwidth) {
+ ret = ad7960_set_mode(st, AD7960_MODE_NARROW_BANDWIDTH,
+ st->have_refin, st->vref_mv);
+ } else {
+ return dev_err_probe(dev, -EINVAL,
+ "couldn't set device to wide or narrow bandwidth modes\n");
+ }
+
+ if (ret)
+ return dev_err_probe(dev, -EINVAL,
+ "failed to set EN pins\n");
+ }
+
+ ret = devm_ad7625_pwm_get(dev, st);
+ if (ret)
+ return ret;
+
+ indio_dev->channels = &st->info->chan_spec;
+ indio_dev->num_channels = 1;
+ indio_dev->name = st->info->name;
+ indio_dev->info = &ad7625_info;
+ indio_dev->setup_ops = &ad7625_buffer_setup_ops;
+
+ st->back = devm_iio_backend_get(dev, NULL);
+ if (IS_ERR(st->back))
+ return dev_err_probe(dev, PTR_ERR(st->back),
+ "failed to get IIO backend");
+
+ ret = devm_iio_backend_request_buffer(dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = devm_iio_backend_enable(dev, st->back);
+ if (ret)
+ return ret;
+
+ /*
+ * Set the initial sampling frequency to the maximum, unless the
+ * AD796x device is limited to narrow bandwidth by EN2 == 1, in
+ * which case the sampling frequency should be limited to 2MSPS
+ */
+ default_sample_freq = st->info->max_sample_freq_hz;
+ if (st->info->has_bandwidth_control && !st->can_wide_bandwidth)
+ default_sample_freq = AD7960_MAX_NBW_FREQ;
+
+ ret = ad7625_set_sampling_freq(st, default_sample_freq);
+ if (ret)
+ dev_err_probe(dev, ret,
+ "failed to set valid sampling frequency\n");
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id ad7625_of_match[] = {
+ { .compatible = "adi,ad7625", .data = &ad7625_chip_info },
+ { .compatible = "adi,ad7626", .data = &ad7626_chip_info },
+ { .compatible = "adi,ad7960", .data = &ad7960_chip_info },
+ { .compatible = "adi,ad7961", .data = &ad7961_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad7625_of_match);
+
+static const struct platform_device_id ad7625_device_ids[] = {
+ { .name = "ad7625", .driver_data = (kernel_ulong_t)&ad7625_chip_info },
+ { .name = "ad7626", .driver_data = (kernel_ulong_t)&ad7626_chip_info },
+ { .name = "ad7960", .driver_data = (kernel_ulong_t)&ad7960_chip_info },
+ { .name = "ad7961", .driver_data = (kernel_ulong_t)&ad7961_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, ad7625_device_ids);
+
+static struct platform_driver ad7625_driver = {
+ .probe = ad7625_probe,
+ .driver = {
+ .name = "ad7625",
+ .of_match_table = ad7625_of_match,
+ },
+ .id_table = ad7625_device_ids,
+};
+module_platform_driver(ad7625_driver);
+
+MODULE_AUTHOR("Trevor Gamblin <tgamblin@baylibre.com>");
+MODULE_DESCRIPTION("Analog Devices AD7625 ADC");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_IMPORT_NS("IIO_BACKEND");
diff --git a/drivers/iio/adc/ad7779.c b/drivers/iio/adc/ad7779.c
new file mode 100644
index 000000000000..2537dab69a35
--- /dev/null
+++ b/drivers/iio/adc/ad7779.c
@@ -0,0 +1,914 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * AD7770, AD7771, AD7779 ADC
+ *
+ * Copyright 2023-2024 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/bitmap.h>
+#include <linux/clk.h>
+#include <linux/crc8.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio/consumer.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/math.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/unaligned.h>
+#include <linux/units.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+#define AD7779_SPI_READ_CMD BIT(7)
+
+#define AD7779_DISABLE_SD BIT(7)
+
+#define AD7779_REG_CH_DISABLE 0x08
+#define AD7779_REG_CH_SYNC_OFFSET(ch) (0x09 + (ch))
+#define AD7779_REG_CH_CONFIG(ch) (0x00 + (ch))
+#define AD7779_REG_GENERAL_USER_CONFIG_1 0x11
+#define AD7779_REG_GENERAL_USER_CONFIG_2 0x12
+#define AD7779_REG_GENERAL_USER_CONFIG_3 0x13
+#define AD7779_REG_DOUT_FORMAT 0x14
+#define AD7779_REG_ADC_MUX_CONFIG 0x15
+#define AD7779_REG_GPIO_CONFIG 0x17
+#define AD7779_REG_BUFFER_CONFIG_1 0x19
+#define AD7779_REG_GLOBAL_MUX_CONFIG 0x16
+#define AD7779_REG_BUFFER_CONFIG_2 0x1A
+#define AD7779_REG_GPIO_DATA 0x18
+#define AD7779_REG_CH_OFFSET_UPPER_BYTE(ch) (0x1C + (ch) * 6)
+#define AD7779_REG_CH_OFFSET_LOWER_BYTE(ch) (0x1E + (ch) * 6)
+#define AD7779_REG_CH_GAIN_UPPER_BYTE(ch) (0x1F + (ch) * 6)
+#define AD7779_REG_CH_OFFSET_MID_BYTE(ch) (0x1D + (ch) * 6)
+#define AD7779_REG_CH_GAIN_MID_BYTE(ch) (0x20 + (ch) * 6)
+#define AD7779_REG_CH_ERR_REG(ch) (0x4C + (ch))
+#define AD7779_REG_CH0_1_SAT_ERR 0x54
+#define AD7779_REG_CH_GAIN_LOWER_BYTE(ch) (0x21 + (ch) * 6)
+#define AD7779_REG_CH2_3_SAT_ERR 0x55
+#define AD7779_REG_CH4_5_SAT_ERR 0x56
+#define AD7779_REG_CH6_7_SAT_ERR 0x57
+#define AD7779_REG_CHX_ERR_REG_EN 0x58
+#define AD7779_REG_GEN_ERR_REG_1 0x59
+#define AD7779_REG_GEN_ERR_REG_1_EN 0x5A
+#define AD7779_REG_GEN_ERR_REG_2 0x5B
+#define AD7779_REG_GEN_ERR_REG_2_EN 0x5C
+#define AD7779_REG_STATUS_REG_1 0x5D
+#define AD7779_REG_STATUS_REG_2 0x5E
+#define AD7779_REG_STATUS_REG_3 0x5F
+#define AD7779_REG_SRC_N_MSB 0x60
+#define AD7779_REG_SRC_N_LSB 0x61
+#define AD7779_REG_SRC_IF_MSB 0x62
+#define AD7779_REG_SRC_IF_LSB 0x63
+#define AD7779_REG_SRC_UPDATE 0x64
+
+#define AD7779_FILTER_MSK BIT(6)
+#define AD7779_MOD_POWERMODE_MSK BIT(6)
+#define AD7779_MOD_PDB_REFOUT_MSK BIT(4)
+#define AD7779_MOD_SPI_EN_MSK BIT(4)
+#define AD7779_USRMOD_INIT_MSK GENMASK(6, 4)
+
+/* AD7779_REG_DOUT_FORMAT */
+#define AD7779_DOUT_FORMAT_MSK GENMASK(7, 6)
+#define AD7779_DOUT_HEADER_FORMAT BIT(5)
+#define AD7779_DCLK_CLK_DIV_MSK GENMASK(3, 1)
+
+#define AD7779_REFMUX_CTRL_MSK GENMASK(7, 6)
+#define AD7779_SPI_CRC_EN_MSK BIT(0)
+
+#define AD7779_MAXCLK_LOWPOWER (4096 * HZ_PER_KHZ)
+#define AD7779_NUM_CHANNELS 8
+#define AD7779_RESET_BUF_SIZE 8
+#define AD7779_CHAN_DATA_SIZE 4
+
+#define AD7779_LOWPOWER_DIV 512
+#define AD7779_HIGHPOWER_DIV 2048
+
+#define AD7779_SINC3_MAXFREQ (16 * HZ_PER_KHZ)
+#define AD7779_SINC5_MAXFREQ (128 * HZ_PER_KHZ)
+
+#define AD7779_DEFAULT_SAMPLING_FREQ (8 * HZ_PER_KHZ)
+#define AD7779_DEFAULT_SAMPLING_2LINE (4 * HZ_PER_KHZ)
+#define AD7779_DEFAULT_SAMPLING_1LINE (2 * HZ_PER_KHZ)
+
+#define AD7779_SPIMODE_MAX_SAMP_FREQ (16 * HZ_PER_KHZ)
+
+#define GAIN_REL 0x555555
+#define AD7779_FREQ_MSB_MSK GENMASK(15, 8)
+#define AD7779_FREQ_LSB_MSK GENMASK(7, 0)
+#define AD7779_UPPER GENMASK(23, 16)
+#define AD7779_MID GENMASK(15, 8)
+#define AD7779_LOWER GENMASK(7, 0)
+
+#define AD7779_REG_MSK GENMASK(6, 0)
+
+#define AD7779_CRC8_POLY 0x07
+DECLARE_CRC8_TABLE(ad7779_crc8_table);
+
+enum ad7779_filter {
+ AD7779_SINC3,
+ AD7779_SINC5,
+};
+
+enum ad7779_variant {
+ ad7770,
+ ad7771,
+ ad7779,
+};
+
+enum ad7779_power_mode {
+ AD7779_LOW_POWER,
+ AD7779_HIGH_POWER,
+};
+
+struct ad7779_chip_info {
+ const char *name;
+ struct iio_chan_spec const *channels;
+};
+
+struct ad7779_state {
+ struct spi_device *spi;
+ const struct ad7779_chip_info *chip_info;
+ struct clk *mclk;
+ struct iio_trigger *trig;
+ struct completion completion;
+ unsigned int sampling_freq;
+ enum ad7779_filter filter_enabled;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ struct {
+ u32 chans[8];
+ aligned_s64 timestamp;
+ } data __aligned(IIO_DMA_MINALIGN);
+ u32 spidata_tx[8];
+ u8 reg_rx_buf[3];
+ u8 reg_tx_buf[3];
+ u8 reset_buf[8];
+};
+
+static const char * const ad7779_filter_type[] = {
+ [AD7779_SINC3] = "sinc3",
+ [AD7779_SINC5] = "sinc5",
+};
+
+static const char * const ad7779_power_supplies[] = {
+ "avdd1", "avdd2", "avdd4",
+};
+
+static int ad7779_spi_read(struct ad7779_state *st, u8 reg, u8 *rbuf)
+{
+ int ret;
+ u8 crc_buf[2];
+ u8 exp_crc;
+ struct spi_transfer t = {
+ .tx_buf = st->reg_tx_buf,
+ .rx_buf = st->reg_rx_buf,
+ };
+
+ st->reg_tx_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg);
+ st->reg_tx_buf[1] = 0;
+
+ if (reg == AD7779_REG_GEN_ERR_REG_1_EN) {
+ t.len = 2;
+ } else {
+ t.len = 3;
+ st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf,
+ t.len - 1, 0);
+ }
+
+ ret = spi_sync_transfer(st->spi, &t, 1);
+ if (ret)
+ return ret;
+
+ crc_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg);
+ crc_buf[1] = st->reg_rx_buf[1];
+ exp_crc = crc8(ad7779_crc8_table, crc_buf, ARRAY_SIZE(crc_buf), 0);
+ if (reg != AD7779_REG_GEN_ERR_REG_1_EN && exp_crc != st->reg_rx_buf[2]) {
+ dev_err(&st->spi->dev, "Bad CRC %x, expected %x",
+ st->reg_rx_buf[2], exp_crc);
+ return -EINVAL;
+ }
+ *rbuf = st->reg_rx_buf[1];
+
+ return 0;
+}
+
+static int ad7779_spi_write(struct ad7779_state *st, u8 reg, u8 val)
+{
+ u8 length = 3;
+
+ st->reg_tx_buf[0] = FIELD_GET(AD7779_REG_MSK, reg);
+ st->reg_tx_buf[1] = val;
+ if (reg == AD7779_REG_GEN_ERR_REG_1_EN)
+ length = 2;
+ else
+ st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf,
+ length - 1, 0);
+
+ return spi_write(st->spi, st->reg_tx_buf, length);
+}
+
+static int ad7779_spi_write_mask(struct ad7779_state *st, u8 reg, u8 mask,
+ u8 val)
+{
+ int ret;
+ u8 regval, data;
+
+ ret = ad7779_spi_read(st, reg, &data);
+ if (ret)
+ return ret;
+
+ regval = (data & ~mask) | (val & mask);
+
+ if (regval == data)
+ return 0;
+
+ return ad7779_spi_write(st, reg, regval);
+}
+
+static int ad7779_reg_access(struct iio_dev *indio_dev,
+ unsigned int reg,
+ unsigned int writeval,
+ unsigned int *readval)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ u8 rval;
+ int ret;
+
+ if (readval) {
+ ret = ad7779_spi_read(st, reg, &rval);
+ *readval = rval;
+ return ret;
+ }
+
+ return ad7779_spi_write(st, reg, writeval);
+}
+
+static int ad7779_set_sampling_frequency(struct ad7779_state *st,
+ unsigned int sampling_freq)
+{
+ int ret;
+ unsigned int dec;
+ unsigned int frac;
+ unsigned int div;
+ unsigned int decimal;
+ unsigned int freq_khz;
+
+ if (st->filter_enabled == AD7779_SINC3 &&
+ sampling_freq > AD7779_SINC3_MAXFREQ)
+ return -EINVAL;
+
+ if (st->filter_enabled == AD7779_SINC5 &&
+ sampling_freq > AD7779_SINC5_MAXFREQ)
+ return -EINVAL;
+
+ if (sampling_freq > AD7779_SPIMODE_MAX_SAMP_FREQ)
+ return -EINVAL;
+
+ div = AD7779_HIGHPOWER_DIV;
+
+ freq_khz = sampling_freq / HZ_PER_KHZ;
+ dec = div / freq_khz;
+ frac = div % freq_khz;
+
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
+ FIELD_GET(AD7779_FREQ_MSB_MSK, dec));
+ if (ret)
+ return ret;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
+ FIELD_GET(AD7779_FREQ_LSB_MSK, dec));
+ if (ret)
+ return ret;
+
+ if (frac) {
+ /*
+ * In order to obtain the first three decimals of the decimation
+ * the initial number is multiplied with 10^3 prior to the
+ * division, then the original division result is subtracted and
+ * the number is divided by 10^3.
+ */
+ decimal = ((mult_frac(div, KILO, freq_khz) - dec * KILO) << 16)
+ / KILO;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
+ FIELD_GET(AD7779_FREQ_MSB_MSK, decimal));
+ if (ret)
+ return ret;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
+ FIELD_GET(AD7779_FREQ_LSB_MSK, decimal));
+ if (ret)
+ return ret;
+ } else {
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
+ FIELD_GET(AD7779_FREQ_MSB_MSK, 0x0));
+ if (ret)
+ return ret;
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
+ FIELD_GET(AD7779_FREQ_LSB_MSK, 0x0));
+ if (ret)
+ return ret;
+ }
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, BIT(0));
+ if (ret)
+ return ret;
+
+ /* SRC update settling time */
+ fsleep(15);
+
+ ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, 0x0);
+ if (ret)
+ return ret;
+
+ /* SRC update settling time */
+ fsleep(15);
+
+ st->sampling_freq = sampling_freq;
+
+ return 0;
+}
+
+static int ad7779_get_filter(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ u8 temp;
+ int ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_GENERAL_USER_CONFIG_2, &temp);
+ if (ret)
+ return ret;
+
+ return FIELD_GET(AD7779_FILTER_MSK, temp);
+}
+
+static int ad7779_set_filter(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ unsigned int mode)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = ad7779_spi_write_mask(st,
+ AD7779_REG_GENERAL_USER_CONFIG_2,
+ AD7779_FILTER_MSK,
+ FIELD_PREP(AD7779_FILTER_MSK, mode));
+ if (ret)
+ return ret;
+
+ ret = ad7779_set_sampling_frequency(st, st->sampling_freq);
+ if (ret)
+ return ret;
+
+ st->filter_enabled = mode;
+
+ return 0;
+}
+
+static int ad7779_get_calibscale(struct ad7779_state *st, int channel)
+{
+ int ret;
+ u8 calibscale[3];
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel),
+ &calibscale[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_MID_BYTE(channel),
+ &calibscale[1]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel),
+ &calibscale[2]);
+ if (ret)
+ return ret;
+
+ return get_unaligned_be24(calibscale);
+}
+
+static int ad7779_set_calibscale(struct ad7779_state *st, int channel, int val)
+{
+ int ret;
+ unsigned int gain;
+ u8 gain_bytes[3];
+
+ /*
+ * The gain value is relative to 0x555555, which represents a gain of 1
+ */
+ gain = DIV_ROUND_CLOSEST_ULL((u64)val * 5592405LL, MEGA);
+ put_unaligned_be24(gain, gain_bytes);
+ ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel),
+ gain_bytes[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_MID_BYTE(channel),
+ gain_bytes[1]);
+ if (ret)
+ return ret;
+
+ return ad7779_spi_write(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel),
+ gain_bytes[2]);
+}
+
+static int ad7779_get_calibbias(struct ad7779_state *st, int channel)
+{
+ int ret;
+ u8 calibbias[3];
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel),
+ &calibbias[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel),
+ &calibbias[1]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel),
+ &calibbias[2]);
+ if (ret)
+ return ret;
+
+ return get_unaligned_be24(calibbias);
+}
+
+static int ad7779_set_calibbias(struct ad7779_state *st, int channel, int val)
+{
+ int ret;
+ u8 calibbias[3];
+
+ put_unaligned_be24(val, calibbias);
+ ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel),
+ calibbias[0]);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel),
+ calibbias[1]);
+ if (ret)
+ return ret;
+
+ return ad7779_spi_write(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel),
+ calibbias[2]);
+}
+
+static int ad7779_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ switch (mask) {
+ case IIO_CHAN_INFO_CALIBSCALE:
+ ret = ad7779_get_calibscale(st, chan->channel);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ *val2 = GAIN_REL;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_CHAN_INFO_CALIBBIAS:
+ ret = ad7779_get_calibbias(st, chan->channel);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = st->sampling_freq;
+ if (*val < 0)
+ return -EINVAL;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ }
+ unreachable();
+}
+
+static int ad7779_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2,
+ long mask)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ switch (mask) {
+ case IIO_CHAN_INFO_CALIBSCALE:
+ return ad7779_set_calibscale(st, chan->channel, val2);
+ case IIO_CHAN_INFO_CALIBBIAS:
+ return ad7779_set_calibbias(st, chan->channel, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return ad7779_set_sampling_frequency(st, val);
+ default:
+ return -EINVAL;
+ }
+ }
+ unreachable();
+}
+
+static int ad7779_buffer_preenable(struct iio_dev *indio_dev)
+{
+ int ret;
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ ret = ad7779_spi_write_mask(st,
+ AD7779_REG_GENERAL_USER_CONFIG_3,
+ AD7779_MOD_SPI_EN_MSK,
+ FIELD_PREP(AD7779_MOD_SPI_EN_MSK, 1));
+ if (ret)
+ return ret;
+
+ /*
+ * DRDY output cannot be disabled at device level therefore we mask
+ * the irq at host end.
+ */
+ enable_irq(st->spi->irq);
+
+ return 0;
+}
+
+static int ad7779_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ disable_irq(st->spi->irq);
+
+ return ad7779_spi_write(st, AD7779_REG_GENERAL_USER_CONFIG_3,
+ AD7779_DISABLE_SD);
+}
+
+static irqreturn_t ad7779_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+ struct spi_transfer t = {
+ .rx_buf = st->data.chans,
+ .tx_buf = st->spidata_tx,
+ .len = AD7779_NUM_CHANNELS * AD7779_CHAN_DATA_SIZE,
+ };
+
+ st->spidata_tx[0] = AD7779_SPI_READ_CMD;
+ ret = spi_sync_transfer(st->spi, &t, 1);
+ if (ret) {
+ dev_err(&st->spi->dev, "SPI transfer error in IRQ handler");
+ goto exit_handler;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &st->data, pf->timestamp);
+
+exit_handler:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int ad7779_reset(struct iio_dev *indio_dev, struct gpio_desc *reset_gpio)
+{
+ struct ad7779_state *st = iio_priv(indio_dev);
+ int ret;
+ struct spi_transfer t = {
+ .tx_buf = st->reset_buf,
+ .len = 8,
+ };
+
+ if (reset_gpio) {
+ gpiod_set_value(reset_gpio, 1);
+ /* Delay for reset to occur is 225 microseconds */
+ fsleep(230);
+ ret = 0;
+ } else {
+ memset(st->reset_buf, 0xff, sizeof(st->reset_buf));
+ ret = spi_sync_transfer(st->spi, &t, 1);
+ if (ret)
+ return ret;
+ }
+
+ /* Delay for reset to occur is 225 microseconds */
+ fsleep(230);
+
+ return ret;
+}
+
+static const struct iio_info ad7779_info = {
+ .read_raw = ad7779_read_raw,
+ .write_raw = ad7779_write_raw,
+ .debugfs_reg_access = &ad7779_reg_access,
+};
+
+static const struct iio_enum ad7779_filter_enum = {
+ .items = ad7779_filter_type,
+ .num_items = ARRAY_SIZE(ad7779_filter_type),
+ .get = ad7779_get_filter,
+ .set = ad7779_set_filter,
+};
+
+static const struct iio_chan_spec_ext_info ad7779_ext_filter[] = {
+ IIO_ENUM("filter_type", IIO_SHARED_BY_ALL, &ad7779_filter_enum),
+ IIO_ENUM_AVAILABLE("filter_type", IIO_SHARED_BY_ALL,
+ &ad7779_filter_enum),
+ { }
+};
+
+#define AD777x_CHAN_S(index, _ext_info) \
+ { \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE) | \
+ BIT(IIO_CHAN_INFO_CALIBBIAS), \
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
+ .address = (index), \
+ .indexed = 1, \
+ .channel = (index), \
+ .scan_index = (index), \
+ .ext_info = (_ext_info), \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 24, \
+ .storagebits = 32, \
+ .endianness = IIO_BE, \
+ }, \
+ }
+
+#define AD777x_CHAN_NO_FILTER_S(index) \
+ AD777x_CHAN_S(index, NULL)
+
+#define AD777x_CHAN_FILTER_S(index) \
+ AD777x_CHAN_S(index, ad7779_ext_filter)
+static const struct iio_chan_spec ad7779_channels[] = {
+ AD777x_CHAN_NO_FILTER_S(0),
+ AD777x_CHAN_NO_FILTER_S(1),
+ AD777x_CHAN_NO_FILTER_S(2),
+ AD777x_CHAN_NO_FILTER_S(3),
+ AD777x_CHAN_NO_FILTER_S(4),
+ AD777x_CHAN_NO_FILTER_S(5),
+ AD777x_CHAN_NO_FILTER_S(6),
+ AD777x_CHAN_NO_FILTER_S(7),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+static const struct iio_chan_spec ad7779_channels_filter[] = {
+ AD777x_CHAN_FILTER_S(0),
+ AD777x_CHAN_FILTER_S(1),
+ AD777x_CHAN_FILTER_S(2),
+ AD777x_CHAN_FILTER_S(3),
+ AD777x_CHAN_FILTER_S(4),
+ AD777x_CHAN_FILTER_S(5),
+ AD777x_CHAN_FILTER_S(6),
+ AD777x_CHAN_FILTER_S(7),
+ IIO_CHAN_SOFT_TIMESTAMP(8),
+};
+
+static const struct iio_buffer_setup_ops ad7779_buffer_setup_ops = {
+ .preenable = ad7779_buffer_preenable,
+ .postdisable = ad7779_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops ad7779_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
+};
+
+static int ad7779_conf(struct ad7779_state *st, struct gpio_desc *start_gpio)
+{
+ int ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_GEN_ERR_REG_1_EN,
+ AD7779_SPI_CRC_EN_MSK,
+ FIELD_PREP(AD7779_SPI_CRC_EN_MSK, 1));
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
+ AD7779_USRMOD_INIT_MSK,
+ FIELD_PREP(AD7779_USRMOD_INIT_MSK, 5));
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT,
+ AD7779_DCLK_CLK_DIV_MSK,
+ FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 1));
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_ADC_MUX_CONFIG,
+ AD7779_REFMUX_CTRL_MSK,
+ FIELD_PREP(AD7779_REFMUX_CTRL_MSK, 1));
+ if (ret)
+ return ret;
+
+ ret = ad7779_set_sampling_frequency(st, AD7779_DEFAULT_SAMPLING_FREQ);
+ if (ret)
+ return ret;
+
+ gpiod_set_value(start_gpio, 0);
+ /* Start setup time */
+ fsleep(15);
+ gpiod_set_value(start_gpio, 1);
+ /* Start setup time */
+ fsleep(15);
+ gpiod_set_value(start_gpio, 0);
+ /* Start setup time */
+ fsleep(15);
+
+ return 0;
+}
+
+static int ad7779_probe(struct spi_device *spi)
+{
+ struct iio_dev *indio_dev;
+ struct ad7779_state *st;
+ struct gpio_desc *reset_gpio, *start_gpio;
+ struct device *dev = &spi->dev;
+ int ret = -EINVAL;
+
+ if (!spi->irq)
+ return dev_err_probe(dev, ret, "DRDY irq not present\n");
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+
+ ret = devm_regulator_bulk_get_enable(dev,
+ ARRAY_SIZE(ad7779_power_supplies),
+ ad7779_power_supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to get and enable supplies\n");
+
+ st->mclk = devm_clk_get_enabled(dev, "mclk");
+ if (IS_ERR(st->mclk))
+ return PTR_ERR(st->mclk);
+
+ reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset_gpio))
+ return PTR_ERR(reset_gpio);
+
+ start_gpio = devm_gpiod_get(dev, "start", GPIOD_OUT_HIGH);
+ if (IS_ERR(start_gpio))
+ return PTR_ERR(start_gpio);
+
+ crc8_populate_msb(ad7779_crc8_table, AD7779_CRC8_POLY);
+ st->spi = spi;
+
+ st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return -ENODEV;
+
+ ret = ad7779_reset(indio_dev, reset_gpio);
+ if (ret)
+ return ret;
+
+ ret = ad7779_conf(st, start_gpio);
+ if (ret)
+ return ret;
+
+ indio_dev->name = st->chip_info->name;
+ indio_dev->info = &ad7779_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = st->chip_info->channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad7779_channels);
+
+ st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!st->trig)
+ return -ENOMEM;
+
+ st->trig->ops = &ad7779_trigger_ops;
+
+ iio_trigger_set_drvdata(st->trig, st);
+
+ ret = devm_request_irq(dev, spi->irq, iio_trigger_generic_data_rdy_poll,
+ IRQF_ONESHOT | IRQF_NO_AUTOEN, indio_dev->name,
+ st->trig);
+ if (ret)
+ return dev_err_probe(dev, ret, "request IRQ %d failed\n",
+ st->spi->irq);
+
+ ret = devm_iio_trigger_register(dev, st->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(st->trig);
+
+ init_completion(&st->completion);
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ &iio_pollfunc_store_time,
+ &ad7779_trigger_handler,
+ &ad7779_buffer_setup_ops);
+ if (ret)
+ return ret;
+
+ ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT,
+ AD7779_DCLK_CLK_DIV_MSK,
+ FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 7));
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static int ad7779_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
+ AD7779_MOD_POWERMODE_MSK,
+ FIELD_PREP(AD7779_MOD_POWERMODE_MSK,
+ AD7779_LOW_POWER));
+}
+
+static int ad7779_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ad7779_state *st = iio_priv(indio_dev);
+
+ return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
+ AD7779_MOD_POWERMODE_MSK,
+ FIELD_PREP(AD7779_MOD_POWERMODE_MSK,
+ AD7779_HIGH_POWER));
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(ad7779_pm_ops, ad7779_suspend, ad7779_resume);
+
+static const struct ad7779_chip_info ad7770_chip_info = {
+ .name = "ad7770",
+ .channels = ad7779_channels,
+};
+
+static const struct ad7779_chip_info ad7771_chip_info = {
+ .name = "ad7771",
+ .channels = ad7779_channels_filter,
+};
+
+static const struct ad7779_chip_info ad7779_chip_info = {
+ .name = "ad7779",
+ .channels = ad7779_channels,
+};
+
+static const struct spi_device_id ad7779_id[] = {
+ {
+ .name = "ad7770",
+ .driver_data = (kernel_ulong_t)&ad7770_chip_info,
+ },
+ {
+ .name = "ad7771",
+ .driver_data = (kernel_ulong_t)&ad7771_chip_info,
+ },
+ {
+ .name = "ad7779",
+ .driver_data = (kernel_ulong_t)&ad7779_chip_info,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad7779_id);
+
+static const struct of_device_id ad7779_of_table[] = {
+ {
+ .compatible = "adi,ad7770",
+ .data = &ad7770_chip_info,
+ },
+ {
+ .compatible = "adi,ad7771",
+ .data = &ad7771_chip_info,
+ },
+ {
+ .compatible = "adi,ad7779",
+ .data = &ad7779_chip_info,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad7779_of_table);
+
+static struct spi_driver ad7779_driver = {
+ .driver = {
+ .name = "ad7779",
+ .pm = pm_sleep_ptr(&ad7779_pm_ops),
+ .of_match_table = ad7779_of_table,
+ },
+ .probe = ad7779_probe,
+ .id_table = ad7779_id,
+};
+module_spi_driver(ad7779_driver);
+
+MODULE_AUTHOR("Ramona Alexandra Nechita <ramona.nechita@analog.com>");
+MODULE_DESCRIPTION("Analog Devices AD7779 ADC");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/ad7780.c b/drivers/iio/adc/ad7780.c
index e9b0c577c9cc..24d2dcad8f4d 100644
--- a/drivers/iio/adc/ad7780.c
+++ b/drivers/iio/adc/ad7780.c
@@ -152,7 +152,7 @@ static int ad7780_write_raw(struct iio_dev *indio_dev,
switch (m) {
case IIO_CHAN_INFO_SCALE:
- if (val != 0)
+ if (val != 0 || val2 == 0)
return -EINVAL;
vref = st->int_vref_mv * 1000000LL;
@@ -375,4 +375,4 @@ module_spi_driver(ad7780_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7780 and similar ADCs");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA);
+MODULE_IMPORT_NS("IIO_AD_SIGMA_DELTA");
diff --git a/drivers/iio/adc/ad7791.c b/drivers/iio/adc/ad7791.c
index 86effe8501b4..e1bf13fe2cd7 100644
--- a/drivers/iio/adc/ad7791.c
+++ b/drivers/iio/adc/ad7791.c
@@ -371,7 +371,7 @@ static const struct iio_info ad7791_no_filter_info = {
};
static int ad7791_setup(struct ad7791_state *st,
- struct ad7791_platform_data *pdata)
+ const struct ad7791_platform_data *pdata)
{
/* Set to poweron-reset default values */
st->mode = AD7791_MODE_BUFFER;
@@ -401,7 +401,7 @@ static void ad7791_reg_disable(void *reg)
static int ad7791_probe(struct spi_device *spi)
{
- struct ad7791_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7791_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad7791_state *st;
int ret;
@@ -474,4 +474,4 @@ module_spi_driver(ad7791_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Analog Devices AD7787/AD7788/AD7789/AD7790/AD7791 ADC driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA);
+MODULE_IMPORT_NS("IIO_AD_SIGMA_DELTA");
diff --git a/drivers/iio/adc/ad7793.c b/drivers/iio/adc/ad7793.c
index abebd519cafa..d55c71566707 100644
--- a/drivers/iio/adc/ad7793.c
+++ b/drivers/iio/adc/ad7793.c
@@ -770,7 +770,7 @@ static const struct ad7793_chip_info ad7793_chip_info_tbl[] = {
static int ad7793_probe(struct spi_device *spi)
{
- const struct ad7793_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7793_platform_data *pdata = dev_get_platdata(&spi->dev);
struct ad7793_state *st;
struct iio_dev *indio_dev;
int ret, vref_mv = 0;
@@ -849,4 +849,4 @@ module_spi_driver(ad7793_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD7793 and similar ADCs");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA);
+MODULE_IMPORT_NS("IIO_AD_SIGMA_DELTA");
diff --git a/drivers/iio/adc/ad7887.c b/drivers/iio/adc/ad7887.c
index 6265ce7df703..69add1dc4b53 100644
--- a/drivers/iio/adc/ad7887.c
+++ b/drivers/iio/adc/ad7887.c
@@ -41,7 +41,7 @@ enum ad7887_channels {
};
/**
- * struct ad7887_chip_info - chip specifc information
+ * struct ad7887_chip_info - chip specific information
* @int_vref_mv: the internal reference voltage
* @channels: channels specification
* @num_channels: number of channels
@@ -234,7 +234,7 @@ static void ad7887_reg_disable(void *data)
static int ad7887_probe(struct spi_device *spi)
{
- struct ad7887_platform_data *pdata = spi->dev.platform_data;
+ const struct ad7887_platform_data *pdata = dev_get_platdata(&spi->dev);
struct ad7887_state *st;
struct iio_dev *indio_dev;
uint8_t mode;
diff --git a/drivers/iio/adc/ad7923.c b/drivers/iio/adc/ad7923.c
index 09680015a7ab..acc44cb34f82 100644
--- a/drivers/iio/adc/ad7923.c
+++ b/drivers/iio/adc/ad7923.c
@@ -48,7 +48,7 @@
struct ad7923_state {
struct spi_device *spi;
- struct spi_transfer ring_xfer[5];
+ struct spi_transfer ring_xfer[9];
struct spi_transfer scan_single_xfer[2];
struct spi_message ring_msg;
struct spi_message scan_single_msg;
@@ -64,7 +64,7 @@ struct ad7923_state {
* Length = 8 channels + 4 extra for 8 byte timestamp
*/
__be16 rx_buf[12] __aligned(IIO_DMA_MINALIGN);
- __be16 tx_buf[4];
+ __be16 tx_buf[8];
};
struct ad7923_chip_info {
diff --git a/drivers/iio/adc/ad7944.c b/drivers/iio/adc/ad7944.c
index 0f36138a7144..a5aea4e9f1a7 100644
--- a/drivers/iio/adc/ad7944.c
+++ b/drivers/iio/adc/ad7944.c
@@ -80,7 +80,7 @@ struct ad7944_adc {
};
/* quite time before CNV rising edge */
-#define T_QUIET_NS 20
+#define AD7944_T_QUIET_NS 20
static const struct ad7944_timing_spec ad7944_timing_spec = {
.conv_ns = 420,
@@ -150,7 +150,7 @@ static int ad7944_3wire_cs_mode_init_msg(struct device *dev, struct ad7944_adc *
* CS is tied to CNV and we need a low to high transition to start the
* conversion, so place CNV low for t_QUIET to prepare for this.
*/
- xfers[0].delay.value = T_QUIET_NS;
+ xfers[0].delay.value = AD7944_T_QUIET_NS;
xfers[0].delay.unit = SPI_DELAY_UNIT_NSECS;
/*
diff --git a/drivers/iio/adc/ad799x.c b/drivers/iio/adc/ad799x.c
index 0f107e3fc2c8..aa44b4e2542b 100644
--- a/drivers/iio/adc/ad799x.c
+++ b/drivers/iio/adc/ad799x.c
@@ -406,7 +406,7 @@ static int ad799x_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct ad799x_state *st = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/adc/ad9467.c b/drivers/iio/adc/ad9467.c
index 05fb7a75531f..d358958ab310 100644
--- a/drivers/iio/adc/ad9467.c
+++ b/drivers/iio/adc/ad9467.c
@@ -1280,4 +1280,4 @@ module_spi_driver(ad9467_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD9467 ADC driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_BACKEND);
+MODULE_IMPORT_NS("IIO_BACKEND");
diff --git a/drivers/iio/adc/ad_sigma_delta.c b/drivers/iio/adc/ad_sigma_delta.c
index ea4aabd3960a..3fd200b34161 100644
--- a/drivers/iio/adc/ad_sigma_delta.c
+++ b/drivers/iio/adc/ad_sigma_delta.c
@@ -43,7 +43,7 @@ void ad_sd_set_comm(struct ad_sigma_delta *sigma_delta, uint8_t comm)
* to select the channel */
sigma_delta->comm = comm & AD_SD_COMM_CHAN_MASK;
}
-EXPORT_SYMBOL_NS_GPL(ad_sd_set_comm, IIO_AD_SIGMA_DELTA);
+EXPORT_SYMBOL_NS_GPL(ad_sd_set_comm, "IIO_AD_SIGMA_DELTA");
/**
* ad_sd_write_reg() - Write a register
@@ -95,7 +95,7 @@ int ad_sd_write_reg(struct ad_sigma_delta *sigma_delta, unsigned int reg,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(ad_sd_write_reg, IIO_AD_SIGMA_DELTA);
+EXPORT_SYMBOL_NS_GPL(ad_sd_write_reg, "IIO_AD_SIGMA_DELTA");
static int ad_sd_read_reg_raw(struct ad_sigma_delta *sigma_delta,
unsigned int reg, unsigned int size, uint8_t *val)
@@ -172,7 +172,7 @@ int ad_sd_read_reg(struct ad_sigma_delta *sigma_delta,
out:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(ad_sd_read_reg, IIO_AD_SIGMA_DELTA);
+EXPORT_SYMBOL_NS_GPL(ad_sd_read_reg, "IIO_AD_SIGMA_DELTA");
/**
* ad_sd_reset() - Reset the serial interface
@@ -200,7 +200,7 @@ int ad_sd_reset(struct ad_sigma_delta *sigma_delta,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(ad_sd_reset, IIO_AD_SIGMA_DELTA);
+EXPORT_SYMBOL_NS_GPL(ad_sd_reset, "IIO_AD_SIGMA_DELTA");
int ad_sd_calibrate(struct ad_sigma_delta *sigma_delta,
unsigned int mode, unsigned int channel)
@@ -239,7 +239,7 @@ out:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(ad_sd_calibrate, IIO_AD_SIGMA_DELTA);
+EXPORT_SYMBOL_NS_GPL(ad_sd_calibrate, "IIO_AD_SIGMA_DELTA");
/**
* ad_sd_calibrate_all() - Performs channel calibration
@@ -263,7 +263,7 @@ int ad_sd_calibrate_all(struct ad_sigma_delta *sigma_delta,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ad_sd_calibrate_all, IIO_AD_SIGMA_DELTA);
+EXPORT_SYMBOL_NS_GPL(ad_sd_calibrate_all, "IIO_AD_SIGMA_DELTA");
/**
* ad_sigma_delta_single_conversion() - Performs a single data conversion
@@ -339,7 +339,7 @@ out:
return IIO_VAL_INT;
}
-EXPORT_SYMBOL_NS_GPL(ad_sigma_delta_single_conversion, IIO_AD_SIGMA_DELTA);
+EXPORT_SYMBOL_NS_GPL(ad_sigma_delta_single_conversion, "IIO_AD_SIGMA_DELTA");
static int ad_sd_buffer_postenable(struct iio_dev *indio_dev)
{
@@ -469,7 +469,7 @@ static irqreturn_t ad_sd_trigger_handler(int irq, void *p)
/*
* Data array after transfer will look like (if status is appended):
* data[] = { [0][sample][sample][sample][status] }
- * Keeping the first byte 0 shifts the status postion by 1 byte to the right.
+ * Keeping the first byte 0 shifts the status position by 1 byte to the right.
*/
status_pos = reg_size + 1;
@@ -564,7 +564,7 @@ int ad_sd_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ad_sd_validate_trigger, IIO_AD_SIGMA_DELTA);
+EXPORT_SYMBOL_NS_GPL(ad_sd_validate_trigger, "IIO_AD_SIGMA_DELTA");
static int devm_ad_sd_probe_trigger(struct device *dev, struct iio_dev *indio_dev)
{
@@ -638,7 +638,7 @@ int devm_ad_sd_setup_buffer_and_trigger(struct device *dev, struct iio_dev *indi
return devm_ad_sd_probe_trigger(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(devm_ad_sd_setup_buffer_and_trigger, IIO_AD_SIGMA_DELTA);
+EXPORT_SYMBOL_NS_GPL(devm_ad_sd_setup_buffer_and_trigger, "IIO_AD_SIGMA_DELTA");
/**
* ad_sd_init() - Initializes a ad_sigma_delta struct
@@ -656,7 +656,7 @@ int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
sigma_delta->spi = spi;
sigma_delta->info = info;
- /* If the field is unset in ad_sigma_delta_info, asume there can only be 1 slot. */
+ /* If the field is unset in ad_sigma_delta_info, assume there can only be 1 slot. */
if (!info->num_slots)
sigma_delta->num_slots = 1;
else
@@ -683,7 +683,7 @@ int ad_sd_init(struct ad_sigma_delta *sigma_delta, struct iio_dev *indio_dev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ad_sd_init, IIO_AD_SIGMA_DELTA);
+EXPORT_SYMBOL_NS_GPL(ad_sd_init, "IIO_AD_SIGMA_DELTA");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Analog Devices Sigma-Delta ADCs");
diff --git a/drivers/iio/adc/adi-axi-adc.c b/drivers/iio/adc/adi-axi-adc.c
index 5c8c87eb36d1..c7357601f0f8 100644
--- a/drivers/iio/adc/adi-axi-adc.c
+++ b/drivers/iio/adc/adi-axi-adc.c
@@ -437,5 +437,5 @@ module_platform_driver(adi_axi_adc_driver);
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices Generic AXI ADC IP core driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER);
-MODULE_IMPORT_NS(IIO_BACKEND);
+MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER");
+MODULE_IMPORT_NS("IIO_BACKEND");
diff --git a/drivers/iio/adc/at91-sama5d2_adc.c b/drivers/iio/adc/at91-sama5d2_adc.c
index d7fd21e7c6e2..8e5aaf15a921 100644
--- a/drivers/iio/adc/at91-sama5d2_adc.c
+++ b/drivers/iio/adc/at91-sama5d2_adc.c
@@ -2625,7 +2625,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_match);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
- .remove_new = at91_adc_remove,
+ .remove = at91_adc_remove,
.driver = {
.name = "at91-sama5d2_adc",
.of_match_table = at91_adc_dt_match,
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 9c39acff17e6..a3f0a2321666 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -1341,7 +1341,7 @@ MODULE_DEVICE_TABLE(of, at91_adc_dt_ids);
static struct platform_driver at91_adc_driver = {
.probe = at91_adc_probe,
- .remove_new = at91_adc_remove,
+ .remove = at91_adc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = at91_adc_dt_ids,
diff --git a/drivers/iio/adc/axp20x_adc.c b/drivers/iio/adc/axp20x_adc.c
index 6c1a5d1b0a83..9fd7027623d0 100644
--- a/drivers/iio/adc/axp20x_adc.c
+++ b/drivers/iio/adc/axp20x_adc.c
@@ -155,52 +155,22 @@ enum axp813_adc_channel_v {
AXP813_BATT_V,
};
-static struct iio_map axp20x_maps[] = {
- {
- .consumer_dev_name = "axp20x-usb-power-supply",
- .consumer_channel = "vbus_v",
- .adc_channel_label = "vbus_v",
- }, {
- .consumer_dev_name = "axp20x-usb-power-supply",
- .consumer_channel = "vbus_i",
- .adc_channel_label = "vbus_i",
- }, {
- .consumer_dev_name = "axp20x-ac-power-supply",
- .consumer_channel = "acin_v",
- .adc_channel_label = "acin_v",
- }, {
- .consumer_dev_name = "axp20x-ac-power-supply",
- .consumer_channel = "acin_i",
- .adc_channel_label = "acin_i",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_v",
- .adc_channel_label = "batt_v",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_chrg_i",
- .adc_channel_label = "batt_chrg_i",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_dischrg_i",
- .adc_channel_label = "batt_dischrg_i",
- }, { /* sentinel */ }
+static const struct iio_map axp20x_maps[] = {
+ IIO_MAP("vbus_v", "axp20x-usb-power-supply", "vbus_v"),
+ IIO_MAP("vbus_i", "axp20x-usb-power-supply", "vbus_i"),
+ IIO_MAP("acin_v", "axp20x-ac-power-supply", "acin_v"),
+ IIO_MAP("acin_i", "axp20x-ac-power-supply", "acin_i"),
+ IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"),
+ IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"),
+ IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"),
+ { /* sentinel */ }
};
-static struct iio_map axp22x_maps[] = {
- {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_v",
- .adc_channel_label = "batt_v",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_chrg_i",
- .adc_channel_label = "batt_chrg_i",
- }, {
- .consumer_dev_name = "axp20x-battery-power-supply",
- .consumer_channel = "batt_dischrg_i",
- .adc_channel_label = "batt_dischrg_i",
- }, { /* sentinel */ }
+static const struct iio_map axp22x_maps[] = {
+ IIO_MAP("batt_v", "axp20x-battery-power-supply", "batt_v"),
+ IIO_MAP("batt_chrg_i", "axp20x-battery-power-supply", "batt_chrg_i"),
+ IIO_MAP("batt_dischrg_i", "axp20x-battery-power-supply", "batt_dischrg_i"),
+ { /* sentinel */ }
};
static struct iio_map axp717_maps[] = {
@@ -1044,7 +1014,7 @@ struct axp_data {
unsigned long adc_en2_mask;
int (*adc_rate)(struct axp20x_adc_iio *info,
int rate);
- struct iio_map *maps;
+ const struct iio_map *maps;
};
static const struct axp_data axp192_data = {
@@ -1212,7 +1182,7 @@ static struct platform_driver axp20x_adc_driver = {
},
.id_table = axp20x_adc_id_match,
.probe = axp20x_probe,
- .remove_new = axp20x_remove,
+ .remove = axp20x_remove,
};
module_platform_driver(axp20x_adc_driver);
diff --git a/drivers/iio/adc/axp288_adc.c b/drivers/iio/adc/axp288_adc.c
index 8c3acc0cd7e9..45542efc3ece 100644
--- a/drivers/iio/adc/axp288_adc.c
+++ b/drivers/iio/adc/axp288_adc.c
@@ -103,7 +103,7 @@ static const struct iio_chan_spec axp288_adc_channels[] = {
};
/* for consumer drivers */
-static struct iio_map axp288_adc_default_maps[] = {
+static const struct iio_map axp288_adc_default_maps[] = {
IIO_MAP("TS_PIN", "axp288-batt", "axp288-batt-temp"),
IIO_MAP("PMIC_TEMP", "axp288-pmic", "axp288-pmic-temp"),
IIO_MAP("GPADC", "axp288-gpadc", "axp288-system-temp"),
diff --git a/drivers/iio/adc/bcm_iproc_adc.c b/drivers/iio/adc/bcm_iproc_adc.c
index cdfe304eaa20..f258668b0dc7 100644
--- a/drivers/iio/adc/bcm_iproc_adc.c
+++ b/drivers/iio/adc/bcm_iproc_adc.c
@@ -611,10 +611,10 @@ static const struct of_device_id iproc_adc_of_match[] = {
MODULE_DEVICE_TABLE(of, iproc_adc_of_match);
static struct platform_driver iproc_adc_driver = {
- .probe = iproc_adc_probe,
- .remove_new = iproc_adc_remove,
- .driver = {
- .name = "iproc-static-adc",
+ .probe = iproc_adc_probe,
+ .remove = iproc_adc_remove,
+ .driver = {
+ .name = "iproc-static-adc",
.of_match_table = iproc_adc_of_match,
},
};
diff --git a/drivers/iio/adc/da9150-gpadc.c b/drivers/iio/adc/da9150-gpadc.c
index 8f0d3fb63b67..0290345ade84 100644
--- a/drivers/iio/adc/da9150-gpadc.c
+++ b/drivers/iio/adc/da9150-gpadc.c
@@ -291,27 +291,11 @@ static const struct iio_chan_spec da9150_gpadc_channels[] = {
};
/* Default maps used by da9150-charger */
-static struct iio_map da9150_gpadc_default_maps[] = {
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_IBUS",
- .adc_channel_label = "IBUS",
- },
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_VBUS",
- .adc_channel_label = "VBUS",
- },
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_TJUNC",
- .adc_channel_label = "TJUNC_CORE",
- },
- {
- .consumer_dev_name = "da9150-charger",
- .consumer_channel = "CHAN_VBAT",
- .adc_channel_label = "VBAT",
- },
+static const struct iio_map da9150_gpadc_default_maps[] = {
+ IIO_MAP("IBUS", "da9150-charger", "CHAN_IBUS"),
+ IIO_MAP("VBUS", "da9150-charger", "CHAN_VBUS"),
+ IIO_MAP("TJUNC_CORE", "da9150-charger", "CHAN_TJUNC"),
+ IIO_MAP("VBAT", "da9150-charger", "CHAN_VBAT"),
{},
};
diff --git a/drivers/iio/adc/dln2-adc.c b/drivers/iio/adc/dln2-adc.c
index de7252a10047..30328626d9be 100644
--- a/drivers/iio/adc/dln2-adc.c
+++ b/drivers/iio/adc/dln2-adc.c
@@ -700,7 +700,7 @@ static void dln2_adc_remove(struct platform_device *pdev)
static struct platform_driver dln2_adc_driver = {
.driver.name = DLN2_ADC_MOD_NAME,
.probe = dln2_adc_probe,
- .remove_new = dln2_adc_remove,
+ .remove = dln2_adc_remove,
};
module_platform_driver(dln2_adc_driver);
diff --git a/drivers/iio/adc/ep93xx_adc.c b/drivers/iio/adc/ep93xx_adc.c
index cc38d5e0608e..a3e9c697e2cb 100644
--- a/drivers/iio/adc/ep93xx_adc.c
+++ b/drivers/iio/adc/ep93xx_adc.c
@@ -238,7 +238,7 @@ static struct platform_driver ep93xx_adc_driver = {
.of_match_table = ep93xx_adc_of_ids,
},
.probe = ep93xx_adc_probe,
- .remove_new = ep93xx_adc_remove,
+ .remove = ep93xx_adc_remove,
};
module_platform_driver(ep93xx_adc_driver);
diff --git a/drivers/iio/adc/exynos_adc.c b/drivers/iio/adc/exynos_adc.c
index 4d00ee8dd14d..4614cf848535 100644
--- a/drivers/iio/adc/exynos_adc.c
+++ b/drivers/iio/adc/exynos_adc.c
@@ -1008,7 +1008,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(exynos_adc_pm_ops, exynos_adc_suspend,
static struct platform_driver exynos_adc_driver = {
.probe = exynos_adc_probe,
- .remove_new = exynos_adc_remove,
+ .remove = exynos_adc_remove,
.driver = {
.name = "exynos-adc",
.of_match_table = exynos_adc_match,
diff --git a/drivers/iio/adc/gehc-pmc-adc.c b/drivers/iio/adc/gehc-pmc-adc.c
new file mode 100644
index 000000000000..d1167818b17d
--- /dev/null
+++ b/drivers/iio/adc/gehc-pmc-adc.c
@@ -0,0 +1,228 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * The GE HealthCare PMC ADC is a 16-Channel (Voltage and current), 16-Bit
+ * ADC with an I2C Interface.
+ *
+ * Copyright (C) 2024, GE HealthCare
+ *
+ * Authors:
+ * Herve Codina <herve.codina@bootlin.com>
+ */
+#include <dt-bindings/iio/adc/gehc,pmc-adc.h>
+#include <linux/bitops.h>
+#include <linux/clk.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+
+struct pmc_adc {
+ struct i2c_client *client;
+};
+
+#define PMC_ADC_CMD_REQUEST_PROTOCOL_VERSION 0x01
+#define PMC_ADC_CMD_READ_VOLTAGE(_ch) (0x10 | (_ch))
+#define PMC_ADC_CMD_READ_CURRENT(_ch) (0x20 | (_ch))
+
+#define PMC_ADC_VOLTAGE_CHANNEL(_ch, _ds_name) { \
+ .type = IIO_VOLTAGE, \
+ .indexed = 1, \
+ .channel = (_ch), \
+ .address = PMC_ADC_CMD_READ_VOLTAGE(_ch), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .datasheet_name = (_ds_name), \
+}
+
+#define PMC_ADC_CURRENT_CHANNEL(_ch, _ds_name) { \
+ .type = IIO_CURRENT, \
+ .indexed = 1, \
+ .channel = (_ch), \
+ .address = PMC_ADC_CMD_READ_CURRENT(_ch), \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED), \
+ .datasheet_name = (_ds_name), \
+}
+
+static const struct iio_chan_spec pmc_adc_channels[] = {
+ PMC_ADC_VOLTAGE_CHANNEL(0, "CH0_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(1, "CH1_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(2, "CH2_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(3, "CH3_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(4, "CH4_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(5, "CH5_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(6, "CH6_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(7, "CH7_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(8, "CH8_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(9, "CH9_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(10, "CH10_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(11, "CH11_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(12, "CH12_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(13, "CH13_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(14, "CH14_V"),
+ PMC_ADC_VOLTAGE_CHANNEL(15, "CH15_V"),
+
+ PMC_ADC_CURRENT_CHANNEL(0, "CH0_I"),
+ PMC_ADC_CURRENT_CHANNEL(1, "CH1_I"),
+ PMC_ADC_CURRENT_CHANNEL(2, "CH2_I"),
+ PMC_ADC_CURRENT_CHANNEL(3, "CH3_I"),
+ PMC_ADC_CURRENT_CHANNEL(4, "CH4_I"),
+ PMC_ADC_CURRENT_CHANNEL(5, "CH5_I"),
+ PMC_ADC_CURRENT_CHANNEL(6, "CH6_I"),
+ PMC_ADC_CURRENT_CHANNEL(7, "CH7_I"),
+ PMC_ADC_CURRENT_CHANNEL(8, "CH8_I"),
+ PMC_ADC_CURRENT_CHANNEL(9, "CH9_I"),
+ PMC_ADC_CURRENT_CHANNEL(10, "CH10_I"),
+ PMC_ADC_CURRENT_CHANNEL(11, "CH11_I"),
+ PMC_ADC_CURRENT_CHANNEL(12, "CH12_I"),
+ PMC_ADC_CURRENT_CHANNEL(13, "CH13_I"),
+ PMC_ADC_CURRENT_CHANNEL(14, "CH14_I"),
+ PMC_ADC_CURRENT_CHANNEL(15, "CH15_I"),
+};
+
+static int pmc_adc_read_raw_ch(struct pmc_adc *pmc_adc, u8 cmd, int *val)
+{
+ s32 ret;
+
+ ret = i2c_smbus_read_word_swapped(pmc_adc->client, cmd);
+ if (ret < 0) {
+ dev_err(&pmc_adc->client->dev, "i2c read word failed (%d)\n", ret);
+ return ret;
+ }
+
+ *val = sign_extend32(ret, 15);
+ return 0;
+}
+
+static int pmc_adc_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct pmc_adc *pmc_adc = iio_priv(indio_dev);
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ /* Values are directly read in mV or mA */
+ ret = pmc_adc_read_raw_ch(pmc_adc, chan->address, val);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+ }
+
+ return -EINVAL;
+}
+
+static int pmc_adc_fwnode_xlate(struct iio_dev *indio_dev,
+ const struct fwnode_reference_args *iiospec)
+{
+ enum iio_chan_type expected_type;
+ unsigned int i;
+
+ /*
+ * args[0]: Acquisition type (i.e. voltage or current)
+ * args[1]: PMC ADC channel number
+ */
+ if (iiospec->nargs != 2)
+ return -EINVAL;
+
+ switch (iiospec->args[0]) {
+ case GEHC_PMC_ADC_VOLTAGE:
+ expected_type = IIO_VOLTAGE;
+ break;
+ case GEHC_PMC_ADC_CURRENT:
+ expected_type = IIO_CURRENT;
+ break;
+ default:
+ dev_err(&indio_dev->dev, "Invalid channel type %llu\n",
+ iiospec->args[0]);
+ return -EINVAL;
+ }
+
+ for (i = 0; i < indio_dev->num_channels; i++)
+ if (indio_dev->channels[i].type == expected_type &&
+ indio_dev->channels[i].channel == iiospec->args[1])
+ return i;
+
+ dev_err(&indio_dev->dev, "Invalid channel type %llu number %llu\n",
+ iiospec->args[0], iiospec->args[1]);
+ return -EINVAL;
+}
+
+static const struct iio_info pmc_adc_info = {
+ .read_raw = pmc_adc_read_raw,
+ .fwnode_xlate = pmc_adc_fwnode_xlate,
+};
+
+static const char *const pmc_adc_regulator_names[] = {
+ "vdd",
+ "vdda",
+ "vddio",
+ "vref",
+};
+
+static int pmc_adc_probe(struct i2c_client *client)
+{
+ struct iio_dev *indio_dev;
+ struct pmc_adc *pmc_adc;
+ struct clk *clk;
+ s32 val;
+ int ret;
+
+ ret = devm_regulator_bulk_get_enable(&client->dev, ARRAY_SIZE(pmc_adc_regulator_names),
+ pmc_adc_regulator_names);
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "Failed to get regulators\n");
+
+ clk = devm_clk_get_optional_enabled(&client->dev, "osc");
+ if (IS_ERR(clk))
+ return dev_err_probe(&client->dev, PTR_ERR(clk), "Failed to get osc clock\n");
+
+ indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*pmc_adc));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ pmc_adc = iio_priv(indio_dev);
+ pmc_adc->client = client;
+
+ val = i2c_smbus_read_byte_data(pmc_adc->client, PMC_ADC_CMD_REQUEST_PROTOCOL_VERSION);
+ if (val < 0)
+ return dev_err_probe(&client->dev, val, "Failed to get protocol version\n");
+
+ if (val != 0x01)
+ return dev_err_probe(&client->dev, -EINVAL,
+ "Unsupported protocol version 0x%02x\n", val);
+
+ indio_dev->name = "pmc_adc";
+ indio_dev->info = &pmc_adc_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->channels = pmc_adc_channels;
+ indio_dev->num_channels = ARRAY_SIZE(pmc_adc_channels);
+
+ return devm_iio_device_register(&client->dev, indio_dev);
+}
+
+static const struct of_device_id pmc_adc_of_match[] = {
+ { .compatible = "gehc,pmc-adc"},
+ { }
+};
+MODULE_DEVICE_TABLE(of, pmc_adc_of_match);
+
+static const struct i2c_device_id pmc_adc_id_table[] = {
+ { "pmc-adc" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, pmc_adc_id_table);
+
+static struct i2c_driver pmc_adc_i2c_driver = {
+ .driver = {
+ .name = "pmc-adc",
+ .of_match_table = pmc_adc_of_match,
+ },
+ .id_table = pmc_adc_id_table,
+ .probe = pmc_adc_probe,
+};
+
+module_i2c_driver(pmc_adc_i2c_driver);
+
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
+MODULE_DESCRIPTION("GE HealthCare PMC ADC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/adc/hi8435.c b/drivers/iio/adc/hi8435.c
index fb635a756440..689e34f06987 100644
--- a/drivers/iio/adc/hi8435.c
+++ b/drivers/iio/adc/hi8435.c
@@ -132,7 +132,7 @@ static int hi8435_read_event_config(struct iio_dev *idev,
static int hi8435_write_event_config(struct iio_dev *idev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct hi8435_priv *priv = iio_priv(idev);
int ret;
diff --git a/drivers/iio/adc/imx8qxp-adc.c b/drivers/iio/adc/imx8qxp-adc.c
index fe82198170d5..3d19d7d744aa 100644
--- a/drivers/iio/adc/imx8qxp-adc.c
+++ b/drivers/iio/adc/imx8qxp-adc.c
@@ -487,7 +487,7 @@ MODULE_DEVICE_TABLE(of, imx8qxp_adc_match);
static struct platform_driver imx8qxp_adc_driver = {
.probe = imx8qxp_adc_probe,
- .remove_new = imx8qxp_adc_remove,
+ .remove = imx8qxp_adc_remove,
.driver = {
.name = ADC_DRIVER_NAME,
.of_match_table = imx8qxp_adc_match,
diff --git a/drivers/iio/adc/imx93_adc.c b/drivers/iio/adc/imx93_adc.c
index 4ccf4819f1f1..002eb19587d6 100644
--- a/drivers/iio/adc/imx93_adc.c
+++ b/drivers/iio/adc/imx93_adc.c
@@ -470,7 +470,7 @@ MODULE_DEVICE_TABLE(of, imx93_adc_match);
static struct platform_driver imx93_adc_driver = {
.probe = imx93_adc_probe,
- .remove_new = imx93_adc_remove,
+ .remove = imx93_adc_remove,
.driver = {
.name = IMX93_ADC_DRIVER_NAME,
.of_match_table = imx93_adc_match,
diff --git a/drivers/iio/adc/intel_mrfld_adc.c b/drivers/iio/adc/intel_mrfld_adc.c
index 30733252aa56..c178850eaaab 100644
--- a/drivers/iio/adc/intel_mrfld_adc.c
+++ b/drivers/iio/adc/intel_mrfld_adc.c
@@ -164,7 +164,7 @@ static const struct iio_chan_spec mrfld_adc_channels[] = {
BCOVE_ADC_CHANNEL(IIO_TEMP, 8, "CH8", 0xC6),
};
-static struct iio_map iio_maps[] = {
+static const struct iio_map iio_maps[] = {
IIO_MAP("CH0", "bcove-battery", "VBATRSLT"),
IIO_MAP("CH1", "bcove-battery", "BATTID"),
IIO_MAP("CH2", "bcove-battery", "IBATRSLT"),
diff --git a/drivers/iio/adc/lp8788_adc.c b/drivers/iio/adc/lp8788_adc.c
index 6d9b354bc705..33bf8aef79e3 100644
--- a/drivers/iio/adc/lp8788_adc.c
+++ b/drivers/iio/adc/lp8788_adc.c
@@ -26,7 +26,7 @@
struct lp8788_adc {
struct lp8788 *lp;
- struct iio_map *map;
+ const struct iio_map *map;
struct mutex lock;
};
@@ -149,17 +149,9 @@ static const struct iio_chan_spec lp8788_adc_channels[] = {
};
/* default maps used by iio consumer (lp8788-charger driver) */
-static struct iio_map lp8788_default_iio_maps[] = {
- {
- .consumer_dev_name = "lp8788-charger",
- .consumer_channel = "lp8788_vbatt_5p0",
- .adc_channel_label = "VBATT_5P0",
- },
- {
- .consumer_dev_name = "lp8788-charger",
- .consumer_channel = "lp8788_adc1",
- .adc_channel_label = "ADC1",
- },
+static const struct iio_map lp8788_default_iio_maps[] = {
+ IIO_MAP("VBATT_5P0", "lp8788-charger", "lp8788_vbatt_5p0"),
+ IIO_MAP("ADC1", "lp8788-charger", "lp8788_adc1"),
{ }
};
@@ -168,7 +160,7 @@ static int lp8788_iio_map_register(struct device *dev,
struct lp8788_platform_data *pdata,
struct lp8788_adc *adc)
{
- struct iio_map *map;
+ const struct iio_map *map;
int ret;
map = (!pdata || !pdata->adc_pdata) ?
diff --git a/drivers/iio/adc/ltc2497-core.c b/drivers/iio/adc/ltc2497-core.c
index 996f6cbbed3c..2dc5c7044269 100644
--- a/drivers/iio/adc/ltc2497-core.c
+++ b/drivers/iio/adc/ltc2497-core.c
@@ -168,6 +168,7 @@ static const struct iio_info ltc2497core_info = {
int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev)
{
struct ltc2497core_driverdata *ddata = iio_priv(indio_dev);
+ struct iio_map *plat_data = dev_get_platdata(dev);
int ret;
/*
@@ -200,16 +201,10 @@ int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev)
return ret;
}
- if (dev->platform_data) {
- struct iio_map *plat_data;
-
- plat_data = (struct iio_map *)dev->platform_data;
-
- ret = iio_map_array_register(indio_dev, plat_data);
- if (ret) {
- dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
- goto err_regulator_disable;
- }
+ ret = iio_map_array_register(indio_dev, plat_data);
+ if (ret) {
+ dev_err(&indio_dev->dev, "iio map err: %d\n", ret);
+ goto err_regulator_disable;
}
ddata->addr_prev = LTC2497_CONFIG_DEFAULT;
@@ -231,7 +226,7 @@ err_regulator_disable:
return ret;
}
-EXPORT_SYMBOL_NS(ltc2497core_probe, LTC2497);
+EXPORT_SYMBOL_NS(ltc2497core_probe, "LTC2497");
void ltc2497core_remove(struct iio_dev *indio_dev)
{
@@ -243,7 +238,7 @@ void ltc2497core_remove(struct iio_dev *indio_dev)
regulator_disable(ddata->ref);
}
-EXPORT_SYMBOL_NS(ltc2497core_remove, LTC2497);
+EXPORT_SYMBOL_NS(ltc2497core_remove, "LTC2497");
MODULE_DESCRIPTION("common code for LTC2496/LTC2497 drivers");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/adc/ltc2497.h b/drivers/iio/adc/ltc2497.h
index 781519b52475..64e81c95a3dd 100644
--- a/drivers/iio/adc/ltc2497.h
+++ b/drivers/iio/adc/ltc2497.h
@@ -23,4 +23,4 @@ struct ltc2497core_driverdata {
int ltc2497core_probe(struct device *dev, struct iio_dev *indio_dev);
void ltc2497core_remove(struct iio_dev *indio_dev);
-MODULE_IMPORT_NS(LTC2497);
+MODULE_IMPORT_NS("LTC2497");
diff --git a/drivers/iio/adc/max11205.c b/drivers/iio/adc/max11205.c
index 9d8bc0b154dd..6c803df220b6 100644
--- a/drivers/iio/adc/max11205.c
+++ b/drivers/iio/adc/max11205.c
@@ -177,4 +177,4 @@ module_spi_driver(max11205_spi_driver);
MODULE_AUTHOR("Ramona Bolboaca <ramona.bolboaca@analog.com>");
MODULE_DESCRIPTION("MAX11205 ADC driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD_SIGMA_DELTA);
+MODULE_IMPORT_NS("IIO_AD_SIGMA_DELTA");
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index d0c6e94f7204..9a0baea08ab6 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -25,6 +25,7 @@
#include <linux/module.h>
#include <linux/mod_devicetable.h>
#include <linux/property.h>
+#include <linux/unaligned.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -392,7 +393,7 @@ static int max1363_read_single_chan(struct iio_dev *indio_dev,
if (data < 0)
return data;
- data = (rxbuf[1] | rxbuf[0] << 8) &
+ data = get_unaligned_be16(rxbuf) &
((1 << st->chip_info->bits) - 1);
} else {
/* Get reading */
@@ -943,7 +944,7 @@ error_ret:
static int max1363_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct max1363_state *st = iio_priv(indio_dev);
diff --git a/drivers/iio/adc/max34408.c b/drivers/iio/adc/max34408.c
index ffec22be2d59..971e6e5dee9b 100644
--- a/drivers/iio/adc/max34408.c
+++ b/drivers/iio/adc/max34408.c
@@ -161,7 +161,7 @@ static int max34408_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
/*
- * calcluate current for 8bit ADC with Rsense
+ * calculate current for 8bit ADC with Rsense
* value.
* 10 mV * 1000 / Rsense uOhm = max current
* (max current * adc val * 1000) / (2^8 - 1) mA
diff --git a/drivers/iio/adc/men_z188_adc.c b/drivers/iio/adc/men_z188_adc.c
index 198c7e68e0cf..cf8a8c0412ec 100644
--- a/drivers/iio/adc/men_z188_adc.c
+++ b/drivers/iio/adc/men_z188_adc.c
@@ -172,4 +172,4 @@ MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("IIO ADC driver for MEN 16z188 ADC Core");
MODULE_ALIAS("mcb:16z188");
-MODULE_IMPORT_NS(MCB);
+MODULE_IMPORT_NS("MCB");
diff --git a/drivers/iio/adc/meson_saradc.c b/drivers/iio/adc/meson_saradc.c
index e16b0e28974e..2d475b43e717 100644
--- a/drivers/iio/adc/meson_saradc.c
+++ b/drivers/iio/adc/meson_saradc.c
@@ -1483,7 +1483,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(meson_sar_adc_pm_ops,
static struct platform_driver meson_sar_adc_driver = {
.probe = meson_sar_adc_probe,
- .remove_new = meson_sar_adc_remove,
+ .remove = meson_sar_adc_remove,
.driver = {
.name = "meson-saradc",
.of_match_table = meson_sar_adc_of_match,
diff --git a/drivers/iio/adc/mp2629_adc.c b/drivers/iio/adc/mp2629_adc.c
index 5fbf9b6abd9c..1cb043b17437 100644
--- a/drivers/iio/adc/mp2629_adc.c
+++ b/drivers/iio/adc/mp2629_adc.c
@@ -52,7 +52,7 @@ static struct iio_chan_spec mp2629_channels[] = {
MP2629_ADC_CHAN(INPUT_CURRENT, IIO_CURRENT)
};
-static struct iio_map mp2629_adc_maps[] = {
+static const struct iio_map mp2629_adc_maps[] = {
MP2629_MAP(BATT_VOLT, "batt-volt"),
MP2629_MAP(SYSTEM_VOLT, "system-volt"),
MP2629_MAP(INPUT_VOLT, "input-volt"),
@@ -195,7 +195,7 @@ static struct platform_driver mp2629_adc_driver = {
.of_match_table = mp2629_adc_of_match,
},
.probe = mp2629_adc_probe,
- .remove_new = mp2629_adc_remove,
+ .remove = mp2629_adc_remove,
};
module_platform_driver(mp2629_adc_driver);
diff --git a/drivers/iio/adc/mt6360-adc.c b/drivers/iio/adc/mt6360-adc.c
index 83161e6d29b9..4eb2455d6ffa 100644
--- a/drivers/iio/adc/mt6360-adc.c
+++ b/drivers/iio/adc/mt6360-adc.c
@@ -124,7 +124,7 @@ static int mt6360_adc_read_channel(struct mt6360_adc_data *mad, int channel, int
usleep_range(ADC_LOOP_TIME_US / 2, ADC_LOOP_TIME_US);
}
- *val = rpt[1] << 8 | rpt[2];
+ *val = get_unaligned_be16(&rpt[1]);
ret = IIO_VAL_INT;
out_adc_conv:
diff --git a/drivers/iio/adc/mxs-lradc-adc.c b/drivers/iio/adc/mxs-lradc-adc.c
index 8c7b64e78dbb..152cbe265e1a 100644
--- a/drivers/iio/adc/mxs-lradc-adc.c
+++ b/drivers/iio/adc/mxs-lradc-adc.c
@@ -819,10 +819,10 @@ static void mxs_lradc_adc_remove(struct platform_device *pdev)
static struct platform_driver mxs_lradc_adc_driver = {
.driver = {
- .name = "mxs-lradc-adc",
+ .name = "mxs-lradc-adc",
},
- .probe = mxs_lradc_adc_probe,
- .remove_new = mxs_lradc_adc_remove,
+ .probe = mxs_lradc_adc_probe,
+ .remove = mxs_lradc_adc_remove,
};
module_platform_driver(mxs_lradc_adc_driver);
diff --git a/drivers/iio/adc/npcm_adc.c b/drivers/iio/adc/npcm_adc.c
index 3a55465951e7..7c1511ee3a4b 100644
--- a/drivers/iio/adc/npcm_adc.c
+++ b/drivers/iio/adc/npcm_adc.c
@@ -337,7 +337,7 @@ static void npcm_adc_remove(struct platform_device *pdev)
static struct platform_driver npcm_adc_driver = {
.probe = npcm_adc_probe,
- .remove_new = npcm_adc_remove,
+ .remove = npcm_adc_remove,
.driver = {
.name = "npcm_adc",
.of_match_table = npcm_adc_match,
diff --git a/drivers/iio/adc/pac1921.c b/drivers/iio/adc/pac1921.c
index 36e813d9c73f..b0f6727cfe38 100644
--- a/drivers/iio/adc/pac1921.c
+++ b/drivers/iio/adc/pac1921.c
@@ -241,7 +241,7 @@ static inline void pac1921_calc_scale(int dividend, int divisor, int *val,
s64 tmp;
tmp = div_s64(dividend * (s64)NANO, divisor);
- *val = (int)div_s64_rem(tmp, NANO, val2);
+ *val = div_s64_rem(tmp, NANO, val2);
}
/*
@@ -260,7 +260,7 @@ static void pac1921_calc_current_scales(struct pac1921_priv *priv)
int max = (PAC1921_MAX_VSENSE_MV * MICRO) >> i;
int vsense_lsb = DIV_ROUND_CLOSEST(max, PAC1921_RES_RESOLUTION);
- pac1921_calc_scale(vsense_lsb, (int)priv->rshunt_uohm,
+ pac1921_calc_scale(vsense_lsb, priv->rshunt_uohm,
&priv->current_scales[i][0],
&priv->current_scales[i][1]);
}
@@ -314,7 +314,7 @@ static int pac1921_check_push_overflow(struct iio_dev *indio_dev, s64 timestamp)
timestamp);
}
- priv->prev_ovf_flags = (u8)flags;
+ priv->prev_ovf_flags = flags;
return 0;
}
@@ -329,8 +329,7 @@ static int pac1921_check_push_overflow(struct iio_dev *indio_dev, s64 timestamp)
static int pac1921_read_res(struct pac1921_priv *priv, unsigned long reg,
u16 *val)
{
- int ret = regmap_bulk_read(priv->regmap, (unsigned int)reg, val,
- sizeof(*val));
+ int ret = regmap_bulk_read(priv->regmap, reg, val, sizeof(*val));
if (ret)
return ret;
@@ -366,7 +365,7 @@ static int pac1921_read_raw(struct iio_dev *indio_dev,
if (ret)
return ret;
- *val = (int)res_val;
+ *val = res_val;
return IIO_VAL_INT;
}
@@ -400,10 +399,10 @@ static int pac1921_read_raw(struct iio_dev *indio_dev,
s64 tmp = curr_scale[0] * (s64)NANO + curr_scale[1];
/* Multiply by max_vbus (V) / dv_gain */
- tmp *= PAC1921_MAX_VBUS_V >> (int)priv->dv_gain;
+ tmp *= PAC1921_MAX_VBUS_V >> priv->dv_gain;
/* Convert back to INT_PLUS_NANO */
- *val = (int)div_s64_rem(tmp, NANO, val2);
+ *val = div_s64_rem(tmp, NANO, val2);
return IIO_VAL_INT_PLUS_NANO;
}
@@ -426,7 +425,7 @@ static int pac1921_read_raw(struct iio_dev *indio_dev,
* 1/(integr_period_usecs/MICRO) = MICRO/integr_period_usecs
*/
*val = MICRO;
- *val2 = (int)priv->integr_period_usecs;
+ *val2 = priv->integr_period_usecs;
return IIO_VAL_FRACTIONAL;
default:
@@ -503,7 +502,7 @@ static int pac1921_lookup_scale(const int (*const scales_tbl)[2], size_t size,
for (unsigned int i = 0; i < size; i++)
if (scales_tbl[i][0] == scale_val &&
scales_tbl[i][1] == scale_val2)
- return (int)i;
+ return i;
return -EINVAL;
}
@@ -553,7 +552,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- return pac1921_update_gain(priv, &priv->dv_gain, (u8)ret,
+ return pac1921_update_gain(priv, &priv->dv_gain, ret,
PAC1921_GAIN_DV_GAIN_MASK);
case PAC1921_CHAN_VSENSE:
ret = pac1921_lookup_scale(pac1921_vsense_scales,
@@ -562,7 +561,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- return pac1921_update_gain(priv, &priv->di_gain, (u8)ret,
+ return pac1921_update_gain(priv, &priv->di_gain, ret,
PAC1921_GAIN_DI_GAIN_MASK);
case PAC1921_CHAN_CURRENT:
ret = pac1921_lookup_scale(priv->current_scales,
@@ -571,7 +570,7 @@ static int pac1921_update_gain_from_scale(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- return pac1921_update_gain(priv, &priv->di_gain, (u8)ret,
+ return pac1921_update_gain(priv, &priv->di_gain, ret,
PAC1921_GAIN_DI_GAIN_MASK);
default:
return -EINVAL;
@@ -586,7 +585,7 @@ static int pac1921_lookup_int_num_samples(int num_samples)
{
for (unsigned int i = 0; i < ARRAY_SIZE(pac1921_int_num_samples); i++)
if (pac1921_int_num_samples[i] == num_samples)
- return (int)i;
+ return i;
return -EINVAL;
}
@@ -607,7 +606,7 @@ static int pac1921_update_int_num_samples(struct pac1921_priv *priv,
if (ret < 0)
return ret;
- n_samples = (u8)ret;
+ n_samples = ret;
if (priv->n_samples == n_samples)
return 0;
@@ -700,7 +699,8 @@ static int pac1921_read_event_config(struct iio_dev *indio_dev,
static int pac1921_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct pac1921_priv *priv = iio_priv(indio_dev);
u8 ovf_bit;
@@ -770,7 +770,7 @@ static ssize_t pac1921_read_shunt_resistor(struct iio_dev *indio_dev,
guard(mutex)(&priv->lock);
- vals[0] = (int)priv->rshunt_uohm;
+ vals[0] = priv->rshunt_uohm;
vals[1] = MICRO;
return iio_format_value(buf, IIO_VAL_FRACTIONAL, 1, vals);
@@ -793,13 +793,13 @@ static ssize_t pac1921_write_shunt_resistor(struct iio_dev *indio_dev,
if (ret)
return ret;
- rshunt_uohm = (u32)val * MICRO + (u32)val_fract;
+ rshunt_uohm = val * MICRO + val_fract;
if (rshunt_uohm == 0 || rshunt_uohm > INT_MAX)
return -EINVAL;
guard(mutex)(&priv->lock);
- priv->rshunt_uohm = (u32)rshunt_uohm;
+ priv->rshunt_uohm = rshunt_uohm;
pac1921_calc_current_scales(priv);
@@ -1077,7 +1077,7 @@ static int pac1921_init(struct pac1921_priv *priv)
/*
* Init control register:
* - VPower free run integration mode
- * - OUT pin full scale range: 3V (HW detault)
+ * - OUT pin full scale range: 3V (HW default)
* - no timeout, no sleep, no sleep override, no recalc (HW defaults)
*/
val = FIELD_PREP(PAC1921_CONTROL_MXSL_MASK,
@@ -1168,10 +1168,12 @@ static int pac1921_probe(struct i2c_client *client)
priv->regmap = devm_regmap_init_i2c(client, &pac1921_regmap_config);
if (IS_ERR(priv->regmap))
- return dev_err_probe(dev, (int)PTR_ERR(priv->regmap),
+ return dev_err_probe(dev, PTR_ERR(priv->regmap),
"Cannot initialize register map\n");
- devm_mutex_init(dev, &priv->lock);
+ ret = devm_mutex_init(dev, &priv->lock);
+ if (ret)
+ return ret;
priv->dv_gain = PAC1921_DEFAULT_DV_GAIN;
priv->di_gain = PAC1921_DEFAULT_DI_GAIN;
@@ -1191,7 +1193,7 @@ static int pac1921_probe(struct i2c_client *client)
priv->vdd = devm_regulator_get(dev, "vdd");
if (IS_ERR(priv->vdd))
- return dev_err_probe(dev, (int)PTR_ERR(priv->vdd),
+ return dev_err_probe(dev, PTR_ERR(priv->vdd),
"Cannot get vdd regulator\n");
ret = regulator_enable(priv->vdd);
diff --git a/drivers/iio/adc/pac1934.c b/drivers/iio/adc/pac1934.c
index 7ef249d83286..20802b7f49ea 100644
--- a/drivers/iio/adc/pac1934.c
+++ b/drivers/iio/adc/pac1934.c
@@ -1507,7 +1507,7 @@ static int pac1934_probe(struct i2c_client *client)
indio_dev->name = pac1934_chip_config[ret].name;
}
- if (acpi_match_device(dev->driver->acpi_match_table, dev))
+ if (is_acpi_device_node(dev_fwnode(dev)))
ret = pac1934_acpi_parse_channel_config(client, info);
else
/*
diff --git a/drivers/iio/adc/palmas_gpadc.c b/drivers/iio/adc/palmas_gpadc.c
index 203cbbc70719..d283ee8fb1d2 100644
--- a/drivers/iio/adc/palmas_gpadc.c
+++ b/drivers/iio/adc/palmas_gpadc.c
@@ -456,7 +456,7 @@ static int palmas_gpadc_get_calibrated_code(struct palmas_gpadc *adc,
* raw high threshold = (ideal threshold + INL) * gain error + offset error
*
* The gain error include both gain error, as specified in the datasheet, and
- * the gain error drift. These paramenters vary depending on device and whether
+ * the gain error drift. These parameters vary depending on device and whether
* the channel is calibrated (trimmed) or not.
*/
static int palmas_gpadc_threshold_with_tolerance(int val, const int INL,
@@ -676,7 +676,7 @@ static int palmas_gpadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct palmas_gpadc *adc = iio_priv(indio_dev);
int adc_chan = chan->channel;
diff --git a/drivers/iio/adc/qcom-pm8xxx-xoadc.c b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
index 9e1112f5acc6..31f88cf7f7f1 100644
--- a/drivers/iio/adc/qcom-pm8xxx-xoadc.c
+++ b/drivers/iio/adc/qcom-pm8xxx-xoadc.c
@@ -821,7 +821,6 @@ static int pm8xxx_xoadc_parse_channel(struct device *dev,
static int pm8xxx_xoadc_parse_channels(struct pm8xxx_xoadc *adc)
{
- struct fwnode_handle *child;
struct pm8xxx_chan_info *ch;
int ret;
int i;
@@ -844,16 +843,15 @@ static int pm8xxx_xoadc_parse_channels(struct pm8xxx_xoadc *adc)
return -ENOMEM;
i = 0;
- device_for_each_child_node(adc->dev, child) {
+ device_for_each_child_node_scoped(adc->dev, child) {
ch = &adc->chans[i];
ret = pm8xxx_xoadc_parse_channel(adc->dev, child,
adc->variant->channels,
&adc->iio_chans[i],
ch);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
+
i++;
}
@@ -1016,7 +1014,7 @@ static struct platform_driver pm8xxx_xoadc_driver = {
.of_match_table = pm8xxx_xoadc_id_table,
},
.probe = pm8xxx_xoadc_probe,
- .remove_new = pm8xxx_xoadc_remove,
+ .remove = pm8xxx_xoadc_remove,
};
module_platform_driver(pm8xxx_xoadc_driver);
diff --git a/drivers/iio/adc/qcom-spmi-adc5.c b/drivers/iio/adc/qcom-spmi-adc5.c
index 9b69f40beed8..af3c2f659f5e 100644
--- a/drivers/iio/adc/qcom-spmi-adc5.c
+++ b/drivers/iio/adc/qcom-spmi-adc5.c
@@ -830,7 +830,7 @@ static int adc5_get_fw_data(struct adc5_chip *adc)
adc->nchannels = device_get_child_node_count(adc->dev);
if (!adc->nchannels)
- return -EINVAL;
+ return dev_err_probe(adc->dev, -EINVAL, "no channels defined\n");
adc->iio_chans = devm_kcalloc(adc->dev, adc->nchannels,
sizeof(*adc->iio_chans), GFP_KERNEL);
@@ -903,7 +903,7 @@ static int adc5_probe(struct platform_device *pdev)
ret = adc5_get_fw_data(adc);
if (ret)
- return dev_err_probe(dev, ret, "adc get dt data failed\n");
+ return ret;
irq_eoc = platform_get_irq(pdev, 0);
if (irq_eoc < 0) {
diff --git a/drivers/iio/adc/qcom-spmi-vadc.c b/drivers/iio/adc/qcom-spmi-vadc.c
index f5c6f1f27b2c..00a7f0982025 100644
--- a/drivers/iio/adc/qcom-spmi-vadc.c
+++ b/drivers/iio/adc/qcom-spmi-vadc.c
@@ -754,7 +754,6 @@ static int vadc_get_fw_data(struct vadc_priv *vadc)
const struct vadc_channels *vadc_chan;
struct iio_chan_spec *iio_chan;
struct vadc_channel_prop prop;
- struct fwnode_handle *child;
unsigned int index = 0;
int ret;
@@ -774,12 +773,10 @@ static int vadc_get_fw_data(struct vadc_priv *vadc)
iio_chan = vadc->iio_chans;
- device_for_each_child_node(vadc->dev, child) {
+ device_for_each_child_node_scoped(vadc->dev, child) {
ret = vadc_get_fw_channel_data(vadc->dev, &prop, child);
- if (ret) {
- fwnode_handle_put(child);
+ if (ret)
return ret;
- }
prop.scale_fn_type = vadc_chans[prop.channel].scale_fn_type;
vadc->chan_props[index] = prop;
diff --git a/drivers/iio/adc/rcar-gyroadc.c b/drivers/iio/adc/rcar-gyroadc.c
index 15a21d2860e7..11170b5852d1 100644
--- a/drivers/iio/adc/rcar-gyroadc.c
+++ b/drivers/iio/adc/rcar-gyroadc.c
@@ -592,7 +592,7 @@ static const struct dev_pm_ops rcar_gyroadc_pm_ops = {
static struct platform_driver rcar_gyroadc_driver = {
.probe = rcar_gyroadc_probe,
- .remove_new = rcar_gyroadc_remove,
+ .remove = rcar_gyroadc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = rcar_gyroadc_match,
diff --git a/drivers/iio/adc/rn5t618-adc.c b/drivers/iio/adc/rn5t618-adc.c
index ce5f3011fe00..b33536157adc 100644
--- a/drivers/iio/adc/rn5t618-adc.c
+++ b/drivers/iio/adc/rn5t618-adc.c
@@ -185,7 +185,7 @@ static const struct iio_chan_spec rn5t618_adc_iio_channels[] = {
RN5T618_ADC_CHANNEL(AIN0, IIO_VOLTAGE, "AIN0")
};
-static struct iio_map rn5t618_maps[] = {
+static const struct iio_map rn5t618_maps[] = {
IIO_MAP("VADP", "rn5t618-power", "vadp"),
IIO_MAP("VUSB", "rn5t618-power", "vusb"),
{ /* sentinel */ }
diff --git a/drivers/iio/adc/sd_adc_modulator.c b/drivers/iio/adc/sd_adc_modulator.c
index 654b6a38b650..9f7a75168aac 100644
--- a/drivers/iio/adc/sd_adc_modulator.c
+++ b/drivers/iio/adc/sd_adc_modulator.c
@@ -159,4 +159,4 @@ module_platform_driver(iio_sd_mod_adc);
MODULE_DESCRIPTION("Basic sigma delta modulator");
MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_BACKEND);
+MODULE_IMPORT_NS("IIO_BACKEND");
diff --git a/drivers/iio/adc/stm32-adc-core.c b/drivers/iio/adc/stm32-adc-core.c
index 616dd729666a..2201ee9987ae 100644
--- a/drivers/iio/adc/stm32-adc-core.c
+++ b/drivers/iio/adc/stm32-adc-core.c
@@ -906,7 +906,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
static struct platform_driver stm32_adc_driver = {
.probe = stm32_adc_probe,
- .remove_new = stm32_adc_remove,
+ .remove = stm32_adc_remove,
.driver = {
.name = "stm32-adc-core",
.of_match_table = stm32_adc_of_match,
diff --git a/drivers/iio/adc/stm32-adc.c b/drivers/iio/adc/stm32-adc.c
index 32ca26ed59f7..9d3b23efcc06 100644
--- a/drivers/iio/adc/stm32-adc.c
+++ b/drivers/iio/adc/stm32-adc.c
@@ -2644,7 +2644,7 @@ MODULE_DEVICE_TABLE(of, stm32_adc_of_match);
static struct platform_driver stm32_adc_driver = {
.probe = stm32_adc_probe,
- .remove_new = stm32_adc_remove,
+ .remove = stm32_adc_remove,
.driver = {
.name = "stm32-adc",
.of_match_table = stm32_adc_of_match,
diff --git a/drivers/iio/adc/stm32-dfsdm-adc.c b/drivers/iio/adc/stm32-dfsdm-adc.c
index 2037f73426d4..1f9eca2fb2bf 100644
--- a/drivers/iio/adc/stm32-dfsdm-adc.c
+++ b/drivers/iio/adc/stm32-dfsdm-adc.c
@@ -1890,11 +1890,11 @@ static struct platform_driver stm32_dfsdm_adc_driver = {
.pm = pm_sleep_ptr(&stm32_dfsdm_adc_pm_ops),
},
.probe = stm32_dfsdm_adc_probe,
- .remove_new = stm32_dfsdm_adc_remove,
+ .remove = stm32_dfsdm_adc_remove,
};
module_platform_driver(stm32_dfsdm_adc_driver);
MODULE_DESCRIPTION("STM32 sigma delta ADC");
MODULE_AUTHOR("Arnaud Pouliquen <arnaud.pouliquen@st.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_BACKEND);
+MODULE_IMPORT_NS("IIO_BACKEND");
diff --git a/drivers/iio/adc/stm32-dfsdm-core.c b/drivers/iio/adc/stm32-dfsdm-core.c
index bef59fcc0d80..041dc9ebc048 100644
--- a/drivers/iio/adc/stm32-dfsdm-core.c
+++ b/drivers/iio/adc/stm32-dfsdm-core.c
@@ -506,7 +506,7 @@ static const struct dev_pm_ops stm32_dfsdm_core_pm_ops = {
static struct platform_driver stm32_dfsdm_driver = {
.probe = stm32_dfsdm_probe,
- .remove_new = stm32_dfsdm_core_remove,
+ .remove = stm32_dfsdm_core_remove,
.driver = {
.name = "stm32-dfsdm",
.of_match_table = stm32_dfsdm_of_match,
diff --git a/drivers/iio/adc/sun20i-gpadc-iio.c b/drivers/iio/adc/sun20i-gpadc-iio.c
index 6a893d484cf7..136b8d9c294f 100644
--- a/drivers/iio/adc/sun20i-gpadc-iio.c
+++ b/drivers/iio/adc/sun20i-gpadc-iio.c
@@ -155,7 +155,6 @@ static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
unsigned int channel;
int num_channels, i, ret;
struct iio_chan_spec *channels;
- struct fwnode_handle *node;
num_channels = device_get_child_node_count(dev);
if (num_channels == 0)
@@ -167,12 +166,10 @@ static int sun20i_gpadc_alloc_channels(struct iio_dev *indio_dev,
return -ENOMEM;
i = 0;
- device_for_each_child_node(dev, node) {
+ device_for_each_child_node_scoped(dev, node) {
ret = fwnode_property_read_u32(node, "reg", &channel);
- if (ret) {
- fwnode_handle_put(node);
+ if (ret)
return dev_err_probe(dev, ret, "invalid channel number\n");
- }
channels[i].type = IIO_VOLTAGE;
channels[i].indexed = 1;
diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
index 100ecced5fc1..8b27458dcd66 100644
--- a/drivers/iio/adc/sun4i-gpadc-iio.c
+++ b/drivers/iio/adc/sun4i-gpadc-iio.c
@@ -114,11 +114,8 @@ struct sun4i_gpadc_iio {
.datasheet_name = _name, \
}
-static struct iio_map sun4i_gpadc_hwmon_maps[] = {
- {
- .adc_channel_label = "temp_adc",
- .consumer_dev_name = "iio_hwmon.0",
- },
+static const struct iio_map sun4i_gpadc_hwmon_maps[] = {
+ IIO_MAP("temp_adc", "iio_hwmon.0", NULL),
{ /* sentinel */ },
};
@@ -700,7 +697,7 @@ static struct platform_driver sun4i_gpadc_driver = {
},
.id_table = sun4i_gpadc_id,
.probe = sun4i_gpadc_probe,
- .remove_new = sun4i_gpadc_remove,
+ .remove = sun4i_gpadc_remove,
};
MODULE_DEVICE_TABLE(of, sun4i_gpadc_of_id);
diff --git a/drivers/iio/adc/ti-ads1015.c b/drivers/iio/adc/ti-ads1015.c
index 6d1bc9659946..47fe8e16aee4 100644
--- a/drivers/iio/adc/ti-ads1015.c
+++ b/drivers/iio/adc/ti-ads1015.c
@@ -806,7 +806,7 @@ static int ads1015_disable_event_config(struct ads1015_data *data,
static int ads1015_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ads1015_data *data = iio_priv(indio_dev);
int ret;
@@ -1032,8 +1032,7 @@ static int ads1015_probe(struct i2c_client *client)
}
if (client->irq && chip->has_comparator) {
- unsigned long irq_trig =
- irqd_get_trigger_type(irq_get_irq_data(client->irq));
+ unsigned long irq_trig = irq_get_trigger_type(client->irq);
unsigned int cfg_comp_mask = ADS1015_CFG_COMP_QUE_MASK |
ADS1015_CFG_COMP_LAT_MASK | ADS1015_CFG_COMP_POL_MASK;
unsigned int cfg_comp =
diff --git a/drivers/iio/adc/ti-ads1119.c b/drivers/iio/adc/ti-ads1119.c
index 1c7606375149..e9d9d4d46d38 100644
--- a/drivers/iio/adc/ti-ads1119.c
+++ b/drivers/iio/adc/ti-ads1119.c
@@ -804,7 +804,7 @@ static const struct of_device_id __maybe_unused ads1119_of_match[] = {
MODULE_DEVICE_TABLE(of, ads1119_of_match);
static const struct i2c_device_id ads1119_id[] = {
- { "ads1119", 0 },
+ { "ads1119" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ads1119_id);
diff --git a/drivers/iio/adc/ti-ads1298.c b/drivers/iio/adc/ti-ads1298.c
index 0f9f75baaebb..36d43495f603 100644
--- a/drivers/iio/adc/ti-ads1298.c
+++ b/drivers/iio/adc/ti-ads1298.c
@@ -294,7 +294,7 @@ static int ads1298_get_scale(struct ads1298_private *priv,
if (ret)
return ret;
- /* Refererence in millivolts */
+ /* Reference in millivolts */
*val = regval & ADS1298_MASK_CONFIG3_VREF_4V ? 4000 : 2400;
}
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 426e3c9f88a1..fe1509d3b1e7 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -494,7 +494,7 @@ static int tiadc_read_raw(struct iio_dev *indio_dev,
/*
* We check the complete FIFO. We programmed just one entry but in case
* something went wrong we left empty handed (-EAGAIN previously) and
- * then the value apeared somehow in the FIFO we would have two entries.
+ * then the value appeared somehow in the FIFO we would have two entries.
* Therefore we read every item and keep only the latest version of the
* requested channel.
*/
@@ -740,12 +740,12 @@ MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);
static struct platform_driver tiadc_driver = {
.driver = {
- .name = "TI-am335x-adc",
- .pm = pm_sleep_ptr(&tiadc_pm_ops),
+ .name = "TI-am335x-adc",
+ .pm = pm_sleep_ptr(&tiadc_pm_ops),
.of_match_table = ti_adc_dt_ids,
},
- .probe = tiadc_probe,
- .remove_new = tiadc_remove,
+ .probe = tiadc_probe,
+ .remove = tiadc_remove,
};
module_platform_driver(tiadc_driver);
diff --git a/drivers/iio/adc/twl4030-madc.c b/drivers/iio/adc/twl4030-madc.c
index 0253064fadec..0ea51ddeaa0a 100644
--- a/drivers/iio/adc/twl4030-madc.c
+++ b/drivers/iio/adc/twl4030-madc.c
@@ -248,7 +248,7 @@ static const struct s16_fract twl4030_divider_ratios[16] = {
{15, 100}, /* CHANNEL 11 */
{1, 4}, /* CHANNEL 12 */
{1, 1}, /* CHANNEL 13 Reserved channels */
- {1, 1}, /* CHANNEL 14 Reseved channels */
+ {1, 1}, /* CHANNEL 14 Reserved channels */
{5, 11}, /* CHANNEL 15 */
};
@@ -914,7 +914,7 @@ MODULE_DEVICE_TABLE(of, twl_madc_of_match);
static struct platform_driver twl4030_madc_driver = {
.probe = twl4030_madc_probe,
- .remove_new = twl4030_madc_remove,
+ .remove = twl4030_madc_remove,
.driver = {
.name = "twl4030_madc",
.of_match_table = twl_madc_of_match,
diff --git a/drivers/iio/adc/twl6030-gpadc.c b/drivers/iio/adc/twl6030-gpadc.c
index 6a3db2bce460..ef7430e6877d 100644
--- a/drivers/iio/adc/twl6030-gpadc.c
+++ b/drivers/iio/adc/twl6030-gpadc.c
@@ -1003,7 +1003,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(twl6030_gpadc_pm_ops, twl6030_gpadc_suspend,
static struct platform_driver twl6030_gpadc_driver = {
.probe = twl6030_gpadc_probe,
- .remove_new = twl6030_gpadc_remove,
+ .remove = twl6030_gpadc_remove,
.driver = {
.name = DRIVER_NAME,
.pm = pm_sleep_ptr(&twl6030_gpadc_pm_ops),
diff --git a/drivers/iio/adc/vf610_adc.c b/drivers/iio/adc/vf610_adc.c
index 5afd2feb8c3d..4d83c12975c5 100644
--- a/drivers/iio/adc/vf610_adc.c
+++ b/drivers/iio/adc/vf610_adc.c
@@ -972,7 +972,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_adc_pm_ops, vf610_adc_suspend,
static struct platform_driver vf610_adc_driver = {
.probe = vf610_adc_probe,
- .remove_new = vf610_adc_remove,
+ .remove = vf610_adc_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = vf610_adc_match,
diff --git a/drivers/iio/adc/xilinx-ams.c b/drivers/iio/adc/xilinx-ams.c
index ebc583b07e0c..76dd0343f5f7 100644
--- a/drivers/iio/adc/xilinx-ams.c
+++ b/drivers/iio/adc/xilinx-ams.c
@@ -905,7 +905,7 @@ static int ams_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct ams *ams = iio_priv(indio_dev);
unsigned int alarm;
diff --git a/drivers/iio/adc/xilinx-xadc-events.c b/drivers/iio/adc/xilinx-xadc-events.c
index 1bd375fb10e0..c188d3dcab48 100644
--- a/drivers/iio/adc/xilinx-xadc-events.c
+++ b/drivers/iio/adc/xilinx-xadc-events.c
@@ -121,7 +121,7 @@ int xadc_read_event_config(struct iio_dev *indio_dev,
int xadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
unsigned int alarm = xadc_get_alarm_mask(chan);
struct xadc *xadc = iio_priv(indio_dev);
@@ -220,7 +220,7 @@ int xadc_write_event_value(struct iio_dev *indio_dev,
/*
* Since we store the hysteresis as relative (to the threshold)
* value, but the hardware expects an absolute value we need to
- * recalcualte this value whenever the hysteresis or the
+ * recalculate this value whenever the hysteresis or the
* threshold changes.
*/
if (xadc->threshold[offset] < xadc->temp_hysteresis)
diff --git a/drivers/iio/adc/xilinx-xadc.h b/drivers/iio/adc/xilinx-xadc.h
index 3036f4d613ff..b4d9d4683117 100644
--- a/drivers/iio/adc/xilinx-xadc.h
+++ b/drivers/iio/adc/xilinx-xadc.h
@@ -25,7 +25,7 @@ int xadc_read_event_config(struct iio_dev *indio_dev,
enum iio_event_direction dir);
int xadc_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state);
+ enum iio_event_direction dir, bool state);
int xadc_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
enum iio_event_direction dir, enum iio_event_info info,
diff --git a/drivers/iio/addac/ad74115.c b/drivers/iio/addac/ad74115.c
index 3ee0dd5537c1..a7e480f2472d 100644
--- a/drivers/iio/addac/ad74115.c
+++ b/drivers/iio/addac/ad74115.c
@@ -191,7 +191,7 @@ enum ad74115_gpio_mode {
};
struct ad74115_channels {
- struct iio_chan_spec *channels;
+ const struct iio_chan_spec *channels;
unsigned int num_channels;
};
@@ -1295,46 +1295,46 @@ static const struct iio_info ad74115_info = {
_AD74115_ADC_CHANNEL(_type, index, BIT(IIO_CHAN_INFO_SCALE) \
| BIT(IIO_CHAN_INFO_OFFSET))
-static struct iio_chan_spec ad74115_voltage_input_channels[] = {
+static const struct iio_chan_spec ad74115_voltage_input_channels[] = {
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_voltage_output_channels[] = {
+static const struct iio_chan_spec ad74115_voltage_output_channels[] = {
AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_MAIN),
AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_current_input_channels[] = {
+static const struct iio_chan_spec ad74115_current_input_channels[] = {
AD74115_ADC_CHANNEL(IIO_CURRENT, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_current_output_channels[] = {
+static const struct iio_chan_spec ad74115_current_output_channels[] = {
AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = {
+static const struct iio_chan_spec ad74115_2_wire_resistance_input_channels[] = {
_AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1,
BIT(IIO_CHAN_INFO_PROCESSED)),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = {
+static const struct iio_chan_spec ad74115_3_4_wire_resistance_input_channels[] = {
AD74115_ADC_CHANNEL(IIO_RESISTANCE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_digital_input_logic_channels[] = {
+static const struct iio_chan_spec ad74115_digital_input_logic_channels[] = {
AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV2),
};
-static struct iio_chan_spec ad74115_digital_input_loop_channels[] = {
+static const struct iio_chan_spec ad74115_digital_input_loop_channels[] = {
AD74115_DAC_CHANNEL(IIO_CURRENT, AD74115_DAC_CH_MAIN),
AD74115_DAC_CHANNEL(IIO_VOLTAGE, AD74115_DAC_CH_COMPARATOR),
AD74115_ADC_CHANNEL(IIO_VOLTAGE, AD74115_ADC_CH_CONV1),
diff --git a/drivers/iio/addac/ad74413r.c b/drivers/iio/addac/ad74413r.c
index 69c586525d21..daea2bde7acf 100644
--- a/drivers/iio/addac/ad74413r.c
+++ b/drivers/iio/addac/ad74413r.c
@@ -6,9 +6,11 @@
#include <linux/unaligned.h>
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/crc8.h>
#include <linux/device.h>
#include <linux/err.h>
+#include <linux/gpio/consumer.h>
#include <linux/gpio/driver.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
@@ -45,8 +47,8 @@ struct ad74413r_channel_config {
};
struct ad74413r_channels {
- struct iio_chan_spec *channels;
- unsigned int num_channels;
+ const struct iio_chan_spec *channels;
+ unsigned int num_channels;
};
struct ad74413r_state {
@@ -59,7 +61,7 @@ struct ad74413r_state {
unsigned int num_gpo_gpios;
unsigned int num_comparator_gpios;
u32 sense_resistor_ohms;
-
+ int refin_reg_uv;
/*
* Synchronize consecutive operations when doing a one-shot
* conversion and when updating the ADC samples SPI message.
@@ -68,11 +70,9 @@ struct ad74413r_state {
const struct ad74413r_chip_info *chip_info;
struct spi_device *spi;
- struct regulator *refin_reg;
struct regmap *regmap;
struct device *dev;
struct iio_trigger *trig;
- struct gpio_desc *reset_gpio;
size_t adc_active_channels;
struct spi_message adc_samples_msg;
@@ -407,12 +407,16 @@ static int ad74413r_gpio_set_comp_config(struct gpio_chip *chip,
static int ad74413r_reset(struct ad74413r_state *st)
{
+ struct gpio_desc *reset_gpio;
int ret;
- if (st->reset_gpio) {
- gpiod_set_value_cansleep(st->reset_gpio, 1);
+ reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(reset_gpio))
+ return PTR_ERR(reset_gpio);
+
+ if (reset_gpio) {
fsleep(50);
- gpiod_set_value_cansleep(st->reset_gpio, 0);
+ gpiod_set_value_cansleep(reset_gpio, 0);
return 0;
}
@@ -660,7 +664,7 @@ static int ad74413r_get_output_voltage_scale(struct ad74413r_state *st,
static int ad74413r_get_output_current_scale(struct ad74413r_state *st,
int *val, int *val2)
{
- *val = regulator_get_voltage(st->refin_reg);
+ *val = st->refin_reg_uv;
*val2 = st->sense_resistor_ohms * AD74413R_DAC_CODE_MAX * 1000;
return IIO_VAL_FRACTIONAL;
@@ -861,19 +865,12 @@ static int ad74413r_get_single_adc_result(struct iio_dev *indio_dev,
unsigned int channel, int *val)
{
struct ad74413r_state *st = iio_priv(indio_dev);
- int ret;
-
- ret = iio_device_claim_direct_mode(indio_dev);
- if (ret)
- return ret;
-
- mutex_lock(&st->lock);
- ret = _ad74413r_get_single_adc_result(st, channel, val);
- mutex_unlock(&st->lock);
-
- iio_device_release_direct_mode(indio_dev);
- return ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ guard(mutex)(&st->lock);
+ return _ad74413r_get_single_adc_result(st, channel, val);
+ }
+ unreachable();
}
static void ad74413r_adc_to_resistance_result(int adc_result, int *val)
@@ -895,7 +892,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
unsigned int channel;
int ret = -EINVAL;
- mutex_lock(&st->lock);
+ guard(mutex)(&st->lock);
spi_message_init(&st->adc_samples_msg);
st->adc_active_channels = 0;
@@ -903,11 +900,11 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
for_each_clear_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) {
ret = ad74413r_set_adc_channel_enable(st, channel, false);
if (ret)
- goto out;
+ return ret;
}
if (*active_scan_mask == 0)
- goto out;
+ return ret;
/*
* The read select register is used to select which register's value
@@ -925,7 +922,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
for_each_set_bit(channel, active_scan_mask, AD74413R_CHANNEL_MAX) {
ret = ad74413r_set_adc_channel_enable(st, channel, true);
if (ret)
- goto out;
+ return ret;
st->adc_active_channels++;
@@ -956,11 +953,7 @@ static int ad74413r_update_scan_mode(struct iio_dev *indio_dev,
xfer->cs_change = 0;
spi_message_add_tail(xfer, &st->adc_samples_msg);
-
-out:
- mutex_unlock(&st->lock);
-
- return ret;
+ return 0;
}
static int ad74413r_buffer_postenable(struct iio_dev *indio_dev)
@@ -1138,34 +1131,34 @@ static const struct iio_info ad74413r_info = {
AD74413R_ADC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE) \
| BIT(IIO_CHAN_INFO_OFFSET))
-static struct iio_chan_spec ad74413r_voltage_output_channels[] = {
+static const struct iio_chan_spec ad74413r_voltage_output_channels[] = {
AD74413R_DAC_CHANNEL(IIO_VOLTAGE, BIT(IIO_CHAN_INFO_SCALE)),
AD74413R_ADC_CURRENT_CHANNEL,
};
-static struct iio_chan_spec ad74413r_current_output_channels[] = {
+static const struct iio_chan_spec ad74413r_current_output_channels[] = {
AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)),
AD74413R_ADC_VOLTAGE_CHANNEL,
};
-static struct iio_chan_spec ad74413r_voltage_input_channels[] = {
+static const struct iio_chan_spec ad74413r_voltage_input_channels[] = {
AD74413R_ADC_VOLTAGE_CHANNEL,
};
-static struct iio_chan_spec ad74413r_current_input_channels[] = {
+static const struct iio_chan_spec ad74413r_current_input_channels[] = {
AD74413R_ADC_CURRENT_CHANNEL,
};
-static struct iio_chan_spec ad74413r_current_input_loop_channels[] = {
+static const struct iio_chan_spec ad74413r_current_input_loop_channels[] = {
AD74413R_DAC_CHANNEL(IIO_CURRENT, BIT(IIO_CHAN_INFO_SCALE)),
AD74413R_ADC_CURRENT_CHANNEL,
};
-static struct iio_chan_spec ad74413r_resistance_input_channels[] = {
+static const struct iio_chan_spec ad74413r_resistance_input_channels[] = {
AD74413R_ADC_CHANNEL(IIO_RESISTANCE, BIT(IIO_CHAN_INFO_PROCESSED)),
};
-static struct iio_chan_spec ad74413r_digital_input_channels[] = {
+static const struct iio_chan_spec ad74413r_digital_input_channels[] = {
AD74413R_ADC_VOLTAGE_CHANNEL,
};
@@ -1270,7 +1263,8 @@ static int ad74413r_setup_channels(struct iio_dev *indio_dev)
{
struct ad74413r_state *st = iio_priv(indio_dev);
struct ad74413r_channel_config *config;
- struct iio_chan_spec *channels, *chans;
+ const struct iio_chan_spec *chans;
+ struct iio_chan_spec *channels;
unsigned int i, num_chans, chan_i;
int ret;
@@ -1346,11 +1340,6 @@ static int ad74413r_setup_gpios(struct ad74413r_state *st)
return 0;
}
-static void ad74413r_regulator_disable(void *regulator)
-{
- regulator_disable(regulator);
-}
-
static int ad74413r_probe(struct spi_device *spi)
{
struct ad74413r_state *st;
@@ -1369,7 +1358,10 @@ static int ad74413r_probe(struct spi_device *spi)
if (!st->chip_info)
return -EINVAL;
- mutex_init(&st->lock);
+ ret = devm_mutex_init(st->dev, &st->lock);
+ if (ret)
+ return ret;
+
init_completion(&st->adc_data_completion);
st->regmap = devm_regmap_init(st->dev, NULL, st,
@@ -1377,23 +1369,11 @@ static int ad74413r_probe(struct spi_device *spi)
if (IS_ERR(st->regmap))
return PTR_ERR(st->regmap);
- st->reset_gpio = devm_gpiod_get_optional(st->dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(st->reset_gpio))
- return PTR_ERR(st->reset_gpio);
-
- st->refin_reg = devm_regulator_get(st->dev, "refin");
- if (IS_ERR(st->refin_reg))
- return dev_err_probe(st->dev, PTR_ERR(st->refin_reg),
- "Failed to get refin regulator\n");
-
- ret = regulator_enable(st->refin_reg);
- if (ret)
- return ret;
-
- ret = devm_add_action_or_reset(st->dev, ad74413r_regulator_disable,
- st->refin_reg);
- if (ret)
- return ret;
+ ret = devm_regulator_get_enable_read_voltage(st->dev, "refin");
+ if (ret < 0)
+ return dev_err_probe(st->dev, ret,
+ "Failed to get refin regulator voltage\n");
+ st->refin_reg_uv = ret;
st->sense_resistor_ohms = 100000000;
device_property_read_u32(st->dev, "shunt-resistor-micro-ohms",
diff --git a/drivers/iio/addac/stx104.c b/drivers/iio/addac/stx104.c
index 6946a65512ca..7bdf2cb94176 100644
--- a/drivers/iio/addac/stx104.c
+++ b/drivers/iio/addac/stx104.c
@@ -520,4 +520,4 @@ module_isa_driver(stx104_driver, num_stx104);
MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
MODULE_DESCRIPTION("Apex Embedded Systems STX104 IIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(I8254);
+MODULE_IMPORT_NS("I8254");
diff --git a/drivers/iio/afe/iio-rescale.c b/drivers/iio/afe/iio-rescale.c
index 56e5913ab82d..b6a46036d5ea 100644
--- a/drivers/iio/afe/iio-rescale.c
+++ b/drivers/iio/afe/iio-rescale.c
@@ -107,7 +107,7 @@ int rescale_process_scale(struct rescale *rescale, int scale_type,
return -EOPNOTSUPP;
}
}
-EXPORT_SYMBOL_NS_GPL(rescale_process_scale, IIO_RESCALE);
+EXPORT_SYMBOL_NS_GPL(rescale_process_scale, "IIO_RESCALE");
int rescale_process_offset(struct rescale *rescale, int scale_type,
int scale, int scale2, int schan_off,
@@ -141,7 +141,7 @@ int rescale_process_offset(struct rescale *rescale, int scale_type,
return -EOPNOTSUPP;
}
}
-EXPORT_SYMBOL_NS_GPL(rescale_process_offset, IIO_RESCALE);
+EXPORT_SYMBOL_NS_GPL(rescale_process_offset, "IIO_RESCALE");
static int rescale_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
diff --git a/drivers/iio/buffer/industrialio-buffer-dma.c b/drivers/iio/buffer/industrialio-buffer-dma.c
index dbde1443d6ed..7ea784304ffb 100644
--- a/drivers/iio/buffer/industrialio-buffer-dma.c
+++ b/drivers/iio/buffer/industrialio-buffer-dma.c
@@ -248,7 +248,7 @@ void iio_dma_buffer_block_done(struct iio_dma_buffer_block *block)
iio_dma_buffer_queue_wake(queue);
dma_fence_end_signalling(cookie);
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_block_done, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_block_done, "IIO_DMA_BUFFER");
/**
* iio_dma_buffer_block_list_abort() - Indicate that a list block has been
@@ -287,7 +287,7 @@ void iio_dma_buffer_block_list_abort(struct iio_dma_buffer_queue *queue,
iio_dma_buffer_queue_wake(queue);
dma_fence_end_signalling(cookie);
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_block_list_abort, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_block_list_abort, "IIO_DMA_BUFFER");
static bool iio_dma_block_reusable(struct iio_dma_buffer_block *block)
{
@@ -420,7 +420,7 @@ out_unlock:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_request_update, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_request_update, "IIO_DMA_BUFFER");
static void iio_dma_buffer_fileio_free(struct iio_dma_buffer_queue *queue)
{
@@ -506,7 +506,7 @@ int iio_dma_buffer_enable(struct iio_buffer *buffer,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_enable, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_enable, "IIO_DMA_BUFFER");
/**
* iio_dma_buffer_disable() - Disable DMA buffer
@@ -530,7 +530,7 @@ int iio_dma_buffer_disable(struct iio_buffer *buffer,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_disable, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_disable, "IIO_DMA_BUFFER");
static void iio_dma_buffer_enqueue(struct iio_dma_buffer_queue *queue,
struct iio_dma_buffer_block *block)
@@ -636,7 +636,7 @@ int iio_dma_buffer_read(struct iio_buffer *buffer, size_t n,
{
return iio_dma_buffer_io(buffer, n, user_buffer, false);
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_read, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_read, "IIO_DMA_BUFFER");
/**
* iio_dma_buffer_write() - DMA buffer write callback
@@ -653,7 +653,7 @@ int iio_dma_buffer_write(struct iio_buffer *buffer, size_t n,
return iio_dma_buffer_io(buffer, n,
(__force __user char *)user_buffer, true);
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_write, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_write, "IIO_DMA_BUFFER");
/**
* iio_dma_buffer_usage() - DMA buffer data_available and
@@ -696,7 +696,7 @@ size_t iio_dma_buffer_usage(struct iio_buffer *buf)
return data_available;
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_usage, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_usage, "IIO_DMA_BUFFER");
struct iio_dma_buffer_block *
iio_dma_buffer_attach_dmabuf(struct iio_buffer *buffer,
@@ -723,7 +723,7 @@ iio_dma_buffer_attach_dmabuf(struct iio_buffer *buffer,
return block;
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_attach_dmabuf, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_attach_dmabuf, "IIO_DMA_BUFFER");
void iio_dma_buffer_detach_dmabuf(struct iio_buffer *buffer,
struct iio_dma_buffer_block *block)
@@ -731,7 +731,7 @@ void iio_dma_buffer_detach_dmabuf(struct iio_buffer *buffer,
block->state = IIO_BLOCK_STATE_DEAD;
iio_buffer_block_put_atomic(block);
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_detach_dmabuf, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_detach_dmabuf, "IIO_DMA_BUFFER");
static int iio_dma_can_enqueue_block(struct iio_dma_buffer_block *block)
{
@@ -784,7 +784,7 @@ out_end_signalling:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_enqueue_dmabuf, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_enqueue_dmabuf, "IIO_DMA_BUFFER");
void iio_dma_buffer_lock_queue(struct iio_buffer *buffer)
{
@@ -792,7 +792,7 @@ void iio_dma_buffer_lock_queue(struct iio_buffer *buffer)
mutex_lock(&queue->lock);
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_lock_queue, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_lock_queue, "IIO_DMA_BUFFER");
void iio_dma_buffer_unlock_queue(struct iio_buffer *buffer)
{
@@ -800,7 +800,7 @@ void iio_dma_buffer_unlock_queue(struct iio_buffer *buffer)
mutex_unlock(&queue->lock);
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_unlock_queue, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_unlock_queue, "IIO_DMA_BUFFER");
/**
* iio_dma_buffer_set_bytes_per_datum() - DMA buffer set_bytes_per_datum callback
@@ -816,7 +816,7 @@ int iio_dma_buffer_set_bytes_per_datum(struct iio_buffer *buffer, size_t bpd)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_set_bytes_per_datum, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_set_bytes_per_datum, "IIO_DMA_BUFFER");
/**
* iio_dma_buffer_set_length - DMA buffer set_length callback
@@ -836,7 +836,7 @@ int iio_dma_buffer_set_length(struct iio_buffer *buffer, unsigned int length)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_set_length, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_set_length, "IIO_DMA_BUFFER");
/**
* iio_dma_buffer_init() - Initialize DMA buffer queue
@@ -864,7 +864,7 @@ int iio_dma_buffer_init(struct iio_dma_buffer_queue *queue,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_init, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_init, "IIO_DMA_BUFFER");
/**
* iio_dma_buffer_exit() - Cleanup DMA buffer queue
@@ -882,7 +882,7 @@ void iio_dma_buffer_exit(struct iio_dma_buffer_queue *queue)
mutex_unlock(&queue->lock);
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_exit, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_exit, "IIO_DMA_BUFFER");
/**
* iio_dma_buffer_release() - Release final buffer resources
@@ -896,7 +896,7 @@ void iio_dma_buffer_release(struct iio_dma_buffer_queue *queue)
{
mutex_destroy(&queue->lock);
}
-EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_release, IIO_DMA_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dma_buffer_release, "IIO_DMA_BUFFER");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("DMA buffer for the IIO framework");
diff --git a/drivers/iio/buffer/industrialio-buffer-dmaengine.c b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
index 19af1caf14cd..d2e1529ad8fd 100644
--- a/drivers/iio/buffer/industrialio-buffer-dmaengine.c
+++ b/drivers/iio/buffer/industrialio-buffer-dmaengine.c
@@ -286,7 +286,7 @@ void iio_dmaengine_buffer_free(struct iio_buffer *buffer)
iio_buffer_put(buffer);
}
-EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_free, IIO_DMAENGINE_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_free, "IIO_DMAENGINE_BUFFER");
struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev,
struct iio_dev *indio_dev,
@@ -312,7 +312,7 @@ struct iio_buffer *iio_dmaengine_buffer_setup_ext(struct device *dev,
return buffer;
}
-EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_setup_ext, IIO_DMAENGINE_BUFFER);
+EXPORT_SYMBOL_NS_GPL(iio_dmaengine_buffer_setup_ext, "IIO_DMAENGINE_BUFFER");
static void __devm_iio_dmaengine_buffer_free(void *buffer)
{
@@ -345,9 +345,9 @@ int devm_iio_dmaengine_buffer_setup_ext(struct device *dev,
return devm_add_action_or_reset(dev, __devm_iio_dmaengine_buffer_free,
buffer);
}
-EXPORT_SYMBOL_NS_GPL(devm_iio_dmaengine_buffer_setup_ext, IIO_DMAENGINE_BUFFER);
+EXPORT_SYMBOL_NS_GPL(devm_iio_dmaengine_buffer_setup_ext, "IIO_DMAENGINE_BUFFER");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("DMA buffer for the IIO framework");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_DMA_BUFFER);
+MODULE_IMPORT_NS("IIO_DMA_BUFFER");
diff --git a/drivers/iio/cdc/ad7150.c b/drivers/iio/cdc/ad7150.c
index 4c03b9e834b8..e64a41bae32c 100644
--- a/drivers/iio/cdc/ad7150.c
+++ b/drivers/iio/cdc/ad7150.c
@@ -232,7 +232,7 @@ static int ad7150_write_event_params(struct iio_dev *indio_dev,
static int ad7150_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ad7150_chip_info *chip = iio_priv(indio_dev);
int ret = 0;
diff --git a/drivers/iio/chemical/Kconfig b/drivers/iio/chemical/Kconfig
index 6c87223f58d9..330fe0af946f 100644
--- a/drivers/iio/chemical/Kconfig
+++ b/drivers/iio/chemical/Kconfig
@@ -50,6 +50,8 @@ config BME680
select REGMAP
select BME680_I2C if I2C
select BME680_SPI if SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
Say yes here to build support for Bosch Sensortec BME680 sensor with
temperature, pressure, humidity and gas sensing capability.
diff --git a/drivers/iio/chemical/bme680.h b/drivers/iio/chemical/bme680.h
index b2c547ac8d34..00ab89b3138b 100644
--- a/drivers/iio/chemical/bme680.h
+++ b/drivers/iio/chemical/bme680.h
@@ -2,6 +2,8 @@
#ifndef BME680_H_
#define BME680_H_
+#include <linux/regmap.h>
+
#define BME680_REG_CHIP_ID 0xD0
#define BME680_CHIP_ID_VAL 0x61
#define BME680_REG_SOFT_RESET 0xE0
@@ -25,8 +27,6 @@
#define BME680_OSRS_TEMP_MASK GENMASK(7, 5)
#define BME680_OSRS_PRESS_MASK GENMASK(4, 2)
#define BME680_MODE_MASK GENMASK(1, 0)
-#define BME680_MODE_FORCED 1
-#define BME680_MODE_SLEEP 0
#define BME680_REG_CONFIG 0x75
#define BME680_FILTER_MASK GENMASK(4, 2)
@@ -42,6 +42,7 @@
#define BME680_RHRANGE_MASK GENMASK(5, 4)
#define BME680_REG_RES_HEAT_VAL 0x00
#define BME680_RSERROR_MASK GENMASK(7, 4)
+#define BME680_REG_IDAC_HEAT_0 0x50
#define BME680_REG_RES_HEAT_0 0x5A
#define BME680_REG_GAS_WAIT_0 0x64
#define BME680_ADC_GAS_RES GENMASK(15, 6)
@@ -63,7 +64,11 @@
#define BME680_MEAS_TRIM_MASK GENMASK(24, 4)
-#define BME680_STARTUP_TIME_US 5000
+/* Datasheet Section 1.1, Table 1 */
+#define BME680_STARTUP_TIME_US 2000
+
+#define BME680_NUM_CHANNELS 4
+#define BME680_NUM_BULK_READ_REGS 15
/* Calibration Parameters */
#define BME680_T2_LSB_REG 0x8A
diff --git a/drivers/iio/chemical/bme680_core.c b/drivers/iio/chemical/bme680_core.c
index 0b96534c6867..d12270409c8a 100644
--- a/drivers/iio/chemical/bme680_core.c
+++ b/drivers/iio/chemical/bme680_core.c
@@ -16,8 +16,11 @@
#include <linux/module.h>
#include <linux/regmap.h>
+#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#include <linux/unaligned.h>
@@ -95,6 +98,19 @@ struct bme680_calib {
s8 range_sw_err;
};
+/* values of CTRL_MEAS register */
+enum bme680_op_mode {
+ BME680_MODE_SLEEP = 0,
+ BME680_MODE_FORCED = 1,
+};
+
+enum bme680_scan {
+ BME680_TEMP,
+ BME680_PRESS,
+ BME680_HUMID,
+ BME680_GAS,
+};
+
struct bme680_data {
struct regmap *regmap;
struct bme680_calib bme680;
@@ -102,11 +118,17 @@ struct bme680_data {
u8 oversampling_temp;
u8 oversampling_press;
u8 oversampling_humid;
+ u8 preheat_curr_mA;
u16 heater_dur;
u16 heater_temp;
+ struct {
+ s32 chan[4];
+ aligned_s64 ts;
+ } scan;
+
union {
- u8 buf[3];
+ u8 buf[BME680_NUM_BULK_READ_REGS];
unsigned int check;
__be16 be16;
u8 bme680_cal_buf_1[BME680_CALIB_RANGE_1_LEN];
@@ -133,27 +155,71 @@ const struct regmap_config bme680_regmap_config = {
.volatile_table = &bme680_volatile_table,
.cache_type = REGCACHE_RBTREE,
};
-EXPORT_SYMBOL_NS(bme680_regmap_config, IIO_BME680);
+EXPORT_SYMBOL_NS(bme680_regmap_config, "IIO_BME680");
static const struct iio_chan_spec bme680_channels[] = {
{
.type = IIO_TEMP,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_PRESSURE,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_HUMIDITYRELATIVE,
+ /* PROCESSED maintained for ABI backwards compatibility */
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
BIT(IIO_CHAN_INFO_OVERSAMPLING_RATIO),
+ .scan_index = 2,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
},
{
.type = IIO_RESISTANCE,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .scan_index = 3,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 32,
+ .storagebits = 32,
+ .endianness = IIO_CPU,
+ },
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+ {
+ .type = IIO_CURRENT,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .output = 1,
+ .scan_index = -1,
},
};
@@ -224,7 +290,7 @@ static int bme680_read_calib(struct bme680_data *data,
calib->res_heat_val = data->bme680_cal_buf_3[RES_HEAT_VAL];
calib->res_heat_range = FIELD_GET(BME680_RHRANGE_MASK,
- data->bme680_cal_buf_3[RES_HEAT_RANGE]);
+ data->bme680_cal_buf_3[RES_HEAT_RANGE]);
calib->range_sw_err = FIELD_GET(BME680_RSERROR_MASK,
data->bme680_cal_buf_3[RANGE_SW_ERR]);
@@ -438,19 +504,19 @@ static u32 bme680_compensate_gas(struct bme680_data *data, u16 gas_res_adc,
u32 calc_gas_res;
/* Look up table for the possible gas range values */
- static const u32 lookupTable[16] = {2147483647u, 2147483647u,
- 2147483647u, 2147483647u, 2147483647u,
- 2126008810u, 2147483647u, 2130303777u,
- 2147483647u, 2147483647u, 2143188679u,
- 2136746228u, 2147483647u, 2126008810u,
- 2147483647u, 2147483647u};
-
- var1 = ((1340 + (5 * (s64) calib->range_sw_err)) *
- ((s64) lookupTable[gas_range])) >> 16;
+ static const u32 lookup_table[16] = {
+ 2147483647u, 2147483647u, 2147483647u, 2147483647u,
+ 2147483647u, 2126008810u, 2147483647u, 2130303777u,
+ 2147483647u, 2147483647u, 2143188679u, 2136746228u,
+ 2147483647u, 2126008810u, 2147483647u, 2147483647u
+ };
+
+ var1 = ((1340LL + (5 * calib->range_sw_err)) *
+ (lookup_table[gas_range])) >> 16;
var2 = ((gas_res_adc << 15) - 16777216) + var1;
var3 = ((125000 << (15 - gas_range)) * var1) >> 9;
var3 += (var2 >> 1);
- calc_gas_res = div64_s64(var3, (s64) var2);
+ calc_gas_res = div64_s64(var3, (s64)var2);
return calc_gas_res;
}
@@ -468,7 +534,7 @@ static u8 bme680_calc_heater_res(struct bme680_data *data, u16 temp)
if (temp > 400) /* Cap temperature */
temp = 400;
- var1 = (((s32) BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256;
+ var1 = (((s32)BME680_AMB_TEMP * calib->par_gh3) / 1000) * 256;
var2 = (calib->par_gh1 + 784) * (((((calib->par_gh2 + 154009) *
temp * 5) / 100)
+ 3276800) / 10);
@@ -502,23 +568,22 @@ static u8 bme680_calc_heater_dur(u16 dur)
return durval;
}
-static int bme680_set_mode(struct bme680_data *data, bool mode)
+/* Taken from datasheet, section 5.3.3 */
+static u8 bme680_calc_heater_preheat_current(u8 curr)
+{
+ return 8 * curr - 1;
+}
+
+static int bme680_set_mode(struct bme680_data *data, enum bme680_op_mode mode)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
- if (mode) {
- ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
- BME680_MODE_MASK, BME680_MODE_FORCED);
- if (ret < 0)
- dev_err(dev, "failed to set forced mode\n");
-
- } else {
- ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
- BME680_MODE_MASK, BME680_MODE_SLEEP);
- if (ret < 0)
- dev_err(dev, "failed to set sleep mode\n");
-
+ ret = regmap_write_bits(data->regmap, BME680_REG_CTRL_MEAS,
+ BME680_MODE_MASK, mode);
+ if (ret < 0) {
+ dev_err(dev, "failed to set ctrl_meas register\n");
+ return ret;
}
return ret;
@@ -546,7 +611,7 @@ static int bme680_wait_for_eoc(struct bme680_data *data)
data->oversampling_humid) * 1936) + (477 * 4) +
(477 * 5) + 1000 + (data->heater_dur * 1000);
- usleep_range(wait_eoc_us, wait_eoc_us + 100);
+ fsleep(wait_eoc_us);
ret = regmap_read(data->regmap, BME680_REG_MEAS_STAT_0, &data->check);
if (ret) {
@@ -571,9 +636,8 @@ static int bme680_chip_config(struct bme680_data *data)
int ret;
u8 osrs;
- osrs = FIELD_PREP(
- BME680_OSRS_HUMIDITY_MASK,
- bme680_oversampling_to_reg(data->oversampling_humid));
+ osrs = FIELD_PREP(BME680_OSRS_HUMIDITY_MASK,
+ bme680_oversampling_to_reg(data->oversampling_humid));
/*
* Highly recommended to set oversampling of humidity before
* temperature/pressure oversampling.
@@ -587,8 +651,7 @@ static int bme680_chip_config(struct bme680_data *data)
/* IIR filter settings */
ret = regmap_update_bits(data->regmap, BME680_REG_CONFIG,
- BME680_FILTER_MASK,
- BME680_FILTER_COEFF_VAL);
+ BME680_FILTER_MASK, BME680_FILTER_COEFF_VAL);
if (ret < 0) {
dev_err(dev, "failed to write config register\n");
return ret;
@@ -609,14 +672,27 @@ static int bme680_chip_config(struct bme680_data *data)
return 0;
}
+static int bme680_preheat_curr_config(struct bme680_data *data, u8 val)
+{
+ struct device *dev = regmap_get_device(data->regmap);
+ u8 heatr_curr;
+ int ret;
+
+ heatr_curr = bme680_calc_heater_preheat_current(val);
+ ret = regmap_write(data->regmap, BME680_REG_IDAC_HEAT_0, heatr_curr);
+ if (ret < 0)
+ dev_err(dev, "failed to write idac_heat_0 register\n");
+
+ return ret;
+}
+
static int bme680_gas_config(struct bme680_data *data)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
u8 heatr_res, heatr_dur;
- /* Go to sleep */
- ret = bme680_set_mode(data, false);
+ ret = bme680_set_mode(data, BME680_MODE_SLEEP);
if (ret < 0)
return ret;
@@ -638,6 +714,10 @@ static int bme680_gas_config(struct bme680_data *data)
return ret;
}
+ ret = bme680_preheat_curr_config(data, data->preheat_curr_mA);
+ if (ret)
+ return ret;
+
/* Enable the gas sensor and select heater profile set-point 0 */
ret = regmap_update_bits(data->regmap, BME680_REG_CTRL_GAS_1,
BME680_RUN_GAS_MASK | BME680_NB_CONV_MASK,
@@ -649,23 +729,20 @@ static int bme680_gas_config(struct bme680_data *data)
return ret;
}
-static int bme680_read_temp(struct bme680_data *data, int *val)
+static int bme680_read_temp(struct bme680_data *data, s16 *comp_temp)
{
int ret;
u32 adc_temp;
- s16 comp_temp;
ret = bme680_read_temp_adc(data, &adc_temp);
if (ret)
return ret;
- comp_temp = bme680_compensate_temp(data, adc_temp);
- *val = comp_temp * 10; /* Centidegrees to millidegrees */
- return IIO_VAL_INT;
+ *comp_temp = bme680_compensate_temp(data, adc_temp);
+ return 0;
}
-static int bme680_read_press(struct bme680_data *data,
- int *val, int *val2)
+static int bme680_read_press(struct bme680_data *data, u32 *comp_press)
{
int ret;
u32 adc_press;
@@ -679,16 +756,14 @@ static int bme680_read_press(struct bme680_data *data,
if (ret)
return ret;
- *val = bme680_compensate_press(data, adc_press, t_fine);
- *val2 = 1000;
- return IIO_VAL_FRACTIONAL;
+ *comp_press = bme680_compensate_press(data, adc_press, t_fine);
+ return 0;
}
-static int bme680_read_humid(struct bme680_data *data,
- int *val, int *val2)
+static int bme680_read_humid(struct bme680_data *data, u32 *comp_humidity)
{
int ret;
- u32 adc_humidity, comp_humidity;
+ u32 adc_humidity;
s32 t_fine;
ret = bme680_get_t_fine(data, &t_fine);
@@ -699,15 +774,11 @@ static int bme680_read_humid(struct bme680_data *data,
if (ret)
return ret;
- comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine);
-
- *val = comp_humidity;
- *val2 = 1000;
- return IIO_VAL_FRACTIONAL;
+ *comp_humidity = bme680_compensate_humid(data, adc_humidity, t_fine);
+ return 0;
}
-static int bme680_read_gas(struct bme680_data *data,
- int *val)
+static int bme680_read_gas(struct bme680_data *data, int *comp_gas_res)
{
struct device *dev = regmap_get_device(data->regmap);
int ret;
@@ -742,9 +813,8 @@ static int bme680_read_gas(struct bme680_data *data,
}
gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val);
-
- *val = bme680_compensate_gas(data, adc_gas_res, gas_range);
- return IIO_VAL_INT;
+ *comp_gas_res = bme680_compensate_gas(data, adc_gas_res, gas_range);
+ return 0;
}
static int bme680_read_raw(struct iio_dev *indio_dev,
@@ -752,12 +822,12 @@ static int bme680_read_raw(struct iio_dev *indio_dev,
int *val, int *val2, long mask)
{
struct bme680_data *data = iio_priv(indio_dev);
- int ret;
+ int chan_val, ret;
+ s16 temp_chan_val;
guard(mutex)(&data->lock);
- /* set forced mode to trigger measurement */
- ret = bme680_set_mode(data, true);
+ ret = bme680_set_mode(data, BME680_MODE_FORCED);
if (ret < 0)
return ret;
@@ -769,13 +839,77 @@ static int bme680_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_PROCESSED:
switch (chan->type) {
case IIO_TEMP:
- return bme680_read_temp(data, val);
+ ret = bme680_read_temp(data, &temp_chan_val);
+ if (ret)
+ return ret;
+
+ *val = temp_chan_val * 10;
+ return IIO_VAL_INT;
case IIO_PRESSURE:
- return bme680_read_press(data, val, val2);
+ ret = bme680_read_press(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
case IIO_HUMIDITYRELATIVE:
- return bme680_read_humid(data, val, val2);
+ ret = bme680_read_humid(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
case IIO_RESISTANCE:
- return bme680_read_gas(data, val);
+ ret = bme680_read_gas(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_TEMP:
+ ret = bme680_read_temp(data, (s16 *)&chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ case IIO_PRESSURE:
+ ret = bme680_read_press(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ case IIO_HUMIDITYRELATIVE:
+ ret = bme680_read_humid(data, &chan_val);
+ if (ret)
+ return ret;
+
+ *val = chan_val;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = 10;
+ return IIO_VAL_INT;
+ case IIO_PRESSURE:
+ *val = 1;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_HUMIDITYRELATIVE:
+ *val = 1;
+ *val2 = 1000;
+ return IIO_VAL_FRACTIONAL;
default:
return -EINVAL;
}
@@ -836,6 +970,15 @@ static int bme680_write_raw(struct iio_dev *indio_dev,
return bme680_chip_config(data);
}
+ case IIO_CHAN_INFO_PROCESSED:
+ {
+ switch (chan->type) {
+ case IIO_CURRENT:
+ return bme680_preheat_curr_config(data, (u8)val);
+ default:
+ return -EINVAL;
+ }
+ }
default:
return -EINVAL;
}
@@ -861,6 +1004,86 @@ static const struct iio_info bme680_info = {
.attrs = &bme680_attribute_group,
};
+static const unsigned long bme680_avail_scan_masks[] = {
+ BIT(BME680_GAS) | BIT(BME680_HUMID) | BIT(BME680_PRESS) | BIT(BME680_TEMP),
+ 0
+};
+
+static irqreturn_t bme680_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct bme680_data *data = iio_priv(indio_dev);
+ struct device *dev = regmap_get_device(data->regmap);
+ u32 adc_temp, adc_press, adc_humid;
+ u16 adc_gas_res, gas_regs_val;
+ u8 gas_range;
+ s32 t_fine;
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = bme680_set_mode(data, BME680_MODE_FORCED);
+ if (ret < 0)
+ goto out;
+
+ ret = bme680_wait_for_eoc(data);
+ if (ret)
+ goto out;
+
+ ret = regmap_bulk_read(data->regmap, BME680_REG_MEAS_STAT_0,
+ data->buf, sizeof(data->buf));
+ if (ret) {
+ dev_err(dev, "failed to burst read sensor data\n");
+ goto out;
+ }
+ if (data->buf[0] & BME680_GAS_MEAS_BIT) {
+ dev_err(dev, "gas measurement incomplete\n");
+ goto out;
+ }
+
+ /* Temperature calculations */
+ adc_temp = FIELD_GET(BME680_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[5]));
+ if (adc_temp == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading temperature skipped\n");
+ goto out;
+ }
+ data->scan.chan[0] = bme680_compensate_temp(data, adc_temp);
+ t_fine = bme680_calc_t_fine(data, adc_temp);
+
+ /* Pressure calculations */
+ adc_press = FIELD_GET(BME680_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[2]));
+ if (adc_press == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading pressure skipped\n");
+ goto out;
+ }
+ data->scan.chan[1] = bme680_compensate_press(data, adc_press, t_fine);
+
+ /* Humidity calculations */
+ adc_humid = get_unaligned_be16(&data->buf[8]);
+ if (adc_humid == BME680_MEAS_SKIPPED) {
+ dev_err(dev, "reading humidity skipped\n");
+ goto out;
+ }
+ data->scan.chan[2] = bme680_compensate_humid(data, adc_humid, t_fine);
+
+ /* Gas calculations */
+ gas_regs_val = get_unaligned_be16(&data->buf[13]);
+ adc_gas_res = FIELD_GET(BME680_ADC_GAS_RES, gas_regs_val);
+ if ((gas_regs_val & BME680_GAS_STAB_BIT) == 0) {
+ dev_err(dev, "heater failed to reach the target temperature\n");
+ goto out;
+ }
+ gas_range = FIELD_GET(BME680_GAS_RANGE_MASK, gas_regs_val);
+ data->scan.chan[3] = bme680_compensate_gas(data, adc_gas_res, gas_range);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+ iio_get_time_ns(indio_dev));
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
int bme680_core_probe(struct device *dev, struct regmap *regmap,
const char *name)
{
@@ -879,6 +1102,7 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
indio_dev->name = name;
indio_dev->channels = bme680_channels;
indio_dev->num_channels = ARRAY_SIZE(bme680_channels);
+ indio_dev->available_scan_masks = bme680_avail_scan_masks;
indio_dev->info = &bme680_info;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -888,13 +1112,13 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
data->oversampling_temp = 8; /* 8X oversampling rate */
data->heater_temp = 320; /* degree Celsius */
data->heater_dur = 150; /* milliseconds */
+ data->preheat_curr_mA = 0;
- ret = regmap_write(regmap, BME680_REG_SOFT_RESET,
- BME680_CMD_SOFTRESET);
+ ret = regmap_write(regmap, BME680_REG_SOFT_RESET, BME680_CMD_SOFTRESET);
if (ret < 0)
return dev_err_probe(dev, ret, "Failed to reset chip\n");
- usleep_range(BME680_STARTUP_TIME_US, BME680_STARTUP_TIME_US + 1000);
+ fsleep(BME680_STARTUP_TIME_US);
ret = regmap_read(regmap, BME680_REG_CHIP_ID, &data->check);
if (ret < 0)
@@ -922,9 +1146,17 @@ int bme680_core_probe(struct device *dev, struct regmap *regmap,
return dev_err_probe(dev, ret,
"failed to set gas config data\n");
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ bme680_trigger_handler,
+ NULL);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "iio triggered buffer setup failed\n");
+
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(bme680_core_probe, IIO_BME680);
+EXPORT_SYMBOL_NS_GPL(bme680_core_probe, "IIO_BME680");
MODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>");
MODULE_DESCRIPTION("Bosch BME680 Driver");
diff --git a/drivers/iio/chemical/bme680_i2c.c b/drivers/iio/chemical/bme680_i2c.c
index 7c4224d75955..7a949228b4a6 100644
--- a/drivers/iio/chemical/bme680_i2c.c
+++ b/drivers/iio/chemical/bme680_i2c.c
@@ -60,4 +60,4 @@ module_i2c_driver(bme680_i2c_driver);
MODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>");
MODULE_DESCRIPTION("BME680 I2C driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_BME680);
+MODULE_IMPORT_NS("IIO_BME680");
diff --git a/drivers/iio/chemical/bme680_spi.c b/drivers/iio/chemical/bme680_spi.c
index 7c54bd17d4b0..3916a51ba68e 100644
--- a/drivers/iio/chemical/bme680_spi.c
+++ b/drivers/iio/chemical/bme680_spi.c
@@ -163,4 +163,4 @@ module_spi_driver(bme680_spi_driver);
MODULE_AUTHOR("Himanshu Jha <himanshujha199640@gmail.com>");
MODULE_DESCRIPTION("Bosch BME680 SPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_BME680);
+MODULE_IMPORT_NS("IIO_BME680");
diff --git a/drivers/iio/chemical/ens160_core.c b/drivers/iio/chemical/ens160_core.c
index c1aa3b498d3b..4a89cd5894d9 100644
--- a/drivers/iio/chemical/ens160_core.c
+++ b/drivers/iio/chemical/ens160_core.c
@@ -360,7 +360,7 @@ int devm_ens160_core_probe(struct device *dev, struct regmap *regmap, int irq,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS(devm_ens160_core_probe, IIO_ENS160);
+EXPORT_SYMBOL_NS(devm_ens160_core_probe, "IIO_ENS160");
MODULE_AUTHOR("Gustavo Silva <gustavograzs@gmail.com>");
MODULE_DESCRIPTION("ScioSense ENS160 driver");
diff --git a/drivers/iio/chemical/ens160_i2c.c b/drivers/iio/chemical/ens160_i2c.c
index 57a189a4c257..aa0dfe639245 100644
--- a/drivers/iio/chemical/ens160_i2c.c
+++ b/drivers/iio/chemical/ens160_i2c.c
@@ -59,4 +59,4 @@ module_i2c_driver(ens160_i2c_driver);
MODULE_AUTHOR("Gustavo Silva <gustavograzs@gmail.com>");
MODULE_DESCRIPTION("ScioSense ENS160 I2C driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ENS160);
+MODULE_IMPORT_NS("IIO_ENS160");
diff --git a/drivers/iio/chemical/ens160_spi.c b/drivers/iio/chemical/ens160_spi.c
index 10e4f5fd0f45..a674c0e1bf4b 100644
--- a/drivers/iio/chemical/ens160_spi.c
+++ b/drivers/iio/chemical/ens160_spi.c
@@ -58,4 +58,4 @@ module_spi_driver(ens160_spi_driver);
MODULE_AUTHOR("Gustavo Silva <gustavograzs@gmail.com>");
MODULE_DESCRIPTION("ScioSense ENS160 SPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ENS160);
+MODULE_IMPORT_NS("IIO_ENS160");
diff --git a/drivers/iio/chemical/scd30_core.c b/drivers/iio/chemical/scd30_core.c
index 7be5a45cf71a..ac3080929f0b 100644
--- a/drivers/iio/chemical/scd30_core.c
+++ b/drivers/iio/chemical/scd30_core.c
@@ -747,7 +747,7 @@ int scd30_probe(struct device *dev, int irq, const char *name, void *priv,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS(scd30_probe, IIO_SCD30);
+EXPORT_SYMBOL_NS(scd30_probe, "IIO_SCD30");
MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");
MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor core driver");
diff --git a/drivers/iio/chemical/scd30_i2c.c b/drivers/iio/chemical/scd30_i2c.c
index b31dfaf52df9..436df9c61a71 100644
--- a/drivers/iio/chemical/scd30_i2c.c
+++ b/drivers/iio/chemical/scd30_i2c.c
@@ -137,4 +137,4 @@ module_i2c_driver(scd30_i2c_driver);
MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");
MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_SCD30);
+MODULE_IMPORT_NS("IIO_SCD30");
diff --git a/drivers/iio/chemical/scd30_serial.c b/drivers/iio/chemical/scd30_serial.c
index 55044f07d5a3..e8b453aae859 100644
--- a/drivers/iio/chemical/scd30_serial.c
+++ b/drivers/iio/chemical/scd30_serial.c
@@ -261,4 +261,4 @@ module_serdev_device_driver(scd30_serdev_driver);
MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");
MODULE_DESCRIPTION("Sensirion SCD30 carbon dioxide sensor serial driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_SCD30);
+MODULE_IMPORT_NS("IIO_SCD30");
diff --git a/drivers/iio/chemical/sps30.c b/drivers/iio/chemical/sps30.c
index 814ce0aad1cc..6f4f2ba2c09d 100644
--- a/drivers/iio/chemical/sps30.c
+++ b/drivers/iio/chemical/sps30.c
@@ -372,7 +372,7 @@ int sps30_probe(struct device *dev, const char *name, void *priv, const struct s
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(sps30_probe, IIO_SPS30);
+EXPORT_SYMBOL_NS_GPL(sps30_probe, "IIO_SPS30");
MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor driver");
diff --git a/drivers/iio/chemical/sps30_i2c.c b/drivers/iio/chemical/sps30_i2c.c
index 1b21b6bcd0e7..f692c089d17b 100644
--- a/drivers/iio/chemical/sps30_i2c.c
+++ b/drivers/iio/chemical/sps30_i2c.c
@@ -256,4 +256,4 @@ module_i2c_driver(sps30_i2c_driver);
MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");
MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_SPS30);
+MODULE_IMPORT_NS("IIO_SPS30");
diff --git a/drivers/iio/chemical/sps30_serial.c b/drivers/iio/chemical/sps30_serial.c
index a6dfbe28c914..008bc88590f3 100644
--- a/drivers/iio/chemical/sps30_serial.c
+++ b/drivers/iio/chemical/sps30_serial.c
@@ -429,4 +429,4 @@ module_serdev_device_driver(sps30_serial_driver);
MODULE_AUTHOR("Tomasz Duszynski <tomasz.duszynski@octakon.com>");
MODULE_DESCRIPTION("Sensirion SPS30 particulate matter sensor serial driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_SPS30);
+MODULE_IMPORT_NS("IIO_SPS30");
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
index 9b279937a24e..ad1882f608c0 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-attributes.c
@@ -169,7 +169,7 @@ s32 hid_sensor_read_poll_value(struct hid_sensor_common *st)
return value;
}
-EXPORT_SYMBOL_NS(hid_sensor_read_poll_value, IIO_HID_ATTRIBUTES);
+EXPORT_SYMBOL_NS(hid_sensor_read_poll_value, "IIO_HID_ATTRIBUTES");
int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st,
int *val1, int *val2)
@@ -196,7 +196,7 @@ int hid_sensor_read_samp_freq_value(struct hid_sensor_common *st,
return IIO_VAL_INT_PLUS_MICRO;
}
-EXPORT_SYMBOL_NS(hid_sensor_read_samp_freq_value, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_read_samp_freq_value, "IIO_HID");
int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st,
int val1, int val2)
@@ -231,7 +231,7 @@ int hid_sensor_write_samp_freq_value(struct hid_sensor_common *st,
return 0;
}
-EXPORT_SYMBOL_NS(hid_sensor_write_samp_freq_value, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_write_samp_freq_value, "IIO_HID");
int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st,
int *val1, int *val2)
@@ -254,7 +254,7 @@ int hid_sensor_read_raw_hyst_value(struct hid_sensor_common *st,
return IIO_VAL_INT_PLUS_MICRO;
}
-EXPORT_SYMBOL_NS(hid_sensor_read_raw_hyst_value, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_read_raw_hyst_value, "IIO_HID");
int hid_sensor_read_raw_hyst_rel_value(struct hid_sensor_common *st, int *val1,
int *val2)
@@ -276,7 +276,7 @@ int hid_sensor_read_raw_hyst_rel_value(struct hid_sensor_common *st, int *val1,
return IIO_VAL_INT_PLUS_MICRO;
}
-EXPORT_SYMBOL_NS(hid_sensor_read_raw_hyst_rel_value, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_read_raw_hyst_rel_value, "IIO_HID");
int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st,
@@ -308,7 +308,7 @@ int hid_sensor_write_raw_hyst_value(struct hid_sensor_common *st,
return 0;
}
-EXPORT_SYMBOL_NS(hid_sensor_write_raw_hyst_value, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_write_raw_hyst_value, "IIO_HID");
int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st,
int val1, int val2)
@@ -339,7 +339,7 @@ int hid_sensor_write_raw_hyst_rel_value(struct hid_sensor_common *st,
return 0;
}
-EXPORT_SYMBOL_NS(hid_sensor_write_raw_hyst_rel_value, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_write_raw_hyst_rel_value, "IIO_HID");
/*
* This fuction applies the unit exponent to the scale.
@@ -423,14 +423,14 @@ int hid_sensor_format_scale(u32 usage_id,
return IIO_VAL_INT_PLUS_NANO;
}
-EXPORT_SYMBOL_NS(hid_sensor_format_scale, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_format_scale, "IIO_HID");
int64_t hid_sensor_convert_timestamp(struct hid_sensor_common *st,
int64_t raw_value)
{
return st->timestamp_ns_scale * raw_value;
}
-EXPORT_SYMBOL_NS(hid_sensor_convert_timestamp, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_convert_timestamp, "IIO_HID");
static
int hid_sensor_get_reporting_interval(struct hid_sensor_hub_device *hsdev,
@@ -477,7 +477,7 @@ int hid_sensor_get_report_latency(struct hid_sensor_common *st)
return value;
}
-EXPORT_SYMBOL_NS(hid_sensor_get_report_latency, IIO_HID_ATTRIBUTES);
+EXPORT_SYMBOL_NS(hid_sensor_get_report_latency, "IIO_HID_ATTRIBUTES");
int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms)
{
@@ -485,13 +485,13 @@ int hid_sensor_set_report_latency(struct hid_sensor_common *st, int latency_ms)
st->report_latency.index,
sizeof(latency_ms), &latency_ms);
}
-EXPORT_SYMBOL_NS(hid_sensor_set_report_latency, IIO_HID_ATTRIBUTES);
+EXPORT_SYMBOL_NS(hid_sensor_set_report_latency, "IIO_HID_ATTRIBUTES");
bool hid_sensor_batch_mode_supported(struct hid_sensor_common *st)
{
return st->report_latency.index > 0 && st->report_latency.report_id > 0;
}
-EXPORT_SYMBOL_NS(hid_sensor_batch_mode_supported, IIO_HID_ATTRIBUTES);
+EXPORT_SYMBOL_NS(hid_sensor_batch_mode_supported, "IIO_HID_ATTRIBUTES");
int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
u32 usage_id,
@@ -583,7 +583,7 @@ int hid_sensor_parse_common_attributes(struct hid_sensor_hub_device *hsdev,
return 0;
}
-EXPORT_SYMBOL_NS(hid_sensor_parse_common_attributes, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_parse_common_attributes, "IIO_HID");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
MODULE_DESCRIPTION("HID Sensor common attribute processing");
diff --git a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
index abb09fefc792..48193937275b 100644
--- a/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
+++ b/drivers/iio/common/hid-sensors/hid-sensor-trigger.c
@@ -147,7 +147,7 @@ static int _hid_sensor_power_state(struct hid_sensor_common *st, bool state)
return 0;
}
-EXPORT_SYMBOL_NS(hid_sensor_power_state, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_power_state, "IIO_HID");
int hid_sensor_power_state(struct hid_sensor_common *st, bool state)
{
@@ -222,7 +222,7 @@ void hid_sensor_remove_trigger(struct iio_dev *indio_dev,
iio_trigger_free(attrb->trigger);
iio_triggered_buffer_cleanup(indio_dev);
}
-EXPORT_SYMBOL_NS(hid_sensor_remove_trigger, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_remove_trigger, "IIO_HID");
static const struct iio_trigger_ops hid_sensor_trigger_ops = {
.set_trigger_state = &hid_sensor_data_rdy_trigger_set_state,
@@ -289,7 +289,7 @@ error_triggered_buffer_cleanup:
iio_triggered_buffer_cleanup(indio_dev);
return ret;
}
-EXPORT_SYMBOL_NS(hid_sensor_setup_trigger, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_setup_trigger, "IIO_HID");
static int __maybe_unused hid_sensor_suspend(struct device *dev)
{
@@ -319,9 +319,9 @@ const struct dev_pm_ops hid_sensor_pm_ops = {
SET_RUNTIME_PM_OPS(hid_sensor_suspend,
hid_sensor_runtime_resume, NULL)
};
-EXPORT_SYMBOL_NS(hid_sensor_pm_ops, IIO_HID);
+EXPORT_SYMBOL_NS(hid_sensor_pm_ops, "IIO_HID");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
MODULE_DESCRIPTION("HID Sensor trigger processing");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID_ATTRIBUTES);
+MODULE_IMPORT_NS("IIO_HID_ATTRIBUTES");
diff --git a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
index f44458c380d9..c081b5caa475 100644
--- a/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
+++ b/drivers/iio/common/inv_sensors/inv_sensors_timestamp.c
@@ -55,7 +55,7 @@ void inv_sensors_timestamp_init(struct inv_sensors_timestamp *ts,
/* use theoretical value for chip period */
inv_update_acc(&ts->chip_period, chip->clock_period);
}
-EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_init, IIO_INV_SENSORS_TIMESTAMP);
+EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_init, "IIO_INV_SENSORS_TIMESTAMP");
int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts,
uint32_t period, bool fifo)
@@ -70,9 +70,13 @@ int inv_sensors_timestamp_update_odr(struct inv_sensors_timestamp *ts,
if (mult != ts->mult)
ts->new_mult = mult;
+ /* When FIFO is off, directly apply the new ODR */
+ if (!fifo)
+ inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
+
return 0;
}
-EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_update_odr, IIO_INV_SENSORS_TIMESTAMP);
+EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_update_odr, "IIO_INV_SENSORS_TIMESTAMP");
static bool inv_validate_period(struct inv_sensors_timestamp *ts, uint32_t period)
{
@@ -162,7 +166,7 @@ void inv_sensors_timestamp_interrupt(struct inv_sensors_timestamp *ts,
if (valid)
inv_align_timestamp_it(ts);
}
-EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_interrupt, IIO_INV_SENSORS_TIMESTAMP);
+EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_interrupt, "IIO_INV_SENSORS_TIMESTAMP");
void inv_sensors_timestamp_apply_odr(struct inv_sensors_timestamp *ts,
uint32_t fifo_period, size_t fifo_nb,
@@ -194,7 +198,7 @@ void inv_sensors_timestamp_apply_odr(struct inv_sensors_timestamp *ts,
ts->timestamp = ts->it.up - interval;
}
}
-EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_apply_odr, IIO_INV_SENSORS_TIMESTAMP);
+EXPORT_SYMBOL_NS_GPL(inv_sensors_timestamp_apply_odr, "IIO_INV_SENSORS_TIMESTAMP");
MODULE_AUTHOR("InvenSense, Inc.");
MODULE_DESCRIPTION("InvenSense sensors timestamp module");
diff --git a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
index 9c9bc77003c7..588470863681 100644
--- a/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
+++ b/drivers/iio/common/ms_sensors/ms_sensors_i2c.c
@@ -58,7 +58,7 @@ int ms_sensors_reset(void *cli, u8 cmd, unsigned int delay)
return 0;
}
-EXPORT_SYMBOL_NS(ms_sensors_reset, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_reset, "IIO_MEAS_SPEC_SENSORS");
/**
* ms_sensors_read_prom_word() - PROM word read function
@@ -84,7 +84,7 @@ int ms_sensors_read_prom_word(void *cli, int cmd, u16 *word)
return 0;
}
-EXPORT_SYMBOL_NS(ms_sensors_read_prom_word, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_read_prom_word, "IIO_MEAS_SPEC_SENSORS");
/**
* ms_sensors_convert_and_read() - ADC conversion & read function
@@ -130,7 +130,7 @@ err:
dev_err(&client->dev, "Unable to make sensor adc conversion\n");
return ret;
}
-EXPORT_SYMBOL_NS(ms_sensors_convert_and_read, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_convert_and_read, "IIO_MEAS_SPEC_SENSORS");
/**
* ms_sensors_crc_valid() - CRC check function
@@ -248,7 +248,7 @@ int ms_sensors_read_serial(struct i2c_client *client, u64 *sn)
return 0;
}
-EXPORT_SYMBOL_NS(ms_sensors_read_serial, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_read_serial, "IIO_MEAS_SPEC_SENSORS");
static int ms_sensors_read_config_reg(struct i2c_client *client,
u8 *config_reg)
@@ -299,7 +299,7 @@ ssize_t ms_sensors_write_resolution(struct ms_ht_dev *dev_data,
MS_SENSORS_CONFIG_REG_WRITE,
config_reg);
}
-EXPORT_SYMBOL_NS(ms_sensors_write_resolution, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_write_resolution, "IIO_MEAS_SPEC_SENSORS");
/**
* ms_sensors_show_battery_low() - Show device battery low indicator
@@ -326,7 +326,7 @@ ssize_t ms_sensors_show_battery_low(struct ms_ht_dev *dev_data,
return sysfs_emit(buf, "%d\n", (config_reg & 0x40) >> 6);
}
-EXPORT_SYMBOL_NS(ms_sensors_show_battery_low, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_show_battery_low, "IIO_MEAS_SPEC_SENSORS");
/**
* ms_sensors_show_heater() - Show device heater
@@ -353,7 +353,7 @@ ssize_t ms_sensors_show_heater(struct ms_ht_dev *dev_data,
return sysfs_emit(buf, "%d\n", (config_reg & 0x4) >> 2);
}
-EXPORT_SYMBOL_NS(ms_sensors_show_heater, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_show_heater, "IIO_MEAS_SPEC_SENSORS");
/**
* ms_sensors_write_heater() - Write device heater
@@ -401,7 +401,7 @@ ssize_t ms_sensors_write_heater(struct ms_ht_dev *dev_data,
return len;
}
-EXPORT_SYMBOL_NS(ms_sensors_write_heater, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_write_heater, "IIO_MEAS_SPEC_SENSORS");
/**
* ms_sensors_ht_read_temperature() - Read temperature
@@ -442,7 +442,7 @@ int ms_sensors_ht_read_temperature(struct ms_ht_dev *dev_data,
return 0;
}
-EXPORT_SYMBOL_NS(ms_sensors_ht_read_temperature, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_ht_read_temperature, "IIO_MEAS_SPEC_SENSORS");
/**
* ms_sensors_ht_read_humidity() - Read humidity
@@ -485,7 +485,7 @@ int ms_sensors_ht_read_humidity(struct ms_ht_dev *dev_data,
return 0;
}
-EXPORT_SYMBOL_NS(ms_sensors_ht_read_humidity, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_ht_read_humidity, "IIO_MEAS_SPEC_SENSORS");
/**
* ms_sensors_tp_crc4() - Calculate PROM CRC for
@@ -602,7 +602,7 @@ int ms_sensors_tp_read_prom(struct ms_tp_dev *dev_data)
return 0;
}
-EXPORT_SYMBOL_NS(ms_sensors_tp_read_prom, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_tp_read_prom, "IIO_MEAS_SPEC_SENSORS");
/**
* ms_sensors_read_temp_and_pressure() - read temp and pressure
@@ -688,7 +688,7 @@ int ms_sensors_read_temp_and_pressure(struct ms_tp_dev *dev_data,
return 0;
}
-EXPORT_SYMBOL_NS(ms_sensors_read_temp_and_pressure, IIO_MEAS_SPEC_SENSORS);
+EXPORT_SYMBOL_NS(ms_sensors_read_temp_and_pressure, "IIO_MEAS_SPEC_SENSORS");
MODULE_DESCRIPTION("Measurement-Specialties common i2c driver");
MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
diff --git a/drivers/iio/common/ssp_sensors/ssp_dev.c b/drivers/iio/common/ssp_sensors/ssp_dev.c
index e64d242145e0..65f8a2b13cfd 100644
--- a/drivers/iio/common/ssp_sensors/ssp_dev.c
+++ b/drivers/iio/common/ssp_sensors/ssp_dev.c
@@ -205,7 +205,7 @@ u32 ssp_get_sensor_delay(struct ssp_data *data, enum ssp_sensor_type type)
{
return data->delay_buf[type];
}
-EXPORT_SYMBOL_NS(ssp_get_sensor_delay, IIO_SSP_SENSORS);
+EXPORT_SYMBOL_NS(ssp_get_sensor_delay, "IIO_SSP_SENSORS");
/**
* ssp_enable_sensor() - enables data acquisition for sensor
@@ -267,7 +267,7 @@ int ssp_enable_sensor(struct ssp_data *data, enum ssp_sensor_type type,
derror:
return ret;
}
-EXPORT_SYMBOL_NS(ssp_enable_sensor, IIO_SSP_SENSORS);
+EXPORT_SYMBOL_NS(ssp_enable_sensor, "IIO_SSP_SENSORS");
/**
* ssp_change_delay() - changes data acquisition for sensor
@@ -298,7 +298,7 @@ int ssp_change_delay(struct ssp_data *data, enum ssp_sensor_type type,
return 0;
}
-EXPORT_SYMBOL_NS(ssp_change_delay, IIO_SSP_SENSORS);
+EXPORT_SYMBOL_NS(ssp_change_delay, "IIO_SSP_SENSORS");
/**
* ssp_disable_sensor() - disables sensor
@@ -335,7 +335,7 @@ int ssp_disable_sensor(struct ssp_data *data, enum ssp_sensor_type type)
return 0;
}
-EXPORT_SYMBOL_NS(ssp_disable_sensor, IIO_SSP_SENSORS);
+EXPORT_SYMBOL_NS(ssp_disable_sensor, "IIO_SSP_SENSORS");
static irqreturn_t ssp_irq_thread_fn(int irq, void *dev_id)
{
@@ -478,7 +478,7 @@ void ssp_register_consumer(struct iio_dev *indio_dev, enum ssp_sensor_type type)
data->sensor_devs[type] = indio_dev;
}
-EXPORT_SYMBOL_NS(ssp_register_consumer, IIO_SSP_SENSORS);
+EXPORT_SYMBOL_NS(ssp_register_consumer, "IIO_SSP_SENSORS");
static int ssp_probe(struct spi_device *spi)
{
diff --git a/drivers/iio/common/ssp_sensors/ssp_iio.c b/drivers/iio/common/ssp_sensors/ssp_iio.c
index 88b8b56bfa51..caa404edd9d0 100644
--- a/drivers/iio/common/ssp_sensors/ssp_iio.c
+++ b/drivers/iio/common/ssp_sensors/ssp_iio.c
@@ -32,7 +32,7 @@ int ssp_common_buffer_postenable(struct iio_dev *indio_dev)
return ssp_enable_sensor(data, spd->type,
ssp_get_sensor_delay(data, spd->type));
}
-EXPORT_SYMBOL_NS(ssp_common_buffer_postenable, IIO_SSP_SENSORS);
+EXPORT_SYMBOL_NS(ssp_common_buffer_postenable, "IIO_SSP_SENSORS");
/**
* ssp_common_buffer_postdisable() - generic postdisable callback for ssp buffer
@@ -55,7 +55,7 @@ int ssp_common_buffer_postdisable(struct iio_dev *indio_dev)
return ret;
}
-EXPORT_SYMBOL_NS(ssp_common_buffer_postdisable, IIO_SSP_SENSORS);
+EXPORT_SYMBOL_NS(ssp_common_buffer_postdisable, "IIO_SSP_SENSORS");
/**
* ssp_common_process_data() - Common process data callback for ssp sensors
@@ -91,9 +91,9 @@ int ssp_common_process_data(struct iio_dev *indio_dev, void *buf,
return iio_push_to_buffers_with_timestamp(indio_dev, spd->buffer,
calculated_time);
}
-EXPORT_SYMBOL_NS(ssp_common_process_data, IIO_SSP_SENSORS);
+EXPORT_SYMBOL_NS(ssp_common_process_data, "IIO_SSP_SENSORS");
MODULE_AUTHOR("Karol Wrona <k.wrona@samsung.com>");
MODULE_DESCRIPTION("Samsung sensorhub commons");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_SSP_SENSORS);
+MODULE_IMPORT_NS("IIO_SSP_SENSORS");
diff --git a/drivers/iio/common/st_sensors/st_sensors_buffer.c b/drivers/iio/common/st_sensors/st_sensors_buffer.c
index e2f108ca949c..57f087c2216f 100644
--- a/drivers/iio/common/st_sensors/st_sensors_buffer.c
+++ b/drivers/iio/common/st_sensors/st_sensors_buffer.c
@@ -76,4 +76,4 @@ st_sensors_get_buffer_element_error:
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS(st_sensors_trigger_handler, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_trigger_handler, "IIO_ST_SENSORS");
diff --git a/drivers/iio/common/st_sensors/st_sensors_core.c b/drivers/iio/common/st_sensors/st_sensors_core.c
index 1b4287991d00..e4f5a7ff7e74 100644
--- a/drivers/iio/common/st_sensors/st_sensors_core.c
+++ b/drivers/iio/common/st_sensors/st_sensors_core.c
@@ -46,7 +46,7 @@ int st_sensors_debugfs_reg_access(struct iio_dev *indio_dev,
return 0;
}
-EXPORT_SYMBOL_NS(st_sensors_debugfs_reg_access, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_debugfs_reg_access, "IIO_ST_SENSORS");
static int st_sensors_match_odr(struct st_sensor_settings *sensor_settings,
unsigned int odr, struct st_sensor_odr_avl *odr_out)
@@ -110,7 +110,7 @@ unlock_mutex:
return err;
}
-EXPORT_SYMBOL_NS(st_sensors_set_odr, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_set_odr, "IIO_ST_SENSORS");
static int st_sensors_match_fs(struct st_sensor_settings *sensor_settings,
unsigned int fs, int *index_fs_avl)
@@ -203,7 +203,7 @@ int st_sensors_set_enable(struct iio_dev *indio_dev, bool enable)
set_enable_error:
return err;
}
-EXPORT_SYMBOL_NS(st_sensors_set_enable, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_set_enable, "IIO_ST_SENSORS");
int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
{
@@ -217,7 +217,7 @@ int st_sensors_set_axis_enable(struct iio_dev *indio_dev, u8 axis_enable)
axis_enable);
return err;
}
-EXPORT_SYMBOL_NS(st_sensors_set_axis_enable, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_set_axis_enable, "IIO_ST_SENSORS");
int st_sensors_power_enable(struct iio_dev *indio_dev)
@@ -236,7 +236,7 @@ int st_sensors_power_enable(struct iio_dev *indio_dev)
return 0;
}
-EXPORT_SYMBOL_NS(st_sensors_power_enable, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_power_enable, "IIO_ST_SENSORS");
static int st_sensors_set_drdy_int_pin(struct iio_dev *indio_dev,
struct st_sensors_platform_data *pdata)
@@ -331,7 +331,7 @@ void st_sensors_dev_name_probe(struct device *dev, char *name, int len)
/* The name from the match takes precedence if present */
strscpy(name, match, len);
}
-EXPORT_SYMBOL_NS(st_sensors_dev_name_probe, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_dev_name_probe, "IIO_ST_SENSORS");
int st_sensors_init_sensor(struct iio_dev *indio_dev,
struct st_sensors_platform_data *pdata)
@@ -418,7 +418,7 @@ int st_sensors_init_sensor(struct iio_dev *indio_dev,
return err;
}
-EXPORT_SYMBOL_NS(st_sensors_init_sensor, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_init_sensor, "IIO_ST_SENSORS");
int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
{
@@ -467,7 +467,7 @@ int st_sensors_set_dataready_irq(struct iio_dev *indio_dev, bool enable)
st_accel_set_dataready_irq_error:
return err;
}
-EXPORT_SYMBOL_NS(st_sensors_set_dataready_irq, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_set_dataready_irq, "IIO_ST_SENSORS");
int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale)
{
@@ -490,7 +490,7 @@ int st_sensors_set_fullscale_by_gain(struct iio_dev *indio_dev, int scale)
st_sensors_match_scale_error:
return err;
}
-EXPORT_SYMBOL_NS(st_sensors_set_fullscale_by_gain, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_set_fullscale_by_gain, "IIO_ST_SENSORS");
static int st_sensors_read_axis_data(struct iio_dev *indio_dev,
struct iio_chan_spec const *ch, int *data)
@@ -555,7 +555,7 @@ out:
return err;
}
-EXPORT_SYMBOL_NS(st_sensors_read_info_raw, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_read_info_raw, "IIO_ST_SENSORS");
/*
* st_sensors_get_settings_index() - get index of the sensor settings for a
@@ -582,7 +582,7 @@ int st_sensors_get_settings_index(const char *name,
return -ENODEV;
}
-EXPORT_SYMBOL_NS(st_sensors_get_settings_index, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_get_settings_index, "IIO_ST_SENSORS");
/*
* st_sensors_verify_id() - verify sensor ID (WhoAmI) is matching with the
@@ -614,7 +614,7 @@ int st_sensors_verify_id(struct iio_dev *indio_dev)
return 0;
}
-EXPORT_SYMBOL_NS(st_sensors_verify_id, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_verify_id, "IIO_ST_SENSORS");
ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -634,7 +634,7 @@ ssize_t st_sensors_sysfs_sampling_frequency_avail(struct device *dev,
return len;
}
-EXPORT_SYMBOL_NS(st_sensors_sysfs_sampling_frequency_avail, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_sysfs_sampling_frequency_avail, "IIO_ST_SENSORS");
ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -656,7 +656,7 @@ ssize_t st_sensors_sysfs_scale_avail(struct device *dev,
return len;
}
-EXPORT_SYMBOL_NS(st_sensors_sysfs_scale_avail, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_sysfs_scale_avail, "IIO_ST_SENSORS");
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics ST-sensors core");
diff --git a/drivers/iio/common/st_sensors/st_sensors_i2c.c b/drivers/iio/common/st_sensors/st_sensors_i2c.c
index ee95082c7410..7156302fe997 100644
--- a/drivers/iio/common/st_sensors/st_sensors_i2c.c
+++ b/drivers/iio/common/st_sensors/st_sensors_i2c.c
@@ -61,7 +61,7 @@ int st_sensors_i2c_configure(struct iio_dev *indio_dev,
return 0;
}
-EXPORT_SYMBOL_NS(st_sensors_i2c_configure, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_i2c_configure, "IIO_ST_SENSORS");
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics ST-sensors i2c driver");
diff --git a/drivers/iio/common/st_sensors/st_sensors_spi.c b/drivers/iio/common/st_sensors/st_sensors_spi.c
index 63e302c3fbaa..0da27013943d 100644
--- a/drivers/iio/common/st_sensors/st_sensors_spi.c
+++ b/drivers/iio/common/st_sensors/st_sensors_spi.c
@@ -113,7 +113,7 @@ int st_sensors_spi_configure(struct iio_dev *indio_dev,
return 0;
}
-EXPORT_SYMBOL_NS(st_sensors_spi_configure, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_spi_configure, "IIO_ST_SENSORS");
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics ST-sensors spi driver");
diff --git a/drivers/iio/common/st_sensors/st_sensors_trigger.c b/drivers/iio/common/st_sensors/st_sensors_trigger.c
index a0df9250a69f..9d4bf822a15d 100644
--- a/drivers/iio/common/st_sensors/st_sensors_trigger.c
+++ b/drivers/iio/common/st_sensors/st_sensors_trigger.c
@@ -134,11 +134,11 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
iio_trigger_set_drvdata(sdata->trig, indio_dev);
sdata->trig->ops = trigger_ops;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(sdata->irq));
/*
* If the IRQ is triggered on falling edge, we need to mark the
* interrupt as active low, if the hardware supports this.
*/
+ irq_trig = irq_get_trigger_type(sdata->irq);
switch(irq_trig) {
case IRQF_TRIGGER_FALLING:
case IRQF_TRIGGER_LOW:
@@ -227,7 +227,7 @@ int st_sensors_allocate_trigger(struct iio_dev *indio_dev,
return 0;
}
-EXPORT_SYMBOL_NS(st_sensors_allocate_trigger, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_allocate_trigger, "IIO_ST_SENSORS");
int st_sensors_validate_device(struct iio_trigger *trig,
struct iio_dev *indio_dev)
@@ -239,4 +239,4 @@ int st_sensors_validate_device(struct iio_trigger *trig,
return 0;
}
-EXPORT_SYMBOL_NS(st_sensors_validate_device, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_sensors_validate_device, "IIO_ST_SENSORS");
diff --git a/drivers/iio/dac/Kconfig b/drivers/iio/dac/Kconfig
index 9f5d5ebb8653..5d01ba4edbf3 100644
--- a/drivers/iio/dac/Kconfig
+++ b/drivers/iio/dac/Kconfig
@@ -6,9 +6,28 @@
menu "Digital to analog converters"
+config AD3552R_HS
+ tristate "Analog Devices AD3552R DAC High Speed driver"
+ select AD3552R_LIB
+ select IIO_BACKEND
+ help
+ Say yes here to build support for Analog Devices AD3552R
+ Digital to Analog Converter High Speed driver.
+
+ The driver requires the assistance of an IP core to operate,
+ since data is streamed into target device via DMA, sent over a
+ QSPI + DDR (Double Data Rate) bus.
+
+ To compile this driver as a module, choose M here: the
+ module will be called ad3552r-hs.
+
+config AD3552R_LIB
+ tristate
+
config AD3552R
tristate "Analog Devices AD3552R DAC driver"
depends on SPI_MASTER
+ select AD3552R_LIB
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
@@ -306,6 +325,19 @@ config AD7303
To compile this driver as module choose M here: the module will be called
ad7303.
+config AD8460
+ tristate "Analog Devices AD8460 DAC driver"
+ depends on SPI
+ select REGMAP_SPI
+ select IIO_BUFFER
+ select IIO_BUFFER_DMAENGINE
+ help
+ Say yes here to build support for Analog Devices AD8460 Digital to
+ Analog Converters (DAC).
+
+ To compile this driver as a module choose M here: the module will be called
+ ad8460.
+
config AD8801
tristate "Analog Devices AD8801/AD8803 DAC driver"
depends on SPI_MASTER
diff --git a/drivers/iio/dac/Makefile b/drivers/iio/dac/Makefile
index 2cf148f16306..414c152be779 100644
--- a/drivers/iio/dac/Makefile
+++ b/drivers/iio/dac/Makefile
@@ -4,6 +4,8 @@
#
# When adding new entries keep the list in alphabetical order
+obj-$(CONFIG_AD3552R_HS) += ad3552r-hs.o
+obj-$(CONFIG_AD3552R_LIB) += ad3552r-common.o
obj-$(CONFIG_AD3552R) += ad3552r.o
obj-$(CONFIG_AD5360) += ad5360.o
obj-$(CONFIG_AD5380) += ad5380.o
@@ -28,6 +30,7 @@ obj-$(CONFIG_AD5686_SPI) += ad5686-spi.o
obj-$(CONFIG_AD5696_I2C) += ad5696-i2c.o
obj-$(CONFIG_AD7293) += ad7293.o
obj-$(CONFIG_AD7303) += ad7303.o
+obj-$(CONFIG_AD8460) += ad8460.o
obj-$(CONFIG_AD8801) += ad8801.o
obj-$(CONFIG_AD9739A) += ad9739a.o
obj-$(CONFIG_ADI_AXI_DAC) += adi-axi-dac.o
diff --git a/drivers/iio/dac/ad3552r-common.c b/drivers/iio/dac/ad3552r-common.c
new file mode 100644
index 000000000000..0f495df2e5ce
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-common.c
@@ -0,0 +1,249 @@
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Copyright (c) 2010-2024 Analog Devices Inc.
+// Copyright (c) 2024 Baylibre, SAS
+
+#include <linux/bitfield.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/property.h>
+#include <linux/regulator/consumer.h>
+
+#include "ad3552r.h"
+
+const s32 ad3552r_ch_ranges[AD3552R_MAX_RANGES][2] = {
+ [AD3552R_CH_OUTPUT_RANGE_0__2P5V] = { 0, 2500 },
+ [AD3552R_CH_OUTPUT_RANGE_0__5V] = { 0, 5000 },
+ [AD3552R_CH_OUTPUT_RANGE_0__10V] = { 0, 10000 },
+ [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] = { -5000, 5000 },
+ [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = { -10000, 10000 }
+};
+EXPORT_SYMBOL_NS_GPL(ad3552r_ch_ranges, "IIO_AD3552R");
+
+const s32 ad3542r_ch_ranges[AD3542R_MAX_RANGES][2] = {
+ [AD3542R_CH_OUTPUT_RANGE_0__2P5V] = { 0, 2500 },
+ [AD3542R_CH_OUTPUT_RANGE_0__3V] = { 0, 3000 },
+ [AD3542R_CH_OUTPUT_RANGE_0__5V] = { 0, 5000 },
+ [AD3542R_CH_OUTPUT_RANGE_0__10V] = { 0, 10000 },
+ [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] = { -2500, 7500 },
+ [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] = { -5000, 5000 }
+};
+EXPORT_SYMBOL_NS_GPL(ad3542r_ch_ranges, "IIO_AD3552R");
+
+/* Gain * AD3552R_GAIN_SCALE */
+static const s32 gains_scaling_table[] = {
+ [AD3552R_CH_GAIN_SCALING_1] = 1000,
+ [AD3552R_CH_GAIN_SCALING_0_5] = 500,
+ [AD3552R_CH_GAIN_SCALING_0_25] = 250,
+ [AD3552R_CH_GAIN_SCALING_0_125] = 125
+};
+
+u16 ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs)
+{
+ return FIELD_PREP(AD3552R_MASK_CH_RANGE_OVERRIDE, 1) |
+ FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_P, p) |
+ FIELD_PREP(AD3552R_MASK_CH_GAIN_SCALING_N, n) |
+ FIELD_PREP(AD3552R_MASK_CH_OFFSET_BIT_8, abs(goffs)) |
+ FIELD_PREP(AD3552R_MASK_CH_OFFSET_POLARITY, goffs < 0);
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_calc_custom_gain, "IIO_AD3552R");
+
+static void ad3552r_get_custom_range(struct ad3552r_ch_data *ch_data,
+ s32 *v_min, s32 *v_max)
+{
+ s64 vref, tmp, common, offset, gn, gp;
+ /*
+ * From datasheet formula (In Volts):
+ * Vmin = 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03]
+ * Vmax = 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03]
+ * Calculus are converted to milivolts
+ */
+ vref = 2500;
+ /* 2.5 * 1.03 * 1000 (To mV) */
+ common = 2575 * ch_data->rfb;
+ offset = ch_data->gain_offset;
+
+ gn = gains_scaling_table[ch_data->n];
+ tmp = (1024 * gn + AD3552R_GAIN_SCALE * offset) * common;
+ tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
+ *v_max = vref + tmp;
+
+ gp = gains_scaling_table[ch_data->p];
+ tmp = (1024 * gp - AD3552R_GAIN_SCALE * offset) * common;
+ tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
+ *v_min = vref - tmp;
+}
+
+void ad3552r_calc_gain_and_offset(struct ad3552r_ch_data *ch_data,
+ const struct ad3552r_model_data *model_data)
+{
+ s32 idx, v_max, v_min, span, rem;
+ s64 tmp;
+
+ if (ch_data->range_override) {
+ ad3552r_get_custom_range(ch_data, &v_min, &v_max);
+ } else {
+ /* Normal range */
+ idx = ch_data->range;
+ v_min = model_data->ranges_table[idx][0];
+ v_max = model_data->ranges_table[idx][1];
+ }
+
+ /*
+ * From datasheet formula:
+ * Vout = Span * (D / 65536) + Vmin
+ * Converted to scale and offset:
+ * Scale = Span / 65536
+ * Offset = 65536 * Vmin / Span
+ *
+ * Reminders are in micros in order to be printed as
+ * IIO_VAL_INT_PLUS_MICRO
+ */
+ span = v_max - v_min;
+ ch_data->scale_int = div_s64_rem(span, 65536, &rem);
+ /* Do operations in microvolts */
+ ch_data->scale_dec = DIV_ROUND_CLOSEST((s64)rem * 1000000, 65536);
+
+ ch_data->offset_int = div_s64_rem(v_min * 65536, span, &rem);
+ tmp = (s64)rem * 1000000;
+ ch_data->offset_dec = div_s64(tmp, span);
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_calc_gain_and_offset, "IIO_AD3552R");
+
+int ad3552r_get_ref_voltage(struct device *dev, u32 *val)
+{
+ int voltage;
+ int delta = 100000;
+
+ voltage = devm_regulator_get_enable_read_voltage(dev, "vref");
+ if (voltage < 0 && voltage != -ENODEV)
+ return dev_err_probe(dev, voltage,
+ "Error getting vref voltage\n");
+
+ if (voltage == -ENODEV) {
+ if (device_property_read_bool(dev, "adi,vref-out-en"))
+ *val = AD3552R_INTERNAL_VREF_PIN_2P5V;
+ else
+ *val = AD3552R_INTERNAL_VREF_PIN_FLOATING;
+
+ return 0;
+ }
+
+ if (voltage > 2500000 + delta || voltage < 2500000 - delta) {
+ dev_warn(dev, "vref-supply must be 2.5V");
+ return -EINVAL;
+ }
+
+ *val = AD3552R_EXTERNAL_VREF_PIN_INPUT;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_ref_voltage, "IIO_AD3552R");
+
+int ad3552r_get_drive_strength(struct device *dev, u32 *val)
+{
+ int err;
+ u32 drive_strength;
+
+ err = device_property_read_u32(dev, "adi,sdo-drive-strength",
+ &drive_strength);
+ if (err)
+ return err;
+
+ if (drive_strength > 3) {
+ dev_err_probe(dev, -EINVAL,
+ "adi,sdo-drive-strength must be less than 4\n");
+ return -EINVAL;
+ }
+
+ *val = drive_strength;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_drive_strength, "IIO_AD3552R");
+
+int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *child,
+ u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs)
+{
+ int err;
+ u32 val;
+ struct fwnode_handle *gain_child __free(fwnode_handle) =
+ fwnode_get_named_child_node(child,
+ "custom-output-range-config");
+
+ if (!gain_child)
+ return dev_err_probe(dev, -EINVAL,
+ "custom-output-range-config mandatory\n");
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-scaling-p mandatory\n");
+ *gs_p = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-scaling-n property mandatory\n");
+ *gs_n = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,rfb-ohms mandatory\n");
+ *rfb = val;
+
+ err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val);
+ if (err)
+ return dev_err_probe(dev, err,
+ "adi,gain-offset mandatory\n");
+ *goffs = val;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_custom_gain, "IIO_AD3552R");
+
+static int ad3552r_find_range(const struct ad3552r_model_data *model_info,
+ s32 *vals)
+{
+ int i;
+
+ for (i = 0; i < model_info->num_ranges; i++)
+ if (vals[0] == model_info->ranges_table[i][0] * 1000 &&
+ vals[1] == model_info->ranges_table[i][1] * 1000)
+ return i;
+
+ return -EINVAL;
+}
+
+int ad3552r_get_output_range(struct device *dev,
+ const struct ad3552r_model_data *model_info,
+ struct fwnode_handle *child, u32 *val)
+{
+ int ret;
+ s32 vals[2];
+
+ /* This property is optional, so returning -ENOENT if missing */
+ if (!fwnode_property_present(child, "adi,output-range-microvolt"))
+ return -ENOENT;
+
+ ret = fwnode_property_read_u32_array(child,
+ "adi,output-range-microvolt",
+ vals, 2);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "invalid adi,output-range-microvolt\n");
+
+ ret = ad3552r_find_range(model_info, vals);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "invalid adi,output-range-microvolt value\n");
+
+ *val = ret;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS_GPL(ad3552r_get_output_range, "IIO_AD3552R");
+
+MODULE_DESCRIPTION("ad3552r common functions");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/dac/ad3552r-hs.c b/drivers/iio/dac/ad3552r-hs.c
new file mode 100644
index 000000000000..216c634f3eaf
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-hs.c
@@ -0,0 +1,529 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Analog Devices AD3552R
+ * Digital to Analog converter driver, High Speed version
+ *
+ * Copyright 2024 Analog Devices Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/iio/backend.h>
+#include <linux/iio/buffer.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/property.h>
+#include <linux/units.h>
+
+#include "ad3552r.h"
+#include "ad3552r-hs.h"
+
+struct ad3552r_hs_state {
+ const struct ad3552r_model_data *model_data;
+ struct gpio_desc *reset_gpio;
+ struct device *dev;
+ struct iio_backend *back;
+ bool single_channel;
+ struct ad3552r_ch_data ch_data[AD3552R_MAX_CH];
+ struct ad3552r_hs_platform_data *data;
+};
+
+static int ad3552r_qspi_update_reg_bits(struct ad3552r_hs_state *st,
+ u32 reg, u32 mask, u32 val,
+ size_t xfer_size)
+{
+ u32 rval;
+ int ret;
+
+ ret = st->data->bus_reg_read(st->back, reg, &rval, xfer_size);
+ if (ret)
+ return ret;
+
+ rval = (rval & ~mask) | val;
+
+ return st->data->bus_reg_write(st->back, reg, rval, xfer_size);
+}
+
+static int ad3552r_hs_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+ int ret;
+ int ch = chan->channel;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ /*
+ * Using 4 lanes (QSPI), then using 2 as DDR mode is
+ * considered always on (considering buffering mode always).
+ */
+ *val = DIV_ROUND_CLOSEST(st->data->bus_sample_data_clock_hz *
+ 4 * 2, chan->scan_type.realbits);
+
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_RAW:
+ ret = st->data->bus_reg_read(st->back,
+ AD3552R_REG_ADDR_CH_DAC_16B(chan->channel),
+ val, 2);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = st->ch_data[ch].scale_int;
+ *val2 = st->ch_data[ch].scale_dec;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_OFFSET:
+ *val = st->ch_data[ch].offset_int;
+ *val2 = st->ch_data[ch].offset_dec;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad3552r_hs_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ return st->data->bus_reg_write(st->back,
+ AD3552R_REG_ADDR_CH_DAC_16B(chan->channel),
+ val, 2);
+ }
+ unreachable();
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad3552r_hs_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+ struct iio_backend_data_fmt fmt = {
+ .type = IIO_BACKEND_DATA_UNSIGNED
+ };
+ int loop_len, val, ret;
+
+ switch (*indio_dev->active_scan_mask) {
+ case AD3552R_CH0_ACTIVE:
+ st->single_channel = true;
+ loop_len = 2;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(0);
+ break;
+ case AD3552R_CH1_ACTIVE:
+ st->single_channel = true;
+ loop_len = 2;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(1);
+ break;
+ case AD3552R_CH0_ACTIVE | AD3552R_CH1_ACTIVE:
+ st->single_channel = false;
+ loop_len = 4;
+ val = AD3552R_REG_ADDR_CH_DAC_16B(1);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_STREAM_MODE,
+ loop_len, 1);
+ if (ret)
+ return ret;
+
+ /* Inform DAC chip to switch into DDR mode */
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ AD3552R_MASK_SPI_CONFIG_DDR, 1);
+ if (ret)
+ return ret;
+
+ /* Inform DAC IP to go for DDR mode from now on */
+ ret = iio_backend_ddr_enable(st->back);
+ if (ret) {
+ dev_err(st->dev, "could not set DDR mode, not streaming");
+ goto exit_err;
+ }
+
+ ret = iio_backend_data_transfer_addr(st->back, val);
+ if (ret)
+ goto exit_err;
+
+ ret = iio_backend_data_format_set(st->back, 0, &fmt);
+ if (ret)
+ goto exit_err;
+
+ ret = iio_backend_data_stream_enable(st->back);
+ if (ret)
+ goto exit_err;
+
+ return 0;
+
+exit_err:
+ ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ 0, 1);
+
+ iio_backend_ddr_disable(st->back);
+
+ return ret;
+}
+
+static int ad3552r_hs_buffer_predisable(struct iio_dev *indio_dev)
+{
+ struct ad3552r_hs_state *st = iio_priv(indio_dev);
+ int ret;
+
+ ret = iio_backend_data_stream_disable(st->back);
+ if (ret)
+ return ret;
+
+ /* Inform DAC to set in SDR mode */
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SPI_CONFIG_DDR,
+ 0, 1);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_ddr_disable(st->back);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static inline int ad3552r_hs_set_output_range(struct ad3552r_hs_state *st,
+ int ch, unsigned int mode)
+{
+ int val;
+
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH0_RANGE, mode);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH1_RANGE, mode);
+
+ return ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
+ AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch),
+ val, 1);
+}
+
+static int ad3552r_hs_reset(struct ad3552r_hs_state *st)
+{
+ int ret;
+
+ st->reset_gpio = devm_gpiod_get_optional(st->dev,
+ "reset", GPIOD_OUT_HIGH);
+ if (IS_ERR(st->reset_gpio))
+ return PTR_ERR(st->reset_gpio);
+
+ if (st->reset_gpio) {
+ fsleep(10);
+ gpiod_set_value_cansleep(st->reset_gpio, 0);
+ } else {
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
+ AD3552R_MASK_SOFTWARE_RESET,
+ AD3552R_MASK_SOFTWARE_RESET, 1);
+ if (ret)
+ return ret;
+ }
+ msleep(100);
+
+ return 0;
+}
+
+static int ad3552r_hs_scratch_pad_test(struct ad3552r_hs_state *st)
+{
+ int ret, val;
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ AD3552R_SCRATCH_PAD_TEST_VAL1, 1);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ if (val != AD3552R_SCRATCH_PAD_TEST_VAL1)
+ return dev_err_probe(st->dev, -EIO,
+ "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
+ AD3552R_SCRATCH_PAD_TEST_VAL1, val);
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ AD3552R_SCRATCH_PAD_TEST_VAL2, 1);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_SCRATCH_PAD,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ if (val != AD3552R_SCRATCH_PAD_TEST_VAL2)
+ return dev_err_probe(st->dev, -EIO,
+ "SCRATCH_PAD_TEST mismatch. Expected 0x%x, Read 0x%x\n",
+ AD3552R_SCRATCH_PAD_TEST_VAL2, val);
+
+ return 0;
+}
+
+static int ad3552r_hs_setup_custom_gain(struct ad3552r_hs_state *st,
+ int ch, u16 gain, u16 offset)
+{
+ int ret;
+
+ ret = st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_OFFSET(ch),
+ offset, 1);
+ if (ret)
+ return ret;
+
+ return st->data->bus_reg_write(st->back, AD3552R_REG_ADDR_CH_GAIN(ch),
+ gain, 1);
+}
+
+static int ad3552r_hs_setup(struct ad3552r_hs_state *st)
+{
+ u16 id;
+ u16 gain = 0, offset = 0;
+ u32 ch, val, range;
+ int ret;
+
+ ret = ad3552r_hs_reset(st);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_ddr_disable(st->back);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_hs_scratch_pad_test(st);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_L,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ id = val;
+
+ ret = st->data->bus_reg_read(st->back, AD3552R_REG_ADDR_PRODUCT_ID_H,
+ &val, 1);
+ if (ret)
+ return ret;
+
+ id |= val << 8;
+ if (id != st->model_data->chip_id)
+ dev_info(st->dev, "Chip ID error. Expected 0x%x, Read 0x%x\n",
+ AD3552R_ID, id);
+
+ ret = st->data->bus_reg_write(st->back,
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ 0, 1);
+ if (ret)
+ return ret;
+
+ ret = st->data->bus_reg_write(st->back,
+ AD3552R_REG_ADDR_TRANSFER_REGISTER,
+ FIELD_PREP(AD3552R_MASK_MULTI_IO_MODE,
+ AD3552R_QUAD_SPI) |
+ AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE, 1);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_data_source_set(st->back, 0, IIO_BACKEND_EXTERNAL);
+ if (ret)
+ return ret;
+
+ ret = iio_backend_data_source_set(st->back, 1, IIO_BACKEND_EXTERNAL);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_get_ref_voltage(st->dev, &val);
+ if (ret < 0)
+ return ret;
+
+ val = ret;
+
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ AD3552R_MASK_REFERENCE_VOLTAGE_SEL,
+ val, 1);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_get_drive_strength(st->dev, &val);
+ if (!ret) {
+ ret = ad3552r_qspi_update_reg_bits(st,
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SDO_DRIVE_STRENGTH,
+ val, 1);
+ if (ret)
+ return ret;
+ }
+
+ device_for_each_child_node_scoped(st->dev, child) {
+ ret = fwnode_property_read_u32(child, "reg", &ch);
+ if (ret)
+ return dev_err_probe(st->dev, ret,
+ "reg property missing\n");
+
+ ret = ad3552r_get_output_range(st->dev, st->model_data, child,
+ &range);
+ if (ret && ret != -ENOENT)
+ return ret;
+ if (ret == -ENOENT) {
+ ret = ad3552r_get_custom_gain(st->dev, child,
+ &st->ch_data[ch].p,
+ &st->ch_data[ch].n,
+ &st->ch_data[ch].rfb,
+ &st->ch_data[ch].gain_offset);
+ if (ret)
+ return ret;
+
+ gain = ad3552r_calc_custom_gain(st->ch_data[ch].p,
+ st->ch_data[ch].n,
+ st->ch_data[ch].gain_offset);
+ offset = abs(st->ch_data[ch].gain_offset);
+
+ st->ch_data[ch].range_override = 1;
+
+ ret = ad3552r_hs_setup_custom_gain(st, ch, gain,
+ offset);
+ if (ret)
+ return ret;
+ } else {
+ st->ch_data[ch].range = range;
+
+ ret = ad3552r_hs_set_output_range(st, ch, range);
+ if (ret)
+ return ret;
+ }
+
+ ad3552r_calc_gain_and_offset(&st->ch_data[ch], st->model_data);
+ }
+
+ return 0;
+}
+
+static const struct iio_buffer_setup_ops ad3552r_hs_buffer_setup_ops = {
+ .postenable = ad3552r_hs_buffer_postenable,
+ .predisable = ad3552r_hs_buffer_predisable,
+};
+
+#define AD3552R_CHANNEL(ch) { \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = (ch), \
+ .scan_index = (ch), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_BE, \
+ } \
+}
+
+static const struct iio_chan_spec ad3552r_hs_channels[] = {
+ AD3552R_CHANNEL(0),
+ AD3552R_CHANNEL(1),
+};
+
+static const struct iio_info ad3552r_hs_info = {
+ .read_raw = &ad3552r_hs_read_raw,
+ .write_raw = &ad3552r_hs_write_raw,
+};
+
+static int ad3552r_hs_probe(struct platform_device *pdev)
+{
+ struct ad3552r_hs_state *st;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*st));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ st = iio_priv(indio_dev);
+ st->dev = &pdev->dev;
+
+ st->data = dev_get_platdata(st->dev);
+ if (!st->data)
+ return dev_err_probe(st->dev, -ENODEV, "No platform data !");
+
+ st->back = devm_iio_backend_get(&pdev->dev, NULL);
+ if (IS_ERR(st->back))
+ return PTR_ERR(st->back);
+
+ ret = devm_iio_backend_enable(&pdev->dev, st->back);
+ if (ret)
+ return ret;
+
+ st->model_data = device_get_match_data(&pdev->dev);
+ if (!st->model_data)
+ return -ENODEV;
+
+ indio_dev->name = "ad3552r";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->setup_ops = &ad3552r_hs_buffer_setup_ops;
+ indio_dev->channels = ad3552r_hs_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad3552r_hs_channels);
+ indio_dev->info = &ad3552r_hs_info;
+
+ ret = devm_iio_backend_request_buffer(&pdev->dev, st->back, indio_dev);
+ if (ret)
+ return ret;
+
+ ret = ad3552r_hs_setup(st);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(&pdev->dev, indio_dev);
+}
+
+static const struct ad3552r_model_data ad3552r_model_data = {
+ .model_name = "ad3552r",
+ .chip_id = AD3552R_ID,
+ .num_hw_channels = 2,
+ .ranges_table = ad3552r_ch_ranges,
+ .num_ranges = ARRAY_SIZE(ad3552r_ch_ranges),
+};
+
+static const struct of_device_id ad3552r_hs_of_id[] = {
+ { .compatible = "adi,ad3552r", .data = &ad3552r_model_data },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad3552r_hs_of_id);
+
+static struct platform_driver ad3552r_hs_driver = {
+ .driver = {
+ .name = "ad3552r-hs",
+ .of_match_table = ad3552r_hs_of_id,
+ },
+ .probe = ad3552r_hs_probe,
+};
+module_platform_driver(ad3552r_hs_driver);
+
+MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
+MODULE_AUTHOR("Angelo Dureghello <adueghello@baylibre.com>");
+MODULE_DESCRIPTION("AD3552R Driver - High Speed version");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_BACKEND");
+MODULE_IMPORT_NS("IIO_AD3552R");
diff --git a/drivers/iio/dac/ad3552r-hs.h b/drivers/iio/dac/ad3552r-hs.h
new file mode 100644
index 000000000000..724261d38dea
--- /dev/null
+++ b/drivers/iio/dac/ad3552r-hs.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (c) 2024 Analog Devices Inc.
+ * Copyright (c) 2024 Baylibre, SAS
+ */
+#ifndef __LINUX_PLATFORM_DATA_AD3552R_HS_H__
+#define __LINUX_PLATFORM_DATA_AD3552R_HS_H__
+
+struct iio_backend;
+
+struct ad3552r_hs_platform_data {
+ int (*bus_reg_read)(struct iio_backend *back, u32 reg, u32 *val,
+ size_t data_size);
+ int (*bus_reg_write)(struct iio_backend *back, u32 reg, u32 val,
+ size_t data_size);
+ u32 bus_sample_data_clock_hz;
+};
+
+#endif /* __LINUX_PLATFORM_DATA_AD3552R_HS_H__ */
diff --git a/drivers/iio/dac/ad3552r.c b/drivers/iio/dac/ad3552r.c
index 7d61b2fe6624..e7206af53af6 100644
--- a/drivers/iio/dac/ad3552r.c
+++ b/drivers/iio/dac/ad3552r.c
@@ -6,271 +6,15 @@
* Copyright 2021 Analog Devices Inc.
*/
#include <linux/unaligned.h>
+#include <linux/bitfield.h>
#include <linux/device.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iopoll.h>
#include <linux/kernel.h>
-#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
-/* Register addresses */
-/* Primary address space */
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00
-#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0))
-#define AD3552R_MASK_ADDR_ASCENSION BIT(5)
-#define AD3552R_MASK_SDO_ACTIVE BIT(4)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01
-#define AD3552R_MASK_SINGLE_INST BIT(7)
-#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3)
-#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02
-#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n))
-#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2)
-#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0)
-#define AD3552R_REG_ADDR_CHIP_TYPE 0x03
-#define AD3552R_MASK_CLASS GENMASK(7, 0)
-#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04
-#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05
-#define AD3552R_REG_ADDR_CHIP_GRADE 0x06
-#define AD3552R_MASK_GRADE GENMASK(7, 4)
-#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0)
-#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A
-#define AD3552R_REG_ADDR_SPI_REVISION 0x0B
-#define AD3552R_REG_ADDR_VENDOR_L 0x0C
-#define AD3552R_REG_ADDR_VENDOR_H 0x0D
-#define AD3552R_REG_ADDR_STREAM_MODE 0x0E
-#define AD3552R_MASK_LENGTH GENMASK(7, 0)
-#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F
-#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6)
-#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10
-#define AD3552R_MASK_CRC_ENABLE (GENMASK(7, 6) |\
- GENMASK(1, 0))
-#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5)
-#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11
-#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7)
-#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5)
-#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3)
-#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2)
-#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1)
-#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0)
-#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14
-#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6)
-#define AD3552R_MASK_MEM_CRC_EN BIT(4)
-#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2)
-#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1)
-#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0)
-#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15
-#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6)
-#define AD3552R_MASK_SAMPLE_HOLD_DIFFERENTIAL_USER_EN BIT(5)
-#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3)
-#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2)
-#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0)
-#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16
-#define AD3552R_MASK_REF_RANGE_ALARM BIT(6)
-#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5)
-#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4)
-#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3)
-#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2)
-#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1)
-#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0)
-#define AD3552R_REG_ADDR_ERR_STATUS 0x17
-#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6)
-#define AD3552R_MASK_DUAL_SPI_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5)
-#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4)
-#define AD3552R_MASK_RESET_STATUS BIT(0)
-#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18
-#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch))
-#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch)
-#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19
-#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) ((ch) ? GENMASK(7, 4) :\
- GENMASK(3, 0))
-#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2)
-#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0)
-#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2)
-#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7)
-#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5)
-#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3)
-#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2)
-#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(0)
-/*
- * Secondary region
- * For multibyte registers specify the highest address because the access is
- * done in descending order
- */
-#define AD3552R_SECONDARY_REGION_START 0x28
-#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28
-#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - ch) * 2)
-#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E
-#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F
-#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31
-#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32
-#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - ch) * 2)
-/* 3 bytes registers */
-#define AD3552R_REG_START_24B 0x37
-#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37
-#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - ch) * 3)
-#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40
-#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41
-#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44
-#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45
-#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - ch) * 3)
-
-/* Useful defines */
-#define AD3552R_MAX_CH 2
-#define AD3552R_MASK_CH(ch) BIT(ch)
-#define AD3552R_MASK_ALL_CH GENMASK(1, 0)
-#define AD3552R_MAX_REG_SIZE 3
-#define AD3552R_READ_BIT BIT(7)
-#define AD3552R_ADDR_MASK GENMASK(6, 0)
-#define AD3552R_MASK_DAC_12B 0xFFF0
-#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8
-#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34
-#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2
-#define AD3552R_GAIN_SCALE 1000
-#define AD3552R_LDAC_PULSE_US 100
-
-enum ad3552r_ch_vref_select {
- /* Internal source with Vref I/O floating */
- AD3552R_INTERNAL_VREF_PIN_FLOATING,
- /* Internal source with Vref I/O at 2.5V */
- AD3552R_INTERNAL_VREF_PIN_2P5V,
- /* External source with Vref I/O as input */
- AD3552R_EXTERNAL_VREF_PIN_INPUT
-};
-
-enum ad3552r_id {
- AD3541R_ID = 0x400b,
- AD3542R_ID = 0x4009,
- AD3551R_ID = 0x400a,
- AD3552R_ID = 0x4008,
-};
-
-enum ad3552r_ch_output_range {
- /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
- AD3552R_CH_OUTPUT_RANGE_0__2P5V,
- /* Range from 0 V to 5 V. Requires Rfb1x connection */
- AD3552R_CH_OUTPUT_RANGE_0__5V,
- /* Range from 0 V to 10 V. Requires Rfb2x connection */
- AD3552R_CH_OUTPUT_RANGE_0__10V,
- /* Range from -5 V to 5 V. Requires Rfb2x connection */
- AD3552R_CH_OUTPUT_RANGE_NEG_5__5V,
- /* Range from -10 V to 10 V. Requires Rfb4x connection */
- AD3552R_CH_OUTPUT_RANGE_NEG_10__10V,
-};
-
-static const s32 ad3552r_ch_ranges[][2] = {
- [AD3552R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500},
- [AD3552R_CH_OUTPUT_RANGE_0__5V] = {0, 5000},
- [AD3552R_CH_OUTPUT_RANGE_0__10V] = {0, 10000},
- [AD3552R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000},
- [AD3552R_CH_OUTPUT_RANGE_NEG_10__10V] = {-10000, 10000}
-};
-
-enum ad3542r_ch_output_range {
- /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__2P5V,
- /* Range from 0 V to 3 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__3V,
- /* Range from 0 V to 5 V. Requires Rfb1x connection */
- AD3542R_CH_OUTPUT_RANGE_0__5V,
- /* Range from 0 V to 10 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_0__10V,
- /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V,
- /* Range from -5 V to 5 V. Requires Rfb2x connection */
- AD3542R_CH_OUTPUT_RANGE_NEG_5__5V,
-};
-
-static const s32 ad3542r_ch_ranges[][2] = {
- [AD3542R_CH_OUTPUT_RANGE_0__2P5V] = {0, 2500},
- [AD3542R_CH_OUTPUT_RANGE_0__3V] = {0, 3000},
- [AD3542R_CH_OUTPUT_RANGE_0__5V] = {0, 5000},
- [AD3542R_CH_OUTPUT_RANGE_0__10V] = {0, 10000},
- [AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V] = {-2500, 7500},
- [AD3542R_CH_OUTPUT_RANGE_NEG_5__5V] = {-5000, 5000}
-};
-
-enum ad3552r_ch_gain_scaling {
- /* Gain scaling of 1 */
- AD3552R_CH_GAIN_SCALING_1,
- /* Gain scaling of 0.5 */
- AD3552R_CH_GAIN_SCALING_0_5,
- /* Gain scaling of 0.25 */
- AD3552R_CH_GAIN_SCALING_0_25,
- /* Gain scaling of 0.125 */
- AD3552R_CH_GAIN_SCALING_0_125,
-};
-
-/* Gain * AD3552R_GAIN_SCALE */
-static const s32 gains_scaling_table[] = {
- [AD3552R_CH_GAIN_SCALING_1] = 1000,
- [AD3552R_CH_GAIN_SCALING_0_5] = 500,
- [AD3552R_CH_GAIN_SCALING_0_25] = 250,
- [AD3552R_CH_GAIN_SCALING_0_125] = 125
-};
-
-enum ad3552r_dev_attributes {
- /* - Direct register values */
- /* From 0-3 */
- AD3552R_SDO_DRIVE_STRENGTH,
- /*
- * 0 -> Internal Vref, vref_io pin floating (default)
- * 1 -> Internal Vref, vref_io driven by internal vref
- * 2 or 3 -> External Vref
- */
- AD3552R_VREF_SELECT,
- /* Read registers in ascending order if set. Else descending */
- AD3552R_ADDR_ASCENSION,
-};
-
-enum ad3552r_ch_attributes {
- /* DAC powerdown */
- AD3552R_CH_DAC_POWERDOWN,
- /* DAC amplifier powerdown */
- AD3552R_CH_AMPLIFIER_POWERDOWN,
- /* Select the output range. Select from enum ad3552r_ch_output_range */
- AD3552R_CH_OUTPUT_RANGE_SEL,
- /*
- * Over-rider the range selector in order to manually set the output
- * voltage range
- */
- AD3552R_CH_RANGE_OVERRIDE,
- /* Manually set the offset voltage */
- AD3552R_CH_GAIN_OFFSET,
- /* Sets the polarity of the offset. */
- AD3552R_CH_GAIN_OFFSET_POLARITY,
- /* PDAC gain scaling */
- AD3552R_CH_GAIN_SCALING_P,
- /* NDAC gain scaling */
- AD3552R_CH_GAIN_SCALING_N,
- /* Rfb value */
- AD3552R_CH_RFB,
- /* Channel select. When set allow Input -> DAC and Mask -> DAC */
- AD3552R_CH_SELECT,
-};
-
-struct ad3552r_ch_data {
- s32 scale_int;
- s32 scale_dec;
- s32 offset_int;
- s32 offset_dec;
- s16 gain_offset;
- u16 rfb;
- u8 n;
- u8 p;
- u8 range;
- bool range_override;
-};
-
-struct ad3552r_model_data {
- const char *model_name;
- enum ad3552r_id chip_id;
- unsigned int num_hw_channels;
- const s32 (*ranges_table)[2];
- int num_ranges;
- bool requires_output_range;
-};
+#include "ad3552r.h"
struct ad3552r_desc {
const struct ad3552r_model_data *model_data;
@@ -285,45 +29,6 @@ struct ad3552r_desc {
unsigned int num_ch;
};
-static const u16 addr_mask_map[][2] = {
- [AD3552R_ADDR_ASCENSION] = {
- AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
- AD3552R_MASK_ADDR_ASCENSION
- },
- [AD3552R_SDO_DRIVE_STRENGTH] = {
- AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
- AD3552R_MASK_SDO_DRIVE_STRENGTH
- },
- [AD3552R_VREF_SELECT] = {
- AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
- AD3552R_MASK_REFERENCE_VOLTAGE_SEL
- },
-};
-
-/* 0 -> reg addr, 1->ch0 mask, 2->ch1 mask */
-static const u16 addr_mask_map_ch[][3] = {
- [AD3552R_CH_DAC_POWERDOWN] = {
- AD3552R_REG_ADDR_POWERDOWN_CONFIG,
- AD3552R_MASK_CH_DAC_POWERDOWN(0),
- AD3552R_MASK_CH_DAC_POWERDOWN(1)
- },
- [AD3552R_CH_AMPLIFIER_POWERDOWN] = {
- AD3552R_REG_ADDR_POWERDOWN_CONFIG,
- AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0),
- AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1)
- },
- [AD3552R_CH_OUTPUT_RANGE_SEL] = {
- AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
- AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0),
- AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1)
- },
- [AD3552R_CH_SELECT] = {
- AD3552R_REG_ADDR_CH_SELECT_16B,
- AD3552R_MASK_CH(0),
- AD3552R_MASK_CH(1)
- }
-};
-
static u8 _ad3552r_reg_len(u8 addr)
{
switch (addr) {
@@ -399,11 +104,6 @@ static int ad3552r_read_reg(struct ad3552r_desc *dac, u8 addr, u16 *val)
return 0;
}
-static u16 ad3552r_field_prep(u16 val, u16 mask)
-{
- return (val << __ffs(mask)) & mask;
-}
-
/* Update field of a register, shift val if needed */
static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
u16 val)
@@ -416,21 +116,11 @@ static int ad3552r_update_reg_field(struct ad3552r_desc *dac, u8 addr, u16 mask,
return ret;
reg &= ~mask;
- reg |= ad3552r_field_prep(val, mask);
+ reg |= val;
return ad3552r_write_reg(dac, addr, reg);
}
-static int ad3552r_set_ch_value(struct ad3552r_desc *dac,
- enum ad3552r_ch_attributes attr,
- u8 ch,
- u16 val)
-{
- /* Update register related to attributes in chip */
- return ad3552r_update_reg_field(dac, addr_mask_map_ch[attr][0],
- addr_mask_map_ch[attr][ch + 1], val);
-}
-
#define AD3552R_CH_DAC(_idx) ((struct iio_chan_spec) { \
.type = IIO_VOLTAGE, \
.output = true, \
@@ -510,8 +200,14 @@ static int ad3552r_write_raw(struct iio_dev *indio_dev,
val);
break;
case IIO_CHAN_INFO_ENABLE:
- err = ad3552r_set_ch_value(dac, AD3552R_CH_DAC_POWERDOWN,
- chan->channel, !val);
+ if (chan->channel == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_DAC_POWERDOWN(0), !val);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_DAC_POWERDOWN(1), !val);
+
+ err = ad3552r_update_reg_field(dac, AD3552R_REG_ADDR_POWERDOWN_CONFIG,
+ AD3552R_MASK_CH_DAC_POWERDOWN(chan->channel),
+ val);
break;
default:
err = -EINVAL;
@@ -715,83 +411,9 @@ static int ad3552r_reset(struct ad3552r_desc *dac)
}
return ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_ADDR_ASCENSION][0],
- addr_mask_map[AD3552R_ADDR_ASCENSION][1],
- val);
-}
-
-static void ad3552r_get_custom_range(struct ad3552r_desc *dac, s32 i, s32 *v_min,
- s32 *v_max)
-{
- s64 vref, tmp, common, offset, gn, gp;
- /*
- * From datasheet formula (In Volts):
- * Vmin = 2.5 + [(GainN + Offset / 1024) * 2.5 * Rfb * 1.03]
- * Vmax = 2.5 - [(GainP + Offset / 1024) * 2.5 * Rfb * 1.03]
- * Calculus are converted to milivolts
- */
- vref = 2500;
- /* 2.5 * 1.03 * 1000 (To mV) */
- common = 2575 * dac->ch_data[i].rfb;
- offset = dac->ch_data[i].gain_offset;
-
- gn = gains_scaling_table[dac->ch_data[i].n];
- tmp = (1024 * gn + AD3552R_GAIN_SCALE * offset) * common;
- tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
- *v_max = vref + tmp;
-
- gp = gains_scaling_table[dac->ch_data[i].p];
- tmp = (1024 * gp - AD3552R_GAIN_SCALE * offset) * common;
- tmp = div_s64(tmp, 1024 * AD3552R_GAIN_SCALE);
- *v_min = vref - tmp;
-}
-
-static void ad3552r_calc_gain_and_offset(struct ad3552r_desc *dac, s32 ch)
-{
- s32 idx, v_max, v_min, span, rem;
- s64 tmp;
-
- if (dac->ch_data[ch].range_override) {
- ad3552r_get_custom_range(dac, ch, &v_min, &v_max);
- } else {
- /* Normal range */
- idx = dac->ch_data[ch].range;
- v_min = dac->model_data->ranges_table[idx][0];
- v_max = dac->model_data->ranges_table[idx][1];
- }
-
- /*
- * From datasheet formula:
- * Vout = Span * (D / 65536) + Vmin
- * Converted to scale and offset:
- * Scale = Span / 65536
- * Offset = 65536 * Vmin / Span
- *
- * Reminders are in micros in order to be printed as
- * IIO_VAL_INT_PLUS_MICRO
- */
- span = v_max - v_min;
- dac->ch_data[ch].scale_int = div_s64_rem(span, 65536, &rem);
- /* Do operations in microvolts */
- dac->ch_data[ch].scale_dec = DIV_ROUND_CLOSEST((s64)rem * 1000000,
- 65536);
-
- dac->ch_data[ch].offset_int = div_s64_rem(v_min * 65536, span, &rem);
- tmp = (s64)rem * 1000000;
- dac->ch_data[ch].offset_dec = div_s64(tmp, span);
-}
-
-static int ad3552r_find_range(const struct ad3552r_model_data *model_data,
- s32 *vals)
-{
- int i;
-
- for (i = 0; i < model_data->num_ranges; i++)
- if (vals[0] == model_data->ranges_table[i][0] * 1000 &&
- vals[1] == model_data->ranges_table[i][1] * 1000)
- return i;
-
- return -EINVAL;
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_A,
+ AD3552R_MASK_ADDR_ASCENSION,
+ FIELD_PREP(AD3552R_MASK_ADDR_ASCENSION, val));
}
static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
@@ -799,57 +421,30 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
u32 ch)
{
struct device *dev = &dac->spi->dev;
- u32 val;
int err;
u8 addr;
- u16 reg = 0, offset;
-
- struct fwnode_handle *gain_child __free(fwnode_handle)
- = fwnode_get_named_child_node(child,
- "custom-output-range-config");
- if (!gain_child)
- return dev_err_probe(dev, -EINVAL,
- "mandatory custom-output-range-config property missing\n");
-
- dac->ch_data[ch].range_override = 1;
- reg |= ad3552r_field_prep(1, AD3552R_MASK_CH_RANGE_OVERRIDE);
-
- err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-p", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-scaling-p property missing\n");
- reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_P);
- dac->ch_data[ch].p = val;
-
- err = fwnode_property_read_u32(gain_child, "adi,gain-scaling-n", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-scaling-n property missing\n");
- reg |= ad3552r_field_prep(val, AD3552R_MASK_CH_GAIN_SCALING_N);
- dac->ch_data[ch].n = val;
-
- err = fwnode_property_read_u32(gain_child, "adi,rfb-ohms", &val);
- if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,rfb-ohms property missing\n");
- dac->ch_data[ch].rfb = val;
+ u16 reg;
- err = fwnode_property_read_u32(gain_child, "adi,gain-offset", &val);
+ err = ad3552r_get_custom_gain(dev, child,
+ &dac->ch_data[ch].p,
+ &dac->ch_data[ch].n,
+ &dac->ch_data[ch].rfb,
+ &dac->ch_data[ch].gain_offset);
if (err)
- return dev_err_probe(dev, err,
- "mandatory adi,gain-offset property missing\n");
- dac->ch_data[ch].gain_offset = val;
+ return err;
- offset = abs((s32)val);
- reg |= ad3552r_field_prep((offset >> 8), AD3552R_MASK_CH_OFFSET_BIT_8);
+ dac->ch_data[ch].range_override = 1;
- reg |= ad3552r_field_prep((s32)val < 0, AD3552R_MASK_CH_OFFSET_POLARITY);
addr = AD3552R_REG_ADDR_CH_GAIN(ch);
err = ad3552r_write_reg(dac, addr,
- offset & AD3552R_MASK_CH_OFFSET_BITS_0_7);
+ abs((s32)dac->ch_data[ch].gain_offset) &
+ AD3552R_MASK_CH_OFFSET_BITS_0_7);
if (err)
return dev_err_probe(dev, err, "Error writing register\n");
+ reg = ad3552r_calc_custom_gain(dac->ch_data[ch].p, dac->ch_data[ch].n,
+ dac->ch_data[ch].gain_offset);
+
err = ad3552r_write_reg(dac, addr, reg);
if (err)
return dev_err_probe(dev, err, "Error writing register\n");
@@ -860,49 +455,31 @@ static int ad3552r_configure_custom_gain(struct ad3552r_desc *dac,
static int ad3552r_configure_device(struct ad3552r_desc *dac)
{
struct device *dev = &dac->spi->dev;
- int err, cnt = 0, voltage, delta = 100000;
- u32 vals[2], val, ch;
+ int err, cnt = 0;
+ u32 val, ch;
dac->gpio_ldac = devm_gpiod_get_optional(dev, "ldac", GPIOD_OUT_HIGH);
if (IS_ERR(dac->gpio_ldac))
return dev_err_probe(dev, PTR_ERR(dac->gpio_ldac),
"Error getting gpio ldac");
- voltage = devm_regulator_get_enable_read_voltage(dev, "vref");
- if (voltage < 0 && voltage != -ENODEV)
- return dev_err_probe(dev, voltage, "Error getting vref voltage\n");
-
- if (voltage == -ENODEV) {
- if (device_property_read_bool(dev, "adi,vref-out-en"))
- val = AD3552R_INTERNAL_VREF_PIN_2P5V;
- else
- val = AD3552R_INTERNAL_VREF_PIN_FLOATING;
- } else {
- if (voltage > 2500000 + delta || voltage < 2500000 - delta) {
- dev_warn(dev, "vref-supply must be 2.5V");
- return -EINVAL;
- }
- val = AD3552R_EXTERNAL_VREF_PIN_INPUT;
- }
+ err = ad3552r_get_ref_voltage(dev, &val);
+ if (err < 0)
+ return err;
err = ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_VREF_SELECT][0],
- addr_mask_map[AD3552R_VREF_SELECT][1],
- val);
+ AD3552R_REG_ADDR_SH_REFERENCE_CONFIG,
+ AD3552R_MASK_REFERENCE_VOLTAGE_SEL,
+ FIELD_PREP(AD3552R_MASK_REFERENCE_VOLTAGE_SEL, val));
if (err)
return err;
- err = device_property_read_u32(dev, "adi,sdo-drive-strength", &val);
+ err = ad3552r_get_drive_strength(dev, &val);
if (!err) {
- if (val > 3) {
- dev_err(dev, "adi,sdo-drive-strength must be less than 4\n");
- return -EINVAL;
- }
-
err = ad3552r_update_reg_field(dac,
- addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][0],
- addr_mask_map[AD3552R_SDO_DRIVE_STRENGTH][1],
- val);
+ AD3552R_REG_ADDR_INTERFACE_CONFIG_D,
+ AD3552R_MASK_SDO_DRIVE_STRENGTH,
+ FIELD_PREP(AD3552R_MASK_SDO_DRIVE_STRENGTH, val));
if (err)
return err;
}
@@ -923,24 +500,21 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
"reg must be less than %d\n",
dac->model_data->num_hw_channels);
- if (fwnode_property_present(child, "adi,output-range-microvolt")) {
- err = fwnode_property_read_u32_array(child,
- "adi,output-range-microvolt",
- vals,
- 2);
- if (err)
- return dev_err_probe(dev, err,
- "adi,output-range-microvolt property could not be parsed\n");
-
- err = ad3552r_find_range(dac->model_data, vals);
- if (err < 0)
- return dev_err_probe(dev, err,
- "Invalid adi,output-range-microvolt value\n");
-
- val = err;
- err = ad3552r_set_ch_value(dac,
- AD3552R_CH_OUTPUT_RANGE_SEL,
- ch, val);
+ err = ad3552r_get_output_range(dev, dac->model_data,
+ child, &val);
+ if (err && err != -ENOENT)
+ return err;
+
+ if (!err) {
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(0), val);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_OUTPUT_RANGE_SEL(1), val);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE,
+ AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch),
+ val);
if (err)
return err;
@@ -955,10 +529,17 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
return err;
}
- ad3552r_calc_gain_and_offset(dac, ch);
+ ad3552r_calc_gain_and_offset(&dac->ch_data[ch], dac->model_data);
dac->enabled_ch |= BIT(ch);
- err = ad3552r_set_ch_value(dac, AD3552R_CH_SELECT, ch, 1);
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH(0), 1);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH(1), 1);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_CH_SELECT_16B,
+ AD3552R_MASK_CH(ch), val);
if (err < 0)
return err;
@@ -970,8 +551,15 @@ static int ad3552r_configure_device(struct ad3552r_desc *dac)
/* Disable unused channels */
for_each_clear_bit(ch, &dac->enabled_ch,
dac->model_data->num_hw_channels) {
- err = ad3552r_set_ch_value(dac, AD3552R_CH_AMPLIFIER_POWERDOWN,
- ch, 1);
+ if (ch == 0)
+ val = FIELD_PREP(AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(0), 1);
+ else
+ val = FIELD_PREP(AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(1), 1);
+
+ err = ad3552r_update_reg_field(dac,
+ AD3552R_REG_ADDR_POWERDOWN_CONFIG,
+ AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch),
+ val);
if (err)
return err;
}
@@ -1140,3 +728,4 @@ module_spi_driver(ad3552r_driver);
MODULE_AUTHOR("Mihail Chindris <mihail.chindris@analog.com>");
MODULE_DESCRIPTION("Analog Device AD3552R DAC");
MODULE_LICENSE("GPL v2");
+MODULE_IMPORT_NS("IIO_AD3552R");
diff --git a/drivers/iio/dac/ad3552r.h b/drivers/iio/dac/ad3552r.h
new file mode 100644
index 000000000000..fd5a3dfd1d1c
--- /dev/null
+++ b/drivers/iio/dac/ad3552r.h
@@ -0,0 +1,228 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AD3552R Digital <-> Analog converters common header
+ *
+ * Copyright 2021-2024 Analog Devices Inc.
+ * Author: Angelo Dureghello <adureghello@baylibre.com>
+ */
+
+#ifndef __DRIVERS_IIO_DAC_AD3552R_H__
+#define __DRIVERS_IIO_DAC_AD3552R_H__
+
+/* Register addresses */
+/* Primary address space */
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_A 0x00
+#define AD3552R_MASK_SOFTWARE_RESET (BIT(7) | BIT(0))
+#define AD3552R_MASK_ADDR_ASCENSION BIT(5)
+#define AD3552R_MASK_SDO_ACTIVE BIT(4)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_B 0x01
+#define AD3552R_MASK_SINGLE_INST BIT(7)
+#define AD3552R_MASK_SHORT_INSTRUCTION BIT(3)
+#define AD3552R_REG_ADDR_DEVICE_CONFIG 0x02
+#define AD3552R_MASK_DEVICE_STATUS(n) BIT(4 + (n))
+#define AD3552R_MASK_CUSTOM_MODES GENMASK(3, 2)
+#define AD3552R_MASK_OPERATING_MODES GENMASK(1, 0)
+#define AD3552R_REG_ADDR_CHIP_TYPE 0x03
+#define AD3552R_MASK_CLASS GENMASK(7, 0)
+#define AD3552R_REG_ADDR_PRODUCT_ID_L 0x04
+#define AD3552R_REG_ADDR_PRODUCT_ID_H 0x05
+#define AD3552R_REG_ADDR_CHIP_GRADE 0x06
+#define AD3552R_MASK_GRADE GENMASK(7, 4)
+#define AD3552R_MASK_DEVICE_REVISION GENMASK(3, 0)
+#define AD3552R_REG_ADDR_SCRATCH_PAD 0x0A
+#define AD3552R_REG_ADDR_SPI_REVISION 0x0B
+#define AD3552R_REG_ADDR_VENDOR_L 0x0C
+#define AD3552R_REG_ADDR_VENDOR_H 0x0D
+#define AD3552R_REG_ADDR_STREAM_MODE 0x0E
+#define AD3552R_MASK_LENGTH GENMASK(7, 0)
+#define AD3552R_REG_ADDR_TRANSFER_REGISTER 0x0F
+#define AD3552R_MASK_MULTI_IO_MODE GENMASK(7, 6)
+#define AD3552R_MASK_STREAM_LENGTH_KEEP_VALUE BIT(2)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_C 0x10
+#define AD3552R_MASK_CRC_ENABLE \
+ (GENMASK(7, 6) | GENMASK(1, 0))
+#define AD3552R_MASK_STRICT_REGISTER_ACCESS BIT(5)
+#define AD3552R_REG_ADDR_INTERFACE_STATUS_A 0x11
+#define AD3552R_MASK_INTERFACE_NOT_READY BIT(7)
+#define AD3552R_MASK_CLOCK_COUNTING_ERROR BIT(5)
+#define AD3552R_MASK_INVALID_OR_NO_CRC BIT(3)
+#define AD3552R_MASK_WRITE_TO_READ_ONLY_REGISTER BIT(2)
+#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS BIT(1)
+#define AD3552R_MASK_REGISTER_ADDRESS_INVALID BIT(0)
+#define AD3552R_REG_ADDR_INTERFACE_CONFIG_D 0x14
+#define AD3552R_MASK_ALERT_ENABLE_PULLUP BIT(6)
+#define AD3552R_MASK_MEM_CRC_EN BIT(4)
+#define AD3552R_MASK_SDO_DRIVE_STRENGTH GENMASK(3, 2)
+#define AD3552R_MASK_DUAL_SPI_SYNCHROUNOUS_EN BIT(1)
+#define AD3552R_MASK_SPI_CONFIG_DDR BIT(0)
+#define AD3552R_REG_ADDR_SH_REFERENCE_CONFIG 0x15
+#define AD3552R_MASK_IDUMP_FAST_MODE BIT(6)
+#define AD3552R_MASK_SAMPLE_HOLD_DIFF_USER_EN BIT(5)
+#define AD3552R_MASK_SAMPLE_HOLD_USER_TRIM GENMASK(4, 3)
+#define AD3552R_MASK_SAMPLE_HOLD_USER_ENABLE BIT(2)
+#define AD3552R_MASK_REFERENCE_VOLTAGE_SEL GENMASK(1, 0)
+#define AD3552R_REG_ADDR_ERR_ALARM_MASK 0x16
+#define AD3552R_MASK_REF_RANGE_ALARM BIT(6)
+#define AD3552R_MASK_CLOCK_COUNT_ERR_ALARM BIT(5)
+#define AD3552R_MASK_MEM_CRC_ERR_ALARM BIT(4)
+#define AD3552R_MASK_SPI_CRC_ERR_ALARM BIT(3)
+#define AD3552R_MASK_WRITE_TO_READ_ONLY_ALARM BIT(2)
+#define AD3552R_MASK_PARTIAL_REGISTER_ACCESS_ALARM BIT(1)
+#define AD3552R_MASK_REGISTER_ADDRESS_INVALID_ALARM BIT(0)
+#define AD3552R_REG_ADDR_ERR_STATUS 0x17
+#define AD3552R_MASK_REF_RANGE_ERR_STATUS BIT(6)
+#define AD3552R_MASK_STREAM_EXCEEDS_DAC_ERR_STATUS BIT(5)
+#define AD3552R_MASK_MEM_CRC_ERR_STATUS BIT(4)
+#define AD3552R_MASK_RESET_STATUS BIT(0)
+#define AD3552R_REG_ADDR_POWERDOWN_CONFIG 0x18
+#define AD3552R_MASK_CH_DAC_POWERDOWN(ch) BIT(4 + (ch))
+#define AD3552R_MASK_CH_AMPLIFIER_POWERDOWN(ch) BIT(ch)
+#define AD3552R_REG_ADDR_CH0_CH1_OUTPUT_RANGE 0x19
+#define AD3552R_MASK_CH0_RANGE GENMASK(2, 0)
+#define AD3552R_MASK_CH1_RANGE GENMASK(6, 4)
+#define AD3552R_MASK_CH_OUTPUT_RANGE GENMASK(7, 0)
+#define AD3552R_MASK_CH_OUTPUT_RANGE_SEL(ch) \
+ ((ch) ? GENMASK(7, 4) : GENMASK(3, 0))
+#define AD3552R_REG_ADDR_CH_OFFSET(ch) (0x1B + (ch) * 2)
+#define AD3552R_MASK_CH_OFFSET_BITS_0_7 GENMASK(7, 0)
+#define AD3552R_REG_ADDR_CH_GAIN(ch) (0x1C + (ch) * 2)
+#define AD3552R_MASK_CH_RANGE_OVERRIDE BIT(7)
+#define AD3552R_MASK_CH_GAIN_SCALING_N GENMASK(6, 5)
+#define AD3552R_MASK_CH_GAIN_SCALING_P GENMASK(4, 3)
+#define AD3552R_MASK_CH_OFFSET_POLARITY BIT(2)
+#define AD3552R_MASK_CH_OFFSET_BIT_8 BIT(8)
+/*
+ * Secondary region
+ * For multibyte registers specify the highest address because the access is
+ * done in descending order
+ */
+#define AD3552R_SECONDARY_REGION_START 0x28
+#define AD3552R_REG_ADDR_HW_LDAC_16B 0x28
+#define AD3552R_REG_ADDR_CH_DAC_16B(ch) (0x2C - (1 - (ch)) * 2)
+#define AD3552R_REG_ADDR_DAC_PAGE_MASK_16B 0x2E
+#define AD3552R_REG_ADDR_CH_SELECT_16B 0x2F
+#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_16B 0x31
+#define AD3552R_REG_ADDR_SW_LDAC_16B 0x32
+#define AD3552R_REG_ADDR_CH_INPUT_16B(ch) (0x36 - (1 - (ch)) * 2)
+/* 3 bytes registers */
+#define AD3552R_REG_START_24B 0x37
+#define AD3552R_REG_ADDR_HW_LDAC_24B 0x37
+#define AD3552R_REG_ADDR_CH_DAC_24B(ch) (0x3D - (1 - (ch)) * 3)
+#define AD3552R_REG_ADDR_DAC_PAGE_MASK_24B 0x40
+#define AD3552R_REG_ADDR_CH_SELECT_24B 0x41
+#define AD3552R_REG_ADDR_INPUT_PAGE_MASK_24B 0x44
+#define AD3552R_REG_ADDR_SW_LDAC_24B 0x45
+#define AD3552R_REG_ADDR_CH_INPUT_24B(ch) (0x4B - (1 - (ch)) * 3)
+
+#define AD3552R_MAX_CH 2
+#define AD3552R_MASK_CH(ch) BIT(ch)
+#define AD3552R_MASK_ALL_CH GENMASK(1, 0)
+#define AD3552R_MAX_REG_SIZE 3
+#define AD3552R_READ_BIT BIT(7)
+#define AD3552R_ADDR_MASK GENMASK(6, 0)
+#define AD3552R_MASK_DAC_12B GENMASK(15, 4)
+#define AD3552R_DEFAULT_CONFIG_B_VALUE 0x8
+#define AD3552R_SCRATCH_PAD_TEST_VAL1 0x34
+#define AD3552R_SCRATCH_PAD_TEST_VAL2 0xB2
+#define AD3552R_GAIN_SCALE 1000
+#define AD3552R_LDAC_PULSE_US 100
+
+#define AD3552R_CH0_ACTIVE BIT(0)
+#define AD3552R_CH1_ACTIVE BIT(1)
+
+#define AD3552R_MAX_RANGES 5
+#define AD3542R_MAX_RANGES 6
+#define AD3552R_QUAD_SPI 2
+
+extern const s32 ad3552r_ch_ranges[AD3552R_MAX_RANGES][2];
+extern const s32 ad3542r_ch_ranges[AD3542R_MAX_RANGES][2];
+
+enum ad3552r_id {
+ AD3541R_ID = 0x400b,
+ AD3542R_ID = 0x4009,
+ AD3551R_ID = 0x400a,
+ AD3552R_ID = 0x4008,
+};
+
+struct ad3552r_model_data {
+ const char *model_name;
+ enum ad3552r_id chip_id;
+ unsigned int num_hw_channels;
+ const s32 (*ranges_table)[2];
+ int num_ranges;
+ bool requires_output_range;
+};
+
+struct ad3552r_ch_data {
+ s32 scale_int;
+ s32 scale_dec;
+ s32 offset_int;
+ s32 offset_dec;
+ s16 gain_offset;
+ u16 rfb;
+ u8 n;
+ u8 p;
+ u8 range;
+ bool range_override;
+};
+
+enum ad3552r_ch_gain_scaling {
+ /* Gain scaling of 1 */
+ AD3552R_CH_GAIN_SCALING_1,
+ /* Gain scaling of 0.5 */
+ AD3552R_CH_GAIN_SCALING_0_5,
+ /* Gain scaling of 0.25 */
+ AD3552R_CH_GAIN_SCALING_0_25,
+ /* Gain scaling of 0.125 */
+ AD3552R_CH_GAIN_SCALING_0_125,
+};
+
+enum ad3552r_ch_vref_select {
+ /* Internal source with Vref I/O floating */
+ AD3552R_INTERNAL_VREF_PIN_FLOATING,
+ /* Internal source with Vref I/O at 2.5V */
+ AD3552R_INTERNAL_VREF_PIN_2P5V,
+ /* External source with Vref I/O as input */
+ AD3552R_EXTERNAL_VREF_PIN_INPUT
+};
+
+enum ad3542r_ch_output_range {
+ /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__2P5V,
+ /* Range from 0 V to 3 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__3V,
+ /* Range from 0 V to 5 V. Requires Rfb1x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__5V,
+ /* Range from 0 V to 10 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_0__10V,
+ /* Range from -2.5 V to 7.5 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_NEG_2P5__7P5V,
+ /* Range from -5 V to 5 V. Requires Rfb2x connection */
+ AD3542R_CH_OUTPUT_RANGE_NEG_5__5V,
+};
+
+enum ad3552r_ch_output_range {
+ /* Range from 0 V to 2.5 V. Requires Rfb1x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__2P5V,
+ /* Range from 0 V to 5 V. Requires Rfb1x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__5V,
+ /* Range from 0 V to 10 V. Requires Rfb2x connection */
+ AD3552R_CH_OUTPUT_RANGE_0__10V,
+ /* Range from -5 V to 5 V. Requires Rfb2x connection */
+ AD3552R_CH_OUTPUT_RANGE_NEG_5__5V,
+ /* Range from -10 V to 10 V. Requires Rfb4x connection */
+ AD3552R_CH_OUTPUT_RANGE_NEG_10__10V,
+};
+
+int ad3552r_get_output_range(struct device *dev,
+ const struct ad3552r_model_data *model_info,
+ struct fwnode_handle *child, u32 *val);
+int ad3552r_get_custom_gain(struct device *dev, struct fwnode_handle *child,
+ u8 *gs_p, u8 *gs_n, u16 *rfb, s16 *goffs);
+u16 ad3552r_calc_custom_gain(u8 p, u8 n, s16 goffs);
+int ad3552r_get_ref_voltage(struct device *dev, u32 *val);
+int ad3552r_get_drive_strength(struct device *dev, u32 *val);
+void ad3552r_calc_gain_and_offset(struct ad3552r_ch_data *ch_data,
+ const struct ad3552r_model_data *model_data);
+
+#endif /* __DRIVERS_IIO_DAC_AD3552R_H__ */
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 2e3e33f92bc0..392a1c7aee03 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -47,7 +47,6 @@ struct ad5380_chip_info {
* struct ad5380_state - driver instance specific data
* @regmap: regmap instance used by the device
* @chip_info: chip model specific constants, available modes etc
- * @vref_reg: vref supply regulator
* @vref: actual reference voltage used in uA
* @pwr_down: whether the chip is currently in power down mode
* @lock: lock to protect the data buffer during regmap ops
@@ -55,7 +54,6 @@ struct ad5380_chip_info {
struct ad5380_state {
struct regmap *regmap;
const struct ad5380_chip_info *chip_info;
- struct regulator *vref_reg;
int vref;
bool pwr_down;
struct mutex lock;
@@ -341,14 +339,14 @@ static const struct ad5380_chip_info ad5380_chip_info_tbl[] = {
},
};
-static int ad5380_alloc_channels(struct iio_dev *indio_dev)
+static int ad5380_alloc_channels(struct device *dev, struct iio_dev *indio_dev)
{
struct ad5380_state *st = iio_priv(indio_dev);
struct iio_chan_spec *channels;
unsigned int i;
- channels = kcalloc(st->chip_info->num_channels,
- sizeof(struct iio_chan_spec), GFP_KERNEL);
+ channels = devm_kcalloc(dev, st->chip_info->num_channels,
+ sizeof(struct iio_chan_spec), GFP_KERNEL);
if (!channels)
return -ENOMEM;
@@ -379,7 +377,6 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
}
st = iio_priv(indio_dev);
- dev_set_drvdata(dev, indio_dev);
st->chip_info = &ad5380_chip_info_tbl[type];
st->regmap = regmap;
@@ -391,68 +388,32 @@ static int ad5380_probe(struct device *dev, struct regmap *regmap,
mutex_init(&st->lock);
- ret = ad5380_alloc_channels(indio_dev);
- if (ret) {
- dev_err(dev, "Failed to allocate channel spec: %d\n", ret);
- return ret;
- }
+ ret = ad5380_alloc_channels(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to allocate channel spec\n");
if (st->chip_info->int_vref == 2500)
ctrl |= AD5380_CTRL_INT_VREF_2V5;
- st->vref_reg = devm_regulator_get(dev, "vref");
- if (!IS_ERR(st->vref_reg)) {
- ret = regulator_enable(st->vref_reg);
- if (ret) {
- dev_err(dev, "Failed to enable vref regulators: %d\n",
- ret);
- goto error_free_reg;
- }
-
- ret = regulator_get_voltage(st->vref_reg);
- if (ret < 0)
- goto error_disable_reg;
-
- st->vref = ret / 1000;
- } else {
+ ret = devm_regulator_get_enable_read_voltage(dev, "vref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "Failed to get vref voltage\n");
+ if (ret == -ENODEV) {
st->vref = st->chip_info->int_vref;
ctrl |= AD5380_CTRL_INT_VREF_EN;
+ } else {
+ st->vref = ret / 1000;
}
ret = regmap_write(st->regmap, AD5380_REG_SF_CTRL, ctrl);
- if (ret) {
- dev_err(dev, "Failed to write to device: %d\n", ret);
- goto error_disable_reg;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to write to device\n");
- ret = iio_device_register(indio_dev);
- if (ret) {
- dev_err(dev, "Failed to register iio device: %d\n", ret);
- goto error_disable_reg;
- }
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register iio device\n");
return 0;
-
-error_disable_reg:
- if (!IS_ERR(st->vref_reg))
- regulator_disable(st->vref_reg);
-error_free_reg:
- kfree(indio_dev->channels);
-
- return ret;
-}
-
-static void ad5380_remove(struct device *dev)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5380_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- kfree(indio_dev->channels);
-
- if (!IS_ERR(st->vref_reg))
- regulator_disable(st->vref_reg);
}
static bool ad5380_reg_false(struct device *dev, unsigned int reg)
@@ -486,11 +447,6 @@ static int ad5380_spi_probe(struct spi_device *spi)
return ad5380_probe(&spi->dev, regmap, id->driver_data, id->name);
}
-static void ad5380_spi_remove(struct spi_device *spi)
-{
- ad5380_remove(&spi->dev);
-}
-
static const struct spi_device_id ad5380_spi_ids[] = {
{ "ad5380-3", ID_AD5380_3 },
{ "ad5380-5", ID_AD5380_5 },
@@ -517,7 +473,6 @@ static struct spi_driver ad5380_spi_driver = {
.name = "ad5380",
},
.probe = ad5380_spi_probe,
- .remove = ad5380_spi_remove,
.id_table = ad5380_spi_ids,
};
@@ -559,11 +514,6 @@ static int ad5380_i2c_probe(struct i2c_client *i2c)
return ad5380_probe(&i2c->dev, regmap, id->driver_data, id->name);
}
-static void ad5380_i2c_remove(struct i2c_client *i2c)
-{
- ad5380_remove(&i2c->dev);
-}
-
static const struct i2c_device_id ad5380_i2c_ids[] = {
{ "ad5380-3", ID_AD5380_3 },
{ "ad5380-5", ID_AD5380_5 },
@@ -590,7 +540,6 @@ static struct i2c_driver ad5380_i2c_driver = {
.name = "ad5380",
},
.probe = ad5380_i2c_probe,
- .remove = ad5380_i2c_remove,
.id_table = ad5380_i2c_ids,
};
diff --git a/drivers/iio/dac/ad5421.c b/drivers/iio/dac/ad5421.c
index 7644acfd879e..1462ee640b16 100644
--- a/drivers/iio/dac/ad5421.c
+++ b/drivers/iio/dac/ad5421.c
@@ -384,7 +384,7 @@ static int ad5421_write_raw(struct iio_dev *indio_dev,
static int ad5421_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ad5421_state *st = iio_priv(indio_dev);
unsigned int mask;
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 708629efc157..6ad99f97eed5 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -32,7 +32,6 @@
* struct ad5446_state - driver instance specific data
* @dev: this device
* @chip_info: chip model specific constants, available modes etc
- * @reg: supply regulator
* @vref_mv: actual reference voltage used
* @cached_val: store/retrieve values during power down
* @pwr_down_mode: power down mode (1k, 100k or tristate)
@@ -43,7 +42,6 @@
struct ad5446_state {
struct device *dev;
const struct ad5446_chip_info *chip_info;
- struct regulator *reg;
unsigned short vref_mv;
unsigned cached_val;
unsigned pwr_down_mode;
@@ -226,32 +224,15 @@ static int ad5446_probe(struct device *dev, const char *name,
{
struct ad5446_state *st;
struct iio_dev *indio_dev;
- struct regulator *reg;
- int ret, voltage_uv = 0;
-
- reg = devm_regulator_get(dev, "vcc");
- if (!IS_ERR(reg)) {
- ret = regulator_enable(reg);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(reg);
- if (ret < 0)
- goto error_disable_reg;
-
- voltage_uv = ret;
- }
+ int ret;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
- if (indio_dev == NULL) {
- ret = -ENOMEM;
- goto error_disable_reg;
- }
+ if (!indio_dev)
+ return -ENOMEM;
+
st = iio_priv(indio_dev);
st->chip_info = chip_info;
- dev_set_drvdata(dev, indio_dev);
- st->reg = reg;
st->dev = dev;
indio_dev->name = name;
@@ -264,33 +245,19 @@ static int ad5446_probe(struct device *dev, const char *name,
st->pwr_down_mode = MODE_PWRDWN_1k;
- if (st->chip_info->int_vref_mv)
- st->vref_mv = st->chip_info->int_vref_mv;
- else if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else
- dev_warn(dev, "reference voltage unspecified\n");
-
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg;
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(reg))
- regulator_disable(reg);
- return ret;
-}
-
-static void ad5446_remove(struct device *dev)
-{
- struct iio_dev *indio_dev = dev_get_drvdata(dev);
- struct ad5446_state *st = iio_priv(indio_dev);
+ ret = devm_regulator_get_enable_read_voltage(dev, "vcc");
+ if (ret < 0 && ret != -ENODEV)
+ return ret;
+ if (ret == -ENODEV) {
+ if (chip_info->int_vref_mv)
+ st->vref_mv = chip_info->int_vref_mv;
+ else
+ dev_warn(dev, "reference voltage unspecified\n");
+ } else {
+ st->vref_mv = ret / 1000;
+ }
- iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ return devm_iio_device_register(dev, indio_dev);
}
#if IS_ENABLED(CONFIG_SPI_MASTER)
@@ -491,18 +458,12 @@ static int ad5446_spi_probe(struct spi_device *spi)
&ad5446_spi_chip_info[id->driver_data]);
}
-static void ad5446_spi_remove(struct spi_device *spi)
-{
- ad5446_remove(&spi->dev);
-}
-
static struct spi_driver ad5446_spi_driver = {
.driver = {
.name = "ad5446",
.of_match_table = ad5446_of_ids,
},
.probe = ad5446_spi_probe,
- .remove = ad5446_spi_remove,
.id_table = ad5446_spi_ids,
};
@@ -575,11 +536,6 @@ static int ad5446_i2c_probe(struct i2c_client *i2c)
&ad5446_i2c_chip_info[id->driver_data]);
}
-static void ad5446_i2c_remove(struct i2c_client *i2c)
-{
- ad5446_remove(&i2c->dev);
-}
-
static const struct i2c_device_id ad5446_i2c_ids[] = {
{"ad5301", ID_AD5602},
{"ad5311", ID_AD5612},
@@ -596,7 +552,6 @@ static struct i2c_driver ad5446_i2c_driver = {
.name = "ad5446",
},
.probe = ad5446_i2c_probe,
- .remove = ad5446_i2c_remove,
.id_table = ad5446_i2c_ids,
};
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index e6c5be728bb2..ff0765c8af47 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -270,38 +270,29 @@ static const struct iio_chan_spec ad5504_channels[] = {
static int ad5504_probe(struct spi_device *spi)
{
- struct ad5504_platform_data *pdata = spi->dev.platform_data;
+ const struct ad5504_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad5504_state *st;
- struct regulator *reg;
- int ret, voltage_uv = 0;
+ int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
- reg = devm_regulator_get(&spi->dev, "vcc");
- if (!IS_ERR(reg)) {
- ret = regulator_enable(reg);
- if (ret)
- return ret;
- ret = regulator_get_voltage(reg);
- if (ret < 0)
- goto error_disable_reg;
+ st = iio_priv(indio_dev);
- voltage_uv = ret;
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc");
+ if (ret < 0 && ret != -ENODEV)
+ return ret;
+ if (ret == -ENODEV) {
+ if (pdata->vref_mv)
+ st->vref_mv = pdata->vref_mv;
+ else
+ dev_warn(&spi->dev, "reference voltage unspecified\n");
+ } else {
+ st->vref_mv = ret / 1000;
}
- spi_set_drvdata(spi, indio_dev);
- st = iio_priv(indio_dev);
- if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else if (pdata)
- st->vref_mv = pdata->vref_mv;
- else
- dev_warn(&spi->dev, "reference voltage unspecified\n");
-
- st->reg = reg;
st->spi = spi;
indio_dev->name = spi_get_device_id(st->spi)->name;
indio_dev->info = &ad5504_info;
@@ -320,31 +311,10 @@ static int ad5504_probe(struct spi_device *spi)
spi_get_device_id(st->spi)->name,
indio_dev);
if (ret)
- goto error_disable_reg;
+ return ret;
}
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg;
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(reg))
- regulator_disable(reg);
-
- return ret;
-}
-
-static void ad5504_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad5504_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
-
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id ad5504_id[] = {
@@ -359,7 +329,6 @@ static struct spi_driver ad5504_driver = {
.name = "ad5504",
},
.probe = ad5504_probe,
- .remove = ad5504_remove,
.id_table = ad5504_id,
};
module_spi_driver(ad5504_driver);
diff --git a/drivers/iio/dac/ad5592r-base.c b/drivers/iio/dac/ad5592r-base.c
index 4763402dbcd6..50d19304bacb 100644
--- a/drivers/iio/dac/ad5592r-base.c
+++ b/drivers/iio/dac/ad5592r-base.c
@@ -665,7 +665,7 @@ error_disable_reg:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(ad5592r_probe, IIO_AD5592R);
+EXPORT_SYMBOL_NS_GPL(ad5592r_probe, "IIO_AD5592R");
void ad5592r_remove(struct device *dev)
{
@@ -679,7 +679,7 @@ void ad5592r_remove(struct device *dev)
if (st->reg)
regulator_disable(st->reg);
}
-EXPORT_SYMBOL_NS_GPL(ad5592r_remove, IIO_AD5592R);
+EXPORT_SYMBOL_NS_GPL(ad5592r_remove, "IIO_AD5592R");
MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters");
diff --git a/drivers/iio/dac/ad5592r.c b/drivers/iio/dac/ad5592r.c
index 32d950bbb1ca..fd82d8701322 100644
--- a/drivers/iio/dac/ad5592r.c
+++ b/drivers/iio/dac/ad5592r.c
@@ -168,4 +168,4 @@ module_spi_driver(ad5592r_spi_driver);
MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5592R multi-channel converters");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD5592R);
+MODULE_IMPORT_NS("IIO_AD5592R");
diff --git a/drivers/iio/dac/ad5593r.c b/drivers/iio/dac/ad5593r.c
index 62e1fbb9e910..ddd13ad821a7 100644
--- a/drivers/iio/dac/ad5593r.c
+++ b/drivers/iio/dac/ad5593r.c
@@ -147,4 +147,4 @@ module_i2c_driver(ad5593r_driver);
MODULE_AUTHOR("Paul Cercueil <paul.cercueil@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5593R multi-channel converters");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD5592R);
+MODULE_IMPORT_NS("IIO_AD5592R");
diff --git a/drivers/iio/dac/ad5624r.h b/drivers/iio/dac/ad5624r.h
index 13964f3a22a4..14a439b06eb6 100644
--- a/drivers/iio/dac/ad5624r.h
+++ b/drivers/iio/dac/ad5624r.h
@@ -54,7 +54,6 @@ struct ad5624r_chip_info {
struct ad5624r_state {
struct spi_device *us;
const struct ad5624r_chip_info *chip_info;
- struct regulator *reg;
unsigned short vref_mv;
unsigned pwr_down_mask;
unsigned pwr_down_mode;
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index 9304d0499bae..2fd38ac8f698 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -223,50 +223,26 @@ static int ad5624r_probe(struct spi_device *spi)
{
struct ad5624r_state *st;
struct iio_dev *indio_dev;
- int ret, voltage_uv = 0;
+ bool external_vref;
+ int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg = devm_regulator_get_optional(&spi->dev, "vref");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(st->reg);
- if (ret < 0)
- goto error_disable_reg;
-
- voltage_uv = ret;
- } else {
- if (PTR_ERR(st->reg) != -ENODEV)
- return PTR_ERR(st->reg);
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
+ if (ret == -ENODEV)
/* Backwards compatibility. This naming is not correct */
- st->reg = devm_regulator_get_optional(&spi->dev, "vcc");
- if (!IS_ERR(st->reg)) {
- ret = regulator_enable(st->reg);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(st->reg);
- if (ret < 0)
- goto error_disable_reg;
-
- voltage_uv = ret;
- }
- }
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vcc");
+ if (ret < 0 && ret != -ENODEV)
+ return ret;
+
+ external_vref = ret != -ENODEV;
+ st->vref_mv = external_vref ? ret / 1000 : st->chip_info->int_vref_mv;
- spi_set_drvdata(spi, indio_dev);
st->chip_info =
&ad5624r_chip_info_tbl[spi_get_device_id(spi)->driver_data];
- if (voltage_uv)
- st->vref_mv = voltage_uv / 1000;
- else
- st->vref_mv = st->chip_info->int_vref_mv;
-
st->us = spi;
indio_dev->name = spi_get_device_id(spi)->name;
@@ -276,31 +252,11 @@ static int ad5624r_probe(struct spi_device *spi)
indio_dev->num_channels = AD5624R_DAC_CHANNELS;
ret = ad5624r_spi_write(spi, AD5624R_CMD_INTERNAL_REFER_SETUP, 0,
- !!voltage_uv, 16);
- if (ret)
- goto error_disable_reg;
-
- ret = iio_device_register(indio_dev);
+ external_vref, 16);
if (ret)
- goto error_disable_reg;
-
- return 0;
-
-error_disable_reg:
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
-
- return ret;
-}
-
-static void ad5624r_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad5624r_state *st = iio_priv(indio_dev);
+ return ret;
- iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg))
- regulator_disable(st->reg);
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id ad5624r_id[] = {
@@ -319,7 +275,6 @@ static struct spi_driver ad5624r_driver = {
.name = "ad5624r",
},
.probe = ad5624r_probe,
- .remove = ad5624r_remove,
.id_table = ad5624r_id,
};
module_spi_driver(ad5624r_driver);
diff --git a/drivers/iio/dac/ad5686-spi.c b/drivers/iio/dac/ad5686-spi.c
index 8ba2ea70451a..39b5dad0d6a5 100644
--- a/drivers/iio/dac/ad5686-spi.c
+++ b/drivers/iio/dac/ad5686-spi.c
@@ -135,4 +135,4 @@ module_spi_driver(ad5686_spi_driver);
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5686 and similar multi-channel DACs");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD5686);
+MODULE_IMPORT_NS("IIO_AD5686");
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 57cc0f0eedc6..8dc578b08784 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -543,7 +543,7 @@ error_disable_reg:
regulator_disable(st->reg);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(ad5686_probe, IIO_AD5686);
+EXPORT_SYMBOL_NS_GPL(ad5686_probe, "IIO_AD5686");
void ad5686_remove(struct device *dev)
{
@@ -554,7 +554,7 @@ void ad5686_remove(struct device *dev)
if (!IS_ERR(st->reg))
regulator_disable(st->reg);
}
-EXPORT_SYMBOL_NS_GPL(ad5686_remove, IIO_AD5686);
+EXPORT_SYMBOL_NS_GPL(ad5686_remove, "IIO_AD5686");
MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5686/85/84 DAC");
diff --git a/drivers/iio/dac/ad5696-i2c.c b/drivers/iio/dac/ad5696-i2c.c
index 81541f755a3e..bbcda246c547 100644
--- a/drivers/iio/dac/ad5696-i2c.c
+++ b/drivers/iio/dac/ad5696-i2c.c
@@ -125,4 +125,4 @@ module_i2c_driver(ad5686_i2c_driver);
MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD5686 and similar multi-channel DACs");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_AD5686);
+MODULE_IMPORT_NS("IIO_AD5686");
diff --git a/drivers/iio/dac/ad5755.c b/drivers/iio/dac/ad5755.c
index 0b24cb19ac9d..05e80b6ae2cc 100644
--- a/drivers/iio/dac/ad5755.c
+++ b/drivers/iio/dac/ad5755.c
@@ -699,7 +699,6 @@ static const struct ad5755_platform_data ad5755_default_pdata = {
static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
{
- struct fwnode_handle *pp;
struct ad5755_platform_data *pdata;
unsigned int tmp;
unsigned int tmparray[3];
@@ -746,11 +745,12 @@ static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
}
devnr = 0;
- device_for_each_child_node(dev, pp) {
+ device_for_each_child_node_scoped(dev, pp) {
if (devnr >= AD5755_NUM_CHANNELS) {
dev_err(dev,
"There are too many channels defined in DT\n");
- goto error_out;
+ devm_kfree(dev, pdata);
+ return NULL;
}
pdata->dac[devnr].mode = AD5755_MODE_CURRENT_4mA_20mA;
@@ -800,11 +800,6 @@ static struct ad5755_platform_data *ad5755_parse_fw(struct device *dev)
}
return pdata;
-
- error_out:
- fwnode_handle_put(pp);
- devm_kfree(dev, pdata);
- return NULL;
}
static int ad5755_probe(struct spi_device *spi)
diff --git a/drivers/iio/dac/ad5761.c b/drivers/iio/dac/ad5761.c
index 6aa1a068adb0..0aa5ba7f4654 100644
--- a/drivers/iio/dac/ad5761.c
+++ b/drivers/iio/dac/ad5761.c
@@ -53,7 +53,6 @@ enum ad5761_supported_device_ids {
/**
* struct ad5761_state - driver instance specific data
* @spi: spi_device
- * @vref_reg: reference voltage regulator
* @use_intref: true when the internal voltage reference is used
* @vref: actual voltage reference in mVolts
* @range: output range mode used
@@ -62,7 +61,6 @@ enum ad5761_supported_device_ids {
*/
struct ad5761_state {
struct spi_device *spi;
- struct regulator *vref_reg;
struct mutex lock;
bool use_intref;
@@ -287,63 +285,6 @@ static const struct ad5761_chip_info ad5761_chip_infos[] = {
},
};
-static int ad5761_get_vref(struct ad5761_state *st,
- const struct ad5761_chip_info *chip_info)
-{
- int ret;
-
- st->vref_reg = devm_regulator_get_optional(&st->spi->dev, "vref");
- if (PTR_ERR(st->vref_reg) == -ENODEV) {
- /* Use Internal regulator */
- if (!chip_info->int_vref) {
- dev_err(&st->spi->dev,
- "Voltage reference not found\n");
- return -EIO;
- }
-
- st->use_intref = true;
- st->vref = chip_info->int_vref;
- return 0;
- }
-
- if (IS_ERR(st->vref_reg)) {
- dev_err(&st->spi->dev,
- "Error getting voltage reference regulator\n");
- return PTR_ERR(st->vref_reg);
- }
-
- ret = regulator_enable(st->vref_reg);
- if (ret) {
- dev_err(&st->spi->dev,
- "Failed to enable voltage reference\n");
- return ret;
- }
-
- ret = regulator_get_voltage(st->vref_reg);
- if (ret < 0) {
- dev_err(&st->spi->dev,
- "Failed to get voltage reference value\n");
- goto disable_regulator_vref;
- }
-
- if (ret < 2000000 || ret > 3000000) {
- dev_warn(&st->spi->dev,
- "Invalid external voltage ref. value %d uV\n", ret);
- ret = -EIO;
- goto disable_regulator_vref;
- }
-
- st->vref = ret / 1000;
- st->use_intref = false;
-
- return 0;
-
-disable_regulator_vref:
- regulator_disable(st->vref_reg);
- st->vref_reg = NULL;
- return ret;
-}
-
static int ad5761_probe(struct spi_device *spi)
{
struct iio_dev *iio_dev;
@@ -361,11 +302,28 @@ static int ad5761_probe(struct spi_device *spi)
st = iio_priv(iio_dev);
st->spi = spi;
- spi_set_drvdata(spi, iio_dev);
- ret = ad5761_get_vref(st, chip_info);
- if (ret)
- return ret;
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(&spi->dev, ret,
+ "Failed to get voltage reference value\n");
+ if (ret == -ENODEV) {
+ /* Use Internal regulator */
+ if (!chip_info->int_vref)
+ return dev_err_probe(&spi->dev, -EIO,
+ "Voltage reference not found\n");
+
+ st->use_intref = true;
+ st->vref = chip_info->int_vref;
+ } else {
+ if (ret < 2000000 || ret > 3000000)
+ return dev_err_probe(&spi->dev, -EIO,
+ "Invalid external voltage ref. value %d uV\n",
+ ret);
+
+ st->use_intref = false;
+ st->vref = ret / 1000;
+ }
if (pdata)
voltage_range = pdata->voltage_range;
@@ -374,35 +332,15 @@ static int ad5761_probe(struct spi_device *spi)
ret = ad5761_spi_set_range(st, voltage_range);
if (ret)
- goto disable_regulator_err;
+ return ret;
iio_dev->info = &ad5761_info;
iio_dev->modes = INDIO_DIRECT_MODE;
iio_dev->channels = &chip_info->channel;
iio_dev->num_channels = 1;
iio_dev->name = spi_get_device_id(st->spi)->name;
- ret = iio_device_register(iio_dev);
- if (ret)
- goto disable_regulator_err;
-
- return 0;
-
-disable_regulator_err:
- if (!IS_ERR_OR_NULL(st->vref_reg))
- regulator_disable(st->vref_reg);
-
- return ret;
-}
-
-static void ad5761_remove(struct spi_device *spi)
-{
- struct iio_dev *iio_dev = spi_get_drvdata(spi);
- struct ad5761_state *st = iio_priv(iio_dev);
-
- iio_device_unregister(iio_dev);
- if (!IS_ERR_OR_NULL(st->vref_reg))
- regulator_disable(st->vref_reg);
+ return devm_iio_device_register(&spi->dev, iio_dev);
}
static const struct spi_device_id ad5761_id[] = {
@@ -419,7 +357,6 @@ static struct spi_driver ad5761_driver = {
.name = "ad5761",
},
.probe = ad5761_probe,
- .remove = ad5761_remove,
.id_table = ad5761_id,
};
module_spi_driver(ad5761_driver);
diff --git a/drivers/iio/dac/ad5770r.c b/drivers/iio/dac/ad5770r.c
index c360ebf5297a..25cf11d0471b 100644
--- a/drivers/iio/dac/ad5770r.c
+++ b/drivers/iio/dac/ad5770r.c
@@ -17,6 +17,7 @@
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
+#include <linux/unaligned.h>
#define ADI_SPI_IF_CONFIG_A 0x00
#define ADI_SPI_IF_CONFIG_B 0x01
@@ -121,7 +122,6 @@ struct ad5770r_out_range {
* struct ad5770r_state - driver instance specific data
* @spi: spi_device
* @regmap: regmap
- * @vref_reg: fixed regulator for reference configuration
* @gpio_reset: gpio descriptor
* @output_mode: array contains channels output ranges
* @vref: reference value
@@ -133,7 +133,6 @@ struct ad5770r_out_range {
struct ad5770r_state {
struct spi_device *spi;
struct regmap *regmap;
- struct regulator *vref_reg;
struct gpio_desc *gpio_reset;
struct ad5770r_out_range output_mode[AD5770R_MAX_CHANNELS];
int vref;
@@ -325,7 +324,7 @@ static int ad5770r_read_raw(struct iio_dev *indio_dev,
if (ret)
return 0;
- buf16 = st->transf_buf[0] + (st->transf_buf[1] << 8);
+ buf16 = get_unaligned_le16(st->transf_buf);
*val = buf16 >> 2;
return IIO_VAL_INT;
case IIO_CHAN_INFO_SCALE:
@@ -590,13 +589,6 @@ static int ad5770r_init(struct ad5770r_state *st)
return ret;
}
-static void ad5770r_disable_regulator(void *data)
-{
- struct ad5770r_state *st = data;
-
- regulator_disable(st->vref_reg);
-}
-
static int ad5770r_probe(struct spi_device *spi)
{
struct ad5770r_state *st;
@@ -621,34 +613,12 @@ static int ad5770r_probe(struct spi_device *spi)
}
st->regmap = regmap;
- st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref");
- if (!IS_ERR(st->vref_reg)) {
- ret = regulator_enable(st->vref_reg);
- if (ret) {
- dev_err(&spi->dev,
- "Failed to enable vref regulators: %d\n", ret);
- return ret;
- }
+ ret = devm_regulator_get_enable_read_voltage(&spi->dev, "vref");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(&spi->dev, ret, "Failed to get vref voltage\n");
- ret = devm_add_action_or_reset(&spi->dev,
- ad5770r_disable_regulator,
- st);
- if (ret < 0)
- return ret;
-
- ret = regulator_get_voltage(st->vref_reg);
- if (ret < 0)
- return ret;
-
- st->vref = ret / 1000;
- } else {
- if (PTR_ERR(st->vref_reg) == -ENODEV) {
- st->vref = AD5770R_LOW_VREF_mV;
- st->internal_ref = true;
- } else {
- return PTR_ERR(st->vref_reg);
- }
- }
+ st->internal_ref = ret == -ENODEV;
+ st->vref = st->internal_ref ? AD5770R_LOW_VREF_mV : ret / 1000;
indio_dev->name = spi_get_device_id(spi)->name;
indio_dev->info = &ad5770r_info;
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index 75b549827e15..57374f78f6b8 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -9,6 +9,7 @@
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/device.h>
+#include <linux/delay.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
@@ -61,11 +62,14 @@
/**
* struct ad5791_chip_info - chip specific information
+ * @name: name of the dac chip
+ * @channel: channel specification
* @get_lin_comp: function pointer to the device specific function
*/
-
struct ad5791_chip_info {
- int (*get_lin_comp) (unsigned int span);
+ const char *name;
+ const struct iio_chan_spec channel;
+ int (*get_lin_comp)(unsigned int span);
};
/**
@@ -73,6 +77,9 @@ struct ad5791_chip_info {
* @spi: spi_device
* @reg_vdd: positive supply regulator
* @reg_vss: negative supply regulator
+ * @gpio_reset: reset gpio
+ * @gpio_clear: clear gpio
+ * @gpio_ldac: load dac gpio
* @chip_info: chip model specific constants
* @vref_mv: actual reference voltage used
* @vref_neg_mv: voltage of the negative supply
@@ -85,6 +92,9 @@ struct ad5791_state {
struct spi_device *spi;
struct regulator *reg_vdd;
struct regulator *reg_vss;
+ struct gpio_desc *gpio_reset;
+ struct gpio_desc *gpio_clear;
+ struct gpio_desc *gpio_ldac;
const struct ad5791_chip_info *chip_info;
unsigned short vref_mv;
unsigned int vref_neg_mv;
@@ -98,13 +108,6 @@ struct ad5791_state {
} data[3] __aligned(IIO_DMA_MINALIGN);
};
-enum ad5791_supported_device_ids {
- ID_AD5760,
- ID_AD5780,
- ID_AD5781,
- ID_AD5791,
-};
-
static int ad5791_spi_write(struct ad5791_state *st, u8 addr, u32 val)
{
st->data[0].d32 = cpu_to_be32(AD5791_CMD_WRITE |
@@ -228,20 +231,6 @@ static int ad5780_get_lin_comp(unsigned int span)
else
return AD5780_LINCOMP_10_20;
}
-static const struct ad5791_chip_info ad5791_chip_info_tbl[] = {
- [ID_AD5760] = {
- .get_lin_comp = ad5780_get_lin_comp,
- },
- [ID_AD5780] = {
- .get_lin_comp = ad5780_get_lin_comp,
- },
- [ID_AD5781] = {
- .get_lin_comp = ad5791_get_lin_comp,
- },
- [ID_AD5791] = {
- .get_lin_comp = ad5791_get_lin_comp,
- },
-};
static int ad5791_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -289,30 +278,34 @@ static const struct iio_chan_spec_ext_info ad5791_ext_info[] = {
{ },
};
-#define AD5791_CHAN(bits, _shift) { \
- .type = IIO_VOLTAGE, \
- .output = 1, \
- .indexed = 1, \
- .address = AD5791_ADDR_DAC0, \
- .channel = 0, \
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
- BIT(IIO_CHAN_INFO_OFFSET), \
- .scan_type = { \
- .sign = 'u', \
- .realbits = (bits), \
- .storagebits = 24, \
- .shift = (_shift), \
- }, \
- .ext_info = ad5791_ext_info, \
+#define AD5791_DEFINE_CHIP_INFO(_name, bits, _shift, _lin_comp) \
+static const struct ad5791_chip_info _name##_chip_info = { \
+ .name = #_name, \
+ .get_lin_comp = &(_lin_comp), \
+ .channel = { \
+ .type = IIO_VOLTAGE, \
+ .output = 1, \
+ .indexed = 1, \
+ .address = AD5791_ADDR_DAC0, \
+ .channel = 0, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_OFFSET), \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = (bits), \
+ .storagebits = 24, \
+ .shift = (_shift), \
+ }, \
+ .ext_info = ad5791_ext_info, \
+ }, \
}
-static const struct iio_chan_spec ad5791_channels[] = {
- [ID_AD5760] = AD5791_CHAN(16, 4),
- [ID_AD5780] = AD5791_CHAN(18, 2),
- [ID_AD5781] = AD5791_CHAN(18, 2),
- [ID_AD5791] = AD5791_CHAN(20, 0)
-};
+AD5791_DEFINE_CHIP_INFO(ad5760, 16, 4, ad5780_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5780, 18, 2, ad5780_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5781, 18, 2, ad5791_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5790, 20, 0, ad5791_get_lin_comp);
+AD5791_DEFINE_CHIP_INFO(ad5791, 20, 0, ad5791_get_lin_comp);
static int ad5791_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
@@ -341,7 +334,7 @@ static const struct iio_info ad5791_info = {
static int ad5791_probe(struct spi_device *spi)
{
- struct ad5791_platform_data *pdata = spi->dev.platform_data;
+ const struct ad5791_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad5791_state *st;
int ret, pos_voltage_uv = 0, neg_voltage_uv = 0;
@@ -351,31 +344,21 @@ static int ad5791_probe(struct spi_device *spi)
if (!indio_dev)
return -ENOMEM;
st = iio_priv(indio_dev);
- st->reg_vdd = devm_regulator_get(&spi->dev, "vdd");
- if (!IS_ERR(st->reg_vdd)) {
- ret = regulator_enable(st->reg_vdd);
- if (ret)
- return ret;
-
- ret = regulator_get_voltage(st->reg_vdd);
- if (ret < 0)
- goto error_disable_reg_pos;
-
- pos_voltage_uv = ret;
- }
- st->reg_vss = devm_regulator_get(&spi->dev, "vss");
- if (!IS_ERR(st->reg_vss)) {
- ret = regulator_enable(st->reg_vss);
- if (ret)
- goto error_disable_reg_pos;
+ st->gpio_reset = devm_gpiod_get_optional(&spi->dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(st->gpio_reset))
+ return PTR_ERR(st->gpio_reset);
- ret = regulator_get_voltage(st->reg_vss);
- if (ret < 0)
- goto error_disable_reg_neg;
+ st->gpio_clear = devm_gpiod_get_optional(&spi->dev, "clear",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(st->gpio_clear))
+ return PTR_ERR(st->gpio_clear);
- neg_voltage_uv = ret;
- }
+ st->gpio_ldac = devm_gpiod_get_optional(&spi->dev, "ldac",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(st->gpio_ldac))
+ return PTR_ERR(st->gpio_ldac);
st->pwr_down = true;
st->spi = spi;
@@ -386,7 +369,17 @@ static int ad5791_probe(struct spi_device *spi)
use_rbuf_gain2 = device_property_read_bool(&spi->dev,
"adi,rbuf-gain2-en");
- if (!IS_ERR(st->reg_vss) && !IS_ERR(st->reg_vdd)) {
+ pos_voltage_uv = devm_regulator_get_enable_read_voltage(&spi->dev, "vdd");
+ if (pos_voltage_uv < 0 && pos_voltage_uv != -ENODEV)
+ return dev_err_probe(&spi->dev, pos_voltage_uv,
+ "failed to get vdd voltage\n");
+
+ neg_voltage_uv = devm_regulator_get_enable_read_voltage(&spi->dev, "vss");
+ if (neg_voltage_uv < 0 && neg_voltage_uv != -ENODEV)
+ return dev_err_probe(&spi->dev, neg_voltage_uv,
+ "failed to get vss voltage\n");
+
+ if (neg_voltage_uv >= 0 && pos_voltage_uv >= 0) {
st->vref_mv = (pos_voltage_uv + neg_voltage_uv) / 1000;
st->vref_neg_mv = neg_voltage_uv / 1000;
} else if (pdata) {
@@ -396,13 +389,18 @@ static int ad5791_probe(struct spi_device *spi)
dev_warn(&spi->dev, "reference voltage unspecified\n");
}
- ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
- if (ret)
- goto error_disable_reg_neg;
-
- st->chip_info = &ad5791_chip_info_tbl[spi_get_device_id(spi)
- ->driver_data];
+ if (st->gpio_reset) {
+ fsleep(20);
+ gpiod_set_value_cansleep(st->gpio_reset, 0);
+ } else {
+ ret = ad5791_spi_write(st, AD5791_ADDR_SW_CTRL, AD5791_SWCTRL_RESET);
+ if (ret)
+ return dev_err_probe(&spi->dev, ret, "fail to reset\n");
+ }
+ st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return dev_err_probe(&spi->dev, -EINVAL, "no chip info\n");
st->ctrl = AD5761_CTRL_LINCOMP(st->chip_info->get_lin_comp(st->vref_mv))
| (use_rbuf_gain2 ? 0 : AD5791_CTRL_RBUF) |
@@ -411,59 +409,42 @@ static int ad5791_probe(struct spi_device *spi)
ret = ad5791_spi_write(st, AD5791_ADDR_CTRL, st->ctrl |
AD5791_CTRL_OPGND | AD5791_CTRL_DACTRI);
if (ret)
- goto error_disable_reg_neg;
+ return dev_err_probe(&spi->dev, ret, "fail to write ctrl register\n");
- spi_set_drvdata(spi, indio_dev);
indio_dev->info = &ad5791_info;
indio_dev->modes = INDIO_DIRECT_MODE;
- indio_dev->channels
- = &ad5791_channels[spi_get_device_id(spi)->driver_data];
+ indio_dev->channels = &st->chip_info->channel;
indio_dev->num_channels = 1;
- indio_dev->name = spi_get_device_id(st->spi)->name;
- ret = iio_device_register(indio_dev);
- if (ret)
- goto error_disable_reg_neg;
-
- return 0;
-
-error_disable_reg_neg:
- if (!IS_ERR(st->reg_vss))
- regulator_disable(st->reg_vss);
-error_disable_reg_pos:
- if (!IS_ERR(st->reg_vdd))
- regulator_disable(st->reg_vdd);
- return ret;
+ indio_dev->name = st->chip_info->name;
+ return devm_iio_device_register(&spi->dev, indio_dev);
}
-static void ad5791_remove(struct spi_device *spi)
-{
- struct iio_dev *indio_dev = spi_get_drvdata(spi);
- struct ad5791_state *st = iio_priv(indio_dev);
-
- iio_device_unregister(indio_dev);
- if (!IS_ERR(st->reg_vdd))
- regulator_disable(st->reg_vdd);
-
- if (!IS_ERR(st->reg_vss))
- regulator_disable(st->reg_vss);
-}
+static const struct of_device_id ad5791_of_match[] = {
+ { .compatible = "adi,ad5760", .data = &ad5760_chip_info },
+ { .compatible = "adi,ad5780", .data = &ad5780_chip_info },
+ { .compatible = "adi,ad5781", .data = &ad5781_chip_info },
+ { .compatible = "adi,ad5790", .data = &ad5790_chip_info },
+ { .compatible = "adi,ad5791", .data = &ad5791_chip_info },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad5791_of_match);
static const struct spi_device_id ad5791_id[] = {
- {"ad5760", ID_AD5760},
- {"ad5780", ID_AD5780},
- {"ad5781", ID_AD5781},
- {"ad5790", ID_AD5791},
- {"ad5791", ID_AD5791},
- {}
+ { "ad5760", (kernel_ulong_t)&ad5760_chip_info },
+ { "ad5780", (kernel_ulong_t)&ad5780_chip_info },
+ { "ad5781", (kernel_ulong_t)&ad5781_chip_info },
+ { "ad5790", (kernel_ulong_t)&ad5790_chip_info },
+ { "ad5791", (kernel_ulong_t)&ad5791_chip_info },
+ { }
};
MODULE_DEVICE_TABLE(spi, ad5791_id);
static struct spi_driver ad5791_driver = {
.driver = {
.name = "ad5791",
+ .of_match_table = ad5791_of_match,
},
.probe = ad5791_probe,
- .remove = ad5791_remove,
.id_table = ad5791_id,
};
module_spi_driver(ad5791_driver);
diff --git a/drivers/iio/dac/ad8460.c b/drivers/iio/dac/ad8460.c
new file mode 100644
index 000000000000..535ee3105af6
--- /dev/null
+++ b/drivers/iio/dac/ad8460.c
@@ -0,0 +1,951 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * AD8460 Waveform generator DAC Driver
+ *
+ * Copyright (C) 2024 Analog Devices, Inc.
+ */
+
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/gpio/consumer.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+#include <linux/spi/spi.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/buffer-dma.h>
+#include <linux/iio/buffer-dmaengine.h>
+#include <linux/iio/consumer.h>
+#include <linux/iio/events.h>
+#include <linux/iio/iio.h>
+
+#define AD8460_CTRL_REG(x) (x)
+#define AD8460_HVDAC_DATA_WORD(x) (0x60 + (2 * (x)))
+
+#define AD8460_HV_RESET_MSK BIT(7)
+#define AD8460_HV_SLEEP_MSK BIT(4)
+#define AD8460_WAVE_GEN_MODE_MSK BIT(0)
+
+#define AD8460_HVDAC_SLEEP_MSK BIT(3)
+
+#define AD8460_FAULT_ARM_MSK BIT(7)
+#define AD8460_FAULT_LIMIT_MSK GENMASK(6, 0)
+
+#define AD8460_APG_MODE_ENABLE_MSK BIT(5)
+#define AD8460_PATTERN_DEPTH_MSK GENMASK(3, 0)
+
+#define AD8460_QUIESCENT_CURRENT_MSK GENMASK(7, 0)
+
+#define AD8460_SHUTDOWN_FLAG_MSK BIT(7)
+
+#define AD8460_DATA_BYTE_LOW_MSK GENMASK(7, 0)
+#define AD8460_DATA_BYTE_HIGH_MSK GENMASK(5, 0)
+#define AD8460_DATA_BYTE_FULL_MSK GENMASK(13, 0)
+
+#define AD8460_DEFAULT_FAULT_PROTECT 0x00
+#define AD8460_DATA_BYTE_WORD_LENGTH 2
+#define AD8460_NUM_DATA_WORDS 16
+#define AD8460_NOMINAL_VOLTAGE_SPAN 80
+#define AD8460_MIN_EXT_RESISTOR_OHMS 2000
+#define AD8460_MAX_EXT_RESISTOR_OHMS 20000
+#define AD8460_MIN_VREFIO_UV 120000
+#define AD8460_MAX_VREFIO_UV 1200000
+#define AD8460_ABS_MAX_OVERVOLTAGE_UV 55000000
+#define AD8460_ABS_MAX_OVERCURRENT_UA 1000000
+#define AD8460_MAX_OVERTEMPERATURE_MC 150000
+#define AD8460_MIN_OVERTEMPERATURE_MC 20000
+#define AD8460_CURRENT_LIMIT_CONV(x) ((x) / 15625)
+#define AD8460_VOLTAGE_LIMIT_CONV(x) ((x) / 1953000)
+#define AD8460_TEMP_LIMIT_CONV(x) (((x) + 266640) / 6510)
+
+enum ad8460_fault_type {
+ AD8460_OVERCURRENT_SRC,
+ AD8460_OVERCURRENT_SNK,
+ AD8460_OVERVOLTAGE_POS,
+ AD8460_OVERVOLTAGE_NEG,
+ AD8460_OVERTEMPERATURE,
+};
+
+struct ad8460_state {
+ struct spi_device *spi;
+ struct regmap *regmap;
+ struct iio_channel *tmp_adc_channel;
+ struct clk *sync_clk;
+ /* lock to protect against multiple access to the device and shared data */
+ struct mutex lock;
+ int refio_1p2v_mv;
+ u32 ext_resistor_ohms;
+ /*
+ * DMA (thus cache coherency maintenance) requires the
+ * transfer buffers to live in their own cache lines.
+ */
+ __le16 spi_tx_buf __aligned(IIO_DMA_MINALIGN);
+};
+
+static int ad8460_hv_reset(struct ad8460_state *state)
+{
+ int ret;
+
+ ret = regmap_set_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_HV_RESET_MSK);
+ if (ret)
+ return ret;
+
+ fsleep(20);
+
+ return regmap_clear_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_HV_RESET_MSK);
+}
+
+static int ad8460_reset(const struct ad8460_state *state)
+{
+ struct device *dev = &state->spi->dev;
+ struct gpio_desc *reset;
+
+ reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
+ if (IS_ERR(reset))
+ return dev_err_probe(dev, PTR_ERR(reset),
+ "Failed to get reset gpio");
+ if (reset) {
+ /* minimum duration of 10ns */
+ ndelay(10);
+ gpiod_set_value_cansleep(reset, 1);
+ return 0;
+ }
+
+ /* bring all registers to their default state */
+ return regmap_write(state->regmap, AD8460_CTRL_REG(0x03), 1);
+}
+
+static int ad8460_enable_apg_mode(struct ad8460_state *state, int val)
+{
+ int ret;
+
+ ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x02),
+ AD8460_APG_MODE_ENABLE_MSK,
+ FIELD_PREP(AD8460_APG_MODE_ENABLE_MSK, val));
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_WAVE_GEN_MODE_MSK,
+ FIELD_PREP(AD8460_WAVE_GEN_MODE_MSK, val));
+}
+
+static int ad8460_read_shutdown_flag(struct ad8460_state *state, u64 *flag)
+{
+ int ret, val;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x0E), &val);
+ if (ret)
+ return ret;
+
+ *flag = FIELD_GET(AD8460_SHUTDOWN_FLAG_MSK, val);
+ return 0;
+}
+
+static int ad8460_get_hvdac_word(struct ad8460_state *state, int index, int *val)
+{
+ int ret;
+
+ ret = regmap_bulk_read(state->regmap, AD8460_HVDAC_DATA_WORD(index),
+ &state->spi_tx_buf, AD8460_DATA_BYTE_WORD_LENGTH);
+ if (ret)
+ return ret;
+
+ *val = le16_to_cpu(state->spi_tx_buf);
+
+ return ret;
+}
+
+static int ad8460_set_hvdac_word(struct ad8460_state *state, int index, int val)
+{
+ state->spi_tx_buf = cpu_to_le16(FIELD_PREP(AD8460_DATA_BYTE_FULL_MSK, val));
+
+ return regmap_bulk_write(state->regmap, AD8460_HVDAC_DATA_WORD(index),
+ &state->spi_tx_buf, AD8460_DATA_BYTE_WORD_LENGTH);
+}
+
+static ssize_t ad8460_dac_input_read(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = ad8460_get_hvdac_word(state, private, &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%u\n", reg);
+}
+
+static ssize_t ad8460_dac_input_write(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = kstrtou32(buf, 10, &reg);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+
+ return ad8460_set_hvdac_word(state, private, reg);
+}
+
+static ssize_t ad8460_read_symbol(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x02), &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%lu\n", FIELD_GET(AD8460_PATTERN_DEPTH_MSK, reg));
+}
+
+static ssize_t ad8460_write_symbol(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ uint16_t sym;
+ int ret;
+
+ ret = kstrtou16(buf, 10, &sym);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+
+ return regmap_update_bits(state->regmap,
+ AD8460_CTRL_REG(0x02),
+ AD8460_PATTERN_DEPTH_MSK,
+ FIELD_PREP(AD8460_PATTERN_DEPTH_MSK, sym));
+}
+
+static ssize_t ad8460_read_toggle_en(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x02), &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%ld\n", FIELD_GET(AD8460_APG_MODE_ENABLE_MSK, reg));
+}
+
+static ssize_t ad8460_write_toggle_en(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ bool toggle_en;
+ int ret;
+
+ ret = kstrtobool(buf, &toggle_en);
+ if (ret)
+ return ret;
+
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
+ return ad8460_enable_apg_mode(state, toggle_en);
+ unreachable();
+}
+
+static ssize_t ad8460_read_powerdown(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan, char *buf)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x01), &reg);
+ if (ret)
+ return ret;
+
+ return sysfs_emit(buf, "%ld\n", FIELD_GET(AD8460_HVDAC_SLEEP_MSK, reg));
+}
+
+static ssize_t ad8460_write_powerdown(struct iio_dev *indio_dev, uintptr_t private,
+ const struct iio_chan_spec *chan,
+ const char *buf, size_t len)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ bool pwr_down;
+ u64 sdn_flag;
+ int ret;
+
+ ret = kstrtobool(buf, &pwr_down);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+
+ /*
+ * If powerdown is set, HVDAC is enabled and the HV driver is
+ * enabled via HV_RESET in case it is in shutdown mode,
+ * If powerdown is cleared, HVDAC is set to shutdown state
+ * as well as the HV driver. Quiescent current decreases and ouput is
+ * floating (high impedance).
+ */
+
+ ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x01),
+ AD8460_HVDAC_SLEEP_MSK,
+ FIELD_PREP(AD8460_HVDAC_SLEEP_MSK, pwr_down));
+ if (ret)
+ return ret;
+
+ if (!pwr_down) {
+ ret = ad8460_read_shutdown_flag(state, &sdn_flag);
+ if (ret)
+ return ret;
+
+ if (sdn_flag) {
+ ret = ad8460_hv_reset(state);
+ if (ret)
+ return ret;
+ }
+ }
+
+ ret = regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x00),
+ AD8460_HV_SLEEP_MSK,
+ FIELD_PREP(AD8460_HV_SLEEP_MSK, !pwr_down));
+ if (ret)
+ return ret;
+
+ return len;
+}
+
+static const char * const ad8460_powerdown_modes[] = {
+ "three_state",
+};
+
+static int ad8460_get_powerdown_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan)
+{
+ return 0;
+}
+
+static int ad8460_set_powerdown_mode(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ unsigned int type)
+{
+ return 0;
+}
+
+static int ad8460_set_sample(struct ad8460_state *state, int val)
+{
+ int ret;
+
+ ret = ad8460_enable_apg_mode(state, 1);
+ if (ret)
+ return ret;
+
+ guard(mutex)(&state->lock);
+ ret = ad8460_set_hvdac_word(state, 0, val);
+ if (ret)
+ return ret;
+
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x02),
+ AD8460_PATTERN_DEPTH_MSK,
+ FIELD_PREP(AD8460_PATTERN_DEPTH_MSK, 0));
+}
+
+static int ad8460_set_fault_threshold(struct ad8460_state *state,
+ enum ad8460_fault_type fault,
+ unsigned int threshold)
+{
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x08 + fault),
+ AD8460_FAULT_LIMIT_MSK,
+ FIELD_PREP(AD8460_FAULT_LIMIT_MSK, threshold));
+}
+
+static int ad8460_get_fault_threshold(struct ad8460_state *state,
+ enum ad8460_fault_type fault,
+ unsigned int *threshold)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x08 + fault), &val);
+ if (ret)
+ return ret;
+
+ *threshold = FIELD_GET(AD8460_FAULT_LIMIT_MSK, val);
+
+ return ret;
+}
+
+static int ad8460_set_fault_threshold_en(struct ad8460_state *state,
+ enum ad8460_fault_type fault, bool en)
+{
+ return regmap_update_bits(state->regmap, AD8460_CTRL_REG(0x08 + fault),
+ AD8460_FAULT_ARM_MSK,
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, en));
+}
+
+static int ad8460_get_fault_threshold_en(struct ad8460_state *state,
+ enum ad8460_fault_type fault, bool *en)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x08 + fault), &val);
+ if (ret)
+ return ret;
+
+ *en = FIELD_GET(AD8460_FAULT_ARM_MSK, val);
+
+ return 0;
+}
+
+static int ad8460_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2,
+ long mask)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev)
+ return ad8460_set_sample(state, val);
+ unreachable();
+ case IIO_CURRENT:
+ return regmap_write(state->regmap, AD8460_CTRL_REG(0x04),
+ FIELD_PREP(AD8460_QUIESCENT_CURRENT_MSK, val));
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad8460_read_raw(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int data, ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_VOLTAGE:
+ scoped_guard(mutex, &state->lock) {
+ ret = ad8460_get_hvdac_word(state, 0, &data);
+ if (ret)
+ return ret;
+ }
+ *val = data;
+ return IIO_VAL_INT;
+ case IIO_CURRENT:
+ ret = regmap_read(state->regmap, AD8460_CTRL_REG(0x04),
+ &data);
+ if (ret)
+ return ret;
+ *val = data;
+ return IIO_VAL_INT;
+ case IIO_TEMP:
+ ret = iio_read_channel_raw(state->tmp_adc_channel, &data);
+ if (ret)
+ return ret;
+ *val = data;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = clk_get_rate(state->sync_clk);
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ /*
+ * vCONV = vNOMINAL_SPAN * (DAC_CODE / 2**14) - 40V
+ * vMAX = vNOMINAL_SPAN * (2**14 / 2**14) - 40V
+ * vMIN = vNOMINAL_SPAN * (0 / 2**14) - 40V
+ * vADJ = vCONV * (2000 / rSET) * (vREF / 1.2)
+ * vSPAN = vADJ_MAX - vADJ_MIN
+ * See datasheet page 49, section FULL-SCALE REDUCTION
+ */
+ *val = AD8460_NOMINAL_VOLTAGE_SPAN * 2000 * state->refio_1p2v_mv;
+ *val2 = state->ext_resistor_ohms * 1200;
+ return IIO_VAL_FRACTIONAL;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad8460_select_fault_type(int chan_type, enum iio_event_direction dir)
+{
+ switch (chan_type) {
+ case IIO_VOLTAGE:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return AD8460_OVERVOLTAGE_POS;
+ case IIO_EV_DIR_FALLING:
+ return AD8460_OVERVOLTAGE_NEG;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CURRENT:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return AD8460_OVERCURRENT_SRC;
+ case IIO_EV_DIR_FALLING:
+ return AD8460_OVERCURRENT_SNK;
+ default:
+ return -EINVAL;
+ }
+ case IIO_TEMP:
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return AD8460_OVERTEMPERATURE;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ad8460_write_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info, int val, int val2)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ if (info != IIO_EV_INFO_VALUE)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ return ad8460_set_fault_threshold(state, fault, val);
+}
+
+static int ad8460_read_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info, int *val, int *val2)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ if (info != IIO_EV_INFO_VALUE)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ return ad8460_get_fault_threshold(state, fault, val);
+}
+
+static int ad8460_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir, bool val)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ return ad8460_set_fault_threshold_en(state, fault, val);
+}
+
+static int ad8460_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+ int fault, ret;
+ bool en;
+
+ if (type != IIO_EV_TYPE_THRESH)
+ return -EINVAL;
+
+ fault = ad8460_select_fault_type(chan->type, dir);
+ if (fault < 0)
+ return fault;
+
+ ret = ad8460_get_fault_threshold_en(state, fault, &en);
+ if (ret)
+ return ret;
+
+ return en;
+}
+
+static int ad8460_reg_access(struct iio_dev *indio_dev, unsigned int reg,
+ unsigned int writeval, unsigned int *readval)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ if (readval)
+ return regmap_read(state->regmap, reg, readval);
+
+ return regmap_write(state->regmap, reg, writeval);
+}
+
+static int ad8460_buffer_preenable(struct iio_dev *indio_dev)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ return ad8460_enable_apg_mode(state, 0);
+}
+
+static int ad8460_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct ad8460_state *state = iio_priv(indio_dev);
+
+ return ad8460_enable_apg_mode(state, 1);
+}
+
+static const struct iio_buffer_setup_ops ad8460_buffer_setup_ops = {
+ .preenable = &ad8460_buffer_preenable,
+ .postdisable = &ad8460_buffer_postdisable,
+};
+
+static const struct iio_info ad8460_info = {
+ .read_raw = &ad8460_read_raw,
+ .write_raw = &ad8460_write_raw,
+ .write_event_value = &ad8460_write_event_value,
+ .read_event_value = &ad8460_read_event_value,
+ .write_event_config = &ad8460_write_event_config,
+ .read_event_config = &ad8460_read_event_config,
+ .debugfs_reg_access = &ad8460_reg_access,
+};
+
+static const struct iio_enum ad8460_powerdown_mode_enum = {
+ .items = ad8460_powerdown_modes,
+ .num_items = ARRAY_SIZE(ad8460_powerdown_modes),
+ .get = ad8460_get_powerdown_mode,
+ .set = ad8460_set_powerdown_mode,
+};
+
+#define AD8460_CHAN_EXT_INFO(_name, _what, _read, _write) { \
+ .name = (_name), \
+ .read = (_read), \
+ .write = (_write), \
+ .private = (_what), \
+ .shared = IIO_SEPARATE, \
+}
+
+static const struct iio_chan_spec_ext_info ad8460_ext_info[] = {
+ AD8460_CHAN_EXT_INFO("raw0", 0, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw1", 1, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw2", 2, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw3", 3, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw4", 4, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw5", 5, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw6", 6, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw7", 7, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw8", 8, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw9", 9, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw10", 10, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw11", 11, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw12", 12, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw13", 13, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw14", 14, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("raw15", 15, ad8460_dac_input_read,
+ ad8460_dac_input_write),
+ AD8460_CHAN_EXT_INFO("toggle_en", 0, ad8460_read_toggle_en,
+ ad8460_write_toggle_en),
+ AD8460_CHAN_EXT_INFO("symbol", 0, ad8460_read_symbol,
+ ad8460_write_symbol),
+ AD8460_CHAN_EXT_INFO("powerdown", 0, ad8460_read_powerdown,
+ ad8460_write_powerdown),
+ IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad8460_powerdown_mode_enum),
+ IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE,
+ &ad8460_powerdown_mode_enum),
+ { }
+};
+
+static const struct iio_event_spec ad8460_events[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE) |
+ BIT(IIO_EV_INFO_ENABLE),
+ },
+};
+
+#define AD8460_VOLTAGE_CHAN { \
+ .type = IIO_VOLTAGE, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_SAMP_FREQ) | \
+ BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = 0, \
+ .scan_index = 0, \
+ .scan_type = { \
+ .sign = 'u', \
+ .realbits = 14, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+ .ext_info = ad8460_ext_info, \
+ .event_spec = ad8460_events, \
+ .num_event_specs = ARRAY_SIZE(ad8460_events), \
+}
+
+#define AD8460_CURRENT_CHAN { \
+ .type = IIO_CURRENT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .output = 1, \
+ .indexed = 1, \
+ .channel = 0, \
+ .scan_index = -1, \
+ .event_spec = ad8460_events, \
+ .num_event_specs = ARRAY_SIZE(ad8460_events), \
+}
+
+#define AD8460_TEMP_CHAN { \
+ .type = IIO_TEMP, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .indexed = 1, \
+ .channel = 0, \
+ .scan_index = -1, \
+ .event_spec = ad8460_events, \
+ .num_event_specs = 1, \
+}
+
+static const struct iio_chan_spec ad8460_channels[] = {
+ AD8460_VOLTAGE_CHAN,
+ AD8460_CURRENT_CHAN,
+};
+
+static const struct iio_chan_spec ad8460_channels_with_tmp_adc[] = {
+ AD8460_VOLTAGE_CHAN,
+ AD8460_CURRENT_CHAN,
+ AD8460_TEMP_CHAN,
+};
+
+static const struct regmap_config ad8460_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0x7F,
+};
+
+static const char * const ad8460_supplies[] = {
+ "avdd_3p3v", "dvdd_3p3v", "vcc_5v", "hvcc", "hvee", "vref_5v"
+};
+
+static int ad8460_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct ad8460_state *state;
+ struct iio_dev *indio_dev;
+ u32 tmp[2], temp;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*state));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ state = iio_priv(indio_dev);
+
+ indio_dev->name = "ad8460";
+ indio_dev->info = &ad8460_info;
+
+ state->spi = spi;
+
+ state->regmap = devm_regmap_init_spi(spi, &ad8460_regmap_config);
+ if (IS_ERR(state->regmap))
+ return dev_err_probe(dev, PTR_ERR(state->regmap),
+ "Failed to initialize regmap");
+
+ ret = devm_mutex_init(dev, &state->lock);
+ if (ret)
+ return ret;
+
+ state->sync_clk = devm_clk_get_enabled(dev, NULL);
+ if (IS_ERR(state->sync_clk))
+ return dev_err_probe(dev, PTR_ERR(state->sync_clk),
+ "Failed to get sync clk\n");
+
+ state->tmp_adc_channel = devm_iio_channel_get(dev, "ad8460-tmp");
+ if (IS_ERR(state->tmp_adc_channel)) {
+ if (PTR_ERR(state->tmp_adc_channel) == -EPROBE_DEFER)
+ return -EPROBE_DEFER;
+ indio_dev->channels = ad8460_channels;
+ indio_dev->num_channels = ARRAY_SIZE(ad8460_channels);
+ } else {
+ indio_dev->channels = ad8460_channels_with_tmp_adc;
+ indio_dev->num_channels = ARRAY_SIZE(ad8460_channels_with_tmp_adc);
+ }
+
+ ret = devm_regulator_bulk_get_enable(dev, ARRAY_SIZE(ad8460_supplies),
+ ad8460_supplies);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to enable power supplies\n");
+
+ ret = devm_regulator_get_enable_read_voltage(dev, "refio_1p2v");
+ if (ret < 0 && ret != -ENODEV)
+ return dev_err_probe(dev, ret, "Failed to get reference voltage\n");
+
+ state->refio_1p2v_mv = ret == -ENODEV ? 1200 : ret / 1000;
+
+ if (!in_range(state->refio_1p2v_mv, AD8460_MIN_VREFIO_UV / 1000,
+ AD8460_MAX_VREFIO_UV / 1000))
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid ref voltage range(%u mV) [%u mV, %u mV]\n",
+ state->refio_1p2v_mv,
+ AD8460_MIN_VREFIO_UV / 1000,
+ AD8460_MAX_VREFIO_UV / 1000);
+
+ ret = device_property_read_u32(dev, "adi,external-resistor-ohms",
+ &state->ext_resistor_ohms);
+ if (ret)
+ state->ext_resistor_ohms = 2000;
+ else if (!in_range(state->ext_resistor_ohms, AD8460_MIN_EXT_RESISTOR_OHMS,
+ AD8460_MAX_EXT_RESISTOR_OHMS))
+ return dev_err_probe(dev, -EINVAL,
+ "Invalid resistor set range(%u) [%u, %u]\n",
+ state->ext_resistor_ohms,
+ AD8460_MIN_EXT_RESISTOR_OHMS,
+ AD8460_MAX_EXT_RESISTOR_OHMS);
+
+ ret = device_property_read_u32_array(dev, "adi,range-microamp",
+ tmp, ARRAY_SIZE(tmp));
+ if (!ret) {
+ if (in_range(tmp[1], 0, AD8460_ABS_MAX_OVERCURRENT_UA))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x08),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_CURRENT_LIMIT_CONV(tmp[1]));
+
+ if (in_range(tmp[0], -AD8460_ABS_MAX_OVERCURRENT_UA, 0))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x09),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_CURRENT_LIMIT_CONV(abs(tmp[0])));
+ }
+
+ ret = device_property_read_u32_array(dev, "adi,range-microvolt",
+ tmp, ARRAY_SIZE(tmp));
+ if (!ret) {
+ if (in_range(tmp[1], 0, AD8460_ABS_MAX_OVERVOLTAGE_UV))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x0A),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_VOLTAGE_LIMIT_CONV(tmp[1]));
+
+ if (in_range(tmp[0], -AD8460_ABS_MAX_OVERVOLTAGE_UV, 0))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x0B),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_VOLTAGE_LIMIT_CONV(abs(tmp[0])));
+ }
+
+ ret = device_property_read_u32(dev, "adi,max-millicelsius", &temp);
+ if (!ret) {
+ if (in_range(temp, AD8460_MIN_OVERTEMPERATURE_MC,
+ AD8460_MAX_OVERTEMPERATURE_MC))
+ regmap_write(state->regmap, AD8460_CTRL_REG(0x0C),
+ FIELD_PREP(AD8460_FAULT_ARM_MSK, 1) |
+ AD8460_TEMP_LIMIT_CONV(abs(temp)));
+ }
+
+ ret = ad8460_reset(state);
+ if (ret)
+ return ret;
+
+ /* Enables DAC by default */
+ ret = regmap_clear_bits(state->regmap, AD8460_CTRL_REG(0x01),
+ AD8460_HVDAC_SLEEP_MSK);
+ if (ret)
+ return ret;
+
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->setup_ops = &ad8460_buffer_setup_ops;
+
+ ret = devm_iio_dmaengine_buffer_setup_ext(dev, indio_dev, "tx",
+ IIO_BUFFER_DIRECTION_OUT);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get DMA buffer\n");
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static const struct of_device_id ad8460_of_match[] = {
+ { .compatible = "adi,ad8460" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, ad8460_of_match);
+
+static const struct spi_device_id ad8460_spi_match[] = {
+ { .name = "ad8460" },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, ad8460_spi_match);
+
+static struct spi_driver ad8460_driver = {
+ .driver = {
+ .name = "ad8460",
+ .of_match_table = ad8460_of_match,
+ },
+ .probe = ad8460_probe,
+ .id_table = ad8460_spi_match,
+};
+module_spi_driver(ad8460_driver);
+
+MODULE_AUTHOR("Mariel Tinaco <mariel.tinaco@analog.com");
+MODULE_DESCRIPTION("AD8460 DAC driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER");
diff --git a/drivers/iio/dac/ad9739a.c b/drivers/iio/dac/ad9739a.c
index 615d1a196db3..b6a65359b0b4 100644
--- a/drivers/iio/dac/ad9739a.c
+++ b/drivers/iio/dac/ad9739a.c
@@ -466,4 +466,4 @@ MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
MODULE_DESCRIPTION("Analog Devices AD9739 DAC");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_BACKEND);
+MODULE_IMPORT_NS("IIO_BACKEND");
diff --git a/drivers/iio/dac/adi-axi-dac.c b/drivers/iio/dac/adi-axi-dac.c
index 0cb00f3bec04..b143f7ed6847 100644
--- a/drivers/iio/dac/adi-axi-dac.c
+++ b/drivers/iio/dac/adi-axi-dac.c
@@ -29,44 +29,77 @@
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
+#include "ad3552r-hs.h"
+
/*
* Register definitions:
* https://wiki.analog.com/resources/fpga/docs/axi_dac_ip#register_map
*/
/* Base controls */
-#define AXI_DAC_REG_CONFIG 0x0c
-#define AXI_DDS_DISABLE BIT(6)
+#define AXI_DAC_CONFIG_REG 0x0c
+#define AXI_DAC_CONFIG_DDS_DISABLE BIT(6)
/* DAC controls */
-#define AXI_DAC_REG_RSTN 0x0040
-#define AXI_DAC_RSTN_CE_N BIT(2)
-#define AXI_DAC_RSTN_MMCM_RSTN BIT(1)
-#define AXI_DAC_RSTN_RSTN BIT(0)
-#define AXI_DAC_REG_CNTRL_1 0x0044
-#define AXI_DAC_SYNC BIT(0)
-#define AXI_DAC_REG_CNTRL_2 0x0048
-#define ADI_DAC_R1_MODE BIT(4)
-#define AXI_DAC_DRP_STATUS 0x0074
-#define AXI_DAC_DRP_LOCKED BIT(17)
+#define AXI_DAC_RSTN_REG 0x0040
+#define AXI_DAC_RSTN_CE_N BIT(2)
+#define AXI_DAC_RSTN_MMCM_RSTN BIT(1)
+#define AXI_DAC_RSTN_RSTN BIT(0)
+#define AXI_DAC_CNTRL_1_REG 0x0044
+#define AXI_DAC_CNTRL_1_SYNC BIT(0)
+#define AXI_DAC_CNTRL_2_REG 0x0048
+#define AXI_DAC_CNTRL_2_SDR_DDR_N BIT(16)
+#define AXI_DAC_CNTRL_2_SYMB_8B BIT(14)
+#define ADI_DAC_CNTRL_2_R1_MODE BIT(5)
+#define AXI_DAC_CNTRL_2_UNSIGNED_DATA BIT(4)
+#define AXI_DAC_STATUS_1_REG 0x0054
+#define AXI_DAC_STATUS_2_REG 0x0058
+#define AXI_DAC_DRP_STATUS_REG 0x0074
+#define AXI_DAC_DRP_STATUS_DRP_LOCKED BIT(17)
+#define AXI_DAC_CUSTOM_RD_REG 0x0080
+#define AXI_DAC_CUSTOM_WR_REG 0x0084
+#define AXI_DAC_CUSTOM_WR_DATA_8 GENMASK(23, 16)
+#define AXI_DAC_CUSTOM_WR_DATA_16 GENMASK(23, 8)
+#define AXI_DAC_UI_STATUS_REG 0x0088
+#define AXI_DAC_UI_STATUS_IF_BUSY BIT(4)
+#define AXI_DAC_CUSTOM_CTRL_REG 0x008C
+#define AXI_DAC_CUSTOM_CTRL_ADDRESS GENMASK(31, 24)
+#define AXI_DAC_CUSTOM_CTRL_SYNCED_TRANSFER BIT(2)
+#define AXI_DAC_CUSTOM_CTRL_STREAM BIT(1)
+#define AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA BIT(0)
+
+#define AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE (AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA | \
+ AXI_DAC_CUSTOM_CTRL_STREAM)
+
/* DAC Channel controls */
-#define AXI_DAC_REG_CHAN_CNTRL_1(c) (0x0400 + (c) * 0x40)
-#define AXI_DAC_REG_CHAN_CNTRL_3(c) (0x0408 + (c) * 0x40)
-#define AXI_DAC_SCALE_SIGN BIT(15)
-#define AXI_DAC_SCALE_INT BIT(14)
-#define AXI_DAC_SCALE GENMASK(14, 0)
-#define AXI_DAC_REG_CHAN_CNTRL_2(c) (0x0404 + (c) * 0x40)
-#define AXI_DAC_REG_CHAN_CNTRL_4(c) (0x040c + (c) * 0x40)
-#define AXI_DAC_PHASE GENMASK(31, 16)
-#define AXI_DAC_FREQUENCY GENMASK(15, 0)
-#define AXI_DAC_REG_CHAN_CNTRL_7(c) (0x0418 + (c) * 0x40)
-#define AXI_DAC_DATA_SEL GENMASK(3, 0)
+#define AXI_DAC_CHAN_CNTRL_1_REG(c) (0x0400 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_3_REG(c) (0x0408 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN BIT(15)
+#define AXI_DAC_CHAN_CNTRL_3_SCALE_INT BIT(14)
+#define AXI_DAC_CHAN_CNTRL_3_SCALE GENMASK(14, 0)
+#define AXI_DAC_CHAN_CNTRL_2_REG(c) (0x0404 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_2_PHASE GENMASK(31, 16)
+#define AXI_DAC_CHAN_CNTRL_2_FREQUENCY GENMASK(15, 0)
+#define AXI_DAC_CHAN_CNTRL_4_REG(c) (0x040c + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_7_REG(c) (0x0418 + (c) * 0x40)
+#define AXI_DAC_CHAN_CNTRL_7_DATA_SEL GENMASK(3, 0)
+
+#define AXI_DAC_RD_ADDR(x) (BIT(7) | (x))
/* 360 degrees in rad */
-#define AXI_DAC_2_PI_MEGA 6283190
+#define AXI_DAC_2_PI_MEGA 6283190
+
enum {
AXI_DAC_DATA_INTERNAL_TONE,
AXI_DAC_DATA_DMA = 2,
+ AXI_DAC_DATA_INTERNAL_RAMP_16BIT = 11,
+};
+
+struct axi_dac_info {
+ unsigned int version;
+ const struct iio_backend_info *backend_info;
+ bool has_dac_clk;
+ bool has_child_nodes;
};
struct axi_dac_state {
@@ -77,9 +110,11 @@ struct axi_dac_state {
* data/variables.
*/
struct mutex lock;
+ const struct axi_dac_info *info;
u64 dac_clk;
u32 reg_config;
bool int_tone;
+ int dac_clk_rate;
};
static int axi_dac_enable(struct iio_backend *back)
@@ -89,7 +124,7 @@ static int axi_dac_enable(struct iio_backend *back)
int ret;
guard(mutex)(&st->lock);
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_RSTN,
+ ret = regmap_set_bits(st->regmap, AXI_DAC_RSTN_REG,
AXI_DAC_RSTN_MMCM_RSTN);
if (ret)
return ret;
@@ -98,12 +133,14 @@ static int axi_dac_enable(struct iio_backend *back)
* designs really use it but if they don't we still get the lock bit
* set. So let's do it all the time so the code is generic.
*/
- ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_DRP_STATUS, __val,
- __val & AXI_DAC_DRP_LOCKED, 100, 1000);
+ ret = regmap_read_poll_timeout(st->regmap, AXI_DAC_DRP_STATUS_REG,
+ __val,
+ __val & AXI_DAC_DRP_STATUS_DRP_LOCKED,
+ 100, 1000);
if (ret)
return ret;
- return regmap_set_bits(st->regmap, AXI_DAC_REG_RSTN,
+ return regmap_set_bits(st->regmap, AXI_DAC_RSTN_REG,
AXI_DAC_RSTN_RSTN | AXI_DAC_RSTN_MMCM_RSTN);
}
@@ -112,7 +149,7 @@ static void axi_dac_disable(struct iio_backend *back)
struct axi_dac_state *st = iio_backend_get_priv(back);
guard(mutex)(&st->lock);
- regmap_write(st->regmap, AXI_DAC_REG_RSTN, 0);
+ regmap_write(st->regmap, AXI_DAC_RSTN_REG, 0);
}
static struct iio_buffer *axi_dac_request_buffer(struct iio_backend *back,
@@ -155,15 +192,15 @@ static int __axi_dac_frequency_get(struct axi_dac_state *st, unsigned int chan,
}
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan);
ret = regmap_read(st->regmap, reg, &raw);
if (ret)
return ret;
- raw = FIELD_GET(AXI_DAC_FREQUENCY, raw);
+ raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_2_FREQUENCY, raw);
*freq = DIV_ROUND_CLOSEST_ULL(raw * st->dac_clk, BIT(16));
return 0;
@@ -194,17 +231,18 @@ static int axi_dac_scale_get(struct axi_dac_state *st,
u32 reg, raw;
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_3_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_1_REG(chan->channel);
ret = regmap_read(st->regmap, reg, &raw);
if (ret)
return ret;
- sign = FIELD_GET(AXI_DAC_SCALE_SIGN, raw);
- raw = FIELD_GET(AXI_DAC_SCALE, raw);
- scale = DIV_ROUND_CLOSEST_ULL((u64)raw * MEGA, AXI_DAC_SCALE_INT);
+ sign = FIELD_GET(AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN, raw);
+ raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_3_SCALE, raw);
+ scale = DIV_ROUND_CLOSEST_ULL((u64)raw * MEGA,
+ AXI_DAC_CHAN_CNTRL_3_SCALE_INT);
vals[0] = scale / MEGA;
vals[1] = scale % MEGA;
@@ -227,15 +265,15 @@ static int axi_dac_phase_get(struct axi_dac_state *st,
int ret, vals[2];
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan->channel);
ret = regmap_read(st->regmap, reg, &raw);
if (ret)
return ret;
- raw = FIELD_GET(AXI_DAC_PHASE, raw);
+ raw = FIELD_GET(AXI_DAC_CHAN_CNTRL_2_PHASE, raw);
phase = DIV_ROUND_CLOSEST_ULL((u64)raw * AXI_DAC_2_PI_MEGA, U16_MAX);
vals[0] = phase / MEGA;
@@ -260,18 +298,20 @@ static int __axi_dac_frequency_set(struct axi_dac_state *st, unsigned int chan,
}
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan);
raw = DIV64_U64_ROUND_CLOSEST((u64)freq * BIT(16), sample_rate);
- ret = regmap_update_bits(st->regmap, reg, AXI_DAC_FREQUENCY, raw);
+ ret = regmap_update_bits(st->regmap, reg,
+ AXI_DAC_CHAN_CNTRL_2_FREQUENCY, raw);
if (ret)
return ret;
/* synchronize channels */
- return regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
+ return regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG,
+ AXI_DAC_CNTRL_1_SYNC);
}
static int axi_dac_frequency_set(struct axi_dac_state *st,
@@ -312,16 +352,16 @@ static int axi_dac_scale_set(struct axi_dac_state *st,
/* format is 1.1.14 (sign, integer and fractional bits) */
if (scale < 0) {
- raw = FIELD_PREP(AXI_DAC_SCALE_SIGN, 1);
+ raw = FIELD_PREP(AXI_DAC_CHAN_CNTRL_3_SCALE_SIGN, 1);
scale *= -1;
}
- raw |= div_u64((u64)scale * AXI_DAC_SCALE_INT, MEGA);
+ raw |= div_u64((u64)scale * AXI_DAC_CHAN_CNTRL_3_SCALE_INT, MEGA);
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_3(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_3_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_1(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_1_REG(chan->channel);
guard(mutex)(&st->lock);
ret = regmap_write(st->regmap, reg, raw);
@@ -329,7 +369,8 @@ static int axi_dac_scale_set(struct axi_dac_state *st,
return ret;
/* synchronize channels */
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG,
+ AXI_DAC_CNTRL_1_SYNC);
if (ret)
return ret;
@@ -355,18 +396,19 @@ static int axi_dac_phase_set(struct axi_dac_state *st,
raw = DIV_ROUND_CLOSEST_ULL((u64)phase * U16_MAX, AXI_DAC_2_PI_MEGA);
if (tone_2)
- reg = AXI_DAC_REG_CHAN_CNTRL_4(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_4_REG(chan->channel);
else
- reg = AXI_DAC_REG_CHAN_CNTRL_2(chan->channel);
+ reg = AXI_DAC_CHAN_CNTRL_2_REG(chan->channel);
guard(mutex)(&st->lock);
- ret = regmap_update_bits(st->regmap, reg, AXI_DAC_PHASE,
- FIELD_PREP(AXI_DAC_PHASE, raw));
+ ret = regmap_update_bits(st->regmap, reg, AXI_DAC_CHAN_CNTRL_2_PHASE,
+ FIELD_PREP(AXI_DAC_CHAN_CNTRL_2_PHASE, raw));
if (ret)
return ret;
/* synchronize channels */
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_1, AXI_DAC_SYNC);
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_1_REG,
+ AXI_DAC_CNTRL_1_SYNC);
if (ret)
return ret;
@@ -437,7 +479,7 @@ static int axi_dac_extend_chan(struct iio_backend *back,
if (chan->type != IIO_ALTVOLTAGE)
return -EINVAL;
- if (st->reg_config & AXI_DDS_DISABLE)
+ if (st->reg_config & AXI_DAC_CONFIG_DDS_DISABLE)
/* nothing to extend */
return 0;
@@ -454,13 +496,19 @@ static int axi_dac_data_source_set(struct iio_backend *back, unsigned int chan,
switch (data) {
case IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE:
return regmap_update_bits(st->regmap,
- AXI_DAC_REG_CHAN_CNTRL_7(chan),
- AXI_DAC_DATA_SEL,
+ AXI_DAC_CHAN_CNTRL_7_REG(chan),
+ AXI_DAC_CHAN_CNTRL_7_DATA_SEL,
AXI_DAC_DATA_INTERNAL_TONE);
case IIO_BACKEND_EXTERNAL:
return regmap_update_bits(st->regmap,
- AXI_DAC_REG_CHAN_CNTRL_7(chan),
- AXI_DAC_DATA_SEL, AXI_DAC_DATA_DMA);
+ AXI_DAC_CHAN_CNTRL_7_REG(chan),
+ AXI_DAC_CHAN_CNTRL_7_DATA_SEL,
+ AXI_DAC_DATA_DMA);
+ case IIO_BACKEND_INTERNAL_RAMP_16BIT:
+ return regmap_update_bits(st->regmap,
+ AXI_DAC_CHAN_CNTRL_7_REG(chan),
+ AXI_DAC_CHAN_CNTRL_7_DATA_SEL,
+ AXI_DAC_DATA_INTERNAL_RAMP_16BIT);
default:
return -EINVAL;
}
@@ -475,7 +523,7 @@ static int axi_dac_set_sample_rate(struct iio_backend *back, unsigned int chan,
if (!sample_rate)
return -EINVAL;
- if (st->reg_config & AXI_DDS_DISABLE)
+ if (st->reg_config & AXI_DAC_CONFIG_DDS_DISABLE)
/* sample_rate has no meaning if DDS is disabled */
return 0;
@@ -518,6 +566,184 @@ static int axi_dac_reg_access(struct iio_backend *back, unsigned int reg,
return regmap_write(st->regmap, reg, writeval);
}
+static int axi_dac_ddr_enable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SDR_DDR_N);
+}
+
+static int axi_dac_ddr_disable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SDR_DDR_N);
+}
+
+static int axi_dac_data_stream_enable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_set_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE);
+}
+
+static int axi_dac_data_stream_disable(struct iio_backend *back)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ return regmap_clear_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_STREAM_ENABLE);
+}
+
+static int axi_dac_data_transfer_addr(struct iio_backend *back, u32 address)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ if (address > FIELD_MAX(AXI_DAC_CUSTOM_CTRL_ADDRESS))
+ return -EINVAL;
+
+ /*
+ * Sample register address, when the DAC is configured, or stream
+ * start address when the FSM is in stream state.
+ */
+ return regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_ADDRESS,
+ FIELD_PREP(AXI_DAC_CUSTOM_CTRL_ADDRESS,
+ address));
+}
+
+static int axi_dac_data_format_set(struct iio_backend *back, unsigned int ch,
+ const struct iio_backend_data_fmt *data)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ switch (data->type) {
+ case IIO_BACKEND_DATA_UNSIGNED:
+ return regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_UNSIGNED_DATA);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int __axi_dac_bus_reg_write(struct iio_backend *back, u32 reg,
+ u32 val, size_t data_size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+ int ret;
+ u32 ival;
+
+ /*
+ * Both AXI_DAC_CNTRL_2_REG and AXI_DAC_CUSTOM_WR_REG need to know
+ * the data size. So keeping data size control here only,
+ * since data size is mandatory for the current transfer.
+ * DDR state handled separately by specific backend calls,
+ * generally all raw register writes are SDR.
+ */
+ if (data_size == sizeof(u16))
+ ival = FIELD_PREP(AXI_DAC_CUSTOM_WR_DATA_16, val);
+ else
+ ival = FIELD_PREP(AXI_DAC_CUSTOM_WR_DATA_8, val);
+
+ ret = regmap_write(st->regmap, AXI_DAC_CUSTOM_WR_REG, ival);
+ if (ret)
+ return ret;
+
+ if (data_size == sizeof(u8))
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SYMB_8B);
+ else
+ ret = regmap_clear_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ AXI_DAC_CNTRL_2_SYMB_8B);
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_ADDRESS,
+ FIELD_PREP(AXI_DAC_CUSTOM_CTRL_ADDRESS, reg));
+ if (ret)
+ return ret;
+
+ ret = regmap_update_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA,
+ AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA);
+ if (ret)
+ return ret;
+
+ ret = regmap_read_poll_timeout(st->regmap,
+ AXI_DAC_UI_STATUS_REG, ival,
+ FIELD_GET(AXI_DAC_UI_STATUS_IF_BUSY, ival) == 0,
+ 10, 100 * KILO);
+ if (ret == -ETIMEDOUT)
+ dev_err(st->dev, "AXI read timeout\n");
+
+ /* Cleaning always AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA */
+ return regmap_clear_bits(st->regmap, AXI_DAC_CUSTOM_CTRL_REG,
+ AXI_DAC_CUSTOM_CTRL_TRANSFER_DATA);
+}
+
+static int axi_dac_bus_reg_write(struct iio_backend *back, u32 reg,
+ u32 val, size_t data_size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+
+ guard(mutex)(&st->lock);
+ return __axi_dac_bus_reg_write(back, reg, val, data_size);
+}
+
+static int axi_dac_bus_reg_read(struct iio_backend *back, u32 reg, u32 *val,
+ size_t data_size)
+{
+ struct axi_dac_state *st = iio_backend_get_priv(back);
+ int ret;
+
+ guard(mutex)(&st->lock);
+
+ /*
+ * SPI, we write with read flag, then we read just at the AXI
+ * io address space to get data read.
+ */
+ ret = __axi_dac_bus_reg_write(back, AXI_DAC_RD_ADDR(reg), 0,
+ data_size);
+ if (ret)
+ return ret;
+
+ return regmap_read(st->regmap, AXI_DAC_CUSTOM_RD_REG, val);
+}
+
+static void axi_dac_child_remove(void *data)
+{
+ platform_device_unregister(data);
+}
+
+static int axi_dac_create_platform_device(struct axi_dac_state *st,
+ struct fwnode_handle *child)
+{
+ struct ad3552r_hs_platform_data pdata = {
+ .bus_reg_read = axi_dac_bus_reg_read,
+ .bus_reg_write = axi_dac_bus_reg_write,
+ .bus_sample_data_clock_hz = st->dac_clk_rate,
+ };
+ struct platform_device_info pi = {
+ .parent = st->dev,
+ .name = fwnode_get_name(child),
+ .id = PLATFORM_DEVID_AUTO,
+ .fwnode = child,
+ .data = &pdata,
+ .size_data = sizeof(pdata),
+ };
+ struct platform_device *pdev;
+
+ pdev = platform_device_register_full(&pi);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ return devm_add_action_or_reset(st->dev, axi_dac_child_remove, pdev);
+}
+
static const struct iio_backend_ops axi_dac_generic_ops = {
.enable = axi_dac_enable,
.disable = axi_dac_disable,
@@ -531,11 +757,30 @@ static const struct iio_backend_ops axi_dac_generic_ops = {
.debugfs_reg_access = iio_backend_debugfs_ptr(axi_dac_reg_access),
};
+static const struct iio_backend_ops axi_ad3552r_ops = {
+ .enable = axi_dac_enable,
+ .disable = axi_dac_disable,
+ .request_buffer = axi_dac_request_buffer,
+ .free_buffer = axi_dac_free_buffer,
+ .data_source_set = axi_dac_data_source_set,
+ .ddr_enable = axi_dac_ddr_enable,
+ .ddr_disable = axi_dac_ddr_disable,
+ .data_stream_enable = axi_dac_data_stream_enable,
+ .data_stream_disable = axi_dac_data_stream_disable,
+ .data_format_set = axi_dac_data_format_set,
+ .data_transfer_addr = axi_dac_data_transfer_addr,
+};
+
static const struct iio_backend_info axi_dac_generic = {
.name = "axi-dac",
.ops = &axi_dac_generic_ops,
};
+static const struct iio_backend_info axi_ad3552r = {
+ .name = "axi-ad3552r",
+ .ops = &axi_ad3552r_ops,
+};
+
static const struct regmap_config axi_dac_regmap_config = {
.val_bits = 32,
.reg_bits = 32,
@@ -545,7 +790,6 @@ static const struct regmap_config axi_dac_regmap_config = {
static int axi_dac_probe(struct platform_device *pdev)
{
- const unsigned int *expected_ver;
struct axi_dac_state *st;
void __iomem *base;
unsigned int ver;
@@ -556,14 +800,29 @@ static int axi_dac_probe(struct platform_device *pdev)
if (!st)
return -ENOMEM;
- expected_ver = device_get_match_data(&pdev->dev);
- if (!expected_ver)
+ st->info = device_get_match_data(&pdev->dev);
+ if (!st->info)
return -ENODEV;
+ clk = devm_clk_get_enabled(&pdev->dev, "s_axi_aclk");
+ if (IS_ERR(clk)) {
+ /* Backward compat., old fdt versions without clock-names. */
+ clk = devm_clk_get_enabled(&pdev->dev, NULL);
+ if (IS_ERR(clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(clk),
+ "failed to get clock\n");
+ }
- clk = devm_clk_get_enabled(&pdev->dev, NULL);
- if (IS_ERR(clk))
- return dev_err_probe(&pdev->dev, PTR_ERR(clk),
- "failed to get clock\n");
+ if (st->info->has_dac_clk) {
+ struct clk *dac_clk;
+
+ dac_clk = devm_clk_get_enabled(&pdev->dev, "dac_clk");
+ if (IS_ERR(dac_clk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(dac_clk),
+ "failed to get dac_clk clock\n");
+
+ /* We only care about the streaming mode rate */
+ st->dac_clk_rate = clk_get_rate(dac_clk) / 2;
+ }
base = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(base))
@@ -580,7 +839,7 @@ static int axi_dac_probe(struct platform_device *pdev)
* Force disable the core. Up to the frontend to enable us. And we can
* still read/write registers...
*/
- ret = regmap_write(st->regmap, AXI_DAC_REG_RSTN, 0);
+ ret = regmap_write(st->regmap, AXI_DAC_RSTN_REG, 0);
if (ret)
return ret;
@@ -588,12 +847,13 @@ static int axi_dac_probe(struct platform_device *pdev)
if (ret)
return ret;
- if (ADI_AXI_PCORE_VER_MAJOR(ver) != ADI_AXI_PCORE_VER_MAJOR(*expected_ver)) {
+ if (ADI_AXI_PCORE_VER_MAJOR(ver) !=
+ ADI_AXI_PCORE_VER_MAJOR(st->info->version)) {
dev_err(&pdev->dev,
"Major version mismatch. Expected %d.%.2d.%c, Reported %d.%.2d.%c\n",
- ADI_AXI_PCORE_VER_MAJOR(*expected_ver),
- ADI_AXI_PCORE_VER_MINOR(*expected_ver),
- ADI_AXI_PCORE_VER_PATCH(*expected_ver),
+ ADI_AXI_PCORE_VER_MAJOR(st->info->version),
+ ADI_AXI_PCORE_VER_MINOR(st->info->version),
+ ADI_AXI_PCORE_VER_PATCH(st->info->version),
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
ADI_AXI_PCORE_VER_PATCH(ver));
@@ -601,7 +861,7 @@ static int axi_dac_probe(struct platform_device *pdev)
}
/* Let's get the core read only configuration */
- ret = regmap_read(st->regmap, AXI_DAC_REG_CONFIG, &st->reg_config);
+ ret = regmap_read(st->regmap, AXI_DAC_CONFIG_REG, &st->reg_config);
if (ret)
return ret;
@@ -613,16 +873,40 @@ static int axi_dac_probe(struct platform_device *pdev)
* want independent channels let's override the core's default value and
* set the R1_MODE bit.
*/
- ret = regmap_set_bits(st->regmap, AXI_DAC_REG_CNTRL_2, ADI_DAC_R1_MODE);
+ ret = regmap_set_bits(st->regmap, AXI_DAC_CNTRL_2_REG,
+ ADI_DAC_CNTRL_2_R1_MODE);
if (ret)
return ret;
mutex_init(&st->lock);
- ret = devm_iio_backend_register(&pdev->dev, &axi_dac_generic, st);
+
+ ret = devm_iio_backend_register(&pdev->dev, st->info->backend_info, st);
if (ret)
return dev_err_probe(&pdev->dev, ret,
"failed to register iio backend\n");
+ device_for_each_child_node_scoped(&pdev->dev, child) {
+ int val;
+
+ if (!st->info->has_child_nodes)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "invalid fdt axi-dac compatible.");
+
+ /* Processing only reg 0 node */
+ ret = fwnode_property_read_u32(child, "reg", &val);
+ if (ret)
+ return dev_err_probe(&pdev->dev, ret,
+ "invalid reg property.");
+ if (val != 0)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "invalid node address.");
+
+ ret = axi_dac_create_platform_device(st, child);
+ if (ret)
+ return dev_err_probe(&pdev->dev, -EINVAL,
+ "cannot create device.");
+ }
+
dev_info(&pdev->dev, "AXI DAC IP core (%d.%.2d.%c) probed\n",
ADI_AXI_PCORE_VER_MAJOR(ver),
ADI_AXI_PCORE_VER_MINOR(ver),
@@ -631,10 +915,21 @@ static int axi_dac_probe(struct platform_device *pdev)
return 0;
}
-static unsigned int axi_dac_9_1_b_info = ADI_AXI_PCORE_VER(9, 1, 'b');
+static const struct axi_dac_info dac_generic = {
+ .version = ADI_AXI_PCORE_VER(9, 1, 'b'),
+ .backend_info = &axi_dac_generic,
+};
+
+static const struct axi_dac_info dac_ad3552r = {
+ .version = ADI_AXI_PCORE_VER(9, 1, 'b'),
+ .backend_info = &axi_ad3552r,
+ .has_dac_clk = true,
+ .has_child_nodes = true,
+};
static const struct of_device_id axi_dac_of_match[] = {
- { .compatible = "adi,axi-dac-9.1.b", .data = &axi_dac_9_1_b_info },
+ { .compatible = "adi,axi-dac-9.1.b", .data = &dac_generic },
+ { .compatible = "adi,axi-ad3552r", .data = &dac_ad3552r },
{}
};
MODULE_DEVICE_TABLE(of, axi_dac_of_match);
@@ -651,5 +946,5 @@ module_platform_driver(axi_dac_driver);
MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
MODULE_DESCRIPTION("Analog Devices Generic AXI DAC IP core driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_DMAENGINE_BUFFER);
-MODULE_IMPORT_NS(IIO_BACKEND);
+MODULE_IMPORT_NS("IIO_DMAENGINE_BUFFER");
+MODULE_IMPORT_NS("IIO_BACKEND");
diff --git a/drivers/iio/dac/dpot-dac.c b/drivers/iio/dac/dpot-dac.c
index 7332064d0852..f36f10bfb6be 100644
--- a/drivers/iio/dac/dpot-dac.c
+++ b/drivers/iio/dac/dpot-dac.c
@@ -243,7 +243,7 @@ MODULE_DEVICE_TABLE(of, dpot_dac_match);
static struct platform_driver dpot_dac_driver = {
.probe = dpot_dac_probe,
- .remove_new = dpot_dac_remove,
+ .remove = dpot_dac_remove,
.driver = {
.name = "iio-dpot-dac",
.of_match_table = dpot_dac_match,
diff --git a/drivers/iio/dac/lpc18xx_dac.c b/drivers/iio/dac/lpc18xx_dac.c
index b3aa4443a6a4..2332b0c22691 100644
--- a/drivers/iio/dac/lpc18xx_dac.c
+++ b/drivers/iio/dac/lpc18xx_dac.c
@@ -184,9 +184,9 @@ static const struct of_device_id lpc18xx_dac_match[] = {
MODULE_DEVICE_TABLE(of, lpc18xx_dac_match);
static struct platform_driver lpc18xx_dac_driver = {
- .probe = lpc18xx_dac_probe,
- .remove_new = lpc18xx_dac_remove,
- .driver = {
+ .probe = lpc18xx_dac_probe,
+ .remove = lpc18xx_dac_remove,
+ .driver = {
.name = "lpc18xx-dac",
.of_match_table = lpc18xx_dac_match,
},
diff --git a/drivers/iio/dac/m62332.c b/drivers/iio/dac/m62332.c
index ae53baccec91..3497513854d7 100644
--- a/drivers/iio/dac/m62332.c
+++ b/drivers/iio/dac/m62332.c
@@ -201,7 +201,7 @@ static int m62332_probe(struct i2c_client *client)
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->info = &m62332_info;
- ret = iio_map_array_register(indio_dev, client->dev.platform_data);
+ ret = iio_map_array_register(indio_dev, dev_get_platdata(&client->dev));
if (ret < 0)
return ret;
diff --git a/drivers/iio/dac/max517.c b/drivers/iio/dac/max517.c
index 685980184d3c..84336736a47b 100644
--- a/drivers/iio/dac/max517.c
+++ b/drivers/iio/dac/max517.c
@@ -143,10 +143,10 @@ static const struct iio_chan_spec max517_channels[] = {
static int max517_probe(struct i2c_client *client)
{
+ const struct max517_platform_data *platform_data = dev_get_platdata(&client->dev);
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct max517_data *data;
struct iio_dev *indio_dev;
- struct max517_platform_data *platform_data = client->dev.platform_data;
int chan;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
diff --git a/drivers/iio/dac/stm32-dac-core.c b/drivers/iio/dac/stm32-dac-core.c
index 2d567073996b..95ed5197d16f 100644
--- a/drivers/iio/dac/stm32-dac-core.c
+++ b/drivers/iio/dac/stm32-dac-core.c
@@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
- .remove_new = stm32_dac_remove,
+ .remove = stm32_dac_remove,
.driver = {
.name = "stm32-dac-core",
.of_match_table = stm32_dac_of_match,
diff --git a/drivers/iio/dac/stm32-dac.c b/drivers/iio/dac/stm32-dac.c
index 5a722f307e7e..3bfb368b3a23 100644
--- a/drivers/iio/dac/stm32-dac.c
+++ b/drivers/iio/dac/stm32-dac.c
@@ -398,7 +398,7 @@ MODULE_DEVICE_TABLE(of, stm32_dac_of_match);
static struct platform_driver stm32_dac_driver = {
.probe = stm32_dac_probe,
- .remove_new = stm32_dac_remove,
+ .remove = stm32_dac_remove,
.driver = {
.name = "stm32-dac",
.of_match_table = stm32_dac_of_match,
diff --git a/drivers/iio/dac/vf610_dac.c b/drivers/iio/dac/vf610_dac.c
index de73bc5a1c93..82a078fa98ad 100644
--- a/drivers/iio/dac/vf610_dac.c
+++ b/drivers/iio/dac/vf610_dac.c
@@ -272,7 +272,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(vf610_dac_pm_ops, vf610_dac_suspend,
static struct platform_driver vf610_dac_driver = {
.probe = vf610_dac_probe,
- .remove_new = vf610_dac_remove,
+ .remove = vf610_dac_remove,
.driver = {
.name = "vf610-dac",
.of_match_table = vf610_dac_match,
diff --git a/drivers/iio/dummy/iio_simple_dummy.h b/drivers/iio/dummy/iio_simple_dummy.h
index a91622ac54e0..8246f25dbad0 100644
--- a/drivers/iio/dummy/iio_simple_dummy.h
+++ b/drivers/iio/dummy/iio_simple_dummy.h
@@ -60,7 +60,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state);
+ bool state);
int iio_simple_dummy_read_event_value(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
diff --git a/drivers/iio/dummy/iio_simple_dummy_events.c b/drivers/iio/dummy/iio_simple_dummy_events.c
index 63a2b844be50..b51ec21b6309 100644
--- a/drivers/iio/dummy/iio_simple_dummy_events.c
+++ b/drivers/iio/dummy/iio_simple_dummy_events.c
@@ -53,7 +53,7 @@ int iio_simple_dummy_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct iio_dummy_state *st = iio_priv(indio_dev);
@@ -183,36 +183,34 @@ static irqreturn_t iio_simple_dummy_event_handler(int irq, void *private)
switch (st->regs->reg_data) {
case 0:
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_VOLTAGE, 0, 0,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH, 0, 0, 0),
+ IIO_UNMOD_EVENT_CODE(IIO_VOLTAGE, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
st->event_timestamp);
break;
case 1:
if (st->activity_running > st->event_val)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- IIO_MOD_RUNNING,
- IIO_EV_DIR_RISING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ IIO_MOD_RUNNING,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_RISING),
st->event_timestamp);
break;
case 2:
if (st->activity_walking < st->event_val)
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_ACTIVITY, 0,
- IIO_MOD_WALKING,
- IIO_EV_DIR_FALLING,
- IIO_EV_TYPE_THRESH,
- 0, 0, 0),
+ IIO_MOD_EVENT_CODE(IIO_ACTIVITY, 0,
+ IIO_MOD_WALKING,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_FALLING),
st->event_timestamp);
break;
case 3:
iio_push_event(indio_dev,
- IIO_EVENT_CODE(IIO_STEPS, 0, IIO_NO_MOD,
- IIO_EV_DIR_NONE,
- IIO_EV_TYPE_CHANGE, 0, 0, 0),
+ IIO_UNMOD_EVENT_CODE(IIO_STEPS, 0,
+ IIO_EV_TYPE_CHANGE,
+ IIO_EV_DIR_NONE),
st->event_timestamp);
break;
default:
diff --git a/drivers/iio/frequency/ad9523.c b/drivers/iio/frequency/ad9523.c
index b391c6e27ab0..b1554ced7a26 100644
--- a/drivers/iio/frequency/ad9523.c
+++ b/drivers/iio/frequency/ad9523.c
@@ -970,7 +970,7 @@ static int ad9523_setup(struct iio_dev *indio_dev)
static int ad9523_probe(struct spi_device *spi)
{
- struct ad9523_platform_data *pdata = spi->dev.platform_data;
+ struct ad9523_platform_data *pdata = dev_get_platdata(&spi->dev);
struct iio_dev *indio_dev;
struct ad9523_state *st;
int ret;
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index e13e64a5164c..61828e61e275 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -603,7 +603,7 @@ static int adf4350_probe(struct spi_device *spi)
if (pdata == NULL)
return -EINVAL;
} else {
- pdata = spi->dev.platform_data;
+ pdata = dev_get_platdata(&spi->dev);
}
if (!pdata) {
diff --git a/drivers/iio/frequency/adf4371.c b/drivers/iio/frequency/adf4371.c
index b27088464826..d752507e0c98 100644
--- a/drivers/iio/frequency/adf4371.c
+++ b/drivers/iio/frequency/adf4371.c
@@ -4,6 +4,7 @@
*
* Copyright 2019 Analog Devices Inc.
*/
+#include "linux/dev_printk.h"
#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/device.h>
@@ -150,6 +151,7 @@ static const struct regmap_config adf4371_regmap_config = {
};
struct adf4371_chip_info {
+ const char *name;
unsigned int num_channels;
const struct iio_chan_spec *channels;
};
@@ -157,7 +159,6 @@ struct adf4371_chip_info {
struct adf4371_state {
struct spi_device *spi;
struct regmap *regmap;
- struct clk *clkin;
/*
* Lock for accessing device registers. Some operations require
* multiple consecutive R/W operations, during which the device
@@ -444,15 +445,16 @@ static const struct iio_chan_spec adf4371_chan[] = {
ADF4371_CHANNEL(ADF4371_CH_RF32),
};
-static const struct adf4371_chip_info adf4371_chip_info[] = {
- [ADF4371] = {
- .channels = adf4371_chan,
- .num_channels = 4,
- },
- [ADF4372] = {
- .channels = adf4371_chan,
- .num_channels = 3,
- }
+static const struct adf4371_chip_info adf4371_chip_info = {
+ .name = "adf4371",
+ .channels = adf4371_chan,
+ .num_channels = 4,
+};
+
+static const struct adf4371_chip_info adf4372_chip_info = {
+ .name = "adf4372",
+ .channels = adf4371_chan,
+ .num_channels = 3,
};
static int adf4371_reg_access(struct iio_dev *indio_dev,
@@ -542,10 +544,10 @@ static int adf4371_setup(struct adf4371_state *st)
static int adf4371_probe(struct spi_device *spi)
{
- const struct spi_device_id *id = spi_get_device_id(spi);
struct iio_dev *indio_dev;
struct adf4371_state *st;
struct regmap *regmap;
+ struct clk *clkin;
int ret;
indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
@@ -553,50 +555,49 @@ static int adf4371_probe(struct spi_device *spi)
return -ENOMEM;
regmap = devm_regmap_init_spi(spi, &adf4371_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
- PTR_ERR(regmap));
- return PTR_ERR(regmap);
- }
+ if (IS_ERR(regmap))
+ return dev_err_probe(&spi->dev, PTR_ERR(regmap),
+ "Error initializing spi regmap\n");
st = iio_priv(indio_dev);
- spi_set_drvdata(spi, indio_dev);
st->spi = spi;
st->regmap = regmap;
mutex_init(&st->lock);
- st->chip_info = &adf4371_chip_info[id->driver_data];
- indio_dev->name = id->name;
+ st->chip_info = spi_get_device_match_data(spi);
+ if (!st->chip_info)
+ return -ENODEV;
+
+ indio_dev->name = st->chip_info->name;
indio_dev->info = &adf4371_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->channels = st->chip_info->channels;
indio_dev->num_channels = st->chip_info->num_channels;
- st->clkin = devm_clk_get_enabled(&spi->dev, "clkin");
- if (IS_ERR(st->clkin))
- return PTR_ERR(st->clkin);
+ clkin = devm_clk_get_enabled(&spi->dev, "clkin");
+ if (IS_ERR(clkin))
+ return dev_err_probe(&spi->dev, PTR_ERR(clkin),
+ "Failed to get clkin\n");
- st->clkin_freq = clk_get_rate(st->clkin);
+ st->clkin_freq = clk_get_rate(clkin);
ret = adf4371_setup(st);
- if (ret < 0) {
- dev_err(&spi->dev, "ADF4371 setup failed\n");
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(&spi->dev, ret, "ADF4371 setup failed\n");
return devm_iio_device_register(&spi->dev, indio_dev);
}
static const struct spi_device_id adf4371_id_table[] = {
- { "adf4371", ADF4371 },
- { "adf4372", ADF4372 },
+ { "adf4371", (kernel_ulong_t)&adf4371_chip_info },
+ { "adf4372", (kernel_ulong_t)&adf4372_chip_info },
{}
};
MODULE_DEVICE_TABLE(spi, adf4371_id_table);
static const struct of_device_id adf4371_of_match[] = {
- { .compatible = "adi,adf4371" },
- { .compatible = "adi,adf4372" },
+ { .compatible = "adi,adf4371", .data = &adf4371_chip_info },
+ { .compatible = "adi,adf4372", .data = &adf4372_chip_info},
{ },
};
MODULE_DEVICE_TABLE(of, adf4371_of_match);
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 97b86c4a53a6..3e193ee0fb61 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -27,7 +27,7 @@ config ADIS16136
select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
help
Say yes here to build support for the Analog Devices ADIS16133, ADIS16135,
- ADIS16136 gyroscope devices.
+ ADIS16136, ADIS16137 gyroscope devices.
config ADIS16260
tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
diff --git a/drivers/iio/gyro/adis16136.c b/drivers/iio/gyro/adis16136.c
index da83adc684d0..369c7428e1ef 100644
--- a/drivers/iio/gyro/adis16136.c
+++ b/drivers/iio/gyro/adis16136.c
@@ -583,4 +583,4 @@ module_spi_driver(adis16136_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Analog Devices ADIS16133/ADIS16135/ADIS16136 gyroscope driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADISLIB);
+MODULE_IMPORT_NS("IIO_ADISLIB");
diff --git a/drivers/iio/gyro/adis16260.c b/drivers/iio/gyro/adis16260.c
index 495b64a27061..c151fbb59ffe 100644
--- a/drivers/iio/gyro/adis16260.c
+++ b/drivers/iio/gyro/adis16260.c
@@ -430,4 +430,4 @@ module_spi_driver(adis16260_driver);
MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16260/5 Digital Gyroscope Sensor");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADISLIB);
+MODULE_IMPORT_NS("IIO_ADISLIB");
diff --git a/drivers/iio/gyro/bmg160_core.c b/drivers/iio/gyro/bmg160_core.c
index 10728d5ccae3..ba877d067afb 100644
--- a/drivers/iio/gyro/bmg160_core.c
+++ b/drivers/iio/gyro/bmg160_core.c
@@ -8,7 +8,6 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
@@ -444,7 +443,7 @@ static int bmg160_setup_new_data_interrupt(struct bmg160_data *data,
static int bmg160_get_bw(struct bmg160_data *data, int *val)
{
- struct device *dev = regmap_get_device(data->regmap);
+ struct device *dev = regmap_get_device(data->regmap);
int i;
unsigned int bw_bits;
int ret;
@@ -749,7 +748,7 @@ static int bmg160_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct bmg160_data *data = iio_priv(indio_dev);
int ret;
@@ -1055,17 +1054,6 @@ static const struct iio_buffer_setup_ops bmg160_buffer_setup_ops = {
.postdisable = bmg160_buffer_postdisable,
};
-static const char *bmg160_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
const char *name)
{
@@ -1098,9 +1086,6 @@ int bmg160_core_probe(struct device *dev, struct regmap *regmap, int irq,
mutex_init(&data->mutex);
- if (ACPI_HANDLE(dev))
- name = bmg160_match_acpi_device(dev);
-
indio_dev->channels = bmg160_channels;
indio_dev->num_channels = ARRAY_SIZE(bmg160_channels);
indio_dev->name = name;
diff --git a/drivers/iio/gyro/bmg160_i2c.c b/drivers/iio/gyro/bmg160_i2c.c
index 672d0b720f61..9c5d7e8ee99c 100644
--- a/drivers/iio/gyro/bmg160_i2c.c
+++ b/drivers/iio/gyro/bmg160_i2c.c
@@ -17,7 +17,7 @@ static int bmg160_i2c_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct regmap *regmap;
- const char *name = NULL;
+ const char *name;
regmap = devm_regmap_init_i2c(client, &bmg160_regmap_i2c_conf);
if (IS_ERR(regmap)) {
@@ -28,6 +28,8 @@ static int bmg160_i2c_probe(struct i2c_client *client)
if (id)
name = id->name;
+ else
+ name = iio_get_acpi_device_name(&client->dev);
return bmg160_core_probe(&client->dev, regmap, client->irq, name);
}
@@ -39,8 +41,6 @@ static void bmg160_i2c_remove(struct i2c_client *client)
static const struct acpi_device_id bmg160_acpi_match[] = {
{"BMG0160", 0},
- {"BMI055B", 0},
- {"BMI088B", 0},
{},
};
diff --git a/drivers/iio/gyro/fxas21002c_core.c b/drivers/iio/gyro/fxas21002c_core.c
index c28d17ca6f5e..0391c78c2f18 100644
--- a/drivers/iio/gyro/fxas21002c_core.c
+++ b/drivers/iio/gyro/fxas21002c_core.c
@@ -849,8 +849,7 @@ static int fxas21002c_trigger_probe(struct fxas21002c_data *data)
if (!data->dready_trig)
return -ENOMEM;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(data->irq));
-
+ irq_trig = irq_get_trigger_type(data->irq);
if (irq_trig == IRQF_TRIGGER_RISING) {
ret = regmap_field_write(data->regmap_fields[F_IPOL], 1);
if (ret < 0)
@@ -998,7 +997,7 @@ pm_disable:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(fxas21002c_core_probe, IIO_FXAS21002C);
+EXPORT_SYMBOL_NS_GPL(fxas21002c_core_probe, "IIO_FXAS21002C");
void fxas21002c_core_remove(struct device *dev)
{
@@ -1009,7 +1008,7 @@ void fxas21002c_core_remove(struct device *dev)
pm_runtime_disable(dev);
pm_runtime_set_suspended(dev);
}
-EXPORT_SYMBOL_NS_GPL(fxas21002c_core_remove, IIO_FXAS21002C);
+EXPORT_SYMBOL_NS_GPL(fxas21002c_core_remove, "IIO_FXAS21002C");
static int fxas21002c_suspend(struct device *dev)
{
diff --git a/drivers/iio/gyro/fxas21002c_i2c.c b/drivers/iio/gyro/fxas21002c_i2c.c
index b1318a1ea41b..43c6b3079487 100644
--- a/drivers/iio/gyro/fxas21002c_i2c.c
+++ b/drivers/iio/gyro/fxas21002c_i2c.c
@@ -65,4 +65,4 @@ module_i2c_driver(fxas21002c_i2c_driver);
MODULE_AUTHOR("Rui Miguel Silva <rui.silva@linaro.org>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("FXAS21002C I2C Gyro driver");
-MODULE_IMPORT_NS(IIO_FXAS21002C);
+MODULE_IMPORT_NS("IIO_FXAS21002C");
diff --git a/drivers/iio/gyro/fxas21002c_spi.c b/drivers/iio/gyro/fxas21002c_spi.c
index 4f633826547c..d62efe50b697 100644
--- a/drivers/iio/gyro/fxas21002c_spi.c
+++ b/drivers/iio/gyro/fxas21002c_spi.c
@@ -66,4 +66,4 @@ module_spi_driver(fxas21002c_spi_driver);
MODULE_AUTHOR("Rui Miguel Silva <rui.silva@linaro.org>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("FXAS21002C SPI Gyro driver");
-MODULE_IMPORT_NS(IIO_FXAS21002C);
+MODULE_IMPORT_NS("IIO_FXAS21002C");
diff --git a/drivers/iio/gyro/hid-sensor-gyro-3d.c b/drivers/iio/gyro/hid-sensor-gyro-3d.c
index 59a38bf9459b..54b6f6fbdcaa 100644
--- a/drivers/iio/gyro/hid-sensor-gyro-3d.c
+++ b/drivers/iio/gyro/hid-sensor-gyro-3d.c
@@ -27,7 +27,7 @@ struct gyro_3d_state {
struct hid_sensor_hub_attribute_info gyro[GYRO_3D_CHANNEL_MAX];
struct {
u32 gyro_val[GYRO_3D_CHANNEL_MAX];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -279,11 +279,11 @@ static int gyro_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_gyro_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "gyro_3d";
struct iio_dev *indio_dev;
struct gyro_3d_state *gyro_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(*gyro_state));
if (!indio_dev)
@@ -361,7 +361,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_gyro_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct gyro_3d_state *gyro_state = iio_priv(indio_dev);
@@ -386,11 +386,11 @@ static struct platform_driver hid_gyro_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_gyro_3d_probe,
- .remove_new = hid_gyro_3d_remove,
+ .remove = hid_gyro_3d_remove,
};
module_platform_driver(hid_gyro_3d_platform_driver);
MODULE_DESCRIPTION("HID Sensor Gyroscope 3D");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/gyro/mpu3050-core.c b/drivers/iio/gyro/mpu3050-core.c
index 35af68b41408..b6883e8b2a8b 100644
--- a/drivers/iio/gyro/mpu3050-core.c
+++ b/drivers/iio/gyro/mpu3050-core.c
@@ -1059,12 +1059,12 @@ static int mpu3050_trigger_probe(struct iio_dev *indio_dev, int irq)
/* Check if IRQ is open drain */
mpu3050->irq_opendrain = device_property_read_bool(dev, "drive-open-drain");
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
/*
* Configure the interrupt generator hardware to supply whatever
* the interrupt is configured for, edges low/high level low/high,
* we can provide it all.
*/
+ irq_trig = irq_get_trigger_type(irq);
switch (irq_trig) {
case IRQF_TRIGGER_RISING:
dev_info(&indio_dev->dev,
diff --git a/drivers/iio/gyro/ssp_gyro_sensor.c b/drivers/iio/gyro/ssp_gyro_sensor.c
index d332474bc484..d9b41cf8d799 100644
--- a/drivers/iio/gyro/ssp_gyro_sensor.c
+++ b/drivers/iio/gyro/ssp_gyro_sensor.c
@@ -141,4 +141,4 @@ module_platform_driver(ssp_gyro_driver);
MODULE_AUTHOR("Karol Wrona <k.wrona@samsung.com>");
MODULE_DESCRIPTION("Samsung sensorhub gyroscopes driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_SSP_SENSORS);
+MODULE_IMPORT_NS("IIO_SSP_SENSORS");
diff --git a/drivers/iio/gyro/st_gyro_core.c b/drivers/iio/gyro/st_gyro_core.c
index eaa35da42b33..7fd82cd707c7 100644
--- a/drivers/iio/gyro/st_gyro_core.c
+++ b/drivers/iio/gyro/st_gyro_core.c
@@ -465,7 +465,7 @@ const struct st_sensor_settings *st_gyro_get_settings(const char *name)
return &st_gyro_sensors_settings[index];
}
-EXPORT_SYMBOL_NS(st_gyro_get_settings, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_gyro_get_settings, "IIO_ST_SENSORS");
int st_gyro_common_probe(struct iio_dev *indio_dev)
{
@@ -511,9 +511,9 @@ int st_gyro_common_probe(struct iio_dev *indio_dev)
return devm_iio_device_register(parent, indio_dev);
}
-EXPORT_SYMBOL_NS(st_gyro_common_probe, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_gyro_common_probe, "IIO_ST_SENSORS");
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics gyroscopes driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/gyro/st_gyro_i2c.c b/drivers/iio/gyro/st_gyro_i2c.c
index 5a10a3556ab0..d4b11bdba666 100644
--- a/drivers/iio/gyro/st_gyro_i2c.c
+++ b/drivers/iio/gyro/st_gyro_i2c.c
@@ -119,4 +119,4 @@ module_i2c_driver(st_gyro_driver);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics gyroscopes i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/gyro/st_gyro_spi.c b/drivers/iio/gyro/st_gyro_spi.c
index 22aaabe48e4a..811f712711f5 100644
--- a/drivers/iio/gyro/st_gyro_spi.c
+++ b/drivers/iio/gyro/st_gyro_spi.c
@@ -124,4 +124,4 @@ module_spi_driver(st_gyro_driver);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics gyroscopes spi driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/humidity/hid-sensor-humidity.c b/drivers/iio/humidity/hid-sensor-humidity.c
index bf6d2636a85e..a40e1eb6e98c 100644
--- a/drivers/iio/humidity/hid-sensor-humidity.c
+++ b/drivers/iio/humidity/hid-sensor-humidity.c
@@ -18,7 +18,7 @@ struct hid_humidity_state {
struct hid_sensor_hub_attribute_info humidity_attr;
struct {
s32 humidity_data;
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -287,11 +287,11 @@ static struct platform_driver hid_humidity_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_humidity_probe,
- .remove_new = hid_humidity_remove,
+ .remove = hid_humidity_remove,
};
module_platform_driver(hid_humidity_platform_driver);
MODULE_DESCRIPTION("HID Environmental humidity sensor");
MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/humidity/hts221_buffer.c b/drivers/iio/humidity/hts221_buffer.c
index 11ef38994a95..4d03db19063e 100644
--- a/drivers/iio/humidity/hts221_buffer.c
+++ b/drivers/iio/humidity/hts221_buffer.c
@@ -81,8 +81,7 @@ int hts221_allocate_trigger(struct iio_dev *iio_dev)
unsigned long irq_type;
int err;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
-
+ irq_type = irq_get_trigger_type(hw->irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
diff --git a/drivers/iio/humidity/hts221_core.c b/drivers/iio/humidity/hts221_core.c
index 87627d116eff..0be11470730c 100644
--- a/drivers/iio/humidity/hts221_core.c
+++ b/drivers/iio/humidity/hts221_core.c
@@ -649,7 +649,7 @@ int hts221_probe(struct device *dev, int irq, const char *name,
return devm_iio_device_register(hw->dev, iio_dev);
}
-EXPORT_SYMBOL_NS(hts221_probe, IIO_HTS221);
+EXPORT_SYMBOL_NS(hts221_probe, "IIO_HTS221");
static int hts221_suspend(struct device *dev)
{
diff --git a/drivers/iio/humidity/hts221_i2c.c b/drivers/iio/humidity/hts221_i2c.c
index 5cb263e0ef5a..87a8e3c8d277 100644
--- a/drivers/iio/humidity/hts221_i2c.c
+++ b/drivers/iio/humidity/hts221_i2c.c
@@ -73,4 +73,4 @@ module_i2c_driver(hts221_driver);
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
MODULE_DESCRIPTION("STMicroelectronics hts221 i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_HTS221);
+MODULE_IMPORT_NS("IIO_HTS221");
diff --git a/drivers/iio/humidity/hts221_spi.c b/drivers/iio/humidity/hts221_spi.c
index fc4adb68faf6..00154b9d66b5 100644
--- a/drivers/iio/humidity/hts221_spi.c
+++ b/drivers/iio/humidity/hts221_spi.c
@@ -66,4 +66,4 @@ module_spi_driver(hts221_driver);
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
MODULE_DESCRIPTION("STMicroelectronics hts221 spi driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_HTS221);
+MODULE_IMPORT_NS("IIO_HTS221");
diff --git a/drivers/iio/humidity/htu21.c b/drivers/iio/humidity/htu21.c
index 39e886075299..6402e393edb8 100644
--- a/drivers/iio/humidity/htu21.c
+++ b/drivers/iio/humidity/htu21.c
@@ -258,4 +258,4 @@ MODULE_DESCRIPTION("Measurement-Specialties htu21 temperature and humidity drive
MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
MODULE_AUTHOR("Ludovic Tancerel <ludovic.tancerel@maplehightech.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_MEAS_SPEC_SENSORS);
+MODULE_IMPORT_NS("IIO_MEAS_SPEC_SENSORS");
diff --git a/drivers/iio/imu/Kconfig b/drivers/iio/imu/Kconfig
index 782fb80e44c2..ca0efecb5b5c 100644
--- a/drivers/iio/imu/Kconfig
+++ b/drivers/iio/imu/Kconfig
@@ -53,6 +53,7 @@ config ADIS16480
ADIS16485, ADIS16488 inertial sensors.
source "drivers/iio/imu/bmi160/Kconfig"
+source "drivers/iio/imu/bmi270/Kconfig"
source "drivers/iio/imu/bmi323/Kconfig"
source "drivers/iio/imu/bno055/Kconfig"
@@ -96,6 +97,20 @@ config KMX61
source "drivers/iio/imu/inv_icm42600/Kconfig"
source "drivers/iio/imu/inv_mpu6050/Kconfig"
+
+config SMI240
+ tristate "Bosch Sensor SMI240 Inertial Measurement Unit"
+ depends on SPI
+ select REGMAP_SPI
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ If you say yes here you get support for SMI240 IMU on SPI with
+ accelerometer and gyroscope.
+
+ This driver can also be built as a module. If so, the module will be
+ called smi240.
+
source "drivers/iio/imu/st_lsm6dsx/Kconfig"
source "drivers/iio/imu/st_lsm9ds0/Kconfig"
diff --git a/drivers/iio/imu/Makefile b/drivers/iio/imu/Makefile
index 7e2d7d5c3b7b..04c77c2c4df8 100644
--- a/drivers/iio/imu/Makefile
+++ b/drivers/iio/imu/Makefile
@@ -15,6 +15,7 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
obj-y += bmi160/
+obj-y += bmi270/
obj-y += bmi323/
obj-y += bno055/
@@ -27,5 +28,7 @@ obj-y += inv_mpu6050/
obj-$(CONFIG_KMX61) += kmx61.o
+obj-$(CONFIG_SMI240) += smi240.o
+
obj-y += st_lsm6dsx/
obj-y += st_lsm9ds0/
diff --git a/drivers/iio/imu/adis.c b/drivers/iio/imu/adis.c
index 99410733c1ca..494171844812 100644
--- a/drivers/iio/imu/adis.c
+++ b/drivers/iio/imu/adis.c
@@ -115,7 +115,7 @@ int __adis_write_reg(struct adis *adis, unsigned int reg, unsigned int value,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(__adis_write_reg, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(__adis_write_reg, "IIO_ADISLIB");
/**
* __adis_read_reg() - read N bytes from register (unlocked version)
@@ -206,7 +206,7 @@ int __adis_read_reg(struct adis *adis, unsigned int reg, unsigned int *val,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(__adis_read_reg, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(__adis_read_reg, "IIO_ADISLIB");
/**
* __adis_update_bits_base() - ADIS Update bits function - Unlocked version
* @adis: The adis device
@@ -231,7 +231,7 @@ int __adis_update_bits_base(struct adis *adis, unsigned int reg, const u32 mask,
return __adis_write_reg(adis, reg, __val, size);
}
-EXPORT_SYMBOL_NS_GPL(__adis_update_bits_base, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(__adis_update_bits_base, "IIO_ADISLIB");
#ifdef CONFIG_DEBUG_FS
@@ -253,7 +253,7 @@ int adis_debugfs_reg_access(struct iio_dev *indio_dev, unsigned int reg,
return adis_write_reg_16(adis, reg, writeval);
}
-EXPORT_SYMBOL_NS(adis_debugfs_reg_access, IIO_ADISLIB);
+EXPORT_SYMBOL_NS(adis_debugfs_reg_access, "IIO_ADISLIB");
#endif
@@ -294,7 +294,7 @@ int __adis_enable_irq(struct adis *adis, bool enable)
return __adis_write_reg_16(adis, adis->data->msc_ctrl_reg, msc);
}
-EXPORT_SYMBOL_NS(__adis_enable_irq, IIO_ADISLIB);
+EXPORT_SYMBOL_NS(__adis_enable_irq, "IIO_ADISLIB");
/**
* __adis_check_status() - Check the device for error conditions (unlocked)
@@ -326,7 +326,7 @@ int __adis_check_status(struct adis *adis)
return -EIO;
}
-EXPORT_SYMBOL_NS_GPL(__adis_check_status, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(__adis_check_status, "IIO_ADISLIB");
/**
* __adis_reset() - Reset the device (unlocked version)
@@ -350,7 +350,7 @@ int __adis_reset(struct adis *adis)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(__adis_reset, IIO_ADIS_LIB);
+EXPORT_SYMBOL_NS_GPL(__adis_reset, "IIO_ADIS_LIB");
static int adis_self_test(struct adis *adis)
{
@@ -441,7 +441,7 @@ int __adis_initial_startup(struct adis *adis)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(__adis_initial_startup, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(__adis_initial_startup, "IIO_ADISLIB");
/**
* adis_single_conversion() - Performs a single sample conversion
@@ -486,7 +486,7 @@ int adis_single_conversion(struct iio_dev *indio_dev,
return IIO_VAL_INT;
}
-EXPORT_SYMBOL_NS_GPL(adis_single_conversion, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(adis_single_conversion, "IIO_ADISLIB");
/**
* adis_init() - Initialize adis device structure
@@ -529,7 +529,7 @@ int adis_init(struct adis *adis, struct iio_dev *indio_dev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(adis_init, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(adis_init, "IIO_ADISLIB");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
diff --git a/drivers/iio/imu/adis16400.c b/drivers/iio/imu/adis16400.c
index 6484ab8aff55..3086dd536203 100644
--- a/drivers/iio/imu/adis16400.c
+++ b/drivers/iio/imu/adis16400.c
@@ -1228,4 +1228,4 @@ module_spi_driver(adis16400_driver);
MODULE_AUTHOR("Manuel Stahl <manuel.stahl@iis.fraunhofer.de>");
MODULE_DESCRIPTION("Analog Devices ADIS16400/5 IMU SPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADISLIB);
+MODULE_IMPORT_NS("IIO_ADISLIB");
diff --git a/drivers/iio/imu/adis16460.c b/drivers/iio/imu/adis16460.c
index eaa38dd6201f..ecf74046fde1 100644
--- a/drivers/iio/imu/adis16460.c
+++ b/drivers/iio/imu/adis16460.c
@@ -418,4 +418,4 @@ module_spi_driver(adis16460_driver);
MODULE_AUTHOR("Dragos Bogdan <dragos.bogdan@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16460 IMU driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_ADISLIB);
+MODULE_IMPORT_NS("IIO_ADISLIB");
diff --git a/drivers/iio/imu/adis16475.c b/drivers/iio/imu/adis16475.c
index 88efe728b61b..df8c6cd91169 100644
--- a/drivers/iio/imu/adis16475.c
+++ b/drivers/iio/imu/adis16475.c
@@ -2107,4 +2107,4 @@ module_spi_driver(adis16475_driver);
MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16475 IMU driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_ADISLIB);
+MODULE_IMPORT_NS("IIO_ADISLIB");
diff --git a/drivers/iio/imu/adis16480.c b/drivers/iio/imu/adis16480.c
index 294181f2fcb3..0a5d13d2240e 100644
--- a/drivers/iio/imu/adis16480.c
+++ b/drivers/iio/imu/adis16480.c
@@ -1794,4 +1794,4 @@ module_spi_driver(adis16480_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Analog Devices ADIS16480 IMU driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ADISLIB);
+MODULE_IMPORT_NS("IIO_ADISLIB");
diff --git a/drivers/iio/imu/adis_buffer.c b/drivers/iio/imu/adis_buffer.c
index b7c1cc04492a..fdfc0538734c 100644
--- a/drivers/iio/imu/adis_buffer.c
+++ b/drivers/iio/imu/adis_buffer.c
@@ -124,7 +124,7 @@ int adis_update_scan_mode(struct iio_dev *indio_dev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(adis_update_scan_mode, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(adis_update_scan_mode, "IIO_ADISLIB");
static int adis_paging_trigger_handler(struct adis *adis)
{
@@ -222,4 +222,4 @@ devm_adis_setup_buffer_and_trigger_with_attrs(struct adis *adis, struct iio_dev
return devm_add_action_or_reset(&adis->spi->dev, adis_buffer_cleanup,
adis);
}
-EXPORT_SYMBOL_NS_GPL(devm_adis_setup_buffer_and_trigger_with_attrs, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(devm_adis_setup_buffer_and_trigger_with_attrs, "IIO_ADISLIB");
diff --git a/drivers/iio/imu/adis_trigger.c b/drivers/iio/imu/adis_trigger.c
index a8740b043cfe..d76e13cbac68 100644
--- a/drivers/iio/imu/adis_trigger.c
+++ b/drivers/iio/imu/adis_trigger.c
@@ -102,5 +102,5 @@ int devm_adis_probe_trigger(struct adis *adis, struct iio_dev *indio_dev)
return devm_iio_trigger_register(&adis->spi->dev, adis->trig);
}
-EXPORT_SYMBOL_NS_GPL(devm_adis_probe_trigger, IIO_ADISLIB);
+EXPORT_SYMBOL_NS_GPL(devm_adis_probe_trigger, "IIO_ADISLIB");
diff --git a/drivers/iio/imu/bmi160/bmi160_core.c b/drivers/iio/imu/bmi160/bmi160_core.c
index 495e8a74ac67..0423ef6f9571 100644
--- a/drivers/iio/imu/bmi160/bmi160_core.c
+++ b/drivers/iio/imu/bmi160/bmi160_core.c
@@ -149,7 +149,7 @@ const struct regmap_config bmi160_regmap_config = {
.reg_bits = 8,
.val_bits = 8,
};
-EXPORT_SYMBOL_NS(bmi160_regmap_config, IIO_BMI160);
+EXPORT_SYMBOL_NS(bmi160_regmap_config, "IIO_BMI160");
struct bmi160_regs {
u8 data; /* LSB byte register for X-axis */
@@ -638,7 +638,7 @@ int bmi160_enable_irq(struct regmap *regmap, bool enable)
BMI160_DRDY_INT_EN, enable_bit,
BMI160_NORMAL_WRITE_USLEEP);
}
-EXPORT_SYMBOL_NS(bmi160_enable_irq, IIO_BMI160);
+EXPORT_SYMBOL_NS(bmi160_enable_irq, "IIO_BMI160");
static int bmi160_get_irq(struct fwnode_handle *fwnode, enum bmi160_int_pin *pin)
{
@@ -690,18 +690,9 @@ static int bmi160_config_device_irq(struct iio_dev *indio_dev, int irq_type,
static int bmi160_setup_irq(struct iio_dev *indio_dev, int irq,
enum bmi160_int_pin pin)
{
- struct irq_data *desc;
- u32 irq_type;
+ u32 irq_type = irq_get_trigger_type(irq);
int ret;
- desc = irq_get_irq_data(irq);
- if (!desc) {
- dev_err(&indio_dev->dev, "Could not find IRQ %d\n", irq);
- return -EINVAL;
- }
-
- irq_type = irqd_get_trigger_type(desc);
-
ret = bmi160_config_device_irq(indio_dev, irq_type, pin);
if (ret)
return ret;
@@ -897,7 +888,7 @@ int bmi160_core_probe(struct device *dev, struct regmap *regmap,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(bmi160_core_probe, IIO_BMI160);
+EXPORT_SYMBOL_NS_GPL(bmi160_core_probe, "IIO_BMI160");
MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
MODULE_DESCRIPTION("Bosch BMI160 driver");
diff --git a/drivers/iio/imu/bmi160/bmi160_i2c.c b/drivers/iio/imu/bmi160/bmi160_i2c.c
index 3aa5d748f9b6..214503fa4af5 100644
--- a/drivers/iio/imu/bmi160/bmi160_i2c.c
+++ b/drivers/iio/imu/bmi160/bmi160_i2c.c
@@ -80,4 +80,4 @@ module_i2c_driver(bmi160_i2c_driver);
MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com>");
MODULE_DESCRIPTION("BMI160 I2C driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_BMI160);
+MODULE_IMPORT_NS("IIO_BMI160");
diff --git a/drivers/iio/imu/bmi160/bmi160_spi.c b/drivers/iio/imu/bmi160/bmi160_spi.c
index 9f40500132f7..8fbaab22db81 100644
--- a/drivers/iio/imu/bmi160/bmi160_spi.c
+++ b/drivers/iio/imu/bmi160/bmi160_spi.c
@@ -68,4 +68,4 @@ module_spi_driver(bmi160_spi_driver);
MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com");
MODULE_DESCRIPTION("Bosch BMI160 SPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_BMI160);
+MODULE_IMPORT_NS("IIO_BMI160");
diff --git a/drivers/iio/imu/bmi270/Kconfig b/drivers/iio/imu/bmi270/Kconfig
new file mode 100644
index 000000000000..6362acc706da
--- /dev/null
+++ b/drivers/iio/imu/bmi270/Kconfig
@@ -0,0 +1,33 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# BMI270 IMU driver
+#
+
+config BMI270
+ tristate
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+
+config BMI270_I2C
+ tristate "Bosch BMI270 I2C driver"
+ depends on I2C
+ select BMI270
+ select REGMAP_I2C
+ help
+ Enable support for the Bosch BMI270 6-Axis IMU connected to I2C
+ interface.
+
+ This driver can also be built as a module. If so, the module will be
+ called bmi270_i2c.
+
+config BMI270_SPI
+ tristate "Bosch BMI270 SPI driver"
+ depends on SPI
+ select BMI270
+ select REGMAP_SPI
+ help
+ Enable support for the Bosch BMI270 6-Axis IMU connected to SPI
+ interface.
+
+ This driver can also be built as a module. If so, the module will be
+ called bmi270_spi.
diff --git a/drivers/iio/imu/bmi270/Makefile b/drivers/iio/imu/bmi270/Makefile
new file mode 100644
index 000000000000..d96c96fc3d83
--- /dev/null
+++ b/drivers/iio/imu/bmi270/Makefile
@@ -0,0 +1,7 @@
+# SPDX-License-Identifier: GPL-2.0
+#
+# Makefile for Bosch BMI270 IMU
+#
+obj-$(CONFIG_BMI270) += bmi270_core.o
+obj-$(CONFIG_BMI270_I2C) += bmi270_i2c.o
+obj-$(CONFIG_BMI270_SPI) += bmi270_spi.o
diff --git a/drivers/iio/imu/bmi270/bmi270.h b/drivers/iio/imu/bmi270/bmi270.h
new file mode 100644
index 000000000000..fdfad5784cc5
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270.h
@@ -0,0 +1,38 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+
+#ifndef BMI270_H_
+#define BMI270_H_
+
+#include <linux/regmap.h>
+#include <linux/iio/iio.h>
+
+struct device;
+struct bmi270_data {
+ struct device *dev;
+ struct regmap *regmap;
+ const struct bmi270_chip_info *chip_info;
+
+ /*
+ * Where IIO_DMA_MINALIGN may be larger than 8 bytes, align to
+ * that to ensure a DMA safe buffer.
+ */
+ struct {
+ __le16 channels[6];
+ aligned_s64 timestamp;
+ } data __aligned(IIO_DMA_MINALIGN);
+};
+
+struct bmi270_chip_info {
+ const char *name;
+ int chip_id;
+ const char *fw_name;
+};
+
+extern const struct regmap_config bmi270_regmap_config;
+extern const struct bmi270_chip_info bmi260_chip_info;
+extern const struct bmi270_chip_info bmi270_chip_info;
+
+int bmi270_core_probe(struct device *dev, struct regmap *regmap,
+ const struct bmi270_chip_info *chip_info);
+
+#endif /* BMI270_H_ */
diff --git a/drivers/iio/imu/bmi270/bmi270_core.c b/drivers/iio/imu/bmi270/bmi270_core.c
new file mode 100644
index 000000000000..7fec52e0b486
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270_core.c
@@ -0,0 +1,734 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <linux/bitfield.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+
+#include <linux/iio/iio.h>
+#include <linux/iio/sysfs.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
+
+#include "bmi270.h"
+
+#define BMI270_CHIP_ID_REG 0x00
+
+/* Checked to prevent sending incompatible firmware to BMI160 devices */
+#define BMI160_CHIP_ID_VAL 0xD1
+
+#define BMI260_CHIP_ID_VAL 0x27
+#define BMI270_CHIP_ID_VAL 0x24
+#define BMI270_CHIP_ID_MSK GENMASK(7, 0)
+
+#define BMI270_ACCEL_X_REG 0x0c
+#define BMI270_ANG_VEL_X_REG 0x12
+
+#define BMI270_INTERNAL_STATUS_REG 0x21
+#define BMI270_INTERNAL_STATUS_MSG_MSK GENMASK(3, 0)
+#define BMI270_INTERNAL_STATUS_MSG_INIT_OK 0x01
+
+#define BMI270_INTERNAL_STATUS_AXES_REMAP_ERR_MSK BIT(5)
+#define BMI270_INTERNAL_STATUS_ODR_50HZ_ERR_MSK BIT(6)
+
+#define BMI270_ACC_CONF_REG 0x40
+#define BMI270_ACC_CONF_ODR_MSK GENMASK(3, 0)
+#define BMI270_ACC_CONF_ODR_100HZ 0x08
+#define BMI270_ACC_CONF_BWP_MSK GENMASK(6, 4)
+#define BMI270_ACC_CONF_BWP_NORMAL_MODE 0x02
+#define BMI270_ACC_CONF_FILTER_PERF_MSK BIT(7)
+
+#define BMI270_ACC_CONF_RANGE_REG 0x41
+#define BMI270_ACC_CONF_RANGE_MSK GENMASK(1, 0)
+
+#define BMI270_GYR_CONF_REG 0x42
+#define BMI270_GYR_CONF_ODR_MSK GENMASK(3, 0)
+#define BMI270_GYR_CONF_ODR_200HZ 0x09
+#define BMI270_GYR_CONF_BWP_MSK GENMASK(5, 4)
+#define BMI270_GYR_CONF_BWP_NORMAL_MODE 0x02
+#define BMI270_GYR_CONF_NOISE_PERF_MSK BIT(6)
+#define BMI270_GYR_CONF_FILTER_PERF_MSK BIT(7)
+
+#define BMI270_GYR_CONF_RANGE_REG 0x43
+#define BMI270_GYR_CONF_RANGE_MSK GENMASK(2, 0)
+
+#define BMI270_INIT_CTRL_REG 0x59
+#define BMI270_INIT_CTRL_LOAD_DONE_MSK BIT(0)
+
+#define BMI270_INIT_DATA_REG 0x5e
+
+#define BMI270_PWR_CONF_REG 0x7c
+#define BMI270_PWR_CONF_ADV_PWR_SAVE_MSK BIT(0)
+#define BMI270_PWR_CONF_FIFO_WKUP_MSK BIT(1)
+#define BMI270_PWR_CONF_FUP_EN_MSK BIT(2)
+
+#define BMI270_PWR_CTRL_REG 0x7d
+#define BMI270_PWR_CTRL_AUX_EN_MSK BIT(0)
+#define BMI270_PWR_CTRL_GYR_EN_MSK BIT(1)
+#define BMI270_PWR_CTRL_ACCEL_EN_MSK BIT(2)
+#define BMI270_PWR_CTRL_TEMP_EN_MSK BIT(3)
+
+#define BMI260_INIT_DATA_FILE "bmi260-init-data.fw"
+#define BMI270_INIT_DATA_FILE "bmi270-init-data.fw"
+
+enum bmi270_scan {
+ BMI270_SCAN_ACCEL_X,
+ BMI270_SCAN_ACCEL_Y,
+ BMI270_SCAN_ACCEL_Z,
+ BMI270_SCAN_GYRO_X,
+ BMI270_SCAN_GYRO_Y,
+ BMI270_SCAN_GYRO_Z,
+ BMI270_SCAN_TIMESTAMP,
+};
+
+static const unsigned long bmi270_avail_scan_masks[] = {
+ (BIT(BMI270_SCAN_ACCEL_X) |
+ BIT(BMI270_SCAN_ACCEL_Y) |
+ BIT(BMI270_SCAN_ACCEL_Z) |
+ BIT(BMI270_SCAN_GYRO_X) |
+ BIT(BMI270_SCAN_GYRO_Y) |
+ BIT(BMI270_SCAN_GYRO_Z)),
+ 0
+};
+
+const struct bmi270_chip_info bmi260_chip_info = {
+ .name = "bmi260",
+ .chip_id = BMI260_CHIP_ID_VAL,
+ .fw_name = BMI260_INIT_DATA_FILE,
+};
+EXPORT_SYMBOL_NS_GPL(bmi260_chip_info, "IIO_BMI270");
+
+const struct bmi270_chip_info bmi270_chip_info = {
+ .name = "bmi270",
+ .chip_id = BMI270_CHIP_ID_VAL,
+ .fw_name = BMI270_INIT_DATA_FILE,
+};
+EXPORT_SYMBOL_NS_GPL(bmi270_chip_info, "IIO_BMI270");
+
+enum bmi270_sensor_type {
+ BMI270_ACCEL = 0,
+ BMI270_GYRO,
+};
+
+struct bmi270_scale {
+ int scale;
+ int uscale;
+};
+
+struct bmi270_odr {
+ int odr;
+ int uodr;
+};
+
+static const struct bmi270_scale bmi270_accel_scale[] = {
+ { 0, 598 },
+ { 0, 1197 },
+ { 0, 2394 },
+ { 0, 4788 },
+};
+
+static const struct bmi270_scale bmi270_gyro_scale[] = {
+ { 0, 1065 },
+ { 0, 532 },
+ { 0, 266 },
+ { 0, 133 },
+ { 0, 66 },
+};
+
+struct bmi270_scale_item {
+ const struct bmi270_scale *tbl;
+ int num;
+};
+
+static const struct bmi270_scale_item bmi270_scale_table[] = {
+ [BMI270_ACCEL] = {
+ .tbl = bmi270_accel_scale,
+ .num = ARRAY_SIZE(bmi270_accel_scale),
+ },
+ [BMI270_GYRO] = {
+ .tbl = bmi270_gyro_scale,
+ .num = ARRAY_SIZE(bmi270_gyro_scale),
+ },
+};
+
+static const struct bmi270_odr bmi270_accel_odr[] = {
+ { 0, 781250 },
+ { 1, 562500 },
+ { 3, 125000 },
+ { 6, 250000 },
+ { 12, 500000 },
+ { 25, 0 },
+ { 50, 0 },
+ { 100, 0 },
+ { 200, 0 },
+ { 400, 0 },
+ { 800, 0 },
+ { 1600, 0 },
+};
+
+static const u8 bmi270_accel_odr_vals[] = {
+ 0x01,
+ 0x02,
+ 0x03,
+ 0x04,
+ 0x05,
+ 0x06,
+ 0x07,
+ 0x08,
+ 0x09,
+ 0x0A,
+ 0x0B,
+ 0x0C,
+};
+
+static const struct bmi270_odr bmi270_gyro_odr[] = {
+ { 25, 0 },
+ { 50, 0 },
+ { 100, 0 },
+ { 200, 0 },
+ { 400, 0 },
+ { 800, 0 },
+ { 1600, 0 },
+ { 3200, 0 },
+};
+
+static const u8 bmi270_gyro_odr_vals[] = {
+ 0x06,
+ 0x07,
+ 0x08,
+ 0x09,
+ 0x0A,
+ 0x0B,
+ 0x0C,
+ 0x0D,
+};
+
+struct bmi270_odr_item {
+ const struct bmi270_odr *tbl;
+ const u8 *vals;
+ int num;
+};
+
+static const struct bmi270_odr_item bmi270_odr_table[] = {
+ [BMI270_ACCEL] = {
+ .tbl = bmi270_accel_odr,
+ .vals = bmi270_accel_odr_vals,
+ .num = ARRAY_SIZE(bmi270_accel_odr),
+ },
+ [BMI270_GYRO] = {
+ .tbl = bmi270_gyro_odr,
+ .vals = bmi270_gyro_odr_vals,
+ .num = ARRAY_SIZE(bmi270_gyro_odr),
+ },
+};
+
+static int bmi270_set_scale(struct bmi270_data *data, int chan_type, int uscale)
+{
+ int i;
+ int reg, mask;
+ struct bmi270_scale_item bmi270_scale_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ reg = BMI270_ACC_CONF_RANGE_REG;
+ mask = BMI270_ACC_CONF_RANGE_MSK;
+ bmi270_scale_item = bmi270_scale_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ reg = BMI270_GYR_CONF_RANGE_REG;
+ mask = BMI270_GYR_CONF_RANGE_MSK;
+ bmi270_scale_item = bmi270_scale_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < bmi270_scale_item.num; i++) {
+ if (bmi270_scale_item.tbl[i].uscale != uscale)
+ continue;
+
+ return regmap_update_bits(data->regmap, reg, mask, i);
+ }
+
+ return -EINVAL;
+}
+
+static int bmi270_get_scale(struct bmi270_data *bmi270_device, int chan_type,
+ int *uscale)
+{
+ int ret;
+ unsigned int val;
+ struct bmi270_scale_item bmi270_scale_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ ret = regmap_read(bmi270_device->regmap,
+ BMI270_ACC_CONF_RANGE_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_ACC_CONF_RANGE_MSK, val);
+ bmi270_scale_item = bmi270_scale_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ ret = regmap_read(bmi270_device->regmap,
+ BMI270_GYR_CONF_RANGE_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_GYR_CONF_RANGE_MSK, val);
+ bmi270_scale_item = bmi270_scale_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (val >= bmi270_scale_item.num)
+ return -EINVAL;
+
+ *uscale = bmi270_scale_item.tbl[val].uscale;
+ return 0;
+}
+
+static int bmi270_set_odr(struct bmi270_data *data, int chan_type, int odr,
+ int uodr)
+{
+ int i;
+ int reg, mask;
+ struct bmi270_odr_item bmi270_odr_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ reg = BMI270_ACC_CONF_REG;
+ mask = BMI270_ACC_CONF_ODR_MSK;
+ bmi270_odr_item = bmi270_odr_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ reg = BMI270_GYR_CONF_REG;
+ mask = BMI270_GYR_CONF_ODR_MSK;
+ bmi270_odr_item = bmi270_odr_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < bmi270_odr_item.num; i++) {
+ if (bmi270_odr_item.tbl[i].odr != odr ||
+ bmi270_odr_item.tbl[i].uodr != uodr)
+ continue;
+
+ return regmap_update_bits(data->regmap, reg, mask,
+ bmi270_odr_item.vals[i]);
+ }
+
+ return -EINVAL;
+}
+
+static int bmi270_get_odr(struct bmi270_data *data, int chan_type, int *odr,
+ int *uodr)
+{
+ int i, val, ret;
+ struct bmi270_odr_item bmi270_odr_item;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ ret = regmap_read(data->regmap, BMI270_ACC_CONF_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_ACC_CONF_ODR_MSK, val);
+ bmi270_odr_item = bmi270_odr_table[BMI270_ACCEL];
+ break;
+ case IIO_ANGL_VEL:
+ ret = regmap_read(data->regmap, BMI270_GYR_CONF_REG, &val);
+ if (ret)
+ return ret;
+
+ val = FIELD_GET(BMI270_GYR_CONF_ODR_MSK, val);
+ bmi270_odr_item = bmi270_odr_table[BMI270_GYRO];
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ for (i = 0; i < bmi270_odr_item.num; i++) {
+ if (val != bmi270_odr_item.vals[i])
+ continue;
+
+ *odr = bmi270_odr_item.tbl[i].odr;
+ *uodr = bmi270_odr_item.tbl[i].uodr;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static irqreturn_t bmi270_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct bmi270_data *bmi270_device = iio_priv(indio_dev);
+ int ret;
+
+ ret = regmap_bulk_read(bmi270_device->regmap, BMI270_ACCEL_X_REG,
+ &bmi270_device->data.channels,
+ sizeof(bmi270_device->data.channels));
+
+ if (ret)
+ goto done;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &bmi270_device->data,
+ pf->timestamp);
+done:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int bmi270_get_data(struct bmi270_data *bmi270_device,
+ int chan_type, int axis, int *val)
+{
+ __le16 sample;
+ int reg;
+ int ret;
+
+ switch (chan_type) {
+ case IIO_ACCEL:
+ reg = BMI270_ACCEL_X_REG + (axis - IIO_MOD_X) * 2;
+ break;
+ case IIO_ANGL_VEL:
+ reg = BMI270_ANG_VEL_X_REG + (axis - IIO_MOD_X) * 2;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_bulk_read(bmi270_device->regmap, reg, &sample, sizeof(sample));
+ if (ret)
+ return ret;
+
+ *val = sign_extend32(le16_to_cpu(sample), 15);
+
+ return 0;
+}
+
+static int bmi270_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int *val, int *val2, long mask)
+{
+ int ret;
+ struct bmi270_data *bmi270_device = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = bmi270_get_data(bmi270_device, chan->type, chan->channel2, val);
+ if (ret)
+ return ret;
+
+ return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SCALE:
+ *val = 0;
+ ret = bmi270_get_scale(bmi270_device, chan->type, val2);
+ return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ ret = bmi270_get_odr(bmi270_device, chan->type, val, val2);
+ return ret ? ret : IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bmi270_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct bmi270_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ return bmi270_set_scale(data, chan->type, val2);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ return bmi270_set_odr(data, chan->type, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int bmi270_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_SCALE:
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ *vals = (const int *)bmi270_gyro_scale;
+ *length = ARRAY_SIZE(bmi270_gyro_scale) * 2;
+ return IIO_AVAIL_LIST;
+ case IIO_ACCEL:
+ *vals = (const int *)bmi270_accel_scale;
+ *length = ARRAY_SIZE(bmi270_accel_scale) * 2;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ switch (chan->type) {
+ case IIO_ANGL_VEL:
+ *vals = (const int *)bmi270_gyro_odr;
+ *length = ARRAY_SIZE(bmi270_gyro_odr) * 2;
+ return IIO_AVAIL_LIST;
+ case IIO_ACCEL:
+ *vals = (const int *)bmi270_accel_odr;
+ *length = ARRAY_SIZE(bmi270_accel_odr) * 2;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct iio_info bmi270_info = {
+ .read_raw = bmi270_read_raw,
+ .write_raw = bmi270_write_raw,
+ .read_avail = bmi270_read_avail,
+};
+
+#define BMI270_ACCEL_CHANNEL(_axis) { \
+ .type = IIO_ACCEL, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = BMI270_SCAN_ACCEL_##_axis, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
+}
+
+#define BMI270_ANG_VEL_CHANNEL(_axis) { \
+ .type = IIO_ANGL_VEL, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_SAMP_FREQ), \
+ .scan_index = BMI270_SCAN_GYRO_##_axis, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_LE, \
+ }, \
+}
+
+static const struct iio_chan_spec bmi270_channels[] = {
+ BMI270_ACCEL_CHANNEL(X),
+ BMI270_ACCEL_CHANNEL(Y),
+ BMI270_ACCEL_CHANNEL(Z),
+ BMI270_ANG_VEL_CHANNEL(X),
+ BMI270_ANG_VEL_CHANNEL(Y),
+ BMI270_ANG_VEL_CHANNEL(Z),
+ IIO_CHAN_SOFT_TIMESTAMP(BMI270_SCAN_TIMESTAMP),
+};
+
+static int bmi270_validate_chip_id(struct bmi270_data *bmi270_device)
+{
+ int chip_id;
+ int ret;
+ struct device *dev = bmi270_device->dev;
+ struct regmap *regmap = bmi270_device->regmap;
+
+ ret = regmap_read(regmap, BMI270_CHIP_ID_REG, &chip_id);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read chip id");
+
+ /*
+ * Some manufacturers use "BMI0160" for both the BMI160 and
+ * BMI260. If the device is actually a BMI160, the bmi160
+ * driver should handle it and this driver should not.
+ */
+ if (chip_id == BMI160_CHIP_ID_VAL)
+ return -ENODEV;
+
+ if (chip_id != bmi270_device->chip_info->chip_id)
+ dev_info(dev, "Unexpected chip id 0x%x", chip_id);
+
+ if (chip_id == bmi260_chip_info.chip_id)
+ bmi270_device->chip_info = &bmi260_chip_info;
+ else if (chip_id == bmi270_chip_info.chip_id)
+ bmi270_device->chip_info = &bmi270_chip_info;
+
+ return 0;
+}
+
+static int bmi270_write_calibration_data(struct bmi270_data *bmi270_device)
+{
+ int ret;
+ int status = 0;
+ const struct firmware *init_data;
+ struct device *dev = bmi270_device->dev;
+ struct regmap *regmap = bmi270_device->regmap;
+
+ ret = regmap_clear_bits(regmap, BMI270_PWR_CONF_REG,
+ BMI270_PWR_CONF_ADV_PWR_SAVE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to write power configuration");
+
+ /*
+ * After disabling advanced power save, all registers are accessible
+ * after a 450us delay. This delay is specified in table A of the
+ * datasheet.
+ */
+ usleep_range(450, 1000);
+
+ ret = regmap_clear_bits(regmap, BMI270_INIT_CTRL_REG,
+ BMI270_INIT_CTRL_LOAD_DONE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to prepare device to load init data");
+
+ ret = request_firmware(&init_data,
+ bmi270_device->chip_info->fw_name, dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to load init data file");
+
+ ret = regmap_bulk_write(regmap, BMI270_INIT_DATA_REG,
+ init_data->data, init_data->size);
+ release_firmware(init_data);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to write init data");
+
+ ret = regmap_set_bits(regmap, BMI270_INIT_CTRL_REG,
+ BMI270_INIT_CTRL_LOAD_DONE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to stop device initialization");
+
+ /*
+ * Wait at least 140ms for the device to complete configuration.
+ * This delay is specified in table C of the datasheet.
+ */
+ usleep_range(140000, 160000);
+
+ ret = regmap_read(regmap, BMI270_INTERNAL_STATUS_REG, &status);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read internal status");
+
+ if (status != BMI270_INTERNAL_STATUS_MSG_INIT_OK)
+ return dev_err_probe(dev, -ENODEV, "Device failed to initialize");
+
+ return 0;
+}
+
+static int bmi270_configure_imu(struct bmi270_data *bmi270_device)
+{
+ int ret;
+ struct device *dev = bmi270_device->dev;
+ struct regmap *regmap = bmi270_device->regmap;
+
+ ret = regmap_set_bits(regmap, BMI270_PWR_CTRL_REG,
+ BMI270_PWR_CTRL_AUX_EN_MSK |
+ BMI270_PWR_CTRL_GYR_EN_MSK |
+ BMI270_PWR_CTRL_ACCEL_EN_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable accelerometer and gyroscope");
+
+ ret = regmap_set_bits(regmap, BMI270_ACC_CONF_REG,
+ FIELD_PREP(BMI270_ACC_CONF_ODR_MSK,
+ BMI270_ACC_CONF_ODR_100HZ) |
+ FIELD_PREP(BMI270_ACC_CONF_BWP_MSK,
+ BMI270_ACC_CONF_BWP_NORMAL_MODE) |
+ BMI270_PWR_CONF_ADV_PWR_SAVE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to configure accelerometer");
+
+ ret = regmap_set_bits(regmap, BMI270_GYR_CONF_REG,
+ FIELD_PREP(BMI270_GYR_CONF_ODR_MSK,
+ BMI270_GYR_CONF_ODR_200HZ) |
+ FIELD_PREP(BMI270_GYR_CONF_BWP_MSK,
+ BMI270_GYR_CONF_BWP_NORMAL_MODE) |
+ BMI270_PWR_CONF_ADV_PWR_SAVE_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to configure gyroscope");
+
+ /* Enable FIFO_WKUP, Disable ADV_PWR_SAVE and FUP_EN */
+ ret = regmap_write(regmap, BMI270_PWR_CONF_REG,
+ BMI270_PWR_CONF_FIFO_WKUP_MSK);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to set power configuration");
+
+ return 0;
+}
+
+static int bmi270_chip_init(struct bmi270_data *bmi270_device)
+{
+ int ret;
+
+ ret = bmi270_validate_chip_id(bmi270_device);
+ if (ret)
+ return ret;
+
+ ret = bmi270_write_calibration_data(bmi270_device);
+ if (ret)
+ return ret;
+
+ return bmi270_configure_imu(bmi270_device);
+}
+
+int bmi270_core_probe(struct device *dev, struct regmap *regmap,
+ const struct bmi270_chip_info *chip_info)
+{
+ int ret;
+ struct bmi270_data *bmi270_device;
+ struct iio_dev *indio_dev;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*bmi270_device));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ bmi270_device = iio_priv(indio_dev);
+ bmi270_device->dev = dev;
+ bmi270_device->regmap = regmap;
+ bmi270_device->chip_info = chip_info;
+
+ ret = bmi270_chip_init(bmi270_device);
+ if (ret)
+ return ret;
+
+ indio_dev->channels = bmi270_channels;
+ indio_dev->num_channels = ARRAY_SIZE(bmi270_channels);
+ indio_dev->name = chip_info->name;
+ indio_dev->available_scan_masks = bmi270_avail_scan_masks;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &bmi270_info;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ bmi270_trigger_handler, NULL);
+ if (ret)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+EXPORT_SYMBOL_NS_GPL(bmi270_core_probe, "IIO_BMI270");
+
+MODULE_AUTHOR("Alex Lanzano");
+MODULE_DESCRIPTION("BMI270 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/bmi270/bmi270_i2c.c b/drivers/iio/imu/bmi270/bmi270_i2c.c
new file mode 100644
index 000000000000..44699ab58909
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270_i2c.c
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/regmap.h>
+
+#include "bmi270.h"
+
+static const struct regmap_config bmi270_i2c_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int bmi270_i2c_probe(struct i2c_client *client)
+{
+ struct regmap *regmap;
+ struct device *dev = &client->dev;
+ const struct bmi270_chip_info *chip_info;
+
+ chip_info = i2c_get_match_data(client);
+ if (!chip_info)
+ return -ENODEV;
+
+ regmap = devm_regmap_init_i2c(client, &bmi270_i2c_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init i2c regmap");
+
+ return bmi270_core_probe(dev, regmap, chip_info);
+}
+
+static const struct i2c_device_id bmi270_i2c_id[] = {
+ { "bmi260", (kernel_ulong_t)&bmi260_chip_info },
+ { "bmi270", (kernel_ulong_t)&bmi270_chip_info },
+ { }
+};
+
+static const struct acpi_device_id bmi270_acpi_match[] = {
+ /* GPD Win Mini, Aya Neo AIR Pro, OXP Mini Pro, etc. */
+ { "BMI0160", (kernel_ulong_t)&bmi260_chip_info },
+ { }
+};
+
+static const struct of_device_id bmi270_of_match[] = {
+ { .compatible = "bosch,bmi260", .data = &bmi260_chip_info },
+ { .compatible = "bosch,bmi270", .data = &bmi270_chip_info },
+ { }
+};
+
+static struct i2c_driver bmi270_i2c_driver = {
+ .driver = {
+ .name = "bmi270_i2c",
+ .acpi_match_table = bmi270_acpi_match,
+ .of_match_table = bmi270_of_match,
+ },
+ .probe = bmi270_i2c_probe,
+ .id_table = bmi270_i2c_id,
+};
+module_i2c_driver(bmi270_i2c_driver);
+
+MODULE_AUTHOR("Alex Lanzano");
+MODULE_DESCRIPTION("BMI270 driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_BMI270");
diff --git a/drivers/iio/imu/bmi270/bmi270_spi.c b/drivers/iio/imu/bmi270/bmi270_spi.c
new file mode 100644
index 000000000000..88a77aba5e4f
--- /dev/null
+++ b/drivers/iio/imu/bmi270/bmi270_spi.c
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+
+#include <linux/iio/iio.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+
+#include "bmi270.h"
+
+/*
+ * The following two functions are taken from the BMI323 spi driver code.
+ * In section 6.4 of the BMI270 data it specifies that after a read
+ * operation the first data byte from the device is a dummy byte
+ */
+static int bmi270_regmap_spi_read(void *spi, const void *reg_buf,
+ size_t reg_size, void *val_buf,
+ size_t val_size)
+{
+ return spi_write_then_read(spi, reg_buf, reg_size, val_buf, val_size);
+}
+
+static int bmi270_regmap_spi_write(void *spi, const void *data,
+ size_t count)
+{
+ u8 *data_buff = (u8 *)data;
+
+ /*
+ * Remove the extra pad byte since its only needed for the read
+ * operation
+ */
+ data_buff[1] = data_buff[0];
+ return spi_write_then_read(spi, data_buff + 1, count - 1, NULL, 0);
+}
+
+static const struct regmap_bus bmi270_regmap_bus = {
+ .read = bmi270_regmap_spi_read,
+ .write = bmi270_regmap_spi_write,
+};
+
+static const struct regmap_config bmi270_spi_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .pad_bits = 8,
+ .read_flag_mask = BIT(7),
+};
+
+static int bmi270_spi_probe(struct spi_device *spi)
+{
+ struct regmap *regmap;
+ struct device *dev = &spi->dev;
+ const struct bmi270_chip_info *chip_info;
+
+ chip_info = spi_get_device_match_data(spi);
+ if (!chip_info)
+ return -ENODEV;
+
+ regmap = devm_regmap_init(dev, &bmi270_regmap_bus, dev,
+ &bmi270_spi_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to init i2c regmap");
+
+ return bmi270_core_probe(dev, regmap, chip_info);
+}
+
+static const struct spi_device_id bmi270_spi_id[] = {
+ { "bmi260", (kernel_ulong_t)&bmi260_chip_info },
+ { "bmi270", (kernel_ulong_t)&bmi270_chip_info },
+ { }
+};
+
+static const struct of_device_id bmi270_of_match[] = {
+ { .compatible = "bosch,bmi260", .data = &bmi260_chip_info },
+ { .compatible = "bosch,bmi270", .data = &bmi270_chip_info },
+ { }
+};
+
+static struct spi_driver bmi270_spi_driver = {
+ .driver = {
+ .name = "bmi270",
+ .of_match_table = bmi270_of_match,
+ },
+ .probe = bmi270_spi_probe,
+ .id_table = bmi270_spi_id,
+};
+module_spi_driver(bmi270_spi_driver);
+
+MODULE_AUTHOR("Alex Lanzano");
+MODULE_DESCRIPTION("BMI270 driver");
+MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("IIO_BMI270");
diff --git a/drivers/iio/imu/bmi323/bmi323.h b/drivers/iio/imu/bmi323/bmi323.h
index 209bccb1f335..b4cfe92600a4 100644
--- a/drivers/iio/imu/bmi323/bmi323.h
+++ b/drivers/iio/imu/bmi323/bmi323.h
@@ -141,7 +141,6 @@
#define BMI323_STEP_SC1_REG 0x10
#define BMI323_STEP_SC1_WTRMRK_MSK GENMASK(9, 0)
#define BMI323_STEP_SC1_RST_CNT_MSK BIT(10)
-#define BMI323_STEP_SC1_REG 0x10
#define BMI323_STEP_LEN 2
/* Tap gesture config registers */
diff --git a/drivers/iio/imu/bmi323/bmi323_core.c b/drivers/iio/imu/bmi323/bmi323_core.c
index e1f3b0d778be..f7d7f4442e65 100644
--- a/drivers/iio/imu/bmi323/bmi323_core.c
+++ b/drivers/iio/imu/bmi323/bmi323_core.c
@@ -467,7 +467,7 @@ static int bmi323_feature_engine_events(struct bmi323_data *data,
BMI323_FEAT_IO_STATUS_MSK);
}
-static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state)
+static int bmi323_step_wtrmrk_en(struct bmi323_data *data, bool state)
{
enum bmi323_irq_pin step_irq;
int ret;
@@ -484,7 +484,7 @@ static int bmi323_step_wtrmrk_en(struct bmi323_data *data, int state)
ret = bmi323_update_ext_reg(data, BMI323_STEP_SC1_REG,
BMI323_STEP_SC1_WTRMRK_MSK,
FIELD_PREP(BMI323_STEP_SC1_WTRMRK_MSK,
- state ? 1 : 0));
+ state));
if (ret)
return ret;
@@ -506,7 +506,7 @@ static int bmi323_motion_config_reg(enum iio_event_direction dir)
}
static int bmi323_motion_event_en(struct bmi323_data *data,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
unsigned int state_value = state ? BMI323_FEAT_XYZ_MSK : 0;
int config, ret, msk, raw, field_value;
@@ -570,7 +570,7 @@ static int bmi323_motion_event_en(struct bmi323_data *data,
}
static int bmi323_tap_event_en(struct bmi323_data *data,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
enum bmi323_irq_pin tap_irq;
int ret, tap_enabled;
@@ -785,7 +785,7 @@ static const struct attribute_group bmi323_event_attribute_group = {
static int bmi323_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct bmi323_data *data = iio_priv(indio_dev);
@@ -1881,7 +1881,6 @@ static int bmi323_trigger_probe(struct bmi323_data *data,
struct fwnode_handle *fwnode;
enum bmi323_irq_pin irq_pin;
int ret, irq, irq_type;
- struct irq_data *desc;
fwnode = dev_fwnode(data->dev);
if (!fwnode)
@@ -1898,12 +1897,7 @@ static int bmi323_trigger_probe(struct bmi323_data *data,
irq_pin = BMI323_IRQ_INT2;
}
- desc = irq_get_irq_data(irq);
- if (!desc)
- return dev_err_probe(data->dev, -EINVAL,
- "Could not find IRQ %d\n", irq);
-
- irq_type = irqd_get_trigger_type(desc);
+ irq_type = irq_get_trigger_type(irq);
switch (irq_type) {
case IRQF_TRIGGER_RISING:
latch = false;
@@ -2170,7 +2164,7 @@ int bmi323_core_probe(struct device *dev)
return bmi323_fifo_disable(data);
}
-EXPORT_SYMBOL_NS_GPL(bmi323_core_probe, IIO_BMI323);
+EXPORT_SYMBOL_NS_GPL(bmi323_core_probe, "IIO_BMI323");
static int bmi323_core_runtime_suspend(struct device *dev)
{
@@ -2298,7 +2292,7 @@ const struct dev_pm_ops bmi323_core_pm_ops = {
RUNTIME_PM_OPS(bmi323_core_runtime_suspend,
bmi323_core_runtime_resume, NULL)
};
-EXPORT_SYMBOL_NS_GPL(bmi323_core_pm_ops, IIO_BMI323);
+EXPORT_SYMBOL_NS_GPL(bmi323_core_pm_ops, "IIO_BMI323");
MODULE_DESCRIPTION("Bosch BMI323 IMU driver");
MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>");
diff --git a/drivers/iio/imu/bmi323/bmi323_i2c.c b/drivers/iio/imu/bmi323/bmi323_i2c.c
index 0ba5d69d8329..8457fe304db8 100644
--- a/drivers/iio/imu/bmi323/bmi323_i2c.c
+++ b/drivers/iio/imu/bmi323/bmi323_i2c.c
@@ -140,4 +140,4 @@ module_i2c_driver(bmi323_i2c_driver);
MODULE_DESCRIPTION("Bosch BMI323 IMU driver");
MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_BMI323);
+MODULE_IMPORT_NS("IIO_BMI323");
diff --git a/drivers/iio/imu/bmi323/bmi323_spi.c b/drivers/iio/imu/bmi323/bmi323_spi.c
index 9de3ade78d71..fd56ab620750 100644
--- a/drivers/iio/imu/bmi323/bmi323_spi.c
+++ b/drivers/iio/imu/bmi323/bmi323_spi.c
@@ -90,4 +90,4 @@ module_spi_driver(bmi323_spi_driver);
MODULE_DESCRIPTION("Bosch BMI323 IMU driver");
MODULE_AUTHOR("Jagath Jog J <jagathjog1996@gmail.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_BMI323);
+MODULE_IMPORT_NS("IIO_BMI323");
diff --git a/drivers/iio/imu/bno055/bno055.c b/drivers/iio/imu/bno055/bno055.c
index ea6519b22b2f..0728d38260a1 100644
--- a/drivers/iio/imu/bno055/bno055.c
+++ b/drivers/iio/imu/bno055/bno055.c
@@ -292,7 +292,7 @@ const struct regmap_config bno055_regmap_config = {
.readable_reg = bno055_regmap_readable,
.cache_type = REGCACHE_RBTREE,
};
-EXPORT_SYMBOL_NS_GPL(bno055_regmap_config, IIO_BNO055);
+EXPORT_SYMBOL_NS_GPL(bno055_regmap_config, "IIO_BNO055");
/* must be called in configuration mode */
static int bno055_calibration_load(struct bno055_priv *priv, const u8 *data, int len)
@@ -1678,7 +1678,7 @@ int bno055_probe(struct device *dev, struct regmap *regmap,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(bno055_probe, IIO_BNO055);
+EXPORT_SYMBOL_NS_GPL(bno055_probe, "IIO_BNO055");
MODULE_AUTHOR("Andrea Merello <andrea.merello@iit.it>");
MODULE_DESCRIPTION("Bosch BNO055 driver");
diff --git a/drivers/iio/imu/bno055/bno055_i2c.c b/drivers/iio/imu/bno055/bno055_i2c.c
index cf3dd62a83ba..f49d0905ee33 100644
--- a/drivers/iio/imu/bno055/bno055_i2c.c
+++ b/drivers/iio/imu/bno055/bno055_i2c.c
@@ -53,5 +53,5 @@ module_i2c_driver(bno055_driver);
MODULE_AUTHOR("Andrea Merello");
MODULE_DESCRIPTION("Bosch BNO055 I2C interface");
-MODULE_IMPORT_NS(IIO_BNO055);
+MODULE_IMPORT_NS("IIO_BNO055");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/bno055/bno055_ser_core.c b/drivers/iio/imu/bno055/bno055_ser_core.c
index da7873bfd348..48669dabb37b 100644
--- a/drivers/iio/imu/bno055/bno055_ser_core.c
+++ b/drivers/iio/imu/bno055/bno055_ser_core.c
@@ -556,5 +556,5 @@ module_serdev_device_driver(bno055_ser_driver);
MODULE_AUTHOR("Andrea Merello <andrea.merello@iit.it>");
MODULE_DESCRIPTION("Bosch BNO055 serdev interface");
-MODULE_IMPORT_NS(IIO_BNO055);
+MODULE_IMPORT_NS("IIO_BNO055");
MODULE_LICENSE("GPL");
diff --git a/drivers/iio/imu/fxos8700_core.c b/drivers/iio/imu/fxos8700_core.c
index 6d189c4b9ff9..281ebfd9c15a 100644
--- a/drivers/iio/imu/fxos8700_core.c
+++ b/drivers/iio/imu/fxos8700_core.c
@@ -8,7 +8,6 @@
*/
#include <linux/module.h>
#include <linux/regmap.h>
-#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/bitfield.h>
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
index 56ac19814250..7968aa27f9fd 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_accel.c
@@ -200,7 +200,6 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
{
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
struct inv_icm42600_sensor_state *accel_st = iio_priv(indio_dev);
- struct inv_sensors_timestamp *ts = &accel_st->ts;
struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
unsigned int fifo_en = 0;
unsigned int sleep_temp = 0;
@@ -229,7 +228,6 @@ static int inv_icm42600_accel_update_scan_mode(struct iio_dev *indio_dev,
}
/* update data FIFO write */
- inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
out_unlock:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
index c3924cc6190e..561d245c1d64 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_core.c
@@ -85,7 +85,7 @@ const struct regmap_config inv_icm42600_regmap_config = {
.rd_noinc_table = inv_icm42600_regmap_rd_noinc_accesses,
.cache_type = REGCACHE_RBTREE,
};
-EXPORT_SYMBOL_NS_GPL(inv_icm42600_regmap_config, IIO_ICM42600);
+EXPORT_SYMBOL_NS_GPL(inv_icm42600_regmap_config, "IIO_ICM42600");
struct inv_icm42600_hw {
uint8_t whoami;
@@ -673,7 +673,6 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
{
struct device *dev = regmap_get_device(regmap);
struct inv_icm42600_state *st;
- struct irq_data *irq_desc;
int irq_type;
bool open_drain;
int ret;
@@ -683,14 +682,7 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
return -ENODEV;
}
- /* get irq properties, set trigger falling by default */
- irq_desc = irq_get_irq_data(irq);
- if (!irq_desc) {
- dev_err(dev, "could not find IRQ %d\n", irq);
- return -EINVAL;
- }
-
- irq_type = irqd_get_trigger_type(irq_desc);
+ irq_type = irq_get_trigger_type(irq);
if (!irq_type)
irq_type = IRQF_TRIGGER_FALLING;
@@ -773,7 +765,7 @@ int inv_icm42600_core_probe(struct regmap *regmap, int chip, int irq,
return devm_add_action_or_reset(dev, inv_icm42600_disable_pm, dev);
}
-EXPORT_SYMBOL_NS_GPL(inv_icm42600_core_probe, IIO_ICM42600);
+EXPORT_SYMBOL_NS_GPL(inv_icm42600_core_probe, "IIO_ICM42600");
/*
* Suspend saves sensors state and turns everything off.
@@ -896,4 +888,4 @@ EXPORT_NS_GPL_DEV_PM_OPS(inv_icm42600_pm_ops, IIO_ICM42600) = {
MODULE_AUTHOR("InvenSense, Inc.");
MODULE_DESCRIPTION("InvenSense ICM-426xx device driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_INV_SENSORS_TIMESTAMP);
+MODULE_IMPORT_NS("IIO_INV_SENSORS_TIMESTAMP");
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
index 938af5b640b0..c6bb68bf5e14 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_gyro.c
@@ -99,8 +99,6 @@ static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev,
const unsigned long *scan_mask)
{
struct inv_icm42600_state *st = iio_device_get_drvdata(indio_dev);
- struct inv_icm42600_sensor_state *gyro_st = iio_priv(indio_dev);
- struct inv_sensors_timestamp *ts = &gyro_st->ts;
struct inv_icm42600_sensor_conf conf = INV_ICM42600_SENSOR_CONF_INIT;
unsigned int fifo_en = 0;
unsigned int sleep_gyro = 0;
@@ -128,7 +126,6 @@ static int inv_icm42600_gyro_update_scan_mode(struct iio_dev *indio_dev,
}
/* update data FIFO write */
- inv_sensors_timestamp_apply_odr(ts, 0, 0, 0);
ret = inv_icm42600_buffer_set_fifo_en(st, fifo_en | st->fifo.en);
out_unlock:
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
index ebb31b385881..04e440fe023a 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_i2c.c
@@ -71,6 +71,22 @@ static int inv_icm42600_probe(struct i2c_client *client)
inv_icm42600_i2c_bus_setup);
}
+/*
+ * device id table is used to identify what device can be
+ * supported by this driver
+ */
+static const struct i2c_device_id inv_icm42600_id[] = {
+ { "icm42600", INV_CHIP_ICM42600 },
+ { "icm42602", INV_CHIP_ICM42602 },
+ { "icm42605", INV_CHIP_ICM42605 },
+ { "icm42686", INV_CHIP_ICM42686 },
+ { "icm42622", INV_CHIP_ICM42622 },
+ { "icm42688", INV_CHIP_ICM42688 },
+ { "icm42631", INV_CHIP_ICM42631 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, inv_icm42600_id);
+
static const struct of_device_id inv_icm42600_of_matches[] = {
{
.compatible = "invensense,icm42600",
@@ -104,6 +120,7 @@ static struct i2c_driver inv_icm42600_driver = {
.of_match_table = inv_icm42600_of_matches,
.pm = pm_ptr(&inv_icm42600_pm_ops),
},
+ .id_table = inv_icm42600_id,
.probe = inv_icm42600_probe,
};
module_i2c_driver(inv_icm42600_driver);
@@ -111,4 +128,4 @@ module_i2c_driver(inv_icm42600_driver);
MODULE_AUTHOR("InvenSense, Inc.");
MODULE_DESCRIPTION("InvenSense ICM-426xx I2C driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_ICM42600);
+MODULE_IMPORT_NS("IIO_ICM42600");
diff --git a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
index eae5ff7a3cc1..c55d8e672183 100644
--- a/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
+++ b/drivers/iio/imu/inv_icm42600/inv_icm42600_spi.c
@@ -67,6 +67,22 @@ static int inv_icm42600_probe(struct spi_device *spi)
inv_icm42600_spi_bus_setup);
}
+/*
+ * device id table is used to identify what device can be
+ * supported by this driver
+ */
+static const struct spi_device_id inv_icm42600_id[] = {
+ { "icm42600", INV_CHIP_ICM42600 },
+ { "icm42602", INV_CHIP_ICM42602 },
+ { "icm42605", INV_CHIP_ICM42605 },
+ { "icm42686", INV_CHIP_ICM42686 },
+ { "icm42622", INV_CHIP_ICM42622 },
+ { "icm42688", INV_CHIP_ICM42688 },
+ { "icm42631", INV_CHIP_ICM42631 },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, inv_icm42600_id);
+
static const struct of_device_id inv_icm42600_of_matches[] = {
{
.compatible = "invensense,icm42600",
@@ -100,6 +116,7 @@ static struct spi_driver inv_icm42600_driver = {
.of_match_table = inv_icm42600_of_matches,
.pm = pm_ptr(&inv_icm42600_pm_ops),
},
+ .id_table = inv_icm42600_id,
.probe = inv_icm42600_probe,
};
module_spi_driver(inv_icm42600_driver);
@@ -107,4 +124,4 @@ module_spi_driver(inv_icm42600_driver);
MODULE_AUTHOR("InvenSense, Inc.");
MODULE_DESCRIPTION("InvenSense ICM-426xx SPI driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_ICM42600);
+MODULE_IMPORT_NS("IIO_ICM42600");
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
index f7bce428d9eb..373e59f6d91a 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_acpi.c
@@ -10,6 +10,8 @@
#include <linux/i2c.h>
#include <linux/dmi.h>
#include <linux/acpi.h>
+#include <linux/wordpart.h>
+
#include "inv_mpu_iio.h"
enum inv_mpu_product_name {
@@ -102,14 +104,11 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client,
unsigned short *secondary_addr)
{
struct acpi_device *adev = ACPI_COMPANION(&client->dev);
- const struct acpi_device_id *id;
u32 i2c_addr = 0;
LIST_HEAD(resources);
int ret;
- id = acpi_match_device(client->dev.driver->acpi_match_table,
- &client->dev);
- if (!id)
+ if (!is_acpi_device_node(dev_fwnode(&client->dev)))
return -ENODEV;
ret = acpi_dev_get_resources(adev, &resources,
@@ -118,8 +117,8 @@ static int inv_mpu_process_acpi_config(struct i2c_client *client,
return ret;
acpi_dev_free_resource_list(&resources);
- *primary_addr = i2c_addr & 0x0000ffff;
- *secondary_addr = (i2c_addr & 0xffff0000) >> 16;
+ *primary_addr = lower_16_bits(i2c_addr);
+ *secondary_addr = upper_16_bits(i2c_addr);
return 0;
}
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
index 14d95f34e981..844b611b825a 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_core.c
@@ -286,6 +286,24 @@ static const struct inv_mpu6050_hw hw_info[] = {
.temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
.startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
},
+ {
+ .whoami = INV_IAM20680HP_WHOAMI_VALUE,
+ .name = "IAM20680HP",
+ .reg = &reg_set_6500,
+ .config = &chip_config_6500,
+ .fifo_size = 4 * 1024,
+ .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
+ },
+ {
+ .whoami = INV_IAM20680HT_WHOAMI_VALUE,
+ .name = "IAM20680HT",
+ .reg = &reg_set_6500,
+ .config = &chip_config_6500,
+ .fifo_size = 4 * 1024,
+ .temp = {INV_ICM20608_TEMP_OFFSET, INV_ICM20608_TEMP_SCALE},
+ .startup_time = {INV_MPU6500_GYRO_STARTUP_TIME, INV_MPU6500_ACCEL_STARTUP_TIME},
+ },
};
static int inv_mpu6050_pwr_mgmt_1_write(struct inv_mpu6050_state *st, bool sleep,
@@ -510,6 +528,8 @@ static int inv_mpu6050_set_accel_lpf_regs(struct inv_mpu6050_state *st,
return 0;
case INV_ICM20689:
case INV_ICM20690:
+ case INV_IAM20680HT:
+ case INV_IAM20680HP:
/* set FIFO size to maximum value */
val |= INV_ICM20689_BITS_FIFO_SIZE_MAX;
break;
@@ -1153,24 +1173,21 @@ static int inv_mpu6050_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct inv_mpu6050_state *st = iio_priv(indio_dev);
- int enable;
/* support only WoM (accel roc rising) event */
if (chan->type != IIO_ACCEL || type != IIO_EV_TYPE_ROC ||
dir != IIO_EV_DIR_RISING)
return -EINVAL;
- enable = !!state;
-
guard(mutex)(&st->lock);
- if (st->chip_config.wom_en == enable)
+ if (st->chip_config.wom_en == state)
return 0;
- return inv_mpu6050_enable_wom(st, enable);
+ return inv_mpu6050_enable_wom(st, state);
}
static int inv_mpu6050_read_event_value(struct iio_dev *indio_dev,
@@ -1859,7 +1876,6 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
struct inv_mpu6050_platform_data *pdata;
struct device *dev = regmap_get_device(regmap);
int result;
- struct irq_data *desc;
int irq_type;
indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
@@ -1893,13 +1909,7 @@ int inv_mpu_core_probe(struct regmap *regmap, int irq, const char *name,
}
if (irq > 0) {
- desc = irq_get_irq_data(irq);
- if (!desc) {
- dev_err(dev, "Could not find IRQ %d\n", irq);
- return -EINVAL;
- }
-
- irq_type = irqd_get_trigger_type(desc);
+ irq_type = irq_get_trigger_type(irq);
if (!irq_type)
irq_type = IRQF_TRIGGER_RISING;
} else {
@@ -2082,7 +2092,7 @@ error_power_off:
inv_mpu6050_set_power_itg(st, false);
return result;
}
-EXPORT_SYMBOL_NS_GPL(inv_mpu_core_probe, IIO_MPU6050);
+EXPORT_SYMBOL_NS_GPL(inv_mpu_core_probe, "IIO_MPU6050");
static int inv_mpu_resume(struct device *dev)
{
@@ -2233,4 +2243,4 @@ EXPORT_NS_GPL_DEV_PM_OPS(inv_mpu_pmops, IIO_MPU6050) = {
MODULE_AUTHOR("Invensense Corporation");
MODULE_DESCRIPTION("Invensense device MPU6050 driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_INV_SENSORS_TIMESTAMP);
+MODULE_IMPORT_NS("IIO_INV_SENSORS_TIMESTAMP");
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
index 0e03137fb3d4..307a06f4df2e 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_i2c.c
@@ -188,6 +188,8 @@ static const struct i2c_device_id inv_mpu_id[] = {
{"icm20602", INV_ICM20602},
{"icm20690", INV_ICM20690},
{"iam20680", INV_IAM20680},
+ {"iam20680hp", INV_IAM20680HP},
+ {"iam20680ht", INV_IAM20680HT},
{}
};
@@ -254,6 +256,14 @@ static const struct of_device_id inv_of_match[] = {
.compatible = "invensense,iam20680",
.data = (void *)INV_IAM20680
},
+ {
+ .compatible = "invensense,iam20680hp",
+ .data = (void *)INV_IAM20680HP
+ },
+ {
+ .compatible = "invensense,iam20680ht",
+ .data = (void *)INV_IAM20680HT
+ },
{ }
};
MODULE_DEVICE_TABLE(of, inv_of_match);
@@ -281,4 +291,4 @@ module_i2c_driver(inv_mpu_driver);
MODULE_AUTHOR("Invensense Corporation");
MODULE_DESCRIPTION("Invensense device MPU6050 driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_MPU6050);
+MODULE_IMPORT_NS("IIO_MPU6050");
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
index e1c0c5146876..a6862cf42639 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_iio.h
@@ -85,6 +85,8 @@ enum inv_devices {
INV_ICM20602,
INV_ICM20690,
INV_IAM20680,
+ INV_IAM20680HP,
+ INV_IAM20680HT,
INV_NUM_PARTS
};
@@ -424,6 +426,8 @@ struct inv_mpu6050_state {
#define INV_ICM20602_WHOAMI_VALUE 0x12
#define INV_ICM20690_WHOAMI_VALUE 0x20
#define INV_IAM20680_WHOAMI_VALUE 0xA9
+#define INV_IAM20680HP_WHOAMI_VALUE 0xF8
+#define INV_IAM20680HT_WHOAMI_VALUE 0xFA
/* scan element definition for generic MPU6xxx devices */
enum inv_mpu6050_scan {
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
index 05451ca1580b..ab415874d699 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_spi.c
@@ -80,6 +80,8 @@ static const struct spi_device_id inv_mpu_id[] = {
{"icm20602", INV_ICM20602},
{"icm20690", INV_ICM20690},
{"iam20680", INV_IAM20680},
+ {"iam20680hp", INV_IAM20680HP},
+ {"iam20680ht", INV_IAM20680HT},
{}
};
@@ -142,6 +144,14 @@ static const struct of_device_id inv_of_match[] = {
.compatible = "invensense,iam20680",
.data = (void *)INV_IAM20680
},
+ {
+ .compatible = "invensense,iam20680hp",
+ .data = (void *)INV_IAM20680HP
+ },
+ {
+ .compatible = "invensense,iam20680ht",
+ .data = (void *)INV_IAM20680HT
+ },
{ }
};
MODULE_DEVICE_TABLE(of, inv_of_match);
@@ -168,4 +178,4 @@ module_spi_driver(inv_mpu_driver);
MODULE_AUTHOR("Adriana Reus <adriana.reus@intel.com>");
MODULE_DESCRIPTION("Invensense device MPU6000 driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_MPU6050);
+MODULE_IMPORT_NS("IIO_MPU6050");
diff --git a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
index 3bfeabab0ec4..5b1088cc3704 100644
--- a/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
+++ b/drivers/iio/imu/inv_mpu6050/inv_mpu_trigger.c
@@ -112,7 +112,6 @@ int inv_mpu6050_prepare_fifo(struct inv_mpu6050_state *st, bool enable)
if (enable) {
/* reset timestamping */
inv_sensors_timestamp_reset(&st->timestamp);
- inv_sensors_timestamp_apply_odr(&st->timestamp, 0, 0, 0);
/* reset FIFO */
d = st->chip_config.user_ctrl | INV_MPU6050_BIT_FIFO_RST;
ret = regmap_write(st->map, st->reg->user_ctrl, d);
diff --git a/drivers/iio/imu/kmx61.c b/drivers/iio/imu/kmx61.c
index c61c012e25bb..324c38764656 100644
--- a/drivers/iio/imu/kmx61.c
+++ b/drivers/iio/imu/kmx61.c
@@ -7,12 +7,13 @@
* IIO driver for KMX61 (7-bit I2C slave address 0x0E or 0x0F).
*/
-#include <linux/module.h>
#include <linux/i2c.h>
-#include <linux/acpi.h>
#include <linux/interrupt.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
+
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
@@ -941,7 +942,7 @@ static int kmx61_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct kmx61_data *data = kmx61_get_data(indio_dev);
int ret = 0;
@@ -1217,16 +1218,6 @@ err:
return IRQ_HANDLED;
}
-static const char *kmx61_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
- return dev_name(dev);
-}
-
static struct iio_dev *kmx61_indiodev_setup(struct kmx61_data *data,
const struct iio_info *info,
const struct iio_chan_spec *chan,
@@ -1293,8 +1284,6 @@ static int kmx61_probe(struct i2c_client *client)
if (id)
name = id->name;
- else if (ACPI_HANDLE(&client->dev))
- name = kmx61_match_acpi_device(&client->dev);
else
return -ENODEV;
@@ -1496,13 +1485,6 @@ static const struct dev_pm_ops kmx61_pm_ops = {
RUNTIME_PM_OPS(kmx61_runtime_suspend, kmx61_runtime_resume, NULL)
};
-static const struct acpi_device_id kmx61_acpi_match[] = {
- {"KMX61021", 0},
- {}
-};
-
-MODULE_DEVICE_TABLE(acpi, kmx61_acpi_match);
-
static const struct i2c_device_id kmx61_id[] = {
{ "kmx611021" },
{}
@@ -1513,7 +1495,6 @@ MODULE_DEVICE_TABLE(i2c, kmx61_id);
static struct i2c_driver kmx61_driver = {
.driver = {
.name = KMX61_DRV_NAME,
- .acpi_match_table = kmx61_acpi_match,
.pm = pm_ptr(&kmx61_pm_ops),
},
.probe = kmx61_probe,
diff --git a/drivers/iio/imu/smi240.c b/drivers/iio/imu/smi240.c
new file mode 100644
index 000000000000..4492c4d013bd
--- /dev/null
+++ b/drivers/iio/imu/smi240.c
@@ -0,0 +1,621 @@
+// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
+/*
+ * Copyright (c) 2024 Robert Bosch GmbH.
+ */
+#include <linux/bitfield.h>
+#include <linux/bits.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <linux/unaligned.h>
+#include <linux/units.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+#define SMI240_CHIP_ID 0x0024
+
+#define SMI240_SOFT_CONFIG_EOC_MASK BIT(0)
+#define SMI240_SOFT_CONFIG_GYR_BW_MASK BIT(1)
+#define SMI240_SOFT_CONFIG_ACC_BW_MASK BIT(2)
+#define SMI240_SOFT_CONFIG_BITE_AUTO_MASK BIT(3)
+#define SMI240_SOFT_CONFIG_BITE_REP_MASK GENMASK(6, 4)
+
+#define SMI240_CHIP_ID_REG 0x00
+#define SMI240_SOFT_CONFIG_REG 0x0A
+#define SMI240_TEMP_CUR_REG 0x10
+#define SMI240_ACCEL_X_CUR_REG 0x11
+#define SMI240_GYRO_X_CUR_REG 0x14
+#define SMI240_DATA_CAP_FIRST_REG 0x17
+#define SMI240_CMD_REG 0x2F
+
+#define SMI240_SOFT_RESET_CMD 0xB6
+
+#define SMI240_BITE_SEQUENCE_DELAY_US 140000
+#define SMI240_FILTER_FLUSH_DELAY_US 60000
+#define SMI240_DIGITAL_STARTUP_DELAY_US 120000
+#define SMI240_MECH_STARTUP_DELAY_US 100000
+
+#define SMI240_BUS_ID 0x00
+#define SMI240_CRC_INIT 0x05
+#define SMI240_CRC_POLY 0x0B
+#define SMI240_CRC_MASK GENMASK(2, 0)
+
+#define SMI240_READ_SD_BIT_MASK BIT(31)
+#define SMI240_READ_DATA_MASK GENMASK(19, 4)
+#define SMI240_READ_CS_BIT_MASK BIT(3)
+
+#define SMI240_WRITE_BUS_ID_MASK GENMASK(31, 30)
+#define SMI240_WRITE_ADDR_MASK GENMASK(29, 22)
+#define SMI240_WRITE_BIT_MASK BIT(21)
+#define SMI240_WRITE_CAP_BIT_MASK BIT(20)
+#define SMI240_WRITE_DATA_MASK GENMASK(18, 3)
+
+/* T°C = (temp / 256) + 25 */
+#define SMI240_TEMP_OFFSET 6400 /* 25 * 256 */
+#define SMI240_TEMP_SCALE 3906250 /* (1 / 256) * 1e9 */
+
+#define SMI240_ACCEL_SCALE 500 /* (1 / 2000) * 1e6 */
+#define SMI240_GYRO_SCALE 10000 /* (1 / 100) * 1e6 */
+
+#define SMI240_LOW_BANDWIDTH_HZ 50
+#define SMI240_HIGH_BANDWIDTH_HZ 400
+
+#define SMI240_BUILT_IN_SELF_TEST_COUNT 3
+
+#define SMI240_DATA_CHANNEL(_type, _axis, _index) { \
+ .type = _type, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##_axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
+ .info_mask_shared_by_type = \
+ BIT(IIO_CHAN_INFO_SCALE) | \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .info_mask_shared_by_type_available = \
+ BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+#define SMI240_TEMP_CHANNEL(_index) { \
+ .type = IIO_TEMP, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_TEMP_OBJECT, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_OFFSET) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .scan_index = _index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 16, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+}
+
+enum capture_mode { SMI240_CAPTURE_OFF = 0, SMI240_CAPTURE_ON = 1 };
+
+struct smi240_data {
+ struct regmap *regmap;
+ u16 accel_filter_freq;
+ u16 anglvel_filter_freq;
+ u8 built_in_self_test_count;
+ enum capture_mode capture;
+ /*
+ * Ensure natural alignment for timestamp if present.
+ * Channel size: 2 bytes.
+ * Max length needed: 2 * 3 channels + temp channel + 2 bytes padding + 8 byte ts.
+ * If fewer channels are enabled, less space may be needed, as
+ * long as the timestamp is still aligned to 8 bytes.
+ */
+ s16 buf[12] __aligned(8);
+
+ __be32 spi_buf __aligned(IIO_DMA_MINALIGN);
+};
+
+enum {
+ SMI240_TEMP_OBJECT,
+ SMI240_SCAN_ACCEL_X,
+ SMI240_SCAN_ACCEL_Y,
+ SMI240_SCAN_ACCEL_Z,
+ SMI240_SCAN_GYRO_X,
+ SMI240_SCAN_GYRO_Y,
+ SMI240_SCAN_GYRO_Z,
+ SMI240_SCAN_TIMESTAMP,
+};
+
+static const struct iio_chan_spec smi240_channels[] = {
+ SMI240_TEMP_CHANNEL(SMI240_TEMP_OBJECT),
+ SMI240_DATA_CHANNEL(IIO_ACCEL, X, SMI240_SCAN_ACCEL_X),
+ SMI240_DATA_CHANNEL(IIO_ACCEL, Y, SMI240_SCAN_ACCEL_Y),
+ SMI240_DATA_CHANNEL(IIO_ACCEL, Z, SMI240_SCAN_ACCEL_Z),
+ SMI240_DATA_CHANNEL(IIO_ANGL_VEL, X, SMI240_SCAN_GYRO_X),
+ SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Y, SMI240_SCAN_GYRO_Y),
+ SMI240_DATA_CHANNEL(IIO_ANGL_VEL, Z, SMI240_SCAN_GYRO_Z),
+ IIO_CHAN_SOFT_TIMESTAMP(SMI240_SCAN_TIMESTAMP),
+};
+
+static const int smi240_low_pass_freqs[] = { SMI240_LOW_BANDWIDTH_HZ,
+ SMI240_HIGH_BANDWIDTH_HZ };
+
+static u8 smi240_crc3(u32 data, u8 init, u8 poly)
+{
+ u8 crc = init;
+ u8 do_xor;
+ s8 i = 31;
+
+ do {
+ do_xor = crc & 0x04;
+ crc <<= 1;
+ crc |= 0x01 & (data >> i);
+ if (do_xor)
+ crc ^= poly;
+
+ crc &= SMI240_CRC_MASK;
+ } while (--i >= 0);
+
+ return crc;
+}
+
+static bool smi240_sensor_data_is_valid(u32 data)
+{
+ if (smi240_crc3(data, SMI240_CRC_INIT, SMI240_CRC_POLY) != 0)
+ return false;
+
+ if (FIELD_GET(SMI240_READ_SD_BIT_MASK, data) &
+ FIELD_GET(SMI240_READ_CS_BIT_MASK, data))
+ return false;
+
+ return true;
+}
+
+static int smi240_regmap_spi_read(void *context, const void *reg_buf,
+ size_t reg_size, void *val_buf,
+ size_t val_size)
+{
+ int ret;
+ u32 request, response;
+ u16 *val = val_buf;
+ struct spi_device *spi = context;
+ struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
+ struct smi240_data *iio_priv_data = iio_priv(indio_dev);
+
+ if (reg_size != 1 || val_size != 2)
+ return -EINVAL;
+
+ request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID);
+ request |= FIELD_PREP(SMI240_WRITE_CAP_BIT_MASK, iio_priv_data->capture);
+ request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, *(u8 *)reg_buf);
+ request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY);
+
+ iio_priv_data->spi_buf = cpu_to_be32(request);
+
+ /*
+ * SMI240 module consists of a 32Bit Out Of Frame (OOF)
+ * SPI protocol, where the slave interface responds to
+ * the Master request in the next frame.
+ * CS signal must toggle (> 700 ns) between the frames.
+ */
+ ret = spi_write(spi, &iio_priv_data->spi_buf, sizeof(request));
+ if (ret)
+ return ret;
+
+ ret = spi_read(spi, &iio_priv_data->spi_buf, sizeof(response));
+ if (ret)
+ return ret;
+
+ response = be32_to_cpu(iio_priv_data->spi_buf);
+
+ if (!smi240_sensor_data_is_valid(response))
+ return -EIO;
+
+ *val = FIELD_GET(SMI240_READ_DATA_MASK, response);
+
+ return 0;
+}
+
+static int smi240_regmap_spi_write(void *context, const void *data,
+ size_t count)
+{
+ u8 reg_addr;
+ u16 reg_data;
+ u32 request;
+ const u8 *data_ptr = data;
+ struct spi_device *spi = context;
+ struct iio_dev *indio_dev = dev_get_drvdata(&spi->dev);
+ struct smi240_data *iio_priv_data = iio_priv(indio_dev);
+
+ if (count < 2)
+ return -EINVAL;
+
+ reg_addr = data_ptr[0];
+ memcpy(&reg_data, &data_ptr[1], sizeof(reg_data));
+
+ request = FIELD_PREP(SMI240_WRITE_BUS_ID_MASK, SMI240_BUS_ID);
+ request |= FIELD_PREP(SMI240_WRITE_BIT_MASK, 1);
+ request |= FIELD_PREP(SMI240_WRITE_ADDR_MASK, reg_addr);
+ request |= FIELD_PREP(SMI240_WRITE_DATA_MASK, reg_data);
+ request |= smi240_crc3(request, SMI240_CRC_INIT, SMI240_CRC_POLY);
+
+ iio_priv_data->spi_buf = cpu_to_be32(request);
+
+ return spi_write(spi, &iio_priv_data->spi_buf, sizeof(request));
+}
+
+static const struct regmap_bus smi240_regmap_bus = {
+ .read = smi240_regmap_spi_read,
+ .write = smi240_regmap_spi_write,
+};
+
+static const struct regmap_config smi240_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .val_format_endian = REGMAP_ENDIAN_NATIVE,
+};
+
+static int smi240_soft_reset(struct smi240_data *data)
+{
+ int ret;
+
+ ret = regmap_write(data->regmap, SMI240_CMD_REG, SMI240_SOFT_RESET_CMD);
+ if (ret)
+ return ret;
+ fsleep(SMI240_DIGITAL_STARTUP_DELAY_US);
+
+ return 0;
+}
+
+static int smi240_soft_config(struct smi240_data *data)
+{
+ int ret;
+ u8 acc_bw, gyr_bw;
+ u16 request;
+
+ switch (data->accel_filter_freq) {
+ case SMI240_LOW_BANDWIDTH_HZ:
+ acc_bw = 0x1;
+ break;
+ case SMI240_HIGH_BANDWIDTH_HZ:
+ acc_bw = 0x0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (data->anglvel_filter_freq) {
+ case SMI240_LOW_BANDWIDTH_HZ:
+ gyr_bw = 0x1;
+ break;
+ case SMI240_HIGH_BANDWIDTH_HZ:
+ gyr_bw = 0x0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ request = FIELD_PREP(SMI240_SOFT_CONFIG_EOC_MASK, 1);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_GYR_BW_MASK, gyr_bw);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_ACC_BW_MASK, acc_bw);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_AUTO_MASK, 1);
+ request |= FIELD_PREP(SMI240_SOFT_CONFIG_BITE_REP_MASK,
+ data->built_in_self_test_count - 1);
+
+ ret = regmap_write(data->regmap, SMI240_SOFT_CONFIG_REG, request);
+ if (ret)
+ return ret;
+
+ fsleep(SMI240_MECH_STARTUP_DELAY_US +
+ data->built_in_self_test_count * SMI240_BITE_SEQUENCE_DELAY_US +
+ SMI240_FILTER_FLUSH_DELAY_US);
+
+ return 0;
+}
+
+static int smi240_get_low_pass_filter_freq(struct smi240_data *data,
+ int chan_type, int *val)
+{
+ switch (chan_type) {
+ case IIO_ACCEL:
+ *val = data->accel_filter_freq;
+ return 0;
+ case IIO_ANGL_VEL:
+ *val = data->anglvel_filter_freq;
+ return 0;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int smi240_get_data(struct smi240_data *data, int chan_type, int axis,
+ int *val)
+{
+ u8 reg;
+ int ret, sample;
+
+ switch (chan_type) {
+ case IIO_TEMP:
+ reg = SMI240_TEMP_CUR_REG;
+ break;
+ case IIO_ACCEL:
+ reg = SMI240_ACCEL_X_CUR_REG + (axis - IIO_MOD_X);
+ break;
+ case IIO_ANGL_VEL:
+ reg = SMI240_GYRO_X_CUR_REG + (axis - IIO_MOD_X);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_read(data->regmap, reg, &sample);
+ if (ret)
+ return ret;
+
+ *val = sign_extend32(sample, 15);
+
+ return 0;
+}
+
+static irqreturn_t smi240_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct smi240_data *data = iio_priv(indio_dev);
+ int base = SMI240_DATA_CAP_FIRST_REG, i = 0;
+ int ret, chan, sample;
+
+ data->capture = SMI240_CAPTURE_ON;
+
+ iio_for_each_active_channel(indio_dev, chan) {
+ ret = regmap_read(data->regmap, base + chan, &sample);
+ data->capture = SMI240_CAPTURE_OFF;
+ if (ret)
+ goto out;
+ data->buf[i++] = sample;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->buf, pf->timestamp);
+
+out:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int smi240_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, const int **vals,
+ int *type, int *length, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ *vals = smi240_low_pass_freqs;
+ *length = ARRAY_SIZE(smi240_low_pass_freqs);
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int smi240_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ int ret;
+ struct smi240_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+ ret = smi240_get_data(data, chan->type, chan->channel2, val);
+ iio_device_release_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ ret = smi240_get_low_pass_filter_freq(data, chan->type, val);
+ if (ret)
+ return ret;
+ return IIO_VAL_INT;
+
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = SMI240_TEMP_SCALE / GIGA;
+ *val2 = SMI240_TEMP_SCALE % GIGA;
+ return IIO_VAL_INT_PLUS_NANO;
+ case IIO_ACCEL:
+ *val = 0;
+ *val2 = SMI240_ACCEL_SCALE;
+ return IIO_VAL_INT_PLUS_MICRO;
+ case IIO_ANGL_VEL:
+ *val = 0;
+ *val2 = SMI240_GYRO_SCALE;
+ return IIO_VAL_INT_PLUS_MICRO;
+ default:
+ return -EINVAL;
+ }
+
+ case IIO_CHAN_INFO_OFFSET:
+ if (chan->type == IIO_TEMP) {
+ *val = SMI240_TEMP_OFFSET;
+ return IIO_VAL_INT;
+ } else {
+ return -EINVAL;
+ }
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int smi240_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int val, int val2,
+ long mask)
+{
+ int ret, i;
+ struct smi240_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
+ for (i = 0; i < ARRAY_SIZE(smi240_low_pass_freqs); i++) {
+ if (val == smi240_low_pass_freqs[i])
+ break;
+ }
+
+ if (i == ARRAY_SIZE(smi240_low_pass_freqs))
+ return -EINVAL;
+
+ switch (chan->type) {
+ case IIO_ACCEL:
+ data->accel_filter_freq = val;
+ break;
+ case IIO_ANGL_VEL:
+ data->anglvel_filter_freq = val;
+ break;
+ default:
+ return -EINVAL;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Write access to soft config is locked until hard/soft reset */
+ ret = smi240_soft_reset(data);
+ if (ret)
+ return ret;
+
+ return smi240_soft_config(data);
+}
+
+static int smi240_write_raw_get_fmt(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, long info)
+{
+ switch (info) {
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ return IIO_VAL_INT_PLUS_NANO;
+ default:
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+ default:
+ return IIO_VAL_INT_PLUS_MICRO;
+ }
+}
+
+static int smi240_init(struct smi240_data *data)
+{
+ int ret;
+
+ data->accel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ;
+ data->anglvel_filter_freq = SMI240_HIGH_BANDWIDTH_HZ;
+ data->built_in_self_test_count = SMI240_BUILT_IN_SELF_TEST_COUNT;
+
+ ret = smi240_soft_reset(data);
+ if (ret)
+ return ret;
+
+ return smi240_soft_config(data);
+}
+
+static const struct iio_info smi240_info = {
+ .read_avail = smi240_read_avail,
+ .read_raw = smi240_read_raw,
+ .write_raw = smi240_write_raw,
+ .write_raw_get_fmt = smi240_write_raw_get_fmt,
+};
+
+static int smi240_probe(struct spi_device *spi)
+{
+ struct device *dev = &spi->dev;
+ struct iio_dev *indio_dev;
+ struct regmap *regmap;
+ struct smi240_data *data;
+ int ret, response;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ regmap = devm_regmap_init(dev, &smi240_regmap_bus, dev,
+ &smi240_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed to initialize SPI Regmap\n");
+
+ data = iio_priv(indio_dev);
+ dev_set_drvdata(dev, indio_dev);
+ data->regmap = regmap;
+ data->capture = SMI240_CAPTURE_OFF;
+
+ ret = regmap_read(data->regmap, SMI240_CHIP_ID_REG, &response);
+ if (ret)
+ return dev_err_probe(dev, ret, "Read chip id failed\n");
+
+ if (response != SMI240_CHIP_ID)
+ dev_info(dev, "Unknown chip id: 0x%04x\n", response);
+
+ ret = smi240_init(data);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Device initialization failed\n");
+
+ indio_dev->channels = smi240_channels;
+ indio_dev->num_channels = ARRAY_SIZE(smi240_channels);
+ indio_dev->name = "smi240";
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &smi240_info;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ smi240_trigger_handler, NULL);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Setup triggered buffer failed\n");
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "Register IIO device failed\n");
+
+ return 0;
+}
+
+static const struct spi_device_id smi240_spi_id[] = {
+ { "smi240" },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, smi240_spi_id);
+
+static const struct of_device_id smi240_of_match[] = {
+ { .compatible = "bosch,smi240" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, smi240_of_match);
+
+static struct spi_driver smi240_spi_driver = {
+ .probe = smi240_probe,
+ .id_table = smi240_spi_id,
+ .driver = {
+ .of_match_table = smi240_of_match,
+ .name = "smi240",
+ },
+};
+module_spi_driver(smi240_spi_driver);
+
+MODULE_AUTHOR("Markus Lochmann <markus.lochmann@de.bosch.com>");
+MODULE_AUTHOR("Stefan Gutmann <stefan.gutmann@de.bosch.com>");
+MODULE_DESCRIPTION("Bosch SMI240 SPI driver");
+MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
index a3b93566533b..c225b246c8a5 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx.h
@@ -447,7 +447,7 @@ struct st_lsm6dsx_hw {
/* Ensure natural alignment of buffer elements */
struct {
__le16 channels[3];
- s64 ts __aligned(8);
+ aligned_s64 ts;
} scan[ST_LSM6DSX_ID_MAX];
};
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
index ed0267929725..4fdcc2acc94e 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_core.c
@@ -1865,7 +1865,7 @@ static int st_lsm6dsx_write_raw(struct iio_dev *iio_dev,
return err;
}
-static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, int state)
+static int st_lsm6dsx_event_setup(struct st_lsm6dsx_hw *hw, bool state)
{
const struct st_lsm6dsx_reg *reg;
unsigned int data;
@@ -1959,7 +1959,7 @@ static int
st_lsm6dsx_write_event_config(struct iio_dev *iio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct st_lsm6dsx_sensor *sensor = iio_priv(iio_dev);
struct st_lsm6dsx_hw *hw = sensor->hw;
@@ -2132,14 +2132,11 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw,
const struct st_lsm6dsx_reg **drdy_reg)
{
struct device *dev = hw->dev;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
int err = 0, drdy_pin;
- if (device_property_read_u32(dev, "st,drdy-int-pin", &drdy_pin) < 0) {
- struct st_sensors_platform_data *pdata;
-
- pdata = (struct st_sensors_platform_data *)dev->platform_data;
+ if (device_property_read_u32(dev, "st,drdy-int-pin", &drdy_pin) < 0)
drdy_pin = pdata ? pdata->drdy_int_pin : 1;
- }
switch (drdy_pin) {
case 1:
@@ -2162,14 +2159,13 @@ st_lsm6dsx_get_drdy_reg(struct st_lsm6dsx_hw *hw,
static int st_lsm6dsx_init_shub(struct st_lsm6dsx_hw *hw)
{
const struct st_lsm6dsx_shub_settings *hub_settings;
- struct st_sensors_platform_data *pdata;
struct device *dev = hw->dev;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
unsigned int data;
int err = 0;
hub_settings = &hw->settings->shub_settings;
- pdata = (struct st_sensors_platform_data *)dev->platform_data;
if (device_property_read_bool(dev, "st,pullups") ||
(pdata && pdata->pullups)) {
if (hub_settings->pullup_en.sec_page) {
@@ -2524,15 +2520,14 @@ static irqreturn_t st_lsm6dsx_sw_trigger_handler_thread(int irq,
static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
{
- struct st_sensors_platform_data *pdata;
const struct st_lsm6dsx_reg *reg;
struct device *dev = hw->dev;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
unsigned long irq_type;
bool irq_active_low;
int err;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
-
+ irq_type = irq_get_trigger_type(hw->irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
@@ -2554,7 +2549,6 @@ static int st_lsm6dsx_irq_setup(struct st_lsm6dsx_hw *hw)
if (err < 0)
return err;
- pdata = (struct st_sensors_platform_data *)dev->platform_data;
if (device_property_read_bool(dev, "drive-open-drain") ||
(pdata && pdata->open_drain)) {
reg = &hw->settings->irq_config.od;
@@ -2639,7 +2633,7 @@ static int st_lsm6dsx_init_regulators(struct device *dev)
int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
struct regmap *regmap)
{
- struct st_sensors_platform_data *pdata = dev->platform_data;
+ const struct st_sensors_platform_data *pdata = dev_get_platdata(dev);
const struct st_lsm6dsx_shub_settings *hub_settings;
struct st_lsm6dsx_hw *hw;
const char *name = NULL;
@@ -2730,7 +2724,7 @@ int st_lsm6dsx_probe(struct device *dev, int irq, int hw_id,
return 0;
}
-EXPORT_SYMBOL_NS(st_lsm6dsx_probe, IIO_LSM6DSX);
+EXPORT_SYMBOL_NS(st_lsm6dsx_probe, "IIO_LSM6DSX");
static int st_lsm6dsx_suspend(struct device *dev)
{
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
index cddf41cc0ca9..25e1de89b6e4 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i2c.c
@@ -193,4 +193,4 @@ MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_LSM6DSX);
+MODULE_IMPORT_NS("IIO_LSM6DSX");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c
index 3b0c8b19c448..6952d901316f 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_i3c.c
@@ -54,4 +54,4 @@ module_i3c_driver(st_lsm6dsx_driver);
MODULE_AUTHOR("Vitor Soares <vitor.soares@synopsys.com>");
MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx i3c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_LSM6DSX);
+MODULE_IMPORT_NS("IIO_LSM6DSX");
diff --git a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
index c122c8831365..4b4b6d45524f 100644
--- a/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
+++ b/drivers/iio/imu/st_lsm6dsx/st_lsm6dsx_spi.c
@@ -181,4 +181,4 @@ MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi@st.com>");
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics st_lsm6dsx spi driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_LSM6DSX);
+MODULE_IMPORT_NS("IIO_LSM6DSX");
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c
index 10c1b2ba7a3d..8f4a67edb335 100644
--- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_core.c
@@ -88,9 +88,9 @@ int st_lsm9ds0_probe(struct st_lsm9ds0 *lsm9ds0, struct regmap *regmap)
/* Setup magnetometer device */
return st_lsm9ds0_probe_magn(lsm9ds0, regmap);
}
-EXPORT_SYMBOL_NS_GPL(st_lsm9ds0_probe, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS_GPL(st_lsm9ds0_probe, "IIO_ST_SENSORS");
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU core driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
index d03cec3b24fe..0732cfa258c4 100644
--- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_i2c.c
@@ -91,4 +91,4 @@ module_i2c_driver(st_lsm9ds0_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU I2C driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
index 69e9135795a3..43ec57c1e604 100644
--- a/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
+++ b/drivers/iio/imu/st_lsm9ds0/st_lsm9ds0_spi.c
@@ -83,4 +83,4 @@ module_spi_driver(st_lsm9ds0_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("STMicroelectronics LSM9DS0 IMU SPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/industrialio-acpi.c b/drivers/iio/industrialio-acpi.c
index 981b75d40780..d67a43843799 100644
--- a/drivers/iio/industrialio-acpi.c
+++ b/drivers/iio/industrialio-acpi.c
@@ -2,7 +2,8 @@
/* IIO ACPI helper functions */
#include <linux/acpi.h>
-#include <linux/dev_printk.h>
+#include <linux/device.h>
+#include <linux/export.h>
#include <linux/iio/iio.h>
#include <linux/sprintf.h>
@@ -28,17 +29,21 @@ bool iio_read_acpi_mount_matrix(struct device *dev,
char *acpi_method)
{
struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_device *adev = ACPI_COMPANION(dev);
char *str;
union acpi_object *obj, *elements;
+ acpi_handle handle;
acpi_status status;
int i, j, val[3];
bool ret = false;
- if (!adev || !acpi_has_method(adev->handle, acpi_method))
+ handle = ACPI_HANDLE(dev);
+ if (!handle)
return false;
- status = acpi_evaluate_object(adev->handle, acpi_method, NULL, &buffer);
+ if (!acpi_has_method(handle, acpi_method))
+ return false;
+
+ status = acpi_evaluate_object(handle, acpi_method, NULL, &buffer);
if (ACPI_FAILURE(status)) {
dev_err(dev, "Failed to get ACPI mount matrix: %d\n", status);
return false;
@@ -83,3 +88,38 @@ out_free_buffer:
return ret;
}
EXPORT_SYMBOL_GPL(iio_read_acpi_mount_matrix);
+
+/**
+ * iio_get_acpi_device_name_and_data() - Return ACPI device instance name and driver data
+ * @dev: Device structure
+ * @data: Optional pointer to return driver data
+ *
+ * When device was enumerated by ACPI ID matching, the user might
+ * want to set description for the physical chip. In such cases
+ * the ACPI device instance name might be used. This call may be
+ * performed to retrieve this information.
+ *
+ * NOTE: This helper function exists only for backward compatibility,
+ * do not use in a new code!
+ *
+ * Returns: ACPI device instance name or %NULL.
+ */
+const char *iio_get_acpi_device_name_and_data(struct device *dev, const void **data)
+{
+ const struct acpi_device_id *id;
+ acpi_handle handle;
+
+ handle = ACPI_HANDLE(dev);
+ if (!handle)
+ return NULL;
+
+ id = acpi_match_device(dev->driver->acpi_match_table, dev);
+ if (!id)
+ return NULL;
+
+ if (data)
+ *data = (const void *)id->driver_data;
+
+ return dev_name(dev);
+}
+EXPORT_SYMBOL_GPL(iio_get_acpi_device_name_and_data);
diff --git a/drivers/iio/industrialio-backend.c b/drivers/iio/industrialio-backend.c
index 20b3b5212da7..363281272035 100644
--- a/drivers/iio/industrialio-backend.c
+++ b/drivers/iio/industrialio-backend.c
@@ -230,7 +230,7 @@ void iio_backend_debugfs_add(struct iio_backend *back,
debugfs_create_file("name", 0400, back_d, back,
&iio_backend_debugfs_name_fops);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_debugfs_add, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_debugfs_add, "IIO_BACKEND");
/**
* iio_backend_debugfs_print_chan_status - Print channel status
@@ -256,7 +256,7 @@ ssize_t iio_backend_debugfs_print_chan_status(struct iio_backend *back,
return iio_backend_op_call(back, debugfs_print_chan_status, chan, buf,
len);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_debugfs_print_chan_status, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_debugfs_print_chan_status, "IIO_BACKEND");
/**
* iio_backend_chan_enable - Enable a backend channel
@@ -270,7 +270,7 @@ int iio_backend_chan_enable(struct iio_backend *back, unsigned int chan)
{
return iio_backend_op_call(back, chan_enable, chan);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_chan_enable, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_chan_enable, "IIO_BACKEND");
/**
* iio_backend_chan_disable - Disable a backend channel
@@ -284,7 +284,7 @@ int iio_backend_chan_disable(struct iio_backend *back, unsigned int chan)
{
return iio_backend_op_call(back, chan_disable, chan);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_chan_disable, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_chan_disable, "IIO_BACKEND");
static void __iio_backend_disable(void *back)
{
@@ -299,7 +299,7 @@ void iio_backend_disable(struct iio_backend *back)
{
__iio_backend_disable(back);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_disable, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_disable, "IIO_BACKEND");
/**
* iio_backend_enable - Backend enable
@@ -312,7 +312,7 @@ int iio_backend_enable(struct iio_backend *back)
{
return iio_backend_op_call(back, enable);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_enable, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_enable, "IIO_BACKEND");
/**
* devm_iio_backend_enable - Device managed backend enable
@@ -332,7 +332,7 @@ int devm_iio_backend_enable(struct device *dev, struct iio_backend *back)
return devm_add_action_or_reset(dev, __iio_backend_disable, back);
}
-EXPORT_SYMBOL_NS_GPL(devm_iio_backend_enable, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(devm_iio_backend_enable, "IIO_BACKEND");
/**
* iio_backend_data_format_set - Configure the channel data format
@@ -354,7 +354,7 @@ int iio_backend_data_format_set(struct iio_backend *back, unsigned int chan,
return iio_backend_op_call(back, data_format_set, chan, data);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_data_format_set, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_format_set, "IIO_BACKEND");
/**
* iio_backend_data_source_set - Select data source
@@ -376,7 +376,7 @@ int iio_backend_data_source_set(struct iio_backend *back, unsigned int chan,
return iio_backend_op_call(back, data_source_set, chan, data);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_data_source_set, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_source_set, "IIO_BACKEND");
/**
* iio_backend_set_sampling_freq - Set channel sampling rate
@@ -392,7 +392,7 @@ int iio_backend_set_sampling_freq(struct iio_backend *back, unsigned int chan,
{
return iio_backend_op_call(back, set_sample_rate, chan, sample_rate_hz);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_set_sampling_freq, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_set_sampling_freq, "IIO_BACKEND");
/**
* iio_backend_test_pattern_set - Configure a test pattern
@@ -415,7 +415,7 @@ int iio_backend_test_pattern_set(struct iio_backend *back,
return iio_backend_op_call(back, test_pattern_set, chan, pattern);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_test_pattern_set, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_test_pattern_set, "IIO_BACKEND");
/**
* iio_backend_chan_status - Get the channel status
@@ -434,7 +434,7 @@ int iio_backend_chan_status(struct iio_backend *back, unsigned int chan,
{
return iio_backend_op_call(back, chan_status, chan, error);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_chan_status, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_chan_status, "IIO_BACKEND");
/**
* iio_backend_iodelay_set - Set digital I/O delay
@@ -457,7 +457,7 @@ int iio_backend_iodelay_set(struct iio_backend *back, unsigned int lane,
{
return iio_backend_op_call(back, iodelay_set, lane, taps);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_iodelay_set, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_iodelay_set, "IIO_BACKEND");
/**
* iio_backend_data_sample_trigger - Control when to sample data
@@ -478,7 +478,7 @@ int iio_backend_data_sample_trigger(struct iio_backend *back,
return iio_backend_op_call(back, data_sample_trigger, trigger);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_data_sample_trigger, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_sample_trigger, "IIO_BACKEND");
static void iio_backend_free_buffer(void *arg)
{
@@ -523,7 +523,7 @@ int devm_iio_backend_request_buffer(struct device *dev,
return devm_add_action_or_reset(dev, iio_backend_free_buffer, pair);
}
-EXPORT_SYMBOL_NS_GPL(devm_iio_backend_request_buffer, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(devm_iio_backend_request_buffer, "IIO_BACKEND");
/**
* iio_backend_read_raw - Read a channel attribute from a backend device.
@@ -542,7 +542,7 @@ int iio_backend_read_raw(struct iio_backend *back,
{
return iio_backend_op_call(back, read_raw, chan, val, val2, mask);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_read_raw, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_read_raw, "IIO_BACKEND");
static struct iio_backend *iio_backend_from_indio_dev_parent(const struct device *dev)
{
@@ -604,7 +604,7 @@ ssize_t iio_backend_ext_info_get(struct iio_dev *indio_dev, uintptr_t private,
return iio_backend_op_call(back, ext_info_get, private, chan, buf);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_ext_info_get, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_ext_info_get, "IIO_BACKEND");
/**
* iio_backend_ext_info_set - IIO ext_info write callback
@@ -634,7 +634,7 @@ ssize_t iio_backend_ext_info_set(struct iio_dev *indio_dev, uintptr_t private,
return iio_backend_op_call(back, ext_info_set, private, chan, buf, len);
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_ext_info_set, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_ext_info_set, "IIO_BACKEND");
/**
* iio_backend_extend_chan_spec - Extend an IIO channel
@@ -677,7 +677,7 @@ int iio_backend_extend_chan_spec(struct iio_backend *back,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_extend_chan_spec, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_extend_chan_spec, "IIO_BACKEND");
static void iio_backend_release(void *arg)
{
@@ -718,6 +718,84 @@ static int __devm_iio_backend_get(struct device *dev, struct iio_backend *back)
return 0;
}
+/**
+ * iio_backend_ddr_enable - Enable interface DDR (Double Data Rate) mode
+ * @back: Backend device
+ *
+ * Enable DDR, data is generated by the IP at each front (raising and falling)
+ * of the bus clock signal.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_ddr_enable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, ddr_enable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_ddr_enable, "IIO_BACKEND");
+
+/**
+ * iio_backend_ddr_disable - Disable interface DDR (Double Data Rate) mode
+ * @back: Backend device
+ *
+ * Disable DDR, setting into SDR mode (Single Data Rate).
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_ddr_disable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, ddr_disable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_ddr_disable, "IIO_BACKEND");
+
+/**
+ * iio_backend_data_stream_enable - Enable data stream
+ * @back: Backend device
+ *
+ * Enable data stream over the bus interface.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_stream_enable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, data_stream_enable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_stream_enable, "IIO_BACKEND");
+
+/**
+ * iio_backend_data_stream_disable - Disable data stream
+ * @back: Backend device
+ *
+ * Disable data stream over the bus interface.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_stream_disable(struct iio_backend *back)
+{
+ return iio_backend_op_call(back, data_stream_disable);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_stream_disable, "IIO_BACKEND");
+
+/**
+ * iio_backend_data_transfer_addr - Set data address.
+ * @back: Backend device
+ * @address: Data register address
+ *
+ * Some devices may need to inform the backend about an address
+ * where to read or write the data.
+ *
+ * RETURNS:
+ * 0 on success, negative error number on failure.
+ */
+int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address)
+{
+ return iio_backend_op_call(back, data_transfer_addr, address);
+}
+EXPORT_SYMBOL_NS_GPL(iio_backend_data_transfer_addr, "IIO_BACKEND");
+
static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, const char *name,
struct fwnode_handle *fwnode)
{
@@ -737,8 +815,8 @@ static struct iio_backend *__devm_iio_backend_fwnode_get(struct device *dev, con
}
fwnode_back = fwnode_find_reference(fwnode, "io-backends", index);
- if (IS_ERR(fwnode))
- return dev_err_cast_probe(dev, fwnode,
+ if (IS_ERR(fwnode_back))
+ return dev_err_cast_probe(dev, fwnode_back,
"Cannot get Firmware reference\n");
guard(mutex)(&iio_back_lock);
@@ -775,7 +853,7 @@ struct iio_backend *devm_iio_backend_get(struct device *dev, const char *name)
{
return __devm_iio_backend_fwnode_get(dev, name, dev_fwnode(dev));
}
-EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(devm_iio_backend_get, "IIO_BACKEND");
/**
* devm_iio_backend_fwnode_get - Device managed backend firmware node get
@@ -794,7 +872,7 @@ struct iio_backend *devm_iio_backend_fwnode_get(struct device *dev,
{
return __devm_iio_backend_fwnode_get(dev, name, fwnode);
}
-EXPORT_SYMBOL_NS_GPL(devm_iio_backend_fwnode_get, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(devm_iio_backend_fwnode_get, "IIO_BACKEND");
/**
* __devm_iio_backend_get_from_fwnode_lookup - Device managed fwnode backend device get
@@ -829,7 +907,7 @@ __devm_iio_backend_get_from_fwnode_lookup(struct device *dev,
return ERR_PTR(-EPROBE_DEFER);
}
-EXPORT_SYMBOL_NS_GPL(__devm_iio_backend_get_from_fwnode_lookup, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(__devm_iio_backend_get_from_fwnode_lookup, "IIO_BACKEND");
/**
* iio_backend_get_priv - Get driver private data
@@ -839,7 +917,7 @@ void *iio_backend_get_priv(const struct iio_backend *back)
{
return back->priv;
}
-EXPORT_SYMBOL_NS_GPL(iio_backend_get_priv, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(iio_backend_get_priv, "IIO_BACKEND");
static void iio_backend_unregister(void *arg)
{
@@ -888,7 +966,7 @@ int devm_iio_backend_register(struct device *dev,
return devm_add_action_or_reset(dev, iio_backend_unregister, back);
}
-EXPORT_SYMBOL_NS_GPL(devm_iio_backend_register, IIO_BACKEND);
+EXPORT_SYMBOL_NS_GPL(devm_iio_backend_register, "IIO_BACKEND");
MODULE_AUTHOR("Nuno Sa <nuno.sa@analog.com>");
MODULE_DESCRIPTION("Framework to handle complex IIO aggregate devices");
diff --git a/drivers/iio/industrialio-buffer.c b/drivers/iio/industrialio-buffer.c
index 8104696cd475..2708f87df719 100644
--- a/drivers/iio/industrialio-buffer.c
+++ b/drivers/iio/industrialio-buffer.c
@@ -36,7 +36,7 @@
#define DMABUF_ENQUEUE_TIMEOUT_MS 5000
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
struct iio_dmabuf_priv {
struct list_head entry;
diff --git a/drivers/iio/industrialio-core.c b/drivers/iio/industrialio-core.c
index 6a6568d4a2cb..a2117ad1337d 100644
--- a/drivers/iio/industrialio-core.c
+++ b/drivers/iio/industrialio-core.c
@@ -95,6 +95,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_DELTA_VELOCITY] = "deltavelocity",
[IIO_COLORTEMP] = "colortemp",
[IIO_CHROMATICITY] = "chromaticity",
+ [IIO_ATTENTION] = "attention",
};
static const char * const iio_modifier_names[] = {
@@ -1665,7 +1666,7 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv)
indio_dev = &iio_dev_opaque->indio_dev;
if (sizeof_priv)
- indio_dev->priv = (char *)iio_dev_opaque +
+ ACCESS_PRIVATE(indio_dev, priv) = (char *)iio_dev_opaque +
ALIGN(sizeof(*iio_dev_opaque), IIO_DMA_MINALIGN);
indio_dev->dev.parent = parent;
diff --git a/drivers/iio/industrialio-gts-helper.c b/drivers/iio/industrialio-gts-helper.c
index 5f131bc1a01e..3b5a99815062 100644
--- a/drivers/iio/industrialio-gts-helper.c
+++ b/drivers/iio/industrialio-gts-helper.c
@@ -134,7 +134,7 @@ int iio_gts_total_gain_to_scale(struct iio_gts *gts, int total_gain,
return iio_gts_delinearize(tmp, NANO, scale_int, scale_nano);
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_total_gain_to_scale, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_total_gain_to_scale, "IIO_GTS_HELPER");
/**
* iio_gts_purge_avail_scale_table - free-up the available scale tables
@@ -167,7 +167,7 @@ static int iio_gts_gain_cmp(const void *a, const void *b)
static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
{
- int ret, i, j, new_idx, time_idx;
+ int i, j, new_idx, time_idx, ret = 0;
int *all_gains;
size_t gain_bytes;
@@ -205,7 +205,7 @@ static int gain_to_scaletables(struct iio_gts *gts, int **gains, int **scales)
memcpy(all_gains, gains[time_idx], gain_bytes);
new_idx = gts->num_hwgain;
- while (time_idx--) {
+ while (time_idx-- > 0) {
for (j = 0; j < gts->num_hwgain; j++) {
int candidate = gains[time_idx][j];
int chk;
@@ -622,7 +622,7 @@ int devm_iio_init_iio_gts(struct device *dev, int max_scale_int, int max_scale_n
return devm_iio_gts_build_avail_tables(dev, gts);
}
-EXPORT_SYMBOL_NS_GPL(devm_iio_init_iio_gts, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(devm_iio_init_iio_gts, "IIO_GTS_HELPER");
/**
* iio_gts_all_avail_scales - helper for listing all available scales
@@ -645,7 +645,7 @@ int iio_gts_all_avail_scales(struct iio_gts *gts, const int **vals, int *type,
return IIO_AVAIL_LIST;
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_all_avail_scales, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_all_avail_scales, "IIO_GTS_HELPER");
/**
* iio_gts_avail_scales_for_time - list scales for integration time
@@ -679,7 +679,7 @@ int iio_gts_avail_scales_for_time(struct iio_gts *gts, int time,
return IIO_AVAIL_LIST;
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_avail_scales_for_time, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_avail_scales_for_time, "IIO_GTS_HELPER");
/**
* iio_gts_avail_times - helper for listing available integration times
@@ -702,7 +702,7 @@ int iio_gts_avail_times(struct iio_gts *gts, const int **vals, int *type,
return IIO_AVAIL_LIST;
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_avail_times, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_avail_times, "IIO_GTS_HELPER");
/**
* iio_gts_find_sel_by_gain - find selector corresponding to a HW-gain
@@ -722,7 +722,7 @@ int iio_gts_find_sel_by_gain(struct iio_gts *gts, int gain)
return -EINVAL;
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_find_sel_by_gain, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_find_sel_by_gain, "IIO_GTS_HELPER");
/**
* iio_gts_find_gain_by_sel - find HW-gain corresponding to a selector
@@ -742,7 +742,7 @@ int iio_gts_find_gain_by_sel(struct iio_gts *gts, int sel)
return -EINVAL;
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_find_gain_by_sel, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_find_gain_by_sel, "IIO_GTS_HELPER");
/**
* iio_gts_get_min_gain - find smallest valid HW-gain
@@ -765,7 +765,7 @@ int iio_gts_get_min_gain(struct iio_gts *gts)
return min;
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_get_min_gain, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_get_min_gain, "IIO_GTS_HELPER");
/**
* iio_find_closest_gain_low - Find the closest lower matching gain
@@ -826,7 +826,7 @@ int iio_find_closest_gain_low(struct iio_gts *gts, int gain, bool *in_range)
return gts->hwgain_table[best].gain;
}
-EXPORT_SYMBOL_NS_GPL(iio_find_closest_gain_low, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_find_closest_gain_low, "IIO_GTS_HELPER");
static int iio_gts_get_int_time_gain_multiplier_by_sel(struct iio_gts *gts,
int sel)
@@ -913,7 +913,7 @@ int iio_gts_find_gain_sel_for_scale_using_time(struct iio_gts *gts, int time_sel
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_find_gain_sel_for_scale_using_time, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_find_gain_sel_for_scale_using_time, "IIO_GTS_HELPER");
static int iio_gts_get_total_gain(struct iio_gts *gts, int gain, int time)
{
@@ -975,7 +975,7 @@ int iio_gts_get_scale(struct iio_gts *gts, int gain, int time, int *scale_int,
return iio_gts_delinearize(lin_scale, NANO, scale_int, scale_nano);
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_get_scale, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_get_scale, "IIO_GTS_HELPER");
/**
* iio_gts_find_new_gain_sel_by_old_gain_time - compensate for time change
@@ -1032,7 +1032,7 @@ int iio_gts_find_new_gain_sel_by_old_gain_time(struct iio_gts *gts,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_find_new_gain_sel_by_old_gain_time, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_find_new_gain_sel_by_old_gain_time, "IIO_GTS_HELPER");
/**
* iio_gts_find_new_gain_by_old_gain_time - compensate for time change
@@ -1084,7 +1084,7 @@ int iio_gts_find_new_gain_by_old_gain_time(struct iio_gts *gts, int old_gain,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iio_gts_find_new_gain_by_old_gain_time, IIO_GTS_HELPER);
+EXPORT_SYMBOL_NS_GPL(iio_gts_find_new_gain_by_old_gain_time, "IIO_GTS_HELPER");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>");
diff --git a/drivers/iio/inkern.c b/drivers/iio/inkern.c
index 151099be2863..136b225b6bc8 100644
--- a/drivers/iio/inkern.c
+++ b/drivers/iio/inkern.c
@@ -20,7 +20,7 @@
struct iio_map_internal {
struct iio_dev *indio_dev;
- struct iio_map *map;
+ const struct iio_map *map;
struct list_head l;
};
@@ -42,7 +42,7 @@ static int iio_map_array_unregister_locked(struct iio_dev *indio_dev)
return ret;
}
-int iio_map_array_register(struct iio_dev *indio_dev, struct iio_map *maps)
+int iio_map_array_register(struct iio_dev *indio_dev, const struct iio_map *maps)
{
struct iio_map_internal *mapi;
int i = 0;
@@ -86,7 +86,8 @@ static void iio_map_array_unregister_cb(void *indio_dev)
iio_map_array_unregister(indio_dev);
}
-int devm_iio_map_array_register(struct device *dev, struct iio_dev *indio_dev, struct iio_map *maps)
+int devm_iio_map_array_register(struct device *dev, struct iio_dev *indio_dev,
+ const struct iio_map *maps)
{
int ret;
@@ -269,7 +270,7 @@ struct iio_channel *fwnode_iio_channel_get_by_name(struct fwnode_handle *fwnode,
return ERR_PTR(-ENODEV);
}
- chan = __fwnode_iio_channel_get_by_name(fwnode, name);
+ chan = __fwnode_iio_channel_get_by_name(parent, name);
if (!IS_ERR(chan) || PTR_ERR(chan) != -ENODEV) {
fwnode_handle_put(parent);
return chan;
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index f2f3e414849a..29ffa8491927 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -248,7 +248,6 @@ config SENSORS_ISL29018
tristate "Intersil 29018 light and proximity sensor"
depends on I2C
select REGMAP_I2C
- default n
help
If you say yes here you get support for ambient light sensing and
proximity infrared sensing from Intersil ISL29018.
@@ -476,7 +475,7 @@ config OPT3001
depends on I2C
help
If you say Y or M here, you get support for Texas Instruments
- OPT3001 Ambient Light Sensor.
+ OPT3001 Ambient Light Sensor, OPT3002 Light-to-Digital Sensor.
If built as a dynamically linked module, it will be called
opt3001.
@@ -670,13 +669,24 @@ config VCNL4035
To compile this driver as a module, choose M here: the
module will be called vcnl4035.
+config VEML3235
+ tristate "VEML3235 ambient light sensor"
+ select REGMAP_I2C
+ depends on I2C
+ help
+ Say Y here if you want to build a driver for the Vishay VEML3235
+ ambient light sensor.
+
+ To compile this driver as a module, choose M here: the
+ module will be called veml3235.
+
config VEML6030
- tristate "VEML6030 ambient light sensor"
+ tristate "VEML6030 and VEML6035 ambient light sensors"
select REGMAP_I2C
depends on I2C
help
Say Y here if you want to build a driver for the Vishay VEML6030
- ambient light sensor (ALS).
+ and VEML6035 ambient light sensors (ALS).
To compile this driver as a module, choose M here: the
module will be called veml6030.
diff --git a/drivers/iio/light/Makefile b/drivers/iio/light/Makefile
index 321010fc0b93..f14a37442712 100644
--- a/drivers/iio/light/Makefile
+++ b/drivers/iio/light/Makefile
@@ -62,6 +62,7 @@ obj-$(CONFIG_TSL4531) += tsl4531.o
obj-$(CONFIG_US5182D) += us5182d.o
obj-$(CONFIG_VCNL4000) += vcnl4000.o
obj-$(CONFIG_VCNL4035) += vcnl4035.o
+obj-$(CONFIG_VEML3235) += veml3235.o
obj-$(CONFIG_VEML6030) += veml6030.o
obj-$(CONFIG_VEML6040) += veml6040.o
obj-$(CONFIG_VEML6070) += veml6070.o
diff --git a/drivers/iio/light/adux1020.c b/drivers/iio/light/adux1020.c
index 2e0170be077a..593d614b1689 100644
--- a/drivers/iio/light/adux1020.c
+++ b/drivers/iio/light/adux1020.c
@@ -502,7 +502,8 @@ fail:
static int adux1020_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct adux1020_data *data = iio_priv(indio_dev);
int ret, mask;
@@ -526,12 +527,11 @@ static int adux1020_write_event_config(struct iio_dev *indio_dev,
mask = ADUX1020_PROX_OFF1_INT;
if (state)
- state = 0;
+ ret = regmap_clear_bits(data->regmap,
+ ADUX1020_REG_INT_MASK, mask);
else
- state = mask;
-
- ret = regmap_update_bits(data->regmap, ADUX1020_REG_INT_MASK,
- mask, state);
+ ret = regmap_set_bits(data->regmap,
+ ADUX1020_REG_INT_MASK, mask);
if (ret < 0)
goto fail;
diff --git a/drivers/iio/light/al3010.c b/drivers/iio/light/al3010.c
index 53569587ccb7..7cbb8b203300 100644
--- a/drivers/iio/light/al3010.c
+++ b/drivers/iio/light/al3010.c
@@ -87,7 +87,12 @@ static int al3010_init(struct al3010_data *data)
int ret;
ret = al3010_set_pwr(data->client, true);
+ if (ret < 0)
+ return ret;
+ ret = devm_add_action_or_reset(&data->client->dev,
+ al3010_set_pwr_off,
+ data);
if (ret < 0)
return ret;
@@ -190,12 +195,6 @@ static int al3010_probe(struct i2c_client *client)
return ret;
}
- ret = devm_add_action_or_reset(&client->dev,
- al3010_set_pwr_off,
- data);
- if (ret < 0)
- return ret;
-
return devm_iio_device_register(&client->dev, indio_dev);
}
diff --git a/drivers/iio/light/apds9300.c b/drivers/iio/light/apds9300.c
index 11f2ab4ca261..938d76f7e312 100644
--- a/drivers/iio/light/apds9300.c
+++ b/drivers/iio/light/apds9300.c
@@ -46,10 +46,10 @@
struct apds9300_data {
struct i2c_client *client;
struct mutex mutex;
- int power_state;
+ bool power_state;
int thresh_low;
int thresh_hi;
- int intr_en;
+ bool intr_en;
};
/* Lux calculation */
@@ -148,7 +148,7 @@ static int apds9300_set_thresh_hi(struct apds9300_data *data, int value)
return 0;
}
-static int apds9300_set_intr_state(struct apds9300_data *data, int state)
+static int apds9300_set_intr_state(struct apds9300_data *data, bool state)
{
int ret;
u8 cmd;
@@ -169,7 +169,7 @@ static int apds9300_set_intr_state(struct apds9300_data *data, int state)
return 0;
}
-static int apds9300_set_power_state(struct apds9300_data *data, int state)
+static int apds9300_set_power_state(struct apds9300_data *data, bool state)
{
int ret;
u8 cmd;
@@ -221,7 +221,7 @@ static int apds9300_chip_init(struct apds9300_data *data)
* Disable interrupt to ensure thai it is doesn't enable
* i.e. after device soft reset
*/
- ret = apds9300_set_intr_state(data, 0);
+ ret = apds9300_set_intr_state(data, false);
if (ret < 0)
goto err;
@@ -321,7 +321,7 @@ static int apds9300_read_interrupt_config(struct iio_dev *indio_dev,
static int apds9300_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct apds9300_data *data = iio_priv(indio_dev);
int ret;
@@ -459,8 +459,8 @@ static void apds9300_remove(struct i2c_client *client)
iio_device_unregister(indio_dev);
/* Ensure that power off and interrupts are disabled */
- apds9300_set_intr_state(data, 0);
- apds9300_set_power_state(data, 0);
+ apds9300_set_intr_state(data, false);
+ apds9300_set_power_state(data, false);
}
static int apds9300_suspend(struct device *dev)
@@ -470,7 +470,7 @@ static int apds9300_suspend(struct device *dev)
int ret;
mutex_lock(&data->mutex);
- ret = apds9300_set_power_state(data, 0);
+ ret = apds9300_set_power_state(data, false);
mutex_unlock(&data->mutex);
return ret;
@@ -483,7 +483,7 @@ static int apds9300_resume(struct device *dev)
int ret;
mutex_lock(&data->mutex);
- ret = apds9300_set_power_state(data, 1);
+ ret = apds9300_set_power_state(data, true);
mutex_unlock(&data->mutex);
return ret;
diff --git a/drivers/iio/light/apds9306.c b/drivers/iio/light/apds9306.c
index 079e02be1005..69a0d609cffc 100644
--- a/drivers/iio/light/apds9306.c
+++ b/drivers/iio/light/apds9306.c
@@ -1071,7 +1071,7 @@ static int apds9306_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct apds9306_data *data = iio_priv(indio_dev);
struct apds9306_regfields *rf = &data->rf;
@@ -1125,10 +1125,7 @@ static int apds9306_write_event_config(struct iio_dev *indio_dev,
}
}
case IIO_EV_TYPE_THRESH_ADAPTIVE:
- if (state)
- return regmap_field_write(rf->int_thresh_var_en, 1);
- else
- return regmap_field_write(rf->int_thresh_var_en, 0);
+ return regmap_field_write(rf->int_thresh_var_en, state);
default:
return -EINVAL;
}
@@ -1358,4 +1355,4 @@ module_i2c_driver(apds9306_driver);
MODULE_AUTHOR("Subhajit Ghosh <subhajit.ghosh@tweaklogic.com>");
MODULE_DESCRIPTION("APDS9306 Ambient Light Sensor driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_GTS_HELPER);
+MODULE_IMPORT_NS("IIO_GTS_HELPER");
diff --git a/drivers/iio/light/apds9960.c b/drivers/iio/light/apds9960.c
index 3c14e4c30805..d30441d33703 100644
--- a/drivers/iio/light/apds9960.c
+++ b/drivers/iio/light/apds9960.c
@@ -133,8 +133,8 @@ struct apds9960_data {
struct regmap_field *reg_enable_pxs;
/* state */
- int als_int;
- int pxs_int;
+ bool als_int;
+ bool pxs_int;
int gesture_mode_running;
/* gain values */
@@ -749,21 +749,17 @@ static int apds9960_read_event_config(struct iio_dev *indio_dev,
default:
return -EINVAL;
}
-
- return 0;
}
static int apds9960_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct apds9960_data *data = iio_priv(indio_dev);
int ret;
- state = !!state;
-
switch (chan->type) {
case IIO_PROXIMITY:
if (data->pxs_int == state)
diff --git a/drivers/iio/light/bh1745.c b/drivers/iio/light/bh1745.c
index 2e458e9d5d85..56e32689bb97 100644
--- a/drivers/iio/light/bh1745.c
+++ b/drivers/iio/light/bh1745.c
@@ -638,46 +638,42 @@ static int bh1745_read_event_config(struct iio_dev *indio_dev,
static int bh1745_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct bh1745_data *data = iio_priv(indio_dev);
int value;
- if (state == 0)
+ if (!state)
return regmap_clear_bits(data->regmap,
BH1745_INTR, BH1745_INTR_ENABLE);
- if (state == 1) {
- /* Latch is always enabled when enabling interrupt */
- value = BH1745_INTR_ENABLE;
+ /* Latch is always enabled when enabling interrupt */
+ value = BH1745_INTR_ENABLE;
- switch (chan->channel2) {
- case IIO_MOD_LIGHT_RED:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_RED));
+ switch (chan->channel2) {
+ case IIO_MOD_LIGHT_RED:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_RED));
- case IIO_MOD_LIGHT_GREEN:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_GREEN));
+ case IIO_MOD_LIGHT_GREEN:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_GREEN));
- case IIO_MOD_LIGHT_BLUE:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_BLUE));
+ case IIO_MOD_LIGHT_BLUE:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_BLUE));
- case IIO_MOD_LIGHT_CLEAR:
- return regmap_write(data->regmap, BH1745_INTR,
- value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
- BH1745_INTR_SOURCE_CLEAR));
+ case IIO_MOD_LIGHT_CLEAR:
+ return regmap_write(data->regmap, BH1745_INTR,
+ value | FIELD_PREP(BH1745_INTR_SOURCE_MASK,
+ BH1745_INTR_SOURCE_CLEAR));
- default:
- return -EINVAL;
- }
+ default:
+ return -EINVAL;
}
-
- return -EINVAL;
}
static int bh1745_read_avail(struct iio_dev *indio_dev,
@@ -903,4 +899,4 @@ module_i2c_driver(bh1745_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mudit Sharma <muditsharma.info@gmail.com>");
MODULE_DESCRIPTION("BH1745 colour sensor driver");
-MODULE_IMPORT_NS(IIO_GTS_HELPER);
+MODULE_IMPORT_NS("IIO_GTS_HELPER");
diff --git a/drivers/iio/light/cm32181.c b/drivers/iio/light/cm32181.c
index 9df85b3999fa..aeae0566ec12 100644
--- a/drivers/iio/light/cm32181.c
+++ b/drivers/iio/light/cm32181.c
@@ -217,8 +217,7 @@ static int cm32181_reg_init(struct cm32181_chip *cm32181)
cm32181->lux_per_bit = CM32181_LUX_PER_BIT;
cm32181->lux_per_bit_base_it = CM32181_LUX_PER_BIT_BASE_IT;
- if (ACPI_HANDLE(cm32181->dev))
- cm32181_acpi_parse_cpm_tables(cm32181);
+ cm32181_acpi_parse_cpm_tables(cm32181);
/* Initialize registers*/
for_each_set_bit(i, &cm32181->init_regs_bitmap, CM32181_CONF_REG_NUM) {
diff --git a/drivers/iio/light/cm3605.c b/drivers/iio/light/cm3605.c
index 22a63a89f289..675c0fd44db4 100644
--- a/drivers/iio/light/cm3605.c
+++ b/drivers/iio/light/cm3605.c
@@ -318,7 +318,7 @@ static struct platform_driver cm3605_driver = {
.pm = pm_sleep_ptr(&cm3605_dev_pm_ops),
},
.probe = cm3605_probe,
- .remove_new = cm3605_remove,
+ .remove = cm3605_remove,
};
module_platform_driver(cm3605_driver);
diff --git a/drivers/iio/light/cm36651.c b/drivers/iio/light/cm36651.c
index a4a1505534c0..ae3fc3299eec 100644
--- a/drivers/iio/light/cm36651.c
+++ b/drivers/iio/light/cm36651.c
@@ -529,7 +529,7 @@ static int cm36651_write_prox_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct cm36651_data *cm36651 = iio_priv(indio_dev);
int cmd, ret;
diff --git a/drivers/iio/light/gp2ap002.c b/drivers/iio/light/gp2ap002.c
index f8b1d7dd6f5f..d56ee217fe53 100644
--- a/drivers/iio/light/gp2ap002.c
+++ b/drivers/iio/light/gp2ap002.c
@@ -340,7 +340,7 @@ static int gp2ap002_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct gp2ap002 *gp2ap002 = iio_priv(indio_dev);
diff --git a/drivers/iio/light/gp2ap020a00f.c b/drivers/iio/light/gp2ap020a00f.c
index 81e718cdeae3..1a352c88598e 100644
--- a/drivers/iio/light/gp2ap020a00f.c
+++ b/drivers/iio/light/gp2ap020a00f.c
@@ -1159,7 +1159,7 @@ static int gp2ap020a00f_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct gp2ap020a00f_data *data = iio_priv(indio_dev);
enum gp2ap020a00f_cmd cmd;
diff --git a/drivers/iio/light/hid-sensor-als.c b/drivers/iio/light/hid-sensor-als.c
index 260281194f61..aa4c72d4849e 100644
--- a/drivers/iio/light/hid-sensor-als.c
+++ b/drivers/iio/light/hid-sensor-als.c
@@ -31,7 +31,7 @@ struct als_state {
struct iio_chan_spec channels[CHANNEL_SCAN_INDEX_MAX + 1];
struct {
u32 illum[CHANNEL_SCAN_INDEX_MAX];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -356,11 +356,11 @@ static int als_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_als_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "als";
struct iio_dev *indio_dev;
struct als_state *als_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev, sizeof(struct als_state));
if (!indio_dev)
@@ -438,7 +438,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_als_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct als_state *als_state = iio_priv(indio_dev);
@@ -467,11 +467,11 @@ static struct platform_driver hid_als_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_als_probe,
- .remove_new = hid_als_remove,
+ .remove = hid_als_remove,
};
module_platform_driver(hid_als_platform_driver);
MODULE_DESCRIPTION("HID Sensor ALS");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/light/hid-sensor-prox.c b/drivers/iio/light/hid-sensor-prox.c
index 26c481d2998c..c83acbd78275 100644
--- a/drivers/iio/light/hid-sensor-prox.c
+++ b/drivers/iio/light/hid-sensor-prox.c
@@ -13,16 +13,32 @@
#include <linux/iio/buffer.h>
#include "../common/hid-sensors/hid-sensor-trigger.h"
-#define CHANNEL_SCAN_INDEX_PRESENCE 0
+static const u32 prox_usage_ids[] = {
+ HID_USAGE_SENSOR_HUMAN_PRESENCE,
+ HID_USAGE_SENSOR_HUMAN_PROXIMITY,
+ HID_USAGE_SENSOR_HUMAN_ATTENTION,
+};
+
+#define MAX_CHANNELS ARRAY_SIZE(prox_usage_ids)
+
+enum {
+ HID_HUMAN_PRESENCE,
+ HID_HUMAN_PROXIMITY,
+ HID_HUMAN_ATTENTION,
+};
struct prox_state {
struct hid_sensor_hub_callbacks callbacks;
struct hid_sensor_common common_attributes;
- struct hid_sensor_hub_attribute_info prox_attr;
- u32 human_presence;
+ struct hid_sensor_hub_attribute_info prox_attr[MAX_CHANNELS];
+ struct iio_chan_spec channels[MAX_CHANNELS];
+ u32 channel2usage[MAX_CHANNELS];
+ u32 human_presence[MAX_CHANNELS];
int scale_pre_decml;
int scale_post_decml;
int scale_precision;
+ unsigned long scan_mask[2]; /* One entry plus one terminator. */
+ int num_channels;
};
static const u32 prox_sensitivity_addresses[] = {
@@ -30,17 +46,24 @@ static const u32 prox_sensitivity_addresses[] = {
HID_USAGE_SENSOR_DATA_PRESENCE,
};
-/* Channel definitions */
-static const struct iio_chan_spec prox_channels[] = {
- {
- .type = IIO_PROXIMITY,
- .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |
- BIT(IIO_CHAN_INFO_SCALE) |
- BIT(IIO_CHAN_INFO_SAMP_FREQ) |
- BIT(IIO_CHAN_INFO_HYSTERESIS),
- .scan_index = CHANNEL_SCAN_INDEX_PRESENCE,
+#define PROX_CHANNEL(_is_proximity, _channel) \
+ {\
+ .type = _is_proximity ? IIO_PROXIMITY : IIO_ATTENTION,\
+ .info_mask_separate = _is_proximity ? BIT(IIO_CHAN_INFO_RAW) :\
+ BIT(IIO_CHAN_INFO_PROCESSED),\
+ .info_mask_shared_by_type = BIT(IIO_CHAN_INFO_OFFSET) |\
+ BIT(IIO_CHAN_INFO_SCALE) |\
+ BIT(IIO_CHAN_INFO_SAMP_FREQ) |\
+ BIT(IIO_CHAN_INFO_HYSTERESIS),\
+ .indexed = _is_proximity,\
+ .channel = _channel,\
}
+
+/* Channel definitions (same order as prox_usage_ids) */
+static const struct iio_chan_spec prox_channels[] = {
+ PROX_CHANNEL(true, HID_HUMAN_PRESENCE),
+ PROX_CHANNEL(true, HID_HUMAN_PROXIMITY),
+ PROX_CHANNEL(false, 0),
};
/* Adjust channel real bits based on report descriptor */
@@ -62,7 +85,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
{
struct prox_state *prox_state = iio_priv(indio_dev);
struct hid_sensor_hub_device *hsdev;
- int report_id = -1;
+ int report_id;
u32 address;
int ret_type;
s32 min;
@@ -71,29 +94,23 @@ static int prox_read_raw(struct iio_dev *indio_dev,
*val2 = 0;
switch (mask) {
case IIO_CHAN_INFO_RAW:
- switch (chan->scan_index) {
- case CHANNEL_SCAN_INDEX_PRESENCE:
- report_id = prox_state->prox_attr.report_id;
- min = prox_state->prox_attr.logical_minimum;
- address = HID_USAGE_SENSOR_HUMAN_PRESENCE;
- hsdev = prox_state->common_attributes.hsdev;
- break;
- default:
- report_id = -1;
- break;
- }
- if (report_id >= 0) {
- hid_sensor_power_state(&prox_state->common_attributes,
- true);
- *val = sensor_hub_input_attr_get_raw_value(
- hsdev, hsdev->usage, address, report_id,
- SENSOR_HUB_SYNC, min < 0);
- hid_sensor_power_state(&prox_state->common_attributes,
- false);
- } else {
- *val = 0;
+ if (chan->scan_index >= prox_state->num_channels)
return -EINVAL;
- }
+ address = prox_state->channel2usage[chan->scan_index];
+ report_id = prox_state->prox_attr[chan->scan_index].report_id;
+ hsdev = prox_state->common_attributes.hsdev;
+ min = prox_state->prox_attr[chan->scan_index].logical_minimum;
+ hid_sensor_power_state(&prox_state->common_attributes, true);
+ *val = sensor_hub_input_attr_get_raw_value(hsdev,
+ hsdev->usage,
+ address,
+ report_id,
+ SENSOR_HUB_SYNC,
+ min < 0);
+ if (prox_state->channel2usage[chan->scan_index] ==
+ HID_USAGE_SENSOR_HUMAN_ATTENTION)
+ *val *= 100;
+ hid_sensor_power_state(&prox_state->common_attributes, false);
ret_type = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SCALE:
@@ -103,7 +120,7 @@ static int prox_read_raw(struct iio_dev *indio_dev,
break;
case IIO_CHAN_INFO_OFFSET:
*val = hid_sensor_convert_exponent(
- prox_state->prox_attr.unit_expo);
+ prox_state->prox_attr[chan->scan_index].unit_expo);
ret_type = IIO_VAL_INT;
break;
case IIO_CHAN_INFO_SAMP_FREQ:
@@ -153,14 +170,6 @@ static const struct iio_info prox_info = {
.write_raw = &prox_write_raw,
};
-/* Function to push data to buffer */
-static void hid_sensor_push_data(struct iio_dev *indio_dev, const void *data,
- int len)
-{
- dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
- iio_push_to_buffers(indio_dev, data);
-}
-
/* Callback handler to send event after all samples are received and captured */
static int prox_proc_event(struct hid_sensor_hub_device *hsdev,
unsigned usage_id,
@@ -170,10 +179,10 @@ static int prox_proc_event(struct hid_sensor_hub_device *hsdev,
struct prox_state *prox_state = iio_priv(indio_dev);
dev_dbg(&indio_dev->dev, "prox_proc_event\n");
- if (atomic_read(&prox_state->common_attributes.data_ready))
- hid_sensor_push_data(indio_dev,
- &prox_state->human_presence,
- sizeof(prox_state->human_presence));
+ if (atomic_read(&prox_state->common_attributes.data_ready)) {
+ dev_dbg(&indio_dev->dev, "hid_sensor_push_data\n");
+ iio_push_to_buffers(indio_dev, &prox_state->human_presence);
+ }
return 0;
}
@@ -186,58 +195,77 @@ static int prox_capture_sample(struct hid_sensor_hub_device *hsdev,
{
struct iio_dev *indio_dev = platform_get_drvdata(priv);
struct prox_state *prox_state = iio_priv(indio_dev);
- int ret = -EINVAL;
-
- switch (usage_id) {
- case HID_USAGE_SENSOR_HUMAN_PRESENCE:
- switch (raw_len) {
- case 1:
- prox_state->human_presence = *(u8 *)raw_data;
- return 0;
- case 4:
- prox_state->human_presence = *(u32 *)raw_data;
- return 0;
- default:
+ int multiplier = 1;
+ int chan;
+
+ for (chan = 0; chan < prox_state->num_channels; chan++)
+ if (prox_state->channel2usage[chan] == usage_id)
break;
- }
- break;
+ if (chan == prox_state->num_channels)
+ return -EINVAL;
+
+ if (usage_id == HID_USAGE_SENSOR_HUMAN_ATTENTION)
+ multiplier = 100;
+
+ switch (raw_len) {
+ case 1:
+ prox_state->human_presence[chan] = *(u8 *)raw_data * multiplier;
+ return 0;
+ case 4:
+ prox_state->human_presence[chan] = *(u32 *)raw_data * multiplier;
+ return 0;
}
- return ret;
+ return -EINVAL;
}
/* Parse report which is specific to an usage id*/
static int prox_parse_report(struct platform_device *pdev,
struct hid_sensor_hub_device *hsdev,
- struct iio_chan_spec *channels,
- unsigned usage_id,
struct prox_state *st)
{
+ struct iio_chan_spec *channels = st->channels;
+ int index = 0;
int ret;
+ int i;
+
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ u32 usage_id = prox_usage_ids[i];
+
+ ret = sensor_hub_input_get_attribute_info(hsdev,
+ HID_INPUT_REPORT,
+ hsdev->usage,
+ usage_id,
+ &st->prox_attr[index]);
+ if (ret < 0)
+ continue;
+ st->channel2usage[index] = usage_id;
+ st->scan_mask[0] |= BIT(index);
+ channels[index] = prox_channels[i];
+ channels[index].scan_index = index;
+ prox_adjust_channel_bit_mask(channels, index,
+ st->prox_attr[index].size);
+ dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr[index].index,
+ st->prox_attr[index].report_id);
+ index++;
+ }
- ret = sensor_hub_input_get_attribute_info(hsdev, HID_INPUT_REPORT,
- usage_id,
- HID_USAGE_SENSOR_HUMAN_PRESENCE,
- &st->prox_attr);
- if (ret < 0)
+ if (!index)
return ret;
- prox_adjust_channel_bit_mask(channels, CHANNEL_SCAN_INDEX_PRESENCE,
- st->prox_attr.size);
- dev_dbg(&pdev->dev, "prox %x:%x\n", st->prox_attr.index,
- st->prox_attr.report_id);
+ st->num_channels = index;
- return ret;
+ return 0;
}
/* Function to initialize the processing for usage id */
static int hid_prox_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "prox";
struct iio_dev *indio_dev;
struct prox_state *prox_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct prox_state));
@@ -258,22 +286,15 @@ static int hid_prox_probe(struct platform_device *pdev)
return ret;
}
- indio_dev->channels = devm_kmemdup(&pdev->dev, prox_channels,
- sizeof(prox_channels), GFP_KERNEL);
- if (!indio_dev->channels) {
- dev_err(&pdev->dev, "failed to duplicate channels\n");
- return -ENOMEM;
- }
-
- ret = prox_parse_report(pdev, hsdev,
- (struct iio_chan_spec *)indio_dev->channels,
- hsdev->usage, prox_state);
+ ret = prox_parse_report(pdev, hsdev, prox_state);
if (ret) {
dev_err(&pdev->dev, "failed to setup attributes\n");
return ret;
}
- indio_dev->num_channels = ARRAY_SIZE(prox_channels);
+ indio_dev->num_channels = prox_state->num_channels;
+ indio_dev->channels = prox_state->channels;
+ indio_dev->available_scan_masks = prox_state->scan_mask;
indio_dev->info = &prox_info;
indio_dev->name = name;
indio_dev->modes = INDIO_DIRECT_MODE;
@@ -315,7 +336,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_prox_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct prox_state *prox_state = iio_priv(indio_dev);
@@ -344,11 +365,11 @@ static struct platform_driver hid_prox_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_prox_probe,
- .remove_new = hid_prox_remove,
+ .remove = hid_prox_remove,
};
module_platform_driver(hid_prox_platform_driver);
MODULE_DESCRIPTION("HID Sensor Proximity");
MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/light/iqs621-als.c b/drivers/iio/light/iqs621-als.c
index 6de33feada3a..b9f230210f07 100644
--- a/drivers/iio/light/iqs621-als.c
+++ b/drivers/iio/light/iqs621-als.c
@@ -271,7 +271,7 @@ static int iqs621_als_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct iqs621_als_private *iqs621_als = iio_priv(indio_dev);
struct iqs62x_core *iqs62x = iqs621_als->iqs62x;
diff --git a/drivers/iio/light/isl29018.c b/drivers/iio/light/isl29018.c
index 8dfc750e68c0..201eae1c4589 100644
--- a/drivers/iio/light/isl29018.c
+++ b/drivers/iio/light/isl29018.c
@@ -8,17 +8,18 @@
* Copyright (c) 2010, NVIDIA Corporation.
*/
-#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/err.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/delay.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
-#include <linux/acpi.h>
#define ISL29018_CONV_TIME_MS 100
@@ -687,20 +688,6 @@ static const struct isl29018_chip_info isl29018_chip_info_tbl[] = {
},
};
-static const char *isl29018_match_acpi_device(struct device *dev, int *data)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
-
- if (!id)
- return NULL;
-
- *data = (int)id->driver_data;
-
- return dev_name(dev);
-}
-
static void isl29018_disable_regulator_action(void *_data)
{
struct isl29018_chip *chip = _data;
@@ -716,9 +703,10 @@ static int isl29018_probe(struct i2c_client *client)
const struct i2c_device_id *id = i2c_client_get_device_id(client);
struct isl29018_chip *chip;
struct iio_dev *indio_dev;
+ const void *ddata = NULL;
+ const char *name;
+ int dev_id;
int err;
- const char *name = NULL;
- int dev_id = 0;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*chip));
if (!indio_dev)
@@ -731,11 +719,11 @@ static int isl29018_probe(struct i2c_client *client)
if (id) {
name = id->name;
dev_id = id->driver_data;
+ } else {
+ name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
+ dev_id = (intptr_t)ddata;
}
- if (ACPI_HANDLE(&client->dev))
- name = isl29018_match_acpi_device(&client->dev, &dev_id);
-
mutex_init(&chip->lock);
chip->type = dev_id;
@@ -832,15 +820,13 @@ static int isl29018_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(isl29018_pm_ops, isl29018_suspend,
isl29018_resume);
-#ifdef CONFIG_ACPI
static const struct acpi_device_id isl29018_acpi_match[] = {
{"ISL29018", isl29018},
{"ISL29023", isl29023},
{"ISL29035", isl29035},
- {},
+ {}
};
MODULE_DEVICE_TABLE(acpi, isl29018_acpi_match);
-#endif
static const struct i2c_device_id isl29018_id[] = {
{"isl29018", isl29018},
@@ -854,14 +840,14 @@ static const struct of_device_id isl29018_of_match[] = {
{ .compatible = "isil,isl29018", },
{ .compatible = "isil,isl29023", },
{ .compatible = "isil,isl29035", },
- { },
+ { }
};
MODULE_DEVICE_TABLE(of, isl29018_of_match);
static struct i2c_driver isl29018_driver = {
.driver = {
.name = "isl29018",
- .acpi_match_table = ACPI_PTR(isl29018_acpi_match),
+ .acpi_match_table = isl29018_acpi_match,
.pm = pm_sleep_ptr(&isl29018_pm_ops),
.of_match_table = isl29018_of_match,
},
diff --git a/drivers/iio/light/lm3533-als.c b/drivers/iio/light/lm3533-als.c
index 7800f7fa51b7..99f0b903018c 100644
--- a/drivers/iio/light/lm3533-als.c
+++ b/drivers/iio/light/lm3533-als.c
@@ -754,7 +754,7 @@ static int lm3533_als_set_resistor(struct lm3533_als *als, u8 val)
}
static int lm3533_als_setup(struct lm3533_als *als,
- struct lm3533_als_platform_data *pdata)
+ const struct lm3533_als_platform_data *pdata)
{
int ret;
@@ -828,8 +828,8 @@ static const struct iio_info lm3533_als_info = {
static int lm3533_als_probe(struct platform_device *pdev)
{
+ const struct lm3533_als_platform_data *pdata;
struct lm3533 *lm3533;
- struct lm3533_als_platform_data *pdata;
struct lm3533_als *als;
struct iio_dev *indio_dev;
int ret;
@@ -838,7 +838,7 @@ static int lm3533_als_probe(struct platform_device *pdev)
if (!lm3533)
return -EINVAL;
- pdata = pdev->dev.platform_data;
+ pdata = dev_get_platdata(&pdev->dev);
if (!pdata) {
dev_err(&pdev->dev, "no platform data\n");
return -EINVAL;
@@ -912,7 +912,7 @@ static struct platform_driver lm3533_als_driver = {
.name = "lm3533-als",
},
.probe = lm3533_als_probe,
- .remove_new = lm3533_als_remove,
+ .remove = lm3533_als_remove,
};
module_platform_driver(lm3533_als_driver);
diff --git a/drivers/iio/light/ltr390.c b/drivers/iio/light/ltr390.c
index 4f6975e63a8f..df664f360903 100644
--- a/drivers/iio/light/ltr390.c
+++ b/drivers/iio/light/ltr390.c
@@ -18,14 +18,18 @@
* - Interrupt support
*/
+#include <linux/bitfield.h>
+#include <linux/device.h>
#include <linux/i2c.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
-#include <linux/bitfield.h>
#include <linux/iio/iio.h>
+#include <linux/iio/events.h>
#include <linux/unaligned.h>
@@ -33,18 +37,27 @@
#define LTR390_ALS_UVS_MEAS_RATE 0x04
#define LTR390_ALS_UVS_GAIN 0x05
#define LTR390_PART_ID 0x06
+#define LTR390_MAIN_STATUS 0x07
#define LTR390_ALS_DATA 0x0D
#define LTR390_UVS_DATA 0x10
#define LTR390_INT_CFG 0x19
+#define LTR390_INT_PST 0x1A
+#define LTR390_THRESH_UP 0x21
+#define LTR390_THRESH_LOW 0x24
#define LTR390_PART_NUMBER_ID 0xb
-#define LTR390_ALS_UVS_GAIN_MASK 0x07
-#define LTR390_ALS_UVS_INT_TIME_MASK 0x70
+#define LTR390_ALS_UVS_GAIN_MASK GENMASK(2, 0)
+#define LTR390_ALS_UVS_MEAS_RATE_MASK GENMASK(2, 0)
+#define LTR390_ALS_UVS_INT_TIME_MASK GENMASK(6, 4)
#define LTR390_ALS_UVS_INT_TIME(x) FIELD_PREP(LTR390_ALS_UVS_INT_TIME_MASK, (x))
+#define LTR390_INT_PST_MASK GENMASK(7, 4)
+#define LTR390_INT_PST_VAL(x) FIELD_PREP(LTR390_INT_PST_MASK, (x))
#define LTR390_SW_RESET BIT(4)
#define LTR390_UVS_MODE BIT(3)
#define LTR390_SENSOR_ENABLE BIT(1)
+#define LTR390_LS_INT_EN BIT(2)
+#define LTR390_LS_INT_SEL_UVS BIT(5)
#define LTR390_FRACTIONAL_PRECISION 100
@@ -70,6 +83,11 @@ enum ltr390_mode {
LTR390_SET_UVS_MODE,
};
+enum ltr390_meas_rate {
+ LTR390_GET_FREQ,
+ LTR390_GET_PERIOD,
+};
+
struct ltr390_data {
struct regmap *regmap;
struct i2c_client *client;
@@ -87,6 +105,18 @@ static const struct regmap_config ltr390_regmap_config = {
.val_bits = 8,
};
+/* Sampling frequency is in mili Hz and mili Seconds */
+static const int ltr390_samp_freq_table[][2] = {
+ [0] = { 40000, 25 },
+ [1] = { 20000, 50 },
+ [2] = { 10000, 100 },
+ [3] = { 5000, 200 },
+ [4] = { 2000, 500 },
+ [5] = { 1000, 1000 },
+ [6] = { 500, 2000 },
+ [7] = { 500, 2000 },
+};
+
static int ltr390_register_read(struct ltr390_data *data, u8 register_address)
{
struct device *dev = &data->client->dev;
@@ -135,6 +165,19 @@ static int ltr390_counts_per_uvi(struct ltr390_data *data)
return DIV_ROUND_CLOSEST(23 * data->gain * data->int_time_us, 10 * orig_gain * orig_int_time);
}
+static int ltr390_get_samp_freq_or_period(struct ltr390_data *data,
+ enum ltr390_meas_rate option)
+{
+ int ret, value;
+
+ ret = regmap_read(data->regmap, LTR390_ALS_UVS_MEAS_RATE, &value);
+ if (ret < 0)
+ return ret;
+ value = FIELD_GET(LTR390_ALS_UVS_MEAS_RATE_MASK, value);
+
+ return ltr390_samp_freq_table[value][option];
+}
+
static int ltr390_read_raw(struct iio_dev *iio_device,
struct iio_chan_spec const *chan, int *val,
int *val2, long mask)
@@ -191,6 +234,10 @@ static int ltr390_read_raw(struct iio_dev *iio_device,
*val = data->int_time_us;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *val = ltr390_get_samp_freq_or_period(data, LTR390_GET_FREQ);
+ return IIO_VAL_INT;
+
default:
return -EINVAL;
}
@@ -199,6 +246,24 @@ static int ltr390_read_raw(struct iio_dev *iio_device,
/* integration time in us */
static const int ltr390_int_time_map_us[] = { 400000, 200000, 100000, 50000, 25000, 12500 };
static const int ltr390_gain_map[] = { 1, 3, 6, 9, 18 };
+static const int ltr390_freq_map[] = { 40000, 20000, 10000, 5000, 2000, 1000, 500, 500 };
+
+static const struct iio_event_spec ltr390_event_spec[] = {
+ {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_RISING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE),
+ }, {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_FALLING,
+ .mask_separate = BIT(IIO_EV_INFO_VALUE),
+ }, {
+ .type = IIO_EV_TYPE_THRESH,
+ .dir = IIO_EV_DIR_EITHER,
+ .mask_separate = BIT(IIO_EV_INFO_ENABLE) |
+ BIT(IIO_EV_INFO_PERIOD),
+ }
+};
static const struct iio_chan_spec ltr390_channels[] = {
/* UV sensor */
@@ -206,16 +271,24 @@ static const struct iio_chan_spec ltr390_channels[] = {
.type = IIO_UVINDEX,
.scan_index = 0,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
- .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .event_spec = ltr390_event_spec,
+ .num_event_specs = ARRAY_SIZE(ltr390_event_spec),
},
/* ALS sensor */
{
.type = IIO_LIGHT,
.scan_index = 1,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | BIT(IIO_CHAN_INFO_SCALE),
- .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
- .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SCALE)
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) | BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .event_spec = ltr390_event_spec,
+ .num_event_specs = ARRAY_SIZE(ltr390_event_spec),
},
};
@@ -264,6 +337,23 @@ static int ltr390_set_int_time(struct ltr390_data *data, int val)
return -EINVAL;
}
+static int ltr390_set_samp_freq(struct ltr390_data *data, int val)
+{
+ int idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(ltr390_samp_freq_table); idx++) {
+ if (ltr390_samp_freq_table[idx][0] != val)
+ continue;
+
+ guard(mutex)(&data->lock);
+ return regmap_update_bits(data->regmap,
+ LTR390_ALS_UVS_MEAS_RATE,
+ LTR390_ALS_UVS_MEAS_RATE_MASK, idx);
+ }
+
+ return -EINVAL;
+}
+
static int ltr390_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec const *chan,
const int **vals, int *type, int *length, long mask)
{
@@ -278,6 +368,11 @@ static int ltr390_read_avail(struct iio_dev *indio_dev, struct iio_chan_spec con
*type = IIO_VAL_INT;
*vals = ltr390_int_time_map_us;
return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ *length = ARRAY_SIZE(ltr390_freq_map);
+ *type = IIO_VAL_INT;
+ *vals = ltr390_freq_map;
+ return IIO_AVAIL_LIST;
default:
return -EINVAL;
}
@@ -301,6 +396,191 @@ static int ltr390_write_raw(struct iio_dev *indio_dev, struct iio_chan_spec cons
return ltr390_set_int_time(data, val);
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ if (val2 != 0)
+ return -EINVAL;
+
+ return ltr390_set_samp_freq(data, val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_read_intr_prst(struct ltr390_data *data, int *val)
+{
+ int ret, prst, samp_period;
+
+ samp_period = ltr390_get_samp_freq_or_period(data, LTR390_GET_PERIOD);
+ ret = regmap_read(data->regmap, LTR390_INT_PST, &prst);
+ if (ret < 0)
+ return ret;
+ *val = prst * samp_period;
+
+ return IIO_VAL_INT;
+}
+
+static int ltr390_write_intr_prst(struct ltr390_data *data, int val)
+{
+ int ret, samp_period, new_val;
+
+ samp_period = ltr390_get_samp_freq_or_period(data, LTR390_GET_PERIOD);
+
+ /* persist period should be greater than or equal to samp period */
+ if (val < samp_period)
+ return -EINVAL;
+
+ new_val = DIV_ROUND_UP(val, samp_period);
+ if (new_val < 0 || new_val > 0x0f)
+ return -EINVAL;
+
+ guard(mutex)(&data->lock);
+ ret = regmap_update_bits(data->regmap,
+ LTR390_INT_PST,
+ LTR390_INT_PST_MASK,
+ LTR390_INT_PST_VAL(new_val));
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int ltr390_read_threshold(struct iio_dev *indio_dev,
+ enum iio_event_direction dir,
+ int *val, int *val2)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret;
+
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ ret = ltr390_register_read(data, LTR390_THRESH_UP);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+
+ case IIO_EV_DIR_FALLING:
+ ret = ltr390_register_read(data, LTR390_THRESH_LOW);
+ if (ret < 0)
+ return ret;
+ *val = ret;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_write_threshold(struct iio_dev *indio_dev,
+ enum iio_event_direction dir,
+ int val, int val2)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+
+ guard(mutex)(&data->lock);
+ switch (dir) {
+ case IIO_EV_DIR_RISING:
+ return regmap_bulk_write(data->regmap, LTR390_THRESH_UP, &val, 3);
+
+ case IIO_EV_DIR_FALLING:
+ return regmap_bulk_write(data->regmap, LTR390_THRESH_LOW, &val, 3);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_read_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int *val, int *val2)
+{
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ return ltr390_read_threshold(indio_dev, dir, val, val2);
+
+ case IIO_EV_INFO_PERIOD:
+ return ltr390_read_intr_prst(iio_priv(indio_dev), val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_write_event_value(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ enum iio_event_info info,
+ int val, int val2)
+{
+ switch (info) {
+ case IIO_EV_INFO_VALUE:
+ if (val2 != 0)
+ return -EINVAL;
+
+ return ltr390_write_threshold(indio_dev, dir, val, val2);
+
+ case IIO_EV_INFO_PERIOD:
+ if (val2 != 0)
+ return -EINVAL;
+
+ return ltr390_write_intr_prst(iio_priv(indio_dev), val);
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static int ltr390_read_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret, status;
+
+ ret = regmap_read(data->regmap, LTR390_INT_CFG, &status);
+ if (ret < 0)
+ return ret;
+
+ return FIELD_GET(LTR390_LS_INT_EN, status);
+}
+
+static int ltr390_write_event_config(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan,
+ enum iio_event_type type,
+ enum iio_event_direction dir,
+ bool state)
+{
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret;
+
+ if (!state)
+ return regmap_clear_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_EN);
+
+ guard(mutex)(&data->lock);
+ ret = regmap_set_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_EN);
+ if (ret < 0)
+ return ret;
+
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = ltr390_set_mode(data, LTR390_SET_ALS_MODE);
+ if (ret < 0)
+ return ret;
+
+ return regmap_clear_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_SEL_UVS);
+
+ case IIO_UVINDEX:
+ ret = ltr390_set_mode(data, LTR390_SET_UVS_MODE);
+ if (ret < 0)
+ return ret;
+
+ return regmap_set_bits(data->regmap, LTR390_INT_CFG, LTR390_LS_INT_SEL_UVS);
+
default:
return -EINVAL;
}
@@ -310,8 +590,44 @@ static const struct iio_info ltr390_info = {
.read_raw = ltr390_read_raw,
.write_raw = ltr390_write_raw,
.read_avail = ltr390_read_avail,
+ .read_event_value = ltr390_read_event_value,
+ .read_event_config = ltr390_read_event_config,
+ .write_event_value = ltr390_write_event_value,
+ .write_event_config = ltr390_write_event_config,
};
+static irqreturn_t ltr390_interrupt_handler(int irq, void *private)
+{
+ struct iio_dev *indio_dev = private;
+ struct ltr390_data *data = iio_priv(indio_dev);
+ int ret, status;
+
+ /* Reading the status register to clear the interrupt flag, Datasheet pg: 17*/
+ ret = regmap_read(data->regmap, LTR390_MAIN_STATUS, &status);
+ if (ret < 0)
+ return ret;
+
+ switch (data->mode) {
+ case LTR390_SET_ALS_MODE:
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ iio_get_time_ns(indio_dev));
+ break;
+
+ case LTR390_SET_UVS_MODE:
+ iio_push_event(indio_dev,
+ IIO_UNMOD_EVENT_CODE(IIO_UVINDEX, 0,
+ IIO_EV_TYPE_THRESH,
+ IIO_EV_DIR_EITHER),
+ iio_get_time_ns(indio_dev));
+ break;
+ }
+
+ return IRQ_HANDLED;
+}
+
static int ltr390_probe(struct i2c_client *client)
{
struct ltr390_data *data;
@@ -365,9 +681,40 @@ static int ltr390_probe(struct i2c_client *client)
if (ret)
return dev_err_probe(dev, ret, "failed to enable the sensor\n");
+ if (client->irq) {
+ ret = devm_request_threaded_irq(dev, client->irq,
+ NULL, ltr390_interrupt_handler,
+ IRQF_ONESHOT,
+ "ltr390_thresh_event",
+ indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "request irq (%d) failed\n", client->irq);
+ }
+
return devm_iio_device_register(dev, indio_dev);
}
+static int ltr390_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ltr390_data *data = iio_priv(indio_dev);
+
+ return regmap_clear_bits(data->regmap, LTR390_MAIN_CTRL,
+ LTR390_SENSOR_ENABLE);
+}
+
+static int ltr390_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct ltr390_data *data = iio_priv(indio_dev);
+
+ return regmap_set_bits(data->regmap, LTR390_MAIN_CTRL,
+ LTR390_SENSOR_ENABLE);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(ltr390_pm_ops, ltr390_suspend, ltr390_resume);
+
static const struct i2c_device_id ltr390_id[] = {
{ "ltr390" },
{ /* Sentinel */ }
@@ -384,6 +731,7 @@ static struct i2c_driver ltr390_driver = {
.driver = {
.name = "ltr390",
.of_match_table = ltr390_of_table,
+ .pm = pm_sleep_ptr(&ltr390_pm_ops),
},
.probe = ltr390_probe,
.id_table = ltr390_id,
diff --git a/drivers/iio/light/ltr501.c b/drivers/iio/light/ltr501.c
index 8c516ede9116..604f5f900a2e 100644
--- a/drivers/iio/light/ltr501.c
+++ b/drivers/iio/light/ltr501.c
@@ -15,7 +15,6 @@
#include <linux/err.h>
#include <linux/delay.h>
#include <linux/regmap.h>
-#include <linux/acpi.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
@@ -1078,15 +1077,11 @@ static int ltr501_read_event_config(struct iio_dev *indio_dev,
static int ltr501_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct ltr501_data *data = iio_priv(indio_dev);
int ret;
- /* only 1 and 0 are valid inputs */
- if (state != 1 && state != 0)
- return -EINVAL;
-
switch (chan->type) {
case IIO_INTENSITY:
mutex_lock(&data->lock_als);
@@ -1422,17 +1417,6 @@ static int ltr501_powerdown(struct ltr501_data *data)
data->ps_contr & ~LTR501_CONTR_ACTIVE);
}
-static const char *ltr501_match_acpi_device(struct device *dev, int *chip_idx)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
- *chip_idx = id->driver_data;
- return dev_name(dev);
-}
-
static int ltr501_probe(struct i2c_client *client)
{
const struct i2c_device_id *id = i2c_client_get_device_id(client);
@@ -1440,8 +1424,10 @@ static int ltr501_probe(struct i2c_client *client)
struct ltr501_data *data;
struct iio_dev *indio_dev;
struct regmap *regmap;
- int ret, partid, chip_idx = 0;
- const char *name = NULL;
+ const void *ddata = NULL;
+ int partid, chip_idx;
+ const char *name;
+ int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -1523,11 +1509,12 @@ static int ltr501_probe(struct i2c_client *client)
if (id) {
name = id->name;
chip_idx = id->driver_data;
- } else if (ACPI_HANDLE(&client->dev)) {
- name = ltr501_match_acpi_device(&client->dev, &chip_idx);
} else {
- return -ENODEV;
+ name = iio_get_acpi_device_name_and_data(&client->dev, &ddata);
+ chip_idx = (intptr_t)ddata;
}
+ if (!name)
+ return -ENODEV;
data->chip_info = &ltr501_chip_info_tbl[chip_idx];
@@ -1610,9 +1597,9 @@ static int ltr501_resume(struct device *dev)
static DEFINE_SIMPLE_DEV_PM_OPS(ltr501_pm_ops, ltr501_suspend, ltr501_resume);
static const struct acpi_device_id ltr_acpi_match[] = {
- { "LTER0501", ltr501 },
- { "LTER0559", ltr559 },
{ "LTER0301", ltr301 },
+ /* https://www.catalog.update.microsoft.com/Search.aspx?q=lter0303 */
+ { "LTER0303", ltr303 },
{ },
};
MODULE_DEVICE_TABLE(acpi, ltr_acpi_match);
diff --git a/drivers/iio/light/ltrf216a.c b/drivers/iio/light/ltrf216a.c
index 37eecff571b9..dbec1e7cfeb8 100644
--- a/drivers/iio/light/ltrf216a.c
+++ b/drivers/iio/light/ltrf216a.c
@@ -561,6 +561,7 @@ MODULE_DEVICE_TABLE(i2c, ltrf216a_id);
static const struct of_device_id ltrf216a_of_match[] = {
{ .compatible = "liteon,ltr308", .data = &ltr308_chip_info },
{ .compatible = "liteon,ltrf216a", .data = &ltrf216a_chip_info },
+ /* For Valve's Steamdeck device, an ACPI platform using PRP0001 */
{ .compatible = "ltr,ltrf216a", .data = &ltrf216a_chip_info },
{}
};
diff --git a/drivers/iio/light/max44009.c b/drivers/iio/light/max44009.c
index 3b92362675dc..8cd7f5664e5b 100644
--- a/drivers/iio/light/max44009.c
+++ b/drivers/iio/light/max44009.c
@@ -422,7 +422,7 @@ static int max44009_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct max44009_data *data = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/light/opt3001.c b/drivers/iio/light/opt3001.c
index 176e54bb48c3..65b295877b41 100644
--- a/drivers/iio/light/opt3001.c
+++ b/drivers/iio/light/opt3001.c
@@ -70,6 +70,35 @@
#define OPT3001_RESULT_READY_SHORT 150
#define OPT3001_RESULT_READY_LONG 1000
+struct opt3001_scale {
+ int val;
+ int val2;
+};
+
+struct opt3001_chip_info {
+ const struct iio_chan_spec (*channels)[2];
+ enum iio_chan_type chan_type;
+ int num_channels;
+
+ const struct opt3001_scale (*scales)[12];
+ /*
+ * Factor as specified by conversion equation in datasheet.
+ * eg. 0.01 (scaled to integer 10) for opt3001.
+ */
+ int factor_whole;
+ /*
+ * Factor to compensate for potentially scaled factor_whole.
+ */
+ int factor_integer;
+ /*
+ * Factor used to align decimal part of proccessed value to six decimal
+ * places.
+ */
+ int factor_decimal;
+
+ bool has_id;
+};
+
struct opt3001 {
struct i2c_client *client;
struct device *dev;
@@ -79,6 +108,7 @@ struct opt3001 {
bool result_ready;
wait_queue_head_t result_ready_queue;
u16 result;
+ const struct opt3001_chip_info *chip_info;
u32 int_time;
u32 mode;
@@ -92,11 +122,6 @@ struct opt3001 {
bool use_irq;
};
-struct opt3001_scale {
- int val;
- int val2;
-};
-
static const struct opt3001_scale opt3001_scales[] = {
{
.val = 40,
@@ -148,21 +173,68 @@ static const struct opt3001_scale opt3001_scales[] = {
},
};
+static const struct opt3001_scale opt3002_scales[] = {
+ {
+ .val = 4914,
+ .val2 = 0,
+ },
+ {
+ .val = 9828,
+ .val2 = 0,
+ },
+ {
+ .val = 19656,
+ .val2 = 0,
+ },
+ {
+ .val = 39312,
+ .val2 = 0,
+ },
+ {
+ .val = 78624,
+ .val2 = 0,
+ },
+ {
+ .val = 157248,
+ .val2 = 0,
+ },
+ {
+ .val = 314496,
+ .val2 = 0,
+ },
+ {
+ .val = 628992,
+ .val2 = 0,
+ },
+ {
+ .val = 1257984,
+ .val2 = 0,
+ },
+ {
+ .val = 2515968,
+ .val2 = 0,
+ },
+ {
+ .val = 5031936,
+ .val2 = 0,
+ },
+ {
+ .val = 10063872,
+ .val2 = 0,
+ },
+};
+
static int opt3001_find_scale(const struct opt3001 *opt, int val,
int val2, u8 *exponent)
{
int i;
-
- for (i = 0; i < ARRAY_SIZE(opt3001_scales); i++) {
- const struct opt3001_scale *scale = &opt3001_scales[i];
-
+ for (i = 0; i < ARRAY_SIZE(*opt->chip_info->scales); i++) {
+ const struct opt3001_scale *scale = &(*opt->chip_info->scales)[i];
/*
- * Combine the integer and micro parts for comparison
- * purposes. Use milli lux precision to avoid 32-bit integer
- * overflows.
+ * Compare the integer and micro parts to determine value scale.
*/
- if ((val * 1000 + val2 / 1000) <=
- (scale->val * 1000 + scale->val2 / 1000)) {
+ if (val < scale->val ||
+ (val == scale->val && val2 <= scale->val2)) {
*exponent = i;
return 0;
}
@@ -174,11 +246,14 @@ static int opt3001_find_scale(const struct opt3001 *opt, int val,
static void opt3001_to_iio_ret(struct opt3001 *opt, u8 exponent,
u16 mantissa, int *val, int *val2)
{
- int lux;
+ int ret;
+ int whole = opt->chip_info->factor_whole;
+ int integer = opt->chip_info->factor_integer;
+ int decimal = opt->chip_info->factor_decimal;
- lux = 10 * (mantissa << exponent);
- *val = lux / 1000;
- *val2 = (lux - (*val * 1000)) * 1000;
+ ret = whole * (mantissa << exponent);
+ *val = ret / integer;
+ *val2 = (ret - (*val * integer)) * decimal;
}
static void opt3001_set_mode(struct opt3001 *opt, u16 *reg, u16 mode)
@@ -225,7 +300,18 @@ static const struct iio_chan_spec opt3001_channels[] = {
IIO_CHAN_SOFT_TIMESTAMP(1),
};
-static int opt3001_get_lux(struct opt3001 *opt, int *val, int *val2)
+static const struct iio_chan_spec opt3002_channels[] = {
+ {
+ .type = IIO_INTENSITY,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_INT_TIME),
+ .event_spec = opt3001_event_spec,
+ .num_event_specs = ARRAY_SIZE(opt3001_event_spec),
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(1),
+};
+
+static int opt3001_get_processed(struct opt3001 *opt, int *val, int *val2)
{
int ret;
u16 mantissa;
@@ -397,14 +483,15 @@ static int opt3001_read_raw(struct iio_dev *iio,
if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return -EBUSY;
- if (chan->type != IIO_LIGHT)
+ if (chan->type != opt->chip_info->chan_type)
return -EINVAL;
mutex_lock(&opt->lock);
switch (mask) {
+ case IIO_CHAN_INFO_RAW:
case IIO_CHAN_INFO_PROCESSED:
- ret = opt3001_get_lux(opt, val, val2);
+ ret = opt3001_get_processed(opt, val, val2);
break;
case IIO_CHAN_INFO_INT_TIME:
ret = opt3001_get_int_time(opt, val, val2);
@@ -428,7 +515,7 @@ static int opt3001_write_raw(struct iio_dev *iio,
if (opt->mode == OPT3001_CONFIGURATION_M_CONTINUOUS)
return -EBUSY;
- if (chan->type != IIO_LIGHT)
+ if (chan->type != opt->chip_info->chan_type)
return -EINVAL;
if (mask != IIO_CHAN_INFO_INT_TIME)
@@ -479,6 +566,9 @@ static int opt3001_write_event_value(struct iio_dev *iio,
{
struct opt3001 *opt = iio_priv(iio);
int ret;
+ int whole;
+ int integer;
+ int decimal;
u16 mantissa;
u16 value;
@@ -497,7 +587,12 @@ static int opt3001_write_event_value(struct iio_dev *iio,
goto err;
}
- mantissa = (((val * 1000) + (val2 / 1000)) / 10) >> exponent;
+ whole = opt->chip_info->factor_whole;
+ integer = opt->chip_info->factor_integer;
+ decimal = opt->chip_info->factor_decimal;
+
+ mantissa = (((val * integer) + (val2 / decimal)) / whole) >> exponent;
+
value = (exponent << 12) | mantissa;
switch (dir) {
@@ -539,7 +634,7 @@ static int opt3001_read_event_config(struct iio_dev *iio,
static int opt3001_write_event_config(struct iio_dev *iio,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct opt3001 *opt = iio_priv(iio);
int ret;
@@ -610,7 +705,7 @@ static int opt3001_read_id(struct opt3001 *opt)
ret = i2c_smbus_read_word_swapped(opt->client, OPT3001_DEVICE_ID);
if (ret < 0) {
dev_err(opt->dev, "failed to read register %02x\n",
- OPT3001_DEVICE_ID);
+ OPT3001_DEVICE_ID);
return ret;
}
@@ -692,6 +787,7 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
struct opt3001 *opt = iio_priv(iio);
int ret;
bool wake_result_ready_queue = false;
+ enum iio_chan_type chan_type = opt->chip_info->chan_type;
if (!opt->ok_to_ignore_lock)
mutex_lock(&opt->lock);
@@ -707,13 +803,13 @@ static irqreturn_t opt3001_irq(int irq, void *_iio)
OPT3001_CONFIGURATION_M_CONTINUOUS) {
if (ret & OPT3001_CONFIGURATION_FH)
iio_push_event(iio,
- IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_UNMOD_EVENT_CODE(chan_type, 0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_RISING),
iio_get_time_ns(iio));
if (ret & OPT3001_CONFIGURATION_FL)
iio_push_event(iio,
- IIO_UNMOD_EVENT_CODE(IIO_LIGHT, 0,
+ IIO_UNMOD_EVENT_CODE(chan_type, 0,
IIO_EV_TYPE_THRESH,
IIO_EV_DIR_FALLING),
iio_get_time_ns(iio));
@@ -755,22 +851,25 @@ static int opt3001_probe(struct i2c_client *client)
opt = iio_priv(iio);
opt->client = client;
opt->dev = dev;
+ opt->chip_info = i2c_get_match_data(client);
mutex_init(&opt->lock);
init_waitqueue_head(&opt->result_ready_queue);
i2c_set_clientdata(client, iio);
- ret = opt3001_read_id(opt);
- if (ret)
- return ret;
+ if (opt->chip_info->has_id) {
+ ret = opt3001_read_id(opt);
+ if (ret)
+ return ret;
+ }
ret = opt3001_configure(opt);
if (ret)
return ret;
iio->name = client->name;
- iio->channels = opt3001_channels;
- iio->num_channels = ARRAY_SIZE(opt3001_channels);
+ iio->channels = *opt->chip_info->channels;
+ iio->num_channels = opt->chip_info->num_channels;
iio->modes = INDIO_DIRECT_MODE;
iio->info = &opt3001_info;
@@ -825,14 +924,38 @@ static void opt3001_remove(struct i2c_client *client)
}
}
+static const struct opt3001_chip_info opt3001_chip_information = {
+ .channels = &opt3001_channels,
+ .chan_type = IIO_LIGHT,
+ .num_channels = ARRAY_SIZE(opt3001_channels),
+ .scales = &opt3001_scales,
+ .factor_whole = 10,
+ .factor_integer = 1000,
+ .factor_decimal = 1000,
+ .has_id = true,
+};
+
+static const struct opt3001_chip_info opt3002_chip_information = {
+ .channels = &opt3002_channels,
+ .chan_type = IIO_INTENSITY,
+ .num_channels = ARRAY_SIZE(opt3002_channels),
+ .scales = &opt3002_scales,
+ .factor_whole = 12,
+ .factor_integer = 10,
+ .factor_decimal = 100000,
+ .has_id = false,
+};
+
static const struct i2c_device_id opt3001_id[] = {
- { "opt3001" },
+ { "opt3001", (kernel_ulong_t)&opt3001_chip_information },
+ { "opt3002", (kernel_ulong_t)&opt3002_chip_information },
{ } /* Terminating Entry */
};
MODULE_DEVICE_TABLE(i2c, opt3001_id);
static const struct of_device_id opt3001_of_match[] = {
- { .compatible = "ti,opt3001" },
+ { .compatible = "ti,opt3001", .data = &opt3001_chip_information },
+ { .compatible = "ti,opt3002", .data = &opt3002_chip_information },
{ }
};
MODULE_DEVICE_TABLE(of, opt3001_of_match);
diff --git a/drivers/iio/light/rohm-bu27008.c b/drivers/iio/light/rohm-bu27008.c
index 0f010eff1981..fa35dd32700c 100644
--- a/drivers/iio/light/rohm-bu27008.c
+++ b/drivers/iio/light/rohm-bu27008.c
@@ -1632,4 +1632,4 @@ module_i2c_driver(bu27008_i2c_driver);
MODULE_DESCRIPTION("ROHM BU27008 and BU27010 colour sensor driver");
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_GTS_HELPER);
+MODULE_IMPORT_NS("IIO_GTS_HELPER");
diff --git a/drivers/iio/light/rohm-bu27034.c b/drivers/iio/light/rohm-bu27034.c
index 76711c3cdf7c..4f591c2278f2 100644
--- a/drivers/iio/light/rohm-bu27034.c
+++ b/drivers/iio/light/rohm-bu27034.c
@@ -1350,4 +1350,4 @@ module_i2c_driver(bu27034_i2c_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Matti Vaittinen <matti.vaittinen@fi.rohmeurope.com>");
MODULE_DESCRIPTION("ROHM BU27034 ambient light sensor driver");
-MODULE_IMPORT_NS(IIO_GTS_HELPER);
+MODULE_IMPORT_NS("IIO_GTS_HELPER");
diff --git a/drivers/iio/light/rpr0521.c b/drivers/iio/light/rpr0521.c
index 78c08e0bd077..56f5fbbf79ac 100644
--- a/drivers/iio/light/rpr0521.c
+++ b/drivers/iio/light/rpr0521.c
@@ -438,18 +438,6 @@ static irqreturn_t rpr0521_drdy_irq_thread(int irq, void *private)
return IRQ_NONE;
}
-static irqreturn_t rpr0521_trigger_consumer_store_time(int irq, void *p)
-{
- struct iio_poll_func *pf = p;
- struct iio_dev *indio_dev = pf->indio_dev;
-
- /* Other trigger polls store time here. */
- if (!iio_trigger_using_own(indio_dev))
- pf->timestamp = iio_get_time_ns(indio_dev);
-
- return IRQ_WAKE_THREAD;
-}
-
static irqreturn_t rpr0521_trigger_consumer_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
@@ -1016,7 +1004,7 @@ static int rpr0521_probe(struct i2c_client *client)
/* Trigger consumer setup */
ret = devm_iio_triggered_buffer_setup(indio_dev->dev.parent,
indio_dev,
- rpr0521_trigger_consumer_store_time,
+ iio_pollfunc_store_time,
rpr0521_trigger_consumer_handler,
&rpr0521_buffer_setup_ops);
if (ret < 0) {
diff --git a/drivers/iio/light/st_uvis25_core.c b/drivers/iio/light/st_uvis25_core.c
index fba3997574bb..40a810000df0 100644
--- a/drivers/iio/light/st_uvis25_core.c
+++ b/drivers/iio/light/st_uvis25_core.c
@@ -174,8 +174,7 @@ static int st_uvis25_allocate_trigger(struct iio_dev *iio_dev)
unsigned long irq_type;
int err;
- irq_type = irqd_get_trigger_type(irq_get_irq_data(hw->irq));
-
+ irq_type = irq_get_trigger_type(hw->irq);
switch (irq_type) {
case IRQF_TRIGGER_HIGH:
case IRQF_TRIGGER_RISING:
@@ -323,7 +322,7 @@ int st_uvis25_probe(struct device *dev, int irq, struct regmap *regmap)
return devm_iio_device_register(dev, iio_dev);
}
-EXPORT_SYMBOL_NS(st_uvis25_probe, IIO_UVIS25);
+EXPORT_SYMBOL_NS(st_uvis25_probe, "IIO_UVIS25");
static int st_uvis25_suspend(struct device *dev)
{
diff --git a/drivers/iio/light/st_uvis25_i2c.c b/drivers/iio/light/st_uvis25_i2c.c
index 6bc2ddfb77ca..f54282476d11 100644
--- a/drivers/iio/light/st_uvis25_i2c.c
+++ b/drivers/iio/light/st_uvis25_i2c.c
@@ -65,4 +65,4 @@ module_i2c_driver(st_uvis25_driver);
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
MODULE_DESCRIPTION("STMicroelectronics uvis25 i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_UVIS25);
+MODULE_IMPORT_NS("IIO_UVIS25");
diff --git a/drivers/iio/light/st_uvis25_spi.c b/drivers/iio/light/st_uvis25_spi.c
index 86a232320d7d..18edc6a5a4a4 100644
--- a/drivers/iio/light/st_uvis25_spi.c
+++ b/drivers/iio/light/st_uvis25_spi.c
@@ -66,4 +66,4 @@ module_spi_driver(st_uvis25_driver);
MODULE_AUTHOR("Lorenzo Bianconi <lorenzo.bianconi83@gmail.com>");
MODULE_DESCRIPTION("STMicroelectronics uvis25 spi driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_UVIS25);
+MODULE_IMPORT_NS("IIO_UVIS25");
diff --git a/drivers/iio/light/stk3310.c b/drivers/iio/light/stk3310.c
index ed20b6714546..b81cc44db43c 100644
--- a/drivers/iio/light/stk3310.c
+++ b/drivers/iio/light/stk3310.c
@@ -324,15 +324,12 @@ static int stk3310_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
int ret;
struct stk3310_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
- if (state < 0 || state > 7)
- return -EINVAL;
-
/* Set INT_PS value */
mutex_lock(&data->lock);
ret = regmap_field_write(data->reg_int_ps, state);
diff --git a/drivers/iio/light/tcs3472.c b/drivers/iio/light/tcs3472.c
index 04452b4664f3..4186aac04902 100644
--- a/drivers/iio/light/tcs3472.c
+++ b/drivers/iio/light/tcs3472.c
@@ -327,7 +327,7 @@ static int tcs3472_read_event_config(struct iio_dev *indio_dev,
static int tcs3472_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct tcs3472_data *data = iio_priv(indio_dev);
int ret = 0;
diff --git a/drivers/iio/light/tsl2563.c b/drivers/iio/light/tsl2563.c
index 1a6f514bced6..f1fe7640fce6 100644
--- a/drivers/iio/light/tsl2563.c
+++ b/drivers/iio/light/tsl2563.c
@@ -630,7 +630,7 @@ static irqreturn_t tsl2563_event_handler(int irq, void *private)
static int tsl2563_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct tsl2563_chip *chip = iio_priv(indio_dev);
int ret = 0;
diff --git a/drivers/iio/light/tsl2591.c b/drivers/iio/light/tsl2591.c
index 850c2465992f..b81ca6f73f92 100644
--- a/drivers/iio/light/tsl2591.c
+++ b/drivers/iio/light/tsl2591.c
@@ -985,7 +985,7 @@ static int tsl2591_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct tsl2591_chip *chip = iio_priv(indio_dev);
struct i2c_client *client = chip->client;
diff --git a/drivers/iio/light/tsl2772.c b/drivers/iio/light/tsl2772.c
index cab468a82b61..349afdcbe30d 100644
--- a/drivers/iio/light/tsl2772.c
+++ b/drivers/iio/light/tsl2772.c
@@ -1081,14 +1081,14 @@ static int tsl2772_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int val)
+ bool val)
{
struct tsl2772_chip *chip = iio_priv(indio_dev);
if (chan->type == IIO_INTENSITY)
- chip->settings.als_interrupt_en = val ? true : false;
+ chip->settings.als_interrupt_en = val;
else
- chip->settings.prox_interrupt_en = val ? true : false;
+ chip->settings.prox_interrupt_en = val;
return tsl2772_invoke_change(indio_dev);
}
diff --git a/drivers/iio/light/us5182d.c b/drivers/iio/light/us5182d.c
index de6967ac3b0b..c83114aed6b2 100644
--- a/drivers/iio/light/us5182d.c
+++ b/drivers/iio/light/us5182d.c
@@ -627,7 +627,7 @@ static int us5182d_read_event_config(struct iio_dev *indio_dev,
static int us5182d_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct us5182d_data *data = iio_priv(indio_dev);
int ret;
diff --git a/drivers/iio/light/vcnl4000.c b/drivers/iio/light/vcnl4000.c
index 4e3641ff2ed4..e19199b17f2e 100644
--- a/drivers/iio/light/vcnl4000.c
+++ b/drivers/iio/light/vcnl4000.c
@@ -1456,7 +1456,7 @@ static int vcnl4010_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
switch (chan->type) {
case IIO_PROXIMITY:
@@ -1501,7 +1501,8 @@ static int vcnl4040_read_event_config(struct iio_dev *indio_dev,
static int vcnl4040_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
int ret = -EINVAL;
u16 val, mask;
diff --git a/drivers/iio/light/veml3235.c b/drivers/iio/light/veml3235.c
new file mode 100644
index 000000000000..66361c3012a3
--- /dev/null
+++ b/drivers/iio/light/veml3235.c
@@ -0,0 +1,495 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * VEML3235 Ambient Light Sensor
+ *
+ * Copyright (c) 2024, Javier Carrasco <javier.carrasco.cruz@gmail.com>
+ *
+ * Datasheet: https://www.vishay.com/docs/80131/veml3235.pdf
+ * Appnote-80222: https://www.vishay.com/docs/80222/designingveml3235.pdf
+ */
+
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/iio/iio.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
+
+#define VEML3235_REG_CONF 0x00
+#define VEML3235_REG_WH_DATA 0x04
+#define VEML3235_REG_ALS_DATA 0x05
+#define VEML3235_REG_ID 0x09
+
+#define VEML3235_CONF_SD BIT(0)
+#define VEML3235_CONF_SD0 BIT(15)
+
+struct veml3235_rf {
+ struct regmap_field *it;
+ struct regmap_field *gain;
+ struct regmap_field *id;
+};
+
+struct veml3235_data {
+ struct i2c_client *client;
+ struct device *dev;
+ struct regmap *regmap;
+ struct veml3235_rf rf;
+};
+
+static const int veml3235_it_times[][2] = {
+ { 0, 50000 },
+ { 0, 100000 },
+ { 0, 200000 },
+ { 0, 400000 },
+ { 0, 800000 },
+};
+
+static const int veml3235_scale_vals[] = { 1, 2, 4, 8 };
+
+static int veml3235_power_on(struct veml3235_data *data)
+{
+ int ret;
+
+ ret = regmap_clear_bits(data->regmap, VEML3235_REG_CONF,
+ VEML3235_CONF_SD | VEML3235_CONF_SD0);
+ if (ret)
+ return ret;
+
+ /* Wait 4 ms to let processor & oscillator start correctly */
+ fsleep(4000);
+
+ return 0;
+}
+
+static int veml3235_shut_down(struct veml3235_data *data)
+{
+ return regmap_set_bits(data->regmap, VEML3235_REG_CONF,
+ VEML3235_CONF_SD | VEML3235_CONF_SD0);
+}
+
+static void veml3235_shut_down_action(void *data)
+{
+ veml3235_shut_down(data);
+}
+
+enum veml3235_chan {
+ CH_ALS,
+ CH_WHITE,
+};
+
+static const struct iio_chan_spec veml3235_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .channel = CH_ALS,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .channel = CH_WHITE,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+};
+
+static const struct regmap_config veml3235_regmap_config = {
+ .name = "veml3235_regmap",
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = VEML3235_REG_ID,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
+};
+
+static int veml3235_get_it(struct veml3235_data *data, int *val, int *val2)
+{
+ int ret, reg;
+
+ ret = regmap_field_read(data->rf.it, &reg);
+ if (ret)
+ return ret;
+
+ switch (reg) {
+ case 0:
+ *val2 = 50000;
+ break;
+ case 1:
+ *val2 = 100000;
+ break;
+ case 2:
+ *val2 = 200000;
+ break;
+ case 3:
+ *val2 = 400000;
+ break;
+ case 4:
+ *val2 = 800000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ *val = 0;
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int veml3235_set_it(struct iio_dev *indio_dev, int val, int val2)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ int ret, new_it;
+
+ if (val)
+ return -EINVAL;
+
+ switch (val2) {
+ case 50000:
+ new_it = 0x00;
+ break;
+ case 100000:
+ new_it = 0x01;
+ break;
+ case 200000:
+ new_it = 0x02;
+ break;
+ case 400000:
+ new_it = 0x03;
+ break;
+ case 800000:
+ new_it = 0x04;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_field_write(data->rf.it, new_it);
+ if (ret) {
+ dev_err(data->dev,
+ "failed to update integration time: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int veml3235_set_gain(struct iio_dev *indio_dev, int val, int val2)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ int ret, new_gain;
+
+ if (val2 != 0)
+ return -EINVAL;
+
+ switch (val) {
+ case 1:
+ new_gain = 0x00;
+ break;
+ case 2:
+ new_gain = 0x01;
+ break;
+ case 4:
+ new_gain = 0x03;
+ break;
+ case 8:
+ new_gain = 0x07;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = regmap_field_write(data->rf.gain, new_gain);
+ if (ret) {
+ dev_err(data->dev, "failed to set gain: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int veml3235_get_gain(struct veml3235_data *data, int *val)
+{
+ int ret, reg;
+
+ ret = regmap_field_read(data->rf.gain, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read gain %d\n", ret);
+ return ret;
+ }
+
+ switch (reg & 0x03) {
+ case 0:
+ *val = 1;
+ break;
+ case 1:
+ *val = 2;
+ break;
+ case 3:
+ *val = 4;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Double gain */
+ if (reg & 0x04)
+ *val *= 2;
+
+ return IIO_VAL_INT;
+}
+
+static int veml3235_read_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan, int *val,
+ int *val2, long mask)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ struct regmap *regmap = data->regmap;
+ int ret, reg;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_RAW:
+ switch (chan->type) {
+ case IIO_LIGHT:
+ ret = regmap_read(regmap, VEML3235_REG_ALS_DATA, &reg);
+ if (ret < 0)
+ return ret;
+
+ *val = reg;
+ return IIO_VAL_INT;
+ case IIO_INTENSITY:
+ ret = regmap_read(regmap, VEML3235_REG_WH_DATA, &reg);
+ if (ret < 0)
+ return ret;
+
+ *val = reg;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml3235_get_it(data, val, val2);
+ case IIO_CHAN_INFO_SCALE:
+ return veml3235_get_gain(data, val);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml3235_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *vals = (int *)&veml3235_it_times;
+ *length = 2 * ARRAY_SIZE(veml3235_it_times);
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (int *)&veml3235_scale_vals;
+ *length = ARRAY_SIZE(veml3235_scale_vals);
+ *type = IIO_VAL_INT;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml3235_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml3235_set_it(indio_dev, val, val2);
+ case IIO_CHAN_INFO_SCALE:
+ return veml3235_set_gain(indio_dev, val, val2);
+ }
+
+ return -EINVAL;
+}
+
+static void veml3235_read_id(struct veml3235_data *data)
+{
+ int ret, reg;
+
+ ret = regmap_field_read(data->rf.id, &reg);
+ if (ret) {
+ dev_info(data->dev, "failed to read ID\n");
+ return;
+ }
+
+ if (reg != 0x35)
+ dev_info(data->dev, "Unknown ID %d\n", reg);
+}
+
+static const struct reg_field veml3235_rf_it =
+ REG_FIELD(VEML3235_REG_CONF, 4, 6);
+
+static const struct reg_field veml3235_rf_gain =
+ REG_FIELD(VEML3235_REG_CONF, 11, 13);
+
+static const struct reg_field veml3235_rf_id =
+ REG_FIELD(VEML3235_REG_ID, 0, 7);
+
+static int veml3235_regfield_init(struct veml3235_data *data)
+{
+ struct regmap *regmap = data->regmap;
+ struct device *dev = data->dev;
+ struct regmap_field *rm_field;
+ struct veml3235_rf *rf = &data->rf;
+
+ rm_field = devm_regmap_field_alloc(dev, regmap, veml3235_rf_it);
+ if (IS_ERR(rm_field))
+ return PTR_ERR(rm_field);
+ rf->it = rm_field;
+
+ rm_field = devm_regmap_field_alloc(dev, regmap, veml3235_rf_gain);
+ if (IS_ERR(rm_field))
+ return PTR_ERR(rm_field);
+ rf->gain = rm_field;
+
+ rm_field = devm_regmap_field_alloc(dev, regmap, veml3235_rf_id);
+ if (IS_ERR(rm_field))
+ return PTR_ERR(rm_field);
+ rf->id = rm_field;
+
+ return 0;
+}
+
+static int veml3235_hw_init(struct iio_dev *indio_dev)
+{
+ struct veml3235_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
+ int ret;
+
+ /* Set gain to 1 and integration time to 100 ms */
+ ret = regmap_field_write(data->rf.gain, 0x00);
+ if (ret)
+ return dev_err_probe(data->dev, ret, "failed to set gain\n");
+
+ ret = regmap_field_write(data->rf.it, 0x01);
+ if (ret)
+ return dev_err_probe(data->dev, ret,
+ "failed to set integration time\n");
+
+ ret = veml3235_power_on(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to power on\n");
+
+ return devm_add_action_or_reset(dev, veml3235_shut_down_action, data);
+}
+
+static const struct iio_info veml3235_info = {
+ .read_raw = veml3235_read_raw,
+ .read_avail = veml3235_read_avail,
+ .write_raw = veml3235_write_raw,
+};
+
+static int veml3235_probe(struct i2c_client *client)
+{
+ struct device *dev = &client->dev;
+ struct veml3235_data *data;
+ struct iio_dev *indio_dev;
+ struct regmap *regmap;
+ int ret;
+
+ regmap = devm_regmap_init_i2c(client, &veml3235_regmap_config);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "failed to setup regmap\n");
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ i2c_set_clientdata(client, indio_dev);
+ data->client = client;
+ data->dev = dev;
+ data->regmap = regmap;
+
+ ret = veml3235_regfield_init(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to init regfield\n");
+
+ ret = devm_regulator_get_enable(dev, "vdd");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable regulator\n");
+
+ indio_dev->name = "veml3235";
+ indio_dev->channels = veml3235_channels;
+ indio_dev->num_channels = ARRAY_SIZE(veml3235_channels);
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->info = &veml3235_info;
+
+ veml3235_read_id(data);
+
+ ret = veml3235_hw_init(indio_dev);
+ if (ret < 0)
+ return ret;
+
+ return devm_iio_device_register(dev, indio_dev);
+}
+
+static int veml3235_runtime_suspend(struct device *dev)
+{
+ struct veml3235_data *data = iio_priv(dev_get_drvdata(dev));
+ int ret;
+
+ ret = veml3235_shut_down(data);
+ if (ret < 0)
+ dev_err(data->dev, "failed to suspend: %d\n", ret);
+
+ return ret;
+}
+
+static int veml3235_runtime_resume(struct device *dev)
+{
+ struct veml3235_data *data = iio_priv(dev_get_drvdata(dev));
+ int ret;
+
+ ret = veml3235_power_on(data);
+ if (ret < 0)
+ dev_err(data->dev, "failed to resume: %d\n", ret);
+
+ return ret;
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(veml3235_pm_ops, veml3235_runtime_suspend,
+ veml3235_runtime_resume, NULL);
+
+static const struct of_device_id veml3235_of_match[] = {
+ { .compatible = "vishay,veml3235" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, veml3235_of_match);
+
+static const struct i2c_device_id veml3235_id[] = {
+ { "veml3235" },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, veml3235_id);
+
+static struct i2c_driver veml3235_driver = {
+ .driver = {
+ .name = "veml3235",
+ .of_match_table = veml3235_of_match,
+ .pm = pm_ptr(&veml3235_pm_ops),
+ },
+ .probe = veml3235_probe,
+ .id_table = veml3235_id,
+};
+module_i2c_driver(veml3235_driver);
+
+MODULE_AUTHOR("Javier Carrasco <javier.carrasco.cruz@gmail.com>");
+MODULE_DESCRIPTION("VEML3235 Ambient Light Sensor");
+MODULE_LICENSE("GPL");
diff --git a/drivers/iio/light/veml6030.c b/drivers/iio/light/veml6030.c
index 621428885455..ccb43dfd5cf7 100644
--- a/drivers/iio/light/veml6030.c
+++ b/drivers/iio/light/veml6030.c
@@ -1,19 +1,30 @@
// SPDX-License-Identifier: GPL-2.0+
/*
- * VEML6030 Ambient Light Sensor
+ * VEML6030, VMEL6035 and VEML7700 Ambient Light Sensors
*
* Copyright (c) 2019, Rishi Gupta <gupt21@gmail.com>
*
+ * VEML6030:
* Datasheet: https://www.vishay.com/docs/84366/veml6030.pdf
* Appnote-84367: https://www.vishay.com/docs/84367/designingveml6030.pdf
+ *
+ * VEML6035:
+ * Datasheet: https://www.vishay.com/docs/84889/veml6035.pdf
+ * Appnote-84944: https://www.vishay.com/docs/84944/designingveml6035.pdf
+ *
+ * VEML7700:
+ * Datasheet: https://www.vishay.com/docs/84286/veml7700.pdf
+ * Appnote-84323: https://www.vishay.com/docs/84323/designingveml7700.pdf
*/
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/events.h>
@@ -38,16 +49,35 @@
#define VEML6030_ALS_INT_EN BIT(1)
#define VEML6030_ALS_SD BIT(0)
+#define VEML6035_GAIN_M GENMASK(12, 10)
+#define VEML6035_GAIN BIT(10)
+#define VEML6035_DG BIT(11)
+#define VEML6035_SENS BIT(12)
+#define VEML6035_INT_CHAN BIT(3)
+#define VEML6035_CHAN_EN BIT(2)
+
+struct veml603x_chip {
+ const char *name;
+ const int(*scale_vals)[][2];
+ const int num_scale_vals;
+ const struct iio_chan_spec *channels;
+ const int num_channels;
+ int (*hw_init)(struct iio_dev *indio_dev, struct device *dev);
+ int (*set_info)(struct iio_dev *indio_dev);
+ int (*set_als_gain)(struct iio_dev *indio_dev, int val, int val2);
+ int (*get_als_gain)(struct iio_dev *indio_dev, int *val, int *val2);
+};
+
/*
* The resolution depends on both gain and integration time. The
* cur_resolution stores one of the resolution mentioned in the
* table during startup and gets updated whenever integration time
* or gain is changed.
*
- * Table 'resolution and maximum detection range' in appnote 84367
+ * Table 'resolution and maximum detection range' in the appnotes
* is visualized as a 2D array. The cur_gain stores index of gain
- * in this table (0-3) while the cur_integration_time holds index
- * of integration time (0-5).
+ * in this table (0-3 for VEML6030, 0-5 for VEML6035) while the
+ * cur_integration_time holds index of integration time (0-5).
*/
struct veml6030_data {
struct i2c_client *client;
@@ -55,27 +85,37 @@ struct veml6030_data {
int cur_resolution;
int cur_gain;
int cur_integration_time;
+ const struct veml603x_chip *chip;
};
-/* Integration time available in seconds */
-static IIO_CONST_ATTR(in_illuminance_integration_time_available,
- "0.025 0.05 0.1 0.2 0.4 0.8");
+static const int veml6030_it_times[][2] = {
+ { 0, 25000 },
+ { 0, 50000 },
+ { 0, 100000 },
+ { 0, 200000 },
+ { 0, 400000 },
+ { 0, 800000 },
+};
/*
* Scale is 1/gain. Value 0.125 is ALS gain x (1/8), 0.25 is
- * ALS gain x (1/4), 1.0 = ALS gain x 1 and 2.0 is ALS gain x 2.
+ * ALS gain x (1/4), 0.5 is ALS gain x (1/2), 1.0 is ALS gain x 1,
+ * 2.0 is ALS gain x2, and 4.0 is ALS gain x 4.
*/
-static IIO_CONST_ATTR(in_illuminance_scale_available,
- "0.125 0.25 1.0 2.0");
-
-static struct attribute *veml6030_attributes[] = {
- &iio_const_attr_in_illuminance_integration_time_available.dev_attr.attr,
- &iio_const_attr_in_illuminance_scale_available.dev_attr.attr,
- NULL
+static const int veml6030_scale_vals[][2] = {
+ { 0, 125000 },
+ { 0, 250000 },
+ { 1, 0 },
+ { 2, 0 },
};
-static const struct attribute_group veml6030_attr_group = {
- .attrs = veml6030_attributes,
+static const int veml6035_scale_vals[][2] = {
+ { 0, 125000 },
+ { 0, 250000 },
+ { 0, 500000 },
+ { 1, 0 },
+ { 2, 0 },
+ { 4, 0 },
};
/*
@@ -143,14 +183,23 @@ static const struct attribute_group veml6030_event_attr_group = {
static int veml6030_als_pwr_on(struct veml6030_data *data)
{
- return regmap_clear_bits(data->regmap, VEML6030_REG_ALS_CONF,
- VEML6030_ALS_SD);
+ int ret;
+
+ ret = regmap_clear_bits(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6030_ALS_SD);
+ if (ret)
+ return ret;
+
+ /* Wait 4 ms to let processor & oscillator start correctly */
+ fsleep(4000);
+
+ return 0;
}
static int veml6030_als_shut_down(struct veml6030_data *data)
{
- return regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
- VEML6030_ALS_SD, 1);
+ return regmap_set_bits(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6030_ALS_SD);
}
static void veml6030_als_shut_down_action(void *data)
@@ -189,6 +238,8 @@ static const struct iio_chan_spec veml6030_channels[] = {
BIT(IIO_CHAN_INFO_PROCESSED) |
BIT(IIO_CHAN_INFO_INT_TIME) |
BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
.event_spec = veml6030_event_spec,
.num_event_specs = ARRAY_SIZE(veml6030_event_spec),
},
@@ -198,7 +249,34 @@ static const struct iio_chan_spec veml6030_channels[] = {
.modified = 1,
.channel2 = IIO_MOD_LIGHT_BOTH,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_PROCESSED),
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+};
+
+static const struct iio_chan_spec veml7700_channels[] = {
+ {
+ .type = IIO_LIGHT,
+ .channel = CH_ALS,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_PROCESSED) |
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ },
+ {
+ .type = IIO_INTENSITY,
+ .channel = CH_WHITE,
+ .modified = 1,
+ .channel2 = IIO_MOD_LIGHT_BOTH,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME) |
+ BIT(IIO_CHAN_INFO_SCALE),
},
};
@@ -371,6 +449,21 @@ static int veml6030_write_persistence(struct iio_dev *indio_dev,
return ret;
}
+/*
+ * Cache currently set gain & update resolution. For every
+ * increase in the gain to next level, resolution is halved
+ * and vice-versa.
+ */
+static void veml6030_update_gain_res(struct veml6030_data *data, int gain_idx)
+{
+ if (data->cur_gain < gain_idx)
+ data->cur_resolution <<= gain_idx - data->cur_gain;
+ else if (data->cur_gain > gain_idx)
+ data->cur_resolution >>= data->cur_gain - gain_idx;
+
+ data->cur_gain = gain_idx;
+}
+
static int veml6030_set_als_gain(struct iio_dev *indio_dev,
int val, int val2)
{
@@ -401,19 +494,49 @@ static int veml6030_set_als_gain(struct iio_dev *indio_dev,
return ret;
}
- /*
- * Cache currently set gain & update resolution. For every
- * increase in the gain to next level, resolution is halved
- * and vice-versa.
- */
- if (data->cur_gain < gain_idx)
- data->cur_resolution <<= gain_idx - data->cur_gain;
- else if (data->cur_gain > gain_idx)
- data->cur_resolution >>= data->cur_gain - gain_idx;
+ veml6030_update_gain_res(data, gain_idx);
- data->cur_gain = gain_idx;
+ return 0;
+}
- return ret;
+static int veml6035_set_als_gain(struct iio_dev *indio_dev, int val, int val2)
+{
+ int ret, new_gain, gain_idx;
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ if (val == 0 && val2 == 125000) {
+ new_gain = VEML6035_SENS;
+ gain_idx = 5;
+ } else if (val == 0 && val2 == 250000) {
+ new_gain = VEML6035_SENS | VEML6035_GAIN;
+ gain_idx = 4;
+ } else if (val == 0 && val2 == 500000) {
+ new_gain = VEML6035_SENS | VEML6035_GAIN |
+ VEML6035_DG;
+ gain_idx = 3;
+ } else if (val == 1 && val2 == 0) {
+ new_gain = 0x0000;
+ gain_idx = 2;
+ } else if (val == 2 && val2 == 0) {
+ new_gain = VEML6035_GAIN;
+ gain_idx = 1;
+ } else if (val == 4 && val2 == 0) {
+ new_gain = VEML6035_GAIN | VEML6035_DG;
+ gain_idx = 0;
+ } else {
+ return -EINVAL;
+ }
+
+ ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6035_GAIN_M, new_gain);
+ if (ret) {
+ dev_err(&data->client->dev, "can't set als gain %d\n", ret);
+ return ret;
+ }
+
+ veml6030_update_gain_res(data, gain_idx);
+
+ return 0;
}
static int veml6030_get_als_gain(struct iio_dev *indio_dev,
@@ -453,6 +576,52 @@ static int veml6030_get_als_gain(struct iio_dev *indio_dev,
return IIO_VAL_INT_PLUS_MICRO;
}
+static int veml6035_get_als_gain(struct iio_dev *indio_dev, int *val, int *val2)
+{
+ int ret, reg;
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ ret = regmap_read(data->regmap, VEML6030_REG_ALS_CONF, &reg);
+ if (ret) {
+ dev_err(&data->client->dev,
+ "can't read als conf register %d\n", ret);
+ return ret;
+ }
+
+ switch (FIELD_GET(VEML6035_GAIN_M, reg)) {
+ case 0:
+ *val = 1;
+ *val2 = 0;
+ break;
+ case 1:
+ case 2:
+ *val = 2;
+ *val2 = 0;
+ break;
+ case 3:
+ *val = 4;
+ *val2 = 0;
+ break;
+ case 4:
+ *val = 0;
+ *val2 = 125000;
+ break;
+ case 5:
+ case 6:
+ *val = 0;
+ *val2 = 250000;
+ break;
+ case 7:
+ *val = 0;
+ *val2 = 500000;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
static int veml6030_read_thresh(struct iio_dev *indio_dev,
int *val, int *val2, int dir)
{
@@ -533,48 +702,54 @@ static int veml6030_read_raw(struct iio_dev *indio_dev,
dev_err(dev, "can't read white data %d\n", ret);
return ret;
}
- if (mask == IIO_CHAN_INFO_PROCESSED) {
- *val = (reg * data->cur_resolution) / 10000;
- *val2 = (reg * data->cur_resolution) % 10000;
- return IIO_VAL_INT_PLUS_MICRO;
- }
*val = reg;
return IIO_VAL_INT;
default:
return -EINVAL;
}
case IIO_CHAN_INFO_INT_TIME:
- if (chan->type == IIO_LIGHT)
- return veml6030_get_intgrn_tm(indio_dev, val, val2);
- return -EINVAL;
+ return veml6030_get_intgrn_tm(indio_dev, val, val2);
case IIO_CHAN_INFO_SCALE:
- if (chan->type == IIO_LIGHT)
- return veml6030_get_als_gain(indio_dev, val, val2);
- return -EINVAL;
+ return data->chip->get_als_gain(indio_dev, val, val2);
default:
return -EINVAL;
}
}
+static int veml6030_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *vals = (int *)&veml6030_it_times;
+ *length = 2 * ARRAY_SIZE(veml6030_it_times);
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ case IIO_CHAN_INFO_SCALE:
+ *vals = (int *)*data->chip->scale_vals;
+ *length = 2 * data->chip->num_scale_vals;
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ }
+
+ return -EINVAL;
+}
+
static int veml6030_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
+ struct veml6030_data *data = iio_priv(indio_dev);
+
switch (mask) {
case IIO_CHAN_INFO_INT_TIME:
- switch (chan->type) {
- case IIO_LIGHT:
- return veml6030_set_intgrn_tm(indio_dev, val, val2);
- default:
- return -EINVAL;
- }
+ return veml6030_set_intgrn_tm(indio_dev, val, val2);
case IIO_CHAN_INFO_SCALE:
- switch (chan->type) {
- case IIO_LIGHT:
- return veml6030_set_als_gain(indio_dev, val, val2);
- default:
- return -EINVAL;
- }
+ return data->chip->set_als_gain(indio_dev, val, val2);
default:
return -EINVAL;
}
@@ -646,14 +821,11 @@ static int veml6030_read_interrupt_config(struct iio_dev *indio_dev,
*/
static int veml6030_write_interrupt_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
int ret;
struct veml6030_data *data = iio_priv(indio_dev);
- if (state < 0 || state > 1)
- return -EINVAL;
-
ret = veml6030_als_shut_down(data);
if (ret < 0) {
dev_err(&data->client->dev,
@@ -673,19 +845,19 @@ static int veml6030_write_interrupt_config(struct iio_dev *indio_dev,
static const struct iio_info veml6030_info = {
.read_raw = veml6030_read_raw,
+ .read_avail = veml6030_read_avail,
.write_raw = veml6030_write_raw,
.read_event_value = veml6030_read_event_val,
.write_event_value = veml6030_write_event_val,
.read_event_config = veml6030_read_interrupt_config,
.write_event_config = veml6030_write_interrupt_config,
- .attrs = &veml6030_attr_group,
.event_attrs = &veml6030_event_attr_group,
};
static const struct iio_info veml6030_info_no_irq = {
.read_raw = veml6030_read_raw,
+ .read_avail = veml6030_read_avail,
.write_raw = veml6030_write_raw,
- .attrs = &veml6030_attr_group,
};
static irqreturn_t veml6030_event_handler(int irq, void *private)
@@ -717,65 +889,82 @@ static irqreturn_t veml6030_event_handler(int irq, void *private)
return IRQ_HANDLED;
}
+static int veml6030_set_info(struct iio_dev *indio_dev)
+{
+ struct veml6030_data *data = iio_priv(indio_dev);
+ struct i2c_client *client = data->client;
+ int ret;
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, veml6030_event_handler,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret < 0)
+ return dev_err_probe(&client->dev, ret,
+ "irq %d request failed\n",
+ client->irq);
+
+ indio_dev->info = &veml6030_info;
+ } else {
+ indio_dev->info = &veml6030_info_no_irq;
+ }
+
+ return 0;
+}
+
+static int veml7700_set_info(struct iio_dev *indio_dev)
+{
+ indio_dev->info = &veml6030_info_no_irq;
+
+ return 0;
+}
+
/*
* Set ALS gain to 1/8, integration time to 100 ms, PSM to mode 2,
* persistence to 1 x integration time and the threshold
* interrupt disabled by default. First shutdown the sensor,
* update registers and then power on the sensor.
*/
-static int veml6030_hw_init(struct iio_dev *indio_dev)
+static int veml6030_hw_init(struct iio_dev *indio_dev, struct device *dev)
{
int ret, val;
struct veml6030_data *data = iio_priv(indio_dev);
- struct i2c_client *client = data->client;
ret = veml6030_als_shut_down(data);
- if (ret) {
- dev_err(&client->dev, "can't shutdown als %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't shutdown als\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF, 0x1001);
- if (ret) {
- dev_err(&client->dev, "can't setup als configs %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup als configs\n");
ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
VEML6030_PSM | VEML6030_PSM_EN, 0x03);
- if (ret) {
- dev_err(&client->dev, "can't setup default PSM %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup default PSM\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF);
- if (ret) {
- dev_err(&client->dev, "can't setup high threshold %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup high threshold\n");
ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000);
- if (ret) {
- dev_err(&client->dev, "can't setup low threshold %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup low threshold\n");
ret = veml6030_als_pwr_on(data);
- if (ret) {
- dev_err(&client->dev, "can't poweron als %d\n", ret);
- return ret;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "can't poweron als\n");
- /* Wait 4 ms to let processor & oscillator start correctly */
- usleep_range(4000, 4002);
+ ret = devm_add_action_or_reset(dev, veml6030_als_shut_down_action, data);
+ if (ret < 0)
+ return ret;
/* Clear stale interrupt status bits if any during start */
ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val);
- if (ret < 0) {
- dev_err(&client->dev,
- "can't clear als interrupt status %d\n", ret);
- return ret;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "can't clear als interrupt status\n");
/* Cache currently active measurement parameters */
data->cur_gain = 3;
@@ -785,6 +974,62 @@ static int veml6030_hw_init(struct iio_dev *indio_dev)
return ret;
}
+/*
+ * Set ALS gain to 1/8, integration time to 100 ms, ALS and WHITE
+ * channel enabled, ALS channel interrupt, PSM enabled,
+ * PSM_WAIT = 0.8 s, persistence to 1 x integration time and the
+ * threshold interrupt disabled by default. First shutdown the sensor,
+ * update registers and then power on the sensor.
+ */
+static int veml6035_hw_init(struct iio_dev *indio_dev, struct device *dev)
+{
+ int ret, val;
+ struct veml6030_data *data = iio_priv(indio_dev);
+
+ ret = veml6030_als_shut_down(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't shutdown als\n");
+
+ ret = regmap_write(data->regmap, VEML6030_REG_ALS_CONF,
+ VEML6035_SENS | VEML6035_CHAN_EN | VEML6030_ALS_SD);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup als configs\n");
+
+ ret = regmap_update_bits(data->regmap, VEML6030_REG_ALS_PSM,
+ VEML6030_PSM | VEML6030_PSM_EN, 0x03);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup default PSM\n");
+
+ ret = regmap_write(data->regmap, VEML6030_REG_ALS_WH, 0xFFFF);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup high threshold\n");
+
+ ret = regmap_write(data->regmap, VEML6030_REG_ALS_WL, 0x0000);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't setup low threshold\n");
+
+ ret = veml6030_als_pwr_on(data);
+ if (ret)
+ return dev_err_probe(dev, ret, "can't poweron als\n");
+
+ ret = devm_add_action_or_reset(dev, veml6030_als_shut_down_action, data);
+ if (ret < 0)
+ return ret;
+
+ /* Clear stale interrupt status bits if any during start */
+ ret = regmap_read(data->regmap, VEML6030_REG_ALS_INT, &val);
+ if (ret < 0)
+ return dev_err_probe(dev, ret,
+ "can't clear als interrupt status\n");
+
+ /* Cache currently active measurement parameters */
+ data->cur_gain = 5;
+ data->cur_resolution = 1024;
+ data->cur_integration_time = 3;
+
+ return 0;
+}
+
static int veml6030_probe(struct i2c_client *client)
{
int ret;
@@ -792,16 +1037,14 @@ static int veml6030_probe(struct i2c_client *client)
struct iio_dev *indio_dev;
struct regmap *regmap;
- if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
- dev_err(&client->dev, "i2c adapter doesn't support plain i2c\n");
- return -EOPNOTSUPP;
- }
+ if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
+ return dev_err_probe(&client->dev, -EOPNOTSUPP,
+ "i2c adapter doesn't support plain i2c\n");
regmap = devm_regmap_init_i2c(client, &veml6030_regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&client->dev, "can't setup regmap\n");
- return PTR_ERR(regmap);
- }
+ if (IS_ERR(regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(regmap),
+ "can't setup regmap\n");
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -812,32 +1055,25 @@ static int veml6030_probe(struct i2c_client *client)
data->client = client;
data->regmap = regmap;
- indio_dev->name = "veml6030";
- indio_dev->channels = veml6030_channels;
- indio_dev->num_channels = ARRAY_SIZE(veml6030_channels);
- indio_dev->modes = INDIO_DIRECT_MODE;
+ ret = devm_regulator_get_enable(&client->dev, "vdd");
+ if (ret)
+ return dev_err_probe(&client->dev, ret,
+ "failed to enable regulator\n");
- if (client->irq) {
- ret = devm_request_threaded_irq(&client->dev, client->irq,
- NULL, veml6030_event_handler,
- IRQF_TRIGGER_LOW | IRQF_ONESHOT,
- "veml6030", indio_dev);
- if (ret < 0) {
- dev_err(&client->dev,
- "irq %d request failed\n", client->irq);
- return ret;
- }
- indio_dev->info = &veml6030_info;
- } else {
- indio_dev->info = &veml6030_info_no_irq;
- }
+ data->chip = i2c_get_match_data(client);
+ if (!data->chip)
+ return -EINVAL;
+
+ indio_dev->name = data->chip->name;
+ indio_dev->channels = data->chip->channels;
+ indio_dev->num_channels = data->chip->num_channels;
+ indio_dev->modes = INDIO_DIRECT_MODE;
- ret = veml6030_hw_init(indio_dev);
+ ret = data->chip->set_info(indio_dev);
if (ret < 0)
return ret;
- ret = devm_add_action_or_reset(&client->dev,
- veml6030_als_shut_down_action, data);
+ ret = data->chip->hw_init(indio_dev, &client->dev);
if (ret < 0)
return ret;
@@ -873,14 +1109,63 @@ static int veml6030_runtime_resume(struct device *dev)
static DEFINE_RUNTIME_DEV_PM_OPS(veml6030_pm_ops, veml6030_runtime_suspend,
veml6030_runtime_resume, NULL);
+static const struct veml603x_chip veml6030_chip = {
+ .name = "veml6030",
+ .scale_vals = &veml6030_scale_vals,
+ .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals),
+ .channels = veml6030_channels,
+ .num_channels = ARRAY_SIZE(veml6030_channels),
+ .hw_init = veml6030_hw_init,
+ .set_info = veml6030_set_info,
+ .set_als_gain = veml6030_set_als_gain,
+ .get_als_gain = veml6030_get_als_gain,
+};
+
+static const struct veml603x_chip veml6035_chip = {
+ .name = "veml6035",
+ .scale_vals = &veml6035_scale_vals,
+ .num_scale_vals = ARRAY_SIZE(veml6035_scale_vals),
+ .channels = veml6030_channels,
+ .num_channels = ARRAY_SIZE(veml6030_channels),
+ .hw_init = veml6035_hw_init,
+ .set_info = veml6030_set_info,
+ .set_als_gain = veml6035_set_als_gain,
+ .get_als_gain = veml6035_get_als_gain,
+};
+
+static const struct veml603x_chip veml7700_chip = {
+ .name = "veml7700",
+ .scale_vals = &veml6030_scale_vals,
+ .num_scale_vals = ARRAY_SIZE(veml6030_scale_vals),
+ .channels = veml7700_channels,
+ .num_channels = ARRAY_SIZE(veml7700_channels),
+ .hw_init = veml6030_hw_init,
+ .set_info = veml7700_set_info,
+ .set_als_gain = veml6030_set_als_gain,
+ .get_als_gain = veml6030_get_als_gain,
+};
+
static const struct of_device_id veml6030_of_match[] = {
- { .compatible = "vishay,veml6030" },
+ {
+ .compatible = "vishay,veml6030",
+ .data = &veml6030_chip,
+ },
+ {
+ .compatible = "vishay,veml6035",
+ .data = &veml6035_chip,
+ },
+ {
+ .compatible = "vishay,veml7700",
+ .data = &veml7700_chip,
+ },
{ }
};
MODULE_DEVICE_TABLE(of, veml6030_of_match);
static const struct i2c_device_id veml6030_id[] = {
- { "veml6030" },
+ { "veml6030", (kernel_ulong_t)&veml6030_chip},
+ { "veml6035", (kernel_ulong_t)&veml6035_chip},
+ { "veml7700", (kernel_ulong_t)&veml7700_chip},
{ }
};
MODULE_DEVICE_TABLE(i2c, veml6030_id);
diff --git a/drivers/iio/light/veml6070.c b/drivers/iio/light/veml6070.c
index f8321d346d77..6d4483c85f30 100644
--- a/drivers/iio/light/veml6070.c
+++ b/drivers/iio/light/veml6070.c
@@ -6,14 +6,16 @@
*
* IIO driver for VEML6070 (7-bit I2C slave addresses 0x38 and 0x39)
*
- * TODO: integration time, ACK signal
+ * TODO: ACK signal
*/
+#include <linux/bitfield.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
#include <linux/err.h>
#include <linux/delay.h>
+#include <linux/units.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
@@ -28,50 +30,113 @@
#define VEML6070_COMMAND_RSRVD BIT(1) /* reserved, set to 1 */
#define VEML6070_COMMAND_SD BIT(0) /* shutdown mode when set */
-#define VEML6070_IT_10 0x04 /* integration time 1x */
+#define VEML6070_IT_05 0x00
+#define VEML6070_IT_10 0x01
+#define VEML6070_IT_20 0x02
+#define VEML6070_IT_40 0x03
+
+#define VEML6070_MIN_RSET_KOHM 75
+#define VEML6070_MIN_IT_US 15625 /* Rset = 75 kohm, IT = 1/2 */
struct veml6070_data {
struct i2c_client *client1;
struct i2c_client *client2;
u8 config;
struct mutex lock;
+ u32 rset;
+ int it[4][2];
};
+static int veml6070_calc_it(struct device *dev, struct veml6070_data *data)
+{
+ int i, tmp_it;
+
+ data->rset = 270000;
+ device_property_read_u32(dev, "vishay,rset-ohms", &data->rset);
+
+ if (data->rset < 75000 || data->rset > 1200000)
+ return dev_err_probe(dev, -EINVAL, "Rset out of range\n");
+
+ /*
+ * convert to kohm to avoid overflows and work with the same units as
+ * in the datasheet and simplify UVI operations.
+ */
+ data->rset /= KILO;
+
+ tmp_it = VEML6070_MIN_IT_US * data->rset / VEML6070_MIN_RSET_KOHM;
+ for (i = 0; i < ARRAY_SIZE(data->it); i++) {
+ data->it[i][0] = (tmp_it << i) / MICRO;
+ data->it[i][1] = (tmp_it << i) % MICRO;
+ }
+
+ return 0;
+}
+
+static int veml6070_get_it(struct veml6070_data *data, int *val, int *val2)
+{
+ int it_idx = FIELD_GET(VEML6070_COMMAND_IT, data->config);
+
+ *val = data->it[it_idx][0];
+ *val2 = data->it[it_idx][1];
+
+ return IIO_VAL_INT_PLUS_MICRO;
+}
+
+static int veml6070_set_it(struct veml6070_data *data, int val, int val2)
+{
+ int it_idx;
+
+ for (it_idx = 0; it_idx < ARRAY_SIZE(data->it); it_idx++) {
+ if (data->it[it_idx][0] == val && data->it[it_idx][1] == val2)
+ break;
+ }
+
+ if (it_idx >= ARRAY_SIZE(data->it))
+ return -EINVAL;
+
+ data->config = (data->config & ~VEML6070_COMMAND_IT) |
+ FIELD_PREP(VEML6070_COMMAND_IT, it_idx);
+
+ return i2c_smbus_write_byte(data->client1, data->config);
+}
+
static int veml6070_read(struct veml6070_data *data)
{
- int ret;
+ int ret, it_ms, val, val2;
u8 msb, lsb;
- mutex_lock(&data->lock);
+ guard(mutex)(&data->lock);
/* disable shutdown */
ret = i2c_smbus_write_byte(data->client1,
data->config & ~VEML6070_COMMAND_SD);
if (ret < 0)
- goto out;
+ return ret;
- msleep(125 + 10); /* measurement takes up to 125 ms for IT 1x */
+ veml6070_get_it(data, &val, &val2);
+ it_ms = val * MILLI + val2 / (MICRO / MILLI);
+ msleep(it_ms + 10);
ret = i2c_smbus_read_byte(data->client2); /* read MSB, address 0x39 */
if (ret < 0)
- goto out;
+ return ret;
+
msb = ret;
ret = i2c_smbus_read_byte(data->client1); /* read LSB, address 0x38 */
if (ret < 0)
- goto out;
+ return ret;
+
lsb = ret;
/* shutdown again */
ret = i2c_smbus_write_byte(data->client1, data->config);
if (ret < 0)
- goto out;
+ return ret;
ret = (msb << 8) | lsb;
-out:
- mutex_unlock(&data->lock);
- return ret;
+ return 0;
}
static const struct iio_chan_spec veml6070_channels[] = {
@@ -80,26 +145,37 @@ static const struct iio_chan_spec veml6070_channels[] = {
.modified = 1,
.channel2 = IIO_MOD_LIGHT_UV,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
},
{
.type = IIO_UVINDEX,
.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
+ .info_mask_shared_by_all = BIT(IIO_CHAN_INFO_INT_TIME),
+ .info_mask_shared_by_all_available = BIT(IIO_CHAN_INFO_INT_TIME),
}
};
-static int veml6070_to_uv_index(unsigned val)
+static int veml6070_to_uv_index(struct veml6070_data *data, unsigned int val)
{
/*
* conversion of raw UV intensity values to UV index depends on
* integration time (IT) and value of the resistor connected to
- * the RSET pin (default: 270 KOhm)
+ * the RSET pin.
*/
- unsigned uvi[11] = {
+ unsigned int uvi[11] = {
187, 373, 560, /* low */
746, 933, 1120, /* moderate */
1308, 1494, /* high */
1681, 1868, 2054}; /* very high */
- int i;
+ int i, it_idx;
+
+ it_idx = FIELD_GET(VEML6070_COMMAND_IT, data->config);
+
+ if (!it_idx)
+ val = (val * 270 / data->rset) << 1;
+ else
+ val = (val * 270 / data->rset) >> (it_idx - 1);
for (i = 0; i < ARRAY_SIZE(uvi); i++)
if (val <= uvi[i])
@@ -122,10 +198,44 @@ static int veml6070_read_raw(struct iio_dev *indio_dev,
if (ret < 0)
return ret;
if (mask == IIO_CHAN_INFO_PROCESSED)
- *val = veml6070_to_uv_index(ret);
+ *val = veml6070_to_uv_index(data, ret);
else
*val = ret;
return IIO_VAL_INT;
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml6070_get_it(data, val, val2);
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml6070_read_avail(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ const int **vals, int *type, int *length,
+ long mask)
+{
+ struct veml6070_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ *vals = (int *)data->it;
+ *length = 2 * ARRAY_SIZE(data->it);
+ *type = IIO_VAL_INT_PLUS_MICRO;
+ return IIO_AVAIL_LIST;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int veml6070_write_raw(struct iio_dev *indio_dev,
+ struct iio_chan_spec const *chan,
+ int val, int val2, long mask)
+{
+ struct veml6070_data *data = iio_priv(indio_dev);
+
+ switch (mask) {
+ case IIO_CHAN_INFO_INT_TIME:
+ return veml6070_set_it(data, val, val2);
default:
return -EINVAL;
}
@@ -133,8 +243,17 @@ static int veml6070_read_raw(struct iio_dev *indio_dev,
static const struct iio_info veml6070_info = {
.read_raw = veml6070_read_raw,
+ .read_avail = veml6070_read_avail,
+ .write_raw = veml6070_write_raw,
};
+static void veml6070_i2c_unreg(void *p)
+{
+ struct veml6070_data *data = p;
+
+ i2c_unregister_device(data->client2);
+}
+
static int veml6070_probe(struct i2c_client *client)
{
struct veml6070_data *data;
@@ -156,36 +275,30 @@ static int veml6070_probe(struct i2c_client *client)
indio_dev->name = VEML6070_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
- data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB);
- if (IS_ERR(data->client2)) {
- dev_err(&client->dev, "i2c device for second chip address failed\n");
- return PTR_ERR(data->client2);
- }
-
- data->config = VEML6070_IT_10 | VEML6070_COMMAND_RSRVD |
- VEML6070_COMMAND_SD;
- ret = i2c_smbus_write_byte(data->client1, data->config);
+ ret = veml6070_calc_it(&client->dev, data);
if (ret < 0)
- goto fail;
+ return ret;
- ret = iio_device_register(indio_dev);
+ ret = devm_regulator_get_enable(&client->dev, "vdd");
if (ret < 0)
- goto fail;
+ return ret;
- return ret;
+ data->client2 = i2c_new_dummy_device(client->adapter, VEML6070_ADDR_DATA_LSB);
+ if (IS_ERR(data->client2))
+ return dev_err_probe(&client->dev, PTR_ERR(data->client2),
+ "i2c device for second chip address failed\n");
-fail:
- i2c_unregister_device(data->client2);
- return ret;
-}
+ data->config = FIELD_PREP(VEML6070_COMMAND_IT, VEML6070_IT_10) |
+ VEML6070_COMMAND_RSRVD | VEML6070_COMMAND_SD;
+ ret = i2c_smbus_write_byte(data->client1, data->config);
+ if (ret < 0)
+ return ret;
-static void veml6070_remove(struct i2c_client *client)
-{
- struct iio_dev *indio_dev = i2c_get_clientdata(client);
- struct veml6070_data *data = iio_priv(indio_dev);
+ ret = devm_add_action_or_reset(&client->dev, veml6070_i2c_unreg, data);
+ if (ret < 0)
+ return ret;
- iio_device_unregister(indio_dev);
- i2c_unregister_device(data->client2);
+ return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id veml6070_id[] = {
@@ -194,12 +307,18 @@ static const struct i2c_device_id veml6070_id[] = {
};
MODULE_DEVICE_TABLE(i2c, veml6070_id);
+static const struct of_device_id veml6070_of_match[] = {
+ { .compatible = "vishay,veml6070" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, veml6070_of_match);
+
static struct i2c_driver veml6070_driver = {
.driver = {
.name = VEML6070_DRV_NAME,
+ .of_match_table = veml6070_of_match,
},
.probe = veml6070_probe,
- .remove = veml6070_remove,
.id_table = veml6070_id,
};
diff --git a/drivers/iio/light/vl6180.c b/drivers/iio/light/vl6180.c
index a1b2b3c0b4c8..6e2183a4243e 100644
--- a/drivers/iio/light/vl6180.c
+++ b/drivers/iio/light/vl6180.c
@@ -25,6 +25,10 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#define VL6180_DRV_NAME "vl6180"
@@ -38,7 +42,9 @@
#define VL6180_OUT_OF_RESET 0x016
#define VL6180_HOLD 0x017
#define VL6180_RANGE_START 0x018
+#define VL6180_RANGE_INTER_MEAS_TIME 0x01b
#define VL6180_ALS_START 0x038
+#define VL6180_ALS_INTER_MEAS_TIME 0x03e
#define VL6180_ALS_GAIN 0x03f
#define VL6180_ALS_IT 0x040
@@ -84,8 +90,17 @@
struct vl6180_data {
struct i2c_client *client;
struct mutex lock;
+ struct completion completion;
+ struct iio_trigger *trig;
unsigned int als_gain_milli;
unsigned int als_it_ms;
+ unsigned int als_meas_rate;
+ unsigned int range_meas_rate;
+
+ struct {
+ u16 chan[2];
+ aligned_s64 timestamp;
+ } scan;
};
enum { VL6180_ALS, VL6180_RANGE, VL6180_PROX };
@@ -207,29 +222,40 @@ static int vl6180_write_word(struct i2c_client *client, u16 cmd, u16 val)
static int vl6180_measure(struct vl6180_data *data, int addr)
{
struct i2c_client *client = data->client;
+ unsigned long time_left;
int tries = 20, ret;
u16 value;
mutex_lock(&data->lock);
+ reinit_completion(&data->completion);
+
/* Start single shot measurement */
ret = vl6180_write_byte(client,
vl6180_chan_regs_table[addr].start_reg, VL6180_STARTSTOP);
if (ret < 0)
goto fail;
- while (tries--) {
- ret = vl6180_read_byte(client, VL6180_INTR_STATUS);
- if (ret < 0)
+ if (client->irq) {
+ time_left = wait_for_completion_timeout(&data->completion, HZ / 10);
+ if (time_left == 0) {
+ ret = -ETIMEDOUT;
goto fail;
+ }
+ } else {
+ while (tries--) {
+ ret = vl6180_read_byte(client, VL6180_INTR_STATUS);
+ if (ret < 0)
+ goto fail;
+
+ if (ret & vl6180_chan_regs_table[addr].drdy_mask)
+ break;
+ msleep(20);
+ }
- if (ret & vl6180_chan_regs_table[addr].drdy_mask)
- break;
- msleep(20);
- }
-
- if (tries < 0) {
- ret = -EIO;
- goto fail;
+ if (tries < 0) {
+ ret = -EIO;
+ goto fail;
+ }
}
/* Read result value from appropriate registers */
@@ -258,20 +284,41 @@ static const struct iio_chan_spec vl6180_channels[] = {
{
.type = IIO_LIGHT,
.address = VL6180_ALS,
+ .scan_index = VL6180_ALS,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ },
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_INT_TIME) |
BIT(IIO_CHAN_INFO_SCALE) |
- BIT(IIO_CHAN_INFO_HARDWAREGAIN),
+ BIT(IIO_CHAN_INFO_HARDWAREGAIN) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
}, {
.type = IIO_DISTANCE,
.address = VL6180_RANGE,
+ .scan_index = VL6180_RANGE,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 8,
+ .storagebits = 8,
+ },
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
- BIT(IIO_CHAN_INFO_SCALE),
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_SAMP_FREQ),
}, {
.type = IIO_PROXIMITY,
.address = VL6180_PROX,
+ .scan_index = VL6180_PROX,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ },
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
- }
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(3),
};
/*
@@ -333,6 +380,18 @@ static int vl6180_read_raw(struct iio_dev *indio_dev,
return IIO_VAL_FRACTIONAL;
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ switch (chan->type) {
+ case IIO_DISTANCE:
+ *val = data->range_meas_rate;
+ return IIO_VAL_INT;
+ case IIO_LIGHT:
+ *val = data->als_meas_rate;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+
default:
return -EINVAL;
}
@@ -412,11 +471,23 @@ fail:
return ret;
}
+static int vl6180_meas_reg_val_from_mhz(unsigned int mhz)
+{
+ unsigned int period = DIV_ROUND_CLOSEST(1000 * 1000, mhz);
+ unsigned int reg_val = 0;
+
+ if (period > 10)
+ reg_val = period < 2550 ? (DIV_ROUND_CLOSEST(period, 10) - 1) : 254;
+
+ return reg_val;
+}
+
static int vl6180_write_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int val, int val2, long mask)
{
struct vl6180_data *data = iio_priv(indio_dev);
+ unsigned int reg_val;
switch (mask) {
case IIO_CHAN_INFO_INT_TIME:
@@ -427,18 +498,126 @@ static int vl6180_write_raw(struct iio_dev *indio_dev,
return -EINVAL;
return vl6180_set_als_gain(data, val, val2);
+
+ case IIO_CHAN_INFO_SAMP_FREQ:
+ {
+ guard(mutex)(&data->lock);
+ switch (chan->type) {
+ case IIO_DISTANCE:
+ data->range_meas_rate = val;
+ reg_val = vl6180_meas_reg_val_from_mhz(val);
+ return vl6180_write_byte(data->client,
+ VL6180_RANGE_INTER_MEAS_TIME, reg_val);
+
+ case IIO_LIGHT:
+ data->als_meas_rate = val;
+ reg_val = vl6180_meas_reg_val_from_mhz(val);
+ return vl6180_write_byte(data->client,
+ VL6180_ALS_INTER_MEAS_TIME, reg_val);
+
+ default:
+ return -EINVAL;
+ }
+ }
+
default:
return -EINVAL;
}
}
+static irqreturn_t vl6180_threaded_irq(int irq, void *priv)
+{
+ struct iio_dev *indio_dev = priv;
+ struct vl6180_data *data = iio_priv(indio_dev);
+
+ if (iio_buffer_enabled(indio_dev))
+ iio_trigger_poll_nested(indio_dev->trig);
+ else
+ complete(&data->completion);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t vl6180_trigger_handler(int irq, void *priv)
+{
+ struct iio_poll_func *pf = priv;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct vl6180_data *data = iio_priv(indio_dev);
+ s64 time_ns = iio_get_time_ns(indio_dev);
+ int ret, bit, i = 0;
+
+ iio_for_each_active_channel(indio_dev, bit) {
+ if (vl6180_chan_regs_table[bit].word)
+ ret = vl6180_read_word(data->client,
+ vl6180_chan_regs_table[bit].value_reg);
+ else
+ ret = vl6180_read_byte(data->client,
+ vl6180_chan_regs_table[bit].value_reg);
+
+ if (ret < 0) {
+ dev_err(&data->client->dev,
+ "failed to read from value regs: %d\n", ret);
+ return IRQ_HANDLED;
+ }
+
+ data->scan.chan[i++] = ret;
+ }
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan, time_ns);
+ iio_trigger_notify_done(indio_dev->trig);
+
+ /* Clear the interrupt flag after data read */
+ ret = vl6180_write_byte(data->client, VL6180_INTR_CLEAR,
+ VL6180_CLEAR_ERROR | VL6180_CLEAR_ALS | VL6180_CLEAR_RANGE);
+ if (ret < 0)
+ dev_err(&data->client->dev, "failed to clear irq: %d\n", ret);
+
+ return IRQ_HANDLED;
+}
+
static const struct iio_info vl6180_info = {
.read_raw = vl6180_read_raw,
.write_raw = vl6180_write_raw,
.attrs = &vl6180_attribute_group,
+ .validate_trigger = iio_validate_own_trigger,
+};
+
+static int vl6180_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct vl6180_data *data = iio_priv(indio_dev);
+ int bit;
+
+ iio_for_each_active_channel(indio_dev, bit)
+ return vl6180_write_byte(data->client,
+ vl6180_chan_regs_table[bit].start_reg,
+ VL6180_MODE_CONT | VL6180_STARTSTOP);
+
+ return -EINVAL;
+}
+
+static int vl6180_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct vl6180_data *data = iio_priv(indio_dev);
+ int bit;
+
+ iio_for_each_active_channel(indio_dev, bit)
+ return vl6180_write_byte(data->client,
+ vl6180_chan_regs_table[bit].start_reg,
+ VL6180_STARTSTOP);
+
+ return -EINVAL;
+}
+
+static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
+ .postenable = &vl6180_buffer_postenable,
+ .postdisable = &vl6180_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops vl6180_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
};
-static int vl6180_init(struct vl6180_data *data)
+static int vl6180_init(struct vl6180_data *data, struct iio_dev *indio_dev)
{
struct i2c_client *client = data->client;
int ret;
@@ -473,6 +652,26 @@ static int vl6180_init(struct vl6180_data *data)
if (ret < 0)
return ret;
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
+ &vl6180_trigger_handler,
+ &iio_triggered_buffer_setup_ops);
+ if (ret)
+ return ret;
+
+ /* Default Range inter-measurement time: 50ms or 20000 mHz */
+ ret = vl6180_write_byte(client, VL6180_RANGE_INTER_MEAS_TIME,
+ vl6180_meas_reg_val_from_mhz(20000));
+ if (ret < 0)
+ return ret;
+ data->range_meas_rate = 20000;
+
+ /* Default ALS inter-measurement time: 10ms or 100000 mHz */
+ ret = vl6180_write_byte(client, VL6180_ALS_INTER_MEAS_TIME,
+ vl6180_meas_reg_val_from_mhz(100000));
+ if (ret < 0)
+ return ret;
+ data->als_meas_rate = 100000;
+
/* ALS integration time: 100ms */
data->als_it_ms = 100;
ret = vl6180_write_word(client, VL6180_ALS_IT, VL6180_ALS_IT_100);
@@ -513,10 +712,34 @@ static int vl6180_probe(struct i2c_client *client)
indio_dev->name = VL6180_DRV_NAME;
indio_dev->modes = INDIO_DIRECT_MODE;
- ret = vl6180_init(data);
+ ret = vl6180_init(data, indio_dev);
if (ret < 0)
return ret;
+ if (client->irq) {
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, vl6180_threaded_irq,
+ IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret)
+ return dev_err_probe(&client->dev, ret, "devm_request_irq error \n");
+
+ init_completion(&data->completion);
+
+ data->trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
+ indio_dev->name, iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = &vl6180_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+ ret = devm_iio_trigger_register(&client->dev, data->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+ }
+
return devm_iio_device_register(&client->dev, indio_dev);
}
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index f69ac75500f9..7177cd1d67cb 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -54,6 +54,19 @@ config AK09911
help
Deprecated: AK09911 is now supported by AK8975 driver.
+config ALS31300
+ tristate "Allegro MicroSystems ALS31300 3-D Linear Hall Effect Sensor"
+ depends on I2C
+ select REGMAP_I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
+ help
+ Say yes here to build support for the Allegro MicroSystems
+ ALS31300 Hall Effect Sensor through its I2C interface.
+
+ To compile this driver as a module, choose M here: the
+ module will be called als31300.
+
config BMC150_MAGN
tristate
select IIO_BUFFER
diff --git a/drivers/iio/magnetometer/Makefile b/drivers/iio/magnetometer/Makefile
index ec5c46fbf999..3e4c2ecd9adf 100644
--- a/drivers/iio/magnetometer/Makefile
+++ b/drivers/iio/magnetometer/Makefile
@@ -7,6 +7,7 @@
obj-$(CONFIG_AF8133J) += af8133j.o
obj-$(CONFIG_AK8974) += ak8974.o
obj-$(CONFIG_AK8975) += ak8975.o
+obj-$(CONFIG_ALS31300) += als31300.o
obj-$(CONFIG_BMC150_MAGN) += bmc150_magn.o
obj-$(CONFIG_BMC150_MAGN_I2C) += bmc150_magn_i2c.o
obj-$(CONFIG_BMC150_MAGN_SPI) += bmc150_magn_spi.o
diff --git a/drivers/iio/magnetometer/ak8974.c b/drivers/iio/magnetometer/ak8974.c
index 961b1e0bfb13..8306a18706ac 100644
--- a/drivers/iio/magnetometer/ak8974.c
+++ b/drivers/iio/magnetometer/ak8974.c
@@ -910,7 +910,7 @@ static int ak8974_probe(struct i2c_client *i2c)
/* If we have a valid DRDY IRQ, make use of it */
if (irq > 0) {
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
+ irq_trig = irq_get_trigger_type(irq);
if (irq_trig == IRQF_TRIGGER_RISING) {
dev_info(&i2c->dev, "enable rising edge DRDY IRQ\n");
} else if (irq_trig == IRQF_TRIGGER_FALLING) {
diff --git a/drivers/iio/magnetometer/als31300.c b/drivers/iio/magnetometer/als31300.c
new file mode 100644
index 000000000000..87b60c4e81fa
--- /dev/null
+++ b/drivers/iio/magnetometer/als31300.c
@@ -0,0 +1,494 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for the Allegro MicroSystems ALS31300 3-D Linear Hall Effect Sensor
+ *
+ * Copyright (c) 2024 Linaro Limited
+ */
+
+#include <linux/bits.h>
+#include <linux/bitfield.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/types.h>
+#include <linux/units.h>
+
+#include <linux/iio/buffer.h>
+#include <linux/iio/iio.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
+
+/*
+ * The Allegro MicroSystems ALS31300 has an EEPROM space to configure how
+ * the device works and how the interrupt line behaves.
+ * Only the default setup with external trigger is supported.
+ *
+ * While the bindings supports declaring an interrupt line, those
+ * events are not supported.
+ *
+ * It should be possible to adapt the driver to the current
+ * device EEPROM setup at runtime.
+ */
+
+#define ALS31300_EEPROM_CONFIG 0x02
+#define ALS31300_EEPROM_INTERRUPT 0x03
+#define ALS31300_EEPROM_CUSTOMER_1 0x0d
+#define ALS31300_EEPROM_CUSTOMER_2 0x0e
+#define ALS31300_EEPROM_CUSTOMER_3 0x0f
+#define ALS31300_VOL_MODE 0x27
+#define ALS31300_VOL_MODE_LPDCM GENMASK(6, 4)
+#define ALS31300_LPDCM_INACTIVE_0_5_MS 0
+#define ALS31300_LPDCM_INACTIVE_1_0_MS 1
+#define ALS31300_LPDCM_INACTIVE_5_0_MS 2
+#define ALS31300_LPDCM_INACTIVE_10_0_MS 3
+#define ALS31300_LPDCM_INACTIVE_50_0_MS 4
+#define ALS31300_LPDCM_INACTIVE_100_0_MS 5
+#define ALS31300_LPDCM_INACTIVE_500_0_MS 6
+#define ALS31300_LPDCM_INACTIVE_1000_0_MS 7
+#define ALS31300_VOL_MODE_SLEEP GENMASK(1, 0)
+#define ALS31300_VOL_MODE_ACTIVE_MODE 0
+#define ALS31300_VOL_MODE_SLEEP_MODE 1
+#define ALS31300_VOL_MODE_LPDCM_MODE 2
+#define ALS31300_VOL_MSB 0x28
+#define ALS31300_VOL_MSB_TEMPERATURE GENMASK(5, 0)
+#define ALS31300_VOL_MSB_INTERRUPT BIT(6)
+#define ALS31300_VOL_MSB_NEW_DATA BIT(7)
+#define ALS31300_VOL_MSB_Z_AXIS GENMASK(15, 8)
+#define ALS31300_VOL_MSB_Y_AXIS GENMASK(23, 16)
+#define ALS31300_VOL_MSB_X_AXIS GENMASK(31, 24)
+#define ALS31300_VOL_LSB 0x29
+#define ALS31300_VOL_LSB_TEMPERATURE GENMASK(5, 0)
+#define ALS31300_VOL_LSB_HALL_STATUS GENMASK(7, 7)
+#define ALS31300_VOL_LSB_Z_AXIS GENMASK(11, 8)
+#define ALS31300_VOL_LSB_Y_AXIS GENMASK(15, 12)
+#define ALS31300_VOL_LSB_X_AXIS GENMASK(19, 16)
+#define ALS31300_VOL_LSB_INTERRUPT_WRITE BIT(20)
+#define ALS31300_CUSTOMER_ACCESS 0x35
+
+#define ALS31300_DATA_X_GET(b) \
+ sign_extend32(FIELD_GET(ALS31300_VOL_MSB_X_AXIS, b[0]) << 4 | \
+ FIELD_GET(ALS31300_VOL_LSB_X_AXIS, b[1]), 11)
+#define ALS31300_DATA_Y_GET(b) \
+ sign_extend32(FIELD_GET(ALS31300_VOL_MSB_Y_AXIS, b[0]) << 4 | \
+ FIELD_GET(ALS31300_VOL_LSB_Y_AXIS, b[1]), 11)
+#define ALS31300_DATA_Z_GET(b) \
+ sign_extend32(FIELD_GET(ALS31300_VOL_MSB_Z_AXIS, b[0]) << 4 | \
+ FIELD_GET(ALS31300_VOL_LSB_Z_AXIS, b[1]), 11)
+#define ALS31300_TEMPERATURE_GET(b) \
+ (FIELD_GET(ALS31300_VOL_MSB_TEMPERATURE, b[0]) << 6 | \
+ FIELD_GET(ALS31300_VOL_LSB_TEMPERATURE, b[1]))
+
+enum als31300_channels {
+ TEMPERATURE = 0,
+ AXIS_X,
+ AXIS_Y,
+ AXIS_Z,
+};
+
+struct als31300_variant_info {
+ u8 sensitivity;
+};
+
+struct als31300_data {
+ struct device *dev;
+ /* protects power on/off the device and access HW */
+ struct mutex mutex;
+ const struct als31300_variant_info *variant_info;
+ struct regmap *map;
+};
+
+/* The whole measure is split into 2x32-bit registers, we need to read them both at once */
+static int als31300_get_measure(struct als31300_data *data,
+ u16 *t, s16 *x, s16 *y, s16 *z)
+{
+ u32 buf[2];
+ int ret, err;
+
+ guard(mutex)(&data->mutex);
+
+ ret = pm_runtime_resume_and_get(data->dev);
+ if (ret)
+ return ret;
+
+ /*
+ * Loop until data is valid, new data should have the
+ * ALS31300_VOL_MSB_NEW_DATA bit set to 1.
+ * Max update rate is 2KHz, wait up to 1ms.
+ */
+ ret = read_poll_timeout(regmap_bulk_read, err,
+ err || FIELD_GET(ALS31300_VOL_MSB_NEW_DATA, buf[0]),
+ 20, USEC_PER_MSEC, false,
+ data->map, ALS31300_VOL_MSB, buf, ARRAY_SIZE(buf));
+ /* Bail out on read_poll_timeout() error */
+ if (ret)
+ goto out;
+
+ /* Bail out on regmap_bulk_read() error */
+ if (err) {
+ dev_err(data->dev, "read data failed, error %d\n", ret);
+ ret = err;
+ goto out;
+ }
+
+ *t = ALS31300_TEMPERATURE_GET(buf);
+ *x = ALS31300_DATA_X_GET(buf);
+ *y = ALS31300_DATA_Y_GET(buf);
+ *z = ALS31300_DATA_Z_GET(buf);
+
+out:
+ pm_runtime_mark_last_busy(data->dev);
+ pm_runtime_put_autosuspend(data->dev);
+
+ return ret;
+}
+
+static int als31300_read_raw(struct iio_dev *indio_dev,
+ const struct iio_chan_spec *chan, int *val,
+ int *val2, long mask)
+{
+ struct als31300_data *data = iio_priv(indio_dev);
+ s16 x, y, z;
+ u16 t;
+ int ret;
+
+ switch (mask) {
+ case IIO_CHAN_INFO_PROCESSED:
+ case IIO_CHAN_INFO_RAW:
+ ret = als31300_get_measure(data, &t, &x, &y, &z);
+ if (ret)
+ return ret;
+
+ switch (chan->address) {
+ case TEMPERATURE:
+ *val = t;
+ return IIO_VAL_INT;
+ case AXIS_X:
+ *val = x;
+ return IIO_VAL_INT;
+ case AXIS_Y:
+ *val = y;
+ return IIO_VAL_INT;
+ case AXIS_Z:
+ *val = z;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_SCALE:
+ switch (chan->type) {
+ case IIO_TEMP:
+ /*
+ * Fractional part of:
+ * 1000 * 302 * (value - 1708)
+ * temp = ----------------------------
+ * 4096
+ * to convert temperature in millicelcius.
+ */
+ *val = MILLI * 302;
+ *val2 = 4096;
+ return IIO_VAL_FRACTIONAL;
+ case IIO_MAGN:
+ /*
+ * Devices are configured in factory
+ * with different sensitivities:
+ * - 500 GAUSS <-> 4 LSB/Gauss
+ * - 1000 GAUSS <-> 2 LSB/Gauss
+ * - 2000 GAUSS <-> 1 LSB/Gauss
+ * with translates by a division of the returned
+ * value to get Gauss value.
+ * The sensitivity cannot be read at runtime
+ * so the value depends on the model compatible
+ * or device id.
+ */
+ *val = 1;
+ *val2 = data->variant_info->sensitivity;
+ return IIO_VAL_FRACTIONAL;
+ default:
+ return -EINVAL;
+ }
+ case IIO_CHAN_INFO_OFFSET:
+ switch (chan->type) {
+ case IIO_TEMP:
+ *val = -1708;
+ return IIO_VAL_INT;
+ default:
+ return -EINVAL;
+ }
+ default:
+ return -EINVAL;
+ }
+}
+
+static irqreturn_t als31300_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct als31300_data *data = iio_priv(indio_dev);
+ struct {
+ u16 temperature;
+ s16 channels[3];
+ aligned_s64 timestamp;
+ } scan;
+ s16 x, y, z;
+ int ret;
+ u16 t;
+
+ ret = als31300_get_measure(data, &t, &x, &y, &z);
+ if (ret)
+ goto trigger_out;
+
+ scan.temperature = t;
+ scan.channels[0] = x;
+ scan.channels[1] = y;
+ scan.channels[2] = z;
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
+ pf->timestamp);
+
+trigger_out:
+ iio_trigger_notify_done(indio_dev->trig);
+
+ return IRQ_HANDLED;
+}
+
+#define ALS31300_AXIS_CHANNEL(axis, index) \
+ { \
+ .type = IIO_MAGN, \
+ .modified = 1, \
+ .channel2 = IIO_MOD_##axis, \
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
+ BIT(IIO_CHAN_INFO_SCALE), \
+ .address = index, \
+ .scan_index = index, \
+ .scan_type = { \
+ .sign = 's', \
+ .realbits = 12, \
+ .storagebits = 16, \
+ .endianness = IIO_CPU, \
+ }, \
+ }
+
+static const struct iio_chan_spec als31300_channels[] = {
+ {
+ .type = IIO_TEMP,
+ .info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
+ BIT(IIO_CHAN_INFO_SCALE) |
+ BIT(IIO_CHAN_INFO_OFFSET),
+ .address = TEMPERATURE,
+ .scan_index = TEMPERATURE,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_CPU,
+ },
+ },
+ ALS31300_AXIS_CHANNEL(X, AXIS_X),
+ ALS31300_AXIS_CHANNEL(Y, AXIS_Y),
+ ALS31300_AXIS_CHANNEL(Z, AXIS_Z),
+ IIO_CHAN_SOFT_TIMESTAMP(4),
+};
+
+static const struct iio_info als31300_info = {
+ .read_raw = als31300_read_raw,
+};
+
+static int als31300_set_operating_mode(struct als31300_data *data,
+ unsigned int val)
+{
+ int ret;
+
+ ret = regmap_update_bits(data->map, ALS31300_VOL_MODE,
+ ALS31300_VOL_MODE_SLEEP, val);
+ if (ret) {
+ dev_err(data->dev, "failed to set operating mode (%pe)\n", ERR_PTR(ret));
+ return ret;
+ }
+
+ /* The time it takes to exit sleep mode is equivalent to Power-On Delay Time */
+ if (val == ALS31300_VOL_MODE_ACTIVE_MODE)
+ fsleep(600);
+
+ return 0;
+}
+
+static void als31300_power_down(void *data)
+{
+ als31300_set_operating_mode(data, ALS31300_VOL_MODE_SLEEP_MODE);
+}
+
+static const struct iio_buffer_setup_ops als31300_setup_ops = {};
+
+static const unsigned long als31300_scan_masks[] = { GENMASK(3, 0), 0 };
+
+static bool als31300_volatile_reg(struct device *dev, unsigned int reg)
+{
+ return reg == ALS31300_VOL_MSB || reg == ALS31300_VOL_LSB;
+}
+
+static const struct regmap_config als31300_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 32,
+ .max_register = ALS31300_CUSTOMER_ACCESS,
+ .volatile_reg = als31300_volatile_reg,
+};
+
+static int als31300_probe(struct i2c_client *i2c)
+{
+ struct device *dev = &i2c->dev;
+ struct als31300_data *data;
+ struct iio_dev *indio_dev;
+ int ret;
+
+ indio_dev = devm_iio_device_alloc(dev, sizeof(*data));
+ if (!indio_dev)
+ return -ENOMEM;
+
+ data = iio_priv(indio_dev);
+ data->dev = dev;
+ i2c_set_clientdata(i2c, indio_dev);
+
+ ret = devm_mutex_init(dev, &data->mutex);
+ if (ret)
+ return ret;
+
+ data->variant_info = i2c_get_match_data(i2c);
+ if (!data->variant_info)
+ return -EINVAL;
+
+ data->map = devm_regmap_init_i2c(i2c, &als31300_regmap_config);
+ if (IS_ERR(data->map))
+ return dev_err_probe(dev, PTR_ERR(data->map),
+ "failed to allocate register map\n");
+
+ ret = devm_regulator_get_enable(dev, "vcc");
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to enable regulator\n");
+
+ ret = als31300_set_operating_mode(data, ALS31300_VOL_MODE_ACTIVE_MODE);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to power on device\n");
+
+ ret = devm_add_action_or_reset(dev, als31300_power_down, data);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to add powerdown action\n");
+
+ indio_dev->info = &als31300_info;
+ indio_dev->modes = INDIO_DIRECT_MODE;
+ indio_dev->name = i2c->name;
+ indio_dev->channels = als31300_channels;
+ indio_dev->num_channels = ARRAY_SIZE(als31300_channels);
+ indio_dev->available_scan_masks = als31300_scan_masks;
+
+ ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
+ iio_pollfunc_store_time,
+ als31300_trigger_handler,
+ &als31300_setup_ops);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "iio triggered buffer setup failed\n");
+
+ ret = pm_runtime_set_active(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ pm_runtime_get_noresume(dev);
+ pm_runtime_set_autosuspend_delay(dev, 200);
+ pm_runtime_use_autosuspend(dev);
+
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_put_autosuspend(dev);
+
+ ret = devm_iio_device_register(dev, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "device register failed\n");
+
+ return 0;
+}
+
+static int als31300_runtime_suspend(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct als31300_data *data = iio_priv(indio_dev);
+
+ return als31300_set_operating_mode(data, ALS31300_VOL_MODE_SLEEP_MODE);
+}
+
+static int als31300_runtime_resume(struct device *dev)
+{
+ struct iio_dev *indio_dev = dev_get_drvdata(dev);
+ struct als31300_data *data = iio_priv(indio_dev);
+
+ return als31300_set_operating_mode(data, ALS31300_VOL_MODE_ACTIVE_MODE);
+}
+
+static DEFINE_RUNTIME_DEV_PM_OPS(als31300_pm_ops,
+ als31300_runtime_suspend, als31300_runtime_resume,
+ NULL);
+
+static const struct als31300_variant_info al31300_variant_500 = {
+ .sensitivity = 4,
+};
+
+static const struct als31300_variant_info al31300_variant_1000 = {
+ .sensitivity = 2,
+};
+
+static const struct als31300_variant_info al31300_variant_2000 = {
+ .sensitivity = 1,
+};
+
+static const struct i2c_device_id als31300_id[] = {
+ {
+ .name = "als31300-500",
+ .driver_data = (kernel_ulong_t)&al31300_variant_500,
+ },
+ {
+ .name = "als31300-1000",
+ .driver_data = (kernel_ulong_t)&al31300_variant_1000,
+ },
+ {
+ .name = "als31300-2000",
+ .driver_data = (kernel_ulong_t)&al31300_variant_2000,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(i2c, als31300_id);
+
+static const struct of_device_id als31300_of_match[] = {
+ {
+ .compatible = "allegromicro,als31300-500",
+ .data = &al31300_variant_500,
+ },
+ {
+ .compatible = "allegromicro,als31300-1000",
+ .data = &al31300_variant_1000,
+ },
+ {
+ .compatible = "allegromicro,als31300-2000",
+ .data = &al31300_variant_2000,
+ },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, als31300_of_match);
+
+static struct i2c_driver als31300_driver = {
+ .driver = {
+ .name = "als31300",
+ .of_match_table = als31300_of_match,
+ .pm = pm_ptr(&als31300_pm_ops),
+ },
+ .probe = als31300_probe,
+ .id_table = als31300_id,
+};
+module_i2c_driver(als31300_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ALS31300 3-D Linear Hall Effect Driver");
+MODULE_AUTHOR("Neil Armstrong <neil.armstrong@linaro.org>");
diff --git a/drivers/iio/magnetometer/bmc150_magn.c b/drivers/iio/magnetometer/bmc150_magn.c
index 06d5a1ef1fbd..7f545740178e 100644
--- a/drivers/iio/magnetometer/bmc150_magn.c
+++ b/drivers/iio/magnetometer/bmc150_magn.c
@@ -14,7 +14,6 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/acpi.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
#include <linux/iio/iio.h>
@@ -226,7 +225,7 @@ const struct regmap_config bmc150_magn_regmap_config = {
.writeable_reg = bmc150_magn_is_writeable_reg,
.volatile_reg = bmc150_magn_is_volatile_reg,
};
-EXPORT_SYMBOL_NS(bmc150_magn_regmap_config, IIO_BMC150_MAGN);
+EXPORT_SYMBOL_NS(bmc150_magn_regmap_config, "IIO_BMC150_MAGN");
static int bmc150_magn_set_power_mode(struct bmc150_magn_data *data,
enum bmc150_magn_power_modes mode,
@@ -855,17 +854,6 @@ static const struct iio_buffer_setup_ops bmc150_magn_buffer_setup_ops = {
.postdisable = bmc150_magn_buffer_postdisable,
};
-static const char *bmc150_magn_match_acpi_device(struct device *dev)
-{
- const struct acpi_device_id *id;
-
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
- if (!id)
- return NULL;
-
- return dev_name(dev);
-}
-
int bmc150_magn_probe(struct device *dev, struct regmap *regmap,
int irq, const char *name)
{
@@ -894,9 +882,6 @@ int bmc150_magn_probe(struct device *dev, struct regmap *regmap,
if (ret)
return ret;
- if (!name && ACPI_HANDLE(dev))
- name = bmc150_magn_match_acpi_device(dev);
-
mutex_init(&data->mutex);
ret = bmc150_magn_init(data);
@@ -983,7 +968,7 @@ err_poweroff:
bmc150_magn_set_power_mode(data, BMC150_MAGN_POWER_MODE_SUSPEND, true);
return ret;
}
-EXPORT_SYMBOL_NS(bmc150_magn_probe, IIO_BMC150_MAGN);
+EXPORT_SYMBOL_NS(bmc150_magn_probe, "IIO_BMC150_MAGN");
void bmc150_magn_remove(struct device *dev)
{
@@ -1009,7 +994,7 @@ void bmc150_magn_remove(struct device *dev)
regulator_bulk_disable(ARRAY_SIZE(data->regulators), data->regulators);
}
-EXPORT_SYMBOL_NS(bmc150_magn_remove, IIO_BMC150_MAGN);
+EXPORT_SYMBOL_NS(bmc150_magn_remove, "IIO_BMC150_MAGN");
#ifdef CONFIG_PM
static int bmc150_magn_runtime_suspend(struct device *dev)
@@ -1077,7 +1062,7 @@ const struct dev_pm_ops bmc150_magn_pm_ops = {
SET_RUNTIME_PM_OPS(bmc150_magn_runtime_suspend,
bmc150_magn_runtime_resume, NULL)
};
-EXPORT_SYMBOL_NS(bmc150_magn_pm_ops, IIO_BMC150_MAGN);
+EXPORT_SYMBOL_NS(bmc150_magn_pm_ops, "IIO_BMC150_MAGN");
MODULE_AUTHOR("Irina Tirdea <irina.tirdea@intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iio/magnetometer/bmc150_magn_i2c.c b/drivers/iio/magnetometer/bmc150_magn_i2c.c
index a28d46d59875..8cbeda924bda 100644
--- a/drivers/iio/magnetometer/bmc150_magn_i2c.c
+++ b/drivers/iio/magnetometer/bmc150_magn_i2c.c
@@ -38,14 +38,6 @@ static void bmc150_magn_i2c_remove(struct i2c_client *client)
bmc150_magn_remove(&client->dev);
}
-static const struct acpi_device_id bmc150_magn_acpi_match[] = {
- {"BMC150B", 0},
- {"BMC156B", 0},
- {"BMM150B", 0},
- {},
-};
-MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
-
static const struct i2c_device_id bmc150_magn_i2c_id[] = {
{ "bmc150_magn" },
{ "bmc156_magn" },
@@ -67,7 +59,6 @@ static struct i2c_driver bmc150_magn_driver = {
.driver = {
.name = "bmc150_magn_i2c",
.of_match_table = bmc150_magn_of_match,
- .acpi_match_table = bmc150_magn_acpi_match,
.pm = &bmc150_magn_pm_ops,
},
.probe = bmc150_magn_i2c_probe,
@@ -79,4 +70,4 @@ module_i2c_driver(bmc150_magn_driver);
MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("BMC150 I2C magnetometer driver");
-MODULE_IMPORT_NS(IIO_BMC150_MAGN);
+MODULE_IMPORT_NS("IIO_BMC150_MAGN");
diff --git a/drivers/iio/magnetometer/bmc150_magn_spi.c b/drivers/iio/magnetometer/bmc150_magn_spi.c
index abc75a05c46a..2d4b8cba32f1 100644
--- a/drivers/iio/magnetometer/bmc150_magn_spi.c
+++ b/drivers/iio/magnetometer/bmc150_magn_spi.c
@@ -41,20 +41,11 @@ static const struct spi_device_id bmc150_magn_spi_id[] = {
};
MODULE_DEVICE_TABLE(spi, bmc150_magn_spi_id);
-static const struct acpi_device_id bmc150_magn_acpi_match[] = {
- {"BMC150B", 0},
- {"BMC156B", 0},
- {"BMM150B", 0},
- {},
-};
-MODULE_DEVICE_TABLE(acpi, bmc150_magn_acpi_match);
-
static struct spi_driver bmc150_magn_spi_driver = {
.probe = bmc150_magn_spi_probe,
.remove = bmc150_magn_spi_remove,
.id_table = bmc150_magn_spi_id,
.driver = {
- .acpi_match_table = bmc150_magn_acpi_match,
.name = "bmc150_magn_spi",
},
};
@@ -63,4 +54,4 @@ module_spi_driver(bmc150_magn_spi_driver);
MODULE_AUTHOR("Daniel Baluta <daniel.baluta@intel.com");
MODULE_DESCRIPTION("BMC150 magnetometer SPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_BMC150_MAGN);
+MODULE_IMPORT_NS("IIO_BMC150_MAGN");
diff --git a/drivers/iio/magnetometer/hid-sensor-magn-3d.c b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
index 5c795a430d09..97ddaa2a03f6 100644
--- a/drivers/iio/magnetometer/hid-sensor-magn-3d.c
+++ b/drivers/iio/magnetometer/hid-sensor-magn-3d.c
@@ -466,11 +466,11 @@ static int magn_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_magn_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static char *name = "magn_3d";
struct iio_dev *indio_dev;
struct magn_3d_state *magn_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
struct iio_chan_spec *channels;
int chan_count = 0;
@@ -549,7 +549,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_magn_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct magn_3d_state *magn_state = iio_priv(indio_dev);
@@ -574,11 +574,11 @@ static struct platform_driver hid_magn_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_magn_3d_probe,
- .remove_new = hid_magn_3d_remove,
+ .remove = hid_magn_3d_remove,
};
module_platform_driver(hid_magn_3d_platform_driver);
MODULE_DESCRIPTION("HID Sensor Magnetometer 3D");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/magnetometer/hmc5843_core.c b/drivers/iio/magnetometer/hmc5843_core.c
index c5521d61da29..2fc84310e2cc 100644
--- a/drivers/iio/magnetometer/hmc5843_core.c
+++ b/drivers/iio/magnetometer/hmc5843_core.c
@@ -669,7 +669,7 @@ buffer_setup_err:
hmc5843_set_mode(iio_priv(indio_dev), HMC5843_MODE_SLEEP);
return ret;
}
-EXPORT_SYMBOL_NS(hmc5843_common_probe, IIO_HMC5843);
+EXPORT_SYMBOL_NS(hmc5843_common_probe, "IIO_HMC5843");
void hmc5843_common_remove(struct device *dev)
{
@@ -681,7 +681,7 @@ void hmc5843_common_remove(struct device *dev)
/* sleep mode to save power */
hmc5843_set_mode(iio_priv(indio_dev), HMC5843_MODE_SLEEP);
}
-EXPORT_SYMBOL_NS(hmc5843_common_remove, IIO_HMC5843);
+EXPORT_SYMBOL_NS(hmc5843_common_remove, "IIO_HMC5843");
MODULE_AUTHOR("Shubhrajyoti Datta <shubhrajyoti@ti.com>");
MODULE_DESCRIPTION("HMC5843/5883/5883L/5983 core driver");
diff --git a/drivers/iio/magnetometer/hmc5843_i2c.c b/drivers/iio/magnetometer/hmc5843_i2c.c
index bdd2784a9f86..657a309e2bd5 100644
--- a/drivers/iio/magnetometer/hmc5843_i2c.c
+++ b/drivers/iio/magnetometer/hmc5843_i2c.c
@@ -103,4 +103,4 @@ module_i2c_driver(hmc5843_driver);
MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>");
MODULE_DESCRIPTION("HMC5843/5883/5883L/5983 i2c driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HMC5843);
+MODULE_IMPORT_NS("IIO_HMC5843");
diff --git a/drivers/iio/magnetometer/hmc5843_spi.c b/drivers/iio/magnetometer/hmc5843_spi.c
index c42d2e2a6a6c..b7fde331069d 100644
--- a/drivers/iio/magnetometer/hmc5843_spi.c
+++ b/drivers/iio/magnetometer/hmc5843_spi.c
@@ -100,4 +100,4 @@ module_spi_driver(hmc5843_driver);
MODULE_AUTHOR("Josef Gajdusek <atx@atx.name>");
MODULE_DESCRIPTION("HMC5983 SPI driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HMC5843);
+MODULE_IMPORT_NS("IIO_HMC5843");
diff --git a/drivers/iio/magnetometer/rm3100-core.c b/drivers/iio/magnetometer/rm3100-core.c
index baab918b3825..c99694a77a14 100644
--- a/drivers/iio/magnetometer/rm3100-core.c
+++ b/drivers/iio/magnetometer/rm3100-core.c
@@ -100,7 +100,7 @@ const struct regmap_access_table rm3100_readable_table = {
.yes_ranges = rm3100_readable_ranges,
.n_yes_ranges = ARRAY_SIZE(rm3100_readable_ranges),
};
-EXPORT_SYMBOL_NS_GPL(rm3100_readable_table, IIO_RM3100);
+EXPORT_SYMBOL_NS_GPL(rm3100_readable_table, "IIO_RM3100");
static const struct regmap_range rm3100_writable_ranges[] = {
regmap_reg_range(RM3100_W_REG_START, RM3100_W_REG_END),
@@ -110,7 +110,7 @@ const struct regmap_access_table rm3100_writable_table = {
.yes_ranges = rm3100_writable_ranges,
.n_yes_ranges = ARRAY_SIZE(rm3100_writable_ranges),
};
-EXPORT_SYMBOL_NS_GPL(rm3100_writable_table, IIO_RM3100);
+EXPORT_SYMBOL_NS_GPL(rm3100_writable_table, "IIO_RM3100");
static const struct regmap_range rm3100_volatile_ranges[] = {
regmap_reg_range(RM3100_V_REG_START, RM3100_V_REG_END),
@@ -120,7 +120,7 @@ const struct regmap_access_table rm3100_volatile_table = {
.yes_ranges = rm3100_volatile_ranges,
.n_yes_ranges = ARRAY_SIZE(rm3100_volatile_ranges),
};
-EXPORT_SYMBOL_NS_GPL(rm3100_volatile_table, IIO_RM3100);
+EXPORT_SYMBOL_NS_GPL(rm3100_volatile_table, "IIO_RM3100");
static irqreturn_t rm3100_thread_fn(int irq, void *d)
{
@@ -604,7 +604,7 @@ int rm3100_common_probe(struct device *dev, struct regmap *regmap, int irq)
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(rm3100_common_probe, IIO_RM3100);
+EXPORT_SYMBOL_NS_GPL(rm3100_common_probe, "IIO_RM3100");
MODULE_AUTHOR("Song Qiang <songqiang1304521@gmail.com>");
MODULE_DESCRIPTION("PNI RM3100 3-axis magnetometer i2c driver");
diff --git a/drivers/iio/magnetometer/rm3100-i2c.c b/drivers/iio/magnetometer/rm3100-i2c.c
index ac7276b3798c..a09a271b62c5 100644
--- a/drivers/iio/magnetometer/rm3100-i2c.c
+++ b/drivers/iio/magnetometer/rm3100-i2c.c
@@ -52,4 +52,4 @@ module_i2c_driver(rm3100_driver);
MODULE_AUTHOR("Song Qiang <songqiang1304521@gmail.com>");
MODULE_DESCRIPTION("PNI RM3100 3-axis magnetometer i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_RM3100);
+MODULE_IMPORT_NS("IIO_RM3100");
diff --git a/drivers/iio/magnetometer/rm3100-spi.c b/drivers/iio/magnetometer/rm3100-spi.c
index 76dc9b66cd3c..dd6d48043740 100644
--- a/drivers/iio/magnetometer/rm3100-spi.c
+++ b/drivers/iio/magnetometer/rm3100-spi.c
@@ -62,4 +62,4 @@ module_spi_driver(rm3100_driver);
MODULE_AUTHOR("Song Qiang <songqiang1304521@gmail.com>");
MODULE_DESCRIPTION("PNI RM3100 3-axis magnetometer spi driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_RM3100);
+MODULE_IMPORT_NS("IIO_RM3100");
diff --git a/drivers/iio/magnetometer/st_magn_core.c b/drivers/iio/magnetometer/st_magn_core.c
index 6cc0dfd31821..ef348d316c00 100644
--- a/drivers/iio/magnetometer/st_magn_core.c
+++ b/drivers/iio/magnetometer/st_magn_core.c
@@ -601,7 +601,7 @@ const struct st_sensor_settings *st_magn_get_settings(const char *name)
return &st_magn_sensors_settings[index];
}
-EXPORT_SYMBOL_NS(st_magn_get_settings, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_magn_get_settings, "IIO_ST_SENSORS");
int st_magn_common_probe(struct iio_dev *indio_dev)
{
@@ -648,9 +648,9 @@ int st_magn_common_probe(struct iio_dev *indio_dev)
return devm_iio_device_register(parent, indio_dev);
}
-EXPORT_SYMBOL_NS(st_magn_common_probe, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_magn_common_probe, "IIO_ST_SENSORS");
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics magnetometers driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/magnetometer/st_magn_i2c.c b/drivers/iio/magnetometer/st_magn_i2c.c
index 950826dd20bf..1672b274768d 100644
--- a/drivers/iio/magnetometer/st_magn_i2c.c
+++ b/drivers/iio/magnetometer/st_magn_i2c.c
@@ -119,4 +119,4 @@ module_i2c_driver(st_magn_driver);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics magnetometers i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/magnetometer/st_magn_spi.c b/drivers/iio/magnetometer/st_magn_spi.c
index f203e1f87eec..fe4d0e63133c 100644
--- a/drivers/iio/magnetometer/st_magn_spi.c
+++ b/drivers/iio/magnetometer/st_magn_spi.c
@@ -111,4 +111,4 @@ module_spi_driver(st_magn_driver);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics magnetometers spi driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/magnetometer/yamaha-yas530.c b/drivers/iio/magnetometer/yamaha-yas530.c
index 65011a8598d3..c55a38650c0d 100644
--- a/drivers/iio/magnetometer/yamaha-yas530.c
+++ b/drivers/iio/magnetometer/yamaha-yas530.c
@@ -372,6 +372,7 @@ static int yas537_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y
u8 data[8];
u16 xy1y2[3];
s32 h[3], s[3];
+ int half_range = BIT(13);
int i, ret;
mutex_lock(&yas5xx->lock);
@@ -406,13 +407,13 @@ static int yas537_measure(struct yas5xx *yas5xx, u16 *t, u16 *x, u16 *y1, u16 *y
/* The second version of YAS537 needs to include calibration coefficients */
if (yas5xx->version == YAS537_VERSION_1) {
for (i = 0; i < 3; i++)
- s[i] = xy1y2[i] - BIT(13);
- h[0] = (c->k * (128 * s[0] + c->a2 * s[1] + c->a3 * s[2])) / BIT(13);
- h[1] = (c->k * (c->a4 * s[0] + c->a5 * s[1] + c->a6 * s[2])) / BIT(13);
- h[2] = (c->k * (c->a7 * s[0] + c->a8 * s[1] + c->a9 * s[2])) / BIT(13);
+ s[i] = xy1y2[i] - half_range;
+ h[0] = (c->k * (128 * s[0] + c->a2 * s[1] + c->a3 * s[2])) / half_range;
+ h[1] = (c->k * (c->a4 * s[0] + c->a5 * s[1] + c->a6 * s[2])) / half_range;
+ h[2] = (c->k * (c->a7 * s[0] + c->a8 * s[1] + c->a9 * s[2])) / half_range;
for (i = 0; i < 3; i++) {
- clamp_val(h[i], -BIT(13), BIT(13) - 1);
- xy1y2[i] = h[i] + BIT(13);
+ h[i] = clamp(h[i], -half_range, half_range - 1);
+ xy1y2[i] = h[i] + half_range;
}
}
diff --git a/drivers/iio/orientation/hid-sensor-incl-3d.c b/drivers/iio/orientation/hid-sensor-incl-3d.c
index 8943d5c78bc0..429035b65c65 100644
--- a/drivers/iio/orientation/hid-sensor-incl-3d.c
+++ b/drivers/iio/orientation/hid-sensor-incl-3d.c
@@ -29,7 +29,7 @@ struct incl_3d_state {
struct hid_sensor_hub_attribute_info incl[INCLI_3D_CHANNEL_MAX];
struct {
u32 incl_val[INCLI_3D_CHANNEL_MAX];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -299,11 +299,11 @@ static int incl_3d_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_incl_3d_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret;
static char *name = "incli_3d";
struct iio_dev *indio_dev;
struct incl_3d_state *incl_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct incl_3d_state));
@@ -385,7 +385,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_incl_3d_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct incl_3d_state *incl_state = iio_priv(indio_dev);
@@ -410,11 +410,11 @@ static struct platform_driver hid_incl_3d_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_incl_3d_probe,
- .remove_new = hid_incl_3d_remove,
+ .remove = hid_incl_3d_remove,
};
module_platform_driver(hid_incl_3d_platform_driver);
MODULE_DESCRIPTION("HID Sensor Inclinometer 3D");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/orientation/hid-sensor-rotation.c b/drivers/iio/orientation/hid-sensor-rotation.c
index 5e8cadd5177a..96f03988640c 100644
--- a/drivers/iio/orientation/hid-sensor-rotation.c
+++ b/drivers/iio/orientation/hid-sensor-rotation.c
@@ -20,7 +20,7 @@ struct dev_rot_state {
struct hid_sensor_hub_attribute_info quaternion;
struct {
s32 sampled_vals[4] __aligned(16);
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -230,11 +230,11 @@ static int dev_rot_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_dev_rot_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret;
char *name;
struct iio_dev *indio_dev;
struct dev_rot_state *rot_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct dev_rot_state));
@@ -329,7 +329,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_dev_rot_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct dev_rot_state *rot_state = iio_priv(indio_dev);
@@ -362,11 +362,11 @@ static struct platform_driver hid_dev_rot_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_dev_rot_probe,
- .remove_new = hid_dev_rot_remove,
+ .remove = hid_dev_rot_remove,
};
module_platform_driver(hid_dev_rot_platform_driver);
MODULE_DESCRIPTION("HID Sensor Device Rotation");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/position/hid-sensor-custom-intel-hinge.c b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
index 76e173850a35..423bbb8a3b38 100644
--- a/drivers/iio/position/hid-sensor-custom-intel-hinge.c
+++ b/drivers/iio/position/hid-sensor-custom-intel-hinge.c
@@ -39,7 +39,7 @@ struct hinge_state {
const char *labels[CHANNEL_SCAN_INDEX_MAX];
struct {
u32 hinge_val[3];
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
@@ -263,9 +263,9 @@ static int hinge_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_hinge_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct hinge_state *st;
struct iio_dev *indio_dev;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
int ret;
int i;
@@ -344,7 +344,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_hinge_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct hinge_state *st = iio_priv(indio_dev);
@@ -369,11 +369,11 @@ static struct platform_driver hid_hinge_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_hinge_probe,
- .remove_new = hid_hinge_remove,
+ .remove = hid_hinge_remove,
};
module_platform_driver(hid_hinge_platform_driver);
MODULE_DESCRIPTION("HID Sensor INTEL Hinge");
MODULE_AUTHOR("Ye Xiang <xiang.ye@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/position/iqs624-pos.c b/drivers/iio/position/iqs624-pos.c
index 4d7452314209..8239239c6ee2 100644
--- a/drivers/iio/position/iqs624-pos.c
+++ b/drivers/iio/position/iqs624-pos.c
@@ -181,7 +181,7 @@ static int iqs624_pos_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct iqs624_pos_private *iqs624_pos = iio_priv(indio_dev);
struct iqs62x_core *iqs62x = iqs624_pos->iqs62x;
diff --git a/drivers/iio/pressure/bmp280-core.c b/drivers/iio/pressure/bmp280-core.c
index a8b97b9b0461..5376605b69b4 100644
--- a/drivers/iio/pressure/bmp280-core.c
+++ b/drivers/iio/pressure/bmp280-core.c
@@ -16,6 +16,11 @@
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp390-ds002.pdf
* https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmp581-ds004.pdf
*
+ * Sensor API:
+ * https://github.com/boschsensortec/BME280_SensorAPI
+ * https://github.com/boschsensortec/BMP3_SensorAPI
+ * https://github.com/boschsensortec/BMP5_SensorAPI
+ *
* Notice:
* The link to the bmp180 datasheet points to an outdated version missing these changes:
* - Changed document referral from ANP015 to BST-MPS-AN004-00 on page 26
@@ -37,12 +42,14 @@
#include <linux/module.h>
#include <linux/nvmem-provider.h>
#include <linux/pm_runtime.h>
+#include <linux/property.h>
#include <linux/random.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
+#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
@@ -340,10 +347,19 @@ static int bmp280_read_calib(struct bmp280_data *data)
return 0;
}
+/*
+ * These enums are used for indexing into the array of humidity parameters
+ * for BME280. Due to some weird indexing, unaligned BE/LE accesses co-exist in
+ * order to prepare the FIELD_{GET/PREP}() fields. Table 16 in Section 4.2.2 of
+ * the datasheet.
+ */
+enum { H2 = 0, H3 = 2, H4 = 3, H5 = 4, H6 = 6 };
+
static int bme280_read_calib(struct bmp280_data *data)
{
struct bmp280_calib *calib = &data->calib.bmp280;
struct device *dev = data->dev;
+ s16 h4_upper, h4_lower, tmp_1, tmp_2, tmp_3;
unsigned int tmp;
int ret;
@@ -352,14 +368,6 @@ static int bme280_read_calib(struct bmp280_data *data)
if (ret)
return ret;
- /*
- * Read humidity calibration values.
- * Due to some odd register addressing we cannot just
- * do a big bulk read. Instead, we have to read each Hx
- * value separately and sometimes do some bit shifting...
- * Humidity data is only available on BME280.
- */
-
ret = regmap_read(data->regmap, BME280_REG_COMP_H1, &tmp);
if (ret) {
dev_err(dev, "failed to read H1 comp value\n");
@@ -368,43 +376,23 @@ static int bme280_read_calib(struct bmp280_data *data)
calib->H1 = tmp;
ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H2,
- &data->le16, sizeof(data->le16));
+ data->bme280_humid_cal_buf,
+ sizeof(data->bme280_humid_cal_buf));
if (ret) {
- dev_err(dev, "failed to read H2 comp value\n");
+ dev_err(dev, "failed to read humidity calibration values\n");
return ret;
}
- calib->H2 = sign_extend32(le16_to_cpu(data->le16), 15);
- ret = regmap_read(data->regmap, BME280_REG_COMP_H3, &tmp);
- if (ret) {
- dev_err(dev, "failed to read H3 comp value\n");
- return ret;
- }
- calib->H3 = tmp;
-
- ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H4,
- &data->be16, sizeof(data->be16));
- if (ret) {
- dev_err(dev, "failed to read H4 comp value\n");
- return ret;
- }
- calib->H4 = sign_extend32(((be16_to_cpu(data->be16) >> 4) & 0xff0) |
- (be16_to_cpu(data->be16) & 0xf), 11);
-
- ret = regmap_bulk_read(data->regmap, BME280_REG_COMP_H5,
- &data->le16, sizeof(data->le16));
- if (ret) {
- dev_err(dev, "failed to read H5 comp value\n");
- return ret;
- }
- calib->H5 = sign_extend32(FIELD_GET(BME280_COMP_H5_MASK, le16_to_cpu(data->le16)), 11);
-
- ret = regmap_read(data->regmap, BME280_REG_COMP_H6, &tmp);
- if (ret) {
- dev_err(dev, "failed to read H6 comp value\n");
- return ret;
- }
- calib->H6 = sign_extend32(tmp, 7);
+ calib->H2 = get_unaligned_le16(&data->bme280_humid_cal_buf[H2]);
+ calib->H3 = data->bme280_humid_cal_buf[H3];
+ tmp_1 = get_unaligned_be16(&data->bme280_humid_cal_buf[H4]);
+ tmp_2 = FIELD_GET(BME280_COMP_H4_GET_MASK_UP, tmp_1);
+ h4_upper = FIELD_PREP(BME280_COMP_H4_PREP_MASK_UP, tmp_2);
+ h4_lower = FIELD_GET(BME280_COMP_H4_MASK_LOW, tmp_1);
+ calib->H4 = sign_extend32(h4_upper | h4_lower, 11);
+ tmp_3 = get_unaligned_le16(&data->bme280_humid_cal_buf[H5]);
+ calib->H5 = sign_extend32(FIELD_GET(BME280_COMP_H5_MASK, tmp_3), 11);
+ calib->H6 = data->bme280_humid_cal_buf[H6];
return 0;
}
@@ -635,6 +623,14 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
switch (mask) {
case IIO_CHAN_INFO_PROCESSED:
+ ret = data->chip_info->set_mode(data, BMP280_FORCED);
+ if (ret)
+ return ret;
+
+ ret = data->chip_info->wait_conv(data);
+ if (ret)
+ return ret;
+
switch (chan->type) {
case IIO_HUMIDITYRELATIVE:
ret = data->chip_info->read_humid(data, &chan_value);
@@ -664,6 +660,14 @@ static int bmp280_read_raw_impl(struct iio_dev *indio_dev,
return -EINVAL;
}
case IIO_CHAN_INFO_RAW:
+ ret = data->chip_info->set_mode(data, BMP280_FORCED);
+ if (ret)
+ return ret;
+
+ ret = data->chip_info->wait_conv(data);
+ if (ret)
+ return ret;
+
switch (chan->type) {
case IIO_HUMIDITYRELATIVE:
ret = data->chip_info->read_humid(data, &chan_value);
@@ -983,6 +987,92 @@ static const unsigned long bme280_avail_scan_masks[] = {
0
};
+static int bmp280_preinit(struct bmp280_data *data)
+{
+ struct device *dev = data->dev;
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_write(data->regmap, BMP280_REG_RESET, BMP280_RST_SOFT_CMD);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to reset device.\n");
+
+ /*
+ * According to the datasheet in Chapter 1: Specification, Table 2,
+ * after resetting, the device uses the complete power-on sequence so
+ * it needs to wait for the defined start-up time.
+ */
+ fsleep(data->start_up_time);
+
+ ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to read status register.\n");
+
+ if (reg & BMP280_REG_STATUS_IM_UPDATE)
+ return dev_err_probe(dev, -EIO, "Failed to copy NVM contents.\n");
+
+ return 0;
+}
+
+static const u8 bmp280_operation_mode[] = {
+ [BMP280_SLEEP] = BMP280_MODE_SLEEP,
+ [BMP280_FORCED] = BMP280_MODE_FORCED,
+ [BMP280_NORMAL] = BMP280_MODE_NORMAL,
+};
+
+static int bmp280_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ int ret;
+
+ ret = regmap_write_bits(data->regmap, BMP280_REG_CTRL_MEAS,
+ BMP280_MODE_MASK, bmp280_operation_mode[mode]);
+ if (ret) {
+ dev_err(data->dev, "failed to write ctrl_meas register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp280_wait_conv(struct bmp280_data *data)
+{
+ unsigned int reg, meas_time_us;
+ int ret;
+
+ /* Check if we are using a BME280 device */
+ if (data->oversampling_humid)
+ meas_time_us = BMP280_PRESS_HUMID_MEAS_OFFSET +
+ BIT(data->oversampling_humid) * BMP280_MEAS_DUR;
+
+ else
+ meas_time_us = 0;
+
+ /* Pressure measurement time */
+ meas_time_us += BMP280_PRESS_HUMID_MEAS_OFFSET +
+ BIT(data->oversampling_press) * BMP280_MEAS_DUR;
+
+ /* Temperature measurement time */
+ meas_time_us += BIT(data->oversampling_temp) * BMP280_MEAS_DUR;
+
+ /* Waiting time according to the BM(P/E)2 Sensor API */
+ fsleep(meas_time_us);
+
+ ret = regmap_read(data->regmap, BMP280_REG_STATUS, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read status register.\n");
+ return ret;
+ }
+
+ if (reg & BMP280_REG_STATUS_MEAS_BIT) {
+ dev_err(data->dev, "Measurement cycle didn't complete.\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static int bmp280_chip_config(struct bmp280_data *data)
{
u8 osrs = FIELD_PREP(BMP280_OSRS_TEMP_MASK, data->oversampling_temp + 1) |
@@ -993,7 +1083,7 @@ static int bmp280_chip_config(struct bmp280_data *data)
BMP280_OSRS_TEMP_MASK |
BMP280_OSRS_PRESS_MASK |
BMP280_MODE_MASK,
- osrs | BMP280_MODE_NORMAL);
+ osrs | BMP280_MODE_SLEEP);
if (ret) {
dev_err(data->dev, "failed to write ctrl_meas register\n");
return ret;
@@ -1015,7 +1105,9 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, t_fine;
+ u32 adc_temp, adc_press, comp_press;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1035,7 +1127,7 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
+ comp_temp = bmp280_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
@@ -1045,10 +1137,12 @@ static irqreturn_t bmp280_trigger_handler(int irq, void *p)
}
t_fine = bmp280_calc_t_fine(data, adc_temp);
+ comp_press = bmp280_compensate_press(data, adc_press, t_fine);
- data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1099,10 +1193,13 @@ const struct bmp280_chip_info bmp280_chip_info = {
.read_temp = bmp280_read_temp,
.read_press = bmp280_read_press,
.read_calib = bmp280_read_calib,
+ .set_mode = bmp280_set_mode,
+ .wait_conv = bmp280_wait_conv,
+ .preinit = bmp280_preinit,
.trigger_handler = bmp280_trigger_handler,
};
-EXPORT_SYMBOL_NS(bmp280_chip_info, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp280_chip_info, "IIO_BMP280");
static int bme280_chip_config(struct bmp280_data *data)
{
@@ -1128,7 +1225,9 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, adc_humidity, t_fine;
+ u32 adc_temp, adc_press, adc_humidity, comp_press, comp_humidity;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1148,7 +1247,7 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp280_compensate_temp(data, adc_temp);
+ comp_temp = bmp280_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = FIELD_GET(BMP280_MEAS_TRIM_MASK, get_unaligned_be24(&data->buf[0]));
@@ -1158,8 +1257,7 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
}
t_fine = bmp280_calc_t_fine(data, adc_temp);
-
- data->sensor_data[0] = bmp280_compensate_press(data, adc_press, t_fine);
+ comp_press = bmp280_compensate_press(data, adc_press, t_fine);
/* Humidity calculations */
adc_humidity = get_unaligned_be16(&data->buf[6]);
@@ -1168,9 +1266,14 @@ static irqreturn_t bme280_trigger_handler(int irq, void *p)
dev_err(data->dev, "reading humidity skipped\n");
goto out;
}
- data->sensor_data[2] = bme280_compensate_humidity(data, adc_humidity, t_fine);
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ comp_humidity = bme280_compensate_humidity(data, adc_humidity, t_fine);
+
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
+ chans[2] = comp_humidity;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1179,6 +1282,63 @@ out:
return IRQ_HANDLED;
}
+static int __bmp280_trigger_probe(struct iio_dev *indio_dev,
+ const struct iio_trigger_ops *trigger_ops,
+ int (*int_pin_config)(struct bmp280_data *data),
+ irq_handler_t irq_thread_handler)
+{
+ struct bmp280_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
+ u32 irq_type;
+ int ret, irq;
+
+ irq = fwnode_irq_get(dev_fwnode(dev), 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "No interrupt found.\n");
+
+ irq_type = irq_get_trigger_type(irq);
+ switch (irq_type) {
+ case IRQF_TRIGGER_RISING:
+ data->trig_active_high = true;
+ break;
+ case IRQF_TRIGGER_FALLING:
+ data->trig_active_high = false;
+ break;
+ default:
+ return dev_err_probe(dev, -EINVAL, "Invalid interrupt type specified.\n");
+ }
+
+ data->trig_open_drain =
+ fwnode_property_read_bool(dev_fwnode(dev), "int-open-drain");
+
+ ret = int_pin_config(data);
+ if (ret)
+ return ret;
+
+ data->trig = devm_iio_trigger_alloc(data->dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = trigger_ops;
+ iio_trigger_set_drvdata(data->trig, data);
+
+ ret = devm_request_threaded_irq(data->dev, irq, NULL,
+ irq_thread_handler, IRQF_ONESHOT,
+ indio_dev->name, indio_dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "request IRQ failed.\n");
+
+ ret = devm_iio_trigger_register(data->dev, data->trig);
+ if (ret)
+ return dev_err_probe(dev, ret, "iio trigger register failed.\n");
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+
+ return 0;
+}
+
static const u8 bme280_chip_ids[] = { BME280_CHIP_ID };
static const int bme280_humid_coeffs[] = { 1000, 1024 };
@@ -1216,10 +1376,13 @@ const struct bmp280_chip_info bme280_chip_info = {
.read_press = bmp280_read_press,
.read_humid = bme280_read_humid,
.read_calib = bme280_read_calib,
+ .set_mode = bmp280_set_mode,
+ .wait_conv = bmp280_wait_conv,
+ .preinit = bmp280_preinit,
.trigger_handler = bme280_trigger_handler,
};
-EXPORT_SYMBOL_NS(bme280_chip_info, IIO_BMP280);
+EXPORT_SYMBOL_NS(bme280_chip_info, "IIO_BMP280");
/*
* Helper function to send a command to BMP3XX sensors.
@@ -1502,6 +1665,64 @@ static int bmp380_preinit(struct bmp280_data *data)
return bmp380_cmd(data, BMP380_CMD_SOFT_RESET);
}
+static const u8 bmp380_operation_mode[] = {
+ [BMP280_SLEEP] = BMP380_MODE_SLEEP,
+ [BMP280_FORCED] = BMP380_MODE_FORCED,
+ [BMP280_NORMAL] = BMP380_MODE_NORMAL,
+};
+
+static int bmp380_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ int ret;
+
+ ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
+ BMP380_MODE_MASK,
+ FIELD_PREP(BMP380_MODE_MASK,
+ bmp380_operation_mode[mode]));
+ if (ret) {
+ dev_err(data->dev, "failed to write power control register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp380_wait_conv(struct bmp280_data *data)
+{
+ unsigned int reg;
+ int ret, meas_time_us;
+
+ /* Offset measurement time */
+ meas_time_us = BMP380_MEAS_OFFSET;
+
+ /* Pressure measurement time */
+ meas_time_us += BMP380_PRESS_MEAS_OFFSET +
+ BIT(data->oversampling_press) * BMP380_MEAS_DUR;
+
+ /* Temperature measurement time */
+ meas_time_us += BMP380_TEMP_MEAS_OFFSET +
+ BIT(data->oversampling_temp) * BMP380_MEAS_DUR;
+
+ /* Measurement time defined in Datasheet Section 3.9.2 */
+ fsleep(meas_time_us);
+
+ ret = regmap_read(data->regmap, BMP380_REG_STATUS, &reg);
+ if (ret) {
+ dev_err(data->dev, "failed to read status register.\n");
+ return ret;
+ }
+
+ if (!((reg & BMP380_STATUS_DRDY_PRESS_MASK) &&
+ (reg & BMP380_STATUS_DRDY_TEMP_MASK))) {
+ dev_err(data->dev, "Measurement cycle didn't complete.\n");
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
static int bmp380_chip_config(struct bmp280_data *data)
{
bool change = false, aux;
@@ -1545,14 +1766,12 @@ static int bmp380_chip_config(struct bmp280_data *data)
change = change || aux;
/* Set filter data */
- ret = regmap_update_bits_check(data->regmap, BMP380_REG_CONFIG, BMP380_FILTER_MASK,
- FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff),
- &aux);
+ ret = regmap_update_bits(data->regmap, BMP380_REG_CONFIG, BMP380_FILTER_MASK,
+ FIELD_PREP(BMP380_FILTER_MASK, data->iir_filter_coeff));
if (ret) {
dev_err(data->dev, "failed to write config register\n");
return ret;
}
- change = change || aux;
if (change) {
/*
@@ -1564,17 +1783,19 @@ static int bmp380_chip_config(struct bmp280_data *data)
* Resets sensor measurement loop toggling between sleep and
* normal operating modes.
*/
- ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
- BMP380_MODE_MASK,
- FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_SLEEP));
+ ret = bmp380_set_mode(data, BMP280_SLEEP);
if (ret) {
dev_err(data->dev, "failed to set sleep mode\n");
return ret;
}
- usleep_range(2000, 2500);
- ret = regmap_write_bits(data->regmap, BMP380_REG_POWER_CONTROL,
- BMP380_MODE_MASK,
- FIELD_PREP(BMP380_MODE_MASK, BMP380_MODE_NORMAL));
+
+ /*
+ * According to the BMP3 Sensor API, the sensor needs 5ms
+ * in order to go to the sleep mode.
+ */
+ fsleep(5 * USEC_PER_MSEC);
+
+ ret = bmp380_set_mode(data, BMP280_NORMAL);
if (ret) {
dev_err(data->dev, "failed to set normal mode\n");
return ret;
@@ -1600,7 +1821,77 @@ static int bmp380_chip_config(struct bmp280_data *data)
}
}
- return 0;
+ /* Dummy read to empty data registers. */
+ ret = bmp380_read_press(data, &tmp);
+ if (ret)
+ return ret;
+
+ ret = bmp380_set_mode(data, BMP280_SLEEP);
+ if (ret)
+ dev_err(data->dev, "failed to set sleep mode.\n");
+
+ return ret;
+}
+
+static int bmp380_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = regmap_update_bits(data->regmap, BMP380_REG_INT_CONTROL,
+ BMP380_INT_CTRL_DRDY_EN,
+ FIELD_PREP(BMP380_INT_CTRL_DRDY_EN, !!state));
+ if (ret)
+ dev_err(data->dev,
+ "Could not %s interrupt.\n", str_enable_disable(state));
+ return ret;
+}
+
+static const struct iio_trigger_ops bmp380_trigger_ops = {
+ .set_trigger_state = &bmp380_data_rdy_trigger_set_state,
+};
+
+static int bmp380_int_pin_config(struct bmp280_data *data)
+{
+ int pin_drive_cfg = FIELD_PREP(BMP380_INT_CTRL_OPEN_DRAIN,
+ data->trig_open_drain);
+ int pin_level_cfg = FIELD_PREP(BMP380_INT_CTRL_LEVEL,
+ data->trig_active_high);
+ int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
+
+ ret = regmap_update_bits(data->regmap, BMP380_REG_INT_CONTROL,
+ BMP380_INT_CTRL_SETTINGS_MASK, int_pin_cfg);
+ if (ret)
+ dev_err(data->dev, "Could not set interrupt settings.\n");
+
+ return ret;
+}
+
+static irqreturn_t bmp380_irq_thread_handler(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct bmp280_data *data = iio_priv(indio_dev);
+ unsigned int int_ctrl;
+ int ret;
+
+ ret = regmap_read(data->regmap, BMP380_REG_INT_STATUS, &int_ctrl);
+ if (ret)
+ return IRQ_NONE;
+
+ if (FIELD_GET(BMP380_INT_STATUS_DRDY, int_ctrl))
+ iio_trigger_poll_nested(data->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int bmp380_trigger_probe(struct iio_dev *indio_dev)
+{
+ return __bmp280_trigger_probe(indio_dev, &bmp380_trigger_ops,
+ bmp380_int_pin_config,
+ bmp380_irq_thread_handler);
}
static irqreturn_t bmp380_trigger_handler(int irq, void *p)
@@ -1608,7 +1899,9 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- s32 adc_temp, adc_press, t_fine;
+ u32 adc_temp, adc_press, comp_press;
+ s32 t_fine, comp_temp;
+ s32 *chans = (s32 *)data->sensor_data;
int ret;
guard(mutex)(&data->lock);
@@ -1628,7 +1921,7 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
goto out;
}
- data->sensor_data[1] = bmp380_compensate_temp(data, adc_temp);
+ comp_temp = bmp380_compensate_temp(data, adc_temp);
/* Pressure calculations */
adc_press = get_unaligned_le24(&data->buf[0]);
@@ -1638,10 +1931,12 @@ static irqreturn_t bmp380_trigger_handler(int irq, void *p)
}
t_fine = bmp380_calc_t_fine(data, adc_temp);
+ comp_press = bmp380_compensate_press(data, adc_press, t_fine);
- data->sensor_data[0] = bmp380_compensate_press(data, adc_press, t_fine);
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -1692,11 +1987,14 @@ const struct bmp280_chip_info bmp380_chip_info = {
.read_temp = bmp380_read_temp,
.read_press = bmp380_read_press,
.read_calib = bmp380_read_calib,
+ .set_mode = bmp380_set_mode,
+ .wait_conv = bmp380_wait_conv,
.preinit = bmp380_preinit,
+ .trigger_probe = bmp380_trigger_probe,
.trigger_handler = bmp380_trigger_handler,
};
-EXPORT_SYMBOL_NS(bmp380_chip_info, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp380_chip_info, "IIO_BMP280");
static int bmp580_soft_reset(struct bmp280_data *data)
{
@@ -2079,6 +2377,70 @@ static int bmp580_preinit(struct bmp280_data *data)
return PTR_ERR_OR_ZERO(devm_nvmem_register(config.dev, &config));
}
+static const u8 bmp580_operation_mode[] = {
+ [BMP280_SLEEP] = BMP580_MODE_SLEEP,
+ [BMP280_FORCED] = BMP580_MODE_FORCED,
+ [BMP280_NORMAL] = BMP580_MODE_NORMAL,
+};
+
+static int bmp580_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ struct device *dev = data->dev;
+ int ret;
+
+ if (mode == BMP280_FORCED) {
+ ret = regmap_set_bits(data->regmap, BMP580_REG_DSP_CONFIG,
+ BMP580_DSP_IIR_FORCED_FLUSH);
+ if (ret) {
+ dev_err(dev, "Could not flush IIR filter constants.\n");
+ return ret;
+ }
+ }
+
+ ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
+ BMP580_MODE_MASK,
+ FIELD_PREP(BMP580_MODE_MASK,
+ bmp580_operation_mode[mode]));
+ if (ret) {
+ dev_err(dev, "failed to write power control register.\n");
+ return ret;
+ }
+
+ data->op_mode = mode;
+
+ return 0;
+}
+
+static int bmp580_wait_conv(struct bmp280_data *data)
+{
+ /*
+ * Taken from datasheet, Section 2 "Specification, Table 3 "Electrical
+ * characteristics.
+ */
+ static const int time_conv_press[] = {
+ 0, 1050, 1785, 3045, 5670, 10920, 21420, 42420,
+ 84420,
+ };
+ static const int time_conv_temp[] = {
+ 0, 1050, 1105, 1575, 2205, 3465, 6090, 11340,
+ 21840,
+ };
+ int meas_time_us;
+
+ meas_time_us = 4 * USEC_PER_MSEC +
+ time_conv_temp[data->oversampling_temp] +
+ time_conv_press[data->oversampling_press];
+
+ /*
+ * Measurement time mentioned in Chapter 2, Table 4 of the datasheet.
+ * The extra 4ms is the required mode change to start of measurement
+ * time.
+ */
+ fsleep(meas_time_us);
+
+ return 0;
+}
+
static int bmp580_chip_config(struct bmp280_data *data)
{
bool change = false, aux;
@@ -2141,26 +2503,13 @@ static int bmp580_chip_config(struct bmp280_data *data)
reg_val = FIELD_PREP(BMP580_DSP_IIR_PRESS_MASK, data->iir_filter_coeff) |
FIELD_PREP(BMP580_DSP_IIR_TEMP_MASK, data->iir_filter_coeff);
- ret = regmap_update_bits_check(data->regmap, BMP580_REG_DSP_IIR,
- BMP580_DSP_IIR_PRESS_MASK |
- BMP580_DSP_IIR_TEMP_MASK,
- reg_val, &aux);
+ ret = regmap_update_bits(data->regmap, BMP580_REG_DSP_IIR,
+ BMP580_DSP_IIR_PRESS_MASK | BMP580_DSP_IIR_TEMP_MASK,
+ reg_val);
if (ret) {
dev_err(data->dev, "failed to write config register\n");
return ret;
}
- change = change || aux;
-
- /* Restore sensor to normal operation mode */
- ret = regmap_write_bits(data->regmap, BMP580_REG_ODR_CONFIG,
- BMP580_MODE_MASK,
- FIELD_PREP(BMP580_MODE_MASK, BMP580_MODE_NORMAL));
- if (ret) {
- dev_err(data->dev, "failed to set normal mode\n");
- return ret;
- }
- /* From datasheet's table 4: electrical characteristics */
- usleep_range(3000, 3500);
if (change) {
/*
@@ -2185,12 +2534,80 @@ static int bmp580_chip_config(struct bmp280_data *data)
return 0;
}
+static int bmp580_data_rdy_trigger_set_state(struct iio_trigger *trig,
+ bool state)
+{
+ struct bmp280_data *data = iio_trigger_get_drvdata(trig);
+ int ret;
+
+ guard(mutex)(&data->lock);
+
+ ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
+ BMP580_INT_CONFIG_INT_EN,
+ FIELD_PREP(BMP580_INT_CONFIG_INT_EN, !!state));
+ if (ret)
+ dev_err(data->dev,
+ "Could not %s interrupt.\n", str_enable_disable(state));
+ return ret;
+}
+
+static const struct iio_trigger_ops bmp580_trigger_ops = {
+ .set_trigger_state = &bmp580_data_rdy_trigger_set_state,
+};
+
+static int bmp580_int_pin_config(struct bmp280_data *data)
+{
+ int pin_drive_cfg = FIELD_PREP(BMP580_INT_CONFIG_OPEN_DRAIN,
+ data->trig_open_drain);
+ int pin_level_cfg = FIELD_PREP(BMP580_INT_CONFIG_LEVEL,
+ data->trig_active_high);
+ int ret, int_pin_cfg = pin_drive_cfg | pin_level_cfg;
+
+ ret = regmap_update_bits(data->regmap, BMP580_REG_INT_CONFIG,
+ BMP580_INT_CONFIG_MASK, int_pin_cfg);
+ if (ret) {
+ dev_err(data->dev, "Could not set interrupt settings.\n");
+ return ret;
+ }
+
+ ret = regmap_set_bits(data->regmap, BMP580_REG_INT_SOURCE,
+ BMP580_INT_SOURCE_DRDY);
+ if (ret)
+ dev_err(data->dev, "Could not set interrupt source.\n");
+
+ return ret;
+}
+
+static irqreturn_t bmp580_irq_thread_handler(int irq, void *p)
+{
+ struct iio_dev *indio_dev = p;
+ struct bmp280_data *data = iio_priv(indio_dev);
+ unsigned int int_ctrl;
+ int ret;
+
+ ret = regmap_read(data->regmap, BMP580_REG_INT_STATUS, &int_ctrl);
+ if (ret)
+ return IRQ_NONE;
+
+ if (FIELD_GET(BMP580_INT_STATUS_DRDY_MASK, int_ctrl))
+ iio_trigger_poll_nested(data->trig);
+
+ return IRQ_HANDLED;
+}
+
+static int bmp580_trigger_probe(struct iio_dev *indio_dev)
+{
+ return __bmp280_trigger_probe(indio_dev, &bmp580_trigger_ops,
+ bmp580_int_pin_config,
+ bmp580_irq_thread_handler);
+}
+
static irqreturn_t bmp580_trigger_handler(int irq, void *p)
{
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- int ret;
+ int ret, offset;
guard(mutex)(&data->lock);
@@ -2202,13 +2619,17 @@ static irqreturn_t bmp580_trigger_handler(int irq, void *p)
goto out;
}
- /* Temperature calculations */
- memcpy(&data->sensor_data[1], &data->buf[0], 3);
+ offset = 0;
/* Pressure calculations */
- memcpy(&data->sensor_data[0], &data->buf[3], 3);
+ memcpy(&data->sensor_data[offset], &data->buf[3], 3);
+
+ offset += sizeof(s32);
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ /* Temperature calculations */
+ memcpy(&data->sensor_data[offset], &data->buf[0], 3);
+
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -2257,11 +2678,14 @@ const struct bmp280_chip_info bmp580_chip_info = {
.chip_config = bmp580_chip_config,
.read_temp = bmp580_read_temp,
.read_press = bmp580_read_press,
+ .set_mode = bmp580_set_mode,
+ .wait_conv = bmp580_wait_conv,
.preinit = bmp580_preinit,
+ .trigger_probe = bmp580_trigger_probe,
.trigger_handler = bmp580_trigger_handler,
};
-EXPORT_SYMBOL_NS(bmp580_chip_info, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp580_chip_info, "IIO_BMP280");
static int bmp180_wait_for_eoc(struct bmp280_data *data, u8 ctrl_meas)
{
@@ -2504,6 +2928,19 @@ static int bmp180_read_press(struct bmp280_data *data, u32 *comp_press)
return 0;
}
+/* Keep compatibility with newer generations of the sensor */
+static int bmp180_set_mode(struct bmp280_data *data, enum bmp280_op_mode mode)
+{
+ return 0;
+}
+
+/* Keep compatibility with newer generations of the sensor */
+static int bmp180_wait_conv(struct bmp280_data *data)
+{
+ return 0;
+}
+
+/* Keep compatibility with newer generations of the sensor */
static int bmp180_chip_config(struct bmp280_data *data)
{
return 0;
@@ -2514,23 +2951,24 @@ static irqreturn_t bmp180_trigger_handler(int irq, void *p)
struct iio_poll_func *pf = p;
struct iio_dev *indio_dev = pf->indio_dev;
struct bmp280_data *data = iio_priv(indio_dev);
- int ret, chan_value;
+ int ret, comp_temp, comp_press;
+ s32 *chans = (s32 *)data->sensor_data;
guard(mutex)(&data->lock);
- ret = bmp180_read_temp(data, &chan_value);
+ ret = bmp180_read_temp(data, &comp_temp);
if (ret)
goto out;
- data->sensor_data[1] = chan_value;
- ret = bmp180_read_press(data, &chan_value);
+ ret = bmp180_read_press(data, &comp_press);
if (ret)
goto out;
- data->sensor_data[0] = chan_value;
+ chans[0] = comp_press;
+ chans[1] = comp_temp;
- iio_push_to_buffers_with_timestamp(indio_dev, &data->sensor_data,
+ iio_push_to_buffers_with_timestamp(indio_dev, data->sensor_data,
iio_get_time_ns(indio_dev));
out:
@@ -2574,10 +3012,12 @@ const struct bmp280_chip_info bmp180_chip_info = {
.read_temp = bmp180_read_temp,
.read_press = bmp180_read_press,
.read_calib = bmp180_read_calib,
+ .set_mode = bmp180_set_mode,
+ .wait_conv = bmp180_wait_conv,
.trigger_handler = bmp180_trigger_handler,
};
-EXPORT_SYMBOL_NS(bmp180_chip_info, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp180_chip_info, "IIO_BMP280");
static irqreturn_t bmp085_eoc_irq(int irq, void *d)
{
@@ -2588,15 +3028,18 @@ static irqreturn_t bmp085_eoc_irq(int irq, void *d)
return IRQ_HANDLED;
}
-static int bmp085_fetch_eoc_irq(struct device *dev,
- const char *name,
- int irq,
- struct bmp280_data *data)
+static int bmp085_trigger_probe(struct iio_dev *indio_dev)
{
+ struct bmp280_data *data = iio_priv(indio_dev);
+ struct device *dev = data->dev;
unsigned long irq_trig;
- int ret;
+ int ret, irq;
- irq_trig = irqd_get_trigger_type(irq_get_irq_data(irq));
+ irq = fwnode_irq_get(dev_fwnode(dev), 0);
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "No interrupt found.\n");
+
+ irq_trig = irq_get_trigger_type(irq);
if (irq_trig != IRQF_TRIGGER_RISING) {
dev_err(dev, "non-rising trigger given for EOC interrupt, trying to enforce it\n");
irq_trig = IRQF_TRIGGER_RISING;
@@ -2604,13 +3047,8 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
init_completion(&data->done);
- ret = devm_request_threaded_irq(dev,
- irq,
- bmp085_eoc_irq,
- NULL,
- irq_trig,
- name,
- data);
+ ret = devm_request_irq(dev, irq, bmp085_eoc_irq, irq_trig,
+ indio_dev->name, data);
if (ret) {
/* Bail out without IRQ but keep the driver in place */
dev_err(dev, "unable to request DRDY IRQ\n");
@@ -2618,14 +3056,54 @@ static int bmp085_fetch_eoc_irq(struct device *dev,
}
data->use_eoc = true;
+
return 0;
}
+/* Identical to bmp180_chip_info + bmp085_trigger_probe */
+const struct bmp280_chip_info bmp085_chip_info = {
+ .id_reg = BMP280_REG_ID,
+ .chip_id = bmp180_chip_ids,
+ .num_chip_id = ARRAY_SIZE(bmp180_chip_ids),
+ .regmap_config = &bmp180_regmap_config,
+ .start_up_time = 2000,
+ .channels = bmp280_channels,
+ .num_channels = ARRAY_SIZE(bmp280_channels),
+ .avail_scan_masks = bmp280_avail_scan_masks,
+
+ .oversampling_temp_avail = bmp180_oversampling_temp_avail,
+ .num_oversampling_temp_avail =
+ ARRAY_SIZE(bmp180_oversampling_temp_avail),
+ .oversampling_temp_default = 0,
+
+ .oversampling_press_avail = bmp180_oversampling_press_avail,
+ .num_oversampling_press_avail =
+ ARRAY_SIZE(bmp180_oversampling_press_avail),
+ .oversampling_press_default = BMP180_MEAS_PRESS_8X,
+
+ .temp_coeffs = bmp180_temp_coeffs,
+ .temp_coeffs_type = IIO_VAL_FRACTIONAL,
+ .press_coeffs = bmp180_press_coeffs,
+ .press_coeffs_type = IIO_VAL_FRACTIONAL,
+
+ .chip_config = bmp180_chip_config,
+ .read_temp = bmp180_read_temp,
+ .read_press = bmp180_read_press,
+ .read_calib = bmp180_read_calib,
+ .set_mode = bmp180_set_mode,
+ .wait_conv = bmp180_wait_conv,
+
+ .trigger_probe = bmp085_trigger_probe,
+ .trigger_handler = bmp180_trigger_handler,
+};
+EXPORT_SYMBOL_NS(bmp085_chip_info, "IIO_BMP280");
+
static int bmp280_buffer_preenable(struct iio_dev *indio_dev)
{
struct bmp280_data *data = iio_priv(indio_dev);
pm_runtime_get_sync(data->dev);
+ data->chip_info->set_mode(data, BMP280_NORMAL);
return 0;
}
@@ -2790,12 +3268,17 @@ int bmp280_common_probe(struct device *dev,
* however as it happens, the BMP085 shares the chip ID of BMP180
* so we look for an IRQ if we have that.
*/
- if (irq > 0 && (chip_id == BMP180_CHIP_ID)) {
- ret = bmp085_fetch_eoc_irq(dev, name, irq, data);
+ if (irq > 0) {
+ if (data->chip_info->trigger_probe)
+ ret = data->chip_info->trigger_probe(indio_dev);
if (ret)
return ret;
}
+ ret = data->chip_info->set_mode(data, BMP280_SLEEP);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to set sleep mode\n");
+
/* Enable runtime PM */
pm_runtime_get_noresume(dev);
pm_runtime_set_active(dev);
@@ -2814,13 +3297,16 @@ int bmp280_common_probe(struct device *dev,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS(bmp280_common_probe, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp280_common_probe, "IIO_BMP280");
static int bmp280_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = dev_get_drvdata(dev);
struct bmp280_data *data = iio_priv(indio_dev);
+ data->chip_info->set_mode(data, BMP280_SLEEP);
+
+ fsleep(data->start_up_time);
return regulator_bulk_disable(BMP280_NUM_SUPPLIES, data->supplies);
}
@@ -2835,7 +3321,12 @@ static int bmp280_runtime_resume(struct device *dev)
return ret;
usleep_range(data->start_up_time, data->start_up_time + 100);
- return data->chip_info->chip_config(data);
+
+ ret = data->chip_info->chip_config(data);
+ if (ret)
+ return ret;
+
+ return data->chip_info->set_mode(data, data->op_mode);
}
EXPORT_RUNTIME_DEV_PM_OPS(bmp280_dev_pm_ops, bmp280_runtime_suspend,
diff --git a/drivers/iio/pressure/bmp280-i2c.c b/drivers/iio/pressure/bmp280-i2c.c
index 5c3a63b4327c..868e1b2ec711 100644
--- a/drivers/iio/pressure/bmp280-i2c.c
+++ b/drivers/iio/pressure/bmp280-i2c.c
@@ -27,7 +27,7 @@ static int bmp280_i2c_probe(struct i2c_client *client)
}
static const struct of_device_id bmp280_of_i2c_match[] = {
- { .compatible = "bosch,bmp085", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp085", .data = &bmp085_chip_info },
{ .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
{ .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
{ .compatible = "bosch,bme280", .data = &bme280_chip_info },
@@ -38,7 +38,7 @@ static const struct of_device_id bmp280_of_i2c_match[] = {
MODULE_DEVICE_TABLE(of, bmp280_of_i2c_match);
static const struct i2c_device_id bmp280_i2c_id[] = {
- {"bmp085", (kernel_ulong_t)&bmp180_chip_info },
+ {"bmp085", (kernel_ulong_t)&bmp085_chip_info },
{"bmp180", (kernel_ulong_t)&bmp180_chip_info },
{"bmp280", (kernel_ulong_t)&bmp280_chip_info },
{"bme280", (kernel_ulong_t)&bme280_chip_info },
@@ -62,4 +62,4 @@ module_i2c_driver(bmp280_i2c_driver);
MODULE_AUTHOR("Vlad Dogaru <vlad.dogaru@intel.com>");
MODULE_DESCRIPTION("Driver for Bosch Sensortec BMP180/BMP280 pressure and temperature sensor");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_BMP280);
+MODULE_IMPORT_NS("IIO_BMP280");
diff --git a/drivers/iio/pressure/bmp280-regmap.c b/drivers/iio/pressure/bmp280-regmap.c
index d27d68edd906..b6a7b417c8cf 100644
--- a/drivers/iio/pressure/bmp280-regmap.c
+++ b/drivers/iio/pressure/bmp280-regmap.c
@@ -39,7 +39,7 @@ const struct regmap_config bmp180_regmap_config = {
.writeable_reg = bmp180_is_writeable_reg,
.volatile_reg = bmp180_is_volatile_reg,
};
-EXPORT_SYMBOL_NS(bmp180_regmap_config, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp180_regmap_config, "IIO_BMP280");
static bool bme280_is_writeable_reg(struct device *dev, unsigned int reg)
{
@@ -200,7 +200,7 @@ const struct regmap_config bmp280_regmap_config = {
.writeable_reg = bmp280_is_writeable_reg,
.volatile_reg = bmp280_is_volatile_reg,
};
-EXPORT_SYMBOL_NS(bmp280_regmap_config, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp280_regmap_config, "IIO_BMP280");
const struct regmap_config bme280_regmap_config = {
.reg_bits = 8,
@@ -212,7 +212,7 @@ const struct regmap_config bme280_regmap_config = {
.writeable_reg = bme280_is_writeable_reg,
.volatile_reg = bme280_is_volatile_reg,
};
-EXPORT_SYMBOL_NS(bme280_regmap_config, IIO_BMP280);
+EXPORT_SYMBOL_NS(bme280_regmap_config, "IIO_BMP280");
const struct regmap_config bmp380_regmap_config = {
.reg_bits = 8,
@@ -224,7 +224,7 @@ const struct regmap_config bmp380_regmap_config = {
.writeable_reg = bmp380_is_writeable_reg,
.volatile_reg = bmp380_is_volatile_reg,
};
-EXPORT_SYMBOL_NS(bmp380_regmap_config, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp380_regmap_config, "IIO_BMP280");
const struct regmap_config bmp580_regmap_config = {
.reg_bits = 8,
@@ -236,4 +236,4 @@ const struct regmap_config bmp580_regmap_config = {
.writeable_reg = bmp580_is_writeable_reg,
.volatile_reg = bmp580_is_volatile_reg,
};
-EXPORT_SYMBOL_NS(bmp580_regmap_config, IIO_BMP280);
+EXPORT_SYMBOL_NS(bmp580_regmap_config, "IIO_BMP280");
diff --git a/drivers/iio/pressure/bmp280-spi.c b/drivers/iio/pressure/bmp280-spi.c
index d18549d9bb64..0e6e27892f99 100644
--- a/drivers/iio/pressure/bmp280-spi.c
+++ b/drivers/iio/pressure/bmp280-spi.c
@@ -114,7 +114,7 @@ static int bmp280_spi_probe(struct spi_device *spi)
}
static const struct of_device_id bmp280_of_spi_match[] = {
- { .compatible = "bosch,bmp085", .data = &bmp180_chip_info },
+ { .compatible = "bosch,bmp085", .data = &bmp085_chip_info },
{ .compatible = "bosch,bmp180", .data = &bmp180_chip_info },
{ .compatible = "bosch,bmp181", .data = &bmp180_chip_info },
{ .compatible = "bosch,bmp280", .data = &bmp280_chip_info },
@@ -126,7 +126,7 @@ static const struct of_device_id bmp280_of_spi_match[] = {
MODULE_DEVICE_TABLE(of, bmp280_of_spi_match);
static const struct spi_device_id bmp280_spi_id[] = {
- { "bmp085", (kernel_ulong_t)&bmp180_chip_info },
+ { "bmp085", (kernel_ulong_t)&bmp085_chip_info },
{ "bmp180", (kernel_ulong_t)&bmp180_chip_info },
{ "bmp181", (kernel_ulong_t)&bmp180_chip_info },
{ "bmp280", (kernel_ulong_t)&bmp280_chip_info },
@@ -150,4 +150,4 @@ module_spi_driver(bmp280_spi_driver);
MODULE_DESCRIPTION("BMP280 SPI bus driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_BMP280);
+MODULE_IMPORT_NS("IIO_BMP280");
diff --git a/drivers/iio/pressure/bmp280.h b/drivers/iio/pressure/bmp280.h
index ccacc67c1473..2df1175b6b85 100644
--- a/drivers/iio/pressure/bmp280.h
+++ b/drivers/iio/pressure/bmp280.h
@@ -55,8 +55,17 @@
#define BMP580_CMD_NVM_WRITE_SEQ_1 0xA0
#define BMP580_CMD_SOFT_RESET 0xB6
+#define BMP580_INT_STATUS_DRDY_MASK BIT(0)
#define BMP580_INT_STATUS_POR_MASK BIT(4)
+#define BMP580_INT_SOURCE_DRDY BIT(0)
+
+#define BMP580_INT_CONFIG_MASK GENMASK(3, 0)
+#define BMP580_INT_CONFIG_LATCH BIT(0)
+#define BMP580_INT_CONFIG_LEVEL BIT(1)
+#define BMP580_INT_CONFIG_OPEN_DRAIN BIT(2)
+#define BMP580_INT_CONFIG_INT_EN BIT(3)
+
#define BMP580_STATUS_CORE_RDY_MASK BIT(0)
#define BMP580_STATUS_NVM_RDY_MASK BIT(1)
#define BMP580_STATUS_NVM_ERR_MASK BIT(2)
@@ -170,6 +179,19 @@
#define BMP380_MODE_FORCED 1
#define BMP380_MODE_NORMAL 3
+#define BMP380_MEAS_OFFSET 234
+#define BMP380_MEAS_DUR 2020
+#define BMP380_TEMP_MEAS_OFFSET 163
+#define BMP380_PRESS_MEAS_OFFSET 392
+
+#define BMP380_INT_STATUS_DRDY BIT(3)
+
+#define BMP380_INT_CTRL_SETTINGS_MASK GENMASK(2, 0)
+#define BMP380_INT_CTRL_OPEN_DRAIN BIT(0)
+#define BMP380_INT_CTRL_LEVEL BIT(1)
+#define BMP380_INT_CTRL_LATCH BIT(2)
+#define BMP380_INT_CTRL_DRDY_EN BIT(6)
+
#define BMP380_MIN_TEMP -4000
#define BMP380_MAX_TEMP 8500
#define BMP380_MIN_PRES 3000000
@@ -205,6 +227,10 @@
#define BMP280_REG_CONFIG 0xF5
#define BMP280_REG_CTRL_MEAS 0xF4
#define BMP280_REG_STATUS 0xF3
+#define BMP280_REG_STATUS_IM_UPDATE BIT(0)
+#define BMP280_REG_STATUS_MEAS_BIT BIT(3)
+#define BMP280_REG_RESET 0xE0
+#define BMP280_RST_SOFT_CMD 0xB6
#define BMP280_REG_COMP_TEMP_START 0x88
#define BMP280_COMP_TEMP_REG_COUNT 6
@@ -243,6 +269,10 @@
#define BMP280_MODE_FORCED 1
#define BMP280_MODE_NORMAL 3
+#define BMP280_MEAS_OFFSET 1250
+#define BMP280_MEAS_DUR 2300
+#define BMP280_PRESS_HUMID_MEAS_OFFSET 575
+
/* BME280 specific registers */
#define BME280_REG_HUMIDITY_LSB 0xFE
#define BME280_REG_HUMIDITY_MSB 0xFD
@@ -257,8 +287,13 @@
#define BME280_REG_COMP_H5 0xE5
#define BME280_REG_COMP_H6 0xE7
+#define BME280_COMP_H4_GET_MASK_UP GENMASK(15, 8)
+#define BME280_COMP_H4_PREP_MASK_UP GENMASK(11, 4)
+#define BME280_COMP_H4_MASK_LOW GENMASK(3, 0)
#define BME280_COMP_H5_MASK GENMASK(15, 4)
+#define BME280_CONTIGUOUS_CALIB_REGS 7
+
#define BME280_OSRS_HUMIDITY_MASK GENMASK(2, 0)
#define BME280_OSRS_HUMIDITY_SKIP 0
#define BME280_OSRS_HUMIDITY_1X 1
@@ -314,6 +349,7 @@
BMP280_NUM_TEMP_BYTES + \
BME280_NUM_HUMIDITY_BYTES)
+#define BME280_NUM_MAX_CHANNELS 3
/* Core exported structs */
static const char *const bmp280_supply_names[] = {
@@ -376,12 +412,21 @@ struct bmp380_calib {
s8 P11;
};
+enum bmp280_op_mode {
+ BMP280_SLEEP,
+ BMP280_FORCED,
+ BMP280_NORMAL,
+};
+
struct bmp280_data {
struct device *dev;
struct mutex lock;
struct regmap *regmap;
struct completion done;
bool use_eoc;
+ bool trig_open_drain;
+ bool trig_active_high;
+ struct iio_trigger *trig;
const struct bmp280_chip_info *chip_info;
union {
struct bmp180_calib bmp180;
@@ -411,7 +456,11 @@ struct bmp280_data {
* Data to push to userspace triggered buffer. Up to 3 channels and
* s64 timestamp, aligned.
*/
- s32 sensor_data[6] __aligned(8);
+ u8 sensor_data[ALIGN(sizeof(s32) * BME280_NUM_MAX_CHANNELS, sizeof(s64))
+ + sizeof(s64)] __aligned(sizeof(s64));
+
+ /* Value to hold the current operation mode of the device */
+ enum bmp280_op_mode op_mode;
/*
* DMA (thus cache coherency maintenance) may require the
@@ -423,6 +472,7 @@ struct bmp280_data {
/* Calibration data buffers */
__le16 bmp280_cal_buf[BMP280_CONTIGUOUS_CALIB_REGS / 2];
__be16 bmp180_cal_buf[BMP180_REG_CALIB_COUNT / 2];
+ u8 bme280_humid_cal_buf[BME280_CONTIGUOUS_CALIB_REGS];
u8 bmp380_cal_buf[BMP380_CALIB_REG_COUNT];
/* Miscellaneous, endianness-aware data buffers */
__le16 le16;
@@ -476,11 +526,15 @@ struct bmp280_chip_info {
int (*read_humid)(struct bmp280_data *data, u32 *adc_humidity);
int (*read_calib)(struct bmp280_data *data);
int (*preinit)(struct bmp280_data *data);
+ int (*set_mode)(struct bmp280_data *data, enum bmp280_op_mode mode);
+ int (*wait_conv)(struct bmp280_data *data);
+ int (*trigger_probe)(struct iio_dev *indio_dev);
irqreturn_t (*trigger_handler)(int irq, void *p);
};
/* Chip infos for each variant */
+extern const struct bmp280_chip_info bmp085_chip_info;
extern const struct bmp280_chip_info bmp180_chip_info;
extern const struct bmp280_chip_info bmp280_chip_info;
extern const struct bmp280_chip_info bme280_chip_info;
diff --git a/drivers/iio/pressure/hid-sensor-press.c b/drivers/iio/pressure/hid-sensor-press.c
index 956045e2db29..f7273d30c5f0 100644
--- a/drivers/iio/pressure/hid-sensor-press.c
+++ b/drivers/iio/pressure/hid-sensor-press.c
@@ -24,7 +24,7 @@ struct press_state {
struct hid_sensor_hub_attribute_info press_attr;
struct {
u32 press_data;
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -241,11 +241,11 @@ static int press_parse_report(struct platform_device *pdev,
/* Function to initialize the processing for usage id */
static int hid_press_probe(struct platform_device *pdev)
{
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
int ret = 0;
static const char *name = "press";
struct iio_dev *indio_dev;
struct press_state *press_state;
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
indio_dev = devm_iio_device_alloc(&pdev->dev,
sizeof(struct press_state));
@@ -325,7 +325,7 @@ error_remove_trigger:
/* Function to deinitialize the processing for usage id */
static void hid_press_remove(struct platform_device *pdev)
{
- struct hid_sensor_hub_device *hsdev = pdev->dev.platform_data;
+ struct hid_sensor_hub_device *hsdev = dev_get_platdata(&pdev->dev);
struct iio_dev *indio_dev = platform_get_drvdata(pdev);
struct press_state *press_state = iio_priv(indio_dev);
@@ -350,11 +350,11 @@ static struct platform_driver hid_press_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_press_probe,
- .remove_new = hid_press_remove,
+ .remove = hid_press_remove,
};
module_platform_driver(hid_press_platform_driver);
MODULE_DESCRIPTION("HID Sensor Pressure");
MODULE_AUTHOR("Archana Patni <archana.patni@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/pressure/hsc030pa.c b/drivers/iio/pressure/hsc030pa.c
index 4e6f10eeabc3..168245818cfe 100644
--- a/drivers/iio/pressure/hsc030pa.c
+++ b/drivers/iio/pressure/hsc030pa.c
@@ -534,7 +534,7 @@ int hsc_common_probe(struct device *dev, hsc_recv_fn recv)
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS(hsc_common_probe, IIO_HONEYWELL_HSC030PA);
+EXPORT_SYMBOL_NS(hsc_common_probe, "IIO_HONEYWELL_HSC030PA");
MODULE_AUTHOR("Petre Rodan <petre.rodan@subdimension.ro>");
MODULE_DESCRIPTION("Honeywell HSC and SSC pressure sensor core driver");
diff --git a/drivers/iio/pressure/hsc030pa_i2c.c b/drivers/iio/pressure/hsc030pa_i2c.c
index b3fd230e71da..7f2398aa8155 100644
--- a/drivers/iio/pressure/hsc030pa_i2c.c
+++ b/drivers/iio/pressure/hsc030pa_i2c.c
@@ -71,4 +71,4 @@ module_i2c_driver(hsc_i2c_driver);
MODULE_AUTHOR("Petre Rodan <petre.rodan@subdimension.ro>");
MODULE_DESCRIPTION("Honeywell HSC and SSC pressure sensor i2c driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HONEYWELL_HSC030PA);
+MODULE_IMPORT_NS("IIO_HONEYWELL_HSC030PA");
diff --git a/drivers/iio/pressure/hsc030pa_spi.c b/drivers/iio/pressure/hsc030pa_spi.c
index 337eecc577d2..60768726e9ad 100644
--- a/drivers/iio/pressure/hsc030pa_spi.c
+++ b/drivers/iio/pressure/hsc030pa_spi.c
@@ -58,4 +58,4 @@ module_spi_driver(hsc_spi_driver);
MODULE_AUTHOR("Petre Rodan <petre.rodan@subdimension.ro>");
MODULE_DESCRIPTION("Honeywell HSC and SSC pressure sensor spi driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HONEYWELL_HSC030PA);
+MODULE_IMPORT_NS("IIO_HONEYWELL_HSC030PA");
diff --git a/drivers/iio/pressure/mpl115.c b/drivers/iio/pressure/mpl115.c
index 02ea38c8a3e4..71beb28b7f2c 100644
--- a/drivers/iio/pressure/mpl115.c
+++ b/drivers/iio/pressure/mpl115.c
@@ -225,7 +225,7 @@ int mpl115_probe(struct device *dev, const char *name,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(mpl115_probe, IIO_MPL115);
+EXPORT_SYMBOL_NS_GPL(mpl115_probe, "IIO_MPL115");
static int mpl115_runtime_suspend(struct device *dev)
{
diff --git a/drivers/iio/pressure/mpl115_i2c.c b/drivers/iio/pressure/mpl115_i2c.c
index 0c51dc02478e..3db9ef4e2770 100644
--- a/drivers/iio/pressure/mpl115_i2c.c
+++ b/drivers/iio/pressure/mpl115_i2c.c
@@ -63,4 +63,4 @@ module_i2c_driver(mpl115_i2c_driver);
MODULE_AUTHOR("Peter Meerwald <pmeerw@pmeerw.net>");
MODULE_DESCRIPTION("Freescale MPL115A2 pressure/temperature driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_MPL115);
+MODULE_IMPORT_NS("IIO_MPL115");
diff --git a/drivers/iio/pressure/mpl115_spi.c b/drivers/iio/pressure/mpl115_spi.c
index 58d218fd90dc..888cfa666238 100644
--- a/drivers/iio/pressure/mpl115_spi.c
+++ b/drivers/iio/pressure/mpl115_spi.c
@@ -102,4 +102,4 @@ module_spi_driver(mpl115_spi_driver);
MODULE_AUTHOR("Akinobu Mita <akinobu.mita@gmail.com>");
MODULE_DESCRIPTION("Freescale MPL115A1 pressure/temperature driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_MPL115);
+MODULE_IMPORT_NS("IIO_MPL115");
diff --git a/drivers/iio/pressure/mprls0025pa.c b/drivers/iio/pressure/mprls0025pa.c
index 3b6145348c2e..2336f2760eae 100644
--- a/drivers/iio/pressure/mprls0025pa.c
+++ b/drivers/iio/pressure/mprls0025pa.c
@@ -448,7 +448,7 @@ int mpr_common_probe(struct device *dev, const struct mpr_ops *ops, int irq)
return 0;
}
-EXPORT_SYMBOL_NS(mpr_common_probe, IIO_HONEYWELL_MPRLS0025PA);
+EXPORT_SYMBOL_NS(mpr_common_probe, "IIO_HONEYWELL_MPRLS0025PA");
MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
MODULE_DESCRIPTION("Honeywell MPR pressure sensor core driver");
diff --git a/drivers/iio/pressure/mprls0025pa_i2c.c b/drivers/iio/pressure/mprls0025pa_i2c.c
index 7a5c5aa2b456..48b23a4256ce 100644
--- a/drivers/iio/pressure/mprls0025pa_i2c.c
+++ b/drivers/iio/pressure/mprls0025pa_i2c.c
@@ -97,4 +97,4 @@ module_i2c_driver(mpr_i2c_driver);
MODULE_AUTHOR("Andreas Klinger <ak@it-klinger.de>");
MODULE_DESCRIPTION("Honeywell MPR pressure sensor i2c driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HONEYWELL_MPRLS0025PA);
+MODULE_IMPORT_NS("IIO_HONEYWELL_MPRLS0025PA");
diff --git a/drivers/iio/pressure/mprls0025pa_spi.c b/drivers/iio/pressure/mprls0025pa_spi.c
index 3aed14cd95c5..09f724c76d70 100644
--- a/drivers/iio/pressure/mprls0025pa_spi.c
+++ b/drivers/iio/pressure/mprls0025pa_spi.c
@@ -89,4 +89,4 @@ module_spi_driver(mpr_spi_driver);
MODULE_AUTHOR("Petre Rodan <petre.rodan@subdimension.ro>");
MODULE_DESCRIPTION("Honeywell MPR pressure sensor spi driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HONEYWELL_MPRLS0025PA);
+MODULE_IMPORT_NS("IIO_HONEYWELL_MPRLS0025PA");
diff --git a/drivers/iio/pressure/ms5611_core.c b/drivers/iio/pressure/ms5611_core.c
index 2fc706f9d8ae..056c8271c49d 100644
--- a/drivers/iio/pressure/ms5611_core.c
+++ b/drivers/iio/pressure/ms5611_core.c
@@ -449,7 +449,7 @@ int ms5611_probe(struct iio_dev *indio_dev, struct device *dev,
return 0;
}
-EXPORT_SYMBOL_NS(ms5611_probe, IIO_MS5611);
+EXPORT_SYMBOL_NS(ms5611_probe, "IIO_MS5611");
MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
MODULE_DESCRIPTION("MS5611 core driver");
diff --git a/drivers/iio/pressure/ms5611_i2c.c b/drivers/iio/pressure/ms5611_i2c.c
index 7e2cb8b6afa2..1c041b9085fb 100644
--- a/drivers/iio/pressure/ms5611_i2c.c
+++ b/drivers/iio/pressure/ms5611_i2c.c
@@ -132,4 +132,4 @@ module_i2c_driver(ms5611_driver);
MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
MODULE_DESCRIPTION("MS5611 i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_MS5611);
+MODULE_IMPORT_NS("IIO_MS5611");
diff --git a/drivers/iio/pressure/ms5611_spi.c b/drivers/iio/pressure/ms5611_spi.c
index 87181963a3e3..b5a91e885793 100644
--- a/drivers/iio/pressure/ms5611_spi.c
+++ b/drivers/iio/pressure/ms5611_spi.c
@@ -134,4 +134,4 @@ module_spi_driver(ms5611_driver);
MODULE_AUTHOR("Tomasz Duszynski <tduszyns@gmail.com>");
MODULE_DESCRIPTION("MS5611 spi driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_MS5611);
+MODULE_IMPORT_NS("IIO_MS5611");
diff --git a/drivers/iio/pressure/ms5637.c b/drivers/iio/pressure/ms5637.c
index ac30d76285d1..a1767a17fdce 100644
--- a/drivers/iio/pressure/ms5637.c
+++ b/drivers/iio/pressure/ms5637.c
@@ -248,4 +248,4 @@ MODULE_DESCRIPTION("Measurement-Specialties ms5637 temperature & pressure driver
MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
MODULE_AUTHOR("Ludovic Tancerel <ludovic.tancerel@maplehightech.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_MEAS_SPEC_SENSORS);
+MODULE_IMPORT_NS("IIO_MEAS_SPEC_SENSORS");
diff --git a/drivers/iio/pressure/rohm-bm1390.c b/drivers/iio/pressure/rohm-bm1390.c
index ccaa07a569c9..f24d9f927681 100644
--- a/drivers/iio/pressure/rohm-bm1390.c
+++ b/drivers/iio/pressure/rohm-bm1390.c
@@ -417,9 +417,6 @@ static int __bm1390_fifo_flush(struct iio_dev *idev, unsigned int samples,
return ret;
}
- if (ret)
- return ret;
-
for (i = 0; i < smp_lvl; i++) {
buffer[i].temp = temp;
iio_push_to_buffers(idev, &buffer[i]);
diff --git a/drivers/iio/pressure/st_pressure_core.c b/drivers/iio/pressure/st_pressure_core.c
index 597bf268ea51..b70d1cee82f3 100644
--- a/drivers/iio/pressure/st_pressure_core.c
+++ b/drivers/iio/pressure/st_pressure_core.c
@@ -738,7 +738,7 @@ const struct st_sensor_settings *st_press_get_settings(const char *name)
return &st_press_sensors_settings[index];
}
-EXPORT_SYMBOL_NS(st_press_get_settings, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_press_get_settings, "IIO_ST_SENSORS");
int st_press_common_probe(struct iio_dev *indio_dev)
{
@@ -790,9 +790,9 @@ int st_press_common_probe(struct iio_dev *indio_dev)
return devm_iio_device_register(parent, indio_dev);
}
-EXPORT_SYMBOL_NS(st_press_common_probe, IIO_ST_SENSORS);
+EXPORT_SYMBOL_NS(st_press_common_probe, "IIO_ST_SENSORS");
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics pressures driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/pressure/st_pressure_i2c.c b/drivers/iio/pressure/st_pressure_i2c.c
index 389523d6ae32..b7b66ddc3a73 100644
--- a/drivers/iio/pressure/st_pressure_i2c.c
+++ b/drivers/iio/pressure/st_pressure_i2c.c
@@ -121,4 +121,4 @@ module_i2c_driver(st_press_driver);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics pressures i2c driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/pressure/st_pressure_spi.c b/drivers/iio/pressure/st_pressure_spi.c
index 25cca5ad7c55..1a4bd1a0f787 100644
--- a/drivers/iio/pressure/st_pressure_spi.c
+++ b/drivers/iio/pressure/st_pressure_spi.c
@@ -123,4 +123,4 @@ module_spi_driver(st_press_driver);
MODULE_AUTHOR("Denis Ciocca <denis.ciocca@st.com>");
MODULE_DESCRIPTION("STMicroelectronics pressures spi driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ST_SENSORS);
+MODULE_IMPORT_NS("IIO_ST_SENSORS");
diff --git a/drivers/iio/pressure/zpa2326.c b/drivers/iio/pressure/zpa2326.c
index 950f8dee2b26..2adea84f5b4d 100644
--- a/drivers/iio/pressure/zpa2326.c
+++ b/drivers/iio/pressure/zpa2326.c
@@ -162,7 +162,7 @@ bool zpa2326_isreg_writeable(struct device *dev, unsigned int reg)
return false;
}
}
-EXPORT_SYMBOL_NS_GPL(zpa2326_isreg_writeable, IIO_ZPA2326);
+EXPORT_SYMBOL_NS_GPL(zpa2326_isreg_writeable, "IIO_ZPA2326");
bool zpa2326_isreg_readable(struct device *dev, unsigned int reg)
{
@@ -191,7 +191,7 @@ bool zpa2326_isreg_readable(struct device *dev, unsigned int reg)
return false;
}
}
-EXPORT_SYMBOL_NS_GPL(zpa2326_isreg_readable, IIO_ZPA2326);
+EXPORT_SYMBOL_NS_GPL(zpa2326_isreg_readable, "IIO_ZPA2326");
bool zpa2326_isreg_precious(struct device *dev, unsigned int reg)
{
@@ -204,7 +204,7 @@ bool zpa2326_isreg_precious(struct device *dev, unsigned int reg)
return false;
}
}
-EXPORT_SYMBOL_NS_GPL(zpa2326_isreg_precious, IIO_ZPA2326);
+EXPORT_SYMBOL_NS_GPL(zpa2326_isreg_precious, "IIO_ZPA2326");
/**
* zpa2326_enable_device() - Enable device, i.e. get out of low power mode.
@@ -649,7 +649,7 @@ const struct dev_pm_ops zpa2326_pm_ops = {
SET_RUNTIME_PM_OPS(zpa2326_runtime_suspend, zpa2326_runtime_resume,
NULL)
};
-EXPORT_SYMBOL_NS_GPL(zpa2326_pm_ops, IIO_ZPA2326);
+EXPORT_SYMBOL_NS_GPL(zpa2326_pm_ops, "IIO_ZPA2326");
/**
* zpa2326_resume() - Request the PM layer to power supply the device.
@@ -1698,7 +1698,7 @@ poweroff:
return err;
}
-EXPORT_SYMBOL_NS_GPL(zpa2326_probe, IIO_ZPA2326);
+EXPORT_SYMBOL_NS_GPL(zpa2326_probe, "IIO_ZPA2326");
void zpa2326_remove(const struct device *parent)
{
@@ -1709,7 +1709,7 @@ void zpa2326_remove(const struct device *parent)
zpa2326_sleep(indio_dev);
zpa2326_power_off(indio_dev, iio_priv(indio_dev));
}
-EXPORT_SYMBOL_NS_GPL(zpa2326_remove, IIO_ZPA2326);
+EXPORT_SYMBOL_NS_GPL(zpa2326_remove, "IIO_ZPA2326");
MODULE_AUTHOR("Gregor Boirie <gregor.boirie@parrot.com>");
MODULE_DESCRIPTION("Core driver for Murata ZPA2326 pressure sensor");
diff --git a/drivers/iio/pressure/zpa2326_i2c.c b/drivers/iio/pressure/zpa2326_i2c.c
index 4833e525c393..49a239ebdabf 100644
--- a/drivers/iio/pressure/zpa2326_i2c.c
+++ b/drivers/iio/pressure/zpa2326_i2c.c
@@ -85,4 +85,4 @@ module_i2c_driver(zpa2326_i2c_driver);
MODULE_AUTHOR("Gregor Boirie <gregor.boirie@parrot.com>");
MODULE_DESCRIPTION("I2C driver for Murata ZPA2326 pressure sensor");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ZPA2326);
+MODULE_IMPORT_NS("IIO_ZPA2326");
diff --git a/drivers/iio/pressure/zpa2326_spi.c b/drivers/iio/pressure/zpa2326_spi.c
index 9c1bcb82d360..317270fa1c43 100644
--- a/drivers/iio/pressure/zpa2326_spi.c
+++ b/drivers/iio/pressure/zpa2326_spi.c
@@ -89,4 +89,4 @@ module_spi_driver(zpa2326_spi_driver);
MODULE_AUTHOR("Gregor Boirie <gregor.boirie@parrot.com>");
MODULE_DESCRIPTION("SPI driver for Murata ZPA2326 pressure sensor");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_ZPA2326);
+MODULE_IMPORT_NS("IIO_ZPA2326");
diff --git a/drivers/iio/proximity/aw96103.c b/drivers/iio/proximity/aw96103.c
index 707ba0a510aa..cdd254da9e50 100644
--- a/drivers/iio/proximity/aw96103.c
+++ b/drivers/iio/proximity/aw96103.c
@@ -422,7 +422,7 @@ static int aw96103_read_event_config(struct iio_dev *indio_dev,
static int aw96103_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct aw96103 *aw96103 = iio_priv(indio_dev);
diff --git a/drivers/iio/proximity/cros_ec_mkbp_proximity.c b/drivers/iio/proximity/cros_ec_mkbp_proximity.c
index c25472b14d4b..667369be0555 100644
--- a/drivers/iio/proximity/cros_ec_mkbp_proximity.c
+++ b/drivers/iio/proximity/cros_ec_mkbp_proximity.c
@@ -167,7 +167,7 @@ static int cros_ec_mkbp_proximity_read_event_config(struct iio_dev *indio_dev,
static int cros_ec_mkbp_proximity_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct cros_ec_mkbp_proximity_data *data = iio_priv(indio_dev);
@@ -261,7 +261,7 @@ static struct platform_driver cros_ec_mkbp_proximity_driver = {
.pm = pm_sleep_ptr(&cros_ec_mkbp_proximity_pm_ops),
},
.probe = cros_ec_mkbp_proximity_probe,
- .remove_new = cros_ec_mkbp_proximity_remove,
+ .remove = cros_ec_mkbp_proximity_remove,
};
module_platform_driver(cros_ec_mkbp_proximity_driver);
diff --git a/drivers/iio/proximity/hx9023s.c b/drivers/iio/proximity/hx9023s.c
index d8fb34060d3d..4021feb7a7ac 100644
--- a/drivers/iio/proximity/hx9023s.c
+++ b/drivers/iio/proximity/hx9023s.c
@@ -874,12 +874,12 @@ static int hx9023s_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct hx9023s_data *data = iio_priv(indio_dev);
if (test_bit(chan->channel, &data->chan_in_use)) {
- hx9023s_ch_en(data, chan->channel, !!state);
+ hx9023s_ch_en(data, chan->channel, state);
__assign_bit(chan->channel, &data->chan_event,
data->ch_data[chan->channel].enable);
}
diff --git a/drivers/iio/proximity/irsd200.c b/drivers/iio/proximity/irsd200.c
index 6e96b764fed8..b09d15230111 100644
--- a/drivers/iio/proximity/irsd200.c
+++ b/drivers/iio/proximity/irsd200.c
@@ -648,7 +648,8 @@ static int irsd200_read_event_config(struct iio_dev *indio_dev,
static int irsd200_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir,
+ bool state)
{
struct irsd200_data *data = iio_priv(indio_dev);
unsigned int tmp;
@@ -662,7 +663,7 @@ static int irsd200_write_event_config(struct iio_dev *indio_dev,
return ret;
return regmap_field_write(
- data->regfields[IRS_REGF_INTR_COUNT_THR_OR], !!state);
+ data->regfields[IRS_REGF_INTR_COUNT_THR_OR], state);
default:
return -EINVAL;
}
diff --git a/drivers/iio/proximity/srf04.c b/drivers/iio/proximity/srf04.c
index 86c57672fc7e..71ad29e441b2 100644
--- a/drivers/iio/proximity/srf04.c
+++ b/drivers/iio/proximity/srf04.c
@@ -389,7 +389,7 @@ static const struct dev_pm_ops srf04_pm_ops = {
static struct platform_driver srf04_driver = {
.probe = srf04_probe,
- .remove_new = srf04_remove,
+ .remove = srf04_remove,
.driver = {
.name = "srf04-gpio",
.of_match_table = of_srf04_match,
diff --git a/drivers/iio/proximity/sx9310.c b/drivers/iio/proximity/sx9310.c
index 427c9343d6d1..0d7f0518d4fb 100644
--- a/drivers/iio/proximity/sx9310.c
+++ b/drivers/iio/proximity/sx9310.c
@@ -1029,4 +1029,4 @@ MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
MODULE_AUTHOR("Daniel Campello <campello@chromium.org>");
MODULE_DESCRIPTION("Driver for Semtech SX9310/SX9311 proximity sensor");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SEMTECH_PROX);
+MODULE_IMPORT_NS("SEMTECH_PROX");
diff --git a/drivers/iio/proximity/sx9324.c b/drivers/iio/proximity/sx9324.c
index 629f83c37d59..f7819dd2775c 100644
--- a/drivers/iio/proximity/sx9324.c
+++ b/drivers/iio/proximity/sx9324.c
@@ -868,6 +868,26 @@ static u8 sx9324_parse_phase_prop(struct device *dev,
return raw;
}
+static void sx_common_get_raw_register_config(struct device *dev,
+ struct sx_common_reg_default *reg_def)
+{
+#ifdef CONFIG_ACPI
+ struct acpi_device *adev = ACPI_COMPANION(dev);
+ u32 raw = 0, ret;
+ char prop[80];
+
+ if (!reg_def->property || !adev)
+ return;
+
+ snprintf(prop, ARRAY_SIZE(prop), "%s,reg_%s", acpi_device_hid(adev), reg_def->property);
+ ret = device_property_read_u32(dev, prop, &raw);
+ if (ret)
+ return;
+
+ reg_def->def = raw;
+#endif
+}
+
static const struct sx_common_reg_default *
sx9324_get_default_reg(struct device *dev, int idx,
struct sx_common_reg_default *reg_def)
@@ -1135,4 +1155,4 @@ module_i2c_driver(sx9324_driver);
MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
MODULE_DESCRIPTION("Driver for Semtech SX9324 proximity sensor");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SEMTECH_PROX);
+MODULE_IMPORT_NS("SEMTECH_PROX");
diff --git a/drivers/iio/proximity/sx9360.c b/drivers/iio/proximity/sx9360.c
index 2b90bf45a201..a6ff16e33c1e 100644
--- a/drivers/iio/proximity/sx9360.c
+++ b/drivers/iio/proximity/sx9360.c
@@ -7,7 +7,6 @@
* https://edit.wpgdadawant.com/uploads/news_file/program/2019/30184/tech_files/program_30184_suggest_other_file.pdf
*/
-#include <linux/acpi.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/delay.h>
@@ -866,4 +865,4 @@ module_i2c_driver(sx9360_driver);
MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
MODULE_DESCRIPTION("Driver for Semtech SX9360 proximity sensor");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SEMTECH_PROX);
+MODULE_IMPORT_NS("SEMTECH_PROX");
diff --git a/drivers/iio/proximity/sx9500.c b/drivers/iio/proximity/sx9500.c
index 3f4eace05cfc..c4e94d0fb163 100644
--- a/drivers/iio/proximity/sx9500.c
+++ b/drivers/iio/proximity/sx9500.c
@@ -540,7 +540,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct sx9500_data *data = iio_priv(indio_dev);
int ret;
@@ -551,7 +551,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev,
mutex_lock(&data->mutex);
- if (state == 1) {
+ if (state) {
ret = sx9500_inc_chan_users(data, chan->channel);
if (ret < 0)
goto out_unlock;
@@ -571,7 +571,7 @@ static int sx9500_write_event_config(struct iio_dev *indio_dev,
goto out_unlock;
out_undo_chan:
- if (state == 1)
+ if (state)
sx9500_dec_chan_users(data, chan->channel);
else
sx9500_inc_chan_users(data, chan->channel);
diff --git a/drivers/iio/proximity/sx_common.c b/drivers/iio/proximity/sx_common.c
index 71aa6dced7d3..f70198a1f0d1 100644
--- a/drivers/iio/proximity/sx_common.c
+++ b/drivers/iio/proximity/sx_common.c
@@ -53,7 +53,7 @@ const struct iio_event_spec sx_common_events[3] = {
BIT(IIO_EV_INFO_VALUE),
},
};
-EXPORT_SYMBOL_NS_GPL(sx_common_events, SEMTECH_PROX);
+EXPORT_SYMBOL_NS_GPL(sx_common_events, "SEMTECH_PROX");
static irqreturn_t sx_common_irq_handler(int irq, void *private)
{
@@ -233,7 +233,7 @@ out:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(sx_common_read_proximity, SEMTECH_PROX);
+EXPORT_SYMBOL_NS_GPL(sx_common_read_proximity, "SEMTECH_PROX");
/**
* sx_common_read_event_config() - Configure event setting.
@@ -253,7 +253,7 @@ int sx_common_read_event_config(struct iio_dev *indio_dev,
return !!(data->chan_event & BIT(chan->channel));
}
-EXPORT_SYMBOL_NS_GPL(sx_common_read_event_config, SEMTECH_PROX);
+EXPORT_SYMBOL_NS_GPL(sx_common_read_event_config, "SEMTECH_PROX");
/**
* sx_common_write_event_config() - Configure event setting.
@@ -268,7 +268,7 @@ EXPORT_SYMBOL_NS_GPL(sx_common_read_event_config, SEMTECH_PROX);
int sx_common_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct sx_common_data *data = iio_priv(indio_dev);
unsigned int eventirq = SX_COMMON_FAR_IRQ | SX_COMMON_CLOSE_IRQ;
@@ -303,7 +303,7 @@ out_unlock:
mutex_unlock(&data->mutex);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(sx_common_write_event_config, SEMTECH_PROX);
+EXPORT_SYMBOL_NS_GPL(sx_common_write_event_config, "SEMTECH_PROX");
static int sx_common_set_trigger_state(struct iio_trigger *trig, bool state)
{
@@ -421,27 +421,6 @@ static const struct iio_buffer_setup_ops sx_common_buffer_setup_ops = {
.postdisable = sx_common_buffer_postdisable,
};
-void sx_common_get_raw_register_config(struct device *dev,
- struct sx_common_reg_default *reg_def)
-{
-#ifdef CONFIG_ACPI
- struct acpi_device *adev = ACPI_COMPANION(dev);
- u32 raw = 0, ret;
- char prop[80];
-
- if (!reg_def->property || !adev)
- return;
-
- snprintf(prop, ARRAY_SIZE(prop), "%s,reg_%s", acpi_device_hid(adev), reg_def->property);
- ret = device_property_read_u32(dev, prop, &raw);
- if (ret)
- return;
-
- reg_def->def = raw;
-#endif
-}
-EXPORT_SYMBOL_NS_GPL(sx_common_get_raw_register_config, SEMTECH_PROX);
-
#define SX_COMMON_SOFT_RESET 0xde
static int sx_common_init_device(struct device *dev, struct iio_dev *indio_dev)
@@ -563,7 +542,7 @@ int sx_common_probe(struct i2c_client *client,
return devm_iio_device_register(dev, indio_dev);
}
-EXPORT_SYMBOL_NS_GPL(sx_common_probe, SEMTECH_PROX);
+EXPORT_SYMBOL_NS_GPL(sx_common_probe, "SEMTECH_PROX");
MODULE_AUTHOR("Gwendal Grignou <gwendal@chromium.org>");
MODULE_DESCRIPTION("Common functions and structures for Semtech sensor");
diff --git a/drivers/iio/proximity/sx_common.h b/drivers/iio/proximity/sx_common.h
index 101b90e52ff2..fb14e6f06a6d 100644
--- a/drivers/iio/proximity/sx_common.h
+++ b/drivers/iio/proximity/sx_common.h
@@ -8,7 +8,6 @@
#ifndef IIO_SX_COMMON_H
#define IIO_SX_COMMON_H
-#include <linux/acpi.h>
#include <linux/iio/iio.h>
#include <linux/iio/types.h>
#include <linux/regulator/consumer.h>
@@ -144,15 +143,12 @@ int sx_common_read_event_config(struct iio_dev *indio_dev,
int sx_common_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
- enum iio_event_direction dir, int state);
+ enum iio_event_direction dir, bool state);
int sx_common_probe(struct i2c_client *client,
const struct sx_common_chip_info *chip_info,
const struct regmap_config *regmap_config);
-void sx_common_get_raw_register_config(struct device *dev,
- struct sx_common_reg_default *reg_def);
-
/* 3 is the number of events defined by a single phase. */
extern const struct iio_event_spec sx_common_events[3];
diff --git a/drivers/iio/proximity/vcnl3020.c b/drivers/iio/proximity/vcnl3020.c
index d1ddf85f5383..bb6c9cc88b35 100644
--- a/drivers/iio/proximity/vcnl3020.c
+++ b/drivers/iio/proximity/vcnl3020.c
@@ -449,7 +449,7 @@ static int vcnl3020_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
switch (chan->type) {
case IIO_PROXIMITY:
diff --git a/drivers/iio/proximity/vl53l0x-i2c.c b/drivers/iio/proximity/vl53l0x-i2c.c
index 8d4f3f849fe2..87d10faaff9b 100644
--- a/drivers/iio/proximity/vl53l0x-i2c.c
+++ b/drivers/iio/proximity/vl53l0x-i2c.c
@@ -20,8 +20,13 @@
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/module.h>
+#include <linux/unaligned.h>
#include <linux/iio/iio.h>
+#include <linux/iio/buffer.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/trigger_consumer.h>
+#include <linux/iio/triggered_buffer.h>
#define VL_REG_SYSRANGE_START 0x00
@@ -39,21 +44,74 @@
#define VL_REG_RESULT_INT_STATUS 0x13
#define VL_REG_RESULT_RANGE_STATUS 0x14
+#define VL_REG_IDENTIFICATION_MODEL_ID 0xC0
#define VL_REG_RESULT_RANGE_STATUS_COMPLETE BIT(0)
+#define VL53L0X_MODEL_ID_VAL 0xEE
+#define VL53L0X_CONTINUOUS_MODE 0x02
+#define VL53L0X_SINGLE_MODE 0x01
+
struct vl53l0x_data {
struct i2c_client *client;
struct completion completion;
struct regulator *vdd_supply;
struct gpio_desc *reset_gpio;
+ struct iio_trigger *trig;
+
+ struct {
+ u16 chan;
+ aligned_s64 timestamp;
+ } scan;
};
-static irqreturn_t vl53l0x_handle_irq(int irq, void *priv)
+static int vl53l0x_clear_irq(struct vl53l0x_data *data)
+{ int ret;
+
+ ret = i2c_smbus_write_byte_data(data->client,
+ VL_REG_SYSTEM_INTERRUPT_CLEAR, 1);
+ if (ret < 0) {
+ dev_err(&data->client->dev, "failed to clear irq: %d\n", ret);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static irqreturn_t vl53l0x_trigger_handler(int irq, void *priv)
+{
+ struct iio_poll_func *pf = priv;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+ u8 buffer[12];
+ int ret;
+
+ ret = i2c_smbus_read_i2c_block_data(data->client,
+ VL_REG_RESULT_RANGE_STATUS,
+ sizeof(buffer), buffer);
+ if (ret < 0)
+ return ret;
+ else if (ret != 12)
+ return -EREMOTEIO;
+
+ data->scan.chan = get_unaligned_be16(&buffer[10]);
+ iio_push_to_buffers_with_timestamp(indio_dev, &data->scan,
+ iio_get_time_ns(indio_dev));
+
+ iio_trigger_notify_done(indio_dev->trig);
+ vl53l0x_clear_irq(data);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t vl53l0x_threaded_irq(int irq, void *priv)
{
struct iio_dev *indio_dev = priv;
struct vl53l0x_data *data = iio_priv(indio_dev);
- complete(&data->completion);
+ if (iio_buffer_enabled(indio_dev))
+ iio_trigger_poll_nested(indio_dev->trig);
+ else
+ complete(&data->completion);
return IRQ_HANDLED;
}
@@ -68,8 +126,9 @@ static int vl53l0x_configure_irq(struct i2c_client *client,
if (!irq_flags)
irq_flags = IRQF_TRIGGER_FALLING;
- ret = devm_request_irq(&client->dev, client->irq, vl53l0x_handle_irq,
- irq_flags, indio_dev->name, indio_dev);
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ NULL, vl53l0x_threaded_irq,
+ irq_flags | IRQF_ONESHOT, indio_dev->name, indio_dev);
if (ret) {
dev_err(&client->dev, "devm_request_irq error: %d\n", ret);
return ret;
@@ -84,26 +143,6 @@ static int vl53l0x_configure_irq(struct i2c_client *client,
return ret;
}
-static void vl53l0x_clear_irq(struct vl53l0x_data *data)
-{
- struct device *dev = &data->client->dev;
- int ret;
-
- ret = i2c_smbus_write_byte_data(data->client,
- VL_REG_SYSTEM_INTERRUPT_CLEAR, 1);
- if (ret < 0)
- dev_err(dev, "failed to clear error irq: %d\n", ret);
-
- ret = i2c_smbus_write_byte_data(data->client,
- VL_REG_SYSTEM_INTERRUPT_CLEAR, 0);
- if (ret < 0)
- dev_err(dev, "failed to clear range irq: %d\n", ret);
-
- ret = i2c_smbus_read_byte_data(data->client, VL_REG_RESULT_INT_STATUS);
- if (ret < 0 || ret & 0x07)
- dev_err(dev, "failed to clear irq: %d\n", ret);
-}
-
static int vl53l0x_read_proximity(struct vl53l0x_data *data,
const struct iio_chan_spec *chan,
int *val)
@@ -125,7 +164,9 @@ static int vl53l0x_read_proximity(struct vl53l0x_data *data,
if (time_left == 0)
return -ETIMEDOUT;
- vl53l0x_clear_irq(data);
+ ret = vl53l0x_clear_irq(data);
+ if (ret < 0)
+ return ret;
} else {
do {
ret = i2c_smbus_read_byte_data(client,
@@ -150,7 +191,7 @@ static int vl53l0x_read_proximity(struct vl53l0x_data *data,
return -EREMOTEIO;
/* Values should be between 30~1200 in millimeters. */
- *val = (buffer[10] << 8) + buffer[11];
+ *val = get_unaligned_be16(&buffer[10]);
return 0;
}
@@ -160,7 +201,14 @@ static const struct iio_chan_spec vl53l0x_channels[] = {
.type = IIO_DISTANCE,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 'u',
+ .realbits = 12,
+ .storagebits = 16,
+ },
},
+ IIO_CHAN_SOFT_TIMESTAMP(1),
};
static int vl53l0x_read_raw(struct iio_dev *indio_dev,
@@ -190,8 +238,16 @@ static int vl53l0x_read_raw(struct iio_dev *indio_dev,
}
}
+static int vl53l0x_validate_trigger(struct iio_dev *indio_dev, struct iio_trigger *trig)
+{
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+
+ return data->trig == trig ? 0 : -EINVAL;
+}
+
static const struct iio_info vl53l0x_info = {
.read_raw = vl53l0x_read_raw,
+ .validate_trigger = vl53l0x_validate_trigger,
};
static void vl53l0x_power_off(void *_data)
@@ -218,11 +274,46 @@ static int vl53l0x_power_on(struct vl53l0x_data *data)
return 0;
}
+static int vl53l0x_buffer_postenable(struct iio_dev *indio_dev)
+{
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+
+ return i2c_smbus_write_byte_data(data->client, VL_REG_SYSRANGE_START,
+ VL53L0X_CONTINUOUS_MODE);
+}
+
+static int vl53l0x_buffer_postdisable(struct iio_dev *indio_dev)
+{
+ struct vl53l0x_data *data = iio_priv(indio_dev);
+ int ret;
+
+ ret = i2c_smbus_write_byte_data(data->client, VL_REG_SYSRANGE_START,
+ VL53L0X_SINGLE_MODE);
+ if (ret < 0)
+ return ret;
+
+ /* Let the ongoing reading finish */
+ reinit_completion(&data->completion);
+ wait_for_completion_timeout(&data->completion, HZ / 10);
+
+ return vl53l0x_clear_irq(data);
+}
+
+static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
+ .postenable = &vl53l0x_buffer_postenable,
+ .postdisable = &vl53l0x_buffer_postdisable,
+};
+
+static const struct iio_trigger_ops vl53l0x_trigger_ops = {
+ .validate_device = iio_trigger_validate_own_device,
+};
+
static int vl53l0x_probe(struct i2c_client *client)
{
struct vl53l0x_data *data;
struct iio_dev *indio_dev;
int error;
+ int ret;
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (!indio_dev)
@@ -237,6 +328,13 @@ static int vl53l0x_probe(struct i2c_client *client)
I2C_FUNC_SMBUS_BYTE_DATA))
return -EOPNOTSUPP;
+ ret = i2c_smbus_read_byte_data(data->client, VL_REG_IDENTIFICATION_MODEL_ID);
+ if (ret < 0)
+ return -EINVAL;
+
+ if (ret != VL53L0X_MODEL_ID_VAL)
+ dev_info(&client->dev, "Unknown model id: 0x%x", ret);
+
data->vdd_supply = devm_regulator_get(&client->dev, "vdd");
if (IS_ERR(data->vdd_supply))
return dev_err_probe(&client->dev, PTR_ERR(data->vdd_supply),
@@ -265,13 +363,33 @@ static int vl53l0x_probe(struct i2c_client *client)
/* usage of interrupt is optional */
if (client->irq) {
- int ret;
-
init_completion(&data->completion);
+ data->trig = devm_iio_trigger_alloc(&client->dev, "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->trig)
+ return -ENOMEM;
+
+ data->trig->ops = &vl53l0x_trigger_ops;
+ iio_trigger_set_drvdata(data->trig, indio_dev);
+ ret = devm_iio_trigger_register(&client->dev, data->trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->trig);
+
ret = vl53l0x_configure_irq(client, indio_dev);
if (ret)
return ret;
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev,
+ indio_dev,
+ NULL,
+ &vl53l0x_trigger_handler,
+ &iio_triggered_buffer_setup_ops);
+ if (ret)
+ return ret;
}
return devm_iio_device_register(&client->dev, indio_dev);
diff --git a/drivers/iio/temperature/Kconfig b/drivers/iio/temperature/Kconfig
index ed0e4963362f..1244d8e17d50 100644
--- a/drivers/iio/temperature/Kconfig
+++ b/drivers/iio/temperature/Kconfig
@@ -91,6 +91,8 @@ config MLX90635
config TMP006
tristate "TMP006 infrared thermopile sensor"
depends on I2C
+ select IIO_BUFFER
+ select IIO_TRIGGERED_BUFFER
help
If you say yes here you get support for the Texas Instruments
TMP006 infrared thermopile sensor.
diff --git a/drivers/iio/temperature/hid-sensor-temperature.c b/drivers/iio/temperature/hid-sensor-temperature.c
index 0143fd478933..692520e1c497 100644
--- a/drivers/iio/temperature/hid-sensor-temperature.c
+++ b/drivers/iio/temperature/hid-sensor-temperature.c
@@ -18,7 +18,7 @@ struct temperature_state {
struct hid_sensor_hub_attribute_info temperature_attr;
struct {
s32 temperature_data;
- u64 timestamp __aligned(8);
+ aligned_s64 timestamp;
} scan;
int scale_pre_decml;
int scale_post_decml;
@@ -283,11 +283,11 @@ static struct platform_driver hid_temperature_platform_driver = {
.pm = &hid_sensor_pm_ops,
},
.probe = hid_temperature_probe,
- .remove_new = hid_temperature_remove,
+ .remove = hid_temperature_remove,
};
module_platform_driver(hid_temperature_platform_driver);
MODULE_DESCRIPTION("HID Environmental temperature sensor");
MODULE_AUTHOR("Song Hongyan <hongyan.song@intel.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/iio/temperature/mcp9600.c b/drivers/iio/temperature/mcp9600.c
index f1bb0976273d..c2447860adfd 100644
--- a/drivers/iio/temperature/mcp9600.c
+++ b/drivers/iio/temperature/mcp9600.c
@@ -200,7 +200,7 @@ static int mcp9600_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state)
+ bool state)
{
struct mcp9600_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
diff --git a/drivers/iio/temperature/tmp006.c b/drivers/iio/temperature/tmp006.c
index 6d8d661f0c82..0c844137d7aa 100644
--- a/drivers/iio/temperature/tmp006.c
+++ b/drivers/iio/temperature/tmp006.c
@@ -7,8 +7,6 @@
* Driver for the Texas Instruments I2C 16-bit IR thermopile sensor
*
* (7-bit I2C slave address 0x40, changeable via ADR pins)
- *
- * TODO: data ready irq
*/
#include <linux/err.h>
@@ -21,6 +19,9 @@
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
+#include <linux/iio/trigger.h>
+#include <linux/iio/triggered_buffer.h>
+#include <linux/iio/trigger_consumer.h>
#define TMP006_VOBJECT 0x00
#define TMP006_TAMBIENT 0x01
@@ -45,6 +46,7 @@
struct tmp006_data {
struct i2c_client *client;
u16 config;
+ struct iio_trigger *drdy_trig;
};
static int tmp006_read_measurement(struct tmp006_data *data, u8 reg)
@@ -83,15 +85,19 @@ static int tmp006_read_raw(struct iio_dev *indio_dev,
case IIO_CHAN_INFO_RAW:
if (channel->type == IIO_VOLTAGE) {
/* LSB is 156.25 nV */
- ret = tmp006_read_measurement(data, TMP006_VOBJECT);
- if (ret < 0)
- return ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ ret = tmp006_read_measurement(data, TMP006_VOBJECT);
+ if (ret < 0)
+ return ret;
+ }
*val = sign_extend32(ret, 15);
} else if (channel->type == IIO_TEMP) {
/* LSB is 0.03125 degrees Celsius */
- ret = tmp006_read_measurement(data, TMP006_TAMBIENT);
- if (ret < 0)
- return ret;
+ iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
+ ret = tmp006_read_measurement(data, TMP006_TAMBIENT);
+ if (ret < 0)
+ return ret;
+ }
*val = sign_extend32(ret, 15) >> TMP006_TAMBIENT_SHIFT;
} else {
break;
@@ -128,7 +134,7 @@ static int tmp006_write_raw(struct iio_dev *indio_dev,
long mask)
{
struct tmp006_data *data = iio_priv(indio_dev);
- int i;
+ int ret, i;
if (mask != IIO_CHAN_INFO_SAMP_FREQ)
return -EINVAL;
@@ -136,13 +142,19 @@ static int tmp006_write_raw(struct iio_dev *indio_dev,
for (i = 0; i < ARRAY_SIZE(tmp006_freqs); i++)
if ((val == tmp006_freqs[i][0]) &&
(val2 == tmp006_freqs[i][1])) {
+ ret = iio_device_claim_direct_mode(indio_dev);
+ if (ret)
+ return ret;
+
data->config &= ~TMP006_CONFIG_CR_MASK;
data->config |= i << TMP006_CONFIG_CR_SHIFT;
- return i2c_smbus_write_word_swapped(data->client,
- TMP006_CONFIG,
- data->config);
+ ret = i2c_smbus_write_word_swapped(data->client,
+ TMP006_CONFIG,
+ data->config);
+ iio_device_release_direct_mode(indio_dev);
+ return ret;
}
return -EINVAL;
}
@@ -164,13 +176,29 @@ static const struct iio_chan_spec tmp006_channels[] = {
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
+ .scan_index = 0,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 16,
+ .storagebits = 16,
+ .endianness = IIO_BE,
+ }
},
{
.type = IIO_TEMP,
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
BIT(IIO_CHAN_INFO_SCALE),
.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
- }
+ .scan_index = 1,
+ .scan_type = {
+ .sign = 's',
+ .realbits = 14,
+ .storagebits = 16,
+ .shift = TMP006_TAMBIENT_SHIFT,
+ .endianness = IIO_BE,
+ }
+ },
+ IIO_CHAN_SOFT_TIMESTAMP(2),
};
static const struct iio_info tmp006_info = {
@@ -213,6 +241,54 @@ static void tmp006_powerdown_cleanup(void *dev)
tmp006_power(dev, false);
}
+static irqreturn_t tmp006_trigger_handler(int irq, void *p)
+{
+ struct iio_poll_func *pf = p;
+ struct iio_dev *indio_dev = pf->indio_dev;
+ struct tmp006_data *data = iio_priv(indio_dev);
+ struct {
+ s16 channels[2];
+ s64 ts __aligned(8);
+ } scan;
+ s32 ret;
+
+ ret = i2c_smbus_read_word_data(data->client, TMP006_VOBJECT);
+ if (ret < 0)
+ goto err;
+ scan.channels[0] = ret;
+
+ ret = i2c_smbus_read_word_data(data->client, TMP006_TAMBIENT);
+ if (ret < 0)
+ goto err;
+ scan.channels[1] = ret;
+
+ iio_push_to_buffers_with_timestamp(indio_dev, &scan,
+ iio_get_time_ns(indio_dev));
+err:
+ iio_trigger_notify_done(indio_dev->trig);
+ return IRQ_HANDLED;
+}
+
+static int tmp006_set_trigger_state(struct iio_trigger *trig, bool state)
+{
+ struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
+ struct tmp006_data *data = iio_priv(indio_dev);
+
+ if (state)
+ data->config |= TMP006_CONFIG_DRDY_EN;
+ else
+ data->config &= ~TMP006_CONFIG_DRDY_EN;
+
+ return i2c_smbus_write_word_swapped(data->client, TMP006_CONFIG,
+ data->config);
+}
+
+static const struct iio_trigger_ops tmp006_trigger_ops = {
+ .set_trigger_state = tmp006_set_trigger_state,
+};
+
+static const unsigned long tmp006_scan_masks[] = { 0x3, 0 };
+
static int tmp006_probe(struct i2c_client *client)
{
struct iio_dev *indio_dev;
@@ -241,6 +317,7 @@ static int tmp006_probe(struct i2c_client *client)
indio_dev->channels = tmp006_channels;
indio_dev->num_channels = ARRAY_SIZE(tmp006_channels);
+ indio_dev->available_scan_masks = tmp006_scan_masks;
ret = i2c_smbus_read_word_swapped(data->client, TMP006_CONFIG);
if (ret < 0)
@@ -258,6 +335,37 @@ static int tmp006_probe(struct i2c_client *client)
if (ret < 0)
return ret;
+ if (client->irq > 0) {
+ data->drdy_trig = devm_iio_trigger_alloc(&client->dev,
+ "%s-dev%d",
+ indio_dev->name,
+ iio_device_id(indio_dev));
+ if (!data->drdy_trig)
+ return -ENOMEM;
+
+ data->drdy_trig->ops = &tmp006_trigger_ops;
+ iio_trigger_set_drvdata(data->drdy_trig, indio_dev);
+ ret = iio_trigger_register(data->drdy_trig);
+ if (ret)
+ return ret;
+
+ indio_dev->trig = iio_trigger_get(data->drdy_trig);
+
+ ret = devm_request_threaded_irq(&client->dev, client->irq,
+ iio_trigger_generic_data_rdy_poll,
+ NULL,
+ IRQF_ONESHOT,
+ "tmp006_irq",
+ data->drdy_trig);
+ if (ret < 0)
+ return ret;
+ }
+
+ ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev, NULL,
+ tmp006_trigger_handler, NULL);
+ if (ret < 0)
+ return ret;
+
return devm_iio_device_register(&client->dev, indio_dev);
}
diff --git a/drivers/iio/temperature/tmp007.c b/drivers/iio/temperature/tmp007.c
index 9bdfa9423492..fd4d389ce1df 100644
--- a/drivers/iio/temperature/tmp007.c
+++ b/drivers/iio/temperature/tmp007.c
@@ -216,7 +216,7 @@ static irqreturn_t tmp007_interrupt_handler(int irq, void *private)
static int tmp007_write_event_config(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan, enum iio_event_type type,
- enum iio_event_direction dir, int state)
+ enum iio_event_direction dir, bool state)
{
struct tmp007_data *data = iio_priv(indio_dev);
unsigned int status_mask;
diff --git a/drivers/iio/temperature/tsys01.c b/drivers/iio/temperature/tsys01.c
index 9213761c5d18..cfaa16f46a3f 100644
--- a/drivers/iio/temperature/tsys01.c
+++ b/drivers/iio/temperature/tsys01.c
@@ -232,4 +232,4 @@ MODULE_DESCRIPTION("Measurement-Specialties tsys01 temperature driver");
MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
MODULE_AUTHOR("Ludovic Tancerel <ludovic.tancerel@maplehightech.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_MEAS_SPEC_SENSORS);
+MODULE_IMPORT_NS("IIO_MEAS_SPEC_SENSORS");
diff --git a/drivers/iio/temperature/tsys02d.c b/drivers/iio/temperature/tsys02d.c
index 2b4959d6e467..ef34b3c58f26 100644
--- a/drivers/iio/temperature/tsys02d.c
+++ b/drivers/iio/temperature/tsys02d.c
@@ -187,4 +187,4 @@ MODULE_DESCRIPTION("Measurement-Specialties tsys02d temperature driver");
MODULE_AUTHOR("William Markezana <william.markezana@meas-spec.com>");
MODULE_AUTHOR("Ludovic Tancerel <ludovic.tancerel@maplehightech.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_MEAS_SPEC_SENSORS);
+MODULE_IMPORT_NS("IIO_MEAS_SPEC_SENSORS");
diff --git a/drivers/iio/test/iio-test-gts.c b/drivers/iio/test/iio-test-gts.c
index 5f16a7b5e6d4..1eceec9d477f 100644
--- a/drivers/iio/test/iio-test-gts.c
+++ b/drivers/iio/test/iio-test-gts.c
@@ -512,4 +512,4 @@ kunit_test_suite(iio_gts_test_suite);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Matti Vaittinen <mazziesaccount@gmail.com>");
MODULE_DESCRIPTION("Test IIO light sensor gain-time-scale helpers");
-MODULE_IMPORT_NS(IIO_GTS_HELPER);
+MODULE_IMPORT_NS("IIO_GTS_HELPER");
diff --git a/drivers/iio/test/iio-test-rescale.c b/drivers/iio/test/iio-test-rescale.c
index 31ee55a6faed..cbf13337ed1f 100644
--- a/drivers/iio/test/iio-test-rescale.c
+++ b/drivers/iio/test/iio-test-rescale.c
@@ -712,4 +712,4 @@ kunit_test_suite(iio_rescale_test_suite);
MODULE_AUTHOR("Liam Beguin <liambeguin@gmail.com>");
MODULE_DESCRIPTION("Test IIO rescale conversion functions");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(IIO_RESCALE);
+MODULE_IMPORT_NS("IIO_RESCALE");
diff --git a/drivers/iio/trigger/iio-trig-interrupt.c b/drivers/iio/trigger/iio-trig-interrupt.c
index dec256bfbd73..21c6b6292a72 100644
--- a/drivers/iio/trigger/iio-trig-interrupt.c
+++ b/drivers/iio/trigger/iio-trig-interrupt.c
@@ -96,7 +96,7 @@ static void iio_interrupt_trigger_remove(struct platform_device *pdev)
static struct platform_driver iio_interrupt_trigger_driver = {
.probe = iio_interrupt_trigger_probe,
- .remove_new = iio_interrupt_trigger_remove,
+ .remove = iio_interrupt_trigger_remove,
.driver = {
.name = "iio_interrupt_trigger",
},
diff --git a/drivers/iio/trigger/stm32-timer-trigger.c b/drivers/iio/trigger/stm32-timer-trigger.c
index 0684329956d9..bb60b2d7b2ec 100644
--- a/drivers/iio/trigger/stm32-timer-trigger.c
+++ b/drivers/iio/trigger/stm32-timer-trigger.c
@@ -900,7 +900,7 @@ MODULE_DEVICE_TABLE(of, stm32_trig_of_match);
static struct platform_driver stm32_timer_trigger_driver = {
.probe = stm32_timer_trigger_probe,
- .remove_new = stm32_timer_trigger_remove,
+ .remove = stm32_timer_trigger_remove,
.driver = {
.name = "stm32-timer-trigger",
.of_match_table = stm32_trig_of_match,
diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
index 64ace0b968f0..91db10515d74 100644
--- a/drivers/infiniband/core/cma.c
+++ b/drivers/infiniband/core/cma.c
@@ -690,6 +690,7 @@ cma_validate_port(struct ib_device *device, u32 port,
int bound_if_index = dev_addr->bound_dev_if;
int dev_type = dev_addr->dev_type;
struct net_device *ndev = NULL;
+ struct net_device *pdev = NULL;
if (!rdma_dev_access_netns(device, id_priv->id.route.addr.dev_addr.net))
goto out;
@@ -714,6 +715,21 @@ cma_validate_port(struct ib_device *device, u32 port,
rcu_read_lock();
ndev = rcu_dereference(sgid_attr->ndev);
+ if (ndev->ifindex != bound_if_index) {
+ pdev = dev_get_by_index_rcu(dev_addr->net, bound_if_index);
+ if (pdev) {
+ if (is_vlan_dev(pdev)) {
+ pdev = vlan_dev_real_dev(pdev);
+ if (ndev->ifindex == pdev->ifindex)
+ bound_if_index = pdev->ifindex;
+ }
+ if (is_vlan_dev(ndev)) {
+ pdev = vlan_dev_real_dev(ndev);
+ if (bound_if_index == pdev->ifindex)
+ bound_if_index = ndev->ifindex;
+ }
+ }
+ }
if (!net_eq(dev_net(ndev), dev_addr->net) ||
ndev->ifindex != bound_if_index) {
rdma_put_gid_attr(sgid_attr);
diff --git a/drivers/infiniband/core/nldev.c b/drivers/infiniband/core/nldev.c
index ff121e59b9c0..cb987ab0177c 100644
--- a/drivers/infiniband/core/nldev.c
+++ b/drivers/infiniband/core/nldev.c
@@ -2833,8 +2833,8 @@ int rdma_nl_notify_event(struct ib_device *device, u32 port_num,
enum rdma_nl_notify_event_type type)
{
struct sk_buff *skb;
+ int ret = -EMSGSIZE;
struct net *net;
- int ret = 0;
void *nlh;
net = read_pnet(&device->coredev.rdma_net);
diff --git a/drivers/infiniband/core/umem_dmabuf.c b/drivers/infiniband/core/umem_dmabuf.c
index 9fcd37761264..0ec2e4120cc9 100644
--- a/drivers/infiniband/core/umem_dmabuf.c
+++ b/drivers/infiniband/core/umem_dmabuf.c
@@ -10,7 +10,7 @@
#include "uverbs.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
int ib_umem_dmabuf_map_pages(struct ib_umem_dmabuf *umem_dmabuf)
{
diff --git a/drivers/infiniband/core/uverbs_cmd.c b/drivers/infiniband/core/uverbs_cmd.c
index 66b02fbf077a..5ad14c39d48c 100644
--- a/drivers/infiniband/core/uverbs_cmd.c
+++ b/drivers/infiniband/core/uverbs_cmd.c
@@ -161,7 +161,7 @@ static const void __user *uverbs_request_next_ptr(struct uverbs_req_iter *iter,
{
const void __user *res = iter->cur;
- if (iter->cur + len > iter->end)
+ if (len > iter->end - iter->cur)
return (void __force __user *)ERR_PTR(-ENOSPC);
iter->cur += len;
return res;
@@ -2008,11 +2008,13 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
ret = uverbs_request_start(attrs, &iter, &cmd, sizeof(cmd));
if (ret)
return ret;
- wqes = uverbs_request_next_ptr(&iter, cmd.wqe_size * cmd.wr_count);
+ wqes = uverbs_request_next_ptr(&iter, size_mul(cmd.wqe_size,
+ cmd.wr_count));
if (IS_ERR(wqes))
return PTR_ERR(wqes);
- sgls = uverbs_request_next_ptr(
- &iter, cmd.sge_count * sizeof(struct ib_uverbs_sge));
+ sgls = uverbs_request_next_ptr(&iter,
+ size_mul(cmd.sge_count,
+ sizeof(struct ib_uverbs_sge)));
if (IS_ERR(sgls))
return PTR_ERR(sgls);
ret = uverbs_request_finish(&iter);
@@ -2198,11 +2200,11 @@ ib_uverbs_unmarshall_recv(struct uverbs_req_iter *iter, u32 wr_count,
if (wqe_size < sizeof(struct ib_uverbs_recv_wr))
return ERR_PTR(-EINVAL);
- wqes = uverbs_request_next_ptr(iter, wqe_size * wr_count);
+ wqes = uverbs_request_next_ptr(iter, size_mul(wqe_size, wr_count));
if (IS_ERR(wqes))
return ERR_CAST(wqes);
- sgls = uverbs_request_next_ptr(
- iter, sge_count * sizeof(struct ib_uverbs_sge));
+ sgls = uverbs_request_next_ptr(iter, size_mul(sge_count,
+ sizeof(struct ib_uverbs_sge)));
if (IS_ERR(sgls))
return ERR_CAST(sgls);
ret = uverbs_request_finish(iter);
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
index 82023394e330..e3d26bd6de05 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c
@@ -199,7 +199,7 @@ int bnxt_re_query_device(struct ib_device *ibdev,
ib_attr->vendor_id = rdev->en_dev->pdev->vendor;
ib_attr->vendor_part_id = rdev->en_dev->pdev->device;
- ib_attr->hw_ver = rdev->en_dev->pdev->subsystem_device;
+ ib_attr->hw_ver = rdev->en_dev->pdev->revision;
ib_attr->max_qp = dev_attr->max_qp;
ib_attr->max_qp_wr = dev_attr->max_qp_wqes;
ib_attr->device_cap_flags =
@@ -967,13 +967,13 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
unsigned int flags;
int rc;
+ bnxt_re_debug_rem_qpinfo(rdev, qp);
+
bnxt_qplib_flush_cqn_wq(&qp->qplib_qp);
rc = bnxt_qplib_destroy_qp(&rdev->qplib_res, &qp->qplib_qp);
- if (rc) {
+ if (rc)
ibdev_err(&rdev->ibdev, "Failed to destroy HW QP");
- return rc;
- }
if (rdma_is_kernel_res(&qp->ib_qp.res)) {
flags = bnxt_re_lock_cqs(qp);
@@ -983,11 +983,8 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
bnxt_qplib_free_qp_res(&rdev->qplib_res, &qp->qplib_qp);
- if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp) {
- rc = bnxt_re_destroy_gsi_sqp(qp);
- if (rc)
- return rc;
- }
+ if (ib_qp->qp_type == IB_QPT_GSI && rdev->gsi_ctx.gsi_sqp)
+ bnxt_re_destroy_gsi_sqp(qp);
mutex_lock(&rdev->qp_lock);
list_del(&qp->list);
@@ -998,8 +995,6 @@ int bnxt_re_destroy_qp(struct ib_qp *ib_qp, struct ib_udata *udata)
else if (qp->qplib_qp.type == CMDQ_CREATE_QP_TYPE_UD)
atomic_dec(&rdev->stats.res.ud_qp_count);
- bnxt_re_debug_rem_qpinfo(rdev, qp);
-
ib_umem_release(qp->rumem);
ib_umem_release(qp->sumem);
@@ -2167,18 +2162,20 @@ int bnxt_re_modify_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
}
}
- if (qp_attr_mask & IB_QP_PATH_MTU) {
- qp->qplib_qp.modify_flags |=
- CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
- qp->qplib_qp.path_mtu = __from_ib_mtu(qp_attr->path_mtu);
- qp->qplib_qp.mtu = ib_mtu_enum_to_int(qp_attr->path_mtu);
- } else if (qp_attr->qp_state == IB_QPS_RTR) {
- qp->qplib_qp.modify_flags |=
- CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
- qp->qplib_qp.path_mtu =
- __from_ib_mtu(iboe_get_mtu(rdev->netdev->mtu));
- qp->qplib_qp.mtu =
- ib_mtu_enum_to_int(iboe_get_mtu(rdev->netdev->mtu));
+ if (qp_attr->qp_state == IB_QPS_RTR) {
+ enum ib_mtu qpmtu;
+
+ qpmtu = iboe_get_mtu(rdev->netdev->mtu);
+ if (qp_attr_mask & IB_QP_PATH_MTU) {
+ if (ib_mtu_enum_to_int(qp_attr->path_mtu) >
+ ib_mtu_enum_to_int(qpmtu))
+ return -EINVAL;
+ qpmtu = qp_attr->path_mtu;
+ }
+
+ qp->qplib_qp.modify_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PATH_MTU;
+ qp->qplib_qp.path_mtu = __from_ib_mtu(qpmtu);
+ qp->qplib_qp.mtu = ib_mtu_enum_to_int(qpmtu);
}
if (qp_attr_mask & IB_QP_TIMEOUT) {
@@ -2328,6 +2325,7 @@ int bnxt_re_query_qp(struct ib_qp *ib_qp, struct ib_qp_attr *qp_attr,
qp_attr->retry_cnt = qplib_qp->retry_cnt;
qp_attr->rnr_retry = qplib_qp->rnr_retry;
qp_attr->min_rnr_timer = qplib_qp->min_rnr_timer;
+ qp_attr->port_num = __to_ib_port_num(qplib_qp->port_id);
qp_attr->rq_psn = qplib_qp->rq.psn;
qp_attr->max_rd_atomic = qplib_qp->max_rd_atomic;
qp_attr->sq_psn = qplib_qp->sq.psn;
@@ -2824,7 +2822,8 @@ bad:
wr = wr->next;
}
bnxt_qplib_post_send_db(&qp->qplib_qp);
- bnxt_ud_qp_hw_stall_workaround(qp);
+ if (!bnxt_qplib_is_chip_gen_p5_p7(qp->rdev->chip_ctx))
+ bnxt_ud_qp_hw_stall_workaround(qp);
spin_unlock_irqrestore(&qp->sq_lock, flags);
return rc;
}
@@ -2936,7 +2935,8 @@ bad:
wr = wr->next;
}
bnxt_qplib_post_send_db(&qp->qplib_qp);
- bnxt_ud_qp_hw_stall_workaround(qp);
+ if (!bnxt_qplib_is_chip_gen_p5_p7(qp->rdev->chip_ctx))
+ bnxt_ud_qp_hw_stall_workaround(qp);
spin_unlock_irqrestore(&qp->sq_lock, flags);
return rc;
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index ac59f1d73b15..fbb16a411d6a 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -268,6 +268,10 @@ void bnxt_re_dealloc_ucontext(struct ib_ucontext *context);
int bnxt_re_mmap(struct ib_ucontext *context, struct vm_area_struct *vma);
void bnxt_re_mmap_free(struct rdma_user_mmap_entry *rdma_entry);
+static inline u32 __to_ib_port_num(u16 port_id)
+{
+ return (u32)port_id + 1;
+}
unsigned long bnxt_re_lock_cqs(struct bnxt_re_qp *qp);
void bnxt_re_unlock_cqs(struct bnxt_re_qp *qp, unsigned long flags);
diff --git a/drivers/infiniband/hw/bnxt_re/main.c b/drivers/infiniband/hw/bnxt_re/main.c
index b7af0d5ff3b6..c143f273b759 100644
--- a/drivers/infiniband/hw/bnxt_re/main.c
+++ b/drivers/infiniband/hw/bnxt_re/main.c
@@ -1715,11 +1715,8 @@ static bool bnxt_re_is_qp1_or_shadow_qp(struct bnxt_re_dev *rdev,
static void bnxt_re_dev_stop(struct bnxt_re_dev *rdev)
{
- int mask = IB_QP_STATE;
- struct ib_qp_attr qp_attr;
struct bnxt_re_qp *qp;
- qp_attr.qp_state = IB_QPS_ERR;
mutex_lock(&rdev->qp_lock);
list_for_each_entry(qp, &rdev->qp_list, list) {
/* Modify the state of all QPs except QP1/Shadow QP */
@@ -1727,12 +1724,9 @@ static void bnxt_re_dev_stop(struct bnxt_re_dev *rdev)
if (qp->qplib_qp.state !=
CMDQ_MODIFY_QP_NEW_STATE_RESET &&
qp->qplib_qp.state !=
- CMDQ_MODIFY_QP_NEW_STATE_ERR) {
+ CMDQ_MODIFY_QP_NEW_STATE_ERR)
bnxt_re_dispatch_event(&rdev->ibdev, &qp->ib_qp,
1, IB_EVENT_QP_FATAL);
- bnxt_re_modify_qp(&qp->ib_qp, &qp_attr, mask,
- NULL);
- }
}
}
mutex_unlock(&rdev->qp_lock);
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.c b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
index e42abf5be6c0..5336f74297f8 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.c
@@ -659,13 +659,6 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res,
rc = bnxt_qplib_alloc_init_hwq(&srq->hwq, &hwq_attr);
if (rc)
return rc;
-
- srq->swq = kcalloc(srq->hwq.max_elements, sizeof(*srq->swq),
- GFP_KERNEL);
- if (!srq->swq) {
- rc = -ENOMEM;
- goto fail;
- }
srq->dbinfo.flags = 0;
bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
CMDQ_BASE_OPCODE_CREATE_SRQ,
@@ -694,9 +687,17 @@ int bnxt_qplib_create_srq(struct bnxt_qplib_res *res,
spin_lock_init(&srq->lock);
srq->start_idx = 0;
srq->last_idx = srq->hwq.max_elements - 1;
- for (idx = 0; idx < srq->hwq.max_elements; idx++)
- srq->swq[idx].next_idx = idx + 1;
- srq->swq[srq->last_idx].next_idx = -1;
+ if (!srq->hwq.is_user) {
+ srq->swq = kcalloc(srq->hwq.max_elements, sizeof(*srq->swq),
+ GFP_KERNEL);
+ if (!srq->swq) {
+ rc = -ENOMEM;
+ goto fail;
+ }
+ for (idx = 0; idx < srq->hwq.max_elements; idx++)
+ srq->swq[idx].next_idx = idx + 1;
+ srq->swq[srq->last_idx].next_idx = -1;
+ }
srq->id = le32_to_cpu(resp.xid);
srq->dbinfo.hwq = &srq->hwq;
@@ -1000,9 +1001,7 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
u32 tbl_indx;
u16 nsge;
- if (res->dattr)
- qp->is_host_msn_tbl = _is_host_msn_table(res->dattr->dev_cap_flags2);
-
+ qp->is_host_msn_tbl = _is_host_msn_table(res->dattr->dev_cap_flags2);
sq->dbinfo.flags = 0;
bnxt_qplib_rcfw_cmd_prep((struct cmdq_base *)&req,
CMDQ_BASE_OPCODE_CREATE_QP,
@@ -1034,7 +1033,12 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
: 0;
/* Update msn tbl size */
if (qp->is_host_msn_tbl && psn_sz) {
- hwq_attr.aux_depth = roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode));
+ if (qp->wqe_mode == BNXT_QPLIB_WQE_MODE_STATIC)
+ hwq_attr.aux_depth =
+ roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode));
+ else
+ hwq_attr.aux_depth =
+ roundup_pow_of_two(bnxt_qplib_set_sq_size(sq, qp->wqe_mode)) / 2;
qp->msn_tbl_sz = hwq_attr.aux_depth;
qp->msn = 0;
}
@@ -1044,13 +1048,14 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
if (rc)
return rc;
- rc = bnxt_qplib_alloc_init_swq(sq);
- if (rc)
- goto fail_sq;
-
- if (psn_sz)
- bnxt_qplib_init_psn_ptr(qp, psn_sz);
+ if (!sq->hwq.is_user) {
+ rc = bnxt_qplib_alloc_init_swq(sq);
+ if (rc)
+ goto fail_sq;
+ if (psn_sz)
+ bnxt_qplib_init_psn_ptr(qp, psn_sz);
+ }
req.sq_size = cpu_to_le32(bnxt_qplib_set_sq_size(sq, qp->wqe_mode));
pbl = &sq->hwq.pbl[PBL_LVL_0];
req.sq_pbl = cpu_to_le64(pbl->pg_map_arr[0]);
@@ -1076,9 +1081,11 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
rc = bnxt_qplib_alloc_init_hwq(&rq->hwq, &hwq_attr);
if (rc)
goto sq_swq;
- rc = bnxt_qplib_alloc_init_swq(rq);
- if (rc)
- goto fail_rq;
+ if (!rq->hwq.is_user) {
+ rc = bnxt_qplib_alloc_init_swq(rq);
+ if (rc)
+ goto fail_rq;
+ }
req.rq_size = cpu_to_le32(rq->max_wqe);
pbl = &rq->hwq.pbl[PBL_LVL_0];
@@ -1174,9 +1181,11 @@ int bnxt_qplib_create_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
rq->dbinfo.db = qp->dpi->dbr;
rq->dbinfo.max_slot = bnxt_qplib_set_rq_max_slot(rq->wqe_size);
}
+ spin_lock_bh(&rcfw->tbl_lock);
tbl_indx = map_qp_id_to_tbl_indx(qp->id, rcfw);
rcfw->qp_tbl[tbl_indx].qp_id = qp->id;
rcfw->qp_tbl[tbl_indx].qp_handle = (void *)qp;
+ spin_unlock_bh(&rcfw->tbl_lock);
return 0;
fail:
@@ -1283,7 +1292,8 @@ static void __filter_modify_flags(struct bnxt_qplib_qp *qp)
}
}
-static void bnxt_set_mandatory_attributes(struct bnxt_qplib_qp *qp,
+static void bnxt_set_mandatory_attributes(struct bnxt_qplib_res *res,
+ struct bnxt_qplib_qp *qp,
struct cmdq_modify_qp *req)
{
u32 mandatory_flags = 0;
@@ -1298,6 +1308,14 @@ static void bnxt_set_mandatory_attributes(struct bnxt_qplib_qp *qp,
mandatory_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_PKEY;
}
+ if (_is_min_rnr_in_rtr_rts_mandatory(res->dattr->dev_cap_flags2) &&
+ (qp->cur_qp_state == CMDQ_MODIFY_QP_NEW_STATE_RTR &&
+ qp->state == CMDQ_MODIFY_QP_NEW_STATE_RTS)) {
+ if (qp->type == CMDQ_MODIFY_QP_QP_TYPE_RC)
+ mandatory_flags |=
+ CMDQ_MODIFY_QP_MODIFY_MASK_MIN_RNR_TIMER;
+ }
+
if (qp->type == CMDQ_MODIFY_QP_QP_TYPE_UD ||
qp->type == CMDQ_MODIFY_QP_QP_TYPE_GSI)
mandatory_flags |= CMDQ_MODIFY_QP_MODIFY_MASK_QKEY;
@@ -1338,7 +1356,7 @@ int bnxt_qplib_modify_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
/* Set mandatory attributes for INIT -> RTR and RTR -> RTS transition */
if (_is_optimize_modify_qp_supported(res->dattr->dev_cap_flags2) &&
is_optimized_state_transition(qp))
- bnxt_set_mandatory_attributes(qp, &req);
+ bnxt_set_mandatory_attributes(res, qp, &req);
}
bmask = qp->modify_flags;
req.modify_mask = cpu_to_le32(qp->modify_flags);
@@ -1521,6 +1539,7 @@ int bnxt_qplib_query_qp(struct bnxt_qplib_res *res, struct bnxt_qplib_qp *qp)
qp->dest_qpn = le32_to_cpu(sb->dest_qp_id);
memcpy(qp->smac, sb->src_mac, 6);
qp->vlan_id = le16_to_cpu(sb->vlan_pcp_vlan_dei_vlan_id);
+ qp->port_id = le16_to_cpu(sb->port_id);
bail:
dma_free_coherent(&rcfw->pdev->dev, sbuf.size,
sbuf.sb, sbuf.dma_addr);
@@ -2667,10 +2686,12 @@ static int bnxt_qplib_cq_process_req(struct bnxt_qplib_cq *cq,
bnxt_qplib_add_flush_qp(qp);
} else {
/* Before we complete, do WA 9060 */
- if (do_wa9060(qp, cq, cq_cons, sq->swq_last,
- cqe_sq_cons)) {
- *lib_qp = qp;
- goto out;
+ if (!bnxt_qplib_is_chip_gen_p5_p7(qp->cctx)) {
+ if (do_wa9060(qp, cq, cq_cons, sq->swq_last,
+ cqe_sq_cons)) {
+ *lib_qp = qp;
+ goto out;
+ }
}
if (swq->flags & SQ_SEND_FLAGS_SIGNAL_COMP) {
cqe->status = CQ_REQ_STATUS_OK;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_fp.h b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
index ef3424c81345..0660101b5310 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_fp.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_fp.h
@@ -114,7 +114,6 @@ struct bnxt_qplib_sge {
u32 size;
};
-#define BNXT_QPLIB_QP_MAX_SGL 6
struct bnxt_qplib_swq {
u64 wr_id;
int next_idx;
@@ -154,7 +153,7 @@ struct bnxt_qplib_swqe {
#define BNXT_QPLIB_SWQE_FLAGS_UC_FENCE BIT(2)
#define BNXT_QPLIB_SWQE_FLAGS_SOLICIT_EVENT BIT(3)
#define BNXT_QPLIB_SWQE_FLAGS_INLINE BIT(4)
- struct bnxt_qplib_sge sg_list[BNXT_QPLIB_QP_MAX_SGL];
+ struct bnxt_qplib_sge sg_list[BNXT_VAR_MAX_SGE];
int num_sge;
/* Max inline data is 96 bytes */
u32 inline_len;
@@ -299,6 +298,7 @@ struct bnxt_qplib_qp {
u32 dest_qpn;
u8 smac[6];
u16 vlan_id;
+ u16 port_id;
u8 nw_type;
struct bnxt_qplib_ah ah;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
index 5e90ea232de8..17e62f22683b 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_rcfw.c
@@ -424,7 +424,8 @@ static int __send_message_basic_sanity(struct bnxt_qplib_rcfw *rcfw,
/* Prevent posting if f/w is not in a state to process */
if (test_bit(ERR_DEVICE_DETACHED, &rcfw->cmdq.flags))
- return bnxt_qplib_map_rc(opcode);
+ return -ENXIO;
+
if (test_bit(FIRMWARE_STALL_DETECTED, &cmdq->flags))
return -ETIMEDOUT;
@@ -493,7 +494,7 @@ static int __bnxt_qplib_rcfw_send_message(struct bnxt_qplib_rcfw *rcfw,
rc = __send_message_basic_sanity(rcfw, msg, opcode);
if (rc)
- return rc;
+ return rc == -ENXIO ? bnxt_qplib_map_rc(opcode) : rc;
rc = __send_message(rcfw, msg, opcode);
if (rc)
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h
index 21fb148713a6..cbfc49a1a56d 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h
@@ -584,6 +584,11 @@ static inline bool _is_optimize_modify_qp_supported(u16 dev_cap_ext_flags2)
return dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_OPTIMIZE_MODIFY_QP_SUPPORTED;
}
+static inline bool _is_min_rnr_in_rtr_rts_mandatory(u16 dev_cap_ext_flags2)
+{
+ return !!(dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_MIN_RNR_RTR_RTS_OPT_SUPPORTED);
+}
+
static inline bool _is_cq_coalescing_supported(u16 dev_cap_ext_flags2)
{
return dev_cap_ext_flags2 & CREQ_QUERY_FUNC_RESP_SB_CQ_COALESCING_SUPPORTED;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
index 7e20ae3d2c4f..9df3e3271577 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c
@@ -129,12 +129,18 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw,
attr->max_qp_init_rd_atom =
sb->max_qp_init_rd_atom > BNXT_QPLIB_MAX_OUT_RD_ATOM ?
BNXT_QPLIB_MAX_OUT_RD_ATOM : sb->max_qp_init_rd_atom;
- attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr);
- /*
- * 128 WQEs needs to be reserved for the HW (8916). Prevent
- * reporting the max number
- */
- attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1;
+ attr->max_qp_wqes = le16_to_cpu(sb->max_qp_wr) - 1;
+ if (!bnxt_qplib_is_chip_gen_p5_p7(rcfw->res->cctx)) {
+ /*
+ * 128 WQEs needs to be reserved for the HW (8916). Prevent
+ * reporting the max number on legacy devices
+ */
+ attr->max_qp_wqes -= BNXT_QPLIB_RESERVED_QP_WRS + 1;
+ }
+
+ /* Adjust for max_qp_wqes for variable wqe */
+ if (cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE)
+ attr->max_qp_wqes = BNXT_VAR_MAX_WQE - 1;
attr->max_qp_sges = cctx->modes.wqe_mode == BNXT_QPLIB_WQE_MODE_VARIABLE ?
min_t(u32, sb->max_sge_var_wqe, BNXT_VAR_MAX_SGE) : 6;
diff --git a/drivers/infiniband/hw/bnxt_re/roce_hsi.h b/drivers/infiniband/hw/bnxt_re/roce_hsi.h
index a98fc9c2313e..0ee60fdc18b3 100644
--- a/drivers/infiniband/hw/bnxt_re/roce_hsi.h
+++ b/drivers/infiniband/hw/bnxt_re/roce_hsi.h
@@ -2215,6 +2215,7 @@ struct creq_query_func_resp_sb {
#define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_IQM_MSN_TABLE (0x2UL << 4)
#define CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_LAST \
CREQ_QUERY_FUNC_RESP_SB_REQ_RETRANSMISSION_SUPPORT_IQM_MSN_TABLE
+ #define CREQ_QUERY_FUNC_RESP_SB_MIN_RNR_RTR_RTS_OPT_SUPPORTED 0x1000UL
__le16 max_xp_qp_size;
__le16 create_qp_batch_size;
__le16 destroy_qp_batch_size;
diff --git a/drivers/infiniband/hw/hns/hns_roce_hem.c b/drivers/infiniband/hw/hns/hns_roce_hem.c
index f84521be3bea..605562122ecc 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hem.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hem.c
@@ -931,6 +931,7 @@ struct hns_roce_hem_item {
size_t count; /* max ba numbers */
int start; /* start buf offset in this hem */
int end; /* end buf offset in this hem */
+ bool exist_bt;
};
/* All HEM items are linked in a tree structure */
@@ -959,6 +960,7 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count,
}
}
+ hem->exist_bt = exist_bt;
hem->count = count;
hem->start = start;
hem->end = end;
@@ -969,22 +971,22 @@ hem_list_alloc_item(struct hns_roce_dev *hr_dev, int start, int end, int count,
}
static void hem_list_free_item(struct hns_roce_dev *hr_dev,
- struct hns_roce_hem_item *hem, bool exist_bt)
+ struct hns_roce_hem_item *hem)
{
- if (exist_bt)
+ if (hem->exist_bt)
dma_free_coherent(hr_dev->dev, hem->count * BA_BYTE_LEN,
hem->addr, hem->dma_addr);
kfree(hem);
}
static void hem_list_free_all(struct hns_roce_dev *hr_dev,
- struct list_head *head, bool exist_bt)
+ struct list_head *head)
{
struct hns_roce_hem_item *hem, *temp_hem;
list_for_each_entry_safe(hem, temp_hem, head, list) {
list_del(&hem->list);
- hem_list_free_item(hr_dev, hem, exist_bt);
+ hem_list_free_item(hr_dev, hem);
}
}
@@ -1084,6 +1086,10 @@ int hns_roce_hem_list_calc_root_ba(const struct hns_roce_buf_region *regions,
for (i = 0; i < region_cnt; i++) {
r = (struct hns_roce_buf_region *)&regions[i];
+ /* when r->hopnum = 0, the region should not occupy root_ba. */
+ if (!r->hopnum)
+ continue;
+
if (r->hopnum > 1) {
step = hem_list_calc_ba_range(r->hopnum, 1, unit);
if (step > 0)
@@ -1177,7 +1183,7 @@ static int hem_list_alloc_mid_bt(struct hns_roce_dev *hr_dev,
err_exit:
for (level = 1; level < hopnum; level++)
- hem_list_free_all(hr_dev, &temp_list[level], true);
+ hem_list_free_all(hr_dev, &temp_list[level]);
return ret;
}
@@ -1218,16 +1224,26 @@ static int alloc_fake_root_bt(struct hns_roce_dev *hr_dev, void *cpu_base,
{
struct hns_roce_hem_item *hem;
+ /* This is on the has_mtt branch, if r->hopnum
+ * is 0, there is no root_ba to reuse for the
+ * region's fake hem, so a dma_alloc request is
+ * necessary here.
+ */
hem = hem_list_alloc_item(hr_dev, r->offset, r->offset + r->count - 1,
- r->count, false);
+ r->count, !r->hopnum);
if (!hem)
return -ENOMEM;
- hem_list_assign_bt(hem, cpu_base, phy_base);
+ /* The root_ba can be reused only when r->hopnum > 0. */
+ if (r->hopnum)
+ hem_list_assign_bt(hem, cpu_base, phy_base);
list_add(&hem->list, branch_head);
list_add(&hem->sibling, leaf_head);
- return r->count;
+ /* If r->hopnum == 0, 0 is returned,
+ * so that the root_bt entry is not occupied.
+ */
+ return r->hopnum ? r->count : 0;
}
static int setup_middle_bt(struct hns_roce_dev *hr_dev, void *cpu_base,
@@ -1271,7 +1287,7 @@ setup_root_hem(struct hns_roce_dev *hr_dev, struct hns_roce_hem_list *hem_list,
return -ENOMEM;
total = 0;
- for (i = 0; i < region_cnt && total < max_ba_num; i++) {
+ for (i = 0; i < region_cnt && total <= max_ba_num; i++) {
r = &regions[i];
if (!r->count)
continue;
@@ -1337,9 +1353,9 @@ static int hem_list_alloc_root_bt(struct hns_roce_dev *hr_dev,
region_cnt);
if (ret) {
for (i = 0; i < region_cnt; i++)
- hem_list_free_all(hr_dev, &head.branch[i], false);
+ hem_list_free_all(hr_dev, &head.branch[i]);
- hem_list_free_all(hr_dev, &head.root, true);
+ hem_list_free_all(hr_dev, &head.root);
}
return ret;
@@ -1402,10 +1418,9 @@ void hns_roce_hem_list_release(struct hns_roce_dev *hr_dev,
for (i = 0; i < HNS_ROCE_MAX_BT_REGION; i++)
for (j = 0; j < HNS_ROCE_MAX_BT_LEVEL; j++)
- hem_list_free_all(hr_dev, &hem_list->mid_bt[i][j],
- j != 0);
+ hem_list_free_all(hr_dev, &hem_list->mid_bt[i][j]);
- hem_list_free_all(hr_dev, &hem_list->root_bt, true);
+ hem_list_free_all(hr_dev, &hem_list->root_bt);
INIT_LIST_HEAD(&hem_list->btm_bt);
hem_list->root_ba = 0;
}
diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
index 697b17cca02e..0144e7210d05 100644
--- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
+++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c
@@ -468,7 +468,7 @@ static inline int set_ud_wqe(struct hns_roce_qp *qp,
valid_num_sge = calc_wr_sge_num(wr, &msg_len);
ret = set_ud_opcode(ud_sq_wqe, wr);
- if (WARN_ON(ret))
+ if (WARN_ON_ONCE(ret))
return ret;
ud_sq_wqe->msg_len = cpu_to_le32(msg_len);
@@ -572,7 +572,7 @@ static inline int set_rc_wqe(struct hns_roce_qp *qp,
rc_sq_wqe->msg_len = cpu_to_le32(msg_len);
ret = set_rc_opcode(hr_dev, rc_sq_wqe, wr);
- if (WARN_ON(ret))
+ if (WARN_ON_ONCE(ret))
return ret;
hr_reg_write(rc_sq_wqe, RC_SEND_WQE_SO,
@@ -670,6 +670,10 @@ static void write_dwqe(struct hns_roce_dev *hr_dev, struct hns_roce_qp *qp,
#define HNS_ROCE_SL_SHIFT 2
struct hns_roce_v2_rc_send_wqe *rc_sq_wqe = wqe;
+ if (unlikely(qp->state == IB_QPS_ERR)) {
+ flush_cqe(hr_dev, qp);
+ return;
+ }
/* All kinds of DirectWQE have the same header field layout */
hr_reg_enable(rc_sq_wqe, RC_SEND_WQE_FLAG);
hr_reg_write(rc_sq_wqe, RC_SEND_WQE_DB_SL_L, qp->sl);
@@ -5619,6 +5623,9 @@ static void put_dip_ctx_idx(struct hns_roce_dev *hr_dev,
{
struct hns_roce_dip *hr_dip = hr_qp->dip;
+ if (!hr_dip)
+ return;
+
xa_lock(&hr_dev->qp_table.dip_xa);
hr_dip->qp_cnt--;
diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c
index bf30b3a65a9b..55b9283bfc6f 100644
--- a/drivers/infiniband/hw/hns/hns_roce_mr.c
+++ b/drivers/infiniband/hw/hns/hns_roce_mr.c
@@ -814,11 +814,6 @@ int hns_roce_mtr_map(struct hns_roce_dev *hr_dev, struct hns_roce_mtr *mtr,
for (i = 0, mapped_cnt = 0; i < mtr->hem_cfg.region_count &&
mapped_cnt < page_cnt; i++) {
r = &mtr->hem_cfg.region[i];
- /* if hopnum is 0, no need to map pages in this region */
- if (!r->hopnum) {
- mapped_cnt += r->count;
- continue;
- }
if (r->offset + r->count > page_cnt) {
ret = -EINVAL;
diff --git a/drivers/infiniband/hw/mana/device.c b/drivers/infiniband/hw/mana/device.c
index 7ac01918ef7c..3416a85f8738 100644
--- a/drivers/infiniband/hw/mana/device.c
+++ b/drivers/infiniband/hw/mana/device.c
@@ -9,7 +9,7 @@
MODULE_DESCRIPTION("Microsoft Azure Network Adapter IB driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(NET_MANA);
+MODULE_IMPORT_NS("NET_MANA");
static const struct ib_device_ops mana_ib_dev_ops = {
.owner = THIS_MODULE,
diff --git a/drivers/infiniband/hw/mlx5/fs.c b/drivers/infiniband/hw/mlx5/fs.c
index 520034acf73a..162814ae8cb4 100644
--- a/drivers/infiniband/hw/mlx5/fs.c
+++ b/drivers/infiniband/hw/mlx5/fs.c
@@ -943,7 +943,7 @@ int mlx5_ib_fs_add_op_fc(struct mlx5_ib_dev *dev, u32 port_num,
}
dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dst.counter_id = mlx5_fc_id(opfc->fc);
+ dst.counter = opfc->fc;
flow_act.action =
MLX5_FLOW_CONTEXT_ACTION_COUNT | MLX5_FLOW_CONTEXT_ACTION_ALLOW;
@@ -1113,8 +1113,8 @@ static struct mlx5_ib_flow_handler *_create_flow_rule(struct mlx5_ib_dev *dev,
handler->ibcounters = flow_act.counters;
dest_arr[dest_num].type =
MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest_arr[dest_num].counter_id =
- mlx5_fc_id(mcounters->hw_cntrs_hndl);
+ dest_arr[dest_num].counter =
+ mcounters->hw_cntrs_hndl;
dest_num++;
}
@@ -1603,7 +1603,7 @@ static bool raw_fs_is_multicast(struct mlx5_ib_flow_matcher *fs_matcher,
static struct mlx5_ib_flow_handler *raw_fs_rule_add(
struct mlx5_ib_dev *dev, struct mlx5_ib_flow_matcher *fs_matcher,
struct mlx5_flow_context *flow_context, struct mlx5_flow_act *flow_act,
- u32 counter_id, void *cmd_in, int inlen, int dest_id, int dest_type)
+ struct mlx5_fc *counter, void *cmd_in, int inlen, int dest_id, int dest_type)
{
struct mlx5_flow_destination *dst;
struct mlx5_ib_flow_prio *ft_prio;
@@ -1652,8 +1652,12 @@ static struct mlx5_ib_flow_handler *raw_fs_rule_add(
}
if (flow_act->action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
+ if (WARN_ON(!counter)) {
+ err = -EINVAL;
+ goto unlock;
+ }
dst[dst_num].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dst[dst_num].counter_id = counter_id;
+ dst[dst_num].counter = counter;
dst_num++;
}
@@ -1878,7 +1882,8 @@ static int get_dests(struct uverbs_attr_bundle *attrs,
return 0;
}
-static bool is_flow_counter(void *obj, u32 offset, u32 *counter_id)
+static bool
+is_flow_counter(void *obj, u32 offset, u32 *counter_id, u32 *fc_bulk_size)
{
struct devx_obj *devx_obj = obj;
u16 opcode = MLX5_GET(general_obj_in_cmd_hdr, devx_obj->dinbox, opcode);
@@ -1888,6 +1893,7 @@ static bool is_flow_counter(void *obj, u32 offset, u32 *counter_id)
if (offset && offset >= devx_obj->flow_counter_bulk_size)
return false;
+ *fc_bulk_size = devx_obj->flow_counter_bulk_size;
*counter_id = MLX5_GET(dealloc_flow_counter_in,
devx_obj->dinbox,
flow_counter_id);
@@ -1904,13 +1910,13 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
{
struct mlx5_flow_context flow_context = {.flow_tag =
MLX5_FS_DEFAULT_FLOW_TAG};
- u32 *offset_attr, offset = 0, counter_id = 0;
int dest_id, dest_type = -1, inlen, len, ret, i;
struct mlx5_ib_flow_handler *flow_handler;
struct mlx5_ib_flow_matcher *fs_matcher;
struct ib_uobject **arr_flow_actions;
struct ib_uflow_resources *uflow_res;
struct mlx5_flow_act flow_act = {};
+ struct mlx5_fc *counter = NULL;
struct ib_qp *qp = NULL;
void *devx_obj, *cmd_in;
struct ib_uobject *uobj;
@@ -1937,6 +1943,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
len = uverbs_attr_get_uobjs_arr(attrs,
MLX5_IB_ATTR_CREATE_FLOW_ARR_COUNTERS_DEVX, &arr_flow_actions);
if (len) {
+ u32 *offset_attr, fc_bulk_size, offset = 0, counter_id = 0;
devx_obj = arr_flow_actions[0]->object;
if (uverbs_attr_is_valid(attrs,
@@ -1956,8 +1963,11 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
offset = *offset_attr;
}
- if (!is_flow_counter(devx_obj, offset, &counter_id))
+ if (!is_flow_counter(devx_obj, offset, &counter_id, &fc_bulk_size))
return -EINVAL;
+ counter = mlx5_fc_local_create(counter_id, offset, fc_bulk_size);
+ if (IS_ERR(counter))
+ return PTR_ERR(counter);
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
}
@@ -1968,8 +1978,10 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
MLX5_IB_ATTR_CREATE_FLOW_MATCH_VALUE);
uflow_res = flow_resources_alloc(MLX5_IB_CREATE_FLOW_MAX_FLOW_ACTIONS);
- if (!uflow_res)
- return -ENOMEM;
+ if (!uflow_res) {
+ ret = -ENOMEM;
+ goto destroy_counter;
+ }
len = uverbs_attr_get_uobjs_arr(attrs,
MLX5_IB_ATTR_CREATE_FLOW_ARR_FLOW_ACTIONS, &arr_flow_actions);
@@ -1996,7 +2008,7 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
flow_handler =
raw_fs_rule_add(dev, fs_matcher, &flow_context, &flow_act,
- counter_id, cmd_in, inlen, dest_id, dest_type);
+ counter, cmd_in, inlen, dest_id, dest_type);
if (IS_ERR(flow_handler)) {
ret = PTR_ERR(flow_handler);
goto err_out;
@@ -2007,6 +2019,9 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_CREATE_FLOW)(
return 0;
err_out:
ib_uverbs_flow_resources_free(uflow_res);
+destroy_counter:
+ if (counter)
+ mlx5_fc_local_destroy(counter);
return ret;
}
diff --git a/drivers/infiniband/hw/mlx5/main.c b/drivers/infiniband/hw/mlx5/main.c
index bc7930d0c564..f5b59d02f4d3 100644
--- a/drivers/infiniband/hw/mlx5/main.c
+++ b/drivers/infiniband/hw/mlx5/main.c
@@ -2839,7 +2839,7 @@ static int mlx5_ib_get_plane_num(struct mlx5_core_dev *mdev, u8 *num_plane)
int err;
*num_plane = 0;
- if (!MLX5_CAP_GEN(mdev, ib_virt))
+ if (!MLX5_CAP_GEN(mdev, ib_virt) || !MLX5_CAP_GEN_2(mdev, multiplane))
return 0;
err = mlx5_query_hca_vport_context(mdev, 0, 1, 0, &vport_ctx);
@@ -3639,7 +3639,8 @@ static int mlx5_ib_init_multiport_master(struct mlx5_ib_dev *dev)
list_for_each_entry(mpi, &mlx5_ib_unaffiliated_port_list,
list) {
if (dev->sys_image_guid == mpi->sys_image_guid &&
- (mlx5_core_native_port_num(mpi->mdev) - 1) == i) {
+ (mlx5_core_native_port_num(mpi->mdev) - 1) == i &&
+ mlx5_core_same_coredev_type(dev->mdev, mpi->mdev)) {
bound = mlx5_ib_bind_slave_port(dev, mpi);
}
@@ -4785,7 +4786,8 @@ static int mlx5r_mp_probe(struct auxiliary_device *adev,
mutex_lock(&mlx5_ib_multiport_mutex);
list_for_each_entry(dev, &mlx5_ib_dev_list, ib_dev_list) {
- if (dev->sys_image_guid == mpi->sys_image_guid)
+ if (dev->sys_image_guid == mpi->sys_image_guid &&
+ mlx5_core_same_coredev_type(dev->mdev, mpi->mdev))
bound = mlx5_ib_bind_slave_port(dev, mpi);
if (bound) {
diff --git a/drivers/infiniband/hw/qib/qib_sysfs.c b/drivers/infiniband/hw/qib/qib_sysfs.c
index 53ec7510e4eb..ba2cd68b53e6 100644
--- a/drivers/infiniband/hw/qib/qib_sysfs.c
+++ b/drivers/infiniband/hw/qib/qib_sysfs.c
@@ -283,7 +283,7 @@ static struct bin_attribute *port_ccmgta_attributes[] = {
};
static umode_t qib_ccmgta_is_bin_visible(struct kobject *kobj,
- struct bin_attribute *attr, int n)
+ const struct bin_attribute *attr, int n)
{
struct qib_pportdata *ppd = qib_get_pportdata_kobj(kobj);
diff --git a/drivers/infiniband/sw/rxe/rxe.c b/drivers/infiniband/sw/rxe/rxe.c
index 255677bc12b2..1ba4a0c8726a 100644
--- a/drivers/infiniband/sw/rxe/rxe.c
+++ b/drivers/infiniband/sw/rxe/rxe.c
@@ -40,6 +40,8 @@ void rxe_dealloc(struct ib_device *ib_dev)
/* initialize rxe device parameters */
static void rxe_init_device_param(struct rxe_dev *rxe)
{
+ struct net_device *ndev;
+
rxe->max_inline_data = RXE_MAX_INLINE_DATA;
rxe->attr.vendor_id = RXE_VENDOR_ID;
@@ -71,8 +73,15 @@ static void rxe_init_device_param(struct rxe_dev *rxe)
rxe->attr.max_fast_reg_page_list_len = RXE_MAX_FMR_PAGE_LIST_LEN;
rxe->attr.max_pkeys = RXE_MAX_PKEYS;
rxe->attr.local_ca_ack_delay = RXE_LOCAL_CA_ACK_DELAY;
+
+ ndev = rxe_ib_device_get_netdev(&rxe->ib_dev);
+ if (!ndev)
+ return;
+
addrconf_addr_eui48((unsigned char *)&rxe->attr.sys_image_guid,
- rxe->ndev->dev_addr);
+ ndev->dev_addr);
+
+ dev_put(ndev);
rxe->max_ucontext = RXE_MAX_UCONTEXT;
}
@@ -109,10 +118,15 @@ static void rxe_init_port_param(struct rxe_port *port)
static void rxe_init_ports(struct rxe_dev *rxe)
{
struct rxe_port *port = &rxe->port;
+ struct net_device *ndev;
rxe_init_port_param(port);
+ ndev = rxe_ib_device_get_netdev(&rxe->ib_dev);
+ if (!ndev)
+ return;
addrconf_addr_eui48((unsigned char *)&port->port_guid,
- rxe->ndev->dev_addr);
+ ndev->dev_addr);
+ dev_put(ndev);
spin_lock_init(&port->port_lock);
}
@@ -167,12 +181,13 @@ void rxe_set_mtu(struct rxe_dev *rxe, unsigned int ndev_mtu)
/* called by ifc layer to create new rxe device.
* The caller should allocate memory for rxe by calling ib_alloc_device.
*/
-int rxe_add(struct rxe_dev *rxe, unsigned int mtu, const char *ibdev_name)
+int rxe_add(struct rxe_dev *rxe, unsigned int mtu, const char *ibdev_name,
+ struct net_device *ndev)
{
rxe_init(rxe);
rxe_set_mtu(rxe, mtu);
- return rxe_register_device(rxe, ibdev_name);
+ return rxe_register_device(rxe, ibdev_name, ndev);
}
static int rxe_newlink(const char *ibdev_name, struct net_device *ndev)
diff --git a/drivers/infiniband/sw/rxe/rxe.h b/drivers/infiniband/sw/rxe/rxe.h
index d8fb2c7af30a..fe7f97066732 100644
--- a/drivers/infiniband/sw/rxe/rxe.h
+++ b/drivers/infiniband/sw/rxe/rxe.h
@@ -139,7 +139,8 @@ enum resp_states {
void rxe_set_mtu(struct rxe_dev *rxe, unsigned int dev_mtu);
-int rxe_add(struct rxe_dev *rxe, unsigned int mtu, const char *ibdev_name);
+int rxe_add(struct rxe_dev *rxe, unsigned int mtu, const char *ibdev_name,
+ struct net_device *ndev);
void rxe_rcv(struct sk_buff *skb);
diff --git a/drivers/infiniband/sw/rxe/rxe_mcast.c b/drivers/infiniband/sw/rxe/rxe_mcast.c
index 86cc2e18a7fd..07ff47bae31d 100644
--- a/drivers/infiniband/sw/rxe/rxe_mcast.c
+++ b/drivers/infiniband/sw/rxe/rxe_mcast.c
@@ -31,10 +31,19 @@
static int rxe_mcast_add(struct rxe_dev *rxe, union ib_gid *mgid)
{
unsigned char ll_addr[ETH_ALEN];
+ struct net_device *ndev;
+ int ret;
+
+ ndev = rxe_ib_device_get_netdev(&rxe->ib_dev);
+ if (!ndev)
+ return -ENODEV;
ipv6_eth_mc_map((struct in6_addr *)mgid->raw, ll_addr);
- return dev_mc_add(rxe->ndev, ll_addr);
+ ret = dev_mc_add(ndev, ll_addr);
+ dev_put(ndev);
+
+ return ret;
}
/**
@@ -47,10 +56,19 @@ static int rxe_mcast_add(struct rxe_dev *rxe, union ib_gid *mgid)
static int rxe_mcast_del(struct rxe_dev *rxe, union ib_gid *mgid)
{
unsigned char ll_addr[ETH_ALEN];
+ struct net_device *ndev;
+ int ret;
+
+ ndev = rxe_ib_device_get_netdev(&rxe->ib_dev);
+ if (!ndev)
+ return -ENODEV;
ipv6_eth_mc_map((struct in6_addr *)mgid->raw, ll_addr);
- return dev_mc_del(rxe->ndev, ll_addr);
+ ret = dev_mc_del(ndev, ll_addr);
+ dev_put(ndev);
+
+ return ret;
}
/**
diff --git a/drivers/infiniband/sw/rxe/rxe_net.c b/drivers/infiniband/sw/rxe/rxe_net.c
index 75d1407db52d..8cc64ceeb356 100644
--- a/drivers/infiniband/sw/rxe/rxe_net.c
+++ b/drivers/infiniband/sw/rxe/rxe_net.c
@@ -524,7 +524,16 @@ out:
*/
const char *rxe_parent_name(struct rxe_dev *rxe, unsigned int port_num)
{
- return rxe->ndev->name;
+ struct net_device *ndev;
+ char *ndev_name;
+
+ ndev = rxe_ib_device_get_netdev(&rxe->ib_dev);
+ if (!ndev)
+ return NULL;
+ ndev_name = ndev->name;
+ dev_put(ndev);
+
+ return ndev_name;
}
int rxe_net_add(const char *ibdev_name, struct net_device *ndev)
@@ -536,10 +545,9 @@ int rxe_net_add(const char *ibdev_name, struct net_device *ndev)
if (!rxe)
return -ENOMEM;
- rxe->ndev = ndev;
ib_mark_name_assigned_by_user(&rxe->ib_dev);
- err = rxe_add(rxe, ndev->mtu, ibdev_name);
+ err = rxe_add(rxe, ndev->mtu, ibdev_name, ndev);
if (err) {
ib_dealloc_device(&rxe->ib_dev);
return err;
@@ -587,10 +595,18 @@ void rxe_port_down(struct rxe_dev *rxe)
void rxe_set_port_state(struct rxe_dev *rxe)
{
- if (netif_running(rxe->ndev) && netif_carrier_ok(rxe->ndev))
+ struct net_device *ndev;
+
+ ndev = rxe_ib_device_get_netdev(&rxe->ib_dev);
+ if (!ndev)
+ return;
+
+ if (netif_running(ndev) && netif_carrier_ok(ndev))
rxe_port_up(rxe);
else
rxe_port_down(rxe);
+
+ dev_put(ndev);
}
static int rxe_notify(struct notifier_block *not_blk,
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.c b/drivers/infiniband/sw/rxe/rxe_verbs.c
index 5c18f7e342f2..8a5fc20fd186 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.c
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.c
@@ -41,6 +41,7 @@ static int rxe_query_port(struct ib_device *ibdev,
u32 port_num, struct ib_port_attr *attr)
{
struct rxe_dev *rxe = to_rdev(ibdev);
+ struct net_device *ndev;
int err, ret;
if (port_num != 1) {
@@ -49,6 +50,12 @@ static int rxe_query_port(struct ib_device *ibdev,
goto err_out;
}
+ ndev = rxe_ib_device_get_netdev(ibdev);
+ if (!ndev) {
+ err = -ENODEV;
+ goto err_out;
+ }
+
memcpy(attr, &rxe->port.attr, sizeof(*attr));
mutex_lock(&rxe->usdev_lock);
@@ -57,13 +64,14 @@ static int rxe_query_port(struct ib_device *ibdev,
if (attr->state == IB_PORT_ACTIVE)
attr->phys_state = IB_PORT_PHYS_STATE_LINK_UP;
- else if (dev_get_flags(rxe->ndev) & IFF_UP)
+ else if (dev_get_flags(ndev) & IFF_UP)
attr->phys_state = IB_PORT_PHYS_STATE_POLLING;
else
attr->phys_state = IB_PORT_PHYS_STATE_DISABLED;
mutex_unlock(&rxe->usdev_lock);
+ dev_put(ndev);
return ret;
err_out:
@@ -1425,9 +1433,16 @@ static const struct attribute_group rxe_attr_group = {
static int rxe_enable_driver(struct ib_device *ib_dev)
{
struct rxe_dev *rxe = container_of(ib_dev, struct rxe_dev, ib_dev);
+ struct net_device *ndev;
+
+ ndev = rxe_ib_device_get_netdev(ib_dev);
+ if (!ndev)
+ return -ENODEV;
rxe_set_port_state(rxe);
- dev_info(&rxe->ib_dev.dev, "added %s\n", netdev_name(rxe->ndev));
+ dev_info(&rxe->ib_dev.dev, "added %s\n", netdev_name(ndev));
+
+ dev_put(ndev);
return 0;
}
@@ -1495,7 +1510,8 @@ static const struct ib_device_ops rxe_dev_ops = {
INIT_RDMA_OBJ_SIZE(ib_mw, rxe_mw, ibmw),
};
-int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name)
+int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name,
+ struct net_device *ndev)
{
int err;
struct ib_device *dev = &rxe->ib_dev;
@@ -1507,13 +1523,13 @@ int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name)
dev->num_comp_vectors = num_possible_cpus();
dev->local_dma_lkey = 0;
addrconf_addr_eui48((unsigned char *)&dev->node_guid,
- rxe->ndev->dev_addr);
+ ndev->dev_addr);
dev->uverbs_cmd_mask |= BIT_ULL(IB_USER_VERBS_CMD_POST_SEND) |
BIT_ULL(IB_USER_VERBS_CMD_REQ_NOTIFY_CQ);
ib_set_device_ops(dev, &rxe_dev_ops);
- err = ib_device_set_netdev(&rxe->ib_dev, rxe->ndev, 1);
+ err = ib_device_set_netdev(&rxe->ib_dev, ndev, 1);
if (err)
return err;
diff --git a/drivers/infiniband/sw/rxe/rxe_verbs.h b/drivers/infiniband/sw/rxe/rxe_verbs.h
index 3c1354f82283..6573ceec0ef5 100644
--- a/drivers/infiniband/sw/rxe/rxe_verbs.h
+++ b/drivers/infiniband/sw/rxe/rxe_verbs.h
@@ -370,6 +370,7 @@ struct rxe_port {
u32 qp_gsi_index;
};
+#define RXE_PORT 1
struct rxe_dev {
struct ib_device ib_dev;
struct ib_device_attr attr;
@@ -377,8 +378,6 @@ struct rxe_dev {
int max_inline_data;
struct mutex usdev_lock;
- struct net_device *ndev;
-
struct rxe_pool uc_pool;
struct rxe_pool pd_pool;
struct rxe_pool ah_pool;
@@ -406,6 +405,11 @@ struct rxe_dev {
struct crypto_shash *tfm;
};
+static inline struct net_device *rxe_ib_device_get_netdev(struct ib_device *dev)
+{
+ return ib_device_get_netdev(dev, RXE_PORT);
+}
+
static inline void rxe_counter_inc(struct rxe_dev *rxe, enum rxe_counters index)
{
atomic64_inc(&rxe->stats_counters[index]);
@@ -471,6 +475,7 @@ static inline struct rxe_pd *rxe_mw_pd(struct rxe_mw *mw)
return to_rpd(mw->ibmw.pd);
}
-int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name);
+int rxe_register_device(struct rxe_dev *rxe, const char *ibdev_name,
+ struct net_device *ndev);
#endif /* RXE_VERBS_H */
diff --git a/drivers/infiniband/sw/siw/siw.h b/drivers/infiniband/sw/siw/siw.h
index 86d4d6a2170e..ea5eee50dc39 100644
--- a/drivers/infiniband/sw/siw/siw.h
+++ b/drivers/infiniband/sw/siw/siw.h
@@ -46,6 +46,9 @@
*/
#define SIW_IRQ_MAXBURST_SQ_ACTIVE 4
+/* There is always only a port 1 per siw device */
+#define SIW_PORT 1
+
struct siw_dev_cap {
int max_qp;
int max_qp_wr;
@@ -69,16 +72,12 @@ struct siw_pd {
struct siw_device {
struct ib_device base_dev;
- struct net_device *netdev;
struct siw_dev_cap attrs;
u32 vendor_part_id;
int numa_node;
char raw_gid[ETH_ALEN];
- /* physical port state (only one port per device) */
- enum ib_port_state state;
-
spinlock_t lock;
struct xarray qp_xa;
diff --git a/drivers/infiniband/sw/siw/siw_cm.c b/drivers/infiniband/sw/siw/siw_cm.c
index 86323918a570..708b13993fdf 100644
--- a/drivers/infiniband/sw/siw/siw_cm.c
+++ b/drivers/infiniband/sw/siw/siw_cm.c
@@ -1759,6 +1759,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
{
struct socket *s;
struct siw_cep *cep = NULL;
+ struct net_device *ndev = NULL;
struct siw_device *sdev = to_siw_dev(id->device);
int addr_family = id->local_addr.ss_family;
int rv = 0;
@@ -1779,9 +1780,15 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
struct sockaddr_in *laddr = &to_sockaddr_in(id->local_addr);
/* For wildcard addr, limit binding to current device only */
- if (ipv4_is_zeronet(laddr->sin_addr.s_addr))
- s->sk->sk_bound_dev_if = sdev->netdev->ifindex;
-
+ if (ipv4_is_zeronet(laddr->sin_addr.s_addr)) {
+ ndev = ib_device_get_netdev(id->device, SIW_PORT);
+ if (ndev) {
+ s->sk->sk_bound_dev_if = ndev->ifindex;
+ } else {
+ rv = -ENODEV;
+ goto error;
+ }
+ }
rv = s->ops->bind(s, (struct sockaddr *)laddr,
sizeof(struct sockaddr_in));
} else {
@@ -1797,9 +1804,15 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
}
/* For wildcard addr, limit binding to current device only */
- if (ipv6_addr_any(&laddr->sin6_addr))
- s->sk->sk_bound_dev_if = sdev->netdev->ifindex;
-
+ if (ipv6_addr_any(&laddr->sin6_addr)) {
+ ndev = ib_device_get_netdev(id->device, SIW_PORT);
+ if (ndev) {
+ s->sk->sk_bound_dev_if = ndev->ifindex;
+ } else {
+ rv = -ENODEV;
+ goto error;
+ }
+ }
rv = s->ops->bind(s, (struct sockaddr *)laddr,
sizeof(struct sockaddr_in6));
}
@@ -1860,6 +1873,7 @@ int siw_create_listen(struct iw_cm_id *id, int backlog)
}
list_add_tail(&cep->listenq, (struct list_head *)id->provider_data);
cep->state = SIW_EPSTATE_LISTENING;
+ dev_put(ndev);
siw_dbg(id->device, "Listen at laddr %pISp\n", &id->local_addr);
@@ -1879,6 +1893,7 @@ error:
siw_cep_set_free_and_put(cep);
}
sock_release(s);
+ dev_put(ndev);
return rv;
}
diff --git a/drivers/infiniband/sw/siw/siw_main.c b/drivers/infiniband/sw/siw/siw_main.c
index 17abef48abcd..14d3103aee6f 100644
--- a/drivers/infiniband/sw/siw/siw_main.c
+++ b/drivers/infiniband/sw/siw/siw_main.c
@@ -287,7 +287,6 @@ static struct siw_device *siw_device_create(struct net_device *netdev)
return NULL;
base_dev = &sdev->base_dev;
- sdev->netdev = netdev;
if (netdev->addr_len) {
memcpy(sdev->raw_gid, netdev->dev_addr,
@@ -381,12 +380,10 @@ static int siw_netdev_event(struct notifier_block *nb, unsigned long event,
switch (event) {
case NETDEV_UP:
- sdev->state = IB_PORT_ACTIVE;
siw_port_event(sdev, 1, IB_EVENT_PORT_ACTIVE);
break;
case NETDEV_DOWN:
- sdev->state = IB_PORT_DOWN;
siw_port_event(sdev, 1, IB_EVENT_PORT_ERR);
break;
@@ -407,12 +404,8 @@ static int siw_netdev_event(struct notifier_block *nb, unsigned long event,
siw_port_event(sdev, 1, IB_EVENT_LID_CHANGE);
break;
/*
- * Todo: Below netdev events are currently not handled.
+ * All other events are not handled
*/
- case NETDEV_CHANGEMTU:
- case NETDEV_CHANGE:
- break;
-
default:
break;
}
@@ -442,12 +435,6 @@ static int siw_newlink(const char *basedev_name, struct net_device *netdev)
sdev = siw_device_create(netdev);
if (sdev) {
dev_dbg(&netdev->dev, "siw: new device\n");
-
- if (netif_running(netdev) && netif_carrier_ok(netdev))
- sdev->state = IB_PORT_ACTIVE;
- else
- sdev->state = IB_PORT_DOWN;
-
ib_mark_name_assigned_by_user(&sdev->base_dev);
rv = siw_device_register(sdev, basedev_name);
if (rv)
diff --git a/drivers/infiniband/sw/siw/siw_verbs.c b/drivers/infiniband/sw/siw/siw_verbs.c
index 986666c19378..7ca0297d68a4 100644
--- a/drivers/infiniband/sw/siw/siw_verbs.c
+++ b/drivers/infiniband/sw/siw/siw_verbs.c
@@ -171,21 +171,29 @@ int siw_query_device(struct ib_device *base_dev, struct ib_device_attr *attr,
int siw_query_port(struct ib_device *base_dev, u32 port,
struct ib_port_attr *attr)
{
- struct siw_device *sdev = to_siw_dev(base_dev);
+ struct net_device *ndev;
int rv;
memset(attr, 0, sizeof(*attr));
rv = ib_get_eth_speed(base_dev, port, &attr->active_speed,
&attr->active_width);
+ if (rv)
+ return rv;
+
+ ndev = ib_device_get_netdev(base_dev, SIW_PORT);
+ if (!ndev)
+ return -ENODEV;
+
attr->gid_tbl_len = 1;
attr->max_msg_sz = -1;
- attr->max_mtu = ib_mtu_int_to_enum(sdev->netdev->mtu);
- attr->active_mtu = ib_mtu_int_to_enum(sdev->netdev->mtu);
- attr->phys_state = sdev->state == IB_PORT_ACTIVE ?
+ attr->max_mtu = ib_mtu_int_to_enum(ndev->max_mtu);
+ attr->active_mtu = ib_mtu_int_to_enum(READ_ONCE(ndev->mtu));
+ attr->phys_state = (netif_running(ndev) && netif_carrier_ok(ndev)) ?
IB_PORT_PHYS_STATE_LINK_UP : IB_PORT_PHYS_STATE_DISABLED;
+ attr->state = attr->phys_state == IB_PORT_PHYS_STATE_LINK_UP ?
+ IB_PORT_ACTIVE : IB_PORT_DOWN;
attr->port_cap_flags = IB_PORT_CM_SUP | IB_PORT_DEVICE_MGMT_SUP;
- attr->state = sdev->state;
/*
* All zero
*
@@ -199,6 +207,7 @@ int siw_query_port(struct ib_device *base_dev, u32 port,
* attr->subnet_timeout = 0;
* attr->init_type_repy = 0;
*/
+ dev_put(ndev);
return rv;
}
@@ -505,21 +514,24 @@ int siw_query_qp(struct ib_qp *base_qp, struct ib_qp_attr *qp_attr,
int qp_attr_mask, struct ib_qp_init_attr *qp_init_attr)
{
struct siw_qp *qp;
- struct siw_device *sdev;
+ struct net_device *ndev;
- if (base_qp && qp_attr && qp_init_attr) {
+ if (base_qp && qp_attr && qp_init_attr)
qp = to_siw_qp(base_qp);
- sdev = to_siw_dev(base_qp->device);
- } else {
+ else
return -EINVAL;
- }
+
+ ndev = ib_device_get_netdev(base_qp->device, SIW_PORT);
+ if (!ndev)
+ return -ENODEV;
+
qp_attr->qp_state = siw_qp_state_to_ib_qp_state[qp->attrs.state];
qp_attr->cap.max_inline_data = SIW_MAX_INLINE;
qp_attr->cap.max_send_wr = qp->attrs.sq_size;
qp_attr->cap.max_send_sge = qp->attrs.sq_max_sges;
qp_attr->cap.max_recv_wr = qp->attrs.rq_size;
qp_attr->cap.max_recv_sge = qp->attrs.rq_max_sges;
- qp_attr->path_mtu = ib_mtu_int_to_enum(sdev->netdev->mtu);
+ qp_attr->path_mtu = ib_mtu_int_to_enum(READ_ONCE(ndev->mtu));
qp_attr->max_rd_atomic = qp->attrs.irq_size;
qp_attr->max_dest_rd_atomic = qp->attrs.orq_size;
@@ -534,6 +546,7 @@ int siw_query_qp(struct ib_qp *base_qp, struct ib_qp_attr *qp_attr,
qp_init_attr->cap = qp_attr->cap;
+ dev_put(ndev);
return 0;
}
diff --git a/drivers/infiniband/ulp/rtrs/rtrs-srv.c b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
index e83d95647852..ef4abdea3c2d 100644
--- a/drivers/infiniband/ulp/rtrs/rtrs-srv.c
+++ b/drivers/infiniband/ulp/rtrs/rtrs-srv.c
@@ -349,6 +349,7 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id,
struct rtrs_srv_mr *srv_mr;
bool need_inval = false;
enum ib_send_flags flags;
+ struct ib_sge list;
u32 imm;
int err;
@@ -401,7 +402,6 @@ static int send_io_resp_imm(struct rtrs_srv_con *con, struct rtrs_srv_op *id,
imm = rtrs_to_io_rsp_imm(id->msg_id, errno, need_inval);
imm_wr.wr.next = NULL;
if (always_invalidate) {
- struct ib_sge list;
struct rtrs_msg_rkey_rsp *msg;
srv_mr = &srv_path->mrs[id->msg_id];
diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c
index 7e9b996b47c8..9d5404a07e8a 100644
--- a/drivers/interconnect/core.c
+++ b/drivers/interconnect/core.c
@@ -808,7 +808,7 @@ void icc_put(struct icc_path *path)
mutex_unlock(&icc_bw_lock);
mutex_unlock(&icc_lock);
- kfree_const(path->name);
+ kfree(path->name);
kfree(path);
}
EXPORT_SYMBOL_GPL(icc_put);
@@ -1081,7 +1081,7 @@ static int of_count_icc_providers(struct device_node *np)
int count = 0;
for_each_available_child_of_node(np, child) {
- if (of_property_read_bool(child, "#interconnect-cells") &&
+ if (of_property_present(child, "#interconnect-cells") &&
likely(!of_match_node(ignore_list, child)))
count++;
count += of_count_icc_providers(child);
diff --git a/drivers/interconnect/imx/imx8mm.c b/drivers/interconnect/imx/imx8mm.c
index a36aaaf106ae..efed12d635c1 100644
--- a/drivers/interconnect/imx/imx8mm.c
+++ b/drivers/interconnect/imx/imx8mm.c
@@ -88,7 +88,7 @@ static int imx8mm_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mm_icc_driver = {
.probe = imx8mm_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mm-interconnect",
},
diff --git a/drivers/interconnect/imx/imx8mn.c b/drivers/interconnect/imx/imx8mn.c
index 2a97c74e875b..535fae791f2e 100644
--- a/drivers/interconnect/imx/imx8mn.c
+++ b/drivers/interconnect/imx/imx8mn.c
@@ -77,7 +77,7 @@ static int imx8mn_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mn_icc_driver = {
.probe = imx8mn_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mn-interconnect",
},
diff --git a/drivers/interconnect/imx/imx8mp.c b/drivers/interconnect/imx/imx8mp.c
index 86d4c1517b26..c5751ed18d51 100644
--- a/drivers/interconnect/imx/imx8mp.c
+++ b/drivers/interconnect/imx/imx8mp.c
@@ -241,7 +241,7 @@ static int imx8mp_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mp_icc_driver = {
.probe = imx8mp_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mp-interconnect",
},
diff --git a/drivers/interconnect/imx/imx8mq.c b/drivers/interconnect/imx/imx8mq.c
index f817d24aeefb..6aa4f06b4676 100644
--- a/drivers/interconnect/imx/imx8mq.c
+++ b/drivers/interconnect/imx/imx8mq.c
@@ -87,7 +87,7 @@ static int imx8mq_icc_probe(struct platform_device *pdev)
static struct platform_driver imx8mq_icc_driver = {
.probe = imx8mq_icc_probe,
- .remove_new = imx_icc_unregister,
+ .remove = imx_icc_unregister,
.driver = {
.name = "imx8mq-interconnect",
.sync_state = icc_sync_state,
diff --git a/drivers/interconnect/mediatek/mt8183.c b/drivers/interconnect/mediatek/mt8183.c
index 24245085c7a9..c212e79334cf 100644
--- a/drivers/interconnect/mediatek/mt8183.c
+++ b/drivers/interconnect/mediatek/mt8183.c
@@ -133,7 +133,7 @@ static struct platform_driver mtk_emi_icc_mt8183_driver = {
.sync_state = icc_sync_state,
},
.probe = mtk_emi_icc_probe,
- .remove_new = mtk_emi_icc_remove,
+ .remove = mtk_emi_icc_remove,
};
module_platform_driver(mtk_emi_icc_mt8183_driver);
diff --git a/drivers/interconnect/mediatek/mt8195.c b/drivers/interconnect/mediatek/mt8195.c
index 710e14c5447c..3ca23469ab18 100644
--- a/drivers/interconnect/mediatek/mt8195.c
+++ b/drivers/interconnect/mediatek/mt8195.c
@@ -329,7 +329,7 @@ static struct platform_driver mtk_emi_icc_mt8195_driver = {
.sync_state = icc_sync_state,
},
.probe = mtk_emi_icc_probe,
- .remove_new = mtk_emi_icc_remove,
+ .remove = mtk_emi_icc_remove,
};
module_platform_driver(mtk_emi_icc_mt8195_driver);
diff --git a/drivers/interconnect/qcom/Kconfig b/drivers/interconnect/qcom/Kconfig
index de96d4661340..362fb9b0a198 100644
--- a/drivers/interconnect/qcom/Kconfig
+++ b/drivers/interconnect/qcom/Kconfig
@@ -105,6 +105,26 @@ config INTERCONNECT_QCOM_QCS404
This is a driver for the Qualcomm Network-on-Chip on qcs404-based
platforms.
+config INTERCONNECT_QCOM_QCS615
+ tristate "Qualcomm QCS615 interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Network-on-Chip on qcs615-based
+ platforms.
+
+config INTERCONNECT_QCOM_QCS8300
+ tristate "Qualcomm QCS8300 interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Technologies, Inc. Network-on-Chip
+ on QCS8300-based platforms. The interconnect provider collects and
+ aggreagates the cosumer bandwidth requests to satisfy constraints
+ placed on Network-on-Chip performance states.
+
config INTERCONNECT_QCOM_QDU1000
tristate "Qualcomm QDU1000/QRU1000 interconnect driver"
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
@@ -137,6 +157,15 @@ config INTERCONNECT_QCOM_SA8775P
This is a driver for the Qualcomm Network-on-Chip on sa8775p-based
platforms.
+config INTERCONNECT_QCOM_SAR2130P
+ tristate "Qualcomm SAR2130P interconnect driver"
+ depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
+ select INTERCONNECT_QCOM_RPMH
+ select INTERCONNECT_QCOM_BCM_VOTER
+ help
+ This is a driver for the Qualcomm Network-on-Chip on SAR2130P-based
+ platforms.
+
config INTERCONNECT_QCOM_SC7180
tristate "Qualcomm SC7180 interconnect driver"
depends on INTERCONNECT_QCOM_RPMH_POSSIBLE
diff --git a/drivers/interconnect/qcom/Makefile b/drivers/interconnect/qcom/Makefile
index bfeea8416fcf..9997728c02bf 100644
--- a/drivers/interconnect/qcom/Makefile
+++ b/drivers/interconnect/qcom/Makefile
@@ -15,9 +15,12 @@ qnoc-msm8996-objs := msm8996.o
icc-osm-l3-objs := osm-l3.o
qnoc-qcm2290-objs := qcm2290.o
qnoc-qcs404-objs := qcs404.o
+qnoc-qcs615-objs := qcs615.o
+qnoc-qcs8300-objs := qcs8300.o
qnoc-qdu1000-objs := qdu1000.o
icc-rpmh-obj := icc-rpmh.o
qnoc-sa8775p-objs := sa8775p.o
+qnoc-sar2130p-objs := sar2130p.o
qnoc-sc7180-objs := sc7180.o
qnoc-sc7280-objs := sc7280.o
qnoc-sc8180x-objs := sc8180x.o
@@ -52,9 +55,12 @@ obj-$(CONFIG_INTERCONNECT_QCOM_MSM8996) += qnoc-msm8996.o
obj-$(CONFIG_INTERCONNECT_QCOM_OSM_L3) += icc-osm-l3.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCM2290) += qnoc-qcm2290.o
obj-$(CONFIG_INTERCONNECT_QCOM_QCS404) += qnoc-qcs404.o
+obj-$(CONFIG_INTERCONNECT_QCOM_QCS615) += qnoc-qcs615.o
+obj-$(CONFIG_INTERCONNECT_QCOM_QCS8300) += qnoc-qcs8300.o
obj-$(CONFIG_INTERCONNECT_QCOM_QDU1000) += qnoc-qdu1000.o
obj-$(CONFIG_INTERCONNECT_QCOM_RPMH) += icc-rpmh.o
obj-$(CONFIG_INTERCONNECT_QCOM_SA8775P) += qnoc-sa8775p.o
+obj-$(CONFIG_INTERCONNECT_QCOM_SAR2130P) += qnoc-sar2130p.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC7180) += qnoc-sc7180.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC7280) += qnoc-sc7280.o
obj-$(CONFIG_INTERCONNECT_QCOM_SC8180X) += qnoc-sc8180x.o
diff --git a/drivers/interconnect/qcom/icc-rpmh.c b/drivers/interconnect/qcom/icc-rpmh.c
index f49a8e0cb03c..f2d63745be54 100644
--- a/drivers/interconnect/qcom/icc-rpmh.c
+++ b/drivers/interconnect/qcom/icc-rpmh.c
@@ -311,7 +311,10 @@ int qcom_icc_rpmh_probe(struct platform_device *pdev)
}
qp->num_clks = devm_clk_bulk_get_all(qp->dev, &qp->clks);
- if (qp->num_clks < 0 || (!qp->num_clks && desc->qos_clks_required)) {
+ if (qp->num_clks == -EPROBE_DEFER)
+ return dev_err_probe(dev, qp->num_clks, "Failed to get QoS clocks\n");
+
+ if (qp->num_clks < 0 || (!qp->num_clks && desc->qos_requires_clocks)) {
dev_info(dev, "Skipping QoS, failed to get clk: %d\n", qp->num_clks);
goto skip_qos_config;
}
diff --git a/drivers/interconnect/qcom/icc-rpmh.h b/drivers/interconnect/qcom/icc-rpmh.h
index 14db89850fb3..82344c734091 100644
--- a/drivers/interconnect/qcom/icc-rpmh.h
+++ b/drivers/interconnect/qcom/icc-rpmh.h
@@ -153,7 +153,7 @@ struct qcom_icc_desc {
size_t num_nodes;
struct qcom_icc_bcm * const *bcms;
size_t num_bcms;
- bool qos_clks_required;
+ bool qos_requires_clocks;
};
int qcom_icc_aggregate(struct icc_node *node, u32 tag, u32 avg_bw,
diff --git a/drivers/interconnect/qcom/msm8909.c b/drivers/interconnect/qcom/msm8909.c
index 0d0cd7282f5b..dd656ce7b64d 100644
--- a/drivers/interconnect/qcom/msm8909.c
+++ b/drivers/interconnect/qcom/msm8909.c
@@ -1316,7 +1316,7 @@ MODULE_DEVICE_TABLE(of, msm8909_noc_of_match);
static struct platform_driver msm8909_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8909",
.of_match_table = msm8909_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8916.c b/drivers/interconnect/qcom/msm8916.c
index 499b1a9ac413..35148880b3e8 100644
--- a/drivers/interconnect/qcom/msm8916.c
+++ b/drivers/interconnect/qcom/msm8916.c
@@ -1344,7 +1344,7 @@ MODULE_DEVICE_TABLE(of, msm8916_noc_of_match);
static struct platform_driver msm8916_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8916",
.of_match_table = msm8916_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8937.c b/drivers/interconnect/qcom/msm8937.c
index 052b14c28ef8..58533d00266b 100644
--- a/drivers/interconnect/qcom/msm8937.c
+++ b/drivers/interconnect/qcom/msm8937.c
@@ -1175,7 +1175,7 @@ static struct qcom_icc_node slv_lpass = {
.qos.qos_mode = NOC_QOS_MODE_INVALID,
};
-static struct qcom_icc_node *msm8937_bimc_nodes[] = {
+static struct qcom_icc_node * const msm8937_bimc_nodes[] = {
[MAS_APPS_PROC] = &mas_apps_proc,
[MAS_OXILI] = &mas_oxili,
[MAS_SNOC_BIMC_0] = &mas_snoc_bimc_0,
@@ -1204,7 +1204,7 @@ static const struct qcom_icc_desc msm8937_bimc = {
.ab_coeff = 154,
};
-static struct qcom_icc_node *msm8937_pcnoc_nodes[] = {
+static struct qcom_icc_node * const msm8937_pcnoc_nodes[] = {
[MAS_SPDM] = &mas_spdm,
[MAS_BLSP_1] = &mas_blsp_1,
[MAS_BLSP_2] = &mas_blsp_2,
@@ -1268,7 +1268,7 @@ static const struct qcom_icc_desc msm8937_pcnoc = {
.regmap_cfg = &msm8937_pcnoc_regmap_config,
};
-static struct qcom_icc_node *msm8937_snoc_nodes[] = {
+static struct qcom_icc_node * const msm8937_snoc_nodes[] = {
[MAS_QDSS_BAM] = &mas_qdss_bam,
[MAS_BIMC_SNOC] = &mas_bimc_snoc,
[MAS_PCNOC_SNOC] = &mas_pcnoc_snoc,
@@ -1304,7 +1304,7 @@ static const struct qcom_icc_desc msm8937_snoc = {
.qos_offset = 0x7000,
};
-static struct qcom_icc_node *msm8937_snoc_mm_nodes[] = {
+static struct qcom_icc_node * const msm8937_snoc_mm_nodes[] = {
[MAS_JPEG] = &mas_jpeg,
[MAS_MDP] = &mas_mdp,
[MAS_VENUS] = &mas_venus,
@@ -1337,7 +1337,7 @@ MODULE_DEVICE_TABLE(of, msm8937_noc_of_match);
static struct platform_driver msm8937_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8937",
.of_match_table = msm8937_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8939.c b/drivers/interconnect/qcom/msm8939.c
index 8ff2c23b1ca0..b52c5ac1175c 100644
--- a/drivers/interconnect/qcom/msm8939.c
+++ b/drivers/interconnect/qcom/msm8939.c
@@ -1421,7 +1421,7 @@ MODULE_DEVICE_TABLE(of, msm8939_noc_of_match);
static struct platform_driver msm8939_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8939",
.of_match_table = msm8939_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8953.c b/drivers/interconnect/qcom/msm8953.c
index 62f8c0774b3e..be2b1a606612 100644
--- a/drivers/interconnect/qcom/msm8953.c
+++ b/drivers/interconnect/qcom/msm8953.c
@@ -1310,7 +1310,7 @@ static const struct of_device_id msm8953_noc_of_match[] = {
static struct platform_driver msm8953_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8953",
.of_match_table = msm8953_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8974.c b/drivers/interconnect/qcom/msm8974.c
index 241076b5f36b..469fc48ebfe9 100644
--- a/drivers/interconnect/qcom/msm8974.c
+++ b/drivers/interconnect/qcom/msm8974.c
@@ -762,7 +762,7 @@ MODULE_DEVICE_TABLE(of, msm8974_noc_of_match);
static struct platform_driver msm8974_noc_driver = {
.probe = msm8974_icc_probe,
- .remove_new = msm8974_icc_remove,
+ .remove = msm8974_icc_remove,
.driver = {
.name = "qnoc-msm8974",
.of_match_table = msm8974_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8976.c b/drivers/interconnect/qcom/msm8976.c
index ab963def77c3..4e2ac7ebe742 100644
--- a/drivers/interconnect/qcom/msm8976.c
+++ b/drivers/interconnect/qcom/msm8976.c
@@ -1427,7 +1427,7 @@ MODULE_DEVICE_TABLE(of, msm8976_noc_of_match);
static struct platform_driver msm8976_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8976",
.of_match_table = msm8976_noc_of_match,
diff --git a/drivers/interconnect/qcom/msm8996.c b/drivers/interconnect/qcom/msm8996.c
index 788131400cd1..b73566c9b21f 100644
--- a/drivers/interconnect/qcom/msm8996.c
+++ b/drivers/interconnect/qcom/msm8996.c
@@ -2108,7 +2108,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-msm8996",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/osm-l3.c b/drivers/interconnect/qcom/osm-l3.c
index 61a8695a9adc..6a656ed44d49 100644
--- a/drivers/interconnect/qcom/osm-l3.c
+++ b/drivers/interconnect/qcom/osm-l3.c
@@ -290,7 +290,7 @@ MODULE_DEVICE_TABLE(of, osm_l3_of_match);
static struct platform_driver osm_l3_driver = {
.probe = qcom_osm_l3_probe,
- .remove_new = qcom_osm_l3_remove,
+ .remove = qcom_osm_l3_remove,
.driver = {
.name = "osm-l3",
.of_match_table = osm_l3_of_match,
diff --git a/drivers/interconnect/qcom/qcm2290.c b/drivers/interconnect/qcom/qcm2290.c
index ccbdc6202c07..e120bc1395f3 100644
--- a/drivers/interconnect/qcom/qcm2290.c
+++ b/drivers/interconnect/qcom/qcm2290.c
@@ -1367,7 +1367,7 @@ MODULE_DEVICE_TABLE(of, qcm2290_noc_of_match);
static struct platform_driver qcm2290_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-qcm2290",
.of_match_table = qcm2290_noc_of_match,
diff --git a/drivers/interconnect/qcom/qcs404.c b/drivers/interconnect/qcom/qcs404.c
index 63e9ff223ac4..ceac7a698769 100644
--- a/drivers/interconnect/qcom/qcs404.c
+++ b/drivers/interconnect/qcom/qcs404.c
@@ -1204,7 +1204,7 @@ MODULE_DEVICE_TABLE(of, qcs404_noc_of_match);
static struct platform_driver qcs404_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-qcs404",
.of_match_table = qcs404_noc_of_match,
diff --git a/drivers/interconnect/qcom/qcs615.c b/drivers/interconnect/qcom/qcs615.c
new file mode 100644
index 000000000000..7e59e91ce886
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs615.c
@@ -0,0 +1,1563 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <dt-bindings/interconnect/qcom,qcs615-rpmh.h>
+
+#include "bcm-voter.h"
+#include "icc-rpmh.h"
+#include "qcs615.h"
+
+static struct qcom_icc_node qhm_a1noc_cfg = {
+ .name = "qhm_a1noc_cfg",
+ .id = QCS615_MASTER_A1NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_SERVICE_A2NOC },
+};
+
+static struct qcom_icc_node qhm_qdss_bam = {
+ .name = "qhm_qdss_bam",
+ .id = QCS615_MASTER_QDSS_BAM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qspi = {
+ .name = "qhm_qspi",
+ .id = QCS615_MASTER_QSPI,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup0 = {
+ .name = "qhm_qup0",
+ .id = QCS615_MASTER_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup1 = {
+ .name = "qhm_qup1",
+ .id = QCS615_MASTER_BLSP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qnm_cnoc = {
+ .name = "qnm_cnoc",
+ .id = QCS615_MASTER_CNOC_A2NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_crypto = {
+ .name = "qxm_crypto",
+ .id = QCS615_MASTER_CRYPTO,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_ipa = {
+ .name = "qxm_ipa",
+ .id = QCS615_MASTER_IPA,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LPASS_SNOC },
+};
+
+static struct qcom_icc_node xm_emac_avb = {
+ .name = "xm_emac_avb",
+ .id = QCS615_MASTER_EMAC_EVB,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_pcie = {
+ .name = "xm_pcie",
+ .id = QCS615_MASTER_PCIE,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_ANOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node xm_qdss_etr = {
+ .name = "xm_qdss_etr",
+ .id = QCS615_MASTER_QDSS_ETR,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .id = QCS615_MASTER_SDCC_1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_sdc2 = {
+ .name = "xm_sdc2",
+ .id = QCS615_MASTER_SDCC_2,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_ufs_mem = {
+ .name = "xm_ufs_mem",
+ .id = QCS615_MASTER_UFS_MEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb2 = {
+ .name = "xm_usb2",
+ .id = QCS615_MASTER_USB2,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .id = QCS615_MASTER_USB3_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf0_uncomp = {
+ .name = "qxm_camnoc_hf0_uncomp",
+ .id = QCS615_MASTER_CAMNOC_HF0_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CAMNOC_UNCOMP },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf1_uncomp = {
+ .name = "qxm_camnoc_hf1_uncomp",
+ .id = QCS615_MASTER_CAMNOC_HF1_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CAMNOC_UNCOMP },
+};
+
+static struct qcom_icc_node qxm_camnoc_sf_uncomp = {
+ .name = "qxm_camnoc_sf_uncomp",
+ .id = QCS615_MASTER_CAMNOC_SF_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CAMNOC_UNCOMP },
+};
+
+static struct qcom_icc_node qhm_spdm = {
+ .name = "qhm_spdm",
+ .id = QCS615_MASTER_SPDM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_CNOC_A2NOC },
+};
+
+static struct qcom_icc_node qnm_snoc = {
+ .name = "qnm_snoc",
+ .id = QCS615_MASTER_SNOC_CNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 39,
+ .links = { QCS615_SLAVE_A1NOC_CFG, QCS615_SLAVE_AHB2PHY_EAST,
+ QCS615_SLAVE_AHB2PHY_WEST, QCS615_SLAVE_AOP,
+ QCS615_SLAVE_AOSS, QCS615_SLAVE_CAMERA_CFG,
+ QCS615_SLAVE_CLK_CTL, QCS615_SLAVE_RBCPR_CX_CFG,
+ QCS615_SLAVE_RBCPR_MX_CFG, QCS615_SLAVE_CRYPTO_0_CFG,
+ QCS615_SLAVE_CNOC_DDRSS, QCS615_SLAVE_DISPLAY_CFG,
+ QCS615_SLAVE_EMAC_AVB_CFG, QCS615_SLAVE_GLM,
+ QCS615_SLAVE_GFX3D_CFG, QCS615_SLAVE_IMEM_CFG,
+ QCS615_SLAVE_IPA_CFG, QCS615_SLAVE_CNOC_MNOC_CFG,
+ QCS615_SLAVE_PCIE_CFG, QCS615_SLAVE_PIMEM_CFG,
+ QCS615_SLAVE_PRNG, QCS615_SLAVE_QDSS_CFG,
+ QCS615_SLAVE_QSPI, QCS615_SLAVE_QUP_0,
+ QCS615_SLAVE_QUP_1, QCS615_SLAVE_SDCC_1,
+ QCS615_SLAVE_SDCC_2, QCS615_SLAVE_SNOC_CFG,
+ QCS615_SLAVE_SPDM_WRAPPER, QCS615_SLAVE_TCSR,
+ QCS615_SLAVE_TLMM_EAST, QCS615_SLAVE_TLMM_SOUTH,
+ QCS615_SLAVE_TLMM_WEST, QCS615_SLAVE_UFS_MEM_CFG,
+ QCS615_SLAVE_USB2, QCS615_SLAVE_USB3,
+ QCS615_SLAVE_VENUS_CFG, QCS615_SLAVE_VSENSE_CTRL_CFG,
+ QCS615_SLAVE_SERVICE_CNOC },
+};
+
+static struct qcom_icc_node xm_qdss_dap = {
+ .name = "xm_qdss_dap",
+ .id = QCS615_MASTER_QDSS_DAP,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 40,
+ .links = { QCS615_SLAVE_A1NOC_CFG, QCS615_SLAVE_AHB2PHY_EAST,
+ QCS615_SLAVE_AHB2PHY_WEST, QCS615_SLAVE_AOP,
+ QCS615_SLAVE_AOSS, QCS615_SLAVE_CAMERA_CFG,
+ QCS615_SLAVE_CLK_CTL, QCS615_SLAVE_RBCPR_CX_CFG,
+ QCS615_SLAVE_RBCPR_MX_CFG, QCS615_SLAVE_CRYPTO_0_CFG,
+ QCS615_SLAVE_CNOC_DDRSS, QCS615_SLAVE_DISPLAY_CFG,
+ QCS615_SLAVE_EMAC_AVB_CFG, QCS615_SLAVE_GLM,
+ QCS615_SLAVE_GFX3D_CFG, QCS615_SLAVE_IMEM_CFG,
+ QCS615_SLAVE_IPA_CFG, QCS615_SLAVE_CNOC_MNOC_CFG,
+ QCS615_SLAVE_PCIE_CFG, QCS615_SLAVE_PIMEM_CFG,
+ QCS615_SLAVE_PRNG, QCS615_SLAVE_QDSS_CFG,
+ QCS615_SLAVE_QSPI, QCS615_SLAVE_QUP_0,
+ QCS615_SLAVE_QUP_1, QCS615_SLAVE_SDCC_1,
+ QCS615_SLAVE_SDCC_2, QCS615_SLAVE_SNOC_CFG,
+ QCS615_SLAVE_SPDM_WRAPPER, QCS615_SLAVE_TCSR,
+ QCS615_SLAVE_TLMM_EAST, QCS615_SLAVE_TLMM_SOUTH,
+ QCS615_SLAVE_TLMM_WEST, QCS615_SLAVE_UFS_MEM_CFG,
+ QCS615_SLAVE_USB2, QCS615_SLAVE_USB3,
+ QCS615_SLAVE_VENUS_CFG, QCS615_SLAVE_VSENSE_CTRL_CFG,
+ QCS615_SLAVE_CNOC_A2NOC, QCS615_SLAVE_SERVICE_CNOC },
+};
+
+static struct qcom_icc_node qhm_cnoc = {
+ .name = "qhm_cnoc",
+ .id = QCS615_MASTER_CNOC_DC_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_DC_NOC_GEMNOC, QCS615_SLAVE_LLCC_CFG },
+};
+
+static struct qcom_icc_node acm_apps = {
+ .name = "acm_apps",
+ .id = QCS615_MASTER_APPSS_PROC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 3,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC,
+ QCS615_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node acm_gpu_tcu = {
+ .name = "acm_gpu_tcu",
+ .id = QCS615_MASTER_GPU_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node acm_sys_tcu = {
+ .name = "acm_sys_tcu",
+ .id = QCS615_MASTER_SYS_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qhm_gemnoc_cfg = {
+ .name = "qhm_gemnoc_cfg",
+ .id = QCS615_MASTER_GEM_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_MSS_PROC_MS_MPU_CFG, QCS615_SLAVE_SERVICE_GEM_NOC },
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .id = QCS615_MASTER_GFX3D,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_mnoc_hf = {
+ .name = "qnm_mnoc_hf",
+ .id = QCS615_MASTER_MNOC_HF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_mnoc_sf = {
+ .name = "qnm_mnoc_sf",
+ .id = QCS615_MASTER_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_GEM_NOC_SNOC, QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_gc = {
+ .name = "qnm_snoc_gc",
+ .id = QCS615_MASTER_SNOC_GC_MEM_NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_sf = {
+ .name = "qnm_snoc_sf",
+ .id = QCS615_MASTER_SNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node ipa_core_master = {
+ .name = "ipa_core_master",
+ .id = QCS615_MASTER_IPA_CORE,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_IPA_CORE },
+};
+
+static struct qcom_icc_node llcc_mc = {
+ .name = "llcc_mc",
+ .id = QCS615_MASTER_LLCC,
+ .channels = 2,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_EBI1 },
+};
+
+static struct qcom_icc_node qhm_mnoc_cfg = {
+ .name = "qhm_mnoc_cfg",
+ .id = QCS615_MASTER_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_SERVICE_MNOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf0 = {
+ .name = "qxm_camnoc_hf0",
+ .id = QCS615_MASTER_CAMNOC_HF0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_hf1 = {
+ .name = "qxm_camnoc_hf1",
+ .id = QCS615_MASTER_CAMNOC_HF1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_camnoc_sf = {
+ .name = "qxm_camnoc_sf",
+ .id = QCS615_MASTER_CAMNOC_SF,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_mdp0 = {
+ .name = "qxm_mdp0",
+ .id = QCS615_MASTER_MDP0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_rot = {
+ .name = "qxm_rot",
+ .id = QCS615_MASTER_ROTATOR,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_venus0 = {
+ .name = "qxm_venus0",
+ .id = QCS615_MASTER_VIDEO_P0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qxm_venus_arm9 = {
+ .name = "qxm_venus_arm9",
+ .id = QCS615_MASTER_VIDEO_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qhm_snoc_cfg = {
+ .name = "qhm_snoc_cfg",
+ .id = QCS615_MASTER_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_SERVICE_SNOC },
+};
+
+static struct qcom_icc_node qnm_aggre1_noc = {
+ .name = "qnm_aggre1_noc",
+ .id = QCS615_MASTER_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 8,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_SNOC_GEM_NOC_SF, QCS615_SLAVE_IMEM,
+ QCS615_SLAVE_PIMEM, QCS615_SLAVE_PCIE_0,
+ QCS615_SLAVE_QDSS_STM, QCS615_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc = {
+ .name = "qnm_gemnoc",
+ .id = QCS615_MASTER_GEM_NOC_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 6,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_IMEM, QCS615_SLAVE_PIMEM,
+ QCS615_SLAVE_QDSS_STM, QCS615_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc_pcie = {
+ .name = "qnm_gemnoc_pcie",
+ .id = QCS615_MASTER_GEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_SLAVE_PCIE_0 },
+};
+
+static struct qcom_icc_node qnm_lpass_anoc = {
+ .name = "qnm_lpass_anoc",
+ .id = QCS615_MASTER_LPASS_ANOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 7,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_SNOC_GEM_NOC_SF, QCS615_SLAVE_IMEM,
+ QCS615_SLAVE_PIMEM, QCS615_SLAVE_PCIE_0,
+ QCS615_SLAVE_QDSS_STM },
+};
+
+static struct qcom_icc_node qnm_pcie_anoc = {
+ .name = "qnm_pcie_anoc",
+ .id = QCS615_MASTER_ANOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 5,
+ .links = { QCS615_SLAVE_APPSS, QCS615_SLAVE_SNOC_CNOC,
+ QCS615_SLAVE_SNOC_GEM_NOC_SF, QCS615_SLAVE_IMEM,
+ QCS615_SLAVE_QDSS_STM },
+};
+
+static struct qcom_icc_node qxm_pimem = {
+ .name = "qxm_pimem",
+ .id = QCS615_MASTER_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_SNOC_MEM_NOC_GC, QCS615_SLAVE_IMEM },
+};
+
+static struct qcom_icc_node xm_gic = {
+ .name = "xm_gic",
+ .id = QCS615_MASTER_GIC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS615_SLAVE_SNOC_MEM_NOC_GC, QCS615_SLAVE_IMEM },
+};
+
+static struct qcom_icc_node qns_a1noc_snoc = {
+ .name = "qns_a1noc_snoc",
+ .id = QCS615_SLAVE_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_MASTER_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_lpass_snoc = {
+ .name = "qns_lpass_snoc",
+ .id = QCS615_SLAVE_LPASS_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_LPASS_ANOC },
+};
+
+static struct qcom_icc_node qns_pcie_snoc = {
+ .name = "qns_pcie_snoc",
+ .id = QCS615_SLAVE_ANOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_ANOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node srvc_aggre2_noc = {
+ .name = "srvc_aggre2_noc",
+ .id = QCS615_SLAVE_SERVICE_A2NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_camnoc_uncomp = {
+ .name = "qns_camnoc_uncomp",
+ .id = QCS615_SLAVE_CAMNOC_UNCOMP,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_a1_noc_cfg = {
+ .name = "qhs_a1_noc_cfg",
+ .id = QCS615_SLAVE_A1NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_A1NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_ahb2phy_east = {
+ .name = "qhs_ahb2phy_east",
+ .id = QCS615_SLAVE_AHB2PHY_EAST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy_west = {
+ .name = "qhs_ahb2phy_west",
+ .id = QCS615_SLAVE_AHB2PHY_WEST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aop = {
+ .name = "qhs_aop",
+ .id = QCS615_SLAVE_AOP,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aoss = {
+ .name = "qhs_aoss",
+ .id = QCS615_SLAVE_AOSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_cfg = {
+ .name = "qhs_camera_cfg",
+ .id = QCS615_SLAVE_CAMERA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .id = QCS615_SLAVE_CLK_CTL,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_cx = {
+ .name = "qhs_cpr_cx",
+ .id = QCS615_SLAVE_RBCPR_CX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mx = {
+ .name = "qhs_cpr_mx",
+ .id = QCS615_SLAVE_RBCPR_MX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .id = QCS615_SLAVE_CRYPTO_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ddrss_cfg = {
+ .name = "qhs_ddrss_cfg",
+ .id = QCS615_SLAVE_CNOC_DDRSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_CNOC_DC_NOC },
+};
+
+static struct qcom_icc_node qhs_display_cfg = {
+ .name = "qhs_display_cfg",
+ .id = QCS615_SLAVE_DISPLAY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_emac_avb_cfg = {
+ .name = "qhs_emac_avb_cfg",
+ .id = QCS615_SLAVE_EMAC_AVB_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_glm = {
+ .name = "qhs_glm",
+ .id = QCS615_SLAVE_GLM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpuss_cfg = {
+ .name = "qhs_gpuss_cfg",
+ .id = QCS615_SLAVE_GFX3D_CFG,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .id = QCS615_SLAVE_IMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipa = {
+ .name = "qhs_ipa",
+ .id = QCS615_SLAVE_IPA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mnoc_cfg = {
+ .name = "qhs_mnoc_cfg",
+ .id = QCS615_SLAVE_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_CNOC_MNOC_CFG },
+};
+
+static struct qcom_icc_node qhs_pcie_config = {
+ .name = "qhs_pcie_config",
+ .id = QCS615_SLAVE_PCIE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pimem_cfg = {
+ .name = "qhs_pimem_cfg",
+ .id = QCS615_SLAVE_PIMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_prng = {
+ .name = "qhs_prng",
+ .id = QCS615_SLAVE_PRNG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .id = QCS615_SLAVE_QDSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qspi = {
+ .name = "qhs_qspi",
+ .id = QCS615_SLAVE_QSPI,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup0 = {
+ .name = "qhs_qup0",
+ .id = QCS615_SLAVE_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup1 = {
+ .name = "qhs_qup1",
+ .id = QCS615_SLAVE_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc1 = {
+ .name = "qhs_sdc1",
+ .id = QCS615_SLAVE_SDCC_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc2 = {
+ .name = "qhs_sdc2",
+ .id = QCS615_SLAVE_SDCC_2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_snoc_cfg = {
+ .name = "qhs_snoc_cfg",
+ .id = QCS615_SLAVE_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_CFG },
+};
+
+static struct qcom_icc_node qhs_spdm = {
+ .name = "qhs_spdm",
+ .id = QCS615_SLAVE_SPDM_WRAPPER,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .id = QCS615_SLAVE_TCSR,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm_east = {
+ .name = "qhs_tlmm_east",
+ .id = QCS615_SLAVE_TLMM_EAST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm_south = {
+ .name = "qhs_tlmm_south",
+ .id = QCS615_SLAVE_TLMM_SOUTH,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm_west = {
+ .name = "qhs_tlmm_west",
+ .id = QCS615_SLAVE_TLMM_WEST,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ufs_mem_cfg = {
+ .name = "qhs_ufs_mem_cfg",
+ .id = QCS615_SLAVE_UFS_MEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb2 = {
+ .name = "qhs_usb2",
+ .id = QCS615_SLAVE_USB2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb3 = {
+ .name = "qhs_usb3",
+ .id = QCS615_SLAVE_USB3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .id = QCS615_SLAVE_VENUS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_vsense_ctrl_cfg = {
+ .name = "qhs_vsense_ctrl_cfg",
+ .id = QCS615_SLAVE_VSENSE_CTRL_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_cnoc_a2noc = {
+ .name = "qns_cnoc_a2noc",
+ .id = QCS615_SLAVE_CNOC_A2NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_CNOC_A2NOC },
+};
+
+static struct qcom_icc_node srvc_cnoc = {
+ .name = "srvc_cnoc",
+ .id = QCS615_SLAVE_SERVICE_CNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_dc_noc_gemnoc = {
+ .name = "qhs_dc_noc_gemnoc",
+ .id = QCS615_SLAVE_DC_NOC_GEMNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS615_MASTER_GEM_NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_llcc = {
+ .name = "qhs_llcc",
+ .id = QCS615_SLAVE_LLCC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mdsp_ms_mpu_cfg = {
+ .name = "qhs_mdsp_ms_mpu_cfg",
+ .id = QCS615_SLAVE_MSS_PROC_MS_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gem_noc_snoc = {
+ .name = "qns_gem_noc_snoc",
+ .id = QCS615_SLAVE_GEM_NOC_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_GEM_NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_llcc = {
+ .name = "qns_llcc",
+ .id = QCS615_SLAVE_LLCC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_MASTER_LLCC },
+};
+
+static struct qcom_icc_node qns_sys_pcie = {
+ .name = "qns_sys_pcie",
+ .id = QCS615_SLAVE_MEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_GEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node srvc_gemnoc = {
+ .name = "srvc_gemnoc",
+ .id = QCS615_SLAVE_SERVICE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ipa_core_slave = {
+ .name = "ipa_core_slave",
+ .id = QCS615_SLAVE_IPA_CORE,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .id = QCS615_SLAVE_EBI1,
+ .channels = 2,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns2_mem_noc = {
+ .name = "qns2_mem_noc",
+ .id = QCS615_SLAVE_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_MASTER_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_mem_noc_hf = {
+ .name = "qns_mem_noc_hf",
+ .id = QCS615_SLAVE_MNOC_HF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS615_MASTER_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_mnoc = {
+ .name = "srvc_mnoc",
+ .id = QCS615_SLAVE_SERVICE_MNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_apss = {
+ .name = "qhs_apss",
+ .id = QCS615_SLAVE_APPSS,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_cnoc = {
+ .name = "qns_cnoc",
+ .id = QCS615_SLAVE_SNOC_CNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_CNOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_sf = {
+ .name = "qns_gemnoc_sf",
+ .id = QCS615_SLAVE_SNOC_GEM_NOC_SF,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_memnoc_gc = {
+ .name = "qns_memnoc_gc",
+ .id = QCS615_SLAVE_SNOC_MEM_NOC_GC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS615_MASTER_SNOC_GC_MEM_NOC },
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .id = QCS615_SLAVE_IMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_pimem = {
+ .name = "qxs_pimem",
+ .id = QCS615_SLAVE_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_snoc = {
+ .name = "srvc_snoc",
+ .id = QCS615_SLAVE_SERVICE_SNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie = {
+ .name = "xs_pcie",
+ .id = QCS615_SLAVE_PCIE_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .id = QCS615_SLAVE_QDSS_STM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .id = QCS615_SLAVE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_bcm bcm_acv = {
+ .name = "ACV",
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 1,
+ .nodes = { &qxm_crypto },
+};
+
+static struct qcom_icc_bcm bcm_cn0 = {
+ .name = "CN0",
+ .keepalive = true,
+ .num_nodes = 37,
+ .nodes = { &qhm_spdm, &qnm_snoc,
+ &qhs_a1_noc_cfg, &qhs_aop,
+ &qhs_aoss, &qhs_camera_cfg,
+ &qhs_clk_ctl, &qhs_cpr_cx,
+ &qhs_cpr_mx, &qhs_crypto0_cfg,
+ &qhs_ddrss_cfg, &qhs_display_cfg,
+ &qhs_emac_avb_cfg, &qhs_glm,
+ &qhs_gpuss_cfg, &qhs_imem_cfg,
+ &qhs_ipa, &qhs_mnoc_cfg,
+ &qhs_pcie_config, &qhs_pimem_cfg,
+ &qhs_prng, &qhs_qdss_cfg,
+ &qhs_qup0, &qhs_qup1,
+ &qhs_snoc_cfg, &qhs_spdm,
+ &qhs_tcsr, &qhs_tlmm_east,
+ &qhs_tlmm_south, &qhs_tlmm_west,
+ &qhs_ufs_mem_cfg, &qhs_usb2,
+ &qhs_usb3, &qhs_venus_cfg,
+ &qhs_vsense_ctrl_cfg, &qns_cnoc_a2noc,
+ &srvc_cnoc },
+};
+
+static struct qcom_icc_bcm bcm_cn1 = {
+ .name = "CN1",
+ .num_nodes = 8,
+ .nodes = { &qhm_qspi, &xm_sdc1,
+ &xm_sdc2, &qhs_ahb2phy_east,
+ &qhs_ahb2phy_west, &qhs_qspi,
+ &qhs_sdc1, &qhs_sdc2 },
+};
+
+static struct qcom_icc_bcm bcm_ip0 = {
+ .name = "IP0",
+ .num_nodes = 1,
+ .nodes = { &ipa_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_mc0 = {
+ .name = "MC0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_mm0 = {
+ .name = "MM0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_bcm bcm_mm1 = {
+ .name = "MM1",
+ .num_nodes = 7,
+ .nodes = { &qxm_camnoc_hf0_uncomp, &qxm_camnoc_hf1_uncomp,
+ &qxm_camnoc_sf_uncomp, &qxm_camnoc_hf0,
+ &qxm_camnoc_hf1, &qxm_mdp0,
+ &qxm_rot },
+};
+
+static struct qcom_icc_bcm bcm_mm2 = {
+ .name = "MM2",
+ .num_nodes = 2,
+ .nodes = { &qxm_camnoc_sf, &qns2_mem_noc },
+};
+
+static struct qcom_icc_bcm bcm_mm3 = {
+ .name = "MM3",
+ .num_nodes = 2,
+ .nodes = { &qxm_venus0, &qxm_venus_arm9 },
+};
+
+static struct qcom_icc_bcm bcm_qup0 = {
+ .name = "QUP0",
+ .keepalive = true,
+ .vote_scale = 1,
+ .num_nodes = 2,
+ .nodes = { &qhm_qup0, &qhm_qup1 },
+};
+
+static struct qcom_icc_bcm bcm_sh0 = {
+ .name = "SH0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_bcm bcm_sh2 = {
+ .name = "SH2",
+ .num_nodes = 1,
+ .nodes = { &acm_apps },
+};
+
+static struct qcom_icc_bcm bcm_sh3 = {
+ .name = "SH3",
+ .num_nodes = 1,
+ .nodes = { &qns_gem_noc_snoc },
+};
+
+static struct qcom_icc_bcm bcm_sn0 = {
+ .name = "SN0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_bcm bcm_sn1 = {
+ .name = "SN1",
+ .num_nodes = 1,
+ .nodes = { &qxs_imem },
+};
+
+static struct qcom_icc_bcm bcm_sn2 = {
+ .name = "SN2",
+ .num_nodes = 1,
+ .nodes = { &qns_memnoc_gc },
+};
+
+static struct qcom_icc_bcm bcm_sn3 = {
+ .name = "SN3",
+ .num_nodes = 2,
+ .nodes = { &srvc_aggre2_noc, &qns_cnoc },
+};
+
+static struct qcom_icc_bcm bcm_sn4 = {
+ .name = "SN4",
+ .num_nodes = 1,
+ .nodes = { &qxs_pimem },
+};
+
+static struct qcom_icc_bcm bcm_sn5 = {
+ .name = "SN5",
+ .num_nodes = 1,
+ .nodes = { &xs_qdss_stm },
+};
+
+static struct qcom_icc_bcm bcm_sn8 = {
+ .name = "SN8",
+ .num_nodes = 2,
+ .nodes = { &qnm_gemnoc_pcie, &xs_pcie },
+};
+
+static struct qcom_icc_bcm bcm_sn9 = {
+ .name = "SN9",
+ .num_nodes = 1,
+ .nodes = { &qnm_aggre1_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn12 = {
+ .name = "SN12",
+ .num_nodes = 2,
+ .nodes = { &qxm_pimem, &xm_gic },
+};
+
+static struct qcom_icc_bcm bcm_sn13 = {
+ .name = "SN13",
+ .num_nodes = 1,
+ .nodes = { &qnm_lpass_anoc },
+};
+
+static struct qcom_icc_bcm bcm_sn14 = {
+ .name = "SN14",
+ .num_nodes = 1,
+ .nodes = { &qns_pcie_snoc },
+};
+
+static struct qcom_icc_bcm bcm_sn15 = {
+ .name = "SN15",
+ .num_nodes = 1,
+ .nodes = { &qnm_gemnoc },
+};
+
+static struct qcom_icc_bcm * const aggre1_noc_bcms[] = {
+ &bcm_ce0,
+ &bcm_cn1,
+ &bcm_qup0,
+ &bcm_sn3,
+ &bcm_sn14,
+ &bcm_ip0,
+};
+
+static struct qcom_icc_node * const aggre1_noc_nodes[] = {
+ [MASTER_A1NOC_CFG] = &qhm_a1noc_cfg,
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_QSPI] = &qhm_qspi,
+ [MASTER_QUP_0] = &qhm_qup0,
+ [MASTER_BLSP_1] = &qhm_qup1,
+ [MASTER_CNOC_A2NOC] = &qnm_cnoc,
+ [MASTER_CRYPTO] = &qxm_crypto,
+ [MASTER_IPA] = &qxm_ipa,
+ [MASTER_EMAC_EVB] = &xm_emac_avb,
+ [MASTER_PCIE] = &xm_pcie,
+ [MASTER_QDSS_ETR] = &xm_qdss_etr,
+ [MASTER_SDCC_1] = &xm_sdc1,
+ [MASTER_SDCC_2] = &xm_sdc2,
+ [MASTER_UFS_MEM] = &xm_ufs_mem,
+ [MASTER_USB2] = &xm_usb2,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc,
+ [SLAVE_LPASS_SNOC] = &qns_lpass_snoc,
+ [SLAVE_ANOC_PCIE_SNOC] = &qns_pcie_snoc,
+ [SLAVE_SERVICE_A2NOC] = &srvc_aggre2_noc,
+};
+
+static const struct qcom_icc_desc qcs615_aggre1_noc = {
+ .nodes = aggre1_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
+ .bcms = aggre1_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const camnoc_virt_bcms[] = {
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const camnoc_virt_nodes[] = {
+ [MASTER_CAMNOC_HF0_UNCOMP] = &qxm_camnoc_hf0_uncomp,
+ [MASTER_CAMNOC_HF1_UNCOMP] = &qxm_camnoc_hf1_uncomp,
+ [MASTER_CAMNOC_SF_UNCOMP] = &qxm_camnoc_sf_uncomp,
+ [SLAVE_CAMNOC_UNCOMP] = &qns_camnoc_uncomp,
+};
+
+static const struct qcom_icc_desc qcs615_camnoc_virt = {
+ .nodes = camnoc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(camnoc_virt_nodes),
+ .bcms = camnoc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(camnoc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const config_noc_bcms[] = {
+ &bcm_cn0,
+ &bcm_cn1,
+};
+
+static struct qcom_icc_node * const config_noc_nodes[] = {
+ [MASTER_SPDM] = &qhm_spdm,
+ [MASTER_SNOC_CNOC] = &qnm_snoc,
+ [MASTER_QDSS_DAP] = &xm_qdss_dap,
+ [SLAVE_A1NOC_CFG] = &qhs_a1_noc_cfg,
+ [SLAVE_AHB2PHY_EAST] = &qhs_ahb2phy_east,
+ [SLAVE_AHB2PHY_WEST] = &qhs_ahb2phy_west,
+ [SLAVE_AOP] = &qhs_aop,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_RBCPR_MX_CFG] = &qhs_cpr_mx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_CNOC_DDRSS] = &qhs_ddrss_cfg,
+ [SLAVE_DISPLAY_CFG] = &qhs_display_cfg,
+ [SLAVE_EMAC_AVB_CFG] = &qhs_emac_avb_cfg,
+ [SLAVE_GLM] = &qhs_glm,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPA_CFG] = &qhs_ipa,
+ [SLAVE_CNOC_MNOC_CFG] = &qhs_mnoc_cfg,
+ [SLAVE_PCIE_CFG] = &qhs_pcie_config,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PRNG] = &qhs_prng,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QSPI] = &qhs_qspi,
+ [SLAVE_QUP_0] = &qhs_qup0,
+ [SLAVE_QUP_1] = &qhs_qup1,
+ [SLAVE_SDCC_1] = &qhs_sdc1,
+ [SLAVE_SDCC_2] = &qhs_sdc2,
+ [SLAVE_SNOC_CFG] = &qhs_snoc_cfg,
+ [SLAVE_SPDM_WRAPPER] = &qhs_spdm,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM_EAST] = &qhs_tlmm_east,
+ [SLAVE_TLMM_SOUTH] = &qhs_tlmm_south,
+ [SLAVE_TLMM_WEST] = &qhs_tlmm_west,
+ [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg,
+ [SLAVE_USB2] = &qhs_usb2,
+ [SLAVE_USB3] = &qhs_usb3,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg,
+ [SLAVE_CNOC_A2NOC] = &qns_cnoc_a2noc,
+ [SLAVE_SERVICE_CNOC] = &srvc_cnoc,
+};
+
+static const struct qcom_icc_desc qcs615_config_noc = {
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .bcms = config_noc_bcms,
+ .num_bcms = ARRAY_SIZE(config_noc_bcms),
+};
+
+static struct qcom_icc_node * const dc_noc_nodes[] = {
+ [MASTER_CNOC_DC_NOC] = &qhm_cnoc,
+ [SLAVE_DC_NOC_GEMNOC] = &qhs_dc_noc_gemnoc,
+ [SLAVE_LLCC_CFG] = &qhs_llcc,
+};
+
+static const struct qcom_icc_desc qcs615_dc_noc = {
+ .nodes = dc_noc_nodes,
+ .num_nodes = ARRAY_SIZE(dc_noc_nodes),
+};
+
+static struct qcom_icc_bcm * const gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh2,
+ &bcm_sh3,
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const gem_noc_nodes[] = {
+ [MASTER_APPSS_PROC] = &acm_apps,
+ [MASTER_GPU_TCU] = &acm_gpu_tcu,
+ [MASTER_SYS_TCU] = &acm_sys_tcu,
+ [MASTER_GEM_NOC_CFG] = &qhm_gemnoc_cfg,
+ [MASTER_GFX3D] = &qnm_gpu,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [SLAVE_MSS_PROC_MS_MPU_CFG] = &qhs_mdsp_ms_mpu_cfg,
+ [SLAVE_GEM_NOC_SNOC] = &qns_gem_noc_snoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_sys_pcie,
+ [SLAVE_SERVICE_GEM_NOC] = &srvc_gemnoc,
+};
+
+static const struct qcom_icc_desc qcs615_gem_noc = {
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const ipa_virt_bcms[] = {
+ &bcm_ip0,
+};
+
+static struct qcom_icc_node * const ipa_virt_nodes[] = {
+ [MASTER_IPA_CORE] = &ipa_core_master,
+ [SLAVE_IPA_CORE] = &ipa_core_slave,
+};
+
+static const struct qcom_icc_desc qcs615_ipa_virt = {
+ .nodes = ipa_virt_nodes,
+ .num_nodes = ARRAY_SIZE(ipa_virt_nodes),
+ .bcms = ipa_virt_bcms,
+ .num_bcms = ARRAY_SIZE(ipa_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mc_virt_bcms[] = {
+ &bcm_acv,
+ &bcm_mc0,
+};
+
+static struct qcom_icc_node * const mc_virt_nodes[] = {
+ [MASTER_LLCC] = &llcc_mc,
+ [SLAVE_EBI1] = &ebi,
+};
+
+static const struct qcom_icc_desc qcs615_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+ &bcm_mm2,
+ &bcm_mm3,
+};
+
+static struct qcom_icc_node * const mmss_noc_nodes[] = {
+ [MASTER_CNOC_MNOC_CFG] = &qhm_mnoc_cfg,
+ [MASTER_CAMNOC_HF0] = &qxm_camnoc_hf0,
+ [MASTER_CAMNOC_HF1] = &qxm_camnoc_hf1,
+ [MASTER_CAMNOC_SF] = &qxm_camnoc_sf,
+ [MASTER_MDP0] = &qxm_mdp0,
+ [MASTER_ROTATOR] = &qxm_rot,
+ [MASTER_VIDEO_P0] = &qxm_venus0,
+ [MASTER_VIDEO_PROC] = &qxm_venus_arm9,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns2_mem_noc,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_SERVICE_MNOC] = &srvc_mnoc,
+};
+
+static const struct qcom_icc_desc qcs615_mmss_noc = {
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const system_noc_bcms[] = {
+ &bcm_sn0,
+ &bcm_sn1,
+ &bcm_sn2,
+ &bcm_sn3,
+ &bcm_sn4,
+ &bcm_sn5,
+ &bcm_sn8,
+ &bcm_sn9,
+ &bcm_sn12,
+ &bcm_sn13,
+ &bcm_sn15,
+};
+
+static struct qcom_icc_node * const system_noc_nodes[] = {
+ [MASTER_SNOC_CFG] = &qhm_snoc_cfg,
+ [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc,
+ [MASTER_GEM_NOC_SNOC] = &qnm_gemnoc,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie,
+ [MASTER_LPASS_ANOC] = &qnm_lpass_anoc,
+ [MASTER_ANOC_PCIE_SNOC] = &qnm_pcie_anoc,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_GIC] = &xm_gic,
+ [SLAVE_APPSS] = &qhs_apss,
+ [SLAVE_SNOC_CNOC] = &qns_cnoc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf,
+ [SLAVE_SNOC_MEM_NOC_GC] = &qns_memnoc_gc,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+ [SLAVE_PCIE_0] = &xs_pcie,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc qcs615_system_noc = {
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,qcs615-aggre1-noc",
+ .data = &qcs615_aggre1_noc},
+ { .compatible = "qcom,qcs615-camnoc-virt",
+ .data = &qcs615_camnoc_virt},
+ { .compatible = "qcom,qcs615-config-noc",
+ .data = &qcs615_config_noc},
+ { .compatible = "qcom,qcs615-dc-noc",
+ .data = &qcs615_dc_noc},
+ { .compatible = "qcom,qcs615-gem-noc",
+ .data = &qcs615_gem_noc},
+ { .compatible = "qcom,qcs615-ipa-virt",
+ .data = &qcs615_ipa_virt},
+ { .compatible = "qcom,qcs615-mc-virt",
+ .data = &qcs615_mc_virt},
+ { .compatible = "qcom,qcs615-mmss-noc",
+ .data = &qcs615_mmss_noc},
+ { .compatible = "qcom,qcs615-system-noc",
+ .data = &qcs615_system_noc},
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
+ .driver = {
+ .name = "qnoc-qcs615",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+module_exit(qnoc_driver_exit);
+
+MODULE_DESCRIPTION("qcs615 NoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/qcs615.h b/drivers/interconnect/qcom/qcs615.h
new file mode 100644
index 000000000000..66e66c7e23d4
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs615.h
@@ -0,0 +1,128 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __DRIVERS_INTERCONNECT_QCOM_QCS615_H
+#define __DRIVERS_INTERCONNECT_QCOM_QCS615_H
+
+#define QCS615_MASTER_A1NOC_CFG 1
+#define QCS615_MASTER_A1NOC_SNOC 2
+#define QCS615_MASTER_ANOC_PCIE_SNOC 3
+#define QCS615_MASTER_APPSS_PROC 4
+#define QCS615_MASTER_BLSP_1 5
+#define QCS615_MASTER_CAMNOC_HF0 6
+#define QCS615_MASTER_CAMNOC_HF0_UNCOMP 7
+#define QCS615_MASTER_CAMNOC_HF1 8
+#define QCS615_MASTER_CAMNOC_HF1_UNCOMP 9
+#define QCS615_MASTER_CAMNOC_SF 10
+#define QCS615_MASTER_CAMNOC_SF_UNCOMP 11
+#define QCS615_MASTER_CNOC_A2NOC 12
+#define QCS615_MASTER_CNOC_DC_NOC 13
+#define QCS615_MASTER_CNOC_MNOC_CFG 14
+#define QCS615_MASTER_CRYPTO 15
+#define QCS615_MASTER_EMAC_EVB 16
+#define QCS615_MASTER_GEM_NOC_CFG 17
+#define QCS615_MASTER_GEM_NOC_PCIE_SNOC 18
+#define QCS615_MASTER_GEM_NOC_SNOC 19
+#define QCS615_MASTER_GFX3D 20
+#define QCS615_MASTER_GIC 21
+#define QCS615_MASTER_GPU_TCU 22
+#define QCS615_MASTER_IPA 23
+#define QCS615_MASTER_IPA_CORE 24
+#define QCS615_MASTER_LLCC 25
+#define QCS615_MASTER_LPASS_ANOC 26
+#define QCS615_MASTER_MDP0 27
+#define QCS615_MASTER_MNOC_HF_MEM_NOC 28
+#define QCS615_MASTER_MNOC_SF_MEM_NOC 29
+#define QCS615_MASTER_PCIE 30
+#define QCS615_MASTER_PIMEM 31
+#define QCS615_MASTER_QDSS_BAM 32
+#define QCS615_MASTER_QDSS_DAP 33
+#define QCS615_MASTER_QDSS_ETR 34
+#define QCS615_MASTER_QSPI 35
+#define QCS615_MASTER_QUP_0 36
+#define QCS615_MASTER_ROTATOR 37
+#define QCS615_MASTER_SDCC_1 38
+#define QCS615_MASTER_SDCC_2 39
+#define QCS615_MASTER_SNOC_CFG 40
+#define QCS615_MASTER_SNOC_CNOC 41
+#define QCS615_MASTER_SNOC_GC_MEM_NOC 42
+#define QCS615_MASTER_SNOC_SF_MEM_NOC 43
+#define QCS615_MASTER_SPDM 44
+#define QCS615_MASTER_SYS_TCU 45
+#define QCS615_MASTER_UFS_MEM 46
+#define QCS615_MASTER_USB2 47
+#define QCS615_MASTER_USB3_0 48
+#define QCS615_MASTER_VIDEO_P0 49
+#define QCS615_MASTER_VIDEO_PROC 50
+#define QCS615_SLAVE_A1NOC_CFG 51
+#define QCS615_SLAVE_A1NOC_SNOC 52
+#define QCS615_SLAVE_AHB2PHY_EAST 53
+#define QCS615_SLAVE_AHB2PHY_WEST 54
+#define QCS615_SLAVE_ANOC_PCIE_SNOC 55
+#define QCS615_SLAVE_AOP 56
+#define QCS615_SLAVE_AOSS 57
+#define QCS615_SLAVE_APPSS 58
+#define QCS615_SLAVE_CAMERA_CFG 59
+#define QCS615_SLAVE_CAMNOC_UNCOMP 60
+#define QCS615_SLAVE_CLK_CTL 61
+#define QCS615_SLAVE_CNOC_A2NOC 62
+#define QCS615_SLAVE_CNOC_DDRSS 63
+#define QCS615_SLAVE_CNOC_MNOC_CFG 64
+#define QCS615_SLAVE_CRYPTO_0_CFG 65
+#define QCS615_SLAVE_DC_NOC_GEMNOC 66
+#define QCS615_SLAVE_DISPLAY_CFG 67
+#define QCS615_SLAVE_EBI1 68
+#define QCS615_SLAVE_EMAC_AVB_CFG 69
+#define QCS615_SLAVE_GEM_NOC_SNOC 70
+#define QCS615_SLAVE_GFX3D_CFG 71
+#define QCS615_SLAVE_GLM 72
+#define QCS615_SLAVE_IMEM 73
+#define QCS615_SLAVE_IMEM_CFG 74
+#define QCS615_SLAVE_IPA_CFG 75
+#define QCS615_SLAVE_IPA_CORE 76
+#define QCS615_SLAVE_LLCC 77
+#define QCS615_SLAVE_LLCC_CFG 78
+#define QCS615_SLAVE_LPASS_SNOC 79
+#define QCS615_SLAVE_MEM_NOC_PCIE_SNOC 80
+#define QCS615_SLAVE_MNOC_HF_MEM_NOC 81
+#define QCS615_SLAVE_MNOC_SF_MEM_NOC 82
+#define QCS615_SLAVE_MSS_PROC_MS_MPU_CFG 83
+#define QCS615_SLAVE_PCIE_0 84
+#define QCS615_SLAVE_PCIE_CFG 85
+#define QCS615_SLAVE_PIMEM 86
+#define QCS615_SLAVE_PIMEM_CFG 87
+#define QCS615_SLAVE_PRNG 88
+#define QCS615_SLAVE_QDSS_CFG 89
+#define QCS615_SLAVE_QDSS_STM 90
+#define QCS615_SLAVE_QSPI 91
+#define QCS615_SLAVE_QUP_0 92
+#define QCS615_SLAVE_QUP_1 93
+#define QCS615_SLAVE_RBCPR_CX_CFG 94
+#define QCS615_SLAVE_RBCPR_MX_CFG 95
+#define QCS615_SLAVE_SDCC_1 96
+#define QCS615_SLAVE_SDCC_2 97
+#define QCS615_SLAVE_SERVICE_A2NOC 98
+#define QCS615_SLAVE_SERVICE_CNOC 99
+#define QCS615_SLAVE_SERVICE_GEM_NOC 100
+#define QCS615_SLAVE_SERVICE_MNOC 101
+#define QCS615_SLAVE_SERVICE_SNOC 102
+#define QCS615_SLAVE_SNOC_CFG 103
+#define QCS615_SLAVE_SNOC_CNOC 104
+#define QCS615_SLAVE_SNOC_GEM_NOC_SF 105
+#define QCS615_SLAVE_SNOC_MEM_NOC_GC 106
+#define QCS615_SLAVE_SPDM_WRAPPER 107
+#define QCS615_SLAVE_TCSR 108
+#define QCS615_SLAVE_TCU 109
+#define QCS615_SLAVE_TLMM_EAST 110
+#define QCS615_SLAVE_TLMM_SOUTH 111
+#define QCS615_SLAVE_TLMM_WEST 112
+#define QCS615_SLAVE_UFS_MEM_CFG 113
+#define QCS615_SLAVE_USB2 114
+#define QCS615_SLAVE_USB3 115
+#define QCS615_SLAVE_VENUS_CFG 116
+#define QCS615_SLAVE_VSENSE_CTRL_CFG 117
+
+#endif
+
diff --git a/drivers/interconnect/qcom/qcs8300.c b/drivers/interconnect/qcom/qcs8300.c
new file mode 100644
index 000000000000..e7a1b2fc69ba
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs8300.c
@@ -0,0 +1,2088 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ *
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <dt-bindings/interconnect/qcom,qcs8300-rpmh.h>
+
+#include "bcm-voter.h"
+#include "icc-rpmh.h"
+#include "qcs8300.h"
+
+static struct qcom_icc_node qxm_qup3 = {
+ .name = "qxm_qup3",
+ .id = QCS8300_MASTER_QUP_3,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_emac_0 = {
+ .name = "xm_emac_0",
+ .id = QCS8300_MASTER_EMAC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .id = QCS8300_MASTER_SDC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_ufs_mem = {
+ .name = "xm_ufs_mem",
+ .id = QCS8300_MASTER_UFS_MEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb2_2 = {
+ .name = "xm_usb2_2",
+ .id = QCS8300_MASTER_USB2,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .id = QCS8300_MASTER_USB3_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qdss_bam = {
+ .name = "qhm_qdss_bam",
+ .id = QCS8300_MASTER_QDSS_BAM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup0 = {
+ .name = "qhm_qup0",
+ .id = QCS8300_MASTER_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qhm_qup1 = {
+ .name = "qhm_qup1",
+ .id = QCS8300_MASTER_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qnm_cnoc_datapath = {
+ .name = "qnm_cnoc_datapath",
+ .id = QCS8300_MASTER_CNOC_A2NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_crypto_0 = {
+ .name = "qxm_crypto_0",
+ .id = QCS8300_MASTER_CRYPTO_CORE0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_crypto_1 = {
+ .name = "qxm_crypto_1",
+ .id = QCS8300_MASTER_CRYPTO_CORE1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qxm_ipa = {
+ .name = "qxm_ipa",
+ .id = QCS8300_MASTER_IPA,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_qdss_etr_0 = {
+ .name = "xm_qdss_etr_0",
+ .id = QCS8300_MASTER_QDSS_ETR_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node xm_qdss_etr_1 = {
+ .name = "xm_qdss_etr_1",
+ .id = QCS8300_MASTER_QDSS_ETR_1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qup0_core_master = {
+ .name = "qup0_core_master",
+ .id = QCS8300_MASTER_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_QUP_CORE_0 },
+};
+
+static struct qcom_icc_node qup1_core_master = {
+ .name = "qup1_core_master",
+ .id = QCS8300_MASTER_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_QUP_CORE_1 },
+};
+
+static struct qcom_icc_node qup3_core_master = {
+ .name = "qup3_core_master",
+ .id = QCS8300_MASTER_QUP_CORE_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_QUP_CORE_3 },
+};
+
+static struct qcom_icc_node qnm_gemnoc_cnoc = {
+ .name = "qnm_gemnoc_cnoc",
+ .id = QCS8300_MASTER_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 71,
+ .links = { QCS8300_SLAVE_AHB2PHY_2, QCS8300_SLAVE_AHB2PHY_3,
+ QCS8300_SLAVE_ANOC_THROTTLE_CFG, QCS8300_SLAVE_AOSS,
+ QCS8300_SLAVE_APPSS, QCS8300_SLAVE_BOOT_ROM,
+ QCS8300_SLAVE_CAMERA_CFG, QCS8300_SLAVE_CAMERA_NRT_THROTTLE_CFG,
+ QCS8300_SLAVE_CAMERA_RT_THROTTLE_CFG, QCS8300_SLAVE_CLK_CTL,
+ QCS8300_SLAVE_CDSP_CFG, QCS8300_SLAVE_RBCPR_CX_CFG,
+ QCS8300_SLAVE_RBCPR_MMCX_CFG, QCS8300_SLAVE_RBCPR_MX_CFG,
+ QCS8300_SLAVE_CPR_NSPCX, QCS8300_SLAVE_CPR_NSPHMX,
+ QCS8300_SLAVE_CRYPTO_0_CFG, QCS8300_SLAVE_CX_RDPM,
+ QCS8300_SLAVE_DISPLAY_CFG, QCS8300_SLAVE_DISPLAY_RT_THROTTLE_CFG,
+ QCS8300_SLAVE_EMAC_CFG, QCS8300_SLAVE_GP_DSP0_CFG,
+ QCS8300_SLAVE_GPDSP0_THROTTLE_CFG, QCS8300_SLAVE_GPU_TCU_THROTTLE_CFG,
+ QCS8300_SLAVE_GFX3D_CFG, QCS8300_SLAVE_HWKM,
+ QCS8300_SLAVE_IMEM_CFG, QCS8300_SLAVE_IPA_CFG,
+ QCS8300_SLAVE_IPC_ROUTER_CFG, QCS8300_SLAVE_LPASS,
+ QCS8300_SLAVE_LPASS_THROTTLE_CFG, QCS8300_SLAVE_MX_RDPM,
+ QCS8300_SLAVE_MXC_RDPM, QCS8300_SLAVE_PCIE_0_CFG,
+ QCS8300_SLAVE_PCIE_1_CFG, QCS8300_SLAVE_PCIE_TCU_THROTTLE_CFG,
+ QCS8300_SLAVE_PCIE_THROTTLE_CFG, QCS8300_SLAVE_PDM,
+ QCS8300_SLAVE_PIMEM_CFG, QCS8300_SLAVE_PKA_WRAPPER_CFG,
+ QCS8300_SLAVE_QDSS_CFG, QCS8300_SLAVE_QM_CFG,
+ QCS8300_SLAVE_QM_MPU_CFG, QCS8300_SLAVE_QUP_0,
+ QCS8300_SLAVE_QUP_1, QCS8300_SLAVE_QUP_3,
+ QCS8300_SLAVE_SAIL_THROTTLE_CFG, QCS8300_SLAVE_SDC1,
+ QCS8300_SLAVE_SECURITY, QCS8300_SLAVE_SNOC_THROTTLE_CFG,
+ QCS8300_SLAVE_TCSR, QCS8300_SLAVE_TLMM,
+ QCS8300_SLAVE_TSC_CFG, QCS8300_SLAVE_UFS_MEM_CFG,
+ QCS8300_SLAVE_USB2, QCS8300_SLAVE_USB3_0,
+ QCS8300_SLAVE_VENUS_CFG, QCS8300_SLAVE_VENUS_CVP_THROTTLE_CFG,
+ QCS8300_SLAVE_VENUS_V_CPU_THROTTLE_CFG,
+ QCS8300_SLAVE_VENUS_VCODEC_THROTTLE_CFG,
+ QCS8300_SLAVE_DDRSS_CFG, QCS8300_SLAVE_GPDSP_NOC_CFG,
+ QCS8300_SLAVE_CNOC_MNOC_HF_CFG, QCS8300_SLAVE_CNOC_MNOC_SF_CFG,
+ QCS8300_SLAVE_PCIE_ANOC_CFG, QCS8300_SLAVE_SNOC_CFG,
+ QCS8300_SLAVE_BOOT_IMEM, QCS8300_SLAVE_IMEM,
+ QCS8300_SLAVE_PIMEM, QCS8300_SLAVE_QDSS_STM,
+ QCS8300_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc_pcie = {
+ .name = "qnm_gemnoc_pcie",
+ .id = QCS8300_MASTER_GEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_PCIE_0, QCS8300_SLAVE_PCIE_1 },
+};
+
+static struct qcom_icc_node qnm_cnoc_dc_noc = {
+ .name = "qnm_cnoc_dc_noc",
+ .id = QCS8300_MASTER_CNOC_DC_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_LLCC_CFG, QCS8300_SLAVE_GEM_NOC_CFG },
+};
+
+static struct qcom_icc_node alm_gpu_tcu = {
+ .name = "alm_gpu_tcu",
+ .id = QCS8300_MASTER_GPU_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node alm_pcie_tcu = {
+ .name = "alm_pcie_tcu",
+ .id = QCS8300_MASTER_PCIE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node alm_sys_tcu = {
+ .name = "alm_sys_tcu",
+ .id = QCS8300_MASTER_SYS_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node chm_apps = {
+ .name = "chm_apps",
+ .id = QCS8300_MASTER_APPSS_PROC,
+ .channels = 4,
+ .buswidth = 32,
+ .num_links = 3,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC,
+ QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_cmpnoc0 = {
+ .name = "qnm_cmpnoc0",
+ .id = QCS8300_MASTER_COMPUTE_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_gemnoc_cfg = {
+ .name = "qnm_gemnoc_cfg",
+ .id = QCS8300_MASTER_GEM_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 4,
+ .links = { QCS8300_SLAVE_SERVICE_GEM_NOC_1, QCS8300_SLAVE_SERVICE_GEM_NOC_2,
+ QCS8300_SLAVE_SERVICE_GEM_NOC, QCS8300_SLAVE_SERVICE_GEM_NOC2 },
+};
+
+static struct qcom_icc_node qnm_gpdsp_sail = {
+ .name = "qnm_gpdsp_sail",
+ .id = QCS8300_MASTER_GPDSP_SAIL,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .id = QCS8300_MASTER_GFX3D,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_mnoc_hf = {
+ .name = "qnm_mnoc_hf",
+ .id = QCS8300_MASTER_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_LLCC, QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_mnoc_sf = {
+ .name = "qnm_mnoc_sf",
+ .id = QCS8300_MASTER_MNOC_SF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 3,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC,
+ QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_pcie = {
+ .name = "qnm_pcie",
+ .id = QCS8300_MASTER_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_gc = {
+ .name = "qnm_snoc_gc",
+ .id = QCS8300_MASTER_SNOC_GC_MEM_NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node qnm_snoc_sf = {
+ .name = "qnm_snoc_sf",
+ .id = QCS8300_MASTER_SNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 3,
+ .links = { QCS8300_SLAVE_GEM_NOC_CNOC, QCS8300_SLAVE_LLCC,
+ QCS8300_SLAVE_GEM_NOC_PCIE_CNOC },
+};
+
+static struct qcom_icc_node qnm_sailss_md0 = {
+ .name = "qnm_sailss_md0",
+ .id = QCS8300_MASTER_SAILSS_MD0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_GP_DSP_SAIL_NOC },
+};
+
+static struct qcom_icc_node qxm_dsp0 = {
+ .name = "qxm_dsp0",
+ .id = QCS8300_MASTER_DSP0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_GP_DSP_SAIL_NOC },
+};
+
+static struct qcom_icc_node qhm_config_noc = {
+ .name = "qhm_config_noc",
+ .id = QCS8300_MASTER_CNOC_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 6,
+ .links = { QCS8300_SLAVE_LPASS_CORE_CFG, QCS8300_SLAVE_LPASS_LPI_CFG,
+ QCS8300_SLAVE_LPASS_MPU_CFG, QCS8300_SLAVE_LPASS_TOP_CFG,
+ QCS8300_SLAVE_SERVICES_LPASS_AML_NOC, QCS8300_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qxm_lpass_dsp = {
+ .name = "qxm_lpass_dsp",
+ .id = QCS8300_MASTER_LPASS_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 4,
+ .links = { QCS8300_SLAVE_LPASS_TOP_CFG, QCS8300_SLAVE_LPASS_SNOC,
+ QCS8300_SLAVE_SERVICES_LPASS_AML_NOC, QCS8300_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node llcc_mc = {
+ .name = "llcc_mc",
+ .id = QCS8300_MASTER_LLCC,
+ .channels = 8,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_EBI1 },
+};
+
+static struct qcom_icc_node qnm_camnoc_hf = {
+ .name = "qnm_camnoc_hf",
+ .id = QCS8300_MASTER_CAMNOC_HF,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_camnoc_icp = {
+ .name = "qnm_camnoc_icp",
+ .id = QCS8300_MASTER_CAMNOC_ICP,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_camnoc_sf = {
+ .name = "qnm_camnoc_sf",
+ .id = QCS8300_MASTER_CAMNOC_SF,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mdp0_0 = {
+ .name = "qnm_mdp0_0",
+ .id = QCS8300_MASTER_MDP0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mdp0_1 = {
+ .name = "qnm_mdp0_1",
+ .id = QCS8300_MASTER_MDP1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mnoc_hf_cfg = {
+ .name = "qnm_mnoc_hf_cfg",
+ .id = QCS8300_MASTER_CNOC_MNOC_HF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_MNOC_HF },
+};
+
+static struct qcom_icc_node qnm_mnoc_sf_cfg = {
+ .name = "qnm_mnoc_sf_cfg",
+ .id = QCS8300_MASTER_CNOC_MNOC_SF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_MNOC_SF },
+};
+
+static struct qcom_icc_node qnm_video0 = {
+ .name = "qnm_video0",
+ .id = QCS8300_MASTER_VIDEO_P0,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_video_cvp = {
+ .name = "qnm_video_cvp",
+ .id = QCS8300_MASTER_VIDEO_PROC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_video_v_cpu = {
+ .name = "qnm_video_v_cpu",
+ .id = QCS8300_MASTER_VIDEO_V_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qhm_nsp_noc_config = {
+ .name = "qhm_nsp_noc_config",
+ .id = QCS8300_MASTER_CDSP_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_NSP_NOC },
+};
+
+static struct qcom_icc_node qxm_nsp = {
+ .name = "qxm_nsp",
+ .id = QCS8300_MASTER_CDSP_PROC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 2,
+ .links = { QCS8300_SLAVE_HCP_A, QCS8300_SLAVE_CDSP_MEM_NOC },
+};
+
+static struct qcom_icc_node xm_pcie3_0 = {
+ .name = "xm_pcie3_0",
+ .id = QCS8300_MASTER_PCIE_0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node xm_pcie3_1 = {
+ .name = "xm_pcie3_1",
+ .id = QCS8300_MASTER_PCIE_1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node qhm_gic = {
+ .name = "qhm_gic",
+ .id = QCS8300_MASTER_GIC_AHB,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_aggre1_noc = {
+ .name = "qnm_aggre1_noc",
+ .id = QCS8300_MASTER_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_aggre2_noc = {
+ .name = "qnm_aggre2_noc",
+ .id = QCS8300_MASTER_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_lpass_noc = {
+ .name = "qnm_lpass_noc",
+ .id = QCS8300_MASTER_LPASS_ANOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_snoc_cfg = {
+ .name = "qnm_snoc_cfg",
+ .id = QCS8300_MASTER_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SERVICE_SNOC },
+};
+
+static struct qcom_icc_node qxm_pimem = {
+ .name = "qxm_pimem",
+ .id = QCS8300_MASTER_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static struct qcom_icc_node xm_gic = {
+ .name = "xm_gic",
+ .id = QCS8300_MASTER_GIC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static struct qcom_icc_node qns_a1noc_snoc = {
+ .name = "qns_a1noc_snoc",
+ .id = QCS8300_SLAVE_A1NOC_SNOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_A1NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_a2noc_snoc = {
+ .name = "qns_a2noc_snoc",
+ .id = QCS8300_SLAVE_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qup0_core_slave = {
+ .name = "qup0_core_slave",
+ .id = QCS8300_SLAVE_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qup1_core_slave = {
+ .name = "qup1_core_slave",
+ .id = QCS8300_SLAVE_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qup3_core_slave = {
+ .name = "qup3_core_slave",
+ .id = QCS8300_SLAVE_QUP_CORE_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy2 = {
+ .name = "qhs_ahb2phy2",
+ .id = QCS8300_SLAVE_AHB2PHY_2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy3 = {
+ .name = "qhs_ahb2phy3",
+ .id = QCS8300_SLAVE_AHB2PHY_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_anoc_throttle_cfg = {
+ .name = "qhs_anoc_throttle_cfg",
+ .id = QCS8300_SLAVE_ANOC_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aoss = {
+ .name = "qhs_aoss",
+ .id = QCS8300_SLAVE_AOSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_apss = {
+ .name = "qhs_apss",
+ .id = QCS8300_SLAVE_APPSS,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_boot_rom = {
+ .name = "qhs_boot_rom",
+ .id = QCS8300_SLAVE_BOOT_ROM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_cfg = {
+ .name = "qhs_camera_cfg",
+ .id = QCS8300_SLAVE_CAMERA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_nrt_throttle_cfg = {
+ .name = "qhs_camera_nrt_throttle_cfg",
+ .id = QCS8300_SLAVE_CAMERA_NRT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_rt_throttle_cfg = {
+ .name = "qhs_camera_rt_throttle_cfg",
+ .id = QCS8300_SLAVE_CAMERA_RT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .id = QCS8300_SLAVE_CLK_CTL,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_compute0_cfg = {
+ .name = "qhs_compute0_cfg",
+ .id = QCS8300_SLAVE_CDSP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CDSP_NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_cpr_cx = {
+ .name = "qhs_cpr_cx",
+ .id = QCS8300_SLAVE_RBCPR_CX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mmcx = {
+ .name = "qhs_cpr_mmcx",
+ .id = QCS8300_SLAVE_RBCPR_MMCX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mx = {
+ .name = "qhs_cpr_mx",
+ .id = QCS8300_SLAVE_RBCPR_MX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_nspcx = {
+ .name = "qhs_cpr_nspcx",
+ .id = QCS8300_SLAVE_CPR_NSPCX,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_nsphmx = {
+ .name = "qhs_cpr_nsphmx",
+ .id = QCS8300_SLAVE_CPR_NSPHMX,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .id = QCS8300_SLAVE_CRYPTO_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cx_rdpm = {
+ .name = "qhs_cx_rdpm",
+ .id = QCS8300_SLAVE_CX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_display0_cfg = {
+ .name = "qhs_display0_cfg",
+ .id = QCS8300_SLAVE_DISPLAY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_display0_rt_throttle_cfg = {
+ .name = "qhs_display0_rt_throttle_cfg",
+ .id = QCS8300_SLAVE_DISPLAY_RT_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_emac0_cfg = {
+ .name = "qhs_emac0_cfg",
+ .id = QCS8300_SLAVE_EMAC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gp_dsp0_cfg = {
+ .name = "qhs_gp_dsp0_cfg",
+ .id = QCS8300_SLAVE_GP_DSP0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpdsp0_throttle_cfg = {
+ .name = "qhs_gpdsp0_throttle_cfg",
+ .id = QCS8300_SLAVE_GPDSP0_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpu_tcu_throttle_cfg = {
+ .name = "qhs_gpu_tcu_throttle_cfg",
+ .id = QCS8300_SLAVE_GPU_TCU_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpuss_cfg = {
+ .name = "qhs_gpuss_cfg",
+ .id = QCS8300_SLAVE_GFX3D_CFG,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_hwkm = {
+ .name = "qhs_hwkm",
+ .id = QCS8300_SLAVE_HWKM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .id = QCS8300_SLAVE_IMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipa = {
+ .name = "qhs_ipa",
+ .id = QCS8300_SLAVE_IPA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipc_router = {
+ .name = "qhs_ipc_router",
+ .id = QCS8300_SLAVE_IPC_ROUTER_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_cfg = {
+ .name = "qhs_lpass_cfg",
+ .id = QCS8300_SLAVE_LPASS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qhs_lpass_throttle_cfg = {
+ .name = "qhs_lpass_throttle_cfg",
+ .id = QCS8300_SLAVE_LPASS_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mx_rdpm = {
+ .name = "qhs_mx_rdpm",
+ .id = QCS8300_SLAVE_MX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_mxc_rdpm = {
+ .name = "qhs_mxc_rdpm",
+ .id = QCS8300_SLAVE_MXC_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie0_cfg = {
+ .name = "qhs_pcie0_cfg",
+ .id = QCS8300_SLAVE_PCIE_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie1_cfg = {
+ .name = "qhs_pcie1_cfg",
+ .id = QCS8300_SLAVE_PCIE_1_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie_tcu_throttle_cfg = {
+ .name = "qhs_pcie_tcu_throttle_cfg",
+ .id = QCS8300_SLAVE_PCIE_TCU_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie_throttle_cfg = {
+ .name = "qhs_pcie_throttle_cfg",
+ .id = QCS8300_SLAVE_PCIE_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pdm = {
+ .name = "qhs_pdm",
+ .id = QCS8300_SLAVE_PDM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pimem_cfg = {
+ .name = "qhs_pimem_cfg",
+ .id = QCS8300_SLAVE_PIMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pke_wrapper_cfg = {
+ .name = "qhs_pke_wrapper_cfg",
+ .id = QCS8300_SLAVE_PKA_WRAPPER_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .id = QCS8300_SLAVE_QDSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qm_cfg = {
+ .name = "qhs_qm_cfg",
+ .id = QCS8300_SLAVE_QM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qm_mpu_cfg = {
+ .name = "qhs_qm_mpu_cfg",
+ .id = QCS8300_SLAVE_QM_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup0 = {
+ .name = "qhs_qup0",
+ .id = QCS8300_SLAVE_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup1 = {
+ .name = "qhs_qup1",
+ .id = QCS8300_SLAVE_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup3 = {
+ .name = "qhs_qup3",
+ .id = QCS8300_SLAVE_QUP_3,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sail_throttle_cfg = {
+ .name = "qhs_sail_throttle_cfg",
+ .id = QCS8300_SLAVE_SAIL_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc1 = {
+ .name = "qhs_sdc1",
+ .id = QCS8300_SLAVE_SDC1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_security = {
+ .name = "qhs_security",
+ .id = QCS8300_SLAVE_SECURITY,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_snoc_throttle_cfg = {
+ .name = "qhs_snoc_throttle_cfg",
+ .id = QCS8300_SLAVE_SNOC_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .id = QCS8300_SLAVE_TCSR,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm = {
+ .name = "qhs_tlmm",
+ .id = QCS8300_SLAVE_TLMM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tsc_cfg = {
+ .name = "qhs_tsc_cfg",
+ .id = QCS8300_SLAVE_TSC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ufs_mem_cfg = {
+ .name = "qhs_ufs_mem_cfg",
+ .id = QCS8300_SLAVE_UFS_MEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb2_0 = {
+ .name = "qhs_usb2_0",
+ .id = QCS8300_SLAVE_USB2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb3_0 = {
+ .name = "qhs_usb3_0",
+ .id = QCS8300_SLAVE_USB3_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .id = QCS8300_SLAVE_VENUS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cvp_throttle_cfg = {
+ .name = "qhs_venus_cvp_throttle_cfg",
+ .id = QCS8300_SLAVE_VENUS_CVP_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_v_cpu_throttle_cfg = {
+ .name = "qhs_venus_v_cpu_throttle_cfg",
+ .id = QCS8300_SLAVE_VENUS_V_CPU_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_vcodec_throttle_cfg = {
+ .name = "qhs_venus_vcodec_throttle_cfg",
+ .id = QCS8300_SLAVE_VENUS_VCODEC_THROTTLE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_ddrss_cfg = {
+ .name = "qns_ddrss_cfg",
+ .id = QCS8300_SLAVE_DDRSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_DC_NOC },
+};
+
+static struct qcom_icc_node qns_gpdsp_noc_cfg = {
+ .name = "qns_gpdsp_noc_cfg",
+ .id = QCS8300_SLAVE_GPDSP_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mnoc_hf_cfg = {
+ .name = "qns_mnoc_hf_cfg",
+ .id = QCS8300_SLAVE_CNOC_MNOC_HF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_MNOC_HF_CFG },
+};
+
+static struct qcom_icc_node qns_mnoc_sf_cfg = {
+ .name = "qns_mnoc_sf_cfg",
+ .id = QCS8300_SLAVE_CNOC_MNOC_SF_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_CNOC_MNOC_SF_CFG },
+};
+
+static struct qcom_icc_node qns_pcie_anoc_cfg = {
+ .name = "qns_pcie_anoc_cfg",
+ .id = QCS8300_SLAVE_PCIE_ANOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_snoc_cfg = {
+ .name = "qns_snoc_cfg",
+ .id = QCS8300_SLAVE_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_SNOC_CFG },
+};
+
+static struct qcom_icc_node qxs_boot_imem = {
+ .name = "qxs_boot_imem",
+ .id = QCS8300_SLAVE_BOOT_IMEM,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .id = QCS8300_SLAVE_IMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_pimem = {
+ .name = "qxs_pimem",
+ .id = QCS8300_SLAVE_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_0 = {
+ .name = "xs_pcie_0",
+ .id = QCS8300_SLAVE_PCIE_0,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_1 = {
+ .name = "xs_pcie_1",
+ .id = QCS8300_SLAVE_PCIE_1,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .id = QCS8300_SLAVE_QDSS_STM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .id = QCS8300_SLAVE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_llcc = {
+ .name = "qhs_llcc",
+ .id = QCS8300_SLAVE_LLCC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gemnoc = {
+ .name = "qns_gemnoc",
+ .id = QCS8300_SLAVE_GEM_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GEM_NOC_CFG },
+};
+
+static struct qcom_icc_node qns_gem_noc_cnoc = {
+ .name = "qns_gem_noc_cnoc",
+ .id = QCS8300_SLAVE_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GEM_NOC_CNOC },
+};
+
+static struct qcom_icc_node qns_llcc = {
+ .name = "qns_llcc",
+ .id = QCS8300_SLAVE_LLCC,
+ .channels = 4,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_LLCC },
+};
+
+static struct qcom_icc_node qns_pcie = {
+ .name = "qns_pcie",
+ .id = QCS8300_SLAVE_GEM_NOC_PCIE_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node srvc_even_gemnoc = {
+ .name = "srvc_even_gemnoc",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_odd_gemnoc = {
+ .name = "srvc_odd_gemnoc",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC_2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_sys_gemnoc = {
+ .name = "srvc_sys_gemnoc",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_sys_gemnoc_2 = {
+ .name = "srvc_sys_gemnoc_2",
+ .id = QCS8300_SLAVE_SERVICE_GEM_NOC2,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gp_dsp_sail_noc = {
+ .name = "qns_gp_dsp_sail_noc",
+ .id = QCS8300_SLAVE_GP_DSP_SAIL_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_GPDSP_SAIL },
+};
+
+static struct qcom_icc_node qhs_lpass_core = {
+ .name = "qhs_lpass_core",
+ .id = QCS8300_SLAVE_LPASS_CORE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_lpi = {
+ .name = "qhs_lpass_lpi",
+ .id = QCS8300_SLAVE_LPASS_LPI_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_mpu = {
+ .name = "qhs_lpass_mpu",
+ .id = QCS8300_SLAVE_LPASS_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_top = {
+ .name = "qhs_lpass_top",
+ .id = QCS8300_SLAVE_LPASS_TOP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_sysnoc = {
+ .name = "qns_sysnoc",
+ .id = QCS8300_SLAVE_LPASS_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_LPASS_ANOC },
+};
+
+static struct qcom_icc_node srvc_niu_aml_noc = {
+ .name = "srvc_niu_aml_noc",
+ .id = QCS8300_SLAVE_SERVICES_LPASS_AML_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_niu_lpass_agnoc = {
+ .name = "srvc_niu_lpass_agnoc",
+ .id = QCS8300_SLAVE_SERVICE_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .id = QCS8300_SLAVE_EBI1,
+ .channels = 8,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mem_noc_hf = {
+ .name = "qns_mem_noc_hf",
+ .id = QCS8300_SLAVE_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_mem_noc_sf = {
+ .name = "qns_mem_noc_sf",
+ .id = QCS8300_SLAVE_MNOC_SF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_mnoc_hf = {
+ .name = "srvc_mnoc_hf",
+ .id = QCS8300_SLAVE_SERVICE_MNOC_HF,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_mnoc_sf = {
+ .name = "srvc_mnoc_sf",
+ .id = QCS8300_SLAVE_SERVICE_MNOC_SF,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_hcp = {
+ .name = "qns_hcp",
+ .id = QCS8300_SLAVE_HCP_A,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_nsp_gemnoc = {
+ .name = "qns_nsp_gemnoc",
+ .id = QCS8300_SLAVE_CDSP_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_COMPUTE_NOC },
+};
+
+static struct qcom_icc_node service_nsp_noc = {
+ .name = "service_nsp_noc",
+ .id = QCS8300_SLAVE_SERVICE_NSP_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_pcie_mem_noc = {
+ .name = "qns_pcie_mem_noc",
+ .id = QCS8300_SLAVE_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_gc = {
+ .name = "qns_gemnoc_gc",
+ .id = QCS8300_SLAVE_SNOC_GEM_NOC_GC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_SNOC_GC_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_sf = {
+ .name = "qns_gemnoc_sf",
+ .id = QCS8300_SLAVE_SNOC_GEM_NOC_SF,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { QCS8300_MASTER_SNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_snoc = {
+ .name = "srvc_snoc",
+ .id = QCS8300_SLAVE_SERVICE_SNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_bcm bcm_acv = {
+ .name = "ACV",
+ .enable_mask = BIT(3),
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 2,
+ .nodes = { &qxm_crypto_0, &qxm_crypto_1 },
+};
+
+static struct qcom_icc_bcm bcm_cn0 = {
+ .name = "CN0",
+ .keepalive = true,
+ .num_nodes = 2,
+ .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie },
+};
+
+static struct qcom_icc_bcm bcm_cn1 = {
+ .name = "CN1",
+ .num_nodes = 66,
+ .nodes = { &qhs_ahb2phy2, &qhs_ahb2phy3,
+ &qhs_anoc_throttle_cfg, &qhs_aoss,
+ &qhs_apss, &qhs_boot_rom,
+ &qhs_camera_cfg, &qhs_camera_nrt_throttle_cfg,
+ &qhs_camera_rt_throttle_cfg, &qhs_clk_ctl,
+ &qhs_compute0_cfg, &qhs_cpr_cx,
+ &qhs_cpr_mmcx, &qhs_cpr_mx,
+ &qhs_cpr_nspcx, &qhs_cpr_nsphmx,
+ &qhs_crypto0_cfg, &qhs_cx_rdpm,
+ &qhs_display0_cfg, &qhs_display0_rt_throttle_cfg,
+ &qhs_emac0_cfg, &qhs_gp_dsp0_cfg,
+ &qhs_gpdsp0_throttle_cfg, &qhs_gpu_tcu_throttle_cfg,
+ &qhs_gpuss_cfg, &qhs_hwkm,
+ &qhs_imem_cfg, &qhs_ipa,
+ &qhs_ipc_router, &qhs_lpass_cfg,
+ &qhs_lpass_throttle_cfg, &qhs_mx_rdpm,
+ &qhs_mxc_rdpm, &qhs_pcie0_cfg,
+ &qhs_pcie1_cfg, &qhs_pcie_tcu_throttle_cfg,
+ &qhs_pcie_throttle_cfg, &qhs_pdm,
+ &qhs_pimem_cfg, &qhs_pke_wrapper_cfg,
+ &qhs_qdss_cfg, &qhs_qm_cfg,
+ &qhs_qm_mpu_cfg, &qhs_sail_throttle_cfg,
+ &qhs_sdc1, &qhs_security,
+ &qhs_snoc_throttle_cfg, &qhs_tcsr,
+ &qhs_tlmm, &qhs_tsc_cfg,
+ &qhs_ufs_mem_cfg, &qhs_usb2_0,
+ &qhs_usb3_0, &qhs_venus_cfg,
+ &qhs_venus_cvp_throttle_cfg, &qhs_venus_v_cpu_throttle_cfg,
+ &qhs_venus_vcodec_throttle_cfg, &qns_ddrss_cfg,
+ &qns_gpdsp_noc_cfg, &qns_mnoc_hf_cfg,
+ &qns_mnoc_sf_cfg, &qns_pcie_anoc_cfg,
+ &qns_snoc_cfg, &qxs_boot_imem,
+ &qxs_imem, &xs_sys_tcu_cfg },
+};
+
+static struct qcom_icc_bcm bcm_cn2 = {
+ .name = "CN2",
+ .num_nodes = 3,
+ .nodes = { &qhs_qup0, &qhs_qup1,
+ &qhs_qup3 },
+};
+
+static struct qcom_icc_bcm bcm_cn3 = {
+ .name = "CN3",
+ .num_nodes = 2,
+ .nodes = { &xs_pcie_0, &xs_pcie_1 },
+};
+
+static struct qcom_icc_bcm bcm_gna0 = {
+ .name = "GNA0",
+ .num_nodes = 1,
+ .nodes = { &qxm_dsp0 },
+};
+
+static struct qcom_icc_bcm bcm_mc0 = {
+ .name = "MC0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_mm0 = {
+ .name = "MM0",
+ .keepalive = true,
+ .num_nodes = 4,
+ .nodes = { &qnm_camnoc_hf, &qnm_mdp0_0,
+ &qnm_mdp0_1, &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_bcm bcm_mm1 = {
+ .name = "MM1",
+ .num_nodes = 6,
+ .nodes = { &qnm_camnoc_icp, &qnm_camnoc_sf,
+ &qnm_video0, &qnm_video_cvp,
+ &qnm_video_v_cpu, &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_bcm bcm_nsa0 = {
+ .name = "NSA0",
+ .num_nodes = 2,
+ .nodes = { &qns_hcp, &qns_nsp_gemnoc },
+};
+
+static struct qcom_icc_bcm bcm_nsa1 = {
+ .name = "NSA1",
+ .num_nodes = 1,
+ .nodes = { &qxm_nsp },
+};
+
+static struct qcom_icc_bcm bcm_pci0 = {
+ .name = "PCI0",
+ .num_nodes = 1,
+ .nodes = { &qns_pcie_mem_noc },
+};
+
+static struct qcom_icc_bcm bcm_qup0 = {
+ .name = "QUP0",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup0_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_qup1 = {
+ .name = "QUP1",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup1_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_qup2 = {
+ .name = "QUP2",
+ .vote_scale = 1,
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qup3_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_sh0 = {
+ .name = "SH0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_bcm bcm_sh2 = {
+ .name = "SH2",
+ .num_nodes = 1,
+ .nodes = { &chm_apps },
+};
+
+static struct qcom_icc_bcm bcm_sn0 = {
+ .name = "SN0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_bcm bcm_sn1 = {
+ .name = "SN1",
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_gc },
+};
+
+static struct qcom_icc_bcm bcm_sn2 = {
+ .name = "SN2",
+ .num_nodes = 1,
+ .nodes = { &qxs_pimem },
+};
+
+static struct qcom_icc_bcm bcm_sn3 = {
+ .name = "SN3",
+ .num_nodes = 2,
+ .nodes = { &qns_a1noc_snoc, &qnm_aggre1_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn4 = {
+ .name = "SN4",
+ .num_nodes = 2,
+ .nodes = { &qns_a2noc_snoc, &qnm_aggre2_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn9 = {
+ .name = "SN9",
+ .num_nodes = 2,
+ .nodes = { &qns_sysnoc, &qnm_lpass_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn10 = {
+ .name = "SN10",
+ .num_nodes = 1,
+ .nodes = { &xs_qdss_stm },
+};
+
+static struct qcom_icc_bcm * const aggre1_noc_bcms[] = {
+ &bcm_sn3,
+};
+
+static struct qcom_icc_node * const aggre1_noc_nodes[] = {
+ [MASTER_QUP_3] = &qxm_qup3,
+ [MASTER_EMAC] = &xm_emac_0,
+ [MASTER_SDC] = &xm_sdc1,
+ [MASTER_UFS_MEM] = &xm_ufs_mem,
+ [MASTER_USB2] = &xm_usb2_2,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [SLAVE_A1NOC_SNOC] = &qns_a1noc_snoc,
+};
+
+static const struct qcom_icc_desc qcs8300_aggre1_noc = {
+ .nodes = aggre1_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
+ .bcms = aggre1_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const aggre2_noc_bcms[] = {
+ &bcm_ce0,
+ &bcm_sn4,
+};
+
+static struct qcom_icc_node * const aggre2_noc_nodes[] = {
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_QUP_0] = &qhm_qup0,
+ [MASTER_QUP_1] = &qhm_qup1,
+ [MASTER_CNOC_A2NOC] = &qnm_cnoc_datapath,
+ [MASTER_CRYPTO_CORE0] = &qxm_crypto_0,
+ [MASTER_CRYPTO_CORE1] = &qxm_crypto_1,
+ [MASTER_IPA] = &qxm_ipa,
+ [MASTER_QDSS_ETR_0] = &xm_qdss_etr_0,
+ [MASTER_QDSS_ETR_1] = &xm_qdss_etr_1,
+ [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc,
+};
+
+static const struct qcom_icc_desc qcs8300_aggre2_noc = {
+ .nodes = aggre2_noc_nodes,
+ .num_nodes = ARRAY_SIZE(aggre2_noc_nodes),
+ .bcms = aggre2_noc_bcms,
+ .num_bcms = ARRAY_SIZE(aggre2_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const clk_virt_bcms[] = {
+ &bcm_qup0,
+ &bcm_qup1,
+ &bcm_qup2,
+};
+
+static struct qcom_icc_node * const clk_virt_nodes[] = {
+ [MASTER_QUP_CORE_0] = &qup0_core_master,
+ [MASTER_QUP_CORE_1] = &qup1_core_master,
+ [MASTER_QUP_CORE_3] = &qup3_core_master,
+ [SLAVE_QUP_CORE_0] = &qup0_core_slave,
+ [SLAVE_QUP_CORE_1] = &qup1_core_slave,
+ [SLAVE_QUP_CORE_3] = &qup3_core_slave,
+};
+
+static const struct qcom_icc_desc qcs8300_clk_virt = {
+ .nodes = clk_virt_nodes,
+ .num_nodes = ARRAY_SIZE(clk_virt_nodes),
+ .bcms = clk_virt_bcms,
+ .num_bcms = ARRAY_SIZE(clk_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const config_noc_bcms[] = {
+ &bcm_cn0,
+ &bcm_cn1,
+ &bcm_cn2,
+ &bcm_cn3,
+ &bcm_sn2,
+ &bcm_sn10,
+};
+
+static struct qcom_icc_node * const config_noc_nodes[] = {
+ [MASTER_GEM_NOC_CNOC] = &qnm_gemnoc_cnoc,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie,
+ [SLAVE_AHB2PHY_2] = &qhs_ahb2phy2,
+ [SLAVE_AHB2PHY_3] = &qhs_ahb2phy3,
+ [SLAVE_ANOC_THROTTLE_CFG] = &qhs_anoc_throttle_cfg,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_APPSS] = &qhs_apss,
+ [SLAVE_BOOT_ROM] = &qhs_boot_rom,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CAMERA_NRT_THROTTLE_CFG] = &qhs_camera_nrt_throttle_cfg,
+ [SLAVE_CAMERA_RT_THROTTLE_CFG] = &qhs_camera_rt_throttle_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_CDSP_CFG] = &qhs_compute0_cfg,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_RBCPR_MMCX_CFG] = &qhs_cpr_mmcx,
+ [SLAVE_RBCPR_MX_CFG] = &qhs_cpr_mx,
+ [SLAVE_CPR_NSPCX] = &qhs_cpr_nspcx,
+ [SLAVE_CPR_NSPHMX] = &qhs_cpr_nsphmx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_CX_RDPM] = &qhs_cx_rdpm,
+ [SLAVE_DISPLAY_CFG] = &qhs_display0_cfg,
+ [SLAVE_DISPLAY_RT_THROTTLE_CFG] = &qhs_display0_rt_throttle_cfg,
+ [SLAVE_EMAC_CFG] = &qhs_emac0_cfg,
+ [SLAVE_GP_DSP0_CFG] = &qhs_gp_dsp0_cfg,
+ [SLAVE_GPDSP0_THROTTLE_CFG] = &qhs_gpdsp0_throttle_cfg,
+ [SLAVE_GPU_TCU_THROTTLE_CFG] = &qhs_gpu_tcu_throttle_cfg,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_HWKM] = &qhs_hwkm,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPA_CFG] = &qhs_ipa,
+ [SLAVE_IPC_ROUTER_CFG] = &qhs_ipc_router,
+ [SLAVE_LPASS] = &qhs_lpass_cfg,
+ [SLAVE_LPASS_THROTTLE_CFG] = &qhs_lpass_throttle_cfg,
+ [SLAVE_MX_RDPM] = &qhs_mx_rdpm,
+ [SLAVE_MXC_RDPM] = &qhs_mxc_rdpm,
+ [SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg,
+ [SLAVE_PCIE_1_CFG] = &qhs_pcie1_cfg,
+ [SLAVE_PCIE_TCU_THROTTLE_CFG] = &qhs_pcie_tcu_throttle_cfg,
+ [SLAVE_PCIE_THROTTLE_CFG] = &qhs_pcie_throttle_cfg,
+ [SLAVE_PDM] = &qhs_pdm,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PKA_WRAPPER_CFG] = &qhs_pke_wrapper_cfg,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QM_CFG] = &qhs_qm_cfg,
+ [SLAVE_QM_MPU_CFG] = &qhs_qm_mpu_cfg,
+ [SLAVE_QUP_0] = &qhs_qup0,
+ [SLAVE_QUP_1] = &qhs_qup1,
+ [SLAVE_QUP_3] = &qhs_qup3,
+ [SLAVE_SAIL_THROTTLE_CFG] = &qhs_sail_throttle_cfg,
+ [SLAVE_SDC1] = &qhs_sdc1,
+ [SLAVE_SECURITY] = &qhs_security,
+ [SLAVE_SNOC_THROTTLE_CFG] = &qhs_snoc_throttle_cfg,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM] = &qhs_tlmm,
+ [SLAVE_TSC_CFG] = &qhs_tsc_cfg,
+ [SLAVE_UFS_MEM_CFG] = &qhs_ufs_mem_cfg,
+ [SLAVE_USB2] = &qhs_usb2_0,
+ [SLAVE_USB3_0] = &qhs_usb3_0,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VENUS_CVP_THROTTLE_CFG] = &qhs_venus_cvp_throttle_cfg,
+ [SLAVE_VENUS_V_CPU_THROTTLE_CFG] = &qhs_venus_v_cpu_throttle_cfg,
+ [SLAVE_VENUS_VCODEC_THROTTLE_CFG] = &qhs_venus_vcodec_throttle_cfg,
+ [SLAVE_DDRSS_CFG] = &qns_ddrss_cfg,
+ [SLAVE_GPDSP_NOC_CFG] = &qns_gpdsp_noc_cfg,
+ [SLAVE_CNOC_MNOC_HF_CFG] = &qns_mnoc_hf_cfg,
+ [SLAVE_CNOC_MNOC_SF_CFG] = &qns_mnoc_sf_cfg,
+ [SLAVE_PCIE_ANOC_CFG] = &qns_pcie_anoc_cfg,
+ [SLAVE_SNOC_CFG] = &qns_snoc_cfg,
+ [SLAVE_BOOT_IMEM] = &qxs_boot_imem,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SLAVE_PCIE_0] = &xs_pcie_0,
+ [SLAVE_PCIE_1] = &xs_pcie_1,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc qcs8300_config_noc = {
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .bcms = config_noc_bcms,
+ .num_bcms = ARRAY_SIZE(config_noc_bcms),
+};
+
+static struct qcom_icc_node * const dc_noc_nodes[] = {
+ [MASTER_CNOC_DC_NOC] = &qnm_cnoc_dc_noc,
+ [SLAVE_LLCC_CFG] = &qhs_llcc,
+ [SLAVE_GEM_NOC_CFG] = &qns_gemnoc,
+};
+
+static const struct qcom_icc_desc qcs8300_dc_noc = {
+ .nodes = dc_noc_nodes,
+ .num_nodes = ARRAY_SIZE(dc_noc_nodes),
+};
+
+static struct qcom_icc_bcm * const gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh2,
+};
+
+static struct qcom_icc_node * const gem_noc_nodes[] = {
+ [MASTER_GPU_TCU] = &alm_gpu_tcu,
+ [MASTER_PCIE_TCU] = &alm_pcie_tcu,
+ [MASTER_SYS_TCU] = &alm_sys_tcu,
+ [MASTER_APPSS_PROC] = &chm_apps,
+ [MASTER_COMPUTE_NOC] = &qnm_cmpnoc0,
+ [MASTER_GEM_NOC_CFG] = &qnm_gemnoc_cfg,
+ [MASTER_GPDSP_SAIL] = &qnm_gpdsp_sail,
+ [MASTER_GFX3D] = &qnm_gpu,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_ANOC_PCIE_GEM_NOC] = &qnm_pcie,
+ [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [SLAVE_GEM_NOC_CNOC] = &qns_gem_noc_cnoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_GEM_NOC_PCIE_CNOC] = &qns_pcie,
+ [SLAVE_SERVICE_GEM_NOC_1] = &srvc_even_gemnoc,
+ [SLAVE_SERVICE_GEM_NOC_2] = &srvc_odd_gemnoc,
+ [SLAVE_SERVICE_GEM_NOC] = &srvc_sys_gemnoc,
+ [SLAVE_SERVICE_GEM_NOC2] = &srvc_sys_gemnoc_2,
+};
+
+static const struct qcom_icc_desc qcs8300_gem_noc = {
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const gpdsp_anoc_bcms[] = {
+ &bcm_gna0,
+};
+
+static struct qcom_icc_node * const gpdsp_anoc_nodes[] = {
+ [MASTER_SAILSS_MD0] = &qnm_sailss_md0,
+ [MASTER_DSP0] = &qxm_dsp0,
+ [SLAVE_GP_DSP_SAIL_NOC] = &qns_gp_dsp_sail_noc,
+};
+
+static const struct qcom_icc_desc qcs8300_gpdsp_anoc = {
+ .nodes = gpdsp_anoc_nodes,
+ .num_nodes = ARRAY_SIZE(gpdsp_anoc_nodes),
+ .bcms = gpdsp_anoc_bcms,
+ .num_bcms = ARRAY_SIZE(gpdsp_anoc_bcms),
+};
+
+static struct qcom_icc_bcm * const lpass_ag_noc_bcms[] = {
+ &bcm_sn9,
+};
+
+static struct qcom_icc_node * const lpass_ag_noc_nodes[] = {
+ [MASTER_CNOC_LPASS_AG_NOC] = &qhm_config_noc,
+ [MASTER_LPASS_PROC] = &qxm_lpass_dsp,
+ [SLAVE_LPASS_CORE_CFG] = &qhs_lpass_core,
+ [SLAVE_LPASS_LPI_CFG] = &qhs_lpass_lpi,
+ [SLAVE_LPASS_MPU_CFG] = &qhs_lpass_mpu,
+ [SLAVE_LPASS_TOP_CFG] = &qhs_lpass_top,
+ [SLAVE_LPASS_SNOC] = &qns_sysnoc,
+ [SLAVE_SERVICES_LPASS_AML_NOC] = &srvc_niu_aml_noc,
+ [SLAVE_SERVICE_LPASS_AG_NOC] = &srvc_niu_lpass_agnoc,
+};
+
+static const struct qcom_icc_desc qcs8300_lpass_ag_noc = {
+ .nodes = lpass_ag_noc_nodes,
+ .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes),
+ .bcms = lpass_ag_noc_bcms,
+ .num_bcms = ARRAY_SIZE(lpass_ag_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const mc_virt_bcms[] = {
+ &bcm_acv,
+ &bcm_mc0,
+};
+
+static struct qcom_icc_node * const mc_virt_nodes[] = {
+ [MASTER_LLCC] = &llcc_mc,
+ [SLAVE_EBI1] = &ebi,
+};
+
+static const struct qcom_icc_desc qcs8300_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const mmss_noc_nodes[] = {
+ [MASTER_CAMNOC_HF] = &qnm_camnoc_hf,
+ [MASTER_CAMNOC_ICP] = &qnm_camnoc_icp,
+ [MASTER_CAMNOC_SF] = &qnm_camnoc_sf,
+ [MASTER_MDP0] = &qnm_mdp0_0,
+ [MASTER_MDP1] = &qnm_mdp0_1,
+ [MASTER_CNOC_MNOC_HF_CFG] = &qnm_mnoc_hf_cfg,
+ [MASTER_CNOC_MNOC_SF_CFG] = &qnm_mnoc_sf_cfg,
+ [MASTER_VIDEO_P0] = &qnm_video0,
+ [MASTER_VIDEO_PROC] = &qnm_video_cvp,
+ [MASTER_VIDEO_V_PROC] = &qnm_video_v_cpu,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf,
+ [SLAVE_SERVICE_MNOC_HF] = &srvc_mnoc_hf,
+ [SLAVE_SERVICE_MNOC_SF] = &srvc_mnoc_sf,
+};
+
+static const struct qcom_icc_desc qcs8300_mmss_noc = {
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const nspa_noc_bcms[] = {
+ &bcm_nsa0,
+ &bcm_nsa1,
+};
+
+static struct qcom_icc_node * const nspa_noc_nodes[] = {
+ [MASTER_CDSP_NOC_CFG] = &qhm_nsp_noc_config,
+ [MASTER_CDSP_PROC] = &qxm_nsp,
+ [SLAVE_HCP_A] = &qns_hcp,
+ [SLAVE_CDSP_MEM_NOC] = &qns_nsp_gemnoc,
+ [SLAVE_SERVICE_NSP_NOC] = &service_nsp_noc,
+};
+
+static const struct qcom_icc_desc qcs8300_nspa_noc = {
+ .nodes = nspa_noc_nodes,
+ .num_nodes = ARRAY_SIZE(nspa_noc_nodes),
+ .bcms = nspa_noc_bcms,
+ .num_bcms = ARRAY_SIZE(nspa_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const pcie_anoc_bcms[] = {
+ &bcm_pci0,
+};
+
+static struct qcom_icc_node * const pcie_anoc_nodes[] = {
+ [MASTER_PCIE_0] = &xm_pcie3_0,
+ [MASTER_PCIE_1] = &xm_pcie3_1,
+ [SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_mem_noc,
+};
+
+static const struct qcom_icc_desc qcs8300_pcie_anoc = {
+ .nodes = pcie_anoc_nodes,
+ .num_nodes = ARRAY_SIZE(pcie_anoc_nodes),
+ .bcms = pcie_anoc_bcms,
+ .num_bcms = ARRAY_SIZE(pcie_anoc_bcms),
+};
+
+static struct qcom_icc_bcm * const system_noc_bcms[] = {
+ &bcm_sn0,
+ &bcm_sn1,
+ &bcm_sn3,
+ &bcm_sn4,
+ &bcm_sn9,
+};
+
+static struct qcom_icc_node * const system_noc_nodes[] = {
+ [MASTER_GIC_AHB] = &qhm_gic,
+ [MASTER_A1NOC_SNOC] = &qnm_aggre1_noc,
+ [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc,
+ [MASTER_LPASS_ANOC] = &qnm_lpass_noc,
+ [MASTER_SNOC_CFG] = &qnm_snoc_cfg,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_GIC] = &xm_gic,
+ [SLAVE_SNOC_GEM_NOC_GC] = &qns_gemnoc_gc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+};
+
+static const struct qcom_icc_desc qcs8300_system_noc = {
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,qcs8300-aggre1-noc",
+ .data = &qcs8300_aggre1_noc},
+ { .compatible = "qcom,qcs8300-aggre2-noc",
+ .data = &qcs8300_aggre2_noc},
+ { .compatible = "qcom,qcs8300-clk-virt",
+ .data = &qcs8300_clk_virt},
+ { .compatible = "qcom,qcs8300-config-noc",
+ .data = &qcs8300_config_noc},
+ { .compatible = "qcom,qcs8300-dc-noc",
+ .data = &qcs8300_dc_noc},
+ { .compatible = "qcom,qcs8300-gem-noc",
+ .data = &qcs8300_gem_noc},
+ { .compatible = "qcom,qcs8300-gpdsp-anoc",
+ .data = &qcs8300_gpdsp_anoc},
+ { .compatible = "qcom,qcs8300-lpass-ag-noc",
+ .data = &qcs8300_lpass_ag_noc},
+ { .compatible = "qcom,qcs8300-mc-virt",
+ .data = &qcs8300_mc_virt},
+ { .compatible = "qcom,qcs8300-mmss-noc",
+ .data = &qcs8300_mmss_noc},
+ { .compatible = "qcom,qcs8300-nspa-noc",
+ .data = &qcs8300_nspa_noc},
+ { .compatible = "qcom,qcs8300-pcie-anoc",
+ .data = &qcs8300_pcie_anoc},
+ { .compatible = "qcom,qcs8300-system-noc",
+ .data = &qcs8300_system_noc},
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
+ .driver = {
+ .name = "qnoc-qcs8300",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+module_exit(qnoc_driver_exit);
+
+MODULE_DESCRIPTION("QCS8300 NoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/qcs8300.h b/drivers/interconnect/qcom/qcs8300.h
new file mode 100644
index 000000000000..6b9e2b424c2a
--- /dev/null
+++ b/drivers/interconnect/qcom/qcs8300.h
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __DRIVERS_INTERCONNECT_QCOM_QCS8300_H
+#define __DRIVERS_INTERCONNECT_QCOM_QCS8300_H
+
+#define QCS8300_MASTER_GPU_TCU 0
+#define QCS8300_MASTER_PCIE_TCU 1
+#define QCS8300_MASTER_SYS_TCU 2
+#define QCS8300_MASTER_APPSS_PROC 3
+#define QCS8300_MASTER_LLCC 4
+#define QCS8300_MASTER_CNOC_LPASS_AG_NOC 5
+#define QCS8300_MASTER_GIC_AHB 6
+#define QCS8300_MASTER_CDSP_NOC_CFG 7
+#define QCS8300_MASTER_QDSS_BAM 8
+#define QCS8300_MASTER_QUP_0 9
+#define QCS8300_MASTER_QUP_1 10
+#define QCS8300_MASTER_A1NOC_SNOC 11
+#define QCS8300_MASTER_A2NOC_SNOC 12
+#define QCS8300_MASTER_CAMNOC_HF 13
+#define QCS8300_MASTER_CAMNOC_ICP 14
+#define QCS8300_MASTER_CAMNOC_SF 15
+#define QCS8300_MASTER_COMPUTE_NOC 16
+#define QCS8300_MASTER_CNOC_A2NOC 17
+#define QCS8300_MASTER_CNOC_DC_NOC 18
+#define QCS8300_MASTER_GEM_NOC_CFG 19
+#define QCS8300_MASTER_GEM_NOC_CNOC 20
+#define QCS8300_MASTER_GEM_NOC_PCIE_SNOC 21
+#define QCS8300_MASTER_GPDSP_SAIL 22
+#define QCS8300_MASTER_GFX3D 23
+#define QCS8300_MASTER_LPASS_ANOC 24
+#define QCS8300_MASTER_MDP0 25
+#define QCS8300_MASTER_MDP1 26
+#define QCS8300_MASTER_MNOC_HF_MEM_NOC 27
+#define QCS8300_MASTER_CNOC_MNOC_HF_CFG 28
+#define QCS8300_MASTER_MNOC_SF_MEM_NOC 29
+#define QCS8300_MASTER_CNOC_MNOC_SF_CFG 30
+#define QCS8300_MASTER_ANOC_PCIE_GEM_NOC 31
+#define QCS8300_MASTER_SAILSS_MD0 32
+#define QCS8300_MASTER_SNOC_CFG 33
+#define QCS8300_MASTER_SNOC_GC_MEM_NOC 34
+#define QCS8300_MASTER_SNOC_SF_MEM_NOC 35
+#define QCS8300_MASTER_VIDEO_P0 36
+#define QCS8300_MASTER_VIDEO_PROC 37
+#define QCS8300_MASTER_VIDEO_V_PROC 38
+#define QCS8300_MASTER_QUP_CORE_0 39
+#define QCS8300_MASTER_QUP_CORE_1 40
+#define QCS8300_MASTER_QUP_CORE_3 41
+#define QCS8300_MASTER_CRYPTO_CORE0 42
+#define QCS8300_MASTER_CRYPTO_CORE1 43
+#define QCS8300_MASTER_DSP0 44
+#define QCS8300_MASTER_IPA 45
+#define QCS8300_MASTER_LPASS_PROC 46
+#define QCS8300_MASTER_CDSP_PROC 47
+#define QCS8300_MASTER_PIMEM 48
+#define QCS8300_MASTER_QUP_3 49
+#define QCS8300_MASTER_EMAC 50
+#define QCS8300_MASTER_GIC 51
+#define QCS8300_MASTER_PCIE_0 52
+#define QCS8300_MASTER_PCIE_1 53
+#define QCS8300_MASTER_QDSS_ETR_0 54
+#define QCS8300_MASTER_QDSS_ETR_1 55
+#define QCS8300_MASTER_SDC 56
+#define QCS8300_MASTER_UFS_MEM 57
+#define QCS8300_MASTER_USB2 58
+#define QCS8300_MASTER_USB3_0 59
+#define QCS8300_SLAVE_EBI1 60
+#define QCS8300_SLAVE_AHB2PHY_2 61
+#define QCS8300_SLAVE_AHB2PHY_3 62
+#define QCS8300_SLAVE_ANOC_THROTTLE_CFG 63
+#define QCS8300_SLAVE_AOSS 64
+#define QCS8300_SLAVE_APPSS 65
+#define QCS8300_SLAVE_BOOT_ROM 66
+#define QCS8300_SLAVE_CAMERA_CFG 67
+#define QCS8300_SLAVE_CAMERA_NRT_THROTTLE_CFG 68
+#define QCS8300_SLAVE_CAMERA_RT_THROTTLE_CFG 69
+#define QCS8300_SLAVE_CLK_CTL 70
+#define QCS8300_SLAVE_CDSP_CFG 71
+#define QCS8300_SLAVE_RBCPR_CX_CFG 72
+#define QCS8300_SLAVE_RBCPR_MMCX_CFG 73
+#define QCS8300_SLAVE_RBCPR_MX_CFG 74
+#define QCS8300_SLAVE_CPR_NSPCX 75
+#define QCS8300_SLAVE_CPR_NSPHMX 76
+#define QCS8300_SLAVE_CRYPTO_0_CFG 77
+#define QCS8300_SLAVE_CX_RDPM 78
+#define QCS8300_SLAVE_DISPLAY_CFG 79
+#define QCS8300_SLAVE_DISPLAY_RT_THROTTLE_CFG 80
+#define QCS8300_SLAVE_EMAC_CFG 81
+#define QCS8300_SLAVE_GP_DSP0_CFG 82
+#define QCS8300_SLAVE_GPDSP0_THROTTLE_CFG 83
+#define QCS8300_SLAVE_GPU_TCU_THROTTLE_CFG 84
+#define QCS8300_SLAVE_GFX3D_CFG 85
+#define QCS8300_SLAVE_HWKM 86
+#define QCS8300_SLAVE_IMEM_CFG 87
+#define QCS8300_SLAVE_IPA_CFG 88
+#define QCS8300_SLAVE_IPC_ROUTER_CFG 89
+#define QCS8300_SLAVE_LLCC_CFG 90
+#define QCS8300_SLAVE_LPASS 91
+#define QCS8300_SLAVE_LPASS_CORE_CFG 92
+#define QCS8300_SLAVE_LPASS_LPI_CFG 93
+#define QCS8300_SLAVE_LPASS_MPU_CFG 94
+#define QCS8300_SLAVE_LPASS_THROTTLE_CFG 95
+#define QCS8300_SLAVE_LPASS_TOP_CFG 96
+#define QCS8300_SLAVE_MX_RDPM 97
+#define QCS8300_SLAVE_MXC_RDPM 98
+#define QCS8300_SLAVE_PCIE_0_CFG 99
+#define QCS8300_SLAVE_PCIE_1_CFG 100
+#define QCS8300_SLAVE_PCIE_TCU_THROTTLE_CFG 101
+#define QCS8300_SLAVE_PCIE_THROTTLE_CFG 102
+#define QCS8300_SLAVE_PDM 103
+#define QCS8300_SLAVE_PIMEM_CFG 104
+#define QCS8300_SLAVE_PKA_WRAPPER_CFG 105
+#define QCS8300_SLAVE_QDSS_CFG 106
+#define QCS8300_SLAVE_QM_CFG 107
+#define QCS8300_SLAVE_QM_MPU_CFG 108
+#define QCS8300_SLAVE_QUP_0 109
+#define QCS8300_SLAVE_QUP_1 110
+#define QCS8300_SLAVE_QUP_3 111
+#define QCS8300_SLAVE_SAIL_THROTTLE_CFG 112
+#define QCS8300_SLAVE_SDC1 113
+#define QCS8300_SLAVE_SECURITY 114
+#define QCS8300_SLAVE_SNOC_THROTTLE_CFG 115
+#define QCS8300_SLAVE_TCSR 116
+#define QCS8300_SLAVE_TLMM 117
+#define QCS8300_SLAVE_TSC_CFG 118
+#define QCS8300_SLAVE_UFS_MEM_CFG 119
+#define QCS8300_SLAVE_USB2 120
+#define QCS8300_SLAVE_USB3_0 121
+#define QCS8300_SLAVE_VENUS_CFG 122
+#define QCS8300_SLAVE_VENUS_CVP_THROTTLE_CFG 123
+#define QCS8300_SLAVE_VENUS_V_CPU_THROTTLE_CFG 124
+#define QCS8300_SLAVE_VENUS_VCODEC_THROTTLE_CFG 125
+#define QCS8300_SLAVE_A1NOC_SNOC 126
+#define QCS8300_SLAVE_A2NOC_SNOC 127
+#define QCS8300_SLAVE_DDRSS_CFG 128
+#define QCS8300_SLAVE_GEM_NOC_CNOC 129
+#define QCS8300_SLAVE_GEM_NOC_CFG 130
+#define QCS8300_SLAVE_SNOC_GEM_NOC_GC 131
+#define QCS8300_SLAVE_SNOC_GEM_NOC_SF 132
+#define QCS8300_SLAVE_GP_DSP_SAIL_NOC 133
+#define QCS8300_SLAVE_GPDSP_NOC_CFG 134
+#define QCS8300_SLAVE_HCP_A 135
+#define QCS8300_SLAVE_LLCC 136
+#define QCS8300_SLAVE_MNOC_HF_MEM_NOC 137
+#define QCS8300_SLAVE_MNOC_SF_MEM_NOC 138
+#define QCS8300_SLAVE_CNOC_MNOC_HF_CFG 139
+#define QCS8300_SLAVE_CNOC_MNOC_SF_CFG 140
+#define QCS8300_SLAVE_CDSP_MEM_NOC 141
+#define QCS8300_SLAVE_GEM_NOC_PCIE_CNOC 142
+#define QCS8300_SLAVE_PCIE_ANOC_CFG 143
+#define QCS8300_SLAVE_ANOC_PCIE_GEM_NOC 144
+#define QCS8300_SLAVE_SNOC_CFG 145
+#define QCS8300_SLAVE_LPASS_SNOC 146
+#define QCS8300_SLAVE_QUP_CORE_0 147
+#define QCS8300_SLAVE_QUP_CORE_1 148
+#define QCS8300_SLAVE_QUP_CORE_3 149
+#define QCS8300_SLAVE_BOOT_IMEM 150
+#define QCS8300_SLAVE_IMEM 151
+#define QCS8300_SLAVE_PIMEM 152
+#define QCS8300_SLAVE_SERVICE_NSP_NOC 153
+#define QCS8300_SLAVE_SERVICE_GEM_NOC_1 154
+#define QCS8300_SLAVE_SERVICE_MNOC_HF 155
+#define QCS8300_SLAVE_SERVICE_MNOC_SF 156
+#define QCS8300_SLAVE_SERVICES_LPASS_AML_NOC 157
+#define QCS8300_SLAVE_SERVICE_LPASS_AG_NOC 158
+#define QCS8300_SLAVE_SERVICE_GEM_NOC_2 159
+#define QCS8300_SLAVE_SERVICE_SNOC 160
+#define QCS8300_SLAVE_SERVICE_GEM_NOC 161
+#define QCS8300_SLAVE_SERVICE_GEM_NOC2 162
+#define QCS8300_SLAVE_PCIE_0 163
+#define QCS8300_SLAVE_PCIE_1 164
+#define QCS8300_SLAVE_QDSS_STM 165
+#define QCS8300_SLAVE_TCU 166
+
+#endif
diff --git a/drivers/interconnect/qcom/qdu1000.c b/drivers/interconnect/qcom/qdu1000.c
index 9cb477d2bdfe..a7392eb73d4a 100644
--- a/drivers/interconnect/qcom/qdu1000.c
+++ b/drivers/interconnect/qcom/qdu1000.c
@@ -1046,7 +1046,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-qdu1000",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sa8775p.c b/drivers/interconnect/qcom/sa8775p.c
index a729775c2aa4..e2826af3ea2e 100644
--- a/drivers/interconnect/qcom/sa8775p.c
+++ b/drivers/interconnect/qcom/sa8775p.c
@@ -2519,7 +2519,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sa8775p",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sar2130p.c b/drivers/interconnect/qcom/sar2130p.c
new file mode 100644
index 000000000000..9eac0ac76812
--- /dev/null
+++ b/drivers/interconnect/qcom/sar2130p.c
@@ -0,0 +1,1930 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2024, Linaro Ltd.
+ */
+
+#include <linux/device.h>
+#include <linux/interconnect.h>
+#include <linux/interconnect-provider.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/sort.h>
+#include <dt-bindings/interconnect/qcom,sar2130p-rpmh.h>
+
+#include "bcm-voter.h"
+#include "icc-common.h"
+#include "icc-rpmh.h"
+
+enum {
+ SAR2130P_MASTER_QUP_CORE_0,
+ SAR2130P_MASTER_QUP_CORE_1,
+ SAR2130P_MASTER_GEM_NOC_CNOC,
+ SAR2130P_MASTER_GEM_NOC_PCIE_SNOC,
+ SAR2130P_MASTER_QDSS_DAP,
+ SAR2130P_MASTER_GPU_TCU,
+ SAR2130P_MASTER_SYS_TCU,
+ SAR2130P_MASTER_APPSS_PROC,
+ SAR2130P_MASTER_GFX3D,
+ SAR2130P_MASTER_MNOC_HF_MEM_NOC,
+ SAR2130P_MASTER_MNOC_SF_MEM_NOC,
+ SAR2130P_MASTER_COMPUTE_NOC,
+ SAR2130P_MASTER_ANOC_PCIE_GEM_NOC,
+ SAR2130P_MASTER_SNOC_GC_MEM_NOC,
+ SAR2130P_MASTER_SNOC_SF_MEM_NOC,
+ SAR2130P_MASTER_WLAN_Q6,
+ SAR2130P_MASTER_CNOC_LPASS_AG_NOC,
+ SAR2130P_MASTER_LPASS_PROC,
+ SAR2130P_MASTER_LLCC,
+ SAR2130P_MASTER_CAMNOC_HF,
+ SAR2130P_MASTER_CAMNOC_ICP,
+ SAR2130P_MASTER_CAMNOC_SF,
+ SAR2130P_MASTER_LSR,
+ SAR2130P_MASTER_MDP,
+ SAR2130P_MASTER_CNOC_MNOC_CFG,
+ SAR2130P_MASTER_VIDEO,
+ SAR2130P_MASTER_VIDEO_CV_PROC,
+ SAR2130P_MASTER_VIDEO_PROC,
+ SAR2130P_MASTER_VIDEO_V_PROC,
+ SAR2130P_MASTER_CDSP_NOC_CFG,
+ SAR2130P_MASTER_CDSP_PROC,
+ SAR2130P_MASTER_PCIE_0,
+ SAR2130P_MASTER_PCIE_1,
+ SAR2130P_MASTER_GIC_AHB,
+ SAR2130P_MASTER_QDSS_BAM,
+ SAR2130P_MASTER_QSPI_0,
+ SAR2130P_MASTER_QUP_0,
+ SAR2130P_MASTER_QUP_1,
+ SAR2130P_MASTER_A2NOC_SNOC,
+ SAR2130P_MASTER_CNOC_DATAPATH,
+ SAR2130P_MASTER_LPASS_ANOC,
+ SAR2130P_MASTER_SNOC_CFG,
+ SAR2130P_MASTER_CRYPTO,
+ SAR2130P_MASTER_PIMEM,
+ SAR2130P_MASTER_GIC,
+ SAR2130P_MASTER_QDSS_ETR,
+ SAR2130P_MASTER_QDSS_ETR_1,
+ SAR2130P_MASTER_SDCC_1,
+ SAR2130P_MASTER_USB3_0,
+ SAR2130P_SLAVE_QUP_CORE_0,
+ SAR2130P_SLAVE_QUP_CORE_1,
+ SAR2130P_SLAVE_AHB2PHY_SOUTH,
+ SAR2130P_SLAVE_AOSS,
+ SAR2130P_SLAVE_CAMERA_CFG,
+ SAR2130P_SLAVE_CLK_CTL,
+ SAR2130P_SLAVE_CDSP_CFG,
+ SAR2130P_SLAVE_RBCPR_CX_CFG,
+ SAR2130P_SLAVE_RBCPR_MMCX_CFG,
+ SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ SAR2130P_SLAVE_RBCPR_MXC_CFG,
+ SAR2130P_SLAVE_CPR_NSPCX,
+ SAR2130P_SLAVE_CRYPTO_0_CFG,
+ SAR2130P_SLAVE_CX_RDPM,
+ SAR2130P_SLAVE_DISPLAY_CFG,
+ SAR2130P_SLAVE_GFX3D_CFG,
+ SAR2130P_SLAVE_IMEM_CFG,
+ SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ SAR2130P_SLAVE_LPASS,
+ SAR2130P_SLAVE_MX_RDPM,
+ SAR2130P_SLAVE_PCIE_0_CFG,
+ SAR2130P_SLAVE_PCIE_1_CFG,
+ SAR2130P_SLAVE_PDM,
+ SAR2130P_SLAVE_PIMEM_CFG,
+ SAR2130P_SLAVE_PRNG,
+ SAR2130P_SLAVE_QDSS_CFG,
+ SAR2130P_SLAVE_QSPI_0,
+ SAR2130P_SLAVE_QUP_0,
+ SAR2130P_SLAVE_QUP_1,
+ SAR2130P_SLAVE_SDCC_1,
+ SAR2130P_SLAVE_TCSR,
+ SAR2130P_SLAVE_TLMM,
+ SAR2130P_SLAVE_TME_CFG,
+ SAR2130P_SLAVE_USB3_0,
+ SAR2130P_SLAVE_VENUS_CFG,
+ SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ SAR2130P_SLAVE_WLAN_Q6_CFG,
+ SAR2130P_SLAVE_DDRSS_CFG,
+ SAR2130P_SLAVE_CNOC_MNOC_CFG,
+ SAR2130P_SLAVE_SNOC_CFG,
+ SAR2130P_SLAVE_IMEM,
+ SAR2130P_SLAVE_PIMEM,
+ SAR2130P_SLAVE_SERVICE_CNOC,
+ SAR2130P_SLAVE_PCIE_0,
+ SAR2130P_SLAVE_PCIE_1,
+ SAR2130P_SLAVE_QDSS_STM,
+ SAR2130P_SLAVE_TCU,
+ SAR2130P_SLAVE_GEM_NOC_CNOC,
+ SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC,
+ SAR2130P_SLAVE_LPASS_CORE_CFG,
+ SAR2130P_SLAVE_LPASS_LPI_CFG,
+ SAR2130P_SLAVE_LPASS_MPU_CFG,
+ SAR2130P_SLAVE_LPASS_TOP_CFG,
+ SAR2130P_SLAVE_LPASS_SNOC,
+ SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC,
+ SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC,
+ SAR2130P_SLAVE_EBI1,
+ SAR2130P_SLAVE_MNOC_HF_MEM_NOC,
+ SAR2130P_SLAVE_MNOC_SF_MEM_NOC,
+ SAR2130P_SLAVE_SERVICE_MNOC,
+ SAR2130P_SLAVE_CDSP_MEM_NOC,
+ SAR2130P_SLAVE_SERVICE_NSP_NOC,
+ SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC,
+ SAR2130P_SLAVE_A2NOC_SNOC,
+ SAR2130P_SLAVE_SNOC_GEM_NOC_GC,
+ SAR2130P_SLAVE_SNOC_GEM_NOC_SF,
+ SAR2130P_SLAVE_SERVICE_SNOC,
+};
+
+static const struct regmap_config icc_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .fast_io = true,
+};
+
+static struct qcom_icc_node qup0_core_master = {
+ .name = "qup0_core_master",
+ .id = SAR2130P_MASTER_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_QUP_CORE_0 },
+};
+
+static struct qcom_icc_node qup1_core_master = {
+ .name = "qup1_core_master",
+ .id = SAR2130P_MASTER_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_QUP_CORE_1 },
+};
+
+static struct qcom_icc_node qnm_gemnoc_cnoc = {
+ .name = "qnm_gemnoc_cnoc",
+ .id = SAR2130P_MASTER_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 43,
+ .links = { SAR2130P_SLAVE_AHB2PHY_SOUTH, SAR2130P_SLAVE_AOSS,
+ SAR2130P_SLAVE_CAMERA_CFG, SAR2130P_SLAVE_CLK_CTL,
+ SAR2130P_SLAVE_CDSP_CFG, SAR2130P_SLAVE_RBCPR_CX_CFG,
+ SAR2130P_SLAVE_RBCPR_MMCX_CFG, SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ SAR2130P_SLAVE_RBCPR_MXC_CFG, SAR2130P_SLAVE_CPR_NSPCX,
+ SAR2130P_SLAVE_CRYPTO_0_CFG, SAR2130P_SLAVE_CX_RDPM,
+ SAR2130P_SLAVE_DISPLAY_CFG, SAR2130P_SLAVE_GFX3D_CFG,
+ SAR2130P_SLAVE_IMEM_CFG, SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ SAR2130P_SLAVE_LPASS, SAR2130P_SLAVE_MX_RDPM,
+ SAR2130P_SLAVE_PCIE_0_CFG, SAR2130P_SLAVE_PCIE_1_CFG,
+ SAR2130P_SLAVE_PDM, SAR2130P_SLAVE_PIMEM_CFG,
+ SAR2130P_SLAVE_PRNG, SAR2130P_SLAVE_QDSS_CFG,
+ SAR2130P_SLAVE_QSPI_0, SAR2130P_SLAVE_QUP_0,
+ SAR2130P_SLAVE_QUP_1, SAR2130P_SLAVE_SDCC_1,
+ SAR2130P_SLAVE_TCSR, SAR2130P_SLAVE_TLMM,
+ SAR2130P_SLAVE_TME_CFG, SAR2130P_SLAVE_USB3_0,
+ SAR2130P_SLAVE_VENUS_CFG, SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ SAR2130P_SLAVE_WLAN_Q6_CFG, SAR2130P_SLAVE_DDRSS_CFG,
+ SAR2130P_SLAVE_CNOC_MNOC_CFG, SAR2130P_SLAVE_SNOC_CFG,
+ SAR2130P_SLAVE_IMEM, SAR2130P_SLAVE_PIMEM,
+ SAR2130P_SLAVE_SERVICE_CNOC, SAR2130P_SLAVE_QDSS_STM,
+ SAR2130P_SLAVE_TCU },
+};
+
+static struct qcom_icc_node qnm_gemnoc_pcie = {
+ .name = "qnm_gemnoc_pcie",
+ .id = SAR2130P_MASTER_GEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_PCIE_0, SAR2130P_SLAVE_PCIE_1 },
+};
+
+static struct qcom_icc_node xm_qdss_dap = {
+ .name = "xm_qdss_dap",
+ .id = SAR2130P_MASTER_QDSS_DAP,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 43,
+ .links = { SAR2130P_SLAVE_AHB2PHY_SOUTH, SAR2130P_SLAVE_AOSS,
+ SAR2130P_SLAVE_CAMERA_CFG, SAR2130P_SLAVE_CLK_CTL,
+ SAR2130P_SLAVE_CDSP_CFG, SAR2130P_SLAVE_RBCPR_CX_CFG,
+ SAR2130P_SLAVE_RBCPR_MMCX_CFG, SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ SAR2130P_SLAVE_RBCPR_MXC_CFG, SAR2130P_SLAVE_CPR_NSPCX,
+ SAR2130P_SLAVE_CRYPTO_0_CFG, SAR2130P_SLAVE_CX_RDPM,
+ SAR2130P_SLAVE_DISPLAY_CFG, SAR2130P_SLAVE_GFX3D_CFG,
+ SAR2130P_SLAVE_IMEM_CFG, SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ SAR2130P_SLAVE_LPASS, SAR2130P_SLAVE_MX_RDPM,
+ SAR2130P_SLAVE_PCIE_0_CFG, SAR2130P_SLAVE_PCIE_1_CFG,
+ SAR2130P_SLAVE_PDM, SAR2130P_SLAVE_PIMEM_CFG,
+ SAR2130P_SLAVE_PRNG, SAR2130P_SLAVE_QDSS_CFG,
+ SAR2130P_SLAVE_QSPI_0, SAR2130P_SLAVE_QUP_0,
+ SAR2130P_SLAVE_QUP_1, SAR2130P_SLAVE_SDCC_1,
+ SAR2130P_SLAVE_TCSR, SAR2130P_SLAVE_TLMM,
+ SAR2130P_SLAVE_TME_CFG, SAR2130P_SLAVE_USB3_0,
+ SAR2130P_SLAVE_VENUS_CFG, SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ SAR2130P_SLAVE_WLAN_Q6_CFG, SAR2130P_SLAVE_DDRSS_CFG,
+ SAR2130P_SLAVE_CNOC_MNOC_CFG, SAR2130P_SLAVE_SNOC_CFG,
+ SAR2130P_SLAVE_IMEM, SAR2130P_SLAVE_PIMEM,
+ SAR2130P_SLAVE_SERVICE_CNOC, SAR2130P_SLAVE_QDSS_STM,
+ SAR2130P_SLAVE_TCU },
+};
+
+static const struct qcom_icc_qosbox alm_gpu_tcu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9e000 },
+ .prio = 1,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node alm_gpu_tcu = {
+ .name = "alm_gpu_tcu",
+ .id = SAR2130P_MASTER_GPU_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &alm_gpu_tcu_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox alm_sys_tcu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9f000 },
+ .prio = 6,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node alm_sys_tcu = {
+ .name = "alm_sys_tcu",
+ .id = SAR2130P_MASTER_SYS_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &alm_sys_tcu_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static struct qcom_icc_node chm_apps = {
+ .name = "chm_apps",
+ .id = SAR2130P_MASTER_APPSS_PROC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 3,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static const struct qcom_icc_qosbox qnm_gpu_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0xe000, 0x4e000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_gpu = {
+ .name = "qnm_gpu",
+ .id = SAR2130P_MASTER_GFX3D,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_gpu_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_mnoc_hf_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0xf000, 0x4f000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_mnoc_hf = {
+ .name = "qnm_mnoc_hf",
+ .id = SAR2130P_MASTER_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_mnoc_hf_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_mnoc_sf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9d000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_mnoc_sf = {
+ .name = "qnm_mnoc_sf",
+ .id = SAR2130P_MASTER_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_mnoc_sf_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_nsp_gemnoc_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x10000, 0x50000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_nsp_gemnoc = {
+ .name = "qnm_nsp_gemnoc",
+ .id = SAR2130P_MASTER_COMPUTE_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_nsp_gemnoc_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_pcie_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa2000 },
+ .prio = 2,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_pcie = {
+ .name = "qnm_pcie",
+ .id = SAR2130P_MASTER_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_pcie_qos,
+ .num_links = 2,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_snoc_gc_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa0000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_snoc_gc = {
+ .name = "qnm_snoc_gc",
+ .id = SAR2130P_MASTER_SNOC_GC_MEM_NOC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_snoc_gc_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_LLCC },
+};
+
+static const struct qcom_icc_qosbox qnm_snoc_sf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa1000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_snoc_sf = {
+ .name = "qnm_snoc_sf",
+ .id = SAR2130P_MASTER_SNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_snoc_sf_qos,
+ .num_links = 3,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node qxm_wlan_q6 = {
+ .name = "qxm_wlan_q6",
+ .id = SAR2130P_MASTER_WLAN_Q6,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 3,
+ .links = { SAR2130P_SLAVE_GEM_NOC_CNOC, SAR2130P_SLAVE_LLCC,
+ SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node qhm_config_noc = {
+ .name = "qhm_config_noc",
+ .id = SAR2130P_MASTER_CNOC_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 6,
+ .links = { SAR2130P_SLAVE_LPASS_CORE_CFG, SAR2130P_SLAVE_LPASS_LPI_CFG,
+ SAR2130P_SLAVE_LPASS_MPU_CFG, SAR2130P_SLAVE_LPASS_TOP_CFG,
+ SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC, SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qxm_lpass_dsp = {
+ .name = "qxm_lpass_dsp",
+ .id = SAR2130P_MASTER_LPASS_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 4,
+ .links = { SAR2130P_SLAVE_LPASS_TOP_CFG, SAR2130P_SLAVE_LPASS_SNOC,
+ SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC, SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node llcc_mc = {
+ .name = "llcc_mc",
+ .id = SAR2130P_MASTER_LLCC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_EBI1 },
+};
+
+static const struct qcom_icc_qosbox qnm_camnoc_hf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c000 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_camnoc_hf = {
+ .name = "qnm_camnoc_hf",
+ .id = SAR2130P_MASTER_CAMNOC_HF,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_camnoc_hf_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_camnoc_icp_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c080 },
+ .prio = 4,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_camnoc_icp = {
+ .name = "qnm_camnoc_icp",
+ .id = SAR2130P_MASTER_CAMNOC_ICP,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_camnoc_icp_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_camnoc_sf_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c100 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_camnoc_sf = {
+ .name = "qnm_camnoc_sf",
+ .id = SAR2130P_MASTER_CAMNOC_SF,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_camnoc_sf_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_lsr_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x1f000, 0x1f080 },
+ .prio = 3,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_lsr = {
+ .name = "qnm_lsr",
+ .id = SAR2130P_MASTER_LSR,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_lsr_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_mdp_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x1d000, 0x1d080 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_mdp = {
+ .name = "qnm_mdp",
+ .id = SAR2130P_MASTER_MDP,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_mdp_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qnm_mnoc_cfg = {
+ .name = "qnm_mnoc_cfg",
+ .id = SAR2130P_MASTER_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SERVICE_MNOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_qos = {
+ .num_ports = 2,
+ .port_offsets = { 0x1e000, 0x1e080 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video = {
+ .name = "qnm_video",
+ .id = SAR2130P_MASTER_VIDEO,
+ .channels = 2,
+ .buswidth = 32,
+ .qosbox = &qnm_video_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_cv_cpu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e100 },
+ .prio = 4,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video_cv_cpu = {
+ .name = "qnm_video_cv_cpu",
+ .id = SAR2130P_MASTER_VIDEO_CV_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_video_cv_cpu_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_cvp_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e180 },
+ .prio = 0,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video_cvp = {
+ .name = "qnm_video_cvp",
+ .id = SAR2130P_MASTER_VIDEO_PROC,
+ .channels = 1,
+ .buswidth = 32,
+ .qosbox = &qnm_video_cvp_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qnm_video_v_cpu_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e200 },
+ .prio = 4,
+ .urg_fwd = 1,
+};
+
+static struct qcom_icc_node qnm_video_v_cpu = {
+ .name = "qnm_video_v_cpu",
+ .id = SAR2130P_MASTER_VIDEO_V_PROC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_video_v_cpu_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node qhm_nsp_noc_config = {
+ .name = "qhm_nsp_noc_config",
+ .id = SAR2130P_MASTER_CDSP_NOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SERVICE_NSP_NOC },
+};
+
+static struct qcom_icc_node qxm_nsp = {
+ .name = "qxm_nsp",
+ .id = SAR2130P_MASTER_CDSP_PROC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_CDSP_MEM_NOC },
+};
+
+static const struct qcom_icc_qosbox xm_pcie3_0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x9000 },
+ .prio = 3,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_pcie3_0 = {
+ .name = "xm_pcie3_0",
+ .id = SAR2130P_MASTER_PCIE_0,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_pcie3_0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static const struct qcom_icc_qosbox xm_pcie3_1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0xa000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_pcie3_1 = {
+ .name = "xm_pcie3_1",
+ .id = SAR2130P_MASTER_PCIE_1,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_pcie3_1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC },
+};
+
+static const struct qcom_icc_qosbox qhm_gic_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1d000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_gic = {
+ .name = "qhm_gic",
+ .id = SAR2130P_MASTER_GIC_AHB,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_gic_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static const struct qcom_icc_qosbox qhm_qdss_bam_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x22000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qdss_bam = {
+ .name = "qhm_qdss_bam",
+ .id = SAR2130P_MASTER_QDSS_BAM,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qdss_bam_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qhm_qspi_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x23000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qspi = {
+ .name = "qhm_qspi",
+ .id = SAR2130P_MASTER_QSPI_0,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qspi_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qhm_qup0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x24000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qup0 = {
+ .name = "qhm_qup0",
+ .id = SAR2130P_MASTER_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qup0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qhm_qup1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x25000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qhm_qup1 = {
+ .name = "qhm_qup1",
+ .id = SAR2130P_MASTER_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .qosbox = &qhm_qup1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qnm_aggre2_noc = {
+ .name = "qnm_aggre2_noc",
+ .id = SAR2130P_MASTER_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static const struct qcom_icc_qosbox qnm_cnoc_datapath_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x26000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_cnoc_datapath = {
+ .name = "qnm_cnoc_datapath",
+ .id = SAR2130P_MASTER_CNOC_DATAPATH,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qnm_cnoc_datapath_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qnm_lpass_noc_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1e000 },
+ .prio = 0,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qnm_lpass_noc = {
+ .name = "qnm_lpass_noc",
+ .id = SAR2130P_MASTER_LPASS_ANOC,
+ .channels = 1,
+ .buswidth = 16,
+ .qosbox = &qnm_lpass_noc_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_SF },
+};
+
+static struct qcom_icc_node qnm_snoc_cfg = {
+ .name = "qnm_snoc_cfg",
+ .id = SAR2130P_MASTER_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SERVICE_SNOC },
+};
+
+static const struct qcom_icc_qosbox qxm_crypto_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x27000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qxm_crypto = {
+ .name = "qxm_crypto",
+ .id = SAR2130P_MASTER_CRYPTO,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qxm_crypto_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox qxm_pimem_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1f000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node qxm_pimem = {
+ .name = "qxm_pimem",
+ .id = SAR2130P_MASTER_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &qxm_pimem_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static const struct qcom_icc_qosbox xm_gic_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x21000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_gic = {
+ .name = "xm_gic",
+ .id = SAR2130P_MASTER_GIC,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_gic_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_SNOC_GEM_NOC_GC },
+};
+
+static const struct qcom_icc_qosbox xm_qdss_etr_0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1b000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_qdss_etr_0 = {
+ .name = "xm_qdss_etr_0",
+ .id = SAR2130P_MASTER_QDSS_ETR,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_qdss_etr_0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox xm_qdss_etr_1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x1c000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_qdss_etr_1 = {
+ .name = "xm_qdss_etr_1",
+ .id = SAR2130P_MASTER_QDSS_ETR_1,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_qdss_etr_1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox xm_sdc1_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x29000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_sdc1 = {
+ .name = "xm_sdc1",
+ .id = SAR2130P_MASTER_SDCC_1,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_sdc1_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static const struct qcom_icc_qosbox xm_usb3_0_qos = {
+ .num_ports = 1,
+ .port_offsets = { 0x28000 },
+ .prio = 2,
+ .urg_fwd = 0,
+ .prio_fwd_disable = 1,
+};
+
+static struct qcom_icc_node xm_usb3_0 = {
+ .name = "xm_usb3_0",
+ .id = SAR2130P_MASTER_USB3_0,
+ .channels = 1,
+ .buswidth = 8,
+ .qosbox = &xm_usb3_0_qos,
+ .num_links = 1,
+ .links = { SAR2130P_SLAVE_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qup0_core_slave = {
+ .name = "qup0_core_slave",
+ .id = SAR2130P_SLAVE_QUP_CORE_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qup1_core_slave = {
+ .name = "qup1_core_slave",
+ .id = SAR2130P_SLAVE_QUP_CORE_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ahb2phy0 = {
+ .name = "qhs_ahb2phy0",
+ .id = SAR2130P_SLAVE_AHB2PHY_SOUTH,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_aoss = {
+ .name = "qhs_aoss",
+ .id = SAR2130P_SLAVE_AOSS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_camera_cfg = {
+ .name = "qhs_camera_cfg",
+ .id = SAR2130P_SLAVE_CAMERA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_clk_ctl = {
+ .name = "qhs_clk_ctl",
+ .id = SAR2130P_SLAVE_CLK_CTL,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_compute_cfg = {
+ .name = "qhs_compute_cfg",
+ .id = SAR2130P_SLAVE_CDSP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_CDSP_NOC_CFG },
+};
+
+static struct qcom_icc_node qhs_cpr_cx = {
+ .name = "qhs_cpr_cx",
+ .id = SAR2130P_SLAVE_RBCPR_CX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mmcx = {
+ .name = "qhs_cpr_mmcx",
+ .id = SAR2130P_SLAVE_RBCPR_MMCX_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mxa = {
+ .name = "qhs_cpr_mxa",
+ .id = SAR2130P_SLAVE_RBCPR_MXA_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_mxc = {
+ .name = "qhs_cpr_mxc",
+ .id = SAR2130P_SLAVE_RBCPR_MXC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cpr_nspcx = {
+ .name = "qhs_cpr_nspcx",
+ .id = SAR2130P_SLAVE_CPR_NSPCX,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_crypto0_cfg = {
+ .name = "qhs_crypto0_cfg",
+ .id = SAR2130P_SLAVE_CRYPTO_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_cx_rdpm = {
+ .name = "qhs_cx_rdpm",
+ .id = SAR2130P_SLAVE_CX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_display_cfg = {
+ .name = "qhs_display_cfg",
+ .id = SAR2130P_SLAVE_DISPLAY_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_gpuss_cfg = {
+ .name = "qhs_gpuss_cfg",
+ .id = SAR2130P_SLAVE_GFX3D_CFG,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_imem_cfg = {
+ .name = "qhs_imem_cfg",
+ .id = SAR2130P_SLAVE_IMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_ipc_router = {
+ .name = "qhs_ipc_router",
+ .id = SAR2130P_SLAVE_IPC_ROUTER_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_cfg = {
+ .name = "qhs_lpass_cfg",
+ .id = SAR2130P_SLAVE_LPASS,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_CNOC_LPASS_AG_NOC },
+};
+
+static struct qcom_icc_node qhs_mx_rdpm = {
+ .name = "qhs_mx_rdpm",
+ .id = SAR2130P_SLAVE_MX_RDPM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie0_cfg = {
+ .name = "qhs_pcie0_cfg",
+ .id = SAR2130P_SLAVE_PCIE_0_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pcie1_cfg = {
+ .name = "qhs_pcie1_cfg",
+ .id = SAR2130P_SLAVE_PCIE_1_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pdm = {
+ .name = "qhs_pdm",
+ .id = SAR2130P_SLAVE_PDM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_pimem_cfg = {
+ .name = "qhs_pimem_cfg",
+ .id = SAR2130P_SLAVE_PIMEM_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_prng = {
+ .name = "qhs_prng",
+ .id = SAR2130P_SLAVE_PRNG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qdss_cfg = {
+ .name = "qhs_qdss_cfg",
+ .id = SAR2130P_SLAVE_QDSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qspi = {
+ .name = "qhs_qspi",
+ .id = SAR2130P_SLAVE_QSPI_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup0 = {
+ .name = "qhs_qup0",
+ .id = SAR2130P_SLAVE_QUP_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_qup1 = {
+ .name = "qhs_qup1",
+ .id = SAR2130P_SLAVE_QUP_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_sdc1 = {
+ .name = "qhs_sdc1",
+ .id = SAR2130P_SLAVE_SDCC_1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tcsr = {
+ .name = "qhs_tcsr",
+ .id = SAR2130P_SLAVE_TCSR,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tlmm = {
+ .name = "qhs_tlmm",
+ .id = SAR2130P_SLAVE_TLMM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_tme_cfg = {
+ .name = "qhs_tme_cfg",
+ .id = SAR2130P_SLAVE_TME_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_usb3_0 = {
+ .name = "qhs_usb3_0",
+ .id = SAR2130P_SLAVE_USB3_0,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_venus_cfg = {
+ .name = "qhs_venus_cfg",
+ .id = SAR2130P_SLAVE_VENUS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_vsense_ctrl_cfg = {
+ .name = "qhs_vsense_ctrl_cfg",
+ .id = SAR2130P_SLAVE_VSENSE_CTRL_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_wlan_q6 = {
+ .name = "qhs_wlan_q6",
+ .id = SAR2130P_SLAVE_WLAN_Q6_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_ddrss_cfg = {
+ .name = "qns_ddrss_cfg",
+ .id = SAR2130P_SLAVE_DDRSS_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mnoc_cfg = {
+ .name = "qns_mnoc_cfg",
+ .id = SAR2130P_SLAVE_CNOC_MNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_CNOC_MNOC_CFG },
+};
+
+static struct qcom_icc_node qns_snoc_cfg = {
+ .name = "qns_snoc_cfg",
+ .id = SAR2130P_SLAVE_SNOC_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_SNOC_CFG },
+};
+
+static struct qcom_icc_node qxs_imem = {
+ .name = "qxs_imem",
+ .id = SAR2130P_SLAVE_IMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qxs_pimem = {
+ .name = "qxs_pimem",
+ .id = SAR2130P_SLAVE_PIMEM,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_cnoc = {
+ .name = "srvc_cnoc",
+ .id = SAR2130P_SLAVE_SERVICE_CNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_0 = {
+ .name = "xs_pcie_0",
+ .id = SAR2130P_SLAVE_PCIE_0,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_pcie_1 = {
+ .name = "xs_pcie_1",
+ .id = SAR2130P_SLAVE_PCIE_1,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_qdss_stm = {
+ .name = "xs_qdss_stm",
+ .id = SAR2130P_SLAVE_QDSS_STM,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node xs_sys_tcu_cfg = {
+ .name = "xs_sys_tcu_cfg",
+ .id = SAR2130P_SLAVE_TCU,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_gem_noc_cnoc = {
+ .name = "qns_gem_noc_cnoc",
+ .id = SAR2130P_SLAVE_GEM_NOC_CNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_GEM_NOC_CNOC },
+};
+
+static struct qcom_icc_node qns_llcc = {
+ .name = "qns_llcc",
+ .id = SAR2130P_SLAVE_LLCC,
+ .channels = 2,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_LLCC },
+};
+
+static struct qcom_icc_node qns_pcie = {
+ .name = "qns_pcie",
+ .id = SAR2130P_SLAVE_MEM_NOC_PCIE_SNOC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_GEM_NOC_PCIE_SNOC },
+};
+
+static struct qcom_icc_node qhs_lpass_core = {
+ .name = "qhs_lpass_core",
+ .id = SAR2130P_SLAVE_LPASS_CORE_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_lpi = {
+ .name = "qhs_lpass_lpi",
+ .id = SAR2130P_SLAVE_LPASS_LPI_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_mpu = {
+ .name = "qhs_lpass_mpu",
+ .id = SAR2130P_SLAVE_LPASS_MPU_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qhs_lpass_top = {
+ .name = "qhs_lpass_top",
+ .id = SAR2130P_SLAVE_LPASS_TOP_CFG,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_sysnoc = {
+ .name = "qns_sysnoc",
+ .id = SAR2130P_SLAVE_LPASS_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_LPASS_ANOC },
+};
+
+static struct qcom_icc_node srvc_niu_aml_noc = {
+ .name = "srvc_niu_aml_noc",
+ .id = SAR2130P_SLAVE_SERVICES_LPASS_AML_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node srvc_niu_lpass_agnoc = {
+ .name = "srvc_niu_lpass_agnoc",
+ .id = SAR2130P_SLAVE_SERVICE_LPASS_AG_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node ebi = {
+ .name = "ebi",
+ .id = SAR2130P_SLAVE_EBI1,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_mem_noc_hf = {
+ .name = "qns_mem_noc_hf",
+ .id = SAR2130P_SLAVE_MNOC_HF_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_MNOC_HF_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_mem_noc_sf = {
+ .name = "qns_mem_noc_sf",
+ .id = SAR2130P_SLAVE_MNOC_SF_MEM_NOC,
+ .channels = 1,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_MNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_mnoc = {
+ .name = "srvc_mnoc",
+ .id = SAR2130P_SLAVE_SERVICE_MNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_nsp_gemnoc = {
+ .name = "qns_nsp_gemnoc",
+ .id = SAR2130P_SLAVE_CDSP_MEM_NOC,
+ .channels = 2,
+ .buswidth = 32,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_COMPUTE_NOC },
+};
+
+static struct qcom_icc_node service_nsp_noc = {
+ .name = "service_nsp_noc",
+ .id = SAR2130P_SLAVE_SERVICE_NSP_NOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_node qns_pcie_mem_noc = {
+ .name = "qns_pcie_mem_noc",
+ .id = SAR2130P_SLAVE_ANOC_PCIE_GEM_NOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_ANOC_PCIE_GEM_NOC },
+};
+
+static struct qcom_icc_node qns_a2noc_snoc = {
+ .name = "qns_a2noc_snoc",
+ .id = SAR2130P_SLAVE_A2NOC_SNOC,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_A2NOC_SNOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_gc = {
+ .name = "qns_gemnoc_gc",
+ .id = SAR2130P_SLAVE_SNOC_GEM_NOC_GC,
+ .channels = 1,
+ .buswidth = 8,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_SNOC_GC_MEM_NOC },
+};
+
+static struct qcom_icc_node qns_gemnoc_sf = {
+ .name = "qns_gemnoc_sf",
+ .id = SAR2130P_SLAVE_SNOC_GEM_NOC_SF,
+ .channels = 1,
+ .buswidth = 16,
+ .num_links = 1,
+ .links = { SAR2130P_MASTER_SNOC_SF_MEM_NOC },
+};
+
+static struct qcom_icc_node srvc_snoc = {
+ .name = "srvc_snoc",
+ .id = SAR2130P_SLAVE_SERVICE_SNOC,
+ .channels = 1,
+ .buswidth = 4,
+ .num_links = 0,
+};
+
+static struct qcom_icc_bcm bcm_acv = {
+ .name = "ACV",
+ .enable_mask = BIT(3),
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_ce0 = {
+ .name = "CE0",
+ .num_nodes = 1,
+ .nodes = { &qxm_crypto },
+};
+
+static struct qcom_icc_bcm bcm_cn0 = {
+ .name = "CN0",
+ .enable_mask = BIT(0),
+ .keepalive = true,
+ .num_nodes = 48,
+ .nodes = { &qnm_gemnoc_cnoc, &qnm_gemnoc_pcie,
+ &xm_qdss_dap, &qhs_ahb2phy0,
+ &qhs_aoss, &qhs_camera_cfg,
+ &qhs_clk_ctl, &qhs_compute_cfg,
+ &qhs_cpr_cx, &qhs_cpr_mmcx,
+ &qhs_cpr_mxa, &qhs_cpr_mxc,
+ &qhs_cpr_nspcx, &qhs_crypto0_cfg,
+ &qhs_cx_rdpm, &qhs_display_cfg,
+ &qhs_gpuss_cfg, &qhs_imem_cfg,
+ &qhs_ipc_router, &qhs_lpass_cfg,
+ &qhs_mx_rdpm, &qhs_pcie0_cfg,
+ &qhs_pcie1_cfg, &qhs_pdm,
+ &qhs_pimem_cfg, &qhs_prng,
+ &qhs_qdss_cfg, &qhs_qspi,
+ &qhs_qup0, &qhs_qup1,
+ &qhs_sdc1, &qhs_tcsr,
+ &qhs_tlmm, &qhs_tme_cfg,
+ &qhs_usb3_0, &qhs_venus_cfg,
+ &qhs_vsense_ctrl_cfg, &qhs_wlan_q6,
+ &qns_ddrss_cfg, &qns_mnoc_cfg,
+ &qns_snoc_cfg, &qxs_imem,
+ &qxs_pimem, &srvc_cnoc,
+ &xs_pcie_0, &xs_pcie_1,
+ &xs_qdss_stm, &xs_sys_tcu_cfg },
+};
+
+static struct qcom_icc_bcm bcm_co0 = {
+ .name = "CO0",
+ .enable_mask = BIT(0),
+ .num_nodes = 2,
+ .nodes = { &qxm_nsp, &qns_nsp_gemnoc },
+};
+
+static struct qcom_icc_bcm bcm_mc0 = {
+ .name = "MC0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &ebi },
+};
+
+static struct qcom_icc_bcm bcm_mm0 = {
+ .name = "MM0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_mem_noc_hf },
+};
+
+static struct qcom_icc_bcm bcm_mm1 = {
+ .name = "MM1",
+ .enable_mask = BIT(0),
+ .num_nodes = 11,
+ .nodes = { &qnm_camnoc_hf, &qnm_camnoc_icp,
+ &qnm_camnoc_sf, &qnm_lsr,
+ &qnm_mdp, &qnm_mnoc_cfg,
+ &qnm_video, &qnm_video_cv_cpu,
+ &qnm_video_cvp, &qnm_video_v_cpu,
+ &qns_mem_noc_sf },
+};
+
+static struct qcom_icc_bcm bcm_qup0 = {
+ .name = "QUP0",
+ .keepalive = true,
+ .vote_scale = 1,
+ .num_nodes = 1,
+ .nodes = { &qup0_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_qup1 = {
+ .name = "QUP1",
+ .keepalive = true,
+ .vote_scale = 1,
+ .num_nodes = 1,
+ .nodes = { &qup1_core_slave },
+};
+
+static struct qcom_icc_bcm bcm_sh0 = {
+ .name = "SH0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_llcc },
+};
+
+static struct qcom_icc_bcm bcm_sh1 = {
+ .name = "SH1",
+ .enable_mask = BIT(0),
+ .num_nodes = 13,
+ .nodes = { &alm_gpu_tcu, &alm_sys_tcu,
+ &chm_apps, &qnm_gpu,
+ &qnm_mnoc_hf, &qnm_mnoc_sf,
+ &qnm_nsp_gemnoc, &qnm_pcie,
+ &qnm_snoc_gc, &qnm_snoc_sf,
+ &qxm_wlan_q6, &qns_gem_noc_cnoc,
+ &qns_pcie },
+};
+
+static struct qcom_icc_bcm bcm_sn0 = {
+ .name = "SN0",
+ .keepalive = true,
+ .num_nodes = 1,
+ .nodes = { &qns_gemnoc_sf },
+};
+
+static struct qcom_icc_bcm bcm_sn1 = {
+ .name = "SN1",
+ .enable_mask = BIT(0),
+ .num_nodes = 4,
+ .nodes = { &qhm_gic, &qxm_pimem,
+ &xm_gic, &qns_gemnoc_gc },
+};
+
+static struct qcom_icc_bcm bcm_sn3 = {
+ .name = "SN3",
+ .num_nodes = 1,
+ .nodes = { &qnm_aggre2_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn4 = {
+ .name = "SN4",
+ .num_nodes = 1,
+ .nodes = { &qnm_lpass_noc },
+};
+
+static struct qcom_icc_bcm bcm_sn7 = {
+ .name = "SN7",
+ .num_nodes = 1,
+ .nodes = { &qns_pcie_mem_noc },
+};
+
+static struct qcom_icc_bcm * const clk_virt_bcms[] = {
+ &bcm_qup0,
+ &bcm_qup1,
+};
+
+static struct qcom_icc_node * const clk_virt_nodes[] = {
+ [MASTER_QUP_CORE_0] = &qup0_core_master,
+ [MASTER_QUP_CORE_1] = &qup1_core_master,
+ [SLAVE_QUP_CORE_0] = &qup0_core_slave,
+ [SLAVE_QUP_CORE_1] = &qup1_core_slave,
+};
+
+static const struct qcom_icc_desc sar2130p_clk_virt = {
+ .nodes = clk_virt_nodes,
+ .num_nodes = ARRAY_SIZE(clk_virt_nodes),
+ .bcms = clk_virt_bcms,
+ .num_bcms = ARRAY_SIZE(clk_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const config_noc_bcms[] = {
+ &bcm_cn0,
+};
+
+static struct qcom_icc_node * const config_noc_nodes[] = {
+ [MASTER_GEM_NOC_CNOC] = &qnm_gemnoc_cnoc,
+ [MASTER_GEM_NOC_PCIE_SNOC] = &qnm_gemnoc_pcie,
+ [MASTER_QDSS_DAP] = &xm_qdss_dap,
+ [SLAVE_AHB2PHY_SOUTH] = &qhs_ahb2phy0,
+ [SLAVE_AOSS] = &qhs_aoss,
+ [SLAVE_CAMERA_CFG] = &qhs_camera_cfg,
+ [SLAVE_CLK_CTL] = &qhs_clk_ctl,
+ [SLAVE_CDSP_CFG] = &qhs_compute_cfg,
+ [SLAVE_RBCPR_CX_CFG] = &qhs_cpr_cx,
+ [SLAVE_RBCPR_MMCX_CFG] = &qhs_cpr_mmcx,
+ [SLAVE_RBCPR_MXA_CFG] = &qhs_cpr_mxa,
+ [SLAVE_RBCPR_MXC_CFG] = &qhs_cpr_mxc,
+ [SLAVE_CPR_NSPCX] = &qhs_cpr_nspcx,
+ [SLAVE_CRYPTO_0_CFG] = &qhs_crypto0_cfg,
+ [SLAVE_CX_RDPM] = &qhs_cx_rdpm,
+ [SLAVE_DISPLAY_CFG] = &qhs_display_cfg,
+ [SLAVE_GFX3D_CFG] = &qhs_gpuss_cfg,
+ [SLAVE_IMEM_CFG] = &qhs_imem_cfg,
+ [SLAVE_IPC_ROUTER_CFG] = &qhs_ipc_router,
+ [SLAVE_LPASS] = &qhs_lpass_cfg,
+ [SLAVE_MX_RDPM] = &qhs_mx_rdpm,
+ [SLAVE_PCIE_0_CFG] = &qhs_pcie0_cfg,
+ [SLAVE_PCIE_1_CFG] = &qhs_pcie1_cfg,
+ [SLAVE_PDM] = &qhs_pdm,
+ [SLAVE_PIMEM_CFG] = &qhs_pimem_cfg,
+ [SLAVE_PRNG] = &qhs_prng,
+ [SLAVE_QDSS_CFG] = &qhs_qdss_cfg,
+ [SLAVE_QSPI_0] = &qhs_qspi,
+ [SLAVE_QUP_0] = &qhs_qup0,
+ [SLAVE_QUP_1] = &qhs_qup1,
+ [SLAVE_SDCC_1] = &qhs_sdc1,
+ [SLAVE_TCSR] = &qhs_tcsr,
+ [SLAVE_TLMM] = &qhs_tlmm,
+ [SLAVE_TME_CFG] = &qhs_tme_cfg,
+ [SLAVE_USB3_0] = &qhs_usb3_0,
+ [SLAVE_VENUS_CFG] = &qhs_venus_cfg,
+ [SLAVE_VSENSE_CTRL_CFG] = &qhs_vsense_ctrl_cfg,
+ [SLAVE_WLAN_Q6_CFG] = &qhs_wlan_q6,
+ [SLAVE_DDRSS_CFG] = &qns_ddrss_cfg,
+ [SLAVE_CNOC_MNOC_CFG] = &qns_mnoc_cfg,
+ [SLAVE_SNOC_CFG] = &qns_snoc_cfg,
+ [SLAVE_IMEM] = &qxs_imem,
+ [SLAVE_PIMEM] = &qxs_pimem,
+ [SLAVE_SERVICE_CNOC] = &srvc_cnoc,
+ [SLAVE_PCIE_0] = &xs_pcie_0,
+ [SLAVE_PCIE_1] = &xs_pcie_1,
+ [SLAVE_QDSS_STM] = &xs_qdss_stm,
+ [SLAVE_TCU] = &xs_sys_tcu_cfg,
+};
+
+static const struct qcom_icc_desc sar2130p_config_noc = {
+ .config = &icc_regmap_config,
+ .nodes = config_noc_nodes,
+ .num_nodes = ARRAY_SIZE(config_noc_nodes),
+ .bcms = config_noc_bcms,
+ .num_bcms = ARRAY_SIZE(config_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const gem_noc_bcms[] = {
+ &bcm_sh0,
+ &bcm_sh1,
+};
+
+static struct qcom_icc_node * const gem_noc_nodes[] = {
+ [MASTER_GPU_TCU] = &alm_gpu_tcu,
+ [MASTER_SYS_TCU] = &alm_sys_tcu,
+ [MASTER_APPSS_PROC] = &chm_apps,
+ [MASTER_GFX3D] = &qnm_gpu,
+ [MASTER_MNOC_HF_MEM_NOC] = &qnm_mnoc_hf,
+ [MASTER_MNOC_SF_MEM_NOC] = &qnm_mnoc_sf,
+ [MASTER_COMPUTE_NOC] = &qnm_nsp_gemnoc,
+ [MASTER_ANOC_PCIE_GEM_NOC] = &qnm_pcie,
+ [MASTER_SNOC_GC_MEM_NOC] = &qnm_snoc_gc,
+ [MASTER_SNOC_SF_MEM_NOC] = &qnm_snoc_sf,
+ [MASTER_WLAN_Q6] = &qxm_wlan_q6,
+ [SLAVE_GEM_NOC_CNOC] = &qns_gem_noc_cnoc,
+ [SLAVE_LLCC] = &qns_llcc,
+ [SLAVE_MEM_NOC_PCIE_SNOC] = &qns_pcie,
+};
+
+static const struct qcom_icc_desc sar2130p_gem_noc = {
+ .config = &icc_regmap_config,
+ .nodes = gem_noc_nodes,
+ .num_nodes = ARRAY_SIZE(gem_noc_nodes),
+ .bcms = gem_noc_bcms,
+ .num_bcms = ARRAY_SIZE(gem_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const lpass_ag_noc_bcms[] = {
+};
+
+static struct qcom_icc_node * const lpass_ag_noc_nodes[] = {
+ [MASTER_CNOC_LPASS_AG_NOC] = &qhm_config_noc,
+ [MASTER_LPASS_PROC] = &qxm_lpass_dsp,
+ [SLAVE_LPASS_CORE_CFG] = &qhs_lpass_core,
+ [SLAVE_LPASS_LPI_CFG] = &qhs_lpass_lpi,
+ [SLAVE_LPASS_MPU_CFG] = &qhs_lpass_mpu,
+ [SLAVE_LPASS_TOP_CFG] = &qhs_lpass_top,
+ [SLAVE_LPASS_SNOC] = &qns_sysnoc,
+ [SLAVE_SERVICES_LPASS_AML_NOC] = &srvc_niu_aml_noc,
+ [SLAVE_SERVICE_LPASS_AG_NOC] = &srvc_niu_lpass_agnoc,
+};
+
+static const struct qcom_icc_desc sar2130p_lpass_ag_noc = {
+ .config = &icc_regmap_config,
+ .nodes = lpass_ag_noc_nodes,
+ .num_nodes = ARRAY_SIZE(lpass_ag_noc_nodes),
+ .bcms = lpass_ag_noc_bcms,
+ .num_bcms = ARRAY_SIZE(lpass_ag_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const mc_virt_bcms[] = {
+ &bcm_acv,
+ &bcm_mc0,
+};
+
+static struct qcom_icc_node * const mc_virt_nodes[] = {
+ [MASTER_LLCC] = &llcc_mc,
+ [SLAVE_EBI1] = &ebi,
+};
+
+static const struct qcom_icc_desc sar2130p_mc_virt = {
+ .nodes = mc_virt_nodes,
+ .num_nodes = ARRAY_SIZE(mc_virt_nodes),
+ .bcms = mc_virt_bcms,
+ .num_bcms = ARRAY_SIZE(mc_virt_bcms),
+};
+
+static struct qcom_icc_bcm * const mmss_noc_bcms[] = {
+ &bcm_mm0,
+ &bcm_mm1,
+};
+
+static struct qcom_icc_node * const mmss_noc_nodes[] = {
+ [MASTER_CAMNOC_HF] = &qnm_camnoc_hf,
+ [MASTER_CAMNOC_ICP] = &qnm_camnoc_icp,
+ [MASTER_CAMNOC_SF] = &qnm_camnoc_sf,
+ [MASTER_LSR] = &qnm_lsr,
+ [MASTER_MDP] = &qnm_mdp,
+ [MASTER_CNOC_MNOC_CFG] = &qnm_mnoc_cfg,
+ [MASTER_VIDEO] = &qnm_video,
+ [MASTER_VIDEO_CV_PROC] = &qnm_video_cv_cpu,
+ [MASTER_VIDEO_PROC] = &qnm_video_cvp,
+ [MASTER_VIDEO_V_PROC] = &qnm_video_v_cpu,
+ [SLAVE_MNOC_HF_MEM_NOC] = &qns_mem_noc_hf,
+ [SLAVE_MNOC_SF_MEM_NOC] = &qns_mem_noc_sf,
+ [SLAVE_SERVICE_MNOC] = &srvc_mnoc,
+};
+
+static const struct qcom_icc_desc sar2130p_mmss_noc = {
+ .config = &icc_regmap_config,
+ .nodes = mmss_noc_nodes,
+ .num_nodes = ARRAY_SIZE(mmss_noc_nodes),
+ .bcms = mmss_noc_bcms,
+ .num_bcms = ARRAY_SIZE(mmss_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const nsp_noc_bcms[] = {
+ &bcm_co0,
+};
+
+static struct qcom_icc_node * const nsp_noc_nodes[] = {
+ [MASTER_CDSP_NOC_CFG] = &qhm_nsp_noc_config,
+ [MASTER_CDSP_PROC] = &qxm_nsp,
+ [SLAVE_CDSP_MEM_NOC] = &qns_nsp_gemnoc,
+ [SLAVE_SERVICE_NSP_NOC] = &service_nsp_noc,
+};
+
+static const struct qcom_icc_desc sar2130p_nsp_noc = {
+ .config = &icc_regmap_config,
+ .nodes = nsp_noc_nodes,
+ .num_nodes = ARRAY_SIZE(nsp_noc_nodes),
+ .bcms = nsp_noc_bcms,
+ .num_bcms = ARRAY_SIZE(nsp_noc_bcms),
+};
+
+static struct qcom_icc_bcm * const pcie_anoc_bcms[] = {
+ &bcm_sn7,
+};
+
+static struct qcom_icc_node * const pcie_anoc_nodes[] = {
+ [MASTER_PCIE_0] = &xm_pcie3_0,
+ [MASTER_PCIE_1] = &xm_pcie3_1,
+ [SLAVE_ANOC_PCIE_GEM_NOC] = &qns_pcie_mem_noc,
+};
+
+static const struct qcom_icc_desc sar2130p_pcie_anoc = {
+ .config = &icc_regmap_config,
+ .nodes = pcie_anoc_nodes,
+ .num_nodes = ARRAY_SIZE(pcie_anoc_nodes),
+ .bcms = pcie_anoc_bcms,
+ .num_bcms = ARRAY_SIZE(pcie_anoc_bcms),
+};
+
+static struct qcom_icc_bcm * const system_noc_bcms[] = {
+ &bcm_ce0,
+ &bcm_sn0,
+ &bcm_sn1,
+ &bcm_sn3,
+ &bcm_sn4,
+};
+
+static struct qcom_icc_node * const system_noc_nodes[] = {
+ [MASTER_GIC_AHB] = &qhm_gic,
+ [MASTER_QDSS_BAM] = &qhm_qdss_bam,
+ [MASTER_QSPI_0] = &qhm_qspi,
+ [MASTER_QUP_0] = &qhm_qup0,
+ [MASTER_QUP_1] = &qhm_qup1,
+ [MASTER_A2NOC_SNOC] = &qnm_aggre2_noc,
+ [MASTER_CNOC_DATAPATH] = &qnm_cnoc_datapath,
+ [MASTER_LPASS_ANOC] = &qnm_lpass_noc,
+ [MASTER_SNOC_CFG] = &qnm_snoc_cfg,
+ [MASTER_CRYPTO] = &qxm_crypto,
+ [MASTER_PIMEM] = &qxm_pimem,
+ [MASTER_GIC] = &xm_gic,
+ [MASTER_QDSS_ETR] = &xm_qdss_etr_0,
+ [MASTER_QDSS_ETR_1] = &xm_qdss_etr_1,
+ [MASTER_SDCC_1] = &xm_sdc1,
+ [MASTER_USB3_0] = &xm_usb3_0,
+ [SLAVE_A2NOC_SNOC] = &qns_a2noc_snoc,
+ [SLAVE_SNOC_GEM_NOC_GC] = &qns_gemnoc_gc,
+ [SLAVE_SNOC_GEM_NOC_SF] = &qns_gemnoc_sf,
+ [SLAVE_SERVICE_SNOC] = &srvc_snoc,
+};
+
+static const struct qcom_icc_desc sar2130p_system_noc = {
+ .config = &icc_regmap_config,
+ .nodes = system_noc_nodes,
+ .num_nodes = ARRAY_SIZE(system_noc_nodes),
+ .bcms = system_noc_bcms,
+ .num_bcms = ARRAY_SIZE(system_noc_bcms),
+};
+
+static const struct of_device_id qnoc_of_match[] = {
+ { .compatible = "qcom,sar2130p-clk-virt", .data = &sar2130p_clk_virt},
+ { .compatible = "qcom,sar2130p-config-noc", .data = &sar2130p_config_noc},
+ { .compatible = "qcom,sar2130p-gem-noc", .data = &sar2130p_gem_noc},
+ { .compatible = "qcom,sar2130p-lpass-ag-noc", .data = &sar2130p_lpass_ag_noc},
+ { .compatible = "qcom,sar2130p-mc-virt", .data = &sar2130p_mc_virt},
+ { .compatible = "qcom,sar2130p-mmss-noc", .data = &sar2130p_mmss_noc},
+ { .compatible = "qcom,sar2130p-nsp-noc", .data = &sar2130p_nsp_noc},
+ { .compatible = "qcom,sar2130p-pcie-anoc", .data = &sar2130p_pcie_anoc},
+ { .compatible = "qcom,sar2130p-system-noc", .data = &sar2130p_system_noc},
+ { }
+};
+MODULE_DEVICE_TABLE(of, qnoc_of_match);
+
+static struct platform_driver qnoc_driver = {
+ .probe = qcom_icc_rpmh_probe,
+ .remove = qcom_icc_rpmh_remove,
+ .driver = {
+ .name = "qnoc-sar2130p",
+ .of_match_table = qnoc_of_match,
+ .sync_state = icc_sync_state,
+ },
+};
+
+static int __init qnoc_driver_init(void)
+{
+ return platform_driver_register(&qnoc_driver);
+}
+core_initcall(qnoc_driver_init);
+
+static void __exit qnoc_driver_exit(void)
+{
+ platform_driver_unregister(&qnoc_driver);
+}
+
+module_exit(qnoc_driver_exit);
+MODULE_DESCRIPTION("Qualcomm SAR2130P NoC driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/interconnect/qcom/sc7180.c b/drivers/interconnect/qcom/sc7180.c
index 34a1d163d6e1..af2be1543840 100644
--- a/drivers/interconnect/qcom/sc7180.c
+++ b/drivers/interconnect/qcom/sc7180.c
@@ -1807,7 +1807,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc7180",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc7280.c b/drivers/interconnect/qcom/sc7280.c
index 167971f8e8be..346f18d70e9e 100644
--- a/drivers/interconnect/qcom/sc7280.c
+++ b/drivers/interconnect/qcom/sc7280.c
@@ -1691,7 +1691,7 @@ static const struct qcom_icc_desc sc7280_aggre1_noc = {
.num_nodes = ARRAY_SIZE(aggre1_noc_nodes),
.bcms = aggre1_noc_bcms,
.num_bcms = ARRAY_SIZE(aggre1_noc_bcms),
- .qos_clks_required = true,
+ .qos_requires_clocks = true,
};
static struct qcom_icc_bcm * const aggre2_noc_bcms[] = {
@@ -1723,7 +1723,7 @@ static const struct qcom_icc_desc sc7280_aggre2_noc = {
.num_nodes = ARRAY_SIZE(aggre2_noc_nodes),
.bcms = aggre2_noc_bcms,
.num_bcms = ARRAY_SIZE(aggre2_noc_bcms),
- .qos_clks_required = true,
+ .qos_requires_clocks = true,
};
static struct qcom_icc_bcm * const clk_virt_bcms[] = {
@@ -2111,7 +2111,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc7280",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc8180x.c b/drivers/interconnect/qcom/sc8180x.c
index 03d626776ba1..a741badaa966 100644
--- a/drivers/interconnect/qcom/sc8180x.c
+++ b/drivers/interconnect/qcom/sc8180x.c
@@ -1889,7 +1889,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc8180x",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sc8280xp.c b/drivers/interconnect/qcom/sc8280xp.c
index 7acd152bf0dd..0270f6c64481 100644
--- a/drivers/interconnect/qcom/sc8280xp.c
+++ b/drivers/interconnect/qcom/sc8280xp.c
@@ -2391,7 +2391,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sc8280xp",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdm660.c b/drivers/interconnect/qcom/sdm660.c
index ab91de446da8..7392bebba334 100644
--- a/drivers/interconnect/qcom/sdm660.c
+++ b/drivers/interconnect/qcom/sdm660.c
@@ -1714,7 +1714,7 @@ MODULE_DEVICE_TABLE(of, sdm660_noc_of_match);
static struct platform_driver sdm660_noc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-sdm660",
.of_match_table = sdm660_noc_of_match,
diff --git a/drivers/interconnect/qcom/sdm670.c b/drivers/interconnect/qcom/sdm670.c
index e5ee7fbaa641..907e1ff4ff81 100644
--- a/drivers/interconnect/qcom/sdm670.c
+++ b/drivers/interconnect/qcom/sdm670.c
@@ -1533,7 +1533,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdm670",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdm845.c b/drivers/interconnect/qcom/sdm845.c
index 584800ac871a..855802be93fe 100644
--- a/drivers/interconnect/qcom/sdm845.c
+++ b/drivers/interconnect/qcom/sdm845.c
@@ -1802,7 +1802,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdm845",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdx55.c b/drivers/interconnect/qcom/sdx55.c
index e97f28b8d2b2..4117db046fa0 100644
--- a/drivers/interconnect/qcom/sdx55.c
+++ b/drivers/interconnect/qcom/sdx55.c
@@ -913,7 +913,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdx55",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdx65.c b/drivers/interconnect/qcom/sdx65.c
index 2f3f5479d8a5..d3a6c6c148e5 100644
--- a/drivers/interconnect/qcom/sdx65.c
+++ b/drivers/interconnect/qcom/sdx65.c
@@ -897,7 +897,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdx65",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sdx75.c b/drivers/interconnect/qcom/sdx75.c
index 7f422c27488d..7ef1f17f3292 100644
--- a/drivers/interconnect/qcom/sdx75.c
+++ b/drivers/interconnect/qcom/sdx75.c
@@ -1083,7 +1083,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sdx75",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm6115.c b/drivers/interconnect/qcom/sm6115.c
index 271b07c74862..3ee12c8a4d56 100644
--- a/drivers/interconnect/qcom/sm6115.c
+++ b/drivers/interconnect/qcom/sm6115.c
@@ -1402,7 +1402,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qnoc_probe,
- .remove_new = qnoc_remove,
+ .remove = qnoc_remove,
.driver = {
.name = "qnoc-sm6115",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm6350.c b/drivers/interconnect/qcom/sm6350.c
index 20923e8e6110..f41d7e19ba26 100644
--- a/drivers/interconnect/qcom/sm6350.c
+++ b/drivers/interconnect/qcom/sm6350.c
@@ -1702,7 +1702,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm6350",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm7150.c b/drivers/interconnect/qcom/sm7150.c
index dc0d1343f510..c8c77407cd50 100644
--- a/drivers/interconnect/qcom/sm7150.c
+++ b/drivers/interconnect/qcom/sm7150.c
@@ -1730,7 +1730,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm7150",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8150.c b/drivers/interconnect/qcom/sm8150.c
index f29b77556a79..edfe824cad35 100644
--- a/drivers/interconnect/qcom/sm8150.c
+++ b/drivers/interconnect/qcom/sm8150.c
@@ -1864,7 +1864,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8150",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8250.c b/drivers/interconnect/qcom/sm8250.c
index 1879fa15761f..cc1b14c13529 100644
--- a/drivers/interconnect/qcom/sm8250.c
+++ b/drivers/interconnect/qcom/sm8250.c
@@ -1991,7 +1991,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8250",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8350.c b/drivers/interconnect/qcom/sm8350.c
index 4236a43dc256..38105ead4f29 100644
--- a/drivers/interconnect/qcom/sm8350.c
+++ b/drivers/interconnect/qcom/sm8350.c
@@ -1807,7 +1807,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8350",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8450.c b/drivers/interconnect/qcom/sm8450.c
index b3cd0087377c..eb7e17df32ba 100644
--- a/drivers/interconnect/qcom/sm8450.c
+++ b/drivers/interconnect/qcom/sm8450.c
@@ -1884,7 +1884,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8450",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8550.c b/drivers/interconnect/qcom/sm8550.c
index 4d0e6fa9e003..fdb97d1f1d07 100644
--- a/drivers/interconnect/qcom/sm8550.c
+++ b/drivers/interconnect/qcom/sm8550.c
@@ -1645,7 +1645,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8550",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/sm8650.c b/drivers/interconnect/qcom/sm8650.c
index b962e6c233ef..20ac5bc5e1fb 100644
--- a/drivers/interconnect/qcom/sm8650.c
+++ b/drivers/interconnect/qcom/sm8650.c
@@ -1650,7 +1650,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-sm8650",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/qcom/smd-rpm.c b/drivers/interconnect/qcom/smd-rpm.c
index 3816bfb4e2f3..8316c87a2c60 100644
--- a/drivers/interconnect/qcom/smd-rpm.c
+++ b/drivers/interconnect/qcom/smd-rpm.c
@@ -85,7 +85,7 @@ static struct platform_driver qcom_interconnect_rpm_smd_driver = {
.name = "icc_smd_rpm",
},
.probe = qcom_icc_rpm_smd_probe,
- .remove_new = qcom_icc_rpm_smd_remove,
+ .remove = qcom_icc_rpm_smd_remove,
};
module_platform_driver(qcom_interconnect_rpm_smd_driver);
MODULE_AUTHOR("Georgi Djakov <georgi.djakov@linaro.org>");
diff --git a/drivers/interconnect/qcom/x1e80100.c b/drivers/interconnect/qcom/x1e80100.c
index 654abb9ce08e..2c46fdb4a054 100644
--- a/drivers/interconnect/qcom/x1e80100.c
+++ b/drivers/interconnect/qcom/x1e80100.c
@@ -1964,7 +1964,7 @@ MODULE_DEVICE_TABLE(of, qnoc_of_match);
static struct platform_driver qnoc_driver = {
.probe = qcom_icc_rpmh_probe,
- .remove_new = qcom_icc_rpmh_remove,
+ .remove = qcom_icc_rpmh_remove,
.driver = {
.name = "qnoc-x1e80100",
.of_match_table = qnoc_of_match,
diff --git a/drivers/interconnect/samsung/exynos.c b/drivers/interconnect/samsung/exynos.c
index c9e5361e17c5..9e041365d909 100644
--- a/drivers/interconnect/samsung/exynos.c
+++ b/drivers/interconnect/samsung/exynos.c
@@ -180,7 +180,7 @@ static struct platform_driver exynos_generic_icc_driver = {
.sync_state = icc_sync_state,
},
.probe = exynos_generic_icc_probe,
- .remove_new = exynos_generic_icc_remove,
+ .remove = exynos_generic_icc_remove,
};
module_platform_driver(exynos_generic_icc_driver);
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 3f691e1fd22c..16f40b8000d7 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -1415,6 +1415,7 @@ static int domain_flush_pages_v2(struct protection_domain *pdom,
struct iommu_cmd cmd;
int ret = 0;
+ lockdep_assert_held(&pdom->lock);
list_for_each_entry(dev_data, &pdom->dev_list, list) {
struct amd_iommu *iommu = get_amd_iommu_from_dev(dev_data->dev);
u16 domid = dev_data->gcr3_info.domid;
@@ -1464,6 +1465,8 @@ static void __domain_flush_pages(struct protection_domain *domain,
ioasid_t pasid = IOMMU_NO_PASID;
bool gn = false;
+ lockdep_assert_held(&domain->lock);
+
if (pdom_is_v2_pgtbl_mode(domain)) {
gn = true;
ret = domain_flush_pages_v2(domain, address, size);
@@ -1585,6 +1588,8 @@ void amd_iommu_update_and_flush_device_table(struct protection_domain *domain)
{
struct iommu_dev_data *dev_data;
+ lockdep_assert_held(&domain->lock);
+
list_for_each_entry(dev_data, &domain->dev_list, list) {
struct amd_iommu *iommu = rlookup_amd_iommu(dev_data->dev);
@@ -2073,6 +2078,7 @@ static int attach_device(struct device *dev,
struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
struct pci_dev *pdev;
+ unsigned long flags;
int ret = 0;
mutex_lock(&dev_data->mutex);
@@ -2113,7 +2119,9 @@ static int attach_device(struct device *dev,
/* Update data structures */
dev_data->domain = domain;
+ spin_lock_irqsave(&domain->lock, flags);
list_add(&dev_data->list, &domain->dev_list);
+ spin_unlock_irqrestore(&domain->lock, flags);
/* Update device table */
dev_update_dte(dev_data, true);
@@ -2160,6 +2168,7 @@ static void detach_device(struct device *dev)
/* Flush IOTLB and wait for the flushes to finish */
spin_lock_irqsave(&domain->lock, flags);
amd_iommu_domain_flush_all(domain);
+ list_del(&dev_data->list);
spin_unlock_irqrestore(&domain->lock, flags);
/* Clear GCR3 table */
@@ -2168,7 +2177,6 @@ static void detach_device(struct device *dev)
/* Update data structures */
dev_data->domain = NULL;
- list_del(&dev_data->list);
/* decrease reference counters - needs to happen after the flushes */
pdom_detach_iommu(iommu, domain);
diff --git a/drivers/iommu/apple-dart.c b/drivers/iommu/apple-dart.c
index eb1e62cd499a..95ba3caeb401 100644
--- a/drivers/iommu/apple-dart.c
+++ b/drivers/iommu/apple-dart.c
@@ -1352,7 +1352,7 @@ static struct platform_driver apple_dart_driver = {
.pm = pm_sleep_ptr(&apple_dart_pm_ops),
},
.probe = apple_dart_probe,
- .remove_new = apple_dart_remove,
+ .remove = apple_dart_remove,
};
module_platform_driver(apple_dart_driver);
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
index 6cc14d82399f..c7cc613050d9 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-iommufd.c
@@ -398,4 +398,4 @@ struct iommufd_viommu *arm_vsmmu_alloc(struct device *dev,
return &vsmmu->core;
}
-MODULE_IMPORT_NS(IOMMUFD);
+MODULE_IMPORT_NS("IOMMUFD");
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
index 84baa021370a..d2671bfd3798 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3-test.c
@@ -607,6 +607,6 @@ static struct kunit_suite arm_smmu_v3_test_module = {
};
kunit_test_suites(&arm_smmu_v3_test_module);
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
MODULE_DESCRIPTION("KUnit tests for arm-smmu-v3 driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index e4ebd9e12ad4..a5c7002ff75b 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -4729,7 +4729,7 @@ static struct platform_driver arm_smmu_driver = {
.suppress_bind_attrs = true,
},
.probe = arm_smmu_device_probe,
- .remove_new = arm_smmu_device_remove,
+ .remove = arm_smmu_device_remove,
.shutdown = arm_smmu_device_shutdown,
};
module_driver(arm_smmu_driver, platform_driver_register,
diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
index c8ec74f089f3..6e41ddaa24d6 100644
--- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
+++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
@@ -339,7 +339,7 @@ tegra241_cmdqv_get_cmdq(struct arm_smmu_device *smmu,
* one CPU at a time can enter the process, while the others
* will be spinning at the same lock.
*/
- lidx = smp_processor_id() % cmdqv->num_lvcmdqs_per_vintf;
+ lidx = raw_smp_processor_id() % cmdqv->num_lvcmdqs_per_vintf;
vcmdq = vintf->lvcmdqs[lidx];
if (!vcmdq || !READ_ONCE(vcmdq->enabled))
return NULL;
diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c b/drivers/iommu/arm/arm-smmu/arm-smmu.c
index ade4684c14c9..650664e0f6e3 100644
--- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
+++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
@@ -2367,7 +2367,7 @@ static struct platform_driver arm_smmu_driver = {
.suppress_bind_attrs = true,
},
.probe = arm_smmu_device_probe,
- .remove_new = arm_smmu_device_remove,
+ .remove = arm_smmu_device_remove,
.shutdown = arm_smmu_device_shutdown,
};
module_platform_driver(arm_smmu_driver);
diff --git a/drivers/iommu/arm/arm-smmu/qcom_iommu.c b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
index b98a7a598b89..3907924646a2 100644
--- a/drivers/iommu/arm/arm-smmu/qcom_iommu.c
+++ b/drivers/iommu/arm/arm-smmu/qcom_iommu.c
@@ -759,7 +759,7 @@ static struct platform_driver qcom_iommu_ctx_driver = {
.of_match_table = ctx_of_match,
},
.probe = qcom_iommu_ctx_probe,
- .remove_new = qcom_iommu_ctx_remove,
+ .remove = qcom_iommu_ctx_remove,
};
static bool qcom_iommu_has_secure_context(struct qcom_iommu_dev *qcom_iommu)
@@ -931,7 +931,7 @@ static struct platform_driver qcom_iommu_driver = {
.pm = &qcom_iommu_pm_ops,
},
.probe = qcom_iommu_device_probe,
- .remove_new = qcom_iommu_device_remove,
+ .remove = qcom_iommu_device_remove,
};
static int __init qcom_iommu_init(void)
diff --git a/drivers/iommu/intel/cache.c b/drivers/iommu/intel/cache.c
index e5b89f728ad3..09694cca8752 100644
--- a/drivers/iommu/intel/cache.c
+++ b/drivers/iommu/intel/cache.c
@@ -105,12 +105,35 @@ static void cache_tag_unassign(struct dmar_domain *domain, u16 did,
spin_unlock_irqrestore(&domain->cache_lock, flags);
}
+/* domain->qi_batch will be freed in iommu_free_domain() path. */
+static int domain_qi_batch_alloc(struct dmar_domain *domain)
+{
+ unsigned long flags;
+ int ret = 0;
+
+ spin_lock_irqsave(&domain->cache_lock, flags);
+ if (domain->qi_batch)
+ goto out_unlock;
+
+ domain->qi_batch = kzalloc(sizeof(*domain->qi_batch), GFP_ATOMIC);
+ if (!domain->qi_batch)
+ ret = -ENOMEM;
+out_unlock:
+ spin_unlock_irqrestore(&domain->cache_lock, flags);
+
+ return ret;
+}
+
static int __cache_tag_assign_domain(struct dmar_domain *domain, u16 did,
struct device *dev, ioasid_t pasid)
{
struct device_domain_info *info = dev_iommu_priv_get(dev);
int ret;
+ ret = domain_qi_batch_alloc(domain);
+ if (ret)
+ return ret;
+
ret = cache_tag_assign(domain, did, dev, pasid, CACHE_TAG_IOTLB);
if (ret || !info->ats_enabled)
return ret;
@@ -139,6 +162,10 @@ static int __cache_tag_assign_parent_domain(struct dmar_domain *domain, u16 did,
struct device_domain_info *info = dev_iommu_priv_get(dev);
int ret;
+ ret = domain_qi_batch_alloc(domain);
+ if (ret)
+ return ret;
+
ret = cache_tag_assign(domain, did, dev, pasid, CACHE_TAG_NESTING_IOTLB);
if (ret || !info->ats_enabled)
return ret;
@@ -190,13 +217,6 @@ int cache_tag_assign_domain(struct dmar_domain *domain,
u16 did = domain_get_id_for_dev(domain, dev);
int ret;
- /* domain->qi_bach will be freed in iommu_free_domain() path. */
- if (!domain->qi_batch) {
- domain->qi_batch = kzalloc(sizeof(*domain->qi_batch), GFP_KERNEL);
- if (!domain->qi_batch)
- return -ENOMEM;
- }
-
ret = __cache_tag_assign_domain(domain, did, dev, pasid);
if (ret || domain->domain.type != IOMMU_DOMAIN_NESTED)
return ret;
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 7d0acb74d5a5..79e0da9eb626 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -3220,6 +3220,9 @@ void device_block_translation(struct device *dev)
struct intel_iommu *iommu = info->iommu;
unsigned long flags;
+ if (info->domain)
+ cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID);
+
iommu_disable_pci_caps(info);
if (!dev_is_real_dma_subdevice(dev)) {
if (sm_supported(iommu))
@@ -3236,7 +3239,6 @@ void device_block_translation(struct device *dev)
list_del(&info->link);
spin_unlock_irqrestore(&info->domain->lock, flags);
- cache_tag_unassign_domain(info->domain, dev, IOMMU_NO_PASID);
domain_detach_iommu(info->domain, iommu);
info->domain = NULL;
}
diff --git a/drivers/iommu/intel/pasid.c b/drivers/iommu/intel/pasid.c
index 0f2a926d3bd5..5b7d85f1e143 100644
--- a/drivers/iommu/intel/pasid.c
+++ b/drivers/iommu/intel/pasid.c
@@ -265,7 +265,8 @@ void intel_pasid_tear_down_entry(struct intel_iommu *iommu, struct device *dev,
iommu->flush.flush_iotlb(iommu, did, 0, 0, DMA_TLB_DSI_FLUSH);
devtlb_invalidation_with_pasid(iommu, dev, pasid);
- intel_iommu_drain_pasid_prq(dev, pasid);
+ if (!fault_ignore)
+ intel_iommu_drain_pasid_prq(dev, pasid);
}
/*
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 9bc0c74cca3c..599030e1e890 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2211,7 +2211,7 @@ int iommu_group_replace_domain(struct iommu_group *group,
mutex_unlock(&group->mutex);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(iommu_group_replace_domain, IOMMUFD_INTERNAL);
+EXPORT_SYMBOL_NS_GPL(iommu_group_replace_domain, "IOMMUFD_INTERNAL");
static int __iommu_device_set_domain(struct iommu_group *group,
struct device *dev,
@@ -3482,7 +3482,7 @@ iommu_attach_handle_get(struct iommu_group *group, ioasid_t pasid, unsigned int
return handle;
}
-EXPORT_SYMBOL_NS_GPL(iommu_attach_handle_get, IOMMUFD_INTERNAL);
+EXPORT_SYMBOL_NS_GPL(iommu_attach_handle_get, "IOMMUFD_INTERNAL");
/**
* iommu_attach_group_handle - Attach an IOMMU domain to an IOMMU group
@@ -3522,7 +3522,7 @@ err_unlock:
mutex_unlock(&group->mutex);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(iommu_attach_group_handle, IOMMUFD_INTERNAL);
+EXPORT_SYMBOL_NS_GPL(iommu_attach_group_handle, "IOMMUFD_INTERNAL");
/**
* iommu_detach_group_handle - Detach an IOMMU domain from an IOMMU group
@@ -3540,7 +3540,7 @@ void iommu_detach_group_handle(struct iommu_domain *domain,
xa_erase(&group->pasid_array, IOMMU_NO_PASID);
mutex_unlock(&group->mutex);
}
-EXPORT_SYMBOL_NS_GPL(iommu_detach_group_handle, IOMMUFD_INTERNAL);
+EXPORT_SYMBOL_NS_GPL(iommu_detach_group_handle, "IOMMUFD_INTERNAL");
/**
* iommu_replace_group_handle - replace the domain that a group is attached to
@@ -3586,4 +3586,4 @@ err_unlock:
mutex_unlock(&group->mutex);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(iommu_replace_group_handle, IOMMUFD_INTERNAL);
+EXPORT_SYMBOL_NS_GPL(iommu_replace_group_handle, "IOMMUFD_INTERNAL");
diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c
index 5fd3dd420290..dfd0898fb6c1 100644
--- a/drivers/iommu/iommufd/device.c
+++ b/drivers/iommu/iommufd/device.c
@@ -233,7 +233,7 @@ out_group_put:
iommufd_put_group(igroup);
return ERR_PTR(rc);
}
-EXPORT_SYMBOL_NS_GPL(iommufd_device_bind, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_device_bind, "IOMMUFD");
/**
* iommufd_ctx_has_group - True if any device within the group is bound
@@ -264,7 +264,7 @@ bool iommufd_ctx_has_group(struct iommufd_ctx *ictx, struct iommu_group *group)
xa_unlock(&ictx->objects);
return false;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_ctx_has_group, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_ctx_has_group, "IOMMUFD");
/**
* iommufd_device_unbind - Undo iommufd_device_bind()
@@ -279,19 +279,19 @@ void iommufd_device_unbind(struct iommufd_device *idev)
{
iommufd_object_destroy_user(idev->ictx, &idev->obj);
}
-EXPORT_SYMBOL_NS_GPL(iommufd_device_unbind, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_device_unbind, "IOMMUFD");
struct iommufd_ctx *iommufd_device_to_ictx(struct iommufd_device *idev)
{
return idev->ictx;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_device_to_ictx, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_device_to_ictx, "IOMMUFD");
u32 iommufd_device_to_id(struct iommufd_device *idev)
{
return idev->obj.id;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_device_to_id, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_device_to_id, "IOMMUFD");
static int iommufd_group_setup_msi(struct iommufd_group *igroup,
struct iommufd_hwpt_paging *hwpt_paging)
@@ -692,7 +692,7 @@ int iommufd_device_attach(struct iommufd_device *idev, u32 *pt_id)
refcount_inc(&idev->obj.users);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_device_attach, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_device_attach, "IOMMUFD");
/**
* iommufd_device_replace - Change the device's iommu_domain
@@ -714,7 +714,7 @@ int iommufd_device_replace(struct iommufd_device *idev, u32 *pt_id)
return iommufd_device_change_pt(idev, pt_id,
&iommufd_device_do_replace);
}
-EXPORT_SYMBOL_NS_GPL(iommufd_device_replace, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_device_replace, "IOMMUFD");
/**
* iommufd_device_detach - Disconnect a device to an iommu_domain
@@ -731,7 +731,7 @@ void iommufd_device_detach(struct iommufd_device *idev)
iommufd_hw_pagetable_put(idev->ictx, hwpt);
refcount_dec(&idev->obj.users);
}
-EXPORT_SYMBOL_NS_GPL(iommufd_device_detach, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_device_detach, "IOMMUFD");
/*
* On success, it will refcount_inc() at a valid new_ioas and refcount_dec() at
@@ -853,7 +853,7 @@ iommufd_access_create(struct iommufd_ctx *ictx,
mutex_init(&access->ioas_lock);
return access;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_access_create, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_access_create, "IOMMUFD");
/**
* iommufd_access_destroy - Destroy an iommufd_access
@@ -865,7 +865,7 @@ void iommufd_access_destroy(struct iommufd_access *access)
{
iommufd_object_destroy_user(access->ictx, &access->obj);
}
-EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_access_destroy, "IOMMUFD");
void iommufd_access_detach(struct iommufd_access *access)
{
@@ -877,7 +877,7 @@ void iommufd_access_detach(struct iommufd_access *access)
WARN_ON(iommufd_access_change_ioas(access, NULL));
mutex_unlock(&access->ioas_lock);
}
-EXPORT_SYMBOL_NS_GPL(iommufd_access_detach, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_access_detach, "IOMMUFD");
int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id)
{
@@ -893,7 +893,7 @@ int iommufd_access_attach(struct iommufd_access *access, u32 ioas_id)
mutex_unlock(&access->ioas_lock);
return rc;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_access_attach, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_access_attach, "IOMMUFD");
int iommufd_access_replace(struct iommufd_access *access, u32 ioas_id)
{
@@ -908,7 +908,7 @@ int iommufd_access_replace(struct iommufd_access *access, u32 ioas_id)
mutex_unlock(&access->ioas_lock);
return rc;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_access_replace, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_access_replace, "IOMMUFD");
/**
* iommufd_access_notify_unmap - Notify users of an iopt to stop using it
@@ -991,7 +991,7 @@ void iommufd_access_unpin_pages(struct iommufd_access *access,
up_read(&iopt->iova_rwsem);
mutex_unlock(&access->ioas_lock);
}
-EXPORT_SYMBOL_NS_GPL(iommufd_access_unpin_pages, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_access_unpin_pages, "IOMMUFD");
static bool iopt_area_contig_is_aligned(struct iopt_area_contig_iter *iter)
{
@@ -1106,7 +1106,7 @@ err_remove:
mutex_unlock(&access->ioas_lock);
return rc;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_access_pin_pages, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_access_pin_pages, "IOMMUFD");
/**
* iommufd_access_rw - Read or write data under the iova
@@ -1170,7 +1170,7 @@ err_out:
mutex_unlock(&access->ioas_lock);
return rc;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_access_rw, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_access_rw, "IOMMUFD");
int iommufd_get_hw_info(struct iommufd_ucmd *ucmd)
{
diff --git a/drivers/iommu/iommufd/driver.c b/drivers/iommu/iommufd/driver.c
index 7b67fdf44134..2d98b04ff1cb 100644
--- a/drivers/iommu/iommufd/driver.c
+++ b/drivers/iommu/iommufd/driver.c
@@ -34,7 +34,7 @@ out_free:
kfree(obj);
return ERR_PTR(rc);
}
-EXPORT_SYMBOL_NS_GPL(_iommufd_object_alloc, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(_iommufd_object_alloc, "IOMMUFD");
/* Caller should xa_lock(&viommu->vdevs) to protect the return value */
struct device *iommufd_viommu_find_dev(struct iommufd_viommu *viommu,
@@ -47,7 +47,7 @@ struct device *iommufd_viommu_find_dev(struct iommufd_viommu *viommu,
vdev = xa_load(&viommu->vdevs, vdev_id);
return vdev ? vdev->dev : NULL;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_viommu_find_dev, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_viommu_find_dev, "IOMMUFD");
MODULE_DESCRIPTION("iommufd code shared with builtin modules");
MODULE_LICENSE("GPL");
diff --git a/drivers/iommu/iommufd/fault.c b/drivers/iommu/iommufd/fault.c
index 053b0e30f55a..1fe804e28a86 100644
--- a/drivers/iommu/iommufd/fault.c
+++ b/drivers/iommu/iommufd/fault.c
@@ -420,8 +420,6 @@ out_put_fdno:
put_unused_fd(fdno);
out_fput:
fput(filep);
- refcount_dec(&fault->obj.users);
- iommufd_ctx_put(fault->ictx);
out_abort:
iommufd_object_abort_and_destroy(ucmd->ictx, &fault->obj);
diff --git a/drivers/iommu/iommufd/iova_bitmap.c b/drivers/iommu/iommufd/iova_bitmap.c
index d90b9e253412..ab665cf38ef4 100644
--- a/drivers/iommu/iommufd/iova_bitmap.c
+++ b/drivers/iommu/iommufd/iova_bitmap.c
@@ -272,7 +272,7 @@ err:
iova_bitmap_free(bitmap);
return ERR_PTR(rc);
}
-EXPORT_SYMBOL_NS_GPL(iova_bitmap_alloc, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iova_bitmap_alloc, "IOMMUFD");
/**
* iova_bitmap_free() - Frees an IOVA bitmap object
@@ -294,7 +294,7 @@ void iova_bitmap_free(struct iova_bitmap *bitmap)
kfree(bitmap);
}
-EXPORT_SYMBOL_NS_GPL(iova_bitmap_free, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iova_bitmap_free, "IOMMUFD");
/*
* Returns the remaining bitmap indexes from mapped_total_index to process for
@@ -387,7 +387,7 @@ int iova_bitmap_for_each(struct iova_bitmap *bitmap, void *opaque,
{
return fn(bitmap, bitmap->iova, bitmap->length, opaque);
}
-EXPORT_SYMBOL_NS_GPL(iova_bitmap_for_each, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iova_bitmap_for_each, "IOMMUFD");
/**
* iova_bitmap_set() - Records an IOVA range in bitmap
@@ -445,4 +445,4 @@ update_indexes:
cur_bit += nbits;
} while (cur_bit <= last_bit);
}
-EXPORT_SYMBOL_NS_GPL(iova_bitmap_set, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iova_bitmap_set, "IOMMUFD");
diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c
index 0a96cc8f27da..97c5e3567d33 100644
--- a/drivers/iommu/iommufd/main.c
+++ b/drivers/iommu/iommufd/main.c
@@ -427,7 +427,7 @@ void iommufd_ctx_get(struct iommufd_ctx *ictx)
{
get_file(ictx->file);
}
-EXPORT_SYMBOL_NS_GPL(iommufd_ctx_get, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_ctx_get, "IOMMUFD");
/**
* iommufd_ctx_from_file - Acquires a reference to the iommufd context
@@ -447,7 +447,7 @@ struct iommufd_ctx *iommufd_ctx_from_file(struct file *file)
iommufd_ctx_get(ictx);
return ictx;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_ctx_from_file, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_ctx_from_file, "IOMMUFD");
/**
* iommufd_ctx_from_fd - Acquires a reference to the iommufd context
@@ -471,7 +471,7 @@ struct iommufd_ctx *iommufd_ctx_from_fd(int fd)
/* fget is the same as iommufd_ctx_get() */
return file->private_data;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_ctx_from_fd, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_ctx_from_fd, "IOMMUFD");
/**
* iommufd_ctx_put - Put back a reference
@@ -481,7 +481,7 @@ void iommufd_ctx_put(struct iommufd_ctx *ictx)
{
fput(ictx->file);
}
-EXPORT_SYMBOL_NS_GPL(iommufd_ctx_put, IOMMUFD);
+EXPORT_SYMBOL_NS_GPL(iommufd_ctx_put, "IOMMUFD");
static const struct iommufd_object_ops iommufd_object_ops[] = {
[IOMMUFD_OBJ_ACCESS] = {
@@ -575,7 +575,7 @@ module_exit(iommufd_exit);
MODULE_ALIAS_MISCDEV(VFIO_MINOR);
MODULE_ALIAS("devname:vfio/vfio");
#endif
-MODULE_IMPORT_NS(IOMMUFD_INTERNAL);
-MODULE_IMPORT_NS(IOMMUFD);
+MODULE_IMPORT_NS("IOMMUFD_INTERNAL");
+MODULE_IMPORT_NS("IOMMUFD");
MODULE_DESCRIPTION("I/O Address Space Management for passthrough devices");
MODULE_LICENSE("GPL");
diff --git a/drivers/iommu/iommufd/vfio_compat.c b/drivers/iommu/iommufd/vfio_compat.c
index 514aacd64009..a258ee2f4579 100644
--- a/drivers/iommu/iommufd/vfio_compat.c
+++ b/drivers/iommu/iommufd/vfio_compat.c
@@ -44,7 +44,7 @@ int iommufd_vfio_compat_ioas_get_id(struct iommufd_ctx *ictx, u32 *out_ioas_id)
iommufd_put_object(ictx, &ioas->obj);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_vfio_compat_ioas_get_id, IOMMUFD_VFIO);
+EXPORT_SYMBOL_NS_GPL(iommufd_vfio_compat_ioas_get_id, "IOMMUFD_VFIO");
/**
* iommufd_vfio_compat_set_no_iommu - Called when a no-iommu device is attached
@@ -66,7 +66,7 @@ int iommufd_vfio_compat_set_no_iommu(struct iommufd_ctx *ictx)
xa_unlock(&ictx->objects);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_vfio_compat_set_no_iommu, IOMMUFD_VFIO);
+EXPORT_SYMBOL_NS_GPL(iommufd_vfio_compat_set_no_iommu, "IOMMUFD_VFIO");
/**
* iommufd_vfio_compat_ioas_create - Ensure the compat IOAS is created
@@ -118,7 +118,7 @@ out_abort:
iommufd_object_abort(ictx, &ioas->obj);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(iommufd_vfio_compat_ioas_create, IOMMUFD_VFIO);
+EXPORT_SYMBOL_NS_GPL(iommufd_vfio_compat_ioas_create, "IOMMUFD_VFIO");
int iommufd_vfio_ioas(struct iommufd_ucmd *ucmd)
{
diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index ff55b8c30712..074daf1aac4e 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -1159,6 +1159,6 @@ static struct platform_driver ipmmu_driver = {
.pm = pm_sleep_ptr(&ipmmu_pm),
},
.probe = ipmmu_probe,
- .remove_new = ipmmu_remove,
+ .remove = ipmmu_remove,
};
builtin_platform_driver(ipmmu_driver);
diff --git a/drivers/iommu/msm_iommu.c b/drivers/iommu/msm_iommu.c
index 989e0869d805..ce40f0a419ea 100644
--- a/drivers/iommu/msm_iommu.c
+++ b/drivers/iommu/msm_iommu.c
@@ -838,6 +838,6 @@ static struct platform_driver msm_iommu_driver = {
.of_match_table = msm_iommu_dt_match,
},
.probe = msm_iommu_probe,
- .remove_new = msm_iommu_remove,
+ .remove = msm_iommu_remove,
};
builtin_platform_driver(msm_iommu_driver);
diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index c45313c43b9e..ab60901f8f92 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -1794,7 +1794,7 @@ MODULE_DEVICE_TABLE(of, mtk_iommu_of_ids);
static struct platform_driver mtk_iommu_driver = {
.probe = mtk_iommu_probe,
- .remove_new = mtk_iommu_remove,
+ .remove = mtk_iommu_remove,
.driver = {
.name = "mtk-iommu",
.of_match_table = mtk_iommu_of_ids,
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index ee4e55b6b190..b6de1ca00cef 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -745,7 +745,7 @@ static const struct dev_pm_ops mtk_iommu_v1_pm_ops = {
static struct platform_driver mtk_iommu_v1_driver = {
.probe = mtk_iommu_v1_probe,
- .remove_new = mtk_iommu_v1_remove,
+ .remove = mtk_iommu_v1_remove,
.driver = {
.name = "mtk-iommu-v1",
.of_match_table = mtk_iommu_v1_of_ids,
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index 3f72aef8bd5b..3c62337f43c6 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1285,7 +1285,7 @@ static const struct of_device_id omap_iommu_of_match[] = {
static struct platform_driver omap_iommu_driver = {
.probe = omap_iommu_probe,
- .remove_new = omap_iommu_remove,
+ .remove = omap_iommu_remove,
.driver = {
.name = "omap-iommu",
.pm = &omap_iommu_pm_ops,
diff --git a/drivers/iommu/riscv/iommu-platform.c b/drivers/iommu/riscv/iommu-platform.c
index da336863f152..382ba2841849 100644
--- a/drivers/iommu/riscv/iommu-platform.c
+++ b/drivers/iommu/riscv/iommu-platform.c
@@ -81,7 +81,7 @@ static const struct of_device_id riscv_iommu_of_match[] = {
static struct platform_driver riscv_iommu_platform_driver = {
.probe = riscv_iommu_platform_probe,
- .remove_new = riscv_iommu_platform_remove,
+ .remove = riscv_iommu_platform_remove,
.driver = {
.name = "riscv,iommu",
.of_match_table = riscv_iommu_of_match,
diff --git a/drivers/iommu/sprd-iommu.c b/drivers/iommu/sprd-iommu.c
index a2f4ffe6d949..941d1f361c8c 100644
--- a/drivers/iommu/sprd-iommu.c
+++ b/drivers/iommu/sprd-iommu.c
@@ -531,7 +531,7 @@ static struct platform_driver sprd_iommu_driver = {
.suppress_bind_attrs = true,
},
.probe = sprd_iommu_probe,
- .remove_new = sprd_iommu_remove,
+ .remove = sprd_iommu_remove,
};
module_platform_driver(sprd_iommu_driver);
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 55d7122121e2..9bee02db1643 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -415,7 +415,7 @@ config PARTITION_PERCPU
config STM32MP_EXTI
tristate "STM32MP extended interrupts and event controller"
depends on (ARCH_STM32 && !ARM_SINGLE_ARMV7M) || COMPILE_TEST
- default y
+ default ARCH_STM32 && !ARM_SINGLE_ARMV7M
select IRQ_DOMAIN_HIERARCHY
select GENERIC_IRQ_CHIP
help
diff --git a/drivers/irqchip/irq-bcm2836.c b/drivers/irqchip/irq-bcm2836.c
index e5f1059b989f..e366257684b5 100644
--- a/drivers/irqchip/irq-bcm2836.c
+++ b/drivers/irqchip/irq-bcm2836.c
@@ -58,6 +58,7 @@ static struct irq_chip bcm2836_arm_irqchip_timer = {
.name = "bcm2836-timer",
.irq_mask = bcm2836_arm_irqchip_mask_timer_irq,
.irq_unmask = bcm2836_arm_irqchip_unmask_timer_irq,
+ .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
};
static void bcm2836_arm_irqchip_mask_pmu_irq(struct irq_data *d)
@@ -74,6 +75,7 @@ static struct irq_chip bcm2836_arm_irqchip_pmu = {
.name = "bcm2836-pmu",
.irq_mask = bcm2836_arm_irqchip_mask_pmu_irq,
.irq_unmask = bcm2836_arm_irqchip_unmask_pmu_irq,
+ .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
};
static void bcm2836_arm_irqchip_mask_gpu_irq(struct irq_data *d)
@@ -88,6 +90,7 @@ static struct irq_chip bcm2836_arm_irqchip_gpu = {
.name = "bcm2836-gpu",
.irq_mask = bcm2836_arm_irqchip_mask_gpu_irq,
.irq_unmask = bcm2836_arm_irqchip_unmask_gpu_irq,
+ .flags = IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
};
static void bcm2836_arm_irqchip_dummy_op(struct irq_data *d)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 16acce0f102d..92244cfa0464 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -47,6 +47,7 @@
#define ITS_FLAGS_WORKAROUND_CAVIUM_22375 (1ULL << 1)
#define ITS_FLAGS_WORKAROUND_CAVIUM_23144 (1ULL << 2)
#define ITS_FLAGS_FORCE_NON_SHAREABLE (1ULL << 3)
+#define ITS_FLAGS_WORKAROUND_HISILICON_162100801 (1ULL << 4)
#define RD_LOCAL_LPI_ENABLED BIT(0)
#define RD_LOCAL_PENDTABLE_PREALLOCATED BIT(1)
@@ -64,6 +65,7 @@ static u32 lpi_id_bits;
#define LPI_PENDBASE_SZ ALIGN(BIT(LPI_NRBITS) / 8, SZ_64K)
static u8 __ro_after_init lpi_prop_prio;
+static struct its_node *find_4_1_its(void);
/*
* Collection structure - just an ID, and a redistributor address to
@@ -3883,6 +3885,20 @@ static void its_vpe_db_proxy_move(struct its_vpe *vpe, int from, int to)
raw_spin_unlock_irqrestore(&vpe_proxy.lock, flags);
}
+static void its_vpe_4_1_invall_locked(int cpu, struct its_vpe *vpe)
+{
+ void __iomem *rdbase;
+ u64 val;
+
+ val = GICR_INVALLR_V;
+ val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);
+
+ guard(raw_spinlock)(&gic_data_rdist_cpu(cpu)->rd_lock);
+ rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
+ gic_write_lpir(val, rdbase + GICR_INVALLR);
+ wait_for_syncr(rdbase);
+}
+
static int its_vpe_set_affinity(struct irq_data *d,
const struct cpumask *mask_val,
bool force)
@@ -3890,6 +3906,7 @@ static int its_vpe_set_affinity(struct irq_data *d,
struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
unsigned int from, cpu = nr_cpu_ids;
struct cpumask *table_mask;
+ struct its_node *its;
unsigned long flags;
/*
@@ -3952,6 +3969,11 @@ static int its_vpe_set_affinity(struct irq_data *d,
vpe->col_idx = cpu;
its_send_vmovp(vpe);
+
+ its = find_4_1_its();
+ if (its && its->flags & ITS_FLAGS_WORKAROUND_HISILICON_162100801)
+ its_vpe_4_1_invall_locked(cpu, vpe);
+
its_vpe_db_proxy_move(vpe, from, cpu);
out:
@@ -4259,22 +4281,12 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
static void its_vpe_4_1_invall(struct its_vpe *vpe)
{
- void __iomem *rdbase;
unsigned long flags;
- u64 val;
int cpu;
- val = GICR_INVALLR_V;
- val |= FIELD_PREP(GICR_INVALLR_VPEID, vpe->vpe_id);
-
/* Target the redistributor this vPE is currently known on */
cpu = vpe_to_cpuid_lock(vpe, &flags);
- raw_spin_lock(&gic_data_rdist_cpu(cpu)->rd_lock);
- rdbase = per_cpu_ptr(gic_rdists->rdist, cpu)->rd_base;
- gic_write_lpir(val, rdbase + GICR_INVALLR);
-
- wait_for_syncr(rdbase);
- raw_spin_unlock(&gic_data_rdist_cpu(cpu)->rd_lock);
+ its_vpe_4_1_invall_locked(cpu, vpe);
vpe_to_cpuid_unlock(vpe, flags);
}
@@ -4867,6 +4879,14 @@ static bool its_set_non_coherent(void *data)
return true;
}
+static bool __maybe_unused its_enable_quirk_hip09_162100801(void *data)
+{
+ struct its_node *its = data;
+
+ its->flags |= ITS_FLAGS_WORKAROUND_HISILICON_162100801;
+ return true;
+}
+
static const struct gic_quirk its_quirks[] = {
#ifdef CONFIG_CAVIUM_ERRATUM_22375
{
@@ -4913,6 +4933,14 @@ static const struct gic_quirk its_quirks[] = {
.init = its_enable_quirk_hip07_161600802,
},
#endif
+#ifdef CONFIG_HISILICON_ERRATUM_162100801
+ {
+ .desc = "ITS: Hip09 erratum 162100801",
+ .iidr = 0x00051736,
+ .mask = 0xffffffff,
+ .init = its_enable_quirk_hip09_162100801,
+ },
+#endif
#ifdef CONFIG_ROCKCHIP_ERRATUM_3588001
{
.desc = "ITS: Rockchip erratum RK3588001",
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 8b6159f4cdaf..79d8cc80693c 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -161,7 +161,22 @@ static bool cpus_have_group0 __ro_after_init;
static void __init gic_prio_init(void)
{
- cpus_have_security_disabled = gic_dist_security_disabled();
+ bool ds;
+
+ ds = gic_dist_security_disabled();
+ if (!ds) {
+ u32 val;
+
+ val = readl_relaxed(gic_data.dist_base + GICD_CTLR);
+ val |= GICD_CTLR_DS;
+ writel_relaxed(val, gic_data.dist_base + GICD_CTLR);
+
+ ds = gic_dist_security_disabled();
+ if (ds)
+ pr_warn("Broken GIC integration, security disabled");
+ }
+
+ cpus_have_security_disabled = ds;
cpus_have_group0 = gic_has_group0();
/*
@@ -817,7 +832,7 @@ static void gic_deactivate_unhandled(u32 irqnr)
* register state is not stale, as these may have been indirectly written
* *after* exception entry.
*
- * (2) Deactivate the interrupt when EOI mode 1 is in use.
+ * (2) Execute an interrupt priority drop when EOI mode 1 is in use.
*/
static inline void gic_complete_ack(u32 irqnr)
{
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 3be7bd8cd8cd..6503573557fd 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -64,7 +64,7 @@ static void gic_check_cpu_features(void)
union gic_base {
void __iomem *common_base;
- void __percpu * __iomem *percpu_base;
+ void __iomem * __percpu *percpu_base;
};
struct gic_chip_data {
@@ -400,7 +400,7 @@ static void gic_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gic_chip_data *gic = irq_data_get_irq_chip_data(d);
if (gic->domain->pm_dev)
- seq_printf(p, gic->domain->pm_dev->of_node->name);
+ seq_puts(p, gic->domain->pm_dev->of_node->name);
else
seq_printf(p, "GIC-%d", (int)(gic - &gic_data[0]));
}
diff --git a/drivers/irqchip/irq-imgpdc.c b/drivers/irqchip/irq-imgpdc.c
index b42ed68acfa6..85f80bac0961 100644
--- a/drivers/irqchip/irq-imgpdc.c
+++ b/drivers/irqchip/irq-imgpdc.c
@@ -479,7 +479,7 @@ static struct platform_driver pdc_intc_driver = {
.of_match_table = pdc_intc_match,
},
.probe = pdc_intc_probe,
- .remove_new = pdc_intc_remove,
+ .remove = pdc_intc_remove,
};
static int __init pdc_intc_init(void)
diff --git a/drivers/irqchip/irq-imx-intmux.c b/drivers/irqchip/irq-imx-intmux.c
index 511adfaeec82..787543d07565 100644
--- a/drivers/irqchip/irq-imx-intmux.c
+++ b/drivers/irqchip/irq-imx-intmux.c
@@ -361,6 +361,6 @@ static struct platform_driver imx_intmux_driver = {
.pm = &imx_intmux_pm_ops,
},
.probe = imx_intmux_probe,
- .remove_new = imx_intmux_remove,
+ .remove = imx_intmux_remove,
};
builtin_platform_driver(imx_intmux_driver);
diff --git a/drivers/irqchip/irq-imx-irqsteer.c b/drivers/irqchip/irq-imx-irqsteer.c
index 75a0e980ff35..b0e9788c0045 100644
--- a/drivers/irqchip/irq-imx-irqsteer.c
+++ b/drivers/irqchip/irq-imx-irqsteer.c
@@ -328,6 +328,6 @@ static struct platform_driver imx_irqsteer_driver = {
.pm = &imx_irqsteer_pm_ops,
},
.probe = imx_irqsteer_probe,
- .remove_new = imx_irqsteer_remove,
+ .remove = imx_irqsteer_remove,
};
builtin_platform_driver(imx_irqsteer_driver);
diff --git a/drivers/irqchip/irq-keystone.c b/drivers/irqchip/irq-keystone.c
index 30f1979fa124..808c781e2548 100644
--- a/drivers/irqchip/irq-keystone.c
+++ b/drivers/irqchip/irq-keystone.c
@@ -211,7 +211,7 @@ MODULE_DEVICE_TABLE(of, keystone_irq_dt_ids);
static struct platform_driver keystone_irq_device_driver = {
.probe = keystone_irq_probe,
- .remove_new = keystone_irq_remove,
+ .remove = keystone_irq_remove,
.driver = {
.name = "keystone_irq",
.of_match_table = of_match_ptr(keystone_irq_dt_ids),
diff --git a/drivers/irqchip/irq-ls-scfg-msi.c b/drivers/irqchip/irq-ls-scfg-msi.c
index 1aef5c4d27c6..c0e1aafe468c 100644
--- a/drivers/irqchip/irq-ls-scfg-msi.c
+++ b/drivers/irqchip/irq-ls-scfg-msi.c
@@ -418,7 +418,7 @@ static struct platform_driver ls_scfg_msi_driver = {
.of_match_table = ls_scfg_msi_id,
},
.probe = ls_scfg_msi_probe,
- .remove_new = ls_scfg_msi_remove,
+ .remove = ls_scfg_msi_remove,
};
module_platform_driver(ls_scfg_msi_driver);
diff --git a/drivers/irqchip/irq-madera.c b/drivers/irqchip/irq-madera.c
index acceb6e7fa95..b32982c11515 100644
--- a/drivers/irqchip/irq-madera.c
+++ b/drivers/irqchip/irq-madera.c
@@ -236,7 +236,7 @@ static void madera_irq_remove(struct platform_device *pdev)
static struct platform_driver madera_irq_driver = {
.probe = madera_irq_probe,
- .remove_new = madera_irq_remove,
+ .remove = madera_irq_remove,
.driver = {
.name = "madera-irq",
.pm = &madera_irq_pm_ops,
diff --git a/drivers/irqchip/irq-mvebu-pic.c b/drivers/irqchip/irq-mvebu-pic.c
index 08b0cc862adf..3888b7585981 100644
--- a/drivers/irqchip/irq-mvebu-pic.c
+++ b/drivers/irqchip/irq-mvebu-pic.c
@@ -71,7 +71,7 @@ static void mvebu_pic_print_chip(struct irq_data *d, struct seq_file *p)
{
struct mvebu_pic *pic = irq_data_get_irq_chip_data(d);
- seq_printf(p, dev_name(&pic->pdev->dev));
+ seq_puts(p, dev_name(&pic->pdev->dev));
}
static const struct irq_chip mvebu_pic_chip = {
@@ -183,7 +183,7 @@ MODULE_DEVICE_TABLE(of, mvebu_pic_of_match);
static struct platform_driver mvebu_pic_driver = {
.probe = mvebu_pic_probe,
- .remove_new = mvebu_pic_remove,
+ .remove = mvebu_pic_remove,
.driver = {
.name = "mvebu-pic",
.of_match_table = mvebu_pic_of_match,
diff --git a/drivers/irqchip/irq-mvebu-sei.c b/drivers/irqchip/irq-mvebu-sei.c
index f8c70f2d100a..065166ab5dbc 100644
--- a/drivers/irqchip/irq-mvebu-sei.c
+++ b/drivers/irqchip/irq-mvebu-sei.c
@@ -192,7 +192,6 @@ static void mvebu_sei_domain_free(struct irq_domain *domain, unsigned int virq,
}
static const struct irq_domain_ops mvebu_sei_domain_ops = {
- .select = msi_lib_irq_domain_select,
.alloc = mvebu_sei_domain_alloc,
.free = mvebu_sei_domain_free,
};
@@ -306,6 +305,7 @@ static void mvebu_sei_cp_domain_free(struct irq_domain *domain,
}
static const struct irq_domain_ops mvebu_sei_cp_domain_ops = {
+ .select = msi_lib_irq_domain_select,
.alloc = mvebu_sei_cp_domain_alloc,
.free = mvebu_sei_cp_domain_free,
};
diff --git a/drivers/irqchip/irq-pruss-intc.c b/drivers/irqchip/irq-pruss-intc.c
index 060eb000e9d3..bee01980b463 100644
--- a/drivers/irqchip/irq-pruss-intc.c
+++ b/drivers/irqchip/irq-pruss-intc.c
@@ -648,7 +648,7 @@ static struct platform_driver pruss_intc_driver = {
.suppress_bind_attrs = true,
},
.probe = pruss_intc_probe,
- .remove_new = pruss_intc_remove,
+ .remove = pruss_intc_remove,
};
module_platform_driver(pruss_intc_driver);
diff --git a/drivers/irqchip/irq-renesas-intc-irqpin.c b/drivers/irqchip/irq-renesas-intc-irqpin.c
index 9ad37237ba95..954419f2460d 100644
--- a/drivers/irqchip/irq-renesas-intc-irqpin.c
+++ b/drivers/irqchip/irq-renesas-intc-irqpin.c
@@ -584,7 +584,7 @@ static SIMPLE_DEV_PM_OPS(intc_irqpin_pm_ops, intc_irqpin_suspend, NULL);
static struct platform_driver intc_irqpin_device_driver = {
.probe = intc_irqpin_probe,
- .remove_new = intc_irqpin_remove,
+ .remove = intc_irqpin_remove,
.driver = {
.name = "renesas_intc_irqpin",
.of_match_table = intc_irqpin_dt_ids,
diff --git a/drivers/irqchip/irq-renesas-irqc.c b/drivers/irqchip/irq-renesas-irqc.c
index 76026e0b8e20..cbce8ffc7de4 100644
--- a/drivers/irqchip/irq-renesas-irqc.c
+++ b/drivers/irqchip/irq-renesas-irqc.c
@@ -247,7 +247,7 @@ MODULE_DEVICE_TABLE(of, irqc_dt_ids);
static struct platform_driver irqc_device_driver = {
.probe = irqc_probe,
- .remove_new = irqc_remove,
+ .remove = irqc_remove,
.driver = {
.name = "renesas_irqc",
.of_match_table = irqc_dt_ids,
diff --git a/drivers/irqchip/irq-renesas-rza1.c b/drivers/irqchip/irq-renesas-rza1.c
index f05afe82db4d..d4e6a68889ec 100644
--- a/drivers/irqchip/irq-renesas-rza1.c
+++ b/drivers/irqchip/irq-renesas-rza1.c
@@ -259,7 +259,7 @@ MODULE_DEVICE_TABLE(of, rza1_irqc_dt_ids);
static struct platform_driver rza1_irqc_device_driver = {
.probe = rza1_irqc_probe,
- .remove_new = rza1_irqc_remove,
+ .remove = rza1_irqc_remove,
.driver = {
.name = "renesas_rza1_irqc",
.of_match_table = rza1_irqc_dt_ids,
diff --git a/drivers/irqchip/irq-ts4800.c b/drivers/irqchip/irq-ts4800.c
index b5dddb3c1568..cc219f28d317 100644
--- a/drivers/irqchip/irq-ts4800.c
+++ b/drivers/irqchip/irq-ts4800.c
@@ -154,7 +154,7 @@ MODULE_DEVICE_TABLE(of, ts4800_ic_of_match);
static struct platform_driver ts4800_ic_driver = {
.probe = ts4800_ic_probe,
- .remove_new = ts4800_ic_remove,
+ .remove = ts4800_ic_remove,
.driver = {
.name = "ts4800-irqc",
.of_match_table = ts4800_ic_of_match,
diff --git a/drivers/irqchip/irq-versatile-fpga.c b/drivers/irqchip/irq-versatile-fpga.c
index ca471c6fee99..0abc8934c2ee 100644
--- a/drivers/irqchip/irq-versatile-fpga.c
+++ b/drivers/irqchip/irq-versatile-fpga.c
@@ -69,7 +69,7 @@ static void fpga_irq_print_chip(struct irq_data *d, struct seq_file *p)
{
struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
- seq_printf(p, irq_domain_get_of_node(f->domain)->name);
+ seq_puts(p, irq_domain_get_of_node(f->domain)->name);
}
static const struct irq_chip fpga_chip = {
diff --git a/drivers/isdn/mISDN/core.c b/drivers/isdn/mISDN/core.c
index e34a7a46754e..8ec2d4d4f135 100644
--- a/drivers/isdn/mISDN/core.c
+++ b/drivers/isdn/mISDN/core.c
@@ -294,20 +294,6 @@ get_Bprotocol4mask(u_int m)
return NULL;
}
-struct Bprotocol *
-get_Bprotocol4id(u_int id)
-{
- u_int m;
-
- if (id < ISDN_P_B_START || id > 63) {
- printk(KERN_WARNING "%s id not in range %d\n",
- __func__, id);
- return NULL;
- }
- m = 1 << (id & ISDN_P_B_MASK);
- return get_Bprotocol4mask(m);
-}
-
int
mISDN_register_Bprotocol(struct Bprotocol *bp)
{
diff --git a/drivers/isdn/mISDN/core.h b/drivers/isdn/mISDN/core.h
index 42599f49c189..5617c06de8e4 100644
--- a/drivers/isdn/mISDN/core.h
+++ b/drivers/isdn/mISDN/core.h
@@ -55,7 +55,6 @@ extern void __add_layer2(struct mISDNchannel *, struct mISDNstack *);
extern u_int get_all_Bprotocols(void);
struct Bprotocol *get_Bprotocol4mask(u_int);
-struct Bprotocol *get_Bprotocol4id(u_int);
extern int mISDN_inittimer(u_int *);
extern void mISDN_timer_cleanup(void);
diff --git a/drivers/leds/flash/leds-ktd2692.c b/drivers/leds/flash/leds-ktd2692.c
index 743830a10f99..0f16eefcfe4c 100644
--- a/drivers/leds/flash/leds-ktd2692.c
+++ b/drivers/leds/flash/leds-ktd2692.c
@@ -349,7 +349,7 @@ static struct platform_driver ktd2692_driver = {
module_platform_driver(ktd2692_driver);
-MODULE_IMPORT_NS(EXPRESSWIRE);
+MODULE_IMPORT_NS("EXPRESSWIRE");
MODULE_AUTHOR("Ingi Kim <ingi2.kim@samsung.com>");
MODULE_DESCRIPTION("Kinetic KTD2692 LED driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/leds/leds-expresswire.c b/drivers/leds/leds-expresswire.c
index e4937a8e0f44..bb69be228a6d 100644
--- a/drivers/leds/leds-expresswire.c
+++ b/drivers/leds/leds-expresswire.c
@@ -18,7 +18,7 @@ void expresswire_power_off(struct expresswire_common_props *props)
gpiod_set_value_cansleep(props->ctrl_gpio, 0);
usleep_range(props->timing.poweroff_us, props->timing.poweroff_us * 2);
}
-EXPORT_SYMBOL_NS_GPL(expresswire_power_off, EXPRESSWIRE);
+EXPORT_SYMBOL_NS_GPL(expresswire_power_off, "EXPRESSWIRE");
void expresswire_enable(struct expresswire_common_props *props)
{
@@ -28,14 +28,14 @@ void expresswire_enable(struct expresswire_common_props *props)
udelay(props->timing.detect_us);
gpiod_set_value(props->ctrl_gpio, 1);
}
-EXPORT_SYMBOL_NS_GPL(expresswire_enable, EXPRESSWIRE);
+EXPORT_SYMBOL_NS_GPL(expresswire_enable, "EXPRESSWIRE");
void expresswire_start(struct expresswire_common_props *props)
{
gpiod_set_value(props->ctrl_gpio, 1);
udelay(props->timing.data_start_us);
}
-EXPORT_SYMBOL_NS_GPL(expresswire_start, EXPRESSWIRE);
+EXPORT_SYMBOL_NS_GPL(expresswire_start, "EXPRESSWIRE");
void expresswire_end(struct expresswire_common_props *props)
{
@@ -44,7 +44,7 @@ void expresswire_end(struct expresswire_common_props *props)
gpiod_set_value(props->ctrl_gpio, 1);
udelay(props->timing.end_of_data_high_us);
}
-EXPORT_SYMBOL_NS_GPL(expresswire_end, EXPRESSWIRE);
+EXPORT_SYMBOL_NS_GPL(expresswire_end, "EXPRESSWIRE");
void expresswire_set_bit(struct expresswire_common_props *props, bool bit)
{
@@ -60,7 +60,7 @@ void expresswire_set_bit(struct expresswire_common_props *props, bool bit)
udelay(props->timing.short_bitset_us);
}
}
-EXPORT_SYMBOL_NS_GPL(expresswire_set_bit, EXPRESSWIRE);
+EXPORT_SYMBOL_NS_GPL(expresswire_set_bit, "EXPRESSWIRE");
void expresswire_write_u8(struct expresswire_common_props *props, u8 val)
{
@@ -69,4 +69,4 @@ void expresswire_write_u8(struct expresswire_common_props *props, u8 val)
expresswire_set_bit(props, val & BIT(i));
expresswire_end(props);
}
-EXPORT_SYMBOL_NS_GPL(expresswire_write_u8, EXPRESSWIRE);
+EXPORT_SYMBOL_NS_GPL(expresswire_write_u8, "EXPRESSWIRE");
diff --git a/drivers/macintosh/Kconfig b/drivers/macintosh/Kconfig
index fb38f684444f..d00e713c1092 100644
--- a/drivers/macintosh/Kconfig
+++ b/drivers/macintosh/Kconfig
@@ -120,6 +120,7 @@ config PMAC_MEDIABAY
config PMAC_BACKLIGHT
bool "Backlight control for LCD screens"
depends on PPC_PMAC && ADB_PMU && FB = y && (BROKEN || !PPC64)
+ depends on BACKLIGHT_CLASS_DEVICE=y
select FB_BACKLIGHT
help
Say Y here to enable Macintosh specific extensions of the generic
diff --git a/drivers/macintosh/therm_windtunnel.c b/drivers/macintosh/therm_windtunnel.c
index 2576a53f247e..0b2e08a1bee0 100644
--- a/drivers/macintosh/therm_windtunnel.c
+++ b/drivers/macintosh/therm_windtunnel.c
@@ -499,7 +499,7 @@ static struct platform_driver therm_of_driver = {
.of_match_table = therm_of_match,
},
.probe = therm_of_probe,
- .remove_new = therm_of_remove,
+ .remove = therm_of_remove,
};
struct apple_thermal_info {
diff --git a/drivers/macintosh/windfarm_pm112.c b/drivers/macintosh/windfarm_pm112.c
index 876b4d8cbe37..5bd6d1ccf246 100644
--- a/drivers/macintosh/windfarm_pm112.c
+++ b/drivers/macintosh/windfarm_pm112.c
@@ -669,7 +669,7 @@ static void wf_pm112_remove(struct platform_device *dev)
static struct platform_driver wf_pm112_driver = {
.probe = wf_pm112_probe,
- .remove_new = wf_pm112_remove,
+ .remove = wf_pm112_remove,
.driver = {
.name = "windfarm",
},
diff --git a/drivers/macintosh/windfarm_pm121.c b/drivers/macintosh/windfarm_pm121.c
index cd45fbc4fe1c..660180c843a3 100644
--- a/drivers/macintosh/windfarm_pm121.c
+++ b/drivers/macintosh/windfarm_pm121.c
@@ -999,7 +999,7 @@ static void pm121_remove(struct platform_device *ddev)
static struct platform_driver pm121_driver = {
.probe = pm121_probe,
- .remove_new = pm121_remove,
+ .remove = pm121_remove,
.driver = {
.name = "windfarm",
.bus = &platform_bus_type,
diff --git a/drivers/macintosh/windfarm_pm72.c b/drivers/macintosh/windfarm_pm72.c
index 14fa1e9ac3e0..10aa14074c39 100644
--- a/drivers/macintosh/windfarm_pm72.c
+++ b/drivers/macintosh/windfarm_pm72.c
@@ -782,7 +782,7 @@ static void wf_pm72_remove(struct platform_device *dev)
static struct platform_driver wf_pm72_driver = {
.probe = wf_pm72_probe,
- .remove_new = wf_pm72_remove,
+ .remove = wf_pm72_remove,
.driver = {
.name = "windfarm",
},
diff --git a/drivers/macintosh/windfarm_pm81.c b/drivers/macintosh/windfarm_pm81.c
index 404d2454e33d..ada97377e19e 100644
--- a/drivers/macintosh/windfarm_pm81.c
+++ b/drivers/macintosh/windfarm_pm81.c
@@ -765,7 +765,7 @@ static void wf_smu_remove(struct platform_device *ddev)
static struct platform_driver wf_smu_driver = {
.probe = wf_smu_probe,
- .remove_new = wf_smu_remove,
+ .remove = wf_smu_remove,
.driver = {
.name = "windfarm",
},
diff --git a/drivers/macintosh/windfarm_pm91.c b/drivers/macintosh/windfarm_pm91.c
index fba02a375435..108d7938e714 100644
--- a/drivers/macintosh/windfarm_pm91.c
+++ b/drivers/macintosh/windfarm_pm91.c
@@ -695,7 +695,7 @@ static void wf_smu_remove(struct platform_device *ddev)
static struct platform_driver wf_smu_driver = {
.probe = wf_smu_probe,
- .remove_new = wf_smu_remove,
+ .remove = wf_smu_remove,
.driver = {
.name = "windfarm",
},
diff --git a/drivers/macintosh/windfarm_rm31.c b/drivers/macintosh/windfarm_rm31.c
index dc8f2c7ef103..44d86a410238 100644
--- a/drivers/macintosh/windfarm_rm31.c
+++ b/drivers/macintosh/windfarm_rm31.c
@@ -675,7 +675,7 @@ static void wf_rm31_remove(struct platform_device *dev)
static struct platform_driver wf_rm31_driver = {
.probe = wf_rm31_probe,
- .remove_new = wf_rm31_remove,
+ .remove = wf_rm31_remove,
.driver = {
.name = "windfarm",
},
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index 6797770474a5..680243751d62 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -15,6 +15,7 @@
#include <linux/slab.h>
#include <linux/kfifo.h>
#include <linux/err.h>
+#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
diff --git a/drivers/mcb/mcb-core.c b/drivers/mcb/mcb-core.c
index 91bbd948ee93..9b8c40a6459a 100644
--- a/drivers/mcb/mcb-core.c
+++ b/drivers/mcb/mcb-core.c
@@ -191,7 +191,7 @@ int __mcb_register_driver(struct mcb_driver *drv, struct module *owner,
return driver_register(&drv->driver);
}
-EXPORT_SYMBOL_NS_GPL(__mcb_register_driver, MCB);
+EXPORT_SYMBOL_NS_GPL(__mcb_register_driver, "MCB");
/**
* mcb_unregister_driver() - Unregister a @mcb_driver from the system
@@ -203,7 +203,7 @@ void mcb_unregister_driver(struct mcb_driver *drv)
{
driver_unregister(&drv->driver);
}
-EXPORT_SYMBOL_NS_GPL(mcb_unregister_driver, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_unregister_driver, "MCB");
static void mcb_release_dev(struct device *dev)
{
@@ -250,7 +250,7 @@ out:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(mcb_device_register, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_device_register, "MCB");
static void mcb_free_bus(struct device *dev)
{
@@ -303,7 +303,7 @@ err_put:
put_device(&bus->dev);
return ERR_PTR(rc);
}
-EXPORT_SYMBOL_NS_GPL(mcb_alloc_bus, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_alloc_bus, "MCB");
static int __mcb_devices_unregister(struct device *dev, void *data)
{
@@ -325,7 +325,7 @@ void mcb_release_bus(struct mcb_bus *bus)
{
mcb_devices_unregister(bus);
}
-EXPORT_SYMBOL_NS_GPL(mcb_release_bus, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_release_bus, "MCB");
/**
* mcb_bus_get() - Increment refcnt
@@ -340,7 +340,7 @@ struct mcb_bus *mcb_bus_get(struct mcb_bus *bus)
return bus;
}
-EXPORT_SYMBOL_NS_GPL(mcb_bus_get, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_bus_get, "MCB");
/**
* mcb_bus_put() - Decrement refcnt
@@ -353,7 +353,7 @@ void mcb_bus_put(struct mcb_bus *bus)
if (bus)
put_device(&bus->dev);
}
-EXPORT_SYMBOL_NS_GPL(mcb_bus_put, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_bus_put, "MCB");
/**
* mcb_alloc_dev() - Allocate a device
@@ -373,7 +373,7 @@ struct mcb_device *mcb_alloc_dev(struct mcb_bus *bus)
return dev;
}
-EXPORT_SYMBOL_NS_GPL(mcb_alloc_dev, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_alloc_dev, "MCB");
/**
* mcb_free_dev() - Free @mcb_device
@@ -385,7 +385,7 @@ void mcb_free_dev(struct mcb_device *dev)
{
kfree(dev);
}
-EXPORT_SYMBOL_NS_GPL(mcb_free_dev, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_free_dev, "MCB");
static int __mcb_bus_add_devices(struct device *dev, void *data)
{
@@ -410,7 +410,7 @@ void mcb_bus_add_devices(const struct mcb_bus *bus)
{
bus_for_each_dev(bus->dev.bus, NULL, NULL, __mcb_bus_add_devices);
}
-EXPORT_SYMBOL_NS_GPL(mcb_bus_add_devices, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_bus_add_devices, "MCB");
/**
* mcb_get_resource() - get a resource for a mcb device
@@ -426,7 +426,7 @@ struct resource *mcb_get_resource(struct mcb_device *dev, unsigned int type)
else
return NULL;
}
-EXPORT_SYMBOL_NS_GPL(mcb_get_resource, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_get_resource, "MCB");
/**
* mcb_request_mem() - Request memory
@@ -452,7 +452,7 @@ struct resource *mcb_request_mem(struct mcb_device *dev, const char *name)
return mem;
}
-EXPORT_SYMBOL_NS_GPL(mcb_request_mem, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_request_mem, "MCB");
/**
* mcb_release_mem() - Release memory requested by device
@@ -467,7 +467,7 @@ void mcb_release_mem(struct resource *mem)
size = resource_size(mem);
release_mem_region(mem->start, size);
}
-EXPORT_SYMBOL_NS_GPL(mcb_release_mem, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_release_mem, "MCB");
static int __mcb_get_irq(struct mcb_device *dev)
{
@@ -493,7 +493,7 @@ int mcb_get_irq(struct mcb_device *dev)
return __mcb_get_irq(dev);
}
-EXPORT_SYMBOL_NS_GPL(mcb_get_irq, MCB);
+EXPORT_SYMBOL_NS_GPL(mcb_get_irq, "MCB");
static int mcb_init(void)
{
diff --git a/drivers/mcb/mcb-lpc.c b/drivers/mcb/mcb-lpc.c
index 2bec2086ee17..070aa787abc6 100644
--- a/drivers/mcb/mcb-lpc.c
+++ b/drivers/mcb/mcb-lpc.c
@@ -138,7 +138,7 @@ static struct platform_driver mcb_lpc_driver = {
.name = "mcb-lpc",
},
.probe = mcb_lpc_probe,
- .remove_new = mcb_lpc_remove,
+ .remove = mcb_lpc_remove,
};
static const struct dmi_system_id mcb_lpc_dmi_table[] = {
@@ -184,4 +184,4 @@ module_exit(mcb_lpc_exit);
MODULE_AUTHOR("Andreas Werner <andreas.werner@men.de>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MCB over LPC support");
-MODULE_IMPORT_NS(MCB);
+MODULE_IMPORT_NS("MCB");
diff --git a/drivers/mcb/mcb-parse.c b/drivers/mcb/mcb-parse.c
index a5f8ab9a0910..02a680c73979 100644
--- a/drivers/mcb/mcb-parse.c
+++ b/drivers/mcb/mcb-parse.c
@@ -251,4 +251,4 @@ free_header:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(chameleon_parse_cells, MCB);
+EXPORT_SYMBOL_NS_GPL(chameleon_parse_cells, "MCB");
diff --git a/drivers/mcb/mcb-pci.c b/drivers/mcb/mcb-pci.c
index 3b634ea318c7..f1353da6ef4f 100644
--- a/drivers/mcb/mcb-pci.c
+++ b/drivers/mcb/mcb-pci.c
@@ -154,4 +154,4 @@ module_pci_driver(mcb_pci_driver);
MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MCB over PCI support");
-MODULE_IMPORT_NS(MCB);
+MODULE_IMPORT_NS("MCB");
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index e7abfdd77c3b..e42f1400cea9 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -1718,7 +1718,7 @@ static CLOSURE_CALLBACK(cache_set_flush)
if (!IS_ERR_OR_NULL(c->gc_thread))
kthread_stop(c->gc_thread);
- if (!IS_ERR(c->root))
+ if (!IS_ERR_OR_NULL(c->root))
list_add(&c->root->list, &c->btree_cache);
/*
diff --git a/drivers/md/dm-ebs-target.c b/drivers/md/dm-ebs-target.c
index ec5db1478b2f..18ae45dcbfb2 100644
--- a/drivers/md/dm-ebs-target.c
+++ b/drivers/md/dm-ebs-target.c
@@ -442,7 +442,7 @@ static int ebs_iterate_devices(struct dm_target *ti,
static struct target_type ebs_target = {
.name = "ebs",
.version = {1, 0, 1},
- .features = DM_TARGET_PASSES_INTEGRITY,
+ .features = 0,
.module = THIS_MODULE,
.ctr = ebs_ctr,
.dtr = ebs_dtr,
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index bf0f9dddd146..05cf4e3f2bbe 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2332,10 +2332,9 @@ static struct thin_c *get_first_thin(struct pool *pool)
struct thin_c *tc = NULL;
rcu_read_lock();
- if (!list_empty(&pool->active_thins)) {
- tc = list_entry_rcu(pool->active_thins.next, struct thin_c, list);
+ tc = list_first_or_null_rcu(&pool->active_thins, struct thin_c, list);
+ if (tc)
thin_get(tc);
- }
rcu_read_unlock();
return tc;
diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c
index 62b1a44b8dd2..e61855da6461 100644
--- a/drivers/md/dm-verity-fec.c
+++ b/drivers/md/dm-verity-fec.c
@@ -40,35 +40,23 @@ static inline u64 fec_interleave(struct dm_verity *v, u64 offset)
}
/*
- * Decode an RS block using Reed-Solomon.
- */
-static int fec_decode_rs8(struct dm_verity *v, struct dm_verity_fec_io *fio,
- u8 *data, u8 *fec, int neras)
-{
- int i;
- uint16_t par[DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN];
-
- for (i = 0; i < v->fec->roots; i++)
- par[i] = fec[i];
-
- return decode_rs8(fio->rs, data, par, v->fec->rsn, NULL, neras,
- fio->erasures, 0, NULL);
-}
-
-/*
* Read error-correcting codes for the requested RS block. Returns a pointer
* to the data block. Caller is responsible for releasing buf.
*/
static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index,
- unsigned int *offset, struct dm_buffer **buf,
- unsigned short ioprio)
+ unsigned int *offset, unsigned int par_buf_offset,
+ struct dm_buffer **buf, unsigned short ioprio)
{
u64 position, block, rem;
u8 *res;
+ /* We have already part of parity bytes read, skip to the next block */
+ if (par_buf_offset)
+ index++;
+
position = (index + rsb) * v->fec->roots;
block = div64_u64_rem(position, v->fec->io_size, &rem);
- *offset = (unsigned int)rem;
+ *offset = par_buf_offset ? 0 : (unsigned int)rem;
res = dm_bufio_read_with_ioprio(v->fec->bufio, block, buf, ioprio);
if (IS_ERR(res)) {
@@ -128,11 +116,13 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io,
{
int r, corrected = 0, res;
struct dm_buffer *buf;
- unsigned int n, i, offset;
+ unsigned int n, i, j, offset, par_buf_offset = 0;
+ uint16_t par_buf[DM_VERITY_FEC_RSM - DM_VERITY_FEC_MIN_RSN];
u8 *par, *block;
struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
- par = fec_read_parity(v, rsb, block_offset, &offset, &buf, bio_prio(bio));
+ par = fec_read_parity(v, rsb, block_offset, &offset,
+ par_buf_offset, &buf, bio_prio(bio));
if (IS_ERR(par))
return PTR_ERR(par);
@@ -142,7 +132,11 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io,
*/
fec_for_each_buffer_rs_block(fio, n, i) {
block = fec_buffer_rs_block(v, fio, n, i);
- res = fec_decode_rs8(v, fio, block, &par[offset], neras);
+ for (j = 0; j < v->fec->roots - par_buf_offset; j++)
+ par_buf[par_buf_offset + j] = par[offset + j];
+ /* Decode an RS block using Reed-Solomon */
+ res = decode_rs8(fio->rs, block, par_buf, v->fec->rsn,
+ NULL, neras, fio->erasures, 0, NULL);
if (res < 0) {
r = res;
goto error;
@@ -155,12 +149,22 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_io *io,
if (block_offset >= 1 << v->data_dev_block_bits)
goto done;
- /* read the next block when we run out of parity bytes */
- offset += v->fec->roots;
+ /* Read the next block when we run out of parity bytes */
+ offset += (v->fec->roots - par_buf_offset);
+ /* Check if parity bytes are split between blocks */
+ if (offset < v->fec->io_size && (offset + v->fec->roots) > v->fec->io_size) {
+ par_buf_offset = v->fec->io_size - offset;
+ for (j = 0; j < par_buf_offset; j++)
+ par_buf[j] = par[offset + j];
+ offset += par_buf_offset;
+ } else
+ par_buf_offset = 0;
+
if (offset >= v->fec->io_size) {
dm_bufio_release(buf);
- par = fec_read_parity(v, rsb, block_offset, &offset, &buf, bio_prio(bio));
+ par = fec_read_parity(v, rsb, block_offset, &offset,
+ par_buf_offset, &buf, bio_prio(bio));
if (IS_ERR(par))
return PTR_ERR(par);
}
@@ -724,10 +728,7 @@ int verity_fec_ctr(struct dm_verity *v)
return -E2BIG;
}
- if ((f->roots << SECTOR_SHIFT) & ((1 << v->data_dev_block_bits) - 1))
- f->io_size = 1 << v->data_dev_block_bits;
- else
- f->io_size = v->fec->roots << SECTOR_SHIFT;
+ f->io_size = 1 << v->data_dev_block_bits;
f->bufio = dm_bufio_client_create(f->dev->bdev,
f->io_size,
diff --git a/drivers/md/dm-zoned-reclaim.c b/drivers/md/dm-zoned-reclaim.c
index d58db9a27e6c..76e2c6868548 100644
--- a/drivers/md/dm-zoned-reclaim.c
+++ b/drivers/md/dm-zoned-reclaim.c
@@ -76,9 +76,9 @@ static int dmz_reclaim_align_wp(struct dmz_reclaim *zrc, struct dm_zone *zone,
* pointer and the requested position.
*/
nr_blocks = block - wp_block;
- ret = blkdev_issue_zeroout(dev->bdev,
- dmz_start_sect(zmd, zone) + dmz_blk2sect(wp_block),
- dmz_blk2sect(nr_blocks), GFP_NOIO, 0);
+ ret = blk_zone_issue_zeroout(dev->bdev,
+ dmz_start_sect(zmd, zone) + dmz_blk2sect(wp_block),
+ dmz_blk2sect(nr_blocks), GFP_NOIO);
if (ret) {
dmz_dev_err(dev,
"Align zone %u wp %llu to %llu (wp+%u) blocks failed %d",
diff --git a/drivers/md/persistent-data/dm-array.c b/drivers/md/persistent-data/dm-array.c
index 157c9bd2fed7..8f8792e55806 100644
--- a/drivers/md/persistent-data/dm-array.c
+++ b/drivers/md/persistent-data/dm-array.c
@@ -917,23 +917,27 @@ static int load_ablock(struct dm_array_cursor *c)
if (c->block)
unlock_ablock(c->info, c->block);
- c->block = NULL;
- c->ab = NULL;
c->index = 0;
r = dm_btree_cursor_get_value(&c->cursor, &key, &value_le);
if (r) {
DMERR("dm_btree_cursor_get_value failed");
- dm_btree_cursor_end(&c->cursor);
+ goto out;
} else {
r = get_ablock(c->info, le64_to_cpu(value_le), &c->block, &c->ab);
if (r) {
DMERR("get_ablock failed");
- dm_btree_cursor_end(&c->cursor);
+ goto out;
}
}
+ return 0;
+
+out:
+ dm_btree_cursor_end(&c->cursor);
+ c->block = NULL;
+ c->ab = NULL;
return r;
}
@@ -956,10 +960,10 @@ EXPORT_SYMBOL_GPL(dm_array_cursor_begin);
void dm_array_cursor_end(struct dm_array_cursor *c)
{
- if (c->block) {
+ if (c->block)
unlock_ablock(c->info, c->block);
- dm_btree_cursor_end(&c->cursor);
- }
+
+ dm_btree_cursor_end(&c->cursor);
}
EXPORT_SYMBOL_GPL(dm_array_cursor_end);
@@ -999,6 +1003,7 @@ int dm_array_cursor_skip(struct dm_array_cursor *c, uint32_t count)
}
count -= remaining;
+ c->index += (remaining - 1);
r = dm_array_cursor_next(c);
} while (!r);
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index baaf5f8b80ae..7049ec7fb8eb 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -384,6 +384,7 @@ static int raid0_set_limits(struct mddev *mddev)
lim.max_write_zeroes_sectors = mddev->chunk_sectors;
lim.io_min = mddev->chunk_sectors << 9;
lim.io_opt = lim.io_min * mddev->raid_disks;
+ lim.features |= BLK_FEAT_ATOMIC_WRITES_STACKED;
err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
if (err) {
queue_limits_cancel_update(mddev->gendisk->queue);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index a5adf08ee174..519c56f0ee3d 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1571,7 +1571,21 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
continue;
}
if (is_bad) {
- int good_sectors = first_bad - r1_bio->sector;
+ int good_sectors;
+
+ /*
+ * We cannot atomically write this, so just
+ * error in that case. It could be possible to
+ * atomically write other mirrors, but the
+ * complexity of supporting that is not worth
+ * the benefit.
+ */
+ if (bio->bi_opf & REQ_ATOMIC) {
+ error = -EIO;
+ goto err_handle;
+ }
+
+ good_sectors = first_bad - r1_bio->sector;
if (good_sectors < max_sectors)
max_sectors = good_sectors;
}
@@ -1657,7 +1671,8 @@ static void raid1_write_request(struct mddev *mddev, struct bio *bio,
mbio->bi_iter.bi_sector = (r1_bio->sector + rdev->data_offset);
mbio->bi_end_io = raid1_end_write_request;
- mbio->bi_opf = bio_op(bio) | (bio->bi_opf & (REQ_SYNC | REQ_FUA));
+ mbio->bi_opf = bio_op(bio) |
+ (bio->bi_opf & (REQ_SYNC | REQ_FUA | REQ_ATOMIC));
if (test_bit(FailFast, &rdev->flags) &&
!test_bit(WriteMostly, &rdev->flags) &&
conf->raid_disks - mddev->degraded > 1)
@@ -3224,6 +3239,7 @@ static int raid1_set_limits(struct mddev *mddev)
md_init_stacking_limits(&lim);
lim.max_write_zeroes_sectors = 0;
+ lim.features |= BLK_FEAT_ATOMIC_WRITES_STACKED;
err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
if (err) {
queue_limits_cancel_update(mddev->gendisk->queue);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 18989231791a..7d7a8a2524dc 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1255,6 +1255,7 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
const enum req_op op = bio_op(bio);
const blk_opf_t do_sync = bio->bi_opf & REQ_SYNC;
const blk_opf_t do_fua = bio->bi_opf & REQ_FUA;
+ const blk_opf_t do_atomic = bio->bi_opf & REQ_ATOMIC;
unsigned long flags;
struct r10conf *conf = mddev->private;
struct md_rdev *rdev;
@@ -1273,7 +1274,7 @@ static void raid10_write_one_disk(struct mddev *mddev, struct r10bio *r10_bio,
mbio->bi_iter.bi_sector = (r10_bio->devs[n_copy].addr +
choose_data_offset(r10_bio, rdev));
mbio->bi_end_io = raid10_end_write_request;
- mbio->bi_opf = op | do_sync | do_fua;
+ mbio->bi_opf = op | do_sync | do_fua | do_atomic;
if (!replacement && test_bit(FailFast,
&conf->mirrors[devnum].rdev->flags)
&& enough(conf, devnum))
@@ -1468,7 +1469,21 @@ static void raid10_write_request(struct mddev *mddev, struct bio *bio,
continue;
}
if (is_bad) {
- int good_sectors = first_bad - dev_sector;
+ int good_sectors;
+
+ /*
+ * We cannot atomically write this, so just
+ * error in that case. It could be possible to
+ * atomically write other mirrors, but the
+ * complexity of supporting that is not worth
+ * the benefit.
+ */
+ if (bio->bi_opf & REQ_ATOMIC) {
+ error = -EIO;
+ goto err_handle;
+ }
+
+ good_sectors = first_bad - dev_sector;
if (good_sectors < max_sectors)
max_sectors = good_sectors;
}
@@ -4025,6 +4040,7 @@ static int raid10_set_queue_limits(struct mddev *mddev)
lim.max_write_zeroes_sectors = 0;
lim.io_min = mddev->chunk_sectors << 9;
lim.io_opt = lim.io_min * raid10_nr_stripes(conf);
+ lim.features |= BLK_FEAT_ATOMIC_WRITES_STACKED;
err = mddev_stack_rdev_limits(mddev, &lim, MDDEV_STACK_INTEGRITY);
if (err) {
queue_limits_cancel_update(mddev->gendisk->queue);
diff --git a/drivers/media/common/videobuf2/videobuf2-core.c b/drivers/media/common/videobuf2/videobuf2-core.c
index c0cc441b5164..2df566f409b6 100644
--- a/drivers/media/common/videobuf2/videobuf2-core.c
+++ b/drivers/media/common/videobuf2/videobuf2-core.c
@@ -3334,4 +3334,4 @@ EXPORT_SYMBOL_GPL(vb2_thread_stop);
MODULE_DESCRIPTION("Media buffer core framework");
MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-contig.c b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
index bb0b7fa67b53..a13ec569c82f 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-contig.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-contig.c
@@ -862,4 +862,4 @@ EXPORT_SYMBOL_GPL(vb2_dma_contig_set_max_seg_size);
MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2");
MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
diff --git a/drivers/media/common/videobuf2/videobuf2-dma-sg.c b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
index 6975a71d740f..c6ddf2357c58 100644
--- a/drivers/media/common/videobuf2/videobuf2-dma-sg.c
+++ b/drivers/media/common/videobuf2/videobuf2-dma-sg.c
@@ -676,4 +676,4 @@ EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
MODULE_DESCRIPTION("dma scatter/gather memory handling routines for videobuf2");
MODULE_AUTHOR("Andrzej Pietrasiewicz");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
diff --git a/drivers/media/common/videobuf2/videobuf2-vmalloc.c b/drivers/media/common/videobuf2/videobuf2-vmalloc.c
index 7d953706f3f8..3f777068cd34 100644
--- a/drivers/media/common/videobuf2/videobuf2-vmalloc.c
+++ b/drivers/media/common/videobuf2/videobuf2-vmalloc.c
@@ -442,4 +442,4 @@ EXPORT_SYMBOL_GPL(vb2_vmalloc_memops);
MODULE_DESCRIPTION("vmalloc memory handling routines for videobuf2");
MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
diff --git a/drivers/media/dvb-frontends/dib3000mb.c b/drivers/media/dvb-frontends/dib3000mb.c
index 822639f11c04..63bc7b74bc8b 100644
--- a/drivers/media/dvb-frontends/dib3000mb.c
+++ b/drivers/media/dvb-frontends/dib3000mb.c
@@ -51,7 +51,7 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info,2=xfer,4=setfe,8=getfe (|-a
static int dib3000_read_reg(struct dib3000_state *state, u16 reg)
{
u8 wb[] = { ((reg >> 8) | 0x80) & 0xff, reg & 0xff };
- u8 rb[2];
+ u8 rb[2] = {};
struct i2c_msg msg[] = {
{ .addr = state->config.demod_address, .flags = 0, .buf = wb, .len = 2 },
{ .addr = state->config.demod_address, .flags = I2C_M_RD, .buf = rb, .len = 2 },
diff --git a/drivers/media/i2c/ds90ub913.c b/drivers/media/i2c/ds90ub913.c
index 8eed4a200fd8..79bddfee2e2e 100644
--- a/drivers/media/i2c/ds90ub913.c
+++ b/drivers/media/i2c/ds90ub913.c
@@ -904,4 +904,4 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Texas Instruments DS90UB913 FPD-Link III Serializer Driver");
MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>");
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
-MODULE_IMPORT_NS(I2C_ATR);
+MODULE_IMPORT_NS("I2C_ATR");
diff --git a/drivers/media/i2c/ds90ub953.c b/drivers/media/i2c/ds90ub953.c
index 8b028a84f5bc..725589b3e1c5 100644
--- a/drivers/media/i2c/ds90ub953.c
+++ b/drivers/media/i2c/ds90ub953.c
@@ -1425,4 +1425,4 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Texas Instruments FPD-Link III/IV CSI-2 Serializers Driver");
MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>");
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
-MODULE_IMPORT_NS(I2C_ATR);
+MODULE_IMPORT_NS("I2C_ATR");
diff --git a/drivers/media/i2c/ds90ub960.c b/drivers/media/i2c/ds90ub960.c
index 33f362a00875..1b1ff7f7505b 100644
--- a/drivers/media/i2c/ds90ub960.c
+++ b/drivers/media/i2c/ds90ub960.c
@@ -4052,4 +4052,4 @@ MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Texas Instruments FPD-Link III/IV Deserializers Driver");
MODULE_AUTHOR("Luca Ceresoli <luca@lucaceresoli.net>");
MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ideasonboard.com>");
-MODULE_IMPORT_NS(I2C_ATR);
+MODULE_IMPORT_NS("I2C_ATR");
diff --git a/drivers/media/pci/intel/ipu-bridge.c b/drivers/media/pci/intel/ipu-bridge.c
index a0e9a71580b5..1bf249f446a9 100644
--- a/drivers/media/pci/intel/ipu-bridge.c
+++ b/drivers/media/pci/intel/ipu-bridge.c
@@ -323,7 +323,7 @@ int ipu_bridge_parse_ssdb(struct acpi_device *adev, struct ipu_sensor *sensor)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ipu_bridge_parse_ssdb, INTEL_IPU_BRIDGE);
+EXPORT_SYMBOL_NS_GPL(ipu_bridge_parse_ssdb, "INTEL_IPU_BRIDGE");
static void ipu_bridge_create_fwnode_properties(
struct ipu_sensor *sensor,
@@ -631,7 +631,7 @@ int ipu_bridge_instantiate_vcm(struct device *sensor)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ipu_bridge_instantiate_vcm, INTEL_IPU_BRIDGE);
+EXPORT_SYMBOL_NS_GPL(ipu_bridge_instantiate_vcm, "INTEL_IPU_BRIDGE");
static int ipu_bridge_instantiate_ivsc(struct ipu_sensor *sensor)
{
@@ -882,7 +882,7 @@ err_free_bridge:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(ipu_bridge_init, INTEL_IPU_BRIDGE);
+EXPORT_SYMBOL_NS_GPL(ipu_bridge_init, "INTEL_IPU_BRIDGE");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Intel IPU Sensors Bridge driver");
diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2.c b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
index 4e98f432ed55..dd73d534ac49 100644
--- a/drivers/media/pci/intel/ipu3/ipu3-cio2.c
+++ b/drivers/media/pci/intel/ipu3/ipu3-cio2.c
@@ -2000,4 +2000,4 @@ MODULE_AUTHOR("Yuning Pu");
MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("IPU3 CIO2 driver");
-MODULE_IMPORT_NS(INTEL_IPU_BRIDGE);
+MODULE_IMPORT_NS("INTEL_IPU_BRIDGE");
diff --git a/drivers/media/pci/intel/ipu6/ipu6-buttress.c b/drivers/media/pci/intel/ipu6/ipu6-buttress.c
index 277e101da137..e898902e83f3 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-buttress.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-buttress.c
@@ -506,7 +506,7 @@ bool ipu6_buttress_auth_done(struct ipu6_device *isp)
return val == BUTTRESS_SECURITY_CTL_AUTH_DONE;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_buttress_auth_done, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_auth_done, "INTEL_IPU6");
int ipu6_buttress_reset_authentication(struct ipu6_device *isp)
{
@@ -598,7 +598,7 @@ out:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_buttress_map_fw_image, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_map_fw_image, "INTEL_IPU6");
void ipu6_buttress_unmap_fw_image(struct ipu6_bus_device *sys,
struct sg_table *sgt)
@@ -609,7 +609,7 @@ void ipu6_buttress_unmap_fw_image(struct ipu6_bus_device *sys,
dma_unmap_sgtable(&pdev->dev, sgt, DMA_TO_DEVICE, 0);
sg_free_table(sgt);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_buttress_unmap_fw_image, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_unmap_fw_image, "INTEL_IPU6");
int ipu6_buttress_authenticate(struct ipu6_device *isp)
{
@@ -774,7 +774,7 @@ int ipu6_buttress_start_tsc_sync(struct ipu6_device *isp)
return -ETIMEDOUT;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_buttress_start_tsc_sync, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_start_tsc_sync, "INTEL_IPU6");
void ipu6_buttress_tsc_read(struct ipu6_device *isp, u64 *val)
{
@@ -796,7 +796,7 @@ void ipu6_buttress_tsc_read(struct ipu6_device *isp, u64 *val)
}
local_irq_restore(flags);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_read, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_read, "INTEL_IPU6");
u64 ipu6_buttress_tsc_ticks_to_ns(u64 ticks, const struct ipu6_device *isp)
{
@@ -811,7 +811,7 @@ u64 ipu6_buttress_tsc_ticks_to_ns(u64 ticks, const struct ipu6_device *isp)
*/
return div_u64(ns, isp->buttress.ref_clk);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_ticks_to_ns, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_buttress_tsc_ticks_to_ns, "INTEL_IPU6");
void ipu6_buttress_restore(struct ipu6_device *isp)
{
diff --git a/drivers/media/pci/intel/ipu6/ipu6-cpd.c b/drivers/media/pci/intel/ipu6/ipu6-cpd.c
index 55ffd988ae4f..8b8142bcb2d5 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-cpd.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-cpd.c
@@ -216,14 +216,14 @@ int ipu6_cpd_create_pkg_dir(struct ipu6_bus_device *adev, const void *src)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_cpd_create_pkg_dir, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_cpd_create_pkg_dir, "INTEL_IPU6");
void ipu6_cpd_free_pkg_dir(struct ipu6_bus_device *adev)
{
ipu6_dma_free(adev, adev->pkg_dir_size, adev->pkg_dir,
adev->pkg_dir_dma_addr, 0);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_cpd_free_pkg_dir, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_cpd_free_pkg_dir, "INTEL_IPU6");
static int ipu6_cpd_validate_cpd(struct ipu6_device *isp, const void *cpd,
unsigned long cpd_size,
diff --git a/drivers/media/pci/intel/ipu6/ipu6-dma.c b/drivers/media/pci/intel/ipu6/ipu6-dma.c
index 287b77a6aeab..b34022bad83b 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-dma.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-dma.c
@@ -130,7 +130,7 @@ void ipu6_dma_sync_single(struct ipu6_bus_device *sys, dma_addr_t dma_handle,
vaddr = info->vaddr + offset;
clflush_cache_range(vaddr, size);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_single, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_single, "INTEL_IPU6");
void ipu6_dma_sync_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
int nents)
@@ -141,13 +141,13 @@ void ipu6_dma_sync_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
for_each_sg(sglist, sg, nents, i)
clflush_cache_range(sg_virt(sg), sg->length);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sg, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sg, "INTEL_IPU6");
void ipu6_dma_sync_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt)
{
ipu6_dma_sync_sg(sys, sgt->sgl, sgt->orig_nents);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sgtable, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_sync_sgtable, "INTEL_IPU6");
void *ipu6_dma_alloc(struct ipu6_bus_device *sys, size_t size,
dma_addr_t *dma_handle, gfp_t gfp,
@@ -239,7 +239,7 @@ out_kfree:
return NULL;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_dma_alloc, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_alloc, "INTEL_IPU6");
void ipu6_dma_free(struct ipu6_bus_device *sys, size_t size, void *vaddr,
dma_addr_t dma_handle, unsigned long attrs)
@@ -292,7 +292,7 @@ void ipu6_dma_free(struct ipu6_bus_device *sys, size_t size, void *vaddr,
kfree(info);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_dma_free, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_free, "INTEL_IPU6");
int ipu6_dma_mmap(struct ipu6_bus_device *sys, struct vm_area_struct *vma,
void *addr, dma_addr_t iova, size_t size,
@@ -369,7 +369,7 @@ void ipu6_dma_unmap_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
mmu->tlb_invalidate(mmu);
__free_iova(&mmu->dmap->iovad, iova);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sg, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sg, "INTEL_IPU6");
int ipu6_dma_map_sg(struct ipu6_bus_device *sys, struct scatterlist *sglist,
int nents, enum dma_data_direction dir,
@@ -434,7 +434,7 @@ out_fail:
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sg, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sg, "INTEL_IPU6");
int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
enum dma_data_direction dir, unsigned long attrs)
@@ -449,14 +449,14 @@ int ipu6_dma_map_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sgtable, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_map_sgtable, "INTEL_IPU6");
void ipu6_dma_unmap_sgtable(struct ipu6_bus_device *sys, struct sg_table *sgt,
enum dma_data_direction dir, unsigned long attrs)
{
ipu6_dma_unmap_sg(sys, sgt->sgl, sgt->nents, dir, attrs);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sgtable, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_dma_unmap_sgtable, "INTEL_IPU6");
/*
* Create scatter-list for the already allocated DMA buffer
diff --git a/drivers/media/pci/intel/ipu6/ipu6-fw-com.c b/drivers/media/pci/intel/ipu6/ipu6-fw-com.c
index 53edb445d939..40d8ce138a67 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-fw-com.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-fw-com.c
@@ -261,7 +261,7 @@ void *ipu6_fw_com_prepare(struct ipu6_fw_com_cfg *cfg,
return ctx;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_prepare, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_prepare, "INTEL_IPU6");
int ipu6_fw_com_open(struct ipu6_fw_com_context *ctx)
{
@@ -289,7 +289,7 @@ int ipu6_fw_com_open(struct ipu6_fw_com_context *ctx)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_open, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_open, "INTEL_IPU6");
int ipu6_fw_com_close(struct ipu6_fw_com_context *ctx)
{
@@ -307,7 +307,7 @@ int ipu6_fw_com_close(struct ipu6_fw_com_context *ctx)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_close, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_close, "INTEL_IPU6");
int ipu6_fw_com_release(struct ipu6_fw_com_context *ctx, unsigned int force)
{
@@ -320,7 +320,7 @@ int ipu6_fw_com_release(struct ipu6_fw_com_context *ctx, unsigned int force)
kfree(ctx);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_release, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_release, "INTEL_IPU6");
bool ipu6_fw_com_ready(struct ipu6_fw_com_context *ctx)
{
@@ -332,7 +332,7 @@ bool ipu6_fw_com_ready(struct ipu6_fw_com_context *ctx)
return state == SYSCOM_STATE_READY;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_ready, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_fw_com_ready, "INTEL_IPU6");
void *ipu6_send_get_token(struct ipu6_fw_com_context *ctx, int q_nbr)
{
@@ -360,7 +360,7 @@ void *ipu6_send_get_token(struct ipu6_fw_com_context *ctx, int q_nbr)
return (void *)((uintptr_t)q->host_address + index * q->token_size);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_send_get_token, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_send_get_token, "INTEL_IPU6");
void ipu6_send_put_token(struct ipu6_fw_com_context *ctx, int q_nbr)
{
@@ -373,7 +373,7 @@ void ipu6_send_put_token(struct ipu6_fw_com_context *ctx, int q_nbr)
writel(wr, q_dmem + FW_COM_WR_REG);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_send_put_token, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_send_put_token, "INTEL_IPU6");
void *ipu6_recv_get_token(struct ipu6_fw_com_context *ctx, int q_nbr)
{
@@ -397,7 +397,7 @@ void *ipu6_recv_get_token(struct ipu6_fw_com_context *ctx, int q_nbr)
return (void *)((uintptr_t)q->host_address + rd * q->token_size);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_recv_get_token, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_recv_get_token, "INTEL_IPU6");
void ipu6_recv_put_token(struct ipu6_fw_com_context *ctx, int q_nbr)
{
@@ -410,4 +410,4 @@ void ipu6_recv_put_token(struct ipu6_fw_com_context *ctx, int q_nbr)
writel(rd, q_dmem + FW_COM_RD_REG);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_recv_put_token, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_recv_put_token, "INTEL_IPU6");
diff --git a/drivers/media/pci/intel/ipu6/ipu6-isys.c b/drivers/media/pci/intel/ipu6/ipu6-isys.c
index 7148f8fe23f5..77f9c7319868 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-isys.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-isys.c
@@ -1377,5 +1377,5 @@ MODULE_AUTHOR("Yunliang Ding <yunliang.ding@intel.com>");
MODULE_AUTHOR("Hongju Wang <hongju.wang@intel.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Intel IPU6 input system driver");
-MODULE_IMPORT_NS(INTEL_IPU6);
-MODULE_IMPORT_NS(INTEL_IPU_BRIDGE);
+MODULE_IMPORT_NS("INTEL_IPU6");
+MODULE_IMPORT_NS("INTEL_IPU_BRIDGE");
diff --git a/drivers/media/pci/intel/ipu6/ipu6-mmu.c b/drivers/media/pci/intel/ipu6/ipu6-mmu.c
index a81e9b09a3c5..6d1c0b90169d 100644
--- a/drivers/media/pci/intel/ipu6/ipu6-mmu.c
+++ b/drivers/media/pci/intel/ipu6/ipu6-mmu.c
@@ -542,7 +542,7 @@ int ipu6_mmu_hw_init(struct ipu6_mmu *mmu)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_init, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_init, "INTEL_IPU6");
static struct ipu6_mmu_info *ipu6_mmu_alloc(struct ipu6_device *isp)
{
@@ -607,7 +607,7 @@ void ipu6_mmu_hw_cleanup(struct ipu6_mmu *mmu)
mmu->ready = false;
spin_unlock_irqrestore(&mmu->ready_lock, flags);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_cleanup, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_mmu_hw_cleanup, "INTEL_IPU6");
static struct ipu6_dma_mapping *alloc_dma_mapping(struct ipu6_device *isp)
{
diff --git a/drivers/media/pci/intel/ipu6/ipu6.c b/drivers/media/pci/intel/ipu6/ipu6.c
index a38292e8eaac..277af7cda8ee 100644
--- a/drivers/media/pci/intel/ipu6/ipu6.c
+++ b/drivers/media/pci/intel/ipu6/ipu6.c
@@ -281,7 +281,7 @@ void ipu6_configure_spc(struct ipu6_device *isp,
ipu6_pkg_dir_configure_spc(isp, hw_variant, pkg_dir_idx, base,
pkg_dir, pkg_dir_dma_addr);
}
-EXPORT_SYMBOL_NS_GPL(ipu6_configure_spc, INTEL_IPU6);
+EXPORT_SYMBOL_NS_GPL(ipu6_configure_spc, "INTEL_IPU6");
#define IPU6_ISYS_CSI2_NPORTS 4
#define IPU6SE_ISYS_CSI2_NPORTS 4
@@ -840,7 +840,7 @@ static struct pci_driver ipu6_pci_driver = {
module_pci_driver(ipu6_pci_driver);
-MODULE_IMPORT_NS(INTEL_IPU_BRIDGE);
+MODULE_IMPORT_NS("INTEL_IPU_BRIDGE");
MODULE_AUTHOR("Sakari Ailus <sakari.ailus@linux.intel.com>");
MODULE_AUTHOR("Tianshu Qiu <tian.shu.qiu@intel.com>");
MODULE_AUTHOR("Bingbu Cao <bingbu.cao@intel.com>");
diff --git a/drivers/media/pci/intel/ivsc/mei_csi.c b/drivers/media/pci/intel/ivsc/mei_csi.c
index 2a9c12c975ca..6a893c4547b2 100644
--- a/drivers/media/pci/intel/ivsc/mei_csi.c
+++ b/drivers/media/pci/intel/ivsc/mei_csi.c
@@ -808,7 +808,7 @@ static struct mei_cl_driver mei_csi_driver = {
module_mei_cl_driver(mei_csi_driver);
-MODULE_IMPORT_NS(INTEL_IPU_BRIDGE);
+MODULE_IMPORT_NS("INTEL_IPU_BRIDGE");
MODULE_AUTHOR("Wentong Wu <wentong.wu@intel.com>");
MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>");
MODULE_DESCRIPTION("Device driver for IVSC CSI");
diff --git a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
index eea709d93820..47c302745c1d 100644
--- a/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
+++ b/drivers/media/platform/mediatek/vcodec/decoder/vdec/vdec_vp9_req_lat_if.c
@@ -1188,7 +1188,8 @@ err:
return ret;
}
-static
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
void vdec_vp9_slice_map_counts_eob_coef(unsigned int i, unsigned int j, unsigned int k,
struct vdec_vp9_slice_frame_counts *counts,
struct v4l2_vp9_frame_symbol_counts *counts_helper)
diff --git a/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c b/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
index 1c5b94989aec..b34244ea14dd 100644
--- a/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
+++ b/drivers/media/platform/nvidia/tegra-vde/dmabuf-cache.c
@@ -16,7 +16,7 @@
#include "vde.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
struct tegra_vde_cache_entry {
enum dma_data_direction dma_dir;
diff --git a/drivers/memory/brcmstb_dpfe.c b/drivers/memory/brcmstb_dpfe.c
index 5028467b2dc9..08d9e05b1b33 100644
--- a/drivers/memory/brcmstb_dpfe.c
+++ b/drivers/memory/brcmstb_dpfe.c
@@ -934,7 +934,7 @@ static struct platform_driver brcmstb_dpfe_driver = {
.of_match_table = brcmstb_dpfe_of_match,
},
.probe = brcmstb_dpfe_probe,
- .remove_new = brcmstb_dpfe_remove,
+ .remove = brcmstb_dpfe_remove,
.resume = brcmstb_dpfe_resume,
};
diff --git a/drivers/memory/brcmstb_memc.c b/drivers/memory/brcmstb_memc.c
index 4f17a93aa028..c87b37e2c1f0 100644
--- a/drivers/memory/brcmstb_memc.c
+++ b/drivers/memory/brcmstb_memc.c
@@ -283,7 +283,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(brcmstb_memc_pm_ops, brcmstb_memc_suspend,
static struct platform_driver brcmstb_memc_driver = {
.probe = brcmstb_memc_probe,
- .remove_new = brcmstb_memc_remove,
+ .remove = brcmstb_memc_remove,
.driver = {
.name = "brcmstb_memc",
.of_match_table = brcmstb_memc_of_match,
diff --git a/drivers/memory/emif.c b/drivers/memory/emif.c
index 99eb7d1baa5f..2e1ecae9e959 100644
--- a/drivers/memory/emif.c
+++ b/drivers/memory/emif.c
@@ -1159,7 +1159,7 @@ MODULE_DEVICE_TABLE(of, emif_of_match);
static struct platform_driver emif_driver = {
.probe = emif_probe,
- .remove_new = emif_remove,
+ .remove = emif_remove,
.shutdown = emif_shutdown,
.driver = {
.name = "emif",
diff --git a/drivers/memory/fsl-corenet-cf.c b/drivers/memory/fsl-corenet-cf.c
index f47d05f7c5c5..ecd6c1955153 100644
--- a/drivers/memory/fsl-corenet-cf.c
+++ b/drivers/memory/fsl-corenet-cf.c
@@ -249,7 +249,7 @@ static struct platform_driver ccf_driver = {
.of_match_table = ccf_matches,
},
.probe = ccf_probe,
- .remove_new = ccf_remove,
+ .remove = ccf_remove,
};
module_platform_driver(ccf_driver);
diff --git a/drivers/memory/fsl_ifc.c b/drivers/memory/fsl_ifc.c
index 15e919c24f81..e89e0c6cc4bc 100644
--- a/drivers/memory/fsl_ifc.c
+++ b/drivers/memory/fsl_ifc.c
@@ -316,7 +316,7 @@ static struct platform_driver fsl_ifc_ctrl_driver = {
.of_match_table = fsl_ifc_match,
},
.probe = fsl_ifc_ctrl_probe,
- .remove_new = fsl_ifc_ctrl_remove,
+ .remove = fsl_ifc_ctrl_remove,
};
static int __init fsl_ifc_init(void)
diff --git a/drivers/memory/jz4780-nemc.c b/drivers/memory/jz4780-nemc.c
index fb6db2ffe71b..1a8161514d03 100644
--- a/drivers/memory/jz4780-nemc.c
+++ b/drivers/memory/jz4780-nemc.c
@@ -407,7 +407,7 @@ static const struct of_device_id jz4780_nemc_dt_match[] = {
static struct platform_driver jz4780_nemc_driver = {
.probe = jz4780_nemc_probe,
- .remove_new = jz4780_nemc_remove,
+ .remove = jz4780_nemc_remove,
.driver = {
.name = "jz4780-nemc",
.of_match_table = of_match_ptr(jz4780_nemc_dt_match),
diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 2bc034dff691..5710348f72f6 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -616,7 +616,7 @@ static const struct dev_pm_ops smi_larb_pm_ops = {
static struct platform_driver mtk_smi_larb_driver = {
.probe = mtk_smi_larb_probe,
- .remove_new = mtk_smi_larb_remove,
+ .remove = mtk_smi_larb_remove,
.driver = {
.name = "mtk-smi-larb",
.of_match_table = mtk_smi_larb_of_ids,
@@ -838,7 +838,7 @@ static const struct dev_pm_ops smi_common_pm_ops = {
static struct platform_driver mtk_smi_common_driver = {
.probe = mtk_smi_common_probe,
- .remove_new = mtk_smi_common_remove,
+ .remove = mtk_smi_common_remove,
.driver = {
.name = "mtk-smi-common",
.of_match_table = mtk_smi_common_of_ids,
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index c8a0d82f9c27..50eb9f49512b 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -2743,7 +2743,7 @@ MODULE_DEVICE_TABLE(of, gpmc_dt_ids);
static struct platform_driver gpmc_driver = {
.probe = gpmc_probe,
- .remove_new = gpmc_remove,
+ .remove = gpmc_remove,
.driver = {
.name = DEVICE_NAME,
.of_match_table = of_match_ptr(gpmc_dt_ids),
diff --git a/drivers/memory/renesas-rpc-if.c b/drivers/memory/renesas-rpc-if.c
index 7fbd36fa1a1b..15b4706aafee 100644
--- a/drivers/memory/renesas-rpc-if.c
+++ b/drivers/memory/renesas-rpc-if.c
@@ -795,7 +795,7 @@ MODULE_DEVICE_TABLE(of, rpcif_of_match);
static struct platform_driver rpcif_driver = {
.probe = rpcif_probe,
- .remove_new = rpcif_remove,
+ .remove = rpcif_remove,
.driver = {
.name = "rpc-if",
.of_match_table = rpcif_of_match,
diff --git a/drivers/memory/samsung/exynos5422-dmc.c b/drivers/memory/samsung/exynos5422-dmc.c
index 7d80322754fa..788d49c688b1 100644
--- a/drivers/memory/samsung/exynos5422-dmc.c
+++ b/drivers/memory/samsung/exynos5422-dmc.c
@@ -1571,7 +1571,7 @@ MODULE_DEVICE_TABLE(of, exynos5_dmc_of_match);
static struct platform_driver exynos5_dmc_platdrv = {
.probe = exynos5_dmc_probe,
- .remove_new = exynos5_dmc_remove,
+ .remove = exynos5_dmc_remove,
.driver = {
.name = "exynos5-dmc",
.of_match_table = exynos5_dmc_of_match,
diff --git a/drivers/memory/stm32-fmc2-ebi.c b/drivers/memory/stm32-fmc2-ebi.c
index 566c225f71c0..6e386ab54091 100644
--- a/drivers/memory/stm32-fmc2-ebi.c
+++ b/drivers/memory/stm32-fmc2-ebi.c
@@ -1815,7 +1815,7 @@ MODULE_DEVICE_TABLE(of, stm32_fmc2_ebi_match);
static struct platform_driver stm32_fmc2_ebi_driver = {
.probe = stm32_fmc2_ebi_probe,
- .remove_new = stm32_fmc2_ebi_remove,
+ .remove = stm32_fmc2_ebi_remove,
.driver = {
.name = "stm32_fmc2_ebi",
.of_match_table = stm32_fmc2_ebi_match,
diff --git a/drivers/memory/tegra/tegra186-emc.c b/drivers/memory/tegra/tegra186-emc.c
index 33d67d251719..bc807d7fcd4e 100644
--- a/drivers/memory/tegra/tegra186-emc.c
+++ b/drivers/memory/tegra/tegra186-emc.c
@@ -406,7 +406,7 @@ static struct platform_driver tegra186_emc_driver = {
.sync_state = icc_sync_state,
},
.probe = tegra186_emc_probe,
- .remove_new = tegra186_emc_remove,
+ .remove = tegra186_emc_remove,
};
module_platform_driver(tegra186_emc_driver);
diff --git a/drivers/memory/tegra/tegra210-emc-core.c b/drivers/memory/tegra/tegra210-emc-core.c
index 78ca1d6c0977..2d5d8245a1d3 100644
--- a/drivers/memory/tegra/tegra210-emc-core.c
+++ b/drivers/memory/tegra/tegra210-emc-core.c
@@ -2051,7 +2051,7 @@ static struct platform_driver tegra210_emc_driver = {
.pm = &tegra210_emc_pm_ops,
},
.probe = tegra210_emc_probe,
- .remove_new = tegra210_emc_remove,
+ .remove = tegra210_emc_remove,
};
module_platform_driver(tegra210_emc_driver);
diff --git a/drivers/memory/ti-emif-pm.c b/drivers/memory/ti-emif-pm.c
index 592f70e9c8e5..df362ecc59e9 100644
--- a/drivers/memory/ti-emif-pm.c
+++ b/drivers/memory/ti-emif-pm.c
@@ -330,7 +330,7 @@ static const struct dev_pm_ops ti_emif_pm_ops = {
static struct platform_driver ti_emif_driver = {
.probe = ti_emif_probe,
- .remove_new = ti_emif_remove,
+ .remove = ti_emif_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = ti_emif_of_match,
diff --git a/drivers/memstick/host/rtsx_usb_ms.c b/drivers/memstick/host/rtsx_usb_ms.c
index ffdd8de9ec5d..6eb892fd4d34 100644
--- a/drivers/memstick/host/rtsx_usb_ms.c
+++ b/drivers/memstick/host/rtsx_usb_ms.c
@@ -853,7 +853,7 @@ MODULE_DEVICE_TABLE(platform, rtsx_usb_ms_ids);
static struct platform_driver rtsx_usb_ms_driver = {
.probe = rtsx_usb_ms_drv_probe,
- .remove_new = rtsx_usb_ms_drv_remove,
+ .remove = rtsx_usb_ms_drv_remove,
.id_table = rtsx_usb_ms_ids,
.driver = {
.name = "rtsx_usb_ms",
diff --git a/drivers/message/fusion/mptfc.c b/drivers/message/fusion/mptfc.c
index 91242f26defb..ee61b70aa677 100644
--- a/drivers/message/fusion/mptfc.c
+++ b/drivers/message/fusion/mptfc.c
@@ -137,7 +137,7 @@ static const struct scsi_host_template mptfc_driver_template = {
* Supported hardware
*/
-static struct pci_device_id mptfc_pci_table[] = {
+static const struct pci_device_id mptfc_pci_table[] = {
{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC909,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVICEID_FC919,
diff --git a/drivers/message/fusion/mptsas.c b/drivers/message/fusion/mptsas.c
index a798e26c6402..d0549a4daf76 100644
--- a/drivers/message/fusion/mptsas.c
+++ b/drivers/message/fusion/mptsas.c
@@ -5377,7 +5377,7 @@ static void mptsas_remove(struct pci_dev *pdev)
mptscsih_remove(pdev);
}
-static struct pci_device_id mptsas_pci_table[] = {
+static const struct pci_device_id mptsas_pci_table[] = {
{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1064,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_SAS1068,
diff --git a/drivers/message/fusion/mptspi.c b/drivers/message/fusion/mptspi.c
index 574b882c9a85..4184d0c70ac3 100644
--- a/drivers/message/fusion/mptspi.c
+++ b/drivers/message/fusion/mptspi.c
@@ -1238,7 +1238,7 @@ static struct spi_function_template mptspi_transport_functions = {
* Supported hardware
*/
-static struct pci_device_id mptspi_pci_table[] = {
+static const struct pci_device_id mptspi_pci_table[] = {
{ PCI_VENDOR_ID_LSI_LOGIC, MPI_MANUFACTPAGE_DEVID_53C1030,
PCI_ANY_ID, PCI_ANY_ID },
{ PCI_VENDOR_ID_ATTO, MPI_MANUFACTPAGE_DEVID_53C1030,
diff --git a/drivers/mfd/cs40l50-core.c b/drivers/mfd/cs40l50-core.c
index 26e7a769eb14..4859a33777a0 100644
--- a/drivers/mfd/cs40l50-core.c
+++ b/drivers/mfd/cs40l50-core.c
@@ -567,4 +567,4 @@ EXPORT_GPL_DEV_PM_OPS(cs40l50_pm_ops) = {
MODULE_DESCRIPTION("CS40L50 Advanced Haptic Driver");
MODULE_AUTHOR("James Ogletree, Cirrus Logic Inc. <james.ogletree@cirrus.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(FW_CS_DSP);
+MODULE_IMPORT_NS("FW_CS_DSP");
diff --git a/drivers/mfd/cs42l43-i2c.c b/drivers/mfd/cs42l43-i2c.c
index c9e4ea76149a..f0ad4002652d 100644
--- a/drivers/mfd/cs42l43-i2c.c
+++ b/drivers/mfd/cs42l43-i2c.c
@@ -92,7 +92,7 @@ static struct i2c_driver cs42l43_i2c_driver = {
};
module_i2c_driver(cs42l43_i2c_driver);
-MODULE_IMPORT_NS(MFD_CS42L43);
+MODULE_IMPORT_NS("MFD_CS42L43");
MODULE_DESCRIPTION("CS42L43 I2C Driver");
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
diff --git a/drivers/mfd/cs42l43-sdw.c b/drivers/mfd/cs42l43-sdw.c
index 65f7b1d78248..3938d48039c4 100644
--- a/drivers/mfd/cs42l43-sdw.c
+++ b/drivers/mfd/cs42l43-sdw.c
@@ -215,7 +215,7 @@ static struct sdw_driver cs42l43_sdw_driver = {
};
module_sdw_driver(cs42l43_sdw_driver);
-MODULE_IMPORT_NS(MFD_CS42L43);
+MODULE_IMPORT_NS("MFD_CS42L43");
MODULE_DESCRIPTION("CS42L43 SoundWire Driver");
MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
diff --git a/drivers/mfd/cs42l43.c b/drivers/mfd/cs42l43.c
index e5f17fc430e4..b5ab5e613db7 100644
--- a/drivers/mfd/cs42l43.c
+++ b/drivers/mfd/cs42l43.c
@@ -264,7 +264,7 @@ const struct reg_default cs42l43_reg_default[CS42L43_N_DEFAULTS] = {
{ CS42L43_ASRC_MASK, 0x0000000F },
{ CS42L43_HPOUT_MASK, 0x00000003 },
};
-EXPORT_SYMBOL_NS_GPL(cs42l43_reg_default, MFD_CS42L43);
+EXPORT_SYMBOL_NS_GPL(cs42l43_reg_default, "MFD_CS42L43");
bool cs42l43_readable_register(struct device *dev, unsigned int reg)
{
@@ -392,7 +392,7 @@ bool cs42l43_readable_register(struct device *dev, unsigned int reg)
return false;
}
}
-EXPORT_SYMBOL_NS_GPL(cs42l43_readable_register, MFD_CS42L43);
+EXPORT_SYMBOL_NS_GPL(cs42l43_readable_register, "MFD_CS42L43");
bool cs42l43_precious_register(struct device *dev, unsigned int reg)
{
@@ -407,7 +407,7 @@ bool cs42l43_precious_register(struct device *dev, unsigned int reg)
return false;
}
}
-EXPORT_SYMBOL_NS_GPL(cs42l43_precious_register, MFD_CS42L43);
+EXPORT_SYMBOL_NS_GPL(cs42l43_precious_register, "MFD_CS42L43");
bool cs42l43_volatile_register(struct device *dev, unsigned int reg)
{
@@ -435,7 +435,7 @@ bool cs42l43_volatile_register(struct device *dev, unsigned int reg)
return cs42l43_precious_register(dev, reg);
}
}
-EXPORT_SYMBOL_NS_GPL(cs42l43_volatile_register, MFD_CS42L43);
+EXPORT_SYMBOL_NS_GPL(cs42l43_volatile_register, "MFD_CS42L43");
#define CS42L43_IRQ_OFFSET(reg) ((CS42L43_##reg##_INT) - CS42L43_DECIM_INT)
@@ -1096,7 +1096,7 @@ int cs42l43_dev_probe(struct cs42l43 *cs42l43)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs42l43_dev_probe, MFD_CS42L43);
+EXPORT_SYMBOL_NS_GPL(cs42l43_dev_probe, "MFD_CS42L43");
void cs42l43_dev_remove(struct cs42l43 *cs42l43)
{
@@ -1104,7 +1104,7 @@ void cs42l43_dev_remove(struct cs42l43 *cs42l43)
cs42l43_power_down(cs42l43);
}
-EXPORT_SYMBOL_NS_GPL(cs42l43_dev_remove, MFD_CS42L43);
+EXPORT_SYMBOL_NS_GPL(cs42l43_dev_remove, "MFD_CS42L43");
static int cs42l43_suspend(struct device *dev)
{
diff --git a/drivers/mfd/intel-lpss-acpi.c b/drivers/mfd/intel-lpss-acpi.c
index 557061856e58..63406026d809 100644
--- a/drivers/mfd/intel-lpss-acpi.c
+++ b/drivers/mfd/intel-lpss-acpi.c
@@ -222,4 +222,4 @@ MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel LPSS ACPI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(INTEL_LPSS);
+MODULE_IMPORT_NS("INTEL_LPSS");
diff --git a/drivers/mfd/intel-lpss-pci.c b/drivers/mfd/intel-lpss-pci.c
index 1d8cdc4d5819..1a5b8b13f8d0 100644
--- a/drivers/mfd/intel-lpss-pci.c
+++ b/drivers/mfd/intel-lpss-pci.c
@@ -653,4 +653,4 @@ MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel LPSS PCI driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(INTEL_LPSS);
+MODULE_IMPORT_NS("INTEL_LPSS");
diff --git a/drivers/mfd/intel-lpss.c b/drivers/mfd/intel-lpss.c
index 2a9018112dfc..3ba05ebb9035 100644
--- a/drivers/mfd/intel-lpss.c
+++ b/drivers/mfd/intel-lpss.c
@@ -464,7 +464,7 @@ err_clk_register:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(intel_lpss_probe, INTEL_LPSS);
+EXPORT_SYMBOL_NS_GPL(intel_lpss_probe, "INTEL_LPSS");
void intel_lpss_remove(struct device *dev)
{
@@ -476,7 +476,7 @@ void intel_lpss_remove(struct device *dev)
intel_lpss_unregister_clock(lpss);
ida_free(&intel_lpss_devid_ida, lpss->devid);
}
-EXPORT_SYMBOL_NS_GPL(intel_lpss_remove, INTEL_LPSS);
+EXPORT_SYMBOL_NS_GPL(intel_lpss_remove, "INTEL_LPSS");
static int resume_lpss_device(struct device *dev, void *data)
{
diff --git a/drivers/mfd/intel-m10-bmc-core.c b/drivers/mfd/intel-m10-bmc-core.c
index 8ad5b3821584..e930161bf65e 100644
--- a/drivers/mfd/intel-m10-bmc-core.c
+++ b/drivers/mfd/intel-m10-bmc-core.c
@@ -22,7 +22,7 @@ void m10bmc_fw_state_set(struct intel_m10bmc *m10bmc, enum m10bmc_fw_state new_s
m10bmc->bmcfw_state = new_state;
up_write(&m10bmc->bmcfw_lock);
}
-EXPORT_SYMBOL_NS_GPL(m10bmc_fw_state_set, INTEL_M10_BMC_CORE);
+EXPORT_SYMBOL_NS_GPL(m10bmc_fw_state_set, "INTEL_M10_BMC_CORE");
/*
* For some Intel FPGA devices, the BMC firmware is not available to service
@@ -75,7 +75,7 @@ int m10bmc_sys_read(struct intel_m10bmc *m10bmc, unsigned int offset, unsigned i
return ret;
}
-EXPORT_SYMBOL_NS_GPL(m10bmc_sys_read, INTEL_M10_BMC_CORE);
+EXPORT_SYMBOL_NS_GPL(m10bmc_sys_read, "INTEL_M10_BMC_CORE");
int m10bmc_sys_update_bits(struct intel_m10bmc *m10bmc, unsigned int offset,
unsigned int msk, unsigned int val)
@@ -95,7 +95,7 @@ int m10bmc_sys_update_bits(struct intel_m10bmc *m10bmc, unsigned int offset,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(m10bmc_sys_update_bits, INTEL_M10_BMC_CORE);
+EXPORT_SYMBOL_NS_GPL(m10bmc_sys_update_bits, "INTEL_M10_BMC_CORE");
static ssize_t bmc_version_show(struct device *dev,
struct device_attribute *attr, char *buf)
@@ -183,7 +183,7 @@ const struct attribute_group *m10bmc_dev_groups[] = {
&m10bmc_group,
NULL,
};
-EXPORT_SYMBOL_NS_GPL(m10bmc_dev_groups, INTEL_M10_BMC_CORE);
+EXPORT_SYMBOL_NS_GPL(m10bmc_dev_groups, "INTEL_M10_BMC_CORE");
int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platform_info *info)
{
@@ -201,7 +201,7 @@ int m10bmc_dev_init(struct intel_m10bmc *m10bmc, const struct intel_m10bmc_platf
return ret;
}
-EXPORT_SYMBOL_NS_GPL(m10bmc_dev_init, INTEL_M10_BMC_CORE);
+EXPORT_SYMBOL_NS_GPL(m10bmc_dev_init, "INTEL_M10_BMC_CORE");
MODULE_DESCRIPTION("Intel MAX 10 BMC core driver");
MODULE_AUTHOR("Intel Corporation");
diff --git a/drivers/mfd/intel-m10-bmc-pmci.c b/drivers/mfd/intel-m10-bmc-pmci.c
index 4fa9d380c62b..d213c6ec04ba 100644
--- a/drivers/mfd/intel-m10-bmc-pmci.c
+++ b/drivers/mfd/intel-m10-bmc-pmci.c
@@ -454,4 +454,4 @@ module_dfl_driver(m10bmc_pmci_driver);
MODULE_DESCRIPTION("MAX10 BMC PMCI-based interface");
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(INTEL_M10_BMC_CORE);
+MODULE_IMPORT_NS("INTEL_M10_BMC_CORE");
diff --git a/drivers/mfd/intel-m10-bmc-spi.c b/drivers/mfd/intel-m10-bmc-spi.c
index 36f631ef7a67..cfa620f0c70e 100644
--- a/drivers/mfd/intel-m10-bmc-spi.c
+++ b/drivers/mfd/intel-m10-bmc-spi.c
@@ -181,4 +181,4 @@ MODULE_DESCRIPTION("Intel MAX 10 BMC SPI bus interface");
MODULE_AUTHOR("Intel Corporation");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:intel-m10-bmc");
-MODULE_IMPORT_NS(INTEL_M10_BMC_CORE);
+MODULE_IMPORT_NS("INTEL_M10_BMC_CORE");
diff --git a/drivers/mfd/ocelot-core.c b/drivers/mfd/ocelot-core.c
index 9cccf54fc9c8..41aff2708854 100644
--- a/drivers/mfd/ocelot-core.c
+++ b/drivers/mfd/ocelot-core.c
@@ -113,7 +113,7 @@ int ocelot_chip_reset(struct device *dev)
return readx_poll_timeout(ocelot_gcb_chip_rst_status, ddata, val, !val,
VSC7512_GCB_RST_SLEEP_US, VSC7512_GCB_RST_TIMEOUT_US);
}
-EXPORT_SYMBOL_NS(ocelot_chip_reset, MFD_OCELOT);
+EXPORT_SYMBOL_NS(ocelot_chip_reset, "MFD_OCELOT");
static const struct resource vsc7512_miim0_resources[] = {
DEFINE_RES_REG_NAMED(VSC7512_MIIM0_RES_START, VSC7512_MIIM_RES_SIZE, "gcb_miim0"),
@@ -226,9 +226,9 @@ int ocelot_core_init(struct device *dev)
return devm_mfd_add_devices(dev, PLATFORM_DEVID_AUTO, vsc7512_devs, ndevs, NULL, 0, NULL);
}
-EXPORT_SYMBOL_NS(ocelot_core_init, MFD_OCELOT);
+EXPORT_SYMBOL_NS(ocelot_core_init, "MFD_OCELOT");
MODULE_DESCRIPTION("Externally Controlled Ocelot Chip Driver");
MODULE_AUTHOR("Colin Foster <colin.foster@in-advantage.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(MFD_OCELOT_SPI);
+MODULE_IMPORT_NS("MFD_OCELOT_SPI");
diff --git a/drivers/mfd/ocelot-spi.c b/drivers/mfd/ocelot-spi.c
index b015c8683f1b..1fed9878c323 100644
--- a/drivers/mfd/ocelot-spi.c
+++ b/drivers/mfd/ocelot-spi.c
@@ -193,7 +193,7 @@ struct regmap *ocelot_spi_init_regmap(struct device *dev, const struct resource
return devm_regmap_init(dev, &ocelot_spi_regmap_bus, dev, &regmap_config);
}
-EXPORT_SYMBOL_NS(ocelot_spi_init_regmap, MFD_OCELOT_SPI);
+EXPORT_SYMBOL_NS(ocelot_spi_init_regmap, "MFD_OCELOT_SPI");
static int ocelot_spi_probe(struct spi_device *spi)
{
@@ -295,4 +295,4 @@ module_spi_driver(ocelot_spi_driver);
MODULE_DESCRIPTION("SPI Controlled Ocelot Chip Driver");
MODULE_AUTHOR("Colin Foster <colin.foster@in-advantage.com>");
MODULE_LICENSE("Dual MIT/GPL");
-MODULE_IMPORT_NS(MFD_OCELOT);
+MODULE_IMPORT_NS("MFD_OCELOT");
diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 902c306bc972..09cbe3f0ab1e 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -637,7 +637,6 @@ config MCHP_LAN966X_PCI
source "drivers/misc/c2port/Kconfig"
source "drivers/misc/eeprom/Kconfig"
source "drivers/misc/cb710/Kconfig"
-source "drivers/misc/ti-st/Kconfig"
source "drivers/misc/lis3lv02d/Kconfig"
source "drivers/misc/altera-stapl/Kconfig"
source "drivers/misc/mei/Kconfig"
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 885b22989580..40bf953185c7 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -40,7 +40,6 @@ obj-y += eeprom/
obj-y += cb710/
obj-$(CONFIG_VMWARE_BALLOON) += vmw_balloon.o
obj-$(CONFIG_PCH_PHUB) += pch_phub.o
-obj-y += ti-st/
obj-y += lis3lv02d/
obj-$(CONFIG_ALTERA_STAPL) +=altera-stapl/
obj-$(CONFIG_INTEL_MEI) += mei/
diff --git a/drivers/misc/apds990x.c b/drivers/misc/apds990x.c
index 6d4edd69db12..e7d73c972f65 100644
--- a/drivers/misc/apds990x.c
+++ b/drivers/misc/apds990x.c
@@ -1147,7 +1147,7 @@ static int apds990x_probe(struct i2c_client *client)
err = chip->pdata->setup_resources();
if (err) {
err = -EINVAL;
- goto fail3;
+ goto fail4;
}
}
@@ -1155,7 +1155,7 @@ static int apds990x_probe(struct i2c_client *client)
apds990x_attribute_group);
if (err < 0) {
dev_err(&chip->client->dev, "Sysfs registration failed\n");
- goto fail4;
+ goto fail5;
}
err = request_threaded_irq(client->irq, NULL,
@@ -1166,15 +1166,17 @@ static int apds990x_probe(struct i2c_client *client)
if (err) {
dev_err(&client->dev, "could not get IRQ %d\n",
client->irq);
- goto fail5;
+ goto fail6;
}
return err;
-fail5:
+fail6:
sysfs_remove_group(&chip->client->dev.kobj,
&apds990x_attribute_group[0]);
-fail4:
+fail5:
if (chip->pdata && chip->pdata->release_resources)
chip->pdata->release_resources();
+fail4:
+ pm_runtime_disable(&client->dev);
fail3:
regulator_bulk_disable(ARRAY_SIZE(chip->regs), chip->regs);
fail2:
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 6eac0f335915..35a196341534 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -153,7 +153,7 @@ static int ssc_sound_dai_probe(struct ssc_device *ssc)
ssc->sound_dai = false;
- if (!of_property_read_bool(np, "#sound-dai-cells"))
+ if (!of_property_present(np, "#sound-dai-cells"))
return 0;
id = of_alias_get_id(np, "ssc");
@@ -176,7 +176,7 @@ static void ssc_sound_dai_remove(struct ssc_device *ssc)
#else
static inline int ssc_sound_dai_probe(struct ssc_device *ssc)
{
- if (of_property_read_bool(ssc->pdev->dev.of_node, "#sound-dai-cells"))
+ if (of_property_present(ssc->pdev->dev.of_node, "#sound-dai-cells"))
return -ENOTSUPP;
return 0;
@@ -269,7 +269,7 @@ static struct platform_driver ssc_driver = {
},
.id_table = atmel_ssc_devtypes,
.probe = ssc_probe,
- .remove_new = ssc_remove,
+ .remove = ssc_remove,
};
module_platform_driver(ssc_driver);
diff --git a/drivers/misc/cardreader/alcor_pci.c b/drivers/misc/cardreader/alcor_pci.c
index 0142c4bf4f42..a5549eaf52d0 100644
--- a/drivers/misc/cardreader/alcor_pci.c
+++ b/drivers/misc/cardreader/alcor_pci.c
@@ -17,8 +17,6 @@
#include <linux/alcor_pci.h>
-#define DRV_NAME_ALCOR_PCI "alcor_pci"
-
static DEFINE_IDA(alcor_pci_idr);
static struct mfd_cell alcor_pci_cells[] = {
diff --git a/drivers/misc/cardreader/rtsx_usb.c b/drivers/misc/cardreader/rtsx_usb.c
index f150d8769f19..77b0490a1b38 100644
--- a/drivers/misc/cardreader/rtsx_usb.c
+++ b/drivers/misc/cardreader/rtsx_usb.c
@@ -20,11 +20,11 @@ MODULE_PARM_DESC(polling_pipe, "polling pipe (0: ctl, 1: bulk)");
static const struct mfd_cell rtsx_usb_cells[] = {
[RTSX_USB_SD_CARD] = {
- .name = "rtsx_usb_sdmmc",
+ .name = DRV_NAME_RTSX_USB_SDMMC,
.pdata_size = 0,
},
[RTSX_USB_MS_CARD] = {
- .name = "rtsx_usb_ms",
+ .name = DRV_NAME_RTSX_USB_MS,
.pdata_size = 0,
},
};
@@ -780,7 +780,7 @@ static const struct usb_device_id rtsx_usb_usb_ids[] = {
MODULE_DEVICE_TABLE(usb, rtsx_usb_usb_ids);
static struct usb_driver rtsx_usb_driver = {
- .name = "rtsx_usb",
+ .name = DRV_NAME_RTSX_USB,
.probe = rtsx_usb_probe,
.disconnect = rtsx_usb_disconnect,
.suspend = rtsx_usb_suspend,
diff --git a/drivers/misc/cxl/of.c b/drivers/misc/cxl/of.c
index 03633cccd043..cf6bd8a43056 100644
--- a/drivers/misc/cxl/of.c
+++ b/drivers/misc/cxl/of.c
@@ -339,6 +339,6 @@ struct platform_driver cxl_of_driver = {
.owner = THIS_MODULE
},
.probe = cxl_of_probe,
- .remove_new = cxl_of_remove,
+ .remove = cxl_of_remove,
.shutdown = cxl_of_shutdown,
};
diff --git a/drivers/misc/eeprom/Kconfig b/drivers/misc/eeprom/Kconfig
index 9df12399bda3..cb1c4b8e7fd3 100644
--- a/drivers/misc/eeprom/Kconfig
+++ b/drivers/misc/eeprom/Kconfig
@@ -97,11 +97,11 @@ config EEPROM_DIGSY_MTC_CFG
If unsure, say N.
config EEPROM_IDT_89HPESX
- tristate "IDT 89HPESx PCIe-swtiches EEPROM / CSR support"
+ tristate "IDT 89HPESx PCIe-switches EEPROM / CSR support"
depends on I2C && SYSFS
help
Enable this driver to get read/write access to EEPROM / CSRs
- over IDT PCIe-swtich i2c-slave interface.
+ over IDT PCIe-switch i2c-slave interface.
This driver can also be built as a module. If so, the module
will be called idt_89hpesx.
diff --git a/drivers/misc/eeprom/eeprom_93cx6.c b/drivers/misc/eeprom/eeprom_93cx6.c
index 9627294fe3e9..e6f0e0fc1ca2 100644
--- a/drivers/misc/eeprom/eeprom_93cx6.c
+++ b/drivers/misc/eeprom/eeprom_93cx6.c
@@ -8,6 +8,7 @@
* Supported chipsets: 93c46 & 93c66.
*/
+#include <linux/bits.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
@@ -102,7 +103,7 @@ static void eeprom_93cx6_write_bits(struct eeprom_93cx6 *eeprom,
/*
* Check if this bit needs to be set.
*/
- eeprom->reg_data_in = !!(data & (1 << (i - 1)));
+ eeprom->reg_data_in = !!(data & BIT(i - 1));
/*
* Write the bit to the eeprom register.
@@ -152,7 +153,7 @@ static void eeprom_93cx6_read_bits(struct eeprom_93cx6 *eeprom,
* Read if the bit has been set.
*/
if (eeprom->reg_data_out)
- buf |= (1 << (i - 1));
+ buf |= BIT(i - 1);
eeprom_93cx6_pulse_low(eeprom);
}
@@ -186,6 +187,11 @@ void eeprom_93cx6_read(struct eeprom_93cx6 *eeprom, const u8 word,
eeprom_93cx6_write_bits(eeprom, command,
PCI_EEPROM_WIDTH_OPCODE + eeprom->width);
+ if (has_quirk_extra_read_cycle(eeprom)) {
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
/*
* Read the requested 16 bits.
*/
@@ -252,6 +258,11 @@ void eeprom_93cx6_readb(struct eeprom_93cx6 *eeprom, const u8 byte,
eeprom_93cx6_write_bits(eeprom, command,
PCI_EEPROM_WIDTH_OPCODE + eeprom->width + 1);
+ if (has_quirk_extra_read_cycle(eeprom)) {
+ eeprom_93cx6_pulse_high(eeprom);
+ eeprom_93cx6_pulse_low(eeprom);
+ }
+
/*
* Read the requested 8 bits.
*/
diff --git a/drivers/misc/eeprom/eeprom_93xx46.c b/drivers/misc/eeprom/eeprom_93xx46.c
index e2221be88445..9cae6f530679 100644
--- a/drivers/misc/eeprom/eeprom_93xx46.c
+++ b/drivers/misc/eeprom/eeprom_93xx46.c
@@ -229,7 +229,7 @@ static int eeprom_93xx46_ew(struct eeprom_93xx46_dev *edev, int is_on)
static ssize_t
eeprom_93xx46_write_word(struct eeprom_93xx46_dev *edev,
- const char *buf, unsigned off)
+ const char *buf, unsigned int off)
{
struct spi_message m;
struct spi_transfer t[2] = {};
diff --git a/drivers/misc/fastrpc.c b/drivers/misc/fastrpc.c
index 74181b8c386b..48d08eeb2d20 100644
--- a/drivers/misc/fastrpc.c
+++ b/drivers/misc/fastrpc.c
@@ -2215,7 +2215,7 @@ static const struct of_device_id fastrpc_match_table[] = {
static struct platform_driver fastrpc_cb_driver = {
.probe = fastrpc_cb_probe,
- .remove_new = fastrpc_cb_remove,
+ .remove = fastrpc_cb_remove,
.driver = {
.name = "qcom,fastrpc-cb",
.of_match_table = fastrpc_match_table,
@@ -2505,4 +2505,4 @@ module_exit(fastrpc_exit);
MODULE_DESCRIPTION("Qualcomm FastRPC");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
diff --git a/drivers/misc/hisi_hikey_usb.c b/drivers/misc/hisi_hikey_usb.c
index fb9be37057a8..ffe7b945a298 100644
--- a/drivers/misc/hisi_hikey_usb.c
+++ b/drivers/misc/hisi_hikey_usb.c
@@ -260,7 +260,7 @@ MODULE_DEVICE_TABLE(of, id_table_hisi_hikey_usb);
static struct platform_driver hisi_hikey_usb_driver = {
.probe = hisi_hikey_usb_probe,
- .remove_new = hisi_hikey_usb_remove,
+ .remove = hisi_hikey_usb_remove,
.driver = {
.name = DEVICE_DRIVER_NAME,
.of_match_table = id_table_hisi_hikey_usb,
diff --git a/drivers/misc/isl29020.c b/drivers/misc/isl29020.c
index 1643ba2ff964..c288aeec16c0 100644
--- a/drivers/misc/isl29020.c
+++ b/drivers/misc/isl29020.c
@@ -68,7 +68,7 @@ static ssize_t als_lux_input_data_show(struct device *dev,
if (val < 0)
return val;
lux = ((((1 << (2 * (val & 3))))*1000) * ret_val) / 65536;
- return sprintf(buf, "%ld\n", lux);
+ return sprintf(buf, "%lu\n", lux);
}
static ssize_t als_sensing_range_store(struct device *dev,
diff --git a/drivers/misc/keba/Kconfig b/drivers/misc/keba/Kconfig
index 5fbcbc2252ac..d6d47197a963 100644
--- a/drivers/misc/keba/Kconfig
+++ b/drivers/misc/keba/Kconfig
@@ -1,7 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
config KEBA_CP500
tristate "KEBA CP500 system FPGA support"
+ depends on X86_64 || ARM64 || COMPILE_TEST
depends on PCI
+ depends on I2C
select AUXILIARY_BUS
help
This driver supports the KEBA CP500 system FPGA, which is used in
@@ -11,3 +13,14 @@ config KEBA_CP500
This driver can also be built as a module. If so, the module will be
called cp500.
+
+config KEBA_LAN9252
+ tristate "KEBA CP500 LAN9252 configuration"
+ depends on SPI
+ depends on KEBA_CP500 || COMPILE_TEST
+ help
+ This driver is used for updating the configuration of the LAN9252
+ controller on KEBA CP500 devices.
+
+ This driver can also be built as a module. If so, the module will be
+ called lan9252.
diff --git a/drivers/misc/keba/Makefile b/drivers/misc/keba/Makefile
index 0a8b846cda7d..05e9efcad54f 100644
--- a/drivers/misc/keba/Makefile
+++ b/drivers/misc/keba/Makefile
@@ -1,3 +1,4 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_KEBA_CP500) += cp500.o
+obj-$(CONFIG_KEBA_LAN9252) += lan9252.o
diff --git a/drivers/misc/keba/cp500.c b/drivers/misc/keba/cp500.c
index ae0922817881..255d3022dae8 100644
--- a/drivers/misc/keba/cp500.c
+++ b/drivers/misc/keba/cp500.c
@@ -12,7 +12,12 @@
#include <linux/i2c.h>
#include <linux/misc/keba.h>
#include <linux/module.h>
+#include <linux/mtd/partitions.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/nvmem-provider.h>
#include <linux/pci.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
#define CP500 "cp500"
@@ -27,6 +32,7 @@
/* BAR 0 registers */
#define CP500_VERSION_REG 0x00
#define CP500_RECONFIG_REG 0x11 /* upper 8-bits of STARTUP register */
+#define CP500_PRESENT_REG 0x20
#define CP500_AXI_REG 0x40
/* Bits in BUILD_REG */
@@ -35,14 +41,35 @@
/* Bits in RECONFIG_REG */
#define CP500_RECFG_REQ 0x01 /* reconfigure FPGA on next reset */
+/* Bits in PRESENT_REG */
+#define CP500_PRESENT_FAN0 0x01
+
/* MSIX */
#define CP500_AXI_MSIX 3
+#define CP500_RFB_UART_MSIX 4
+#define CP500_DEBUG_UART_MSIX 5
+#define CP500_SI1_UART_MSIX 6
#define CP500_NUM_MSIX 8
#define CP500_NUM_MSIX_NO_MMI 2
#define CP500_NUM_MSIX_NO_AXI 3
/* EEPROM */
-#define CP500_HW_CPU_EEPROM_NAME "cp500_cpu_eeprom"
+#define CP500_EEPROM_DA_OFFSET 0x016F
+#define CP500_EEPROM_DA_ESC_TYPE_MASK 0x01
+#define CP500_EEPROM_ESC_LAN9252 0x00
+#define CP500_EEPROM_ESC_ET1100 0x01
+#define CP500_EEPROM_CPU_NAME "cpu_eeprom"
+#define CP500_EEPROM_CPU_OFFSET 0
+#define CP500_EEPROM_CPU_SIZE 3072
+#define CP500_EEPROM_USER_NAME "user_eeprom"
+#define CP500_EEPROM_USER_OFFSET 3072
+#define CP500_EEPROM_USER_SIZE 1024
+
+/* SPI flash running at full speed */
+#define CP500_FLASH_HZ (33 * 1000 * 1000)
+
+/* LAN9252 */
+#define CP500_LAN9252_HZ (10 * 1000 * 1000)
#define CP500_IS_CP035(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP035)
#define CP500_IS_CP505(dev) ((dev)->pci_dev->device == PCI_DEVICE_ID_KEBA_CP505)
@@ -51,29 +78,56 @@
struct cp500_dev_info {
off_t offset;
size_t size;
+ unsigned int msix;
};
struct cp500_devs {
struct cp500_dev_info startup;
+ struct cp500_dev_info spi;
struct cp500_dev_info i2c;
+ struct cp500_dev_info fan;
+ struct cp500_dev_info batt;
+ struct cp500_dev_info uart0_rfb;
+ struct cp500_dev_info uart1_dbg;
+ struct cp500_dev_info uart2_si1;
};
/* list of devices within FPGA of CP035 family (CP035, CP056, CP057) */
static struct cp500_devs cp035_devices = {
.startup = { 0x0000, SZ_4K },
+ .spi = { 0x1000, SZ_4K },
.i2c = { 0x4000, SZ_4K },
+ .fan = { 0x9000, SZ_4K },
+ .batt = { 0xA000, SZ_4K },
+ .uart0_rfb = { 0xB000, SZ_4K, CP500_RFB_UART_MSIX },
+ .uart2_si1 = { 0xD000, SZ_4K, CP500_SI1_UART_MSIX },
};
/* list of devices within FPGA of CP505 family (CP503, CP505, CP507) */
static struct cp500_devs cp505_devices = {
.startup = { 0x0000, SZ_4K },
+ .spi = { 0x4000, SZ_4K },
.i2c = { 0x5000, SZ_4K },
+ .fan = { 0x9000, SZ_4K },
+ .batt = { 0xA000, SZ_4K },
+ .uart0_rfb = { 0xB000, SZ_4K, CP500_RFB_UART_MSIX },
+ .uart2_si1 = { 0xD000, SZ_4K, CP500_SI1_UART_MSIX },
};
/* list of devices within FPGA of CP520 family (CP520, CP530) */
static struct cp500_devs cp520_devices = {
- .startup = { 0x0000, SZ_4K },
- .i2c = { 0x5000, SZ_4K },
+ .startup = { 0x0000, SZ_4K },
+ .spi = { 0x4000, SZ_4K },
+ .i2c = { 0x5000, SZ_4K },
+ .fan = { 0x8000, SZ_4K },
+ .batt = { 0x9000, SZ_4K },
+ .uart0_rfb = { 0xC000, SZ_4K, CP500_RFB_UART_MSIX },
+ .uart1_dbg = { 0xD000, SZ_4K, CP500_DEBUG_UART_MSIX },
+};
+
+struct cp500_nvmem {
+ struct nvmem_device *nvmem;
+ unsigned int offset;
};
struct cp500 {
@@ -85,18 +139,31 @@ struct cp500 {
int minor;
int build;
} version;
+ struct notifier_block nvmem_notifier;
+ atomic_t nvmem_notified;
/* system FPGA BAR */
resource_size_t sys_hwbase;
+ struct keba_spi_auxdev *spi;
struct keba_i2c_auxdev *i2c;
+ struct keba_fan_auxdev *fan;
+ struct keba_batt_auxdev *batt;
+ struct keba_uart_auxdev *uart0_rfb;
+ struct keba_uart_auxdev *uart1_dbg;
+ struct keba_uart_auxdev *uart2_si1;
/* ECM EtherCAT BAR */
resource_size_t ecm_hwbase;
+ /* NVMEM devices */
+ struct cp500_nvmem nvmem_cpu;
+ struct cp500_nvmem nvmem_user;
+
void __iomem *system_startup_addr;
};
/* I2C devices */
+#define CP500_EEPROM_ADDR 0x50
static struct i2c_board_info cp500_i2c_info[] = {
{ /* temperature sensor */
I2C_BOARD_INFO("emc1403", 0x4c),
@@ -107,30 +174,66 @@ static struct i2c_board_info cp500_i2c_info[] = {
* CP505 family: bridge board
* CP520 family: carrier board
*/
- I2C_BOARD_INFO("24c32", 0x50),
- .dev_name = CP500_HW_CPU_EEPROM_NAME,
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR),
},
{ /* interface board EEPROM */
- I2C_BOARD_INFO("24c32", 0x51),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 1),
},
{ /*
* EEPROM (optional)
* CP505 family: CPU board
* CP520 family: MMI board
*/
- I2C_BOARD_INFO("24c32", 0x52),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 2),
},
{ /* extension module 0 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x53),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 3),
},
{ /* extension module 1 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x54),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 4),
},
{ /* extension module 2 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x55),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 5),
},
{ /* extension module 3 EEPROM (optional) */
- I2C_BOARD_INFO("24c32", 0x56),
+ I2C_BOARD_INFO("24c32", CP500_EEPROM_ADDR + 6),
+ }
+};
+
+/* SPI devices */
+static struct mtd_partition cp500_partitions[] = {
+ {
+ .name = "system-flash-parts",
+ .size = MTDPART_SIZ_FULL,
+ .offset = 0,
+ .mask_flags = 0
+ }
+};
+static const struct flash_platform_data cp500_w25q32 = {
+ .type = "w25q32",
+ .name = "system-flash",
+ .parts = cp500_partitions,
+ .nr_parts = ARRAY_SIZE(cp500_partitions),
+};
+static const struct flash_platform_data cp500_m25p16 = {
+ .type = "m25p16",
+ .name = "system-flash",
+ .parts = cp500_partitions,
+ .nr_parts = ARRAY_SIZE(cp500_partitions),
+};
+static struct spi_board_info cp500_spi_info[] = {
+ { /* system FPGA configuration bitstream flash */
+ .modalias = "m25p80",
+ .platform_data = &cp500_m25p16,
+ .max_speed_hz = CP500_FLASH_HZ,
+ .chip_select = 0,
+ .mode = SPI_MODE_3,
+ }, { /* LAN9252 EtherCAT slave controller */
+ .modalias = "lan9252",
+ .platform_data = NULL,
+ .max_speed_hz = CP500_LAN9252_HZ,
+ .chip_select = 1,
+ .mode = SPI_MODE_3,
}
};
@@ -229,7 +332,7 @@ static void cp500_i2c_release(struct device *dev)
static int cp500_register_i2c(struct cp500 *cp500)
{
- int retval;
+ int ret;
cp500->i2c = kzalloc(sizeof(*cp500->i2c), GFP_KERNEL);
if (!cp500->i2c)
@@ -251,30 +354,412 @@ static int cp500_register_i2c(struct cp500 *cp500)
cp500->i2c->info_size = ARRAY_SIZE(cp500_i2c_info);
cp500->i2c->info = cp500_i2c_info;
- retval = auxiliary_device_init(&cp500->i2c->auxdev);
- if (retval) {
+ ret = auxiliary_device_init(&cp500->i2c->auxdev);
+ if (ret) {
kfree(cp500->i2c);
cp500->i2c = NULL;
- return retval;
+ return ret;
}
- retval = __auxiliary_device_add(&cp500->i2c->auxdev, "keba");
- if (retval) {
+ ret = __auxiliary_device_add(&cp500->i2c->auxdev, "keba");
+ if (ret) {
auxiliary_device_uninit(&cp500->i2c->auxdev);
cp500->i2c = NULL;
- return retval;
+ return ret;
+ }
+
+ return 0;
+}
+
+static void cp500_spi_release(struct device *dev)
+{
+ struct keba_spi_auxdev *spi =
+ container_of(dev, struct keba_spi_auxdev, auxdev.dev);
+
+ kfree(spi);
+}
+
+static int cp500_register_spi(struct cp500 *cp500, u8 esc_type)
+{
+ int info_size;
+ int ret;
+
+ cp500->spi = kzalloc(sizeof(*cp500->spi), GFP_KERNEL);
+ if (!cp500->spi)
+ return -ENOMEM;
+
+ if (CP500_IS_CP035(cp500))
+ cp500_spi_info[0].platform_data = &cp500_w25q32;
+ if (esc_type == CP500_EEPROM_ESC_LAN9252)
+ info_size = ARRAY_SIZE(cp500_spi_info);
+ else
+ info_size = ARRAY_SIZE(cp500_spi_info) - 1;
+
+ cp500->spi->auxdev.name = "spi";
+ cp500->spi->auxdev.id = 0;
+ cp500->spi->auxdev.dev.release = cp500_spi_release;
+ cp500->spi->auxdev.dev.parent = &cp500->pci_dev->dev;
+ cp500->spi->io = (struct resource) {
+ /* SPI register area */
+ .start = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->spi.offset,
+ .end = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->spi.offset +
+ cp500->devs->spi.size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+ cp500->spi->info_size = info_size;
+ cp500->spi->info = cp500_spi_info;
+
+ ret = auxiliary_device_init(&cp500->spi->auxdev);
+ if (ret) {
+ kfree(cp500->spi);
+ cp500->spi = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&cp500->spi->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&cp500->spi->auxdev);
+ cp500->spi = NULL;
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static void cp500_fan_release(struct device *dev)
+{
+ struct keba_fan_auxdev *fan =
+ container_of(dev, struct keba_fan_auxdev, auxdev.dev);
+
+ kfree(fan);
+}
+
+static int cp500_register_fan(struct cp500 *cp500)
+{
+ int ret;
+
+ cp500->fan = kzalloc(sizeof(*cp500->fan), GFP_KERNEL);
+ if (!cp500->fan)
+ return -ENOMEM;
+
+ cp500->fan->auxdev.name = "fan";
+ cp500->fan->auxdev.id = 0;
+ cp500->fan->auxdev.dev.release = cp500_fan_release;
+ cp500->fan->auxdev.dev.parent = &cp500->pci_dev->dev;
+ cp500->fan->io = (struct resource) {
+ /* fan register area */
+ .start = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->fan.offset,
+ .end = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->fan.offset +
+ cp500->devs->fan.size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+
+ ret = auxiliary_device_init(&cp500->fan->auxdev);
+ if (ret) {
+ kfree(cp500->fan);
+ cp500->fan = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&cp500->fan->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&cp500->fan->auxdev);
+ cp500->fan = NULL;
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static void cp500_batt_release(struct device *dev)
+{
+ struct keba_batt_auxdev *fan =
+ container_of(dev, struct keba_batt_auxdev, auxdev.dev);
+
+ kfree(fan);
+}
+
+static int cp500_register_batt(struct cp500 *cp500)
+{
+ int ret;
+
+ cp500->batt = kzalloc(sizeof(*cp500->batt), GFP_KERNEL);
+ if (!cp500->batt)
+ return -ENOMEM;
+
+ cp500->batt->auxdev.name = "batt";
+ cp500->batt->auxdev.id = 0;
+ cp500->batt->auxdev.dev.release = cp500_batt_release;
+ cp500->batt->auxdev.dev.parent = &cp500->pci_dev->dev;
+ cp500->batt->io = (struct resource) {
+ /* battery register area */
+ .start = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->batt.offset,
+ .end = (resource_size_t) cp500->sys_hwbase +
+ cp500->devs->batt.offset +
+ cp500->devs->batt.size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+
+ ret = auxiliary_device_init(&cp500->batt->auxdev);
+ if (ret) {
+ kfree(cp500->batt);
+ cp500->batt = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&cp500->batt->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&cp500->batt->auxdev);
+ cp500->batt = NULL;
+
+ return ret;
}
return 0;
}
+static void cp500_uart_release(struct device *dev)
+{
+ struct keba_uart_auxdev *uart =
+ container_of(dev, struct keba_uart_auxdev, auxdev.dev);
+
+ kfree(uart);
+}
+
+static int cp500_register_uart(struct cp500 *cp500,
+ struct keba_uart_auxdev **uart, const char *name,
+ struct cp500_dev_info *info, unsigned int irq)
+{
+ int ret;
+
+ *uart = kzalloc(sizeof(**uart), GFP_KERNEL);
+ if (!*uart)
+ return -ENOMEM;
+
+ (*uart)->auxdev.name = name;
+ (*uart)->auxdev.id = 0;
+ (*uart)->auxdev.dev.release = cp500_uart_release;
+ (*uart)->auxdev.dev.parent = &cp500->pci_dev->dev;
+ (*uart)->io = (struct resource) {
+ /* UART register area */
+ .start = (resource_size_t) cp500->sys_hwbase + info->offset,
+ .end = (resource_size_t) cp500->sys_hwbase + info->offset +
+ info->size - 1,
+ .flags = IORESOURCE_MEM,
+ };
+ (*uart)->irq = irq;
+
+ ret = auxiliary_device_init(&(*uart)->auxdev);
+ if (ret) {
+ kfree(*uart);
+ *uart = NULL;
+
+ return ret;
+ }
+ ret = __auxiliary_device_add(&(*uart)->auxdev, "keba");
+ if (ret) {
+ auxiliary_device_uninit(&(*uart)->auxdev);
+ *uart = NULL;
+
+ return ret;
+ }
+
+ return 0;
+}
+
+static int cp500_nvmem_read(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct cp500_nvmem *nvmem = priv;
+ int ret;
+
+ ret = nvmem_device_read(nvmem->nvmem, nvmem->offset + offset, bytes,
+ val);
+ if (ret != bytes)
+ return ret;
+
+ return 0;
+}
+
+static int cp500_nvmem_write(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct cp500_nvmem *nvmem = priv;
+ int ret;
+
+ ret = nvmem_device_write(nvmem->nvmem, nvmem->offset + offset, bytes,
+ val);
+ if (ret != bytes)
+ return ret;
+
+ return 0;
+}
+
+static int cp500_nvmem_register(struct cp500 *cp500, struct nvmem_device *nvmem)
+{
+ struct device *dev = &cp500->pci_dev->dev;
+ struct nvmem_config nvmem_config = {};
+ struct nvmem_device *tmp;
+
+ /*
+ * The main EEPROM of CP500 devices is logically split into two EEPROMs.
+ * The first logical EEPROM with 3 kB contains the type label which is
+ * programmed during production of the device. The second logical EEPROM
+ * with 1 kB is not programmed during production and can be used for
+ * arbitrary user data.
+ */
+
+ nvmem_config.dev = dev;
+ nvmem_config.owner = THIS_MODULE;
+ nvmem_config.id = NVMEM_DEVID_NONE;
+ nvmem_config.type = NVMEM_TYPE_EEPROM;
+ nvmem_config.root_only = true;
+ nvmem_config.reg_read = cp500_nvmem_read;
+ nvmem_config.reg_write = cp500_nvmem_write;
+
+ cp500->nvmem_cpu.nvmem = nvmem;
+ cp500->nvmem_cpu.offset = CP500_EEPROM_CPU_OFFSET;
+ nvmem_config.name = CP500_EEPROM_CPU_NAME;
+ nvmem_config.size = CP500_EEPROM_CPU_SIZE;
+ nvmem_config.priv = &cp500->nvmem_cpu;
+ tmp = devm_nvmem_register(dev, &nvmem_config);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ cp500->nvmem_user.nvmem = nvmem;
+ cp500->nvmem_user.offset = CP500_EEPROM_USER_OFFSET;
+ nvmem_config.name = CP500_EEPROM_USER_NAME;
+ nvmem_config.size = CP500_EEPROM_USER_SIZE;
+ nvmem_config.priv = &cp500->nvmem_user;
+ tmp = devm_nvmem_register(dev, &nvmem_config);
+ if (IS_ERR(tmp))
+ return PTR_ERR(tmp);
+
+ return 0;
+}
+
+static int cp500_nvmem_match(struct device *dev, const void *data)
+{
+ const struct cp500 *cp500 = data;
+ struct i2c_client *client;
+
+ /* match only CPU EEPROM below the cp500 device */
+ dev = dev->parent;
+ client = i2c_verify_client(dev);
+ if (!client || client->addr != CP500_EEPROM_ADDR)
+ return 0;
+ while ((dev = dev->parent))
+ if (dev == &cp500->pci_dev->dev)
+ return 1;
+
+ return 0;
+}
+
+static void cp500_devm_nvmem_put(void *data)
+{
+ struct nvmem_device *nvmem = data;
+
+ nvmem_device_put(nvmem);
+}
+
+static int cp500_nvmem(struct notifier_block *nb, unsigned long action,
+ void *data)
+{
+ struct nvmem_device *nvmem;
+ struct cp500 *cp500;
+ struct device *dev;
+ int notified;
+ u8 esc_type;
+ int ret;
+
+ if (action != NVMEM_ADD)
+ return NOTIFY_DONE;
+ cp500 = container_of(nb, struct cp500, nvmem_notifier);
+ dev = &cp500->pci_dev->dev;
+
+ /* process CPU EEPROM content only once */
+ notified = atomic_read(&cp500->nvmem_notified);
+ if (notified)
+ return NOTIFY_DONE;
+ nvmem = nvmem_device_find(cp500, cp500_nvmem_match);
+ if (IS_ERR_OR_NULL(nvmem))
+ return NOTIFY_DONE;
+ if (!atomic_try_cmpxchg_relaxed(&cp500->nvmem_notified, &notified, 1)) {
+ nvmem_device_put(nvmem);
+
+ return NOTIFY_DONE;
+ }
+
+ ret = devm_add_action_or_reset(dev, cp500_devm_nvmem_put, nvmem);
+ if (ret)
+ return ret;
+
+ ret = cp500_nvmem_register(cp500, nvmem);
+ if (ret)
+ return ret;
+
+ ret = nvmem_device_read(nvmem, CP500_EEPROM_DA_OFFSET, sizeof(esc_type),
+ (void *)&esc_type);
+ if (ret != sizeof(esc_type)) {
+ dev_warn(dev, "Failed to read device assembly!\n");
+
+ return NOTIFY_DONE;
+ }
+ esc_type &= CP500_EEPROM_DA_ESC_TYPE_MASK;
+
+ if (cp500_register_spi(cp500, esc_type))
+ dev_warn(dev, "Failed to register SPI!\n");
+
+ return NOTIFY_OK;
+}
+
static void cp500_register_auxiliary_devs(struct cp500 *cp500)
{
struct device *dev = &cp500->pci_dev->dev;
+ u8 present = ioread8(cp500->system_startup_addr + CP500_PRESENT_REG);
if (cp500_register_i2c(cp500))
- dev_warn(dev, "Failed to register i2c!\n");
+ dev_warn(dev, "Failed to register I2C!\n");
+ if (present & CP500_PRESENT_FAN0)
+ if (cp500_register_fan(cp500))
+ dev_warn(dev, "Failed to register fan!\n");
+ if (cp500_register_batt(cp500))
+ dev_warn(dev, "Failed to register battery!\n");
+ if (cp500->devs->uart0_rfb.size &&
+ cp500->devs->uart0_rfb.msix < cp500->msix_num) {
+ int irq = pci_irq_vector(cp500->pci_dev,
+ cp500->devs->uart0_rfb.msix);
+
+ if (cp500_register_uart(cp500, &cp500->uart0_rfb, "rs485-uart",
+ &cp500->devs->uart0_rfb, irq))
+ dev_warn(dev, "Failed to register RFB UART!\n");
+ }
+ if (cp500->devs->uart1_dbg.size &&
+ cp500->devs->uart1_dbg.msix < cp500->msix_num) {
+ int irq = pci_irq_vector(cp500->pci_dev,
+ cp500->devs->uart1_dbg.msix);
+
+ if (cp500_register_uart(cp500, &cp500->uart1_dbg, "rs232-uart",
+ &cp500->devs->uart1_dbg, irq))
+ dev_warn(dev, "Failed to register debug UART!\n");
+ }
+ if (cp500->devs->uart2_si1.size &&
+ cp500->devs->uart2_si1.msix < cp500->msix_num) {
+ int irq = pci_irq_vector(cp500->pci_dev,
+ cp500->devs->uart2_si1.msix);
+
+ if (cp500_register_uart(cp500, &cp500->uart2_si1, "uart",
+ &cp500->devs->uart2_si1, irq))
+ dev_warn(dev, "Failed to register SI1 UART!\n");
+ }
}
static void cp500_unregister_dev(struct auxiliary_device *auxdev)
@@ -285,11 +770,34 @@ static void cp500_unregister_dev(struct auxiliary_device *auxdev)
static void cp500_unregister_auxiliary_devs(struct cp500 *cp500)
{
-
+ if (cp500->spi) {
+ cp500_unregister_dev(&cp500->spi->auxdev);
+ cp500->spi = NULL;
+ }
if (cp500->i2c) {
cp500_unregister_dev(&cp500->i2c->auxdev);
cp500->i2c = NULL;
}
+ if (cp500->fan) {
+ cp500_unregister_dev(&cp500->fan->auxdev);
+ cp500->fan = NULL;
+ }
+ if (cp500->batt) {
+ cp500_unregister_dev(&cp500->batt->auxdev);
+ cp500->batt = NULL;
+ }
+ if (cp500->uart0_rfb) {
+ cp500_unregister_dev(&cp500->uart0_rfb->auxdev);
+ cp500->uart0_rfb = NULL;
+ }
+ if (cp500->uart1_dbg) {
+ cp500_unregister_dev(&cp500->uart1_dbg->auxdev);
+ cp500->uart1_dbg = NULL;
+ }
+ if (cp500->uart2_si1) {
+ cp500_unregister_dev(&cp500->uart2_si1->auxdev);
+ cp500->uart2_si1 = NULL;
+ }
}
static irqreturn_t cp500_axi_handler(int irq, void *dev)
@@ -396,15 +904,21 @@ static int cp500_probe(struct pci_dev *pci_dev, const struct pci_device_id *id)
pci_set_drvdata(pci_dev, cp500);
+ cp500->nvmem_notifier.notifier_call = cp500_nvmem;
+ ret = nvmem_register_notifier(&cp500->nvmem_notifier);
+ if (ret != 0)
+ goto out_free_irq;
ret = cp500_enable(cp500);
if (ret != 0)
- goto out_free_irq;
+ goto out_unregister_nvmem;
cp500_register_auxiliary_devs(cp500);
return 0;
+out_unregister_nvmem:
+ nvmem_unregister_notifier(&cp500->nvmem_notifier);
out_free_irq:
pci_free_irq_vectors(pci_dev);
out_disable:
@@ -422,6 +936,8 @@ static void cp500_remove(struct pci_dev *pci_dev)
cp500_disable(cp500);
+ nvmem_unregister_notifier(&cp500->nvmem_notifier);
+
pci_set_drvdata(pci_dev, 0);
pci_free_irq_vectors(pci_dev);
diff --git a/drivers/misc/keba/lan9252.c b/drivers/misc/keba/lan9252.c
new file mode 100644
index 000000000000..fc54afd1d05b
--- /dev/null
+++ b/drivers/misc/keba/lan9252.c
@@ -0,0 +1,359 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) KEBA Industrial Automation Gmbh 2024
+ *
+ * Driver for LAN9252 on KEBA CP500 devices
+ *
+ * This driver is used for updating the configuration of the LAN9252 controller
+ * on KEBA CP500 devices. The LAN9252 is connected over SPI, which is also named
+ * PDI.
+ */
+
+#include <linux/spi/spi.h>
+#include <linux/mii.h>
+
+/* SPI commands */
+#define LAN9252_SPI_READ 0x3
+#define LAN9252_SPI_WRITE 0x2
+
+struct lan9252_read_cmd {
+ u8 cmd;
+ u8 addr_0;
+ u8 addr_1;
+} __packed;
+
+struct lan9252_write_cmd {
+ u8 cmd;
+ u8 addr_0;
+ u8 addr_1;
+ u32 data;
+} __packed;
+
+/* byte test register */
+#define LAN9252_BYTE_TEST 0x64
+#define LAN9252_BYTE_TEST_VALUE 0x87654321
+
+/* hardware configuration register */
+#define LAN9252_HW_CFG 0x74
+#define LAN9252_HW_CFG_READY 0x08000000
+
+/* EtherCAT CSR interface data register */
+#define LAN9252_ECAT_CSR_DATA 0x300
+
+/* EtherCAT CSR interface command register */
+#define LAN9252_ECAT_CSR_CMD 0x304
+#define LAN9252_ECAT_CSR_BUSY 0x80000000
+#define LAN9252_ECAT_CSR_READ 0x40000000
+
+/* EtherCAT slave controller MII register */
+#define LAN9252_ESC_MII 0x510
+#define LAN9252_ESC_MII_BUSY 0x8000
+#define LAN9252_ESC_MII_CMD_ERR 0x4000
+#define LAN9252_ESC_MII_READ_ERR 0x2000
+#define LAN9252_ESC_MII_ERR_MASK (LAN9252_ESC_MII_CMD_ERR | \
+ LAN9252_ESC_MII_READ_ERR)
+#define LAN9252_ESC_MII_WRITE 0x0200
+#define LAN9252_ESC_MII_READ 0x0100
+
+/* EtherCAT slave controller PHY address register */
+#define LAN9252_ESC_PHY_ADDR 0x512
+
+/* EtherCAT slave controller PHY register address register */
+#define LAN9252_ESC_PHY_REG_ADDR 0x513
+
+/* EtherCAT slave controller PHY data register */
+#define LAN9252_ESC_PHY_DATA 0x514
+
+/* EtherCAT slave controller PDI access state register */
+#define LAN9252_ESC_MII_PDI 0x517
+#define LAN9252_ESC_MII_ACCESS_PDI 0x01
+#define LAN9252_ESC_MII_ACCESS_ECAT 0x00
+
+/* PHY address */
+#define PHY_ADDRESS 2
+
+#define SPI_RETRY_COUNT 10
+#define SPI_WAIT_US 100
+#define SPI_CSR_WAIT_US 500
+
+static int lan9252_spi_read(struct spi_device *spi, u16 addr, u32 *data)
+{
+ struct lan9252_read_cmd cmd;
+
+ cmd.cmd = LAN9252_SPI_READ;
+ cmd.addr_0 = (addr >> 8) & 0xFF;
+ cmd.addr_1 = addr & 0xFF;
+
+ return spi_write_then_read(spi, (u8 *)&cmd,
+ sizeof(struct lan9252_read_cmd),
+ (u8 *)data, sizeof(u32));
+}
+
+static int lan9252_spi_write(struct spi_device *spi, u16 addr, u32 data)
+{
+ struct lan9252_write_cmd cmd;
+
+ cmd.cmd = LAN9252_SPI_WRITE;
+ cmd.addr_0 = (addr >> 8) & 0xFF;
+ cmd.addr_1 = addr & 0xFF;
+ cmd.data = data;
+
+ return spi_write(spi, (u8 *)&cmd, sizeof(struct lan9252_write_cmd));
+}
+
+static bool lan9252_init(struct spi_device *spi)
+{
+ u32 data;
+ int ret;
+
+ ret = lan9252_spi_read(spi, LAN9252_BYTE_TEST, &data);
+ if (ret || data != LAN9252_BYTE_TEST_VALUE)
+ return false;
+
+ ret = lan9252_spi_read(spi, LAN9252_HW_CFG, &data);
+ if (ret || !(data & LAN9252_HW_CFG_READY))
+ return false;
+
+ return true;
+}
+
+static u8 lan9252_esc_get_size(u16 addr)
+{
+ if (addr == LAN9252_ESC_MII || addr == LAN9252_ESC_PHY_DATA)
+ return 2;
+
+ return 1;
+}
+
+static int lan9252_esc_wait(struct spi_device *spi)
+{
+ ktime_t timeout = ktime_add_us(ktime_get(), SPI_WAIT_US);
+ u32 data;
+ int ret;
+
+ /* wait while CSR command is busy */
+ for (;;) {
+ ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_CMD, &data);
+ if (ret)
+ return ret;
+ if (!(data & LAN9252_ECAT_CSR_BUSY))
+ return 0;
+
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_CMD, &data);
+ if (ret)
+ return ret;
+ break;
+ }
+ }
+
+ return (!(data & LAN9252_ECAT_CSR_BUSY)) ? 0 : -ETIMEDOUT;
+}
+
+static int lan9252_esc_read(struct spi_device *spi, u16 addr, u32 *data)
+{
+ u32 csr_cmd;
+ u8 size;
+ int ret;
+
+ size = lan9252_esc_get_size(addr);
+ csr_cmd = LAN9252_ECAT_CSR_BUSY | LAN9252_ECAT_CSR_READ;
+ csr_cmd |= (size << 16) | addr;
+ ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_CMD, csr_cmd);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_wait(spi);
+ if (ret)
+ return ret;
+
+ ret = lan9252_spi_read(spi, LAN9252_ECAT_CSR_DATA, data);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lan9252_esc_write(struct spi_device *spi, u16 addr, u32 data)
+{
+ u32 csr_cmd;
+ u8 size;
+ int ret;
+
+ ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_DATA, data);
+ if (ret)
+ return ret;
+
+ size = lan9252_esc_get_size(addr);
+ csr_cmd = LAN9252_ECAT_CSR_BUSY;
+ csr_cmd |= (size << 16) | addr;
+ ret = lan9252_spi_write(spi, LAN9252_ECAT_CSR_CMD, csr_cmd);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_wait(spi);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int lan9252_access_mii(struct spi_device *spi, bool access)
+{
+ u32 data;
+
+ if (access)
+ data = LAN9252_ESC_MII_ACCESS_PDI;
+ else
+ data = LAN9252_ESC_MII_ACCESS_ECAT;
+
+ return lan9252_esc_write(spi, LAN9252_ESC_MII_PDI, data);
+}
+
+static int lan9252_mii_wait(struct spi_device *spi)
+{
+ ktime_t timeout = ktime_add_us(ktime_get(), SPI_CSR_WAIT_US);
+ u32 data;
+ int ret;
+
+ /* wait while MII control state machine is busy */
+ for (;;) {
+ ret = lan9252_esc_read(spi, LAN9252_ESC_MII, &data);
+ if (ret)
+ return ret;
+ if (data & LAN9252_ESC_MII_ERR_MASK)
+ return -EIO;
+ if (!(data & LAN9252_ESC_MII_BUSY))
+ return 0;
+
+ if (ktime_compare(ktime_get(), timeout) > 0) {
+ ret = lan9252_esc_read(spi, LAN9252_ESC_MII, &data);
+ if (ret)
+ return ret;
+ if (data & LAN9252_ESC_MII_ERR_MASK)
+ return -EIO;
+ break;
+ }
+ }
+
+ return (!(data & LAN9252_ESC_MII_BUSY)) ? 0 : -ETIMEDOUT;
+}
+
+static int lan9252_mii_read(struct spi_device *spi, u8 phy_addr, u8 reg_addr,
+ u32 *data)
+{
+ int ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_ADDR, phy_addr);
+ if (ret)
+ return ret;
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_REG_ADDR, reg_addr);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_MII, LAN9252_ESC_MII_READ);
+ if (ret)
+ return ret;
+
+ ret = lan9252_mii_wait(spi);
+ if (ret)
+ return ret;
+
+ return lan9252_esc_read(spi, LAN9252_ESC_PHY_DATA, data);
+}
+
+static int lan9252_mii_write(struct spi_device *spi, u8 phy_addr, u8 reg_addr,
+ u32 data)
+{
+ int ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_ADDR, phy_addr);
+ if (ret)
+ return ret;
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_REG_ADDR, reg_addr);
+ if (ret)
+ return ret;
+ ret = lan9252_esc_write(spi, LAN9252_ESC_PHY_DATA, data);
+ if (ret)
+ return ret;
+
+ ret = lan9252_esc_write(spi, LAN9252_ESC_MII, LAN9252_ESC_MII_WRITE);
+ if (ret)
+ return ret;
+
+ return lan9252_mii_wait(spi);
+}
+
+static int lan9252_probe(struct spi_device *spi)
+{
+ u32 data;
+ int retry = SPI_RETRY_COUNT;
+ int ret;
+
+ /* execute specified initialization sequence */
+ while (retry && !lan9252_init(spi))
+ retry--;
+ if (retry == 0) {
+ dev_err(&spi->dev,
+ "Can't initialize LAN9252 SPI communication!");
+ return -EIO;
+ }
+
+ /* enable access to MII management for PDI */
+ ret = lan9252_access_mii(spi, true);
+ if (ret) {
+ dev_err(&spi->dev, "Can't enable access to MII management!");
+ return ret;
+ }
+
+ /*
+ * check PHY configuration and configure if necessary
+ * - full duplex
+ * - auto negotiation disabled
+ * - 100 Mbps
+ */
+ ret = lan9252_mii_read(spi, PHY_ADDRESS, MII_BMCR, &data);
+ if (ret) {
+ dev_err(&spi->dev, "Can't read LAN9252 configuration!");
+ goto out;
+ }
+ if (!(data & BMCR_FULLDPLX) || (data & BMCR_ANENABLE) ||
+ !(data & BMCR_SPEED100)) {
+ /*
+ */
+ data &= ~(BMCR_ANENABLE);
+ data |= (BMCR_FULLDPLX | BMCR_SPEED100);
+ ret = lan9252_mii_write(spi, PHY_ADDRESS, MII_BMCR, data);
+ if (ret)
+ dev_err(&spi->dev,
+ "Can't write LAN9252 configuration!");
+ }
+
+ dev_info(&spi->dev, "LAN9252 PHY configuration");
+
+out:
+ /* disable access to MII management for PDI */
+ lan9252_access_mii(spi, false);
+
+ return ret;
+}
+
+static const struct spi_device_id lan9252_id[] = {
+ {"lan9252"},
+ {}
+};
+MODULE_DEVICE_TABLE(spi, lan9252_id);
+
+static struct spi_driver lan9252_driver = {
+ .driver = {
+ .name = "lan9252",
+ },
+ .probe = lan9252_probe,
+ .id_table = lan9252_id,
+};
+module_spi_driver(lan9252_driver);
+
+MODULE_AUTHOR("Petar Bojanic <boja@keba.com>");
+MODULE_AUTHOR("Gerhard Engleder <eg@keba.com>");
+MODULE_DESCRIPTION("KEBA LAN9252 driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/mei/bus.c b/drivers/misc/mei/bus.c
index 5576146ab13b..718ec5d81d94 100644
--- a/drivers/misc/mei/bus.c
+++ b/drivers/misc/mei/bus.c
@@ -145,8 +145,8 @@ out:
* @cl: host client
* @buf: buffer to receive
* @length: buffer length
- * @mode: io mode
* @vtag: virtual tag
+ * @mode: io mode
* @timeout: recv timeout, 0 for infinite timeout
*
* Return: read size in bytes of < 0 on error
diff --git a/drivers/misc/mei/platform-vsc.c b/drivers/misc/mei/platform-vsc.c
index 20a11b299bcd..435760b1e86f 100644
--- a/drivers/misc/mei/platform-vsc.c
+++ b/drivers/misc/mei/platform-vsc.c
@@ -256,8 +256,6 @@ static int mei_vsc_hw_reset(struct mei_device *mei_dev, bool intr_enable)
vsc_tp_reset(hw->tp);
- vsc_tp_intr_disable(hw->tp);
-
return vsc_tp_init(hw->tp, mei_dev->dev);
}
@@ -437,7 +435,7 @@ MODULE_DEVICE_TABLE(platform, mei_vsc_id_table);
static struct platform_driver mei_vsc_drv = {
.probe = mei_vsc_probe,
- .remove_new = mei_vsc_remove,
+ .remove = mei_vsc_remove,
.id_table = mei_vsc_id_table,
.driver = {
.name = MEI_VSC_DRV_NAME,
@@ -451,4 +449,4 @@ MODULE_AUTHOR("Wentong Wu <wentong.wu@intel.com>");
MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>");
MODULE_DESCRIPTION("Intel Visual Sensing Controller Interface");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(VSC_TP);
+MODULE_IMPORT_NS("VSC_TP");
diff --git a/drivers/misc/mei/vsc-fw-loader.c b/drivers/misc/mei/vsc-fw-loader.c
index 9f129bc641f6..43abefa806e1 100644
--- a/drivers/misc/mei/vsc-fw-loader.c
+++ b/drivers/misc/mei/vsc-fw-loader.c
@@ -317,28 +317,34 @@ static int vsc_identify_silicon(struct vsc_fw_loader *fw_loader)
cmd->data.dump_mem.addr = cpu_to_le32(VSC_EFUSE_ADDR);
cmd->data.dump_mem.len = cpu_to_le16(sizeof(__le32));
ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE);
- if (ret)
- return ret;
- if (ack->token == VSC_TOKEN_ERROR)
- return -EINVAL;
+ if (ret || ack->token == VSC_TOKEN_ERROR) {
+ dev_err(fw_loader->dev, "CMD_DUMP_MEM error %d token %d\n", ret, ack->token);
+ return ret ?: -EINVAL;
+ }
cmd->magic = cpu_to_le32(VSC_MAGIC_NUM);
cmd->cmd_id = VSC_CMD_GET_CONT;
ret = vsc_tp_rom_xfer(fw_loader->tp, cmd, ack, VSC_ROM_PKG_SIZE);
- if (ret)
- return ret;
- if (ack->token != VSC_TOKEN_DUMP_RESP)
- return -EINVAL;
+ if (ret || ack->token != VSC_TOKEN_DUMP_RESP) {
+ dev_err(fw_loader->dev, "CMD_GETCONT error %d token %d\n", ret, ack->token);
+ return ret ?: -EINVAL;
+ }
version = FIELD_GET(VSC_MAINSTEPPING_VERSION_MASK, ack->payload[0]);
sub_version = FIELD_GET(VSC_SUBSTEPPING_VERSION_MASK, ack->payload[0]);
- if (version != VSC_MAINSTEPPING_VERSION_A)
+ if (version != VSC_MAINSTEPPING_VERSION_A) {
+ dev_err(fw_loader->dev, "mainstepping mismatch expected %d got %d\n",
+ VSC_MAINSTEPPING_VERSION_A, version);
return -EINVAL;
+ }
if (sub_version != VSC_SUBSTEPPING_VERSION_0 &&
- sub_version != VSC_SUBSTEPPING_VERSION_1)
+ sub_version != VSC_SUBSTEPPING_VERSION_1) {
+ dev_err(fw_loader->dev, "substepping %d is out of supported range %d - %d\n",
+ sub_version, VSC_SUBSTEPPING_VERSION_0, VSC_SUBSTEPPING_VERSION_1);
return -EINVAL;
+ }
dev_info(fw_loader->dev, "silicon stepping version is %u:%u\n",
version, sub_version);
@@ -767,4 +773,4 @@ err_release_csi:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(vsc_tp_init, VSC_TP);
+EXPORT_SYMBOL_NS_GPL(vsc_tp_init, "VSC_TP");
diff --git a/drivers/misc/mei/vsc-tp.c b/drivers/misc/mei/vsc-tp.c
index 1618cca9a731..35d349fee769 100644
--- a/drivers/misc/mei/vsc-tp.c
+++ b/drivers/misc/mei/vsc-tp.c
@@ -299,7 +299,7 @@ int vsc_tp_xfer(struct vsc_tp *tp, u8 cmd, const void *obuf, size_t olen,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(vsc_tp_xfer, VSC_TP);
+EXPORT_SYMBOL_NS_GPL(vsc_tp_xfer, "VSC_TP");
/**
* vsc_tp_rom_xfer - transfer data to rom code
@@ -364,10 +364,8 @@ void vsc_tp_reset(struct vsc_tp *tp)
gpiod_set_value_cansleep(tp->wakeupfw, 1);
atomic_set(&tp->assert_cnt, 0);
-
- enable_irq(tp->spi->irq);
}
-EXPORT_SYMBOL_NS_GPL(vsc_tp_reset, VSC_TP);
+EXPORT_SYMBOL_NS_GPL(vsc_tp_reset, "VSC_TP");
/**
* vsc_tp_need_read - check if device has data to sent
@@ -385,7 +383,7 @@ bool vsc_tp_need_read(struct vsc_tp *tp)
return true;
}
-EXPORT_SYMBOL_NS_GPL(vsc_tp_need_read, VSC_TP);
+EXPORT_SYMBOL_NS_GPL(vsc_tp_need_read, "VSC_TP");
/**
* vsc_tp_register_event_cb - register a callback function to receive event
@@ -402,7 +400,7 @@ int vsc_tp_register_event_cb(struct vsc_tp *tp, vsc_tp_event_cb_t event_cb,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(vsc_tp_register_event_cb, VSC_TP);
+EXPORT_SYMBOL_NS_GPL(vsc_tp_register_event_cb, "VSC_TP");
/**
* vsc_tp_request_irq - request irq for vsc_tp device
@@ -423,7 +421,7 @@ int vsc_tp_request_irq(struct vsc_tp *tp)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(vsc_tp_request_irq, VSC_TP);
+EXPORT_SYMBOL_NS_GPL(vsc_tp_request_irq, "VSC_TP");
/**
* vsc_tp_free_irq - free irq for vsc_tp device
@@ -433,7 +431,7 @@ void vsc_tp_free_irq(struct vsc_tp *tp)
{
free_irq(tp->spi->irq, tp);
}
-EXPORT_SYMBOL_NS_GPL(vsc_tp_free_irq, VSC_TP);
+EXPORT_SYMBOL_NS_GPL(vsc_tp_free_irq, "VSC_TP");
/**
* vsc_tp_intr_synchronize - synchronize vsc_tp interrupt
@@ -443,7 +441,7 @@ void vsc_tp_intr_synchronize(struct vsc_tp *tp)
{
synchronize_irq(tp->spi->irq);
}
-EXPORT_SYMBOL_NS_GPL(vsc_tp_intr_synchronize, VSC_TP);
+EXPORT_SYMBOL_NS_GPL(vsc_tp_intr_synchronize, "VSC_TP");
/**
* vsc_tp_intr_enable - enable vsc_tp interrupt
@@ -453,7 +451,7 @@ void vsc_tp_intr_enable(struct vsc_tp *tp)
{
enable_irq(tp->spi->irq);
}
-EXPORT_SYMBOL_NS_GPL(vsc_tp_intr_enable, VSC_TP);
+EXPORT_SYMBOL_NS_GPL(vsc_tp_intr_enable, "VSC_TP");
/**
* vsc_tp_intr_disable - disable vsc_tp interrupt
@@ -463,7 +461,7 @@ void vsc_tp_intr_disable(struct vsc_tp *tp)
{
disable_irq(tp->spi->irq);
}
-EXPORT_SYMBOL_NS_GPL(vsc_tp_intr_disable, VSC_TP);
+EXPORT_SYMBOL_NS_GPL(vsc_tp_intr_disable, "VSC_TP");
static int vsc_tp_match_any(struct acpi_device *adev, void *data)
{
diff --git a/drivers/misc/ocxl/sysfs.c b/drivers/misc/ocxl/sysfs.c
index 405180d47d9b..07520d6e6dc5 100644
--- a/drivers/misc/ocxl/sysfs.c
+++ b/drivers/misc/ocxl/sysfs.c
@@ -125,7 +125,7 @@ static const struct vm_operations_struct global_mmio_vmops = {
};
static int global_mmio_mmap(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
struct vm_area_struct *vma)
{
struct ocxl_afu *afu = to_afu(kobj_to_dev(kobj));
diff --git a/drivers/misc/open-dice.c b/drivers/misc/open-dice.c
index e6a61e6d9427..24c29e0f00ef 100644
--- a/drivers/misc/open-dice.c
+++ b/drivers/misc/open-dice.c
@@ -178,7 +178,7 @@ static const struct of_device_id open_dice_of_match[] = {
};
static struct platform_driver open_dice_driver = {
- .remove_new = open_dice_remove,
+ .remove = open_dice_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = open_dice_of_match,
diff --git a/drivers/misc/rpmb-core.c b/drivers/misc/rpmb-core.c
index bc68cde1a8bf..2d653926cdbb 100644
--- a/drivers/misc/rpmb-core.c
+++ b/drivers/misc/rpmb-core.c
@@ -13,7 +13,6 @@
#include <linux/slab.h>
static DEFINE_IDA(rpmb_ida);
-static DEFINE_MUTEX(rpmb_mutex);
/**
* rpmb_dev_get() - increase rpmb device ref counter
@@ -63,9 +62,7 @@ static void rpmb_dev_release(struct device *dev)
{
struct rpmb_dev *rdev = to_rpmb_dev(dev);
- mutex_lock(&rpmb_mutex);
- ida_simple_remove(&rpmb_ida, rdev->id);
- mutex_unlock(&rpmb_mutex);
+ ida_free(&rpmb_ida, rdev->id);
kfree(rdev->descr.dev_id);
kfree(rdev);
}
@@ -175,9 +172,7 @@ struct rpmb_dev *rpmb_dev_register(struct device *dev,
goto err_free_rdev;
}
- mutex_lock(&rpmb_mutex);
- ret = ida_simple_get(&rpmb_ida, 0, 0, GFP_KERNEL);
- mutex_unlock(&rpmb_mutex);
+ ret = ida_alloc(&rpmb_ida, GFP_KERNEL);
if (ret < 0)
goto err_free_dev_id;
rdev->id = ret;
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index 546eb06a40d0..e40b027a88e2 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -451,7 +451,7 @@ static struct platform_driver sram_driver = {
.of_match_table = sram_dt_ids,
},
.probe = sram_probe,
- .remove_new = sram_remove,
+ .remove = sram_remove,
};
static int __init sram_init(void)
diff --git a/drivers/misc/ti-st/Kconfig b/drivers/misc/ti-st/Kconfig
deleted file mode 100644
index 1503a6496f63..000000000000
--- a/drivers/misc/ti-st/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# TI's shared transport line discipline and the protocol
-# drivers (BT, FM and GPS)
-#
-menu "Texas Instruments shared transport line discipline"
-config TI_ST
- tristate "Shared transport core driver"
- depends on NET && TTY
- depends on GPIOLIB || COMPILE_TEST
- select FW_LOADER
- help
- This enables the shared transport core driver for TI
- BT / FM and GPS combo chips. This enables protocol drivers
- to register themselves with core and send data, the responses
- are returned to relevant protocol drivers based on their
- packet types.
-
-endmenu
diff --git a/drivers/misc/ti-st/Makefile b/drivers/misc/ti-st/Makefile
deleted file mode 100644
index 93393100952e..000000000000
--- a/drivers/misc/ti-st/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for TI's shared transport line discipline
-# and its protocol drivers (BT, FM, GPS)
-#
-obj-$(CONFIG_TI_ST) += st_drv.o
-st_drv-objs := st_core.o st_kim.o st_ll.o
diff --git a/drivers/misc/ti-st/st_core.c b/drivers/misc/ti-st/st_core.c
deleted file mode 100644
index b878431553ab..000000000000
--- a/drivers/misc/ti-st/st_core.c
+++ /dev/null
@@ -1,918 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Shared Transport Line discipline driver Core
- * This hooks up ST KIM driver and ST LL driver
- * Copyright (C) 2009-2010 Texas Instruments
- * Author: Pavan Savoy <pavan_savoy@ti.com>
- */
-
-#define pr_fmt(fmt) "(stc): " fmt
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-
-#include <linux/seq_file.h>
-#include <linux/skbuff.h>
-
-#include <linux/ti_wilink_st.h>
-#include <linux/netdevice.h>
-
-/*
- * function pointer pointing to either,
- * st_kim_recv during registration to receive fw download responses
- * st_int_recv after registration to receive proto stack responses
- */
-static void (*st_recv)(void *disc_data, const u8 *ptr, size_t count);
-
-/********************************************************************/
-static void add_channel_to_table(struct st_data_s *st_gdata,
- struct st_proto_s *new_proto)
-{
- pr_info("%s: id %d\n", __func__, new_proto->chnl_id);
- /* list now has the channel id as index itself */
- st_gdata->list[new_proto->chnl_id] = new_proto;
- st_gdata->is_registered[new_proto->chnl_id] = true;
-}
-
-static void remove_channel_from_table(struct st_data_s *st_gdata,
- struct st_proto_s *proto)
-{
- pr_info("%s: id %d\n", __func__, proto->chnl_id);
-/* st_gdata->list[proto->chnl_id] = NULL; */
- st_gdata->is_registered[proto->chnl_id] = false;
-}
-
-/*
- * called from KIM during firmware download.
- *
- * This is a wrapper function to tty->ops->write_room.
- * It returns number of free space available in
- * uart tx buffer.
- */
-int st_get_uart_wr_room(struct st_data_s *st_gdata)
-{
- if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
- pr_err("tty unavailable to perform write");
- return -1;
- }
-
- return tty_write_room(st_gdata->tty);
-}
-
-/*
- * can be called in from
- * -- KIM (during fw download)
- * -- ST Core (during st_write)
- *
- * This is the internal write function - a wrapper
- * to tty->ops->write
- */
-int st_int_write(struct st_data_s *st_gdata,
- const unsigned char *data, int count)
-{
- struct tty_struct *tty;
- if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
- pr_err("tty unavailable to perform write");
- return -EINVAL;
- }
- tty = st_gdata->tty;
-#ifdef VERBOSE
- print_hex_dump(KERN_DEBUG, "<out<", DUMP_PREFIX_NONE,
- 16, 1, data, count, 0);
-#endif
- return tty->ops->write(tty, data, count);
-
-}
-
-/*
- * push the skb received to relevant
- * protocol stacks
- */
-static void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
-{
- pr_debug(" %s(prot:%d) ", __func__, chnl_id);
-
- if (unlikely
- (st_gdata == NULL || st_gdata->rx_skb == NULL
- || st_gdata->is_registered[chnl_id] == false)) {
- pr_err("chnl_id %d not registered, no data to send?",
- chnl_id);
- kfree_skb(st_gdata->rx_skb);
- return;
- }
- /*
- * this cannot fail
- * this shouldn't take long
- * - should be just skb_queue_tail for the
- * protocol stack driver
- */
- if (likely(st_gdata->list[chnl_id]->recv != NULL)) {
- if (unlikely
- (st_gdata->list[chnl_id]->recv
- (st_gdata->list[chnl_id]->priv_data, st_gdata->rx_skb)
- != 0)) {
- pr_err(" proto stack %d's ->recv failed", chnl_id);
- kfree_skb(st_gdata->rx_skb);
- return;
- }
- } else {
- pr_err(" proto stack %d's ->recv null", chnl_id);
- kfree_skb(st_gdata->rx_skb);
- }
- return;
-}
-
-/*
- * st_reg_complete - to call registration complete callbacks
- * of all protocol stack drivers
- * This function is being called with spin lock held, protocol drivers are
- * only expected to complete their waits and do nothing more than that.
- */
-static void st_reg_complete(struct st_data_s *st_gdata, int err)
-{
- unsigned char i = 0;
- pr_info(" %s ", __func__);
- for (i = 0; i < ST_MAX_CHANNELS; i++) {
- if (likely(st_gdata != NULL &&
- st_gdata->is_registered[i] == true &&
- st_gdata->list[i]->reg_complete_cb != NULL)) {
- st_gdata->list[i]->reg_complete_cb
- (st_gdata->list[i]->priv_data, err);
- pr_info("protocol %d's cb sent %d\n", i, err);
- if (err) { /* cleanup registered protocol */
- st_gdata->is_registered[i] = false;
- if (st_gdata->protos_registered)
- st_gdata->protos_registered--;
- }
- }
- }
-}
-
-static inline int st_check_data_len(struct st_data_s *st_gdata,
- unsigned char chnl_id, int len)
-{
- int room = skb_tailroom(st_gdata->rx_skb);
-
- pr_debug("len %d room %d", len, room);
-
- if (!len) {
- /*
- * Received packet has only packet header and
- * has zero length payload. So, ask ST CORE to
- * forward the packet to protocol driver (BT/FM/GPS)
- */
- st_send_frame(chnl_id, st_gdata);
-
- } else if (len > room) {
- /*
- * Received packet's payload length is larger.
- * We can't accommodate it in created skb.
- */
- pr_err("Data length is too large len %d room %d", len,
- room);
- kfree_skb(st_gdata->rx_skb);
- } else {
- /*
- * Packet header has non-zero payload length and
- * we have enough space in created skb. Lets read
- * payload data */
- st_gdata->rx_state = ST_W4_DATA;
- st_gdata->rx_count = len;
- return len;
- }
-
- /* Change ST state to continue to process next packet */
- st_gdata->rx_state = ST_W4_PACKET_TYPE;
- st_gdata->rx_skb = NULL;
- st_gdata->rx_count = 0;
- st_gdata->rx_chnl = 0;
-
- return 0;
-}
-
-/*
- * st_wakeup_ack - internal function for action when wake-up ack
- * received
- */
-static inline void st_wakeup_ack(struct st_data_s *st_gdata,
- unsigned char cmd)
-{
- struct sk_buff *waiting_skb;
- unsigned long flags = 0;
-
- spin_lock_irqsave(&st_gdata->lock, flags);
- /*
- * de-Q from waitQ and Q in txQ now that the
- * chip is awake
- */
- while ((waiting_skb = skb_dequeue(&st_gdata->tx_waitq)))
- skb_queue_tail(&st_gdata->txq, waiting_skb);
-
- /* state forwarded to ST LL */
- st_ll_sleep_state(st_gdata, (unsigned long)cmd);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- /* wake up to send the recently copied skbs from waitQ */
- st_tx_wakeup(st_gdata);
-}
-
-/*
- * st_int_recv - ST's internal receive function.
- * Decodes received RAW data and forwards to corresponding
- * client drivers (Bluetooth,FM,GPS..etc).
- * This can receive various types of packets,
- * HCI-Events, ACL, SCO, 4 types of HCI-LL PM packets
- * CH-8 packets from FM, CH-9 packets from GPS cores.
- */
-static void st_int_recv(void *disc_data, const u8 *ptr, size_t count)
-{
- struct st_proto_s *proto;
- unsigned short payload_len = 0;
- int len = 0;
- unsigned char type = 0;
- unsigned char *plen;
- struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
- unsigned long flags;
-
- if (st_gdata == NULL) {
- pr_err(" received null from TTY ");
- return;
- }
-
- pr_debug("count %zu rx_state %ld"
- "rx_count %ld", count, st_gdata->rx_state,
- st_gdata->rx_count);
-
- spin_lock_irqsave(&st_gdata->lock, flags);
- /* Decode received bytes here */
- while (count) {
- if (st_gdata->rx_count) {
- len = min_t(unsigned int, st_gdata->rx_count, count);
- skb_put_data(st_gdata->rx_skb, ptr, len);
- st_gdata->rx_count -= len;
- count -= len;
- ptr += len;
-
- if (st_gdata->rx_count)
- continue;
-
- /* Check ST RX state machine , where are we? */
- switch (st_gdata->rx_state) {
- /* Waiting for complete packet ? */
- case ST_W4_DATA:
- pr_debug("Complete pkt received");
- /*
- * Ask ST CORE to forward
- * the packet to protocol driver
- */
- st_send_frame(st_gdata->rx_chnl, st_gdata);
-
- st_gdata->rx_state = ST_W4_PACKET_TYPE;
- st_gdata->rx_skb = NULL;
- continue;
- /* parse the header to know details */
- case ST_W4_HEADER:
- proto = st_gdata->list[st_gdata->rx_chnl];
- plen =
- &st_gdata->rx_skb->data
- [proto->offset_len_in_hdr];
- pr_debug("plen pointing to %x\n", *plen);
- if (proto->len_size == 1) /* 1 byte len field */
- payload_len = *(unsigned char *)plen;
- else if (proto->len_size == 2)
- payload_len =
- __le16_to_cpu(*(unsigned short *)plen);
- else
- pr_info("%s: invalid length "
- "for id %d\n",
- __func__, proto->chnl_id);
- st_check_data_len(st_gdata, proto->chnl_id,
- payload_len);
- pr_debug("off %d, pay len %d\n",
- proto->offset_len_in_hdr, payload_len);
- continue;
- } /* end of switch rx_state */
- }
-
- /* end of if rx_count */
-
- /*
- * Check first byte of packet and identify module
- * owner (BT/FM/GPS)
- */
- switch (*ptr) {
- case LL_SLEEP_IND:
- case LL_SLEEP_ACK:
- case LL_WAKE_UP_IND:
- pr_debug("PM packet");
- /*
- * this takes appropriate action based on
- * sleep state received --
- */
- st_ll_sleep_state(st_gdata, *ptr);
- /*
- * if WAKEUP_IND collides copy from waitq to txq
- * and assume chip awake
- */
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- if (st_ll_getstate(st_gdata) == ST_LL_AWAKE)
- st_wakeup_ack(st_gdata, LL_WAKE_UP_ACK);
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- ptr++;
- count--;
- continue;
- case LL_WAKE_UP_ACK:
- pr_debug("PM packet");
-
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- /* wake up ack received */
- st_wakeup_ack(st_gdata, *ptr);
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- ptr++;
- count--;
- continue;
- /* Unknown packet? */
- default:
- type = *ptr;
-
- /*
- * Default case means non-HCILL packets,
- * possibilities are packets for:
- * (a) valid protocol - Supported Protocols within
- * the ST_MAX_CHANNELS.
- * (b) registered protocol - Checked by
- * "st_gdata->list[type] == NULL)" are supported
- * protocols only.
- * Rules out any invalid protocol and
- * unregistered protocols with channel ID < 16.
- */
-
- if ((type >= ST_MAX_CHANNELS) ||
- (st_gdata->list[type] == NULL)) {
- pr_err("chip/interface misbehavior: "
- "dropping frame starting "
- "with 0x%02x\n", type);
- goto done;
- }
-
- st_gdata->rx_skb = alloc_skb(
- st_gdata->list[type]->max_frame_size,
- GFP_ATOMIC);
- if (st_gdata->rx_skb == NULL) {
- pr_err("out of memory: dropping\n");
- goto done;
- }
-
- skb_reserve(st_gdata->rx_skb,
- st_gdata->list[type]->reserve);
- /* next 2 required for BT only */
- st_gdata->rx_skb->cb[0] = type; /*pkt_type*/
- st_gdata->rx_skb->cb[1] = 0; /*incoming*/
- st_gdata->rx_chnl = *ptr;
- st_gdata->rx_state = ST_W4_HEADER;
- st_gdata->rx_count = st_gdata->list[type]->hdr_len;
- pr_debug("rx_count %ld\n", st_gdata->rx_count);
- }
- ptr++;
- count--;
- }
-done:
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- pr_debug("done %s", __func__);
- return;
-}
-
-/*
- * st_int_dequeue - internal de-Q function.
- * If the previous data set was not written
- * completely, return that skb which has the pending data.
- * In normal cases, return top of txq.
- */
-static struct sk_buff *st_int_dequeue(struct st_data_s *st_gdata)
-{
- struct sk_buff *returning_skb;
-
- pr_debug("%s", __func__);
- if (st_gdata->tx_skb != NULL) {
- returning_skb = st_gdata->tx_skb;
- st_gdata->tx_skb = NULL;
- return returning_skb;
- }
- return skb_dequeue(&st_gdata->txq);
-}
-
-/*
- * st_int_enqueue - internal Q-ing function.
- * Will either Q the skb to txq or the tx_waitq
- * depending on the ST LL state.
- * If the chip is asleep, then Q it onto waitq and
- * wakeup the chip.
- * txq and waitq needs protection since the other contexts
- * may be sending data, waking up chip.
- */
-static void st_int_enqueue(struct st_data_s *st_gdata, struct sk_buff *skb)
-{
- unsigned long flags = 0;
-
- pr_debug("%s", __func__);
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- switch (st_ll_getstate(st_gdata)) {
- case ST_LL_AWAKE:
- pr_debug("ST LL is AWAKE, sending normally");
- skb_queue_tail(&st_gdata->txq, skb);
- break;
- case ST_LL_ASLEEP_TO_AWAKE:
- skb_queue_tail(&st_gdata->tx_waitq, skb);
- break;
- case ST_LL_AWAKE_TO_ASLEEP:
- pr_err("ST LL is illegal state(%ld),"
- "purging received skb.", st_ll_getstate(st_gdata));
- dev_kfree_skb_irq(skb);
- break;
- case ST_LL_ASLEEP:
- skb_queue_tail(&st_gdata->tx_waitq, skb);
- st_ll_wakeup(st_gdata);
- break;
- default:
- pr_err("ST LL is illegal state(%ld),"
- "purging received skb.", st_ll_getstate(st_gdata));
- dev_kfree_skb_irq(skb);
- break;
- }
-
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- pr_debug("done %s", __func__);
- return;
-}
-
-/*
- * internal wakeup function
- * called from either
- * - TTY layer when write's finished
- * - st_write (in context of the protocol stack)
- */
-static void work_fn_write_wakeup(struct work_struct *work)
-{
- struct st_data_s *st_gdata = container_of(work, struct st_data_s,
- work_write_wakeup);
-
- st_tx_wakeup((void *)st_gdata);
-}
-void st_tx_wakeup(struct st_data_s *st_data)
-{
- struct sk_buff *skb;
- unsigned long flags; /* for irq save flags */
- pr_debug("%s", __func__);
- /* check for sending & set flag sending here */
- if (test_and_set_bit(ST_TX_SENDING, &st_data->tx_state)) {
- pr_debug("ST already sending");
- /* keep sending */
- set_bit(ST_TX_WAKEUP, &st_data->tx_state);
- return;
- /* TX_WAKEUP will be checked in another
- * context
- */
- }
- do { /* come back if st_tx_wakeup is set */
- /* woke-up to write */
- clear_bit(ST_TX_WAKEUP, &st_data->tx_state);
- while ((skb = st_int_dequeue(st_data))) {
- int len;
- spin_lock_irqsave(&st_data->lock, flags);
- /* enable wake-up from TTY */
- set_bit(TTY_DO_WRITE_WAKEUP, &st_data->tty->flags);
- len = st_int_write(st_data, skb->data, skb->len);
- skb_pull(skb, len);
- /* if skb->len = len as expected, skb->len=0 */
- if (skb->len) {
- /* would be the next skb to be sent */
- st_data->tx_skb = skb;
- spin_unlock_irqrestore(&st_data->lock, flags);
- break;
- }
- dev_kfree_skb_irq(skb);
- spin_unlock_irqrestore(&st_data->lock, flags);
- }
- /* if wake-up is set in another context- restart sending */
- } while (test_bit(ST_TX_WAKEUP, &st_data->tx_state));
-
- /* clear flag sending */
- clear_bit(ST_TX_SENDING, &st_data->tx_state);
-}
-
-/********************************************************************/
-/* functions called from ST KIM
-*/
-void kim_st_list_protocols(struct st_data_s *st_gdata, void *buf)
-{
- seq_printf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n",
- st_gdata->protos_registered,
- st_gdata->is_registered[0x04] == true ? 'R' : 'U',
- st_gdata->is_registered[0x08] == true ? 'R' : 'U',
- st_gdata->is_registered[0x09] == true ? 'R' : 'U');
-}
-
-/********************************************************************/
-/*
- * functions called from protocol stack drivers
- * to be EXPORT-ed
- */
-long st_register(struct st_proto_s *new_proto)
-{
- struct st_data_s *st_gdata;
- long err = 0;
- unsigned long flags = 0;
-
- st_kim_ref(&st_gdata, 0);
- if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
- || new_proto->reg_complete_cb == NULL) {
- pr_err("gdata/new_proto/recv or reg_complete_cb not ready");
- return -EINVAL;
- }
-
- if (new_proto->chnl_id >= ST_MAX_CHANNELS) {
- pr_err("chnl_id %d not supported", new_proto->chnl_id);
- return -EPROTONOSUPPORT;
- }
-
- if (st_gdata->is_registered[new_proto->chnl_id] == true) {
- pr_err("chnl_id %d already registered", new_proto->chnl_id);
- return -EALREADY;
- }
-
- /* can be from process context only */
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- if (test_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state)) {
- pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->chnl_id);
- /* fw download in progress */
-
- add_channel_to_table(st_gdata, new_proto);
- st_gdata->protos_registered++;
- new_proto->write = st_write;
-
- set_bit(ST_REG_PENDING, &st_gdata->st_state);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return -EINPROGRESS;
- } else if (st_gdata->protos_registered == ST_EMPTY) {
- pr_info(" chnl_id list empty :%d ", new_proto->chnl_id);
- set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
- st_recv = st_kim_recv;
-
- /* enable the ST LL - to set default chip state */
- st_ll_enable(st_gdata);
-
- /* release lock previously held - re-locked below */
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- /*
- * this may take a while to complete
- * since it involves BT fw download
- */
- err = st_kim_start(st_gdata->kim_data);
- if (err != 0) {
- clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
- if ((st_gdata->protos_registered != ST_EMPTY) &&
- (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
- pr_err(" KIM failure complete callback ");
- spin_lock_irqsave(&st_gdata->lock, flags);
- st_reg_complete(st_gdata, err);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- clear_bit(ST_REG_PENDING, &st_gdata->st_state);
- }
- return -EINVAL;
- }
-
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
- st_recv = st_int_recv;
-
- /*
- * this is where all pending registration
- * are signalled to be complete by calling callback functions
- */
- if ((st_gdata->protos_registered != ST_EMPTY) &&
- (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
- pr_debug(" call reg complete callback ");
- st_reg_complete(st_gdata, 0);
- }
- clear_bit(ST_REG_PENDING, &st_gdata->st_state);
-
- /*
- * check for already registered once more,
- * since the above check is old
- */
- if (st_gdata->is_registered[new_proto->chnl_id] == true) {
- pr_err(" proto %d already registered ",
- new_proto->chnl_id);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return -EALREADY;
- }
-
- add_channel_to_table(st_gdata, new_proto);
- st_gdata->protos_registered++;
- new_proto->write = st_write;
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return err;
- }
- /* if fw is already downloaded & new stack registers protocol */
- else {
- add_channel_to_table(st_gdata, new_proto);
- st_gdata->protos_registered++;
- new_proto->write = st_write;
-
- /* lock already held before entering else */
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return err;
- }
-}
-EXPORT_SYMBOL_GPL(st_register);
-
-/*
- * to unregister a protocol -
- * to be called from protocol stack driver
- */
-long st_unregister(struct st_proto_s *proto)
-{
- long err = 0;
- unsigned long flags = 0;
- struct st_data_s *st_gdata;
-
- pr_debug("%s: %d ", __func__, proto->chnl_id);
-
- st_kim_ref(&st_gdata, 0);
- if (!st_gdata || proto->chnl_id >= ST_MAX_CHANNELS) {
- pr_err(" chnl_id %d not supported", proto->chnl_id);
- return -EPROTONOSUPPORT;
- }
-
- spin_lock_irqsave(&st_gdata->lock, flags);
-
- if (st_gdata->is_registered[proto->chnl_id] == false) {
- pr_err(" chnl_id %d not registered", proto->chnl_id);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- return -EPROTONOSUPPORT;
- }
-
- if (st_gdata->protos_registered)
- st_gdata->protos_registered--;
-
- remove_channel_from_table(st_gdata, proto);
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- if ((st_gdata->protos_registered == ST_EMPTY) &&
- (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
- pr_info(" all chnl_ids unregistered ");
-
- /* stop traffic on tty */
- if (st_gdata->tty) {
- tty_ldisc_flush(st_gdata->tty);
- stop_tty(st_gdata->tty);
- }
-
- /* all chnl_ids now unregistered */
- st_kim_stop(st_gdata->kim_data);
- /* disable ST LL */
- st_ll_disable(st_gdata);
- }
- return err;
-}
-
-/*
- * called in protocol stack drivers
- * via the write function pointer
- */
-long st_write(struct sk_buff *skb)
-{
- struct st_data_s *st_gdata;
- long len;
-
- st_kim_ref(&st_gdata, 0);
- if (unlikely(skb == NULL || st_gdata == NULL
- || st_gdata->tty == NULL)) {
- pr_err("data/tty unavailable to perform write");
- return -EINVAL;
- }
-
- pr_debug("%d to be written", skb->len);
- len = skb->len;
-
- /* st_ll to decide where to enqueue the skb */
- st_int_enqueue(st_gdata, skb);
- /* wake up */
- st_tx_wakeup(st_gdata);
-
- /* return number of bytes written */
- return len;
-}
-
-/* for protocols making use of shared transport */
-EXPORT_SYMBOL_GPL(st_unregister);
-
-/********************************************************************/
-/*
- * functions called from TTY layer
- */
-static int st_tty_open(struct tty_struct *tty)
-{
- struct st_data_s *st_gdata;
- pr_info("%s ", __func__);
-
- st_kim_ref(&st_gdata, 0);
- st_gdata->tty = tty;
- tty->disc_data = st_gdata;
-
- /* don't do an wakeup for now */
- clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-
- /* mem already allocated
- */
- tty->receive_room = 65536;
- /* Flush any pending characters in the driver and discipline. */
- tty_ldisc_flush(tty);
- tty_driver_flush_buffer(tty);
- /*
- * signal to UIM via KIM that -
- * installation of N_TI_WL ldisc is complete
- */
- st_kim_complete(st_gdata->kim_data);
- pr_debug("done %s", __func__);
-
- return 0;
-}
-
-static void st_tty_close(struct tty_struct *tty)
-{
- unsigned char i;
- unsigned long flags;
- struct st_data_s *st_gdata = tty->disc_data;
-
- pr_info("%s ", __func__);
-
- /*
- * TODO:
- * if a protocol has been registered & line discipline
- * un-installed for some reason - what should be done ?
- */
- spin_lock_irqsave(&st_gdata->lock, flags);
- for (i = ST_BT; i < ST_MAX_CHANNELS; i++) {
- if (st_gdata->is_registered[i] == true)
- pr_err("%d not un-registered", i);
- st_gdata->list[i] = NULL;
- st_gdata->is_registered[i] = false;
- }
- st_gdata->protos_registered = 0;
- spin_unlock_irqrestore(&st_gdata->lock, flags);
- /*
- * signal to UIM via KIM that -
- * N_TI_WL ldisc is un-installed
- */
- st_kim_complete(st_gdata->kim_data);
- st_gdata->tty = NULL;
- /* Flush any pending characters in the driver and discipline. */
- tty_ldisc_flush(tty);
- tty_driver_flush_buffer(tty);
-
- spin_lock_irqsave(&st_gdata->lock, flags);
- /* empty out txq and tx_waitq */
- skb_queue_purge(&st_gdata->txq);
- skb_queue_purge(&st_gdata->tx_waitq);
- /* reset the TTY Rx states of ST */
- st_gdata->rx_count = 0;
- st_gdata->rx_state = ST_W4_PACKET_TYPE;
- kfree_skb(st_gdata->rx_skb);
- st_gdata->rx_skb = NULL;
- spin_unlock_irqrestore(&st_gdata->lock, flags);
-
- pr_debug("%s: done ", __func__);
-}
-
-static void st_tty_receive(struct tty_struct *tty, const u8 *data,
- const u8 *tty_flags, size_t count)
-{
-#ifdef VERBOSE
- print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE,
- 16, 1, data, count, 0);
-#endif
-
- /*
- * if fw download is in progress then route incoming data
- * to KIM for validation
- */
- st_recv(tty->disc_data, data, count);
- pr_debug("done %s", __func__);
-}
-
-/*
- * wake-up function called in from the TTY layer
- * inside the internal wakeup function will be called
- */
-static void st_tty_wakeup(struct tty_struct *tty)
-{
- struct st_data_s *st_gdata = tty->disc_data;
- pr_debug("%s ", __func__);
- /* don't do an wakeup for now */
- clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
-
- /*
- * schedule the internal wakeup instead of calling directly to
- * avoid lockup (port->lock needed in tty->ops->write is
- * already taken here
- */
- schedule_work(&st_gdata->work_write_wakeup);
-}
-
-static void st_tty_flush_buffer(struct tty_struct *tty)
-{
- struct st_data_s *st_gdata = tty->disc_data;
- pr_debug("%s ", __func__);
-
- kfree_skb(st_gdata->tx_skb);
- st_gdata->tx_skb = NULL;
-
- tty_driver_flush_buffer(tty);
- return;
-}
-
-static struct tty_ldisc_ops st_ldisc_ops = {
- .num = N_TI_WL,
- .name = "n_st",
- .open = st_tty_open,
- .close = st_tty_close,
- .receive_buf = st_tty_receive,
- .write_wakeup = st_tty_wakeup,
- .flush_buffer = st_tty_flush_buffer,
- .owner = THIS_MODULE
-};
-
-/********************************************************************/
-int st_core_init(struct st_data_s **core_data)
-{
- struct st_data_s *st_gdata;
- long err;
-
- err = tty_register_ldisc(&st_ldisc_ops);
- if (err) {
- pr_err("error registering %d line discipline %ld",
- N_TI_WL, err);
- return err;
- }
- pr_debug("registered n_shared line discipline");
-
- st_gdata = kzalloc(sizeof(struct st_data_s), GFP_KERNEL);
- if (!st_gdata) {
- pr_err("memory allocation failed");
- err = -ENOMEM;
- goto err_unreg_ldisc;
- }
-
- /* Initialize ST TxQ and Tx waitQ queue head. All BT/FM/GPS module skb's
- * will be pushed in this queue for actual transmission.
- */
- skb_queue_head_init(&st_gdata->txq);
- skb_queue_head_init(&st_gdata->tx_waitq);
-
- /* Locking used in st_int_enqueue() to avoid multiple execution */
- spin_lock_init(&st_gdata->lock);
-
- err = st_ll_init(st_gdata);
- if (err) {
- pr_err("error during st_ll initialization(%ld)", err);
- goto err_free_gdata;
- }
-
- INIT_WORK(&st_gdata->work_write_wakeup, work_fn_write_wakeup);
-
- *core_data = st_gdata;
- return 0;
-err_free_gdata:
- kfree(st_gdata);
-err_unreg_ldisc:
- tty_unregister_ldisc(&st_ldisc_ops);
- return err;
-}
-
-void st_core_exit(struct st_data_s *st_gdata)
-{
- long err;
- /* internal module cleanup */
- err = st_ll_deinit(st_gdata);
- if (err)
- pr_err("error during deinit of ST LL %ld", err);
-
- if (st_gdata != NULL) {
- /* Free ST Tx Qs and skbs */
- skb_queue_purge(&st_gdata->txq);
- skb_queue_purge(&st_gdata->tx_waitq);
- kfree_skb(st_gdata->rx_skb);
- kfree_skb(st_gdata->tx_skb);
- /* TTY ldisc cleanup */
- tty_unregister_ldisc(&st_ldisc_ops);
- /* free the global data pointer */
- kfree(st_gdata);
- }
-}
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
deleted file mode 100644
index ff172cf4614d..000000000000
--- a/drivers/misc/ti-st/st_kim.c
+++ /dev/null
@@ -1,839 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Shared Transport Line discipline driver Core
- * Init Manager module responsible for GPIO control
- * and firmware download
- * Copyright (C) 2009-2010 Texas Instruments
- * Author: Pavan Savoy <pavan_savoy@ti.com>
- */
-
-#define pr_fmt(fmt) "(stk) :" fmt
-#include <linux/platform_device.h>
-#include <linux/jiffies.h>
-#include <linux/firmware.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/gpio.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/sched.h>
-#include <linux/sysfs.h>
-#include <linux/tty.h>
-
-#include <linux/skbuff.h>
-#include <linux/ti_wilink_st.h>
-#include <linux/module.h>
-
-#define MAX_ST_DEVICES 3 /* Imagine 1 on each UART for now */
-static struct platform_device *st_kim_devices[MAX_ST_DEVICES];
-
-/**********************************************************************/
-/* internal functions */
-
-/*
- * st_get_plat_device -
- * function which returns the reference to the platform device
- * requested by id. As of now only 1 such device exists (id=0)
- * the context requesting for reference can get the id to be
- * requested by a. The protocol driver which is registering or
- * b. the tty device which is opened.
- */
-static struct platform_device *st_get_plat_device(int id)
-{
- return st_kim_devices[id];
-}
-
-/*
- * validate_firmware_response -
- * function to return whether the firmware response was proper
- * in case of error don't complete so that waiting for proper
- * response times out
- */
-static void validate_firmware_response(struct kim_data_s *kim_gdata)
-{
- struct sk_buff *skb = kim_gdata->rx_skb;
- if (!skb)
- return;
-
- /*
- * these magic numbers are the position in the response buffer which
- * allows us to distinguish whether the response is for the read
- * version info. command
- */
- if (skb->data[2] == 0x01 && skb->data[3] == 0x01 &&
- skb->data[4] == 0x10 && skb->data[5] == 0x00) {
- /* fw version response */
- memcpy(kim_gdata->resp_buffer,
- kim_gdata->rx_skb->data,
- kim_gdata->rx_skb->len);
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_skb = NULL;
- kim_gdata->rx_count = 0;
- } else if (unlikely(skb->data[5] != 0)) {
- pr_err("no proper response during fw download");
- pr_err("data6 %x", skb->data[5]);
- kfree_skb(skb);
- return; /* keep waiting for the proper response */
- }
- /* becos of all the script being downloaded */
- complete_all(&kim_gdata->kim_rcvd);
- kfree_skb(skb);
-}
-
-/*
- * check for data len received inside kim_int_recv
- * most often hit the last case to update state to waiting for data
- */
-static inline int kim_check_data_len(struct kim_data_s *kim_gdata, int len)
-{
- register int room = skb_tailroom(kim_gdata->rx_skb);
-
- pr_debug("len %d room %d", len, room);
-
- if (!len) {
- validate_firmware_response(kim_gdata);
- } else if (len > room) {
- /*
- * Received packet's payload length is larger.
- * We can't accommodate it in created skb.
- */
- pr_err("Data length is too large len %d room %d", len,
- room);
- kfree_skb(kim_gdata->rx_skb);
- } else {
- /*
- * Packet header has non-zero payload length and
- * we have enough space in created skb. Lets read
- * payload data */
- kim_gdata->rx_state = ST_W4_DATA;
- kim_gdata->rx_count = len;
- return len;
- }
-
- /*
- * Change ST LL state to continue to process next
- * packet
- */
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_skb = NULL;
- kim_gdata->rx_count = 0;
-
- return 0;
-}
-
-/*
- * kim_int_recv - receive function called during firmware download
- * firmware download responses on different UART drivers
- * have been observed to come in bursts of different
- * tty_receive and hence the logic
- */
-static void kim_int_recv(struct kim_data_s *kim_gdata, const u8 *ptr,
- size_t count)
-{
- int len = 0;
- unsigned char *plen;
-
- pr_debug("%s", __func__);
- /* Decode received bytes here */
- while (count) {
- if (kim_gdata->rx_count) {
- len = min_t(unsigned int, kim_gdata->rx_count, count);
- skb_put_data(kim_gdata->rx_skb, ptr, len);
- kim_gdata->rx_count -= len;
- count -= len;
- ptr += len;
-
- if (kim_gdata->rx_count)
- continue;
-
- /* Check ST RX state machine , where are we? */
- switch (kim_gdata->rx_state) {
- /* Waiting for complete packet ? */
- case ST_W4_DATA:
- pr_debug("Complete pkt received");
- validate_firmware_response(kim_gdata);
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_skb = NULL;
- continue;
- /* Waiting for Bluetooth event header ? */
- case ST_W4_HEADER:
- plen =
- (unsigned char *)&kim_gdata->rx_skb->data[1];
- pr_debug("event hdr: plen 0x%02x\n", *plen);
- kim_check_data_len(kim_gdata, *plen);
- continue;
- } /* end of switch */
- } /* end of if rx_state */
- switch (*ptr) {
- /* Bluetooth event packet? */
- case 0x04:
- kim_gdata->rx_state = ST_W4_HEADER;
- kim_gdata->rx_count = 2;
- break;
- default:
- pr_info("unknown packet");
- ptr++;
- count--;
- continue;
- }
- ptr++;
- count--;
- kim_gdata->rx_skb =
- alloc_skb(1024+8, GFP_ATOMIC);
- if (!kim_gdata->rx_skb) {
- pr_err("can't allocate mem for new packet");
- kim_gdata->rx_state = ST_W4_PACKET_TYPE;
- kim_gdata->rx_count = 0;
- return;
- }
- skb_reserve(kim_gdata->rx_skb, 8);
- kim_gdata->rx_skb->cb[0] = 4;
- kim_gdata->rx_skb->cb[1] = 0;
-
- }
- return;
-}
-
-static long read_local_version(struct kim_data_s *kim_gdata, char *bts_scr_name)
-{
- unsigned short version = 0, chip = 0, min_ver = 0, maj_ver = 0;
- static const char read_ver_cmd[] = { 0x01, 0x01, 0x10, 0x00 };
- long time_left;
-
- pr_debug("%s", __func__);
-
- reinit_completion(&kim_gdata->kim_rcvd);
- if (4 != st_int_write(kim_gdata->core_data, read_ver_cmd, 4)) {
- pr_err("kim: couldn't write 4 bytes");
- return -EIO;
- }
-
- time_left = wait_for_completion_interruptible_timeout(
- &kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME));
- if (time_left <= 0) {
- pr_err(" waiting for ver info- timed out or received signal");
- return time_left ? -ERESTARTSYS : -ETIMEDOUT;
- }
- reinit_completion(&kim_gdata->kim_rcvd);
- /*
- * the positions 12 & 13 in the response buffer provide with the
- * chip, major & minor numbers
- */
-
- version =
- MAKEWORD(kim_gdata->resp_buffer[12],
- kim_gdata->resp_buffer[13]);
- chip = (version & 0x7C00) >> 10;
- min_ver = (version & 0x007F);
- maj_ver = (version & 0x0380) >> 7;
-
- if (version & 0x8000)
- maj_ver |= 0x0008;
-
- sprintf(bts_scr_name, "ti-connectivity/TIInit_%d.%d.%d.bts",
- chip, maj_ver, min_ver);
-
- /* to be accessed later via sysfs entry */
- kim_gdata->version.full = version;
- kim_gdata->version.chip = chip;
- kim_gdata->version.maj_ver = maj_ver;
- kim_gdata->version.min_ver = min_ver;
-
- pr_info("%s", bts_scr_name);
- return 0;
-}
-
-static void skip_change_remote_baud(unsigned char **ptr, long *len)
-{
- unsigned char *nxt_action, *cur_action;
- cur_action = *ptr;
-
- nxt_action = cur_action + sizeof(struct bts_action) +
- ((struct bts_action *) cur_action)->size;
-
- if (((struct bts_action *) nxt_action)->type != ACTION_WAIT_EVENT) {
- pr_err("invalid action after change remote baud command");
- } else {
- *ptr = *ptr + sizeof(struct bts_action) +
- ((struct bts_action *)cur_action)->size;
- *len = *len - (sizeof(struct bts_action) +
- ((struct bts_action *)cur_action)->size);
- /* warn user on not commenting these in firmware */
- pr_warn("skipping the wait event of change remote baud");
- }
-}
-
-/*
- * download_firmware -
- * internal function which parses through the .bts firmware
- * script file intreprets SEND, DELAY actions only as of now
- */
-static long download_firmware(struct kim_data_s *kim_gdata)
-{
- long err = 0;
- long len = 0;
- unsigned char *ptr = NULL;
- unsigned char *action_ptr = NULL;
- unsigned char bts_scr_name[40] = { 0 }; /* 40 char long bts scr name? */
- int wr_room_space;
- int cmd_size;
- unsigned long timeout;
-
- err = read_local_version(kim_gdata, bts_scr_name);
- if (err != 0) {
- pr_err("kim: failed to read local ver");
- return err;
- }
- err =
- request_firmware(&kim_gdata->fw_entry, bts_scr_name,
- &kim_gdata->kim_pdev->dev);
- if (unlikely((err != 0) || (kim_gdata->fw_entry->data == NULL) ||
- (kim_gdata->fw_entry->size == 0))) {
- pr_err(" request_firmware failed(errno %ld) for %s", err,
- bts_scr_name);
- return -EINVAL;
- }
- ptr = (void *)kim_gdata->fw_entry->data;
- len = kim_gdata->fw_entry->size;
- /*
- * bts_header to remove out magic number and
- * version
- */
- ptr += sizeof(struct bts_header);
- len -= sizeof(struct bts_header);
-
- while (len > 0 && ptr) {
- pr_debug(" action size %d, type %d ",
- ((struct bts_action *)ptr)->size,
- ((struct bts_action *)ptr)->type);
-
- switch (((struct bts_action *)ptr)->type) {
- case ACTION_SEND_COMMAND: /* action send */
- pr_debug("S");
- action_ptr = &(((struct bts_action *)ptr)->data[0]);
- if (unlikely
- (((struct hci_command *)action_ptr)->opcode ==
- 0xFF36)) {
- /*
- * ignore remote change
- * baud rate HCI VS command
- */
- pr_warn("change remote baud"
- " rate command in firmware");
- skip_change_remote_baud(&ptr, &len);
- break;
- }
- /*
- * Make sure we have enough free space in uart
- * tx buffer to write current firmware command
- */
- cmd_size = ((struct bts_action *)ptr)->size;
- timeout = jiffies + msecs_to_jiffies(CMD_WR_TIME);
- do {
- wr_room_space =
- st_get_uart_wr_room(kim_gdata->core_data);
- if (wr_room_space < 0) {
- pr_err("Unable to get free "
- "space info from uart tx buffer");
- release_firmware(kim_gdata->fw_entry);
- return wr_room_space;
- }
- mdelay(1); /* wait 1ms before checking room */
- } while ((wr_room_space < cmd_size) &&
- time_before(jiffies, timeout));
-
- /* Timeout happened ? */
- if (time_after_eq(jiffies, timeout)) {
- pr_err("Timeout while waiting for free "
- "free space in uart tx buffer");
- release_firmware(kim_gdata->fw_entry);
- return -ETIMEDOUT;
- }
- /*
- * reinit completion before sending for the
- * relevant wait
- */
- reinit_completion(&kim_gdata->kim_rcvd);
-
- /*
- * Free space found in uart buffer, call st_int_write
- * to send current firmware command to the uart tx
- * buffer.
- */
- err = st_int_write(kim_gdata->core_data,
- ((struct bts_action_send *)action_ptr)->data,
- ((struct bts_action *)ptr)->size);
- if (unlikely(err < 0)) {
- release_firmware(kim_gdata->fw_entry);
- return err;
- }
- /*
- * Check number of bytes written to the uart tx buffer
- * and requested command write size
- */
- if (err != cmd_size) {
- pr_err("Number of bytes written to uart "
- "tx buffer are not matching with "
- "requested cmd write size");
- release_firmware(kim_gdata->fw_entry);
- return -EIO;
- }
- break;
- case ACTION_WAIT_EVENT: /* wait */
- pr_debug("W");
- err = wait_for_completion_interruptible_timeout(
- &kim_gdata->kim_rcvd,
- msecs_to_jiffies(CMD_RESP_TIME));
- if (err <= 0) {
- pr_err("response timeout/signaled during fw download ");
- /* timed out */
- release_firmware(kim_gdata->fw_entry);
- return err ? -ERESTARTSYS : -ETIMEDOUT;
- }
- reinit_completion(&kim_gdata->kim_rcvd);
- break;
- case ACTION_DELAY: /* sleep */
- pr_info("sleep command in scr");
- action_ptr = &(((struct bts_action *)ptr)->data[0]);
- mdelay(((struct bts_action_delay *)action_ptr)->msec);
- break;
- }
- len =
- len - (sizeof(struct bts_action) +
- ((struct bts_action *)ptr)->size);
- ptr =
- ptr + sizeof(struct bts_action) +
- ((struct bts_action *)ptr)->size;
- }
- /* fw download complete */
- release_firmware(kim_gdata->fw_entry);
- return 0;
-}
-
-/**********************************************************************/
-/* functions called from ST core */
-/* called from ST Core, when REG_IN_PROGRESS (registration in progress)
- * can be because of
- * 1. response to read local version
- * 2. during send/recv's of firmware download
- */
-void st_kim_recv(void *disc_data, const u8 *data, size_t count)
-{
- struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
- struct kim_data_s *kim_gdata = st_gdata->kim_data;
-
- /*
- * proceed to gather all data and distinguish read fw version response
- * from other fw responses when data gathering is complete
- */
- kim_int_recv(kim_gdata, data, count);
- return;
-}
-
-/*
- * to signal completion of line discipline installation
- * called from ST Core, upon tty_open
- */
-void st_kim_complete(void *kim_data)
-{
- struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
- complete(&kim_gdata->ldisc_installed);
-}
-
-/*
- * st_kim_start - called from ST Core upon 1st registration
- * This involves toggling the chip enable gpio, reading
- * the firmware version from chip, forming the fw file name
- * based on the chip version, requesting the fw, parsing it
- * and perform download(send/recv).
- */
-long st_kim_start(void *kim_data)
-{
- long err = 0;
- long retry = POR_RETRY_COUNT;
- struct ti_st_plat_data *pdata;
- struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
-
- pr_info(" %s", __func__);
- pdata = kim_gdata->kim_pdev->dev.platform_data;
-
- do {
- /* platform specific enabling code here */
- if (pdata->chip_enable)
- pdata->chip_enable(kim_gdata);
-
- /* Configure BT nShutdown to HIGH state */
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
- mdelay(5); /* FIXME: a proper toggle */
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH);
- mdelay(100);
- /* re-initialize the completion */
- reinit_completion(&kim_gdata->ldisc_installed);
- /* send notification to UIM */
- kim_gdata->ldisc_install = 1;
- pr_info("ldisc_install = 1");
- sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
- NULL, "install");
- /* wait for ldisc to be installed */
- err = wait_for_completion_interruptible_timeout(
- &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
- if (!err) {
- /*
- * ldisc installation timeout,
- * flush uart, power cycle BT_EN
- */
- pr_err("ldisc installation timeout");
- err = st_kim_stop(kim_gdata);
- continue;
- } else {
- /* ldisc installed now */
- pr_info("line discipline installed");
- err = download_firmware(kim_gdata);
- if (err != 0) {
- /*
- * ldisc installed but fw download failed,
- * flush uart & power cycle BT_EN
- */
- pr_err("download firmware failed");
- err = st_kim_stop(kim_gdata);
- continue;
- } else { /* on success don't retry */
- break;
- }
- }
- } while (retry--);
- return err;
-}
-
-/*
- * st_kim_stop - stop communication with chip.
- * This can be called from ST Core/KIM, on the-
- * (a) last un-register when chip need not be powered there-after,
- * (b) upon failure to either install ldisc or download firmware.
- * The function is responsible to (a) notify UIM about un-installation,
- * (b) flush UART if the ldisc was installed.
- * (c) reset BT_EN - pull down nshutdown at the end.
- * (d) invoke platform's chip disabling routine.
- */
-long st_kim_stop(void *kim_data)
-{
- long err = 0;
- struct kim_data_s *kim_gdata = (struct kim_data_s *)kim_data;
- struct ti_st_plat_data *pdata =
- kim_gdata->kim_pdev->dev.platform_data;
- struct tty_struct *tty = kim_gdata->core_data->tty;
-
- reinit_completion(&kim_gdata->ldisc_installed);
-
- if (tty) { /* can be called before ldisc is installed */
- /* Flush any pending characters in the driver and discipline. */
- tty_ldisc_flush(tty);
- tty_driver_flush_buffer(tty);
- }
-
- /* send uninstall notification to UIM */
- pr_info("ldisc_install = 0");
- kim_gdata->ldisc_install = 0;
- sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
-
- /* wait for ldisc to be un-installed */
- err = wait_for_completion_interruptible_timeout(
- &kim_gdata->ldisc_installed, msecs_to_jiffies(LDISC_TIME));
- if (!err) { /* timeout */
- pr_err(" timed out waiting for ldisc to be un-installed");
- err = -ETIMEDOUT;
- }
-
- /* By default configure BT nShutdown to LOW state */
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
- mdelay(1);
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_HIGH);
- mdelay(1);
- gpio_set_value_cansleep(kim_gdata->nshutdown, GPIO_LOW);
-
- /* platform specific disable */
- if (pdata->chip_disable)
- pdata->chip_disable(kim_gdata);
- return err;
-}
-
-/**********************************************************************/
-/* functions called from subsystems */
-/* called when debugfs entry is read from */
-
-static int version_show(struct seq_file *s, void *unused)
-{
- struct kim_data_s *kim_gdata = s->private;
- seq_printf(s, "%04X %d.%d.%d\n", kim_gdata->version.full,
- kim_gdata->version.chip, kim_gdata->version.maj_ver,
- kim_gdata->version.min_ver);
- return 0;
-}
-
-static int list_show(struct seq_file *s, void *unused)
-{
- struct kim_data_s *kim_gdata = s->private;
- kim_st_list_protocols(kim_gdata->core_data, s);
- return 0;
-}
-
-static ssize_t show_install(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", kim_data->ldisc_install);
-}
-
-#ifdef DEBUG
-static ssize_t store_dev_name(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- pr_debug("storing dev name >%s<", buf);
- strscpy(kim_data->dev_name, buf, sizeof(kim_data->dev_name));
- pr_debug("stored dev name >%s<", kim_data->dev_name);
- return count;
-}
-
-static ssize_t store_baud_rate(struct device *dev,
- struct device_attribute *attr, const char *buf, size_t count)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- pr_debug("storing baud rate >%s<", buf);
- sscanf(buf, "%ld", &kim_data->baud_rate);
- pr_debug("stored baud rate >%ld<", kim_data->baud_rate);
- return count;
-}
-#endif /* if DEBUG */
-
-static ssize_t show_dev_name(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%s\n", kim_data->dev_name);
-}
-
-static ssize_t show_baud_rate(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", kim_data->baud_rate);
-}
-
-static ssize_t show_flow_cntrl(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct kim_data_s *kim_data = dev_get_drvdata(dev);
- return sprintf(buf, "%d\n", kim_data->flow_cntrl);
-}
-
-/* structures specific for sysfs entries */
-static struct kobj_attribute ldisc_install =
-__ATTR(install, 0444, (void *)show_install, NULL);
-
-static struct kobj_attribute uart_dev_name =
-#ifdef DEBUG /* TODO: move this to debug-fs if possible */
-__ATTR(dev_name, 0644, (void *)show_dev_name, (void *)store_dev_name);
-#else
-__ATTR(dev_name, 0444, (void *)show_dev_name, NULL);
-#endif
-
-static struct kobj_attribute uart_baud_rate =
-#ifdef DEBUG /* TODO: move to debugfs */
-__ATTR(baud_rate, 0644, (void *)show_baud_rate, (void *)store_baud_rate);
-#else
-__ATTR(baud_rate, 0444, (void *)show_baud_rate, NULL);
-#endif
-
-static struct kobj_attribute uart_flow_cntrl =
-__ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL);
-
-static struct attribute *uim_attrs[] = {
- &ldisc_install.attr,
- &uart_dev_name.attr,
- &uart_baud_rate.attr,
- &uart_flow_cntrl.attr,
- NULL,
-};
-
-static const struct attribute_group uim_attr_grp = {
- .attrs = uim_attrs,
-};
-
-/*
- * st_kim_ref - reference the core's data
- * This references the per-ST platform device in the arch/xx/
- * board-xx.c file.
- * This would enable multiple such platform devices to exist
- * on a given platform
- */
-void st_kim_ref(struct st_data_s **core_data, int id)
-{
- struct platform_device *pdev;
- struct kim_data_s *kim_gdata;
- /* get kim_gdata reference from platform device */
- pdev = st_get_plat_device(id);
- if (!pdev)
- goto err;
- kim_gdata = platform_get_drvdata(pdev);
- if (!kim_gdata)
- goto err;
-
- *core_data = kim_gdata->core_data;
- return;
-err:
- *core_data = NULL;
-}
-
-DEFINE_SHOW_ATTRIBUTE(version);
-DEFINE_SHOW_ATTRIBUTE(list);
-
-/**********************************************************************/
-/* functions called from platform device driver subsystem
- * need to have a relevant platform device entry in the platform's
- * board-*.c file
- */
-
-static struct dentry *kim_debugfs_dir;
-static int kim_probe(struct platform_device *pdev)
-{
- struct kim_data_s *kim_gdata;
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
- int err;
-
- if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
- /* multiple devices could exist */
- st_kim_devices[pdev->id] = pdev;
- } else {
- /* platform's sure about existence of 1 device */
- st_kim_devices[0] = pdev;
- }
-
- kim_gdata = kzalloc(sizeof(struct kim_data_s), GFP_KERNEL);
- if (!kim_gdata) {
- pr_err("no mem to allocate");
- return -ENOMEM;
- }
- platform_set_drvdata(pdev, kim_gdata);
-
- err = st_core_init(&kim_gdata->core_data);
- if (err != 0) {
- pr_err(" ST core init failed");
- err = -EIO;
- goto err_core_init;
- }
- /* refer to itself */
- kim_gdata->core_data->kim_data = kim_gdata;
-
- /* Claim the chip enable nShutdown gpio from the system */
- kim_gdata->nshutdown = pdata->nshutdown_gpio;
- err = gpio_request(kim_gdata->nshutdown, "kim");
- if (unlikely(err)) {
- pr_err(" gpio %d request failed ", kim_gdata->nshutdown);
- goto err_sysfs_group;
- }
-
- /* Configure nShutdown GPIO as output=0 */
- err = gpio_direction_output(kim_gdata->nshutdown, 0);
- if (unlikely(err)) {
- pr_err(" unable to configure gpio %d", kim_gdata->nshutdown);
- goto err_sysfs_group;
- }
- /* get reference of pdev for request_firmware */
- kim_gdata->kim_pdev = pdev;
- init_completion(&kim_gdata->kim_rcvd);
- init_completion(&kim_gdata->ldisc_installed);
-
- err = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
- if (err) {
- pr_err("failed to create sysfs entries");
- goto err_sysfs_group;
- }
-
- /* copying platform data */
- strscpy(kim_gdata->dev_name, pdata->dev_name,
- sizeof(kim_gdata->dev_name));
- kim_gdata->flow_cntrl = pdata->flow_cntrl;
- kim_gdata->baud_rate = pdata->baud_rate;
- pr_info("sysfs entries created\n");
-
- kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
-
- debugfs_create_file("version", S_IRUGO, kim_debugfs_dir,
- kim_gdata, &version_fops);
- debugfs_create_file("protocols", S_IRUGO, kim_debugfs_dir,
- kim_gdata, &list_fops);
- return 0;
-
-err_sysfs_group:
- st_core_exit(kim_gdata->core_data);
-
-err_core_init:
- kfree(kim_gdata);
-
- return err;
-}
-
-static void kim_remove(struct platform_device *pdev)
-{
- /* free the GPIOs requested */
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
- struct kim_data_s *kim_gdata;
-
- kim_gdata = platform_get_drvdata(pdev);
-
- /*
- * Free the Bluetooth/FM/GPIO
- * nShutdown gpio from the system
- */
- gpio_free(pdata->nshutdown_gpio);
- pr_info("nshutdown GPIO Freed");
-
- debugfs_remove_recursive(kim_debugfs_dir);
- sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
- pr_info("sysfs entries removed");
-
- kim_gdata->kim_pdev = NULL;
- st_core_exit(kim_gdata->core_data);
-
- kfree(kim_gdata);
- kim_gdata = NULL;
-}
-
-static int kim_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
-
- if (pdata->suspend)
- return pdata->suspend(pdev, state);
-
- return 0;
-}
-
-static int kim_resume(struct platform_device *pdev)
-{
- struct ti_st_plat_data *pdata = pdev->dev.platform_data;
-
- if (pdata->resume)
- return pdata->resume(pdev);
-
- return 0;
-}
-
-/**********************************************************************/
-/* entry point for ST KIM module, called in from ST Core */
-static struct platform_driver kim_platform_driver = {
- .probe = kim_probe,
- .remove_new = kim_remove,
- .suspend = kim_suspend,
- .resume = kim_resume,
- .driver = {
- .name = "kim",
- },
-};
-
-module_platform_driver(kim_platform_driver);
-
-MODULE_AUTHOR("Pavan Savoy <pavan_savoy@ti.com>");
-MODULE_DESCRIPTION("Shared Transport Driver for TI BT/FM/GPS combo chips ");
-MODULE_LICENSE("GPL");
diff --git a/drivers/misc/ti-st/st_ll.c b/drivers/misc/ti-st/st_ll.c
deleted file mode 100644
index 07406140d277..000000000000
--- a/drivers/misc/ti-st/st_ll.c
+++ /dev/null
@@ -1,156 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-only
-/*
- * Shared Transport driver
- * HCI-LL module responsible for TI proprietary HCI_LL protocol
- * Copyright (C) 2009-2010 Texas Instruments
- * Author: Pavan Savoy <pavan_savoy@ti.com>
- */
-
-#define pr_fmt(fmt) "(stll) :" fmt
-#include <linux/skbuff.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/ti_wilink_st.h>
-
-/**********************************************************************/
-/* internal functions */
-static void send_ll_cmd(struct st_data_s *st_data,
- unsigned char cmd)
-{
-
- pr_debug("%s: writing %x", __func__, cmd);
- st_int_write(st_data, &cmd, 1);
- return;
-}
-
-static void ll_device_want_to_sleep(struct st_data_s *st_data)
-{
- struct kim_data_s *kim_data;
- struct ti_st_plat_data *pdata;
-
- pr_debug("%s", __func__);
- /* sanity check */
- if (st_data->ll_state != ST_LL_AWAKE)
- pr_err("ERR hcill: ST_LL_GO_TO_SLEEP_IND"
- "in state %ld", st_data->ll_state);
-
- send_ll_cmd(st_data, LL_SLEEP_ACK);
- /* update state */
- st_data->ll_state = ST_LL_ASLEEP;
-
- /* communicate to platform about chip asleep */
- kim_data = st_data->kim_data;
- pdata = kim_data->kim_pdev->dev.platform_data;
- if (pdata->chip_asleep)
- pdata->chip_asleep(NULL);
-}
-
-static void ll_device_want_to_wakeup(struct st_data_s *st_data)
-{
- struct kim_data_s *kim_data;
- struct ti_st_plat_data *pdata;
-
- /* diff actions in diff states */
- switch (st_data->ll_state) {
- case ST_LL_ASLEEP:
- send_ll_cmd(st_data, LL_WAKE_UP_ACK); /* send wake_ack */
- break;
- case ST_LL_ASLEEP_TO_AWAKE:
- /* duplicate wake_ind */
- pr_err("duplicate wake_ind while waiting for Wake ack");
- break;
- case ST_LL_AWAKE:
- /* duplicate wake_ind */
- pr_err("duplicate wake_ind already AWAKE");
- break;
- case ST_LL_AWAKE_TO_ASLEEP:
- /* duplicate wake_ind */
- pr_err("duplicate wake_ind");
- break;
- }
- /* update state */
- st_data->ll_state = ST_LL_AWAKE;
-
- /* communicate to platform about chip wakeup */
- kim_data = st_data->kim_data;
- pdata = kim_data->kim_pdev->dev.platform_data;
- if (pdata->chip_awake)
- pdata->chip_awake(NULL);
-}
-
-/**********************************************************************/
-/* functions invoked by ST Core */
-
-/* called when ST Core wants to
- * enable ST LL */
-void st_ll_enable(struct st_data_s *ll)
-{
- ll->ll_state = ST_LL_AWAKE;
-}
-
-/* called when ST Core /local module wants to
- * disable ST LL */
-void st_ll_disable(struct st_data_s *ll)
-{
- ll->ll_state = ST_LL_INVALID;
-}
-
-/* called when ST Core wants to update the state */
-void st_ll_wakeup(struct st_data_s *ll)
-{
- if (likely(ll->ll_state != ST_LL_AWAKE)) {
- send_ll_cmd(ll, LL_WAKE_UP_IND); /* WAKE_IND */
- ll->ll_state = ST_LL_ASLEEP_TO_AWAKE;
- } else {
- /* don't send the duplicate wake_indication */
- pr_err(" Chip already AWAKE ");
- }
-}
-
-/* called when ST Core wants the state */
-unsigned long st_ll_getstate(struct st_data_s *ll)
-{
- pr_debug(" returning state %ld", ll->ll_state);
- return ll->ll_state;
-}
-
-/* called from ST Core, when a PM related packet arrives */
-unsigned long st_ll_sleep_state(struct st_data_s *st_data,
- unsigned char cmd)
-{
- switch (cmd) {
- case LL_SLEEP_IND: /* sleep ind */
- pr_debug("sleep indication recvd");
- ll_device_want_to_sleep(st_data);
- break;
- case LL_SLEEP_ACK: /* sleep ack */
- pr_err("sleep ack rcvd: host shouldn't");
- break;
- case LL_WAKE_UP_IND: /* wake ind */
- pr_debug("wake indication recvd");
- ll_device_want_to_wakeup(st_data);
- break;
- case LL_WAKE_UP_ACK: /* wake ack */
- pr_debug("wake ack rcvd");
- st_data->ll_state = ST_LL_AWAKE;
- break;
- default:
- pr_err(" unknown input/state ");
- return -EINVAL;
- }
- return 0;
-}
-
-/* Called from ST CORE to initialize ST LL */
-long st_ll_init(struct st_data_s *ll)
-{
- /* set state to invalid */
- ll->ll_state = ST_LL_INVALID;
- return 0;
-}
-
-/* Called from ST CORE to de-initialize ST LL */
-long st_ll_deinit(struct st_data_s *ll)
-{
- return 0;
-}
diff --git a/drivers/misc/tps6594-esm.c b/drivers/misc/tps6594-esm.c
index b4d67a1a24e4..2fbd3fbdf713 100644
--- a/drivers/misc/tps6594-esm.c
+++ b/drivers/misc/tps6594-esm.c
@@ -135,7 +135,7 @@ static struct platform_driver tps6594_esm_driver = {
.pm = pm_sleep_ptr(&tps6594_esm_pm_ops),
},
.probe = tps6594_esm_probe,
- .remove_new = tps6594_esm_remove,
+ .remove = tps6594_esm_remove,
};
module_platform_driver(tps6594_esm_driver);
diff --git a/drivers/misc/tps6594-pfsm.c b/drivers/misc/tps6594-pfsm.c
index 9bcca1856bfe..0a24ce44cc37 100644
--- a/drivers/misc/tps6594-pfsm.c
+++ b/drivers/misc/tps6594-pfsm.c
@@ -314,7 +314,7 @@ static struct platform_driver tps6594_pfsm_driver = {
.name = "tps6594-pfsm",
},
.probe = tps6594_pfsm_probe,
- .remove_new = tps6594_pfsm_remove,
+ .remove = tps6594_pfsm_remove,
};
module_platform_driver(tps6594_pfsm_driver);
diff --git a/drivers/misc/vcpu_stall_detector.c b/drivers/misc/vcpu_stall_detector.c
index 41b8c2119e20..f0b1fc87490e 100644
--- a/drivers/misc/vcpu_stall_detector.c
+++ b/drivers/misc/vcpu_stall_detector.c
@@ -233,7 +233,7 @@ MODULE_DEVICE_TABLE(of, vcpu_stall_detect_of_match);
static struct platform_driver vcpu_stall_detect_driver = {
.probe = vcpu_stall_detect_probe,
- .remove_new = vcpu_stall_detect_remove,
+ .remove = vcpu_stall_detect_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = vcpu_stall_detect_of_match,
diff --git a/drivers/misc/xilinx_sdfec.c b/drivers/misc/xilinx_sdfec.c
index ea433695f4c4..3135ba3a58ee 100644
--- a/drivers/misc/xilinx_sdfec.c
+++ b/drivers/misc/xilinx_sdfec.c
@@ -1444,7 +1444,7 @@ static struct platform_driver xsdfec_driver = {
.of_match_table = xsdfec_of_match,
},
.probe = xsdfec_probe,
- .remove_new = xsdfec_remove,
+ .remove = xsdfec_remove,
};
module_platform_driver(xsdfec_driver);
diff --git a/drivers/misc/xilinx_tmr_inject.c b/drivers/misc/xilinx_tmr_inject.c
index 734fdfac19ef..6284606ffb9f 100644
--- a/drivers/misc/xilinx_tmr_inject.c
+++ b/drivers/misc/xilinx_tmr_inject.c
@@ -164,7 +164,7 @@ static struct platform_driver xtmr_inject_driver = {
.of_match_table = xtmr_inject_of_match,
},
.probe = xtmr_inject_probe,
- .remove_new = xtmr_inject_remove,
+ .remove = xtmr_inject_remove,
};
module_platform_driver(xtmr_inject_driver);
MODULE_AUTHOR("Advanced Micro Devices, Inc");
diff --git a/drivers/mmc/core/bus.c b/drivers/mmc/core/bus.c
index 9283b28bc69f..1cf64e0952fb 100644
--- a/drivers/mmc/core/bus.c
+++ b/drivers/mmc/core/bus.c
@@ -149,6 +149,8 @@ static void mmc_bus_shutdown(struct device *dev)
if (dev->driver && drv->shutdown)
drv->shutdown(card);
+ __mmc_stop_host(host);
+
if (host->bus_ops->shutdown) {
ret = host->bus_ops->shutdown(host);
if (ret)
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index a499f3c59de5..d996d39c0d6f 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2335,6 +2335,9 @@ void mmc_start_host(struct mmc_host *host)
void __mmc_stop_host(struct mmc_host *host)
{
+ if (host->rescan_disable)
+ return;
+
if (host->slot.cd_irq >= 0) {
mmc_gpio_set_cd_wake(host, false);
disable_irq(host->slot.cd_irq);
diff --git a/drivers/mmc/host/mtk-sd.c b/drivers/mmc/host/mtk-sd.c
index efb0d2d5716b..af445d3f8e2a 100644
--- a/drivers/mmc/host/mtk-sd.c
+++ b/drivers/mmc/host/mtk-sd.c
@@ -3070,6 +3070,7 @@ release_clk:
msdc_gate_clock(host);
platform_set_drvdata(pdev, NULL);
release_mem:
+ device_init_wakeup(&pdev->dev, false);
if (host->dma.gpd)
dma_free_coherent(&pdev->dev,
2 * sizeof(struct mt_gpdma_desc),
@@ -3103,6 +3104,7 @@ static void msdc_drv_remove(struct platform_device *pdev)
host->dma.gpd, host->dma.gpd_addr);
dma_free_coherent(&pdev->dev, MAX_BD_NUM * sizeof(struct mt_bdma_desc),
host->dma.bd, host->dma.bd_addr);
+ device_init_wakeup(&pdev->dev, false);
}
static void msdc_save_reg(struct msdc_host *host)
diff --git a/drivers/mmc/host/sdhci-msm.c b/drivers/mmc/host/sdhci-msm.c
index e00208535bd1..319f0ebbe652 100644
--- a/drivers/mmc/host/sdhci-msm.c
+++ b/drivers/mmc/host/sdhci-msm.c
@@ -1867,20 +1867,20 @@ static int sdhci_msm_program_key(struct cqhci_host *cq_host,
struct sdhci_msm_host *msm_host = sdhci_pltfm_priv(pltfm_host);
union cqhci_crypto_cap_entry cap;
+ if (!(cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE))
+ return qcom_ice_evict_key(msm_host->ice, slot);
+
/* Only AES-256-XTS has been tested so far. */
cap = cq_host->crypto_cap_array[cfg->crypto_cap_idx];
if (cap.algorithm_id != CQHCI_CRYPTO_ALG_AES_XTS ||
cap.key_size != CQHCI_CRYPTO_KEY_SIZE_256)
return -EINVAL;
- if (cfg->config_enable & CQHCI_CRYPTO_CONFIGURATION_ENABLE)
- return qcom_ice_program_key(msm_host->ice,
- QCOM_ICE_CRYPTO_ALG_AES_XTS,
- QCOM_ICE_CRYPTO_KEY_SIZE_256,
- cfg->crypto_key,
- cfg->data_unit_size, slot);
- else
- return qcom_ice_evict_key(msm_host->ice, slot);
+ return qcom_ice_program_key(msm_host->ice,
+ QCOM_ICE_CRYPTO_ALG_AES_XTS,
+ QCOM_ICE_CRYPTO_KEY_SIZE_256,
+ cfg->crypto_key,
+ cfg->data_unit_size, slot);
}
#else /* CONFIG_MMC_CRYPTO */
diff --git a/drivers/mmc/host/sdhci-pci-core.c b/drivers/mmc/host/sdhci-pci-core.c
index 2b300bc4a701..1f0bd723f011 100644
--- a/drivers/mmc/host/sdhci-pci-core.c
+++ b/drivers/mmc/host/sdhci-pci-core.c
@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/gpio.h>
+#include <linux/gpio/machine.h>
#include <linux/pm_runtime.h>
#include <linux/pm_qos.h>
#include <linux/debugfs.h>
@@ -1236,6 +1237,29 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sdio = {
.priv_size = sizeof(struct intel_host),
};
+/* DMI quirks for devices with missing or broken CD GPIO info */
+static const struct gpiod_lookup_table vexia_edu_atla10_cd_gpios = {
+ .dev_id = "0000:00:12.0",
+ .table = {
+ GPIO_LOOKUP("INT33FC:00", 38, "cd", GPIO_ACTIVE_HIGH),
+ { }
+ },
+};
+
+static const struct dmi_system_id sdhci_intel_byt_cd_gpio_override[] = {
+ {
+ /* Vexia Edu Atla 10 tablet 9V version */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "AMI Corporation"),
+ DMI_MATCH(DMI_BOARD_NAME, "Aptio CRB"),
+ /* Above strings are too generic, also match on BIOS date */
+ DMI_MATCH(DMI_BIOS_DATE, "08/25/2014"),
+ },
+ .driver_data = (void *)&vexia_edu_atla10_cd_gpios,
+ },
+ { }
+};
+
static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
#ifdef CONFIG_PM_SLEEP
.resume = byt_resume,
@@ -1254,6 +1278,7 @@ static const struct sdhci_pci_fixes sdhci_intel_byt_sd = {
.add_host = byt_add_host,
.remove_slot = byt_remove_slot,
.ops = &sdhci_intel_byt_ops,
+ .cd_gpio_override = sdhci_intel_byt_cd_gpio_override,
.priv_size = sizeof(struct intel_host),
};
@@ -2055,6 +2080,42 @@ static const struct dev_pm_ops sdhci_pci_pm_ops = {
* *
\*****************************************************************************/
+static struct gpiod_lookup_table *sdhci_pci_add_gpio_lookup_table(
+ struct sdhci_pci_chip *chip)
+{
+ struct gpiod_lookup_table *cd_gpio_lookup_table;
+ const struct dmi_system_id *dmi_id = NULL;
+ size_t count;
+
+ if (chip->fixes && chip->fixes->cd_gpio_override)
+ dmi_id = dmi_first_match(chip->fixes->cd_gpio_override);
+
+ if (!dmi_id)
+ return NULL;
+
+ cd_gpio_lookup_table = dmi_id->driver_data;
+ for (count = 0; cd_gpio_lookup_table->table[count].key; count++)
+ ;
+
+ cd_gpio_lookup_table = kmemdup(dmi_id->driver_data,
+ /* count + 1 terminating entry */
+ struct_size(cd_gpio_lookup_table, table, count + 1),
+ GFP_KERNEL);
+ if (!cd_gpio_lookup_table)
+ return ERR_PTR(-ENOMEM);
+
+ gpiod_add_lookup_table(cd_gpio_lookup_table);
+ return cd_gpio_lookup_table;
+}
+
+static void sdhci_pci_remove_gpio_lookup_table(struct gpiod_lookup_table *lookup_table)
+{
+ if (lookup_table) {
+ gpiod_remove_lookup_table(lookup_table);
+ kfree(lookup_table);
+ }
+}
+
static struct sdhci_pci_slot *sdhci_pci_probe_slot(
struct pci_dev *pdev, struct sdhci_pci_chip *chip, int first_bar,
int slotno)
@@ -2130,8 +2191,19 @@ static struct sdhci_pci_slot *sdhci_pci_probe_slot(
device_init_wakeup(&pdev->dev, true);
if (slot->cd_idx >= 0) {
+ struct gpiod_lookup_table *cd_gpio_lookup_table;
+
+ cd_gpio_lookup_table = sdhci_pci_add_gpio_lookup_table(chip);
+ if (IS_ERR(cd_gpio_lookup_table)) {
+ ret = PTR_ERR(cd_gpio_lookup_table);
+ goto remove;
+ }
+
ret = mmc_gpiod_request_cd(host->mmc, "cd", slot->cd_idx,
slot->cd_override_level, 0);
+
+ sdhci_pci_remove_gpio_lookup_table(cd_gpio_lookup_table);
+
if (ret && ret != -EPROBE_DEFER)
ret = mmc_gpiod_request_cd(host->mmc, NULL,
slot->cd_idx,
diff --git a/drivers/mmc/host/sdhci-pci.h b/drivers/mmc/host/sdhci-pci.h
index e807c039a8b1..f38f0bd4165c 100644
--- a/drivers/mmc/host/sdhci-pci.h
+++ b/drivers/mmc/host/sdhci-pci.h
@@ -157,6 +157,7 @@ struct sdhci_pci_fixes {
#endif
const struct sdhci_ops *ops;
+ const struct dmi_system_id *cd_gpio_override;
size_t priv_size;
};
diff --git a/drivers/mmc/host/sdhci-tegra.c b/drivers/mmc/host/sdhci-tegra.c
index 4d402b601883..b2f5c3f8b839 100644
--- a/drivers/mmc/host/sdhci-tegra.c
+++ b/drivers/mmc/host/sdhci-tegra.c
@@ -1525,7 +1525,6 @@ static const struct sdhci_pltfm_data sdhci_tegra186_pdata = {
.quirks = SDHCI_QUIRK_BROKEN_TIMEOUT_VAL |
SDHCI_QUIRK_SINGLE_POWER_WRITE |
SDHCI_QUIRK_NO_HISPD_BIT |
- SDHCI_QUIRK_BROKEN_ADMA_ZEROLEN_DESC |
SDHCI_QUIRK_CAP_CLOCK_BASE_BROKEN,
.quirks2 = SDHCI_QUIRK2_PRESET_VALUE_BROKEN |
SDHCI_QUIRK2_ISSUE_CMD_DAT_RESET_TOGETHER,
diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
index db42aa0c7b6b..865754737f5f 100644
--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
+++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
@@ -1409,8 +1409,8 @@ static int anfc_parse_cs(struct arasan_nfc *nfc)
* case, the "not" chosen CS is assigned to nfc->spare_cs and selected
* whenever a GPIO CS must be asserted.
*/
- if (nfc->cs_array && nfc->ncs > 2) {
- if (!nfc->cs_array[0] && !nfc->cs_array[1]) {
+ if (nfc->cs_array) {
+ if (nfc->ncs > 2 && !nfc->cs_array[0] && !nfc->cs_array[1]) {
dev_err(nfc->dev,
"Assign a single native CS when using GPIOs\n");
return -EINVAL;
@@ -1478,8 +1478,15 @@ static int anfc_probe(struct platform_device *pdev)
static void anfc_remove(struct platform_device *pdev)
{
+ int i;
struct arasan_nfc *nfc = platform_get_drvdata(pdev);
+ for (i = 0; i < nfc->ncs; i++) {
+ if (nfc->cs_array[i]) {
+ gpiod_put(nfc->cs_array[i]);
+ }
+ }
+
anfc_chips_cleanup(nfc);
}
diff --git a/drivers/mtd/nand/raw/atmel/pmecc.c b/drivers/mtd/nand/raw/atmel/pmecc.c
index a22aab4ed4e8..3c7dee1be21d 100644
--- a/drivers/mtd/nand/raw/atmel/pmecc.c
+++ b/drivers/mtd/nand/raw/atmel/pmecc.c
@@ -380,10 +380,8 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
user->delta = user->dmu + req->ecc.strength + 1;
gf_tables = atmel_pmecc_get_gf_tables(req);
- if (IS_ERR(gf_tables)) {
- kfree(user);
+ if (IS_ERR(gf_tables))
return ERR_CAST(gf_tables);
- }
user->gf_tables = gf_tables;
diff --git a/drivers/mtd/nand/raw/diskonchip.c b/drivers/mtd/nand/raw/diskonchip.c
index 8db7fc424571..70d6c2250f32 100644
--- a/drivers/mtd/nand/raw/diskonchip.c
+++ b/drivers/mtd/nand/raw/diskonchip.c
@@ -1098,7 +1098,7 @@ static inline int __init inftl_partscan(struct mtd_info *mtd, struct mtd_partiti
(i == 0) && (ip->firstUnit > 0)) {
parts[0].name = " DiskOnChip IPL / Media Header partition";
parts[0].offset = 0;
- parts[0].size = mtd->erasesize * ip->firstUnit;
+ parts[0].size = (uint64_t)mtd->erasesize * ip->firstUnit;
numparts = 1;
}
diff --git a/drivers/mtd/nand/raw/omap2.c b/drivers/mtd/nand/raw/omap2.c
index d9141f3c0dd1..b8af3a3533fc 100644
--- a/drivers/mtd/nand/raw/omap2.c
+++ b/drivers/mtd/nand/raw/omap2.c
@@ -254,6 +254,10 @@ static int omap_prefetch_reset(int cs, struct omap_nand_info *info)
/**
* omap_nand_data_in_pref - NAND data in using prefetch engine
+ * @chip: NAND chip
+ * @buf: output buffer where NAND data is placed into
+ * @len: length of transfer
+ * @force_8bit: force 8-bit transfers
*/
static void omap_nand_data_in_pref(struct nand_chip *chip, void *buf,
unsigned int len, bool force_8bit)
@@ -297,6 +301,10 @@ static void omap_nand_data_in_pref(struct nand_chip *chip, void *buf,
/**
* omap_nand_data_out_pref - NAND data out using Write Posting engine
+ * @chip: NAND chip
+ * @buf: input buffer that is sent to NAND
+ * @len: length of transfer
+ * @force_8bit: force 8-bit transfers
*/
static void omap_nand_data_out_pref(struct nand_chip *chip,
const void *buf, unsigned int len,
@@ -440,6 +448,10 @@ out_copy:
/**
* omap_nand_data_in_dma_pref - NAND data in using DMA and Prefetch
+ * @chip: NAND chip
+ * @buf: output buffer where NAND data is placed into
+ * @len: length of transfer
+ * @force_8bit: force 8-bit transfers
*/
static void omap_nand_data_in_dma_pref(struct nand_chip *chip, void *buf,
unsigned int len, bool force_8bit)
@@ -460,6 +472,10 @@ static void omap_nand_data_in_dma_pref(struct nand_chip *chip, void *buf,
/**
* omap_nand_data_out_dma_pref - NAND data out using DMA and write posting
+ * @chip: NAND chip
+ * @buf: input buffer that is sent to NAND
+ * @len: length of transfer
+ * @force_8bit: force 8-bit transfers
*/
static void omap_nand_data_out_dma_pref(struct nand_chip *chip,
const void *buf, unsigned int len,
diff --git a/drivers/mtd/spi-nor/sysfs.c b/drivers/mtd/spi-nor/sysfs.c
index 96064e4babf0..5e9eb268073d 100644
--- a/drivers/mtd/spi-nor/sysfs.c
+++ b/drivers/mtd/spi-nor/sysfs.c
@@ -87,7 +87,7 @@ static umode_t spi_nor_sysfs_is_visible(struct kobject *kobj,
}
static umode_t spi_nor_sysfs_is_bin_visible(struct kobject *kobj,
- struct bin_attribute *attr, int n)
+ const struct bin_attribute *attr, int n)
{
struct spi_device *spi = to_spi_device(kobj_to_dev(kobj));
struct spi_mem *spimem = spi_get_drvdata(spi);
diff --git a/drivers/mtd/ubi/attach.c b/drivers/mtd/ubi/attach.c
index ae5abe492b52..adc47b87b38a 100644
--- a/drivers/mtd/ubi/attach.c
+++ b/drivers/mtd/ubi/attach.c
@@ -1447,7 +1447,7 @@ out_ech:
return err;
}
-static struct ubi_attach_info *alloc_ai(void)
+static struct ubi_attach_info *alloc_ai(const char *slab_name)
{
struct ubi_attach_info *ai;
@@ -1461,7 +1461,7 @@ static struct ubi_attach_info *alloc_ai(void)
INIT_LIST_HEAD(&ai->alien);
INIT_LIST_HEAD(&ai->fastmap);
ai->volumes = RB_ROOT;
- ai->aeb_slab_cache = kmem_cache_create("ubi_aeb_slab_cache",
+ ai->aeb_slab_cache = kmem_cache_create(slab_name,
sizeof(struct ubi_ainf_peb),
0, 0, NULL);
if (!ai->aeb_slab_cache) {
@@ -1491,7 +1491,7 @@ static int scan_fast(struct ubi_device *ubi, struct ubi_attach_info **ai)
err = -ENOMEM;
- scan_ai = alloc_ai();
+ scan_ai = alloc_ai("ubi_aeb_slab_cache_fastmap");
if (!scan_ai)
goto out;
@@ -1557,7 +1557,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
int err;
struct ubi_attach_info *ai;
- ai = alloc_ai();
+ ai = alloc_ai("ubi_aeb_slab_cache");
if (!ai)
return -ENOMEM;
@@ -1575,7 +1575,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
if (err > 0 || mtd_is_eccerr(err)) {
if (err != UBI_NO_FASTMAP) {
destroy_ai(ai);
- ai = alloc_ai();
+ ai = alloc_ai("ubi_aeb_slab_cache");
if (!ai)
return -ENOMEM;
@@ -1614,7 +1614,7 @@ int ubi_attach(struct ubi_device *ubi, int force_scan)
if (ubi->fm && ubi_dbg_chk_fastmap(ubi)) {
struct ubi_attach_info *scan_ai;
- scan_ai = alloc_ai();
+ scan_ai = alloc_ai("ubi_aeb_slab_cache_dbg_chk_fastmap");
if (!scan_ai) {
err = -ENOMEM;
goto out_wl;
diff --git a/drivers/mtd/ubi/fastmap-wl.c b/drivers/mtd/ubi/fastmap-wl.c
index 2a9cc9413c42..9bdb6525f128 100644
--- a/drivers/mtd/ubi/fastmap-wl.c
+++ b/drivers/mtd/ubi/fastmap-wl.c
@@ -346,14 +346,27 @@ out:
* WL sub-system.
*
* @ubi: UBI device description object
+ * @need_fill: whether to fill wear-leveling pool when no PEBs are found
*/
-static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi)
+static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
+ bool need_fill)
{
struct ubi_fm_pool *pool = &ubi->fm_wl_pool;
int pnum;
- if (pool->used == pool->size)
+ if (pool->used == pool->size) {
+ if (need_fill && !ubi->fm_work_scheduled) {
+ /*
+ * We cannot update the fastmap here because this
+ * function is called in atomic context.
+ * Let's fail here and refill/update it as soon as
+ * possible.
+ */
+ ubi->fm_work_scheduled = 1;
+ schedule_work(&ubi->fm_work);
+ }
return NULL;
+ }
pnum = pool->pebs[pool->used];
return ubi->lookuptbl[pnum];
@@ -375,7 +388,7 @@ static bool need_wear_leveling(struct ubi_device *ubi)
if (!ubi->used.rb_node)
return false;
- e = next_peb_for_wl(ubi);
+ e = next_peb_for_wl(ubi, false);
if (!e) {
if (!ubi->free.rb_node)
return false;
diff --git a/drivers/mtd/ubi/nvmem.c b/drivers/mtd/ubi/nvmem.c
index a94a1a9aaec1..34f8c1d3cdee 100644
--- a/drivers/mtd/ubi/nvmem.c
+++ b/drivers/mtd/ubi/nvmem.c
@@ -55,7 +55,7 @@ static int ubi_nvmem_reg_read(void *priv, unsigned int from,
if (err)
return err;
- return bytes_left == 0 ? 0 : -EIO;
+ return 0;
}
static int ubi_nvmem_add(struct ubi_volume_info *vi)
diff --git a/drivers/mtd/ubi/ubi.h b/drivers/mtd/ubi/ubi.h
index 1c9e874e8ede..26cc53ad34ec 100644
--- a/drivers/mtd/ubi/ubi.h
+++ b/drivers/mtd/ubi/ubi.h
@@ -549,6 +549,7 @@ struct ubi_debug_info {
* @peb_buf: a buffer of PEB size used for different purposes
* @buf_mutex: protects @peb_buf
* @ckvol_mutex: serializes static volume checking when opening
+ * @wl_reboot_notifier: close all wear-leveling work before reboot
*
* @dbg: debugging information for this UBI device
*/
@@ -651,6 +652,7 @@ struct ubi_device {
void *peb_buf;
struct mutex buf_mutex;
struct mutex ckvol_mutex;
+ struct notifier_block wl_reboot_notifier;
struct ubi_debug_info dbg;
};
@@ -831,7 +833,6 @@ void ubi_remove_av(struct ubi_attach_info *ai, struct ubi_ainf_volume *av);
struct ubi_ainf_peb *ubi_early_get_peb(struct ubi_device *ubi,
struct ubi_attach_info *ai);
int ubi_attach(struct ubi_device *ubi, int force_scan);
-void ubi_destroy_ai(struct ubi_attach_info *ai);
/* vtbl.c */
int ubi_change_vtbl_record(struct ubi_device *ubi, int idx,
diff --git a/drivers/mtd/ubi/vmt.c b/drivers/mtd/ubi/vmt.c
index 5a3558bbb903..e5cf3bdca3b0 100644
--- a/drivers/mtd/ubi/vmt.c
+++ b/drivers/mtd/ubi/vmt.c
@@ -143,8 +143,10 @@ static struct fwnode_handle *find_volume_fwnode(struct ubi_volume *vol)
vol->vol_id != volid)
continue;
+ fwnode_handle_put(fw_vols);
return fw_vol;
}
+ fwnode_handle_put(fw_vols);
return NULL;
}
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index a357f3d27f2f..4f6f339d8fb8 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -89,6 +89,7 @@
#include <linux/crc32.h>
#include <linux/freezer.h>
#include <linux/kthread.h>
+#include <linux/reboot.h>
#include "ubi.h"
#include "wl.h"
@@ -127,6 +128,8 @@ static int self_check_in_wl_tree(const struct ubi_device *ubi,
struct ubi_wl_entry *e, struct rb_root *root);
static int self_check_in_pq(const struct ubi_device *ubi,
struct ubi_wl_entry *e);
+static int ubi_wl_reboot_notifier(struct notifier_block *n,
+ unsigned long state, void *cmd);
/**
* wl_tree_add - add a wear-leveling entry to a WL RB-tree.
@@ -683,7 +686,7 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
ubi_assert(!ubi->move_to_put);
#ifdef CONFIG_MTD_UBI_FASTMAP
- if (!next_peb_for_wl(ubi) ||
+ if (!next_peb_for_wl(ubi, true) ||
#else
if (!ubi->free.rb_node ||
#endif
@@ -846,7 +849,14 @@ static int wear_leveling_worker(struct ubi_device *ubi, struct ubi_work *wrk,
goto out_not_moved;
}
if (err == MOVE_RETRY) {
- scrubbing = 1;
+ /*
+ * For source PEB:
+ * 1. The scrubbing is set for scrub type PEB, it will
+ * be put back into ubi->scrub list.
+ * 2. Non-scrub type PEB will be put back into ubi->used
+ * list.
+ */
+ keep = 1;
dst_leb_clean = 1;
goto out_not_moved;
}
@@ -1943,6 +1953,13 @@ int ubi_wl_init(struct ubi_device *ubi, struct ubi_attach_info *ai)
if (!ubi->ro_mode && !ubi->fm_disabled)
ubi_ensure_anchor_pebs(ubi);
#endif
+
+ if (!ubi->wl_reboot_notifier.notifier_call) {
+ ubi->wl_reboot_notifier.notifier_call = ubi_wl_reboot_notifier;
+ ubi->wl_reboot_notifier.priority = 1; /* Higher than MTD */
+ register_reboot_notifier(&ubi->wl_reboot_notifier);
+ }
+
return 0;
out_free:
@@ -1988,6 +2005,17 @@ void ubi_wl_close(struct ubi_device *ubi)
kfree(ubi->lookuptbl);
}
+static int ubi_wl_reboot_notifier(struct notifier_block *n,
+ unsigned long state, void *cmd)
+{
+ struct ubi_device *ubi;
+
+ ubi = container_of(n, struct ubi_device, wl_reboot_notifier);
+ ubi_wl_close(ubi);
+
+ return NOTIFY_DONE;
+}
+
/**
* self_check_ec - make sure that the erase counter of a PEB is correct.
* @ubi: UBI device description object
diff --git a/drivers/mtd/ubi/wl.h b/drivers/mtd/ubi/wl.h
index 7b6715ef6d4a..a69169c35e31 100644
--- a/drivers/mtd/ubi/wl.h
+++ b/drivers/mtd/ubi/wl.h
@@ -5,7 +5,8 @@
static void update_fastmap_work_fn(struct work_struct *wrk);
static struct ubi_wl_entry *find_anchor_wl_entry(struct rb_root *root);
static struct ubi_wl_entry *get_peb_for_wl(struct ubi_device *ubi);
-static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi);
+static struct ubi_wl_entry *next_peb_for_wl(struct ubi_device *ubi,
+ bool need_fill);
static bool need_wear_leveling(struct ubi_device *ubi);
static void ubi_fastmap_close(struct ubi_device *ubi);
static inline void ubi_fastmap_init(struct ubi_device *ubi, int *count)
diff --git a/drivers/net/bareudp.c b/drivers/net/bareudp.c
index a2abfade82dd..70814303aab8 100644
--- a/drivers/net/bareudp.c
+++ b/drivers/net/bareudp.c
@@ -84,7 +84,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
if (skb_copy_bits(skb, BAREUDP_BASE_HLEN, &ipversion,
sizeof(ipversion))) {
- dev_core_stats_rx_dropped_inc(bareudp->dev);
+ dev_dstats_rx_dropped(bareudp->dev);
goto drop;
}
ipversion >>= 4;
@@ -94,7 +94,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
} else if (ipversion == 6 && bareudp->multi_proto_mode) {
proto = htons(ETH_P_IPV6);
} else {
- dev_core_stats_rx_dropped_inc(bareudp->dev);
+ dev_dstats_rx_dropped(bareudp->dev);
goto drop;
}
} else if (bareudp->ethertype == htons(ETH_P_MPLS_UC)) {
@@ -108,7 +108,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
ipv4_is_multicast(tunnel_hdr->daddr)) {
proto = htons(ETH_P_MPLS_MC);
} else {
- dev_core_stats_rx_dropped_inc(bareudp->dev);
+ dev_dstats_rx_dropped(bareudp->dev);
goto drop;
}
} else {
@@ -124,7 +124,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
(addr_type & IPV6_ADDR_MULTICAST)) {
proto = htons(ETH_P_MPLS_MC);
} else {
- dev_core_stats_rx_dropped_inc(bareudp->dev);
+ dev_dstats_rx_dropped(bareudp->dev);
goto drop;
}
}
@@ -136,7 +136,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
proto,
!net_eq(bareudp->net,
dev_net(bareudp->dev)))) {
- dev_core_stats_rx_dropped_inc(bareudp->dev);
+ dev_dstats_rx_dropped(bareudp->dev);
goto drop;
}
@@ -144,7 +144,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
tun_dst = udp_tun_rx_dst(skb, family, key, 0, 0);
if (!tun_dst) {
- dev_core_stats_rx_dropped_inc(bareudp->dev);
+ dev_dstats_rx_dropped(bareudp->dev);
goto drop;
}
skb_dst_set(skb, &tun_dst->dst);
@@ -194,7 +194,7 @@ static int bareudp_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
len = skb->len;
err = gro_cells_receive(&bareudp->gro_cells, skb);
if (likely(err == NET_RX_SUCCESS))
- dev_sw_netstats_rx_add(bareudp->dev, len);
+ dev_dstats_rx_add(bareudp->dev, len);
return 0;
drop:
@@ -589,7 +589,7 @@ static void bareudp_setup(struct net_device *dev)
dev->priv_flags |= IFF_NO_QUEUE;
dev->lltx = true;
dev->flags = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
- dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
}
static int bareudp_validate(struct nlattr *tb[], struct nlattr *data[],
diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c
index 49dd4fe195e5..7b78c2bada81 100644
--- a/drivers/net/bonding/bond_main.c
+++ b/drivers/net/bonding/bond_main.c
@@ -1520,9 +1520,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
struct slave *slave;
mask = features;
-
- features &= ~NETIF_F_ONE_FOR_ALL;
- features |= NETIF_F_ALL_FOR_ALL;
+ features = netdev_base_features(features);
bond_for_each_slave(bond, slave, iter) {
features = netdev_increment_features(features,
@@ -1536,6 +1534,7 @@ static netdev_features_t bond_fix_features(struct net_device *dev,
#define BOND_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
+ NETIF_F_GSO_ENCAP_ALL | \
NETIF_F_HIGHDMA | NETIF_F_LRO)
#define BOND_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
@@ -1565,8 +1564,9 @@ static void bond_compute_features(struct bonding *bond)
if (!bond_has_slaves(bond))
goto done;
- vlan_features &= NETIF_F_ALL_FOR_ALL;
- mpls_features &= NETIF_F_ALL_FOR_ALL;
+
+ vlan_features = netdev_base_features(vlan_features);
+ mpls_features = netdev_base_features(mpls_features);
bond_for_each_slave(bond, slave, iter) {
vlan_features = netdev_increment_features(vlan_features,
diff --git a/drivers/net/can/c_can/c_can_main.c b/drivers/net/can/c_can/c_can_main.c
index 511615dc3341..cc371d0c9f3c 100644
--- a/drivers/net/can/c_can/c_can_main.c
+++ b/drivers/net/can/c_can/c_can_main.c
@@ -1014,49 +1014,57 @@ static int c_can_handle_bus_err(struct net_device *dev,
/* propagate the error condition to the CAN stack */
skb = alloc_can_err_skb(dev, &cf);
- if (unlikely(!skb))
- return 0;
/* check for 'last error code' which tells us the
* type of the last error to occur on the CAN bus
*/
- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ if (likely(skb))
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
switch (lec_type) {
case LEC_STUFF_ERROR:
netdev_dbg(dev, "stuff error\n");
- cf->data[2] |= CAN_ERR_PROT_STUFF;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
stats->rx_errors++;
break;
case LEC_FORM_ERROR:
netdev_dbg(dev, "form error\n");
- cf->data[2] |= CAN_ERR_PROT_FORM;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_FORM;
stats->rx_errors++;
break;
case LEC_ACK_ERROR:
netdev_dbg(dev, "ack error\n");
- cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+ if (likely(skb))
+ cf->data[3] = CAN_ERR_PROT_LOC_ACK;
stats->tx_errors++;
break;
case LEC_BIT1_ERROR:
netdev_dbg(dev, "bit1 error\n");
- cf->data[2] |= CAN_ERR_PROT_BIT1;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_BIT1;
stats->tx_errors++;
break;
case LEC_BIT0_ERROR:
netdev_dbg(dev, "bit0 error\n");
- cf->data[2] |= CAN_ERR_PROT_BIT0;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_BIT0;
stats->tx_errors++;
break;
case LEC_CRC_ERROR:
netdev_dbg(dev, "CRC error\n");
- cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+ if (likely(skb))
+ cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
stats->rx_errors++;
break;
default:
break;
}
+ if (unlikely(!skb))
+ return 0;
+
netif_receive_skb(skb);
return 1;
}
diff --git a/drivers/net/can/dev/dev.c b/drivers/net/can/dev/dev.c
index 6792c14fd7eb..681643ab3780 100644
--- a/drivers/net/can/dev/dev.c
+++ b/drivers/net/can/dev/dev.c
@@ -468,7 +468,7 @@ static int can_set_termination(struct net_device *ndev, u16 term)
else
set = 0;
- gpiod_set_value(priv->termination_gpio, set);
+ gpiod_set_value_cansleep(priv->termination_gpio, set);
return 0;
}
diff --git a/drivers/net/can/ifi_canfd/ifi_canfd.c b/drivers/net/can/ifi_canfd/ifi_canfd.c
index d32b10900d2f..c86b57d47085 100644
--- a/drivers/net/can/ifi_canfd/ifi_canfd.c
+++ b/drivers/net/can/ifi_canfd/ifi_canfd.c
@@ -390,36 +390,55 @@ static int ifi_canfd_handle_lec_err(struct net_device *ndev)
return 0;
priv->can.can_stats.bus_error++;
- stats->rx_errors++;
/* Propagate the error condition to the CAN stack. */
skb = alloc_can_err_skb(ndev, &cf);
- if (unlikely(!skb))
- return 0;
/* Read the error counter register and check for new errors. */
- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ if (likely(skb))
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
- if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST)
- cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
+ if (errctr & IFI_CANFD_ERROR_CTR_OVERLOAD_FIRST) {
+ stats->rx_errors++;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_OVERLOAD;
+ }
- if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST)
- cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+ if (errctr & IFI_CANFD_ERROR_CTR_ACK_ERROR_FIRST) {
+ stats->tx_errors++;
+ if (likely(skb))
+ cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+ }
- if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST)
- cf->data[2] |= CAN_ERR_PROT_BIT0;
+ if (errctr & IFI_CANFD_ERROR_CTR_BIT0_ERROR_FIRST) {
+ stats->tx_errors++;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_BIT0;
+ }
- if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST)
- cf->data[2] |= CAN_ERR_PROT_BIT1;
+ if (errctr & IFI_CANFD_ERROR_CTR_BIT1_ERROR_FIRST) {
+ stats->tx_errors++;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_BIT1;
+ }
- if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST)
- cf->data[2] |= CAN_ERR_PROT_STUFF;
+ if (errctr & IFI_CANFD_ERROR_CTR_STUFF_ERROR_FIRST) {
+ stats->rx_errors++;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ }
- if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST)
- cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+ if (errctr & IFI_CANFD_ERROR_CTR_CRC_ERROR_FIRST) {
+ stats->rx_errors++;
+ if (likely(skb))
+ cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+ }
- if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST)
- cf->data[2] |= CAN_ERR_PROT_FORM;
+ if (errctr & IFI_CANFD_ERROR_CTR_FORM_ERROR_FIRST) {
+ stats->rx_errors++;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ }
/* Reset the error counter, ack the IRQ and re-enable the counter. */
writel(IFI_CANFD_ERROR_CTR_ER_RESET, priv->base + IFI_CANFD_ERROR_CTR);
@@ -427,6 +446,9 @@ static int ifi_canfd_handle_lec_err(struct net_device *ndev)
priv->base + IFI_CANFD_INTERRUPT);
writel(IFI_CANFD_ERROR_CTR_ER_ENABLE, priv->base + IFI_CANFD_ERROR_CTR);
+ if (unlikely(!skb))
+ return 0;
+
netif_receive_skb(skb);
return 1;
diff --git a/drivers/net/can/m_can/m_can.c b/drivers/net/can/m_can/m_can.c
index 16e9e7d7527d..97cd8bbf2e32 100644
--- a/drivers/net/can/m_can/m_can.c
+++ b/drivers/net/can/m_can/m_can.c
@@ -695,47 +695,60 @@ static int m_can_handle_lec_err(struct net_device *dev,
u32 timestamp = 0;
cdev->can.can_stats.bus_error++;
- stats->rx_errors++;
/* propagate the error condition to the CAN stack */
skb = alloc_can_err_skb(dev, &cf);
- if (unlikely(!skb))
- return 0;
/* check for 'last error code' which tells us the
* type of the last error to occur on the CAN bus
*/
- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ if (likely(skb))
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
switch (lec_type) {
case LEC_STUFF_ERROR:
netdev_dbg(dev, "stuff error\n");
- cf->data[2] |= CAN_ERR_PROT_STUFF;
+ stats->rx_errors++;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
break;
case LEC_FORM_ERROR:
netdev_dbg(dev, "form error\n");
- cf->data[2] |= CAN_ERR_PROT_FORM;
+ stats->rx_errors++;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_FORM;
break;
case LEC_ACK_ERROR:
netdev_dbg(dev, "ack error\n");
- cf->data[3] = CAN_ERR_PROT_LOC_ACK;
+ stats->tx_errors++;
+ if (likely(skb))
+ cf->data[3] = CAN_ERR_PROT_LOC_ACK;
break;
case LEC_BIT1_ERROR:
netdev_dbg(dev, "bit1 error\n");
- cf->data[2] |= CAN_ERR_PROT_BIT1;
+ stats->tx_errors++;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_BIT1;
break;
case LEC_BIT0_ERROR:
netdev_dbg(dev, "bit0 error\n");
- cf->data[2] |= CAN_ERR_PROT_BIT0;
+ stats->tx_errors++;
+ if (likely(skb))
+ cf->data[2] |= CAN_ERR_PROT_BIT0;
break;
case LEC_CRC_ERROR:
netdev_dbg(dev, "CRC error\n");
- cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
+ stats->rx_errors++;
+ if (likely(skb))
+ cf->data[3] = CAN_ERR_PROT_LOC_CRC_SEQ;
break;
default:
break;
}
+ if (unlikely(!skb))
+ return 0;
+
if (cdev->is_peripheral)
timestamp = m_can_get_timestamp(cdev);
@@ -1207,20 +1220,32 @@ static void m_can_coalescing_update(struct m_can_classdev *cdev, u32 ir)
static int m_can_interrupt_handler(struct m_can_classdev *cdev)
{
struct net_device *dev = cdev->net;
- u32 ir;
+ u32 ir = 0, ir_read;
int ret;
if (pm_runtime_suspended(cdev->dev))
return IRQ_NONE;
- ir = m_can_read(cdev, M_CAN_IR);
+ /* The m_can controller signals its interrupt status as a level, but
+ * depending in the integration the CPU may interpret the signal as
+ * edge-triggered (for example with m_can_pci). For these
+ * edge-triggered integrations, we must observe that IR is 0 at least
+ * once to be sure that the next interrupt will generate an edge.
+ */
+ while ((ir_read = m_can_read(cdev, M_CAN_IR)) != 0) {
+ ir |= ir_read;
+
+ /* ACK all irqs */
+ m_can_write(cdev, M_CAN_IR, ir);
+
+ if (!cdev->irq_edge_triggered)
+ break;
+ }
+
m_can_coalescing_update(cdev, ir);
if (!ir)
return IRQ_NONE;
- /* ACK all irqs */
- m_can_write(cdev, M_CAN_IR, ir);
-
if (cdev->ops->clear_interrupts)
cdev->ops->clear_interrupts(cdev);
@@ -1682,6 +1707,14 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
return -EINVAL;
}
+ /* Write the INIT bit, in case no hardware reset has happened before
+ * the probe (for example, it was observed that the Intel Elkhart Lake
+ * SoCs do not properly reset the CAN controllers on reboot)
+ */
+ err = m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
+ if (err)
+ return err;
+
if (!cdev->is_peripheral)
netif_napi_add(dev, &cdev->napi, m_can_poll);
@@ -1733,11 +1766,7 @@ static int m_can_dev_setup(struct m_can_classdev *cdev)
return -EINVAL;
}
- /* Forcing standby mode should be redundant, as the chip should be in
- * standby after a reset. Write the INIT bit anyways, should the chip
- * be configured by previous stage.
- */
- return m_can_cccr_update_bits(cdev, CCCR_INIT, CCCR_INIT);
+ return 0;
}
static void m_can_stop(struct net_device *dev)
diff --git a/drivers/net/can/m_can/m_can.h b/drivers/net/can/m_can/m_can.h
index 92b2bd8628e6..ef39e8e527ab 100644
--- a/drivers/net/can/m_can/m_can.h
+++ b/drivers/net/can/m_can/m_can.h
@@ -99,6 +99,7 @@ struct m_can_classdev {
int pm_clock_support;
int pm_wake_source;
int is_peripheral;
+ bool irq_edge_triggered;
// Cached M_CAN_IE register content
u32 active_interrupts;
diff --git a/drivers/net/can/m_can/m_can_pci.c b/drivers/net/can/m_can/m_can_pci.c
index d72fe771dfc7..9ad7419f88f8 100644
--- a/drivers/net/can/m_can/m_can_pci.c
+++ b/drivers/net/can/m_can/m_can_pci.c
@@ -127,6 +127,7 @@ static int m_can_pci_probe(struct pci_dev *pci, const struct pci_device_id *id)
mcan_class->pm_clock_support = 1;
mcan_class->pm_wake_source = 0;
mcan_class->can.clock.freq = id->driver_data;
+ mcan_class->irq_edge_triggered = true;
mcan_class->ops = &m_can_pci_ops;
pci_set_drvdata(pci, mcan_class);
diff --git a/drivers/net/can/sja1000/sja1000.c b/drivers/net/can/sja1000/sja1000.c
index ddb3247948ad..4d245857ef1c 100644
--- a/drivers/net/can/sja1000/sja1000.c
+++ b/drivers/net/can/sja1000/sja1000.c
@@ -416,8 +416,6 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
int ret = 0;
skb = alloc_can_err_skb(dev, &cf);
- if (skb == NULL)
- return -ENOMEM;
txerr = priv->read_reg(priv, SJA1000_TXERR);
rxerr = priv->read_reg(priv, SJA1000_RXERR);
@@ -425,8 +423,11 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
if (isrc & IRQ_DOI) {
/* data overrun interrupt */
netdev_dbg(dev, "data overrun interrupt\n");
- cf->can_id |= CAN_ERR_CRTL;
- cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+ if (skb) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+ }
+
stats->rx_over_errors++;
stats->rx_errors++;
sja1000_write_cmdreg(priv, CMD_CDO); /* clear bit */
@@ -452,7 +453,7 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
else
state = CAN_STATE_ERROR_ACTIVE;
}
- if (state != CAN_STATE_BUS_OFF) {
+ if (state != CAN_STATE_BUS_OFF && skb) {
cf->can_id |= CAN_ERR_CNT;
cf->data[6] = txerr;
cf->data[7] = rxerr;
@@ -460,33 +461,38 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
if (isrc & IRQ_BEI) {
/* bus error interrupt */
priv->can.can_stats.bus_error++;
- stats->rx_errors++;
ecc = priv->read_reg(priv, SJA1000_ECC);
+ if (skb) {
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
-
- /* set error type */
- switch (ecc & ECC_MASK) {
- case ECC_BIT:
- cf->data[2] |= CAN_ERR_PROT_BIT;
- break;
- case ECC_FORM:
- cf->data[2] |= CAN_ERR_PROT_FORM;
- break;
- case ECC_STUFF:
- cf->data[2] |= CAN_ERR_PROT_STUFF;
- break;
- default:
- break;
- }
+ /* set error type */
+ switch (ecc & ECC_MASK) {
+ case ECC_BIT:
+ cf->data[2] |= CAN_ERR_PROT_BIT;
+ break;
+ case ECC_FORM:
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ break;
+ case ECC_STUFF:
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ break;
+ default:
+ break;
+ }
- /* set error location */
- cf->data[3] = ecc & ECC_SEG;
+ /* set error location */
+ cf->data[3] = ecc & ECC_SEG;
+ }
/* Error occurred during transmission? */
- if ((ecc & ECC_DIR) == 0)
- cf->data[2] |= CAN_ERR_PROT_TX;
+ if ((ecc & ECC_DIR) == 0) {
+ stats->tx_errors++;
+ if (skb)
+ cf->data[2] |= CAN_ERR_PROT_TX;
+ } else {
+ stats->rx_errors++;
+ }
}
if (isrc & IRQ_EPI) {
/* error passive interrupt */
@@ -502,8 +508,10 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
netdev_dbg(dev, "arbitration lost interrupt\n");
alc = priv->read_reg(priv, SJA1000_ALC);
priv->can.can_stats.arbitration_lost++;
- cf->can_id |= CAN_ERR_LOSTARB;
- cf->data[0] = alc & 0x1f;
+ if (skb) {
+ cf->can_id |= CAN_ERR_LOSTARB;
+ cf->data[0] = alc & 0x1f;
+ }
}
if (state != priv->can.state) {
@@ -516,6 +524,9 @@ static int sja1000_err(struct net_device *dev, uint8_t isrc, uint8_t status)
can_bus_off(dev);
}
+ if (!skb)
+ return -ENOMEM;
+
netif_rx(skb);
return ret;
diff --git a/drivers/net/can/sja1000/sja1000_platform.c b/drivers/net/can/sja1000/sja1000_platform.c
index c42ebe9da55a..2d555f854008 100644
--- a/drivers/net/can/sja1000/sja1000_platform.c
+++ b/drivers/net/can/sja1000/sja1000_platform.c
@@ -230,18 +230,9 @@ static int sp_probe(struct platform_device *pdev)
return -ENODEV;
}
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res_mem)
- return -ENODEV;
-
- if (!devm_request_mem_region(&pdev->dev, res_mem->start,
- resource_size(res_mem), DRV_NAME))
- return -EBUSY;
-
- addr = devm_ioremap(&pdev->dev, res_mem->start,
- resource_size(res_mem));
- if (!addr)
- return -ENOMEM;
+ addr = devm_platform_get_and_ioremap_resource(pdev, 0, &res_mem);
+ if (IS_ERR(addr))
+ return PTR_ERR(addr);
if (of) {
irq = platform_get_irq(pdev, 0);
diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c
index 148d974ebb21..09ae218315d7 100644
--- a/drivers/net/can/spi/hi311x.c
+++ b/drivers/net/can/spi/hi311x.c
@@ -663,27 +663,27 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
u8 rxerr, txerr;
skb = alloc_can_err_skb(net, &cf);
- if (!skb)
- break;
txerr = hi3110_read(spi, HI3110_READ_TEC);
rxerr = hi3110_read(spi, HI3110_READ_REC);
tx_state = txerr >= rxerr ? new_state : 0;
rx_state = txerr <= rxerr ? new_state : 0;
can_change_state(net, cf, tx_state, rx_state);
- netif_rx(skb);
if (new_state == CAN_STATE_BUS_OFF) {
+ if (skb)
+ netif_rx(skb);
can_bus_off(net);
if (priv->can.restart_ms == 0) {
priv->force_quit = 1;
hi3110_hw_sleep(spi);
break;
}
- } else {
+ } else if (skb) {
cf->can_id |= CAN_ERR_CNT;
cf->data[6] = txerr;
cf->data[7] = rxerr;
+ netif_rx(skb);
}
}
@@ -696,27 +696,38 @@ static irqreturn_t hi3110_can_ist(int irq, void *dev_id)
/* Check for protocol errors */
if (eflag & HI3110_ERR_PROTOCOL_MASK) {
skb = alloc_can_err_skb(net, &cf);
- if (!skb)
- break;
+ if (skb)
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
priv->can.can_stats.bus_error++;
- priv->net->stats.rx_errors++;
- if (eflag & HI3110_ERR_BITERR)
- cf->data[2] |= CAN_ERR_PROT_BIT;
- else if (eflag & HI3110_ERR_FRMERR)
- cf->data[2] |= CAN_ERR_PROT_FORM;
- else if (eflag & HI3110_ERR_STUFERR)
- cf->data[2] |= CAN_ERR_PROT_STUFF;
- else if (eflag & HI3110_ERR_CRCERR)
- cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
- else if (eflag & HI3110_ERR_ACKERR)
- cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
-
- cf->data[6] = hi3110_read(spi, HI3110_READ_TEC);
- cf->data[7] = hi3110_read(spi, HI3110_READ_REC);
+ if (eflag & HI3110_ERR_BITERR) {
+ priv->net->stats.tx_errors++;
+ if (skb)
+ cf->data[2] |= CAN_ERR_PROT_BIT;
+ } else if (eflag & HI3110_ERR_FRMERR) {
+ priv->net->stats.rx_errors++;
+ if (skb)
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ } else if (eflag & HI3110_ERR_STUFERR) {
+ priv->net->stats.rx_errors++;
+ if (skb)
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ } else if (eflag & HI3110_ERR_CRCERR) {
+ priv->net->stats.rx_errors++;
+ if (skb)
+ cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ;
+ } else if (eflag & HI3110_ERR_ACKERR) {
+ priv->net->stats.tx_errors++;
+ if (skb)
+ cf->data[3] |= CAN_ERR_PROT_LOC_ACK;
+ }
+
netdev_dbg(priv->net, "Bus Error\n");
- netif_rx(skb);
+ if (skb) {
+ cf->data[6] = hi3110_read(spi, HI3110_READ_TEC);
+ cf->data[7] = hi3110_read(spi, HI3110_READ_REC);
+ netif_rx(skb);
+ }
}
}
diff --git a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
index d3ac865933fd..e94321849fd7 100644
--- a/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
+++ b/drivers/net/can/spi/mcp251xfd/mcp251xfd-tef.c
@@ -21,6 +21,11 @@ static inline bool mcp251xfd_tx_fifo_sta_empty(u32 fifo_sta)
return fifo_sta & MCP251XFD_REG_FIFOSTA_TFERFFIF;
}
+static inline bool mcp251xfd_tx_fifo_sta_less_than_half_full(u32 fifo_sta)
+{
+ return fifo_sta & MCP251XFD_REG_FIFOSTA_TFHRFHIF;
+}
+
static inline int
mcp251xfd_tef_tail_get_from_chip(const struct mcp251xfd_priv *priv,
u8 *tef_tail)
@@ -147,7 +152,29 @@ mcp251xfd_get_tef_len(struct mcp251xfd_priv *priv, u8 *len_p)
BUILD_BUG_ON(sizeof(tx_ring->obj_num) != sizeof(len));
len = (chip_tx_tail << shift) - (tail << shift);
- *len_p = len >> shift;
+ len >>= shift;
+
+ /* According to mcp2518fd erratum DS80000789E 6. the FIFOCI
+ * bits of a FIFOSTA register, here the TX-FIFO tail index
+ * might be corrupted.
+ *
+ * However here it seems the bit indicating that the TX-FIFO
+ * is empty (MCP251XFD_REG_FIFOSTA_TFERFFIF) is not correct
+ * while the TX-FIFO tail index is.
+ *
+ * We assume the TX-FIFO is empty, i.e. all pending CAN frames
+ * haven been send, if:
+ * - Chip's head and tail index are equal (len == 0).
+ * - The TX-FIFO is less than half full.
+ * (The TX-FIFO empty case has already been checked at the
+ * beginning of this function.)
+ * - No free buffers in the TX ring.
+ */
+ if (len == 0 && mcp251xfd_tx_fifo_sta_less_than_half_full(fifo_sta) &&
+ mcp251xfd_get_tx_free(tx_ring) == 0)
+ len = tx_ring->obj_num;
+
+ *len_p = len;
return 0;
}
diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c
index 360158c295d3..4311c1f0eafd 100644
--- a/drivers/net/can/sun4i_can.c
+++ b/drivers/net/can/sun4i_can.c
@@ -579,11 +579,9 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
/* bus error interrupt */
netdev_dbg(dev, "bus error interrupt\n");
priv->can.can_stats.bus_error++;
- stats->rx_errors++;
+ ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
if (likely(skb)) {
- ecc = readl(priv->base + SUN4I_REG_STA_ADDR);
-
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
switch (ecc & SUN4I_STA_MASK_ERR) {
@@ -601,9 +599,15 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
>> 16;
break;
}
- /* error occurred during transmission? */
- if ((ecc & SUN4I_STA_ERR_DIR) == 0)
+ }
+
+ /* error occurred during transmission? */
+ if ((ecc & SUN4I_STA_ERR_DIR) == 0) {
+ if (likely(skb))
cf->data[2] |= CAN_ERR_PROT_TX;
+ stats->tx_errors++;
+ } else {
+ stats->rx_errors++;
}
}
if (isrc & SUN4I_INT_ERR_PASSIVE) {
@@ -629,10 +633,10 @@ static int sun4i_can_err(struct net_device *dev, u8 isrc, u8 status)
tx_state = txerr >= rxerr ? state : 0;
rx_state = txerr <= rxerr ? state : 0;
- if (likely(skb))
- can_change_state(dev, cf, tx_state, rx_state);
- else
- priv->can.state = state;
+ /* The skb allocation might fail, but can_change_state()
+ * handles cf == NULL.
+ */
+ can_change_state(dev, cf, tx_state, rx_state);
if (state == CAN_STATE_BUS_OFF)
can_bus_off(dev);
}
diff --git a/drivers/net/can/usb/ems_usb.c b/drivers/net/can/usb/ems_usb.c
index 050c0b49938a..5355bac4dccb 100644
--- a/drivers/net/can/usb/ems_usb.c
+++ b/drivers/net/can/usb/ems_usb.c
@@ -335,15 +335,14 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
struct net_device_stats *stats = &dev->netdev->stats;
skb = alloc_can_err_skb(dev->netdev, &cf);
- if (skb == NULL)
- return;
if (msg->type == CPC_MSG_TYPE_CAN_STATE) {
u8 state = msg->msg.can_state;
if (state & SJA1000_SR_BS) {
dev->can.state = CAN_STATE_BUS_OFF;
- cf->can_id |= CAN_ERR_BUSOFF;
+ if (skb)
+ cf->can_id |= CAN_ERR_BUSOFF;
dev->can.can_stats.bus_off++;
can_bus_off(dev->netdev);
@@ -361,44 +360,53 @@ static void ems_usb_rx_err(struct ems_usb *dev, struct ems_cpc_msg *msg)
/* bus error interrupt */
dev->can.can_stats.bus_error++;
- stats->rx_errors++;
- cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+ if (skb) {
+ cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
- switch (ecc & SJA1000_ECC_MASK) {
- case SJA1000_ECC_BIT:
- cf->data[2] |= CAN_ERR_PROT_BIT;
- break;
- case SJA1000_ECC_FORM:
- cf->data[2] |= CAN_ERR_PROT_FORM;
- break;
- case SJA1000_ECC_STUFF:
- cf->data[2] |= CAN_ERR_PROT_STUFF;
- break;
- default:
- cf->data[3] = ecc & SJA1000_ECC_SEG;
- break;
+ switch (ecc & SJA1000_ECC_MASK) {
+ case SJA1000_ECC_BIT:
+ cf->data[2] |= CAN_ERR_PROT_BIT;
+ break;
+ case SJA1000_ECC_FORM:
+ cf->data[2] |= CAN_ERR_PROT_FORM;
+ break;
+ case SJA1000_ECC_STUFF:
+ cf->data[2] |= CAN_ERR_PROT_STUFF;
+ break;
+ default:
+ cf->data[3] = ecc & SJA1000_ECC_SEG;
+ break;
+ }
}
/* Error occurred during transmission? */
- if ((ecc & SJA1000_ECC_DIR) == 0)
- cf->data[2] |= CAN_ERR_PROT_TX;
+ if ((ecc & SJA1000_ECC_DIR) == 0) {
+ stats->tx_errors++;
+ if (skb)
+ cf->data[2] |= CAN_ERR_PROT_TX;
+ } else {
+ stats->rx_errors++;
+ }
- if (dev->can.state == CAN_STATE_ERROR_WARNING ||
- dev->can.state == CAN_STATE_ERROR_PASSIVE) {
+ if (skb && (dev->can.state == CAN_STATE_ERROR_WARNING ||
+ dev->can.state == CAN_STATE_ERROR_PASSIVE)) {
cf->can_id |= CAN_ERR_CRTL;
cf->data[1] = (txerr > rxerr) ?
CAN_ERR_CRTL_TX_PASSIVE : CAN_ERR_CRTL_RX_PASSIVE;
}
} else if (msg->type == CPC_MSG_TYPE_OVERRUN) {
- cf->can_id |= CAN_ERR_CRTL;
- cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+ if (skb) {
+ cf->can_id |= CAN_ERR_CRTL;
+ cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+ }
stats->rx_over_errors++;
stats->rx_errors++;
}
- netif_rx(skb);
+ if (skb)
+ netif_rx(skb);
}
/*
diff --git a/drivers/net/can/usb/f81604.c b/drivers/net/can/usb/f81604.c
index bc0c8903fe77..e0cfa1460b0b 100644
--- a/drivers/net/can/usb/f81604.c
+++ b/drivers/net/can/usb/f81604.c
@@ -526,7 +526,6 @@ static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
netdev_dbg(netdev, "bus error interrupt\n");
priv->can.can_stats.bus_error++;
- stats->rx_errors++;
if (skb) {
cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
@@ -548,10 +547,15 @@ static void f81604_handle_can_bus_errors(struct f81604_port_priv *priv,
/* set error location */
cf->data[3] = data->ecc & F81604_SJA1000_ECC_SEG;
+ }
- /* Error occurred during transmission? */
- if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0)
+ /* Error occurred during transmission? */
+ if ((data->ecc & F81604_SJA1000_ECC_DIR) == 0) {
+ stats->tx_errors++;
+ if (skb)
cf->data[2] |= CAN_ERR_PROT_TX;
+ } else {
+ stats->rx_errors++;
}
set_bit(F81604_CLEAR_ECC, &priv->clear_flags);
diff --git a/drivers/net/can/usb/gs_usb.c b/drivers/net/can/usb/gs_usb.c
index bc86e9b329fd..b6f4de375df7 100644
--- a/drivers/net/can/usb/gs_usb.c
+++ b/drivers/net/can/usb/gs_usb.c
@@ -43,9 +43,6 @@
#define USB_XYLANTA_SAINT3_VENDOR_ID 0x16d0
#define USB_XYLANTA_SAINT3_PRODUCT_ID 0x0f30
-#define GS_USB_ENDPOINT_IN 1
-#define GS_USB_ENDPOINT_OUT 2
-
/* Timestamp 32 bit timer runs at 1 MHz (1 µs tick). Worker accounts
* for timer overflow (will be after ~71 minutes)
*/
@@ -336,6 +333,9 @@ struct gs_usb {
unsigned int hf_size_rx;
u8 active_channels;
+
+ unsigned int pipe_in;
+ unsigned int pipe_out;
};
/* 'allocate' a tx context.
@@ -687,7 +687,7 @@ static void gs_usb_receive_bulk_callback(struct urb *urb)
resubmit_urb:
usb_fill_bulk_urb(urb, parent->udev,
- usb_rcvbulkpipe(parent->udev, GS_USB_ENDPOINT_IN),
+ parent->pipe_in,
hf, dev->parent->hf_size_rx,
gs_usb_receive_bulk_callback, parent);
@@ -819,7 +819,7 @@ static netdev_tx_t gs_can_start_xmit(struct sk_buff *skb,
}
usb_fill_bulk_urb(urb, dev->udev,
- usb_sndbulkpipe(dev->udev, GS_USB_ENDPOINT_OUT),
+ dev->parent->pipe_out,
hf, dev->hf_size_tx,
gs_usb_xmit_callback, txc);
@@ -925,8 +925,7 @@ static int gs_can_open(struct net_device *netdev)
/* fill, anchor, and submit rx urb */
usb_fill_bulk_urb(urb,
dev->udev,
- usb_rcvbulkpipe(dev->udev,
- GS_USB_ENDPOINT_IN),
+ dev->parent->pipe_in,
buf,
dev->parent->hf_size_rx,
gs_usb_receive_bulk_callback, parent);
@@ -1413,6 +1412,7 @@ static int gs_usb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
{
struct usb_device *udev = interface_to_usbdev(intf);
+ struct usb_endpoint_descriptor *ep_in, *ep_out;
struct gs_host_frame *hf;
struct gs_usb *parent;
struct gs_host_config hconf = {
@@ -1422,6 +1422,13 @@ static int gs_usb_probe(struct usb_interface *intf,
unsigned int icount, i;
int rc;
+ rc = usb_find_common_endpoints(intf->cur_altsetting,
+ &ep_in, &ep_out, NULL, NULL);
+ if (rc) {
+ dev_err(&intf->dev, "Required endpoints not found\n");
+ return rc;
+ }
+
/* send host config */
rc = usb_control_msg_send(udev, 0,
GS_USB_BREQ_HOST_FORMAT,
@@ -1466,6 +1473,10 @@ static int gs_usb_probe(struct usb_interface *intf,
usb_set_intfdata(intf, parent);
parent->udev = udev;
+ /* store the detected endpoints */
+ parent->pipe_in = usb_rcvbulkpipe(parent->udev, ep_in->bEndpointAddress);
+ parent->pipe_out = usb_sndbulkpipe(parent->udev, ep_out->bEndpointAddress);
+
for (i = 0; i < icount; i++) {
unsigned int hf_size_rx = 0;
diff --git a/drivers/net/can/vxcan.c b/drivers/net/can/vxcan.c
index da7c72105fb6..ca8811941085 100644
--- a/drivers/net/can/vxcan.c
+++ b/drivers/net/can/vxcan.c
@@ -172,13 +172,12 @@ static void vxcan_setup(struct net_device *dev)
/* forward declaration for rtnl_create_link() */
static struct rtnl_link_ops vxcan_link_ops;
-static int vxcan_newlink(struct net *net, struct net_device *dev,
+static int vxcan_newlink(struct net *peer_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
struct vxcan_priv *priv;
struct net_device *peer;
- struct net *peer_net;
struct nlattr *peer_tb[IFLA_MAX + 1], **tbp = tb;
char ifname[IFNAMSIZ];
@@ -203,20 +202,15 @@ static int vxcan_newlink(struct net *net, struct net_device *dev,
name_assign_type = NET_NAME_ENUM;
}
- peer_net = rtnl_link_get_net(net, tbp);
peer = rtnl_create_link(peer_net, ifname, name_assign_type,
&vxcan_link_ops, tbp, extack);
- if (IS_ERR(peer)) {
- put_net(peer_net);
+ if (IS_ERR(peer))
return PTR_ERR(peer);
- }
if (ifmp && dev->ifindex)
peer->ifindex = ifmp->ifi_index;
err = register_netdevice(peer);
- put_net(peer_net);
- peer_net = NULL;
if (err < 0) {
free_netdev(peer);
return err;
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index 285785c942b0..79dc77835681 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -2224,25 +2224,19 @@ int b53_eee_init(struct dsa_switch *ds, int port, struct phy_device *phy)
}
EXPORT_SYMBOL(b53_eee_init);
-int b53_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e)
+bool b53_support_eee(struct dsa_switch *ds, int port)
{
struct b53_device *dev = ds->priv;
- if (is5325(dev) || is5365(dev))
- return -EOPNOTSUPP;
-
- return 0;
+ return !is5325(dev) && !is5365(dev);
}
-EXPORT_SYMBOL(b53_get_mac_eee);
+EXPORT_SYMBOL(b53_support_eee);
int b53_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e)
{
struct b53_device *dev = ds->priv;
struct ethtool_keee *p = &dev->ports[port].eee;
- if (is5325(dev) || is5365(dev))
- return -EOPNOTSUPP;
-
p->eee_enabled = e->eee_enabled;
b53_eee_enable_set(ds, port, e->eee_enabled);
@@ -2298,7 +2292,7 @@ static const struct dsa_switch_ops b53_switch_ops = {
.phylink_get_caps = b53_phylink_get_caps,
.port_enable = b53_enable_port,
.port_disable = b53_disable_port,
- .get_mac_eee = b53_get_mac_eee,
+ .support_eee = b53_support_eee,
.set_mac_eee = b53_set_mac_eee,
.port_bridge_join = b53_br_join,
.port_bridge_leave = b53_br_leave,
diff --git a/drivers/net/dsa/b53/b53_priv.h b/drivers/net/dsa/b53/b53_priv.h
index 05141176daf5..9e9b5bc0c5d6 100644
--- a/drivers/net/dsa/b53/b53_priv.h
+++ b/drivers/net/dsa/b53/b53_priv.h
@@ -384,7 +384,7 @@ int b53_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy);
void b53_disable_port(struct dsa_switch *ds, int port);
void b53_brcm_hdr_setup(struct dsa_switch *ds, int port);
int b53_eee_init(struct dsa_switch *ds, int port, struct phy_device *phy);
-int b53_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e);
+bool b53_support_eee(struct dsa_switch *ds, int port);
int b53_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e);
#endif
diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c
index 43bde1f583ff..fa2bf3fa9019 100644
--- a/drivers/net/dsa/bcm_sf2.c
+++ b/drivers/net/dsa/bcm_sf2.c
@@ -1232,7 +1232,7 @@ static const struct dsa_switch_ops bcm_sf2_ops = {
.set_wol = bcm_sf2_sw_set_wol,
.port_enable = bcm_sf2_port_setup,
.port_disable = bcm_sf2_port_disable,
- .get_mac_eee = b53_get_mac_eee,
+ .support_eee = b53_support_eee,
.set_mac_eee = b53_set_mac_eee,
.port_bridge_join = b53_br_join,
.port_bridge_leave = b53_br_leave,
diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c
index d16817e0476f..29fe79ea74cd 100644
--- a/drivers/net/dsa/microchip/ksz9477.c
+++ b/drivers/net/dsa/microchip/ksz9477.c
@@ -2,7 +2,7 @@
/*
* Microchip KSZ9477 switch driver main logic
*
- * Copyright (C) 2017-2019 Microchip Technology Inc.
+ * Copyright (C) 2017-2024 Microchip Technology Inc.
*/
#include <linux/kernel.h>
@@ -983,26 +983,51 @@ void ksz9477_get_caps(struct ksz_device *dev, int port,
int ksz9477_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
{
u32 secs = msecs / 1000;
- u8 value;
- u8 data;
+ u8 data, mult, value;
+ u32 max_val;
int ret;
- value = FIELD_GET(SW_AGE_PERIOD_7_0_M, secs);
+#define MAX_TIMER_VAL ((1 << 8) - 1)
- ret = ksz_write8(dev, REG_SW_LUE_CTRL_3, value);
- if (ret < 0)
- return ret;
+ /* The aging timer comprises a 3-bit multiplier and an 8-bit second
+ * value. Either of them cannot be zero. The maximum timer is then
+ * 7 * 255 = 1785 seconds.
+ */
+ if (!secs)
+ secs = 1;
- data = FIELD_GET(SW_AGE_PERIOD_10_8_M, secs);
+ /* Return error if too large. */
+ else if (secs > 7 * MAX_TIMER_VAL)
+ return -EINVAL;
ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &value);
if (ret < 0)
return ret;
- value &= ~SW_AGE_CNT_M;
- value |= FIELD_PREP(SW_AGE_CNT_M, data);
+ /* Check whether there is need to update the multiplier. */
+ mult = FIELD_GET(SW_AGE_CNT_M, value);
+ max_val = MAX_TIMER_VAL;
+ if (mult > 0) {
+ /* Try to use the same multiplier already in the register as
+ * the hardware default uses multiplier 4 and 75 seconds for
+ * 300 seconds.
+ */
+ max_val = DIV_ROUND_UP(secs, mult);
+ if (max_val > MAX_TIMER_VAL || max_val * mult != secs)
+ max_val = MAX_TIMER_VAL;
+ }
+
+ data = DIV_ROUND_UP(secs, max_val);
+ if (mult != data) {
+ value &= ~SW_AGE_CNT_M;
+ value |= FIELD_PREP(SW_AGE_CNT_M, data);
+ ret = ksz_write8(dev, REG_SW_LUE_CTRL_0, value);
+ if (ret < 0)
+ return ret;
+ }
- return ksz_write8(dev, REG_SW_LUE_CTRL_0, value);
+ value = DIV_ROUND_UP(secs, data);
+ return ksz_write8(dev, REG_SW_LUE_CTRL_3, value);
}
void ksz9477_port_queue_split(struct ksz_device *dev, int port)
diff --git a/drivers/net/dsa/microchip/ksz9477_i2c.c b/drivers/net/dsa/microchip/ksz9477_i2c.c
index 1c6d7fc16772..a2beb27459f1 100644
--- a/drivers/net/dsa/microchip/ksz9477_i2c.c
+++ b/drivers/net/dsa/microchip/ksz9477_i2c.c
@@ -127,10 +127,14 @@ static const struct of_device_id ksz9477_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, ksz9477_dt_ids);
+static DEFINE_SIMPLE_DEV_PM_OPS(ksz_i2c_pm_ops,
+ ksz_switch_suspend, ksz_switch_resume);
+
static struct i2c_driver ksz9477_i2c_driver = {
.driver = {
.name = "ksz9477-switch",
.of_match_table = ksz9477_dt_ids,
+ .pm = &ksz_i2c_pm_ops,
},
.probe = ksz9477_i2c_probe,
.remove = ksz9477_i2c_remove,
diff --git a/drivers/net/dsa/microchip/ksz9477_reg.h b/drivers/net/dsa/microchip/ksz9477_reg.h
index 04235c22bf40..ff579920078e 100644
--- a/drivers/net/dsa/microchip/ksz9477_reg.h
+++ b/drivers/net/dsa/microchip/ksz9477_reg.h
@@ -2,7 +2,7 @@
/*
* Microchip KSZ9477 register definitions
*
- * Copyright (C) 2017-2018 Microchip Technology Inc.
+ * Copyright (C) 2017-2024 Microchip Technology Inc.
*/
#ifndef __KSZ9477_REGS_H
@@ -165,8 +165,6 @@
#define SW_VLAN_ENABLE BIT(7)
#define SW_DROP_INVALID_VID BIT(6)
#define SW_AGE_CNT_M GENMASK(5, 3)
-#define SW_AGE_CNT_S 3
-#define SW_AGE_PERIOD_10_8_M GENMASK(10, 8)
#define SW_RESV_MCAST_ENABLE BIT(2)
#define SW_HASH_OPTION_M 0x03
#define SW_HASH_OPTION_CRC 1
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 920443ee8ffd..89f0796894af 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -1100,10 +1100,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
regmap_reg_range(0x1030, 0x1030),
regmap_reg_range(0x1100, 0x1115),
regmap_reg_range(0x111a, 0x111f),
- regmap_reg_range(0x1122, 0x1127),
- regmap_reg_range(0x112a, 0x112b),
- regmap_reg_range(0x1136, 0x1139),
- regmap_reg_range(0x113e, 0x113f),
+ regmap_reg_range(0x1120, 0x112b),
+ regmap_reg_range(0x1134, 0x113b),
+ regmap_reg_range(0x113c, 0x113f),
regmap_reg_range(0x1400, 0x1401),
regmap_reg_range(0x1403, 0x1403),
regmap_reg_range(0x1410, 0x1417),
@@ -1130,10 +1129,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
regmap_reg_range(0x2030, 0x2030),
regmap_reg_range(0x2100, 0x2115),
regmap_reg_range(0x211a, 0x211f),
- regmap_reg_range(0x2122, 0x2127),
- regmap_reg_range(0x212a, 0x212b),
- regmap_reg_range(0x2136, 0x2139),
- regmap_reg_range(0x213e, 0x213f),
+ regmap_reg_range(0x2120, 0x212b),
+ regmap_reg_range(0x2134, 0x213b),
+ regmap_reg_range(0x213c, 0x213f),
regmap_reg_range(0x2400, 0x2401),
regmap_reg_range(0x2403, 0x2403),
regmap_reg_range(0x2410, 0x2417),
@@ -1160,10 +1158,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
regmap_reg_range(0x3030, 0x3030),
regmap_reg_range(0x3100, 0x3115),
regmap_reg_range(0x311a, 0x311f),
- regmap_reg_range(0x3122, 0x3127),
- regmap_reg_range(0x312a, 0x312b),
- regmap_reg_range(0x3136, 0x3139),
- regmap_reg_range(0x313e, 0x313f),
+ regmap_reg_range(0x3120, 0x312b),
+ regmap_reg_range(0x3134, 0x313b),
+ regmap_reg_range(0x313c, 0x313f),
regmap_reg_range(0x3400, 0x3401),
regmap_reg_range(0x3403, 0x3403),
regmap_reg_range(0x3410, 0x3417),
@@ -1190,10 +1187,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
regmap_reg_range(0x4030, 0x4030),
regmap_reg_range(0x4100, 0x4115),
regmap_reg_range(0x411a, 0x411f),
- regmap_reg_range(0x4122, 0x4127),
- regmap_reg_range(0x412a, 0x412b),
- regmap_reg_range(0x4136, 0x4139),
- regmap_reg_range(0x413e, 0x413f),
+ regmap_reg_range(0x4120, 0x412b),
+ regmap_reg_range(0x4134, 0x413b),
+ regmap_reg_range(0x413c, 0x413f),
regmap_reg_range(0x4400, 0x4401),
regmap_reg_range(0x4403, 0x4403),
regmap_reg_range(0x4410, 0x4417),
@@ -1220,10 +1216,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
regmap_reg_range(0x5030, 0x5030),
regmap_reg_range(0x5100, 0x5115),
regmap_reg_range(0x511a, 0x511f),
- regmap_reg_range(0x5122, 0x5127),
- regmap_reg_range(0x512a, 0x512b),
- regmap_reg_range(0x5136, 0x5139),
- regmap_reg_range(0x513e, 0x513f),
+ regmap_reg_range(0x5120, 0x512b),
+ regmap_reg_range(0x5134, 0x513b),
+ regmap_reg_range(0x513c, 0x513f),
regmap_reg_range(0x5400, 0x5401),
regmap_reg_range(0x5403, 0x5403),
regmap_reg_range(0x5410, 0x5417),
@@ -1250,10 +1245,9 @@ static const struct regmap_range ksz9896_valid_regs[] = {
regmap_reg_range(0x6030, 0x6030),
regmap_reg_range(0x6100, 0x6115),
regmap_reg_range(0x611a, 0x611f),
- regmap_reg_range(0x6122, 0x6127),
- regmap_reg_range(0x612a, 0x612b),
- regmap_reg_range(0x6136, 0x6139),
- regmap_reg_range(0x613e, 0x613f),
+ regmap_reg_range(0x6120, 0x612b),
+ regmap_reg_range(0x6134, 0x613b),
+ regmap_reg_range(0x613c, 0x613f),
regmap_reg_range(0x6300, 0x6301),
regmap_reg_range(0x6400, 0x6401),
regmap_reg_range(0x6403, 0x6403),
@@ -1345,6 +1339,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.supports_rgmii = {false, false, true},
.internal_phy = {true, true, false},
.gbit_capable = {false, false, true},
+ .ptp_capable = true,
.wr_table = &ksz8563_register_set,
.rd_table = &ksz8563_register_set,
},
@@ -1556,6 +1551,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.internal_phy = {true, true, true, true,
true, false, false},
.gbit_capable = {true, true, true, true, true, true, true},
+ .ptp_capable = true,
.wr_table = &ksz9477_register_set,
.rd_table = &ksz9477_register_set,
},
@@ -1683,6 +1679,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.supports_rgmii = {false, false, true},
.internal_phy = {true, true, false},
.gbit_capable = {true, true, true},
+ .ptp_capable = true,
},
[KSZ8567] = {
@@ -1718,6 +1715,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
true, false, false},
.gbit_capable = {false, false, false, false, false,
true, true},
+ .ptp_capable = true,
},
[KSZ9567] = {
@@ -1750,6 +1748,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.internal_phy = {true, true, true, true,
true, false, false},
.gbit_capable = {true, true, true, true, true, true, true},
+ .ptp_capable = true,
},
[LAN9370] = {
@@ -1779,6 +1778,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.supports_rmii = {false, false, false, false, true},
.supports_rgmii = {false, false, false, false, true},
.internal_phy = {true, true, true, true, false},
+ .ptp_capable = true,
},
[LAN9371] = {
@@ -1808,6 +1808,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
.supports_rmii = {false, false, false, false, true, true},
.supports_rgmii = {false, false, false, false, true, true},
.internal_phy = {true, true, true, true, false, false},
+ .ptp_capable = true,
},
[LAN9372] = {
@@ -1841,6 +1842,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
true, true, false, false},
.internal_phy = {true, true, true, true,
false, false, true, true},
+ .ptp_capable = true,
},
[LAN9373] = {
@@ -1874,6 +1876,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
true, true, false, false},
.internal_phy = {true, true, true, false,
false, false, true, true},
+ .ptp_capable = true,
},
[LAN9374] = {
@@ -1907,6 +1910,7 @@ const struct ksz_chip_data ksz_switch_chips[] = {
true, true, false, false},
.internal_phy = {true, true, true, true,
false, false, true, true},
+ .ptp_capable = true,
},
[LAN9646] = {
@@ -2550,7 +2554,11 @@ static int ksz_mdio_register(struct ksz_device *dev)
bus->read = ksz_sw_mdio_read;
bus->write = ksz_sw_mdio_write;
bus->name = "ksz user smi";
- snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index);
+ if (ds->dst->index != 0) {
+ snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d-%d", ds->dst->index, ds->index);
+ } else {
+ snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index);
+ }
}
ret = ksz_parse_dt_phy_config(dev, bus, mdio_np);
@@ -2811,16 +2819,21 @@ static int ksz_setup(struct dsa_switch *ds)
if (ret)
goto out_girq;
- ret = ksz_ptp_irq_setup(ds, dp->index);
- if (ret)
- goto out_pirq;
+ if (dev->info->ptp_capable) {
+ ret = ksz_ptp_irq_setup(ds, dp->index);
+ if (ret)
+ goto out_pirq;
+ }
}
}
- ret = ksz_ptp_clock_register(ds);
- if (ret) {
- dev_err(dev->dev, "Failed to register PTP clock: %d\n", ret);
- goto out_ptpirq;
+ if (dev->info->ptp_capable) {
+ ret = ksz_ptp_clock_register(ds);
+ if (ret) {
+ dev_err(dev->dev, "Failed to register PTP clock: %d\n",
+ ret);
+ goto out_ptpirq;
+ }
}
ret = ksz_mdio_register(dev);
@@ -2840,9 +2853,10 @@ static int ksz_setup(struct dsa_switch *ds)
return 0;
out_ptp_clock_unregister:
- ksz_ptp_clock_unregister(ds);
+ if (dev->info->ptp_capable)
+ ksz_ptp_clock_unregister(ds);
out_ptpirq:
- if (dev->irq > 0)
+ if (dev->irq > 0 && dev->info->ptp_capable)
dsa_switch_for_each_user_port(dp, dev->ds)
ksz_ptp_irq_free(ds, dp->index);
out_pirq:
@@ -2861,11 +2875,13 @@ static void ksz_teardown(struct dsa_switch *ds)
struct ksz_device *dev = ds->priv;
struct dsa_port *dp;
- ksz_ptp_clock_unregister(ds);
+ if (dev->info->ptp_capable)
+ ksz_ptp_clock_unregister(ds);
if (dev->irq > 0) {
dsa_switch_for_each_user_port(dp, dev->ds) {
- ksz_ptp_irq_free(ds, dp->index);
+ if (dev->info->ptp_capable)
+ ksz_ptp_irq_free(ds, dp->index);
ksz_irq_free(&dev->ports[dp->index].pirq);
}
@@ -3450,12 +3466,12 @@ static int ksz_max_mtu(struct dsa_switch *ds, int port)
return -EOPNOTSUPP;
}
-static int ksz_validate_eee(struct dsa_switch *ds, int port)
+static bool ksz_support_eee(struct dsa_switch *ds, int port)
{
struct ksz_device *dev = ds->priv;
if (!dev->info->internal_phy[port])
- return -EOPNOTSUPP;
+ return false;
switch (dev->chip_id) {
case KSZ8563_CHIP_ID:
@@ -3467,41 +3483,16 @@ static int ksz_validate_eee(struct dsa_switch *ds, int port)
case KSZ9896_CHIP_ID:
case KSZ9897_CHIP_ID:
case LAN9646_CHIP_ID:
- return 0;
+ return true;
}
- return -EOPNOTSUPP;
-}
-
-static int ksz_get_mac_eee(struct dsa_switch *ds, int port,
- struct ethtool_keee *e)
-{
- int ret;
-
- ret = ksz_validate_eee(ds, port);
- if (ret)
- return ret;
-
- /* There is no documented control of Tx LPI configuration. */
- e->tx_lpi_enabled = true;
-
- /* There is no documented control of Tx LPI timer. According to tests
- * Tx LPI timer seems to be set by default to minimal value.
- */
- e->tx_lpi_timer = 0;
-
- return 0;
+ return false;
}
static int ksz_set_mac_eee(struct dsa_switch *ds, int port,
struct ethtool_keee *e)
{
struct ksz_device *dev = ds->priv;
- int ret;
-
- ret = ksz_validate_eee(ds, port);
- if (ret)
- return ret;
if (!e->tx_lpi_enabled) {
dev_err(dev->dev, "Disabling EEE Tx LPI is not supported\n");
@@ -4599,6 +4590,23 @@ static int ksz_hsr_leave(struct dsa_switch *ds, int port,
return 0;
}
+static int ksz_suspend(struct dsa_switch *ds)
+{
+ struct ksz_device *dev = ds->priv;
+
+ cancel_delayed_work_sync(&dev->mib_read);
+ return 0;
+}
+
+static int ksz_resume(struct dsa_switch *ds)
+{
+ struct ksz_device *dev = ds->priv;
+
+ if (dev->mib_read_interval)
+ schedule_delayed_work(&dev->mib_read, dev->mib_read_interval);
+ return 0;
+}
+
static const struct dsa_switch_ops ksz_switch_ops = {
.get_tag_protocol = ksz_get_tag_protocol,
.connect_tag_protocol = ksz_connect_tag_protocol,
@@ -4639,6 +4647,8 @@ static const struct dsa_switch_ops ksz_switch_ops = {
.port_max_mtu = ksz_max_mtu,
.get_wol = ksz_get_wol,
.set_wol = ksz_set_wol,
+ .suspend = ksz_suspend,
+ .resume = ksz_resume,
.get_ts_info = ksz_get_ts_info,
.port_hwtstamp_get = ksz_hwtstamp_get,
.port_hwtstamp_set = ksz_hwtstamp_set,
@@ -4647,7 +4657,7 @@ static const struct dsa_switch_ops ksz_switch_ops = {
.cls_flower_add = ksz_cls_flower_add,
.cls_flower_del = ksz_cls_flower_del,
.port_setup_tc = ksz_setup_tc,
- .get_mac_eee = ksz_get_mac_eee,
+ .support_eee = ksz_support_eee,
.set_mac_eee = ksz_set_mac_eee,
.port_get_default_prio = ksz_port_get_default_prio,
.port_set_default_prio = ksz_port_set_default_prio,
@@ -5138,6 +5148,24 @@ void ksz_switch_remove(struct ksz_device *dev)
}
EXPORT_SYMBOL(ksz_switch_remove);
+#ifdef CONFIG_PM_SLEEP
+int ksz_switch_suspend(struct device *dev)
+{
+ struct ksz_device *priv = dev_get_drvdata(dev);
+
+ return dsa_switch_suspend(priv->ds);
+}
+EXPORT_SYMBOL(ksz_switch_suspend);
+
+int ksz_switch_resume(struct device *dev)
+{
+ struct ksz_device *priv = dev_get_drvdata(dev);
+
+ return dsa_switch_resume(priv->ds);
+}
+EXPORT_SYMBOL(ksz_switch_resume);
+#endif
+
MODULE_AUTHOR("Woojung Huh <Woojung.Huh@microchip.com>");
MODULE_DESCRIPTION("Microchip KSZ Series Switch DSA Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index b3bb75ca0796..af17a9c030d4 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -92,6 +92,7 @@ struct ksz_chip_data {
bool supports_rgmii[KSZ_MAX_NUM_PORTS];
bool internal_phy[KSZ_MAX_NUM_PORTS];
bool gbit_capable[KSZ_MAX_NUM_PORTS];
+ bool ptp_capable;
const struct regmap_access_table *wr_table;
const struct regmap_access_table *rd_table;
};
@@ -444,6 +445,8 @@ struct ksz_dev_ops {
struct ksz_device *ksz_switch_alloc(struct device *base, void *priv);
int ksz_switch_register(struct ksz_device *dev);
void ksz_switch_remove(struct ksz_device *dev);
+int ksz_switch_suspend(struct device *dev);
+int ksz_switch_resume(struct device *dev);
void ksz_init_mib_timer(struct ksz_device *dev);
bool ksz_is_port_mac_global_usable(struct dsa_switch *ds, int port);
diff --git a/drivers/net/dsa/microchip/ksz_spi.c b/drivers/net/dsa/microchip/ksz_spi.c
index 108a958dc356..b633d263098c 100644
--- a/drivers/net/dsa/microchip/ksz_spi.c
+++ b/drivers/net/dsa/microchip/ksz_spi.c
@@ -239,10 +239,14 @@ static const struct spi_device_id ksz_spi_ids[] = {
};
MODULE_DEVICE_TABLE(spi, ksz_spi_ids);
+static DEFINE_SIMPLE_DEV_PM_OPS(ksz_spi_pm_ops,
+ ksz_switch_suspend, ksz_switch_resume);
+
static struct spi_driver ksz_spi_driver = {
.driver = {
.name = "ksz-switch",
.of_match_table = ksz_dt_ids,
+ .pm = &ksz_spi_pm_ops,
},
.id_table = ksz_spi_ids,
.probe = ksz_spi_probe,
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index b7652efd632e..b1ae3b9de3d1 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/* Microchip LAN937X switch driver main logic
- * Copyright (C) 2019-2022 Microchip Technology Inc.
+ * Copyright (C) 2019-2024 Microchip Technology Inc.
*/
#include <linux/kernel.h>
#include <linux/module.h>
@@ -461,10 +461,66 @@ int lan937x_change_mtu(struct ksz_device *dev, int port, int new_mtu)
int lan937x_set_ageing_time(struct ksz_device *dev, unsigned int msecs)
{
- u32 secs = msecs / 1000;
- u32 value;
+ u8 data, mult, value8;
+ bool in_msec = false;
+ u32 max_val, value;
+ u32 secs = msecs;
int ret;
+#define MAX_TIMER_VAL ((1 << 20) - 1)
+
+ /* The aging timer comprises a 3-bit multiplier and a 20-bit second
+ * value. Either of them cannot be zero. The maximum timer is then
+ * 7 * 1048575 = 7340025 seconds. As this value is too large for
+ * practical use it can be interpreted as microseconds, making the
+ * maximum timer 7340 seconds with finer control. This allows for
+ * maximum 122 minutes compared to 29 minutes in KSZ9477 switch.
+ */
+ if (msecs % 1000)
+ in_msec = true;
+ else
+ secs /= 1000;
+ if (!secs)
+ secs = 1;
+
+ /* Return error if too large. */
+ else if (secs > 7 * MAX_TIMER_VAL)
+ return -EINVAL;
+
+ /* Configure how to interpret the number value. */
+ ret = ksz_rmw8(dev, REG_SW_LUE_CTRL_2, SW_AGE_CNT_IN_MICROSEC,
+ in_msec ? SW_AGE_CNT_IN_MICROSEC : 0);
+ if (ret < 0)
+ return ret;
+
+ ret = ksz_read8(dev, REG_SW_LUE_CTRL_0, &value8);
+ if (ret < 0)
+ return ret;
+
+ /* Check whether there is need to update the multiplier. */
+ mult = FIELD_GET(SW_AGE_CNT_M, value8);
+ max_val = MAX_TIMER_VAL;
+ if (mult > 0) {
+ /* Try to use the same multiplier already in the register as
+ * the hardware default uses multiplier 4 and 75 seconds for
+ * 300 seconds.
+ */
+ max_val = DIV_ROUND_UP(secs, mult);
+ if (max_val > MAX_TIMER_VAL || max_val * mult != secs)
+ max_val = MAX_TIMER_VAL;
+ }
+
+ data = DIV_ROUND_UP(secs, max_val);
+ if (mult != data) {
+ value8 &= ~SW_AGE_CNT_M;
+ value8 |= FIELD_PREP(SW_AGE_CNT_M, data);
+ ret = ksz_write8(dev, REG_SW_LUE_CTRL_0, value8);
+ if (ret < 0)
+ return ret;
+ }
+
+ secs = DIV_ROUND_UP(secs, data);
+
value = FIELD_GET(SW_AGE_PERIOD_7_0_M, secs);
ret = ksz_write8(dev, REG_SW_AGE_PERIOD__1, value);
diff --git a/drivers/net/dsa/microchip/lan937x_reg.h b/drivers/net/dsa/microchip/lan937x_reg.h
index 4ec93e421da4..72042fd64e5b 100644
--- a/drivers/net/dsa/microchip/lan937x_reg.h
+++ b/drivers/net/dsa/microchip/lan937x_reg.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Microchip LAN937X switch register definitions
- * Copyright (C) 2019-2021 Microchip Technology Inc.
+ * Copyright (C) 2019-2024 Microchip Technology Inc.
*/
#ifndef __LAN937X_REG_H
#define __LAN937X_REG_H
@@ -56,8 +56,7 @@
#define SW_VLAN_ENABLE BIT(7)
#define SW_DROP_INVALID_VID BIT(6)
-#define SW_AGE_CNT_M 0x7
-#define SW_AGE_CNT_S 3
+#define SW_AGE_CNT_M GENMASK(5, 3)
#define SW_RESV_MCAST_ENABLE BIT(2)
#define REG_SW_LUE_CTRL_1 0x0311
@@ -70,6 +69,10 @@
#define SW_FAST_AGING BIT(1)
#define SW_LINK_AUTO_AGING BIT(0)
+#define REG_SW_LUE_CTRL_2 0x0312
+
+#define SW_AGE_CNT_IN_MICROSEC BIT(7)
+
#define REG_SW_AGE_PERIOD__1 0x0313
#define SW_AGE_PERIOD_7_0_M GENMASK(7, 0)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 086b8b3d5b40..d2d0f091e49e 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -3085,18 +3085,6 @@ mt753x_setup(struct dsa_switch *ds)
return ret;
}
-static int mt753x_get_mac_eee(struct dsa_switch *ds, int port,
- struct ethtool_keee *e)
-{
- struct mt7530_priv *priv = ds->priv;
- u32 eeecr = mt7530_read(priv, MT753X_PMEEECR_P(port));
-
- e->tx_lpi_enabled = !(eeecr & LPI_MODE_EN);
- e->tx_lpi_timer = LPI_THRESH_GET(eeecr);
-
- return 0;
-}
-
static int mt753x_set_mac_eee(struct dsa_switch *ds, int port,
struct ethtool_keee *e)
{
@@ -3238,7 +3226,7 @@ const struct dsa_switch_ops mt7530_switch_ops = {
.port_mirror_add = mt753x_port_mirror_add,
.port_mirror_del = mt753x_port_mirror_del,
.phylink_get_caps = mt753x_phylink_get_caps,
- .get_mac_eee = mt753x_get_mac_eee,
+ .support_eee = dsa_supports_eee,
.set_mac_eee = mt753x_set_mac_eee,
.conduit_state_change = mt753x_conduit_state_change,
.port_setup_tc = mt753x_setup_tc,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 3a792f79270d..35ae084af166 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -1289,9 +1289,6 @@ static size_t mv88e6095_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data)
{
- if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_PORT)))
- return 0;
-
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0,
MV88E6XXX_G1_STATS_OP_HIST_RX);
return 1;
@@ -1301,9 +1298,6 @@ static size_t mv88e6250_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data)
{
- if (!(stat->type & STATS_TYPE_BANK0))
- return 0;
-
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port, 0,
MV88E6XXX_G1_STATS_OP_HIST_RX);
return 1;
@@ -1313,9 +1307,6 @@ static size_t mv88e6320_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data)
{
- if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_BANK1)))
- return 0;
-
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
MV88E6XXX_G1_STATS_OP_BANK_1_BIT_9,
MV88E6XXX_G1_STATS_OP_HIST_RX);
@@ -1326,9 +1317,6 @@ static size_t mv88e6390_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
const struct mv88e6xxx_hw_stat *stat,
uint64_t *data)
{
- if (!(stat->type & (STATS_TYPE_BANK0 | STATS_TYPE_BANK1)))
- return 0;
-
*data = _mv88e6xxx_get_ethtool_stat(chip, stat, port,
MV88E6XXX_G1_STATS_OP_BANK_1_BIT_10,
0);
@@ -1341,6 +1329,9 @@ static size_t mv88e6xxx_stats_get_stat(struct mv88e6xxx_chip *chip, int port,
{
int ret = 0;
+ if (!(stat->type & chip->info->stats_type))
+ return 0;
+
if (chip->info->ops->stats_get_stat) {
mv88e6xxx_reg_lock(chip);
ret = chip->info->ops->stats_get_stat(chip, port, stat, data);
@@ -1522,13 +1513,6 @@ static void mv88e6xxx_get_regs(struct dsa_switch *ds, int port,
mv88e6xxx_reg_unlock(chip);
}
-static int mv88e6xxx_get_mac_eee(struct dsa_switch *ds, int port,
- struct ethtool_keee *e)
-{
- /* Nothing to do on the port's MAC */
- return 0;
-}
-
static int mv88e6xxx_set_mac_eee(struct dsa_switch *ds, int port,
struct ethtool_keee *e)
{
@@ -5645,6 +5629,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 5,
+ .stats_type = STATS_TYPE_BANK0,
.atu_move_port_mask = 0xf,
.dual_chip = true,
.ops = &mv88e6250_ops,
@@ -5665,6 +5650,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 5,
+ .stats_type = STATS_TYPE_BANK0,
.atu_move_port_mask = 0xf,
.dual_chip = true,
.ops = &mv88e6250_ops,
@@ -5687,6 +5673,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 8,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -5708,6 +5695,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 8,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.multi_chip = true,
.ops = &mv88e6095_ops,
@@ -5730,6 +5718,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 8,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -5754,6 +5743,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -5776,6 +5766,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 9,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.multi_chip = true,
.ops = &mv88e6131_ops,
@@ -5800,6 +5791,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.atu_move_port_mask = 0x1f,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.pvt = true,
.multi_chip = true,
.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
@@ -5823,6 +5815,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -5848,6 +5841,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -5872,6 +5866,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -5897,6 +5892,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -5921,6 +5917,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -5946,6 +5943,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -5968,6 +5966,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.global2_addr = 0x1c,
.age_time_coeff = 15000,
.g1_irqs = 8,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.multi_chip = true,
.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
@@ -5992,6 +5991,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 3750,
.g1_irqs = 9,
.g2_irqs = 14,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.pvt = true,
.multi_chip = true,
.atu_move_port_mask = 0x1f,
@@ -6016,6 +6016,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 3750,
.g1_irqs = 9,
.g2_irqs = 14,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0x1f,
.pvt = true,
.multi_chip = true,
@@ -6039,6 +6040,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 3750,
.g1_irqs = 9,
.g2_irqs = 14,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0x1f,
.pvt = true,
.multi_chip = true,
@@ -6063,6 +6065,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 3750,
.g1_irqs = 10,
.g2_irqs = 14,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0x1f,
.pvt = true,
.multi_chip = true,
@@ -6087,6 +6090,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 3750,
.g1_irqs = 10,
.g2_irqs = 14,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0x1f,
.pvt = true,
.multi_chip = true,
@@ -6114,6 +6118,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0,
.atu_move_port_mask = 0xf,
.dual_chip = true,
.ptp_support = true,
@@ -6138,6 +6143,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -6161,6 +6167,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0,
.atu_move_port_mask = 0xf,
.dual_chip = true,
.ptp_support = true,
@@ -6184,6 +6191,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 3750,
.g1_irqs = 9,
.g2_irqs = 14,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0x1f,
.pvt = true,
.multi_chip = true,
@@ -6208,6 +6216,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 8,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -6233,6 +6242,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 8,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0xf,
.multi_chip = true,
.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
@@ -6259,6 +6269,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.atu_move_port_mask = 0x1f,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.pvt = true,
.multi_chip = true,
.edsa_support = MV88E6XXX_EDSA_SUPPORTED,
@@ -6283,6 +6294,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -6307,6 +6319,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -6332,6 +6345,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 15000,
.g1_irqs = 9,
.g2_irqs = 10,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_PORT,
.atu_move_port_mask = 0xf,
.pvt = true,
.multi_chip = true,
@@ -6359,6 +6373,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 3750,
.g1_irqs = 10,
.g2_irqs = 14,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0x1f,
.pvt = true,
.multi_chip = true,
@@ -6383,6 +6398,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 3750,
.g1_irqs = 9,
.g2_irqs = 14,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0x1f,
.pvt = true,
.multi_chip = true,
@@ -6408,6 +6424,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 3750,
.g1_irqs = 9,
.g2_irqs = 14,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0x1f,
.pvt = true,
.multi_chip = true,
@@ -6433,6 +6450,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.age_time_coeff = 3750,
.g1_irqs = 10,
.g2_irqs = 14,
+ .stats_type = STATS_TYPE_BANK0 | STATS_TYPE_BANK1,
.atu_move_port_mask = 0x1f,
.pvt = true,
.multi_chip = true,
@@ -7074,7 +7092,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
.get_sset_count = mv88e6xxx_get_sset_count,
.port_max_mtu = mv88e6xxx_get_max_mtu,
.port_change_mtu = mv88e6xxx_change_mtu,
- .get_mac_eee = mv88e6xxx_get_mac_eee,
+ .support_eee = dsa_supports_eee,
.set_mac_eee = mv88e6xxx_set_mac_eee,
.get_eeprom_len = mv88e6xxx_get_eeprom_len,
.get_eeprom = mv88e6xxx_get_eeprom,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index 9fe8e8a7856b..86bf113c9bfa 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -144,6 +144,7 @@ struct mv88e6xxx_info {
unsigned int age_time_coeff;
unsigned int g1_irqs;
unsigned int g2_irqs;
+ int stats_type;
bool pvt;
/* Mark certain ports as invalid. This is required for example for the
diff --git a/drivers/net/dsa/ocelot/felix_vsc9959.c b/drivers/net/dsa/ocelot/felix_vsc9959.c
index 0102a82e88cc..940f1b71226d 100644
--- a/drivers/net/dsa/ocelot/felix_vsc9959.c
+++ b/drivers/net/dsa/ocelot/felix_vsc9959.c
@@ -24,7 +24,7 @@
#define VSC9959_NUM_PORTS 6
#define VSC9959_TAS_GCL_ENTRY_MAX 63
-#define VSC9959_TAS_MIN_GATE_LEN_NS 33
+#define VSC9959_TAS_MIN_GATE_LEN_NS 35
#define VSC9959_VCAP_POLICER_BASE 63
#define VSC9959_VCAP_POLICER_MAX 383
#define VSC9959_SWITCH_PCI_BAR 4
@@ -1056,11 +1056,15 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
mdiobus_free(felix->imdio);
}
-/* The switch considers any frame (regardless of size) as eligible for
- * transmission if the traffic class gate is open for at least 33 ns.
+/* The switch considers any frame (regardless of size) as eligible
+ * for transmission if the traffic class gate is open for at least
+ * VSC9959_TAS_MIN_GATE_LEN_NS.
+ *
* Overruns are prevented by cropping an interval at the end of the gate time
- * slot for which egress scheduling is blocked, but we need to still keep 33 ns
- * available for one packet to be transmitted, otherwise the port tc will hang.
+ * slot for which egress scheduling is blocked, but we need to still keep
+ * VSC9959_TAS_MIN_GATE_LEN_NS available for one packet to be transmitted,
+ * otherwise the port tc will hang.
+ *
* This function returns the size of a gate interval that remains available for
* setting the guard band, after reserving the space for one egress frame.
*/
@@ -1303,7 +1307,8 @@ static void vsc9959_tas_guard_bands_update(struct ocelot *ocelot, int port)
* per-tc static guard band lengths, so it reduces the
* useful gate interval length. Therefore, be careful
* to calculate a guard band (and therefore max_sdu)
- * that still leaves 33 ns available in the time slot.
+ * that still leaves VSC9959_TAS_MIN_GATE_LEN_NS
+ * available in the time slot.
*/
max_sdu = div_u64(remaining_gate_len_ps, picos_per_byte);
/* A TC gate may be completely closed, which is a
diff --git a/drivers/net/dsa/ocelot/ocelot_ext.c b/drivers/net/dsa/ocelot/ocelot_ext.c
index 450bda18ef37..d5c557a20292 100644
--- a/drivers/net/dsa/ocelot/ocelot_ext.c
+++ b/drivers/net/dsa/ocelot/ocelot_ext.c
@@ -109,4 +109,4 @@ module_platform_driver(ocelot_ext_switch_driver);
MODULE_DESCRIPTION("External Ocelot Switch driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(MFD_OCELOT);
+MODULE_IMPORT_NS("MFD_OCELOT");
diff --git a/drivers/net/dsa/qca/qca8k-8xxx.c b/drivers/net/dsa/qca/qca8k-8xxx.c
index 59b4a7240b58..750fc76a6e11 100644
--- a/drivers/net/dsa/qca/qca8k-8xxx.c
+++ b/drivers/net/dsa/qca/qca8k-8xxx.c
@@ -342,7 +342,7 @@ static int qca8k_read_eth(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
dev_queue_xmit(skb);
ret = wait_for_completion_timeout(&mgmt_eth_data->rw_done,
- msecs_to_jiffies(QCA8K_ETHERNET_TIMEOUT));
+ QCA8K_ETHERNET_TIMEOUT);
*val = mgmt_eth_data->data[0];
if (len > QCA_HDR_MGMT_DATA1_LEN)
@@ -394,7 +394,7 @@ static int qca8k_write_eth(struct qca8k_priv *priv, u32 reg, u32 *val, int len)
dev_queue_xmit(skb);
ret = wait_for_completion_timeout(&mgmt_eth_data->rw_done,
- msecs_to_jiffies(QCA8K_ETHERNET_TIMEOUT));
+ QCA8K_ETHERNET_TIMEOUT);
ack = mgmt_eth_data->ack;
@@ -1019,7 +1019,7 @@ qca8k_setup_mdio_bus(struct qca8k_priv *priv)
of_get_phy_mode(port, &mode);
- if (of_property_read_bool(port, "phy-handle") &&
+ if (of_property_present(port, "phy-handle") &&
mode != PHY_INTERFACE_MODE_INTERNAL)
external_mdio_mask |= BIT(reg);
else
@@ -2016,7 +2016,7 @@ static const struct dsa_switch_ops qca8k_switch_ops = {
.get_ethtool_stats = qca8k_get_ethtool_stats,
.get_sset_count = qca8k_get_sset_count,
.set_ageing_time = qca8k_set_ageing_time,
- .get_mac_eee = qca8k_get_mac_eee,
+ .support_eee = dsa_supports_eee,
.set_mac_eee = qca8k_set_mac_eee,
.port_enable = qca8k_port_enable,
.port_disable = qca8k_port_disable,
diff --git a/drivers/net/dsa/qca/qca8k-common.c b/drivers/net/dsa/qca/qca8k-common.c
index 560c74c4ac3d..13005f10edb7 100644
--- a/drivers/net/dsa/qca/qca8k-common.c
+++ b/drivers/net/dsa/qca/qca8k-common.c
@@ -557,13 +557,6 @@ exit:
return ret;
}
-int qca8k_get_mac_eee(struct dsa_switch *ds, int port,
- struct ethtool_keee *e)
-{
- /* Nothing to do on the port's MAC */
- return 0;
-}
-
static int qca8k_port_configure_learning(struct dsa_switch *ds, int port,
bool learning)
{
diff --git a/drivers/net/dsa/qca/qca8k.h b/drivers/net/dsa/qca/qca8k.h
index 3664a2e2f1f6..d046679265fa 100644
--- a/drivers/net/dsa/qca/qca8k.h
+++ b/drivers/net/dsa/qca/qca8k.h
@@ -16,7 +16,7 @@
#define QCA8K_ETHERNET_MDIO_PRIORITY 7
#define QCA8K_ETHERNET_PHY_PRIORITY 6
-#define QCA8K_ETHERNET_TIMEOUT 5
+#define QCA8K_ETHERNET_TIMEOUT msecs_to_jiffies(5)
#define QCA8K_NUM_PORTS 7
#define QCA8K_NUM_CPU_PORTS 2
@@ -520,7 +520,6 @@ int qca8k_get_sset_count(struct dsa_switch *ds, int port, int sset);
/* Common eee function */
int qca8k_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *eee);
-int qca8k_get_mac_eee(struct dsa_switch *ds, int port, struct ethtool_keee *e);
/* Common bridge function */
void qca8k_port_stp_state_set(struct dsa_switch *ds, int port, u8 state);
diff --git a/drivers/net/dsa/realtek/realtek-mdio.c b/drivers/net/dsa/realtek/realtek-mdio.c
index 5f545dda702b..a5e7dff96e91 100644
--- a/drivers/net/dsa/realtek/realtek-mdio.c
+++ b/drivers/net/dsa/realtek/realtek-mdio.c
@@ -140,7 +140,7 @@ int realtek_mdio_probe(struct mdio_device *mdiodev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(realtek_mdio_probe, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(realtek_mdio_probe, "REALTEK_DSA");
/**
* realtek_mdio_remove() - Remove the driver of an MDIO-connected switch
@@ -163,7 +163,7 @@ void realtek_mdio_remove(struct mdio_device *mdiodev)
rtl83xx_remove(priv);
}
-EXPORT_SYMBOL_NS_GPL(realtek_mdio_remove, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(realtek_mdio_remove, "REALTEK_DSA");
/**
* realtek_mdio_shutdown() - Shutdown the driver of a MDIO-connected switch
@@ -184,4 +184,4 @@ void realtek_mdio_shutdown(struct mdio_device *mdiodev)
rtl83xx_shutdown(priv);
}
-EXPORT_SYMBOL_NS_GPL(realtek_mdio_shutdown, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(realtek_mdio_shutdown, "REALTEK_DSA");
diff --git a/drivers/net/dsa/realtek/realtek-smi.c b/drivers/net/dsa/realtek/realtek-smi.c
index d750bddf27b4..972e22218418 100644
--- a/drivers/net/dsa/realtek/realtek-smi.c
+++ b/drivers/net/dsa/realtek/realtek-smi.c
@@ -361,7 +361,7 @@ int realtek_smi_probe(struct platform_device *pdev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(realtek_smi_probe, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(realtek_smi_probe, "REALTEK_DSA");
/**
* realtek_smi_remove() - Remove the driver of a SMI-connected switch
@@ -384,7 +384,7 @@ void realtek_smi_remove(struct platform_device *pdev)
rtl83xx_remove(priv);
}
-EXPORT_SYMBOL_NS_GPL(realtek_smi_remove, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(realtek_smi_remove, "REALTEK_DSA");
/**
* realtek_smi_shutdown() - Shutdown the driver of a SMI-connected switch
@@ -405,4 +405,4 @@ void realtek_smi_shutdown(struct platform_device *pdev)
rtl83xx_shutdown(priv);
}
-EXPORT_SYMBOL_NS_GPL(realtek_smi_shutdown, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(realtek_smi_shutdown, "REALTEK_DSA");
diff --git a/drivers/net/dsa/realtek/rtl8365mb.c b/drivers/net/dsa/realtek/rtl8365mb.c
index 6b9dbdb00941..7e96355c28bd 100644
--- a/drivers/net/dsa/realtek/rtl8365mb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb.c
@@ -2206,4 +2206,4 @@ module_exit(rtl8365mb_exit);
MODULE_AUTHOR("Alvin Šipraga <alsi@bang-olufsen.dk>");
MODULE_DESCRIPTION("Driver for RTL8365MB-VC ethernet switch");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(REALTEK_DSA);
+MODULE_IMPORT_NS("REALTEK_DSA");
diff --git a/drivers/net/dsa/realtek/rtl8366-core.c b/drivers/net/dsa/realtek/rtl8366-core.c
index 7c6520ba3a26..047feeed96a2 100644
--- a/drivers/net/dsa/realtek/rtl8366-core.c
+++ b/drivers/net/dsa/realtek/rtl8366-core.c
@@ -34,7 +34,7 @@ int rtl8366_mc_is_used(struct realtek_priv *priv, int mc_index, int *used)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_mc_is_used, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_mc_is_used, "REALTEK_DSA");
/**
* rtl8366_obtain_mc() - retrieve or allocate a VLAN member configuration
@@ -187,7 +187,7 @@ int rtl8366_set_vlan(struct realtek_priv *priv, int vid, u32 member,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_set_vlan, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_set_vlan, "REALTEK_DSA");
int rtl8366_set_pvid(struct realtek_priv *priv, unsigned int port,
unsigned int vid)
@@ -217,7 +217,7 @@ int rtl8366_set_pvid(struct realtek_priv *priv, unsigned int port,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_set_pvid, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_set_pvid, "REALTEK_DSA");
int rtl8366_enable_vlan4k(struct realtek_priv *priv, bool enable)
{
@@ -243,7 +243,7 @@ int rtl8366_enable_vlan4k(struct realtek_priv *priv, bool enable)
priv->vlan4k_enabled = enable;
return 0;
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_enable_vlan4k, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_enable_vlan4k, "REALTEK_DSA");
int rtl8366_enable_vlan(struct realtek_priv *priv, bool enable)
{
@@ -265,7 +265,7 @@ int rtl8366_enable_vlan(struct realtek_priv *priv, bool enable)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_enable_vlan, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_enable_vlan, "REALTEK_DSA");
int rtl8366_reset_vlan(struct realtek_priv *priv)
{
@@ -290,7 +290,7 @@ int rtl8366_reset_vlan(struct realtek_priv *priv)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_reset_vlan, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_reset_vlan, "REALTEK_DSA");
int rtl8366_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
@@ -345,7 +345,7 @@ int rtl8366_vlan_add(struct dsa_switch *ds, int port,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_vlan_add, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_vlan_add, "REALTEK_DSA");
int rtl8366_vlan_del(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan)
@@ -389,7 +389,7 @@ int rtl8366_vlan_del(struct dsa_switch *ds, int port,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_vlan_del, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_vlan_del, "REALTEK_DSA");
void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
uint8_t *data)
@@ -403,7 +403,7 @@ void rtl8366_get_strings(struct dsa_switch *ds, int port, u32 stringset,
for (i = 0; i < priv->num_mib_counters; i++)
ethtool_puts(&data, priv->mib_counters[i].name);
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_get_strings, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_get_strings, "REALTEK_DSA");
int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
{
@@ -417,7 +417,7 @@ int rtl8366_get_sset_count(struct dsa_switch *ds, int port, int sset)
return priv->num_mib_counters;
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_get_sset_count, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_get_sset_count, "REALTEK_DSA");
void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
{
@@ -441,4 +441,4 @@ void rtl8366_get_ethtool_stats(struct dsa_switch *ds, int port, uint64_t *data)
data[i] = mibvalue;
}
}
-EXPORT_SYMBOL_NS_GPL(rtl8366_get_ethtool_stats, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl8366_get_ethtool_stats, "REALTEK_DSA");
diff --git a/drivers/net/dsa/realtek/rtl8366rb.c b/drivers/net/dsa/realtek/rtl8366rb.c
index 6ba03f81c882..23374178a176 100644
--- a/drivers/net/dsa/realtek/rtl8366rb.c
+++ b/drivers/net/dsa/realtek/rtl8366rb.c
@@ -2144,4 +2144,4 @@ module_exit(rtl8366rb_exit);
MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
MODULE_DESCRIPTION("Driver for RTL8366RB ethernet switch");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(REALTEK_DSA);
+MODULE_IMPORT_NS("REALTEK_DSA");
diff --git a/drivers/net/dsa/realtek/rtl83xx.c b/drivers/net/dsa/realtek/rtl83xx.c
index 3c5018d5e1f9..2b9bd4462714 100644
--- a/drivers/net/dsa/realtek/rtl83xx.c
+++ b/drivers/net/dsa/realtek/rtl83xx.c
@@ -25,7 +25,7 @@ void rtl83xx_lock(void *ctx)
mutex_lock(&priv->map_lock);
}
-EXPORT_SYMBOL_NS_GPL(rtl83xx_lock, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl83xx_lock, "REALTEK_DSA");
/**
* rtl83xx_unlock() - Unlocks the mutex used by regmaps
@@ -42,7 +42,7 @@ void rtl83xx_unlock(void *ctx)
mutex_unlock(&priv->map_lock);
}
-EXPORT_SYMBOL_NS_GPL(rtl83xx_unlock, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl83xx_unlock, "REALTEK_DSA");
static int rtl83xx_user_mdio_read(struct mii_bus *bus, int addr, int regnum)
{
@@ -109,7 +109,7 @@ err_put_node:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(rtl83xx_setup_user_mdio, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl83xx_setup_user_mdio, "REALTEK_DSA");
/**
* rtl83xx_probe() - probe a Realtek switch
@@ -208,7 +208,7 @@ rtl83xx_probe(struct device *dev,
return priv;
}
-EXPORT_SYMBOL_NS_GPL(rtl83xx_probe, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl83xx_probe, "REALTEK_DSA");
/**
* rtl83xx_register_switch() - detects and register a switch
@@ -245,7 +245,7 @@ int rtl83xx_register_switch(struct realtek_priv *priv)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(rtl83xx_register_switch, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl83xx_register_switch, "REALTEK_DSA");
/**
* rtl83xx_unregister_switch() - unregister a switch
@@ -262,7 +262,7 @@ void rtl83xx_unregister_switch(struct realtek_priv *priv)
dsa_unregister_switch(ds);
}
-EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_switch, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl83xx_unregister_switch, "REALTEK_DSA");
/**
* rtl83xx_shutdown() - shutdown a switch
@@ -283,7 +283,7 @@ void rtl83xx_shutdown(struct realtek_priv *priv)
dev_set_drvdata(priv->dev, NULL);
}
-EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, "REALTEK_DSA");
/**
* rtl83xx_remove() - Cleanup a realtek switch driver
@@ -297,7 +297,7 @@ EXPORT_SYMBOL_NS_GPL(rtl83xx_shutdown, REALTEK_DSA);
void rtl83xx_remove(struct realtek_priv *priv)
{
}
-EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, REALTEK_DSA);
+EXPORT_SYMBOL_NS_GPL(rtl83xx_remove, "REALTEK_DSA");
void rtl83xx_reset_assert(struct realtek_priv *priv)
{
diff --git a/drivers/net/dsa/sja1105/sja1105_static_config.c b/drivers/net/dsa/sja1105/sja1105_static_config.c
index baba204ad62f..3d790f8c6f4d 100644
--- a/drivers/net/dsa/sja1105/sja1105_static_config.c
+++ b/drivers/net/dsa/sja1105/sja1105_static_config.c
@@ -26,12 +26,8 @@ void sja1105_pack(void *buf, const u64 *val, int start, int end, size_t len)
pr_err("Start bit (%d) expected to be larger than end (%d)\n",
start, end);
} else if (rc == -ERANGE) {
- if ((start - end + 1) > 64)
- pr_err("Field %d-%d too large for 64 bits!\n",
- start, end);
- else
- pr_err("Cannot store %llx inside bits %d-%d (would truncate)\n",
- *val, start, end);
+ pr_err("Field %d-%d too large for 64 bits!\n",
+ start, end);
}
dump_stack();
}
diff --git a/drivers/net/ethernet/Kconfig b/drivers/net/ethernet/Kconfig
index 9a542e3c9b05..977b42bc1e8c 100644
--- a/drivers/net/ethernet/Kconfig
+++ b/drivers/net/ethernet/Kconfig
@@ -159,7 +159,7 @@ config ETHOC
Say Y here if you want to use the OpenCores 10/100 Mbps Ethernet MAC.
config OA_TC6
- tristate "OPEN Alliance TC6 10BASE-T1x MAC-PHY support"
+ tristate "OPEN Alliance TC6 10BASE-T1x MAC-PHY support" if COMPILE_TEST
depends on SPI
select PHYLIB
help
diff --git a/drivers/net/ethernet/amazon/ena/ena_netdev.c b/drivers/net/ethernet/amazon/ena/ena_netdev.c
index 63c8a2328142..c1295dfad0d0 100644
--- a/drivers/net/ethernet/amazon/ena/ena_netdev.c
+++ b/drivers/net/ethernet/amazon/ena/ena_netdev.c
@@ -74,7 +74,7 @@ static void ena_tx_timeout(struct net_device *dev, unsigned int txqueue)
if (threshold < time_since_last_napi && napi_scheduled) {
netdev_err(dev,
"napi handler hasn't been called for a long time but is scheduled\n");
- reset_reason = ENA_REGS_RESET_SUSPECTED_POLL_STARVATION;
+ reset_reason = ENA_REGS_RESET_SUSPECTED_POLL_STARVATION;
}
schedule_reset:
/* Change the state of the device to trigger reset
diff --git a/drivers/net/ethernet/amd/pds_core/devlink.c b/drivers/net/ethernet/amd/pds_core/devlink.c
index 2681889162a2..44971e71991f 100644
--- a/drivers/net/ethernet/amd/pds_core/devlink.c
+++ b/drivers/net/ethernet/amd/pds_core/devlink.c
@@ -118,7 +118,7 @@ int pdsc_dl_info_get(struct devlink *dl, struct devlink_info_req *req,
if (err && err != -EIO)
return err;
- listlen = fw_list.num_fw_slots;
+ listlen = min(fw_list.num_fw_slots, ARRAY_SIZE(fw_list.fw_names));
for (i = 0; i < listlen; i++) {
if (i < ARRAY_SIZE(fw_slotnames))
strscpy(buf, fw_slotnames[i], sizeof(buf));
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
index e641dbbea1e2..b854b6b42d77 100644
--- a/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
+++ b/drivers/net/ethernet/apm/xgene/xgene_enet_hw.c
@@ -421,18 +421,12 @@ static void xgene_enet_configure_clock(struct xgene_enet_pdata *pdata)
if (dev->of_node) {
struct clk *parent = clk_get_parent(pdata->clk);
+ long rate = rgmii_clock(pdata->phy_speed);
- switch (pdata->phy_speed) {
- case SPEED_10:
- clk_set_rate(parent, 2500000);
- break;
- case SPEED_100:
- clk_set_rate(parent, 25000000);
- break;
- default:
- clk_set_rate(parent, 125000000);
- break;
- }
+ if (rate < 0)
+ rate = 125000000;
+
+ clk_set_rate(parent, rate);
}
#ifdef CONFIG_ACPI
else {
diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c
index 42672c63f108..bc4e1f3b3752 100644
--- a/drivers/net/ethernet/broadcom/bcmsysport.c
+++ b/drivers/net/ethernet/broadcom/bcmsysport.c
@@ -1933,7 +1933,11 @@ static int bcm_sysport_open(struct net_device *dev)
unsigned int i;
int ret;
- clk_prepare_enable(priv->clk);
+ ret = clk_prepare_enable(priv->clk);
+ if (ret) {
+ netdev_err(dev, "could not enable priv clock\n");
+ return ret;
+ }
/* Reset UniMAC */
umac_reset(priv);
@@ -2591,7 +2595,11 @@ static int bcm_sysport_probe(struct platform_device *pdev)
goto err_deregister_notifier;
}
- clk_prepare_enable(priv->clk);
+ ret = clk_prepare_enable(priv->clk);
+ if (ret) {
+ dev_err(&pdev->dev, "could not enable priv clock\n");
+ goto err_deregister_netdev;
+ }
priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK;
dev_info(&pdev->dev,
@@ -2605,6 +2613,8 @@ static int bcm_sysport_probe(struct platform_device *pdev)
return 0;
+err_deregister_netdev:
+ unregister_netdev(dev);
err_deregister_notifier:
unregister_netdevice_notifier(&priv->netdev_notifier);
err_deregister_fixed_link:
@@ -2774,7 +2784,12 @@ static int __maybe_unused bcm_sysport_resume(struct device *d)
if (!netif_running(dev))
return 0;
- clk_prepare_enable(priv->clk);
+ ret = clk_prepare_enable(priv->clk);
+ if (ret) {
+ netdev_err(dev, "could not enable priv clock\n");
+ return ret;
+ }
+
if (priv->wolopts)
clk_disable_unprepare(priv->wol_clk);
diff --git a/drivers/net/ethernet/broadcom/bgmac-platform.c b/drivers/net/ethernet/broadcom/bgmac-platform.c
index ecce23cecbea..4e266ce41180 100644
--- a/drivers/net/ethernet/broadcom/bgmac-platform.c
+++ b/drivers/net/ethernet/broadcom/bgmac-platform.c
@@ -171,6 +171,7 @@ static int platform_phy_connect(struct bgmac *bgmac)
static int bgmac_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
+ struct device_node *phy_node;
struct bgmac *bgmac;
struct resource *regs;
int ret;
@@ -236,7 +237,9 @@ static int bgmac_probe(struct platform_device *pdev)
bgmac->cco_ctl_maskset = platform_bgmac_cco_ctl_maskset;
bgmac->get_bus_clock = platform_bgmac_get_bus_clock;
bgmac->cmn_maskset32 = platform_bgmac_cmn_maskset32;
- if (of_parse_phandle(np, "phy-handle", 0)) {
+ phy_node = of_parse_phandle(np, "phy-handle", 0);
+ if (phy_node) {
+ of_node_put(phy_node);
bgmac->phy_connect = platform_phy_connect;
} else {
bgmac->phy_connect = bgmac_phy_connect_direct;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
index 4ec4934a4edd..884d42db5554 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c
@@ -1531,7 +1531,7 @@ static void bnxt_tpa_start(struct bnxt *bp, struct bnxt_rx_ring_info *rxr,
if (TPA_START_IS_IPV6(tpa_start1))
tpa_info->gso_type = SKB_GSO_TCPV6;
/* RSS profiles 1 and 3 with extract code 0 for inner 4-tuple */
- else if (cmp_type == CMP_TYPE_RX_L2_TPA_START_CMP &&
+ else if (!BNXT_CHIP_P4_PLUS(bp) &&
TPA_START_HASH_TYPE(tpa_start) == 3)
tpa_info->gso_type = SKB_GSO_TCPV6;
tpa_info->rss_hash =
@@ -2226,15 +2226,13 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
if (cmp_type == CMP_TYPE_RX_L2_V3_CMP) {
type = bnxt_rss_ext_op(bp, rxcmp);
} else {
- u32 hash_type = RX_CMP_HASH_TYPE(rxcmp);
+ u32 itypes = RX_CMP_ITYPES(rxcmp);
- /* RSS profiles 1 and 3 with extract code 0 for inner
- * 4-tuple
- */
- if (hash_type != 1 && hash_type != 3)
- type = PKT_HASH_TYPE_L3;
- else
+ if (itypes == RX_CMP_FLAGS_ITYPE_TCP ||
+ itypes == RX_CMP_FLAGS_ITYPE_UDP)
type = PKT_HASH_TYPE_L4;
+ else
+ type = PKT_HASH_TYPE_L3;
}
skb_set_hash(skb, le32_to_cpu(rxcmp->rx_cmp_rss_hash), type);
}
@@ -2899,6 +2897,13 @@ static int bnxt_hwrm_handler(struct bnxt *bp, struct tx_cmp *txcmp)
return 0;
}
+static bool bnxt_vnic_is_active(struct bnxt *bp)
+{
+ struct bnxt_vnic_info *vnic = &bp->vnic_info[0];
+
+ return vnic->fw_vnic_id != INVALID_HW_RING_ID && vnic->mru > 0;
+}
+
static irqreturn_t bnxt_msix(int irq, void *dev_instance)
{
struct bnxt_napi *bnapi = dev_instance;
@@ -3166,7 +3171,7 @@ static int bnxt_poll(struct napi_struct *napi, int budget)
break;
}
}
- if (bp->flags & BNXT_FLAG_DIM) {
+ if ((bp->flags & BNXT_FLAG_DIM) && bnxt_vnic_is_active(bp)) {
struct dim_sample dim_sample = {};
dim_update_sample(cpr->event_ctr,
@@ -3297,7 +3302,7 @@ static int bnxt_poll_p5(struct napi_struct *napi, int budget)
poll_done:
cpr_rx = &cpr->cp_ring_arr[0];
if (cpr_rx->cp_ring_type == BNXT_NQ_HDL_TYPE_RX &&
- (bp->flags & BNXT_FLAG_DIM)) {
+ (bp->flags & BNXT_FLAG_DIM) && bnxt_vnic_is_active(bp)) {
struct dim_sample dim_sample = {};
dim_update_sample(cpr->event_ctr,
@@ -3421,15 +3426,11 @@ static void bnxt_free_one_rx_agg_ring(struct bnxt *bp, struct bnxt_rx_ring_info
}
}
-static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
+static void bnxt_free_one_tpa_info_data(struct bnxt *bp,
+ struct bnxt_rx_ring_info *rxr)
{
- struct bnxt_rx_ring_info *rxr = &bp->rx_ring[ring_nr];
- struct bnxt_tpa_idx_map *map;
int i;
- if (!rxr->rx_tpa)
- goto skip_rx_tpa_free;
-
for (i = 0; i < bp->max_tpa; i++) {
struct bnxt_tpa_info *tpa_info = &rxr->rx_tpa[i];
u8 *data = tpa_info->data;
@@ -3440,6 +3441,17 @@ static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp, int ring_nr)
tpa_info->data = NULL;
page_pool_free_va(rxr->head_pool, data, false);
}
+}
+
+static void bnxt_free_one_rx_ring_skbs(struct bnxt *bp,
+ struct bnxt_rx_ring_info *rxr)
+{
+ struct bnxt_tpa_idx_map *map;
+
+ if (!rxr->rx_tpa)
+ goto skip_rx_tpa_free;
+
+ bnxt_free_one_tpa_info_data(bp, rxr);
skip_rx_tpa_free:
if (!rxr->rx_buf_ring)
@@ -3467,7 +3479,7 @@ static void bnxt_free_rx_skbs(struct bnxt *bp)
return;
for (i = 0; i < bp->rx_nr_rings; i++)
- bnxt_free_one_rx_ring_skbs(bp, i);
+ bnxt_free_one_rx_ring_skbs(bp, &bp->rx_ring[i]);
}
static void bnxt_free_skbs(struct bnxt *bp)
@@ -3608,29 +3620,64 @@ static int bnxt_alloc_ring(struct bnxt *bp, struct bnxt_ring_mem_info *rmem)
return 0;
}
+static void bnxt_free_one_tpa_info(struct bnxt *bp,
+ struct bnxt_rx_ring_info *rxr)
+{
+ int i;
+
+ kfree(rxr->rx_tpa_idx_map);
+ rxr->rx_tpa_idx_map = NULL;
+ if (rxr->rx_tpa) {
+ for (i = 0; i < bp->max_tpa; i++) {
+ kfree(rxr->rx_tpa[i].agg_arr);
+ rxr->rx_tpa[i].agg_arr = NULL;
+ }
+ }
+ kfree(rxr->rx_tpa);
+ rxr->rx_tpa = NULL;
+}
+
static void bnxt_free_tpa_info(struct bnxt *bp)
{
- int i, j;
+ int i;
for (i = 0; i < bp->rx_nr_rings; i++) {
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
- kfree(rxr->rx_tpa_idx_map);
- rxr->rx_tpa_idx_map = NULL;
- if (rxr->rx_tpa) {
- for (j = 0; j < bp->max_tpa; j++) {
- kfree(rxr->rx_tpa[j].agg_arr);
- rxr->rx_tpa[j].agg_arr = NULL;
- }
- }
- kfree(rxr->rx_tpa);
- rxr->rx_tpa = NULL;
+ bnxt_free_one_tpa_info(bp, rxr);
+ }
+}
+
+static int bnxt_alloc_one_tpa_info(struct bnxt *bp,
+ struct bnxt_rx_ring_info *rxr)
+{
+ struct rx_agg_cmp *agg;
+ int i;
+
+ rxr->rx_tpa = kcalloc(bp->max_tpa, sizeof(struct bnxt_tpa_info),
+ GFP_KERNEL);
+ if (!rxr->rx_tpa)
+ return -ENOMEM;
+
+ if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS))
+ return 0;
+ for (i = 0; i < bp->max_tpa; i++) {
+ agg = kcalloc(MAX_SKB_FRAGS, sizeof(*agg), GFP_KERNEL);
+ if (!agg)
+ return -ENOMEM;
+ rxr->rx_tpa[i].agg_arr = agg;
}
+ rxr->rx_tpa_idx_map = kzalloc(sizeof(*rxr->rx_tpa_idx_map),
+ GFP_KERNEL);
+ if (!rxr->rx_tpa_idx_map)
+ return -ENOMEM;
+
+ return 0;
}
static int bnxt_alloc_tpa_info(struct bnxt *bp)
{
- int i, j;
+ int i, rc;
bp->max_tpa = MAX_TPA;
if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
@@ -3641,25 +3688,10 @@ static int bnxt_alloc_tpa_info(struct bnxt *bp)
for (i = 0; i < bp->rx_nr_rings; i++) {
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
- struct rx_agg_cmp *agg;
- rxr->rx_tpa = kcalloc(bp->max_tpa, sizeof(struct bnxt_tpa_info),
- GFP_KERNEL);
- if (!rxr->rx_tpa)
- return -ENOMEM;
-
- if (!(bp->flags & BNXT_FLAG_CHIP_P5_PLUS))
- continue;
- for (j = 0; j < bp->max_tpa; j++) {
- agg = kcalloc(MAX_SKB_FRAGS, sizeof(*agg), GFP_KERNEL);
- if (!agg)
- return -ENOMEM;
- rxr->rx_tpa[j].agg_arr = agg;
- }
- rxr->rx_tpa_idx_map = kzalloc(sizeof(*rxr->rx_tpa_idx_map),
- GFP_KERNEL);
- if (!rxr->rx_tpa_idx_map)
- return -ENOMEM;
+ rc = bnxt_alloc_one_tpa_info(bp, rxr);
+ if (rc)
+ return rc;
}
return 0;
}
@@ -3683,7 +3715,7 @@ static void bnxt_free_rx_rings(struct bnxt *bp)
xdp_rxq_info_unreg(&rxr->xdp_rxq);
page_pool_destroy(rxr->page_pool);
- if (rxr->page_pool != rxr->head_pool)
+ if (bnxt_separate_head_pool())
page_pool_destroy(rxr->head_pool);
rxr->page_pool = rxr->head_pool = NULL;
@@ -3737,6 +3769,19 @@ err_destroy_pp:
return PTR_ERR(pool);
}
+static int bnxt_alloc_rx_agg_bmap(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
+{
+ u16 mem_size;
+
+ rxr->rx_agg_bmap_size = bp->rx_agg_ring_mask + 1;
+ mem_size = rxr->rx_agg_bmap_size / 8;
+ rxr->rx_agg_bmap = kzalloc(mem_size, GFP_KERNEL);
+ if (!rxr->rx_agg_bmap)
+ return -ENOMEM;
+
+ return 0;
+}
+
static int bnxt_alloc_rx_rings(struct bnxt *bp)
{
int numa_node = dev_to_node(&bp->pdev->dev);
@@ -3781,19 +3826,15 @@ static int bnxt_alloc_rx_rings(struct bnxt *bp)
ring->grp_idx = i;
if (agg_rings) {
- u16 mem_size;
-
ring = &rxr->rx_agg_ring_struct;
rc = bnxt_alloc_ring(bp, &ring->ring_mem);
if (rc)
return rc;
ring->grp_idx = i;
- rxr->rx_agg_bmap_size = bp->rx_agg_ring_mask + 1;
- mem_size = rxr->rx_agg_bmap_size / 8;
- rxr->rx_agg_bmap = kzalloc(mem_size, GFP_KERNEL);
- if (!rxr->rx_agg_bmap)
- return -ENOMEM;
+ rc = bnxt_alloc_rx_agg_bmap(bp, rxr);
+ if (rc)
+ return rc;
}
}
if (bp->flags & BNXT_FLAG_TPA)
@@ -4268,10 +4309,31 @@ static void bnxt_alloc_one_rx_ring_page(struct bnxt *bp,
rxr->rx_agg_prod = prod;
}
+static int bnxt_alloc_one_tpa_info_data(struct bnxt *bp,
+ struct bnxt_rx_ring_info *rxr)
+{
+ dma_addr_t mapping;
+ u8 *data;
+ int i;
+
+ for (i = 0; i < bp->max_tpa; i++) {
+ data = __bnxt_alloc_rx_frag(bp, &mapping, rxr,
+ GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ rxr->rx_tpa[i].data = data;
+ rxr->rx_tpa[i].data_ptr = data + bp->rx_offset;
+ rxr->rx_tpa[i].mapping = mapping;
+ }
+
+ return 0;
+}
+
static int bnxt_alloc_one_rx_ring(struct bnxt *bp, int ring_nr)
{
struct bnxt_rx_ring_info *rxr = &bp->rx_ring[ring_nr];
- int i;
+ int rc;
bnxt_alloc_one_rx_ring_skb(bp, rxr, ring_nr);
@@ -4281,19 +4343,9 @@ static int bnxt_alloc_one_rx_ring(struct bnxt *bp, int ring_nr)
bnxt_alloc_one_rx_ring_page(bp, rxr, ring_nr);
if (rxr->rx_tpa) {
- dma_addr_t mapping;
- u8 *data;
-
- for (i = 0; i < bp->max_tpa; i++) {
- data = __bnxt_alloc_rx_frag(bp, &mapping, rxr,
- GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- rxr->rx_tpa[i].data = data;
- rxr->rx_tpa[i].data_ptr = data + bp->rx_offset;
- rxr->rx_tpa[i].mapping = mapping;
- }
+ rc = bnxt_alloc_one_tpa_info_data(bp, rxr);
+ if (rc)
+ return rc;
}
return 0;
}
@@ -7221,6 +7273,26 @@ err_out:
return rc;
}
+static void bnxt_cancel_dim(struct bnxt *bp)
+{
+ int i;
+
+ /* DIM work is initialized in bnxt_enable_napi(). Proceed only
+ * if NAPI is enabled.
+ */
+ if (!bp->bnapi || test_bit(BNXT_STATE_NAPI_DISABLED, &bp->state))
+ return;
+
+ /* Make sure NAPI sees that the VNIC is disabled */
+ synchronize_net();
+ for (i = 0; i < bp->rx_nr_rings; i++) {
+ struct bnxt_rx_ring_info *rxr = &bp->rx_ring[i];
+ struct bnxt_napi *bnapi = rxr->bnapi;
+
+ cancel_work_sync(&bnapi->cp_ring.dim.work);
+ }
+}
+
static int hwrm_ring_free_send_msg(struct bnxt *bp,
struct bnxt_ring_struct *ring,
u32 ring_type, int cmpl_ring_id)
@@ -7321,6 +7393,7 @@ static void bnxt_hwrm_ring_free(struct bnxt *bp, bool close_path)
}
}
+ bnxt_cancel_dim(bp);
for (i = 0; i < bp->rx_nr_rings; i++) {
bnxt_hwrm_rx_ring_free(bp, &bp->rx_ring[i], close_path);
bnxt_hwrm_rx_agg_ring_free(bp, &bp->rx_ring[i], close_path);
@@ -8234,16 +8307,20 @@ static int bnxt_hwrm_func_qcfg(struct bnxt *bp)
if (rc)
goto func_qcfg_exit;
+ flags = le16_to_cpu(resp->flags);
#ifdef CONFIG_BNXT_SRIOV
if (BNXT_VF(bp)) {
struct bnxt_vf_info *vf = &bp->vf;
vf->vlan = le16_to_cpu(resp->vlan) & VLAN_VID_MASK;
+ if (flags & FUNC_QCFG_RESP_FLAGS_TRUSTED_VF)
+ vf->flags |= BNXT_VF_TRUST;
+ else
+ vf->flags &= ~BNXT_VF_TRUST;
} else {
bp->pf.registered_vfs = le16_to_cpu(resp->registered_vfs);
}
#endif
- flags = le16_to_cpu(resp->flags);
if (flags & (FUNC_QCFG_RESP_FLAGS_FW_DCBX_AGENT_ENABLED |
FUNC_QCFG_RESP_FLAGS_FW_LLDP_AGENT_ENABLED)) {
bp->fw_cap |= BNXT_FW_CAP_LLDP_AGENT;
@@ -8320,7 +8397,7 @@ static int bnxt_alloc_all_ctx_pg_info(struct bnxt *bp, int ctx_max)
struct bnxt_ctx_mem_type *ctxm = &ctx->ctx_arr[type];
int n = 1;
- if (!ctxm->max_entries)
+ if (!ctxm->max_entries || ctxm->pg_info)
continue;
if (ctxm->instance_bmap)
@@ -8924,8 +9001,8 @@ static int bnxt_backing_store_cfg_v2(struct bnxt *bp, u32 ena)
continue;
}
bnxt_bs_trace_init(bp, ctxm);
- last_type = type;
}
+ last_type = type;
}
if (last_type == BNXT_CTX_INV) {
@@ -9072,10 +9149,18 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp)
ena = 0;
if ((bp->flags & BNXT_FLAG_ROCE_CAP) && !is_kdump_kernel()) {
pg_lvl = 2;
- extra_qps = min_t(u32, 65536, max_qps - l2_qps - qp1_qps);
- /* allocate extra qps if fw supports RoCE fast qp destroy feature */
- extra_qps += fast_qpmd_qps;
- extra_srqs = min_t(u32, 8192, max_srqs - srqs);
+ if (BNXT_SW_RES_LMT(bp)) {
+ extra_qps = max_qps - l2_qps - qp1_qps;
+ extra_srqs = max_srqs - srqs;
+ } else {
+ extra_qps = min_t(u32, 65536,
+ max_qps - l2_qps - qp1_qps);
+ /* allocate extra qps if fw supports RoCE fast qp
+ * destroy feature
+ */
+ extra_qps += fast_qpmd_qps;
+ extra_srqs = min_t(u32, 8192, max_srqs - srqs);
+ }
if (fast_qpmd_qps)
ena |= FUNC_BACKING_STORE_CFG_REQ_ENABLES_QP_FAST_QPMD;
}
@@ -9111,14 +9196,20 @@ static int bnxt_alloc_ctx_mem(struct bnxt *bp)
goto skip_rdma;
ctxm = &ctx->ctx_arr[BNXT_CTX_MRAV];
- /* 128K extra is needed to accommodate static AH context
- * allocation by f/w.
- */
- num_mr = min_t(u32, ctxm->max_entries / 2, 1024 * 256);
- num_ah = min_t(u32, num_mr, 1024 * 128);
- ctxm->split_entry_cnt = BNXT_CTX_MRAV_AV_SPLIT_ENTRY + 1;
- if (!ctxm->mrav_av_entries || ctxm->mrav_av_entries > num_ah)
- ctxm->mrav_av_entries = num_ah;
+ if (BNXT_SW_RES_LMT(bp) &&
+ ctxm->split_entry_cnt == BNXT_CTX_MRAV_AV_SPLIT_ENTRY + 1) {
+ num_ah = ctxm->mrav_av_entries;
+ num_mr = ctxm->max_entries - num_ah;
+ } else {
+ /* 128K extra is needed to accommodate static AH context
+ * allocation by f/w.
+ */
+ num_mr = min_t(u32, ctxm->max_entries / 2, 1024 * 256);
+ num_ah = min_t(u32, num_mr, 1024 * 128);
+ ctxm->split_entry_cnt = BNXT_CTX_MRAV_AV_SPLIT_ENTRY + 1;
+ if (!ctxm->mrav_av_entries || ctxm->mrav_av_entries > num_ah)
+ ctxm->mrav_av_entries = num_ah;
+ }
rc = bnxt_setup_ctxm_pg_tbls(bp, ctxm, num_mr + num_ah, 2);
if (rc)
@@ -9425,6 +9516,9 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
bp->flags |= BNXT_FLAG_UDP_GSO_CAP;
if (flags_ext2 & FUNC_QCAPS_RESP_FLAGS_EXT2_TX_PKT_TS_CMPL_SUPPORTED)
bp->fw_cap |= BNXT_FW_CAP_TX_TS_CMP;
+ if (flags_ext2 &
+ FUNC_QCAPS_RESP_FLAGS_EXT2_SW_MAX_RESOURCE_LIMITS_SUPPORTED)
+ bp->fw_cap |= BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS;
if (BNXT_PF(bp) &&
(flags_ext2 & FUNC_QCAPS_RESP_FLAGS_EXT2_ROCE_VF_RESOURCE_MGMT_SUPPORTED))
bp->fw_cap |= BNXT_FW_CAP_ROCE_VF_RESC_MGMT_SUPPORTED;
@@ -11264,8 +11358,6 @@ static void bnxt_disable_napi(struct bnxt *bp)
if (bnapi->in_reset)
cpr->sw_stats->rx.rx_resets++;
napi_disable(&bnapi->napi);
- if (bnapi->rx_ring)
- cancel_work_sync(&cpr->dim.work);
}
}
@@ -11485,6 +11577,26 @@ hwrm_phy_qcaps_exit:
return rc;
}
+static void bnxt_hwrm_mac_qcaps(struct bnxt *bp)
+{
+ struct hwrm_port_mac_qcaps_output *resp;
+ struct hwrm_port_mac_qcaps_input *req;
+ int rc;
+
+ if (bp->hwrm_spec_code < 0x10a03)
+ return;
+
+ rc = hwrm_req_init(bp, req, HWRM_PORT_MAC_QCAPS);
+ if (rc)
+ return;
+
+ resp = hwrm_req_hold(bp, req);
+ rc = hwrm_req_send_silent(bp, req);
+ if (!rc)
+ bp->mac_flags = resp->flags;
+ hwrm_req_drop(bp, req);
+}
+
static bool bnxt_support_dropped(u16 advertising, u16 supported)
{
u16 diff = advertising ^ supported;
@@ -13663,7 +13775,7 @@ static void bnxt_rx_ring_reset(struct bnxt *bp)
bnxt_reset_task(bp, true);
break;
}
- bnxt_free_one_rx_ring_skbs(bp, i);
+ bnxt_free_one_rx_ring_skbs(bp, rxr);
rxr->rx_prod = 0;
rxr->rx_agg_prod = 0;
rxr->rx_sw_agg_prod = 0;
@@ -15293,19 +15405,6 @@ static const struct netdev_stat_ops bnxt_stat_ops = {
.get_base_stats = bnxt_get_base_stats,
};
-static int bnxt_alloc_rx_agg_bmap(struct bnxt *bp, struct bnxt_rx_ring_info *rxr)
-{
- u16 mem_size;
-
- rxr->rx_agg_bmap_size = bp->rx_agg_ring_mask + 1;
- mem_size = rxr->rx_agg_bmap_size / 8;
- rxr->rx_agg_bmap = kzalloc(mem_size, GFP_KERNEL);
- if (!rxr->rx_agg_bmap)
- return -ENOMEM;
-
- return 0;
-}
-
static int bnxt_queue_mem_alloc(struct net_device *dev, void *qmem, int idx)
{
struct bnxt_rx_ring_info *rxr, *clone;
@@ -15354,15 +15453,25 @@ static int bnxt_queue_mem_alloc(struct net_device *dev, void *qmem, int idx)
goto err_free_rx_agg_ring;
}
+ if (bp->flags & BNXT_FLAG_TPA) {
+ rc = bnxt_alloc_one_tpa_info(bp, clone);
+ if (rc)
+ goto err_free_tpa_info;
+ }
+
bnxt_init_one_rx_ring_rxbd(bp, clone);
bnxt_init_one_rx_agg_ring_rxbd(bp, clone);
bnxt_alloc_one_rx_ring_skb(bp, clone, idx);
if (bp->flags & BNXT_FLAG_AGG_RINGS)
bnxt_alloc_one_rx_ring_page(bp, clone, idx);
+ if (bp->flags & BNXT_FLAG_TPA)
+ bnxt_alloc_one_tpa_info_data(bp, clone);
return 0;
+err_free_tpa_info:
+ bnxt_free_one_tpa_info(bp, clone);
err_free_rx_agg_ring:
bnxt_free_ring(bp, &clone->rx_agg_ring_struct.ring_mem);
err_free_rx_ring:
@@ -15370,9 +15479,11 @@ err_free_rx_ring:
err_rxq_info_unreg:
xdp_rxq_info_unreg(&clone->xdp_rxq);
err_page_pool_destroy:
- clone->page_pool->p.napi = NULL;
page_pool_destroy(clone->page_pool);
+ if (bnxt_separate_head_pool())
+ page_pool_destroy(clone->head_pool);
clone->page_pool = NULL;
+ clone->head_pool = NULL;
return rc;
}
@@ -15382,13 +15493,15 @@ static void bnxt_queue_mem_free(struct net_device *dev, void *qmem)
struct bnxt *bp = netdev_priv(dev);
struct bnxt_ring_struct *ring;
- bnxt_free_one_rx_ring(bp, rxr);
- bnxt_free_one_rx_agg_ring(bp, rxr);
+ bnxt_free_one_rx_ring_skbs(bp, rxr);
xdp_rxq_info_unreg(&rxr->xdp_rxq);
page_pool_destroy(rxr->page_pool);
+ if (bnxt_separate_head_pool())
+ page_pool_destroy(rxr->head_pool);
rxr->page_pool = NULL;
+ rxr->head_pool = NULL;
ring = &rxr->rx_ring_struct;
bnxt_free_ring(bp, &ring->ring_mem);
@@ -15470,7 +15583,10 @@ static int bnxt_queue_start(struct net_device *dev, void *qmem, int idx)
rxr->rx_agg_prod = clone->rx_agg_prod;
rxr->rx_sw_agg_prod = clone->rx_sw_agg_prod;
rxr->rx_next_cons = clone->rx_next_cons;
+ rxr->rx_tpa = clone->rx_tpa;
+ rxr->rx_tpa_idx_map = clone->rx_tpa_idx_map;
rxr->page_pool = clone->page_pool;
+ rxr->head_pool = clone->head_pool;
rxr->xdp_rxq = clone->xdp_rxq;
bnxt_copy_rx_ring(bp, rxr, clone);
@@ -15523,12 +15639,16 @@ static int bnxt_queue_stop(struct net_device *dev, void *qmem, int idx)
bnxt_hwrm_vnic_update(bp, vnic,
VNIC_UPDATE_REQ_ENABLES_MRU_VALID);
}
-
+ /* Make sure NAPI sees that the VNIC is disabled */
+ synchronize_net();
rxr = &bp->rx_ring[idx];
+ cancel_work_sync(&rxr->bnapi->cp_ring.dim.work);
bnxt_hwrm_rx_ring_free(bp, rxr, false);
bnxt_hwrm_rx_agg_ring_free(bp, rxr, false);
rxr->rx_next_cons = 0;
page_pool_disable_direct_recycling(rxr->page_pool);
+ if (bnxt_separate_head_pool())
+ page_pool_disable_direct_recycling(rxr->head_pool);
memcpy(qmem, rxr, sizeof(*rxr));
bnxt_init_rx_ring_struct(bp, qmem);
@@ -15607,6 +15727,10 @@ static int bnxt_probe_phy(struct bnxt *bp, bool fw_dflt)
bp->dev->priv_flags |= IFF_SUPP_NOFCS;
else
bp->dev->priv_flags &= ~IFF_SUPP_NOFCS;
+
+ bp->mac_flags = 0;
+ bnxt_hwrm_mac_qcaps(bp);
+
if (!fw_dflt)
return 0;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.h b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
index 23f1aff214b4..094c9e95b463 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.h
@@ -267,6 +267,9 @@ struct rx_cmp {
(((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_RSS_HASH_TYPE) >>\
RX_CMP_RSS_HASH_TYPE_SHIFT) & RSS_PROFILE_ID_MASK)
+#define RX_CMP_ITYPES(rxcmp) \
+ (le32_to_cpu((rxcmp)->rx_cmp_len_flags_type) & RX_CMP_FLAGS_ITYPES_MASK)
+
#define RX_CMP_V3_HASH_TYPE_LEGACY(rxcmp) \
((le32_to_cpu((rxcmp)->rx_cmp_misc_v1) & RX_CMP_V3_RSS_EXT_OP_LEGACY) >>\
RX_CMP_V3_RSS_EXT_OP_LEGACY_SHIFT)
@@ -378,7 +381,7 @@ struct rx_agg_cmp {
u32 rx_agg_cmp_opaque;
__le32 rx_agg_cmp_v;
#define RX_AGG_CMP_V (1 << 0)
- #define RX_AGG_CMP_AGG_ID (0xffff << 16)
+ #define RX_AGG_CMP_AGG_ID (0x0fff << 16)
#define RX_AGG_CMP_AGG_ID_SHIFT 16
__le32 rx_agg_cmp_unused;
};
@@ -416,7 +419,7 @@ struct rx_tpa_start_cmp {
#define RX_TPA_START_CMP_V3_RSS_HASH_TYPE_SHIFT 7
#define RX_TPA_START_CMP_AGG_ID (0x7f << 25)
#define RX_TPA_START_CMP_AGG_ID_SHIFT 25
- #define RX_TPA_START_CMP_AGG_ID_P5 (0xffff << 16)
+ #define RX_TPA_START_CMP_AGG_ID_P5 (0x0fff << 16)
#define RX_TPA_START_CMP_AGG_ID_SHIFT_P5 16
#define RX_TPA_START_CMP_METADATA1 (0xf << 28)
#define RX_TPA_START_CMP_METADATA1_SHIFT 28
@@ -540,7 +543,7 @@ struct rx_tpa_end_cmp {
#define RX_TPA_END_CMP_PAYLOAD_OFFSET_SHIFT 16
#define RX_TPA_END_CMP_AGG_ID (0x7f << 25)
#define RX_TPA_END_CMP_AGG_ID_SHIFT 25
- #define RX_TPA_END_CMP_AGG_ID_P5 (0xffff << 16)
+ #define RX_TPA_END_CMP_AGG_ID_P5 (0x0fff << 16)
#define RX_TPA_END_CMP_AGG_ID_SHIFT_P5 16
__le32 rx_tpa_end_cmp_tsdelta;
@@ -2267,6 +2270,11 @@ struct bnxt {
#define BNXT_PF(bp) (!((bp)->flags & BNXT_FLAG_VF))
#define BNXT_VF(bp) ((bp)->flags & BNXT_FLAG_VF)
+#ifdef CONFIG_BNXT_SRIOV
+#define BNXT_VF_IS_TRUSTED(bp) ((bp)->vf.flags & BNXT_VF_TRUST)
+#else
+#define BNXT_VF_IS_TRUSTED(bp) 0
+#endif
#define BNXT_NPAR(bp) ((bp)->port_partition_type)
#define BNXT_MH(bp) ((bp)->flags & BNXT_FLAG_MULTI_HOST)
#define BNXT_SINGLE_PF(bp) (BNXT_PF(bp) && !BNXT_NPAR(bp) && !BNXT_MH(bp))
@@ -2479,6 +2487,7 @@ struct bnxt {
#define BNXT_FW_CAP_CFA_NTUPLE_RX_EXT_IP_PROTO BIT_ULL(38)
#define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V3 BIT_ULL(39)
#define BNXT_FW_CAP_VNIC_RE_FLUSH BIT_ULL(40)
+ #define BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS BIT_ULL(41)
u32 fw_dbg_cap;
@@ -2498,6 +2507,8 @@ struct bnxt {
((bp)->fw_cap & BNXT_FW_CAP_ENABLE_RDMA_SRIOV)
#define BNXT_ROCE_VF_RESC_CAP(bp) \
((bp)->fw_cap & BNXT_FW_CAP_ROCE_VF_RESC_MGMT_SUPPORTED)
+#define BNXT_SW_RES_LMT(bp) \
+ ((bp)->fw_cap & BNXT_FW_CAP_SW_MAX_RESOURCE_LIMITS)
u32 hwrm_spec_code;
u16 hwrm_cmd_seq;
@@ -2657,6 +2668,11 @@ struct bnxt {
#define BNXT_PHY_FL_BANK_SEL (PORT_PHY_QCAPS_RESP_FLAGS2_BANK_ADDR_SUPPORTED << 8)
#define BNXT_PHY_FL_SPEEDS2 (PORT_PHY_QCAPS_RESP_FLAGS2_SPEEDS2_SUPPORTED << 8)
+ /* copied from flags in hwrm_port_mac_qcaps_output */
+ u8 mac_flags;
+#define BNXT_MAC_FL_NO_MAC_LPBK \
+ PORT_MAC_QCAPS_RESP_FLAGS_LOCAL_LPBK_NOT_SUPPORTED
+
u8 num_tests;
struct bnxt_test_info *test_info;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
index f1f6bb328a55..75a59dd72bce 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
@@ -1187,10 +1187,14 @@ static int bnxt_grxclsrule(struct bnxt *bp, struct ethtool_rxnfc *cmd)
}
}
- if (fltr->base.flags & BNXT_ACT_DROP)
+ if (fltr->base.flags & BNXT_ACT_DROP) {
fs->ring_cookie = RX_CLS_FLOW_DISC;
- else
+ } else if (fltr->base.flags & BNXT_ACT_RSS_CTX) {
+ fs->flow_type |= FLOW_RSS;
+ cmd->rss_context = fltr->base.fw_vnic_id;
+ } else {
fs->ring_cookie = fltr->base.rxq;
+ }
rc = 0;
fltr_err:
@@ -2046,7 +2050,8 @@ static void bnxt_get_regs(struct net_device *dev, struct ethtool_regs *regs,
int rc;
regs->version = 0;
- bnxt_dbg_hwrm_rd_reg(bp, 0, BNXT_PXP_REG_LEN / 4, _p);
+ if (!(bp->fw_dbg_cap & DBG_QCAPS_RESP_FLAGS_REG_ACCESS_RESTRICTED))
+ bnxt_dbg_hwrm_rd_reg(bp, 0, BNXT_PXP_REG_LEN / 4, _p);
if (!(bp->fw_cap & BNXT_FW_CAP_PCIE_STATS_SUPPORTED))
return;
@@ -4371,6 +4376,9 @@ static int bnxt_get_module_info(struct net_device *dev,
struct bnxt *bp = netdev_priv(dev);
int rc;
+ if (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp))
+ return -EPERM;
+
/* No point in going further if phy status indicates
* module is not inserted or if it is powered down or
* if it is of type 10GBase-T
@@ -4422,6 +4430,9 @@ static int bnxt_get_module_eeprom(struct net_device *dev,
u16 start = eeprom->offset, length = eeprom->len;
int rc = 0;
+ if (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp))
+ return -EPERM;
+
memset(data, 0, eeprom->len);
/* Read A0 portion of the EEPROM */
@@ -4476,6 +4487,12 @@ static int bnxt_get_module_eeprom_by_page(struct net_device *dev,
struct bnxt *bp = netdev_priv(dev);
int rc;
+ if (BNXT_VF(bp) && !BNXT_VF_IS_TRUSTED(bp)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Module read not permitted on untrusted VF");
+ return -EPERM;
+ }
+
rc = bnxt_get_module_status(bp, extack);
if (rc)
return rc;
@@ -4883,35 +4900,44 @@ static void bnxt_self_test(struct net_device *dev, struct ethtool_test *etest,
bnxt_close_nic(bp, true, false);
bnxt_run_fw_tests(bp, test_mask, &test_results);
- buf[BNXT_MACLPBK_TEST_IDX] = 1;
- bnxt_hwrm_mac_loopback(bp, true);
- msleep(250);
rc = bnxt_half_open_nic(bp);
if (rc) {
- bnxt_hwrm_mac_loopback(bp, false);
etest->flags |= ETH_TEST_FL_FAILED;
return;
}
+ buf[BNXT_MACLPBK_TEST_IDX] = 1;
+ if (bp->mac_flags & BNXT_MAC_FL_NO_MAC_LPBK)
+ goto skip_mac_loopback;
+
+ bnxt_hwrm_mac_loopback(bp, true);
+ msleep(250);
if (bnxt_run_loopback(bp))
etest->flags |= ETH_TEST_FL_FAILED;
else
buf[BNXT_MACLPBK_TEST_IDX] = 0;
bnxt_hwrm_mac_loopback(bp, false);
+skip_mac_loopback:
+ buf[BNXT_PHYLPBK_TEST_IDX] = 1;
+ if (bp->phy_flags & BNXT_PHY_FL_NO_PHY_LPBK)
+ goto skip_phy_loopback;
+
bnxt_hwrm_phy_loopback(bp, true, false);
msleep(1000);
- if (bnxt_run_loopback(bp)) {
- buf[BNXT_PHYLPBK_TEST_IDX] = 1;
+ if (bnxt_run_loopback(bp))
etest->flags |= ETH_TEST_FL_FAILED;
- }
+ else
+ buf[BNXT_PHYLPBK_TEST_IDX] = 0;
+skip_phy_loopback:
+ buf[BNXT_EXTLPBK_TEST_IDX] = 1;
if (do_ext_lpbk) {
etest->flags |= ETH_TEST_FL_EXTERNAL_LB_DONE;
bnxt_hwrm_phy_loopback(bp, true, true);
msleep(1000);
- if (bnxt_run_loopback(bp)) {
- buf[BNXT_EXTLPBK_TEST_IDX] = 1;
+ if (bnxt_run_loopback(bp))
etest->flags |= ETH_TEST_FL_FAILED;
- }
+ else
+ buf[BNXT_EXTLPBK_TEST_IDX] = 0;
}
bnxt_hwrm_phy_loopback(bp, false, false);
bnxt_half_close_nic(bp);
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
index b771c84cdd89..7c88b9f05c4c 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.c
@@ -208,7 +208,7 @@ int bnxt_send_msg(struct bnxt_en_dev *edev,
rc = hwrm_req_replace(bp, req, fw_msg->msg, fw_msg->msg_len);
if (rc)
- return rc;
+ goto drop_req;
hwrm_req_timeout(bp, req, fw_msg->timeout);
resp = hwrm_req_hold(bp, req);
@@ -220,6 +220,7 @@ int bnxt_send_msg(struct bnxt_en_dev *edev,
memcpy(fw_msg->resp, resp, resp_len);
}
+drop_req:
hwrm_req_drop(bp, req);
return rc;
}
@@ -416,6 +417,8 @@ static void bnxt_set_edev_info(struct bnxt_en_dev *edev, struct bnxt *bp)
edev->flags |= BNXT_EN_FLAG_VF;
if (BNXT_ROCE_VF_RESC_CAP(bp))
edev->flags |= BNXT_EN_FLAG_ROCE_VF_RES_MGMT;
+ if (BNXT_SW_RES_LMT(bp))
+ edev->flags |= BNXT_EN_FLAG_SW_RES_LMT;
edev->chip_num = bp->chip_num;
edev->hw_ring_stats_size = bp->hw_ring_stats_size;
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
index 5d6aac60f236..54ad9f8273d7 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ulp.h
@@ -65,6 +65,8 @@ struct bnxt_en_dev {
#define BNXT_EN_FLAG_VF 0x10
#define BNXT_EN_VF(edev) ((edev)->flags & BNXT_EN_FLAG_VF)
#define BNXT_EN_FLAG_ROCE_VF_RES_MGMT 0x20
+ #define BNXT_EN_FLAG_SW_RES_LMT 0x40
+#define BNXT_EN_SW_RES_LMT(edev) ((edev)->flags & BNXT_EN_FLAG_SW_RES_LMT)
struct bnxt_ulp *ulp_tbl;
int l2_db_size; /* Doorbell BAR size in
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index daa416fb1724..640f500f989d 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -530,19 +530,9 @@ static void macb_set_tx_clk(struct macb *bp, int speed)
if (bp->phy_interface == PHY_INTERFACE_MODE_MII)
return;
- switch (speed) {
- case SPEED_10:
- rate = 2500000;
- break;
- case SPEED_100:
- rate = 25000000;
- break;
- case SPEED_1000:
- rate = 125000000;
- break;
- default:
+ rate = rgmii_clock(speed);
+ if (rate < 0)
return;
- }
rate_rounded = clk_round_rate(bp->tx_clk, rate);
if (rate_rounded < 0)
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
index 75bd69ff61a8..c7c2c15a1815 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4.h
@@ -2076,7 +2076,7 @@ void t4_idma_monitor(struct adapter *adapter,
struct sge_idma_monitor_state *idma,
int hz, int ticks);
int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
- unsigned int naddr, u8 *addr);
+ u8 start, unsigned int naddr, u8 *addr);
void t4_tp_pio_read(struct adapter *adap, u32 *buff, u32 nregs,
u32 start_index, bool sleep_ok);
void t4_tp_tm_pio_read(struct adapter *adap, u32 *buff, u32 nregs,
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index 1b3254b49443..2f0b3e389e62 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1799,7 +1799,10 @@ void cxgb4_remove_tid(struct tid_info *t, unsigned int chan, unsigned int tid,
struct adapter *adap = container_of(t, struct adapter, tids);
struct sk_buff *skb;
- WARN_ON(tid_out_of_range(&adap->tids, tid));
+ if (tid_out_of_range(&adap->tids, tid)) {
+ dev_err(adap->pdev_dev, "tid %d out of range\n", tid);
+ return;
+ }
if (t->tid_tab[tid - adap->tids.tid_base]) {
t->tid_tab[tid - adap->tids.tid_base] = NULL;
@@ -3234,7 +3237,7 @@ static int cxgb4_mgmt_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
dev_info(pi->adapter->pdev_dev,
"Setting MAC %pM on VF %d\n", mac, vf);
- ret = t4_set_vf_mac_acl(adap, vf + 1, 1, mac);
+ ret = t4_set_vf_mac_acl(adap, vf + 1, pi->lport, 1, mac);
if (!ret)
ether_addr_copy(adap->vfinfo[vf].vf_mac_addr, mac);
return ret;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
index 76de55306c4d..175bf9b13058 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c
@@ -10215,11 +10215,12 @@ out:
* t4_set_vf_mac_acl - Set MAC address for the specified VF
* @adapter: The adapter
* @vf: one of the VFs instantiated by the specified PF
+ * @start: The start port id associated with specified VF
* @naddr: the number of MAC addresses
* @addr: the MAC address(es) to be set to the specified VF
*/
int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
- unsigned int naddr, u8 *addr)
+ u8 start, unsigned int naddr, u8 *addr)
{
struct fw_acl_mac_cmd cmd;
@@ -10234,7 +10235,7 @@ int t4_set_vf_mac_acl(struct adapter *adapter, unsigned int vf,
cmd.en_to_len16 = cpu_to_be32((unsigned int)FW_LEN16(cmd));
cmd.nmac = naddr;
- switch (adapter->pf) {
+ switch (start) {
case 3:
memcpy(cmd.macaddr3, addr, sizeof(cmd.macaddr3));
break;
diff --git a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
index 96fd31d75dfd..daa1ebaef511 100644
--- a/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
+++ b/drivers/net/ethernet/chelsio/inline_crypto/chtls/chtls_main.c
@@ -346,8 +346,9 @@ static struct sk_buff *copy_gl_to_skb_pkt(const struct pkt_gl *gl,
* driver. Once driver synthesizes cpl_pass_accept_req the skb will go
* through the regular cpl_pass_accept_req processing in TOM.
*/
- skb = alloc_skb(gl->tot_len + sizeof(struct cpl_pass_accept_req)
- - pktshift, GFP_ATOMIC);
+ skb = alloc_skb(size_add(gl->tot_len,
+ sizeof(struct cpl_pass_accept_req)) -
+ pktshift, GFP_ATOMIC);
if (unlikely(!skb))
return NULL;
__skb_put(skb, gl->tot_len + sizeof(struct cpl_pass_accept_req)
diff --git a/drivers/net/ethernet/cisco/enic/enic_main.c b/drivers/net/ethernet/cisco/enic/enic_main.c
index 9913952ccb42..49f6cab01ed5 100644
--- a/drivers/net/ethernet/cisco/enic/enic_main.c
+++ b/drivers/net/ethernet/cisco/enic/enic_main.c
@@ -109,7 +109,7 @@ static struct enic_intr_mod_table mod_table[ENIC_MAX_COALESCE_TIMERS + 1] = {
static struct enic_intr_mod_range mod_range[ENIC_MAX_LINK_SPEEDS] = {
{0, 0}, /* 0 - 4 Gbps */
{0, 3}, /* 4 - 10 Gbps */
- {3, 6}, /* 10 - 40 Gbps */
+ {3, 6}, /* 10+ Gbps */
};
static void enic_init_affinity_hint(struct enic *enic)
@@ -428,6 +428,36 @@ static void enic_mtu_check(struct enic *enic)
}
}
+static void enic_set_rx_coal_setting(struct enic *enic)
+{
+ unsigned int speed;
+ int index = -1;
+ struct enic_rx_coal *rx_coal = &enic->rx_coalesce_setting;
+
+ /* 1. Read the link speed from fw
+ * 2. Pick the default range for the speed
+ * 3. Update it in enic->rx_coalesce_setting
+ */
+ speed = vnic_dev_port_speed(enic->vdev);
+ if (speed > ENIC_LINK_SPEED_10G)
+ index = ENIC_LINK_40G_INDEX;
+ else if (speed > ENIC_LINK_SPEED_4G)
+ index = ENIC_LINK_10G_INDEX;
+ else
+ index = ENIC_LINK_4G_INDEX;
+
+ rx_coal->small_pkt_range_start = mod_range[index].small_pkt_range_start;
+ rx_coal->large_pkt_range_start = mod_range[index].large_pkt_range_start;
+ rx_coal->range_end = ENIC_RX_COALESCE_RANGE_END;
+
+ /* Start with the value provided by UCSM */
+ for (index = 0; index < enic->rq_count; index++)
+ enic->cq[index].cur_rx_coal_timeval =
+ enic->config.intr_timer_usec;
+
+ rx_coal->use_adaptive_rx_coalesce = 1;
+}
+
static void enic_link_check(struct enic *enic)
{
int link_status = vnic_dev_link_status(enic->vdev);
@@ -436,6 +466,7 @@ static void enic_link_check(struct enic *enic)
if (link_status && !carrier_ok) {
netdev_info(enic->netdev, "Link UP\n");
netif_carrier_on(enic->netdev);
+ enic_set_rx_coal_setting(enic);
} else if (!link_status && carrier_ok) {
netdev_info(enic->netdev, "Link DOWN\n");
netif_carrier_off(enic->netdev);
@@ -1901,36 +1932,6 @@ static void enic_synchronize_irqs(struct enic *enic)
}
}
-static void enic_set_rx_coal_setting(struct enic *enic)
-{
- unsigned int speed;
- int index = -1;
- struct enic_rx_coal *rx_coal = &enic->rx_coalesce_setting;
-
- /* 1. Read the link speed from fw
- * 2. Pick the default range for the speed
- * 3. Update it in enic->rx_coalesce_setting
- */
- speed = vnic_dev_port_speed(enic->vdev);
- if (ENIC_LINK_SPEED_10G < speed)
- index = ENIC_LINK_40G_INDEX;
- else if (ENIC_LINK_SPEED_4G < speed)
- index = ENIC_LINK_10G_INDEX;
- else
- index = ENIC_LINK_4G_INDEX;
-
- rx_coal->small_pkt_range_start = mod_range[index].small_pkt_range_start;
- rx_coal->large_pkt_range_start = mod_range[index].large_pkt_range_start;
- rx_coal->range_end = ENIC_RX_COALESCE_RANGE_END;
-
- /* Start with the value provided by UCSM */
- for (index = 0; index < enic->rq_count; index++)
- enic->cq[index].cur_rx_coal_timeval =
- enic->config.intr_timer_usec;
-
- rx_coal->use_adaptive_rx_coalesce = 1;
-}
-
static int enic_dev_notify_set(struct enic *enic)
{
int err;
@@ -3063,7 +3064,6 @@ static int enic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
timer_setup(&enic->notify_timer, enic_notify_timer, 0);
enic_rfs_flw_tbl_init(enic);
- enic_set_rx_coal_setting(enic);
INIT_WORK(&enic->reset, enic_reset);
INIT_WORK(&enic->tx_hang_reset, enic_tx_hang_reset);
INIT_WORK(&enic->change_mtu_work, enic_change_mtu_work);
diff --git a/drivers/net/ethernet/freescale/Kconfig b/drivers/net/ethernet/freescale/Kconfig
index 75401d2a5fb4..a2d7300925a8 100644
--- a/drivers/net/ethernet/freescale/Kconfig
+++ b/drivers/net/ethernet/freescale/Kconfig
@@ -81,8 +81,7 @@ config UCC_GETH
tristate "Freescale QE Gigabit Ethernet"
depends on QUICC_ENGINE && PPC32
select FSL_PQ_MDIO
- select PHYLIB
- select FIXED_PHY
+ select PHYLINK
help
This driver supports the Gigabit Ethernet mode of the QUICC Engine,
which is available on some Freescale SOCs.
diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
index bf5baef5c3e0..4948b4906584 100644
--- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
+++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c
@@ -2281,7 +2281,7 @@ static int dpaa_a050385_wa_xdpf(struct dpaa_priv *priv,
new_xdpf->len = xdpf->len;
new_xdpf->headroom = priv->tx_headroom;
new_xdpf->frame_sz = DPAA_BP_RAW_SIZE;
- new_xdpf->mem.type = MEM_TYPE_PAGE_ORDER0;
+ new_xdpf->mem_type = MEM_TYPE_PAGE_ORDER0;
/* Release the initial buffer */
xdp_return_frame_rx_napi(xdpf);
diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
index a293b08f36d4..147a93bf9fa9 100644
--- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
+++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-switch.c
@@ -780,13 +780,14 @@ struct ethsw_dump_ctx {
static int dpaa2_switch_fdb_dump_nl(struct fdb_dump_entry *entry,
struct ethsw_dump_ctx *dump)
{
+ struct ndo_fdb_dump_context *ctx = (void *)dump->cb->ctx;
int is_dynamic = entry->type & DPSW_FDB_ENTRY_DINAMIC;
u32 portid = NETLINK_CB(dump->cb->skb).portid;
u32 seq = dump->cb->nlh->nlmsg_seq;
struct nlmsghdr *nlh;
struct ndmsg *ndm;
- if (dump->idx < dump->cb->args[2])
+ if (dump->idx < ctx->fdb_idx)
goto skip;
nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.c b/drivers/net/ethernet/freescale/enetc/enetc.c
index 35634c516e26..6a6fc819dfde 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc.c
@@ -29,6 +29,9 @@ EXPORT_SYMBOL_GPL(enetc_port_mac_wr);
static void enetc_change_preemptible_tcs(struct enetc_ndev_priv *priv,
u8 preemptible_tcs)
{
+ if (!(priv->si->hw_features & ENETC_SI_F_QBU))
+ return;
+
priv->preemptible_tcs = preemptible_tcs;
enetc_mm_commit_preemptible_tcs(priv);
}
@@ -143,6 +146,27 @@ static int enetc_ptp_parse(struct sk_buff *skb, u8 *udp,
return 0;
}
+static bool enetc_tx_csum_offload_check(struct sk_buff *skb)
+{
+ switch (skb->csum_offset) {
+ case offsetof(struct tcphdr, check):
+ case offsetof(struct udphdr, check):
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool enetc_skb_is_ipv6(struct sk_buff *skb)
+{
+ return vlan_get_protocol(skb) == htons(ETH_P_IPV6);
+}
+
+static bool enetc_skb_is_tcp(struct sk_buff *skb)
+{
+ return skb->csum_offset == offsetof(struct tcphdr, check);
+}
+
static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
{
bool do_vlan, do_onestep_tstamp = false, do_twostep_tstamp = false;
@@ -160,6 +184,29 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
dma_addr_t dma;
u8 flags = 0;
+ enetc_clear_tx_bd(&temp_bd);
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ /* Can not support TSD and checksum offload at the same time */
+ if (priv->active_offloads & ENETC_F_TXCSUM &&
+ enetc_tx_csum_offload_check(skb) && !tx_ring->tsd_enable) {
+ temp_bd.l3_aux0 = FIELD_PREP(ENETC_TX_BD_L3_START,
+ skb_network_offset(skb));
+ temp_bd.l3_aux1 = FIELD_PREP(ENETC_TX_BD_L3_HDR_LEN,
+ skb_network_header_len(skb) / 4);
+ temp_bd.l3_aux1 |= FIELD_PREP(ENETC_TX_BD_L3T,
+ enetc_skb_is_ipv6(skb));
+ if (enetc_skb_is_tcp(skb))
+ temp_bd.l4_aux = FIELD_PREP(ENETC_TX_BD_L4T,
+ ENETC_TXBD_L4T_TCP);
+ else
+ temp_bd.l4_aux = FIELD_PREP(ENETC_TX_BD_L4T,
+ ENETC_TXBD_L4T_UDP);
+ flags |= ENETC_TXBD_FLAGS_CSUM_LSO | ENETC_TXBD_FLAGS_L4CS;
+ } else if (skb_checksum_help(skb)) {
+ return 0;
+ }
+ }
+
i = tx_ring->next_to_use;
txbd = ENETC_TXBD(*tx_ring, i);
prefetchw(txbd);
@@ -170,7 +217,6 @@ static int enetc_map_tx_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
temp_bd.addr = cpu_to_le64(dma);
temp_bd.buf_len = cpu_to_le16(len);
- temp_bd.lstatus = 0;
tx_swbd = &tx_ring->tx_swbd[i];
tx_swbd->dma = dma;
@@ -486,8 +532,233 @@ static void enetc_tso_complete_csum(struct enetc_bdr *tx_ring, struct tso_t *tso
}
}
+static int enetc_lso_count_descs(const struct sk_buff *skb)
+{
+ /* 4 BDs: 1 BD for LSO header + 1 BD for extended BD + 1 BD
+ * for linear area data but not include LSO header, namely
+ * skb_headlen(skb) - lso_hdr_len (it may be 0, but that's
+ * okay, we only need to consider the worst case). And 1 BD
+ * for gap.
+ */
+ return skb_shinfo(skb)->nr_frags + 4;
+}
+
+static int enetc_lso_get_hdr_len(const struct sk_buff *skb)
+{
+ int hdr_len, tlen;
+
+ tlen = skb_is_gso_tcp(skb) ? tcp_hdrlen(skb) : sizeof(struct udphdr);
+ hdr_len = skb_transport_offset(skb) + tlen;
+
+ return hdr_len;
+}
+
+static void enetc_lso_start(struct sk_buff *skb, struct enetc_lso_t *lso)
+{
+ lso->lso_seg_size = skb_shinfo(skb)->gso_size;
+ lso->ipv6 = enetc_skb_is_ipv6(skb);
+ lso->tcp = skb_is_gso_tcp(skb);
+ lso->l3_hdr_len = skb_network_header_len(skb);
+ lso->l3_start = skb_network_offset(skb);
+ lso->hdr_len = enetc_lso_get_hdr_len(skb);
+ lso->total_len = skb->len - lso->hdr_len;
+}
+
+static void enetc_lso_map_hdr(struct enetc_bdr *tx_ring, struct sk_buff *skb,
+ int *i, struct enetc_lso_t *lso)
+{
+ union enetc_tx_bd txbd_tmp, *txbd;
+ struct enetc_tx_swbd *tx_swbd;
+ u16 frm_len, frm_len_ext;
+ u8 flags, e_flags = 0;
+ dma_addr_t addr;
+ char *hdr;
+
+ /* Get the first BD of the LSO BDs chain */
+ txbd = ENETC_TXBD(*tx_ring, *i);
+ tx_swbd = &tx_ring->tx_swbd[*i];
+ prefetchw(txbd);
+
+ /* Prepare LSO header: MAC + IP + TCP/UDP */
+ hdr = tx_ring->tso_headers + *i * TSO_HEADER_SIZE;
+ memcpy(hdr, skb->data, lso->hdr_len);
+ addr = tx_ring->tso_headers_dma + *i * TSO_HEADER_SIZE;
+
+ /* {frm_len_ext, frm_len} indicates the total length of
+ * large transmit data unit. frm_len contains the 16 least
+ * significant bits and frm_len_ext contains the 4 most
+ * significant bits.
+ */
+ frm_len = lso->total_len & 0xffff;
+ frm_len_ext = (lso->total_len >> 16) & 0xf;
+
+ /* Set the flags of the first BD */
+ flags = ENETC_TXBD_FLAGS_EX | ENETC_TXBD_FLAGS_CSUM_LSO |
+ ENETC_TXBD_FLAGS_LSO | ENETC_TXBD_FLAGS_L4CS;
+
+ enetc_clear_tx_bd(&txbd_tmp);
+ txbd_tmp.addr = cpu_to_le64(addr);
+ txbd_tmp.hdr_len = cpu_to_le16(lso->hdr_len);
+
+ /* first BD needs frm_len and offload flags set */
+ txbd_tmp.frm_len = cpu_to_le16(frm_len);
+ txbd_tmp.flags = flags;
+
+ txbd_tmp.l3_aux0 = FIELD_PREP(ENETC_TX_BD_L3_START, lso->l3_start);
+ /* l3_hdr_size in 32-bits (4 bytes) */
+ txbd_tmp.l3_aux1 = FIELD_PREP(ENETC_TX_BD_L3_HDR_LEN,
+ lso->l3_hdr_len / 4);
+ if (lso->ipv6)
+ txbd_tmp.l3_aux1 |= ENETC_TX_BD_L3T;
+ else
+ txbd_tmp.l3_aux0 |= ENETC_TX_BD_IPCS;
+
+ txbd_tmp.l4_aux = FIELD_PREP(ENETC_TX_BD_L4T, lso->tcp ?
+ ENETC_TXBD_L4T_TCP : ENETC_TXBD_L4T_UDP);
+
+ /* For the LSO header we do not set the dma address since
+ * we do not want it unmapped when we do cleanup. We still
+ * set len so that we count the bytes sent.
+ */
+ tx_swbd->len = lso->hdr_len;
+ tx_swbd->do_twostep_tstamp = false;
+ tx_swbd->check_wb = false;
+
+ /* Actually write the header in the BD */
+ *txbd = txbd_tmp;
+
+ /* Get the next BD, and the next BD is extended BD */
+ enetc_bdr_idx_inc(tx_ring, i);
+ txbd = ENETC_TXBD(*tx_ring, *i);
+ tx_swbd = &tx_ring->tx_swbd[*i];
+ prefetchw(txbd);
+
+ enetc_clear_tx_bd(&txbd_tmp);
+ if (skb_vlan_tag_present(skb)) {
+ /* Setup the VLAN fields */
+ txbd_tmp.ext.vid = cpu_to_le16(skb_vlan_tag_get(skb));
+ txbd_tmp.ext.tpid = ENETC_TPID_8021Q;
+ e_flags = ENETC_TXBD_E_FLAGS_VLAN_INS;
+ }
+
+ /* Write the BD */
+ txbd_tmp.ext.e_flags = e_flags;
+ txbd_tmp.ext.lso_sg_size = cpu_to_le16(lso->lso_seg_size);
+ txbd_tmp.ext.frm_len_ext = cpu_to_le16(frm_len_ext);
+ *txbd = txbd_tmp;
+}
+
+static int enetc_lso_map_data(struct enetc_bdr *tx_ring, struct sk_buff *skb,
+ int *i, struct enetc_lso_t *lso, int *count)
+{
+ union enetc_tx_bd txbd_tmp, *txbd = NULL;
+ struct enetc_tx_swbd *tx_swbd;
+ skb_frag_t *frag;
+ dma_addr_t dma;
+ u8 flags = 0;
+ int len, f;
+
+ len = skb_headlen(skb) - lso->hdr_len;
+ if (len > 0) {
+ dma = dma_map_single(tx_ring->dev, skb->data + lso->hdr_len,
+ len, DMA_TO_DEVICE);
+ if (dma_mapping_error(tx_ring->dev, dma))
+ return -ENOMEM;
+
+ enetc_bdr_idx_inc(tx_ring, i);
+ txbd = ENETC_TXBD(*tx_ring, *i);
+ tx_swbd = &tx_ring->tx_swbd[*i];
+ prefetchw(txbd);
+ *count += 1;
+
+ enetc_clear_tx_bd(&txbd_tmp);
+ txbd_tmp.addr = cpu_to_le64(dma);
+ txbd_tmp.buf_len = cpu_to_le16(len);
+
+ tx_swbd->dma = dma;
+ tx_swbd->len = len;
+ tx_swbd->is_dma_page = 0;
+ tx_swbd->dir = DMA_TO_DEVICE;
+ }
+
+ frag = &skb_shinfo(skb)->frags[0];
+ for (f = 0; f < skb_shinfo(skb)->nr_frags; f++, frag++) {
+ if (txbd)
+ *txbd = txbd_tmp;
+
+ len = skb_frag_size(frag);
+ dma = skb_frag_dma_map(tx_ring->dev, frag);
+ if (dma_mapping_error(tx_ring->dev, dma))
+ return -ENOMEM;
+
+ /* Get the next BD */
+ enetc_bdr_idx_inc(tx_ring, i);
+ txbd = ENETC_TXBD(*tx_ring, *i);
+ tx_swbd = &tx_ring->tx_swbd[*i];
+ prefetchw(txbd);
+ *count += 1;
+
+ enetc_clear_tx_bd(&txbd_tmp);
+ txbd_tmp.addr = cpu_to_le64(dma);
+ txbd_tmp.buf_len = cpu_to_le16(len);
+
+ tx_swbd->dma = dma;
+ tx_swbd->len = len;
+ tx_swbd->is_dma_page = 1;
+ tx_swbd->dir = DMA_TO_DEVICE;
+ }
+
+ /* Last BD needs 'F' bit set */
+ flags |= ENETC_TXBD_FLAGS_F;
+ txbd_tmp.flags = flags;
+ *txbd = txbd_tmp;
+
+ tx_swbd->is_eof = 1;
+ tx_swbd->skb = skb;
+
+ return 0;
+}
+
+static int enetc_lso_hw_offload(struct enetc_bdr *tx_ring, struct sk_buff *skb)
+{
+ struct enetc_tx_swbd *tx_swbd;
+ struct enetc_lso_t lso = {0};
+ int err, i, count = 0;
+
+ /* Initialize the LSO handler */
+ enetc_lso_start(skb, &lso);
+ i = tx_ring->next_to_use;
+
+ enetc_lso_map_hdr(tx_ring, skb, &i, &lso);
+ /* First BD and an extend BD */
+ count += 2;
+
+ err = enetc_lso_map_data(tx_ring, skb, &i, &lso, &count);
+ if (err)
+ goto dma_err;
+
+ /* Go to the next BD */
+ enetc_bdr_idx_inc(tx_ring, &i);
+ tx_ring->next_to_use = i;
+ enetc_update_tx_ring_tail(tx_ring);
+
+ return count;
+
+dma_err:
+ do {
+ tx_swbd = &tx_ring->tx_swbd[i];
+ enetc_free_tx_frame(tx_ring, tx_swbd);
+ if (i == 0)
+ i = tx_ring->bd_count;
+ i--;
+ } while (--count);
+
+ return 0;
+}
+
static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb)
{
+ struct enetc_ndev_priv *priv = netdev_priv(tx_ring->ndev);
int hdr_len, total_len, data_len;
struct enetc_tx_swbd *tx_swbd;
union enetc_tx_bd *txbd;
@@ -553,7 +824,7 @@ static int enetc_map_tx_tso_buffs(struct enetc_bdr *tx_ring, struct sk_buff *skb
bd_data_num++;
tso_build_data(skb, &tso, size);
- if (unlikely(bd_data_num >= ENETC_MAX_SKB_FRAGS && data_len))
+ if (unlikely(bd_data_num >= priv->max_frags && data_len))
goto err_chained_bd;
}
@@ -591,7 +862,7 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb,
{
struct enetc_ndev_priv *priv = netdev_priv(ndev);
struct enetc_bdr *tx_ring;
- int count, err;
+ int count;
/* Queue one-step Sync packet if already locked */
if (skb->cb[0] & ENETC_F_TX_ONESTEP_SYNC_TSTAMP) {
@@ -605,16 +876,28 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb,
tx_ring = priv->tx_ring[skb->queue_mapping];
if (skb_is_gso(skb)) {
- if (enetc_bd_unused(tx_ring) < tso_count_descs(skb)) {
- netif_stop_subqueue(ndev, tx_ring->index);
- return NETDEV_TX_BUSY;
- }
+ /* LSO data unit lengths of up to 256KB are supported */
+ if (priv->active_offloads & ENETC_F_LSO &&
+ (skb->len - enetc_lso_get_hdr_len(skb)) <=
+ ENETC_LSO_MAX_DATA_LEN) {
+ if (enetc_bd_unused(tx_ring) < enetc_lso_count_descs(skb)) {
+ netif_stop_subqueue(ndev, tx_ring->index);
+ return NETDEV_TX_BUSY;
+ }
- enetc_lock_mdio();
- count = enetc_map_tx_tso_buffs(tx_ring, skb);
- enetc_unlock_mdio();
+ count = enetc_lso_hw_offload(tx_ring, skb);
+ } else {
+ if (enetc_bd_unused(tx_ring) < tso_count_descs(skb)) {
+ netif_stop_subqueue(ndev, tx_ring->index);
+ return NETDEV_TX_BUSY;
+ }
+
+ enetc_lock_mdio();
+ count = enetc_map_tx_tso_buffs(tx_ring, skb);
+ enetc_unlock_mdio();
+ }
} else {
- if (unlikely(skb_shinfo(skb)->nr_frags > ENETC_MAX_SKB_FRAGS))
+ if (unlikely(skb_shinfo(skb)->nr_frags > priv->max_frags))
if (unlikely(skb_linearize(skb)))
goto drop_packet_err;
@@ -624,11 +907,6 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
- if (skb->ip_summed == CHECKSUM_PARTIAL) {
- err = skb_checksum_help(skb);
- if (err)
- goto drop_packet_err;
- }
enetc_lock_mdio();
count = enetc_map_tx_buffs(tx_ring, skb);
enetc_unlock_mdio();
@@ -637,7 +915,7 @@ static netdev_tx_t enetc_start_xmit(struct sk_buff *skb,
if (unlikely(!count))
goto drop_packet_err;
- if (enetc_bd_unused(tx_ring) < ENETC_TXBDS_MAX_NEEDED)
+ if (enetc_bd_unused(tx_ring) < ENETC_TXBDS_MAX_NEEDED(priv->max_frags))
netif_stop_subqueue(ndev, tx_ring->index);
return NETDEV_TX_OK;
@@ -905,7 +1183,8 @@ static bool enetc_clean_tx_ring(struct enetc_bdr *tx_ring, int napi_budget)
if (unlikely(tx_frm_cnt && netif_carrier_ok(ndev) &&
__netif_subqueue_stopped(ndev, tx_ring->index) &&
!test_bit(ENETC_TX_DOWN, &priv->flags) &&
- (enetc_bd_unused(tx_ring) >= ENETC_TXBDS_MAX_NEEDED))) {
+ (enetc_bd_unused(tx_ring) >=
+ ENETC_TXBDS_MAX_NEEDED(priv->max_frags)))) {
netif_wake_subqueue(ndev, tx_ring->index);
}
@@ -1757,14 +2036,8 @@ void enetc_get_si_caps(struct enetc_si *si)
si->num_rss = ENETC_SIRSSCAPR_GET_NUM_RSS(rss);
}
- if (val & ENETC_SIPCAPR0_QBV)
- si->hw_features |= ENETC_SI_F_QBV;
-
- if (val & ENETC_SIPCAPR0_QBU)
- si->hw_features |= ENETC_SI_F_QBU;
-
- if (val & ENETC_SIPCAPR0_PSFP)
- si->hw_features |= ENETC_SI_F_PSFP;
+ if (val & ENETC_SIPCAPR0_LSO)
+ si->hw_features |= ENETC_SI_F_LSO;
}
EXPORT_SYMBOL_GPL(enetc_get_si_caps);
@@ -2061,6 +2334,14 @@ static int enetc_setup_default_rss_table(struct enetc_si *si, int num_groups)
return 0;
}
+static void enetc_set_lso_flags_mask(struct enetc_hw *hw)
+{
+ enetc_wr(hw, ENETC4_SILSOSFMR0,
+ SILSOSFMR0_VAL_SET(ENETC4_TCP_NL_SEG_FLAGS_DMASK,
+ ENETC4_TCP_NL_SEG_FLAGS_DMASK));
+ enetc_wr(hw, ENETC4_SILSOSFMR1, 0);
+}
+
int enetc_configure_si(struct enetc_ndev_priv *priv)
{
struct enetc_si *si = priv->si;
@@ -2074,6 +2355,9 @@ int enetc_configure_si(struct enetc_ndev_priv *priv)
/* enable SI */
enetc_wr(hw, ENETC_SIMR, ENETC_SIMR_EN);
+ if (si->hw_features & ENETC_SI_F_LSO)
+ enetc_set_lso_flags_mask(hw);
+
/* TODO: RSS support for i.MX95 will be supported later, and the
* is_enetc_rev1() condition will be removed
*/
@@ -3275,17 +3559,21 @@ EXPORT_SYMBOL_GPL(enetc_pci_remove);
static const struct enetc_drvdata enetc_pf_data = {
.sysclk_freq = ENETC_CLK_400M,
.pmac_offset = ENETC_PMAC_OFFSET,
+ .max_frags = ENETC_MAX_SKB_FRAGS,
.eth_ops = &enetc_pf_ethtool_ops,
};
static const struct enetc_drvdata enetc4_pf_data = {
.sysclk_freq = ENETC_CLK_333M,
+ .tx_csum = true,
+ .max_frags = ENETC4_MAX_SKB_FRAGS,
.pmac_offset = ENETC4_PMAC_OFFSET,
.eth_ops = &enetc4_pf_ethtool_ops,
};
static const struct enetc_drvdata enetc_vf_data = {
.sysclk_freq = ENETC_CLK_400M,
+ .max_frags = ENETC_MAX_SKB_FRAGS,
.eth_ops = &enetc_vf_ethtool_ops,
};
diff --git a/drivers/net/ethernet/freescale/enetc/enetc.h b/drivers/net/ethernet/freescale/enetc/enetc.h
index 72fa03dbc2dd..4ad4eb5c5a74 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc.h
@@ -41,6 +41,18 @@ struct enetc_tx_swbd {
u8 qbv_en:1;
};
+struct enetc_lso_t {
+ bool ipv6;
+ bool tcp;
+ u8 l3_hdr_len;
+ u8 hdr_len; /* LSO header length */
+ u8 l3_start;
+ u16 lso_seg_size;
+ int total_len; /* total data length, not include LSO header */
+};
+
+#define ENETC_LSO_MAX_DATA_LEN SZ_256K
+
#define ENETC_RX_MAXFRM_SIZE ENETC_MAC_MAXFRM_SIZE
#define ENETC_RXB_TRUESIZE 2048 /* PAGE_SIZE >> 1 */
#define ENETC_RXB_PAD NET_SKB_PAD /* add extra space if needed */
@@ -59,9 +71,16 @@ struct enetc_rx_swbd {
/* ENETC overhead: optional extension BD + 1 BD gap */
#define ENETC_TXBDS_NEEDED(val) ((val) + 2)
-/* max # of chained Tx BDs is 15, including head and extension BD */
+/* For LS1028A, max # of chained Tx BDs is 15, including head and
+ * extension BD.
+ */
#define ENETC_MAX_SKB_FRAGS 13
-#define ENETC_TXBDS_MAX_NEEDED ENETC_TXBDS_NEEDED(ENETC_MAX_SKB_FRAGS + 1)
+/* For ENETC v4 and later versions, max # of chained Tx BDs is 63,
+ * including head and extension BD, but the range of MAX_SKB_FRAGS
+ * is 17 ~ 45, so set ENETC4_MAX_SKB_FRAGS to MAX_SKB_FRAGS.
+ */
+#define ENETC4_MAX_SKB_FRAGS MAX_SKB_FRAGS
+#define ENETC_TXBDS_MAX_NEEDED(x) ENETC_TXBDS_NEEDED((x) + 1)
struct enetc_ring_stats {
unsigned int packets;
@@ -231,9 +250,12 @@ enum enetc_errata {
#define ENETC_SI_F_PSFP BIT(0)
#define ENETC_SI_F_QBV BIT(1)
#define ENETC_SI_F_QBU BIT(2)
+#define ENETC_SI_F_LSO BIT(3)
struct enetc_drvdata {
u32 pmac_offset; /* Only valid for PSI which supports 802.1Qbu */
+ u8 tx_csum:1;
+ u8 max_frags;
u64 sysclk_freq;
const struct ethtool_ops *eth_ops;
};
@@ -341,6 +363,8 @@ enum enetc_active_offloads {
ENETC_F_QBV = BIT(9),
ENETC_F_QCI = BIT(10),
ENETC_F_QBU = BIT(11),
+ ENETC_F_TXCSUM = BIT(12),
+ ENETC_F_LSO = BIT(13),
};
enum enetc_flags_bit {
@@ -375,6 +399,7 @@ struct enetc_ndev_priv {
u16 msg_enable;
u8 preemptible_tcs;
+ u8 max_frags; /* The maximum number of BDs for fragments */
enum enetc_active_offloads active_offloads;
diff --git a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
index 26b220677448..695cb07c74bc 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc4_hw.h
@@ -12,6 +12,29 @@
#define NXP_ENETC_VENDOR_ID 0x1131
#define NXP_ENETC_PF_DEV_ID 0xe101
+/**********************Station interface registers************************/
+/* Station interface LSO segmentation flag mask register 0/1 */
+#define ENETC4_SILSOSFMR0 0x1300
+#define SILSOSFMR0_TCP_MID_SEG GENMASK(27, 16)
+#define SILSOSFMR0_TCP_1ST_SEG GENMASK(11, 0)
+#define SILSOSFMR0_VAL_SET(first, mid) (FIELD_PREP(SILSOSFMR0_TCP_MID_SEG, mid) | \
+ FIELD_PREP(SILSOSFMR0_TCP_1ST_SEG, first))
+
+#define ENETC4_SILSOSFMR1 0x1304
+#define SILSOSFMR1_TCP_LAST_SEG GENMASK(11, 0)
+#define ENETC4_TCP_FLAGS_FIN BIT(0)
+#define ENETC4_TCP_FLAGS_SYN BIT(1)
+#define ENETC4_TCP_FLAGS_RST BIT(2)
+#define ENETC4_TCP_FLAGS_PSH BIT(3)
+#define ENETC4_TCP_FLAGS_ACK BIT(4)
+#define ENETC4_TCP_FLAGS_URG BIT(5)
+#define ENETC4_TCP_FLAGS_ECE BIT(6)
+#define ENETC4_TCP_FLAGS_CWR BIT(7)
+#define ENETC4_TCP_FLAGS_NS BIT(8)
+/* According to tso_build_hdr(), clear all special flags for not last packet. */
+#define ENETC4_TCP_NL_SEG_FLAGS_DMASK (ENETC4_TCP_FLAGS_FIN | \
+ ENETC4_TCP_FLAGS_RST | ENETC4_TCP_FLAGS_PSH)
+
/***************************ENETC port registers**************************/
#define ENETC4_ECAPR0 0x0
#define ECAPR0_RFS BIT(2)
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_hw.h b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
index 7c3285584f8a..4098f01479bc 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_hw.h
+++ b/drivers/net/ethernet/freescale/enetc/enetc_hw.h
@@ -23,11 +23,9 @@
#define ENETC_SICTR0 0x18
#define ENETC_SICTR1 0x1c
#define ENETC_SIPCAPR0 0x20
-#define ENETC_SIPCAPR0_PSFP BIT(9)
#define ENETC_SIPCAPR0_RSS BIT(8)
-#define ENETC_SIPCAPR0_QBV BIT(4)
-#define ENETC_SIPCAPR0_QBU BIT(3)
#define ENETC_SIPCAPR0_RFS BIT(2)
+#define ENETC_SIPCAPR0_LSO BIT(1)
#define ENETC_SIPCAPR1 0x24
#define ENETC_SITGTGR 0x30
#define ENETC_SIRBGCR 0x38
@@ -194,6 +192,9 @@ enum enetc_bdr_type {TX, RX};
#define ENETC_PCAPR0 0x0900
#define ENETC_PCAPR0_RXBDR(val) ((val) >> 24)
#define ENETC_PCAPR0_TXBDR(val) (((val) >> 16) & 0xff)
+#define ENETC_PCAPR0_PSFP BIT(9)
+#define ENETC_PCAPR0_QBV BIT(4)
+#define ENETC_PCAPR0_QBU BIT(3)
#define ENETC_PCAPR1 0x0904
#define ENETC_PSICFGR0(n) (0x0940 + (n) * 0xc) /* n = SI index */
#define ENETC_PSICFGR0_SET_TXBDR(val) ((val) & 0xff)
@@ -554,11 +555,23 @@ static inline u64 _enetc_rd_reg64_wa(void __iomem *reg)
union enetc_tx_bd {
struct {
__le64 addr;
- __le16 buf_len;
+ union {
+ __le16 buf_len;
+ __le16 hdr_len; /* For LSO, ENETC 4.1 and later */
+ };
__le16 frm_len;
union {
struct {
- u8 reserved[3];
+ u8 l3_aux0;
+#define ENETC_TX_BD_L3_START GENMASK(6, 0)
+#define ENETC_TX_BD_IPCS BIT(7)
+ u8 l3_aux1;
+#define ENETC_TX_BD_L3_HDR_LEN GENMASK(6, 0)
+#define ENETC_TX_BD_L3T BIT(7)
+ u8 l4_aux;
+#define ENETC_TX_BD_L4T GENMASK(7, 5)
+#define ENETC_TXBD_L4T_UDP 1
+#define ENETC_TXBD_L4T_TCP 2
u8 flags;
}; /* default layout */
__le32 txstart;
@@ -569,23 +582,27 @@ union enetc_tx_bd {
__le32 tstamp;
__le16 tpid;
__le16 vid;
- u8 reserved[6];
+ __le16 lso_sg_size; /* For ENETC 4.1 and later */
+ __le16 frm_len_ext; /* For ENETC 4.1 and later */
+ u8 reserved[2];
u8 e_flags;
u8 flags;
} ext; /* Tx BD extension */
struct {
__le32 tstamp;
- u8 reserved[10];
+ u8 reserved[8];
+ __le16 lso_err_count; /* For ENETC 4.1 and later */
u8 status;
u8 flags;
} wb; /* writeback descriptor */
};
enum enetc_txbd_flags {
- ENETC_TXBD_FLAGS_RES0 = BIT(0), /* reserved */
+ ENETC_TXBD_FLAGS_L4CS = BIT(0), /* For ENETC 4.1 and later */
ENETC_TXBD_FLAGS_TSE = BIT(1),
+ ENETC_TXBD_FLAGS_LSO = BIT(1), /* For ENETC 4.1 and later */
ENETC_TXBD_FLAGS_W = BIT(2),
- ENETC_TXBD_FLAGS_RES3 = BIT(3), /* reserved */
+ ENETC_TXBD_FLAGS_CSUM_LSO = BIT(3), /* For ENETC 4.1 and later */
ENETC_TXBD_FLAGS_TXSTART = BIT(4),
ENETC_TXBD_FLAGS_EX = BIT(6),
ENETC_TXBD_FLAGS_F = BIT(7)
@@ -654,6 +671,8 @@ union enetc_rx_bd {
#define ENETC_CBD_FLAGS_SF BIT(7) /* short format */
#define ENETC_CBD_STATUS_MASK 0xf
+#define ENETC_TPID_8021Q 0
+
struct enetc_cmd_rfse {
u8 smac_h[6];
u8 smac_m[6];
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
index c47b4a743d93..203862ec1114 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c
@@ -409,6 +409,23 @@ static void enetc_port_assign_rfs_entries(struct enetc_si *si)
enetc_port_wr(hw, ENETC_PRFSMR, ENETC_PRFSMR_RFSE);
}
+static void enetc_port_get_caps(struct enetc_si *si)
+{
+ struct enetc_hw *hw = &si->hw;
+ u32 val;
+
+ val = enetc_port_rd(hw, ENETC_PCAPR0);
+
+ if (val & ENETC_PCAPR0_QBV)
+ si->hw_features |= ENETC_SI_F_QBV;
+
+ if (val & ENETC_PCAPR0_QBU)
+ si->hw_features |= ENETC_SI_F_QBU;
+
+ if (val & ENETC_PCAPR0_PSFP)
+ si->hw_features |= ENETC_SI_F_PSFP;
+}
+
static void enetc_port_si_configure(struct enetc_si *si)
{
struct enetc_pf *pf = enetc_si_priv(si);
@@ -416,6 +433,8 @@ static void enetc_port_si_configure(struct enetc_si *si)
int num_rings, i;
u32 val;
+ enetc_port_get_caps(si);
+
val = enetc_port_rd(hw, ENETC_PCAPR0);
num_rings = min(ENETC_PCAPR0_RXBDR(val), ENETC_PCAPR0_TXBDR(val));
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
index 0eecfc833164..3fd9b0727875 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_pf_common.c
@@ -101,6 +101,7 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
priv->msg_enable = (NETIF_MSG_WOL << 1) - 1;
priv->sysclk_freq = si->drvdata->sysclk_freq;
+ priv->max_frags = si->drvdata->max_frags;
ndev->netdev_ops = ndev_ops;
enetc_set_ethtool_ops(ndev);
ndev->watchdog_timeo = 5 * HZ;
@@ -109,16 +110,24 @@ void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX |
NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK |
- NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
+ NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_GSO_UDP_L4;
ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
+ NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_GSO_UDP_L4;
ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
NETIF_F_TSO | NETIF_F_TSO6;
ndev->priv_flags |= IFF_UNICAST_FLT;
+ if (si->drvdata->tx_csum)
+ priv->active_offloads |= ENETC_F_TXCSUM;
+
+ if (si->hw_features & ENETC_SI_F_LSO)
+ priv->active_offloads |= ENETC_F_LSO;
+
/* TODO: currently, i.MX95 ENETC driver does not support advanced features */
if (!is_enetc_rev1(si)) {
ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK);
diff --git a/drivers/net/ethernet/freescale/enetc/enetc_vf.c b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
index a5f8ce576b6e..3768752b6008 100644
--- a/drivers/net/ethernet/freescale/enetc/enetc_vf.c
+++ b/drivers/net/ethernet/freescale/enetc/enetc_vf.c
@@ -136,6 +136,7 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
priv->msg_enable = (NETIF_MSG_IFUP << 1) - 1;
priv->sysclk_freq = si->drvdata->sysclk_freq;
+ priv->max_frags = si->drvdata->max_frags;
ndev->netdev_ops = ndev_ops;
enetc_set_ethtool_ops(ndev);
ndev->watchdog_timeo = 5 * HZ;
@@ -144,11 +145,13 @@ static void enetc_vf_netdev_setup(struct enetc_si *si, struct net_device *ndev,
ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
+ NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_GSO_UDP_L4;
ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM |
NETIF_F_HW_VLAN_CTAG_TX |
NETIF_F_HW_VLAN_CTAG_RX |
- NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6;
+ NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 |
+ NETIF_F_GSO_UDP_L4;
ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM |
NETIF_F_TSO | NETIF_F_TSO6;
diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h
index 1cca0425d493..c81f2ea588f2 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -671,8 +671,6 @@ struct fec_enet_private {
unsigned int tx_time_itr;
unsigned int itr_clk_rate;
- /* tx lpi eee mode */
- struct ethtool_keee eee;
unsigned int clk_ref_rate;
/* ptp clock period in ns*/
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 1b55047c0237..b2daed55bf6c 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -2045,14 +2045,14 @@ static int fec_enet_us_to_tx_cycle(struct net_device *ndev, int us)
return us * (fep->clk_ref_rate / 1000) / 1000;
}
-static int fec_enet_eee_mode_set(struct net_device *ndev, bool enable)
+static int fec_enet_eee_mode_set(struct net_device *ndev, u32 lpi_timer,
+ bool enable)
{
struct fec_enet_private *fep = netdev_priv(ndev);
- struct ethtool_keee *p = &fep->eee;
unsigned int sleep_cycle, wake_cycle;
if (enable) {
- sleep_cycle = fec_enet_us_to_tx_cycle(ndev, p->tx_lpi_timer);
+ sleep_cycle = fec_enet_us_to_tx_cycle(ndev, lpi_timer);
wake_cycle = sleep_cycle;
} else {
sleep_cycle = 0;
@@ -2105,7 +2105,9 @@ static void fec_enet_adjust_link(struct net_device *ndev)
napi_enable(&fep->napi);
}
if (fep->quirks & FEC_QUIRK_HAS_EEE)
- fec_enet_eee_mode_set(ndev, phy_dev->enable_tx_lpi);
+ fec_enet_eee_mode_set(ndev,
+ phy_dev->eee_cfg.tx_lpi_timer,
+ phy_dev->enable_tx_lpi);
} else {
if (fep->link) {
netif_stop_queue(ndev);
@@ -3181,7 +3183,6 @@ static int
fec_enet_get_eee(struct net_device *ndev, struct ethtool_keee *edata)
{
struct fec_enet_private *fep = netdev_priv(ndev);
- struct ethtool_keee *p = &fep->eee;
if (!(fep->quirks & FEC_QUIRK_HAS_EEE))
return -EOPNOTSUPP;
@@ -3189,8 +3190,6 @@ fec_enet_get_eee(struct net_device *ndev, struct ethtool_keee *edata)
if (!netif_running(ndev))
return -ENETDOWN;
- edata->tx_lpi_timer = p->tx_lpi_timer;
-
return phy_ethtool_get_eee(ndev->phydev, edata);
}
@@ -3198,7 +3197,6 @@ static int
fec_enet_set_eee(struct net_device *ndev, struct ethtool_keee *edata)
{
struct fec_enet_private *fep = netdev_priv(ndev);
- struct ethtool_keee *p = &fep->eee;
if (!(fep->quirks & FEC_QUIRK_HAS_EEE))
return -EOPNOTSUPP;
@@ -3206,8 +3204,6 @@ fec_enet_set_eee(struct net_device *ndev, struct ethtool_keee *edata)
if (!netif_running(ndev))
return -ENETDOWN;
- p->tx_lpi_timer = edata->tx_lpi_timer;
-
return phy_ethtool_set_eee(ndev->phydev, edata);
}
diff --git a/drivers/net/ethernet/freescale/fman/fman.c b/drivers/net/ethernet/freescale/fman/fman.c
index fb416d60dcd7..11887458f050 100644
--- a/drivers/net/ethernet/freescale/fman/fman.c
+++ b/drivers/net/ethernet/freescale/fman/fman.c
@@ -2690,13 +2690,12 @@ static struct fman *read_dts_node(struct platform_device *of_dev)
{
struct fman *fman;
struct device_node *fm_node, *muram_node;
+ void __iomem *base_addr;
struct resource *res;
u32 val, range[2];
int err, irq;
struct clk *clk;
u32 clk_rate;
- phys_addr_t phys_base_addr;
- resource_size_t mem_size;
fman = kzalloc(sizeof(*fman), GFP_KERNEL);
if (!fman)
@@ -2724,18 +2723,6 @@ static struct fman *read_dts_node(struct platform_device *of_dev)
goto fman_node_put;
fman->dts_params.err_irq = err;
- /* Get the FM address */
- res = platform_get_resource(of_dev, IORESOURCE_MEM, 0);
- if (!res) {
- err = -EINVAL;
- dev_err(&of_dev->dev, "%s: Can't get FMan memory resource\n",
- __func__);
- goto fman_node_put;
- }
-
- phys_base_addr = res->start;
- mem_size = resource_size(res);
-
clk = of_clk_get(fm_node, 0);
if (IS_ERR(clk)) {
err = PTR_ERR(clk);
@@ -2803,24 +2790,16 @@ static struct fman *read_dts_node(struct platform_device *of_dev)
}
}
- fman->dts_params.res =
- devm_request_mem_region(&of_dev->dev, phys_base_addr,
- mem_size, "fman");
- if (!fman->dts_params.res) {
- err = -EBUSY;
- dev_err(&of_dev->dev, "%s: request_mem_region() failed\n",
- __func__);
- goto fman_free;
- }
-
- fman->dts_params.base_addr =
- devm_ioremap(&of_dev->dev, phys_base_addr, mem_size);
- if (!fman->dts_params.base_addr) {
- err = -ENOMEM;
+ base_addr = devm_platform_get_and_ioremap_resource(of_dev, 0, &res);
+ if (IS_ERR(base_addr)) {
+ err = PTR_ERR(base_addr);
dev_err(&of_dev->dev, "%s: devm_ioremap() failed\n", __func__);
goto fman_free;
}
+ fman->dts_params.base_addr = base_addr;
+ fman->dts_params.res = res;
+
fman->dev = &of_dev->dev;
err = of_platform_populate(fm_node, NULL, NULL, &of_dev->dev);
diff --git a/drivers/net/ethernet/freescale/ucc_geth.c b/drivers/net/ethernet/freescale/ucc_geth.c
index 6663c1768089..88510f822759 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.c
+++ b/drivers/net/ethernet/freescale/ucc_geth.c
@@ -26,7 +26,7 @@
#include <linux/dma-mapping.h>
#include <linux/mii.h>
#include <linux/phy.h>
-#include <linux/phy_fixed.h>
+#include <linux/phylink.h>
#include <linux/workqueue.h>
#include <linux/of.h>
#include <linux/of_address.h>
@@ -34,6 +34,7 @@
#include <linux/of_mdio.h>
#include <linux/of_net.h>
#include <linux/platform_device.h>
+#include <linux/rtnetlink.h>
#include <linux/uaccess.h>
#include <asm/irq.h>
@@ -132,7 +133,6 @@ static const struct ucc_geth_info ugeth_primary_info = {
.transmitFlowControl = 1,
.maxGroupAddrInHash = 4,
.maxIndAddrInHash = 4,
- .prel = 7,
.maxFrameLength = 1518+16, /* Add extra bytes for VLANs etc. */
.minFrameLength = 64,
.maxD1Length = 1520+16, /* Add extra bytes for VLANs etc. */
@@ -1205,34 +1205,6 @@ static int init_mac_station_addr_regs(u8 address_byte_0,
return 0;
}
-static int init_check_frame_length_mode(int length_check,
- u32 __iomem *maccfg2_register)
-{
- u32 value = 0;
-
- value = in_be32(maccfg2_register);
-
- if (length_check)
- value |= MACCFG2_LC;
- else
- value &= ~MACCFG2_LC;
-
- out_be32(maccfg2_register, value);
- return 0;
-}
-
-static int init_preamble_length(u8 preamble_length,
- u32 __iomem *maccfg2_register)
-{
- if ((preamble_length < 3) || (preamble_length > 7))
- return -EINVAL;
-
- clrsetbits_be32(maccfg2_register, MACCFG2_PREL_MASK,
- preamble_length << MACCFG2_PREL_SHIFT);
-
- return 0;
-}
-
static int init_rx_parameters(int reject_broadcast,
int receive_short_frames,
int promiscuous, u32 __iomem *upsmr_register)
@@ -1287,94 +1259,11 @@ static int init_min_frame_len(u16 min_frame_length,
return 0;
}
-static int adjust_enet_interface(struct ucc_geth_private *ugeth)
+static bool phy_interface_mode_is_reduced(phy_interface_t interface)
{
- struct ucc_geth_info *ug_info;
- struct ucc_geth __iomem *ug_regs;
- struct ucc_fast __iomem *uf_regs;
- int ret_val;
- u32 upsmr, maccfg2;
- u16 value;
-
- ugeth_vdbg("%s: IN", __func__);
-
- ug_info = ugeth->ug_info;
- ug_regs = ugeth->ug_regs;
- uf_regs = ugeth->uccf->uf_regs;
-
- /* Set MACCFG2 */
- maccfg2 = in_be32(&ug_regs->maccfg2);
- maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK;
- if ((ugeth->max_speed == SPEED_10) ||
- (ugeth->max_speed == SPEED_100))
- maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
- else if (ugeth->max_speed == SPEED_1000)
- maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
- maccfg2 |= ug_info->padAndCrc;
- out_be32(&ug_regs->maccfg2, maccfg2);
-
- /* Set UPSMR */
- upsmr = in_be32(&uf_regs->upsmr);
- upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M |
- UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM);
- if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
- if (ugeth->phy_interface != PHY_INTERFACE_MODE_RMII)
- upsmr |= UCC_GETH_UPSMR_RPM;
- switch (ugeth->max_speed) {
- case SPEED_10:
- upsmr |= UCC_GETH_UPSMR_R10M;
- fallthrough;
- case SPEED_100:
- if (ugeth->phy_interface != PHY_INTERFACE_MODE_RTBI)
- upsmr |= UCC_GETH_UPSMR_RMM;
- }
- }
- if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
- upsmr |= UCC_GETH_UPSMR_TBIM;
- }
- if (ugeth->phy_interface == PHY_INTERFACE_MODE_SGMII)
- upsmr |= UCC_GETH_UPSMR_SGMM;
-
- out_be32(&uf_regs->upsmr, upsmr);
-
- /* Disable autonegotiation in tbi mode, because by default it
- comes up in autonegotiation mode. */
- /* Note that this depends on proper setting in utbipar register. */
- if ((ugeth->phy_interface == PHY_INTERFACE_MODE_TBI) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
- struct ucc_geth_info *ug_info = ugeth->ug_info;
- struct phy_device *tbiphy;
-
- if (!ug_info->tbi_node)
- pr_warn("TBI mode requires that the device tree specify a tbi-handle\n");
-
- tbiphy = of_phy_find_device(ug_info->tbi_node);
- if (!tbiphy)
- pr_warn("Could not get TBI device\n");
-
- value = phy_read(tbiphy, ENET_TBI_MII_CR);
- value &= ~0x1000; /* Turn off autonegotiation */
- phy_write(tbiphy, ENET_TBI_MII_CR, value);
-
- put_device(&tbiphy->mdio.dev);
- }
-
- init_check_frame_length_mode(ug_info->lengthCheckRx, &ug_regs->maccfg2);
-
- ret_val = init_preamble_length(ug_info->prel, &ug_regs->maccfg2);
- if (ret_val != 0) {
- if (netif_msg_probe(ugeth))
- pr_err("Preamble length must be between 3 and 7 inclusive\n");
- return ret_val;
- }
-
- return 0;
+ return phy_interface_mode_is_rgmii(interface) ||
+ interface == PHY_INTERFACE_MODE_RMII ||
+ interface == PHY_INTERFACE_MODE_RTBI;
}
static int ugeth_graceful_stop_tx(struct ucc_geth_private *ugeth)
@@ -1545,108 +1434,7 @@ static void ugeth_activate(struct ucc_geth_private *ugeth)
/* allow to xmit again */
netif_tx_wake_all_queues(ugeth->ndev);
- __netdev_watchdog_up(ugeth->ndev);
-}
-
-/* Called every time the controller might need to be made
- * aware of new link state. The PHY code conveys this
- * information through variables in the ugeth structure, and this
- * function converts those variables into the appropriate
- * register values, and can bring down the device if needed.
- */
-
-static void adjust_link(struct net_device *dev)
-{
- struct ucc_geth_private *ugeth = netdev_priv(dev);
- struct ucc_geth __iomem *ug_regs;
- struct ucc_fast __iomem *uf_regs;
- struct phy_device *phydev = ugeth->phydev;
- int new_state = 0;
-
- ug_regs = ugeth->ug_regs;
- uf_regs = ugeth->uccf->uf_regs;
-
- if (phydev->link) {
- u32 tempval = in_be32(&ug_regs->maccfg2);
- u32 upsmr = in_be32(&uf_regs->upsmr);
- /* Now we make sure that we can be in full duplex mode.
- * If not, we operate in half-duplex mode. */
- if (phydev->duplex != ugeth->oldduplex) {
- new_state = 1;
- if (!(phydev->duplex))
- tempval &= ~(MACCFG2_FDX);
- else
- tempval |= MACCFG2_FDX;
- ugeth->oldduplex = phydev->duplex;
- }
-
- if (phydev->speed != ugeth->oldspeed) {
- new_state = 1;
- switch (phydev->speed) {
- case SPEED_1000:
- tempval = ((tempval &
- ~(MACCFG2_INTERFACE_MODE_MASK)) |
- MACCFG2_INTERFACE_MODE_BYTE);
- break;
- case SPEED_100:
- case SPEED_10:
- tempval = ((tempval &
- ~(MACCFG2_INTERFACE_MODE_MASK)) |
- MACCFG2_INTERFACE_MODE_NIBBLE);
- /* if reduced mode, re-set UPSMR.R10M */
- if ((ugeth->phy_interface == PHY_INTERFACE_MODE_RMII) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_ID) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RGMII_TXID) ||
- (ugeth->phy_interface == PHY_INTERFACE_MODE_RTBI)) {
- if (phydev->speed == SPEED_10)
- upsmr |= UCC_GETH_UPSMR_R10M;
- else
- upsmr &= ~UCC_GETH_UPSMR_R10M;
- }
- break;
- default:
- if (netif_msg_link(ugeth))
- pr_warn(
- "%s: Ack! Speed (%d) is not 10/100/1000!",
- dev->name, phydev->speed);
- break;
- }
- ugeth->oldspeed = phydev->speed;
- }
-
- if (!ugeth->oldlink) {
- new_state = 1;
- ugeth->oldlink = 1;
- }
-
- if (new_state) {
- /*
- * To change the MAC configuration we need to disable
- * the controller. To do so, we have to either grab
- * ugeth->lock, which is a bad idea since 'graceful
- * stop' commands might take quite a while, or we can
- * quiesce driver's activity.
- */
- ugeth_quiesce(ugeth);
- ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
-
- out_be32(&ug_regs->maccfg2, tempval);
- out_be32(&uf_regs->upsmr, upsmr);
-
- ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
- ugeth_activate(ugeth);
- }
- } else if (ugeth->oldlink) {
- new_state = 1;
- ugeth->oldlink = 0;
- ugeth->oldspeed = 0;
- ugeth->oldduplex = -1;
- }
-
- if (new_state && netif_msg_link(ugeth))
- phy_print_status(phydev);
+ netdev_watchdog_up(ugeth->ndev);
}
/* Initialize TBI PHY interface for communicating with the
@@ -1664,8 +1452,7 @@ static void uec_configure_serdes(struct net_device *dev)
struct phy_device *tbiphy;
if (!ug_info->tbi_node) {
- dev_warn(&dev->dev, "SGMII mode requires that the device "
- "tree specify a tbi-handle\n");
+ dev_warn(&dev->dev, "SGMII mode requires that the device tree specify a tbi-handle\n");
return;
}
@@ -1696,34 +1483,145 @@ static void uec_configure_serdes(struct net_device *dev)
put_device(&tbiphy->mdio.dev);
}
-/* Configure the PHY for dev.
- * returns 0 if success. -1 if failure
- */
-static int init_phy(struct net_device *dev)
+static void ugeth_mac_link_up(struct phylink_config *config, struct phy_device *phy,
+ unsigned int mode, phy_interface_t interface,
+ int speed, int duplex, bool tx_pause, bool rx_pause)
{
- struct ucc_geth_private *priv = netdev_priv(dev);
- struct ucc_geth_info *ug_info = priv->ug_info;
- struct phy_device *phydev;
+ struct net_device *ndev = to_net_dev(config->dev);
+ struct ucc_geth_private *ugeth = netdev_priv(ndev);
+ struct ucc_geth_info *ug_info = ugeth->ug_info;
+ struct ucc_geth __iomem *ug_regs = ugeth->ug_regs;
+ struct ucc_fast __iomem *uf_regs = ugeth->uccf->uf_regs;
+ u32 old_maccfg2, maccfg2 = in_be32(&ug_regs->maccfg2);
+ u32 old_upsmr, upsmr = in_be32(&uf_regs->upsmr);
- priv->oldlink = 0;
- priv->oldspeed = 0;
- priv->oldduplex = -1;
+ old_maccfg2 = maccfg2;
+ old_upsmr = upsmr;
- phydev = of_phy_connect(dev, ug_info->phy_node, &adjust_link, 0,
- priv->phy_interface);
- if (!phydev) {
- dev_err(&dev->dev, "Could not attach to PHY\n");
- return -ENODEV;
+ /* No length check */
+ maccfg2 &= ~MACCFG2_LC;
+ maccfg2 &= ~MACCFG2_INTERFACE_MODE_MASK;
+ upsmr &= ~(UCC_GETH_UPSMR_RPM | UCC_GETH_UPSMR_R10M |
+ UCC_GETH_UPSMR_TBIM | UCC_GETH_UPSMR_RMM);
+
+ if (speed == SPEED_10 || speed == SPEED_100)
+ maccfg2 |= MACCFG2_INTERFACE_MODE_NIBBLE;
+ else if (speed == SPEED_1000)
+ maccfg2 |= MACCFG2_INTERFACE_MODE_BYTE;
+
+ maccfg2 |= ug_info->padAndCrc;
+
+ if (phy_interface_mode_is_reduced(interface)) {
+
+ if (interface != PHY_INTERFACE_MODE_RMII)
+ upsmr |= UCC_GETH_UPSMR_RPM;
+
+ switch (speed) {
+ case SPEED_10:
+ upsmr |= UCC_GETH_UPSMR_R10M;
+ fallthrough;
+ case SPEED_100:
+ if (interface != PHY_INTERFACE_MODE_RTBI)
+ upsmr |= UCC_GETH_UPSMR_RMM;
+ }
}
- if (priv->phy_interface == PHY_INTERFACE_MODE_SGMII)
- uec_configure_serdes(dev);
+ if (interface == PHY_INTERFACE_MODE_TBI ||
+ interface == PHY_INTERFACE_MODE_RTBI)
+ upsmr |= UCC_GETH_UPSMR_TBIM;
- phy_set_max_speed(phydev, priv->max_speed);
+ if (interface == PHY_INTERFACE_MODE_SGMII)
+ upsmr |= UCC_GETH_UPSMR_SGMM;
- priv->phydev = phydev;
+ if (duplex == DUPLEX_HALF)
+ maccfg2 &= ~(MACCFG2_FDX);
+ else
+ maccfg2 |= MACCFG2_FDX;
- return 0;
+ if (maccfg2 != old_maccfg2 || upsmr != old_upsmr) {
+ /*
+ * To change the MAC configuration we need to disable
+ * the controller. To do so, we have to either grab
+ * ugeth->lock, which is a bad idea since 'graceful
+ * stop' commands might take quite a while, or we can
+ * quiesce driver's activity.
+ */
+ ugeth_quiesce(ugeth);
+ ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+
+ out_be32(&ug_regs->maccfg2, maccfg2);
+ out_be32(&uf_regs->upsmr, upsmr);
+
+ ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+ ugeth_activate(ugeth);
+ }
+
+ if (interface == PHY_INTERFACE_MODE_SGMII)
+ uec_configure_serdes(ndev);
+
+ if (!phylink_autoneg_inband(mode)) {
+ ug_info->aufc = 0;
+ ug_info->receiveFlowControl = rx_pause;
+ ug_info->transmitFlowControl = tx_pause;
+
+ init_flow_control_params(ug_info->aufc,
+ ug_info->receiveFlowControl,
+ ug_info->transmitFlowControl,
+ ug_info->pausePeriod,
+ ug_info->extensionField,
+ &ugeth->uccf->uf_regs->upsmr,
+ &ugeth->ug_regs->uempr,
+ &ugeth->ug_regs->maccfg1);
+ }
+
+ ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
+}
+
+static void ugeth_mac_link_down(struct phylink_config *config,
+ unsigned int mode, phy_interface_t interface)
+{
+ struct net_device *ndev = to_net_dev(config->dev);
+ struct ucc_geth_private *ugeth = netdev_priv(ndev);
+
+ ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
+}
+
+static void ugeth_mac_config(struct phylink_config *config, unsigned int mode,
+ const struct phylink_link_state *state)
+{
+ struct net_device *ndev = to_net_dev(config->dev);
+ struct ucc_geth_private *ugeth = netdev_priv(ndev);
+ struct ucc_geth_info *ug_info = ugeth->ug_info;
+ u16 value;
+
+ if (state->interface == PHY_INTERFACE_MODE_TBI ||
+ state->interface == PHY_INTERFACE_MODE_RTBI) {
+ struct phy_device *tbiphy;
+
+ if (!ug_info->tbi_node)
+ pr_warn("TBI mode requires that the device tree specify a tbi-handle\n");
+
+ tbiphy = of_phy_find_device(ug_info->tbi_node);
+ if (!tbiphy)
+ pr_warn("Could not get TBI device\n");
+
+ value = phy_read(tbiphy, ENET_TBI_MII_CR);
+ value &= ~0x1000; /* Turn off autonegotiation */
+ phy_write(tbiphy, ENET_TBI_MII_CR, value);
+
+ put_device(&tbiphy->mdio.dev);
+ }
+
+ if (phylink_autoneg_inband(mode)) {
+ ug_info->aufc = 1;
+
+ init_flow_control_params(ug_info->aufc, 1, 1,
+ ug_info->pausePeriod,
+ ug_info->extensionField,
+ &ugeth->uccf->uf_regs->upsmr,
+ &ugeth->ug_regs->uempr,
+ &ugeth->ug_regs->maccfg1);
+ }
}
static void ugeth_dump_regs(struct ucc_geth_private *ugeth)
@@ -1995,7 +1893,6 @@ static void ucc_geth_set_multi(struct net_device *dev)
static void ucc_geth_stop(struct ucc_geth_private *ugeth)
{
struct ucc_geth __iomem *ug_regs = ugeth->ug_regs;
- struct phy_device *phydev = ugeth->phydev;
ugeth_vdbg("%s: IN", __func__);
@@ -2004,7 +1901,7 @@ static void ucc_geth_stop(struct ucc_geth_private *ugeth)
* Must be done before disabling the controller
* or deadlock may happen.
*/
- phy_stop(phydev);
+ phylink_stop(ugeth->phylink);
/* Disable the controller */
ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
@@ -3246,12 +3143,6 @@ static int ucc_geth_init_mac(struct ucc_geth_private *ugeth)
goto err;
}
- err = adjust_enet_interface(ugeth);
- if (err) {
- netif_err(ugeth, ifup, dev, "Cannot configure net device, aborting\n");
- goto err;
- }
-
/* Set MACSTNADDR1, MACSTNADDR2 */
/* For more details see the hardware spec. */
init_mac_station_addr_regs(dev->dev_addr[0],
@@ -3263,12 +3154,6 @@ static int ucc_geth_init_mac(struct ucc_geth_private *ugeth)
&ugeth->ug_regs->macstnaddr1,
&ugeth->ug_regs->macstnaddr2);
- err = ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
- if (err) {
- netif_err(ugeth, ifup, dev, "Cannot enable net device, aborting\n");
- goto err;
- }
-
return 0;
err:
ucc_geth_stop(ugeth);
@@ -3291,10 +3176,10 @@ static int ucc_geth_open(struct net_device *dev)
return -EINVAL;
}
- err = init_phy(dev);
+ err = phylink_of_phy_connect(ugeth->phylink, ugeth->dev->of_node, 0);
if (err) {
- netif_err(ugeth, ifup, dev, "Cannot initialize PHY, aborting\n");
- return err;
+ dev_err(&dev->dev, "Could not attach to PHY\n");
+ return -ENODEV;
}
err = ucc_geth_init_mac(ugeth);
@@ -3310,13 +3195,13 @@ static int ucc_geth_open(struct net_device *dev)
goto err;
}
- phy_start(ugeth->phydev);
+ phylink_start(ugeth->phylink);
napi_enable(&ugeth->napi);
netdev_reset_queue(dev);
netif_start_queue(dev);
device_set_wakeup_capable(&dev->dev,
- qe_alive_during_sleep() || ugeth->phydev->irq);
+ qe_alive_during_sleep() || dev->phydev->irq);
device_set_wakeup_enable(&dev->dev, ugeth->wol_en);
return err;
@@ -3337,8 +3222,7 @@ static int ucc_geth_close(struct net_device *dev)
cancel_work_sync(&ugeth->timeout_work);
ucc_geth_stop(ugeth);
- phy_disconnect(ugeth->phydev);
- ugeth->phydev = NULL;
+ phylink_disconnect_phy(ugeth->phylink);
free_irq(ugeth->ug_info->uf_info.irq, ugeth->ndev);
@@ -3372,7 +3256,7 @@ static void ucc_geth_timeout_work(struct work_struct *work)
ucc_geth_stop(ugeth);
ucc_geth_init_mac(ugeth);
/* Must start PHY here */
- phy_start(ugeth->phydev);
+ phylink_start(ugeth->phylink);
netif_tx_start_all_queues(dev);
}
@@ -3397,6 +3281,7 @@ static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state)
{
struct net_device *ndev = platform_get_drvdata(ofdev);
struct ucc_geth_private *ugeth = netdev_priv(ndev);
+ bool mac_wol = false;
if (!netif_running(ndev))
return 0;
@@ -3410,14 +3295,17 @@ static int ucc_geth_suspend(struct platform_device *ofdev, pm_message_t state)
*/
ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
- if (ugeth->wol_en & WAKE_MAGIC) {
+ if (ugeth->wol_en & WAKE_MAGIC && !ugeth->phy_wol_en) {
setbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
setbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
ucc_fast_enable(ugeth->uccf, COMM_DIR_RX_AND_TX);
- } else if (!(ugeth->wol_en & WAKE_PHY)) {
- phy_stop(ugeth->phydev);
+ mac_wol = true;
}
+ rtnl_lock();
+ phylink_suspend(ugeth->phylink, mac_wol);
+ rtnl_unlock();
+
return 0;
}
@@ -3451,12 +3339,9 @@ static int ucc_geth_resume(struct platform_device *ofdev)
}
}
- ugeth->oldlink = 0;
- ugeth->oldspeed = 0;
- ugeth->oldduplex = -1;
-
- phy_stop(ugeth->phydev);
- phy_start(ugeth->phydev);
+ rtnl_lock();
+ phylink_resume(ugeth->phylink);
+ rtnl_unlock();
napi_enable(&ugeth->napi);
netif_device_attach(ndev);
@@ -3469,32 +3354,6 @@ static int ucc_geth_resume(struct platform_device *ofdev)
#define ucc_geth_resume NULL
#endif
-static phy_interface_t to_phy_interface(const char *phy_connection_type)
-{
- if (strcasecmp(phy_connection_type, "mii") == 0)
- return PHY_INTERFACE_MODE_MII;
- if (strcasecmp(phy_connection_type, "gmii") == 0)
- return PHY_INTERFACE_MODE_GMII;
- if (strcasecmp(phy_connection_type, "tbi") == 0)
- return PHY_INTERFACE_MODE_TBI;
- if (strcasecmp(phy_connection_type, "rmii") == 0)
- return PHY_INTERFACE_MODE_RMII;
- if (strcasecmp(phy_connection_type, "rgmii") == 0)
- return PHY_INTERFACE_MODE_RGMII;
- if (strcasecmp(phy_connection_type, "rgmii-id") == 0)
- return PHY_INTERFACE_MODE_RGMII_ID;
- if (strcasecmp(phy_connection_type, "rgmii-txid") == 0)
- return PHY_INTERFACE_MODE_RGMII_TXID;
- if (strcasecmp(phy_connection_type, "rgmii-rxid") == 0)
- return PHY_INTERFACE_MODE_RGMII_RXID;
- if (strcasecmp(phy_connection_type, "rtbi") == 0)
- return PHY_INTERFACE_MODE_RTBI;
- if (strcasecmp(phy_connection_type, "sgmii") == 0)
- return PHY_INTERFACE_MODE_SGMII;
-
- return PHY_INTERFACE_MODE_MII;
-}
-
static int ucc_geth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
{
struct ucc_geth_private *ugeth = netdev_priv(dev);
@@ -3502,10 +3361,7 @@ static int ucc_geth_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
if (!netif_running(dev))
return -EINVAL;
- if (!ugeth->phydev)
- return -ENODEV;
-
- return phy_mii_ioctl(ugeth->phydev, rq, cmd);
+ return phylink_mii_ioctl(ugeth->phylink, rq, cmd);
}
static const struct net_device_ops ucc_geth_netdev_ops = {
@@ -3513,7 +3369,6 @@ static const struct net_device_ops ucc_geth_netdev_ops = {
.ndo_stop = ucc_geth_close,
.ndo_start_xmit = ucc_geth_start_xmit,
.ndo_validate_addr = eth_validate_addr,
- .ndo_change_carrier = fixed_phy_change_carrier,
.ndo_set_mac_address = ucc_geth_set_mac_addr,
.ndo_set_rx_mode = ucc_geth_set_multi,
.ndo_tx_timeout = ucc_geth_timeout,
@@ -3553,6 +3408,12 @@ static int ucc_geth_parse_clock(struct device_node *np, const char *which,
return 0;
}
+struct phylink_mac_ops ugeth_mac_ops = {
+ .mac_link_up = ugeth_mac_link_up,
+ .mac_link_down = ugeth_mac_link_down,
+ .mac_config = ugeth_mac_config,
+};
+
static int ucc_geth_probe(struct platform_device* ofdev)
{
struct device *device = &ofdev->dev;
@@ -3560,23 +3421,12 @@ static int ucc_geth_probe(struct platform_device* ofdev)
struct net_device *dev = NULL;
struct ucc_geth_private *ugeth = NULL;
struct ucc_geth_info *ug_info;
+ struct device_node *phy_node;
+ struct phylink *phylink;
struct resource res;
- int err, ucc_num, max_speed = 0;
+ int err, ucc_num;
const unsigned int *prop;
phy_interface_t phy_interface;
- static const int enet_to_speed[] = {
- SPEED_10, SPEED_10, SPEED_10,
- SPEED_100, SPEED_100, SPEED_100,
- SPEED_1000, SPEED_1000, SPEED_1000, SPEED_1000,
- };
- static const phy_interface_t enet_to_phy_interface[] = {
- PHY_INTERFACE_MODE_MII, PHY_INTERFACE_MODE_RMII,
- PHY_INTERFACE_MODE_RGMII, PHY_INTERFACE_MODE_MII,
- PHY_INTERFACE_MODE_RMII, PHY_INTERFACE_MODE_RGMII,
- PHY_INTERFACE_MODE_GMII, PHY_INTERFACE_MODE_RGMII,
- PHY_INTERFACE_MODE_TBI, PHY_INTERFACE_MODE_RTBI,
- PHY_INTERFACE_MODE_SGMII,
- };
ugeth_vdbg("%s: IN", __func__);
@@ -3612,57 +3462,35 @@ static int ucc_geth_probe(struct platform_device* ofdev)
ug_info->uf_info.regs = res.start;
ug_info->uf_info.irq = irq_of_parse_and_map(np, 0);
- ug_info->phy_node = of_parse_phandle(np, "phy-handle", 0);
- if (!ug_info->phy_node && of_phy_is_fixed_link(np)) {
- /*
- * In the case of a fixed PHY, the DT node associated
- * to the PHY is the Ethernet MAC DT node.
- */
- err = of_phy_register_fixed_link(np);
- if (err)
- return err;
- ug_info->phy_node = of_node_get(np);
- }
-
/* Find the TBI PHY node. If it's not there, we don't support SGMII */
ug_info->tbi_node = of_parse_phandle(np, "tbi-handle", 0);
- /* get the phy interface type, or default to MII */
- prop = of_get_property(np, "phy-connection-type", NULL);
- if (!prop) {
- /* handle interface property present in old trees */
- prop = of_get_property(ug_info->phy_node, "interface", NULL);
- if (prop != NULL) {
- phy_interface = enet_to_phy_interface[*prop];
- max_speed = enet_to_speed[*prop];
- } else
- phy_interface = PHY_INTERFACE_MODE_MII;
- } else {
- phy_interface = to_phy_interface((const char *)prop);
- }
-
- /* get speed, or derive from PHY interface */
- if (max_speed == 0)
- switch (phy_interface) {
- case PHY_INTERFACE_MODE_GMII:
- case PHY_INTERFACE_MODE_RGMII:
- case PHY_INTERFACE_MODE_RGMII_ID:
- case PHY_INTERFACE_MODE_RGMII_RXID:
- case PHY_INTERFACE_MODE_RGMII_TXID:
- case PHY_INTERFACE_MODE_TBI:
- case PHY_INTERFACE_MODE_RTBI:
- case PHY_INTERFACE_MODE_SGMII:
- max_speed = SPEED_1000;
- break;
- default:
- max_speed = SPEED_100;
- break;
+ phy_node = of_parse_phandle(np, "phy-handle", 0);
+ if (phy_node) {
+ prop = of_get_property(phy_node, "interface", NULL);
+ if (prop) {
+ dev_err(&ofdev->dev,
+ "Device-tree property 'interface' is no longer supported. Please use 'phy-connection-type' instead.");
+ of_node_put(phy_node);
+ err = -EINVAL;
+ goto err_put_tbi;
}
+ of_node_put(phy_node);
+ }
+
+ err = of_get_phy_mode(np, &phy_interface);
+ if (err) {
+ dev_err(&ofdev->dev, "Invalid phy-connection-type");
+ goto err_put_tbi;
+ }
- if (max_speed == SPEED_1000) {
+ if (phy_interface == PHY_INTERFACE_MODE_GMII ||
+ phy_interface_mode_is_rgmii(phy_interface) ||
+ phy_interface == PHY_INTERFACE_MODE_TBI ||
+ phy_interface == PHY_INTERFACE_MODE_RTBI ||
+ phy_interface == PHY_INTERFACE_MODE_SGMII) {
unsigned int snums = qe_get_num_of_snums();
- /* configure muram FIFOs for gigabit operation */
ug_info->uf_info.urfs = UCC_GETH_URFS_GIGA_INIT;
ug_info->uf_info.urfet = UCC_GETH_URFET_GIGA_INIT;
ug_info->uf_info.urfset = UCC_GETH_URFSET_GIGA_INIT;
@@ -3691,7 +3519,7 @@ static int ucc_geth_probe(struct platform_device* ofdev)
dev = devm_alloc_etherdev(&ofdev->dev, sizeof(*ugeth));
if (!dev) {
err = -ENOMEM;
- goto err_deregister_fixed_link;
+ goto err_put_tbi;
}
ugeth = netdev_priv(dev);
@@ -3718,23 +3546,50 @@ static int ucc_geth_probe(struct platform_device* ofdev)
dev->max_mtu = 1518;
ugeth->msg_enable = netif_msg_init(debug.msg_enable, UGETH_MSG_DEFAULT);
- ugeth->phy_interface = phy_interface;
- ugeth->max_speed = max_speed;
- /* Carrier starts down, phylib will bring it up */
- netif_carrier_off(dev);
+ ugeth->phylink_config.dev = &dev->dev;
+ ugeth->phylink_config.type = PHYLINK_NETDEV;
+
+ ugeth->phylink_config.mac_capabilities =
+ MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD;
+
+ __set_bit(PHY_INTERFACE_MODE_MII,
+ ugeth->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_RMII,
+ ugeth->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_GMII,
+ ugeth->phylink_config.supported_interfaces);
+ phy_interface_set_rgmii(ugeth->phylink_config.supported_interfaces);
+
+ if (ug_info->tbi_node) {
+ __set_bit(PHY_INTERFACE_MODE_SGMII,
+ ugeth->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_TBI,
+ ugeth->phylink_config.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_RTBI,
+ ugeth->phylink_config.supported_interfaces);
+ }
+
+ phylink = phylink_create(&ugeth->phylink_config, dev_fwnode(&dev->dev),
+ phy_interface, &ugeth_mac_ops);
+ if (IS_ERR(phylink)) {
+ err = PTR_ERR(phylink);
+ goto err_put_tbi;
+ }
+
+ ugeth->phylink = phylink;
err = devm_register_netdev(&ofdev->dev, dev);
if (err) {
if (netif_msg_probe(ugeth))
pr_err("%s: Cannot register net device, aborting\n",
dev->name);
- goto err_deregister_fixed_link;
+ goto err_destroy_phylink;
}
err = of_get_ethdev_address(np, dev);
if (err == -EPROBE_DEFER)
- goto err_deregister_fixed_link;
+ goto err_destroy_phylink;
ugeth->ug_info = ug_info;
ugeth->dev = device;
@@ -3743,11 +3598,11 @@ static int ucc_geth_probe(struct platform_device* ofdev)
return 0;
-err_deregister_fixed_link:
- if (of_phy_is_fixed_link(np))
- of_phy_deregister_fixed_link(np);
+err_destroy_phylink:
+ phylink_destroy(phylink);
+err_put_tbi:
of_node_put(ug_info->tbi_node);
- of_node_put(ug_info->phy_node);
+
return err;
}
@@ -3755,13 +3610,10 @@ static void ucc_geth_remove(struct platform_device* ofdev)
{
struct net_device *dev = platform_get_drvdata(ofdev);
struct ucc_geth_private *ugeth = netdev_priv(dev);
- struct device_node *np = ofdev->dev.of_node;
ucc_geth_memclean(ugeth);
- if (of_phy_is_fixed_link(np))
- of_phy_deregister_fixed_link(np);
+ phylink_destroy(ugeth->phylink);
of_node_put(ugeth->ug_info->tbi_node);
- of_node_put(ugeth->ug_info->phy_node);
}
static const struct of_device_id ucc_geth_match[] = {
diff --git a/drivers/net/ethernet/freescale/ucc_geth.h b/drivers/net/ethernet/freescale/ucc_geth.h
index 4294ed096ebb..38789faae706 100644
--- a/drivers/net/ethernet/freescale/ucc_geth.h
+++ b/drivers/net/ethernet/freescale/ucc_geth.h
@@ -16,6 +16,7 @@
#include <linux/kernel.h>
#include <linux/list.h>
+#include <linux/phylink.h>
#include <linux/if_ether.h>
#include <soc/fsl/qe/immap_qe.h>
@@ -921,7 +922,8 @@ struct ucc_geth_hardware_statistics {
#define UCC_GETH_UPSMR_INIT UCC_GETH_UPSMR_RES1
#define UCC_GETH_MACCFG1_INIT 0
-#define UCC_GETH_MACCFG2_INIT (MACCFG2_RESERVED_1)
+#define UCC_GETH_MACCFG2_INIT (MACCFG2_RESERVED_1 | \
+ (7 << MACCFG2_PREL_SHIFT))
/* Ethernet Address Type. */
enum enet_addr_type {
@@ -1073,6 +1075,9 @@ struct ucc_geth_tad_params {
u16 vid;
};
+struct phylink;
+struct phylink_config;
+
/* GETH protocol initialization structure */
struct ucc_geth_info {
struct ucc_fast_info uf_info;
@@ -1088,7 +1093,6 @@ struct ucc_geth_info {
u8 miminumInterFrameGapEnforcement;
u8 backToBackInterFrameGap;
int ipAddressAlignment;
- int lengthCheckRx;
u32 mblinterval;
u16 nortsrbytetime;
u8 fracsiz;
@@ -1114,7 +1118,6 @@ struct ucc_geth_info {
int transmitFlowControl;
u8 maxGroupAddrInHash;
u8 maxIndAddrInHash;
- u8 prel;
u16 maxFrameLength;
u16 minFrameLength;
u16 maxD1Length;
@@ -1125,7 +1128,6 @@ struct ucc_geth_info {
u32 eventRegMask;
u16 pausePeriod;
u16 extensionField;
- struct device_node *phy_node;
struct device_node *tbi_node;
u8 weightfactor[NUM_TX_QUEUES];
u8 interruptcoalescingmaxvalue[NUM_RX_QUEUES];
@@ -1210,14 +1212,12 @@ struct ucc_geth_private {
u16 skb_dirtytx[NUM_TX_QUEUES];
struct ugeth_mii_info *mii_info;
- struct phy_device *phydev;
- phy_interface_t phy_interface;
- int max_speed;
uint32_t msg_enable;
- int oldspeed;
- int oldduplex;
- int oldlink;
- int wol_en;
+ u32 wol_en;
+ u32 phy_wol_en;
+
+ struct phylink *phylink;
+ struct phylink_config phylink_config;
struct device_node *node;
};
diff --git a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
index 699f346faf5c..1fb49e5a414a 100644
--- a/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
+++ b/drivers/net/ethernet/freescale/ucc_geth_ethtool.c
@@ -104,14 +104,8 @@ static int
uec_get_ksettings(struct net_device *netdev, struct ethtool_link_ksettings *cmd)
{
struct ucc_geth_private *ugeth = netdev_priv(netdev);
- struct phy_device *phydev = ugeth->phydev;
- if (!phydev)
- return -ENODEV;
-
- phy_ethtool_ksettings_get(phydev, cmd);
-
- return 0;
+ return phylink_ethtool_ksettings_get(ugeth->phylink, cmd);
}
static int
@@ -119,12 +113,8 @@ uec_set_ksettings(struct net_device *netdev,
const struct ethtool_link_ksettings *cmd)
{
struct ucc_geth_private *ugeth = netdev_priv(netdev);
- struct phy_device *phydev = ugeth->phydev;
- if (!phydev)
- return -ENODEV;
-
- return phy_ethtool_ksettings_set(phydev, cmd);
+ return phylink_ethtool_ksettings_set(ugeth->phylink, cmd);
}
static void
@@ -133,12 +123,7 @@ uec_get_pauseparam(struct net_device *netdev,
{
struct ucc_geth_private *ugeth = netdev_priv(netdev);
- pause->autoneg = ugeth->phydev->autoneg;
-
- if (ugeth->ug_info->receiveFlowControl)
- pause->rx_pause = 1;
- if (ugeth->ug_info->transmitFlowControl)
- pause->tx_pause = 1;
+ return phylink_ethtool_get_pauseparam(ugeth->phylink, pause);
}
static int
@@ -146,30 +131,11 @@ uec_set_pauseparam(struct net_device *netdev,
struct ethtool_pauseparam *pause)
{
struct ucc_geth_private *ugeth = netdev_priv(netdev);
- int ret = 0;
ugeth->ug_info->receiveFlowControl = pause->rx_pause;
ugeth->ug_info->transmitFlowControl = pause->tx_pause;
- if (ugeth->phydev->autoneg) {
- if (netif_running(netdev)) {
- /* FIXME: automatically restart */
- netdev_info(netdev, "Please re-open the interface\n");
- }
- } else {
- struct ucc_geth_info *ug_info = ugeth->ug_info;
-
- ret = init_flow_control_params(ug_info->aufc,
- ug_info->receiveFlowControl,
- ug_info->transmitFlowControl,
- ug_info->pausePeriod,
- ug_info->extensionField,
- &ugeth->uccf->uf_regs->upsmr,
- &ugeth->ug_regs->uempr,
- &ugeth->ug_regs->maccfg1);
- }
-
- return ret;
+ return phylink_ethtool_set_pauseparam(ugeth->phylink, pause);
}
static uint32_t
@@ -343,28 +309,42 @@ uec_get_drvinfo(struct net_device *netdev,
static void uec_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct ucc_geth_private *ugeth = netdev_priv(netdev);
- struct phy_device *phydev = ugeth->phydev;
- if (phydev && phydev->irq)
- wol->supported |= WAKE_PHY;
+ phylink_ethtool_get_wol(ugeth->phylink, wol);
+
if (qe_alive_during_sleep())
wol->supported |= WAKE_MAGIC;
- wol->wolopts = ugeth->wol_en;
+ wol->wolopts |= ugeth->wol_en;
}
static int uec_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct ucc_geth_private *ugeth = netdev_priv(netdev);
- struct phy_device *phydev = ugeth->phydev;
+ int ret = 0;
- if (wol->wolopts & ~(WAKE_PHY | WAKE_MAGIC))
- return -EINVAL;
- else if (wol->wolopts & WAKE_PHY && (!phydev || !phydev->irq))
+ ret = phylink_ethtool_set_wol(ugeth->phylink, wol);
+ if (ret == -EOPNOTSUPP) {
+ ugeth->phy_wol_en = 0;
+ } else if (ret) {
+ return ret;
+ } else {
+ ugeth->phy_wol_en = wol->wolopts;
+ goto out;
+ }
+
+ /* If the PHY isn't handling the WoL and the MAC is asked to more than
+ * WAKE_MAGIC, error-out
+ */
+ if (!ugeth->phy_wol_en &&
+ wol->wolopts & ~WAKE_MAGIC)
return -EINVAL;
- else if (wol->wolopts & WAKE_MAGIC && !qe_alive_during_sleep())
+
+ if (wol->wolopts & WAKE_MAGIC &&
+ !qe_alive_during_sleep())
return -EINVAL;
+out:
ugeth->wol_en = wol->wolopts;
device_set_wakeup_enable(&netdev->dev, ugeth->wol_en);
diff --git a/drivers/net/ethernet/google/gve/gve.h b/drivers/net/ethernet/google/gve/gve.h
index dd92949bb214..8167cc5fb0df 100644
--- a/drivers/net/ethernet/google/gve/gve.h
+++ b/drivers/net/ethernet/google/gve/gve.h
@@ -1140,6 +1140,7 @@ int gve_xdp_xmit_one(struct gve_priv *priv, struct gve_tx_ring *tx,
void gve_xdp_tx_flush(struct gve_priv *priv, u32 xdp_qid);
bool gve_tx_poll(struct gve_notify_block *block, int budget);
bool gve_xdp_poll(struct gve_notify_block *block, int budget);
+int gve_xsk_tx_poll(struct gve_notify_block *block, int budget);
int gve_tx_alloc_rings_gqi(struct gve_priv *priv,
struct gve_tx_alloc_rings_cfg *cfg);
void gve_tx_free_rings_gqi(struct gve_priv *priv,
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.c b/drivers/net/ethernet/google/gve/gve_adminq.c
index 060e0e674938..aa7d723011d0 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.c
+++ b/drivers/net/ethernet/google/gve/gve_adminq.c
@@ -1128,20 +1128,6 @@ int gve_adminq_unregister_page_list(struct gve_priv *priv, u32 page_list_id)
return gve_adminq_execute_cmd(priv, &cmd);
}
-int gve_adminq_set_mtu(struct gve_priv *priv, u64 mtu)
-{
- union gve_adminq_command cmd;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.opcode = cpu_to_be32(GVE_ADMINQ_SET_DRIVER_PARAMETER);
- cmd.set_driver_param = (struct gve_adminq_set_driver_parameter) {
- .parameter_type = cpu_to_be32(GVE_SET_PARAM_MTU),
- .parameter_value = cpu_to_be64(mtu),
- };
-
- return gve_adminq_execute_cmd(priv, &cmd);
-}
-
int gve_adminq_report_stats(struct gve_priv *priv, u64 stats_report_len,
dma_addr_t stats_report_addr, u64 interval)
{
diff --git a/drivers/net/ethernet/google/gve/gve_adminq.h b/drivers/net/ethernet/google/gve/gve_adminq.h
index 863683de9694..228217458275 100644
--- a/drivers/net/ethernet/google/gve/gve_adminq.h
+++ b/drivers/net/ethernet/google/gve/gve_adminq.h
@@ -612,7 +612,6 @@ int gve_adminq_destroy_rx_queues(struct gve_priv *priv, u32 queue_id);
int gve_adminq_register_page_list(struct gve_priv *priv,
struct gve_queue_page_list *qpl);
int gve_adminq_unregister_page_list(struct gve_priv *priv, u32 page_list_id);
-int gve_adminq_set_mtu(struct gve_priv *priv, u64 mtu);
int gve_adminq_report_stats(struct gve_priv *priv, u64 stats_report_len,
dma_addr_t stats_report_addr, u64 interval);
int gve_adminq_verify_driver_compatibility(struct gve_priv *priv,
diff --git a/drivers/net/ethernet/google/gve/gve_main.c b/drivers/net/ethernet/google/gve/gve_main.c
index e171ca248f9a..533e659b15b3 100644
--- a/drivers/net/ethernet/google/gve/gve_main.c
+++ b/drivers/net/ethernet/google/gve/gve_main.c
@@ -333,6 +333,14 @@ int gve_napi_poll(struct napi_struct *napi, int budget)
if (block->rx) {
work_done = gve_rx_poll(block, budget);
+
+ /* Poll XSK TX as part of RX NAPI. Setup re-poll based on max of
+ * TX and RX work done.
+ */
+ if (priv->xdp_prog)
+ work_done = max_t(int, work_done,
+ gve_xsk_tx_poll(block, budget));
+
reschedule |= work_done == budget;
}
@@ -922,11 +930,13 @@ static void gve_init_sync_stats(struct gve_priv *priv)
static void gve_tx_get_curr_alloc_cfg(struct gve_priv *priv,
struct gve_tx_alloc_rings_cfg *cfg)
{
+ int num_xdp_queues = priv->xdp_prog ? priv->rx_cfg.num_queues : 0;
+
cfg->qcfg = &priv->tx_cfg;
cfg->raw_addressing = !gve_is_qpl(priv);
cfg->ring_size = priv->tx_desc_cnt;
cfg->start_idx = 0;
- cfg->num_rings = gve_num_tx_queues(priv);
+ cfg->num_rings = priv->tx_cfg.num_queues + num_xdp_queues;
cfg->tx = priv->tx;
}
@@ -1623,8 +1633,8 @@ static int gve_xsk_pool_enable(struct net_device *dev,
if (err)
return err;
- /* If XDP prog is not installed, return */
- if (!priv->xdp_prog)
+ /* If XDP prog is not installed or interface is down, return. */
+ if (!priv->xdp_prog || !netif_running(dev))
return 0;
rx = &priv->rx[qid];
@@ -1669,21 +1679,16 @@ static int gve_xsk_pool_disable(struct net_device *dev,
if (qid >= priv->rx_cfg.num_queues)
return -EINVAL;
- /* If XDP prog is not installed, unmap DMA and return */
- if (!priv->xdp_prog)
- goto done;
-
- tx_qid = gve_xdp_tx_queue_id(priv, qid);
- if (!netif_running(dev)) {
- priv->rx[qid].xsk_pool = NULL;
- xdp_rxq_info_unreg(&priv->rx[qid].xsk_rxq);
- priv->tx[tx_qid].xsk_pool = NULL;
+ /* If XDP prog is not installed or interface is down, unmap DMA and
+ * return.
+ */
+ if (!priv->xdp_prog || !netif_running(dev))
goto done;
- }
napi_rx = &priv->ntfy_blocks[priv->rx[qid].ntfy_id].napi;
napi_disable(napi_rx); /* make sure current rx poll is done */
+ tx_qid = gve_xdp_tx_queue_id(priv, qid);
napi_tx = &priv->ntfy_blocks[priv->tx[tx_qid].ntfy_id].napi;
napi_disable(napi_tx); /* make sure current tx poll is done */
@@ -1709,24 +1714,20 @@ done:
static int gve_xsk_wakeup(struct net_device *dev, u32 queue_id, u32 flags)
{
struct gve_priv *priv = netdev_priv(dev);
- int tx_queue_id = gve_xdp_tx_queue_id(priv, queue_id);
+ struct napi_struct *napi;
+
+ if (!gve_get_napi_enabled(priv))
+ return -ENETDOWN;
if (queue_id >= priv->rx_cfg.num_queues || !priv->xdp_prog)
return -EINVAL;
- if (flags & XDP_WAKEUP_TX) {
- struct gve_tx_ring *tx = &priv->tx[tx_queue_id];
- struct napi_struct *napi =
- &priv->ntfy_blocks[tx->ntfy_id].napi;
-
- if (!napi_if_scheduled_mark_missed(napi)) {
- /* Call local_bh_enable to trigger SoftIRQ processing */
- local_bh_disable();
- napi_schedule(napi);
- local_bh_enable();
- }
-
- tx->xdp_xsk_wakeup++;
+ napi = &priv->ntfy_blocks[gve_rx_idx_to_ntfy(priv, queue_id)].napi;
+ if (!napi_if_scheduled_mark_missed(napi)) {
+ /* Call local_bh_enable to trigger SoftIRQ processing */
+ local_bh_disable();
+ napi_schedule(napi);
+ local_bh_enable();
}
return 0;
@@ -1837,6 +1838,7 @@ int gve_adjust_queues(struct gve_priv *priv,
{
struct gve_tx_alloc_rings_cfg tx_alloc_cfg = {0};
struct gve_rx_alloc_rings_cfg rx_alloc_cfg = {0};
+ int num_xdp_queues;
int err;
gve_get_curr_alloc_cfgs(priv, &tx_alloc_cfg, &rx_alloc_cfg);
@@ -1847,6 +1849,10 @@ int gve_adjust_queues(struct gve_priv *priv,
rx_alloc_cfg.qcfg = &new_rx_config;
tx_alloc_cfg.num_rings = new_tx_config.num_queues;
+ /* Add dedicated XDP TX queues if enabled. */
+ num_xdp_queues = priv->xdp_prog ? new_rx_config.num_queues : 0;
+ tx_alloc_cfg.num_rings += num_xdp_queues;
+
if (netif_running(priv->dev)) {
err = gve_adjust_config(priv, &tx_alloc_cfg, &rx_alloc_cfg);
return err;
@@ -1899,6 +1905,9 @@ static void gve_turndown(struct gve_priv *priv)
gve_clear_napi_enabled(priv);
gve_clear_report_stats(priv);
+
+ /* Make sure that all traffic is finished processing. */
+ synchronize_net();
}
static void gve_turnup(struct gve_priv *priv)
@@ -2232,14 +2241,18 @@ static void gve_service_task(struct work_struct *work)
static void gve_set_netdev_xdp_features(struct gve_priv *priv)
{
+ xdp_features_t xdp_features;
+
if (priv->queue_format == GVE_GQI_QPL_FORMAT) {
- priv->dev->xdp_features = NETDEV_XDP_ACT_BASIC;
- priv->dev->xdp_features |= NETDEV_XDP_ACT_REDIRECT;
- priv->dev->xdp_features |= NETDEV_XDP_ACT_NDO_XMIT;
- priv->dev->xdp_features |= NETDEV_XDP_ACT_XSK_ZEROCOPY;
+ xdp_features = NETDEV_XDP_ACT_BASIC;
+ xdp_features |= NETDEV_XDP_ACT_REDIRECT;
+ xdp_features |= NETDEV_XDP_ACT_NDO_XMIT;
+ xdp_features |= NETDEV_XDP_ACT_XSK_ZEROCOPY;
} else {
- priv->dev->xdp_features = 0;
+ xdp_features = 0;
}
+
+ xdp_set_features_flag(priv->dev, xdp_features);
}
static int gve_init_priv(struct gve_priv *priv, bool skip_describe_device)
diff --git a/drivers/net/ethernet/google/gve/gve_tx.c b/drivers/net/ethernet/google/gve/gve_tx.c
index e7fb7d6d283d..4350ebd9c2bd 100644
--- a/drivers/net/ethernet/google/gve/gve_tx.c
+++ b/drivers/net/ethernet/google/gve/gve_tx.c
@@ -206,7 +206,10 @@ void gve_tx_stop_ring_gqi(struct gve_priv *priv, int idx)
return;
gve_remove_napi(priv, ntfy_idx);
- gve_clean_tx_done(priv, tx, priv->tx_desc_cnt, false);
+ if (tx->q_num < priv->tx_cfg.num_queues)
+ gve_clean_tx_done(priv, tx, priv->tx_desc_cnt, false);
+ else
+ gve_clean_xdp_done(priv, tx, priv->tx_desc_cnt);
netdev_tx_reset_queue(tx->netdev_txq);
gve_tx_remove_from_block(priv, idx);
}
@@ -834,9 +837,12 @@ int gve_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
struct gve_tx_ring *tx;
int i, err = 0, qid;
- if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
+ if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK) || !priv->xdp_prog)
return -EINVAL;
+ if (!gve_get_napi_enabled(priv))
+ return -ENETDOWN;
+
qid = gve_xdp_tx_queue_id(priv,
smp_processor_id() % priv->num_xdp_queues);
@@ -975,33 +981,41 @@ out:
return sent;
}
+int gve_xsk_tx_poll(struct gve_notify_block *rx_block, int budget)
+{
+ struct gve_rx_ring *rx = rx_block->rx;
+ struct gve_priv *priv = rx->gve;
+ struct gve_tx_ring *tx;
+ int sent = 0;
+
+ tx = &priv->tx[gve_xdp_tx_queue_id(priv, rx->q_num)];
+ if (tx->xsk_pool) {
+ sent = gve_xsk_tx(priv, tx, budget);
+
+ u64_stats_update_begin(&tx->statss);
+ tx->xdp_xsk_sent += sent;
+ u64_stats_update_end(&tx->statss);
+ if (xsk_uses_need_wakeup(tx->xsk_pool))
+ xsk_set_tx_need_wakeup(tx->xsk_pool);
+ }
+
+ return sent;
+}
+
bool gve_xdp_poll(struct gve_notify_block *block, int budget)
{
struct gve_priv *priv = block->priv;
struct gve_tx_ring *tx = block->tx;
u32 nic_done;
- bool repoll;
u32 to_do;
/* Find out how much work there is to be done */
nic_done = gve_tx_load_event_counter(priv, tx);
to_do = min_t(u32, (nic_done - tx->done), budget);
gve_clean_xdp_done(priv, tx, to_do);
- repoll = nic_done != tx->done;
-
- if (tx->xsk_pool) {
- int sent = gve_xsk_tx(priv, tx, budget);
-
- u64_stats_update_begin(&tx->statss);
- tx->xdp_xsk_sent += sent;
- u64_stats_update_end(&tx->statss);
- repoll |= (sent == budget);
- if (xsk_uses_need_wakeup(tx->xsk_pool))
- xsk_set_tx_need_wakeup(tx->xsk_pool);
- }
/* If we still have work we want to repoll */
- return repoll;
+ return nic_done != tx->done;
}
bool gve_tx_poll(struct gve_notify_block *block, int budget)
diff --git a/drivers/net/ethernet/google/gve/gve_tx_dqo.c b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
index f879426cb552..394debc62268 100644
--- a/drivers/net/ethernet/google/gve/gve_tx_dqo.c
+++ b/drivers/net/ethernet/google/gve/gve_tx_dqo.c
@@ -1146,8 +1146,7 @@ static void gve_handle_miss_completion(struct gve_priv *priv,
/* jiffies can wraparound but time comparisons can handle overflows. */
pending_packet->timeout_jiffies =
jiffies +
- msecs_to_jiffies(GVE_REINJECT_COMPL_TIMEOUT *
- MSEC_PER_SEC);
+ secs_to_jiffies(GVE_REINJECT_COMPL_TIMEOUT);
add_to_list(tx, &tx->dqo_compl.miss_completions, pending_packet);
*bytes += pending_packet->skb->len;
@@ -1191,8 +1190,7 @@ static void remove_miss_completions(struct gve_priv *priv,
pending_packet->state = GVE_PACKET_STATE_TIMED_OUT_COMPL;
pending_packet->timeout_jiffies =
jiffies +
- msecs_to_jiffies(GVE_DEALLOCATE_COMPL_TIMEOUT *
- MSEC_PER_SEC);
+ secs_to_jiffies(GVE_DEALLOCATE_COMPL_TIMEOUT);
/* Maintain pending packet in another list so the packet can be
* unallocated at a later time.
*/
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/Makefile b/drivers/net/ethernet/hisilicon/hibmcge/Makefile
index ae58ac38c206..7ea15f9ef849 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/Makefile
+++ b/drivers/net/ethernet/hisilicon/hibmcge/Makefile
@@ -5,4 +5,5 @@
obj-$(CONFIG_HIBMCGE) += hibmcge.o
-hibmcge-objs = hbg_main.o hbg_hw.o hbg_mdio.o hbg_irq.o hbg_txrx.o hbg_ethtool.o
+hibmcge-objs = hbg_main.o hbg_hw.o hbg_mdio.o hbg_irq.o hbg_txrx.o hbg_ethtool.o \
+ hbg_debugfs.o hbg_err.o
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
index 96daf058d387..b4300d8ea4ad 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_common.h
@@ -4,6 +4,7 @@
#ifndef __HBG_COMMON_H
#define __HBG_COMMON_H
+#include <linux/ethtool.h>
#include <linux/netdevice.h>
#include <linux/pci.h>
#include "hbg_reg.h"
@@ -33,6 +34,14 @@ enum hbg_tx_state {
enum hbg_nic_state {
HBG_NIC_STATE_EVENT_HANDLING = 0,
+ HBG_NIC_STATE_RESETTING,
+ HBG_NIC_STATE_RESET_FAIL,
+};
+
+enum hbg_reset_type {
+ HBG_RESET_TYPE_NONE = 0,
+ HBG_RESET_TYPE_FLR,
+ HBG_RESET_TYPE_FUNCTION,
};
struct hbg_buffer {
@@ -84,6 +93,7 @@ struct hbg_dev_specs {
u32 vlan_layers;
u32 max_mtu;
u32 min_mtu;
+ u32 uc_mac_num;
u32 max_frame_len;
u32 rx_buf_size;
@@ -114,6 +124,22 @@ struct hbg_mac {
u32 duplex;
u32 autoneg;
u32 link_status;
+ u32 pause_autoneg;
+};
+
+struct hbg_mac_table_entry {
+ u8 addr[ETH_ALEN];
+};
+
+struct hbg_mac_filter {
+ struct hbg_mac_table_entry *mac_table;
+ u32 table_max_len;
+ bool enabled;
+};
+
+/* saved for restore after rest */
+struct hbg_user_def {
+ struct ethtool_pauseparam pause_param;
};
struct hbg_priv {
@@ -126,6 +152,9 @@ struct hbg_priv {
struct hbg_vector vectors;
struct hbg_ring tx_ring;
struct hbg_ring rx_ring;
+ struct hbg_mac_filter filter;
+ enum hbg_reset_type reset_type;
+ struct hbg_user_def user_def;
};
#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c
new file mode 100644
index 000000000000..8473c43d171a
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.c
@@ -0,0 +1,160 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2024 Hisilicon Limited.
+
+#include <linux/debugfs.h>
+#include <linux/device.h>
+#include <linux/etherdevice.h>
+#include <linux/seq_file.h>
+#include <linux/string_choices.h>
+#include "hbg_common.h"
+#include "hbg_debugfs.h"
+#include "hbg_hw.h"
+#include "hbg_irq.h"
+#include "hbg_txrx.h"
+
+static struct dentry *hbg_dbgfs_root;
+
+struct hbg_dbg_info {
+ const char *name;
+ int (*read)(struct seq_file *seq, void *data);
+};
+
+#define state_str_true_false(p, s) str_true_false(test_bit(s, &(p)->state))
+
+static void hbg_dbg_ring(struct hbg_priv *priv, struct hbg_ring *ring,
+ struct seq_file *s)
+{
+ u32 irq_mask = ring->dir == HBG_DIR_TX ? HBG_INT_MSK_TX_B :
+ HBG_INT_MSK_RX_B;
+
+ seq_printf(s, "ring used num: %u\n",
+ hbg_get_queue_used_num(ring));
+ seq_printf(s, "ring max num: %u\n", ring->len);
+ seq_printf(s, "ring head: %u, tail: %u\n", ring->head, ring->tail);
+ seq_printf(s, "fifo used num: %u\n",
+ hbg_hw_get_fifo_used_num(priv, ring->dir));
+ seq_printf(s, "fifo max num: %u\n",
+ hbg_get_spec_fifo_max_num(priv, ring->dir));
+ seq_printf(s, "irq enabled: %s\n",
+ str_true_false(hbg_hw_irq_is_enabled(priv, irq_mask)));
+}
+
+static int hbg_dbg_tx_ring(struct seq_file *s, void *unused)
+{
+ struct net_device *netdev = dev_get_drvdata(s->private);
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ hbg_dbg_ring(priv, &priv->tx_ring, s);
+ return 0;
+}
+
+static int hbg_dbg_rx_ring(struct seq_file *s, void *unused)
+{
+ struct net_device *netdev = dev_get_drvdata(s->private);
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ hbg_dbg_ring(priv, &priv->rx_ring, s);
+ return 0;
+}
+
+static int hbg_dbg_irq_info(struct seq_file *s, void *unused)
+{
+ struct net_device *netdev = dev_get_drvdata(s->private);
+ struct hbg_priv *priv = netdev_priv(netdev);
+ struct hbg_irq_info *info;
+ u32 i;
+
+ for (i = 0; i < priv->vectors.info_array_len; i++) {
+ info = &priv->vectors.info_array[i];
+ seq_printf(s,
+ "%-20s: enabled: %-5s, logged: %-5s, count: %llu\n",
+ info->name,
+ str_true_false(hbg_hw_irq_is_enabled(priv,
+ info->mask)),
+ str_true_false(info->need_print),
+ info->count);
+ }
+
+ return 0;
+}
+
+static int hbg_dbg_mac_table(struct seq_file *s, void *unused)
+{
+ struct net_device *netdev = dev_get_drvdata(s->private);
+ struct hbg_priv *priv = netdev_priv(netdev);
+ struct hbg_mac_filter *filter;
+ u32 i;
+
+ filter = &priv->filter;
+ seq_printf(s, "mac addr max count: %u\n", filter->table_max_len);
+ seq_printf(s, "filter enabled: %s\n", str_true_false(filter->enabled));
+
+ for (i = 0; i < filter->table_max_len; i++) {
+ if (is_zero_ether_addr(filter->mac_table[i].addr))
+ continue;
+
+ seq_printf(s, "[%u] %pM\n", i, filter->mac_table[i].addr);
+ }
+
+ return 0;
+}
+
+static const char * const reset_type_str[] = {"None", "FLR", "Function"};
+
+static int hbg_dbg_nic_state(struct seq_file *s, void *unused)
+{
+ struct net_device *netdev = dev_get_drvdata(s->private);
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ seq_printf(s, "event handling state: %s\n",
+ state_str_true_false(priv, HBG_NIC_STATE_EVENT_HANDLING));
+ seq_printf(s, "resetting state: %s\n",
+ state_str_true_false(priv, HBG_NIC_STATE_RESETTING));
+ seq_printf(s, "reset fail state: %s\n",
+ state_str_true_false(priv, HBG_NIC_STATE_RESET_FAIL));
+ seq_printf(s, "last reset type: %s\n",
+ reset_type_str[priv->reset_type]);
+
+ return 0;
+}
+
+static const struct hbg_dbg_info hbg_dbg_infos[] = {
+ { "tx_ring", hbg_dbg_tx_ring },
+ { "rx_ring", hbg_dbg_rx_ring },
+ { "irq_info", hbg_dbg_irq_info },
+ { "mac_table", hbg_dbg_mac_table },
+ { "nic_state", hbg_dbg_nic_state },
+};
+
+static void hbg_debugfs_uninit(void *data)
+{
+ debugfs_remove_recursive((struct dentry *)data);
+}
+
+void hbg_debugfs_init(struct hbg_priv *priv)
+{
+ const char *name = pci_name(priv->pdev);
+ struct device *dev = &priv->pdev->dev;
+ struct dentry *root;
+ u32 i;
+
+ root = debugfs_create_dir(name, hbg_dbgfs_root);
+
+ for (i = 0; i < ARRAY_SIZE(hbg_dbg_infos); i++)
+ debugfs_create_devm_seqfile(dev, hbg_dbg_infos[i].name,
+ root, hbg_dbg_infos[i].read);
+
+ /* Ignore the failure because debugfs is not a key feature. */
+ devm_add_action_or_reset(dev, hbg_debugfs_uninit, root);
+}
+
+void hbg_debugfs_register(void)
+{
+ hbg_dbgfs_root = debugfs_create_dir("hibmcge", NULL);
+}
+
+void hbg_debugfs_unregister(void)
+{
+ debugfs_remove_recursive(hbg_dbgfs_root);
+ hbg_dbgfs_root = NULL;
+}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.h
new file mode 100644
index 000000000000..80670d66bbeb
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_debugfs.h
@@ -0,0 +1,12 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_DEBUGFS_H
+#define __HBG_DEBUGFS_H
+
+void hbg_debugfs_register(void);
+void hbg_debugfs_unregister(void);
+
+void hbg_debugfs_init(struct hbg_priv *priv);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c
new file mode 100644
index 000000000000..4d1f4a33391a
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.c
@@ -0,0 +1,134 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright (c) 2024 Hisilicon Limited.
+
+#include <linux/etherdevice.h>
+#include <linux/netdevice.h>
+#include <linux/phy.h>
+#include <linux/rtnetlink.h>
+#include "hbg_common.h"
+#include "hbg_err.h"
+#include "hbg_hw.h"
+
+static void hbg_restore_mac_table(struct hbg_priv *priv)
+{
+ struct hbg_mac_filter *filter = &priv->filter;
+ u64 addr;
+ u32 i;
+
+ for (i = 0; i < filter->table_max_len; i++)
+ if (!is_zero_ether_addr(filter->mac_table[i].addr)) {
+ addr = ether_addr_to_u64(filter->mac_table[i].addr);
+ hbg_hw_set_uc_addr(priv, addr, i);
+ }
+
+ hbg_hw_set_mac_filter_enable(priv, priv->filter.enabled);
+}
+
+static void hbg_restore_user_def_settings(struct hbg_priv *priv)
+{
+ struct ethtool_pauseparam *pause_param = &priv->user_def.pause_param;
+
+ hbg_restore_mac_table(priv);
+ hbg_hw_set_mtu(priv, priv->netdev->mtu);
+ hbg_hw_set_pause_enable(priv, pause_param->tx_pause,
+ pause_param->rx_pause);
+}
+
+int hbg_rebuild(struct hbg_priv *priv)
+{
+ int ret;
+
+ ret = hbg_hw_init(priv);
+ if (ret)
+ return ret;
+
+ hbg_restore_user_def_settings(priv);
+ return 0;
+}
+
+static int hbg_reset_prepare(struct hbg_priv *priv, enum hbg_reset_type type)
+{
+ int ret;
+
+ ASSERT_RTNL();
+
+ if (netif_running(priv->netdev)) {
+ dev_warn(&priv->pdev->dev,
+ "failed to reset because port is up\n");
+ return -EBUSY;
+ }
+
+ priv->reset_type = type;
+ set_bit(HBG_NIC_STATE_RESETTING, &priv->state);
+ clear_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state);
+ ret = hbg_hw_event_notify(priv, HBG_HW_EVENT_RESET);
+ if (ret) {
+ set_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state);
+ clear_bit(HBG_NIC_STATE_RESETTING, &priv->state);
+ }
+
+ return ret;
+}
+
+static int hbg_reset_done(struct hbg_priv *priv, enum hbg_reset_type type)
+{
+ int ret;
+
+ if (!test_bit(HBG_NIC_STATE_RESETTING, &priv->state) ||
+ type != priv->reset_type)
+ return 0;
+
+ ASSERT_RTNL();
+
+ clear_bit(HBG_NIC_STATE_RESETTING, &priv->state);
+ ret = hbg_rebuild(priv);
+ if (ret) {
+ set_bit(HBG_NIC_STATE_RESET_FAIL, &priv->state);
+ dev_err(&priv->pdev->dev, "failed to rebuild after reset\n");
+ return ret;
+ }
+
+ dev_info(&priv->pdev->dev, "reset done\n");
+ return ret;
+}
+
+/* must be protected by rtnl lock */
+int hbg_reset(struct hbg_priv *priv)
+{
+ int ret;
+
+ ASSERT_RTNL();
+ ret = hbg_reset_prepare(priv, HBG_RESET_TYPE_FUNCTION);
+ if (ret)
+ return ret;
+
+ return hbg_reset_done(priv, HBG_RESET_TYPE_FUNCTION);
+}
+
+static void hbg_pci_err_reset_prepare(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ rtnl_lock();
+ hbg_reset_prepare(priv, HBG_RESET_TYPE_FLR);
+}
+
+static void hbg_pci_err_reset_done(struct pci_dev *pdev)
+{
+ struct net_device *netdev = pci_get_drvdata(pdev);
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ hbg_reset_done(priv, HBG_RESET_TYPE_FLR);
+ rtnl_unlock();
+}
+
+static const struct pci_error_handlers hbg_pci_err_handler = {
+ .reset_prepare = hbg_pci_err_reset_prepare,
+ .reset_done = hbg_pci_err_reset_done,
+};
+
+void hbg_set_pci_err_handler(struct pci_driver *pdrv)
+{
+ pdrv->err_handler = &hbg_pci_err_handler;
+}
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.h
new file mode 100644
index 000000000000..d7828e446308
--- /dev/null
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_err.h
@@ -0,0 +1,13 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/* Copyright (c) 2024 Hisilicon Limited. */
+
+#ifndef __HBG_ERR_H
+#define __HBG_ERR_H
+
+#include <linux/pci.h>
+
+void hbg_set_pci_err_handler(struct pci_driver *pdrv);
+int hbg_reset(struct hbg_priv *priv);
+int hbg_rebuild(struct hbg_priv *priv);
+
+#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
index c3370114aef3..00364a438ec2 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_ethtool.c
@@ -3,12 +3,193 @@
#include <linux/ethtool.h>
#include <linux/phy.h>
+#include <linux/rtnetlink.h>
+#include "hbg_common.h"
+#include "hbg_err.h"
#include "hbg_ethtool.h"
+#include "hbg_hw.h"
+
+enum hbg_reg_dump_type {
+ HBG_DUMP_REG_TYPE_SPEC = 0,
+ HBG_DUMP_REG_TYPE_MDIO,
+ HBG_DUMP_REG_TYPE_GMAC,
+ HBG_DUMP_REG_TYPE_PCU,
+};
+
+struct hbg_reg_info {
+ u32 type;
+ u32 offset;
+ u32 val;
+};
+
+#define HBG_DUMP_SPEC_I(offset) {HBG_DUMP_REG_TYPE_SPEC, offset, 0}
+#define HBG_DUMP_MDIO_I(offset) {HBG_DUMP_REG_TYPE_MDIO, offset, 0}
+#define HBG_DUMP_GMAC_I(offset) {HBG_DUMP_REG_TYPE_GMAC, offset, 0}
+#define HBG_DUMP_PCU_I(offset) {HBG_DUMP_REG_TYPE_PCU, offset, 0}
+
+static const struct hbg_reg_info hbg_dump_reg_infos[] = {
+ /* dev specs */
+ HBG_DUMP_SPEC_I(HBG_REG_SPEC_VALID_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_EVENT_REQ_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_MAC_ID_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_PHY_ID_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_MAC_ADDR_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_MAC_ADDR_HIGH_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_UC_MAC_NUM_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_MDIO_FREQ_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_MAX_MTU_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_MIN_MTU_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_TX_FIFO_NUM_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_RX_FIFO_NUM_ADDR),
+ HBG_DUMP_SPEC_I(HBG_REG_VLAN_LAYERS_ADDR),
+
+ /* mdio */
+ HBG_DUMP_MDIO_I(HBG_REG_MDIO_COMMAND_ADDR),
+ HBG_DUMP_MDIO_I(HBG_REG_MDIO_ADDR_ADDR),
+ HBG_DUMP_MDIO_I(HBG_REG_MDIO_WDATA_ADDR),
+ HBG_DUMP_MDIO_I(HBG_REG_MDIO_RDATA_ADDR),
+ HBG_DUMP_MDIO_I(HBG_REG_MDIO_STA_ADDR),
+
+ /* gmac */
+ HBG_DUMP_GMAC_I(HBG_REG_DUPLEX_TYPE_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_FD_FC_TYPE_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_FC_TX_TIMER_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_FD_FC_ADDR_LOW_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_FD_FC_ADDR_HIGH_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_MAX_FRAME_SIZE_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_PORT_MODE_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_PORT_ENABLE_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_PAUSE_ENABLE_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_AN_NEG_STATE_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_TRANSMIT_CTRL_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_REC_FILT_CTRL_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_LINE_LOOP_BACK_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_CF_CRC_STRIP_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_MODE_CHANGE_EN_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_LOOP_REG_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_RECV_CTRL_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_VLAN_CODE_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_0_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_0_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_1_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_1_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_2_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_2_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_3_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_3_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_4_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_4_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_LOW_5_ADDR),
+ HBG_DUMP_GMAC_I(HBG_REG_STATION_ADDR_HIGH_5_ADDR),
+
+ /* pcu */
+ HBG_DUMP_PCU_I(HBG_REG_TX_FIFO_THRSLD_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_RX_FIFO_THRSLD_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CFG_FIFO_THRSLD_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_MSK_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_STAT_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_INTRPT_CLR_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_TX_BUS_ERR_ADDR_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_RX_BUS_ERR_ADDR_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_MAX_FRAME_LEN_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_DEBUG_ST_MCH_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_FIFO_CURR_STATUS_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_FIFO_HIST_STATUS_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_CFF_DATA_NUM_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_TX_PAUSE_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_RX_CFF_ADDR_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_RX_BUF_SIZE_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_BUS_CTRL_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_RX_CTRL_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_RX_PKT_MODE_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_DBG_ST0_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_DBG_ST1_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_DBG_ST2_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_BUS_RST_EN_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_MSK_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_STAT_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_IND_TXINT_CLR_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_MSK_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_STAT_ADDR),
+ HBG_DUMP_PCU_I(HBG_REG_CF_IND_RXINT_CLR_ADDR),
+};
+
+static const u32 hbg_dump_type_base_array[] = {
+ [HBG_DUMP_REG_TYPE_SPEC] = 0,
+ [HBG_DUMP_REG_TYPE_MDIO] = HBG_REG_MDIO_BASE,
+ [HBG_DUMP_REG_TYPE_GMAC] = HBG_REG_SGMII_BASE,
+ [HBG_DUMP_REG_TYPE_PCU] = HBG_REG_SGMII_BASE,
+};
+
+static int hbg_ethtool_get_regs_len(struct net_device *netdev)
+{
+ return ARRAY_SIZE(hbg_dump_reg_infos) * sizeof(struct hbg_reg_info);
+}
+
+static void hbg_ethtool_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *data)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+ struct hbg_reg_info *info;
+ u32 i, offset = 0;
+
+ regs->version = 0;
+ for (i = 0; i < ARRAY_SIZE(hbg_dump_reg_infos); i++) {
+ info = data + offset;
+
+ *info = hbg_dump_reg_infos[i];
+ info->val = hbg_reg_read(priv, info->offset);
+ info->offset -= hbg_dump_type_base_array[info->type];
+
+ offset += sizeof(*info);
+ }
+}
+
+static void hbg_ethtool_get_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *param)
+{
+ struct hbg_priv *priv = netdev_priv(net_dev);
+
+ param->autoneg = priv->mac.pause_autoneg;
+ hbg_hw_get_pause_enable(priv, &param->tx_pause, &param->rx_pause);
+}
+
+static int hbg_ethtool_set_pauseparam(struct net_device *net_dev,
+ struct ethtool_pauseparam *param)
+{
+ struct hbg_priv *priv = netdev_priv(net_dev);
+
+ priv->mac.pause_autoneg = param->autoneg;
+ phy_set_asym_pause(priv->mac.phydev, param->rx_pause, param->tx_pause);
+
+ if (!param->autoneg)
+ hbg_hw_set_pause_enable(priv, param->tx_pause, param->rx_pause);
+
+ priv->user_def.pause_param = *param;
+ return 0;
+}
+
+static int hbg_ethtool_reset(struct net_device *netdev, u32 *flags)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ if (*flags != ETH_RESET_DEDICATED)
+ return -EOPNOTSUPP;
+
+ *flags = 0;
+ return hbg_reset(priv);
+}
static const struct ethtool_ops hbg_ethtool_ops = {
.get_link = ethtool_op_get_link,
.get_link_ksettings = phy_ethtool_get_link_ksettings,
.set_link_ksettings = phy_ethtool_set_link_ksettings,
+ .get_regs_len = hbg_ethtool_get_regs_len,
+ .get_regs = hbg_ethtool_get_regs,
+ .get_pauseparam = hbg_ethtool_get_pauseparam,
+ .set_pauseparam = hbg_ethtool_set_pauseparam,
+ .reset = hbg_ethtool_reset,
+ .nway_reset = phy_ethtool_nway_reset,
};
void hbg_ethtool_set_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
index 05295c2ad439..e7798f213645 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.c
@@ -3,6 +3,7 @@
#include <linux/etherdevice.h>
#include <linux/ethtool.h>
+#include <linux/if_vlan.h>
#include <linux/iopoll.h>
#include <linux/minmax.h>
#include "hbg_common.h"
@@ -67,6 +68,8 @@ static int hbg_hw_dev_specs_init(struct hbg_priv *priv)
specs->vlan_layers = hbg_reg_read(priv, HBG_REG_VLAN_LAYERS_ADDR);
specs->rx_fifo_num = hbg_reg_read(priv, HBG_REG_RX_FIFO_NUM_ADDR);
specs->tx_fifo_num = hbg_reg_read(priv, HBG_REG_TX_FIFO_NUM_ADDR);
+ specs->uc_mac_num = hbg_reg_read(priv, HBG_REG_UC_MAC_NUM_ADDR);
+
mac_addr = hbg_reg_read64(priv, HBG_REG_MAC_ADDR_ADDR);
u64_to_ether_addr(mac_addr, (u8 *)specs->mac_addr.sa_data);
@@ -135,9 +138,13 @@ void hbg_hw_irq_enable(struct hbg_priv *priv, u32 mask, bool enable)
hbg_reg_write(priv, HBG_REG_CF_INTRPT_MSK_ADDR, value);
}
-void hbg_hw_set_uc_addr(struct hbg_priv *priv, u64 mac_addr)
+void hbg_hw_set_uc_addr(struct hbg_priv *priv, u64 mac_addr, u32 index)
{
- hbg_reg_write64(priv, HBG_REG_STATION_ADDR_LOW_2_ADDR, mac_addr);
+ u32 addr;
+
+ /* mac addr is u64, so the addr offset is 0x8 */
+ addr = HBG_REG_STATION_ADDR_LOW_2_ADDR + (index * 0x8);
+ hbg_reg_write64(priv, addr, mac_addr);
}
static void hbg_hw_set_pcu_max_frame_len(struct hbg_priv *priv,
@@ -161,8 +168,13 @@ static void hbg_hw_set_mac_max_frame_len(struct hbg_priv *priv,
void hbg_hw_set_mtu(struct hbg_priv *priv, u16 mtu)
{
- hbg_hw_set_pcu_max_frame_len(priv, mtu);
- hbg_hw_set_mac_max_frame_len(priv, mtu);
+ u32 frame_len;
+
+ frame_len = mtu + VLAN_HLEN * priv->dev_specs.vlan_layers +
+ ETH_HLEN + ETH_FCS_LEN;
+
+ hbg_hw_set_pcu_max_frame_len(priv, frame_len);
+ hbg_hw_set_mac_max_frame_len(priv, frame_len);
}
void hbg_hw_mac_enable(struct hbg_priv *priv, u32 enable)
@@ -207,6 +219,34 @@ void hbg_hw_adjust_link(struct hbg_priv *priv, u32 speed, u32 duplex)
HBG_REG_DUPLEX_B, duplex);
}
+/* only support uc filter */
+void hbg_hw_set_mac_filter_enable(struct hbg_priv *priv, u32 enable)
+{
+ hbg_reg_write_field(priv, HBG_REG_REC_FILT_CTRL_ADDR,
+ HBG_REG_REC_FILT_CTRL_UC_MATCH_EN_B, enable);
+}
+
+void hbg_hw_set_pause_enable(struct hbg_priv *priv, u32 tx_en, u32 rx_en)
+{
+ hbg_reg_write_field(priv, HBG_REG_PAUSE_ENABLE_ADDR,
+ HBG_REG_PAUSE_ENABLE_TX_B, tx_en);
+ hbg_reg_write_field(priv, HBG_REG_PAUSE_ENABLE_ADDR,
+ HBG_REG_PAUSE_ENABLE_RX_B, rx_en);
+}
+
+void hbg_hw_get_pause_enable(struct hbg_priv *priv, u32 *tx_en, u32 *rx_en)
+{
+ *tx_en = hbg_reg_read_field(priv, HBG_REG_PAUSE_ENABLE_ADDR,
+ HBG_REG_PAUSE_ENABLE_TX_B);
+ *rx_en = hbg_reg_read_field(priv, HBG_REG_PAUSE_ENABLE_ADDR,
+ HBG_REG_PAUSE_ENABLE_RX_B);
+}
+
+void hbg_hw_set_rx_pause_mac_addr(struct hbg_priv *priv, u64 mac_addr)
+{
+ hbg_reg_write64(priv, HBG_REG_FD_FC_ADDR_LOW_ADDR, mac_addr);
+}
+
static void hbg_hw_init_transmit_ctrl(struct hbg_priv *priv)
{
u32 ctrl = 0;
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
index 14fb39241c93..a4a049b5121d 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_hw.h
@@ -51,9 +51,13 @@ bool hbg_hw_irq_is_enabled(struct hbg_priv *priv, u32 mask);
void hbg_hw_irq_enable(struct hbg_priv *priv, u32 mask, bool enable);
void hbg_hw_set_mtu(struct hbg_priv *priv, u16 mtu);
void hbg_hw_mac_enable(struct hbg_priv *priv, u32 enable);
-void hbg_hw_set_uc_addr(struct hbg_priv *priv, u64 mac_addr);
+void hbg_hw_set_uc_addr(struct hbg_priv *priv, u64 mac_addr, u32 index);
u32 hbg_hw_get_fifo_used_num(struct hbg_priv *priv, enum hbg_dir dir);
void hbg_hw_set_tx_desc(struct hbg_priv *priv, struct hbg_tx_desc *tx_desc);
void hbg_hw_fill_buffer(struct hbg_priv *priv, u32 buffer_dma_addr);
+void hbg_hw_set_mac_filter_enable(struct hbg_priv *priv, u32 enable);
+void hbg_hw_set_pause_enable(struct hbg_priv *priv, u32 tx_en, u32 rx_en);
+void hbg_hw_get_pause_enable(struct hbg_priv *priv, u32 *tx_en, u32 *rx_en);
+void hbg_hw_set_rx_pause_mac_addr(struct hbg_priv *priv, u64 mac_addr);
#endif
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
index 75505fb5cc4a..bb0f25ac9760 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_main.c
@@ -6,13 +6,13 @@
#include <linux/netdevice.h>
#include <linux/pci.h>
#include "hbg_common.h"
+#include "hbg_err.h"
#include "hbg_ethtool.h"
#include "hbg_hw.h"
#include "hbg_irq.h"
#include "hbg_mdio.h"
#include "hbg_txrx.h"
-
-static void hbg_change_mtu(struct hbg_priv *priv, int new_mtu);
+#include "hbg_debugfs.h"
static void hbg_all_irq_enable(struct hbg_priv *priv, bool enabled)
{
@@ -55,11 +55,7 @@ static int hbg_hw_txrx_clear(struct hbg_priv *priv)
return ret;
/* After reset, regs need to be reconfigured */
- hbg_hw_init(priv);
- hbg_hw_set_uc_addr(priv, ether_addr_to_u64(priv->netdev->dev_addr));
- hbg_change_mtu(priv, priv->netdev->mtu);
-
- return 0;
+ return hbg_rebuild(priv);
}
static int hbg_net_stop(struct net_device *netdev)
@@ -74,31 +70,127 @@ static int hbg_net_stop(struct net_device *netdev)
return hbg_hw_txrx_clear(priv);
}
+static void hbg_update_promisc_mode(struct net_device *netdev, bool overflow)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ /* Only when not table_overflow, and netdev->flags not set IFF_PROMISC,
+ * The MAC filter will be enabled.
+ * Otherwise the filter will be disabled.
+ */
+ priv->filter.enabled = !(overflow || (netdev->flags & IFF_PROMISC));
+ hbg_hw_set_mac_filter_enable(priv, priv->filter.enabled);
+}
+
+static void hbg_set_mac_to_mac_table(struct hbg_priv *priv,
+ u32 index, const u8 *addr)
+{
+ if (addr) {
+ ether_addr_copy(priv->filter.mac_table[index].addr, addr);
+ hbg_hw_set_uc_addr(priv, ether_addr_to_u64(addr), index);
+ } else {
+ eth_zero_addr(priv->filter.mac_table[index].addr);
+ hbg_hw_set_uc_addr(priv, 0, index);
+ }
+}
+
+static int hbg_get_index_from_mac_table(struct hbg_priv *priv,
+ const u8 *addr, u32 *index)
+{
+ u32 i;
+
+ for (i = 0; i < priv->filter.table_max_len; i++)
+ if (ether_addr_equal(priv->filter.mac_table[i].addr, addr)) {
+ *index = i;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int hbg_add_mac_to_filter(struct hbg_priv *priv, const u8 *addr)
+{
+ u32 index;
+
+ /* already exists */
+ if (!hbg_get_index_from_mac_table(priv, addr, &index))
+ return 0;
+
+ for (index = 0; index < priv->filter.table_max_len; index++)
+ if (is_zero_ether_addr(priv->filter.mac_table[index].addr)) {
+ hbg_set_mac_to_mac_table(priv, index, addr);
+ return 0;
+ }
+
+ return -ENOSPC;
+}
+
+static void hbg_del_mac_from_filter(struct hbg_priv *priv, const u8 *addr)
+{
+ u32 index;
+
+ /* not exists */
+ if (hbg_get_index_from_mac_table(priv, addr, &index))
+ return;
+
+ hbg_set_mac_to_mac_table(priv, index, NULL);
+}
+
+static int hbg_uc_sync(struct net_device *netdev, const unsigned char *addr)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ return hbg_add_mac_to_filter(priv, addr);
+}
+
+static int hbg_uc_unsync(struct net_device *netdev, const unsigned char *addr)
+{
+ struct hbg_priv *priv = netdev_priv(netdev);
+
+ if (ether_addr_equal(netdev->dev_addr, (u8 *)addr))
+ return 0;
+
+ hbg_del_mac_from_filter(priv, addr);
+ return 0;
+}
+
+static void hbg_net_set_rx_mode(struct net_device *netdev)
+{
+ int ret;
+
+ ret = __dev_uc_sync(netdev, hbg_uc_sync, hbg_uc_unsync);
+
+ /* If ret != 0, overflow has occurred */
+ hbg_update_promisc_mode(netdev, !!ret);
+}
+
static int hbg_net_set_mac_address(struct net_device *netdev, void *addr)
{
struct hbg_priv *priv = netdev_priv(netdev);
u8 *mac_addr;
+ bool exists;
+ u32 index;
mac_addr = ((struct sockaddr *)addr)->sa_data;
if (!is_valid_ether_addr(mac_addr))
return -EADDRNOTAVAIL;
- hbg_hw_set_uc_addr(priv, ether_addr_to_u64(mac_addr));
- dev_addr_set(netdev, mac_addr);
+ /* The index of host mac is always 0.
+ * If new mac address already exists,
+ * delete the existing mac address and
+ * add it to the position with index 0.
+ */
+ exists = !hbg_get_index_from_mac_table(priv, mac_addr, &index);
+ hbg_set_mac_to_mac_table(priv, 0, mac_addr);
+ if (exists)
+ hbg_set_mac_to_mac_table(priv, index, NULL);
+ hbg_hw_set_rx_pause_mac_addr(priv, ether_addr_to_u64(mac_addr));
+ dev_addr_set(netdev, mac_addr);
return 0;
}
-static void hbg_change_mtu(struct hbg_priv *priv, int new_mtu)
-{
- u32 frame_len;
-
- frame_len = new_mtu + VLAN_HLEN * priv->dev_specs.vlan_layers +
- ETH_HLEN + ETH_FCS_LEN;
- hbg_hw_set_mtu(priv, frame_len);
-}
-
static int hbg_net_change_mtu(struct net_device *netdev, int new_mtu)
{
struct hbg_priv *priv = netdev_priv(netdev);
@@ -106,7 +198,7 @@ static int hbg_net_change_mtu(struct net_device *netdev, int new_mtu)
if (netif_running(netdev))
return -EBUSY;
- hbg_change_mtu(priv, new_mtu);
+ hbg_hw_set_mtu(priv, new_mtu);
WRITE_ONCE(netdev->mtu, new_mtu);
dev_dbg(&priv->pdev->dev,
@@ -142,8 +234,39 @@ static const struct net_device_ops hbg_netdev_ops = {
.ndo_set_mac_address = hbg_net_set_mac_address,
.ndo_change_mtu = hbg_net_change_mtu,
.ndo_tx_timeout = hbg_net_tx_timeout,
+ .ndo_set_rx_mode = hbg_net_set_rx_mode,
};
+static int hbg_mac_filter_init(struct hbg_priv *priv)
+{
+ struct hbg_dev_specs *dev_specs = &priv->dev_specs;
+ struct hbg_mac_filter *filter = &priv->filter;
+ struct hbg_mac_table_entry *tmp_table;
+
+ tmp_table = devm_kcalloc(&priv->pdev->dev, dev_specs->uc_mac_num,
+ sizeof(*tmp_table), GFP_KERNEL);
+ if (!tmp_table)
+ return -ENOMEM;
+
+ filter->mac_table = tmp_table;
+ filter->table_max_len = dev_specs->uc_mac_num;
+ filter->enabled = true;
+
+ hbg_hw_set_mac_filter_enable(priv, filter->enabled);
+ return 0;
+}
+
+static void hbg_init_user_def(struct hbg_priv *priv)
+{
+ struct ethtool_pauseparam *pause_param = &priv->user_def.pause_param;
+
+ priv->mac.pause_autoneg = HBG_STATUS_ENABLE;
+
+ pause_param->autoneg = priv->mac.pause_autoneg;
+ hbg_hw_get_pause_enable(priv, &pause_param->tx_pause,
+ &pause_param->rx_pause);
+}
+
static int hbg_init(struct hbg_priv *priv)
{
int ret;
@@ -160,7 +283,17 @@ static int hbg_init(struct hbg_priv *priv)
if (ret)
return ret;
- return hbg_mdio_init(priv);
+ ret = hbg_mdio_init(priv);
+ if (ret)
+ return ret;
+
+ ret = hbg_mac_filter_init(priv);
+ if (ret)
+ return ret;
+
+ hbg_debugfs_init(priv);
+ hbg_init_user_def(priv);
+ return 0;
}
static int hbg_pci_init(struct pci_dev *pdev)
@@ -216,13 +349,15 @@ static int hbg_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (ret)
return ret;
+ netdev->priv_flags |= IFF_UNICAST_FLT;
+
netdev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
netdev->max_mtu = priv->dev_specs.max_mtu;
netdev->min_mtu = priv->dev_specs.min_mtu;
netdev->netdev_ops = &hbg_netdev_ops;
netdev->watchdog_timeo = 5 * HZ;
- hbg_change_mtu(priv, ETH_DATA_LEN);
+ hbg_hw_set_mtu(priv, ETH_DATA_LEN);
hbg_net_set_mac_address(priv->netdev, &priv->dev_specs.mac_addr);
hbg_ethtool_set_ops(netdev);
@@ -245,7 +380,27 @@ static struct pci_driver hbg_driver = {
.id_table = hbg_pci_tbl,
.probe = hbg_probe,
};
-module_pci_driver(hbg_driver);
+
+static int __init hbg_module_init(void)
+{
+ int ret;
+
+ hbg_debugfs_register();
+ hbg_set_pci_err_handler(&hbg_driver);
+ ret = pci_register_driver(&hbg_driver);
+ if (ret)
+ hbg_debugfs_unregister();
+
+ return ret;
+}
+module_init(hbg_module_init);
+
+static void __exit hbg_module_exit(void)
+{
+ pci_unregister_driver(&hbg_driver);
+ hbg_debugfs_unregister();
+}
+module_exit(hbg_module_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c
index a3479fba8501..db6bc4cfb971 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_mdio.c
@@ -114,6 +114,19 @@ static void hbg_mdio_init_hw(struct hbg_priv *priv)
hbg_mdio_set_command(mac, cmd);
}
+static void hbg_flowctrl_cfg(struct hbg_priv *priv)
+{
+ struct phy_device *phydev = priv->mac.phydev;
+ bool rx_pause;
+ bool tx_pause;
+
+ if (!priv->mac.pause_autoneg)
+ return;
+
+ phy_get_pause(phydev, &tx_pause, &rx_pause);
+ hbg_hw_set_pause_enable(priv, tx_pause, rx_pause);
+}
+
static void hbg_phy_adjust_link(struct net_device *netdev)
{
struct hbg_priv *priv = netdev_priv(netdev);
@@ -140,6 +153,7 @@ static void hbg_phy_adjust_link(struct net_device *netdev)
priv->mac.duplex = phydev->duplex;
priv->mac.autoneg = phydev->autoneg;
hbg_hw_adjust_link(priv, speed, phydev->duplex);
+ hbg_flowctrl_cfg(priv);
}
priv->mac.link_status = phydev->link;
@@ -168,6 +182,7 @@ static int hbg_phy_connect(struct hbg_priv *priv)
return ret;
phy_remove_link_mode(phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
+ phy_support_asym_pause(phydev);
phy_attached_info(phydev);
return 0;
diff --git a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
index 57d81c6d7633..f12efc12f3c5 100644
--- a/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
+++ b/drivers/net/ethernet/hisilicon/hibmcge/hbg_reg.h
@@ -10,6 +10,8 @@
#define HBG_REG_MAC_ID_ADDR 0x0008
#define HBG_REG_PHY_ID_ADDR 0x000C
#define HBG_REG_MAC_ADDR_ADDR 0x0010
+#define HBG_REG_MAC_ADDR_HIGH_ADDR 0x0014
+#define HBG_REG_UC_MAC_NUM_ADDR 0x0018
#define HBG_REG_MDIO_FREQ_ADDR 0x0024
#define HBG_REG_MAX_MTU_ADDR 0x0028
#define HBG_REG_MIN_MTU_ADDR 0x002C
@@ -28,6 +30,7 @@
#define HBG_REG_MDIO_COMMAND_OP_M GENMASK(11, 10)
#define HBG_REG_MDIO_COMMAND_PRTAD_M GENMASK(9, 5)
#define HBG_REG_MDIO_COMMAND_DEVAD_M GENMASK(4, 0)
+#define HBG_REG_MDIO_ADDR_ADDR (HBG_REG_MDIO_BASE + 0x0004)
#define HBG_REG_MDIO_WDATA_ADDR (HBG_REG_MDIO_BASE + 0x0008)
#define HBG_REG_MDIO_WDATA_M GENMASK(15, 0)
#define HBG_REG_MDIO_RDATA_ADDR (HBG_REG_MDIO_BASE + 0x000C)
@@ -36,6 +39,10 @@
/* GMAC */
#define HBG_REG_SGMII_BASE 0x10000
#define HBG_REG_DUPLEX_TYPE_ADDR (HBG_REG_SGMII_BASE + 0x0008)
+#define HBG_REG_FD_FC_TYPE_ADDR (HBG_REG_SGMII_BASE + 0x000C)
+#define HBG_REG_FC_TX_TIMER_ADDR (HBG_REG_SGMII_BASE + 0x001C)
+#define HBG_REG_FD_FC_ADDR_LOW_ADDR (HBG_REG_SGMII_BASE + 0x0020)
+#define HBG_REG_FD_FC_ADDR_HIGH_ADDR (HBG_REG_SGMII_BASE + 0x0024)
#define HBG_REG_DUPLEX_B BIT(0)
#define HBG_REG_MAX_FRAME_SIZE_ADDR (HBG_REG_SGMII_BASE + 0x003C)
#define HBG_REG_PORT_MODE_ADDR (HBG_REG_SGMII_BASE + 0x0040)
@@ -43,20 +50,42 @@
#define HBG_REG_PORT_ENABLE_ADDR (HBG_REG_SGMII_BASE + 0x0044)
#define HBG_REG_PORT_ENABLE_RX_B BIT(1)
#define HBG_REG_PORT_ENABLE_TX_B BIT(2)
+#define HBG_REG_PAUSE_ENABLE_ADDR (HBG_REG_SGMII_BASE + 0x0048)
+#define HBG_REG_PAUSE_ENABLE_RX_B BIT(0)
+#define HBG_REG_PAUSE_ENABLE_TX_B BIT(1)
+#define HBG_REG_AN_NEG_STATE_ADDR (HBG_REG_SGMII_BASE + 0x0058)
#define HBG_REG_TRANSMIT_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x0060)
#define HBG_REG_TRANSMIT_CTRL_PAD_EN_B BIT(7)
#define HBG_REG_TRANSMIT_CTRL_CRC_ADD_B BIT(6)
#define HBG_REG_TRANSMIT_CTRL_AN_EN_B BIT(5)
+#define HBG_REG_REC_FILT_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x0064)
+#define HBG_REG_REC_FILT_CTRL_UC_MATCH_EN_B BIT(0)
+#define HBG_REG_LINE_LOOP_BACK_ADDR (HBG_REG_SGMII_BASE + 0x01A8)
#define HBG_REG_CF_CRC_STRIP_ADDR (HBG_REG_SGMII_BASE + 0x01B0)
#define HBG_REG_CF_CRC_STRIP_B BIT(0)
#define HBG_REG_MODE_CHANGE_EN_ADDR (HBG_REG_SGMII_BASE + 0x01B4)
#define HBG_REG_MODE_CHANGE_EN_B BIT(0)
+#define HBG_REG_LOOP_REG_ADDR (HBG_REG_SGMII_BASE + 0x01DC)
#define HBG_REG_RECV_CTRL_ADDR (HBG_REG_SGMII_BASE + 0x01E0)
#define HBG_REG_RECV_CTRL_STRIP_PAD_EN_B BIT(3)
+#define HBG_REG_VLAN_CODE_ADDR (HBG_REG_SGMII_BASE + 0x01E8)
+#define HBG_REG_STATION_ADDR_LOW_0_ADDR (HBG_REG_SGMII_BASE + 0x0200)
+#define HBG_REG_STATION_ADDR_HIGH_0_ADDR (HBG_REG_SGMII_BASE + 0x0204)
+#define HBG_REG_STATION_ADDR_LOW_1_ADDR (HBG_REG_SGMII_BASE + 0x0208)
+#define HBG_REG_STATION_ADDR_HIGH_1_ADDR (HBG_REG_SGMII_BASE + 0x020C)
#define HBG_REG_STATION_ADDR_LOW_2_ADDR (HBG_REG_SGMII_BASE + 0x0210)
#define HBG_REG_STATION_ADDR_HIGH_2_ADDR (HBG_REG_SGMII_BASE + 0x0214)
+#define HBG_REG_STATION_ADDR_LOW_3_ADDR (HBG_REG_SGMII_BASE + 0x0218)
+#define HBG_REG_STATION_ADDR_HIGH_3_ADDR (HBG_REG_SGMII_BASE + 0x021C)
+#define HBG_REG_STATION_ADDR_LOW_4_ADDR (HBG_REG_SGMII_BASE + 0x0220)
+#define HBG_REG_STATION_ADDR_HIGH_4_ADDR (HBG_REG_SGMII_BASE + 0x0224)
+#define HBG_REG_STATION_ADDR_LOW_5_ADDR (HBG_REG_SGMII_BASE + 0x0228)
+#define HBG_REG_STATION_ADDR_HIGH_5_ADDR (HBG_REG_SGMII_BASE + 0x022C)
/* PCU */
+#define HBG_REG_TX_FIFO_THRSLD_ADDR (HBG_REG_SGMII_BASE + 0x0420)
+#define HBG_REG_RX_FIFO_THRSLD_ADDR (HBG_REG_SGMII_BASE + 0x0424)
+#define HBG_REG_CFG_FIFO_THRSLD_ADDR (HBG_REG_SGMII_BASE + 0x0428)
#define HBG_REG_CF_INTRPT_MSK_ADDR (HBG_REG_SGMII_BASE + 0x042C)
#define HBG_INT_MSK_WE_ERR_B BIT(31)
#define HBG_INT_MSK_RBREQ_ERR_B BIT(30)
@@ -78,11 +107,17 @@
#define HBG_INT_MSK_RX_B BIT(0) /* just used in driver */
#define HBG_REG_CF_INTRPT_STAT_ADDR (HBG_REG_SGMII_BASE + 0x0434)
#define HBG_REG_CF_INTRPT_CLR_ADDR (HBG_REG_SGMII_BASE + 0x0438)
+#define HBG_REG_TX_BUS_ERR_ADDR_ADDR (HBG_REG_SGMII_BASE + 0x043C)
+#define HBG_REG_RX_BUS_ERR_ADDR_ADDR (HBG_REG_SGMII_BASE + 0x0440)
#define HBG_REG_MAX_FRAME_LEN_ADDR (HBG_REG_SGMII_BASE + 0x0444)
#define HBG_REG_MAX_FRAME_LEN_M GENMASK(15, 0)
+#define HBG_REG_DEBUG_ST_MCH_ADDR (HBG_REG_SGMII_BASE + 0x0450)
+#define HBG_REG_FIFO_CURR_STATUS_ADDR (HBG_REG_SGMII_BASE + 0x0454)
+#define HBG_REG_FIFO_HIST_STATUS_ADDR (HBG_REG_SGMII_BASE + 0x0458)
#define HBG_REG_CF_CFF_DATA_NUM_ADDR (HBG_REG_SGMII_BASE + 0x045C)
#define HBG_REG_CF_CFF_DATA_NUM_ADDR_TX_M GENMASK(8, 0)
#define HBG_REG_CF_CFF_DATA_NUM_ADDR_RX_M GENMASK(24, 16)
+#define HBG_REG_CF_TX_PAUSE_ADDR (HBG_REG_SGMII_BASE + 0x0470)
#define HBG_REG_TX_CFF_ADDR_0_ADDR (HBG_REG_SGMII_BASE + 0x0488)
#define HBG_REG_TX_CFF_ADDR_1_ADDR (HBG_REG_SGMII_BASE + 0x048C)
#define HBG_REG_TX_CFF_ADDR_2_ADDR (HBG_REG_SGMII_BASE + 0x0490)
@@ -101,6 +136,10 @@
#define HBG_REG_RX_CTRL_RXBUF_1ST_SKIP_SIZE2_M GENMASK(3, 0)
#define HBG_REG_RX_PKT_MODE_ADDR (HBG_REG_SGMII_BASE + 0x04F4)
#define HBG_REG_RX_PKT_MODE_PARSE_MODE_M GENMASK(22, 21)
+#define HBG_REG_DBG_ST0_ADDR (HBG_REG_SGMII_BASE + 0x05E4)
+#define HBG_REG_DBG_ST1_ADDR (HBG_REG_SGMII_BASE + 0x05E8)
+#define HBG_REG_DBG_ST2_ADDR (HBG_REG_SGMII_BASE + 0x05EC)
+#define HBG_REG_BUS_RST_EN_ADDR (HBG_REG_SGMII_BASE + 0x0688)
#define HBG_REG_CF_IND_TXINT_MSK_ADDR (HBG_REG_SGMII_BASE + 0x0694)
#define HBG_REG_IND_INTR_MASK_B BIT(0)
#define HBG_REG_CF_IND_TXINT_STAT_ADDR (HBG_REG_SGMII_BASE + 0x0698)
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
index 851490346261..6b6ced37e490 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.c
@@ -3019,115 +3019,6 @@ static struct platform_driver g_dsaf_driver = {
module_platform_driver(g_dsaf_driver);
-/**
- * hns_dsaf_roce_reset - reset dsaf and roce
- * @dsaf_fwnode: Pointer to framework node for the dasf
- * @dereset: false - request reset , true - drop reset
- * return 0 - success , negative -fail
- */
-int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
-{
- struct dsaf_device *dsaf_dev;
- struct platform_device *pdev;
- u32 mp;
- u32 sl;
- u32 credit;
- int i;
- static const u32 port_map[DSAF_ROCE_CREDIT_CHN][DSAF_ROCE_CHAN_MODE_NUM] = {
- {DSAF_ROCE_PORT_0, DSAF_ROCE_PORT_0, DSAF_ROCE_PORT_0},
- {DSAF_ROCE_PORT_1, DSAF_ROCE_PORT_0, DSAF_ROCE_PORT_0},
- {DSAF_ROCE_PORT_2, DSAF_ROCE_PORT_1, DSAF_ROCE_PORT_0},
- {DSAF_ROCE_PORT_3, DSAF_ROCE_PORT_1, DSAF_ROCE_PORT_0},
- {DSAF_ROCE_PORT_4, DSAF_ROCE_PORT_2, DSAF_ROCE_PORT_1},
- {DSAF_ROCE_PORT_4, DSAF_ROCE_PORT_2, DSAF_ROCE_PORT_1},
- {DSAF_ROCE_PORT_5, DSAF_ROCE_PORT_3, DSAF_ROCE_PORT_1},
- {DSAF_ROCE_PORT_5, DSAF_ROCE_PORT_3, DSAF_ROCE_PORT_1},
- };
- static const u32 sl_map[DSAF_ROCE_CREDIT_CHN][DSAF_ROCE_CHAN_MODE_NUM] = {
- {DSAF_ROCE_SL_0, DSAF_ROCE_SL_0, DSAF_ROCE_SL_0},
- {DSAF_ROCE_SL_0, DSAF_ROCE_SL_1, DSAF_ROCE_SL_1},
- {DSAF_ROCE_SL_0, DSAF_ROCE_SL_0, DSAF_ROCE_SL_2},
- {DSAF_ROCE_SL_0, DSAF_ROCE_SL_1, DSAF_ROCE_SL_3},
- {DSAF_ROCE_SL_0, DSAF_ROCE_SL_0, DSAF_ROCE_SL_0},
- {DSAF_ROCE_SL_1, DSAF_ROCE_SL_1, DSAF_ROCE_SL_1},
- {DSAF_ROCE_SL_0, DSAF_ROCE_SL_0, DSAF_ROCE_SL_2},
- {DSAF_ROCE_SL_1, DSAF_ROCE_SL_1, DSAF_ROCE_SL_3},
- };
-
- /* find the platform device corresponding to fwnode */
- if (is_of_node(dsaf_fwnode)) {
- pdev = of_find_device_by_node(to_of_node(dsaf_fwnode));
- } else if (is_acpi_device_node(dsaf_fwnode)) {
- pdev = hns_dsaf_find_platform_device(dsaf_fwnode);
- } else {
- pr_err("fwnode is neither OF or ACPI type\n");
- return -EINVAL;
- }
-
- /* check if we were a success in fetching pdev */
- if (!pdev) {
- pr_err("couldn't find platform device for node\n");
- return -ENODEV;
- }
-
- /* retrieve the dsaf_device from the driver data */
- dsaf_dev = dev_get_drvdata(&pdev->dev);
- if (!dsaf_dev) {
- dev_err(&pdev->dev, "dsaf_dev is NULL\n");
- put_device(&pdev->dev);
- return -ENODEV;
- }
-
- /* now, make sure we are running on compatible SoC */
- if (AE_IS_VER1(dsaf_dev->dsaf_ver)) {
- dev_err(dsaf_dev->dev, "%s v1 chip doesn't support RoCE!\n",
- dsaf_dev->ae_dev.name);
- put_device(&pdev->dev);
- return -ENODEV;
- }
-
- /* do reset or de-reset according to the flag */
- if (!dereset) {
- /* reset rocee-channels in dsaf and rocee */
- dsaf_dev->misc_op->hns_dsaf_srst_chns(dsaf_dev, DSAF_CHNS_MASK,
- false);
- dsaf_dev->misc_op->hns_dsaf_roce_srst(dsaf_dev, false);
- } else {
- /* configure dsaf tx roce correspond to port map and sl map */
- mp = dsaf_read_dev(dsaf_dev, DSAF_ROCE_PORT_MAP_REG);
- for (i = 0; i < DSAF_ROCE_CREDIT_CHN; i++)
- dsaf_set_field(mp, 7 << i * 3, i * 3,
- port_map[i][DSAF_ROCE_6PORT_MODE]);
- dsaf_set_field(mp, 3 << i * 3, i * 3, 0);
- dsaf_write_dev(dsaf_dev, DSAF_ROCE_PORT_MAP_REG, mp);
-
- sl = dsaf_read_dev(dsaf_dev, DSAF_ROCE_SL_MAP_REG);
- for (i = 0; i < DSAF_ROCE_CREDIT_CHN; i++)
- dsaf_set_field(sl, 3 << i * 2, i * 2,
- sl_map[i][DSAF_ROCE_6PORT_MODE]);
- dsaf_write_dev(dsaf_dev, DSAF_ROCE_SL_MAP_REG, sl);
-
- /* de-reset rocee-channels in dsaf and rocee */
- dsaf_dev->misc_op->hns_dsaf_srst_chns(dsaf_dev, DSAF_CHNS_MASK,
- true);
- msleep(SRST_TIME_INTERVAL);
- dsaf_dev->misc_op->hns_dsaf_roce_srst(dsaf_dev, true);
-
- /* enable dsaf channel rocee credit */
- credit = dsaf_read_dev(dsaf_dev, DSAF_SBM_ROCEE_CFG_REG_REG);
- dsaf_set_bit(credit, DSAF_SBM_ROCEE_CFG_CRD_EN_B, 0);
- dsaf_write_dev(dsaf_dev, DSAF_SBM_ROCEE_CFG_REG_REG, credit);
-
- dsaf_set_bit(credit, DSAF_SBM_ROCEE_CFG_CRD_EN_B, 1);
- dsaf_write_dev(dsaf_dev, DSAF_SBM_ROCEE_CFG_REG_REG, credit);
- }
-
- put_device(&pdev->dev);
-
- return 0;
-}
-EXPORT_SYMBOL(hns_dsaf_roce_reset);
-
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Huawei Tech. Co., Ltd.");
MODULE_DESCRIPTION("HNS DSAF driver");
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
index 0eb03dff1a8b..653dfbb25d1b 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_main.h
@@ -42,29 +42,6 @@ struct hns_mac_cb;
#define HNS_MAX_WAIT_CNT 10000
-enum dsaf_roce_port_mode {
- DSAF_ROCE_6PORT_MODE,
- DSAF_ROCE_4PORT_MODE,
- DSAF_ROCE_2PORT_MODE,
- DSAF_ROCE_CHAN_MODE_NUM,
-};
-
-enum dsaf_roce_port_num {
- DSAF_ROCE_PORT_0,
- DSAF_ROCE_PORT_1,
- DSAF_ROCE_PORT_2,
- DSAF_ROCE_PORT_3,
- DSAF_ROCE_PORT_4,
- DSAF_ROCE_PORT_5,
-};
-
-enum dsaf_roce_qos_sl {
- DSAF_ROCE_SL_0,
- DSAF_ROCE_SL_1,
- DSAF_ROCE_SL_2,
- DSAF_ROCE_SL_3,
-};
-
#define DSAF_STATS_READ(p, offset) (*((u64 *)((u8 *)(p) + (offset))))
#define HNS_DSAF_IS_DEBUG(dev) ((dev)->dsaf_mode == DSAF_MODE_DISABLE_SP)
@@ -307,9 +284,6 @@ struct dsaf_misc_op {
void (*ge_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset);
void (*ppe_srst)(struct dsaf_device *dsaf_dev, u32 port, bool dereset);
void (*ppe_comm_srst)(struct dsaf_device *dsaf_dev, bool dereset);
- void (*hns_dsaf_srst_chns)(struct dsaf_device *dsaf_dev, u32 msk,
- bool dereset);
- void (*hns_dsaf_roce_srst)(struct dsaf_device *dsaf_dev, bool dereset);
phy_interface_t (*get_phy_if)(struct hns_mac_cb *mac_cb);
int (*get_sfp_prsnt)(struct hns_mac_cb *mac_cb, int *sfp_prsnt);
@@ -463,6 +437,4 @@ int hns_dsaf_clr_mac_mc_port(struct dsaf_device *dsaf_dev,
u8 mac_id, u8 port_num);
int hns_dsaf_wait_pkt_clean(struct dsaf_device *dsaf_dev, int port);
-int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset);
-
#endif /* __HNS_DSAF_MAIN_H__ */
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
index 5df19c604d09..91391a49fcea 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_misc.c
@@ -326,69 +326,6 @@ static void hns_dsaf_xge_srst_by_port_acpi(struct dsaf_device *dsaf_dev,
HNS_XGE_RESET_FUNC, port, dereset);
}
-/**
- * hns_dsaf_srst_chns - reset dsaf channels
- * @dsaf_dev: dsaf device struct pointer
- * @msk: xbar channels mask value:
- * @dereset: false - request reset , true - drop reset
- *
- * bit0-5 for xge0-5
- * bit6-11 for ppe0-5
- * bit12-17 for roce0-5
- * bit18-19 for com/dfx
- */
-static void
-hns_dsaf_srst_chns(struct dsaf_device *dsaf_dev, u32 msk, bool dereset)
-{
- u32 reg_addr;
-
- if (!dereset)
- reg_addr = DSAF_SUB_SC_DSAF_RESET_REQ_REG;
- else
- reg_addr = DSAF_SUB_SC_DSAF_RESET_DREQ_REG;
-
- dsaf_write_sub(dsaf_dev, reg_addr, msk);
-}
-
-/**
- * hns_dsaf_srst_chns_acpi - reset dsaf channels
- * @dsaf_dev: dsaf device struct pointer
- * @msk: xbar channels mask value:
- * @dereset: false - request reset , true - drop reset
- *
- * bit0-5 for xge0-5
- * bit6-11 for ppe0-5
- * bit12-17 for roce0-5
- * bit18-19 for com/dfx
- */
-static void
-hns_dsaf_srst_chns_acpi(struct dsaf_device *dsaf_dev, u32 msk, bool dereset)
-{
- hns_dsaf_acpi_srst_by_port(dsaf_dev, HNS_OP_RESET_FUNC,
- HNS_DSAF_CHN_RESET_FUNC,
- msk, dereset);
-}
-
-static void hns_dsaf_roce_srst(struct dsaf_device *dsaf_dev, bool dereset)
-{
- if (!dereset) {
- dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_ROCEE_RESET_REQ_REG, 1);
- } else {
- dsaf_write_sub(dsaf_dev,
- DSAF_SUB_SC_ROCEE_CLK_DIS_REG, 1);
- dsaf_write_sub(dsaf_dev,
- DSAF_SUB_SC_ROCEE_RESET_DREQ_REG, 1);
- msleep(20);
- dsaf_write_sub(dsaf_dev, DSAF_SUB_SC_ROCEE_CLK_EN_REG, 1);
- }
-}
-
-static void hns_dsaf_roce_srst_acpi(struct dsaf_device *dsaf_dev, bool dereset)
-{
- hns_dsaf_acpi_srst_by_port(dsaf_dev, HNS_OP_RESET_FUNC,
- HNS_ROCE_RESET_FUNC, 0, dereset);
-}
-
static void hns_dsaf_ge_srst_by_port(struct dsaf_device *dsaf_dev, u32 port,
bool dereset)
{
@@ -729,8 +666,6 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev)
misc_op->ge_srst = hns_dsaf_ge_srst_by_port;
misc_op->ppe_srst = hns_ppe_srst_by_port;
misc_op->ppe_comm_srst = hns_ppe_com_srst;
- misc_op->hns_dsaf_srst_chns = hns_dsaf_srst_chns;
- misc_op->hns_dsaf_roce_srst = hns_dsaf_roce_srst;
misc_op->get_phy_if = hns_mac_get_phy_if;
misc_op->get_sfp_prsnt = hns_mac_get_sfp_prsnt;
@@ -746,8 +681,6 @@ struct dsaf_misc_op *hns_misc_op_get(struct dsaf_device *dsaf_dev)
misc_op->ge_srst = hns_dsaf_ge_srst_by_port_acpi;
misc_op->ppe_srst = hns_ppe_srst_by_port_acpi;
misc_op->ppe_comm_srst = hns_ppe_com_srst;
- misc_op->hns_dsaf_srst_chns = hns_dsaf_srst_chns_acpi;
- misc_op->hns_dsaf_roce_srst = hns_dsaf_roce_srst_acpi;
misc_op->get_phy_if = hns_mac_get_phy_if_acpi;
misc_op->get_sfp_prsnt = hns_mac_get_sfp_prsnt_acpi;
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
index 46af467aa596..635b3a95dd82 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.c
@@ -195,11 +195,6 @@ void hns_rcb_ring_enable_hw(struct hnae_queue *q, u32 val)
dsaf_write_dev(q, RCB_RING_PREFETCH_EN_REG, !!val);
}
-void hns_rcb_start(struct hnae_queue *q, u32 val)
-{
- hns_rcb_ring_enable_hw(q, val);
-}
-
/**
*hns_rcb_common_init_commit_hw - make rcb common init completed
*@rcb_common: rcb common device
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
index 0f4cc184ef39..68f81547dfb4 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
+++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_rcb.h
@@ -116,7 +116,6 @@ int hns_rcb_buf_size2type(u32 buf_size);
int hns_rcb_common_get_cfg(struct dsaf_device *dsaf_dev, int comm_index);
void hns_rcb_common_free_cfg(struct dsaf_device *dsaf_dev, u32 comm_index);
int hns_rcb_common_init_hw(struct rcb_common_cb *rcb_common);
-void hns_rcb_start(struct hnae_queue *q, u32 val);
int hns_rcb_get_cfg(struct rcb_common_cb *rcb_common);
void hns_rcb_get_queue_mode(enum dsaf_mode dsaf_mode,
u16 *max_vfn, u16 *max_q_per_vf);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
index 710a8f9f2248..12ba380eb701 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h
+++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h
@@ -916,9 +916,6 @@ struct hnae3_handle {
u8 netdev_flags;
struct dentry *hnae3_dbgfs;
- /* protects concurrent contention between debugfs commands */
- struct mutex dbgfs_lock;
- char **dbgfs_buf;
/* Network interface message level enabled bits */
u32 msg_enable;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
index 807eb3bbb11c..9bbece25552b 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_debugfs.c
@@ -1260,69 +1260,55 @@ static int hns3_dbg_read_cmd(struct hns3_dbg_data *dbg_data,
static ssize_t hns3_dbg_read(struct file *filp, char __user *buffer,
size_t count, loff_t *ppos)
{
- struct hns3_dbg_data *dbg_data = filp->private_data;
+ char *buf = filp->private_data;
+
+ return simple_read_from_buffer(buffer, count, ppos, buf, strlen(buf));
+}
+
+static int hns3_dbg_open(struct inode *inode, struct file *filp)
+{
+ struct hns3_dbg_data *dbg_data = inode->i_private;
struct hnae3_handle *handle = dbg_data->handle;
struct hns3_nic_priv *priv = handle->priv;
- ssize_t size = 0;
- char **save_buf;
- char *read_buf;
u32 index;
+ char *buf;
int ret;
+ if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) ||
+ test_bit(HNS3_NIC_STATE_RESETTING, &priv->state))
+ return -EBUSY;
+
ret = hns3_dbg_get_cmd_index(dbg_data, &index);
if (ret)
return ret;
- mutex_lock(&handle->dbgfs_lock);
- save_buf = &handle->dbgfs_buf[index];
-
- if (!test_bit(HNS3_NIC_STATE_INITED, &priv->state) ||
- test_bit(HNS3_NIC_STATE_RESETTING, &priv->state)) {
- ret = -EBUSY;
- goto out;
- }
-
- if (*save_buf) {
- read_buf = *save_buf;
- } else {
- read_buf = kvzalloc(hns3_dbg_cmd[index].buf_len, GFP_KERNEL);
- if (!read_buf) {
- ret = -ENOMEM;
- goto out;
- }
-
- /* save the buffer addr until the last read operation */
- *save_buf = read_buf;
-
- /* get data ready for the first time to read */
- ret = hns3_dbg_read_cmd(dbg_data, hns3_dbg_cmd[index].cmd,
- read_buf, hns3_dbg_cmd[index].buf_len);
- if (ret)
- goto out;
- }
+ buf = kvzalloc(hns3_dbg_cmd[index].buf_len, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
- size = simple_read_from_buffer(buffer, count, ppos, read_buf,
- strlen(read_buf));
- if (size > 0) {
- mutex_unlock(&handle->dbgfs_lock);
- return size;
+ ret = hns3_dbg_read_cmd(dbg_data, hns3_dbg_cmd[index].cmd,
+ buf, hns3_dbg_cmd[index].buf_len);
+ if (ret) {
+ kvfree(buf);
+ return ret;
}
-out:
- /* free the buffer for the last read operation */
- if (*save_buf) {
- kvfree(*save_buf);
- *save_buf = NULL;
- }
+ filp->private_data = buf;
+ return 0;
+}
- mutex_unlock(&handle->dbgfs_lock);
- return ret;
+static int hns3_dbg_release(struct inode *inode, struct file *filp)
+{
+ kvfree(filp->private_data);
+ filp->private_data = NULL;
+ return 0;
}
static const struct file_operations hns3_dbg_fops = {
.owner = THIS_MODULE,
- .open = simple_open,
+ .open = hns3_dbg_open,
.read = hns3_dbg_read,
+ .release = hns3_dbg_release,
};
static int hns3_dbg_bd_file_init(struct hnae3_handle *handle, u32 cmd)
@@ -1379,13 +1365,6 @@ int hns3_dbg_init(struct hnae3_handle *handle)
int ret;
u32 i;
- handle->dbgfs_buf = devm_kcalloc(&handle->pdev->dev,
- ARRAY_SIZE(hns3_dbg_cmd),
- sizeof(*handle->dbgfs_buf),
- GFP_KERNEL);
- if (!handle->dbgfs_buf)
- return -ENOMEM;
-
hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry =
debugfs_create_dir(name, hns3_dbgfs_root);
handle->hnae3_dbgfs = hns3_dbg_dentry[HNS3_DBG_DENTRY_COMMON].dentry;
@@ -1395,8 +1374,6 @@ int hns3_dbg_init(struct hnae3_handle *handle)
debugfs_create_dir(hns3_dbg_dentry[i].name,
handle->hnae3_dbgfs);
- mutex_init(&handle->dbgfs_lock);
-
for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++) {
if ((hns3_dbg_cmd[i].cmd == HNAE3_DBG_CMD_TM_NODES &&
ae_dev->dev_version <= HNAE3_DEVICE_VERSION_V2) ||
@@ -1425,24 +1402,13 @@ int hns3_dbg_init(struct hnae3_handle *handle)
out:
debugfs_remove_recursive(handle->hnae3_dbgfs);
handle->hnae3_dbgfs = NULL;
- mutex_destroy(&handle->dbgfs_lock);
return ret;
}
void hns3_dbg_uninit(struct hnae3_handle *handle)
{
- u32 i;
-
debugfs_remove_recursive(handle->hnae3_dbgfs);
handle->hnae3_dbgfs = NULL;
-
- for (i = 0; i < ARRAY_SIZE(hns3_dbg_cmd); i++)
- if (handle->dbgfs_buf[i]) {
- kvfree(handle->dbgfs_buf[i]);
- handle->dbgfs_buf[i] = NULL;
- }
-
- mutex_destroy(&handle->dbgfs_lock);
}
void hns3_dbg_register_debugfs(const char *debugfs_dir_name)
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
index 43377a7b2426..a7e3b22f641c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c
@@ -2452,7 +2452,6 @@ static int hns3_nic_set_features(struct net_device *netdev,
return ret;
}
- netdev->features = features;
return 0;
}
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 05942fa78b11..db7845009252 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -6,6 +6,7 @@
#include <linux/etherdevice.h>
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/netdevice.h>
@@ -3574,6 +3575,17 @@ static int hclge_set_vf_link_state(struct hnae3_handle *handle, int vf,
return ret;
}
+static void hclge_set_reset_pending(struct hclge_dev *hdev,
+ enum hnae3_reset_type reset_type)
+{
+ /* When an incorrect reset type is executed, the get_reset_level
+ * function generates the HNAE3_NONE_RESET flag. As a result, this
+ * type do not need to pending.
+ */
+ if (reset_type != HNAE3_NONE_RESET)
+ set_bit(reset_type, &hdev->reset_pending);
+}
+
static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
{
u32 cmdq_src_reg, msix_src_reg, hw_err_src_reg;
@@ -3594,7 +3606,7 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
*/
if (BIT(HCLGE_VECTOR0_IMPRESET_INT_B) & msix_src_reg) {
dev_info(&hdev->pdev->dev, "IMP reset interrupt\n");
- set_bit(HNAE3_IMP_RESET, &hdev->reset_pending);
+ hclge_set_reset_pending(hdev, HNAE3_IMP_RESET);
set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state);
*clearval = BIT(HCLGE_VECTOR0_IMPRESET_INT_B);
hdev->rst_stats.imp_rst_cnt++;
@@ -3604,7 +3616,7 @@ static u32 hclge_check_event_cause(struct hclge_dev *hdev, u32 *clearval)
if (BIT(HCLGE_VECTOR0_GLOBALRESET_INT_B) & msix_src_reg) {
dev_info(&hdev->pdev->dev, "global reset interrupt\n");
set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state);
- set_bit(HNAE3_GLOBAL_RESET, &hdev->reset_pending);
+ hclge_set_reset_pending(hdev, HNAE3_GLOBAL_RESET);
*clearval = BIT(HCLGE_VECTOR0_GLOBALRESET_INT_B);
hdev->rst_stats.global_rst_cnt++;
return HCLGE_VECTOR0_EVENT_RST;
@@ -3759,7 +3771,7 @@ static int hclge_misc_irq_init(struct hclge_dev *hdev)
snprintf(hdev->misc_vector.name, HNAE3_INT_NAME_LEN, "%s-misc-%s",
HCLGE_NAME, pci_name(hdev->pdev));
ret = request_irq(hdev->misc_vector.vector_irq, hclge_misc_irq_handle,
- 0, hdev->misc_vector.name, hdev);
+ IRQF_NO_AUTOEN, hdev->misc_vector.name, hdev);
if (ret) {
hclge_free_vector(hdev, 0);
dev_err(&hdev->pdev->dev, "request misc irq(%d) fail\n",
@@ -4052,7 +4064,7 @@ static void hclge_do_reset(struct hclge_dev *hdev)
case HNAE3_FUNC_RESET:
dev_info(&pdev->dev, "PF reset requested\n");
/* schedule again to check later */
- set_bit(HNAE3_FUNC_RESET, &hdev->reset_pending);
+ hclge_set_reset_pending(hdev, HNAE3_FUNC_RESET);
hclge_reset_task_schedule(hdev);
break;
default:
@@ -4086,6 +4098,8 @@ static enum hnae3_reset_type hclge_get_reset_level(struct hnae3_ae_dev *ae_dev,
clear_bit(HNAE3_FLR_RESET, addr);
}
+ clear_bit(HNAE3_NONE_RESET, addr);
+
if (hdev->reset_type != HNAE3_NONE_RESET &&
rst_level < hdev->reset_type)
return HNAE3_NONE_RESET;
@@ -4227,7 +4241,7 @@ static bool hclge_reset_err_handle(struct hclge_dev *hdev)
return false;
} else if (hdev->rst_stats.reset_fail_cnt < MAX_RESET_FAIL_CNT) {
hdev->rst_stats.reset_fail_cnt++;
- set_bit(hdev->reset_type, &hdev->reset_pending);
+ hclge_set_reset_pending(hdev, hdev->reset_type);
dev_info(&hdev->pdev->dev,
"re-schedule reset task(%u)\n",
hdev->rst_stats.reset_fail_cnt);
@@ -4470,8 +4484,20 @@ static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle)
static void hclge_set_def_reset_request(struct hnae3_ae_dev *ae_dev,
enum hnae3_reset_type rst_type)
{
+#define HCLGE_SUPPORT_RESET_TYPE \
+ (BIT(HNAE3_FLR_RESET) | BIT(HNAE3_FUNC_RESET) | \
+ BIT(HNAE3_GLOBAL_RESET) | BIT(HNAE3_IMP_RESET))
+
struct hclge_dev *hdev = ae_dev->priv;
+ if (!(BIT(rst_type) & HCLGE_SUPPORT_RESET_TYPE)) {
+ /* To prevent reset triggered by hclge_reset_event */
+ set_bit(HNAE3_NONE_RESET, &hdev->default_reset_request);
+ dev_warn(&hdev->pdev->dev, "unsupported reset type %d\n",
+ rst_type);
+ return;
+ }
+
set_bit(rst_type, &hdev->default_reset_request);
}
@@ -11881,9 +11907,6 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
hclge_init_rxd_adv_layout(hdev);
- /* Enable MISC vector(vector0) */
- hclge_enable_vector(&hdev->misc_vector, true);
-
ret = hclge_init_wol(hdev);
if (ret)
dev_warn(&pdev->dev,
@@ -11896,6 +11919,10 @@ static int hclge_init_ae_dev(struct hnae3_ae_dev *ae_dev)
hclge_state_init(hdev);
hdev->last_reset_time = jiffies;
+ /* Enable MISC vector(vector0) */
+ enable_irq(hdev->misc_vector.vector_irq);
+ hclge_enable_vector(&hdev->misc_vector, true);
+
dev_info(&hdev->pdev->dev, "%s driver initialization finished.\n",
HCLGE_DRIVER_NAME);
@@ -12301,7 +12328,7 @@ static void hclge_uninit_ae_dev(struct hnae3_ae_dev *ae_dev)
/* Disable MISC vector(vector0) */
hclge_enable_vector(&hdev->misc_vector, false);
- synchronize_irq(hdev->misc_vector.vector_irq);
+ disable_irq(hdev->misc_vector.vector_irq);
/* Disable all hw interrupts */
hclge_config_mac_tnl_int(hdev, false);
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c
index 5505caea88e9..bab16c2191b2 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_ptp.c
@@ -58,6 +58,9 @@ bool hclge_ptp_set_tx_info(struct hnae3_handle *handle, struct sk_buff *skb)
struct hclge_dev *hdev = vport->back;
struct hclge_ptp *ptp = hdev->ptp;
+ if (!ptp)
+ return false;
+
if (!test_bit(HCLGE_PTP_FLAG_TX_EN, &ptp->flags) ||
test_and_set_bit(HCLGE_STATE_PTP_TX_HANDLING, &hdev->state)) {
ptp->tx_skipped++;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c
index 43c1c18fa81f..8c057192aae6 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_regs.c
@@ -510,9 +510,9 @@ out:
static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data,
struct hnae3_knic_private_info *kinfo)
{
-#define HCLGE_RING_REG_OFFSET 0x200
#define HCLGE_RING_INT_REG_OFFSET 0x4
+ struct hnae3_queue *tqp;
int i, j, reg_num;
int data_num_sum;
u32 *reg = data;
@@ -533,10 +533,11 @@ static int hclge_fetch_pf_reg(struct hclge_dev *hdev, void *data,
reg_num = ARRAY_SIZE(ring_reg_addr_list);
for (j = 0; j < kinfo->num_tqps; j++) {
reg += hclge_reg_get_tlv(HCLGE_REG_TAG_RING, reg_num, reg);
+ tqp = kinfo->tqp[j];
for (i = 0; i < reg_num; i++)
- *reg++ = hclge_read_dev(&hdev->hw,
- ring_reg_addr_list[i] +
- HCLGE_RING_REG_OFFSET * j);
+ *reg++ = readl_relaxed(tqp->io_base -
+ HCLGE_TQP_REG_OFFSET +
+ ring_reg_addr_list[i]);
}
data_num_sum += (reg_num + HCLGE_REG_TLV_SPACE) * kinfo->num_tqps;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
index 2f6ffb88e700..163c6e59ea4c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c
@@ -1393,6 +1393,17 @@ static int hclgevf_notify_roce_client(struct hclgevf_dev *hdev,
return ret;
}
+static void hclgevf_set_reset_pending(struct hclgevf_dev *hdev,
+ enum hnae3_reset_type reset_type)
+{
+ /* When an incorrect reset type is executed, the get_reset_level
+ * function generates the HNAE3_NONE_RESET flag. As a result, this
+ * type do not need to pending.
+ */
+ if (reset_type != HNAE3_NONE_RESET)
+ set_bit(reset_type, &hdev->reset_pending);
+}
+
static int hclgevf_reset_wait(struct hclgevf_dev *hdev)
{
#define HCLGEVF_RESET_WAIT_US 20000
@@ -1542,7 +1553,7 @@ static void hclgevf_reset_err_handle(struct hclgevf_dev *hdev)
hdev->rst_stats.rst_fail_cnt);
if (hdev->rst_stats.rst_fail_cnt < HCLGEVF_RESET_MAX_FAIL_CNT)
- set_bit(hdev->reset_type, &hdev->reset_pending);
+ hclgevf_set_reset_pending(hdev, hdev->reset_type);
if (hclgevf_is_reset_pending(hdev)) {
set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
@@ -1662,6 +1673,8 @@ static enum hnae3_reset_type hclgevf_get_reset_level(unsigned long *addr)
clear_bit(HNAE3_FLR_RESET, addr);
}
+ clear_bit(HNAE3_NONE_RESET, addr);
+
return rst_level;
}
@@ -1671,14 +1684,15 @@ static void hclgevf_reset_event(struct pci_dev *pdev,
struct hnae3_ae_dev *ae_dev = pci_get_drvdata(pdev);
struct hclgevf_dev *hdev = ae_dev->priv;
- dev_info(&hdev->pdev->dev, "received reset request from VF enet\n");
-
if (hdev->default_reset_request)
hdev->reset_level =
hclgevf_get_reset_level(&hdev->default_reset_request);
else
hdev->reset_level = HNAE3_VF_FUNC_RESET;
+ dev_info(&hdev->pdev->dev, "received reset request from VF enet, reset level is %d\n",
+ hdev->reset_level);
+
/* reset of this VF requested */
set_bit(HCLGEVF_RESET_REQUESTED, &hdev->reset_state);
hclgevf_reset_task_schedule(hdev);
@@ -1689,8 +1703,20 @@ static void hclgevf_reset_event(struct pci_dev *pdev,
static void hclgevf_set_def_reset_request(struct hnae3_ae_dev *ae_dev,
enum hnae3_reset_type rst_type)
{
+#define HCLGEVF_SUPPORT_RESET_TYPE \
+ (BIT(HNAE3_VF_RESET) | BIT(HNAE3_VF_FUNC_RESET) | \
+ BIT(HNAE3_VF_PF_FUNC_RESET) | BIT(HNAE3_VF_FULL_RESET) | \
+ BIT(HNAE3_FLR_RESET) | BIT(HNAE3_VF_EXP_RESET))
+
struct hclgevf_dev *hdev = ae_dev->priv;
+ if (!(BIT(rst_type) & HCLGEVF_SUPPORT_RESET_TYPE)) {
+ /* To prevent reset triggered by hclge_reset_event */
+ set_bit(HNAE3_NONE_RESET, &hdev->default_reset_request);
+ dev_info(&hdev->pdev->dev, "unsupported reset type %d\n",
+ rst_type);
+ return;
+ }
set_bit(rst_type, &hdev->default_reset_request);
}
@@ -1847,14 +1873,14 @@ static void hclgevf_reset_service_task(struct hclgevf_dev *hdev)
*/
if (hdev->reset_attempts > HCLGEVF_MAX_RESET_ATTEMPTS_CNT) {
/* prepare for full reset of stack + pcie interface */
- set_bit(HNAE3_VF_FULL_RESET, &hdev->reset_pending);
+ hclgevf_set_reset_pending(hdev, HNAE3_VF_FULL_RESET);
/* "defer" schedule the reset task again */
set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
} else {
hdev->reset_attempts++;
- set_bit(hdev->reset_level, &hdev->reset_pending);
+ hclgevf_set_reset_pending(hdev, hdev->reset_level);
set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
}
hclgevf_reset_task_schedule(hdev);
@@ -1977,7 +2003,7 @@ static enum hclgevf_evt_cause hclgevf_check_evt_cause(struct hclgevf_dev *hdev,
rst_ing_reg = hclgevf_read_dev(&hdev->hw, HCLGEVF_RST_ING);
dev_info(&hdev->pdev->dev,
"receive reset interrupt 0x%x!\n", rst_ing_reg);
- set_bit(HNAE3_VF_RESET, &hdev->reset_pending);
+ hclgevf_set_reset_pending(hdev, HNAE3_VF_RESET);
set_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state);
set_bit(HCLGE_COMM_STATE_CMD_DISABLE, &hdev->hw.hw.comm_state);
*clearval = ~(1U << HCLGEVF_VECTOR0_RST_INT_B);
@@ -2287,6 +2313,8 @@ static void hclgevf_state_init(struct hclgevf_dev *hdev)
clear_bit(HCLGEVF_STATE_RST_FAIL, &hdev->state);
INIT_DELAYED_WORK(&hdev->service_task, hclgevf_service_task);
+ /* timer needs to be initialized before misc irq */
+ timer_setup(&hdev->reset_timer, hclgevf_reset_timer, 0);
mutex_init(&hdev->mbx_resp.mbx_mutex);
sema_init(&hdev->reset_sem, 1);
@@ -2986,7 +3014,6 @@ static int hclgevf_init_hdev(struct hclgevf_dev *hdev)
HCLGEVF_DRIVER_NAME);
hclgevf_task_schedule(hdev, round_jiffies_relative(HZ));
- timer_setup(&hdev->reset_timer, hclgevf_reset_timer, 0);
return 0;
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c
index 6db415d8b917..7d9d9dbc7560 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_regs.c
@@ -123,10 +123,10 @@ int hclgevf_get_regs_len(struct hnae3_handle *handle)
void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
void *data)
{
-#define HCLGEVF_RING_REG_OFFSET 0x200
#define HCLGEVF_RING_INT_REG_OFFSET 0x4
struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle);
+ struct hnae3_queue *tqp;
int i, j, reg_um;
u32 *reg = data;
@@ -147,10 +147,11 @@ void hclgevf_get_regs(struct hnae3_handle *handle, u32 *version,
reg_um = ARRAY_SIZE(ring_reg_addr_list);
for (j = 0; j < hdev->num_tqps; j++) {
reg += hclgevf_reg_get_tlv(HCLGEVF_REG_TAG_RING, reg_um, reg);
+ tqp = &hdev->htqp[j].q;
for (i = 0; i < reg_um; i++)
- *reg++ = hclgevf_read_dev(&hdev->hw,
- ring_reg_addr_list[i] +
- HCLGEVF_RING_REG_OFFSET * j);
+ *reg++ = readl_relaxed(tqp->io_base -
+ HCLGEVF_TQP_REG_OFFSET +
+ ring_reg_addr_list[i]);
}
reg_um = ARRAY_SIZE(tqp_intr_reg_addr_list);
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_main.c b/drivers/net/ethernet/huawei/hinic/hinic_main.c
index 890f213da8d1..ae1f523d6841 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_main.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_main.c
@@ -172,6 +172,7 @@ err_init_txq:
hinic_sq_dbgfs_uninit(nic_dev);
devm_kfree(&netdev->dev, nic_dev->txqs);
+ nic_dev->txqs = NULL;
return err;
}
@@ -268,6 +269,7 @@ err_init_rxq:
hinic_rq_dbgfs_uninit(nic_dev);
devm_kfree(&netdev->dev, nic_dev->rxqs);
+ nic_dev->rxqs = NULL;
return err;
}
diff --git a/drivers/net/ethernet/huawei/hinic/hinic_port.c b/drivers/net/ethernet/huawei/hinic/hinic_port.c
index f81a43d2cdfc..486fb0e20bef 100644
--- a/drivers/net/ethernet/huawei/hinic/hinic_port.c
+++ b/drivers/net/ethernet/huawei/hinic/hinic_port.c
@@ -469,7 +469,7 @@ int hinic_set_vlan_fliter(struct hinic_dev *nic_dev, u32 en)
err = HINIC_MGMT_CMD_UNSUPPORTED;
} else if (err || !out_size || vlan_filter.status) {
dev_err(&pdev->dev,
- "Failed to set vlan fliter, err: %d, status: 0x%x, out size: 0x%x\n",
+ "Failed to set vlan filter, err: %d, status: 0x%x, out size: 0x%x\n",
err, vlan_filter.status, out_size);
err = -EINVAL;
}
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 20bc40eec487..24ec9a4f1ffa 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -292,6 +292,7 @@ config ICE
select DIMLIB
select LIBIE
select NET_DEVLINK
+ select PACKING
select PLDMFW
select DPLL
help
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
index 98861cc6df7c..b9dd7b719832 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.c
@@ -1180,126 +1180,6 @@ s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid)
}
/**
- * fm10k_iov_msg_mac_vlan_pf - Message handler for MAC/VLAN request from VF
- * @hw: Pointer to hardware structure
- * @results: Pointer array to message, results[0] is pointer to message
- * @mbx: Pointer to mailbox information structure
- *
- * This function is a default handler for MAC/VLAN requests from the VF.
- * The assumption is that in this case it is acceptable to just directly
- * hand off the message from the VF to the underlying shared code.
- **/
-s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *hw, u32 **results,
- struct fm10k_mbx_info *mbx)
-{
- struct fm10k_vf_info *vf_info = (struct fm10k_vf_info *)mbx;
- u8 mac[ETH_ALEN];
- u32 *result;
- int err = 0;
- bool set;
- u16 vlan;
- u32 vid;
-
- /* we shouldn't be updating rules on a disabled interface */
- if (!FM10K_VF_FLAG_ENABLED(vf_info))
- err = FM10K_ERR_PARAM;
-
- if (!err && !!results[FM10K_MAC_VLAN_MSG_VLAN]) {
- result = results[FM10K_MAC_VLAN_MSG_VLAN];
-
- /* record VLAN id requested */
- err = fm10k_tlv_attr_get_u32(result, &vid);
- if (err)
- return err;
-
- set = !(vid & FM10K_VLAN_CLEAR);
- vid &= ~FM10K_VLAN_CLEAR;
-
- /* if the length field has been set, this is a multi-bit
- * update request. For multi-bit requests, simply disallow
- * them when the pf_vid has been set. In this case, the PF
- * should have already cleared the VLAN_TABLE, and if we
- * allowed them, it could allow a rogue VF to receive traffic
- * on a VLAN it was not assigned. In the single-bit case, we
- * need to modify requests for VLAN 0 to use the default PF or
- * SW vid when assigned.
- */
-
- if (vid >> 16) {
- /* prevent multi-bit requests when PF has
- * administratively set the VLAN for this VF
- */
- if (vf_info->pf_vid)
- return FM10K_ERR_PARAM;
- } else {
- err = fm10k_iov_select_vid(vf_info, (u16)vid);
- if (err < 0)
- return err;
-
- vid = err;
- }
-
- /* update VSI info for VF in regards to VLAN table */
- err = hw->mac.ops.update_vlan(hw, vid, vf_info->vsi, set);
- }
-
- if (!err && !!results[FM10K_MAC_VLAN_MSG_MAC]) {
- result = results[FM10K_MAC_VLAN_MSG_MAC];
-
- /* record unicast MAC address requested */
- err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan);
- if (err)
- return err;
-
- /* block attempts to set MAC for a locked device */
- if (is_valid_ether_addr(vf_info->mac) &&
- !ether_addr_equal(mac, vf_info->mac))
- return FM10K_ERR_PARAM;
-
- set = !(vlan & FM10K_VLAN_CLEAR);
- vlan &= ~FM10K_VLAN_CLEAR;
-
- err = fm10k_iov_select_vid(vf_info, vlan);
- if (err < 0)
- return err;
-
- vlan = (u16)err;
-
- /* notify switch of request for new unicast address */
- err = hw->mac.ops.update_uc_addr(hw, vf_info->glort,
- mac, vlan, set, 0);
- }
-
- if (!err && !!results[FM10K_MAC_VLAN_MSG_MULTICAST]) {
- result = results[FM10K_MAC_VLAN_MSG_MULTICAST];
-
- /* record multicast MAC address requested */
- err = fm10k_tlv_attr_get_mac_vlan(result, mac, &vlan);
- if (err)
- return err;
-
- /* verify that the VF is allowed to request multicast */
- if (!(vf_info->vf_flags & FM10K_VF_FLAG_MULTI_ENABLED))
- return FM10K_ERR_PARAM;
-
- set = !(vlan & FM10K_VLAN_CLEAR);
- vlan &= ~FM10K_VLAN_CLEAR;
-
- err = fm10k_iov_select_vid(vf_info, vlan);
- if (err < 0)
- return err;
-
- vlan = (u16)err;
-
- /* notify switch of request for new multicast address */
- err = hw->mac.ops.update_mc_addr(hw, vf_info->glort,
- mac, vlan, set);
- }
-
- return err;
-}
-
-/**
* fm10k_iov_supported_xcast_mode_pf - Determine best match for xcast mode
* @vf_info: VF info structure containing capability flags
* @mode: Requested xcast mode
diff --git a/drivers/net/ethernet/intel/fm10k/fm10k_pf.h b/drivers/net/ethernet/intel/fm10k/fm10k_pf.h
index 8e814df709d2..ad3696893cb1 100644
--- a/drivers/net/ethernet/intel/fm10k/fm10k_pf.h
+++ b/drivers/net/ethernet/intel/fm10k/fm10k_pf.h
@@ -99,8 +99,6 @@ extern const struct fm10k_tlv_attr fm10k_err_msg_attr[];
s32 fm10k_iov_select_vid(struct fm10k_vf_info *vf_info, u16 vid);
s32 fm10k_iov_msg_msix_pf(struct fm10k_hw *, u32 **, struct fm10k_mbx_info *);
-s32 fm10k_iov_msg_mac_vlan_pf(struct fm10k_hw *, u32 **,
- struct fm10k_mbx_info *);
s32 fm10k_iov_msg_lport_state_pf(struct fm10k_hw *, u32 **,
struct fm10k_mbx_info *);
diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h
index d4255c2706fa..c67963bfe14e 100644
--- a/drivers/net/ethernet/intel/i40e/i40e.h
+++ b/drivers/net/ethernet/intel/i40e/i40e.h
@@ -88,6 +88,7 @@ enum i40e_state {
__I40E_SERVICE_SCHED,
__I40E_ADMINQ_EVENT_PENDING,
__I40E_MDD_EVENT_PENDING,
+ __I40E_MDD_VF_PRINT_PENDING,
__I40E_VFLR_EVENT_PENDING,
__I40E_RESET_RECOVERY_PENDING,
__I40E_TIMEOUT_RECOVERY_PENDING,
@@ -191,6 +192,7 @@ enum i40e_pf_flags {
*/
I40E_FLAG_TOTAL_PORT_SHUTDOWN_ENA,
I40E_FLAG_VF_VLAN_PRUNING_ENA,
+ I40E_FLAG_MDD_AUTO_RESET_VF,
I40E_PF_FLAGS_NBITS, /* must be last */
};
@@ -572,7 +574,7 @@ struct i40e_pf {
int num_alloc_vfs; /* actual number of VFs allocated */
u32 vf_aq_requests;
u32 arq_overflows; /* Not fatal, possibly indicative of problems */
-
+ struct ratelimit_state mdd_message_rate_limit;
/* DCBx/DCBNL capability for PF that indicates
* whether DCBx is managed by firmware or host
* based agent (LLDPAD). Also, indicates what
@@ -1189,7 +1191,6 @@ int i40e_add_del_fdir(struct i40e_vsi *vsi,
struct i40e_fdir_filter *input, bool add);
void i40e_fdir_check_and_reenable(struct i40e_pf *pf);
u32 i40e_get_current_fd_count(struct i40e_pf *pf);
-u32 i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf);
u32 i40e_get_current_atr_cnt(struct i40e_pf *pf);
u32 i40e_get_global_fd_count(struct i40e_pf *pf);
bool i40e_set_ntuple(struct i40e_pf *pf, netdev_features_t features);
@@ -1197,7 +1198,6 @@ void i40e_set_ethtool_ops(struct net_device *netdev);
struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
const u8 *macaddr, s16 vlan);
void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f);
-void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan);
int i40e_sync_vsi_filters(struct i40e_vsi *vsi);
struct i40e_vsi *i40e_vsi_setup(struct i40e_pf *pf, u8 type,
u16 uplink, u32 param1);
@@ -1313,7 +1313,6 @@ int i40e_update_adq_vsi_queues(struct i40e_vsi *vsi, int vsi_offset);
int i40e_is_vsi_uplink_mode_veb(struct i40e_vsi *vsi);
int i40e_get_partition_bw_setting(struct i40e_pf *pf);
int i40e_set_partition_bw_setting(struct i40e_pf *pf);
-int i40e_commit_partition_bw_setting(struct i40e_pf *pf);
void i40e_print_link_message(struct i40e_vsi *vsi, bool isup);
void i40e_set_fec_in_flags(u8 fec_cfg, unsigned long *flags);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq.c b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
index f73f5930fc58..175c1320c143 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_adminq.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_adminq.c
@@ -1016,16 +1016,6 @@ i40e_asq_send_command_atomic_v2(struct i40e_hw *hw,
return status;
}
-int
-i40e_asq_send_command_v2(struct i40e_hw *hw, struct i40e_aq_desc *desc,
- void *buff, /* can be NULL */ u16 buff_size,
- struct i40e_asq_cmd_details *cmd_details,
- enum i40e_admin_queue_err *aq_status)
-{
- return i40e_asq_send_command_atomic_v2(hw, desc, buff, buff_size,
- cmd_details, true, aq_status);
-}
-
/**
* i40e_fill_default_direct_cmd_desc - AQ descriptor helper function
* @desc: pointer to the temp descriptor (non DMA mem)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c
index e8031f1a9b4f..370b4bddee44 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_common.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_common.c
@@ -1805,37 +1805,6 @@ int i40e_aq_set_vsi_broadcast(struct i40e_hw *hw,
}
/**
- * i40e_aq_set_vsi_vlan_promisc - control the VLAN promiscuous setting
- * @hw: pointer to the hw struct
- * @seid: vsi number
- * @enable: set MAC L2 layer unicast promiscuous enable/disable for a given VLAN
- * @cmd_details: pointer to command details structure or NULL
- **/
-int i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw,
- u16 seid, bool enable,
- struct i40e_asq_cmd_details *cmd_details)
-{
- struct i40e_aq_desc desc;
- struct i40e_aqc_set_vsi_promiscuous_modes *cmd =
- (struct i40e_aqc_set_vsi_promiscuous_modes *)&desc.params.raw;
- u16 flags = 0;
- int status;
-
- i40e_fill_default_direct_cmd_desc(&desc,
- i40e_aqc_opc_set_vsi_promiscuous_modes);
- if (enable)
- flags |= I40E_AQC_SET_VSI_PROMISC_VLAN;
-
- cmd->promiscuous_flags = cpu_to_le16(flags);
- cmd->valid_flags = cpu_to_le16(I40E_AQC_SET_VSI_PROMISC_VLAN);
- cmd->seid = cpu_to_le16(seid);
-
- status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
-
- return status;
-}
-
-/**
* i40e_aq_get_vsi_params - get VSI configuration info
* @hw: pointer to the hw struct
* @vsi_ctx: pointer to a vsi context struct
@@ -2436,136 +2405,6 @@ i40e_aq_remove_macvlan_v2(struct i40e_hw *hw, u16 seid,
}
/**
- * i40e_mirrorrule_op - Internal helper function to add/delete mirror rule
- * @hw: pointer to the hw struct
- * @opcode: AQ opcode for add or delete mirror rule
- * @sw_seid: Switch SEID (to which rule refers)
- * @rule_type: Rule Type (ingress/egress/VLAN)
- * @id: Destination VSI SEID or Rule ID
- * @count: length of the list
- * @mr_list: list of mirrored VSI SEIDs or VLAN IDs
- * @cmd_details: pointer to command details structure or NULL
- * @rule_id: Rule ID returned from FW
- * @rules_used: Number of rules used in internal switch
- * @rules_free: Number of rules free in internal switch
- *
- * Add/Delete a mirror rule to a specific switch. Mirror rules are supported for
- * VEBs/VEPA elements only
- **/
-static int i40e_mirrorrule_op(struct i40e_hw *hw,
- u16 opcode, u16 sw_seid, u16 rule_type, u16 id,
- u16 count, __le16 *mr_list,
- struct i40e_asq_cmd_details *cmd_details,
- u16 *rule_id, u16 *rules_used, u16 *rules_free)
-{
- struct i40e_aq_desc desc;
- struct i40e_aqc_add_delete_mirror_rule *cmd =
- (struct i40e_aqc_add_delete_mirror_rule *)&desc.params.raw;
- struct i40e_aqc_add_delete_mirror_rule_completion *resp =
- (struct i40e_aqc_add_delete_mirror_rule_completion *)&desc.params.raw;
- u16 buf_size;
- int status;
-
- buf_size = count * sizeof(*mr_list);
-
- /* prep the rest of the request */
- i40e_fill_default_direct_cmd_desc(&desc, opcode);
- cmd->seid = cpu_to_le16(sw_seid);
- cmd->rule_type = cpu_to_le16(rule_type &
- I40E_AQC_MIRROR_RULE_TYPE_MASK);
- cmd->num_entries = cpu_to_le16(count);
- /* Dest VSI for add, rule_id for delete */
- cmd->destination = cpu_to_le16(id);
- if (mr_list) {
- desc.flags |= cpu_to_le16((u16)(I40E_AQ_FLAG_BUF |
- I40E_AQ_FLAG_RD));
- if (buf_size > I40E_AQ_LARGE_BUF)
- desc.flags |= cpu_to_le16((u16)I40E_AQ_FLAG_LB);
- }
-
- status = i40e_asq_send_command(hw, &desc, mr_list, buf_size,
- cmd_details);
- if (!status ||
- hw->aq.asq_last_status == I40E_AQ_RC_ENOSPC) {
- if (rule_id)
- *rule_id = le16_to_cpu(resp->rule_id);
- if (rules_used)
- *rules_used = le16_to_cpu(resp->mirror_rules_used);
- if (rules_free)
- *rules_free = le16_to_cpu(resp->mirror_rules_free);
- }
- return status;
-}
-
-/**
- * i40e_aq_add_mirrorrule - add a mirror rule
- * @hw: pointer to the hw struct
- * @sw_seid: Switch SEID (to which rule refers)
- * @rule_type: Rule Type (ingress/egress/VLAN)
- * @dest_vsi: SEID of VSI to which packets will be mirrored
- * @count: length of the list
- * @mr_list: list of mirrored VSI SEIDs or VLAN IDs
- * @cmd_details: pointer to command details structure or NULL
- * @rule_id: Rule ID returned from FW
- * @rules_used: Number of rules used in internal switch
- * @rules_free: Number of rules free in internal switch
- *
- * Add mirror rule. Mirror rules are supported for VEBs or VEPA elements only
- **/
-int i40e_aq_add_mirrorrule(struct i40e_hw *hw, u16 sw_seid,
- u16 rule_type, u16 dest_vsi, u16 count,
- __le16 *mr_list,
- struct i40e_asq_cmd_details *cmd_details,
- u16 *rule_id, u16 *rules_used, u16 *rules_free)
-{
- if (!(rule_type == I40E_AQC_MIRROR_RULE_TYPE_ALL_INGRESS ||
- rule_type == I40E_AQC_MIRROR_RULE_TYPE_ALL_EGRESS)) {
- if (count == 0 || !mr_list)
- return -EINVAL;
- }
-
- return i40e_mirrorrule_op(hw, i40e_aqc_opc_add_mirror_rule, sw_seid,
- rule_type, dest_vsi, count, mr_list,
- cmd_details, rule_id, rules_used, rules_free);
-}
-
-/**
- * i40e_aq_delete_mirrorrule - delete a mirror rule
- * @hw: pointer to the hw struct
- * @sw_seid: Switch SEID (to which rule refers)
- * @rule_type: Rule Type (ingress/egress/VLAN)
- * @count: length of the list
- * @rule_id: Rule ID that is returned in the receive desc as part of
- * add_mirrorrule.
- * @mr_list: list of mirrored VLAN IDs to be removed
- * @cmd_details: pointer to command details structure or NULL
- * @rules_used: Number of rules used in internal switch
- * @rules_free: Number of rules free in internal switch
- *
- * Delete a mirror rule. Mirror rules are supported for VEBs/VEPA elements only
- **/
-int i40e_aq_delete_mirrorrule(struct i40e_hw *hw, u16 sw_seid,
- u16 rule_type, u16 rule_id, u16 count,
- __le16 *mr_list,
- struct i40e_asq_cmd_details *cmd_details,
- u16 *rules_used, u16 *rules_free)
-{
- /* Rule ID has to be valid except rule_type: INGRESS VLAN mirroring */
- if (rule_type == I40E_AQC_MIRROR_RULE_TYPE_VLAN) {
- /* count and mr_list shall be valid for rule_type INGRESS VLAN
- * mirroring. For other rule_type, count and rule_type should
- * not matter.
- */
- if (count == 0 || !mr_list)
- return -EINVAL;
- }
-
- return i40e_mirrorrule_op(hw, i40e_aqc_opc_delete_mirror_rule, sw_seid,
- rule_type, rule_id, count, mr_list,
- cmd_details, NULL, rules_used, rules_free);
-}
-
-/**
* i40e_aq_send_msg_to_vf
* @hw: pointer to the hardware structure
* @vfid: VF id to send msg
@@ -3180,41 +3019,6 @@ i40e_aq_update_nvm_exit:
}
/**
- * i40e_aq_rearrange_nvm
- * @hw: pointer to the hw struct
- * @rearrange_nvm: defines direction of rearrangement
- * @cmd_details: pointer to command details structure or NULL
- *
- * Rearrange NVM structure, available only for transition FW
- **/
-int i40e_aq_rearrange_nvm(struct i40e_hw *hw,
- u8 rearrange_nvm,
- struct i40e_asq_cmd_details *cmd_details)
-{
- struct i40e_aqc_nvm_update *cmd;
- struct i40e_aq_desc desc;
- int status;
-
- cmd = (struct i40e_aqc_nvm_update *)&desc.params.raw;
-
- i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_nvm_update);
-
- rearrange_nvm &= (I40E_AQ_NVM_REARRANGE_TO_FLAT |
- I40E_AQ_NVM_REARRANGE_TO_STRUCT);
-
- if (!rearrange_nvm) {
- status = -EINVAL;
- goto i40e_aq_rearrange_nvm_exit;
- }
-
- cmd->command_flags |= rearrange_nvm;
- status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
-
-i40e_aq_rearrange_nvm_exit:
- return status;
-}
-
-/**
* i40e_aq_get_lldp_mib
* @hw: pointer to the hw struct
* @bridge_type: type of bridge requested
@@ -3335,44 +3139,6 @@ int i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw,
}
/**
- * i40e_aq_restore_lldp
- * @hw: pointer to the hw struct
- * @setting: pointer to factory setting variable or NULL
- * @restore: True if factory settings should be restored
- * @cmd_details: pointer to command details structure or NULL
- *
- * Restore LLDP Agent factory settings if @restore set to True. In other case
- * only returns factory setting in AQ response.
- **/
-int
-i40e_aq_restore_lldp(struct i40e_hw *hw, u8 *setting, bool restore,
- struct i40e_asq_cmd_details *cmd_details)
-{
- struct i40e_aq_desc desc;
- struct i40e_aqc_lldp_restore *cmd =
- (struct i40e_aqc_lldp_restore *)&desc.params.raw;
- int status;
-
- if (!test_bit(I40E_HW_CAP_FW_LLDP_PERSISTENT, hw->caps)) {
- i40e_debug(hw, I40E_DEBUG_ALL,
- "Restore LLDP not supported by current FW version.\n");
- return -ENODEV;
- }
-
- i40e_fill_default_direct_cmd_desc(&desc, i40e_aqc_opc_lldp_restore);
-
- if (restore)
- cmd->command |= I40E_AQ_LLDP_AGENT_RESTORE;
-
- status = i40e_asq_send_command(hw, &desc, NULL, 0, cmd_details);
-
- if (setting)
- *setting = cmd->command & 1;
-
- return status;
-}
-
-/**
* i40e_aq_stop_lldp
* @hw: pointer to the hw struct
* @shutdown_agent: True if LLDP Agent needs to be Shutdown
@@ -4570,84 +4336,6 @@ phy_write_end:
}
/**
- * i40e_write_phy_register
- * @hw: pointer to the HW structure
- * @page: registers page number
- * @reg: register address in the page
- * @phy_addr: PHY address on MDIO interface
- * @value: PHY register value
- *
- * Writes value to specified PHY register
- **/
-int i40e_write_phy_register(struct i40e_hw *hw,
- u8 page, u16 reg, u8 phy_addr, u16 value)
-{
- int status;
-
- switch (hw->device_id) {
- case I40E_DEV_ID_1G_BASE_T_X722:
- status = i40e_write_phy_register_clause22(hw, reg, phy_addr,
- value);
- break;
- case I40E_DEV_ID_1G_BASE_T_BC:
- case I40E_DEV_ID_5G_BASE_T_BC:
- case I40E_DEV_ID_10G_BASE_T:
- case I40E_DEV_ID_10G_BASE_T4:
- case I40E_DEV_ID_10G_BASE_T_BC:
- case I40E_DEV_ID_10G_BASE_T_X722:
- case I40E_DEV_ID_25G_B:
- case I40E_DEV_ID_25G_SFP28:
- status = i40e_write_phy_register_clause45(hw, page, reg,
- phy_addr, value);
- break;
- default:
- status = -EIO;
- break;
- }
-
- return status;
-}
-
-/**
- * i40e_read_phy_register
- * @hw: pointer to the HW structure
- * @page: registers page number
- * @reg: register address in the page
- * @phy_addr: PHY address on MDIO interface
- * @value: PHY register value
- *
- * Reads specified PHY register value
- **/
-int i40e_read_phy_register(struct i40e_hw *hw,
- u8 page, u16 reg, u8 phy_addr, u16 *value)
-{
- int status;
-
- switch (hw->device_id) {
- case I40E_DEV_ID_1G_BASE_T_X722:
- status = i40e_read_phy_register_clause22(hw, reg, phy_addr,
- value);
- break;
- case I40E_DEV_ID_1G_BASE_T_BC:
- case I40E_DEV_ID_5G_BASE_T_BC:
- case I40E_DEV_ID_10G_BASE_T:
- case I40E_DEV_ID_10G_BASE_T4:
- case I40E_DEV_ID_10G_BASE_T_BC:
- case I40E_DEV_ID_10G_BASE_T_X722:
- case I40E_DEV_ID_25G_B:
- case I40E_DEV_ID_25G_SFP28:
- status = i40e_read_phy_register_clause45(hw, page, reg,
- phy_addr, value);
- break;
- default:
- status = -EIO;
- break;
- }
-
- return status;
-}
-
-/**
* i40e_get_phy_address
* @hw: pointer to the HW structure
* @dev_num: PHY port num that address we want
@@ -4663,80 +4351,6 @@ u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num)
}
/**
- * i40e_blink_phy_link_led
- * @hw: pointer to the HW structure
- * @time: time how long led will blinks in secs
- * @interval: gap between LED on and off in msecs
- *
- * Blinks PHY link LED
- **/
-int i40e_blink_phy_link_led(struct i40e_hw *hw,
- u32 time, u32 interval)
-{
- u16 led_addr = I40E_PHY_LED_PROV_REG_1;
- u16 gpio_led_port;
- u8 phy_addr = 0;
- int status = 0;
- u16 led_ctl;
- u8 port_num;
- u16 led_reg;
- u32 i;
-
- i = rd32(hw, I40E_PFGEN_PORTNUM);
- port_num = (u8)(i & I40E_PFGEN_PORTNUM_PORT_NUM_MASK);
- phy_addr = i40e_get_phy_address(hw, port_num);
-
- for (gpio_led_port = 0; gpio_led_port < 3; gpio_led_port++,
- led_addr++) {
- status = i40e_read_phy_register_clause45(hw,
- I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr,
- &led_reg);
- if (status)
- goto phy_blinking_end;
- led_ctl = led_reg;
- if (led_reg & I40E_PHY_LED_LINK_MODE_MASK) {
- led_reg = 0;
- status = i40e_write_phy_register_clause45(hw,
- I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr,
- led_reg);
- if (status)
- goto phy_blinking_end;
- break;
- }
- }
-
- if (time > 0 && interval > 0) {
- for (i = 0; i < time * 1000; i += interval) {
- status = i40e_read_phy_register_clause45(hw,
- I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, &led_reg);
- if (status)
- goto restore_config;
- if (led_reg & I40E_PHY_LED_MANUAL_ON)
- led_reg = 0;
- else
- led_reg = I40E_PHY_LED_MANUAL_ON;
- status = i40e_write_phy_register_clause45(hw,
- I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, led_reg);
- if (status)
- goto restore_config;
- msleep(interval);
- }
- }
-
-restore_config:
- status = i40e_write_phy_register_clause45(hw,
- I40E_PHY_COM_REG_PAGE,
- led_addr, phy_addr, led_ctl);
-
-phy_blinking_end:
- return status;
-}
-
-/**
* i40e_led_get_reg - read LED register
* @hw: pointer to the HW structure
* @led_addr: LED register address
@@ -5269,39 +4883,6 @@ i40e_find_segment_in_package(u32 segment_type,
(struct i40e_profile_section_header *)((u8 *)(profile) + (offset))
/**
- * i40e_find_section_in_profile
- * @section_type: the section type to search for (i.e., SECTION_TYPE_NOTE)
- * @profile: pointer to the i40e segment header to be searched
- *
- * This function searches i40e segment for a particular section type. On
- * success it returns a pointer to the section header, otherwise it will
- * return NULL.
- **/
-struct i40e_profile_section_header *
-i40e_find_section_in_profile(u32 section_type,
- struct i40e_profile_segment *profile)
-{
- struct i40e_profile_section_header *sec;
- struct i40e_section_table *sec_tbl;
- u32 sec_off;
- u32 i;
-
- if (profile->header.type != SEGMENT_TYPE_I40E)
- return NULL;
-
- I40E_SECTION_TABLE(profile, sec_tbl);
-
- for (i = 0; i < sec_tbl->section_count; i++) {
- sec_off = sec_tbl->section_offset[i];
- sec = I40E_SECTION_HEADER(profile, sec_off);
- if (sec->section.type == section_type)
- return sec;
- }
-
- return NULL;
-}
-
-/**
* i40e_ddp_exec_aq_section - Execute generic AQ for DDP
* @hw: pointer to the hw struct
* @aq: command buffer containing all data to execute AQ
@@ -5524,45 +5105,6 @@ i40e_rollback_profile(struct i40e_hw *hw, struct i40e_profile_segment *profile,
}
/**
- * i40e_add_pinfo_to_list
- * @hw: pointer to the hardware structure
- * @profile: pointer to the profile segment of the package
- * @profile_info_sec: buffer for information section
- * @track_id: package tracking id
- *
- * Register a profile to the list of loaded profiles.
- */
-int
-i40e_add_pinfo_to_list(struct i40e_hw *hw,
- struct i40e_profile_segment *profile,
- u8 *profile_info_sec, u32 track_id)
-{
- struct i40e_profile_section_header *sec = NULL;
- struct i40e_profile_info *pinfo;
- u32 offset = 0, info = 0;
- int status = 0;
-
- sec = (struct i40e_profile_section_header *)profile_info_sec;
- sec->tbl_size = 1;
- sec->data_end = sizeof(struct i40e_profile_section_header) +
- sizeof(struct i40e_profile_info);
- sec->section.type = SECTION_TYPE_INFO;
- sec->section.offset = sizeof(struct i40e_profile_section_header);
- sec->section.size = sizeof(struct i40e_profile_info);
- pinfo = (struct i40e_profile_info *)(profile_info_sec +
- sec->section.offset);
- pinfo->track_id = track_id;
- pinfo->version = profile->version;
- pinfo->op = I40E_DDP_ADD_TRACKID;
- memcpy(pinfo->name, profile->name, I40E_DDP_NAME_SIZE);
-
- status = i40e_aq_write_ddp(hw, (void *)sec, sec->data_end,
- track_id, &offset, &info, NULL);
-
- return status;
-}
-
-/**
* i40e_aq_add_cloud_filters
* @hw: pointer to the hardware structure
* @seid: VSI seid to add cloud filters from
diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.c b/drivers/net/ethernet/intel/i40e/i40e_dcb.c
index 8db1eb0c1768..352e957443fd 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_dcb.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.c
@@ -1491,19 +1491,6 @@ void i40e_dcb_hw_set_num_tc(struct i40e_hw *hw, u8 num_tc)
}
/**
- * i40e_dcb_hw_get_num_tc
- * @hw: pointer to the hw struct
- *
- * Returns number of traffic classes configured in HW
- **/
-u8 i40e_dcb_hw_get_num_tc(struct i40e_hw *hw)
-{
- u32 reg = rd32(hw, I40E_PRTDCB_GENC);
-
- return FIELD_GET(I40E_PRTDCB_GENC_NUMTC_MASK, reg);
-}
-
-/**
* i40e_dcb_hw_rx_ets_bw_config
* @hw: pointer to the hw struct
* @bw_share: Bandwidth share indexed per traffic class
diff --git a/drivers/net/ethernet/intel/i40e/i40e_dcb.h b/drivers/net/ethernet/intel/i40e/i40e_dcb.h
index d76497566e40..d5662c639c41 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_dcb.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_dcb.h
@@ -253,7 +253,6 @@ void i40e_dcb_hw_rx_cmd_monitor_config(struct i40e_hw *hw,
void i40e_dcb_hw_pfc_config(struct i40e_hw *hw,
u8 pfc_en, u8 *prio_tc);
void i40e_dcb_hw_set_num_tc(struct i40e_hw *hw, u8 num_tc);
-u8 i40e_dcb_hw_get_num_tc(struct i40e_hw *hw);
void i40e_dcb_hw_rx_ets_bw_config(struct i40e_hw *hw, u8 *bw_share,
u8 *mode, u8 *prio_type);
void i40e_dcb_hw_rx_up2tc_config(struct i40e_hw *hw, u8 *prio_tc);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
index 208c2f0857b6..6cd9da662ae1 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c
@@ -722,7 +722,7 @@ static void i40e_dbg_dump_vf(struct i40e_pf *pf, int vf_id)
dev_info(&pf->pdev->dev, "vf %2d: VSI id=%d, seid=%d, qps=%d\n",
vf_id, vf->lan_vsi_id, vsi->seid, vf->num_queue_pairs);
dev_info(&pf->pdev->dev, " num MDD=%lld\n",
- vf->num_mdd_events);
+ vf->mdd_tx_events.count + vf->mdd_rx_events.count);
} else {
dev_info(&pf->pdev->dev, "invalid VF id %d\n", vf_id);
}
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
index bce5b76f1e7a..8a7a83f83ee5 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c
@@ -459,6 +459,8 @@ static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = {
I40E_PRIV_FLAG("base-r-fec", I40E_FLAG_BASE_R_FEC, 0),
I40E_PRIV_FLAG("vf-vlan-pruning",
I40E_FLAG_VF_VLAN_PRUNING_ENA, 0),
+ I40E_PRIV_FLAG("mdd-auto-reset-vf",
+ I40E_FLAG_MDD_AUTO_RESET_VF, 0),
};
#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gstrings_priv_flags)
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index ab5febf83ec3..65a702668e21 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -99,7 +99,7 @@ module_param(debug, uint, 0);
MODULE_PARM_DESC(debug, "Debug level (0=none,...,16=all), Debug mask (0x8XXXXXXX)");
MODULE_DESCRIPTION("Intel(R) Ethernet Connection XL710 Network Driver");
-MODULE_IMPORT_NS(LIBIE);
+MODULE_IMPORT_NS("LIBIE");
MODULE_LICENSE("GPL v2");
static struct workqueue_struct *i40e_wq;
@@ -1666,9 +1666,8 @@ struct i40e_mac_filter *i40e_add_filter(struct i40e_vsi *vsi,
* @vsi: VSI to remove from
* @f: the filter to remove from the list
*
- * This function should be called instead of i40e_del_filter only if you know
- * the exact filter you will remove already, such as via i40e_find_filter or
- * i40e_find_mac.
+ * This function requires you've found * the exact filter you will remove
+ * already, such as via i40e_find_filter or i40e_find_mac.
*
* NOTE: This function is expected to be called with mac_filter_hash_lock
* being held.
@@ -1698,29 +1697,6 @@ void __i40e_del_filter(struct i40e_vsi *vsi, struct i40e_mac_filter *f)
}
/**
- * i40e_del_filter - Remove a MAC/VLAN filter from the VSI
- * @vsi: the VSI to be searched
- * @macaddr: the MAC address
- * @vlan: the VLAN
- *
- * NOTE: This function is expected to be called with mac_filter_hash_lock
- * being held.
- * ANOTHER NOTE: This function MUST be called from within the context of
- * the "safe" variants of any list iterators, e.g. list_for_each_entry_safe()
- * instead of list_for_each_entry().
- **/
-void i40e_del_filter(struct i40e_vsi *vsi, const u8 *macaddr, s16 vlan)
-{
- struct i40e_mac_filter *f;
-
- if (!vsi || !macaddr)
- return;
-
- f = i40e_find_filter(vsi, macaddr, vlan);
- __i40e_del_filter(vsi, f);
-}
-
-/**
* i40e_add_mac_filter - Add a MAC filter for all active VLANs
* @vsi: the VSI to be searched
* @macaddr: the mac address to be filtered
@@ -9629,19 +9605,6 @@ static void i40e_handle_lan_overflow_event(struct i40e_pf *pf,
}
/**
- * i40e_get_cur_guaranteed_fd_count - Get the consumed guaranteed FD filters
- * @pf: board private structure
- **/
-u32 i40e_get_cur_guaranteed_fd_count(struct i40e_pf *pf)
-{
- u32 val, fcnt_prog;
-
- val = rd32(&pf->hw, I40E_PFQF_FDSTAT);
- fcnt_prog = (val & I40E_PFQF_FDSTAT_GUARANT_CNT_MASK);
- return fcnt_prog;
-}
-
-/**
* i40e_get_current_fd_count - Get total FD filters programmed for this PF
* @pf: board private structure
**/
@@ -11217,6 +11180,67 @@ static void i40e_handle_reset_warning(struct i40e_pf *pf, bool lock_acquired)
}
/**
+ * i40e_print_vf_mdd_event - print VF Tx/Rx malicious driver detect event
+ * @pf: board private structure
+ * @vf: pointer to the VF structure
+ * @is_tx: true - for Tx event, false - for Rx
+ */
+static void i40e_print_vf_mdd_event(struct i40e_pf *pf, struct i40e_vf *vf,
+ bool is_tx)
+{
+ dev_err(&pf->pdev->dev, is_tx ?
+ "%lld Tx Malicious Driver Detection events detected on PF %d VF %d MAC %pm. mdd-auto-reset-vfs=%s\n" :
+ "%lld Rx Malicious Driver Detection events detected on PF %d VF %d MAC %pm. mdd-auto-reset-vfs=%s\n",
+ is_tx ? vf->mdd_tx_events.count : vf->mdd_rx_events.count,
+ pf->hw.pf_id,
+ vf->vf_id,
+ vf->default_lan_addr.addr,
+ str_on_off(test_bit(I40E_FLAG_MDD_AUTO_RESET_VF, pf->flags)));
+}
+
+/**
+ * i40e_print_vfs_mdd_events - print VFs malicious driver detect event
+ * @pf: pointer to the PF structure
+ *
+ * Called from i40e_handle_mdd_event to rate limit and print VFs MDD events.
+ */
+static void i40e_print_vfs_mdd_events(struct i40e_pf *pf)
+{
+ unsigned int i;
+
+ /* check that there are pending MDD events to print */
+ if (!test_and_clear_bit(__I40E_MDD_VF_PRINT_PENDING, pf->state))
+ return;
+
+ if (!__ratelimit(&pf->mdd_message_rate_limit))
+ return;
+
+ for (i = 0; i < pf->num_alloc_vfs; i++) {
+ struct i40e_vf *vf = &pf->vf[i];
+ bool is_printed = false;
+
+ /* only print Rx MDD event message if there are new events */
+ if (vf->mdd_rx_events.count != vf->mdd_rx_events.last_printed) {
+ vf->mdd_rx_events.last_printed = vf->mdd_rx_events.count;
+ i40e_print_vf_mdd_event(pf, vf, false);
+ is_printed = true;
+ }
+
+ /* only print Tx MDD event message if there are new events */
+ if (vf->mdd_tx_events.count != vf->mdd_tx_events.last_printed) {
+ vf->mdd_tx_events.last_printed = vf->mdd_tx_events.count;
+ i40e_print_vf_mdd_event(pf, vf, true);
+ is_printed = true;
+ }
+
+ if (is_printed && !test_bit(I40E_FLAG_MDD_AUTO_RESET_VF, pf->flags))
+ dev_info(&pf->pdev->dev,
+ "Use PF Control I/F to re-enable the VF #%d\n",
+ i);
+ }
+}
+
+/**
* i40e_handle_mdd_event
* @pf: pointer to the PF structure
*
@@ -11230,8 +11254,13 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
u32 reg;
int i;
- if (!test_bit(__I40E_MDD_EVENT_PENDING, pf->state))
+ if (!test_and_clear_bit(__I40E_MDD_EVENT_PENDING, pf->state)) {
+ /* Since the VF MDD event logging is rate limited, check if
+ * there are pending MDD events.
+ */
+ i40e_print_vfs_mdd_events(pf);
return;
+ }
/* find what triggered the MDD event */
reg = rd32(hw, I40E_GL_MDET_TX);
@@ -11275,36 +11304,48 @@ static void i40e_handle_mdd_event(struct i40e_pf *pf)
/* see if one of the VFs needs its hand slapped */
for (i = 0; i < pf->num_alloc_vfs && mdd_detected; i++) {
+ bool is_mdd_on_tx = false;
+ bool is_mdd_on_rx = false;
+
vf = &(pf->vf[i]);
reg = rd32(hw, I40E_VP_MDET_TX(i));
if (reg & I40E_VP_MDET_TX_VALID_MASK) {
+ set_bit(__I40E_MDD_VF_PRINT_PENDING, pf->state);
wr32(hw, I40E_VP_MDET_TX(i), 0xFFFF);
- vf->num_mdd_events++;
- dev_info(&pf->pdev->dev, "TX driver issue detected on VF %d\n",
- i);
- dev_info(&pf->pdev->dev,
- "Use PF Control I/F to re-enable the VF\n");
+ vf->mdd_tx_events.count++;
set_bit(I40E_VF_STATE_DISABLED, &vf->vf_states);
+ is_mdd_on_tx = true;
}
reg = rd32(hw, I40E_VP_MDET_RX(i));
if (reg & I40E_VP_MDET_RX_VALID_MASK) {
+ set_bit(__I40E_MDD_VF_PRINT_PENDING, pf->state);
wr32(hw, I40E_VP_MDET_RX(i), 0xFFFF);
- vf->num_mdd_events++;
- dev_info(&pf->pdev->dev, "RX driver issue detected on VF %d\n",
- i);
- dev_info(&pf->pdev->dev,
- "Use PF Control I/F to re-enable the VF\n");
+ vf->mdd_rx_events.count++;
set_bit(I40E_VF_STATE_DISABLED, &vf->vf_states);
+ is_mdd_on_rx = true;
+ }
+
+ if ((is_mdd_on_tx || is_mdd_on_rx) &&
+ test_bit(I40E_FLAG_MDD_AUTO_RESET_VF, pf->flags)) {
+ /* VF MDD event counters will be cleared by
+ * reset, so print the event prior to reset.
+ */
+ if (is_mdd_on_rx)
+ i40e_print_vf_mdd_event(pf, vf, false);
+ if (is_mdd_on_tx)
+ i40e_print_vf_mdd_event(pf, vf, true);
+
+ i40e_vc_reset_vf(vf, true);
}
}
- /* re-enable mdd interrupt cause */
- clear_bit(__I40E_MDD_EVENT_PENDING, pf->state);
reg = rd32(hw, I40E_PFINT_ICR0_ENA);
reg |= I40E_PFINT_ICR0_ENA_MAL_DETECT_MASK;
wr32(hw, I40E_PFINT_ICR0_ENA, reg);
i40e_flush(hw);
+
+ i40e_print_vfs_mdd_events(pf);
}
/**
@@ -12614,89 +12655,6 @@ int i40e_set_partition_bw_setting(struct i40e_pf *pf)
}
/**
- * i40e_commit_partition_bw_setting - Commit BW settings for this PF partition
- * @pf: board private structure
- **/
-int i40e_commit_partition_bw_setting(struct i40e_pf *pf)
-{
- /* Commit temporary BW setting to permanent NVM image */
- enum i40e_admin_queue_err last_aq_status;
- u16 nvm_word;
- int ret;
-
- if (pf->hw.partition_id != 1) {
- dev_info(&pf->pdev->dev,
- "Commit BW only works on partition 1! This is partition %d",
- pf->hw.partition_id);
- ret = -EOPNOTSUPP;
- goto bw_commit_out;
- }
-
- /* Acquire NVM for read access */
- ret = i40e_acquire_nvm(&pf->hw, I40E_RESOURCE_READ);
- last_aq_status = pf->hw.aq.asq_last_status;
- if (ret) {
- dev_info(&pf->pdev->dev,
- "Cannot acquire NVM for read access, err %pe aq_err %s\n",
- ERR_PTR(ret),
- i40e_aq_str(&pf->hw, last_aq_status));
- goto bw_commit_out;
- }
-
- /* Read word 0x10 of NVM - SW compatibility word 1 */
- ret = i40e_aq_read_nvm(&pf->hw,
- I40E_SR_NVM_CONTROL_WORD,
- 0x10, sizeof(nvm_word), &nvm_word,
- false, NULL);
- /* Save off last admin queue command status before releasing
- * the NVM
- */
- last_aq_status = pf->hw.aq.asq_last_status;
- i40e_release_nvm(&pf->hw);
- if (ret) {
- dev_info(&pf->pdev->dev, "NVM read error, err %pe aq_err %s\n",
- ERR_PTR(ret),
- i40e_aq_str(&pf->hw, last_aq_status));
- goto bw_commit_out;
- }
-
- /* Wait a bit for NVM release to complete */
- msleep(50);
-
- /* Acquire NVM for write access */
- ret = i40e_acquire_nvm(&pf->hw, I40E_RESOURCE_WRITE);
- last_aq_status = pf->hw.aq.asq_last_status;
- if (ret) {
- dev_info(&pf->pdev->dev,
- "Cannot acquire NVM for write access, err %pe aq_err %s\n",
- ERR_PTR(ret),
- i40e_aq_str(&pf->hw, last_aq_status));
- goto bw_commit_out;
- }
- /* Write it back out unchanged to initiate update NVM,
- * which will force a write of the shadow (alt) RAM to
- * the NVM - thus storing the bandwidth values permanently.
- */
- ret = i40e_aq_update_nvm(&pf->hw,
- I40E_SR_NVM_CONTROL_WORD,
- 0x10, sizeof(nvm_word),
- &nvm_word, true, 0, NULL);
- /* Save off last admin queue command status before releasing
- * the NVM
- */
- last_aq_status = pf->hw.aq.asq_last_status;
- i40e_release_nvm(&pf->hw);
- if (ret)
- dev_info(&pf->pdev->dev,
- "BW settings NOT SAVED, err %pe aq_err %s\n",
- ERR_PTR(ret),
- i40e_aq_str(&pf->hw, last_aq_status));
-bw_commit_out:
-
- return ret;
-}
-
-/**
* i40e_is_total_port_shutdown_enabled - read NVM and return value
* if total port shutdown feature is enabled for this PF
* @pf: board private structure
@@ -15998,6 +15956,9 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
ERR_PTR(err),
i40e_aq_str(&pf->hw, pf->hw.aq.asq_last_status));
+ /* VF MDD event logs are rate limited to one second intervals */
+ ratelimit_state_init(&pf->mdd_message_rate_limit, 1 * HZ, 1);
+
/* Reconfigure hardware for allowing smaller MSS in the case
* of TSO, so that we avoid the MDD being fired and causing
* a reset in the case of small MSS+TSO.
diff --git a/drivers/net/ethernet/intel/i40e/i40e_prototype.h b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
index 5a0699ca7ce5..099bb8ab7d70 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_prototype.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_prototype.h
@@ -27,13 +27,6 @@ i40e_asq_send_command(struct i40e_hw *hw, struct i40e_aq_desc *desc,
void *buff, /* can be NULL */ u16 buff_size,
struct i40e_asq_cmd_details *cmd_details);
int
-i40e_asq_send_command_v2(struct i40e_hw *hw,
- struct i40e_aq_desc *desc,
- void *buff, /* can be NULL */
- u16 buff_size,
- struct i40e_asq_cmd_details *cmd_details,
- enum i40e_admin_queue_err *aq_status);
-int
i40e_asq_send_command_atomic(struct i40e_hw *hw, struct i40e_aq_desc *desc,
void *buff, /* can be NULL */ u16 buff_size,
struct i40e_asq_cmd_details *cmd_details,
@@ -72,8 +65,6 @@ int i40e_led_set_phy(struct i40e_hw *hw, bool on,
u16 led_addr, u32 mode);
int i40e_led_get_phy(struct i40e_hw *hw, u16 *led_addr,
u16 *val);
-int i40e_blink_phy_link_led(struct i40e_hw *hw,
- u32 time, u32 interval);
/* admin send queue commands */
@@ -141,9 +132,6 @@ int i40e_aq_set_vsi_uc_promisc_on_vlan(struct i40e_hw *hw,
int i40e_aq_set_vsi_bc_promisc_on_vlan(struct i40e_hw *hw,
u16 seid, bool enable, u16 vid,
struct i40e_asq_cmd_details *cmd_details);
-int i40e_aq_set_vsi_vlan_promisc(struct i40e_hw *hw,
- u16 seid, bool enable,
- struct i40e_asq_cmd_details *cmd_details);
int i40e_aq_get_vsi_params(struct i40e_hw *hw,
struct i40e_vsi_context *vsi_ctx,
struct i40e_asq_cmd_details *cmd_details);
@@ -176,14 +164,6 @@ i40e_aq_remove_macvlan_v2(struct i40e_hw *hw, u16 seid,
struct i40e_aqc_remove_macvlan_element_data *mv_list,
u16 count, struct i40e_asq_cmd_details *cmd_details,
enum i40e_admin_queue_err *aq_status);
-int i40e_aq_add_mirrorrule(struct i40e_hw *hw, u16 sw_seid,
- u16 rule_type, u16 dest_vsi, u16 count, __le16 *mr_list,
- struct i40e_asq_cmd_details *cmd_details,
- u16 *rule_id, u16 *rules_used, u16 *rules_free);
-int i40e_aq_delete_mirrorrule(struct i40e_hw *hw, u16 sw_seid,
- u16 rule_type, u16 rule_id, u16 count, __le16 *mr_list,
- struct i40e_asq_cmd_details *cmd_details,
- u16 *rules_used, u16 *rules_free);
int i40e_aq_send_msg_to_vf(struct i40e_hw *hw, u16 vfid,
u32 v_opcode, u32 v_retval, u8 *msg, u16 msglen,
@@ -220,9 +200,6 @@ int i40e_aq_update_nvm(struct i40e_hw *hw, u8 module_pointer,
u32 offset, u16 length, void *data,
bool last_command, u8 preservation_flags,
struct i40e_asq_cmd_details *cmd_details);
-int i40e_aq_rearrange_nvm(struct i40e_hw *hw,
- u8 rearrange_nvm,
- struct i40e_asq_cmd_details *cmd_details);
int i40e_aq_get_lldp_mib(struct i40e_hw *hw, u8 bridge_type,
u8 mib_type, void *buff, u16 buff_size,
u16 *local_len, u16 *remote_len,
@@ -234,9 +211,6 @@ i40e_aq_set_lldp_mib(struct i40e_hw *hw,
int i40e_aq_cfg_lldp_mib_change_event(struct i40e_hw *hw,
bool enable_update,
struct i40e_asq_cmd_details *cmd_details);
-int
-i40e_aq_restore_lldp(struct i40e_hw *hw, u8 *setting, bool restore,
- struct i40e_asq_cmd_details *cmd_details);
int i40e_aq_stop_lldp(struct i40e_hw *hw, bool shutdown_agent,
bool persist,
struct i40e_asq_cmd_details *cmd_details);
@@ -458,13 +432,7 @@ int i40e_read_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u16 *value);
int i40e_write_phy_register_clause45(struct i40e_hw *hw,
u8 page, u16 reg, u8 phy_addr, u16 value);
-int i40e_read_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
- u8 phy_addr, u16 *value);
-int i40e_write_phy_register(struct i40e_hw *hw, u8 page, u16 reg,
- u8 phy_addr, u16 value);
u8 i40e_get_phy_address(struct i40e_hw *hw, u8 dev_num);
-int i40e_blink_phy_link_led(struct i40e_hw *hw,
- u32 time, u32 interval);
int i40e_aq_write_ddp(struct i40e_hw *hw, void *buff,
u16 buff_size, u32 track_id,
u32 *error_offset, u32 *error_info,
@@ -477,20 +445,12 @@ int i40e_aq_get_ddp_list(struct i40e_hw *hw, void *buff,
struct i40e_generic_seg_header *
i40e_find_segment_in_package(u32 segment_type,
struct i40e_package_header *pkg_header);
-struct i40e_profile_section_header *
-i40e_find_section_in_profile(u32 section_type,
- struct i40e_profile_segment *profile);
int
i40e_write_profile(struct i40e_hw *hw, struct i40e_profile_segment *i40e_seg,
u32 track_id);
int
i40e_rollback_profile(struct i40e_hw *hw, struct i40e_profile_segment *i40e_seg,
u32 track_id);
-int
-i40e_add_pinfo_to_list(struct i40e_hw *hw,
- struct i40e_profile_segment *profile,
- u8 *profile_info_sec, u32 track_id);
-
/* i40e_ddp */
int i40e_ddp_flash(struct net_device *netdev, struct ethtool_flash *flash);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
index dfa785e39458..1120f8e4bb67 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c
@@ -216,7 +216,7 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf)
* @notify_vf: notify vf about reset or not
* Reset VF handler.
**/
-static void i40e_vc_reset_vf(struct i40e_vf *vf, bool notify_vf)
+void i40e_vc_reset_vf(struct i40e_vf *vf, bool notify_vf)
{
struct i40e_pf *pf = vf->pf;
int i;
diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
index 66f95e2f3146..5cf74f16f433 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
+++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.h
@@ -64,6 +64,12 @@ struct i40evf_channel {
u64 max_tx_rate; /* bandwidth rate allocation for VSIs */
};
+struct i40e_mdd_vf_events {
+ u64 count; /* total count of Rx|Tx events */
+ /* count number of the last printed event */
+ u64 last_printed;
+};
+
/* VF information structure */
struct i40e_vf {
struct i40e_pf *pf;
@@ -92,7 +98,9 @@ struct i40e_vf {
u8 num_queue_pairs; /* num of qps assigned to VF vsis */
u8 num_req_queues; /* num of requested qps */
- u64 num_mdd_events; /* num of mdd events detected */
+ /* num of mdd tx and rx events detected */
+ struct i40e_mdd_vf_events mdd_rx_events;
+ struct i40e_mdd_vf_events mdd_tx_events;
unsigned long vf_caps; /* vf's adv. capabilities */
unsigned long vf_states; /* vf's runtime states */
@@ -120,6 +128,7 @@ int i40e_alloc_vfs(struct i40e_pf *pf, u16 num_alloc_vfs);
int i40e_vc_process_vf_msg(struct i40e_pf *pf, s16 vf_id, u32 v_opcode,
u32 v_retval, u8 *msg, u16 msglen);
int i40e_vc_process_vflr_event(struct i40e_pf *pf);
+void i40e_vc_reset_vf(struct i40e_vf *vf, bool notify_vf);
bool i40e_reset_vf(struct i40e_vf *vf, bool flr);
bool i40e_reset_all_vfs(struct i40e_pf *pf, bool flr);
void i40e_vc_notify_vf_reset(struct i40e_vf *vf);
diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
index 4e885df789ef..e28f1905a4a0 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c
@@ -395,32 +395,6 @@ static void i40e_handle_xdp_result_zc(struct i40e_ring *rx_ring,
WARN_ON_ONCE(1);
}
-static int
-i40e_add_xsk_frag(struct i40e_ring *rx_ring, struct xdp_buff *first,
- struct xdp_buff *xdp, const unsigned int size)
-{
- struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(first);
-
- if (!xdp_buff_has_frags(first)) {
- sinfo->nr_frags = 0;
- sinfo->xdp_frags_size = 0;
- xdp_buff_set_frags_flag(first);
- }
-
- if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) {
- xsk_buff_free(first);
- return -ENOMEM;
- }
-
- __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++,
- virt_to_page(xdp->data_hard_start),
- XDP_PACKET_HEADROOM, size);
- sinfo->xdp_frags_size += size;
- xsk_buff_add_frag(xdp);
-
- return 0;
-}
-
/**
* i40e_clean_rx_irq_zc - Consumes Rx packets from the hardware ring
* @rx_ring: Rx ring
@@ -486,8 +460,10 @@ int i40e_clean_rx_irq_zc(struct i40e_ring *rx_ring, int budget)
if (!first)
first = bi;
- else if (i40e_add_xsk_frag(rx_ring, first, bi, size))
+ else if (!xsk_buff_add_frag(first, bi)) {
+ xsk_buff_free(first);
break;
+ }
if (++next_to_process == count)
next_to_process = 0;
diff --git a/drivers/net/ethernet/intel/iavf/iavf_main.c b/drivers/net/ethernet/intel/iavf/iavf_main.c
index 12ef160425aa..a9e54866ae6b 100644
--- a/drivers/net/ethernet/intel/iavf/iavf_main.c
+++ b/drivers/net/ethernet/intel/iavf/iavf_main.c
@@ -46,8 +46,8 @@ MODULE_DEVICE_TABLE(pci, iavf_pci_tbl);
MODULE_ALIAS("i40evf");
MODULE_DESCRIPTION("Intel(R) Ethernet Adaptive Virtual Function Network Driver");
-MODULE_IMPORT_NS(LIBETH);
-MODULE_IMPORT_NS(LIBIE);
+MODULE_IMPORT_NS("LIBETH");
+MODULE_IMPORT_NS("LIBIE");
MODULE_LICENSE("GPL v2");
static const struct net_device_ops iavf_netdev_ops;
diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile
index 3307d551f431..9e0d9f710441 100644
--- a/drivers/net/ethernet/intel/ice/Makefile
+++ b/drivers/net/ethernet/intel/ice/Makefile
@@ -32,7 +32,8 @@ ice-y := ice_main.o \
ice_parser_rt.o \
ice_idc.o \
devlink/devlink.o \
- devlink/devlink_port.o \
+ devlink/health.o \
+ devlink/port.o \
ice_sf_eth.o \
ice_sf_vsi_vlan_ops.o \
ice_ddp.o \
diff --git a/drivers/net/ethernet/intel/ice/devlink/devlink.c b/drivers/net/ethernet/intel/ice/devlink/devlink.c
index 415445cefdb2..1b10682c00b8 100644
--- a/drivers/net/ethernet/intel/ice/devlink/devlink.c
+++ b/drivers/net/ethernet/intel/ice/devlink/devlink.c
@@ -6,7 +6,7 @@
#include "ice.h"
#include "ice_lib.h"
#include "devlink.h"
-#include "devlink_port.h"
+#include "port.h"
#include "ice_eswitch.h"
#include "ice_fw_update.h"
#include "ice_dcb_lib.h"
diff --git a/drivers/net/ethernet/intel/ice/devlink/health.c b/drivers/net/ethernet/intel/ice/devlink/health.c
new file mode 100644
index 000000000000..d23ae3aafaa7
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/devlink/health.c
@@ -0,0 +1,269 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024, Intel Corporation. */
+
+#include "health.h"
+#include "ice.h"
+
+#define ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, obj, name) \
+ devlink_fmsg_put(fmsg, #name, (obj)->name)
+
+/**
+ * ice_devlink_health_report - boilerplate to call given @reporter
+ *
+ * @reporter: devlink health reporter to call, do nothing on NULL
+ * @msg: message to pass up, "event name" is fine
+ * @priv_ctx: typically some event struct
+ */
+static void ice_devlink_health_report(struct devlink_health_reporter *reporter,
+ const char *msg, void *priv_ctx)
+{
+ if (!reporter)
+ return;
+
+ /* We do not do auto recovering, so return value of the below function
+ * will always be 0, thus we do ignore it.
+ */
+ devlink_health_report(reporter, msg, priv_ctx);
+}
+
+struct ice_mdd_event {
+ enum ice_mdd_src src;
+ u16 vf_num;
+ u16 queue;
+ u8 pf_num;
+ u8 event;
+};
+
+static const char *ice_mdd_src_to_str(enum ice_mdd_src src)
+{
+ switch (src) {
+ case ICE_MDD_SRC_TX_PQM:
+ return "tx_pqm";
+ case ICE_MDD_SRC_TX_TCLAN:
+ return "tx_tclan";
+ case ICE_MDD_SRC_TX_TDPU:
+ return "tx_tdpu";
+ case ICE_MDD_SRC_RX:
+ return "rx";
+ default:
+ return "invalid";
+ }
+}
+
+static int
+ice_mdd_reporter_dump(struct devlink_health_reporter *reporter,
+ struct devlink_fmsg *fmsg, void *priv_ctx,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_mdd_event *mdd_event = priv_ctx;
+ const char *src;
+
+ if (!mdd_event)
+ return 0;
+
+ src = ice_mdd_src_to_str(mdd_event->src);
+
+ devlink_fmsg_obj_nest_start(fmsg);
+ devlink_fmsg_put(fmsg, "src", src);
+ ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, pf_num);
+ ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, vf_num);
+ ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, event);
+ ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, mdd_event, queue);
+ devlink_fmsg_obj_nest_end(fmsg);
+
+ return 0;
+}
+
+/**
+ * ice_report_mdd_event - Report an MDD event through devlink health
+ * @pf: the PF device structure
+ * @src: the HW block that was the source of this MDD event
+ * @pf_num: the pf_num on which the MDD event occurred
+ * @vf_num: the vf_num on which the MDD event occurred
+ * @event: the event type of the MDD event
+ * @queue: the queue on which the MDD event occurred
+ *
+ * Report an MDD event that has occurred on this PF.
+ */
+void ice_report_mdd_event(struct ice_pf *pf, enum ice_mdd_src src, u8 pf_num,
+ u16 vf_num, u8 event, u16 queue)
+{
+ struct ice_mdd_event ev = {
+ .src = src,
+ .pf_num = pf_num,
+ .vf_num = vf_num,
+ .event = event,
+ .queue = queue,
+ };
+
+ ice_devlink_health_report(pf->health_reporters.mdd, "MDD event", &ev);
+}
+
+/**
+ * ice_fmsg_put_ptr - put hex value of pointer into fmsg
+ *
+ * @fmsg: devlink fmsg under construction
+ * @name: name to pass
+ * @ptr: 64 bit value to print as hex and put into fmsg
+ */
+static void ice_fmsg_put_ptr(struct devlink_fmsg *fmsg, const char *name,
+ void *ptr)
+{
+ char buf[sizeof(ptr) * 3];
+
+ sprintf(buf, "%p", ptr);
+ devlink_fmsg_put(fmsg, name, buf);
+}
+
+struct ice_tx_hang_event {
+ u32 head;
+ u32 intr;
+ u16 vsi_num;
+ u16 queue;
+ u16 next_to_clean;
+ u16 next_to_use;
+ struct ice_tx_ring *tx_ring;
+};
+
+static int ice_tx_hang_reporter_dump(struct devlink_health_reporter *reporter,
+ struct devlink_fmsg *fmsg, void *priv_ctx,
+ struct netlink_ext_ack *extack)
+{
+ struct ice_tx_hang_event *event = priv_ctx;
+ struct sk_buff *skb;
+
+ if (!event)
+ return 0;
+
+ skb = event->tx_ring->tx_buf->skb;
+ devlink_fmsg_obj_nest_start(fmsg);
+ ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, head);
+ ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, intr);
+ ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, vsi_num);
+ ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, queue);
+ ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, next_to_clean);
+ ICE_DEVLINK_FMSG_PUT_FIELD(fmsg, event, next_to_use);
+ devlink_fmsg_put(fmsg, "irq-mapping", event->tx_ring->q_vector->name);
+ ice_fmsg_put_ptr(fmsg, "desc-ptr", event->tx_ring->desc);
+ ice_fmsg_put_ptr(fmsg, "dma-ptr", (void *)(long)event->tx_ring->dma);
+ ice_fmsg_put_ptr(fmsg, "skb-ptr", skb);
+ devlink_fmsg_binary_pair_put(fmsg, "desc", event->tx_ring->desc,
+ event->tx_ring->count * sizeof(struct ice_tx_desc));
+ devlink_fmsg_dump_skb(fmsg, skb);
+ devlink_fmsg_obj_nest_end(fmsg);
+
+ return 0;
+}
+
+void ice_prep_tx_hang_report(struct ice_pf *pf, struct ice_tx_ring *tx_ring,
+ u16 vsi_num, u32 head, u32 intr)
+{
+ struct ice_health_tx_hang_buf *buf = &pf->health_reporters.tx_hang_buf;
+
+ buf->tx_ring = tx_ring;
+ buf->vsi_num = vsi_num;
+ buf->head = head;
+ buf->intr = intr;
+}
+
+void ice_report_tx_hang(struct ice_pf *pf)
+{
+ struct ice_health_tx_hang_buf *buf = &pf->health_reporters.tx_hang_buf;
+ struct ice_tx_ring *tx_ring = buf->tx_ring;
+
+ struct ice_tx_hang_event ev = {
+ .head = buf->head,
+ .intr = buf->intr,
+ .vsi_num = buf->vsi_num,
+ .queue = tx_ring->q_index,
+ .next_to_clean = tx_ring->next_to_clean,
+ .next_to_use = tx_ring->next_to_use,
+ .tx_ring = tx_ring,
+ };
+
+ ice_devlink_health_report(pf->health_reporters.tx_hang, "Tx hang", &ev);
+}
+
+static struct devlink_health_reporter *
+ice_init_devlink_rep(struct ice_pf *pf,
+ const struct devlink_health_reporter_ops *ops)
+{
+ struct devlink *devlink = priv_to_devlink(pf);
+ struct devlink_health_reporter *rep;
+ const u64 graceful_period = 0;
+
+ rep = devl_health_reporter_create(devlink, ops, graceful_period, pf);
+ if (IS_ERR(rep)) {
+ struct device *dev = ice_pf_to_dev(pf);
+
+ dev_err(dev, "failed to create devlink %s health report er",
+ ops->name);
+ return NULL;
+ }
+ return rep;
+}
+
+#define ICE_DEFINE_HEALTH_REPORTER_OPS(_name) \
+ static const struct devlink_health_reporter_ops ice_ ## _name ## _reporter_ops = { \
+ .name = #_name, \
+ .dump = ice_ ## _name ## _reporter_dump, \
+}
+
+ICE_DEFINE_HEALTH_REPORTER_OPS(mdd);
+ICE_DEFINE_HEALTH_REPORTER_OPS(tx_hang);
+
+/**
+ * ice_health_init - allocate and init all ice devlink health reporters and
+ * accompanied data
+ *
+ * @pf: PF struct
+ */
+void ice_health_init(struct ice_pf *pf)
+{
+ struct ice_health *reps = &pf->health_reporters;
+
+ reps->mdd = ice_init_devlink_rep(pf, &ice_mdd_reporter_ops);
+ reps->tx_hang = ice_init_devlink_rep(pf, &ice_tx_hang_reporter_ops);
+}
+
+/**
+ * ice_deinit_devl_reporter - destroy given devlink health reporter
+ * @reporter: reporter to destroy
+ */
+static void ice_deinit_devl_reporter(struct devlink_health_reporter *reporter)
+{
+ if (reporter)
+ devl_health_reporter_destroy(reporter);
+}
+
+/**
+ * ice_health_deinit - deallocate all ice devlink health reporters and
+ * accompanied data
+ *
+ * @pf: PF struct
+ */
+void ice_health_deinit(struct ice_pf *pf)
+{
+ ice_deinit_devl_reporter(pf->health_reporters.mdd);
+ ice_deinit_devl_reporter(pf->health_reporters.tx_hang);
+}
+
+static
+void ice_health_assign_healthy_state(struct devlink_health_reporter *reporter)
+{
+ if (reporter)
+ devlink_health_reporter_state_update(reporter,
+ DEVLINK_HEALTH_REPORTER_STATE_HEALTHY);
+}
+
+/**
+ * ice_health_clear - clear devlink health issues after a reset
+ * @pf: the PF device structure
+ *
+ * Mark the PF in healthy state again after a reset has completed.
+ */
+void ice_health_clear(struct ice_pf *pf)
+{
+ ice_health_assign_healthy_state(pf->health_reporters.mdd);
+ ice_health_assign_healthy_state(pf->health_reporters.tx_hang);
+}
diff --git a/drivers/net/ethernet/intel/ice/devlink/health.h b/drivers/net/ethernet/intel/ice/devlink/health.h
new file mode 100644
index 000000000000..532277fc57d7
--- /dev/null
+++ b/drivers/net/ethernet/intel/ice/devlink/health.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2024, Intel Corporation. */
+
+#ifndef _HEALTH_H_
+#define _HEALTH_H_
+
+#include <linux/types.h>
+
+/**
+ * DOC: health.h
+ *
+ * This header file stores everything that is needed for broadly understood
+ * devlink health mechanism for ice driver.
+ */
+
+struct ice_pf;
+struct ice_tx_ring;
+
+enum ice_mdd_src {
+ ICE_MDD_SRC_TX_PQM,
+ ICE_MDD_SRC_TX_TCLAN,
+ ICE_MDD_SRC_TX_TDPU,
+ ICE_MDD_SRC_RX,
+};
+
+/**
+ * struct ice_health - stores ice devlink health reporters and accompanied data
+ * @tx_hang: devlink health reporter for tx_hang event
+ * @mdd: devlink health reporter for MDD detection event
+ * @tx_hang_buf: pre-allocated place to put info for Tx hang reporter from
+ * non-sleeping context
+ * @tx_ring: ring that the hang occurred on
+ * @head: descriptor head
+ * @intr: interrupt register value
+ * @vsi_num: VSI owning the queue that the hang occurred on
+ */
+struct ice_health {
+ struct devlink_health_reporter *mdd;
+ struct devlink_health_reporter *tx_hang;
+ struct_group_tagged(ice_health_tx_hang_buf, tx_hang_buf,
+ struct ice_tx_ring *tx_ring;
+ u32 head;
+ u32 intr;
+ u16 vsi_num;
+ );
+};
+
+void ice_health_init(struct ice_pf *pf);
+void ice_health_deinit(struct ice_pf *pf);
+void ice_health_clear(struct ice_pf *pf);
+
+void ice_prep_tx_hang_report(struct ice_pf *pf, struct ice_tx_ring *tx_ring,
+ u16 vsi_num, u32 head, u32 intr);
+void ice_report_mdd_event(struct ice_pf *pf, enum ice_mdd_src src, u8 pf_num,
+ u16 vf_num, u8 event, u16 queue);
+void ice_report_tx_hang(struct ice_pf *pf);
+
+#endif /* _HEALTH_H_ */
diff --git a/drivers/net/ethernet/intel/ice/devlink/devlink_port.c b/drivers/net/ethernet/intel/ice/devlink/port.c
index c6779d9dffff..767419a67fef 100644
--- a/drivers/net/ethernet/intel/ice/devlink/devlink_port.c
+++ b/drivers/net/ethernet/intel/ice/devlink/port.c
@@ -5,7 +5,7 @@
#include "ice.h"
#include "devlink.h"
-#include "devlink_port.h"
+#include "port.h"
#include "ice_lib.h"
#include "ice_fltr.h"
diff --git a/drivers/net/ethernet/intel/ice/devlink/devlink_port.h b/drivers/net/ethernet/intel/ice/devlink/port.h
index d60efc340945..d60efc340945 100644
--- a/drivers/net/ethernet/intel/ice/devlink/devlink_port.h
+++ b/drivers/net/ethernet/intel/ice/devlink/port.h
diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h
index 2f5d6f974185..71e05d30f0fd 100644
--- a/drivers/net/ethernet/intel/ice/ice.h
+++ b/drivers/net/ethernet/intel/ice/ice.h
@@ -78,6 +78,7 @@
#include "ice_irq.h"
#include "ice_dpll.h"
#include "ice_adapter.h"
+#include "devlink/health.h"
#define ICE_BAR0 0
#define ICE_REQ_DESC_MULTIPLE 32
@@ -665,6 +666,7 @@ struct ice_pf {
struct ice_agg_node vf_agg_node[ICE_MAX_VF_AGG_NODES];
struct ice_dplls dplls;
struct device *hwmon_dev;
+ struct ice_health health_reporters;
u8 num_quanta_prof_used;
};
diff --git a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
index 1489a8ceec51..73f5fddf3ee9 100644
--- a/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
+++ b/drivers/net/ethernet/intel/ice/ice_adminq_cmd.h
@@ -12,6 +12,13 @@
#define ICE_AQC_TOPO_MAX_LEVEL_NUM 0x9
#define ICE_AQ_SET_MAC_FRAME_SIZE_MAX 9728
+#define ICE_RXQ_CTX_SIZE_DWORDS 8
+#define ICE_RXQ_CTX_SZ (ICE_RXQ_CTX_SIZE_DWORDS * sizeof(u32))
+#define ICE_TXQ_CTX_SZ 22
+
+typedef struct __packed { u8 buf[ICE_RXQ_CTX_SZ]; } ice_rxq_ctx_buf_t;
+typedef struct __packed { u8 buf[ICE_TXQ_CTX_SZ]; } ice_txq_ctx_buf_t;
+
struct ice_aqc_generic {
__le32 param0;
__le32 param1;
@@ -2084,10 +2091,10 @@ struct ice_aqc_add_txqs_perq {
__le16 txq_id;
u8 rsvd[2];
__le32 q_teid;
- u8 txq_ctx[22];
+ ice_txq_ctx_buf_t txq_ctx;
u8 rsvd2[2];
struct ice_aqc_txsched_elem info;
-};
+} __packed;
/* The format of the command buffer for Add Tx LAN Queues (0x0C30)
* is an array of the following structs. Please note that the length of
@@ -2264,6 +2271,8 @@ struct ice_aqc_get_pkg_info_resp {
struct ice_aqc_get_pkg_info pkg_info[];
};
+#define ICE_AQC_GET_CGU_MAX_PHASE_ADJ GENMASK(30, 0)
+
/* Get CGU abilities command response data structure (indirect 0x0C61) */
struct ice_aqc_get_cgu_abilities {
u8 num_inputs;
diff --git a/drivers/net/ethernet/intel/ice/ice_base.c b/drivers/net/ethernet/intel/ice/ice_base.c
index 82a9cd4ec7ae..b2af8e3586f7 100644
--- a/drivers/net/ethernet/intel/ice/ice_base.c
+++ b/drivers/net/ethernet/intel/ice/ice_base.c
@@ -454,6 +454,9 @@ static int ice_setup_rx_ctx(struct ice_rx_ring *ring)
/* Rx queue threshold in units of 64 */
rlan_ctx.lrxqthresh = 1;
+ /* Enable descriptor prefetch */
+ rlan_ctx.prefena = 1;
+
/* PF acts as uplink for switchdev; set flex descriptor with src_vsi
* metadata and flags to allow redirecting to PR netdev
*/
@@ -910,8 +913,7 @@ ice_vsi_cfg_txq(struct ice_vsi *vsi, struct ice_tx_ring *ring,
ice_setup_tx_ctx(ring, &tlan_ctx, pf_q);
/* copy context contents into the qg_buf */
qg_buf->txqs[0].txq_id = cpu_to_le16(pf_q);
- ice_set_ctx(hw, (u8 *)&tlan_ctx, qg_buf->txqs[0].txq_ctx,
- ice_tlan_ctx_info);
+ ice_pack_txq_ctx(&tlan_ctx, &qg_buf->txqs[0].txq_ctx);
/* init queue specific tail reg. It is referred as
* transmit comm scheduler queue doorbell.
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index b22e71dc59d4..f89bc6ede315 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -6,6 +6,7 @@
#include "ice_adminq_cmd.h"
#include "ice_flow.h"
#include "ice_ptp_hw.h"
+#include <linux/packing.h>
#define ICE_PF_RESET_WAIT_COUNT 300
#define ICE_MAX_NETLIST_SIZE 10
@@ -542,7 +543,8 @@ ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
/**
* ice_find_netlist_node
* @hw: pointer to the hw struct
- * @node_type_ctx: type of netlist node to look for
+ * @node_type: type of netlist node to look for
+ * @ctx: context of the search
* @node_part_number: node part number to look for
* @node_handle: output parameter if node found - optional
*
@@ -552,10 +554,12 @@ ice_aq_get_netlist_node(struct ice_hw *hw, struct ice_aqc_get_link_topo *cmd,
* valid if the function returns zero, and should be ignored on any non-zero
* return value.
*
- * Returns: 0 if the node is found, -ENOENT if no handle was found, and
- * a negative error code on failure to access the AQ.
+ * Return:
+ * * 0 if the node is found,
+ * * -ENOENT if no handle was found,
+ * * negative error code on failure to access the AQ.
*/
-static int ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx,
+static int ice_find_netlist_node(struct ice_hw *hw, u8 node_type, u8 ctx,
u8 node_part_number, u16 *node_handle)
{
u8 idx;
@@ -566,8 +570,8 @@ static int ice_find_netlist_node(struct ice_hw *hw, u8 node_type_ctx,
int status;
cmd.addr.topo_params.node_type_ctx =
- FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M,
- node_type_ctx);
+ FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_TYPE_M, node_type) |
+ FIELD_PREP(ICE_AQC_LINK_TOPO_NODE_CTX_M, ctx);
cmd.addr.topo_params.index = idx;
status = ice_aq_get_netlist_node(hw, &cmd,
@@ -1357,39 +1361,31 @@ int ice_reset(struct ice_hw *hw, enum ice_reset_req req)
}
/**
- * ice_copy_rxq_ctx_to_hw
+ * ice_copy_rxq_ctx_to_hw - Copy packed Rx queue context to HW registers
* @hw: pointer to the hardware structure
- * @ice_rxq_ctx: pointer to the rxq context
+ * @rxq_ctx: pointer to the packed Rx queue context
* @rxq_index: the index of the Rx queue
- *
- * Copies rxq context from dense structure to HW register space
*/
-static int
-ice_copy_rxq_ctx_to_hw(struct ice_hw *hw, u8 *ice_rxq_ctx, u32 rxq_index)
+static void ice_copy_rxq_ctx_to_hw(struct ice_hw *hw,
+ const ice_rxq_ctx_buf_t *rxq_ctx,
+ u32 rxq_index)
{
- u8 i;
-
- if (!ice_rxq_ctx)
- return -EINVAL;
-
- if (rxq_index > QRX_CTRL_MAX_INDEX)
- return -EINVAL;
-
/* Copy each dword separately to HW */
- for (i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
- wr32(hw, QRX_CONTEXT(i, rxq_index),
- *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
+ for (int i = 0; i < ICE_RXQ_CTX_SIZE_DWORDS; i++) {
+ u32 ctx = ((const u32 *)rxq_ctx)[i];
- ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i,
- *((u32 *)(ice_rxq_ctx + (i * sizeof(u32)))));
- }
+ wr32(hw, QRX_CONTEXT(i, rxq_index), ctx);
- return 0;
+ ice_debug(hw, ICE_DBG_QCTX, "qrxdata[%d]: %08X\n", i, ctx);
+ }
}
+#define ICE_CTX_STORE(struct_name, struct_field, width, lsb) \
+ PACKED_FIELD((lsb) + (width) - 1, (lsb), struct struct_name, struct_field)
+
/* LAN Rx Queue Context */
-static const struct ice_ctx_ele ice_rlan_ctx_info[] = {
- /* Field Width LSB */
+static const struct packed_field_u8 ice_rlan_ctx_fields[] = {
+ /* Field Width LSB */
ICE_CTX_STORE(ice_rlan_ctx, head, 13, 0),
ICE_CTX_STORE(ice_rlan_ctx, cpuid, 8, 13),
ICE_CTX_STORE(ice_rlan_ctx, base, 57, 32),
@@ -1410,35 +1406,50 @@ static const struct ice_ctx_ele ice_rlan_ctx_info[] = {
ICE_CTX_STORE(ice_rlan_ctx, tphhead_ena, 1, 196),
ICE_CTX_STORE(ice_rlan_ctx, lrxqthresh, 3, 198),
ICE_CTX_STORE(ice_rlan_ctx, prefena, 1, 201),
- { 0 }
};
/**
- * ice_write_rxq_ctx
+ * ice_pack_rxq_ctx - Pack Rx queue context into a HW buffer
+ * @ctx: the Rx queue context to pack
+ * @buf: the HW buffer to pack into
+ *
+ * Pack the Rx queue context from the CPU-friendly unpacked buffer into its
+ * bit-packed HW layout.
+ */
+static void ice_pack_rxq_ctx(const struct ice_rlan_ctx *ctx,
+ ice_rxq_ctx_buf_t *buf)
+{
+ pack_fields(buf, sizeof(*buf), ctx, ice_rlan_ctx_fields,
+ QUIRK_LITTLE_ENDIAN | QUIRK_LSW32_IS_FIRST);
+}
+
+/**
+ * ice_write_rxq_ctx - Write Rx Queue context to hardware
* @hw: pointer to the hardware structure
- * @rlan_ctx: pointer to the rxq context
+ * @rlan_ctx: pointer to the unpacked Rx queue context
* @rxq_index: the index of the Rx queue
*
- * Converts rxq context from sparse to dense structure and then writes
- * it to HW register space and enables the hardware to prefetch descriptors
- * instead of only fetching them on demand
+ * Pack the sparse Rx Queue context into dense hardware format and write it
+ * into the HW register space.
+ *
+ * Return: 0 on success, or -EINVAL if the Rx queue index is invalid.
*/
int ice_write_rxq_ctx(struct ice_hw *hw, struct ice_rlan_ctx *rlan_ctx,
u32 rxq_index)
{
- u8 ctx_buf[ICE_RXQ_CTX_SZ] = { 0 };
+ ice_rxq_ctx_buf_t buf = {};
- if (!rlan_ctx)
+ if (rxq_index > QRX_CTRL_MAX_INDEX)
return -EINVAL;
- rlan_ctx->prefena = 1;
+ ice_pack_rxq_ctx(rlan_ctx, &buf);
+ ice_copy_rxq_ctx_to_hw(hw, &buf, rxq_index);
- ice_set_ctx(hw, (u8 *)rlan_ctx, ctx_buf, ice_rlan_ctx_info);
- return ice_copy_rxq_ctx_to_hw(hw, ctx_buf, rxq_index);
+ return 0;
}
/* LAN Tx Queue Context */
-const struct ice_ctx_ele ice_tlan_ctx_info[] = {
+static const struct packed_field_u8 ice_tlan_ctx_fields[] = {
/* Field Width LSB */
ICE_CTX_STORE(ice_tlan_ctx, base, 57, 0),
ICE_CTX_STORE(ice_tlan_ctx, port_num, 3, 57),
@@ -1467,10 +1478,22 @@ const struct ice_ctx_ele ice_tlan_ctx_info[] = {
ICE_CTX_STORE(ice_tlan_ctx, drop_ena, 1, 165),
ICE_CTX_STORE(ice_tlan_ctx, cache_prof_idx, 2, 166),
ICE_CTX_STORE(ice_tlan_ctx, pkt_shaper_prof_idx, 3, 168),
- ICE_CTX_STORE(ice_tlan_ctx, int_q_state, 122, 171),
- { 0 }
};
+/**
+ * ice_pack_txq_ctx - Pack Tx queue context into a HW buffer
+ * @ctx: the Tx queue context to pack
+ * @buf: the HW buffer to pack into
+ *
+ * Pack the Tx queue context from the CPU-friendly unpacked buffer into its
+ * bit-packed HW layout.
+ */
+void ice_pack_txq_ctx(const struct ice_tlan_ctx *ctx, ice_txq_ctx_buf_t *buf)
+{
+ pack_fields(buf, sizeof(*buf), ctx, ice_tlan_ctx_fields,
+ QUIRK_LITTLE_ENDIAN | QUIRK_LSW32_IS_FIRST);
+}
+
/* Sideband Queue command wrappers */
/**
@@ -2747,9 +2770,11 @@ bool ice_is_pf_c827(struct ice_hw *hw)
*/
bool ice_is_phy_rclk_in_netlist(struct ice_hw *hw)
{
- if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
+ if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY,
+ ICE_AQC_LINK_TOPO_NODE_CTX_PORT,
ICE_AQC_GET_LINK_TOPO_NODE_NR_C827, NULL) &&
- ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
+ ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_PHY,
+ ICE_AQC_LINK_TOPO_NODE_CTX_PORT,
ICE_AQC_GET_LINK_TOPO_NODE_NR_E822_PHY, NULL))
return false;
@@ -2765,6 +2790,7 @@ bool ice_is_phy_rclk_in_netlist(struct ice_hw *hw)
bool ice_is_clock_mux_in_netlist(struct ice_hw *hw)
{
if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_MUX,
+ ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
ICE_AQC_GET_LINK_TOPO_NODE_NR_GEN_CLK_MUX,
NULL))
return false;
@@ -2785,12 +2811,14 @@ bool ice_is_clock_mux_in_netlist(struct ice_hw *hw)
bool ice_is_cgu_in_netlist(struct ice_hw *hw)
{
if (!ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
+ ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL30632_80032,
NULL)) {
hw->cgu_part_number = ICE_AQC_GET_LINK_TOPO_NODE_NR_ZL30632_80032;
return true;
} else if (!ice_find_netlist_node(hw,
ICE_AQC_LINK_TOPO_NODE_TYPE_CLK_CTRL,
+ ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
ICE_AQC_GET_LINK_TOPO_NODE_NR_SI5383_5384,
NULL)) {
hw->cgu_part_number = ICE_AQC_GET_LINK_TOPO_NODE_NR_SI5383_5384;
@@ -2809,6 +2837,7 @@ bool ice_is_cgu_in_netlist(struct ice_hw *hw)
bool ice_is_gps_in_netlist(struct ice_hw *hw)
{
if (ice_find_netlist_node(hw, ICE_AQC_LINK_TOPO_NODE_TYPE_GPS,
+ ICE_AQC_LINK_TOPO_NODE_CTX_GLOBAL,
ICE_AQC_GET_LINK_TOPO_NODE_NR_GEN_GPS, NULL))
return false;
@@ -4549,205 +4578,6 @@ ice_aq_add_rdma_qsets(struct ice_hw *hw, u8 num_qset_grps,
/* End of FW Admin Queue command wrappers */
/**
- * ice_pack_ctx_byte - write a byte to a packed context structure
- * @src_ctx: unpacked source context structure
- * @dest_ctx: packed destination context data
- * @ce_info: context element description
- */
-static void ice_pack_ctx_byte(u8 *src_ctx, u8 *dest_ctx,
- const struct ice_ctx_ele *ce_info)
-{
- u8 src_byte, dest_byte, mask;
- u8 *from, *dest;
- u16 shift_width;
-
- /* copy from the next struct field */
- from = src_ctx + ce_info->offset;
-
- /* prepare the bits and mask */
- shift_width = ce_info->lsb % 8;
- mask = GENMASK(ce_info->width - 1 + shift_width, shift_width);
-
- src_byte = *from;
- src_byte <<= shift_width;
- src_byte &= mask;
-
- /* get the current bits from the target bit string */
- dest = dest_ctx + (ce_info->lsb / 8);
-
- memcpy(&dest_byte, dest, sizeof(dest_byte));
-
- dest_byte &= ~mask; /* get the bits not changing */
- dest_byte |= src_byte; /* add in the new bits */
-
- /* put it all back */
- memcpy(dest, &dest_byte, sizeof(dest_byte));
-}
-
-/**
- * ice_pack_ctx_word - write a word to a packed context structure
- * @src_ctx: unpacked source context structure
- * @dest_ctx: packed destination context data
- * @ce_info: context element description
- */
-static void ice_pack_ctx_word(u8 *src_ctx, u8 *dest_ctx,
- const struct ice_ctx_ele *ce_info)
-{
- u16 src_word, mask;
- __le16 dest_word;
- u8 *from, *dest;
- u16 shift_width;
-
- /* copy from the next struct field */
- from = src_ctx + ce_info->offset;
-
- /* prepare the bits and mask */
- shift_width = ce_info->lsb % 8;
- mask = GENMASK(ce_info->width - 1 + shift_width, shift_width);
-
- /* don't swizzle the bits until after the mask because the mask bits
- * will be in a different bit position on big endian machines
- */
- src_word = *(u16 *)from;
- src_word <<= shift_width;
- src_word &= mask;
-
- /* get the current bits from the target bit string */
- dest = dest_ctx + (ce_info->lsb / 8);
-
- memcpy(&dest_word, dest, sizeof(dest_word));
-
- dest_word &= ~(cpu_to_le16(mask)); /* get the bits not changing */
- dest_word |= cpu_to_le16(src_word); /* add in the new bits */
-
- /* put it all back */
- memcpy(dest, &dest_word, sizeof(dest_word));
-}
-
-/**
- * ice_pack_ctx_dword - write a dword to a packed context structure
- * @src_ctx: unpacked source context structure
- * @dest_ctx: packed destination context data
- * @ce_info: context element description
- */
-static void ice_pack_ctx_dword(u8 *src_ctx, u8 *dest_ctx,
- const struct ice_ctx_ele *ce_info)
-{
- u32 src_dword, mask;
- __le32 dest_dword;
- u8 *from, *dest;
- u16 shift_width;
-
- /* copy from the next struct field */
- from = src_ctx + ce_info->offset;
-
- /* prepare the bits and mask */
- shift_width = ce_info->lsb % 8;
- mask = GENMASK(ce_info->width - 1 + shift_width, shift_width);
-
- /* don't swizzle the bits until after the mask because the mask bits
- * will be in a different bit position on big endian machines
- */
- src_dword = *(u32 *)from;
- src_dword <<= shift_width;
- src_dword &= mask;
-
- /* get the current bits from the target bit string */
- dest = dest_ctx + (ce_info->lsb / 8);
-
- memcpy(&dest_dword, dest, sizeof(dest_dword));
-
- dest_dword &= ~(cpu_to_le32(mask)); /* get the bits not changing */
- dest_dword |= cpu_to_le32(src_dword); /* add in the new bits */
-
- /* put it all back */
- memcpy(dest, &dest_dword, sizeof(dest_dword));
-}
-
-/**
- * ice_pack_ctx_qword - write a qword to a packed context structure
- * @src_ctx: unpacked source context structure
- * @dest_ctx: packed destination context data
- * @ce_info: context element description
- */
-static void ice_pack_ctx_qword(u8 *src_ctx, u8 *dest_ctx,
- const struct ice_ctx_ele *ce_info)
-{
- u64 src_qword, mask;
- __le64 dest_qword;
- u8 *from, *dest;
- u16 shift_width;
-
- /* copy from the next struct field */
- from = src_ctx + ce_info->offset;
-
- /* prepare the bits and mask */
- shift_width = ce_info->lsb % 8;
- mask = GENMASK_ULL(ce_info->width - 1 + shift_width, shift_width);
-
- /* don't swizzle the bits until after the mask because the mask bits
- * will be in a different bit position on big endian machines
- */
- src_qword = *(u64 *)from;
- src_qword <<= shift_width;
- src_qword &= mask;
-
- /* get the current bits from the target bit string */
- dest = dest_ctx + (ce_info->lsb / 8);
-
- memcpy(&dest_qword, dest, sizeof(dest_qword));
-
- dest_qword &= ~(cpu_to_le64(mask)); /* get the bits not changing */
- dest_qword |= cpu_to_le64(src_qword); /* add in the new bits */
-
- /* put it all back */
- memcpy(dest, &dest_qword, sizeof(dest_qword));
-}
-
-/**
- * ice_set_ctx - set context bits in packed structure
- * @hw: pointer to the hardware structure
- * @src_ctx: pointer to a generic non-packed context structure
- * @dest_ctx: pointer to memory for the packed structure
- * @ce_info: List of Rx context elements
- */
-int ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
- const struct ice_ctx_ele *ce_info)
-{
- int f;
-
- for (f = 0; ce_info[f].width; f++) {
- /* We have to deal with each element of the FW response
- * using the correct size so that we are correct regardless
- * of the endianness of the machine.
- */
- if (ce_info[f].width > (ce_info[f].size_of * BITS_PER_BYTE)) {
- ice_debug(hw, ICE_DBG_QCTX, "Field %d width of %d bits larger than size of %d byte(s) ... skipping write\n",
- f, ce_info[f].width, ce_info[f].size_of);
- continue;
- }
- switch (ce_info[f].size_of) {
- case sizeof(u8):
- ice_pack_ctx_byte(src_ctx, dest_ctx, &ce_info[f]);
- break;
- case sizeof(u16):
- ice_pack_ctx_word(src_ctx, dest_ctx, &ce_info[f]);
- break;
- case sizeof(u32):
- ice_pack_ctx_dword(src_ctx, dest_ctx, &ce_info[f]);
- break;
- case sizeof(u64):
- ice_pack_ctx_qword(src_ctx, dest_ctx, &ce_info[f]);
- break;
- default:
- return -EINVAL;
- }
- }
-
- return 0;
-}
-
-/**
* ice_get_lan_q_ctx - get the LAN queue context for the given VSI and TC
* @hw: pointer to the HW struct
* @vsi_handle: software VSI handle
diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h
index 27208a60cece..a68bea3934e3 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.h
+++ b/drivers/net/ethernet/intel/ice/ice_common.h
@@ -92,9 +92,8 @@ ice_aq_set_rss_key(struct ice_hw *hw, u16 vsi_handle,
bool ice_check_sq_alive(struct ice_hw *hw, struct ice_ctl_q_info *cq);
int ice_aq_q_shutdown(struct ice_hw *hw, bool unloading);
void ice_fill_dflt_direct_cmd_desc(struct ice_aq_desc *desc, u16 opcode);
-extern const struct ice_ctx_ele ice_tlan_ctx_info[];
-int ice_set_ctx(struct ice_hw *hw, u8 *src_ctx, u8 *dest_ctx,
- const struct ice_ctx_ele *ce_info);
+
+void ice_pack_txq_ctx(const struct ice_tlan_ctx *ctx, ice_txq_ctx_buf_t *buf);
extern struct mutex ice_global_cfg_lock_sw;
diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c
index d5ad6d84007c..38e151c7ea23 100644
--- a/drivers/net/ethernet/intel/ice/ice_dpll.c
+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c
@@ -2065,6 +2065,18 @@ static int ice_dpll_init_worker(struct ice_pf *pf)
}
/**
+ * ice_dpll_phase_range_set - initialize phase adjust range helper
+ * @range: pointer to phase adjust range struct to be initialized
+ * @phase_adj: a value to be used as min(-)/max(+) boundary
+ */
+static void ice_dpll_phase_range_set(struct dpll_pin_phase_adjust_range *range,
+ u32 phase_adj)
+{
+ range->min = -phase_adj;
+ range->max = phase_adj;
+}
+
+/**
* ice_dpll_init_info_pins_generic - initializes generic pins info
* @pf: board private structure
* @input: if input pins initialized
@@ -2105,8 +2117,8 @@ static int ice_dpll_init_info_pins_generic(struct ice_pf *pf, bool input)
for (i = 0; i < pin_num; i++) {
pins[i].idx = i;
pins[i].prop.board_label = labels[i];
- pins[i].prop.phase_range.min = phase_adj_max;
- pins[i].prop.phase_range.max = -phase_adj_max;
+ ice_dpll_phase_range_set(&pins[i].prop.phase_range,
+ phase_adj_max);
pins[i].prop.capabilities = cap;
pins[i].pf = pf;
ret = ice_dpll_pin_state_update(pf, &pins[i], pin_type, NULL);
@@ -2152,6 +2164,7 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf,
struct ice_hw *hw = &pf->hw;
struct ice_dpll_pin *pins;
unsigned long caps;
+ u32 phase_adj_max;
u8 freq_supp_num;
bool input;
@@ -2159,11 +2172,13 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf,
case ICE_DPLL_PIN_TYPE_INPUT:
pins = pf->dplls.inputs;
num_pins = pf->dplls.num_inputs;
+ phase_adj_max = pf->dplls.input_phase_adj_max;
input = true;
break;
case ICE_DPLL_PIN_TYPE_OUTPUT:
pins = pf->dplls.outputs;
num_pins = pf->dplls.num_outputs;
+ phase_adj_max = pf->dplls.output_phase_adj_max;
input = false;
break;
default:
@@ -2188,19 +2203,13 @@ ice_dpll_init_info_direct_pins(struct ice_pf *pf,
return ret;
caps |= (DPLL_PIN_CAPABILITIES_PRIORITY_CAN_CHANGE |
DPLL_PIN_CAPABILITIES_STATE_CAN_CHANGE);
- pins[i].prop.phase_range.min =
- pf->dplls.input_phase_adj_max;
- pins[i].prop.phase_range.max =
- -pf->dplls.input_phase_adj_max;
} else {
- pins[i].prop.phase_range.min =
- pf->dplls.output_phase_adj_max;
- pins[i].prop.phase_range.max =
- -pf->dplls.output_phase_adj_max;
ret = ice_cgu_get_output_pin_state_caps(hw, i, &caps);
if (ret)
return ret;
}
+ ice_dpll_phase_range_set(&pins[i].prop.phase_range,
+ phase_adj_max);
pins[i].prop.capabilities = caps;
ret = ice_dpll_pin_state_update(pf, &pins[i], pin_type, NULL);
if (ret)
@@ -2308,8 +2317,10 @@ static int ice_dpll_init_info(struct ice_pf *pf, bool cgu)
dp->dpll_idx = abilities.pps_dpll_idx;
d->num_inputs = abilities.num_inputs;
d->num_outputs = abilities.num_outputs;
- d->input_phase_adj_max = le32_to_cpu(abilities.max_in_phase_adj);
- d->output_phase_adj_max = le32_to_cpu(abilities.max_out_phase_adj);
+ d->input_phase_adj_max = le32_to_cpu(abilities.max_in_phase_adj) &
+ ICE_AQC_GET_CGU_MAX_PHASE_ADJ;
+ d->output_phase_adj_max = le32_to_cpu(abilities.max_out_phase_adj) &
+ ICE_AQC_GET_CGU_MAX_PHASE_ADJ;
alloc_size = sizeof(*d->inputs) * d->num_inputs;
d->inputs = kzalloc(alloc_size, GFP_KERNEL);
diff --git a/drivers/net/ethernet/intel/ice/ice_eswitch.h b/drivers/net/ethernet/intel/ice/ice_eswitch.h
index ac7db100e2cd..5c7dcf21b222 100644
--- a/drivers/net/ethernet/intel/ice/ice_eswitch.h
+++ b/drivers/net/ethernet/intel/ice/ice_eswitch.h
@@ -5,7 +5,7 @@
#define _ICE_ESWITCH_H_
#include <net/devlink.h>
-#include "devlink/devlink_port.h"
+#include "devlink/port.h"
#ifdef CONFIG_ICE_SWITCHDEV
void ice_eswitch_detach_vf(struct ice_pf *pf, struct ice_vf *vf);
diff --git a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
index 611577ebc29d..1479b45738af 100644
--- a/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
+++ b/drivers/net/ethernet/intel/ice/ice_lan_tx_rx.h
@@ -371,29 +371,21 @@ enum ice_rx_flex_desc_status_error_1_bits {
ICE_RX_FLEX_DESC_STATUS1_LAST /* this entry must be last!!! */
};
-#define ICE_RXQ_CTX_SIZE_DWORDS 8
-#define ICE_RXQ_CTX_SZ (ICE_RXQ_CTX_SIZE_DWORDS * sizeof(u32))
#define ICE_TX_CMPLTNQ_CTX_SIZE_DWORDS 22
#define ICE_TX_DRBELL_Q_CTX_SIZE_DWORDS 5
#define GLTCLAN_CQ_CNTX(i, CQ) (GLTCLAN_CQ_CNTX0(CQ) + ((i) * 0x0800))
-/* RLAN Rx queue context data
- *
- * The sizes of the variables may be larger than needed due to crossing byte
- * boundaries. If we do not have the width of the variable set to the correct
- * size then we could end up shifting bits off the top of the variable when the
- * variable is at the top of a byte and crosses over into the next byte.
- */
+/* RLAN Rx queue context data */
struct ice_rlan_ctx {
u16 head;
- u16 cpuid; /* bigger than needed, see above for reason */
+ u8 cpuid;
#define ICE_RLAN_BASE_S 7
u64 base;
u16 qlen;
#define ICE_RLAN_CTX_DBUF_S 7
- u16 dbuf; /* bigger than needed, see above for reason */
+ u8 dbuf;
#define ICE_RLAN_CTX_HBUF_S 6
- u16 hbuf; /* bigger than needed, see above for reason */
+ u8 hbuf;
u8 dtype;
u8 dsize;
u8 crcstrip;
@@ -401,29 +393,15 @@ struct ice_rlan_ctx {
u8 hsplit_0;
u8 hsplit_1;
u8 showiv;
- u32 rxmax; /* bigger than needed, see above for reason */
+ u16 rxmax;
u8 tphrdesc_ena;
u8 tphwdesc_ena;
u8 tphdata_ena;
u8 tphhead_ena;
- u16 lrxqthresh; /* bigger than needed, see above for reason */
+ u8 lrxqthresh;
u8 prefena; /* NOTE: normally must be set to 1 at init */
};
-struct ice_ctx_ele {
- u16 offset;
- u16 size_of;
- u16 width;
- u16 lsb;
-};
-
-#define ICE_CTX_STORE(_struct, _ele, _width, _lsb) { \
- .offset = offsetof(struct _struct, _ele), \
- .size_of = sizeof_field(struct _struct, _ele), \
- .width = _width, \
- .lsb = _lsb, \
-}
-
/* for hsplit_0 field of Rx RLAN context */
enum ice_rlan_ctx_rx_hsplit_0 {
ICE_RLAN_RX_HSPLIT_0_NO_SPLIT = 0,
@@ -551,18 +529,12 @@ enum ice_tx_ctx_desc_eipt_offload {
#define ICE_LAN_TXQ_MAX_QGRPS 127
#define ICE_LAN_TXQ_MAX_QDIS 1023
-/* Tx queue context data
- *
- * The sizes of the variables may be larger than needed due to crossing byte
- * boundaries. If we do not have the width of the variable set to the correct
- * size then we could end up shifting bits off the top of the variable when the
- * variable is at the top of a byte and crosses over into the next byte.
- */
+/* Tx queue context data */
struct ice_tlan_ctx {
#define ICE_TLAN_CTX_BASE_S 7
u64 base; /* base is defined in 128-byte units */
u8 port_num;
- u16 cgd_num; /* bigger than needed, see above for reason */
+ u8 cgd_num;
u8 pf_num;
u16 vmvf_num;
u8 vmvf_type;
@@ -573,7 +545,7 @@ struct ice_tlan_ctx {
u8 tsyn_ena;
u8 internal_usage_flag;
u8 alt_vlan;
- u16 cpuid; /* bigger than needed, see above for reason */
+ u8 cpuid;
u8 wb_mode;
u8 tphrd_desc;
u8 tphrd;
@@ -582,7 +554,7 @@ struct ice_tlan_ctx {
u16 qnum_in_func;
u8 itr_notification_mode;
u8 adjust_prof_id;
- u32 qlen; /* bigger than needed, see above for reason */
+ u16 qlen;
u8 quanta_prof_idx;
u8 tso_ena;
u16 tso_qnum;
@@ -590,7 +562,6 @@ struct ice_tlan_ctx {
u8 drop_ena;
u8 cache_prof_idx;
u8 pkt_shaper_prof_idx;
- u8 int_q_state; /* width not needed - internal - DO NOT WRITE!!! */
};
#endif /* _ICE_LAN_TX_RX_H_ */
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 1eaa4428fd24..1701f7143f24 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -14,7 +14,7 @@
#include "ice_dcb_lib.h"
#include "ice_dcb_nl.h"
#include "devlink/devlink.h"
-#include "devlink/devlink_port.h"
+#include "devlink/port.h"
#include "ice_sf_eth.h"
#include "ice_hwmon.h"
/* Including ice_trace.h with CREATE_TRACE_POINTS defined will generate the
@@ -37,7 +37,7 @@ static const char ice_copyright[] = "Copyright (c) 2018, Intel Corporation.";
#define ICE_DDP_PKG_FILE ICE_DDP_PKG_PATH "ice.pkg"
MODULE_DESCRIPTION(DRV_SUMMARY);
-MODULE_IMPORT_NS(LIBIE);
+MODULE_IMPORT_NS("LIBIE");
MODULE_LICENSE("GPL v2");
MODULE_FIRMWARE(ICE_DDP_PKG_FILE);
@@ -1816,6 +1816,8 @@ static void ice_handle_mdd_event(struct ice_pf *pf)
if (netif_msg_tx_err(pf))
dev_info(dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n",
event, queue, pf_num, vf_num);
+ ice_report_mdd_event(pf, ICE_MDD_SRC_TX_PQM, pf_num, vf_num,
+ event, queue);
wr32(hw, GL_MDET_TX_PQM, 0xffffffff);
}
@@ -1829,6 +1831,8 @@ static void ice_handle_mdd_event(struct ice_pf *pf)
if (netif_msg_tx_err(pf))
dev_info(dev, "Malicious Driver Detection event %d on TX queue %d PF# %d VF# %d\n",
event, queue, pf_num, vf_num);
+ ice_report_mdd_event(pf, ICE_MDD_SRC_TX_TCLAN, pf_num, vf_num,
+ event, queue);
wr32(hw, GL_MDET_TX_TCLAN_BY_MAC(hw), U32_MAX);
}
@@ -1842,6 +1846,8 @@ static void ice_handle_mdd_event(struct ice_pf *pf)
if (netif_msg_rx_err(pf))
dev_info(dev, "Malicious Driver Detection event %d on RX queue %d PF# %d VF# %d\n",
event, queue, pf_num, vf_num);
+ ice_report_mdd_event(pf, ICE_MDD_SRC_RX, pf_num, vf_num, event,
+ queue);
wr32(hw, GL_MDET_RX, 0xffffffff);
}
@@ -2364,9 +2370,11 @@ static void ice_service_task(struct work_struct *work)
struct ice_pf *pf = container_of(work, struct ice_pf, serv_task);
unsigned long start_time = jiffies;
- /* subtasks */
+ if (pf->health_reporters.tx_hang_buf.tx_ring) {
+ ice_report_tx_hang(pf);
+ pf->health_reporters.tx_hang_buf.tx_ring = NULL;
+ }
- /* process reset requests first */
ice_reset_subtask(pf);
/* bail if a reset/recovery cycle is pending or rebuild failed */
@@ -5087,6 +5095,7 @@ static int ice_init_devlink(struct ice_pf *pf)
return err;
ice_devlink_init_regions(pf);
+ ice_health_init(pf);
ice_devlink_register(pf);
return 0;
@@ -5095,6 +5104,7 @@ static int ice_init_devlink(struct ice_pf *pf)
static void ice_deinit_devlink(struct ice_pf *pf)
{
ice_devlink_unregister(pf);
+ ice_health_deinit(pf);
ice_devlink_destroy_regions(pf);
ice_devlink_unregister_params(pf);
}
@@ -6408,10 +6418,12 @@ ice_set_vlan_filtering_features(struct ice_vsi *vsi, netdev_features_t features)
int err = 0;
/* support Single VLAN Mode (SVM) and Double VLAN Mode (DVM) by checking
- * if either bit is set
+ * if either bit is set. In switchdev mode Rx filtering should never be
+ * enabled.
*/
- if (features &
- (NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER))
+ if ((features &
+ (NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_HW_VLAN_STAG_FILTER)) &&
+ !ice_is_eswitch_mode_switchdev(vsi->back))
err = vlan_ops->ena_rx_filtering(vsi);
else
err = vlan_ops->dis_rx_filtering(vsi);
@@ -7791,6 +7803,8 @@ static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
/* if we get here, reset flow is successful */
clear_bit(ICE_RESET_FAILED, pf->state);
+ ice_health_clear(pf);
+
ice_plug_aux_dev(pf);
if (ice_is_feature_supported(pf, ICE_F_SRIOV_LAG))
ice_lag_rebuild(pf);
@@ -8281,16 +8295,18 @@ void ice_tx_timeout(struct net_device *netdev, unsigned int txqueue)
if (tx_ring) {
struct ice_hw *hw = &pf->hw;
- u32 head, val = 0;
+ u32 head, intr = 0;
head = FIELD_GET(QTX_COMM_HEAD_HEAD_M,
rd32(hw, QTX_COMM_HEAD(vsi->txq_map[txqueue])));
/* Read interrupt register */
- val = rd32(hw, GLINT_DYN_CTL(tx_ring->q_vector->reg_idx));
+ intr = rd32(hw, GLINT_DYN_CTL(tx_ring->q_vector->reg_idx));
netdev_info(netdev, "tx_timeout: VSI_num: %d, Q %u, NTC: 0x%x, HW_HEAD: 0x%x, NTU: 0x%x, INT: 0x%x\n",
vsi->vsi_num, txqueue, tx_ring->next_to_clean,
- head, tx_ring->next_to_use, val);
+ head, tx_ring->next_to_use, intr);
+
+ ice_prep_tx_hang_report(pf, tx_ring, vsi->vsi_num, head, intr);
}
pf->tx_timeout_last_recovery = jiffies;
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
index 585ce200c60f..d75f0eddd631 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_consts.h
@@ -761,9 +761,9 @@ const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD] = {
/* rx_desk_rsgb_par */
644531250, /* 644.53125 MHz Reed Solomon gearbox */
/* tx_desk_rsgb_pcs */
- 644531250, /* 644.53125 MHz Reed Solomon gearbox */
+ 390625000, /* 390.625 MHz Reed Solomon gearbox */
/* rx_desk_rsgb_pcs */
- 644531250, /* 644.53125 MHz Reed Solomon gearbox */
+ 390625000, /* 390.625 MHz Reed Solomon gearbox */
/* tx_fixed_delay */
1620,
/* pmd_adj_divisor */
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
index dfd49732bd5b..518893f23372 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
@@ -1518,7 +1518,8 @@ static int ice_read_ptp_tstamp_eth56g(struct ice_hw *hw, u8 port, u8 idx,
* lower 8 bits in the low register, and the upper 32 bits in the high
* register.
*/
- *tstamp = ((u64)hi) << TS_PHY_HIGH_S | ((u64)lo & TS_PHY_LOW_M);
+ *tstamp = FIELD_PREP(TS_PHY_HIGH_M, hi) |
+ FIELD_PREP(TS_PHY_LOW_M, lo);
return 0;
}
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
index 47af7c5c79b8..1cee0f1bba2d 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
@@ -682,9 +682,8 @@ static inline bool ice_is_dual(struct ice_hw *hw)
#define TS_HIGH_M 0xFF
#define TS_HIGH_S 32
-#define TS_PHY_LOW_M 0xFF
-#define TS_PHY_HIGH_M 0xFFFFFFFF
-#define TS_PHY_HIGH_S 8
+#define TS_PHY_LOW_M GENMASK(7, 0)
+#define TS_PHY_HIGH_M GENMASK_ULL(39, 8)
#define BYTES_PER_IDX_ADDR_L_U 8
#define BYTES_PER_IDX_ADDR_L 4
diff --git a/drivers/net/ethernet/intel/ice/ice_repr.c b/drivers/net/ethernet/intel/ice/ice_repr.c
index 970a99a52bf1..fb7a1b9a4313 100644
--- a/drivers/net/ethernet/intel/ice/ice_repr.c
+++ b/drivers/net/ethernet/intel/ice/ice_repr.c
@@ -4,7 +4,7 @@
#include "ice.h"
#include "ice_eswitch.h"
#include "devlink/devlink.h"
-#include "devlink/devlink_port.h"
+#include "devlink/port.h"
#include "ice_sriov.h"
#include "ice_tc_lib.h"
#include "ice_dcb_lib.h"
diff --git a/drivers/net/ethernet/intel/ice/ice_sf_eth.c b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
index 75d7147e1c01..1a2c94375ca7 100644
--- a/drivers/net/ethernet/intel/ice/ice_sf_eth.c
+++ b/drivers/net/ethernet/intel/ice/ice_sf_eth.c
@@ -5,8 +5,8 @@
#include "ice_txrx.h"
#include "ice_fltr.h"
#include "ice_sf_eth.h"
-#include "devlink/devlink_port.h"
#include "devlink/devlink.h"
+#include "devlink/port.h"
static const struct net_device_ops ice_sf_netdev_ops = {
.ndo_open = ice_open,
diff --git a/drivers/net/ethernet/intel/ice/ice_virtchnl.c b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
index f445e33b2028..ff4ad788d96a 100644
--- a/drivers/net/ethernet/intel/ice/ice_virtchnl.c
+++ b/drivers/net/ethernet/intel/ice/ice_virtchnl.c
@@ -4128,6 +4128,9 @@ static const struct ice_virtchnl_ops ice_virtchnl_dflt_ops = {
.get_qos_caps = ice_vc_get_qos_caps,
.cfg_q_bw = ice_vc_cfg_q_bw,
.cfg_q_quanta = ice_vc_cfg_q_quanta,
+ /* If you add a new op here please make sure to add it to
+ * ice_virtchnl_repr_ops as well.
+ */
};
/**
@@ -4258,6 +4261,9 @@ static const struct ice_virtchnl_ops ice_virtchnl_repr_ops = {
.dis_vlan_stripping_v2_msg = ice_vc_dis_vlan_stripping_v2_msg,
.ena_vlan_insertion_v2_msg = ice_vc_ena_vlan_insertion_v2_msg,
.dis_vlan_insertion_v2_msg = ice_vc_dis_vlan_insertion_v2_msg,
+ .get_qos_caps = ice_vc_get_qos_caps,
+ .cfg_q_bw = ice_vc_cfg_q_bw,
+ .cfg_q_quanta = ice_vc_cfg_q_quanta,
};
/**
diff --git a/drivers/net/ethernet/intel/ice/ice_xsk.c b/drivers/net/ethernet/intel/ice/ice_xsk.c
index 334ae945d640..8975d2971bc3 100644
--- a/drivers/net/ethernet/intel/ice/ice_xsk.c
+++ b/drivers/net/ethernet/intel/ice/ice_xsk.c
@@ -801,35 +801,6 @@ out_failure:
return result;
}
-static int
-ice_add_xsk_frag(struct ice_rx_ring *rx_ring, struct xdp_buff *first,
- struct xdp_buff *xdp, const unsigned int size)
-{
- struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(first);
-
- if (!size)
- return 0;
-
- if (!xdp_buff_has_frags(first)) {
- sinfo->nr_frags = 0;
- sinfo->xdp_frags_size = 0;
- xdp_buff_set_frags_flag(first);
- }
-
- if (unlikely(sinfo->nr_frags == MAX_SKB_FRAGS)) {
- xsk_buff_free(first);
- return -ENOMEM;
- }
-
- __skb_fill_page_desc_noacc(sinfo, sinfo->nr_frags++,
- virt_to_page(xdp->data_hard_start),
- XDP_PACKET_HEADROOM, size);
- sinfo->xdp_frags_size += size;
- xsk_buff_add_frag(xdp);
-
- return 0;
-}
-
/**
* ice_clean_rx_irq_zc - consumes packets from the hardware ring
* @rx_ring: AF_XDP Rx ring
@@ -895,7 +866,8 @@ int ice_clean_rx_irq_zc(struct ice_rx_ring *rx_ring,
if (!first) {
first = xdp;
- } else if (ice_add_xsk_frag(rx_ring, first, xdp, size)) {
+ } else if (likely(size) && !xsk_buff_add_frag(first, xdp)) {
+ xsk_buff_free(first);
break;
}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_dev.c b/drivers/net/ethernet/intel/idpf/idpf_dev.c
index 6c913a703df6..41e4bd49402a 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_dev.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_dev.c
@@ -101,6 +101,9 @@ static int idpf_intr_reg_init(struct idpf_vport *vport)
intr->dyn_ctl_itridx_s = PF_GLINT_DYN_CTL_ITR_INDX_S;
intr->dyn_ctl_intrvl_s = PF_GLINT_DYN_CTL_INTERVAL_S;
intr->dyn_ctl_wb_on_itr_m = PF_GLINT_DYN_CTL_WB_ON_ITR_M;
+ intr->dyn_ctl_swint_trig_m = PF_GLINT_DYN_CTL_SWINT_TRIG_M;
+ intr->dyn_ctl_sw_itridx_ena_m =
+ PF_GLINT_DYN_CTL_SW_ITR_INDX_ENA_M;
spacing = IDPF_ITR_IDX_SPACING(reg_vals[vec_id].itrn_index_spacing,
IDPF_PF_ITR_IDX_SPACING);
diff --git a/drivers/net/ethernet/intel/idpf/idpf_main.c b/drivers/net/ethernet/intel/idpf/idpf_main.c
index db476b3314c8..f71d3182580b 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_main.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_main.c
@@ -8,7 +8,7 @@
#define DRV_SUMMARY "Intel(R) Infrastructure Data Path Function Linux Driver"
MODULE_DESCRIPTION(DRV_SUMMARY);
-MODULE_IMPORT_NS(LIBETH);
+MODULE_IMPORT_NS("LIBETH");
MODULE_LICENSE("GPL");
/**
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.c b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
index da2a5becf62f..2fa9c36e33c9 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.c
@@ -2448,6 +2448,7 @@ static void idpf_tx_splitq_map(struct idpf_tx_queue *tx_q,
* rest of the packet.
*/
tx_buf->type = LIBETH_SQE_EMPTY;
+ idpf_tx_buf_compl_tag(tx_buf) = params->compl_tag;
/* Adjust the DMA offset and the remaining size of the
* fragment. On the first iteration of this loop,
@@ -3603,21 +3604,31 @@ static void idpf_vport_intr_dis_irq_all(struct idpf_vport *vport)
/**
* idpf_vport_intr_buildreg_itr - Enable default interrupt generation settings
* @q_vector: pointer to q_vector
- * @type: itr index
- * @itr: itr value
*/
-static u32 idpf_vport_intr_buildreg_itr(struct idpf_q_vector *q_vector,
- const int type, u16 itr)
+static u32 idpf_vport_intr_buildreg_itr(struct idpf_q_vector *q_vector)
{
- u32 itr_val;
+ u32 itr_val = q_vector->intr_reg.dyn_ctl_intena_m;
+ int type = IDPF_NO_ITR_UPDATE_IDX;
+ u16 itr = 0;
+
+ if (q_vector->wb_on_itr) {
+ /*
+ * Trigger a software interrupt when exiting wb_on_itr, to make
+ * sure we catch any pending write backs that might have been
+ * missed due to interrupt state transition.
+ */
+ itr_val |= q_vector->intr_reg.dyn_ctl_swint_trig_m |
+ q_vector->intr_reg.dyn_ctl_sw_itridx_ena_m;
+ type = IDPF_SW_ITR_UPDATE_IDX;
+ itr = IDPF_ITR_20K;
+ }
itr &= IDPF_ITR_MASK;
/* Don't clear PBA because that can cause lost interrupts that
* came in while we were cleaning/polling
*/
- itr_val = q_vector->intr_reg.dyn_ctl_intena_m |
- (type << q_vector->intr_reg.dyn_ctl_itridx_s) |
- (itr << (q_vector->intr_reg.dyn_ctl_intrvl_s - 1));
+ itr_val |= (type << q_vector->intr_reg.dyn_ctl_itridx_s) |
+ (itr << (q_vector->intr_reg.dyn_ctl_intrvl_s - 1));
return itr_val;
}
@@ -3715,9 +3726,8 @@ void idpf_vport_intr_update_itr_ena_irq(struct idpf_q_vector *q_vector)
/* net_dim() updates ITR out-of-band using a work item */
idpf_net_dim(q_vector);
+ intval = idpf_vport_intr_buildreg_itr(q_vector);
q_vector->wb_on_itr = false;
- intval = idpf_vport_intr_buildreg_itr(q_vector,
- IDPF_NO_ITR_UPDATE_IDX, 0);
writel(intval, q_vector->intr_reg.dyn_ctl);
}
diff --git a/drivers/net/ethernet/intel/idpf/idpf_txrx.h b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
index 9c1fe84108ed..0f71a6f5557b 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_txrx.h
+++ b/drivers/net/ethernet/intel/idpf/idpf_txrx.h
@@ -354,6 +354,8 @@ struct idpf_vec_regs {
* @dyn_ctl_itridx_m: Mask for ITR index
* @dyn_ctl_intrvl_s: Register bit offset for ITR interval
* @dyn_ctl_wb_on_itr_m: Mask for WB on ITR feature
+ * @dyn_ctl_sw_itridx_ena_m: Mask for SW ITR index
+ * @dyn_ctl_swint_trig_m: Mask for dyn_ctl SW triggered interrupt enable
* @rx_itr: RX ITR register
* @tx_itr: TX ITR register
* @icr_ena: Interrupt cause register offset
@@ -367,6 +369,8 @@ struct idpf_intr_reg {
u32 dyn_ctl_itridx_m;
u32 dyn_ctl_intrvl_s;
u32 dyn_ctl_wb_on_itr_m;
+ u32 dyn_ctl_sw_itridx_ena_m;
+ u32 dyn_ctl_swint_trig_m;
void __iomem *rx_itr;
void __iomem *tx_itr;
void __iomem *icr_ena;
@@ -437,7 +441,7 @@ struct idpf_q_vector {
cpumask_var_t affinity_mask;
__cacheline_group_end_aligned(cold);
};
-libeth_cacheline_set_assert(struct idpf_q_vector, 112,
+libeth_cacheline_set_assert(struct idpf_q_vector, 120,
24 + sizeof(struct napi_struct) +
2 * sizeof(struct dim),
8 + sizeof(cpumask_var_t));
@@ -471,6 +475,8 @@ struct idpf_tx_queue_stats {
#define IDPF_ITR_IS_DYNAMIC(itr_mode) (itr_mode)
#define IDPF_ITR_TX_DEF IDPF_ITR_20K
#define IDPF_ITR_RX_DEF IDPF_ITR_20K
+/* Index used for 'SW ITR' update in DYN_CTL register */
+#define IDPF_SW_ITR_UPDATE_IDX 2
/* Index used for 'No ITR' update in DYN_CTL register */
#define IDPF_NO_ITR_UPDATE_IDX 3
#define IDPF_ITR_IDX_SPACING(spacing, dflt) (spacing ? spacing : dflt)
diff --git a/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c b/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
index aad62e270ae4..aba828abcb17 100644
--- a/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
+++ b/drivers/net/ethernet/intel/idpf/idpf_vf_dev.c
@@ -101,6 +101,9 @@ static int idpf_vf_intr_reg_init(struct idpf_vport *vport)
intr->dyn_ctl_itridx_s = VF_INT_DYN_CTLN_ITR_INDX_S;
intr->dyn_ctl_intrvl_s = VF_INT_DYN_CTLN_INTERVAL_S;
intr->dyn_ctl_wb_on_itr_m = VF_INT_DYN_CTLN_WB_ON_ITR_M;
+ intr->dyn_ctl_swint_trig_m = VF_INT_DYN_CTLN_SWINT_TRIG_M;
+ intr->dyn_ctl_sw_itridx_ena_m =
+ VF_INT_DYN_CTLN_SW_ITR_INDX_ENA_M;
spacing = IDPF_ITR_IDX_SPACING(reg_vals[vec_id].itrn_index_spacing,
IDPF_VF_ITR_IDX_SPACING);
diff --git a/drivers/net/ethernet/intel/igb/Makefile b/drivers/net/ethernet/intel/igb/Makefile
index 463c0d26b9d4..6c1b702fd992 100644
--- a/drivers/net/ethernet/intel/igb/Makefile
+++ b/drivers/net/ethernet/intel/igb/Makefile
@@ -8,4 +8,4 @@ obj-$(CONFIG_IGB) += igb.o
igb-y := igb_main.o igb_ethtool.o e1000_82575.o \
e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o \
- e1000_i210.o igb_ptp.o igb_hwmon.o
+ e1000_i210.o igb_ptp.o igb_hwmon.o igb_xsk.o
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 3c2dc7bdebb5..02f340280d20 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -18,8 +18,10 @@
#include <linux/i2c-algo-bit.h>
#include <linux/pci.h>
#include <linux/mdio.h>
+#include <linux/lockdep.h>
#include <net/xdp.h>
+#include <net/xdp_sock_drv.h>
struct igb_adapter;
@@ -86,6 +88,7 @@ struct igb_adapter;
#define IGB_XDP_CONSUMED BIT(0)
#define IGB_XDP_TX BIT(1)
#define IGB_XDP_REDIR BIT(2)
+#define IGB_XDP_EXIT BIT(3)
struct vf_data_storage {
unsigned char vf_mac_addresses[ETH_ALEN];
@@ -255,6 +258,7 @@ enum igb_tx_flags {
enum igb_tx_buf_type {
IGB_TYPE_SKB = 0,
IGB_TYPE_XDP,
+ IGB_TYPE_XSK
};
/* wrapper around a pointer to a socket buffer,
@@ -320,6 +324,7 @@ struct igb_ring {
union { /* array of buffer info structs */
struct igb_tx_buffer *tx_buffer_info;
struct igb_rx_buffer *rx_buffer_info;
+ struct xdp_buff **rx_buffer_info_zc;
};
void *desc; /* descriptor ring memory */
unsigned long flags; /* ring specific flags */
@@ -357,6 +362,7 @@ struct igb_ring {
};
};
struct xdp_rxq_info xdp_rxq;
+ struct xsk_buff_pool *xsk_pool;
} ____cacheline_internodealigned_in_smp;
struct igb_q_vector {
@@ -384,7 +390,8 @@ enum e1000_ring_flags_t {
IGB_RING_FLAG_RX_SCTP_CSUM,
IGB_RING_FLAG_RX_LB_VLAN_BSWAP,
IGB_RING_FLAG_TX_CTX_IDX,
- IGB_RING_FLAG_TX_DETECT_HANG
+ IGB_RING_FLAG_TX_DETECT_HANG,
+ IGB_RING_FLAG_TX_DISABLED
};
#define ring_uses_large_buffer(ring) \
@@ -731,12 +738,21 @@ int igb_setup_tx_resources(struct igb_ring *);
int igb_setup_rx_resources(struct igb_ring *);
void igb_free_tx_resources(struct igb_ring *);
void igb_free_rx_resources(struct igb_ring *);
+void igb_clean_tx_ring(struct igb_ring *tx_ring);
+void igb_clean_rx_ring(struct igb_ring *rx_ring);
void igb_configure_tx_ring(struct igb_adapter *, struct igb_ring *);
void igb_configure_rx_ring(struct igb_adapter *, struct igb_ring *);
+void igb_finalize_xdp(struct igb_adapter *adapter, unsigned int status);
+void igb_update_rx_stats(struct igb_q_vector *q_vector, unsigned int packets,
+ unsigned int bytes);
void igb_setup_tctl(struct igb_adapter *);
void igb_setup_rctl(struct igb_adapter *);
void igb_setup_srrctl(struct igb_adapter *, struct igb_ring *);
netdev_tx_t igb_xmit_frame_ring(struct sk_buff *, struct igb_ring *);
+int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp);
+void igb_process_skb_fields(struct igb_ring *rx_ring,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb);
void igb_alloc_rx_buffers(struct igb_ring *, u16);
void igb_update_stats(struct igb_adapter *);
bool igb_has_link(struct igb_adapter *adapter);
@@ -797,6 +813,33 @@ static inline struct netdev_queue *txring_txq(const struct igb_ring *tx_ring)
return netdev_get_tx_queue(tx_ring->netdev, tx_ring->queue_index);
}
+/* This function assumes __netif_tx_lock is held by the caller. */
+static inline void igb_xdp_ring_update_tail(struct igb_ring *ring)
+{
+ lockdep_assert_held(&txring_txq(ring)->_xmit_lock);
+
+ /* Force memory writes to complete before letting h/w know there
+ * are new descriptors to fetch.
+ */
+ wmb();
+ writel(ring->next_to_use, ring->tail);
+}
+
+static inline struct igb_ring *igb_xdp_tx_queue_mapping(struct igb_adapter *adapter)
+{
+ unsigned int r_idx = smp_processor_id();
+
+ if (r_idx >= adapter->num_tx_queues)
+ r_idx = r_idx % adapter->num_tx_queues;
+
+ return adapter->tx_ring[r_idx];
+}
+
+static inline bool igb_xdp_is_enabled(struct igb_adapter *adapter)
+{
+ return !!READ_ONCE(adapter->xdp_prog);
+}
+
int igb_add_filter(struct igb_adapter *adapter,
struct igb_nfc_filter *input);
int igb_erase_filter(struct igb_adapter *adapter,
@@ -807,4 +850,17 @@ int igb_add_mac_steering_filter(struct igb_adapter *adapter,
int igb_del_mac_steering_filter(struct igb_adapter *adapter,
const u8 *addr, u8 queue, u8 flags);
+struct xsk_buff_pool *igb_xsk_pool(struct igb_adapter *adapter,
+ struct igb_ring *ring);
+int igb_xsk_pool_setup(struct igb_adapter *adapter,
+ struct xsk_buff_pool *pool,
+ u16 qid);
+bool igb_alloc_rx_buffers_zc(struct igb_ring *rx_ring,
+ struct xsk_buff_pool *xsk_pool, u16 count);
+void igb_clean_rx_ring_zc(struct igb_ring *rx_ring);
+int igb_clean_rx_irq_zc(struct igb_q_vector *q_vector,
+ struct xsk_buff_pool *xsk_pool, const int budget);
+bool igb_xmit_zc(struct igb_ring *tx_ring, struct xsk_buff_pool *xsk_pool);
+int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags);
+
#endif /* _IGB_H_ */
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 08578980b651..d368b753a467 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -33,7 +33,6 @@
#include <linux/bpf_trace.h>
#include <linux/pm_runtime.h>
#include <linux/etherdevice.h>
-#include <linux/lockdep.h>
#ifdef CONFIG_IGB_DCA
#include <linux/dca.h>
#endif
@@ -116,8 +115,6 @@ static void igb_configure_tx(struct igb_adapter *);
static void igb_configure_rx(struct igb_adapter *);
static void igb_clean_all_tx_rings(struct igb_adapter *);
static void igb_clean_all_rx_rings(struct igb_adapter *);
-static void igb_clean_tx_ring(struct igb_ring *);
-static void igb_clean_rx_ring(struct igb_ring *);
static void igb_set_rx_mode(struct net_device *);
static void igb_update_phy_info(struct timer_list *);
static void igb_watchdog(struct timer_list *);
@@ -475,12 +472,17 @@ rx_ring_summary:
for (i = 0; i < rx_ring->count; i++) {
const char *next_desc;
- struct igb_rx_buffer *buffer_info;
- buffer_info = &rx_ring->rx_buffer_info[i];
+ dma_addr_t dma = (dma_addr_t)0;
+ struct igb_rx_buffer *buffer_info = NULL;
rx_desc = IGB_RX_DESC(rx_ring, i);
u0 = (struct my_u0 *)rx_desc;
staterr = le32_to_cpu(rx_desc->wb.upper.status_error);
+ if (!rx_ring->xsk_pool) {
+ buffer_info = &rx_ring->rx_buffer_info[i];
+ dma = buffer_info->dma;
+ }
+
if (i == rx_ring->next_to_use)
next_desc = " NTU";
else if (i == rx_ring->next_to_clean)
@@ -500,11 +502,11 @@ rx_ring_summary:
"R ", i,
le64_to_cpu(u0->a),
le64_to_cpu(u0->b),
- (u64)buffer_info->dma,
+ (u64)dma,
next_desc);
if (netif_msg_pktdata(adapter) &&
- buffer_info->dma && buffer_info->page) {
+ buffer_info && dma && buffer_info->page) {
print_hex_dump(KERN_INFO, "",
DUMP_PREFIX_ADDRESS,
16, 1,
@@ -637,6 +639,10 @@ static int __init igb_init_module(void)
dca_register_notify(&dca_notifier);
#endif
ret = pci_register_driver(&igb_driver);
+#ifdef CONFIG_IGB_DCA
+ if (ret)
+ dca_unregister_notify(&dca_notifier);
+#endif
return ret;
}
@@ -1986,7 +1992,11 @@ static void igb_configure(struct igb_adapter *adapter)
*/
for (i = 0; i < adapter->num_rx_queues; i++) {
struct igb_ring *ring = adapter->rx_ring[i];
- igb_alloc_rx_buffers(ring, igb_desc_unused(ring));
+ if (ring->xsk_pool)
+ igb_alloc_rx_buffers_zc(ring, ring->xsk_pool,
+ igb_desc_unused(ring));
+ else
+ igb_alloc_rx_buffers(ring, igb_desc_unused(ring));
}
}
@@ -2907,37 +2917,20 @@ static int igb_xdp_setup(struct net_device *dev, struct netdev_bpf *bpf)
static int igb_xdp(struct net_device *dev, struct netdev_bpf *xdp)
{
+ struct igb_adapter *adapter = netdev_priv(dev);
+
switch (xdp->command) {
case XDP_SETUP_PROG:
return igb_xdp_setup(dev, xdp);
+ case XDP_SETUP_XSK_POOL:
+ return igb_xsk_pool_setup(adapter, xdp->xsk.pool,
+ xdp->xsk.queue_id);
default:
return -EINVAL;
}
}
-/* This function assumes __netif_tx_lock is held by the caller. */
-static void igb_xdp_ring_update_tail(struct igb_ring *ring)
-{
- lockdep_assert_held(&txring_txq(ring)->_xmit_lock);
-
- /* Force memory writes to complete before letting h/w know there
- * are new descriptors to fetch.
- */
- wmb();
- writel(ring->next_to_use, ring->tail);
-}
-
-static struct igb_ring *igb_xdp_tx_queue_mapping(struct igb_adapter *adapter)
-{
- unsigned int r_idx = smp_processor_id();
-
- if (r_idx >= adapter->num_tx_queues)
- r_idx = r_idx % adapter->num_tx_queues;
-
- return adapter->tx_ring[r_idx];
-}
-
-static int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp)
+int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp)
{
struct xdp_frame *xdpf = xdp_convert_buff_to_frame(xdp);
int cpu = smp_processor_id();
@@ -2951,7 +2944,8 @@ static int igb_xdp_xmit_back(struct igb_adapter *adapter, struct xdp_buff *xdp)
/* During program transitions its possible adapter->xdp_prog is assigned
* but ring has not been configured yet. In this case simply abort xmit.
*/
- tx_ring = adapter->xdp_prog ? igb_xdp_tx_queue_mapping(adapter) : NULL;
+ tx_ring = igb_xdp_is_enabled(adapter) ?
+ igb_xdp_tx_queue_mapping(adapter) : NULL;
if (unlikely(!tx_ring))
return IGB_XDP_CONSUMED;
@@ -2984,10 +2978,14 @@ static int igb_xdp_xmit(struct net_device *dev, int n,
/* During program transitions its possible adapter->xdp_prog is assigned
* but ring has not been configured yet. In this case simply abort xmit.
*/
- tx_ring = adapter->xdp_prog ? igb_xdp_tx_queue_mapping(adapter) : NULL;
+ tx_ring = igb_xdp_is_enabled(adapter) ?
+ igb_xdp_tx_queue_mapping(adapter) : NULL;
if (unlikely(!tx_ring))
return -ENXIO;
+ if (unlikely(test_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags)))
+ return -ENXIO;
+
nq = txring_txq(tx_ring);
__netif_tx_lock(nq, cpu);
@@ -3038,6 +3036,7 @@ static const struct net_device_ops igb_netdev_ops = {
.ndo_setup_tc = igb_setup_tc,
.ndo_bpf = igb_xdp,
.ndo_xdp_xmit = igb_xdp_xmit,
+ .ndo_xsk_wakeup = igb_xsk_wakeup,
};
/**
@@ -3334,7 +3333,8 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
netdev->priv_flags |= IFF_SUPP_NOFCS;
netdev->priv_flags |= IFF_UNICAST_FLT;
- netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT;
+ netdev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT |
+ NETDEV_XDP_ACT_XSK_ZEROCOPY;
/* MTU range: 68 - 9216 */
netdev->min_mtu = ETH_MIN_MTU;
@@ -4360,6 +4360,8 @@ void igb_configure_tx_ring(struct igb_adapter *adapter,
u64 tdba = ring->dma;
int reg_idx = ring->reg_idx;
+ WRITE_ONCE(ring->xsk_pool, igb_xsk_pool(adapter, ring));
+
wr32(E1000_TDLEN(reg_idx),
ring->count * sizeof(union e1000_adv_tx_desc));
wr32(E1000_TDBAL(reg_idx),
@@ -4420,7 +4422,8 @@ int igb_setup_rx_resources(struct igb_ring *rx_ring)
if (xdp_rxq_info_is_reg(&rx_ring->xdp_rxq))
xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
res = xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev,
- rx_ring->queue_index, 0);
+ rx_ring->queue_index,
+ rx_ring->q_vector->napi.napi_id);
if (res < 0) {
dev_err(dev, "Failed to register xdp_rxq index %u\n",
rx_ring->queue_index);
@@ -4716,12 +4719,17 @@ void igb_setup_srrctl(struct igb_adapter *adapter, struct igb_ring *ring)
struct e1000_hw *hw = &adapter->hw;
int reg_idx = ring->reg_idx;
u32 srrctl = 0;
+ u32 buf_size;
- srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
- if (ring_uses_large_buffer(ring))
- srrctl |= IGB_RXBUFFER_3072 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+ if (ring->xsk_pool)
+ buf_size = xsk_pool_get_rx_frame_size(ring->xsk_pool);
+ else if (ring_uses_large_buffer(ring))
+ buf_size = IGB_RXBUFFER_3072;
else
- srrctl |= IGB_RXBUFFER_2048 >> E1000_SRRCTL_BSIZEPKT_SHIFT;
+ buf_size = IGB_RXBUFFER_2048;
+
+ srrctl = IGB_RX_HDR_LEN << E1000_SRRCTL_BSIZEHDRSIZE_SHIFT;
+ srrctl |= buf_size >> E1000_SRRCTL_BSIZEPKT_SHIFT;
srrctl |= E1000_SRRCTL_DESCTYPE_ADV_ONEBUF;
if (hw->mac.type >= e1000_82580)
srrctl |= E1000_SRRCTL_TIMESTAMP;
@@ -4753,8 +4761,17 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
u32 rxdctl = 0;
xdp_rxq_info_unreg_mem_model(&ring->xdp_rxq);
- WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
- MEM_TYPE_PAGE_SHARED, NULL));
+ WRITE_ONCE(ring->xsk_pool, igb_xsk_pool(adapter, ring));
+ if (ring->xsk_pool) {
+ WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
+ MEM_TYPE_XSK_BUFF_POOL,
+ NULL));
+ xsk_pool_set_rxq_info(ring->xsk_pool, &ring->xdp_rxq);
+ } else {
+ WARN_ON(xdp_rxq_info_reg_mem_model(&ring->xdp_rxq,
+ MEM_TYPE_PAGE_SHARED,
+ NULL));
+ }
/* disable the queue */
wr32(E1000_RXDCTL(reg_idx), 0);
@@ -4781,9 +4798,12 @@ void igb_configure_rx_ring(struct igb_adapter *adapter,
rxdctl |= IGB_RX_HTHRESH << 8;
rxdctl |= IGB_RX_WTHRESH << 16;
- /* initialize rx_buffer_info */
- memset(ring->rx_buffer_info, 0,
- sizeof(struct igb_rx_buffer) * ring->count);
+ if (ring->xsk_pool)
+ memset(ring->rx_buffer_info_zc, 0,
+ sizeof(*ring->rx_buffer_info_zc) * ring->count);
+ else
+ memset(ring->rx_buffer_info, 0,
+ sizeof(*ring->rx_buffer_info) * ring->count);
/* initialize Rx descriptor 0 */
rx_desc = IGB_RX_DESC(ring, 0);
@@ -4884,19 +4904,24 @@ static void igb_free_all_tx_resources(struct igb_adapter *adapter)
* igb_clean_tx_ring - Free Tx Buffers
* @tx_ring: ring to be cleaned
**/
-static void igb_clean_tx_ring(struct igb_ring *tx_ring)
+void igb_clean_tx_ring(struct igb_ring *tx_ring)
{
u16 i = tx_ring->next_to_clean;
struct igb_tx_buffer *tx_buffer = &tx_ring->tx_buffer_info[i];
+ u32 xsk_frames = 0;
while (i != tx_ring->next_to_use) {
union e1000_adv_tx_desc *eop_desc, *tx_desc;
/* Free all the Tx ring sk_buffs or xdp frames */
- if (tx_buffer->type == IGB_TYPE_SKB)
+ if (tx_buffer->type == IGB_TYPE_SKB) {
dev_kfree_skb_any(tx_buffer->skb);
- else
+ } else if (tx_buffer->type == IGB_TYPE_XDP) {
xdp_return_frame(tx_buffer->xdpf);
+ } else if (tx_buffer->type == IGB_TYPE_XSK) {
+ xsk_frames++;
+ goto skip_for_xsk;
+ }
/* unmap skb header data */
dma_unmap_single(tx_ring->dev,
@@ -4927,6 +4952,7 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
DMA_TO_DEVICE);
}
+skip_for_xsk:
tx_buffer->next_to_watch = NULL;
/* move us one more past the eop_desc for start of next pkt */
@@ -4941,6 +4967,9 @@ static void igb_clean_tx_ring(struct igb_ring *tx_ring)
/* reset BQL for queue */
netdev_tx_reset_queue(txring_txq(tx_ring));
+ if (tx_ring->xsk_pool && xsk_frames)
+ xsk_tx_completed(tx_ring->xsk_pool, xsk_frames);
+
/* reset next_to_use and next_to_clean */
tx_ring->next_to_use = 0;
tx_ring->next_to_clean = 0;
@@ -4971,8 +5000,13 @@ void igb_free_rx_resources(struct igb_ring *rx_ring)
rx_ring->xdp_prog = NULL;
xdp_rxq_info_unreg(&rx_ring->xdp_rxq);
- vfree(rx_ring->rx_buffer_info);
- rx_ring->rx_buffer_info = NULL;
+ if (rx_ring->xsk_pool) {
+ vfree(rx_ring->rx_buffer_info_zc);
+ rx_ring->rx_buffer_info_zc = NULL;
+ } else {
+ vfree(rx_ring->rx_buffer_info);
+ rx_ring->rx_buffer_info = NULL;
+ }
/* if not set, then don't free */
if (!rx_ring->desc)
@@ -5003,13 +5037,18 @@ static void igb_free_all_rx_resources(struct igb_adapter *adapter)
* igb_clean_rx_ring - Free Rx Buffers per Queue
* @rx_ring: ring to free buffers from
**/
-static void igb_clean_rx_ring(struct igb_ring *rx_ring)
+void igb_clean_rx_ring(struct igb_ring *rx_ring)
{
u16 i = rx_ring->next_to_clean;
dev_kfree_skb(rx_ring->skb);
rx_ring->skb = NULL;
+ if (rx_ring->xsk_pool) {
+ igb_clean_rx_ring_zc(rx_ring);
+ goto skip_for_xsk;
+ }
+
/* Free all the Rx ring sk_buffs */
while (i != rx_ring->next_to_alloc) {
struct igb_rx_buffer *buffer_info = &rx_ring->rx_buffer_info[i];
@@ -5037,6 +5076,7 @@ static void igb_clean_rx_ring(struct igb_ring *rx_ring)
i = 0;
}
+skip_for_xsk:
rx_ring->next_to_alloc = 0;
rx_ring->next_to_clean = 0;
rx_ring->next_to_use = 0;
@@ -6463,6 +6503,9 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
return NETDEV_TX_BUSY;
}
+ if (unlikely(test_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags)))
+ return NETDEV_TX_BUSY;
+
/* record the location of the first descriptor for this packet */
first = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
first->type = IGB_TYPE_SKB;
@@ -6618,7 +6661,7 @@ static int igb_change_mtu(struct net_device *netdev, int new_mtu)
struct igb_adapter *adapter = netdev_priv(netdev);
int max_frame = new_mtu + IGB_ETH_PKT_HDR_PAD;
- if (adapter->xdp_prog) {
+ if (igb_xdp_is_enabled(adapter)) {
int i;
for (i = 0; i < adapter->num_rx_queues; i++) {
@@ -8191,6 +8234,7 @@ static int igb_poll(struct napi_struct *napi, int budget)
struct igb_q_vector *q_vector = container_of(napi,
struct igb_q_vector,
napi);
+ struct xsk_buff_pool *xsk_pool;
bool clean_complete = true;
int work_done = 0;
@@ -8202,7 +8246,12 @@ static int igb_poll(struct napi_struct *napi, int budget)
clean_complete = igb_clean_tx_irq(q_vector, budget);
if (q_vector->rx.ring) {
- int cleaned = igb_clean_rx_irq(q_vector, budget);
+ int cleaned;
+
+ xsk_pool = READ_ONCE(q_vector->rx.ring->xsk_pool);
+ cleaned = xsk_pool ?
+ igb_clean_rx_irq_zc(q_vector, xsk_pool, budget) :
+ igb_clean_rx_irq(q_vector, budget);
work_done += cleaned;
if (cleaned >= budget)
@@ -8231,13 +8280,18 @@ static int igb_poll(struct napi_struct *napi, int budget)
**/
static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
{
- struct igb_adapter *adapter = q_vector->adapter;
- struct igb_ring *tx_ring = q_vector->tx.ring;
- struct igb_tx_buffer *tx_buffer;
- union e1000_adv_tx_desc *tx_desc;
unsigned int total_bytes = 0, total_packets = 0;
+ struct igb_adapter *adapter = q_vector->adapter;
unsigned int budget = q_vector->tx.work_limit;
+ struct igb_ring *tx_ring = q_vector->tx.ring;
unsigned int i = tx_ring->next_to_clean;
+ union e1000_adv_tx_desc *tx_desc;
+ struct igb_tx_buffer *tx_buffer;
+ struct xsk_buff_pool *xsk_pool;
+ int cpu = smp_processor_id();
+ bool xsk_xmit_done = true;
+ struct netdev_queue *nq;
+ u32 xsk_frames = 0;
if (test_bit(__IGB_DOWN, &adapter->state))
return true;
@@ -8268,10 +8322,14 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
total_packets += tx_buffer->gso_segs;
/* free the skb */
- if (tx_buffer->type == IGB_TYPE_SKB)
+ if (tx_buffer->type == IGB_TYPE_SKB) {
napi_consume_skb(tx_buffer->skb, napi_budget);
- else
+ } else if (tx_buffer->type == IGB_TYPE_XDP) {
xdp_return_frame(tx_buffer->xdpf);
+ } else if (tx_buffer->type == IGB_TYPE_XSK) {
+ xsk_frames++;
+ goto skip_for_xsk;
+ }
/* unmap skb header data */
dma_unmap_single(tx_ring->dev,
@@ -8303,6 +8361,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
}
}
+skip_for_xsk:
/* move us one more past the eop_desc for start of next pkt */
tx_buffer++;
tx_desc++;
@@ -8331,6 +8390,21 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
q_vector->tx.total_bytes += total_bytes;
q_vector->tx.total_packets += total_packets;
+ xsk_pool = READ_ONCE(tx_ring->xsk_pool);
+ if (xsk_pool) {
+ if (xsk_frames)
+ xsk_tx_completed(xsk_pool, xsk_frames);
+ if (xsk_uses_need_wakeup(xsk_pool))
+ xsk_set_tx_need_wakeup(xsk_pool);
+
+ nq = txring_txq(tx_ring);
+ __netif_tx_lock(nq, cpu);
+ /* Avoid transmit queue timeout since we share it with the slow path */
+ txq_trans_cond_update(nq);
+ xsk_xmit_done = igb_xmit_zc(tx_ring, xsk_pool);
+ __netif_tx_unlock(nq);
+ }
+
if (test_bit(IGB_RING_FLAG_TX_DETECT_HANG, &tx_ring->flags)) {
struct e1000_hw *hw = &adapter->hw;
@@ -8393,7 +8467,7 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector, int napi_budget)
}
}
- return !!budget;
+ return !!budget && xsk_xmit_done;
}
/**
@@ -8584,9 +8658,8 @@ static struct sk_buff *igb_build_skb(struct igb_ring *rx_ring,
return skb;
}
-static struct sk_buff *igb_run_xdp(struct igb_adapter *adapter,
- struct igb_ring *rx_ring,
- struct xdp_buff *xdp)
+static int igb_run_xdp(struct igb_adapter *adapter, struct igb_ring *rx_ring,
+ struct xdp_buff *xdp)
{
int err, result = IGB_XDP_PASS;
struct bpf_prog *xdp_prog;
@@ -8626,7 +8699,7 @@ out_failure:
break;
}
xdp_out:
- return ERR_PTR(-result);
+ return result;
}
static unsigned int igb_rx_frame_truesize(struct igb_ring *rx_ring,
@@ -8752,10 +8825,6 @@ static bool igb_cleanup_headers(struct igb_ring *rx_ring,
union e1000_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
- /* XDP packets use error pointer so abort at this point */
- if (IS_ERR(skb))
- return true;
-
if (unlikely((igb_test_staterr(rx_desc,
E1000_RXDEXT_ERR_FRAME_ERR_MASK)))) {
struct net_device *netdev = rx_ring->netdev;
@@ -8782,9 +8851,9 @@ static bool igb_cleanup_headers(struct igb_ring *rx_ring,
* order to populate the hash, checksum, VLAN, timestamp, protocol, and
* other fields within the skb.
**/
-static void igb_process_skb_fields(struct igb_ring *rx_ring,
- union e1000_adv_rx_desc *rx_desc,
- struct sk_buff *skb)
+void igb_process_skb_fields(struct igb_ring *rx_ring,
+ union e1000_adv_rx_desc *rx_desc,
+ struct sk_buff *skb)
{
struct net_device *dev = rx_ring->netdev;
@@ -8866,6 +8935,38 @@ static void igb_put_rx_buffer(struct igb_ring *rx_ring,
rx_buffer->page = NULL;
}
+void igb_finalize_xdp(struct igb_adapter *adapter, unsigned int status)
+{
+ int cpu = smp_processor_id();
+ struct netdev_queue *nq;
+
+ if (status & IGB_XDP_REDIR)
+ xdp_do_flush();
+
+ if (status & IGB_XDP_TX) {
+ struct igb_ring *tx_ring = igb_xdp_tx_queue_mapping(adapter);
+
+ nq = txring_txq(tx_ring);
+ __netif_tx_lock(nq, cpu);
+ igb_xdp_ring_update_tail(tx_ring);
+ __netif_tx_unlock(nq);
+ }
+}
+
+void igb_update_rx_stats(struct igb_q_vector *q_vector, unsigned int packets,
+ unsigned int bytes)
+{
+ struct igb_ring *ring = q_vector->rx.ring;
+
+ u64_stats_update_begin(&ring->rx_syncp);
+ ring->rx_stats.packets += packets;
+ ring->rx_stats.bytes += bytes;
+ u64_stats_update_end(&ring->rx_syncp);
+
+ q_vector->rx.total_packets += packets;
+ q_vector->rx.total_bytes += bytes;
+}
+
static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
{
unsigned int total_bytes = 0, total_packets = 0;
@@ -8873,12 +8974,11 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
struct igb_ring *rx_ring = q_vector->rx.ring;
u16 cleaned_count = igb_desc_unused(rx_ring);
struct sk_buff *skb = rx_ring->skb;
- int cpu = smp_processor_id();
unsigned int xdp_xmit = 0;
- struct netdev_queue *nq;
struct xdp_buff xdp;
u32 frame_sz = 0;
int rx_buf_pgcnt;
+ int xdp_res = 0;
/* Frame size depend on rx_ring setup when PAGE_SIZE=4K */
#if (PAGE_SIZE < 8192)
@@ -8936,12 +9036,10 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
/* At larger PAGE_SIZE, frame_sz depend on len size */
xdp.frame_sz = igb_rx_frame_truesize(rx_ring, size);
#endif
- skb = igb_run_xdp(adapter, rx_ring, &xdp);
+ xdp_res = igb_run_xdp(adapter, rx_ring, &xdp);
}
- if (IS_ERR(skb)) {
- unsigned int xdp_res = -PTR_ERR(skb);
-
+ if (xdp_res) {
if (xdp_res & (IGB_XDP_TX | IGB_XDP_REDIR)) {
xdp_xmit |= xdp_res;
igb_rx_buffer_flip(rx_ring, rx_buffer, size);
@@ -8960,7 +9058,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
&xdp, timestamp);
/* exit if we failed to retrieve a buffer */
- if (!skb) {
+ if (!xdp_res && !skb) {
rx_ring->rx_stats.alloc_failed++;
rx_buffer->pagecnt_bias++;
break;
@@ -8974,7 +9072,7 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
continue;
/* verify the packet layout is correct */
- if (igb_cleanup_headers(rx_ring, rx_desc, skb)) {
+ if (xdp_res || igb_cleanup_headers(rx_ring, rx_desc, skb)) {
skb = NULL;
continue;
}
@@ -8997,24 +9095,10 @@ static int igb_clean_rx_irq(struct igb_q_vector *q_vector, const int budget)
/* place incomplete frames back on ring for completion */
rx_ring->skb = skb;
- if (xdp_xmit & IGB_XDP_REDIR)
- xdp_do_flush();
-
- if (xdp_xmit & IGB_XDP_TX) {
- struct igb_ring *tx_ring = igb_xdp_tx_queue_mapping(adapter);
-
- nq = txring_txq(tx_ring);
- __netif_tx_lock(nq, cpu);
- igb_xdp_ring_update_tail(tx_ring);
- __netif_tx_unlock(nq);
- }
+ if (xdp_xmit)
+ igb_finalize_xdp(adapter, xdp_xmit);
- u64_stats_update_begin(&rx_ring->rx_syncp);
- rx_ring->rx_stats.packets += total_packets;
- rx_ring->rx_stats.bytes += total_bytes;
- u64_stats_update_end(&rx_ring->rx_syncp);
- q_vector->rx.total_packets += total_packets;
- q_vector->rx.total_bytes += total_bytes;
+ igb_update_rx_stats(q_vector, total_packets, total_bytes);
if (cleaned_count)
igb_alloc_rx_buffers(rx_ring, cleaned_count);
diff --git a/drivers/net/ethernet/intel/igb/igb_xsk.c b/drivers/net/ethernet/intel/igb/igb_xsk.c
new file mode 100644
index 000000000000..157d43787fa0
--- /dev/null
+++ b/drivers/net/ethernet/intel/igb/igb_xsk.c
@@ -0,0 +1,562 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2018 Intel Corporation. */
+
+#include <linux/bpf_trace.h>
+#include <net/xdp_sock_drv.h>
+#include <net/xdp.h>
+
+#include "e1000_hw.h"
+#include "igb.h"
+
+static int igb_realloc_rx_buffer_info(struct igb_ring *ring, bool pool_present)
+{
+ int size = pool_present ?
+ sizeof(*ring->rx_buffer_info_zc) * ring->count :
+ sizeof(*ring->rx_buffer_info) * ring->count;
+ void *buff_info = vmalloc(size);
+
+ if (!buff_info)
+ return -ENOMEM;
+
+ if (pool_present) {
+ vfree(ring->rx_buffer_info);
+ ring->rx_buffer_info = NULL;
+ ring->rx_buffer_info_zc = buff_info;
+ } else {
+ vfree(ring->rx_buffer_info_zc);
+ ring->rx_buffer_info_zc = NULL;
+ ring->rx_buffer_info = buff_info;
+ }
+
+ return 0;
+}
+
+static void igb_txrx_ring_disable(struct igb_adapter *adapter, u16 qid)
+{
+ struct igb_ring *tx_ring = adapter->tx_ring[qid];
+ struct igb_ring *rx_ring = adapter->rx_ring[qid];
+ struct e1000_hw *hw = &adapter->hw;
+
+ set_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags);
+
+ wr32(E1000_TXDCTL(tx_ring->reg_idx), 0);
+ wr32(E1000_RXDCTL(rx_ring->reg_idx), 0);
+
+ synchronize_net();
+
+ /* Rx/Tx share the same napi context. */
+ napi_disable(&rx_ring->q_vector->napi);
+
+ igb_clean_tx_ring(tx_ring);
+ igb_clean_rx_ring(rx_ring);
+
+ memset(&rx_ring->rx_stats, 0, sizeof(rx_ring->rx_stats));
+ memset(&tx_ring->tx_stats, 0, sizeof(tx_ring->tx_stats));
+}
+
+static void igb_txrx_ring_enable(struct igb_adapter *adapter, u16 qid)
+{
+ struct igb_ring *tx_ring = adapter->tx_ring[qid];
+ struct igb_ring *rx_ring = adapter->rx_ring[qid];
+
+ igb_configure_tx_ring(adapter, tx_ring);
+ igb_configure_rx_ring(adapter, rx_ring);
+
+ synchronize_net();
+
+ clear_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags);
+
+ /* call igb_desc_unused which always leaves
+ * at least 1 descriptor unused to make sure
+ * next_to_use != next_to_clean
+ */
+ if (rx_ring->xsk_pool)
+ igb_alloc_rx_buffers_zc(rx_ring, rx_ring->xsk_pool,
+ igb_desc_unused(rx_ring));
+ else
+ igb_alloc_rx_buffers(rx_ring, igb_desc_unused(rx_ring));
+
+ /* Rx/Tx share the same napi context. */
+ napi_enable(&rx_ring->q_vector->napi);
+}
+
+struct xsk_buff_pool *igb_xsk_pool(struct igb_adapter *adapter,
+ struct igb_ring *ring)
+{
+ int qid = ring->queue_index;
+ struct xsk_buff_pool *pool;
+
+ pool = xsk_get_pool_from_qid(adapter->netdev, qid);
+
+ if (!igb_xdp_is_enabled(adapter))
+ return NULL;
+
+ return (pool && pool->dev) ? pool : NULL;
+}
+
+static int igb_xsk_pool_enable(struct igb_adapter *adapter,
+ struct xsk_buff_pool *pool,
+ u16 qid)
+{
+ struct net_device *netdev = adapter->netdev;
+ struct igb_ring *rx_ring;
+ bool if_running;
+ int err;
+
+ if (qid >= adapter->num_rx_queues)
+ return -EINVAL;
+
+ if (qid >= netdev->real_num_rx_queues ||
+ qid >= netdev->real_num_tx_queues)
+ return -EINVAL;
+
+ err = xsk_pool_dma_map(pool, &adapter->pdev->dev, IGB_RX_DMA_ATTR);
+ if (err)
+ return err;
+
+ rx_ring = adapter->rx_ring[qid];
+ if_running = netif_running(adapter->netdev) && igb_xdp_is_enabled(adapter);
+ if (if_running)
+ igb_txrx_ring_disable(adapter, qid);
+
+ if (if_running) {
+ err = igb_realloc_rx_buffer_info(rx_ring, true);
+ if (!err) {
+ igb_txrx_ring_enable(adapter, qid);
+ /* Kick start the NAPI context so that receiving will start */
+ err = igb_xsk_wakeup(adapter->netdev, qid, XDP_WAKEUP_RX);
+ }
+
+ if (err) {
+ xsk_pool_dma_unmap(pool, IGB_RX_DMA_ATTR);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
+static int igb_xsk_pool_disable(struct igb_adapter *adapter, u16 qid)
+{
+ struct xsk_buff_pool *pool;
+ struct igb_ring *rx_ring;
+ bool if_running;
+ int err;
+
+ pool = xsk_get_pool_from_qid(adapter->netdev, qid);
+ if (!pool)
+ return -EINVAL;
+
+ rx_ring = adapter->rx_ring[qid];
+ if_running = netif_running(adapter->netdev) && igb_xdp_is_enabled(adapter);
+ if (if_running)
+ igb_txrx_ring_disable(adapter, qid);
+
+ xsk_pool_dma_unmap(pool, IGB_RX_DMA_ATTR);
+
+ if (if_running) {
+ err = igb_realloc_rx_buffer_info(rx_ring, false);
+ if (err)
+ return err;
+
+ igb_txrx_ring_enable(adapter, qid);
+ }
+
+ return 0;
+}
+
+int igb_xsk_pool_setup(struct igb_adapter *adapter,
+ struct xsk_buff_pool *pool,
+ u16 qid)
+{
+ return pool ? igb_xsk_pool_enable(adapter, pool, qid) :
+ igb_xsk_pool_disable(adapter, qid);
+}
+
+static u16 igb_fill_rx_descs(struct xsk_buff_pool *pool, struct xdp_buff **xdp,
+ union e1000_adv_rx_desc *rx_desc, u16 count)
+{
+ dma_addr_t dma;
+ u16 buffs;
+ int i;
+
+ /* nothing to do */
+ if (!count)
+ return 0;
+
+ buffs = xsk_buff_alloc_batch(pool, xdp, count);
+ for (i = 0; i < buffs; i++) {
+ dma = xsk_buff_xdp_get_dma(*xdp);
+ rx_desc->read.pkt_addr = cpu_to_le64(dma);
+ rx_desc->wb.upper.length = 0;
+
+ rx_desc++;
+ xdp++;
+ }
+
+ return buffs;
+}
+
+bool igb_alloc_rx_buffers_zc(struct igb_ring *rx_ring,
+ struct xsk_buff_pool *xsk_pool, u16 count)
+{
+ u32 nb_buffs_extra = 0, nb_buffs = 0;
+ union e1000_adv_rx_desc *rx_desc;
+ u16 ntu = rx_ring->next_to_use;
+ u16 total_count = count;
+ struct xdp_buff **xdp;
+
+ rx_desc = IGB_RX_DESC(rx_ring, ntu);
+ xdp = &rx_ring->rx_buffer_info_zc[ntu];
+
+ if (ntu + count >= rx_ring->count) {
+ nb_buffs_extra = igb_fill_rx_descs(xsk_pool, xdp, rx_desc,
+ rx_ring->count - ntu);
+ if (nb_buffs_extra != rx_ring->count - ntu) {
+ ntu += nb_buffs_extra;
+ goto exit;
+ }
+ rx_desc = IGB_RX_DESC(rx_ring, 0);
+ xdp = rx_ring->rx_buffer_info_zc;
+ ntu = 0;
+ count -= nb_buffs_extra;
+ }
+
+ nb_buffs = igb_fill_rx_descs(xsk_pool, xdp, rx_desc, count);
+ ntu += nb_buffs;
+ if (ntu == rx_ring->count)
+ ntu = 0;
+
+ /* clear the length for the next_to_use descriptor */
+ rx_desc = IGB_RX_DESC(rx_ring, ntu);
+ rx_desc->wb.upper.length = 0;
+
+exit:
+ if (rx_ring->next_to_use != ntu) {
+ rx_ring->next_to_use = ntu;
+
+ /* Force memory writes to complete before letting h/w
+ * know there are new descriptors to fetch. (Only
+ * applicable for weak-ordered memory model archs,
+ * such as IA-64).
+ */
+ wmb();
+ writel(ntu, rx_ring->tail);
+ }
+
+ return total_count == (nb_buffs + nb_buffs_extra);
+}
+
+void igb_clean_rx_ring_zc(struct igb_ring *rx_ring)
+{
+ u16 ntc = rx_ring->next_to_clean;
+ u16 ntu = rx_ring->next_to_use;
+
+ while (ntc != ntu) {
+ struct xdp_buff *xdp = rx_ring->rx_buffer_info_zc[ntc];
+
+ xsk_buff_free(xdp);
+ ntc++;
+ if (ntc >= rx_ring->count)
+ ntc = 0;
+ }
+}
+
+static struct sk_buff *igb_construct_skb_zc(struct igb_ring *rx_ring,
+ struct xdp_buff *xdp,
+ ktime_t timestamp)
+{
+ unsigned int totalsize = xdp->data_end - xdp->data_meta;
+ unsigned int metasize = xdp->data - xdp->data_meta;
+ struct sk_buff *skb;
+
+ net_prefetch(xdp->data_meta);
+
+ /* allocate a skb to store the frags */
+ skb = napi_alloc_skb(&rx_ring->q_vector->napi, totalsize);
+ if (unlikely(!skb))
+ return NULL;
+
+ if (timestamp)
+ skb_hwtstamps(skb)->hwtstamp = timestamp;
+
+ memcpy(__skb_put(skb, totalsize), xdp->data_meta,
+ ALIGN(totalsize, sizeof(long)));
+
+ if (metasize) {
+ skb_metadata_set(skb, metasize);
+ __skb_pull(skb, metasize);
+ }
+
+ return skb;
+}
+
+static int igb_run_xdp_zc(struct igb_adapter *adapter, struct igb_ring *rx_ring,
+ struct xdp_buff *xdp, struct xsk_buff_pool *xsk_pool,
+ struct bpf_prog *xdp_prog)
+{
+ int err, result = IGB_XDP_PASS;
+ u32 act;
+
+ prefetchw(xdp->data_hard_start); /* xdp_frame write */
+
+ act = bpf_prog_run_xdp(xdp_prog, xdp);
+
+ if (likely(act == XDP_REDIRECT)) {
+ err = xdp_do_redirect(adapter->netdev, xdp, xdp_prog);
+ if (!err)
+ return IGB_XDP_REDIR;
+
+ if (xsk_uses_need_wakeup(xsk_pool) &&
+ err == -ENOBUFS)
+ result = IGB_XDP_EXIT;
+ else
+ result = IGB_XDP_CONSUMED;
+ goto out_failure;
+ }
+
+ switch (act) {
+ case XDP_PASS:
+ break;
+ case XDP_TX:
+ result = igb_xdp_xmit_back(adapter, xdp);
+ if (result == IGB_XDP_CONSUMED)
+ goto out_failure;
+ break;
+ default:
+ bpf_warn_invalid_xdp_action(adapter->netdev, xdp_prog, act);
+ fallthrough;
+ case XDP_ABORTED:
+out_failure:
+ trace_xdp_exception(rx_ring->netdev, xdp_prog, act);
+ fallthrough;
+ case XDP_DROP:
+ result = IGB_XDP_CONSUMED;
+ break;
+ }
+
+ return result;
+}
+
+int igb_clean_rx_irq_zc(struct igb_q_vector *q_vector,
+ struct xsk_buff_pool *xsk_pool, const int budget)
+{
+ struct igb_adapter *adapter = q_vector->adapter;
+ unsigned int total_bytes = 0, total_packets = 0;
+ struct igb_ring *rx_ring = q_vector->rx.ring;
+ u32 ntc = rx_ring->next_to_clean;
+ struct bpf_prog *xdp_prog;
+ unsigned int xdp_xmit = 0;
+ bool failure = false;
+ u16 entries_to_alloc;
+ struct sk_buff *skb;
+
+ /* xdp_prog cannot be NULL in the ZC path */
+ xdp_prog = READ_ONCE(rx_ring->xdp_prog);
+
+ while (likely(total_packets < budget)) {
+ union e1000_adv_rx_desc *rx_desc;
+ ktime_t timestamp = 0;
+ struct xdp_buff *xdp;
+ unsigned int size;
+ int xdp_res = 0;
+
+ rx_desc = IGB_RX_DESC(rx_ring, ntc);
+ size = le16_to_cpu(rx_desc->wb.upper.length);
+ if (!size)
+ break;
+
+ /* This memory barrier is needed to keep us from reading
+ * any other fields out of the rx_desc until we know the
+ * descriptor has been written back
+ */
+ dma_rmb();
+
+ xdp = rx_ring->rx_buffer_info_zc[ntc];
+ xsk_buff_set_size(xdp, size);
+ xsk_buff_dma_sync_for_cpu(xdp);
+
+ /* pull rx packet timestamp if available and valid */
+ if (igb_test_staterr(rx_desc, E1000_RXDADV_STAT_TSIP)) {
+ int ts_hdr_len;
+
+ ts_hdr_len = igb_ptp_rx_pktstamp(rx_ring->q_vector,
+ xdp->data,
+ &timestamp);
+
+ xdp->data += ts_hdr_len;
+ xdp->data_meta += ts_hdr_len;
+ size -= ts_hdr_len;
+ }
+
+ xdp_res = igb_run_xdp_zc(adapter, rx_ring, xdp, xsk_pool,
+ xdp_prog);
+
+ if (xdp_res) {
+ if (likely(xdp_res & (IGB_XDP_TX | IGB_XDP_REDIR))) {
+ xdp_xmit |= xdp_res;
+ } else if (xdp_res == IGB_XDP_EXIT) {
+ failure = true;
+ break;
+ } else if (xdp_res == IGB_XDP_CONSUMED) {
+ xsk_buff_free(xdp);
+ }
+
+ total_packets++;
+ total_bytes += size;
+ ntc++;
+ if (ntc == rx_ring->count)
+ ntc = 0;
+ continue;
+ }
+
+ skb = igb_construct_skb_zc(rx_ring, xdp, timestamp);
+
+ /* exit if we failed to retrieve a buffer */
+ if (!skb) {
+ rx_ring->rx_stats.alloc_failed++;
+ break;
+ }
+
+ xsk_buff_free(xdp);
+ ntc++;
+ if (ntc == rx_ring->count)
+ ntc = 0;
+
+ if (eth_skb_pad(skb))
+ continue;
+
+ /* probably a little skewed due to removing CRC */
+ total_bytes += skb->len;
+
+ /* populate checksum, timestamp, VLAN, and protocol */
+ igb_process_skb_fields(rx_ring, rx_desc, skb);
+
+ napi_gro_receive(&q_vector->napi, skb);
+
+ /* update budget accounting */
+ total_packets++;
+ }
+
+ rx_ring->next_to_clean = ntc;
+
+ if (xdp_xmit)
+ igb_finalize_xdp(adapter, xdp_xmit);
+
+ igb_update_rx_stats(q_vector, total_packets, total_bytes);
+
+ entries_to_alloc = igb_desc_unused(rx_ring);
+ if (entries_to_alloc >= IGB_RX_BUFFER_WRITE)
+ failure |= !igb_alloc_rx_buffers_zc(rx_ring, xsk_pool,
+ entries_to_alloc);
+
+ if (xsk_uses_need_wakeup(xsk_pool)) {
+ if (failure || rx_ring->next_to_clean == rx_ring->next_to_use)
+ xsk_set_rx_need_wakeup(xsk_pool);
+ else
+ xsk_clear_rx_need_wakeup(xsk_pool);
+
+ return (int)total_packets;
+ }
+ return failure ? budget : (int)total_packets;
+}
+
+bool igb_xmit_zc(struct igb_ring *tx_ring, struct xsk_buff_pool *xsk_pool)
+{
+ unsigned int budget = igb_desc_unused(tx_ring);
+ u32 cmd_type, olinfo_status, nb_pkts, i = 0;
+ struct xdp_desc *descs = xsk_pool->tx_descs;
+ union e1000_adv_tx_desc *tx_desc = NULL;
+ struct igb_tx_buffer *tx_buffer_info;
+ unsigned int total_bytes = 0;
+ dma_addr_t dma;
+
+ if (!netif_carrier_ok(tx_ring->netdev))
+ return true;
+
+ if (test_bit(IGB_RING_FLAG_TX_DISABLED, &tx_ring->flags))
+ return true;
+
+ nb_pkts = xsk_tx_peek_release_desc_batch(xsk_pool, budget);
+ if (!nb_pkts)
+ return true;
+
+ while (nb_pkts-- > 0) {
+ dma = xsk_buff_raw_get_dma(xsk_pool, descs[i].addr);
+ xsk_buff_raw_dma_sync_for_device(xsk_pool, dma, descs[i].len);
+
+ tx_buffer_info = &tx_ring->tx_buffer_info[tx_ring->next_to_use];
+ tx_buffer_info->bytecount = descs[i].len;
+ tx_buffer_info->type = IGB_TYPE_XSK;
+ tx_buffer_info->xdpf = NULL;
+ tx_buffer_info->gso_segs = 1;
+ tx_buffer_info->time_stamp = jiffies;
+
+ tx_desc = IGB_TX_DESC(tx_ring, tx_ring->next_to_use);
+ tx_desc->read.buffer_addr = cpu_to_le64(dma);
+
+ /* put descriptor type bits */
+ cmd_type = E1000_ADVTXD_DTYP_DATA | E1000_ADVTXD_DCMD_DEXT |
+ E1000_ADVTXD_DCMD_IFCS;
+ olinfo_status = descs[i].len << E1000_ADVTXD_PAYLEN_SHIFT;
+
+ /* FIXME: This sets the Report Status (RS) bit for every
+ * descriptor. One nice to have optimization would be to set it
+ * only for the last descriptor in the whole batch. See Intel
+ * ice driver for an example on how to do it.
+ */
+ cmd_type |= descs[i].len | IGB_TXD_DCMD;
+ tx_desc->read.cmd_type_len = cpu_to_le32(cmd_type);
+ tx_desc->read.olinfo_status = cpu_to_le32(olinfo_status);
+
+ total_bytes += descs[i].len;
+
+ i++;
+ tx_ring->next_to_use++;
+ tx_buffer_info->next_to_watch = tx_desc;
+ if (tx_ring->next_to_use == tx_ring->count)
+ tx_ring->next_to_use = 0;
+ }
+
+ netdev_tx_sent_queue(txring_txq(tx_ring), total_bytes);
+ igb_xdp_ring_update_tail(tx_ring);
+
+ return nb_pkts < budget;
+}
+
+int igb_xsk_wakeup(struct net_device *dev, u32 qid, u32 flags)
+{
+ struct igb_adapter *adapter = netdev_priv(dev);
+ struct e1000_hw *hw = &adapter->hw;
+ struct igb_ring *ring;
+ u32 eics = 0;
+
+ if (test_bit(__IGB_DOWN, &adapter->state))
+ return -ENETDOWN;
+
+ if (!igb_xdp_is_enabled(adapter))
+ return -EINVAL;
+
+ if (qid >= adapter->num_tx_queues)
+ return -EINVAL;
+
+ ring = adapter->tx_ring[qid];
+
+ if (test_bit(IGB_RING_FLAG_TX_DISABLED, &ring->flags))
+ return -ENETDOWN;
+
+ if (!READ_ONCE(ring->xsk_pool))
+ return -EINVAL;
+
+ if (!napi_if_scheduled_mark_missed(&ring->q_vector->napi)) {
+ /* Cause software interrupt */
+ if (adapter->flags & IGB_FLAG_HAS_MSIX) {
+ eics |= ring->q_vector->eims_value;
+ wr32(E1000_EICS, eics);
+ } else {
+ wr32(E1000_ICS, E1000_ICS_RXDMT0);
+ }
+ }
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index eac0f966e0e4..b8111ad9a9a8 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -337,6 +337,8 @@ struct igc_adapter {
struct igc_led_classdev *leds;
};
+void igc_set_queue_napi(struct igc_adapter *adapter, int q_idx,
+ struct napi_struct *napi);
void igc_up(struct igc_adapter *adapter);
void igc_down(struct igc_adapter *adapter);
int igc_open(struct net_device *netdev);
diff --git a/drivers/net/ethernet/intel/igc/igc_base.c b/drivers/net/ethernet/intel/igc/igc_base.c
index 9fae8bdec2a7..1613b562d17c 100644
--- a/drivers/net/ethernet/intel/igc/igc_base.c
+++ b/drivers/net/ethernet/intel/igc/igc_base.c
@@ -68,6 +68,10 @@ static s32 igc_init_nvm_params_base(struct igc_hw *hw)
u32 eecd = rd32(IGC_EECD);
u16 size;
+ /* failed to read reg and got all F's */
+ if (!(~eecd))
+ return -ENXIO;
+
size = FIELD_GET(IGC_EECD_SIZE_EX_MASK, eecd);
/* Added to a constant, "size" becomes the left-shift value
@@ -221,6 +225,8 @@ static s32 igc_get_invariants_base(struct igc_hw *hw)
/* NVM initialization */
ret_val = igc_init_nvm_params_base(hw);
+ if (ret_val)
+ goto out;
switch (hw->mac.type) {
case igc_i225:
ret_val = igc_init_nvm_params_i225(hw);
diff --git a/drivers/net/ethernet/intel/igc/igc_hw.h b/drivers/net/ethernet/intel/igc/igc_hw.h
index d9d1a1a11daf..be8a49a86d09 100644
--- a/drivers/net/ethernet/intel/igc/igc_hw.h
+++ b/drivers/net/ethernet/intel/igc/igc_hw.h
@@ -279,9 +279,4 @@ struct net_device *igc_get_hw_dev(struct igc_hw *hw);
#define hw_dbg(format, arg...) \
netdev_dbg(igc_get_hw_dev(hw), format, ##arg)
-s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
-s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value);
-void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
-void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value);
-
#endif /* _IGC_HW_H_ */
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 27872bdea9bd..56a35d58e7a6 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -2123,10 +2123,6 @@ static bool igc_cleanup_headers(struct igc_ring *rx_ring,
union igc_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
- /* XDP packets use error pointer so abort at this point */
- if (IS_ERR(skb))
- return true;
-
if (unlikely(igc_test_staterr(rx_desc, IGC_RXDEXT_STATERR_RXE))) {
struct net_device *netdev = rx_ring->netdev;
@@ -2515,8 +2511,7 @@ out_failure:
}
}
-static struct sk_buff *igc_xdp_run_prog(struct igc_adapter *adapter,
- struct xdp_buff *xdp)
+static int igc_xdp_run_prog(struct igc_adapter *adapter, struct xdp_buff *xdp)
{
struct bpf_prog *prog;
int res;
@@ -2530,7 +2525,7 @@ static struct sk_buff *igc_xdp_run_prog(struct igc_adapter *adapter,
res = __igc_xdp_run_prog(adapter, prog, xdp);
out:
- return ERR_PTR(-res);
+ return res;
}
/* This function assumes __netif_tx_lock is held by the caller. */
@@ -2585,6 +2580,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
struct sk_buff *skb = rx_ring->skb;
u16 cleaned_count = igc_desc_unused(rx_ring);
int xdp_status = 0, rx_buffer_pgcnt;
+ int xdp_res = 0;
while (likely(total_packets < budget)) {
struct igc_xdp_buff ctx = { .rx_ts = NULL };
@@ -2630,12 +2626,10 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
xdp_buff_clear_frags_flag(&ctx.xdp);
ctx.rx_desc = rx_desc;
- skb = igc_xdp_run_prog(adapter, &ctx.xdp);
+ xdp_res = igc_xdp_run_prog(adapter, &ctx.xdp);
}
- if (IS_ERR(skb)) {
- unsigned int xdp_res = -PTR_ERR(skb);
-
+ if (xdp_res) {
switch (xdp_res) {
case IGC_XDP_CONSUMED:
rx_buffer->pagecnt_bias++;
@@ -2657,7 +2651,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
skb = igc_construct_skb(rx_ring, rx_buffer, &ctx);
/* exit if we failed to retrieve a buffer */
- if (!skb) {
+ if (!xdp_res && !skb) {
rx_ring->rx_stats.alloc_failed++;
rx_buffer->pagecnt_bias++;
set_bit(IGC_RING_FLAG_RX_ALLOC_FAILED, &rx_ring->flags);
@@ -2672,7 +2666,7 @@ static int igc_clean_rx_irq(struct igc_q_vector *q_vector, const int budget)
continue;
/* verify the packet layout is correct */
- if (igc_cleanup_headers(rx_ring, rx_desc, skb)) {
+ if (xdp_res || igc_cleanup_headers(rx_ring, rx_desc, skb)) {
skb = NULL;
continue;
}
@@ -4948,6 +4942,22 @@ static int igc_sw_init(struct igc_adapter *adapter)
return 0;
}
+void igc_set_queue_napi(struct igc_adapter *adapter, int vector,
+ struct napi_struct *napi)
+{
+ struct igc_q_vector *q_vector = adapter->q_vector[vector];
+
+ if (q_vector->rx.ring)
+ netif_queue_set_napi(adapter->netdev,
+ q_vector->rx.ring->queue_index,
+ NETDEV_QUEUE_TYPE_RX, napi);
+
+ if (q_vector->tx.ring)
+ netif_queue_set_napi(adapter->netdev,
+ q_vector->tx.ring->queue_index,
+ NETDEV_QUEUE_TYPE_TX, napi);
+}
+
/**
* igc_up - Open the interface and prepare it to handle traffic
* @adapter: board private structure
@@ -4955,6 +4965,7 @@ static int igc_sw_init(struct igc_adapter *adapter)
void igc_up(struct igc_adapter *adapter)
{
struct igc_hw *hw = &adapter->hw;
+ struct napi_struct *napi;
int i = 0;
/* hardware has been reset, we need to reload some things */
@@ -4962,8 +4973,11 @@ void igc_up(struct igc_adapter *adapter)
clear_bit(__IGC_DOWN, &adapter->state);
- for (i = 0; i < adapter->num_q_vectors; i++)
- napi_enable(&adapter->q_vector[i]->napi);
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ napi = &adapter->q_vector[i]->napi;
+ napi_enable(napi);
+ igc_set_queue_napi(adapter, i, napi);
+ }
if (adapter->msix_entries)
igc_configure_msix(adapter);
@@ -5192,6 +5206,7 @@ void igc_down(struct igc_adapter *adapter)
for (i = 0; i < adapter->num_q_vectors; i++) {
if (adapter->q_vector[i]) {
napi_synchronize(&adapter->q_vector[i]->napi);
+ igc_set_queue_napi(adapter, i, NULL);
napi_disable(&adapter->q_vector[i]->napi);
}
}
@@ -5576,6 +5591,9 @@ static int igc_request_msix(struct igc_adapter *adapter)
q_vector);
if (err)
goto err_free;
+
+ netif_napi_set_irq(&q_vector->napi,
+ adapter->msix_entries[vector].vector);
}
igc_configure_msix(adapter);
@@ -6018,6 +6036,7 @@ static int __igc_open(struct net_device *netdev, bool resuming)
struct igc_adapter *adapter = netdev_priv(netdev);
struct pci_dev *pdev = adapter->pdev;
struct igc_hw *hw = &adapter->hw;
+ struct napi_struct *napi;
int err = 0;
int i = 0;
@@ -6053,8 +6072,11 @@ static int __igc_open(struct net_device *netdev, bool resuming)
clear_bit(__IGC_DOWN, &adapter->state);
- for (i = 0; i < adapter->num_q_vectors; i++)
- napi_enable(&adapter->q_vector[i]->napi);
+ for (i = 0; i < adapter->num_q_vectors; i++) {
+ napi = &adapter->q_vector[i]->napi;
+ napi_enable(napi);
+ igc_set_queue_napi(adapter, i, napi);
+ }
/* Clear any pending interrupts. */
rd32(IGC_ICR);
@@ -6779,45 +6801,6 @@ static const struct net_device_ops igc_netdev_ops = {
.ndo_get_tstamp = igc_get_tstamp,
};
-/* PCIe configuration access */
-void igc_read_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value)
-{
- struct igc_adapter *adapter = hw->back;
-
- pci_read_config_word(adapter->pdev, reg, value);
-}
-
-void igc_write_pci_cfg(struct igc_hw *hw, u32 reg, u16 *value)
-{
- struct igc_adapter *adapter = hw->back;
-
- pci_write_config_word(adapter->pdev, reg, *value);
-}
-
-s32 igc_read_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value)
-{
- struct igc_adapter *adapter = hw->back;
-
- if (!pci_is_pcie(adapter->pdev))
- return -IGC_ERR_CONFIG;
-
- pcie_capability_read_word(adapter->pdev, reg, value);
-
- return IGC_SUCCESS;
-}
-
-s32 igc_write_pcie_cap_reg(struct igc_hw *hw, u32 reg, u16 *value)
-{
- struct igc_adapter *adapter = hw->back;
-
- if (!pci_is_pcie(adapter->pdev))
- return -IGC_ERR_CONFIG;
-
- pcie_capability_write_word(adapter->pdev, reg, *value);
-
- return IGC_SUCCESS;
-}
-
u32 igc_rd32(struct igc_hw *hw, u32 reg)
{
struct igc_adapter *igc = container_of(hw, struct igc_adapter, hw);
@@ -7338,7 +7321,7 @@ static void igc_deliver_wake_packet(struct net_device *netdev)
netif_rx(skb);
}
-static int igc_resume(struct device *dev)
+static int __igc_resume(struct device *dev, bool rpm)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *netdev = pci_get_drvdata(pdev);
@@ -7381,7 +7364,11 @@ static int igc_resume(struct device *dev)
wr32(IGC_WUS, ~0);
if (netif_running(netdev)) {
+ if (!rpm)
+ rtnl_lock();
err = __igc_open(netdev, true);
+ if (!rpm)
+ rtnl_unlock();
if (!err)
netif_device_attach(netdev);
}
@@ -7389,9 +7376,14 @@ static int igc_resume(struct device *dev)
return err;
}
+static int igc_resume(struct device *dev)
+{
+ return __igc_resume(dev, false);
+}
+
static int igc_runtime_resume(struct device *dev)
{
- return igc_resume(dev);
+ return __igc_resume(dev, true);
}
static int igc_suspend(struct device *dev)
@@ -7436,14 +7428,18 @@ static pci_ers_result_t igc_io_error_detected(struct pci_dev *pdev,
struct net_device *netdev = pci_get_drvdata(pdev);
struct igc_adapter *adapter = netdev_priv(netdev);
+ rtnl_lock();
netif_device_detach(netdev);
- if (state == pci_channel_io_perm_failure)
+ if (state == pci_channel_io_perm_failure) {
+ rtnl_unlock();
return PCI_ERS_RESULT_DISCONNECT;
+ }
if (netif_running(netdev))
igc_down(adapter);
pci_disable_device(pdev);
+ rtnl_unlock();
/* Request a slot reset. */
return PCI_ERS_RESULT_NEED_RESET;
@@ -7454,7 +7450,7 @@ static pci_ers_result_t igc_io_error_detected(struct pci_dev *pdev,
* @pdev: Pointer to PCI device
*
* Restart the card from scratch, as if from a cold-boot. Implementation
- * resembles the first-half of the igc_resume routine.
+ * resembles the first-half of the __igc_resume routine.
**/
static pci_ers_result_t igc_io_slot_reset(struct pci_dev *pdev)
{
@@ -7493,7 +7489,7 @@ static pci_ers_result_t igc_io_slot_reset(struct pci_dev *pdev)
*
* This callback is called when the error recovery driver tells us that
* its OK to resume normal operation. Implementation resembles the
- * second-half of the igc_resume routine.
+ * second-half of the __igc_resume routine.
*/
static void igc_io_resume(struct pci_dev *pdev)
{
diff --git a/drivers/net/ethernet/intel/igc/igc_nvm.c b/drivers/net/ethernet/intel/igc/igc_nvm.c
index 58f81aba0144..efd121c03967 100644
--- a/drivers/net/ethernet/intel/igc/igc_nvm.c
+++ b/drivers/net/ethernet/intel/igc/igc_nvm.c
@@ -36,56 +36,6 @@ static s32 igc_poll_eerd_eewr_done(struct igc_hw *hw, int ee_reg)
}
/**
- * igc_acquire_nvm - Generic request for access to EEPROM
- * @hw: pointer to the HW structure
- *
- * Set the EEPROM access request bit and wait for EEPROM access grant bit.
- * Return successful if access grant bit set, else clear the request for
- * EEPROM access and return -IGC_ERR_NVM (-1).
- */
-s32 igc_acquire_nvm(struct igc_hw *hw)
-{
- s32 timeout = IGC_NVM_GRANT_ATTEMPTS;
- u32 eecd = rd32(IGC_EECD);
- s32 ret_val = 0;
-
- wr32(IGC_EECD, eecd | IGC_EECD_REQ);
- eecd = rd32(IGC_EECD);
-
- while (timeout) {
- if (eecd & IGC_EECD_GNT)
- break;
- udelay(5);
- eecd = rd32(IGC_EECD);
- timeout--;
- }
-
- if (!timeout) {
- eecd &= ~IGC_EECD_REQ;
- wr32(IGC_EECD, eecd);
- hw_dbg("Could not acquire NVM grant\n");
- ret_val = -IGC_ERR_NVM;
- }
-
- return ret_val;
-}
-
-/**
- * igc_release_nvm - Release exclusive access to EEPROM
- * @hw: pointer to the HW structure
- *
- * Stop any current commands to the EEPROM and clear the EEPROM request bit.
- */
-void igc_release_nvm(struct igc_hw *hw)
-{
- u32 eecd;
-
- eecd = rd32(IGC_EECD);
- eecd &= ~IGC_EECD_REQ;
- wr32(IGC_EECD, eecd);
-}
-
-/**
* igc_read_nvm_eerd - Reads EEPROM using EERD register
* @hw: pointer to the HW structure
* @offset: offset of word in the EEPROM to read
diff --git a/drivers/net/ethernet/intel/igc/igc_nvm.h b/drivers/net/ethernet/intel/igc/igc_nvm.h
index f9fc2e9cfb03..ab78d0c64547 100644
--- a/drivers/net/ethernet/intel/igc/igc_nvm.h
+++ b/drivers/net/ethernet/intel/igc/igc_nvm.h
@@ -4,8 +4,6 @@
#ifndef _IGC_NVM_H_
#define _IGC_NVM_H_
-s32 igc_acquire_nvm(struct igc_hw *hw);
-void igc_release_nvm(struct igc_hw *hw);
s32 igc_read_mac_addr(struct igc_hw *hw);
s32 igc_read_nvm_eerd(struct igc_hw *hw, u16 offset, u16 words, u16 *data);
s32 igc_validate_nvm_checksum(struct igc_hw *hw);
diff --git a/drivers/net/ethernet/intel/igc/igc_xdp.c b/drivers/net/ethernet/intel/igc/igc_xdp.c
index e27af72aada8..13bbd3346e01 100644
--- a/drivers/net/ethernet/intel/igc/igc_xdp.c
+++ b/drivers/net/ethernet/intel/igc/igc_xdp.c
@@ -13,6 +13,7 @@ int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
struct net_device *dev = adapter->netdev;
bool if_running = netif_running(dev);
struct bpf_prog *old_prog;
+ bool need_update;
if (dev->mtu > ETH_DATA_LEN) {
/* For now, the driver doesn't support XDP functionality with
@@ -22,7 +23,8 @@ int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
return -EOPNOTSUPP;
}
- if (if_running)
+ need_update = !!adapter->xdp_prog != !!prog;
+ if (if_running && need_update)
igc_close(dev);
old_prog = xchg(&adapter->xdp_prog, prog);
@@ -34,7 +36,7 @@ int igc_xdp_set_prog(struct igc_adapter *adapter, struct bpf_prog *prog,
else
xdp_features_clear_redirect_target(dev);
- if (if_running)
+ if (if_running && need_update)
igc_open(dev);
return 0;
@@ -84,6 +86,7 @@ static int igc_xdp_enable_pool(struct igc_adapter *adapter,
napi_disable(napi);
}
+ igc_set_queue_napi(adapter, queue_id, NULL);
set_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags);
set_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags);
@@ -133,6 +136,7 @@ static int igc_xdp_disable_pool(struct igc_adapter *adapter, u16 queue_id)
xsk_pool_dma_unmap(pool, IGC_RX_DMA_ATTR);
clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &rx_ring->flags);
clear_bit(IGC_RING_FLAG_AF_XDP_ZC, &tx_ring->flags);
+ igc_set_queue_napi(adapter, queue_id, napi);
if (needs_reset) {
napi_enable(napi);
diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile
index 965e5ce1b326..b456d102655a 100644
--- a/drivers/net/ethernet/intel/ixgbe/Makefile
+++ b/drivers/net/ethernet/intel/ixgbe/Makefile
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0
-# Copyright(c) 1999 - 2018 Intel Corporation.
+# Copyright(c) 1999 - 2024 Intel Corporation.
#
# Makefile for the Intel(R) 10GbE PCI Express ethernet driver
#
@@ -9,7 +9,7 @@ obj-$(CONFIG_IXGBE) += ixgbe.o
ixgbe-y := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
ixgbe_mbx.o ixgbe_x540.o ixgbe_x550.o ixgbe_lib.o ixgbe_ptp.o \
- ixgbe_xsk.o
+ ixgbe_xsk.o ixgbe_e610.o
ixgbe-$(CONFIG_IXGBE_DCB) += ixgbe_dcb.o ixgbe_dcb_82598.o \
ixgbe_dcb_82599.o ixgbe_dcb_nl.o
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe.h b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
index 559b443c409f..e6a380d4929b 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#ifndef _IXGBE_H_
#define _IXGBE_H_
@@ -20,6 +20,7 @@
#include "ixgbe_type.h"
#include "ixgbe_common.h"
#include "ixgbe_dcb.h"
+#include "ixgbe_e610.h"
#if IS_ENABLED(CONFIG_FCOE)
#define IXGBE_FCOE
#include "ixgbe_fcoe.h"
@@ -173,6 +174,7 @@ enum ixgbe_tx_flags {
#define VMDQ_P(p) ((p) + adapter->ring_feature[RING_F_VMDQ].offset)
#define IXGBE_82599_VF_DEVICE_ID 0x10ED
#define IXGBE_X540_VF_DEVICE_ID 0x1515
+#define IXGBE_E610_VF_DEVICE_ID 0x57AD
#define UPDATE_VF_COUNTER_32bit(reg, last_counter, counter) \
{ \
@@ -654,6 +656,7 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_RSS_FIELD_IPV6_UDP BIT(9)
#define IXGBE_FLAG2_PTP_PPS_ENABLED BIT(10)
#define IXGBE_FLAG2_PHY_INTERRUPT BIT(11)
+#define IXGBE_FLAG2_FW_ASYNC_EVENT BIT(12)
#define IXGBE_FLAG2_VLAN_PROMISC BIT(13)
#define IXGBE_FLAG2_EEE_CAPABLE BIT(14)
#define IXGBE_FLAG2_EEE_ENABLED BIT(15)
@@ -661,6 +664,9 @@ struct ixgbe_adapter {
#define IXGBE_FLAG2_IPSEC_ENABLED BIT(17)
#define IXGBE_FLAG2_VF_IPSEC_ENABLED BIT(18)
#define IXGBE_FLAG2_AUTO_DISABLE_VF BIT(19)
+#define IXGBE_FLAG2_PHY_FW_LOAD_FAILED BIT(20)
+#define IXGBE_FLAG2_NO_MEDIA BIT(21)
+#define IXGBE_FLAG2_MOD_POWER_UNSUPPORTED BIT(22)
/* Tx fast path data */
int num_tx_queues;
@@ -793,6 +799,7 @@ struct ixgbe_adapter {
u32 vferr_refcount;
struct ixgbe_mac_addr *mac_table;
struct kobject *info_kobj;
+ u16 lse_mask;
#ifdef CONFIG_IXGBE_HWMON
struct hwmon_buff *ixgbe_hwmon_buff;
#endif /* CONFIG_IXGBE_HWMON */
@@ -849,6 +856,7 @@ static inline u8 ixgbe_max_rss_indices(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
return IXGBE_MAX_RSS_INDICES_X550;
default:
return 0;
@@ -874,6 +882,7 @@ enum ixgbe_state_t {
__IXGBE_PTP_RUNNING,
__IXGBE_PTP_TX_IN_PROGRESS,
__IXGBE_RESET_REQUESTED,
+ __IXGBE_PHY_INIT_COMPLETE,
};
struct ixgbe_cb {
@@ -896,6 +905,7 @@ enum ixgbe_boards {
board_x550em_x_fw,
board_x550em_a,
board_x550em_a_fw,
+ board_e610,
};
extern const struct ixgbe_info ixgbe_82598_info;
@@ -906,6 +916,7 @@ extern const struct ixgbe_info ixgbe_X550EM_x_info;
extern const struct ixgbe_info ixgbe_x550em_x_fw_info;
extern const struct ixgbe_info ixgbe_x550em_a_info;
extern const struct ixgbe_info ixgbe_x550em_a_fw_info;
+extern const struct ixgbe_info ixgbe_e610_info;
#ifdef CONFIG_IXGBE_DCB
extern const struct dcbnl_rtnl_ops ixgbe_dcbnl_ops;
#endif
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
index cdaf087b4e85..964988b4d58b 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_82599.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#include <linux/pci.h>
#include <linux/delay.h>
@@ -1615,6 +1615,7 @@ int ixgbe_fdir_set_input_mask_82599(struct ixgbe_hw *hw,
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
IXGBE_WRITE_REG(hw, IXGBE_FDIRSCTPM, ~fdirtcpm);
break;
default:
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
index 3be1bfb16498..7beaf6ea57f9 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#include <linux/pci.h>
#include <linux/delay.h>
@@ -58,6 +58,7 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
switch (hw->device_id) {
case IXGBE_DEV_ID_X550EM_A_SFP:
case IXGBE_DEV_ID_X550EM_A_SFP_N:
+ case IXGBE_DEV_ID_E610_SFP:
supported = false;
break;
default:
@@ -88,6 +89,8 @@ bool ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
case IXGBE_DEV_ID_X550EM_A_10G_T:
case IXGBE_DEV_ID_X550EM_A_1G_T:
case IXGBE_DEV_ID_X550EM_A_1G_T_L:
+ case IXGBE_DEV_ID_E610_10G_T:
+ case IXGBE_DEV_ID_E610_2_5G_T:
supported = true;
break;
default:
@@ -469,9 +472,14 @@ int ixgbe_clear_hw_cntrs_generic(struct ixgbe_hw *hw)
}
}
- if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) {
+ if (hw->mac.type == ixgbe_mac_X550 ||
+ hw->mac.type == ixgbe_mac_X540 ||
+ hw->mac.type == ixgbe_mac_e610) {
if (hw->phy.id == 0)
hw->phy.ops.identify(hw);
+ }
+
+ if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_X540) {
hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECL, MDIO_MMD_PCS, &i);
hw->phy.ops.read_reg(hw, IXGBE_PCRC8ECH, MDIO_MMD_PCS, &i);
hw->phy.ops.read_reg(hw, IXGBE_LDPCECL, MDIO_MMD_PCS, &i);
@@ -660,7 +668,11 @@ int ixgbe_get_bus_info_generic(struct ixgbe_hw *hw)
hw->bus.type = ixgbe_bus_type_pci_express;
/* Get the negotiated link width and speed from PCI config space */
- link_status = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_LINK_STATUS);
+ if (hw->mac.type == ixgbe_mac_e610)
+ link_status = ixgbe_read_pci_cfg_word(hw, IXGBE_PCI_LINK_STATUS_E610);
+ else
+ link_status = ixgbe_read_pci_cfg_word(hw,
+ IXGBE_PCI_LINK_STATUS);
hw->bus.width = ixgbe_convert_bus_width(link_status);
hw->bus.speed = ixgbe_convert_bus_speed(link_status);
@@ -2918,6 +2930,10 @@ u16 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw)
pcie_offset = IXGBE_PCIE_MSIX_82599_CAPS;
max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
break;
+ case ixgbe_mac_e610:
+ pcie_offset = IXGBE_PCIE_MSIX_E610_CAPS;
+ max_msix_count = IXGBE_MAX_MSIX_VECTORS_82599;
+ break;
default:
return 1;
}
@@ -3366,7 +3382,8 @@ int ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
*speed = IXGBE_LINK_SPEED_1GB_FULL;
break;
case IXGBE_LINKS_SPEED_100_82599:
- if ((hw->mac.type >= ixgbe_mac_X550) &&
+ if ((hw->mac.type >= ixgbe_mac_X550 ||
+ hw->mac.type == ixgbe_mac_e610) &&
(links_reg & IXGBE_LINKS_SPEED_NON_STD))
*speed = IXGBE_LINK_SPEED_5GB_FULL;
else
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
index 6493abf189de..6639069ad528 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_common.h
@@ -194,6 +194,8 @@ u32 ixgbe_read_reg(struct ixgbe_hw *hw, u32 reg);
dev_err(&adapter->pdev->dev, format, ## arg)
#define e_dev_notice(format, arg...) \
dev_notice(&adapter->pdev->dev, format, ## arg)
+#define e_dbg(msglvl, format, arg...) \
+ netif_dbg(adapter, msglvl, adapter->netdev, format, ## arg)
#define e_info(msglvl, format, arg...) \
netif_info(adapter, msglvl, adapter->netdev, format, ## arg)
#define e_err(msglvl, format, arg...) \
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
index f2709b10c2e5..19d6b6fa8fb3 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_dcb_nl.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#include "ixgbe.h"
#include <linux/dcbnl.h>
@@ -154,6 +154,7 @@ static void ixgbe_dcbnl_get_perm_hw_addr(struct net_device *netdev,
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
case ixgbe_mac_X550:
+ case ixgbe_mac_e610:
for (j = 0; j < netdev->addr_len; j++, i++)
perm_addr[i] = adapter->hw.mac.san_addr[j];
break;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c
new file mode 100644
index 000000000000..683c668672d6
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c
@@ -0,0 +1,2658 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright(c) 2024 Intel Corporation. */
+
+#include "ixgbe_common.h"
+#include "ixgbe_e610.h"
+#include "ixgbe_x550.h"
+#include "ixgbe_type.h"
+#include "ixgbe_x540.h"
+#include "ixgbe_mbx.h"
+#include "ixgbe_phy.h"
+
+/**
+ * ixgbe_should_retry_aci_send_cmd_execute - decide if ACI command should
+ * be resent
+ * @opcode: ACI opcode
+ *
+ * Check if ACI command should be sent again depending on the provided opcode.
+ * It may happen when CSR is busy during link state changes.
+ *
+ * Return: true if the sending command routine should be repeated,
+ * otherwise false.
+ */
+static bool ixgbe_should_retry_aci_send_cmd_execute(u16 opcode)
+{
+ switch (opcode) {
+ case ixgbe_aci_opc_disable_rxen:
+ case ixgbe_aci_opc_get_phy_caps:
+ case ixgbe_aci_opc_get_link_status:
+ case ixgbe_aci_opc_get_link_topo:
+ return true;
+ }
+
+ return false;
+}
+
+/**
+ * ixgbe_aci_send_cmd_execute - execute sending FW Admin Command to FW Admin
+ * Command Interface
+ * @hw: pointer to the HW struct
+ * @desc: descriptor describing the command
+ * @buf: buffer to use for indirect commands (NULL for direct commands)
+ * @buf_size: size of buffer for indirect commands (0 for direct commands)
+ *
+ * Admin Command is sent using CSR by setting descriptor and buffer in specific
+ * registers.
+ *
+ * Return: the exit code of the operation.
+ * * - 0 - success.
+ * * - -EIO - CSR mechanism is not enabled.
+ * * - -EBUSY - CSR mechanism is busy.
+ * * - -EINVAL - buf_size is too big or
+ * invalid argument buf or buf_size.
+ * * - -ETIME - Admin Command X command timeout.
+ * * - -EIO - Admin Command X invalid state of HICR register or
+ * Admin Command failed because of bad opcode was returned or
+ * Admin Command failed with error Y.
+ */
+static int ixgbe_aci_send_cmd_execute(struct ixgbe_hw *hw,
+ struct ixgbe_aci_desc *desc,
+ void *buf, u16 buf_size)
+{
+ u16 opcode, buf_tail_size = buf_size % 4;
+ u32 *raw_desc = (u32 *)desc;
+ u32 hicr, i, buf_tail = 0;
+ bool valid_buf = false;
+
+ hw->aci.last_status = IXGBE_ACI_RC_OK;
+
+ /* It's necessary to check if mechanism is enabled */
+ hicr = IXGBE_READ_REG(hw, IXGBE_PF_HICR);
+
+ if (!(hicr & IXGBE_PF_HICR_EN))
+ return -EIO;
+
+ if (hicr & IXGBE_PF_HICR_C) {
+ hw->aci.last_status = IXGBE_ACI_RC_EBUSY;
+ return -EBUSY;
+ }
+
+ opcode = le16_to_cpu(desc->opcode);
+
+ if (buf_size > IXGBE_ACI_MAX_BUFFER_SIZE)
+ return -EINVAL;
+
+ if (buf)
+ desc->flags |= cpu_to_le16(IXGBE_ACI_FLAG_BUF);
+
+ if (desc->flags & cpu_to_le16(IXGBE_ACI_FLAG_BUF)) {
+ if ((buf && !buf_size) ||
+ (!buf && buf_size))
+ return -EINVAL;
+ if (buf && buf_size)
+ valid_buf = true;
+ }
+
+ if (valid_buf) {
+ if (buf_tail_size)
+ memcpy(&buf_tail, buf + buf_size - buf_tail_size,
+ buf_tail_size);
+
+ if (((buf_size + 3) & ~0x3) > IXGBE_ACI_LG_BUF)
+ desc->flags |= cpu_to_le16(IXGBE_ACI_FLAG_LB);
+
+ desc->datalen = cpu_to_le16(buf_size);
+
+ if (desc->flags & cpu_to_le16(IXGBE_ACI_FLAG_RD)) {
+ for (i = 0; i < buf_size / 4; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_PF_HIBA(i), ((u32 *)buf)[i]);
+ if (buf_tail_size)
+ IXGBE_WRITE_REG(hw, IXGBE_PF_HIBA(i), buf_tail);
+ }
+ }
+
+ /* Descriptor is written to specific registers */
+ for (i = 0; i < IXGBE_ACI_DESC_SIZE_IN_DWORDS; i++)
+ IXGBE_WRITE_REG(hw, IXGBE_PF_HIDA(i), raw_desc[i]);
+
+ /* SW has to set PF_HICR.C bit and clear PF_HICR.SV and
+ * PF_HICR_EV
+ */
+ hicr = (IXGBE_READ_REG(hw, IXGBE_PF_HICR) | IXGBE_PF_HICR_C) &
+ ~(IXGBE_PF_HICR_SV | IXGBE_PF_HICR_EV);
+ IXGBE_WRITE_REG(hw, IXGBE_PF_HICR, hicr);
+
+#define MAX_SLEEP_RESP_US 1000
+#define MAX_TMOUT_RESP_SYNC_US 100000000
+
+ /* Wait for sync Admin Command response */
+ read_poll_timeout(IXGBE_READ_REG, hicr,
+ (hicr & IXGBE_PF_HICR_SV) ||
+ !(hicr & IXGBE_PF_HICR_C),
+ MAX_SLEEP_RESP_US, MAX_TMOUT_RESP_SYNC_US, true, hw,
+ IXGBE_PF_HICR);
+
+#define MAX_TMOUT_RESP_ASYNC_US 150000000
+
+ /* Wait for async Admin Command response */
+ read_poll_timeout(IXGBE_READ_REG, hicr,
+ (hicr & IXGBE_PF_HICR_EV) ||
+ !(hicr & IXGBE_PF_HICR_C),
+ MAX_SLEEP_RESP_US, MAX_TMOUT_RESP_ASYNC_US, true, hw,
+ IXGBE_PF_HICR);
+
+ /* Read sync Admin Command response */
+ if ((hicr & IXGBE_PF_HICR_SV)) {
+ for (i = 0; i < IXGBE_ACI_DESC_SIZE_IN_DWORDS; i++) {
+ raw_desc[i] = IXGBE_READ_REG(hw, IXGBE_PF_HIDA(i));
+ raw_desc[i] = raw_desc[i];
+ }
+ }
+
+ /* Read async Admin Command response */
+ if ((hicr & IXGBE_PF_HICR_EV) && !(hicr & IXGBE_PF_HICR_C)) {
+ for (i = 0; i < IXGBE_ACI_DESC_SIZE_IN_DWORDS; i++) {
+ raw_desc[i] = IXGBE_READ_REG(hw, IXGBE_PF_HIDA_2(i));
+ raw_desc[i] = raw_desc[i];
+ }
+ }
+
+ /* Handle timeout and invalid state of HICR register */
+ if (hicr & IXGBE_PF_HICR_C)
+ return -ETIME;
+
+ if (!(hicr & IXGBE_PF_HICR_SV) && !(hicr & IXGBE_PF_HICR_EV))
+ return -EIO;
+
+ /* For every command other than 0x0014 treat opcode mismatch
+ * as an error. Response to 0x0014 command read from HIDA_2
+ * is a descriptor of an event which is expected to contain
+ * different opcode than the command.
+ */
+ if (desc->opcode != cpu_to_le16(opcode) &&
+ opcode != ixgbe_aci_opc_get_fw_event)
+ return -EIO;
+
+ if (desc->retval) {
+ hw->aci.last_status = (enum ixgbe_aci_err)
+ le16_to_cpu(desc->retval);
+ return -EIO;
+ }
+
+ /* Write a response values to a buf */
+ if (valid_buf) {
+ for (i = 0; i < buf_size / 4; i++)
+ ((u32 *)buf)[i] = IXGBE_READ_REG(hw, IXGBE_PF_HIBA(i));
+ if (buf_tail_size) {
+ buf_tail = IXGBE_READ_REG(hw, IXGBE_PF_HIBA(i));
+ memcpy(buf + buf_size - buf_tail_size, &buf_tail,
+ buf_tail_size);
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_aci_send_cmd - send FW Admin Command to FW Admin Command Interface
+ * @hw: pointer to the HW struct
+ * @desc: descriptor describing the command
+ * @buf: buffer to use for indirect commands (NULL for direct commands)
+ * @buf_size: size of buffer for indirect commands (0 for direct commands)
+ *
+ * Helper function to send FW Admin Commands to the FW Admin Command Interface.
+ *
+ * Retry sending the FW Admin Command multiple times to the FW ACI
+ * if the EBUSY Admin Command error is returned.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_aci_send_cmd(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
+ void *buf, u16 buf_size)
+{
+ u16 opcode = le16_to_cpu(desc->opcode);
+ struct ixgbe_aci_desc desc_cpy;
+ enum ixgbe_aci_err last_status;
+ u8 idx = 0, *buf_cpy = NULL;
+ bool is_cmd_for_retry;
+ unsigned long timeout;
+ int err;
+
+ is_cmd_for_retry = ixgbe_should_retry_aci_send_cmd_execute(opcode);
+ if (is_cmd_for_retry) {
+ if (buf) {
+ buf_cpy = kmalloc(buf_size, GFP_KERNEL);
+ if (!buf_cpy)
+ return -ENOMEM;
+ *buf_cpy = *(u8 *)buf;
+ }
+ desc_cpy = *desc;
+ }
+
+ timeout = jiffies + msecs_to_jiffies(IXGBE_ACI_SEND_TIMEOUT_MS);
+ do {
+ mutex_lock(&hw->aci.lock);
+ err = ixgbe_aci_send_cmd_execute(hw, desc, buf, buf_size);
+ last_status = hw->aci.last_status;
+ mutex_unlock(&hw->aci.lock);
+
+ if (!is_cmd_for_retry || !err ||
+ last_status != IXGBE_ACI_RC_EBUSY)
+ break;
+
+ if (buf)
+ memcpy(buf, buf_cpy, buf_size);
+ *desc = desc_cpy;
+
+ msleep(IXGBE_ACI_SEND_DELAY_TIME_MS);
+ } while (++idx < IXGBE_ACI_SEND_MAX_EXECUTE &&
+ time_before(jiffies, timeout));
+
+ kfree(buf_cpy);
+
+ return err;
+}
+
+/**
+ * ixgbe_aci_check_event_pending - check if there are any pending events
+ * @hw: pointer to the HW struct
+ *
+ * Determine if there are any pending events.
+ *
+ * Return: true if there are any currently pending events
+ * otherwise false.
+ */
+bool ixgbe_aci_check_event_pending(struct ixgbe_hw *hw)
+{
+ u32 ep_bit_mask = hw->bus.func ? GL_FWSTS_EP_PF1 : GL_FWSTS_EP_PF0;
+ u32 fwsts = IXGBE_READ_REG(hw, GL_FWSTS);
+
+ return (fwsts & ep_bit_mask) ? true : false;
+}
+
+/**
+ * ixgbe_aci_get_event - get an event from ACI
+ * @hw: pointer to the HW struct
+ * @e: event information structure
+ * @pending: optional flag signaling that there are more pending events
+ *
+ * Obtain an event from ACI and return its content
+ * through 'e' using ACI command (0x0014).
+ * Provide information if there are more events
+ * to retrieve through 'pending'.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_aci_get_event(struct ixgbe_hw *hw, struct ixgbe_aci_event *e,
+ bool *pending)
+{
+ struct ixgbe_aci_desc desc;
+ int err;
+
+ if (!e || (!e->msg_buf && e->buf_len))
+ return -EINVAL;
+
+ mutex_lock(&hw->aci.lock);
+
+ /* Check if there are any events pending */
+ if (!ixgbe_aci_check_event_pending(hw)) {
+ err = -ENOENT;
+ goto aci_get_event_exit;
+ }
+
+ /* Obtain pending event */
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_fw_event);
+ err = ixgbe_aci_send_cmd_execute(hw, &desc, e->msg_buf, e->buf_len);
+ if (err)
+ goto aci_get_event_exit;
+
+ /* Returned 0x0014 opcode indicates that no event was obtained */
+ if (desc.opcode == cpu_to_le16(ixgbe_aci_opc_get_fw_event)) {
+ err = -ENOENT;
+ goto aci_get_event_exit;
+ }
+
+ /* Determine size of event data */
+ e->msg_len = min_t(u16, le16_to_cpu(desc.datalen), e->buf_len);
+ /* Write event descriptor to event info structure */
+ memcpy(&e->desc, &desc, sizeof(e->desc));
+
+ /* Check if there are any further events pending */
+ if (pending)
+ *pending = ixgbe_aci_check_event_pending(hw);
+
+aci_get_event_exit:
+ mutex_unlock(&hw->aci.lock);
+
+ return err;
+}
+
+/**
+ * ixgbe_fill_dflt_direct_cmd_desc - fill ACI descriptor with default values.
+ * @desc: pointer to the temp descriptor (non DMA mem)
+ * @opcode: the opcode can be used to decide which flags to turn off or on
+ *
+ * Helper function to fill the descriptor desc with default values
+ * and the provided opcode.
+ */
+void ixgbe_fill_dflt_direct_cmd_desc(struct ixgbe_aci_desc *desc, u16 opcode)
+{
+ /* Zero out the desc. */
+ memset(desc, 0, sizeof(*desc));
+ desc->opcode = cpu_to_le16(opcode);
+ desc->flags = cpu_to_le16(IXGBE_ACI_FLAG_SI);
+}
+
+/**
+ * ixgbe_aci_req_res - request a common resource
+ * @hw: pointer to the HW struct
+ * @res: resource ID
+ * @access: access type
+ * @sdp_number: resource number
+ * @timeout: the maximum time in ms that the driver may hold the resource
+ *
+ * Requests a common resource using the ACI command (0x0008).
+ * Specifies the maximum time the driver may hold the resource.
+ * If the requested resource is currently occupied by some other driver,
+ * a busy return value is returned and the timeout field value indicates the
+ * maximum time the current owner has to free it.
+ *
+ * Return: the exit code of the operation.
+ */
+static int ixgbe_aci_req_res(struct ixgbe_hw *hw, enum ixgbe_aci_res_ids res,
+ enum ixgbe_aci_res_access_type access,
+ u8 sdp_number, u32 *timeout)
+{
+ struct ixgbe_aci_cmd_req_res *cmd_resp;
+ struct ixgbe_aci_desc desc;
+ int err;
+
+ cmd_resp = &desc.params.res_owner;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_req_res);
+
+ cmd_resp->res_id = cpu_to_le16(res);
+ cmd_resp->access_type = cpu_to_le16(access);
+ cmd_resp->res_number = cpu_to_le32(sdp_number);
+ cmd_resp->timeout = cpu_to_le32(*timeout);
+ *timeout = 0;
+
+ err = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
+
+ /* If the resource is held by some other driver, the command completes
+ * with a busy return value and the timeout field indicates the maximum
+ * time the current owner of the resource has to free it.
+ */
+ if (!err || hw->aci.last_status == IXGBE_ACI_RC_EBUSY)
+ *timeout = le32_to_cpu(cmd_resp->timeout);
+
+ return err;
+}
+
+/**
+ * ixgbe_aci_release_res - release a common resource using ACI
+ * @hw: pointer to the HW struct
+ * @res: resource ID
+ * @sdp_number: resource number
+ *
+ * Release a common resource using ACI command (0x0009).
+ *
+ * Return: the exit code of the operation.
+ */
+static int ixgbe_aci_release_res(struct ixgbe_hw *hw,
+ enum ixgbe_aci_res_ids res, u8 sdp_number)
+{
+ struct ixgbe_aci_cmd_req_res *cmd;
+ struct ixgbe_aci_desc desc;
+
+ cmd = &desc.params.res_owner;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_release_res);
+
+ cmd->res_id = cpu_to_le16(res);
+ cmd->res_number = cpu_to_le32(sdp_number);
+
+ return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
+}
+
+/**
+ * ixgbe_acquire_res - acquire the ownership of a resource
+ * @hw: pointer to the HW structure
+ * @res: resource ID
+ * @access: access type (read or write)
+ * @timeout: timeout in milliseconds
+ *
+ * Make an attempt to acquire the ownership of a resource using
+ * the ixgbe_aci_req_res to utilize ACI.
+ * In case if some other driver has previously acquired the resource and
+ * performed any necessary updates, the -EALREADY is returned,
+ * and the caller does not obtain the resource and has no further work to do.
+ * If needed, the function will poll until the current lock owner timeouts.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_acquire_res(struct ixgbe_hw *hw, enum ixgbe_aci_res_ids res,
+ enum ixgbe_aci_res_access_type access, u32 timeout)
+{
+#define IXGBE_RES_POLLING_DELAY_MS 10
+ u32 delay = IXGBE_RES_POLLING_DELAY_MS;
+ u32 res_timeout = timeout;
+ u32 retry_timeout;
+ int err;
+
+ err = ixgbe_aci_req_res(hw, res, access, 0, &res_timeout);
+
+ /* A return code of -EALREADY means that another driver has
+ * previously acquired the resource and performed any necessary updates;
+ * in this case the caller does not obtain the resource and has no
+ * further work to do.
+ */
+ if (err == -EALREADY)
+ return err;
+
+ /* If necessary, poll until the current lock owner timeouts.
+ * Set retry_timeout to the timeout value reported by the FW in the
+ * response to the "Request Resource Ownership" (0x0008) Admin Command
+ * as it indicates the maximum time the current owner of the resource
+ * is allowed to hold it.
+ */
+ retry_timeout = res_timeout;
+ while (err && retry_timeout && res_timeout) {
+ msleep(delay);
+ retry_timeout = (retry_timeout > delay) ?
+ retry_timeout - delay : 0;
+ err = ixgbe_aci_req_res(hw, res, access, 0, &res_timeout);
+
+ /* Success - lock acquired.
+ * -EALREADY - lock free, no work to do.
+ */
+ if (!err || err == -EALREADY)
+ break;
+ }
+
+ return err;
+}
+
+/**
+ * ixgbe_release_res - release a common resource
+ * @hw: pointer to the HW structure
+ * @res: resource ID
+ *
+ * Release a common resource using ixgbe_aci_release_res.
+ */
+void ixgbe_release_res(struct ixgbe_hw *hw, enum ixgbe_aci_res_ids res)
+{
+ u32 total_delay = 0;
+ int err;
+
+ err = ixgbe_aci_release_res(hw, res, 0);
+
+ /* There are some rare cases when trying to release the resource
+ * results in an admin command timeout, so handle them correctly.
+ */
+ while (err == -ETIME &&
+ total_delay < IXGBE_ACI_RELEASE_RES_TIMEOUT) {
+ usleep_range(1000, 1500);
+ err = ixgbe_aci_release_res(hw, res, 0);
+ total_delay++;
+ }
+}
+
+/**
+ * ixgbe_parse_e610_caps - Parse common device/function capabilities
+ * @hw: pointer to the HW struct
+ * @caps: pointer to common capabilities structure
+ * @elem: the capability element to parse
+ * @prefix: message prefix for tracing capabilities
+ *
+ * Given a capability element, extract relevant details into the common
+ * capability structure.
+ *
+ * Return: true if the capability matches one of the common capability ids,
+ * false otherwise.
+ */
+static bool ixgbe_parse_e610_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_caps *caps,
+ struct ixgbe_aci_cmd_list_caps_elem *elem,
+ const char *prefix)
+{
+ u32 logical_id = le32_to_cpu(elem->logical_id);
+ u32 phys_id = le32_to_cpu(elem->phys_id);
+ u32 number = le32_to_cpu(elem->number);
+ u16 cap = le16_to_cpu(elem->cap);
+
+ switch (cap) {
+ case IXGBE_ACI_CAPS_VALID_FUNCTIONS:
+ caps->valid_functions = number;
+ break;
+ case IXGBE_ACI_CAPS_SRIOV:
+ caps->sr_iov_1_1 = (number == 1);
+ break;
+ case IXGBE_ACI_CAPS_VMDQ:
+ caps->vmdq = (number == 1);
+ break;
+ case IXGBE_ACI_CAPS_DCB:
+ caps->dcb = (number == 1);
+ caps->active_tc_bitmap = logical_id;
+ caps->maxtc = phys_id;
+ break;
+ case IXGBE_ACI_CAPS_RSS:
+ caps->rss_table_size = number;
+ caps->rss_table_entry_width = logical_id;
+ break;
+ case IXGBE_ACI_CAPS_RXQS:
+ caps->num_rxq = number;
+ caps->rxq_first_id = phys_id;
+ break;
+ case IXGBE_ACI_CAPS_TXQS:
+ caps->num_txq = number;
+ caps->txq_first_id = phys_id;
+ break;
+ case IXGBE_ACI_CAPS_MSIX:
+ caps->num_msix_vectors = number;
+ caps->msix_vector_first_id = phys_id;
+ break;
+ case IXGBE_ACI_CAPS_NVM_VER:
+ break;
+ case IXGBE_ACI_CAPS_MAX_MTU:
+ caps->max_mtu = number;
+ break;
+ case IXGBE_ACI_CAPS_PCIE_RESET_AVOIDANCE:
+ caps->pcie_reset_avoidance = (number > 0);
+ break;
+ case IXGBE_ACI_CAPS_POST_UPDATE_RESET_RESTRICT:
+ caps->reset_restrict_support = (number == 1);
+ break;
+ case IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG0:
+ case IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG1:
+ case IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG2:
+ case IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG3:
+ {
+ u8 index = cap - IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG0;
+
+ caps->ext_topo_dev_img_ver_high[index] = number;
+ caps->ext_topo_dev_img_ver_low[index] = logical_id;
+ caps->ext_topo_dev_img_part_num[index] =
+ FIELD_GET(IXGBE_EXT_TOPO_DEV_IMG_PART_NUM_M, phys_id);
+ caps->ext_topo_dev_img_load_en[index] =
+ (phys_id & IXGBE_EXT_TOPO_DEV_IMG_LOAD_EN) != 0;
+ caps->ext_topo_dev_img_prog_en[index] =
+ (phys_id & IXGBE_EXT_TOPO_DEV_IMG_PROG_EN) != 0;
+ break;
+ }
+ default:
+ /* Not one of the recognized common capabilities */
+ return false;
+ }
+
+ return true;
+}
+
+/**
+ * ixgbe_parse_valid_functions_cap - Parse IXGBE_ACI_CAPS_VALID_FUNCTIONS caps
+ * @hw: pointer to the HW struct
+ * @dev_p: pointer to device capabilities structure
+ * @cap: capability element to parse
+ *
+ * Parse IXGBE_ACI_CAPS_VALID_FUNCTIONS for device capabilities.
+ */
+static void
+ixgbe_parse_valid_functions_cap(struct ixgbe_hw *hw,
+ struct ixgbe_hw_dev_caps *dev_p,
+ struct ixgbe_aci_cmd_list_caps_elem *cap)
+{
+ dev_p->num_funcs = hweight32(le32_to_cpu(cap->number));
+}
+
+/**
+ * ixgbe_parse_vf_dev_caps - Parse IXGBE_ACI_CAPS_VF device caps
+ * @hw: pointer to the HW struct
+ * @dev_p: pointer to device capabilities structure
+ * @cap: capability element to parse
+ *
+ * Parse IXGBE_ACI_CAPS_VF for device capabilities.
+ */
+static void ixgbe_parse_vf_dev_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_dev_caps *dev_p,
+ struct ixgbe_aci_cmd_list_caps_elem *cap)
+{
+ dev_p->num_vfs_exposed = le32_to_cpu(cap->number);
+}
+
+/**
+ * ixgbe_parse_vsi_dev_caps - Parse IXGBE_ACI_CAPS_VSI device caps
+ * @hw: pointer to the HW struct
+ * @dev_p: pointer to device capabilities structure
+ * @cap: capability element to parse
+ *
+ * Parse IXGBE_ACI_CAPS_VSI for device capabilities.
+ */
+static void ixgbe_parse_vsi_dev_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_dev_caps *dev_p,
+ struct ixgbe_aci_cmd_list_caps_elem *cap)
+{
+ dev_p->num_vsi_allocd_to_host = le32_to_cpu(cap->number);
+}
+
+/**
+ * ixgbe_parse_fdir_dev_caps - Parse IXGBE_ACI_CAPS_FD device caps
+ * @hw: pointer to the HW struct
+ * @dev_p: pointer to device capabilities structure
+ * @cap: capability element to parse
+ *
+ * Parse IXGBE_ACI_CAPS_FD for device capabilities.
+ */
+static void ixgbe_parse_fdir_dev_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_dev_caps *dev_p,
+ struct ixgbe_aci_cmd_list_caps_elem *cap)
+{
+ dev_p->num_flow_director_fltr = le32_to_cpu(cap->number);
+}
+
+/**
+ * ixgbe_parse_dev_caps - Parse device capabilities
+ * @hw: pointer to the HW struct
+ * @dev_p: pointer to device capabilities structure
+ * @buf: buffer containing the device capability records
+ * @cap_count: the number of capabilities
+ *
+ * Helper device to parse device (0x000B) capabilities list. For
+ * capabilities shared between device and function, this relies on
+ * ixgbe_parse_e610_caps.
+ *
+ * Loop through the list of provided capabilities and extract the relevant
+ * data into the device capabilities structured.
+ */
+static void ixgbe_parse_dev_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_dev_caps *dev_p,
+ void *buf, u32 cap_count)
+{
+ struct ixgbe_aci_cmd_list_caps_elem *cap_resp;
+ u32 i;
+
+ cap_resp = (struct ixgbe_aci_cmd_list_caps_elem *)buf;
+
+ memset(dev_p, 0, sizeof(*dev_p));
+
+ for (i = 0; i < cap_count; i++) {
+ u16 cap = le16_to_cpu(cap_resp[i].cap);
+
+ ixgbe_parse_e610_caps(hw, &dev_p->common_cap, &cap_resp[i],
+ "dev caps");
+
+ switch (cap) {
+ case IXGBE_ACI_CAPS_VALID_FUNCTIONS:
+ ixgbe_parse_valid_functions_cap(hw, dev_p,
+ &cap_resp[i]);
+ break;
+ case IXGBE_ACI_CAPS_VF:
+ ixgbe_parse_vf_dev_caps(hw, dev_p, &cap_resp[i]);
+ break;
+ case IXGBE_ACI_CAPS_VSI:
+ ixgbe_parse_vsi_dev_caps(hw, dev_p, &cap_resp[i]);
+ break;
+ case IXGBE_ACI_CAPS_FD:
+ ixgbe_parse_fdir_dev_caps(hw, dev_p, &cap_resp[i]);
+ break;
+ default:
+ /* Don't list common capabilities as unknown */
+ break;
+ }
+ }
+}
+
+/**
+ * ixgbe_parse_vf_func_caps - Parse IXGBE_ACI_CAPS_VF function caps
+ * @hw: pointer to the HW struct
+ * @func_p: pointer to function capabilities structure
+ * @cap: pointer to the capability element to parse
+ *
+ * Extract function capabilities for IXGBE_ACI_CAPS_VF.
+ */
+static void ixgbe_parse_vf_func_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_func_caps *func_p,
+ struct ixgbe_aci_cmd_list_caps_elem *cap)
+{
+ func_p->num_allocd_vfs = le32_to_cpu(cap->number);
+ func_p->vf_base_id = le32_to_cpu(cap->logical_id);
+}
+
+/**
+ * ixgbe_get_num_per_func - determine number of resources per PF
+ * @hw: pointer to the HW structure
+ * @max: value to be evenly split between each PF
+ *
+ * Determine the number of valid functions by going through the bitmap returned
+ * from parsing capabilities and use this to calculate the number of resources
+ * per PF based on the max value passed in.
+ *
+ * Return: the number of resources per PF or 0, if no PH are available.
+ */
+static u32 ixgbe_get_num_per_func(struct ixgbe_hw *hw, u32 max)
+{
+#define IXGBE_CAPS_VALID_FUNCS_M GENMASK(7, 0)
+ u8 funcs = hweight8(hw->dev_caps.common_cap.valid_functions &
+ IXGBE_CAPS_VALID_FUNCS_M);
+
+ return funcs ? (max / funcs) : 0;
+}
+
+/**
+ * ixgbe_parse_vsi_func_caps - Parse IXGBE_ACI_CAPS_VSI function caps
+ * @hw: pointer to the HW struct
+ * @func_p: pointer to function capabilities structure
+ * @cap: pointer to the capability element to parse
+ *
+ * Extract function capabilities for IXGBE_ACI_CAPS_VSI.
+ */
+static void ixgbe_parse_vsi_func_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_func_caps *func_p,
+ struct ixgbe_aci_cmd_list_caps_elem *cap)
+{
+ func_p->guar_num_vsi = ixgbe_get_num_per_func(hw, IXGBE_MAX_VSI);
+}
+
+/**
+ * ixgbe_parse_func_caps - Parse function capabilities
+ * @hw: pointer to the HW struct
+ * @func_p: pointer to function capabilities structure
+ * @buf: buffer containing the function capability records
+ * @cap_count: the number of capabilities
+ *
+ * Helper function to parse function (0x000A) capabilities list. For
+ * capabilities shared between device and function, this relies on
+ * ixgbe_parse_e610_caps.
+ *
+ * Loop through the list of provided capabilities and extract the relevant
+ * data into the function capabilities structured.
+ */
+static void ixgbe_parse_func_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_func_caps *func_p,
+ void *buf, u32 cap_count)
+{
+ struct ixgbe_aci_cmd_list_caps_elem *cap_resp;
+ u32 i;
+
+ cap_resp = (struct ixgbe_aci_cmd_list_caps_elem *)buf;
+
+ memset(func_p, 0, sizeof(*func_p));
+
+ for (i = 0; i < cap_count; i++) {
+ u16 cap = le16_to_cpu(cap_resp[i].cap);
+
+ ixgbe_parse_e610_caps(hw, &func_p->common_cap,
+ &cap_resp[i], "func caps");
+
+ switch (cap) {
+ case IXGBE_ACI_CAPS_VF:
+ ixgbe_parse_vf_func_caps(hw, func_p, &cap_resp[i]);
+ break;
+ case IXGBE_ACI_CAPS_VSI:
+ ixgbe_parse_vsi_func_caps(hw, func_p, &cap_resp[i]);
+ break;
+ default:
+ /* Don't list common capabilities as unknown */
+ break;
+ }
+ }
+}
+
+/**
+ * ixgbe_aci_list_caps - query function/device capabilities
+ * @hw: pointer to the HW struct
+ * @buf: a buffer to hold the capabilities
+ * @buf_size: size of the buffer
+ * @cap_count: if not NULL, set to the number of capabilities reported
+ * @opc: capabilities type to discover, device or function
+ *
+ * Get the function (0x000A) or device (0x000B) capabilities description from
+ * firmware and store it in the buffer.
+ *
+ * If the cap_count pointer is not NULL, then it is set to the number of
+ * capabilities firmware will report. Note that if the buffer size is too
+ * small, it is possible the command will return -ENOMEM. The
+ * cap_count will still be updated in this case. It is recommended that the
+ * buffer size be set to IXGBE_ACI_MAX_BUFFER_SIZE (the largest possible
+ * buffer that firmware could return) to avoid this.
+ *
+ * Return: the exit code of the operation.
+ * Exit code of -ENOMEM means the buffer size is too small.
+ */
+int ixgbe_aci_list_caps(struct ixgbe_hw *hw, void *buf, u16 buf_size,
+ u32 *cap_count, enum ixgbe_aci_opc opc)
+{
+ struct ixgbe_aci_cmd_list_caps *cmd;
+ struct ixgbe_aci_desc desc;
+ int err;
+
+ cmd = &desc.params.get_cap;
+
+ if (opc != ixgbe_aci_opc_list_func_caps &&
+ opc != ixgbe_aci_opc_list_dev_caps)
+ return -EINVAL;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, opc);
+ err = ixgbe_aci_send_cmd(hw, &desc, buf, buf_size);
+
+ if (cap_count)
+ *cap_count = le32_to_cpu(cmd->count);
+
+ return err;
+}
+
+/**
+ * ixgbe_discover_dev_caps - Read and extract device capabilities
+ * @hw: pointer to the hardware structure
+ * @dev_caps: pointer to device capabilities structure
+ *
+ * Read the device capabilities and extract them into the dev_caps structure
+ * for later use.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_discover_dev_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_dev_caps *dev_caps)
+{
+ u32 cap_count;
+ u8 *cbuf;
+ int err;
+
+ cbuf = kzalloc(IXGBE_ACI_MAX_BUFFER_SIZE, GFP_KERNEL);
+ if (!cbuf)
+ return -ENOMEM;
+
+ /* Although the driver doesn't know the number of capabilities the
+ * device will return, we can simply send a 4KB buffer, the maximum
+ * possible size that firmware can return.
+ */
+ cap_count = IXGBE_ACI_MAX_BUFFER_SIZE /
+ sizeof(struct ixgbe_aci_cmd_list_caps_elem);
+
+ err = ixgbe_aci_list_caps(hw, cbuf, IXGBE_ACI_MAX_BUFFER_SIZE,
+ &cap_count,
+ ixgbe_aci_opc_list_dev_caps);
+ if (!err)
+ ixgbe_parse_dev_caps(hw, dev_caps, cbuf, cap_count);
+
+ kfree(cbuf);
+
+ return 0;
+}
+
+/**
+ * ixgbe_discover_func_caps - Read and extract function capabilities
+ * @hw: pointer to the hardware structure
+ * @func_caps: pointer to function capabilities structure
+ *
+ * Read the function capabilities and extract them into the func_caps structure
+ * for later use.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_discover_func_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_func_caps *func_caps)
+{
+ u32 cap_count;
+ u8 *cbuf;
+ int err;
+
+ cbuf = kzalloc(IXGBE_ACI_MAX_BUFFER_SIZE, GFP_KERNEL);
+ if (!cbuf)
+ return -ENOMEM;
+
+ /* Although the driver doesn't know the number of capabilities the
+ * device will return, we can simply send a 4KB buffer, the maximum
+ * possible size that firmware can return.
+ */
+ cap_count = IXGBE_ACI_MAX_BUFFER_SIZE /
+ sizeof(struct ixgbe_aci_cmd_list_caps_elem);
+
+ err = ixgbe_aci_list_caps(hw, cbuf, IXGBE_ACI_MAX_BUFFER_SIZE,
+ &cap_count,
+ ixgbe_aci_opc_list_func_caps);
+ if (!err)
+ ixgbe_parse_func_caps(hw, func_caps, cbuf, cap_count);
+
+ kfree(cbuf);
+
+ return 0;
+}
+
+/**
+ * ixgbe_get_caps - get info about the HW
+ * @hw: pointer to the hardware structure
+ *
+ * Retrieve both device and function capabilities.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_get_caps(struct ixgbe_hw *hw)
+{
+ int err;
+
+ err = ixgbe_discover_dev_caps(hw, &hw->dev_caps);
+ if (err)
+ return err;
+
+ return ixgbe_discover_func_caps(hw, &hw->func_caps);
+}
+
+/**
+ * ixgbe_aci_disable_rxen - disable RX
+ * @hw: pointer to the HW struct
+ *
+ * Request a safe disable of Receive Enable using ACI command (0x000C).
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_aci_disable_rxen(struct ixgbe_hw *hw)
+{
+ struct ixgbe_aci_cmd_disable_rxen *cmd;
+ struct ixgbe_aci_desc desc;
+
+ cmd = &desc.params.disable_rxen;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_disable_rxen);
+
+ cmd->lport_num = hw->bus.func;
+
+ return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
+}
+
+/**
+ * ixgbe_aci_get_phy_caps - returns PHY capabilities
+ * @hw: pointer to the HW struct
+ * @qual_mods: report qualified modules
+ * @report_mode: report mode capabilities
+ * @pcaps: structure for PHY capabilities to be filled
+ *
+ * Returns the various PHY capabilities supported on the Port
+ * using ACI command (0x0600).
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_aci_get_phy_caps(struct ixgbe_hw *hw, bool qual_mods, u8 report_mode,
+ struct ixgbe_aci_cmd_get_phy_caps_data *pcaps)
+{
+ struct ixgbe_aci_cmd_get_phy_caps *cmd;
+ u16 pcaps_size = sizeof(*pcaps);
+ struct ixgbe_aci_desc desc;
+ int err;
+
+ cmd = &desc.params.get_phy;
+
+ if (!pcaps || (report_mode & ~IXGBE_ACI_REPORT_MODE_M))
+ return -EINVAL;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_phy_caps);
+
+ if (qual_mods)
+ cmd->param0 |= cpu_to_le16(IXGBE_ACI_GET_PHY_RQM);
+
+ cmd->param0 |= cpu_to_le16(report_mode);
+ err = ixgbe_aci_send_cmd(hw, &desc, pcaps, pcaps_size);
+ if (!err && report_mode == IXGBE_ACI_REPORT_TOPO_CAP_MEDIA) {
+ hw->phy.phy_type_low = le64_to_cpu(pcaps->phy_type_low);
+ hw->phy.phy_type_high = le64_to_cpu(pcaps->phy_type_high);
+ memcpy(hw->link.link_info.module_type, &pcaps->module_type,
+ sizeof(hw->link.link_info.module_type));
+ }
+
+ return err;
+}
+
+/**
+ * ixgbe_copy_phy_caps_to_cfg - Copy PHY ability data to configuration data
+ * @caps: PHY ability structure to copy data from
+ * @cfg: PHY configuration structure to copy data to
+ *
+ * Helper function to copy data from PHY capabilities data structure
+ * to PHY configuration data structure
+ */
+void ixgbe_copy_phy_caps_to_cfg(struct ixgbe_aci_cmd_get_phy_caps_data *caps,
+ struct ixgbe_aci_cmd_set_phy_cfg_data *cfg)
+{
+ if (!caps || !cfg)
+ return;
+
+ memset(cfg, 0, sizeof(*cfg));
+ cfg->phy_type_low = caps->phy_type_low;
+ cfg->phy_type_high = caps->phy_type_high;
+ cfg->caps = caps->caps;
+ cfg->low_power_ctrl_an = caps->low_power_ctrl_an;
+ cfg->eee_cap = caps->eee_cap;
+ cfg->eeer_value = caps->eeer_value;
+ cfg->link_fec_opt = caps->link_fec_options;
+ cfg->module_compliance_enforcement =
+ caps->module_compliance_enforcement;
+}
+
+/**
+ * ixgbe_aci_set_phy_cfg - set PHY configuration
+ * @hw: pointer to the HW struct
+ * @cfg: structure with PHY configuration data to be set
+ *
+ * Set the various PHY configuration parameters supported on the Port
+ * using ACI command (0x0601).
+ * One or more of the Set PHY config parameters may be ignored in an MFP
+ * mode as the PF may not have the privilege to set some of the PHY Config
+ * parameters.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_aci_set_phy_cfg(struct ixgbe_hw *hw,
+ struct ixgbe_aci_cmd_set_phy_cfg_data *cfg)
+{
+ struct ixgbe_aci_desc desc;
+ int err;
+
+ if (!cfg)
+ return -EINVAL;
+
+ /* Ensure that only valid bits of cfg->caps can be turned on. */
+ cfg->caps &= IXGBE_ACI_PHY_ENA_VALID_MASK;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_set_phy_cfg);
+ desc.params.set_phy.lport_num = hw->bus.func;
+ desc.flags |= cpu_to_le16(IXGBE_ACI_FLAG_RD);
+
+ err = ixgbe_aci_send_cmd(hw, &desc, cfg, sizeof(*cfg));
+ if (!err)
+ hw->phy.curr_user_phy_cfg = *cfg;
+
+ return err;
+}
+
+/**
+ * ixgbe_aci_set_link_restart_an - set up link and restart AN
+ * @hw: pointer to the HW struct
+ * @ena_link: if true: enable link, if false: disable link
+ *
+ * Function sets up the link and restarts the Auto-Negotiation over the link.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_aci_set_link_restart_an(struct ixgbe_hw *hw, bool ena_link)
+{
+ struct ixgbe_aci_cmd_restart_an *cmd;
+ struct ixgbe_aci_desc desc;
+
+ cmd = &desc.params.restart_an;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_restart_an);
+
+ cmd->cmd_flags = IXGBE_ACI_RESTART_AN_LINK_RESTART;
+ cmd->lport_num = hw->bus.func;
+ if (ena_link)
+ cmd->cmd_flags |= IXGBE_ACI_RESTART_AN_LINK_ENABLE;
+ else
+ cmd->cmd_flags &= ~IXGBE_ACI_RESTART_AN_LINK_ENABLE;
+
+ return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
+}
+
+/**
+ * ixgbe_is_media_cage_present - check if media cage is present
+ * @hw: pointer to the HW struct
+ *
+ * Identify presence of media cage using the ACI command (0x06E0).
+ *
+ * Return: true if media cage is present, else false. If no cage, then
+ * media type is backplane or BASE-T.
+ */
+static bool ixgbe_is_media_cage_present(struct ixgbe_hw *hw)
+{
+ struct ixgbe_aci_cmd_get_link_topo *cmd;
+ struct ixgbe_aci_desc desc;
+
+ cmd = &desc.params.get_link_topo;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_link_topo);
+
+ cmd->addr.topo_params.node_type_ctx =
+ FIELD_PREP(IXGBE_ACI_LINK_TOPO_NODE_CTX_M,
+ IXGBE_ACI_LINK_TOPO_NODE_CTX_PORT);
+
+ /* Set node type. */
+ cmd->addr.topo_params.node_type_ctx |=
+ FIELD_PREP(IXGBE_ACI_LINK_TOPO_NODE_TYPE_M,
+ IXGBE_ACI_LINK_TOPO_NODE_TYPE_CAGE);
+
+ /* Node type cage can be used to determine if cage is present. If AQC
+ * returns error (ENOENT), then no cage present. If no cage present then
+ * connection type is backplane or BASE-T.
+ */
+ return ixgbe_aci_get_netlist_node(hw, cmd, NULL, NULL);
+}
+
+/**
+ * ixgbe_get_media_type_from_phy_type - Gets media type based on phy type
+ * @hw: pointer to the HW struct
+ *
+ * Try to identify the media type based on the phy type.
+ * If more than one media type, the ixgbe_media_type_unknown is returned.
+ * First, phy_type_low is checked, then phy_type_high.
+ * If none are identified, the ixgbe_media_type_unknown is returned
+ *
+ * Return: type of a media based on phy type in form of enum.
+ */
+static enum ixgbe_media_type
+ixgbe_get_media_type_from_phy_type(struct ixgbe_hw *hw)
+{
+ struct ixgbe_link_status *hw_link_info;
+
+ if (!hw)
+ return ixgbe_media_type_unknown;
+
+ hw_link_info = &hw->link.link_info;
+ if (hw_link_info->phy_type_low && hw_link_info->phy_type_high)
+ /* If more than one media type is selected, report unknown */
+ return ixgbe_media_type_unknown;
+
+ if (hw_link_info->phy_type_low) {
+ /* 1G SGMII is a special case where some DA cable PHYs
+ * may show this as an option when it really shouldn't
+ * be since SGMII is meant to be between a MAC and a PHY
+ * in a backplane. Try to detect this case and handle it
+ */
+ if (hw_link_info->phy_type_low == IXGBE_PHY_TYPE_LOW_1G_SGMII &&
+ (hw_link_info->module_type[IXGBE_ACI_MOD_TYPE_IDENT] ==
+ IXGBE_ACI_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE ||
+ hw_link_info->module_type[IXGBE_ACI_MOD_TYPE_IDENT] ==
+ IXGBE_ACI_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE))
+ return ixgbe_media_type_da;
+
+ switch (hw_link_info->phy_type_low) {
+ case IXGBE_PHY_TYPE_LOW_1000BASE_SX:
+ case IXGBE_PHY_TYPE_LOW_1000BASE_LX:
+ case IXGBE_PHY_TYPE_LOW_10GBASE_SR:
+ case IXGBE_PHY_TYPE_LOW_10GBASE_LR:
+ case IXGBE_PHY_TYPE_LOW_25GBASE_SR:
+ case IXGBE_PHY_TYPE_LOW_25GBASE_LR:
+ return ixgbe_media_type_fiber;
+ case IXGBE_PHY_TYPE_LOW_10G_SFI_AOC_ACC:
+ case IXGBE_PHY_TYPE_LOW_25G_AUI_AOC_ACC:
+ return ixgbe_media_type_fiber;
+ case IXGBE_PHY_TYPE_LOW_100BASE_TX:
+ case IXGBE_PHY_TYPE_LOW_1000BASE_T:
+ case IXGBE_PHY_TYPE_LOW_2500BASE_T:
+ case IXGBE_PHY_TYPE_LOW_5GBASE_T:
+ case IXGBE_PHY_TYPE_LOW_10GBASE_T:
+ case IXGBE_PHY_TYPE_LOW_25GBASE_T:
+ return ixgbe_media_type_copper;
+ case IXGBE_PHY_TYPE_LOW_10G_SFI_DA:
+ case IXGBE_PHY_TYPE_LOW_25GBASE_CR:
+ case IXGBE_PHY_TYPE_LOW_25GBASE_CR_S:
+ case IXGBE_PHY_TYPE_LOW_25GBASE_CR1:
+ return ixgbe_media_type_da;
+ case IXGBE_PHY_TYPE_LOW_25G_AUI_C2C:
+ if (ixgbe_is_media_cage_present(hw))
+ return ixgbe_media_type_aui;
+ fallthrough;
+ case IXGBE_PHY_TYPE_LOW_1000BASE_KX:
+ case IXGBE_PHY_TYPE_LOW_2500BASE_KX:
+ case IXGBE_PHY_TYPE_LOW_2500BASE_X:
+ case IXGBE_PHY_TYPE_LOW_5GBASE_KR:
+ case IXGBE_PHY_TYPE_LOW_10GBASE_KR_CR1:
+ case IXGBE_PHY_TYPE_LOW_10G_SFI_C2C:
+ case IXGBE_PHY_TYPE_LOW_25GBASE_KR:
+ case IXGBE_PHY_TYPE_LOW_25GBASE_KR1:
+ case IXGBE_PHY_TYPE_LOW_25GBASE_KR_S:
+ return ixgbe_media_type_backplane;
+ }
+ } else {
+ switch (hw_link_info->phy_type_high) {
+ case IXGBE_PHY_TYPE_HIGH_10BASE_T:
+ return ixgbe_media_type_copper;
+ }
+ }
+ return ixgbe_media_type_unknown;
+}
+
+/**
+ * ixgbe_update_link_info - update status of the HW network link
+ * @hw: pointer to the HW struct
+ *
+ * Update the status of the HW network link.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_update_link_info(struct ixgbe_hw *hw)
+{
+ struct ixgbe_aci_cmd_get_phy_caps_data *pcaps;
+ struct ixgbe_link_status *li;
+ int err;
+
+ if (!hw)
+ return -EINVAL;
+
+ li = &hw->link.link_info;
+
+ err = ixgbe_aci_get_link_info(hw, true, NULL);
+ if (err)
+ return err;
+
+ if (!(li->link_info & IXGBE_ACI_MEDIA_AVAILABLE))
+ return 0;
+
+ pcaps = kzalloc(sizeof(*pcaps), GFP_KERNEL);
+ if (!pcaps)
+ return -ENOMEM;
+
+ err = ixgbe_aci_get_phy_caps(hw, false, IXGBE_ACI_REPORT_TOPO_CAP_MEDIA,
+ pcaps);
+
+ if (!err)
+ memcpy(li->module_type, &pcaps->module_type,
+ sizeof(li->module_type));
+
+ kfree(pcaps);
+
+ return err;
+}
+
+/**
+ * ixgbe_get_link_status - get status of the HW network link
+ * @hw: pointer to the HW struct
+ * @link_up: pointer to bool (true/false = linkup/linkdown)
+ *
+ * Variable link_up is true if link is up, false if link is down.
+ * The variable link_up is invalid if status is non zero. As a
+ * result of this call, link status reporting becomes enabled
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_get_link_status(struct ixgbe_hw *hw, bool *link_up)
+{
+ if (!hw || !link_up)
+ return -EINVAL;
+
+ if (hw->link.get_link_info) {
+ int err = ixgbe_update_link_info(hw);
+
+ if (err)
+ return err;
+ }
+
+ *link_up = hw->link.link_info.link_info & IXGBE_ACI_LINK_UP;
+
+ return 0;
+}
+
+/**
+ * ixgbe_aci_get_link_info - get the link status
+ * @hw: pointer to the HW struct
+ * @ena_lse: enable/disable LinkStatusEvent reporting
+ * @link: pointer to link status structure - optional
+ *
+ * Get the current Link Status using ACI command (0x607).
+ * The current link can be optionally provided to update
+ * the status.
+ *
+ * Return: the link status of the adapter.
+ */
+int ixgbe_aci_get_link_info(struct ixgbe_hw *hw, bool ena_lse,
+ struct ixgbe_link_status *link)
+{
+ struct ixgbe_aci_cmd_get_link_status_data link_data = {};
+ struct ixgbe_aci_cmd_get_link_status *resp;
+ struct ixgbe_link_status *li_old, *li;
+ struct ixgbe_fc_info *hw_fc_info;
+ struct ixgbe_aci_desc desc;
+ bool tx_pause, rx_pause;
+ u8 cmd_flags;
+ int err;
+
+ if (!hw)
+ return -EINVAL;
+
+ li_old = &hw->link.link_info_old;
+ li = &hw->link.link_info;
+ hw_fc_info = &hw->fc;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_link_status);
+ cmd_flags = (ena_lse) ? IXGBE_ACI_LSE_ENA : IXGBE_ACI_LSE_DIS;
+ resp = &desc.params.get_link_status;
+ resp->cmd_flags = cpu_to_le16(cmd_flags);
+ resp->lport_num = hw->bus.func;
+
+ err = ixgbe_aci_send_cmd(hw, &desc, &link_data, sizeof(link_data));
+ if (err)
+ return err;
+
+ /* Save off old link status information. */
+ *li_old = *li;
+
+ /* Update current link status information. */
+ li->link_speed = le16_to_cpu(link_data.link_speed);
+ li->phy_type_low = le64_to_cpu(link_data.phy_type_low);
+ li->phy_type_high = le64_to_cpu(link_data.phy_type_high);
+ li->link_info = link_data.link_info;
+ li->link_cfg_err = link_data.link_cfg_err;
+ li->an_info = link_data.an_info;
+ li->ext_info = link_data.ext_info;
+ li->max_frame_size = le16_to_cpu(link_data.max_frame_size);
+ li->fec_info = link_data.cfg & IXGBE_ACI_FEC_MASK;
+ li->topo_media_conflict = link_data.topo_media_conflict;
+ li->pacing = link_data.cfg & (IXGBE_ACI_CFG_PACING_M |
+ IXGBE_ACI_CFG_PACING_TYPE_M);
+
+ /* Update fc info. */
+ tx_pause = !!(link_data.an_info & IXGBE_ACI_LINK_PAUSE_TX);
+ rx_pause = !!(link_data.an_info & IXGBE_ACI_LINK_PAUSE_RX);
+ if (tx_pause && rx_pause)
+ hw_fc_info->current_mode = ixgbe_fc_full;
+ else if (tx_pause)
+ hw_fc_info->current_mode = ixgbe_fc_tx_pause;
+ else if (rx_pause)
+ hw_fc_info->current_mode = ixgbe_fc_rx_pause;
+ else
+ hw_fc_info->current_mode = ixgbe_fc_none;
+
+ li->lse_ena = !!(le16_to_cpu(resp->cmd_flags) &
+ IXGBE_ACI_LSE_IS_ENABLED);
+
+ /* Save link status information. */
+ if (link)
+ *link = *li;
+
+ /* Flag cleared so calling functions don't call AQ again. */
+ hw->link.get_link_info = false;
+
+ return 0;
+}
+
+/**
+ * ixgbe_aci_set_event_mask - set event mask
+ * @hw: pointer to the HW struct
+ * @port_num: port number of the physical function
+ * @mask: event mask to be set
+ *
+ * Set the event mask using ACI command (0x0613).
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_aci_set_event_mask(struct ixgbe_hw *hw, u8 port_num, u16 mask)
+{
+ struct ixgbe_aci_cmd_set_event_mask *cmd;
+ struct ixgbe_aci_desc desc;
+
+ cmd = &desc.params.set_event_mask;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_set_event_mask);
+
+ cmd->lport_num = port_num;
+
+ cmd->event_mask = cpu_to_le16(mask);
+ return ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
+}
+
+/**
+ * ixgbe_configure_lse - enable/disable link status events
+ * @hw: pointer to the HW struct
+ * @activate: true for enable lse, false otherwise
+ * @mask: event mask to be set; a set bit means deactivation of the
+ * corresponding event
+ *
+ * Set the event mask and then enable or disable link status events
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_configure_lse(struct ixgbe_hw *hw, bool activate, u16 mask)
+{
+ int err;
+
+ err = ixgbe_aci_set_event_mask(hw, (u8)hw->bus.func, mask);
+ if (err)
+ return err;
+
+ /* Enabling link status events generation by fw. */
+ return ixgbe_aci_get_link_info(hw, activate, NULL);
+}
+
+/**
+ * ixgbe_get_media_type_e610 - Gets media type
+ * @hw: pointer to the HW struct
+ *
+ * In order to get the media type, the function gets PHY
+ * capabilities and later on use them to identify the PHY type
+ * checking phy_type_high and phy_type_low.
+ *
+ * Return: the type of media in form of ixgbe_media_type enum
+ * or ixgbe_media_type_unknown in case of an error.
+ */
+enum ixgbe_media_type ixgbe_get_media_type_e610(struct ixgbe_hw *hw)
+{
+ struct ixgbe_aci_cmd_get_phy_caps_data pcaps;
+ int rc;
+
+ rc = ixgbe_update_link_info(hw);
+ if (rc)
+ return ixgbe_media_type_unknown;
+
+ /* If there is no link but PHY (dongle) is available SW should use
+ * Get PHY Caps admin command instead of Get Link Status, find most
+ * significant bit that is set in PHY types reported by the command
+ * and use it to discover media type.
+ */
+ if (!(hw->link.link_info.link_info & IXGBE_ACI_LINK_UP) &&
+ (hw->link.link_info.link_info & IXGBE_ACI_MEDIA_AVAILABLE)) {
+ int highest_bit;
+
+ /* Get PHY Capabilities */
+ rc = ixgbe_aci_get_phy_caps(hw, false,
+ IXGBE_ACI_REPORT_TOPO_CAP_MEDIA,
+ &pcaps);
+ if (rc)
+ return ixgbe_media_type_unknown;
+
+ highest_bit = fls64(le64_to_cpu(pcaps.phy_type_high));
+ if (highest_bit) {
+ hw->link.link_info.phy_type_high =
+ BIT_ULL(highest_bit - 1);
+ hw->link.link_info.phy_type_low = 0;
+ } else {
+ highest_bit = fls64(le64_to_cpu(pcaps.phy_type_low));
+ if (highest_bit)
+ hw->link.link_info.phy_type_low =
+ BIT_ULL(highest_bit - 1);
+ }
+ }
+
+ /* Based on link status or search above try to discover media type. */
+ hw->phy.media_type = ixgbe_get_media_type_from_phy_type(hw);
+
+ return hw->phy.media_type;
+}
+
+/**
+ * ixgbe_setup_link_e610 - Set up link
+ * @hw: pointer to hardware structure
+ * @speed: new link speed
+ * @autoneg_wait: true when waiting for completion is needed
+ *
+ * Set up the link with the specified speed.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_setup_link_e610(struct ixgbe_hw *hw, ixgbe_link_speed speed,
+ bool autoneg_wait)
+{
+ /* Simply request FW to perform proper PHY setup */
+ return hw->phy.ops.setup_link_speed(hw, speed, autoneg_wait);
+}
+
+/**
+ * ixgbe_check_link_e610 - Determine link and speed status
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @link_up: true when link is up
+ * @link_up_wait_to_complete: bool used to wait for link up or not
+ *
+ * Determine if the link is up and the current link speed
+ * using ACI command (0x0607).
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_check_link_e610(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
+ bool *link_up, bool link_up_wait_to_complete)
+{
+ int err;
+ u32 i;
+
+ if (!speed || !link_up)
+ return -EINVAL;
+
+ /* Set get_link_info flag to ensure that fresh
+ * link information will be obtained from FW
+ * by sending Get Link Status admin command.
+ */
+ hw->link.get_link_info = true;
+
+ /* Update link information in adapter context. */
+ err = ixgbe_get_link_status(hw, link_up);
+ if (err)
+ return err;
+
+ /* Wait for link up if it was requested. */
+ if (link_up_wait_to_complete && !(*link_up)) {
+ for (i = 0; i < hw->mac.max_link_up_time; i++) {
+ msleep(100);
+ hw->link.get_link_info = true;
+ err = ixgbe_get_link_status(hw, link_up);
+ if (err)
+ return err;
+ if (*link_up)
+ break;
+ }
+ }
+
+ /* Use link information in adapter context updated by the call
+ * to ixgbe_get_link_status() to determine current link speed.
+ * Link speed information is valid only when link up was
+ * reported by FW.
+ */
+ if (*link_up) {
+ switch (hw->link.link_info.link_speed) {
+ case IXGBE_ACI_LINK_SPEED_10MB:
+ *speed = IXGBE_LINK_SPEED_10_FULL;
+ break;
+ case IXGBE_ACI_LINK_SPEED_100MB:
+ *speed = IXGBE_LINK_SPEED_100_FULL;
+ break;
+ case IXGBE_ACI_LINK_SPEED_1000MB:
+ *speed = IXGBE_LINK_SPEED_1GB_FULL;
+ break;
+ case IXGBE_ACI_LINK_SPEED_2500MB:
+ *speed = IXGBE_LINK_SPEED_2_5GB_FULL;
+ break;
+ case IXGBE_ACI_LINK_SPEED_5GB:
+ *speed = IXGBE_LINK_SPEED_5GB_FULL;
+ break;
+ case IXGBE_ACI_LINK_SPEED_10GB:
+ *speed = IXGBE_LINK_SPEED_10GB_FULL;
+ break;
+ default:
+ *speed = IXGBE_LINK_SPEED_UNKNOWN;
+ break;
+ }
+ } else {
+ *speed = IXGBE_LINK_SPEED_UNKNOWN;
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_get_link_capabilities_e610 - Determine link capabilities
+ * @hw: pointer to hardware structure
+ * @speed: pointer to link speed
+ * @autoneg: true when autoneg or autotry is enabled
+ *
+ * Determine speed and AN parameters of a link.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_get_link_capabilities_e610(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *autoneg)
+{
+ if (!speed || !autoneg)
+ return -EINVAL;
+
+ *autoneg = true;
+ *speed = hw->phy.speeds_supported;
+
+ return 0;
+}
+
+/**
+ * ixgbe_cfg_phy_fc - Configure PHY Flow Control (FC) data based on FC mode
+ * @hw: pointer to hardware structure
+ * @cfg: PHY configuration data to set FC mode
+ * @req_mode: FC mode to configure
+ *
+ * Configures PHY Flow Control according to the provided configuration.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_cfg_phy_fc(struct ixgbe_hw *hw,
+ struct ixgbe_aci_cmd_set_phy_cfg_data *cfg,
+ enum ixgbe_fc_mode req_mode)
+{
+ u8 pause_mask = 0x0;
+
+ if (!cfg)
+ return -EINVAL;
+
+ switch (req_mode) {
+ case ixgbe_fc_full:
+ pause_mask |= IXGBE_ACI_PHY_EN_TX_LINK_PAUSE;
+ pause_mask |= IXGBE_ACI_PHY_EN_RX_LINK_PAUSE;
+ break;
+ case ixgbe_fc_rx_pause:
+ pause_mask |= IXGBE_ACI_PHY_EN_RX_LINK_PAUSE;
+ break;
+ case ixgbe_fc_tx_pause:
+ pause_mask |= IXGBE_ACI_PHY_EN_TX_LINK_PAUSE;
+ break;
+ default:
+ break;
+ }
+
+ /* Clear the old pause settings. */
+ cfg->caps &= ~(IXGBE_ACI_PHY_EN_TX_LINK_PAUSE |
+ IXGBE_ACI_PHY_EN_RX_LINK_PAUSE);
+
+ /* Set the new capabilities. */
+ cfg->caps |= pause_mask;
+
+ return 0;
+}
+
+/**
+ * ixgbe_setup_fc_e610 - Set up flow control
+ * @hw: pointer to hardware structure
+ *
+ * Set up flow control. This has to be done during init time.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_setup_fc_e610(struct ixgbe_hw *hw)
+{
+ struct ixgbe_aci_cmd_get_phy_caps_data pcaps = {};
+ struct ixgbe_aci_cmd_set_phy_cfg_data cfg = {};
+ int err;
+
+ /* Get the current PHY config */
+ err = ixgbe_aci_get_phy_caps(hw, false,
+ IXGBE_ACI_REPORT_ACTIVE_CFG, &pcaps);
+ if (err)
+ return err;
+
+ ixgbe_copy_phy_caps_to_cfg(&pcaps, &cfg);
+
+ /* Configure the set PHY data */
+ err = ixgbe_cfg_phy_fc(hw, &cfg, hw->fc.requested_mode);
+ if (err)
+ return err;
+
+ /* If the capabilities have changed, then set the new config */
+ if (cfg.caps != pcaps.caps) {
+ cfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
+
+ err = ixgbe_aci_set_phy_cfg(hw, &cfg);
+ if (err)
+ return err;
+ }
+
+ return err;
+}
+
+/**
+ * ixgbe_fc_autoneg_e610 - Configure flow control
+ * @hw: pointer to hardware structure
+ *
+ * Configure Flow Control.
+ */
+void ixgbe_fc_autoneg_e610(struct ixgbe_hw *hw)
+{
+ int err;
+
+ /* Get current link err.
+ * Current FC mode will be stored in the hw context.
+ */
+ err = ixgbe_aci_get_link_info(hw, false, NULL);
+ if (err)
+ goto no_autoneg;
+
+ /* Check if the link is up */
+ if (!(hw->link.link_info.link_info & IXGBE_ACI_LINK_UP))
+ goto no_autoneg;
+
+ /* Check if auto-negotiation has completed */
+ if (!(hw->link.link_info.an_info & IXGBE_ACI_AN_COMPLETED))
+ goto no_autoneg;
+
+ hw->fc.fc_was_autonegged = true;
+ return;
+
+no_autoneg:
+ hw->fc.fc_was_autonegged = false;
+ hw->fc.current_mode = hw->fc.requested_mode;
+}
+
+/**
+ * ixgbe_disable_rx_e610 - Disable RX unit
+ * @hw: pointer to hardware structure
+ *
+ * Disable RX DMA unit on E610 with use of ACI command (0x000C).
+ *
+ * Return: the exit code of the operation.
+ */
+void ixgbe_disable_rx_e610(struct ixgbe_hw *hw)
+{
+ u32 rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+ u32 pfdtxgswc;
+ int err;
+
+ if (!(rxctrl & IXGBE_RXCTRL_RXEN))
+ return;
+
+ pfdtxgswc = IXGBE_READ_REG(hw, IXGBE_PFDTXGSWC);
+ if (pfdtxgswc & IXGBE_PFDTXGSWC_VT_LBEN) {
+ pfdtxgswc &= ~IXGBE_PFDTXGSWC_VT_LBEN;
+ IXGBE_WRITE_REG(hw, IXGBE_PFDTXGSWC, pfdtxgswc);
+ hw->mac.set_lben = true;
+ } else {
+ hw->mac.set_lben = false;
+ }
+
+ err = ixgbe_aci_disable_rxen(hw);
+
+ /* If we fail - disable RX using register write */
+ if (err) {
+ rxctrl = IXGBE_READ_REG(hw, IXGBE_RXCTRL);
+ if (rxctrl & IXGBE_RXCTRL_RXEN) {
+ rxctrl &= ~IXGBE_RXCTRL_RXEN;
+ IXGBE_WRITE_REG(hw, IXGBE_RXCTRL, rxctrl);
+ }
+ }
+}
+
+/**
+ * ixgbe_init_phy_ops_e610 - PHY specific init
+ * @hw: pointer to hardware structure
+ *
+ * Initialize any function pointers that were not able to be
+ * set during init_shared_code because the PHY type was not known.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_init_phy_ops_e610(struct ixgbe_hw *hw)
+{
+ struct ixgbe_mac_info *mac = &hw->mac;
+ struct ixgbe_phy_info *phy = &hw->phy;
+
+ if (mac->ops.get_media_type(hw) == ixgbe_media_type_copper)
+ phy->ops.set_phy_power = ixgbe_set_phy_power_e610;
+ else
+ phy->ops.set_phy_power = NULL;
+
+ /* Identify the PHY */
+ return phy->ops.identify(hw);
+}
+
+/**
+ * ixgbe_identify_phy_e610 - Identify PHY
+ * @hw: pointer to hardware structure
+ *
+ * Determine PHY type, supported speeds and PHY ID.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_identify_phy_e610(struct ixgbe_hw *hw)
+{
+ struct ixgbe_aci_cmd_get_phy_caps_data pcaps;
+ u64 phy_type_low, phy_type_high;
+ int err;
+
+ /* Set PHY type */
+ hw->phy.type = ixgbe_phy_fw;
+
+ err = ixgbe_aci_get_phy_caps(hw, false,
+ IXGBE_ACI_REPORT_TOPO_CAP_MEDIA, &pcaps);
+ if (err)
+ return err;
+
+ if (!(pcaps.module_compliance_enforcement &
+ IXGBE_ACI_MOD_ENFORCE_STRICT_MODE)) {
+ /* Handle lenient mode */
+ err = ixgbe_aci_get_phy_caps(hw, false,
+ IXGBE_ACI_REPORT_TOPO_CAP_NO_MEDIA,
+ &pcaps);
+ if (err)
+ return err;
+ }
+
+ /* Determine supported speeds */
+ hw->phy.speeds_supported = IXGBE_LINK_SPEED_UNKNOWN;
+ phy_type_high = le64_to_cpu(pcaps.phy_type_high);
+ phy_type_low = le64_to_cpu(pcaps.phy_type_low);
+
+ if (phy_type_high & IXGBE_PHY_TYPE_HIGH_10BASE_T ||
+ phy_type_high & IXGBE_PHY_TYPE_HIGH_10M_SGMII)
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10_FULL;
+ if (phy_type_low & IXGBE_PHY_TYPE_LOW_100BASE_TX ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_100M_SGMII ||
+ phy_type_high & IXGBE_PHY_TYPE_HIGH_100M_USXGMII)
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_100_FULL;
+ if (phy_type_low & IXGBE_PHY_TYPE_LOW_1000BASE_T ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_1000BASE_SX ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_1000BASE_LX ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_1000BASE_KX ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_1G_SGMII ||
+ phy_type_high & IXGBE_PHY_TYPE_HIGH_1G_USXGMII)
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_1GB_FULL;
+ if (phy_type_low & IXGBE_PHY_TYPE_LOW_10GBASE_T ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_10G_SFI_DA ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_10GBASE_SR ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_10GBASE_LR ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_10GBASE_KR_CR1 ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_10G_SFI_AOC_ACC ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_10G_SFI_C2C ||
+ phy_type_high & IXGBE_PHY_TYPE_HIGH_10G_USXGMII)
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_10GB_FULL;
+
+ /* 2.5 and 5 Gbps link speeds must be excluded from the
+ * auto-negotiation set used during driver initialization due to
+ * compatibility issues with certain switches. Those issues do not
+ * exist in case of E610 2.5G SKU device (0x57b1).
+ */
+ if (!hw->phy.autoneg_advertised &&
+ hw->device_id != IXGBE_DEV_ID_E610_2_5G_T)
+ hw->phy.autoneg_advertised = hw->phy.speeds_supported;
+
+ if (phy_type_low & IXGBE_PHY_TYPE_LOW_2500BASE_T ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_2500BASE_X ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_2500BASE_KX ||
+ phy_type_high & IXGBE_PHY_TYPE_HIGH_2500M_SGMII ||
+ phy_type_high & IXGBE_PHY_TYPE_HIGH_2500M_USXGMII)
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL;
+
+ if (!hw->phy.autoneg_advertised &&
+ hw->device_id == IXGBE_DEV_ID_E610_2_5G_T)
+ hw->phy.autoneg_advertised = hw->phy.speeds_supported;
+
+ if (phy_type_low & IXGBE_PHY_TYPE_LOW_5GBASE_T ||
+ phy_type_low & IXGBE_PHY_TYPE_LOW_5GBASE_KR ||
+ phy_type_high & IXGBE_PHY_TYPE_HIGH_5G_USXGMII)
+ hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
+
+ /* Set PHY ID */
+ memcpy(&hw->phy.id, pcaps.phy_id_oui, sizeof(u32));
+
+ hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_10_FULL |
+ IXGBE_LINK_SPEED_100_FULL |
+ IXGBE_LINK_SPEED_1GB_FULL;
+ hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported;
+
+ return 0;
+}
+
+/**
+ * ixgbe_identify_module_e610 - Identify SFP module type
+ * @hw: pointer to hardware structure
+ *
+ * Identify the SFP module type.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_identify_module_e610(struct ixgbe_hw *hw)
+{
+ bool media_available;
+ u8 module_type;
+ int err;
+
+ err = ixgbe_update_link_info(hw);
+ if (err)
+ return err;
+
+ media_available =
+ (hw->link.link_info.link_info & IXGBE_ACI_MEDIA_AVAILABLE);
+
+ if (media_available) {
+ hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+
+ /* Get module type from hw context updated by
+ * ixgbe_update_link_info()
+ */
+ module_type = hw->link.link_info.module_type[IXGBE_ACI_MOD_TYPE_IDENT];
+
+ if ((module_type & IXGBE_ACI_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE) ||
+ (module_type & IXGBE_ACI_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE)) {
+ hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
+ } else if (module_type & IXGBE_ACI_MOD_TYPE_BYTE1_10G_BASE_SR) {
+ hw->phy.sfp_type = ixgbe_sfp_type_sr;
+ } else if ((module_type & IXGBE_ACI_MOD_TYPE_BYTE1_10G_BASE_LR) ||
+ (module_type & IXGBE_ACI_MOD_TYPE_BYTE1_10G_BASE_LRM)) {
+ hw->phy.sfp_type = ixgbe_sfp_type_lr;
+ }
+ } else {
+ hw->phy.sfp_type = ixgbe_sfp_type_not_present;
+ return -ENOENT;
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_setup_phy_link_e610 - Sets up firmware-controlled PHYs
+ * @hw: pointer to hardware structure
+ *
+ * Set the parameters for the firmware-controlled PHYs.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_setup_phy_link_e610(struct ixgbe_hw *hw)
+{
+ struct ixgbe_aci_cmd_get_phy_caps_data pcaps;
+ struct ixgbe_aci_cmd_set_phy_cfg_data pcfg;
+ u8 rmode = IXGBE_ACI_REPORT_TOPO_CAP_MEDIA;
+ u64 sup_phy_type_low, sup_phy_type_high;
+ u64 phy_type_low = 0, phy_type_high = 0;
+ int err;
+
+ err = ixgbe_aci_get_link_info(hw, false, NULL);
+ if (err)
+ return err;
+
+ /* If media is not available get default config. */
+ if (!(hw->link.link_info.link_info & IXGBE_ACI_MEDIA_AVAILABLE))
+ rmode = IXGBE_ACI_REPORT_DFLT_CFG;
+
+ err = ixgbe_aci_get_phy_caps(hw, false, rmode, &pcaps);
+ if (err)
+ return err;
+
+ sup_phy_type_low = le64_to_cpu(pcaps.phy_type_low);
+ sup_phy_type_high = le64_to_cpu(pcaps.phy_type_high);
+
+ /* Get Active configuration to avoid unintended changes. */
+ err = ixgbe_aci_get_phy_caps(hw, false, IXGBE_ACI_REPORT_ACTIVE_CFG,
+ &pcaps);
+ if (err)
+ return err;
+
+ ixgbe_copy_phy_caps_to_cfg(&pcaps, &pcfg);
+
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10_FULL) {
+ phy_type_high |= IXGBE_PHY_TYPE_HIGH_10BASE_T;
+ phy_type_high |= IXGBE_PHY_TYPE_HIGH_10M_SGMII;
+ }
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) {
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_100BASE_TX;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_100M_SGMII;
+ phy_type_high |= IXGBE_PHY_TYPE_HIGH_100M_USXGMII;
+ }
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) {
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_1000BASE_T;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_1000BASE_SX;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_1000BASE_LX;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_1000BASE_KX;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_1G_SGMII;
+ phy_type_high |= IXGBE_PHY_TYPE_HIGH_1G_USXGMII;
+ }
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) {
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_2500BASE_T;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_2500BASE_X;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_2500BASE_KX;
+ phy_type_high |= IXGBE_PHY_TYPE_HIGH_2500M_SGMII;
+ phy_type_high |= IXGBE_PHY_TYPE_HIGH_2500M_USXGMII;
+ }
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) {
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_5GBASE_T;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_5GBASE_KR;
+ phy_type_high |= IXGBE_PHY_TYPE_HIGH_5G_USXGMII;
+ }
+ if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) {
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_10GBASE_T;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_10G_SFI_DA;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_10GBASE_SR;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_10GBASE_LR;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_10GBASE_KR_CR1;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_10G_SFI_AOC_ACC;
+ phy_type_low |= IXGBE_PHY_TYPE_LOW_10G_SFI_C2C;
+ phy_type_high |= IXGBE_PHY_TYPE_HIGH_10G_USXGMII;
+ }
+
+ /* Mask the set values to avoid requesting unsupported link types. */
+ phy_type_low &= sup_phy_type_low;
+ pcfg.phy_type_low = cpu_to_le64(phy_type_low);
+ phy_type_high &= sup_phy_type_high;
+ pcfg.phy_type_high = cpu_to_le64(phy_type_high);
+
+ if (pcfg.phy_type_high != pcaps.phy_type_high ||
+ pcfg.phy_type_low != pcaps.phy_type_low ||
+ pcfg.caps != pcaps.caps) {
+ pcfg.caps |= IXGBE_ACI_PHY_ENA_LINK;
+ pcfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
+
+ err = ixgbe_aci_set_phy_cfg(hw, &pcfg);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+/**
+ * ixgbe_set_phy_power_e610 - Control power for copper PHY
+ * @hw: pointer to hardware structure
+ * @on: true for on, false for off
+ *
+ * Set the power on/off of the PHY
+ * by getting its capabilities and setting the appropriate
+ * configuration parameters.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_set_phy_power_e610(struct ixgbe_hw *hw, bool on)
+{
+ struct ixgbe_aci_cmd_get_phy_caps_data phy_caps = {};
+ struct ixgbe_aci_cmd_set_phy_cfg_data phy_cfg = {};
+ int err;
+
+ err = ixgbe_aci_get_phy_caps(hw, false,
+ IXGBE_ACI_REPORT_ACTIVE_CFG,
+ &phy_caps);
+ if (err)
+ return err;
+
+ ixgbe_copy_phy_caps_to_cfg(&phy_caps, &phy_cfg);
+
+ if (on)
+ phy_cfg.caps &= ~IXGBE_ACI_PHY_ENA_LOW_POWER;
+ else
+ phy_cfg.caps |= IXGBE_ACI_PHY_ENA_LOW_POWER;
+
+ /* PHY is already in requested power mode. */
+ if (phy_caps.caps == phy_cfg.caps)
+ return 0;
+
+ phy_cfg.caps |= IXGBE_ACI_PHY_ENA_LINK;
+ phy_cfg.caps |= IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT;
+
+ return ixgbe_aci_set_phy_cfg(hw, &phy_cfg);
+}
+
+/**
+ * ixgbe_enter_lplu_e610 - Transition to low power states
+ * @hw: pointer to hardware structure
+ *
+ * Configures Low Power Link Up on transition to low power states
+ * (from D0 to non-D0). Link is required to enter LPLU so avoid resetting the
+ * X557 PHY immediately prior to entering LPLU.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_enter_lplu_e610(struct ixgbe_hw *hw)
+{
+ struct ixgbe_aci_cmd_get_phy_caps_data phy_caps = {};
+ struct ixgbe_aci_cmd_set_phy_cfg_data phy_cfg = {};
+ int err;
+
+ err = ixgbe_aci_get_phy_caps(hw, false,
+ IXGBE_ACI_REPORT_ACTIVE_CFG,
+ &phy_caps);
+ if (err)
+ return err;
+
+ ixgbe_copy_phy_caps_to_cfg(&phy_caps, &phy_cfg);
+
+ phy_cfg.low_power_ctrl_an |= IXGBE_ACI_PHY_EN_D3COLD_LOW_POWER_AUTONEG;
+
+ return ixgbe_aci_set_phy_cfg(hw, &phy_cfg);
+}
+
+/**
+ * ixgbe_init_eeprom_params_e610 - Initialize EEPROM params
+ * @hw: pointer to hardware structure
+ *
+ * Initialize the EEPROM parameters ixgbe_eeprom_info within the ixgbe_hw
+ * struct in order to set up EEPROM access.
+ *
+ * Return: the operation exit code.
+ */
+int ixgbe_init_eeprom_params_e610(struct ixgbe_hw *hw)
+{
+ struct ixgbe_eeprom_info *eeprom = &hw->eeprom;
+ u32 gens_stat;
+ u8 sr_size;
+
+ if (eeprom->type != ixgbe_eeprom_uninitialized)
+ return 0;
+
+ eeprom->type = ixgbe_flash;
+
+ gens_stat = IXGBE_READ_REG(hw, GLNVM_GENS);
+ sr_size = FIELD_GET(GLNVM_GENS_SR_SIZE_M, gens_stat);
+
+ /* Switching to words (sr_size contains power of 2). */
+ eeprom->word_size = BIT(sr_size) * IXGBE_SR_WORDS_IN_1KB;
+
+ hw_dbg(hw, "Eeprom params: type = %d, size = %d\n", eeprom->type,
+ eeprom->word_size);
+
+ return 0;
+}
+
+/**
+ * ixgbe_aci_get_netlist_node - get a node handle
+ * @hw: pointer to the hw struct
+ * @cmd: get_link_topo AQ structure
+ * @node_part_number: output node part number if node found
+ * @node_handle: output node handle parameter if node found
+ *
+ * Get the netlist node and assigns it to
+ * the provided handle using ACI command (0x06E0).
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_aci_get_netlist_node(struct ixgbe_hw *hw,
+ struct ixgbe_aci_cmd_get_link_topo *cmd,
+ u8 *node_part_number, u16 *node_handle)
+{
+ struct ixgbe_aci_desc desc;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_get_link_topo);
+ desc.params.get_link_topo = *cmd;
+
+ if (ixgbe_aci_send_cmd(hw, &desc, NULL, 0))
+ return -EOPNOTSUPP;
+
+ if (node_handle)
+ *node_handle =
+ le16_to_cpu(desc.params.get_link_topo.addr.handle);
+ if (node_part_number)
+ *node_part_number = desc.params.get_link_topo.node_part_num;
+
+ return 0;
+}
+
+/**
+ * ixgbe_acquire_nvm - Generic request for acquiring the NVM ownership
+ * @hw: pointer to the HW structure
+ * @access: NVM access type (read or write)
+ *
+ * Request NVM ownership.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_acquire_nvm(struct ixgbe_hw *hw,
+ enum ixgbe_aci_res_access_type access)
+{
+ u32 fla;
+
+ /* Skip if we are in blank NVM programming mode */
+ fla = IXGBE_READ_REG(hw, IXGBE_GLNVM_FLA);
+ if ((fla & IXGBE_GLNVM_FLA_LOCKED_M) == 0)
+ return 0;
+
+ return ixgbe_acquire_res(hw, IXGBE_NVM_RES_ID, access,
+ IXGBE_NVM_TIMEOUT);
+}
+
+/**
+ * ixgbe_release_nvm - Generic request for releasing the NVM ownership
+ * @hw: pointer to the HW structure
+ *
+ * Release NVM ownership.
+ */
+void ixgbe_release_nvm(struct ixgbe_hw *hw)
+{
+ u32 fla;
+
+ /* Skip if we are in blank NVM programming mode */
+ fla = IXGBE_READ_REG(hw, IXGBE_GLNVM_FLA);
+ if ((fla & IXGBE_GLNVM_FLA_LOCKED_M) == 0)
+ return;
+
+ ixgbe_release_res(hw, IXGBE_NVM_RES_ID);
+}
+
+/**
+ * ixgbe_aci_read_nvm - read NVM
+ * @hw: pointer to the HW struct
+ * @module_typeid: module pointer location in words from the NVM beginning
+ * @offset: byte offset from the module beginning
+ * @length: length of the section to be read (in bytes from the offset)
+ * @data: command buffer (size [bytes] = length)
+ * @last_command: tells if this is the last command in a series
+ * @read_shadow_ram: tell if this is a shadow RAM read
+ *
+ * Read the NVM using ACI command (0x0701).
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_aci_read_nvm(struct ixgbe_hw *hw, u16 module_typeid, u32 offset,
+ u16 length, void *data, bool last_command,
+ bool read_shadow_ram)
+{
+ struct ixgbe_aci_cmd_nvm *cmd;
+ struct ixgbe_aci_desc desc;
+
+ if (offset > IXGBE_ACI_NVM_MAX_OFFSET)
+ return -EINVAL;
+
+ cmd = &desc.params.nvm;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_read);
+
+ if (!read_shadow_ram && module_typeid == IXGBE_ACI_NVM_START_POINT)
+ cmd->cmd_flags |= IXGBE_ACI_NVM_FLASH_ONLY;
+
+ /* If this is the last command in a series, set the proper flag. */
+ if (last_command)
+ cmd->cmd_flags |= IXGBE_ACI_NVM_LAST_CMD;
+ cmd->module_typeid = cpu_to_le16(module_typeid);
+ cmd->offset_low = cpu_to_le16(offset & 0xFFFF);
+ cmd->offset_high = (offset >> 16) & 0xFF;
+ cmd->length = cpu_to_le16(length);
+
+ return ixgbe_aci_send_cmd(hw, &desc, data, length);
+}
+
+/**
+ * ixgbe_nvm_validate_checksum - validate checksum
+ * @hw: pointer to the HW struct
+ *
+ * Verify NVM PFA checksum validity using ACI command (0x0706).
+ * If the checksum verification failed, IXGBE_ERR_NVM_CHECKSUM is returned.
+ * The function acquires and then releases the NVM ownership.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_nvm_validate_checksum(struct ixgbe_hw *hw)
+{
+ struct ixgbe_aci_cmd_nvm_checksum *cmd;
+ struct ixgbe_aci_desc desc;
+ int err;
+
+ err = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
+ if (err)
+ return err;
+
+ cmd = &desc.params.nvm_checksum;
+
+ ixgbe_fill_dflt_direct_cmd_desc(&desc, ixgbe_aci_opc_nvm_checksum);
+ cmd->flags = IXGBE_ACI_NVM_CHECKSUM_VERIFY;
+
+ err = ixgbe_aci_send_cmd(hw, &desc, NULL, 0);
+
+ ixgbe_release_nvm(hw);
+
+ if (!err && cmd->checksum !=
+ cpu_to_le16(IXGBE_ACI_NVM_CHECKSUM_CORRECT)) {
+ struct ixgbe_adapter *adapter = container_of(hw, struct ixgbe_adapter,
+ hw);
+
+ err = -EIO;
+ netdev_err(adapter->netdev, "Invalid Shadow Ram checksum");
+ }
+
+ return err;
+}
+
+/**
+ * ixgbe_read_sr_word_aci - Reads Shadow RAM via ACI
+ * @hw: pointer to the HW structure
+ * @offset: offset of the Shadow RAM word to read (0x000000 - 0x001FFF)
+ * @data: word read from the Shadow RAM
+ *
+ * Reads one 16 bit word from the Shadow RAM using ixgbe_read_flat_nvm.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_read_sr_word_aci(struct ixgbe_hw *hw, u16 offset, u16 *data)
+{
+ u32 bytes = sizeof(u16);
+ u16 data_local;
+ int err;
+
+ err = ixgbe_read_flat_nvm(hw, offset * sizeof(u16), &bytes,
+ (u8 *)&data_local, true);
+ if (err)
+ return err;
+
+ *data = data_local;
+ return 0;
+}
+
+/**
+ * ixgbe_read_flat_nvm - Read portion of NVM by flat offset
+ * @hw: pointer to the HW struct
+ * @offset: offset from beginning of NVM
+ * @length: (in) number of bytes to read; (out) number of bytes actually read
+ * @data: buffer to return data in (sized to fit the specified length)
+ * @read_shadow_ram: if true, read from shadow RAM instead of NVM
+ *
+ * Reads a portion of the NVM, as a flat memory space. This function correctly
+ * breaks read requests across Shadow RAM sectors, prevents Shadow RAM size
+ * from being exceeded in case of Shadow RAM read requests and ensures that no
+ * single read request exceeds the maximum 4KB read for a single admin command.
+ *
+ * Returns an error code on failure. Note that the data pointer may be
+ * partially updated if some reads succeed before a failure.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_read_flat_nvm(struct ixgbe_hw *hw, u32 offset, u32 *length,
+ u8 *data, bool read_shadow_ram)
+{
+ u32 inlen = *length;
+ u32 bytes_read = 0;
+ bool last_cmd;
+ int err;
+
+ /* Verify the length of the read if this is for the Shadow RAM */
+ if (read_shadow_ram && ((offset + inlen) >
+ (hw->eeprom.word_size * 2u)))
+ return -EINVAL;
+
+ do {
+ u32 read_size, sector_offset;
+
+ /* ixgbe_aci_read_nvm cannot read more than 4KB at a time.
+ * Additionally, a read from the Shadow RAM may not cross over
+ * a sector boundary. Conveniently, the sector size is also 4KB.
+ */
+ sector_offset = offset % IXGBE_ACI_MAX_BUFFER_SIZE;
+ read_size = min_t(u32,
+ IXGBE_ACI_MAX_BUFFER_SIZE - sector_offset,
+ inlen - bytes_read);
+
+ last_cmd = !(bytes_read + read_size < inlen);
+
+ /* ixgbe_aci_read_nvm takes the length as a u16. Our read_size
+ * is calculated using a u32, but the IXGBE_ACI_MAX_BUFFER_SIZE
+ * maximum size guarantees that it will fit within the 2 bytes.
+ */
+ err = ixgbe_aci_read_nvm(hw, IXGBE_ACI_NVM_START_POINT,
+ offset, (u16)read_size,
+ data + bytes_read, last_cmd,
+ read_shadow_ram);
+ if (err)
+ break;
+
+ bytes_read += read_size;
+ offset += read_size;
+ } while (!last_cmd);
+
+ *length = bytes_read;
+ return err;
+}
+
+/**
+ * ixgbe_read_sr_buf_aci - Read Shadow RAM buffer via ACI
+ * @hw: pointer to the HW structure
+ * @offset: offset of the Shadow RAM words to read (0x000000 - 0x001FFF)
+ * @words: (in) number of words to read; (out) number of words actually read
+ * @data: words read from the Shadow RAM
+ *
+ * Read 16 bit words (data buf) from the Shadow RAM. Acquire/release the NVM
+ * ownership.
+ *
+ * Return: the operation exit code.
+ */
+int ixgbe_read_sr_buf_aci(struct ixgbe_hw *hw, u16 offset, u16 *words,
+ u16 *data)
+{
+ u32 bytes = *words * 2;
+ int err;
+
+ err = ixgbe_read_flat_nvm(hw, offset * 2, &bytes, (u8 *)data, true);
+ if (err)
+ return err;
+
+ *words = bytes / 2;
+
+ for (int i = 0; i < *words; i++)
+ data[i] = le16_to_cpu(((__le16 *)data)[i]);
+
+ return 0;
+}
+
+/**
+ * ixgbe_read_ee_aci_e610 - Read EEPROM word using the admin command.
+ * @hw: pointer to hardware structure
+ * @offset: offset of word in the EEPROM to read
+ * @data: word read from the EEPROM
+ *
+ * Reads a 16 bit word from the EEPROM using the ACI.
+ * If the EEPROM params are not initialized, the function
+ * initialize them before proceeding with reading.
+ * The function acquires and then releases the NVM ownership.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_read_ee_aci_e610(struct ixgbe_hw *hw, u16 offset, u16 *data)
+{
+ int err;
+
+ if (hw->eeprom.type == ixgbe_eeprom_uninitialized) {
+ err = hw->eeprom.ops.init_params(hw);
+ if (err)
+ return err;
+ }
+
+ err = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
+ if (err)
+ return err;
+
+ err = ixgbe_read_sr_word_aci(hw, offset, data);
+ ixgbe_release_nvm(hw);
+
+ return err;
+}
+
+/**
+ * ixgbe_read_ee_aci_buffer_e610 - Read EEPROM words via ACI
+ * @hw: pointer to hardware structure
+ * @offset: offset of words in the EEPROM to read
+ * @words: number of words to read
+ * @data: words to read from the EEPROM
+ *
+ * Read 16 bit words from the EEPROM via the ACI. Initialize the EEPROM params
+ * prior to the read. Acquire/release the NVM ownership.
+ *
+ * Return: the operation exit code.
+ */
+int ixgbe_read_ee_aci_buffer_e610(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data)
+{
+ int err;
+
+ if (hw->eeprom.type == ixgbe_eeprom_uninitialized) {
+ err = hw->eeprom.ops.init_params(hw);
+ if (err)
+ return err;
+ }
+
+ err = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
+ if (err)
+ return err;
+
+ err = ixgbe_read_sr_buf_aci(hw, offset, &words, data);
+ ixgbe_release_nvm(hw);
+
+ return err;
+}
+
+/**
+ * ixgbe_validate_eeprom_checksum_e610 - Validate EEPROM checksum
+ * @hw: pointer to hardware structure
+ * @checksum_val: calculated checksum
+ *
+ * Performs checksum calculation and validates the EEPROM checksum. If the
+ * caller does not need checksum_val, the value can be NULL.
+ * If the EEPROM params are not initialized, the function
+ * initialize them before proceeding.
+ * The function acquires and then releases the NVM ownership.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_validate_eeprom_checksum_e610(struct ixgbe_hw *hw, u16 *checksum_val)
+{
+ int err;
+
+ if (hw->eeprom.type == ixgbe_eeprom_uninitialized) {
+ err = hw->eeprom.ops.init_params(hw);
+ if (err)
+ return err;
+ }
+
+ err = ixgbe_nvm_validate_checksum(hw);
+ if (err)
+ return err;
+
+ if (checksum_val) {
+ u16 tmp_checksum;
+
+ err = ixgbe_acquire_nvm(hw, IXGBE_RES_READ);
+ if (err)
+ return err;
+
+ err = ixgbe_read_sr_word_aci(hw, E610_SR_SW_CHECKSUM_WORD,
+ &tmp_checksum);
+ ixgbe_release_nvm(hw);
+
+ if (!err)
+ *checksum_val = tmp_checksum;
+ }
+
+ return err;
+}
+
+/**
+ * ixgbe_reset_hw_e610 - Perform hardware reset
+ * @hw: pointer to hardware structure
+ *
+ * Resets the hardware by resetting the transmit and receive units, masks
+ * and clears all interrupts, and performs a reset.
+ *
+ * Return: the exit code of the operation.
+ */
+int ixgbe_reset_hw_e610(struct ixgbe_hw *hw)
+{
+ u32 swfw_mask = hw->phy.phy_semaphore_mask;
+ u32 ctrl, i;
+ int err;
+
+ /* Call adapter stop to disable tx/rx and clear interrupts */
+ err = hw->mac.ops.stop_adapter(hw);
+ if (err)
+ goto reset_hw_out;
+
+ /* Flush pending Tx transactions. */
+ ixgbe_clear_tx_pending(hw);
+
+ hw->phy.ops.init(hw);
+mac_reset_top:
+ err = hw->mac.ops.acquire_swfw_sync(hw, swfw_mask);
+ if (err)
+ return -EBUSY;
+ ctrl = IXGBE_CTRL_RST;
+ ctrl |= IXGBE_READ_REG(hw, IXGBE_CTRL);
+ IXGBE_WRITE_REG(hw, IXGBE_CTRL, ctrl);
+ IXGBE_WRITE_FLUSH(hw);
+ hw->mac.ops.release_swfw_sync(hw, swfw_mask);
+
+ /* Poll for reset bit to self-clear indicating reset is complete */
+ for (i = 0; i < 10; i++) {
+ udelay(1);
+ ctrl = IXGBE_READ_REG(hw, IXGBE_CTRL);
+ if (!(ctrl & IXGBE_CTRL_RST_MASK))
+ break;
+ }
+
+ if (ctrl & IXGBE_CTRL_RST_MASK) {
+ struct ixgbe_adapter *adapter = container_of(hw, struct ixgbe_adapter,
+ hw);
+
+ err = -EIO;
+ netdev_err(adapter->netdev, "Reset polling failed to complete.");
+ }
+
+ /* Double resets are required for recovery from certain error
+ * conditions. Between resets, it is necessary to stall to allow time
+ * for any pending HW events to complete.
+ */
+ msleep(100);
+ if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+ hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+ goto mac_reset_top;
+ }
+
+ /* Set the Rx packet buffer size. */
+ IXGBE_WRITE_REG(hw, IXGBE_RXPBSIZE(0), GENMASK(18, 17));
+
+ /* Store the permanent mac address */
+ hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+
+ /* Maximum number of Receive Address Registers. */
+#define IXGBE_MAX_NUM_RAR 128
+
+ /* Store MAC address from RAR0, clear receive address registers, and
+ * clear the multicast table. Also reset num_rar_entries to the
+ * maximum number of Receive Address Registers, since we modify this
+ * value when programming the SAN MAC address.
+ */
+ hw->mac.num_rar_entries = IXGBE_MAX_NUM_RAR;
+ hw->mac.ops.init_rx_addrs(hw);
+
+ /* Initialize bus function number */
+ hw->mac.ops.set_lan_id(hw);
+
+reset_hw_out:
+ return err;
+}
+
+static const struct ixgbe_mac_operations mac_ops_e610 = {
+ .init_hw = ixgbe_init_hw_generic,
+ .start_hw = ixgbe_start_hw_X540,
+ .clear_hw_cntrs = ixgbe_clear_hw_cntrs_generic,
+ .enable_rx_dma = ixgbe_enable_rx_dma_generic,
+ .get_mac_addr = ixgbe_get_mac_addr_generic,
+ .get_device_caps = ixgbe_get_device_caps_generic,
+ .stop_adapter = ixgbe_stop_adapter_generic,
+ .set_lan_id = ixgbe_set_lan_id_multi_port_pcie,
+ .set_rxpba = ixgbe_set_rxpba_generic,
+ .check_link = ixgbe_check_link_e610,
+ .blink_led_start = ixgbe_blink_led_start_X540,
+ .blink_led_stop = ixgbe_blink_led_stop_X540,
+ .set_rar = ixgbe_set_rar_generic,
+ .clear_rar = ixgbe_clear_rar_generic,
+ .set_vmdq = ixgbe_set_vmdq_generic,
+ .set_vmdq_san_mac = ixgbe_set_vmdq_san_mac_generic,
+ .clear_vmdq = ixgbe_clear_vmdq_generic,
+ .init_rx_addrs = ixgbe_init_rx_addrs_generic,
+ .update_mc_addr_list = ixgbe_update_mc_addr_list_generic,
+ .enable_mc = ixgbe_enable_mc_generic,
+ .disable_mc = ixgbe_disable_mc_generic,
+ .clear_vfta = ixgbe_clear_vfta_generic,
+ .set_vfta = ixgbe_set_vfta_generic,
+ .fc_enable = ixgbe_fc_enable_generic,
+ .set_fw_drv_ver = ixgbe_set_fw_drv_ver_x550,
+ .init_uta_tables = ixgbe_init_uta_tables_generic,
+ .set_mac_anti_spoofing = ixgbe_set_mac_anti_spoofing,
+ .set_vlan_anti_spoofing = ixgbe_set_vlan_anti_spoofing,
+ .set_source_address_pruning =
+ ixgbe_set_source_address_pruning_x550,
+ .set_ethertype_anti_spoofing =
+ ixgbe_set_ethertype_anti_spoofing_x550,
+ .disable_rx_buff = ixgbe_disable_rx_buff_generic,
+ .enable_rx_buff = ixgbe_enable_rx_buff_generic,
+ .enable_rx = ixgbe_enable_rx_generic,
+ .disable_rx = ixgbe_disable_rx_e610,
+ .led_on = ixgbe_led_on_generic,
+ .led_off = ixgbe_led_off_generic,
+ .init_led_link_act = ixgbe_init_led_link_act_generic,
+ .reset_hw = ixgbe_reset_hw_e610,
+ .get_media_type = ixgbe_get_media_type_e610,
+ .setup_link = ixgbe_setup_link_e610,
+ .get_link_capabilities = ixgbe_get_link_capabilities_e610,
+ .get_bus_info = ixgbe_get_bus_info_generic,
+ .acquire_swfw_sync = ixgbe_acquire_swfw_sync_X540,
+ .release_swfw_sync = ixgbe_release_swfw_sync_X540,
+ .init_swfw_sync = ixgbe_init_swfw_sync_X540,
+ .prot_autoc_read = prot_autoc_read_generic,
+ .prot_autoc_write = prot_autoc_write_generic,
+ .setup_fc = ixgbe_setup_fc_e610,
+ .fc_autoneg = ixgbe_fc_autoneg_e610,
+};
+
+static const struct ixgbe_phy_operations phy_ops_e610 = {
+ .init = ixgbe_init_phy_ops_e610,
+ .identify = ixgbe_identify_phy_e610,
+ .identify_sfp = ixgbe_identify_module_e610,
+ .setup_link_speed = ixgbe_setup_phy_link_speed_generic,
+ .setup_link = ixgbe_setup_phy_link_e610,
+ .enter_lplu = ixgbe_enter_lplu_e610,
+};
+
+static const struct ixgbe_eeprom_operations eeprom_ops_e610 = {
+ .read = ixgbe_read_ee_aci_e610,
+ .read_buffer = ixgbe_read_ee_aci_buffer_e610,
+ .validate_checksum = ixgbe_validate_eeprom_checksum_e610,
+};
+
+const struct ixgbe_info ixgbe_e610_info = {
+ .mac = ixgbe_mac_e610,
+ .get_invariants = ixgbe_get_invariants_X540,
+ .mac_ops = &mac_ops_e610,
+ .eeprom_ops = &eeprom_ops_e610,
+ .phy_ops = &phy_ops_e610,
+ .mbx_ops = &mbx_ops_generic,
+ .mvals = ixgbe_mvals_x550em_a,
+};
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h
new file mode 100644
index 000000000000..ba8c06b73810
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h
@@ -0,0 +1,81 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2024 Intel Corporation. */
+
+#ifndef _IXGBE_E610_H_
+#define _IXGBE_E610_H_
+
+#include "ixgbe_type.h"
+
+int ixgbe_aci_send_cmd(struct ixgbe_hw *hw, struct ixgbe_aci_desc *desc,
+ void *buf, u16 buf_size);
+bool ixgbe_aci_check_event_pending(struct ixgbe_hw *hw);
+int ixgbe_aci_get_event(struct ixgbe_hw *hw, struct ixgbe_aci_event *e,
+ bool *pending);
+void ixgbe_fill_dflt_direct_cmd_desc(struct ixgbe_aci_desc *desc, u16 opcode);
+int ixgbe_acquire_res(struct ixgbe_hw *hw, enum ixgbe_aci_res_ids res,
+ enum ixgbe_aci_res_access_type access, u32 timeout);
+void ixgbe_release_res(struct ixgbe_hw *hw, enum ixgbe_aci_res_ids res);
+int ixgbe_aci_list_caps(struct ixgbe_hw *hw, void *buf, u16 buf_size,
+ u32 *cap_count, enum ixgbe_aci_opc opc);
+int ixgbe_discover_dev_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_dev_caps *dev_caps);
+int ixgbe_discover_func_caps(struct ixgbe_hw *hw,
+ struct ixgbe_hw_func_caps *func_caps);
+int ixgbe_get_caps(struct ixgbe_hw *hw);
+int ixgbe_aci_disable_rxen(struct ixgbe_hw *hw);
+int ixgbe_aci_get_phy_caps(struct ixgbe_hw *hw, bool qual_mods, u8 report_mode,
+ struct ixgbe_aci_cmd_get_phy_caps_data *pcaps);
+void ixgbe_copy_phy_caps_to_cfg(struct ixgbe_aci_cmd_get_phy_caps_data *caps,
+ struct ixgbe_aci_cmd_set_phy_cfg_data *cfg);
+int ixgbe_aci_set_phy_cfg(struct ixgbe_hw *hw,
+ struct ixgbe_aci_cmd_set_phy_cfg_data *cfg);
+int ixgbe_aci_set_link_restart_an(struct ixgbe_hw *hw, bool ena_link);
+int ixgbe_update_link_info(struct ixgbe_hw *hw);
+int ixgbe_get_link_status(struct ixgbe_hw *hw, bool *link_up);
+int ixgbe_aci_get_link_info(struct ixgbe_hw *hw, bool ena_lse,
+ struct ixgbe_link_status *link);
+int ixgbe_aci_set_event_mask(struct ixgbe_hw *hw, u8 port_num, u16 mask);
+int ixgbe_configure_lse(struct ixgbe_hw *hw, bool activate, u16 mask);
+enum ixgbe_media_type ixgbe_get_media_type_e610(struct ixgbe_hw *hw);
+int ixgbe_setup_link_e610(struct ixgbe_hw *hw, ixgbe_link_speed speed,
+ bool autoneg_wait);
+int ixgbe_check_link_e610(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
+ bool *link_up, bool link_up_wait_to_complete);
+int ixgbe_get_link_capabilities_e610(struct ixgbe_hw *hw,
+ ixgbe_link_speed *speed,
+ bool *autoneg);
+int ixgbe_cfg_phy_fc(struct ixgbe_hw *hw,
+ struct ixgbe_aci_cmd_set_phy_cfg_data *cfg,
+ enum ixgbe_fc_mode req_mode);
+int ixgbe_setup_fc_e610(struct ixgbe_hw *hw);
+void ixgbe_fc_autoneg_e610(struct ixgbe_hw *hw);
+void ixgbe_disable_rx_e610(struct ixgbe_hw *hw);
+int ixgbe_init_phy_ops_e610(struct ixgbe_hw *hw);
+int ixgbe_identify_phy_e610(struct ixgbe_hw *hw);
+int ixgbe_identify_module_e610(struct ixgbe_hw *hw);
+int ixgbe_setup_phy_link_e610(struct ixgbe_hw *hw);
+int ixgbe_set_phy_power_e610(struct ixgbe_hw *hw, bool on);
+int ixgbe_enter_lplu_e610(struct ixgbe_hw *hw);
+int ixgbe_init_eeprom_params_e610(struct ixgbe_hw *hw);
+int ixgbe_aci_get_netlist_node(struct ixgbe_hw *hw,
+ struct ixgbe_aci_cmd_get_link_topo *cmd,
+ u8 *node_part_number, u16 *node_handle);
+int ixgbe_acquire_nvm(struct ixgbe_hw *hw,
+ enum ixgbe_aci_res_access_type access);
+void ixgbe_release_nvm(struct ixgbe_hw *hw);
+int ixgbe_aci_read_nvm(struct ixgbe_hw *hw, u16 module_typeid, u32 offset,
+ u16 length, void *data, bool last_command,
+ bool read_shadow_ram);
+int ixgbe_nvm_validate_checksum(struct ixgbe_hw *hw);
+int ixgbe_read_sr_word_aci(struct ixgbe_hw *hw, u16 offset, u16 *data);
+int ixgbe_read_flat_nvm(struct ixgbe_hw *hw, u32 offset, u32 *length,
+ u8 *data, bool read_shadow_ram);
+int ixgbe_read_sr_buf_aci(struct ixgbe_hw *hw, u16 offset, u16 *words,
+ u16 *data);
+int ixgbe_read_ee_aci_e610(struct ixgbe_hw *hw, u16 offset, u16 *data);
+int ixgbe_read_ee_aci_buffer_e610(struct ixgbe_hw *hw, u16 offset,
+ u16 words, u16 *data);
+int ixgbe_validate_eeprom_checksum_e610(struct ixgbe_hw *hw, u16 *checksum_val);
+int ixgbe_reset_hw_e610(struct ixgbe_hw *hw);
+
+#endif /* _IXGBE_E610_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
index 9482e0cca8b7..da91c582d439 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
/* ethtool support for ixgbe */
@@ -690,6 +690,7 @@ static void ixgbe_get_regs(struct net_device *netdev,
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
regs_buff[35 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTL_82599(i));
regs_buff[43 + i] = IXGBE_READ_REG(hw, IXGBE_FCRTH_82599(i));
break;
@@ -1613,6 +1614,7 @@ static int ixgbe_reg_test(struct ixgbe_adapter *adapter, u64 *data)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
toggle = 0x7FFFF30F;
test = reg_test_82599;
break;
@@ -1874,6 +1876,7 @@ static int ixgbe_setup_desc_rings(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
reg_data = IXGBE_READ_REG(&adapter->hw, IXGBE_DMATXCTL);
reg_data |= IXGBE_DMATXCTL_TE;
IXGBE_WRITE_REG(&adapter->hw, IXGBE_DMATXCTL, reg_data);
@@ -1935,6 +1938,7 @@ static int ixgbe_setup_loopback_test(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
reg_data = IXGBE_READ_REG(hw, IXGBE_MACC);
reg_data |= IXGBE_MACC_FLU;
IXGBE_WRITE_REG(hw, IXGBE_MACC, reg_data);
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
index 16fa621ce0ff..336d47ffb95a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_lib.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#include "ixgbe.h"
#include "ixgbe_sriov.h"
@@ -107,6 +107,7 @@ static void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
if (num_tcs > 4) {
/*
* TCs : TC0/1 TC2/3 TC4-7
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 2e38e8f6fac1..7236f20c9a30 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#include <linux/types.h>
#include <linux/module.h>
@@ -42,6 +42,7 @@
#include "ixgbe.h"
#include "ixgbe_common.h"
+#include "ixgbe_e610.h"
#include "ixgbe_dcb_82599.h"
#include "ixgbe_mbx.h"
#include "ixgbe_phy.h"
@@ -73,6 +74,7 @@ static const struct ixgbe_info *ixgbe_info_tbl[] = {
[board_x550em_x_fw] = &ixgbe_x550em_x_fw_info,
[board_x550em_a] = &ixgbe_x550em_a_info,
[board_x550em_a_fw] = &ixgbe_x550em_a_fw_info,
+ [board_e610] = &ixgbe_e610_info,
};
/* ixgbe_pci_tbl - PCI Device ID Table
@@ -131,6 +133,11 @@ static const struct pci_device_id ixgbe_pci_tbl[] = {
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_SFP), board_x550em_a },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_1G_T), board_x550em_a_fw },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_1G_T_L), board_x550em_a_fw },
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_E610_BACKPLANE), board_e610},
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_E610_SFP), board_e610},
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_E610_10G_T), board_e610},
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_E610_2_5G_T), board_e610},
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_E610_SGMII), board_e610},
/* required last entry */
{0, }
};
@@ -173,6 +180,8 @@ static struct workqueue_struct *ixgbe_wq;
static bool ixgbe_check_cfg_remove(struct ixgbe_hw *hw, struct pci_dev *pdev);
static void ixgbe_watchdog_link_is_down(struct ixgbe_adapter *);
+static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *);
+static void ixgbe_watchdog_update_link(struct ixgbe_adapter *);
static const struct net_device_ops ixgbe_netdev_ops;
@@ -236,8 +245,11 @@ static int ixgbe_get_parent_bus_info(struct ixgbe_adapter *adapter)
* bandwidth details should be gathered from the parent bus instead of from the
* device. Used to ensure that various locations all have the correct device ID
* checks.
+ *
+ * Return: true if information should be collected from the parent bus, false
+ * otherwise
*/
-static inline bool ixgbe_pcie_from_parent(struct ixgbe_hw *hw)
+static bool ixgbe_pcie_from_parent(struct ixgbe_hw *hw)
{
switch (hw->device_id) {
case IXGBE_DEV_ID_82599_SFP_SF_QP:
@@ -876,6 +888,7 @@ static void ixgbe_set_ivar(struct ixgbe_adapter *adapter, s8 direction,
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
if (direction == -1) {
/* other causes */
msix_vector |= IXGBE_IVAR_ALLOC_VAL;
@@ -915,6 +928,7 @@ void ixgbe_irq_rearm_queues(struct ixgbe_adapter *adapter,
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
mask = (qmask & 0xFFFFFFFF);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EICS_EX(0), mask);
mask = (qmask >> 32);
@@ -1025,7 +1039,7 @@ static u64 ixgbe_get_tx_pending(struct ixgbe_ring *ring)
return ((head <= tail) ? tail : tail + ring->count) - head;
}
-static inline bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring)
+static bool ixgbe_check_tx_hang(struct ixgbe_ring *tx_ring)
{
u32 tx_done = ixgbe_get_tx_completed(tx_ring);
u32 tx_done_old = tx_ring->tx_stats.tx_done_old;
@@ -1909,10 +1923,6 @@ bool ixgbe_cleanup_headers(struct ixgbe_ring *rx_ring,
{
struct net_device *netdev = rx_ring->netdev;
- /* XDP packets use error pointer so abort at this point */
- if (IS_ERR(skb))
- return true;
-
/* Verify netdev is present, and that packet does not have any
* errors that would be unacceptable to the netdev.
*/
@@ -2220,9 +2230,9 @@ static struct sk_buff *ixgbe_build_skb(struct ixgbe_ring *rx_ring,
return skb;
}
-static struct sk_buff *ixgbe_run_xdp(struct ixgbe_adapter *adapter,
- struct ixgbe_ring *rx_ring,
- struct xdp_buff *xdp)
+static int ixgbe_run_xdp(struct ixgbe_adapter *adapter,
+ struct ixgbe_ring *rx_ring,
+ struct xdp_buff *xdp)
{
int err, result = IXGBE_XDP_PASS;
struct bpf_prog *xdp_prog;
@@ -2272,7 +2282,7 @@ out_failure:
break;
}
xdp_out:
- return ERR_PTR(-result);
+ return result;
}
static unsigned int ixgbe_rx_frame_truesize(struct ixgbe_ring *rx_ring,
@@ -2330,6 +2340,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
unsigned int offset = rx_ring->rx_offset;
unsigned int xdp_xmit = 0;
struct xdp_buff xdp;
+ int xdp_res = 0;
/* Frame size depend on rx_ring setup when PAGE_SIZE=4K */
#if (PAGE_SIZE < 8192)
@@ -2375,12 +2386,10 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
/* At larger PAGE_SIZE, frame_sz depend on len size */
xdp.frame_sz = ixgbe_rx_frame_truesize(rx_ring, size);
#endif
- skb = ixgbe_run_xdp(adapter, rx_ring, &xdp);
+ xdp_res = ixgbe_run_xdp(adapter, rx_ring, &xdp);
}
- if (IS_ERR(skb)) {
- unsigned int xdp_res = -PTR_ERR(skb);
-
+ if (xdp_res) {
if (xdp_res & (IXGBE_XDP_TX | IXGBE_XDP_REDIR)) {
xdp_xmit |= xdp_res;
ixgbe_rx_buffer_flip(rx_ring, rx_buffer, size);
@@ -2400,7 +2409,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
}
/* exit if we failed to retrieve a buffer */
- if (!skb) {
+ if (!xdp_res && !skb) {
rx_ring->rx_stats.alloc_rx_buff_failed++;
rx_buffer->pagecnt_bias++;
break;
@@ -2414,7 +2423,7 @@ static int ixgbe_clean_rx_irq(struct ixgbe_q_vector *q_vector,
continue;
/* verify the packet layout is correct */
- if (ixgbe_cleanup_headers(rx_ring, rx_desc, skb))
+ if (xdp_res || ixgbe_cleanup_headers(rx_ring, rx_desc, skb))
continue;
/* probably a little skewed due to removing CRC */
@@ -2515,6 +2524,7 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
ixgbe_set_ivar(adapter, -1, 1, v_idx);
break;
default:
@@ -2528,6 +2538,9 @@ static void ixgbe_configure_msix(struct ixgbe_adapter *adapter)
IXGBE_EIMS_MAILBOX |
IXGBE_EIMS_LSC);
+ if (adapter->hw.mac.type == ixgbe_mac_e610)
+ mask &= ~IXGBE_EIMS_FW_EVENT;
+
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIAC, mask);
}
@@ -2744,6 +2757,7 @@ void ixgbe_write_eitr(struct ixgbe_q_vector *q_vector)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
/*
* set the WDIS bit to not clear the timer bits and cause an
* immediate assertion of the interrupt
@@ -2966,6 +2980,218 @@ static void ixgbe_check_lsc(struct ixgbe_adapter *adapter)
}
}
+/**
+ * ixgbe_check_phy_fw_load - check if PHY FW load failed
+ * @adapter: pointer to adapter structure
+ * @link_cfg_err: bitmap from the link info structure
+ *
+ * Check if external PHY FW load failed and print an error message if it did.
+ */
+static void ixgbe_check_phy_fw_load(struct ixgbe_adapter *adapter,
+ u8 link_cfg_err)
+{
+ if (!(link_cfg_err & IXGBE_ACI_LINK_EXTERNAL_PHY_LOAD_FAILURE)) {
+ adapter->flags2 &= ~IXGBE_FLAG2_PHY_FW_LOAD_FAILED;
+ return;
+ }
+
+ if (adapter->flags2 & IXGBE_FLAG2_PHY_FW_LOAD_FAILED)
+ return;
+
+ if (link_cfg_err & IXGBE_ACI_LINK_EXTERNAL_PHY_LOAD_FAILURE) {
+ netdev_err(adapter->netdev, "Device failed to load the FW for the external PHY. Please download and install the latest NVM for your device and try again\n");
+ adapter->flags2 |= IXGBE_FLAG2_PHY_FW_LOAD_FAILED;
+ }
+}
+
+/**
+ * ixgbe_check_module_power - check module power level
+ * @adapter: pointer to adapter structure
+ * @link_cfg_err: bitmap from the link info structure
+ *
+ * Check module power level returned by a previous call to aci_get_link_info
+ * and print error messages if module power level is not supported.
+ */
+static void ixgbe_check_module_power(struct ixgbe_adapter *adapter,
+ u8 link_cfg_err)
+{
+ /* If module power level is supported, clear the flag. */
+ if (!(link_cfg_err & (IXGBE_ACI_LINK_INVAL_MAX_POWER_LIMIT |
+ IXGBE_ACI_LINK_MODULE_POWER_UNSUPPORTED))) {
+ adapter->flags2 &= ~IXGBE_FLAG2_MOD_POWER_UNSUPPORTED;
+ return;
+ }
+
+ /* If IXGBE_FLAG2_MOD_POWER_UNSUPPORTED was previously set and the
+ * above block didn't clear this bit, there's nothing to do.
+ */
+ if (adapter->flags2 & IXGBE_FLAG2_MOD_POWER_UNSUPPORTED)
+ return;
+
+ if (link_cfg_err & IXGBE_ACI_LINK_INVAL_MAX_POWER_LIMIT) {
+ netdev_err(adapter->netdev, "The installed module is incompatible with the device's NVM image. Cannot start link.\n");
+ adapter->flags2 |= IXGBE_FLAG2_MOD_POWER_UNSUPPORTED;
+ } else if (link_cfg_err & IXGBE_ACI_LINK_MODULE_POWER_UNSUPPORTED) {
+ netdev_err(adapter->netdev, "The module's power requirements exceed the device's power supply. Cannot start link.\n");
+ adapter->flags2 |= IXGBE_FLAG2_MOD_POWER_UNSUPPORTED;
+ }
+}
+
+/**
+ * ixgbe_check_link_cfg_err - check if link configuration failed
+ * @adapter: pointer to adapter structure
+ * @link_cfg_err: bitmap from the link info structure
+ *
+ * Print if any link configuration failure happens due to the value in the
+ * link_cfg_err parameter in the link info structure.
+ */
+static void ixgbe_check_link_cfg_err(struct ixgbe_adapter *adapter,
+ u8 link_cfg_err)
+{
+ ixgbe_check_module_power(adapter, link_cfg_err);
+ ixgbe_check_phy_fw_load(adapter, link_cfg_err);
+}
+
+/**
+ * ixgbe_process_link_status_event - process the link event
+ * @adapter: pointer to adapter structure
+ * @link_up: true if the physical link is up and false if it is down
+ * @link_speed: current link speed received from the link event
+ *
+ * Return: 0 on success or negative value on failure.
+ */
+static int
+ixgbe_process_link_status_event(struct ixgbe_adapter *adapter, bool link_up,
+ u16 link_speed)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+ int status;
+
+ /* Update the link info structures and re-enable link events,
+ * don't bail on failure due to other book keeping needed.
+ */
+ status = ixgbe_update_link_info(hw);
+ if (status)
+ e_dev_err("Failed to update link status, err %d aq_err %d\n",
+ status, hw->aci.last_status);
+
+ ixgbe_check_link_cfg_err(adapter, hw->link.link_info.link_cfg_err);
+
+ /* Check if the link state is up after updating link info, and treat
+ * this event as an UP event since the link is actually UP now.
+ */
+ if (hw->link.link_info.link_info & IXGBE_ACI_LINK_UP)
+ link_up = true;
+
+ /* Turn off PHY if media was removed. */
+ if (!(adapter->flags2 & IXGBE_FLAG2_NO_MEDIA) &&
+ !(hw->link.link_info.link_info & IXGBE_ACI_MEDIA_AVAILABLE))
+ adapter->flags2 |= IXGBE_FLAG2_NO_MEDIA;
+
+ if (link_up == adapter->link_up &&
+ link_up == netif_carrier_ok(adapter->netdev) &&
+ link_speed == adapter->link_speed)
+ return 0;
+
+ adapter->flags |= IXGBE_FLAG_NEED_LINK_UPDATE;
+ adapter->link_check_timeout = jiffies;
+ ixgbe_watchdog_update_link(adapter);
+
+ if (link_up)
+ ixgbe_watchdog_link_is_up(adapter);
+ else
+ ixgbe_watchdog_link_is_down(adapter);
+
+ return 0;
+}
+
+/**
+ * ixgbe_handle_link_status_event - handle link status event via ACI
+ * @adapter: pointer to adapter structure
+ * @e: event structure containing link status info
+ */
+static void
+ixgbe_handle_link_status_event(struct ixgbe_adapter *adapter,
+ struct ixgbe_aci_event *e)
+{
+ struct ixgbe_aci_cmd_get_link_status_data *link_data;
+ u16 link_speed;
+ bool link_up;
+
+ link_data = (struct ixgbe_aci_cmd_get_link_status_data *)e->msg_buf;
+
+ link_up = !!(link_data->link_info & IXGBE_ACI_LINK_UP);
+ link_speed = le16_to_cpu(link_data->link_speed);
+
+ if (ixgbe_process_link_status_event(adapter, link_up, link_speed))
+ e_dev_warn("Could not process link status event");
+}
+
+/**
+ * ixgbe_schedule_fw_event - schedule Firmware event
+ * @adapter: pointer to the adapter structure
+ *
+ * If the adapter is not in down, removing or resetting state,
+ * an event is scheduled.
+ */
+static void ixgbe_schedule_fw_event(struct ixgbe_adapter *adapter)
+{
+ if (!test_bit(__IXGBE_DOWN, &adapter->state) &&
+ !test_bit(__IXGBE_REMOVING, &adapter->state) &&
+ !test_bit(__IXGBE_RESETTING, &adapter->state)) {
+ adapter->flags2 |= IXGBE_FLAG2_FW_ASYNC_EVENT;
+ ixgbe_service_event_schedule(adapter);
+ }
+}
+
+/**
+ * ixgbe_aci_event_cleanup - release msg_buf memory
+ * @event: pointer to the event holding msg_buf to be released
+ *
+ * Clean memory allocated for event's msg_buf. Implements auto memory cleanup.
+ */
+static void ixgbe_aci_event_cleanup(struct ixgbe_aci_event *event)
+{
+ kfree(event->msg_buf);
+}
+
+/**
+ * ixgbe_handle_fw_event - handle Firmware event
+ * @adapter: pointer to the adapter structure
+ *
+ * Obtain an event from the ACI and then and then process it according to the
+ * type of the event and the opcode.
+ */
+static void ixgbe_handle_fw_event(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_aci_event event __cleanup(ixgbe_aci_event_cleanup);
+ struct ixgbe_hw *hw = &adapter->hw;
+ bool pending = false;
+ int err;
+
+ if (adapter->flags2 & IXGBE_FLAG2_FW_ASYNC_EVENT)
+ adapter->flags2 &= ~IXGBE_FLAG2_FW_ASYNC_EVENT;
+ event.buf_len = IXGBE_ACI_MAX_BUFFER_SIZE;
+ event.msg_buf = kzalloc(event.buf_len, GFP_KERNEL);
+ if (!event.msg_buf)
+ return;
+
+ do {
+ err = ixgbe_aci_get_event(hw, &event, &pending);
+ if (err)
+ break;
+
+ switch (le16_to_cpu(event.desc.opcode)) {
+ case ixgbe_aci_opc_get_link_status:
+ ixgbe_handle_link_status_event(adapter, &event);
+ break;
+ default:
+ e_warn(hw, "unknown FW async event captured\n");
+ break;
+ }
+ } while (pending);
+}
+
static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
u64 qmask)
{
@@ -2982,6 +3208,7 @@ static inline void ixgbe_irq_enable_queues(struct ixgbe_adapter *adapter,
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
mask = (qmask & 0xFFFFFFFF);
if (mask)
IXGBE_WRITE_REG(hw, IXGBE_EIMS_EX(0), mask);
@@ -3035,6 +3262,9 @@ static inline void ixgbe_irq_enable(struct ixgbe_adapter *adapter, bool queues,
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_e610:
+ mask |= IXGBE_EIMS_FW_EVENT;
+ fallthrough;
case ixgbe_mac_x550em_a:
if (adapter->hw.device_id == IXGBE_DEV_ID_X550EM_X_SFP ||
adapter->hw.device_id == IXGBE_DEV_ID_X550EM_A_SFP ||
@@ -3091,12 +3321,16 @@ static irqreturn_t ixgbe_msix_other(int irq, void *data)
if (eicr & IXGBE_EICR_MAILBOX)
ixgbe_msg_task(adapter);
+ if (eicr & IXGBE_EICR_FW_EVENT)
+ ixgbe_schedule_fw_event(adapter);
+
switch (hw->mac.type) {
case ixgbe_mac_82599EB:
case ixgbe_mac_X540:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
if (hw->phy.type == ixgbe_phy_x550em_ext_t &&
(eicr & IXGBE_EICR_GPI_SDP0_X540)) {
adapter->flags2 |= IXGBE_FLAG2_PHY_INTERRUPT;
@@ -3334,6 +3568,9 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
if (eicr & IXGBE_EICR_LSC)
ixgbe_check_lsc(adapter);
+ if (eicr & IXGBE_EICR_FW_EVENT)
+ ixgbe_schedule_fw_event(adapter);
+
switch (hw->mac.type) {
case ixgbe_mac_82599EB:
ixgbe_check_sfp_event(adapter, eicr);
@@ -3342,6 +3579,7 @@ static irqreturn_t ixgbe_intr(int irq, void *data)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
if (eicr & IXGBE_EICR_ECC) {
e_info(link, "Received ECC Err, initiating reset\n");
set_bit(__IXGBE_RESET_REQUESTED, &adapter->state);
@@ -3442,6 +3680,7 @@ static inline void ixgbe_irq_disable(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC, 0xFFFF0000);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(0), ~0);
IXGBE_WRITE_REG(&adapter->hw, IXGBE_EIMC_EX(1), ~0);
@@ -4359,6 +4598,7 @@ static void ixgbe_setup_rdrxctl(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
if (adapter->num_vfs)
rdrxctl |= IXGBE_RDRXCTL_PSP;
fallthrough;
@@ -4526,6 +4766,7 @@ static void ixgbe_vlan_strip_disable(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
for (i = 0; i < adapter->num_rx_queues; i++) {
struct ixgbe_ring *ring = adapter->rx_ring[i];
@@ -4564,6 +4805,7 @@ static void ixgbe_vlan_strip_enable(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
for (i = 0; i < adapter->num_rx_queues; i++) {
struct ixgbe_ring *ring = adapter->rx_ring[i];
@@ -5148,6 +5390,7 @@ static int ixgbe_hpbthresh(struct ixgbe_adapter *adapter, int pb)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
dv_id = IXGBE_DV_X540(link, tc);
break;
default:
@@ -5208,6 +5451,7 @@ static int ixgbe_lpbthresh(struct ixgbe_adapter *adapter, int pb)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
dv_id = IXGBE_LOW_DV_X540(tc);
break;
default:
@@ -5510,6 +5754,48 @@ static void ixgbe_configure(struct ixgbe_adapter *adapter)
}
/**
+ * ixgbe_enable_link_status_events - enable link status events
+ * @adapter: pointer to the adapter structure
+ * @mask: event mask to be set
+ *
+ * Enables link status events by invoking ixgbe_configure_lse()
+ *
+ * Return: the exit code of the operation.
+ */
+static int ixgbe_enable_link_status_events(struct ixgbe_adapter *adapter,
+ u16 mask)
+{
+ int err;
+
+ err = ixgbe_configure_lse(&adapter->hw, true, mask);
+ if (err)
+ return err;
+
+ adapter->lse_mask = mask;
+ return 0;
+}
+
+/**
+ * ixgbe_disable_link_status_events - disable link status events
+ * @adapter: pointer to the adapter structure
+ *
+ * Disables link status events by invoking ixgbe_configure_lse()
+ *
+ * Return: the exit code of the operation.
+ */
+static int ixgbe_disable_link_status_events(struct ixgbe_adapter *adapter)
+{
+ int err;
+
+ err = ixgbe_configure_lse(&adapter->hw, false, adapter->lse_mask);
+ if (err)
+ return err;
+
+ adapter->lse_mask = 0;
+ return 0;
+}
+
+/**
* ixgbe_sfp_link_config - set up SFP+ link
* @adapter: pointer to private adapter struct
**/
@@ -5532,13 +5818,21 @@ static void ixgbe_sfp_link_config(struct ixgbe_adapter *adapter)
* ixgbe_non_sfp_link_config - set up non-SFP+ link
* @hw: pointer to private hardware struct
*
- * Returns 0 on success, negative on failure
+ * Configure non-SFP link.
+ *
+ * Return: 0 on success, negative on failure
**/
static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw)
{
- u32 speed;
+ struct ixgbe_adapter *adapter = container_of(hw, struct ixgbe_adapter,
+ hw);
+ u16 mask = ~((u16)(IXGBE_ACI_LINK_EVENT_UPDOWN |
+ IXGBE_ACI_LINK_EVENT_MEDIA_NA |
+ IXGBE_ACI_LINK_EVENT_MODULE_QUAL_FAIL |
+ IXGBE_ACI_LINK_EVENT_PHY_FW_LOAD_FAIL));
bool autoneg, link_up = false;
int ret = -EIO;
+ u32 speed;
if (hw->mac.ops.check_link)
ret = hw->mac.ops.check_link(hw, &speed, &link_up, false);
@@ -5561,13 +5855,53 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw)
if (ret)
return ret;
- if (hw->mac.ops.setup_link)
+ if (hw->mac.ops.setup_link) {
+ if (adapter->hw.mac.type == ixgbe_mac_e610) {
+ ret = ixgbe_enable_link_status_events(adapter, mask);
+ if (ret)
+ return ret;
+ }
ret = hw->mac.ops.setup_link(hw, speed, link_up);
+ }
return ret;
}
/**
+ * ixgbe_check_media_subtask - check for media
+ * @adapter: pointer to adapter structure
+ *
+ * If media is available then initialize PHY user configuration. Configure the
+ * PHY if the interface is up.
+ */
+static void ixgbe_check_media_subtask(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_hw *hw = &adapter->hw;
+
+ /* No need to check for media if it's already present */
+ if (!(adapter->flags2 & IXGBE_FLAG2_NO_MEDIA))
+ return;
+
+ /* Refresh link info and check if media is present */
+ if (ixgbe_update_link_info(hw))
+ return;
+
+ ixgbe_check_link_cfg_err(adapter, hw->link.link_info.link_cfg_err);
+
+ if (hw->link.link_info.link_info & IXGBE_ACI_MEDIA_AVAILABLE) {
+ /* PHY settings are reset on media insertion, reconfigure
+ * PHY to preserve settings.
+ */
+ if (!(ixgbe_non_sfp_link_config(&adapter->hw)))
+ adapter->flags2 &= ~IXGBE_FLAG2_NO_MEDIA;
+
+ /* A Link Status Event will be generated; the event handler
+ * will complete bringing the interface up
+ */
+ }
+}
+
+/**
* ixgbe_clear_vf_stats_counters - Clear out VF stats after reset
* @adapter: board private structure
*
@@ -5630,6 +5964,7 @@ static void ixgbe_setup_gpie(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
default:
IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(0), 0xFFFFFFFF);
IXGBE_WRITE_REG(hw, IXGBE_EIAM_EX(1), 0xFFFFFFFF);
@@ -5980,6 +6315,7 @@ dma_engine_disable:
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
IXGBE_WRITE_REG(hw, IXGBE_DMATXCTL,
(IXGBE_READ_REG(hw, IXGBE_DMATXCTL) &
~IXGBE_DMATXCTL_TE));
@@ -6224,6 +6560,8 @@ void ixgbe_down(struct ixgbe_adapter *adapter)
ixgbe_clean_all_tx_rings(adapter);
ixgbe_clean_all_rx_rings(adapter);
+ if (adapter->hw.mac.type == ixgbe_mac_e610)
+ ixgbe_disable_link_status_events(adapter);
}
/**
@@ -6279,6 +6617,7 @@ static void ixgbe_init_dcb(struct ixgbe_adapter *adapter)
break;
case ixgbe_mac_X540:
case ixgbe_mac_X550:
+ case ixgbe_mac_e610:
adapter->dcb_cfg.num_tcs.pg_tcs = X540_TRAFFIC_CLASS;
adapter->dcb_cfg.num_tcs.pfc_tcs = X540_TRAFFIC_CLASS;
break;
@@ -6342,6 +6681,8 @@ static int ixgbe_sw_init(struct ixgbe_adapter *adapter,
hw->subsystem_vendor_id = pdev->subsystem_vendor;
hw->subsystem_device_id = pdev->subsystem_device;
+ hw->mac.max_link_up_time = IXGBE_LINK_UP_TIME;
+
/* get_invariants needs the device IDs */
ii->get_invariants(hw);
@@ -6909,6 +7250,19 @@ int ixgbe_open(struct net_device *netdev)
ixgbe_up_complete(adapter);
udp_tunnel_nic_reset_ntf(netdev);
+ if (adapter->hw.mac.type == ixgbe_mac_e610) {
+ int err = ixgbe_update_link_info(&adapter->hw);
+
+ if (err)
+ e_dev_err("Failed to update link info, err %d.\n", err);
+
+ ixgbe_check_link_cfg_err(adapter,
+ adapter->hw.link.link_info.link_cfg_err);
+
+ err = ixgbe_non_sfp_link_config(&adapter->hw);
+ if (ixgbe_non_sfp_link_config(&adapter->hw))
+ e_dev_err("Link setup failed, err %d.\n", err);
+ }
return 0;
@@ -7062,6 +7416,7 @@ static int __ixgbe_shutdown(struct pci_dev *pdev, bool *enable_wake)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
pci_wake_from_d3(pdev, !!wufc);
break;
default:
@@ -7209,6 +7564,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
hwstats->pxonrxc[i] +=
IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
break;
@@ -7221,11 +7577,12 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
for (i = 0; i < 16; i++) {
hwstats->qptc[i] += IXGBE_READ_REG(hw, IXGBE_QPTC(i));
hwstats->qprc[i] += IXGBE_READ_REG(hw, IXGBE_QPRC(i));
- if ((hw->mac.type == ixgbe_mac_82599EB) ||
- (hw->mac.type == ixgbe_mac_X540) ||
- (hw->mac.type == ixgbe_mac_X550) ||
- (hw->mac.type == ixgbe_mac_X550EM_x) ||
- (hw->mac.type == ixgbe_mac_x550em_a)) {
+ if (hw->mac.type == ixgbe_mac_82599EB ||
+ hw->mac.type == ixgbe_mac_X540 ||
+ hw->mac.type == ixgbe_mac_X550 ||
+ hw->mac.type == ixgbe_mac_X550EM_x ||
+ hw->mac.type == ixgbe_mac_x550em_a ||
+ hw->mac.type == ixgbe_mac_e610) {
hwstats->qbtc[i] += IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
IXGBE_READ_REG(hw, IXGBE_QBTC_H(i)); /* to clear */
hwstats->qbrc[i] += IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
@@ -7251,6 +7608,7 @@ void ixgbe_update_stats(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
/* OS2BMC stats are X540 and later */
hwstats->o2bgptc += IXGBE_READ_REG(hw, IXGBE_O2BGPTC);
hwstats->o2bspc += IXGBE_READ_REG(hw, IXGBE_O2BSPC);
@@ -7551,6 +7909,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
case ixgbe_mac_82599EB: {
u32 mflcn = IXGBE_READ_REG(hw, IXGBE_MFLCN);
u32 fccfg = IXGBE_READ_REG(hw, IXGBE_FCCFG);
@@ -8052,6 +8411,11 @@ static void ixgbe_service_task(struct work_struct *work)
ixgbe_service_event_complete(adapter);
return;
}
+ if (adapter->hw.mac.type == ixgbe_mac_e610) {
+ if (adapter->flags2 & IXGBE_FLAG2_FW_ASYNC_EVENT)
+ ixgbe_handle_fw_event(adapter);
+ ixgbe_check_media_subtask(adapter);
+ }
ixgbe_reset_subtask(adapter);
ixgbe_phy_interrupt_subtask(adapter);
ixgbe_sfp_detection_subtask(adapter);
@@ -10771,6 +11135,24 @@ bool ixgbe_wol_supported(struct ixgbe_adapter *adapter, u16 device_id,
}
/**
+ * ixgbe_set_fw_version_e610 - Set FW version specifically on E610 adapters
+ * @adapter: the adapter private structure
+ *
+ * This function is used by probe and ethtool to determine the FW version to
+ * format to display. The FW version is taken from the EEPROM/NVM.
+ *
+ */
+static void ixgbe_set_fw_version_e610(struct ixgbe_adapter *adapter)
+{
+ struct ixgbe_orom_info *orom = &adapter->hw.flash.orom;
+ struct ixgbe_nvm_info *nvm = &adapter->hw.flash.nvm;
+
+ snprintf(adapter->eeprom_id, sizeof(adapter->eeprom_id),
+ "%x.%02x 0x%x %d.%d.%d", nvm->major, nvm->minor,
+ nvm->eetrack, orom->major, orom->build, orom->patch);
+}
+
+/**
* ixgbe_set_fw_version - Set FW version
* @adapter: the adapter private structure
*
@@ -10782,6 +11164,11 @@ static void ixgbe_set_fw_version(struct ixgbe_adapter *adapter)
struct ixgbe_hw *hw = &adapter->hw;
struct ixgbe_nvm_version nvm_ver;
+ if (adapter->hw.mac.type == ixgbe_mac_e610) {
+ ixgbe_set_fw_version_e610(adapter);
+ return;
+ }
+
ixgbe_get_oem_prod_version(hw, &nvm_ver);
if (nvm_ver.oem_valid) {
snprintf(adapter->eeprom_id, sizeof(adapter->eeprom_id),
@@ -10868,6 +11255,8 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
#else
indices = IXGBE_MAX_RSS_INDICES;
#endif
+ } else if (ii->mac == ixgbe_mac_e610) {
+ indices = IXGBE_MAX_RSS_INDICES_X550;
}
netdev = alloc_etherdev_mq(sizeof(struct ixgbe_adapter), indices);
@@ -10933,12 +11322,19 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
if (err)
goto err_sw_init;
+ if (adapter->hw.mac.type == ixgbe_mac_e610) {
+ err = ixgbe_get_caps(&adapter->hw);
+ if (err)
+ dev_err(&pdev->dev, "ixgbe_get_caps failed %d\n", err);
+ }
+
if (adapter->hw.mac.type == ixgbe_mac_82599EB)
adapter->flags2 |= IXGBE_FLAG2_AUTO_DISABLE_VF;
switch (adapter->hw.mac.type) {
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
+ case ixgbe_mac_e610:
netdev->udp_tunnel_nic_info = &ixgbe_udp_tunnels_x550;
break;
case ixgbe_mac_x550em_a:
@@ -10959,6 +11355,7 @@ static int ixgbe_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
IXGBE_WRITE_REG(&adapter->hw, IXGBE_WUS, ~0);
break;
default:
@@ -11130,6 +11527,8 @@ skip_sriov:
ether_addr_copy(hw->mac.addr, hw->mac.perm_addr);
ixgbe_mac_set_default_filter(adapter);
+ if (hw->mac.type == ixgbe_mac_e610)
+ mutex_init(&hw->aci.lock);
timer_setup(&adapter->service_timer, ixgbe_service_timer, 0);
if (ixgbe_removed(hw->hw_addr)) {
@@ -11275,6 +11674,8 @@ err_netdev:
err_register:
ixgbe_release_hw_control(adapter);
ixgbe_clear_interrupt_scheme(adapter);
+ if (hw->mac.type == ixgbe_mac_e610)
+ mutex_destroy(&adapter->hw.aci.lock);
err_sw_init:
ixgbe_disable_sriov(adapter);
adapter->flags2 &= ~IXGBE_FLAG2_SEARCH_FOR_SFP;
@@ -11321,6 +11722,11 @@ static void ixgbe_remove(struct pci_dev *pdev)
set_bit(__IXGBE_REMOVING, &adapter->state);
cancel_work_sync(&adapter->service_task);
+ if (adapter->hw.mac.type == ixgbe_mac_e610) {
+ ixgbe_disable_link_status_events(adapter);
+ mutex_destroy(&adapter->hw.aci.lock);
+ }
+
if (adapter->mii_bus)
mdiobus_unregister(adapter->mii_bus);
@@ -11452,6 +11858,9 @@ static pci_ers_result_t ixgbe_io_error_detected(struct pci_dev *pdev,
case ixgbe_mac_x550em_a:
device_id = IXGBE_DEV_ID_X550EM_A_VF;
break;
+ case ixgbe_mac_e610:
+ device_id = IXGBE_DEV_ID_E610_VF;
+ break;
default:
device_id = 0;
break;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
index d67d77e5dacc..788b5af07c70 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_mbx.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#include <linux/pci.h>
#include <linux/delay.h>
@@ -283,6 +283,7 @@ static int ixgbe_check_for_rst_pf(struct ixgbe_hw *hw, u16 vf_number)
case ixgbe_mac_X550:
case ixgbe_mac_X550EM_x:
case ixgbe_mac_x550em_a:
+ case ixgbe_mac_e610:
vflre = IXGBE_READ_REG(hw, IXGBE_VFLREC(reg_offset));
break;
default:
@@ -407,6 +408,7 @@ void ixgbe_init_mbx_params_pf(struct ixgbe_hw *hw)
hw->mac.type != ixgbe_mac_X550 &&
hw->mac.type != ixgbe_mac_X550EM_x &&
hw->mac.type != ixgbe_mac_x550em_a &&
+ hw->mac.type != ixgbe_mac_e610 &&
hw->mac.type != ixgbe_mac_X540)
return;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
index 07eaa3c3f4d3..0a03a8bb5f88 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#include <linux/pci.h>
#include <linux/delay.h>
@@ -1117,7 +1117,7 @@ int ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
MDIO_MMD_AN, &autoneg_reg);
- if (hw->mac.type == ixgbe_mac_X550) {
+ if (hw->mac.type == ixgbe_mac_X550 || hw->mac.type == ixgbe_mac_e610) {
/* Set or unset auto-negotiation 5G advertisement */
autoneg_reg &= ~IXGBE_MII_5GBASE_T_ADVERTISE;
if ((hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL) &&
@@ -1233,6 +1233,7 @@ static int ixgbe_get_copper_speeds_supported(struct ixgbe_hw *hw)
switch (hw->mac.type) {
case ixgbe_mac_X550:
+ case ixgbe_mac_e610:
hw->phy.speeds_supported |= IXGBE_LINK_SPEED_2_5GB_FULL;
hw->phy.speeds_supported |= IXGBE_LINK_SPEED_5GB_FULL;
break;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
index 14aa2ca51f70..81179c60af4e 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_phy.h
@@ -40,7 +40,7 @@
#define IXGBE_SFF_1GBASESX_CAPABLE 0x1
#define IXGBE_SFF_1GBASELX_CAPABLE 0x2
#define IXGBE_SFF_1GBASET_CAPABLE 0x8
-#define IXGBE_SFF_BASEBX10_CAPABLE 0x64
+#define IXGBE_SFF_BASEBX10_CAPABLE 0x40
#define IXGBE_SFF_10GBASESR_CAPABLE 0x10
#define IXGBE_SFF_10GBASELR_CAPABLE 0x20
#define IXGBE_SFF_SOFT_RS_SELECT_MASK 0x8
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
index 9631559a5aea..ccdce80edd14 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_sriov.c
@@ -1048,7 +1048,7 @@ static int ixgbe_negotiate_vf_api(struct ixgbe_adapter *adapter,
break;
}
- e_info(drv, "VF %d requested invalid api version %u\n", vf, api);
+ e_dbg(drv, "VF %d requested unsupported api version %u\n", vf, api);
return -1;
}
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
index 9baccacd02a1..5fdf32d79d82 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#ifndef _IXGBE_TYPE_H_
#define _IXGBE_TYPE_H_
@@ -7,6 +7,7 @@
#include <linux/types.h>
#include <linux/mdio.h>
#include <linux/netdevice.h>
+#include "ixgbe_type_e610.h"
/* Device IDs */
#define IXGBE_DEV_ID_82598 0x10B6
@@ -71,12 +72,19 @@
#define IXGBE_DEV_ID_X550EM_A_1G_T 0x15E4
#define IXGBE_DEV_ID_X550EM_A_1G_T_L 0x15E5
+#define IXGBE_DEV_ID_E610_BACKPLANE 0x57AE
+#define IXGBE_DEV_ID_E610_SFP 0x57AF
+#define IXGBE_DEV_ID_E610_10G_T 0x57B0
+#define IXGBE_DEV_ID_E610_2_5G_T 0x57B1
+#define IXGBE_DEV_ID_E610_SGMII 0x57B2
+
/* VF Device IDs */
#define IXGBE_DEV_ID_82599_VF 0x10ED
#define IXGBE_DEV_ID_X540_VF 0x1515
#define IXGBE_DEV_ID_X550_VF 0x1565
#define IXGBE_DEV_ID_X550EM_X_VF 0x15A8
#define IXGBE_DEV_ID_X550EM_A_VF 0x15C5
+#define IXGBE_DEV_ID_E610_VF 0x57AD
#define IXGBE_CAT(r, m) IXGBE_##r##_##m
@@ -1600,7 +1608,7 @@ enum {
#define IXGBE_EICR_PCI 0x00040000 /* PCI Exception */
#define IXGBE_EICR_MAILBOX 0x00080000 /* VF to PF Mailbox Interrupt */
#define IXGBE_EICR_LSC 0x00100000 /* Link Status Change */
-#define IXGBE_EICR_LINKSEC 0x00200000 /* PN Threshold */
+#define IXGBE_EICR_FW_EVENT 0x00200000 /* Async FW event */
#define IXGBE_EICR_MNG 0x00400000 /* Manageability Event Interrupt */
#define IXGBE_EICR_TS 0x00800000 /* Thermal Sensor Event */
#define IXGBE_EICR_TIMESYNC 0x01000000 /* Timesync Event */
@@ -1636,6 +1644,7 @@ enum {
#define IXGBE_EICS_PCI IXGBE_EICR_PCI /* PCI Exception */
#define IXGBE_EICS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */
#define IXGBE_EICS_LSC IXGBE_EICR_LSC /* Link Status Change */
+#define IXGBE_EICS_FW_EVENT IXGBE_EICR_FW_EVENT /* Async FW event */
#define IXGBE_EICS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
#define IXGBE_EICS_TIMESYNC IXGBE_EICR_TIMESYNC /* Timesync Event */
#define IXGBE_EICS_GPI_SDP0(_hw) IXGBE_EICR_GPI_SDP0(_hw)
@@ -1654,6 +1663,7 @@ enum {
#define IXGBE_EIMS_PCI IXGBE_EICR_PCI /* PCI Exception */
#define IXGBE_EIMS_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */
#define IXGBE_EIMS_LSC IXGBE_EICR_LSC /* Link Status Change */
+#define IXGBE_EIMS_FW_EVENT IXGBE_EICR_FW_EVENT /* Async FW event */
#define IXGBE_EIMS_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
#define IXGBE_EIMS_TS IXGBE_EICR_TS /* Thermel Sensor Event */
#define IXGBE_EIMS_TIMESYNC IXGBE_EICR_TIMESYNC /* Timesync Event */
@@ -1673,6 +1683,7 @@ enum {
#define IXGBE_EIMC_PCI IXGBE_EICR_PCI /* PCI Exception */
#define IXGBE_EIMC_MAILBOX IXGBE_EICR_MAILBOX /* VF to PF Mailbox Int */
#define IXGBE_EIMC_LSC IXGBE_EICR_LSC /* Link Status Change */
+#define IXGBE_EIMC_FW_EVENT IXGBE_EICR_FW_EVENT /* Async FW event */
#define IXGBE_EIMC_MNG IXGBE_EICR_MNG /* MNG Event Interrupt */
#define IXGBE_EIMC_TIMESYNC IXGBE_EICR_TIMESYNC /* Timesync Event */
#define IXGBE_EIMC_GPI_SDP0(_hw) IXGBE_EICR_GPI_SDP0(_hw)
@@ -2068,6 +2079,7 @@ enum {
#define IXGBE_SAN_MAC_ADDR_PTR 0x28
#define IXGBE_DEVICE_CAPS 0x2C
#define IXGBE_SERIAL_NUMBER_MAC_ADDR 0x11
+#define IXGBE_PCIE_MSIX_E610_CAPS 0xB2
#define IXGBE_PCIE_MSIX_82599_CAPS 0x72
#define IXGBE_MAX_MSIX_VECTORS_82599 0x40
#define IXGBE_PCIE_MSIX_82598_CAPS 0x62
@@ -2168,6 +2180,7 @@ enum {
#define IXGBE_PCI_DEVICE_STATUS 0xAA
#define IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING 0x0020
#define IXGBE_PCI_LINK_STATUS 0xB2
+#define IXGBE_PCI_LINK_STATUS_E610 0x82
#define IXGBE_PCI_DEVICE_CONTROL2 0xC8
#define IXGBE_PCI_LINK_WIDTH 0x3F0
#define IXGBE_PCI_LINK_WIDTH_1 0x10
@@ -2288,6 +2301,7 @@ enum {
#define IXGBE_RXMTRL_V2_MGMT_MSG 0x0D00
#define IXGBE_FCTRL_SBP 0x00000002 /* Store Bad Packet */
+#define IXGBE_FCTRL_TPE 0x00000080 /* Tag Promiscuous Ena*/
#define IXGBE_FCTRL_MPE 0x00000100 /* Multicast Promiscuous Ena*/
#define IXGBE_FCTRL_UPE 0x00000200 /* Unicast Promiscuous Ena */
#define IXGBE_FCTRL_BAM 0x00000400 /* Broadcast Accept Mode */
@@ -2351,6 +2365,7 @@ enum {
/* Multiple Transmit Queue Command Register */
#define IXGBE_MTQC_RT_ENA 0x1 /* DCB Enable */
#define IXGBE_MTQC_VT_ENA 0x2 /* VMDQ2 Enable */
+#define IXGBE_MTQC_NUM_TC_OR_Q 0xC /* Number of TCs or TxQs per pool */
#define IXGBE_MTQC_64Q_1PB 0x0 /* 64 queues 1 pack buffer */
#define IXGBE_MTQC_32VF 0x8 /* 4 TX Queues per pool w/32VF's */
#define IXGBE_MTQC_64VF 0x4 /* 2 TX Queues per pool w/64VF's */
@@ -2970,6 +2985,29 @@ typedef u32 ixgbe_link_speed;
IXGBE_LINK_SPEED_1GB_FULL | \
IXGBE_LINK_SPEED_10GB_FULL)
+/* Physical layer type */
+typedef u64 ixgbe_physical_layer;
+#define IXGBE_PHYSICAL_LAYER_UNKNOWN 0
+#define IXGBE_PHYSICAL_LAYER_10GBASE_T 0x00001
+#define IXGBE_PHYSICAL_LAYER_1000BASE_T 0x00002
+#define IXGBE_PHYSICAL_LAYER_100BASE_TX 0x00004
+#define IXGBE_PHYSICAL_LAYER_SFP_PLUS_CU 0x00008
+#define IXGBE_PHYSICAL_LAYER_10GBASE_LR 0x00010
+#define IXGBE_PHYSICAL_LAYER_10GBASE_LRM 0x00020
+#define IXGBE_PHYSICAL_LAYER_10GBASE_SR 0x00040
+#define IXGBE_PHYSICAL_LAYER_10GBASE_KX4 0x00080
+#define IXGBE_PHYSICAL_LAYER_10GBASE_CX4 0x00100
+#define IXGBE_PHYSICAL_LAYER_1000BASE_KX 0x00200
+#define IXGBE_PHYSICAL_LAYER_1000BASE_BX 0x00400
+#define IXGBE_PHYSICAL_LAYER_10GBASE_KR 0x00800
+#define IXGBE_PHYSICAL_LAYER_10GBASE_XAUI 0x01000
+#define IXGBE_PHYSICAL_LAYER_SFP_ACTIVE_DA 0x02000
+#define IXGBE_PHYSICAL_LAYER_1000BASE_SX 0x04000
+#define IXGBE_PHYSICAL_LAYER_10BASE_T 0x08000
+#define IXGBE_PHYSICAL_LAYER_2500BASE_KX 0x10000
+#define IXGBE_PHYSICAL_LAYER_2500BASE_T 0x20000
+#define IXGBE_PHYSICAL_LAYER_5000BASE_T 0x40000
+
/* Flow Control Data Sheet defined values
* Calculation and defines taken from 802.1bb Annex O
*/
@@ -3145,6 +3183,8 @@ enum ixgbe_mac_type {
ixgbe_mac_X550,
ixgbe_mac_X550EM_x,
ixgbe_mac_x550em_a,
+ ixgbe_mac_e610,
+ ixgbe_mac_e610_vf,
ixgbe_num_macs
};
@@ -3224,7 +3264,9 @@ enum ixgbe_media_type {
ixgbe_media_type_copper,
ixgbe_media_type_backplane,
ixgbe_media_type_cx4,
- ixgbe_media_type_virtual
+ ixgbe_media_type_virtual,
+ ixgbe_media_type_da,
+ ixgbe_media_type_aui,
};
/* Flow Control Settings */
@@ -3233,7 +3275,8 @@ enum ixgbe_fc_mode {
ixgbe_fc_rx_pause,
ixgbe_fc_tx_pause,
ixgbe_fc_full,
- ixgbe_fc_default
+ ixgbe_fc_default,
+ ixgbe_fc_pfc,
};
/* Smart Speed Settings */
@@ -3533,6 +3576,9 @@ struct ixgbe_link_operations {
struct ixgbe_link_info {
struct ixgbe_link_operations ops;
u8 addr;
+ struct ixgbe_link_status link_info;
+ struct ixgbe_link_status link_info_old;
+ u8 get_link_info;
};
struct ixgbe_eeprom_info {
@@ -3575,6 +3621,7 @@ struct ixgbe_mac_info {
u8 san_mac_rar_index;
struct ixgbe_thermal_sensor_data thermal_sensor_data;
bool set_lben;
+ u32 max_link_up_time;
u8 led_link_act;
};
@@ -3599,6 +3646,10 @@ struct ixgbe_phy_info {
bool reset_if_overtemp;
bool qsfp_shared_i2c_bus;
u32 nw_mng_if_sel;
+ u64 phy_type_low;
+ u64 phy_type_high;
+ u16 curr_user_speed_req;
+ struct ixgbe_aci_cmd_set_phy_cfg_data curr_user_phy_cfg;
};
struct ixgbe_mbx_stats {
@@ -3643,6 +3694,19 @@ struct ixgbe_hw {
bool allow_unsupported_sfp;
bool wol_enabled;
bool need_crosstalk_fix;
+ u8 api_branch;
+ u8 api_maj_ver;
+ u8 api_min_ver;
+ u8 api_patch;
+ u8 fw_branch;
+ u8 fw_maj_ver;
+ u8 fw_min_ver;
+ u8 fw_patch;
+ u32 fw_build;
+ struct ixgbe_aci_info aci;
+ struct ixgbe_flash_info flash;
+ struct ixgbe_hw_dev_caps dev_caps;
+ struct ixgbe_hw_func_caps func_caps;
};
struct ixgbe_info {
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h
new file mode 100644
index 000000000000..8d06ade3c7cd
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h
@@ -0,0 +1,1074 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2024 Intel Corporation. */
+
+#ifndef _IXGBE_TYPE_E610_H_
+#define _IXGBE_TYPE_E610_H_
+
+#define BYTES_PER_DWORD 4
+
+/* General E610 defines */
+#define IXGBE_MAX_VSI 768
+
+/* Checksum and Shadow RAM pointers */
+#define E610_SR_SW_CHECKSUM_WORD 0x3F
+
+/* Shadow RAM related */
+#define IXGBE_SR_WORDS_IN_1KB 512
+
+/* Firmware Status Register (GL_FWSTS) */
+#define GL_FWSTS 0x00083048 /* Reset Source: POR */
+#define GL_FWSTS_EP_PF0 BIT(24)
+#define GL_FWSTS_EP_PF1 BIT(25)
+
+/* Global NVM General Status Register */
+#define GLNVM_GENS 0x000B6100 /* Reset Source: POR */
+#define GLNVM_GENS_SR_SIZE_M GENMASK(7, 5)
+
+/* Flash Access Register */
+#define IXGBE_GLNVM_FLA 0x000B6108 /* Reset Source: POR */
+#define IXGBE_GLNVM_FLA_LOCKED_S 6
+#define IXGBE_GLNVM_FLA_LOCKED_M BIT(6)
+
+/* Admin Command Interface (ACI) registers */
+#define IXGBE_PF_HIDA(_i) (0x00085000 + ((_i) * 4))
+#define IXGBE_PF_HIDA_2(_i) (0x00085020 + ((_i) * 4))
+#define IXGBE_PF_HIBA(_i) (0x00084000 + ((_i) * 4))
+#define IXGBE_PF_HICR 0x00082048
+
+#define IXGBE_PF_HICR_EN BIT(0)
+#define IXGBE_PF_HICR_C BIT(1)
+#define IXGBE_PF_HICR_SV BIT(2)
+#define IXGBE_PF_HICR_EV BIT(3)
+
+#define IXGBE_ACI_DESC_SIZE 32
+#define IXGBE_ACI_DESC_SIZE_IN_DWORDS (IXGBE_ACI_DESC_SIZE / BYTES_PER_DWORD)
+
+#define IXGBE_ACI_MAX_BUFFER_SIZE 4096 /* Size in bytes */
+#define IXGBE_ACI_SEND_DELAY_TIME_MS 10
+#define IXGBE_ACI_SEND_MAX_EXECUTE 3
+#define IXGBE_ACI_SEND_TIMEOUT_MS \
+ (IXGBE_ACI_SEND_MAX_EXECUTE * IXGBE_ACI_SEND_DELAY_TIME_MS)
+/* [ms] timeout of waiting for sync response */
+#define IXGBE_ACI_SYNC_RESPONSE_TIMEOUT 100000
+/* [ms] timeout of waiting for async response */
+#define IXGBE_ACI_ASYNC_RESPONSE_TIMEOUT 150000
+/* [ms] timeout of waiting for resource release */
+#define IXGBE_ACI_RELEASE_RES_TIMEOUT 10000
+
+/* FW defined boundary for a large buffer, 4k >= Large buffer > 512 bytes */
+#define IXGBE_ACI_LG_BUF 512
+
+/* Flags sub-structure
+ * |0 |1 |2 |3 |4 |5 |6 |7 |8 |9 |10 |11 |12 |13 |14 |15 |
+ * |DD |CMP|ERR|VFE| * * RESERVED * * |LB |RD |VFC|BUF|SI |EI |FE |
+ */
+
+#define IXGBE_ACI_FLAG_DD BIT(0) /* 0x1 */
+#define IXGBE_ACI_FLAG_CMP BIT(1) /* 0x2 */
+#define IXGBE_ACI_FLAG_ERR BIT(2) /* 0x4 */
+#define IXGBE_ACI_FLAG_VFE BIT(3) /* 0x8 */
+#define IXGBE_ACI_FLAG_LB BIT(9) /* 0x200 */
+#define IXGBE_ACI_FLAG_RD BIT(10) /* 0x400 */
+#define IXGBE_ACI_FLAG_VFC BIT(11) /* 0x800 */
+#define IXGBE_ACI_FLAG_BUF BIT(12) /* 0x1000 */
+#define IXGBE_ACI_FLAG_SI BIT(13) /* 0x2000 */
+#define IXGBE_ACI_FLAG_EI BIT(14) /* 0x4000 */
+#define IXGBE_ACI_FLAG_FE BIT(15) /* 0x8000 */
+
+/* Admin Command Interface (ACI) error codes */
+enum ixgbe_aci_err {
+ IXGBE_ACI_RC_OK = 0, /* Success */
+ IXGBE_ACI_RC_EPERM = 1, /* Operation not permitted */
+ IXGBE_ACI_RC_ENOENT = 2, /* No such element */
+ IXGBE_ACI_RC_ESRCH = 3, /* Bad opcode */
+ IXGBE_ACI_RC_EINTR = 4, /* Operation interrupted */
+ IXGBE_ACI_RC_EIO = 5, /* I/O error */
+ IXGBE_ACI_RC_ENXIO = 6, /* No such resource */
+ IXGBE_ACI_RC_E2BIG = 7, /* Arg too long */
+ IXGBE_ACI_RC_EAGAIN = 8, /* Try again */
+ IXGBE_ACI_RC_ENOMEM = 9, /* Out of memory */
+ IXGBE_ACI_RC_EACCES = 10, /* Permission denied */
+ IXGBE_ACI_RC_EFAULT = 11, /* Bad address */
+ IXGBE_ACI_RC_EBUSY = 12, /* Device or resource busy */
+ IXGBE_ACI_RC_EEXIST = 13, /* Object already exists */
+ IXGBE_ACI_RC_EINVAL = 14, /* Invalid argument */
+ IXGBE_ACI_RC_ENOTTY = 15, /* Not a typewriter */
+ IXGBE_ACI_RC_ENOSPC = 16, /* No space left or alloc failure */
+ IXGBE_ACI_RC_ENOSYS = 17, /* Function not implemented */
+ IXGBE_ACI_RC_ERANGE = 18, /* Parameter out of range */
+ IXGBE_ACI_RC_EFLUSHED = 19, /* Cmd flushed due to prev cmd error */
+ IXGBE_ACI_RC_BAD_ADDR = 20, /* Descriptor contains a bad pointer */
+ IXGBE_ACI_RC_EMODE = 21, /* Op not allowed in current dev mode */
+ IXGBE_ACI_RC_EFBIG = 22, /* File too big */
+ IXGBE_ACI_RC_ESBCOMP = 23, /* SB-IOSF completion unsuccessful */
+ IXGBE_ACI_RC_ENOSEC = 24, /* Missing security manifest */
+ IXGBE_ACI_RC_EBADSIG = 25, /* Bad RSA signature */
+ IXGBE_ACI_RC_ESVN = 26, /* SVN number prohibits this package */
+ IXGBE_ACI_RC_EBADMAN = 27, /* Manifest hash mismatch */
+ IXGBE_ACI_RC_EBADBUF = 28, /* Buffer hash mismatches manifest */
+ IXGBE_ACI_RC_EACCES_BMCU = 29, /* BMC Update in progress */
+};
+
+/* Admin Command Interface (ACI) opcodes */
+enum ixgbe_aci_opc {
+ ixgbe_aci_opc_get_ver = 0x0001,
+ ixgbe_aci_opc_driver_ver = 0x0002,
+ ixgbe_aci_opc_get_exp_err = 0x0005,
+
+ /* resource ownership */
+ ixgbe_aci_opc_req_res = 0x0008,
+ ixgbe_aci_opc_release_res = 0x0009,
+
+ /* device/function capabilities */
+ ixgbe_aci_opc_list_func_caps = 0x000A,
+ ixgbe_aci_opc_list_dev_caps = 0x000B,
+
+ /* safe disable of RXEN */
+ ixgbe_aci_opc_disable_rxen = 0x000C,
+
+ /* FW events */
+ ixgbe_aci_opc_get_fw_event = 0x0014,
+
+ /* PHY commands */
+ ixgbe_aci_opc_get_phy_caps = 0x0600,
+ ixgbe_aci_opc_set_phy_cfg = 0x0601,
+ ixgbe_aci_opc_restart_an = 0x0605,
+ ixgbe_aci_opc_get_link_status = 0x0607,
+ ixgbe_aci_opc_set_event_mask = 0x0613,
+ ixgbe_aci_opc_get_link_topo = 0x06E0,
+ ixgbe_aci_opc_get_link_topo_pin = 0x06E1,
+ ixgbe_aci_opc_read_i2c = 0x06E2,
+ ixgbe_aci_opc_write_i2c = 0x06E3,
+ ixgbe_aci_opc_read_mdio = 0x06E4,
+ ixgbe_aci_opc_write_mdio = 0x06E5,
+ ixgbe_aci_opc_set_gpio_by_func = 0x06E6,
+ ixgbe_aci_opc_get_gpio_by_func = 0x06E7,
+ ixgbe_aci_opc_set_gpio = 0x06EC,
+ ixgbe_aci_opc_get_gpio = 0x06ED,
+ ixgbe_aci_opc_sff_eeprom = 0x06EE,
+ ixgbe_aci_opc_prog_topo_dev_nvm = 0x06F2,
+ ixgbe_aci_opc_read_topo_dev_nvm = 0x06F3,
+
+ /* NVM commands */
+ ixgbe_aci_opc_nvm_read = 0x0701,
+ ixgbe_aci_opc_nvm_erase = 0x0702,
+ ixgbe_aci_opc_nvm_write = 0x0703,
+ ixgbe_aci_opc_nvm_cfg_read = 0x0704,
+ ixgbe_aci_opc_nvm_cfg_write = 0x0705,
+ ixgbe_aci_opc_nvm_checksum = 0x0706,
+ ixgbe_aci_opc_nvm_write_activate = 0x0707,
+ ixgbe_aci_opc_nvm_sr_dump = 0x0707,
+ ixgbe_aci_opc_nvm_save_factory_settings = 0x0708,
+ ixgbe_aci_opc_nvm_update_empr = 0x0709,
+ ixgbe_aci_opc_nvm_pkg_data = 0x070A,
+ ixgbe_aci_opc_nvm_pass_component_tbl = 0x070B,
+
+ /* Alternate Structure Commands */
+ ixgbe_aci_opc_write_alt_direct = 0x0900,
+ ixgbe_aci_opc_write_alt_indirect = 0x0901,
+ ixgbe_aci_opc_read_alt_direct = 0x0902,
+ ixgbe_aci_opc_read_alt_indirect = 0x0903,
+ ixgbe_aci_opc_done_alt_write = 0x0904,
+ ixgbe_aci_opc_clear_port_alt_write = 0x0906,
+
+ /* debug commands */
+ ixgbe_aci_opc_debug_dump_internals = 0xFF08,
+
+ /* SystemDiagnostic commands */
+ ixgbe_aci_opc_set_health_status_config = 0xFF20,
+ ixgbe_aci_opc_get_supported_health_status_codes = 0xFF21,
+ ixgbe_aci_opc_get_health_status = 0xFF22,
+ ixgbe_aci_opc_clear_health_status = 0xFF23,
+};
+
+/* Get version (direct 0x0001) */
+struct ixgbe_aci_cmd_get_ver {
+ __le32 rom_ver;
+ __le32 fw_build;
+ u8 fw_branch;
+ u8 fw_major;
+ u8 fw_minor;
+ u8 fw_patch;
+ u8 api_branch;
+ u8 api_major;
+ u8 api_minor;
+ u8 api_patch;
+};
+
+#define IXGBE_DRV_VER_STR_LEN_E610 32
+
+/* Send driver version (indirect 0x0002) */
+struct ixgbe_aci_cmd_driver_ver {
+ u8 major_ver;
+ u8 minor_ver;
+ u8 build_ver;
+ u8 subbuild_ver;
+ u8 reserved[4];
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+/* Get Expanded Error Code (0x0005, direct) */
+struct ixgbe_aci_cmd_get_exp_err {
+ __le32 reason;
+#define IXGBE_ACI_EXPANDED_ERROR_NOT_PROVIDED 0xFFFFFFFF
+ __le32 identifier;
+ u8 rsvd[8];
+};
+
+/* FW update timeout definitions are in milliseconds */
+#define IXGBE_NVM_TIMEOUT 180000
+
+enum ixgbe_aci_res_access_type {
+ IXGBE_RES_READ = 1,
+ IXGBE_RES_WRITE
+};
+
+enum ixgbe_aci_res_ids {
+ IXGBE_NVM_RES_ID = 1,
+ IXGBE_SPD_RES_ID,
+ IXGBE_CHANGE_LOCK_RES_ID,
+ IXGBE_GLOBAL_CFG_LOCK_RES_ID
+};
+
+/* Request resource ownership (direct 0x0008)
+ * Release resource ownership (direct 0x0009)
+ */
+struct ixgbe_aci_cmd_req_res {
+ __le16 res_id;
+ __le16 access_type;
+
+ /* Upon successful completion, FW writes this value and driver is
+ * expected to release resource before timeout. This value is provided
+ * in milliseconds.
+ */
+ __le32 timeout;
+#define IXGBE_ACI_RES_NVM_READ_DFLT_TIMEOUT_MS 3000
+#define IXGBE_ACI_RES_NVM_WRITE_DFLT_TIMEOUT_MS 180000
+#define IXGBE_ACI_RES_CHNG_LOCK_DFLT_TIMEOUT_MS 1000
+#define IXGBE_ACI_RES_GLBL_LOCK_DFLT_TIMEOUT_MS 3000
+ /* For SDP: pin ID of the SDP */
+ __le32 res_number;
+ __le16 status;
+#define IXGBE_ACI_RES_GLBL_SUCCESS 0
+#define IXGBE_ACI_RES_GLBL_IN_PROG 1
+#define IXGBE_ACI_RES_GLBL_DONE 2
+ u8 reserved[2];
+};
+
+/* Get function capabilities (indirect 0x000A)
+ * Get device capabilities (indirect 0x000B)
+ */
+struct ixgbe_aci_cmd_list_caps {
+ u8 cmd_flags;
+ u8 pf_index;
+ u8 reserved[2];
+ __le32 count;
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+/* Device/Function buffer entry, repeated per reported capability */
+struct ixgbe_aci_cmd_list_caps_elem {
+ __le16 cap;
+#define IXGBE_ACI_CAPS_VALID_FUNCTIONS 0x0005
+#define IXGBE_ACI_MAX_VALID_FUNCTIONS 0x8
+#define IXGBE_ACI_CAPS_SRIOV 0x0012
+#define IXGBE_ACI_CAPS_VF 0x0013
+#define IXGBE_ACI_CAPS_VMDQ 0x0014
+#define IXGBE_ACI_CAPS_VSI 0x0017
+#define IXGBE_ACI_CAPS_DCB 0x0018
+#define IXGBE_ACI_CAPS_RSS 0x0040
+#define IXGBE_ACI_CAPS_RXQS 0x0041
+#define IXGBE_ACI_CAPS_TXQS 0x0042
+#define IXGBE_ACI_CAPS_MSIX 0x0043
+#define IXGBE_ACI_CAPS_FD 0x0045
+#define IXGBE_ACI_CAPS_1588 0x0046
+#define IXGBE_ACI_CAPS_MAX_MTU 0x0047
+#define IXGBE_ACI_CAPS_NVM_VER 0x0048
+#define IXGBE_ACI_CAPS_PENDING_NVM_VER 0x0049
+#define IXGBE_ACI_CAPS_OROM_VER 0x004A
+#define IXGBE_ACI_CAPS_PENDING_OROM_VER 0x004B
+#define IXGBE_ACI_CAPS_PENDING_NET_VER 0x004D
+#define IXGBE_ACI_CAPS_INLINE_IPSEC 0x0070
+#define IXGBE_ACI_CAPS_NUM_ENABLED_PORTS 0x0072
+#define IXGBE_ACI_CAPS_PCIE_RESET_AVOIDANCE 0x0076
+#define IXGBE_ACI_CAPS_POST_UPDATE_RESET_RESTRICT 0x0077
+#define IXGBE_ACI_CAPS_NVM_MGMT 0x0080
+#define IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG0 0x0081
+#define IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG1 0x0082
+#define IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG2 0x0083
+#define IXGBE_ACI_CAPS_EXT_TOPO_DEV_IMG3 0x0084
+ u8 major_ver;
+ u8 minor_ver;
+ /* Number of resources described by this capability */
+ __le32 number;
+ /* Only meaningful for some types of resources */
+ __le32 logical_id;
+ /* Only meaningful for some types of resources */
+ __le32 phys_id;
+ __le64 rsvd1;
+ __le64 rsvd2;
+};
+
+/* Disable RXEN (direct 0x000C) */
+struct ixgbe_aci_cmd_disable_rxen {
+ u8 lport_num;
+ u8 reserved[15];
+};
+
+/* Get PHY capabilities (indirect 0x0600) */
+struct ixgbe_aci_cmd_get_phy_caps {
+ u8 lport_num;
+ u8 reserved;
+ __le16 param0;
+ /* 18.0 - Report qualified modules */
+#define IXGBE_ACI_GET_PHY_RQM BIT(0)
+ /* 18.1 - 18.3 : Report mode
+ * 000b - Report topology capabilities, without media
+ * 001b - Report topology capabilities, with media
+ * 010b - Report Active configuration
+ * 011b - Report PHY Type and FEC mode capabilities
+ * 100b - Report Default capabilities
+ */
+#define IXGBE_ACI_REPORT_MODE_M GENMASK(3, 1)
+#define IXGBE_ACI_REPORT_TOPO_CAP_NO_MEDIA 0
+#define IXGBE_ACI_REPORT_TOPO_CAP_MEDIA BIT(1)
+#define IXGBE_ACI_REPORT_ACTIVE_CFG BIT(2)
+#define IXGBE_ACI_REPORT_DFLT_CFG BIT(3)
+ __le32 reserved1;
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+/* This is #define of PHY type (Extended):
+ * The first set of defines is for phy_type_low.
+ */
+#define IXGBE_PHY_TYPE_LOW_100BASE_TX BIT_ULL(0)
+#define IXGBE_PHY_TYPE_LOW_100M_SGMII BIT_ULL(1)
+#define IXGBE_PHY_TYPE_LOW_1000BASE_T BIT_ULL(2)
+#define IXGBE_PHY_TYPE_LOW_1000BASE_SX BIT_ULL(3)
+#define IXGBE_PHY_TYPE_LOW_1000BASE_LX BIT_ULL(4)
+#define IXGBE_PHY_TYPE_LOW_1000BASE_KX BIT_ULL(5)
+#define IXGBE_PHY_TYPE_LOW_1G_SGMII BIT_ULL(6)
+#define IXGBE_PHY_TYPE_LOW_2500BASE_T BIT_ULL(7)
+#define IXGBE_PHY_TYPE_LOW_2500BASE_X BIT_ULL(8)
+#define IXGBE_PHY_TYPE_LOW_2500BASE_KX BIT_ULL(9)
+#define IXGBE_PHY_TYPE_LOW_5GBASE_T BIT_ULL(10)
+#define IXGBE_PHY_TYPE_LOW_5GBASE_KR BIT_ULL(11)
+#define IXGBE_PHY_TYPE_LOW_10GBASE_T BIT_ULL(12)
+#define IXGBE_PHY_TYPE_LOW_10G_SFI_DA BIT_ULL(13)
+#define IXGBE_PHY_TYPE_LOW_10GBASE_SR BIT_ULL(14)
+#define IXGBE_PHY_TYPE_LOW_10GBASE_LR BIT_ULL(15)
+#define IXGBE_PHY_TYPE_LOW_10GBASE_KR_CR1 BIT_ULL(16)
+#define IXGBE_PHY_TYPE_LOW_10G_SFI_AOC_ACC BIT_ULL(17)
+#define IXGBE_PHY_TYPE_LOW_10G_SFI_C2C BIT_ULL(18)
+#define IXGBE_PHY_TYPE_LOW_25GBASE_T BIT_ULL(19)
+#define IXGBE_PHY_TYPE_LOW_25GBASE_CR BIT_ULL(20)
+#define IXGBE_PHY_TYPE_LOW_25GBASE_CR_S BIT_ULL(21)
+#define IXGBE_PHY_TYPE_LOW_25GBASE_CR1 BIT_ULL(22)
+#define IXGBE_PHY_TYPE_LOW_25GBASE_SR BIT_ULL(23)
+#define IXGBE_PHY_TYPE_LOW_25GBASE_LR BIT_ULL(24)
+#define IXGBE_PHY_TYPE_LOW_25GBASE_KR BIT_ULL(25)
+#define IXGBE_PHY_TYPE_LOW_25GBASE_KR_S BIT_ULL(26)
+#define IXGBE_PHY_TYPE_LOW_25GBASE_KR1 BIT_ULL(27)
+#define IXGBE_PHY_TYPE_LOW_25G_AUI_AOC_ACC BIT_ULL(28)
+#define IXGBE_PHY_TYPE_LOW_25G_AUI_C2C BIT_ULL(29)
+#define IXGBE_PHY_TYPE_LOW_MAX_INDEX 29
+/* The second set of defines is for phy_type_high. */
+#define IXGBE_PHY_TYPE_HIGH_10BASE_T BIT_ULL(1)
+#define IXGBE_PHY_TYPE_HIGH_10M_SGMII BIT_ULL(2)
+#define IXGBE_PHY_TYPE_HIGH_2500M_SGMII BIT_ULL(56)
+#define IXGBE_PHY_TYPE_HIGH_100M_USXGMII BIT_ULL(57)
+#define IXGBE_PHY_TYPE_HIGH_1G_USXGMII BIT_ULL(58)
+#define IXGBE_PHY_TYPE_HIGH_2500M_USXGMII BIT_ULL(59)
+#define IXGBE_PHY_TYPE_HIGH_5G_USXGMII BIT_ULL(60)
+#define IXGBE_PHY_TYPE_HIGH_10G_USXGMII BIT_ULL(61)
+#define IXGBE_PHY_TYPE_HIGH_MAX_INDEX 61
+
+struct ixgbe_aci_cmd_get_phy_caps_data {
+ __le64 phy_type_low; /* Use values from IXGBE_PHY_TYPE_LOW_* */
+ __le64 phy_type_high; /* Use values from IXGBE_PHY_TYPE_HIGH_* */
+ u8 caps;
+#define IXGBE_ACI_PHY_EN_TX_LINK_PAUSE BIT(0)
+#define IXGBE_ACI_PHY_EN_RX_LINK_PAUSE BIT(1)
+#define IXGBE_ACI_PHY_LOW_POWER_MODE BIT(2)
+#define IXGBE_ACI_PHY_EN_LINK BIT(3)
+#define IXGBE_ACI_PHY_AN_MODE BIT(4)
+#define IXGBE_ACI_PHY_EN_MOD_QUAL BIT(5)
+#define IXGBE_ACI_PHY_EN_LESM BIT(6)
+#define IXGBE_ACI_PHY_EN_AUTO_FEC BIT(7)
+#define IXGBE_ACI_PHY_CAPS_MASK GENMASK(7, 0)
+ u8 low_power_ctrl_an;
+#define IXGBE_ACI_PHY_EN_D3COLD_LOW_POWER_AUTONEG BIT(0)
+#define IXGBE_ACI_PHY_AN_EN_CLAUSE28 BIT(1)
+#define IXGBE_ACI_PHY_AN_EN_CLAUSE73 BIT(2)
+#define IXGBE_ACI_PHY_AN_EN_CLAUSE37 BIT(3)
+ __le16 eee_cap;
+#define IXGBE_ACI_PHY_EEE_EN_100BASE_TX BIT(0)
+#define IXGBE_ACI_PHY_EEE_EN_1000BASE_T BIT(1)
+#define IXGBE_ACI_PHY_EEE_EN_10GBASE_T BIT(2)
+#define IXGBE_ACI_PHY_EEE_EN_1000BASE_KX BIT(3)
+#define IXGBE_ACI_PHY_EEE_EN_10GBASE_KR BIT(4)
+#define IXGBE_ACI_PHY_EEE_EN_25GBASE_KR BIT(5)
+#define IXGBE_ACI_PHY_EEE_EN_10BASE_T BIT(11)
+ __le16 eeer_value;
+ u8 phy_id_oui[4]; /* PHY/Module ID connected on the port */
+ u8 phy_fw_ver[8];
+ u8 link_fec_options;
+#define IXGBE_ACI_PHY_FEC_10G_KR_40G_KR4_EN BIT(0)
+#define IXGBE_ACI_PHY_FEC_10G_KR_40G_KR4_REQ BIT(1)
+#define IXGBE_ACI_PHY_FEC_25G_RS_528_REQ BIT(2)
+#define IXGBE_ACI_PHY_FEC_25G_KR_REQ BIT(3)
+#define IXGBE_ACI_PHY_FEC_25G_RS_544_REQ BIT(4)
+#define IXGBE_ACI_PHY_FEC_25G_RS_CLAUSE91_EN BIT(6)
+#define IXGBE_ACI_PHY_FEC_25G_KR_CLAUSE74_EN BIT(7)
+#define IXGBE_ACI_PHY_FEC_MASK 0xdf
+ u8 module_compliance_enforcement;
+#define IXGBE_ACI_MOD_ENFORCE_STRICT_MODE BIT(0)
+ u8 extended_compliance_code;
+#define IXGBE_ACI_MODULE_TYPE_TOTAL_BYTE 3
+ u8 module_type[IXGBE_ACI_MODULE_TYPE_TOTAL_BYTE];
+#define IXGBE_ACI_MOD_TYPE_BYTE0_SFP_PLUS 0xA0
+#define IXGBE_ACI_MOD_TYPE_BYTE0_QSFP_PLUS 0x80
+#define IXGBE_ACI_MOD_TYPE_IDENT 1
+#define IXGBE_ACI_MOD_TYPE_BYTE1_SFP_PLUS_CU_PASSIVE BIT(0)
+#define IXGBE_ACI_MOD_TYPE_BYTE1_SFP_PLUS_CU_ACTIVE BIT(1)
+#define IXGBE_ACI_MOD_TYPE_BYTE1_10G_BASE_SR BIT(4)
+#define IXGBE_ACI_MOD_TYPE_BYTE1_10G_BASE_LR BIT(5)
+#define IXGBE_ACI_MOD_TYPE_BYTE1_10G_BASE_LRM BIT(6)
+#define IXGBE_ACI_MOD_TYPE_BYTE1_10G_BASE_ER BIT(7)
+#define IXGBE_ACI_MOD_TYPE_BYTE2_SFP_PLUS 0xA0
+#define IXGBE_ACI_MOD_TYPE_BYTE2_QSFP_PLUS 0x86
+ u8 qualified_module_count;
+ u8 rsvd2[7]; /* Bytes 47:41 reserved */
+#define IXGBE_ACI_QUAL_MOD_COUNT_MAX 16
+ struct {
+ u8 v_oui[3];
+ u8 rsvd3;
+ u8 v_part[16];
+ __le32 v_rev;
+ __le64 rsvd4;
+ } qual_modules[IXGBE_ACI_QUAL_MOD_COUNT_MAX];
+};
+
+/* Set PHY capabilities (direct 0x0601)
+ * NOTE: This command must be followed by setup link and restart auto-neg
+ */
+struct ixgbe_aci_cmd_set_phy_cfg {
+ u8 lport_num;
+ u8 reserved[7];
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+/* Set PHY config command data structure */
+struct ixgbe_aci_cmd_set_phy_cfg_data {
+ __le64 phy_type_low; /* Use values from IXGBE_PHY_TYPE_LOW_* */
+ __le64 phy_type_high; /* Use values from IXGBE_PHY_TYPE_HIGH_* */
+ u8 caps;
+#define IXGBE_ACI_PHY_ENA_VALID_MASK 0xef
+#define IXGBE_ACI_PHY_ENA_TX_PAUSE_ABILITY BIT(0)
+#define IXGBE_ACI_PHY_ENA_RX_PAUSE_ABILITY BIT(1)
+#define IXGBE_ACI_PHY_ENA_LOW_POWER BIT(2)
+#define IXGBE_ACI_PHY_ENA_LINK BIT(3)
+#define IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT BIT(5)
+#define IXGBE_ACI_PHY_ENA_LESM BIT(6)
+#define IXGBE_ACI_PHY_ENA_AUTO_FEC BIT(7)
+ u8 low_power_ctrl_an;
+ __le16 eee_cap; /* Value from ixgbe_aci_get_phy_caps */
+ __le16 eeer_value; /* Use defines from ixgbe_aci_get_phy_caps */
+ u8 link_fec_opt; /* Use defines from ixgbe_aci_get_phy_caps */
+ u8 module_compliance_enforcement;
+};
+
+/* Restart AN command data structure (direct 0x0605)
+ * Also used for response, with only the lport_num field present.
+ */
+struct ixgbe_aci_cmd_restart_an {
+ u8 lport_num;
+ u8 reserved;
+ u8 cmd_flags;
+#define IXGBE_ACI_RESTART_AN_LINK_RESTART BIT(1)
+#define IXGBE_ACI_RESTART_AN_LINK_ENABLE BIT(2)
+ u8 reserved2[13];
+};
+
+/* Get link status (indirect 0x0607), also used for Link Status Event */
+struct ixgbe_aci_cmd_get_link_status {
+ u8 lport_num;
+ u8 reserved;
+ __le16 cmd_flags;
+#define IXGBE_ACI_LSE_M GENMASK(1, 0)
+#define IXGBE_ACI_LSE_NOP 0x0
+#define IXGBE_ACI_LSE_DIS 0x2
+#define IXGBE_ACI_LSE_ENA 0x3
+ /* only response uses this flag */
+#define IXGBE_ACI_LSE_IS_ENABLED 0x1
+ __le32 reserved2;
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+/* Get link status response data structure, also used for Link Status Event */
+struct ixgbe_aci_cmd_get_link_status_data {
+ u8 topo_media_conflict;
+#define IXGBE_ACI_LINK_TOPO_CONFLICT BIT(0)
+#define IXGBE_ACI_LINK_MEDIA_CONFLICT BIT(1)
+#define IXGBE_ACI_LINK_TOPO_CORRUPT BIT(2)
+#define IXGBE_ACI_LINK_TOPO_UNREACH_PRT BIT(4)
+#define IXGBE_ACI_LINK_TOPO_UNDRUTIL_PRT BIT(5)
+#define IXGBE_ACI_LINK_TOPO_UNDRUTIL_MEDIA BIT(6)
+#define IXGBE_ACI_LINK_TOPO_UNSUPP_MEDIA BIT(7)
+ u8 link_cfg_err;
+#define IXGBE_ACI_LINK_CFG_ERR BIT(0)
+#define IXGBE_ACI_LINK_CFG_COMPLETED BIT(1)
+#define IXGBE_ACI_LINK_ACT_PORT_OPT_INVAL BIT(2)
+#define IXGBE_ACI_LINK_FEAT_ID_OR_CONFIG_ID_INVAL BIT(3)
+#define IXGBE_ACI_LINK_TOPO_CRITICAL_SDP_ERR BIT(4)
+#define IXGBE_ACI_LINK_MODULE_POWER_UNSUPPORTED BIT(5)
+#define IXGBE_ACI_LINK_EXTERNAL_PHY_LOAD_FAILURE BIT(6)
+#define IXGBE_ACI_LINK_INVAL_MAX_POWER_LIMIT BIT(7)
+ u8 link_info;
+#define IXGBE_ACI_LINK_UP BIT(0) /* Link Status */
+#define IXGBE_ACI_LINK_FAULT BIT(1)
+#define IXGBE_ACI_LINK_FAULT_TX BIT(2)
+#define IXGBE_ACI_LINK_FAULT_RX BIT(3)
+#define IXGBE_ACI_LINK_FAULT_REMOTE BIT(4)
+#define IXGBE_ACI_LINK_UP_PORT BIT(5) /* External Port Link Status */
+#define IXGBE_ACI_MEDIA_AVAILABLE BIT(6)
+#define IXGBE_ACI_SIGNAL_DETECT BIT(7)
+ u8 an_info;
+#define IXGBE_ACI_AN_COMPLETED BIT(0)
+#define IXGBE_ACI_LP_AN_ABILITY BIT(1)
+#define IXGBE_ACI_PD_FAULT BIT(2) /* Parallel Detection Fault */
+#define IXGBE_ACI_FEC_EN BIT(3)
+#define IXGBE_ACI_PHY_LOW_POWER BIT(4) /* Low Power State */
+#define IXGBE_ACI_LINK_PAUSE_TX BIT(5)
+#define IXGBE_ACI_LINK_PAUSE_RX BIT(6)
+#define IXGBE_ACI_QUALIFIED_MODULE BIT(7)
+ u8 ext_info;
+#define IXGBE_ACI_LINK_PHY_TEMP_ALARM BIT(0)
+#define IXGBE_ACI_LINK_EXCESSIVE_ERRORS BIT(1) /* Excessive Link Errors */
+ /* Port Tx Suspended */
+#define IXGBE_ACI_LINK_TX_ACTIVE 0
+#define IXGBE_ACI_LINK_TX_DRAINED 1
+#define IXGBE_ACI_LINK_TX_FLUSHED 3
+ u8 lb_status;
+#define IXGBE_ACI_LINK_LB_PHY_LCL BIT(0)
+#define IXGBE_ACI_LINK_LB_PHY_RMT BIT(1)
+#define IXGBE_ACI_LINK_LB_MAC_LCL BIT(2)
+ __le16 max_frame_size;
+ u8 cfg;
+#define IXGBE_ACI_LINK_25G_KR_FEC_EN BIT(0)
+#define IXGBE_ACI_LINK_25G_RS_528_FEC_EN BIT(1)
+#define IXGBE_ACI_LINK_25G_RS_544_FEC_EN BIT(2)
+#define IXGBE_ACI_FEC_MASK GENMASK(2, 0)
+ /* Pacing Config */
+#define IXGBE_ACI_CFG_PACING_M GENMASK(6, 3)
+#define IXGBE_ACI_CFG_PACING_TYPE_M BIT(7)
+#define IXGBE_ACI_CFG_PACING_TYPE_AVG 0
+#define IXGBE_ACI_CFG_PACING_TYPE_FIXED IXGBE_ACI_CFG_PACING_TYPE_M
+ /* External Device Power Ability */
+ u8 power_desc;
+#define IXGBE_ACI_PWR_CLASS_M GENMASK(5, 0)
+#define IXGBE_ACI_LINK_PWR_BASET_LOW_HIGH 0
+#define IXGBE_ACI_LINK_PWR_BASET_HIGH 1
+#define IXGBE_ACI_LINK_PWR_QSFP_CLASS_1 0
+#define IXGBE_ACI_LINK_PWR_QSFP_CLASS_2 1
+#define IXGBE_ACI_LINK_PWR_QSFP_CLASS_3 2
+#define IXGBE_ACI_LINK_PWR_QSFP_CLASS_4 3
+ __le16 link_speed;
+#define IXGBE_ACI_LINK_SPEED_M GENMASK(10, 0)
+#define IXGBE_ACI_LINK_SPEED_10MB BIT(0)
+#define IXGBE_ACI_LINK_SPEED_100MB BIT(1)
+#define IXGBE_ACI_LINK_SPEED_1000MB BIT(2)
+#define IXGBE_ACI_LINK_SPEED_2500MB BIT(3)
+#define IXGBE_ACI_LINK_SPEED_5GB BIT(4)
+#define IXGBE_ACI_LINK_SPEED_10GB BIT(5)
+#define IXGBE_ACI_LINK_SPEED_20GB BIT(6)
+#define IXGBE_ACI_LINK_SPEED_25GB BIT(7)
+#define IXGBE_ACI_LINK_SPEED_40GB BIT(8)
+#define IXGBE_ACI_LINK_SPEED_50GB BIT(9)
+#define IXGBE_ACI_LINK_SPEED_100GB BIT(10)
+#define IXGBE_ACI_LINK_SPEED_200GB BIT(11)
+#define IXGBE_ACI_LINK_SPEED_UNKNOWN BIT(15)
+ __le16 reserved3;
+ u8 ext_fec_status;
+#define IXGBE_ACI_LINK_RS_272_FEC_EN BIT(0) /* RS 272 FEC enabled */
+ u8 reserved4;
+ __le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
+ __le64 phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */
+ /* Get link status version 2 link partner data */
+ __le64 lp_phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */
+ __le64 lp_phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */
+ u8 lp_fec_adv;
+#define IXGBE_ACI_LINK_LP_10G_KR_FEC_CAP BIT(0)
+#define IXGBE_ACI_LINK_LP_25G_KR_FEC_CAP BIT(1)
+#define IXGBE_ACI_LINK_LP_RS_528_FEC_CAP BIT(2)
+#define IXGBE_ACI_LINK_LP_50G_KR_272_FEC_CAP BIT(3)
+#define IXGBE_ACI_LINK_LP_100G_KR_272_FEC_CAP BIT(4)
+#define IXGBE_ACI_LINK_LP_200G_KR_272_FEC_CAP BIT(5)
+ u8 lp_fec_req;
+#define IXGBE_ACI_LINK_LP_10G_KR_FEC_REQ BIT(0)
+#define IXGBE_ACI_LINK_LP_25G_KR_FEC_REQ BIT(1)
+#define IXGBE_ACI_LINK_LP_RS_528_FEC_REQ BIT(2)
+#define IXGBE_ACI_LINK_LP_KR_272_FEC_REQ BIT(3)
+ u8 lp_flowcontrol;
+#define IXGBE_ACI_LINK_LP_PAUSE_ADV BIT(0)
+#define IXGBE_ACI_LINK_LP_ASM_DIR_ADV BIT(1)
+ u8 reserved5[5];
+} __packed;
+
+/* Set event mask command (direct 0x0613) */
+struct ixgbe_aci_cmd_set_event_mask {
+ u8 lport_num;
+ u8 reserved[7];
+ __le16 event_mask;
+#define IXGBE_ACI_LINK_EVENT_UPDOWN BIT(1)
+#define IXGBE_ACI_LINK_EVENT_MEDIA_NA BIT(2)
+#define IXGBE_ACI_LINK_EVENT_LINK_FAULT BIT(3)
+#define IXGBE_ACI_LINK_EVENT_PHY_TEMP_ALARM BIT(4)
+#define IXGBE_ACI_LINK_EVENT_EXCESSIVE_ERRORS BIT(5)
+#define IXGBE_ACI_LINK_EVENT_SIGNAL_DETECT BIT(6)
+#define IXGBE_ACI_LINK_EVENT_AN_COMPLETED BIT(7)
+#define IXGBE_ACI_LINK_EVENT_MODULE_QUAL_FAIL BIT(8)
+#define IXGBE_ACI_LINK_EVENT_PORT_TX_SUSPENDED BIT(9)
+#define IXGBE_ACI_LINK_EVENT_TOPO_CONFLICT BIT(10)
+#define IXGBE_ACI_LINK_EVENT_MEDIA_CONFLICT BIT(11)
+#define IXGBE_ACI_LINK_EVENT_PHY_FW_LOAD_FAIL BIT(12)
+ u8 reserved1[6];
+};
+
+struct ixgbe_aci_cmd_link_topo_params {
+ u8 lport_num;
+ u8 lport_num_valid;
+#define IXGBE_ACI_LINK_TOPO_PORT_NUM_VALID BIT(0)
+ u8 node_type_ctx;
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_M GENMASK(3, 0)
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_PHY 0
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_GPIO_CTRL 1
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_MUX_CTRL 2
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_LED_CTRL 3
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_LED 4
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_THERMAL 5
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_CAGE 6
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_MEZZ 7
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_ID_EEPROM 8
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_CLK_CTRL 9
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_CLK_MUX 10
+#define IXGBE_ACI_LINK_TOPO_NODE_TYPE_GPS 11
+#define IXGBE_ACI_LINK_TOPO_NODE_CTX_S 4
+#define IXGBE_ACI_LINK_TOPO_NODE_CTX_M GENMASK(7, 4)
+#define IXGBE_ACI_LINK_TOPO_NODE_CTX_GLOBAL 0
+#define IXGBE_ACI_LINK_TOPO_NODE_CTX_BOARD 1
+#define IXGBE_ACI_LINK_TOPO_NODE_CTX_PORT 2
+#define IXGBE_ACI_LINK_TOPO_NODE_CTX_NODE 3
+#define IXGBE_ACI_LINK_TOPO_NODE_CTX_NODE_HANDLE 4
+#define IXGBE_ACI_LINK_TOPO_NODE_CTX_DIRECT_BUS_ACCESS 5
+#define IXGBE_ACI_LINK_TOPO_NODE_CTX_NODE_HANDLE_BUS_ADDRESS 6
+ u8 index;
+};
+
+struct ixgbe_aci_cmd_link_topo_addr {
+ struct ixgbe_aci_cmd_link_topo_params topo_params;
+ __le16 handle;
+/* Used to decode the handle field */
+#define IXGBE_ACI_LINK_TOPO_HANDLE_BRD_TYPE_M BIT(9)
+#define IXGBE_ACI_LINK_TOPO_HANDLE_BRD_TYPE_LOM BIT(9)
+#define IXGBE_ACI_LINK_TOPO_HANDLE_BRD_TYPE_MEZZ 0
+};
+
+/* Get Link Topology Handle (direct, 0x06E0) */
+struct ixgbe_aci_cmd_get_link_topo {
+ struct ixgbe_aci_cmd_link_topo_addr addr;
+ u8 node_part_num;
+#define IXGBE_ACI_GET_LINK_TOPO_NODE_NR_PCA9575 0x21
+#define IXGBE_ACI_GET_LINK_TOPO_NODE_NR_ZL30632_80032 0x24
+#define IXGBE_ACI_GET_LINK_TOPO_NODE_NR_SI5384 0x25
+#define IXGBE_ACI_GET_LINK_TOPO_NODE_NR_C827 0x31
+#define IXGBE_ACI_GET_LINK_TOPO_NODE_NR_GEN_CLK_MUX 0x47
+#define IXGBE_ACI_GET_LINK_TOPO_NODE_NR_GEN_GPS 0x48
+#define IXGBE_ACI_GET_LINK_TOPO_NODE_NR_E610_PTC 0x49
+ u8 rsvd[9];
+};
+
+/* Get Link Topology Pin (direct, 0x06E1) */
+struct ixgbe_aci_cmd_get_link_topo_pin {
+ struct ixgbe_aci_cmd_link_topo_addr addr;
+ u8 input_io_params;
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_GPIO 0
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_RESET_N 1
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_INT_N 2
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_PRESENT_N 3
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_TX_DIS 4
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_MODSEL_N 5
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_LPMODE 6
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_TX_FAULT 7
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_RX_LOSS 8
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_RS0 9
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_RS1 10
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_EEPROM_WP 11
+/* 12 repeats intentionally due to two different uses depending on context */
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_LED 12
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_RED_LED 12
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_GREEN_LED 13
+#define IXGBE_ACI_LINK_TOPO_IO_FUNC_BLUE_LED 14
+#define IXGBE_ACI_LINK_TOPO_INPUT_IO_TYPE_GPIO 3
+/* Use IXGBE_ACI_LINK_TOPO_NODE_TYPE_* for the type values */
+ u8 output_io_params;
+/* Use IXGBE_ACI_LINK_TOPO_NODE_TYPE_* for the type values */
+ u8 output_io_flags;
+#define IXGBE_ACI_LINK_TOPO_OUTPUT_POLARITY BIT(5)
+#define IXGBE_ACI_LINK_TOPO_OUTPUT_VALUE BIT(6)
+#define IXGBE_ACI_LINK_TOPO_OUTPUT_DRIVEN BIT(7)
+ u8 rsvd[7];
+};
+
+/* Read/Write SFF EEPROM command (indirect 0x06EE) */
+struct ixgbe_aci_cmd_sff_eeprom {
+ u8 lport_num;
+ u8 lport_num_valid;
+#define IXGBE_ACI_SFF_PORT_NUM_VALID BIT(0)
+ __le16 i2c_bus_addr;
+#define IXGBE_ACI_SFF_I2CBUS_7BIT_M GENMASK(6, 0)
+#define IXGBE_ACI_SFF_I2CBUS_10BIT_M GENMASK(9, 0)
+#define IXGBE_ACI_SFF_I2CBUS_TYPE_M BIT(10)
+#define IXGBE_ACI_SFF_I2CBUS_TYPE_7BIT 0
+#define IXGBE_ACI_SFF_I2CBUS_TYPE_10BIT IXGBE_ACI_SFF_I2CBUS_TYPE_M
+#define IXGBE_ACI_SFF_NO_PAGE_BANK_UPDATE 0
+#define IXGBE_ACI_SFF_UPDATE_PAGE 1
+#define IXGBE_ACI_SFF_UPDATE_BANK 2
+#define IXGBE_ACI_SFF_UPDATE_PAGE_BANK 3
+#define IXGBE_ACI_SFF_IS_WRITE BIT(15)
+ __le16 i2c_offset;
+ u8 module_bank;
+ u8 module_page;
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+/* NVM Read command (indirect 0x0701)
+ * NVM Erase commands (direct 0x0702)
+ * NVM Write commands (indirect 0x0703)
+ * NVM Write Activate commands (direct 0x0707)
+ * NVM Shadow RAM Dump commands (direct 0x0707)
+ */
+struct ixgbe_aci_cmd_nvm {
+#define IXGBE_ACI_NVM_MAX_OFFSET 0xFFFFFF
+ __le16 offset_low;
+ u8 offset_high; /* For Write Activate offset_high is used as flags2 */
+ u8 cmd_flags;
+#define IXGBE_ACI_NVM_LAST_CMD BIT(0)
+#define IXGBE_ACI_NVM_PCIR_REQ BIT(0) /* Used by NVM Write reply */
+#define IXGBE_ACI_NVM_PRESERVE_ALL BIT(1)
+#define IXGBE_ACI_NVM_ACTIV_SEL_NVM BIT(3) /* Write Activate/SR Dump only */
+#define IXGBE_ACI_NVM_ACTIV_SEL_OROM BIT(4)
+#define IXGBE_ACI_NVM_ACTIV_SEL_NETLIST BIT(5)
+#define IXGBE_ACI_NVM_SPECIAL_UPDATE BIT(6)
+#define IXGBE_ACI_NVM_REVERT_LAST_ACTIV BIT(6) /* Write Activate only */
+#define IXGBE_ACI_NVM_FLASH_ONLY BIT(7)
+#define IXGBE_ACI_NVM_RESET_LVL_M GENMASK(1, 0) /* Write reply only */
+#define IXGBE_ACI_NVM_POR_FLAG 0
+#define IXGBE_ACI_NVM_PERST_FLAG 1
+#define IXGBE_ACI_NVM_EMPR_FLAG 2
+#define IXGBE_ACI_NVM_EMPR_ENA BIT(0) /* Write Activate reply only */
+ /* For Write Activate, several flags are sent as part of a separate
+ * flags2 field using a separate byte. For simplicity of the software
+ * interface, we pass the flags as a 16 bit value so these flags are
+ * all offset by 8 bits
+ */
+#define IXGBE_ACI_NVM_ACTIV_REQ_EMPR BIT(8) /* NVM Write Activate only */
+ __le16 module_typeid;
+ __le16 length;
+#define IXGBE_ACI_NVM_ERASE_LEN 0xFFFF
+ __le32 addr_high;
+ __le32 addr_low;
+};
+
+/* NVM Module_Type ID, needed offset and read_len for
+ * struct ixgbe_aci_cmd_nvm.
+ */
+#define IXGBE_ACI_NVM_START_POINT 0
+
+/* NVM Checksum Command (direct, 0x0706) */
+struct ixgbe_aci_cmd_nvm_checksum {
+ u8 flags;
+#define IXGBE_ACI_NVM_CHECKSUM_VERIFY BIT(0)
+#define IXGBE_ACI_NVM_CHECKSUM_RECALC BIT(1)
+ u8 rsvd;
+ __le16 checksum; /* Used only by response */
+#define IXGBE_ACI_NVM_CHECKSUM_CORRECT 0xBABA
+ u8 rsvd2[12];
+};
+
+/**
+ * struct ixgbe_aci_desc - Admin Command (AC) descriptor
+ * @flags: IXGBE_ACI_FLAG_* flags
+ * @opcode: Admin command opcode
+ * @datalen: length in bytes of indirect/external data buffer
+ * @retval: return value from firmware
+ * @cookie_high: opaque data high-half
+ * @cookie_low: opaque data low-half
+ * @params: command-specific parameters
+ *
+ * Descriptor format for commands the driver posts via the
+ * Admin Command Interface (ACI).
+ * The firmware writes back onto the command descriptor and returns
+ * the result of the command. Asynchronous events that are not an immediate
+ * result of the command are written to the Admin Command Interface (ACI) using
+ * the same descriptor format. Descriptors are in little-endian notation with
+ * 32-bit words.
+ */
+struct ixgbe_aci_desc {
+ __le16 flags;
+ __le16 opcode;
+ __le16 datalen;
+ __le16 retval;
+ __le32 cookie_high;
+ __le32 cookie_low;
+ union {
+ u8 raw[16];
+ struct ixgbe_aci_cmd_get_ver get_ver;
+ struct ixgbe_aci_cmd_driver_ver driver_ver;
+ struct ixgbe_aci_cmd_get_exp_err exp_err;
+ struct ixgbe_aci_cmd_req_res res_owner;
+ struct ixgbe_aci_cmd_list_caps get_cap;
+ struct ixgbe_aci_cmd_disable_rxen disable_rxen;
+ struct ixgbe_aci_cmd_get_phy_caps get_phy;
+ struct ixgbe_aci_cmd_set_phy_cfg set_phy;
+ struct ixgbe_aci_cmd_restart_an restart_an;
+ struct ixgbe_aci_cmd_get_link_status get_link_status;
+ struct ixgbe_aci_cmd_set_event_mask set_event_mask;
+ struct ixgbe_aci_cmd_get_link_topo get_link_topo;
+ struct ixgbe_aci_cmd_get_link_topo_pin get_link_topo_pin;
+ struct ixgbe_aci_cmd_sff_eeprom read_write_sff_param;
+ struct ixgbe_aci_cmd_nvm nvm;
+ struct ixgbe_aci_cmd_nvm_checksum nvm_checksum;
+ } params;
+};
+
+/* E610-specific adapter context structures */
+
+struct ixgbe_link_status {
+ /* Refer to ixgbe_aci_phy_type for bits definition */
+ u64 phy_type_low;
+ u64 phy_type_high;
+ u16 max_frame_size;
+ u16 link_speed;
+ u16 req_speeds;
+ u8 topo_media_conflict;
+ u8 link_cfg_err;
+ u8 lse_ena; /* Link Status Event notification */
+ u8 link_info;
+ u8 an_info;
+ u8 ext_info;
+ u8 fec_info;
+ u8 pacing;
+ /* Refer to #define from module_type[IXGBE_ACI_MODULE_TYPE_TOTAL_BYTE]
+ * of ixgbe_aci_get_phy_caps structure
+ */
+ u8 module_type[IXGBE_ACI_MODULE_TYPE_TOTAL_BYTE];
+};
+
+/* Common HW capabilities for SW use */
+struct ixgbe_hw_caps {
+ /* Write CSR protection */
+ u64 wr_csr_prot;
+ u32 switching_mode;
+ /* switching mode supported - EVB switching (including cloud) */
+#define IXGBE_NVM_IMAGE_TYPE_EVB 0x0
+
+ /* Manageability mode & supported protocols over MCTP */
+ u32 mgmt_mode;
+#define IXGBE_MGMT_MODE_PASS_THRU_MODE_M GENMASK(3, 0)
+#define IXGBE_MGMT_MODE_CTL_INTERFACE_M GENMASK(7, 4)
+#define IXGBE_MGMT_MODE_REDIR_SB_INTERFACE_M GENMASK(11, 8)
+
+ u32 mgmt_protocols_mctp;
+#define IXGBE_MGMT_MODE_PROTO_RSVD BIT(0)
+#define IXGBE_MGMT_MODE_PROTO_PLDM BIT(1)
+#define IXGBE_MGMT_MODE_PROTO_OEM BIT(2)
+#define IXGBE_MGMT_MODE_PROTO_NC_SI BIT(3)
+
+ u32 os2bmc;
+ u32 valid_functions;
+ /* DCB capabilities */
+ u32 active_tc_bitmap;
+ u32 maxtc;
+
+ /* RSS related capabilities */
+ u32 rss_table_size; /* 512 for PFs and 64 for VFs */
+ u32 rss_table_entry_width; /* RSS Entry width in bits */
+
+ /* Tx/Rx queues */
+ u32 num_rxq; /* Number/Total Rx queues */
+ u32 rxq_first_id; /* First queue ID for Rx queues */
+ u32 num_txq; /* Number/Total Tx queues */
+ u32 txq_first_id; /* First queue ID for Tx queues */
+
+ /* MSI-X vectors */
+ u32 num_msix_vectors;
+ u32 msix_vector_first_id;
+
+ /* Max MTU for function or device */
+ u32 max_mtu;
+
+ /* WOL related */
+ u32 num_wol_proxy_fltr;
+ u32 wol_proxy_vsi_seid;
+
+ /* LED/SDP pin count */
+ u32 led_pin_num;
+ u32 sdp_pin_num;
+
+ /* LED/SDP - Supports up to 12 LED pins and 8 SDP signals */
+#define IXGBE_MAX_SUPPORTED_GPIO_LED 12
+#define IXGBE_MAX_SUPPORTED_GPIO_SDP 8
+ u8 led[IXGBE_MAX_SUPPORTED_GPIO_LED];
+ u8 sdp[IXGBE_MAX_SUPPORTED_GPIO_SDP];
+ /* SR-IOV virtualization */
+ u8 sr_iov_1_1; /* SR-IOV enabled */
+ /* VMDQ */
+ u8 vmdq; /* VMDQ supported */
+
+ /* EVB capabilities */
+ u8 evb_802_1_qbg; /* Edge Virtual Bridging */
+ u8 evb_802_1_qbh; /* Bridge Port Extension */
+
+ u8 dcb;
+ u8 iscsi;
+ u8 ieee_1588;
+ u8 mgmt_cem;
+
+ /* WoL and APM support */
+#define IXGBE_WOL_SUPPORT_M BIT(0)
+#define IXGBE_ACPI_PROG_MTHD_M BIT(1)
+#define IXGBE_PROXY_SUPPORT_M BIT(2)
+ u8 apm_wol_support;
+ u8 acpi_prog_mthd;
+ u8 proxy_support;
+ bool nvm_update_pending_nvm;
+ bool nvm_update_pending_orom;
+ bool nvm_update_pending_netlist;
+#define IXGBE_NVM_PENDING_NVM_IMAGE BIT(0)
+#define IXGBE_NVM_PENDING_OROM BIT(1)
+#define IXGBE_NVM_PENDING_NETLIST BIT(2)
+ bool sec_rev_disabled;
+ bool update_disabled;
+ bool nvm_unified_update;
+ bool netlist_auth;
+#define IXGBE_NVM_MGMT_SEC_REV_DISABLED BIT(0)
+#define IXGBE_NVM_MGMT_UPDATE_DISABLED BIT(1)
+#define IXGBE_NVM_MGMT_UNIFIED_UPD_SUPPORT BIT(3)
+#define IXGBE_NVM_MGMT_NETLIST_AUTH_SUPPORT BIT(5)
+ bool no_drop_policy_support;
+ /* PCIe reset avoidance */
+ bool pcie_reset_avoidance; /* false: not supported, true: supported */
+ /* Post update reset restriction */
+ bool reset_restrict_support; /* false: not supported, true: supported */
+
+ /* External topology device images within the NVM */
+#define IXGBE_EXT_TOPO_DEV_IMG_COUNT 4
+ u32 ext_topo_dev_img_ver_high[IXGBE_EXT_TOPO_DEV_IMG_COUNT];
+ u32 ext_topo_dev_img_ver_low[IXGBE_EXT_TOPO_DEV_IMG_COUNT];
+ u8 ext_topo_dev_img_part_num[IXGBE_EXT_TOPO_DEV_IMG_COUNT];
+#define IXGBE_EXT_TOPO_DEV_IMG_PART_NUM_S 8
+#define IXGBE_EXT_TOPO_DEV_IMG_PART_NUM_M GENMASK(15, 8)
+ bool ext_topo_dev_img_load_en[IXGBE_EXT_TOPO_DEV_IMG_COUNT];
+#define IXGBE_EXT_TOPO_DEV_IMG_LOAD_EN BIT(0)
+ bool ext_topo_dev_img_prog_en[IXGBE_EXT_TOPO_DEV_IMG_COUNT];
+#define IXGBE_EXT_TOPO_DEV_IMG_PROG_EN BIT(1)
+} __packed;
+
+/* Function specific capabilities */
+struct ixgbe_hw_func_caps {
+ u32 num_allocd_vfs; /* Number of allocated VFs */
+ u32 vf_base_id; /* Logical ID of the first VF */
+ u32 guar_num_vsi;
+ struct ixgbe_hw_caps common_cap;
+ bool no_drop_policy_ena;
+};
+
+/* Device wide capabilities */
+struct ixgbe_hw_dev_caps {
+ struct ixgbe_hw_caps common_cap;
+ u32 num_vfs_exposed; /* Total number of VFs exposed */
+ u32 num_vsi_allocd_to_host; /* Excluding EMP VSI */
+ u32 num_flow_director_fltr; /* Number of FD filters available */
+ u32 num_funcs;
+};
+
+/* ACI event information */
+struct ixgbe_aci_event {
+ struct ixgbe_aci_desc desc;
+ u8 *msg_buf;
+ u16 msg_len;
+ u16 buf_len;
+};
+
+struct ixgbe_aci_info {
+ struct mutex lock; /* admin command interface lock */
+ enum ixgbe_aci_err last_status; /* last status of sent admin command */
+};
+
+/* Option ROM version information */
+struct ixgbe_orom_info {
+ u8 major; /* Major version of OROM */
+ u8 patch; /* Patch version of OROM */
+ u16 build; /* Build version of OROM */
+ u32 srev; /* Security revision */
+};
+
+/* NVM version information */
+struct ixgbe_nvm_info {
+ u32 eetrack;
+ u32 srev;
+ u8 major;
+ u8 minor;
+} __packed;
+
+/* netlist version information */
+struct ixgbe_netlist_info {
+ u32 major; /* major high/low */
+ u32 minor; /* minor high/low */
+ u32 type; /* type high/low */
+ u32 rev; /* revision high/low */
+ u32 hash; /* SHA-1 hash word */
+ u16 cust_ver; /* customer version */
+} __packed;
+
+/* Enumeration of possible flash banks for the NVM, OROM, and Netlist modules
+ * of the flash image.
+ */
+enum ixgbe_flash_bank {
+ IXGBE_INVALID_FLASH_BANK,
+ IXGBE_1ST_FLASH_BANK,
+ IXGBE_2ND_FLASH_BANK,
+};
+
+/* information for accessing NVM, OROM, and Netlist flash banks */
+struct ixgbe_bank_info {
+ u32 nvm_ptr; /* Pointer to 1st NVM bank */
+ u32 nvm_size; /* Size of NVM bank */
+ u32 orom_ptr; /* Pointer to 1st OROM bank */
+ u32 orom_size; /* Size of OROM bank */
+ u32 netlist_ptr; /* Ptr to 1st Netlist bank */
+ u32 netlist_size; /* Size of Netlist bank */
+ enum ixgbe_flash_bank nvm_bank; /* Active NVM bank */
+ enum ixgbe_flash_bank orom_bank; /* Active OROM bank */
+ enum ixgbe_flash_bank netlist_bank; /* Active Netlist bank */
+};
+
+/* Flash Chip Information */
+struct ixgbe_flash_info {
+ struct ixgbe_orom_info orom; /* Option ROM version info */
+ u32 flash_size; /* Available flash size in bytes */
+ struct ixgbe_nvm_info nvm; /* NVM version information */
+ struct ixgbe_netlist_info netlist; /* Netlist version info */
+ struct ixgbe_bank_info banks; /* Flash Bank information */
+ u16 sr_words; /* Shadow RAM size in words */
+ u8 blank_nvm_mode; /* is NVM empty (no FW present) */
+};
+
+#endif /* _IXGBE_TYPE_E610_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
index 81e1df83f136..1fc821fb351a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#include <linux/pci.h>
#include <linux/delay.h>
@@ -66,7 +66,9 @@ int ixgbe_setup_mac_link_X540(struct ixgbe_hw *hw, ixgbe_link_speed speed,
* Resets the hardware by resetting the transmit and receive units, masks
* and clears all interrupts, perform a PHY reset, and perform a link (MAC)
* reset.
- **/
+ *
+ * Return: 0 on success or negative value on failure
+ */
int ixgbe_reset_hw_X540(struct ixgbe_hw *hw)
{
u32 swfw_mask = hw->phy.phy_semaphore_mask;
@@ -133,10 +135,14 @@ mac_reset_top:
hw->mac.num_rar_entries = IXGBE_X540_MAX_TX_QUEUES;
hw->mac.ops.init_rx_addrs(hw);
+ /* The following is not supported by E610. */
+ if (hw->mac.type == ixgbe_mac_e610)
+ return status;
+
/* Store the permanent SAN mac address */
hw->mac.ops.get_san_mac_addr(hw, hw->mac.san_addr);
- /* Add the SAN MAC address to the RAR only if it's a valid address */
+ /* Add the SAN MAC address to RAR if it's a valid address */
if (is_valid_ether_addr(hw->mac.san_addr)) {
/* Save the SAN MAC RAR index */
hw->mac.san_mac_rar_index = hw->mac.num_rar_entries - 1;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h
index b69a680d3ab5..6ed360c5b605 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x540.h
@@ -1,5 +1,8 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
+
+#ifndef _IXGBE_X540_H_
+#define _IXGBE_X540_H_
#include "ixgbe_type.h"
@@ -17,3 +20,5 @@ int ixgbe_acquire_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask);
void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u32 mask);
void ixgbe_init_swfw_sync_X540(struct ixgbe_hw *hw);
int ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw);
+
+#endif /* _IXGBE_X540_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
index d9a8cf018d3b..277ceaf8a793 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c
@@ -1,7 +1,8 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#include "ixgbe_x540.h"
+#include "ixgbe_x550.h"
#include "ixgbe_type.h"
#include "ixgbe_common.h"
#include "ixgbe_mbx.h"
@@ -2770,9 +2771,9 @@ static int ixgbe_led_off_t_x550em(struct ixgbe_hw *hw, u32 led_idx)
* semaphore, -EIO when command fails or -ENIVAL when incorrect
* params passed.
**/
-static int ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
- u8 build, u8 sub, u16 len,
- const char *driver_ver)
+int ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
+ u8 build, u8 sub, u16 len,
+ const char *driver_ver)
{
struct ixgbe_hic_drv_info2 fw_cmd;
int ret_val;
@@ -3505,14 +3506,14 @@ mac_reset_top:
return status;
}
-/** ixgbe_set_ethertype_anti_spoofing_X550 - Enable/Disable Ethertype
+/** ixgbe_set_ethertype_anti_spoofing_x550 - Enable/Disable Ethertype
* anti-spoofing
* @hw: pointer to hardware structure
* @enable: enable or disable switch for Ethertype anti-spoofing
* @vf: Virtual Function pool - VF Pool to set for Ethertype anti-spoofing
**/
-static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
- bool enable, int vf)
+void ixgbe_set_ethertype_anti_spoofing_x550(struct ixgbe_hw *hw,
+ bool enable, int vf)
{
int vf_target_reg = vf >> 3;
int vf_target_shift = vf % 8 + IXGBE_SPOOF_ETHERTYPEAS_SHIFT;
@@ -3527,14 +3528,14 @@ static void ixgbe_set_ethertype_anti_spoofing_X550(struct ixgbe_hw *hw,
IXGBE_WRITE_REG(hw, IXGBE_PFVFSPOOF(vf_target_reg), pfvfspoof);
}
-/** ixgbe_set_source_address_pruning_X550 - Enable/Disbale src address pruning
+/** ixgbe_set_source_address_pruning_x550 - Enable/Disable src address pruning
* @hw: pointer to hardware structure
* @enable: enable or disable source address pruning
* @pool: Rx pool to set source address pruning for
**/
-static void ixgbe_set_source_address_pruning_X550(struct ixgbe_hw *hw,
- bool enable,
- unsigned int pool)
+void ixgbe_set_source_address_pruning_x550(struct ixgbe_hw *hw,
+ bool enable,
+ unsigned int pool)
{
u64 pfflp;
@@ -3831,9 +3832,9 @@ static int ixgbe_write_phy_reg_x550a(struct ixgbe_hw *hw, u32 reg_addr,
.set_mac_anti_spoofing = &ixgbe_set_mac_anti_spoofing, \
.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing, \
.set_source_address_pruning = \
- &ixgbe_set_source_address_pruning_X550, \
+ &ixgbe_set_source_address_pruning_x550, \
.set_ethertype_anti_spoofing = \
- &ixgbe_set_ethertype_anti_spoofing_X550, \
+ &ixgbe_set_ethertype_anti_spoofing_x550, \
.disable_rx_buff = &ixgbe_disable_rx_buff_generic, \
.enable_rx_buff = &ixgbe_enable_rx_buff_generic, \
.get_thermal_sensor_data = NULL, \
@@ -4047,7 +4048,7 @@ static const u32 ixgbe_mvals_X550EM_x[IXGBE_MVALS_IDX_LIMIT] = {
IXGBE_MVALS_INIT(X550EM_x)
};
-static const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = {
+const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT] = {
IXGBE_MVALS_INIT(X550EM_a)
};
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.h
new file mode 100644
index 000000000000..3e4092f8da3e
--- /dev/null
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright(c) 2024 Intel Corporation. */
+
+#ifndef _IXGBE_X550_H_
+#define _IXGBE_X550_H_
+
+#include "ixgbe_type.h"
+
+extern const u32 ixgbe_mvals_x550em_a[IXGBE_MVALS_IDX_LIMIT];
+
+int ixgbe_set_fw_drv_ver_x550(struct ixgbe_hw *hw, u8 maj, u8 min,
+ u8 build, u8 sub, u16 len,
+ const char *driver_ver);
+void ixgbe_set_source_address_pruning_x550(struct ixgbe_hw *hw,
+ bool enable,
+ unsigned int pool);
+void ixgbe_set_ethertype_anti_spoofing_x550(struct ixgbe_hw *hw,
+ bool enable, int vf);
+
+#endif /* _IXGBE_X550_H_ */
diff --git a/drivers/net/ethernet/intel/ixgbevf/defines.h b/drivers/net/ethernet/intel/ixgbevf/defines.h
index 5f08779c0e4e..a9bc96f6399d 100644
--- a/drivers/net/ethernet/intel/ixgbevf/defines.h
+++ b/drivers/net/ethernet/intel/ixgbevf/defines.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#ifndef _IXGBEVF_DEFINES_H_
#define _IXGBEVF_DEFINES_H_
@@ -16,6 +16,9 @@
#define IXGBE_DEV_ID_X550_VF_HV 0x1564
#define IXGBE_DEV_ID_X550EM_X_VF_HV 0x15A9
+#define IXGBE_DEV_ID_E610_VF 0x57AD
+#define IXGBE_SUBDEV_ID_E610_VF_HV 0x00FF
+
#define IXGBE_VF_IRQ_CLEAR_MASK 7
#define IXGBE_VF_MAX_TX_QUEUES 8
#define IXGBE_VF_MAX_RX_QUEUES 8
diff --git a/drivers/net/ethernet/intel/ixgbevf/ipsec.c b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
index 66cf17f19408..f804b35d79c7 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ipsec.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ipsec.c
@@ -629,7 +629,6 @@ void ixgbevf_init_ipsec_offload(struct ixgbevf_adapter *adapter)
switch (adapter->hw.api_version) {
case ixgbe_mbox_api_14:
- case ixgbe_mbox_api_15:
break;
default:
return;
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
index 130cb868774c..4384e892f967 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#ifndef _IXGBEVF_H_
#define _IXGBEVF_H_
@@ -418,6 +418,8 @@ enum ixgbevf_boards {
board_X550EM_x_vf,
board_X550EM_x_vf_hv,
board_x550em_a_vf,
+ board_e610_vf,
+ board_e610_vf_hv,
};
enum ixgbevf_xcast_modes {
@@ -434,12 +436,13 @@ extern const struct ixgbevf_info ixgbevf_X550EM_x_vf_info;
extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops;
extern const struct ixgbe_mbx_operations ixgbevf_mbx_ops_legacy;
extern const struct ixgbevf_info ixgbevf_x550em_a_vf_info;
+extern const struct ixgbevf_info ixgbevf_e610_vf_info;
extern const struct ixgbevf_info ixgbevf_82599_vf_hv_info;
extern const struct ixgbevf_info ixgbevf_X540_vf_hv_info;
extern const struct ixgbevf_info ixgbevf_X550_vf_hv_info;
extern const struct ixgbevf_info ixgbevf_X550EM_x_vf_hv_info;
-extern const struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops;
+extern const struct ixgbevf_info ixgbevf_e610_vf_hv_info;
/* needed by ethtool.c */
extern const char ixgbevf_driver_name[];
diff --git a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
index 149911e3002a..6442f115a262 100644
--- a/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
+++ b/drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
/******************************************************************************
Copyright (c)2006 - 2007 Myricom, Inc. for some LRO specific code
@@ -39,7 +39,7 @@ static const char ixgbevf_driver_string[] =
"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
static char ixgbevf_copyright[] =
- "Copyright (c) 2009 - 2018 Intel Corporation.";
+ "Copyright (c) 2009 - 2024 Intel Corporation.";
static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
[board_82599_vf] = &ixgbevf_82599_vf_info,
@@ -51,6 +51,8 @@ static const struct ixgbevf_info *ixgbevf_info_tbl[] = {
[board_X550EM_x_vf] = &ixgbevf_X550EM_x_vf_info,
[board_X550EM_x_vf_hv] = &ixgbevf_X550EM_x_vf_hv_info,
[board_x550em_a_vf] = &ixgbevf_x550em_a_vf_info,
+ [board_e610_vf] = &ixgbevf_e610_vf_info,
+ [board_e610_vf_hv] = &ixgbevf_e610_vf_hv_info,
};
/* ixgbevf_pci_tbl - PCI Device ID Table
@@ -71,6 +73,9 @@ static const struct pci_device_id ixgbevf_pci_tbl[] = {
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF), board_X550EM_x_vf },
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_X_VF_HV), board_X550EM_x_vf_hv},
{PCI_VDEVICE(INTEL, IXGBE_DEV_ID_X550EM_A_VF), board_x550em_a_vf },
+ {PCI_VDEVICE_SUB(INTEL, IXGBE_DEV_ID_E610_VF, PCI_ANY_ID,
+ IXGBE_SUBDEV_ID_E610_VF_HV), board_e610_vf_hv},
+ {PCI_VDEVICE(INTEL, IXGBE_DEV_ID_E610_VF), board_e610_vf},
/* required last entry */
{0, }
};
@@ -732,10 +737,6 @@ static bool ixgbevf_cleanup_headers(struct ixgbevf_ring *rx_ring,
union ixgbe_adv_rx_desc *rx_desc,
struct sk_buff *skb)
{
- /* XDP packets use error pointer so abort at this point */
- if (IS_ERR(skb))
- return true;
-
/* verify that the packet does not have any known errors */
if (unlikely(ixgbevf_test_staterr(rx_desc,
IXGBE_RXDADV_ERR_FRAME_ERR_MASK))) {
@@ -1044,9 +1045,9 @@ static int ixgbevf_xmit_xdp_ring(struct ixgbevf_ring *ring,
return IXGBEVF_XDP_TX;
}
-static struct sk_buff *ixgbevf_run_xdp(struct ixgbevf_adapter *adapter,
- struct ixgbevf_ring *rx_ring,
- struct xdp_buff *xdp)
+static int ixgbevf_run_xdp(struct ixgbevf_adapter *adapter,
+ struct ixgbevf_ring *rx_ring,
+ struct xdp_buff *xdp)
{
int result = IXGBEVF_XDP_PASS;
struct ixgbevf_ring *xdp_ring;
@@ -1080,7 +1081,7 @@ out_failure:
break;
}
xdp_out:
- return ERR_PTR(-result);
+ return result;
}
static unsigned int ixgbevf_rx_frame_truesize(struct ixgbevf_ring *rx_ring,
@@ -1122,6 +1123,7 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
struct sk_buff *skb = rx_ring->skb;
bool xdp_xmit = false;
struct xdp_buff xdp;
+ int xdp_res = 0;
/* Frame size depend on rx_ring setup when PAGE_SIZE=4K */
#if (PAGE_SIZE < 8192)
@@ -1165,11 +1167,11 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
/* At larger PAGE_SIZE, frame_sz depend on len size */
xdp.frame_sz = ixgbevf_rx_frame_truesize(rx_ring, size);
#endif
- skb = ixgbevf_run_xdp(adapter, rx_ring, &xdp);
+ xdp_res = ixgbevf_run_xdp(adapter, rx_ring, &xdp);
}
- if (IS_ERR(skb)) {
- if (PTR_ERR(skb) == -IXGBEVF_XDP_TX) {
+ if (xdp_res) {
+ if (xdp_res == IXGBEVF_XDP_TX) {
xdp_xmit = true;
ixgbevf_rx_buffer_flip(rx_ring, rx_buffer,
size);
@@ -1189,7 +1191,7 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
}
/* exit if we failed to retrieve a buffer */
- if (!skb) {
+ if (!xdp_res && !skb) {
rx_ring->rx_stats.alloc_rx_buff_failed++;
rx_buffer->pagecnt_bias++;
break;
@@ -1203,7 +1205,7 @@ static int ixgbevf_clean_rx_irq(struct ixgbevf_q_vector *q_vector,
continue;
/* verify the packet layout is correct */
- if (ixgbevf_cleanup_headers(rx_ring, rx_desc, skb)) {
+ if (xdp_res || ixgbevf_cleanup_headers(rx_ring, rx_desc, skb)) {
skb = NULL;
continue;
}
@@ -4693,6 +4695,9 @@ static int ixgbevf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
case ixgbe_mac_X540_vf:
dev_info(&pdev->dev, "Intel(R) X540 Virtual Function\n");
break;
+ case ixgbe_mac_e610_vf:
+ dev_info(&pdev->dev, "Intel(R) E610 Virtual Function\n");
+ break;
case ixgbe_mac_82599_vf:
default:
dev_info(&pdev->dev, "Intel(R) 82599 Virtual Function\n");
diff --git a/drivers/net/ethernet/intel/ixgbevf/mbx.c b/drivers/net/ethernet/intel/ixgbevf/mbx.c
index a55dd978f7ca..24d0237e7a99 100644
--- a/drivers/net/ethernet/intel/ixgbevf/mbx.c
+++ b/drivers/net/ethernet/intel/ixgbevf/mbx.c
@@ -505,15 +505,3 @@ const struct ixgbe_mbx_operations ixgbevf_mbx_ops_legacy = {
.check_for_ack = ixgbevf_check_for_ack_vf,
.check_for_rst = ixgbevf_check_for_rst_vf,
};
-
-/* Mailbox operations when running on Hyper-V.
- * On Hyper-V, PF/VF communication is not through the
- * hardware mailbox; this communication is through
- * a software mediated path.
- * Most mail box operations are noop while running on
- * Hyper-V.
- */
-const struct ixgbe_mbx_operations ixgbevf_hv_mbx_ops = {
- .init_params = ixgbevf_init_mbx_params_vf,
- .check_for_rst = ixgbevf_check_for_rst_vf,
-};
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.c b/drivers/net/ethernet/intel/ixgbevf/vf.c
index 1641d00d8ed3..da7a72ecce7a 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.c
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.c
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#include "vf.h"
#include "ixgbevf.h"
@@ -1076,3 +1076,13 @@ const struct ixgbevf_info ixgbevf_x550em_a_vf_info = {
.mac = ixgbe_mac_x550em_a_vf,
.mac_ops = &ixgbevf_mac_ops,
};
+
+const struct ixgbevf_info ixgbevf_e610_vf_info = {
+ .mac = ixgbe_mac_e610_vf,
+ .mac_ops = &ixgbevf_mac_ops,
+};
+
+const struct ixgbevf_info ixgbevf_e610_vf_hv_info = {
+ .mac = ixgbe_mac_e610_vf,
+ .mac_ops = &ixgbevf_hv_mac_ops,
+};
diff --git a/drivers/net/ethernet/intel/ixgbevf/vf.h b/drivers/net/ethernet/intel/ixgbevf/vf.h
index b4eef5b6c172..2d791bc26ae4 100644
--- a/drivers/net/ethernet/intel/ixgbevf/vf.h
+++ b/drivers/net/ethernet/intel/ixgbevf/vf.h
@@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright(c) 1999 - 2018 Intel Corporation. */
+/* Copyright(c) 1999 - 2024 Intel Corporation. */
#ifndef __IXGBE_VF_H__
#define __IXGBE_VF_H__
@@ -54,6 +54,8 @@ enum ixgbe_mac_type {
ixgbe_mac_X550_vf,
ixgbe_mac_X550EM_x_vf,
ixgbe_mac_x550em_a_vf,
+ ixgbe_mac_e610,
+ ixgbe_mac_e610_vf,
ixgbe_num_macs
};
diff --git a/drivers/net/ethernet/intel/libeth/rx.c b/drivers/net/ethernet/intel/libeth/rx.c
index f20926669318..66d1d23b8ad2 100644
--- a/drivers/net/ethernet/intel/libeth/rx.c
+++ b/drivers/net/ethernet/intel/libeth/rx.c
@@ -186,7 +186,7 @@ err_buf:
return -ENOMEM;
}
-EXPORT_SYMBOL_NS_GPL(libeth_rx_fq_create, LIBETH);
+EXPORT_SYMBOL_NS_GPL(libeth_rx_fq_create, "LIBETH");
/**
* libeth_rx_fq_destroy - destroy a &page_pool created by libeth
@@ -197,7 +197,7 @@ void libeth_rx_fq_destroy(struct libeth_fq *fq)
kvfree(fq->fqes);
page_pool_destroy(fq->pp);
}
-EXPORT_SYMBOL_NS_GPL(libeth_rx_fq_destroy, LIBETH);
+EXPORT_SYMBOL_NS_GPL(libeth_rx_fq_destroy, "LIBETH");
/**
* libeth_rx_recycle_slow - recycle a libeth page from the NAPI context
@@ -209,7 +209,7 @@ void libeth_rx_recycle_slow(struct page *page)
{
page_pool_recycle_direct(page->pp, page);
}
-EXPORT_SYMBOL_NS_GPL(libeth_rx_recycle_slow, LIBETH);
+EXPORT_SYMBOL_NS_GPL(libeth_rx_recycle_slow, "LIBETH");
/* Converting abstract packet type numbers into a software structure with
* the packet parameters to do O(1) lookup on Rx.
@@ -251,7 +251,7 @@ void libeth_rx_pt_gen_hash_type(struct libeth_rx_pt *pt)
pt->hash_type |= libeth_rx_pt_xdp_iprot[pt->inner_prot];
pt->hash_type |= libeth_rx_pt_xdp_pl[pt->payload_layer];
}
-EXPORT_SYMBOL_NS_GPL(libeth_rx_pt_gen_hash_type, LIBETH);
+EXPORT_SYMBOL_NS_GPL(libeth_rx_pt_gen_hash_type, "LIBETH");
/* Module */
diff --git a/drivers/net/ethernet/intel/libie/rx.c b/drivers/net/ethernet/intel/libie/rx.c
index aceb8d8813c4..66a9825fe11f 100644
--- a/drivers/net/ethernet/intel/libie/rx.c
+++ b/drivers/net/ethernet/intel/libie/rx.c
@@ -116,8 +116,8 @@ const struct libeth_rx_pt libie_rx_pt_lut[LIBIE_RX_PT_NUM] = {
LIBIE_RX_PT_IP(4),
LIBIE_RX_PT_IP(6),
};
-EXPORT_SYMBOL_NS_GPL(libie_rx_pt_lut, LIBIE);
+EXPORT_SYMBOL_NS_GPL(libie_rx_pt_lut, "LIBIE");
MODULE_DESCRIPTION("Intel(R) Ethernet common library");
-MODULE_IMPORT_NS(LIBETH);
+MODULE_IMPORT_NS("LIBETH");
MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/lantiq_etop.c b/drivers/net/ethernet/lantiq_etop.c
index 660dff5426e7..83ce3bfefa5c 100644
--- a/drivers/net/ethernet/lantiq_etop.c
+++ b/drivers/net/ethernet/lantiq_etop.c
@@ -90,7 +90,6 @@ struct ltq_etop_priv {
struct net_device *netdev;
struct platform_device *pdev;
struct ltq_eth_data *pldata;
- struct resource *res;
struct mii_bus *mii_bus;
@@ -643,31 +642,14 @@ ltq_etop_probe(struct platform_device *pdev)
{
struct net_device *dev;
struct ltq_etop_priv *priv;
- struct resource *res;
int err;
int i;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res) {
- dev_err(&pdev->dev, "failed to get etop resource\n");
- err = -ENOENT;
- goto err_out;
- }
-
- res = devm_request_mem_region(&pdev->dev, res->start,
- resource_size(res), dev_name(&pdev->dev));
- if (!res) {
- dev_err(&pdev->dev, "failed to request etop resource\n");
- err = -EBUSY;
- goto err_out;
- }
-
- ltq_etop_membase = devm_ioremap(&pdev->dev, res->start,
- resource_size(res));
- if (!ltq_etop_membase) {
+ ltq_etop_membase = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(ltq_etop_membase)) {
dev_err(&pdev->dev, "failed to remap etop engine %d\n",
pdev->id);
- err = -ENOMEM;
+ err = PTR_ERR(ltq_etop_membase);
goto err_out;
}
@@ -679,7 +661,6 @@ ltq_etop_probe(struct platform_device *pdev)
dev->netdev_ops = &ltq_eth_netdev_ops;
dev->ethtool_ops = &ltq_etop_ethtool_ops;
priv = netdev_priv(dev);
- priv->res = res;
priv->pdev = pdev;
priv->pldata = dev_get_platdata(&pdev->dev);
priv->netdev = dev;
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index a06048719e84..67a6ff07c83d 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -2704,9 +2704,15 @@ static struct platform_device *port_platdev[3];
static void mv643xx_eth_shared_of_remove(void)
{
+ struct mv643xx_eth_platform_data *pd;
int n;
for (n = 0; n < 3; n++) {
+ if (!port_platdev[n])
+ continue;
+ pd = dev_get_platdata(&port_platdev[n]->dev);
+ if (pd)
+ of_node_put(pd->phy_node);
platform_device_del(port_platdev[n]);
port_platdev[n] = NULL;
}
@@ -2769,8 +2775,10 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
}
ppdev = platform_device_alloc(MV643XX_ETH_NAME, dev_num);
- if (!ppdev)
- return -ENOMEM;
+ if (!ppdev) {
+ ret = -ENOMEM;
+ goto put_err;
+ }
ppdev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
ppdev->dev.of_node = pnp;
@@ -2792,6 +2800,8 @@ static int mv643xx_eth_shared_of_add_port(struct platform_device *pdev,
port_err:
platform_device_put(ppdev);
+put_err:
+ of_node_put(ppd.phy_node);
return ret;
}
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
index 549436efc204..3a9825883d79 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.c
@@ -1137,6 +1137,43 @@ static int octep_set_features(struct net_device *dev, netdev_features_t features
return err;
}
+static int octep_get_vf_config(struct net_device *dev, int vf,
+ struct ifla_vf_info *ivi)
+{
+ struct octep_device *oct = netdev_priv(dev);
+
+ ivi->vf = vf;
+ ether_addr_copy(ivi->mac, oct->vf_info[vf].mac_addr);
+ ivi->spoofchk = true;
+ ivi->linkstate = IFLA_VF_LINK_STATE_ENABLE;
+ ivi->trusted = false;
+
+ return 0;
+}
+
+static int octep_set_vf_mac(struct net_device *dev, int vf, u8 *mac)
+{
+ struct octep_device *oct = netdev_priv(dev);
+ int err;
+
+ if (!is_valid_ether_addr(mac)) {
+ dev_err(&oct->pdev->dev, "Invalid MAC Address %pM\n", mac);
+ return -EADDRNOTAVAIL;
+ }
+
+ dev_dbg(&oct->pdev->dev, "set vf-%d mac to %pM\n", vf, mac);
+ ether_addr_copy(oct->vf_info[vf].mac_addr, mac);
+ oct->vf_info[vf].flags |= OCTEON_PFVF_FLAG_MAC_SET_BY_PF;
+
+ err = octep_ctrl_net_set_mac_addr(oct, vf, mac, true);
+ if (err)
+ dev_err(&oct->pdev->dev,
+ "Set VF%d MAC address failed via host control Mbox\n",
+ vf);
+
+ return err;
+}
+
static const struct net_device_ops octep_netdev_ops = {
.ndo_open = octep_open,
.ndo_stop = octep_stop,
@@ -1146,6 +1183,8 @@ static const struct net_device_ops octep_netdev_ops = {
.ndo_set_mac_address = octep_set_mac,
.ndo_change_mtu = octep_change_mtu,
.ndo_set_features = octep_set_features,
+ .ndo_get_vf_config = octep_get_vf_config,
+ .ndo_set_vf_mac = octep_set_vf_mac
};
/**
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
index fee59e0e0138..3b56916af468 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_main.h
@@ -220,6 +220,7 @@ struct octep_iface_link_info {
/* The Octeon VF device specific info data structure.*/
struct octep_pfvf_info {
u8 mac_addr[ETH_ALEN];
+ u32 flags;
u32 mbox_version;
};
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
index e6eb98d70f3c..ebecdd29f3bd 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.c
@@ -156,12 +156,23 @@ static void octep_pfvf_set_mac_addr(struct octep_device *oct, u32 vf_id,
{
int err;
+ if (oct->vf_info[vf_id].flags & OCTEON_PFVF_FLAG_MAC_SET_BY_PF) {
+ dev_err(&oct->pdev->dev,
+ "VF%d attempted to override administrative set MAC address\n",
+ vf_id);
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
+ return;
+ }
+
err = octep_ctrl_net_set_mac_addr(oct, vf_id, cmd.s_set_mac.mac_addr, true);
if (err) {
rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
- dev_err(&oct->pdev->dev, "Set VF MAC address failed via host control Mbox\n");
+ dev_err(&oct->pdev->dev, "Set VF%d MAC address failed via host control Mbox\n",
+ vf_id);
return;
}
+
+ ether_addr_copy(oct->vf_info[vf_id].mac_addr, cmd.s_set_mac.mac_addr);
rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
}
@@ -171,10 +182,18 @@ static void octep_pfvf_get_mac_addr(struct octep_device *oct, u32 vf_id,
{
int err;
+ if (oct->vf_info[vf_id].flags & OCTEON_PFVF_FLAG_MAC_SET_BY_PF) {
+ dev_dbg(&oct->pdev->dev, "VF%d MAC address set by PF\n", vf_id);
+ ether_addr_copy(rsp->s_set_mac.mac_addr,
+ oct->vf_info[vf_id].mac_addr);
+ rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
+ return;
+ }
err = octep_ctrl_net_get_mac_addr(oct, vf_id, rsp->s_set_mac.mac_addr);
if (err) {
rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_NACK;
- dev_err(&oct->pdev->dev, "Get VF MAC address failed via host control Mbox\n");
+ dev_err(&oct->pdev->dev, "Get VF%d MAC address failed via host control Mbox\n",
+ vf_id);
return;
}
rsp->s_set_mac.type = OCTEP_PFVF_MBOX_TYPE_RSP_ACK;
diff --git a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
index 0dc6eead292a..386a095a99bc 100644
--- a/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
+++ b/drivers/net/ethernet/marvell/octeon_ep/octep_pfvf_mbox.h
@@ -8,8 +8,6 @@
#ifndef _OCTEP_PFVF_MBOX_H_
#define _OCTEP_PFVF_MBOX_H_
-/* VF flags */
-#define OCTEON_PFVF_FLAG_MAC_SET_BY_PF BIT_ULL(0) /* PF has set VF MAC address */
#define OCTEON_SDP_16K_HW_FRS 16380UL
#define OCTEON_SDP_64K_HW_FRS 65531UL
@@ -23,6 +21,10 @@ enum octep_pfvf_mbox_version {
#define OCTEP_PFVF_MBOX_VERSION_CURRENT OCTEP_PFVF_MBOX_VERSION_V2
+/* VF flags */
+/* PF has set VF MAC address */
+#define OCTEON_PFVF_FLAG_MAC_SET_BY_PF BIT(0)
+
enum octep_pfvf_mbox_opcode {
OCTEP_PFVF_MBOX_CMD_VERSION,
OCTEP_PFVF_MBOX_CMD_SET_MTU,
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/common.h b/drivers/net/ethernet/marvell/octeontx2/af/common.h
index 5d84386ed22d..406c59100a35 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/common.h
@@ -159,6 +159,7 @@ enum nix_scheduler {
#define SDP_HW_MIN_FRS 16
#define CN10K_LMAC_LINK_MAX_FRS 16380 /* 16k - FCS */
#define CN10K_LBK_LINK_MAX_FRS 65535 /* 64k */
+#define SDP_LINK_CREDIT 0x320202
/* NIX RX action operation*/
#define NIX_RX_ACTIONOP_DROP (0x0ull)
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
index 62c07407eb94..005ca8a056c0 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
+++ b/drivers/net/ethernet/marvell/octeontx2/af/mbox.h
@@ -313,6 +313,10 @@ M(NIX_BANDPROF_FREE, 0x801e, nix_bandprof_free, nix_bandprof_free_req, \
msg_rsp) \
M(NIX_BANDPROF_GET_HWINFO, 0x801f, nix_bandprof_get_hwinfo, msg_req, \
nix_bandprof_get_hwinfo_rsp) \
+M(NIX_CPT_BP_ENABLE, 0x8020, nix_cpt_bp_enable, nix_bp_cfg_req, \
+ nix_bp_cfg_rsp) \
+M(NIX_CPT_BP_DISABLE, 0x8021, nix_cpt_bp_disable, nix_bp_cfg_req, \
+ msg_rsp) \
M(NIX_READ_INLINE_IPSEC_CFG, 0x8023, nix_read_inline_ipsec_cfg, \
msg_req, nix_inline_ipsec_cfg) \
M(NIX_MCAST_GRP_CREATE, 0x802b, nix_mcast_grp_create, nix_mcast_grp_create_req, \
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
index 5d5a01dbbca1..613655fcd34f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_nix.c
@@ -569,9 +569,17 @@ void rvu_nix_flr_free_bpids(struct rvu *rvu, u16 pcifunc)
mutex_unlock(&rvu->rsrc_lock);
}
-int rvu_mbox_handler_nix_bp_disable(struct rvu *rvu,
- struct nix_bp_cfg_req *req,
- struct msg_rsp *rsp)
+static u16 nix_get_channel(u16 chan, bool cpt_link)
+{
+ /* CPT channel for a given link channel is always
+ * assumed to be BIT(11) set in link channel.
+ */
+ return cpt_link ? chan | BIT(11) : chan;
+}
+
+static int nix_bp_disable(struct rvu *rvu,
+ struct nix_bp_cfg_req *req,
+ struct msg_rsp *rsp, bool cpt_link)
{
u16 pcifunc = req->hdr.pcifunc;
int blkaddr, pf, type, err;
@@ -579,6 +587,7 @@ int rvu_mbox_handler_nix_bp_disable(struct rvu *rvu,
struct rvu_pfvf *pfvf;
struct nix_hw *nix_hw;
struct nix_bp *bp;
+ u16 chan_v;
u64 cfg;
pf = rvu_get_pf(pcifunc);
@@ -589,6 +598,9 @@ int rvu_mbox_handler_nix_bp_disable(struct rvu *rvu,
if (is_sdp_pfvf(pcifunc))
type = NIX_INTF_TYPE_SDP;
+ if (cpt_link && !rvu->hw->cpt_links)
+ return 0;
+
pfvf = rvu_get_pfvf(rvu, pcifunc);
err = nix_get_struct_ptrs(rvu, pcifunc, &nix_hw, &blkaddr);
if (err)
@@ -597,8 +609,9 @@ int rvu_mbox_handler_nix_bp_disable(struct rvu *rvu,
bp = &nix_hw->bp;
chan_base = pfvf->rx_chan_base + req->chan_base;
for (chan = chan_base; chan < (chan_base + req->chan_cnt); chan++) {
- cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan));
- rvu_write64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan),
+ chan_v = nix_get_channel(chan, cpt_link);
+ cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan_v));
+ rvu_write64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan_v),
cfg & ~BIT_ULL(16));
if (type == NIX_INTF_TYPE_LBK) {
@@ -617,6 +630,20 @@ int rvu_mbox_handler_nix_bp_disable(struct rvu *rvu,
return 0;
}
+int rvu_mbox_handler_nix_bp_disable(struct rvu *rvu,
+ struct nix_bp_cfg_req *req,
+ struct msg_rsp *rsp)
+{
+ return nix_bp_disable(rvu, req, rsp, false);
+}
+
+int rvu_mbox_handler_nix_cpt_bp_disable(struct rvu *rvu,
+ struct nix_bp_cfg_req *req,
+ struct msg_rsp *rsp)
+{
+ return nix_bp_disable(rvu, req, rsp, true);
+}
+
static int rvu_nix_get_bpid(struct rvu *rvu, struct nix_bp_cfg_req *req,
int type, int chan_id)
{
@@ -696,15 +723,17 @@ static int rvu_nix_get_bpid(struct rvu *rvu, struct nix_bp_cfg_req *req,
return bpid;
}
-int rvu_mbox_handler_nix_bp_enable(struct rvu *rvu,
- struct nix_bp_cfg_req *req,
- struct nix_bp_cfg_rsp *rsp)
+static int nix_bp_enable(struct rvu *rvu,
+ struct nix_bp_cfg_req *req,
+ struct nix_bp_cfg_rsp *rsp,
+ bool cpt_link)
{
int blkaddr, pf, type, chan_id = 0;
u16 pcifunc = req->hdr.pcifunc;
struct rvu_pfvf *pfvf;
u16 chan_base, chan;
s16 bpid, bpid_base;
+ u16 chan_v;
u64 cfg;
pf = rvu_get_pf(pcifunc);
@@ -717,6 +746,9 @@ int rvu_mbox_handler_nix_bp_enable(struct rvu *rvu,
type != NIX_INTF_TYPE_SDP)
return 0;
+ if (cpt_link && !rvu->hw->cpt_links)
+ return 0;
+
pfvf = rvu_get_pfvf(rvu, pcifunc);
blkaddr = rvu_get_blkaddr(rvu, BLKTYPE_NIX, pcifunc);
@@ -730,9 +762,11 @@ int rvu_mbox_handler_nix_bp_enable(struct rvu *rvu,
return -EINVAL;
}
- cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan));
+ chan_v = nix_get_channel(chan, cpt_link);
+
+ cfg = rvu_read64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan_v));
cfg &= ~GENMASK_ULL(8, 0);
- rvu_write64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan),
+ rvu_write64(rvu, blkaddr, NIX_AF_RX_CHANX_CFG(chan_v),
cfg | (bpid & GENMASK_ULL(8, 0)) | BIT_ULL(16));
chan_id++;
bpid = rvu_nix_get_bpid(rvu, req, type, chan_id);
@@ -750,6 +784,20 @@ int rvu_mbox_handler_nix_bp_enable(struct rvu *rvu,
return 0;
}
+int rvu_mbox_handler_nix_bp_enable(struct rvu *rvu,
+ struct nix_bp_cfg_req *req,
+ struct nix_bp_cfg_rsp *rsp)
+{
+ return nix_bp_enable(rvu, req, rsp, false);
+}
+
+int rvu_mbox_handler_nix_cpt_bp_enable(struct rvu *rvu,
+ struct nix_bp_cfg_req *req,
+ struct nix_bp_cfg_rsp *rsp)
+{
+ return nix_bp_enable(rvu, req, rsp, true);
+}
+
static void nix_setup_lso_tso_l3(struct rvu *rvu, int blkaddr,
u64 format, bool v4, u64 *fidx)
{
@@ -4672,6 +4720,9 @@ static void nix_link_config(struct rvu *rvu, int blkaddr,
rvu_get_lbk_link_max_frs(rvu, &lbk_max_frs);
rvu_get_lmac_link_max_frs(rvu, &lmac_max_frs);
+ /* Set SDP link credit */
+ rvu_write64(rvu, blkaddr, NIX_AF_SDP_LINK_CREDIT, SDP_LINK_CREDIT);
+
/* Set default min/max packet lengths allowed on NIX Rx links.
*
* With HW reset minlen value of 60byte, HW will treat ARP pkts
diff --git a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
index da69e454662a..1b765045aa63 100644
--- a/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
+++ b/drivers/net/ethernet/marvell/octeontx2/af/rvu_npc_fs.c
@@ -1452,23 +1452,21 @@ process_flow:
* hence modify pcifunc accordingly.
*/
- /* AF installing for a PF/VF */
- if (!req->hdr.pcifunc)
+ if (!req->hdr.pcifunc) {
+ /* AF installing for a PF/VF */
target = req->vf;
-
- /* PF installing for its VF */
- if (!from_vf && req->vf && !from_rep_dev) {
+ } else if (!from_vf && req->vf && !from_rep_dev) {
+ /* PF installing for its VF */
target = (req->hdr.pcifunc & ~RVU_PFVF_FUNC_MASK) | req->vf;
pf_set_vfs_mac = req->default_rule &&
(req->features & BIT_ULL(NPC_DMAC));
- }
-
- /* Representor device installing for a representee */
- if (from_rep_dev && req->vf)
+ } else if (from_rep_dev && req->vf) {
+ /* Representor device installing for a representee */
target = req->vf;
- else
+ } else {
/* msg received from PF/VF */
target = req->hdr.pcifunc;
+ }
/* ignore chan_mask in case pf func is not AF, revisit later */
if (!is_pffunc_af(req->hdr.pcifunc))
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
index dbc971266865..cb6513ab35e7 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/Makefile
@@ -15,5 +15,6 @@ rvu_rep-y := rep.o
rvu_nicpf-$(CONFIG_DCB) += otx2_dcbnl.o
rvu_nicpf-$(CONFIG_MACSEC) += cn10k_macsec.o
+rvu_nicpf-$(CONFIG_XFRM_OFFLOAD) += cn10k_ipsec.o
ccflags-y += -I$(srctree)/drivers/net/ethernet/marvell/octeontx2/af
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c
new file mode 100644
index 000000000000..09a5b5268205
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.c
@@ -0,0 +1,1056 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Marvell IPSEC offload driver
+ *
+ * Copyright (C) 2024 Marvell.
+ */
+
+#include <net/xfrm.h>
+#include <linux/netdevice.h>
+#include <linux/bitfield.h>
+#include <crypto/aead.h>
+#include <crypto/gcm.h>
+
+#include "otx2_common.h"
+#include "otx2_struct.h"
+#include "cn10k_ipsec.h"
+
+static bool is_dev_support_ipsec_offload(struct pci_dev *pdev)
+{
+ return is_dev_cn10ka_b0(pdev) || is_dev_cn10kb(pdev);
+}
+
+static bool cn10k_cpt_device_set_inuse(struct otx2_nic *pf)
+{
+ enum cn10k_cpt_hw_state_e state;
+
+ while (true) {
+ state = atomic_cmpxchg(&pf->ipsec.cpt_state,
+ CN10K_CPT_HW_AVAILABLE,
+ CN10K_CPT_HW_IN_USE);
+ if (state == CN10K_CPT_HW_AVAILABLE)
+ return true;
+ if (state == CN10K_CPT_HW_UNAVAILABLE)
+ return false;
+
+ mdelay(1);
+ }
+}
+
+static void cn10k_cpt_device_set_available(struct otx2_nic *pf)
+{
+ atomic_set(&pf->ipsec.cpt_state, CN10K_CPT_HW_AVAILABLE);
+}
+
+static void cn10k_cpt_device_set_unavailable(struct otx2_nic *pf)
+{
+ atomic_set(&pf->ipsec.cpt_state, CN10K_CPT_HW_UNAVAILABLE);
+}
+
+static int cn10k_outb_cptlf_attach(struct otx2_nic *pf)
+{
+ struct rsrc_attach *attach;
+ int ret = -ENOMEM;
+
+ mutex_lock(&pf->mbox.lock);
+ /* Get memory to put this msg */
+ attach = otx2_mbox_alloc_msg_attach_resources(&pf->mbox);
+ if (!attach)
+ goto unlock;
+
+ attach->cptlfs = true;
+ attach->modify = true;
+
+ /* Send attach request to AF */
+ ret = otx2_sync_mbox_msg(&pf->mbox);
+
+unlock:
+ mutex_unlock(&pf->mbox.lock);
+ return ret;
+}
+
+static int cn10k_outb_cptlf_detach(struct otx2_nic *pf)
+{
+ struct rsrc_detach *detach;
+ int ret = -ENOMEM;
+
+ mutex_lock(&pf->mbox.lock);
+ detach = otx2_mbox_alloc_msg_detach_resources(&pf->mbox);
+ if (!detach)
+ goto unlock;
+
+ detach->partial = true;
+ detach->cptlfs = true;
+
+ /* Send detach request to AF */
+ ret = otx2_sync_mbox_msg(&pf->mbox);
+
+unlock:
+ mutex_unlock(&pf->mbox.lock);
+ return ret;
+}
+
+static int cn10k_outb_cptlf_alloc(struct otx2_nic *pf)
+{
+ struct cpt_lf_alloc_req_msg *req;
+ int ret = -ENOMEM;
+
+ mutex_lock(&pf->mbox.lock);
+ req = otx2_mbox_alloc_msg_cpt_lf_alloc(&pf->mbox);
+ if (!req)
+ goto unlock;
+
+ /* PF function */
+ req->nix_pf_func = pf->pcifunc;
+ /* Enable SE-IE Engine Group */
+ req->eng_grpmsk = 1 << CN10K_DEF_CPT_IPSEC_EGRP;
+
+ ret = otx2_sync_mbox_msg(&pf->mbox);
+
+unlock:
+ mutex_unlock(&pf->mbox.lock);
+ return ret;
+}
+
+static void cn10k_outb_cptlf_free(struct otx2_nic *pf)
+{
+ mutex_lock(&pf->mbox.lock);
+ otx2_mbox_alloc_msg_cpt_lf_free(&pf->mbox);
+ otx2_sync_mbox_msg(&pf->mbox);
+ mutex_unlock(&pf->mbox.lock);
+}
+
+static int cn10k_outb_cptlf_config(struct otx2_nic *pf)
+{
+ struct cpt_inline_ipsec_cfg_msg *req;
+ int ret = -ENOMEM;
+
+ mutex_lock(&pf->mbox.lock);
+ req = otx2_mbox_alloc_msg_cpt_inline_ipsec_cfg(&pf->mbox);
+ if (!req)
+ goto unlock;
+
+ req->dir = CPT_INLINE_OUTBOUND;
+ req->enable = 1;
+ req->nix_pf_func = pf->pcifunc;
+ ret = otx2_sync_mbox_msg(&pf->mbox);
+unlock:
+ mutex_unlock(&pf->mbox.lock);
+ return ret;
+}
+
+static void cn10k_outb_cptlf_iq_enable(struct otx2_nic *pf)
+{
+ u64 reg_val;
+
+ /* Set Execution Enable of instruction queue */
+ reg_val = otx2_read64(pf, CN10K_CPT_LF_INPROG);
+ reg_val |= BIT_ULL(16);
+ otx2_write64(pf, CN10K_CPT_LF_INPROG, reg_val);
+
+ /* Set iqueue's enqueuing */
+ reg_val = otx2_read64(pf, CN10K_CPT_LF_CTL);
+ reg_val |= BIT_ULL(0);
+ otx2_write64(pf, CN10K_CPT_LF_CTL, reg_val);
+}
+
+static void cn10k_outb_cptlf_iq_disable(struct otx2_nic *pf)
+{
+ u32 inflight, grb_cnt, gwb_cnt;
+ u32 nq_ptr, dq_ptr;
+ int timeout = 20;
+ u64 reg_val;
+ int cnt;
+
+ /* Disable instructions enqueuing */
+ otx2_write64(pf, CN10K_CPT_LF_CTL, 0ull);
+
+ /* Wait for instruction queue to become empty.
+ * CPT_LF_INPROG.INFLIGHT count is zero
+ */
+ do {
+ reg_val = otx2_read64(pf, CN10K_CPT_LF_INPROG);
+ inflight = FIELD_GET(CPT_LF_INPROG_INFLIGHT, reg_val);
+ if (!inflight)
+ break;
+
+ usleep_range(10000, 20000);
+ if (timeout-- < 0) {
+ netdev_err(pf->netdev, "Timeout to cleanup CPT IQ\n");
+ break;
+ }
+ } while (1);
+
+ /* Disable executions in the LF's queue,
+ * the queue should be empty at this point
+ */
+ reg_val &= ~BIT_ULL(16);
+ otx2_write64(pf, CN10K_CPT_LF_INPROG, reg_val);
+
+ /* Wait for instruction queue to become empty */
+ cnt = 0;
+ do {
+ reg_val = otx2_read64(pf, CN10K_CPT_LF_INPROG);
+ if (reg_val & BIT_ULL(31))
+ cnt = 0;
+ else
+ cnt++;
+ reg_val = otx2_read64(pf, CN10K_CPT_LF_Q_GRP_PTR);
+ nq_ptr = FIELD_GET(CPT_LF_Q_GRP_PTR_DQ_PTR, reg_val);
+ dq_ptr = FIELD_GET(CPT_LF_Q_GRP_PTR_DQ_PTR, reg_val);
+ } while ((cnt < 10) && (nq_ptr != dq_ptr));
+
+ cnt = 0;
+ do {
+ reg_val = otx2_read64(pf, CN10K_CPT_LF_INPROG);
+ inflight = FIELD_GET(CPT_LF_INPROG_INFLIGHT, reg_val);
+ grb_cnt = FIELD_GET(CPT_LF_INPROG_GRB_CNT, reg_val);
+ gwb_cnt = FIELD_GET(CPT_LF_INPROG_GWB_CNT, reg_val);
+ if (inflight == 0 && gwb_cnt < 40 &&
+ (grb_cnt == 0 || grb_cnt == 40))
+ cnt++;
+ else
+ cnt = 0;
+ } while (cnt < 10);
+}
+
+/* Allocate memory for CPT outbound Instruction queue.
+ * Instruction queue memory format is:
+ * -----------------------------
+ * | Instruction Group memory |
+ * | (CPT_LF_Q_SIZE[SIZE_DIV40] |
+ * | x 16 Bytes) |
+ * | |
+ * ----------------------------- <-- CPT_LF_Q_BASE[ADDR]
+ * | Flow Control (128 Bytes) |
+ * | |
+ * -----------------------------
+ * | Instruction Memory |
+ * | (CPT_LF_Q_SIZE[SIZE_DIV40] |
+ * | × 40 × 64 bytes) |
+ * | |
+ * -----------------------------
+ */
+static int cn10k_outb_cptlf_iq_alloc(struct otx2_nic *pf)
+{
+ struct cn10k_cpt_inst_queue *iq = &pf->ipsec.iq;
+
+ iq->size = CN10K_CPT_INST_QLEN_BYTES + CN10K_CPT_Q_FC_LEN +
+ CN10K_CPT_INST_GRP_QLEN_BYTES + OTX2_ALIGN;
+
+ iq->real_vaddr = dma_alloc_coherent(pf->dev, iq->size,
+ &iq->real_dma_addr, GFP_KERNEL);
+ if (!iq->real_vaddr)
+ return -ENOMEM;
+
+ /* iq->vaddr/dma_addr points to Flow Control location */
+ iq->vaddr = iq->real_vaddr + CN10K_CPT_INST_GRP_QLEN_BYTES;
+ iq->dma_addr = iq->real_dma_addr + CN10K_CPT_INST_GRP_QLEN_BYTES;
+
+ /* Align pointers */
+ iq->vaddr = PTR_ALIGN(iq->vaddr, OTX2_ALIGN);
+ iq->dma_addr = PTR_ALIGN(iq->dma_addr, OTX2_ALIGN);
+ return 0;
+}
+
+static void cn10k_outb_cptlf_iq_free(struct otx2_nic *pf)
+{
+ struct cn10k_cpt_inst_queue *iq = &pf->ipsec.iq;
+
+ if (iq->real_vaddr)
+ dma_free_coherent(pf->dev, iq->size, iq->real_vaddr,
+ iq->real_dma_addr);
+
+ iq->real_vaddr = NULL;
+ iq->vaddr = NULL;
+}
+
+static int cn10k_outb_cptlf_iq_init(struct otx2_nic *pf)
+{
+ u64 reg_val;
+ int ret;
+
+ /* Allocate Memory for CPT IQ */
+ ret = cn10k_outb_cptlf_iq_alloc(pf);
+ if (ret)
+ return ret;
+
+ /* Disable IQ */
+ cn10k_outb_cptlf_iq_disable(pf);
+
+ /* Set IQ base address */
+ otx2_write64(pf, CN10K_CPT_LF_Q_BASE, pf->ipsec.iq.dma_addr);
+
+ /* Set IQ size */
+ reg_val = FIELD_PREP(CPT_LF_Q_SIZE_DIV40, CN10K_CPT_SIZE_DIV40 +
+ CN10K_CPT_EXTRA_SIZE_DIV40);
+ otx2_write64(pf, CN10K_CPT_LF_Q_SIZE, reg_val);
+
+ return 0;
+}
+
+static int cn10k_outb_cptlf_init(struct otx2_nic *pf)
+{
+ int ret;
+
+ /* Initialize CPTLF Instruction Queue (IQ) */
+ ret = cn10k_outb_cptlf_iq_init(pf);
+ if (ret)
+ return ret;
+
+ /* Configure CPTLF for outbound ipsec offload */
+ ret = cn10k_outb_cptlf_config(pf);
+ if (ret)
+ goto iq_clean;
+
+ /* Enable CPTLF IQ */
+ cn10k_outb_cptlf_iq_enable(pf);
+ return 0;
+iq_clean:
+ cn10k_outb_cptlf_iq_free(pf);
+ return ret;
+}
+
+static int cn10k_outb_cpt_init(struct net_device *netdev)
+{
+ struct otx2_nic *pf = netdev_priv(netdev);
+ int ret;
+
+ /* Attach a CPT LF for outbound ipsec offload */
+ ret = cn10k_outb_cptlf_attach(pf);
+ if (ret)
+ return ret;
+
+ /* Allocate a CPT LF for outbound ipsec offload */
+ ret = cn10k_outb_cptlf_alloc(pf);
+ if (ret)
+ goto detach;
+
+ /* Initialize the CPTLF for outbound ipsec offload */
+ ret = cn10k_outb_cptlf_init(pf);
+ if (ret)
+ goto lf_free;
+
+ pf->ipsec.io_addr = (__force u64)otx2_get_regaddr(pf,
+ CN10K_CPT_LF_NQX(0));
+
+ /* Set ipsec offload enabled for this device */
+ pf->flags |= OTX2_FLAG_IPSEC_OFFLOAD_ENABLED;
+
+ cn10k_cpt_device_set_available(pf);
+ return 0;
+
+lf_free:
+ cn10k_outb_cptlf_free(pf);
+detach:
+ cn10k_outb_cptlf_detach(pf);
+ return ret;
+}
+
+static int cn10k_outb_cpt_clean(struct otx2_nic *pf)
+{
+ int ret;
+
+ if (!cn10k_cpt_device_set_inuse(pf)) {
+ netdev_err(pf->netdev, "CPT LF device unavailable\n");
+ return -ENODEV;
+ }
+
+ /* Set ipsec offload disabled for this device */
+ pf->flags &= ~OTX2_FLAG_IPSEC_OFFLOAD_ENABLED;
+
+ /* Disable CPTLF Instruction Queue (IQ) */
+ cn10k_outb_cptlf_iq_disable(pf);
+
+ /* Set IQ base address and size to 0 */
+ otx2_write64(pf, CN10K_CPT_LF_Q_BASE, 0);
+ otx2_write64(pf, CN10K_CPT_LF_Q_SIZE, 0);
+
+ /* Free CPTLF IQ */
+ cn10k_outb_cptlf_iq_free(pf);
+
+ /* Free and detach CPT LF */
+ cn10k_outb_cptlf_free(pf);
+ ret = cn10k_outb_cptlf_detach(pf);
+ if (ret)
+ netdev_err(pf->netdev, "Failed to detach CPT LF\n");
+
+ cn10k_cpt_device_set_unavailable(pf);
+ return ret;
+}
+
+static void cn10k_cpt_inst_flush(struct otx2_nic *pf, struct cpt_inst_s *inst,
+ u64 size)
+{
+ struct otx2_lmt_info *lmt_info;
+ u64 val = 0, tar_addr = 0;
+
+ lmt_info = per_cpu_ptr(pf->hw.lmt_info, smp_processor_id());
+ /* FIXME: val[0:10] LMT_ID.
+ * [12:15] no of LMTST - 1 in the burst.
+ * [19:63] data size of each LMTST in the burst except first.
+ */
+ val = (lmt_info->lmt_id & 0x7FF);
+ /* Target address for LMTST flush tells HW how many 128bit
+ * words are present.
+ * tar_addr[6:4] size of first LMTST - 1 in units of 128b.
+ */
+ tar_addr |= pf->ipsec.io_addr | (((size / 16) - 1) & 0x7) << 4;
+ dma_wmb();
+ memcpy((u64 *)lmt_info->lmt_addr, inst, size);
+ cn10k_lmt_flush(val, tar_addr);
+}
+
+static int cn10k_wait_for_cpt_respose(struct otx2_nic *pf,
+ struct cpt_res_s *res)
+{
+ unsigned long timeout = jiffies + msecs_to_jiffies(100);
+ u64 *completion_ptr = (u64 *)res;
+
+ do {
+ if (time_after(jiffies, timeout)) {
+ netdev_err(pf->netdev, "CPT response timeout\n");
+ return -EBUSY;
+ }
+ } while ((READ_ONCE(*completion_ptr) & CN10K_CPT_COMP_E_MASK) ==
+ CN10K_CPT_COMP_E_NOTDONE);
+
+ if (!(res->compcode == CN10K_CPT_COMP_E_GOOD ||
+ res->compcode == CN10K_CPT_COMP_E_WARN) || res->uc_compcode) {
+ netdev_err(pf->netdev, "compcode=%x doneint=%x\n",
+ res->compcode, res->doneint);
+ netdev_err(pf->netdev, "uc_compcode=%x uc_info=%llx esn=%llx\n",
+ res->uc_compcode, (u64)res->uc_info, res->esn);
+ }
+ return 0;
+}
+
+static int cn10k_outb_write_sa(struct otx2_nic *pf, struct qmem *sa_info)
+{
+ dma_addr_t res_iova, dptr_iova, sa_iova;
+ struct cn10k_tx_sa_s *sa_dptr;
+ struct cpt_inst_s inst = {};
+ struct cpt_res_s *res;
+ u32 sa_size, off;
+ u64 *sptr, *dptr;
+ u64 reg_val;
+ int ret;
+
+ sa_iova = sa_info->iova;
+ if (!sa_iova)
+ return -EINVAL;
+
+ res = dma_alloc_coherent(pf->dev, sizeof(struct cpt_res_s),
+ &res_iova, GFP_ATOMIC);
+ if (!res)
+ return -ENOMEM;
+
+ sa_size = sizeof(struct cn10k_tx_sa_s);
+ sa_dptr = dma_alloc_coherent(pf->dev, sa_size, &dptr_iova, GFP_ATOMIC);
+ if (!sa_dptr) {
+ dma_free_coherent(pf->dev, sizeof(struct cpt_res_s), res,
+ res_iova);
+ return -ENOMEM;
+ }
+
+ sptr = (__force u64 *)sa_info->base;
+ dptr = (__force u64 *)sa_dptr;
+ for (off = 0; off < (sa_size / 8); off++)
+ *(dptr + off) = (__force u64)cpu_to_be64(*(sptr + off));
+
+ res->compcode = CN10K_CPT_COMP_E_NOTDONE;
+ inst.res_addr = res_iova;
+ inst.dptr = (u64)dptr_iova;
+ inst.param2 = sa_size >> 3;
+ inst.dlen = sa_size;
+ inst.opcode_major = CN10K_IPSEC_MAJOR_OP_WRITE_SA;
+ inst.opcode_minor = CN10K_IPSEC_MINOR_OP_WRITE_SA;
+ inst.cptr = sa_iova;
+ inst.ctx_val = 1;
+ inst.egrp = CN10K_DEF_CPT_IPSEC_EGRP;
+
+ /* Check if CPT-LF available */
+ if (!cn10k_cpt_device_set_inuse(pf)) {
+ ret = -ENODEV;
+ goto free_mem;
+ }
+
+ cn10k_cpt_inst_flush(pf, &inst, sizeof(struct cpt_inst_s));
+ dma_wmb();
+ ret = cn10k_wait_for_cpt_respose(pf, res);
+ if (ret)
+ goto set_available;
+
+ /* Trigger CTX flush to write dirty data back to DRAM */
+ reg_val = FIELD_PREP(CPT_LF_CTX_FLUSH, sa_iova >> 7);
+ otx2_write64(pf, CN10K_CPT_LF_CTX_FLUSH, reg_val);
+
+set_available:
+ cn10k_cpt_device_set_available(pf);
+free_mem:
+ dma_free_coherent(pf->dev, sa_size, sa_dptr, dptr_iova);
+ dma_free_coherent(pf->dev, sizeof(struct cpt_res_s), res, res_iova);
+ return ret;
+}
+
+static int cn10k_ipsec_get_hw_ctx_offset(void)
+{
+ /* Offset on Hardware-context offset in word */
+ return (offsetof(struct cn10k_tx_sa_s, hw_ctx) / sizeof(u64)) & 0x7F;
+}
+
+static int cn10k_ipsec_get_ctx_push_size(void)
+{
+ /* Context push size is round up and in multiple of 8 Byte */
+ return (roundup(offsetof(struct cn10k_tx_sa_s, hw_ctx), 8) / 8) & 0x7F;
+}
+
+static int cn10k_ipsec_get_aes_key_len(int key_len)
+{
+ /* key_len is aes key length in bytes */
+ switch (key_len) {
+ case 16:
+ return CN10K_IPSEC_SA_AES_KEY_LEN_128;
+ case 24:
+ return CN10K_IPSEC_SA_AES_KEY_LEN_192;
+ default:
+ return CN10K_IPSEC_SA_AES_KEY_LEN_256;
+ }
+}
+
+static void cn10k_outb_prepare_sa(struct xfrm_state *x,
+ struct cn10k_tx_sa_s *sa_entry)
+{
+ int key_len = (x->aead->alg_key_len + 7) / 8;
+ struct net_device *netdev = x->xso.dev;
+ u8 *key = x->aead->alg_key;
+ struct otx2_nic *pf;
+ u32 *tmp_salt;
+ u64 *tmp_key;
+ int idx;
+
+ memset(sa_entry, 0, sizeof(struct cn10k_tx_sa_s));
+
+ /* context size, 128 Byte aligned up */
+ pf = netdev_priv(netdev);
+ sa_entry->ctx_size = (pf->ipsec.sa_size / OTX2_ALIGN) & 0xF;
+ sa_entry->hw_ctx_off = cn10k_ipsec_get_hw_ctx_offset();
+ sa_entry->ctx_push_size = cn10k_ipsec_get_ctx_push_size();
+
+ /* Ucode to skip two words of CPT_CTX_HW_S */
+ sa_entry->ctx_hdr_size = 1;
+
+ /* Allow Atomic operation (AOP) */
+ sa_entry->aop_valid = 1;
+
+ /* Outbound, ESP TRANSPORT/TUNNEL Mode, AES-GCM with */
+ sa_entry->sa_dir = CN10K_IPSEC_SA_DIR_OUTB;
+ sa_entry->ipsec_protocol = CN10K_IPSEC_SA_IPSEC_PROTO_ESP;
+ sa_entry->enc_type = CN10K_IPSEC_SA_ENCAP_TYPE_AES_GCM;
+ sa_entry->iv_src = CN10K_IPSEC_SA_IV_SRC_PACKET;
+ if (x->props.mode == XFRM_MODE_TUNNEL)
+ sa_entry->ipsec_mode = CN10K_IPSEC_SA_IPSEC_MODE_TUNNEL;
+ else
+ sa_entry->ipsec_mode = CN10K_IPSEC_SA_IPSEC_MODE_TRANSPORT;
+
+ /* Last 4 bytes are salt */
+ key_len -= 4;
+ sa_entry->aes_key_len = cn10k_ipsec_get_aes_key_len(key_len);
+ memcpy(sa_entry->cipher_key, key, key_len);
+ tmp_key = (u64 *)sa_entry->cipher_key;
+
+ for (idx = 0; idx < key_len / 8; idx++)
+ tmp_key[idx] = (__force u64)cpu_to_be64(tmp_key[idx]);
+
+ memcpy(&sa_entry->iv_gcm_salt, key + key_len, 4);
+ tmp_salt = (u32 *)&sa_entry->iv_gcm_salt;
+ *tmp_salt = (__force u32)cpu_to_be32(*tmp_salt);
+
+ /* Write SA context data to memory before enabling */
+ wmb();
+
+ /* Enable SA */
+ sa_entry->sa_valid = 1;
+}
+
+static int cn10k_ipsec_validate_state(struct xfrm_state *x,
+ struct netlink_ext_ack *extack)
+{
+ if (x->props.aalgo != SADB_AALG_NONE) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot offload authenticated xfrm states");
+ return -EINVAL;
+ }
+ if (x->props.ealgo != SADB_X_EALG_AES_GCM_ICV16) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Only AES-GCM-ICV16 xfrm state may be offloaded");
+ return -EINVAL;
+ }
+ if (x->props.calgo != SADB_X_CALG_NONE) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot offload compressed xfrm states");
+ return -EINVAL;
+ }
+ if (x->props.flags & XFRM_STATE_ESN) {
+ NL_SET_ERR_MSG_MOD(extack, "Cannot offload ESN xfrm states");
+ return -EINVAL;
+ }
+ if (x->props.family != AF_INET && x->props.family != AF_INET6) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Only IPv4/v6 xfrm states may be offloaded");
+ return -EINVAL;
+ }
+ if (x->xso.type != XFRM_DEV_OFFLOAD_CRYPTO) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot offload other than crypto-mode");
+ return -EINVAL;
+ }
+ if (x->props.mode != XFRM_MODE_TRANSPORT &&
+ x->props.mode != XFRM_MODE_TUNNEL) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Only tunnel/transport xfrm states may be offloaded");
+ return -EINVAL;
+ }
+ if (x->id.proto != IPPROTO_ESP) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Only ESP xfrm state may be offloaded");
+ return -EINVAL;
+ }
+ if (x->encap) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Encapsulated xfrm state may not be offloaded");
+ return -EINVAL;
+ }
+ if (!x->aead) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot offload xfrm states without aead");
+ return -EINVAL;
+ }
+
+ if (x->aead->alg_icv_len != 128) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot offload xfrm states with AEAD ICV length other than 128bit");
+ return -EINVAL;
+ }
+ if (x->aead->alg_key_len != 128 + 32 &&
+ x->aead->alg_key_len != 192 + 32 &&
+ x->aead->alg_key_len != 256 + 32) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot offload xfrm states with AEAD key length other than 128/192/256bit");
+ return -EINVAL;
+ }
+ if (x->tfcpad) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot offload xfrm states with tfc padding");
+ return -EINVAL;
+ }
+ if (!x->geniv) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot offload xfrm states without geniv");
+ return -EINVAL;
+ }
+ if (strcmp(x->geniv, "seqiv")) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "Cannot offload xfrm states with geniv other than seqiv");
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int cn10k_ipsec_inb_add_state(struct xfrm_state *x,
+ struct netlink_ext_ack *extack)
+{
+ NL_SET_ERR_MSG_MOD(extack, "xfrm inbound offload not supported");
+ return -EOPNOTSUPP;
+}
+
+static int cn10k_ipsec_outb_add_state(struct xfrm_state *x,
+ struct netlink_ext_ack *extack)
+{
+ struct net_device *netdev = x->xso.dev;
+ struct cn10k_tx_sa_s *sa_entry;
+ struct qmem *sa_info;
+ struct otx2_nic *pf;
+ int err;
+
+ err = cn10k_ipsec_validate_state(x, extack);
+ if (err)
+ return err;
+
+ pf = netdev_priv(netdev);
+
+ err = qmem_alloc(pf->dev, &sa_info, pf->ipsec.sa_size, OTX2_ALIGN);
+ if (err)
+ return err;
+
+ sa_entry = (struct cn10k_tx_sa_s *)sa_info->base;
+ cn10k_outb_prepare_sa(x, sa_entry);
+
+ err = cn10k_outb_write_sa(pf, sa_info);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(extack, "Error writing outbound SA");
+ qmem_free(pf->dev, sa_info);
+ return err;
+ }
+
+ x->xso.offload_handle = (unsigned long)sa_info;
+ /* Enable static branch when first SA setup */
+ if (!pf->ipsec.outb_sa_count)
+ static_branch_enable(&cn10k_ipsec_sa_enabled);
+ pf->ipsec.outb_sa_count++;
+ return 0;
+}
+
+static int cn10k_ipsec_add_state(struct xfrm_state *x,
+ struct netlink_ext_ack *extack)
+{
+ if (x->xso.dir == XFRM_DEV_OFFLOAD_IN)
+ return cn10k_ipsec_inb_add_state(x, extack);
+ else
+ return cn10k_ipsec_outb_add_state(x, extack);
+}
+
+static void cn10k_ipsec_del_state(struct xfrm_state *x)
+{
+ struct net_device *netdev = x->xso.dev;
+ struct cn10k_tx_sa_s *sa_entry;
+ struct qmem *sa_info;
+ struct otx2_nic *pf;
+ int err;
+
+ if (x->xso.dir == XFRM_DEV_OFFLOAD_IN)
+ return;
+
+ pf = netdev_priv(netdev);
+
+ sa_info = (struct qmem *)x->xso.offload_handle;
+ sa_entry = (struct cn10k_tx_sa_s *)sa_info->base;
+ memset(sa_entry, 0, sizeof(struct cn10k_tx_sa_s));
+ /* Disable SA in CPT h/w */
+ sa_entry->ctx_push_size = cn10k_ipsec_get_ctx_push_size();
+ sa_entry->ctx_size = (pf->ipsec.sa_size / OTX2_ALIGN) & 0xF;
+ sa_entry->aop_valid = 1;
+
+ err = cn10k_outb_write_sa(pf, sa_info);
+ if (err)
+ netdev_err(netdev, "Error (%d) deleting SA\n", err);
+
+ x->xso.offload_handle = 0;
+ qmem_free(pf->dev, sa_info);
+
+ /* If no more SA's then update netdev feature for potential change
+ * in NETIF_F_HW_ESP.
+ */
+ if (!--pf->ipsec.outb_sa_count)
+ queue_work(pf->ipsec.sa_workq, &pf->ipsec.sa_work);
+}
+
+static bool cn10k_ipsec_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
+{
+ if (x->props.family == AF_INET) {
+ /* Offload with IPv4 options is not supported yet */
+ if (ip_hdr(skb)->ihl > 5)
+ return false;
+ } else {
+ /* Offload with IPv6 extension headers is not support yet */
+ if (ipv6_ext_hdr(ipv6_hdr(skb)->nexthdr))
+ return false;
+ }
+ return true;
+}
+
+static const struct xfrmdev_ops cn10k_ipsec_xfrmdev_ops = {
+ .xdo_dev_state_add = cn10k_ipsec_add_state,
+ .xdo_dev_state_delete = cn10k_ipsec_del_state,
+ .xdo_dev_offload_ok = cn10k_ipsec_offload_ok,
+};
+
+static void cn10k_ipsec_sa_wq_handler(struct work_struct *work)
+{
+ struct cn10k_ipsec *ipsec = container_of(work, struct cn10k_ipsec,
+ sa_work);
+ struct otx2_nic *pf = container_of(ipsec, struct otx2_nic, ipsec);
+
+ /* Disable static branch when no more SA enabled */
+ static_branch_disable(&cn10k_ipsec_sa_enabled);
+ rtnl_lock();
+ netdev_update_features(pf->netdev);
+ rtnl_unlock();
+}
+
+int cn10k_ipsec_ethtool_init(struct net_device *netdev, bool enable)
+{
+ struct otx2_nic *pf = netdev_priv(netdev);
+
+ /* IPsec offload supported on cn10k */
+ if (!is_dev_support_ipsec_offload(pf->pdev))
+ return -EOPNOTSUPP;
+
+ /* Initialize CPT for outbound ipsec offload */
+ if (enable)
+ return cn10k_outb_cpt_init(netdev);
+
+ /* Don't do CPT cleanup if SA installed */
+ if (pf->ipsec.outb_sa_count) {
+ netdev_err(pf->netdev, "SA installed on this device\n");
+ return -EBUSY;
+ }
+
+ return cn10k_outb_cpt_clean(pf);
+}
+
+int cn10k_ipsec_init(struct net_device *netdev)
+{
+ struct otx2_nic *pf = netdev_priv(netdev);
+ u32 sa_size;
+
+ if (!is_dev_support_ipsec_offload(pf->pdev))
+ return 0;
+
+ /* Each SA entry size is 128 Byte round up in size */
+ sa_size = sizeof(struct cn10k_tx_sa_s) % OTX2_ALIGN ?
+ (sizeof(struct cn10k_tx_sa_s) / OTX2_ALIGN + 1) *
+ OTX2_ALIGN : sizeof(struct cn10k_tx_sa_s);
+ pf->ipsec.sa_size = sa_size;
+
+ INIT_WORK(&pf->ipsec.sa_work, cn10k_ipsec_sa_wq_handler);
+ pf->ipsec.sa_workq = alloc_workqueue("cn10k_ipsec_sa_workq", 0, 0);
+ if (!pf->ipsec.sa_workq) {
+ netdev_err(pf->netdev, "SA alloc workqueue failed\n");
+ return -ENOMEM;
+ }
+
+ /* Set xfrm device ops */
+ netdev->xfrmdev_ops = &cn10k_ipsec_xfrmdev_ops;
+ netdev->hw_features |= NETIF_F_HW_ESP;
+ netdev->hw_enc_features |= NETIF_F_HW_ESP;
+
+ cn10k_cpt_device_set_unavailable(pf);
+ return 0;
+}
+EXPORT_SYMBOL(cn10k_ipsec_init);
+
+void cn10k_ipsec_clean(struct otx2_nic *pf)
+{
+ if (!is_dev_support_ipsec_offload(pf->pdev))
+ return;
+
+ if (!(pf->flags & OTX2_FLAG_IPSEC_OFFLOAD_ENABLED))
+ return;
+
+ if (pf->ipsec.sa_workq) {
+ destroy_workqueue(pf->ipsec.sa_workq);
+ pf->ipsec.sa_workq = NULL;
+ }
+
+ cn10k_outb_cpt_clean(pf);
+}
+EXPORT_SYMBOL(cn10k_ipsec_clean);
+
+static u16 cn10k_ipsec_get_ip_data_len(struct xfrm_state *x,
+ struct sk_buff *skb)
+{
+ struct ipv6hdr *ipv6h;
+ struct iphdr *iph;
+ u8 *src;
+
+ src = (u8 *)skb->data + ETH_HLEN;
+
+ if (x->props.family == AF_INET) {
+ iph = (struct iphdr *)src;
+ return ntohs(iph->tot_len);
+ }
+
+ ipv6h = (struct ipv6hdr *)src;
+ return ntohs(ipv6h->payload_len) + sizeof(struct ipv6hdr);
+}
+
+/* Prepare CPT and NIX SQE scatter/gather subdescriptor structure.
+ * SG of NIX and CPT are same in size.
+ * Layout of a NIX SQE and CPT SG entry:
+ * -----------------------------
+ * | CPT Scatter Gather |
+ * | (SQE SIZE) |
+ * | |
+ * -----------------------------
+ * | NIX SQE |
+ * | (SQE SIZE) |
+ * | |
+ * -----------------------------
+ */
+bool otx2_sqe_add_sg_ipsec(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
+ struct sk_buff *skb, int num_segs, int *offset)
+{
+ struct cpt_sg_s *cpt_sg = NULL;
+ struct nix_sqe_sg_s *sg = NULL;
+ u64 dma_addr, *iova = NULL;
+ u64 *cpt_iova = NULL;
+ u16 *sg_lens = NULL;
+ int seg, len;
+
+ sq->sg[sq->head].num_segs = 0;
+ cpt_sg = (struct cpt_sg_s *)(sq->sqe_base - sq->sqe_size);
+
+ for (seg = 0; seg < num_segs; seg++) {
+ if ((seg % MAX_SEGS_PER_SG) == 0) {
+ sg = (struct nix_sqe_sg_s *)(sq->sqe_base + *offset);
+ sg->ld_type = NIX_SEND_LDTYPE_LDD;
+ sg->subdc = NIX_SUBDC_SG;
+ sg->segs = 0;
+ sg_lens = (void *)sg;
+ iova = (void *)sg + sizeof(*sg);
+ /* Next subdc always starts at a 16byte boundary.
+ * So if sg->segs is whether 2 or 3, offset += 16bytes.
+ */
+ if ((num_segs - seg) >= (MAX_SEGS_PER_SG - 1))
+ *offset += sizeof(*sg) + (3 * sizeof(u64));
+ else
+ *offset += sizeof(*sg) + sizeof(u64);
+
+ cpt_sg += (seg / MAX_SEGS_PER_SG) * 4;
+ cpt_iova = (void *)cpt_sg + sizeof(*cpt_sg);
+ }
+ dma_addr = otx2_dma_map_skb_frag(pfvf, skb, seg, &len);
+ if (dma_mapping_error(pfvf->dev, dma_addr))
+ return false;
+
+ sg_lens[seg % MAX_SEGS_PER_SG] = len;
+ sg->segs++;
+ *iova++ = dma_addr;
+ *cpt_iova++ = dma_addr;
+
+ /* Save DMA mapping info for later unmapping */
+ sq->sg[sq->head].dma_addr[seg] = dma_addr;
+ sq->sg[sq->head].size[seg] = len;
+ sq->sg[sq->head].num_segs++;
+
+ *cpt_sg = *(struct cpt_sg_s *)sg;
+ cpt_sg->rsvd_63_50 = 0;
+ }
+
+ sq->sg[sq->head].skb = (u64)skb;
+ return true;
+}
+
+static u16 cn10k_ipsec_get_param1(u8 iv_offset)
+{
+ u16 param1_val;
+
+ /* Set Crypto mode, disable L3/L4 checksum */
+ param1_val = CN10K_IPSEC_INST_PARAM1_DIS_L4_CSUM |
+ CN10K_IPSEC_INST_PARAM1_DIS_L3_CSUM;
+ param1_val |= (u16)iv_offset << CN10K_IPSEC_INST_PARAM1_IV_OFFSET_SHIFT;
+ return param1_val;
+}
+
+bool cn10k_ipsec_transmit(struct otx2_nic *pf, struct netdev_queue *txq,
+ struct otx2_snd_queue *sq, struct sk_buff *skb,
+ int num_segs, int size)
+{
+ struct cpt_inst_s inst;
+ struct cpt_res_s *res;
+ struct xfrm_state *x;
+ struct qmem *sa_info;
+ dma_addr_t dptr_iova;
+ struct sec_path *sp;
+ u8 encap_offset;
+ u8 auth_offset;
+ u8 gthr_size;
+ u8 iv_offset;
+ u16 dlen;
+
+ /* Check for IPSEC offload enabled */
+ if (!(pf->flags & OTX2_FLAG_IPSEC_OFFLOAD_ENABLED))
+ goto drop;
+
+ sp = skb_sec_path(skb);
+ if (unlikely(!sp->len))
+ goto drop;
+
+ x = xfrm_input_state(skb);
+ if (unlikely(!x))
+ goto drop;
+
+ if (x->props.mode != XFRM_MODE_TRANSPORT &&
+ x->props.mode != XFRM_MODE_TUNNEL)
+ goto drop;
+
+ dlen = cn10k_ipsec_get_ip_data_len(x, skb);
+ if (dlen == 0 && netif_msg_tx_err(pf)) {
+ netdev_err(pf->netdev, "Invalid IP header, ip-length zero\n");
+ goto drop;
+ }
+
+ /* Check for valid SA context */
+ sa_info = (struct qmem *)x->xso.offload_handle;
+ if (!sa_info)
+ goto drop;
+
+ memset(&inst, 0, sizeof(struct cpt_inst_s));
+
+ /* Get authentication offset */
+ if (x->props.family == AF_INET)
+ auth_offset = sizeof(struct iphdr);
+ else
+ auth_offset = sizeof(struct ipv6hdr);
+
+ /* IV offset is after ESP header */
+ iv_offset = auth_offset + sizeof(struct ip_esp_hdr);
+ /* Encap will start after IV */
+ encap_offset = iv_offset + GCM_RFC4106_IV_SIZE;
+
+ /* CPT Instruction word-1 */
+ res = (struct cpt_res_s *)(sq->cpt_resp->base + (64 * sq->head));
+ res->compcode = 0;
+ inst.res_addr = sq->cpt_resp->iova + (64 * sq->head);
+
+ /* CPT Instruction word-2 */
+ inst.rvu_pf_func = pf->pcifunc;
+
+ /* CPT Instruction word-3:
+ * Set QORD to force CPT_RES_S write completion
+ */
+ inst.qord = 1;
+
+ /* CPT Instruction word-4 */
+ /* inst.dlen should not include ICV length */
+ inst.dlen = dlen + ETH_HLEN - (x->aead->alg_icv_len / 8);
+ inst.opcode_major = CN10K_IPSEC_MAJOR_OP_OUTB_IPSEC;
+ inst.param1 = cn10k_ipsec_get_param1(iv_offset);
+
+ inst.param2 = encap_offset <<
+ CN10K_IPSEC_INST_PARAM2_ENC_DATA_OFFSET_SHIFT;
+ inst.param2 |= (u16)auth_offset <<
+ CN10K_IPSEC_INST_PARAM2_AUTH_DATA_OFFSET_SHIFT;
+
+ /* CPT Instruction word-5 */
+ gthr_size = num_segs / MAX_SEGS_PER_SG;
+ gthr_size = (num_segs % MAX_SEGS_PER_SG) ? gthr_size + 1 : gthr_size;
+
+ gthr_size &= 0xF;
+ dptr_iova = (sq->sqe_ring->iova + (sq->head * (sq->sqe_size * 2)));
+ inst.dptr = dptr_iova | ((u64)gthr_size << 60);
+
+ /* CPT Instruction word-6 */
+ inst.rptr = inst.dptr;
+
+ /* CPT Instruction word-7 */
+ inst.cptr = sa_info->iova;
+ inst.ctx_val = 1;
+ inst.egrp = CN10K_DEF_CPT_IPSEC_EGRP;
+
+ /* CPT Instruction word-0 */
+ inst.nixtxl = (size / 16) - 1;
+ inst.dat_offset = ETH_HLEN;
+ inst.nixtx_offset = sq->sqe_size;
+
+ netdev_tx_sent_queue(txq, skb->len);
+
+ /* Finally Flush the CPT instruction */
+ sq->head++;
+ sq->head &= (sq->sqe_cnt - 1);
+ cn10k_cpt_inst_flush(pf, &inst, sizeof(struct cpt_inst_s));
+ return true;
+drop:
+ dev_kfree_skb_any(skb);
+ return false;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h
new file mode 100644
index 000000000000..9965df0faa3e
--- /dev/null
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_ipsec.h
@@ -0,0 +1,265 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Marvell IPSEC offload driver
+ *
+ * Copyright (C) 2024 Marvell.
+ */
+
+#ifndef CN10K_IPSEC_H
+#define CN10K_IPSEC_H
+
+#include <linux/types.h>
+
+DECLARE_STATIC_KEY_FALSE(cn10k_ipsec_sa_enabled);
+
+/* CPT instruction size in bytes */
+#define CN10K_CPT_INST_SIZE 64
+
+/* CPT instruction (CPT_INST_S) queue length */
+#define CN10K_CPT_INST_QLEN 8200
+
+/* CPT instruction queue size passed to HW is in units of
+ * 40*CPT_INST_S messages.
+ */
+#define CN10K_CPT_SIZE_DIV40 (CN10K_CPT_INST_QLEN / 40)
+
+/* CPT needs 320 free entries */
+#define CN10K_CPT_INST_QLEN_EXTRA_BYTES (320 * CN10K_CPT_INST_SIZE)
+#define CN10K_CPT_EXTRA_SIZE_DIV40 (320 / 40)
+
+/* CPT instruction queue length in bytes */
+#define CN10K_CPT_INST_QLEN_BYTES \
+ ((CN10K_CPT_SIZE_DIV40 * 40 * CN10K_CPT_INST_SIZE) + \
+ CN10K_CPT_INST_QLEN_EXTRA_BYTES)
+
+/* CPT instruction group queue length in bytes */
+#define CN10K_CPT_INST_GRP_QLEN_BYTES \
+ ((CN10K_CPT_SIZE_DIV40 + CN10K_CPT_EXTRA_SIZE_DIV40) * 16)
+
+/* CPT FC length in bytes */
+#define CN10K_CPT_Q_FC_LEN 128
+
+/* Default CPT engine group for ipsec offload */
+#define CN10K_DEF_CPT_IPSEC_EGRP 1
+
+/* CN10K CPT LF registers */
+#define CPT_LFBASE (BLKTYPE_CPT << RVU_FUNC_BLKADDR_SHIFT)
+#define CN10K_CPT_LF_CTL (CPT_LFBASE | 0x10)
+#define CN10K_CPT_LF_INPROG (CPT_LFBASE | 0x40)
+#define CN10K_CPT_LF_Q_BASE (CPT_LFBASE | 0xf0)
+#define CN10K_CPT_LF_Q_SIZE (CPT_LFBASE | 0x100)
+#define CN10K_CPT_LF_Q_INST_PTR (CPT_LFBASE | 0x110)
+#define CN10K_CPT_LF_Q_GRP_PTR (CPT_LFBASE | 0x120)
+#define CN10K_CPT_LF_NQX(a) (CPT_LFBASE | 0x400 | (a) << 3)
+#define CN10K_CPT_LF_CTX_FLUSH (CPT_LFBASE | 0x510)
+
+/* IPSEC Instruction opcodes */
+#define CN10K_IPSEC_MAJOR_OP_WRITE_SA 0x01UL
+#define CN10K_IPSEC_MINOR_OP_WRITE_SA 0x09UL
+#define CN10K_IPSEC_MAJOR_OP_OUTB_IPSEC 0x2AUL
+
+enum cn10k_cpt_comp_e {
+ CN10K_CPT_COMP_E_NOTDONE = 0x00,
+ CN10K_CPT_COMP_E_GOOD = 0x01,
+ CN10K_CPT_COMP_E_FAULT = 0x02,
+ CN10K_CPT_COMP_E_HWERR = 0x04,
+ CN10K_CPT_COMP_E_INSTERR = 0x05,
+ CN10K_CPT_COMP_E_WARN = 0x06,
+ CN10K_CPT_COMP_E_MASK = 0x3F
+};
+
+struct cn10k_cpt_inst_queue {
+ u8 *vaddr;
+ u8 *real_vaddr;
+ dma_addr_t dma_addr;
+ dma_addr_t real_dma_addr;
+ u32 size;
+};
+
+enum cn10k_cpt_hw_state_e {
+ CN10K_CPT_HW_UNAVAILABLE,
+ CN10K_CPT_HW_AVAILABLE,
+ CN10K_CPT_HW_IN_USE
+};
+
+struct cn10k_ipsec {
+ /* Outbound CPT */
+ u64 io_addr;
+ atomic_t cpt_state;
+ struct cn10k_cpt_inst_queue iq;
+
+ /* SA info */
+ u32 sa_size;
+ u32 outb_sa_count;
+ struct work_struct sa_work;
+ struct workqueue_struct *sa_workq;
+};
+
+/* CN10K IPSEC Security Association (SA) */
+/* SA direction */
+#define CN10K_IPSEC_SA_DIR_INB 0
+#define CN10K_IPSEC_SA_DIR_OUTB 1
+/* SA protocol */
+#define CN10K_IPSEC_SA_IPSEC_PROTO_AH 0
+#define CN10K_IPSEC_SA_IPSEC_PROTO_ESP 1
+/* SA Encryption Type */
+#define CN10K_IPSEC_SA_ENCAP_TYPE_AES_GCM 5
+/* SA IPSEC mode Transport/Tunnel */
+#define CN10K_IPSEC_SA_IPSEC_MODE_TRANSPORT 0
+#define CN10K_IPSEC_SA_IPSEC_MODE_TUNNEL 1
+/* SA AES Key Length */
+#define CN10K_IPSEC_SA_AES_KEY_LEN_128 1
+#define CN10K_IPSEC_SA_AES_KEY_LEN_192 2
+#define CN10K_IPSEC_SA_AES_KEY_LEN_256 3
+/* IV Source */
+#define CN10K_IPSEC_SA_IV_SRC_COUNTER 0
+#define CN10K_IPSEC_SA_IV_SRC_PACKET 3
+
+struct cn10k_tx_sa_s {
+ u64 esn_en : 1; /* W0 */
+ u64 rsvd_w0_1_8 : 8;
+ u64 hw_ctx_off : 7;
+ u64 ctx_id : 16;
+ u64 rsvd_w0_32_47 : 16;
+ u64 ctx_push_size : 7;
+ u64 rsvd_w0_55 : 1;
+ u64 ctx_hdr_size : 2;
+ u64 aop_valid : 1;
+ u64 rsvd_w0_59 : 1;
+ u64 ctx_size : 4;
+ u64 w1; /* W1 */
+ u64 sa_valid : 1; /* W2 */
+ u64 sa_dir : 1;
+ u64 rsvd_w2_2_3 : 2;
+ u64 ipsec_mode : 1;
+ u64 ipsec_protocol : 1;
+ u64 aes_key_len : 2;
+ u64 enc_type : 3;
+ u64 rsvd_w2_11_19 : 9;
+ u64 iv_src : 2;
+ u64 rsvd_w2_22_31 : 10;
+ u64 rsvd_w2_32_63 : 32;
+ u64 w3; /* W3 */
+ u8 cipher_key[32]; /* W4 - W7 */
+ u32 rsvd_w8_0_31; /* W8 : IV */
+ u32 iv_gcm_salt;
+ u64 rsvd_w9_w30[22]; /* W9 - W30 */
+ u64 hw_ctx[6]; /* W31 - W36 */
+};
+
+/* CPT instruction parameter-1 */
+#define CN10K_IPSEC_INST_PARAM1_DIS_L4_CSUM 0x1
+#define CN10K_IPSEC_INST_PARAM1_DIS_L3_CSUM 0x2
+#define CN10K_IPSEC_INST_PARAM1_CRYPTO_MODE 0x20
+#define CN10K_IPSEC_INST_PARAM1_IV_OFFSET_SHIFT 8
+
+/* CPT instruction parameter-2 */
+#define CN10K_IPSEC_INST_PARAM2_ENC_DATA_OFFSET_SHIFT 0
+#define CN10K_IPSEC_INST_PARAM2_AUTH_DATA_OFFSET_SHIFT 8
+
+/* CPT Instruction Structure */
+struct cpt_inst_s {
+ u64 nixtxl : 3; /* W0 */
+ u64 doneint : 1;
+ u64 rsvd_w0_4_15 : 12;
+ u64 dat_offset : 8;
+ u64 ext_param1 : 8;
+ u64 nixtx_offset : 20;
+ u64 rsvd_w0_52_63 : 12;
+ u64 res_addr; /* W1 */
+ u64 tag : 32; /* W2 */
+ u64 tt : 2;
+ u64 grp : 10;
+ u64 rsvd_w2_44_47 : 4;
+ u64 rvu_pf_func : 16;
+ u64 qord : 1; /* W3 */
+ u64 rsvd_w3_1_2 : 2;
+ u64 wqe_ptr : 61;
+ u64 dlen : 16; /* W4 */
+ u64 param2 : 16;
+ u64 param1 : 16;
+ u64 opcode_major : 8;
+ u64 opcode_minor : 8;
+ u64 dptr; /* W5 */
+ u64 rptr; /* W6 */
+ u64 cptr : 60; /* W7 */
+ u64 ctx_val : 1;
+ u64 egrp : 3;
+};
+
+/* CPT Instruction Result Structure */
+struct cpt_res_s {
+ u64 compcode : 7; /* W0 */
+ u64 doneint : 1;
+ u64 uc_compcode : 8;
+ u64 uc_info : 48;
+ u64 esn; /* W1 */
+};
+
+/* CPT SG structure */
+struct cpt_sg_s {
+ u64 seg1_size : 16;
+ u64 seg2_size : 16;
+ u64 seg3_size : 16;
+ u64 segs : 2;
+ u64 rsvd_63_50 : 14;
+};
+
+/* CPT LF_INPROG Register */
+#define CPT_LF_INPROG_INFLIGHT GENMASK_ULL(8, 0)
+#define CPT_LF_INPROG_GRB_CNT GENMASK_ULL(39, 32)
+#define CPT_LF_INPROG_GWB_CNT GENMASK_ULL(47, 40)
+
+/* CPT LF_Q_GRP_PTR Register */
+#define CPT_LF_Q_GRP_PTR_DQ_PTR GENMASK_ULL(14, 0)
+#define CPT_LF_Q_GRP_PTR_NQ_PTR GENMASK_ULL(46, 32)
+
+/* CPT LF_Q_SIZE Register */
+#define CPT_LF_Q_BASE_ADDR GENMASK_ULL(52, 7)
+
+/* CPT LF_Q_SIZE Register */
+#define CPT_LF_Q_SIZE_DIV40 GENMASK_ULL(14, 0)
+
+/* CPT LF CTX Flush Register */
+#define CPT_LF_CTX_FLUSH GENMASK_ULL(45, 0)
+
+#ifdef CONFIG_XFRM_OFFLOAD
+int cn10k_ipsec_init(struct net_device *netdev);
+void cn10k_ipsec_clean(struct otx2_nic *pf);
+int cn10k_ipsec_ethtool_init(struct net_device *netdev, bool enable);
+bool otx2_sqe_add_sg_ipsec(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
+ struct sk_buff *skb, int num_segs, int *offset);
+bool cn10k_ipsec_transmit(struct otx2_nic *pf, struct netdev_queue *txq,
+ struct otx2_snd_queue *sq, struct sk_buff *skb,
+ int num_segs, int size);
+#else
+static inline __maybe_unused int cn10k_ipsec_init(struct net_device *netdev)
+{
+ return 0;
+}
+
+static inline __maybe_unused void cn10k_ipsec_clean(struct otx2_nic *pf)
+{
+}
+
+static inline __maybe_unused
+int cn10k_ipsec_ethtool_init(struct net_device *netdev, bool enable)
+{
+ return 0;
+}
+
+static inline bool __maybe_unused
+otx2_sqe_add_sg_ipsec(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
+ struct sk_buff *skb, int num_segs, int *offset)
+{
+ return true;
+}
+
+static inline bool __maybe_unused
+cn10k_ipsec_transmit(struct otx2_nic *pf, struct netdev_queue *txq,
+ struct otx2_snd_queue *sq, struct sk_buff *skb,
+ int num_segs, int size)
+{
+ return true;
+}
+#endif
+#endif // CN10K_IPSEC_H
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
index 6cc7a78968fc..f3b9daffaec3 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/cn10k_macsec.c
@@ -133,9 +133,7 @@ static const char *rsrc_name(enum mcs_rsrc_type rsrc_type)
return "SA";
default:
return "Unknown";
- };
-
- return "Unknown";
+ }
}
static int cn10k_mcs_alloc_rsrc(struct otx2_nic *pfvf, enum mcs_direction dir,
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
index 523ecb798a7a..2b49bfec7869 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.c
@@ -10,12 +10,19 @@
#include <net/page_pool/helpers.h>
#include <net/tso.h>
#include <linux/bitfield.h>
+#include <linux/dcbnl.h>
+#include <net/xfrm.h>
#include "otx2_reg.h"
#include "otx2_common.h"
#include "otx2_struct.h"
#include "cn10k.h"
+static bool otx2_is_pfc_enabled(struct otx2_nic *pfvf)
+{
+ return IS_ENABLED(CONFIG_DCB) && !!pfvf->pfc_en;
+}
+
static void otx2_nix_rq_op_stats(struct queue_stats *stats,
struct otx2_nic *pfvf, int qidx)
{
@@ -964,6 +971,29 @@ int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura)
if (err)
return err;
+ /* Allocate memory for NIX SQE (which includes NIX SG) and CPT SG.
+ * SG of NIX and CPT are same in size. Allocate memory for CPT SG
+ * same as NIX SQE for base address alignment.
+ * Layout of a NIX SQE and CPT SG entry:
+ * -----------------------------
+ * | CPT Scatter Gather |
+ * | (SQE SIZE) |
+ * | |
+ * -----------------------------
+ * | NIX SQE |
+ * | (SQE SIZE) |
+ * | |
+ * -----------------------------
+ */
+ err = qmem_alloc(pfvf->dev, &sq->sqe_ring, qset->sqe_cnt,
+ sq->sqe_size * 2);
+ if (err)
+ return err;
+
+ err = qmem_alloc(pfvf->dev, &sq->cpt_resp, qset->sqe_cnt, 64);
+ if (err)
+ return err;
+
if (qidx < pfvf->hw.tx_queues) {
err = qmem_alloc(pfvf->dev, &sq->tso_hdrs, qset->sqe_cnt,
TSO_HEADER_SIZE);
@@ -1722,18 +1752,43 @@ int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable)
return -ENOMEM;
req->chan_base = 0;
-#ifdef CONFIG_DCB
- req->chan_cnt = pfvf->pfc_en ? IEEE_8021QAZ_MAX_TCS : 1;
- req->bpid_per_chan = pfvf->pfc_en ? 1 : 0;
-#else
- req->chan_cnt = 1;
- req->bpid_per_chan = 0;
-#endif
+ if (otx2_is_pfc_enabled(pfvf)) {
+ req->chan_cnt = IEEE_8021QAZ_MAX_TCS;
+ req->bpid_per_chan = 1;
+ } else {
+ req->chan_cnt = 1;
+ req->bpid_per_chan = 0;
+ }
return otx2_sync_mbox_msg(&pfvf->mbox);
}
EXPORT_SYMBOL(otx2_nix_config_bp);
+int otx2_nix_cpt_config_bp(struct otx2_nic *pfvf, bool enable)
+{
+ struct nix_bp_cfg_req *req;
+
+ if (enable)
+ req = otx2_mbox_alloc_msg_nix_cpt_bp_enable(&pfvf->mbox);
+ else
+ req = otx2_mbox_alloc_msg_nix_cpt_bp_disable(&pfvf->mbox);
+
+ if (!req)
+ return -ENOMEM;
+
+ req->chan_base = 0;
+ if (otx2_is_pfc_enabled(pfvf)) {
+ req->chan_cnt = IEEE_8021QAZ_MAX_TCS;
+ req->bpid_per_chan = 1;
+ } else {
+ req->chan_cnt = 1;
+ req->bpid_per_chan = 0;
+ }
+
+ return otx2_sync_mbox_msg(&pfvf->mbox);
+}
+EXPORT_SYMBOL(otx2_nix_cpt_config_bp);
+
/* Mbox message handlers */
void mbox_handler_cgx_stats(struct otx2_nic *pfvf,
struct cgx_stats_rsp *rsp)
@@ -1947,3 +2002,48 @@ EXPORT_SYMBOL(otx2_mbox_up_handler_ ## _fn_name);
MBOX_UP_CGX_MESSAGES
MBOX_UP_MCS_MESSAGES
#undef M
+
+dma_addr_t otx2_dma_map_skb_frag(struct otx2_nic *pfvf,
+ struct sk_buff *skb, int seg, int *len)
+{
+ enum dma_data_direction dir = DMA_TO_DEVICE;
+ const skb_frag_t *frag;
+ struct page *page;
+ int offset;
+
+ /* Crypto hardware need write permission for ipsec crypto offload */
+ if (unlikely(xfrm_offload(skb))) {
+ dir = DMA_BIDIRECTIONAL;
+ skb = skb_unshare(skb, GFP_ATOMIC);
+ }
+
+ /* First segment is always skb->data */
+ if (!seg) {
+ page = virt_to_page(skb->data);
+ offset = offset_in_page(skb->data);
+ *len = skb_headlen(skb);
+ } else {
+ frag = &skb_shinfo(skb)->frags[seg - 1];
+ page = skb_frag_page(frag);
+ offset = skb_frag_off(frag);
+ *len = skb_frag_size(frag);
+ }
+ return otx2_dma_map_page(pfvf, page, offset, *len, dir);
+}
+
+void otx2_dma_unmap_skb_frags(struct otx2_nic *pfvf, struct sg_list *sg)
+{
+ enum dma_data_direction dir = DMA_TO_DEVICE;
+ struct sk_buff *skb = NULL;
+ int seg;
+
+ skb = (struct sk_buff *)sg->skb;
+ if (unlikely(xfrm_offload(skb)))
+ dir = DMA_BIDIRECTIONAL;
+
+ for (seg = 0; seg < sg->num_segs; seg++) {
+ otx2_dma_unmap_page(pfvf, sg->dma_addr[seg],
+ sg->size[seg], dir);
+ }
+ sg->num_segs = 0;
+}
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
index 566848663fea..65814e3dc93f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_common.h
@@ -30,6 +30,7 @@
#include <rvu_trace.h>
#include "qos.h"
#include "rep.h"
+#include "cn10k_ipsec.h"
/* IPv4 flag more fragment bit */
#define IPV4_FLAG_MORE 0x20
@@ -40,6 +41,7 @@
#define PCI_DEVID_OCTEONTX2_RVU_AFVF 0xA0F8
#define PCI_SUBSYS_DEVID_96XX_RVU_PFVF 0xB200
+#define PCI_SUBSYS_DEVID_CN10K_A_RVU_PFVF 0xB900
#define PCI_SUBSYS_DEVID_CN10K_B_RVU_PFVF 0xBD00
#define PCI_DEVID_OCTEONTX2_SDP_REP 0xA0F7
@@ -55,6 +57,9 @@
#define NIX_PF_PFC_PRIO_MAX 8
#endif
+/* Number of segments per SG structure */
+#define MAX_SEGS_PER_SG 3
+
enum arua_mapped_qtypes {
AURA_NIX_RQ,
AURA_NIX_SQ,
@@ -448,6 +453,7 @@ struct otx2_nic {
#define OTX2_FLAG_TC_MARK_ENABLED BIT_ULL(17)
#define OTX2_FLAG_REP_MODE_ENABLED BIT_ULL(18)
#define OTX2_FLAG_PORT_UP BIT_ULL(19)
+#define OTX2_FLAG_IPSEC_OFFLOAD_ENABLED BIT_ULL(20)
u64 flags;
u64 *cq_op_addr;
@@ -499,9 +505,9 @@ struct otx2_nic {
/* Devlink */
struct otx2_devlink *dl;
-#ifdef CONFIG_DCB
/* PFC */
u8 pfc_en;
+#ifdef CONFIG_DCB
u8 *queue_to_pfc_map;
u16 pfc_schq_list[NIX_TXSCH_LVL_CNT][MAX_TXSCHQ_PER_FUNC];
bool pfc_alloc_status[NIX_PF_PFC_PRIO_MAX];
@@ -522,6 +528,9 @@ struct otx2_nic {
u16 rep_pf_map[RVU_MAX_REP];
u16 esw_mode;
#endif
+
+ /* Inline ipsec */
+ struct cn10k_ipsec ipsec;
};
static inline bool is_otx2_lbkvf(struct pci_dev *pdev)
@@ -572,6 +581,15 @@ static inline bool is_dev_cn10kb(struct pci_dev *pdev)
return pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_B_RVU_PFVF;
}
+static inline bool is_dev_cn10ka_b0(struct pci_dev *pdev)
+{
+ if (pdev->subsystem_device == PCI_SUBSYS_DEVID_CN10K_A_RVU_PFVF &&
+ (pdev->revision & 0xFF) == 0x54)
+ return true;
+
+ return false;
+}
+
static inline void otx2_setup_dev_hw_settings(struct otx2_nic *pfvf)
{
struct otx2_hw *hw = &pfvf->hw;
@@ -621,6 +639,9 @@ static inline void __iomem *otx2_get_regaddr(struct otx2_nic *nic, u64 offset)
case BLKTYPE_NPA:
blkaddr = BLKADDR_NPA;
break;
+ case BLKTYPE_CPT:
+ blkaddr = BLKADDR_CPT0;
+ break;
default:
blkaddr = BLKADDR_RVUM;
break;
@@ -985,6 +1006,7 @@ int otx2_alloc_rbuf(struct otx2_nic *pfvf, struct otx2_pool *pool,
int otx2_rxtx_enable(struct otx2_nic *pfvf, bool enable);
void otx2_ctx_disable(struct mbox *mbox, int type, bool npa);
int otx2_nix_config_bp(struct otx2_nic *pfvf, bool enable);
+int otx2_nix_cpt_config_bp(struct otx2_nic *pfvf, bool enable);
void otx2_cleanup_rx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq, int qidx);
void otx2_cleanup_tx_cqes(struct otx2_nic *pfvf, struct otx2_cq_queue *cq);
int otx2_sq_init(struct otx2_nic *pfvf, u16 qidx, u16 sqb_aura);
@@ -1149,4 +1171,8 @@ static inline int mcam_entry_cmp(const void *a, const void *b)
{
return *(u16 *)a - *(u16 *)b;
}
+
+dma_addr_t otx2_dma_map_skb_frag(struct otx2_nic *pfvf,
+ struct sk_buff *skb, int seg, int *len);
+void otx2_dma_unmap_skb_frags(struct otx2_nic *pfvf, struct sg_list *sg);
#endif /* OTX2_COMMON_H */
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
index 294fba58b670..f110dfa42360 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_dcbnl.c
@@ -435,6 +435,9 @@ process_pfc:
return err;
}
+ /* Default disable backpressure on NIX-CPT */
+ otx2_nix_cpt_config_bp(pfvf, false);
+
/* Request Per channel Bpids */
if (pfc->pfc_en)
otx2_nix_config_bp(pfvf, true);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
index e310f99b1736..e1dde93e8af8 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_pf.c
@@ -26,6 +26,7 @@
#include "cn10k.h"
#include "qos.h"
#include <rvu_trace.h>
+#include "cn10k_ipsec.h"
#define DRV_NAME "rvu_nicpf"
#define DRV_STRING "Marvell RVU NIC Physical Function Driver"
@@ -1484,6 +1485,8 @@ static void otx2_free_sq_res(struct otx2_nic *pf)
if (!sq->sqe)
continue;
qmem_free(pf->dev, sq->sqe);
+ qmem_free(pf->dev, sq->sqe_ring);
+ qmem_free(pf->dev, sq->cpt_resp);
qmem_free(pf->dev, sq->tso_hdrs);
kfree(sq->sg);
kfree(sq->sqb_ptrs);
@@ -1551,6 +1554,9 @@ int otx2_init_hw_resources(struct otx2_nic *pf)
if (err)
goto err_free_npa_lf;
+ /* Default disable backpressure on NIX-CPT */
+ otx2_nix_cpt_config_bp(pf, false);
+
/* Enable backpressure for CGX mapped PF/VFs */
if (!is_otx2_lbkvf(pf->pdev))
otx2_nix_config_bp(pf, true);
@@ -2273,6 +2279,10 @@ static int otx2_set_features(struct net_device *netdev,
return otx2_enable_rxvlan(pf,
features & NETIF_F_HW_VLAN_CTAG_RX);
+ if (changed & NETIF_F_HW_ESP)
+ return cn10k_ipsec_ethtool_init(netdev,
+ features & NETIF_F_HW_ESP);
+
return otx2_handle_ntuple_tc_features(netdev, features);
}
@@ -3162,10 +3172,14 @@ static int otx2_probe(struct pci_dev *pdev, const struct pci_device_id *id)
/* reset CGX/RPM MAC stats */
otx2_reset_mac_stats(pf);
+ err = cn10k_ipsec_init(netdev);
+ if (err)
+ goto err_mcs_free;
+
err = register_netdev(netdev);
if (err) {
dev_err(dev, "Failed to register netdevice\n");
- goto err_mcs_free;
+ goto err_ipsec_clean;
}
err = otx2_wq_init(pf);
@@ -3206,6 +3220,8 @@ err_mcam_flow_del:
otx2_mcam_flow_del(pf);
err_unreg_netdev:
unregister_netdev(netdev);
+err_ipsec_clean:
+ cn10k_ipsec_clean(pf);
err_mcs_free:
cn10k_mcs_free(pf);
err_del_mcam_entries:
@@ -3403,6 +3419,7 @@ static void otx2_remove(struct pci_dev *pdev)
otx2_unregister_dl(pf);
unregister_netdev(netdev);
+ cn10k_ipsec_clean(pf);
cn10k_mcs_free(pf);
otx2_sriov_disable(pf->pdev);
otx2_sriov_vfcfg_cleanup(pf);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
index 04bc06a80e23..224cef938927 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.c
@@ -11,6 +11,7 @@
#include <linux/bpf.h>
#include <linux/bpf_trace.h>
#include <net/ip6_checksum.h>
+#include <net/xfrm.h>
#include "otx2_reg.h"
#include "otx2_common.h"
@@ -26,12 +27,25 @@
*/
#define PTP_SYNC_SEC_OFFSET 34
+DEFINE_STATIC_KEY_FALSE(cn10k_ipsec_sa_enabled);
+
static bool otx2_xdp_rcv_pkt_handler(struct otx2_nic *pfvf,
struct bpf_prog *prog,
struct nix_cqe_rx_s *cqe,
struct otx2_cq_queue *cq,
bool *need_xdp_flush);
+static void otx2_sq_set_sqe_base(struct otx2_snd_queue *sq,
+ struct sk_buff *skb)
+{
+ if (static_branch_unlikely(&cn10k_ipsec_sa_enabled) &&
+ (xfrm_offload(skb)))
+ sq->sqe_base = sq->sqe_ring->base + sq->sqe_size +
+ (sq->head * (sq->sqe_size * 2));
+ else
+ sq->sqe_base = sq->sqe->base;
+}
+
static int otx2_nix_cq_op_status(struct otx2_nic *pfvf,
struct otx2_cq_queue *cq)
{
@@ -80,38 +94,6 @@ static unsigned int frag_num(unsigned int i)
#endif
}
-static dma_addr_t otx2_dma_map_skb_frag(struct otx2_nic *pfvf,
- struct sk_buff *skb, int seg, int *len)
-{
- const skb_frag_t *frag;
- struct page *page;
- int offset;
-
- /* First segment is always skb->data */
- if (!seg) {
- page = virt_to_page(skb->data);
- offset = offset_in_page(skb->data);
- *len = skb_headlen(skb);
- } else {
- frag = &skb_shinfo(skb)->frags[seg - 1];
- page = skb_frag_page(frag);
- offset = skb_frag_off(frag);
- *len = skb_frag_size(frag);
- }
- return otx2_dma_map_page(pfvf, page, offset, *len, DMA_TO_DEVICE);
-}
-
-static void otx2_dma_unmap_skb_frags(struct otx2_nic *pfvf, struct sg_list *sg)
-{
- int seg;
-
- for (seg = 0; seg < sg->num_segs; seg++) {
- otx2_dma_unmap_page(pfvf, sg->dma_addr[seg],
- sg->size[seg], DMA_TO_DEVICE);
- }
- sg->num_segs = 0;
-}
-
static void otx2_xdp_snd_pkt_handler(struct otx2_nic *pfvf,
struct otx2_snd_queue *sq,
struct nix_cqe_tx_s *cqe)
@@ -625,7 +607,6 @@ void otx2_sqe_flush(void *dev, struct otx2_snd_queue *sq,
sq->head &= (sq->sqe_cnt - 1);
}
-#define MAX_SEGS_PER_SG 3
/* Add SQE scatter/gather subdescriptor structure */
static bool otx2_sqe_add_sg(struct otx2_nic *pfvf, struct otx2_snd_queue *sq,
struct sk_buff *skb, int num_segs, int *offset)
@@ -1161,6 +1142,7 @@ bool otx2_sq_append_skb(void *dev, struct netdev_queue *txq,
int offset, num_segs, free_desc;
struct nix_sqe_hdr_s *sqe_hdr;
struct otx2_nic *pfvf = dev;
+ bool ret;
/* Check if there is enough room between producer
* and consumer index.
@@ -1177,6 +1159,7 @@ bool otx2_sq_append_skb(void *dev, struct netdev_queue *txq,
/* If SKB doesn't fit in a single SQE, linearize it.
* TODO: Consider adding JUMP descriptor instead.
*/
+
if (unlikely(num_segs > OTX2_MAX_FRAGS_IN_SQE)) {
if (__skb_linearize(skb)) {
dev_kfree_skb_any(skb);
@@ -1196,6 +1179,9 @@ bool otx2_sq_append_skb(void *dev, struct netdev_queue *txq,
return true;
}
+ /* Set sqe base address */
+ otx2_sq_set_sqe_base(sq, skb);
+
/* Set SQE's SEND_HDR.
* Do not clear the first 64bit as it contains constant info.
*/
@@ -1208,7 +1194,13 @@ bool otx2_sq_append_skb(void *dev, struct netdev_queue *txq,
otx2_sqe_add_ext(pfvf, sq, skb, &offset);
/* Add SG subdesc with data frags */
- if (!otx2_sqe_add_sg(pfvf, sq, skb, num_segs, &offset)) {
+ if (static_branch_unlikely(&cn10k_ipsec_sa_enabled) &&
+ (xfrm_offload(skb)))
+ ret = otx2_sqe_add_sg_ipsec(pfvf, sq, skb, num_segs, &offset);
+ else
+ ret = otx2_sqe_add_sg(pfvf, sq, skb, num_segs, &offset);
+
+ if (!ret) {
otx2_dma_unmap_skb_frags(pfvf, &sq->sg[sq->head]);
return false;
}
@@ -1217,11 +1209,15 @@ bool otx2_sq_append_skb(void *dev, struct netdev_queue *txq,
sqe_hdr->sizem1 = (offset / 16) - 1;
+ if (static_branch_unlikely(&cn10k_ipsec_sa_enabled) &&
+ (xfrm_offload(skb)))
+ return cn10k_ipsec_transmit(pfvf, txq, sq, skb, num_segs,
+ offset);
+
netdev_tx_sent_queue(txq, skb->len);
/* Flush SQE to HW */
pfvf->hw_ops->sqe_flush(pfvf, sq, offset, qidx);
-
return true;
}
EXPORT_SYMBOL(otx2_sq_append_skb);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
index e1db5f961877..d23810963fdb 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_txrx.h
@@ -101,6 +101,9 @@ struct otx2_snd_queue {
struct queue_stats stats;
u16 sqb_count;
u64 *sqb_ptrs;
+ /* SQE ring and CPT response queue for Inline IPSEC */
+ struct qmem *sqe_ring;
+ struct qmem *cpt_resp;
} ____cacheline_aligned_in_smp;
enum cq_type {
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
index 839fc77c11b2..e926c6ce96cf 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_vf.c
@@ -14,6 +14,7 @@
#include "otx2_reg.h"
#include "otx2_ptp.h"
#include "cn10k.h"
+#include "cn10k_ipsec.h"
#define DRV_NAME "rvu_nicvf"
#define DRV_STRING "Marvell RVU NIC Virtual Function Driver"
@@ -693,10 +694,14 @@ static int otx2vf_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pdev->bus->number, n);
}
+ err = cn10k_ipsec_init(netdev);
+ if (err)
+ goto err_ptp_destroy;
+
err = register_netdev(netdev);
if (err) {
dev_err(dev, "Failed to register netdevice\n");
- goto err_ptp_destroy;
+ goto err_ipsec_clean;
}
err = otx2_vf_wq_init(vf);
@@ -730,6 +735,8 @@ err_shutdown_tc:
otx2_shutdown_tc(vf);
err_unreg_netdev:
unregister_netdev(netdev);
+err_ipsec_clean:
+ cn10k_ipsec_clean(vf);
err_ptp_destroy:
otx2_ptp_destroy(vf);
err_detach_rsrc:
@@ -782,6 +789,7 @@ static void otx2vf_remove(struct pci_dev *pdev)
unregister_netdev(netdev);
if (vf->otx2_wq)
destroy_workqueue(vf->otx2_wq);
+ cn10k_ipsec_clean(vf);
otx2_ptp_destroy(vf);
otx2_mcam_flow_del(vf);
otx2_shutdown_tc(vf);
diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
index 232b10740c13..04e08e06f30f 100644
--- a/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
+++ b/drivers/net/ethernet/marvell/octeontx2/nic/rep.c
@@ -680,14 +680,17 @@ int rvu_rep_create(struct otx2_nic *priv, struct netlink_ext_ack *extack)
ndev->features |= ndev->hw_features;
eth_hw_addr_random(ndev);
err = rvu_rep_devlink_port_register(rep);
- if (err)
+ if (err) {
+ free_netdev(ndev);
goto exit;
+ }
SET_NETDEV_DEVLINK_PORT(ndev, &rep->dl_port);
err = register_netdev(ndev);
if (err) {
NL_SET_ERR_MSG_MOD(extack,
"PFVF representor registration failed");
+ rvu_rep_devlink_port_unregister(rep);
free_netdev(ndev);
goto exit;
}
diff --git a/drivers/net/ethernet/marvell/sky2.c b/drivers/net/ethernet/marvell/sky2.c
index 3914cd9210d4..988fa28cfb5f 100644
--- a/drivers/net/ethernet/marvell/sky2.c
+++ b/drivers/net/ethernet/marvell/sky2.c
@@ -130,6 +130,7 @@ static const struct pci_device_id sky2_id_table[] = {
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436C) }, /* 88E8072 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x436D) }, /* 88E8055 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4370) }, /* 88E8075 */
+ { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4373) }, /* 88E8075 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4380) }, /* 88E8057 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4381) }, /* 88E8059 */
{ PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4382) }, /* 88E8079 */
diff --git a/drivers/net/ethernet/mediatek/airoha_eth.c b/drivers/net/ethernet/mediatek/airoha_eth.c
index 6c683a12d5aa..b9f1c42f0a40 100644
--- a/drivers/net/ethernet/mediatek/airoha_eth.c
+++ b/drivers/net/ethernet/mediatek/airoha_eth.c
@@ -15,6 +15,7 @@
#include <linux/u64_stats_sync.h>
#include <net/dsa.h>
#include <net/page_pool/helpers.h>
+#include <net/pkt_cls.h>
#include <uapi/linux/ppp_defs.h>
#define AIROHA_MAX_NUM_GDM_PORTS 1
@@ -23,8 +24,12 @@
#define AIROHA_MAX_NUM_XSI_RSTS 5
#define AIROHA_MAX_MTU 2000
#define AIROHA_MAX_PACKET_SIZE 2048
+#define AIROHA_NUM_QOS_CHANNELS 4
+#define AIROHA_NUM_QOS_QUEUES 8
#define AIROHA_NUM_TX_RING 32
#define AIROHA_NUM_RX_RING 32
+#define AIROHA_NUM_NETDEV_TX_RINGS (AIROHA_NUM_TX_RING + \
+ AIROHA_NUM_QOS_CHANNELS)
#define AIROHA_FE_MC_MAX_VLAN_TABLE 64
#define AIROHA_FE_MC_MAX_VLAN_PORT 16
#define AIROHA_NUM_TX_IRQ 2
@@ -40,6 +45,9 @@
#define PSE_RSV_PAGES 128
#define PSE_QUEUE_RSV_PAGES 64
+#define QDMA_METER_IDX(_n) ((_n) & 0xff)
+#define QDMA_METER_GROUP(_n) (((_n) >> 8) & 0x3)
+
/* FE */
#define PSE_BASE 0x0100
#define CSR_IFC_BASE 0x0200
@@ -541,9 +549,24 @@
#define INGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16)
#define INGRESS_FAST_TICK_MASK GENMASK(15, 0)
+#define REG_QUEUE_CLOSE_CFG(_n) (0x00a0 + ((_n) & 0xfc))
+#define TXQ_DISABLE_CHAN_QUEUE_MASK(_n, _m) BIT((_m) + (((_n) & 0x3) << 3))
+
#define REG_TXQ_DIS_CFG_BASE(_n) ((_n) ? 0x20a0 : 0x00a0)
#define REG_TXQ_DIS_CFG(_n, _m) (REG_TXQ_DIS_CFG_BASE((_n)) + (_m) << 2)
+#define REG_CNTR_CFG(_n) (0x0400 + ((_n) << 3))
+#define CNTR_EN_MASK BIT(31)
+#define CNTR_ALL_CHAN_EN_MASK BIT(30)
+#define CNTR_ALL_QUEUE_EN_MASK BIT(29)
+#define CNTR_ALL_DSCP_RING_EN_MASK BIT(28)
+#define CNTR_SRC_MASK GENMASK(27, 24)
+#define CNTR_DSCP_RING_MASK GENMASK(20, 16)
+#define CNTR_CHAN_MASK GENMASK(7, 3)
+#define CNTR_QUEUE_MASK GENMASK(2, 0)
+
+#define REG_CNTR_VAL(_n) (0x0404 + ((_n) << 3))
+
#define REG_LMGR_INIT_CFG 0x1000
#define LMGR_INIT_START BIT(31)
#define LMGR_SRAM_MODE_MASK BIT(30)
@@ -565,13 +588,34 @@
#define EGRESS_SLOW_TICK_RATIO_MASK GENMASK(29, 16)
#define EGRESS_FAST_TICK_MASK GENMASK(15, 0)
+#define TRTCM_PARAM_RW_MASK BIT(31)
+#define TRTCM_PARAM_RW_DONE_MASK BIT(30)
+#define TRTCM_PARAM_TYPE_MASK GENMASK(29, 28)
+#define TRTCM_METER_GROUP_MASK GENMASK(27, 26)
+#define TRTCM_PARAM_INDEX_MASK GENMASK(23, 17)
+#define TRTCM_PARAM_RATE_TYPE_MASK BIT(16)
+
+#define REG_TRTCM_CFG_PARAM(_n) ((_n) + 0x4)
+#define REG_TRTCM_DATA_LOW(_n) ((_n) + 0x8)
+#define REG_TRTCM_DATA_HIGH(_n) ((_n) + 0xc)
+
#define REG_TXWRR_MODE_CFG 0x1020
#define TWRR_WEIGHT_SCALE_MASK BIT(31)
#define TWRR_WEIGHT_BASE_MASK BIT(3)
+#define REG_TXWRR_WEIGHT_CFG 0x1024
+#define TWRR_RW_CMD_MASK BIT(31)
+#define TWRR_RW_CMD_DONE BIT(30)
+#define TWRR_CHAN_IDX_MASK GENMASK(23, 19)
+#define TWRR_QUEUE_IDX_MASK GENMASK(18, 16)
+#define TWRR_VALUE_MASK GENMASK(15, 0)
+
#define REG_PSE_BUF_USAGE_CFG 0x1028
#define PSE_BUF_ESTIMATE_EN_MASK BIT(29)
+#define REG_CHAN_QOS_MODE(_n) (0x1040 + ((_n) << 2))
+#define CHAN_QOS_MODE_MASK(_n) GENMASK(2 + ((_n) << 2), (_n) << 2)
+
#define REG_GLB_TRTCM_CFG 0x1080
#define GLB_TRTCM_EN_MASK BIT(31)
#define GLB_TRTCM_MODE_MASK BIT(30)
@@ -720,6 +764,40 @@ enum {
FE_PSE_PORT_DROP = 0xf,
};
+enum tx_sched_mode {
+ TC_SCH_WRR8,
+ TC_SCH_SP,
+ TC_SCH_WRR7,
+ TC_SCH_WRR6,
+ TC_SCH_WRR5,
+ TC_SCH_WRR4,
+ TC_SCH_WRR3,
+ TC_SCH_WRR2,
+};
+
+enum trtcm_param_type {
+ TRTCM_MISC_MODE, /* meter_en, pps_mode, tick_sel */
+ TRTCM_TOKEN_RATE_MODE,
+ TRTCM_BUCKETSIZE_SHIFT_MODE,
+ TRTCM_BUCKET_COUNTER_MODE,
+};
+
+enum trtcm_mode_type {
+ TRTCM_COMMIT_MODE,
+ TRTCM_PEAK_MODE,
+};
+
+enum trtcm_param {
+ TRTCM_TICK_SEL = BIT(0),
+ TRTCM_PKT_MODE = BIT(1),
+ TRTCM_METER_MODE = BIT(2),
+};
+
+#define MIN_TOKEN_SIZE 4096
+#define MAX_TOKEN_SIZE_OFFSET 17
+#define TRTCM_TOKEN_RATE_MASK GENMASK(23, 6)
+#define TRTCM_TOKEN_RATE_FRACTION_MASK GENMASK(5, 0)
+
struct airoha_queue_entry {
union {
void *buf;
@@ -810,6 +888,12 @@ struct airoha_gdm_port {
int id;
struct airoha_hw_stats stats;
+
+ DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
+
+ /* qos stats counters */
+ u64 cpu_tx_packets;
+ u64 fwd_tx_packets;
};
struct airoha_eth {
@@ -1789,6 +1873,10 @@ static int airoha_qdma_init_tx_queue(struct airoha_queue *q,
WRITE_ONCE(q->desc[i].ctrl, cpu_to_le32(val));
}
+ /* xmit ring drop default setting */
+ airoha_qdma_set(qdma, REG_TX_RING_BLOCKING(qid),
+ TX_RING_IRQ_BLOCKING_TX_DROP_EN_MASK);
+
airoha_qdma_wr(qdma, REG_TX_RING_BASE(qid), dma_addr);
airoha_qdma_rmw(qdma, REG_TX_CPU_IDX(qid), TX_RING_CPU_IDX_MASK,
FIELD_PREP(TX_RING_CPU_IDX_MASK, q->head));
@@ -1955,6 +2043,27 @@ static void airoha_qdma_init_qos(struct airoha_qdma *qdma)
FIELD_PREP(SLA_SLOW_TICK_RATIO_MASK, 40));
}
+static void airoha_qdma_init_qos_stats(struct airoha_qdma *qdma)
+{
+ int i;
+
+ for (i = 0; i < AIROHA_NUM_QOS_CHANNELS; i++) {
+ /* Tx-cpu transferred count */
+ airoha_qdma_wr(qdma, REG_CNTR_VAL(i << 1), 0);
+ airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1),
+ CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK |
+ CNTR_ALL_DSCP_RING_EN_MASK |
+ FIELD_PREP(CNTR_CHAN_MASK, i));
+ /* Tx-fwd transferred count */
+ airoha_qdma_wr(qdma, REG_CNTR_VAL((i << 1) + 1), 0);
+ airoha_qdma_wr(qdma, REG_CNTR_CFG(i << 1),
+ CNTR_EN_MASK | CNTR_ALL_QUEUE_EN_MASK |
+ CNTR_ALL_DSCP_RING_EN_MASK |
+ FIELD_PREP(CNTR_SRC_MASK, 1) |
+ FIELD_PREP(CNTR_CHAN_MASK, i));
+ }
+}
+
static int airoha_qdma_hw_init(struct airoha_qdma *qdma)
{
int i;
@@ -2005,6 +2114,7 @@ static int airoha_qdma_hw_init(struct airoha_qdma *qdma)
airoha_qdma_set(qdma, REG_TXQ_CNGST_CFG,
TXQ_CNGST_DROP_EN | TXQ_CNGST_DEI_DROP_EN);
+ airoha_qdma_init_qos_stats(qdma);
return 0;
}
@@ -2138,17 +2248,14 @@ static void airoha_hw_cleanup(struct airoha_qdma *qdma)
if (!qdma->q_rx[i].ndesc)
continue;
- napi_disable(&qdma->q_rx[i].napi);
netif_napi_del(&qdma->q_rx[i].napi);
airoha_qdma_cleanup_rx_queue(&qdma->q_rx[i]);
if (qdma->q_rx[i].page_pool)
page_pool_destroy(qdma->q_rx[i].page_pool);
}
- for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++) {
- napi_disable(&qdma->q_tx_irq[i].napi);
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
netif_napi_del(&qdma->q_tx_irq[i].napi);
- }
for (i = 0; i < ARRAY_SIZE(qdma->q_tx); i++) {
if (!qdma->q_tx[i].ndesc)
@@ -2173,6 +2280,21 @@ static void airoha_qdma_start_napi(struct airoha_qdma *qdma)
}
}
+static void airoha_qdma_stop_napi(struct airoha_qdma *qdma)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(qdma->q_tx_irq); i++)
+ napi_disable(&qdma->q_tx_irq[i].napi);
+
+ for (i = 0; i < ARRAY_SIZE(qdma->q_rx); i++) {
+ if (!qdma->q_rx[i].ndesc)
+ continue;
+
+ napi_disable(&qdma->q_rx[i].napi);
+ }
+}
+
static void airoha_update_hw_stats(struct airoha_gdm_port *port)
{
struct airoha_eth *eth = port->qdma->eth;
@@ -2413,21 +2535,44 @@ static void airoha_dev_get_stats64(struct net_device *dev,
} while (u64_stats_fetch_retry(&port->stats.syncp, start));
}
+static u16 airoha_dev_select_queue(struct net_device *dev, struct sk_buff *skb,
+ struct net_device *sb_dev)
+{
+ struct airoha_gdm_port *port = netdev_priv(dev);
+ int queue, channel;
+
+ /* For dsa device select QoS channel according to the dsa user port
+ * index, rely on port id otherwise. Select QoS queue based on the
+ * skb priority.
+ */
+ channel = netdev_uses_dsa(dev) ? skb_get_queue_mapping(skb) : port->id;
+ channel = channel % AIROHA_NUM_QOS_CHANNELS;
+ queue = (skb->priority - 1) % AIROHA_NUM_QOS_QUEUES; /* QoS queue */
+ queue = channel * AIROHA_NUM_QOS_QUEUES + queue;
+
+ return queue < dev->num_tx_queues ? queue : 0;
+}
+
static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
struct net_device *dev)
{
struct skb_shared_info *sinfo = skb_shinfo(skb);
struct airoha_gdm_port *port = netdev_priv(dev);
- u32 msg0 = 0, msg1, len = skb_headlen(skb);
- int i, qid = skb_get_queue_mapping(skb);
+ u32 msg0, msg1, len = skb_headlen(skb);
struct airoha_qdma *qdma = port->qdma;
u32 nr_frags = 1 + sinfo->nr_frags;
struct netdev_queue *txq;
struct airoha_queue *q;
void *data = skb->data;
+ int i, qid;
u16 index;
u8 fport;
+ qid = skb_get_queue_mapping(skb) % ARRAY_SIZE(qdma->q_tx);
+ msg0 = FIELD_PREP(QDMA_ETH_TXMSG_CHAN_MASK,
+ qid / AIROHA_NUM_QOS_QUEUES) |
+ FIELD_PREP(QDMA_ETH_TXMSG_QUEUE_MASK,
+ qid % AIROHA_NUM_QOS_QUEUES);
if (skb->ip_summed == CHECKSUM_PARTIAL)
msg0 |= FIELD_PREP(QDMA_ETH_TXMSG_TCO_MASK, 1) |
FIELD_PREP(QDMA_ETH_TXMSG_UCO_MASK, 1) |
@@ -2597,13 +2742,383 @@ airoha_ethtool_get_rmon_stats(struct net_device *dev,
} while (u64_stats_fetch_retry(&port->stats.syncp, start));
}
+static int airoha_qdma_set_chan_tx_sched(struct airoha_gdm_port *port,
+ int channel, enum tx_sched_mode mode,
+ const u16 *weights, u8 n_weights)
+{
+ int i;
+
+ for (i = 0; i < AIROHA_NUM_TX_RING; i++)
+ airoha_qdma_clear(port->qdma, REG_QUEUE_CLOSE_CFG(channel),
+ TXQ_DISABLE_CHAN_QUEUE_MASK(channel, i));
+
+ for (i = 0; i < n_weights; i++) {
+ u32 status;
+ int err;
+
+ airoha_qdma_wr(port->qdma, REG_TXWRR_WEIGHT_CFG,
+ TWRR_RW_CMD_MASK |
+ FIELD_PREP(TWRR_CHAN_IDX_MASK, channel) |
+ FIELD_PREP(TWRR_QUEUE_IDX_MASK, i) |
+ FIELD_PREP(TWRR_VALUE_MASK, weights[i]));
+ err = read_poll_timeout(airoha_qdma_rr, status,
+ status & TWRR_RW_CMD_DONE,
+ USEC_PER_MSEC, 10 * USEC_PER_MSEC,
+ true, port->qdma,
+ REG_TXWRR_WEIGHT_CFG);
+ if (err)
+ return err;
+ }
+
+ airoha_qdma_rmw(port->qdma, REG_CHAN_QOS_MODE(channel >> 3),
+ CHAN_QOS_MODE_MASK(channel),
+ mode << __ffs(CHAN_QOS_MODE_MASK(channel)));
+
+ return 0;
+}
+
+static int airoha_qdma_set_tx_prio_sched(struct airoha_gdm_port *port,
+ int channel)
+{
+ static const u16 w[AIROHA_NUM_QOS_QUEUES] = {};
+
+ return airoha_qdma_set_chan_tx_sched(port, channel, TC_SCH_SP, w,
+ ARRAY_SIZE(w));
+}
+
+static int airoha_qdma_set_tx_ets_sched(struct airoha_gdm_port *port,
+ int channel,
+ struct tc_ets_qopt_offload *opt)
+{
+ struct tc_ets_qopt_offload_replace_params *p = &opt->replace_params;
+ enum tx_sched_mode mode = TC_SCH_SP;
+ u16 w[AIROHA_NUM_QOS_QUEUES] = {};
+ int i, nstrict = 0;
+
+ if (p->bands > AIROHA_NUM_QOS_QUEUES)
+ return -EINVAL;
+
+ for (i = 0; i < p->bands; i++) {
+ if (!p->quanta[i])
+ nstrict++;
+ }
+
+ /* this configuration is not supported by the hw */
+ if (nstrict == AIROHA_NUM_QOS_QUEUES - 1)
+ return -EINVAL;
+
+ for (i = 0; i < p->bands - nstrict; i++)
+ w[i] = p->weights[nstrict + i];
+
+ if (!nstrict)
+ mode = TC_SCH_WRR8;
+ else if (nstrict < AIROHA_NUM_QOS_QUEUES - 1)
+ mode = nstrict + 1;
+
+ return airoha_qdma_set_chan_tx_sched(port, channel, mode, w,
+ ARRAY_SIZE(w));
+}
+
+static int airoha_qdma_get_tx_ets_stats(struct airoha_gdm_port *port,
+ int channel,
+ struct tc_ets_qopt_offload *opt)
+{
+ u64 cpu_tx_packets = airoha_qdma_rr(port->qdma,
+ REG_CNTR_VAL(channel << 1));
+ u64 fwd_tx_packets = airoha_qdma_rr(port->qdma,
+ REG_CNTR_VAL((channel << 1) + 1));
+ u64 tx_packets = (cpu_tx_packets - port->cpu_tx_packets) +
+ (fwd_tx_packets - port->fwd_tx_packets);
+ _bstats_update(opt->stats.bstats, 0, tx_packets);
+
+ port->cpu_tx_packets = cpu_tx_packets;
+ port->fwd_tx_packets = fwd_tx_packets;
+
+ return 0;
+}
+
+static int airoha_tc_setup_qdisc_ets(struct airoha_gdm_port *port,
+ struct tc_ets_qopt_offload *opt)
+{
+ int channel = TC_H_MAJ(opt->handle) >> 16;
+
+ if (opt->parent == TC_H_ROOT)
+ return -EINVAL;
+
+ switch (opt->command) {
+ case TC_ETS_REPLACE:
+ return airoha_qdma_set_tx_ets_sched(port, channel, opt);
+ case TC_ETS_DESTROY:
+ /* PRIO is default qdisc scheduler */
+ return airoha_qdma_set_tx_prio_sched(port, channel);
+ case TC_ETS_STATS:
+ return airoha_qdma_get_tx_ets_stats(port, channel, opt);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
+static int airoha_qdma_get_trtcm_param(struct airoha_qdma *qdma, int channel,
+ u32 addr, enum trtcm_param_type param,
+ enum trtcm_mode_type mode,
+ u32 *val_low, u32 *val_high)
+{
+ u32 idx = QDMA_METER_IDX(channel), group = QDMA_METER_GROUP(channel);
+ u32 val, config = FIELD_PREP(TRTCM_PARAM_TYPE_MASK, param) |
+ FIELD_PREP(TRTCM_METER_GROUP_MASK, group) |
+ FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) |
+ FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode);
+
+ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config);
+ if (read_poll_timeout(airoha_qdma_rr, val,
+ val & TRTCM_PARAM_RW_DONE_MASK,
+ USEC_PER_MSEC, 10 * USEC_PER_MSEC, true,
+ qdma, REG_TRTCM_CFG_PARAM(addr)))
+ return -ETIMEDOUT;
+
+ *val_low = airoha_qdma_rr(qdma, REG_TRTCM_DATA_LOW(addr));
+ if (val_high)
+ *val_high = airoha_qdma_rr(qdma, REG_TRTCM_DATA_HIGH(addr));
+
+ return 0;
+}
+
+static int airoha_qdma_set_trtcm_param(struct airoha_qdma *qdma, int channel,
+ u32 addr, enum trtcm_param_type param,
+ enum trtcm_mode_type mode, u32 val)
+{
+ u32 idx = QDMA_METER_IDX(channel), group = QDMA_METER_GROUP(channel);
+ u32 config = TRTCM_PARAM_RW_MASK |
+ FIELD_PREP(TRTCM_PARAM_TYPE_MASK, param) |
+ FIELD_PREP(TRTCM_METER_GROUP_MASK, group) |
+ FIELD_PREP(TRTCM_PARAM_INDEX_MASK, idx) |
+ FIELD_PREP(TRTCM_PARAM_RATE_TYPE_MASK, mode);
+
+ airoha_qdma_wr(qdma, REG_TRTCM_DATA_LOW(addr), val);
+ airoha_qdma_wr(qdma, REG_TRTCM_CFG_PARAM(addr), config);
+
+ return read_poll_timeout(airoha_qdma_rr, val,
+ val & TRTCM_PARAM_RW_DONE_MASK,
+ USEC_PER_MSEC, 10 * USEC_PER_MSEC, true,
+ qdma, REG_TRTCM_CFG_PARAM(addr));
+}
+
+static int airoha_qdma_set_trtcm_config(struct airoha_qdma *qdma, int channel,
+ u32 addr, enum trtcm_mode_type mode,
+ bool enable, u32 enable_mask)
+{
+ u32 val;
+
+ if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE,
+ mode, &val, NULL))
+ return -EINVAL;
+
+ val = enable ? val | enable_mask : val & ~enable_mask;
+
+ return airoha_qdma_set_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE,
+ mode, val);
+}
+
+static int airoha_qdma_set_trtcm_token_bucket(struct airoha_qdma *qdma,
+ int channel, u32 addr,
+ enum trtcm_mode_type mode,
+ u32 rate_val, u32 bucket_size)
+{
+ u32 val, config, tick, unit, rate, rate_frac;
+ int err;
+
+ if (airoha_qdma_get_trtcm_param(qdma, channel, addr, TRTCM_MISC_MODE,
+ mode, &config, NULL))
+ return -EINVAL;
+
+ val = airoha_qdma_rr(qdma, addr);
+ tick = FIELD_GET(INGRESS_FAST_TICK_MASK, val);
+ if (config & TRTCM_TICK_SEL)
+ tick *= FIELD_GET(INGRESS_SLOW_TICK_RATIO_MASK, val);
+ if (!tick)
+ return -EINVAL;
+
+ unit = (config & TRTCM_PKT_MODE) ? 1000000 / tick : 8000 / tick;
+ if (!unit)
+ return -EINVAL;
+
+ rate = rate_val / unit;
+ rate_frac = rate_val % unit;
+ rate_frac = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate_frac) / unit;
+ rate = FIELD_PREP(TRTCM_TOKEN_RATE_MASK, rate) |
+ FIELD_PREP(TRTCM_TOKEN_RATE_FRACTION_MASK, rate_frac);
+
+ err = airoha_qdma_set_trtcm_param(qdma, channel, addr,
+ TRTCM_TOKEN_RATE_MODE, mode, rate);
+ if (err)
+ return err;
+
+ val = max_t(u32, bucket_size, MIN_TOKEN_SIZE);
+ val = min_t(u32, __fls(val), MAX_TOKEN_SIZE_OFFSET);
+
+ return airoha_qdma_set_trtcm_param(qdma, channel, addr,
+ TRTCM_BUCKETSIZE_SHIFT_MODE,
+ mode, val);
+}
+
+static int airoha_qdma_set_tx_rate_limit(struct airoha_gdm_port *port,
+ int channel, u32 rate,
+ u32 bucket_size)
+{
+ int i, err;
+
+ for (i = 0; i <= TRTCM_PEAK_MODE; i++) {
+ err = airoha_qdma_set_trtcm_config(port->qdma, channel,
+ REG_EGRESS_TRTCM_CFG, i,
+ !!rate, TRTCM_METER_MODE);
+ if (err)
+ return err;
+
+ err = airoha_qdma_set_trtcm_token_bucket(port->qdma, channel,
+ REG_EGRESS_TRTCM_CFG,
+ i, rate, bucket_size);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+static int airoha_tc_htb_alloc_leaf_queue(struct airoha_gdm_port *port,
+ struct tc_htb_qopt_offload *opt)
+{
+ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
+ u32 rate = div_u64(opt->rate, 1000) << 3; /* kbps */
+ struct net_device *dev = port->dev;
+ int num_tx_queues = dev->real_num_tx_queues;
+ int err;
+
+ if (opt->parent_classid != TC_HTB_CLASSID_ROOT) {
+ NL_SET_ERR_MSG_MOD(opt->extack, "invalid parent classid");
+ return -EINVAL;
+ }
+
+ err = airoha_qdma_set_tx_rate_limit(port, channel, rate, opt->quantum);
+ if (err) {
+ NL_SET_ERR_MSG_MOD(opt->extack,
+ "failed configuring htb offload");
+ return err;
+ }
+
+ if (opt->command == TC_HTB_NODE_MODIFY)
+ return 0;
+
+ err = netif_set_real_num_tx_queues(dev, num_tx_queues + 1);
+ if (err) {
+ airoha_qdma_set_tx_rate_limit(port, channel, 0, opt->quantum);
+ NL_SET_ERR_MSG_MOD(opt->extack,
+ "failed setting real_num_tx_queues");
+ return err;
+ }
+
+ set_bit(channel, port->qos_sq_bmap);
+ opt->qid = AIROHA_NUM_TX_RING + channel;
+
+ return 0;
+}
+
+static void airoha_tc_remove_htb_queue(struct airoha_gdm_port *port, int queue)
+{
+ struct net_device *dev = port->dev;
+
+ netif_set_real_num_tx_queues(dev, dev->real_num_tx_queues - 1);
+ airoha_qdma_set_tx_rate_limit(port, queue + 1, 0, 0);
+ clear_bit(queue, port->qos_sq_bmap);
+}
+
+static int airoha_tc_htb_delete_leaf_queue(struct airoha_gdm_port *port,
+ struct tc_htb_qopt_offload *opt)
+{
+ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
+
+ if (!test_bit(channel, port->qos_sq_bmap)) {
+ NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
+ return -EINVAL;
+ }
+
+ airoha_tc_remove_htb_queue(port, channel);
+
+ return 0;
+}
+
+static int airoha_tc_htb_destroy(struct airoha_gdm_port *port)
+{
+ int q;
+
+ for_each_set_bit(q, port->qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS)
+ airoha_tc_remove_htb_queue(port, q);
+
+ return 0;
+}
+
+static int airoha_tc_get_htb_get_leaf_queue(struct airoha_gdm_port *port,
+ struct tc_htb_qopt_offload *opt)
+{
+ u32 channel = TC_H_MIN(opt->classid) % AIROHA_NUM_QOS_CHANNELS;
+
+ if (!test_bit(channel, port->qos_sq_bmap)) {
+ NL_SET_ERR_MSG_MOD(opt->extack, "invalid queue id");
+ return -EINVAL;
+ }
+
+ opt->qid = channel;
+
+ return 0;
+}
+
+static int airoha_tc_setup_qdisc_htb(struct airoha_gdm_port *port,
+ struct tc_htb_qopt_offload *opt)
+{
+ switch (opt->command) {
+ case TC_HTB_CREATE:
+ break;
+ case TC_HTB_DESTROY:
+ return airoha_tc_htb_destroy(port);
+ case TC_HTB_NODE_MODIFY:
+ case TC_HTB_LEAF_ALLOC_QUEUE:
+ return airoha_tc_htb_alloc_leaf_queue(port, opt);
+ case TC_HTB_LEAF_DEL:
+ case TC_HTB_LEAF_DEL_LAST:
+ case TC_HTB_LEAF_DEL_LAST_FORCE:
+ return airoha_tc_htb_delete_leaf_queue(port, opt);
+ case TC_HTB_LEAF_QUERY_QUEUE:
+ return airoha_tc_get_htb_get_leaf_queue(port, opt);
+ default:
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+static int airoha_dev_tc_setup(struct net_device *dev, enum tc_setup_type type,
+ void *type_data)
+{
+ struct airoha_gdm_port *port = netdev_priv(dev);
+
+ switch (type) {
+ case TC_SETUP_QDISC_ETS:
+ return airoha_tc_setup_qdisc_ets(port, type_data);
+ case TC_SETUP_QDISC_HTB:
+ return airoha_tc_setup_qdisc_htb(port, type_data);
+ default:
+ return -EOPNOTSUPP;
+ }
+}
+
static const struct net_device_ops airoha_netdev_ops = {
.ndo_init = airoha_dev_init,
.ndo_open = airoha_dev_open,
.ndo_stop = airoha_dev_stop,
+ .ndo_select_queue = airoha_dev_select_queue,
.ndo_start_xmit = airoha_dev_xmit,
.ndo_get_stats64 = airoha_dev_get_stats64,
.ndo_set_mac_address = airoha_dev_set_macaddr,
+ .ndo_setup_tc = airoha_dev_tc_setup,
};
static const struct ethtool_ops airoha_ethtool_ops = {
@@ -2640,7 +3155,8 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np)
}
dev = devm_alloc_etherdev_mqs(eth->dev, sizeof(*port),
- AIROHA_NUM_TX_RING, AIROHA_NUM_RX_RING);
+ AIROHA_NUM_NETDEV_TX_RINGS,
+ AIROHA_NUM_RX_RING);
if (!dev) {
dev_err(eth->dev, "alloc_etherdev failed\n");
return -ENOMEM;
@@ -2653,12 +3169,18 @@ static int airoha_alloc_gdm_port(struct airoha_eth *eth, struct device_node *np)
dev->watchdog_timeo = 5 * HZ;
dev->hw_features = NETIF_F_IP_CSUM | NETIF_F_RXCSUM |
NETIF_F_TSO6 | NETIF_F_IPV6_CSUM |
- NETIF_F_SG | NETIF_F_TSO;
+ NETIF_F_SG | NETIF_F_TSO |
+ NETIF_F_HW_TC;
dev->features |= dev->hw_features;
dev->dev.of_node = np;
dev->irq = qdma->irq;
SET_NETDEV_DEV(dev, eth->dev);
+ /* reserve hw queues for HTB offloading */
+ err = netif_set_real_num_tx_queues(dev, AIROHA_NUM_TX_RING);
+ if (err)
+ return err;
+
err = of_get_ethdev_address(np, dev);
if (err) {
if (err == -EPROBE_DEFER)
@@ -2738,7 +3260,7 @@ static int airoha_probe(struct platform_device *pdev)
err = airoha_hw_init(pdev, eth);
if (err)
- goto error;
+ goto error_hw_cleanup;
for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
airoha_qdma_start_napi(&eth->qdma[i]);
@@ -2753,13 +3275,16 @@ static int airoha_probe(struct platform_device *pdev)
err = airoha_alloc_gdm_port(eth, np);
if (err) {
of_node_put(np);
- goto error;
+ goto error_napi_stop;
}
}
return 0;
-error:
+error_napi_stop:
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
+ airoha_qdma_stop_napi(&eth->qdma[i]);
+error_hw_cleanup:
for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
airoha_hw_cleanup(&eth->qdma[i]);
@@ -2780,8 +3305,10 @@ static void airoha_remove(struct platform_device *pdev)
struct airoha_eth *eth = platform_get_drvdata(pdev);
int i;
- for (i = 0; i < ARRAY_SIZE(eth->qdma); i++)
+ for (i = 0; i < ARRAY_SIZE(eth->qdma); i++) {
+ airoha_qdma_stop_napi(&eth->qdma[i]);
airoha_hw_cleanup(&eth->qdma[i]);
+ }
for (i = 0; i < ARRAY_SIZE(eth->ports); i++) {
struct airoha_gdm_port *port = eth->ports[i];
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/Makefile b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
index be3d0876c521..10a763e668ed 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/Makefile
+++ b/drivers/net/ethernet/mellanox/mlx5/core/Makefile
@@ -17,7 +17,7 @@ mlx5_core-y := main.o cmd.o debugfs.o fw.o eq.o uar.o pagealloc.o \
fs_counters.o fs_ft_pool.o rl.o lag/debugfs.o lag/lag.o dev.o events.o wq.o lib/gid.o \
lib/devcom.o lib/pci_vsc.o lib/dm.o lib/fs_ttc.o diag/fs_tracepoint.o \
diag/fw_tracer.o diag/crdump.o devlink.o diag/rsc_dump.o diag/reporter_vnic.o \
- fw_reset.o qos.o lib/tout.o lib/aso.o wc.o
+ fw_reset.o qos.o lib/tout.o lib/aso.o wc.o fs_pool.o
#
# Netdev basic
@@ -123,6 +123,7 @@ mlx5_core-$(CONFIG_MLX5_SW_STEERING) += steering/sws/dr_domain.o \
steering/sws/dr_ste_v0.o \
steering/sws/dr_ste_v1.o \
steering/sws/dr_ste_v2.o \
+ steering/sws/dr_ste_v3.o \
steering/sws/dr_cmd.o \
steering/sws/dr_fw.o \
steering/sws/dr_action.o \
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
index 6bd8a18e3af3..e733b81e18a2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c
@@ -1013,6 +1013,7 @@ static void cmd_work_handler(struct work_struct *work)
complete(&ent->done);
}
up(&cmd->vars.sem);
+ complete(&ent->slotted);
return;
}
} else {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
index 9aed29fa4900..d6e736c1fb24 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/diag/fs_tracepoint.h
@@ -292,7 +292,7 @@ TRACE_EVENT(mlx5_fs_add_rule,
if (rule->dest_attr.type &
MLX5_FLOW_DESTINATION_TYPE_COUNTER)
__entry->counter_id =
- rule->dest_attr.counter_id;
+ mlx5_fc_id(rule->dest_attr.counter);
),
TP_printk("rule=%p fte=%p index=%u sw_action=<%s> [dst] %s\n",
__entry->rule, __entry->fte, __entry->index,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
index 878cbdbf5ec8..e7e01f3298ef 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c
@@ -5,6 +5,7 @@
#include <net/nexthop.h>
#include <net/ip_tunnels.h>
#include "tc_tun_encap.h"
+#include "fs_core.h"
#include "en_tc.h"
#include "tc_tun.h"
#include "rep/tc.h"
@@ -24,10 +25,18 @@ static int mlx5e_set_int_port_tunnel(struct mlx5e_priv *priv,
route_dev = dev_get_by_index(dev_net(e->out_dev), e->route_dev_ifindex);
- if (!route_dev || !netif_is_ovs_master(route_dev) ||
- attr->parse_attr->filter_dev == e->out_dev)
+ if (!route_dev || !netif_is_ovs_master(route_dev))
goto out;
+ if (priv->mdev->priv.steering->mode == MLX5_FLOW_STEERING_MODE_DMFS &&
+ mlx5e_eswitch_uplink_rep(attr->parse_attr->filter_dev) &&
+ (attr->esw_attr->dests[out_index].flags & MLX5_ESW_DEST_ENCAP)) {
+ mlx5_core_warn(priv->mdev,
+ "Matching on external port with encap + fwd to table actions is not allowed for firmware steering\n");
+ err = -EINVAL;
+ goto out;
+ }
+
err = mlx5e_set_fwd_to_int_port_actions(priv, attr, e->route_dev_ifindex,
MLX5E_TC_INT_PORT_EGRESS,
&attr->action, out_index);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
index e51b03d4c717..687bd95d2c3e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c
@@ -194,7 +194,7 @@ static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry,
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
flow_act.flags = FLOW_ACT_NO_APPEND;
dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest.counter_id = mlx5_fc_id(flow_counter);
+ dest.counter = flow_counter;
if (rx == ipsec->rx_esw)
spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
@@ -223,7 +223,7 @@ static int rx_add_rule_drop_auth_trailer(struct mlx5e_ipsec_sa_entry *sa_entry,
}
sa_entry->ipsec_rule.trailer.fc = flow_counter;
- dest.counter_id = mlx5_fc_id(flow_counter);
+ dest.counter = flow_counter;
MLX5_SET(fte_match_param, spec->match_value, misc_parameters_2.ipsec_syndrome, 2);
rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
if (IS_ERR(rule)) {
@@ -275,7 +275,7 @@ static int rx_add_rule_drop_replay(struct mlx5e_ipsec_sa_entry *sa_entry, struct
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
flow_act.flags = FLOW_ACT_NO_APPEND;
dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest.counter_id = mlx5_fc_id(flow_counter);
+ dest.counter = flow_counter;
if (rx == ipsec->rx_esw)
spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
@@ -348,7 +348,7 @@ static int ipsec_rx_status_drop_all_create(struct mlx5e_ipsec *ipsec,
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest.counter_id = mlx5_fc_id(flow_counter);
+ dest.counter = flow_counter;
if (rx == ipsec->rx_esw)
spec->flow_context.flow_source = MLX5_FLOW_CONTEXT_FLOW_SOURCE_UPLINK;
rule = mlx5_add_flow_rules(ft, spec, &flow_act, &dest, 1);
@@ -686,7 +686,7 @@ static int rx_create(struct mlx5_core_dev *mdev, struct mlx5e_ipsec *ipsec,
rx->ft.status = ft;
dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest[1].counter_id = mlx5_fc_id(rx->fc->cnt);
+ dest[1].counter = rx->fc->cnt;
err = mlx5_ipsec_rx_status_create(ipsec, rx, dest);
if (err)
goto err_add;
@@ -873,7 +873,7 @@ static int ipsec_counter_rule_tx(struct mlx5_core_dev *mdev, struct mlx5e_ipsec_
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW |
MLX5_FLOW_CONTEXT_ACTION_COUNT;
dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest.counter_id = mlx5_fc_id(tx->fc->cnt);
+ dest.counter = tx->fc->cnt;
fte = mlx5_add_flow_rules(tx->ft.status, spec, &flow_act, &dest, 1);
if (IS_ERR(fte)) {
err = PTR_ERR(fte);
@@ -1649,7 +1649,7 @@ static int rx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
dest[0].ft = rx->ft.status;
dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest[1].counter_id = mlx5_fc_id(counter);
+ dest[1].counter = counter;
rule = mlx5_add_flow_rules(rx->ft.sa, spec, &flow_act, dest, 2);
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
@@ -1762,7 +1762,7 @@ static int tx_add_rule(struct mlx5e_ipsec_sa_entry *sa_entry)
dest[0].ft = tx->ft.status;
dest[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
dest[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest[1].counter_id = mlx5_fc_id(counter);
+ dest[1].counter = counter;
rule = mlx5_add_flow_rules(tx->ft.sa, spec, &flow_act, dest, 2);
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
@@ -1835,7 +1835,7 @@ static int tx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry)
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
MLX5_FLOW_CONTEXT_ACTION_COUNT;
dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest[dstn].counter_id = mlx5_fc_id(tx->fc->drop);
+ dest[dstn].counter = tx->fc->drop;
dstn++;
break;
default:
@@ -1913,7 +1913,7 @@ static int rx_add_policy(struct mlx5e_ipsec_pol_entry *pol_entry)
case XFRM_POLICY_BLOCK:
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest[dstn].counter_id = mlx5_fc_id(rx->fc->drop);
+ dest[dstn].counter = rx->fc->drop;
dstn++;
break;
default:
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
index cc9bcc420032..6ab02f3fc291 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/macsec.c
@@ -339,9 +339,13 @@ static int mlx5e_macsec_init_sa_fs(struct macsec_context *ctx,
{
struct mlx5e_priv *priv = macsec_netdev_priv(ctx->netdev);
struct mlx5_macsec_fs *macsec_fs = priv->mdev->macsec_fs;
+ const struct macsec_tx_sc *tx_sc = &ctx->secy->tx_sc;
struct mlx5_macsec_rule_attrs rule_attrs;
union mlx5_macsec_rule *macsec_rule;
+ if (is_tx && tx_sc->encoding_sa != sa->assoc_num)
+ return 0;
+
rule_attrs.macsec_obj_id = sa->macsec_obj_id;
rule_attrs.sci = sa->sci;
rule_attrs.assoc_num = sa->assoc_num;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
index d0b80b520397..bd41b75d246e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c
@@ -2680,11 +2680,11 @@ void mlx5e_trigger_napi_sched(struct napi_struct *napi)
static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
struct mlx5e_params *params,
- struct mlx5e_channel_param *cparam,
struct xsk_buff_pool *xsk_pool,
struct mlx5e_channel **cp)
{
struct net_device *netdev = priv->netdev;
+ struct mlx5e_channel_param *cparam;
struct mlx5_core_dev *mdev;
struct mlx5e_xsk_param xsk;
struct mlx5e_channel *c;
@@ -2706,8 +2706,15 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
return err;
c = kvzalloc_node(sizeof(*c), GFP_KERNEL, cpu_to_node(cpu));
- if (!c)
- return -ENOMEM;
+ cparam = kvzalloc(sizeof(*cparam), GFP_KERNEL);
+ if (!c || !cparam) {
+ err = -ENOMEM;
+ goto err_free;
+ }
+
+ err = mlx5e_build_channel_param(mdev, params, cparam);
+ if (err)
+ goto err_free;
c->priv = priv;
c->mdev = mdev;
@@ -2741,6 +2748,7 @@ static int mlx5e_open_channel(struct mlx5e_priv *priv, int ix,
*cp = c;
+ kvfree(cparam);
return 0;
err_close_queues:
@@ -2749,6 +2757,8 @@ err_close_queues:
err_napi_del:
netif_napi_del(&c->napi);
+err_free:
+ kvfree(cparam);
kvfree(c);
return err;
@@ -2807,20 +2817,14 @@ static void mlx5e_close_channel(struct mlx5e_channel *c)
int mlx5e_open_channels(struct mlx5e_priv *priv,
struct mlx5e_channels *chs)
{
- struct mlx5e_channel_param *cparam;
int err = -ENOMEM;
int i;
chs->num = chs->params.num_channels;
chs->c = kcalloc(chs->num, sizeof(struct mlx5e_channel *), GFP_KERNEL);
- cparam = kvzalloc(sizeof(struct mlx5e_channel_param), GFP_KERNEL);
- if (!chs->c || !cparam)
- goto err_free;
-
- err = mlx5e_build_channel_param(priv->mdev, &chs->params, cparam);
- if (err)
- goto err_free;
+ if (!chs->c)
+ goto err_out;
for (i = 0; i < chs->num; i++) {
struct xsk_buff_pool *xsk_pool = NULL;
@@ -2828,7 +2832,7 @@ int mlx5e_open_channels(struct mlx5e_priv *priv,
if (chs->params.xdp_prog)
xsk_pool = mlx5e_xsk_get_pool(&chs->params, chs->params.xsk, i);
- err = mlx5e_open_channel(priv, i, &chs->params, cparam, xsk_pool, &chs->c[i]);
+ err = mlx5e_open_channel(priv, i, &chs->params, xsk_pool, &chs->c[i]);
if (err)
goto err_close_channels;
}
@@ -2846,7 +2850,6 @@ int mlx5e_open_channels(struct mlx5e_priv *priv,
}
mlx5e_health_channels_update(priv);
- kvfree(cparam);
return 0;
err_close_ptp:
@@ -2857,9 +2860,8 @@ err_close_channels:
for (i--; i >= 0; i--)
mlx5e_close_channel(chs->c[i]);
-err_free:
kfree(chs->c);
- kvfree(cparam);
+err_out:
chs->num = 0;
return err;
}
@@ -3944,6 +3946,7 @@ mlx5e_get_stats(struct net_device *dev, struct rtnl_link_stats64 *stats)
}
stats->rx_missed_errors = priv->stats.qcnt.rx_out_of_buffer;
+ stats->rx_dropped = PPORT_2863_GET(pstats, if_in_discards);
stats->rx_length_errors =
PPORT_802_3_GET(pstats, a_in_range_length_errors) +
@@ -6540,8 +6543,23 @@ static void _mlx5e_remove(struct auxiliary_device *adev)
mlx5_core_uplink_netdev_set(mdev, NULL);
mlx5e_dcbnl_delete_app(priv);
- unregister_netdev(priv->netdev);
- _mlx5e_suspend(adev, false);
+ /* When unload driver, the netdev is in registered state
+ * if it's from legacy mode. If from switchdev mode, it
+ * is already unregistered before changing to NIC profile.
+ */
+ if (priv->netdev->reg_state == NETREG_REGISTERED) {
+ unregister_netdev(priv->netdev);
+ _mlx5e_suspend(adev, false);
+ } else {
+ struct mlx5_core_dev *pos;
+ int i;
+
+ if (test_bit(MLX5E_STATE_DESTROYING, &priv->state))
+ mlx5_sd_for_each_dev(i, mdev, pos)
+ mlx5e_destroy_mdev_resources(pos);
+ else
+ _mlx5e_suspend(adev, true);
+ }
/* Avoid cleanup if profile rollback failed. */
if (priv->profile)
priv->profile->cleanup(priv);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 554f9cb5b53f..fdff9fd8a89e 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -1509,6 +1509,21 @@ mlx5e_vport_uplink_rep_unload(struct mlx5e_rep_priv *rpriv)
priv = netdev_priv(netdev);
+ /* This bit is set when using devlink to change eswitch mode from
+ * switchdev to legacy. As need to keep uplink netdev ifindex, we
+ * detach uplink representor profile and attach NIC profile only.
+ * The netdev will be unregistered later when unload NIC auxiliary
+ * driver for this case.
+ * We explicitly block devlink eswitch mode change if any IPSec rules
+ * offloaded, but can't block other cases, such as driver unload
+ * and devlink reload. We have to unregister netdev before profile
+ * change for those cases. This is to avoid resource leak because
+ * the offloaded rules don't have the chance to be unoffloaded before
+ * cleanup which is triggered by detach uplink representor profile.
+ */
+ if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_SWITCH_LEGACY))
+ unregister_netdev(netdev);
+
mlx5e_netdev_attach_nic_profile(priv);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 6b3b1afe8312..9ba99609999f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -1282,7 +1282,7 @@ mlx5e_add_offloaded_nic_rule(struct mlx5e_priv *priv,
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
dest[dest_ix].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest[dest_ix].counter_id = mlx5_fc_id(attr->counter);
+ dest[dest_ix].counter = attr->counter;
dest_ix++;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c
index 6b4c9ffad95b..7dd1dc3f77c7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/egress_lgcy.c
@@ -135,7 +135,7 @@ int esw_acl_egress_lgcy_setup(struct mlx5_eswitch *esw,
if (drop_counter) {
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- drop_ctr_dst.counter_id = mlx5_fc_id(drop_counter);
+ drop_ctr_dst.counter = drop_counter;
dst = &drop_ctr_dst;
dest_num++;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c
index 093ed86a0acd..1c37098e09ea 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/acl/ingress_lgcy.c
@@ -260,7 +260,7 @@ int esw_acl_ingress_lgcy_setup(struct mlx5_eswitch *esw,
if (counter) {
flow_act.action |= MLX5_FLOW_CONTEXT_ACTION_COUNT;
drop_ctr_dst.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- drop_ctr_dst.counter_id = mlx5_fc_id(counter);
+ drop_ctr_dst.counter = counter;
dst = &drop_ctr_dst;
dest_num++;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
index c5ea1d1d2b03..5f647358a05c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/bridge.c
@@ -570,7 +570,8 @@ mlx5_esw_bridge_egress_table_cleanup(struct mlx5_esw_bridge *bridge)
static struct mlx5_flow_handle *
mlx5_esw_bridge_ingress_flow_with_esw_create(u16 vport_num, const unsigned char *addr,
- struct mlx5_esw_bridge_vlan *vlan, u32 counter_id,
+ struct mlx5_esw_bridge_vlan *vlan,
+ struct mlx5_fc *counter,
struct mlx5_esw_bridge *bridge,
struct mlx5_eswitch *esw)
{
@@ -628,7 +629,7 @@ mlx5_esw_bridge_ingress_flow_with_esw_create(u16 vport_num, const unsigned char
dests[0].type = MLX5_FLOW_DESTINATION_TYPE_FLOW_TABLE;
dests[0].ft = bridge->egress_ft;
dests[1].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dests[1].counter_id = counter_id;
+ dests[1].counter = counter;
handle = mlx5_add_flow_rules(br_offloads->ingress_ft, rule_spec, &flow_act, dests,
ARRAY_SIZE(dests));
@@ -639,17 +640,19 @@ mlx5_esw_bridge_ingress_flow_with_esw_create(u16 vport_num, const unsigned char
static struct mlx5_flow_handle *
mlx5_esw_bridge_ingress_flow_create(u16 vport_num, const unsigned char *addr,
- struct mlx5_esw_bridge_vlan *vlan, u32 counter_id,
+ struct mlx5_esw_bridge_vlan *vlan,
+ struct mlx5_fc *counter,
struct mlx5_esw_bridge *bridge)
{
- return mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter_id,
+ return mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter,
bridge, bridge->br_offloads->esw);
}
static struct mlx5_flow_handle *
mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, u16 esw_owner_vhca_id,
const unsigned char *addr,
- struct mlx5_esw_bridge_vlan *vlan, u32 counter_id,
+ struct mlx5_esw_bridge_vlan *vlan,
+ struct mlx5_fc *counter,
struct mlx5_esw_bridge *bridge)
{
struct mlx5_devcom_comp_dev *devcom = bridge->br_offloads->esw->devcom, *pos;
@@ -671,7 +674,7 @@ mlx5_esw_bridge_ingress_flow_peer_create(u16 vport_num, u16 esw_owner_vhca_id,
goto out;
}
- handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter_id,
+ handle = mlx5_esw_bridge_ingress_flow_with_esw_create(vport_num, addr, vlan, counter,
bridge, peer_esw);
out:
@@ -1385,10 +1388,9 @@ mlx5_esw_bridge_fdb_entry_init(struct net_device *dev, u16 vport_num, u16 esw_ow
handle = peer ?
mlx5_esw_bridge_ingress_flow_peer_create(vport_num, esw_owner_vhca_id,
- addr, vlan, mlx5_fc_id(counter),
- bridge) :
+ addr, vlan, counter, bridge) :
mlx5_esw_bridge_ingress_flow_create(vport_num, addr, vlan,
- mlx5_fc_id(counter), bridge);
+ counter, bridge);
if (IS_ERR(handle)) {
err = PTR_ERR(handle);
esw_warn(esw->dev, "Failed to create ingress flow(vport=%u,err=%d,peer=%d)\n",
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
index 5a0047bdcb51..ed977ae75fab 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/ipsec_fs.c
@@ -150,11 +150,11 @@ void mlx5_esw_ipsec_restore_dest_uplink(struct mlx5_core_dev *mdev)
unsigned long i;
int err;
- xa_for_each(&esw->offloads.vport_reps, i, rep) {
- rpriv = rep->rep_data[REP_ETH].priv;
- if (!rpriv || !rpriv->netdev)
+ mlx5_esw_for_each_rep(esw, i, rep) {
+ if (atomic_read(&rep->rep_data[REP_ETH].state) != REP_LOADED)
continue;
+ rpriv = rep->rep_data[REP_ETH].priv;
rhashtable_walk_enter(&rpriv->tc_ht, &iter);
rhashtable_walk_start(&iter);
while ((flow = rhashtable_walk_next(&iter)) != NULL) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index a83d41121db6..8573d36785f4 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -714,6 +714,9 @@ void mlx5e_tc_clean_fdb_peer_flows(struct mlx5_eswitch *esw);
MLX5_CAP_GEN_2((esw->dev), ec_vf_vport_base) +\
(last) - 1)
+#define mlx5_esw_for_each_rep(esw, i, rep) \
+ xa_for_each(&((esw)->offloads.vport_reps), i, rep)
+
struct mlx5_eswitch *__must_check
mlx5_devlink_eswitch_get(struct devlink *devlink);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
index d6ff2dc4c19e..20cc01ceee8a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
@@ -53,9 +53,6 @@
#include "lag/lag.h"
#include "en/tc/post_meter.h"
-#define mlx5_esw_for_each_rep(esw, i, rep) \
- xa_for_each(&((esw)->offloads.vport_reps), i, rep)
-
/* There are two match-all miss flows, one for unicast dst mac and
* one for multicast.
*/
@@ -724,7 +721,7 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_COUNT) {
dest[i].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest[i].counter_id = mlx5_fc_id(attr->counter);
+ dest[i].counter = attr->counter;
i++;
}
@@ -2335,9 +2332,10 @@ out_free:
static void esw_mode_change(struct mlx5_eswitch *esw, u16 mode)
{
mlx5_devcom_comp_lock(esw->dev->priv.hca_devcom_comp);
-
- if (esw->dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_IB_ADEV) {
+ if (esw->dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_IB_ADEV ||
+ mlx5_core_mp_enabled(esw->dev)) {
esw->mode = mode;
+ mlx5_rescan_drivers_locked(esw->dev);
mlx5_devcom_comp_unlock(esw->dev->priv.hca_devcom_comp);
return;
}
@@ -3779,6 +3777,8 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
esw->eswitch_operation_in_progress = true;
up_write(&esw->mode_lock);
+ if (mode == DEVLINK_ESWITCH_MODE_LEGACY)
+ esw->dev->priv.flags |= MLX5_PRIV_FLAGS_SWITCH_LEGACY;
mlx5_eswitch_disable_locked(esw);
if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) {
if (mlx5_devlink_trap_get_num_active(esw->dev)) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
index 676005854dad..ae20c061e0fb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_cmd.c
@@ -217,7 +217,8 @@ static int mlx5_cmd_update_root_ft(struct mlx5_flow_root_namespace *ns,
int err;
if ((MLX5_CAP_GEN(dev, port_type) == MLX5_CAP_PORT_TYPE_IB) &&
- underlay_qpn == 0)
+ underlay_qpn == 0 &&
+ (ft->type != FS_FT_RDMA_RX && ft->type != FS_FT_RDMA_TX))
return 0;
if (ft->type == FS_FT_FDB &&
@@ -718,7 +719,7 @@ static int mlx5_cmd_set_fte(struct mlx5_core_dev *dev,
continue;
MLX5_SET(flow_counter_list, in_dests, flow_counter_id,
- dst->dest_attr.counter_id);
+ mlx5_fc_id(dst->dest_attr.counter));
in_dests += dst_cnt_size;
list_size++;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
index 2eabfcc247c6..41b5e98a0495 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_core.c
@@ -658,6 +658,7 @@ static void del_sw_hw_rule(struct fs_node *node)
BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_ACTION) |
BIT(MLX5_SET_FTE_MODIFY_ENABLE_MASK_FLOW_COUNTERS);
fte->act_dests.action.action &= ~MLX5_FLOW_CONTEXT_ACTION_COUNT;
+ mlx5_fc_local_destroy(rule->dest_attr.counter);
goto out;
}
@@ -820,11 +821,17 @@ static int insert_fte(struct mlx5_flow_group *fg, struct fs_fte *fte)
return index;
fte->index = index + fg->start_index;
+retry_insert:
ret = rhashtable_insert_fast(&fg->ftes_hash,
&fte->hash,
rhash_fte);
- if (ret)
+ if (ret) {
+ if (ret == -EBUSY) {
+ cond_resched();
+ goto retry_insert;
+ }
goto err_ida_remove;
+ }
tree_add_node(&fte->node, &fg->node);
list_add_tail(&fte->node.list, &fg->node.children);
@@ -3658,8 +3665,7 @@ int mlx5_fs_core_init(struct mlx5_core_dev *dev)
goto err;
}
- if (MLX5_CAP_FLOWTABLE_RDMA_RX(dev, ft_support) &&
- MLX5_CAP_FLOWTABLE_RDMA_RX(dev, table_miss_action_domain)) {
+ if (MLX5_CAP_FLOWTABLE_RDMA_RX(dev, ft_support)) {
err = init_rdma_rx_root_ns(steering);
if (err)
goto err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
index 62d0c689796b..d8e1c4ebd364 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_counters.c
@@ -34,6 +34,7 @@
#include <linux/mlx5/fs.h>
#include "mlx5_core.h"
#include "fs_core.h"
+#include "fs_pool.h"
#include "fs_cmd.h"
#define MLX5_FC_STATS_PERIOD msecs_to_jiffies(1000)
@@ -43,6 +44,11 @@
#define MLX5_FC_POOL_MAX_THRESHOLD BIT(18)
#define MLX5_FC_POOL_USED_BUFF_RATIO 10
+enum mlx5_fc_type {
+ MLX5_FC_TYPE_ACQUIRED = 0,
+ MLX5_FC_TYPE_LOCAL,
+};
+
struct mlx5_fc_cache {
u64 packets;
u64 bytes;
@@ -52,6 +58,7 @@ struct mlx5_fc_cache {
struct mlx5_fc {
u32 id;
bool aging;
+ enum mlx5_fc_type type;
struct mlx5_fc_bulk *bulk;
struct mlx5_fc_cache cache;
/* last{packets,bytes} are used for calculating deltas since last reading. */
@@ -59,17 +66,6 @@ struct mlx5_fc {
u64 lastbytes;
};
-struct mlx5_fc_pool {
- struct mlx5_core_dev *dev;
- struct mutex pool_lock; /* protects pool lists */
- struct list_head fully_used;
- struct list_head partially_used;
- struct list_head unused;
- int available_fcs;
- int used_fcs;
- int threshold;
-};
-
struct mlx5_fc_stats {
struct xarray counters;
@@ -80,13 +76,13 @@ struct mlx5_fc_stats {
int bulk_query_len;
bool bulk_query_alloc_failed;
unsigned long next_bulk_query_alloc;
- struct mlx5_fc_pool fc_pool;
+ struct mlx5_fs_pool fc_pool;
};
-static void mlx5_fc_pool_init(struct mlx5_fc_pool *fc_pool, struct mlx5_core_dev *dev);
-static void mlx5_fc_pool_cleanup(struct mlx5_fc_pool *fc_pool);
-static struct mlx5_fc *mlx5_fc_pool_acquire_counter(struct mlx5_fc_pool *fc_pool);
-static void mlx5_fc_pool_release_counter(struct mlx5_fc_pool *fc_pool, struct mlx5_fc *fc);
+static void mlx5_fc_pool_init(struct mlx5_fs_pool *fc_pool, struct mlx5_core_dev *dev);
+static void mlx5_fc_pool_cleanup(struct mlx5_fs_pool *fc_pool);
+static struct mlx5_fc *mlx5_fc_pool_acquire_counter(struct mlx5_fs_pool *fc_pool);
+static void mlx5_fc_pool_release_counter(struct mlx5_fs_pool *fc_pool, struct mlx5_fc *fc);
static int get_init_bulk_query_len(struct mlx5_core_dev *dev)
{
@@ -186,6 +182,9 @@ static void mlx5_fc_release(struct mlx5_core_dev *dev, struct mlx5_fc *counter)
{
struct mlx5_fc_stats *fc_stats = dev->priv.fc_stats;
+ if (WARN_ON(counter->type == MLX5_FC_TYPE_LOCAL))
+ return;
+
if (counter->bulk)
mlx5_fc_pool_release_counter(&fc_stats->fc_pool, counter);
else
@@ -438,11 +437,9 @@ void mlx5_fc_update_sampling_interval(struct mlx5_core_dev *dev,
/* Flow counter bluks */
struct mlx5_fc_bulk {
- struct list_head pool_list;
+ struct mlx5_fs_bulk fs_bulk;
u32 base_id;
- int bulk_len;
- unsigned long *bitmask;
- struct mlx5_fc fcs[] __counted_by(bulk_len);
+ struct mlx5_fc fcs[];
};
static void mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk,
@@ -452,16 +449,10 @@ static void mlx5_fc_init(struct mlx5_fc *counter, struct mlx5_fc_bulk *bulk,
counter->id = id;
}
-static int mlx5_fc_bulk_get_free_fcs_amount(struct mlx5_fc_bulk *bulk)
-{
- return bitmap_weight(bulk->bitmask, bulk->bulk_len);
-}
-
-static struct mlx5_fc_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
+static struct mlx5_fs_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
{
enum mlx5_fc_bulk_alloc_bitmask alloc_bitmask;
- struct mlx5_fc_bulk *bulk;
- int err = -ENOMEM;
+ struct mlx5_fc_bulk *fc_bulk;
int bulk_len;
u32 base_id;
int i;
@@ -469,207 +460,139 @@ static struct mlx5_fc_bulk *mlx5_fc_bulk_create(struct mlx5_core_dev *dev)
alloc_bitmask = MLX5_CAP_GEN(dev, flow_counter_bulk_alloc);
bulk_len = alloc_bitmask > 0 ? MLX5_FC_BULK_NUM_FCS(alloc_bitmask) : 1;
- bulk = kvzalloc(struct_size(bulk, fcs, bulk_len), GFP_KERNEL);
- if (!bulk)
- goto err_alloc_bulk;
+ fc_bulk = kvzalloc(struct_size(fc_bulk, fcs, bulk_len), GFP_KERNEL);
+ if (!fc_bulk)
+ return NULL;
- bulk->bitmask = kvcalloc(BITS_TO_LONGS(bulk_len), sizeof(unsigned long),
- GFP_KERNEL);
- if (!bulk->bitmask)
- goto err_alloc_bitmask;
-
- err = mlx5_cmd_fc_bulk_alloc(dev, alloc_bitmask, &base_id);
- if (err)
- goto err_mlx5_cmd_bulk_alloc;
+ if (mlx5_fs_bulk_init(dev, &fc_bulk->fs_bulk, bulk_len))
+ goto fc_bulk_free;
- bulk->base_id = base_id;
- bulk->bulk_len = bulk_len;
- for (i = 0; i < bulk_len; i++) {
- mlx5_fc_init(&bulk->fcs[i], bulk, base_id + i);
- set_bit(i, bulk->bitmask);
- }
+ if (mlx5_cmd_fc_bulk_alloc(dev, alloc_bitmask, &base_id))
+ goto fs_bulk_cleanup;
+ fc_bulk->base_id = base_id;
+ for (i = 0; i < bulk_len; i++)
+ mlx5_fc_init(&fc_bulk->fcs[i], fc_bulk, base_id + i);
- return bulk;
+ return &fc_bulk->fs_bulk;
-err_mlx5_cmd_bulk_alloc:
- kvfree(bulk->bitmask);
-err_alloc_bitmask:
- kvfree(bulk);
-err_alloc_bulk:
- return ERR_PTR(err);
+fs_bulk_cleanup:
+ mlx5_fs_bulk_cleanup(&fc_bulk->fs_bulk);
+fc_bulk_free:
+ kvfree(fc_bulk);
+ return NULL;
}
static int
-mlx5_fc_bulk_destroy(struct mlx5_core_dev *dev, struct mlx5_fc_bulk *bulk)
+mlx5_fc_bulk_destroy(struct mlx5_core_dev *dev, struct mlx5_fs_bulk *fs_bulk)
{
- if (mlx5_fc_bulk_get_free_fcs_amount(bulk) < bulk->bulk_len) {
+ struct mlx5_fc_bulk *fc_bulk = container_of(fs_bulk,
+ struct mlx5_fc_bulk,
+ fs_bulk);
+
+ if (mlx5_fs_bulk_get_free_amount(fs_bulk) < fs_bulk->bulk_len) {
mlx5_core_err(dev, "Freeing bulk before all counters were released\n");
return -EBUSY;
}
- mlx5_cmd_fc_free(dev, bulk->base_id);
- kvfree(bulk->bitmask);
- kvfree(bulk);
+ mlx5_cmd_fc_free(dev, fc_bulk->base_id);
+ mlx5_fs_bulk_cleanup(fs_bulk);
+ kvfree(fc_bulk);
return 0;
}
-static struct mlx5_fc *mlx5_fc_bulk_acquire_fc(struct mlx5_fc_bulk *bulk)
+static void mlx5_fc_pool_update_threshold(struct mlx5_fs_pool *fc_pool)
{
- int free_fc_index = find_first_bit(bulk->bitmask, bulk->bulk_len);
-
- if (free_fc_index >= bulk->bulk_len)
- return ERR_PTR(-ENOSPC);
-
- clear_bit(free_fc_index, bulk->bitmask);
- return &bulk->fcs[free_fc_index];
-}
-
-static int mlx5_fc_bulk_release_fc(struct mlx5_fc_bulk *bulk, struct mlx5_fc *fc)
-{
- int fc_index = fc->id - bulk->base_id;
-
- if (test_bit(fc_index, bulk->bitmask))
- return -EINVAL;
-
- set_bit(fc_index, bulk->bitmask);
- return 0;
+ fc_pool->threshold = min_t(int, MLX5_FC_POOL_MAX_THRESHOLD,
+ fc_pool->used_units / MLX5_FC_POOL_USED_BUFF_RATIO);
}
/* Flow counters pool API */
-static void mlx5_fc_pool_init(struct mlx5_fc_pool *fc_pool, struct mlx5_core_dev *dev)
-{
- fc_pool->dev = dev;
- mutex_init(&fc_pool->pool_lock);
- INIT_LIST_HEAD(&fc_pool->fully_used);
- INIT_LIST_HEAD(&fc_pool->partially_used);
- INIT_LIST_HEAD(&fc_pool->unused);
- fc_pool->available_fcs = 0;
- fc_pool->used_fcs = 0;
- fc_pool->threshold = 0;
-}
+static const struct mlx5_fs_pool_ops mlx5_fc_pool_ops = {
+ .bulk_destroy = mlx5_fc_bulk_destroy,
+ .bulk_create = mlx5_fc_bulk_create,
+ .update_threshold = mlx5_fc_pool_update_threshold,
+};
-static void mlx5_fc_pool_cleanup(struct mlx5_fc_pool *fc_pool)
+static void
+mlx5_fc_pool_init(struct mlx5_fs_pool *fc_pool, struct mlx5_core_dev *dev)
{
- struct mlx5_core_dev *dev = fc_pool->dev;
- struct mlx5_fc_bulk *bulk;
- struct mlx5_fc_bulk *tmp;
-
- list_for_each_entry_safe(bulk, tmp, &fc_pool->fully_used, pool_list)
- mlx5_fc_bulk_destroy(dev, bulk);
- list_for_each_entry_safe(bulk, tmp, &fc_pool->partially_used, pool_list)
- mlx5_fc_bulk_destroy(dev, bulk);
- list_for_each_entry_safe(bulk, tmp, &fc_pool->unused, pool_list)
- mlx5_fc_bulk_destroy(dev, bulk);
+ mlx5_fs_pool_init(fc_pool, dev, &mlx5_fc_pool_ops);
}
-static void mlx5_fc_pool_update_threshold(struct mlx5_fc_pool *fc_pool)
+static void mlx5_fc_pool_cleanup(struct mlx5_fs_pool *fc_pool)
{
- fc_pool->threshold = min_t(int, MLX5_FC_POOL_MAX_THRESHOLD,
- fc_pool->used_fcs / MLX5_FC_POOL_USED_BUFF_RATIO);
+ mlx5_fs_pool_cleanup(fc_pool);
}
-static struct mlx5_fc_bulk *
-mlx5_fc_pool_alloc_new_bulk(struct mlx5_fc_pool *fc_pool)
+static struct mlx5_fc *
+mlx5_fc_pool_acquire_counter(struct mlx5_fs_pool *fc_pool)
{
- struct mlx5_core_dev *dev = fc_pool->dev;
- struct mlx5_fc_bulk *new_bulk;
+ struct mlx5_fs_pool_index pool_index = {};
+ struct mlx5_fc_bulk *fc_bulk;
+ int err;
- new_bulk = mlx5_fc_bulk_create(dev);
- if (!IS_ERR(new_bulk))
- fc_pool->available_fcs += new_bulk->bulk_len;
- mlx5_fc_pool_update_threshold(fc_pool);
- return new_bulk;
+ err = mlx5_fs_pool_acquire_index(fc_pool, &pool_index);
+ if (err)
+ return ERR_PTR(err);
+ fc_bulk = container_of(pool_index.fs_bulk, struct mlx5_fc_bulk, fs_bulk);
+ return &fc_bulk->fcs[pool_index.index];
}
static void
-mlx5_fc_pool_free_bulk(struct mlx5_fc_pool *fc_pool, struct mlx5_fc_bulk *bulk)
+mlx5_fc_pool_release_counter(struct mlx5_fs_pool *fc_pool, struct mlx5_fc *fc)
{
+ struct mlx5_fs_bulk *fs_bulk = &fc->bulk->fs_bulk;
+ struct mlx5_fs_pool_index pool_index = {};
struct mlx5_core_dev *dev = fc_pool->dev;
- fc_pool->available_fcs -= bulk->bulk_len;
- mlx5_fc_bulk_destroy(dev, bulk);
- mlx5_fc_pool_update_threshold(fc_pool);
+ pool_index.fs_bulk = fs_bulk;
+ pool_index.index = fc->id - fc->bulk->base_id;
+ if (mlx5_fs_pool_release_index(fc_pool, &pool_index))
+ mlx5_core_warn(dev, "Attempted to release a counter which is not acquired\n");
}
-static struct mlx5_fc *
-mlx5_fc_pool_acquire_from_list(struct list_head *src_list,
- struct list_head *next_list,
- bool move_non_full_bulk)
+/**
+ * mlx5_fc_local_create - Allocate mlx5_fc struct for a counter which
+ * was already acquired using its counter id and bulk data.
+ *
+ * @counter_id: counter acquired counter id
+ * @offset: counter offset from bulk base
+ * @bulk_size: counter's bulk size as was allocated
+ *
+ * Return: Pointer to mlx5_fc on success, ERR_PTR otherwise.
+ */
+struct mlx5_fc *
+mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size)
{
- struct mlx5_fc_bulk *bulk;
- struct mlx5_fc *fc;
-
- if (list_empty(src_list))
- return ERR_PTR(-ENODATA);
-
- bulk = list_first_entry(src_list, struct mlx5_fc_bulk, pool_list);
- fc = mlx5_fc_bulk_acquire_fc(bulk);
- if (move_non_full_bulk || mlx5_fc_bulk_get_free_fcs_amount(bulk) == 0)
- list_move(&bulk->pool_list, next_list);
- return fc;
-}
+ struct mlx5_fc_bulk *fc_bulk;
+ struct mlx5_fc *counter;
-static struct mlx5_fc *
-mlx5_fc_pool_acquire_counter(struct mlx5_fc_pool *fc_pool)
-{
- struct mlx5_fc_bulk *new_bulk;
- struct mlx5_fc *fc;
-
- mutex_lock(&fc_pool->pool_lock);
-
- fc = mlx5_fc_pool_acquire_from_list(&fc_pool->partially_used,
- &fc_pool->fully_used, false);
- if (IS_ERR(fc))
- fc = mlx5_fc_pool_acquire_from_list(&fc_pool->unused,
- &fc_pool->partially_used,
- true);
- if (IS_ERR(fc)) {
- new_bulk = mlx5_fc_pool_alloc_new_bulk(fc_pool);
- if (IS_ERR(new_bulk)) {
- fc = ERR_CAST(new_bulk);
- goto out;
- }
- fc = mlx5_fc_bulk_acquire_fc(new_bulk);
- list_add(&new_bulk->pool_list, &fc_pool->partially_used);
+ counter = kzalloc(sizeof(*counter), GFP_KERNEL);
+ if (!counter)
+ return ERR_PTR(-ENOMEM);
+ fc_bulk = kzalloc(sizeof(*fc_bulk), GFP_KERNEL);
+ if (!fc_bulk) {
+ kfree(counter);
+ return ERR_PTR(-ENOMEM);
}
- fc_pool->available_fcs--;
- fc_pool->used_fcs++;
-out:
- mutex_unlock(&fc_pool->pool_lock);
- return fc;
+ counter->type = MLX5_FC_TYPE_LOCAL;
+ counter->id = counter_id;
+ fc_bulk->base_id = counter_id - offset;
+ fc_bulk->fs_bulk.bulk_len = bulk_size;
+ counter->bulk = fc_bulk;
+ return counter;
}
+EXPORT_SYMBOL(mlx5_fc_local_create);
-static void
-mlx5_fc_pool_release_counter(struct mlx5_fc_pool *fc_pool, struct mlx5_fc *fc)
+void mlx5_fc_local_destroy(struct mlx5_fc *counter)
{
- struct mlx5_core_dev *dev = fc_pool->dev;
- struct mlx5_fc_bulk *bulk = fc->bulk;
- int bulk_free_fcs_amount;
-
- mutex_lock(&fc_pool->pool_lock);
-
- if (mlx5_fc_bulk_release_fc(bulk, fc)) {
- mlx5_core_warn(dev, "Attempted to release a counter which is not acquired\n");
- goto unlock;
- }
-
- fc_pool->available_fcs++;
- fc_pool->used_fcs--;
-
- bulk_free_fcs_amount = mlx5_fc_bulk_get_free_fcs_amount(bulk);
- if (bulk_free_fcs_amount == 1)
- list_move_tail(&bulk->pool_list, &fc_pool->partially_used);
- if (bulk_free_fcs_amount == bulk->bulk_len) {
- list_del(&bulk->pool_list);
- if (fc_pool->available_fcs > fc_pool->threshold)
- mlx5_fc_pool_free_bulk(fc_pool, bulk);
- else
- list_add(&bulk->pool_list, &fc_pool->unused);
- }
+ if (!counter || counter->type != MLX5_FC_TYPE_LOCAL)
+ return;
-unlock:
- mutex_unlock(&fc_pool->pool_lock);
+ kfree(counter->bulk);
+ kfree(counter);
}
+EXPORT_SYMBOL(mlx5_fc_local_destroy);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_pool.c b/drivers/net/ethernet/mellanox/mlx5/core/fs_pool.c
new file mode 100644
index 000000000000..b891d7b9e3e0
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_pool.c
@@ -0,0 +1,194 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
+
+#include <mlx5_core.h>
+#include "fs_pool.h"
+
+int mlx5_fs_bulk_init(struct mlx5_core_dev *dev, struct mlx5_fs_bulk *fs_bulk,
+ int bulk_len)
+{
+ int i;
+
+ fs_bulk->bitmask = kvcalloc(BITS_TO_LONGS(bulk_len), sizeof(unsigned long),
+ GFP_KERNEL);
+ if (!fs_bulk->bitmask)
+ return -ENOMEM;
+
+ fs_bulk->bulk_len = bulk_len;
+ for (i = 0; i < bulk_len; i++)
+ set_bit(i, fs_bulk->bitmask);
+
+ return 0;
+}
+
+void mlx5_fs_bulk_cleanup(struct mlx5_fs_bulk *fs_bulk)
+{
+ kvfree(fs_bulk->bitmask);
+}
+
+int mlx5_fs_bulk_get_free_amount(struct mlx5_fs_bulk *bulk)
+{
+ return bitmap_weight(bulk->bitmask, bulk->bulk_len);
+}
+
+static int mlx5_fs_bulk_acquire_index(struct mlx5_fs_bulk *fs_bulk,
+ struct mlx5_fs_pool_index *pool_index)
+{
+ int free_index = find_first_bit(fs_bulk->bitmask, fs_bulk->bulk_len);
+
+ WARN_ON_ONCE(!pool_index || !fs_bulk);
+ if (free_index >= fs_bulk->bulk_len)
+ return -ENOSPC;
+
+ clear_bit(free_index, fs_bulk->bitmask);
+ pool_index->fs_bulk = fs_bulk;
+ pool_index->index = free_index;
+ return 0;
+}
+
+static int mlx5_fs_bulk_release_index(struct mlx5_fs_bulk *fs_bulk, int index)
+{
+ if (test_bit(index, fs_bulk->bitmask))
+ return -EINVAL;
+
+ set_bit(index, fs_bulk->bitmask);
+ return 0;
+}
+
+void mlx5_fs_pool_init(struct mlx5_fs_pool *pool, struct mlx5_core_dev *dev,
+ const struct mlx5_fs_pool_ops *ops)
+{
+ WARN_ON_ONCE(!ops || !ops->bulk_destroy || !ops->bulk_create ||
+ !ops->update_threshold);
+ pool->dev = dev;
+ mutex_init(&pool->pool_lock);
+ INIT_LIST_HEAD(&pool->fully_used);
+ INIT_LIST_HEAD(&pool->partially_used);
+ INIT_LIST_HEAD(&pool->unused);
+ pool->available_units = 0;
+ pool->used_units = 0;
+ pool->threshold = 0;
+ pool->ops = ops;
+}
+
+void mlx5_fs_pool_cleanup(struct mlx5_fs_pool *pool)
+{
+ struct mlx5_core_dev *dev = pool->dev;
+ struct mlx5_fs_bulk *bulk;
+ struct mlx5_fs_bulk *tmp;
+
+ list_for_each_entry_safe(bulk, tmp, &pool->fully_used, pool_list)
+ pool->ops->bulk_destroy(dev, bulk);
+ list_for_each_entry_safe(bulk, tmp, &pool->partially_used, pool_list)
+ pool->ops->bulk_destroy(dev, bulk);
+ list_for_each_entry_safe(bulk, tmp, &pool->unused, pool_list)
+ pool->ops->bulk_destroy(dev, bulk);
+}
+
+static struct mlx5_fs_bulk *
+mlx5_fs_pool_alloc_new_bulk(struct mlx5_fs_pool *fs_pool)
+{
+ struct mlx5_core_dev *dev = fs_pool->dev;
+ struct mlx5_fs_bulk *new_bulk;
+
+ new_bulk = fs_pool->ops->bulk_create(dev);
+ if (new_bulk)
+ fs_pool->available_units += new_bulk->bulk_len;
+ fs_pool->ops->update_threshold(fs_pool);
+ return new_bulk;
+}
+
+static void
+mlx5_fs_pool_free_bulk(struct mlx5_fs_pool *fs_pool, struct mlx5_fs_bulk *bulk)
+{
+ struct mlx5_core_dev *dev = fs_pool->dev;
+
+ fs_pool->available_units -= bulk->bulk_len;
+ fs_pool->ops->bulk_destroy(dev, bulk);
+ fs_pool->ops->update_threshold(fs_pool);
+}
+
+static int
+mlx5_fs_pool_acquire_from_list(struct list_head *src_list,
+ struct list_head *next_list,
+ bool move_non_full_bulk,
+ struct mlx5_fs_pool_index *pool_index)
+{
+ struct mlx5_fs_bulk *fs_bulk;
+ int err;
+
+ if (list_empty(src_list))
+ return -ENODATA;
+
+ fs_bulk = list_first_entry(src_list, struct mlx5_fs_bulk, pool_list);
+ err = mlx5_fs_bulk_acquire_index(fs_bulk, pool_index);
+ if (move_non_full_bulk || mlx5_fs_bulk_get_free_amount(fs_bulk) == 0)
+ list_move(&fs_bulk->pool_list, next_list);
+ return err;
+}
+
+int mlx5_fs_pool_acquire_index(struct mlx5_fs_pool *fs_pool,
+ struct mlx5_fs_pool_index *pool_index)
+{
+ struct mlx5_fs_bulk *new_bulk;
+ int err;
+
+ mutex_lock(&fs_pool->pool_lock);
+
+ err = mlx5_fs_pool_acquire_from_list(&fs_pool->partially_used,
+ &fs_pool->fully_used, false,
+ pool_index);
+ if (err)
+ err = mlx5_fs_pool_acquire_from_list(&fs_pool->unused,
+ &fs_pool->partially_used,
+ true, pool_index);
+ if (err) {
+ new_bulk = mlx5_fs_pool_alloc_new_bulk(fs_pool);
+ if (!new_bulk) {
+ err = -ENOENT;
+ goto out;
+ }
+ err = mlx5_fs_bulk_acquire_index(new_bulk, pool_index);
+ WARN_ON_ONCE(err);
+ list_add(&new_bulk->pool_list, &fs_pool->partially_used);
+ }
+ fs_pool->available_units--;
+ fs_pool->used_units++;
+
+out:
+ mutex_unlock(&fs_pool->pool_lock);
+ return err;
+}
+
+int mlx5_fs_pool_release_index(struct mlx5_fs_pool *fs_pool,
+ struct mlx5_fs_pool_index *pool_index)
+{
+ struct mlx5_fs_bulk *bulk = pool_index->fs_bulk;
+ int bulk_free_amount;
+ int err;
+
+ mutex_lock(&fs_pool->pool_lock);
+
+ /* TBD would rather return void if there was no warn here in original code */
+ err = mlx5_fs_bulk_release_index(bulk, pool_index->index);
+ if (err)
+ goto unlock;
+
+ fs_pool->available_units++;
+ fs_pool->used_units--;
+
+ bulk_free_amount = mlx5_fs_bulk_get_free_amount(bulk);
+ if (bulk_free_amount == 1)
+ list_move_tail(&bulk->pool_list, &fs_pool->partially_used);
+ if (bulk_free_amount == bulk->bulk_len) {
+ list_del(&bulk->pool_list);
+ if (fs_pool->available_units > fs_pool->threshold)
+ mlx5_fs_pool_free_bulk(fs_pool, bulk);
+ else
+ list_add(&bulk->pool_list, &fs_pool->unused);
+ }
+
+unlock:
+ mutex_unlock(&fs_pool->pool_lock);
+ return err;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/fs_pool.h b/drivers/net/ethernet/mellanox/mlx5/core/fs_pool.h
new file mode 100644
index 000000000000..3b149863260c
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/fs_pool.h
@@ -0,0 +1,54 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
+
+#ifndef __MLX5_FS_POOL_H__
+#define __MLX5_FS_POOL_H__
+
+#include <linux/mlx5/driver.h>
+
+struct mlx5_fs_bulk {
+ struct list_head pool_list;
+ int bulk_len;
+ unsigned long *bitmask;
+};
+
+struct mlx5_fs_pool_index {
+ struct mlx5_fs_bulk *fs_bulk;
+ int index;
+};
+
+struct mlx5_fs_pool;
+
+struct mlx5_fs_pool_ops {
+ int (*bulk_destroy)(struct mlx5_core_dev *dev, struct mlx5_fs_bulk *bulk);
+ struct mlx5_fs_bulk * (*bulk_create)(struct mlx5_core_dev *dev);
+ void (*update_threshold)(struct mlx5_fs_pool *pool);
+};
+
+struct mlx5_fs_pool {
+ struct mlx5_core_dev *dev;
+ void *pool_ctx;
+ const struct mlx5_fs_pool_ops *ops;
+ struct mutex pool_lock; /* protects pool lists */
+ struct list_head fully_used;
+ struct list_head partially_used;
+ struct list_head unused;
+ int available_units;
+ int used_units;
+ int threshold;
+};
+
+int mlx5_fs_bulk_init(struct mlx5_core_dev *dev, struct mlx5_fs_bulk *fs_bulk,
+ int bulk_len);
+void mlx5_fs_bulk_cleanup(struct mlx5_fs_bulk *fs_bulk);
+int mlx5_fs_bulk_get_free_amount(struct mlx5_fs_bulk *bulk);
+
+void mlx5_fs_pool_init(struct mlx5_fs_pool *pool, struct mlx5_core_dev *dev,
+ const struct mlx5_fs_pool_ops *ops);
+void mlx5_fs_pool_cleanup(struct mlx5_fs_pool *pool);
+int mlx5_fs_pool_acquire_index(struct mlx5_fs_pool *fs_pool,
+ struct mlx5_fs_pool_index *pool_index);
+int mlx5_fs_pool_release_index(struct mlx5_fs_pool *fs_pool,
+ struct mlx5_fs_pool_index *pool_index);
+
+#endif /* __MLX5_FS_POOL_H__ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c
index f4b777d4e108..62b6faa4276a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/debugfs.c
@@ -105,20 +105,20 @@ static int mapping_show(struct seq_file *file, void *priv)
struct mlx5_lag *ldev;
bool hash = false;
bool lag_active;
+ int i, idx = 0;
int num_ports;
- int i;
ldev = mlx5_lag_dev(dev);
mutex_lock(&ldev->lock);
lag_active = __mlx5_lag_is_active(ldev);
if (lag_active) {
if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &ldev->mode_flags)) {
- mlx5_infer_tx_enabled(&ldev->tracker, ldev->ports, ports,
+ mlx5_infer_tx_enabled(&ldev->tracker, ldev, ports,
&num_ports);
hash = true;
} else {
- for (i = 0; i < ldev->ports; i++)
- ports[i] = ldev->v2p_map[i];
+ mlx5_ldev_for_each(i, 0, ldev)
+ ports[idx++] = ldev->v2p_map[i];
num_ports = ldev->ports;
}
}
@@ -144,11 +144,8 @@ static int members_show(struct seq_file *file, void *priv)
ldev = mlx5_lag_dev(dev);
mutex_lock(&ldev->lock);
- for (i = 0; i < ldev->ports; i++) {
- if (!ldev->pf[i].dev)
- continue;
+ mlx5_ldev_for_each(i, 0, ldev)
seq_printf(file, "%s\n", dev_name(ldev->pf[i].dev->device));
- }
mutex_unlock(&ldev->lock);
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
index 7f68468c2e75..cea5aa314f6c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.c
@@ -43,10 +43,6 @@
#include "mp.h"
#include "mpesw.h"
-enum {
- MLX5_LAG_EGRESS_PORT_1 = 1,
- MLX5_LAG_EGRESS_PORT_2,
-};
/* General purpose, use for short periods of time.
* Beware of lock dependencies (preferably, no locks should be acquired
@@ -72,7 +68,7 @@ static u8 lag_active_port_bits(struct mlx5_lag *ldev)
int num_enabled;
int idx;
- mlx5_infer_tx_enabled(&ldev->tracker, ldev->ports, enabled_ports,
+ mlx5_infer_tx_enabled(&ldev->tracker, ldev, enabled_ports,
&num_enabled);
for (idx = 0; idx < num_enabled; idx++)
active_port |= BIT_MASK(enabled_ports[idx]);
@@ -80,23 +76,30 @@ static u8 lag_active_port_bits(struct mlx5_lag *ldev)
return active_port;
}
-static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 *ports, int mode,
- unsigned long flags)
+static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, struct mlx5_lag *ldev,
+ int mode, unsigned long flags)
{
bool fdb_sel_mode = test_bit(MLX5_LAG_MODE_FLAG_FDB_SEL_MODE_NATIVE,
&flags);
int port_sel_mode = get_port_sel_mode(mode, flags);
u32 in[MLX5_ST_SZ_DW(create_lag_in)] = {};
+ u8 *ports = ldev->v2p_map;
+ int idx0, idx1;
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, fdb_sel_mode);
+ idx0 = mlx5_lag_get_dev_index_by_seq(ldev, 0);
+ idx1 = mlx5_lag_get_dev_index_by_seq(ldev, 1);
+
+ if (idx0 < 0 || idx1 < 0)
+ return -EINVAL;
switch (port_sel_mode) {
case 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]);
+ MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[idx0]);
+ MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[idx1]);
break;
case MLX5_LAG_PORT_SELECT_MODE_PORT_SELECT_FT:
if (!MLX5_CAP_PORT_SELECTION(dev, port_select_flow_table_bypass))
@@ -113,17 +116,23 @@ static int mlx5_cmd_create_lag(struct mlx5_core_dev *dev, u8 *ports, int mode,
return mlx5_cmd_exec_in(dev, create_lag, in);
}
-static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, u8 num_ports,
+static int mlx5_cmd_modify_lag(struct mlx5_core_dev *dev, struct mlx5_lag *ldev,
u8 *ports)
{
u32 in[MLX5_ST_SZ_DW(modify_lag_in)] = {};
void *lag_ctx = MLX5_ADDR_OF(modify_lag_in, in, ctx);
+ int idx0, idx1;
+
+ idx0 = mlx5_lag_get_dev_index_by_seq(ldev, 0);
+ idx1 = mlx5_lag_get_dev_index_by_seq(ldev, 1);
+ if (idx0 < 0 || idx1 < 0)
+ return -EINVAL;
MLX5_SET(modify_lag_in, in, opcode, MLX5_CMD_OP_MODIFY_LAG);
MLX5_SET(modify_lag_in, in, field_select, 0x1);
- MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[0]);
- MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[1]);
+ MLX5_SET(lagc, lag_ctx, tx_remap_affinity_1, ports[idx0]);
+ MLX5_SET(lagc, lag_ctx, tx_remap_affinity_2, ports[idx1]);
return mlx5_cmd_exec_in(dev, modify_lag, in);
}
@@ -148,33 +157,31 @@ int mlx5_cmd_destroy_vport_lag(struct mlx5_core_dev *dev)
}
EXPORT_SYMBOL(mlx5_cmd_destroy_vport_lag);
-static void mlx5_infer_tx_disabled(struct lag_tracker *tracker, u8 num_ports,
+static void mlx5_infer_tx_disabled(struct lag_tracker *tracker, struct mlx5_lag *ldev,
u8 *ports, int *num_disabled)
{
int i;
*num_disabled = 0;
- for (i = 0; i < num_ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev)
if (!tracker->netdev_state[i].tx_enabled ||
!tracker->netdev_state[i].link_up)
ports[(*num_disabled)++] = i;
- }
}
-void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
+void mlx5_infer_tx_enabled(struct lag_tracker *tracker, struct mlx5_lag *ldev,
u8 *ports, int *num_enabled)
{
int i;
*num_enabled = 0;
- for (i = 0; i < num_ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev)
if (tracker->netdev_state[i].tx_enabled &&
tracker->netdev_state[i].link_up)
ports[(*num_enabled)++] = i;
- }
if (*num_enabled == 0)
- mlx5_infer_tx_disabled(tracker, num_ports, ports, num_enabled);
+ mlx5_infer_tx_disabled(tracker, ldev, ports, num_enabled);
}
static void mlx5_lag_print_mapping(struct mlx5_core_dev *dev,
@@ -192,7 +199,7 @@ static void mlx5_lag_print_mapping(struct mlx5_core_dev *dev,
int j;
if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &flags)) {
- mlx5_infer_tx_enabled(tracker, ldev->ports, enabled_ports,
+ mlx5_infer_tx_enabled(tracker, ldev, enabled_ports,
&num_enabled);
for (i = 0; i < num_enabled; i++) {
err = scnprintf(buf + written, 4, "%d, ", enabled_ports[i] + 1);
@@ -203,7 +210,7 @@ static void mlx5_lag_print_mapping(struct mlx5_core_dev *dev,
buf[written - 2] = 0;
mlx5_core_info(dev, "lag map active ports: %s\n", buf);
} else {
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
for (j = 0; j < ldev->buckets; j++) {
idx = i * ldev->buckets + j;
err = scnprintf(buf + written, 10,
@@ -286,13 +293,55 @@ int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
{
int i;
- for (i = 0; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev)
if (ldev->pf[i].netdev == ndev)
return i;
return -ENOENT;
}
+int mlx5_lag_get_dev_index_by_seq(struct mlx5_lag *ldev, int seq)
+{
+ int i, num = 0;
+
+ if (!ldev)
+ return -ENOENT;
+
+ mlx5_ldev_for_each(i, 0, ldev) {
+ if (num == seq)
+ return i;
+ num++;
+ }
+ return -ENOENT;
+}
+
+int mlx5_lag_num_devs(struct mlx5_lag *ldev)
+{
+ int i, num = 0;
+
+ if (!ldev)
+ return 0;
+
+ mlx5_ldev_for_each(i, 0, ldev) {
+ (void)i;
+ num++;
+ }
+ return num;
+}
+
+int mlx5_lag_num_netdevs(struct mlx5_lag *ldev)
+{
+ int i, num = 0;
+
+ if (!ldev)
+ return 0;
+
+ mlx5_ldev_for_each(i, 0, ldev)
+ if (ldev->pf[i].netdev)
+ num++;
+ return num;
+}
+
static bool __mlx5_lag_is_roce(struct mlx5_lag *ldev)
{
return ldev->mode == MLX5_LAG_MODE_ROCE;
@@ -310,7 +359,7 @@ static bool __mlx5_lag_is_sriov(struct mlx5_lag *ldev)
* with mapping that points to active ports.
*/
static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker,
- u8 num_ports,
+ struct mlx5_lag *ldev,
u8 buckets,
u8 *ports)
{
@@ -323,7 +372,7 @@ static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker,
int i;
int j;
- for (i = 0; i < num_ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
if (tracker->netdev_state[i].tx_enabled &&
tracker->netdev_state[i].link_up)
enabled[enabled_ports_num++] = i;
@@ -334,15 +383,16 @@ static void mlx5_infer_tx_affinity_mapping(struct lag_tracker *tracker,
/* Use native mapping by default where each port's buckets
* point the native port: 1 1 1 .. 1 2 2 2 ... 2 3 3 3 ... 3 etc
*/
- for (i = 0; i < num_ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev) {
for (j = 0; j < buckets; j++) {
idx = i * buckets + j;
- ports[idx] = MLX5_LAG_EGRESS_PORT_1 + i;
+ ports[idx] = i + 1;
}
+ }
/* If all ports are disabled/enabled keep native mapping */
- if (enabled_ports_num == num_ports ||
- disabled_ports_num == num_ports)
+ if (enabled_ports_num == ldev->ports ||
+ disabled_ports_num == ldev->ports)
return;
/* Go over the disabled ports and for each assign a random active port */
@@ -358,7 +408,7 @@ static bool mlx5_lag_has_drop_rule(struct mlx5_lag *ldev)
{
int i;
- for (i = 0; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev)
if (ldev->pf[i].has_drop)
return true;
return false;
@@ -368,7 +418,7 @@ static void mlx5_lag_drop_rule_cleanup(struct mlx5_lag *ldev)
{
int i;
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
if (!ldev->pf[i].has_drop)
continue;
@@ -396,7 +446,7 @@ static void mlx5_lag_drop_rule_setup(struct mlx5_lag *ldev,
if (!ldev->tracker.has_inactive)
return;
- mlx5_infer_tx_disabled(tracker, ldev->ports, disabled_ports, &num_disabled);
+ mlx5_infer_tx_disabled(tracker, ldev, disabled_ports, &num_disabled);
for (i = 0; i < num_disabled; i++) {
disabled_index = disabled_ports[i];
@@ -428,10 +478,15 @@ static int mlx5_cmd_modify_active_port(struct mlx5_core_dev *dev, u8 ports)
static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
{
- struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+ int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ struct mlx5_core_dev *dev0;
u8 active_ports;
int ret;
+ if (idx < 0)
+ return -EINVAL;
+
+ dev0 = ldev->pf[idx].dev;
if (test_bit(MLX5_LAG_MODE_FLAG_HASH_BASED, &ldev->mode_flags)) {
ret = mlx5_lag_port_sel_modify(ldev, ports);
if (ret ||
@@ -442,7 +497,7 @@ static int _mlx5_modify_lag(struct mlx5_lag *ldev, u8 *ports)
return mlx5_cmd_modify_active_port(dev0, active_ports);
}
- return mlx5_cmd_modify_lag(dev0, ldev->ports, ports);
+ return mlx5_cmd_modify_lag(dev0, ldev, ports);
}
static struct net_device *mlx5_lag_active_backup_get_netdev(struct mlx5_core_dev *dev)
@@ -450,7 +505,7 @@ static struct net_device *mlx5_lag_active_backup_get_netdev(struct mlx5_core_dev
struct net_device *ndev = NULL;
struct mlx5_lag *ldev;
unsigned long flags;
- int i;
+ int i, last_idx;
spin_lock_irqsave(&lag_lock, flags);
ldev = mlx5_lag_dev(dev);
@@ -458,11 +513,15 @@ static struct net_device *mlx5_lag_active_backup_get_netdev(struct mlx5_core_dev
if (!ldev)
goto unlock;
- for (i = 0; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev)
if (ldev->tracker.netdev_state[i].tx_enabled)
ndev = ldev->pf[i].netdev;
- if (!ndev)
- ndev = ldev->pf[ldev->ports - 1].netdev;
+ if (!ndev) {
+ last_idx = mlx5_lag_get_dev_index_by_seq(ldev, ldev->ports - 1);
+ if (last_idx < 0)
+ goto unlock;
+ ndev = ldev->pf[last_idx].netdev;
+ }
if (ndev)
dev_hold(ndev);
@@ -476,16 +535,21 @@ unlock:
void mlx5_modify_lag(struct mlx5_lag *ldev,
struct lag_tracker *tracker)
{
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
u8 ports[MLX5_MAX_PORTS * MLX5_LAG_MAX_HASH_BUCKETS] = {};
- struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+ struct mlx5_core_dev *dev0;
int idx;
int err;
int i;
int j;
- mlx5_infer_tx_affinity_mapping(tracker, ldev->ports, ldev->buckets, ports);
+ if (first_idx < 0)
+ return;
+
+ dev0 = ldev->pf[first_idx].dev;
+ mlx5_infer_tx_affinity_mapping(tracker, ldev, ldev->buckets, ports);
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
for (j = 0; j < ldev->buckets; j++) {
idx = i * ldev->buckets + j;
if (ports[idx] == ldev->v2p_map[idx])
@@ -523,8 +587,13 @@ void mlx5_modify_lag(struct mlx5_lag *ldev,
static int mlx5_lag_set_port_sel_mode_roce(struct mlx5_lag *ldev,
unsigned long *flags)
{
- struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ struct mlx5_core_dev *dev0;
+
+ if (first_idx < 0)
+ return -EINVAL;
+ dev0 = ldev->pf[first_idx].dev;
if (!MLX5_CAP_PORT_SELECTION(dev0, port_select_flow_table)) {
if (ldev->ports > 2)
return -EINVAL;
@@ -544,11 +613,13 @@ static void mlx5_lag_set_port_sel_mode_offloads(struct mlx5_lag *ldev,
enum mlx5_lag_mode mode,
unsigned long *flags)
{
- struct lag_func *dev0 = &ldev->pf[MLX5_LAG_P1];
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ struct lag_func *dev0;
- if (mode == MLX5_LAG_MODE_MPESW)
+ if (first_idx < 0 || mode == MLX5_LAG_MODE_MPESW)
return;
+ dev0 = &ldev->pf[first_idx];
if (MLX5_CAP_PORT_SELECTION(dev0->dev, port_select_flow_table) &&
tracker->tx_type == NETDEV_LAG_TX_TYPE_HASH) {
if (ldev->ports > 2)
@@ -593,12 +664,18 @@ char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags)
static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev)
{
- struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_eswitch *master_esw = dev0->priv.eswitch;
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ struct mlx5_eswitch *master_esw;
+ struct mlx5_core_dev *dev0;
+ int i, j;
int err;
- int i;
- for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) {
+ if (first_idx < 0)
+ return -EINVAL;
+
+ dev0 = ldev->pf[first_idx].dev;
+ master_esw = dev0->priv.eswitch;
+ mlx5_ldev_for_each(i, first_idx + 1, ldev) {
struct mlx5_eswitch *slave_esw = ldev->pf[i].dev->priv.eswitch;
err = mlx5_eswitch_offloads_single_fdb_add_one(master_esw,
@@ -608,9 +685,9 @@ static int mlx5_lag_create_single_fdb(struct mlx5_lag *ldev)
}
return 0;
err:
- for (; i > MLX5_LAG_P1; i--)
+ mlx5_ldev_for_each_reverse(j, i, first_idx + 1, ldev)
mlx5_eswitch_offloads_single_fdb_del_one(master_esw,
- ldev->pf[i].dev->priv.eswitch);
+ ldev->pf[j].dev->priv.eswitch);
return err;
}
@@ -620,16 +697,21 @@ static int mlx5_create_lag(struct mlx5_lag *ldev,
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;
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
+ struct mlx5_core_dev *dev0;
int err;
+ if (first_idx < 0)
+ return -EINVAL;
+
+ dev0 = ldev->pf[first_idx].dev;
if (tracker)
mlx5_lag_print_mapping(dev0, ldev, tracker, flags);
mlx5_core_info(dev0, "shared_fdb:%d mode:%s\n",
shared_fdb, mlx5_get_str_port_sel_mode(mode, flags));
- err = mlx5_cmd_create_lag(dev0, ldev->v2p_map, mode, flags);
+ err = mlx5_cmd_create_lag(dev0, ldev, mode, flags);
if (err) {
mlx5_core_err(dev0,
"Failed to create LAG (%d)\n",
@@ -661,17 +743,22 @@ int mlx5_activate_lag(struct mlx5_lag *ldev,
enum mlx5_lag_mode mode,
bool shared_fdb)
{
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
bool roce_lag = mode == MLX5_LAG_MODE_ROCE;
- struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+ struct mlx5_core_dev *dev0;
unsigned long flags = 0;
int err;
+ if (first_idx < 0)
+ return -EINVAL;
+
+ dev0 = ldev->pf[first_idx].dev;
err = mlx5_lag_set_flags(ldev, mode, tracker, shared_fdb, &flags);
if (err)
return err;
if (mode != MLX5_LAG_MODE_MPESW) {
- mlx5_infer_tx_affinity_mapping(tracker, ldev->ports, ldev->buckets, ldev->v2p_map);
+ mlx5_infer_tx_affinity_mapping(tracker, ldev, 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);
@@ -709,20 +796,26 @@ int mlx5_activate_lag(struct mlx5_lag *ldev,
int mlx5_deactivate_lag(struct mlx5_lag *ldev)
{
- struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
- struct mlx5_eswitch *master_esw = dev0->priv.eswitch;
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
u32 in[MLX5_ST_SZ_DW(destroy_lag_in)] = {};
bool roce_lag = __mlx5_lag_is_roce(ldev);
unsigned long flags = ldev->mode_flags;
+ struct mlx5_eswitch *master_esw;
+ struct mlx5_core_dev *dev0;
int err;
int i;
+ if (first_idx < 0)
+ return -EINVAL;
+
+ dev0 = ldev->pf[first_idx].dev;
+ master_esw = dev0->priv.eswitch;
ldev->mode = MLX5_LAG_MODE_NONE;
ldev->mode_flags = 0;
mlx5_lag_mp_reset(ldev);
if (test_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags)) {
- for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, first_idx + 1, ldev)
mlx5_eswitch_offloads_single_fdb_del_one(master_esw,
ldev->pf[i].dev->priv.eswitch);
clear_bit(MLX5_LAG_MODE_FLAG_SHARED_FDB, &flags);
@@ -754,6 +847,7 @@ int mlx5_deactivate_lag(struct mlx5_lag *ldev)
bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
{
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
#ifdef CONFIG_MLX5_ESWITCH
struct mlx5_core_dev *dev;
u8 mode;
@@ -761,30 +855,29 @@ bool mlx5_lag_check_prereq(struct mlx5_lag *ldev)
bool roce_support;
int i;
- for (i = 0; i < ldev->ports; i++)
- if (!ldev->pf[i].dev)
- return false;
+ if (first_idx < 0 || mlx5_lag_num_devs(ldev) != ldev->ports)
+ return false;
#ifdef CONFIG_MLX5_ESWITCH
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
dev = ldev->pf[i].dev;
if (mlx5_eswitch_num_vfs(dev->priv.eswitch) && !is_mdev_switchdev_mode(dev))
return false;
}
- dev = ldev->pf[MLX5_LAG_P1].dev;
+ dev = ldev->pf[first_idx].dev;
mode = mlx5_eswitch_mode(dev);
- for (i = 0; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev)
if (mlx5_eswitch_mode(ldev->pf[i].dev) != mode)
return false;
#else
- for (i = 0; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev)
if (mlx5_sriov_is_enabled(ldev->pf[i].dev))
return false;
#endif
- roce_support = mlx5_get_roce_state(ldev->pf[MLX5_LAG_P1].dev);
- for (i = 1; i < ldev->ports; i++)
+ roce_support = mlx5_get_roce_state(ldev->pf[first_idx].dev);
+ mlx5_ldev_for_each(i, first_idx + 1, ldev)
if (mlx5_get_roce_state(ldev->pf[i].dev) != roce_support)
return false;
@@ -795,10 +888,7 @@ void mlx5_lag_add_devices(struct mlx5_lag *ldev)
{
int i;
- for (i = 0; i < ldev->ports; i++) {
- if (!ldev->pf[i].dev)
- continue;
-
+ mlx5_ldev_for_each(i, 0, ldev) {
if (ldev->pf[i].dev->priv.flags &
MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)
continue;
@@ -812,10 +902,7 @@ void mlx5_lag_remove_devices(struct mlx5_lag *ldev)
{
int i;
- for (i = 0; i < ldev->ports; i++) {
- if (!ldev->pf[i].dev)
- continue;
-
+ mlx5_ldev_for_each(i, 0, ldev) {
if (ldev->pf[i].dev->priv.flags &
MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV)
continue;
@@ -828,11 +915,16 @@ void mlx5_lag_remove_devices(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;
+ int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ struct mlx5_core_dev *dev0;
bool roce_lag;
int err;
int i;
+ if (idx < 0)
+ return;
+
+ dev0 = ldev->pf[idx].dev;
roce_lag = __mlx5_lag_is_roce(ldev);
if (shared_fdb) {
@@ -842,7 +934,7 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
dev0->priv.flags |= MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0);
}
- for (i = 1; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, idx + 1, ldev)
mlx5_nic_vport_disable_roce(ldev->pf[i].dev);
}
@@ -854,17 +946,21 @@ void mlx5_disable_lag(struct mlx5_lag *ldev)
mlx5_lag_add_devices(ldev);
if (shared_fdb)
- for (i = 0; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev)
if (!(ldev->pf[i].dev->priv.flags & MLX5_PRIV_FLAGS_DISABLE_ALL_ADEV))
mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
}
static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
{
+ int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct mlx5_core_dev *dev;
int i;
- for (i = MLX5_LAG_P1 + 1; i < ldev->ports; i++) {
+ if (idx < 0)
+ return false;
+
+ mlx5_ldev_for_each(i, idx + 1, ldev) {
dev = ldev->pf[i].dev;
if (is_mdev_switchdev_mode(dev) &&
mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
@@ -876,7 +972,7 @@ static bool mlx5_shared_fdb_supported(struct mlx5_lag *ldev)
return false;
}
- dev = ldev->pf[MLX5_LAG_P1].dev;
+ dev = ldev->pf[idx].dev;
if (is_mdev_switchdev_mode(dev) &&
mlx5_eswitch_vport_match_metadata_enabled(dev->priv.eswitch) &&
mlx5_esw_offloads_devcom_is_ready(dev->priv.eswitch) &&
@@ -892,11 +988,11 @@ static bool mlx5_lag_is_roce_lag(struct mlx5_lag *ldev)
bool roce_lag = true;
int i;
- for (i = 0; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev)
roce_lag = roce_lag && !mlx5_sriov_is_enabled(ldev->pf[i].dev);
#ifdef CONFIG_MLX5_ESWITCH
- for (i = 0; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev)
roce_lag = roce_lag && is_mdev_legacy_mode(ldev->pf[i].dev);
#endif
@@ -917,13 +1013,18 @@ static bool mlx5_lag_should_disable_lag(struct mlx5_lag *ldev, bool do_bond)
static void mlx5_do_bond(struct mlx5_lag *ldev)
{
- struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+ int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct lag_tracker tracker = { };
+ struct mlx5_core_dev *dev0;
struct net_device *ndev;
bool do_bond, roce_lag;
int err;
int i;
+ if (idx < 0)
+ return;
+
+ dev0 = ldev->pf[idx].dev;
if (!mlx5_lag_is_ready(ldev)) {
do_bond = false;
} else {
@@ -956,7 +1057,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
} else if (roce_lag) {
dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0);
- for (i = 1; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, idx + 1, ldev) {
if (mlx5_get_roce_state(ldev->pf[i].dev))
mlx5_nic_vport_enable_roce(ldev->pf[i].dev);
}
@@ -966,7 +1067,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0);
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
err = mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
if (err)
break;
@@ -977,7 +1078,7 @@ static void mlx5_do_bond(struct mlx5_lag *ldev)
mlx5_rescan_drivers_locked(dev0);
mlx5_deactivate_lag(ldev);
mlx5_lag_add_devices(ldev);
- for (i = 0; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev)
mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
mlx5_core_err(dev0, "Failed to enable lag\n");
return;
@@ -1010,12 +1111,9 @@ struct mlx5_devcom_comp_dev *mlx5_lag_get_devcom_comp(struct mlx5_lag *ldev)
int i;
mutex_lock(&ldev->lock);
- for (i = 0; i < ldev->ports; i++) {
- if (ldev->pf[i].dev) {
- devcom = ldev->pf[i].dev->priv.hca_devcom_comp;
- break;
- }
- }
+ i = mlx5_get_next_ldev_func(ldev, 0);
+ if (i < MLX5_MAX_PORTS)
+ devcom = ldev->pf[i].dev->priv.hca_devcom_comp;
mutex_unlock(&ldev->lock);
return devcom;
}
@@ -1068,7 +1166,7 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev,
u8 bond_status = 0;
int num_slaves = 0;
int changed = 0;
- int idx;
+ int i, idx = -1;
if (!netif_is_lag_master(upper))
return 0;
@@ -1083,8 +1181,13 @@ static int mlx5_handle_changeupper_event(struct mlx5_lag *ldev,
*/
rcu_read_lock();
for_each_netdev_in_bond_rcu(upper, ndev_tmp) {
- idx = mlx5_lag_dev_get_netdev_idx(ldev, ndev_tmp);
- if (idx >= 0) {
+ mlx5_ldev_for_each(i, 0, ldev) {
+ if (ldev->pf[i].netdev == ndev_tmp) {
+ idx++;
+ break;
+ }
+ }
+ if (i < MLX5_MAX_PORTS) {
slave = bond_slave_get_rcu(ndev_tmp);
if (slave)
has_inactive |= bond_is_slave_inactive(slave);
@@ -1234,15 +1337,12 @@ static int mlx5_lag_netdev_event(struct notifier_block *this,
}
static void mlx5_ldev_add_netdev(struct mlx5_lag *ldev,
- struct mlx5_core_dev *dev,
- struct net_device *netdev)
+ struct mlx5_core_dev *dev,
+ struct net_device *netdev)
{
unsigned int fn = mlx5_get_dev_index(dev);
unsigned long flags;
- if (fn >= ldev->ports)
- return;
-
spin_lock_irqsave(&lag_lock, flags);
ldev->pf[fn].netdev = netdev;
ldev->tracker.netdev_state[fn].link_up = 0;
@@ -1257,7 +1357,7 @@ static void mlx5_ldev_remove_netdev(struct mlx5_lag *ldev,
int i;
spin_lock_irqsave(&lag_lock, flags);
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
if (ldev->pf[i].netdev == netdev) {
ldev->pf[i].netdev = NULL;
break;
@@ -1267,13 +1367,10 @@ static void mlx5_ldev_remove_netdev(struct mlx5_lag *ldev,
}
static void mlx5_ldev_add_mdev(struct mlx5_lag *ldev,
- struct mlx5_core_dev *dev)
+ struct mlx5_core_dev *dev)
{
unsigned int fn = mlx5_get_dev_index(dev);
- if (fn >= ldev->ports)
- return;
-
ldev->pf[fn].dev = dev;
dev->priv.lag = ldev;
}
@@ -1281,16 +1378,13 @@ static void mlx5_ldev_add_mdev(struct mlx5_lag *ldev,
static void mlx5_ldev_remove_mdev(struct mlx5_lag *ldev,
struct mlx5_core_dev *dev)
{
- int i;
-
- for (i = 0; i < ldev->ports; i++)
- if (ldev->pf[i].dev == dev)
- break;
+ int fn;
- if (i == ldev->ports)
+ fn = mlx5_get_dev_index(dev);
+ if (ldev->pf[fn].dev != dev)
return;
- ldev->pf[i].dev = NULL;
+ ldev->pf[fn].dev = NULL;
dev->priv.lag = NULL;
}
@@ -1398,7 +1492,7 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
struct net_device *netdev)
{
struct mlx5_lag *ldev;
- int i;
+ int num = 0;
ldev = mlx5_lag_dev(dev);
if (!ldev)
@@ -1406,17 +1500,33 @@ void mlx5_lag_add_netdev(struct mlx5_core_dev *dev,
mutex_lock(&ldev->lock);
mlx5_ldev_add_netdev(ldev, dev, netdev);
-
- for (i = 0; i < ldev->ports; i++)
- if (!ldev->pf[i].netdev)
- break;
-
- if (i >= ldev->ports)
+ num = mlx5_lag_num_netdevs(ldev);
+ if (num >= ldev->ports)
set_bit(MLX5_LAG_FLAG_NDEVS_READY, &ldev->state_flags);
mutex_unlock(&ldev->lock);
mlx5_queue_bond_work(ldev, 0);
}
+int mlx5_get_pre_ldev_func(struct mlx5_lag *ldev, int start_idx, int end_idx)
+{
+ int i;
+
+ for (i = start_idx; i >= end_idx; i--)
+ if (ldev->pf[i].dev)
+ return i;
+ return -1;
+}
+
+int mlx5_get_next_ldev_func(struct mlx5_lag *ldev, int start_idx)
+{
+ int i;
+
+ for (i = start_idx; i < MLX5_MAX_PORTS; i++)
+ if (ldev->pf[i].dev)
+ return i;
+ return MLX5_MAX_PORTS;
+}
+
bool mlx5_lag_is_roce(struct mlx5_core_dev *dev)
{
struct mlx5_lag *ldev;
@@ -1467,12 +1577,13 @@ bool mlx5_lag_is_master(struct mlx5_core_dev *dev)
{
struct mlx5_lag *ldev;
unsigned long flags;
- bool res;
+ bool res = false;
+ int idx;
spin_lock_irqsave(&lag_lock, flags);
ldev = mlx5_lag_dev(dev);
- res = ldev && __mlx5_lag_is_active(ldev) &&
- dev == ldev->pf[MLX5_LAG_P1].dev;
+ idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ res = ldev && __mlx5_lag_is_active(ldev) && idx >= 0 && dev == ldev->pf[idx].dev;
spin_unlock_irqrestore(&lag_lock, flags);
return res;
@@ -1555,7 +1666,7 @@ u8 mlx5_lag_get_slave_port(struct mlx5_core_dev *dev,
if (!(ldev && __mlx5_lag_is_roce(ldev)))
goto unlock;
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
if (ldev->pf[i].netdev == slave) {
port = i;
break;
@@ -1594,13 +1705,13 @@ struct mlx5_core_dev *mlx5_lag_get_next_peer_mdev(struct mlx5_core_dev *dev, int
if (!ldev)
goto unlock;
- if (*i == ldev->ports)
+ if (*i == MLX5_MAX_PORTS)
goto unlock;
- for (idx = *i; idx < ldev->ports; idx++)
+ mlx5_ldev_for_each(idx, *i, ldev)
if (ldev->pf[idx].dev != dev)
break;
- if (idx == ldev->ports) {
+ if (idx == MLX5_MAX_PORTS) {
*i = idx;
goto unlock;
}
@@ -1621,10 +1732,10 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
{
int outlen = MLX5_ST_SZ_BYTES(query_cong_statistics_out);
struct mlx5_core_dev **mdev;
+ int ret = 0, i, j, idx = 0;
struct mlx5_lag *ldev;
unsigned long flags;
int num_ports;
- int ret, i, j;
void *out;
out = kvzalloc(outlen, GFP_KERNEL);
@@ -1643,8 +1754,8 @@ int mlx5_lag_query_cong_counters(struct mlx5_core_dev *dev,
ldev = mlx5_lag_dev(dev);
if (ldev && __mlx5_lag_is_active(ldev)) {
num_ports = ldev->ports;
- for (i = 0; i < ldev->ports; i++)
- mdev[i] = ldev->pf[i].dev;
+ mlx5_ldev_for_each(i, 0, ldev)
+ mdev[idx++] = ldev->pf[i].dev;
} else {
num_ports = 1;
mdev[MLX5_LAG_P1] = dev;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
index 50fcb1eee574..01cf72366947 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/lag.h
@@ -103,7 +103,7 @@ int mlx5_lag_dev_get_netdev_idx(struct mlx5_lag *ldev,
struct net_device *ndev);
char *mlx5_get_str_port_sel_mode(enum mlx5_lag_mode mode, unsigned long flags);
-void mlx5_infer_tx_enabled(struct lag_tracker *tracker, u8 num_ports,
+void mlx5_infer_tx_enabled(struct lag_tracker *tracker, struct mlx5_lag *ldev,
u8 *ports, int *num_enabled);
void mlx5_ldev_add_debugfs(struct mlx5_core_dev *dev);
@@ -119,9 +119,24 @@ static inline bool mlx5_lag_is_supported(struct mlx5_core_dev *dev)
if (!MLX5_CAP_GEN(dev, vport_group_manager) ||
!MLX5_CAP_GEN(dev, lag_master) ||
MLX5_CAP_GEN(dev, num_lag_ports) < 2 ||
+ mlx5_get_dev_index(dev) >= MLX5_MAX_PORTS ||
MLX5_CAP_GEN(dev, num_lag_ports) > MLX5_MAX_PORTS)
return false;
return true;
}
+#define mlx5_ldev_for_each(i, start_index, ldev) \
+ for (int tmp = start_index; tmp = mlx5_get_next_ldev_func(ldev, tmp), \
+ i = tmp, tmp < MLX5_MAX_PORTS; tmp++)
+
+#define mlx5_ldev_for_each_reverse(i, start_index, end_index, ldev) \
+ for (int tmp = start_index, tmp1 = end_index; \
+ tmp = mlx5_get_pre_ldev_func(ldev, tmp, tmp1), \
+ i = tmp, tmp >= tmp1; tmp--)
+
+int mlx5_get_pre_ldev_func(struct mlx5_lag *ldev, int start_idx, int end_idx);
+int mlx5_get_next_ldev_func(struct mlx5_lag *ldev, int start_idx);
+int mlx5_lag_get_dev_index_by_seq(struct mlx5_lag *ldev, int seq);
+int mlx5_lag_num_devs(struct mlx5_lag *ldev);
+int mlx5_lag_num_netdevs(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 b1aa494c76ba..aee17fcf3b36 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mp.c
@@ -17,7 +17,10 @@ static bool __mlx5_lag_is_multipath(struct mlx5_lag *ldev)
#define MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS 2
static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
{
- if (!mlx5_lag_is_ready(ldev))
+ int idx0 = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ int idx1 = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P2);
+
+ if (idx0 < 0 || idx1 < 0 || !mlx5_lag_is_ready(ldev))
return false;
if (__mlx5_lag_is_active(ldev) && !__mlx5_lag_is_multipath(ldev))
@@ -26,8 +29,8 @@ static bool mlx5_lag_multipath_check_prereq(struct mlx5_lag *ldev)
if (ldev->ports > MLX5_LAG_MULTIPATH_OFFLOADS_SUPPORTED_PORTS)
return false;
- return mlx5_esw_multipath_prereq(ldev->pf[MLX5_LAG_P1].dev,
- ldev->pf[MLX5_LAG_P2].dev);
+ return mlx5_esw_multipath_prereq(ldev->pf[idx0].dev,
+ ldev->pf[idx1].dev);
}
bool mlx5_lag_is_multipath(struct mlx5_core_dev *dev)
@@ -50,43 +53,45 @@ bool mlx5_lag_is_multipath(struct mlx5_core_dev *dev)
static void mlx5_lag_set_port_affinity(struct mlx5_lag *ldev,
enum mlx5_lag_port_affinity port)
{
+ int idx0 = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ int idx1 = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P2);
struct lag_tracker tracker = {};
- if (!__mlx5_lag_is_multipath(ldev))
+ if (idx0 < 0 || idx1 < 0 || !__mlx5_lag_is_multipath(ldev))
return;
switch (port) {
case MLX5_LAG_NORMAL_AFFINITY:
- tracker.netdev_state[MLX5_LAG_P1].tx_enabled = true;
- tracker.netdev_state[MLX5_LAG_P2].tx_enabled = true;
- tracker.netdev_state[MLX5_LAG_P1].link_up = true;
- tracker.netdev_state[MLX5_LAG_P2].link_up = true;
+ tracker.netdev_state[idx0].tx_enabled = true;
+ tracker.netdev_state[idx1].tx_enabled = true;
+ tracker.netdev_state[idx0].link_up = true;
+ tracker.netdev_state[idx1].link_up = true;
break;
case MLX5_LAG_P1_AFFINITY:
- tracker.netdev_state[MLX5_LAG_P1].tx_enabled = true;
- tracker.netdev_state[MLX5_LAG_P1].link_up = true;
- tracker.netdev_state[MLX5_LAG_P2].tx_enabled = false;
- tracker.netdev_state[MLX5_LAG_P2].link_up = false;
+ tracker.netdev_state[idx0].tx_enabled = true;
+ tracker.netdev_state[idx0].link_up = true;
+ tracker.netdev_state[idx1].tx_enabled = false;
+ tracker.netdev_state[idx1].link_up = false;
break;
case MLX5_LAG_P2_AFFINITY:
- tracker.netdev_state[MLX5_LAG_P1].tx_enabled = false;
- tracker.netdev_state[MLX5_LAG_P1].link_up = false;
- tracker.netdev_state[MLX5_LAG_P2].tx_enabled = true;
- tracker.netdev_state[MLX5_LAG_P2].link_up = true;
+ tracker.netdev_state[idx0].tx_enabled = false;
+ tracker.netdev_state[idx0].link_up = false;
+ tracker.netdev_state[idx1].tx_enabled = true;
+ tracker.netdev_state[idx1].link_up = true;
break;
default:
- mlx5_core_warn(ldev->pf[MLX5_LAG_P1].dev,
+ mlx5_core_warn(ldev->pf[idx0].dev,
"Invalid affinity port %d", port);
return;
}
- if (tracker.netdev_state[MLX5_LAG_P1].tx_enabled)
- mlx5_notifier_call_chain(ldev->pf[MLX5_LAG_P1].dev->priv.events,
+ if (tracker.netdev_state[idx0].tx_enabled)
+ mlx5_notifier_call_chain(ldev->pf[idx0].dev->priv.events,
MLX5_DEV_EVENT_PORT_AFFINITY,
(void *)0);
- if (tracker.netdev_state[MLX5_LAG_P2].tx_enabled)
- mlx5_notifier_call_chain(ldev->pf[MLX5_LAG_P2].dev->priv.events,
+ if (tracker.netdev_state[idx1].tx_enabled)
+ mlx5_notifier_call_chain(ldev->pf[idx1].dev->priv.events,
MLX5_DEV_EVENT_PORT_AFFINITY,
(void *)0);
@@ -150,9 +155,14 @@ mlx5_lag_get_next_fib_dev(struct mlx5_lag *ldev,
static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event,
struct fib_entry_notifier_info *fen_info)
{
+ int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct net_device *nh_dev0, *nh_dev1;
struct fib_info *fi = fen_info->fi;
struct lag_mp *mp = &ldev->lag_mp;
+ int i, dev_idx = 0;
+
+ if (idx < 0)
+ return;
/* Handle delete event */
if (event == FIB_EVENT_ENTRY_DEL) {
@@ -179,17 +189,19 @@ static void mlx5_lag_fib_route_event(struct mlx5_lag *ldev, unsigned long event,
}
if (nh_dev0 == nh_dev1) {
- mlx5_core_warn(ldev->pf[MLX5_LAG_P1].dev,
+ mlx5_core_warn(ldev->pf[idx].dev,
"Multipath offload doesn't support routes with multiple nexthops of the same device");
return;
}
if (!nh_dev1) {
if (__mlx5_lag_is_active(ldev)) {
- int i = mlx5_lag_dev_get_netdev_idx(ldev, nh_dev0);
-
- i++;
- mlx5_lag_set_port_affinity(ldev, i);
+ mlx5_ldev_for_each(i, 0, ldev) {
+ dev_idx++;
+ if (ldev->pf[i].netdev == nh_dev0)
+ break;
+ }
+ mlx5_lag_set_port_affinity(ldev, dev_idx);
mlx5_lag_fib_set(mp, fi, fen_info->dst, fen_info->dst_len);
}
@@ -214,6 +226,7 @@ static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev,
struct fib_info *fi)
{
struct lag_mp *mp = &ldev->lag_mp;
+ int i, dev_idx = 0;
/* Check the nh event is related to the route */
if (!mp->fib.mfi || mp->fib.mfi != fi)
@@ -221,11 +234,15 @@ static void mlx5_lag_fib_nexthop_event(struct mlx5_lag *ldev,
/* nh added/removed */
if (event == FIB_EVENT_NH_DEL) {
- int i = mlx5_lag_dev_get_netdev_idx(ldev, fib_nh->fib_nh_dev);
+ mlx5_ldev_for_each(i, 0, ldev) {
+ if (ldev->pf[i].netdev == fib_nh->fib_nh_dev)
+ break;
+ dev_idx++;
+ }
- if (i >= 0) {
- i = (i + 1) % 2 + 1; /* peer port */
- mlx5_lag_set_port_affinity(ldev, i);
+ if (dev_idx >= 0) {
+ dev_idx = (dev_idx + 1) % 2 + 1; /* peer port */
+ mlx5_lag_set_port_affinity(ldev, dev_idx);
}
} else if (event == FIB_EVENT_NH_ADD &&
fib_info_num_path(fi) == 2) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
index 571ea26edd0c..ffac0bd6c895 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/mpesw.c
@@ -15,7 +15,7 @@ static void mlx5_mpesw_metadata_cleanup(struct mlx5_lag *ldev)
u32 pf_metadata;
int i;
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
dev = ldev->pf[i].dev;
esw = dev->priv.eswitch;
pf_metadata = ldev->lag_mpesw.pf_metadata[i];
@@ -36,7 +36,7 @@ static int mlx5_mpesw_metadata_set(struct mlx5_lag *ldev)
u32 pf_metadata;
int i, err;
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
dev = ldev->pf[i].dev;
esw = dev->priv.eswitch;
pf_metadata = mlx5_esw_match_metadata_alloc(esw);
@@ -52,7 +52,7 @@ static int mlx5_mpesw_metadata_set(struct mlx5_lag *ldev)
goto err_metadata;
}
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
dev = ldev->pf[i].dev;
mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_MULTIPORT_ESW,
(void *)0);
@@ -68,13 +68,15 @@ err_metadata:
#define MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS 4
static int enable_mpesw(struct mlx5_lag *ldev)
{
- struct mlx5_core_dev *dev0 = ldev->pf[MLX5_LAG_P1].dev;
+ int idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ struct mlx5_core_dev *dev0;
int err;
int i;
- if (ldev->mode != MLX5_LAG_MODE_NONE)
+ if (idx < 0 || ldev->mode != MLX5_LAG_MODE_NONE)
return -EINVAL;
+ dev0 = ldev->pf[idx].dev;
if (ldev->ports > MLX5_LAG_MPESW_OFFLOADS_SUPPORTED_PORTS)
return -EOPNOTSUPP;
@@ -98,7 +100,7 @@ static int enable_mpesw(struct mlx5_lag *ldev)
dev0->priv.flags &= ~MLX5_PRIV_FLAGS_DISABLE_IB_ADEV;
mlx5_rescan_drivers_locked(dev0);
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
err = mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
if (err)
goto err_rescan_drivers;
@@ -112,7 +114,7 @@ err_rescan_drivers:
mlx5_deactivate_lag(ldev);
err_add_devices:
mlx5_lag_add_devices(ldev);
- for (i = 0; i < ldev->ports; i++)
+ mlx5_ldev_for_each(i, 0, ldev)
mlx5_eswitch_reload_ib_reps(ldev->pf[i].dev->priv.eswitch);
mlx5_mpesw_metadata_cleanup(ldev);
return err;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
index ab2717012b79..22241f52716c 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lag/port_sel.c
@@ -39,15 +39,18 @@ static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev,
struct mlx5_lag_definer *lag_definer,
u8 *ports)
{
- struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct mlx5_flow_table_attr ft_attr = {};
struct mlx5_flow_destination dest = {};
MLX5_DECLARE_FLOW_ACT(flow_act);
struct mlx5_flow_namespace *ns;
- int err, i;
- int idx;
- int j;
+ struct mlx5_core_dev *dev;
+ int err, i, j, k, idx;
+
+ if (first_idx < 0)
+ return -EINVAL;
+ dev = ldev->pf[first_idx].dev;
ft_attr.max_fte = ldev->ports * ldev->buckets;
ft_attr.level = MLX5_LAG_FT_LEVEL_DEFINER;
@@ -74,7 +77,7 @@ static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev,
dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
flow_act.flags |= FLOW_ACT_NO_APPEND;
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
for (j = 0; j < ldev->buckets; j++) {
u8 affinity;
@@ -88,13 +91,13 @@ static int mlx5_lag_create_port_sel_table(struct mlx5_lag *ldev,
&dest, 1);
if (IS_ERR(lag_definer->rules[idx])) {
err = PTR_ERR(lag_definer->rules[idx]);
- do {
+ mlx5_ldev_for_each_reverse(k, i, 0, ldev) {
while (j--) {
- idx = i * ldev->buckets + j;
+ idx = k * ldev->buckets + j;
mlx5_del_flow_rules(lag_definer->rules[idx]);
}
j = ldev->buckets;
- } while (i--);
+ };
goto destroy_fg;
}
}
@@ -295,11 +298,16 @@ static struct mlx5_lag_definer *
mlx5_lag_create_definer(struct mlx5_lag *ldev, enum netdev_lag_hash hash,
enum mlx5_traffic_types tt, bool tunnel, u8 *ports)
{
- struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct mlx5_lag_definer *lag_definer;
+ struct mlx5_core_dev *dev;
u32 *match_definer_mask;
int format_id, err;
+ if (first_idx < 0)
+ return ERR_PTR(-EINVAL);
+
+ dev = ldev->pf[first_idx].dev;
lag_definer = kzalloc(sizeof(*lag_definer), GFP_KERNEL);
if (!lag_definer)
return ERR_PTR(-ENOMEM);
@@ -341,12 +349,15 @@ free_lag_definer:
static void mlx5_lag_destroy_definer(struct mlx5_lag *ldev,
struct mlx5_lag_definer *lag_definer)
{
- struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
- int idx;
- int i;
- int j;
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
+ struct mlx5_core_dev *dev;
+ int idx, i, j;
+
+ if (first_idx < 0)
+ return;
- for (i = 0; i < ldev->ports; i++) {
+ dev = ldev->pf[first_idx].dev;
+ mlx5_ldev_for_each(i, first_idx, ldev) {
for (j = 0; j < ldev->buckets; j++) {
idx = i * ldev->buckets + j;
mlx5_del_flow_rules(lag_definer->rules[idx]);
@@ -501,10 +512,15 @@ static void mlx5_lag_set_outer_ttc_params(struct mlx5_lag *ldev,
static int mlx5_lag_create_ttc_table(struct mlx5_lag *ldev)
{
- struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
struct ttc_params ttc_params = {};
+ struct mlx5_core_dev *dev;
+ if (first_idx < 0)
+ return -EINVAL;
+
+ dev = ldev->pf[first_idx].dev;
mlx5_lag_set_outer_ttc_params(ldev, &ttc_params);
port_sel->outer.ttc = mlx5_create_ttc_table(dev, &ttc_params);
return PTR_ERR_OR_ZERO(port_sel->outer.ttc);
@@ -512,10 +528,15 @@ static int mlx5_lag_create_ttc_table(struct mlx5_lag *ldev)
static int mlx5_lag_create_inner_ttc_table(struct mlx5_lag *ldev)
{
- struct mlx5_core_dev *dev = ldev->pf[MLX5_LAG_P1].dev;
+ int first_idx = mlx5_lag_get_dev_index_by_seq(ldev, MLX5_LAG_P1);
struct mlx5_lag_port_sel *port_sel = &ldev->port_sel;
struct ttc_params ttc_params = {};
+ struct mlx5_core_dev *dev;
+
+ if (first_idx < 0)
+ return -EINVAL;
+ dev = ldev->pf[first_idx].dev;
mlx5_lag_set_inner_ttc_params(ldev, &ttc_params);
port_sel->inner.ttc = mlx5_create_inner_ttc_table(dev, &ttc_params);
return PTR_ERR_OR_ZERO(port_sel->inner.ttc);
@@ -565,7 +586,7 @@ static int __mlx5_lag_modify_definers_destinations(struct mlx5_lag *ldev,
dest.type = MLX5_FLOW_DESTINATION_TYPE_UPLINK;
dest.vport.flags |= MLX5_FLOW_DEST_VPORT_VHCA_ID;
- for (i = 0; i < ldev->ports; i++) {
+ mlx5_ldev_for_each(i, 0, ldev) {
for (j = 0; j < ldev->buckets; j++) {
idx = i * ldev->buckets + j;
if (ldev->v2p_map[idx] == ports[idx])
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
index 4822d01123b4..d61a1a9297c9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/clock.c
@@ -322,17 +322,16 @@ static void mlx5_pps_out(struct work_struct *work)
}
}
-static void mlx5_timestamp_overflow(struct work_struct *work)
+static long mlx5_timestamp_overflow(struct ptp_clock_info *ptp_info)
{
- struct delayed_work *dwork = to_delayed_work(work);
struct mlx5_core_dev *mdev;
struct mlx5_timer *timer;
struct mlx5_clock *clock;
unsigned long flags;
- timer = container_of(dwork, struct mlx5_timer, overflow_work);
- clock = container_of(timer, struct mlx5_clock, timer);
+ clock = container_of(ptp_info, struct mlx5_clock, ptp_info);
mdev = container_of(clock, struct mlx5_core_dev, clock);
+ timer = &clock->timer;
if (mdev->state == MLX5_DEVICE_STATE_INTERNAL_ERROR)
goto out;
@@ -343,7 +342,7 @@ static void mlx5_timestamp_overflow(struct work_struct *work)
write_sequnlock_irqrestore(&clock->lock, flags);
out:
- schedule_delayed_work(&timer->overflow_work, timer->overflow_period);
+ return timer->overflow_period;
}
static int mlx5_ptp_settime_real_time(struct mlx5_core_dev *mdev,
@@ -517,6 +516,7 @@ static int mlx5_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm)
timer->cycles.mult = mult;
mlx5_update_clock_info_page(mdev);
write_sequnlock_irqrestore(&clock->lock, flags);
+ ptp_schedule_worker(clock->ptp, timer->overflow_period);
return 0;
}
@@ -852,6 +852,7 @@ static const struct ptp_clock_info mlx5_ptp_clock_info = {
.settime64 = mlx5_ptp_settime,
.enable = NULL,
.verify = NULL,
+ .do_aux_work = mlx5_timestamp_overflow,
};
static int mlx5_query_mtpps_pin_mode(struct mlx5_core_dev *mdev, u8 pin,
@@ -1052,12 +1053,11 @@ static void mlx5_init_overflow_period(struct mlx5_clock *clock)
do_div(ns, NSEC_PER_SEC / HZ);
timer->overflow_period = ns;
- INIT_DELAYED_WORK(&timer->overflow_work, mlx5_timestamp_overflow);
- if (timer->overflow_period)
- schedule_delayed_work(&timer->overflow_work, 0);
- else
+ if (!timer->overflow_period) {
+ timer->overflow_period = HZ;
mlx5_core_warn(mdev,
- "invalid overflow period, overflow_work is not scheduled\n");
+ "invalid overflow period, overflow_work is scheduled once per second\n");
+ }
if (clock_info)
clock_info->overflow_period = timer->overflow_period;
@@ -1172,6 +1172,9 @@ void mlx5_init_clock(struct mlx5_core_dev *mdev)
MLX5_NB_INIT(&clock->pps_nb, mlx5_pps_event, PPS_EVENT);
mlx5_eq_notifier_register(mdev, &clock->pps_nb);
+
+ if (clock->ptp)
+ ptp_schedule_worker(clock->ptp, 0);
}
void mlx5_cleanup_clock(struct mlx5_core_dev *mdev)
@@ -1188,7 +1191,6 @@ void mlx5_cleanup_clock(struct mlx5_core_dev *mdev)
}
cancel_work_sync(&clock->pps_info.out_work);
- cancel_delayed_work_sync(&clock->timer.overflow_work);
if (mdev->clock_info) {
free_page((unsigned long)mdev->clock_info);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c
index 4a078113e292..762d55ba9e51 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/lib/macsec_fs.c
@@ -497,7 +497,7 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs)
memset(&dest, 0, sizeof(struct mlx5_flow_destination));
memset(&flow_act, 0, sizeof(flow_act));
dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest.counter_id = mlx5_fc_id(tx_tables->check_miss_rule_counter);
+ dest.counter = tx_tables->check_miss_rule_counter;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
rule = mlx5_add_flow_rules(tx_tables->ft_check, NULL, &flow_act, &dest, 1);
if (IS_ERR(rule)) {
@@ -519,7 +519,7 @@ static int macsec_fs_tx_create(struct mlx5_macsec_fs *macsec_fs)
flow_act.flags = FLOW_ACT_NO_APPEND;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_ALLOW | MLX5_FLOW_CONTEXT_ACTION_COUNT;
dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest.counter_id = mlx5_fc_id(tx_tables->check_rule_counter);
+ dest.counter = tx_tables->check_rule_counter;
rule = mlx5_add_flow_rules(tx_tables->ft_check, spec, &flow_act, &dest, 1);
if (IS_ERR(rule)) {
err = PTR_ERR(rule);
@@ -1200,7 +1200,7 @@ static int macsec_fs_rx_create_check_decap_rule(struct mlx5_macsec_fs *macsec_fs
flow_act->action |= MLX5_FLOW_CONTEXT_ACTION_PACKET_REFORMAT |
MLX5_FLOW_CONTEXT_ACTION_COUNT;
roce_dest[dstn].type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- roce_dest[dstn].counter_id = mlx5_fc_id(rx_tables->check_rule_counter);
+ roce_dest[dstn].counter = rx_tables->check_rule_counter;
rule = mlx5_add_flow_rules(rx_tables->ft_check, spec, flow_act, roce_dest, dstn + 1);
if (IS_ERR(rule)) {
@@ -1592,7 +1592,7 @@ static int macsec_fs_rx_create(struct mlx5_macsec_fs *macsec_fs)
memset(&flow_act, 0, sizeof(flow_act));
dest.type = MLX5_FLOW_DESTINATION_TYPE_COUNTER;
- dest.counter_id = mlx5_fc_id(rx_tables->check_miss_rule_counter);
+ dest.counter = rx_tables->check_miss_rule_counter;
flow_act.action = MLX5_FLOW_CONTEXT_ACTION_DROP | MLX5_FLOW_CONTEXT_ACTION_COUNT;
rule = mlx5_add_flow_rules(rx_tables->ft_check, NULL, &flow_act, &dest, 1);
if (IS_ERR(rule)) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/main.c b/drivers/net/ethernet/mellanox/mlx5/core/main.c
index 220a9ac75c8b..a108d8c726f8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/main.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/main.c
@@ -664,6 +664,10 @@ static int handle_hca_cap(struct mlx5_core_dev *dev, void *set_ctx)
MLX5_SET(cmd_hca_cap, set_hca_cap, log_max_current_uc_list,
ilog2(max_uc_list));
+ /* enable absolute native port num */
+ if (MLX5_CAP_GEN_MAX(dev, abs_native_port_num))
+ MLX5_SET(cmd_hca_cap, set_hca_cap, abs_native_port_num, 1);
+
return set_caps(dev, set_ctx, MLX5_SET_HCA_CAP_OP_MOD_GENERAL_DEVICE);
}
@@ -941,9 +945,7 @@ static int mlx5_pci_init(struct mlx5_core_dev *dev, struct pci_dev *pdev,
mlx5_pci_vsc_init(dev);
- err = pci_enable_ptm(pdev, NULL);
- if (err)
- mlx5_core_info(dev, "PTM is not supported by PCIe\n");
+ pci_enable_ptm(pdev, NULL);
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/rl.c b/drivers/net/ethernet/mellanox/mlx5/core/rl.c
index e393391966e0..39a209b9b684 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/rl.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/rl.c
@@ -56,6 +56,8 @@ bool mlx5_qos_tsar_type_supported(struct mlx5_core_dev *dev, int type, u8 hierar
return cap & TSAR_TYPE_CAP_MASK_ROUND_ROBIN;
case TSAR_ELEMENT_TSAR_TYPE_ETS:
return cap & TSAR_TYPE_CAP_MASK_ETS;
+ case TSAR_ELEMENT_TSAR_TYPE_TC_ARB:
+ return cap & TSAR_TYPE_CAP_MASK_TC_ARB;
}
return false;
@@ -87,6 +89,8 @@ bool mlx5_qos_element_type_supported(struct mlx5_core_dev *dev, int type, u8 hie
return cap & ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC;
case SCHEDULING_CONTEXT_ELEMENT_TYPE_QUEUE_GROUP:
return cap & ELEMENT_TYPE_CAP_MASK_QUEUE_GROUP;
+ case SCHEDULING_CONTEXT_ELEMENT_TYPE_RATE_LIMIT:
+ return cap & ELEMENT_TYPE_CAP_MASK_RATE_LIMIT;
}
return false;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c
index a897cdc60fdb..b5332c54d4fb 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.c
@@ -11,31 +11,29 @@
/* This is the longest supported action sequence for FDB table:
* DECAP, POP_VLAN, MODIFY, CTR, ASO, PUSH_VLAN, MODIFY, ENCAP, Term.
*/
-static const u32 action_order_arr[MLX5HWS_TABLE_TYPE_MAX][MLX5HWS_ACTION_TYP_MAX] = {
- [MLX5HWS_TABLE_TYPE_FDB] = {
- BIT(MLX5HWS_ACTION_TYP_REMOVE_HEADER) |
- BIT(MLX5HWS_ACTION_TYP_REFORMAT_TNL_L2_TO_L2) |
- BIT(MLX5HWS_ACTION_TYP_REFORMAT_TNL_L3_TO_L2),
- BIT(MLX5HWS_ACTION_TYP_POP_VLAN),
- BIT(MLX5HWS_ACTION_TYP_POP_VLAN),
- BIT(MLX5HWS_ACTION_TYP_MODIFY_HDR),
- BIT(MLX5HWS_ACTION_TYP_PUSH_VLAN),
- BIT(MLX5HWS_ACTION_TYP_PUSH_VLAN),
- BIT(MLX5HWS_ACTION_TYP_INSERT_HEADER) |
- BIT(MLX5HWS_ACTION_TYP_REFORMAT_L2_TO_TNL_L2) |
- BIT(MLX5HWS_ACTION_TYP_REFORMAT_L2_TO_TNL_L3),
- BIT(MLX5HWS_ACTION_TYP_CTR),
- BIT(MLX5HWS_ACTION_TYP_TAG),
- BIT(MLX5HWS_ACTION_TYP_ASO_METER),
- BIT(MLX5HWS_ACTION_TYP_MODIFY_HDR),
- BIT(MLX5HWS_ACTION_TYP_TBL) |
- BIT(MLX5HWS_ACTION_TYP_VPORT) |
- BIT(MLX5HWS_ACTION_TYP_DROP) |
- BIT(MLX5HWS_ACTION_TYP_SAMPLER) |
- BIT(MLX5HWS_ACTION_TYP_RANGE) |
- BIT(MLX5HWS_ACTION_TYP_DEST_ARRAY),
- BIT(MLX5HWS_ACTION_TYP_LAST),
- },
+static const u32 action_order_arr[MLX5HWS_ACTION_TYP_MAX] = {
+ BIT(MLX5HWS_ACTION_TYP_REMOVE_HEADER) |
+ BIT(MLX5HWS_ACTION_TYP_REFORMAT_TNL_L2_TO_L2) |
+ BIT(MLX5HWS_ACTION_TYP_REFORMAT_TNL_L3_TO_L2),
+ BIT(MLX5HWS_ACTION_TYP_POP_VLAN),
+ BIT(MLX5HWS_ACTION_TYP_POP_VLAN),
+ BIT(MLX5HWS_ACTION_TYP_MODIFY_HDR),
+ BIT(MLX5HWS_ACTION_TYP_PUSH_VLAN),
+ BIT(MLX5HWS_ACTION_TYP_PUSH_VLAN),
+ BIT(MLX5HWS_ACTION_TYP_INSERT_HEADER) |
+ BIT(MLX5HWS_ACTION_TYP_REFORMAT_L2_TO_TNL_L2) |
+ BIT(MLX5HWS_ACTION_TYP_REFORMAT_L2_TO_TNL_L3),
+ BIT(MLX5HWS_ACTION_TYP_CTR),
+ BIT(MLX5HWS_ACTION_TYP_TAG),
+ BIT(MLX5HWS_ACTION_TYP_ASO_METER),
+ BIT(MLX5HWS_ACTION_TYP_MODIFY_HDR),
+ BIT(MLX5HWS_ACTION_TYP_TBL) |
+ BIT(MLX5HWS_ACTION_TYP_VPORT) |
+ BIT(MLX5HWS_ACTION_TYP_DROP) |
+ BIT(MLX5HWS_ACTION_TYP_SAMPLER) |
+ BIT(MLX5HWS_ACTION_TYP_RANGE) |
+ BIT(MLX5HWS_ACTION_TYP_DEST_ARRAY),
+ BIT(MLX5HWS_ACTION_TYP_LAST),
};
static const char * const mlx5hws_action_type_str[] = {
@@ -83,8 +81,8 @@ static int hws_action_get_shared_stc_nic(struct mlx5hws_context *ctx,
int ret;
mutex_lock(&ctx->ctrl_lock);
- if (ctx->common_res[tbl_type].shared_stc[stc_type]) {
- ctx->common_res[tbl_type].shared_stc[stc_type]->refcount++;
+ if (ctx->common_res.shared_stc[stc_type]) {
+ ctx->common_res.shared_stc[stc_type]->refcount++;
mutex_unlock(&ctx->ctrl_lock);
return 0;
}
@@ -124,8 +122,8 @@ static int hws_action_get_shared_stc_nic(struct mlx5hws_context *ctx,
goto free_shared_stc;
}
- ctx->common_res[tbl_type].shared_stc[stc_type] = shared_stc;
- ctx->common_res[tbl_type].shared_stc[stc_type]->refcount = 1;
+ ctx->common_res.shared_stc[stc_type] = shared_stc;
+ ctx->common_res.shared_stc[stc_type]->refcount = 1;
mutex_unlock(&ctx->ctrl_lock);
@@ -178,16 +176,16 @@ static void hws_action_put_shared_stc(struct mlx5hws_action *action,
}
mutex_lock(&ctx->ctrl_lock);
- if (--ctx->common_res[tbl_type].shared_stc[stc_type]->refcount) {
+ if (--ctx->common_res.shared_stc[stc_type]->refcount) {
mutex_unlock(&ctx->ctrl_lock);
return;
}
- shared_stc = ctx->common_res[tbl_type].shared_stc[stc_type];
+ shared_stc = ctx->common_res.shared_stc[stc_type];
mlx5hws_action_free_single_stc(ctx, tbl_type, &shared_stc->stc_chunk);
kfree(shared_stc);
- ctx->common_res[tbl_type].shared_stc[stc_type] = NULL;
+ ctx->common_res.shared_stc[stc_type] = NULL;
mutex_unlock(&ctx->ctrl_lock);
}
@@ -206,10 +204,10 @@ bool mlx5hws_action_check_combo(struct mlx5hws_context *ctx,
enum mlx5hws_action_type *user_actions,
enum mlx5hws_table_type table_type)
{
- const u32 *order_arr = action_order_arr[table_type];
+ const u32 *order_arr = action_order_arr;
+ bool valid_combo;
u8 order_idx = 0;
u8 user_idx = 0;
- bool valid_combo;
if (table_type >= MLX5HWS_TABLE_TYPE_MAX) {
mlx5hws_err(ctx, "Invalid table_type %d", table_type);
@@ -321,8 +319,8 @@ int mlx5hws_action_alloc_single_stc(struct mlx5hws_context *ctx,
__must_hold(&ctx->ctrl_lock)
{
struct mlx5hws_cmd_stc_modify_attr cleanup_stc_attr = {0};
- struct mlx5hws_pool *stc_pool = ctx->stc_pool[table_type];
struct mlx5hws_cmd_stc_modify_attr fixup_stc_attr = {0};
+ struct mlx5hws_pool *stc_pool = ctx->stc_pool;
bool use_fixup;
u32 obj_0_id;
int ret;
@@ -387,8 +385,8 @@ void mlx5hws_action_free_single_stc(struct mlx5hws_context *ctx,
struct mlx5hws_pool_chunk *stc)
__must_hold(&ctx->ctrl_lock)
{
- struct mlx5hws_pool *stc_pool = ctx->stc_pool[table_type];
struct mlx5hws_cmd_stc_modify_attr stc_attr = {0};
+ struct mlx5hws_pool *stc_pool = ctx->stc_pool;
u32 obj_id;
/* Modify the STC not to point to an object */
@@ -473,6 +471,7 @@ static void hws_action_fill_stc_attr(struct mlx5hws_action *action,
break;
case MLX5HWS_ACTION_TYP_TBL:
case MLX5HWS_ACTION_TYP_DEST_ARRAY:
+ case MLX5HWS_ACTION_TYP_SAMPLER:
attr->action_type = MLX5_IFC_STC_ACTION_TYPE_JUMP_TO_FT;
attr->action_offset = MLX5HWS_ACTION_OFFSET_HIT;
attr->dest_table_id = obj_id;
@@ -561,7 +560,7 @@ hws_action_create_stcs(struct mlx5hws_action *action, u32 obj_id)
if (action->flags & MLX5HWS_ACTION_FLAG_HWS_FDB) {
ret = mlx5hws_action_alloc_single_stc(ctx, &stc_attr,
MLX5HWS_TABLE_TYPE_FDB,
- &action->stc[MLX5HWS_TABLE_TYPE_FDB]);
+ &action->stc);
if (ret)
goto out_err;
}
@@ -585,7 +584,7 @@ hws_action_destroy_stcs(struct mlx5hws_action *action)
if (action->flags & MLX5HWS_ACTION_FLAG_HWS_FDB)
mlx5hws_action_free_single_stc(ctx, MLX5HWS_TABLE_TYPE_FDB,
- &action->stc[MLX5HWS_TABLE_TYPE_FDB]);
+ &action->stc);
mutex_unlock(&ctx->ctrl_lock);
}
@@ -1639,8 +1638,8 @@ hws_action_create_dest_match_range_table(struct mlx5hws_context *ctx,
rtc_attr.table_type = mlx5hws_table_get_res_fw_ft_type(MLX5HWS_TABLE_TYPE_FDB, false);
/* STC is a single resource (obj_id), use any STC for the ID */
- stc_pool = ctx->stc_pool[MLX5HWS_TABLE_TYPE_FDB];
- default_stc = ctx->common_res[MLX5HWS_TABLE_TYPE_FDB].default_stc;
+ stc_pool = ctx->stc_pool;
+ default_stc = ctx->common_res.default_stc;
obj_id = mlx5hws_pool_chunk_get_base_id(stc_pool, &default_stc->default_hit);
rtc_attr.stc_base = obj_id;
@@ -1731,7 +1730,7 @@ hws_action_create_dest_match_range_fill_table(struct mlx5hws_context *ctx,
ste_attr.used_id_rtc_0 = &used_rtc_0_id;
ste_attr.used_id_rtc_1 = &used_rtc_1_id;
- common_res = &ctx->common_res[MLX5HWS_TABLE_TYPE_FDB];
+ common_res = &ctx->common_res;
/* init an empty match STE which will always hit */
ste_attr.wqe_ctrl = &wqe_ctrl;
@@ -1750,7 +1749,7 @@ hws_action_create_dest_match_range_fill_table(struct mlx5hws_context *ctx,
wqe_ctrl.stc_ix[MLX5HWS_ACTION_STC_IDX_CTRL] |=
htonl(MLX5HWS_ACTION_STC_IDX_LAST_COMBO2 << 29);
wqe_ctrl.stc_ix[MLX5HWS_ACTION_STC_IDX_HIT] =
- htonl(hit_ft_action->stc[MLX5HWS_TABLE_TYPE_FDB].offset);
+ htonl(hit_ft_action->stc.offset);
wqe_data_arr = (__force __be32 *)&range_wqe_data;
@@ -1843,7 +1842,7 @@ mlx5hws_action_create_dest_match_range(struct mlx5hws_context *ctx,
stc_attr.ste_table.match_definer_id = ctx->caps->trivial_match_definer;
ret = mlx5hws_action_alloc_single_stc(ctx, &stc_attr, MLX5HWS_TABLE_TYPE_FDB,
- &action->stc[MLX5HWS_TABLE_TYPE_FDB]);
+ &action->stc);
if (ret)
goto error_unlock;
@@ -1875,7 +1874,50 @@ struct mlx5hws_action *
mlx5hws_action_create_flow_sampler(struct mlx5hws_context *ctx,
u32 sampler_id, u32 flags)
{
- mlx5hws_err(ctx, "Flow sampler action - unsupported\n");
+ struct mlx5hws_cmd_ft_create_attr ft_attr = {0};
+ struct mlx5hws_cmd_set_fte_attr fte_attr = {0};
+ struct mlx5hws_cmd_forward_tbl *fw_island;
+ struct mlx5hws_cmd_set_fte_dest dest;
+ struct mlx5hws_action *action;
+ int ret;
+
+ if (flags != (MLX5HWS_ACTION_FLAG_HWS_FDB | MLX5HWS_ACTION_FLAG_SHARED)) {
+ mlx5hws_err(ctx, "Unsupported flags for flow sampler\n");
+ return NULL;
+ }
+
+ ft_attr.type = FS_FT_FDB;
+ ft_attr.level = ctx->caps->fdb_ft.max_level - 1;
+
+ dest.destination_type = MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER;
+ dest.destination_id = sampler_id;
+
+ fte_attr.dests_num = 1;
+ fte_attr.dests = &dest;
+ fte_attr.action_flags = MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
+ fte_attr.ignore_flow_level = 1;
+
+ fw_island = mlx5hws_cmd_forward_tbl_create(ctx->mdev, &ft_attr, &fte_attr);
+ if (!fw_island)
+ return NULL;
+
+ action = hws_action_create_generic(ctx, flags,
+ MLX5HWS_ACTION_TYP_SAMPLER);
+ if (!action)
+ goto destroy_fw_island;
+
+ ret = hws_action_create_stcs(action, fw_island->ft_id);
+ if (ret)
+ goto free_action;
+
+ action->flow_sampler.fw_island = fw_island;
+
+ return action;
+
+free_action:
+ kfree(action);
+destroy_fw_island:
+ mlx5hws_cmd_forward_tbl_destroy(ctx->mdev, fw_island);
return NULL;
}
@@ -1914,6 +1956,11 @@ static void hws_action_destroy_hws(struct mlx5hws_action *action)
}
kfree(action->dest_array.dest_list);
break;
+ case MLX5HWS_ACTION_TYP_SAMPLER:
+ hws_action_destroy_stcs(action);
+ mlx5hws_cmd_forward_tbl_destroy(action->ctx->mdev,
+ action->flow_sampler.fw_island);
+ break;
case MLX5HWS_ACTION_TYP_REFORMAT_TNL_L3_TO_L2:
case MLX5HWS_ACTION_TYP_MODIFY_HDR:
shared_arg = false;
@@ -1970,8 +2017,8 @@ __must_hold(&ctx->ctrl_lock)
struct mlx5hws_action_default_stc *default_stc;
int ret;
- if (ctx->common_res[tbl_type].default_stc) {
- ctx->common_res[tbl_type].default_stc->refcount++;
+ if (ctx->common_res.default_stc) {
+ ctx->common_res.default_stc->refcount++;
return 0;
}
@@ -2023,8 +2070,8 @@ __must_hold(&ctx->ctrl_lock)
goto free_nop_dw7;
}
- ctx->common_res[tbl_type].default_stc = default_stc;
- ctx->common_res[tbl_type].default_stc->refcount++;
+ ctx->common_res.default_stc = default_stc;
+ ctx->common_res.default_stc->refcount++;
return 0;
@@ -2046,9 +2093,7 @@ __must_hold(&ctx->ctrl_lock)
{
struct mlx5hws_action_default_stc *default_stc;
- default_stc = ctx->common_res[tbl_type].default_stc;
-
- default_stc = ctx->common_res[tbl_type].default_stc;
+ default_stc = ctx->common_res.default_stc;
if (--default_stc->refcount)
return;
@@ -2058,7 +2103,7 @@ __must_hold(&ctx->ctrl_lock)
mlx5hws_action_free_single_stc(ctx, tbl_type, &default_stc->nop_dw5);
mlx5hws_action_free_single_stc(ctx, tbl_type, &default_stc->nop_ctr);
kfree(default_stc);
- ctx->common_res[tbl_type].default_stc = NULL;
+ ctx->common_res.default_stc = NULL;
}
static void hws_action_modify_write(struct mlx5hws_send_engine *queue,
@@ -2150,8 +2195,7 @@ hws_action_apply_stc(struct mlx5hws_actions_apply_data *apply,
{
struct mlx5hws_action *action = apply->rule_action[action_idx].action;
- apply->wqe_ctrl->stc_ix[stc_idx] =
- htonl(action->stc[apply->tbl_type].offset);
+ apply->wqe_ctrl->stc_ix[stc_idx] = htonl(action->stc.offset);
}
static void
@@ -2181,7 +2225,7 @@ hws_action_setter_modify_header(struct mlx5hws_actions_apply_data *apply,
rule_action = &apply->rule_action[setter->idx_double];
action = rule_action->action;
- stc_idx = htonl(action->stc[apply->tbl_type].offset);
+ stc_idx = htonl(action->stc.offset);
apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW6] = stc_idx;
apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW7] = 0;
@@ -2240,7 +2284,7 @@ hws_action_setter_insert_ptr(struct mlx5hws_actions_apply_data *apply,
apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW6] = 0;
apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW7] = htonl(arg_idx);
- stc_idx = htonl(action->stc[apply->tbl_type].offset);
+ stc_idx = htonl(action->stc.offset);
apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW6] = stc_idx;
apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW7] = 0;
@@ -2272,7 +2316,7 @@ hws_action_setter_tnl_l3_to_l2(struct mlx5hws_actions_apply_data *apply,
apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW6] = 0;
apply->wqe_data[MLX5HWS_ACTION_OFFSET_DW7] = htonl(arg_idx);
- stc_idx = htonl(action->stc[apply->tbl_type].offset);
+ stc_idx = htonl(action->stc.offset);
apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW6] = stc_idx;
apply->wqe_ctrl->stc_ix[MLX5HWS_ACTION_STC_IDX_DW7] = 0;
@@ -2434,6 +2478,7 @@ int mlx5hws_action_template_process(struct mlx5hws_action_template *at)
case MLX5HWS_ACTION_TYP_DROP:
case MLX5HWS_ACTION_TYP_TBL:
case MLX5HWS_ACTION_TYP_DEST_ARRAY:
+ case MLX5HWS_ACTION_TYP_SAMPLER:
case MLX5HWS_ACTION_TYP_VPORT:
case MLX5HWS_ACTION_TYP_MISS:
/* Hit action */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.h
index e8f562c31826..64b76075f7f8 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/action.h
@@ -70,12 +70,12 @@ struct mlx5hws_action_default_stc {
struct mlx5hws_pool_chunk nop_dw6;
struct mlx5hws_pool_chunk nop_dw7;
struct mlx5hws_pool_chunk default_hit;
- u32 refcount;
+ u32 refcount; /* protected by context ctrl lock */
};
struct mlx5hws_action_shared_stc {
struct mlx5hws_pool_chunk stc_chunk;
- u32 refcount;
+ u32 refcount; /* protected by context ctrl lock */
};
struct mlx5hws_actions_apply_data {
@@ -124,7 +124,7 @@ struct mlx5hws_action {
struct mlx5hws_context *ctx;
union {
struct {
- struct mlx5hws_pool_chunk stc[MLX5HWS_TABLE_TYPE_MAX];
+ struct mlx5hws_pool_chunk stc;
union {
struct {
u32 pat_id;
@@ -166,6 +166,9 @@ struct mlx5hws_action {
struct mlx5hws_cmd_set_fte_dest *dest_list;
} dest_array;
struct {
+ struct mlx5hws_cmd_forward_tbl *fw_island;
+ } flow_sampler;
+ struct {
u8 type;
u8 start_anchor;
u8 end_anchor;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.c
index baacf662c0ab..a8d886e92144 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.c
@@ -152,6 +152,8 @@ mlx5hws_bwc_matcher_create(struct mlx5hws_table *table,
if (!bwc_matcher)
return NULL;
+ atomic_set(&bwc_matcher->num_of_rules, 0);
+
/* Check if the required match params can be all matched
* in single STE, otherwise complex matcher is needed.
*/
@@ -199,10 +201,12 @@ int mlx5hws_bwc_matcher_destroy_simple(struct mlx5hws_bwc_matcher *bwc_matcher)
int mlx5hws_bwc_matcher_destroy(struct mlx5hws_bwc_matcher *bwc_matcher)
{
- if (bwc_matcher->num_of_rules)
+ u32 num_of_rules = atomic_read(&bwc_matcher->num_of_rules);
+
+ if (num_of_rules)
mlx5hws_err(bwc_matcher->matcher->tbl->ctx,
"BWC matcher destroy: matcher still has %d rules\n",
- bwc_matcher->num_of_rules);
+ num_of_rules);
mlx5hws_bwc_matcher_destroy_simple(bwc_matcher);
@@ -215,6 +219,8 @@ static int hws_bwc_queue_poll(struct mlx5hws_context *ctx,
u32 *pending_rules,
bool drain)
{
+ unsigned long timeout = jiffies +
+ msecs_to_jiffies(MLX5HWS_BWC_POLLING_TIMEOUT * MSEC_PER_SEC);
struct mlx5hws_flow_op_result comp[MLX5HWS_BWC_MATCHER_REHASH_BURST_TH];
u16 burst_th = hws_bwc_get_burst_th(ctx, queue_id);
bool got_comp = *pending_rules >= burst_th;
@@ -250,6 +256,11 @@ static int hws_bwc_queue_poll(struct mlx5hws_context *ctx,
}
got_comp = !!ret;
+
+ if (unlikely(!got_comp && time_after(jiffies, timeout))) {
+ mlx5hws_err(ctx, "BWC poll error: polling queue %d - TIMEOUT\n", queue_id);
+ return -ETIMEDOUT;
+ }
}
return err;
@@ -309,7 +320,7 @@ static void hws_bwc_rule_list_add(struct mlx5hws_bwc_rule *bwc_rule, u16 idx)
{
struct mlx5hws_bwc_matcher *bwc_matcher = bwc_rule->bwc_matcher;
- bwc_matcher->num_of_rules++;
+ atomic_inc(&bwc_matcher->num_of_rules);
bwc_rule->bwc_queue_idx = idx;
list_add(&bwc_rule->list_node, &bwc_matcher->rules[idx]);
}
@@ -318,7 +329,7 @@ static void hws_bwc_rule_list_remove(struct mlx5hws_bwc_rule *bwc_rule)
{
struct mlx5hws_bwc_matcher *bwc_matcher = bwc_rule->bwc_matcher;
- bwc_matcher->num_of_rules--;
+ atomic_dec(&bwc_matcher->num_of_rules);
list_del_init(&bwc_rule->list_node);
}
@@ -334,22 +345,21 @@ hws_bwc_rule_destroy_hws_sync(struct mlx5hws_bwc_rule *bwc_rule,
struct mlx5hws_rule_attr *rule_attr)
{
struct mlx5hws_context *ctx = bwc_rule->bwc_matcher->matcher->tbl->ctx;
- struct mlx5hws_flow_op_result completion;
+ u32 expected_completions = 1;
int ret;
ret = hws_bwc_rule_destroy_hws_async(bwc_rule, rule_attr);
if (unlikely(ret))
return ret;
- do {
- ret = mlx5hws_send_queue_poll(ctx, rule_attr->queue_id, &completion, 1);
- } while (ret != 1);
-
- if (unlikely(completion.status != MLX5HWS_FLOW_OP_SUCCESS ||
- (bwc_rule->rule->status != MLX5HWS_RULE_STATUS_DELETED &&
- bwc_rule->rule->status != MLX5HWS_RULE_STATUS_DELETING))) {
- mlx5hws_err(ctx, "Failed destroying BWC rule: completion %d, rule status %d\n",
- completion.status, bwc_rule->rule->status);
+ ret = hws_bwc_queue_poll(ctx, rule_attr->queue_id, &expected_completions, true);
+ if (unlikely(ret))
+ return ret;
+
+ if (unlikely(bwc_rule->rule->status != MLX5HWS_RULE_STATUS_DELETED &&
+ bwc_rule->rule->status != MLX5HWS_RULE_STATUS_DELETING)) {
+ mlx5hws_err(ctx, "Failed destroying BWC rule: rule status %d\n",
+ bwc_rule->rule->status);
return -EINVAL;
}
@@ -615,8 +625,12 @@ static int hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_match
ret = hws_bwc_queue_poll(ctx, rule_attr.queue_id,
&pending_rules[i], false);
- if (unlikely(ret))
+ if (unlikely(ret)) {
+ mlx5hws_err(ctx,
+ "Moving BWC rule failed during rehash (%d)\n",
+ ret);
goto free_bwc_rules;
+ }
}
}
} while (!all_done);
@@ -629,8 +643,11 @@ static int hws_bwc_matcher_move_all_simple(struct mlx5hws_bwc_matcher *bwc_match
mlx5hws_send_engine_flush_queue(&ctx->send_queue[queue_id]);
ret = hws_bwc_queue_poll(ctx, queue_id,
&pending_rules[i], true);
- if (unlikely(ret))
+ if (unlikely(ret)) {
+ mlx5hws_err(ctx,
+ "Moving BWC rule failed during rehash (%d)\n", ret);
goto free_bwc_rules;
+ }
}
}
@@ -704,7 +721,8 @@ hws_bwc_matcher_rehash_size(struct mlx5hws_bwc_matcher *bwc_matcher)
* Need to check again if we really need rehash.
* If the reason for rehash was size, but not any more - skip rehash.
*/
- if (!hws_bwc_matcher_rehash_size_needed(bwc_matcher, bwc_matcher->num_of_rules))
+ if (!hws_bwc_matcher_rehash_size_needed(bwc_matcher,
+ atomic_read(&bwc_matcher->num_of_rules)))
return 0;
/* Now we're done all the checking - do the rehash:
@@ -797,7 +815,7 @@ int mlx5hws_bwc_rule_create_simple(struct mlx5hws_bwc_rule *bwc_rule,
}
/* check if number of rules require rehash */
- num_of_rules = bwc_matcher->num_of_rules;
+ num_of_rules = atomic_read(&bwc_matcher->num_of_rules);
if (unlikely(hws_bwc_matcher_rehash_size_needed(bwc_matcher, num_of_rules))) {
mutex_unlock(queue_lock);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h
index 0b745968e21e..f9f569131dde 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc.h
@@ -8,10 +8,18 @@
#define MLX5HWS_BWC_MATCHER_SIZE_LOG_STEP 1
#define MLX5HWS_BWC_MATCHER_REHASH_PERCENT_TH 70
#define MLX5HWS_BWC_MATCHER_REHASH_BURST_TH 32
-#define MLX5HWS_BWC_MATCHER_ATTACH_AT_NUM 255
+
+/* Max number of AT attach operations for the same matcher.
+ * When the limit is reached, next attempt to attach new AT
+ * will result in creation of a new matcher and moving all
+ * the rules to this matcher.
+ */
+#define MLX5HWS_BWC_MATCHER_ATTACH_AT_NUM 8
#define MLX5HWS_BWC_MAX_ACTS 16
+#define MLX5HWS_BWC_POLLING_TIMEOUT 60
+
struct mlx5hws_bwc_matcher {
struct mlx5hws_matcher *matcher;
struct mlx5hws_match_template *mt;
@@ -19,7 +27,7 @@ struct mlx5hws_bwc_matcher {
u8 num_of_at;
u16 priority;
u8 size_log;
- u32 num_of_rules; /* atomically accessed */
+ atomic_t num_of_rules;
struct list_head *rules;
};
@@ -60,9 +68,11 @@ void mlx5hws_bwc_rule_fill_attr(struct mlx5hws_bwc_matcher *bwc_matcher,
static inline u16 mlx5hws_bwc_queues(struct mlx5hws_context *ctx)
{
/* Besides the control queue, half of the queues are
- * reguler HWS queues, and the other half are BWC queues.
+ * regular HWS queues, and the other half are BWC queues.
*/
- return (ctx->queues - 1) / 2;
+ if (mlx5hws_context_bwc_supported(ctx))
+ return (ctx->queues - 1) / 2;
+ return 0;
}
static inline u16 mlx5hws_bwc_get_queue_id(struct mlx5hws_context *ctx, u16 idx)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c
index c00010ca86bd..9fb059a6511f 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/bwc_complex.c
@@ -39,6 +39,8 @@ bool mlx5hws_bwc_match_params_is_complex(struct mlx5hws_context *ctx,
} else {
mlx5hws_err(ctx, "Failed to calculate matcher definer layout\n");
}
+ } else {
+ kfree(mt->fc);
}
mlx5hws_match_template_destroy(mt);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c
index c00c138c3366..487e75476b0a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.c
@@ -257,6 +257,12 @@ int mlx5hws_cmd_set_fte(struct mlx5_core_dev *mdev,
dest->ext_reformat_id);
}
break;
+ case MLX5_FLOW_DESTINATION_TYPE_FLOW_SAMPLER:
+ MLX5_SET(dest_format, in_dests,
+ destination_type, ifc_dest_type);
+ MLX5_SET(dest_format, in_dests, destination_id,
+ dest->destination_id);
+ break;
default:
ret = -EOPNOTSUPP;
goto out;
@@ -359,7 +365,7 @@ void mlx5hws_cmd_set_attr_connect_miss_tbl(struct mlx5hws_context *ctx,
ft_attr->type = fw_ft_type;
ft_attr->table_miss_action = MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL;
- default_miss_tbl = ctx->common_res[type].default_miss->ft_id;
+ default_miss_tbl = ctx->common_res.default_miss->ft_id;
if (!default_miss_tbl) {
pr_warn("HWS: no flow table ID for default miss\n");
return;
@@ -622,12 +628,12 @@ int mlx5hws_cmd_arg_create(struct mlx5_core_dev *mdev,
u32 pd,
u32 *arg_id)
{
+ u32 in[MLX5_ST_SZ_DW(create_modify_header_arg_in)] = {0};
u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
- u32 in[MLX5_ST_SZ_DW(create_arg_in)] = {0};
void *attr;
int ret;
- attr = MLX5_ADDR_OF(create_arg_in, in, hdr);
+ attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, hdr);
MLX5_SET(general_obj_in_cmd_hdr,
attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
MLX5_SET(general_obj_in_cmd_hdr,
@@ -635,8 +641,8 @@ int mlx5hws_cmd_arg_create(struct mlx5_core_dev *mdev,
MLX5_SET(general_obj_in_cmd_hdr,
attr, op_param.create.log_obj_range, log_obj_range);
- attr = MLX5_ADDR_OF(create_arg_in, in, arg);
- MLX5_SET(arg, attr, access_pd, pd);
+ attr = MLX5_ADDR_OF(create_modify_header_arg_in, in, arg);
+ MLX5_SET(modify_header_arg, attr, access_pd, pd);
ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
if (ret) {
@@ -812,7 +818,7 @@ int mlx5hws_cmd_packet_reformat_create(struct mlx5_core_dev *mdev,
struct mlx5hws_cmd_packet_reformat_create_attr *attr,
u32 *reformat_id)
{
- u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_out)] = {0};
+ u32 out[MLX5_ST_SZ_DW(alloc_packet_reformat_context_out)] = {0};
size_t insz, cmd_data_sz, cmd_total_sz;
void *prctx;
void *pdata;
@@ -845,7 +851,7 @@ int mlx5hws_cmd_packet_reformat_create(struct mlx5_core_dev *mdev,
goto out;
}
- *reformat_id = MLX5_GET(alloc_packet_reformat_out, out, packet_reformat_id);
+ *reformat_id = MLX5_GET(alloc_packet_reformat_context_out, out, packet_reformat_id);
out:
kfree(in);
return ret;
@@ -854,13 +860,13 @@ out:
int mlx5hws_cmd_packet_reformat_destroy(struct mlx5_core_dev *mdev,
u32 reformat_id)
{
- u32 out[MLX5_ST_SZ_DW(dealloc_packet_reformat_out)] = {0};
- u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_in)] = {0};
+ u32 out[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_out)] = {0};
+ u32 in[MLX5_ST_SZ_DW(dealloc_packet_reformat_context_in)] = {0};
int ret;
- MLX5_SET(dealloc_packet_reformat_in, in, opcode,
+ MLX5_SET(dealloc_packet_reformat_context_in, in, opcode,
MLX5_CMD_OP_DEALLOC_PACKET_REFORMAT_CONTEXT);
- MLX5_SET(dealloc_packet_reformat_in, in,
+ MLX5_SET(dealloc_packet_reformat_context_in, in,
packet_reformat_id, reformat_id);
ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
@@ -889,73 +895,6 @@ int mlx5hws_cmd_sq_modify_rdy(struct mlx5_core_dev *mdev, u32 sqn)
return ret;
}
-int mlx5hws_cmd_allow_other_vhca_access(struct mlx5_core_dev *mdev,
- struct mlx5hws_cmd_allow_other_vhca_access_attr *attr)
-{
- u32 out[MLX5_ST_SZ_DW(allow_other_vhca_access_out)] = {0};
- u32 in[MLX5_ST_SZ_DW(allow_other_vhca_access_in)] = {0};
- void *key;
- int ret;
-
- MLX5_SET(allow_other_vhca_access_in,
- in, opcode, MLX5_CMD_OP_ALLOW_OTHER_VHCA_ACCESS);
- MLX5_SET(allow_other_vhca_access_in,
- in, object_type_to_be_accessed, attr->obj_type);
- MLX5_SET(allow_other_vhca_access_in,
- in, object_id_to_be_accessed, attr->obj_id);
-
- key = MLX5_ADDR_OF(allow_other_vhca_access_in, in, access_key);
- memcpy(key, attr->access_key, sizeof(attr->access_key));
-
- ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
- if (ret)
- mlx5_core_err(mdev, "Failed to execute ALLOW_OTHER_VHCA_ACCESS command\n");
-
- return ret;
-}
-
-int mlx5hws_cmd_alias_obj_create(struct mlx5_core_dev *mdev,
- struct mlx5hws_cmd_alias_obj_create_attr *alias_attr,
- u32 *obj_id)
-{
- u32 out[MLX5_ST_SZ_DW(general_obj_out_cmd_hdr)] = {0};
- u32 in[MLX5_ST_SZ_DW(create_alias_obj_in)] = {0};
- void *attr;
- void *key;
- int ret;
-
- attr = MLX5_ADDR_OF(create_alias_obj_in, in, hdr);
- MLX5_SET(general_obj_in_cmd_hdr,
- attr, opcode, MLX5_CMD_OP_CREATE_GENERAL_OBJECT);
- MLX5_SET(general_obj_in_cmd_hdr,
- attr, obj_type, alias_attr->obj_type);
- MLX5_SET(general_obj_in_cmd_hdr, attr, op_param.create.alias_object, 1);
-
- attr = MLX5_ADDR_OF(create_alias_obj_in, in, alias_ctx);
- MLX5_SET(alias_context, attr, vhca_id_to_be_accessed, alias_attr->vhca_id);
- MLX5_SET(alias_context, attr, object_id_to_be_accessed, alias_attr->obj_id);
-
- key = MLX5_ADDR_OF(alias_context, attr, access_key);
- memcpy(key, alias_attr->access_key, sizeof(alias_attr->access_key));
-
- ret = mlx5_cmd_exec(mdev, in, sizeof(in), out, sizeof(out));
- if (ret) {
- mlx5_core_err(mdev, "Failed to create ALIAS OBJ\n");
- goto out;
- }
-
- *obj_id = MLX5_GET(general_obj_out_cmd_hdr, out, obj_id);
-out:
- return ret;
-}
-
-int mlx5hws_cmd_alias_obj_destroy(struct mlx5_core_dev *mdev,
- u16 obj_type,
- u32 obj_id)
-{
- return hws_cmd_general_obj_destroy(mdev, obj_type, obj_id);
-}
-
int mlx5hws_cmd_generate_wqe(struct mlx5_core_dev *mdev,
struct mlx5hws_cmd_generate_wqe_attr *attr,
struct mlx5_cqe64 *ret_cqe)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h
index 434f62b0904e..610c63d81ad9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/cmd.h
@@ -63,7 +63,7 @@ struct mlx5hws_cmd_forward_tbl {
u8 type;
u32 ft_id;
u32 fg_id;
- u32 refcount;
+ u32 refcount; /* protected by context ctrl lock */
};
struct mlx5hws_cmd_rtc_create_attr {
@@ -334,14 +334,6 @@ mlx5hws_cmd_forward_tbl_create(struct mlx5_core_dev *mdev,
void mlx5hws_cmd_forward_tbl_destroy(struct mlx5_core_dev *mdev,
struct mlx5hws_cmd_forward_tbl *tbl);
-int mlx5hws_cmd_alias_obj_create(struct mlx5_core_dev *mdev,
- struct mlx5hws_cmd_alias_obj_create_attr *alias_attr,
- u32 *obj_id);
-
-int mlx5hws_cmd_alias_obj_destroy(struct mlx5_core_dev *mdev,
- u16 obj_type,
- u32 obj_id);
-
int mlx5hws_cmd_sq_modify_rdy(struct mlx5_core_dev *mdev, u32 sqn);
int mlx5hws_cmd_query_caps(struct mlx5_core_dev *mdev,
@@ -352,9 +344,6 @@ void mlx5hws_cmd_set_attr_connect_miss_tbl(struct mlx5hws_context *ctx,
enum mlx5hws_table_type type,
struct mlx5hws_cmd_ft_modify_attr *ft_attr);
-int mlx5hws_cmd_allow_other_vhca_access(struct mlx5_core_dev *mdev,
- struct mlx5hws_cmd_allow_other_vhca_access_attr *attr);
-
int mlx5hws_cmd_query_gvmi(struct mlx5_core_dev *mdev, bool other_function,
u16 vport_number, u16 *gvmi);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.c
index fd48b05e91e0..9cda2774fd64 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.c
@@ -23,7 +23,6 @@ static int hws_context_pools_init(struct mlx5hws_context *ctx)
struct mlx5hws_pool_attr pool_attr = {0};
u8 max_log_sz;
int ret;
- int i;
ret = mlx5hws_pat_init_pattern_cache(&ctx->pattern_cache);
if (ret)
@@ -39,23 +38,17 @@ static int hws_context_pools_init(struct mlx5hws_context *ctx)
max_log_sz = min(MLX5HWS_POOL_STC_LOG_SZ, ctx->caps->stc_alloc_log_max);
pool_attr.alloc_log_sz = max(max_log_sz, ctx->caps->stc_alloc_log_gran);
- for (i = 0; i < MLX5HWS_TABLE_TYPE_MAX; i++) {
- pool_attr.table_type = i;
- ctx->stc_pool[i] = mlx5hws_pool_create(ctx, &pool_attr);
- if (!ctx->stc_pool[i]) {
- mlx5hws_err(ctx, "Failed to allocate STC pool [%d]", i);
- ret = -ENOMEM;
- goto free_stc_pools;
- }
+ pool_attr.table_type = MLX5HWS_TABLE_TYPE_FDB;
+ ctx->stc_pool = mlx5hws_pool_create(ctx, &pool_attr);
+ if (!ctx->stc_pool) {
+ mlx5hws_err(ctx, "Failed to allocate STC pool\n");
+ ret = -ENOMEM;
+ goto uninit_cache;
}
return 0;
-free_stc_pools:
- for (i = 0; i < MLX5HWS_TABLE_TYPE_MAX; i++)
- if (ctx->stc_pool[i])
- mlx5hws_pool_destroy(ctx->stc_pool[i]);
-
+uninit_cache:
mlx5hws_definer_uninit_cache(ctx->definer_cache);
uninit_pat_cache:
mlx5hws_pat_uninit_pattern_cache(ctx->pattern_cache);
@@ -64,12 +57,8 @@ uninit_pat_cache:
static void hws_context_pools_uninit(struct mlx5hws_context *ctx)
{
- int i;
-
- for (i = 0; i < MLX5HWS_TABLE_TYPE_MAX; i++) {
- if (ctx->stc_pool[i])
- mlx5hws_pool_destroy(ctx->stc_pool[i]);
- }
+ if (ctx->stc_pool)
+ mlx5hws_pool_destroy(ctx->stc_pool);
mlx5hws_definer_uninit_cache(ctx->definer_cache);
mlx5hws_pat_uninit_pattern_cache(ctx->pattern_cache);
@@ -161,8 +150,10 @@ static int hws_context_init_hws(struct mlx5hws_context *ctx,
if (ret)
goto uninit_pd;
- if (attr->bwc)
- ctx->flags |= MLX5HWS_CONTEXT_FLAG_BWC_SUPPORT;
+ /* Context has support for backward compatible API,
+ * and does not have support for native HWS API.
+ */
+ ctx->flags |= MLX5HWS_CONTEXT_FLAG_BWC_SUPPORT;
ret = mlx5hws_send_queues_open(ctx, attr->queues, attr->queue_size);
if (ret)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.h
index 47f5cc8de73f..38c3647444ad 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/context.h
@@ -8,6 +8,7 @@ enum mlx5hws_context_flags {
MLX5HWS_CONTEXT_FLAG_HWS_SUPPORT = 1 << 0,
MLX5HWS_CONTEXT_FLAG_PRIVATE_PD = 1 << 1,
MLX5HWS_CONTEXT_FLAG_BWC_SUPPORT = 1 << 2,
+ MLX5HWS_CONTEXT_FLAG_NATIVE_SUPPORT = 1 << 3,
};
enum mlx5hws_context_shared_stc_type {
@@ -37,8 +38,8 @@ struct mlx5hws_context {
struct mlx5_core_dev *mdev;
struct mlx5hws_cmd_query_caps *caps;
u32 pd_num;
- struct mlx5hws_pool *stc_pool[MLX5HWS_TABLE_TYPE_MAX];
- struct mlx5hws_context_common_res common_res[MLX5HWS_TABLE_TYPE_MAX];
+ struct mlx5hws_pool *stc_pool;
+ struct mlx5hws_context_common_res common_res;
struct mlx5hws_pattern_cache *pattern_cache;
struct mlx5hws_definer_cache *definer_cache;
struct mutex ctrl_lock; /* control lock to protect the whole context */
@@ -58,6 +59,11 @@ static inline bool mlx5hws_context_bwc_supported(struct mlx5hws_context *ctx)
return ctx->flags & MLX5HWS_CONTEXT_FLAG_BWC_SUPPORT;
}
+static inline bool mlx5hws_context_native_supported(struct mlx5hws_context *ctx)
+{
+ return ctx->flags & MLX5HWS_CONTEXT_FLAG_NATIVE_SUPPORT;
+}
+
bool mlx5hws_context_cap_dynamic_reparse(struct mlx5hws_context *ctx);
u8 mlx5hws_context_get_reparse_mode(struct mlx5hws_context *ctx);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.c
index 5b200b4bc1a8..60ada3143d60 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/debug.c
@@ -368,9 +368,10 @@ static int hws_debug_dump_context_info(struct seq_file *f, struct mlx5hws_contex
static int hws_debug_dump_context_stc_resource(struct seq_file *f,
struct mlx5hws_context *ctx,
- u32 tbl_type,
struct mlx5hws_pool_resource *resource)
{
+ u32 tbl_type = MLX5HWS_TABLE_TYPE_BASE + MLX5HWS_TABLE_TYPE_FDB;
+
seq_printf(f, "%d,0x%llx,%u,%u\n",
MLX5HWS_DEBUG_RES_TYPE_CONTEXT_STC,
HWS_PTR_TO_ID(ctx),
@@ -382,31 +383,22 @@ static int hws_debug_dump_context_stc_resource(struct seq_file *f,
static int hws_debug_dump_context_stc(struct seq_file *f, struct mlx5hws_context *ctx)
{
- struct mlx5hws_pool *stc_pool;
- u32 table_type;
+ struct mlx5hws_pool *stc_pool = ctx->stc_pool;
int ret;
- int i;
-
- for (i = 0; i < MLX5HWS_TABLE_TYPE_MAX; i++) {
- stc_pool = ctx->stc_pool[i];
- table_type = MLX5HWS_TABLE_TYPE_BASE + i;
- if (!stc_pool)
- continue;
+ if (!stc_pool)
+ return 0;
- if (stc_pool->resource[0]) {
- ret = hws_debug_dump_context_stc_resource(f, ctx, table_type,
- stc_pool->resource[0]);
- if (ret)
- return ret;
- }
+ if (stc_pool->resource[0]) {
+ ret = hws_debug_dump_context_stc_resource(f, ctx, stc_pool->resource[0]);
+ if (ret)
+ return ret;
+ }
- if (i == MLX5HWS_TABLE_TYPE_FDB && stc_pool->mirror_resource[0]) {
- ret = hws_debug_dump_context_stc_resource(f, ctx, table_type,
- stc_pool->mirror_resource[0]);
- if (ret)
- return ret;
- }
+ if (stc_pool->mirror_resource[0]) {
+ ret = hws_debug_dump_context_stc_resource(f, ctx, stc_pool->mirror_resource[0]);
+ if (ret)
+ return ret;
}
return 0;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c
index 8fe96eb76baf..10ece7df1cfa 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.c
@@ -70,7 +70,7 @@
u32 second_dw_mask = (mask) & ((1 << _bit_off) - 1); \
_HWS_SET32(p, (v) >> _bit_off, byte_off, 0, (mask) >> _bit_off); \
_HWS_SET32(p, (v) & second_dw_mask, (byte_off) + DW_SIZE, \
- (bit_off) % BITS_IN_DW, second_dw_mask); \
+ (bit_off + BITS_IN_DW) % BITS_IN_DW, second_dw_mask); \
} else { \
_HWS_SET32(p, v, byte_off, (bit_off), (mask)); \
} \
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.h
index 9432d5084def..5c1a2086efba 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/definer.h
@@ -785,7 +785,7 @@ struct mlx5hws_definer_cache {
struct mlx5hws_definer_cache_item {
struct mlx5hws_definer definer;
- u32 refcount;
+ u32 refcount; /* protected by context ctrl lock */
struct list_head list_node;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c
index 1bb3a6f8c3cd..4419c72ad314 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/matcher.c
@@ -165,14 +165,14 @@ static int hws_matcher_disconnect(struct mlx5hws_matcher *matcher)
next->match_ste.rtc_0_id,
next->match_ste.rtc_1_id);
if (ret) {
- mlx5hws_err(tbl->ctx, "Failed to disconnect matcher\n");
- goto matcher_reconnect;
+ mlx5hws_err(tbl->ctx, "Fatal error, failed to disconnect matcher\n");
+ return ret;
}
} else {
ret = mlx5hws_table_connect_to_miss_table(tbl, tbl->default_miss.miss_tbl);
if (ret) {
- mlx5hws_err(tbl->ctx, "Failed to disconnect last matcher\n");
- goto matcher_reconnect;
+ mlx5hws_err(tbl->ctx, "Fatal error, failed to disconnect last matcher\n");
+ return ret;
}
}
@@ -180,27 +180,19 @@ static int hws_matcher_disconnect(struct mlx5hws_matcher *matcher)
if (prev_ft_id == tbl->ft_id) {
ret = mlx5hws_table_update_connected_miss_tables(tbl);
if (ret) {
- mlx5hws_err(tbl->ctx, "Fatal error, failed to update connected miss table\n");
- goto matcher_reconnect;
+ mlx5hws_err(tbl->ctx,
+ "Fatal error, failed to update connected miss table\n");
+ return ret;
}
}
ret = mlx5hws_table_ft_set_default_next_ft(tbl, prev_ft_id);
if (ret) {
mlx5hws_err(tbl->ctx, "Fatal error, failed to restore matcher ft default miss\n");
- goto matcher_reconnect;
+ return ret;
}
return 0;
-
-matcher_reconnect:
- if (list_empty(&tbl->matchers_list) || !prev)
- list_add(&matcher->list_node, &tbl->matchers_list);
- else
- /* insert after prev matcher */
- list_add(&matcher->list_node, &prev->list_node);
-
- return ret;
}
static void hws_matcher_set_rtc_attr_sz(struct mlx5hws_matcher *matcher,
@@ -318,8 +310,8 @@ static int hws_matcher_create_rtc(struct mlx5hws_matcher *matcher,
hws_matcher_set_rtc_attr_sz(matcher, &rtc_attr, rtc_type, false);
/* STC is a single resource (obj_id), use any STC for the ID */
- stc_pool = ctx->stc_pool[tbl->type];
- default_stc = ctx->common_res[tbl->type].default_stc;
+ stc_pool = ctx->stc_pool;
+ default_stc = ctx->common_res.default_stc;
obj_id = mlx5hws_pool_chunk_get_base_id(stc_pool, &default_stc->default_hit);
rtc_attr.stc_base = obj_id;
@@ -1007,9 +999,9 @@ hws_matcher_set_templates(struct mlx5hws_matcher *matcher,
if (!matcher->mt)
return -ENOMEM;
- matcher->at = kcalloc(num_of_at + matcher->attr.max_num_of_at_attach,
- sizeof(*matcher->at),
- GFP_KERNEL);
+ matcher->at = kvcalloc(num_of_at + matcher->attr.max_num_of_at_attach,
+ sizeof(*matcher->at),
+ GFP_KERNEL);
if (!matcher->at) {
mlx5hws_err(ctx, "Failed to allocate action template array\n");
ret = -ENOMEM;
@@ -1035,7 +1027,7 @@ free_mt:
static void
hws_matcher_unset_templates(struct mlx5hws_matcher *matcher)
{
- kfree(matcher->at);
+ kvfree(matcher->at);
kfree(matcher->mt);
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h
index f39d636ff39a..5121951f2778 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/mlx5hws.h
@@ -70,7 +70,6 @@ enum mlx5hws_send_queue_actions {
struct mlx5hws_context_attr {
u16 queues;
u16 queue_size;
- bool bwc; /* add support for backward compatible API*/
};
struct mlx5hws_table_attr {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c
index 06db5e4726ae..d9dc4f2d0dc6 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.c
@@ -344,7 +344,7 @@ void mlx5hws_arg_write(struct mlx5hws_send_engine *queue,
mlx5hws_send_engine_post_req_wqe(&ctrl, (void *)&wqe_ctrl, &wqe_len);
memset(wqe_ctrl, 0, wqe_len);
mlx5hws_send_engine_post_req_wqe(&ctrl, (void *)&wqe_arg, &wqe_len);
- memcpy(wqe_arg, arg_data, wqe_len);
+ memcpy(wqe_arg, arg_data, MLX5HWS_ARG_DATA_SIZE);
send_attr.id = arg_idx++;
mlx5hws_send_engine_post_end(&ctrl, &send_attr);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.h
index 27ca93385b08..8ddb51980044 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pat_arg.h
@@ -31,7 +31,7 @@ struct mlx5hws_pattern_cache_item {
u8 *data;
u16 num_of_actions;
} mh_data;
- u32 refcount;
+ u32 refcount; /* protected by pattern_cache lock */
struct list_head ptrn_list_node;
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c
index fed2d913f3b8..50a81d360bb2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/pool.c
@@ -183,7 +183,7 @@ static int hws_pool_buddy_get_mem_chunk(struct mlx5hws_pool *pool,
*seg = -1;
/* Find the next free place from the buddy array */
- while (*seg == -1) {
+ while (*seg < 0) {
for (i = 0; i < MLX5HWS_POOL_RESOURCE_ARR_SZ; i++) {
buddy = hws_pool_buddy_get_next_buddy(pool, i,
order,
@@ -194,7 +194,7 @@ static int hws_pool_buddy_get_mem_chunk(struct mlx5hws_pool *pool,
}
*seg = mlx5hws_buddy_alloc_mem(buddy, order);
- if (*seg != -1)
+ if (*seg >= 0)
goto found;
if (pool->flags & MLX5HWS_POOL_FLAGS_ONE_RESOURCE) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/prm.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/prm.h
index de92cecbeb92..271490a51b96 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/prm.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/prm.h
@@ -390,11 +390,6 @@ struct mlx5_ifc_definer_bits {
u8 match_mask[0x160];
};
-struct mlx5_ifc_arg_bits {
- u8 rsvd0[0x88];
- u8 access_pd[0x18];
-};
-
struct mlx5_ifc_header_modify_pattern_in_bits {
u8 modify_field_select[0x40];
@@ -428,11 +423,6 @@ struct mlx5_ifc_create_definer_in_bits {
struct mlx5_ifc_definer_bits definer;
};
-struct mlx5_ifc_create_arg_in_bits {
- struct mlx5_ifc_general_obj_in_cmd_hdr_bits hdr;
- struct mlx5_ifc_arg_bits arg;
-};
-
struct mlx5_ifc_create_header_modify_pattern_in_bits {
struct mlx5_ifc_general_obj_in_cmd_hdr_bits hdr;
struct mlx5_ifc_header_modify_pattern_in_bits pattern;
@@ -479,36 +469,4 @@ enum {
MLX5_IFC_MODIFY_FLOW_TABLE_MISS_ACTION_GOTO_TBL = 1,
};
-struct mlx5_ifc_alloc_packet_reformat_out_bits {
- u8 status[0x8];
- u8 reserved_at_8[0x18];
-
- u8 syndrome[0x20];
-
- u8 packet_reformat_id[0x20];
-
- u8 reserved_at_60[0x20];
-};
-
-struct mlx5_ifc_dealloc_packet_reformat_in_bits {
- u8 opcode[0x10];
- u8 reserved_at_10[0x10];
-
- u8 reserved_at_20[0x10];
- u8 op_mod[0x10];
-
- u8 packet_reformat_id[0x20];
-
- u8 reserved_at_60[0x20];
-};
-
-struct mlx5_ifc_dealloc_packet_reformat_out_bits {
- u8 status[0x8];
- u8 reserved_at_8[0x18];
-
- u8 syndrome[0x20];
-
- u8 reserved_at_40[0x40];
-};
-
#endif /* MLX5_PRM_H_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.c
index e20c67a04203..14f6307a1772 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/rule.c
@@ -315,7 +315,7 @@ static void hws_rule_create_init(struct mlx5hws_rule *rule,
/* Init default action apply */
apply->tbl_type = tbl->type;
- apply->common_res = &ctx->common_res[tbl->type];
+ apply->common_res = &ctx->common_res;
apply->jump_to_action_stc = matcher->action_ste[0].stc.offset;
apply->require_dep = 0;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c
index 424797b6d802..c680b7f984e1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.c
@@ -633,6 +633,7 @@ static int hws_send_ring_create_sq(struct mlx5_core_dev *mdev, u32 pdn,
MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RST);
MLX5_SET(sqc, sqc, flush_in_error_en, 1);
+ MLX5_SET(sqc, sqc, non_wire, 1);
ts_format = mlx5_is_real_time_sq(mdev) ? MLX5_TIMESTAMP_FORMAT_REAL_TIME :
MLX5_TIMESTAMP_FORMAT_FREE_RUNNING;
@@ -896,15 +897,18 @@ close_cq:
return err;
}
-void mlx5hws_send_queue_close(struct mlx5hws_send_engine *queue)
+static void mlx5hws_send_queue_close(struct mlx5hws_send_engine *queue)
{
+ if (!queue->num_entries)
+ return; /* this queue wasn't initialized */
+
hws_send_ring_close(queue);
kfree(queue->completed.entries);
}
-int mlx5hws_send_queue_open(struct mlx5hws_context *ctx,
- struct mlx5hws_send_engine *queue,
- u16 queue_size)
+static int mlx5hws_send_queue_open(struct mlx5hws_context *ctx,
+ struct mlx5hws_send_engine *queue,
+ u16 queue_size)
{
int err;
@@ -990,6 +994,7 @@ static int hws_bwc_send_queues_init(struct mlx5hws_context *ctx)
for (i = 0; i < bwc_queues; i++) {
mutex_init(&ctx->bwc_send_queue_locks[i]);
lockdep_register_key(ctx->bwc_lock_class_keys + i);
+ lockdep_set_class(ctx->bwc_send_queue_locks + i, ctx->bwc_lock_class_keys + i);
}
return 0;
@@ -1004,7 +1009,7 @@ int mlx5hws_send_queues_open(struct mlx5hws_context *ctx,
u16 queue_size)
{
int err = 0;
- u32 i;
+ int i = 0;
/* Open one extra queue for control path */
ctx->queues = queues + 1;
@@ -1020,7 +1025,13 @@ int mlx5hws_send_queues_open(struct mlx5hws_context *ctx,
goto free_bwc_locks;
}
- for (i = 0; i < ctx->queues; i++) {
+ /* If native API isn't supported, skip the unused native queues:
+ * initialize BWC queues and control queue only.
+ */
+ if (!mlx5hws_context_native_supported(ctx))
+ i = mlx5hws_bwc_get_queue_id(ctx, 0);
+
+ for (; i < ctx->queues; i++) {
err = mlx5hws_send_queue_open(ctx, &ctx->send_queue[i], queue_size);
if (err)
goto close_send_queues;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.h
index b50825d6dc53..f833092235c1 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/send.h
@@ -189,12 +189,6 @@ void mlx5hws_send_abort_new_dep_wqe(struct mlx5hws_send_engine *queue);
void mlx5hws_send_all_dep_wqe(struct mlx5hws_send_engine *queue);
-void mlx5hws_send_queue_close(struct mlx5hws_send_engine *queue);
-
-int mlx5hws_send_queue_open(struct mlx5hws_context *ctx,
- struct mlx5hws_send_engine *queue,
- u16 queue_size);
-
void mlx5hws_send_queues_close(struct mlx5hws_context *ctx);
int mlx5hws_send_queues_open(struct mlx5hws_context *ctx,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c
index 9576e02d00c3..ab1297531232 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/hws/table.c
@@ -37,6 +37,7 @@ static void hws_table_set_cap_attr(struct mlx5hws_table *tbl,
}
static int hws_table_up_default_fdb_miss_tbl(struct mlx5hws_table *tbl)
+__must_hold(&tbl->ctx->ctrl_lock)
{
struct mlx5hws_cmd_ft_create_attr ft_attr = {0};
struct mlx5hws_cmd_set_fte_attr fte_attr = {0};
@@ -48,8 +49,8 @@ static int hws_table_up_default_fdb_miss_tbl(struct mlx5hws_table *tbl)
if (tbl->type != MLX5HWS_TABLE_TYPE_FDB)
return 0;
- if (ctx->common_res[tbl_type].default_miss) {
- ctx->common_res[tbl_type].default_miss->refcount++;
+ if (ctx->common_res.default_miss) {
+ ctx->common_res.default_miss->refcount++;
return 0;
}
@@ -70,29 +71,28 @@ static int hws_table_up_default_fdb_miss_tbl(struct mlx5hws_table *tbl)
return -EINVAL;
}
- /* ctx->ctrl_lock must be held here */
- ctx->common_res[tbl_type].default_miss = default_miss;
- ctx->common_res[tbl_type].default_miss->refcount++;
+ ctx->common_res.default_miss = default_miss;
+ ctx->common_res.default_miss->refcount++;
return 0;
}
/* Called under ctx->ctrl_lock */
static void hws_table_down_default_fdb_miss_tbl(struct mlx5hws_table *tbl)
+__must_hold(&tbl->ctx->ctrl_lock)
{
struct mlx5hws_cmd_forward_tbl *default_miss;
struct mlx5hws_context *ctx = tbl->ctx;
- u8 tbl_type = tbl->type;
if (tbl->type != MLX5HWS_TABLE_TYPE_FDB)
return;
- default_miss = ctx->common_res[tbl_type].default_miss;
+ default_miss = ctx->common_res.default_miss;
if (--default_miss->refcount)
return;
mlx5hws_cmd_forward_tbl_destroy(ctx->mdev, default_miss);
- ctx->common_res[tbl_type].default_miss = NULL;
+ ctx->common_res.default_miss = NULL;
}
static int hws_table_connect_to_default_miss_tbl(struct mlx5hws_table *tbl, u32 ft_id)
@@ -478,15 +478,9 @@ int mlx5hws_table_set_default_miss(struct mlx5hws_table *tbl,
if (old_miss_tbl)
list_del_init(&tbl->default_miss.next);
- old_miss_tbl = tbl->default_miss.miss_tbl;
- if (old_miss_tbl)
- list_del_init(&old_miss_tbl->default_miss.head);
-
if (miss_tbl)
list_add(&tbl->default_miss.next, &miss_tbl->default_miss.head);
- mutex_unlock(&ctx->ctrl_lock);
- return 0;
out:
mutex_unlock(&ctx->ctrl_lock);
return ret;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_domain.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_domain.c
index 3d74109f8230..60cb4527588a 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_domain.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_domain.c
@@ -8,7 +8,7 @@
#define DR_DOMAIN_SW_STEERING_SUPPORTED(dmn, dmn_type) \
((dmn)->info.caps.dmn_type##_sw_owner || \
((dmn)->info.caps.dmn_type##_sw_owner_v2 && \
- (dmn)->info.caps.sw_format_ver <= MLX5_STEERING_FORMAT_CONNECTX_7))
+ (dmn)->info.caps.sw_format_ver <= MLX5_STEERING_FORMAT_CONNECTX_8))
bool mlx5dr_domain_is_support_ptrn_arg(struct mlx5dr_domain *dmn)
{
@@ -297,7 +297,9 @@ dr_domain_add_vport_cap(struct mlx5dr_domain *dmn, u16 vport)
if (ret) {
mlx5dr_dbg(dmn, "Couldn't insert new vport into xarray (%d)\n", ret);
kvfree(vport_caps);
- return ERR_PTR(ret);
+ if (ret == -EBUSY)
+ return ERR_PTR(-EBUSY);
+ return NULL;
}
return vport_caps;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c
index 6fa06ba2d346..f57c84e5128b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_send.c
@@ -1067,7 +1067,6 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
int inlen, err, eqn;
void *cqc, *in;
__be64 *pas;
- int vector;
u32 i;
cq = kzalloc(sizeof(*cq), GFP_KERNEL);
@@ -1096,8 +1095,7 @@ static struct mlx5dr_cq *dr_create_cq(struct mlx5_core_dev *mdev,
if (!in)
goto err_cqwq;
- vector = raw_smp_processor_id() % mlx5_comp_vectors_max(mdev);
- err = mlx5_comp_eqn_get(mdev, vector, &eqn);
+ err = mlx5_comp_eqn_get(mdev, 0, &eqn);
if (err) {
kvfree(in);
goto err_cqwq;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.c
index e94fbb015efa..c8b8ff80c7c7 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.c
@@ -555,7 +555,7 @@ void mlx5dr_ste_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx,
struct mlx5dr_ste_actions_attr *attr,
u32 *added_stes)
{
- ste_ctx->set_actions_tx(dmn, action_type_set, ste_ctx->actions_caps,
+ ste_ctx->set_actions_tx(ste_ctx, dmn, action_type_set, ste_ctx->actions_caps,
hw_ste_arr, attr, added_stes);
}
@@ -566,7 +566,7 @@ void mlx5dr_ste_set_actions_rx(struct mlx5dr_ste_ctx *ste_ctx,
struct mlx5dr_ste_actions_attr *attr,
u32 *added_stes)
{
- ste_ctx->set_actions_rx(dmn, action_type_set, ste_ctx->actions_caps,
+ ste_ctx->set_actions_rx(ste_ctx, dmn, action_type_set, ste_ctx->actions_caps,
hw_ste_arr, attr, added_stes);
}
@@ -1458,6 +1458,8 @@ struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx(u8 version)
return mlx5dr_ste_get_ctx_v1();
else if (version == MLX5_STEERING_FORMAT_CONNECTX_7)
return mlx5dr_ste_get_ctx_v2();
+ else if (version == MLX5_STEERING_FORMAT_CONNECTX_8)
+ return mlx5dr_ste_get_ctx_v3();
return NULL;
}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h
index 54a6619c3ecb..5f409dc30aca 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste.h
@@ -160,13 +160,15 @@ struct mlx5dr_ste_ctx {
/* Actions */
u32 actions_caps;
- void (*set_actions_rx)(struct mlx5dr_domain *dmn,
+ void (*set_actions_rx)(struct mlx5dr_ste_ctx *ste_ctx,
+ struct mlx5dr_domain *dmn,
u8 *action_type_set,
u32 actions_caps,
u8 *hw_ste_arr,
struct mlx5dr_ste_actions_attr *attr,
u32 *added_stes);
- void (*set_actions_tx)(struct mlx5dr_domain *dmn,
+ void (*set_actions_tx)(struct mlx5dr_ste_ctx *ste_ctx,
+ struct mlx5dr_domain *dmn,
u8 *action_type_set,
u32 actions_caps,
u8 *hw_ste_arr,
@@ -197,7 +199,17 @@ struct mlx5dr_ste_ctx {
u16 *used_hw_action_num);
int (*alloc_modify_hdr_chunk)(struct mlx5dr_action *action);
void (*dealloc_modify_hdr_chunk)(struct mlx5dr_action *action);
-
+ /* Actions bit set */
+ void (*set_encap)(u8 *hw_ste_p, u8 *d_action,
+ u32 reformat_id, int size);
+ void (*set_push_vlan)(u8 *ste, u8 *d_action,
+ u32 vlan_hdr);
+ void (*set_pop_vlan)(u8 *hw_ste_p, u8 *s_action,
+ u8 vlans_num);
+ void (*set_rx_decap)(u8 *hw_ste_p, u8 *s_action);
+ void (*set_encap_l3)(u8 *hw_ste_p, u8 *frst_s_action,
+ u8 *scnd_d_action, u32 reformat_id,
+ int size);
/* Send */
void (*prepare_for_postsend)(u8 *hw_ste_p, u32 ste_size);
};
@@ -205,5 +217,6 @@ struct mlx5dr_ste_ctx {
struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx_v0(void);
struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx_v1(void);
struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx_v2(void);
+struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx_v3(void);
#endif /* _DR_STE_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v0.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v0.c
index e9f6c7ed7a7b..42536bee55e2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v0.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v0.c
@@ -406,7 +406,8 @@ static void dr_ste_v0_arr_init_next(u8 **last_ste,
}
static void
-dr_ste_v0_set_actions_tx(struct mlx5dr_domain *dmn,
+dr_ste_v0_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx,
+ struct mlx5dr_domain *dmn,
u8 *action_type_set,
u32 actions_caps,
u8 *last_ste,
@@ -476,7 +477,8 @@ dr_ste_v0_set_actions_tx(struct mlx5dr_domain *dmn,
}
static void
-dr_ste_v0_set_actions_rx(struct mlx5dr_domain *dmn,
+dr_ste_v0_set_actions_rx(struct mlx5dr_ste_ctx *ste_ctx,
+ struct mlx5dr_domain *dmn,
u8 *action_type_set,
u32 actions_caps,
u8 *last_ste,
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c
index 1d49704b9542..7f83d77c43ef 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.c
@@ -5,136 +5,6 @@
#include "mlx5_ifc_dr_ste_v1.h"
#include "dr_ste_v1.h"
-#define DR_STE_CALC_DFNR_TYPE(lookup_type, inner) \
- ((inner) ? DR_STE_V1_LU_TYPE_##lookup_type##_I : \
- DR_STE_V1_LU_TYPE_##lookup_type##_O)
-
-enum dr_ste_v1_entry_format {
- DR_STE_V1_TYPE_BWC_BYTE = 0x0,
- DR_STE_V1_TYPE_BWC_DW = 0x1,
- DR_STE_V1_TYPE_MATCH = 0x2,
- DR_STE_V1_TYPE_MATCH_RANGES = 0x7,
-};
-
-/* Lookup type is built from 2B: [ Definer mode 1B ][ Definer index 1B ] */
-enum {
- DR_STE_V1_LU_TYPE_NOP = 0x0000,
- DR_STE_V1_LU_TYPE_ETHL2_TNL = 0x0002,
- DR_STE_V1_LU_TYPE_IBL3_EXT = 0x0102,
- DR_STE_V1_LU_TYPE_ETHL2_O = 0x0003,
- DR_STE_V1_LU_TYPE_IBL4 = 0x0103,
- DR_STE_V1_LU_TYPE_ETHL2_I = 0x0004,
- DR_STE_V1_LU_TYPE_SRC_QP_GVMI = 0x0104,
- DR_STE_V1_LU_TYPE_ETHL2_SRC_O = 0x0005,
- DR_STE_V1_LU_TYPE_ETHL2_HEADERS_O = 0x0105,
- DR_STE_V1_LU_TYPE_ETHL2_SRC_I = 0x0006,
- DR_STE_V1_LU_TYPE_ETHL2_HEADERS_I = 0x0106,
- DR_STE_V1_LU_TYPE_ETHL3_IPV4_5_TUPLE_O = 0x0007,
- DR_STE_V1_LU_TYPE_IPV6_DES_O = 0x0107,
- DR_STE_V1_LU_TYPE_ETHL3_IPV4_5_TUPLE_I = 0x0008,
- DR_STE_V1_LU_TYPE_IPV6_DES_I = 0x0108,
- DR_STE_V1_LU_TYPE_ETHL4_O = 0x0009,
- DR_STE_V1_LU_TYPE_IPV6_SRC_O = 0x0109,
- DR_STE_V1_LU_TYPE_ETHL4_I = 0x000a,
- DR_STE_V1_LU_TYPE_IPV6_SRC_I = 0x010a,
- DR_STE_V1_LU_TYPE_ETHL2_SRC_DST_O = 0x000b,
- DR_STE_V1_LU_TYPE_MPLS_O = 0x010b,
- DR_STE_V1_LU_TYPE_ETHL2_SRC_DST_I = 0x000c,
- DR_STE_V1_LU_TYPE_MPLS_I = 0x010c,
- DR_STE_V1_LU_TYPE_ETHL3_IPV4_MISC_O = 0x000d,
- DR_STE_V1_LU_TYPE_GRE = 0x010d,
- DR_STE_V1_LU_TYPE_FLEX_PARSER_TNL_HEADER = 0x000e,
- DR_STE_V1_LU_TYPE_GENERAL_PURPOSE = 0x010e,
- DR_STE_V1_LU_TYPE_ETHL3_IPV4_MISC_I = 0x000f,
- DR_STE_V1_LU_TYPE_STEERING_REGISTERS_0 = 0x010f,
- DR_STE_V1_LU_TYPE_STEERING_REGISTERS_1 = 0x0110,
- DR_STE_V1_LU_TYPE_FLEX_PARSER_OK = 0x0011,
- DR_STE_V1_LU_TYPE_FLEX_PARSER_0 = 0x0111,
- DR_STE_V1_LU_TYPE_FLEX_PARSER_1 = 0x0112,
- DR_STE_V1_LU_TYPE_ETHL4_MISC_O = 0x0113,
- DR_STE_V1_LU_TYPE_ETHL4_MISC_I = 0x0114,
- DR_STE_V1_LU_TYPE_INVALID = 0x00ff,
- DR_STE_V1_LU_TYPE_DONT_CARE = MLX5DR_STE_LU_TYPE_DONT_CARE,
-};
-
-enum dr_ste_v1_header_anchors {
- DR_STE_HEADER_ANCHOR_START_OUTER = 0x00,
- DR_STE_HEADER_ANCHOR_1ST_VLAN = 0x02,
- DR_STE_HEADER_ANCHOR_IPV6_IPV4 = 0x07,
- DR_STE_HEADER_ANCHOR_INNER_MAC = 0x13,
- DR_STE_HEADER_ANCHOR_INNER_IPV6_IPV4 = 0x19,
-};
-
-enum dr_ste_v1_action_size {
- DR_STE_ACTION_SINGLE_SZ = 4,
- DR_STE_ACTION_DOUBLE_SZ = 8,
- DR_STE_ACTION_TRIPLE_SZ = 12,
-};
-
-enum dr_ste_v1_action_insert_ptr_attr {
- DR_STE_V1_ACTION_INSERT_PTR_ATTR_NONE = 0, /* Regular push header (e.g. push vlan) */
- DR_STE_V1_ACTION_INSERT_PTR_ATTR_ENCAP = 1, /* Encapsulation / Tunneling */
- DR_STE_V1_ACTION_INSERT_PTR_ATTR_ESP = 2, /* IPsec */
-};
-
-enum dr_ste_v1_action_id {
- DR_STE_V1_ACTION_ID_NOP = 0x00,
- DR_STE_V1_ACTION_ID_COPY = 0x05,
- DR_STE_V1_ACTION_ID_SET = 0x06,
- DR_STE_V1_ACTION_ID_ADD = 0x07,
- DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE = 0x08,
- DR_STE_V1_ACTION_ID_REMOVE_HEADER_TO_HEADER = 0x09,
- DR_STE_V1_ACTION_ID_INSERT_INLINE = 0x0a,
- DR_STE_V1_ACTION_ID_INSERT_POINTER = 0x0b,
- DR_STE_V1_ACTION_ID_FLOW_TAG = 0x0c,
- DR_STE_V1_ACTION_ID_QUEUE_ID_SEL = 0x0d,
- DR_STE_V1_ACTION_ID_ACCELERATED_LIST = 0x0e,
- DR_STE_V1_ACTION_ID_MODIFY_LIST = 0x0f,
- DR_STE_V1_ACTION_ID_ASO = 0x12,
- DR_STE_V1_ACTION_ID_TRAILER = 0x13,
- DR_STE_V1_ACTION_ID_COUNTER_ID = 0x14,
- DR_STE_V1_ACTION_ID_MAX = 0x21,
- /* use for special cases */
- DR_STE_V1_ACTION_ID_SPECIAL_ENCAP_L3 = 0x22,
-};
-
-enum {
- DR_STE_V1_ACTION_MDFY_FLD_L2_OUT_0 = 0x00,
- DR_STE_V1_ACTION_MDFY_FLD_L2_OUT_1 = 0x01,
- DR_STE_V1_ACTION_MDFY_FLD_L2_OUT_2 = 0x02,
- DR_STE_V1_ACTION_MDFY_FLD_SRC_L2_OUT_0 = 0x08,
- DR_STE_V1_ACTION_MDFY_FLD_SRC_L2_OUT_1 = 0x09,
- DR_STE_V1_ACTION_MDFY_FLD_L3_OUT_0 = 0x0e,
- DR_STE_V1_ACTION_MDFY_FLD_L4_OUT_0 = 0x18,
- DR_STE_V1_ACTION_MDFY_FLD_L4_OUT_1 = 0x19,
- DR_STE_V1_ACTION_MDFY_FLD_IPV4_OUT_0 = 0x40,
- DR_STE_V1_ACTION_MDFY_FLD_IPV4_OUT_1 = 0x41,
- DR_STE_V1_ACTION_MDFY_FLD_IPV6_DST_OUT_0 = 0x44,
- DR_STE_V1_ACTION_MDFY_FLD_IPV6_DST_OUT_1 = 0x45,
- DR_STE_V1_ACTION_MDFY_FLD_IPV6_DST_OUT_2 = 0x46,
- DR_STE_V1_ACTION_MDFY_FLD_IPV6_DST_OUT_3 = 0x47,
- DR_STE_V1_ACTION_MDFY_FLD_IPV6_SRC_OUT_0 = 0x4c,
- DR_STE_V1_ACTION_MDFY_FLD_IPV6_SRC_OUT_1 = 0x4d,
- DR_STE_V1_ACTION_MDFY_FLD_IPV6_SRC_OUT_2 = 0x4e,
- DR_STE_V1_ACTION_MDFY_FLD_IPV6_SRC_OUT_3 = 0x4f,
- DR_STE_V1_ACTION_MDFY_FLD_TCP_MISC_0 = 0x5e,
- DR_STE_V1_ACTION_MDFY_FLD_TCP_MISC_1 = 0x5f,
- DR_STE_V1_ACTION_MDFY_FLD_CFG_HDR_0_0 = 0x6f,
- DR_STE_V1_ACTION_MDFY_FLD_CFG_HDR_0_1 = 0x70,
- DR_STE_V1_ACTION_MDFY_FLD_METADATA_2_CQE = 0x7b,
- DR_STE_V1_ACTION_MDFY_FLD_GNRL_PURPOSE = 0x7c,
- DR_STE_V1_ACTION_MDFY_FLD_REGISTER_2_0 = 0x8c,
- DR_STE_V1_ACTION_MDFY_FLD_REGISTER_2_1 = 0x8d,
- DR_STE_V1_ACTION_MDFY_FLD_REGISTER_1_0 = 0x8e,
- DR_STE_V1_ACTION_MDFY_FLD_REGISTER_1_1 = 0x8f,
- DR_STE_V1_ACTION_MDFY_FLD_REGISTER_0_0 = 0x90,
- DR_STE_V1_ACTION_MDFY_FLD_REGISTER_0_1 = 0x91,
-};
-
-enum dr_ste_v1_aso_ctx_type {
- DR_STE_V1_ASO_CTX_TYPE_POLICERS = 0x2,
-};
-
static const struct mlx5dr_ste_action_modify_field dr_ste_v1_action_modify_field_arr[] = {
[MLX5_ACTION_IN_FIELD_OUT_SMAC_47_16] = {
.hw_field = DR_STE_V1_ACTION_MDFY_FLD_SRC_L2_OUT_0, .start = 0, .end = 31,
@@ -379,13 +249,12 @@ static void dr_ste_v1_set_counter_id(u8 *hw_ste_p, u32 ctr_id)
MLX5_SET(ste_match_bwc_v1, hw_ste_p, counter_id, ctr_id);
}
-static void dr_ste_v1_set_reparse(u8 *hw_ste_p)
+void dr_ste_v1_set_reparse(u8 *hw_ste_p)
{
MLX5_SET(ste_match_bwc_v1, hw_ste_p, reparse, 1);
}
-static void dr_ste_v1_set_encap(u8 *hw_ste_p, u8 *d_action,
- u32 reformat_id, int size)
+void dr_ste_v1_set_encap(u8 *hw_ste_p, u8 *d_action, u32 reformat_id, int size)
{
MLX5_SET(ste_double_action_insert_with_ptr_v1, d_action, action_id,
DR_STE_V1_ACTION_ID_INSERT_POINTER);
@@ -432,8 +301,7 @@ static void dr_ste_v1_set_remove_hdr(u8 *hw_ste_p, u8 *s_action,
dr_ste_v1_set_reparse(hw_ste_p);
}
-static void dr_ste_v1_set_push_vlan(u8 *hw_ste_p, u8 *d_action,
- u32 vlan_hdr)
+void dr_ste_v1_set_push_vlan(u8 *hw_ste_p, u8 *d_action, u32 vlan_hdr)
{
MLX5_SET(ste_double_action_insert_with_inline_v1, d_action,
action_id, DR_STE_V1_ACTION_ID_INSERT_INLINE);
@@ -446,7 +314,7 @@ static void dr_ste_v1_set_push_vlan(u8 *hw_ste_p, u8 *d_action,
dr_ste_v1_set_reparse(hw_ste_p);
}
-static void dr_ste_v1_set_pop_vlan(u8 *hw_ste_p, u8 *s_action, u8 vlans_num)
+void dr_ste_v1_set_pop_vlan(u8 *hw_ste_p, u8 *s_action, u8 vlans_num)
{
MLX5_SET(ste_single_action_remove_header_size_v1, s_action,
action_id, DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE);
@@ -459,11 +327,8 @@ static void dr_ste_v1_set_pop_vlan(u8 *hw_ste_p, u8 *s_action, u8 vlans_num)
dr_ste_v1_set_reparse(hw_ste_p);
}
-static void dr_ste_v1_set_encap_l3(u8 *hw_ste_p,
- u8 *frst_s_action,
- u8 *scnd_d_action,
- u32 reformat_id,
- int size)
+void dr_ste_v1_set_encap_l3(u8 *hw_ste_p, u8 *frst_s_action, u8 *scnd_d_action,
+ u32 reformat_id, int size)
{
/* Remove L2 headers */
MLX5_SET(ste_single_action_remove_header_v1, frst_s_action, action_id,
@@ -483,7 +348,7 @@ static void dr_ste_v1_set_encap_l3(u8 *hw_ste_p,
dr_ste_v1_set_reparse(hw_ste_p);
}
-static void dr_ste_v1_set_rx_decap(u8 *hw_ste_p, u8 *s_action)
+void dr_ste_v1_set_rx_decap(u8 *hw_ste_p, u8 *s_action)
{
MLX5_SET(ste_single_action_remove_header_v1, s_action, action_id,
DR_STE_V1_ACTION_ID_REMOVE_HEADER_TO_HEADER);
@@ -620,7 +485,8 @@ static void dr_ste_v1_arr_init_next_match_range(u8 **last_ste,
dr_ste_v1_set_entry_type(*last_ste, DR_STE_V1_TYPE_MATCH_RANGES);
}
-void dr_ste_v1_set_actions_tx(struct mlx5dr_domain *dmn,
+void dr_ste_v1_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx,
+ struct mlx5dr_domain *dmn,
u8 *action_type_set,
u32 actions_caps,
u8 *last_ste,
@@ -640,7 +506,7 @@ void dr_ste_v1_set_actions_tx(struct mlx5dr_domain *dmn,
last_ste, action);
action_sz = DR_STE_ACTION_TRIPLE_SZ;
}
- dr_ste_v1_set_pop_vlan(last_ste, action, attr->vlans.count);
+ ste_ctx->set_pop_vlan(last_ste, action, attr->vlans.count);
action_sz -= DR_STE_ACTION_SINGLE_SZ;
action += DR_STE_ACTION_SINGLE_SZ;
@@ -677,8 +543,8 @@ void dr_ste_v1_set_actions_tx(struct mlx5dr_domain *dmn,
action_sz = DR_STE_ACTION_TRIPLE_SZ;
allow_encap = true;
}
- dr_ste_v1_set_push_vlan(last_ste, action,
- attr->vlans.headers[i]);
+ ste_ctx->set_push_vlan(last_ste, action,
+ attr->vlans.headers[i]);
action_sz -= DR_STE_ACTION_DOUBLE_SZ;
action += DR_STE_ACTION_DOUBLE_SZ;
}
@@ -691,9 +557,9 @@ void dr_ste_v1_set_actions_tx(struct mlx5dr_domain *dmn,
action_sz = DR_STE_ACTION_TRIPLE_SZ;
allow_encap = true;
}
- dr_ste_v1_set_encap(last_ste, action,
- attr->reformat.id,
- attr->reformat.size);
+ ste_ctx->set_encap(last_ste, action,
+ attr->reformat.id,
+ attr->reformat.size);
action_sz -= DR_STE_ACTION_DOUBLE_SZ;
action += DR_STE_ACTION_DOUBLE_SZ;
} else if (action_type_set[DR_ACTION_TYP_L2_TO_TNL_L3]) {
@@ -706,10 +572,10 @@ void dr_ste_v1_set_actions_tx(struct mlx5dr_domain *dmn,
}
d_action = action + DR_STE_ACTION_SINGLE_SZ;
- dr_ste_v1_set_encap_l3(last_ste,
- action, d_action,
- attr->reformat.id,
- attr->reformat.size);
+ ste_ctx->set_encap_l3(last_ste,
+ action, d_action,
+ attr->reformat.id,
+ attr->reformat.size);
action_sz -= DR_STE_ACTION_TRIPLE_SZ;
action += DR_STE_ACTION_TRIPLE_SZ;
} else if (action_type_set[DR_ACTION_TYP_INSERT_HDR]) {
@@ -776,7 +642,8 @@ void dr_ste_v1_set_actions_tx(struct mlx5dr_domain *dmn,
dr_ste_v1_set_hit_addr(last_ste, attr->final_icm_addr, 1);
}
-void dr_ste_v1_set_actions_rx(struct mlx5dr_domain *dmn,
+void dr_ste_v1_set_actions_rx(struct mlx5dr_ste_ctx *ste_ctx,
+ struct mlx5dr_domain *dmn,
u8 *action_type_set,
u32 actions_caps,
u8 *last_ste,
@@ -799,7 +666,7 @@ void dr_ste_v1_set_actions_rx(struct mlx5dr_domain *dmn,
allow_modify_hdr = false;
allow_ctr = false;
} else if (action_type_set[DR_ACTION_TYP_TNL_L2_TO_L2]) {
- dr_ste_v1_set_rx_decap(last_ste, action);
+ ste_ctx->set_rx_decap(last_ste, action);
action_sz -= DR_STE_ACTION_SINGLE_SZ;
action += DR_STE_ACTION_SINGLE_SZ;
allow_modify_hdr = false;
@@ -827,7 +694,7 @@ void dr_ste_v1_set_actions_rx(struct mlx5dr_domain *dmn,
action_sz = DR_STE_ACTION_TRIPLE_SZ;
}
- dr_ste_v1_set_pop_vlan(last_ste, action, attr->vlans.count);
+ ste_ctx->set_pop_vlan(last_ste, action, attr->vlans.count);
action_sz -= DR_STE_ACTION_SINGLE_SZ;
action += DR_STE_ACTION_SINGLE_SZ;
allow_ctr = false;
@@ -868,8 +735,8 @@ void dr_ste_v1_set_actions_rx(struct mlx5dr_domain *dmn,
last_ste, action);
action_sz = DR_STE_ACTION_TRIPLE_SZ;
}
- dr_ste_v1_set_push_vlan(last_ste, action,
- attr->vlans.headers[i]);
+ ste_ctx->set_push_vlan(last_ste, action,
+ attr->vlans.headers[i]);
action_sz -= DR_STE_ACTION_DOUBLE_SZ;
action += DR_STE_ACTION_DOUBLE_SZ;
}
@@ -895,9 +762,9 @@ void dr_ste_v1_set_actions_rx(struct mlx5dr_domain *dmn,
action = MLX5_ADDR_OF(ste_mask_and_match_v1, last_ste, action);
action_sz = DR_STE_ACTION_TRIPLE_SZ;
}
- dr_ste_v1_set_encap(last_ste, action,
- attr->reformat.id,
- attr->reformat.size);
+ ste_ctx->set_encap(last_ste, action,
+ attr->reformat.id,
+ attr->reformat.size);
action_sz -= DR_STE_ACTION_DOUBLE_SZ;
action += DR_STE_ACTION_DOUBLE_SZ;
allow_modify_hdr = false;
@@ -912,10 +779,10 @@ void dr_ste_v1_set_actions_rx(struct mlx5dr_domain *dmn,
d_action = action + DR_STE_ACTION_SINGLE_SZ;
- dr_ste_v1_set_encap_l3(last_ste,
- action, d_action,
- attr->reformat.id,
- attr->reformat.size);
+ ste_ctx->set_encap_l3(last_ste,
+ action, d_action,
+ attr->reformat.id,
+ attr->reformat.size);
action_sz -= DR_STE_ACTION_TRIPLE_SZ;
allow_modify_hdr = false;
} else if (action_type_set[DR_ACTION_TYP_INSERT_HDR]) {
@@ -1027,9 +894,6 @@ void dr_ste_v1_set_action_copy(u8 *d_action,
MLX5_SET(ste_double_action_copy_v1, d_action, source_right_shifter, src_shifter);
}
-#define DR_STE_DECAP_L3_ACTION_NUM 8
-#define DR_STE_L2_HDR_MAX_SZ 20
-
int dr_ste_v1_set_action_decap_l3_list(void *data,
u32 data_sz,
u8 *hw_action,
@@ -2330,7 +2194,12 @@ static struct mlx5dr_ste_ctx ste_ctx_v1 = {
.set_action_decap_l3_list = &dr_ste_v1_set_action_decap_l3_list,
.alloc_modify_hdr_chunk = &dr_ste_v1_alloc_modify_hdr_ptrn_arg,
.dealloc_modify_hdr_chunk = &dr_ste_v1_free_modify_hdr_ptrn_arg,
-
+ /* Actions bit set */
+ .set_encap = &dr_ste_v1_set_encap,
+ .set_push_vlan = &dr_ste_v1_set_push_vlan,
+ .set_pop_vlan = &dr_ste_v1_set_pop_vlan,
+ .set_rx_decap = &dr_ste_v1_set_rx_decap,
+ .set_encap_l3 = &dr_ste_v1_set_encap_l3,
/* Send */
.prepare_for_postsend = &dr_ste_v1_prepare_for_postsend,
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h
index e2fc69867088..a8d9e308d339 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v1.h
@@ -7,6 +7,138 @@
#include "dr_types.h"
#include "dr_ste.h"
+#define DR_STE_DECAP_L3_ACTION_NUM 8
+#define DR_STE_L2_HDR_MAX_SZ 20
+#define DR_STE_CALC_DFNR_TYPE(lookup_type, inner) \
+ ((inner) ? DR_STE_V1_LU_TYPE_##lookup_type##_I : \
+ DR_STE_V1_LU_TYPE_##lookup_type##_O)
+
+enum dr_ste_v1_entry_format {
+ DR_STE_V1_TYPE_BWC_BYTE = 0x0,
+ DR_STE_V1_TYPE_BWC_DW = 0x1,
+ DR_STE_V1_TYPE_MATCH = 0x2,
+ DR_STE_V1_TYPE_MATCH_RANGES = 0x7,
+};
+
+/* Lookup type is built from 2B: [ Definer mode 1B ][ Definer index 1B ] */
+enum {
+ DR_STE_V1_LU_TYPE_NOP = 0x0000,
+ DR_STE_V1_LU_TYPE_ETHL2_TNL = 0x0002,
+ DR_STE_V1_LU_TYPE_IBL3_EXT = 0x0102,
+ DR_STE_V1_LU_TYPE_ETHL2_O = 0x0003,
+ DR_STE_V1_LU_TYPE_IBL4 = 0x0103,
+ DR_STE_V1_LU_TYPE_ETHL2_I = 0x0004,
+ DR_STE_V1_LU_TYPE_SRC_QP_GVMI = 0x0104,
+ DR_STE_V1_LU_TYPE_ETHL2_SRC_O = 0x0005,
+ DR_STE_V1_LU_TYPE_ETHL2_HEADERS_O = 0x0105,
+ DR_STE_V1_LU_TYPE_ETHL2_SRC_I = 0x0006,
+ DR_STE_V1_LU_TYPE_ETHL2_HEADERS_I = 0x0106,
+ DR_STE_V1_LU_TYPE_ETHL3_IPV4_5_TUPLE_O = 0x0007,
+ DR_STE_V1_LU_TYPE_IPV6_DES_O = 0x0107,
+ DR_STE_V1_LU_TYPE_ETHL3_IPV4_5_TUPLE_I = 0x0008,
+ DR_STE_V1_LU_TYPE_IPV6_DES_I = 0x0108,
+ DR_STE_V1_LU_TYPE_ETHL4_O = 0x0009,
+ DR_STE_V1_LU_TYPE_IPV6_SRC_O = 0x0109,
+ DR_STE_V1_LU_TYPE_ETHL4_I = 0x000a,
+ DR_STE_V1_LU_TYPE_IPV6_SRC_I = 0x010a,
+ DR_STE_V1_LU_TYPE_ETHL2_SRC_DST_O = 0x000b,
+ DR_STE_V1_LU_TYPE_MPLS_O = 0x010b,
+ DR_STE_V1_LU_TYPE_ETHL2_SRC_DST_I = 0x000c,
+ DR_STE_V1_LU_TYPE_MPLS_I = 0x010c,
+ DR_STE_V1_LU_TYPE_ETHL3_IPV4_MISC_O = 0x000d,
+ DR_STE_V1_LU_TYPE_GRE = 0x010d,
+ DR_STE_V1_LU_TYPE_FLEX_PARSER_TNL_HEADER = 0x000e,
+ DR_STE_V1_LU_TYPE_GENERAL_PURPOSE = 0x010e,
+ DR_STE_V1_LU_TYPE_ETHL3_IPV4_MISC_I = 0x000f,
+ DR_STE_V1_LU_TYPE_STEERING_REGISTERS_0 = 0x010f,
+ DR_STE_V1_LU_TYPE_STEERING_REGISTERS_1 = 0x0110,
+ DR_STE_V1_LU_TYPE_FLEX_PARSER_OK = 0x0011,
+ DR_STE_V1_LU_TYPE_FLEX_PARSER_0 = 0x0111,
+ DR_STE_V1_LU_TYPE_FLEX_PARSER_1 = 0x0112,
+ DR_STE_V1_LU_TYPE_ETHL4_MISC_O = 0x0113,
+ DR_STE_V1_LU_TYPE_ETHL4_MISC_I = 0x0114,
+ DR_STE_V1_LU_TYPE_INVALID = 0x00ff,
+ DR_STE_V1_LU_TYPE_DONT_CARE = MLX5DR_STE_LU_TYPE_DONT_CARE,
+};
+
+enum dr_ste_v1_header_anchors {
+ DR_STE_HEADER_ANCHOR_START_OUTER = 0x00,
+ DR_STE_HEADER_ANCHOR_1ST_VLAN = 0x02,
+ DR_STE_HEADER_ANCHOR_IPV6_IPV4 = 0x07,
+ DR_STE_HEADER_ANCHOR_INNER_MAC = 0x13,
+ DR_STE_HEADER_ANCHOR_INNER_IPV6_IPV4 = 0x19,
+};
+
+enum dr_ste_v1_action_size {
+ DR_STE_ACTION_SINGLE_SZ = 4,
+ DR_STE_ACTION_DOUBLE_SZ = 8,
+ DR_STE_ACTION_TRIPLE_SZ = 12,
+};
+
+enum dr_ste_v1_action_insert_ptr_attr {
+ DR_STE_V1_ACTION_INSERT_PTR_ATTR_NONE = 0, /* Regular push header (e.g. push vlan) */
+ DR_STE_V1_ACTION_INSERT_PTR_ATTR_ENCAP = 1, /* Encapsulation / Tunneling */
+ DR_STE_V1_ACTION_INSERT_PTR_ATTR_ESP = 2, /* IPsec */
+};
+
+enum dr_ste_v1_action_id {
+ DR_STE_V1_ACTION_ID_NOP = 0x00,
+ DR_STE_V1_ACTION_ID_COPY = 0x05,
+ DR_STE_V1_ACTION_ID_SET = 0x06,
+ DR_STE_V1_ACTION_ID_ADD = 0x07,
+ DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE = 0x08,
+ DR_STE_V1_ACTION_ID_REMOVE_HEADER_TO_HEADER = 0x09,
+ DR_STE_V1_ACTION_ID_INSERT_INLINE = 0x0a,
+ DR_STE_V1_ACTION_ID_INSERT_POINTER = 0x0b,
+ DR_STE_V1_ACTION_ID_FLOW_TAG = 0x0c,
+ DR_STE_V1_ACTION_ID_QUEUE_ID_SEL = 0x0d,
+ DR_STE_V1_ACTION_ID_ACCELERATED_LIST = 0x0e,
+ DR_STE_V1_ACTION_ID_MODIFY_LIST = 0x0f,
+ DR_STE_V1_ACTION_ID_ASO = 0x12,
+ DR_STE_V1_ACTION_ID_TRAILER = 0x13,
+ DR_STE_V1_ACTION_ID_COUNTER_ID = 0x14,
+ DR_STE_V1_ACTION_ID_MAX = 0x21,
+ /* use for special cases */
+ DR_STE_V1_ACTION_ID_SPECIAL_ENCAP_L3 = 0x22,
+};
+
+enum {
+ DR_STE_V1_ACTION_MDFY_FLD_L2_OUT_0 = 0x00,
+ DR_STE_V1_ACTION_MDFY_FLD_L2_OUT_1 = 0x01,
+ DR_STE_V1_ACTION_MDFY_FLD_L2_OUT_2 = 0x02,
+ DR_STE_V1_ACTION_MDFY_FLD_SRC_L2_OUT_0 = 0x08,
+ DR_STE_V1_ACTION_MDFY_FLD_SRC_L2_OUT_1 = 0x09,
+ DR_STE_V1_ACTION_MDFY_FLD_L3_OUT_0 = 0x0e,
+ DR_STE_V1_ACTION_MDFY_FLD_L4_OUT_0 = 0x18,
+ DR_STE_V1_ACTION_MDFY_FLD_L4_OUT_1 = 0x19,
+ DR_STE_V1_ACTION_MDFY_FLD_IPV4_OUT_0 = 0x40,
+ DR_STE_V1_ACTION_MDFY_FLD_IPV4_OUT_1 = 0x41,
+ DR_STE_V1_ACTION_MDFY_FLD_IPV6_DST_OUT_0 = 0x44,
+ DR_STE_V1_ACTION_MDFY_FLD_IPV6_DST_OUT_1 = 0x45,
+ DR_STE_V1_ACTION_MDFY_FLD_IPV6_DST_OUT_2 = 0x46,
+ DR_STE_V1_ACTION_MDFY_FLD_IPV6_DST_OUT_3 = 0x47,
+ DR_STE_V1_ACTION_MDFY_FLD_IPV6_SRC_OUT_0 = 0x4c,
+ DR_STE_V1_ACTION_MDFY_FLD_IPV6_SRC_OUT_1 = 0x4d,
+ DR_STE_V1_ACTION_MDFY_FLD_IPV6_SRC_OUT_2 = 0x4e,
+ DR_STE_V1_ACTION_MDFY_FLD_IPV6_SRC_OUT_3 = 0x4f,
+ DR_STE_V1_ACTION_MDFY_FLD_TCP_MISC_0 = 0x5e,
+ DR_STE_V1_ACTION_MDFY_FLD_TCP_MISC_1 = 0x5f,
+ DR_STE_V1_ACTION_MDFY_FLD_CFG_HDR_0_0 = 0x6f,
+ DR_STE_V1_ACTION_MDFY_FLD_CFG_HDR_0_1 = 0x70,
+ DR_STE_V1_ACTION_MDFY_FLD_METADATA_2_CQE = 0x7b,
+ DR_STE_V1_ACTION_MDFY_FLD_GNRL_PURPOSE = 0x7c,
+ DR_STE_V1_ACTION_MDFY_FLD_REGISTER_2_0 = 0x8c,
+ DR_STE_V1_ACTION_MDFY_FLD_REGISTER_2_1 = 0x8d,
+ DR_STE_V1_ACTION_MDFY_FLD_REGISTER_1_0 = 0x8e,
+ DR_STE_V1_ACTION_MDFY_FLD_REGISTER_1_1 = 0x8f,
+ DR_STE_V1_ACTION_MDFY_FLD_REGISTER_0_0 = 0x90,
+ DR_STE_V1_ACTION_MDFY_FLD_REGISTER_0_1 = 0x91,
+};
+
+enum dr_ste_v1_aso_ctx_type {
+ DR_STE_V1_ASO_CTX_TYPE_POLICERS = 0x2,
+};
+
bool dr_ste_v1_is_miss_addr_set(u8 *hw_ste_p);
void dr_ste_v1_set_miss_addr(u8 *hw_ste_p, u64 miss_addr);
u64 dr_ste_v1_get_miss_addr(u8 *hw_ste_p);
@@ -17,11 +149,18 @@ u16 dr_ste_v1_get_next_lu_type(u8 *hw_ste_p);
void dr_ste_v1_set_hit_addr(u8 *hw_ste_p, u64 icm_addr, u32 ht_size);
void dr_ste_v1_init(u8 *hw_ste_p, u16 lu_type, bool is_rx, u16 gvmi);
void dr_ste_v1_prepare_for_postsend(u8 *hw_ste_p, u32 ste_size);
-void dr_ste_v1_set_actions_tx(struct mlx5dr_domain *dmn, u8 *action_type_set,
- u32 actions_caps, u8 *last_ste,
+void dr_ste_v1_set_reparse(u8 *hw_ste_p);
+void dr_ste_v1_set_encap(u8 *hw_ste_p, u8 *d_action, u32 reformat_id, int size);
+void dr_ste_v1_set_push_vlan(u8 *hw_ste_p, u8 *d_action, u32 vlan_hdr);
+void dr_ste_v1_set_pop_vlan(u8 *hw_ste_p, u8 *s_action, u8 vlans_num);
+void dr_ste_v1_set_encap_l3(u8 *hw_ste_p, u8 *frst_s_action, u8 *scnd_d_action,
+ u32 reformat_id, int size);
+void dr_ste_v1_set_rx_decap(u8 *hw_ste_p, u8 *s_action);
+void dr_ste_v1_set_actions_tx(struct mlx5dr_ste_ctx *ste_ctx, struct mlx5dr_domain *dmn,
+ u8 *action_type_set, u32 actions_caps, u8 *last_ste,
struct mlx5dr_ste_actions_attr *attr, u32 *added_stes);
-void dr_ste_v1_set_actions_rx(struct mlx5dr_domain *dmn, u8 *action_type_set,
- u32 actions_caps, u8 *last_ste,
+void dr_ste_v1_set_actions_rx(struct mlx5dr_ste_ctx *ste_ctx, struct mlx5dr_domain *dmn,
+ u8 *action_type_set, u32 actions_caps, u8 *last_ste,
struct mlx5dr_ste_actions_attr *attr, u32 *added_stes);
void dr_ste_v1_set_action_set(u8 *d_action, u8 hw_field, u8 shifter,
u8 length, u32 data);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c
index 808b013cf48c..0882dba0f64b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.c
@@ -2,167 +2,7 @@
/* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
#include "dr_ste_v1.h"
-
-enum {
- DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_0 = 0x00,
- DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_1 = 0x01,
- DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_2 = 0x02,
- DR_STE_V2_ACTION_MDFY_FLD_SRC_L2_OUT_0 = 0x08,
- DR_STE_V2_ACTION_MDFY_FLD_SRC_L2_OUT_1 = 0x09,
- DR_STE_V2_ACTION_MDFY_FLD_L3_OUT_0 = 0x0e,
- DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_0 = 0x18,
- DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_1 = 0x19,
- DR_STE_V2_ACTION_MDFY_FLD_IPV4_OUT_0 = 0x40,
- DR_STE_V2_ACTION_MDFY_FLD_IPV4_OUT_1 = 0x41,
- DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_0 = 0x44,
- DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_1 = 0x45,
- DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_2 = 0x46,
- DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_3 = 0x47,
- DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_0 = 0x4c,
- DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_1 = 0x4d,
- DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_2 = 0x4e,
- DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_3 = 0x4f,
- DR_STE_V2_ACTION_MDFY_FLD_TCP_MISC_0 = 0x5e,
- DR_STE_V2_ACTION_MDFY_FLD_TCP_MISC_1 = 0x5f,
- DR_STE_V2_ACTION_MDFY_FLD_CFG_HDR_0_0 = 0x6f,
- DR_STE_V2_ACTION_MDFY_FLD_CFG_HDR_0_1 = 0x70,
- DR_STE_V2_ACTION_MDFY_FLD_METADATA_2_CQE = 0x7b,
- DR_STE_V2_ACTION_MDFY_FLD_GNRL_PURPOSE = 0x7c,
- DR_STE_V2_ACTION_MDFY_FLD_REGISTER_2_0 = 0x90,
- DR_STE_V2_ACTION_MDFY_FLD_REGISTER_2_1 = 0x91,
- DR_STE_V2_ACTION_MDFY_FLD_REGISTER_1_0 = 0x92,
- DR_STE_V2_ACTION_MDFY_FLD_REGISTER_1_1 = 0x93,
- DR_STE_V2_ACTION_MDFY_FLD_REGISTER_0_0 = 0x94,
- DR_STE_V2_ACTION_MDFY_FLD_REGISTER_0_1 = 0x95,
-};
-
-static const struct mlx5dr_ste_action_modify_field dr_ste_v2_action_modify_field_arr[] = {
- [MLX5_ACTION_IN_FIELD_OUT_SMAC_47_16] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_SRC_L2_OUT_0, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_OUT_SMAC_15_0] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_SRC_L2_OUT_1, .start = 16, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_OUT_ETHERTYPE] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_1, .start = 0, .end = 15,
- },
- [MLX5_ACTION_IN_FIELD_OUT_DMAC_47_16] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_0, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_OUT_DMAC_15_0] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_1, .start = 16, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_OUT_IP_DSCP] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L3_OUT_0, .start = 18, .end = 23,
- },
- [MLX5_ACTION_IN_FIELD_OUT_TCP_FLAGS] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_1, .start = 16, .end = 24,
- .l4_type = DR_STE_ACTION_MDFY_TYPE_L4_TCP,
- },
- [MLX5_ACTION_IN_FIELD_OUT_TCP_SPORT] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_0, .start = 16, .end = 31,
- .l4_type = DR_STE_ACTION_MDFY_TYPE_L4_TCP,
- },
- [MLX5_ACTION_IN_FIELD_OUT_TCP_DPORT] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_0, .start = 0, .end = 15,
- .l4_type = DR_STE_ACTION_MDFY_TYPE_L4_TCP,
- },
- [MLX5_ACTION_IN_FIELD_OUT_IP_TTL] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L3_OUT_0, .start = 8, .end = 15,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV4,
- },
- [MLX5_ACTION_IN_FIELD_OUT_IPV6_HOPLIMIT] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L3_OUT_0, .start = 8, .end = 15,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
- },
- [MLX5_ACTION_IN_FIELD_OUT_UDP_SPORT] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_0, .start = 16, .end = 31,
- .l4_type = DR_STE_ACTION_MDFY_TYPE_L4_UDP,
- },
- [MLX5_ACTION_IN_FIELD_OUT_UDP_DPORT] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_0, .start = 0, .end = 15,
- .l4_type = DR_STE_ACTION_MDFY_TYPE_L4_UDP,
- },
- [MLX5_ACTION_IN_FIELD_OUT_SIPV6_127_96] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_0, .start = 0, .end = 31,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
- },
- [MLX5_ACTION_IN_FIELD_OUT_SIPV6_95_64] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_1, .start = 0, .end = 31,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
- },
- [MLX5_ACTION_IN_FIELD_OUT_SIPV6_63_32] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_2, .start = 0, .end = 31,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
- },
- [MLX5_ACTION_IN_FIELD_OUT_SIPV6_31_0] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_3, .start = 0, .end = 31,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
- },
- [MLX5_ACTION_IN_FIELD_OUT_DIPV6_127_96] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_0, .start = 0, .end = 31,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
- },
- [MLX5_ACTION_IN_FIELD_OUT_DIPV6_95_64] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_1, .start = 0, .end = 31,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
- },
- [MLX5_ACTION_IN_FIELD_OUT_DIPV6_63_32] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_2, .start = 0, .end = 31,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
- },
- [MLX5_ACTION_IN_FIELD_OUT_DIPV6_31_0] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_3, .start = 0, .end = 31,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
- },
- [MLX5_ACTION_IN_FIELD_OUT_SIPV4] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV4_OUT_0, .start = 0, .end = 31,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV4,
- },
- [MLX5_ACTION_IN_FIELD_OUT_DIPV4] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV4_OUT_1, .start = 0, .end = 31,
- .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV4,
- },
- [MLX5_ACTION_IN_FIELD_METADATA_REG_A] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_GNRL_PURPOSE, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_METADATA_REG_B] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_METADATA_2_CQE, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_METADATA_REG_C_0] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_0_0, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_METADATA_REG_C_1] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_0_1, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_METADATA_REG_C_2] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_1_0, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_METADATA_REG_C_3] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_1_1, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_METADATA_REG_C_4] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_2_0, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_METADATA_REG_C_5] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_2_1, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_OUT_TCP_SEQ_NUM] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_TCP_MISC_0, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_OUT_TCP_ACK_NUM] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_TCP_MISC_1, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_OUT_FIRST_VID] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_2, .start = 0, .end = 15,
- },
- [MLX5_ACTION_IN_FIELD_OUT_EMD_31_0] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_CFG_HDR_0_1, .start = 0, .end = 31,
- },
- [MLX5_ACTION_IN_FIELD_OUT_EMD_47_32] = {
- .hw_field = DR_STE_V2_ACTION_MDFY_FLD_CFG_HDR_0_0, .start = 0, .end = 15,
- },
-};
+#include "dr_ste_v2.h"
static struct mlx5dr_ste_ctx ste_ctx_v2 = {
/* Builders */
@@ -223,7 +63,12 @@ static struct mlx5dr_ste_ctx ste_ctx_v2 = {
.set_action_decap_l3_list = &dr_ste_v1_set_action_decap_l3_list,
.alloc_modify_hdr_chunk = &dr_ste_v1_alloc_modify_hdr_ptrn_arg,
.dealloc_modify_hdr_chunk = &dr_ste_v1_free_modify_hdr_ptrn_arg,
-
+ /* Actions bit set */
+ .set_encap = &dr_ste_v1_set_encap,
+ .set_push_vlan = &dr_ste_v1_set_push_vlan,
+ .set_pop_vlan = &dr_ste_v1_set_pop_vlan,
+ .set_rx_decap = &dr_ste_v1_set_rx_decap,
+ .set_encap_l3 = &dr_ste_v1_set_encap_l3,
/* Send */
.prepare_for_postsend = &dr_ste_v1_prepare_for_postsend,
};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.h
new file mode 100644
index 000000000000..d853fde49cfc
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v2.h
@@ -0,0 +1,168 @@
+/* SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB */
+/* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#ifndef _DR_STE_V2_
+#define _DR_STE_V2_
+
+enum {
+ DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_0 = 0x00,
+ DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_1 = 0x01,
+ DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_2 = 0x02,
+ DR_STE_V2_ACTION_MDFY_FLD_SRC_L2_OUT_0 = 0x08,
+ DR_STE_V2_ACTION_MDFY_FLD_SRC_L2_OUT_1 = 0x09,
+ DR_STE_V2_ACTION_MDFY_FLD_L3_OUT_0 = 0x0e,
+ DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_0 = 0x18,
+ DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_1 = 0x19,
+ DR_STE_V2_ACTION_MDFY_FLD_IPV4_OUT_0 = 0x40,
+ DR_STE_V2_ACTION_MDFY_FLD_IPV4_OUT_1 = 0x41,
+ DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_0 = 0x44,
+ DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_1 = 0x45,
+ DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_2 = 0x46,
+ DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_3 = 0x47,
+ DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_0 = 0x4c,
+ DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_1 = 0x4d,
+ DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_2 = 0x4e,
+ DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_3 = 0x4f,
+ DR_STE_V2_ACTION_MDFY_FLD_TCP_MISC_0 = 0x5e,
+ DR_STE_V2_ACTION_MDFY_FLD_TCP_MISC_1 = 0x5f,
+ DR_STE_V2_ACTION_MDFY_FLD_CFG_HDR_0_0 = 0x6f,
+ DR_STE_V2_ACTION_MDFY_FLD_CFG_HDR_0_1 = 0x70,
+ DR_STE_V2_ACTION_MDFY_FLD_METADATA_2_CQE = 0x7b,
+ DR_STE_V2_ACTION_MDFY_FLD_GNRL_PURPOSE = 0x7c,
+ DR_STE_V2_ACTION_MDFY_FLD_REGISTER_2_0 = 0x90,
+ DR_STE_V2_ACTION_MDFY_FLD_REGISTER_2_1 = 0x91,
+ DR_STE_V2_ACTION_MDFY_FLD_REGISTER_1_0 = 0x92,
+ DR_STE_V2_ACTION_MDFY_FLD_REGISTER_1_1 = 0x93,
+ DR_STE_V2_ACTION_MDFY_FLD_REGISTER_0_0 = 0x94,
+ DR_STE_V2_ACTION_MDFY_FLD_REGISTER_0_1 = 0x95,
+};
+
+static const struct mlx5dr_ste_action_modify_field dr_ste_v2_action_modify_field_arr[] = {
+ [MLX5_ACTION_IN_FIELD_OUT_SMAC_47_16] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_SRC_L2_OUT_0, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_SMAC_15_0] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_SRC_L2_OUT_1, .start = 16, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_ETHERTYPE] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_1, .start = 0, .end = 15,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_DMAC_47_16] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_0, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_DMAC_15_0] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_1, .start = 16, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_IP_DSCP] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L3_OUT_0, .start = 18, .end = 23,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_TCP_FLAGS] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_1, .start = 16, .end = 24,
+ .l4_type = DR_STE_ACTION_MDFY_TYPE_L4_TCP,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_TCP_SPORT] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_0, .start = 16, .end = 31,
+ .l4_type = DR_STE_ACTION_MDFY_TYPE_L4_TCP,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_TCP_DPORT] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_0, .start = 0, .end = 15,
+ .l4_type = DR_STE_ACTION_MDFY_TYPE_L4_TCP,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_IP_TTL] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L3_OUT_0, .start = 8, .end = 15,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV4,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_IPV6_HOPLIMIT] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L3_OUT_0, .start = 8, .end = 15,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_UDP_SPORT] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_0, .start = 16, .end = 31,
+ .l4_type = DR_STE_ACTION_MDFY_TYPE_L4_UDP,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_UDP_DPORT] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L4_OUT_0, .start = 0, .end = 15,
+ .l4_type = DR_STE_ACTION_MDFY_TYPE_L4_UDP,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_SIPV6_127_96] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_0, .start = 0, .end = 31,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_SIPV6_95_64] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_1, .start = 0, .end = 31,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_SIPV6_63_32] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_2, .start = 0, .end = 31,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_SIPV6_31_0] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_SRC_OUT_3, .start = 0, .end = 31,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_DIPV6_127_96] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_0, .start = 0, .end = 31,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_DIPV6_95_64] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_1, .start = 0, .end = 31,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_DIPV6_63_32] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_2, .start = 0, .end = 31,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_DIPV6_31_0] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV6_DST_OUT_3, .start = 0, .end = 31,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV6,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_SIPV4] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV4_OUT_0, .start = 0, .end = 31,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV4,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_DIPV4] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_IPV4_OUT_1, .start = 0, .end = 31,
+ .l3_type = DR_STE_ACTION_MDFY_TYPE_L3_IPV4,
+ },
+ [MLX5_ACTION_IN_FIELD_METADATA_REG_A] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_GNRL_PURPOSE, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_METADATA_REG_B] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_METADATA_2_CQE, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_METADATA_REG_C_0] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_0_0, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_METADATA_REG_C_1] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_0_1, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_METADATA_REG_C_2] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_1_0, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_METADATA_REG_C_3] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_1_1, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_METADATA_REG_C_4] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_2_0, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_METADATA_REG_C_5] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_REGISTER_2_1, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_TCP_SEQ_NUM] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_TCP_MISC_0, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_TCP_ACK_NUM] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_TCP_MISC_1, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_FIRST_VID] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_L2_OUT_2, .start = 0, .end = 15,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_EMD_31_0] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_CFG_HDR_0_1, .start = 0, .end = 31,
+ },
+ [MLX5_ACTION_IN_FIELD_OUT_EMD_47_32] = {
+ .hw_field = DR_STE_V2_ACTION_MDFY_FLD_CFG_HDR_0_0, .start = 0, .end = 15,
+ },
+};
+
+#endif /* _DR_STE_V2_ */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c
new file mode 100644
index 000000000000..cc60ce1d274e
--- /dev/null
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/dr_ste_v3.c
@@ -0,0 +1,221 @@
+// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
+/* Copyright (c) 2024, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
+
+#include "dr_ste_v1.h"
+#include "dr_ste_v2.h"
+
+static void dr_ste_v3_set_encap(u8 *hw_ste_p, u8 *d_action,
+ u32 reformat_id, int size)
+{
+ MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, action_id,
+ DR_STE_V1_ACTION_ID_INSERT_POINTER);
+ /* The hardware expects here size in words (2 byte) */
+ MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, size, size / 2);
+ MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, pointer, reformat_id);
+ MLX5_SET(ste_double_action_insert_with_ptr_v3, d_action, attributes,
+ DR_STE_V1_ACTION_INSERT_PTR_ATTR_ENCAP);
+ dr_ste_v1_set_reparse(hw_ste_p);
+}
+
+static void dr_ste_v3_set_push_vlan(u8 *ste, u8 *d_action,
+ u32 vlan_hdr)
+{
+ MLX5_SET(ste_double_action_insert_with_inline_v3, d_action, action_id,
+ DR_STE_V1_ACTION_ID_INSERT_INLINE);
+ /* The hardware expects here offset to vlan header in words (2 byte) */
+ MLX5_SET(ste_double_action_insert_with_inline_v3, d_action, start_offset,
+ HDR_LEN_L2_MACS >> 1);
+ MLX5_SET(ste_double_action_insert_with_inline_v3, d_action, inline_data, vlan_hdr);
+ dr_ste_v1_set_reparse(ste);
+}
+
+static void dr_ste_v3_set_pop_vlan(u8 *hw_ste_p, u8 *s_action,
+ u8 vlans_num)
+{
+ MLX5_SET(ste_single_action_remove_header_size_v3, s_action,
+ action_id, DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE);
+ MLX5_SET(ste_single_action_remove_header_size_v3, s_action,
+ start_anchor, DR_STE_HEADER_ANCHOR_1ST_VLAN);
+ /* The hardware expects here size in words (2 byte) */
+ MLX5_SET(ste_single_action_remove_header_size_v3, s_action,
+ remove_size, (HDR_LEN_L2_VLAN >> 1) * vlans_num);
+
+ dr_ste_v1_set_reparse(hw_ste_p);
+}
+
+static void dr_ste_v3_set_encap_l3(u8 *hw_ste_p,
+ u8 *frst_s_action,
+ u8 *scnd_d_action,
+ u32 reformat_id,
+ int size)
+{
+ /* Remove L2 headers */
+ MLX5_SET(ste_single_action_remove_header_v3, frst_s_action, action_id,
+ DR_STE_V1_ACTION_ID_REMOVE_HEADER_TO_HEADER);
+ MLX5_SET(ste_single_action_remove_header_v3, frst_s_action, end_anchor,
+ DR_STE_HEADER_ANCHOR_IPV6_IPV4);
+
+ /* Encapsulate with given reformat ID */
+ MLX5_SET(ste_double_action_insert_with_ptr_v3, scnd_d_action, action_id,
+ DR_STE_V1_ACTION_ID_INSERT_POINTER);
+ /* The hardware expects here size in words (2 byte) */
+ MLX5_SET(ste_double_action_insert_with_ptr_v3, scnd_d_action, size, size / 2);
+ MLX5_SET(ste_double_action_insert_with_ptr_v3, scnd_d_action, pointer, reformat_id);
+ MLX5_SET(ste_double_action_insert_with_ptr_v3, scnd_d_action, attributes,
+ DR_STE_V1_ACTION_INSERT_PTR_ATTR_ENCAP);
+
+ dr_ste_v1_set_reparse(hw_ste_p);
+}
+
+static void dr_ste_v3_set_rx_decap(u8 *hw_ste_p, u8 *s_action)
+{
+ MLX5_SET(ste_single_action_remove_header_v3, s_action, action_id,
+ DR_STE_V1_ACTION_ID_REMOVE_HEADER_TO_HEADER);
+ MLX5_SET(ste_single_action_remove_header_v3, s_action, decap, 1);
+ MLX5_SET(ste_single_action_remove_header_v3, s_action, vni_to_cqe, 1);
+ MLX5_SET(ste_single_action_remove_header_v3, s_action, end_anchor,
+ DR_STE_HEADER_ANCHOR_INNER_MAC);
+
+ dr_ste_v1_set_reparse(hw_ste_p);
+}
+
+static int
+dr_ste_v3_set_action_decap_l3_list(void *data, u32 data_sz,
+ u8 *hw_action, u32 hw_action_sz,
+ uint16_t *used_hw_action_num)
+{
+ u8 padded_data[DR_STE_L2_HDR_MAX_SZ] = {};
+ void *data_ptr = padded_data;
+ u16 used_actions = 0;
+ u32 inline_data_sz;
+ u32 i;
+
+ if (hw_action_sz / DR_STE_ACTION_DOUBLE_SZ < DR_STE_DECAP_L3_ACTION_NUM)
+ return -EINVAL;
+
+ inline_data_sz =
+ MLX5_FLD_SZ_BYTES(ste_double_action_insert_with_inline_v3, inline_data);
+
+ /* Add an alignment padding */
+ memcpy(padded_data + data_sz % inline_data_sz, data, data_sz);
+
+ /* Remove L2L3 outer headers */
+ MLX5_SET(ste_single_action_remove_header_v3, hw_action, action_id,
+ DR_STE_V1_ACTION_ID_REMOVE_HEADER_TO_HEADER);
+ MLX5_SET(ste_single_action_remove_header_v3, hw_action, decap, 1);
+ MLX5_SET(ste_single_action_remove_header_v3, hw_action, vni_to_cqe, 1);
+ MLX5_SET(ste_single_action_remove_header_v3, hw_action, end_anchor,
+ DR_STE_HEADER_ANCHOR_INNER_IPV6_IPV4);
+ hw_action += DR_STE_ACTION_DOUBLE_SZ;
+ used_actions++; /* Remove and NOP are a single double action */
+
+ /* Point to the last dword of the header */
+ data_ptr += (data_sz / inline_data_sz) * inline_data_sz;
+
+ /* Add the new header using inline action 4Byte at a time, the header
+ * is added in reversed order to the beginning of the packet to avoid
+ * incorrect parsing by the HW. Since header is 14B or 18B an extra
+ * two bytes are padded and later removed.
+ */
+ for (i = 0; i < data_sz / inline_data_sz + 1; i++) {
+ void *addr_inline;
+
+ MLX5_SET(ste_double_action_insert_with_inline_v3, hw_action, action_id,
+ DR_STE_V1_ACTION_ID_INSERT_INLINE);
+ /* The hardware expects here offset to words (2 bytes) */
+ MLX5_SET(ste_double_action_insert_with_inline_v3, hw_action, start_offset, 0);
+
+ /* Copy bytes one by one to avoid endianness problem */
+ addr_inline = MLX5_ADDR_OF(ste_double_action_insert_with_inline_v3,
+ hw_action, inline_data);
+ memcpy(addr_inline, data_ptr - i * inline_data_sz, inline_data_sz);
+ hw_action += DR_STE_ACTION_DOUBLE_SZ;
+ used_actions++;
+ }
+
+ /* Remove first 2 extra bytes */
+ MLX5_SET(ste_single_action_remove_header_size_v3, hw_action, action_id,
+ DR_STE_V1_ACTION_ID_REMOVE_BY_SIZE);
+ MLX5_SET(ste_single_action_remove_header_size_v3, hw_action, start_offset, 0);
+ /* The hardware expects here size in words (2 bytes) */
+ MLX5_SET(ste_single_action_remove_header_size_v3, hw_action, remove_size, 1);
+ used_actions++;
+
+ *used_hw_action_num = used_actions;
+
+ return 0;
+}
+
+static struct mlx5dr_ste_ctx ste_ctx_v3 = {
+ /* Builders */
+ .build_eth_l2_src_dst_init = &dr_ste_v1_build_eth_l2_src_dst_init,
+ .build_eth_l3_ipv6_src_init = &dr_ste_v1_build_eth_l3_ipv6_src_init,
+ .build_eth_l3_ipv6_dst_init = &dr_ste_v1_build_eth_l3_ipv6_dst_init,
+ .build_eth_l3_ipv4_5_tuple_init = &dr_ste_v1_build_eth_l3_ipv4_5_tuple_init,
+ .build_eth_l2_src_init = &dr_ste_v1_build_eth_l2_src_init,
+ .build_eth_l2_dst_init = &dr_ste_v1_build_eth_l2_dst_init,
+ .build_eth_l2_tnl_init = &dr_ste_v1_build_eth_l2_tnl_init,
+ .build_eth_l3_ipv4_misc_init = &dr_ste_v1_build_eth_l3_ipv4_misc_init,
+ .build_eth_ipv6_l3_l4_init = &dr_ste_v1_build_eth_ipv6_l3_l4_init,
+ .build_mpls_init = &dr_ste_v1_build_mpls_init,
+ .build_tnl_gre_init = &dr_ste_v1_build_tnl_gre_init,
+ .build_tnl_mpls_init = &dr_ste_v1_build_tnl_mpls_init,
+ .build_tnl_mpls_over_udp_init = &dr_ste_v1_build_tnl_mpls_over_udp_init,
+ .build_tnl_mpls_over_gre_init = &dr_ste_v1_build_tnl_mpls_over_gre_init,
+ .build_icmp_init = &dr_ste_v1_build_icmp_init,
+ .build_general_purpose_init = &dr_ste_v1_build_general_purpose_init,
+ .build_eth_l4_misc_init = &dr_ste_v1_build_eth_l4_misc_init,
+ .build_tnl_vxlan_gpe_init = &dr_ste_v1_build_flex_parser_tnl_vxlan_gpe_init,
+ .build_tnl_geneve_init = &dr_ste_v1_build_flex_parser_tnl_geneve_init,
+ .build_tnl_geneve_tlv_opt_init = &dr_ste_v1_build_flex_parser_tnl_geneve_tlv_opt_init,
+ .build_tnl_geneve_tlv_opt_exist_init =
+ &dr_ste_v1_build_flex_parser_tnl_geneve_tlv_opt_exist_init,
+ .build_register_0_init = &dr_ste_v1_build_register_0_init,
+ .build_register_1_init = &dr_ste_v1_build_register_1_init,
+ .build_src_gvmi_qpn_init = &dr_ste_v1_build_src_gvmi_qpn_init,
+ .build_flex_parser_0_init = &dr_ste_v1_build_flex_parser_0_init,
+ .build_flex_parser_1_init = &dr_ste_v1_build_flex_parser_1_init,
+ .build_tnl_gtpu_init = &dr_ste_v1_build_flex_parser_tnl_gtpu_init,
+ .build_tnl_header_0_1_init = &dr_ste_v1_build_tnl_header_0_1_init,
+ .build_tnl_gtpu_flex_parser_0_init = &dr_ste_v1_build_tnl_gtpu_flex_parser_0_init,
+ .build_tnl_gtpu_flex_parser_1_init = &dr_ste_v1_build_tnl_gtpu_flex_parser_1_init,
+
+ /* Getters and Setters */
+ .ste_init = &dr_ste_v1_init,
+ .set_next_lu_type = &dr_ste_v1_set_next_lu_type,
+ .get_next_lu_type = &dr_ste_v1_get_next_lu_type,
+ .is_miss_addr_set = &dr_ste_v1_is_miss_addr_set,
+ .set_miss_addr = &dr_ste_v1_set_miss_addr,
+ .get_miss_addr = &dr_ste_v1_get_miss_addr,
+ .set_hit_addr = &dr_ste_v1_set_hit_addr,
+ .set_byte_mask = &dr_ste_v1_set_byte_mask,
+ .get_byte_mask = &dr_ste_v1_get_byte_mask,
+
+ /* Actions */
+ .actions_caps = DR_STE_CTX_ACTION_CAP_TX_POP |
+ DR_STE_CTX_ACTION_CAP_RX_PUSH |
+ DR_STE_CTX_ACTION_CAP_RX_ENCAP,
+ .set_actions_rx = &dr_ste_v1_set_actions_rx,
+ .set_actions_tx = &dr_ste_v1_set_actions_tx,
+ .modify_field_arr_sz = ARRAY_SIZE(dr_ste_v2_action_modify_field_arr),
+ .modify_field_arr = dr_ste_v2_action_modify_field_arr,
+ .set_action_set = &dr_ste_v1_set_action_set,
+ .set_action_add = &dr_ste_v1_set_action_add,
+ .set_action_copy = &dr_ste_v1_set_action_copy,
+ .set_action_decap_l3_list = &dr_ste_v3_set_action_decap_l3_list,
+ .alloc_modify_hdr_chunk = &dr_ste_v1_alloc_modify_hdr_ptrn_arg,
+ .dealloc_modify_hdr_chunk = &dr_ste_v1_free_modify_hdr_ptrn_arg,
+ /* Actions bit set */
+ .set_encap = &dr_ste_v3_set_encap,
+ .set_push_vlan = &dr_ste_v3_set_push_vlan,
+ .set_pop_vlan = &dr_ste_v3_set_pop_vlan,
+ .set_rx_decap = &dr_ste_v3_set_rx_decap,
+ .set_encap_l3 = &dr_ste_v3_set_encap_l3,
+ /* Send */
+ .prepare_for_postsend = &dr_ste_v1_prepare_for_postsend,
+};
+
+struct mlx5dr_ste_ctx *mlx5dr_ste_get_ctx_v3(void)
+{
+ return &ste_ctx_v3;
+}
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.c b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.c
index 4b349d4005e4..8007d3f523c9 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/fs_dr.c
@@ -521,7 +521,7 @@ static int mlx5_cmd_dr_create_fte(struct mlx5_flow_root_namespace *ns,
goto free_actions;
}
- id = dst->dest_attr.counter_id;
+ id = mlx5_fc_id(dst->dest_attr.counter);
tmp_action =
mlx5dr_action_create_flow_counter(id);
if (!tmp_action) {
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr.h
index fb078fa0f0cc..898c3618ff26 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5_ifc_dr.h
@@ -600,4 +600,44 @@ struct mlx5_ifc_ste_double_action_aso_v1_bits {
};
};
+struct mlx5_ifc_ste_single_action_remove_header_v3_bits {
+ u8 action_id[0x8];
+ u8 start_anchor[0x7];
+ u8 end_anchor[0x7];
+ u8 reserved_at_16[0x1];
+ u8 outer_l4_remove[0x1];
+ u8 reserved_at_18[0x4];
+ u8 decap[0x1];
+ u8 vni_to_cqe[0x1];
+ u8 qos_profile[0x2];
+};
+
+struct mlx5_ifc_ste_single_action_remove_header_size_v3_bits {
+ u8 action_id[0x8];
+ u8 start_anchor[0x7];
+ u8 start_offset[0x8];
+ u8 outer_l4_remove[0x1];
+ u8 reserved_at_18[0x2];
+ u8 remove_size[0x6];
+};
+
+struct mlx5_ifc_ste_double_action_insert_with_inline_v3_bits {
+ u8 action_id[0x8];
+ u8 start_anchor[0x7];
+ u8 start_offset[0x8];
+ u8 reserved_at_17[0x9];
+
+ u8 inline_data[0x20];
+};
+
+struct mlx5_ifc_ste_double_action_insert_with_ptr_v3_bits {
+ u8 action_id[0x8];
+ u8 start_anchor[0x7];
+ u8 start_offset[0x8];
+ u8 size[0x6];
+ u8 attributes[0x3];
+
+ u8 pointer[0x20];
+};
+
#endif /* MLX5_IFC_DR_H */
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5dr.h b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5dr.h
index 3ac7dc67509f..0bb3724c10c2 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5dr.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/steering/sws/mlx5dr.h
@@ -160,7 +160,7 @@ mlx5dr_is_supported(struct mlx5_core_dev *dev)
(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, sw_owner) ||
(MLX5_CAP_ESW_FLOWTABLE_FDB(dev, sw_owner_v2) &&
(MLX5_CAP_GEN(dev, steering_format_version) <=
- MLX5_STEERING_FORMAT_CONNECTX_7)));
+ MLX5_STEERING_FORMAT_CONNECTX_8)));
}
/* buddy functions & structure */
diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h
index 6d11225594dd..24c3ff6fcf71 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/core.h
+++ b/drivers/net/ethernet/mellanox/mlxsw/core.h
@@ -73,6 +73,7 @@ struct mlxsw_tx_info {
};
struct mlxsw_rx_md_info {
+ struct napi_struct *napi;
u32 cookie_index;
u32 latency;
u32 tx_congestion;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c
index d6f37456fb31..0863dca2fc0b 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/pci.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c
@@ -737,6 +737,7 @@ static void mlxsw_pci_cqe_rdq_md_init(struct sk_buff *skb, const char *cqe)
}
static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci,
+ struct napi_struct *napi,
struct mlxsw_pci_queue *q,
u16 consumer_counter_limit,
enum mlxsw_pci_cqe_v cqe_v, char *cqe)
@@ -807,6 +808,7 @@ static void mlxsw_pci_cqe_rdq_handle(struct mlxsw_pci *mlxsw_pci,
}
mlxsw_pci_skb_cb_ts_set(mlxsw_pci, skb, cqe_v, cqe);
+ mlxsw_skb_cb(skb)->rx_md_info.napi = napi;
mlxsw_core_skb_receive(mlxsw_pci->core, skb, &rx_info);
@@ -869,7 +871,7 @@ static int mlxsw_pci_napi_poll_cq_rx(struct napi_struct *napi, int budget)
continue;
}
- mlxsw_pci_cqe_rdq_handle(mlxsw_pci, rdq,
+ mlxsw_pci_cqe_rdq_handle(mlxsw_pci, napi, rdq,
wqe_counter, q->u.cq.v, cqe);
if (++work_done == budget)
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 3f5e5d99251b..aa71993daf28 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -2449,7 +2449,7 @@ void mlxsw_sp_rx_listener_no_mark_func(struct sk_buff *skb,
u64_stats_update_end(&pcpu_stats->syncp);
skb->protocol = eth_type_trans(skb, skb->dev);
- netif_receive_skb(skb);
+ napi_gro_receive(mlxsw_skb_cb(skb)->rx_md_info.napi, skb);
}
static void mlxsw_sp_rx_listener_mark_func(struct sk_buff *skb, u16 local_port,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
index 6fe185ea6732..1850a975b380 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_acl_flex_keys.c
@@ -324,6 +324,10 @@ static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_mac_5b[] =
MLXSW_AFK_ELEMENT_INST_EXT_U32(SRC_SYS_PORT, 0x04, 0, 9, -1, true), /* RX_ACL_SYSTEM_PORT */
};
+static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_1b[] = {
+ MLXSW_AFK_ELEMENT_INST_BUF(SRC_IP_0_31, 0x04, 4),
+};
+
static const struct mlxsw_afk_element_inst mlxsw_sp_afk_element_info_ipv4_5b[] = {
MLXSW_AFK_ELEMENT_INST_U32(VIRT_ROUTER, 0x04, 20, 12),
};
@@ -341,7 +345,7 @@ static const struct mlxsw_afk_block mlxsw_sp4_afk_blocks[] = {
MLXSW_AFK_BLOCK(0x14, mlxsw_sp_afk_element_info_mac_4),
MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x1A, mlxsw_sp_afk_element_info_mac_5b),
MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x38, mlxsw_sp_afk_element_info_ipv4_0),
- MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x39, mlxsw_sp_afk_element_info_ipv4_1),
+ MLXSW_AFK_BLOCK_HIGH_ENTROPY(0x3F, mlxsw_sp_afk_element_info_ipv4_1b),
MLXSW_AFK_BLOCK(0x3A, mlxsw_sp_afk_element_info_ipv4_2),
MLXSW_AFK_BLOCK(0x36, mlxsw_sp_afk_element_info_ipv4_5b),
MLXSW_AFK_BLOCK(0x40, mlxsw_sp_afk_element_info_ipv6_0),
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
index f07955b5439f..6a4a81c63451 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
@@ -192,6 +192,11 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
return -EOPNOTSUPP;
}
+ if (sample_act_count) {
+ NL_SET_ERR_MSG_MOD(extack, "Mirror action after sample action is not supported");
+ return -EOPNOTSUPP;
+ }
+
err = mlxsw_sp_acl_rulei_act_mirror(mlxsw_sp, rulei,
block, out_dev,
extack);
@@ -265,6 +270,11 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
return -EOPNOTSUPP;
}
+ if (mirror_act_count) {
+ NL_SET_ERR_MSG_MOD(extack, "Sample action after mirror action is not supported");
+ return -EOPNOTSUPP;
+ }
+
err = mlxsw_sp_acl_rulei_act_sample(mlxsw_sp, rulei,
block,
act->sample.psample_group,
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
index 4b5fd71c897d..32d2e61f2b82 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_span.c
@@ -423,8 +423,7 @@ mlxsw_sp_span_gretap4_route(const struct net_device *to_dev,
parms = mlxsw_sp_ipip_netdev_parms4(to_dev);
ip_tunnel_init_flow(&fl4, parms.iph.protocol, *daddrp, *saddrp,
- 0, 0, dev_net(to_dev), parms.link, tun->fwmark, 0,
- 0);
+ 0, 0, tun->net, parms.link, tun->fwmark, 0, 0);
rt = ip_route_output_key(tun->net, &fl4);
if (IS_ERR(rt))
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
index 899c954e0e5f..1f9c1c86839f 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_trap.c
@@ -173,7 +173,7 @@ static void mlxsw_sp_rx_no_mark_listener(struct sk_buff *skb, u16 local_port,
if (err)
return;
- netif_receive_skb(skb);
+ napi_gro_receive(mlxsw_skb_cb(skb)->rx_md_info.napi, skb);
}
static void mlxsw_sp_rx_mark_listener(struct sk_buff *skb, u16 local_port,
diff --git a/drivers/net/ethernet/meta/fbnic/Makefile b/drivers/net/ethernet/meta/fbnic/Makefile
index 239b2258ec65..ea6214ca48e7 100644
--- a/drivers/net/ethernet/meta/fbnic/Makefile
+++ b/drivers/net/ethernet/meta/fbnic/Makefile
@@ -13,7 +13,6 @@ fbnic-y := fbnic_csr.o \
fbnic_ethtool.o \
fbnic_fw.o \
fbnic_hw_stats.o \
- fbnic_hwmon.o \
fbnic_irq.o \
fbnic_mac.o \
fbnic_netdev.o \
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic.h b/drivers/net/ethernet/meta/fbnic/fbnic.h
index 706ae6104c8e..50f97f5399ff 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic.h
@@ -16,11 +16,14 @@
#include "fbnic_mac.h"
#include "fbnic_rpc.h"
+struct fbnic_napi_vector;
+
+#define FBNIC_MAX_NAPI_VECTORS 128u
+
struct fbnic_dev {
struct device *dev;
struct net_device *netdev;
struct dentry *dbg_fbd;
- struct device *hwmon;
u32 __iomem *uc_addr0;
u32 __iomem *uc_addr4;
@@ -29,11 +32,15 @@ struct fbnic_dev {
unsigned int pcs_msix_vector;
unsigned short num_irqs;
+ struct {
+ u8 users;
+ char name[IFNAMSIZ + 9];
+ } napi_irq[FBNIC_MAX_NAPI_VECTORS];
+
struct delayed_work service_task;
struct fbnic_fw_mbx mbx[FBNIC_IPC_MBX_INDICES];
struct fbnic_fw_cap fw_cap;
- struct fbnic_fw_completion *cmpl_data;
/* Lock protecting Tx Mailbox queue to prevent possible races */
spinlock_t fw_tx_lock;
@@ -142,12 +149,15 @@ void fbnic_devlink_unregister(struct fbnic_dev *fbd);
int fbnic_fw_enable_mbx(struct fbnic_dev *fbd);
void fbnic_fw_disable_mbx(struct fbnic_dev *fbd);
-void fbnic_hwmon_register(struct fbnic_dev *fbd);
-void fbnic_hwmon_unregister(struct fbnic_dev *fbd);
-
int fbnic_pcs_irq_enable(struct fbnic_dev *fbd);
void fbnic_pcs_irq_disable(struct fbnic_dev *fbd);
+void fbnic_napi_name_irqs(struct fbnic_dev *fbd);
+int fbnic_napi_request_irq(struct fbnic_dev *fbd,
+ struct fbnic_napi_vector *nv);
+void fbnic_napi_free_irq(struct fbnic_dev *fbd,
+ struct fbnic_napi_vector *nv);
+void fbnic_synchronize_irq(struct fbnic_dev *fbd, int nr);
int fbnic_request_irq(struct fbnic_dev *dev, int nr, irq_handler_t handler,
unsigned long flags, const char *name, void *data);
void fbnic_free_irq(struct fbnic_dev *dev, int nr, void *data);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_csr.c b/drivers/net/ethernet/meta/fbnic/fbnic_csr.c
index 2118901b25e9..aeb9f333f4c7 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_csr.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_csr.c
@@ -64,7 +64,7 @@ static void fbnic_csr_get_regs_rpc_ram(struct fbnic_dev *fbd, u32 **data_p)
u32 i, j;
*(data++) = start;
- *(data++) = end - 1;
+ *(data++) = end;
/* FBNIC_RPC_TCAM_ACT */
for (i = 0; i < FBNIC_RPC_TCAM_ACT_NUM_ENTRIES; i++) {
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
index cc8ca94529ca..20cd9f5f89e2 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_ethtool.c
@@ -40,49 +40,99 @@ static const struct fbnic_stat fbnic_gstrings_hw_stats[] = {
#define FBNIC_HW_FIXED_STATS_LEN ARRAY_SIZE(fbnic_gstrings_hw_stats)
#define FBNIC_HW_STATS_LEN FBNIC_HW_FIXED_STATS_LEN
-static int
-fbnic_get_ts_info(struct net_device *netdev,
- struct kernel_ethtool_ts_info *tsinfo)
+static void
+fbnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
{
struct fbnic_net *fbn = netdev_priv(netdev);
+ struct fbnic_dev *fbd = fbn->fbd;
- tsinfo->phc_index = ptp_clock_index(fbn->fbd->ptp);
+ fbnic_get_fw_ver_commit_str(fbd, drvinfo->fw_version,
+ sizeof(drvinfo->fw_version));
+}
- tsinfo->so_timestamping =
- SOF_TIMESTAMPING_TX_SOFTWARE |
- SOF_TIMESTAMPING_TX_HARDWARE |
- SOF_TIMESTAMPING_RX_HARDWARE |
- SOF_TIMESTAMPING_RAW_HARDWARE;
+static int fbnic_get_regs_len(struct net_device *netdev)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
- tsinfo->tx_types =
- BIT(HWTSTAMP_TX_OFF) |
- BIT(HWTSTAMP_TX_ON);
+ return fbnic_csr_regs_len(fbn->fbd) * sizeof(u32);
+}
- tsinfo->rx_filters =
- BIT(HWTSTAMP_FILTER_NONE) |
- BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
- BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
- BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
- BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
- BIT(HWTSTAMP_FILTER_ALL);
+static void fbnic_get_regs(struct net_device *netdev,
+ struct ethtool_regs *regs, void *data)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
- return 0;
+ fbnic_csr_get_regs(fbn->fbd, data, &regs->version);
}
-static void
-fbnic_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
+static struct fbnic_net *fbnic_clone_create(struct fbnic_net *orig)
{
- struct fbnic_net *fbn = netdev_priv(netdev);
- struct fbnic_dev *fbd = fbn->fbd;
+ struct fbnic_net *clone;
- fbnic_get_fw_ver_commit_str(fbd, drvinfo->fw_version,
- sizeof(drvinfo->fw_version));
+ clone = kmemdup(orig, sizeof(*orig), GFP_KERNEL);
+ if (!clone)
+ return NULL;
+
+ memset(clone->tx, 0, sizeof(clone->tx));
+ memset(clone->rx, 0, sizeof(clone->rx));
+ memset(clone->napi, 0, sizeof(clone->napi));
+ return clone;
}
-static void fbnic_set_counter(u64 *stat, struct fbnic_stat_counter *counter)
+static void fbnic_clone_swap_cfg(struct fbnic_net *orig,
+ struct fbnic_net *clone)
{
- if (counter->reported)
- *stat = counter->value;
+ swap(clone->rcq_size, orig->rcq_size);
+ swap(clone->hpq_size, orig->hpq_size);
+ swap(clone->ppq_size, orig->ppq_size);
+ swap(clone->txq_size, orig->txq_size);
+ swap(clone->num_rx_queues, orig->num_rx_queues);
+ swap(clone->num_tx_queues, orig->num_tx_queues);
+ swap(clone->num_napi, orig->num_napi);
+}
+
+static void fbnic_aggregate_vector_counters(struct fbnic_net *fbn,
+ struct fbnic_napi_vector *nv)
+{
+ int i, j;
+
+ for (i = 0; i < nv->txt_count; i++) {
+ fbnic_aggregate_ring_tx_counters(fbn, &nv->qt[i].sub0);
+ fbnic_aggregate_ring_tx_counters(fbn, &nv->qt[i].sub1);
+ fbnic_aggregate_ring_tx_counters(fbn, &nv->qt[i].cmpl);
+ }
+
+ for (j = 0; j < nv->rxt_count; j++, i++) {
+ fbnic_aggregate_ring_rx_counters(fbn, &nv->qt[i].sub0);
+ fbnic_aggregate_ring_rx_counters(fbn, &nv->qt[i].sub1);
+ fbnic_aggregate_ring_rx_counters(fbn, &nv->qt[i].cmpl);
+ }
+}
+
+static void fbnic_clone_swap(struct fbnic_net *orig,
+ struct fbnic_net *clone)
+{
+ struct fbnic_dev *fbd = orig->fbd;
+ unsigned int i;
+
+ for (i = 0; i < max(clone->num_napi, orig->num_napi); i++)
+ fbnic_synchronize_irq(fbd, FBNIC_NON_NAPI_VECTORS + i);
+ for (i = 0; i < orig->num_napi; i++)
+ fbnic_aggregate_vector_counters(orig, orig->napi[i]);
+
+ fbnic_clone_swap_cfg(orig, clone);
+
+ for (i = 0; i < ARRAY_SIZE(orig->napi); i++)
+ swap(clone->napi[i], orig->napi[i]);
+ for (i = 0; i < ARRAY_SIZE(orig->tx); i++)
+ swap(clone->tx[i], orig->tx[i]);
+ for (i = 0; i < ARRAY_SIZE(orig->rx); i++)
+ swap(clone->rx[i], orig->rx[i]);
+}
+
+static void fbnic_clone_free(struct fbnic_net *clone)
+{
+ kfree(clone);
}
static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data)
@@ -97,6 +147,21 @@ static void fbnic_get_strings(struct net_device *dev, u32 sset, u8 *data)
}
}
+static void fbnic_get_ethtool_stats(struct net_device *dev,
+ struct ethtool_stats *stats, u64 *data)
+{
+ struct fbnic_net *fbn = netdev_priv(dev);
+ const struct fbnic_stat *stat;
+ int i;
+
+ fbnic_get_hw_stats(fbn->fbd);
+
+ for (i = 0; i < FBNIC_HW_STATS_LEN; i++) {
+ stat = &fbnic_gstrings_hw_stats[i];
+ data[i] = *(u64 *)((u8 *)&fbn->fbd->hw_stats + stat->offset);
+ }
+}
+
static int fbnic_get_sset_count(struct net_device *dev, int sset)
{
switch (sset) {
@@ -107,19 +172,375 @@ static int fbnic_get_sset_count(struct net_device *dev, int sset)
}
}
-static void fbnic_get_ethtool_stats(struct net_device *dev,
- struct ethtool_stats *stats, u64 *data)
+static int fbnic_get_rss_hash_idx(u32 flow_type)
{
- struct fbnic_net *fbn = netdev_priv(dev);
- const struct fbnic_stat *stat;
- int i;
+ switch (flow_type & ~(FLOW_EXT | FLOW_MAC_EXT | FLOW_RSS)) {
+ case TCP_V4_FLOW:
+ return FBNIC_TCP4_HASH_OPT;
+ case TCP_V6_FLOW:
+ return FBNIC_TCP6_HASH_OPT;
+ case UDP_V4_FLOW:
+ return FBNIC_UDP4_HASH_OPT;
+ case UDP_V6_FLOW:
+ return FBNIC_UDP6_HASH_OPT;
+ case AH_V4_FLOW:
+ case ESP_V4_FLOW:
+ case AH_ESP_V4_FLOW:
+ case SCTP_V4_FLOW:
+ case IPV4_FLOW:
+ case IPV4_USER_FLOW:
+ return FBNIC_IPV4_HASH_OPT;
+ case AH_V6_FLOW:
+ case ESP_V6_FLOW:
+ case AH_ESP_V6_FLOW:
+ case SCTP_V6_FLOW:
+ case IPV6_FLOW:
+ case IPV6_USER_FLOW:
+ return FBNIC_IPV6_HASH_OPT;
+ case ETHER_FLOW:
+ return FBNIC_ETHER_HASH_OPT;
+ }
- fbnic_get_hw_stats(fbn->fbd);
+ return -1;
+}
- for (i = 0; i < FBNIC_HW_STATS_LEN; i++) {
- stat = &fbnic_gstrings_hw_stats[i];
- data[i] = *(u64 *)((u8 *)&fbn->fbd->hw_stats + stat->offset);
+static int
+fbnic_get_rss_hash_opts(struct fbnic_net *fbn, struct ethtool_rxnfc *cmd)
+{
+ int hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type);
+
+ if (hash_opt_idx < 0)
+ return -EINVAL;
+
+ /* Report options from rss_en table in fbn */
+ cmd->data = fbn->rss_flow_hash[hash_opt_idx];
+
+ return 0;
+}
+
+static int fbnic_get_rxnfc(struct net_device *netdev,
+ struct ethtool_rxnfc *cmd, u32 *rule_locs)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_GRXRINGS:
+ cmd->data = fbn->num_rx_queues;
+ ret = 0;
+ break;
+ case ETHTOOL_GRXFH:
+ ret = fbnic_get_rss_hash_opts(fbn, cmd);
+ break;
+ }
+
+ return ret;
+}
+
+#define FBNIC_L2_HASH_OPTIONS \
+ (RXH_L2DA | RXH_DISCARD)
+#define FBNIC_L3_HASH_OPTIONS \
+ (FBNIC_L2_HASH_OPTIONS | RXH_IP_SRC | RXH_IP_DST)
+#define FBNIC_L4_HASH_OPTIONS \
+ (FBNIC_L3_HASH_OPTIONS | RXH_L4_B_0_1 | RXH_L4_B_2_3)
+
+static int
+fbnic_set_rss_hash_opts(struct fbnic_net *fbn, const struct ethtool_rxnfc *cmd)
+{
+ int hash_opt_idx;
+
+ /* Verify the type requested is correct */
+ hash_opt_idx = fbnic_get_rss_hash_idx(cmd->flow_type);
+ if (hash_opt_idx < 0)
+ return -EINVAL;
+
+ /* Verify the fields asked for can actually be assigned based on type */
+ if (cmd->data & ~FBNIC_L4_HASH_OPTIONS ||
+ (hash_opt_idx > FBNIC_L4_HASH_OPT &&
+ cmd->data & ~FBNIC_L3_HASH_OPTIONS) ||
+ (hash_opt_idx > FBNIC_IP_HASH_OPT &&
+ cmd->data & ~FBNIC_L2_HASH_OPTIONS))
+ return -EINVAL;
+
+ fbn->rss_flow_hash[hash_opt_idx] = cmd->data;
+
+ if (netif_running(fbn->netdev)) {
+ fbnic_rss_reinit(fbn->fbd, fbn);
+ fbnic_write_rules(fbn->fbd);
+ }
+
+ return 0;
+}
+
+static int fbnic_set_rxnfc(struct net_device *netdev, struct ethtool_rxnfc *cmd)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+ int ret = -EOPNOTSUPP;
+
+ switch (cmd->cmd) {
+ case ETHTOOL_SRXFH:
+ ret = fbnic_set_rss_hash_opts(fbn, cmd);
+ break;
+ }
+
+ return ret;
+}
+
+static u32 fbnic_get_rxfh_key_size(struct net_device *netdev)
+{
+ return FBNIC_RPC_RSS_KEY_BYTE_LEN;
+}
+
+static u32 fbnic_get_rxfh_indir_size(struct net_device *netdev)
+{
+ return FBNIC_RPC_RSS_TBL_SIZE;
+}
+
+static int
+fbnic_get_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+ unsigned int i;
+
+ rxfh->hfunc = ETH_RSS_HASH_TOP;
+
+ if (rxfh->key) {
+ for (i = 0; i < FBNIC_RPC_RSS_KEY_BYTE_LEN; i++) {
+ u32 rss_key = fbn->rss_key[i / 4] << ((i % 4) * 8);
+
+ rxfh->key[i] = rss_key >> 24;
+ }
+ }
+
+ if (rxfh->indir) {
+ for (i = 0; i < FBNIC_RPC_RSS_TBL_SIZE; i++)
+ rxfh->indir[i] = fbn->indir_tbl[0][i];
+ }
+
+ return 0;
+}
+
+static unsigned int
+fbnic_set_indir(struct fbnic_net *fbn, unsigned int idx, const u32 *indir)
+{
+ unsigned int i, changes = 0;
+
+ for (i = 0; i < FBNIC_RPC_RSS_TBL_SIZE; i++) {
+ if (fbn->indir_tbl[idx][i] == indir[i])
+ continue;
+
+ fbn->indir_tbl[idx][i] = indir[i];
+ changes++;
+ }
+
+ return changes;
+}
+
+static int
+fbnic_set_rxfh(struct net_device *netdev, struct ethtool_rxfh_param *rxfh,
+ struct netlink_ext_ack *extack)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+ unsigned int i, changes = 0;
+
+ if (rxfh->hfunc != ETH_RSS_HASH_NO_CHANGE &&
+ rxfh->hfunc != ETH_RSS_HASH_TOP)
+ return -EINVAL;
+
+ if (rxfh->key) {
+ u32 rss_key = 0;
+
+ for (i = FBNIC_RPC_RSS_KEY_BYTE_LEN; i--;) {
+ rss_key >>= 8;
+ rss_key |= (u32)(rxfh->key[i]) << 24;
+
+ if (i % 4)
+ continue;
+
+ if (fbn->rss_key[i / 4] == rss_key)
+ continue;
+
+ fbn->rss_key[i / 4] = rss_key;
+ changes++;
+ }
}
+
+ if (rxfh->indir)
+ changes += fbnic_set_indir(fbn, 0, rxfh->indir);
+
+ if (changes && netif_running(netdev))
+ fbnic_rss_reinit_hw(fbn->fbd, fbn);
+
+ return 0;
+}
+
+static void fbnic_get_channels(struct net_device *netdev,
+ struct ethtool_channels *ch)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+ struct fbnic_dev *fbd = fbn->fbd;
+
+ ch->max_rx = fbd->max_num_queues;
+ ch->max_tx = fbd->max_num_queues;
+ ch->max_combined = min(ch->max_rx, ch->max_tx);
+ ch->max_other = FBNIC_NON_NAPI_VECTORS;
+
+ if (fbn->num_rx_queues > fbn->num_napi ||
+ fbn->num_tx_queues > fbn->num_napi)
+ ch->combined_count = min(fbn->num_rx_queues,
+ fbn->num_tx_queues);
+ else
+ ch->combined_count =
+ fbn->num_rx_queues + fbn->num_tx_queues - fbn->num_napi;
+ ch->rx_count = fbn->num_rx_queues - ch->combined_count;
+ ch->tx_count = fbn->num_tx_queues - ch->combined_count;
+ ch->other_count = FBNIC_NON_NAPI_VECTORS;
+}
+
+static void fbnic_set_queues(struct fbnic_net *fbn, struct ethtool_channels *ch,
+ unsigned int max_napis)
+{
+ fbn->num_rx_queues = ch->rx_count + ch->combined_count;
+ fbn->num_tx_queues = ch->tx_count + ch->combined_count;
+ fbn->num_napi = min(ch->rx_count + ch->tx_count + ch->combined_count,
+ max_napis);
+}
+
+static int fbnic_set_channels(struct net_device *netdev,
+ struct ethtool_channels *ch)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+ unsigned int max_napis, standalone;
+ struct fbnic_dev *fbd = fbn->fbd;
+ struct fbnic_net *clone;
+ int err;
+
+ max_napis = fbd->num_irqs - FBNIC_NON_NAPI_VECTORS;
+ standalone = ch->rx_count + ch->tx_count;
+
+ /* Limits for standalone queues:
+ * - each queue has it's own NAPI (num_napi >= rx + tx + combined)
+ * - combining queues (combined not 0, rx or tx must be 0)
+ */
+ if ((ch->rx_count && ch->tx_count && ch->combined_count) ||
+ (standalone && standalone + ch->combined_count > max_napis) ||
+ ch->rx_count + ch->combined_count > fbd->max_num_queues ||
+ ch->tx_count + ch->combined_count > fbd->max_num_queues ||
+ ch->other_count != FBNIC_NON_NAPI_VECTORS)
+ return -EINVAL;
+
+ if (!netif_running(netdev)) {
+ fbnic_set_queues(fbn, ch, max_napis);
+ fbnic_reset_indir_tbl(fbn);
+ return 0;
+ }
+
+ clone = fbnic_clone_create(fbn);
+ if (!clone)
+ return -ENOMEM;
+
+ fbnic_set_queues(clone, ch, max_napis);
+
+ err = fbnic_alloc_napi_vectors(clone);
+ if (err)
+ goto err_free_clone;
+
+ err = fbnic_alloc_resources(clone);
+ if (err)
+ goto err_free_napis;
+
+ fbnic_down_noidle(fbn);
+ err = fbnic_wait_all_queues_idle(fbn->fbd, true);
+ if (err)
+ goto err_start_stack;
+
+ err = fbnic_set_netif_queues(clone);
+ if (err)
+ goto err_start_stack;
+
+ /* Nothing can fail past this point */
+ fbnic_flush(fbn);
+
+ fbnic_clone_swap(fbn, clone);
+
+ /* Reset RSS indirection table */
+ fbnic_reset_indir_tbl(fbn);
+
+ fbnic_up(fbn);
+
+ fbnic_free_resources(clone);
+ fbnic_free_napi_vectors(clone);
+ fbnic_clone_free(clone);
+
+ return 0;
+
+err_start_stack:
+ fbnic_flush(fbn);
+ fbnic_up(fbn);
+ fbnic_free_resources(clone);
+err_free_napis:
+ fbnic_free_napi_vectors(clone);
+err_free_clone:
+ fbnic_clone_free(clone);
+ return err;
+}
+
+static int
+fbnic_get_ts_info(struct net_device *netdev,
+ struct kernel_ethtool_ts_info *tsinfo)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+
+ tsinfo->phc_index = ptp_clock_index(fbn->fbd->ptp);
+
+ tsinfo->so_timestamping =
+ SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ tsinfo->tx_types =
+ BIT(HWTSTAMP_TX_OFF) |
+ BIT(HWTSTAMP_TX_ON);
+
+ tsinfo->rx_filters =
+ BIT(HWTSTAMP_FILTER_NONE) |
+ BIT(HWTSTAMP_FILTER_PTP_V1_L4_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_EVENT) |
+ BIT(HWTSTAMP_FILTER_ALL);
+
+ return 0;
+}
+
+static void fbnic_get_ts_stats(struct net_device *netdev,
+ struct ethtool_ts_stats *ts_stats)
+{
+ struct fbnic_net *fbn = netdev_priv(netdev);
+ u64 ts_packets, ts_lost;
+ struct fbnic_ring *ring;
+ unsigned int start;
+ int i;
+
+ ts_stats->pkts = fbn->tx_stats.ts_packets;
+ ts_stats->lost = fbn->tx_stats.ts_lost;
+ for (i = 0; i < fbn->num_tx_queues; i++) {
+ ring = fbn->tx[i];
+ do {
+ start = u64_stats_fetch_begin(&ring->stats.syncp);
+ ts_packets = ring->stats.ts_packets;
+ ts_lost = ring->stats.ts_lost;
+ } while (u64_stats_fetch_retry(&ring->stats.syncp, start));
+ ts_stats->pkts += ts_packets;
+ ts_stats->lost += ts_lost;
+ }
+}
+
+static void fbnic_set_counter(u64 *stat, struct fbnic_stat_counter *counter)
+{
+ if (counter->reported)
+ *stat = counter->value;
}
static void
@@ -164,44 +585,6 @@ fbnic_get_eth_mac_stats(struct net_device *netdev,
&mac_stats->eth_mac.FrameTooLongErrors);
}
-static void fbnic_get_ts_stats(struct net_device *netdev,
- struct ethtool_ts_stats *ts_stats)
-{
- struct fbnic_net *fbn = netdev_priv(netdev);
- u64 ts_packets, ts_lost;
- struct fbnic_ring *ring;
- unsigned int start;
- int i;
-
- ts_stats->pkts = fbn->tx_stats.ts_packets;
- ts_stats->lost = fbn->tx_stats.ts_lost;
- for (i = 0; i < fbn->num_tx_queues; i++) {
- ring = fbn->tx[i];
- do {
- start = u64_stats_fetch_begin(&ring->stats.syncp);
- ts_packets = ring->stats.ts_packets;
- ts_lost = ring->stats.ts_lost;
- } while (u64_stats_fetch_retry(&ring->stats.syncp, start));
- ts_stats->pkts += ts_packets;
- ts_stats->lost += ts_lost;
- }
-}
-
-static void fbnic_get_regs(struct net_device *netdev,
- struct ethtool_regs *regs, void *data)
-{
- struct fbnic_net *fbn = netdev_priv(netdev);
-
- fbnic_csr_get_regs(fbn->fbd, data, &regs->version);
-}
-
-static int fbnic_get_regs_len(struct net_device *netdev)
-{
- struct fbnic_net *fbn = netdev_priv(netdev);
-
- return fbnic_csr_regs_len(fbn->fbd) * sizeof(u32);
-}
-
static const struct ethtool_ops fbnic_ethtool_ops = {
.get_drvinfo = fbnic_get_drvinfo,
.get_regs_len = fbnic_get_regs_len,
@@ -209,6 +592,14 @@ static const struct ethtool_ops fbnic_ethtool_ops = {
.get_strings = fbnic_get_strings,
.get_ethtool_stats = fbnic_get_ethtool_stats,
.get_sset_count = fbnic_get_sset_count,
+ .get_rxnfc = fbnic_get_rxnfc,
+ .set_rxnfc = fbnic_set_rxnfc,
+ .get_rxfh_key_size = fbnic_get_rxfh_key_size,
+ .get_rxfh_indir_size = fbnic_get_rxfh_indir_size,
+ .get_rxfh = fbnic_get_rxfh,
+ .set_rxfh = fbnic_set_rxfh,
+ .get_channels = fbnic_get_channels,
+ .set_channels = fbnic_set_channels,
.get_ts_info = fbnic_get_ts_info,
.get_ts_stats = fbnic_get_ts_stats,
.get_eth_mac_stats = fbnic_get_eth_mac_stats,
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
index 7cd8841920e4..221faf8c6756 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_fw.h
@@ -44,13 +44,6 @@ struct fbnic_fw_cap {
u8 link_fec;
};
-struct fbnic_fw_completion {
- struct {
- s32 millivolts;
- s32 millidegrees;
- } tsene;
-};
-
void fbnic_mbx_init(struct fbnic_dev *fbd);
void fbnic_mbx_clean(struct fbnic_dev *fbd);
void fbnic_mbx_poll(struct fbnic_dev *fbd);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c b/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
deleted file mode 100644
index bcd1086e3768..000000000000
--- a/drivers/net/ethernet/meta/fbnic/fbnic_hwmon.c
+++ /dev/null
@@ -1,81 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) Meta Platforms, Inc. and affiliates. */
-
-#include <linux/hwmon.h>
-
-#include "fbnic.h"
-#include "fbnic_mac.h"
-
-static int fbnic_hwmon_sensor_id(enum hwmon_sensor_types type)
-{
- if (type == hwmon_temp)
- return FBNIC_SENSOR_TEMP;
- if (type == hwmon_in)
- return FBNIC_SENSOR_VOLTAGE;
-
- return -EOPNOTSUPP;
-}
-
-static umode_t fbnic_hwmon_is_visible(const void *drvdata,
- enum hwmon_sensor_types type,
- u32 attr, int channel)
-{
- if (type == hwmon_temp && attr == hwmon_temp_input)
- return 0444;
- if (type == hwmon_in && attr == hwmon_in_input)
- return 0444;
-
- return 0;
-}
-
-static int fbnic_hwmon_read(struct device *dev, enum hwmon_sensor_types type,
- u32 attr, int channel, long *val)
-{
- struct fbnic_dev *fbd = dev_get_drvdata(dev);
- const struct fbnic_mac *mac = fbd->mac;
- int id;
-
- id = fbnic_hwmon_sensor_id(type);
- return id < 0 ? id : mac->get_sensor(fbd, id, val);
-}
-
-static const struct hwmon_ops fbnic_hwmon_ops = {
- .is_visible = fbnic_hwmon_is_visible,
- .read = fbnic_hwmon_read,
-};
-
-static const struct hwmon_channel_info *fbnic_hwmon_info[] = {
- HWMON_CHANNEL_INFO(temp, HWMON_T_INPUT),
- HWMON_CHANNEL_INFO(in, HWMON_I_INPUT),
- NULL
-};
-
-static const struct hwmon_chip_info fbnic_chip_info = {
- .ops = &fbnic_hwmon_ops,
- .info = fbnic_hwmon_info,
-};
-
-void fbnic_hwmon_register(struct fbnic_dev *fbd)
-{
- if (!IS_REACHABLE(CONFIG_HWMON))
- return;
-
- fbd->hwmon = hwmon_device_register_with_info(fbd->dev, "fbnic",
- fbd, &fbnic_chip_info,
- NULL);
- if (IS_ERR(fbd->hwmon)) {
- dev_notice(fbd->dev,
- "Failed to register hwmon device %pe\n",
- fbd->hwmon);
- fbd->hwmon = NULL;
- }
-}
-
-void fbnic_hwmon_unregister(struct fbnic_dev *fbd)
-{
- if (!IS_REACHABLE(CONFIG_HWMON) || !fbd->hwmon)
- return;
-
- hwmon_device_unregister(fbd->hwmon);
- fbd->hwmon = NULL;
-}
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_irq.c b/drivers/net/ethernet/meta/fbnic/fbnic_irq.c
index 914362195920..1bbc0e56f3a0 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_irq.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_irq.c
@@ -146,6 +146,17 @@ void fbnic_pcs_irq_disable(struct fbnic_dev *fbd)
free_irq(fbd->pcs_msix_vector, fbd);
}
+void fbnic_synchronize_irq(struct fbnic_dev *fbd, int nr)
+{
+ struct pci_dev *pdev = to_pci_dev(fbd->dev);
+ int irq = pci_irq_vector(pdev, nr);
+
+ if (irq < 0)
+ return;
+
+ synchronize_irq(irq);
+}
+
int fbnic_request_irq(struct fbnic_dev *fbd, int nr, irq_handler_t handler,
unsigned long flags, const char *name, void *data)
{
@@ -169,6 +180,48 @@ void fbnic_free_irq(struct fbnic_dev *fbd, int nr, void *data)
free_irq(irq, data);
}
+void fbnic_napi_name_irqs(struct fbnic_dev *fbd)
+{
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(fbd->napi_irq); i++)
+ snprintf(fbd->napi_irq[i].name,
+ sizeof(fbd->napi_irq[i].name),
+ "%s-TxRx-%u", fbd->netdev->name, i);
+}
+
+int fbnic_napi_request_irq(struct fbnic_dev *fbd,
+ struct fbnic_napi_vector *nv)
+{
+ struct fbnic_net *fbn = netdev_priv(fbd->netdev);
+ int i = fbnic_napi_idx(nv);
+ int err;
+
+ if (!fbd->napi_irq[i].users) {
+ err = fbnic_request_irq(fbd, nv->v_idx,
+ fbnic_msix_clean_rings, 0,
+ fbd->napi_irq[i].name,
+ &fbn->napi[i]);
+ if (err)
+ return err;
+ }
+
+ fbd->napi_irq[i].users++;
+ return 0;
+}
+
+void fbnic_napi_free_irq(struct fbnic_dev *fbd,
+ struct fbnic_napi_vector *nv)
+{
+ struct fbnic_net *fbn = netdev_priv(fbd->netdev);
+ int i = fbnic_napi_idx(nv);
+
+ if (--fbd->napi_irq[i].users)
+ return;
+
+ fbnic_free_irq(fbd, nv->v_idx, &fbn->napi[i]);
+}
+
void fbnic_free_irqs(struct fbnic_dev *fbd)
{
struct pci_dev *pdev = to_pci_dev(fbd->dev);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
index 80b82ff12c4d..7b654d0a6dac 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.c
@@ -686,27 +686,6 @@ fbnic_mac_get_eth_mac_stats(struct fbnic_dev *fbd, bool reset,
MAC_STAT_TX_BROADCAST);
}
-static int fbnic_mac_get_sensor_asic(struct fbnic_dev *fbd, int id, long *val)
-{
- struct fbnic_fw_completion fw_cmpl;
- s32 *sensor;
-
- switch (id) {
- case FBNIC_SENSOR_TEMP:
- sensor = &fw_cmpl.tsene.millidegrees;
- break;
- case FBNIC_SENSOR_VOLTAGE:
- sensor = &fw_cmpl.tsene.millivolts;
- break;
- default:
- return -EINVAL;
- }
-
- *val = *sensor;
-
- return 0;
-}
-
static const struct fbnic_mac fbnic_mac_asic = {
.init_regs = fbnic_mac_init_regs,
.pcs_enable = fbnic_pcs_enable_asic,
@@ -716,7 +695,6 @@ static const struct fbnic_mac fbnic_mac_asic = {
.get_eth_mac_stats = fbnic_mac_get_eth_mac_stats,
.link_down = fbnic_mac_link_down_asic,
.link_up = fbnic_mac_link_up_asic,
- .get_sensor = fbnic_mac_get_sensor_asic,
};
/**
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_mac.h b/drivers/net/ethernet/meta/fbnic/fbnic_mac.h
index 05a591653e09..476239a9d381 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_mac.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_mac.h
@@ -47,11 +47,6 @@ enum {
#define FBNIC_LINK_MODE_PAM4 (FBNIC_LINK_50R1)
#define FBNIC_LINK_MODE_MASK (FBNIC_LINK_AUTO - 1)
-enum fbnic_sensor_id {
- FBNIC_SENSOR_TEMP, /* Temp in millidegrees Centigrade */
- FBNIC_SENSOR_VOLTAGE, /* Voltage in millivolts */
-};
-
/* This structure defines the interface hooks for the MAC. The MAC hooks
* will be configured as a const struct provided with a set of function
* pointers.
@@ -88,8 +83,6 @@ struct fbnic_mac {
void (*link_down)(struct fbnic_dev *fbd);
void (*link_up)(struct fbnic_dev *fbd, bool tx_pause, bool rx_pause);
-
- int (*get_sensor)(struct fbnic_dev *fbd, int id, long *val);
};
int fbnic_mac_init(struct fbnic_dev *fbd);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
index fc7d80db5fa6..7a96b6ee773f 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.c
@@ -23,13 +23,7 @@ int __fbnic_open(struct fbnic_net *fbn)
if (err)
goto free_napi_vectors;
- err = netif_set_real_num_tx_queues(fbn->netdev,
- fbn->num_tx_queues);
- if (err)
- goto free_resources;
-
- err = netif_set_real_num_rx_queues(fbn->netdev,
- fbn->num_rx_queues);
+ err = fbnic_set_netif_queues(fbn);
if (err)
goto free_resources;
@@ -74,6 +68,8 @@ static int fbnic_open(struct net_device *netdev)
struct fbnic_net *fbn = netdev_priv(netdev);
int err;
+ fbnic_napi_name_irqs(fbn->fbd);
+
err = __fbnic_open(fbn);
if (!err)
fbnic_up(fbn);
@@ -91,6 +87,7 @@ static int fbnic_stop(struct net_device *netdev)
fbnic_time_stop(fbn);
fbnic_fw_xmit_ownership_msg(fbn->fbd, false);
+ fbnic_reset_netif_queues(fbn);
fbnic_free_resources(fbn);
fbnic_free_napi_vectors(fbn);
@@ -615,7 +612,6 @@ struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd)
fbn->netdev = netdev;
fbn->fbd = fbd;
- INIT_LIST_HEAD(&fbn->napis);
fbn->txq_size = FBNIC_TXQ_SIZE_DEFAULT;
fbn->hpq_size = FBNIC_HPQ_SIZE_DEFAULT;
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
index b8417b300778..a392ac1cc4f2 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_netdev.h
@@ -11,10 +11,14 @@
#include "fbnic_rpc.h"
#include "fbnic_txrx.h"
+#define FBNIC_MAX_NAPI_VECTORS 128u
+
struct fbnic_net {
struct fbnic_ring *tx[FBNIC_MAX_TXQS];
struct fbnic_ring *rx[FBNIC_MAX_RXQS];
+ struct fbnic_napi_vector *napi[FBNIC_MAX_NAPI_VECTORS];
+
struct net_device *netdev;
struct fbnic_dev *fbd;
@@ -56,13 +60,12 @@ struct fbnic_net {
/* Time stampinn filter config */
struct kernel_hwtstamp_config hwtstamp_config;
-
- struct list_head napis;
};
int __fbnic_open(struct fbnic_net *fbn);
void fbnic_up(struct fbnic_net *fbn);
void fbnic_down(struct fbnic_net *fbn);
+void fbnic_down_noidle(struct fbnic_net *fbn);
struct net_device *fbnic_netdev_alloc(struct fbnic_dev *fbd);
void fbnic_netdev_free(struct fbnic_dev *fbd);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
index 32702dc4a066..2c96980d150d 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_pci.c
@@ -145,7 +145,7 @@ void fbnic_up(struct fbnic_net *fbn)
fbnic_service_task_start(fbn);
}
-static void fbnic_down_noidle(struct fbnic_net *fbn)
+void fbnic_down_noidle(struct fbnic_net *fbn)
{
fbnic_service_task_stop(fbn);
@@ -296,8 +296,6 @@ static int fbnic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
/* Capture snapshot of hardware stats so netdev can calculate delta */
fbnic_reset_hw_stats(fbd);
- fbnic_hwmon_register(fbd);
-
if (!fbd->dsn) {
dev_warn(&pdev->dev, "Reading serial number failed\n");
goto init_failure_mode;
@@ -360,7 +358,6 @@ static void fbnic_remove(struct pci_dev *pdev)
fbnic_netdev_free(fbd);
}
- fbnic_hwmon_unregister(fbd);
fbnic_dbg_fbd_exit(fbd);
fbnic_devlink_unregister(fbd);
fbnic_fw_disable_mbx(fbd);
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c
index 908c098cd59e..c25bd300b902 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_rpc.c
@@ -13,10 +13,11 @@ void fbnic_reset_indir_tbl(struct fbnic_net *fbn)
unsigned int num_rx = fbn->num_rx_queues;
unsigned int i;
- for (i = 0; i < FBNIC_RPC_RSS_TBL_SIZE; i++) {
+ if (netif_is_rxfh_configured(fbn->netdev))
+ return;
+
+ for (i = 0; i < FBNIC_RPC_RSS_TBL_SIZE; i++)
fbn->indir_tbl[0][i] = ethtool_rxfh_indir_default(i, num_rx);
- fbn->indir_tbl[1][i] = ethtool_rxfh_indir_default(i, num_rx);
- }
}
void fbnic_rss_key_fill(u32 *buffer)
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
index b5050fabe8fe..d4d7027df9a0 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.c
@@ -1033,20 +1033,20 @@ static int fbnic_poll(struct napi_struct *napi, int budget)
if (likely(napi_complete_done(napi, work_done)))
fbnic_nv_irq_rearm(nv);
- return 0;
+ return work_done;
}
-static irqreturn_t fbnic_msix_clean_rings(int __always_unused irq, void *data)
+irqreturn_t fbnic_msix_clean_rings(int __always_unused irq, void *data)
{
- struct fbnic_napi_vector *nv = data;
+ struct fbnic_napi_vector *nv = *(void **)data;
napi_schedule_irqoff(&nv->napi);
return IRQ_HANDLED;
}
-static void fbnic_aggregate_ring_rx_counters(struct fbnic_net *fbn,
- struct fbnic_ring *rxr)
+void fbnic_aggregate_ring_rx_counters(struct fbnic_net *fbn,
+ struct fbnic_ring *rxr)
{
struct fbnic_queue_stats *stats = &rxr->stats;
@@ -1056,8 +1056,8 @@ static void fbnic_aggregate_ring_rx_counters(struct fbnic_net *fbn,
fbn->rx_stats.dropped += stats->dropped;
}
-static void fbnic_aggregate_ring_tx_counters(struct fbnic_net *fbn,
- struct fbnic_ring *txr)
+void fbnic_aggregate_ring_tx_counters(struct fbnic_net *fbn,
+ struct fbnic_ring *txr)
{
struct fbnic_queue_stats *stats = &txr->stats;
@@ -1099,7 +1099,6 @@ static void fbnic_free_napi_vector(struct fbnic_net *fbn,
struct fbnic_napi_vector *nv)
{
struct fbnic_dev *fbd = nv->fbd;
- u32 v_idx = nv->v_idx;
int i, j;
for (i = 0; i < nv->txt_count; i++) {
@@ -1113,31 +1112,20 @@ static void fbnic_free_napi_vector(struct fbnic_net *fbn,
fbnic_remove_rx_ring(fbn, &nv->qt[i].cmpl);
}
- fbnic_free_irq(fbd, v_idx, nv);
+ fbnic_napi_free_irq(fbd, nv);
page_pool_destroy(nv->page_pool);
netif_napi_del(&nv->napi);
- list_del(&nv->napis);
+ fbn->napi[fbnic_napi_idx(nv)] = NULL;
kfree(nv);
}
void fbnic_free_napi_vectors(struct fbnic_net *fbn)
{
- struct fbnic_napi_vector *nv, *temp;
-
- list_for_each_entry_safe(nv, temp, &fbn->napis, napis)
- fbnic_free_napi_vector(fbn, nv);
-}
-
-static void fbnic_name_napi_vector(struct fbnic_napi_vector *nv)
-{
- unsigned char *dev_name = nv->napi.dev->name;
+ int i;
- if (!nv->rxt_count)
- snprintf(nv->name, sizeof(nv->name), "%s-Tx-%u", dev_name,
- nv->v_idx - FBNIC_NON_NAPI_VECTORS);
- else
- snprintf(nv->name, sizeof(nv->name), "%s-TxRx-%u", dev_name,
- nv->v_idx - FBNIC_NON_NAPI_VECTORS);
+ for (i = 0; i < fbn->num_napi; i++)
+ if (fbn->napi[i])
+ fbnic_free_napi_vector(fbn, fbn->napi[i]);
}
#define FBNIC_PAGE_POOL_FLAGS \
@@ -1222,7 +1210,7 @@ static int fbnic_alloc_napi_vector(struct fbnic_dev *fbd, struct fbnic_net *fbn,
nv->v_idx = v_idx;
/* Tie napi to netdev */
- list_add(&nv->napis, &fbn->napis);
+ fbn->napi[fbnic_napi_idx(nv)] = nv;
netif_napi_add(fbn->netdev, &nv->napi, fbnic_poll);
/* Record IRQ to NAPI struct */
@@ -1239,12 +1227,8 @@ static int fbnic_alloc_napi_vector(struct fbnic_dev *fbd, struct fbnic_net *fbn,
goto napi_del;
}
- /* Initialize vector name */
- fbnic_name_napi_vector(nv);
-
/* Request the IRQ for napi vector */
- err = fbnic_request_irq(fbd, v_idx, &fbnic_msix_clean_rings,
- IRQF_SHARED, nv->name, nv);
+ err = fbnic_napi_request_irq(fbd, nv);
if (err)
goto pp_destroy;
@@ -1307,7 +1291,7 @@ pp_destroy:
page_pool_destroy(nv->page_pool);
napi_del:
netif_napi_del(&nv->napi);
- list_del(&nv->napis);
+ fbn->napi[fbnic_napi_idx(nv)] = NULL;
kfree(nv);
return err;
}
@@ -1612,19 +1596,18 @@ free_resources:
void fbnic_free_resources(struct fbnic_net *fbn)
{
- struct fbnic_napi_vector *nv;
+ int i;
- list_for_each_entry(nv, &fbn->napis, napis)
- fbnic_free_nv_resources(fbn, nv);
+ for (i = 0; i < fbn->num_napi; i++)
+ fbnic_free_nv_resources(fbn, fbn->napi[i]);
}
int fbnic_alloc_resources(struct fbnic_net *fbn)
{
- struct fbnic_napi_vector *nv;
- int err = -ENODEV;
+ int i, err = -ENODEV;
- list_for_each_entry(nv, &fbn->napis, napis) {
- err = fbnic_alloc_nv_resources(fbn, nv);
+ for (i = 0; i < fbn->num_napi; i++) {
+ err = fbnic_alloc_nv_resources(fbn, fbn->napi[i]);
if (err)
goto free_resources;
}
@@ -1632,12 +1615,77 @@ int fbnic_alloc_resources(struct fbnic_net *fbn)
return 0;
free_resources:
- list_for_each_entry_continue_reverse(nv, &fbn->napis, napis)
- fbnic_free_nv_resources(fbn, nv);
+ while (i--)
+ fbnic_free_nv_resources(fbn, fbn->napi[i]);
return err;
}
+static void fbnic_set_netif_napi(struct fbnic_napi_vector *nv)
+{
+ int i, j;
+
+ /* Associate Tx queue with NAPI */
+ for (i = 0; i < nv->txt_count; i++) {
+ struct fbnic_q_triad *qt = &nv->qt[i];
+
+ netif_queue_set_napi(nv->napi.dev, qt->sub0.q_idx,
+ NETDEV_QUEUE_TYPE_TX, &nv->napi);
+ }
+
+ /* Associate Rx queue with NAPI */
+ for (j = 0; j < nv->rxt_count; j++, i++) {
+ struct fbnic_q_triad *qt = &nv->qt[i];
+
+ netif_queue_set_napi(nv->napi.dev, qt->cmpl.q_idx,
+ NETDEV_QUEUE_TYPE_RX, &nv->napi);
+ }
+}
+
+static void fbnic_reset_netif_napi(struct fbnic_napi_vector *nv)
+{
+ int i, j;
+
+ /* Disassociate Tx queue from NAPI */
+ for (i = 0; i < nv->txt_count; i++) {
+ struct fbnic_q_triad *qt = &nv->qt[i];
+
+ netif_queue_set_napi(nv->napi.dev, qt->sub0.q_idx,
+ NETDEV_QUEUE_TYPE_TX, NULL);
+ }
+
+ /* Disassociate Rx queue from NAPI */
+ for (j = 0; j < nv->rxt_count; j++, i++) {
+ struct fbnic_q_triad *qt = &nv->qt[i];
+
+ netif_queue_set_napi(nv->napi.dev, qt->cmpl.q_idx,
+ NETDEV_QUEUE_TYPE_RX, NULL);
+ }
+}
+
+int fbnic_set_netif_queues(struct fbnic_net *fbn)
+{
+ int i, err;
+
+ err = netif_set_real_num_queues(fbn->netdev, fbn->num_tx_queues,
+ fbn->num_rx_queues);
+ if (err)
+ return err;
+
+ for (i = 0; i < fbn->num_napi; i++)
+ fbnic_set_netif_napi(fbn->napi[i]);
+
+ return 0;
+}
+
+void fbnic_reset_netif_queues(struct fbnic_net *fbn)
+{
+ int i;
+
+ for (i = 0; i < fbn->num_napi; i++)
+ fbnic_reset_netif_napi(fbn->napi[i]);
+}
+
static void fbnic_disable_twq0(struct fbnic_ring *txr)
{
u32 twq_ctl = fbnic_ring_rd32(txr, FBNIC_QUEUE_TWQ0_CTL);
@@ -1670,33 +1718,34 @@ static void fbnic_disable_rcq(struct fbnic_ring *rxr)
void fbnic_napi_disable(struct fbnic_net *fbn)
{
- struct fbnic_napi_vector *nv;
+ int i;
- list_for_each_entry(nv, &fbn->napis, napis) {
- napi_disable(&nv->napi);
+ for (i = 0; i < fbn->num_napi; i++) {
+ napi_disable(&fbn->napi[i]->napi);
- fbnic_nv_irq_disable(nv);
+ fbnic_nv_irq_disable(fbn->napi[i]);
}
}
void fbnic_disable(struct fbnic_net *fbn)
{
struct fbnic_dev *fbd = fbn->fbd;
- struct fbnic_napi_vector *nv;
- int i, j;
+ int i, j, t;
+
+ for (i = 0; i < fbn->num_napi; i++) {
+ struct fbnic_napi_vector *nv = fbn->napi[i];
- list_for_each_entry(nv, &fbn->napis, napis) {
/* Disable Tx queue triads */
- for (i = 0; i < nv->txt_count; i++) {
- struct fbnic_q_triad *qt = &nv->qt[i];
+ for (t = 0; t < nv->txt_count; t++) {
+ struct fbnic_q_triad *qt = &nv->qt[t];
fbnic_disable_twq0(&qt->sub0);
fbnic_disable_tcq(&qt->cmpl);
}
/* Disable Rx queue triads */
- for (j = 0; j < nv->rxt_count; j++, i++) {
- struct fbnic_q_triad *qt = &nv->qt[i];
+ for (j = 0; j < nv->rxt_count; j++, t++) {
+ struct fbnic_q_triad *qt = &nv->qt[t];
fbnic_disable_bdq(&qt->sub0, &qt->sub1);
fbnic_disable_rcq(&qt->cmpl);
@@ -1792,14 +1841,15 @@ int fbnic_wait_all_queues_idle(struct fbnic_dev *fbd, bool may_fail)
void fbnic_flush(struct fbnic_net *fbn)
{
- struct fbnic_napi_vector *nv;
+ int i;
- list_for_each_entry(nv, &fbn->napis, napis) {
- int i, j;
+ for (i = 0; i < fbn->num_napi; i++) {
+ struct fbnic_napi_vector *nv = fbn->napi[i];
+ int j, t;
/* Flush any processed Tx Queue Triads and drop the rest */
- for (i = 0; i < nv->txt_count; i++) {
- struct fbnic_q_triad *qt = &nv->qt[i];
+ for (t = 0; t < nv->txt_count; t++) {
+ struct fbnic_q_triad *qt = &nv->qt[t];
struct netdev_queue *tx_queue;
/* Clean the work queues of unprocessed work */
@@ -1816,15 +1866,11 @@ void fbnic_flush(struct fbnic_net *fbn)
tx_queue = netdev_get_tx_queue(nv->napi.dev,
qt->sub0.q_idx);
netdev_tx_reset_queue(tx_queue);
-
- /* Disassociate Tx queue from NAPI */
- netif_queue_set_napi(nv->napi.dev, qt->sub0.q_idx,
- NETDEV_QUEUE_TYPE_TX, NULL);
}
/* Flush any processed Rx Queue Triads and drop the rest */
- for (j = 0; j < nv->rxt_count; j++, i++) {
- struct fbnic_q_triad *qt = &nv->qt[i];
+ for (j = 0; j < nv->rxt_count; j++, t++) {
+ struct fbnic_q_triad *qt = &nv->qt[t];
/* Clean the work queues of unprocessed work */
fbnic_clean_bdq(nv, 0, &qt->sub0, qt->sub0.tail);
@@ -1835,43 +1881,23 @@ void fbnic_flush(struct fbnic_net *fbn)
fbnic_put_pkt_buff(nv, qt->cmpl.pkt, 0);
qt->cmpl.pkt->buff.data_hard_start = NULL;
-
- /* Disassociate Rx queue from NAPI */
- netif_queue_set_napi(nv->napi.dev, qt->cmpl.q_idx,
- NETDEV_QUEUE_TYPE_RX, NULL);
}
}
}
void fbnic_fill(struct fbnic_net *fbn)
{
- struct fbnic_napi_vector *nv;
-
- list_for_each_entry(nv, &fbn->napis, napis) {
- int i, j;
-
- /* Configure NAPI mapping for Tx */
- for (i = 0; i < nv->txt_count; i++) {
- struct fbnic_q_triad *qt = &nv->qt[i];
-
- /* Nothing to do if Tx queue is disabled */
- if (qt->sub0.flags & FBNIC_RING_F_DISABLED)
- continue;
+ int i;
- /* Associate Tx queue with NAPI */
- netif_queue_set_napi(nv->napi.dev, qt->sub0.q_idx,
- NETDEV_QUEUE_TYPE_TX, &nv->napi);
- }
+ for (i = 0; i < fbn->num_napi; i++) {
+ struct fbnic_napi_vector *nv = fbn->napi[i];
+ int j, t;
/* Configure NAPI mapping and populate pages
* in the BDQ rings to use for Rx
*/
- for (j = 0; j < nv->rxt_count; j++, i++) {
- struct fbnic_q_triad *qt = &nv->qt[i];
-
- /* Associate Rx queue with NAPI */
- netif_queue_set_napi(nv->napi.dev, qt->cmpl.q_idx,
- NETDEV_QUEUE_TYPE_RX, &nv->napi);
+ for (j = 0, t = nv->txt_count; j < nv->rxt_count; j++, t++) {
+ struct fbnic_q_triad *qt = &nv->qt[t];
/* Populate the header and payload BDQs */
fbnic_fill_bdq(nv, &qt->sub0);
@@ -2025,21 +2051,23 @@ static void fbnic_enable_rcq(struct fbnic_napi_vector *nv,
void fbnic_enable(struct fbnic_net *fbn)
{
struct fbnic_dev *fbd = fbn->fbd;
- struct fbnic_napi_vector *nv;
- int i, j;
+ int i;
+
+ for (i = 0; i < fbn->num_napi; i++) {
+ struct fbnic_napi_vector *nv = fbn->napi[i];
+ int j, t;
- list_for_each_entry(nv, &fbn->napis, napis) {
/* Setup Tx Queue Triads */
- for (i = 0; i < nv->txt_count; i++) {
- struct fbnic_q_triad *qt = &nv->qt[i];
+ for (t = 0; t < nv->txt_count; t++) {
+ struct fbnic_q_triad *qt = &nv->qt[t];
fbnic_enable_twq0(&qt->sub0);
fbnic_enable_tcq(nv, &qt->cmpl);
}
/* Setup Rx Queue Triads */
- for (j = 0; j < nv->rxt_count; j++, i++) {
- struct fbnic_q_triad *qt = &nv->qt[i];
+ for (j = 0; j < nv->rxt_count; j++, t++) {
+ struct fbnic_q_triad *qt = &nv->qt[t];
fbnic_enable_bdq(&qt->sub0, &qt->sub1);
fbnic_config_drop_mode_rcq(nv, &qt->cmpl);
@@ -2064,10 +2092,11 @@ void fbnic_napi_enable(struct fbnic_net *fbn)
{
u32 irqs[FBNIC_MAX_MSIX_VECS / 32] = {};
struct fbnic_dev *fbd = fbn->fbd;
- struct fbnic_napi_vector *nv;
int i;
- list_for_each_entry(nv, &fbn->napis, napis) {
+ for (i = 0; i < fbn->num_napi; i++) {
+ struct fbnic_napi_vector *nv = fbn->napi[i];
+
napi_enable(&nv->napi);
fbnic_nv_irq_enable(nv);
@@ -2096,17 +2125,18 @@ void fbnic_napi_depletion_check(struct net_device *netdev)
struct fbnic_net *fbn = netdev_priv(netdev);
u32 irqs[FBNIC_MAX_MSIX_VECS / 32] = {};
struct fbnic_dev *fbd = fbn->fbd;
- struct fbnic_napi_vector *nv;
- int i, j;
+ int i, j, t;
+
+ for (i = 0; i < fbn->num_napi; i++) {
+ struct fbnic_napi_vector *nv = fbn->napi[i];
- list_for_each_entry(nv, &fbn->napis, napis) {
/* Find RQs which are completely out of pages */
- for (i = nv->txt_count, j = 0; j < nv->rxt_count; j++, i++) {
+ for (t = nv->txt_count, j = 0; j < nv->rxt_count; j++, t++) {
/* Assume 4 pages is always enough to fit a packet
* and therefore generate a completion and an IRQ.
*/
- if (fbnic_desc_used(&nv->qt[i].sub0) < 4 ||
- fbnic_desc_used(&nv->qt[i].sub1) < 4)
+ if (fbnic_desc_used(&nv->qt[t].sub0) < 4 ||
+ fbnic_desc_used(&nv->qt[t].sub1) < 4)
irqs[nv->v_idx / 32] |= BIT(nv->v_idx % 32);
}
}
diff --git a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
index 8d626287c3f4..c2a94f31f71b 100644
--- a/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
+++ b/drivers/net/ethernet/meta/fbnic/fbnic_txrx.h
@@ -104,14 +104,11 @@ struct fbnic_napi_vector {
struct device *dev; /* Device for DMA unmapping */
struct page_pool *page_pool;
struct fbnic_dev *fbd;
- char name[IFNAMSIZ + 9];
u16 v_idx;
u8 txt_count;
u8 rxt_count;
- struct list_head napis;
-
struct fbnic_q_triad qt[];
};
@@ -123,10 +120,18 @@ netdev_features_t
fbnic_features_check(struct sk_buff *skb, struct net_device *dev,
netdev_features_t features);
+void fbnic_aggregate_ring_rx_counters(struct fbnic_net *fbn,
+ struct fbnic_ring *rxr);
+void fbnic_aggregate_ring_tx_counters(struct fbnic_net *fbn,
+ struct fbnic_ring *txr);
+
int fbnic_alloc_napi_vectors(struct fbnic_net *fbn);
void fbnic_free_napi_vectors(struct fbnic_net *fbn);
int fbnic_alloc_resources(struct fbnic_net *fbn);
void fbnic_free_resources(struct fbnic_net *fbn);
+int fbnic_set_netif_queues(struct fbnic_net *fbn);
+void fbnic_reset_netif_queues(struct fbnic_net *fbn);
+irqreturn_t fbnic_msix_clean_rings(int irq, void *data);
void fbnic_napi_enable(struct fbnic_net *fbn);
void fbnic_napi_disable(struct fbnic_net *fbn);
void fbnic_enable(struct fbnic_net *fbn);
@@ -137,4 +142,9 @@ void fbnic_fill(struct fbnic_net *fbn);
void fbnic_napi_depletion_check(struct net_device *netdev);
int fbnic_wait_all_queues_idle(struct fbnic_dev *fbd, bool may_fail);
+static inline int fbnic_napi_idx(const struct fbnic_napi_vector *nv)
+{
+ return nv->v_idx - FBNIC_NON_NAPI_VECTORS;
+}
+
#endif /* _FBNIC_TXRX_H_ */
diff --git a/drivers/net/ethernet/microchip/Kconfig b/drivers/net/ethernet/microchip/Kconfig
index 73832fb2bc32..ee046468652c 100644
--- a/drivers/net/ethernet/microchip/Kconfig
+++ b/drivers/net/ethernet/microchip/Kconfig
@@ -59,7 +59,6 @@ config LAN743X
source "drivers/net/ethernet/microchip/lan865x/Kconfig"
source "drivers/net/ethernet/microchip/lan966x/Kconfig"
-source "drivers/net/ethernet/microchip/lan969x/Kconfig"
source "drivers/net/ethernet/microchip/sparx5/Kconfig"
source "drivers/net/ethernet/microchip/vcap/Kconfig"
source "drivers/net/ethernet/microchip/fdma/Kconfig"
diff --git a/drivers/net/ethernet/microchip/Makefile b/drivers/net/ethernet/microchip/Makefile
index 7770df82200f..3c65baed9fd8 100644
--- a/drivers/net/ethernet/microchip/Makefile
+++ b/drivers/net/ethernet/microchip/Makefile
@@ -11,7 +11,6 @@ lan743x-objs := lan743x_main.o lan743x_ethtool.o lan743x_ptp.o
obj-$(CONFIG_LAN865X) += lan865x/
obj-$(CONFIG_LAN966X_SWITCH) += lan966x/
-obj-$(CONFIG_LAN969X_SWITCH) += lan969x/
obj-$(CONFIG_SPARX5_SWITCH) += sparx5/
obj-$(CONFIG_VCAP) += vcap/
obj-$(CONFIG_FDMA) += fdma/
diff --git a/drivers/net/ethernet/microchip/lan969x/Kconfig b/drivers/net/ethernet/microchip/lan969x/Kconfig
deleted file mode 100644
index c5c6122ae2ec..000000000000
--- a/drivers/net/ethernet/microchip/lan969x/Kconfig
+++ /dev/null
@@ -1,5 +0,0 @@
-config LAN969X_SWITCH
- bool "Lan969x switch driver"
- depends on SPARX5_SWITCH
- help
- This driver supports the lan969x family of network switch devices.
diff --git a/drivers/net/ethernet/microchip/lan969x/Makefile b/drivers/net/ethernet/microchip/lan969x/Makefile
deleted file mode 100644
index 316405cbbc71..000000000000
--- a/drivers/net/ethernet/microchip/lan969x/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-#
-# Makefile for the Microchip lan969x network device drivers.
-#
-
-obj-$(CONFIG_SPARX5_SWITCH) += lan969x-switch.o
-
-lan969x-switch-y := lan969x_regs.o lan969x.o lan969x_calendar.o \
- lan969x_vcap_ag_api.o lan969x_vcap_impl.o
-
-# Provide include files
-ccflags-y += -I$(srctree)/drivers/net/ethernet/microchip/fdma
-ccflags-y += -I$(srctree)/drivers/net/ethernet/microchip/vcap
diff --git a/drivers/net/ethernet/microchip/sparx5/Kconfig b/drivers/net/ethernet/microchip/sparx5/Kconfig
index 3f04992eace6..35b057c9d0cb 100644
--- a/drivers/net/ethernet/microchip/sparx5/Kconfig
+++ b/drivers/net/ethernet/microchip/sparx5/Kconfig
@@ -24,3 +24,9 @@ config SPARX5_DCB
DSCP and PCP.
If unsure, set to Y.
+
+config LAN969X_SWITCH
+ bool "Lan969x switch driver"
+ depends on SPARX5_SWITCH
+ help
+ This driver supports the lan969x family of network switch devices.
diff --git a/drivers/net/ethernet/microchip/sparx5/Makefile b/drivers/net/ethernet/microchip/sparx5/Makefile
index 3435ca86dd70..3f34e83246a0 100644
--- a/drivers/net/ethernet/microchip/sparx5/Makefile
+++ b/drivers/net/ethernet/microchip/sparx5/Makefile
@@ -16,6 +16,13 @@ sparx5-switch-y := sparx5_main.o sparx5_packet.o \
sparx5-switch-$(CONFIG_SPARX5_DCB) += sparx5_dcb.o
sparx5-switch-$(CONFIG_DEBUG_FS) += sparx5_vcap_debugfs.o
+sparx5-switch-$(CONFIG_LAN969X_SWITCH) += lan969x/lan969x_regs.o \
+ lan969x/lan969x.o \
+ lan969x/lan969x_calendar.o \
+ lan969x/lan969x_vcap_ag_api.o \
+ lan969x/lan969x_vcap_impl.o \
+ lan969x/lan969x_rgmii.o
+
# Provide include files
ccflags-y += -I$(srctree)/drivers/net/ethernet/microchip/vcap
ccflags-y += -I$(srctree)/drivers/net/ethernet/microchip/fdma
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x.c b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c
index ac37d0f74ee3..396f76b6eea5 100644
--- a/drivers/net/ethernet/microchip/lan969x/lan969x.c
+++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.c
@@ -90,9 +90,12 @@ static const struct sparx5_main_io_resource lan969x_main_iomap[] = {
{ TARGET_DEV2G5 + 27, 0x30d8000, 1 }, /* 0xe30d8000 */
{ TARGET_DEV10G + 9, 0x30dc000, 1 }, /* 0xe30dc000 */
{ TARGET_PCS10G_BR + 9, 0x30e0000, 1 }, /* 0xe30e0000 */
+ { TARGET_DEVRGMII, 0x30e4000, 1 }, /* 0xe30e4000 */
+ { TARGET_DEVRGMII + 1, 0x30e8000, 1 }, /* 0xe30e8000 */
{ TARGET_DSM, 0x30ec000, 1 }, /* 0xe30ec000 */
{ TARGET_PORT_CONF, 0x30f0000, 1 }, /* 0xe30f0000 */
{ TARGET_ASM, 0x3200000, 1 }, /* 0xe3200000 */
+ { TARGET_HSIO_WRAP, 0x3408000, 1 }, /* 0xe3408000 */
};
static struct sparx5_sdlb_group lan969x_sdlb_groups[LAN969X_SDLB_GRP_CNT] = {
@@ -273,9 +276,9 @@ static irqreturn_t lan969x_ptp_irq_handler(int irq, void *args)
if (WARN_ON(!skb_match))
continue;
- spin_lock(&sparx5->ptp_ts_id_lock);
+ spin_lock_irqsave(&sparx5->ptp_ts_id_lock, flags);
sparx5->ptp_skbs--;
- spin_unlock(&sparx5->ptp_ts_id_lock);
+ spin_unlock_irqrestore(&sparx5->ptp_ts_id_lock, flags);
/* Get the h/w timestamp */
sparx5_get_hwtimestamp(sparx5, &ts, delay);
@@ -329,6 +332,7 @@ static const struct sparx5_ops lan969x_ops = {
.is_port_5g = &lan969x_port_is_5g,
.is_port_10g = &lan969x_port_is_10g,
.is_port_25g = &lan969x_port_is_25g,
+ .is_port_rgmii = &lan969x_port_is_rgmii,
.get_port_dev_index = &lan969x_port_dev_mapping,
.get_port_dev_bit = &lan969x_get_dev_mode_bit,
.get_hsch_max_group_rate = &lan969x_get_hsch_max_group_rate,
@@ -336,6 +340,7 @@ static const struct sparx5_ops lan969x_ops = {
.set_port_mux = &lan969x_port_mux_set,
.ptp_irq_handler = &lan969x_ptp_irq_handler,
.dsm_calendar_calc = &lan969x_dsm_calendar_calc,
+ .port_config_rgmii = &lan969x_port_config_rgmii,
};
const struct sparx5_match_data lan969x_desc = {
@@ -346,8 +351,3 @@ const struct sparx5_match_data lan969x_desc = {
.consts = &lan969x_consts,
.ops = &lan969x_ops,
};
-EXPORT_SYMBOL_GPL(lan969x_desc);
-
-MODULE_DESCRIPTION("Microchip lan969x switch driver");
-MODULE_AUTHOR("Daniel Machon <daniel.machon@microchip.com>");
-MODULE_LICENSE("Dual MIT/GPL");
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x.h b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.h
index 2489d0d32dfd..9a7ddebecf1e 100644
--- a/drivers/net/ethernet/microchip/lan969x/lan969x.h
+++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x.h
@@ -59,7 +59,17 @@ static inline bool lan969x_port_is_25g(int portno)
return false;
}
+static inline bool lan969x_port_is_rgmii(int portno)
+{
+ return portno == 28 || portno == 29;
+}
+
/* lan969x_calendar.c */
int lan969x_dsm_calendar_calc(struct sparx5 *sparx5, u32 taxi,
struct sparx5_calendar_data *data);
+
+/* lan969x_rgmii.c */
+int lan969x_port_config_rgmii(struct sparx5_port *port,
+ struct sparx5_port_config *conf);
+
#endif
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x_calendar.c b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_calendar.c
index e857640df185..e857640df185 100644
--- a/drivers/net/ethernet/microchip/lan969x/lan969x_calendar.c
+++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_calendar.c
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x_regs.c b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_regs.c
index ace4ba21eec4..ace4ba21eec4 100644
--- a/drivers/net/ethernet/microchip/lan969x/lan969x_regs.c
+++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_regs.c
diff --git a/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_rgmii.c b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_rgmii.c
new file mode 100644
index 000000000000..4e422ca50828
--- /dev/null
+++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_rgmii.c
@@ -0,0 +1,224 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Microchip lan969x Switch driver
+ *
+ * Copyright (c) 2024 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#include "lan969x.h"
+
+/* Tx clock selectors */
+#define LAN969X_RGMII_TX_CLK_SEL_125MHZ 1 /* 1000Mbps */
+#define LAN969X_RGMII_TX_CLK_SEL_25MHZ 2 /* 100Mbps */
+#define LAN969X_RGMII_TX_CLK_SEL_2M5MHZ 3 /* 10Mbps */
+
+/* Port speed selectors */
+#define LAN969X_RGMII_SPEED_SEL_10 0 /* Select 10Mbps speed */
+#define LAN969X_RGMII_SPEED_SEL_100 1 /* Select 100Mbps speed */
+#define LAN969X_RGMII_SPEED_SEL_1000 2 /* Select 1000Mbps speed */
+
+/* Clock delay selectors */
+#define LAN969X_RGMII_CLK_DELAY_SEL_1_0_NS 2 /* Phase shift 45deg */
+#define LAN969X_RGMII_CLK_DELAY_SEL_1_7_NS 3 /* Phase shift 77deg */
+#define LAN969X_RGMII_CLK_DELAY_SEL_2_0_NS 4 /* Phase shift 90deg */
+#define LAN969X_RGMII_CLK_DELAY_SEL_2_5_NS 5 /* Phase shift 112deg */
+#define LAN969X_RGMII_CLK_DELAY_SEL_3_0_NS 6 /* Phase shift 135deg */
+#define LAN969X_RGMII_CLK_DELAY_SEL_3_3_NS 7 /* Phase shift 147deg */
+
+#define LAN969X_RGMII_PORT_START_IDX 28 /* Index of the first RGMII port */
+#define LAN969X_RGMII_IFG_TX 4 /* TX Inter Frame Gap value */
+#define LAN969X_RGMII_IFG_RX1 5 /* RX1 Inter Frame Gap value */
+#define LAN969X_RGMII_IFG_RX2 1 /* RX2 Inter Frame Gap value */
+
+#define RGMII_PORT_IDX(port) ((port)->portno - LAN969X_RGMII_PORT_START_IDX)
+
+/* Get the tx clock selector based on the port speed. */
+static int lan969x_rgmii_get_clk_sel(int speed)
+{
+ return (speed == SPEED_10 ? LAN969X_RGMII_TX_CLK_SEL_2M5MHZ :
+ speed == SPEED_100 ? LAN969X_RGMII_TX_CLK_SEL_25MHZ :
+ LAN969X_RGMII_TX_CLK_SEL_125MHZ);
+}
+
+/* Get the port speed selector based on the port speed. */
+static int lan969x_rgmii_get_speed_sel(int speed)
+{
+ return (speed == SPEED_10 ? LAN969X_RGMII_SPEED_SEL_10 :
+ speed == SPEED_100 ? LAN969X_RGMII_SPEED_SEL_100 :
+ LAN969X_RGMII_SPEED_SEL_1000);
+}
+
+/* Get the clock delay selector based on the clock delay in picoseconds. */
+static int lan969x_rgmii_get_clk_delay_sel(struct sparx5_port *port,
+ u32 delay_ps, u32 *clk_delay_sel)
+{
+ switch (delay_ps) {
+ case 0:
+ /* Hardware default selector. */
+ *clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_2_5_NS;
+ break;
+ case 1000:
+ *clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_1_0_NS;
+ break;
+ case 1700:
+ *clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_1_7_NS;
+ break;
+ case 2000:
+ *clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_2_0_NS;
+ break;
+ case 2500:
+ *clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_2_5_NS;
+ break;
+ case 3000:
+ *clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_3_0_NS;
+ break;
+ case 3300:
+ *clk_delay_sel = LAN969X_RGMII_CLK_DELAY_SEL_3_3_NS;
+ break;
+ default:
+ dev_err(port->sparx5->dev, "Invalid RGMII delay: %u", delay_ps);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* Configure the RGMII tx clock frequency. */
+static void lan969x_rgmii_tx_clk_config(struct sparx5_port *port,
+ struct sparx5_port_config *conf)
+{
+ u32 clk_sel = lan969x_rgmii_get_clk_sel(conf->speed);
+ u32 idx = RGMII_PORT_IDX(port);
+
+ /* Take the RGMII clock domain out of reset and set tx clock
+ * frequency.
+ */
+ spx5_rmw(HSIO_WRAP_RGMII_CFG_TX_CLK_CFG_SET(clk_sel) |
+ HSIO_WRAP_RGMII_CFG_RGMII_TX_RST_SET(0) |
+ HSIO_WRAP_RGMII_CFG_RGMII_RX_RST_SET(0),
+ HSIO_WRAP_RGMII_CFG_TX_CLK_CFG |
+ HSIO_WRAP_RGMII_CFG_RGMII_TX_RST |
+ HSIO_WRAP_RGMII_CFG_RGMII_RX_RST,
+ port->sparx5, HSIO_WRAP_RGMII_CFG(idx));
+}
+
+/* Configure the RGMII port device. */
+static void lan969x_rgmii_port_device_config(struct sparx5_port *port,
+ struct sparx5_port_config *conf)
+{
+ u32 dtag, dotag, etype, speed_sel, idx = RGMII_PORT_IDX(port);
+
+ speed_sel = lan969x_rgmii_get_speed_sel(conf->speed);
+
+ etype = (port->vlan_type == SPX5_VLAN_PORT_TYPE_S_CUSTOM ?
+ port->custom_etype :
+ port->vlan_type == SPX5_VLAN_PORT_TYPE_C ?
+ ETH_P_8021Q : ETH_P_8021AD);
+
+ dtag = port->max_vlan_tags == SPX5_PORT_MAX_TAGS_TWO;
+ dotag = port->max_vlan_tags != SPX5_PORT_MAX_TAGS_NONE;
+
+ /* Enable the MAC. */
+ spx5_wr(DEVRGMII_MAC_ENA_CFG_RX_ENA_SET(1) |
+ DEVRGMII_MAC_ENA_CFG_TX_ENA_SET(1),
+ port->sparx5, DEVRGMII_MAC_ENA_CFG(idx));
+
+ /* Configure the Inter Frame Gap. */
+ spx5_wr(DEVRGMII_MAC_IFG_CFG_TX_IFG_SET(LAN969X_RGMII_IFG_TX) |
+ DEVRGMII_MAC_IFG_CFG_RX_IFG1_SET(LAN969X_RGMII_IFG_RX1) |
+ DEVRGMII_MAC_IFG_CFG_RX_IFG2_SET(LAN969X_RGMII_IFG_RX2),
+ port->sparx5, DEVRGMII_MAC_IFG_CFG(idx));
+
+ /* Configure port data rate. */
+ spx5_wr(DEVRGMII_DEV_RST_CTRL_SPEED_SEL_SET(speed_sel),
+ port->sparx5, DEVRGMII_DEV_RST_CTRL(idx));
+
+ /* Configure VLAN awareness. */
+ spx5_wr(DEVRGMII_MAC_TAGS_CFG_TAG_ID_SET(etype) |
+ DEVRGMII_MAC_TAGS_CFG_PB_ENA_SET(dtag) |
+ DEVRGMII_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(dotag) |
+ DEVRGMII_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA_SET(dotag),
+ port->sparx5,
+ DEVRGMII_MAC_TAGS_CFG(idx));
+}
+
+/* Configure the RGMII delay lines in the MAC.
+ *
+ * We use the rx-internal-delay-ps" and "tx-internal-delay-ps" properties to
+ * configure the rx and tx delays for the MAC. If these properties are missing
+ * or set to zero, the MAC will not apply any delay.
+ *
+ * The PHY side delays are determined by the PHY mode
+ * (e.g. PHY_INTERFACE_MODE_RGMII_{ID, RXID, TXID}), and ignored by the MAC side
+ * entirely.
+ */
+static int lan969x_rgmii_delay_config(struct sparx5_port *port,
+ struct sparx5_port_config *conf)
+{
+ u32 tx_clk_sel, rx_clk_sel, tx_delay_ps = 0, rx_delay_ps = 0;
+ u32 idx = RGMII_PORT_IDX(port);
+ int err;
+
+ of_property_read_u32(port->of_node, "rx-internal-delay-ps",
+ &rx_delay_ps);
+
+ of_property_read_u32(port->of_node, "tx-internal-delay-ps",
+ &tx_delay_ps);
+
+ err = lan969x_rgmii_get_clk_delay_sel(port, rx_delay_ps, &rx_clk_sel);
+ if (err)
+ return err;
+
+ err = lan969x_rgmii_get_clk_delay_sel(port, tx_delay_ps, &tx_clk_sel);
+ if (err)
+ return err;
+
+ /* Configure rx delay. */
+ spx5_rmw(HSIO_WRAP_DLL_CFG_DLL_RST_SET(0) |
+ HSIO_WRAP_DLL_CFG_DLL_ENA_SET(1) |
+ HSIO_WRAP_DLL_CFG_DLL_CLK_ENA_SET(!!rx_delay_ps) |
+ HSIO_WRAP_DLL_CFG_DLL_CLK_SEL_SET(rx_clk_sel),
+ HSIO_WRAP_DLL_CFG_DLL_RST |
+ HSIO_WRAP_DLL_CFG_DLL_ENA |
+ HSIO_WRAP_DLL_CFG_DLL_CLK_ENA |
+ HSIO_WRAP_DLL_CFG_DLL_CLK_SEL,
+ port->sparx5, HSIO_WRAP_DLL_CFG(idx, 0));
+
+ /* Configure tx delay. */
+ spx5_rmw(HSIO_WRAP_DLL_CFG_DLL_RST_SET(0) |
+ HSIO_WRAP_DLL_CFG_DLL_ENA_SET(1) |
+ HSIO_WRAP_DLL_CFG_DLL_CLK_ENA_SET(!!tx_delay_ps) |
+ HSIO_WRAP_DLL_CFG_DLL_CLK_SEL_SET(tx_clk_sel),
+ HSIO_WRAP_DLL_CFG_DLL_RST |
+ HSIO_WRAP_DLL_CFG_DLL_ENA |
+ HSIO_WRAP_DLL_CFG_DLL_CLK_ENA |
+ HSIO_WRAP_DLL_CFG_DLL_CLK_SEL,
+ port->sparx5, HSIO_WRAP_DLL_CFG(idx, 1));
+
+ return 0;
+}
+
+/* Configure GPIO's to be used as RGMII interface. */
+static void lan969x_rgmii_gpio_config(struct sparx5_port *port)
+{
+ u32 idx = RGMII_PORT_IDX(port);
+
+ /* Enable the RGMII on the GPIOs. */
+ spx5_wr(HSIO_WRAP_XMII_CFG_GPIO_XMII_CFG_SET(1), port->sparx5,
+ HSIO_WRAP_XMII_CFG(!idx));
+}
+
+int lan969x_port_config_rgmii(struct sparx5_port *port,
+ struct sparx5_port_config *conf)
+{
+ int err;
+
+ err = lan969x_rgmii_delay_config(port, conf);
+ if (err)
+ return err;
+
+ lan969x_rgmii_tx_clk_config(port, conf);
+ lan969x_rgmii_gpio_config(port);
+ lan969x_rgmii_port_device_config(port, conf);
+
+ return 0;
+}
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x_vcap_ag_api.c b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_vcap_ag_api.c
index 7acc5bcf337a..7acc5bcf337a 100644
--- a/drivers/net/ethernet/microchip/lan969x/lan969x_vcap_ag_api.c
+++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_vcap_ag_api.c
diff --git a/drivers/net/ethernet/microchip/lan969x/lan969x_vcap_impl.c b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_vcap_impl.c
index 543a1f2bf6bd..543a1f2bf6bd 100644
--- a/drivers/net/ethernet/microchip/lan969x/lan969x_vcap_impl.c
+++ b/drivers/net/ethernet/microchip/sparx5/lan969x/lan969x_vcap_impl.c
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c b/drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c
index 5fe941c66c17..5c46d81de530 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_calendar.c
@@ -98,7 +98,6 @@ u32 sparx5_cal_speed_to_value(enum sparx5_cal_bw speed)
default: return 0;
}
}
-EXPORT_SYMBOL_GPL(sparx5_cal_speed_to_value);
static u32 sparx5_bandwidth_to_calendar(u32 bw)
{
@@ -150,7 +149,6 @@ enum sparx5_cal_bw sparx5_get_port_cal_speed(struct sparx5 *sparx5, u32 portno)
return SPX5_CAL_SPEED_NONE;
return sparx5_bandwidth_to_calendar(port->conf.bandwidth);
}
-EXPORT_SYMBOL_GPL(sparx5_get_port_cal_speed);
/* Auto configure the QSYS calendar based on port configuration */
int sparx5_config_auto_calendar(struct sparx5 *sparx5)
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
index 2f1013f870fb..e68277c38adc 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.c
@@ -24,7 +24,7 @@
#include <linux/types.h>
#include <linux/reset.h>
-#include "../lan969x/lan969x.h" /* for lan969x match data */
+#include "lan969x/lan969x.h" /* for lan969x match data */
#include "sparx5_main_regs.h"
#include "sparx5_main.h"
@@ -313,10 +313,13 @@ static int sparx5_create_port(struct sparx5 *sparx5,
struct initial_port_config *config)
{
struct sparx5_port *spx5_port;
+ const struct sparx5_ops *ops;
struct net_device *ndev;
struct phylink *phylink;
int err;
+ ops = sparx5->data->ops;
+
ndev = sparx5_create_netdev(sparx5, config->portno);
if (IS_ERR(ndev)) {
dev_err(sparx5->dev, "Could not create net device: %02u\n",
@@ -357,6 +360,9 @@ static int sparx5_create_port(struct sparx5 *sparx5,
MAC_SYM_PAUSE | MAC_10 | MAC_100 | MAC_1000FD |
MAC_2500FD | MAC_5000FD | MAC_10000FD | MAC_25000FD;
+ if (ops->is_port_rgmii(spx5_port->portno))
+ phy_interface_set_rgmii(spx5_port->phylink_config.supported_interfaces);
+
__set_bit(PHY_INTERFACE_MODE_SGMII,
spx5_port->phylink_config.supported_interfaces);
__set_bit(PHY_INTERFACE_MODE_QSGMII,
@@ -780,12 +786,11 @@ static int sparx5_start(struct sparx5 *sparx5)
err = -ENXIO;
if (sparx5->fdma_irq >= 0 && is_sparx5(sparx5)) {
if (GCB_CHIP_ID_REV_ID_GET(sparx5->chip_id) > 0)
- err = devm_request_threaded_irq(sparx5->dev,
- sparx5->fdma_irq,
- NULL,
- sparx5_fdma_handler,
- IRQF_ONESHOT,
- "sparx5-fdma", sparx5);
+ err = devm_request_irq(sparx5->dev,
+ sparx5->fdma_irq,
+ sparx5_fdma_handler,
+ 0,
+ "sparx5-fdma", sparx5);
if (!err)
err = sparx5_fdma_start(sparx5);
if (err)
@@ -831,6 +836,7 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
struct initial_port_config *configs, *config;
struct device_node *np = pdev->dev.of_node;
struct device_node *ports, *portnp;
+ const struct sparx5_ops *ops;
struct reset_control *reset;
struct sparx5 *sparx5;
int idx = 0, err = 0;
@@ -852,6 +858,7 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
return -EINVAL;
regs = sparx5->data->regs;
+ ops = sparx5->data->ops;
/* Do switch core reset if available */
reset = devm_reset_control_get_optional_shared(&pdev->dev, "switch");
@@ -881,7 +888,7 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
for_each_available_child_of_node(ports, portnp) {
struct sparx5_port_config *conf;
- struct phy *serdes;
+ struct phy *serdes = NULL;
u32 portno;
err = of_property_read_u32(portnp, "reg", &portno);
@@ -911,13 +918,17 @@ static int mchp_sparx5_probe(struct platform_device *pdev)
conf->sd_sgpio = ~0;
else
sparx5->sd_sgpio_remapping = true;
- serdes = devm_of_phy_get(sparx5->dev, portnp, NULL);
- if (IS_ERR(serdes)) {
- err = dev_err_probe(sparx5->dev, PTR_ERR(serdes),
- "port %u: missing serdes\n",
- portno);
- of_node_put(portnp);
- goto cleanup_config;
+ /* There is no SerDes node for RGMII ports. */
+ if (!ops->is_port_rgmii(portno)) {
+ serdes = devm_of_phy_get(sparx5->dev, portnp, NULL);
+ if (IS_ERR(serdes)) {
+ err = dev_err_probe(sparx5->dev,
+ PTR_ERR(serdes),
+ "port %u: missing serdes\n",
+ portno);
+ of_node_put(portnp);
+ goto cleanup_config;
+ }
}
config->portno = portno;
config->node = portnp;
@@ -1073,6 +1084,7 @@ static const struct sparx5_ops sparx5_ops = {
.is_port_5g = &sparx5_port_is_5g,
.is_port_10g = &sparx5_port_is_10g,
.is_port_25g = &sparx5_port_is_25g,
+ .is_port_rgmii = &sparx5_port_is_rgmii,
.get_port_dev_index = &sparx5_port_dev_mapping,
.get_port_dev_bit = &sparx5_port_dev_mapping,
.get_hsch_max_group_rate = &sparx5_get_hsch_max_group_rate,
@@ -1093,7 +1105,7 @@ static const struct sparx5_match_data sparx5_desc = {
static const struct of_device_id mchp_sparx5_match[] = {
{ .compatible = "microchip,sparx5-switch", .data = &sparx5_desc },
-#if IS_ENABLED(CONFIG_LAN969X_SWITCH)
+#ifdef CONFIG_LAN969X_SWITCH
{ .compatible = "microchip,lan9691-switch", .data = &lan969x_desc },
#endif
{ }
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
index d5dd953b0a71..3ae760da17e2 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
@@ -313,6 +313,7 @@ struct sparx5_ops {
bool (*is_port_5g)(int portno);
bool (*is_port_10g)(int portno);
bool (*is_port_25g)(int portno);
+ bool (*is_port_rgmii)(int portno);
u32 (*get_port_dev_index)(struct sparx5 *sparx5, int port);
u32 (*get_port_dev_bit)(struct sparx5 *sparx5, int port);
u32 (*get_hsch_max_group_rate)(int grp);
@@ -323,6 +324,8 @@ struct sparx5_ops {
irqreturn_t (*ptp_irq_handler)(int irq, void *args);
int (*dsm_calendar_calc)(struct sparx5 *sparx5, u32 taxi,
struct sparx5_calendar_data *data);
+ int (*port_config_rgmii)(struct sparx5_port *port,
+ struct sparx5_port_config *conf);
};
struct sparx5_main_io_resource {
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h
index 561344f19062..d9ef4ef137b8 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main_regs.h
@@ -37,6 +37,7 @@ enum sparx5_target {
TARGET_FDMA = 117,
TARGET_GCB = 118,
TARGET_HSCH = 119,
+ TARGET_HSIO_WRAP = 120,
TARGET_LRN = 122,
TARGET_PCEP = 129,
TARGET_PCS10G_BR = 132,
@@ -54,6 +55,7 @@ enum sparx5_target {
TARGET_VCAP_SUPER = 326,
TARGET_VOP = 327,
TARGET_XQS = 331,
+ TARGET_DEVRGMII = 392,
NUM_TARGETS = 517
};
@@ -5367,6 +5369,69 @@ extern const struct sparx5_regs *regs;
#define HSCH_TAS_STATEMACHINE_CFG_REVISIT_DLY_GET(x)\
FIELD_GET(HSCH_TAS_STATEMACHINE_CFG_REVISIT_DLY, x)
+/* LAN969X ONLY */
+/* HSIOWRAP:XMII_CFG:XMII_CFG */
+#define HSIO_WRAP_XMII_CFG(g) \
+ __REG(TARGET_HSIO_WRAP, 0, 1, 116, g, 2, 20, 0, 0, 1, 4)
+
+#define HSIO_WRAP_XMII_CFG_GPIO_XMII_CFG GENMASK(2, 1)
+#define HSIO_WRAP_XMII_CFG_GPIO_XMII_CFG_SET(x)\
+ FIELD_PREP(HSIO_WRAP_XMII_CFG_GPIO_XMII_CFG, x)
+#define HSIO_WRAP_XMII_CFG_GPIO_XMII_CFG_GET(x)\
+ FIELD_GET(HSIO_WRAP_XMII_CFG_GPIO_XMII_CFG, x)
+
+/* LAN969X ONLY */
+/* HSIOWRAP:XMII_CFG:RGMII_CFG */
+#define HSIO_WRAP_RGMII_CFG(g) \
+ __REG(TARGET_HSIO_WRAP, 0, 1, 116, g, 2, 20, 4, 0, 1, 4)
+
+#define HSIO_WRAP_RGMII_CFG_TX_CLK_CFG GENMASK(4, 2)
+#define HSIO_WRAP_RGMII_CFG_TX_CLK_CFG_SET(x)\
+ FIELD_PREP(HSIO_WRAP_RGMII_CFG_TX_CLK_CFG, x)
+#define HSIO_WRAP_RGMII_CFG_TX_CLK_CFG_GET(x)\
+ FIELD_GET(HSIO_WRAP_RGMII_CFG_TX_CLK_CFG, x)
+
+#define HSIO_WRAP_RGMII_CFG_RGMII_TX_RST BIT(1)
+#define HSIO_WRAP_RGMII_CFG_RGMII_TX_RST_SET(x)\
+ FIELD_PREP(HSIO_WRAP_RGMII_CFG_RGMII_TX_RST, x)
+#define HSIO_WRAP_RGMII_CFG_RGMII_TX_RST_GET(x)\
+ FIELD_GET(HSIO_WRAP_RGMII_CFG_RGMII_TX_RST, x)
+
+#define HSIO_WRAP_RGMII_CFG_RGMII_RX_RST BIT(0)
+#define HSIO_WRAP_RGMII_CFG_RGMII_RX_RST_SET(x)\
+ FIELD_PREP(HSIO_WRAP_RGMII_CFG_RGMII_RX_RST, x)
+#define HSIO_WRAP_RGMII_CFG_RGMII_RX_RST_GET(x)\
+ FIELD_GET(HSIO_WRAP_RGMII_CFG_RGMII_RX_RST, x)
+
+/* LAN969X ONLY */
+/* HSIOWRAP:XMII_CFG:DLL_CFG */
+#define HSIO_WRAP_DLL_CFG(g, r) \
+ __REG(TARGET_HSIO_WRAP, 0, 1, 116, g, 2, 20, 12, r, 2, 4)
+
+#define HSIO_WRAP_DLL_CFG_DLL_ENA BIT(19)
+#define HSIO_WRAP_DLL_CFG_DLL_ENA_SET(x)\
+ FIELD_PREP(HSIO_WRAP_DLL_CFG_DLL_ENA, x)
+#define HSIO_WRAP_DLL_CFG_DLL_ENA_GET(x)\
+ FIELD_GET(HSIO_WRAP_DLL_CFG_DLL_ENA, x)
+
+#define HSIO_WRAP_DLL_CFG_DLL_CLK_ENA BIT(18)
+#define HSIO_WRAP_DLL_CFG_DLL_CLK_ENA_SET(x)\
+ FIELD_PREP(HSIO_WRAP_DLL_CFG_DLL_CLK_ENA, x)
+#define HSIO_WRAP_DLL_CFG_DLL_CLK_ENA_GET(x)\
+ FIELD_GET(HSIO_WRAP_DLL_CFG_DLL_CLK_ENA, x)
+
+#define HSIO_WRAP_DLL_CFG_DLL_CLK_SEL GENMASK(17, 15)
+#define HSIO_WRAP_DLL_CFG_DLL_CLK_SEL_SET(x)\
+ FIELD_PREP(HSIO_WRAP_DLL_CFG_DLL_CLK_SEL, x)
+#define HSIO_WRAP_DLL_CFG_DLL_CLK_SEL_GET(x)\
+ FIELD_GET(HSIO_WRAP_DLL_CFG_DLL_CLK_SEL, x)
+
+#define HSIO_WRAP_DLL_CFG_DLL_RST BIT(0)
+#define HSIO_WRAP_DLL_CFG_DLL_RST_SET(x)\
+ FIELD_PREP(HSIO_WRAP_DLL_CFG_DLL_RST, x)
+#define HSIO_WRAP_DLL_CFG_DLL_RST_GET(x)\
+ FIELD_GET(HSIO_WRAP_DLL_CFG_DLL_RST, x)
+
/* LRN:COMMON:COMMON_ACCESS_CTRL */
#define LRN_COMMON_ACCESS_CTRL \
__REG(TARGET_LRN, 0, 1, 0, 0, 1, 72, 0, 0, 1, 4)
@@ -8110,4 +8175,84 @@ extern const struct sparx5_regs *regs;
#define XQS_CNT(g) \
__REG(TARGET_XQS, 0, 1, 0, g, 1024, 4, 0, 0, 1, 4)
+/* LAN969X ONLY */
+/* DEV1G:DEV_CFG_STATUS:DEV_RST_CTRL */
+#define DEVRGMII_DEV_RST_CTRL(t) \
+ __REG(TARGET_DEVRGMII, t, 2, 0, 0, 1, 36, 0, 0, 1, 4)
+
+#define DEVRGMII_DEV_RST_CTRL_SPEED_SEL GENMASK(22, 20)
+#define DEVRGMII_DEV_RST_CTRL_SPEED_SEL_SET(x)\
+ FIELD_PREP(DEVRGMII_DEV_RST_CTRL_SPEED_SEL, x)
+#define DEVRGMII_DEV_RST_CTRL_SPEED_SEL_GET(x)\
+ FIELD_GET(DEVRGMII_DEV_RST_CTRL_SPEED_SEL, x)
+
+/* LAN969X ONLY */
+/* DEV1G:MAC_CFG_STATUS:MAC_ENA_CFG */
+#define DEVRGMII_MAC_ENA_CFG(t) \
+ __REG(TARGET_DEVRGMII, t, 2, 36, 0, 1, 36, 0, 0, 1, 4)
+
+#define DEVRGMII_MAC_ENA_CFG_RX_ENA BIT(4)
+#define DEVRGMII_MAC_ENA_CFG_RX_ENA_SET(x)\
+ FIELD_PREP(DEVRGMII_MAC_ENA_CFG_RX_ENA, x)
+#define DEVRGMII_MAC_ENA_CFG_RX_ENA_GET(x)\
+ FIELD_GET(DEVRGMII_MAC_ENA_CFG_RX_ENA, x)
+
+#define DEVRGMII_MAC_ENA_CFG_TX_ENA BIT(0)
+#define DEVRGMII_MAC_ENA_CFG_TX_ENA_SET(x)\
+ FIELD_PREP(DEVRGMII_MAC_ENA_CFG_TX_ENA, x)
+#define DEVRGMII_MAC_ENA_CFG_TX_ENA_GET(x)\
+ FIELD_GET(DEVRGMII_MAC_ENA_CFG_TX_ENA, x)
+
+/* LAN969X ONLY */
+/* DEV1G:MAC_CFG_STATUS:MAC_TAGS_CFG */
+#define DEVRGMII_MAC_TAGS_CFG(t) \
+ __REG(TARGET_DEVRGMII, t, 2, 36, 0, 1, 36, 12, 0, 1, 4)
+
+#define DEVRGMII_MAC_TAGS_CFG_TAG_ID GENMASK(31, 16)
+#define DEVRGMII_MAC_TAGS_CFG_TAG_ID_SET(x)\
+ FIELD_PREP(DEVRGMII_MAC_TAGS_CFG_TAG_ID, x)
+#define DEVRGMII_MAC_TAGS_CFG_TAG_ID_GET(x)\
+ FIELD_GET(DEVRGMII_MAC_TAGS_CFG_TAG_ID, x)
+
+#define DEVRGMII_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA BIT(3)
+#define DEVRGMII_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA_SET(x)\
+ FIELD_PREP(DEVRGMII_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA, x)
+#define DEVRGMII_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA_GET(x)\
+ FIELD_GET(DEVRGMII_MAC_TAGS_CFG_VLAN_LEN_AWR_ENA, x)
+
+#define DEVRGMII_MAC_TAGS_CFG_PB_ENA GENMASK(2, 1)
+#define DEVRGMII_MAC_TAGS_CFG_PB_ENA_SET(x)\
+ FIELD_PREP(DEVRGMII_MAC_TAGS_CFG_PB_ENA, x)
+#define DEVRGMII_MAC_TAGS_CFG_PB_ENA_GET(x)\
+ FIELD_GET(DEVRGMII_MAC_TAGS_CFG_PB_ENA, x)
+
+#define DEVRGMII_MAC_TAGS_CFG_VLAN_AWR_ENA BIT(0)
+#define DEVRGMII_MAC_TAGS_CFG_VLAN_AWR_ENA_SET(x)\
+ FIELD_PREP(DEVRGMII_MAC_TAGS_CFG_VLAN_AWR_ENA, x)
+#define DEVRGMII_MAC_TAGS_CFG_VLAN_AWR_ENA_GET(x)\
+ FIELD_GET(DEVRGMII_MAC_TAGS_CFG_VLAN_AWR_ENA, x)
+
+/* LAN969X ONLY */
+/* DEV1G:MAC_CFG_STATUS:MAC_IFG_CFG */
+#define DEVRGMII_MAC_IFG_CFG(t) \
+ __REG(TARGET_DEVRGMII, t, 2, 36, 0, 1, 36, 24, 0, 1, 4)
+
+#define DEVRGMII_MAC_IFG_CFG_TX_IFG GENMASK(12, 8)
+#define DEVRGMII_MAC_IFG_CFG_TX_IFG_SET(x)\
+ FIELD_PREP(DEVRGMII_MAC_IFG_CFG_TX_IFG, x)
+#define DEVRGMII_MAC_IFG_CFG_TX_IFG_GET(x)\
+ FIELD_GET(DEVRGMII_MAC_IFG_CFG_TX_IFG, x)
+
+#define DEVRGMII_MAC_IFG_CFG_RX_IFG2 GENMASK(7, 4)
+#define DEVRGMII_MAC_IFG_CFG_RX_IFG2_SET(x)\
+ FIELD_PREP(DEVRGMII_MAC_IFG_CFG_RX_IFG2, x)
+#define DEVRGMII_MAC_IFG_CFG_RX_IFG2_GET(x)\
+ FIELD_GET(DEVRGMII_MAC_IFG_CFG_RX_IFG2, x)
+
+#define DEVRGMII_MAC_IFG_CFG_RX_IFG1 GENMASK(3, 0)
+#define DEVRGMII_MAC_IFG_CFG_RX_IFG1_SET(x)\
+ FIELD_PREP(DEVRGMII_MAC_IFG_CFG_RX_IFG1, x)
+#define DEVRGMII_MAC_IFG_CFG_RX_IFG1_GET(x)\
+ FIELD_GET(DEVRGMII_MAC_IFG_CFG_RX_IFG1, x)
+
#endif /* _SPARX5_MAIN_REGS_H_ */
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_mirror.c b/drivers/net/ethernet/microchip/sparx5/sparx5_mirror.c
index 9806729e9c62..76097761fa97 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_mirror.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_mirror.c
@@ -12,7 +12,6 @@
#define SPX5_MIRROR_DISABLED 0
#define SPX5_MIRROR_EGRESS 1
#define SPX5_MIRROR_INGRESS 2
-#define SPX5_MIRROR_MONITOR_PORT_DEFAULT 65
#define SPX5_QFWD_MP_OFFSET 9 /* Mirror port offset in the QFWD register */
/* Convert from bool ingress/egress to mirror direction */
@@ -200,7 +199,7 @@ void sparx5_mirror_del(struct sparx5_mall_entry *entry)
sparx5_mirror_monitor_set(sparx5,
mirror_idx,
- SPX5_MIRROR_MONITOR_PORT_DEFAULT);
+ sparx5->data->consts->n_ports);
}
void sparx5_mirror_stats(struct sparx5_mall_entry *entry,
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c
index f8562c1a894d..035d2f1bea0d 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_phylink.c
@@ -32,7 +32,19 @@ sparx5_phylink_mac_select_pcs(struct phylink_config *config,
{
struct sparx5_port *port = netdev_priv(to_net_dev(config->dev));
- return &port->phylink_pcs;
+ /* Return the PCS for all the modes that require it. */
+ switch (interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_QSGMII:
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ case PHY_INTERFACE_MODE_5GBASER:
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_25GBASER:
+ return &port->phylink_pcs;
+ default:
+ return NULL;
+ }
}
static void sparx5_phylink_mac_config(struct phylink_config *config,
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
index 1401761c6251..04bc8fffaf96 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.c
@@ -257,6 +257,15 @@ static int sparx5_port_verify_speed(struct sparx5 *sparx5,
conf->speed != SPEED_25000))
return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
break;
+ case PHY_INTERFACE_MODE_RGMII:
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ case PHY_INTERFACE_MODE_RGMII_TXID:
+ case PHY_INTERFACE_MODE_RGMII_RXID:
+ if (conf->speed != SPEED_1000 &&
+ conf->speed != SPEED_100 &&
+ conf->speed != SPEED_10)
+ return sparx5_port_error(port, conf, SPX5_PERR_SPEED);
+ break;
default:
return sparx5_port_error(port, conf, SPX5_PERR_IFTYPE);
}
@@ -994,6 +1003,7 @@ int sparx5_port_config(struct sparx5 *sparx5,
struct sparx5_port *port,
struct sparx5_port_config *conf)
{
+ bool rgmii = phy_interface_mode_is_rgmii(conf->phy_mode);
bool high_speed_dev = sparx5_is_baser(conf->portmode);
const struct sparx5_ops *ops = sparx5->data->ops;
int err, urgency, stop_wm;
@@ -1002,8 +1012,14 @@ int sparx5_port_config(struct sparx5 *sparx5,
if (err)
return err;
+ if (rgmii) {
+ err = ops->port_config_rgmii(port, conf);
+ if (err)
+ return err;
+ }
+
/* high speed device is already configured */
- if (!high_speed_dev)
+ if (!rgmii && !high_speed_dev)
sparx5_port_config_low_set(sparx5, port, conf);
/* Configure flow control */
@@ -1067,24 +1083,6 @@ int sparx5_port_init(struct sparx5 *sparx5,
if (err)
return err;
- /* Configure MAC vlan awareness */
- err = sparx5_port_max_tags_set(sparx5, port);
- if (err)
- return err;
-
- /* Set Max Length */
- spx5_rmw(DEV2G5_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
- DEV2G5_MAC_MAXLEN_CFG_MAX_LEN,
- sparx5,
- DEV2G5_MAC_MAXLEN_CFG(port->portno));
-
- /* 1G/2G5: Signal Detect configuration */
- spx5_wr(DEV2G5_PCS1G_SD_CFG_SD_POL_SET(sd_pol) |
- DEV2G5_PCS1G_SD_CFG_SD_SEL_SET(sd_sel) |
- DEV2G5_PCS1G_SD_CFG_SD_ENA_SET(sd_ena),
- sparx5,
- DEV2G5_PCS1G_SD_CFG(port->portno));
-
/* Set Pause WM hysteresis */
spx5_rmw(QSYS_PAUSE_CFG_PAUSE_START_SET(pause_start) |
QSYS_PAUSE_CFG_PAUSE_STOP_SET(pause_stop) |
@@ -1108,6 +1106,27 @@ int sparx5_port_init(struct sparx5 *sparx5,
ANA_CL_FILTER_CTRL_FILTER_SMAC_MC_DIS,
sparx5, ANA_CL_FILTER_CTRL(port->portno));
+ if (ops->is_port_rgmii(port->portno))
+ return 0; /* RGMII device - nothing more to configure */
+
+ /* Configure MAC vlan awareness */
+ err = sparx5_port_max_tags_set(sparx5, port);
+ if (err)
+ return err;
+
+ /* Set Max Length */
+ spx5_rmw(DEV2G5_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
+ DEV2G5_MAC_MAXLEN_CFG_MAX_LEN,
+ sparx5,
+ DEV2G5_MAC_MAXLEN_CFG(port->portno));
+
+ /* 1G/2G5: Signal Detect configuration */
+ spx5_wr(DEV2G5_PCS1G_SD_CFG_SD_POL_SET(sd_pol) |
+ DEV2G5_PCS1G_SD_CFG_SD_SEL_SET(sd_sel) |
+ DEV2G5_PCS1G_SD_CFG_SD_ENA_SET(sd_ena),
+ sparx5,
+ DEV2G5_PCS1G_SD_CFG(port->portno));
+
if (conf->portmode == PHY_INTERFACE_MODE_QSGMII ||
conf->portmode == PHY_INTERFACE_MODE_SGMII) {
err = sparx5_serdes_set(sparx5, port, conf);
@@ -1151,7 +1170,7 @@ int sparx5_port_init(struct sparx5 *sparx5,
spx5_inst_rmw(DEV10G_MAC_MAXLEN_CFG_MAX_LEN_SET(ETH_MAXLEN),
DEV10G_MAC_MAXLEN_CFG_MAX_LEN,
devinst,
- DEV10G_MAC_ENA_CFG(0));
+ DEV10G_MAC_MAXLEN_CFG(0));
/* Handle Signal Detect in 10G PCS */
spx5_inst_wr(PCS10G_BR_PCS_SD_CFG_SD_POL_SET(sd_pol) |
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_port.h b/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
index 9b9bcc6834bc..c8a37468a3d1 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_port.h
@@ -40,6 +40,11 @@ static inline bool sparx5_port_is_25g(int portno)
return portno >= 56 && portno <= 63;
}
+static inline bool sparx5_port_is_rgmii(int portno)
+{
+ return false;
+}
+
static inline u32 sparx5_to_high_dev(struct sparx5 *sparx5, int port)
{
const struct sparx5_ops *ops = sparx5->data->ops;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c
index 1c2903700a9c..2f168700f63c 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_ptp.c
@@ -303,7 +303,6 @@ void sparx5_get_hwtimestamp(struct sparx5 *sparx5,
spin_unlock_irqrestore(&sparx5->ptp_clock_lock, flags);
}
-EXPORT_SYMBOL_GPL(sparx5_get_hwtimestamp);
irqreturn_t sparx5_ptp_irq_handler(int irq, void *args)
{
diff --git a/drivers/net/ethernet/microsoft/mana/gdma_main.c b/drivers/net/ethernet/microsoft/mana/gdma_main.c
index e97af7ac2bb2..2dc0c6ad54be 100644
--- a/drivers/net/ethernet/microsoft/mana/gdma_main.c
+++ b/drivers/net/ethernet/microsoft/mana/gdma_main.c
@@ -177,7 +177,7 @@ int mana_gd_send_request(struct gdma_context *gc, u32 req_len, const void *req,
return mana_hwc_send_request(hwc, req_len, req, resp_len, resp);
}
-EXPORT_SYMBOL_NS(mana_gd_send_request, NET_MANA);
+EXPORT_SYMBOL_NS(mana_gd_send_request, "NET_MANA");
int mana_gd_alloc_memory(struct gdma_context *gc, unsigned int length,
struct gdma_mem_info *gmi)
@@ -716,7 +716,7 @@ int mana_gd_destroy_dma_region(struct gdma_context *gc, u64 dma_region_handle)
return 0;
}
-EXPORT_SYMBOL_NS(mana_gd_destroy_dma_region, NET_MANA);
+EXPORT_SYMBOL_NS(mana_gd_destroy_dma_region, "NET_MANA");
static int mana_gd_create_dma_region(struct gdma_dev *gd,
struct gdma_mem_info *gmi)
@@ -820,7 +820,7 @@ free_q:
kfree(queue);
return err;
}
-EXPORT_SYMBOL_NS(mana_gd_create_mana_eq, NET_MANA);
+EXPORT_SYMBOL_NS(mana_gd_create_mana_eq, "NET_MANA");
int mana_gd_create_mana_wq_cq(struct gdma_dev *gd,
const struct gdma_queue_spec *spec,
@@ -897,7 +897,7 @@ void mana_gd_destroy_queue(struct gdma_context *gc, struct gdma_queue *queue)
mana_gd_free_memory(gmi);
kfree(queue);
}
-EXPORT_SYMBOL_NS(mana_gd_destroy_queue, NET_MANA);
+EXPORT_SYMBOL_NS(mana_gd_destroy_queue, "NET_MANA");
int mana_gd_verify_vf_version(struct pci_dev *pdev)
{
@@ -974,7 +974,7 @@ int mana_gd_register_device(struct gdma_dev *gd)
return 0;
}
-EXPORT_SYMBOL_NS(mana_gd_register_device, NET_MANA);
+EXPORT_SYMBOL_NS(mana_gd_register_device, "NET_MANA");
int mana_gd_deregister_device(struct gdma_dev *gd)
{
@@ -1005,7 +1005,7 @@ int mana_gd_deregister_device(struct gdma_dev *gd)
return err;
}
-EXPORT_SYMBOL_NS(mana_gd_deregister_device, NET_MANA);
+EXPORT_SYMBOL_NS(mana_gd_deregister_device, "NET_MANA");
u32 mana_gd_wq_avail_space(struct gdma_queue *wq)
{
@@ -1318,7 +1318,7 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
GFP_KERNEL);
if (!gc->irq_contexts) {
err = -ENOMEM;
- goto free_irq_vector;
+ goto free_irq_array;
}
for (i = 0; i < nvec; i++) {
@@ -1375,6 +1375,7 @@ static int mana_gd_setup_irqs(struct pci_dev *pdev)
gc->max_num_msix = nvec;
gc->num_msix_usable = nvec;
cpus_read_unlock();
+ kfree(irqs);
return 0;
free_irq:
@@ -1387,8 +1388,9 @@ free_irq:
}
kfree(gc->irq_contexts);
- kfree(irqs);
gc->irq_contexts = NULL;
+free_irq_array:
+ kfree(irqs);
free_irq_vector:
cpus_read_unlock();
pci_free_irq_vectors(pdev);
diff --git a/drivers/net/ethernet/microsoft/mana/mana_en.c b/drivers/net/ethernet/microsoft/mana/mana_en.c
index 57ac732e7707..aa1e47233fe5 100644
--- a/drivers/net/ethernet/microsoft/mana/mana_en.c
+++ b/drivers/net/ethernet/microsoft/mana/mana_en.c
@@ -1022,7 +1022,7 @@ void mana_uncfg_vport(struct mana_port_context *apc)
WARN_ON(apc->vport_use_count < 0);
mutex_unlock(&apc->vport_mutex);
}
-EXPORT_SYMBOL_NS(mana_uncfg_vport, NET_MANA);
+EXPORT_SYMBOL_NS(mana_uncfg_vport, "NET_MANA");
int mana_cfg_vport(struct mana_port_context *apc, u32 protection_dom_id,
u32 doorbell_pg_id)
@@ -1092,7 +1092,7 @@ out:
return err;
}
-EXPORT_SYMBOL_NS(mana_cfg_vport, NET_MANA);
+EXPORT_SYMBOL_NS(mana_cfg_vport, "NET_MANA");
static int mana_cfg_vport_steering(struct mana_port_context *apc,
enum TRI_STATE rx,
@@ -1214,7 +1214,7 @@ int mana_create_wq_obj(struct mana_port_context *apc,
out:
return err;
}
-EXPORT_SYMBOL_NS(mana_create_wq_obj, NET_MANA);
+EXPORT_SYMBOL_NS(mana_create_wq_obj, "NET_MANA");
void mana_destroy_wq_obj(struct mana_port_context *apc, u32 wq_type,
mana_handle_t wq_obj)
@@ -1242,7 +1242,7 @@ void mana_destroy_wq_obj(struct mana_port_context *apc, u32 wq_type,
netdev_err(ndev, "Failed to destroy WQ object: %d, 0x%x\n", err,
resp.hdr.status);
}
-EXPORT_SYMBOL_NS(mana_destroy_wq_obj, NET_MANA);
+EXPORT_SYMBOL_NS(mana_destroy_wq_obj, "NET_MANA");
static void mana_destroy_eq(struct mana_context *ac)
{
@@ -2536,6 +2536,7 @@ void mana_query_gf_stats(struct mana_port_context *apc)
mana_gd_init_req_hdr(&req.hdr, MANA_QUERY_GF_STAT,
sizeof(req), sizeof(resp));
+ req.hdr.resp.msg_version = GDMA_MESSAGE_V2;
req.req_stats = STATISTICS_FLAGS_RX_DISCARDS_NO_WQE |
STATISTICS_FLAGS_RX_ERRORS_VPORT_DISABLED |
STATISTICS_FLAGS_HC_RX_BYTES |
@@ -3147,4 +3148,4 @@ struct net_device *mana_get_primary_netdev_rcu(struct mana_context *ac, u32 port
return ndev;
}
-EXPORT_SYMBOL_NS(mana_get_primary_netdev_rcu, NET_MANA);
+EXPORT_SYMBOL_NS(mana_get_primary_netdev_rcu, "NET_MANA");
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index 3d72aa7b1305..ef93df520887 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -1432,7 +1432,7 @@ void ocelot_ifh_set_basic(void *ifh, struct ocelot *ocelot, int port,
memset(ifh, 0, OCELOT_TAG_LEN);
ocelot_ifh_set_bypass(ifh, 1);
- ocelot_ifh_set_src(ifh, BIT_ULL(ocelot->num_phys_ports));
+ ocelot_ifh_set_src(ifh, ocelot->num_phys_ports);
ocelot_ifh_set_dest(ifh, BIT_ULL(port));
ocelot_ifh_set_qos_class(ifh, qos_class);
ocelot_ifh_set_tag_type(ifh, tag_type);
diff --git a/drivers/net/ethernet/mscc/ocelot_net.c b/drivers/net/ethernet/mscc/ocelot_net.c
index 558e03301aa8..8d48468cddd7 100644
--- a/drivers/net/ethernet/mscc/ocelot_net.c
+++ b/drivers/net/ethernet/mscc/ocelot_net.c
@@ -758,12 +758,13 @@ static int ocelot_port_fdb_do_dump(const unsigned char *addr, u16 vid,
bool is_static, void *data)
{
struct ocelot_dump_ctx *dump = data;
+ struct ndo_fdb_dump_context *ctx = (void *)dump->cb->ctx;
u32 portid = NETLINK_CB(dump->cb->skb).portid;
u32 seq = dump->cb->nlh->nlmsg_seq;
struct nlmsghdr *nlh;
struct ndmsg *ndm;
- if (dump->idx < dump->cb->args[2])
+ if (dump->idx < ctx->fdb_idx)
goto skip;
nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
diff --git a/drivers/net/ethernet/mscc/ocelot_ptp.c b/drivers/net/ethernet/mscc/ocelot_ptp.c
index e172638b0601..808ce8e68d39 100644
--- a/drivers/net/ethernet/mscc/ocelot_ptp.c
+++ b/drivers/net/ethernet/mscc/ocelot_ptp.c
@@ -14,6 +14,8 @@
#include <soc/mscc/ocelot.h>
#include "ocelot.h"
+#define OCELOT_PTP_TX_TSTAMP_TIMEOUT (5 * HZ)
+
int ocelot_ptp_gettime64(struct ptp_clock_info *ptp, struct timespec64 *ts)
{
struct ocelot *ocelot = container_of(ptp, struct ocelot, ptp_info);
@@ -495,6 +497,28 @@ static int ocelot_traps_to_ptp_rx_filter(unsigned int proto)
return HWTSTAMP_FILTER_NONE;
}
+static int ocelot_ptp_tx_type_to_cmd(int tx_type, int *ptp_cmd)
+{
+ switch (tx_type) {
+ case HWTSTAMP_TX_ON:
+ *ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
+ break;
+ case HWTSTAMP_TX_ONESTEP_SYNC:
+ /* IFH_REW_OP_ONE_STEP_PTP updates the correctionField,
+ * what we need to update is the originTimestamp.
+ */
+ *ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
+ break;
+ case HWTSTAMP_TX_OFF:
+ *ptp_cmd = 0;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ return 0;
+}
+
int ocelot_hwstamp_get(struct ocelot *ocelot, int port, struct ifreq *ifr)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
@@ -521,30 +545,19 @@ EXPORT_SYMBOL(ocelot_hwstamp_get);
int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
+ int ptp_cmd, old_ptp_cmd = ocelot_port->ptp_cmd;
bool l2 = false, l4 = false;
struct hwtstamp_config cfg;
+ bool old_l2, old_l4;
int err;
if (copy_from_user(&cfg, ifr->ifr_data, sizeof(cfg)))
return -EFAULT;
/* Tx type sanity check */
- switch (cfg.tx_type) {
- case HWTSTAMP_TX_ON:
- ocelot_port->ptp_cmd = IFH_REW_OP_TWO_STEP_PTP;
- break;
- case HWTSTAMP_TX_ONESTEP_SYNC:
- /* IFH_REW_OP_ONE_STEP_PTP updates the correctional field, we
- * need to update the origin time.
- */
- ocelot_port->ptp_cmd = IFH_REW_OP_ORIGIN_PTP;
- break;
- case HWTSTAMP_TX_OFF:
- ocelot_port->ptp_cmd = 0;
- break;
- default:
- return -ERANGE;
- }
+ err = ocelot_ptp_tx_type_to_cmd(cfg.tx_type, &ptp_cmd);
+ if (err)
+ return err;
switch (cfg.rx_filter) {
case HWTSTAMP_FILTER_NONE:
@@ -569,13 +582,27 @@ int ocelot_hwstamp_set(struct ocelot *ocelot, int port, struct ifreq *ifr)
return -ERANGE;
}
+ old_l2 = ocelot_port->trap_proto & OCELOT_PROTO_PTP_L2;
+ old_l4 = ocelot_port->trap_proto & OCELOT_PROTO_PTP_L4;
+
err = ocelot_setup_ptp_traps(ocelot, port, l2, l4);
if (err)
return err;
+ ocelot_port->ptp_cmd = ptp_cmd;
+
cfg.rx_filter = ocelot_traps_to_ptp_rx_filter(ocelot_port->trap_proto);
- return copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg)) ? -EFAULT : 0;
+ if (copy_to_user(ifr->ifr_data, &cfg, sizeof(cfg))) {
+ err = -EFAULT;
+ goto out_restore_ptp_traps;
+ }
+
+ return 0;
+out_restore_ptp_traps:
+ ocelot_setup_ptp_traps(ocelot, port, old_l2, old_l4);
+ ocelot_port->ptp_cmd = old_ptp_cmd;
+ return err;
}
EXPORT_SYMBOL(ocelot_hwstamp_set);
@@ -603,34 +630,87 @@ int ocelot_get_ts_info(struct ocelot *ocelot, int port,
}
EXPORT_SYMBOL(ocelot_get_ts_info);
-static int ocelot_port_add_txtstamp_skb(struct ocelot *ocelot, int port,
- struct sk_buff *clone)
+static struct sk_buff *ocelot_port_dequeue_ptp_tx_skb(struct ocelot *ocelot,
+ int port, u8 ts_id,
+ u32 seqid)
{
struct ocelot_port *ocelot_port = ocelot->ports[port];
- unsigned long flags;
+ struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
+ struct ptp_header *hdr;
- spin_lock_irqsave(&ocelot->ts_id_lock, flags);
+ spin_lock(&ocelot->ts_id_lock);
- if (ocelot_port->ptp_skbs_in_flight == OCELOT_MAX_PTP_ID ||
- ocelot->ptp_skbs_in_flight == OCELOT_PTP_FIFO_SIZE) {
- spin_unlock_irqrestore(&ocelot->ts_id_lock, flags);
- return -EBUSY;
+ skb_queue_walk_safe(&ocelot_port->tx_skbs, skb, skb_tmp) {
+ if (OCELOT_SKB_CB(skb)->ts_id != ts_id)
+ continue;
+
+ /* Check that the timestamp ID is for the expected PTP
+ * sequenceId. We don't have to test ptp_parse_header() against
+ * NULL, because we've pre-validated the packet's ptp_class.
+ */
+ hdr = ptp_parse_header(skb, OCELOT_SKB_CB(skb)->ptp_class);
+ if (seqid != ntohs(hdr->sequence_id))
+ continue;
+
+ __skb_unlink(skb, &ocelot_port->tx_skbs);
+ ocelot->ptp_skbs_in_flight--;
+ skb_match = skb;
+ break;
}
- skb_shinfo(clone)->tx_flags |= SKBTX_IN_PROGRESS;
- /* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
- OCELOT_SKB_CB(clone)->ts_id = ocelot_port->ts_id;
+ spin_unlock(&ocelot->ts_id_lock);
- ocelot_port->ts_id++;
- if (ocelot_port->ts_id == OCELOT_MAX_PTP_ID)
- ocelot_port->ts_id = 0;
+ return skb_match;
+}
+
+static int ocelot_port_queue_ptp_tx_skb(struct ocelot *ocelot, int port,
+ struct sk_buff *clone)
+{
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
+ DECLARE_BITMAP(ts_id_in_flight, OCELOT_MAX_PTP_ID);
+ struct sk_buff *skb, *skb_tmp;
+ unsigned long n;
+
+ spin_lock(&ocelot->ts_id_lock);
+
+ /* To get a better chance of acquiring a timestamp ID, first flush the
+ * stale packets still waiting in the TX timestamping queue. They are
+ * probably lost.
+ */
+ skb_queue_walk_safe(&ocelot_port->tx_skbs, skb, skb_tmp) {
+ if (time_before(OCELOT_SKB_CB(skb)->ptp_tx_time +
+ OCELOT_PTP_TX_TSTAMP_TIMEOUT, jiffies)) {
+ dev_warn_ratelimited(ocelot->dev,
+ "port %d invalidating stale timestamp ID %u which seems lost\n",
+ port, OCELOT_SKB_CB(skb)->ts_id);
+ __skb_unlink(skb, &ocelot_port->tx_skbs);
+ kfree_skb(skb);
+ ocelot->ptp_skbs_in_flight--;
+ } else {
+ __set_bit(OCELOT_SKB_CB(skb)->ts_id, ts_id_in_flight);
+ }
+ }
+
+ if (ocelot->ptp_skbs_in_flight == OCELOT_PTP_FIFO_SIZE) {
+ spin_unlock(&ocelot->ts_id_lock);
+ return -EBUSY;
+ }
+
+ n = find_first_zero_bit(ts_id_in_flight, OCELOT_MAX_PTP_ID);
+ if (n == OCELOT_MAX_PTP_ID) {
+ spin_unlock(&ocelot->ts_id_lock);
+ return -EBUSY;
+ }
- ocelot_port->ptp_skbs_in_flight++;
+ /* Found an available timestamp ID, use it */
+ OCELOT_SKB_CB(clone)->ts_id = n;
+ OCELOT_SKB_CB(clone)->ptp_tx_time = jiffies;
ocelot->ptp_skbs_in_flight++;
+ __skb_queue_tail(&ocelot_port->tx_skbs, clone);
- skb_queue_tail(&ocelot_port->tx_skbs, clone);
+ spin_unlock(&ocelot->ts_id_lock);
- spin_unlock_irqrestore(&ocelot->ts_id_lock, flags);
+ dev_dbg_ratelimited(ocelot->dev, "port %d timestamp id %lu\n", port, n);
return 0;
}
@@ -687,10 +767,14 @@ int ocelot_port_txtstamp_request(struct ocelot *ocelot, int port,
if (!(*clone))
return -ENOMEM;
- err = ocelot_port_add_txtstamp_skb(ocelot, port, *clone);
- if (err)
+ /* Store timestamp ID in OCELOT_SKB_CB(clone)->ts_id */
+ err = ocelot_port_queue_ptp_tx_skb(ocelot, port, *clone);
+ if (err) {
+ kfree_skb(*clone);
return err;
+ }
+ skb_shinfo(*clone)->tx_flags |= SKBTX_IN_PROGRESS;
OCELOT_SKB_CB(skb)->ptp_cmd = ptp_cmd;
OCELOT_SKB_CB(*clone)->ptp_class = ptp_class;
}
@@ -726,28 +810,15 @@ static void ocelot_get_hwtimestamp(struct ocelot *ocelot,
spin_unlock_irqrestore(&ocelot->ptp_clock_lock, flags);
}
-static bool ocelot_validate_ptp_skb(struct sk_buff *clone, u16 seqid)
-{
- struct ptp_header *hdr;
-
- hdr = ptp_parse_header(clone, OCELOT_SKB_CB(clone)->ptp_class);
- if (WARN_ON(!hdr))
- return false;
-
- return seqid == ntohs(hdr->sequence_id);
-}
-
void ocelot_get_txtstamp(struct ocelot *ocelot)
{
int budget = OCELOT_PTP_QUEUE_SZ;
while (budget--) {
- struct sk_buff *skb, *skb_tmp, *skb_match = NULL;
struct skb_shared_hwtstamps shhwtstamps;
u32 val, id, seqid, txport;
- struct ocelot_port *port;
+ struct sk_buff *skb_match;
struct timespec64 ts;
- unsigned long flags;
val = ocelot_read(ocelot, SYS_PTP_STATUS);
@@ -762,36 +833,14 @@ void ocelot_get_txtstamp(struct ocelot *ocelot)
txport = SYS_PTP_STATUS_PTP_MESS_TXPORT_X(val);
seqid = SYS_PTP_STATUS_PTP_MESS_SEQ_ID(val);
- port = ocelot->ports[txport];
-
- spin_lock(&ocelot->ts_id_lock);
- port->ptp_skbs_in_flight--;
- ocelot->ptp_skbs_in_flight--;
- spin_unlock(&ocelot->ts_id_lock);
-
/* Retrieve its associated skb */
-try_again:
- spin_lock_irqsave(&port->tx_skbs.lock, flags);
-
- skb_queue_walk_safe(&port->tx_skbs, skb, skb_tmp) {
- if (OCELOT_SKB_CB(skb)->ts_id != id)
- continue;
- __skb_unlink(skb, &port->tx_skbs);
- skb_match = skb;
- break;
- }
-
- spin_unlock_irqrestore(&port->tx_skbs.lock, flags);
-
- if (WARN_ON(!skb_match))
- continue;
-
- if (!ocelot_validate_ptp_skb(skb_match, seqid)) {
- dev_err_ratelimited(ocelot->dev,
- "port %d received stale TX timestamp for seqid %d, discarding\n",
- txport, seqid);
- dev_kfree_skb_any(skb);
- goto try_again;
+ skb_match = ocelot_port_dequeue_ptp_tx_skb(ocelot, txport, id,
+ seqid);
+ if (!skb_match) {
+ dev_warn_ratelimited(ocelot->dev,
+ "port %d received TX timestamp (seqid %d, ts id %u) for packet previously declared stale\n",
+ txport, seqid, id);
+ goto next_ts;
}
/* Get the h/w timestamp */
@@ -802,7 +851,7 @@ try_again:
shhwtstamps.hwtstamp = ktime_set(ts.tv_sec, ts.tv_nsec);
skb_complete_tx_timestamp(skb_match, &shhwtstamps);
- /* Next ts */
+next_ts:
ocelot_write(ocelot, SYS_PTP_NXT_PTP_NXT, SYS_PTP_NXT);
}
}
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index 98e098c09c03..abba165738a3 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -2779,7 +2779,7 @@ static void nfp_net_netdev_init(struct nfp_net *nn)
break;
}
- netdev->watchdog_timeo = msecs_to_jiffies(5 * 1000);
+ netdev->watchdog_timeo = secs_to_jiffies(5);
/* MTU range: 68 - hw-specific max */
netdev->min_mtu = ETH_MIN_MTU;
diff --git a/drivers/net/ethernet/oa_tc6.c b/drivers/net/ethernet/oa_tc6.c
index f9c0dcd965c2..db200e4ec284 100644
--- a/drivers/net/ethernet/oa_tc6.c
+++ b/drivers/net/ethernet/oa_tc6.c
@@ -113,6 +113,7 @@ struct oa_tc6 {
struct mii_bus *mdiobus;
struct spi_device *spi;
struct mutex spi_ctrl_lock; /* Protects spi control transfer */
+ spinlock_t tx_skb_lock; /* Protects tx skb handling */
void *spi_ctrl_tx_buf;
void *spi_ctrl_rx_buf;
void *spi_data_tx_buf;
@@ -1004,8 +1005,10 @@ static u16 oa_tc6_prepare_spi_tx_buf_for_tx_skbs(struct oa_tc6 *tc6)
for (used_tx_credits = 0; used_tx_credits < tc6->tx_credits;
used_tx_credits++) {
if (!tc6->ongoing_tx_skb) {
+ spin_lock_bh(&tc6->tx_skb_lock);
tc6->ongoing_tx_skb = tc6->waiting_tx_skb;
tc6->waiting_tx_skb = NULL;
+ spin_unlock_bh(&tc6->tx_skb_lock);
}
if (!tc6->ongoing_tx_skb)
break;
@@ -1111,8 +1114,9 @@ static int oa_tc6_spi_thread_handler(void *data)
/* This kthread will be waken up if there is a tx skb or mac-phy
* interrupt to perform spi transfer with tx chunks.
*/
- wait_event_interruptible(tc6->spi_wq, tc6->waiting_tx_skb ||
- tc6->int_flag ||
+ wait_event_interruptible(tc6->spi_wq, tc6->int_flag ||
+ (tc6->waiting_tx_skb &&
+ tc6->tx_credits) ||
kthread_should_stop());
if (kthread_should_stop())
@@ -1209,7 +1213,9 @@ netdev_tx_t oa_tc6_start_xmit(struct oa_tc6 *tc6, struct sk_buff *skb)
return NETDEV_TX_OK;
}
+ spin_lock_bh(&tc6->tx_skb_lock);
tc6->waiting_tx_skb = skb;
+ spin_unlock_bh(&tc6->tx_skb_lock);
/* Wake spi kthread to perform spi transfer */
wake_up_interruptible(&tc6->spi_wq);
@@ -1239,6 +1245,7 @@ struct oa_tc6 *oa_tc6_init(struct spi_device *spi, struct net_device *netdev)
tc6->netdev = netdev;
SET_NETDEV_DEV(netdev, &spi->dev);
mutex_init(&tc6->spi_ctrl_lock);
+ spin_lock_init(&tc6->tx_skb_lock);
/* Set the SPI controller to pump at realtime priority */
tc6->spi->rt = true;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic.h b/drivers/net/ethernet/pensando/ionic/ionic.h
index 1c61390677f7..04f00ea94230 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic.h
@@ -18,8 +18,6 @@ struct ionic_lif;
#define PCI_DEVICE_ID_PENSANDO_IONIC_ETH_PF 0x1002
#define PCI_DEVICE_ID_PENSANDO_IONIC_ETH_VF 0x1003
-#define IONIC_ASIC_TYPE_ELBA 2
-
#define DEVCMD_TIMEOUT 5
#define IONIC_ADMINQ_TIME_SLICE msecs_to_jiffies(100)
@@ -59,7 +57,6 @@ struct ionic {
DECLARE_BITMAP(intrs, IONIC_INTR_CTRL_REGS_MAX);
cpumask_var_t *affinity_masks;
struct delayed_work doorbell_check_dwork;
- struct work_struct nb_work;
struct notifier_block nb;
struct rw_semaphore vf_op_lock; /* lock for VF operations */
struct ionic_vf *vfs;
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.c b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
index 9e42d599840d..57edcde9e6f8 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.c
@@ -277,7 +277,10 @@ void ionic_dev_teardown(struct ionic *ionic)
idev->phy_cmb_pages = 0;
idev->cmb_npages = 0;
- destroy_workqueue(ionic->wq);
+ if (ionic->wq) {
+ destroy_workqueue(ionic->wq);
+ ionic->wq = NULL;
+ }
mutex_destroy(&idev->cmb_inuse_lock);
}
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
index dda22fa4448c..a2d4336d2766 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c
@@ -158,6 +158,20 @@ static int ionic_get_link_ksettings(struct net_device *netdev,
25000baseCR_Full);
copper_seen++;
break;
+ case IONIC_XCVR_PID_QSFP_50G_CR2_FC:
+ case IONIC_XCVR_PID_QSFP_50G_CR2:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 50000baseCR2_Full);
+ copper_seen++;
+ break;
+ case IONIC_XCVR_PID_QSFP_200G_CR4:
+ ethtool_link_ksettings_add_link_mode(ks, supported, 200000baseCR4_Full);
+ copper_seen++;
+ break;
+ case IONIC_XCVR_PID_QSFP_400G_CR4:
+ ethtool_link_ksettings_add_link_mode(ks, supported, 400000baseCR4_Full);
+ copper_seen++;
+ break;
case IONIC_XCVR_PID_SFP_10GBASE_AOC:
case IONIC_XCVR_PID_SFP_10GBASE_CU:
ethtool_link_ksettings_add_link_mode(ks, supported,
@@ -196,6 +210,31 @@ static int ionic_get_link_ksettings(struct net_device *netdev,
ethtool_link_ksettings_add_link_mode(ks, supported,
25000baseSR_Full);
break;
+ case IONIC_XCVR_PID_QSFP_200G_AOC:
+ case IONIC_XCVR_PID_QSFP_200G_SR4:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 200000baseSR4_Full);
+ break;
+ case IONIC_XCVR_PID_QSFP_200G_FR4:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 200000baseLR4_ER4_FR4_Full);
+ break;
+ case IONIC_XCVR_PID_QSFP_200G_DR4:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 200000baseDR4_Full);
+ break;
+ case IONIC_XCVR_PID_QSFP_400G_FR4:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 400000baseLR4_ER4_FR4_Full);
+ break;
+ case IONIC_XCVR_PID_QSFP_400G_DR4:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 400000baseDR4_Full);
+ break;
+ case IONIC_XCVR_PID_QSFP_400G_SR4:
+ ethtool_link_ksettings_add_link_mode(ks, supported,
+ 400000baseSR4_Full);
+ break;
case IONIC_XCVR_PID_SFP_10GBASE_SR:
ethtool_link_ksettings_add_link_mode(ks, supported,
10000baseSR_Full);
@@ -929,6 +968,7 @@ static int ionic_get_module_info(struct net_device *netdev,
break;
case SFF8024_ID_QSFP_8436_8636:
case SFF8024_ID_QSFP28_8636:
+ case SFF8024_ID_QSFP_PLUS_CMIS:
modinfo->type = ETH_MODULE_SFF_8436;
modinfo->eeprom_len = ETH_MODULE_SFF_8436_LEN;
break;
@@ -961,8 +1001,8 @@ static int ionic_get_module_eeprom(struct net_device *netdev,
len = min_t(u32, sizeof(xcvr->sprom), ee->len);
do {
- memcpy(data, xcvr->sprom, len);
- memcpy(tbuf, xcvr->sprom, len);
+ memcpy(data, &xcvr->sprom[ee->offset], len);
+ memcpy(tbuf, &xcvr->sprom[ee->offset], len);
/* Let's make sure we got a consistent copy */
if (!memcmp(data, tbuf, len))
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_if.h b/drivers/net/ethernet/pensando/ionic/ionic_if.h
index 9c85c0706c6e..830c8adbfbee 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_if.h
+++ b/drivers/net/ethernet/pensando/ionic/ionic_if.h
@@ -1277,7 +1277,10 @@ enum ionic_xcvr_pid {
IONIC_XCVR_PID_SFP_25GBASE_CR_S = 3,
IONIC_XCVR_PID_SFP_25GBASE_CR_L = 4,
IONIC_XCVR_PID_SFP_25GBASE_CR_N = 5,
-
+ IONIC_XCVR_PID_QSFP_50G_CR2_FC = 6,
+ IONIC_XCVR_PID_QSFP_50G_CR2 = 7,
+ IONIC_XCVR_PID_QSFP_200G_CR4 = 8,
+ IONIC_XCVR_PID_QSFP_400G_CR4 = 9,
/* Fiber */
IONIC_XCVR_PID_QSFP_100G_AOC = 50,
IONIC_XCVR_PID_QSFP_100G_ACC = 51,
@@ -1303,6 +1306,15 @@ enum ionic_xcvr_pid {
IONIC_XCVR_PID_SFP_25GBASE_ACC = 71,
IONIC_XCVR_PID_SFP_10GBASE_T = 72,
IONIC_XCVR_PID_SFP_1000BASE_T = 73,
+ IONIC_XCVR_PID_QSFP_200G_AOC = 74,
+ IONIC_XCVR_PID_QSFP_200G_FR4 = 75,
+ IONIC_XCVR_PID_QSFP_200G_DR4 = 76,
+ IONIC_XCVR_PID_QSFP_200G_SR4 = 77,
+ IONIC_XCVR_PID_QSFP_200G_ACC = 78,
+ IONIC_XCVR_PID_QSFP_400G_FR4 = 79,
+ IONIC_XCVR_PID_QSFP_400G_DR4 = 80,
+ IONIC_XCVR_PID_QSFP_400G_SR4 = 81,
+ IONIC_XCVR_PID_QSFP_400G_VR4 = 82,
};
/**
@@ -1404,6 +1416,8 @@ struct ionic_xcvr_status {
*/
union ionic_port_config {
struct {
+#define IONIC_SPEED_400G 400000 /* 400G in Mbps */
+#define IONIC_SPEED_200G 200000 /* 200G in Mbps */
#define IONIC_SPEED_100G 100000 /* 100G in Mbps */
#define IONIC_SPEED_50G 50000 /* 50G in Mbps */
#define IONIC_SPEED_40G 40000 /* 40G in Mbps */
@@ -3209,7 +3223,11 @@ union ionic_adminq_comp {
#define IONIC_BAR0_INTR_CTRL_OFFSET 0x2000
#define IONIC_DEV_CMD_DONE 0x00000001
-#define IONIC_ASIC_TYPE_CAPRI 0
+#define IONIC_ASIC_TYPE_NONE 0
+#define IONIC_ASIC_TYPE_CAPRI 1
+#define IONIC_ASIC_TYPE_ELBA 2
+#define IONIC_ASIC_TYPE_GIGLIO 3
+#define IONIC_ASIC_TYPE_SALINA 4
/**
* struct ionic_doorbell - Doorbell register layout
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
index 40496587b2b3..7707a9e53c43 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c
@@ -3265,7 +3265,7 @@ int ionic_lif_alloc(struct ionic *ionic)
lif->netdev->min_mtu = max_t(unsigned int, ETH_MIN_MTU,
le32_to_cpu(lif->identity->eth.min_frame_size));
lif->netdev->max_mtu =
- le32_to_cpu(lif->identity->eth.max_frame_size) - ETH_HLEN - VLAN_HLEN;
+ le32_to_cpu(lif->identity->eth.max_frame_size) - VLAN_ETH_HLEN;
lif->neqs = ionic->neqs_per_lif;
lif->nxqs = ionic->ntxqs_per_lif;
@@ -3804,10 +3804,6 @@ err_out_adminq_deinit:
return err;
}
-static void ionic_lif_notify_work(struct work_struct *ws)
-{
-}
-
static void ionic_lif_set_netdev_info(struct ionic_lif *lif)
{
struct ionic_admin_ctx ctx = {
@@ -3858,8 +3854,6 @@ int ionic_lif_register(struct ionic_lif *lif)
ionic_lif_register_phc(lif);
- INIT_WORK(&lif->ionic->nb_work, ionic_lif_notify_work);
-
lif->ionic->nb.notifier_call = ionic_lif_notify;
err = register_netdevice_notifier(&lif->ionic->nb);
@@ -3869,8 +3863,8 @@ int ionic_lif_register(struct ionic_lif *lif)
/* only register LIF0 for now */
err = register_netdev(lif->netdev);
if (err) {
- dev_err(lif->ionic->dev, "Cannot register net device, aborting\n");
- ionic_lif_unregister_phc(lif);
+ dev_err(lif->ionic->dev, "Cannot register net device: %d, aborting\n", err);
+ ionic_lif_unregister(lif);
return err;
}
@@ -3885,7 +3879,6 @@ void ionic_lif_unregister(struct ionic_lif *lif)
{
if (lif->ionic->nb.notifier_call) {
unregister_netdevice_notifier(&lif->ionic->nb);
- cancel_work_sync(&lif->ionic->nb_work);
lif->ionic->nb.notifier_call = NULL;
}
diff --git a/drivers/net/ethernet/pensando/ionic/ionic_main.c b/drivers/net/ethernet/pensando/ionic/ionic_main.c
index 0f817c3f92d8..daf1e82cb76b 100644
--- a/drivers/net/ethernet/pensando/ionic/ionic_main.c
+++ b/drivers/net/ethernet/pensando/ionic/ionic_main.c
@@ -81,8 +81,9 @@ static int ionic_error_to_errno(enum ionic_status_code code)
case IONIC_RC_EQTYPE:
case IONIC_RC_EQID:
case IONIC_RC_EINVAL:
- case IONIC_RC_ENOSUPP:
return -EINVAL;
+ case IONIC_RC_ENOSUPP:
+ return -EOPNOTSUPP;
case IONIC_RC_EPERM:
return -EPERM;
case IONIC_RC_ENOENT:
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 9cff0a8ffb2c..3383ee1dad14 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -2832,7 +2832,7 @@ netxen_sysfs_validate_crb(struct netxen_adapter *adapter,
static ssize_t
netxen_sysfs_read_crb(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset, size_t size)
{
struct device *dev = kobj_to_dev(kobj);
@@ -2860,7 +2860,7 @@ netxen_sysfs_read_crb(struct file *filp, struct kobject *kobj,
static ssize_t
netxen_sysfs_write_crb(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset, size_t size)
{
struct device *dev = kobj_to_dev(kobj);
@@ -2901,7 +2901,7 @@ netxen_sysfs_validate_mem(struct netxen_adapter *adapter,
static ssize_t
netxen_sysfs_read_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset, size_t size)
{
struct device *dev = kobj_to_dev(kobj);
@@ -2922,7 +2922,7 @@ netxen_sysfs_read_mem(struct file *filp, struct kobject *kobj,
}
static ssize_t netxen_sysfs_write_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t offset, size_t size)
{
struct device *dev = kobj_to_dev(kobj);
@@ -2946,20 +2946,20 @@ static ssize_t netxen_sysfs_write_mem(struct file *filp, struct kobject *kobj,
static const struct bin_attribute bin_attr_crb = {
.attr = { .name = "crb", .mode = 0644 },
.size = 0,
- .read = netxen_sysfs_read_crb,
- .write = netxen_sysfs_write_crb,
+ .read_new = netxen_sysfs_read_crb,
+ .write_new = netxen_sysfs_write_crb,
};
static const struct bin_attribute bin_attr_mem = {
.attr = { .name = "mem", .mode = 0644 },
.size = 0,
- .read = netxen_sysfs_read_mem,
- .write = netxen_sysfs_write_mem,
+ .read_new = netxen_sysfs_read_mem,
+ .write_new = netxen_sysfs_write_mem,
};
static ssize_t
netxen_sysfs_read_dimm(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset, size_t size)
{
struct device *dev = kobj_to_dev(kobj);
@@ -3082,7 +3082,7 @@ out:
static const struct bin_attribute bin_attr_dimm = {
.attr = { .name = "dimm", .mode = 0644 },
.size = sizeof(struct netxen_dimm_cfg),
- .read = netxen_sysfs_read_dimm,
+ .read_new = netxen_sysfs_read_dimm,
};
diff --git a/drivers/net/ethernet/qlogic/qed/qed_mcp.c b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
index 26a714bfad4e..c7f497c36f66 100644
--- a/drivers/net/ethernet/qlogic/qed/qed_mcp.c
+++ b/drivers/net/ethernet/qlogic/qed/qed_mcp.c
@@ -3301,7 +3301,9 @@ int qed_mcp_bist_nvm_get_num_images(struct qed_hwfn *p_hwfn,
if (rc)
return rc;
- if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK))
+ if (((rsp & FW_MSG_CODE_MASK) == FW_MSG_CODE_UNSUPPORTED))
+ rc = -EOPNOTSUPP;
+ else if (((rsp & FW_MSG_CODE_MASK) != FW_MSG_CODE_OK))
rc = -EINVAL;
return rc;
@@ -3356,6 +3358,7 @@ int qed_mcp_nvm_info_populate(struct qed_hwfn *p_hwfn)
p_ptt, &nvm_info.num_images);
if (rc == -EOPNOTSUPP) {
DP_INFO(p_hwfn, "DRV_MSG_CODE_BIST_TEST is not supported\n");
+ nvm_info.num_images = 0;
goto out;
} else if (rc || !nvm_info.num_images) {
DP_ERR(p_hwfn, "Failed getting number of images\n");
diff --git a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
index 74125188beb8..c0f20464fd1e 100644
--- a/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
+++ b/drivers/net/ethernet/qlogic/qlcnic/qlcnic_sysfs.c
@@ -264,7 +264,7 @@ static int qlcnic_sysfs_validate_crb(struct qlcnic_adapter *adapter,
}
static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t offset, size_t size)
{
struct device *dev = kobj_to_dev(kobj);
@@ -281,7 +281,7 @@ static ssize_t qlcnic_sysfs_read_crb(struct file *filp, struct kobject *kobj,
}
static ssize_t qlcnic_sysfs_write_crb(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t offset, size_t size)
{
struct device *dev = kobj_to_dev(kobj);
@@ -310,7 +310,7 @@ static int qlcnic_sysfs_validate_mem(struct qlcnic_adapter *adapter,
}
static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t offset, size_t size)
{
struct device *dev = kobj_to_dev(kobj);
@@ -332,7 +332,7 @@ static ssize_t qlcnic_sysfs_read_mem(struct file *filp, struct kobject *kobj,
}
static ssize_t qlcnic_sysfs_write_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, char *buf,
+ const struct bin_attribute *attr, char *buf,
loff_t offset, size_t size)
{
struct device *dev = kobj_to_dev(kobj);
@@ -396,7 +396,7 @@ static int validate_pm_config(struct qlcnic_adapter *adapter,
static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -446,7 +446,7 @@ static ssize_t qlcnic_sysfs_write_pm_config(struct file *filp,
static ssize_t qlcnic_sysfs_read_pm_config(struct file *filp,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -539,7 +539,7 @@ static int validate_esw_config(struct qlcnic_adapter *adapter,
static ssize_t qlcnic_sysfs_write_esw_config(struct file *file,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -623,7 +623,7 @@ out:
static ssize_t qlcnic_sysfs_read_esw_config(struct file *file,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -675,7 +675,7 @@ static int validate_npar_config(struct qlcnic_adapter *adapter,
static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -722,7 +722,7 @@ static ssize_t qlcnic_sysfs_write_npar_config(struct file *file,
static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -769,7 +769,7 @@ static ssize_t qlcnic_sysfs_read_npar_config(struct file *file,
static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -804,7 +804,7 @@ static ssize_t qlcnic_sysfs_get_port_stats(struct file *file,
static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -839,7 +839,7 @@ static ssize_t qlcnic_sysfs_get_esw_stats(struct file *file,
static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -868,7 +868,7 @@ static ssize_t qlcnic_sysfs_clear_esw_stats(struct file *file,
static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -898,7 +898,7 @@ static ssize_t qlcnic_sysfs_clear_port_stats(struct file *file,
static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -938,7 +938,7 @@ static ssize_t qlcnic_sysfs_read_pci_config(struct file *file,
static ssize_t qlcnic_83xx_sysfs_flash_read_handler(struct file *filp,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -1115,7 +1115,7 @@ static int qlcnic_83xx_sysfs_flash_write(struct qlcnic_adapter *adapter,
static ssize_t qlcnic_83xx_sysfs_flash_write_handler(struct file *filp,
struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
char *buf, loff_t offset,
size_t size)
{
@@ -1195,64 +1195,63 @@ static const struct device_attribute dev_attr_beacon = {
static const struct bin_attribute bin_attr_crb = {
.attr = { .name = "crb", .mode = 0644 },
.size = 0,
- .read = qlcnic_sysfs_read_crb,
- .write = qlcnic_sysfs_write_crb,
+ .read_new = qlcnic_sysfs_read_crb,
+ .write_new = qlcnic_sysfs_write_crb,
};
static const struct bin_attribute bin_attr_mem = {
.attr = { .name = "mem", .mode = 0644 },
.size = 0,
- .read = qlcnic_sysfs_read_mem,
- .write = qlcnic_sysfs_write_mem,
+ .read_new = qlcnic_sysfs_read_mem,
+ .write_new = qlcnic_sysfs_write_mem,
};
static const struct bin_attribute bin_attr_npar_config = {
.attr = { .name = "npar_config", .mode = 0644 },
.size = 0,
- .read = qlcnic_sysfs_read_npar_config,
- .write = qlcnic_sysfs_write_npar_config,
+ .read_new = qlcnic_sysfs_read_npar_config,
+ .write_new = qlcnic_sysfs_write_npar_config,
};
static const struct bin_attribute bin_attr_pci_config = {
.attr = { .name = "pci_config", .mode = 0644 },
.size = 0,
- .read = qlcnic_sysfs_read_pci_config,
- .write = NULL,
+ .read_new = qlcnic_sysfs_read_pci_config,
};
static const struct bin_attribute bin_attr_port_stats = {
.attr = { .name = "port_stats", .mode = 0644 },
.size = 0,
- .read = qlcnic_sysfs_get_port_stats,
- .write = qlcnic_sysfs_clear_port_stats,
+ .read_new = qlcnic_sysfs_get_port_stats,
+ .write_new = qlcnic_sysfs_clear_port_stats,
};
static const struct bin_attribute bin_attr_esw_stats = {
.attr = { .name = "esw_stats", .mode = 0644 },
.size = 0,
- .read = qlcnic_sysfs_get_esw_stats,
- .write = qlcnic_sysfs_clear_esw_stats,
+ .read_new = qlcnic_sysfs_get_esw_stats,
+ .write_new = qlcnic_sysfs_clear_esw_stats,
};
static const struct bin_attribute bin_attr_esw_config = {
.attr = { .name = "esw_config", .mode = 0644 },
.size = 0,
- .read = qlcnic_sysfs_read_esw_config,
- .write = qlcnic_sysfs_write_esw_config,
+ .read_new = qlcnic_sysfs_read_esw_config,
+ .write_new = qlcnic_sysfs_write_esw_config,
};
static const struct bin_attribute bin_attr_pm_config = {
.attr = { .name = "pm_config", .mode = 0644 },
.size = 0,
- .read = qlcnic_sysfs_read_pm_config,
- .write = qlcnic_sysfs_write_pm_config,
+ .read_new = qlcnic_sysfs_read_pm_config,
+ .write_new = qlcnic_sysfs_write_pm_config,
};
static const struct bin_attribute bin_attr_flash = {
.attr = { .name = "flash", .mode = 0644 },
.size = 0,
- .read = qlcnic_83xx_sysfs_flash_read_handler,
- .write = qlcnic_83xx_sysfs_flash_write_handler,
+ .read_new = qlcnic_83xx_sysfs_flash_read_handler,
+ .write_new = qlcnic_83xx_sysfs_flash_write_handler,
};
#ifdef CONFIG_QLCNIC_HWMON
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.c b/drivers/net/ethernet/qualcomm/qca_spi.c
index ef9c02b000e4..38a779f4b866 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.c
+++ b/drivers/net/ethernet/qualcomm/qca_spi.c
@@ -54,7 +54,7 @@ MODULE_PARM_DESC(qcaspi_burst_len, "Number of data bytes per burst. Use 1-5000."
#define QCASPI_PLUGGABLE_MIN 0
#define QCASPI_PLUGGABLE_MAX 1
-static int qcaspi_pluggable = QCASPI_PLUGGABLE_MIN;
+static int qcaspi_pluggable = QCASPI_PLUGGABLE_MAX;
module_param(qcaspi_pluggable, int, 0);
MODULE_PARM_DESC(qcaspi_pluggable, "Pluggable SPI connection (yes/no).");
@@ -818,7 +818,6 @@ qcaspi_netdev_init(struct net_device *dev)
dev->mtu = QCAFRM_MAX_MTU;
dev->type = ARPHRD_ETHER;
- qca->clkspeed = qcaspi_clkspeed;
qca->burst_len = qcaspi_burst_len;
qca->spi_thread = NULL;
qca->buffer_size = (QCAFRM_MAX_MTU + VLAN_ETH_HLEN + QCAFRM_HEADER_LEN +
@@ -909,17 +908,15 @@ qca_spi_probe(struct spi_device *spi)
legacy_mode = of_property_read_bool(spi->dev.of_node,
"qca,legacy-mode");
- if (qcaspi_clkspeed == 0) {
- if (spi->max_speed_hz)
- qcaspi_clkspeed = spi->max_speed_hz;
- else
- qcaspi_clkspeed = QCASPI_CLK_SPEED;
- }
+ if (qcaspi_clkspeed)
+ spi->max_speed_hz = qcaspi_clkspeed;
+ else if (!spi->max_speed_hz)
+ spi->max_speed_hz = QCASPI_CLK_SPEED;
- if ((qcaspi_clkspeed < QCASPI_CLK_SPEED_MIN) ||
- (qcaspi_clkspeed > QCASPI_CLK_SPEED_MAX)) {
- dev_err(&spi->dev, "Invalid clkspeed: %d\n",
- qcaspi_clkspeed);
+ if (spi->max_speed_hz < QCASPI_CLK_SPEED_MIN ||
+ spi->max_speed_hz > QCASPI_CLK_SPEED_MAX) {
+ dev_err(&spi->dev, "Invalid clkspeed: %u\n",
+ spi->max_speed_hz);
return -EINVAL;
}
@@ -944,14 +941,13 @@ qca_spi_probe(struct spi_device *spi)
return -EINVAL;
}
- dev_info(&spi->dev, "ver=%s, clkspeed=%d, burst_len=%d, pluggable=%d\n",
+ dev_info(&spi->dev, "ver=%s, clkspeed=%u, burst_len=%d, pluggable=%d\n",
QCASPI_DRV_VERSION,
- qcaspi_clkspeed,
+ spi->max_speed_hz,
qcaspi_burst_len,
qcaspi_pluggable);
spi->mode = SPI_MODE_3;
- spi->max_speed_hz = qcaspi_clkspeed;
if (spi_setup(spi) < 0) {
dev_err(&spi->dev, "Unable to setup SPI device\n");
return -EFAULT;
diff --git a/drivers/net/ethernet/qualcomm/qca_spi.h b/drivers/net/ethernet/qualcomm/qca_spi.h
index 7ba5c9e2f61c..90b290f94c27 100644
--- a/drivers/net/ethernet/qualcomm/qca_spi.h
+++ b/drivers/net/ethernet/qualcomm/qca_spi.h
@@ -89,7 +89,6 @@ struct qcaspi {
#endif
/* user configurable options */
- u32 clkspeed;
u8 legacy_mode;
u16 burst_len;
};
diff --git a/drivers/net/ethernet/realtek/r8169.h b/drivers/net/ethernet/realtek/r8169.h
index 8904aae41aca..7a194a8ab989 100644
--- a/drivers/net/ethernet/realtek/r8169.h
+++ b/drivers/net/ethernet/realtek/r8169.h
@@ -71,6 +71,8 @@ enum mac_version {
RTL_GIGA_MAC_VER_64,
RTL_GIGA_MAC_VER_65,
RTL_GIGA_MAC_VER_66,
+ RTL_GIGA_MAC_VER_70,
+ RTL_GIGA_MAC_VER_71,
RTL_GIGA_MAC_NONE
};
diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c
index 6934bdee2a91..4b77f2151204 100644
--- a/drivers/net/ethernet/realtek/r8169_main.c
+++ b/drivers/net/ethernet/realtek/r8169_main.c
@@ -57,6 +57,8 @@
#define FIRMWARE_8125A_3 "rtl_nic/rtl8125a-3.fw"
#define FIRMWARE_8125B_2 "rtl_nic/rtl8125b-2.fw"
#define FIRMWARE_8125D_1 "rtl_nic/rtl8125d-1.fw"
+#define FIRMWARE_8125D_2 "rtl_nic/rtl8125d-2.fw"
+#define FIRMWARE_8125BP_2 "rtl_nic/rtl8125bp-2.fw"
#define FIRMWARE_8126A_2 "rtl_nic/rtl8126a-2.fw"
#define FIRMWARE_8126A_3 "rtl_nic/rtl8126a-3.fw"
@@ -140,8 +142,10 @@ static const struct {
/* reserve 62 for CFG_METHOD_4 in the vendor driver */
[RTL_GIGA_MAC_VER_63] = {"RTL8125B", FIRMWARE_8125B_2},
[RTL_GIGA_MAC_VER_64] = {"RTL8125D", FIRMWARE_8125D_1},
- [RTL_GIGA_MAC_VER_65] = {"RTL8126A", FIRMWARE_8126A_2},
- [RTL_GIGA_MAC_VER_66] = {"RTL8126A", FIRMWARE_8126A_3},
+ [RTL_GIGA_MAC_VER_65] = {"RTL8125D", FIRMWARE_8125D_2},
+ [RTL_GIGA_MAC_VER_66] = {"RTL8125BP", FIRMWARE_8125BP_2},
+ [RTL_GIGA_MAC_VER_70] = {"RTL8126A", FIRMWARE_8126A_2},
+ [RTL_GIGA_MAC_VER_71] = {"RTL8126A", FIRMWARE_8126A_3},
};
static const struct pci_device_id rtl8169_pci_tbl[] = {
@@ -630,6 +634,7 @@ enum rtl_dash_type {
RTL_DASH_NONE,
RTL_DASH_DP,
RTL_DASH_EP,
+ RTL_DASH_25_BP,
};
struct rtl8169_private {
@@ -706,6 +711,8 @@ MODULE_FIRMWARE(FIRMWARE_8107E_2);
MODULE_FIRMWARE(FIRMWARE_8125A_3);
MODULE_FIRMWARE(FIRMWARE_8125B_2);
MODULE_FIRMWARE(FIRMWARE_8125D_1);
+MODULE_FIRMWARE(FIRMWARE_8125D_2);
+MODULE_FIRMWARE(FIRMWARE_8125BP_2);
MODULE_FIRMWARE(FIRMWARE_8126A_2);
MODULE_FIRMWARE(FIRMWARE_8126A_3);
@@ -1228,7 +1235,7 @@ static void rtl_writephy(struct rtl8169_private *tp, int location, int val)
case RTL_GIGA_MAC_VER_31:
r8168dp_2_mdio_write(tp, location, val);
break;
- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71:
r8168g_mdio_write(tp, location, val);
break;
default:
@@ -1243,7 +1250,7 @@ static int rtl_readphy(struct rtl8169_private *tp, int location)
case RTL_GIGA_MAC_VER_28:
case RTL_GIGA_MAC_VER_31:
return r8168dp_2_mdio_read(tp, location);
- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71:
return r8168g_mdio_read(tp, location);
default:
return r8169_mdio_read(tp, location);
@@ -1358,10 +1365,19 @@ static void rtl8168ep_driver_start(struct rtl8169_private *tp)
rtl_loop_wait_high(tp, &rtl_ep_ocp_read_cond, 10000, 30);
}
+static void rtl8125bp_driver_start(struct rtl8169_private *tp)
+{
+ r8168ep_ocp_write(tp, 0x01, 0x14, OOB_CMD_DRIVER_START);
+ r8168ep_ocp_write(tp, 0x01, 0x18, 0x00);
+ r8168ep_ocp_write(tp, 0x01, 0x10, 0x01);
+}
+
static void rtl8168_driver_start(struct rtl8169_private *tp)
{
if (tp->dash_type == RTL_DASH_DP)
rtl8168dp_driver_start(tp);
+ else if (tp->dash_type == RTL_DASH_25_BP)
+ rtl8125bp_driver_start(tp);
else
rtl8168ep_driver_start(tp);
}
@@ -1382,10 +1398,19 @@ static void rtl8168ep_driver_stop(struct rtl8169_private *tp)
rtl_loop_wait_low(tp, &rtl_ep_ocp_read_cond, 10000, 10);
}
+static void rtl8125bp_driver_stop(struct rtl8169_private *tp)
+{
+ r8168ep_ocp_write(tp, 0x01, 0x14, OOB_CMD_DRIVER_STOP);
+ r8168ep_ocp_write(tp, 0x01, 0x18, 0x00);
+ r8168ep_ocp_write(tp, 0x01, 0x10, 0x01);
+}
+
static void rtl8168_driver_stop(struct rtl8169_private *tp)
{
if (tp->dash_type == RTL_DASH_DP)
rtl8168dp_driver_stop(tp);
+ else if (tp->dash_type == RTL_DASH_25_BP)
+ rtl8125bp_driver_stop(tp);
else
rtl8168ep_driver_stop(tp);
}
@@ -1408,6 +1433,7 @@ static bool rtl_dash_is_enabled(struct rtl8169_private *tp)
case RTL_DASH_DP:
return r8168dp_check_dash(tp);
case RTL_DASH_EP:
+ case RTL_DASH_25_BP:
return r8168ep_check_dash(tp);
default:
return false;
@@ -1422,6 +1448,8 @@ static enum rtl_dash_type rtl_get_dash_type(struct rtl8169_private *tp)
return RTL_DASH_DP;
case RTL_GIGA_MAC_VER_51 ... RTL_GIGA_MAC_VER_53:
return RTL_DASH_EP;
+ case RTL_GIGA_MAC_VER_66:
+ return RTL_DASH_25_BP;
default:
return RTL_DASH_NONE;
}
@@ -1574,7 +1602,7 @@ static void __rtl8169_set_wol(struct rtl8169_private *tp, u32 wolopts)
break;
case RTL_GIGA_MAC_VER_34:
case RTL_GIGA_MAC_VER_37:
- case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_39 ... RTL_GIGA_MAC_VER_71:
r8169_mod_reg8_cond(tp, Config2, PME_SIGNAL, wolopts);
break;
default:
@@ -2047,7 +2075,7 @@ static void rtl_set_eee_txidle_timer(struct rtl8169_private *tp)
tp->tx_lpi_timer = timer_val;
r8168_mac_ocp_write(tp, 0xe048, timer_val);
break;
- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71:
tp->tx_lpi_timer = timer_val;
RTL_W16(tp, EEE_TXIDLE_TIMER_8125, timer_val);
break;
@@ -2255,10 +2283,14 @@ static enum mac_version rtl8169_get_mac_version(u16 xid, bool gmii)
enum mac_version ver;
} mac_info[] = {
/* 8126A family. */
- { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_66 },
- { 0x7cf, 0x649, RTL_GIGA_MAC_VER_65 },
+ { 0x7cf, 0x64a, RTL_GIGA_MAC_VER_71 },
+ { 0x7cf, 0x649, RTL_GIGA_MAC_VER_70 },
+
+ /* 8125BP family. */
+ { 0x7cf, 0x681, RTL_GIGA_MAC_VER_66 },
/* 8125D family. */
+ { 0x7cf, 0x689, RTL_GIGA_MAC_VER_65 },
{ 0x7cf, 0x688, RTL_GIGA_MAC_VER_64 },
/* 8125B family. */
@@ -2526,7 +2558,7 @@ static void rtl_init_rxcfg(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_61:
RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST);
break;
- case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_71:
RTL_W32(tp, RxConfig, RX_FETCH_DFLT_8125 | RX_DMA_BURST |
RX_PAUSE_SLOT_ON);
break;
@@ -2658,7 +2690,7 @@ static void rtl_wait_txrx_fifo_empty(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_61:
rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
break;
- case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_63 ... RTL_GIGA_MAC_VER_71:
RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond, 100, 42);
rtl_loop_wait_high(tp, &rtl_rxtx_empty_cond_2, 100, 42);
@@ -2901,7 +2933,7 @@ static void rtl_enable_exit_l1(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_37 ... RTL_GIGA_MAC_VER_38:
rtl_eri_set_bits(tp, 0xd4, 0x0c00);
break;
- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71:
r8168_mac_ocp_modify(tp, 0xc0ac, 0, 0x1f80);
break;
default:
@@ -2915,7 +2947,7 @@ static void rtl_disable_exit_l1(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_34 ... RTL_GIGA_MAC_VER_38:
rtl_eri_clear_bits(tp, 0xd4, 0x1f00);
break;
- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71:
r8168_mac_ocp_modify(tp, 0xc0ac, 0x1f80, 0);
break;
default:
@@ -2941,8 +2973,8 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
rtl_mod_config5(tp, 0, ASPM_en);
switch (tp->mac_version) {
- case RTL_GIGA_MAC_VER_65:
- case RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_70:
+ case RTL_GIGA_MAC_VER_71:
val8 = RTL_R8(tp, INT_CFG0_8125) | INT_CFG0_CLKREQEN;
RTL_W8(tp, INT_CFG0_8125, val8);
break;
@@ -2953,7 +2985,7 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71:
/* reset ephy tx/rx disable timer */
r8168_mac_ocp_modify(tp, 0xe094, 0xff00, 0);
/* chip can trigger L1.2 */
@@ -2965,7 +2997,7 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
} else {
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_46 ... RTL_GIGA_MAC_VER_48:
- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71:
r8168_mac_ocp_modify(tp, 0xe092, 0x00ff, 0);
break;
default:
@@ -2973,8 +3005,8 @@ static void rtl_hw_aspm_clkreq_enable(struct rtl8169_private *tp, bool enable)
}
switch (tp->mac_version) {
- case RTL_GIGA_MAC_VER_65:
- case RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_70:
+ case RTL_GIGA_MAC_VER_71:
val8 = RTL_R8(tp, INT_CFG0_8125) & ~INT_CFG0_CLKREQEN;
RTL_W8(tp, INT_CFG0_8125, val8);
break;
@@ -3694,12 +3726,12 @@ static void rtl_hw_start_8125_common(struct rtl8169_private *tp)
/* disable new tx descriptor format */
r8168_mac_ocp_modify(tp, 0xeb58, 0x0001, 0x0000);
- if (tp->mac_version == RTL_GIGA_MAC_VER_65 ||
- tp->mac_version == RTL_GIGA_MAC_VER_66)
+ if (tp->mac_version == RTL_GIGA_MAC_VER_70 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_71)
RTL_W8(tp, 0xD8, RTL_R8(tp, 0xD8) & ~0x02);
- if (tp->mac_version == RTL_GIGA_MAC_VER_65 ||
- tp->mac_version == RTL_GIGA_MAC_VER_66)
+ if (tp->mac_version == RTL_GIGA_MAC_VER_70 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_71)
r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0400);
else if (tp->mac_version == RTL_GIGA_MAC_VER_63)
r8168_mac_ocp_modify(tp, 0xe614, 0x0700, 0x0200);
@@ -3717,8 +3749,8 @@ static void rtl_hw_start_8125_common(struct rtl8169_private *tp)
r8168_mac_ocp_modify(tp, 0xe056, 0x00f0, 0x0030);
r8168_mac_ocp_modify(tp, 0xe040, 0x1000, 0x0000);
r8168_mac_ocp_modify(tp, 0xea1c, 0x0003, 0x0001);
- if (tp->mac_version == RTL_GIGA_MAC_VER_65 ||
- tp->mac_version == RTL_GIGA_MAC_VER_66)
+ if (tp->mac_version == RTL_GIGA_MAC_VER_70 ||
+ tp->mac_version == RTL_GIGA_MAC_VER_71)
r8168_mac_ocp_modify(tp, 0xea1c, 0x0300, 0x0000);
else
r8168_mac_ocp_modify(tp, 0xea1c, 0x0004, 0x0000);
@@ -3837,8 +3869,10 @@ static void rtl_hw_config(struct rtl8169_private *tp)
[RTL_GIGA_MAC_VER_61] = rtl_hw_start_8125a_2,
[RTL_GIGA_MAC_VER_63] = rtl_hw_start_8125b,
[RTL_GIGA_MAC_VER_64] = rtl_hw_start_8125d,
- [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8126a,
- [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8126a,
+ [RTL_GIGA_MAC_VER_65] = rtl_hw_start_8125d,
+ [RTL_GIGA_MAC_VER_66] = rtl_hw_start_8125d,
+ [RTL_GIGA_MAC_VER_70] = rtl_hw_start_8126a,
+ [RTL_GIGA_MAC_VER_71] = rtl_hw_start_8126a,
};
if (hw_configs[tp->mac_version])
@@ -3855,12 +3889,14 @@ static void rtl_hw_start_8125(struct rtl8169_private *tp)
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_61:
case RTL_GIGA_MAC_VER_64:
+ case RTL_GIGA_MAC_VER_65:
+ case RTL_GIGA_MAC_VER_66:
for (i = 0xa00; i < 0xb00; i += 4)
RTL_W32(tp, i, 0);
break;
case RTL_GIGA_MAC_VER_63:
- case RTL_GIGA_MAC_VER_65:
- case RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_70:
+ case RTL_GIGA_MAC_VER_71:
for (i = 0xa00; i < 0xa80; i += 4)
RTL_W32(tp, i, 0);
RTL_W16(tp, INT_CFG1_8125, 0x0000);
@@ -4092,7 +4128,7 @@ static void rtl8169_cleanup(struct rtl8169_private *tp)
RTL_W8(tp, ChipCmd, RTL_R8(tp, ChipCmd) | StopReq);
rtl_loop_wait_high(tp, &rtl_txcfg_empty_cond, 100, 666);
break;
- case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_71:
rtl_enable_rxdvgate(tp);
fsleep(2000);
break;
@@ -4249,7 +4285,7 @@ static unsigned int rtl_quirk_packet_padto(struct rtl8169_private *tp,
switch (tp->mac_version) {
case RTL_GIGA_MAC_VER_34:
- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71:
padto = max_t(unsigned int, padto, ETH_ZLEN);
break;
default:
@@ -5267,7 +5303,7 @@ static void rtl_hw_initialize(struct rtl8169_private *tp)
case RTL_GIGA_MAC_VER_40 ... RTL_GIGA_MAC_VER_48:
rtl_hw_init_8168g(tp);
break;
- case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_66:
+ case RTL_GIGA_MAC_VER_61 ... RTL_GIGA_MAC_VER_71:
rtl_hw_init_8125(tp);
break;
default:
diff --git a/drivers/net/ethernet/realtek/r8169_phy_config.c b/drivers/net/ethernet/realtek/r8169_phy_config.c
index b28b30390e84..cf95e579c65d 100644
--- a/drivers/net/ethernet/realtek/r8169_phy_config.c
+++ b/drivers/net/ethernet/realtek/r8169_phy_config.c
@@ -1102,6 +1102,28 @@ static void rtl8125d_hw_phy_config(struct rtl8169_private *tp,
rtl8125_config_eee_phy(phydev);
}
+static void rtl8125bp_hw_phy_config(struct rtl8169_private *tp,
+ struct phy_device *phydev)
+{
+ r8169_apply_firmware(tp);
+ rtl8168g_enable_gphy_10m(phydev);
+
+ r8168g_phy_param(phydev, 0x8010, 0x0800, 0x0000);
+
+ phy_write(phydev, 0x1f, 0x0b87);
+ phy_write(phydev, 0x16, 0x8088);
+ phy_modify(phydev, 0x17, 0xff00, 0x9000);
+ phy_write(phydev, 0x16, 0x808f);
+ phy_modify(phydev, 0x17, 0xff00, 0x9000);
+ phy_write(phydev, 0x1f, 0x0000);
+
+ r8168g_phy_param(phydev, 0x8174, 0x2000, 0x1800);
+
+ rtl8125_legacy_force_mode(phydev);
+ rtl8168g_disable_aldps(phydev);
+ rtl8125_config_eee_phy(phydev);
+}
+
static void rtl8126a_hw_phy_config(struct rtl8169_private *tp,
struct phy_device *phydev)
{
@@ -1162,8 +1184,10 @@ void r8169_hw_phy_config(struct rtl8169_private *tp, struct phy_device *phydev,
[RTL_GIGA_MAC_VER_61] = rtl8125a_2_hw_phy_config,
[RTL_GIGA_MAC_VER_63] = rtl8125b_hw_phy_config,
[RTL_GIGA_MAC_VER_64] = rtl8125d_hw_phy_config,
- [RTL_GIGA_MAC_VER_65] = rtl8126a_hw_phy_config,
- [RTL_GIGA_MAC_VER_66] = rtl8126a_hw_phy_config,
+ [RTL_GIGA_MAC_VER_65] = rtl8125d_hw_phy_config,
+ [RTL_GIGA_MAC_VER_66] = rtl8125bp_hw_phy_config,
+ [RTL_GIGA_MAC_VER_70] = rtl8126a_hw_phy_config,
+ [RTL_GIGA_MAC_VER_71] = rtl8126a_hw_phy_config,
};
if (phy_configs[ver])
diff --git a/drivers/net/ethernet/realtek/rtase/rtase_main.c b/drivers/net/ethernet/realtek/rtase/rtase_main.c
index 6106aa5333bc..3bd11cb56294 100644
--- a/drivers/net/ethernet/realtek/rtase/rtase_main.c
+++ b/drivers/net/ethernet/realtek/rtase/rtase_main.c
@@ -1828,7 +1828,7 @@ static int rtase_alloc_msix(struct pci_dev *pdev, struct rtase_private *tp)
for (i = 0; i < tp->int_nums; i++) {
irq = pci_irq_vector(pdev, i);
- if (!irq) {
+ if (irq < 0) {
pci_disable_msix(pdev);
return irq;
}
@@ -2018,7 +2018,7 @@ static int rtase_init_board(struct pci_dev *pdev, struct net_device **dev_out,
SET_NETDEV_DEV(dev, &pdev->dev);
ret = pci_enable_device(pdev);
- if (ret < 0)
+ if (ret)
goto err_out_free_dev;
/* make sure PCI base addr 1 is MMIO */
@@ -2034,7 +2034,7 @@ static int rtase_init_board(struct pci_dev *pdev, struct net_device **dev_out,
}
ret = pci_request_regions(pdev, KBUILD_MODNAME);
- if (ret < 0)
+ if (ret)
goto err_out_disable;
ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64));
@@ -2110,7 +2110,7 @@ static int rtase_init_one(struct pci_dev *pdev,
dev_dbg(&pdev->dev, "Automotive Switch Ethernet driver loaded\n");
ret = rtase_init_board(pdev, &dev, &ioaddr);
- if (ret != 0)
+ if (ret)
return ret;
tp = netdev_priv(dev);
@@ -2120,7 +2120,7 @@ static int rtase_init_one(struct pci_dev *pdev,
/* identify chip attached to board */
ret = rtase_check_mac_version_valid(tp);
- if (ret != 0) {
+ if (ret) {
dev_err(&pdev->dev,
"unknown chip version: 0x%08x, contact rtase maintainers (see MAINTAINERS file)\n",
tp->hw_ver);
@@ -2131,7 +2131,7 @@ static int rtase_init_one(struct pci_dev *pdev,
rtase_init_hardware(tp);
ret = rtase_alloc_interrupt(pdev, tp);
- if (ret < 0) {
+ if (ret) {
dev_err(&pdev->dev, "unable to alloc MSIX/MSI\n");
goto err_out_del_napi;
}
@@ -2176,7 +2176,7 @@ static int rtase_init_one(struct pci_dev *pdev,
netif_carrier_off(dev);
ret = register_netdev(dev);
- if (ret != 0)
+ if (ret)
goto err_out_free_dma;
netdev_dbg(dev, "%pM, IRQ %d\n", dev->dev_addr, dev->irq);
diff --git a/drivers/net/ethernet/renesas/rswitch.c b/drivers/net/ethernet/renesas/rswitch.c
index 8d18dae4d8fb..84d09a8973b7 100644
--- a/drivers/net/ethernet/renesas/rswitch.c
+++ b/drivers/net/ethernet/renesas/rswitch.c
@@ -111,25 +111,35 @@ static void rswitch_top_init(struct rswitch_private *priv)
/* Forwarding engine block (MFWD) */
static void rswitch_fwd_init(struct rswitch_private *priv)
{
+ u32 all_ports_mask = GENMASK(RSWITCH_NUM_AGENTS - 1, 0);
unsigned int i;
- /* For ETHA */
- for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
- iowrite32(FWPC0_DEFAULT, priv->addr + FWPC0(i));
+ /* Start with empty configuration */
+ for (i = 0; i < RSWITCH_NUM_AGENTS; i++) {
+ /* Disable all port features */
+ iowrite32(0, priv->addr + FWPC0(i));
+ /* Disallow L3 forwarding and direct descriptor forwarding */
+ iowrite32(FIELD_PREP(FWCP1_LTHFW, all_ports_mask),
+ priv->addr + FWPC1(i));
+ /* Disallow L2 forwarding */
+ iowrite32(FIELD_PREP(FWCP2_LTWFW, all_ports_mask),
+ priv->addr + FWPC2(i));
+ /* Disallow port based forwarding */
iowrite32(0, priv->addr + FWPBFC(i));
}
- for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
+ /* For enabled ETHA ports, setup port based forwarding */
+ rswitch_for_each_enabled_port(priv, i) {
+ /* Port based forwarding from port i to GWCA port */
+ rswitch_modify(priv->addr, FWPBFC(i), FWPBFC_PBDV,
+ FIELD_PREP(FWPBFC_PBDV, BIT(priv->gwca.index)));
+ /* Within GWCA port, forward to Rx queue for port i */
iowrite32(priv->rdev[i]->rx_queue->index,
priv->addr + FWPBFCSDC(GWCA_INDEX, i));
- iowrite32(BIT(priv->gwca.index), priv->addr + FWPBFC(i));
}
- /* For GWCA */
- iowrite32(FWPC0_DEFAULT, priv->addr + FWPC0(priv->gwca.index));
- iowrite32(FWPC1_DDE, priv->addr + FWPC1(priv->gwca.index));
- iowrite32(0, priv->addr + FWPBFC(priv->gwca.index));
- iowrite32(GENMASK(RSWITCH_NUM_PORTS - 1, 0), priv->addr + FWPBFC(priv->gwca.index));
+ /* For GWCA port, allow direct descriptor forwarding */
+ rswitch_modify(priv->addr, FWPC1(priv->gwca.index), FWPC1_DDE, FWPC1_DDE);
}
/* Gateway CPU agent block (GWCA) */
@@ -547,7 +557,6 @@ static int rswitch_gwca_ts_queue_alloc(struct rswitch_private *priv)
desc = &gq->ts_ring[gq->ring_size];
desc->desc.die_dt = DT_LINKFIX;
rswitch_desc_set_dptr(&desc->desc, gq->ring_dma);
- INIT_LIST_HEAD(&priv->gwca.ts_info_list);
return 0;
}
@@ -862,13 +871,10 @@ static void rswitch_tx_free(struct net_device *ndev)
struct rswitch_ext_desc *desc;
struct sk_buff *skb;
- for (; rswitch_get_num_cur_queues(gq) > 0;
- gq->dirty = rswitch_next_queue_index(gq, false, 1)) {
- desc = &gq->tx_ring[gq->dirty];
- if ((desc->desc.die_dt & DT_MASK) != DT_FEMPTY)
- break;
-
+ desc = &gq->tx_ring[gq->dirty];
+ while ((desc->desc.die_dt & DT_MASK) == DT_FEMPTY) {
dma_rmb();
+
skb = gq->skbs[gq->dirty];
if (skb) {
rdev->ndev->stats.tx_packets++;
@@ -879,7 +885,10 @@ static void rswitch_tx_free(struct net_device *ndev)
dev_kfree_skb_any(gq->skbs[gq->dirty]);
gq->skbs[gq->dirty] = NULL;
}
+
desc->desc.die_dt = DT_EEMPTY;
+ gq->dirty = rswitch_next_queue_index(gq, false, 1);
+ desc = &gq->tx_ring[gq->dirty];
}
}
@@ -908,8 +917,10 @@ retry:
if (napi_complete_done(napi, budget - quota)) {
spin_lock_irqsave(&priv->lock, flags);
- rswitch_enadis_data_irq(priv, rdev->tx_queue->index, true);
- rswitch_enadis_data_irq(priv, rdev->rx_queue->index, true);
+ if (test_bit(rdev->port, priv->opened_ports)) {
+ rswitch_enadis_data_irq(priv, rdev->tx_queue->index, true);
+ rswitch_enadis_data_irq(priv, rdev->rx_queue->index, true);
+ }
spin_unlock_irqrestore(&priv->lock, flags);
}
@@ -1001,9 +1012,10 @@ static int rswitch_gwca_request_irqs(struct rswitch_private *priv)
static void rswitch_ts(struct rswitch_private *priv)
{
struct rswitch_gwca_queue *gq = &priv->gwca.ts_queue;
- struct rswitch_gwca_ts_info *ts_info, *ts_info2;
struct skb_shared_hwtstamps shhwtstamps;
struct rswitch_ts_desc *desc;
+ struct rswitch_device *rdev;
+ struct sk_buff *ts_skb;
struct timespec64 ts;
unsigned int num;
u32 tag, port;
@@ -1013,23 +1025,28 @@ static void rswitch_ts(struct rswitch_private *priv)
dma_rmb();
port = TS_DESC_DPN(__le32_to_cpu(desc->desc.dptrl));
- tag = TS_DESC_TSUN(__le32_to_cpu(desc->desc.dptrl));
-
- list_for_each_entry_safe(ts_info, ts_info2, &priv->gwca.ts_info_list, list) {
- if (!(ts_info->port == port && ts_info->tag == tag))
- continue;
-
- memset(&shhwtstamps, 0, sizeof(shhwtstamps));
- ts.tv_sec = __le32_to_cpu(desc->ts_sec);
- ts.tv_nsec = __le32_to_cpu(desc->ts_nsec & cpu_to_le32(0x3fffffff));
- shhwtstamps.hwtstamp = timespec64_to_ktime(ts);
- skb_tstamp_tx(ts_info->skb, &shhwtstamps);
- dev_consume_skb_irq(ts_info->skb);
- list_del(&ts_info->list);
- kfree(ts_info);
- break;
- }
+ if (unlikely(port >= RSWITCH_NUM_PORTS))
+ goto next;
+ rdev = priv->rdev[port];
+ tag = TS_DESC_TSUN(__le32_to_cpu(desc->desc.dptrl));
+ if (unlikely(tag >= TS_TAGS_PER_PORT))
+ goto next;
+ ts_skb = xchg(&rdev->ts_skb[tag], NULL);
+ smp_mb(); /* order rdev->ts_skb[] read before bitmap update */
+ clear_bit(tag, rdev->ts_skb_used);
+
+ if (unlikely(!ts_skb))
+ goto next;
+
+ memset(&shhwtstamps, 0, sizeof(shhwtstamps));
+ ts.tv_sec = __le32_to_cpu(desc->ts_sec);
+ ts.tv_nsec = __le32_to_cpu(desc->ts_nsec & cpu_to_le32(0x3fffffff));
+ shhwtstamps.hwtstamp = timespec64_to_ktime(ts);
+ skb_tstamp_tx(ts_skb, &shhwtstamps);
+ dev_consume_skb_irq(ts_skb);
+
+next:
gq->cur = rswitch_next_queue_index(gq, true, 1);
desc = &gq->ts_ring[gq->cur];
}
@@ -1114,32 +1131,47 @@ static int rswitch_etha_wait_link_verification(struct rswitch_etha *etha)
static void rswitch_rmac_setting(struct rswitch_etha *etha, const u8 *mac)
{
- u32 val;
+ u32 pis, lsc;
rswitch_etha_write_mac_address(etha, mac);
+ switch (etha->phy_interface) {
+ case PHY_INTERFACE_MODE_SGMII:
+ pis = MPIC_PIS_GMII;
+ break;
+ case PHY_INTERFACE_MODE_USXGMII:
+ case PHY_INTERFACE_MODE_5GBASER:
+ pis = MPIC_PIS_XGMII;
+ break;
+ default:
+ pis = FIELD_GET(MPIC_PIS, ioread32(etha->addr + MPIC));
+ break;
+ }
+
switch (etha->speed) {
case 100:
- val = MPIC_LSC_100M;
+ lsc = MPIC_LSC_100M;
break;
case 1000:
- val = MPIC_LSC_1G;
+ lsc = MPIC_LSC_1G;
break;
case 2500:
- val = MPIC_LSC_2_5G;
+ lsc = MPIC_LSC_2_5G;
break;
default:
- return;
+ lsc = FIELD_GET(MPIC_LSC, ioread32(etha->addr + MPIC));
+ break;
}
- iowrite32(MPIC_PIS_GMII | val, etha->addr + MPIC);
+ rswitch_modify(etha->addr, MPIC, MPIC_PIS | MPIC_LSC,
+ FIELD_PREP(MPIC_PIS, pis) | FIELD_PREP(MPIC_LSC, lsc));
}
static void rswitch_etha_enable_mii(struct rswitch_etha *etha)
{
- rswitch_modify(etha->addr, MPIC, MPIC_PSMCS_MASK | MPIC_PSMHT_MASK,
- MPIC_PSMCS(etha->psmcs) | MPIC_PSMHT(0x06));
- rswitch_modify(etha->addr, MPSM, 0, MPSM_MFF_C45);
+ rswitch_modify(etha->addr, MPIC, MPIC_PSMCS | MPIC_PSMHT,
+ FIELD_PREP(MPIC_PSMCS, etha->psmcs) |
+ FIELD_PREP(MPIC_PSMHT, 0x06));
}
static int rswitch_etha_hw_init(struct rswitch_etha *etha, const u8 *mac)
@@ -1168,42 +1200,29 @@ static int rswitch_etha_hw_init(struct rswitch_etha *etha, const u8 *mac)
return rswitch_etha_change_mode(etha, EAMC_OPC_OPERATION);
}
-static int rswitch_etha_set_access(struct rswitch_etha *etha, bool read,
- int phyad, int devad, int regad, int data)
+static int rswitch_etha_mpsm_op(struct rswitch_etha *etha, bool read,
+ unsigned int mmf, unsigned int pda,
+ unsigned int pra, unsigned int pop,
+ unsigned int prd)
{
- int pop = read ? MDIO_READ_C45 : MDIO_WRITE_C45;
u32 val;
int ret;
- if (devad == 0xffffffff)
- return -ENODEV;
-
- writel(MMIS1_CLEAR_FLAGS, etha->addr + MMIS1);
-
- val = MPSM_PSME | MPSM_MFF_C45;
- iowrite32((regad << 16) | (devad << 8) | (phyad << 3) | val, etha->addr + MPSM);
+ val = MPSM_PSME |
+ FIELD_PREP(MPSM_MFF, mmf) |
+ FIELD_PREP(MPSM_PDA, pda) |
+ FIELD_PREP(MPSM_PRA, pra) |
+ FIELD_PREP(MPSM_POP, pop) |
+ FIELD_PREP(MPSM_PRD, prd);
+ iowrite32(val, etha->addr + MPSM);
- ret = rswitch_reg_wait(etha->addr, MMIS1, MMIS1_PAACS, MMIS1_PAACS);
+ ret = rswitch_reg_wait(etha->addr, MPSM, MPSM_PSME, 0);
if (ret)
return ret;
- rswitch_modify(etha->addr, MMIS1, MMIS1_PAACS, MMIS1_PAACS);
-
if (read) {
- writel((pop << 13) | (devad << 8) | (phyad << 3) | val, etha->addr + MPSM);
-
- ret = rswitch_reg_wait(etha->addr, MMIS1, MMIS1_PRACS, MMIS1_PRACS);
- if (ret)
- return ret;
-
- ret = (ioread32(etha->addr + MPSM) & MPSM_PRD_MASK) >> 16;
-
- rswitch_modify(etha->addr, MMIS1, MMIS1_PRACS, MMIS1_PRACS);
- } else {
- iowrite32((data << 16) | (pop << 13) | (devad << 8) | (phyad << 3) | val,
- etha->addr + MPSM);
-
- ret = rswitch_reg_wait(etha->addr, MMIS1, MMIS1_PWACS, MMIS1_PWACS);
+ val = ioread32(etha->addr + MPSM);
+ ret = FIELD_GET(MPSM_PRD, val);
}
return ret;
@@ -1213,16 +1232,47 @@ static int rswitch_etha_mii_read_c45(struct mii_bus *bus, int addr, int devad,
int regad)
{
struct rswitch_etha *etha = bus->priv;
+ int ret;
- return rswitch_etha_set_access(etha, true, addr, devad, regad, 0);
+ ret = rswitch_etha_mpsm_op(etha, false, MPSM_MMF_C45, addr, devad,
+ MPSM_POP_ADDRESS, regad);
+ if (ret)
+ return ret;
+
+ return rswitch_etha_mpsm_op(etha, true, MPSM_MMF_C45, addr, devad,
+ MPSM_POP_READ_C45, 0);
}
static int rswitch_etha_mii_write_c45(struct mii_bus *bus, int addr, int devad,
int regad, u16 val)
{
struct rswitch_etha *etha = bus->priv;
+ int ret;
- return rswitch_etha_set_access(etha, false, addr, devad, regad, val);
+ ret = rswitch_etha_mpsm_op(etha, false, MPSM_MMF_C45, addr, devad,
+ MPSM_POP_ADDRESS, regad);
+ if (ret)
+ return ret;
+
+ return rswitch_etha_mpsm_op(etha, false, MPSM_MMF_C45, addr, devad,
+ MPSM_POP_WRITE, val);
+}
+
+static int rswitch_etha_mii_read_c22(struct mii_bus *bus, int phyad, int regad)
+{
+ struct rswitch_etha *etha = bus->priv;
+
+ return rswitch_etha_mpsm_op(etha, true, MPSM_MMF_C22, phyad, regad,
+ MPSM_POP_READ_C22, 0);
+}
+
+static int rswitch_etha_mii_write_c22(struct mii_bus *bus, int phyad,
+ int regad, u16 val)
+{
+ struct rswitch_etha *etha = bus->priv;
+
+ return rswitch_etha_mpsm_op(etha, false, MPSM_MMF_C22, phyad, regad,
+ MPSM_POP_WRITE, val);
}
/* Call of_node_put(port) after done */
@@ -1307,6 +1357,8 @@ static int rswitch_mii_register(struct rswitch_device *rdev)
mii_bus->priv = rdev->etha;
mii_bus->read_c45 = rswitch_etha_mii_read_c45;
mii_bus->write_c45 = rswitch_etha_mii_write_c45;
+ mii_bus->read = rswitch_etha_mii_read_c22;
+ mii_bus->write = rswitch_etha_mii_write_c22;
mii_bus->parent = &rdev->priv->pdev->dev;
mdio_np = of_get_child_by_name(rdev->np_port, "mdio");
@@ -1527,7 +1579,7 @@ static void rswitch_ether_port_deinit_all(struct rswitch_private *priv)
{
unsigned int i;
- for (i = 0; i < RSWITCH_NUM_PORTS; i++) {
+ rswitch_for_each_enabled_port(priv, i) {
phy_exit(priv->rdev[i]->serdes);
rswitch_ether_port_deinit_one(priv->rdev[i]);
}
@@ -1538,20 +1590,20 @@ static int rswitch_open(struct net_device *ndev)
struct rswitch_device *rdev = netdev_priv(ndev);
unsigned long flags;
- phy_start(ndev->phydev);
+ if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
+ iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDIE);
napi_enable(&rdev->napi);
- netif_start_queue(ndev);
spin_lock_irqsave(&rdev->priv->lock, flags);
+ bitmap_set(rdev->priv->opened_ports, rdev->port, 1);
rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, true);
rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, true);
spin_unlock_irqrestore(&rdev->priv->lock, flags);
- if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
- iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDIE);
+ phy_start(ndev->phydev);
- bitmap_set(rdev->priv->opened_ports, rdev->port, 1);
+ netif_start_queue(ndev);
return 0;
};
@@ -1559,31 +1611,34 @@ static int rswitch_open(struct net_device *ndev)
static int rswitch_stop(struct net_device *ndev)
{
struct rswitch_device *rdev = netdev_priv(ndev);
- struct rswitch_gwca_ts_info *ts_info, *ts_info2;
+ struct sk_buff *ts_skb;
unsigned long flags;
+ unsigned int tag;
netif_tx_stop_all_queues(ndev);
- bitmap_clear(rdev->priv->opened_ports, rdev->port, 1);
-
- if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
- iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID);
- list_for_each_entry_safe(ts_info, ts_info2, &rdev->priv->gwca.ts_info_list, list) {
- if (ts_info->port != rdev->port)
- continue;
- dev_kfree_skb_irq(ts_info->skb);
- list_del(&ts_info->list);
- kfree(ts_info);
- }
+ phy_stop(ndev->phydev);
spin_lock_irqsave(&rdev->priv->lock, flags);
rswitch_enadis_data_irq(rdev->priv, rdev->tx_queue->index, false);
rswitch_enadis_data_irq(rdev->priv, rdev->rx_queue->index, false);
+ bitmap_clear(rdev->priv->opened_ports, rdev->port, 1);
spin_unlock_irqrestore(&rdev->priv->lock, flags);
- phy_stop(ndev->phydev);
napi_disable(&rdev->napi);
+ if (bitmap_empty(rdev->priv->opened_ports, RSWITCH_NUM_PORTS))
+ iowrite32(GWCA_TS_IRQ_BIT, rdev->priv->addr + GWTSDID);
+
+ for (tag = find_first_bit(rdev->ts_skb_used, TS_TAGS_PER_PORT);
+ tag < TS_TAGS_PER_PORT;
+ tag = find_next_bit(rdev->ts_skb_used, TS_TAGS_PER_PORT, tag + 1)) {
+ ts_skb = xchg(&rdev->ts_skb[tag], NULL);
+ clear_bit(tag, rdev->ts_skb_used);
+ if (ts_skb)
+ dev_kfree_skb(ts_skb);
+ }
+
return 0;
};
@@ -1594,20 +1649,17 @@ static bool rswitch_ext_desc_set_info1(struct rswitch_device *rdev,
desc->info1 = cpu_to_le64(INFO1_DV(BIT(rdev->etha->index)) |
INFO1_IPV(GWCA_IPV_NUM) | INFO1_FMT);
if (skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
- struct rswitch_gwca_ts_info *ts_info;
+ unsigned int tag;
- ts_info = kzalloc(sizeof(*ts_info), GFP_ATOMIC);
- if (!ts_info)
+ tag = find_first_zero_bit(rdev->ts_skb_used, TS_TAGS_PER_PORT);
+ if (tag == TS_TAGS_PER_PORT)
return false;
+ smp_mb(); /* order bitmap read before rdev->ts_skb[] write */
+ rdev->ts_skb[tag] = skb_get(skb);
+ set_bit(tag, rdev->ts_skb_used);
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
- rdev->ts_tag++;
- desc->info1 |= cpu_to_le64(INFO1_TSUN(rdev->ts_tag) | INFO1_TXC);
-
- ts_info->skb = skb_get(skb);
- ts_info->port = rdev->port;
- ts_info->tag = rdev->ts_tag;
- list_add_tail(&ts_info->list, &rdev->priv->gwca.ts_info_list);
+ desc->info1 |= cpu_to_le64(INFO1_TSUN(tag) | INFO1_TXC);
skb_tx_timestamp(skb);
}
@@ -1681,8 +1733,11 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
if (dma_mapping_error(ndev->dev.parent, dma_addr_orig))
goto err_kfree;
- gq->skbs[gq->cur] = skb;
- gq->unmap_addrs[gq->cur] = dma_addr_orig;
+ /* Stored the skb at the last descriptor to avoid skb free before hardware completes send */
+ gq->skbs[(gq->cur + nr_desc - 1) % gq->ring_size] = skb;
+ gq->unmap_addrs[(gq->cur + nr_desc - 1) % gq->ring_size] = dma_addr_orig;
+
+ dma_wmb();
/* DT_FSTART should be set at last. So, this is reverse order. */
for (i = nr_desc; i-- > 0; ) {
@@ -1694,14 +1749,13 @@ static netdev_tx_t rswitch_start_xmit(struct sk_buff *skb, struct net_device *nd
goto err_unmap;
}
- wmb(); /* gq->cur must be incremented after die_dt was set */
-
gq->cur = rswitch_next_queue_index(gq, true, nr_desc);
rswitch_modify(rdev->addr, GWTRC(gq->index), 0, BIT(gq->index % 32));
return ret;
err_unmap:
+ gq->skbs[(gq->cur + nr_desc - 1) % gq->ring_size] = NULL;
dma_unmap_single(ndev->dev.parent, dma_addr_orig, skb->len, DMA_TO_DEVICE);
err_kfree:
@@ -1889,7 +1943,6 @@ static int rswitch_device_alloc(struct rswitch_private *priv, unsigned int index
rdev->np_port = rswitch_get_port_node(rdev);
rdev->disabled = !rdev->np_port;
err = of_get_ethdev_address(rdev->np_port, ndev);
- of_node_put(rdev->np_port);
if (err) {
if (is_valid_ether_addr(rdev->etha->mac_addr))
eth_hw_addr_set(ndev, rdev->etha->mac_addr);
@@ -1901,9 +1954,6 @@ static int rswitch_device_alloc(struct rswitch_private *priv, unsigned int index
if (err < 0)
goto out_get_params;
- if (rdev->priv->gwca.speed < rdev->etha->speed)
- rdev->priv->gwca.speed = rdev->etha->speed;
-
err = rswitch_rxdmac_alloc(ndev);
if (err < 0)
goto out_rxdmac;
@@ -1919,6 +1969,7 @@ out_txdmac:
out_rxdmac:
out_get_params:
+ of_node_put(rdev->np_port);
netif_napi_del(&rdev->napi);
free_netdev(ndev);
@@ -1932,6 +1983,7 @@ static void rswitch_device_free(struct rswitch_private *priv, unsigned int index
rswitch_txdmac_free(ndev);
rswitch_rxdmac_free(ndev);
+ of_node_put(rdev->np_port);
netif_napi_del(&rdev->napi);
free_netdev(ndev);
}
diff --git a/drivers/net/ethernet/renesas/rswitch.h b/drivers/net/ethernet/renesas/rswitch.h
index 72e3ff596d31..532192cbca4b 100644
--- a/drivers/net/ethernet/renesas/rswitch.h
+++ b/drivers/net/ethernet/renesas/rswitch.h
@@ -12,6 +12,7 @@
#define RSWITCH_MAX_NUM_QUEUES 128
+#define RSWITCH_NUM_AGENTS 5
#define RSWITCH_NUM_PORTS 3
#define rswitch_for_each_enabled_port(priv, i) \
for (i = 0; i < RSWITCH_NUM_PORTS; i++) \
@@ -724,35 +725,28 @@ enum rswitch_etha_mode {
#define EAVCC_VEM_SC_TAG (0x3 << 16)
-#define MPIC_PIS_MII 0x00
-#define MPIC_PIS_GMII 0x02
-#define MPIC_PIS_XGMII 0x04
-#define MPIC_LSC_SHIFT 3
-#define MPIC_LSC_100M (1 << MPIC_LSC_SHIFT)
-#define MPIC_LSC_1G (2 << MPIC_LSC_SHIFT)
-#define MPIC_LSC_2_5G (3 << MPIC_LSC_SHIFT)
-
-#define MDIO_READ_C45 0x03
-#define MDIO_WRITE_C45 0x01
+#define MPIC_PIS GENMASK(2, 0)
+#define MPIC_PIS_GMII 2
+#define MPIC_PIS_XGMII 4
+#define MPIC_LSC GENMASK(5, 3)
+#define MPIC_LSC_100M 1
+#define MPIC_LSC_1G 2
+#define MPIC_LSC_2_5G 3
+#define MPIC_PSMCS GENMASK(22, 16)
+#define MPIC_PSMHT GENMASK(26, 24)
#define MPSM_PSME BIT(0)
-#define MPSM_MFF_C45 BIT(2)
-#define MPSM_PRD_SHIFT 16
-#define MPSM_PRD_MASK GENMASK(31, MPSM_PRD_SHIFT)
-
-/* Completion flags */
-#define MMIS1_PAACS BIT(2) /* Address */
-#define MMIS1_PWACS BIT(1) /* Write */
-#define MMIS1_PRACS BIT(0) /* Read */
-#define MMIS1_CLEAR_FLAGS 0xf
-
-#define MPIC_PSMCS_SHIFT 16
-#define MPIC_PSMCS_MASK GENMASK(22, MPIC_PSMCS_SHIFT)
-#define MPIC_PSMCS(val) ((val) << MPIC_PSMCS_SHIFT)
-
-#define MPIC_PSMHT_SHIFT 24
-#define MPIC_PSMHT_MASK GENMASK(26, MPIC_PSMHT_SHIFT)
-#define MPIC_PSMHT(val) ((val) << MPIC_PSMHT_SHIFT)
+#define MPSM_MFF BIT(2)
+#define MPSM_MMF_C22 0
+#define MPSM_MMF_C45 1
+#define MPSM_PDA GENMASK(7, 3)
+#define MPSM_PRA GENMASK(12, 8)
+#define MPSM_POP GENMASK(14, 13)
+#define MPSM_POP_ADDRESS 0
+#define MPSM_POP_WRITE 1
+#define MPSM_POP_READ_C22 2
+#define MPSM_POP_READ_C45 3
+#define MPSM_PRD GENMASK(31, 16)
#define MLVC_PLV BIT(16)
@@ -806,6 +800,7 @@ enum rswitch_gwca_mode {
#define CABPPFLC_INIT_VALUE 0x00800080
/* MFWD */
+#define FWPC0(i) (FWPC00 + (i) * 0x10)
#define FWPC0_LTHTA BIT(0)
#define FWPC0_IP4UE BIT(3)
#define FWPC0_IP4TE BIT(4)
@@ -819,15 +814,15 @@ enum rswitch_gwca_mode {
#define FWPC0_MACHMA BIT(27)
#define FWPC0_VLANSA BIT(28)
-#define FWPC0(i) (FWPC00 + (i) * 0x10)
-#define FWPC0_DEFAULT (FWPC0_LTHTA | FWPC0_IP4UE | FWPC0_IP4TE | \
- FWPC0_IP4OE | FWPC0_L2SE | FWPC0_IP4EA | \
- FWPC0_IPDSA | FWPC0_IPHLA | FWPC0_MACSDA | \
- FWPC0_MACHLA | FWPC0_MACHMA | FWPC0_VLANSA)
#define FWPC1(i) (FWPC10 + (i) * 0x10)
+#define FWCP1_LTHFW GENMASK(16 + (RSWITCH_NUM_AGENTS - 1), 16)
#define FWPC1_DDE BIT(0)
-#define FWPBFC(i) (FWPBFC0 + (i) * 0x10)
+#define FWPC2(i) (FWPC20 + (i) * 0x10)
+#define FWCP2_LTWFW GENMASK(16 + (RSWITCH_NUM_AGENTS - 1), 16)
+
+#define FWPBFC(i) (FWPBFC0 + (i) * 0x10)
+#define FWPBFC_PBDV GENMASK(RSWITCH_NUM_AGENTS - 1, 0)
#define FWPBFCSDC(j, i) (FWPBFCSDC00 + (i) * 0x10 + (j) * 0x04)
@@ -972,14 +967,6 @@ struct rswitch_gwca_queue {
};
};
-struct rswitch_gwca_ts_info {
- struct sk_buff *skb;
- struct list_head list;
-
- int port;
- u8 tag;
-};
-
#define RSWITCH_NUM_IRQ_REGS (RSWITCH_MAX_NUM_QUEUES / BITS_PER_TYPE(u32))
struct rswitch_gwca {
unsigned int index;
@@ -989,14 +976,13 @@ struct rswitch_gwca {
struct rswitch_gwca_queue *queues;
int num_queues;
struct rswitch_gwca_queue ts_queue;
- struct list_head ts_info_list;
DECLARE_BITMAP(used, RSWITCH_MAX_NUM_QUEUES);
u32 tx_irq_bits[RSWITCH_NUM_IRQ_REGS];
u32 rx_irq_bits[RSWITCH_NUM_IRQ_REGS];
- int speed;
};
#define NUM_QUEUES_PER_NDEV 2
+#define TS_TAGS_PER_PORT 256
struct rswitch_device {
struct rswitch_private *priv;
struct net_device *ndev;
@@ -1004,7 +990,8 @@ struct rswitch_device {
void __iomem *addr;
struct rswitch_gwca_queue *tx_queue;
struct rswitch_gwca_queue *rx_queue;
- u8 ts_tag;
+ struct sk_buff *ts_skb[TS_TAGS_PER_PORT];
+ DECLARE_BITMAP(ts_skb_used, TS_TAGS_PER_PORT);
bool disabled;
int port;
diff --git a/drivers/net/ethernet/sfc/io.h b/drivers/net/ethernet/sfc/io.h
index 4cc7b501135f..ef374a8e05c3 100644
--- a/drivers/net/ethernet/sfc/io.h
+++ b/drivers/net/ethernet/sfc/io.h
@@ -217,28 +217,4 @@ _efx_writed_page(struct efx_nic *efx, const efx_dword_t *value,
(reg) != 0xa1c), \
page)
-/* Write TIMER_COMMAND. This is a page-mapped 32-bit CSR, but a bug
- * in the BIU means that writes to TIMER_COMMAND[0] invalidate the
- * collector register.
- */
-static inline void _efx_writed_page_locked(struct efx_nic *efx,
- const efx_dword_t *value,
- unsigned int reg,
- unsigned int page)
-{
- unsigned long flags __attribute__ ((unused));
-
- if (page == 0) {
- spin_lock_irqsave(&efx->biu_lock, flags);
- efx_writed(efx, value, efx_paged_reg(efx, page, reg));
- spin_unlock_irqrestore(&efx->biu_lock, flags);
- } else {
- efx_writed(efx, value, efx_paged_reg(efx, page, reg));
- }
-}
-#define efx_writed_page_locked(efx, value, reg, page) \
- _efx_writed_page_locked(efx, value, \
- reg + BUILD_BUG_ON_ZERO((reg) != 0x420), \
- page)
-
#endif /* EFX_IO_H */
diff --git a/drivers/net/ethernet/sfc/net_driver.h b/drivers/net/ethernet/sfc/net_driver.h
index 620ba6ef3514..f70a7b7d6345 100644
--- a/drivers/net/ethernet/sfc/net_driver.h
+++ b/drivers/net/ethernet/sfc/net_driver.h
@@ -831,6 +831,7 @@ struct efx_arfs_rule {
/**
* struct efx_async_filter_insertion - Request to asynchronously insert a filter
* @net_dev: Reference to the netdevice
+ * @net_dev_tracker: reference tracker entry for @net_dev
* @spec: The filter to insert
* @work: Workitem for this request
* @rxq_index: Identifies the channel for which this request was made
@@ -838,6 +839,7 @@ struct efx_arfs_rule {
*/
struct efx_async_filter_insertion {
struct net_device *net_dev;
+ netdevice_tracker net_dev_tracker;
struct efx_filter_spec spec;
struct work_struct work;
u16 rxq_index;
diff --git a/drivers/net/ethernet/sfc/rx_common.c b/drivers/net/ethernet/sfc/rx_common.c
index ab358fe13e1d..4cc83203e188 100644
--- a/drivers/net/ethernet/sfc/rx_common.c
+++ b/drivers/net/ethernet/sfc/rx_common.c
@@ -897,7 +897,7 @@ static void efx_filter_rfs_work(struct work_struct *data)
/* Release references */
clear_bit(slot_idx, &efx->rps_slot_map);
- dev_put(req->net_dev);
+ netdev_put(req->net_dev, &req->net_dev_tracker);
}
int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
@@ -989,7 +989,8 @@ int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
}
/* Queue the request */
- dev_hold(req->net_dev = net_dev);
+ req->net_dev = net_dev;
+ netdev_hold(req->net_dev, &req->net_dev_tracker, GFP_ATOMIC);
INIT_WORK(&req->work, efx_filter_rfs_work);
req->rxq_index = rxq_index;
req->flow_id = flow_id;
diff --git a/drivers/net/ethernet/sfc/siena/net_driver.h b/drivers/net/ethernet/sfc/siena/net_driver.h
index 9785eff10607..2be3bad3c993 100644
--- a/drivers/net/ethernet/sfc/siena/net_driver.h
+++ b/drivers/net/ethernet/sfc/siena/net_driver.h
@@ -753,6 +753,7 @@ struct efx_arfs_rule {
/**
* struct efx_async_filter_insertion - Request to asynchronously insert a filter
* @net_dev: Reference to the netdevice
+ * @net_dev_tracker: reference tracker entry for @net_dev
* @spec: The filter to insert
* @work: Workitem for this request
* @rxq_index: Identifies the channel for which this request was made
@@ -760,6 +761,7 @@ struct efx_arfs_rule {
*/
struct efx_async_filter_insertion {
struct net_device *net_dev;
+ netdevice_tracker net_dev_tracker;
struct efx_filter_spec spec;
struct work_struct work;
u16 rxq_index;
diff --git a/drivers/net/ethernet/sfc/siena/rx_common.c b/drivers/net/ethernet/sfc/siena/rx_common.c
index 082e35c6caaa..2839d0e0a9c1 100644
--- a/drivers/net/ethernet/sfc/siena/rx_common.c
+++ b/drivers/net/ethernet/sfc/siena/rx_common.c
@@ -888,7 +888,7 @@ static void efx_filter_rfs_work(struct work_struct *data)
/* Release references */
clear_bit(slot_idx, &efx->rps_slot_map);
- dev_put(req->net_dev);
+ netdev_put(req->net_dev, &req->net_dev_tracker);
}
int efx_siena_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
@@ -980,7 +980,8 @@ int efx_siena_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
}
/* Queue the request */
- dev_hold(req->net_dev = net_dev);
+ req->net_dev = net_dev;
+ netdev_hold(req->net_dev, &req->net_dev_tracker, GFP_ATOMIC);
INIT_WORK(&req->work, efx_filter_rfs_work);
req->rxq_index = rxq_index;
req->flow_id = flow_id;
diff --git a/drivers/net/ethernet/sfc/tc_conntrack.c b/drivers/net/ethernet/sfc/tc_conntrack.c
index d90206f27161..c0603f54cec3 100644
--- a/drivers/net/ethernet/sfc/tc_conntrack.c
+++ b/drivers/net/ethernet/sfc/tc_conntrack.c
@@ -16,7 +16,7 @@ static int efx_tc_flow_block(enum tc_setup_type type, void *type_data,
void *cb_priv);
static const struct rhashtable_params efx_tc_ct_zone_ht_params = {
- .key_len = offsetof(struct efx_tc_ct_zone, linkage),
+ .key_len = sizeof_field(struct efx_tc_ct_zone, zone),
.key_offset = 0,
.head_offset = offsetof(struct efx_tc_ct_zone, linkage),
};
diff --git a/drivers/net/ethernet/stmicro/stmmac/Kconfig b/drivers/net/ethernet/stmicro/stmmac/Kconfig
index 6658536a4e17..4cc85a36a1ab 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Kconfig
+++ b/drivers/net/ethernet/stmicro/stmmac/Kconfig
@@ -154,6 +154,18 @@ config DWMAC_RZN1
the stmmac device driver. This support can make use of a custom MII
converter PCS device.
+config DWMAC_S32
+ tristate "NXP S32G/S32R GMAC support"
+ default ARCH_S32
+ depends on OF && (ARCH_S32 || COMPILE_TEST)
+ help
+ Support for ethernet controller on NXP S32CC SOCs.
+
+ This selects NXP SoC glue layer support for the stmmac
+ device driver. This driver is used for the S32CC series
+ SOCs GMAC ethernet controller, ie. S32G2xx, S32G3xx and
+ S32R45.
+
config DWMAC_SOCFPGA
tristate "SOCFPGA dwmac support"
default ARCH_INTEL_SOCFPGA
diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile
index 2389fd261344..b26f0e79c2b3 100644
--- a/drivers/net/ethernet/stmicro/stmmac/Makefile
+++ b/drivers/net/ethernet/stmicro/stmmac/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o dwmac-meson8b.o
obj-$(CONFIG_DWMAC_QCOM_ETHQOS) += dwmac-qcom-ethqos.o
obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o
obj-$(CONFIG_DWMAC_RZN1) += dwmac-rzn1.o
+obj-$(CONFIG_DWMAC_S32) += dwmac-s32.o
obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o
obj-$(CONFIG_DWMAC_STARFIVE) += dwmac-starfive.o
obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o
diff --git a/drivers/net/ethernet/stmicro/stmmac/common.h b/drivers/net/ethernet/stmicro/stmmac/common.h
index 1367fa5c9b8e..e25db747a81a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/common.h
+++ b/drivers/net/ethernet/stmicro/stmmac/common.h
@@ -257,6 +257,8 @@ struct stmmac_safety_stats {
#define CSR_F_150M 150000000
#define CSR_F_250M 250000000
#define CSR_F_300M 300000000
+#define CSR_F_500M 500000000
+#define CSR_F_800M 800000000
#define MAC_CSR_H_FRQ_MASK 0x20
@@ -543,18 +545,8 @@ struct dma_features {
#define STMMAC_VLAN_INSERT 0x2
#define STMMAC_VLAN_REPLACE 0x3
-extern const struct stmmac_desc_ops enh_desc_ops;
-extern const struct stmmac_desc_ops ndesc_ops;
-
struct mac_device_info;
-extern const struct stmmac_hwtimestamp stmmac_ptp;
-extern const struct stmmac_hwtimestamp dwmac1000_ptp;
-extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
-
-extern const struct ptp_clock_info stmmac_ptp_clock_ops;
-extern const struct ptp_clock_info dwmac1000_ptp_clock_ops;
-
struct mac_link {
u32 caps;
u32 speed_mask;
@@ -641,8 +633,4 @@ void stmmac_dwmac4_set_mac(void __iomem *ioaddr, bool enable);
void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
-extern const struct stmmac_mode_ops ring_mode_ops;
-extern const struct stmmac_mode_ops chain_mode_ops;
-extern const struct stmmac_desc_ops dwmac4_desc_ops;
-
#endif /* __COMMON_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
index 83290e707df5..bd4eb187f8c6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
@@ -181,24 +181,19 @@ static void dwc_qos_remove(struct platform_device *pdev)
static void tegra_eqos_fix_speed(void *priv, unsigned int speed, unsigned int mode)
{
struct tegra_eqos *eqos = priv;
- unsigned long rate = 125000000;
bool needs_calibration = false;
+ long rate = 125000000;
u32 value;
int err;
switch (speed) {
case SPEED_1000:
- needs_calibration = true;
- rate = 125000000;
- break;
-
case SPEED_100:
needs_calibration = true;
- rate = 25000000;
- break;
+ fallthrough;
case SPEED_10:
- rate = 2500000;
+ rate = rgmii_clock(speed);
break;
default:
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
index 641f3cd019a3..4ac7a78f4b14 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-imx.c
@@ -36,6 +36,8 @@
#define MX93_GPR_ENET_QOS_INTF_SEL_RMII (0x4 << 1)
#define MX93_GPR_ENET_QOS_INTF_SEL_RGMII (0x1 << 1)
#define MX93_GPR_ENET_QOS_CLK_GEN_EN (0x1 << 0)
+#define MX93_GPR_ENET_QOS_CLK_SEL_MASK BIT_MASK(0)
+#define MX93_GPR_CLK_SEL_OFFSET (4)
#define DMA_BUS_MODE 0x00001000
#define DMA_BUS_MODE_SFT_RESET (0x1 << 0)
@@ -108,13 +110,21 @@ imx8dxl_set_intf_mode(struct plat_stmmacenet_data *plat_dat)
static int imx93_set_intf_mode(struct plat_stmmacenet_data *plat_dat)
{
struct imx_priv_data *dwmac = plat_dat->bsp_priv;
- int val;
+ int val, ret;
switch (plat_dat->mac_interface) {
case PHY_INTERFACE_MODE_MII:
val = MX93_GPR_ENET_QOS_INTF_SEL_MII;
break;
case PHY_INTERFACE_MODE_RMII:
+ if (dwmac->rmii_refclk_ext) {
+ ret = regmap_clear_bits(dwmac->intf_regmap,
+ dwmac->intf_reg_off +
+ MX93_GPR_CLK_SEL_OFFSET,
+ MX93_GPR_ENET_QOS_CLK_SEL_MASK);
+ if (ret)
+ return ret;
+ }
val = MX93_GPR_ENET_QOS_INTF_SEL_RMII;
break;
case PHY_INTERFACE_MODE_RGMII:
@@ -186,7 +196,7 @@ static void imx_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mod
{
struct plat_stmmacenet_data *plat_dat;
struct imx_priv_data *dwmac = priv;
- unsigned long rate;
+ long rate;
int err;
plat_dat = dwmac->plat_dat;
@@ -196,17 +206,8 @@ static void imx_dwmac_fix_speed(void *priv, unsigned int speed, unsigned int mod
(plat_dat->mac_interface == PHY_INTERFACE_MODE_MII))
return;
- switch (speed) {
- case SPEED_1000:
- rate = 125000000;
- break;
- case SPEED_100:
- rate = 25000000;
- break;
- case SPEED_10:
- rate = 2500000;
- break;
- default:
+ rate = rgmii_clock(speed);
+ if (rate < 0) {
dev_err(dwmac->dev, "invalid speed %u\n", speed);
return;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
index d94f0a150e93..ddee6154d40b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel-plat.c
@@ -31,27 +31,13 @@ struct intel_dwmac_data {
static void kmb_eth_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode)
{
struct intel_dwmac *dwmac = priv;
- unsigned long rate;
+ long rate;
int ret;
- rate = clk_get_rate(dwmac->tx_clk);
-
- switch (speed) {
- case SPEED_1000:
- rate = 125000000;
- break;
-
- case SPEED_100:
- rate = 25000000;
- break;
-
- case SPEED_10:
- rate = 2500000;
- break;
-
- default:
+ rate = rgmii_clock(speed);
+ if (rate < 0) {
dev_err(dwmac->dev, "Invalid speed\n");
- break;
+ return;
}
ret = clk_set_rate(dwmac->tx_clk, rate);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
index 901a3c1959fa..2a5b38723635 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c
@@ -777,7 +777,7 @@ static void ethqos_ptp_clk_freq_config(struct stmmac_priv *priv)
netdev_err(priv->dev, "Failed to max out clk_ptp_ref: %d\n", err);
plat_dat->clk_ptp_rate = clk_get_rate(plat_dat->clk_ptp_ref);
- netdev_dbg(priv->dev, "PTP rate %d\n", plat_dat->clk_ptp_rate);
+ netdev_dbg(priv->dev, "PTP rate %lu\n", plat_dat->clk_ptp_rate);
}
static int qcom_ethqos_probe(struct platform_device *pdev)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 8cb374668b74..a4dc89e23a68 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
@@ -1079,20 +1079,11 @@ static void rk3568_set_gmac_speed(struct rk_priv_data *bsp_priv, int speed)
{
struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk;
struct device *dev = &bsp_priv->pdev->dev;
- unsigned long rate;
+ long rate;
int ret;
- switch (speed) {
- case 10:
- rate = 2500000;
- break;
- case 100:
- rate = 25000000;
- break;
- case 1000:
- rate = 125000000;
- break;
- default:
+ rate = rgmii_clock(speed);
+ if (rate < 0) {
dev_err(dev, "unknown speed value for GMAC speed=%d", speed);
return;
}
@@ -1540,20 +1531,11 @@ static void rv1126_set_rgmii_speed(struct rk_priv_data *bsp_priv, int speed)
{
struct clk *clk_mac_speed = bsp_priv->clks[RK_CLK_MAC_SPEED].clk;
struct device *dev = &bsp_priv->pdev->dev;
- unsigned long rate;
+ long rate;
int ret;
- switch (speed) {
- case 10:
- rate = 2500000;
- break;
- case 100:
- rate = 25000000;
- break;
- case 1000:
- rate = 125000000;
- break;
- default:
+ rate = rgmii_clock(speed);
+ if (rate < 0) {
dev_err(dev, "unknown speed value for RGMII speed=%d", speed);
return;
}
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
new file mode 100644
index 000000000000..9cc0e5817416
--- /dev/null
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-s32.c
@@ -0,0 +1,202 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * NXP S32G/R GMAC glue layer
+ *
+ * Copyright 2019-2024 NXP
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/device.h>
+#include <linux/ethtool.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/of_address.h>
+#include <linux/phy.h>
+#include <linux/phylink.h>
+#include <linux/platform_device.h>
+#include <linux/stmmac.h>
+
+#include "stmmac_platform.h"
+
+#define GMAC_INTF_RATE_125M 125000000 /* 125MHz */
+
+/* SoC PHY interface control register */
+#define PHY_INTF_SEL_MII 0x00
+#define PHY_INTF_SEL_SGMII 0x01
+#define PHY_INTF_SEL_RGMII 0x02
+#define PHY_INTF_SEL_RMII 0x08
+
+struct s32_priv_data {
+ void __iomem *ioaddr;
+ void __iomem *ctrl_sts;
+ struct device *dev;
+ phy_interface_t *intf_mode;
+ struct clk *tx_clk;
+ struct clk *rx_clk;
+};
+
+static int s32_gmac_write_phy_intf_select(struct s32_priv_data *gmac)
+{
+ writel(PHY_INTF_SEL_RGMII, gmac->ctrl_sts);
+
+ dev_dbg(gmac->dev, "PHY mode set to %s\n", phy_modes(*gmac->intf_mode));
+
+ return 0;
+}
+
+static int s32_gmac_init(struct platform_device *pdev, void *priv)
+{
+ struct s32_priv_data *gmac = priv;
+ int ret;
+
+ /* Set initial TX interface clock */
+ ret = clk_prepare_enable(gmac->tx_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't enable tx clock\n");
+ return ret;
+ }
+ ret = clk_set_rate(gmac->tx_clk, GMAC_INTF_RATE_125M);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't set tx clock\n");
+ goto err_tx_disable;
+ }
+
+ /* Set initial RX interface clock */
+ ret = clk_prepare_enable(gmac->rx_clk);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't enable rx clock\n");
+ goto err_tx_disable;
+ }
+ ret = clk_set_rate(gmac->rx_clk, GMAC_INTF_RATE_125M);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't set rx clock\n");
+ goto err_txrx_disable;
+ }
+
+ /* Set interface mode */
+ ret = s32_gmac_write_phy_intf_select(gmac);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't set PHY interface mode\n");
+ goto err_txrx_disable;
+ }
+
+ return 0;
+
+err_txrx_disable:
+ clk_disable_unprepare(gmac->rx_clk);
+err_tx_disable:
+ clk_disable_unprepare(gmac->tx_clk);
+ return ret;
+}
+
+static void s32_gmac_exit(struct platform_device *pdev, void *priv)
+{
+ struct s32_priv_data *gmac = priv;
+
+ clk_disable_unprepare(gmac->tx_clk);
+ clk_disable_unprepare(gmac->rx_clk);
+}
+
+static void s32_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode)
+{
+ struct s32_priv_data *gmac = priv;
+ long tx_clk_rate;
+ int ret;
+
+ tx_clk_rate = rgmii_clock(speed);
+ if (tx_clk_rate < 0) {
+ dev_err(gmac->dev, "Unsupported/Invalid speed: %d\n", speed);
+ return;
+ }
+
+ dev_dbg(gmac->dev, "Set tx clock to %ld Hz\n", tx_clk_rate);
+ ret = clk_set_rate(gmac->tx_clk, tx_clk_rate);
+ if (ret)
+ dev_err(gmac->dev, "Can't set tx clock\n");
+}
+
+static int s32_dwmac_probe(struct platform_device *pdev)
+{
+ struct plat_stmmacenet_data *plat;
+ struct device *dev = &pdev->dev;
+ struct stmmac_resources res;
+ struct s32_priv_data *gmac;
+ int ret;
+
+ gmac = devm_kzalloc(&pdev->dev, sizeof(*gmac), GFP_KERNEL);
+ if (!gmac)
+ return -ENOMEM;
+
+ gmac->dev = &pdev->dev;
+
+ ret = stmmac_get_platform_resources(pdev, &res);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "Failed to get platform resources\n");
+
+ plat = devm_stmmac_probe_config_dt(pdev, res.mac);
+ if (IS_ERR(plat))
+ return dev_err_probe(dev, PTR_ERR(plat),
+ "dt configuration failed\n");
+
+ /* PHY interface mode control reg */
+ gmac->ctrl_sts = devm_platform_get_and_ioremap_resource(pdev, 1, NULL);
+ if (IS_ERR(gmac->ctrl_sts))
+ return dev_err_probe(dev, PTR_ERR(gmac->ctrl_sts),
+ "S32CC config region is missing\n");
+
+ /* tx clock */
+ gmac->tx_clk = devm_clk_get(&pdev->dev, "tx");
+ if (IS_ERR(gmac->tx_clk))
+ return dev_err_probe(dev, PTR_ERR(gmac->tx_clk),
+ "tx clock not found\n");
+
+ /* rx clock */
+ gmac->rx_clk = devm_clk_get(&pdev->dev, "rx");
+ if (IS_ERR(gmac->rx_clk))
+ return dev_err_probe(dev, PTR_ERR(gmac->rx_clk),
+ "rx clock not found\n");
+
+ gmac->intf_mode = &plat->phy_interface;
+ gmac->ioaddr = res.addr;
+
+ /* S32CC core feature set */
+ plat->has_gmac4 = true;
+ plat->pmt = 1;
+ plat->flags |= STMMAC_FLAG_SPH_DISABLE;
+ plat->rx_fifo_size = 20480;
+ plat->tx_fifo_size = 20480;
+
+ plat->init = s32_gmac_init;
+ plat->exit = s32_gmac_exit;
+ plat->fix_mac_speed = s32_fix_mac_speed;
+
+ plat->bsp_priv = gmac;
+
+ return stmmac_pltfr_probe(pdev, plat, &res);
+}
+
+static const struct of_device_id s32_dwmac_match[] = {
+ { .compatible = "nxp,s32g2-dwmac" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, s32_dwmac_match);
+
+static struct platform_driver s32_dwmac_driver = {
+ .probe = s32_dwmac_probe,
+ .remove = stmmac_pltfr_remove,
+ .driver = {
+ .name = "s32-dwmac",
+ .pm = &stmmac_pltfr_pm_ops,
+ .of_match_table = s32_dwmac_match,
+ },
+};
+module_platform_driver(s32_dwmac_driver);
+
+MODULE_AUTHOR("Jan Petrous (OSS) <jan.petrous@oss.nxp.com>");
+MODULE_DESCRIPTION("NXP S32G/R common chassis GMAC driver");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
index 421666279dd3..0a0a363d3730 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-starfive.c
@@ -34,24 +34,13 @@ struct starfive_dwmac {
static void starfive_dwmac_fix_mac_speed(void *priv, unsigned int speed, unsigned int mode)
{
struct starfive_dwmac *dwmac = priv;
- unsigned long rate;
+ long rate;
int err;
- rate = clk_get_rate(dwmac->clk_tx);
-
- switch (speed) {
- case SPEED_1000:
- rate = 125000000;
- break;
- case SPEED_100:
- rate = 25000000;
- break;
- case SPEED_10:
- rate = 2500000;
- break;
- default:
+ rate = rgmii_clock(speed);
+ if (rate < 0) {
dev_err(dwmac->dev, "invalid speed %u\n", speed);
- break;
+ return;
}
err = clk_set_rate(dwmac->clk_tx, rate);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
index a6ff02d905a9..eabc4da9e1a9 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
@@ -21,10 +21,7 @@
#include "stmmac_platform.h"
-#define DWMAC_125MHZ 125000000
#define DWMAC_50MHZ 50000000
-#define DWMAC_25MHZ 25000000
-#define DWMAC_2_5MHZ 2500000
#define IS_PHY_IF_MODE_RGMII(iface) (iface == PHY_INTERFACE_MODE_RGMII || \
iface == PHY_INTERFACE_MODE_RGMII_ID || \
@@ -140,7 +137,7 @@ static void stih4xx_fix_retime_src(void *priv, u32 spd, unsigned int mode)
struct sti_dwmac *dwmac = priv;
u32 src = dwmac->tx_retime_src;
u32 reg = dwmac->ctrl_reg;
- u32 freq = 0;
+ long freq = 0;
if (dwmac->interface == PHY_INTERFACE_MODE_MII) {
src = TX_RETIME_SRC_TXCLK;
@@ -153,19 +150,14 @@ static void stih4xx_fix_retime_src(void *priv, u32 spd, unsigned int mode)
}
} else if (IS_PHY_IF_MODE_RGMII(dwmac->interface)) {
/* On GiGa clk source can be either ext or from clkgen */
- if (spd == SPEED_1000) {
- freq = DWMAC_125MHZ;
- } else {
+ freq = rgmii_clock(spd);
+
+ if (spd != SPEED_1000 && freq > 0)
/* Switch to clkgen for these speeds */
src = TX_RETIME_SRC_CLKGEN;
- if (spd == SPEED_100)
- freq = DWMAC_25MHZ;
- else if (spd == SPEED_10)
- freq = DWMAC_2_5MHZ;
- }
}
- if (src == TX_RETIME_SRC_CLKGEN && freq)
+ if (src == TX_RETIME_SRC_CLKGEN && freq > 0)
clk_set_rate(dwmac->clk, freq);
regmap_update_bits(dwmac->regmap, reg, STIH4XX_RETIME_SRC_MASK,
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
index 3827997d2132..dc903b846b1b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-tegra.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/iommu.h>
#include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/module.h>
@@ -19,6 +20,8 @@ struct tegra_mgbe {
struct reset_control *rst_mac;
struct reset_control *rst_pcs;
+ u32 iommu_sid;
+
void __iomem *hv;
void __iomem *regs;
void __iomem *xpcs;
@@ -50,7 +53,6 @@ struct tegra_mgbe {
#define MGBE_WRAP_COMMON_INTR_ENABLE 0x8704
#define MAC_SBD_INTR BIT(2)
#define MGBE_WRAP_AXI_ASID0_CTRL 0x8400
-#define MGBE_SID 0x6
static int __maybe_unused tegra_mgbe_suspend(struct device *dev)
{
@@ -84,7 +86,7 @@ static int __maybe_unused tegra_mgbe_resume(struct device *dev)
writel(MAC_SBD_INTR, mgbe->regs + MGBE_WRAP_COMMON_INTR_ENABLE);
/* Program SID */
- writel(MGBE_SID, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL);
+ writel(mgbe->iommu_sid, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL);
value = readl(mgbe->xpcs + XPCS_WRAP_UPHY_STATUS);
if ((value & XPCS_WRAP_UPHY_STATUS_TX_P_UP) == 0) {
@@ -241,6 +243,12 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
if (IS_ERR(mgbe->xpcs))
return PTR_ERR(mgbe->xpcs);
+ /* get controller's stream id from iommu property in device tree */
+ if (!tegra_dev_iommu_get_stream_id(mgbe->dev, &mgbe->iommu_sid)) {
+ dev_err(mgbe->dev, "failed to get iommu stream id\n");
+ return -EINVAL;
+ }
+
res.addr = mgbe->regs;
res.irq = irq;
@@ -346,7 +354,7 @@ static int tegra_mgbe_probe(struct platform_device *pdev)
writel(MAC_SBD_INTR, mgbe->regs + MGBE_WRAP_COMMON_INTR_ENABLE);
/* Program SID */
- writel(MGBE_SID, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL);
+ writel(mgbe->iommu_sid, mgbe->hv + MGBE_WRAP_AXI_ASID0_CTRL);
plat->flags |= STMMAC_FLAG_SERDES_UP_AFTER_PHY_LINKUP;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index c25781874aa7..c36f90a782c5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -27,7 +27,7 @@ static void dwmac4_core_init(struct mac_device_info *hw,
struct stmmac_priv *priv = netdev_priv(dev);
void __iomem *ioaddr = hw->pcsr;
u32 value = readl(ioaddr + GMAC_CONFIG);
- u32 clk_rate;
+ unsigned long clk_rate;
value |= GMAC_CORE_INIT;
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h
index 1ce6f43d545a..806555976496 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_descs.h
@@ -144,4 +144,7 @@
/* TDS3 use for both format (read and write back) */
#define RDES3_OWN BIT(31)
+extern const struct stmmac_mode_ops dwmac4_ring_mode_ops;
+extern const struct stmmac_desc_ops dwmac4_desc_ops;
+
#endif /* __DWMAC4_DESCS_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
index a04a79003692..20027d3c25a7 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
@@ -493,4 +493,9 @@
#define XGMAC_RDES3_TSD BIT(6)
#define XGMAC_RDES3_TSA BIT(4)
+extern const struct stmmac_ops dwxgmac210_ops;
+extern const struct stmmac_ops dwxlgmac2_ops;
+extern const struct stmmac_dma_ops dwxgmac210_dma_ops;
+extern const struct stmmac_desc_ops dwxgmac210_desc_ops;
+
#endif /* __STMMAC_DWXGMAC2_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.c b/drivers/net/ethernet/stmicro/stmmac/hwif.c
index a72d336a8350..31bdbab9a46c 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.c
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.c
@@ -9,6 +9,8 @@
#include "stmmac_fpe.h"
#include "stmmac_ptp.h"
#include "stmmac_est.h"
+#include "dwmac4_descs.h"
+#include "dwxgmac2.h"
static u32 stmmac_get_id(struct stmmac_priv *priv, u32 id_reg)
{
@@ -265,7 +267,7 @@ static const struct stmmac_hwif_entry {
.hwtimestamp = &stmmac_ptp,
.ptp = &stmmac_ptp_clock_ops,
.mode = NULL,
- .tc = &dwxgmac_tc_ops,
+ .tc = &dwmac510_tc_ops,
.mmc = &dwxgmac_mmc_ops,
.est = &dwmac510_est_ops,
.setup = dwxgmac2_setup,
@@ -288,7 +290,7 @@ static const struct stmmac_hwif_entry {
.hwtimestamp = &stmmac_ptp,
.ptp = &stmmac_ptp_clock_ops,
.mode = NULL,
- .tc = &dwxgmac_tc_ops,
+ .tc = &dwmac510_tc_ops,
.mmc = &dwxgmac_mmc_ops,
.est = &dwmac510_est_ops,
.setup = dwxlgmac2_setup,
diff --git a/drivers/net/ethernet/stmicro/stmmac/hwif.h b/drivers/net/ethernet/stmicro/stmmac/hwif.h
index 64f8ed67dcc4..2f7295b6c1c5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/hwif.h
+++ b/drivers/net/ethernet/stmicro/stmmac/hwif.h
@@ -665,6 +665,15 @@ struct stmmac_regs_off {
u32 est_off;
};
+extern const struct stmmac_desc_ops enh_desc_ops;
+extern const struct stmmac_desc_ops ndesc_ops;
+
+extern const struct stmmac_hwtimestamp stmmac_ptp;
+extern const struct stmmac_hwtimestamp dwmac1000_ptp;
+
+extern const struct stmmac_mode_ops ring_mode_ops;
+extern const struct stmmac_mode_ops chain_mode_ops;
+
extern const struct stmmac_ops dwmac100_ops;
extern const struct stmmac_dma_ops dwmac100_dma_ops;
extern const struct stmmac_ops dwmac1000_ops;
@@ -676,14 +685,6 @@ extern const struct stmmac_dma_ops dwmac410_dma_ops;
extern const struct stmmac_ops dwmac510_ops;
extern const struct stmmac_tc_ops dwmac4_tc_ops;
extern const struct stmmac_tc_ops dwmac510_tc_ops;
-extern const struct stmmac_tc_ops dwxgmac_tc_ops;
-extern const struct stmmac_ops dwxgmac210_ops;
-extern const struct stmmac_ops dwxlgmac2_ops;
-extern const struct stmmac_dma_ops dwxgmac210_dma_ops;
-extern const struct stmmac_desc_ops dwxgmac210_desc_ops;
-extern const struct stmmac_mmc_ops dwmac_mmc_ops;
-extern const struct stmmac_mmc_ops dwxgmac_mmc_ops;
-extern const struct stmmac_est_ops dwmac510_est_ops;
#define GMAC_VERSION 0x00000020 /* GMAC CORE Version */
#define GMAC4_VERSION 0x00000110 /* GMAC4+ CORE Version */
diff --git a/drivers/net/ethernet/stmicro/stmmac/mmc.h b/drivers/net/ethernet/stmicro/stmmac/mmc.h
index 5d1ea3e07459..1cba39fb2c44 100644
--- a/drivers/net/ethernet/stmicro/stmmac/mmc.h
+++ b/drivers/net/ethernet/stmicro/stmmac/mmc.h
@@ -139,4 +139,7 @@ struct stmmac_counters {
unsigned int mmc_rx_fpe_fragment_cntr;
};
+extern const struct stmmac_mmc_ops dwmac_mmc_ops;
+extern const struct stmmac_mmc_ops dwxgmac_mmc_ops;
+
#endif /* __MMC_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index 1d86439b8a14..548b28fed9b6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -126,7 +126,6 @@ struct stmmac_rx_queue {
unsigned int cur_rx;
unsigned int dirty_rx;
unsigned int buf_alloc_num;
- u32 rx_zeroc_thresh;
dma_addr_t dma_rx_phy;
u32 rx_tail_addr;
unsigned int state_saved;
@@ -266,7 +265,6 @@ struct stmmac_priv {
int sph_cap;
u32 sarc_type;
- unsigned int rx_copybreak;
u32 rx_riwt[MTL_MAX_TX_QUEUES];
int hwts_rx_en;
@@ -418,14 +416,6 @@ static inline bool stmmac_xdp_is_enabled(struct stmmac_priv *priv)
return !!priv->xdp_prog;
}
-static inline unsigned int stmmac_rx_offset(struct stmmac_priv *priv)
-{
- if (stmmac_xdp_is_enabled(priv))
- return XDP_PACKET_HEADROOM;
-
- return 0;
-}
-
void stmmac_disable_rx_queue(struct stmmac_priv *priv, u32 queue);
void stmmac_enable_rx_queue(struct stmmac_priv *priv, u32 queue);
void stmmac_disable_tx_queue(struct stmmac_priv *priv, u32 queue);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_est.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_est.h
index 7a858c566e7e..d247fa383a6e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_est.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_est.h
@@ -62,3 +62,5 @@
#define EST_SRWO BIT(0)
#define EST_GCL_DATA 0x00000034
+
+extern const struct stmmac_est_ops dwmac510_est_ops;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
index 1d77389ce953..16b4d8c21c90 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ethtool.c
@@ -1227,43 +1227,6 @@ static int stmmac_get_ts_info(struct net_device *dev,
return ethtool_op_get_ts_info(dev, info);
}
-static int stmmac_get_tunable(struct net_device *dev,
- const struct ethtool_tunable *tuna, void *data)
-{
- struct stmmac_priv *priv = netdev_priv(dev);
- int ret = 0;
-
- switch (tuna->id) {
- case ETHTOOL_RX_COPYBREAK:
- *(u32 *)data = priv->rx_copybreak;
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static int stmmac_set_tunable(struct net_device *dev,
- const struct ethtool_tunable *tuna,
- const void *data)
-{
- struct stmmac_priv *priv = netdev_priv(dev);
- int ret = 0;
-
- switch (tuna->id) {
- case ETHTOOL_RX_COPYBREAK:
- priv->rx_copybreak = *(u32 *)data;
- break;
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
static int stmmac_get_mm(struct net_device *ndev,
struct ethtool_mm_state *state)
{
@@ -1390,8 +1353,6 @@ static const struct ethtool_ops stmmac_ethtool_ops = {
.set_per_queue_coalesce = stmmac_set_per_queue_coalesce,
.get_channels = stmmac_get_channels,
.set_channels = stmmac_set_channels,
- .get_tunable = stmmac_get_tunable,
- .set_tunable = stmmac_set_tunable,
.get_link_ksettings = stmmac_ethtool_get_link_ksettings,
.set_link_ksettings = stmmac_ethtool_set_link_ksettings,
.get_mm = stmmac_get_mm,
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 9b262cdad60b..038df1b2bb58 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -77,7 +77,6 @@ module_param(phyaddr, int, 0444);
MODULE_PARM_DESC(phyaddr, "Physical device address");
#define STMMAC_TX_THRESH(x) ((x)->dma_conf.dma_tx_size / 4)
-#define STMMAC_RX_THRESH(x) ((x)->dma_conf.dma_rx_size / 4)
/* Limit to make sure XDP TX and slow path can coexist */
#define STMMAC_XSK_TX_BUDGET_MAX 256
@@ -107,8 +106,6 @@ static int buf_sz = DEFAULT_BUFSIZE;
module_param(buf_sz, int, 0644);
MODULE_PARM_DESC(buf_sz, "DMA buffer size");
-#define STMMAC_RX_COPYBREAK 256
-
static const u32 default_msg_level = (NETIF_MSG_DRV | NETIF_MSG_PROBE |
NETIF_MSG_LINK | NETIF_MSG_IFUP |
NETIF_MSG_IFDOWN | NETIF_MSG_TIMER);
@@ -301,7 +298,7 @@ static void stmmac_global_err(struct stmmac_priv *priv)
*/
static void stmmac_clk_csr_set(struct stmmac_priv *priv)
{
- u32 clk_rate;
+ unsigned long clk_rate;
clk_rate = clk_get_rate(priv->plat->stmmac_clk);
@@ -325,6 +322,10 @@ static void stmmac_clk_csr_set(struct stmmac_priv *priv)
priv->clk_csr = STMMAC_CSR_150_250M;
else if ((clk_rate >= CSR_F_250M) && (clk_rate <= CSR_F_300M))
priv->clk_csr = STMMAC_CSR_250_300M;
+ else if ((clk_rate >= CSR_F_300M) && (clk_rate < CSR_F_500M))
+ priv->clk_csr = STMMAC_CSR_300_500M;
+ else if ((clk_rate >= CSR_F_500M) && (clk_rate < CSR_F_800M))
+ priv->clk_csr = STMMAC_CSR_500_800M;
}
if (priv->plat->flags & STMMAC_FLAG_HAS_SUN8I) {
@@ -1202,6 +1203,7 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
struct stmmac_mdio_bus_data *mdio_bus_data;
int mode = priv->plat->phy_interface;
struct fwnode_handle *fwnode;
+ struct phylink_pcs *pcs;
struct phylink *phylink;
priv->phylink_config.dev = &priv->dev->dev;
@@ -1223,8 +1225,14 @@ static int stmmac_phy_setup(struct stmmac_priv *priv)
/* If we have an xpcs, it defines which PHY interfaces are supported. */
if (priv->hw->xpcs)
- xpcs_get_interfaces(priv->hw->xpcs,
- priv->phylink_config.supported_interfaces);
+ pcs = xpcs_to_phylink_pcs(priv->hw->xpcs);
+ else
+ pcs = priv->hw->phylink_pcs;
+
+ if (pcs)
+ phy_interface_or(priv->phylink_config.supported_interfaces,
+ priv->phylink_config.supported_interfaces,
+ pcs->supported_interfaces);
fwnode = priv->plat->port_node;
if (!fwnode)
@@ -1307,6 +1315,14 @@ static void stmmac_display_rings(struct stmmac_priv *priv,
stmmac_display_tx_rings(priv, dma_conf);
}
+static unsigned int stmmac_rx_offset(struct stmmac_priv *priv)
+{
+ if (stmmac_xdp_is_enabled(priv))
+ return XDP_PACKET_HEADROOM;
+
+ return 0;
+}
+
static int stmmac_set_bfsize(int mtu, int bufsize)
{
int ret = bufsize;
@@ -3923,8 +3939,6 @@ static int __stmmac_open(struct net_device *dev,
}
}
- priv->rx_copybreak = STMMAC_RX_COPYBREAK;
-
buf_sz = dma_conf->dma_buf_sz;
for (int i = 0; i < MTL_MAX_TX_QUEUES; i++)
if (priv->dma_conf.tx_queue[i].tbs & STMMAC_TBS_EN)
@@ -4117,11 +4131,7 @@ static void stmmac_tso_allocator(struct stmmac_priv *priv, dma_addr_t des,
desc = &tx_q->dma_tx[tx_q->cur_tx];
curr_addr = des + (total_len - tmp_len);
- if (priv->dma_cap.addr64 <= 32)
- desc->des0 = cpu_to_le32(curr_addr);
- else
- stmmac_set_desc_addr(priv, desc, curr_addr);
-
+ stmmac_set_desc_addr(priv, desc, curr_addr);
buff_size = tmp_len >= TSO_MAX_BUFF_SIZE ?
TSO_MAX_BUFF_SIZE : tmp_len;
@@ -4167,17 +4177,27 @@ static void stmmac_flush_tx_descriptors(struct stmmac_priv *priv, int queue)
* First Descriptor
* --------
* | DES0 |---> buffer1 = L2/L3/L4 header
- * | DES1 |---> TCP Payload (can continue on next descr...)
- * | DES2 |---> buffer 1 and 2 len
+ * | DES1 |---> can be used as buffer2 for TCP Payload if the DMA AXI address
+ * | | width is 32-bit, but we never use it.
+ * | | Also can be used as the most-significant 8-bits or 16-bits of
+ * | | buffer1 address pointer if the DMA AXI address width is 40-bit
+ * | | or 48-bit, and we always use it.
+ * | DES2 |---> buffer1 len
* | DES3 |---> must set TSE, TCP hdr len-> [22:19]. TCP payload len [17:0]
* --------
+ * --------
+ * | DES0 |---> buffer1 = TCP Payload (can continue on next descr...)
+ * | DES1 |---> same as the First Descriptor
+ * | DES2 |---> buffer1 len
+ * | DES3 |
+ * --------
* |
* ...
* |
* --------
- * | DES0 | --| Split TCP Payload on Buffers 1 and 2
- * | DES1 | --|
- * | DES2 | --> buffer 1 and 2 len
+ * | DES0 |---> buffer1 = Split TCP Payload
+ * | DES1 |---> same as the First Descriptor
+ * | DES2 |---> buffer1 len
* | DES3 |
* --------
*
@@ -4187,15 +4207,14 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
{
struct dma_desc *desc, *first, *mss_desc = NULL;
struct stmmac_priv *priv = netdev_priv(dev);
- int tmp_pay_len = 0, first_tx, nfrags;
unsigned int first_entry, tx_packets;
struct stmmac_txq_stats *txq_stats;
struct stmmac_tx_queue *tx_q;
u32 pay_len, mss, queue;
+ int i, first_tx, nfrags;
u8 proto_hdr_len, hdr;
dma_addr_t des;
bool set_ic;
- int i;
/* Always insert VLAN tag to SKB payload for TSO frames.
*
@@ -4280,23 +4299,9 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
if (dma_mapping_error(priv->device, des))
goto dma_map_err;
- if (priv->dma_cap.addr64 <= 32) {
- first->des0 = cpu_to_le32(des);
-
- /* Fill start of payload in buff2 of first descriptor */
- if (pay_len)
- first->des1 = cpu_to_le32(des + proto_hdr_len);
-
- /* If needed take extra descriptors to fill the remaining payload */
- tmp_pay_len = pay_len - TSO_MAX_BUFF_SIZE;
- } else {
- stmmac_set_desc_addr(priv, first, des);
- tmp_pay_len = pay_len;
- des += proto_hdr_len;
- pay_len = 0;
- }
-
- stmmac_tso_allocator(priv, des, tmp_pay_len, (nfrags == 0), queue);
+ stmmac_set_desc_addr(priv, first, des);
+ stmmac_tso_allocator(priv, des + proto_hdr_len, pay_len,
+ (nfrags == 0), queue);
/* In case two or more DMA transmit descriptors are allocated for this
* non-paged SKB data, the DMA buffer address should be saved to
@@ -4400,11 +4405,9 @@ static netdev_tx_t stmmac_tso_xmit(struct sk_buff *skb, struct net_device *dev)
}
/* Complete the first descriptor before granting the DMA */
- stmmac_prepare_tso_tx_desc(priv, first, 1,
- proto_hdr_len,
- pay_len,
- 1, tx_q->tx_skbuff_dma[first_entry].last_segment,
- hdr / 4, (skb->len - proto_hdr_len));
+ stmmac_prepare_tso_tx_desc(priv, first, 1, proto_hdr_len, 0, 1,
+ tx_q->tx_skbuff_dma[first_entry].last_segment,
+ hdr / 4, (skb->len - proto_hdr_len));
/* If context desc is used to change MSS */
if (mss_desc) {
@@ -5472,7 +5475,7 @@ read_again:
if (priv->extend_desc)
stmmac_rx_extended_status(priv, &priv->xstats, rx_q->dma_erx + entry);
if (unlikely(status == discard_frame)) {
- page_pool_recycle_direct(rx_q->page_pool, buf->page);
+ page_pool_put_page(rx_q->page_pool, buf->page, 0, true);
buf->page = NULL;
error = 1;
if (!priv->hwts_rx_en)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
index 3ac32444e492..d0e61aa1a495 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
@@ -406,22 +406,6 @@ static int stmmac_of_get_mac_mode(struct device_node *np)
}
/**
- * stmmac_remove_config_dt - undo the effects of stmmac_probe_config_dt()
- * @pdev: platform_device structure
- * @plat: driver data platform structure
- *
- * Release resources claimed by stmmac_probe_config_dt().
- */
-static void stmmac_remove_config_dt(struct platform_device *pdev,
- struct plat_stmmacenet_data *plat)
-{
- clk_disable_unprepare(plat->stmmac_clk);
- clk_disable_unprepare(plat->pclk);
- of_node_put(plat->phy_node);
- of_node_put(plat->mdio_node);
-}
-
-/**
* stmmac_probe_config_dt - parse device-tree driver parameters
* @pdev: platform_device structure
* @mac: MAC address to use
@@ -490,8 +474,10 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n");
rc = stmmac_mdio_setup(plat, np, &pdev->dev);
- if (rc)
- return ERR_PTR(rc);
+ if (rc) {
+ ret = ERR_PTR(rc);
+ goto error_put_phy;
+ }
of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size);
@@ -581,8 +567,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
GFP_KERNEL);
if (!dma_cfg) {
- stmmac_remove_config_dt(pdev, plat);
- return ERR_PTR(-ENOMEM);
+ ret = ERR_PTR(-ENOMEM);
+ goto error_put_mdio;
}
plat->dma_cfg = dma_cfg;
@@ -610,8 +596,8 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
rc = stmmac_mtl_setup(pdev, plat);
if (rc) {
- stmmac_remove_config_dt(pdev, plat);
- return ERR_PTR(rc);
+ ret = ERR_PTR(rc);
+ goto error_put_mdio;
}
/* clock setup */
@@ -640,7 +626,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
dev_info(&pdev->dev, "PTP uses main clock\n");
} else {
plat->clk_ptp_rate = clk_get_rate(plat->clk_ptp_ref);
- dev_dbg(&pdev->dev, "PTP rate %d\n", plat->clk_ptp_rate);
+ dev_dbg(&pdev->dev, "PTP rate %lu\n", plat->clk_ptp_rate);
}
plat->stmmac_rst = devm_reset_control_get_optional(&pdev->dev,
@@ -663,6 +649,10 @@ error_hw_init:
clk_disable_unprepare(plat->pclk);
error_pclk_get:
clk_disable_unprepare(plat->stmmac_clk);
+error_put_mdio:
+ of_node_put(plat->mdio_node);
+error_put_phy:
+ of_node_put(plat->phy_node);
return ret;
}
@@ -671,16 +661,17 @@ static void devm_stmmac_remove_config_dt(void *data)
{
struct plat_stmmacenet_data *plat = data;
- /* Platform data argument is unused */
- stmmac_remove_config_dt(NULL, plat);
+ clk_disable_unprepare(plat->stmmac_clk);
+ clk_disable_unprepare(plat->pclk);
+ of_node_put(plat->mdio_node);
+ of_node_put(plat->phy_node);
}
/**
* devm_stmmac_probe_config_dt
* @pdev: platform_device structure
* @mac: MAC address to use
- * Description: Devres variant of stmmac_probe_config_dt(). Does not require
- * the user to call stmmac_remove_config_dt() at driver detach.
+ * Description: Devres variant of stmmac_probe_config_dt().
*/
struct plat_stmmacenet_data *
devm_stmmac_probe_config_dt(struct platform_device *pdev, u8 *mac)
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
index 4cc70480ce0f..3fe0e3a80e80 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.h
@@ -104,4 +104,7 @@ int dwmac1000_ptp_enable(struct ptp_clock_info *ptp,
void dwmac1000_get_ptptime(void __iomem *ptpaddr, u64 *ptp_time);
void dwmac1000_timestamp_interrupt(struct stmmac_priv *priv);
+extern const struct ptp_clock_info stmmac_ptp_clock_ops;
+extern const struct ptp_clock_info dwmac1000_ptp_clock_ops;
+
#endif /* __STMMAC_PTP_H__ */
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 6a79e6a111ed..694d6ee14381 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -1284,14 +1284,3 @@ const struct stmmac_tc_ops dwmac510_tc_ops = {
.query_caps = tc_query_caps,
.setup_mqprio = tc_setup_dwmac510_mqprio,
};
-
-const struct stmmac_tc_ops dwxgmac_tc_ops = {
- .init = tc_init,
- .setup_cls_u32 = tc_setup_cls_u32,
- .setup_cbs = tc_setup_cbs,
- .setup_cls = tc_setup_cls,
- .setup_taprio = tc_setup_taprio,
- .setup_etf = tc_setup_etf,
- .query_caps = tc_query_caps,
- .setup_mqprio = tc_setup_dwmac510_mqprio,
-};
diff --git a/drivers/net/ethernet/sun/niu.c b/drivers/net/ethernet/sun/niu.c
index df6d35d41b97..d7459866d24c 100644
--- a/drivers/net/ethernet/sun/niu.c
+++ b/drivers/net/ethernet/sun/niu.c
@@ -3303,7 +3303,7 @@ static struct page *niu_find_rxpage(struct rx_ring_info *rp, u64 addr,
addr &= PAGE_MASK;
pp = &rp->rxhash[h];
for (; (p = *pp) != NULL; pp = &niu_next_page(p)) {
- if (p->index == addr) {
+ if (p->private == addr) {
*link = pp;
goto found;
}
@@ -3318,7 +3318,7 @@ static void niu_hash_page(struct rx_ring_info *rp, struct page *page, u64 base)
{
unsigned int h = niu_hash_rxaddr(rp, base);
- page->index = base;
+ page->private = base;
niu_next_page(page) = rp->rxhash[h];
rp->rxhash[h] = page;
}
@@ -3400,11 +3400,11 @@ static int niu_rx_pkt_ignore(struct niu *np, struct rx_ring_info *rp)
rcr_size = rp->rbr_sizes[(val & RCR_ENTRY_PKTBUFSZ) >>
RCR_ENTRY_PKTBUFSZ_SHIFT];
- if ((page->index + PAGE_SIZE) - rcr_size == addr) {
+ if ((page->private + PAGE_SIZE) - rcr_size == addr) {
*link = niu_next_page(page);
- np->ops->unmap_page(np->device, page->index,
+ np->ops->unmap_page(np->device, page->private,
PAGE_SIZE, DMA_FROM_DEVICE);
- page->index = 0;
+ page->private = 0;
niu_next_page(page) = NULL;
__free_page(page);
rp->rbr_refill_pending++;
@@ -3469,11 +3469,11 @@ static int niu_process_rx_pkt(struct napi_struct *napi, struct niu *np,
append_size = append_size - skb->len;
niu_rx_skb_append(skb, page, off, append_size, rcr_size);
- if ((page->index + rp->rbr_block_size) - rcr_size == addr) {
+ if ((page->private + rp->rbr_block_size) - rcr_size == addr) {
*link = niu_next_page(page);
- np->ops->unmap_page(np->device, page->index,
+ np->ops->unmap_page(np->device, page->private,
PAGE_SIZE, DMA_FROM_DEVICE);
- page->index = 0;
+ page->private = 0;
niu_next_page(page) = NULL;
rp->rbr_refill_pending++;
} else
@@ -3538,11 +3538,11 @@ static void niu_rbr_free(struct niu *np, struct rx_ring_info *rp)
page = rp->rxhash[i];
while (page) {
struct page *next = niu_next_page(page);
- u64 base = page->index;
+ u64 base = page->private;
np->ops->unmap_page(np->device, base, PAGE_SIZE,
DMA_FROM_DEVICE);
- page->index = 0;
+ page->private = 0;
niu_next_page(page) = NULL;
__free_page(page);
@@ -6460,7 +6460,7 @@ static void niu_reset_buffers(struct niu *np)
page = rp->rxhash[j];
while (page) {
struct page *next = niu_next_page(page);
- u64 base = page->index;
+ u64 base = page->private;
base = base >> RBR_DESCR_ADDR_SHIFT;
rp->rbr[k++] = cpu_to_le32(base);
page = next;
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 14e1df721f2e..5465bf872734 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -3551,7 +3551,7 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
init_completion(&common->tdown_complete);
common->tx_ch_num = AM65_CPSW_DEFAULT_TX_CHNS;
common->rx_ch_num_flows = AM65_CPSW_DEFAULT_RX_CHN_FLOWS;
- common->pf_p0_rx_ptype_rrobin = false;
+ common->pf_p0_rx_ptype_rrobin = true;
common->default_vlan = 1;
common->ports = devm_kcalloc(dev, common->port_num,
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 4ef8cf6ea135..1e290ee8edfd 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -635,6 +635,8 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
slave->phy = phy;
+ phy_disable_eee(slave->phy);
+
phy_attached_info(slave->phy);
phy_start(slave->phy);
@@ -1225,7 +1227,6 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
.get_link_ksettings = cpsw_get_link_ksettings,
.set_link_ksettings = cpsw_set_link_ksettings,
.get_eee = cpsw_get_eee,
- .set_eee = cpsw_set_eee,
.nway_reset = cpsw_nway_reset,
.get_ringparam = cpsw_get_ringparam,
.set_ringparam = cpsw_set_ringparam,
diff --git a/drivers/net/ethernet/ti/cpsw_ethtool.c b/drivers/net/ethernet/ti/cpsw_ethtool.c
index 21d55a180ef6..bdc4db0d169c 100644
--- a/drivers/net/ethernet/ti/cpsw_ethtool.c
+++ b/drivers/net/ethernet/ti/cpsw_ethtool.c
@@ -434,18 +434,6 @@ int cpsw_get_eee(struct net_device *ndev, struct ethtool_keee *edata)
return -EOPNOTSUPP;
}
-int cpsw_set_eee(struct net_device *ndev, struct ethtool_keee *edata)
-{
- struct cpsw_priv *priv = netdev_priv(ndev);
- struct cpsw_common *cpsw = priv->cpsw;
- int slave_no = cpsw_slave_index(cpsw, priv);
-
- if (cpsw->slaves[slave_no].phy)
- return phy_ethtool_set_eee(cpsw->slaves[slave_no].phy, edata);
- else
- return -EOPNOTSUPP;
-}
-
int cpsw_nway_reset(struct net_device *ndev)
{
struct cpsw_priv *priv = netdev_priv(ndev);
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index a98bcc5eb566..be4d90c1cbe7 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -778,6 +778,8 @@ static void cpsw_slave_open(struct cpsw_slave *slave, struct cpsw_priv *priv)
slave->phy = phy;
+ phy_disable_eee(slave->phy);
+
phy_attached_info(slave->phy);
phy_start(slave->phy);
@@ -1209,7 +1211,6 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
.get_link_ksettings = cpsw_get_link_ksettings,
.set_link_ksettings = cpsw_set_link_ksettings,
.get_eee = cpsw_get_eee,
- .set_eee = cpsw_set_eee,
.nway_reset = cpsw_nway_reset,
.get_ringparam = cpsw_get_ringparam,
.set_ringparam = cpsw_set_ringparam,
diff --git a/drivers/net/ethernet/ti/cpsw_priv.h b/drivers/net/ethernet/ti/cpsw_priv.h
index 1f448290b9f4..f2fc55d9295d 100644
--- a/drivers/net/ethernet/ti/cpsw_priv.h
+++ b/drivers/net/ethernet/ti/cpsw_priv.h
@@ -497,7 +497,6 @@ int cpsw_get_link_ksettings(struct net_device *ndev,
int cpsw_set_link_ksettings(struct net_device *ndev,
const struct ethtool_link_ksettings *ecmd);
int cpsw_get_eee(struct net_device *ndev, struct ethtool_keee *edata);
-int cpsw_set_eee(struct net_device *ndev, struct ethtool_keee *edata);
int cpsw_nway_reset(struct net_device *ndev);
void cpsw_get_ringparam(struct net_device *ndev,
struct ethtool_ringparam *ering,
diff --git a/drivers/net/ethernet/ti/icssg/icss_iep.c b/drivers/net/ethernet/ti/icssg/icss_iep.c
index 5d6d1cf78e93..768578c0d958 100644
--- a/drivers/net/ethernet/ti/icssg/icss_iep.c
+++ b/drivers/net/ethernet/ti/icssg/icss_iep.c
@@ -215,6 +215,9 @@ static void icss_iep_enable_shadow_mode(struct icss_iep *iep)
for (cmp = IEP_MIN_CMP; cmp < IEP_MAX_CMP; cmp++) {
regmap_update_bits(iep->map, ICSS_IEP_CMP_STAT_REG,
IEP_CMP_STATUS(cmp), IEP_CMP_STATUS(cmp));
+
+ regmap_update_bits(iep->map, ICSS_IEP_CMP_CFG_REG,
+ IEP_CMP_CFG_CMP_EN(cmp), 0);
}
/* enable reset counter on CMP0 event */
@@ -780,6 +783,11 @@ int icss_iep_exit(struct icss_iep *iep)
}
icss_iep_disable(iep);
+ if (iep->pps_enabled)
+ icss_iep_pps_enable(iep, false);
+ else if (iep->perout_enabled)
+ icss_iep_perout_enable(iep, NULL, false);
+
return 0;
}
EXPORT_SYMBOL_GPL(icss_iep_exit);
diff --git a/drivers/net/ethernet/ti/icssg/icssg_common.c b/drivers/net/ethernet/ti/icssg/icssg_common.c
index fdebeb2f84e0..74f0f200a89d 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_common.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_common.c
@@ -855,31 +855,6 @@ irqreturn_t prueth_rx_irq(int irq, void *dev_id)
}
EXPORT_SYMBOL_GPL(prueth_rx_irq);
-void prueth_emac_stop(struct prueth_emac *emac)
-{
- struct prueth *prueth = emac->prueth;
- int slice;
-
- switch (emac->port_id) {
- case PRUETH_PORT_MII0:
- slice = ICSS_SLICE0;
- break;
- case PRUETH_PORT_MII1:
- slice = ICSS_SLICE1;
- break;
- default:
- netdev_err(emac->ndev, "invalid port\n");
- return;
- }
-
- emac->fw_running = 0;
- if (!emac->is_sr1)
- rproc_shutdown(prueth->txpru[slice]);
- rproc_shutdown(prueth->rtu[slice]);
- rproc_shutdown(prueth->pru[slice]);
-}
-EXPORT_SYMBOL_GPL(prueth_emac_stop);
-
void prueth_cleanup_tx_ts(struct prueth_emac *emac)
{
int i;
diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.c b/drivers/net/ethernet/ti/icssg/icssg_config.c
index 5d2491c2943a..ddfd1c02a885 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_config.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_config.c
@@ -397,7 +397,7 @@ static int prueth_emac_buffer_setup(struct prueth_emac *emac)
return 0;
}
-static void icssg_init_emac_mode(struct prueth *prueth)
+void icssg_init_emac_mode(struct prueth *prueth)
{
/* When the device is configured as a bridge and it is being brought
* back to the emac mode, the host mac address has to be set as 0.
@@ -406,9 +406,6 @@ static void icssg_init_emac_mode(struct prueth *prueth)
int i;
u8 mac[ETH_ALEN] = { 0 };
- if (prueth->emacs_initialized)
- return;
-
/* Set VLAN TABLE address base */
regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, SMEM_VLAN_OFFSET_MASK,
addr << SMEM_VLAN_OFFSET);
@@ -423,15 +420,13 @@ static void icssg_init_emac_mode(struct prueth *prueth)
/* Clear host MAC address */
icssg_class_set_host_mac_addr(prueth->miig_rt, mac);
}
+EXPORT_SYMBOL_GPL(icssg_init_emac_mode);
-static void icssg_init_fw_offload_mode(struct prueth *prueth)
+void icssg_init_fw_offload_mode(struct prueth *prueth)
{
u32 addr = prueth->shram.pa + EMAC_ICSSG_SWITCH_DEFAULT_VLAN_TABLE_OFFSET;
int i;
- if (prueth->emacs_initialized)
- return;
-
/* Set VLAN TABLE address base */
regmap_update_bits(prueth->miig_rt, FDB_GEN_CFG1, SMEM_VLAN_OFFSET_MASK,
addr << SMEM_VLAN_OFFSET);
@@ -448,6 +443,7 @@ static void icssg_init_fw_offload_mode(struct prueth *prueth)
icssg_class_set_host_mac_addr(prueth->miig_rt, prueth->hw_bridge_dev->dev_addr);
icssg_set_pvid(prueth, prueth->default_vlan, PRUETH_PORT_HOST);
}
+EXPORT_SYMBOL_GPL(icssg_init_fw_offload_mode);
int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
{
@@ -455,11 +451,6 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac, int slice)
struct icssg_flow_cfg __iomem *flow_cfg;
int ret;
- if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
- icssg_init_fw_offload_mode(prueth);
- else
- icssg_init_emac_mode(prueth);
-
memset_io(config, 0, TAS_GATE_MASK_LIST0);
icssg_miig_queues_init(prueth, slice);
@@ -786,3 +777,27 @@ void icssg_set_pvid(struct prueth *prueth, u8 vid, u8 port)
writel(pvid, prueth->shram.va + EMAC_ICSSG_SWITCH_PORT0_DEFAULT_VLAN_OFFSET);
}
EXPORT_SYMBOL_GPL(icssg_set_pvid);
+
+int emac_fdb_flow_id_updated(struct prueth_emac *emac)
+{
+ struct mgmt_cmd_rsp fdb_cmd_rsp = { 0 };
+ int slice = prueth_emac_slice(emac);
+ struct mgmt_cmd fdb_cmd = { 0 };
+ int ret;
+
+ fdb_cmd.header = ICSSG_FW_MGMT_CMD_HEADER;
+ fdb_cmd.type = ICSSG_FW_MGMT_FDB_CMD_TYPE_RX_FLOW;
+ fdb_cmd.seqnum = ++(emac->prueth->icssg_hwcmdseq);
+ fdb_cmd.param = 0;
+
+ fdb_cmd.param |= (slice << 4);
+ fdb_cmd.cmd_args[0] = 0;
+
+ ret = icssg_send_fdb_msg(emac, &fdb_cmd, &fdb_cmd_rsp);
+ if (ret)
+ return ret;
+
+ WARN_ON(fdb_cmd.seqnum != fdb_cmd_rsp.seqnum);
+ return fdb_cmd_rsp.status == 1 ? 0 : -EINVAL;
+}
+EXPORT_SYMBOL_GPL(emac_fdb_flow_id_updated);
diff --git a/drivers/net/ethernet/ti/icssg/icssg_config.h b/drivers/net/ethernet/ti/icssg/icssg_config.h
index 92c2deaa3068..c884e9fa099e 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_config.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_config.h
@@ -55,6 +55,7 @@ struct icssg_rxq_ctx {
#define ICSSG_FW_MGMT_FDB_CMD_TYPE 0x03
#define ICSSG_FW_MGMT_CMD_TYPE 0x04
#define ICSSG_FW_MGMT_PKT 0x80000000
+#define ICSSG_FW_MGMT_FDB_CMD_TYPE_RX_FLOW 0x05
struct icssg_r30_cmd {
u32 cmd[4];
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.c b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
index c568c84a032b..d76fe6d05e10 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.c
@@ -164,11 +164,26 @@ static struct icssg_firmwares icssg_emac_firmwares[] = {
}
};
-static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
+static int prueth_start(struct rproc *rproc, const char *fw_name)
+{
+ int ret;
+
+ ret = rproc_set_firmware(rproc, fw_name);
+ if (ret)
+ return ret;
+ return rproc_boot(rproc);
+}
+
+static void prueth_shutdown(struct rproc *rproc)
+{
+ rproc_shutdown(rproc);
+}
+
+static int prueth_emac_start(struct prueth *prueth)
{
struct icssg_firmwares *firmwares;
struct device *dev = prueth->dev;
- int slice, ret;
+ int ret, slice;
if (prueth->is_switch_mode)
firmwares = icssg_switch_firmwares;
@@ -177,49 +192,126 @@ static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
else
firmwares = icssg_emac_firmwares;
- slice = prueth_emac_slice(emac);
- if (slice < 0) {
- netdev_err(emac->ndev, "invalid port\n");
- return -EINVAL;
+ for (slice = 0; slice < PRUETH_NUM_MACS; slice++) {
+ ret = prueth_start(prueth->pru[slice], firmwares[slice].pru);
+ if (ret) {
+ dev_err(dev, "failed to boot PRU%d: %d\n", slice, ret);
+ goto unwind_slices;
+ }
+
+ ret = prueth_start(prueth->rtu[slice], firmwares[slice].rtu);
+ if (ret) {
+ dev_err(dev, "failed to boot RTU%d: %d\n", slice, ret);
+ rproc_shutdown(prueth->pru[slice]);
+ goto unwind_slices;
+ }
+
+ ret = prueth_start(prueth->txpru[slice], firmwares[slice].txpru);
+ if (ret) {
+ dev_err(dev, "failed to boot TX_PRU%d: %d\n", slice, ret);
+ rproc_shutdown(prueth->rtu[slice]);
+ rproc_shutdown(prueth->pru[slice]);
+ goto unwind_slices;
+ }
}
- ret = icssg_config(prueth, emac, slice);
- if (ret)
- return ret;
+ return 0;
- ret = rproc_set_firmware(prueth->pru[slice], firmwares[slice].pru);
- ret = rproc_boot(prueth->pru[slice]);
- if (ret) {
- dev_err(dev, "failed to boot PRU%d: %d\n", slice, ret);
- return -EINVAL;
+unwind_slices:
+ while (--slice >= 0) {
+ prueth_shutdown(prueth->txpru[slice]);
+ prueth_shutdown(prueth->rtu[slice]);
+ prueth_shutdown(prueth->pru[slice]);
}
- ret = rproc_set_firmware(prueth->rtu[slice], firmwares[slice].rtu);
- ret = rproc_boot(prueth->rtu[slice]);
- if (ret) {
- dev_err(dev, "failed to boot RTU%d: %d\n", slice, ret);
- goto halt_pru;
+ return ret;
+}
+
+static void prueth_emac_stop(struct prueth *prueth)
+{
+ int slice;
+
+ for (slice = 0; slice < PRUETH_NUM_MACS; slice++) {
+ prueth_shutdown(prueth->txpru[slice]);
+ prueth_shutdown(prueth->rtu[slice]);
+ prueth_shutdown(prueth->pru[slice]);
}
+}
+
+static int prueth_emac_common_start(struct prueth *prueth)
+{
+ struct prueth_emac *emac;
+ int ret = 0;
+ int slice;
+
+ if (!prueth->emac[ICSS_SLICE0] && !prueth->emac[ICSS_SLICE1])
+ return -EINVAL;
+
+ /* clear SMEM and MSMC settings for all slices */
+ memset_io(prueth->msmcram.va, 0, prueth->msmcram.size);
+ memset_io(prueth->shram.va, 0, ICSSG_CONFIG_OFFSET_SLICE1 * PRUETH_NUM_MACS);
+
+ icssg_class_default(prueth->miig_rt, ICSS_SLICE0, 0, false);
+ icssg_class_default(prueth->miig_rt, ICSS_SLICE1, 0, false);
+
+ if (prueth->is_switch_mode || prueth->is_hsr_offload_mode)
+ icssg_init_fw_offload_mode(prueth);
+ else
+ icssg_init_emac_mode(prueth);
+
+ for (slice = 0; slice < PRUETH_NUM_MACS; slice++) {
+ emac = prueth->emac[slice];
+ if (!emac)
+ continue;
+ ret = icssg_config(prueth, emac, slice);
+ if (ret)
+ goto disable_class;
+ }
+
+ ret = prueth_emac_start(prueth);
+ if (ret)
+ goto disable_class;
- ret = rproc_set_firmware(prueth->txpru[slice], firmwares[slice].txpru);
- ret = rproc_boot(prueth->txpru[slice]);
+ emac = prueth->emac[ICSS_SLICE0] ? prueth->emac[ICSS_SLICE0] :
+ prueth->emac[ICSS_SLICE1];
+ ret = icss_iep_init(emac->iep, &prueth_iep_clockops,
+ emac, IEP_DEFAULT_CYCLE_TIME_NS);
if (ret) {
- dev_err(dev, "failed to boot TX_PRU%d: %d\n", slice, ret);
- goto halt_rtu;
+ dev_err(prueth->dev, "Failed to initialize IEP module\n");
+ goto stop_pruss;
}
- emac->fw_running = 1;
return 0;
-halt_rtu:
- rproc_shutdown(prueth->rtu[slice]);
+stop_pruss:
+ prueth_emac_stop(prueth);
-halt_pru:
- rproc_shutdown(prueth->pru[slice]);
+disable_class:
+ icssg_class_disable(prueth->miig_rt, ICSS_SLICE0);
+ icssg_class_disable(prueth->miig_rt, ICSS_SLICE1);
return ret;
}
+static int prueth_emac_common_stop(struct prueth *prueth)
+{
+ struct prueth_emac *emac;
+
+ if (!prueth->emac[ICSS_SLICE0] && !prueth->emac[ICSS_SLICE1])
+ return -EINVAL;
+
+ icssg_class_disable(prueth->miig_rt, ICSS_SLICE0);
+ icssg_class_disable(prueth->miig_rt, ICSS_SLICE1);
+
+ prueth_emac_stop(prueth);
+
+ emac = prueth->emac[ICSS_SLICE0] ? prueth->emac[ICSS_SLICE0] :
+ prueth->emac[ICSS_SLICE1];
+ icss_iep_exit(emac->iep);
+
+ return 0;
+}
+
/* called back by PHY layer if there is change in link state of hw port*/
static void emac_adjust_link(struct net_device *ndev)
{
@@ -374,9 +466,6 @@ static void prueth_iep_settime(void *clockops_data, u64 ns)
u32 cycletime;
int timeout;
- if (!emac->fw_running)
- return;
-
sc_descp = emac->prueth->shram.va + TIMESYNC_FW_WC_SETCLOCK_DESC_OFFSET;
cycletime = IEP_DEFAULT_CYCLE_TIME_NS;
@@ -543,23 +632,17 @@ static int emac_ndo_open(struct net_device *ndev)
{
struct prueth_emac *emac = netdev_priv(ndev);
int ret, i, num_data_chn = emac->tx_ch_num;
+ struct icssg_flow_cfg __iomem *flow_cfg;
struct prueth *prueth = emac->prueth;
int slice = prueth_emac_slice(emac);
struct device *dev = prueth->dev;
int max_rx_flows;
int rx_flow;
- /* clear SMEM and MSMC settings for all slices */
- if (!prueth->emacs_initialized) {
- memset_io(prueth->msmcram.va, 0, prueth->msmcram.size);
- memset_io(prueth->shram.va, 0, ICSSG_CONFIG_OFFSET_SLICE1 * PRUETH_NUM_MACS);
- }
-
/* set h/w MAC as user might have re-configured */
ether_addr_copy(emac->mac_addr, ndev->dev_addr);
icssg_class_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
- icssg_class_default(prueth->miig_rt, slice, 0, false);
icssg_ft1_set_mac_addr(prueth->miig_rt, slice, emac->mac_addr);
/* Notify the stack of the actual queue counts. */
@@ -597,18 +680,23 @@ static int emac_ndo_open(struct net_device *ndev)
goto cleanup_napi;
}
- /* reset and start PRU firmware */
- ret = prueth_emac_start(prueth, emac);
- if (ret)
- goto free_rx_irq;
+ if (!prueth->emacs_initialized) {
+ ret = prueth_emac_common_start(prueth);
+ if (ret)
+ goto free_rx_irq;
+ }
- icssg_mii_update_mtu(prueth->mii_rt, slice, ndev->max_mtu);
+ flow_cfg = emac->dram.va + ICSSG_CONFIG_OFFSET + PSI_L_REGULAR_FLOW_ID_BASE_OFFSET;
+ writew(emac->rx_flow_id_base, &flow_cfg->rx_base_flow);
+ ret = emac_fdb_flow_id_updated(emac);
- if (!prueth->emacs_initialized) {
- ret = icss_iep_init(emac->iep, &prueth_iep_clockops,
- emac, IEP_DEFAULT_CYCLE_TIME_NS);
+ if (ret) {
+ netdev_err(ndev, "Failed to update Rx Flow ID %d", ret);
+ goto stop;
}
+ icssg_mii_update_mtu(prueth->mii_rt, slice, ndev->max_mtu);
+
ret = request_threaded_irq(emac->tx_ts_irq, NULL, prueth_tx_ts_irq,
IRQF_ONESHOT, dev_name(dev), emac);
if (ret)
@@ -653,7 +741,8 @@ reset_rx_chn:
free_tx_ts_irq:
free_irq(emac->tx_ts_irq, emac);
stop:
- prueth_emac_stop(emac);
+ if (!prueth->emacs_initialized)
+ prueth_emac_common_stop(prueth);
free_rx_irq:
free_irq(emac->rx_chns.irq[rx_flow], emac);
cleanup_napi:
@@ -689,8 +778,6 @@ static int emac_ndo_stop(struct net_device *ndev)
if (ndev->phydev)
phy_stop(ndev->phydev);
- icssg_class_disable(prueth->miig_rt, prueth_emac_slice(emac));
-
if (emac->prueth->is_hsr_offload_mode)
__dev_mc_unsync(ndev, icssg_prueth_hsr_del_mcast);
else
@@ -728,11 +815,9 @@ static int emac_ndo_stop(struct net_device *ndev)
/* Destroying the queued work in ndo_stop() */
cancel_delayed_work_sync(&emac->stats_work);
- if (prueth->emacs_initialized == 1)
- icss_iep_exit(emac->iep);
-
/* stop PRUs */
- prueth_emac_stop(emac);
+ if (prueth->emacs_initialized == 1)
+ prueth_emac_common_stop(prueth);
free_irq(emac->tx_ts_irq, emac);
@@ -1053,10 +1138,11 @@ static void prueth_offload_fwd_mark_update(struct prueth *prueth)
}
}
-static void prueth_emac_restart(struct prueth *prueth)
+static int prueth_emac_restart(struct prueth *prueth)
{
struct prueth_emac *emac0 = prueth->emac[PRUETH_MAC0];
struct prueth_emac *emac1 = prueth->emac[PRUETH_MAC1];
+ int ret;
/* Detach the net_device for both PRUeth ports*/
if (netif_running(emac0->ndev))
@@ -1065,36 +1151,46 @@ static void prueth_emac_restart(struct prueth *prueth)
netif_device_detach(emac1->ndev);
/* Disable both PRUeth ports */
- icssg_set_port_state(emac0, ICSSG_EMAC_PORT_DISABLE);
- icssg_set_port_state(emac1, ICSSG_EMAC_PORT_DISABLE);
+ ret = icssg_set_port_state(emac0, ICSSG_EMAC_PORT_DISABLE);
+ ret |= icssg_set_port_state(emac1, ICSSG_EMAC_PORT_DISABLE);
+ if (ret)
+ return ret;
/* Stop both pru cores for both PRUeth ports*/
- prueth_emac_stop(emac0);
- prueth->emacs_initialized--;
- prueth_emac_stop(emac1);
- prueth->emacs_initialized--;
+ ret = prueth_emac_common_stop(prueth);
+ if (ret) {
+ dev_err(prueth->dev, "Failed to stop the firmwares");
+ return ret;
+ }
/* Start both pru cores for both PRUeth ports */
- prueth_emac_start(prueth, emac0);
- prueth->emacs_initialized++;
- prueth_emac_start(prueth, emac1);
- prueth->emacs_initialized++;
+ ret = prueth_emac_common_start(prueth);
+ if (ret) {
+ dev_err(prueth->dev, "Failed to start the firmwares");
+ return ret;
+ }
/* Enable forwarding for both PRUeth ports */
- icssg_set_port_state(emac0, ICSSG_EMAC_PORT_FORWARD);
- icssg_set_port_state(emac1, ICSSG_EMAC_PORT_FORWARD);
+ ret = icssg_set_port_state(emac0, ICSSG_EMAC_PORT_FORWARD);
+ ret |= icssg_set_port_state(emac1, ICSSG_EMAC_PORT_FORWARD);
/* Attache net_device for both PRUeth ports */
netif_device_attach(emac0->ndev);
netif_device_attach(emac1->ndev);
+
+ return ret;
}
static void icssg_change_mode(struct prueth *prueth)
{
struct prueth_emac *emac;
- int mac;
+ int mac, ret;
- prueth_emac_restart(prueth);
+ ret = prueth_emac_restart(prueth);
+ if (ret) {
+ dev_err(prueth->dev, "Failed to restart the firmwares, aborting the process");
+ return;
+ }
for (mac = PRUETH_MAC0; mac < PRUETH_NUM_MACS; mac++) {
emac = prueth->emac[mac];
@@ -1173,13 +1269,18 @@ static void prueth_netdevice_port_unlink(struct net_device *ndev)
{
struct prueth_emac *emac = netdev_priv(ndev);
struct prueth *prueth = emac->prueth;
+ int ret;
prueth->br_members &= ~BIT(emac->port_id);
if (prueth->is_switch_mode) {
prueth->is_switch_mode = false;
emac->port_vlan = 0;
- prueth_emac_restart(prueth);
+ ret = prueth_emac_restart(prueth);
+ if (ret) {
+ dev_err(prueth->dev, "Failed to restart the firmwares, aborting the process");
+ return;
+ }
}
prueth_offload_fwd_mark_update(prueth);
@@ -1228,6 +1329,7 @@ static void prueth_hsr_port_unlink(struct net_device *ndev)
struct prueth *prueth = emac->prueth;
struct prueth_emac *emac0;
struct prueth_emac *emac1;
+ int ret;
emac0 = prueth->emac[PRUETH_MAC0];
emac1 = prueth->emac[PRUETH_MAC1];
@@ -1238,7 +1340,11 @@ static void prueth_hsr_port_unlink(struct net_device *ndev)
emac0->port_vlan = 0;
emac1->port_vlan = 0;
prueth->hsr_dev = NULL;
- prueth_emac_restart(prueth);
+ ret = prueth_emac_restart(prueth);
+ if (ret) {
+ dev_err(prueth->dev, "Failed to restart the firmwares, aborting the process");
+ return;
+ }
netdev_dbg(ndev, "Disabling HSR Offload mode\n");
}
}
@@ -1413,13 +1519,10 @@ static int prueth_probe(struct platform_device *pdev)
prueth->pa_stats = NULL;
}
- if (eth0_node) {
+ if (eth0_node || eth1_node) {
ret = prueth_get_cores(prueth, ICSS_SLICE0, false);
if (ret)
goto put_cores;
- }
-
- if (eth1_node) {
ret = prueth_get_cores(prueth, ICSS_SLICE1, false);
if (ret)
goto put_cores;
@@ -1618,14 +1721,12 @@ put_pruss:
pruss_put(prueth->pruss);
put_cores:
- if (eth1_node) {
- prueth_put_cores(prueth, ICSS_SLICE1);
- of_node_put(eth1_node);
- }
-
- if (eth0_node) {
+ if (eth0_node || eth1_node) {
prueth_put_cores(prueth, ICSS_SLICE0);
of_node_put(eth0_node);
+
+ prueth_put_cores(prueth, ICSS_SLICE1);
+ of_node_put(eth1_node);
}
return ret;
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth.h b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
index f5c1d473e9f9..5473315ea204 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth.h
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth.h
@@ -140,7 +140,6 @@ struct prueth_rx_chn {
/* data for each emac port */
struct prueth_emac {
bool is_sr1;
- bool fw_running;
struct prueth *prueth;
struct net_device *ndev;
u8 mac_addr[6];
@@ -361,6 +360,8 @@ int icssg_set_port_state(struct prueth_emac *emac,
enum icssg_port_state_cmd state);
void icssg_config_set_speed(struct prueth_emac *emac);
void icssg_config_half_duplex(struct prueth_emac *emac);
+void icssg_init_emac_mode(struct prueth *prueth);
+void icssg_init_fw_offload_mode(struct prueth *prueth);
/* Buffer queue helpers */
int icssg_queue_pop(struct prueth *prueth, u8 queue);
@@ -377,6 +378,7 @@ void icssg_vtbl_modify(struct prueth_emac *emac, u8 vid, u8 port_mask,
u8 untag_mask, bool add);
u16 icssg_get_pvid(struct prueth_emac *emac);
void icssg_set_pvid(struct prueth *prueth, u8 vid, u8 port);
+int emac_fdb_flow_id_updated(struct prueth_emac *emac);
#define prueth_napi_to_tx_chn(pnapi) \
container_of(pnapi, struct prueth_tx_chn, napi_tx)
@@ -407,7 +409,6 @@ void emac_rx_timestamp(struct prueth_emac *emac,
struct sk_buff *skb, u32 *psdata);
enum netdev_tx icssg_ndo_start_xmit(struct sk_buff *skb, struct net_device *ndev);
irqreturn_t prueth_rx_irq(int irq, void *dev_id);
-void prueth_emac_stop(struct prueth_emac *emac);
void prueth_cleanup_tx_ts(struct prueth_emac *emac);
int icssg_napi_rx_poll(struct napi_struct *napi_rx, int budget);
int prueth_prepare_rx_chan(struct prueth_emac *emac,
diff --git a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
index 5024f0647a0d..3dc86397c367 100644
--- a/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
+++ b/drivers/net/ethernet/ti/icssg/icssg_prueth_sr1.c
@@ -440,7 +440,6 @@ static int prueth_emac_start(struct prueth *prueth, struct prueth_emac *emac)
goto halt_pru;
}
- emac->fw_running = 1;
return 0;
halt_pru:
@@ -449,6 +448,29 @@ halt_pru:
return ret;
}
+static void prueth_emac_stop(struct prueth_emac *emac)
+{
+ struct prueth *prueth = emac->prueth;
+ int slice;
+
+ switch (emac->port_id) {
+ case PRUETH_PORT_MII0:
+ slice = ICSS_SLICE0;
+ break;
+ case PRUETH_PORT_MII1:
+ slice = ICSS_SLICE1;
+ break;
+ default:
+ netdev_err(emac->ndev, "invalid port\n");
+ return;
+ }
+
+ if (!emac->is_sr1)
+ rproc_shutdown(prueth->txpru[slice]);
+ rproc_shutdown(prueth->rtu[slice]);
+ rproc_shutdown(prueth->pru[slice]);
+}
+
/**
* emac_ndo_open - EMAC device open
* @ndev: network adapter device
diff --git a/drivers/net/ethernet/wangxun/libwx/wx_hw.c b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
index 1bf9c38e4125..deaf670c160e 100644
--- a/drivers/net/ethernet/wangxun/libwx/wx_hw.c
+++ b/drivers/net/ethernet/wangxun/libwx/wx_hw.c
@@ -334,27 +334,25 @@ int wx_host_interface_command(struct wx *wx, u32 *buffer,
status = read_poll_timeout(rd32, hicr, hicr & WX_MNG_MBOX_CTL_FWRDY, 1000,
timeout * 1000, false, wx, WX_MNG_MBOX_CTL);
+ buf[0] = rd32(wx, WX_MNG_MBOX);
+ if ((buf[0] & 0xff0000) >> 16 == 0x80) {
+ wx_err(wx, "Unknown FW command: 0x%x\n", buffer[0] & 0xff);
+ status = -EINVAL;
+ goto rel_out;
+ }
+
/* Check command completion */
if (status) {
- wx_dbg(wx, "Command has failed with no status valid.\n");
-
- buf[0] = rd32(wx, WX_MNG_MBOX);
- if ((buffer[0] & 0xff) != (~buf[0] >> 24)) {
- status = -EINVAL;
- goto rel_out;
- }
- if ((buf[0] & 0xff0000) >> 16 == 0x80) {
- wx_dbg(wx, "It's unknown cmd.\n");
- status = -EINVAL;
- goto rel_out;
- }
-
+ wx_err(wx, "Command has failed with no status valid.\n");
wx_dbg(wx, "write value:\n");
for (i = 0; i < dword_len; i++)
wx_dbg(wx, "%x ", buffer[i]);
wx_dbg(wx, "read value:\n");
for (i = 0; i < dword_len; i++)
wx_dbg(wx, "%x ", buf[i]);
+ wx_dbg(wx, "\ncheck: %x %x\n", buffer[0] & 0xff, ~buf[0] >> 24);
+
+ goto rel_out;
}
if (!return_data)
diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c
index 2f29b1386b1c..642155cb8315 100644
--- a/drivers/net/geneve.c
+++ b/drivers/net/geneve.c
@@ -235,7 +235,7 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
vni_to_tunnel_id(gnvh->vni),
gnvh->opt_len * 4);
if (!tun_dst) {
- DEV_STATS_INC(geneve->dev, rx_dropped);
+ dev_dstats_rx_dropped(geneve->dev);
goto drop;
}
/* Update tunnel dst according to Geneve options. */
@@ -322,7 +322,7 @@ static void geneve_rx(struct geneve_dev *geneve, struct geneve_sock *gs,
len = skb->len;
err = gro_cells_receive(&geneve->gro_cells, skb);
if (likely(err == NET_RX_SUCCESS))
- dev_sw_netstats_rx_add(geneve->dev, len);
+ dev_dstats_rx_add(geneve->dev, len);
return;
drop:
@@ -387,14 +387,14 @@ static int geneve_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
if (unlikely((!geneve->cfg.inner_proto_inherit &&
inner_proto != htons(ETH_P_TEB)))) {
- DEV_STATS_INC(geneve->dev, rx_dropped);
+ dev_dstats_rx_dropped(geneve->dev);
goto drop;
}
opts_len = geneveh->opt_len * 4;
if (iptunnel_pull_header(skb, GENEVE_BASE_HLEN + opts_len, inner_proto,
!net_eq(geneve->net, dev_net(geneve->dev)))) {
- DEV_STATS_INC(geneve->dev, rx_dropped);
+ dev_dstats_rx_dropped(geneve->dev);
goto drop;
}
@@ -895,7 +895,7 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
if (geneve->cfg.df == GENEVE_DF_SET) {
df = htons(IP_DF);
} else if (geneve->cfg.df == GENEVE_DF_INHERIT) {
- struct ethhdr *eth = eth_hdr(skb);
+ struct ethhdr *eth = skb_eth_hdr(skb);
if (ntohs(eth->h_proto) == ETH_P_IPV6) {
df = htons(IP_DF);
@@ -1023,7 +1023,7 @@ static netdev_tx_t geneve_xmit(struct sk_buff *skb, struct net_device *dev)
if (unlikely(!info || !(info->mode & IP_TUNNEL_INFO_TX))) {
netdev_dbg(dev, "no tunnel metadata\n");
dev_kfree_skb(skb);
- DEV_STATS_INC(dev, tx_dropped);
+ dev_dstats_tx_dropped(dev);
return NETDEV_TX_OK;
}
} else {
@@ -1202,7 +1202,7 @@ static void geneve_setup(struct net_device *dev)
dev->hw_features |= NETIF_F_RXCSUM;
dev->hw_features |= NETIF_F_GSO_SOFTWARE;
- dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
/* MTU range: 68 - (something less than 65535) */
dev->min_mtu = ETH_MIN_MTU;
/* The max_mtu calculation does not take account of GENEVE
diff --git a/drivers/net/ieee802154/ca8210.c b/drivers/net/ieee802154/ca8210.c
index e685a7f946f0..753215ebc67c 100644
--- a/drivers/net/ieee802154/ca8210.c
+++ b/drivers/net/ieee802154/ca8210.c
@@ -3072,7 +3072,11 @@ static int ca8210_probe(struct spi_device *spi_device)
spi_set_drvdata(priv->spi, priv);
if (IS_ENABLED(CONFIG_IEEE802154_CA8210_DEBUGFS)) {
cascoda_api_upstream = ca8210_test_int_driver_write;
- ca8210_test_interface_init(priv);
+ ret = ca8210_test_interface_init(priv);
+ if (ret) {
+ dev_crit(&spi_device->dev, "ca8210_test_interface_init failed\n");
+ goto error;
+ }
} else {
cascoda_api_upstream = NULL;
}
diff --git a/drivers/net/mctp/mctp-i3c.c b/drivers/net/mctp/mctp-i3c.c
index 9adad59b8676..d247fe483c58 100644
--- a/drivers/net/mctp/mctp-i3c.c
+++ b/drivers/net/mctp/mctp-i3c.c
@@ -125,6 +125,8 @@ static int mctp_i3c_read(struct mctp_i3c_device *mi)
xfer.data.in = skb_put(skb, mi->mrl);
+ /* Make sure netif_rx() is read in the same order as i3c. */
+ mutex_lock(&mi->lock);
rc = i3c_device_do_priv_xfers(mi->i3c, &xfer, 1);
if (rc < 0)
goto err;
@@ -166,8 +168,10 @@ static int mctp_i3c_read(struct mctp_i3c_device *mi)
stats->rx_dropped++;
}
+ mutex_unlock(&mi->lock);
return 0;
err:
+ mutex_unlock(&mi->lock);
kfree_skb(skb);
return rc;
}
diff --git a/drivers/net/mdio/fwnode_mdio.c b/drivers/net/mdio/fwnode_mdio.c
index b156493d7084..aea0f0357568 100644
--- a/drivers/net/mdio/fwnode_mdio.c
+++ b/drivers/net/mdio/fwnode_mdio.c
@@ -40,6 +40,7 @@ fwnode_find_pse_control(struct fwnode_handle *fwnode)
static struct mii_timestamper *
fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
{
+ struct mii_timestamper *mii_ts;
struct of_phandle_args arg;
int err;
@@ -53,10 +54,16 @@ fwnode_find_mii_timestamper(struct fwnode_handle *fwnode)
else if (err)
return ERR_PTR(err);
- if (arg.args_count != 1)
- return ERR_PTR(-EINVAL);
+ if (arg.args_count != 1) {
+ mii_ts = ERR_PTR(-EINVAL);
+ goto put_node;
+ }
+
+ mii_ts = register_mii_timestamper(arg.np, arg.args[0]);
- return register_mii_timestamper(arg.np, arg.args[0]);
+put_node:
+ of_node_put(arg.np);
+ return mii_ts;
}
int fwnode_mdiobus_phy_device_register(struct mii_bus *mdio,
diff --git a/drivers/net/mdio/mdio-octeon.c b/drivers/net/mdio/mdio-octeon.c
index 2beb83154d39..cb53dccbde1a 100644
--- a/drivers/net/mdio/mdio-octeon.c
+++ b/drivers/net/mdio/mdio-octeon.c
@@ -17,37 +17,20 @@ static int octeon_mdiobus_probe(struct platform_device *pdev)
{
struct cavium_mdiobus *bus;
struct mii_bus *mii_bus;
- struct resource *res_mem;
- resource_size_t mdio_phys;
- resource_size_t regsize;
union cvmx_smix_en smi_en;
- int err = -ENOENT;
+ int err;
mii_bus = devm_mdiobus_alloc_size(&pdev->dev, sizeof(*bus));
if (!mii_bus)
return -ENOMEM;
- res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res_mem == NULL) {
- dev_err(&pdev->dev, "found no memory resource\n");
- return -ENXIO;
- }
-
bus = mii_bus->priv;
bus->mii_bus = mii_bus;
- mdio_phys = res_mem->start;
- regsize = resource_size(res_mem);
- if (!devm_request_mem_region(&pdev->dev, mdio_phys, regsize,
- res_mem->name)) {
- dev_err(&pdev->dev, "request_mem_region failed\n");
- return -ENXIO;
- }
-
- bus->register_base = devm_ioremap(&pdev->dev, mdio_phys, regsize);
- if (!bus->register_base) {
+ bus->register_base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(bus->register_base)) {
dev_err(&pdev->dev, "dev_ioremap failed\n");
- return -ENOMEM;
+ return PTR_ERR(bus->register_base);
}
smi_en.u64 = 0;
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index f422a2f666ef..86ab4a42769a 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -730,7 +730,7 @@ static void update_userdata(struct netconsole_target *nt)
struct userdatum *udm_item;
struct config_item *item;
- if (child_count >= MAX_USERDATA_ITEMS)
+ if (WARN_ON_ONCE(child_count >= MAX_USERDATA_ITEMS))
break;
child_count++;
diff --git a/drivers/net/netdevsim/health.c b/drivers/net/netdevsim/health.c
index 70e8bdf34be9..688f05316b5e 100644
--- a/drivers/net/netdevsim/health.c
+++ b/drivers/net/netdevsim/health.c
@@ -149,6 +149,8 @@ static ssize_t nsim_dev_health_break_write(struct file *file,
char *break_msg;
int err;
+ if (count == 0 || count > PAGE_SIZE)
+ return -EINVAL;
break_msg = memdup_user_nul(data, count);
if (IS_ERR(break_msg))
return PTR_ERR(break_msg);
diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c
index 0be47fed4efc..d013b6498539 100644
--- a/drivers/net/netdevsim/netdev.c
+++ b/drivers/net/netdevsim/netdev.c
@@ -20,6 +20,7 @@
#include <linux/netdevice.h>
#include <linux/slab.h>
#include <net/netdev_queues.h>
+#include <net/netdev_rx_queue.h>
#include <net/page_pool/helpers.h>
#include <net/netlink.h>
#include <net/net_shaper.h>
@@ -29,6 +30,8 @@
#include "netdevsim.h"
+MODULE_IMPORT_NS("NETDEV_INTERNAL");
+
#define NSIM_RING_SIZE 256
static int nsim_napi_rx(struct nsim_rq *rq, struct sk_buff *skb)
@@ -69,7 +72,7 @@ static netdev_tx_t nsim_start_xmit(struct sk_buff *skb, struct net_device *dev)
rxq = skb_get_queue_mapping(skb);
if (rxq >= peer_dev->num_rx_queues)
rxq = rxq % peer_dev->num_rx_queues;
- rq = &peer_ns->rq[rxq];
+ rq = peer_ns->rq[rxq];
skb_tx_timestamp(skb);
if (unlikely(nsim_forward_skb(peer_dev, skb, rq) == NET_RX_DROP))
@@ -359,25 +362,24 @@ static int nsim_poll(struct napi_struct *napi, int budget)
return done;
}
-static int nsim_create_page_pool(struct nsim_rq *rq)
+static int nsim_create_page_pool(struct page_pool **p, struct napi_struct *napi)
{
- struct page_pool_params p = {
+ struct page_pool_params params = {
.order = 0,
.pool_size = NSIM_RING_SIZE,
.nid = NUMA_NO_NODE,
- .dev = &rq->napi.dev->dev,
- .napi = &rq->napi,
+ .dev = &napi->dev->dev,
+ .napi = napi,
.dma_dir = DMA_BIDIRECTIONAL,
- .netdev = rq->napi.dev,
+ .netdev = napi->dev,
};
+ struct page_pool *pool;
- rq->page_pool = page_pool_create(&p);
- if (IS_ERR(rq->page_pool)) {
- int err = PTR_ERR(rq->page_pool);
+ pool = page_pool_create(&params);
+ if (IS_ERR(pool))
+ return PTR_ERR(pool);
- rq->page_pool = NULL;
- return err;
- }
+ *p = pool;
return 0;
}
@@ -388,15 +390,15 @@ static int nsim_init_napi(struct netdevsim *ns)
int err, i;
for (i = 0; i < dev->num_rx_queues; i++) {
- rq = &ns->rq[i];
+ rq = ns->rq[i];
- netif_napi_add(dev, &rq->napi, nsim_poll);
+ netif_napi_add_config(dev, &rq->napi, nsim_poll, i);
}
for (i = 0; i < dev->num_rx_queues; i++) {
- rq = &ns->rq[i];
+ rq = ns->rq[i];
- err = nsim_create_page_pool(rq);
+ err = nsim_create_page_pool(&rq->page_pool, &rq->napi);
if (err)
goto err_pp_destroy;
}
@@ -405,12 +407,12 @@ static int nsim_init_napi(struct netdevsim *ns)
err_pp_destroy:
while (i--) {
- page_pool_destroy(ns->rq[i].page_pool);
- ns->rq[i].page_pool = NULL;
+ page_pool_destroy(ns->rq[i]->page_pool);
+ ns->rq[i]->page_pool = NULL;
}
for (i = 0; i < dev->num_rx_queues; i++)
- __netif_napi_del(&ns->rq[i].napi);
+ __netif_napi_del(&ns->rq[i]->napi);
return err;
}
@@ -421,7 +423,7 @@ static void nsim_enable_napi(struct netdevsim *ns)
int i;
for (i = 0; i < dev->num_rx_queues; i++) {
- struct nsim_rq *rq = &ns->rq[i];
+ struct nsim_rq *rq = ns->rq[i];
netif_queue_set_napi(dev, i, NETDEV_QUEUE_TYPE_RX, &rq->napi);
napi_enable(&rq->napi);
@@ -448,7 +450,7 @@ static void nsim_del_napi(struct netdevsim *ns)
int i;
for (i = 0; i < dev->num_rx_queues; i++) {
- struct nsim_rq *rq = &ns->rq[i];
+ struct nsim_rq *rq = ns->rq[i];
napi_disable(&rq->napi);
__netif_napi_del(&rq->napi);
@@ -456,8 +458,8 @@ static void nsim_del_napi(struct netdevsim *ns)
synchronize_net();
for (i = 0; i < dev->num_rx_queues; i++) {
- page_pool_destroy(ns->rq[i].page_pool);
- ns->rq[i].page_pool = NULL;
+ page_pool_destroy(ns->rq[i]->page_pool);
+ ns->rq[i]->page_pool = NULL;
}
}
@@ -595,6 +597,182 @@ static const struct netdev_stat_ops nsim_stat_ops = {
.get_base_stats = nsim_get_base_stats,
};
+static struct nsim_rq *nsim_queue_alloc(void)
+{
+ struct nsim_rq *rq;
+
+ rq = kzalloc(sizeof(*rq), GFP_KERNEL_ACCOUNT);
+ if (!rq)
+ return NULL;
+
+ skb_queue_head_init(&rq->skb_queue);
+ return rq;
+}
+
+static void nsim_queue_free(struct nsim_rq *rq)
+{
+ skb_queue_purge_reason(&rq->skb_queue, SKB_DROP_REASON_QUEUE_PURGE);
+ kfree(rq);
+}
+
+/* Queue reset mode is controlled by ns->rq_reset_mode.
+ * - normal - new NAPI new pool (old NAPI enabled when new added)
+ * - mode 1 - allocate new pool (NAPI is only disabled / enabled)
+ * - mode 2 - new NAPI new pool (old NAPI removed before new added)
+ * - mode 3 - new NAPI new pool (old NAPI disabled when new added)
+ */
+struct nsim_queue_mem {
+ struct nsim_rq *rq;
+ struct page_pool *pp;
+};
+
+static int
+nsim_queue_mem_alloc(struct net_device *dev, void *per_queue_mem, int idx)
+{
+ struct nsim_queue_mem *qmem = per_queue_mem;
+ struct netdevsim *ns = netdev_priv(dev);
+ int err;
+
+ if (ns->rq_reset_mode > 3)
+ return -EINVAL;
+
+ if (ns->rq_reset_mode == 1)
+ return nsim_create_page_pool(&qmem->pp, &ns->rq[idx]->napi);
+
+ qmem->rq = nsim_queue_alloc();
+ if (!qmem->rq)
+ return -ENOMEM;
+
+ err = nsim_create_page_pool(&qmem->rq->page_pool, &qmem->rq->napi);
+ if (err)
+ goto err_free;
+
+ if (!ns->rq_reset_mode)
+ netif_napi_add_config(dev, &qmem->rq->napi, nsim_poll, idx);
+
+ return 0;
+
+err_free:
+ nsim_queue_free(qmem->rq);
+ return err;
+}
+
+static void nsim_queue_mem_free(struct net_device *dev, void *per_queue_mem)
+{
+ struct nsim_queue_mem *qmem = per_queue_mem;
+ struct netdevsim *ns = netdev_priv(dev);
+
+ page_pool_destroy(qmem->pp);
+ if (qmem->rq) {
+ if (!ns->rq_reset_mode)
+ netif_napi_del(&qmem->rq->napi);
+ page_pool_destroy(qmem->rq->page_pool);
+ nsim_queue_free(qmem->rq);
+ }
+}
+
+static int
+nsim_queue_start(struct net_device *dev, void *per_queue_mem, int idx)
+{
+ struct nsim_queue_mem *qmem = per_queue_mem;
+ struct netdevsim *ns = netdev_priv(dev);
+
+ if (ns->rq_reset_mode == 1) {
+ ns->rq[idx]->page_pool = qmem->pp;
+ napi_enable(&ns->rq[idx]->napi);
+ return 0;
+ }
+
+ /* netif_napi_add()/_del() should normally be called from alloc/free,
+ * here we want to test various call orders.
+ */
+ if (ns->rq_reset_mode == 2) {
+ netif_napi_del(&ns->rq[idx]->napi);
+ netif_napi_add_config(dev, &qmem->rq->napi, nsim_poll, idx);
+ } else if (ns->rq_reset_mode == 3) {
+ netif_napi_add_config(dev, &qmem->rq->napi, nsim_poll, idx);
+ netif_napi_del(&ns->rq[idx]->napi);
+ }
+
+ ns->rq[idx] = qmem->rq;
+ napi_enable(&ns->rq[idx]->napi);
+
+ return 0;
+}
+
+static int nsim_queue_stop(struct net_device *dev, void *per_queue_mem, int idx)
+{
+ struct nsim_queue_mem *qmem = per_queue_mem;
+ struct netdevsim *ns = netdev_priv(dev);
+
+ napi_disable(&ns->rq[idx]->napi);
+
+ if (ns->rq_reset_mode == 1) {
+ qmem->pp = ns->rq[idx]->page_pool;
+ page_pool_disable_direct_recycling(qmem->pp);
+ } else {
+ qmem->rq = ns->rq[idx];
+ }
+
+ return 0;
+}
+
+static const struct netdev_queue_mgmt_ops nsim_queue_mgmt_ops = {
+ .ndo_queue_mem_size = sizeof(struct nsim_queue_mem),
+ .ndo_queue_mem_alloc = nsim_queue_mem_alloc,
+ .ndo_queue_mem_free = nsim_queue_mem_free,
+ .ndo_queue_start = nsim_queue_start,
+ .ndo_queue_stop = nsim_queue_stop,
+};
+
+static ssize_t
+nsim_qreset_write(struct file *file, const char __user *data,
+ size_t count, loff_t *ppos)
+{
+ struct netdevsim *ns = file->private_data;
+ unsigned int queue, mode;
+ char buf[32];
+ ssize_t ret;
+
+ if (count >= sizeof(buf))
+ return -EINVAL;
+ if (copy_from_user(buf, data, count))
+ return -EFAULT;
+ buf[count] = '\0';
+
+ ret = sscanf(buf, "%u %u", &queue, &mode);
+ if (ret != 2)
+ return -EINVAL;
+
+ rtnl_lock();
+ if (!netif_running(ns->netdev)) {
+ ret = -ENETDOWN;
+ goto exit_unlock;
+ }
+
+ if (queue >= ns->netdev->real_num_rx_queues) {
+ ret = -EINVAL;
+ goto exit_unlock;
+ }
+
+ ns->rq_reset_mode = mode;
+ ret = netdev_rx_queue_restart(ns->netdev, queue);
+ ns->rq_reset_mode = 0;
+ if (ret)
+ goto exit_unlock;
+
+ ret = count;
+exit_unlock:
+ rtnl_unlock();
+ return ret;
+}
+
+static const struct file_operations nsim_qreset_fops = {
+ .open = simple_open,
+ .write = nsim_qreset_write,
+ .owner = THIS_MODULE,
+};
+
static ssize_t
nsim_pp_hold_read(struct file *file, char __user *data,
size_t count, loff_t *ppos)
@@ -628,17 +806,17 @@ nsim_pp_hold_write(struct file *file, const char __user *data,
if (!netif_running(ns->netdev) && val) {
ret = -ENETDOWN;
} else if (val) {
- ns->page = page_pool_dev_alloc_pages(ns->rq[0].page_pool);
+ ns->page = page_pool_dev_alloc_pages(ns->rq[0]->page_pool);
if (!ns->page)
ret = -ENOMEM;
} else {
page_pool_put_full_page(ns->page->pp, ns->page, false);
ns->page = NULL;
}
- rtnl_unlock();
exit:
- return count;
+ rtnl_unlock();
+ return ret;
}
static const struct file_operations nsim_pp_hold_fops = {
@@ -677,27 +855,35 @@ static int nsim_queue_init(struct netdevsim *ns)
struct net_device *dev = ns->netdev;
int i;
- ns->rq = kvcalloc(dev->num_rx_queues, sizeof(*ns->rq),
- GFP_KERNEL_ACCOUNT | __GFP_RETRY_MAYFAIL);
+ ns->rq = kcalloc(dev->num_rx_queues, sizeof(*ns->rq),
+ GFP_KERNEL_ACCOUNT);
if (!ns->rq)
return -ENOMEM;
- for (i = 0; i < dev->num_rx_queues; i++)
- skb_queue_head_init(&ns->rq[i].skb_queue);
+ for (i = 0; i < dev->num_rx_queues; i++) {
+ ns->rq[i] = nsim_queue_alloc();
+ if (!ns->rq[i])
+ goto err_free_prev;
+ }
return 0;
+
+err_free_prev:
+ while (i--)
+ kfree(ns->rq[i]);
+ kfree(ns->rq);
+ return -ENOMEM;
}
-static void nsim_queue_free(struct netdevsim *ns)
+static void nsim_queue_uninit(struct netdevsim *ns)
{
struct net_device *dev = ns->netdev;
int i;
for (i = 0; i < dev->num_rx_queues; i++)
- skb_queue_purge_reason(&ns->rq[i].skb_queue,
- SKB_DROP_REASON_QUEUE_PURGE);
+ nsim_queue_free(ns->rq[i]);
- kvfree(ns->rq);
+ kfree(ns->rq);
ns->rq = NULL;
}
@@ -713,6 +899,7 @@ static int nsim_init_netdevsim(struct netdevsim *ns)
ns->phc = phc;
ns->netdev->netdev_ops = &nsim_netdev_ops;
ns->netdev->stat_ops = &nsim_stat_ops;
+ ns->netdev->queue_mgmt_ops = &nsim_queue_mgmt_ops;
err = nsim_udp_tunnels_info_create(ns->nsim_dev, ns->netdev);
if (err)
@@ -741,7 +928,7 @@ err_ipsec_teardown:
nsim_macsec_teardown(ns);
nsim_bpf_uninit(ns);
err_rq_destroy:
- nsim_queue_free(ns);
+ nsim_queue_uninit(ns);
err_utn_destroy:
rtnl_unlock();
nsim_udp_tunnels_info_destroy(ns->netdev);
@@ -798,6 +985,9 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port)
ns->pp_dfs = debugfs_create_file("pp_hold", 0600, nsim_dev_port->ddir,
ns, &nsim_pp_hold_fops);
+ ns->qr_dfs = debugfs_create_file("queue_reset", 0200,
+ nsim_dev_port->ddir, ns,
+ &nsim_qreset_fops);
return ns;
@@ -811,6 +1001,7 @@ void nsim_destroy(struct netdevsim *ns)
struct net_device *dev = ns->netdev;
struct netdevsim *peer;
+ debugfs_remove(ns->qr_dfs);
debugfs_remove(ns->pp_dfs);
rtnl_lock();
@@ -823,7 +1014,7 @@ void nsim_destroy(struct netdevsim *ns)
nsim_macsec_teardown(ns);
nsim_ipsec_teardown(ns);
nsim_bpf_uninit(ns);
- nsim_queue_free(ns);
+ nsim_queue_uninit(ns);
}
rtnl_unlock();
if (nsim_dev_port_is_pf(ns->nsim_dev_port))
diff --git a/drivers/net/netdevsim/netdevsim.h b/drivers/net/netdevsim/netdevsim.h
index bf02efa10956..a70f62af4c88 100644
--- a/drivers/net/netdevsim/netdevsim.h
+++ b/drivers/net/netdevsim/netdevsim.h
@@ -101,7 +101,9 @@ struct netdevsim {
struct nsim_dev *nsim_dev;
struct nsim_dev_port *nsim_dev_port;
struct mock_phc *phc;
- struct nsim_rq *rq;
+ struct nsim_rq **rq;
+
+ int rq_reset_mode;
u64 tx_packets;
u64 tx_bytes;
@@ -134,6 +136,7 @@ struct netdevsim {
struct page *page;
struct dentry *pp_dfs;
+ struct dentry *qr_dfs;
struct nsim_ethtool ethtool;
struct netdevsim __rcu *peer;
diff --git a/drivers/net/netkit.c b/drivers/net/netkit.c
index bb07725d1c72..1e1b00756be7 100644
--- a/drivers/net/netkit.c
+++ b/drivers/net/netkit.c
@@ -327,7 +327,7 @@ static int netkit_validate(struct nlattr *tb[], struct nlattr *data[],
static struct rtnl_link_ops netkit_link_ops;
-static int netkit_new_link(struct net *src_net, struct net_device *dev,
+static int netkit_new_link(struct net *peer_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -338,11 +338,11 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
enum netkit_scrub scrub_peer = NETKIT_SCRUB_DEFAULT;
enum netkit_mode mode = NETKIT_L3;
unsigned char ifname_assign_type;
+ u16 headroom = 0, tailroom = 0;
struct ifinfomsg *ifmp = NULL;
struct net_device *peer;
char ifname[IFNAMSIZ];
struct netkit *nk;
- struct net *net;
int err;
if (data) {
@@ -372,6 +372,10 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
if (err < 0)
return err;
}
+ if (data[IFLA_NETKIT_HEADROOM])
+ headroom = nla_get_u16(data[IFLA_NETKIT_HEADROOM]);
+ if (data[IFLA_NETKIT_TAILROOM])
+ tailroom = nla_get_u16(data[IFLA_NETKIT_TAILROOM]);
}
if (ifmp && tbp[IFLA_IFNAME]) {
@@ -385,15 +389,20 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
(tb[IFLA_ADDRESS] || tbp[IFLA_ADDRESS]))
return -EOPNOTSUPP;
- net = rtnl_link_get_net(src_net, tbp);
- peer = rtnl_create_link(net, ifname, ifname_assign_type,
+ peer = rtnl_create_link(peer_net, ifname, ifname_assign_type,
&netkit_link_ops, tbp, extack);
- if (IS_ERR(peer)) {
- put_net(net);
+ if (IS_ERR(peer))
return PTR_ERR(peer);
- }
netif_inherit_tso_max(peer, dev);
+ if (headroom) {
+ peer->needed_headroom = headroom;
+ dev->needed_headroom = headroom;
+ }
+ if (tailroom) {
+ peer->needed_tailroom = tailroom;
+ dev->needed_tailroom = tailroom;
+ }
if (mode == NETKIT_L2 && !(ifmp && tbp[IFLA_ADDRESS]))
eth_hw_addr_random(peer);
@@ -405,10 +414,10 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
nk->policy = policy_peer;
nk->scrub = scrub_peer;
nk->mode = mode;
+ nk->headroom = headroom;
bpf_mprog_bundle_init(&nk->bundle);
err = register_netdevice(peer);
- put_net(net);
if (err < 0)
goto err_register_peer;
netif_carrier_off(peer);
@@ -431,6 +440,7 @@ static int netkit_new_link(struct net *src_net, struct net_device *dev,
nk->policy = policy_prim;
nk->scrub = scrub_prim;
nk->mode = mode;
+ nk->headroom = headroom;
bpf_mprog_bundle_init(&nk->bundle);
err = register_netdevice(dev);
@@ -855,7 +865,18 @@ static int netkit_change_link(struct net_device *dev, struct nlattr *tb[],
struct net_device *peer = rtnl_dereference(nk->peer);
enum netkit_action policy;
struct nlattr *attr;
- int err;
+ int err, i;
+ static const struct {
+ u32 attr;
+ char *name;
+ } fixed_params[] = {
+ { IFLA_NETKIT_MODE, "operating mode" },
+ { IFLA_NETKIT_SCRUB, "scrubbing" },
+ { IFLA_NETKIT_PEER_SCRUB, "peer scrubbing" },
+ { IFLA_NETKIT_PEER_INFO, "peer info" },
+ { IFLA_NETKIT_HEADROOM, "headroom" },
+ { IFLA_NETKIT_TAILROOM, "tailroom" },
+ };
if (!nk->primary) {
NL_SET_ERR_MSG(extack,
@@ -863,28 +884,14 @@ static int netkit_change_link(struct net_device *dev, struct nlattr *tb[],
return -EACCES;
}
- if (data[IFLA_NETKIT_MODE]) {
- NL_SET_ERR_MSG_ATTR(extack, data[IFLA_NETKIT_MODE],
- "netkit link operating mode cannot be changed after device creation");
- return -EACCES;
- }
-
- if (data[IFLA_NETKIT_SCRUB]) {
- NL_SET_ERR_MSG_ATTR(extack, data[IFLA_NETKIT_SCRUB],
- "netkit scrubbing cannot be changed after device creation");
- return -EACCES;
- }
-
- if (data[IFLA_NETKIT_PEER_SCRUB]) {
- NL_SET_ERR_MSG_ATTR(extack, data[IFLA_NETKIT_PEER_SCRUB],
- "netkit scrubbing cannot be changed after device creation");
- return -EACCES;
- }
-
- if (data[IFLA_NETKIT_PEER_INFO]) {
- NL_SET_ERR_MSG_ATTR(extack, data[IFLA_NETKIT_PEER_INFO],
- "netkit peer info cannot be changed after device creation");
- return -EINVAL;
+ for (i = 0; i < ARRAY_SIZE(fixed_params); i++) {
+ attr = data[fixed_params[i].attr];
+ if (attr) {
+ NL_SET_ERR_MSG_ATTR_FMT(extack, attr,
+ "netkit link %s cannot be changed after device creation",
+ fixed_params[i].name);
+ return -EACCES;
+ }
}
if (data[IFLA_NETKIT_POLICY]) {
@@ -919,6 +926,8 @@ static size_t netkit_get_size(const struct net_device *dev)
nla_total_size(sizeof(u32)) + /* IFLA_NETKIT_PEER_SCRUB */
nla_total_size(sizeof(u32)) + /* IFLA_NETKIT_MODE */
nla_total_size(sizeof(u8)) + /* IFLA_NETKIT_PRIMARY */
+ nla_total_size(sizeof(u16)) + /* IFLA_NETKIT_HEADROOM */
+ nla_total_size(sizeof(u16)) + /* IFLA_NETKIT_TAILROOM */
0;
}
@@ -935,6 +944,10 @@ static int netkit_fill_info(struct sk_buff *skb, const struct net_device *dev)
return -EMSGSIZE;
if (nla_put_u32(skb, IFLA_NETKIT_SCRUB, nk->scrub))
return -EMSGSIZE;
+ if (nla_put_u16(skb, IFLA_NETKIT_HEADROOM, dev->needed_headroom))
+ return -EMSGSIZE;
+ if (nla_put_u16(skb, IFLA_NETKIT_TAILROOM, dev->needed_tailroom))
+ return -EMSGSIZE;
if (peer) {
nk = netkit_priv(peer);
@@ -952,6 +965,8 @@ static const struct nla_policy netkit_policy[IFLA_NETKIT_MAX + 1] = {
[IFLA_NETKIT_MODE] = NLA_POLICY_MAX(NLA_U32, NETKIT_L3),
[IFLA_NETKIT_POLICY] = { .type = NLA_U32 },
[IFLA_NETKIT_PEER_POLICY] = { .type = NLA_U32 },
+ [IFLA_NETKIT_HEADROOM] = { .type = NLA_U16 },
+ [IFLA_NETKIT_TAILROOM] = { .type = NLA_U16 },
[IFLA_NETKIT_SCRUB] = NLA_POLICY_MAX(NLA_U32, NETKIT_SCRUB_DEFAULT),
[IFLA_NETKIT_PEER_SCRUB] = NLA_POLICY_MAX(NLA_U32, NETKIT_SCRUB_DEFAULT),
[IFLA_NETKIT_PRIMARY] = { .type = NLA_REJECT,
diff --git a/drivers/net/pcs/pcs-lynx.c b/drivers/net/pcs/pcs-lynx.c
index b79aedad855b..6457190ec6e7 100644
--- a/drivers/net/pcs/pcs-lynx.c
+++ b/drivers/net/pcs/pcs-lynx.c
@@ -35,6 +35,27 @@ enum sgmii_speed {
#define phylink_pcs_to_lynx(pl_pcs) container_of((pl_pcs), struct lynx_pcs, pcs)
#define lynx_to_phylink_pcs(lynx) (&(lynx)->pcs)
+static unsigned int lynx_pcs_inband_caps(struct phylink_pcs *pcs,
+ phy_interface_t interface)
+{
+ switch (interface) {
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_SGMII:
+ case PHY_INTERFACE_MODE_QSGMII:
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
+
+ case PHY_INTERFACE_MODE_10GBASER:
+ case PHY_INTERFACE_MODE_2500BASEX:
+ return LINK_INBAND_DISABLE;
+
+ case PHY_INTERFACE_MODE_USXGMII:
+ return LINK_INBAND_ENABLE;
+
+ default:
+ return 0;
+ }
+}
+
static void lynx_pcs_get_state_usxgmii(struct mdio_device *pcs,
struct phylink_link_state *state)
{
@@ -306,15 +327,26 @@ static void lynx_pcs_link_up(struct phylink_pcs *pcs, unsigned int neg_mode,
}
static const struct phylink_pcs_ops lynx_pcs_phylink_ops = {
+ .pcs_inband_caps = lynx_pcs_inband_caps,
.pcs_get_state = lynx_pcs_get_state,
.pcs_config = lynx_pcs_config,
.pcs_an_restart = lynx_pcs_an_restart,
.pcs_link_up = lynx_pcs_link_up,
};
+static const phy_interface_t lynx_interfaces[] = {
+ PHY_INTERFACE_MODE_SGMII,
+ PHY_INTERFACE_MODE_QSGMII,
+ PHY_INTERFACE_MODE_1000BASEX,
+ PHY_INTERFACE_MODE_2500BASEX,
+ PHY_INTERFACE_MODE_10GBASER,
+ PHY_INTERFACE_MODE_USXGMII,
+};
+
static struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
{
struct lynx_pcs *lynx;
+ int i;
lynx = kzalloc(sizeof(*lynx), GFP_KERNEL);
if (!lynx)
@@ -326,6 +358,9 @@ static struct phylink_pcs *lynx_pcs_create(struct mdio_device *mdio)
lynx->pcs.neg_mode = true;
lynx->pcs.poll = true;
+ for (i = 0; i < ARRAY_SIZE(lynx_interfaces); i++)
+ __set_bit(lynx_interfaces[i], lynx->pcs.supported_interfaces);
+
return lynx_to_phylink_pcs(lynx);
}
diff --git a/drivers/net/pcs/pcs-mtk-lynxi.c b/drivers/net/pcs/pcs-mtk-lynxi.c
index 4f63abe638c4..4fe0fb6d12a4 100644
--- a/drivers/net/pcs/pcs-mtk-lynxi.c
+++ b/drivers/net/pcs/pcs-mtk-lynxi.c
@@ -88,6 +88,22 @@ static struct mtk_pcs_lynxi *pcs_to_mtk_pcs_lynxi(struct phylink_pcs *pcs)
return container_of(pcs, struct mtk_pcs_lynxi, pcs);
}
+static unsigned int mtk_pcs_lynxi_inband_caps(struct phylink_pcs *pcs,
+ phy_interface_t interface)
+{
+ switch (interface) {
+ case PHY_INTERFACE_MODE_1000BASEX:
+ case PHY_INTERFACE_MODE_SGMII:
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
+
+ case PHY_INTERFACE_MODE_2500BASEX:
+ return LINK_INBAND_DISABLE;
+
+ default:
+ return 0;
+ }
+}
+
static void mtk_pcs_lynxi_get_state(struct phylink_pcs *pcs,
struct phylink_link_state *state)
{
@@ -241,6 +257,7 @@ static void mtk_pcs_lynxi_disable(struct phylink_pcs *pcs)
}
static const struct phylink_pcs_ops mtk_pcs_lynxi_ops = {
+ .pcs_inband_caps = mtk_pcs_lynxi_inband_caps,
.pcs_get_state = mtk_pcs_lynxi_get_state,
.pcs_config = mtk_pcs_lynxi_config,
.pcs_an_restart = mtk_pcs_lynxi_restart_an,
@@ -290,6 +307,10 @@ struct phylink_pcs *mtk_pcs_lynxi_create(struct device *dev,
mpcs->pcs.poll = true;
mpcs->interface = PHY_INTERFACE_MODE_NA;
+ __set_bit(PHY_INTERFACE_MODE_SGMII, mpcs->pcs.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_1000BASEX, mpcs->pcs.supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_2500BASEX, mpcs->pcs.supported_interfaces);
+
return &mpcs->pcs;
}
EXPORT_SYMBOL(mtk_pcs_lynxi_create);
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 7246a910728d..c06b66f40022 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -567,14 +567,40 @@ static int xpcs_validate(struct phylink_pcs *pcs, unsigned long *supported,
return 0;
}
-void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
+static unsigned int xpcs_inband_caps(struct phylink_pcs *pcs,
+ phy_interface_t interface)
+{
+ struct dw_xpcs *xpcs = phylink_pcs_to_xpcs(pcs);
+ const struct dw_xpcs_compat *compat;
+
+ compat = xpcs_find_compat(xpcs, interface);
+ if (!compat)
+ return 0;
+
+ switch (compat->an_mode) {
+ case DW_AN_C73:
+ return LINK_INBAND_ENABLE;
+
+ case DW_AN_C37_SGMII:
+ case DW_AN_C37_1000BASEX:
+ return LINK_INBAND_DISABLE | LINK_INBAND_ENABLE;
+
+ case DW_10GBASER:
+ case DW_2500BASEX:
+ return LINK_INBAND_DISABLE;
+
+ default:
+ return 0;
+ }
+}
+
+static void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces)
{
const struct dw_xpcs_compat *compat;
for (compat = xpcs->desc->compat; compat->supported; compat++)
__set_bit(compat->interface, interfaces);
}
-EXPORT_SYMBOL_GPL(xpcs_get_interfaces);
int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns, int enable)
{
@@ -1306,6 +1332,7 @@ static const struct dw_xpcs_desc xpcs_desc_list[] = {
static const struct phylink_pcs_ops xpcs_phylink_ops = {
.pcs_validate = xpcs_validate,
+ .pcs_inband_caps = xpcs_inband_caps,
.pcs_pre_config = xpcs_pre_config,
.pcs_config = xpcs_config,
.pcs_get_state = xpcs_get_state,
@@ -1418,6 +1445,8 @@ static struct dw_xpcs *xpcs_create(struct mdio_device *mdiodev)
if (ret)
goto out_clear_clks;
+ xpcs_get_interfaces(xpcs, xpcs->pcs.supported_interfaces);
+
if (xpcs->info.pma == WX_TXGBE_XPCS_PMA_10G_ID)
xpcs->pcs.poll = false;
else
diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index 15828f4710a9..dc625f2b3ae4 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -287,8 +287,15 @@ config MICROCHIP_PHY
config MICROCHIP_T1_PHY
tristate "Microchip T1 PHYs"
+ select MICROCHIP_PHY_RDS_PTP if NETWORK_PHY_TIMESTAMPING && \
+ PTP_1588_CLOCK_OPTIONAL
help
- Supports the LAN87XX PHYs.
+ Supports the LAN8XXX PHYs.
+
+config MICROCHIP_PHY_RDS_PTP
+ tristate
+ help
+ Currently supports LAN887X T1 PHY
config MICROSEMI_PHY
tristate "Microsemi PHYs"
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index e6145153e837..39b72b464287 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -79,6 +79,7 @@ obj-$(CONFIG_MESON_GXL_PHY) += meson-gxl.o
obj-$(CONFIG_MICREL_KS8995MA) += spi_ks8995.o
obj-$(CONFIG_MICREL_PHY) += micrel.o
obj-$(CONFIG_MICROCHIP_PHY) += microchip.o
+obj-$(CONFIG_MICROCHIP_PHY_RDS_PTP) += microchip_rds_ptp.o
obj-$(CONFIG_MICROCHIP_T1_PHY) += microchip_t1.o
obj-$(CONFIG_MICROCHIP_T1S_PHY) += microchip_t1s.o
obj-$(CONFIG_MICROSEMI_PHY) += mscc/
diff --git a/drivers/net/phy/aquantia/aquantia_leds.c b/drivers/net/phy/aquantia/aquantia_leds.c
index 00ad2313fed3..951f46104eff 100644
--- a/drivers/net/phy/aquantia/aquantia_leds.c
+++ b/drivers/net/phy/aquantia/aquantia_leds.c
@@ -156,5 +156,5 @@ int aqr_phy_led_polarity_set(struct phy_device *phydev, int index, unsigned long
if (force_active_high || force_active_low)
return aqr_phy_led_active_low_set(phydev, index, force_active_low);
- unreachable();
+ return -EINVAL;
}
diff --git a/drivers/net/phy/dp83822.c b/drivers/net/phy/dp83822.c
index cf8b6d0bfaa9..334c17a68edd 100644
--- a/drivers/net/phy/dp83822.c
+++ b/drivers/net/phy/dp83822.c
@@ -22,8 +22,6 @@
#define DP83826C_PHY_ID 0x2000a130
#define DP83826NC_PHY_ID 0x2000a110
-#define DP83822_DEVADDR 0x1f
-
#define MII_DP83822_CTRL_2 0x0a
#define MII_DP83822_PHYSTS 0x10
#define MII_DP83822_PHYSCR 0x11
@@ -32,6 +30,7 @@
#define MII_DP83822_FCSCR 0x14
#define MII_DP83822_RCSR 0x17
#define MII_DP83822_RESET_CTRL 0x1f
+#define MII_DP83822_IOCTRL2 0x463
#define MII_DP83822_GENCFG 0x465
#define MII_DP83822_SOR1 0x467
@@ -106,6 +105,18 @@
#define DP83822_RX_CLK_SHIFT BIT(12)
#define DP83822_TX_CLK_SHIFT BIT(11)
+/* IOCTRL2 bits */
+#define DP83822_IOCTRL2_GPIO2_CLK_SRC GENMASK(6, 4)
+#define DP83822_IOCTRL2_GPIO2_CTRL GENMASK(2, 0)
+#define DP83822_IOCTRL2_GPIO2_CTRL_CLK_REF GENMASK(1, 0)
+
+#define DP83822_CLK_SRC_MAC_IF 0x0
+#define DP83822_CLK_SRC_XI 0x1
+#define DP83822_CLK_SRC_INT_REF 0x2
+#define DP83822_CLK_SRC_RMII_MASTER_MODE_REF 0x4
+#define DP83822_CLK_SRC_FREE_RUNNING 0x6
+#define DP83822_CLK_SRC_RECOVERED 0x7
+
/* SOR1 mode */
#define DP83822_STRAP_MODE1 0
#define DP83822_STRAP_MODE2 BIT(0)
@@ -141,6 +152,8 @@ struct dp83822_private {
u8 cfg_dac_minus;
u8 cfg_dac_plus;
struct ethtool_wolinfo wol;
+ bool set_gpio2_clk_out;
+ u32 gpio2_clk_out;
};
static int dp83822_config_wol(struct phy_device *phydev,
@@ -159,14 +172,14 @@ static int dp83822_config_wol(struct phy_device *phydev,
/* MAC addresses start with byte 5, but stored in mac[0].
* 822 PHYs store bytes 4|5, 2|3, 0|1
*/
- phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA1,
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_WOL_DA1,
(mac[1] << 8) | mac[0]);
- phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA2,
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_WOL_DA2,
(mac[3] << 8) | mac[2]);
- phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_DA3,
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_WOL_DA3,
(mac[5] << 8) | mac[4]);
- value = phy_read_mmd(phydev, DP83822_DEVADDR,
+ value = phy_read_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_WOL_CFG);
if (wol->wolopts & WAKE_MAGIC)
value |= DP83822_WOL_MAGIC_EN;
@@ -174,13 +187,13 @@ static int dp83822_config_wol(struct phy_device *phydev,
value &= ~DP83822_WOL_MAGIC_EN;
if (wol->wolopts & WAKE_MAGICSECURE) {
- phy_write_mmd(phydev, DP83822_DEVADDR,
+ phy_write_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_RXSOP1,
(wol->sopass[1] << 8) | wol->sopass[0]);
- phy_write_mmd(phydev, DP83822_DEVADDR,
+ phy_write_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_RXSOP2,
(wol->sopass[3] << 8) | wol->sopass[2]);
- phy_write_mmd(phydev, DP83822_DEVADDR,
+ phy_write_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_RXSOP3,
(wol->sopass[5] << 8) | wol->sopass[4]);
value |= DP83822_WOL_SECURE_ON;
@@ -194,10 +207,10 @@ static int dp83822_config_wol(struct phy_device *phydev,
value |= DP83822_WOL_EN | DP83822_WOL_INDICATION_SEL |
DP83822_WOL_CLR_INDICATION;
- return phy_write_mmd(phydev, DP83822_DEVADDR,
+ return phy_write_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_WOL_CFG, value);
} else {
- return phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
+ return phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_WOL_CFG,
DP83822_WOL_EN |
DP83822_WOL_MAGIC_EN |
@@ -226,23 +239,23 @@ static void dp83822_get_wol(struct phy_device *phydev,
wol->supported = (WAKE_MAGIC | WAKE_MAGICSECURE);
wol->wolopts = 0;
- value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);
+ value = phy_read_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_WOL_CFG);
if (value & DP83822_WOL_MAGIC_EN)
wol->wolopts |= WAKE_MAGIC;
if (value & DP83822_WOL_SECURE_ON) {
- sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,
+ sopass_val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_RXSOP1);
wol->sopass[0] = (sopass_val & 0xff);
wol->sopass[1] = (sopass_val >> 8);
- sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,
+ sopass_val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_RXSOP2);
wol->sopass[2] = (sopass_val & 0xff);
wol->sopass[3] = (sopass_val >> 8);
- sopass_val = phy_read_mmd(phydev, DP83822_DEVADDR,
+ sopass_val = phy_read_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_RXSOP3);
wol->sopass[4] = (sopass_val & 0xff);
wol->sopass[5] = (sopass_val >> 8);
@@ -415,6 +428,15 @@ static int dp83822_config_init(struct phy_device *phydev)
int err = 0;
int bmcr;
+ if (dp83822->set_gpio2_clk_out)
+ phy_modify_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_IOCTRL2,
+ DP83822_IOCTRL2_GPIO2_CTRL |
+ DP83822_IOCTRL2_GPIO2_CLK_SRC,
+ FIELD_PREP(DP83822_IOCTRL2_GPIO2_CTRL,
+ DP83822_IOCTRL2_GPIO2_CTRL_CLK_REF) |
+ FIELD_PREP(DP83822_IOCTRL2_GPIO2_CLK_SRC,
+ dp83822->gpio2_clk_out));
+
if (phy_interface_is_rgmii(phydev)) {
rx_int_delay = phy_get_internal_delay(phydev, dev, NULL, 0,
true);
@@ -430,18 +452,18 @@ static int dp83822_config_init(struct phy_device *phydev)
if (tx_int_delay <= 0)
rgmii_delay |= DP83822_TX_CLK_SHIFT;
- err = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,
+ err = phy_modify_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_RCSR,
DP83822_RX_CLK_SHIFT | DP83822_TX_CLK_SHIFT, rgmii_delay);
if (err)
return err;
- err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
+ err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);
if (err)
return err;
} else {
- err = phy_clear_bits_mmd(phydev, DP83822_DEVADDR,
+ err = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_RCSR, DP83822_RGMII_MODE_EN);
if (err)
@@ -496,7 +518,7 @@ static int dp83822_config_init(struct phy_device *phydev)
return err;
if (dp83822->fx_signal_det_low) {
- err = phy_set_bits_mmd(phydev, DP83822_DEVADDR,
+ err = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2,
MII_DP83822_GENCFG,
DP83822_SIG_DET_LOW);
if (err)
@@ -514,10 +536,10 @@ static int dp8382x_config_rmii_mode(struct phy_device *phydev)
if (!device_property_read_string(dev, "ti,rmii-mode", &of_val)) {
if (strcmp(of_val, "master") == 0) {
- ret = phy_clear_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,
+ ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_RCSR,
DP83822_RMII_MODE_SEL);
} else if (strcmp(of_val, "slave") == 0) {
- ret = phy_set_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,
+ ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_RCSR,
DP83822_RMII_MODE_SEL);
} else {
phydev_err(phydev, "Invalid value for ti,rmii-mode property (%s)\n",
@@ -539,7 +561,7 @@ static int dp83826_config_init(struct phy_device *phydev)
int ret;
if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
- ret = phy_set_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,
+ ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_RCSR,
DP83822_RMII_MODE_EN);
if (ret)
return ret;
@@ -548,7 +570,7 @@ static int dp83826_config_init(struct phy_device *phydev)
if (ret)
return ret;
} else {
- ret = phy_clear_bits_mmd(phydev, DP83822_DEVADDR, MII_DP83822_RCSR,
+ ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_RCSR,
DP83822_RMII_MODE_EN);
if (ret)
return ret;
@@ -560,7 +582,7 @@ static int dp83826_config_init(struct phy_device *phydev)
FIELD_GET(DP83826_CFG_DAC_MINUS_MDIX_5_TO_4,
dp83822->cfg_dac_minus));
mask = DP83826_VOD_CFG1_MINUS_MDIX_MASK | DP83826_VOD_CFG1_MINUS_MDI_MASK;
- ret = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83826_VOD_CFG1, mask, val);
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, MII_DP83826_VOD_CFG1, mask, val);
if (ret)
return ret;
@@ -568,7 +590,7 @@ static int dp83826_config_init(struct phy_device *phydev)
FIELD_GET(DP83826_CFG_DAC_MINUS_MDIX_3_TO_0,
dp83822->cfg_dac_minus));
mask = DP83826_VOD_CFG2_MINUS_MDIX_MASK;
- ret = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83826_VOD_CFG2, mask, val);
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, MII_DP83826_VOD_CFG2, mask, val);
if (ret)
return ret;
}
@@ -577,7 +599,7 @@ static int dp83826_config_init(struct phy_device *phydev)
val = FIELD_PREP(DP83826_VOD_CFG2_PLUS_MDIX_MASK, dp83822->cfg_dac_plus) |
FIELD_PREP(DP83826_VOD_CFG2_PLUS_MDI_MASK, dp83822->cfg_dac_plus);
mask = DP83826_VOD_CFG2_PLUS_MDIX_MASK | DP83826_VOD_CFG2_PLUS_MDI_MASK;
- ret = phy_modify_mmd(phydev, DP83822_DEVADDR, MII_DP83826_VOD_CFG2, mask, val);
+ ret = phy_modify_mmd(phydev, MDIO_MMD_VEND2, MII_DP83826_VOD_CFG2, mask, val);
if (ret)
return ret;
}
@@ -613,6 +635,7 @@ static int dp83822_of_init(struct phy_device *phydev)
{
struct dp83822_private *dp83822 = phydev->priv;
struct device *dev = &phydev->mdio.dev;
+ const char *of_val;
/* Signal detection for the PHY is only enabled if the FX_EN and the
* SD_EN pins are strapped. Signal detection can only enabled if FX_EN
@@ -625,6 +648,29 @@ static int dp83822_of_init(struct phy_device *phydev)
dp83822->fx_enabled = device_property_present(dev,
"ti,fiber-mode");
+ if (!device_property_read_string(dev, "ti,gpio2-clk-out", &of_val)) {
+ if (strcmp(of_val, "mac-if") == 0) {
+ dp83822->gpio2_clk_out = DP83822_CLK_SRC_MAC_IF;
+ } else if (strcmp(of_val, "xi") == 0) {
+ dp83822->gpio2_clk_out = DP83822_CLK_SRC_XI;
+ } else if (strcmp(of_val, "int-ref") == 0) {
+ dp83822->gpio2_clk_out = DP83822_CLK_SRC_INT_REF;
+ } else if (strcmp(of_val, "rmii-master-mode-ref") == 0) {
+ dp83822->gpio2_clk_out = DP83822_CLK_SRC_RMII_MASTER_MODE_REF;
+ } else if (strcmp(of_val, "free-running") == 0) {
+ dp83822->gpio2_clk_out = DP83822_CLK_SRC_FREE_RUNNING;
+ } else if (strcmp(of_val, "recovered") == 0) {
+ dp83822->gpio2_clk_out = DP83822_CLK_SRC_RECOVERED;
+ } else {
+ phydev_err(phydev,
+ "Invalid value for ti,gpio2-clk-out property (%s)\n",
+ of_val);
+ return -EINVAL;
+ }
+
+ dp83822->set_gpio2_clk_out = true;
+ }
+
return 0;
}
@@ -673,7 +719,7 @@ static int dp83822_read_straps(struct phy_device *phydev)
int fx_enabled, fx_sd_enable;
int val;
- val = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_SOR1);
+ val = phy_read_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_SOR1);
if (val < 0)
return val;
@@ -748,7 +794,7 @@ static int dp83822_suspend(struct phy_device *phydev)
{
int value;
- value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);
+ value = phy_read_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_WOL_CFG);
if (!(value & DP83822_WOL_EN))
genphy_suspend(phydev);
@@ -762,9 +808,9 @@ static int dp83822_resume(struct phy_device *phydev)
genphy_resume(phydev);
- value = phy_read_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG);
+ value = phy_read_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_WOL_CFG);
- phy_write_mmd(phydev, DP83822_DEVADDR, MII_DP83822_WOL_CFG, value |
+ phy_write_mmd(phydev, MDIO_MMD_VEND2, MII_DP83822_WOL_CFG, value |
DP83822_WOL_CLR_INDICATION);
return 0;
diff --git a/drivers/net/phy/intel-xway.c b/drivers/net/phy/intel-xway.c
index b672c55a7a4e..e6ed2413e514 100644
--- a/drivers/net/phy/intel-xway.c
+++ b/drivers/net/phy/intel-xway.c
@@ -529,7 +529,7 @@ static int xway_gphy_led_polarity_set(struct phy_device *phydev, int index,
if (force_active_high)
return phy_clear_bits(phydev, XWAY_MDIO_LED, XWAY_GPHY_LED_INV(index));
- unreachable();
+ return -EINVAL;
}
static struct phy_driver xway_gphy[] = {
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index b885bc0fe6e0..ffe223ad9e5f 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -1550,7 +1550,6 @@ static int m88e1540_get_fld(struct phy_device *phydev, u8 *msecs)
static int m88e1540_set_fld(struct phy_device *phydev, const u8 *msecs)
{
- struct ethtool_keee eee;
int val, ret;
if (*msecs == ETHTOOL_PHY_FAST_LINK_DOWN_OFF)
@@ -1560,8 +1559,7 @@ static int m88e1540_set_fld(struct phy_device *phydev, const u8 *msecs)
/* According to the Marvell data sheet EEE must be disabled for
* Fast Link Down detection to work properly
*/
- ret = genphy_c45_ethtool_get_eee(phydev, &eee);
- if (!ret && eee.eee_enabled) {
+ if (phydev->eee_cfg.eee_enabled) {
phydev_warn(phydev, "Fast Link Down detection requires EEE to be disabled!\n");
return -EBUSY;
}
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 3ef508840674..0fd1cb676cd5 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -432,10 +432,12 @@ struct kszphy_ptp_priv {
struct kszphy_priv {
struct kszphy_ptp_priv ptp_priv;
const struct kszphy_type *type;
+ struct clk *clk;
int led_mode;
u16 vct_ctrl1000;
bool rmii_ref_clk_sel;
bool rmii_ref_clk_sel_val;
+ bool clk_enable;
u64 stats[ARRAY_SIZE(kszphy_hw_stats)];
};
@@ -2004,7 +2006,7 @@ static int ksz9477_config_init(struct phy_device *phydev)
* in this switch shall be regarded as broken.
*/
if (phydev->dev_flags & MICREL_NO_EEE)
- linkmode_fill(phydev->eee_broken_modes);
+ phy_disable_eee(phydev);
return kszphy_config_init(phydev);
}
@@ -2050,6 +2052,46 @@ static void kszphy_get_stats(struct phy_device *phydev,
data[i] = kszphy_get_stat(phydev, i);
}
+static void kszphy_enable_clk(struct phy_device *phydev)
+{
+ struct kszphy_priv *priv = phydev->priv;
+
+ if (!priv->clk_enable && priv->clk) {
+ clk_prepare_enable(priv->clk);
+ priv->clk_enable = true;
+ }
+}
+
+static void kszphy_disable_clk(struct phy_device *phydev)
+{
+ struct kszphy_priv *priv = phydev->priv;
+
+ if (priv->clk_enable && priv->clk) {
+ clk_disable_unprepare(priv->clk);
+ priv->clk_enable = false;
+ }
+}
+
+static int kszphy_generic_resume(struct phy_device *phydev)
+{
+ kszphy_enable_clk(phydev);
+
+ return genphy_resume(phydev);
+}
+
+static int kszphy_generic_suspend(struct phy_device *phydev)
+{
+ int ret;
+
+ ret = genphy_suspend(phydev);
+ if (ret)
+ return ret;
+
+ kszphy_disable_clk(phydev);
+
+ return 0;
+}
+
static int kszphy_suspend(struct phy_device *phydev)
{
/* Disable PHY Interrupts */
@@ -2059,7 +2101,7 @@ static int kszphy_suspend(struct phy_device *phydev)
phydev->drv->config_intr(phydev);
}
- return genphy_suspend(phydev);
+ return kszphy_generic_suspend(phydev);
}
static void kszphy_parse_led_mode(struct phy_device *phydev)
@@ -2090,7 +2132,9 @@ static int kszphy_resume(struct phy_device *phydev)
{
int ret;
- genphy_resume(phydev);
+ ret = kszphy_generic_resume(phydev);
+ if (ret)
+ return ret;
/* After switching from power-down to normal mode, an internal global
* reset is automatically generated. Wait a minimum of 1 ms before
@@ -2112,6 +2156,24 @@ static int kszphy_resume(struct phy_device *phydev)
return 0;
}
+/* Because of errata DS80000700A, receiver error following software
+ * power down. Suspend and resume callbacks only disable and enable
+ * external rmii reference clock.
+ */
+static int ksz8041_resume(struct phy_device *phydev)
+{
+ kszphy_enable_clk(phydev);
+
+ return 0;
+}
+
+static int ksz8041_suspend(struct phy_device *phydev)
+{
+ kszphy_disable_clk(phydev);
+
+ return 0;
+}
+
static int ksz9477_resume(struct phy_device *phydev)
{
int ret;
@@ -2159,7 +2221,10 @@ static int ksz8061_resume(struct phy_device *phydev)
if (!(ret & BMCR_PDOWN))
return 0;
- genphy_resume(phydev);
+ ret = kszphy_generic_resume(phydev);
+ if (ret)
+ return ret;
+
usleep_range(1000, 2000);
/* Re-program the value after chip is reset. */
@@ -2177,6 +2242,11 @@ static int ksz8061_resume(struct phy_device *phydev)
return 0;
}
+static int ksz8061_suspend(struct phy_device *phydev)
+{
+ return kszphy_suspend(phydev);
+}
+
static int kszphy_probe(struct phy_device *phydev)
{
const struct kszphy_type *type = phydev->drv->driver_data;
@@ -2217,10 +2287,14 @@ static int kszphy_probe(struct phy_device *phydev)
} else if (!clk) {
/* unnamed clock from the generic ethernet-phy binding */
clk = devm_clk_get_optional_enabled(&phydev->mdio.dev, NULL);
- if (IS_ERR(clk))
- return PTR_ERR(clk);
}
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ clk_disable_unprepare(clk);
+ priv->clk = clk;
+
if (ksz8041_fiber_mode(phydev))
phydev->port = PORT_FIBRE;
@@ -5290,6 +5364,21 @@ static int lan8841_probe(struct phy_device *phydev)
return 0;
}
+static int lan8804_resume(struct phy_device *phydev)
+{
+ return kszphy_resume(phydev);
+}
+
+static int lan8804_suspend(struct phy_device *phydev)
+{
+ return kszphy_generic_suspend(phydev);
+}
+
+static int lan8841_resume(struct phy_device *phydev)
+{
+ return kszphy_generic_resume(phydev);
+}
+
static int lan8841_suspend(struct phy_device *phydev)
{
struct kszphy_priv *priv = phydev->priv;
@@ -5298,7 +5387,7 @@ static int lan8841_suspend(struct phy_device *phydev)
if (ptp_priv->ptp_clock)
ptp_cancel_worker_sync(ptp_priv->ptp_clock);
- return genphy_suspend(phydev);
+ return kszphy_generic_suspend(phydev);
}
static struct phy_driver ksphy_driver[] = {
@@ -5358,9 +5447,8 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
- /* No suspend/resume callbacks because of errata DS80000700A,
- * receiver error following software power down.
- */
+ .suspend = ksz8041_suspend,
+ .resume = ksz8041_resume,
}, {
.phy_id = PHY_ID_KSZ8041RNLI,
.phy_id_mask = MICREL_PHY_ID_MASK,
@@ -5436,7 +5524,7 @@ static struct phy_driver ksphy_driver[] = {
.soft_reset = genphy_soft_reset,
.config_intr = kszphy_config_intr,
.handle_interrupt = kszphy_handle_interrupt,
- .suspend = kszphy_suspend,
+ .suspend = ksz8061_suspend,
.resume = ksz8061_resume,
}, {
.phy_id = PHY_ID_KSZ9021,
@@ -5507,8 +5595,8 @@ static struct phy_driver ksphy_driver[] = {
.get_sset_count = kszphy_get_sset_count,
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
- .suspend = genphy_suspend,
- .resume = kszphy_resume,
+ .suspend = lan8804_suspend,
+ .resume = lan8804_resume,
.config_intr = lan8804_config_intr,
.handle_interrupt = lan8804_handle_interrupt,
}, {
@@ -5526,7 +5614,7 @@ static struct phy_driver ksphy_driver[] = {
.get_strings = kszphy_get_strings,
.get_stats = kszphy_get_stats,
.suspend = lan8841_suspend,
- .resume = genphy_resume,
+ .resume = lan8841_resume,
.cable_test_start = lan8814_cable_test_start,
.cable_test_get_status = ksz886x_cable_test_get_status,
}, {
diff --git a/drivers/net/phy/microchip.c b/drivers/net/phy/microchip.c
index d3273bc0da4a..691969a4910f 100644
--- a/drivers/net/phy/microchip.c
+++ b/drivers/net/phy/microchip.c
@@ -351,6 +351,22 @@ static int lan88xx_config_aneg(struct phy_device *phydev)
static void lan88xx_link_change_notify(struct phy_device *phydev)
{
int temp;
+ int ret;
+
+ /* Reset PHY to ensure MII_LPA provides up-to-date information. This
+ * issue is reproducible only after parallel detection, as described
+ * in IEEE 802.3-2022, Section 28.2.3.1 ("Parallel detection function"),
+ * where the link partner does not support auto-negotiation.
+ */
+ if (phydev->state == PHY_NOLINK) {
+ ret = phy_init_hw(phydev);
+ if (ret < 0)
+ goto link_change_notify_failed;
+
+ ret = _phy_start_aneg(phydev);
+ if (ret < 0)
+ goto link_change_notify_failed;
+ }
/* At forced 100 F/H mode, chip may fail to set mode correctly
* when cable is switched between long(~50+m) and short one.
@@ -377,6 +393,11 @@ static void lan88xx_link_change_notify(struct phy_device *phydev)
temp |= LAN88XX_INT_MASK_MDINTPIN_EN_;
phy_write(phydev, LAN88XX_INT_MASK, temp);
}
+
+ return;
+
+link_change_notify_failed:
+ phydev_err(phydev, "Link change process failed %pe\n", ERR_PTR(ret));
}
/**
diff --git a/drivers/net/phy/microchip_rds_ptp.c b/drivers/net/phy/microchip_rds_ptp.c
new file mode 100644
index 000000000000..2936e46531cf
--- /dev/null
+++ b/drivers/net/phy/microchip_rds_ptp.c
@@ -0,0 +1,1039 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (C) 2024 Microchip Technology
+
+#include "microchip_rds_ptp.h"
+
+static int mchp_rds_phy_read_mmd(struct mchp_rds_ptp_clock *clock,
+ u32 offset, enum mchp_rds_ptp_base base)
+{
+ struct phy_device *phydev = clock->phydev;
+ u32 addr;
+
+ addr = (offset + ((base == MCHP_RDS_PTP_PORT) ? BASE_PORT(clock) :
+ BASE_CLK(clock)));
+
+ return phy_read_mmd(phydev, PTP_MMD(clock), addr);
+}
+
+static int mchp_rds_phy_write_mmd(struct mchp_rds_ptp_clock *clock,
+ u32 offset, enum mchp_rds_ptp_base base,
+ u16 val)
+{
+ struct phy_device *phydev = clock->phydev;
+ u32 addr;
+
+ addr = (offset + ((base == MCHP_RDS_PTP_PORT) ? BASE_PORT(clock) :
+ BASE_CLK(clock)));
+
+ return phy_write_mmd(phydev, PTP_MMD(clock), addr, val);
+}
+
+static int mchp_rds_phy_modify_mmd(struct mchp_rds_ptp_clock *clock,
+ u32 offset, enum mchp_rds_ptp_base base,
+ u16 mask, u16 val)
+{
+ struct phy_device *phydev = clock->phydev;
+ u32 addr;
+
+ addr = (offset + ((base == MCHP_RDS_PTP_PORT) ? BASE_PORT(clock) :
+ BASE_CLK(clock)));
+
+ return phy_modify_mmd(phydev, PTP_MMD(clock), addr, mask, val);
+}
+
+static int mchp_rds_phy_set_bits_mmd(struct mchp_rds_ptp_clock *clock,
+ u32 offset, enum mchp_rds_ptp_base base,
+ u16 val)
+{
+ struct phy_device *phydev = clock->phydev;
+ u32 addr;
+
+ addr = (offset + ((base == MCHP_RDS_PTP_PORT) ? BASE_PORT(clock) :
+ BASE_CLK(clock)));
+
+ return phy_set_bits_mmd(phydev, PTP_MMD(clock), addr, val);
+}
+
+static int mchp_rds_ptp_flush_fifo(struct mchp_rds_ptp_clock *clock,
+ enum mchp_rds_ptp_fifo_dir dir)
+{
+ int rc;
+
+ if (dir == MCHP_RDS_PTP_EGRESS_FIFO)
+ skb_queue_purge(&clock->tx_queue);
+ else
+ skb_queue_purge(&clock->rx_queue);
+
+ for (int i = 0; i < MCHP_RDS_PTP_FIFO_SIZE; ++i) {
+ rc = mchp_rds_phy_read_mmd(clock,
+ dir == MCHP_RDS_PTP_EGRESS_FIFO ?
+ MCHP_RDS_PTP_TX_MSG_HDR2 :
+ MCHP_RDS_PTP_RX_MSG_HDR2,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ return rc;
+ }
+ return mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_INT_STS,
+ MCHP_RDS_PTP_PORT);
+}
+
+static int mchp_rds_ptp_config_intr(struct mchp_rds_ptp_clock *clock,
+ bool enable)
+{
+ /* Enable or disable ptp interrupts */
+ return mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_INT_EN,
+ MCHP_RDS_PTP_PORT,
+ enable ? MCHP_RDS_PTP_INT_ALL_MSK : 0);
+}
+
+static void mchp_rds_ptp_txtstamp(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type)
+{
+ struct mchp_rds_ptp_clock *clock = container_of(mii_ts,
+ struct mchp_rds_ptp_clock,
+ mii_ts);
+
+ switch (clock->hwts_tx_type) {
+ case HWTSTAMP_TX_ONESTEP_SYNC:
+ if (ptp_msg_is_sync(skb, type)) {
+ kfree_skb(skb);
+ return;
+ }
+ fallthrough;
+ case HWTSTAMP_TX_ON:
+ skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+ skb_queue_tail(&clock->tx_queue, skb);
+ break;
+ case HWTSTAMP_TX_OFF:
+ default:
+ kfree_skb(skb);
+ break;
+ }
+}
+
+static bool mchp_rds_ptp_get_sig_rx(struct sk_buff *skb, u16 *sig)
+{
+ struct ptp_header *ptp_header;
+ int type;
+
+ skb_push(skb, ETH_HLEN);
+ type = ptp_classify_raw(skb);
+ if (type == PTP_CLASS_NONE)
+ return false;
+
+ ptp_header = ptp_parse_header(skb, type);
+ if (!ptp_header)
+ return false;
+
+ skb_pull_inline(skb, ETH_HLEN);
+
+ *sig = (__force u16)(ntohs(ptp_header->sequence_id));
+
+ return true;
+}
+
+static bool mchp_rds_ptp_match_skb(struct mchp_rds_ptp_clock *clock,
+ struct mchp_rds_ptp_rx_ts *rx_ts)
+{
+ struct skb_shared_hwtstamps *shhwtstamps;
+ struct sk_buff *skb, *skb_tmp;
+ unsigned long flags;
+ bool rc = false;
+ u16 skb_sig;
+
+ spin_lock_irqsave(&clock->rx_queue.lock, flags);
+ skb_queue_walk_safe(&clock->rx_queue, skb, skb_tmp) {
+ if (!mchp_rds_ptp_get_sig_rx(skb, &skb_sig))
+ continue;
+
+ if (skb_sig != rx_ts->seq_id)
+ continue;
+
+ __skb_unlink(skb, &clock->rx_queue);
+
+ rc = true;
+ break;
+ }
+ spin_unlock_irqrestore(&clock->rx_queue.lock, flags);
+
+ if (rc) {
+ shhwtstamps = skb_hwtstamps(skb);
+ shhwtstamps->hwtstamp = ktime_set(rx_ts->seconds, rx_ts->nsec);
+ netif_rx(skb);
+ }
+
+ return rc;
+}
+
+static void mchp_rds_ptp_match_rx_ts(struct mchp_rds_ptp_clock *clock,
+ struct mchp_rds_ptp_rx_ts *rx_ts)
+{
+ unsigned long flags;
+
+ /* If we failed to match the skb add it to the queue for when
+ * the frame will come
+ */
+ if (!mchp_rds_ptp_match_skb(clock, rx_ts)) {
+ spin_lock_irqsave(&clock->rx_ts_lock, flags);
+ list_add(&rx_ts->list, &clock->rx_ts_list);
+ spin_unlock_irqrestore(&clock->rx_ts_lock, flags);
+ } else {
+ kfree(rx_ts);
+ }
+}
+
+static void mchp_rds_ptp_match_rx_skb(struct mchp_rds_ptp_clock *clock,
+ struct sk_buff *skb)
+{
+ struct mchp_rds_ptp_rx_ts *rx_ts, *tmp, *rx_ts_var = NULL;
+ struct skb_shared_hwtstamps *shhwtstamps;
+ unsigned long flags;
+ u16 skb_sig;
+
+ if (!mchp_rds_ptp_get_sig_rx(skb, &skb_sig))
+ return;
+
+ /* Iterate over all RX timestamps and match it with the received skbs */
+ spin_lock_irqsave(&clock->rx_ts_lock, flags);
+ list_for_each_entry_safe(rx_ts, tmp, &clock->rx_ts_list, list) {
+ /* Check if we found the signature we were looking for. */
+ if (skb_sig != rx_ts->seq_id)
+ continue;
+
+ shhwtstamps = skb_hwtstamps(skb);
+ shhwtstamps->hwtstamp = ktime_set(rx_ts->seconds, rx_ts->nsec);
+ netif_rx(skb);
+
+ rx_ts_var = rx_ts;
+
+ break;
+ }
+ spin_unlock_irqrestore(&clock->rx_ts_lock, flags);
+
+ if (rx_ts_var) {
+ list_del(&rx_ts_var->list);
+ kfree(rx_ts_var);
+ } else {
+ skb_queue_tail(&clock->rx_queue, skb);
+ }
+}
+
+static bool mchp_rds_ptp_rxtstamp(struct mii_timestamper *mii_ts,
+ struct sk_buff *skb, int type)
+{
+ struct mchp_rds_ptp_clock *clock = container_of(mii_ts,
+ struct mchp_rds_ptp_clock,
+ mii_ts);
+
+ if (clock->rx_filter == HWTSTAMP_FILTER_NONE ||
+ type == PTP_CLASS_NONE)
+ return false;
+
+ if ((type & clock->version) == 0 || (type & clock->layer) == 0)
+ return false;
+
+ /* Here if match occurs skb is sent to application, If not skb is added
+ * to queue and sending skb to application will get handled when
+ * interrupt occurs i.e., it get handles in interrupt handler. By
+ * any means skb will reach the application so we should not return
+ * false here if skb doesn't matches.
+ */
+ mchp_rds_ptp_match_rx_skb(clock, skb);
+
+ return true;
+}
+
+static int mchp_rds_ptp_hwtstamp(struct mii_timestamper *mii_ts,
+ struct kernel_hwtstamp_config *config,
+ struct netlink_ext_ack *extack)
+{
+ struct mchp_rds_ptp_clock *clock =
+ container_of(mii_ts, struct mchp_rds_ptp_clock,
+ mii_ts);
+ struct mchp_rds_ptp_rx_ts *rx_ts, *tmp;
+ int txcfg = 0, rxcfg = 0;
+ unsigned long flags;
+ int rc;
+
+ clock->hwts_tx_type = config->tx_type;
+ clock->rx_filter = config->rx_filter;
+
+ switch (config->rx_filter) {
+ case HWTSTAMP_FILTER_NONE:
+ clock->layer = 0;
+ clock->version = 0;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L4_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L4_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L4_DELAY_REQ:
+ clock->layer = PTP_CLASS_L4;
+ clock->version = PTP_CLASS_V2;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_L2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ:
+ clock->layer = PTP_CLASS_L2;
+ clock->version = PTP_CLASS_V2;
+ break;
+ case HWTSTAMP_FILTER_PTP_V2_EVENT:
+ case HWTSTAMP_FILTER_PTP_V2_SYNC:
+ case HWTSTAMP_FILTER_PTP_V2_DELAY_REQ:
+ clock->layer = PTP_CLASS_L4 | PTP_CLASS_L2;
+ clock->version = PTP_CLASS_V2;
+ break;
+ default:
+ return -ERANGE;
+ }
+
+ /* Setup parsing of the frames and enable the timestamping for ptp
+ * frames
+ */
+ if (clock->layer & PTP_CLASS_L2) {
+ rxcfg = MCHP_RDS_PTP_PARSE_CONFIG_LAYER2_EN;
+ txcfg = MCHP_RDS_PTP_PARSE_CONFIG_LAYER2_EN;
+ }
+ if (clock->layer & PTP_CLASS_L4) {
+ rxcfg |= MCHP_RDS_PTP_PARSE_CONFIG_IPV4_EN |
+ MCHP_RDS_PTP_PARSE_CONFIG_IPV6_EN;
+ txcfg |= MCHP_RDS_PTP_PARSE_CONFIG_IPV4_EN |
+ MCHP_RDS_PTP_PARSE_CONFIG_IPV6_EN;
+ }
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_RX_PARSE_CONFIG,
+ MCHP_RDS_PTP_PORT, rxcfg);
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_TX_PARSE_CONFIG,
+ MCHP_RDS_PTP_PORT, txcfg);
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_RX_TIMESTAMP_EN,
+ MCHP_RDS_PTP_PORT,
+ MCHP_RDS_PTP_TIMESTAMP_EN_ALL);
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_TX_TIMESTAMP_EN,
+ MCHP_RDS_PTP_PORT,
+ MCHP_RDS_PTP_TIMESTAMP_EN_ALL);
+ if (rc < 0)
+ return rc;
+
+ if (clock->hwts_tx_type == HWTSTAMP_TX_ONESTEP_SYNC)
+ /* Enable / disable of the TX timestamp in the SYNC frames */
+ rc = mchp_rds_phy_modify_mmd(clock, MCHP_RDS_PTP_TX_MOD,
+ MCHP_RDS_PTP_PORT,
+ MCHP_RDS_TX_MOD_PTP_SYNC_TS_INSERT,
+ MCHP_RDS_TX_MOD_PTP_SYNC_TS_INSERT);
+ else
+ rc = mchp_rds_phy_modify_mmd(clock, MCHP_RDS_PTP_TX_MOD,
+ MCHP_RDS_PTP_PORT,
+ MCHP_RDS_TX_MOD_PTP_SYNC_TS_INSERT,
+ (u16)~MCHP_RDS_TX_MOD_PTP_SYNC_TS_INSERT);
+
+ if (rc < 0)
+ return rc;
+
+ /* In case of multiple starts and stops, these needs to be cleared */
+ spin_lock_irqsave(&clock->rx_ts_lock, flags);
+ list_for_each_entry_safe(rx_ts, tmp, &clock->rx_ts_list, list) {
+ list_del(&rx_ts->list);
+ kfree(rx_ts);
+ }
+ spin_unlock_irqrestore(&clock->rx_ts_lock, flags);
+
+ rc = mchp_rds_ptp_flush_fifo(clock, MCHP_RDS_PTP_INGRESS_FIFO);
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_ptp_flush_fifo(clock, MCHP_RDS_PTP_EGRESS_FIFO);
+ if (rc < 0)
+ return rc;
+
+ /* Now enable the timestamping interrupts */
+ rc = mchp_rds_ptp_config_intr(clock,
+ config->rx_filter != HWTSTAMP_FILTER_NONE);
+
+ return rc < 0 ? rc : 0;
+}
+
+static int mchp_rds_ptp_ts_info(struct mii_timestamper *mii_ts,
+ struct kernel_ethtool_ts_info *info)
+{
+ struct mchp_rds_ptp_clock *clock = container_of(mii_ts,
+ struct mchp_rds_ptp_clock,
+ mii_ts);
+
+ info->phc_index = ptp_clock_index(clock->ptp_clock);
+
+ info->so_timestamping = SOF_TIMESTAMPING_TX_HARDWARE |
+ SOF_TIMESTAMPING_RX_HARDWARE |
+ SOF_TIMESTAMPING_RAW_HARDWARE;
+
+ info->tx_types = BIT(HWTSTAMP_TX_OFF) | BIT(HWTSTAMP_TX_ON) |
+ BIT(HWTSTAMP_TX_ONESTEP_SYNC);
+
+ info->rx_filters = BIT(HWTSTAMP_FILTER_NONE) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L4_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
+ BIT(HWTSTAMP_FILTER_PTP_V2_EVENT);
+
+ return 0;
+}
+
+static int mchp_rds_ptp_ltc_adjtime(struct ptp_clock_info *info, s64 delta)
+{
+ struct mchp_rds_ptp_clock *clock = container_of(info,
+ struct mchp_rds_ptp_clock,
+ caps);
+ struct timespec64 ts;
+ bool add = true;
+ int rc = 0;
+ u32 nsec;
+ s32 sec;
+
+ /* The HW allows up to 15 sec to adjust the time, but here we limit to
+ * 10 sec the adjustment. The reason is, in case the adjustment is 14
+ * sec and 999999999 nsec, then we add 8ns to compensate the actual
+ * increment so the value can be bigger than 15 sec. Therefore limit the
+ * possible adjustments so we will not have these corner cases
+ */
+ if (delta > 10000000000LL || delta < -10000000000LL) {
+ /* The timeadjustment is too big, so fall back using set time */
+ u64 now;
+
+ info->gettime64(info, &ts);
+
+ now = ktime_to_ns(timespec64_to_ktime(ts));
+ ts = ns_to_timespec64(now + delta);
+
+ info->settime64(info, &ts);
+ return 0;
+ }
+ sec = div_u64_rem(abs(delta), NSEC_PER_SEC, &nsec);
+ if (delta < 0 && nsec != 0) {
+ /* It is not allowed to adjust low the nsec part, therefore
+ * subtract more from second part and add to nanosecond such
+ * that would roll over, so the second part will increase
+ */
+ sec--;
+ nsec = NSEC_PER_SEC - nsec;
+ }
+
+ /* Calculate the adjustments and the direction */
+ if (delta < 0)
+ add = false;
+
+ if (nsec > 0) {
+ /* add 8 ns to cover the likely normal increment */
+ nsec += 8;
+
+ if (nsec >= NSEC_PER_SEC) {
+ /* carry into seconds */
+ sec++;
+ nsec -= NSEC_PER_SEC;
+ }
+ }
+
+ mutex_lock(&clock->ptp_lock);
+ if (sec) {
+ sec = abs(sec);
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_STEP_ADJ_LO,
+ MCHP_RDS_PTP_CLOCK, sec);
+ if (rc < 0)
+ goto out_unlock;
+
+ rc = mchp_rds_phy_set_bits_mmd(clock, MCHP_RDS_PTP_STEP_ADJ_HI,
+ MCHP_RDS_PTP_CLOCK,
+ ((add ?
+ MCHP_RDS_PTP_STEP_ADJ_HI_DIR :
+ 0) | ((sec >> 16) &
+ GENMASK(13, 0))));
+ if (rc < 0)
+ goto out_unlock;
+
+ rc = mchp_rds_phy_set_bits_mmd(clock, MCHP_RDS_PTP_CMD_CTL,
+ MCHP_RDS_PTP_CLOCK,
+ MCHP_RDS_PTP_CMD_CTL_LTC_STEP_SEC);
+ if (rc < 0)
+ goto out_unlock;
+ }
+
+ if (nsec) {
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_STEP_ADJ_LO,
+ MCHP_RDS_PTP_CLOCK,
+ nsec & GENMASK(15, 0));
+ if (rc < 0)
+ goto out_unlock;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_STEP_ADJ_HI,
+ MCHP_RDS_PTP_CLOCK,
+ (nsec >> 16) & GENMASK(13, 0));
+ if (rc < 0)
+ goto out_unlock;
+
+ rc = mchp_rds_phy_set_bits_mmd(clock, MCHP_RDS_PTP_CMD_CTL,
+ MCHP_RDS_PTP_CLOCK,
+ MCHP_RDS_PTP_CMD_CTL_LTC_STEP_NSEC);
+ }
+
+out_unlock:
+ mutex_unlock(&clock->ptp_lock);
+
+ return rc;
+}
+
+static int mchp_rds_ptp_ltc_adjfine(struct ptp_clock_info *info,
+ long scaled_ppm)
+{
+ struct mchp_rds_ptp_clock *clock = container_of(info,
+ struct mchp_rds_ptp_clock,
+ caps);
+ u16 rate_lo, rate_hi;
+ bool faster = true;
+ u32 rate;
+ int rc;
+
+ if (!scaled_ppm)
+ return 0;
+
+ if (scaled_ppm < 0) {
+ scaled_ppm = -scaled_ppm;
+ faster = false;
+ }
+
+ rate = MCHP_RDS_PTP_1PPM_FORMAT * (upper_16_bits(scaled_ppm));
+ rate += (MCHP_RDS_PTP_1PPM_FORMAT * (lower_16_bits(scaled_ppm))) >> 16;
+
+ rate_lo = rate & GENMASK(15, 0);
+ rate_hi = (rate >> 16) & GENMASK(13, 0);
+
+ if (faster)
+ rate_hi |= MCHP_RDS_PTP_LTC_RATE_ADJ_HI_DIR;
+
+ mutex_lock(&clock->ptp_lock);
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_LTC_RATE_ADJ_HI,
+ MCHP_RDS_PTP_CLOCK, rate_hi);
+ if (rc < 0)
+ goto error;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_LTC_RATE_ADJ_LO,
+ MCHP_RDS_PTP_CLOCK, rate_lo);
+ if (rc > 0)
+ rc = 0;
+error:
+ mutex_unlock(&clock->ptp_lock);
+
+ return rc;
+}
+
+static int mchp_rds_ptp_ltc_gettime64(struct ptp_clock_info *info,
+ struct timespec64 *ts)
+{
+ struct mchp_rds_ptp_clock *clock = container_of(info,
+ struct mchp_rds_ptp_clock,
+ caps);
+ time64_t secs;
+ int rc = 0;
+ s64 nsecs;
+
+ mutex_lock(&clock->ptp_lock);
+ /* Set read bit to 1 to save current values of 1588 local time counter
+ * into PTP LTC seconds and nanoseconds registers.
+ */
+ rc = mchp_rds_phy_set_bits_mmd(clock, MCHP_RDS_PTP_CMD_CTL,
+ MCHP_RDS_PTP_CLOCK,
+ MCHP_RDS_PTP_CMD_CTL_CLOCK_READ);
+ if (rc < 0)
+ goto out_unlock;
+
+ /* Get LTC clock values */
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_LTC_READ_SEC_HI,
+ MCHP_RDS_PTP_CLOCK);
+ if (rc < 0)
+ goto out_unlock;
+ secs = rc << 16;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_LTC_READ_SEC_MID,
+ MCHP_RDS_PTP_CLOCK);
+ if (rc < 0)
+ goto out_unlock;
+ secs |= rc;
+ secs <<= 16;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_LTC_READ_SEC_LO,
+ MCHP_RDS_PTP_CLOCK);
+ if (rc < 0)
+ goto out_unlock;
+ secs |= rc;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_LTC_READ_NS_HI,
+ MCHP_RDS_PTP_CLOCK);
+ if (rc < 0)
+ goto out_unlock;
+ nsecs = (rc & GENMASK(13, 0));
+ nsecs <<= 16;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_LTC_READ_NS_LO,
+ MCHP_RDS_PTP_CLOCK);
+ if (rc < 0)
+ goto out_unlock;
+ nsecs |= rc;
+
+ set_normalized_timespec64(ts, secs, nsecs);
+
+ if (rc > 0)
+ rc = 0;
+out_unlock:
+ mutex_unlock(&clock->ptp_lock);
+
+ return rc;
+}
+
+static int mchp_rds_ptp_ltc_settime64(struct ptp_clock_info *info,
+ const struct timespec64 *ts)
+{
+ struct mchp_rds_ptp_clock *clock = container_of(info,
+ struct mchp_rds_ptp_clock,
+ caps);
+ int rc;
+
+ mutex_lock(&clock->ptp_lock);
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_LTC_SEC_LO,
+ MCHP_RDS_PTP_CLOCK,
+ lower_16_bits(ts->tv_sec));
+ if (rc < 0)
+ goto out_unlock;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_LTC_SEC_MID,
+ MCHP_RDS_PTP_CLOCK,
+ upper_16_bits(ts->tv_sec));
+ if (rc < 0)
+ goto out_unlock;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_LTC_SEC_HI,
+ MCHP_RDS_PTP_CLOCK,
+ upper_32_bits(ts->tv_sec) & GENMASK(15, 0));
+ if (rc < 0)
+ goto out_unlock;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_LTC_NS_LO,
+ MCHP_RDS_PTP_CLOCK,
+ lower_16_bits(ts->tv_nsec));
+ if (rc < 0)
+ goto out_unlock;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_LTC_NS_HI,
+ MCHP_RDS_PTP_CLOCK,
+ upper_16_bits(ts->tv_nsec) & GENMASK(13, 0));
+ if (rc < 0)
+ goto out_unlock;
+
+ /* Set load bit to 1 to write PTP LTC seconds and nanoseconds
+ * registers to 1588 local time counter.
+ */
+ rc = mchp_rds_phy_set_bits_mmd(clock, MCHP_RDS_PTP_CMD_CTL,
+ MCHP_RDS_PTP_CLOCK,
+ MCHP_RDS_PTP_CMD_CTL_CLOCK_LOAD);
+ if (rc > 0)
+ rc = 0;
+out_unlock:
+ mutex_unlock(&clock->ptp_lock);
+
+ return rc;
+}
+
+static bool mchp_rds_ptp_get_sig_tx(struct sk_buff *skb, u16 *sig)
+{
+ struct ptp_header *ptp_header;
+ int type;
+
+ type = ptp_classify_raw(skb);
+ if (type == PTP_CLASS_NONE)
+ return false;
+
+ ptp_header = ptp_parse_header(skb, type);
+ if (!ptp_header)
+ return false;
+
+ *sig = (__force u16)(ntohs(ptp_header->sequence_id));
+
+ return true;
+}
+
+static void mchp_rds_ptp_match_tx_skb(struct mchp_rds_ptp_clock *clock,
+ u32 seconds, u32 nsec, u16 seq_id)
+{
+ struct skb_shared_hwtstamps shhwtstamps;
+ struct sk_buff *skb, *skb_tmp;
+ unsigned long flags;
+ bool rc = false;
+ u16 skb_sig;
+
+ spin_lock_irqsave(&clock->tx_queue.lock, flags);
+ skb_queue_walk_safe(&clock->tx_queue, skb, skb_tmp) {
+ if (!mchp_rds_ptp_get_sig_tx(skb, &skb_sig))
+ continue;
+
+ if (skb_sig != seq_id)
+ continue;
+
+ __skb_unlink(skb, &clock->tx_queue);
+ rc = true;
+ break;
+ }
+ spin_unlock_irqrestore(&clock->tx_queue.lock, flags);
+
+ if (rc) {
+ shhwtstamps.hwtstamp = ktime_set(seconds, nsec);
+ skb_complete_tx_timestamp(skb, &shhwtstamps);
+ }
+}
+
+static struct mchp_rds_ptp_rx_ts
+ *mchp_rds_ptp_get_rx_ts(struct mchp_rds_ptp_clock *clock)
+{
+ struct phy_device *phydev = clock->phydev;
+ struct mchp_rds_ptp_rx_ts *rx_ts = NULL;
+ u32 sec, nsec;
+ int rc;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_RX_INGRESS_NS_HI,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ goto error;
+ if (!(rc & MCHP_RDS_PTP_RX_INGRESS_NS_HI_TS_VALID)) {
+ phydev_err(phydev, "RX Timestamp is not valid!\n");
+ goto error;
+ }
+ nsec = (rc & GENMASK(13, 0)) << 16;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_RX_INGRESS_NS_LO,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ goto error;
+ nsec |= rc;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_RX_INGRESS_SEC_HI,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ goto error;
+ sec = rc << 16;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_RX_INGRESS_SEC_LO,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ goto error;
+ sec |= rc;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_RX_MSG_HDR2,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ goto error;
+
+ rx_ts = kmalloc(sizeof(*rx_ts), GFP_KERNEL);
+ if (!rx_ts)
+ return NULL;
+
+ rx_ts->seconds = sec;
+ rx_ts->nsec = nsec;
+ rx_ts->seq_id = rc;
+
+error:
+ return rx_ts;
+}
+
+static void mchp_rds_ptp_process_rx_ts(struct mchp_rds_ptp_clock *clock)
+{
+ int caps;
+
+ do {
+ struct mchp_rds_ptp_rx_ts *rx_ts;
+
+ rx_ts = mchp_rds_ptp_get_rx_ts(clock);
+ if (rx_ts)
+ mchp_rds_ptp_match_rx_ts(clock, rx_ts);
+
+ caps = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_CAP_INFO,
+ MCHP_RDS_PTP_PORT);
+ if (caps < 0)
+ return;
+ } while (MCHP_RDS_PTP_RX_TS_CNT(caps) > 0);
+}
+
+static bool mchp_rds_ptp_get_tx_ts(struct mchp_rds_ptp_clock *clock,
+ u32 *sec, u32 *nsec, u16 *seq)
+{
+ int rc;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_TX_EGRESS_NS_HI,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ return false;
+ if (!(rc & MCHP_RDS_PTP_TX_EGRESS_NS_HI_TS_VALID))
+ return false;
+ *nsec = (rc & GENMASK(13, 0)) << 16;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_TX_EGRESS_NS_LO,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ return false;
+ *nsec = *nsec | rc;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_TX_EGRESS_SEC_HI,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ return false;
+ *sec = rc << 16;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_TX_EGRESS_SEC_LO,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ return false;
+ *sec = *sec | rc;
+
+ rc = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_TX_MSG_HDR2,
+ MCHP_RDS_PTP_PORT);
+ if (rc < 0)
+ return false;
+
+ *seq = rc;
+
+ return true;
+}
+
+static void mchp_rds_ptp_process_tx_ts(struct mchp_rds_ptp_clock *clock)
+{
+ int caps;
+
+ do {
+ u32 sec, nsec;
+ u16 seq;
+
+ if (mchp_rds_ptp_get_tx_ts(clock, &sec, &nsec, &seq))
+ mchp_rds_ptp_match_tx_skb(clock, sec, nsec, seq);
+
+ caps = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_CAP_INFO,
+ MCHP_RDS_PTP_PORT);
+ if (caps < 0)
+ return;
+ } while (MCHP_RDS_PTP_TX_TS_CNT(caps) > 0);
+}
+
+int mchp_rds_ptp_top_config_intr(struct mchp_rds_ptp_clock *clock,
+ u16 reg, u16 val, bool clear)
+{
+ if (clear)
+ return phy_clear_bits_mmd(clock->phydev, PTP_MMD(clock), reg,
+ val);
+ else
+ return phy_set_bits_mmd(clock->phydev, PTP_MMD(clock), reg,
+ val);
+}
+EXPORT_SYMBOL_GPL(mchp_rds_ptp_top_config_intr);
+
+irqreturn_t mchp_rds_ptp_handle_interrupt(struct mchp_rds_ptp_clock *clock)
+{
+ int irq_sts;
+
+ /* To handle rogue interrupt scenarios */
+ if (!clock)
+ return IRQ_NONE;
+
+ do {
+ irq_sts = mchp_rds_phy_read_mmd(clock, MCHP_RDS_PTP_INT_STS,
+ MCHP_RDS_PTP_PORT);
+ if (irq_sts < 0)
+ return IRQ_NONE;
+
+ if (irq_sts & MCHP_RDS_PTP_INT_RX_TS_EN)
+ mchp_rds_ptp_process_rx_ts(clock);
+
+ if (irq_sts & MCHP_RDS_PTP_INT_TX_TS_EN)
+ mchp_rds_ptp_process_tx_ts(clock);
+
+ if (irq_sts & MCHP_RDS_PTP_INT_TX_TS_OVRFL_EN)
+ mchp_rds_ptp_flush_fifo(clock,
+ MCHP_RDS_PTP_EGRESS_FIFO);
+
+ if (irq_sts & MCHP_RDS_PTP_INT_RX_TS_OVRFL_EN)
+ mchp_rds_ptp_flush_fifo(clock,
+ MCHP_RDS_PTP_INGRESS_FIFO);
+ } while (irq_sts & (MCHP_RDS_PTP_INT_RX_TS_EN |
+ MCHP_RDS_PTP_INT_TX_TS_EN |
+ MCHP_RDS_PTP_INT_TX_TS_OVRFL_EN |
+ MCHP_RDS_PTP_INT_RX_TS_OVRFL_EN));
+
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL_GPL(mchp_rds_ptp_handle_interrupt);
+
+static int mchp_rds_ptp_init(struct mchp_rds_ptp_clock *clock)
+{
+ int rc;
+
+ /* Disable PTP */
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_CMD_CTL,
+ MCHP_RDS_PTP_CLOCK,
+ MCHP_RDS_PTP_CMD_CTL_DIS);
+ if (rc < 0)
+ return rc;
+
+ /* Disable TSU */
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_TSU_GEN_CONFIG,
+ MCHP_RDS_PTP_PORT, 0);
+ if (rc < 0)
+ return rc;
+
+ /* Clear PTP interrupt status registers */
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_TSU_HARD_RESET,
+ MCHP_RDS_PTP_PORT,
+ MCHP_RDS_PTP_TSU_HARDRESET);
+ if (rc < 0)
+ return rc;
+
+ /* Predictor enable */
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_LATENCY_CORRECTION_CTL,
+ MCHP_RDS_PTP_CLOCK,
+ MCHP_RDS_PTP_LATENCY_SETTING);
+ if (rc < 0)
+ return rc;
+
+ /* Configure PTP operational mode */
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_OP_MODE,
+ MCHP_RDS_PTP_CLOCK,
+ MCHP_RDS_PTP_OP_MODE_STANDALONE);
+ if (rc < 0)
+ return rc;
+
+ /* Reference clock configuration */
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_REF_CLK_CFG,
+ MCHP_RDS_PTP_CLOCK,
+ MCHP_RDS_PTP_REF_CLK_CFG_SET);
+ if (rc < 0)
+ return rc;
+
+ /* Classifier configurations */
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_RX_PARSE_CONFIG,
+ MCHP_RDS_PTP_PORT, 0);
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_TX_PARSE_CONFIG,
+ MCHP_RDS_PTP_PORT, 0);
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_TX_PARSE_L2_ADDR_EN,
+ MCHP_RDS_PTP_PORT, 0);
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_RX_PARSE_L2_ADDR_EN,
+ MCHP_RDS_PTP_PORT, 0);
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_RX_PARSE_IPV4_ADDR_EN,
+ MCHP_RDS_PTP_PORT, 0);
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_TX_PARSE_IPV4_ADDR_EN,
+ MCHP_RDS_PTP_PORT, 0);
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_RX_VERSION,
+ MCHP_RDS_PTP_PORT,
+ MCHP_RDS_PTP_MAX_VERSION(0xff) |
+ MCHP_RDS_PTP_MIN_VERSION(0x0));
+ if (rc < 0)
+ return rc;
+
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_TX_VERSION,
+ MCHP_RDS_PTP_PORT,
+ MCHP_RDS_PTP_MAX_VERSION(0xff) |
+ MCHP_RDS_PTP_MIN_VERSION(0x0));
+ if (rc < 0)
+ return rc;
+
+ /* Enable TSU */
+ rc = mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_TSU_GEN_CONFIG,
+ MCHP_RDS_PTP_PORT,
+ MCHP_RDS_PTP_TSU_GEN_CFG_TSU_EN);
+ if (rc < 0)
+ return rc;
+
+ /* Enable PTP */
+ return mchp_rds_phy_write_mmd(clock, MCHP_RDS_PTP_CMD_CTL,
+ MCHP_RDS_PTP_CLOCK,
+ MCHP_RDS_PTP_CMD_CTL_EN);
+}
+
+struct mchp_rds_ptp_clock *mchp_rds_ptp_probe(struct phy_device *phydev, u8 mmd,
+ u16 clk_base_addr,
+ u16 port_base_addr)
+{
+ struct mchp_rds_ptp_clock *clock;
+ int rc;
+
+ clock = devm_kzalloc(&phydev->mdio.dev, sizeof(*clock), GFP_KERNEL);
+ if (!clock)
+ return ERR_PTR(-ENOMEM);
+
+ clock->port_base_addr = port_base_addr;
+ clock->clk_base_addr = clk_base_addr;
+ clock->mmd = mmd;
+
+ mutex_init(&clock->ptp_lock);
+ /* Register PTP clock */
+ clock->caps.owner = THIS_MODULE;
+ snprintf(clock->caps.name, 30, "%s", phydev->drv->name);
+ clock->caps.max_adj = MCHP_RDS_PTP_MAX_ADJ;
+ clock->caps.n_ext_ts = 0;
+ clock->caps.pps = 0;
+ clock->caps.adjfine = mchp_rds_ptp_ltc_adjfine;
+ clock->caps.adjtime = mchp_rds_ptp_ltc_adjtime;
+ clock->caps.gettime64 = mchp_rds_ptp_ltc_gettime64;
+ clock->caps.settime64 = mchp_rds_ptp_ltc_settime64;
+ clock->ptp_clock = ptp_clock_register(&clock->caps,
+ &phydev->mdio.dev);
+ if (IS_ERR(clock->ptp_clock))
+ return ERR_PTR(-EINVAL);
+
+ /* Check if PHC support is missing at the configuration level */
+ if (!clock->ptp_clock)
+ return NULL;
+
+ /* Initialize the SW */
+ skb_queue_head_init(&clock->tx_queue);
+ skb_queue_head_init(&clock->rx_queue);
+ INIT_LIST_HEAD(&clock->rx_ts_list);
+ spin_lock_init(&clock->rx_ts_lock);
+
+ clock->mii_ts.rxtstamp = mchp_rds_ptp_rxtstamp;
+ clock->mii_ts.txtstamp = mchp_rds_ptp_txtstamp;
+ clock->mii_ts.hwtstamp = mchp_rds_ptp_hwtstamp;
+ clock->mii_ts.ts_info = mchp_rds_ptp_ts_info;
+
+ phydev->mii_ts = &clock->mii_ts;
+
+ /* Timestamp selected by default to keep legacy API */
+ phydev->default_timestamp = true;
+
+ clock->phydev = phydev;
+
+ rc = mchp_rds_ptp_init(clock);
+ if (rc < 0)
+ return ERR_PTR(rc);
+
+ return clock;
+}
+EXPORT_SYMBOL_GPL(mchp_rds_ptp_probe);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("MICROCHIP PHY RDS PTP driver");
+MODULE_AUTHOR("Divya Koppera");
diff --git a/drivers/net/phy/microchip_rds_ptp.h b/drivers/net/phy/microchip_rds_ptp.h
new file mode 100644
index 000000000000..e95c065728b5
--- /dev/null
+++ b/drivers/net/phy/microchip_rds_ptp.h
@@ -0,0 +1,223 @@
+/* SPDX-License-Identifier: GPL-2.0
+ * Copyright (C) 2024 Microchip Technology
+ */
+
+#ifndef _MICROCHIP_RDS_PTP_H
+#define _MICROCHIP_RDS_PTP_H
+
+#include <linux/ptp_clock_kernel.h>
+#include <linux/ptp_clock.h>
+#include <linux/ptp_classify.h>
+#include <linux/net_tstamp.h>
+#include <linux/mii.h>
+#include <linux/phy.h>
+
+#define MCHP_RDS_PTP_CMD_CTL 0x0
+#define MCHP_RDS_PTP_CMD_CTL_LTC_STEP_NSEC BIT(6)
+#define MCHP_RDS_PTP_CMD_CTL_LTC_STEP_SEC BIT(5)
+#define MCHP_RDS_PTP_CMD_CTL_CLOCK_LOAD BIT(4)
+#define MCHP_RDS_PTP_CMD_CTL_CLOCK_READ BIT(3)
+#define MCHP_RDS_PTP_CMD_CTL_EN BIT(1)
+#define MCHP_RDS_PTP_CMD_CTL_DIS BIT(0)
+
+#define MCHP_RDS_PTP_REF_CLK_CFG 0x2
+#define MCHP_RDS_PTP_REF_CLK_SRC_250MHZ 0x0
+#define MCHP_RDS_PTP_REF_CLK_PERIOD_OVERRIDE BIT(9)
+#define MCHP_RDS_PTP_REF_CLK_PERIOD 4
+#define MCHP_RDS_PTP_REF_CLK_CFG_SET (MCHP_RDS_PTP_REF_CLK_SRC_250MHZ |\
+ MCHP_RDS_PTP_REF_CLK_PERIOD_OVERRIDE |\
+ MCHP_RDS_PTP_REF_CLK_PERIOD)
+
+#define MCHP_RDS_PTP_LTC_SEC_HI 0x5
+#define MCHP_RDS_PTP_LTC_SEC_MID 0x6
+#define MCHP_RDS_PTP_LTC_SEC_LO 0x7
+#define MCHP_RDS_PTP_LTC_NS_HI 0x8
+#define MCHP_RDS_PTP_LTC_NS_LO 0x9
+#define MCHP_RDS_PTP_LTC_RATE_ADJ_HI 0xc
+#define MCHP_RDS_PTP_LTC_RATE_ADJ_HI_DIR BIT(15)
+#define MCHP_RDS_PTP_LTC_RATE_ADJ_LO 0xd
+#define MCHP_RDS_PTP_STEP_ADJ_HI 0x12
+#define MCHP_RDS_PTP_STEP_ADJ_HI_DIR BIT(15)
+#define MCHP_RDS_PTP_STEP_ADJ_LO 0x13
+#define MCHP_RDS_PTP_LTC_READ_SEC_HI 0x29
+#define MCHP_RDS_PTP_LTC_READ_SEC_MID 0x2a
+#define MCHP_RDS_PTP_LTC_READ_SEC_LO 0x2b
+#define MCHP_RDS_PTP_LTC_READ_NS_HI 0x2c
+#define MCHP_RDS_PTP_LTC_READ_NS_LO 0x2d
+#define MCHP_RDS_PTP_OP_MODE 0x41
+#define MCHP_RDS_PTP_OP_MODE_DIS 0
+#define MCHP_RDS_PTP_OP_MODE_STANDALONE 1
+#define MCHP_RDS_PTP_LATENCY_CORRECTION_CTL 0x44
+#define MCHP_RDS_PTP_PREDICTOR_EN BIT(6)
+#define MCHP_RDS_PTP_TX_PRED_DIS BIT(1)
+#define MCHP_RDS_PTP_RX_PRED_DIS BIT(0)
+#define MCHP_RDS_PTP_LATENCY_SETTING (MCHP_RDS_PTP_PREDICTOR_EN | \
+ MCHP_RDS_PTP_TX_PRED_DIS | \
+ MCHP_RDS_PTP_RX_PRED_DIS)
+
+#define MCHP_RDS_PTP_INT_EN 0x0
+#define MCHP_RDS_PTP_INT_STS 0x01
+#define MCHP_RDS_PTP_INT_TX_TS_OVRFL_EN BIT(3)
+#define MCHP_RDS_PTP_INT_TX_TS_EN BIT(2)
+#define MCHP_RDS_PTP_INT_RX_TS_OVRFL_EN BIT(1)
+#define MCHP_RDS_PTP_INT_RX_TS_EN BIT(0)
+#define MCHP_RDS_PTP_INT_ALL_MSK (MCHP_RDS_PTP_INT_TX_TS_OVRFL_EN | \
+ MCHP_RDS_PTP_INT_TX_TS_EN | \
+ MCHP_RDS_PTP_INT_RX_TS_OVRFL_EN |\
+ MCHP_RDS_PTP_INT_RX_TS_EN)
+
+#define MCHP_RDS_PTP_CAP_INFO 0x2e
+#define MCHP_RDS_PTP_TX_TS_CNT(v) (((v) & GENMASK(11, 8)) >> 8)
+#define MCHP_RDS_PTP_RX_TS_CNT(v) ((v) & GENMASK(3, 0))
+
+#define MCHP_RDS_PTP_RX_PARSE_CONFIG 0x42
+#define MCHP_RDS_PTP_RX_PARSE_L2_ADDR_EN 0x44
+#define MCHP_RDS_PTP_RX_PARSE_IPV4_ADDR_EN 0x45
+
+#define MCHP_RDS_PTP_RX_TIMESTAMP_CONFIG 0x4e
+#define MCHP_RDS_PTP_RX_TIMESTAMP_CONFIG_PTP_FCS_DIS BIT(0)
+
+#define MCHP_RDS_PTP_RX_VERSION 0x48
+#define MCHP_RDS_PTP_RX_TIMESTAMP_EN 0x4d
+
+#define MCHP_RDS_PTP_RX_INGRESS_NS_HI 0x54
+#define MCHP_RDS_PTP_RX_INGRESS_NS_HI_TS_VALID BIT(15)
+
+#define MCHP_RDS_PTP_RX_INGRESS_NS_LO 0x55
+#define MCHP_RDS_PTP_RX_INGRESS_SEC_HI 0x56
+#define MCHP_RDS_PTP_RX_INGRESS_SEC_LO 0x57
+#define MCHP_RDS_PTP_RX_MSG_HDR2 0x59
+
+#define MCHP_RDS_PTP_TX_PARSE_CONFIG 0x82
+#define MCHP_RDS_PTP_PARSE_CONFIG_LAYER2_EN BIT(0)
+#define MCHP_RDS_PTP_PARSE_CONFIG_IPV4_EN BIT(1)
+#define MCHP_RDS_PTP_PARSE_CONFIG_IPV6_EN BIT(2)
+
+#define MCHP_RDS_PTP_TX_PARSE_L2_ADDR_EN 0x84
+#define MCHP_RDS_PTP_TX_PARSE_IPV4_ADDR_EN 0x85
+
+#define MCHP_RDS_PTP_TX_VERSION 0x88
+#define MCHP_RDS_PTP_MAX_VERSION(x) (((x) & GENMASK(7, 0)) << 8)
+#define MCHP_RDS_PTP_MIN_VERSION(x) ((x) & GENMASK(7, 0))
+
+#define MCHP_RDS_PTP_TX_TIMESTAMP_EN 0x8d
+#define MCHP_RDS_PTP_TIMESTAMP_EN_SYNC BIT(0)
+#define MCHP_RDS_PTP_TIMESTAMP_EN_DREQ BIT(1)
+#define MCHP_RDS_PTP_TIMESTAMP_EN_PDREQ BIT(2)
+#define MCHP_RDS_PTP_TIMESTAMP_EN_PDRES BIT(3)
+#define MCHP_RDS_PTP_TIMESTAMP_EN_ALL (MCHP_RDS_PTP_TIMESTAMP_EN_SYNC |\
+ MCHP_RDS_PTP_TIMESTAMP_EN_DREQ |\
+ MCHP_RDS_PTP_TIMESTAMP_EN_PDREQ |\
+ MCHP_RDS_PTP_TIMESTAMP_EN_PDRES)
+
+#define MCHP_RDS_PTP_TX_TIMESTAMP_CONFIG 0x8e
+#define MCHP_RDS_PTP_TX_TIMESTAMP_CONFIG_PTP_FCS_DIS BIT(0)
+
+#define MCHP_RDS_PTP_TX_MOD 0x8f
+#define MCHP_RDS_TX_MOD_PTP_SYNC_TS_INSERT BIT(12)
+
+#define MCHP_RDS_PTP_TX_EGRESS_NS_HI 0x94
+#define MCHP_RDS_PTP_TX_EGRESS_NS_HI_TS_VALID BIT(15)
+
+#define MCHP_RDS_PTP_TX_EGRESS_NS_LO 0x95
+#define MCHP_RDS_PTP_TX_EGRESS_SEC_HI 0x96
+#define MCHP_RDS_PTP_TX_EGRESS_SEC_LO 0x97
+#define MCHP_RDS_PTP_TX_MSG_HDR2 0x99
+
+#define MCHP_RDS_PTP_TSU_GEN_CONFIG 0xc0
+#define MCHP_RDS_PTP_TSU_GEN_CFG_TSU_EN BIT(0)
+
+#define MCHP_RDS_PTP_TSU_HARD_RESET 0xc1
+#define MCHP_RDS_PTP_TSU_HARDRESET BIT(0)
+
+/* Represents 1ppm adjustment in 2^32 format with
+ * each nsec contains 4 clock cycles in 250MHz.
+ * The value is calculated as following: (1/1000000)/((2^-32)/4)
+ */
+#define MCHP_RDS_PTP_1PPM_FORMAT 17179
+#define MCHP_RDS_PTP_FIFO_SIZE 8
+#define MCHP_RDS_PTP_MAX_ADJ 31249999
+
+#define BASE_CLK(p) ((p)->clk_base_addr)
+#define BASE_PORT(p) ((p)->port_base_addr)
+#define PTP_MMD(p) ((p)->mmd)
+
+enum mchp_rds_ptp_base {
+ MCHP_RDS_PTP_PORT,
+ MCHP_RDS_PTP_CLOCK
+};
+
+enum mchp_rds_ptp_fifo_dir {
+ MCHP_RDS_PTP_INGRESS_FIFO,
+ MCHP_RDS_PTP_EGRESS_FIFO
+};
+
+struct mchp_rds_ptp_clock {
+ struct mii_timestamper mii_ts;
+ struct phy_device *phydev;
+ struct ptp_clock *ptp_clock;
+
+ struct sk_buff_head tx_queue;
+ struct sk_buff_head rx_queue;
+ struct list_head rx_ts_list;
+
+ struct ptp_clock_info caps;
+
+ /* Lock for Rx ts fifo */
+ spinlock_t rx_ts_lock;
+ int hwts_tx_type;
+
+ enum hwtstamp_rx_filters rx_filter;
+ int layer;
+ int version;
+ u16 port_base_addr;
+ u16 clk_base_addr;
+
+ /* Lock for phc */
+ struct mutex ptp_lock;
+ u8 mmd;
+};
+
+struct mchp_rds_ptp_rx_ts {
+ struct list_head list;
+ u32 seconds;
+ u32 nsec;
+ u16 seq_id;
+};
+
+#if IS_ENABLED(CONFIG_MICROCHIP_PHY_RDS_PTP)
+
+struct mchp_rds_ptp_clock *mchp_rds_ptp_probe(struct phy_device *phydev, u8 mmd,
+ u16 clk_base, u16 port_base);
+
+int mchp_rds_ptp_top_config_intr(struct mchp_rds_ptp_clock *clock,
+ u16 reg, u16 val, bool enable);
+
+irqreturn_t mchp_rds_ptp_handle_interrupt(struct mchp_rds_ptp_clock *clock);
+
+#else
+
+static inline struct mchp_rds_ptp_clock *mchp_rds_ptp_probe(struct phy_device
+ *phydev, u8 mmd,
+ u16 clk_base,
+ u16 port_base)
+{
+ return NULL;
+}
+
+static inline int mchp_rds_ptp_top_config_intr(struct mchp_rds_ptp_clock *clock,
+ u16 reg, u16 val, bool enable)
+{
+ return 0;
+}
+
+static inline irqreturn_t mchp_rds_ptp_handle_interrupt(struct
+ mchp_rds_ptp_clock
+ * clock)
+{
+ return IRQ_NONE;
+}
+
+#endif //CONFIG_MICROCHIP_PHY_RDS_PTP
+
+#endif //_MICROCHIP_RDS_PTP_H
diff --git a/drivers/net/phy/microchip_t1.c b/drivers/net/phy/microchip_t1.c
index b17bf6708003..73f28463bc35 100644
--- a/drivers/net/phy/microchip_t1.c
+++ b/drivers/net/phy/microchip_t1.c
@@ -10,11 +10,15 @@
#include <linux/ethtool.h>
#include <linux/ethtool_netlink.h>
#include <linux/bitfield.h>
+#include "microchip_rds_ptp.h"
#define PHY_ID_LAN87XX 0x0007c150
#define PHY_ID_LAN937X 0x0007c180
#define PHY_ID_LAN887X 0x0007c1f0
+#define MCHP_RDS_PTP_LTC_BASE_ADDR 0xe000
+#define MCHP_RDS_PTP_PORT_BASE_ADDR (MCHP_RDS_PTP_LTC_BASE_ADDR + 0x800)
+
/* External Register Control Register */
#define LAN87XX_EXT_REG_CTL (0x14)
#define LAN87XX_EXT_REG_CTL_RD_CTL (0x1000)
@@ -229,6 +233,7 @@
#define LAN887X_INT_STS 0xf000
#define LAN887X_INT_MSK 0xf001
+#define LAN887X_INT_MSK_P1588_MOD_INT_MSK BIT(3)
#define LAN887X_INT_MSK_T1_PHY_INT_MSK BIT(2)
#define LAN887X_INT_MSK_LINK_UP_MSK BIT(1)
#define LAN887X_INT_MSK_LINK_DOWN_MSK BIT(0)
@@ -319,6 +324,8 @@ struct lan887x_regwr_map {
struct lan887x_priv {
u64 stats[ARRAY_SIZE(lan887x_hw_stats)];
+ struct mchp_rds_ptp_clock *clock;
+ bool init_done;
};
static int lan937x_dsp_workaround(struct phy_device *phydev, u16 ereg, u8 bank)
@@ -1269,8 +1276,19 @@ static int lan887x_get_features(struct phy_device *phydev)
static int lan887x_phy_init(struct phy_device *phydev)
{
+ struct lan887x_priv *priv = phydev->priv;
int ret;
+ if (!priv->init_done && phy_interrupt_is_valid(phydev)) {
+ priv->clock = mchp_rds_ptp_probe(phydev, MDIO_MMD_VEND1,
+ MCHP_RDS_PTP_LTC_BASE_ADDR,
+ MCHP_RDS_PTP_PORT_BASE_ADDR);
+ if (IS_ERR(priv->clock))
+ return PTR_ERR(priv->clock);
+
+ priv->init_done = true;
+ }
+
/* Clear loopback */
ret = phy_clear_bits_mmd(phydev, MDIO_MMD_VEND1,
LAN887X_MIS_CFG_REG2,
@@ -1470,6 +1488,7 @@ static int lan887x_probe(struct phy_device *phydev)
if (!priv)
return -ENOMEM;
+ priv->init_done = false;
phydev->priv = priv;
return lan887x_phy_setup(phydev);
@@ -1518,6 +1537,7 @@ static void lan887x_get_strings(struct phy_device *phydev, u8 *data)
static int lan887x_config_intr(struct phy_device *phydev)
{
+ struct lan887x_priv *priv = phydev->priv;
int rc;
if (phydev->interrupts == PHY_INTERRUPT_ENABLED) {
@@ -1537,12 +1557,24 @@ static int lan887x_config_intr(struct phy_device *phydev)
rc = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_STS);
}
+ if (rc < 0)
+ return rc;
- return rc < 0 ? rc : 0;
+ if (phy_is_default_hwtstamp(phydev)) {
+ return mchp_rds_ptp_top_config_intr(priv->clock,
+ LAN887X_INT_MSK,
+ LAN887X_INT_MSK_P1588_MOD_INT_MSK,
+ (phydev->interrupts ==
+ PHY_INTERRUPT_ENABLED));
+ }
+
+ return 0;
}
static irqreturn_t lan887x_handle_interrupt(struct phy_device *phydev)
{
+ struct lan887x_priv *priv = phydev->priv;
+ int rc = IRQ_NONE;
int irq_status;
irq_status = phy_read_mmd(phydev, MDIO_MMD_VEND1, LAN887X_INT_STS);
@@ -1553,10 +1585,13 @@ static irqreturn_t lan887x_handle_interrupt(struct phy_device *phydev)
if (irq_status & LAN887X_MX_CHIP_TOP_LINK_MSK) {
phy_trigger_machine(phydev);
- return IRQ_HANDLED;
+ rc = IRQ_HANDLED;
}
- return IRQ_NONE;
+ if (irq_status & LAN887X_INT_MSK_P1588_MOD_INT_MSK)
+ rc = mchp_rds_ptp_handle_interrupt(priv->clock);
+
+ return rc;
}
static int lan887x_cd_reset(struct phy_device *phydev,
diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c
index db3c1f72b407..a8ccf257c109 100644
--- a/drivers/net/phy/mxl-gpy.c
+++ b/drivers/net/phy/mxl-gpy.c
@@ -1014,7 +1014,7 @@ static int gpy_led_polarity_set(struct phy_device *phydev, int index,
if (force_active_high)
return phy_clear_bits(phydev, PHY_LED, PHY_LED_POLARITY(index));
- unreachable();
+ return -EINVAL;
}
static struct phy_driver gpy_drivers[] = {
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 944ae98ad110..0dac08e85304 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -1469,18 +1469,17 @@ EXPORT_SYMBOL_GPL(genphy_c45_plca_get_status);
* @phydev: target phy_device struct
* @adv: variable to store advertised linkmodes
* @lp: variable to store LP advertised linkmodes
- * @is_enabled: variable to store EEE enabled/disabled configuration value
*
* Description: this function will read local and link partner PHY
* advertisements. Compare them return current EEE state.
*/
int genphy_c45_eee_is_active(struct phy_device *phydev, unsigned long *adv,
- unsigned long *lp, bool *is_enabled)
+ unsigned long *lp)
{
__ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_adv) = {};
__ETHTOOL_DECLARE_LINK_MODE_MASK(tmp_lp) = {};
__ETHTOOL_DECLARE_LINK_MODE_MASK(common);
- bool eee_enabled, eee_active;
+ bool eee_active;
int ret;
ret = genphy_c45_read_eee_adv(phydev, tmp_adv);
@@ -1491,9 +1490,8 @@ int genphy_c45_eee_is_active(struct phy_device *phydev, unsigned long *adv,
if (ret)
return ret;
- eee_enabled = !linkmode_empty(tmp_adv);
linkmode_and(common, tmp_adv, tmp_lp);
- if (eee_enabled && !linkmode_empty(common))
+ if (!linkmode_empty(tmp_adv) && !linkmode_empty(common))
eee_active = phy_check_valid(phydev->speed, phydev->duplex,
common);
else
@@ -1503,8 +1501,6 @@ int genphy_c45_eee_is_active(struct phy_device *phydev, unsigned long *adv,
linkmode_copy(adv, tmp_adv);
if (lp)
linkmode_copy(lp, tmp_lp);
- if (is_enabled)
- *is_enabled = eee_enabled;
return eee_active;
}
@@ -1521,15 +1517,13 @@ EXPORT_SYMBOL(genphy_c45_eee_is_active);
int genphy_c45_ethtool_get_eee(struct phy_device *phydev,
struct ethtool_keee *data)
{
- bool is_enabled;
int ret;
ret = genphy_c45_eee_is_active(phydev, data->advertised,
- data->lp_advertised, &is_enabled);
+ data->lp_advertised);
if (ret < 0)
return ret;
- data->eee_enabled = is_enabled;
data->eee_active = phydev->eee_active;
linkmode_copy(data->supported, phydev->supported_eee);
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index 0c228aa18019..e4b04cdaa995 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -988,8 +988,7 @@ static int phy_check_link_status(struct phy_device *phydev)
if (phydev->link && phydev->state != PHY_RUNNING) {
phy_check_downshift(phydev);
phydev->state = PHY_RUNNING;
- err = genphy_c45_eee_is_active(phydev,
- NULL, NULL, NULL);
+ err = genphy_c45_eee_is_active(phydev, NULL, NULL);
phydev->eee_active = err > 0;
phydev->enable_tx_lpi = phydev->eee_cfg.tx_lpi_enabled &&
phydev->eee_active;
@@ -1658,7 +1657,7 @@ int phy_init_eee(struct phy_device *phydev, bool clk_stop_enable)
if (!phydev->drv)
return -EIO;
- ret = genphy_c45_eee_is_active(phydev, NULL, NULL, NULL);
+ ret = genphy_c45_eee_is_active(phydev, NULL, NULL);
if (ret < 0)
return ret;
if (!ret)
@@ -1702,8 +1701,8 @@ EXPORT_SYMBOL(phy_get_eee_err);
* @phydev: target phy_device struct
* @data: ethtool_keee data
*
- * Description: reports the Supported/Advertisement/LP Advertisement
- * capabilities, etc.
+ * Description: get the current EEE settings, filling in all members of
+ * @data.
*/
int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_keee *data)
{
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index b26bb33cd1d4..bdc997f59779 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -32,6 +32,7 @@
#include <linux/phy_link_topology.h>
#include <linux/pse-pd/pse.h>
#include <linux/property.h>
+#include <linux/ptp_clock_kernel.h>
#include <linux/rtnetlink.h>
#include <linux/sfp.h>
#include <linux/skbuff.h>
@@ -1998,6 +1999,15 @@ void phy_detach(struct phy_device *phydev)
phy_suspend(phydev);
if (dev) {
+ struct hwtstamp_provider *hwprov;
+
+ hwprov = rtnl_dereference(dev->hwprov);
+ /* Disable timestamp if it is the one selected */
+ if (hwprov && hwprov->phydev == phydev) {
+ rcu_assign_pointer(dev->hwprov, NULL);
+ kfree_rcu(hwprov, rcu_head);
+ }
+
phydev->attached_dev->phydev = NULL;
phydev->attached_dev = NULL;
phy_link_topo_del_phy(dev, phydev);
@@ -2994,6 +3004,23 @@ void phy_support_eee(struct phy_device *phydev)
EXPORT_SYMBOL(phy_support_eee);
/**
+ * phy_disable_eee - Disable EEE for the PHY
+ * @phydev: Target phy_device struct
+ *
+ * This function is used by MAC drivers for MAC's which don't support EEE.
+ * It disables EEE on the PHY layer.
+ */
+void phy_disable_eee(struct phy_device *phydev)
+{
+ linkmode_zero(phydev->advertising_eee);
+ phydev->eee_cfg.tx_lpi_enabled = false;
+ phydev->eee_cfg.eee_enabled = false;
+ /* don't let userspace re-enable EEE advertisement */
+ linkmode_fill(phydev->eee_broken_modes);
+}
+EXPORT_SYMBOL_GPL(phy_disable_eee);
+
+/**
* phy_support_sym_pause - Enable support of symmetrical pause
* @phydev: target phy_device struct
*
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 95fbc363f9a6..31754d5fd659 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -691,6 +691,17 @@ static int phylink_validate_mac_and_pcs(struct phylink *pl,
return -EINVAL;
}
+ /* Ensure that this PCS supports the interface which the MAC
+ * returned it for. It is an error for the MAC to return a PCS
+ * that does not support the interface mode.
+ */
+ if (!phy_interface_empty(pcs->supported_interfaces) &&
+ !test_bit(state->interface, pcs->supported_interfaces)) {
+ phylink_err(pl, "MAC returned PCS which does not support %s\n",
+ phy_modes(state->interface));
+ return -EINVAL;
+ }
+
/* Validate the link parameters with the PCS */
if (pcs->ops->pcs_validate) {
ret = pcs->ops->pcs_validate(pcs, supported, state);
@@ -3623,6 +3634,13 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
{
struct phylink *pl = upstream;
+ if (!phy->drv) {
+ phylink_err(pl, "PHY %s (id 0x%.8lx) has no driver loaded\n",
+ phydev_name(phy), (unsigned long)phy->phy_id);
+ phylink_err(pl, "Drivers which handle known common cases: CONFIG_BCM84881_PHY, CONFIG_MARVELL_PHY\n");
+ return -EINVAL;
+ }
+
/*
* This is the new way of dealing with flow control for PHYs,
* as described by Timur Tabi in commit 529ed1275263 ("net: phy:
diff --git a/drivers/net/phy/spi_ks8995.c b/drivers/net/phy/spi_ks8995.c
index 7196e927c2cd..076a370be849 100644
--- a/drivers/net/phy/spi_ks8995.c
+++ b/drivers/net/phy/spi_ks8995.c
@@ -289,7 +289,7 @@ static int ks8995_reset(struct ks8995_switch *ks)
}
static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
+ const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
{
struct device *dev;
struct ks8995_switch *ks8995;
@@ -301,7 +301,7 @@ static ssize_t ks8995_registers_read(struct file *filp, struct kobject *kobj,
}
static ssize_t ks8995_registers_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
+ const struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
{
struct device *dev;
struct ks8995_switch *ks8995;
@@ -401,8 +401,8 @@ static const struct bin_attribute ks8995_registers_attr = {
.mode = 0600,
},
.size = KS8995_REGS_SIZE,
- .read = ks8995_registers_read,
- .write = ks8995_registers_write,
+ .read_new = ks8995_registers_read,
+ .write_new = ks8995_registers_write,
};
/* ------------------------------------------------------------------------ */
diff --git a/drivers/net/pse-pd/tps23881.c b/drivers/net/pse-pd/tps23881.c
index 5c4e88be46ee..8797ca1a8a21 100644
--- a/drivers/net/pse-pd/tps23881.c
+++ b/drivers/net/pse-pd/tps23881.c
@@ -64,15 +64,11 @@ static int tps23881_pi_enable(struct pse_controller_dev *pcdev, int id)
if (id >= TPS23881_MAX_CHANS)
return -ERANGE;
- ret = i2c_smbus_read_word_data(client, TPS23881_REG_PW_STATUS);
- if (ret < 0)
- return ret;
-
chan = priv->port[id].chan[0];
if (chan < 4)
- val = (u16)(ret | BIT(chan));
+ val = BIT(chan);
else
- val = (u16)(ret | BIT(chan + 4));
+ val = BIT(chan + 4);
if (priv->port[id].is_4p) {
chan = priv->port[id].chan[1];
@@ -100,15 +96,11 @@ static int tps23881_pi_disable(struct pse_controller_dev *pcdev, int id)
if (id >= TPS23881_MAX_CHANS)
return -ERANGE;
- ret = i2c_smbus_read_word_data(client, TPS23881_REG_PW_STATUS);
- if (ret < 0)
- return ret;
-
chan = priv->port[id].chan[0];
if (chan < 4)
- val = (u16)(ret | BIT(chan + 4));
+ val = BIT(chan + 4);
else
- val = (u16)(ret | BIT(chan + 8));
+ val = BIT(chan + 8);
if (priv->port[id].is_4p) {
chan = priv->port[id].chan[1];
diff --git a/drivers/net/tap.c b/drivers/net/tap.c
index 5aa41d5f7765..5ca6ecf0ce5f 100644
--- a/drivers/net/tap.c
+++ b/drivers/net/tap.c
@@ -1329,9 +1329,9 @@ int tap_queue_resize(struct tap_dev *tap)
list_for_each_entry(q, &tap->queue_list, next)
rings[i++] = &q->ring;
- ret = ptr_ring_resize_multiple(rings, n,
- dev->tx_queue_len, GFP_KERNEL,
- __skb_array_destroy_skb);
+ ret = ptr_ring_resize_multiple_bh(rings, n,
+ dev->tx_queue_len, GFP_KERNEL,
+ __skb_array_destroy_skb);
kfree(rings);
return ret;
diff --git a/drivers/net/team/team_core.c b/drivers/net/team/team_core.c
index a1b27b69f010..dc7cbd6a9798 100644
--- a/drivers/net/team/team_core.c
+++ b/drivers/net/team/team_core.c
@@ -983,7 +983,8 @@ static void team_port_disable(struct team *team,
#define TEAM_VLAN_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
NETIF_F_FRAGLIST | NETIF_F_GSO_SOFTWARE | \
- NETIF_F_HIGHDMA | NETIF_F_LRO)
+ NETIF_F_HIGHDMA | NETIF_F_LRO | \
+ NETIF_F_GSO_ENCAP_ALL)
#define TEAM_ENC_FEATURES (NETIF_F_HW_CSUM | NETIF_F_SG | \
NETIF_F_RXCSUM | NETIF_F_GSO_SOFTWARE)
@@ -991,14 +992,19 @@ static void team_port_disable(struct team *team,
static void __team_compute_features(struct team *team)
{
struct team_port *port;
- netdev_features_t vlan_features = TEAM_VLAN_FEATURES &
- NETIF_F_ALL_FOR_ALL;
+ netdev_features_t vlan_features = TEAM_VLAN_FEATURES;
netdev_features_t enc_features = TEAM_ENC_FEATURES;
unsigned short max_hard_header_len = ETH_HLEN;
unsigned int dst_release_flag = IFF_XMIT_DST_RELEASE |
IFF_XMIT_DST_RELEASE_PERM;
rcu_read_lock();
+ if (list_empty(&team->port_list))
+ goto done;
+
+ vlan_features = netdev_base_features(vlan_features);
+ enc_features = netdev_base_features(enc_features);
+
list_for_each_entry_rcu(port, &team->port_list, list) {
vlan_features = netdev_increment_features(vlan_features,
port->dev->vlan_features,
@@ -1008,11 +1014,11 @@ static void __team_compute_features(struct team *team)
port->dev->hw_enc_features,
TEAM_ENC_FEATURES);
-
dst_release_flag &= port->dev->priv_flags;
if (port->dev->hard_header_len > max_hard_header_len)
max_hard_header_len = port->dev->hard_header_len;
}
+done:
rcu_read_unlock();
team->dev->vlan_features = vlan_features;
@@ -1169,6 +1175,13 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
return -EBUSY;
}
+ if (netdev_has_upper_dev(port_dev, dev)) {
+ NL_SET_ERR_MSG(extack, "Device is already a lower device of the team interface");
+ netdev_err(dev, "Device %s is already a lower device of the team interface\n",
+ portname);
+ return -EBUSY;
+ }
+
if (port_dev->features & NETIF_F_VLAN_CHALLENGED &&
vlan_uses_dev(dev)) {
NL_SET_ERR_MSG(extack, "Device is VLAN challenged and team device has VLAN set up");
@@ -2011,8 +2024,7 @@ static netdev_features_t team_fix_features(struct net_device *dev,
netdev_features_t mask;
mask = features;
- features &= ~NETIF_F_ONE_FOR_ALL;
- features |= NETIF_F_ALL_FOR_ALL;
+ features = netdev_base_features(features);
rcu_read_lock();
list_for_each_entry_rcu(port, &team->port_list, list) {
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index d7a865ef370b..28624cca91f8 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -574,14 +574,18 @@ static u16 tun_select_queue(struct net_device *dev, struct sk_buff *skb,
return ret;
}
-static inline bool tun_not_capable(struct tun_struct *tun)
+static inline bool tun_capable(struct tun_struct *tun)
{
const struct cred *cred = current_cred();
struct net *net = dev_net(tun->dev);
- return ((uid_valid(tun->owner) && !uid_eq(cred->euid, tun->owner)) ||
- (gid_valid(tun->group) && !in_egroup_p(tun->group))) &&
- !ns_capable(net->user_ns, CAP_NET_ADMIN);
+ if (ns_capable(net->user_ns, CAP_NET_ADMIN))
+ return 1;
+ if (uid_valid(tun->owner) && uid_eq(cred->euid, tun->owner))
+ return 1;
+ if (gid_valid(tun->group) && in_egroup_p(tun->group))
+ return 1;
+ return 0;
}
static void tun_set_real_num_queues(struct tun_struct *tun)
@@ -1481,7 +1485,7 @@ static struct sk_buff *tun_napi_alloc_frags(struct tun_file *tfile,
skb->truesize += skb->data_len;
for (i = 1; i < it->nr_segs; i++) {
- const struct iovec *iov = iter_iov(it);
+ const struct iovec *iov = iter_iov(it) + i;
size_t fragsz = iov->iov_len;
struct page *page;
void *frag;
@@ -2778,7 +2782,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
!!(tun->flags & IFF_MULTI_QUEUE))
return -EINVAL;
- if (tun_not_capable(tun))
+ if (!tun_capable(tun))
return -EPERM;
err = security_tun_dev_open(tun->security);
if (err < 0)
@@ -3697,9 +3701,9 @@ static int tun_queue_resize(struct tun_struct *tun)
list_for_each_entry(tfile, &tun->disabled, next)
rings[i++] = &tfile->tx_ring;
- ret = ptr_ring_resize_multiple(rings, n,
- dev->tx_queue_len, GFP_KERNEL,
- tun_ptr_free);
+ ret = ptr_ring_resize_multiple_bh(rings, n,
+ dev->tx_queue_len, GFP_KERNEL,
+ tun_ptr_free);
kfree(rings);
return ret;
diff --git a/drivers/net/usb/lan78xx.c b/drivers/net/usb/lan78xx.c
index 531b1b6a37d1..a91bf9c7e31d 100644
--- a/drivers/net/usb/lan78xx.c
+++ b/drivers/net/usb/lan78xx.c
@@ -439,7 +439,7 @@ struct lan78xx_net {
struct usb_anchor deferred;
struct mutex dev_mutex; /* serialise open/stop wrt suspend/resume */
- struct mutex phy_mutex; /* for phy access */
+ struct mutex mdiobus_mutex; /* for MDIO bus access */
unsigned int pipe_in, pipe_out, pipe_intr;
unsigned int bulk_in_delay;
@@ -472,10 +472,6 @@ struct lan78xx_net {
struct irq_domain_data domain_data;
};
-/* define external phy id */
-#define PHY_LAN8835 (0x0007C130)
-#define PHY_KSZ9031RNX (0x00221620)
-
/* use ethtool to change the level for any given device */
static int msg_level = -1;
module_param(msg_level, int, 0);
@@ -625,8 +621,8 @@ static int lan78xx_read_reg(struct lan78xx_net *dev, u32 index, u32 *data)
*data = *buf;
} else if (net_ratelimit()) {
netdev_warn(dev->net,
- "Failed to read register index 0x%08x. ret = %d",
- index, ret);
+ "Failed to read register index 0x%08x. ret = %pe",
+ index, ERR_PTR(ret));
}
kfree(buf);
@@ -656,8 +652,8 @@ static int lan78xx_write_reg(struct lan78xx_net *dev, u32 index, u32 data)
if (unlikely(ret < 0) &&
net_ratelimit()) {
netdev_warn(dev->net,
- "Failed to write register index 0x%08x. ret = %d",
- index, ret);
+ "Failed to write register index 0x%08x. ret = %pe",
+ index, ERR_PTR(ret));
}
kfree(buf);
@@ -678,11 +674,7 @@ static int lan78xx_update_reg(struct lan78xx_net *dev, u32 reg, u32 mask,
buf &= ~mask;
buf |= (mask & data);
- ret = lan78xx_write_reg(dev, reg, buf);
- if (ret < 0)
- return ret;
-
- return 0;
+ return lan78xx_write_reg(dev, reg, buf);
}
static int lan78xx_read_stats(struct lan78xx_net *dev,
@@ -812,8 +804,156 @@ static void lan78xx_update_stats(struct lan78xx_net *dev)
usb_autopm_put_interface(dev->intf);
}
-/* Loop until the read is completed with timeout called with phy_mutex held */
-static int lan78xx_phy_wait_not_busy(struct lan78xx_net *dev)
+static int lan78xx_start_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enable)
+{
+ return lan78xx_update_reg(dev, reg, hw_enable, hw_enable);
+}
+
+static int lan78xx_stop_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enabled,
+ u32 hw_disabled)
+{
+ unsigned long timeout;
+ bool stopped = true;
+ int ret;
+ u32 buf;
+
+ /* Stop the h/w block (if not already stopped) */
+
+ ret = lan78xx_read_reg(dev, reg, &buf);
+ if (ret < 0)
+ return ret;
+
+ if (buf & hw_enabled) {
+ buf &= ~hw_enabled;
+
+ ret = lan78xx_write_reg(dev, reg, buf);
+ if (ret < 0)
+ return ret;
+
+ stopped = false;
+ timeout = jiffies + HW_DISABLE_TIMEOUT;
+ do {
+ ret = lan78xx_read_reg(dev, reg, &buf);
+ if (ret < 0)
+ return ret;
+
+ if (buf & hw_disabled)
+ stopped = true;
+ else
+ msleep(HW_DISABLE_DELAY_MS);
+ } while (!stopped && !time_after(jiffies, timeout));
+ }
+
+ return stopped ? 0 : -ETIMEDOUT;
+}
+
+static int lan78xx_flush_fifo(struct lan78xx_net *dev, u32 reg, u32 fifo_flush)
+{
+ return lan78xx_update_reg(dev, reg, fifo_flush, fifo_flush);
+}
+
+static int lan78xx_start_tx_path(struct lan78xx_net *dev)
+{
+ int ret;
+
+ netif_dbg(dev, drv, dev->net, "start tx path");
+
+ /* Start the MAC transmitter */
+
+ ret = lan78xx_start_hw(dev, MAC_TX, MAC_TX_TXEN_);
+ if (ret < 0)
+ return ret;
+
+ /* Start the Tx FIFO */
+
+ ret = lan78xx_start_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int lan78xx_stop_tx_path(struct lan78xx_net *dev)
+{
+ int ret;
+
+ netif_dbg(dev, drv, dev->net, "stop tx path");
+
+ /* Stop the Tx FIFO */
+
+ ret = lan78xx_stop_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_, FCT_TX_CTL_DIS_);
+ if (ret < 0)
+ return ret;
+
+ /* Stop the MAC transmitter */
+
+ ret = lan78xx_stop_hw(dev, MAC_TX, MAC_TX_TXEN_, MAC_TX_TXD_);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/* The caller must ensure the Tx path is stopped before calling
+ * lan78xx_flush_tx_fifo().
+ */
+static int lan78xx_flush_tx_fifo(struct lan78xx_net *dev)
+{
+ return lan78xx_flush_fifo(dev, FCT_TX_CTL, FCT_TX_CTL_RST_);
+}
+
+static int lan78xx_start_rx_path(struct lan78xx_net *dev)
+{
+ int ret;
+
+ netif_dbg(dev, drv, dev->net, "start rx path");
+
+ /* Start the Rx FIFO */
+
+ ret = lan78xx_start_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_);
+ if (ret < 0)
+ return ret;
+
+ /* Start the MAC receiver*/
+
+ ret = lan78xx_start_hw(dev, MAC_RX, MAC_RX_RXEN_);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static int lan78xx_stop_rx_path(struct lan78xx_net *dev)
+{
+ int ret;
+
+ netif_dbg(dev, drv, dev->net, "stop rx path");
+
+ /* Stop the MAC receiver */
+
+ ret = lan78xx_stop_hw(dev, MAC_RX, MAC_RX_RXEN_, MAC_RX_RXD_);
+ if (ret < 0)
+ return ret;
+
+ /* Stop the Rx FIFO */
+
+ ret = lan78xx_stop_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_, FCT_RX_CTL_DIS_);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+/* The caller must ensure the Rx path is stopped before calling
+ * lan78xx_flush_rx_fifo().
+ */
+static int lan78xx_flush_rx_fifo(struct lan78xx_net *dev)
+{
+ return lan78xx_flush_fifo(dev, FCT_RX_CTL, FCT_RX_CTL_RST_);
+}
+
+/* Loop until the read is completed with timeout called with mdiobus_mutex held */
+static int lan78xx_mdiobus_wait_not_busy(struct lan78xx_net *dev)
{
unsigned long start_time = jiffies;
u32 val;
@@ -821,14 +961,14 @@ static int lan78xx_phy_wait_not_busy(struct lan78xx_net *dev)
do {
ret = lan78xx_read_reg(dev, MII_ACC, &val);
- if (unlikely(ret < 0))
- return -EIO;
+ if (ret < 0)
+ return ret;
if (!(val & MII_ACC_MII_BUSY_))
return 0;
} while (!time_after(jiffies, start_time + HZ));
- return -EIO;
+ return -ETIMEDOUT;
}
static inline u32 mii_access(int id, int index, int read)
@@ -854,8 +994,8 @@ static int lan78xx_wait_eeprom(struct lan78xx_net *dev)
do {
ret = lan78xx_read_reg(dev, E2P_CMD, &val);
- if (unlikely(ret < 0))
- return -EIO;
+ if (ret < 0)
+ return ret;
if (!(val & E2P_CMD_EPC_BUSY_) ||
(val & E2P_CMD_EPC_TIMEOUT_))
@@ -865,7 +1005,7 @@ static int lan78xx_wait_eeprom(struct lan78xx_net *dev)
if (val & (E2P_CMD_EPC_TIMEOUT_ | E2P_CMD_EPC_BUSY_)) {
netdev_warn(dev->net, "EEPROM read operation timeout");
- return -EIO;
+ return -ETIMEDOUT;
}
return 0;
@@ -879,8 +1019,8 @@ static int lan78xx_eeprom_confirm_not_busy(struct lan78xx_net *dev)
do {
ret = lan78xx_read_reg(dev, E2P_CMD, &val);
- if (unlikely(ret < 0))
- return -EIO;
+ if (ret < 0)
+ return ret;
if (!(val & E2P_CMD_EPC_BUSY_))
return 0;
@@ -889,75 +1029,81 @@ static int lan78xx_eeprom_confirm_not_busy(struct lan78xx_net *dev)
} while (!time_after(jiffies, start_time + HZ));
netdev_warn(dev->net, "EEPROM is busy");
- return -EIO;
+ return -ETIMEDOUT;
}
static int lan78xx_read_raw_eeprom(struct lan78xx_net *dev, u32 offset,
u32 length, u8 *data)
{
- u32 val;
- u32 saved;
+ u32 val, saved;
int i, ret;
- int retval;
/* depends on chip, some EEPROM pins are muxed with LED function.
* disable & restore LED function to access EEPROM.
*/
ret = lan78xx_read_reg(dev, HW_CFG, &val);
+ if (ret < 0)
+ return ret;
+
saved = val;
if (dev->chipid == ID_REV_CHIP_ID_7800_) {
val &= ~(HW_CFG_LED1_EN_ | HW_CFG_LED0_EN_);
ret = lan78xx_write_reg(dev, HW_CFG, val);
+ if (ret < 0)
+ return ret;
}
- retval = lan78xx_eeprom_confirm_not_busy(dev);
- if (retval)
- return retval;
+ ret = lan78xx_eeprom_confirm_not_busy(dev);
+ if (ret == -ETIMEDOUT)
+ goto read_raw_eeprom_done;
+ /* If USB fails, there is nothing to do */
+ if (ret < 0)
+ return ret;
for (i = 0; i < length; i++) {
val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_READ_;
val |= (offset & E2P_CMD_EPC_ADDR_MASK_);
ret = lan78xx_write_reg(dev, E2P_CMD, val);
- if (unlikely(ret < 0)) {
- retval = -EIO;
- goto exit;
- }
+ if (ret < 0)
+ return ret;
- retval = lan78xx_wait_eeprom(dev);
- if (retval < 0)
- goto exit;
+ ret = lan78xx_wait_eeprom(dev);
+ /* Looks like not USB specific error, try to recover */
+ if (ret == -ETIMEDOUT)
+ goto read_raw_eeprom_done;
+ /* If USB fails, there is nothing to do */
+ if (ret < 0)
+ return ret;
ret = lan78xx_read_reg(dev, E2P_DATA, &val);
- if (unlikely(ret < 0)) {
- retval = -EIO;
- goto exit;
- }
+ if (ret < 0)
+ return ret;
data[i] = val & 0xFF;
offset++;
}
- retval = 0;
-exit:
+read_raw_eeprom_done:
if (dev->chipid == ID_REV_CHIP_ID_7800_)
- ret = lan78xx_write_reg(dev, HW_CFG, saved);
+ return lan78xx_write_reg(dev, HW_CFG, saved);
- return retval;
+ return 0;
}
static int lan78xx_read_eeprom(struct lan78xx_net *dev, u32 offset,
u32 length, u8 *data)
{
- u8 sig;
int ret;
+ u8 sig;
ret = lan78xx_read_raw_eeprom(dev, 0, 1, &sig);
- if ((ret == 0) && (sig == EEPROM_INDICATOR))
- ret = lan78xx_read_raw_eeprom(dev, offset, length, data);
- else
- ret = -EINVAL;
+ if (ret < 0)
+ return ret;
- return ret;
+ if (sig != EEPROM_INDICATOR)
+ return -ENODATA;
+
+ return lan78xx_read_raw_eeprom(dev, offset, length, data);
}
static int lan78xx_write_raw_eeprom(struct lan78xx_net *dev, u32 offset,
@@ -966,113 +1112,144 @@ static int lan78xx_write_raw_eeprom(struct lan78xx_net *dev, u32 offset,
u32 val;
u32 saved;
int i, ret;
- int retval;
/* depends on chip, some EEPROM pins are muxed with LED function.
* disable & restore LED function to access EEPROM.
*/
ret = lan78xx_read_reg(dev, HW_CFG, &val);
+ if (ret < 0)
+ return ret;
+
saved = val;
if (dev->chipid == ID_REV_CHIP_ID_7800_) {
val &= ~(HW_CFG_LED1_EN_ | HW_CFG_LED0_EN_);
ret = lan78xx_write_reg(dev, HW_CFG, val);
+ if (ret < 0)
+ return ret;
}
- retval = lan78xx_eeprom_confirm_not_busy(dev);
- if (retval)
- goto exit;
+ ret = lan78xx_eeprom_confirm_not_busy(dev);
+ /* Looks like not USB specific error, try to recover */
+ if (ret == -ETIMEDOUT)
+ goto write_raw_eeprom_done;
+ /* If USB fails, there is nothing to do */
+ if (ret < 0)
+ return ret;
/* Issue write/erase enable command */
val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_EWEN_;
ret = lan78xx_write_reg(dev, E2P_CMD, val);
- if (unlikely(ret < 0)) {
- retval = -EIO;
- goto exit;
- }
+ if (ret < 0)
+ return ret;
- retval = lan78xx_wait_eeprom(dev);
- if (retval < 0)
- goto exit;
+ ret = lan78xx_wait_eeprom(dev);
+ /* Looks like not USB specific error, try to recover */
+ if (ret == -ETIMEDOUT)
+ goto write_raw_eeprom_done;
+ /* If USB fails, there is nothing to do */
+ if (ret < 0)
+ return ret;
for (i = 0; i < length; i++) {
/* Fill data register */
val = data[i];
ret = lan78xx_write_reg(dev, E2P_DATA, val);
- if (ret < 0) {
- retval = -EIO;
- goto exit;
- }
+ if (ret < 0)
+ return ret;
/* Send "write" command */
val = E2P_CMD_EPC_BUSY_ | E2P_CMD_EPC_CMD_WRITE_;
val |= (offset & E2P_CMD_EPC_ADDR_MASK_);
ret = lan78xx_write_reg(dev, E2P_CMD, val);
- if (ret < 0) {
- retval = -EIO;
- goto exit;
- }
+ if (ret < 0)
+ return ret;
- retval = lan78xx_wait_eeprom(dev);
- if (retval < 0)
- goto exit;
+ ret = lan78xx_wait_eeprom(dev);
+ /* Looks like not USB specific error, try to recover */
+ if (ret == -ETIMEDOUT)
+ goto write_raw_eeprom_done;
+ /* If USB fails, there is nothing to do */
+ if (ret < 0)
+ return ret;
offset++;
}
- retval = 0;
-exit:
+write_raw_eeprom_done:
if (dev->chipid == ID_REV_CHIP_ID_7800_)
- ret = lan78xx_write_reg(dev, HW_CFG, saved);
+ return lan78xx_write_reg(dev, HW_CFG, saved);
- return retval;
+ return 0;
}
static int lan78xx_read_raw_otp(struct lan78xx_net *dev, u32 offset,
u32 length, u8 *data)
{
- int i;
- u32 buf;
unsigned long timeout;
+ int ret, i;
+ u32 buf;
- lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+ ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+ if (ret < 0)
+ return ret;
if (buf & OTP_PWR_DN_PWRDN_N_) {
/* clear it and wait to be cleared */
- lan78xx_write_reg(dev, OTP_PWR_DN, 0);
+ ret = lan78xx_write_reg(dev, OTP_PWR_DN, 0);
+ if (ret < 0)
+ return ret;
timeout = jiffies + HZ;
do {
usleep_range(1, 10);
- lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+ ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+ if (ret < 0)
+ return ret;
+
if (time_after(jiffies, timeout)) {
netdev_warn(dev->net,
"timeout on OTP_PWR_DN");
- return -EIO;
+ return -ETIMEDOUT;
}
} while (buf & OTP_PWR_DN_PWRDN_N_);
}
for (i = 0; i < length; i++) {
- lan78xx_write_reg(dev, OTP_ADDR1,
- ((offset + i) >> 8) & OTP_ADDR1_15_11);
- lan78xx_write_reg(dev, OTP_ADDR2,
- ((offset + i) & OTP_ADDR2_10_3));
+ ret = lan78xx_write_reg(dev, OTP_ADDR1,
+ ((offset + i) >> 8) & OTP_ADDR1_15_11);
+ if (ret < 0)
+ return ret;
+
+ ret = lan78xx_write_reg(dev, OTP_ADDR2,
+ ((offset + i) & OTP_ADDR2_10_3));
+ if (ret < 0)
+ return ret;
- lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
- lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+ ret = lan78xx_write_reg(dev, OTP_FUNC_CMD, OTP_FUNC_CMD_READ_);
+ if (ret < 0)
+ return ret;
+
+ ret = lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+ if (ret < 0)
+ return ret;
timeout = jiffies + HZ;
do {
udelay(1);
- lan78xx_read_reg(dev, OTP_STATUS, &buf);
+ ret = lan78xx_read_reg(dev, OTP_STATUS, &buf);
+ if (ret < 0)
+ return ret;
+
if (time_after(jiffies, timeout)) {
netdev_warn(dev->net,
"timeout on OTP_STATUS");
- return -EIO;
+ return -ETIMEDOUT;
}
} while (buf & OTP_STATUS_BUSY_);
- lan78xx_read_reg(dev, OTP_RD_DATA, &buf);
+ ret = lan78xx_read_reg(dev, OTP_RD_DATA, &buf);
+ if (ret < 0)
+ return ret;
data[i] = (u8)(buf & 0xFF);
}
@@ -1086,45 +1263,72 @@ static int lan78xx_write_raw_otp(struct lan78xx_net *dev, u32 offset,
int i;
u32 buf;
unsigned long timeout;
+ int ret;
- lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+ ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+ if (ret < 0)
+ return ret;
if (buf & OTP_PWR_DN_PWRDN_N_) {
/* clear it and wait to be cleared */
- lan78xx_write_reg(dev, OTP_PWR_DN, 0);
+ ret = lan78xx_write_reg(dev, OTP_PWR_DN, 0);
+ if (ret < 0)
+ return ret;
timeout = jiffies + HZ;
do {
udelay(1);
- lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+ ret = lan78xx_read_reg(dev, OTP_PWR_DN, &buf);
+ if (ret < 0)
+ return ret;
+
if (time_after(jiffies, timeout)) {
netdev_warn(dev->net,
"timeout on OTP_PWR_DN completion");
- return -EIO;
+ return -ETIMEDOUT;
}
} while (buf & OTP_PWR_DN_PWRDN_N_);
}
/* set to BYTE program mode */
- lan78xx_write_reg(dev, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
+ ret = lan78xx_write_reg(dev, OTP_PRGM_MODE, OTP_PRGM_MODE_BYTE_);
+ if (ret < 0)
+ return ret;
for (i = 0; i < length; i++) {
- lan78xx_write_reg(dev, OTP_ADDR1,
- ((offset + i) >> 8) & OTP_ADDR1_15_11);
- lan78xx_write_reg(dev, OTP_ADDR2,
- ((offset + i) & OTP_ADDR2_10_3));
- lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]);
- lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
- lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+ ret = lan78xx_write_reg(dev, OTP_ADDR1,
+ ((offset + i) >> 8) & OTP_ADDR1_15_11);
+ if (ret < 0)
+ return ret;
+
+ ret = lan78xx_write_reg(dev, OTP_ADDR2,
+ ((offset + i) & OTP_ADDR2_10_3));
+ if (ret < 0)
+ return ret;
+
+ ret = lan78xx_write_reg(dev, OTP_PRGM_DATA, data[i]);
+ if (ret < 0)
+ return ret;
+
+ ret = lan78xx_write_reg(dev, OTP_TST_CMD, OTP_TST_CMD_PRGVRFY_);
+ if (ret < 0)
+ return ret;
+
+ ret = lan78xx_write_reg(dev, OTP_CMD_GO, OTP_CMD_GO_GO_);
+ if (ret < 0)
+ return ret;
timeout = jiffies + HZ;
do {
udelay(1);
- lan78xx_read_reg(dev, OTP_STATUS, &buf);
+ ret = lan78xx_read_reg(dev, OTP_STATUS, &buf);
+ if (ret < 0)
+ return ret;
+
if (time_after(jiffies, timeout)) {
netdev_warn(dev->net,
"Timeout on OTP_STATUS completion");
- return -EIO;
+ return -ETIMEDOUT;
}
} while (buf & OTP_STATUS_BUSY_);
}
@@ -1161,7 +1365,7 @@ static int lan78xx_dataport_wait_not_busy(struct lan78xx_net *dev)
ret = lan78xx_read_reg(dev, DP_SEL, &dp_sel);
if (unlikely(ret < 0))
- return -EIO;
+ return ret;
if (dp_sel & DP_SEL_DPRDY_)
return 0;
@@ -1171,44 +1375,51 @@ static int lan78xx_dataport_wait_not_busy(struct lan78xx_net *dev)
netdev_warn(dev->net, "%s timed out", __func__);
- return -EIO;
+ return -ETIMEDOUT;
}
static int lan78xx_dataport_write(struct lan78xx_net *dev, u32 ram_select,
u32 addr, u32 length, u32 *buf)
{
struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
- u32 dp_sel;
int i, ret;
- if (usb_autopm_get_interface(dev->intf) < 0)
- return 0;
+ ret = usb_autopm_get_interface(dev->intf);
+ if (ret < 0)
+ return ret;
mutex_lock(&pdata->dataport_mutex);
ret = lan78xx_dataport_wait_not_busy(dev);
if (ret < 0)
- goto done;
+ goto dataport_write;
- ret = lan78xx_read_reg(dev, DP_SEL, &dp_sel);
-
- dp_sel &= ~DP_SEL_RSEL_MASK_;
- dp_sel |= ram_select;
- ret = lan78xx_write_reg(dev, DP_SEL, dp_sel);
+ ret = lan78xx_update_reg(dev, DP_SEL, DP_SEL_RSEL_MASK_, ram_select);
+ if (ret < 0)
+ goto dataport_write;
for (i = 0; i < length; i++) {
ret = lan78xx_write_reg(dev, DP_ADDR, addr + i);
+ if (ret < 0)
+ goto dataport_write;
ret = lan78xx_write_reg(dev, DP_DATA, buf[i]);
+ if (ret < 0)
+ goto dataport_write;
ret = lan78xx_write_reg(dev, DP_CMD, DP_CMD_WRITE_);
+ if (ret < 0)
+ goto dataport_write;
ret = lan78xx_dataport_wait_not_busy(dev);
if (ret < 0)
- goto done;
+ goto dataport_write;
}
-done:
+dataport_write:
+ if (ret < 0)
+ netdev_warn(dev->net, "dataport write failed %pe", ERR_PTR(ret));
+
mutex_unlock(&pdata->dataport_mutex);
usb_autopm_put_interface(dev->intf);
@@ -1244,23 +1455,39 @@ static void lan78xx_deferred_multicast_write(struct work_struct *param)
struct lan78xx_priv *pdata =
container_of(param, struct lan78xx_priv, set_multicast);
struct lan78xx_net *dev = pdata->dev;
- int i;
+ int i, ret;
netif_dbg(dev, drv, dev->net, "deferred multicast write 0x%08x\n",
pdata->rfe_ctl);
- lan78xx_dataport_write(dev, DP_SEL_RSEL_VLAN_DA_, DP_SEL_VHF_VLAN_LEN,
- DP_SEL_VHF_HASH_LEN, pdata->mchash_table);
+ ret = lan78xx_dataport_write(dev, DP_SEL_RSEL_VLAN_DA_,
+ DP_SEL_VHF_VLAN_LEN,
+ DP_SEL_VHF_HASH_LEN, pdata->mchash_table);
+ if (ret < 0)
+ goto multicast_write_done;
for (i = 1; i < NUM_OF_MAF; i++) {
- lan78xx_write_reg(dev, MAF_HI(i), 0);
- lan78xx_write_reg(dev, MAF_LO(i),
- pdata->pfilter_table[i][1]);
- lan78xx_write_reg(dev, MAF_HI(i),
- pdata->pfilter_table[i][0]);
+ ret = lan78xx_write_reg(dev, MAF_HI(i), 0);
+ if (ret < 0)
+ goto multicast_write_done;
+
+ ret = lan78xx_write_reg(dev, MAF_LO(i),
+ pdata->pfilter_table[i][1]);
+ if (ret < 0)
+ goto multicast_write_done;
+
+ ret = lan78xx_write_reg(dev, MAF_HI(i),
+ pdata->pfilter_table[i][0]);
+ if (ret < 0)
+ goto multicast_write_done;
}
- lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+ ret = lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
+
+multicast_write_done:
+ if (ret < 0)
+ netdev_warn(dev->net, "multicast write failed %pe", ERR_PTR(ret));
+ return;
}
static void lan78xx_set_multicast(struct net_device *netdev)
@@ -1369,24 +1596,24 @@ static int lan78xx_mac_reset(struct lan78xx_net *dev)
u32 val;
int ret;
- mutex_lock(&dev->phy_mutex);
+ mutex_lock(&dev->mdiobus_mutex);
/* Resetting the device while there is activity on the MDIO
* bus can result in the MAC interface locking up and not
* completing register access transactions.
*/
- ret = lan78xx_phy_wait_not_busy(dev);
+ ret = lan78xx_mdiobus_wait_not_busy(dev);
if (ret < 0)
- goto done;
+ goto exit_unlock;
ret = lan78xx_read_reg(dev, MAC_CR, &val);
if (ret < 0)
- goto done;
+ goto exit_unlock;
val |= MAC_CR_RST_;
ret = lan78xx_write_reg(dev, MAC_CR, val);
if (ret < 0)
- goto done;
+ goto exit_unlock;
/* Wait for the reset to complete before allowing any further
* MAC register accesses otherwise the MAC may lock up.
@@ -1394,17 +1621,17 @@ static int lan78xx_mac_reset(struct lan78xx_net *dev)
do {
ret = lan78xx_read_reg(dev, MAC_CR, &val);
if (ret < 0)
- goto done;
+ goto exit_unlock;
if (!(val & MAC_CR_RST_)) {
ret = 0;
- goto done;
+ goto exit_unlock;
}
} while (!time_after(jiffies, start_time + HZ));
ret = -ETIMEDOUT;
-done:
- mutex_unlock(&dev->phy_mutex);
+exit_unlock:
+ mutex_unlock(&dev->mdiobus_mutex);
return ret;
}
@@ -1630,6 +1857,7 @@ static void lan78xx_get_wol(struct net_device *netdev,
ret = lan78xx_read_reg(dev, USB_CFG0, &buf);
if (unlikely(ret < 0)) {
+ netdev_warn(dev->net, "failed to get WoL %pe", ERR_PTR(ret));
wol->supported = 0;
wol->wolopts = 0;
} else {
@@ -1661,10 +1889,13 @@ static int lan78xx_set_wol(struct net_device *netdev,
pdata->wol = wol->wolopts;
- device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts);
+ ret = device_set_wakeup_enable(&dev->udev->dev, (bool)wol->wolopts);
+ if (ret < 0)
+ goto exit_pm_put;
- phy_ethtool_set_wol(netdev->phydev, wol);
+ ret = phy_ethtool_set_wol(netdev->phydev, wol);
+exit_pm_put:
usb_autopm_put_interface(dev->intf);
return ret;
@@ -1869,30 +2100,35 @@ exit:
static int lan78xx_get_regs_len(struct net_device *netdev)
{
- if (!netdev->phydev)
- return (sizeof(lan78xx_regs));
- else
- return (sizeof(lan78xx_regs) + PHY_REG_SIZE);
+ return sizeof(lan78xx_regs);
}
static void
lan78xx_get_regs(struct net_device *netdev, struct ethtool_regs *regs,
void *buf)
{
- u32 *data = buf;
- int i, j;
struct lan78xx_net *dev = netdev_priv(netdev);
+ unsigned int data_count = 0;
+ u32 *data = buf;
+ int i, ret;
/* Read Device/MAC registers */
- for (i = 0; i < ARRAY_SIZE(lan78xx_regs); i++)
- lan78xx_read_reg(dev, lan78xx_regs[i], &data[i]);
+ for (i = 0; i < ARRAY_SIZE(lan78xx_regs); i++) {
+ ret = lan78xx_read_reg(dev, lan78xx_regs[i], &data[i]);
+ if (ret < 0) {
+ netdev_warn(dev->net,
+ "failed to read register 0x%08x\n",
+ lan78xx_regs[i]);
+ goto clean_data;
+ }
- if (!netdev->phydev)
- return;
+ data_count++;
+ }
- /* Read PHY registers */
- for (j = 0; j < 32; i++, j++)
- data[i] = phy_read(netdev->phydev, j);
+ return;
+
+clean_data:
+ memset(data, 0, data_count * sizeof(u32));
}
static const struct ethtool_ops lan78xx_ethtool_ops = {
@@ -1920,13 +2156,19 @@ static const struct ethtool_ops lan78xx_ethtool_ops = {
.get_regs = lan78xx_get_regs,
};
-static void lan78xx_init_mac_address(struct lan78xx_net *dev)
+static int lan78xx_init_mac_address(struct lan78xx_net *dev)
{
u32 addr_lo, addr_hi;
u8 addr[6];
+ int ret;
- lan78xx_read_reg(dev, RX_ADDRL, &addr_lo);
- lan78xx_read_reg(dev, RX_ADDRH, &addr_hi);
+ ret = lan78xx_read_reg(dev, RX_ADDRL, &addr_lo);
+ if (ret < 0)
+ return ret;
+
+ ret = lan78xx_read_reg(dev, RX_ADDRH, &addr_hi);
+ if (ret < 0)
+ return ret;
addr[0] = addr_lo & 0xFF;
addr[1] = (addr_lo >> 8) & 0xFF;
@@ -1959,14 +2201,26 @@ static void lan78xx_init_mac_address(struct lan78xx_net *dev)
(addr[2] << 16) | (addr[3] << 24);
addr_hi = addr[4] | (addr[5] << 8);
- lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
- lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
+ ret = lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
+ if (ret < 0)
+ return ret;
+
+ ret = lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
+ if (ret < 0)
+ return ret;
}
- lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
- lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
+ ret = lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
+ if (ret < 0)
+ return ret;
+
+ ret = lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
+ if (ret < 0)
+ return ret;
eth_hw_addr_set(dev->net, addr);
+
+ return 0;
}
/* MDIO read and write wrappers for phylib */
@@ -1980,27 +2234,31 @@ static int lan78xx_mdiobus_read(struct mii_bus *bus, int phy_id, int idx)
if (ret < 0)
return ret;
- mutex_lock(&dev->phy_mutex);
+ mutex_lock(&dev->mdiobus_mutex);
/* confirm MII not busy */
- ret = lan78xx_phy_wait_not_busy(dev);
+ ret = lan78xx_mdiobus_wait_not_busy(dev);
if (ret < 0)
goto done;
/* set the address, index & direction (read from PHY) */
addr = mii_access(phy_id, idx, MII_READ);
ret = lan78xx_write_reg(dev, MII_ACC, addr);
+ if (ret < 0)
+ goto done;
- ret = lan78xx_phy_wait_not_busy(dev);
+ ret = lan78xx_mdiobus_wait_not_busy(dev);
if (ret < 0)
goto done;
ret = lan78xx_read_reg(dev, MII_DATA, &val);
+ if (ret < 0)
+ goto done;
ret = (int)(val & 0xFFFF);
done:
- mutex_unlock(&dev->phy_mutex);
+ mutex_unlock(&dev->mdiobus_mutex);
usb_autopm_put_interface(dev->intf);
return ret;
@@ -2017,28 +2275,32 @@ static int lan78xx_mdiobus_write(struct mii_bus *bus, int phy_id, int idx,
if (ret < 0)
return ret;
- mutex_lock(&dev->phy_mutex);
+ mutex_lock(&dev->mdiobus_mutex);
/* confirm MII not busy */
- ret = lan78xx_phy_wait_not_busy(dev);
+ ret = lan78xx_mdiobus_wait_not_busy(dev);
if (ret < 0)
goto done;
val = (u32)regval;
ret = lan78xx_write_reg(dev, MII_DATA, val);
+ if (ret < 0)
+ goto done;
/* set the address, index & direction (write to PHY) */
addr = mii_access(phy_id, idx, MII_WRITE);
ret = lan78xx_write_reg(dev, MII_ACC, addr);
+ if (ret < 0)
+ goto done;
- ret = lan78xx_phy_wait_not_busy(dev);
+ ret = lan78xx_mdiobus_wait_not_busy(dev);
if (ret < 0)
goto done;
done:
- mutex_unlock(&dev->phy_mutex);
+ mutex_unlock(&dev->mdiobus_mutex);
usb_autopm_put_interface(dev->intf);
- return 0;
+ return ret;
}
static int lan78xx_mdio_init(struct lan78xx_net *dev)
@@ -2164,13 +2426,22 @@ static void lan78xx_irq_bus_sync_unlock(struct irq_data *irqd)
struct lan78xx_net *dev =
container_of(data, struct lan78xx_net, domain_data);
u32 buf;
+ int ret;
/* call register access here because irq_bus_lock & irq_bus_sync_unlock
* are only two callbacks executed in non-atomic contex.
*/
- lan78xx_read_reg(dev, INT_EP_CTL, &buf);
+ ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf);
+ if (ret < 0)
+ goto irq_bus_sync_unlock;
+
if (buf != data->irqenable)
- lan78xx_write_reg(dev, INT_EP_CTL, data->irqenable);
+ ret = lan78xx_write_reg(dev, INT_EP_CTL, data->irqenable);
+
+irq_bus_sync_unlock:
+ if (ret < 0)
+ netdev_err(dev->net, "Failed to sync IRQ enable register: %pe\n",
+ ERR_PTR(ret));
mutex_unlock(&data->irq_lock);
}
@@ -2195,7 +2466,10 @@ static int lan78xx_setup_irq_domain(struct lan78xx_net *dev)
mutex_init(&dev->domain_data.irq_lock);
- lan78xx_read_reg(dev, INT_EP_CTL, &buf);
+ ret = lan78xx_read_reg(dev, INT_EP_CTL, &buf);
+ if (ret < 0)
+ return ret;
+
dev->domain_data.irqenable = buf;
dev->domain_data.irqchip = &lan78xx_irqchip;
@@ -2234,46 +2508,6 @@ static void lan78xx_remove_irq_domain(struct lan78xx_net *dev)
dev->domain_data.irqdomain = NULL;
}
-static int lan8835_fixup(struct phy_device *phydev)
-{
- int buf;
- struct lan78xx_net *dev = netdev_priv(phydev->attached_dev);
-
- /* LED2/PME_N/IRQ_N/RGMII_ID pin to IRQ_N mode */
- buf = phy_read_mmd(phydev, MDIO_MMD_PCS, 0x8010);
- buf &= ~0x1800;
- buf |= 0x0800;
- phy_write_mmd(phydev, MDIO_MMD_PCS, 0x8010, buf);
-
- /* RGMII MAC TXC Delay Enable */
- lan78xx_write_reg(dev, MAC_RGMII_ID,
- MAC_RGMII_ID_TXC_DELAY_EN_);
-
- /* RGMII TX DLL Tune Adjust */
- lan78xx_write_reg(dev, RGMII_TX_BYP_DLL, 0x3D00);
-
- dev->interface = PHY_INTERFACE_MODE_RGMII_TXID;
-
- return 1;
-}
-
-static int ksz9031rnx_fixup(struct phy_device *phydev)
-{
- struct lan78xx_net *dev = netdev_priv(phydev->attached_dev);
-
- /* Micrel9301RNX PHY configuration */
- /* RGMII Control Signal Pad Skew */
- phy_write_mmd(phydev, MDIO_MMD_WIS, 4, 0x0077);
- /* RGMII RX Data Pad Skew */
- phy_write_mmd(phydev, MDIO_MMD_WIS, 5, 0x7777);
- /* RGMII RX Clock Pad Skew */
- phy_write_mmd(phydev, MDIO_MMD_WIS, 8, 0x1FF);
-
- dev->interface = PHY_INTERFACE_MODE_RGMII_RXID;
-
- return 1;
-}
-
static struct phy_device *lan7801_phy_init(struct lan78xx_net *dev)
{
u32 buf;
@@ -2307,22 +2541,11 @@ static struct phy_device *lan7801_phy_init(struct lan78xx_net *dev)
netdev_err(dev->net, "no PHY driver found\n");
return NULL;
}
- dev->interface = PHY_INTERFACE_MODE_RGMII;
- /* external PHY fixup for KSZ9031RNX */
- ret = phy_register_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0,
- ksz9031rnx_fixup);
- if (ret < 0) {
- netdev_err(dev->net, "Failed to register fixup for PHY_KSZ9031RNX\n");
- return NULL;
- }
- /* external PHY fixup for LAN8835 */
- ret = phy_register_fixup_for_uid(PHY_LAN8835, 0xfffffff0,
- lan8835_fixup);
- if (ret < 0) {
- netdev_err(dev->net, "Failed to register fixup for PHY_LAN8835\n");
- return NULL;
- }
- /* add more external PHY fixup here if needed */
+ dev->interface = PHY_INTERFACE_MODE_RGMII_ID;
+ /* The PHY driver is responsible to configure proper RGMII
+ * interface delays. Disable RGMII delays on MAC side.
+ */
+ lan78xx_write_reg(dev, MAC_RGMII_ID, 0);
phydev->is_internal = false;
}
@@ -2381,11 +2604,6 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
if (phy_is_pseudo_fixed_link(phydev)) {
fixed_phy_unregister(phydev);
phy_device_free(phydev);
- } else {
- phy_unregister_fixup_for_uid(PHY_KSZ9031RNX,
- 0xfffffff0);
- phy_unregister_fixup_for_uid(PHY_LAN8835,
- 0xfffffff0);
}
}
return -EIO;
@@ -2437,27 +2655,36 @@ static int lan78xx_phy_init(struct lan78xx_net *dev)
static int lan78xx_set_rx_max_frame_length(struct lan78xx_net *dev, int size)
{
- u32 buf;
bool rxenabled;
+ u32 buf;
+ int ret;
- lan78xx_read_reg(dev, MAC_RX, &buf);
+ ret = lan78xx_read_reg(dev, MAC_RX, &buf);
+ if (ret < 0)
+ return ret;
rxenabled = ((buf & MAC_RX_RXEN_) != 0);
if (rxenabled) {
buf &= ~MAC_RX_RXEN_;
- lan78xx_write_reg(dev, MAC_RX, buf);
+ ret = lan78xx_write_reg(dev, MAC_RX, buf);
+ if (ret < 0)
+ return ret;
}
/* add 4 to size for FCS */
buf &= ~MAC_RX_MAX_SIZE_MASK_;
buf |= (((size + 4) << MAC_RX_MAX_SIZE_SHIFT_) & MAC_RX_MAX_SIZE_MASK_);
- lan78xx_write_reg(dev, MAC_RX, buf);
+ ret = lan78xx_write_reg(dev, MAC_RX, buf);
+ if (ret < 0)
+ return ret;
if (rxenabled) {
buf |= MAC_RX_RXEN_;
- lan78xx_write_reg(dev, MAC_RX, buf);
+ ret = lan78xx_write_reg(dev, MAC_RX, buf);
+ if (ret < 0)
+ return ret;
}
return 0;
@@ -2523,7 +2750,10 @@ static int lan78xx_change_mtu(struct net_device *netdev, int new_mtu)
return ret;
ret = lan78xx_set_rx_max_frame_length(dev, max_frame_len);
- if (!ret)
+ if (ret < 0)
+ netdev_err(dev->net, "MTU changed to %d from %d failed with %pe\n",
+ new_mtu, netdev->mtu, ERR_PTR(ret));
+ else
WRITE_ONCE(netdev->mtu, new_mtu);
usb_autopm_put_interface(dev->intf);
@@ -2536,6 +2766,7 @@ static int lan78xx_set_mac_addr(struct net_device *netdev, void *p)
struct lan78xx_net *dev = netdev_priv(netdev);
struct sockaddr *addr = p;
u32 addr_lo, addr_hi;
+ int ret;
if (netif_running(netdev))
return -EBUSY;
@@ -2552,14 +2783,20 @@ static int lan78xx_set_mac_addr(struct net_device *netdev, void *p)
addr_hi = netdev->dev_addr[4] |
netdev->dev_addr[5] << 8;
- lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
- lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
+ ret = lan78xx_write_reg(dev, RX_ADDRL, addr_lo);
+ if (ret < 0)
+ return ret;
+
+ ret = lan78xx_write_reg(dev, RX_ADDRH, addr_hi);
+ if (ret < 0)
+ return ret;
/* Added to support MAC address changes */
- lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
- lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
+ ret = lan78xx_write_reg(dev, MAF_LO(0), addr_lo);
+ if (ret < 0)
+ return ret;
- return 0;
+ return lan78xx_write_reg(dev, MAF_HI(0), addr_hi | MAF_HI_VALID_);
}
/* Enable or disable Rx checksum offload engine */
@@ -2592,9 +2829,7 @@ static int lan78xx_set_features(struct net_device *netdev,
spin_unlock_irqrestore(&pdata->rfe_ctl_lock, flags);
- lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
-
- return 0;
+ return lan78xx_write_reg(dev, RFE_CTL, pdata->rfe_ctl);
}
static void lan78xx_deferred_vlan_write(struct work_struct *param)
@@ -2645,13 +2880,16 @@ static int lan78xx_vlan_rx_kill_vid(struct net_device *netdev,
return 0;
}
-static void lan78xx_init_ltm(struct lan78xx_net *dev)
+static int lan78xx_init_ltm(struct lan78xx_net *dev)
{
+ u32 regs[6] = { 0 };
int ret;
u32 buf;
- u32 regs[6] = { 0 };
ret = lan78xx_read_reg(dev, USB_CFG1, &buf);
+ if (ret < 0)
+ goto init_ltm_failed;
+
if (buf & USB_CFG1_LTM_ENABLE_) {
u8 temp[2];
/* Get values from EEPROM first */
@@ -2662,7 +2900,7 @@ static void lan78xx_init_ltm(struct lan78xx_net *dev)
24,
(u8 *)regs);
if (ret < 0)
- return;
+ return ret;
}
} else if (lan78xx_read_otp(dev, 0x3F, 2, temp) == 0) {
if (temp[0] == 24) {
@@ -2671,17 +2909,40 @@ static void lan78xx_init_ltm(struct lan78xx_net *dev)
24,
(u8 *)regs);
if (ret < 0)
- return;
+ return ret;
}
}
}
- lan78xx_write_reg(dev, LTM_BELT_IDLE0, regs[0]);
- lan78xx_write_reg(dev, LTM_BELT_IDLE1, regs[1]);
- lan78xx_write_reg(dev, LTM_BELT_ACT0, regs[2]);
- lan78xx_write_reg(dev, LTM_BELT_ACT1, regs[3]);
- lan78xx_write_reg(dev, LTM_INACTIVE0, regs[4]);
- lan78xx_write_reg(dev, LTM_INACTIVE1, regs[5]);
+ ret = lan78xx_write_reg(dev, LTM_BELT_IDLE0, regs[0]);
+ if (ret < 0)
+ goto init_ltm_failed;
+
+ ret = lan78xx_write_reg(dev, LTM_BELT_IDLE1, regs[1]);
+ if (ret < 0)
+ goto init_ltm_failed;
+
+ ret = lan78xx_write_reg(dev, LTM_BELT_ACT0, regs[2]);
+ if (ret < 0)
+ goto init_ltm_failed;
+
+ ret = lan78xx_write_reg(dev, LTM_BELT_ACT1, regs[3]);
+ if (ret < 0)
+ goto init_ltm_failed;
+
+ ret = lan78xx_write_reg(dev, LTM_INACTIVE0, regs[4]);
+ if (ret < 0)
+ goto init_ltm_failed;
+
+ ret = lan78xx_write_reg(dev, LTM_INACTIVE1, regs[5]);
+ if (ret < 0)
+ goto init_ltm_failed;
+
+ return 0;
+
+init_ltm_failed:
+ netdev_err(dev->net, "Failed to init LTM with error %pe\n", ERR_PTR(ret));
+ return ret;
}
static int lan78xx_urb_config_init(struct lan78xx_net *dev)
@@ -2722,156 +2983,6 @@ static int lan78xx_urb_config_init(struct lan78xx_net *dev)
return result;
}
-static int lan78xx_start_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enable)
-{
- return lan78xx_update_reg(dev, reg, hw_enable, hw_enable);
-}
-
-static int lan78xx_stop_hw(struct lan78xx_net *dev, u32 reg, u32 hw_enabled,
- u32 hw_disabled)
-{
- unsigned long timeout;
- bool stopped = true;
- int ret;
- u32 buf;
-
- /* Stop the h/w block (if not already stopped) */
-
- ret = lan78xx_read_reg(dev, reg, &buf);
- if (ret < 0)
- return ret;
-
- if (buf & hw_enabled) {
- buf &= ~hw_enabled;
-
- ret = lan78xx_write_reg(dev, reg, buf);
- if (ret < 0)
- return ret;
-
- stopped = false;
- timeout = jiffies + HW_DISABLE_TIMEOUT;
- do {
- ret = lan78xx_read_reg(dev, reg, &buf);
- if (ret < 0)
- return ret;
-
- if (buf & hw_disabled)
- stopped = true;
- else
- msleep(HW_DISABLE_DELAY_MS);
- } while (!stopped && !time_after(jiffies, timeout));
- }
-
- ret = stopped ? 0 : -ETIME;
-
- return ret;
-}
-
-static int lan78xx_flush_fifo(struct lan78xx_net *dev, u32 reg, u32 fifo_flush)
-{
- return lan78xx_update_reg(dev, reg, fifo_flush, fifo_flush);
-}
-
-static int lan78xx_start_tx_path(struct lan78xx_net *dev)
-{
- int ret;
-
- netif_dbg(dev, drv, dev->net, "start tx path");
-
- /* Start the MAC transmitter */
-
- ret = lan78xx_start_hw(dev, MAC_TX, MAC_TX_TXEN_);
- if (ret < 0)
- return ret;
-
- /* Start the Tx FIFO */
-
- ret = lan78xx_start_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int lan78xx_stop_tx_path(struct lan78xx_net *dev)
-{
- int ret;
-
- netif_dbg(dev, drv, dev->net, "stop tx path");
-
- /* Stop the Tx FIFO */
-
- ret = lan78xx_stop_hw(dev, FCT_TX_CTL, FCT_TX_CTL_EN_, FCT_TX_CTL_DIS_);
- if (ret < 0)
- return ret;
-
- /* Stop the MAC transmitter */
-
- ret = lan78xx_stop_hw(dev, MAC_TX, MAC_TX_TXEN_, MAC_TX_TXD_);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-/* The caller must ensure the Tx path is stopped before calling
- * lan78xx_flush_tx_fifo().
- */
-static int lan78xx_flush_tx_fifo(struct lan78xx_net *dev)
-{
- return lan78xx_flush_fifo(dev, FCT_TX_CTL, FCT_TX_CTL_RST_);
-}
-
-static int lan78xx_start_rx_path(struct lan78xx_net *dev)
-{
- int ret;
-
- netif_dbg(dev, drv, dev->net, "start rx path");
-
- /* Start the Rx FIFO */
-
- ret = lan78xx_start_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_);
- if (ret < 0)
- return ret;
-
- /* Start the MAC receiver*/
-
- ret = lan78xx_start_hw(dev, MAC_RX, MAC_RX_RXEN_);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int lan78xx_stop_rx_path(struct lan78xx_net *dev)
-{
- int ret;
-
- netif_dbg(dev, drv, dev->net, "stop rx path");
-
- /* Stop the MAC receiver */
-
- ret = lan78xx_stop_hw(dev, MAC_RX, MAC_RX_RXEN_, MAC_RX_RXD_);
- if (ret < 0)
- return ret;
-
- /* Stop the Rx FIFO */
-
- ret = lan78xx_stop_hw(dev, FCT_RX_CTL, FCT_RX_CTL_EN_, FCT_RX_CTL_DIS_);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-/* The caller must ensure the Rx path is stopped before calling
- * lan78xx_flush_rx_fifo().
- */
-static int lan78xx_flush_rx_fifo(struct lan78xx_net *dev)
-{
- return lan78xx_flush_fifo(dev, FCT_RX_CTL, FCT_RX_CTL_RST_);
-}
-
static int lan78xx_reset(struct lan78xx_net *dev)
{
struct lan78xx_priv *pdata = (struct lan78xx_priv *)(dev->data[0]);
@@ -2905,7 +3016,9 @@ static int lan78xx_reset(struct lan78xx_net *dev)
}
} while (buf & HW_CFG_LRST_);
- lan78xx_init_mac_address(dev);
+ ret = lan78xx_init_mac_address(dev);
+ if (ret < 0)
+ return ret;
/* save DEVID for later usage */
ret = lan78xx_read_reg(dev, ID_REV, &buf);
@@ -2927,7 +3040,9 @@ static int lan78xx_reset(struct lan78xx_net *dev)
return ret;
/* Init LTM */
- lan78xx_init_ltm(dev);
+ ret = lan78xx_init_ltm(dev);
+ if (ret < 0)
+ return ret;
ret = lan78xx_write_reg(dev, BURST_CAP, dev->burst_cap);
if (ret < 0)
@@ -4242,9 +4357,6 @@ static void lan78xx_disconnect(struct usb_interface *intf)
phydev = net->phydev;
- phy_unregister_fixup_for_uid(PHY_KSZ9031RNX, 0xfffffff0);
- phy_unregister_fixup_for_uid(PHY_LAN8835, 0xfffffff0);
-
phy_disconnect(net->phydev);
if (phy_is_pseudo_fixed_link(phydev)) {
@@ -4349,7 +4461,7 @@ static int lan78xx_probe(struct usb_interface *intf,
skb_queue_head_init(&dev->rxq_done);
skb_queue_head_init(&dev->txq_pend);
skb_queue_head_init(&dev->rxq_overflow);
- mutex_init(&dev->phy_mutex);
+ mutex_init(&dev->mdiobus_mutex);
mutex_init(&dev->dev_mutex);
ret = lan78xx_urb_config_init(dev);
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 0c011d8f5d4d..e9208a8d2bfa 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -1365,6 +1365,9 @@ static const struct usb_device_id products[] = {
{QMI_QUIRK_SET_DTR(0x1bc7, 0x10a0, 0)}, /* Telit FN920C04 */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x10a4, 0)}, /* Telit FN920C04 */
{QMI_QUIRK_SET_DTR(0x1bc7, 0x10a9, 0)}, /* Telit FN920C04 */
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c0, 0)}, /* Telit FE910C04 */
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c4, 0)}, /* Telit FE910C04 */
+ {QMI_QUIRK_SET_DTR(0x1bc7, 0x10c8, 0)}, /* Telit FE910C04 */
{QMI_FIXED_INTF(0x1bc7, 0x1100, 3)}, /* Telit ME910 */
{QMI_FIXED_INTF(0x1bc7, 0x1101, 3)}, /* Telit ME910 dual modem */
{QMI_FIXED_INTF(0x1bc7, 0x1200, 5)}, /* Telit LE920 */
@@ -1426,6 +1429,7 @@ static const struct usb_device_id products[] = {
{QMI_QUIRK_SET_DTR(0x2c7c, 0x0195, 4)}, /* Quectel EG95 */
{QMI_FIXED_INTF(0x2c7c, 0x0296, 4)}, /* Quectel BG96 */
{QMI_QUIRK_SET_DTR(0x2c7c, 0x030e, 4)}, /* Quectel EM05GV2 */
+ {QMI_QUIRK_SET_DTR(0x2c7c, 0x0316, 3)}, /* Quectel RG255C */
{QMI_QUIRK_SET_DTR(0x2cb7, 0x0104, 4)}, /* Fibocom NL678 series */
{QMI_QUIRK_SET_DTR(0x2cb7, 0x0112, 0)}, /* Fibocom FG132 */
{QMI_FIXED_INTF(0x0489, 0xe0b4, 0)}, /* Foxconn T77W968 LTE */
diff --git a/drivers/net/veth.c b/drivers/net/veth.c
index 0d6d0d749d44..01251868a9c2 100644
--- a/drivers/net/veth.c
+++ b/drivers/net/veth.c
@@ -634,7 +634,7 @@ static struct xdp_frame *veth_xdp_rcv_one(struct veth_rq *rq,
break;
case XDP_TX:
orig_frame = *frame;
- xdp->rxq->mem = frame->mem;
+ xdp->rxq->mem.type = frame->mem_type;
if (unlikely(veth_xdp_tx(rq, xdp, bq) < 0)) {
trace_xdp_exception(rq->dev, xdp_prog, act);
frame = &orig_frame;
@@ -646,7 +646,7 @@ static struct xdp_frame *veth_xdp_rcv_one(struct veth_rq *rq,
goto xdp_xmit;
case XDP_REDIRECT:
orig_frame = *frame;
- xdp->rxq->mem = frame->mem;
+ xdp->rxq->mem.type = frame->mem_type;
if (xdp_do_redirect(rq->dev, xdp, xdp_prog)) {
frame = &orig_frame;
stats->rx_drops++;
@@ -1765,7 +1765,7 @@ static int veth_init_queues(struct net_device *dev, struct nlattr *tb[])
return 0;
}
-static int veth_newlink(struct net *src_net, struct net_device *dev,
+static int veth_newlink(struct net *peer_net, struct net_device *dev,
struct nlattr *tb[], struct nlattr *data[],
struct netlink_ext_ack *extack)
{
@@ -1776,7 +1776,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
struct nlattr *peer_tb[IFLA_MAX + 1], **tbp;
unsigned char name_assign_type;
struct ifinfomsg *ifmp;
- struct net *net;
/*
* create and register peer first
@@ -1800,13 +1799,10 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
name_assign_type = NET_NAME_ENUM;
}
- net = rtnl_link_get_net(src_net, tbp);
- peer = rtnl_create_link(net, ifname, name_assign_type,
+ peer = rtnl_create_link(peer_net, ifname, name_assign_type,
&veth_link_ops, tbp, extack);
- if (IS_ERR(peer)) {
- put_net(net);
+ if (IS_ERR(peer))
return PTR_ERR(peer);
- }
if (!ifmp || !tbp[IFLA_ADDRESS])
eth_hw_addr_random(peer);
@@ -1817,8 +1813,6 @@ static int veth_newlink(struct net *src_net, struct net_device *dev,
netif_inherit_tso_max(peer, dev);
err = register_netdevice(peer);
- put_net(net);
- net = NULL;
if (err < 0)
goto err_register_peer;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index 64c87bb48a41..7646ddd9bef7 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -503,6 +503,7 @@ struct virtio_net_common_hdr {
static struct virtio_net_common_hdr xsk_hdr;
static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf);
+static void virtnet_sq_free_unused_buf_done(struct virtqueue *vq);
static int virtnet_xdp_handler(struct bpf_prog *xdp_prog, struct xdp_buff *xdp,
struct net_device *dev,
unsigned int *xdp_xmit,
@@ -3054,7 +3055,6 @@ static int virtnet_enable_queue_pair(struct virtnet_info *vi, int qp_index)
if (err < 0)
goto err_xdp_reg_mem_model;
- netdev_tx_reset_queue(netdev_get_tx_queue(vi->dev, qp_index));
virtnet_napi_enable(vi->rq[qp_index].vq, &vi->rq[qp_index].napi);
virtnet_napi_tx_enable(vi, vi->sq[qp_index].vq, &vi->sq[qp_index].napi);
@@ -3332,7 +3332,7 @@ static int virtnet_rx_resize(struct virtnet_info *vi,
virtnet_rx_pause(vi, rq);
- err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_unmap_free_buf);
+ err = virtqueue_resize(rq->vq, ring_num, virtnet_rq_unmap_free_buf, NULL);
if (err)
netdev_err(vi->dev, "resize rx fail: rx queue index: %d err: %d\n", qindex, err);
@@ -3395,7 +3395,8 @@ static int virtnet_tx_resize(struct virtnet_info *vi, struct send_queue *sq,
virtnet_tx_pause(vi, sq);
- err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_buf);
+ err = virtqueue_resize(sq->vq, ring_num, virtnet_sq_free_unused_buf,
+ virtnet_sq_free_unused_buf_done);
if (err)
netdev_err(vi->dev, "resize tx fail: tx queue index: %d err: %d\n", qindex, err);
@@ -5710,7 +5711,7 @@ static int virtnet_rq_bind_xsk_pool(struct virtnet_info *vi, struct receive_queu
virtnet_rx_pause(vi, rq);
- err = virtqueue_reset(rq->vq, virtnet_rq_unmap_free_buf);
+ err = virtqueue_reset(rq->vq, virtnet_rq_unmap_free_buf, NULL);
if (err) {
netdev_err(vi->dev, "reset rx fail: rx queue index: %d err: %d\n", qindex, err);
@@ -5739,7 +5740,8 @@ static int virtnet_sq_bind_xsk_pool(struct virtnet_info *vi,
virtnet_tx_pause(vi, sq);
- err = virtqueue_reset(sq->vq, virtnet_sq_free_unused_buf);
+ err = virtqueue_reset(sq->vq, virtnet_sq_free_unused_buf,
+ virtnet_sq_free_unused_buf_done);
if (err) {
netdev_err(vi->dev, "reset tx fail: tx queue index: %d err: %d\n", qindex, err);
pool = NULL;
@@ -6214,7 +6216,7 @@ static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf)
{
struct virtnet_info *vi = vq->vdev->priv;
struct send_queue *sq;
- int i = vq2rxq(vq);
+ int i = vq2txq(vq);
sq = &vi->sq[i];
@@ -6234,6 +6236,14 @@ static void virtnet_sq_free_unused_buf(struct virtqueue *vq, void *buf)
}
}
+static void virtnet_sq_free_unused_buf_done(struct virtqueue *vq)
+{
+ struct virtnet_info *vi = vq->vdev->priv;
+ int i = vq2txq(vq);
+
+ netdev_tx_reset_queue(netdev_get_tx_queue(vi->dev, i));
+}
+
static void free_unused_bufs(struct virtnet_info *vi)
{
void *buf;
@@ -6966,11 +6976,20 @@ free:
static void remove_vq_common(struct virtnet_info *vi)
{
+ int i;
+
virtio_reset_device(vi->vdev);
/* Free unused buffers in both send and recv, if any. */
free_unused_bufs(vi);
+ /*
+ * Rule of thumb is netdev_tx_reset_queue() should follow any
+ * skb freeing not followed by netdev_tx_completed_queue()
+ */
+ for (i = 0; i < vi->max_queue_pairs; i++)
+ netdev_tx_reset_queue(netdev_get_tx_queue(vi->dev, i));
+
free_receive_bufs(vi);
free_receive_page_frags(vi);
diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c
index 67d25f4f94ef..ca81b212a246 100644
--- a/drivers/net/vrf.c
+++ b/drivers/net/vrf.c
@@ -122,16 +122,6 @@ struct net_vrf {
int ifindex;
};
-static void vrf_rx_stats(struct net_device *dev, int len)
-{
- struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
-
- u64_stats_update_begin(&dstats->syncp);
- u64_stats_inc(&dstats->rx_packets);
- u64_stats_add(&dstats->rx_bytes, len);
- u64_stats_update_end(&dstats->syncp);
-}
-
static void vrf_tx_error(struct net_device *vrf_dev, struct sk_buff *skb)
{
vrf_dev->stats.tx_errors++;
@@ -369,7 +359,7 @@ static bool qdisc_tx_is_default(const struct net_device *dev)
static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev,
struct dst_entry *dst)
{
- int len = skb->len;
+ unsigned int len = skb->len;
skb_orphan(skb);
@@ -382,15 +372,10 @@ static int vrf_local_xmit(struct sk_buff *skb, struct net_device *dev,
skb->protocol = eth_type_trans(skb, dev);
- if (likely(__netif_rx(skb) == NET_RX_SUCCESS)) {
- vrf_rx_stats(dev, len);
- } else {
- struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
-
- u64_stats_update_begin(&dstats->syncp);
- u64_stats_inc(&dstats->rx_drops);
- u64_stats_update_end(&dstats->syncp);
- }
+ if (likely(__netif_rx(skb) == NET_RX_SUCCESS))
+ dev_dstats_rx_add(dev, len);
+ else
+ dev_dstats_rx_dropped(dev);
return NETDEV_TX_OK;
}
@@ -578,20 +563,14 @@ static netdev_tx_t is_ip_tx_frame(struct sk_buff *skb, struct net_device *dev)
static netdev_tx_t vrf_xmit(struct sk_buff *skb, struct net_device *dev)
{
- struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
-
- int len = skb->len;
- netdev_tx_t ret = is_ip_tx_frame(skb, dev);
-
- u64_stats_update_begin(&dstats->syncp);
- if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) {
+ unsigned int len = skb->len;
+ netdev_tx_t ret;
- u64_stats_inc(&dstats->tx_packets);
- u64_stats_add(&dstats->tx_bytes, len);
- } else {
- u64_stats_inc(&dstats->tx_drops);
- }
- u64_stats_update_end(&dstats->syncp);
+ ret = is_ip_tx_frame(skb, dev);
+ if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN))
+ dev_dstats_tx_add(dev, len);
+ else
+ dev_dstats_tx_dropped(dev);
return ret;
}
@@ -1364,7 +1343,7 @@ static struct sk_buff *vrf_ip6_rcv(struct net_device *vrf_dev,
if (!is_ndisc) {
struct net_device *orig_dev = skb->dev;
- vrf_rx_stats(vrf_dev, skb->len);
+ dev_dstats_rx_add(vrf_dev, skb->len);
skb->dev = vrf_dev;
skb->skb_iif = vrf_dev->ifindex;
@@ -1420,7 +1399,7 @@ static struct sk_buff *vrf_ip_rcv(struct net_device *vrf_dev,
goto out;
}
- vrf_rx_stats(vrf_dev, skb->len);
+ dev_dstats_rx_add(vrf_dev, skb->len);
if (!list_empty(&vrf_dev->ptype_all)) {
int err;
diff --git a/drivers/net/vxlan/vxlan_core.c b/drivers/net/vxlan/vxlan_core.c
index 9ea63059d52d..05c10acb2a57 100644
--- a/drivers/net/vxlan/vxlan_core.c
+++ b/drivers/net/vxlan/vxlan_core.c
@@ -622,9 +622,9 @@ static int vxlan_fdb_append(struct vxlan_fdb *f,
return 1;
}
-static bool vxlan_parse_gpe_proto(struct vxlanhdr *hdr, __be16 *protocol)
+static bool vxlan_parse_gpe_proto(const struct vxlanhdr *hdr, __be16 *protocol)
{
- struct vxlanhdr_gpe *gpe = (struct vxlanhdr_gpe *)hdr;
+ const struct vxlanhdr_gpe *gpe = (const struct vxlanhdr_gpe *)hdr;
/* Need to have Next Protocol set for interfaces in GPE mode. */
if (!gpe->np_applied)
@@ -1352,6 +1352,7 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
struct net_device *dev,
struct net_device *filter_dev, int *idx)
{
+ struct ndo_fdb_dump_context *ctx = (void *)cb->ctx;
struct vxlan_dev *vxlan = netdev_priv(dev);
unsigned int h;
int err = 0;
@@ -1364,7 +1365,7 @@ static int vxlan_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb,
struct vxlan_rdst *rd;
if (rcu_access_pointer(f->nh)) {
- if (*idx < cb->args[2])
+ if (*idx < ctx->fdb_idx)
goto skip_nh;
err = vxlan_fdb_info(skb, vxlan, f,
NETLINK_CB(cb->skb).portid,
@@ -1381,7 +1382,7 @@ skip_nh:
}
list_for_each_entry_rcu(rd, &f->remotes, list) {
- if (*idx < cb->args[2])
+ if (*idx < ctx->fdb_idx)
goto skip;
err = vxlan_fdb_info(skb, vxlan, f,
@@ -1554,18 +1555,17 @@ static void vxlan_sock_release(struct vxlan_dev *vxlan)
#endif
}
-static enum skb_drop_reason vxlan_remcsum(struct vxlanhdr *unparsed,
- struct sk_buff *skb,
- u32 vxflags)
+static enum skb_drop_reason vxlan_remcsum(struct sk_buff *skb, u32 vxflags)
{
+ const struct vxlanhdr *vh = vxlan_hdr(skb);
enum skb_drop_reason reason;
size_t start, offset;
- if (!(unparsed->vx_flags & VXLAN_HF_RCO) || skb->remcsum_offload)
- goto out;
+ if (!(vh->vx_flags & VXLAN_HF_RCO) || skb->remcsum_offload)
+ return SKB_NOT_DROPPED_YET;
- start = vxlan_rco_start(unparsed->vx_vni);
- offset = start + vxlan_rco_offset(unparsed->vx_vni);
+ start = vxlan_rco_start(vh->vx_vni);
+ offset = start + vxlan_rco_offset(vh->vx_vni);
reason = pskb_may_pull_reason(skb, offset + sizeof(u16));
if (reason)
@@ -1573,22 +1573,20 @@ static enum skb_drop_reason vxlan_remcsum(struct vxlanhdr *unparsed,
skb_remcsum_process(skb, (void *)(vxlan_hdr(skb) + 1), start, offset,
!!(vxflags & VXLAN_F_REMCSUM_NOPARTIAL));
-out:
- unparsed->vx_flags &= ~VXLAN_HF_RCO;
- unparsed->vx_vni &= VXLAN_VNI_MASK;
-
return SKB_NOT_DROPPED_YET;
}
-static void vxlan_parse_gbp_hdr(struct vxlanhdr *unparsed,
- struct sk_buff *skb, u32 vxflags,
+static void vxlan_parse_gbp_hdr(struct sk_buff *skb, u32 vxflags,
struct vxlan_metadata *md)
{
- struct vxlanhdr_gbp *gbp = (struct vxlanhdr_gbp *)unparsed;
+ const struct vxlanhdr *vh = vxlan_hdr(skb);
+ const struct vxlanhdr_gbp *gbp;
struct metadata_dst *tun_dst;
- if (!(unparsed->vx_flags & VXLAN_HF_GBP))
- goto out;
+ gbp = (const struct vxlanhdr_gbp *)vh;
+
+ if (!(vh->vx_flags & VXLAN_HF_GBP))
+ return;
md->gbp = ntohs(gbp->policy_id);
@@ -1607,8 +1605,6 @@ static void vxlan_parse_gbp_hdr(struct vxlanhdr *unparsed,
/* In flow-based mode, GBP is carried in dst_metadata */
if (!(vxflags & VXLAN_F_COLLECT_METADATA))
skb->mark = md->gbp;
-out:
- unparsed->vx_flags &= ~VXLAN_GBP_USED_BITS;
}
static enum skb_drop_reason vxlan_set_mac(struct vxlan_dev *vxlan,
@@ -1672,9 +1668,9 @@ static bool vxlan_ecn_decapsulate(struct vxlan_sock *vs, void *oiph,
static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
{
struct vxlan_vni_node *vninode = NULL;
+ const struct vxlanhdr *vh;
struct vxlan_dev *vxlan;
struct vxlan_sock *vs;
- struct vxlanhdr unparsed;
struct vxlan_metadata _md;
struct vxlan_metadata *md = &_md;
__be16 protocol = htons(ETH_P_TEB);
@@ -1689,24 +1685,21 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
if (reason)
goto drop;
- unparsed = *vxlan_hdr(skb);
+ vh = vxlan_hdr(skb);
/* VNI flag always required to be set */
- if (!(unparsed.vx_flags & VXLAN_HF_VNI)) {
+ if (!(vh->vx_flags & VXLAN_HF_VNI)) {
netdev_dbg(skb->dev, "invalid vxlan flags=%#x vni=%#x\n",
- ntohl(vxlan_hdr(skb)->vx_flags),
- ntohl(vxlan_hdr(skb)->vx_vni));
+ ntohl(vh->vx_flags), ntohl(vh->vx_vni));
reason = SKB_DROP_REASON_VXLAN_INVALID_HDR;
/* Return non vxlan pkt */
goto drop;
}
- unparsed.vx_flags &= ~VXLAN_HF_VNI;
- unparsed.vx_vni &= ~VXLAN_VNI_MASK;
vs = rcu_dereference_sk_user_data(sk);
if (!vs)
goto drop;
- vni = vxlan_vni(vxlan_hdr(skb)->vx_vni);
+ vni = vxlan_vni(vh->vx_vni);
vxlan = vxlan_vs_find_vni(vs, skb->dev->ifindex, vni, &vninode);
if (!vxlan) {
@@ -1714,13 +1707,27 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
goto drop;
}
- /* For backwards compatibility, only allow reserved fields to be
- * used by VXLAN extensions if explicitly requested.
- */
- if (vs->flags & VXLAN_F_GPE) {
- if (!vxlan_parse_gpe_proto(&unparsed, &protocol))
+ if (vh->vx_flags & vxlan->cfg.reserved_bits.vx_flags ||
+ vh->vx_vni & vxlan->cfg.reserved_bits.vx_vni) {
+ /* If the header uses bits besides those enabled by the
+ * netdevice configuration, treat this as a malformed packet.
+ * This behavior diverges from VXLAN RFC (RFC7348) which
+ * stipulates that bits in reserved in reserved fields are to be
+ * ignored. The approach here maintains compatibility with
+ * previous stack code, and also is more robust and provides a
+ * little more security in adding extensions to VXLAN.
+ */
+ reason = SKB_DROP_REASON_VXLAN_INVALID_HDR;
+ DEV_STATS_INC(vxlan->dev, rx_frame_errors);
+ DEV_STATS_INC(vxlan->dev, rx_errors);
+ vxlan_vnifilter_count(vxlan, vni, vninode,
+ VXLAN_VNI_STATS_RX_ERRORS, 0);
+ goto drop;
+ }
+
+ if (vxlan->cfg.flags & VXLAN_F_GPE) {
+ if (!vxlan_parse_gpe_proto(vh, &protocol))
goto drop;
- unparsed.vx_flags &= ~VXLAN_GPE_USED_BITS;
raw_proto = true;
}
@@ -1730,8 +1737,8 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
goto drop;
}
- if (vs->flags & VXLAN_F_REMCSUM_RX) {
- reason = vxlan_remcsum(&unparsed, skb, vs->flags);
+ if (vxlan->cfg.flags & VXLAN_F_REMCSUM_RX) {
+ reason = vxlan_remcsum(skb, vxlan->cfg.flags);
if (unlikely(reason))
goto drop;
}
@@ -1756,25 +1763,12 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
memset(md, 0, sizeof(*md));
}
- if (vs->flags & VXLAN_F_GBP)
- vxlan_parse_gbp_hdr(&unparsed, skb, vs->flags, md);
+ if (vxlan->cfg.flags & VXLAN_F_GBP)
+ vxlan_parse_gbp_hdr(skb, vxlan->cfg.flags, md);
/* Note that GBP and GPE can never be active together. This is
* ensured in vxlan_dev_configure.
*/
- if (unparsed.vx_flags || unparsed.vx_vni) {
- /* If there are any unprocessed flags remaining treat
- * this as a malformed packet. This behavior diverges from
- * VXLAN RFC (RFC7348) which stipulates that bits in reserved
- * in reserved fields are to be ignored. The approach here
- * maintains compatibility with previous stack code, and also
- * is more robust and provides a little more security in
- * adding extensions to VXLAN.
- */
- reason = SKB_DROP_REASON_VXLAN_INVALID_HDR;
- goto drop;
- }
-
if (!raw_proto) {
reason = vxlan_set_mac(vxlan, vs, skb, vni);
if (reason)
@@ -1818,14 +1812,14 @@ static int vxlan_rcv(struct sock *sk, struct sk_buff *skb)
if (unlikely(!(vxlan->dev->flags & IFF_UP))) {
rcu_read_unlock();
- dev_core_stats_rx_dropped_inc(vxlan->dev);
+ dev_dstats_rx_dropped(vxlan->dev);
vxlan_vnifilter_count(vxlan, vni, vninode,
VXLAN_VNI_STATS_RX_DROPS, 0);
reason = SKB_DROP_REASON_DEV_READY;
goto drop;
}
- dev_sw_netstats_rx_add(vxlan->dev, skb->len);
+ dev_dstats_rx_add(vxlan->dev, skb->len);
vxlan_vnifilter_count(vxlan, vni, vninode, VXLAN_VNI_STATS_RX, skb->len);
gro_cells_receive(&vxlan->gro_cells, skb);
@@ -1880,7 +1874,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
goto out;
if (!pskb_may_pull(skb, arp_hdr_len(dev))) {
- dev_core_stats_tx_dropped_inc(dev);
+ dev_dstats_tx_dropped(dev);
vxlan_vnifilter_count(vxlan, vni, NULL,
VXLAN_VNI_STATS_TX_DROPS, 0);
goto out;
@@ -1938,7 +1932,7 @@ static int arp_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
reply->pkt_type = PACKET_HOST;
if (netif_rx(reply) == NET_RX_DROP) {
- dev_core_stats_rx_dropped_inc(dev);
+ dev_dstats_rx_dropped(dev);
vxlan_vnifilter_count(vxlan, vni, NULL,
VXLAN_VNI_STATS_RX_DROPS, 0);
}
@@ -2097,7 +2091,7 @@ static int neigh_reduce(struct net_device *dev, struct sk_buff *skb, __be32 vni)
goto out;
if (netif_rx(reply) == NET_RX_DROP) {
- dev_core_stats_rx_dropped_inc(dev);
+ dev_dstats_rx_dropped(dev);
vxlan_vnifilter_count(vxlan, vni, NULL,
VXLAN_VNI_STATS_RX_DROPS, 0);
}
@@ -2271,8 +2265,8 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
{
union vxlan_addr loopback;
union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip;
+ unsigned int len = skb->len;
struct net_device *dev;
- int len = skb->len;
skb->pkt_type = PACKET_HOST;
skb->encapsulation = 0;
@@ -2299,16 +2293,16 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
if ((dst_vxlan->cfg.flags & VXLAN_F_LEARN) && snoop)
vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni);
- dev_sw_netstats_tx_add(src_vxlan->dev, 1, len);
+ dev_dstats_tx_add(src_vxlan->dev, len);
vxlan_vnifilter_count(src_vxlan, vni, NULL, VXLAN_VNI_STATS_TX, len);
if (__netif_rx(skb) == NET_RX_SUCCESS) {
- dev_sw_netstats_rx_add(dst_vxlan->dev, len);
+ dev_dstats_rx_add(dst_vxlan->dev, len);
vxlan_vnifilter_count(dst_vxlan, vni, NULL, VXLAN_VNI_STATS_RX,
len);
} else {
drop:
- dev_core_stats_rx_dropped_inc(dev);
+ dev_dstats_rx_dropped(dev);
vxlan_vnifilter_count(dst_vxlan, vni, NULL,
VXLAN_VNI_STATS_RX_DROPS, 0);
}
@@ -2621,7 +2615,7 @@ out_unlock:
return;
drop:
- dev_core_stats_tx_dropped_inc(dev);
+ dev_dstats_tx_dropped(dev);
vxlan_vnifilter_count(vxlan, vni, NULL, VXLAN_VNI_STATS_TX_DROPS, 0);
kfree_skb_reason(skb, reason);
return;
@@ -2666,7 +2660,7 @@ static void vxlan_xmit_nh(struct sk_buff *skb, struct net_device *dev,
return;
drop:
- dev_core_stats_tx_dropped_inc(dev);
+ dev_dstats_tx_dropped(dev);
vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
VXLAN_VNI_STATS_TX_DROPS, 0);
dev_kfree_skb(skb);
@@ -2704,7 +2698,7 @@ static netdev_tx_t vxlan_xmit_nhid(struct sk_buff *skb, struct net_device *dev,
return NETDEV_TX_OK;
drop:
- dev_core_stats_tx_dropped_inc(dev);
+ dev_dstats_tx_dropped(dev);
vxlan_vnifilter_count(netdev_priv(dev), vni, NULL,
VXLAN_VNI_STATS_TX_DROPS, 0);
dev_kfree_skb(skb);
@@ -2801,10 +2795,10 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
!is_multicast_ether_addr(eth->h_dest))
vxlan_fdb_miss(vxlan, eth->h_dest);
- dev_core_stats_tx_dropped_inc(dev);
+ dev_dstats_tx_dropped(dev);
vxlan_vnifilter_count(vxlan, vni, NULL,
VXLAN_VNI_STATS_TX_DROPS, 0);
- kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
+ kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
return NETDEV_TX_OK;
}
}
@@ -2827,7 +2821,7 @@ static netdev_tx_t vxlan_xmit(struct sk_buff *skb, struct net_device *dev)
if (fdst)
vxlan_xmit_one(skb, dev, vni, fdst, did_rsc);
else
- kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
+ kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
}
return NETDEV_TX_OK;
@@ -3371,7 +3365,7 @@ static void vxlan_setup(struct net_device *dev)
dev->min_mtu = ETH_MIN_MTU;
dev->max_mtu = ETH_MAX_MTU;
- dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
INIT_LIST_HEAD(&vxlan->next);
timer_setup(&vxlan->age_timer, vxlan_cleanup, TIMER_DEFERRABLE);
@@ -3435,6 +3429,7 @@ static const struct nla_policy vxlan_policy[IFLA_VXLAN_MAX + 1] = {
[IFLA_VXLAN_VNIFILTER] = { .type = NLA_U8 },
[IFLA_VXLAN_LOCALBYPASS] = NLA_POLICY_MAX(NLA_U8, 1),
[IFLA_VXLAN_LABEL_POLICY] = NLA_POLICY_MAX(NLA_U32, VXLAN_LABEL_MAX),
+ [IFLA_VXLAN_RESERVED_BITS] = NLA_POLICY_EXACT_LEN(sizeof(struct vxlanhdr)),
};
static int vxlan_validate(struct nlattr *tb[], struct nlattr *data[],
@@ -4070,6 +4065,10 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
struct net_device *dev, struct vxlan_config *conf,
bool changelink, struct netlink_ext_ack *extack)
{
+ struct vxlanhdr used_bits = {
+ .vx_flags = VXLAN_HF_VNI,
+ .vx_vni = VXLAN_VNI_MASK,
+ };
struct vxlan_dev *vxlan = netdev_priv(dev);
int err = 0;
@@ -4296,6 +4295,8 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
extack);
if (err)
return err;
+ used_bits.vx_flags |= VXLAN_HF_RCO;
+ used_bits.vx_vni |= ~VXLAN_VNI_MASK;
}
if (data[IFLA_VXLAN_GBP]) {
@@ -4303,6 +4304,7 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
VXLAN_F_GBP, changelink, false, extack);
if (err)
return err;
+ used_bits.vx_flags |= VXLAN_GBP_USED_BITS;
}
if (data[IFLA_VXLAN_GPE]) {
@@ -4311,6 +4313,46 @@ static int vxlan_nl2conf(struct nlattr *tb[], struct nlattr *data[],
extack);
if (err)
return err;
+
+ used_bits.vx_flags |= VXLAN_GPE_USED_BITS;
+ }
+
+ if (data[IFLA_VXLAN_RESERVED_BITS]) {
+ struct vxlanhdr reserved_bits;
+
+ if (changelink) {
+ NL_SET_ERR_MSG_ATTR(extack,
+ data[IFLA_VXLAN_RESERVED_BITS],
+ "Cannot change reserved_bits");
+ return -EOPNOTSUPP;
+ }
+
+ nla_memcpy(&reserved_bits, data[IFLA_VXLAN_RESERVED_BITS],
+ sizeof(reserved_bits));
+ if (used_bits.vx_flags & reserved_bits.vx_flags ||
+ used_bits.vx_vni & reserved_bits.vx_vni) {
+ __be64 ub_be64, rb_be64;
+
+ memcpy(&ub_be64, &used_bits, sizeof(ub_be64));
+ memcpy(&rb_be64, &reserved_bits, sizeof(rb_be64));
+
+ NL_SET_ERR_MSG_ATTR_FMT(extack,
+ data[IFLA_VXLAN_RESERVED_BITS],
+ "Used bits %#018llx cannot overlap reserved bits %#018llx",
+ be64_to_cpu(ub_be64),
+ be64_to_cpu(rb_be64));
+ return -EINVAL;
+ }
+
+ conf->reserved_bits = reserved_bits;
+ } else {
+ /* For backwards compatibility, only allow reserved fields to be
+ * used by VXLAN extensions if explicitly requested.
+ */
+ conf->reserved_bits = (struct vxlanhdr) {
+ .vx_flags = ~used_bits.vx_flags,
+ .vx_vni = ~used_bits.vx_vni,
+ };
}
if (data[IFLA_VXLAN_REMCSUM_NOPARTIAL]) {
@@ -4497,6 +4539,8 @@ static size_t vxlan_get_size(const struct net_device *dev)
nla_total_size(0) + /* IFLA_VXLAN_GPE */
nla_total_size(0) + /* IFLA_VXLAN_REMCSUM_NOPARTIAL */
nla_total_size(sizeof(__u8)) + /* IFLA_VXLAN_VNIFILTER */
+ /* IFLA_VXLAN_RESERVED_BITS */
+ nla_total_size(sizeof(struct vxlanhdr)) +
0;
}
@@ -4599,6 +4643,11 @@ static int vxlan_fill_info(struct sk_buff *skb, const struct net_device *dev)
!!(vxlan->cfg.flags & VXLAN_F_VNIFILTER)))
goto nla_put_failure;
+ if (nla_put(skb, IFLA_VXLAN_RESERVED_BITS,
+ sizeof(vxlan->cfg.reserved_bits),
+ &vxlan->cfg.reserved_bits))
+ goto nla_put_failure;
+
return 0;
nla_put_failure:
diff --git a/drivers/net/vxlan/vxlan_mdb.c b/drivers/net/vxlan/vxlan_mdb.c
index 8735891ee128..816ab1aa0526 100644
--- a/drivers/net/vxlan/vxlan_mdb.c
+++ b/drivers/net/vxlan/vxlan_mdb.c
@@ -1712,7 +1712,7 @@ netdev_tx_t vxlan_mdb_xmit(struct vxlan_dev *vxlan,
vxlan_xmit_one(skb, vxlan->dev, src_vni,
rcu_dereference(fremote->rd), false);
else
- kfree_skb_reason(skb, SKB_DROP_REASON_VXLAN_NO_REMOTE);
+ kfree_skb_reason(skb, SKB_DROP_REASON_NO_TX_TARGET);
return NETDEV_TX_OK;
}
diff --git a/drivers/net/wan/framer/framer-core.c b/drivers/net/wan/framer/framer-core.c
index f547c22e26ac..58f5143359df 100644
--- a/drivers/net/wan/framer/framer-core.c
+++ b/drivers/net/wan/framer/framer-core.c
@@ -732,8 +732,8 @@ EXPORT_SYMBOL_GPL(devm_framer_create);
/**
* framer_provider_simple_of_xlate() - returns the framer instance from framer provider
- * @dev: the framer provider device
- * @args: of_phandle_args (not used here)
+ * @dev: the framer provider device (not used here)
+ * @args: of_phandle_args
*
* Intended to be used by framer provider for the common case where #framer-cells is
* 0. For other cases where #framer-cells is greater than '0', the framer provider
@@ -743,21 +743,14 @@ EXPORT_SYMBOL_GPL(devm_framer_create);
struct framer *framer_provider_simple_of_xlate(struct device *dev,
const struct of_phandle_args *args)
{
- struct class_dev_iter iter;
- struct framer *framer;
-
- class_dev_iter_init(&iter, &framer_class, NULL, NULL);
- while ((dev = class_dev_iter_next(&iter))) {
- framer = dev_to_framer(dev);
- if (args->np != framer->dev.of_node)
- continue;
+ struct device *target_dev;
- class_dev_iter_exit(&iter);
- return framer;
- }
+ target_dev = class_find_device_by_of_node(&framer_class, args->np);
+ if (!target_dev)
+ return ERR_PTR(-ENODEV);
- class_dev_iter_exit(&iter);
- return ERR_PTR(-ENODEV);
+ put_device(target_dev);
+ return dev_to_framer(target_dev);
}
EXPORT_SYMBOL_GPL(framer_provider_simple_of_xlate);
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index be67382c00f6..c576bbba52bf 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -123,6 +123,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.tx_ring_size = DP_TCL_DATA_RING_SIZE,
.smp2p_wow_exit = false,
.support_dual_stations = false,
+ .pdev_suspend = false,
},
{
.hw_rev = ATH11K_HW_IPQ6018_HW10,
@@ -207,6 +208,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = false,
.support_fw_mac_sequence = false,
.support_dual_stations = false,
+ .pdev_suspend = false,
},
{
.name = "qca6390 hw2.0",
@@ -296,6 +298,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = false,
.support_fw_mac_sequence = true,
.support_dual_stations = true,
+ .pdev_suspend = false,
},
{
.name = "qcn9074 hw1.0",
@@ -379,6 +382,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = false,
.support_fw_mac_sequence = false,
.support_dual_stations = false,
+ .pdev_suspend = false,
},
{
.name = "wcn6855 hw2.0",
@@ -468,6 +472,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = false,
.support_fw_mac_sequence = true,
.support_dual_stations = true,
+ .pdev_suspend = false,
},
{
.name = "wcn6855 hw2.1",
@@ -555,6 +560,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = false,
.support_fw_mac_sequence = true,
.support_dual_stations = true,
+ .pdev_suspend = false,
},
{
.name = "wcn6750 hw1.0",
@@ -637,6 +643,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = true,
.support_fw_mac_sequence = true,
.support_dual_stations = false,
+ .pdev_suspend = true,
},
{
.hw_rev = ATH11K_HW_IPQ5018_HW10,
@@ -719,6 +726,7 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.smp2p_wow_exit = false,
.support_fw_mac_sequence = false,
.support_dual_stations = false,
+ .pdev_suspend = false,
},
{
.name = "qca2066 hw2.1",
@@ -809,6 +817,94 @@ static const struct ath11k_hw_params ath11k_hw_params[] = {
.support_fw_mac_sequence = true,
.support_dual_stations = true,
},
+ {
+ .name = "qca6698aq hw2.1",
+ .hw_rev = ATH11K_HW_QCA6698AQ_HW21,
+ .fw = {
+ .dir = "QCA6698AQ/hw2.1",
+ .board_size = 256 * 1024,
+ .cal_offset = 128 * 1024,
+ },
+ .max_radios = 3,
+ .bdf_addr = 0x4B0C0000,
+ .hw_ops = &wcn6855_ops,
+ .ring_mask = &ath11k_hw_ring_mask_qca6390,
+ .internal_sleep_clock = true,
+ .regs = &wcn6855_regs,
+ .qmi_service_ins_id = ATH11K_QMI_WLFW_SERVICE_INS_ID_V01_QCA6390,
+ .host_ce_config = ath11k_host_ce_config_qca6390,
+ .ce_count = 9,
+ .target_ce_config = ath11k_target_ce_config_wlan_qca6390,
+ .target_ce_count = 9,
+ .svc_to_ce_map = ath11k_target_service_to_ce_map_wlan_qca6390,
+ .svc_to_ce_map_len = 14,
+ .single_pdev_only = true,
+ .rxdma1_enable = false,
+ .num_rxdma_per_pdev = 2,
+ .rx_mac_buf_ring = true,
+ .vdev_start_delay = true,
+ .htt_peer_map_v2 = false,
+
+ .spectral = {
+ .fft_sz = 0,
+ .fft_pad_sz = 0,
+ .summary_pad_sz = 0,
+ .fft_hdr_len = 0,
+ .max_fft_bins = 0,
+ .fragment_160mhz = false,
+ },
+
+ .interface_modes = BIT(NL80211_IFTYPE_STATION) |
+ BIT(NL80211_IFTYPE_AP) |
+ BIT(NL80211_IFTYPE_P2P_DEVICE) |
+ BIT(NL80211_IFTYPE_P2P_CLIENT) |
+ BIT(NL80211_IFTYPE_P2P_GO),
+ .supports_monitor = false,
+ .supports_shadow_regs = true,
+ .idle_ps = true,
+ .supports_sta_ps = true,
+ .coldboot_cal_mm = false,
+ .coldboot_cal_ftm = false,
+ .cbcal_restart_fw = false,
+ .fw_mem_mode = 0,
+ .num_vdevs = 2 + 1,
+ .num_peers = 512,
+ .supports_suspend = true,
+ .hal_desc_sz = sizeof(struct hal_rx_desc_wcn6855),
+ .supports_regdb = true,
+ .fix_l1ss = false,
+ .credit_flow = true,
+ .max_tx_ring = DP_TCL_NUM_RING_MAX_QCA6390,
+ .hal_params = &ath11k_hw_hal_params_qca6390,
+ .supports_dynamic_smps_6ghz = false,
+ .alloc_cacheable_memory = false,
+ .supports_rssi_stats = true,
+ .fw_wmi_diag_event = true,
+ .current_cc_support = true,
+ .dbr_debug_support = false,
+ .global_reset = true,
+ .bios_sar_capa = &ath11k_hw_sar_capa_wcn6855,
+ .m3_fw_support = true,
+ .fixed_bdf_addr = false,
+ .fixed_mem_region = false,
+ .static_window_map = false,
+ .hybrid_bus_type = false,
+ .fixed_fw_mem = false,
+ .support_off_channel_tx = true,
+ .supports_multi_bssid = true,
+
+ .sram_dump = {
+ .start = 0x01400000,
+ .end = 0x0177ffff,
+ },
+
+ .tcl_ring_retry = true,
+ .tx_ring_size = DP_TCL_DATA_RING_SIZE,
+ .smp2p_wow_exit = false,
+ .support_fw_mac_sequence = true,
+ .support_dual_stations = true,
+ .pdev_suspend = false,
+ },
};
static inline struct ath11k_pdev *ath11k_core_get_single_pdev(struct ath11k_base *ab)
@@ -1669,11 +1765,47 @@ err_pdev_debug:
return ret;
}
+static void ath11k_core_pdev_suspend_target(struct ath11k_base *ab)
+{
+ struct ath11k *ar;
+ struct ath11k_pdev *pdev;
+ unsigned long time_left;
+ int ret;
+ int i;
+
+ if (!ab->hw_params.pdev_suspend)
+ return;
+
+ for (i = 0; i < ab->num_radios; i++) {
+ pdev = &ab->pdevs[i];
+ ar = pdev->ar;
+
+ reinit_completion(&ab->htc_suspend);
+
+ ret = ath11k_wmi_pdev_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR,
+ pdev->pdev_id);
+ if (ret) {
+ ath11k_warn(ab, "could not suspend target :%d\n", ret);
+ /* pointless to try other pdevs */
+ return;
+ }
+
+ time_left = wait_for_completion_timeout(&ab->htc_suspend, 3 * HZ);
+
+ if (!time_left) {
+ ath11k_warn(ab, "suspend timed out - target pause event never came\n");
+ /* pointless to try other pdevs */
+ return;
+ }
+ }
+}
+
static void ath11k_core_pdev_destroy(struct ath11k_base *ab)
{
ath11k_spectral_deinit(ab);
ath11k_thermal_unregister(ab);
ath11k_mac_unregister(ab);
+ ath11k_core_pdev_suspend_target(ab);
ath11k_hif_irq_disable(ab);
ath11k_dp_pdev_free(ab);
ath11k_debugfs_pdev_destroy(ab);
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 09c37e19a168..a9dc7fe7765a 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -148,6 +148,7 @@ enum ath11k_hw_rev {
ATH11K_HW_WCN6750_HW10,
ATH11K_HW_IPQ5018_HW10,
ATH11K_HW_QCA2066_HW21,
+ ATH11K_HW_QCA6698AQ_HW21,
};
enum ath11k_firmware_mode {
@@ -340,7 +341,6 @@ struct ath11k_chan_power_info {
* @ap_power_type: type of power (SP/LPI/VLP)
* @num_pwr_levels: number of power levels
* @reg_max: Array of maximum TX power (dBm) per PSD value
- * @ap_constraint_power: AP constraint power (dBm)
* @tpe: TPE values processed from TPE IE
* @chan_power_info: power info to send to firmware
*/
@@ -350,7 +350,6 @@ struct ath11k_reg_tpc_power_info {
enum wmi_reg_6ghz_ap_type ap_power_type;
u8 num_pwr_levels;
u8 reg_max[ATH11K_NUM_PWR_LEVELS];
- u8 ap_constraint_power;
s8 tpe[ATH11K_NUM_PWR_LEVELS];
struct ath11k_chan_power_info chan_power_info[ATH11K_NUM_PWR_LEVELS];
};
@@ -370,7 +369,6 @@ struct ath11k_vif {
struct ath11k *ar;
struct ieee80211_vif *vif;
- u16 tx_seq_no;
struct wmi_wmm_params_all_arg wmm_params;
struct list_head list;
union {
diff --git a/drivers/net/wireless/ath/ath11k/dp.h b/drivers/net/wireless/ath/ath11k/dp.h
index 65d2bc0687c8..f777314db8b3 100644
--- a/drivers/net/wireless/ath/ath11k/dp.h
+++ b/drivers/net/wireless/ath/ath11k/dp.h
@@ -165,7 +165,6 @@ struct ath11k_mon_data {
struct ath11k_pdev_mon_stats rx_mon_stats;
/* lock for monitor data */
spinlock_t mon_lock;
- struct sk_buff_head rx_status_q;
};
struct ath11k_pdev_dp {
diff --git a/drivers/net/wireless/ath/ath11k/dp_rx.c b/drivers/net/wireless/ath/ath11k/dp_rx.c
index 40088e62572e..029ecf51c9ef 100644
--- a/drivers/net/wireless/ath/ath11k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath11k/dp_rx.c
@@ -3872,6 +3872,7 @@ int ath11k_dp_process_rx_err(struct ath11k_base *ab, struct napi_struct *napi,
ath11k_hal_rx_msdu_link_info_get(link_desc_va, &num_msdus, msdu_cookies,
&rbm);
if (rbm != HAL_RX_BUF_RBM_WBM_IDLE_DESC_LIST &&
+ rbm != HAL_RX_BUF_RBM_SW1_BM &&
rbm != HAL_RX_BUF_RBM_SW3_BM) {
ab->soc_stats.invalid_rbm++;
ath11k_warn(ab, "invalid return buffer manager %d\n", rbm);
@@ -4690,11 +4691,12 @@ static void ath11k_dp_mon_get_buf_len(struct hal_rx_msdu_desc_info *info,
}
}
-static u32
-ath11k_dp_rx_mon_mpdu_pop(struct ath11k *ar, int mac_id,
- void *ring_entry, struct sk_buff **head_msdu,
- struct sk_buff **tail_msdu, u32 *npackets,
- u32 *ppdu_id)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+u32 ath11k_dp_rx_mon_mpdu_pop(struct ath11k *ar, int mac_id,
+ void *ring_entry, struct sk_buff **head_msdu,
+ struct sk_buff **tail_msdu, u32 *npackets,
+ u32 *ppdu_id)
{
struct ath11k_pdev_dp *dp = &ar->dp;
struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
@@ -5705,8 +5707,6 @@ static int ath11k_dp_rx_pdev_mon_status_attach(struct ath11k *ar)
struct ath11k_pdev_dp *dp = &ar->dp;
struct ath11k_mon_data *pmon = (struct ath11k_mon_data *)&dp->mon_data;
- skb_queue_head_init(&pmon->rx_status_q);
-
pmon->mon_ppdu_status = DP_PPDU_STATUS_START;
memset(&pmon->rx_mon_stats, 0,
diff --git a/drivers/net/wireless/ath/ath11k/hal.h b/drivers/net/wireless/ath/ath11k/hal.h
index dc8bbe073017..601542410c75 100644
--- a/drivers/net/wireless/ath/ath11k/hal.h
+++ b/drivers/net/wireless/ath/ath11k/hal.h
@@ -700,7 +700,7 @@ enum hal_rx_buf_return_buf_manager {
#define HAL_REO_CMD_FLG_UNBLK_RESOURCE BIT(7)
#define HAL_REO_CMD_FLG_UNBLK_CACHE BIT(8)
-/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO0_UPD_* feilds */
+/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO0_UPD_* fields */
#define HAL_REO_CMD_UPD0_RX_QUEUE_NUM BIT(8)
#define HAL_REO_CMD_UPD0_VLD BIT(9)
#define HAL_REO_CMD_UPD0_ALDC BIT(10)
@@ -725,7 +725,7 @@ enum hal_rx_buf_return_buf_manager {
#define HAL_REO_CMD_UPD0_PN_VALID BIT(29)
#define HAL_REO_CMD_UPD0_PN BIT(30)
-/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO1_* feilds */
+/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO1_* fields */
#define HAL_REO_CMD_UPD1_VLD BIT(16)
#define HAL_REO_CMD_UPD1_ALDC GENMASK(18, 17)
#define HAL_REO_CMD_UPD1_DIS_DUP_DETECTION BIT(19)
@@ -741,7 +741,7 @@ enum hal_rx_buf_return_buf_manager {
#define HAL_REO_CMD_UPD1_PN_HANDLE_ENABLE BIT(30)
#define HAL_REO_CMD_UPD1_IGNORE_AMPDU_FLG BIT(31)
-/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO2_* feilds */
+/* Should be matching with HAL_REO_UPD_RX_QUEUE_INFO2_* fields */
#define HAL_REO_CMD_UPD2_SVLD BIT(10)
#define HAL_REO_CMD_UPD2_SSN GENMASK(22, 11)
#define HAL_REO_CMD_UPD2_SEQ_2K_ERR BIT(23)
diff --git a/drivers/net/wireless/ath/ath11k/hal_rx.c b/drivers/net/wireless/ath/ath11k/hal_rx.c
index 8f7dd43dc1bd..753bd93f0212 100644
--- a/drivers/net/wireless/ath/ath11k/hal_rx.c
+++ b/drivers/net/wireless/ath/ath11k/hal_rx.c
@@ -372,7 +372,8 @@ int ath11k_hal_wbm_desc_parse_err(struct ath11k_base *ab, void *desc,
ret_buf_mgr = FIELD_GET(BUFFER_ADDR_INFO1_RET_BUF_MGR,
wbm_desc->buf_addr_info.info1);
- if (ret_buf_mgr != HAL_RX_BUF_RBM_SW3_BM) {
+ if (ret_buf_mgr != HAL_RX_BUF_RBM_SW1_BM &&
+ ret_buf_mgr != HAL_RX_BUF_RBM_SW3_BM) {
ab->soc_stats.invalid_rbm++;
return -EINVAL;
}
diff --git a/drivers/net/wireless/ath/ath11k/hw.h b/drivers/net/wireless/ath/ath11k/hw.h
index 300322535766..52d9f4c13b13 100644
--- a/drivers/net/wireless/ath/ath11k/hw.h
+++ b/drivers/net/wireless/ath/ath11k/hw.h
@@ -227,6 +227,7 @@ struct ath11k_hw_params {
bool smp2p_wow_exit;
bool support_fw_mac_sequence;
bool support_dual_stations;
+ bool pdev_suspend;
};
struct ath11k_hw_ops {
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index e6acbff06749..1556392f7ad4 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1697,8 +1697,6 @@ static void ath11k_control_beaconing(struct ath11k_vif *arvif,
return;
}
- arvif->tx_seq_no = 0x1000;
-
arvif->aid = 0;
ether_addr_copy(arvif->bssid, info->bssid);
@@ -2230,7 +2228,7 @@ static void ath11k_peer_assoc_h_vht(struct ath11k *ar,
__le16_to_cpu(vht_cap->vht_mcs.tx_mcs_map), vht_mcs_mask);
/* In IPQ8074 platform, VHT mcs rate 10 and 11 is enabled by default.
- * VHT mcs rate 10 and 11 is not suppoerted in 11ac standard.
+ * VHT mcs rate 10 and 11 is not supported in 11ac standard.
* so explicitly disable the VHT MCS rate 10 and 11 in 11ac mode.
*/
arg->tx_mcs_set &= ~IEEE80211_VHT_MCS_SUPPORT_0_11_MASK;
@@ -6952,7 +6950,7 @@ err_vdev_del:
/* Recalc txpower for remaining vdev */
ath11k_mac_txpower_recalc(ar);
- /* TODO: recal traffic pause state based on the available vdevs */
+ /* TODO: recalc traffic pause state based on the available vdevs */
mutex_unlock(&ar->conf_mutex);
}
@@ -9356,6 +9354,7 @@ static int ath11k_fw_stats_request(struct ath11k *ar,
static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
+ unsigned int link_id,
int *dbm)
{
struct ath11k *ar = hw->priv;
diff --git a/drivers/net/wireless/ath/ath11k/mhi.c b/drivers/net/wireless/ath/ath11k/mhi.c
index 6974a551883f..6e45f464a429 100644
--- a/drivers/net/wireless/ath/ath11k/mhi.c
+++ b/drivers/net/wireless/ath/ath11k/mhi.c
@@ -398,6 +398,7 @@ int ath11k_mhi_register(struct ath11k_pci *ab_pci)
case ATH11K_HW_WCN6855_HW20:
case ATH11K_HW_WCN6855_HW21:
case ATH11K_HW_QCA2066_HW21:
+ case ATH11K_HW_QCA6698AQ_HW21:
ath11k_mhi_config = &ath11k_mhi_config_qca6390;
break;
default:
diff --git a/drivers/net/wireless/ath/ath11k/pci.c b/drivers/net/wireless/ath/ath11k/pci.c
index be9d2c69cc41..b93f04973ad7 100644
--- a/drivers/net/wireless/ath/ath11k/pci.c
+++ b/drivers/net/wireless/ath/ath11k/pci.c
@@ -846,6 +846,9 @@ static int ath11k_pci_probe(struct pci_dev *pdev,
case 0x1019D0E1:
ab->hw_rev = ATH11K_HW_QCA2066_HW21;
break;
+ case 0x001e60e1:
+ ab->hw_rev = ATH11K_HW_QCA6698AQ_HW21;
+ break;
default:
ab->hw_rev = ATH11K_HW_WCN6855_HW21;
}
diff --git a/drivers/net/wireless/ath/ath11k/pcic.c b/drivers/net/wireless/ath/ath11k/pcic.c
index debe7c5919ef..3fe77310c71f 100644
--- a/drivers/net/wireless/ath/ath11k/pcic.c
+++ b/drivers/net/wireless/ath/ath11k/pcic.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2019-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "core.h"
@@ -126,6 +126,17 @@ static const struct ath11k_msi_config ath11k_msi_config[] = {
},
.hw_rev = ATH11K_HW_QCA2066_HW21,
},
+ {
+ .total_vectors = 32,
+ .total_users = 4,
+ .users = (struct ath11k_msi_user[]) {
+ { .name = "MHI", .num_vectors = 3, .base_vector = 0 },
+ { .name = "CE", .num_vectors = 10, .base_vector = 3 },
+ { .name = "WAKE", .num_vectors = 1, .base_vector = 13 },
+ { .name = "DP", .num_vectors = 18, .base_vector = 14 },
+ },
+ .hw_rev = ATH11K_HW_QCA6698AQ_HW21,
+ },
};
int ath11k_pcic_init_msi_config(struct ath11k_base *ab)
diff --git a/drivers/net/wireless/ath/ath11k/qmi.c b/drivers/net/wireless/ath/ath11k/qmi.c
index 7a22483b35cd..5759fc521316 100644
--- a/drivers/net/wireless/ath/ath11k/qmi.c
+++ b/drivers/net/wireless/ath/ath11k/qmi.c
@@ -1704,7 +1704,9 @@ static const struct qmi_elem_info qmi_wlfw_fw_init_done_ind_msg_v01_ei[] = {
},
};
-static int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+int ath11k_qmi_host_cap_send(struct ath11k_base *ab)
{
struct qmi_wlanfw_host_cap_req_msg_v01 req;
struct qmi_wlanfw_host_cap_resp_msg_v01 resp;
@@ -2570,7 +2572,9 @@ static void ath11k_qmi_m3_free(struct ath11k_base *ab)
m3_mem->size = 0;
}
-static int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+int ath11k_qmi_wlanfw_m3_info_send(struct ath11k_base *ab)
{
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
struct qmi_wlanfw_m3_info_req_msg_v01 req;
diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c
index 827085a926b2..b6f08755129f 100644
--- a/drivers/net/wireless/ath/ath11k/wow.c
+++ b/drivers/net/wireless/ath/ath11k/wow.c
@@ -148,8 +148,10 @@ static int ath11k_wow_cleanup(struct ath11k *ar)
* 802.11: |4B|dest mac(6B)| 6B |src mac(6B)| 8B |type(2B)| body... |
* +--+------------+----+-----------+---------------+-----------+
*/
-static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
- const struct cfg80211_pkt_pattern *old)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
+ const struct cfg80211_pkt_pattern *old)
{
u8 hdr_8023_pattern[ETH_HLEN] = {};
u8 hdr_8023_bit_mask[ETH_HLEN] = {};
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index c57322221e1d..49d1ac15cb7a 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -22,6 +22,11 @@ unsigned int ath12k_debug_mask;
module_param_named(debug_mask, ath12k_debug_mask, uint, 0644);
MODULE_PARM_DESC(debug_mask, "Debugging mask");
+/* protected with ath12k_hw_group_mutex */
+static struct list_head ath12k_hw_group_list = LIST_HEAD_INIT(ath12k_hw_group_list);
+
+static DEFINE_MUTEX(ath12k_hw_group_mutex);
+
static int ath12k_core_rfkill_config(struct ath12k_base *ab)
{
struct ath12k *ar;
@@ -79,11 +84,17 @@ int ath12k_core_suspend(struct ath12k_base *ab)
ar = ab->pdevs[i].ar;
if (!ar)
continue;
+
+ wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
+
ret = ath12k_mac_wait_tx_complete(ar);
if (ret) {
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
ath12k_warn(ab, "failed to wait tx complete: %d\n", ret);
return ret;
}
+
+ wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
}
/* PM framework skips suspend_late/resume_early callbacks
@@ -593,14 +604,17 @@ u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab)
static void ath12k_core_stop(struct ath12k_base *ab)
{
+ ath12k_core_stopped(ab);
+
if (!test_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags))
ath12k_qmi_firmware_stop(ab);
ath12k_acpi_stop(ab);
+ ath12k_dp_rx_pdev_reo_cleanup(ab);
ath12k_hif_stop(ab);
ath12k_wmi_detach(ab);
- ath12k_dp_rx_pdev_reo_cleanup(ab);
+ ath12k_dp_free(ab);
/* De-Init of components as needed */
}
@@ -702,7 +716,7 @@ err_qmi_deinit:
static void ath12k_core_soc_destroy(struct ath12k_base *ab)
{
- ath12k_dp_free(ab);
+ ath12k_hif_power_down(ab, false);
ath12k_reg_free(ab);
ath12k_debugfs_soc_destroy(ab);
ath12k_qmi_deinit_service(ab);
@@ -712,30 +726,17 @@ static int ath12k_core_pdev_create(struct ath12k_base *ab)
{
int ret;
- ret = ath12k_mac_register(ab);
- if (ret) {
- ath12k_err(ab, "failed register the radio with mac80211: %d\n", ret);
- return ret;
- }
-
ret = ath12k_dp_pdev_alloc(ab);
if (ret) {
ath12k_err(ab, "failed to attach DP pdev: %d\n", ret);
- goto err_mac_unregister;
+ return ret;
}
return 0;
-
-err_mac_unregister:
- ath12k_mac_unregister(ab);
-
- return ret;
}
static void ath12k_core_pdev_destroy(struct ath12k_base *ab)
{
- ath12k_mac_unregister(ab);
- ath12k_hif_irq_disable(ab);
ath12k_dp_pdev_free(ab);
}
@@ -744,6 +745,8 @@ static int ath12k_core_start(struct ath12k_base *ab,
{
int ret;
+ lockdep_assert_held(&ab->core_lock);
+
ret = ath12k_wmi_attach(ab);
if (ret) {
ath12k_err(ab, "failed to attach wmi: %d\n", ret);
@@ -793,19 +796,12 @@ static int ath12k_core_start(struct ath12k_base *ab,
goto err_hif_stop;
}
- ret = ath12k_mac_allocate(ab);
- if (ret) {
- ath12k_err(ab, "failed to create new hw device with mac80211 :%d\n",
- ret);
- goto err_hif_stop;
- }
-
ath12k_dp_cc_config(ab);
ret = ath12k_dp_rx_pdev_reo_setup(ab);
if (ret) {
ath12k_err(ab, "failed to initialize reo destination rings: %d\n", ret);
- goto err_mac_destroy;
+ goto err_hif_stop;
}
ath12k_dp_hal_rx_desc_init(ab);
@@ -844,12 +840,14 @@ static int ath12k_core_start(struct ath12k_base *ab,
/* ACPI is optional so continue in case of an error */
ath12k_dbg(ab, ATH12K_DBG_BOOT, "acpi failed: %d\n", ret);
+ if (!test_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags))
+ /* Indicate the core start in the appropriate group */
+ ath12k_core_started(ab);
+
return 0;
err_reo_cleanup:
ath12k_dp_rx_pdev_reo_cleanup(ab);
-err_mac_destroy:
- ath12k_mac_destroy(ab);
err_hif_stop:
ath12k_hif_stop(ab);
err_wmi_detach:
@@ -857,6 +855,95 @@ err_wmi_detach:
return ret;
}
+static void ath12k_core_device_cleanup(struct ath12k_base *ab)
+{
+ mutex_lock(&ab->core_lock);
+
+ ath12k_hif_irq_disable(ab);
+ ath12k_core_pdev_destroy(ab);
+
+ mutex_unlock(&ab->core_lock);
+}
+
+static void ath12k_core_hw_group_stop(struct ath12k_hw_group *ag)
+{
+ struct ath12k_base *ab;
+ int i;
+
+ lockdep_assert_held(&ag->mutex);
+
+ clear_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags);
+
+ ath12k_mac_unregister(ag);
+
+ for (i = ag->num_devices - 1; i >= 0; i--) {
+ ab = ag->ab[i];
+ if (!ab)
+ continue;
+ ath12k_core_device_cleanup(ab);
+ }
+
+ ath12k_mac_destroy(ag);
+}
+
+static int ath12k_core_hw_group_start(struct ath12k_hw_group *ag)
+{
+ struct ath12k_base *ab;
+ int ret, i;
+
+ lockdep_assert_held(&ag->mutex);
+
+ if (test_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags))
+ goto core_pdev_create;
+
+ ret = ath12k_mac_allocate(ag);
+ if (WARN_ON(ret))
+ return ret;
+
+ ret = ath12k_mac_register(ag);
+ if (WARN_ON(ret))
+ goto err_mac_destroy;
+
+ set_bit(ATH12K_GROUP_FLAG_REGISTERED, &ag->flags);
+
+core_pdev_create:
+ for (i = 0; i < ag->num_devices; i++) {
+ ab = ag->ab[i];
+ if (!ab)
+ continue;
+
+ mutex_lock(&ab->core_lock);
+
+ ret = ath12k_core_pdev_create(ab);
+ if (ret) {
+ ath12k_err(ab, "failed to create pdev core %d\n", ret);
+ mutex_unlock(&ab->core_lock);
+ goto err;
+ }
+
+ ath12k_hif_irq_enable(ab);
+
+ ret = ath12k_core_rfkill_config(ab);
+ if (ret && ret != -EOPNOTSUPP) {
+ mutex_unlock(&ab->core_lock);
+ goto err;
+ }
+
+ mutex_unlock(&ab->core_lock);
+ }
+
+ return 0;
+
+err:
+ ath12k_core_hw_group_stop(ag);
+ return ret;
+
+err_mac_destroy:
+ ath12k_mac_destroy(ag);
+
+ return ret;
+}
+
static int ath12k_core_start_firmware(struct ath12k_base *ab,
enum ath12k_firmware_mode mode)
{
@@ -874,9 +961,37 @@ static int ath12k_core_start_firmware(struct ath12k_base *ab,
return ret;
}
+static inline
+bool ath12k_core_hw_group_start_ready(struct ath12k_hw_group *ag)
+{
+ lockdep_assert_held(&ag->mutex);
+
+ return (ag->num_started == ag->num_devices);
+}
+
+static void ath12k_core_trigger_partner(struct ath12k_base *ab)
+{
+ struct ath12k_hw_group *ag = ab->ag;
+ struct ath12k_base *partner_ab;
+ bool found = false;
+ int i;
+
+ for (i = 0; i < ag->num_devices; i++) {
+ partner_ab = ag->ab[i];
+ if (!partner_ab)
+ continue;
+
+ if (found)
+ ath12k_qmi_trigger_host_cap(partner_ab);
+
+ found = (partner_ab == ab);
+ }
+}
+
int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab)
{
- int ret;
+ struct ath12k_hw_group *ag = ath12k_ab_to_ag(ab);
+ int ret, i;
ret = ath12k_core_start_firmware(ab, ATH12K_FIRMWARE_MODE_NORMAL);
if (ret) {
@@ -896,41 +1011,52 @@ int ath12k_core_qmi_firmware_ready(struct ath12k_base *ab)
goto err_firmware_stop;
}
+ mutex_lock(&ag->mutex);
mutex_lock(&ab->core_lock);
+
ret = ath12k_core_start(ab, ATH12K_FIRMWARE_MODE_NORMAL);
if (ret) {
ath12k_err(ab, "failed to start core: %d\n", ret);
goto err_dp_free;
}
- ret = ath12k_core_pdev_create(ab);
- if (ret) {
- ath12k_err(ab, "failed to create pdev core: %d\n", ret);
- goto err_core_stop;
- }
- ath12k_hif_irq_enable(ab);
+ mutex_unlock(&ab->core_lock);
- ret = ath12k_core_rfkill_config(ab);
- if (ret && ret != -EOPNOTSUPP) {
- ath12k_err(ab, "failed to config rfkill: %d\n", ret);
- goto err_core_pdev_destroy;
+ if (ath12k_core_hw_group_start_ready(ag)) {
+ ret = ath12k_core_hw_group_start(ag);
+ if (ret) {
+ ath12k_warn(ab, "unable to start hw group\n");
+ goto err_core_stop;
+ }
+ ath12k_dbg(ab, ATH12K_DBG_BOOT, "group %d started\n", ag->id);
+ } else {
+ ath12k_core_trigger_partner(ab);
}
- mutex_unlock(&ab->core_lock);
+ mutex_unlock(&ag->mutex);
return 0;
-err_core_pdev_destroy:
- ath12k_core_pdev_destroy(ab);
err_core_stop:
- ath12k_core_stop(ab);
- ath12k_mac_destroy(ab);
+ for (i = ag->num_devices - 1; i >= 0; i--) {
+ ab = ag->ab[i];
+ if (!ab)
+ continue;
+
+ mutex_lock(&ab->core_lock);
+ ath12k_core_stop(ab);
+ mutex_unlock(&ab->core_lock);
+ }
+ goto exit;
+
err_dp_free:
ath12k_dp_free(ab);
mutex_unlock(&ab->core_lock);
err_firmware_stop:
ath12k_qmi_firmware_stop(ab);
+exit:
+ mutex_unlock(&ag->mutex);
return ret;
}
@@ -982,8 +1108,8 @@ static void ath12k_rfkill_work(struct work_struct *work)
rfkill_radio_on = ab->rfkill_radio_on;
spin_unlock_bh(&ab->base_lock);
- for (i = 0; i < ab->num_hw; i++) {
- ah = ab->ah[i];
+ for (i = 0; i < ath12k_get_num_hw(ab); i++) {
+ ah = ath12k_ab_to_ah(ab, i);
if (!ah)
continue;
@@ -1034,8 +1160,8 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
if (ab->is_reset)
set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags);
- for (i = 0; i < ab->num_hw; i++) {
- ah = ab->ah[i];
+ for (i = 0; i < ath12k_get_num_hw(ab); i++) {
+ ah = ath12k_ab_to_ah(ab, i);
if (!ah || ah->state == ATH12K_HW_STATE_OFF)
continue;
@@ -1073,8 +1199,8 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
struct ath12k *ar;
int i, j;
- for (i = 0; i < ab->num_hw; i++) {
- ah = ab->ah[i];
+ for (i = 0; i < ath12k_get_num_hw(ab); i++) {
+ ah = ath12k_ab_to_ah(ab, i);
if (!ah || ah->state == ATH12K_HW_STATE_OFF)
continue;
@@ -1127,8 +1253,16 @@ static void ath12k_core_restart(struct work_struct *work)
}
if (ab->is_reset) {
- for (i = 0; i < ab->num_hw; i++) {
- ah = ab->ah[i];
+ if (!test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) {
+ atomic_dec(&ab->reset_count);
+ complete(&ab->reset_complete);
+ ab->is_reset = false;
+ atomic_set(&ab->fail_cont_count, 0);
+ ath12k_dbg(ab, ATH12K_DBG_BOOT, "reset success\n");
+ }
+
+ for (i = 0; i < ath12k_get_num_hw(ab); i++) {
+ ah = ath12k_ab_to_ah(ab, i);
ieee80211_restart_hw(ah->hw);
}
}
@@ -1142,7 +1276,7 @@ static void ath12k_core_reset(struct work_struct *work)
int reset_count, fail_cont_count;
long time_left;
- if (!(test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))) {
+ if (!(test_bit(ATH12K_FLAG_QMI_FW_READY_COMPLETE, &ab->dev_flags))) {
ath12k_warn(ab, "ignore reset dev flags 0x%lx\n", ab->dev_flags);
return;
}
@@ -1241,38 +1375,246 @@ static void ath12k_core_panic_notifier_unregister(struct ath12k_base *ab)
&ab->panic_nb);
}
-int ath12k_core_init(struct ath12k_base *ab)
+static inline
+bool ath12k_core_hw_group_create_ready(struct ath12k_hw_group *ag)
{
- int ret;
+ lockdep_assert_held(&ag->mutex);
- ret = ath12k_core_soc_create(ab);
- if (ret) {
- ath12k_err(ab, "failed to create soc core: %d\n", ret);
- return ret;
+ return (ag->num_probed == ag->num_devices);
+}
+
+static struct ath12k_hw_group *ath12k_core_hw_group_alloc(u8 id, u8 max_devices)
+{
+ struct ath12k_hw_group *ag;
+
+ lockdep_assert_held(&ath12k_hw_group_mutex);
+
+ ag = kzalloc(sizeof(*ag), GFP_KERNEL);
+ if (!ag)
+ return NULL;
+
+ ag->id = id;
+ ag->num_devices = max_devices;
+ list_add(&ag->list, &ath12k_hw_group_list);
+ mutex_init(&ag->mutex);
+
+ return ag;
+}
+
+static void ath12k_core_hw_group_free(struct ath12k_hw_group *ag)
+{
+ mutex_lock(&ath12k_hw_group_mutex);
+
+ list_del(&ag->list);
+ kfree(ag);
+
+ mutex_unlock(&ath12k_hw_group_mutex);
+}
+
+static struct ath12k_hw_group *ath12k_core_hw_group_assign(struct ath12k_base *ab)
+{
+ u32 group_id = ATH12K_INVALID_GROUP_ID;
+ struct ath12k_hw_group *ag;
+
+ lockdep_assert_held(&ath12k_hw_group_mutex);
+
+ /* The grouping of multiple devices will be done based on device tree file.
+ * TODO: device tree file parsing to know about the devices involved in group.
+ *
+ * The platforms that do not have any valid group information would have each
+ * device to be part of its own invalid group.
+ *
+ * Currently, we are not parsing any device tree information and hence, grouping
+ * of multiple devices is not involved. Thus, single device is added to device
+ * group.
+ */
+ ag = ath12k_core_hw_group_alloc(group_id, 1);
+ if (!ag) {
+ ath12k_warn(ab, "unable to create new hw group\n");
+ return NULL;
+ }
+
+ ath12k_dbg(ab, ATH12K_DBG_BOOT, "single device added to hardware group\n");
+
+ ab->device_id = ag->num_probed++;
+ ag->ab[ab->device_id] = ab;
+ ab->ag = ag;
+ ag->mlo_capable = false;
+
+ return ag;
+}
+
+void ath12k_core_hw_group_unassign(struct ath12k_base *ab)
+{
+ struct ath12k_hw_group *ag = ath12k_ab_to_ag(ab);
+ u8 device_id = ab->device_id;
+ int num_probed;
+
+ if (!ag)
+ return;
+
+ mutex_lock(&ag->mutex);
+
+ if (WARN_ON(device_id >= ag->num_devices)) {
+ mutex_unlock(&ag->mutex);
+ return;
+ }
+
+ if (WARN_ON(ag->ab[device_id] != ab)) {
+ mutex_unlock(&ag->mutex);
+ return;
+ }
+
+ ag->ab[device_id] = NULL;
+ ab->ag = NULL;
+ ab->device_id = ATH12K_INVALID_DEVICE_ID;
+
+ if (ag->num_probed)
+ ag->num_probed--;
+
+ num_probed = ag->num_probed;
+
+ mutex_unlock(&ag->mutex);
+
+ if (!num_probed)
+ ath12k_core_hw_group_free(ag);
+}
+
+static void ath12k_core_hw_group_destroy(struct ath12k_hw_group *ag)
+{
+ struct ath12k_base *ab;
+ int i;
+
+ if (WARN_ON(!ag))
+ return;
+
+ for (i = 0; i < ag->num_devices; i++) {
+ ab = ag->ab[i];
+ if (!ab)
+ continue;
+
+ ath12k_core_soc_destroy(ab);
+ }
+}
+
+static void ath12k_core_hw_group_cleanup(struct ath12k_hw_group *ag)
+{
+ struct ath12k_base *ab;
+ int i;
+
+ if (!ag)
+ return;
+
+ mutex_lock(&ag->mutex);
+
+ ath12k_core_hw_group_stop(ag);
+
+ for (i = 0; i < ag->num_devices; i++) {
+ ab = ag->ab[i];
+ if (!ab)
+ continue;
+
+ mutex_lock(&ab->core_lock);
+ ath12k_core_stop(ab);
+ mutex_unlock(&ab->core_lock);
+ }
+
+ mutex_unlock(&ag->mutex);
+}
+
+static int ath12k_core_hw_group_create(struct ath12k_hw_group *ag)
+{
+ struct ath12k_base *ab;
+ int i, ret;
+
+ lockdep_assert_held(&ag->mutex);
+
+ for (i = 0; i < ag->num_devices; i++) {
+ ab = ag->ab[i];
+ if (!ab)
+ continue;
+
+ mutex_lock(&ab->core_lock);
+
+ ret = ath12k_core_soc_create(ab);
+ if (ret) {
+ mutex_unlock(&ab->core_lock);
+ ath12k_err(ab, "failed to create soc core: %d\n", ret);
+ return ret;
+ }
+
+ mutex_unlock(&ab->core_lock);
}
+ return 0;
+}
+
+void ath12k_core_hw_group_set_mlo_capable(struct ath12k_hw_group *ag)
+{
+ lockdep_assert_held(&ag->mutex);
+
+ /* If more than one devices are grouped, then inter MLO
+ * functionality can work still independent of whether internally
+ * each device supports single_chip_mlo or not.
+ * Only when there is one device, then it depends whether the
+ * device can support intra chip MLO or not
+ */
+ if (ag->num_devices > 1)
+ ag->mlo_capable = true;
+ else
+ ag->mlo_capable = ag->ab[0]->single_chip_mlo_supp;
+}
+
+int ath12k_core_init(struct ath12k_base *ab)
+{
+ struct ath12k_hw_group *ag;
+ int ret;
+
ret = ath12k_core_panic_notifier_register(ab);
if (ret)
ath12k_warn(ab, "failed to register panic handler: %d\n", ret);
+ mutex_lock(&ath12k_hw_group_mutex);
+
+ ag = ath12k_core_hw_group_assign(ab);
+ if (!ag) {
+ mutex_unlock(&ath12k_hw_group_mutex);
+ ath12k_warn(ab, "unable to get hw group\n");
+ return -ENODEV;
+ }
+
+ mutex_unlock(&ath12k_hw_group_mutex);
+
+ mutex_lock(&ag->mutex);
+
+ ath12k_dbg(ab, ATH12K_DBG_BOOT, "num devices %d num probed %d\n",
+ ag->num_devices, ag->num_probed);
+
+ if (ath12k_core_hw_group_create_ready(ag)) {
+ ret = ath12k_core_hw_group_create(ag);
+ if (ret) {
+ mutex_unlock(&ag->mutex);
+ ath12k_warn(ab, "unable to create hw group\n");
+ goto err;
+ }
+ }
+
+ mutex_unlock(&ag->mutex);
+
return 0;
+
+err:
+ ath12k_core_hw_group_destroy(ab->ag);
+ ath12k_core_hw_group_unassign(ab);
+ return ret;
}
void ath12k_core_deinit(struct ath12k_base *ab)
{
ath12k_core_panic_notifier_unregister(ab);
-
- mutex_lock(&ab->core_lock);
-
- ath12k_core_pdev_destroy(ab);
- ath12k_core_stop(ab);
-
- mutex_unlock(&ab->core_lock);
-
- ath12k_hif_power_down(ab, false);
- ath12k_mac_destroy(ab);
- ath12k_core_soc_destroy(ab);
- ath12k_fw_unmap(ab);
+ ath12k_core_hw_group_cleanup(ab->ag);
+ ath12k_core_hw_group_destroy(ab->ag);
+ ath12k_core_hw_group_unassign(ab);
}
void ath12k_core_free(struct ath12k_base *ab)
@@ -1322,7 +1664,7 @@ struct ath12k_base *ath12k_core_alloc(struct device *dev, size_t priv_size,
ab->dev = dev;
ab->hif.bus = bus;
ab->qmi.num_radios = U8_MAX;
- ab->mlo_capable_flags = ATH12K_INTRA_DEVICE_MLO_SUPPORT;
+ ab->single_chip_mlo_supp = false;
/* Device index used to identify the devices in a group.
*
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 3bf31ee5b9fa..458e3d0071a8 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -63,6 +63,14 @@
#define ATH12K_RECONFIGURE_TIMEOUT_HZ (10 * HZ)
#define ATH12K_RECOVER_START_TIMEOUT_HZ (20 * HZ)
+#define ATH12K_MAX_SOCS 3
+#define ATH12K_GROUP_MAX_RADIO (ATH12K_MAX_SOCS * MAX_RADIOS)
+#define ATH12K_INVALID_GROUP_ID 0xFF
+#define ATH12K_INVALID_DEVICE_ID 0xFF
+
+#define ATH12K_MAX_MLO_PEERS 256
+#define ATH12K_MLO_PEER_ID_INVALID 0xFFFF
+
enum ath12k_bdf_search {
ATH12K_BDF_SEARCH_DEFAULT,
ATH12K_BDF_SEARCH_BUS_AND_BOARD,
@@ -115,6 +123,7 @@ struct ath12k_skb_cb {
dma_addr_t paddr_ext_desc;
u32 cipher;
u8 flags;
+ u8 link_id;
};
struct ath12k_skb_rxcb {
@@ -208,6 +217,10 @@ enum ath12k_scan_state {
ATH12K_SCAN_ABORTING,
};
+enum ath12k_hw_group_flags {
+ ATH12K_GROUP_FLAG_REGISTERED,
+};
+
enum ath12k_dev_flags {
ATH12K_CAC_RUNNING,
ATH12K_FLAG_CRASH_FLUSH,
@@ -220,6 +233,7 @@ enum ath12k_dev_flags {
ATH12K_FLAG_HTC_SUSPEND_COMPLETE,
ATH12K_FLAG_CE_IRQ_ENABLED,
ATH12K_FLAG_EXT_IRQ_ENABLED,
+ ATH12K_FLAG_QMI_FW_READY_COMPLETE,
};
struct ath12k_tx_conf {
@@ -314,10 +328,11 @@ struct ath12k_vif {
bool ps;
struct ath12k_link_vif deflink;
- struct ath12k_link_vif __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
+ struct ath12k_link_vif __rcu *link[ATH12K_NUM_MAX_LINKS];
struct ath12k_vif_cache *cache[IEEE80211_MLD_MAX_NUM_LINKS];
/* indicates bitmap of link vif created in FW */
u16 links_map;
+ u8 last_scan_link;
/* Must be last - ends in a flexible-array member.
*
@@ -469,6 +484,9 @@ struct ath12k_link_sta {
struct ath12k_link_vif *arvif;
struct ath12k_sta *ahsta;
+ /* link address similar to ieee80211_link_sta */
+ u8 addr[ETH_ALEN];
+
/* the following are protected by ar->data_lock */
u32 changed; /* IEEE80211_RC_* */
u32 bw;
@@ -485,14 +503,26 @@ struct ath12k_link_sta {
struct ath12k_rx_peer_stats *rx_stats;
struct ath12k_wbm_tx_stats *wbm_tx_stats;
u32 bw_prev;
+
+ /* For now the assoc link will be considered primary */
+ bool is_assoc_link;
+
+ /* for firmware use only */
+ u8 link_idx;
};
struct ath12k_sta {
+ struct ath12k_vif *ahvif;
enum hal_pn_type pn_type;
struct ath12k_link_sta deflink;
struct ath12k_link_sta __rcu *link[IEEE80211_MLD_MAX_NUM_LINKS];
/* indicates bitmap of link sta created in FW */
u16 links_map;
+ u8 assoc_link_id;
+ u16 ml_peer_id;
+ u8 num_peer;
+
+ enum ieee80211_sta_state state;
};
#define ATH12K_MIN_5G_FREQ 4150
@@ -657,7 +687,7 @@ struct ath12k {
struct work_struct regd_update_work;
- struct work_struct wmi_mgmt_tx_work;
+ struct wiphy_work wmi_mgmt_tx_work;
struct sk_buff_head wmi_mgmt_tx_queue;
struct ath12k_wow wow;
@@ -688,6 +718,8 @@ struct ath12k {
struct ath12k_hw {
struct ieee80211_hw *hw;
+ struct device *dev;
+
/* Protect the write operation of the hardware state ath12k_hw::state
* between hardware start<=>reconfigure<=>stop transitions.
*/
@@ -698,6 +730,11 @@ struct ath12k_hw {
u8 num_radio;
+ DECLARE_BITMAP(free_ml_peer_id_map, ATH12K_MAX_MLO_PEERS);
+
+ /* protected by wiphy_lock() */
+ struct list_head ml_peers;
+
/* Keep last */
struct ath12k radio[] __aligned(sizeof(void *));
};
@@ -784,19 +821,30 @@ struct ath12k_soc_dp_stats {
struct ath12k_soc_dp_tx_err_stats tx_err;
};
-/**
- * enum ath12k_link_capable_flags - link capable flags
- *
- * Single/Multi link capability information
- *
- * @ATH12K_INTRA_DEVICE_MLO_SUPPORT: SLO/MLO form between the radio, where all
- * the links (radios) present within a device.
- * @ATH12K_INTER_DEVICE_MLO_SUPPORT: SLO/MLO form between the radio, where all
- * the links (radios) present across the devices.
+/* Holds info on the group of devices that are registered as a single
+ * wiphy, protected with struct ath12k_hw_group::mutex.
*/
-enum ath12k_link_capable_flags {
- ATH12K_INTRA_DEVICE_MLO_SUPPORT = BIT(0),
- ATH12K_INTER_DEVICE_MLO_SUPPORT = BIT(1),
+struct ath12k_hw_group {
+ struct list_head list;
+ u8 id;
+ u8 num_devices;
+ u8 num_probed;
+ u8 num_started;
+ unsigned long flags;
+ struct ath12k_base *ab[ATH12K_MAX_SOCS];
+
+ /* protects access to this struct */
+ struct mutex mutex;
+
+ /* Holds information of wiphy (hw) registration.
+ *
+ * In Multi/Single Link Operation case, all pdevs are registered as
+ * a single wiphy. In other (legacy/Non-MLO) cases, each pdev is
+ * registered as separate wiphys.
+ */
+ struct ath12k_hw *ah[ATH12K_GROUP_MAX_RADIO];
+ u8 num_hw;
+ bool mlo_capable;
};
/* Master structure to hold the hw data which may be used in core module */
@@ -862,15 +910,6 @@ struct ath12k_base {
struct ath12k_pdev __rcu *pdevs_active[MAX_RADIOS];
- /* Holds information of wiphy (hw) registration.
- *
- * In Multi/Single Link Operation case, all pdevs are registered as
- * a single wiphy. In other (legacy/Non-MLO) cases, each pdev is
- * registered as separate wiphys.
- */
- struct ath12k_hw *ah[MAX_RADIOS];
- u8 num_hw;
-
struct ath12k_wmi_hal_reg_capabilities_ext_arg hal_reg_cap[MAX_RADIOS];
unsigned long long free_vdev_map;
unsigned long long free_vdev_stats_id_map;
@@ -964,12 +1003,8 @@ struct ath12k_base {
const struct hal_rx_ops *hal_rx_ops;
- /* mlo_capable_flags denotes the single/multi link operation
- * capabilities of the Device.
- *
- * See enum ath12k_link_capable_flags
- */
- u8 mlo_capable_flags;
+ /* Denotes the whether MLO is possible within the chip */
+ bool single_chip_mlo_supp;
struct completion restart_completed;
@@ -992,6 +1027,8 @@ struct ath12k_base {
struct notifier_block panic_nb;
+ struct ath12k_hw_group *ag;
+
/* must be last */
u8 drv_priv[] __aligned(sizeof(void *));
};
@@ -1022,6 +1059,7 @@ int ath12k_core_resume_early(struct ath12k_base *ab);
int ath12k_core_resume(struct ath12k_base *ab);
int ath12k_core_suspend(struct ath12k_base *ab);
int ath12k_core_suspend_late(struct ath12k_base *ab);
+void ath12k_core_hw_group_unassign(struct ath12k_base *ab);
const struct firmware *ath12k_core_firmware_request(struct ath12k_base *ab,
const char *filename);
@@ -1029,6 +1067,8 @@ u32 ath12k_core_get_max_station_per_radio(struct ath12k_base *ab);
u32 ath12k_core_get_max_peers_per_radio(struct ath12k_base *ab);
u32 ath12k_core_get_max_num_tids(struct ath12k_base *ab);
+void ath12k_core_hw_group_set_mlo_capable(struct ath12k_hw_group *ag);
+
static inline const char *ath12k_scan_state_str(enum ath12k_scan_state state)
{
switch (state) {
@@ -1129,4 +1169,40 @@ static inline struct ieee80211_hw *ath12k_ar_to_hw(struct ath12k *ar)
#define for_each_ar(ah, ar, index) \
for ((index) = 0; ((index) < (ah)->num_radio && \
((ar) = &(ah)->radio[(index)])); (index)++)
+
+static inline struct ath12k_hw *ath12k_ab_to_ah(struct ath12k_base *ab, int idx)
+{
+ return ab->ag->ah[idx];
+}
+
+static inline void ath12k_ab_set_ah(struct ath12k_base *ab, int idx,
+ struct ath12k_hw *ah)
+{
+ ab->ag->ah[idx] = ah;
+}
+
+static inline int ath12k_get_num_hw(struct ath12k_base *ab)
+{
+ return ab->ag->num_hw;
+}
+
+static inline struct ath12k_hw_group *ath12k_ab_to_ag(struct ath12k_base *ab)
+{
+ return ab->ag;
+}
+
+static inline void ath12k_core_started(struct ath12k_base *ab)
+{
+ lockdep_assert_held(&ab->ag->mutex);
+
+ ab->ag->num_started++;
+}
+
+static inline void ath12k_core_stopped(struct ath12k_base *ab)
+{
+ lockdep_assert_held(&ab->ag->mutex);
+
+ ab->ag->num_started--;
+}
+
#endif /* _CORE_H_ */
diff --git a/drivers/net/wireless/ath/ath12k/debug.c b/drivers/net/wireless/ath/ath12k/debug.c
index fe5a732ba9ec..ff6eaeafa092 100644
--- a/drivers/net/wireless/ath/ath12k/debug.c
+++ b/drivers/net/wireless/ath/ath12k/debug.c
@@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
- * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/vmalloc.h>
@@ -36,7 +36,7 @@ void ath12k_err(struct ath12k_base *ab, const char *fmt, ...)
va_end(args);
}
-void ath12k_warn(struct ath12k_base *ab, const char *fmt, ...)
+void __ath12k_warn(struct device *dev, const char *fmt, ...)
{
struct va_format vaf = {
.fmt = fmt,
@@ -45,7 +45,7 @@ void ath12k_warn(struct ath12k_base *ab, const char *fmt, ...)
va_start(args, fmt);
vaf.va = &args;
- dev_warn_ratelimited(ab->dev, "%pV", &vaf);
+ dev_warn_ratelimited(dev, "%pV", &vaf);
/* TODO: Trace the log */
va_end(args);
}
diff --git a/drivers/net/wireless/ath/ath12k/debug.h b/drivers/net/wireless/ath/ath12k/debug.h
index f7005917362c..90e801136bc6 100644
--- a/drivers/net/wireless/ath/ath12k/debug.h
+++ b/drivers/net/wireless/ath/ath12k/debug.h
@@ -31,7 +31,10 @@ enum ath12k_debug_mask {
__printf(2, 3) void ath12k_info(struct ath12k_base *ab, const char *fmt, ...);
__printf(2, 3) void ath12k_err(struct ath12k_base *ab, const char *fmt, ...);
-__printf(2, 3) void ath12k_warn(struct ath12k_base *ab, const char *fmt, ...);
+__printf(2, 3) void __ath12k_warn(struct device *dev, const char *fmt, ...);
+
+#define ath12k_warn(ab, fmt, ...) __ath12k_warn((ab)->dev, fmt, ##__VA_ARGS__)
+#define ath12k_hw_warn(ah, fmt, ...) __ath12k_warn((ah)->dev, fmt, ##__VA_ARGS__)
extern unsigned int ath12k_debug_mask;
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
index c9980c0193d1..d8f137bfba7b 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c
@@ -48,6 +48,28 @@ print_array_to_buf(u8 *buf, u32 offset, const char *header,
footer);
}
+static const char *ath12k_htt_ax_tx_rx_ru_size_to_str(u8 ru_size)
+{
+ switch (ru_size) {
+ case ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_26:
+ return "26";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_52:
+ return "52";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_106:
+ return "106";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_242:
+ return "242";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_484:
+ return "484";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_996:
+ return "996";
+ case ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_996x2:
+ return "996x2";
+ default:
+ return "unknown";
+ }
+}
+
static const char *ath12k_htt_be_tx_rx_ru_size_to_str(u8 ru_size)
{
switch (ru_size) {
@@ -88,6 +110,17 @@ static const char *ath12k_htt_be_tx_rx_ru_size_to_str(u8 ru_size)
}
}
+static const char*
+ath12k_tx_ru_size_to_str(enum ath12k_htt_stats_ru_type ru_type, u8 ru_size)
+{
+ if (ru_type == ATH12K_HTT_STATS_RU_TYPE_SINGLE_RU_ONLY)
+ return ath12k_htt_ax_tx_rx_ru_size_to_str(ru_size);
+ else if (ru_type == ATH12K_HTT_STATS_RU_TYPE_SINGLE_AND_MULTI_RU)
+ return ath12k_htt_be_tx_rx_ru_size_to_str(ru_size);
+ else
+ return "unknown";
+}
+
static void
htt_print_tx_pdev_stats_cmn_tlv(const void *tag_buf, u16 tag_len,
struct debug_htt_stats_req *stats_req)
@@ -1562,7 +1595,8 @@ ath12k_htt_print_tx_selfgen_ac_stats_tlv(const void *tag_buf, u16 tag_len,
le32_to_cpu(htt_stats_buf->ac_mu_mimo_ndp));
len += print_array_to_buf_index(buf, len, "ac_mu_mimo_brpollX_tried = ", 1,
htt_stats_buf->ac_mu_mimo_brpoll,
- ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS, "\n\n");
+ ATH12K_HTT_TX_NUM_AC_MUMIMO_USER_STATS - 1,
+ "\n\n");
stats_req->buf_len = len;
}
@@ -1590,7 +1624,7 @@ ath12k_htt_print_tx_selfgen_ax_stats_tlv(const void *tag_buf, u16 tag_len,
le32_to_cpu(htt_stats_buf->ax_mu_mimo_ndp));
len += print_array_to_buf_index(buf, len, "ax_mu_mimo_brpollX_tried = ", 1,
htt_stats_buf->ax_mu_mimo_brpoll,
- ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS, "\n");
+ ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS - 1, "\n");
len += scnprintf(buf + len, buf_len - len, "ax_basic_trigger = %u\n",
le32_to_cpu(htt_stats_buf->ax_basic_trigger));
len += scnprintf(buf + len, buf_len - len, "ax_ulmumimo_total_trigger = %u\n",
@@ -2276,9 +2310,9 @@ ath12k_htt_print_tx_pdev_mumimo_grp_stats_tlv(const void *tag_buf, u16 tag_len,
len += print_array_to_buf(buf, len, "ul_mumimo_grp_best_grp_size",
htt_stats_buf->ul_mumimo_grp_best_grp_size,
ATH12K_HTT_STATS_NUM_MAX_MUMIMO_SZ, "\n");
- len += print_array_to_buf_index(buf, len, "ul_mumimo_grp_best_num_usrs = ", 1,
- htt_stats_buf->ul_mumimo_grp_best_usrs,
- ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS, "\n");
+ len += print_array_to_buf(buf, len, "ul_mumimo_grp_best_num_usrs = ",
+ htt_stats_buf->ul_mumimo_grp_best_usrs,
+ ATH12K_HTT_TX_NUM_AX_MUMIMO_USER_STATS, "\n");
len += print_array_to_buf(buf, len,
"ul_mumimo_grp_tputs_observed (per bin = 300 mbps)",
htt_stats_buf->ul_mumimo_grp_tputs,
@@ -2542,6 +2576,573 @@ ath12k_htt_print_pdev_obss_pd_stats_tlv(const void *tag_buf, u16 tag_len,
stats_req->buf_len = len;
}
+static void ath12k_htt_print_dlpager_entry(const struct ath12k_htt_pgs_info *pg_info,
+ int idx, char *str_buf)
+{
+ u64 page_timestamp;
+ u16 index = 0;
+
+ page_timestamp = ath12k_le32hilo_to_u64(pg_info->ts_msb, pg_info->ts_lsb);
+
+ index += snprintf(&str_buf[index], ATH12K_HTT_MAX_STRING_LEN - index,
+ "Index - %u ; Page Number - %u ; ",
+ idx, le32_to_cpu(pg_info->page_num));
+ index += snprintf(&str_buf[index], ATH12K_HTT_MAX_STRING_LEN - index,
+ "Num of pages - %u ; Timestamp - %lluus\n",
+ le32_to_cpu(pg_info->num_pgs), page_timestamp);
+}
+
+static void
+ath12k_htt_print_dlpager_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_dl_pager_stats_tlv *stat_buf = tag_buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 dword_lock, dword_unlock;
+ int i;
+ u8 *buf = stats_req->buf;
+ u8 pg_locked;
+ u8 pg_unlock;
+ char str_buf[ATH12K_HTT_MAX_STRING_LEN] = {0};
+
+ if (tag_len < sizeof(*stat_buf))
+ return;
+
+ dword_lock = le32_get_bits(stat_buf->info2,
+ ATH12K_HTT_DLPAGER_TOTAL_LOCK_PAGES_INFO2);
+ dword_unlock = le32_get_bits(stat_buf->info2,
+ ATH12K_HTT_DLPAGER_TOTAL_FREE_PAGES_INFO2);
+
+ pg_locked = ATH12K_HTT_STATS_PAGE_LOCKED;
+ pg_unlock = ATH12K_HTT_STATS_PAGE_UNLOCKED;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_DLPAGER_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "ASYNC locked pages = %u\n",
+ le32_get_bits(stat_buf->info0,
+ ATH12K_HTT_DLPAGER_ASYNC_LOCK_PG_CNT_INFO0));
+ len += scnprintf(buf + len, buf_len - len, "SYNC locked pages = %u\n",
+ le32_get_bits(stat_buf->info0,
+ ATH12K_HTT_DLPAGER_SYNC_LOCK_PG_CNT_INFO0));
+ len += scnprintf(buf + len, buf_len - len, "Total locked pages = %u\n",
+ le32_get_bits(stat_buf->info1,
+ ATH12K_HTT_DLPAGER_TOTAL_LOCK_PAGES_INFO1));
+ len += scnprintf(buf + len, buf_len - len, "Total free pages = %u\n",
+ le32_get_bits(stat_buf->info1,
+ ATH12K_HTT_DLPAGER_TOTAL_FREE_PAGES_INFO1));
+
+ len += scnprintf(buf + len, buf_len - len, "\nLOCKED PAGES HISTORY\n");
+ len += scnprintf(buf + len, buf_len - len, "last_locked_page_idx = %u\n",
+ dword_lock ? dword_lock - 1 : (ATH12K_PAGER_MAX - 1));
+
+ for (i = 0; i < ATH12K_PAGER_MAX; i++) {
+ memset(str_buf, 0x0, ATH12K_HTT_MAX_STRING_LEN);
+ ath12k_htt_print_dlpager_entry(&stat_buf->pgs_info[pg_locked][i],
+ i, str_buf);
+ len += scnprintf(buf + len, buf_len - len, "%s", str_buf);
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\nUNLOCKED PAGES HISTORY\n");
+ len += scnprintf(buf + len, buf_len - len, "last_unlocked_page_idx = %u\n",
+ dword_unlock ? dword_unlock - 1 : ATH12K_PAGER_MAX - 1);
+
+ for (i = 0; i < ATH12K_PAGER_MAX; i++) {
+ memset(str_buf, 0x0, ATH12K_HTT_MAX_STRING_LEN);
+ ath12k_htt_print_dlpager_entry(&stat_buf->pgs_info[pg_unlock][i],
+ i, str_buf);
+ len += scnprintf(buf + len, buf_len - len, "%s", str_buf);
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_phy_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_phy_stats_tlv *htt_stats_buf = tag_buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 *buf = stats_req->buf, i;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_STATS_TLV:\n");
+ for (i = 0; i < ATH12K_HTT_STATS_MAX_CHAINS; i++)
+ len += scnprintf(buf + len, buf_len - len, "bdf_nf_chain[%d] = %d\n",
+ i, a_sle32_to_cpu(htt_stats_buf->nf_chain[i]));
+ for (i = 0; i < ATH12K_HTT_STATS_MAX_CHAINS; i++)
+ len += scnprintf(buf + len, buf_len - len, "runtime_nf_chain[%d] = %d\n",
+ i, a_sle32_to_cpu(htt_stats_buf->runtime_nf_chain[i]));
+ len += scnprintf(buf + len, buf_len - len, "false_radar_cnt = %u / %u (mins)\n",
+ le32_to_cpu(htt_stats_buf->false_radar_cnt),
+ le32_to_cpu(htt_stats_buf->fw_run_time));
+ len += scnprintf(buf + len, buf_len - len, "radar_cs_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->radar_cs_cnt));
+ len += scnprintf(buf + len, buf_len - len, "ani_level = %d\n\n",
+ a_sle32_to_cpu(htt_stats_buf->ani_level));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_phy_counters_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_phy_counters_tlv *htt_stats_buf = tag_buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 *buf = stats_req->buf;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_COUNTERS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "rx_ofdma_timing_err_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_ofdma_timing_err_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_cck_fail_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_cck_fail_cnt));
+ len += scnprintf(buf + len, buf_len - len, "mactx_abort_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->mactx_abort_cnt));
+ len += scnprintf(buf + len, buf_len - len, "macrx_abort_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->macrx_abort_cnt));
+ len += scnprintf(buf + len, buf_len - len, "phytx_abort_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->phytx_abort_cnt));
+ len += scnprintf(buf + len, buf_len - len, "phyrx_abort_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->phyrx_abort_cnt));
+ len += scnprintf(buf + len, buf_len - len, "phyrx_defer_abort_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->phyrx_defer_abort_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_gain_adj_lstf_event_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_gain_adj_lstf_event_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rx_gain_adj_non_legacy_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rx_gain_adj_non_legacy_cnt));
+ len += print_array_to_buf(buf, len, "rx_pkt_cnt", htt_stats_buf->rx_pkt_cnt,
+ ATH12K_HTT_MAX_RX_PKT_CNT, "\n");
+ len += print_array_to_buf(buf, len, "rx_pkt_crc_pass_cnt",
+ htt_stats_buf->rx_pkt_crc_pass_cnt,
+ ATH12K_HTT_MAX_RX_PKT_CRC_PASS_CNT, "\n");
+ len += print_array_to_buf(buf, len, "per_blk_err_cnt",
+ htt_stats_buf->per_blk_err_cnt,
+ ATH12K_HTT_MAX_PER_BLK_ERR_CNT, "\n");
+ len += print_array_to_buf(buf, len, "rx_ota_err_cnt",
+ htt_stats_buf->rx_ota_err_cnt,
+ ATH12K_HTT_MAX_RX_OTA_ERR_CNT, "\n\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_phy_reset_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_phy_reset_stats_tlv *htt_stats_buf = tag_buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 *buf = stats_req->buf;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_RESET_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n",
+ le32_to_cpu(htt_stats_buf->pdev_id));
+ len += scnprintf(buf + len, buf_len - len, "chan_mhz = %u\n",
+ le32_to_cpu(htt_stats_buf->chan_mhz));
+ len += scnprintf(buf + len, buf_len - len, "chan_band_center_freq1 = %u\n",
+ le32_to_cpu(htt_stats_buf->chan_band_center_freq1));
+ len += scnprintf(buf + len, buf_len - len, "chan_band_center_freq2 = %u\n",
+ le32_to_cpu(htt_stats_buf->chan_band_center_freq2));
+ len += scnprintf(buf + len, buf_len - len, "chan_phy_mode = %u\n",
+ le32_to_cpu(htt_stats_buf->chan_phy_mode));
+ len += scnprintf(buf + len, buf_len - len, "chan_flags = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->chan_flags));
+ len += scnprintf(buf + len, buf_len - len, "chan_num = %u\n",
+ le32_to_cpu(htt_stats_buf->chan_num));
+ len += scnprintf(buf + len, buf_len - len, "reset_cause = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->reset_cause));
+ len += scnprintf(buf + len, buf_len - len, "prev_reset_cause = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->prev_reset_cause));
+ len += scnprintf(buf + len, buf_len - len, "phy_warm_reset_src = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->phy_warm_reset_src));
+ len += scnprintf(buf + len, buf_len - len, "rx_gain_tbl_mode = %d\n",
+ le32_to_cpu(htt_stats_buf->rx_gain_tbl_mode));
+ len += scnprintf(buf + len, buf_len - len, "xbar_val = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->xbar_val));
+ len += scnprintf(buf + len, buf_len - len, "force_calibration = %u\n",
+ le32_to_cpu(htt_stats_buf->force_calibration));
+ len += scnprintf(buf + len, buf_len - len, "phyrf_mode = %u\n",
+ le32_to_cpu(htt_stats_buf->phyrf_mode));
+ len += scnprintf(buf + len, buf_len - len, "phy_homechan = %u\n",
+ le32_to_cpu(htt_stats_buf->phy_homechan));
+ len += scnprintf(buf + len, buf_len - len, "phy_tx_ch_mask = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->phy_tx_ch_mask));
+ len += scnprintf(buf + len, buf_len - len, "phy_rx_ch_mask = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->phy_rx_ch_mask));
+ len += scnprintf(buf + len, buf_len - len, "phybb_ini_mask = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->phybb_ini_mask));
+ len += scnprintf(buf + len, buf_len - len, "phyrf_ini_mask = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->phyrf_ini_mask));
+ len += scnprintf(buf + len, buf_len - len, "phy_dfs_en_mask = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->phy_dfs_en_mask));
+ len += scnprintf(buf + len, buf_len - len, "phy_sscan_en_mask = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->phy_sscan_en_mask));
+ len += scnprintf(buf + len, buf_len - len, "phy_synth_sel_mask = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->phy_synth_sel_mask));
+ len += scnprintf(buf + len, buf_len - len, "phy_adfs_freq = %u\n",
+ le32_to_cpu(htt_stats_buf->phy_adfs_freq));
+ len += scnprintf(buf + len, buf_len - len, "cck_fir_settings = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->cck_fir_settings));
+ len += scnprintf(buf + len, buf_len - len, "phy_dyn_pri_chan = %u\n",
+ le32_to_cpu(htt_stats_buf->phy_dyn_pri_chan));
+ len += scnprintf(buf + len, buf_len - len, "cca_thresh = 0x%0x\n",
+ le32_to_cpu(htt_stats_buf->cca_thresh));
+ len += scnprintf(buf + len, buf_len - len, "dyn_cca_status = %u\n",
+ le32_to_cpu(htt_stats_buf->dyn_cca_status));
+ len += scnprintf(buf + len, buf_len - len, "rxdesense_thresh_hw = 0x%x\n",
+ le32_to_cpu(htt_stats_buf->rxdesense_thresh_hw));
+ len += scnprintf(buf + len, buf_len - len, "rxdesense_thresh_sw = 0x%x\n\n",
+ le32_to_cpu(htt_stats_buf->rxdesense_thresh_sw));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_phy_reset_counters_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_phy_reset_counters_tlv *htt_stats_buf = tag_buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 *buf = stats_req->buf;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_RESET_COUNTERS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n",
+ le32_to_cpu(htt_stats_buf->pdev_id));
+ len += scnprintf(buf + len, buf_len - len, "cf_active_low_fail_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->cf_active_low_fail_cnt));
+ len += scnprintf(buf + len, buf_len - len, "cf_active_low_pass_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->cf_active_low_pass_cnt));
+ len += scnprintf(buf + len, buf_len - len, "phy_off_through_vreg_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->phy_off_through_vreg_cnt));
+ len += scnprintf(buf + len, buf_len - len, "force_calibration_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->force_calibration_cnt));
+ len += scnprintf(buf + len, buf_len - len, "rf_mode_switch_phy_off_cnt = %u\n",
+ le32_to_cpu(htt_stats_buf->rf_mode_switch_phy_off_cnt));
+ len += scnprintf(buf + len, buf_len - len, "temperature_recal_cnt = %u\n\n",
+ le32_to_cpu(htt_stats_buf->temperature_recal_cnt));
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_phy_tpc_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_phy_tpc_stats_tlv *htt_stats_buf = tag_buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 *buf = stats_req->buf;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_PHY_TPC_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "pdev_id = %u\n",
+ le32_to_cpu(htt_stats_buf->pdev_id));
+ len += scnprintf(buf + len, buf_len - len, "tx_power_scale = %u\n",
+ le32_to_cpu(htt_stats_buf->tx_power_scale));
+ len += scnprintf(buf + len, buf_len - len, "tx_power_scale_db = %u\n",
+ le32_to_cpu(htt_stats_buf->tx_power_scale_db));
+ len += scnprintf(buf + len, buf_len - len, "min_negative_tx_power = %d\n",
+ le32_to_cpu(htt_stats_buf->min_negative_tx_power));
+ len += scnprintf(buf + len, buf_len - len, "reg_ctl_domain = %u\n",
+ le32_to_cpu(htt_stats_buf->reg_ctl_domain));
+ len += scnprintf(buf + len, buf_len - len, "twice_max_rd_power = %u\n",
+ le32_to_cpu(htt_stats_buf->twice_max_rd_power));
+ len += scnprintf(buf + len, buf_len - len, "max_tx_power = %u\n",
+ le32_to_cpu(htt_stats_buf->max_tx_power));
+ len += scnprintf(buf + len, buf_len - len, "home_max_tx_power = %u\n",
+ le32_to_cpu(htt_stats_buf->home_max_tx_power));
+ len += scnprintf(buf + len, buf_len - len, "psd_power = %d\n",
+ le32_to_cpu(htt_stats_buf->psd_power));
+ len += scnprintf(buf + len, buf_len - len, "eirp_power = %u\n",
+ le32_to_cpu(htt_stats_buf->eirp_power));
+ len += scnprintf(buf + len, buf_len - len, "power_type_6ghz = %u\n",
+ le32_to_cpu(htt_stats_buf->power_type_6ghz));
+ len += print_array_to_buf(buf, len, "max_reg_allowed_power",
+ htt_stats_buf->max_reg_allowed_power,
+ ATH12K_HTT_STATS_MAX_CHAINS, "\n");
+ len += print_array_to_buf(buf, len, "max_reg_allowed_power_6ghz",
+ htt_stats_buf->max_reg_allowed_power_6ghz,
+ ATH12K_HTT_STATS_MAX_CHAINS, "\n");
+ len += print_array_to_buf(buf, len, "sub_band_cfreq",
+ htt_stats_buf->sub_band_cfreq,
+ ATH12K_HTT_MAX_CH_PWR_INFO_SIZE, "\n");
+ len += print_array_to_buf(buf, len, "sub_band_txpower",
+ htt_stats_buf->sub_band_txpower,
+ ATH12K_HTT_MAX_CH_PWR_INFO_SIZE, "\n\n");
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_soc_txrx_stats_common_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_t2h_soc_txrx_stats_common_tlv *htt_stats_buf = tag_buf;
+ u64 drop_count;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u8 *buf = stats_req->buf;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ drop_count = ath12k_le32hilo_to_u64(htt_stats_buf->inv_peers_msdu_drop_count_hi,
+ htt_stats_buf->inv_peers_msdu_drop_count_lo);
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_SOC_COMMON_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "soc_drop_count = %llu\n\n",
+ drop_count);
+
+ stats_req->buf_len = len;
+}
+
+static void
+ath12k_htt_print_tx_per_rate_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_tx_per_rate_stats_tlv *stats_buf = tag_buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 ru_size_cnt = 0;
+ u32 rc_mode, ru_type;
+ u8 *buf = stats_req->buf, i;
+ const char *mode_prefix;
+
+ if (tag_len < sizeof(*stats_buf))
+ return;
+
+ rc_mode = le32_to_cpu(stats_buf->rc_mode);
+ ru_type = le32_to_cpu(stats_buf->ru_type);
+
+ switch (rc_mode) {
+ case ATH12K_HTT_STATS_RC_MODE_DLSU:
+ len += scnprintf(buf + len, buf_len - len, "HTT_TX_PER_STATS:\n");
+ len += scnprintf(buf + len, buf_len - len, "\nPER_STATS_SU:\n");
+ mode_prefix = "su";
+ break;
+ case ATH12K_HTT_STATS_RC_MODE_DLMUMIMO:
+ len += scnprintf(buf + len, buf_len - len, "\nPER_STATS_DL_MUMIMO:\n");
+ mode_prefix = "mu";
+ break;
+ case ATH12K_HTT_STATS_RC_MODE_DLOFDMA:
+ len += scnprintf(buf + len, buf_len - len, "\nPER_STATS_DL_OFDMA:\n");
+ mode_prefix = "ofdma";
+ if (ru_type == ATH12K_HTT_STATS_RU_TYPE_SINGLE_RU_ONLY)
+ ru_size_cnt = ATH12K_HTT_TX_RX_PDEV_STATS_NUM_AX_RU_SIZE_CNTRS;
+ else if (ru_type == ATH12K_HTT_STATS_RU_TYPE_SINGLE_AND_MULTI_RU)
+ ru_size_cnt = ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS;
+ break;
+ case ATH12K_HTT_STATS_RC_MODE_ULMUMIMO:
+ len += scnprintf(buf + len, buf_len - len, "HTT_RX_PER_STATS:\n");
+ len += scnprintf(buf + len, buf_len - len, "\nPER_STATS_UL_MUMIMO:\n");
+ mode_prefix = "ulmu";
+ break;
+ case ATH12K_HTT_STATS_RC_MODE_ULOFDMA:
+ len += scnprintf(buf + len, buf_len - len, "\nPER_STATS_UL_OFDMA:\n");
+ mode_prefix = "ulofdma";
+ if (ru_type == ATH12K_HTT_STATS_RU_TYPE_SINGLE_RU_ONLY)
+ ru_size_cnt = ATH12K_HTT_TX_RX_PDEV_STATS_NUM_AX_RU_SIZE_CNTRS;
+ else if (ru_type == ATH12K_HTT_STATS_RU_TYPE_SINGLE_AND_MULTI_RU)
+ ru_size_cnt = ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS;
+ break;
+ default:
+ return;
+ }
+
+ len += scnprintf(buf + len, buf_len - len, "\nPER per BW:\n");
+ if (rc_mode == ATH12K_HTT_STATS_RC_MODE_ULOFDMA ||
+ rc_mode == ATH12K_HTT_STATS_RC_MODE_ULMUMIMO)
+ len += scnprintf(buf + len, buf_len - len, "data_ppdus_%s = ",
+ mode_prefix);
+ else
+ len += scnprintf(buf + len, buf_len - len, "ppdus_tried_%s = ",
+ mode_prefix);
+ for (i = 0; i < ATH12K_HTT_TX_PDEV_STATS_NUM_BW_CNTRS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i,
+ le32_to_cpu(stats_buf->per_bw[i].ppdus_tried));
+ len += scnprintf(buf + len, buf_len - len, " %u:%u\n", i,
+ le32_to_cpu(stats_buf->per_bw320.ppdus_tried));
+
+ if (rc_mode == ATH12K_HTT_STATS_RC_MODE_ULOFDMA ||
+ rc_mode == ATH12K_HTT_STATS_RC_MODE_ULMUMIMO)
+ len += scnprintf(buf + len, buf_len - len, "non_data_ppdus_%s = ",
+ mode_prefix);
+ else
+ len += scnprintf(buf + len, buf_len - len, "ppdus_ack_failed_%s = ",
+ mode_prefix);
+ for (i = 0; i < ATH12K_HTT_TX_PDEV_STATS_NUM_BW_CNTRS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i,
+ le32_to_cpu(stats_buf->per_bw[i].ppdus_ack_failed));
+ len += scnprintf(buf + len, buf_len - len, " %u:%u\n", i,
+ le32_to_cpu(stats_buf->per_bw320.ppdus_ack_failed));
+
+ len += scnprintf(buf + len, buf_len - len, "mpdus_tried_%s = ", mode_prefix);
+ for (i = 0; i < ATH12K_HTT_TX_PDEV_STATS_NUM_BW_CNTRS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i,
+ le32_to_cpu(stats_buf->per_bw[i].mpdus_tried));
+ len += scnprintf(buf + len, buf_len - len, " %u:%u\n", i,
+ le32_to_cpu(stats_buf->per_bw320.mpdus_tried));
+
+ len += scnprintf(buf + len, buf_len - len, "mpdus_failed_%s = ", mode_prefix);
+ for (i = 0; i < ATH12K_HTT_TX_PDEV_STATS_NUM_BW_CNTRS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u", i,
+ le32_to_cpu(stats_buf->per_bw[i].mpdus_failed));
+ len += scnprintf(buf + len, buf_len - len, " %u:%u\n", i,
+ le32_to_cpu(stats_buf->per_bw320.mpdus_failed));
+
+ len += scnprintf(buf + len, buf_len - len, "\nPER per NSS:\n");
+ if (rc_mode == ATH12K_HTT_STATS_RC_MODE_ULOFDMA ||
+ rc_mode == ATH12K_HTT_STATS_RC_MODE_ULMUMIMO)
+ len += scnprintf(buf + len, buf_len - len, "data_ppdus_%s = ",
+ mode_prefix);
+ else
+ len += scnprintf(buf + len, buf_len - len, "ppdus_tried_%s = ",
+ mode_prefix);
+ for (i = 0; i < ATH12K_HTT_PDEV_STAT_NUM_SPATIAL_STREAMS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i + 1,
+ le32_to_cpu(stats_buf->per_nss[i].ppdus_tried));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ if (rc_mode == ATH12K_HTT_STATS_RC_MODE_ULOFDMA ||
+ rc_mode == ATH12K_HTT_STATS_RC_MODE_ULMUMIMO)
+ len += scnprintf(buf + len, buf_len - len, "non_data_ppdus_%s = ",
+ mode_prefix);
+ else
+ len += scnprintf(buf + len, buf_len - len, "ppdus_ack_failed_%s = ",
+ mode_prefix);
+ for (i = 0; i < ATH12K_HTT_PDEV_STAT_NUM_SPATIAL_STREAMS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i + 1,
+ le32_to_cpu(stats_buf->per_nss[i].ppdus_ack_failed));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ len += scnprintf(buf + len, buf_len - len, "mpdus_tried_%s = ", mode_prefix);
+ for (i = 0; i < ATH12K_HTT_PDEV_STAT_NUM_SPATIAL_STREAMS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i + 1,
+ le32_to_cpu(stats_buf->per_nss[i].mpdus_tried));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ len += scnprintf(buf + len, buf_len - len, "mpdus_failed_%s = ", mode_prefix);
+ for (i = 0; i < ATH12K_HTT_PDEV_STAT_NUM_SPATIAL_STREAMS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i + 1,
+ le32_to_cpu(stats_buf->per_nss[i].mpdus_failed));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ len += scnprintf(buf + len, buf_len - len, "\nPER per MCS:\n");
+ if (rc_mode == ATH12K_HTT_STATS_RC_MODE_ULOFDMA ||
+ rc_mode == ATH12K_HTT_STATS_RC_MODE_ULMUMIMO)
+ len += scnprintf(buf + len, buf_len - len, "data_ppdus_%s = ",
+ mode_prefix);
+ else
+ len += scnprintf(buf + len, buf_len - len, "ppdus_tried_%s = ",
+ mode_prefix);
+ for (i = 0; i < ATH12K_HTT_TXBF_RATE_STAT_NUM_MCS_CNTRS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i,
+ le32_to_cpu(stats_buf->per_mcs[i].ppdus_tried));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ if (rc_mode == ATH12K_HTT_STATS_RC_MODE_ULOFDMA ||
+ rc_mode == ATH12K_HTT_STATS_RC_MODE_ULMUMIMO)
+ len += scnprintf(buf + len, buf_len - len, "non_data_ppdus_%s = ",
+ mode_prefix);
+ else
+ len += scnprintf(buf + len, buf_len - len, "ppdus_ack_failed_%s = ",
+ mode_prefix);
+ for (i = 0; i < ATH12K_HTT_TXBF_RATE_STAT_NUM_MCS_CNTRS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i,
+ le32_to_cpu(stats_buf->per_mcs[i].ppdus_ack_failed));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ len += scnprintf(buf + len, buf_len - len, "mpdus_tried_%s = ", mode_prefix);
+ for (i = 0; i < ATH12K_HTT_TXBF_RATE_STAT_NUM_MCS_CNTRS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i,
+ le32_to_cpu(stats_buf->per_mcs[i].mpdus_tried));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ len += scnprintf(buf + len, buf_len - len, "mpdus_failed_%s = ", mode_prefix);
+ for (i = 0; i < ATH12K_HTT_TXBF_RATE_STAT_NUM_MCS_CNTRS; i++)
+ len += scnprintf(buf + len, buf_len - len, " %u:%u ", i,
+ le32_to_cpu(stats_buf->per_mcs[i].mpdus_failed));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ if ((rc_mode == ATH12K_HTT_STATS_RC_MODE_DLOFDMA ||
+ rc_mode == ATH12K_HTT_STATS_RC_MODE_ULOFDMA) &&
+ ru_type != ATH12K_HTT_STATS_RU_TYPE_INVALID) {
+ len += scnprintf(buf + len, buf_len - len, "\nPER per RU:\n");
+
+ if (rc_mode == ATH12K_HTT_STATS_RC_MODE_ULOFDMA)
+ len += scnprintf(buf + len, buf_len - len, "data_ppdus_%s = ",
+ mode_prefix);
+ else
+ len += scnprintf(buf + len, buf_len - len, "ppdus_tried_%s = ",
+ mode_prefix);
+ for (i = 0; i < ru_size_cnt; i++)
+ len += scnprintf(buf + len, buf_len - len, " %s:%u ",
+ ath12k_tx_ru_size_to_str(ru_type, i),
+ le32_to_cpu(stats_buf->ru[i].ppdus_tried));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ if (rc_mode == ATH12K_HTT_STATS_RC_MODE_ULOFDMA)
+ len += scnprintf(buf + len, buf_len - len,
+ "non_data_ppdus_%s = ", mode_prefix);
+ else
+ len += scnprintf(buf + len, buf_len - len,
+ "ppdus_ack_failed_%s = ", mode_prefix);
+ for (i = 0; i < ru_size_cnt; i++)
+ len += scnprintf(buf + len, buf_len - len, " %s:%u ",
+ ath12k_tx_ru_size_to_str(ru_type, i),
+ le32_to_cpu(stats_buf->ru[i].ppdus_ack_failed));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ len += scnprintf(buf + len, buf_len - len, "mpdus_tried_%s = ",
+ mode_prefix);
+ for (i = 0; i < ru_size_cnt; i++)
+ len += scnprintf(buf + len, buf_len - len, " %s:%u ",
+ ath12k_tx_ru_size_to_str(ru_type, i),
+ le32_to_cpu(stats_buf->ru[i].mpdus_tried));
+ len += scnprintf(buf + len, buf_len - len, "\n");
+
+ len += scnprintf(buf + len, buf_len - len, "mpdus_failed_%s = ",
+ mode_prefix);
+ for (i = 0; i < ru_size_cnt; i++)
+ len += scnprintf(buf + len, buf_len - len, " %s:%u ",
+ ath12k_tx_ru_size_to_str(ru_type, i),
+ le32_to_cpu(stats_buf->ru[i].mpdus_failed));
+ len += scnprintf(buf + len, buf_len - len, "\n\n");
+ }
+
+ if (rc_mode == ATH12K_HTT_STATS_RC_MODE_DLMUMIMO) {
+ len += scnprintf(buf + len, buf_len - len, "\nlast_probed_bw = %u\n",
+ le32_to_cpu(stats_buf->last_probed_bw));
+ len += scnprintf(buf + len, buf_len - len, "last_probed_nss = %u\n",
+ le32_to_cpu(stats_buf->last_probed_nss));
+ len += scnprintf(buf + len, buf_len - len, "last_probed_mcs = %u\n",
+ le32_to_cpu(stats_buf->last_probed_mcs));
+ len += print_array_to_buf(buf, len, "MU Probe count per RC MODE",
+ stats_buf->probe_cnt,
+ ATH12K_HTT_RC_MODE_2D_COUNT, "\n\n");
+ }
+
+ stats_req->buf_len = len;
+}
+
static void
ath12k_htt_print_dmac_reset_stats_tlv(const void *tag_buf, u16 tag_len,
struct debug_htt_stats_req *stats_req)
@@ -2561,7 +3162,6 @@ ath12k_htt_print_dmac_reset_stats_tlv(const void *tag_buf, u16 tag_len,
time = ath12k_le32hilo_to_u64(htt_stats_buf->reset_time_hi_ms,
htt_stats_buf->reset_time_lo_ms);
len += scnprintf(buf + len, buf_len - len, "reset_time_ms = %llu\n", time);
-
time = ath12k_le32hilo_to_u64(htt_stats_buf->disengage_time_hi_ms,
htt_stats_buf->disengage_time_lo_ms);
len += scnprintf(buf + len, buf_len - len, "disengage_time_ms = %llu\n", time);
@@ -2680,7 +3280,7 @@ ath12k_htt_print_tx_pdev_rate_stats_be_ofdma_tlv(const void *tag_buf, u16 tag_le
len += scnprintf(buf + len, buf_len - len, "\n");
len += print_array_to_buf_index(buf, len, "be_ofdma_tx_nss = ", 1,
htt_stats_buf->be_ofdma_tx_nss,
- ATH12K_HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS,
+ ATH12K_HTT_PDEV_STAT_NUM_SPATIAL_STREAMS,
"\n");
len += print_array_to_buf(buf, len, "be_ofdma_tx_bw",
htt_stats_buf->be_ofdma_tx_bw,
@@ -2696,6 +3296,45 @@ ath12k_htt_print_tx_pdev_rate_stats_be_ofdma_tlv(const void *tag_buf, u16 tag_le
stats_req->buf_len = len;
}
+static void
+ath12k_htt_print_pdev_mbssid_ctrl_frame_stats_tlv(const void *tag_buf, u16 tag_len,
+ struct debug_htt_stats_req *stats_req)
+{
+ const struct ath12k_htt_pdev_mbssid_ctrl_frame_tlv *htt_stats_buf = tag_buf;
+ u8 *buf = stats_req->buf;
+ u32 len = stats_req->buf_len;
+ u32 buf_len = ATH12K_HTT_STATS_BUF_SIZE;
+ u32 mac_id_word;
+
+ if (tag_len < sizeof(*htt_stats_buf))
+ return;
+
+ mac_id_word = le32_to_cpu(htt_stats_buf->mac_id__word);
+
+ len += scnprintf(buf + len, buf_len - len, "HTT_MBSSID_CTRL_FRAME_STATS_TLV:\n");
+ len += scnprintf(buf + len, buf_len - len, "mac_id = %u\n",
+ u32_get_bits(mac_id_word, ATH12K_HTT_STATS_MAC_ID));
+ len += scnprintf(buf + len, buf_len - len, "basic_trigger_across_bss = %u\n",
+ le32_to_cpu(htt_stats_buf->basic_trigger_across_bss));
+ len += scnprintf(buf + len, buf_len - len, "basic_trigger_within_bss = %u\n",
+ le32_to_cpu(htt_stats_buf->basic_trigger_within_bss));
+ len += scnprintf(buf + len, buf_len - len, "bsr_trigger_across_bss = %u\n",
+ le32_to_cpu(htt_stats_buf->bsr_trigger_across_bss));
+ len += scnprintf(buf + len, buf_len - len, "bsr_trigger_within_bss = %u\n",
+ le32_to_cpu(htt_stats_buf->bsr_trigger_within_bss));
+ len += scnprintf(buf + len, buf_len - len, "mu_rts_across_bss = %u\n",
+ le32_to_cpu(htt_stats_buf->mu_rts_across_bss));
+ len += scnprintf(buf + len, buf_len - len, "mu_rts_within_bss = %u\n",
+ le32_to_cpu(htt_stats_buf->mu_rts_within_bss));
+ len += scnprintf(buf + len, buf_len - len, "ul_mumimo_trigger_across_bss = %u\n",
+ le32_to_cpu(htt_stats_buf->ul_mumimo_trigger_across_bss));
+ len += scnprintf(buf + len, buf_len - len,
+ "ul_mumimo_trigger_within_bss = %u\n\n",
+ le32_to_cpu(htt_stats_buf->ul_mumimo_trigger_within_bss));
+
+ stats_req->buf_len = len;
+}
+
static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
u16 tag, u16 len, const void *tag_buf,
void *user_data)
@@ -2869,6 +3508,30 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
case HTT_STATS_PDEV_OBSS_PD_TAG:
ath12k_htt_print_pdev_obss_pd_stats_tlv(tag_buf, len, stats_req);
break;
+ case HTT_STATS_DLPAGER_STATS_TAG:
+ ath12k_htt_print_dlpager_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PHY_STATS_TAG:
+ ath12k_htt_print_phy_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PHY_COUNTERS_TAG:
+ ath12k_htt_print_phy_counters_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PHY_RESET_STATS_TAG:
+ ath12k_htt_print_phy_reset_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PHY_RESET_COUNTERS_TAG:
+ ath12k_htt_print_phy_reset_counters_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PHY_TPC_STATS_TAG:
+ ath12k_htt_print_phy_tpc_stats_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_SOC_TXRX_STATS_COMMON_TAG:
+ ath12k_htt_print_soc_txrx_stats_common_tlv(tag_buf, len, stats_req);
+ break;
+ case HTT_STATS_PER_RATE_STATS_TAG:
+ ath12k_htt_print_tx_per_rate_stats_tlv(tag_buf, len, stats_req);
+ break;
case HTT_STATS_DMAC_RESET_STATS_TAG:
ath12k_htt_print_dmac_reset_stats_tlv(tag_buf, len, stats_req);
break;
@@ -2878,6 +3541,10 @@ static int ath12k_dbg_htt_ext_stats_parse(struct ath12k_base *ab,
case HTT_STATS_TX_PDEV_RATE_STATS_BE_OFDMA_TAG:
ath12k_htt_print_tx_pdev_rate_stats_be_ofdma_tlv(tag_buf, len, stats_req);
break;
+ case HTT_STATS_PDEV_MBSSID_CTRL_FRAME_STATS_TAG:
+ ath12k_htt_print_pdev_mbssid_ctrl_frame_stats_tlv(tag_buf, len,
+ stats_req);
+ break;
default:
break;
}
diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
index ac86cab234ec..cf3c88f8d1b2 100644
--- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
+++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.h
@@ -135,9 +135,14 @@ enum ath12k_dbg_htt_ext_stats_type {
ATH12K_DBG_HTT_EXT_STATS_PDEV_TX_MU = 17,
ATH12K_DBG_HTT_EXT_STATS_PDEV_CCA_STATS = 19,
ATH12K_DBG_HTT_EXT_STATS_PDEV_OBSS_PD_STATS = 23,
+ ATH12K_DBG_HTT_EXT_STATS_DLPAGER_STATS = 36,
+ ATH12K_DBG_HTT_EXT_PHY_COUNTERS_AND_PHY_STATS = 37,
+ ATH12K_DBG_HTT_EXT_VDEVS_TXRX_STATS = 38,
+ ATH12K_DBG_HTT_EXT_PDEV_PER_STATS = 40,
ATH12K_DBG_HTT_EXT_STATS_SOC_ERROR = 45,
ATH12K_DBG_HTT_EXT_STATS_PDEV_SCHED_ALGO = 49,
ATH12K_DBG_HTT_EXT_STATS_MANDATORY_MUOFDMA = 51,
+ ATH12K_DGB_HTT_EXT_STATS_PDEV_MBSSID_CTRL_FRAME = 54,
/* keep this last */
ATH12K_DBG_HTT_NUM_EXT_STATS,
@@ -194,6 +199,13 @@ enum ath12k_dbg_htt_tlv_tag {
HTT_STATS_PDEV_CTRL_PATH_TX_STATS_TAG = 102,
HTT_STATS_TX_SELFGEN_AC_SCHED_STATUS_STATS_TAG = 111,
HTT_STATS_TX_SELFGEN_AX_SCHED_STATUS_STATS_TAG = 112,
+ HTT_STATS_DLPAGER_STATS_TAG = 120,
+ HTT_STATS_PHY_COUNTERS_TAG = 121,
+ HTT_STATS_PHY_STATS_TAG = 122,
+ HTT_STATS_PHY_RESET_COUNTERS_TAG = 123,
+ HTT_STATS_PHY_RESET_STATS_TAG = 124,
+ HTT_STATS_SOC_TXRX_STATS_COMMON_TAG = 125,
+ HTT_STATS_PER_RATE_STATS_TAG = 128,
HTT_STATS_MU_PPDU_DIST_TAG = 129,
HTT_STATS_TX_PDEV_MUMIMO_GRP_STATS_TAG = 130,
HTT_STATS_TX_PDEV_RATE_STATS_BE_OFDMA_TAG = 135,
@@ -201,7 +213,9 @@ enum ath12k_dbg_htt_tlv_tag {
HTT_STATS_TX_SELFGEN_BE_STATS_TAG = 138,
HTT_STATS_TX_SELFGEN_BE_SCHED_STATUS_STATS_TAG = 139,
HTT_STATS_DMAC_RESET_STATS_TAG = 155,
+ HTT_STATS_PHY_TPC_STATS_TAG = 157,
HTT_STATS_PDEV_SCHED_ALGO_OFDMA_STATS_TAG = 165,
+ HTT_STATS_PDEV_MBSSID_CTRL_FRAME_STATS_TAG = 176,
HTT_STATS_MAX_TAG,
};
@@ -1054,6 +1068,132 @@ struct ath12k_htt_pdev_obss_pd_stats_tlv {
__le32 num_sr_ppdu_abort_flush_cnt;
} __packed;
+enum ath12k_htt_stats_page_lock_state {
+ ATH12K_HTT_STATS_PAGE_LOCKED = 0,
+ ATH12K_HTT_STATS_PAGE_UNLOCKED = 1,
+ ATH12K_NUM_PG_LOCK_STATE
+};
+
+#define ATH12K_PAGER_MAX 10
+
+#define ATH12K_HTT_DLPAGER_ASYNC_LOCK_PG_CNT_INFO0 GENMASK(7, 0)
+#define ATH12K_HTT_DLPAGER_SYNC_LOCK_PG_CNT_INFO0 GENMASK(15, 8)
+#define ATH12K_HTT_DLPAGER_TOTAL_LOCK_PAGES_INFO1 GENMASK(15, 0)
+#define ATH12K_HTT_DLPAGER_TOTAL_FREE_PAGES_INFO1 GENMASK(31, 16)
+#define ATH12K_HTT_DLPAGER_TOTAL_LOCK_PAGES_INFO2 GENMASK(15, 0)
+#define ATH12K_HTT_DLPAGER_TOTAL_FREE_PAGES_INFO2 GENMASK(31, 16)
+
+struct ath12k_htt_pgs_info {
+ __le32 page_num;
+ __le32 num_pgs;
+ __le32 ts_lsb;
+ __le32 ts_msb;
+} __packed;
+
+struct ath12k_htt_dl_pager_stats_tlv {
+ __le32 info0;
+ __le32 info1;
+ __le32 info2;
+ struct ath12k_htt_pgs_info pgs_info[ATH12K_NUM_PG_LOCK_STATE][ATH12K_PAGER_MAX];
+} __packed;
+
+#define ATH12K_HTT_STATS_MAX_CHAINS 8
+#define ATH12K_HTT_MAX_RX_PKT_CNT 8
+#define ATH12K_HTT_MAX_RX_PKT_CRC_PASS_CNT 8
+#define ATH12K_HTT_MAX_PER_BLK_ERR_CNT 20
+#define ATH12K_HTT_MAX_RX_OTA_ERR_CNT 14
+#define ATH12K_HTT_MAX_CH_PWR_INFO_SIZE 16
+
+struct ath12k_htt_phy_stats_tlv {
+ a_sle32 nf_chain[ATH12K_HTT_STATS_MAX_CHAINS];
+ __le32 false_radar_cnt;
+ __le32 radar_cs_cnt;
+ a_sle32 ani_level;
+ __le32 fw_run_time;
+ a_sle32 runtime_nf_chain[ATH12K_HTT_STATS_MAX_CHAINS];
+} __packed;
+
+struct ath12k_htt_phy_counters_tlv {
+ __le32 rx_ofdma_timing_err_cnt;
+ __le32 rx_cck_fail_cnt;
+ __le32 mactx_abort_cnt;
+ __le32 macrx_abort_cnt;
+ __le32 phytx_abort_cnt;
+ __le32 phyrx_abort_cnt;
+ __le32 phyrx_defer_abort_cnt;
+ __le32 rx_gain_adj_lstf_event_cnt;
+ __le32 rx_gain_adj_non_legacy_cnt;
+ __le32 rx_pkt_cnt[ATH12K_HTT_MAX_RX_PKT_CNT];
+ __le32 rx_pkt_crc_pass_cnt[ATH12K_HTT_MAX_RX_PKT_CRC_PASS_CNT];
+ __le32 per_blk_err_cnt[ATH12K_HTT_MAX_PER_BLK_ERR_CNT];
+ __le32 rx_ota_err_cnt[ATH12K_HTT_MAX_RX_OTA_ERR_CNT];
+} __packed;
+
+struct ath12k_htt_phy_reset_stats_tlv {
+ __le32 pdev_id;
+ __le32 chan_mhz;
+ __le32 chan_band_center_freq1;
+ __le32 chan_band_center_freq2;
+ __le32 chan_phy_mode;
+ __le32 chan_flags;
+ __le32 chan_num;
+ __le32 reset_cause;
+ __le32 prev_reset_cause;
+ __le32 phy_warm_reset_src;
+ __le32 rx_gain_tbl_mode;
+ __le32 xbar_val;
+ __le32 force_calibration;
+ __le32 phyrf_mode;
+ __le32 phy_homechan;
+ __le32 phy_tx_ch_mask;
+ __le32 phy_rx_ch_mask;
+ __le32 phybb_ini_mask;
+ __le32 phyrf_ini_mask;
+ __le32 phy_dfs_en_mask;
+ __le32 phy_sscan_en_mask;
+ __le32 phy_synth_sel_mask;
+ __le32 phy_adfs_freq;
+ __le32 cck_fir_settings;
+ __le32 phy_dyn_pri_chan;
+ __le32 cca_thresh;
+ __le32 dyn_cca_status;
+ __le32 rxdesense_thresh_hw;
+ __le32 rxdesense_thresh_sw;
+} __packed;
+
+struct ath12k_htt_phy_reset_counters_tlv {
+ __le32 pdev_id;
+ __le32 cf_active_low_fail_cnt;
+ __le32 cf_active_low_pass_cnt;
+ __le32 phy_off_through_vreg_cnt;
+ __le32 force_calibration_cnt;
+ __le32 rf_mode_switch_phy_off_cnt;
+ __le32 temperature_recal_cnt;
+} __packed;
+
+struct ath12k_htt_phy_tpc_stats_tlv {
+ __le32 pdev_id;
+ __le32 tx_power_scale;
+ __le32 tx_power_scale_db;
+ __le32 min_negative_tx_power;
+ __le32 reg_ctl_domain;
+ __le32 max_reg_allowed_power[ATH12K_HTT_STATS_MAX_CHAINS];
+ __le32 max_reg_allowed_power_6ghz[ATH12K_HTT_STATS_MAX_CHAINS];
+ __le32 twice_max_rd_power;
+ __le32 max_tx_power;
+ __le32 home_max_tx_power;
+ __le32 psd_power;
+ __le32 eirp_power;
+ __le32 power_type_6ghz;
+ __le32 sub_band_cfreq[ATH12K_HTT_MAX_CH_PWR_INFO_SIZE];
+ __le32 sub_band_txpower[ATH12K_HTT_MAX_CH_PWR_INFO_SIZE];
+} __packed;
+
+struct ath12k_htt_t2h_soc_txrx_stats_common_tlv {
+ __le32 inv_peers_msdu_drop_count_hi;
+ __le32 inv_peers_msdu_drop_count_lo;
+} __packed;
+
struct ath12k_htt_dmac_reset_stats_tlv {
__le32 reset_count;
__le32 reset_time_lo_ms;
@@ -1085,6 +1225,10 @@ struct ath12k_htt_pdev_sched_algo_ofdma_stats_tlv {
__le32 dlofdma_disabled_consec_no_mpdus_success[ATH12K_HTT_NUM_AC_WMM];
} __packed;
+#define ATH12K_HTT_TX_PDEV_STATS_NUM_BW_CNTRS 4
+#define ATH12K_HTT_PDEV_STAT_NUM_SPATIAL_STREAMS 8
+#define ATH12K_HTT_TXBF_RATE_STAT_NUM_MCS_CNTRS 14
+
enum ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE {
ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_26,
ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE_52,
@@ -1105,7 +1249,65 @@ enum ATH12K_HTT_TX_RX_PDEV_STATS_BE_RU_SIZE {
ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS,
};
-#define ATH12K_HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS 8
+enum ATH12K_HTT_RC_MODE {
+ ATH12K_HTT_RC_MODE_SU_OL,
+ ATH12K_HTT_RC_MODE_SU_BF,
+ ATH12K_HTT_RC_MODE_MU1_INTF,
+ ATH12K_HTT_RC_MODE_MU2_INTF,
+ ATH12K_HTT_RC_MODE_MU3_INTF,
+ ATH12K_HTT_RC_MODE_MU4_INTF,
+ ATH12K_HTT_RC_MODE_MU5_INTF,
+ ATH12K_HTT_RC_MODE_MU6_INTF,
+ ATH12K_HTT_RC_MODE_MU7_INTF,
+ ATH12K_HTT_RC_MODE_2D_COUNT
+};
+
+enum ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE {
+ ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_26,
+ ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_52,
+ ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_106,
+ ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_242,
+ ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_484,
+ ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_996,
+ ATH12K_HTT_TX_RX_PDEV_STATS_AX_RU_SIZE_996x2,
+ ATH12K_HTT_TX_RX_PDEV_STATS_NUM_AX_RU_SIZE_CNTRS
+};
+
+enum ath12k_htt_stats_rc_mode {
+ ATH12K_HTT_STATS_RC_MODE_DLSU = 0,
+ ATH12K_HTT_STATS_RC_MODE_DLMUMIMO = 1,
+ ATH12K_HTT_STATS_RC_MODE_DLOFDMA = 2,
+ ATH12K_HTT_STATS_RC_MODE_ULMUMIMO = 3,
+ ATH12K_HTT_STATS_RC_MODE_ULOFDMA = 4,
+};
+
+enum ath12k_htt_stats_ru_type {
+ ATH12K_HTT_STATS_RU_TYPE_INVALID,
+ ATH12K_HTT_STATS_RU_TYPE_SINGLE_RU_ONLY,
+ ATH12K_HTT_STATS_RU_TYPE_SINGLE_AND_MULTI_RU,
+};
+
+struct ath12k_htt_tx_rate_stats {
+ __le32 ppdus_tried;
+ __le32 ppdus_ack_failed;
+ __le32 mpdus_tried;
+ __le32 mpdus_failed;
+} __packed;
+
+struct ath12k_htt_tx_per_rate_stats_tlv {
+ __le32 rc_mode;
+ __le32 last_probed_mcs;
+ __le32 last_probed_nss;
+ __le32 last_probed_bw;
+ struct ath12k_htt_tx_rate_stats per_bw[ATH12K_HTT_TX_PDEV_STATS_NUM_BW_CNTRS];
+ struct ath12k_htt_tx_rate_stats per_nss[ATH12K_HTT_PDEV_STAT_NUM_SPATIAL_STREAMS];
+ struct ath12k_htt_tx_rate_stats per_mcs[ATH12K_HTT_TXBF_RATE_STAT_NUM_MCS_CNTRS];
+ struct ath12k_htt_tx_rate_stats per_bw320;
+ __le32 probe_cnt[ATH12K_HTT_RC_MODE_2D_COUNT];
+ __le32 ru_type;
+ struct ath12k_htt_tx_rate_stats ru[ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS];
+} __packed;
+
#define ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS 16
#define ATH12K_HTT_TX_PDEV_NUM_BE_BW_CNTRS 5
#define ATH12K_HTT_TX_PDEV_NUM_EHT_SIG_MCS_CNTRS 4
@@ -1115,11 +1317,23 @@ struct ath12k_htt_tx_pdev_rate_stats_be_ofdma_tlv {
__le32 mac_id__word;
__le32 be_ofdma_tx_ldpc;
__le32 be_ofdma_tx_mcs[ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS];
- __le32 be_ofdma_tx_nss[ATH12K_HTT_TX_PDEV_STATS_NUM_SPATIAL_STREAMS];
+ __le32 be_ofdma_tx_nss[ATH12K_HTT_PDEV_STAT_NUM_SPATIAL_STREAMS];
__le32 be_ofdma_tx_bw[ATH12K_HTT_TX_PDEV_NUM_BE_BW_CNTRS];
__le32 gi[ATH12K_HTT_TX_PDEV_NUM_GI_CNTRS][ATH12K_HTT_TX_PDEV_NUM_BE_MCS_CNTRS];
__le32 be_ofdma_tx_ru_size[ATH12K_HTT_TX_RX_PDEV_NUM_BE_RU_SIZE_CNTRS];
__le32 be_ofdma_eht_sig_mcs[ATH12K_HTT_TX_PDEV_NUM_EHT_SIG_MCS_CNTRS];
} __packed;
+struct ath12k_htt_pdev_mbssid_ctrl_frame_tlv {
+ __le32 mac_id__word;
+ __le32 basic_trigger_across_bss;
+ __le32 basic_trigger_within_bss;
+ __le32 bsr_trigger_across_bss;
+ __le32 bsr_trigger_within_bss;
+ __le32 mu_rts_across_bss;
+ __le32 mu_rts_within_bss;
+ __le32 ul_mumimo_trigger_across_bss;
+ __le32 ul_mumimo_trigger_within_bss;
+} __packed;
+
#endif
diff --git a/drivers/net/wireless/ath/ath12k/dp.c b/drivers/net/wireless/ath/ath12k/dp.c
index c99e9ceb1a6e..68abe9d4ab45 100644
--- a/drivers/net/wireless/ath/ath12k/dp.c
+++ b/drivers/net/wireless/ath/ath12k/dp.c
@@ -41,6 +41,11 @@ void ath12k_dp_peer_cleanup(struct ath12k *ar, int vdev_id, const u8 *addr)
return;
}
+ if (!peer->primary_link) {
+ spin_unlock_bh(&ab->base_lock);
+ return;
+ }
+
ath12k_dp_rx_peer_tid_cleanup(ar, peer);
crypto_free_shash(peer->tfm_mmic);
peer->dp_setup_done = false;
@@ -977,27 +982,23 @@ void ath12k_dp_pdev_free(struct ath12k_base *ab)
{
int i;
+ if (!ab->mon_reap_timer.function)
+ return;
+
del_timer_sync(&ab->mon_reap_timer);
for (i = 0; i < ab->num_radios; i++)
ath12k_dp_rx_pdev_free(ab, i);
}
-void ath12k_dp_pdev_pre_alloc(struct ath12k_base *ab)
+void ath12k_dp_pdev_pre_alloc(struct ath12k *ar)
{
- struct ath12k *ar;
- struct ath12k_pdev_dp *dp;
- int i;
+ struct ath12k_pdev_dp *dp = &ar->dp;
- for (i = 0; i < ab->num_radios; i++) {
- ar = ab->pdevs[i].ar;
- dp = &ar->dp;
- dp->mac_id = i;
- atomic_set(&dp->num_tx_pending, 0);
- init_waitqueue_head(&dp->tx_empty_waitq);
-
- /* TODO: Add any RXDMA setup required per pdev */
- }
+ dp->mac_id = ar->pdev_idx;
+ atomic_set(&dp->num_tx_pending, 0);
+ init_waitqueue_head(&dp->tx_empty_waitq);
+ /* TODO: Add any RXDMA setup required per pdev */
}
bool ath12k_dp_wmask_compaction_rx_tlv_supported(struct ath12k_base *ab)
@@ -1260,15 +1261,23 @@ static void ath12k_dp_reoq_lut_cleanup(struct ath12k_base *ab)
if (!ab->hw_params->reoq_lut_support)
return;
- if (!dp->reoq_lut.vaddr)
- return;
-
- dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
- dp->reoq_lut.vaddr, dp->reoq_lut.paddr);
- dp->reoq_lut.vaddr = NULL;
+ if (dp->reoq_lut.vaddr) {
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_REO_REG +
+ HAL_REO1_QDESC_LUT_BASE0(ab), 0);
+ dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
+ dp->reoq_lut.vaddr, dp->reoq_lut.paddr);
+ dp->reoq_lut.vaddr = NULL;
+ }
- ath12k_hif_write32(ab,
- HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab), 0);
+ if (dp->ml_reoq_lut.vaddr) {
+ ath12k_hif_write32(ab,
+ HAL_SEQ_WCSS_UMAC_REO_REG +
+ HAL_REO1_QDESC_LUT_BASE1(ab), 0);
+ dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
+ dp->ml_reoq_lut.vaddr, dp->ml_reoq_lut.paddr);
+ dp->ml_reoq_lut.vaddr = NULL;
+ }
}
void ath12k_dp_free(struct ath12k_base *ab)
@@ -1276,6 +1285,9 @@ void ath12k_dp_free(struct ath12k_base *ab)
struct ath12k_dp *dp = &ab->dp;
int i;
+ if (!dp->ab)
+ return;
+
ath12k_dp_link_desc_cleanup(ab, dp->link_desc_banks,
HAL_WBM_IDLE_LINK, &dp->wbm_idle_ring);
@@ -1293,6 +1305,7 @@ void ath12k_dp_free(struct ath12k_base *ab)
ath12k_dp_rx_free(ab);
/* Deinit any SOC level resource */
+ dp->ab = NULL;
}
void ath12k_dp_cc_config(struct ath12k_base *ab)
@@ -1594,8 +1607,23 @@ static int ath12k_dp_reoq_lut_setup(struct ath12k_base *ab)
return -ENOMEM;
}
+ dp->ml_reoq_lut.vaddr = dma_alloc_coherent(ab->dev,
+ DP_REOQ_LUT_SIZE,
+ &dp->ml_reoq_lut.paddr,
+ GFP_KERNEL | __GFP_ZERO);
+ if (!dp->ml_reoq_lut.vaddr) {
+ ath12k_warn(ab, "failed to allocate memory for ML reoq table");
+ dma_free_coherent(ab->dev, DP_REOQ_LUT_SIZE,
+ dp->reoq_lut.vaddr, dp->reoq_lut.paddr);
+ dp->reoq_lut.vaddr = NULL;
+ return -ENOMEM;
+ }
+
ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE0(ab),
dp->reoq_lut.paddr);
+ ath12k_hif_write32(ab, HAL_SEQ_WCSS_UMAC_REO_REG + HAL_REO1_QDESC_LUT_BASE1(ab),
+ dp->ml_reoq_lut.paddr >> 8);
+
return 0;
}
diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h
index 2e05fc19410e..021cd9e8ee1d 100644
--- a/drivers/net/wireless/ath/ath12k/dp.h
+++ b/drivers/net/wireless/ath/ath12k/dp.h
@@ -368,6 +368,7 @@ struct ath12k_dp {
struct dp_rxdma_mon_ring rxdma_mon_buf_ring;
struct dp_rxdma_mon_ring tx_mon_buf_ring;
struct ath12k_reo_q_addr_lut reoq_lut;
+ struct ath12k_reo_q_addr_lut ml_reoq_lut;
};
/* HTT definitions */
@@ -1805,7 +1806,7 @@ void ath12k_dp_free(struct ath12k_base *ab);
int ath12k_dp_alloc(struct ath12k_base *ab);
void ath12k_dp_cc_config(struct ath12k_base *ab);
int ath12k_dp_pdev_alloc(struct ath12k_base *ab);
-void ath12k_dp_pdev_pre_alloc(struct ath12k_base *ab);
+void ath12k_dp_pdev_pre_alloc(struct ath12k *ar);
void ath12k_dp_pdev_free(struct ath12k_base *ab);
int ath12k_dp_tx_htt_srng_setup(struct ath12k_base *ab, u32 ring_id,
int mac_id, enum hal_ring_type ring_type);
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index 9ae579e50557..b24d1de4aabb 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -740,15 +740,22 @@ static void ath12k_peer_rx_tid_qref_setup(struct ath12k_base *ab, u16 peer_id, u
{
struct ath12k_reo_queue_ref *qref;
struct ath12k_dp *dp = &ab->dp;
+ bool ml_peer = false;
if (!ab->hw_params->reoq_lut_support)
return;
- /* TODO: based on ML peer or not, select the LUT. below assumes non
- * ML peer
- */
- qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
- (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+ if (peer_id & ATH12K_PEER_ML_ID_VALID) {
+ peer_id &= ~ATH12K_PEER_ML_ID_VALID;
+ ml_peer = true;
+ }
+
+ if (ml_peer)
+ qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr +
+ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+ else
+ qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
+ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
qref->info0 = u32_encode_bits(lower_32_bits(paddr),
BUFFER_ADDR_INFO0_ADDR);
@@ -761,15 +768,22 @@ static void ath12k_peer_rx_tid_qref_reset(struct ath12k_base *ab, u16 peer_id, u
{
struct ath12k_reo_queue_ref *qref;
struct ath12k_dp *dp = &ab->dp;
+ bool ml_peer = false;
if (!ab->hw_params->reoq_lut_support)
return;
- /* TODO: based on ML peer or not, select the LUT. below assumes non
- * ML peer
- */
- qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
- (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+ if (peer_id & ATH12K_PEER_ML_ID_VALID) {
+ peer_id &= ~ATH12K_PEER_ML_ID_VALID;
+ ml_peer = true;
+ }
+
+ if (ml_peer)
+ qref = (struct ath12k_reo_queue_ref *)dp->ml_reoq_lut.vaddr +
+ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
+ else
+ qref = (struct ath12k_reo_queue_ref *)dp->reoq_lut.vaddr +
+ (peer_id * (IEEE80211_NUM_TIDS + 1) + tid);
qref->info0 = u32_encode_bits(0, BUFFER_ADDR_INFO0_ADDR);
qref->info1 = u32_encode_bits(0, BUFFER_ADDR_INFO1_ADDR) |
@@ -802,7 +816,10 @@ void ath12k_dp_rx_peer_tid_delete(struct ath12k *ar,
rx_tid->vaddr = NULL;
}
- ath12k_peer_rx_tid_qref_reset(ar->ab, peer->peer_id, tid);
+ if (peer->mlo)
+ ath12k_peer_rx_tid_qref_reset(ar->ab, peer->ml_id, tid);
+ else
+ ath12k_peer_rx_tid_qref_reset(ar->ab, peer->peer_id, tid);
rx_tid->active = false;
}
@@ -940,7 +957,13 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
return -ENOENT;
}
- if (ab->hw_params->reoq_lut_support && !dp->reoq_lut.vaddr) {
+ if (!peer->primary_link) {
+ spin_unlock_bh(&ab->base_lock);
+ return 0;
+ }
+
+ if (ab->hw_params->reoq_lut_support &&
+ (!dp->reoq_lut.vaddr || !dp->ml_reoq_lut.vaddr)) {
spin_unlock_bh(&ab->base_lock);
ath12k_warn(ab, "reo qref table is not setup\n");
return -EINVAL;
@@ -1021,7 +1044,11 @@ int ath12k_dp_rx_peer_tid_setup(struct ath12k *ar, const u8 *peer_mac, int vdev_
/* Update the REO queue LUT at the corresponding peer id
* and tid with qaddr.
*/
- ath12k_peer_rx_tid_qref_setup(ab, peer->peer_id, tid, paddr);
+ if (peer->mlo)
+ ath12k_peer_rx_tid_qref_setup(ab, peer->ml_id, tid, paddr);
+ else
+ ath12k_peer_rx_tid_qref_setup(ab, peer->peer_id, tid, paddr);
+
spin_unlock_bh(&ab->base_lock);
} else {
spin_unlock_bh(&ab->base_lock);
@@ -1038,15 +1065,25 @@ err_mem_free:
}
int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
- struct ieee80211_ampdu_params *params)
+ struct ieee80211_ampdu_params *params,
+ u8 link_id)
{
struct ath12k_base *ab = ar->ab;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
- struct ath12k_link_sta *arsta = &ahsta->deflink;
- int vdev_id = arsta->arvif->vdev_id;
+ struct ath12k_link_sta *arsta;
+ int vdev_id;
int ret;
- ret = ath12k_dp_rx_peer_tid_setup(ar, params->sta->addr, vdev_id,
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
+ ahsta->link[link_id]);
+ if (!arsta)
+ return -ENOLINK;
+
+ vdev_id = arsta->arvif->vdev_id;
+
+ ret = ath12k_dp_rx_peer_tid_setup(ar, arsta->addr, vdev_id,
params->tid, params->buf_size,
params->ssn, arsta->ahsta->pn_type);
if (ret)
@@ -1056,19 +1093,29 @@ int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
}
int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
- struct ieee80211_ampdu_params *params)
+ struct ieee80211_ampdu_params *params,
+ u8 link_id)
{
struct ath12k_base *ab = ar->ab;
struct ath12k_peer *peer;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(params->sta);
- struct ath12k_link_sta *arsta = &ahsta->deflink;
- int vdev_id = arsta->arvif->vdev_id;
+ struct ath12k_link_sta *arsta;
+ int vdev_id;
bool active;
int ret;
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
+ ahsta->link[link_id]);
+ if (!arsta)
+ return -ENOLINK;
+
+ vdev_id = arsta->arvif->vdev_id;
+
spin_lock_bh(&ab->base_lock);
- peer = ath12k_peer_find(ab, vdev_id, params->sta->addr);
+ peer = ath12k_peer_find(ab, vdev_id, arsta->addr);
if (!peer) {
spin_unlock_bh(&ab->base_lock);
ath12k_warn(ab, "failed to find the peer to stop rx aggregation\n");
@@ -2781,6 +2828,11 @@ int ath12k_dp_rx_peer_frag_setup(struct ath12k *ar, const u8 *peer_mac, int vdev
return -ENOENT;
}
+ if (!peer->primary_link) {
+ spin_unlock_bh(&ab->base_lock);
+ return 0;
+ }
+
for (i = 0; i <= IEEE80211_NUM_TIDS; i++) {
rx_tid = &peer->rx_tid[i];
rx_tid->ab = ab;
@@ -3912,7 +3964,7 @@ void ath12k_dp_rx_process_reo_status(struct ath12k_base *ab)
ath12k_hal_srng_access_begin(ab, srng);
while ((hdr = ath12k_hal_srng_dst_get_next_entry(ab, srng))) {
- tag = u64_get_bits(hdr->tl, HAL_SRNG_TLV_HDR_TAG);
+ tag = le64_get_bits(hdr->tl, HAL_SRNG_TLV_HDR_TAG);
switch (tag) {
case HAL_REO_GET_QUEUE_STATS_STATUS:
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.h b/drivers/net/wireless/ath/ath12k/dp_rx.h
index bfd4f814553e..1ce82088c954 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.h
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.h
@@ -85,9 +85,11 @@ static inline u32 ath12k_he_gi_to_nl80211_he_gi(u8 sgi)
}
int ath12k_dp_rx_ampdu_start(struct ath12k *ar,
- struct ieee80211_ampdu_params *params);
+ struct ieee80211_ampdu_params *params,
+ u8 link_id);
int ath12k_dp_rx_ampdu_stop(struct ath12k *ar,
- struct ieee80211_ampdu_params *params);
+ struct ieee80211_ampdu_params *params,
+ u8 link_id);
int ath12k_dp_rx_peer_pn_replay_config(struct ath12k_link_vif *arvif,
const u8 *peer_addr,
enum set_key_cmd key_cmd,
diff --git a/drivers/net/wireless/ath/ath12k/hal_desc.h b/drivers/net/wireless/ath/ath12k/hal_desc.h
index 739f73370015..a460d432288f 100644
--- a/drivers/net/wireless/ath/ath12k/hal_desc.h
+++ b/drivers/net/wireless/ath/ath12k/hal_desc.h
@@ -581,7 +581,7 @@ struct hal_tlv_hdr {
#define HAL_TLV_64_HDR_LEN GENMASK(21, 10)
struct hal_tlv_64_hdr {
- u64 tl;
+ __le64 tl;
u8 value[];
} __packed;
diff --git a/drivers/net/wireless/ath/ath12k/hal_rx.c b/drivers/net/wireless/ath/ath12k/hal_rx.c
index f7c1aaa3b5d4..ac17d6223fa7 100644
--- a/drivers/net/wireless/ath/ath12k/hal_rx.c
+++ b/drivers/net/wireless/ath/ath12k/hal_rx.c
@@ -26,8 +26,8 @@ static int ath12k_hal_reo_cmd_queue_stats(struct hal_tlv_64_hdr *tlv,
{
struct hal_reo_get_queue_stats *desc;
- tlv->tl = u32_encode_bits(HAL_REO_GET_QUEUE_STATS, HAL_TLV_HDR_TAG) |
- u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
+ tlv->tl = le64_encode_bits(HAL_REO_GET_QUEUE_STATS, HAL_TLV_HDR_TAG) |
+ le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
desc = (struct hal_reo_get_queue_stats *)tlv->value;
memset_startat(desc, 0, queue_addr_lo);
@@ -59,8 +59,8 @@ static int ath12k_hal_reo_cmd_flush_cache(struct ath12k_hal *hal,
hal->current_blk_index = avail_slot;
}
- tlv->tl = u32_encode_bits(HAL_REO_FLUSH_CACHE, HAL_TLV_HDR_TAG) |
- u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
+ tlv->tl = le64_encode_bits(HAL_REO_FLUSH_CACHE, HAL_TLV_HDR_TAG) |
+ le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
desc = (struct hal_reo_flush_cache *)tlv->value;
memset_startat(desc, 0, cache_addr_lo);
@@ -97,8 +97,8 @@ static int ath12k_hal_reo_cmd_update_rx_queue(struct hal_tlv_64_hdr *tlv,
{
struct hal_reo_update_rx_queue *desc;
- tlv->tl = u32_encode_bits(HAL_REO_UPDATE_RX_REO_QUEUE, HAL_TLV_HDR_TAG) |
- u32_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
+ tlv->tl = le64_encode_bits(HAL_REO_UPDATE_RX_REO_QUEUE, HAL_TLV_HDR_TAG) |
+ le64_encode_bits(sizeof(*desc), HAL_TLV_HDR_LEN);
desc = (struct hal_reo_update_rx_queue *)tlv->value;
memset_startat(desc, 0, queue_addr_lo);
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index d493ec812055..c4eab4c1c10e 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -501,6 +501,41 @@ static int ath12k_mac_vif_link_chan(struct ieee80211_vif *vif, u8 link_id,
return 0;
}
+static struct ieee80211_bss_conf *
+ath12k_mac_get_link_bss_conf(struct ath12k_link_vif *arvif)
+{
+ struct ieee80211_vif *vif = arvif->ahvif->vif;
+ struct ieee80211_bss_conf *link_conf;
+ struct ath12k *ar = arvif->ar;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ if (arvif->link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
+ return NULL;
+
+ link_conf = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
+ vif->link_conf[arvif->link_id]);
+
+ return link_conf;
+}
+
+static struct ieee80211_link_sta *ath12k_mac_get_link_sta(struct ath12k_link_sta *arsta)
+{
+ struct ath12k_sta *ahsta = arsta->ahsta;
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);
+ struct ieee80211_link_sta *link_sta;
+
+ lockdep_assert_wiphy(ahsta->ahvif->ah->hw->wiphy);
+
+ if (arsta->link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
+ return NULL;
+
+ link_sta = wiphy_dereference(ahsta->ahvif->ah->hw->wiphy,
+ sta->link[arsta->link_id]);
+
+ return link_sta;
+}
+
static bool ath12k_mac_bitrate_is_cck(int bitrate)
{
switch (bitrate) {
@@ -648,6 +683,18 @@ struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id)
return NULL;
}
+static bool ath12k_mac_is_ml_arvif(struct ath12k_link_vif *arvif)
+{
+ struct ath12k_vif *ahvif = arvif->ahvif;
+
+ lockdep_assert_wiphy(ahvif->ah->hw->wiphy);
+
+ if (ahvif->vif->valid_links & BIT(arvif->link_id))
+ return true;
+
+ return false;
+}
+
static struct ath12k *ath12k_mac_get_ar_by_chan(struct ieee80211_hw *hw,
struct ieee80211_channel *channel)
{
@@ -678,11 +725,14 @@ static struct ath12k *ath12k_get_ar_by_ctx(struct ieee80211_hw *hw,
}
static struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
+ struct ieee80211_vif *vif,
+ u8 link_id)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
- struct ath12k_link_vif *arvif = &ahvif->deflink;
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
+ struct ath12k_link_vif *arvif;
+
+ lockdep_assert_wiphy(hw->wiphy);
/* If there is one pdev within ah, then we return
* ar directly.
@@ -690,7 +740,11 @@ static struct ath12k *ath12k_get_ar_by_vif(struct ieee80211_hw *hw,
if (ah->num_radio == 1)
return ah->radio;
- if (arvif->is_created)
+ if (!(ahvif->links_map & BIT(link_id)))
+ return NULL;
+
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (arvif && arvif->is_created)
return arvif->ar;
return NULL;
@@ -1239,7 +1293,7 @@ static int ath12k_mac_monitor_stop(struct ath12k *ar)
return ret;
}
-static int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif)
+int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif)
{
struct ath12k_vif *ahvif = arvif->ahvif;
struct ath12k *ar = arvif->ar;
@@ -1486,7 +1540,7 @@ static void ath12k_mac_set_arvif_ies(struct ath12k_link_vif *arvif, struct sk_bu
static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_link_vif *arvif)
{
struct ath12k_vif *ahvif = arvif->ahvif;
- struct ieee80211_bss_conf *bss_conf = &ahvif->vif->bss_conf;
+ struct ieee80211_bss_conf *bss_conf;
struct ath12k_wmi_bcn_tmpl_ema_arg ema_args;
struct ieee80211_ema_beacons *beacons;
struct ath12k_link_vif *tx_arvif;
@@ -1495,10 +1549,19 @@ static int ath12k_mac_setup_bcn_tmpl_ema(struct ath12k_link_vif *arvif)
int ret = 0;
u8 i;
+ bss_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!bss_conf) {
+ ath12k_warn(arvif->ar->ab,
+ "failed to get link bss conf to update bcn tmpl for vif %pM link %u\n",
+ ahvif->vif->addr, arvif->link_id);
+ return -ENOLINK;
+ }
+
tx_ahvif = ath12k_vif_to_ahvif(ahvif->vif->mbssid_tx_vif);
tx_arvif = &tx_ahvif->deflink;
beacons = ieee80211_beacon_get_template_ema_list(ath12k_ar_to_hw(tx_arvif->ar),
- tx_ahvif->vif, 0);
+ tx_ahvif->vif,
+ tx_arvif->link_id);
if (!beacons || !beacons->cnt) {
ath12k_warn(arvif->ar->ab,
"failed to get ema beacon templates from mac80211\n");
@@ -1540,6 +1603,7 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif)
{
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
+ struct ieee80211_bss_conf *link_conf;
struct ath12k_link_vif *tx_arvif = arvif;
struct ath12k *ar = arvif->ar;
struct ath12k_base *ab = ar->ab;
@@ -1552,18 +1616,25 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif)
if (ahvif->vdev_type != WMI_VDEV_TYPE_AP)
return 0;
+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!link_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf to set bcn tmpl for vif %pM link %u\n",
+ vif->addr, arvif->link_id);
+ return -ENOLINK;
+ }
+
if (vif->mbssid_tx_vif) {
tx_ahvif = ath12k_vif_to_ahvif(vif->mbssid_tx_vif);
tx_arvif = &tx_ahvif->deflink;
if (tx_arvif != arvif && arvif->is_up)
return 0;
- if (vif->bss_conf.ema_ap)
+ if (link_conf->ema_ap)
return ath12k_mac_setup_bcn_tmpl_ema(arvif);
}
bcn = ieee80211_beacon_get_template(ath12k_ar_to_hw(tx_arvif->ar), tx_ahvif->vif,
- &offs, 0);
+ &offs, tx_arvif->link_id);
if (!bcn) {
ath12k_warn(ab, "failed to get beacon template from mac80211\n");
return -EPERM;
@@ -1573,7 +1644,7 @@ static int ath12k_mac_setup_bcn_tmpl(struct ath12k_link_vif *arvif)
ath12k_mac_set_arvif_ies(arvif, bcn, 0, NULL);
} else {
ath12k_mac_set_arvif_ies(arvif, bcn,
- ahvif->vif->bss_conf.bssid_index,
+ link_conf->bssid_index,
&nontx_profile_found);
if (!nontx_profile_found)
ath12k_warn(ab,
@@ -1644,7 +1715,7 @@ static void ath12k_control_beaconing(struct ath12k_link_vif *arvif,
ahvif->aid = 0;
- ether_addr_copy(arvif->bssid, info->bssid);
+ ether_addr_copy(arvif->bssid, info->addr);
params.vdev_id = arvif->vdev_id;
params.aid = ahvif->aid;
@@ -1749,6 +1820,7 @@ static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
+ struct ieee80211_bss_conf *bss_conf;
u32 aid;
lockdep_assert_wiphy(hw->wiphy);
@@ -1758,14 +1830,22 @@ static void ath12k_peer_assoc_h_basic(struct ath12k *ar,
else
aid = sta->aid;
- ether_addr_copy(arg->peer_mac, sta->addr);
+ ether_addr_copy(arg->peer_mac, arsta->addr);
arg->vdev_id = arvif->vdev_id;
arg->peer_associd = aid;
arg->auth_flag = true;
/* TODO: STA WAR in ath10k for listen interval required? */
arg->peer_listen_intval = hw->conf.listen_interval;
arg->peer_nss = 1;
- arg->peer_caps = vif->bss_conf.assoc_capability;
+
+ bss_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!bss_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in peer assoc for vif %pM link %u\n",
+ vif->addr, arvif->link_id);
+ return;
+ }
+
+ arg->peer_caps = bss_conf->assoc_capability;
}
static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
@@ -1775,7 +1855,7 @@ static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
{
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- struct ieee80211_bss_conf *info = &vif->bss_conf;
+ struct ieee80211_bss_conf *info;
struct cfg80211_chan_def def;
struct cfg80211_bss *bss;
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
@@ -1784,6 +1864,13 @@ static void ath12k_peer_assoc_h_crypto(struct ath12k *ar,
lockdep_assert_wiphy(hw->wiphy);
+ info = ath12k_mac_get_link_bss_conf(arvif);
+ if (!info) {
+ ath12k_warn(ar->ab, "unable to access bss link conf for peer assoc crypto for vif %pM link %u\n",
+ vif->addr, arvif->link_id);
+ return;
+ }
+
if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
@@ -1839,6 +1926,7 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct wmi_rate_set_arg *rateset = &arg->peer_legacy_rates;
+ struct ieee80211_link_sta *link_sta;
struct cfg80211_chan_def def;
const struct ieee80211_supported_band *sband;
const struct ieee80211_rate *rates;
@@ -1853,9 +1941,16 @@ static void ath12k_peer_assoc_h_rates(struct ath12k *ar,
if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (!link_sta) {
+ ath12k_warn(ar->ab, "unable to access link sta in peer assoc rates for sta %pM link %u\n",
+ sta->addr, arsta->link_id);
+ return;
+ }
+
band = def.chan->band;
sband = hw->wiphy->bands[band];
- ratemask = sta->deflink.supp_rates[band];
+ ratemask = link_sta->supp_rates[band];
ratemask &= arvif->bitrate_mask.control[band].legacy;
rates = sband->bitrates;
@@ -1902,7 +1997,8 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
{
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
+ const struct ieee80211_sta_ht_cap *ht_cap;
+ struct ieee80211_link_sta *link_sta;
struct cfg80211_chan_def def;
enum nl80211_band band;
const u8 *ht_mcs_mask;
@@ -1915,6 +2011,14 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (!link_sta) {
+ ath12k_warn(ar->ab, "unable to access link sta in peer assoc ht for sta %pM link %u\n",
+ sta->addr, arsta->link_id);
+ return;
+ }
+
+ ht_cap = &link_sta->ht_cap;
if (!ht_cap->ht_supported)
return;
@@ -1938,7 +2042,7 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
if (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)
arg->ldpc_flag = true;
- if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40) {
+ if (link_sta->bandwidth >= IEEE80211_STA_RX_BW_40) {
arg->bw_40 = true;
arg->peer_rate_caps |= WMI_HOST_RC_CW40_FLAG;
}
@@ -1988,7 +2092,7 @@ static void ath12k_peer_assoc_h_ht(struct ath12k *ar,
arg->peer_ht_rates.rates[i] = i;
} else {
arg->peer_ht_rates.num_rates = n;
- arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
+ arg->peer_nss = min(link_sta->rx_nss, max_nss);
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac ht peer %pM mcs cnt %d nss %d\n",
@@ -2064,7 +2168,8 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
{
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- const struct ieee80211_sta_vht_cap *vht_cap = &sta->deflink.vht_cap;
+ const struct ieee80211_sta_vht_cap *vht_cap;
+ struct ieee80211_link_sta *link_sta;
struct cfg80211_chan_def def;
enum nl80211_band band;
const u16 *vht_mcs_mask;
@@ -2078,6 +2183,14 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return;
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (!link_sta) {
+ ath12k_warn(ar->ab, "unable to access link sta in peer assoc vht for sta %pM link %u\n",
+ sta->addr, arsta->link_id);
+ return;
+ }
+
+ vht_cap = &link_sta->vht_cap;
if (!vht_cap->vht_supported)
return;
@@ -2110,10 +2223,10 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
(1U << (IEEE80211_HT_MAX_AMPDU_FACTOR +
ampdu_factor)) - 1);
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
arg->bw_80 = true;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160)
arg->bw_160 = true;
/* Calculate peer NSS capability from VHT capabilities if STA
@@ -2127,7 +2240,7 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
vht_mcs_mask[i])
max_nss = i + 1;
}
- arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
+ arg->peer_nss = min(link_sta->rx_nss, max_nss);
arg->rx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.rx_highest);
arg->rx_mcs_set = __le16_to_cpu(vht_cap->vht_mcs.rx_mcs_map);
arg->tx_max_rate = __le16_to_cpu(vht_cap->vht_mcs.tx_highest);
@@ -2150,7 +2263,7 @@ static void ath12k_peer_assoc_h_vht(struct ath12k *ar,
arg->tx_max_mcs_nss = 0xFF;
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vht peer %pM max_mpdu %d flags 0x%x\n",
- sta->addr, arg->peer_max_mpdu, arg->peer_flags);
+ arsta->addr, arg->peer_max_mpdu, arg->peer_flags);
/* TODO: rxnss_override */
}
@@ -2162,7 +2275,9 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
{
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
+ const struct ieee80211_sta_he_cap *he_cap;
+ struct ieee80211_bss_conf *link_conf;
+ struct ieee80211_link_sta *link_sta;
int i;
u8 ampdu_factor, max_nss;
u8 rx_mcs_80 = IEEE80211_HE_MCS_NOT_SUPPORTED;
@@ -2171,6 +2286,21 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
bool support_160;
u16 v;
+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!link_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in peer assoc he for vif %pM link %u",
+ vif->addr, arvif->link_id);
+ return;
+ }
+
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (!link_sta) {
+ ath12k_warn(ar->ab, "unable to access link sta in peer assoc he for sta %pM link %u\n",
+ sta->addr, arsta->link_id);
+ return;
+ }
+
+ he_cap = &link_sta->he_cap;
if (!he_cap->has_he)
return;
@@ -2208,13 +2338,13 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
else
max_nss = rx_mcs_80;
- arg->peer_nss = min(sta->deflink.rx_nss, max_nss);
+ arg->peer_nss = min(link_sta->rx_nss, max_nss);
memcpy(&arg->peer_he_cap_macinfo, he_cap->he_cap_elem.mac_cap_info,
sizeof(he_cap->he_cap_elem.mac_cap_info));
memcpy(&arg->peer_he_cap_phyinfo, he_cap->he_cap_elem.phy_cap_info,
sizeof(he_cap->he_cap_elem.phy_cap_info));
- arg->peer_he_ops = vif->bss_conf.he_oper.params;
+ arg->peer_he_ops = link_conf->he_oper.params;
/* the top most byte is used to indicate BSS color info */
arg->peer_he_ops &= 0xffffff;
@@ -2235,10 +2365,10 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
IEEE80211_HE_MAC_CAP3_MAX_AMPDU_LEN_EXP_MASK);
if (ampdu_factor) {
- if (sta->deflink.vht_cap.vht_supported)
+ if (link_sta->vht_cap.vht_supported)
arg->peer_max_mpdu = (1 << (IEEE80211_HE_VHT_MAX_AMPDU_FACTOR +
ampdu_factor)) - 1;
- else if (sta->deflink.ht_cap.ht_supported)
+ else if (link_sta->ht_cap.ht_supported)
arg->peer_max_mpdu = (1 << (IEEE80211_HE_HT_MAX_AMPDU_FACTOR +
ampdu_factor)) - 1;
}
@@ -2279,7 +2409,7 @@ static void ath12k_peer_assoc_h_he(struct ath12k *ar,
if (he_cap->he_cap_elem.mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_TWT_REQ)
arg->twt_requester = true;
- switch (sta->deflink.bandwidth) {
+ switch (link_sta->bandwidth) {
case IEEE80211_STA_RX_BW_160:
if (he_cap->he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G) {
@@ -2319,7 +2449,8 @@ static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
{
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
+ const struct ieee80211_sta_he_cap *he_cap;
+ struct ieee80211_link_sta *link_sta;
struct cfg80211_chan_def def;
enum nl80211_band band;
u8 ampdu_factor, mpdu_density;
@@ -2329,22 +2460,31 @@ static void ath12k_peer_assoc_h_he_6ghz(struct ath12k *ar,
band = def.chan->band;
- if (!arg->he_flag || band != NL80211_BAND_6GHZ || !sta->deflink.he_6ghz_capa.capa)
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (!link_sta) {
+ ath12k_warn(ar->ab, "unable to access link sta in peer assoc he 6ghz for sta %pM link %u\n",
+ sta->addr, arsta->link_id);
+ return;
+ }
+
+ he_cap = &link_sta->he_cap;
+
+ if (!arg->he_flag || band != NL80211_BAND_6GHZ || !link_sta->he_6ghz_capa.capa)
return;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
arg->bw_40 = true;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
arg->bw_80 = true;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160)
arg->bw_160 = true;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_320)
arg->bw_320 = true;
- arg->peer_he_caps_6ghz = le16_to_cpu(sta->deflink.he_6ghz_capa.capa);
+ arg->peer_he_caps_6ghz = le16_to_cpu(link_sta->he_6ghz_capa.capa);
mpdu_density = u32_get_bits(arg->peer_he_caps_6ghz,
IEEE80211_HE_6GHZ_CAP_MIN_MPDU_START);
@@ -2388,10 +2528,23 @@ static void ath12k_peer_assoc_h_smps(struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- const struct ieee80211_he_6ghz_capa *he_6ghz_capa = &sta->deflink.he_6ghz_capa;
- const struct ieee80211_sta_ht_cap *ht_cap = &sta->deflink.ht_cap;
+ const struct ieee80211_he_6ghz_capa *he_6ghz_capa;
+ struct ath12k_link_vif *arvif = arsta->arvif;
+ const struct ieee80211_sta_ht_cap *ht_cap;
+ struct ieee80211_link_sta *link_sta;
+ struct ath12k *ar = arvif->ar;
int smps;
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (!link_sta) {
+ ath12k_warn(ar->ab, "unable to access link sta in peer assoc he for sta %pM link %u\n",
+ sta->addr, arsta->link_id);
+ return;
+ }
+
+ he_6ghz_capa = &link_sta->he_6ghz_capa;
+ ht_cap = &link_sta->ht_cap;
+
if (!ht_cap->ht_supported && !he_6ghz_capa->capa)
return;
@@ -2446,7 +2599,7 @@ static void ath12k_peer_assoc_h_qos(struct ath12k *ar,
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac peer %pM qos %d\n",
- sta->addr, arg->qos_flag);
+ arsta->addr, arg->qos_flag);
}
static int ath12k_peer_assoc_qos_ap(struct ath12k *ar,
@@ -2486,26 +2639,26 @@ static int ath12k_peer_assoc_qos_ap(struct ath12k *ar,
arg.param = WMI_AP_PS_PEER_PARAM_UAPSD;
arg.value = uapsd;
- ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
+ ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, arsta->addr, &arg);
if (ret)
goto err;
arg.param = WMI_AP_PS_PEER_PARAM_MAX_SP;
arg.value = max_sp;
- ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
+ ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, arsta->addr, &arg);
if (ret)
goto err;
/* TODO: revisit during testing */
arg.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_FRMTYPE;
arg.value = DISABLE_SIFS_RESPONSE_TRIGGER;
- ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
+ ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, arsta->addr, &arg);
if (ret)
goto err;
arg.param = WMI_AP_PS_PEER_PARAM_SIFS_RESP_UAPSD;
arg.value = DISABLE_SIFS_RESPONSE_TRIGGER;
- ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, sta->addr, &arg);
+ ret = ath12k_wmi_send_set_ap_ps_param_cmd(ar, arsta->addr, &arg);
if (ret)
goto err;
@@ -2517,17 +2670,17 @@ err:
return ret;
}
-static bool ath12k_mac_sta_has_ofdm_only(struct ieee80211_sta *sta)
+static bool ath12k_mac_sta_has_ofdm_only(struct ieee80211_link_sta *sta)
{
- return sta->deflink.supp_rates[NL80211_BAND_2GHZ] >>
+ return sta->supp_rates[NL80211_BAND_2GHZ] >>
ATH12K_MAC_FIRST_OFDM_RATE_IDX;
}
static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,
- struct ieee80211_sta *sta)
+ struct ieee80211_link_sta *link_sta)
{
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
- switch (sta->deflink.vht_cap.cap &
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
+ switch (link_sta->vht_cap.cap &
IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK) {
case IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ:
return MODE_11AC_VHT160;
@@ -2539,74 +2692,74 @@ static enum wmi_phy_mode ath12k_mac_get_phymode_vht(struct ath12k *ar,
}
}
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
return MODE_11AC_VHT80;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
return MODE_11AC_VHT40;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20)
return MODE_11AC_VHT20;
return MODE_UNKNOWN;
}
static enum wmi_phy_mode ath12k_mac_get_phymode_he(struct ath12k *ar,
- struct ieee80211_sta *sta)
+ struct ieee80211_link_sta *link_sta)
{
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
+ if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
return MODE_11AX_HE160;
- else if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
+ else if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
return MODE_11AX_HE80_80;
/* not sure if this is a valid case? */
return MODE_11AX_HE160;
}
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
return MODE_11AX_HE80;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
return MODE_11AX_HE40;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20)
return MODE_11AX_HE20;
return MODE_UNKNOWN;
}
static enum wmi_phy_mode ath12k_mac_get_phymode_eht(struct ath12k *ar,
- struct ieee80211_sta *sta)
+ struct ieee80211_link_sta *link_sta)
{
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_320)
- if (sta->deflink.eht_cap.eht_cap_elem.phy_cap_info[0] &
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_320)
+ if (link_sta->eht_cap.eht_cap_elem.phy_cap_info[0] &
IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ)
return MODE_11BE_EHT320;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) {
- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_160) {
+ if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_160MHZ_IN_5G)
return MODE_11BE_EHT160;
- if (sta->deflink.he_cap.he_cap_elem.phy_cap_info[0] &
+ if (link_sta->he_cap.he_cap_elem.phy_cap_info[0] &
IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
return MODE_11BE_EHT80_80;
ath12k_warn(ar->ab, "invalid EHT PHY capability info for 160 Mhz: %d\n",
- sta->deflink.he_cap.he_cap_elem.phy_cap_info[0]);
+ link_sta->he_cap.he_cap_elem.phy_cap_info[0]);
return MODE_11BE_EHT160;
}
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
return MODE_11BE_EHT80;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
return MODE_11BE_EHT40;
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_20)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_20)
return MODE_11BE_EHT20;
return MODE_UNKNOWN;
@@ -2617,6 +2770,7 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
struct ath12k_link_sta *arsta,
struct ath12k_wmi_peer_assoc_arg *arg)
{
+ struct ieee80211_link_sta *link_sta;
struct cfg80211_chan_def def;
enum nl80211_band band;
const u8 *ht_mcs_mask;
@@ -2635,33 +2789,40 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
ht_mcs_mask = arvif->bitrate_mask.control[band].ht_mcs;
vht_mcs_mask = arvif->bitrate_mask.control[band].vht_mcs;
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (!link_sta) {
+ ath12k_warn(ar->ab, "unable to access link sta in peer assoc he for sta %pM link %u\n",
+ sta->addr, arsta->link_id);
+ return;
+ }
+
switch (band) {
case NL80211_BAND_2GHZ:
- if (sta->deflink.eht_cap.has_eht) {
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
+ if (link_sta->eht_cap.has_eht) {
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
phymode = MODE_11BE_EHT40_2G;
else
phymode = MODE_11BE_EHT20_2G;
- } else if (sta->deflink.he_cap.has_he) {
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_80)
+ } else if (link_sta->he_cap.has_he) {
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_80)
phymode = MODE_11AX_HE80_2G;
- else if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
+ else if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
phymode = MODE_11AX_HE40_2G;
else
phymode = MODE_11AX_HE20_2G;
- } else if (sta->deflink.vht_cap.vht_supported &&
+ } else if (link_sta->vht_cap.vht_supported &&
!ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
phymode = MODE_11AC_VHT40;
else
phymode = MODE_11AC_VHT20;
- } else if (sta->deflink.ht_cap.ht_supported &&
+ } else if (link_sta->ht_cap.ht_supported &&
!ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
- if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_40)
+ if (link_sta->bandwidth == IEEE80211_STA_RX_BW_40)
phymode = MODE_11NG_HT40;
else
phymode = MODE_11NG_HT20;
- } else if (ath12k_mac_sta_has_ofdm_only(sta)) {
+ } else if (ath12k_mac_sta_has_ofdm_only(link_sta)) {
phymode = MODE_11G;
} else {
phymode = MODE_11B;
@@ -2670,16 +2831,16 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
case NL80211_BAND_5GHZ:
case NL80211_BAND_6GHZ:
/* Check EHT first */
- if (sta->deflink.eht_cap.has_eht) {
- phymode = ath12k_mac_get_phymode_eht(ar, sta);
- } else if (sta->deflink.he_cap.has_he) {
- phymode = ath12k_mac_get_phymode_he(ar, sta);
- } else if (sta->deflink.vht_cap.vht_supported &&
+ if (link_sta->eht_cap.has_eht) {
+ phymode = ath12k_mac_get_phymode_eht(ar, link_sta);
+ } else if (link_sta->he_cap.has_he) {
+ phymode = ath12k_mac_get_phymode_he(ar, link_sta);
+ } else if (link_sta->vht_cap.vht_supported &&
!ath12k_peer_assoc_h_vht_masked(vht_mcs_mask)) {
- phymode = ath12k_mac_get_phymode_vht(ar, sta);
- } else if (sta->deflink.ht_cap.ht_supported &&
+ phymode = ath12k_mac_get_phymode_vht(ar, link_sta);
+ } else if (link_sta->ht_cap.ht_supported &&
!ath12k_peer_assoc_h_ht_masked(ht_mcs_mask)) {
- if (sta->deflink.bandwidth >= IEEE80211_STA_RX_BW_40)
+ if (link_sta->bandwidth >= IEEE80211_STA_RX_BW_40)
phymode = MODE_11NA_HT40;
else
phymode = MODE_11NA_HT20;
@@ -2692,7 +2853,7 @@ static void ath12k_peer_assoc_h_phymode(struct ath12k *ar,
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac peer %pM phymode %s\n",
- sta->addr, ath12k_mac_phymode_str(phymode));
+ arsta->addr, ath12k_mac_phymode_str(phymode));
arg->peer_phymode = phymode;
WARN_ON(phymode == MODE_UNKNOWN);
@@ -2767,15 +2928,25 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
struct ath12k_wmi_peer_assoc_arg *arg)
{
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- const struct ieee80211_sta_eht_cap *eht_cap = &sta->deflink.eht_cap;
- const struct ieee80211_sta_he_cap *he_cap = &sta->deflink.he_cap;
const struct ieee80211_eht_mcs_nss_supp_20mhz_only *bw_20;
const struct ieee80211_eht_mcs_nss_supp_bw *bw;
+ const struct ieee80211_sta_eht_cap *eht_cap;
+ const struct ieee80211_sta_he_cap *he_cap;
+ struct ieee80211_link_sta *link_sta;
u32 *rx_mcs, *tx_mcs;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- if (!sta->deflink.he_cap.has_he || !eht_cap->has_eht)
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (!link_sta) {
+ ath12k_warn(ar->ab, "unable to access link sta in peer assoc eht for sta %pM link %u\n",
+ sta->addr, arsta->link_id);
+ return;
+ }
+
+ eht_cap = &link_sta->eht_cap;
+ he_cap = &link_sta->he_cap;
+ if (!he_cap->has_he || !eht_cap->has_eht)
return;
arg->eht_flag = true;
@@ -2794,7 +2965,7 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
rx_mcs = arg->peer_eht_rx_mcs_set;
tx_mcs = arg->peer_eht_tx_mcs_set;
- switch (sta->deflink.bandwidth) {
+ switch (link_sta->bandwidth) {
case IEEE80211_STA_RX_BW_320:
bw = &eht_cap->eht_mcs_nss_supp.bw._320;
ath12k_mac_set_eht_mcs(bw->rx_tx_mcs9_max_nss,
@@ -2846,6 +3017,67 @@ static void ath12k_peer_assoc_h_eht(struct ath12k *ar,
arg->punct_bitmap = ~arvif->punct_bitmap;
}
+static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,
+ struct ath12k_wmi_peer_assoc_arg *arg)
+{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
+ struct peer_assoc_mlo_params *ml = &arg->ml;
+ struct ath12k_sta *ahsta = arsta->ahsta;
+ struct ath12k_link_sta *arsta_p;
+ struct ath12k_link_vif *arvif;
+ unsigned long links;
+ u8 link_id;
+ int i;
+
+ if (!sta->mlo || ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID)
+ return;
+
+ ml->enabled = true;
+ ml->assoc_link = arsta->is_assoc_link;
+
+ /* For now considering the primary umac based on assoc link */
+ ml->primary_umac = arsta->is_assoc_link;
+ ml->peer_id_valid = true;
+ ml->logical_link_idx_valid = true;
+
+ ether_addr_copy(ml->mld_addr, sta->addr);
+ ml->logical_link_idx = arsta->link_idx;
+ ml->ml_peer_id = ahsta->ml_peer_id;
+ ml->ieee_link_id = arsta->link_id;
+ ml->num_partner_links = 0;
+ links = ahsta->links_map;
+
+ rcu_read_lock();
+
+ i = 0;
+
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ if (i >= ATH12K_WMI_MLO_MAX_LINKS)
+ break;
+
+ arsta_p = rcu_dereference(ahsta->link[link_id]);
+ arvif = rcu_dereference(ahsta->ahvif->link[link_id]);
+
+ if (arsta_p == arsta)
+ continue;
+
+ if (!arvif->is_started)
+ continue;
+
+ ml->partner_info[i].vdev_id = arvif->vdev_id;
+ ml->partner_info[i].hw_link_id = arvif->ar->pdev->hw_link_id;
+ ml->partner_info[i].assoc_link = arsta_p->is_assoc_link;
+ ml->partner_info[i].primary_umac = arsta_p->is_assoc_link;
+ ml->partner_info[i].logical_link_idx_valid = true;
+ ml->partner_info[i].logical_link_idx = arsta_p->link_idx;
+ ml->num_partner_links++;
+
+ i++;
+ }
+
+ rcu_read_unlock();
+}
+
static void ath12k_peer_assoc_prepare(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ath12k_link_sta *arsta,
@@ -2870,6 +3102,7 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar,
ath12k_peer_assoc_h_qos(ar, arvif, arsta, arg);
ath12k_peer_assoc_h_phymode(ar, arvif, arsta, arg);
ath12k_peer_assoc_h_smps(arsta, arg);
+ ath12k_peer_assoc_h_mlo(arsta, arg);
/* TODO: amsdu_disable req? */
}
@@ -2900,7 +3133,9 @@ static void ath12k_bss_assoc(struct ath12k *ar,
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k_wmi_vdev_up_params params = {};
- struct ath12k_wmi_peer_assoc_arg peer_arg;
+ struct ath12k_wmi_peer_assoc_arg peer_arg = {};
+ struct ieee80211_link_sta *link_sta;
+ u8 link_id = bss_conf->link_id;
struct ath12k_link_sta *arsta;
struct ieee80211_sta *ap_sta;
struct ath12k_sta *ahsta;
@@ -2910,27 +3145,38 @@ static void ath12k_bss_assoc(struct ath12k *ar,
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n",
- arvif->vdev_id, arvif->bssid, ahvif->aid);
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "mac vdev %i link id %u assoc bssid %pM aid %d\n",
+ arvif->vdev_id, link_id, arvif->bssid, ahvif->aid);
rcu_read_lock();
- ap_sta = ieee80211_find_sta(vif, bss_conf->bssid);
+ /* During ML connection, cfg.ap_addr has the MLD address. For
+ * non-ML connection, it has the BSSID.
+ */
+ ap_sta = ieee80211_find_sta(vif, vif->cfg.ap_addr);
if (!ap_sta) {
ath12k_warn(ar->ab, "failed to find station entry for bss %pM vdev %i\n",
- bss_conf->bssid, arvif->vdev_id);
+ vif->cfg.ap_addr, arvif->vdev_id);
rcu_read_unlock();
return;
}
ahsta = ath12k_sta_to_ahsta(ap_sta);
- arsta = &ahsta->deflink;
+ arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
+ ahsta->link[link_id]);
if (WARN_ON(!arsta)) {
rcu_read_unlock();
return;
}
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (WARN_ON(!link_sta)) {
+ rcu_read_unlock();
+ return;
+ }
+
ath12k_peer_assoc_prepare(ar, arvif, arsta, &peer_arg, false);
rcu_read_unlock();
@@ -2949,8 +3195,7 @@ static void ath12k_bss_assoc(struct ath12k *ar,
}
ret = ath12k_setup_peer_smps(ar, arvif, bss_conf->bssid,
- &ap_sta->deflink.ht_cap,
- &ap_sta->deflink.he_6ghz_capa);
+ &link_sta->ht_cap, &link_sta->he_6ghz_capa);
if (ret) {
ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
arvif->vdev_id, ret);
@@ -3058,6 +3303,7 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_hw *hw = ath12k_ar_to_hw(ar);
const struct ieee80211_supported_band *sband;
+ struct ieee80211_bss_conf *bss_conf;
u8 basic_rate_idx;
int hw_rate_code;
u32 vdev_param;
@@ -3066,8 +3312,15 @@ static void ath12k_recalculate_mgmt_rate(struct ath12k *ar,
lockdep_assert_wiphy(hw->wiphy);
+ bss_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!bss_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in mgmt rate calc for vif %pM link %u\n",
+ vif->addr, arvif->link_id);
+ return;
+ }
+
sband = hw->wiphy->bands[def->chan->band];
- basic_rate_idx = ffs(vif->bss_conf.basic_rates) - 1;
+ basic_rate_idx = ffs(bss_conf->basic_rates) - 1;
bitrate = sband->bitrates[basic_rate_idx].bitrate;
hw_rate_code = ath12k_mac_get_rate_hw_value(bitrate);
@@ -3151,6 +3404,7 @@ static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw,
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
unsigned long links = ahvif->links_map;
+ struct ieee80211_bss_conf *info;
struct ath12k_link_vif *arvif;
struct ath12k *ar;
u8 link_id;
@@ -3171,10 +3425,15 @@ static void ath12k_mac_op_vif_cfg_changed(struct ieee80211_hw *hw,
ar = arvif->ar;
- if (vif->cfg.assoc)
- ath12k_bss_assoc(ar, arvif, &vif->bss_conf);
- else
+ if (vif->cfg.assoc) {
+ info = ath12k_mac_get_link_bss_conf(arvif);
+ if (!info)
+ continue;
+
+ ath12k_bss_assoc(ar, arvif, info);
+ } else {
ath12k_bss_disassoc(ar, arvif);
+ }
}
}
}
@@ -3185,6 +3444,7 @@ static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif)
struct ieee80211_vif *vif = arvif->ahvif->vif;
struct ieee80211_conf *conf = &ath12k_ar_to_hw(ar)->conf;
enum wmi_sta_powersave_param param;
+ struct ieee80211_bss_conf *info;
enum wmi_sta_ps_mode psmode;
int ret;
int timeout;
@@ -3202,8 +3462,15 @@ static void ath12k_mac_vif_setup_ps(struct ath12k_link_vif *arvif)
timeout = conf->dynamic_ps_timeout;
if (timeout == 0) {
+ info = ath12k_mac_get_link_bss_conf(arvif);
+ if (!info) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in setup ps for vif %pM link %u\n",
+ vif->addr, arvif->link_id);
+ return;
+ }
+
/* firmware doesn't like 0 */
- timeout = ieee80211_tu_to_usec(vif->bss_conf.beacon_int) / 1000;
+ timeout = ieee80211_tu_to_usec(info->beacon_int) / 1000;
}
ret = ath12k_wmi_set_sta_ps_param(ar, arvif->vdev_id, param,
@@ -3314,8 +3581,8 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
if (changed & BSS_CHANGED_BEACON_ENABLED) {
ath12k_control_beaconing(arvif, info);
- if (arvif->is_up && vif->bss_conf.he_support &&
- vif->bss_conf.he_oper.params) {
+ if (arvif->is_up && info->he_support &&
+ info->he_oper.params) {
/* TODO: Extend to support 1024 BA Bitmap size */
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
WMI_VDEV_PARAM_BA_MODE,
@@ -3326,7 +3593,7 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
arvif->vdev_id);
param_id = WMI_VDEV_PARAM_HEOPS_0_31;
- param_value = vif->bss_conf.he_oper.params;
+ param_value = info->he_oper.params;
ret = ath12k_wmi_vdev_set_param_cmd(ar, arvif->vdev_id,
param_id, param_value);
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
@@ -3418,12 +3685,12 @@ static void ath12k_mac_bss_info_changed(struct ath12k *ar,
if (changed & BSS_CHANGED_MCAST_RATE &&
!ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)) {
band = def.chan->band;
- mcast_rate = vif->bss_conf.mcast_rate[band];
+ mcast_rate = info->mcast_rate[band];
if (mcast_rate > 0)
rateidx = mcast_rate - 1;
else
- rateidx = ffs(vif->bss_conf.basic_rates) - 1;
+ rateidx = ffs(info->basic_rates) - 1;
if (ar->pdev->cap.supported_bands & WMI_HOST_WLAN_5G_CAP)
rateidx += ATH12K_MAC_FIRST_OFDM_RATE_IDX;
@@ -3537,6 +3804,9 @@ static void ath12k_ahvif_put_link_key_cache(struct ath12k_vif_cache *cache)
static void ath12k_ahvif_put_link_cache(struct ath12k_vif *ahvif, u8 link_id)
{
+ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
+ return;
+
ath12k_ahvif_put_link_key_cache(ahvif->cache[link_id]);
kfree(ahvif->cache[link_id]);
ahvif->cache[link_id] = NULL;
@@ -3597,9 +3867,9 @@ static struct ath12k_link_vif *ath12k_mac_assign_link_vif(struct ath12k_hw *ah,
arvif = &ahvif->deflink;
} else {
/* If this is the first link arvif being created for an ML VIF
- * use the preallocated deflink memory
+ * use the preallocated deflink memory except for scan arvifs
*/
- if (!ahvif->links_map) {
+ if (!ahvif->links_map && link_id != ATH12K_DEFAULT_SCAN_LINK) {
arvif = &ahvif->deflink;
} else {
arvif = (struct ath12k_link_vif *)
@@ -3899,10 +4169,10 @@ ath12k_mac_find_link_id_by_ar(struct ath12k_vif *ahvif, struct ath12k *ar)
return link_id;
}
- /* input ar is not assigned to any of the links, use link id
- * 0 for scan vdev creation.
+ /* input ar is not assigned to any of the links of ML VIF, use scan
+ * link (15) for scan vdev creation.
*/
- return 0;
+ return ATH12K_DEFAULT_SCAN_LINK;
}
static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
@@ -3933,7 +4203,7 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
/* check if any of the links of ML VIF is already started on
* radio(ar) correpsondig to given scan frequency and use it,
- * if not use deflink(link 0) for scan purpose.
+ * if not use scan link (link 15) for scan purpose.
*/
link_id = ath12k_mac_find_link_id_by_ar(ahvif, ar);
arvif = ath12k_mac_assign_link_vif(ah, vif, link_id);
@@ -4043,6 +4313,13 @@ static int ath12k_mac_op_hw_scan(struct ieee80211_hw *hw,
spin_unlock_bh(&ar->data_lock);
}
+ /* As per cfg80211/mac80211 scan design, it allows only one
+ * scan at a time. Hence last_scan link id is used for
+ * tracking the link id on which the scan is been done on
+ * this vif.
+ */
+ ahvif->last_scan_link = arvif->link_id;
+
/* Add a margin to account for event/command processing */
ieee80211_queue_delayed_work(ath12k_ar_to_hw(ar), &ar->scan.timeout,
msecs_to_jiffies(arg->max_scan_time +
@@ -4062,14 +4339,14 @@ static void ath12k_mac_op_cancel_hw_scan(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ u16 link_id = ahvif->last_scan_link;
struct ath12k_link_vif *arvif;
struct ath12k *ar;
lockdep_assert_wiphy(hw->wiphy);
- arvif = &ahvif->deflink;
-
- if (!arvif->is_created)
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (!arvif || !arvif->is_created)
return;
ar = arvif->ar;
@@ -4203,6 +4480,7 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
{
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
+ struct ieee80211_bss_conf *link_conf;
struct ieee80211_sta *sta = NULL;
struct ath12k_base *ab = ar->ab;
struct ath12k_peer *peer;
@@ -4219,12 +4497,19 @@ static int ath12k_mac_set_key(struct ath12k *ar, enum set_key_cmd cmd,
if (test_bit(ATH12K_FLAG_HW_CRYPTO_DISABLED, &ab->dev_flags))
return 1;
+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!link_conf) {
+ ath12k_warn(ab, "unable to access bss link conf in set key for vif %pM link %u\n",
+ vif->addr, arvif->link_id);
+ return -ENOLINK;
+ }
+
if (sta)
- peer_addr = sta->addr;
+ peer_addr = arsta->addr;
else if (ahvif->vdev_type == WMI_VDEV_TYPE_STA)
- peer_addr = vif->bss_conf.bssid;
+ peer_addr = link_conf->bssid;
else
- peer_addr = vif->addr;
+ peer_addr = link_conf->addr;
key->hw_key_idx = key->keyidx;
@@ -4372,6 +4657,7 @@ static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (sta) {
ahsta = ath12k_sta_to_ahsta(sta);
+
/* For an ML STA Pairwise key is same for all associated link Stations,
* hence do set key for all link STAs which are active.
*/
@@ -4394,41 +4680,47 @@ static int ath12k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
if (ret)
break;
}
- } else {
- arsta = &ahsta->deflink;
- arvif = arsta->arvif;
- if (WARN_ON(!arvif)) {
- ret = -EINVAL;
- goto out;
- }
- ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, arsta, key);
- }
- } else {
- if (key->link_id >= 0 && key->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
- link_id = key->link_id;
- arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
- } else {
- link_id = 0;
- arvif = &ahvif->deflink;
+ return 0;
}
- if (!arvif || !arvif->is_created) {
- cache = ath12k_ahvif_get_link_cache(ahvif, link_id);
- if (!cache)
- return -ENOSPC;
+ arsta = &ahsta->deflink;
+ arvif = arsta->arvif;
+ if (WARN_ON(!arvif))
+ return -EINVAL;
+
+ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, arsta, key);
+ if (ret)
+ return ret;
+
+ return 0;
+ }
- ret = ath12k_mac_update_key_cache(cache, cmd, sta, key);
+ if (key->link_id >= 0 && key->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
+ link_id = key->link_id;
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ } else {
+ link_id = 0;
+ arvif = &ahvif->deflink;
+ }
+ if (!arvif || !arvif->is_created) {
+ cache = ath12k_ahvif_get_link_cache(ahvif, link_id);
+ if (!cache)
+ return -ENOSPC;
+
+ ret = ath12k_mac_update_key_cache(cache, cmd, sta, key);
+ if (ret)
return ret;
- }
- ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, NULL, key);
+ return 0;
}
-out:
+ ret = ath12k_mac_set_key(arvif->ar, cmd, arvif, NULL, key);
+ if (ret)
+ return ret;
- return ret;
+ return 0;
}
static int
@@ -4451,7 +4743,6 @@ ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif,
const struct cfg80211_bitrate_mask *mask,
enum nl80211_band band)
{
- struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k *ar = arvif->ar;
u8 vht_rate, nss;
u32 rate_code;
@@ -4470,47 +4761,52 @@ ath12k_mac_set_peer_vht_fixed_rate(struct ath12k_link_vif *arvif,
if (!nss) {
ath12k_warn(ar->ab, "No single VHT Fixed rate found to set for %pM",
- sta->addr);
+ arsta->addr);
return -EINVAL;
}
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
"Setting Fixed VHT Rate for peer %pM. Device will not switch to any other selected rates",
- sta->addr);
+ arsta->addr);
rate_code = ATH12K_HW_RATE_CODE(vht_rate, nss - 1,
WMI_RATE_PREAMBLE_VHT);
- ret = ath12k_wmi_set_peer_param(ar, sta->addr,
+ ret = ath12k_wmi_set_peer_param(ar, arsta->addr,
arvif->vdev_id,
WMI_PEER_PARAM_FIXED_RATE,
rate_code);
if (ret)
ath12k_warn(ar->ab,
"failed to update STA %pM Fixed Rate %d: %d\n",
- sta->addr, rate_code, ret);
+ arsta->addr, rate_code, ret);
return ret;
}
-static int ath12k_station_assoc(struct ath12k *ar,
- struct ath12k_link_vif *arvif,
- struct ath12k_link_sta *arsta,
- bool reassoc)
+static int ath12k_mac_station_assoc(struct ath12k *ar,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
+ bool reassoc)
{
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
struct ath12k_wmi_peer_assoc_arg peer_arg;
+ struct ieee80211_link_sta *link_sta;
int ret;
struct cfg80211_chan_def def;
enum nl80211_band band;
struct cfg80211_bitrate_mask *mask;
u8 num_vht_rates;
+ u8 link_id = arvif->link_id;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (WARN_ON(ath12k_mac_vif_link_chan(vif, arvif->link_id, &def)))
return -EPERM;
+ if (WARN_ON(!rcu_access_pointer(sta->link[link_id])))
+ return -EINVAL;
+
band = def.chan->band;
mask = &arvif->bitrate_mask;
@@ -4524,13 +4820,13 @@ static int ath12k_station_assoc(struct ath12k *ar,
ret = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
if (ret) {
ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
- sta->addr, arvif->vdev_id, ret);
+ arsta->addr, arvif->vdev_id, ret);
return ret;
}
if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
- sta->addr, arvif->vdev_id);
+ arsta->addr, arvif->vdev_id);
return -ETIMEDOUT;
}
@@ -4541,7 +4837,13 @@ static int ath12k_station_assoc(struct ath12k *ar,
* fixed param.
* Note that all other rates and NSS will be disabled for this peer.
*/
- if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (!link_sta) {
+ ath12k_warn(ar->ab, "unable to access link sta in station assoc\n");
+ return -EINVAL;
+ }
+
+ if (link_sta->vht_cap.vht_supported && num_vht_rates == 1) {
ret = ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
band);
if (ret)
@@ -4554,9 +4856,8 @@ static int ath12k_station_assoc(struct ath12k *ar,
if (reassoc)
return 0;
- ret = ath12k_setup_peer_smps(ar, arvif, sta->addr,
- &sta->deflink.ht_cap,
- &sta->deflink.he_6ghz_capa);
+ ret = ath12k_setup_peer_smps(ar, arvif, arsta->addr,
+ &link_sta->ht_cap, &link_sta->he_6ghz_capa);
if (ret) {
ath12k_warn(ar->ab, "failed to setup peer SMPS for vdev %d: %d\n",
arvif->vdev_id, ret);
@@ -4574,7 +4875,7 @@ static int ath12k_station_assoc(struct ath12k *ar,
ret = ath12k_peer_assoc_qos_ap(ar, arvif, arsta);
if (ret) {
ath12k_warn(ar->ab, "failed to set qos params for STA %pM for vdev %i: %d\n",
- sta->addr, arvif->vdev_id, ret);
+ arsta->addr, arvif->vdev_id, ret);
return ret;
}
}
@@ -4582,33 +4883,25 @@ static int ath12k_station_assoc(struct ath12k *ar,
return 0;
}
-static int ath12k_station_disassoc(struct ath12k *ar,
- struct ath12k_link_vif *arvif,
- struct ath12k_link_sta *arsta)
+static int ath12k_mac_station_disassoc(struct ath12k *ar,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
{
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- int ret;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (!sta->wme) {
arvif->num_legacy_stations--;
- ret = ath12k_recalc_rtscts_prot(arvif);
- if (ret)
- return ret;
+ return ath12k_recalc_rtscts_prot(arvif);
}
- ret = ath12k_clear_peer_keys(arvif, sta->addr);
- if (ret) {
- ath12k_warn(ar->ab, "failed to clear all peer keys for vdev %i: %d\n",
- arvif->vdev_id, ret);
- return ret;
- }
return 0;
}
static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
{
+ struct ieee80211_link_sta *link_sta;
struct ath12k *ar;
struct ath12k_link_vif *arvif;
struct ieee80211_sta *sta;
@@ -4666,65 +4959,65 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
* WMI_PEER_CHWIDTH
*/
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth upgrade for sta %pM new %d old %d\n",
- sta->addr, bw, bw_prev);
- err = ath12k_wmi_set_peer_param(ar, sta->addr,
+ arsta->addr, bw, bw_prev);
+ err = ath12k_wmi_set_peer_param(ar, arsta->addr,
arvif->vdev_id, WMI_PEER_PHYMODE,
peer_phymode);
if (err) {
ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
- sta->addr, peer_phymode, err);
+ arsta->addr, peer_phymode, err);
return;
}
- err = ath12k_wmi_set_peer_param(ar, sta->addr,
+ err = ath12k_wmi_set_peer_param(ar, arsta->addr,
arvif->vdev_id, WMI_PEER_CHWIDTH,
bw);
if (err)
ath12k_warn(ar->ab, "failed to update STA %pM to peer bandwidth %d: %d\n",
- sta->addr, bw, err);
+ arsta->addr, bw, err);
} else {
/* When we downgrade bandwidth this will conflict with phymode
* and cause to trigger firmware crash. In this case we send
* WMI_PEER_CHWIDTH followed by WMI_PEER_PHYMODE
*/
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac bandwidth downgrade for sta %pM new %d old %d\n",
- sta->addr, bw, bw_prev);
- err = ath12k_wmi_set_peer_param(ar, sta->addr,
+ arsta->addr, bw, bw_prev);
+ err = ath12k_wmi_set_peer_param(ar, arsta->addr,
arvif->vdev_id, WMI_PEER_CHWIDTH,
bw);
if (err) {
ath12k_warn(ar->ab, "failed to update STA %pM peer to bandwidth %d: %d\n",
- sta->addr, bw, err);
+ arsta->addr, bw, err);
return;
}
- err = ath12k_wmi_set_peer_param(ar, sta->addr,
+ err = ath12k_wmi_set_peer_param(ar, arsta->addr,
arvif->vdev_id, WMI_PEER_PHYMODE,
peer_phymode);
if (err)
ath12k_warn(ar->ab, "failed to update STA %pM to peer phymode %d: %d\n",
- sta->addr, peer_phymode, err);
+ arsta->addr, peer_phymode, err);
}
}
if (changed & IEEE80211_RC_NSS_CHANGED) {
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM nss %d\n",
- sta->addr, nss);
+ arsta->addr, nss);
- err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
+ err = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id,
WMI_PEER_NSS, nss);
if (err)
ath12k_warn(ar->ab, "failed to update STA %pM nss %d: %d\n",
- sta->addr, nss, err);
+ arsta->addr, nss, err);
}
if (changed & IEEE80211_RC_SMPS_CHANGED) {
ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac update sta %pM smps %d\n",
- sta->addr, smps);
+ arsta->addr, smps);
- err = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
+ err = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id,
WMI_PEER_MIMO_PS_STATE, smps);
if (err)
ath12k_warn(ar->ab, "failed to update STA %pM smps %d: %d\n",
- sta->addr, smps, err);
+ arsta->addr, smps, err);
}
if (changed & IEEE80211_RC_SUPP_RATES_CHANGED) {
@@ -4743,7 +5036,14 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
* TODO: Check RATEMASK_CMDID to support auto rates selection
* across HT/VHT and for multiple VHT MCS support.
*/
- if (sta->deflink.vht_cap.vht_supported && num_vht_rates == 1) {
+ link_sta = ath12k_mac_get_link_sta(arsta);
+ if (!link_sta) {
+ ath12k_warn(ar->ab, "unable to access link sta in peer assoc he for sta %pM link %u\n",
+ sta->addr, arsta->link_id);
+ return;
+ }
+
+ if (link_sta->vht_cap.vht_supported && num_vht_rates == 1) {
ath12k_mac_set_peer_vht_fixed_rate(arvif, arsta, mask,
band);
} else {
@@ -4757,15 +5057,44 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
err = ath12k_wmi_send_peer_assoc_cmd(ar, &peer_arg);
if (err)
ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
- sta->addr, arvif->vdev_id, err);
+ arsta->addr, arvif->vdev_id, err);
if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ))
ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
- sta->addr, arvif->vdev_id);
+ arsta->addr, arvif->vdev_id);
}
}
}
+static void ath12k_mac_free_unassign_link_sta(struct ath12k_hw *ah,
+ struct ath12k_sta *ahsta,
+ u8 link_id)
+{
+ struct ath12k_link_sta *arsta;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ if (WARN_ON(link_id >= IEEE80211_MLD_MAX_NUM_LINKS))
+ return;
+
+ arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
+ if (WARN_ON(!arsta))
+ return;
+
+ ahsta->links_map &= ~BIT(link_id);
+ rcu_assign_pointer(ahsta->link[link_id], NULL);
+ synchronize_rcu();
+
+ if (arsta == &ahsta->deflink) {
+ arsta->link_id = ATH12K_INVALID_LINK_ID;
+ arsta->ahsta = NULL;
+ arsta->arvif = NULL;
+ return;
+ }
+
+ kfree(arsta);
+}
+
static int ath12k_mac_inc_num_stations(struct ath12k_link_vif *arvif,
struct ath12k_link_sta *arsta)
{
@@ -4799,6 +5128,144 @@ static void ath12k_mac_dec_num_stations(struct ath12k_link_vif *arvif,
ar->num_stations--;
}
+static void ath12k_mac_station_post_remove(struct ath12k *ar,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
+{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
+ struct ath12k_peer *peer;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ ath12k_mac_dec_num_stations(arvif, arsta);
+
+ spin_lock_bh(&ar->ab->base_lock);
+
+ peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr);
+ if (peer && peer->sta == sta) {
+ ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
+ vif->addr, arvif->vdev_id);
+ peer->sta = NULL;
+ list_del(&peer->list);
+ kfree(peer);
+ ar->num_peers--;
+ }
+
+ spin_unlock_bh(&ar->ab->base_lock);
+
+ kfree(arsta->rx_stats);
+ arsta->rx_stats = NULL;
+}
+
+static int ath12k_mac_station_unauthorize(struct ath12k *ar,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
+{
+ struct ath12k_peer *peer;
+ int ret;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ spin_lock_bh(&ar->ab->base_lock);
+
+ peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr);
+ if (peer)
+ peer->is_authorized = false;
+
+ spin_unlock_bh(&ar->ab->base_lock);
+
+ /* Driver must clear the keys during the state change from
+ * IEEE80211_STA_AUTHORIZED to IEEE80211_STA_ASSOC, since after
+ * returning from here, mac80211 is going to delete the keys
+ * in __sta_info_destroy_part2(). This will ensure that the driver does
+ * not retain stale key references after mac80211 deletes the keys.
+ */
+ ret = ath12k_clear_peer_keys(arvif, arsta->addr);
+ if (ret) {
+ ath12k_warn(ar->ab, "failed to clear all peer keys for vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ath12k_mac_station_authorize(struct ath12k *ar,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
+{
+ struct ath12k_peer *peer;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ int ret;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ spin_lock_bh(&ar->ab->base_lock);
+
+ peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr);
+ if (peer)
+ peer->is_authorized = true;
+
+ spin_unlock_bh(&ar->ab->base_lock);
+
+ if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) {
+ ret = ath12k_wmi_set_peer_param(ar, arsta->addr,
+ arvif->vdev_id,
+ WMI_PEER_AUTHORIZE,
+ 1);
+ if (ret) {
+ ath12k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n",
+ arsta->addr, arvif->vdev_id, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static int ath12k_mac_station_remove(struct ath12k *ar,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta)
+{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ int ret = 0;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ wiphy_work_cancel(ar->ah->hw->wiphy, &arsta->update_wk);
+
+ if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) {
+ ath12k_bss_disassoc(ar, arvif);
+ ret = ath12k_mac_vdev_stop(arvif);
+ if (ret)
+ ath12k_warn(ar->ab, "failed to stop vdev %i: %d\n",
+ arvif->vdev_id, ret);
+ }
+
+ if (sta->mlo)
+ return ret;
+
+ ath12k_dp_peer_cleanup(ar, arvif->vdev_id, arsta->addr);
+
+ ret = ath12k_peer_delete(ar, arvif->vdev_id, arsta->addr);
+ if (ret)
+ ath12k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n",
+ arsta->addr, arvif->vdev_id);
+ else
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n",
+ arsta->addr, arvif->vdev_id);
+
+ ath12k_mac_station_post_remove(ar, arvif, arsta);
+
+ if (sta->valid_links)
+ ath12k_mac_free_unassign_link_sta(ahvif->ah,
+ arsta->ahsta, arsta->link_id);
+
+ return ret;
+}
+
static int ath12k_mac_station_add(struct ath12k *ar,
struct ath12k_link_vif *arvif,
struct ath12k_link_sta *arsta)
@@ -4806,7 +5273,7 @@ static int ath12k_mac_station_add(struct ath12k *ar,
struct ath12k_base *ab = ar->ab;
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
- struct ath12k_wmi_peer_create_arg peer_param;
+ struct ath12k_wmi_peer_create_arg peer_param = {0};
int ret;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -4824,34 +5291,35 @@ static int ath12k_mac_station_add(struct ath12k *ar,
}
peer_param.vdev_id = arvif->vdev_id;
- peer_param.peer_addr = sta->addr;
+ peer_param.peer_addr = arsta->addr;
peer_param.peer_type = WMI_PEER_TYPE_DEFAULT;
+ peer_param.ml_enabled = sta->mlo;
ret = ath12k_peer_create(ar, arvif, sta, &peer_param);
if (ret) {
ath12k_warn(ab, "Failed to add peer: %pM for VDEV: %d\n",
- sta->addr, arvif->vdev_id);
+ arsta->addr, arvif->vdev_id);
goto free_peer;
}
ath12k_dbg(ab, ATH12K_DBG_MAC, "Added peer: %pM for VDEV: %d\n",
- sta->addr, arvif->vdev_id);
+ arsta->addr, arvif->vdev_id);
if (ieee80211_vif_is_mesh(vif)) {
- ret = ath12k_wmi_set_peer_param(ar, sta->addr,
+ ret = ath12k_wmi_set_peer_param(ar, arsta->addr,
arvif->vdev_id,
WMI_PEER_USE_4ADDR, 1);
if (ret) {
ath12k_warn(ab, "failed to STA %pM 4addr capability: %d\n",
- sta->addr, ret);
+ arsta->addr, ret);
goto free_peer;
}
}
- ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, sta->addr);
+ ret = ath12k_dp_peer_setup(ar, arvif->vdev_id, arsta->addr);
if (ret) {
ath12k_warn(ab, "failed to setup dp for peer %pM on vdev %i (%d)\n",
- sta->addr, arvif->vdev_id, ret);
+ arsta->addr, arvif->vdev_id, ret);
goto free_peer;
}
@@ -4868,7 +5336,9 @@ static int ath12k_mac_station_add(struct ath12k *ar,
return 0;
free_peer:
- ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);
+ ath12k_peer_delete(ar, arvif->vdev_id, arsta->addr);
+ kfree(arsta->rx_stats);
+ arsta->rx_stats = NULL;
dec_num_station:
ath12k_mac_dec_num_stations(arvif, arsta);
exit:
@@ -4906,101 +5376,131 @@ static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,
return bw;
}
-static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_sta *sta,
- enum ieee80211_sta_state old_state,
- enum ieee80211_sta_state new_state)
+static int ath12k_mac_assign_link_sta(struct ath12k_hw *ah,
+ struct ath12k_sta *ahsta,
+ struct ath12k_link_sta *arsta,
+ struct ath12k_vif *ahvif,
+ u8 link_id)
{
- struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
- struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
- struct ath12k *ar;
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);
+ struct ieee80211_link_sta *link_sta;
+ struct ath12k_link_vif *arvif;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ if (!arsta || link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
+ return -EINVAL;
+
+ arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
+ if (!arvif)
+ return -EINVAL;
+
+ memset(arsta, 0, sizeof(*arsta));
+
+ link_sta = wiphy_dereference(ah->hw->wiphy, sta->link[link_id]);
+ if (!link_sta)
+ return -EINVAL;
+
+ ether_addr_copy(arsta->addr, link_sta->addr);
+
+ /* logical index of the link sta in order of creation */
+ arsta->link_idx = ahsta->num_peer++;
+
+ arsta->link_id = link_id;
+ ahsta->links_map |= BIT(arsta->link_id);
+ arsta->arvif = arvif;
+ arsta->ahsta = ahsta;
+ ahsta->ahvif = ahvif;
+
+ wiphy_work_init(&arsta->update_wk, ath12k_sta_rc_update_wk);
+
+ rcu_assign_pointer(ahsta->link[link_id], arsta);
+
+ return 0;
+}
+
+static void ath12k_mac_ml_station_remove(struct ath12k_vif *ahvif,
+ struct ath12k_sta *ahsta)
+{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);
+ struct ath12k_hw *ah = ahvif->ah;
struct ath12k_link_vif *arvif;
struct ath12k_link_sta *arsta;
- struct ath12k_peer *peer;
+ unsigned long links;
+ struct ath12k *ar;
+ u8 link_id;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ ath12k_peer_mlo_link_peers_delete(ahvif, ahsta);
+
+ /* validate link station removal and clear arsta links */
+ links = ahsta->links_map;
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
+ arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
+ if (!arvif || !arsta)
+ continue;
+
+ ar = arvif->ar;
+
+ ath12k_mac_station_post_remove(ar, arvif, arsta);
+
+ ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id);
+ }
+
+ ath12k_peer_ml_delete(ah, sta);
+}
+
+static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
+ struct ath12k_link_vif *arvif,
+ struct ath12k_link_sta *arsta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state)
+{
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(arsta->ahsta);
+ struct ath12k *ar = arvif->ar;
int ret = 0;
lockdep_assert_wiphy(hw->wiphy);
- arvif = &ahvif->deflink;
- arsta = &ahsta->deflink;
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "mac handle link %u sta %pM state %d -> %d\n",
+ arsta->link_id, arsta->addr, old_state, new_state);
- ar = ath12k_get_ar_by_vif(hw, vif);
- if (!ar) {
- WARN_ON_ONCE(1);
- return -EINVAL;
+ /* IEEE80211_STA_NONE -> IEEE80211_STA_NOTEXIST: Remove the station
+ * from driver
+ */
+ if ((old_state == IEEE80211_STA_NONE &&
+ new_state == IEEE80211_STA_NOTEXIST)) {
+ ret = ath12k_mac_station_remove(ar, arvif, arsta);
+ if (ret) {
+ ath12k_warn(ar->ab, "Failed to remove station: %pM for VDEV: %d\n",
+ arsta->addr, arvif->vdev_id);
+ goto exit;
+ }
}
+ /* IEEE80211_STA_NOTEXIST -> IEEE80211_STA_NONE: Add new station to driver */
if (old_state == IEEE80211_STA_NOTEXIST &&
new_state == IEEE80211_STA_NONE) {
- memset(arsta, 0, sizeof(*arsta));
- rcu_assign_pointer(ahsta->link[0], arsta);
- /* TODO use appropriate link id once MLO support is added */
- arsta->link_id = ATH12K_DEFAULT_LINK_ID;
- ahsta->links_map = BIT(arsta->link_id);
- arsta->ahsta = ahsta;
- arsta->arvif = arvif;
- wiphy_work_init(&arsta->update_wk, ath12k_sta_rc_update_wk);
-
- synchronize_rcu();
-
ret = ath12k_mac_station_add(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
- sta->addr, arvif->vdev_id);
- } else if ((old_state == IEEE80211_STA_NONE &&
- new_state == IEEE80211_STA_NOTEXIST)) {
- wiphy_work_cancel(hw->wiphy, &arsta->update_wk);
-
- if (ahvif->vdev_type == WMI_VDEV_TYPE_STA) {
- ath12k_bss_disassoc(ar, arvif);
- ret = ath12k_mac_vdev_stop(arvif);
- if (ret)
- ath12k_warn(ar->ab, "failed to stop vdev %i: %d\n",
- arvif->vdev_id, ret);
- }
- ath12k_dp_peer_cleanup(ar, arvif->vdev_id, sta->addr);
+ arsta->addr, arvif->vdev_id);
- ret = ath12k_peer_delete(ar, arvif->vdev_id, sta->addr);
- if (ret)
- ath12k_warn(ar->ab, "Failed to delete peer: %pM for VDEV: %d\n",
- sta->addr, arvif->vdev_id);
- else
- ath12k_dbg(ar->ab, ATH12K_DBG_MAC, "Removed peer: %pM for VDEV: %d\n",
- sta->addr, arvif->vdev_id);
-
- ath12k_mac_dec_num_stations(arvif, arsta);
- spin_lock_bh(&ar->ab->base_lock);
- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
- if (peer && peer->sta == sta) {
- ath12k_warn(ar->ab, "Found peer entry %pM n vdev %i after it was supposedly removed\n",
- vif->addr, arvif->vdev_id);
- peer->sta = NULL;
- list_del(&peer->list);
- kfree(peer);
- ar->num_peers--;
- }
- spin_unlock_bh(&ar->ab->base_lock);
-
- kfree(arsta->rx_stats);
- arsta->rx_stats = NULL;
-
- if (arsta->link_id < IEEE80211_MLD_MAX_NUM_LINKS) {
- rcu_assign_pointer(ahsta->link[arsta->link_id], NULL);
- synchronize_rcu();
- ahsta->links_map &= ~(BIT(arsta->link_id));
- arsta->link_id = ATH12K_INVALID_LINK_ID;
- arsta->ahsta = NULL;
- }
+ /* IEEE80211_STA_AUTH -> IEEE80211_STA_ASSOC: Send station assoc command for
+ * peer associated to AP/Mesh/ADHOC vif type.
+ */
} else if (old_state == IEEE80211_STA_AUTH &&
new_state == IEEE80211_STA_ASSOC &&
(vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) {
- ret = ath12k_station_assoc(ar, arvif, arsta, false);
+ ret = ath12k_mac_station_assoc(ar, arvif, arsta, false);
if (ret)
ath12k_warn(ar->ab, "Failed to associate station: %pM\n",
- sta->addr);
+ arsta->addr);
spin_lock_bh(&ar->data_lock);
@@ -5008,45 +5508,141 @@ static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
arsta->bw_prev = sta->deflink.bandwidth;
spin_unlock_bh(&ar->data_lock);
+
+ /* IEEE80211_STA_ASSOC -> IEEE80211_STA_AUTHORIZED: set peer status as
+ * authorized
+ */
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTHORIZED) {
- spin_lock_bh(&ar->ab->base_lock);
-
- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
- if (peer)
- peer->is_authorized = true;
-
- spin_unlock_bh(&ar->ab->base_lock);
+ ret = ath12k_mac_station_authorize(ar, arvif, arsta);
+ if (ret)
+ ath12k_warn(ar->ab, "Failed to authorize station: %pM\n",
+ arsta->addr);
- if (vif->type == NL80211_IFTYPE_STATION && arvif->is_up) {
- ret = ath12k_wmi_set_peer_param(ar, sta->addr,
- arvif->vdev_id,
- WMI_PEER_AUTHORIZE,
- 1);
- if (ret)
- ath12k_warn(ar->ab, "Unable to authorize peer %pM vdev %d: %d\n",
- sta->addr, arvif->vdev_id, ret);
- }
+ /* IEEE80211_STA_AUTHORIZED -> IEEE80211_STA_ASSOC: station may be in removal,
+ * deauthorize it.
+ */
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
new_state == IEEE80211_STA_ASSOC) {
- spin_lock_bh(&ar->ab->base_lock);
+ ath12k_mac_station_unauthorize(ar, arvif, arsta);
- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
- if (peer)
- peer->is_authorized = false;
-
- spin_unlock_bh(&ar->ab->base_lock);
+ /* IEEE80211_STA_ASSOC -> IEEE80211_STA_AUTH: disassoc peer connected to
+ * AP/mesh/ADHOC vif type.
+ */
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH &&
(vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT ||
vif->type == NL80211_IFTYPE_ADHOC)) {
- ret = ath12k_station_disassoc(ar, arvif, arsta);
+ ret = ath12k_mac_station_disassoc(ar, arvif, arsta);
if (ret)
ath12k_warn(ar->ab, "Failed to disassociate station: %pM\n",
- sta->addr);
+ arsta->addr);
+ }
+
+exit:
+ return ret;
+}
+
+static int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ enum ieee80211_sta_state old_state,
+ enum ieee80211_sta_state new_state)
+{
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
+ struct ath12k_link_vif *arvif;
+ struct ath12k_link_sta *arsta;
+ unsigned long valid_links;
+ u8 link_id = 0;
+ int ret;
+
+ lockdep_assert_wiphy(hw->wiphy);
+
+ if (ieee80211_vif_is_mld(vif) && sta->valid_links) {
+ WARN_ON(!sta->mlo && hweight16(sta->valid_links) != 1);
+ link_id = ffs(sta->valid_links) - 1;
+ }
+
+ /* IEEE80211_STA_NOTEXIST -> IEEE80211_STA_NONE:
+ * New station add received. If this is a ML station then
+ * ahsta->links_map will be zero and sta->valid_links will be 1.
+ * Assign default link to the first link sta.
+ */
+ if (old_state == IEEE80211_STA_NOTEXIST &&
+ new_state == IEEE80211_STA_NONE) {
+ memset(ahsta, 0, sizeof(*ahsta));
+
+ arsta = &ahsta->deflink;
+
+ /* ML sta */
+ if (sta->mlo && !ahsta->links_map &&
+ (hweight16(sta->valid_links) == 1)) {
+ ret = ath12k_peer_ml_create(ah, sta);
+ if (ret) {
+ ath12k_hw_warn(ah, "unable to create ML peer for sta %pM",
+ sta->addr);
+ goto exit;
+ }
+ }
+
+ ret = ath12k_mac_assign_link_sta(ah, ahsta, arsta, ahvif,
+ link_id);
+ if (ret) {
+ ath12k_hw_warn(ah, "unable assign link %d for sta %pM",
+ link_id, sta->addr);
+ goto exit;
+ }
+
+ /* above arsta will get memset, hence do this after assign
+ * link sta
+ */
+ if (sta->mlo) {
+ arsta->is_assoc_link = true;
+ ahsta->assoc_link_id = link_id;
+ }
}
+ /* Handle all the other state transitions in generic way */
+ valid_links = ahsta->links_map;
+ for_each_set_bit(link_id, &valid_links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ arsta = wiphy_dereference(hw->wiphy, ahsta->link[link_id]);
+ /* some assumptions went wrong! */
+ if (WARN_ON(!arvif || !arsta))
+ continue;
+
+ /* vdev might be in deleted */
+ if (WARN_ON(!arvif->ar))
+ continue;
+
+ ret = ath12k_mac_handle_link_sta_state(hw, arvif, arsta,
+ old_state, new_state);
+ if (ret) {
+ ath12k_hw_warn(ah, "unable to move link sta %d of sta %pM from state %d to %d",
+ link_id, arsta->addr, old_state, new_state);
+ goto exit;
+ }
+ }
+
+ /* IEEE80211_STA_NONE -> IEEE80211_STA_NOTEXIST:
+ * Remove the station from driver (handle ML sta here since that
+ * needs special handling. Normal sta will be handled in generic
+ * handler below
+ */
+ if (old_state == IEEE80211_STA_NONE &&
+ new_state == IEEE80211_STA_NOTEXIST && sta->mlo)
+ ath12k_mac_ml_station_remove(ahvif, ahsta);
+
+ ret = 0;
+
+exit:
+ /* update the state if everything went well */
+ if (!ret)
+ ahsta->state = new_state;
+
return ret;
}
@@ -5054,16 +5650,22 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta)
{
- struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
struct ath12k *ar;
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_link_vif *arvif;
+ struct ath12k_link_sta *arsta;
+ u8 link_id;
int ret;
s16 txpwr;
lockdep_assert_wiphy(hw->wiphy);
- arvif = &ahvif->deflink;
+ /* TODO: use link id from mac80211 once that's implemented */
+ link_id = 0;
+
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ arsta = wiphy_dereference(hw->wiphy, ahsta->link[link_id]);
if (sta->deflink.txpwr.type == NL80211_TX_POWER_AUTOMATIC) {
txpwr = 0;
@@ -5080,9 +5682,9 @@ static int ath12k_mac_op_sta_set_txpwr(struct ieee80211_hw *hw,
goto out;
}
- ar = ath12k_ah_to_ar(ah, 0);
+ ar = arvif->ar;
- ret = ath12k_wmi_set_peer_param(ar, sta->addr, arvif->vdev_id,
+ ret = ath12k_wmi_set_peer_param(ar, arsta->addr, arvif->vdev_id,
WMI_PEER_USE_FIXED_PWR, txpwr);
if (ret) {
ath12k_warn(ar->ab, "failed to set tx power for station ret: %d\n",
@@ -5094,62 +5696,69 @@ out:
return ret;
}
-static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_link_sta *link_sta,
- u32 changed)
+static void ath12k_mac_op_link_sta_rc_update(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_link_sta *link_sta,
+ u32 changed)
{
struct ieee80211_sta *sta = link_sta->sta;
struct ath12k *ar;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k_link_sta *arsta;
struct ath12k_link_vif *arvif;
struct ath12k_peer *peer;
u32 bw, smps;
- /* TODO: use proper link id once link sta specific rc update support is
- * available in mac80211.
- */
- u8 link_id = ATH12K_DEFAULT_LINK_ID;
-
- ar = ath12k_get_ar_by_vif(hw, vif);
- if (!ar) {
- WARN_ON_ONCE(1);
- return;
- }
rcu_read_lock();
- arvif = rcu_dereference(ahvif->link[link_id]);
+ arvif = rcu_dereference(ahvif->link[link_sta->link_id]);
if (!arvif) {
- ath12k_warn(ar->ab, "mac sta rc update failed to fetch link vif on link id %u for peer %pM\n",
- link_id, sta->addr);
+ ath12k_hw_warn(ah, "mac sta rc update failed to fetch link vif on link id %u for peer %pM\n",
+ link_sta->link_id, sta->addr);
rcu_read_unlock();
return;
}
- arsta = rcu_dereference(ahsta->link[link_id]);
+
+ ar = arvif->ar;
+
+ arsta = rcu_dereference(ahsta->link[link_sta->link_id]);
if (!arsta) {
rcu_read_unlock();
ath12k_warn(ar->ab, "mac sta rc update failed to fetch link sta on link id %u for peer %pM\n",
- link_id, sta->addr);
+ link_sta->link_id, sta->addr);
return;
}
spin_lock_bh(&ar->ab->base_lock);
- peer = ath12k_peer_find(ar->ab, arvif->vdev_id, sta->addr);
+ peer = ath12k_peer_find(ar->ab, arvif->vdev_id, arsta->addr);
if (!peer) {
spin_unlock_bh(&ar->ab->base_lock);
rcu_read_unlock();
ath12k_warn(ar->ab, "mac sta rc update failed to find peer %pM on vdev %i\n",
- sta->addr, arvif->vdev_id);
+ arsta->addr, arvif->vdev_id);
return;
}
spin_unlock_bh(&ar->ab->base_lock);
+ if (arsta->link_id >= IEEE80211_MLD_MAX_NUM_LINKS) {
+ rcu_read_unlock();
+ return;
+ }
+
+ link_sta = rcu_dereference(sta->link[arsta->link_id]);
+ if (!link_sta) {
+ rcu_read_unlock();
+ ath12k_warn(ar->ab, "unable to access link sta in rc update for sta %pM link %u\n",
+ sta->addr, arsta->link_id);
+ return;
+ }
+
ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
"mac sta rc update for %pM changed %08x bw %d nss %d smps %d\n",
- sta->addr, changed, sta->deflink.bandwidth, sta->deflink.rx_nss,
- sta->deflink.smps_mode);
+ arsta->addr, changed, link_sta->bandwidth, link_sta->rx_nss,
+ link_sta->smps_mode);
spin_lock_bh(&ar->data_lock);
@@ -5160,12 +5769,12 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
}
if (changed & IEEE80211_RC_NSS_CHANGED)
- arsta->nss = sta->deflink.rx_nss;
+ arsta->nss = link_sta->rx_nss;
if (changed & IEEE80211_RC_SMPS_CHANGED) {
smps = WMI_PEER_SMPS_PS_NONE;
- switch (sta->deflink.smps_mode) {
+ switch (link_sta->smps_mode) {
case IEEE80211_SMPS_AUTOMATIC:
case IEEE80211_SMPS_OFF:
smps = WMI_PEER_SMPS_PS_NONE;
@@ -5177,8 +5786,8 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
smps = WMI_PEER_SMPS_DYNAMIC;
break;
default:
- ath12k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM\n",
- sta->deflink.smps_mode, sta->addr);
+ ath12k_warn(ar->ab, "Invalid smps %d in sta rc update for %pM link %u\n",
+ link_sta->smps_mode, arsta->addr, link_sta->link_id);
smps = WMI_PEER_SMPS_PS_NONE;
break;
}
@@ -5195,6 +5804,101 @@ static void ath12k_mac_op_sta_rc_update(struct ieee80211_hw *hw,
rcu_read_unlock();
}
+static struct ath12k_link_sta *ath12k_mac_alloc_assign_link_sta(struct ath12k_hw *ah,
+ struct ath12k_sta *ahsta,
+ struct ath12k_vif *ahvif,
+ u8 link_id)
+{
+ struct ath12k_link_sta *arsta;
+ int ret;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS)
+ return NULL;
+
+ arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
+ if (arsta)
+ return NULL;
+
+ arsta = kmalloc(sizeof(*arsta), GFP_KERNEL);
+ if (!arsta)
+ return NULL;
+
+ ret = ath12k_mac_assign_link_sta(ah, ahsta, arsta, ahvif, link_id);
+ if (ret) {
+ kfree(arsta);
+ return NULL;
+ }
+
+ return arsta;
+}
+
+static int ath12k_mac_op_change_sta_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u16 old_links, u16 new_links)
+{
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_hw *ah = hw->priv;
+ struct ath12k_link_vif *arvif;
+ struct ath12k_link_sta *arsta;
+ unsigned long valid_links;
+ struct ath12k *ar;
+ u8 link_id;
+ int ret;
+
+ lockdep_assert_wiphy(hw->wiphy);
+
+ if (!sta->valid_links)
+ return -EINVAL;
+
+ /* Firmware does not support removal of one of link stas. All sta
+ * would be removed during ML STA delete in sta_state(), hence link
+ * sta removal is not handled here.
+ */
+ if (new_links < old_links)
+ return 0;
+
+ if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
+ ath12k_hw_warn(ah, "unable to add link for ml sta %pM", sta->addr);
+ return -EINVAL;
+ }
+
+ /* this op is expected only after initial sta insertion with default link */
+ if (WARN_ON(ahsta->links_map == 0))
+ return -EINVAL;
+
+ valid_links = new_links;
+ for_each_set_bit(link_id, &valid_links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ if (ahsta->links_map & BIT(link_id))
+ continue;
+
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ arsta = ath12k_mac_alloc_assign_link_sta(ah, ahsta, ahvif, link_id);
+
+ if (!arvif || !arsta) {
+ ath12k_hw_warn(ah, "Failed to alloc/assign link sta");
+ continue;
+ }
+
+ ar = arvif->ar;
+ if (!ar)
+ continue;
+
+ ret = ath12k_mac_station_add(ar, arvif, arsta);
+ if (ret) {
+ ath12k_warn(ar->ab, "Failed to add station: %pM for VDEV: %d\n",
+ arsta->addr, arvif->vdev_id);
+ ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
static int ath12k_conf_tx_uapsd(struct ath12k_link_vif *arvif,
u16 ac, bool enable)
{
@@ -6054,6 +6758,8 @@ static void ath12k_mgmt_over_wmi_tx_drop(struct ath12k *ar, struct sk_buff *skb)
{
int num_mgmt;
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
ieee80211_free_txskb(ath12k_ar_to_hw(ar), skb);
num_mgmt = atomic_dec_if_positive(&ar->num_pending_mgmt_tx);
@@ -6115,6 +6821,8 @@ static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arv
int buf_id;
int ret;
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
ATH12K_SKB_CB(skb)->ar = ar;
spin_lock_bh(&ar->txmgmt_idr_lock);
buf_id = idr_alloc(&ar->txmgmt_idr, skb, 0,
@@ -6169,15 +6877,18 @@ static void ath12k_mgmt_over_wmi_tx_purge(struct ath12k *ar)
ath12k_mgmt_over_wmi_tx_drop(ar, skb);
}
-static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
+static void ath12k_mgmt_over_wmi_tx_work(struct wiphy *wiphy, struct wiphy_work *work)
{
struct ath12k *ar = container_of(work, struct ath12k, wmi_mgmt_tx_work);
+ struct ath12k_hw *ah = ar->ah;
struct ath12k_skb_cb *skb_cb;
struct ath12k_vif *ahvif;
struct ath12k_link_vif *arvif;
struct sk_buff *skb;
int ret;
+ lockdep_assert_wiphy(wiphy);
+
while ((skb = skb_dequeue(&ar->wmi_mgmt_tx_queue)) != NULL) {
skb_cb = ATH12K_SKB_CB(skb);
if (!skb_cb->vif) {
@@ -6187,7 +6898,15 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
}
ahvif = ath12k_vif_to_ahvif(skb_cb->vif);
- arvif = &ahvif->deflink;
+ if (!(ahvif->links_map & BIT(skb_cb->link_id))) {
+ ath12k_warn(ar->ab,
+ "invalid linkid %u in mgmt over wmi tx with linkmap 0x%x\n",
+ skb_cb->link_id, ahvif->links_map);
+ ath12k_mgmt_over_wmi_tx_drop(ar, skb);
+ continue;
+ }
+
+ arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[skb_cb->link_id]);
if (ar->allocated_vdev_map & (1LL << arvif->vdev_id)) {
ret = ath12k_mac_mgmt_tx_wmi(ar, arvif, skb);
if (ret) {
@@ -6197,8 +6916,9 @@ static void ath12k_mgmt_over_wmi_tx_work(struct work_struct *work)
}
} else {
ath12k_warn(ar->ab,
- "dropping mgmt frame for vdev %d, is_started %d\n",
+ "dropping mgmt frame for vdev %d link %u is_started %d\n",
arvif->vdev_id,
+ skb_cb->link_id,
arvif->is_started);
ath12k_mgmt_over_wmi_tx_drop(ar, skb);
}
@@ -6232,7 +6952,7 @@ static int ath12k_mac_mgmt_tx(struct ath12k *ar, struct sk_buff *skb,
skb_queue_tail(q, skb);
atomic_inc(&ar->num_pending_mgmt_tx);
- ieee80211_queue_work(ath12k_ar_to_hw(ar), &ar->wmi_mgmt_tx_work);
+ wiphy_work_queue(ath12k_ar_to_hw(ar)->wiphy, &ar->wmi_mgmt_tx_work);
return 0;
}
@@ -6258,6 +6978,105 @@ static void ath12k_mac_add_p2p_noa_ie(struct ath12k *ar,
spin_unlock_bh(&ar->data_lock);
}
+/* Note: called under rcu_read_lock() */
+static u8 ath12k_mac_get_tx_link(struct ieee80211_sta *sta, struct ieee80211_vif *vif,
+ u8 link, struct sk_buff *skb, u32 info_flags)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
+ struct ieee80211_link_sta *link_sta;
+ struct ieee80211_bss_conf *bss_conf;
+ struct ath12k_sta *ahsta;
+
+ /* Use the link id passed or the default vif link */
+ if (!sta) {
+ if (link != IEEE80211_LINK_UNSPECIFIED)
+ return link;
+
+ return ahvif->deflink.link_id;
+ }
+
+ ahsta = ath12k_sta_to_ahsta(sta);
+
+ /* Below translation ensures we pass proper A2 & A3 for non ML clients.
+ * Also it assumes for now support only for MLO AP in this path
+ */
+ if (!sta->mlo) {
+ link = ahsta->deflink.link_id;
+
+ if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP)
+ return link;
+
+ bss_conf = rcu_dereference(vif->link_conf[link]);
+ if (bss_conf) {
+ ether_addr_copy(hdr->addr2, bss_conf->addr);
+ if (!ieee80211_has_tods(hdr->frame_control) &&
+ !ieee80211_has_fromds(hdr->frame_control))
+ ether_addr_copy(hdr->addr3, bss_conf->addr);
+ }
+
+ return link;
+ }
+
+ /* enqueue eth enacap & data frames on primary link, FW does link
+ * selection and address translation.
+ */
+ if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP ||
+ ieee80211_is_data(hdr->frame_control))
+ return ahsta->assoc_link_id;
+
+ /* 802.11 frame cases */
+ if (link == IEEE80211_LINK_UNSPECIFIED)
+ link = ahsta->deflink.link_id;
+
+ if (!ieee80211_is_mgmt(hdr->frame_control))
+ return link;
+
+ /* Perform address conversion for ML STA Tx */
+ bss_conf = rcu_dereference(vif->link_conf[link]);
+ link_sta = rcu_dereference(sta->link[link]);
+
+ if (bss_conf && link_sta) {
+ ether_addr_copy(hdr->addr1, link_sta->addr);
+ ether_addr_copy(hdr->addr2, bss_conf->addr);
+
+ if (vif->type == NL80211_IFTYPE_STATION && bss_conf->bssid)
+ ether_addr_copy(hdr->addr3, bss_conf->bssid);
+ else if (vif->type == NL80211_IFTYPE_AP)
+ ether_addr_copy(hdr->addr3, bss_conf->addr);
+
+ return link;
+ }
+
+ if (bss_conf) {
+ /* In certain cases where a ML sta associated and added subset of
+ * links on which the ML AP is active, but now sends some frame
+ * (ex. Probe request) on a different link which is active in our
+ * MLD but was not added during previous association, we can
+ * still honor the Tx to that ML STA via the requested link.
+ * The control would reach here in such case only when that link
+ * address is same as the MLD address or in worst case clients
+ * used MLD address at TA wrongly which would have helped
+ * identify the ML sta object and pass it here.
+ * If the link address of that STA is different from MLD address,
+ * then the sta object would be NULL and control won't reach
+ * here but return at the start of the function itself with !sta
+ * check. Also this would not need any translation at hdr->addr1
+ * from MLD to link address since the RA is the MLD address
+ * (same as that link address ideally) already.
+ */
+ ether_addr_copy(hdr->addr2, bss_conf->addr);
+
+ if (vif->type == NL80211_IFTYPE_STATION && bss_conf->bssid)
+ ether_addr_copy(hdr->addr3, bss_conf->bssid);
+ else if (vif->type == NL80211_IFTYPE_AP)
+ ether_addr_copy(hdr->addr3, bss_conf->addr);
+ }
+
+ return link;
+}
+
+/* Note: called under rcu_read_lock() */
static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
@@ -6267,13 +7086,16 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
struct ieee80211_vif *vif = info->control.vif;
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_link_vif *arvif = &ahvif->deflink;
- struct ath12k *ar = arvif->ar;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
struct ieee80211_key_conf *key = info->control.hw_key;
+ struct ieee80211_sta *sta = control->sta;
u32 info_flags = info->flags;
+ struct ath12k *ar;
bool is_prb_rsp;
+ u8 link_id;
int ret;
+ link_id = u32_get_bits(info->control.flags, IEEE80211_TX_CTRL_MLO_LINK);
memset(skb_cb, 0, sizeof(*skb_cb));
skb_cb->vif = vif;
@@ -6282,6 +7104,27 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
skb_cb->flags |= ATH12K_SKB_CIPHER_SET;
}
+ /* handle only for MLO case, use deflink for non MLO case */
+ if (ieee80211_vif_is_mld(vif)) {
+ link_id = ath12k_mac_get_tx_link(sta, vif, link_id, skb, info_flags);
+ if (link_id >= IEEE80211_MLD_MAX_NUM_LINKS) {
+ ieee80211_free_txskb(hw, skb);
+ return;
+ }
+ } else {
+ link_id = 0;
+ }
+
+ arvif = rcu_dereference(ahvif->link[link_id]);
+ if (!arvif || !arvif->ar) {
+ ath12k_warn(ahvif->ah, "failed to find arvif link id %u for frame transmission",
+ link_id);
+ ieee80211_free_txskb(hw, skb);
+ return;
+ }
+
+ ar = arvif->ar;
+ skb_cb->link_id = link_id;
is_prb_rsp = ieee80211_is_probe_resp(hdr->frame_control);
if (info_flags & IEEE80211_TX_CTL_HW_80211_ENCAP) {
@@ -6309,10 +7152,12 @@ static void ath12k_mac_op_tx(struct ieee80211_hw *hw,
void ath12k_mac_drain_tx(struct ath12k *ar)
{
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
/* make sure rcu-protected mac80211 tx path itself is drained */
synchronize_net();
- cancel_work_sync(&ar->wmi_mgmt_tx_work);
+ wiphy_work_cancel(ath12k_ar_to_hw(ar)->wiphy, &ar->wmi_mgmt_tx_work);
ath12k_mgmt_over_wmi_tx_purge(ar);
}
@@ -6429,6 +7274,8 @@ static void ath12k_drain_tx(struct ath12k_hw *ah)
struct ath12k *ar;
int i;
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
for_each_ar(ah, ar, i)
ath12k_mac_drain_tx(ar);
}
@@ -6622,6 +7469,7 @@ static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif,
{
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *tx_vif = ahvif->vif->mbssid_tx_vif;
+ struct ieee80211_bss_conf *link_conf;
struct ath12k *ar = arvif->ar;
struct ath12k_link_vif *tx_arvif;
struct ath12k_vif *tx_ahvif;
@@ -6629,10 +7477,17 @@ static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif,
if (!tx_vif)
return 0;
+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!link_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in set mbssid params for vif %pM link %u\n",
+ ahvif->vif->addr, arvif->link_id);
+ return -ENOLINK;
+ }
+
tx_ahvif = ath12k_vif_to_ahvif(tx_vif);
tx_arvif = &tx_ahvif->deflink;
- if (ahvif->vif->bss_conf.nontransmitted) {
+ if (link_conf->nontransmitted) {
if (ar->ah->hw->wiphy != ieee80211_vif_to_wdev(tx_vif)->wiphy)
return -EINVAL;
@@ -6644,7 +7499,7 @@ static int ath12k_mac_setup_vdev_params_mbssid(struct ath12k_link_vif *arvif,
return -EINVAL;
}
- if (ahvif->vif->bss_conf.ema_ap)
+ if (link_conf->ema_ap)
*flags |= WMI_VDEV_MBSSID_FLAGS_EMA_MODE;
return 0;
@@ -6658,6 +7513,8 @@ static int ath12k_mac_setup_vdev_create_arg(struct ath12k_link_vif *arvif,
struct ath12k_vif *ahvif = arvif->ahvif;
int ret;
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
arg->if_id = arvif->vdev_id;
arg->type = ahvif->vdev_type;
arg->subtype = ahvif->vdev_subtype;
@@ -6689,6 +7546,17 @@ static int ath12k_mac_setup_vdev_create_arg(struct ath12k_link_vif *arvif,
}
arg->if_stats_id = ath12k_mac_get_vdev_stats_id(arvif);
+
+ if (ath12k_mac_is_ml_arvif(arvif)) {
+ if (hweight16(ahvif->vif->valid_links) > ATH12K_WMI_MLO_MAX_LINKS) {
+ ath12k_warn(ar->ab, "too many MLO links during setting up vdev: %d",
+ ahvif->vif->valid_links);
+ return -EINVAL;
+ }
+
+ ether_addr_copy(arg->mld_addr, ahvif->vif->addr);
+ }
+
return 0;
}
@@ -6839,16 +7707,25 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
struct ath12k_vif *ahvif = arvif->ahvif;
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
struct ath12k_wmi_vdev_create_arg vdev_arg = {0};
- struct ath12k_wmi_peer_create_arg peer_param;
+ struct ath12k_wmi_peer_create_arg peer_param = {0};
struct ieee80211_bss_conf *link_conf;
u32 param_id, param_value;
u16 nss;
int i;
int ret, vdev_id;
+ u8 link_id;
lockdep_assert_wiphy(hw->wiphy);
- link_conf = wiphy_dereference(hw->wiphy, vif->link_conf[arvif->link_id]);
+ /* If no link is active and scan vdev is requested
+ * use a default link conf for scan address purpose.
+ */
+ if (arvif->link_id == ATH12K_DEFAULT_SCAN_LINK && vif->valid_links)
+ link_id = ffs(vif->valid_links) - 1;
+ else
+ link_id = arvif->link_id;
+
+ link_conf = wiphy_dereference(hw->wiphy, vif->link_conf[link_id]);
if (!link_conf) {
ath12k_warn(ar->ab, "unable to access bss link conf in vdev create for vif %pM link %u\n",
vif->addr, arvif->link_id);
@@ -6999,7 +7876,7 @@ int ath12k_mac_vdev_create(struct ath12k *ar, struct ath12k_link_vif *arvif)
break;
}
- arvif->txpower = vif->bss_conf.txpower;
+ arvif->txpower = link_conf->txpower;
ret = ath12k_mac_txpower_recalc(ar);
if (ret)
goto err_peer_del;
@@ -7034,8 +7911,7 @@ err_peer_del:
ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id,
arvif->bssid);
if (ret)
- /* KVALO: why not goto err? */
- return ret;
+ goto err_vdev_del;
ar->num_peers--;
}
@@ -7129,7 +8005,9 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx)
{
- struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct ieee80211_vif *vif = ath12k_ahvif_to_vif(ahvif);
+ struct ath12k_link_vif *scan_arvif;
struct ath12k_hw *ah = hw->priv;
struct ath12k *ar;
struct ath12k_base *ab;
@@ -7148,6 +8026,19 @@ static struct ath12k *ath12k_mac_assign_vif_to_vdev(struct ieee80211_hw *hw,
if (!ar)
return NULL;
+ /* cleanup the scan vdev if we are done scan on that ar
+ * and now we want to create for actual usage.
+ */
+ if (ieee80211_vif_is_mld(vif)) {
+ scan_arvif = wiphy_dereference(hw->wiphy,
+ ahvif->link[ATH12K_DEFAULT_SCAN_LINK]);
+ if (scan_arvif && scan_arvif->ar == ar) {
+ ar->scan.vdev_id = -1;
+ ath12k_mac_remove_link_interface(hw, scan_arvif);
+ ath12k_mac_unassign_link_vif(scan_arvif);
+ }
+ }
+
if (arvif->ar) {
/* This is not expected really */
if (WARN_ON(!arvif->is_created)) {
@@ -7243,14 +8134,9 @@ static int ath12k_mac_op_add_interface(struct ieee80211_hw *hw,
vif->hw_queue[i] = ATH12K_HW_DEFAULT_QUEUE;
vif->driver_flags |= IEEE80211_VIF_SUPPORTS_UAPSD;
- /* For non-ml vifs, vif->addr is the actual vdev address but for
- * ML vif link(link BSSID) address is the vdev address and it can be a
- * different one from vif->addr (i.e ML address).
- * Defer vdev creation until assign_chanctx or hw_scan is initiated as driver
+ /* Defer vdev creation until assign_chanctx or hw_scan is initiated as driver
* will not know if this interface is an ML vif at this point.
*/
- ath12k_mac_assign_vif_to_vdev(hw, arvif, NULL);
-
return 0;
}
@@ -7352,7 +8238,7 @@ static void ath12k_mac_op_remove_interface(struct ieee80211_hw *hw,
lockdep_assert_wiphy(hw->wiphy);
- for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
+ for (link_id = 0; link_id < ATH12K_NUM_MAX_LINKS; link_id++) {
/* if we cached some config but never received assign chanctx,
* free the allocated cache.
*/
@@ -7453,20 +8339,26 @@ static int ath12k_mac_op_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx
return ret;
}
-static int ath12k_mac_ampdu_action(struct ath12k_link_vif *arvif,
- struct ieee80211_ampdu_params *params)
+static int ath12k_mac_ampdu_action(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_ampdu_params *params,
+ u8 link_id)
{
- struct ath12k *ar = arvif->ar;
+ struct ath12k *ar;
int ret = -EINVAL;
- lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+ lockdep_assert_wiphy(hw->wiphy);
+
+ ar = ath12k_get_ar_by_vif(hw, vif, link_id);
+ if (!ar)
+ return -EINVAL;
switch (params->action) {
case IEEE80211_AMPDU_RX_START:
- ret = ath12k_dp_rx_ampdu_start(ar, params);
+ ret = ath12k_dp_rx_ampdu_start(ar, params, link_id);
break;
case IEEE80211_AMPDU_RX_STOP:
- ret = ath12k_dp_rx_ampdu_stop(ar, params);
+ ret = ath12k_dp_rx_ampdu_stop(ar, params, link_id);
break;
case IEEE80211_AMPDU_TX_START:
case IEEE80211_AMPDU_TX_STOP_CONT:
@@ -7480,6 +8372,10 @@ static int ath12k_mac_ampdu_action(struct ath12k_link_vif *arvif,
break;
}
+ if (ret)
+ ath12k_warn(ar->ab, "unable to perform ampdu action %d for vif %pM link %u ret %d\n",
+ params->action, vif->addr, link_id, ret);
+
return ret;
}
@@ -7487,27 +8383,24 @@ static int ath12k_mac_op_ampdu_action(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_ampdu_params *params)
{
- struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
- struct ath12k *ar;
- struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
- struct ath12k_link_vif *arvif;
+ struct ieee80211_sta *sta = params->sta;
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ unsigned long links_map = ahsta->links_map;
int ret = -EINVAL;
+ u8 link_id;
lockdep_assert_wiphy(hw->wiphy);
- ar = ath12k_get_ar_by_vif(hw, vif);
- if (!ar)
- return -EINVAL;
-
- ar = ath12k_ah_to_ar(ah, 0);
- arvif = &ahvif->deflink;
+ if (WARN_ON(!links_map))
+ return ret;
- ret = ath12k_mac_ampdu_action(arvif, params);
- if (ret)
- ath12k_warn(ar->ab, "pdev idx %d unable to perform ampdu action %d ret %d\n",
- ar->pdev_idx, params->action, ret);
+ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) {
+ ret = ath12k_mac_ampdu_action(hw, vif, params, link_id);
+ if (ret)
+ return ret;
+ }
- return ret;
+ return 0;
}
static int ath12k_mac_op_add_chanctx(struct ieee80211_hw *hw,
@@ -7627,6 +8520,58 @@ ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar,
return down_mode;
}
+static void
+ath12k_mac_mlo_get_vdev_args(struct ath12k_link_vif *arvif,
+ struct wmi_ml_arg *ml_arg)
+{
+ struct ath12k_vif *ahvif = arvif->ahvif;
+ struct wmi_ml_partner_info *partner_info;
+ struct ieee80211_bss_conf *link_conf;
+ struct ath12k_link_vif *arvif_p;
+ unsigned long links;
+ u8 link_id;
+
+ lockdep_assert_wiphy(ahvif->ah->hw->wiphy);
+
+ if (!ath12k_mac_is_ml_arvif(arvif))
+ return;
+
+ if (hweight16(ahvif->vif->valid_links) > ATH12K_WMI_MLO_MAX_LINKS)
+ return;
+
+ ml_arg->enabled = true;
+
+ /* Driver always add a new link via VDEV START, FW takes
+ * care of internally adding this link to existing
+ * link vdevs which are advertised as partners below
+ */
+ ml_arg->link_add = true;
+ partner_info = ml_arg->partner_info;
+
+ links = ahvif->links_map;
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif_p = wiphy_dereference(ahvif->ah->hw->wiphy, ahvif->link[link_id]);
+
+ if (WARN_ON(!arvif_p))
+ continue;
+
+ if (arvif == arvif_p)
+ continue;
+
+ link_conf = wiphy_dereference(ahvif->ah->hw->wiphy,
+ ahvif->vif->link_conf[arvif_p->link_id]);
+
+ if (!link_conf)
+ continue;
+
+ partner_info->vdev_id = arvif_p->vdev_id;
+ partner_info->hw_link_id = arvif_p->ar->pdev->hw_link_id;
+ ether_addr_copy(partner_info->addr, link_conf->addr);
+ ml_arg->num_partner_links++;
+ partner_info++;
+ }
+}
+
static int
ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif,
struct ieee80211_chanctx_conf *ctx,
@@ -7637,11 +8582,18 @@ ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif,
struct wmi_vdev_start_req_arg arg = {};
const struct cfg80211_chan_def *chandef = &ctx->def;
struct ath12k_vif *ahvif = arvif->ahvif;
- int he_support = ahvif->vif->bss_conf.he_support;
+ struct ieee80211_bss_conf *link_conf;
int ret;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+ link_conf = ath12k_mac_get_link_bss_conf(arvif);
+ if (!link_conf) {
+ ath12k_warn(ar->ab, "unable to access bss link conf in vdev start for vif %pM link %u\n",
+ ahvif->vif->addr, arvif->link_id);
+ return -ENOLINK;
+ }
+
reinit_completion(&ar->vdev_setup_done);
arg.vdev_id = arvif->vdev_id;
@@ -7693,7 +8645,7 @@ ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif,
spin_unlock_bh(&ab->base_lock);
/* TODO: Notify if secondary 80Mhz also needs radar detection */
- if (he_support) {
+ if (link_conf->he_support) {
ret = ath12k_set_he_mu_sounding_mode(ar, arvif);
if (ret) {
ath12k_warn(ar->ab, "failed to set he mode vdev %i\n",
@@ -7705,6 +8657,9 @@ ath12k_mac_vdev_start_restart(struct ath12k_link_vif *arvif,
arg.passive |= !!(chandef->chan->flags & IEEE80211_CHAN_NO_IR);
+ if (!restart)
+ ath12k_mac_mlo_get_vdev_args(arvif, &arg.ml);
+
ath12k_dbg(ab, ATH12K_DBG_MAC,
"mac vdev %d start center_freq %d phymode %s punct_bitmap 0x%x\n",
arg.vdev_id, arg.freq,
@@ -7778,19 +8733,32 @@ ath12k_mac_change_chanctx_cnt_iter(void *data, u8 *mac,
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_mac_change_chanctx_arg *arg = data;
+ struct ieee80211_bss_conf *link_conf;
struct ath12k_link_vif *arvif;
+ unsigned long links_map;
+ u8 link_id;
lockdep_assert_wiphy(ahvif->ah->hw->wiphy);
- arvif = &ahvif->deflink;
+ links_map = ahvif->links_map;
+ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(ahvif->ah->hw->wiphy, ahvif->link[link_id]);
+ if (WARN_ON(!arvif))
+ continue;
- if (arvif->ar != arg->ar)
- return;
+ if (arvif->ar != arg->ar)
+ continue;
- if (rcu_access_pointer(vif->bss_conf.chanctx_conf) != arg->ctx)
- return;
+ link_conf = wiphy_dereference(ahvif->ah->hw->wiphy,
+ vif->link_conf[link_id]);
+ if (WARN_ON(!link_conf))
+ continue;
+
+ if (rcu_access_pointer(link_conf->chanctx_conf) != arg->ctx)
+ continue;
- arg->n_vifs++;
+ arg->n_vifs++;
+ }
}
static void
@@ -7799,27 +8767,41 @@ ath12k_mac_change_chanctx_fill_iter(void *data, u8 *mac,
{
struct ath12k_vif *ahvif = ath12k_vif_to_ahvif(vif);
struct ath12k_mac_change_chanctx_arg *arg = data;
+ struct ieee80211_bss_conf *link_conf;
struct ieee80211_chanctx_conf *ctx;
struct ath12k_link_vif *arvif;
+ unsigned long links_map;
+ u8 link_id;
lockdep_assert_wiphy(ahvif->ah->hw->wiphy);
- arvif = &ahvif->deflink;
+ links_map = ahvif->links_map;
+ for_each_set_bit(link_id, &links_map, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(ahvif->ah->hw->wiphy, ahvif->link[link_id]);
+ if (WARN_ON(!arvif))
+ continue;
- if (arvif->ar != arg->ar)
- return;
+ if (arvif->ar != arg->ar)
+ continue;
- ctx = rcu_access_pointer(vif->bss_conf.chanctx_conf);
- if (ctx != arg->ctx)
- return;
+ link_conf = wiphy_dereference(ahvif->ah->hw->wiphy,
+ vif->link_conf[arvif->link_id]);
+ if (WARN_ON(!link_conf))
+ continue;
- if (WARN_ON(arg->next_vif == arg->n_vifs))
- return;
+ ctx = rcu_access_pointer(link_conf->chanctx_conf);
+ if (ctx != arg->ctx)
+ continue;
+
+ if (WARN_ON(arg->next_vif == arg->n_vifs))
+ return;
- arg->vifs[arg->next_vif].vif = vif;
- arg->vifs[arg->next_vif].old_ctx = ctx;
- arg->vifs[arg->next_vif].new_ctx = ctx;
- arg->next_vif++;
+ arg->vifs[arg->next_vif].vif = vif;
+ arg->vifs[arg->next_vif].old_ctx = ctx;
+ arg->vifs[arg->next_vif].new_ctx = ctx;
+ arg->vifs[arg->next_vif].link_conf = link_conf;
+ arg->next_vif++;
+ }
}
static u32 ath12k_mac_nlwidth_to_wmiwidth(enum nl80211_chan_width width)
@@ -7879,10 +8861,12 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
int n_vifs)
{
struct ath12k_wmi_vdev_up_params params = {};
+ struct ieee80211_bss_conf *link_conf;
struct ath12k_base *ab = ar->ab;
struct ath12k_link_vif *arvif;
struct ieee80211_vif *vif;
struct ath12k_vif *ahvif;
+ u8 link_id;
int ret;
int i;
bool monitor_vif = false;
@@ -7892,7 +8876,10 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
for (i = 0; i < n_vifs; i++) {
vif = vifs[i].vif;
ahvif = ath12k_vif_to_ahvif(vif);
- arvif = &ahvif->deflink;
+ link_conf = vifs[i].link_conf;
+ link_id = link_conf->link_id;
+ arvif = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
+ ahvif->link[link_id]);
if (vif->type == NL80211_IFTYPE_MONITOR)
monitor_vif = true;
@@ -7945,13 +8932,13 @@ ath12k_mac_update_vif_chan(struct ath12k *ar,
params.aid = ahvif->aid;
params.bssid = arvif->bssid;
if (vif->mbssid_tx_vif) {
- struct ath12k_vif *ahvif =
+ struct ath12k_vif *tx_ahvif =
ath12k_vif_to_ahvif(vif->mbssid_tx_vif);
- struct ath12k_link_vif *arvif = &ahvif->deflink;
+ struct ath12k_link_vif *tx_arvif = &tx_ahvif->deflink;
- params.tx_bssid = arvif->bssid;
- params.nontx_profile_idx = vif->bss_conf.bssid_index;
- params.nontx_profile_cnt = 1 << vif->bss_conf.bssid_indicator;
+ params.tx_bssid = tx_arvif->bssid;
+ params.nontx_profile_idx = link_conf->bssid_index;
+ params.nontx_profile_cnt = 1 << link_conf->bssid_indicator;
}
ret = ath12k_wmi_vdev_up(arvif->ar, &params);
if (ret) {
@@ -8099,11 +9086,8 @@ ath12k_mac_op_assign_vif_chanctx(struct ieee80211_hw *hw,
return -ENOMEM;
}
- if (!arvif->is_started) {
- ar = ath12k_mac_assign_vif_to_vdev(hw, arvif, ctx);
- if (!ar)
- return -EINVAL;
- } else {
+ ar = ath12k_mac_assign_vif_to_vdev(hw, arvif, ctx);
+ if (!ar) {
ath12k_warn(arvif->ar->ab, "failed to assign chanctx for vif %pM link id %u link vif is already started",
vif->addr, link_id);
return -EINVAL;
@@ -8348,6 +9332,8 @@ static int ath12k_mac_flush(struct ath12k *ar)
int ath12k_mac_wait_tx_complete(struct ath12k *ar)
{
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
ath12k_mac_drain_tx(ar);
return ath12k_mac_flush(ar);
}
@@ -8356,7 +9342,11 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
u32 queues, bool drop)
{
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
+ struct ath12k_link_vif *arvif;
+ struct ath12k_vif *ahvif;
+ unsigned long links;
struct ath12k *ar;
+ u8 link_id;
int i;
lockdep_assert_wiphy(hw->wiphy);
@@ -8371,12 +9361,18 @@ static void ath12k_mac_op_flush(struct ieee80211_hw *hw, struct ieee80211_vif *v
return;
}
- ar = ath12k_get_ar_by_vif(hw, vif);
+ for_each_ar(ah, ar, i)
+ wiphy_work_flush(hw->wiphy, &ar->wmi_mgmt_tx_work);
- if (!ar)
- return;
+ ahvif = ath12k_vif_to_ahvif(vif);
+ links = ahvif->links_map;
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(hw->wiphy, ahvif->link[link_id]);
+ if (!(arvif && arvif->ar))
+ continue;
- ath12k_mac_flush(ar);
+ ath12k_mac_flush(arvif->ar);
+ }
}
static int
@@ -8575,10 +9571,11 @@ static void ath12k_mac_set_bitrate_mask_iter(void *data,
{
struct ath12k_link_vif *arvif = data;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
- struct ath12k_link_sta *arsta = &ahsta->deflink;
+ struct ath12k_link_sta *arsta;
struct ath12k *ar = arvif->ar;
- if (arsta->arvif != arvif)
+ arsta = rcu_dereference(ahsta->link[arvif->link_id]);
+ if (!arsta || arsta->arvif != arvif)
return;
spin_lock_bh(&ar->data_lock);
@@ -8593,21 +9590,26 @@ static void ath12k_mac_disable_peer_fixed_rate(void *data,
{
struct ath12k_link_vif *arvif = data;
struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
- struct ath12k_link_sta *arsta = &ahsta->deflink;
+ struct ath12k_link_sta *arsta;
struct ath12k *ar = arvif->ar;
int ret;
- if (arsta->arvif != arvif)
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
+ ahsta->link[arvif->link_id]);
+
+ if (!arsta || arsta->arvif != arvif)
return;
- ret = ath12k_wmi_set_peer_param(ar, sta->addr,
+ ret = ath12k_wmi_set_peer_param(ar, arsta->addr,
arvif->vdev_id,
WMI_PEER_PARAM_FIXED_RATE,
WMI_FIXED_RATE_NONE);
if (ret)
ath12k_warn(ar->ab,
"failed to disable peer fixed rate for STA %pM ret %d\n",
- sta->addr, ret);
+ arsta->addr, ret);
}
static int
@@ -9159,7 +10161,7 @@ static const struct ieee80211_ops ath12k_ops = {
.set_rekey_data = ath12k_mac_op_set_rekey_data,
.sta_state = ath12k_mac_op_sta_state,
.sta_set_txpwr = ath12k_mac_op_sta_set_txpwr,
- .link_sta_rc_update = ath12k_mac_op_sta_rc_update,
+ .link_sta_rc_update = ath12k_mac_op_link_sta_rc_update,
.conf_tx = ath12k_mac_op_conf_tx,
.set_antenna = ath12k_mac_op_set_antenna,
.get_antenna = ath12k_mac_op_get_antenna,
@@ -9178,7 +10180,7 @@ static const struct ieee80211_ops ath12k_ops = {
.sta_statistics = ath12k_mac_op_sta_statistics,
.remain_on_channel = ath12k_mac_op_remain_on_channel,
.cancel_remain_on_channel = ath12k_mac_op_cancel_remain_on_channel,
-
+ .change_sta_links = ath12k_mac_op_change_sta_links,
#ifdef CONFIG_PM
.suspend = ath12k_wow_op_suspend,
.resume = ath12k_wow_op_resume,
@@ -9812,36 +10814,32 @@ static void ath12k_mac_setup(struct ath12k *ar)
INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work);
INIT_WORK(&ar->regd_update_work, ath12k_regd_update_work);
- INIT_WORK(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work);
+ wiphy_work_init(&ar->wmi_mgmt_tx_work, ath12k_mgmt_over_wmi_tx_work);
skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
}
-int ath12k_mac_register(struct ath12k_base *ab)
+int ath12k_mac_register(struct ath12k_hw_group *ag)
{
+ struct ath12k_base *ab = ag->ab[0];
struct ath12k_hw *ah;
int i;
int ret;
- if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))
- return 0;
-
- /* Initialize channel counters frequency value in hertz */
- ab->cc_freq_hz = 320000;
- ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1;
-
- for (i = 0; i < ab->num_hw; i++) {
- ah = ab->ah[i];
+ for (i = 0; i < ath12k_get_num_hw(ab); i++) {
+ ah = ath12k_ab_to_ah(ab, i);
ret = ath12k_mac_hw_register(ah);
if (ret)
goto err;
}
+ set_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags);
+
return 0;
err:
for (i = i - 1; i >= 0; i--) {
- ah = ab->ah[i];
+ ah = ath12k_ab_to_ah(ab, i);
if (!ah)
continue;
@@ -9851,13 +10849,16 @@ err:
return ret;
}
-void ath12k_mac_unregister(struct ath12k_base *ab)
+void ath12k_mac_unregister(struct ath12k_hw_group *ag)
{
+ struct ath12k_base *ab = ag->ab[0];
struct ath12k_hw *ah;
int i;
- for (i = ab->num_hw - 1; i >= 0; i--) {
- ah = ab->ah[i];
+ clear_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags);
+
+ for (i = ath12k_get_num_hw(ab) - 1; i >= 0; i--) {
+ ah = ath12k_ab_to_ah(ab, i);
if (!ah)
continue;
@@ -9870,12 +10871,13 @@ static void ath12k_mac_hw_destroy(struct ath12k_hw *ah)
ieee80211_free_hw(ah->hw);
}
-static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_base *ab,
+static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag,
struct ath12k_pdev_map *pdev_map,
u8 num_pdev_map)
{
struct ieee80211_hw *hw;
struct ath12k *ar;
+ struct ath12k_base *ab;
struct ath12k_pdev *pdev;
struct ath12k_hw *ah;
int i;
@@ -9891,6 +10893,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_base *ab,
ah->num_radio = num_pdev_map;
mutex_init(&ah->hw_mutex);
+ INIT_LIST_HEAD(&ah->ml_peers);
for (i = 0; i < num_pdev_map; i++) {
ab = pdev_map[i].ab;
@@ -9906,53 +10909,97 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_base *ab,
pdev->ar = ar;
ath12k_mac_setup(ar);
+ ath12k_dp_pdev_pre_alloc(ar);
}
return ah;
}
-void ath12k_mac_destroy(struct ath12k_base *ab)
+void ath12k_mac_destroy(struct ath12k_hw_group *ag)
{
struct ath12k_pdev *pdev;
- int i;
+ struct ath12k_base *ab = ag->ab[0];
+ int i, j;
+ struct ath12k_hw *ah;
- for (i = 0; i < ab->num_radios; i++) {
- pdev = &ab->pdevs[i];
- if (!pdev->ar)
+ for (i = 0; i < ag->num_devices; i++) {
+ ab = ag->ab[i];
+ if (!ab)
continue;
- pdev->ar = NULL;
+ for (j = 0; j < ab->num_radios; j++) {
+ pdev = &ab->pdevs[j];
+ if (!pdev->ar)
+ continue;
+ pdev->ar = NULL;
+ }
}
- for (i = 0; i < ab->num_hw; i++) {
- if (!ab->ah[i])
+ for (i = 0; i < ath12k_get_num_hw(ab); i++) {
+ ah = ath12k_ab_to_ah(ab, i);
+ if (!ah)
continue;
- ath12k_mac_hw_destroy(ab->ah[i]);
- ab->ah[i] = NULL;
+ ath12k_mac_hw_destroy(ah);
+ ath12k_ab_set_ah(ab, i, NULL);
}
}
-int ath12k_mac_allocate(struct ath12k_base *ab)
+static void ath12k_mac_set_device_defaults(struct ath12k_base *ab)
+{
+ /* Initialize channel counters frequency value in hertz */
+ ab->cc_freq_hz = 320000;
+ ab->free_vdev_map = (1LL << (ab->num_radios * TARGET_NUM_VDEVS)) - 1;
+}
+
+int ath12k_mac_allocate(struct ath12k_hw_group *ag)
{
+ struct ath12k_pdev_map pdev_map[ATH12K_GROUP_MAX_RADIO];
+ int mac_id, device_id, total_radio, num_hw;
+ struct ath12k_base *ab;
struct ath12k_hw *ah;
- struct ath12k_pdev_map pdev_map[MAX_RADIOS];
int ret, i, j;
u8 radio_per_hw;
- if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags))
- return 0;
+ total_radio = 0;
+ for (i = 0; i < ag->num_devices; i++)
+ total_radio += ag->ab[i]->num_radios;
+
+ /* All pdev get combined and register as single wiphy based on
+ * hardware group which participate in multi-link operation else
+ * each pdev get register separately.
+ */
+ if (ag->mlo_capable)
+ radio_per_hw = total_radio;
+ else
+ radio_per_hw = 1;
+
+ num_hw = total_radio / radio_per_hw;
- ab->num_hw = ab->num_radios;
- radio_per_hw = 1;
+ if (WARN_ON(num_hw >= ATH12K_GROUP_MAX_RADIO))
+ return -ENOSPC;
- for (i = 0; i < ab->num_hw; i++) {
+ ag->num_hw = 0;
+ device_id = 0;
+ mac_id = 0;
+ for (i = 0; i < num_hw; i++) {
for (j = 0; j < radio_per_hw; j++) {
+ ab = ag->ab[device_id];
pdev_map[j].ab = ab;
- pdev_map[j].pdev_idx = (i * radio_per_hw) + j;
+ pdev_map[j].pdev_idx = mac_id;
+ mac_id++;
+
+ /* If mac_id falls beyond the current device MACs then
+ * move to next device
+ */
+ if (mac_id >= ab->num_radios) {
+ mac_id = 0;
+ device_id++;
+ ath12k_mac_set_device_defaults(ab);
+ }
}
- ah = ath12k_mac_hw_allocate(ab, pdev_map, radio_per_hw);
+ ah = ath12k_mac_hw_allocate(ag, pdev_map, radio_per_hw);
if (!ah) {
ath12k_warn(ab, "failed to allocate mac80211 hw device for hw_idx %d\n",
i);
@@ -9960,20 +11007,22 @@ int ath12k_mac_allocate(struct ath12k_base *ab)
goto err;
}
- ab->ah[i] = ah;
- }
+ ah->dev = ab->dev;
- ath12k_dp_pdev_pre_alloc(ab);
+ ag->ah[i] = ah;
+ ag->num_hw++;
+ }
return 0;
err:
for (i = i - 1; i >= 0; i--) {
- if (!ab->ah[i])
+ ah = ath12k_ab_to_ah(ab, i);
+ if (!ah)
continue;
- ath12k_mac_hw_destroy(ab->ah[i]);
- ab->ah[i] = NULL;
+ ath12k_mac_hw_destroy(ah);
+ ath12k_ab_set_ah(ab, i, NULL);
}
return ret;
diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h
index d382337ba649..ccfc215d83ff 100644
--- a/drivers/net/wireless/ath/ath12k/mac.h
+++ b/drivers/net/wireless/ath/ath12k/mac.h
@@ -14,6 +14,7 @@
struct ath12k;
struct ath12k_base;
struct ath12k_hw;
+struct ath12k_hw_group;
struct ath12k_pdev_map;
struct ath12k_generic_iter {
@@ -44,6 +45,12 @@ struct ath12k_generic_iter {
#define ATH12K_DEFAULT_LINK_ID 0
#define ATH12K_INVALID_LINK_ID 255
+/* Default link after the IEEE802.11 defined Max link id limit
+ * for driver usage purpose.
+ */
+#define ATH12K_DEFAULT_SCAN_LINK IEEE80211_MLD_MAX_NUM_LINKS
+#define ATH12K_NUM_MAX_LINKS (IEEE80211_MLD_MAX_NUM_LINKS + 1)
+
enum ath12k_supported_bw {
ATH12K_BW_20 = 0,
ATH12K_BW_40 = 1,
@@ -54,10 +61,10 @@ enum ath12k_supported_bw {
extern const struct htt_rx_ring_tlv_filter ath12k_mac_mon_status_filter_default;
-void ath12k_mac_destroy(struct ath12k_base *ab);
-void ath12k_mac_unregister(struct ath12k_base *ab);
-int ath12k_mac_register(struct ath12k_base *ab);
-int ath12k_mac_allocate(struct ath12k_base *ab);
+void ath12k_mac_destroy(struct ath12k_hw_group *ag);
+void ath12k_mac_unregister(struct ath12k_hw_group *ag);
+int ath12k_mac_register(struct ath12k_hw_group *ag);
+int ath12k_mac_allocate(struct ath12k_hw_group *ag);
int ath12k_mac_hw_ratecode_to_legacy_rate(u8 hw_rc, u8 preamble, u8 *rateidx,
u16 *rate);
u8 ath12k_mac_bitrate_to_idx(const struct ieee80211_supported_band *sband,
@@ -89,5 +96,6 @@ int ath12k_mac_vif_set_keepalive(struct ath12k_link_vif *arvif,
enum wmi_sta_keepalive_method method,
u32 interval);
u8 ath12k_mac_get_target_pdev_id(struct ath12k *ar);
+int ath12k_mac_vdev_stop(struct ath12k_link_vif *arvif);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/pci.c b/drivers/net/wireless/ath/ath12k/pci.c
index cf907550e6a4..06cff3849ab8 100644
--- a/drivers/net/wireless/ath/ath12k/pci.c
+++ b/drivers/net/wireless/ath/ath12k/pci.c
@@ -1123,6 +1123,9 @@ void ath12k_pci_ext_irq_enable(struct ath12k_base *ab)
void ath12k_pci_ext_irq_disable(struct ath12k_base *ab)
{
+ if (!test_bit(ATH12K_FLAG_EXT_IRQ_ENABLED, &ab->dev_flags))
+ return;
+
__ath12k_pci_ext_irq_disable(ab);
ath12k_pci_sync_ext_irqs(ab);
}
@@ -1147,6 +1150,11 @@ int ath12k_pci_hif_resume(struct ath12k_base *ab)
void ath12k_pci_stop(struct ath12k_base *ab)
{
+ struct ath12k_pci *ab_pci = ath12k_pci_priv(ab);
+
+ if (!test_bit(ATH12K_PCI_FLAG_INIT_DONE, &ab_pci->flags))
+ return;
+
ath12k_pci_ce_irq_disable_sync(ab);
ath12k_ce_cleanup_pipes(ab);
}
@@ -1717,6 +1725,7 @@ static void ath12k_pci_remove(struct pci_dev *pdev)
if (test_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags)) {
ath12k_pci_power_down(ab, false);
ath12k_qmi_deinit_service(ab);
+ ath12k_core_hw_group_unassign(ab);
goto qmi_fail;
}
@@ -1725,6 +1734,7 @@ static void ath12k_pci_remove(struct pci_dev *pdev)
cancel_work_sync(&ab->reset_work);
cancel_work_sync(&ab->dump_work);
ath12k_core_deinit(ab);
+ ath12k_fw_unmap(ab);
qmi_fail:
ath12k_mhi_unregister(ab_pci);
diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
index 7a62665b8af9..5763c5a40cfc 100644
--- a/drivers/net/wireless/ath/ath12k/peer.c
+++ b/drivers/net/wireless/ath/ath12k/peer.c
@@ -8,6 +8,22 @@
#include "peer.h"
#include "debug.h"
+static struct ath12k_ml_peer *ath12k_peer_ml_find(struct ath12k_hw *ah, const u8 *addr)
+{
+ struct ath12k_ml_peer *ml_peer;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ list_for_each_entry(ml_peer, &ah->ml_peers, list) {
+ if (!ether_addr_equal(ml_peer->addr, addr))
+ continue;
+
+ return ml_peer;
+ }
+
+ return NULL;
+}
+
struct ath12k_peer *ath12k_peer_find(struct ath12k_base *ab, int vdev_id,
const u8 *addr)
{
@@ -63,6 +79,20 @@ struct ath12k_peer *ath12k_peer_find_by_addr(struct ath12k_base *ab,
return NULL;
}
+static struct ath12k_peer *ath12k_peer_find_by_ml_id(struct ath12k_base *ab,
+ int ml_peer_id)
+{
+ struct ath12k_peer *peer;
+
+ lockdep_assert_held(&ab->base_lock);
+
+ list_for_each_entry(peer, &ab->peers, list)
+ if (ml_peer_id == peer->ml_id)
+ return peer;
+
+ return NULL;
+}
+
struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab,
int peer_id)
{
@@ -70,6 +100,9 @@ struct ath12k_peer *ath12k_peer_find_by_id(struct ath12k_base *ab,
lockdep_assert_held(&ab->base_lock);
+ if (peer_id & ATH12K_PEER_ML_ID_VALID)
+ return ath12k_peer_find_by_ml_id(ab, peer_id);
+
list_for_each_entry(peer, &ab->peers, list)
if (peer_id == peer->peer_id)
return peer;
@@ -231,8 +264,9 @@ int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id,
return 0;
}
-int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr)
+static int ath12k_peer_delete_send(struct ath12k *ar, u32 vdev_id, const u8 *addr)
{
+ struct ath12k_base *ab = ar->ab;
int ret;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -241,12 +275,25 @@ int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr)
ret = ath12k_wmi_send_peer_delete_cmd(ar, addr, vdev_id);
if (ret) {
- ath12k_warn(ar->ab,
+ ath12k_warn(ab,
"failed to delete peer vdev_id %d addr %pM ret %d\n",
vdev_id, addr, ret);
return ret;
}
+ return 0;
+}
+
+int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr)
+{
+ int ret;
+
+ lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
+
+ ret = ath12k_peer_delete_send(ar, vdev_id, addr);
+ if (ret)
+ return ret;
+
ret = ath12k_wait_for_peer_delete_done(ar, vdev_id, addr);
if (ret)
return ret;
@@ -266,7 +313,11 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
struct ath12k_wmi_peer_create_arg *arg)
{
struct ieee80211_vif *vif = ath12k_ahvif_to_vif(arvif->ahvif);
+ struct ath12k_link_sta *arsta;
+ u8 link_id = arvif->link_id;
struct ath12k_peer *peer;
+ struct ath12k_sta *ahsta;
+ u16 ml_peer_id;
int ret;
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
@@ -332,6 +383,27 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
arvif->ast_idx = peer->hw_peer_id;
}
+ if (sta) {
+ ahsta = ath12k_sta_to_ahsta(sta);
+ arsta = wiphy_dereference(ath12k_ar_to_hw(ar)->wiphy,
+ ahsta->link[link_id]);
+
+ /* Fill ML info into created peer */
+ if (sta->mlo) {
+ ml_peer_id = ahsta->ml_peer_id;
+ peer->ml_id = ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+ ether_addr_copy(peer->ml_addr, sta->addr);
+
+ /* the assoc link is considered primary for now */
+ peer->primary_link = arsta->is_assoc_link;
+ peer->mlo = true;
+ } else {
+ peer->ml_id = ATH12K_MLO_PEER_ID_INVALID;
+ peer->primary_link = true;
+ peer->mlo = false;
+ }
+ }
+
peer->sec_type = HAL_ENCRYPT_TYPE_OPEN;
peer->sec_type_grp = HAL_ENCRYPT_TYPE_OPEN;
@@ -341,3 +413,150 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
return 0;
}
+
+static u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah)
+{
+ u16 ml_peer_id;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ for (ml_peer_id = 0; ml_peer_id < ATH12K_MAX_MLO_PEERS; ml_peer_id++) {
+ if (test_bit(ml_peer_id, ah->free_ml_peer_id_map))
+ continue;
+
+ set_bit(ml_peer_id, ah->free_ml_peer_id_map);
+ break;
+ }
+
+ if (ml_peer_id == ATH12K_MAX_MLO_PEERS)
+ ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
+
+ return ml_peer_id;
+}
+
+int ath12k_peer_ml_create(struct ath12k_hw *ah, struct ieee80211_sta *sta)
+{
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_ml_peer *ml_peer;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ if (!sta->mlo)
+ return -EINVAL;
+
+ ml_peer = ath12k_peer_ml_find(ah, sta->addr);
+ if (ml_peer) {
+ ath12k_hw_warn(ah, "ML peer %d exists already, unable to add new entry for %pM",
+ ml_peer->id, sta->addr);
+ return -EEXIST;
+ }
+
+ ml_peer = kzalloc(sizeof(*ml_peer), GFP_ATOMIC);
+ if (!ml_peer)
+ return -ENOMEM;
+
+ ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah);
+
+ if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
+ ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM",
+ sta->addr);
+ kfree(ml_peer);
+ return -ENOMEM;
+ }
+
+ ether_addr_copy(ml_peer->addr, sta->addr);
+ ml_peer->id = ahsta->ml_peer_id;
+ list_add(&ml_peer->list, &ah->ml_peers);
+
+ return 0;
+}
+
+int ath12k_peer_ml_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta)
+{
+ struct ath12k_sta *ahsta = ath12k_sta_to_ahsta(sta);
+ struct ath12k_ml_peer *ml_peer;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ if (!sta->mlo)
+ return -EINVAL;
+
+ clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
+ ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
+
+ ml_peer = ath12k_peer_ml_find(ah, sta->addr);
+ if (!ml_peer) {
+ ath12k_hw_warn(ah, "ML peer for %pM not found", sta->addr);
+ return -EINVAL;
+ }
+
+ list_del(&ml_peer->list);
+ kfree(ml_peer);
+
+ return 0;
+}
+
+int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta)
+{
+ struct ieee80211_sta *sta = ath12k_ahsta_to_sta(ahsta);
+ struct ath12k_hw *ah = ahvif->ah;
+ struct ath12k_link_vif *arvif;
+ struct ath12k_link_sta *arsta;
+ unsigned long links;
+ struct ath12k *ar;
+ int ret, err_ret = 0;
+ u8 link_id;
+
+ lockdep_assert_wiphy(ah->hw->wiphy);
+
+ if (!sta->mlo)
+ return -EINVAL;
+
+ /* FW expects delete of all link peers at once before waiting for reception
+ * of peer unmap or delete responses
+ */
+ links = ahsta->links_map;
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
+ arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
+ if (!arvif || !arsta)
+ continue;
+
+ ar = arvif->ar;
+ if (!ar)
+ continue;
+
+ ath12k_dp_peer_cleanup(ar, arvif->vdev_id, arsta->addr);
+
+ ret = ath12k_peer_delete_send(ar, arvif->vdev_id, arsta->addr);
+ if (ret) {
+ ath12k_warn(ar->ab,
+ "failed to delete peer vdev_id %d addr %pM ret %d\n",
+ arvif->vdev_id, arsta->addr, ret);
+ err_ret = ret;
+ continue;
+ }
+ }
+
+ /* Ensure all link peers are deleted and unmapped */
+ links = ahsta->links_map;
+ for_each_set_bit(link_id, &links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ arvif = wiphy_dereference(ah->hw->wiphy, ahvif->link[link_id]);
+ arsta = wiphy_dereference(ah->hw->wiphy, ahsta->link[link_id]);
+ if (!arvif || !arsta)
+ continue;
+
+ ar = arvif->ar;
+ if (!ar)
+ continue;
+
+ ret = ath12k_wait_for_peer_delete_done(ar, arvif->vdev_id, arsta->addr);
+ if (ret) {
+ err_ret = ret;
+ continue;
+ }
+ ar->num_peers--;
+ }
+
+ return err_ret;
+}
diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h
index b955f0cdf598..7e6231cb2b52 100644
--- a/drivers/net/wireless/ath/ath12k/peer.h
+++ b/drivers/net/wireless/ath/ath12k/peer.h
@@ -19,6 +19,8 @@ struct ppdu_user_delayba {
u32 resp_rate_flags;
};
+#define ATH12K_PEER_ML_ID_VALID BIT(13)
+
struct ath12k_peer {
struct list_head list;
struct ieee80211_sta *sta;
@@ -44,9 +46,25 @@ struct ath12k_peer {
struct ppdu_user_delayba ppdu_stats_delayba;
bool delayba_flag;
bool is_authorized;
-
+ bool mlo;
/* protected by ab->data_lock */
bool dp_setup_done;
+
+ u16 ml_id;
+
+ /* any other ML info common for all partners can be added
+ * here and would be same for all partner peers.
+ */
+ u8 ml_addr[ETH_ALEN];
+
+ /* To ensure only certain work related to dp is done once */
+ bool primary_link;
+};
+
+struct ath12k_ml_peer {
+ struct list_head list;
+ u8 addr[ETH_ALEN];
+ u16 id;
};
void ath12k_peer_unmap_event(struct ath12k_base *ab, u16 peer_id);
@@ -66,5 +84,8 @@ int ath12k_wait_for_peer_delete_done(struct ath12k *ar, u32 vdev_id,
const u8 *addr);
bool ath12k_peer_exist_by_vdev_id(struct ath12k_base *ab, int vdev_id);
struct ath12k_peer *ath12k_peer_find_by_ast(struct ath12k_base *ab, int ast_hash);
+int ath12k_peer_ml_create(struct ath12k_hw *ah, struct ieee80211_sta *sta);
+int ath12k_peer_ml_delete(struct ath12k_hw *ah, struct ieee80211_sta *sta);
+int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta);
#endif /* _PEER_H_ */
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index b93ce9f87f61..ba3cd2342465 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -2023,14 +2023,14 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
u8 hw_link_id = 0;
int i;
- if (!(ab->mlo_capable_flags & ATH12K_INTRA_DEVICE_MLO_SUPPORT)) {
+ if (!ab->ag->mlo_capable) {
ath12k_dbg(ab, ATH12K_DBG_QMI,
- "intra device MLO is disabled hence skip QMI MLO cap");
+ "MLO is disabled hence skip QMI MLO cap");
return;
}
if (!ab->qmi.num_radios || ab->qmi.num_radios == U8_MAX) {
- ab->mlo_capable_flags = 0;
+ ab->single_chip_mlo_supp = false;
ath12k_dbg(ab, ATH12K_DBG_QMI,
"skip QMI MLO cap due to invalid num_radio %d\n",
@@ -2066,7 +2066,9 @@ static void ath12k_host_cap_parse_mlo(struct ath12k_base *ab,
req->mlo_chip_info_valid = 1;
}
-static int ath12k_qmi_host_cap_send(struct ath12k_base *ab)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+int ath12k_qmi_host_cap_send(struct ath12k_base *ab)
{
struct qmi_wlanfw_host_cap_req_msg_v01 req = {};
struct qmi_wlanfw_host_cap_resp_msg_v01 resp = {};
@@ -2174,12 +2176,9 @@ static void ath12k_qmi_phy_cap_send(struct ath12k_base *ab)
goto out;
}
- if (resp.single_chip_mlo_support_valid) {
- if (resp.single_chip_mlo_support)
- ab->mlo_capable_flags |= ATH12K_INTRA_DEVICE_MLO_SUPPORT;
- else
- ab->mlo_capable_flags &= ~ATH12K_INTRA_DEVICE_MLO_SUPPORT;
- }
+ if (resp.single_chip_mlo_support_valid &&
+ resp.single_chip_mlo_support)
+ ab->single_chip_mlo_supp = true;
if (!resp.num_phy_valid) {
ret = -ENODATA;
@@ -2275,7 +2274,9 @@ resp_out:
return ret;
}
-static int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+int ath12k_qmi_respond_fw_mem_request(struct ath12k_base *ab)
{
struct qmi_wlanfw_respond_mem_req_msg_v01 *req;
struct qmi_wlanfw_respond_mem_resp_msg_v01 resp = {};
@@ -2433,7 +2434,9 @@ this_chunk_done:
return 0;
}
-static int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
{
struct qmi_wlanfw_cap_req_msg_v01 req = {};
struct qmi_wlanfw_cap_resp_msg_v01 resp = {};
@@ -2619,8 +2622,10 @@ out:
return ret;
}
-static int ath12k_qmi_load_bdf_qmi(struct ath12k_base *ab,
- enum ath12k_qmi_bdf_type type)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+int ath12k_qmi_load_bdf_qmi(struct ath12k_base *ab,
+ enum ath12k_qmi_bdf_type type)
{
struct device *dev = ab->dev;
char filename[ATH12K_QMI_MAX_BDF_FILE_NAME_SIZE];
@@ -2791,7 +2796,9 @@ out:
return ret;
}
-static int ath12k_qmi_wlanfw_m3_info_send(struct ath12k_base *ab)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+int ath12k_qmi_wlanfw_m3_info_send(struct ath12k_base *ab)
{
struct m3_mem_region *m3_mem = &ab->qmi.m3_mem;
struct qmi_wlanfw_m3_info_req_msg_v01 req = {};
@@ -3023,6 +3030,8 @@ void ath12k_qmi_firmware_stop(struct ath12k_base *ab)
{
int ret;
+ clear_bit(ATH12K_FLAG_QMI_FW_READY_COMPLETE, &ab->dev_flags);
+
ret = ath12k_qmi_wlanfw_mode_send(ab, ATH12K_FIRMWARE_MODE_OFF);
if (ret < 0) {
ath12k_warn(ab, "qmi failed to send wlan mode off\n");
@@ -3079,9 +3088,69 @@ ath12k_qmi_driver_event_post(struct ath12k_qmi *qmi,
return 0;
}
-static int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi)
+void ath12k_qmi_trigger_host_cap(struct ath12k_base *ab)
{
- struct ath12k_base *ab = qmi->ab;
+ struct ath12k_qmi *qmi = &ab->qmi;
+
+ spin_lock(&qmi->event_lock);
+
+ if (ath12k_qmi_get_event_block(qmi))
+ ath12k_qmi_set_event_block(qmi, false);
+
+ spin_unlock(&qmi->event_lock);
+
+ ath12k_dbg(ab, ATH12K_DBG_QMI, "trigger host cap for device id %d\n",
+ ab->device_id);
+
+ ath12k_qmi_driver_event_post(qmi, ATH12K_QMI_EVENT_HOST_CAP, NULL);
+}
+
+static bool ath12k_qmi_hw_group_host_cap_ready(struct ath12k_hw_group *ag)
+{
+ struct ath12k_base *ab;
+ int i;
+
+ for (i = 0; i < ag->num_devices; i++) {
+ ab = ag->ab[i];
+
+ if (!(ab && ab->qmi.num_radios != U8_MAX))
+ return false;
+ }
+
+ return true;
+}
+
+static struct ath12k_base *ath12k_qmi_hw_group_find_blocked(struct ath12k_hw_group *ag)
+{
+ struct ath12k_base *ab;
+ int i;
+
+ lockdep_assert_held(&ag->mutex);
+
+ for (i = 0; i < ag->num_devices; i++) {
+ ab = ag->ab[i];
+ if (!ab)
+ continue;
+
+ spin_lock(&ab->qmi.event_lock);
+
+ if (ath12k_qmi_get_event_block(&ab->qmi)) {
+ spin_unlock(&ab->qmi.event_lock);
+ return ab;
+ }
+
+ spin_unlock(&ab->qmi.event_lock);
+ }
+
+ return NULL;
+}
+
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi)
+{
+ struct ath12k_base *ab = qmi->ab, *block_ab;
+ struct ath12k_hw_group *ag = ab->ag;
int ret;
ath12k_qmi_phy_cap_send(ab);
@@ -3092,16 +3161,30 @@ static int ath12k_qmi_event_server_arrive(struct ath12k_qmi *qmi)
return ret;
}
- ret = ath12k_qmi_host_cap_send(ab);
- if (ret < 0) {
- ath12k_warn(ab, "qmi failed to send host cap QMI:%d\n", ret);
- return ret;
+ spin_lock(&qmi->event_lock);
+
+ ath12k_qmi_set_event_block(qmi, true);
+
+ spin_unlock(&qmi->event_lock);
+
+ mutex_lock(&ag->mutex);
+
+ if (ath12k_qmi_hw_group_host_cap_ready(ag)) {
+ ath12k_core_hw_group_set_mlo_capable(ag);
+
+ block_ab = ath12k_qmi_hw_group_find_blocked(ag);
+ if (block_ab)
+ ath12k_qmi_trigger_host_cap(block_ab);
}
+ mutex_unlock(&ag->mutex);
+
return ret;
}
-static int ath12k_qmi_event_mem_request(struct ath12k_qmi *qmi)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+int ath12k_qmi_event_mem_request(struct ath12k_qmi *qmi)
{
struct ath12k_base *ab = qmi->ab;
int ret;
@@ -3115,7 +3198,9 @@ static int ath12k_qmi_event_mem_request(struct ath12k_qmi *qmi)
return ret;
}
-static int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi)
+/* clang stack usage explodes if this is inlined */
+static noinline_for_stack
+int ath12k_qmi_event_load_bdf(struct ath12k_qmi *qmi)
{
struct ath12k_base *ab = qmi->ab;
int ret;
@@ -3280,6 +3365,21 @@ static const struct qmi_ops ath12k_qmi_ops = {
.del_server = ath12k_qmi_ops_del_server,
};
+static int ath12k_qmi_event_host_cap(struct ath12k_qmi *qmi)
+{
+ struct ath12k_base *ab = qmi->ab;
+ int ret;
+
+ ret = ath12k_qmi_host_cap_send(ab);
+ if (ret < 0) {
+ ath12k_warn(ab, "failed to send qmi host cap for device id %d: %d\n",
+ ab->device_id, ret);
+ return ret;
+ }
+
+ return ret;
+}
+
static void ath12k_qmi_driver_event_work(struct work_struct *work)
{
struct ath12k_qmi *qmi = container_of(work, struct ath12k_qmi,
@@ -3306,7 +3406,6 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work)
break;
case ATH12K_QMI_EVENT_SERVER_EXIT:
set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags);
- set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags);
break;
case ATH12K_QMI_EVENT_REQUEST_MEM:
ret = ath12k_qmi_event_mem_request(qmi);
@@ -3320,20 +3419,28 @@ static void ath12k_qmi_driver_event_work(struct work_struct *work)
break;
case ATH12K_QMI_EVENT_FW_READY:
clear_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags);
- if (test_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags)) {
+ if (test_bit(ATH12K_FLAG_QMI_FW_READY_COMPLETE, &ab->dev_flags)) {
if (ab->is_reset)
ath12k_hal_dump_srng_stats(ab);
+
+ set_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags);
queue_work(ab->workqueue, &ab->restart_work);
break;
}
clear_bit(ATH12K_FLAG_CRASH_FLUSH,
&ab->dev_flags);
- clear_bit(ATH12K_FLAG_RECOVERY, &ab->dev_flags);
- ath12k_core_qmi_firmware_ready(ab);
- set_bit(ATH12K_FLAG_REGISTERED, &ab->dev_flags);
+ ret = ath12k_core_qmi_firmware_ready(ab);
+ if (!ret)
+ set_bit(ATH12K_FLAG_QMI_FW_READY_COMPLETE,
+ &ab->dev_flags);
break;
+ case ATH12K_QMI_EVENT_HOST_CAP:
+ ret = ath12k_qmi_event_host_cap(qmi);
+ if (ret < 0)
+ set_bit(ATH12K_FLAG_QMI_FAIL, &ab->dev_flags);
+ break;
default:
ath12k_warn(ab, "invalid event type: %d", event->type);
break;
@@ -3386,11 +3493,15 @@ int ath12k_qmi_init_service(struct ath12k_base *ab)
void ath12k_qmi_deinit_service(struct ath12k_base *ab)
{
+ if (!ab->qmi.ab)
+ return;
+
qmi_handle_release(&ab->qmi.handle);
cancel_work_sync(&ab->qmi.event_work);
destroy_workqueue(ab->qmi.event_wq);
ath12k_qmi_m3_free(ab);
ath12k_qmi_free_target_mem_chunk(ab);
+ ab->qmi.ab = NULL;
}
void ath12k_qmi_free_resource(struct ath12k_base *ab)
diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h
index 0dfcbd8cb59b..98f6009ab21e 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.h
+++ b/drivers/net/wireless/ath/ath12k/qmi.h
@@ -68,6 +68,7 @@ enum ath12k_qmi_event_type {
ATH12K_QMI_EVENT_FORCE_FW_ASSERT,
ATH12K_QMI_EVENT_POWER_UP,
ATH12K_QMI_EVENT_POWER_DOWN,
+ ATH12K_QMI_EVENT_HOST_CAP,
ATH12K_QMI_EVENT_MAX,
};
@@ -142,6 +143,10 @@ struct ath12k_qmi {
u32 target_mem_mode;
bool target_mem_delayed;
u8 cal_done;
+
+ /* protected with struct ath12k_qmi::event_lock */
+ bool block_event;
+
u8 num_radios;
struct target_info target;
struct m3_mem_region m3_mem;
@@ -594,11 +599,26 @@ struct qmi_wlanfw_wlan_ini_resp_msg_v01 {
struct qmi_response_type_v01 resp;
};
+static inline void ath12k_qmi_set_event_block(struct ath12k_qmi *qmi, bool block)
+{
+ lockdep_assert_held(&qmi->event_lock);
+
+ qmi->block_event = block;
+}
+
+static inline bool ath12k_qmi_get_event_block(struct ath12k_qmi *qmi)
+{
+ lockdep_assert_held(&qmi->event_lock);
+
+ return qmi->block_event;
+}
+
int ath12k_qmi_firmware_start(struct ath12k_base *ab,
u32 mode);
void ath12k_qmi_firmware_stop(struct ath12k_base *ab);
void ath12k_qmi_deinit_service(struct ath12k_base *ab);
int ath12k_qmi_init_service(struct ath12k_base *ab);
void ath12k_qmi_free_resource(struct ath12k_base *ab);
+void ath12k_qmi_trigger_host_cap(struct ath12k_base *ab);
#endif
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index dced2aa9ba1a..402ae477da61 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -821,6 +821,8 @@ int ath12k_wmi_vdev_create(struct ath12k *ar, u8 *macaddr,
struct wmi_vdev_create_cmd *cmd;
struct sk_buff *skb;
struct ath12k_wmi_vdev_txrx_streams_params *txrx_streams;
+ bool is_ml_vdev = is_valid_ether_addr(args->mld_addr);
+ struct wmi_vdev_create_mlo_params *ml_params;
struct wmi_tlv *tlv;
int ret, len;
void *ptr;
@@ -830,7 +832,8 @@ int ath12k_wmi_vdev_create(struct ath12k *ar, u8 *macaddr,
* both the bands.
*/
len = sizeof(*cmd) + TLV_HDR_SIZE +
- (WMI_NUM_SUPPORTED_BAND_MAX * sizeof(*txrx_streams));
+ (WMI_NUM_SUPPORTED_BAND_MAX * sizeof(*txrx_streams)) +
+ (is_ml_vdev ? TLV_HDR_SIZE + sizeof(*ml_params) : 0);
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
@@ -879,6 +882,21 @@ int ath12k_wmi_vdev_create(struct ath12k *ar, u8 *macaddr,
txrx_streams->supported_rx_streams =
cpu_to_le32(args->chains[NL80211_BAND_5GHZ].rx);
+ ptr += WMI_NUM_SUPPORTED_BAND_MAX * sizeof(*txrx_streams);
+
+ if (is_ml_vdev) {
+ tlv = ptr;
+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,
+ sizeof(*ml_params));
+ ptr += TLV_HDR_SIZE;
+ ml_params = ptr;
+
+ ml_params->tlv_header =
+ ath12k_wmi_tlv_cmd_hdr(WMI_TAG_MLO_VDEV_CREATE_PARAMS,
+ sizeof(*ml_params));
+ ether_addr_copy(ml_params->mld_macaddr.addr, args->mld_addr);
+ }
+
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
"WMI vdev create: id %d type %d subtype %d macaddr %pM pdevid %d\n",
args->if_id, args->type, args->subtype,
@@ -1020,19 +1038,27 @@ static void ath12k_wmi_put_wmi_channel(struct ath12k_wmi_channel_params *chan,
int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg,
bool restart)
{
+ struct wmi_vdev_start_mlo_params *ml_params;
+ struct wmi_partner_link_info *partner_info;
struct ath12k_wmi_pdev *wmi = ar->wmi;
struct wmi_vdev_start_request_cmd *cmd;
struct sk_buff *skb;
struct ath12k_wmi_channel_params *chan;
struct wmi_tlv *tlv;
void *ptr;
- int ret, len;
+ int ret, len, i, ml_arg_size = 0;
if (WARN_ON(arg->ssid_len > sizeof(cmd->ssid.ssid)))
return -EINVAL;
len = sizeof(*cmd) + sizeof(*chan) + TLV_HDR_SIZE;
+ if (!restart && arg->ml.enabled) {
+ ml_arg_size = TLV_HDR_SIZE + sizeof(*ml_params) +
+ TLV_HDR_SIZE + (arg->ml.num_partner_links *
+ sizeof(*partner_info));
+ len += ml_arg_size;
+ }
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -1085,6 +1111,61 @@ int ath12k_wmi_vdev_start(struct ath12k *ar, struct wmi_vdev_start_req_arg *arg,
ptr += sizeof(*tlv);
+ if (ml_arg_size) {
+ tlv = ptr;
+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,
+ sizeof(*ml_params));
+ ptr += TLV_HDR_SIZE;
+
+ ml_params = ptr;
+
+ ml_params->tlv_header =
+ ath12k_wmi_tlv_cmd_hdr(WMI_TAG_MLO_VDEV_START_PARAMS,
+ sizeof(*ml_params));
+
+ ml_params->flags = le32_encode_bits(arg->ml.enabled,
+ ATH12K_WMI_FLAG_MLO_ENABLED) |
+ le32_encode_bits(arg->ml.assoc_link,
+ ATH12K_WMI_FLAG_MLO_ASSOC_LINK) |
+ le32_encode_bits(arg->ml.mcast_link,
+ ATH12K_WMI_FLAG_MLO_MCAST_VDEV) |
+ le32_encode_bits(arg->ml.link_add,
+ ATH12K_WMI_FLAG_MLO_LINK_ADD);
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "vdev %d start ml flags 0x%x\n",
+ arg->vdev_id, ml_params->flags);
+
+ ptr += sizeof(*ml_params);
+
+ tlv = ptr;
+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,
+ arg->ml.num_partner_links *
+ sizeof(*partner_info));
+ ptr += TLV_HDR_SIZE;
+
+ partner_info = ptr;
+
+ for (i = 0; i < arg->ml.num_partner_links; i++) {
+ partner_info->tlv_header =
+ ath12k_wmi_tlv_cmd_hdr(WMI_TAG_MLO_PARTNER_LINK_PARAMS,
+ sizeof(*partner_info));
+ partner_info->vdev_id =
+ cpu_to_le32(arg->ml.partner_info[i].vdev_id);
+ partner_info->hw_link_id =
+ cpu_to_le32(arg->ml.partner_info[i].hw_link_id);
+ ether_addr_copy(partner_info->vdev_addr.addr,
+ arg->ml.partner_info[i].addr);
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "partner vdev %d hw_link_id %d macaddr%pM\n",
+ partner_info->vdev_id, partner_info->hw_link_id,
+ partner_info->vdev_addr.addr);
+
+ partner_info++;
+ }
+
+ ptr = partner_info;
+ }
+
ath12k_dbg(ar->ab, ATH12K_DBG_WMI, "vdev %s id 0x%x freq 0x%x mode 0x%x\n",
restart ? "restart" : "start", arg->vdev_id,
arg->freq, arg->mode);
@@ -1149,9 +1230,14 @@ int ath12k_wmi_send_peer_create_cmd(struct ath12k *ar,
struct ath12k_wmi_pdev *wmi = ar->wmi;
struct wmi_peer_create_cmd *cmd;
struct sk_buff *skb;
- int ret;
+ int ret, len;
+ struct wmi_peer_create_mlo_params *ml_param;
+ void *ptr;
+ struct wmi_tlv *tlv;
- skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd));
+ len = sizeof(*cmd) + TLV_HDR_SIZE + sizeof(*ml_param);
+
+ skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
return -ENOMEM;
@@ -1163,9 +1249,23 @@ int ath12k_wmi_send_peer_create_cmd(struct ath12k *ar,
cmd->peer_type = cpu_to_le32(arg->peer_type);
cmd->vdev_id = cpu_to_le32(arg->vdev_id);
+ ptr = skb->data + sizeof(*cmd);
+ tlv = ptr;
+ tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT,
+ sizeof(*ml_param));
+ ptr += TLV_HDR_SIZE;
+ ml_param = ptr;
+ ml_param->tlv_header =
+ ath12k_wmi_tlv_cmd_hdr(WMI_TAG_MLO_PEER_CREATE_PARAMS,
+ sizeof(*ml_param));
+ if (arg->ml_enabled)
+ ml_param->flags = cpu_to_le32(ATH12K_WMI_FLAG_MLO_ENABLED);
+
+ ptr += sizeof(*ml_param);
+
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
- "WMI peer create vdev_id %d peer_addr %pM\n",
- arg->vdev_id, arg->peer_addr);
+ "WMI peer create vdev_id %d peer_addr %pM ml_flags 0x%x\n",
+ arg->vdev_id, arg->peer_addr, ml_param->flags);
ret = ath12k_wmi_cmd_send(wmi, skb, WMI_PEER_CREATE_CMDID);
if (ret) {
@@ -2001,12 +2101,15 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
struct ath12k_wmi_vht_rate_set_params *mcs;
struct ath12k_wmi_he_rate_set_params *he_mcs;
struct ath12k_wmi_eht_rate_set_params *eht_mcs;
+ struct wmi_peer_assoc_mlo_params *ml_params;
+ struct wmi_peer_assoc_mlo_partner_info_params *partner_info;
struct sk_buff *skb;
struct wmi_tlv *tlv;
void *ptr;
u32 peer_legacy_rates_align;
u32 peer_ht_rates_align;
int i, ret, len;
+ __le32 v;
peer_legacy_rates_align = roundup(arg->peer_legacy_rates.num_rates,
sizeof(u32));
@@ -2018,8 +2121,13 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
TLV_HDR_SIZE + (peer_ht_rates_align * sizeof(u8)) +
sizeof(*mcs) + TLV_HDR_SIZE +
(sizeof(*he_mcs) * arg->peer_he_mcs_count) +
- TLV_HDR_SIZE + (sizeof(*eht_mcs) * arg->peer_eht_mcs_count) +
- TLV_HDR_SIZE + TLV_HDR_SIZE;
+ TLV_HDR_SIZE + (sizeof(*eht_mcs) * arg->peer_eht_mcs_count);
+
+ if (arg->ml.enabled)
+ len += TLV_HDR_SIZE + sizeof(*ml_params) +
+ TLV_HDR_SIZE + (arg->ml.num_partner_links * sizeof(*partner_info));
+ else
+ len += (2 * TLV_HDR_SIZE);
skb = ath12k_wmi_alloc_skb(wmi->wmi_ab, len);
if (!skb)
@@ -2143,12 +2251,38 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
ptr += sizeof(*he_mcs);
}
- /* MLO header tag with 0 length */
- len = 0;
tlv = ptr;
+ len = arg->ml.enabled ? sizeof(*ml_params) : 0;
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);
ptr += TLV_HDR_SIZE;
+ if (!len)
+ goto skip_ml_params;
+
+ ml_params = ptr;
+ ml_params->tlv_header = ath12k_wmi_tlv_cmd_hdr(WMI_TAG_MLO_PEER_ASSOC_PARAMS,
+ len);
+ ml_params->flags = cpu_to_le32(ATH12K_WMI_FLAG_MLO_ENABLED);
+
+ if (arg->ml.assoc_link)
+ ml_params->flags |= cpu_to_le32(ATH12K_WMI_FLAG_MLO_ASSOC_LINK);
+
+ if (arg->ml.primary_umac)
+ ml_params->flags |= cpu_to_le32(ATH12K_WMI_FLAG_MLO_PRIMARY_UMAC);
+
+ if (arg->ml.logical_link_idx_valid)
+ ml_params->flags |=
+ cpu_to_le32(ATH12K_WMI_FLAG_MLO_LOGICAL_LINK_IDX_VALID);
+
+ if (arg->ml.peer_id_valid)
+ ml_params->flags |= cpu_to_le32(ATH12K_WMI_FLAG_MLO_PEER_ID_VALID);
+ ether_addr_copy(ml_params->mld_addr.addr, arg->ml.mld_addr);
+ ml_params->logical_link_idx = cpu_to_le32(arg->ml.logical_link_idx);
+ ml_params->ml_peer_id = cpu_to_le32(arg->ml.ml_peer_id);
+ ml_params->ieee_link_id = cpu_to_le32(arg->ml.ieee_link_id);
+ ptr += sizeof(*ml_params);
+
+skip_ml_params:
/* Loop through the EHT rate set */
len = arg->peer_eht_mcs_count * sizeof(*eht_mcs);
tlv = ptr;
@@ -2165,12 +2299,45 @@ int ath12k_wmi_send_peer_assoc_cmd(struct ath12k *ar,
ptr += sizeof(*eht_mcs);
}
- /* ML partner links tag with 0 length */
- len = 0;
tlv = ptr;
+ len = arg->ml.enabled ? arg->ml.num_partner_links * sizeof(*partner_info) : 0;
+ /* fill ML Partner links */
tlv->header = ath12k_wmi_tlv_hdr(WMI_TAG_ARRAY_STRUCT, len);
ptr += TLV_HDR_SIZE;
+ if (len == 0)
+ goto send;
+
+ for (i = 0; i < arg->ml.num_partner_links; i++) {
+ u32 cmd = WMI_TAG_MLO_PARTNER_LINK_PARAMS_PEER_ASSOC;
+
+ partner_info = ptr;
+ partner_info->tlv_header = ath12k_wmi_tlv_cmd_hdr(cmd,
+ sizeof(*partner_info));
+ partner_info->vdev_id = cpu_to_le32(arg->ml.partner_info[i].vdev_id);
+ partner_info->hw_link_id =
+ cpu_to_le32(arg->ml.partner_info[i].hw_link_id);
+ partner_info->flags = cpu_to_le32(ATH12K_WMI_FLAG_MLO_ENABLED);
+
+ if (arg->ml.partner_info[i].assoc_link)
+ partner_info->flags |=
+ cpu_to_le32(ATH12K_WMI_FLAG_MLO_ASSOC_LINK);
+
+ if (arg->ml.partner_info[i].primary_umac)
+ partner_info->flags |=
+ cpu_to_le32(ATH12K_WMI_FLAG_MLO_PRIMARY_UMAC);
+
+ if (arg->ml.partner_info[i].logical_link_idx_valid) {
+ v = cpu_to_le32(ATH12K_WMI_FLAG_MLO_LINK_ID_VALID);
+ partner_info->flags |= v;
+ }
+
+ partner_info->logical_link_idx =
+ cpu_to_le32(arg->ml.partner_info[i].logical_link_idx);
+ ptr += sizeof(*partner_info);
+ }
+
+send:
ath12k_dbg(ar->ab, ATH12K_DBG_WMI,
"wmi peer assoc vdev id %d assoc id %d peer mac %pM peer_flags %x rate_caps %x peer_caps %x listen_intval %d ht_caps %x max_mpdu %d nss %d phymode %d peer_mpdu_density %d vht_caps %x he cap_info %x he ops %x he cap_info_ext %x he phy %x %x %x peer_bw_rxnss_override %x peer_flags_ext %x eht mac_cap %x %x eht phy_cap %x %x %x\n",
cmd->vdev_id, cmd->peer_associd, arg->peer_mac,
@@ -6687,6 +6854,7 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,
const u32 *vdev_ids)
{
int i;
+ struct ieee80211_bss_conf *conf;
struct ath12k_link_vif *arvif;
struct ath12k_vif *ahvif;
@@ -6705,7 +6873,20 @@ ath12k_wmi_process_csa_switch_count_event(struct ath12k_base *ab,
}
ahvif = arvif->ahvif;
- if (arvif->is_up && ahvif->vif->bss_conf.csa_active)
+ if (arvif->link_id > IEEE80211_MLD_MAX_NUM_LINKS) {
+ ath12k_warn(ab, "Invalid CSA switch count even link id: %d\n",
+ arvif->link_id);
+ continue;
+ }
+
+ conf = rcu_dereference(ahvif->vif->link_conf[arvif->link_id]);
+ if (!conf) {
+ ath12k_warn(ab, "unable to access bss link conf in process csa for vif %pM link %u\n",
+ ahvif->vif->addr, arvif->link_id);
+ continue;
+ }
+
+ if (arvif->is_up && conf->csa_active)
ieee80211_csa_finish(ahvif->vif, 0);
}
rcu_read_unlock();
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 6f55dbdf629d..05aa9754118a 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -1929,6 +1929,19 @@ enum wmi_tlv_tag {
WMI_TAG_REGULATORY_RULE_EXT_STRUCT = 0x3A9,
WMI_TAG_REG_CHAN_LIST_CC_EXT_EVENT,
WMI_TAG_EHT_RATE_SET = 0x3C4,
+ WMI_TAG_DCS_AWGN_INT_TYPE = 0x3C5,
+ WMI_TAG_MLO_TX_SEND_PARAMS,
+ WMI_TAG_MLO_PARTNER_LINK_PARAMS,
+ WMI_TAG_MLO_PARTNER_LINK_PARAMS_PEER_ASSOC,
+ WMI_TAG_MLO_SETUP_CMD = 0x3C9,
+ WMI_TAG_MLO_SETUP_COMPLETE_EVENT,
+ WMI_TAG_MLO_READY_CMD,
+ WMI_TAG_MLO_TEARDOWN_CMD,
+ WMI_TAG_MLO_TEARDOWN_COMPLETE,
+ WMI_TAG_MLO_PEER_ASSOC_PARAMS = 0x3D0,
+ WMI_TAG_MLO_PEER_CREATE_PARAMS = 0x3D5,
+ WMI_TAG_MLO_VDEV_START_PARAMS = 0x3D6,
+ WMI_TAG_MLO_VDEV_CREATE_PARAMS = 0x3D7,
WMI_TAG_PDEV_SET_BIOS_SAR_TABLE_CMD = 0x3D8,
WMI_TAG_PDEV_SET_BIOS_GEO_TABLE_CMD = 0x3D9,
WMI_TAG_PDEV_SET_BIOS_INTERFACE_CMD = 0x3FB,
@@ -2740,6 +2753,7 @@ struct ath12k_wmi_vdev_create_arg {
u8 if_stats_id;
u32 mbssid_flags;
u32 mbssid_tx_vdev_id;
+ u8 mld_addr[ETH_ALEN];
};
#define ATH12K_MAX_VDEV_STATS_ID 0x30
@@ -2766,6 +2780,33 @@ struct ath12k_wmi_vdev_txrx_streams_params {
__le32 supported_rx_streams;
} __packed;
+struct wmi_vdev_create_mlo_params {
+ __le32 tlv_header;
+ struct ath12k_wmi_mac_addr_params mld_macaddr;
+} __packed;
+
+#define ATH12K_WMI_FLAG_MLO_ENABLED BIT(0)
+#define ATH12K_WMI_FLAG_MLO_ASSOC_LINK BIT(1)
+#define ATH12K_WMI_FLAG_MLO_PRIMARY_UMAC BIT(2)
+#define ATH12K_WMI_FLAG_MLO_LOGICAL_LINK_IDX_VALID BIT(3)
+#define ATH12K_WMI_FLAG_MLO_PEER_ID_VALID BIT(4)
+#define ATH12K_WMI_FLAG_MLO_MCAST_VDEV BIT(5)
+#define ATH12K_WMI_FLAG_MLO_EMLSR_SUPPORT BIT(6)
+#define ATH12K_WMI_FLAG_MLO_FORCED_INACTIVE BIT(7)
+#define ATH12K_WMI_FLAG_MLO_LINK_ADD BIT(8)
+
+struct wmi_vdev_start_mlo_params {
+ __le32 tlv_header;
+ __le32 flags;
+} __packed;
+
+struct wmi_partner_link_info {
+ __le32 tlv_header;
+ __le32 vdev_id;
+ __le32 hw_link_id;
+ struct ath12k_wmi_mac_addr_params vdev_addr;
+} __packed;
+
struct wmi_vdev_delete_cmd {
__le32 tlv_header;
__le32 vdev_id;
@@ -2909,6 +2950,27 @@ enum wmi_phy_mode {
MODE_MAX = 33,
};
+#define ATH12K_WMI_MLO_MAX_LINKS 4
+
+struct wmi_ml_partner_info {
+ u32 vdev_id;
+ u32 hw_link_id;
+ u8 addr[ETH_ALEN];
+ bool assoc_link;
+ bool primary_umac;
+ bool logical_link_idx_valid;
+ u32 logical_link_idx;
+};
+
+struct wmi_ml_arg {
+ bool enabled;
+ bool assoc_link;
+ bool mcast_link;
+ bool link_add;
+ u8 num_partner_links;
+ struct wmi_ml_partner_info partner_info[ATH12K_WMI_MLO_MAX_LINKS];
+};
+
struct wmi_vdev_start_req_arg {
u32 vdev_id;
u32 freq;
@@ -2946,12 +3008,19 @@ struct wmi_vdev_start_req_arg {
u32 mbssid_flags;
u32 mbssid_tx_vdev_id;
u32 punct_bitmap;
+ struct wmi_ml_arg ml;
};
struct ath12k_wmi_peer_create_arg {
const u8 *peer_addr;
u32 peer_type;
u32 vdev_id;
+ bool ml_enabled;
+};
+
+struct wmi_peer_create_mlo_params {
+ __le32 tlv_header;
+ __le32 flags;
};
struct ath12k_wmi_pdev_set_regdomain_arg {
@@ -3618,6 +3687,24 @@ struct wmi_vdev_install_key_arg {
#define WMI_HECAP_TXRX_MCS_NSS_IDX_160 1
#define WMI_HECAP_TXRX_MCS_NSS_IDX_80_80 2
+#define ATH12K_WMI_MLO_MAX_PARTNER_LINKS \
+ (ATH12K_WMI_MLO_MAX_LINKS + ATH12K_MAX_NUM_BRIDGE_LINKS - 1)
+
+struct peer_assoc_mlo_params {
+ bool enabled;
+ bool assoc_link;
+ bool primary_umac;
+ bool peer_id_valid;
+ bool logical_link_idx_valid;
+ bool bridge_peer;
+ u8 mld_addr[ETH_ALEN];
+ u32 logical_link_idx;
+ u32 ml_peer_id;
+ u32 ieee_link_id;
+ u8 num_partner_links;
+ struct wmi_ml_partner_info partner_info[ATH12K_WMI_MLO_MAX_LINKS];
+};
+
struct wmi_rate_set_arg {
u32 num_rates;
u8 rates[WMI_MAX_SUPPORTED_RATES];
@@ -3692,8 +3779,36 @@ struct ath12k_wmi_peer_assoc_arg {
u32 peer_eht_tx_mcs_set[WMI_MAX_EHTCAP_RATE_SET];
struct ath12k_wmi_ppe_threshold_arg peer_eht_ppet;
u32 punct_bitmap;
+ bool is_assoc;
+ struct peer_assoc_mlo_params ml;
};
+#define ATH12K_WMI_FLAG_MLO_ENABLED BIT(0)
+#define ATH12K_WMI_FLAG_MLO_ASSOC_LINK BIT(1)
+#define ATH12K_WMI_FLAG_MLO_PRIMARY_UMAC BIT(2)
+#define ATH12K_WMI_FLAG_MLO_LINK_ID_VALID BIT(3)
+#define ATH12K_WMI_FLAG_MLO_PEER_ID_VALID BIT(4)
+
+struct wmi_peer_assoc_mlo_partner_info_params {
+ __le32 tlv_header;
+ __le32 vdev_id;
+ __le32 hw_link_id;
+ __le32 flags;
+ __le32 logical_link_idx;
+} __packed;
+
+struct wmi_peer_assoc_mlo_params {
+ __le32 tlv_header;
+ __le32 flags;
+ struct ath12k_wmi_mac_addr_params mld_addr;
+ __le32 logical_link_idx;
+ __le32 ml_peer_id;
+ __le32 ieee_link_id;
+ __le32 emlsr_trans_timeout_us;
+ __le32 emlsr_trans_delay_us;
+ __le32 emlsr_padding_delay_us;
+} __packed;
+
struct wmi_peer_assoc_complete_cmd {
__le32 tlv_header;
struct ath12k_wmi_mac_addr_params peer_macaddr;
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 61b2e3f15f0e..72ce321f2a77 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1441,6 +1441,7 @@ static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy,
struct wireless_dev *wdev,
+ unsigned int link_id,
int *dbm)
{
struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
diff --git a/drivers/net/wireless/ath/ath9k/antenna.c b/drivers/net/wireless/ath/ath9k/antenna.c
index acc84e6711b0..e5e274bc9e68 100644
--- a/drivers/net/wireless/ath/ath9k/antenna.c
+++ b/drivers/net/wireless/ath/ath9k/antenna.c
@@ -193,7 +193,7 @@ static void ath_lnaconf_alt_good_scan(struct ath_ant_comb *antcomb,
static void ath_ant_set_alt_ratio(struct ath_ant_comb *antcomb,
struct ath_hw_antcomb_conf *conf)
{
- /* set alt to the conf with maximun ratio */
+ /* set alt to the conf with maximum ratio */
if (antcomb->first_ratio && antcomb->second_ratio) {
if (antcomb->rssi_second > antcomb->rssi_third) {
/* first alt*/
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_hw.c b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
index d08ea0b28530..b26224480041 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -395,7 +395,7 @@ static void ar9002_hw_init_hang_checks(struct ath_hw *ah)
ah->config.hw_hang_checks |= HW_MAC_HANG;
}
-/* Sets up the AR5008/AR9001/AR9002 hardware familiy callbacks */
+/* Sets up the AR5008/AR9001/AR9002 hardware family callbacks */
int ar9002_hw_attach_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
index e9bd13eeee92..6595eca74997 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -1170,7 +1170,7 @@ exit:
return false;
}
-/* Sets up the AR9003 hardware familiy callbacks */
+/* Sets up the AR9003 hardware family callbacks */
void ar9003_hw_attach_ops(struct ath_hw *ah)
{
struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mci.c b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
index 2b9c07961cd7..3f0543e55d9b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mci.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mci.c
@@ -637,7 +637,7 @@ static u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
* same time. Since BT's calibration doesn't happen
* that often, we'll let BT completes calibration then
* we continue to wait for cal_grant from BT.
- * Orginal: Wait BT_CAL_GRANT.
+ * Original: Wait BT_CAL_GRANT.
* New: Receive BT_CAL_REQ -> send WLAN_CAL_GRANT->wait
* BT_CAL_DONE -> Wait BT_CAL_GRANT.
*/
@@ -747,7 +747,7 @@ int ar9003_mci_end_reset(struct ath_hw *ah, struct ath9k_channel *chan,
* BT is sleeping. Check if BT wakes up during
* WLAN calibration. If BT wakes up during
* WLAN calibration, need to go through all
- * message exchanges again and recal.
+ * message exchanges again and recalibrate.
*/
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_RAW,
(AR_MCI_INTERRUPT_RX_MSG_REMOTE_RESET |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.h b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
index ad72a30b67c3..e13873fb8e2f 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h
@@ -246,7 +246,7 @@
/*
- * MRC Feild Definitions
+ * MRC Field Definitions
*/
#define AR_PHY_SGI_DSC_MAN 0x0007FFF0
#define AR_PHY_SGI_DSC_MAN_S 4
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 29ca65a732a6..bcfc8df0efe5 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -1018,6 +1018,8 @@ struct ath_softc {
u8 gtt_cnt;
u32 intrstatus;
+ u32 rx_active_check_time;
+ u32 rx_active_count;
u16 ps_flags; /* PS_* */
bool ps_enabled;
bool ps_idle;
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 571062f2e82a..02237d106f8c 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -17,7 +17,7 @@
#include "ath9k.h"
/* Set/change channels. If the channel is really being changed, it's done
- * by reseting the chip. To accomplish this we must first cleanup any pending
+ * by resetting the chip. To accomplish this we must first cleanup any pending
* DMA, then restart stuff.
*/
static int ath_set_channel(struct ath_softc *sc)
diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c
index 4b27445a5fb8..628eeec4b82f 100644
--- a/drivers/net/wireless/ath/ath9k/common-spectral.c
+++ b/drivers/net/wireless/ath/ath9k/common-spectral.c
@@ -734,7 +734,7 @@ void ath9k_cmn_spectral_scan_trigger(struct ath_common *common,
ATH9K_RX_FILTER_PHYRADAR |
ATH9K_RX_FILTER_PHYERR);
- /* TODO: usually this should not be neccesary, but for some reason
+ /* TODO: usually this should not be necessary, but for some reason
* (or in some mode?) the trigger must be called after the
* configuration, otherwise the register will have its values reset
* (on my ar9220 to value 0x01002310)
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index eff894958a73..74a0134075cf 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -750,6 +750,7 @@ static int read_file_reset(struct seq_file *file, void *data)
[RESET_TYPE_CALIBRATION] = "Calibration error",
[RESET_TX_DMA_ERROR] = "Tx DMA stop error",
[RESET_RX_DMA_ERROR] = "Rx DMA stop error",
+ [RESET_TYPE_RX_INACTIVE] = "Rx path inactive",
};
int i;
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 389459c04d14..cb3e75969875 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -53,6 +53,7 @@ enum ath_reset_type {
RESET_TYPE_CALIBRATION,
RESET_TX_DMA_ERROR,
RESET_RX_DMA_ERROR,
+ RESET_TYPE_RX_INACTIVE,
__RESET_TYPE_MAX
};
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c
index 3689e12db9f7..2fb73a5e1d51 100644
--- a/drivers/net/wireless/ath/ath9k/dfs.c
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
@@ -79,7 +79,7 @@ static int ath9k_get_max_index_ht40(struct ath9k_dfs_fft_40 *fft,
const int DFS_UPPER_BIN_OFFSET = 64;
/* if detected radar on both channels, select the significant one */
if (is_ctl && is_ext) {
- /* first check wether channels have 'strong' bins */
+ /* first check whether channels have 'strong' bins */
is_ctl = fft_bitmap_weight(fft->lower_bins) != 0;
is_ext = fft_bitmap_weight(fft->upper_bins) != 0;
diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c
index 7265766cddbd..fe9abe8cd268 100644
--- a/drivers/net/wireless/ath/ath9k/hif_usb.c
+++ b/drivers/net/wireless/ath/ath9k/hif_usb.c
@@ -1198,7 +1198,7 @@ static int ath9k_hif_request_firmware(struct hif_device_usb *hif_dev,
filename = FIRMWARE_AR9271;
/* expected fw locations:
- * - htc_9271.fw (stable version 1.3, depricated)
+ * - htc_9271.fw (stable version 1.3, deprecated)
*/
snprintf(hif_dev->fw_name, sizeof(hif_dev->fw_name),
"%s", filename);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index e2bef099adb3..a25eacabc664 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -2149,7 +2149,7 @@ static void ath9k_set_power_network_sleep(struct ath_hw *ah)
/* When chip goes into network sleep, it could be waken
* up by MCI_INT interrupt caused by BT's HW messages
- * (LNA_xxx, CONT_xxx) which chould be in a very fast
+ * (LNA_xxx, CONT_xxx) which could be in a very fast
* rate (~100us). This will cause chip to leave and
* re-enter network sleep mode frequently, which in
* consequence will have WLAN MCI HW to generate lots of
@@ -2544,7 +2544,7 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK);
/*
- * For AR9271 we will temporarilly uses the rx chainmax as read from
+ * For AR9271 we will temporarily use the rx chainmax as read from
* the EEPROM.
*/
if ((ah->hw_version.devid == AR5416_DEVID_PCI) &&
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 450ab19b1d4e..e2cbf3f00da0 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -282,7 +282,7 @@ enum ath9k_hw_caps {
* an exact user defined pattern or de-authentication/disassoc pattern.
* @ATH9K_HW_WOW_PATTERN_MATCH_DWORD: device requires the first four
* bytes of the pattern for user defined pattern, de-authentication and
- * disassociation patterns for all types of possible frames recieved
+ * disassociation patterns for all types of possible frames received
* of those types.
*/
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c
index d1e5767aab3c..d078a59d7d3c 100644
--- a/drivers/net/wireless/ath/ath9k/link.c
+++ b/drivers/net/wireless/ath/ath9k/link.c
@@ -50,7 +50,36 @@ reset:
"tx hung, resetting the chip\n");
ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
return false;
+}
+
+#define RX_INACTIVE_CHECK_INTERVAL (4 * MSEC_PER_SEC)
+
+static bool ath_hw_rx_inactive_check(struct ath_softc *sc)
+{
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ u32 interval, count;
+
+ interval = jiffies_to_msecs(jiffies - sc->rx_active_check_time);
+ count = sc->rx_active_count;
+
+ if (interval < RX_INACTIVE_CHECK_INTERVAL)
+ return true; /* too soon to check */
+ sc->rx_active_count = 0;
+ sc->rx_active_check_time = jiffies;
+
+ /* Need at least one interrupt per second, and we should only react if
+ * we are within a factor two of the expected interval
+ */
+ if (interval > RX_INACTIVE_CHECK_INTERVAL * 2 ||
+ count >= interval / MSEC_PER_SEC)
+ return true;
+
+ ath_dbg(common, RESET,
+ "RX inactivity detected. Schedule chip reset\n");
+ ath9k_queue_reset(sc, RESET_TYPE_RX_INACTIVE);
+
+ return false;
}
void ath_hw_check_work(struct work_struct *work)
@@ -58,8 +87,8 @@ void ath_hw_check_work(struct work_struct *work)
struct ath_softc *sc = container_of(work, struct ath_softc,
hw_check_work.work);
- if (!ath_hw_check(sc) ||
- !ath_tx_complete_check(sc))
+ if (!ath_hw_check(sc) || !ath_tx_complete_check(sc) ||
+ !ath_hw_rx_inactive_check(sc))
return;
ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work,
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index f03d792732da..16203e7ecf29 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -251,7 +251,7 @@ struct ath_desc {
* when the descriptor is specifically marked to generate
* an interrupt with this flag. Descriptors should be
* marked periodically to insure timely replenishing of the
- * supply needed for sending frames. Defering interrupts
+ * supply needed for sending frames. Deferring interrupts
* reduces system load and potentially allows more concurrent
* work to be done but if done to aggressively can cause
* senders to backup. When the hardware queue is left too
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index b92c89dad8de..812e0c6bde3e 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -453,6 +453,7 @@ void ath9k_tasklet(struct tasklet_struct *t)
ath_rx_tasklet(sc, 0, true);
ath_rx_tasklet(sc, 0, false);
+ sc->rx_active_count++;
}
if (status & ATH9K_INT_TX) {
@@ -1001,7 +1002,7 @@ static bool ath9k_uses_beacons(int type)
static void ath9k_vif_iter_set_beacon(struct ath9k_vif_iter_data *iter_data,
struct ieee80211_vif *vif)
{
- /* Use the first (configured) interface, but prefering AP interfaces. */
+ /* Use the first (configured) interface, but preferring AP interfaces. */
if (!iter_data->primary_beacon_vif) {
iter_data->primary_beacon_vif = vif;
} else {
@@ -2767,7 +2768,7 @@ void ath9k_fill_chanctx_ops(void)
#endif
static int ath9k_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- int *dbm)
+ unsigned int link_id, int *dbm)
{
struct ath_softc *sc = hw->priv;
struct ath_vif *avp = (void *)vif->drv_priv;
diff --git a/drivers/net/wireless/ath/ath9k/wow.c b/drivers/net/wireless/ath/ath9k/wow.c
index 8d0b1730a9d5..ed4152cd44f0 100644
--- a/drivers/net/wireless/ath/ath9k/wow.c
+++ b/drivers/net/wireless/ath/ath9k/wow.c
@@ -60,7 +60,7 @@ static int ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
memset(dis_deauth_mask, 0, MAX_PATTERN_SIZE);
/*
- * Create Dissassociate / Deauthenticate packet filter
+ * Create Disassociate / Deauthenticate packet filter
*
* 2 bytes 2 byte 6 bytes 6 bytes 6 bytes
* +--------------+----------+---------+--------+--------+----
@@ -70,7 +70,7 @@ static int ath9k_wow_add_disassoc_deauth_pattern(struct ath_softc *sc)
* The above is the management frame format for disassociate/
* deauthenticate pattern, from this we need to match the first byte
* of 'Frame Control' and DA, SA, and BSSID fields
- * (skipping 2nd byte of FC and Duration feild.
+ * (skipping 2nd byte of FC and Duration field.
*
* Disassociate pattern
* --------------------
@@ -225,7 +225,7 @@ int ath9k_suspend(struct ieee80211_hw *hw,
ath9k_stop_btcoex(sc);
/*
- * Enable wake up on recieving disassoc/deauth
+ * Enable wake up on receiving disassoc/deauth
* frame by default.
*/
ret = ath9k_wow_add_disassoc_deauth_pattern(sc);
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 35aa47a9db90..0a24439dd30d 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -557,7 +557,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
/*
* AR5416 can become deaf/mute when BA
* issue happens. Chip needs to be reset.
- * But AP code may have sychronization issues
+ * But AP code may have synchronization issues
* when perform internal reset in this routine.
* Only enable reset in STA mode for now.
*/
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index 8557d4826a46..94d08d6ae1a3 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1590,7 +1590,10 @@ static int wcn36xx_probe(struct platform_device *pdev)
}
n_channels = wcn_band_2ghz.n_channels + wcn_band_5ghz.n_channels;
- wcn->chan_survey = devm_kmalloc(wcn->dev, n_channels, GFP_KERNEL);
+ wcn->chan_survey = devm_kcalloc(wcn->dev,
+ n_channels,
+ sizeof(struct wcn36xx_chan_survey),
+ GFP_KERNEL);
if (!wcn->chan_survey) {
ret = -ENOMEM;
goto out_wq;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bca/module.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bca/module.c
index 4f0c1e1a8e60..1e1c79b18c5b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bca/module.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bca/module.c
@@ -22,7 +22,7 @@ static void __exit brcmf_bca_exit(void)
MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Broadcom AP chipsets");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_IMPORT_NS(BRCMFMAC);
+MODULE_IMPORT_NS("BRCMFMAC");
module_init(brcmf_bca_init);
module_exit(brcmf_bca_exit);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
index 42d991d9f8cb..60eb95fc19a5 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -455,6 +455,11 @@ static int brcmf_sdiod_sglist_rw(struct brcmf_sdio_dev *sdiodev,
if (sg_data_sz > max_req_sz - req_sz)
sg_data_sz = max_req_sz - req_sz;
+ if (!sgl) {
+ /* out of (pre-allocated) scatterlist entries */
+ ret = -ENOMEM;
+ goto exit;
+ }
sg_set_buf(sgl, pkt_data, sg_data_sz);
sg_cnt++;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 297a7c738c01..902ac3108782 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -2676,7 +2676,7 @@ done:
static s32
brcmf_cfg80211_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
- s32 *dbm)
+ unsigned int link_id, s32 *dbm)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_cfg80211_vif *vif = wdev_to_vif(wdev);
@@ -4999,12 +4999,16 @@ exit:
s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif)
{
static const s32 pktflags[] = {
- BRCMF_VNDR_IE_PRBREQ_FLAG,
BRCMF_VNDR_IE_PRBRSP_FLAG,
BRCMF_VNDR_IE_BEACON_FLAG
};
int i;
+ if (vif->wdev.iftype == NL80211_IFTYPE_AP)
+ brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_ASSOCRSP_FLAG, NULL, 0);
+ else
+ brcmf_vif_set_mgmt_ie(vif, BRCMF_VNDR_IE_PRBREQ_FLAG, NULL, 0);
+
for (i = 0; i < ARRAY_SIZE(pktflags); i++)
brcmf_vif_set_mgmt_ie(vif, pktflags[i], NULL, 0);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index da72fd2d541f..c3a57e30c855 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -327,8 +327,8 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
if (skb_headroom(skb) < drvr->hdrlen || skb_header_cloned(skb)) {
head_delta = max_t(int, drvr->hdrlen - skb_headroom(skb), 0);
- brcmf_dbg(INFO, "%s: insufficient headroom (%d)\n",
- brcmf_ifname(ifp), head_delta);
+ brcmf_dbg(INFO, "%s: %s headroom\n", brcmf_ifname(ifp),
+ head_delta ? "insufficient" : "unmodifiable");
atomic_inc(&drvr->bus_if->stats.pktcowed);
ret = pskb_expand_head(skb, ALIGN(head_delta, NET_SKB_PAD), 0,
GFP_ATOMIC);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
index 39226b9c0fa8..d53839f855d7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
@@ -14,7 +14,7 @@
#include "fweh.h"
#if IS_MODULE(CONFIG_BRCMFMAC)
-#define BRCMF_EXPORT_SYMBOL_GPL(__sym) EXPORT_SYMBOL_NS_GPL(__sym, BRCMFMAC)
+#define BRCMF_EXPORT_SYMBOL_GPL(__sym) EXPORT_SYMBOL_NS_GPL(__sym, "BRCMFMAC")
#else
#define BRCMF_EXPORT_SYMBOL_GPL(__sym)
#endif
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/module.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/module.c
index 90d06cda03a2..ce5fcfd42a7e 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/module.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cyw/module.c
@@ -22,7 +22,7 @@ static void __exit brcmf_cyw_exit(void)
MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Cypress/Infineon chipsets");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_IMPORT_NS(BRCMFMAC);
+MODULE_IMPORT_NS("BRCMFMAC");
module_init(brcmf_cyw_init);
module_exit(brcmf_cyw_exit);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
index 31e080e4da66..ab3d6cfcb02b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
@@ -6,6 +6,8 @@
#ifndef _fwil_h_
#define _fwil_h_
+#include "debug.h"
+
/*******************************************************************************
* Dongle command codes that are interpreted by firmware
******************************************************************************/
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/module.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/module.c
index b66135e3cff4..cfe01ca63ba6 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/module.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/wcc/module.c
@@ -22,7 +22,7 @@ static void __exit brcmf_wcc_exit(void)
MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Broadcom mobility chipsets");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_IMPORT_NS(BRCMFMAC);
+MODULE_IMPORT_NS("BRCMFMAC");
module_init(brcmf_wcc_init);
module_exit(brcmf_wcc_exit);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c
index d69879e1bd87..d362c4337616 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/phy/phy_n.c
@@ -23423,6 +23423,9 @@ wlc_phy_iqcal_gainparams_nphy(struct brcms_phy *pi, u16 core_no,
break;
}
+ if (WARN_ON(k == NPHY_IQCAL_NUMGAINS))
+ return;
+
params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1];
params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2];
params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3];
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
index cd1fe8490ae5..1c43f283ac4a 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
@@ -161,6 +161,7 @@ const struct iwl_cfg_trans_params iwl_gl_trans_cfg = {
const char iwl_bz_name[] = "Intel(R) TBD Bz device";
const char iwl_fm_name[] = "Intel(R) Wi-Fi 7 BE201 320MHz";
+const char iwl_wh_name[] = "Intel(R) Wi-Fi 7 BE211 320MHz";
const char iwl_gl_name[] = "Intel(R) Wi-Fi 7 BE200 320MHz";
const char iwl_mtp_name[] = "Intel(R) Wi-Fi 7 BE202 160MHz";
diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
index e0b14be25b02..769b75c3fa5b 100644
--- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c
@@ -48,7 +48,7 @@
#define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux"
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IWLWIFI);
+MODULE_IMPORT_NS("IWLWIFI");
/* Please keep this array *SORTED* by hex value.
* Access is done through binary search.
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 34c91deca57b..17721bb47e25 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -545,6 +545,7 @@ extern const char iwl_ax231_name[];
extern const char iwl_ax411_name[];
extern const char iwl_bz_name[];
extern const char iwl_fm_name[];
+extern const char iwl_wh_name[];
extern const char iwl_gl_name[];
extern const char iwl_mtp_name[];
extern const char iwl_sc_name[];
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
index 6a1d31892417..854957bdf79d 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h
@@ -85,7 +85,7 @@ void iwl_drv_stop(struct iwl_drv *drv);
* everything is built-in, then we can avoid that.
*/
#ifdef CONFIG_IWLWIFI_OPMODE_MODULAR
-#define IWL_EXPORT_SYMBOL(sym) EXPORT_SYMBOL_NS_GPL(sym, IWLWIFI)
+#define IWL_EXPORT_SYMBOL(sym) EXPORT_SYMBOL_NS_GPL(sym, "IWLWIFI")
#else
#define IWL_EXPORT_SYMBOL(sym)
#endif
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
index f85c01e04ebf..7d973546c9fb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c
@@ -2954,6 +2954,7 @@ static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm,
int idx)
{
int i;
+ int n_channels = 0;
if (fw_has_api(&mvm->fw->ucode_capa,
IWL_UCODE_TLV_API_SCAN_OFFLOAD_CHANS)) {
@@ -2962,7 +2963,7 @@ static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm,
for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN * 8; i++)
if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))
- match->channels[match->n_channels++] =
+ match->channels[n_channels++] =
mvm->nd_channels[i]->center_freq;
} else {
struct iwl_scan_offload_profile_match_v1 *matches =
@@ -2970,9 +2971,11 @@ static void iwl_mvm_query_set_freqs(struct iwl_mvm *mvm,
for (i = 0; i < SCAN_OFFLOAD_MATCHING_CHANNELS_LEN_V1 * 8; i++)
if (matches[idx].matching_channels[i / 8] & (BIT(i % 8)))
- match->channels[match->n_channels++] =
+ match->channels[n_channels++] =
mvm->nd_channels[i]->center_freq;
}
+ /* We may have ended up with fewer channels than we allocated. */
+ match->n_channels = n_channels;
}
/**
@@ -3053,6 +3056,8 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
GFP_KERNEL);
if (!net_detect || !n_matches)
goto out_report_nd;
+ net_detect->n_matches = n_matches;
+ n_matches = 0;
for_each_set_bit(i, &matched_profiles, mvm->n_nd_match_sets) {
struct cfg80211_wowlan_nd_match *match;
@@ -3066,8 +3071,9 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
GFP_KERNEL);
if (!match)
goto out_report_nd;
+ match->n_channels = n_channels;
- net_detect->matches[net_detect->n_matches++] = match;
+ net_detect->matches[n_matches++] = match;
/* We inverted the order of the SSIDs in the scan
* request, so invert the index here.
@@ -3082,6 +3088,8 @@ static void iwl_mvm_query_netdetect_reasons(struct iwl_mvm *mvm,
iwl_mvm_query_set_freqs(mvm, d3_data->nd_results, match, i);
}
+ /* We may have fewer matches than we allocated. */
+ net_detect->n_matches = n_matches;
out_report_nd:
wakeup.net_detect = net_detect;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
index 2a13d70da46c..51ee62ae70fb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c
@@ -1972,7 +1972,7 @@ void iwl_mvm_channel_switch_error_notif(struct iwl_mvm *mvm,
if (csa_err_mask & (CS_ERR_COUNT_ERROR |
CS_ERR_LONG_DELAY_AFTER_CS |
CS_ERR_TX_BLOCK_TIMER_EXPIRED))
- ieee80211_channel_switch_disconnect(vif, true);
+ ieee80211_channel_switch_disconnect(vif);
rcu_read_unlock();
}
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
index e25d7570ffab..30fcc733395e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c
@@ -34,7 +34,7 @@
#define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux"
MODULE_DESCRIPTION(DRV_DESCRIPTION);
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IWLWIFI);
+MODULE_IMPORT_NS("IWLWIFI");
static const struct iwl_op_mode_ops iwl_mvm_ops;
static const struct iwl_op_mode_ops iwl_mvm_ops_mq;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c b/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c
index 47b8e7b64ead..1dc57e022191 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tests/links.c
@@ -8,7 +8,7 @@
#include "../mvm.h"
#include <kunit/test.h>
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static struct wiphy wiphy = {
.mtx = __MUTEX_INITIALIZER(wiphy.mtx),
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c b/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c
index d3b6a57c3ebe..7a3275199ace 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tests/scan.c
@@ -8,7 +8,7 @@
#include "../mvm.h"
#include <kunit/test.h>
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static const struct acs_average_db_case {
const char *desc;
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/vendor-cmd.c b/drivers/net/wireless/intel/iwlwifi/mvm/vendor-cmd.c
index 080a1587caa5..0f7fa6032c66 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/vendor-cmd.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/vendor-cmd.c
@@ -104,9 +104,9 @@ static const struct wiphy_vendor_command iwl_mvm_vendor_commands[] = {
};
enum iwl_mvm_vendor_events_idx {
- /* 0x0 - 0x3 are deprecated */
- IWL_MVM_VENDOR_EVENT_IDX_ROAMING_FORBIDDEN = 4,
- NUM_IWL_MVM_VENDOR_EVENT_IDX
+ /* 0x0 - 0x3 are deprecated */
+ IWL_MVM_VENDOR_EVENT_IDX_ROAMING_FORBIDDEN = 4,
+ NUM_IWL_MVM_VENDOR_EVENT_IDX
};
static const struct nl80211_vendor_cmd_info
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index 805fb249a0c6..8fb2aa282242 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1106,19 +1106,54 @@ VISIBLE_IF_IWLWIFI_KUNIT const struct iwl_dev_info iwl_dev_info_table[] = {
iwlax210_2ax_cfg_so_jf_b0, iwl9462_name),
/* Bz */
-/* FIXME: need to change the naming according to the actual CRF */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_bz, iwl_ax201_name),
+
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_bz, iwl_ax211_name),
+
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
iwl_cfg_bz, iwl_fm_name),
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_BZ, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_WH, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_bz, iwl_wh_name),
+
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_BZ_W, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_bz, iwl_ax201_name),
+
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_BZ_W, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_bz, iwl_ax211_name),
+
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_BZ_W, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_FM, IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
iwl_cfg_bz, iwl_fm_name),
+ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_MAC_TYPE_BZ_W, IWL_CFG_ANY,
+ IWL_CFG_RF_TYPE_WH, IWL_CFG_ANY, IWL_CFG_ANY,
+ IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_ANY,
+ iwl_cfg_bz, iwl_wh_name),
+
/* Ga (Gl) */
_IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY,
IWL_CFG_MAC_TYPE_GL, IWL_CFG_ANY,
diff --git a/drivers/net/wireless/intel/iwlwifi/tests/devinfo.c b/drivers/net/wireless/intel/iwlwifi/tests/devinfo.c
index 7361b6d0cdb8..d0bda23c628a 100644
--- a/drivers/net/wireless/intel/iwlwifi/tests/devinfo.c
+++ b/drivers/net/wireless/intel/iwlwifi/tests/devinfo.c
@@ -9,7 +9,7 @@
#include "iwl-drv.h"
#include "iwl-config.h"
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static void iwl_pci_print_dev_info(const char *pfx, const struct iwl_dev_info *di)
{
diff --git a/drivers/net/wireless/marvell/mwifiex/cfg80211.c b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
index fca3eea7ee84..a099fdaafa45 100644
--- a/drivers/net/wireless/marvell/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/marvell/mwifiex/cfg80211.c
@@ -410,7 +410,7 @@ mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy,
static int
mwifiex_cfg80211_get_tx_power(struct wiphy *wiphy,
struct wireless_dev *wdev,
- int *dbm)
+ unsigned int link_id, int *dbm)
{
struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy);
struct mwifiex_private *priv = mwifiex_get_priv(adapter,
diff --git a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
index e06a0622973e..f79589cafe57 100644
--- a/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/marvell/mwifiex/sta_ioctl.c
@@ -545,7 +545,7 @@ int mwifiex_enable_hs(struct mwifiex_adapter *adapter)
if (wait_event_interruptible_timeout(adapter->hs_activate_wait_q,
adapter->hs_activate_wait_q_woken,
- (10 * HZ)) <= 0) {
+ (5 * HZ)) <= 0) {
mwifiex_dbg(adapter, ERROR,
"hs_activate_wait_q terminated\n");
return false;
diff --git a/drivers/net/wireless/mediatek/mt76/mac80211.c b/drivers/net/wireless/mediatek/mt76/mac80211.c
index 9d5561f44134..7fbce5e757df 100644
--- a/drivers/net/wireless/mediatek/mt76/mac80211.c
+++ b/drivers/net/wireless/mediatek/mt76/mac80211.c
@@ -1596,7 +1596,7 @@ void mt76_wcid_cleanup(struct mt76_dev *dev, struct mt76_wcid *wcid)
EXPORT_SYMBOL_GPL(mt76_wcid_cleanup);
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- int *dbm)
+ unsigned int link_id, int *dbm)
{
struct mt76_phy *phy = hw->priv;
int n_chains = hweight16(phy->chainmask);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 0b75a45ad2e8..ca2dba3ac65d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -1431,7 +1431,7 @@ void mt76_sta_pre_rcu_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int mt76_get_min_avg_rssi(struct mt76_dev *dev, bool ext_phy);
int mt76_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- int *dbm);
+ unsigned int link_id, int *dbm);
int mt76_init_sar_power(struct ieee80211_hw *hw,
const struct cfg80211_sar_specs *sar);
int mt76_get_sar_power(struct mt76_phy *phy,
diff --git a/drivers/net/wireless/microchip/wilc1000/cfg80211.c b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
index e96736cc7259..e7aa0f991923 100644
--- a/drivers/net/wireless/microchip/wilc1000/cfg80211.c
+++ b/drivers/net/wireless/microchip/wilc1000/cfg80211.c
@@ -1669,7 +1669,7 @@ static int set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
}
static int get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
- int *dbm)
+ unsigned int link_id, int *dbm)
{
int ret;
struct wilc_vif *vif = netdev_priv(wdev->netdev);
diff --git a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
index 8b97accf6638..0b2282528342 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/cfg80211.c
@@ -881,7 +881,7 @@ static int qtnf_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
}
static int qtnf_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
- int *dbm)
+ unsigned int link_id, int *dbm)
{
struct qtnf_vif *vif = qtnf_netdev_get_priv(wdev->netdev);
int ret;
diff --git a/drivers/net/wireless/quantenna/qtnfmac/core.h b/drivers/net/wireless/quantenna/qtnfmac/core.h
index b375a4751580..a377d85c2451 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/core.h
+++ b/drivers/net/wireless/quantenna/qtnfmac/core.h
@@ -102,7 +102,7 @@ struct qtnf_wmac {
struct qtnf_mac_info macinfo;
struct qtnf_vif iflist[QTNF_MAX_INTF];
struct cfg80211_scan_request *scan_req;
- struct mutex mac_lock; /* lock during wmac speicific ops */
+ struct mutex mac_lock; /* lock during wmac specific ops */
struct delayed_work scan_timeout;
struct ieee80211_regdomain *rd;
struct platform_device *pdev;
diff --git a/drivers/net/wireless/realtek/rtl8xxxu/core.c b/drivers/net/wireless/realtek/rtl8xxxu/core.c
index f95898f68d68..4ce0c05c5129 100644
--- a/drivers/net/wireless/realtek/rtl8xxxu/core.c
+++ b/drivers/net/wireless/realtek/rtl8xxxu/core.c
@@ -8147,6 +8147,8 @@ static const struct usb_device_id dev_table[] = {
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x817e, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x8186, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x818a, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x317f, 0xff, 0xff, 0xff),
@@ -8157,12 +8159,18 @@ static const struct usb_device_id dev_table[] = {
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1102, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x11f2, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe033, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8188, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8189, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9041, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9043, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ba, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(USB_VENDOR_ID_REALTEK, 0x1e1e, 0xff, 0xff, 0xff),
@@ -8179,6 +8187,10 @@ static const struct usb_device_id dev_table[] = {
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x13d3, 0x3357, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x13d3, 0x3358, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x13d3, 0x3359, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330b, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0x4902, 0xff, 0xff, 0xff),
@@ -8193,6 +8205,8 @@ static const struct usb_device_id dev_table[] = {
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x4856, 0x0091, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x9846, 0x9041, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0xcdab, 0x8010, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x04f2, 0xaff7, 0xff, 0xff, 0xff),
@@ -8218,6 +8232,8 @@ static const struct usb_device_id dev_table[] = {
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x341f, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe033, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x06f8, 0xe035, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17ab, 0xff, 0xff, 0xff),
@@ -8226,6 +8242,8 @@ static const struct usb_device_id dev_table[] = {
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0070, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0077, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x0789, 0x016d, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x07aa, 0x0056, 0xff, 0xff, 0xff),
@@ -8248,6 +8266,8 @@ static const struct usb_device_id dev_table[] = {
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330a, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
+{USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330d, 0xff, 0xff, 0xff),
+ .driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab2b, 0xff, 0xff, 0xff),
.driver_info = (unsigned long)&rtl8192cu_fops},
{USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x624d, 0xff, 0xff, 0xff),
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.c b/drivers/net/wireless/realtek/rtlwifi/base.c
index aab4605de9c4..ff61867d142f 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.c
+++ b/drivers/net/wireless/realtek/rtlwifi/base.c
@@ -575,9 +575,15 @@ static void rtl_free_entries_from_ack_queue(struct ieee80211_hw *hw,
void rtl_deinit_core(struct ieee80211_hw *hw)
{
+ struct rtl_priv *rtlpriv = rtl_priv(hw);
+
rtl_c2hcmd_launcher(hw, 0);
rtl_free_entries_from_scan_list(hw);
rtl_free_entries_from_ack_queue(hw, false);
+ if (rtlpriv->works.rtl_wq) {
+ destroy_workqueue(rtlpriv->works.rtl_wq);
+ rtlpriv->works.rtl_wq = NULL;
+ }
}
EXPORT_SYMBOL_GPL(rtl_deinit_core);
@@ -2696,9 +2702,6 @@ MODULE_AUTHOR("Larry Finger <Larry.FInger@lwfinger.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek 802.11n PCI wireless core");
-struct rtl_global_var rtl_global_var = {};
-EXPORT_SYMBOL_GPL(rtl_global_var);
-
static int __init rtl_core_module_init(void)
{
BUILD_BUG_ON(TX_PWR_BY_RATE_NUM_RATE < TX_PWR_BY_RATE_NUM_SECTION);
@@ -2712,10 +2715,6 @@ static int __init rtl_core_module_init(void)
/* add debugfs */
rtl_debugfs_add_topdir();
- /* init some global vars */
- INIT_LIST_HEAD(&rtl_global_var.glb_priv_list);
- spin_lock_init(&rtl_global_var.glb_list_lock);
-
return 0;
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/base.h b/drivers/net/wireless/realtek/rtlwifi/base.h
index f081a9a90563..f3a6a43a42ec 100644
--- a/drivers/net/wireless/realtek/rtlwifi/base.h
+++ b/drivers/net/wireless/realtek/rtlwifi/base.h
@@ -124,7 +124,6 @@ int rtl_send_smps_action(struct ieee80211_hw *hw,
u8 *rtl_find_ie(u8 *data, unsigned int len, u8 ie);
void rtl_recognize_peer(struct ieee80211_hw *hw, u8 *data, unsigned int len);
u8 rtl_tid_to_ac(u8 tid);
-extern struct rtl_global_var rtl_global_var;
void rtl_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation);
#endif
diff --git a/drivers/net/wireless/realtek/rtlwifi/pci.c b/drivers/net/wireless/realtek/rtlwifi/pci.c
index 11709b6c83f1..0eafc4d125f9 100644
--- a/drivers/net/wireless/realtek/rtlwifi/pci.c
+++ b/drivers/net/wireless/realtek/rtlwifi/pci.c
@@ -295,46 +295,6 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
return status;
}
-static bool rtl_pci_check_buddy_priv(struct ieee80211_hw *hw,
- struct rtl_priv **buddy_priv)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
- struct rtl_priv *tpriv = NULL, *iter;
- struct rtl_pci_priv *tpcipriv = NULL;
-
- if (!list_empty(&rtlpriv->glb_var->glb_priv_list)) {
- list_for_each_entry(iter, &rtlpriv->glb_var->glb_priv_list,
- list) {
- tpcipriv = (struct rtl_pci_priv *)iter->priv;
- rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
- "pcipriv->ndis_adapter.funcnumber %x\n",
- pcipriv->ndis_adapter.funcnumber);
- rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
- "tpcipriv->ndis_adapter.funcnumber %x\n",
- tpcipriv->ndis_adapter.funcnumber);
-
- if (pcipriv->ndis_adapter.busnumber ==
- tpcipriv->ndis_adapter.busnumber &&
- pcipriv->ndis_adapter.devnumber ==
- tpcipriv->ndis_adapter.devnumber &&
- pcipriv->ndis_adapter.funcnumber !=
- tpcipriv->ndis_adapter.funcnumber) {
- tpriv = iter;
- break;
- }
- }
- }
-
- rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD,
- "find_buddy_priv %d\n", tpriv != NULL);
-
- if (tpriv)
- *buddy_priv = tpriv;
-
- return tpriv != NULL;
-}
-
static void rtl_pci_parse_configuration(struct pci_dev *pdev,
struct ieee80211_hw *hw)
{
@@ -1696,8 +1656,6 @@ static void rtl_pci_deinit(struct ieee80211_hw *hw)
synchronize_irq(rtlpci->pdev->irq);
tasklet_kill(&rtlpriv->works.irq_tasklet);
cancel_work_sync(&rtlpriv->works.lps_change_work);
-
- destroy_workqueue(rtlpriv->works.rtl_wq);
}
static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev)
@@ -2011,7 +1969,6 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
pcipriv->ndis_adapter.amd_l1_patch);
rtl_pci_parse_configuration(pdev, hw);
- list_add_tail(&rtlpriv->list, &rtlpriv->glb_var->glb_priv_list);
return true;
}
@@ -2158,7 +2115,6 @@ int rtl_pci_probe(struct pci_dev *pdev,
rtlpriv->rtlhal.interface = INTF_PCI;
rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_data);
rtlpriv->intf_ops = &rtl_pci_ops;
- rtlpriv->glb_var = &rtl_global_var;
rtl_efuse_ops_init(hw);
/* MEM map */
@@ -2209,7 +2165,7 @@ int rtl_pci_probe(struct pci_dev *pdev,
if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
pr_err("Can't init_sw_vars\n");
err = -ENODEV;
- goto fail3;
+ goto fail2;
}
rtl_init_sw_leds(hw);
@@ -2227,14 +2183,14 @@ int rtl_pci_probe(struct pci_dev *pdev,
err = rtl_pci_init(hw, pdev);
if (err) {
pr_err("Failed to init PCI\n");
- goto fail3;
+ goto fail4;
}
err = ieee80211_register_hw(hw);
if (err) {
pr_err("Can't register mac80211 hw.\n");
err = -ENODEV;
- goto fail3;
+ goto fail5;
}
rtlpriv->mac80211.mac80211_registered = 1;
@@ -2257,16 +2213,19 @@ int rtl_pci_probe(struct pci_dev *pdev,
set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
return 0;
-fail3:
- pci_set_drvdata(pdev, NULL);
+fail5:
+ rtl_pci_deinit(hw);
+fail4:
rtl_deinit_core(hw);
+fail3:
+ wait_for_completion(&rtlpriv->firmware_loading_complete);
+ rtlpriv->cfg->ops->deinit_sw_vars(hw);
fail2:
if (rtlpriv->io.pci_mem_start != 0)
pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
pci_release_regions(pdev);
- complete(&rtlpriv->firmware_loading_complete);
fail1:
if (hw)
@@ -2317,7 +2276,6 @@ void rtl_pci_disconnect(struct pci_dev *pdev)
if (rtlpci->using_msi)
pci_disable_msi(rtlpci->pdev);
- list_del(&rtlpriv->list);
if (rtlpriv->io.pci_mem_start != 0) {
pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
pci_release_regions(pdev);
@@ -2376,7 +2334,6 @@ EXPORT_SYMBOL(rtl_pci_resume);
const struct rtl_intf_ops rtl_pci_ops = {
.adapter_start = rtl_pci_start,
.adapter_stop = rtl_pci_stop,
- .check_buddy_priv = rtl_pci_check_buddy_priv,
.adapter_tx = rtl_pci_tx,
.flush = rtl_pci_flush,
.reset_trx_ring = rtl_pci_reset_trx_ring,
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
index bbf8ff63dced..e63c67b1861b 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8192se/sw.c
@@ -64,22 +64,23 @@ static void rtl92se_fw_cb(const struct firmware *firmware, void *context)
rtl_dbg(rtlpriv, COMP_ERR, DBG_LOUD,
"Firmware callback routine entered!\n");
- complete(&rtlpriv->firmware_loading_complete);
if (!firmware) {
pr_err("Firmware %s not available\n", fw_name);
rtlpriv->max_fw_size = 0;
- return;
+ goto exit;
}
if (firmware->size > rtlpriv->max_fw_size) {
pr_err("Firmware is too big!\n");
rtlpriv->max_fw_size = 0;
release_firmware(firmware);
- return;
+ goto exit;
}
pfirmware = (struct rt_firmware *)rtlpriv->rtlhal.pfirmware;
memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size);
pfirmware->sz_fw_tmpbufferlen = firmware->size;
release_firmware(firmware);
+exit:
+ complete(&rtlpriv->firmware_loading_complete);
}
static int rtl92s_init_sw_vars(struct ieee80211_hw *hw)
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
index 1be51ea3f3c8..9eddbada8af1 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/phy.c
@@ -2033,8 +2033,10 @@ static bool _rtl8821ae_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
if (!_rtl8821ae_check_condition(hw, v1)) {
i += 2; /* skip the pair of expression*/
v2 = array[i+1];
- while (v2 != 0xDEAD)
+ while (v2 != 0xDEAD) {
i += 3;
+ v2 = array[i + 1];
+ }
}
}
}
diff --git a/drivers/net/wireless/realtek/rtlwifi/usb.c b/drivers/net/wireless/realtek/rtlwifi/usb.c
index d37a017b2b81..f5718e570011 100644
--- a/drivers/net/wireless/realtek/rtlwifi/usb.c
+++ b/drivers/net/wireless/realtek/rtlwifi/usb.c
@@ -629,11 +629,6 @@ static void _rtl_usb_cleanup_rx(struct ieee80211_hw *hw)
tasklet_kill(&rtlusb->rx_work_tasklet);
cancel_work_sync(&rtlpriv->works.lps_change_work);
- if (rtlpriv->works.rtl_wq) {
- destroy_workqueue(rtlpriv->works.rtl_wq);
- rtlpriv->works.rtl_wq = NULL;
- }
-
skb_queue_purge(&rtlusb->rx_queue);
while ((urb = usb_get_from_anchor(&rtlusb->rx_cleanup_urbs))) {
@@ -1028,19 +1023,22 @@ int rtl_usb_probe(struct usb_interface *intf,
err = ieee80211_register_hw(hw);
if (err) {
pr_err("Can't register mac80211 hw.\n");
- goto error_out;
+ goto error_init_vars;
}
rtlpriv->mac80211.mac80211_registered = 1;
set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
return 0;
+error_init_vars:
+ wait_for_completion(&rtlpriv->firmware_loading_complete);
+ rtlpriv->cfg->ops->deinit_sw_vars(hw);
error_out:
+ rtl_usb_deinit(hw);
rtl_deinit_core(hw);
error_out2:
_rtl_usb_io_handler_release(hw);
usb_put_dev(udev);
- complete(&rtlpriv->firmware_loading_complete);
kfree(rtlpriv->usb_data);
ieee80211_free_hw(hw);
return -ENODEV;
diff --git a/drivers/net/wireless/realtek/rtlwifi/wifi.h b/drivers/net/wireless/realtek/rtlwifi/wifi.h
index ae6e351bc83c..f1830ddcdd8c 100644
--- a/drivers/net/wireless/realtek/rtlwifi/wifi.h
+++ b/drivers/net/wireless/realtek/rtlwifi/wifi.h
@@ -2270,8 +2270,6 @@ struct rtl_intf_ops {
/*com */
int (*adapter_start)(struct ieee80211_hw *hw);
void (*adapter_stop)(struct ieee80211_hw *hw);
- bool (*check_buddy_priv)(struct ieee80211_hw *hw,
- struct rtl_priv **buddy_priv);
int (*adapter_tx)(struct ieee80211_hw *hw,
struct ieee80211_sta *sta,
@@ -2514,14 +2512,6 @@ struct dig_t {
u32 rssi_max;
};
-struct rtl_global_var {
- /* from this list we can get
- * other adapter's rtl_priv
- */
- struct list_head glb_priv_list;
- spinlock_t glb_list_lock;
-};
-
#define IN_4WAY_TIMEOUT_TIME (30 * MSEC_PER_SEC) /* 30 seconds */
struct rtl_btc_info {
@@ -2667,9 +2657,7 @@ struct rtl_scan_list {
struct rtl_priv {
struct ieee80211_hw *hw;
struct completion firmware_loading_complete;
- struct list_head list;
struct rtl_priv *buddy_priv;
- struct rtl_global_var *glb_var;
struct rtl_dmsp_ctl dmsp_ctl;
struct rtl_locks locks;
struct rtl_works works;
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8812au.c b/drivers/net/wireless/realtek/rtw88/rtw8812au.c
index 4da69590a423..e18995f4cc78 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8812au.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8812au.c
@@ -9,8 +9,74 @@
#include "usb.h"
static const struct usb_device_id rtw_8812au_id_table[] = {
- { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff),
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8812, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881a, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881b, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x881c, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0409, 0x0408, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* NEC */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x025d, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Buffalo */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0952, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* I-O DATA */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1106, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Belkin */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x050d, 0x1109, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Belkin */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0586, 0x3426, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* ZyXEL */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0789, 0x016e, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Logitec */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x07b8, 0x8812, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Abocom */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9051, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Netgear */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0b05, 0x17d2, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* ASUS */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0df6, 0x0074, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Sitecom */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0022, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Hawking */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1058, 0x0632, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* WD */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x13b1, 0x003f, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Linksys */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x148f, 0x9097, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Amped Wireless */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x1740, 0x0100, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* EnGenius */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x330e, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3313, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3315, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3316, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* D-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab30, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Planex */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x805b, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TRENDnet */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0101, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0103, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010d, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010e, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x010f, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0122, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* TP-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2604, 0x0012, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Tenda */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa822, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8812a_hw_spec) }, /* Edimax */
{},
};
MODULE_DEVICE_TABLE(usb, rtw_8812au_id_table);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8821au.c b/drivers/net/wireless/realtek/rtw88/rtw8821au.c
index 730018773e1c..a01744b64e8d 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8821au.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8821au.c
@@ -9,8 +9,58 @@
#include "usb.h"
static const struct usb_device_id rtw_8821au_id_table[] = {
- { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff),
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0811, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0820, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0821, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x8822, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0x0823, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(RTW_USB_VENDOR_ID_REALTEK, 0xa811, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x0242, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Buffalo */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0411, 0x029b, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Buffalo */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x0953, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* I-O DATA */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4007, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x400e, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x400f, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* ELECOM */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0846, 0x9052, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Netgear */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x0e66, 0x0023, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* HAWKING */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3314, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* D-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x3318, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* D-Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2019, 0xab32, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Planex */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x804b, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TRENDnet */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011e, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x011f, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0120, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* TP Link */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3823, 0x6249, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Obihai */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa811, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa812, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xa813, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x7392, 0xb611, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8821a_hw_spec) }, /* Edimax */
{},
};
MODULE_DEVICE_TABLE(usb, rtw_8821au_id_table);
diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c
index ab620a0b1dfc..8883300fc6ad 100644
--- a/drivers/net/wireless/realtek/rtw88/rtw8822bu.c
+++ b/drivers/net/wireless/realtek/rtw88/rtw8822bu.c
@@ -67,6 +67,12 @@ static const struct usb_device_id rtw_8822bu_id_table[] = {
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* LiteOn */
{ USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x808a, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-808UBM */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0x805a, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* TRENDnet TEW-805UBH */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4011, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* ELECOM WDB-867DU3S */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0107, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&(rtw8822b_hw_spec) }, /* Mercusys MA30H */
{},
};
MODULE_DEVICE_TABLE(usb, rtw_8822bu_id_table);
diff --git a/drivers/net/wireless/realtek/rtw88/usb.c b/drivers/net/wireless/realtek/rtw88/usb.c
index 8d6db68246f1..be193c7add77 100644
--- a/drivers/net/wireless/realtek/rtw88/usb.c
+++ b/drivers/net/wireless/realtek/rtw88/usb.c
@@ -789,6 +789,30 @@ static void rtw_usb_dynamic_rx_agg_v1(struct rtw_dev *rtwdev, bool enable)
rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH, val16);
}
+static void rtw_usb_dynamic_rx_agg_v2(struct rtw_dev *rtwdev, bool enable)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ u8 size, timeout;
+ u16 val16;
+
+ if (!enable) {
+ size = 0x0;
+ timeout = 0x1;
+ } else if (rtwusb->udev->speed == USB_SPEED_SUPER) {
+ size = 0x6;
+ timeout = 0x1a;
+ } else {
+ size = 0x5;
+ timeout = 0x20;
+ }
+
+ val16 = u16_encode_bits(size, BIT_RXDMA_AGG_PG_TH) |
+ u16_encode_bits(timeout, BIT_DMA_AGG_TO_V1);
+
+ rtw_write16(rtwdev, REG_RXDMA_AGG_PG_TH, val16);
+ rtw_write8_set(rtwdev, REG_TXDMA_PQ_MAP, BIT_RXDMA_AGG_EN);
+}
+
static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable)
{
switch (rtwdev->chip->id) {
@@ -797,6 +821,10 @@ static void rtw_usb_dynamic_rx_agg(struct rtw_dev *rtwdev, bool enable)
case RTW_CHIP_TYPE_8821C:
rtw_usb_dynamic_rx_agg_v1(rtwdev, enable);
break;
+ case RTW_CHIP_TYPE_8821A:
+ case RTW_CHIP_TYPE_8812A:
+ rtw_usb_dynamic_rx_agg_v2(rtwdev, enable);
+ break;
case RTW_CHIP_TYPE_8723D:
/* Doesn't like aggregation. */
break;
@@ -930,6 +958,32 @@ static void rtw_usb_intf_deinit(struct rtw_dev *rtwdev,
usb_set_intfdata(intf, NULL);
}
+static int rtw_usb_switch_mode_old(struct rtw_dev *rtwdev)
+{
+ struct rtw_usb *rtwusb = rtw_get_usb_priv(rtwdev);
+ enum usb_device_speed cur_speed = rtwusb->udev->speed;
+ u8 hci_opt;
+
+ if (cur_speed == USB_SPEED_HIGH) {
+ hci_opt = rtw_read8(rtwdev, REG_HCI_OPT_CTRL);
+
+ if ((hci_opt & (BIT(2) | BIT(3))) != BIT(3)) {
+ rtw_write8(rtwdev, REG_HCI_OPT_CTRL, 0x8);
+ rtw_write8(rtwdev, REG_SYS_SDIO_CTRL, 0x2);
+ rtw_write8(rtwdev, REG_ACLK_MON, 0x1);
+ rtw_write8(rtwdev, 0x3d, 0x3);
+ /* usb disconnect */
+ rtw_write8(rtwdev, REG_SYS_PW_CTRL + 1, 0x80);
+ return 1;
+ }
+ } else if (cur_speed == USB_SPEED_SUPER) {
+ rtw_write8_clr(rtwdev, REG_SYS_SDIO_CTRL, BIT(1));
+ rtw_write8_clr(rtwdev, REG_ACLK_MON, BIT(0));
+ }
+
+ return 0;
+}
+
static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev)
{
enum usb_device_speed cur_speed;
@@ -979,11 +1033,22 @@ static int rtw_usb_switch_mode_new(struct rtw_dev *rtwdev)
return 1;
}
+static bool rtw_usb3_chip_old(u8 chip_id)
+{
+ return chip_id == RTW_CHIP_TYPE_8812A;
+}
+
+static bool rtw_usb3_chip_new(u8 chip_id)
+{
+ return chip_id == RTW_CHIP_TYPE_8822C ||
+ chip_id == RTW_CHIP_TYPE_8822B;
+}
+
static int rtw_usb_switch_mode(struct rtw_dev *rtwdev)
{
u8 id = rtwdev->chip->id;
- if (id != RTW_CHIP_TYPE_8822C && id != RTW_CHIP_TYPE_8822B)
+ if (!rtw_usb3_chip_new(id) && !rtw_usb3_chip_old(id))
return 0;
if (!rtwdev->efuse.usb_mode_switch) {
@@ -998,7 +1063,10 @@ static int rtw_usb_switch_mode(struct rtw_dev *rtwdev)
return 0;
}
- return rtw_usb_switch_mode_new(rtwdev);
+ if (rtw_usb3_chip_old(id))
+ return rtw_usb_switch_mode_old(rtwdev);
+ else
+ return rtw_usb_switch_mode_new(rtwdev);
}
int rtw_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
diff --git a/drivers/net/wireless/realtek/rtw89/acpi.c b/drivers/net/wireless/realtek/rtw89/acpi.c
index 908e980a4b72..f5dedb12c129 100644
--- a/drivers/net/wireless/realtek/rtw89/acpi.c
+++ b/drivers/net/wireless/realtek/rtw89/acpi.c
@@ -148,3 +148,50 @@ int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
ACPI_FREE(obj);
return ret;
}
+
+int rtw89_acpi_evaluate_rtag(struct rtw89_dev *rtwdev,
+ struct rtw89_acpi_rtag_result *res)
+{
+ struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+ acpi_handle root, handle;
+ union acpi_object *obj;
+ acpi_status status;
+ u32 buf_len;
+ int ret = 0;
+
+ root = ACPI_HANDLE(rtwdev->dev);
+ if (!root)
+ return -EOPNOTSUPP;
+
+ status = acpi_get_handle(root, (acpi_string)"RTAG", &handle);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ status = acpi_evaluate_object(handle, NULL, NULL, &buf);
+ if (ACPI_FAILURE(status))
+ return -EIO;
+
+ obj = buf.pointer;
+ if (obj->type != ACPI_TYPE_BUFFER) {
+ rtw89_debug(rtwdev, RTW89_DBG_ACPI,
+ "acpi: expect buffer but type: %d\n", obj->type);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ buf_len = obj->buffer.length;
+ if (buf_len != sizeof(*res)) {
+ rtw89_debug(rtwdev, RTW89_DBG_ACPI, "%s: invalid buffer length: %u\n",
+ __func__, buf_len);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ *res = *(struct rtw89_acpi_rtag_result *)obj->buffer.pointer;
+
+ rtw89_hex_dump(rtwdev, RTW89_DBG_ACPI, "antenna_gain: ", res, sizeof(*res));
+
+out:
+ ACPI_FREE(obj);
+ return ret;
+}
diff --git a/drivers/net/wireless/realtek/rtw89/acpi.h b/drivers/net/wireless/realtek/rtw89/acpi.h
index d274be1775bf..b43ab106e44d 100644
--- a/drivers/net/wireless/realtek/rtw89/acpi.h
+++ b/drivers/net/wireless/realtek/rtw89/acpi.h
@@ -63,8 +63,17 @@ struct rtw89_acpi_dsm_result {
} u;
};
+struct rtw89_acpi_rtag_result {
+ u8 tag[4];
+ u8 revision;
+ __le32 domain;
+ u8 ant_gain_table[RTW89_ANT_GAIN_CHAIN_NUM][RTW89_ANT_GAIN_SUBBAND_NR];
+} __packed;
+
int rtw89_acpi_evaluate_dsm(struct rtw89_dev *rtwdev,
enum rtw89_acpi_dsm_func func,
struct rtw89_acpi_dsm_result *res);
+int rtw89_acpi_evaluate_rtag(struct rtw89_dev *rtwdev,
+ struct rtw89_acpi_rtag_result *res);
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/cam.c b/drivers/net/wireless/realtek/rtw89/cam.c
index 8ef59994c0db..8fa1e6c1ce13 100644
--- a/drivers/net/wireless/realtek/rtw89/cam.c
+++ b/drivers/net/wireless/realtek/rtw89/cam.c
@@ -135,8 +135,8 @@ again:
}
static int rtw89_cam_get_addr_cam_key_idx(struct rtw89_addr_cam_entry *addr_cam,
- struct rtw89_sec_cam_entry *sec_cam,
- struct ieee80211_key_conf *key,
+ const struct rtw89_sec_cam_entry *sec_cam,
+ const struct ieee80211_key_conf *key,
u8 *key_idx)
{
u8 idx;
@@ -246,8 +246,8 @@ static int __rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link,
- struct ieee80211_key_conf *key,
- struct rtw89_sec_cam_entry *sec_cam)
+ const struct ieee80211_key_conf *key,
+ const struct rtw89_sec_cam_entry *sec_cam)
{
struct rtw89_addr_cam_entry *addr_cam;
u8 key_idx = 0;
@@ -286,6 +286,22 @@ static int __rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
return 0;
}
+int rtw89_cam_attach_link_sec_cam(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ u8 sec_cam_idx)
+{
+ struct rtw89_cam_info *cam_info = &rtwdev->cam_info;
+ const struct rtw89_sec_cam_entry *sec_cam;
+
+ sec_cam = cam_info->sec_entries[sec_cam_idx];
+ if (!sec_cam)
+ return -ENOENT;
+
+ return __rtw89_cam_attach_sec_cam(rtwdev, rtwvif_link, rtwsta_link,
+ sec_cam->key_conf, sec_cam);
+}
+
static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -306,6 +322,9 @@ static int rtw89_cam_detach_sec_cam(struct rtw89_dev *rtwdev,
rtwvif = vif_to_rtwvif(vif);
+ if (rtwsta)
+ clear_bit(sec_cam->sec_cam_idx, rtwsta->pairwise_sec_cam_map);
+
rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
rtwsta_link = rtwsta ? rtwsta->links[link_id] : NULL;
if (rtwsta && !rtwsta_link)
@@ -369,6 +388,8 @@ static int rtw89_cam_attach_sec_cam(struct rtw89_dev *rtwdev,
return ret;
}
+ set_bit(sec_cam->sec_cam_idx, rtwsta->pairwise_sec_cam_map);
+
return 0;
}
@@ -410,6 +431,9 @@ static int rtw89_cam_sec_key_install(struct rtw89_dev *rtwdev,
sec_cam->len = RTW89_SEC_CAM_LEN;
sec_cam->ext_key = ext_key;
memcpy(sec_cam->key, key->key, key->keylen);
+
+ sec_cam->key_conf = key;
+
ret = rtw89_cam_send_sec_key_cmd(rtwdev, sec_cam);
if (ret) {
rtw89_err(rtwdev, "failed to send sec key cmd: %d\n", ret);
diff --git a/drivers/net/wireless/realtek/rtw89/cam.h b/drivers/net/wireless/realtek/rtw89/cam.h
index 3134ebf08825..8fd2d776408e 100644
--- a/drivers/net/wireless/realtek/rtw89/cam.h
+++ b/drivers/net/wireless/realtek/rtw89/cam.h
@@ -578,4 +578,9 @@ int rtw89_cam_sec_key_del(struct rtw89_dev *rtwdev,
void rtw89_cam_bssid_changed(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link);
void rtw89_cam_reset_keys(struct rtw89_dev *rtwdev);
+int rtw89_cam_attach_link_sec_cam(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link,
+ struct rtw89_sta_link *rtwsta_link,
+ u8 sec_cam_idx);
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index e5b2968c1431..f848185e2ced 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -203,6 +203,55 @@ static const struct ieee80211_iface_combination rtw89_iface_combs[] = {
},
};
+#define RTW89_6GHZ_SPAN_HEAD 6145
+#define RTW89_6GHZ_SPAN_IDX(center_freq) \
+ ((((int)(center_freq) - RTW89_6GHZ_SPAN_HEAD) / 5) / 2)
+
+#define RTW89_DECL_6GHZ_SPAN(center_freq, subband_l, subband_h) \
+ [RTW89_6GHZ_SPAN_IDX(center_freq)] = { \
+ .sar_subband_low = RTW89_SAR_6GHZ_ ## subband_l, \
+ .sar_subband_high = RTW89_SAR_6GHZ_ ## subband_h, \
+ .ant_gain_subband_low = RTW89_ANT_GAIN_6GHZ_ ## subband_l, \
+ .ant_gain_subband_high = RTW89_ANT_GAIN_6GHZ_ ## subband_h, \
+ }
+
+/* Since 6GHz subbands are not edge aligned, some cases span two subbands.
+ * In the following, we describe each of them with rtw89_6ghz_span.
+ */
+static const struct rtw89_6ghz_span rtw89_overlapping_6ghz[] = {
+ RTW89_DECL_6GHZ_SPAN(6145, SUBBAND_5_L, SUBBAND_5_H),
+ RTW89_DECL_6GHZ_SPAN(6165, SUBBAND_5_L, SUBBAND_5_H),
+ RTW89_DECL_6GHZ_SPAN(6185, SUBBAND_5_L, SUBBAND_5_H),
+ RTW89_DECL_6GHZ_SPAN(6505, SUBBAND_6, SUBBAND_7_L),
+ RTW89_DECL_6GHZ_SPAN(6525, SUBBAND_6, SUBBAND_7_L),
+ RTW89_DECL_6GHZ_SPAN(6545, SUBBAND_6, SUBBAND_7_L),
+ RTW89_DECL_6GHZ_SPAN(6665, SUBBAND_7_L, SUBBAND_7_H),
+ RTW89_DECL_6GHZ_SPAN(6705, SUBBAND_7_L, SUBBAND_7_H),
+ RTW89_DECL_6GHZ_SPAN(6825, SUBBAND_7_H, SUBBAND_8),
+ RTW89_DECL_6GHZ_SPAN(6865, SUBBAND_7_H, SUBBAND_8),
+ RTW89_DECL_6GHZ_SPAN(6875, SUBBAND_7_H, SUBBAND_8),
+ RTW89_DECL_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8),
+};
+
+const struct rtw89_6ghz_span *
+rtw89_get_6ghz_span(struct rtw89_dev *rtwdev, u32 center_freq)
+{
+ int idx;
+
+ if (center_freq >= RTW89_6GHZ_SPAN_HEAD) {
+ idx = RTW89_6GHZ_SPAN_IDX(center_freq);
+ /* To decrease size of rtw89_overlapping_6ghz[],
+ * RTW89_6GHZ_SPAN_IDX() truncates the leading NULLs
+ * to make first span as index 0 of the table. So, if center
+ * frequency is less than the first one, it will get netative.
+ */
+ if (idx >= 0 && idx < ARRAY_SIZE(rtw89_overlapping_6ghz))
+ return &rtw89_overlapping_6ghz[idx];
+ }
+
+ return NULL;
+}
+
bool rtw89_ra_report_to_bitrate(struct rtw89_dev *rtwdev, u8 rpt_rate, u16 *bitrate)
{
struct ieee80211_rate rate;
@@ -2140,6 +2189,8 @@ static void rtw89_vif_rx_stats_iter(void *data, u8 *mac,
if (phy_ppdu)
ewma_rssi_add(&rtwdev->phystat.bcn_rssi, phy_ppdu->rssi_avg);
+
+ pkt_stat->beacon_rate = desc_info->data_rate;
}
if (!ether_addr_equal(bss_conf->addr, hdr->addr1))
@@ -2317,6 +2368,12 @@ static void rtw89_core_update_radiotap(struct rtw89_dev *rtwdev,
}
}
+static void rtw89_core_validate_rx_signal(struct ieee80211_rx_status *rx_status)
+{
+ if (!rx_status->signal)
+ rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
+}
+
static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu,
struct rtw89_rx_desc_info *desc_info,
@@ -2333,6 +2390,8 @@ static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev,
rtw89_core_rx_stats(rtwdev, phy_ppdu, desc_info, skb_ppdu);
rtw89_core_update_rx_status_by_ppdu(rtwdev, rx_status, phy_ppdu);
rtw89_core_update_radiotap(rtwdev, skb_ppdu, rx_status);
+ rtw89_core_validate_rx_signal(rx_status);
+
/* In low power mode, it does RX in thread context. */
local_bh_disable();
ieee80211_rx_napi(rtwdev->hw, NULL, skb_ppdu, napi);
@@ -2468,6 +2527,7 @@ void rtw89_core_query_rxdesc_v2(struct rtw89_dev *rtwdev,
struct rtw89_rx_desc_info *desc_info,
u8 *data, u32 data_offset)
{
+ struct rtw89_rxdesc_phy_rpt_v2 *rxd_rpt;
struct rtw89_rxdesc_short_v2 *rxd_s;
struct rtw89_rxdesc_long_v2 *rxd_l;
u16 shift_len, drv_info_len, phy_rtp_len, hdr_cnv_len;
@@ -2515,6 +2575,12 @@ void rtw89_core_query_rxdesc_v2(struct rtw89_dev *rtwdev,
desc_info->rxd_len = sizeof(struct rtw89_rxdesc_short_v2);
desc_info->ready = true;
+ if (phy_rtp_len == sizeof(*rxd_rpt)) {
+ rxd_rpt = (struct rtw89_rxdesc_phy_rpt_v2 *)(data + data_offset +
+ desc_info->rxd_len);
+ desc_info->rssi = le32_get_bits(rxd_rpt->dword0, BE_RXD_PHY_RSSI);
+ }
+
if (!desc_info->long_rxdesc)
return;
@@ -2657,6 +2723,7 @@ static void rtw89_core_update_rx_status(struct rtw89_dev *rtwdev,
rx_status->flag |= RX_FLAG_MACTIME_START;
rx_status->mactime = desc_info->free_run_cnt;
+ rtw89_chip_phy_rpt_to_rssi(rtwdev, desc_info, rx_status);
rtw89_core_stats_sta_rx_status(rtwdev, desc_info, rx_status);
}
@@ -2664,10 +2731,6 @@ static enum rtw89_ps_mode rtw89_update_ps_mode(struct rtw89_dev *rtwdev)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- /* FIXME: Fix __rtw89_enter_ps_mode() to consider MLO cases. */
- if (rtwdev->support_mlo)
- return RTW89_PS_MODE_NONE;
-
if (rtw89_disable_ps_mode || !chip->ps_mode_supported ||
RTW89_CHK_FW_FEATURE(NO_DEEP_PS, &rtwdev->fw))
return RTW89_PS_MODE_NONE;
@@ -2700,6 +2763,41 @@ static void rtw89_core_flush_ppdu_rx_queue(struct rtw89_dev *rtwdev,
}
}
+static
+void rtw89_core_rx_pkt_hdl(struct rtw89_dev *rtwdev, const struct sk_buff *skb,
+ const struct rtw89_rx_desc_info *desc)
+{
+ struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ struct rtw89_sta_link *rtwsta_link;
+ struct ieee80211_sta *sta;
+ struct rtw89_sta *rtwsta;
+ u8 macid = desc->mac_id;
+
+ if (!refcount_read(&rtwdev->refcount_ap_info))
+ return;
+
+ rcu_read_lock();
+
+ rtwsta_link = rtw89_assoc_link_rcu_dereference(rtwdev, macid);
+ if (!rtwsta_link)
+ goto out;
+
+ rtwsta = rtwsta_link->rtwsta;
+ if (!test_bit(RTW89_REMOTE_STA_IN_PS, rtwsta->flags))
+ goto out;
+
+ sta = rtwsta_to_sta(rtwsta);
+ if (ieee80211_is_pspoll(hdr->frame_control))
+ ieee80211_sta_pspoll(sta);
+ else if (ieee80211_has_pm(hdr->frame_control) &&
+ (ieee80211_is_data_qos(hdr->frame_control) ||
+ ieee80211_is_qos_nullfunc(hdr->frame_control)))
+ ieee80211_sta_uapsd_trigger(sta, ieee80211_get_tid(hdr));
+
+out:
+ rcu_read_unlock();
+}
+
void rtw89_core_rx(struct rtw89_dev *rtwdev,
struct rtw89_rx_desc_info *desc_info,
struct sk_buff *skb)
@@ -2722,6 +2820,7 @@ void rtw89_core_rx(struct rtw89_dev *rtwdev,
rx_status = IEEE80211_SKB_RXCB(skb);
memset(rx_status, 0, sizeof(*rx_status));
rtw89_core_update_rx_status(rtwdev, desc_info, rx_status);
+ rtw89_core_rx_pkt_hdl(rtwdev, skb, desc_info);
if (desc_info->long_rxdesc &&
BIT(desc_info->frame_type) & PPDU_FILTER_BITMAP)
skb_queue_tail(&ppdu_sts->rx_queue[band], skb);
@@ -3131,6 +3230,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link, bool qos, bool ps)
{
struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ int link_id = ieee80211_vif_is_mld(vif) ? rtwvif_link->link_id : -1;
struct ieee80211_sta *sta;
struct ieee80211_hdr *hdr;
struct sk_buff *skb;
@@ -3146,7 +3246,7 @@ static int rtw89_core_send_nullfunc(struct rtw89_dev *rtwdev,
goto out;
}
- skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, qos);
+ skb = ieee80211_nullfunc_get(rtwdev->hw, vif, link_id, qos);
if (!skb) {
ret = -ENOMEM;
goto out;
@@ -3367,21 +3467,10 @@ static bool rtw89_traffic_stats_track(struct rtw89_dev *rtwdev)
return tfc_changed;
}
-static void rtw89_vif_enter_lps(struct rtw89_dev *rtwdev,
- struct rtw89_vif_link *rtwvif_link)
-{
- if (rtwvif_link->wifi_role != RTW89_WIFI_ROLE_STATION &&
- rtwvif_link->wifi_role != RTW89_WIFI_ROLE_P2P_CLIENT)
- return;
-
- rtw89_enter_lps(rtwdev, rtwvif_link, true);
-}
-
static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev)
{
- struct rtw89_vif_link *rtwvif_link;
+ struct ieee80211_vif *vif;
struct rtw89_vif *rtwvif;
- unsigned int link_id;
rtw89_for_each_rtwvif(rtwdev, rtwvif) {
if (rtwvif->tdls_peer)
@@ -3393,8 +3482,13 @@ static void rtw89_enter_lps_track(struct rtw89_dev *rtwdev)
rtwvif->stats.rx_tfc_lv != RTW89_TFC_IDLE)
continue;
- rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
- rtw89_vif_enter_lps(rtwdev, rtwvif_link);
+ vif = rtwvif_to_vif(rtwvif);
+
+ if (!(vif->type == NL80211_IFTYPE_STATION ||
+ vif->type == NL80211_IFTYPE_P2P_CLIENT))
+ continue;
+
+ rtw89_enter_lps(rtwdev, rtwvif, true);
}
}
@@ -3699,6 +3793,8 @@ int rtw89_core_sta_link_disassoc(struct rtw89_dev *rtwdev,
{
const struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ rtw89_assoc_link_clr(rtwsta_link);
+
if (vif->type == NL80211_IFTYPE_STATION)
rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, false);
@@ -3748,6 +3844,22 @@ int rtw89_core_sta_link_disconnect(struct rtw89_dev *rtwdev,
return ret;
}
+static bool rtw89_sta_link_can_er(struct rtw89_dev *rtwdev,
+ struct ieee80211_bss_conf *bss_conf,
+ struct ieee80211_link_sta *link_sta)
+{
+ if (!bss_conf->he_support ||
+ bss_conf->he_oper.params & IEEE80211_HE_OPERATION_ER_SU_DISABLE)
+ return false;
+
+ if (rtwdev->chip->chip_id == RTL8852C &&
+ rtw89_sta_link_has_su_mu_4xhe08(link_sta) &&
+ !rtw89_sta_link_has_er_su_4xhe08(link_sta))
+ return false;
+
+ return true;
+}
+
int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
struct rtw89_sta_link *rtwsta_link)
@@ -3758,12 +3870,11 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
rtwsta_link);
const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
rtwvif_link->chanctx_idx);
+ struct ieee80211_link_sta *link_sta;
int ret;
if (vif->type == NL80211_IFTYPE_AP || sta->tdls) {
if (sta->tdls) {
- struct ieee80211_link_sta *link_sta;
-
rcu_read_lock();
link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
@@ -3814,9 +3925,8 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
rcu_read_lock();
bss_conf = rtw89_vif_rcu_dereference_link(rtwvif_link, true);
- if (bss_conf->he_support &&
- !(bss_conf->he_oper.params & IEEE80211_HE_OPERATION_ER_SU_DISABLE))
- rtwsta_link->er_cap = true;
+ link_sta = rtw89_sta_rcu_dereference_link(rtwsta_link, true);
+ rtwsta_link->er_cap = rtw89_sta_link_can_er(rtwdev, bss_conf, link_sta);
rcu_read_unlock();
@@ -3834,6 +3944,7 @@ int rtw89_core_sta_link_assoc(struct rtw89_dev *rtwdev,
rtw89_fw_h2c_set_bcn_fltr_cfg(rtwdev, rtwvif_link, true);
}
+ rtw89_assoc_link_set(rtwsta_link);
return ret;
}
@@ -4433,6 +4544,7 @@ int rtw89_core_start(struct rtw89_dev *rtwdev)
rtw89_phy_dm_init(rtwdev);
rtw89_mac_cfg_ppdu_status_bands(rtwdev, true);
+ rtw89_mac_cfg_phy_rpt_bands(rtwdev, true);
rtw89_mac_update_rts_threshold(rtwdev);
rtw89_tas_reset(rtwdev);
@@ -4755,6 +4867,7 @@ int rtw89_core_init(struct rtw89_dev *rtwdev)
rtw89_ser_init(rtwdev);
rtw89_entity_init(rtwdev);
rtw89_tas_init(rtwdev);
+ rtw89_phy_ant_gain_init(rtwdev);
return 0;
}
@@ -5100,6 +5213,9 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
if (RTW89_CHK_FW_FEATURE(BEACON_FILTER, &rtwdev->fw))
ieee80211_hw_set(hw, CONNECTION_MONITOR);
+ if (RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &rtwdev->fw))
+ ieee80211_hw_set(hw, AP_LINK_PS);
+
hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 5ad32eacd0d5..155538370a89 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -830,6 +830,7 @@ enum rtw89_phy_idx {
};
#define __RTW89_MLD_MAX_LINK_NUM 2
+#define RTW89_MLD_NON_STA_LINK_NUM 1
enum rtw89_chanctx_idx {
RTW89_CHANCTX_0 = 0,
@@ -1083,6 +1084,7 @@ struct rtw89_rx_desc_info {
u16 offset;
u16 rxd_len;
bool ready;
+ u16 rssi;
};
struct rtw89_rxdesc_short {
@@ -1125,6 +1127,11 @@ struct rtw89_rxdesc_long_v2 {
__le32 dword9;
} __packed;
+struct rtw89_rxdesc_phy_rpt_v2 {
+ __le32 dword0;
+ __le32 dword1;
+} __packed;
+
struct rtw89_tx_desc_info {
u16 pkt_size;
u8 wp_offset;
@@ -3358,6 +3365,8 @@ struct rtw89_sec_cam_entry {
u8 spp_mode : 1;
/* 256 bits */
u8 key[32];
+
+ struct ieee80211_key_conf *key_conf;
};
struct rtw89_sta_link {
@@ -3621,6 +3630,9 @@ struct rtw89_chip_ops {
struct ieee80211_rx_status *status);
void (*convert_rpl_to_rssi)(struct rtw89_dev *rtwdev,
struct rtw89_rx_phy_ppdu *phy_ppdu);
+ void (*phy_rpt_to_rssi)(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_desc_info *desc_info,
+ struct ieee80211_rx_status *rx_status);
void (*ctrl_nbtg_bt_tx)(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx);
void (*cfg_txrx_path)(struct rtw89_dev *rtwdev);
@@ -4255,6 +4267,7 @@ struct rtw89_chip_info {
u16 support_bandwidths;
bool support_unii4;
bool support_rnr;
+ bool support_ant_gain;
bool ul_tb_waveform_ctrl;
bool ul_tb_pwr_diff;
bool hw_sec_hdr;
@@ -4296,6 +4309,7 @@ struct rtw89_chip_info {
const struct rtw89_rfe_parms *dflt_parms;
const struct rtw89_chanctx_listener *chanctx_listener;
+ u8 txpwr_factor_bb;
u8 txpwr_factor_rf;
u8 txpwr_factor_mac;
@@ -4448,8 +4462,12 @@ enum rtw89_fw_feature {
RTW89_FW_FEATURE_SCAN_OFFLOAD_BE_V0,
RTW89_FW_FEATURE_WOW_REASON_V1,
RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V0,
+ RTW89_FW_FEATURE_RFK_PRE_NOTIFY_V1,
RTW89_FW_FEATURE_RFK_RXDCK_V0,
RTW89_FW_FEATURE_NO_WOW_CPU_IO_RX,
+ RTW89_FW_FEATURE_NOTIFY_AP_INFO,
+ RTW89_FW_FEATURE_CH_INFO_BE_V0,
+ RTW89_FW_FEATURE_LPS_CH_INFO,
};
struct rtw89_fw_suit {
@@ -4597,6 +4615,44 @@ struct rtw89_sar_info {
};
};
+enum rtw89_ant_gain_subband {
+ RTW89_ANT_GAIN_2GHZ_SUBBAND,
+ RTW89_ANT_GAIN_5GHZ_SUBBAND_1, /* U-NII-1 */
+ RTW89_ANT_GAIN_5GHZ_SUBBAND_2, /* U-NII-2 */
+ RTW89_ANT_GAIN_5GHZ_SUBBAND_2E, /* U-NII-2-Extended */
+ RTW89_ANT_GAIN_5GHZ_SUBBAND_3_4, /* U-NII-3 and U-NII-4 */
+ RTW89_ANT_GAIN_6GHZ_SUBBAND_5_L, /* U-NII-5 lower part */
+ RTW89_ANT_GAIN_6GHZ_SUBBAND_5_H, /* U-NII-5 higher part */
+ RTW89_ANT_GAIN_6GHZ_SUBBAND_6, /* U-NII-6 */
+ RTW89_ANT_GAIN_6GHZ_SUBBAND_7_L, /* U-NII-7 lower part */
+ RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H, /* U-NII-7 higher part */
+ RTW89_ANT_GAIN_6GHZ_SUBBAND_8, /* U-NII-8 */
+
+ RTW89_ANT_GAIN_SUBBAND_NR,
+};
+
+enum rtw89_ant_gain_domain_type {
+ RTW89_ANT_GAIN_ETSI = 0,
+
+ RTW89_ANT_GAIN_DOMAIN_NUM,
+};
+
+#define RTW89_ANT_GAIN_CHAIN_NUM 2
+struct rtw89_ant_gain_info {
+ s8 offset[RTW89_ANT_GAIN_CHAIN_NUM][RTW89_ANT_GAIN_SUBBAND_NR];
+ u32 regd_enabled;
+};
+
+struct rtw89_6ghz_span {
+ enum rtw89_sar_subband sar_subband_low;
+ enum rtw89_sar_subband sar_subband_high;
+ enum rtw89_ant_gain_subband ant_gain_subband_low;
+ enum rtw89_ant_gain_subband ant_gain_subband_high;
+};
+
+#define RTW89_SAR_SPAN_VALID(span) ((span)->sar_subband_high)
+#define RTW89_ANT_GAIN_SPAN_VALID(span) ((span)->ant_gain_subband_high)
+
enum rtw89_tas_state {
RTW89_TAS_STATE_DPR_OFF,
RTW89_TAS_STATE_DPR_ON,
@@ -4781,6 +4837,7 @@ struct rtw89_pkt_drop_params {
struct rtw89_pkt_stat {
u16 beacon_nr;
+ u8 beacon_rate;
u32 rx_rate_cnt[RTW89_HW_RATE_NR];
};
@@ -5556,6 +5613,9 @@ struct rtw89_dev {
struct rtw89_rfe_data *rfe_data;
enum rtw89_custid custid;
+ struct rtw89_sta_link __rcu *assoc_link_on_macid[RTW89_MAX_MAC_ID_NUM];
+ refcount_t refcount_ap_info;
+
/* ensures exclusive access from mac80211 callbacks */
struct mutex mutex;
struct list_head rtwvifs_list;
@@ -5636,6 +5696,7 @@ struct rtw89_dev {
struct rtw89_regulatory_info regulatory;
struct rtw89_sar_info sar;
struct rtw89_tas_info tas;
+ struct rtw89_ant_gain_info ant_gain;
struct rtw89_btc btc;
enum rtw89_ps_mode ps_mode;
@@ -5654,10 +5715,17 @@ struct rtw89_dev {
u8 priv[] __aligned(sizeof(void *));
};
+struct rtw89_link_conf_container {
+ struct ieee80211_bss_conf *link_conf[IEEE80211_MLD_MAX_NUM_LINKS];
+};
+
+#define RTW89_VIF_IDLE_LINK_ID 0
+
struct rtw89_vif {
struct rtw89_dev *rtwdev;
struct list_head list;
struct list_head mgnt_entry;
+ struct rtw89_link_conf_container __rcu *snap_link_confs;
u8 mac_addr[ETH_ALEN];
__be32 ip_addr;
@@ -5689,10 +5757,18 @@ static inline bool rtw89_vif_assign_link_is_valid(struct rtw89_vif_link **rtwvif
for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) \
if (rtw89_vif_assign_link_is_valid(&(rtwvif_link), rtwvif, link_id))
+enum rtw89_sta_flags {
+ RTW89_REMOTE_STA_IN_PS,
+
+ NUM_OF_RTW89_STA_FLAGS,
+};
+
struct rtw89_sta {
struct rtw89_dev *rtwdev;
struct rtw89_vif *rtwvif;
+ DECLARE_BITMAP(flags, NUM_OF_RTW89_STA_FLAGS);
+
bool disassoc;
struct sk_buff_head roc_queue;
@@ -5700,6 +5776,8 @@ struct rtw89_sta {
struct rtw89_ampdu_params ampdu_params[IEEE80211_NUM_TIDS];
DECLARE_BITMAP(ampdu_map, IEEE80211_NUM_TIDS);
+ DECLARE_BITMAP(pairwise_sec_cam_map, RTW89_MAX_SEC_CAM_NUM);
+
u8 links_inst_valid_num;
DECLARE_BITMAP(links_inst_map, __RTW89_MLD_MAX_LINK_NUM);
struct rtw89_sta_link *links[IEEE80211_MLD_MAX_NUM_LINKS];
@@ -5770,6 +5848,31 @@ u8 rtw89_sta_link_inst_get_index(struct rtw89_sta_link *rtwsta_link)
return rtwsta_link - rtwsta->links_inst;
}
+static inline void rtw89_assoc_link_set(struct rtw89_sta_link *rtwsta_link)
+{
+ struct rtw89_sta *rtwsta = rtwsta_link->rtwsta;
+ struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+
+ rcu_assign_pointer(rtwdev->assoc_link_on_macid[rtwsta_link->mac_id],
+ rtwsta_link);
+}
+
+static inline void rtw89_assoc_link_clr(struct rtw89_sta_link *rtwsta_link)
+{
+ struct rtw89_sta *rtwsta = rtwsta_link->rtwsta;
+ struct rtw89_dev *rtwdev = rtwsta->rtwdev;
+
+ rcu_assign_pointer(rtwdev->assoc_link_on_macid[rtwsta_link->mac_id],
+ NULL);
+ synchronize_rcu();
+}
+
+static inline struct rtw89_sta_link *
+rtw89_assoc_link_rcu_dereference(struct rtw89_dev *rtwdev, u8 macid)
+{
+ return rcu_dereference(rtwdev->assoc_link_on_macid[macid]);
+}
+
static inline int rtw89_hci_tx_write(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request *tx_req)
{
@@ -6194,9 +6297,19 @@ static inline struct ieee80211_bss_conf *
__rtw89_vif_rcu_dereference_link(struct rtw89_vif_link *rtwvif_link, bool *nolink)
{
struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ struct rtw89_vif *rtwvif = rtwvif_link->rtwvif;
+ struct rtw89_link_conf_container *snap;
struct ieee80211_bss_conf *bss_conf;
+ snap = rcu_dereference(rtwvif->snap_link_confs);
+ if (snap) {
+ bss_conf = snap->link_conf[rtwvif_link->link_id];
+ goto out;
+ }
+
bss_conf = rcu_dereference(vif->link_conf[rtwvif_link->link_id]);
+
+out:
if (unlikely(!bss_conf)) {
*nolink = true;
return &vif->bss_conf;
@@ -6605,6 +6718,16 @@ static inline void rtw89_chip_convert_rpl_to_rssi(struct rtw89_dev *rtwdev,
chip->ops->convert_rpl_to_rssi(rtwdev, phy_ppdu);
}
+static inline void rtw89_chip_phy_rpt_to_rssi(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_desc_info *desc_info,
+ struct ieee80211_rx_status *rx_status)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ if (chip->ops->phy_rpt_to_rssi)
+ chip->ops->phy_rpt_to_rssi(rtwdev, desc_info, rx_status);
+}
+
static inline void rtw89_ctrl_nbtg_bt_tx(struct rtw89_dev *rtwdev, bool en,
enum rtw89_phy_idx phy_idx)
{
@@ -6753,6 +6876,26 @@ bool rtw89_sta_has_beamformer_cap(struct ieee80211_link_sta *link_sta)
return false;
}
+static inline
+bool rtw89_sta_link_has_su_mu_4xhe08(struct ieee80211_link_sta *link_sta)
+{
+ if (link_sta->he_cap.he_cap_elem.phy_cap_info[7] &
+ IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI)
+ return true;
+
+ return false;
+}
+
+static inline
+bool rtw89_sta_link_has_er_su_4xhe08(struct ieee80211_link_sta *link_sta)
+{
+ if (link_sta->he_cap.he_cap_elem.phy_cap_info[8] &
+ IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI)
+ return true;
+
+ return false;
+}
+
static inline struct rtw89_fw_suit *rtw89_fw_suit_get(struct rtw89_dev *rtwdev,
enum rtw89_fw_type type)
{
@@ -6908,6 +7051,8 @@ struct rtw89_sta_link *rtw89_sta_set_link(struct rtw89_sta *rtwsta,
unsigned int link_id);
void rtw89_sta_unset_link(struct rtw89_sta *rtwsta, unsigned int link_id);
void rtw89_core_set_chip_txpwr(struct rtw89_dev *rtwdev);
+const struct rtw89_6ghz_span *
+rtw89_get_6ghz_span(struct rtw89_dev *rtwdev, u32 center_freq);
void rtw89_get_default_chandef(struct cfg80211_chan_def *chandef);
void rtw89_get_channel_params(const struct cfg80211_chan_def *chandef,
struct rtw89_chan *chan);
diff --git a/drivers/net/wireless/realtek/rtw89/debug.c b/drivers/net/wireless/realtek/rtw89/debug.c
index 6abd88fa80ba..fd86752d86f3 100644
--- a/drivers/net/wireless/realtek/rtw89/debug.c
+++ b/drivers/net/wireless/realtek/rtw89/debug.c
@@ -9,6 +9,7 @@
#include "fw.h"
#include "mac.h"
#include "pci.h"
+#include "phy.h"
#include "ps.h"
#include "reg.h"
#include "sar.h"
@@ -882,6 +883,9 @@ static int rtw89_debug_priv_txpwr_table_get(struct seq_file *m, void *v)
seq_puts(m, "[TAS]\n");
rtw89_print_tas(m, rtwdev);
+ seq_puts(m, "[DAG]\n");
+ rtw89_print_ant_gain(m, rtwdev, chan);
+
tbl = dbgfs_txpwr_tables[chip_gen];
if (!tbl) {
ret = -EOPNOTSUPP;
diff --git a/drivers/net/wireless/realtek/rtw89/fw.c b/drivers/net/wireless/realtek/rtw89/fw.c
index 2191c037d72e..90db15685728 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.c
+++ b/drivers/net/wireless/realtek/rtw89/fw.c
@@ -709,11 +709,13 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 26, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, CRASH_TRIGGER),
__CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 0, SCAN_OFFLOAD),
+ __CFG_FW_FEAT(RTL8852B, ge, 0, 29, 29, 7, BEACON_FILTER),
__CFG_FW_FEAT(RTL8852B, lt, 0, 29, 30, 0, NO_WOW_CPU_IO_RX),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, NO_LPS_PG),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 74, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 90, 0, CRASH_TRIGGER),
__CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 91, 0, SCAN_OFFLOAD),
+ __CFG_FW_FEAT(RTL8852BT, ge, 0, 29, 110, 0, BEACON_FILTER),
__CFG_FW_FEAT(RTL8852C, le, 0, 27, 33, 0, NO_DEEP_PS),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 34, 0, TX_WAKE),
__CFG_FW_FEAT(RTL8852C, ge, 0, 27, 36, 0, SCAN_OFFLOAD),
@@ -727,7 +729,11 @@ static const struct __fw_feat_cfg fw_feat_tbl[] = {
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 12, 0, BEACON_FILTER),
__CFG_FW_FEAT(RTL8922A, ge, 0, 35, 22, 0, WOW_REASON_V1),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, RFK_PRE_NOTIFY_V0),
+ __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 31, 0, LPS_CH_INFO),
__CFG_FW_FEAT(RTL8922A, lt, 0, 35, 42, 0, RFK_RXDCK_V0),
+ __CFG_FW_FEAT(RTL8922A, ge, 0, 35, 46, 0, NOTIFY_AP_INFO),
+ __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 47, 0, CH_INFO_BE_V0),
+ __CFG_FW_FEAT(RTL8922A, lt, 0, 35, 49, 0, RFK_PRE_NOTIFY_V1),
};
static void rtw89_fw_iterate_feature_cfg(struct rtw89_fw_info *fw,
@@ -2414,6 +2420,7 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev,
u8 *id)
{
struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
+ int link_id = ieee80211_vif_is_mld(vif) ? rtwvif_link->link_id : -1;
struct rtw89_pktofld_info *info;
struct sk_buff *skb;
int ret;
@@ -2430,10 +2437,10 @@ static int rtw89_fw_h2c_add_general_pkt(struct rtw89_dev *rtwdev,
skb = ieee80211_proberesp_get(rtwdev->hw, vif);
break;
case RTW89_PKT_OFLD_TYPE_NULL_DATA:
- skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, false);
+ skb = ieee80211_nullfunc_get(rtwdev->hw, vif, link_id, false);
break;
case RTW89_PKT_OFLD_TYPE_QOS_NULL:
- skb = ieee80211_nullfunc_get(rtwdev->hw, vif, -1, true);
+ skb = ieee80211_nullfunc_get(rtwdev->hw, vif, link_id, true);
break;
case RTW89_PKT_OFLD_TYPE_EAPOL_KEY:
skb = rtw89_eapol_get(rtwdev, rtwvif_link);
@@ -2589,14 +2596,17 @@ fail:
return ret;
}
-int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
+int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif)
{
- const struct rtw89_chan *chan = rtw89_chan_get(rtwdev,
- rtwvif_link->chanctx_idx);
const struct rtw89_chip_info *chip = rtwdev->chip;
+ const struct rtw89_chan *chan;
+ struct rtw89_vif_link *rtwvif_link;
struct rtw89_h2c_lps_ch_info *h2c;
u32 len = sizeof(*h2c);
+ unsigned int link_id;
struct sk_buff *skb;
+ bool no_chan = true;
+ u8 phy_idx;
u32 done;
int ret;
@@ -2611,11 +2621,27 @@ int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rt
skb_put(skb, len);
h2c = (struct rtw89_h2c_lps_ch_info *)skb->data;
- h2c->info[0].central_ch = chan->channel;
- h2c->info[0].pri_ch = chan->primary_channel;
- h2c->info[0].band = chan->band_type;
- h2c->info[0].bw = chan->band_width;
- h2c->mlo_dbcc_mode_lps = cpu_to_le32(MLO_2_PLUS_0_1RF);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+ phy_idx = rtwvif_link->phy_idx;
+ if (phy_idx >= ARRAY_SIZE(h2c->info))
+ continue;
+
+ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+ no_chan = false;
+
+ h2c->info[phy_idx].central_ch = chan->channel;
+ h2c->info[phy_idx].pri_ch = chan->primary_channel;
+ h2c->info[phy_idx].band = chan->band_type;
+ h2c->info[phy_idx].bw = chan->band_width;
+ }
+
+ if (no_chan) {
+ rtw89_err(rtwdev, "no chan for h2c lps_ch_info\n");
+ ret = -ENOENT;
+ goto fail;
+ }
+
+ h2c->mlo_dbcc_mode_lps = cpu_to_le32(rtwdev->mlo_dbcc_mode);
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_OUTSRC, H2C_CL_OUTSRC_DM,
@@ -2640,6 +2666,87 @@ fail:
return ret;
}
+int rtw89_fw_h2c_lps_ml_cmn_info(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif)
+{
+ const struct rtw89_phy_bb_gain_info_be *gain = &rtwdev->bb_gain.be;
+ struct rtw89_pkt_stat *pkt_stat = &rtwdev->phystat.cur_pkt_stat;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_h2c_lps_ml_cmn_info *h2c;
+ struct rtw89_vif_link *rtwvif_link;
+ const struct rtw89_chan *chan;
+ u8 bw_idx = RTW89_BB_BW_20_40;
+ u32 len = sizeof(*h2c);
+ unsigned int link_id;
+ struct sk_buff *skb;
+ u8 gain_band;
+ u32 done;
+ u8 path;
+ int ret;
+ int i;
+
+ if (chip->chip_gen != RTW89_CHIP_BE)
+ return 0;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for h2c lps_ml_cmn_info\n");
+ return -ENOMEM;
+ }
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_lps_ml_cmn_info *)skb->data;
+
+ h2c->fmt_id = 0x1;
+
+ h2c->mlo_dbcc_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
+
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+ path = rtwvif_link->phy_idx == RTW89_PHY_1 ? RF_PATH_B : RF_PATH_A;
+ chan = rtw89_chan_get(rtwdev, rtwvif_link->chanctx_idx);
+ gain_band = rtw89_subband_to_gain_band_be(chan->subband_type);
+
+ h2c->central_ch[rtwvif_link->phy_idx] = chan->channel;
+ h2c->pri_ch[rtwvif_link->phy_idx] = chan->primary_channel;
+ h2c->band[rtwvif_link->phy_idx] = chan->band_type;
+ h2c->bw[rtwvif_link->phy_idx] = chan->band_width;
+ if (pkt_stat->beacon_rate < RTW89_HW_RATE_OFDM6)
+ h2c->bcn_rate_type[rtwvif_link->phy_idx] = 0x1;
+ else
+ h2c->bcn_rate_type[rtwvif_link->phy_idx] = 0x2;
+
+ /* Fill BW20 RX gain table for beacon mode */
+ for (i = 0; i < TIA_GAIN_NUM; i++) {
+ h2c->tia_gain[rtwvif_link->phy_idx][i] =
+ cpu_to_le16(gain->tia_gain[gain_band][bw_idx][path][i]);
+ }
+ memcpy(h2c->lna_gain[rtwvif_link->phy_idx],
+ gain->lna_gain[gain_band][bw_idx][path],
+ LNA_GAIN_NUM);
+ }
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_OUTSRC, H2C_CL_OUTSRC_DM,
+ H2C_FUNC_FW_LPS_ML_CMN_INFO, 0, 0, len);
+
+ rtw89_phy_write32_mask(rtwdev, R_CHK_LPS_STAT, B_CHK_LPS_STAT, 0);
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ goto fail;
+ }
+
+ ret = read_poll_timeout(rtw89_phy_read32_mask, done, done, 50, 5000,
+ true, rtwdev, R_CHK_LPS_STAT, B_CHK_LPS_STAT);
+ if (ret)
+ rtw89_warn(rtwdev, "h2c_lps_ml_cmn_info done polling timeout\n");
+
+ return 0;
+fail:
+ dev_kfree_skb_any(skb);
+
+ return ret;
+}
+
#define H2C_P2P_ACT_LEN 20
int rtw89_fw_h2c_p2p_act(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link,
@@ -4954,13 +5061,14 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num,
struct rtw89_wait_info *wait = &rtwdev->mac.fw_ofld_wait;
struct rtw89_h2c_chinfo_elem_be *elem;
struct rtw89_mac_chinfo_be *ch_info;
- struct rtw89_h2c_chinfo *h2c;
+ struct rtw89_h2c_chinfo_be *h2c;
struct sk_buff *skb;
unsigned int cond;
+ u8 ver = U8_MAX;
int skb_len;
int ret;
- static_assert(sizeof(*elem) == RTW89_MAC_CHINFO_SIZE);
+ static_assert(sizeof(*elem) == RTW89_MAC_CHINFO_SIZE_BE);
skb_len = struct_size(h2c, elem, ch_num);
skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, skb_len);
@@ -4969,8 +5077,11 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num,
return -ENOMEM;
}
+ if (RTW89_CHK_FW_FEATURE(CH_INFO_BE_V0, &rtwdev->fw))
+ ver = 0;
+
skb_put(skb, sizeof(*h2c));
- h2c = (struct rtw89_h2c_chinfo *)skb->data;
+ h2c = (struct rtw89_h2c_chinfo_be *)skb->data;
h2c->ch_num = ch_num;
h2c->elem_size = sizeof(*elem) / 4; /* in unit of 4 bytes */
@@ -4980,8 +5091,7 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num,
list_for_each_entry(ch_info, chan_list, list) {
elem = (struct rtw89_h2c_chinfo_elem_be *)skb_put(skb, sizeof(*elem));
- elem->w0 = le32_encode_bits(ch_info->period, RTW89_H2C_CHINFO_BE_W0_PERIOD) |
- le32_encode_bits(ch_info->dwell_time, RTW89_H2C_CHINFO_BE_W0_DWELL) |
+ elem->w0 = le32_encode_bits(ch_info->dwell_time, RTW89_H2C_CHINFO_BE_W0_DWELL) |
le32_encode_bits(ch_info->central_ch,
RTW89_H2C_CHINFO_BE_W0_CENTER_CH) |
le32_encode_bits(ch_info->pri_ch, RTW89_H2C_CHINFO_BE_W0_PRI_CH);
@@ -5028,6 +5138,12 @@ int rtw89_fw_h2c_scan_list_offload_be(struct rtw89_dev *rtwdev, int ch_num,
RTW89_H2C_CHINFO_BE_W6_FW_PROBE0_SHORTSSIDS) |
le32_encode_bits(ch_info->fw_probe0_bssids,
RTW89_H2C_CHINFO_BE_W6_FW_PROBE0_BSSIDS);
+ if (ver == 0)
+ elem->w0 |=
+ le32_encode_bits(ch_info->period, RTW89_H2C_CHINFO_BE_W0_PERIOD);
+ else
+ elem->w7 = le32_encode_bits(ch_info->period,
+ RTW89_H2C_CHINFO_BE_W7_PERIOD_V1);
}
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
@@ -5171,6 +5287,7 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
u8 probe_id[NUM_NL80211_BANDS];
u8 cfg_len = sizeof(*h2c);
unsigned int cond;
+ u8 ver = U8_MAX;
void *ptr;
int ret;
u32 len;
@@ -5191,6 +5308,9 @@ int rtw89_fw_h2c_scan_offload_be(struct rtw89_dev *rtwdev,
memset(probe_id, RTW89_SCANOFLD_PKT_NONE, sizeof(probe_id));
+ if (RTW89_CHK_FW_FEATURE(CH_INFO_BE_V0, &rtwdev->fw))
+ ver = 0;
+
if (!wowlan) {
list_for_each_entry(pkt_info, &scan_info->pkt_list[NL80211_BAND_6GHZ], list) {
if (pkt_info->wildcard_6ghz) {
@@ -5286,9 +5406,7 @@ flex_member:
le32_encode_bits(RTW89_OFF_CHAN_TIME / 10,
RTW89_H2C_SCANOFLD_BE_OPCH_W0_POLICY_VAL);
- opch->w1 = le32_encode_bits(RTW89_CHANNEL_TIME,
- RTW89_H2C_SCANOFLD_BE_OPCH_W1_DURATION) |
- le32_encode_bits(op->band_type,
+ opch->w1 = le32_encode_bits(op->band_type,
RTW89_H2C_SCANOFLD_BE_OPCH_W1_CH_BAND) |
le32_encode_bits(op->band_width,
RTW89_H2C_SCANOFLD_BE_OPCH_W1_BW) |
@@ -5314,6 +5432,13 @@ flex_member:
RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT2) |
le32_encode_bits(RTW89_SCANOFLD_PKT_NONE,
RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT3);
+
+ if (ver == 0)
+ opch->w1 |= le32_encode_bits(RTW89_CHANNEL_TIME,
+ RTW89_H2C_SCANOFLD_BE_OPCH_W1_DURATION);
+ else
+ opch->w4 = le32_encode_bits(RTW89_CHANNEL_TIME,
+ RTW89_H2C_SCANOFLD_BE_OPCH_W4_DURATION_V1);
ptr += sizeof(*opch);
}
@@ -5416,7 +5541,9 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx)
{
struct rtw89_rfk_mcc_info *rfk_mcc = &rtwdev->rfk_mcc;
+ struct rtw89_fw_h2c_rfk_pre_info_common *common;
struct rtw89_fw_h2c_rfk_pre_info_v0 *h2c_v0;
+ struct rtw89_fw_h2c_rfk_pre_info_v1 *h2c_v1;
struct rtw89_fw_h2c_rfk_pre_info *h2c;
u8 tbl_sel[NUM_OF_RTW89_FW_RFK_PATH];
u32 len = sizeof(*h2c);
@@ -5426,7 +5553,10 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
u32 val32;
int ret;
- if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V0, &rtwdev->fw)) {
+ if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V1, &rtwdev->fw)) {
+ len = sizeof(*h2c_v1);
+ ver = 1;
+ } else if (RTW89_CHK_FW_FEATURE(RFK_PRE_NOTIFY_V0, &rtwdev->fw)) {
len = sizeof(*h2c_v0);
ver = 0;
}
@@ -5438,17 +5568,18 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
}
skb_put(skb, len);
h2c = (struct rtw89_fw_h2c_rfk_pre_info *)skb->data;
+ common = &h2c->base_v1.common;
- h2c->common.mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
+ common->mlo_mode = cpu_to_le32(rtwdev->mlo_dbcc_mode);
BUILD_BUG_ON(NUM_OF_RTW89_FW_RFK_TBL > RTW89_RFK_CHS_NR);
BUILD_BUG_ON(ARRAY_SIZE(rfk_mcc->data) < NUM_OF_RTW89_FW_RFK_PATH);
for (tbl = 0; tbl < NUM_OF_RTW89_FW_RFK_TBL; tbl++) {
for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) {
- h2c->common.dbcc.ch[path][tbl] =
+ common->dbcc.ch[path][tbl] =
cpu_to_le32(rfk_mcc->data[path].ch[tbl]);
- h2c->common.dbcc.band[path][tbl] =
+ common->dbcc.band[path][tbl] =
cpu_to_le32(rfk_mcc->data[path].band[tbl]);
}
}
@@ -5456,13 +5587,19 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
for (path = 0; path < NUM_OF_RTW89_FW_RFK_PATH; path++) {
tbl_sel[path] = rfk_mcc->data[path].table_idx;
- h2c->common.tbl.cur_ch[path] =
+ common->tbl.cur_ch[path] =
cpu_to_le32(rfk_mcc->data[path].ch[tbl_sel[path]]);
- h2c->common.tbl.cur_band[path] =
+ common->tbl.cur_band[path] =
cpu_to_le32(rfk_mcc->data[path].band[tbl_sel[path]]);
+
+ if (ver <= 1)
+ continue;
+
+ h2c->cur_bandwidth[path] =
+ cpu_to_le32(rfk_mcc->data[path].bw[tbl_sel[path]]);
}
- h2c->common.phy_idx = cpu_to_le32(phy_idx);
+ common->phy_idx = cpu_to_le32(phy_idx);
if (ver == 0) { /* RFK_PRE_NOTIFY_V0 */
h2c_v0 = (struct rtw89_fw_h2c_rfk_pre_info_v0 *)skb->data;
@@ -5488,8 +5625,10 @@ int rtw89_fw_h2c_rf_pre_ntfy(struct rtw89_dev *rtwdev,
goto done;
}
- if (rtw89_is_mlo_1_1(rtwdev))
- h2c->mlo_1_1 = cpu_to_le32(1);
+ if (rtw89_is_mlo_1_1(rtwdev)) {
+ h2c_v1 = &h2c->base_v1;
+ h2c_v1->mlo_1_1 = cpu_to_le32(1);
+ }
done:
rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
H2C_CAT_OUTSRC, H2C_CL_OUTSRC_RF_FW_RFK,
@@ -6496,7 +6635,7 @@ int rtw89_pno_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
INIT_LIST_HEAD(&chan_list);
for (idx = 0, list_len = 0;
- idx < nd_config->n_channels && list_len < RTW89_SCAN_LIST_LIMIT;
+ idx < nd_config->n_channels && list_len < RTW89_SCAN_LIST_LIMIT_AX;
idx++, list_len++) {
channel = nd_config->channels[idx];
ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
@@ -6547,7 +6686,7 @@ int rtw89_hw_scan_add_chan_list_ax(struct rtw89_dev *rtwdev,
INIT_LIST_HEAD(&chan_list);
for (idx = rtwdev->scan_info.last_chan_idx, list_len = 0;
- idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT;
+ idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT_AX;
idx++, list_len++) {
channel = req->channels[idx];
ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
@@ -6624,7 +6763,7 @@ int rtw89_pno_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
INIT_LIST_HEAD(&chan_list);
for (idx = 0, list_len = 0;
- idx < nd_config->n_channels && list_len < RTW89_SCAN_LIST_LIMIT;
+ idx < nd_config->n_channels && list_len < RTW89_SCAN_LIST_LIMIT_BE;
idx++, list_len++) {
channel = nd_config->channels[idx];
ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
@@ -6679,7 +6818,7 @@ int rtw89_hw_scan_add_chan_list_be(struct rtw89_dev *rtwdev,
INIT_LIST_HEAD(&chan_list);
for (idx = rtwdev->scan_info.last_chan_idx, list_len = 0;
- idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT;
+ idx < req->n_channels && list_len < RTW89_SCAN_LIST_LIMIT_BE;
idx++, list_len++) {
channel = req->channels[idx];
ch_info = kzalloc(sizeof(*ch_info), GFP_KERNEL);
@@ -8164,6 +8303,71 @@ int rtw89_fw_h2c_mrc_upd_duration(struct rtw89_dev *rtwdev,
return 0;
}
+static int rtw89_fw_h2c_ap_info(struct rtw89_dev *rtwdev, bool en)
+{
+ struct rtw89_h2c_ap_info *h2c;
+ u32 len = sizeof(*h2c);
+ struct sk_buff *skb;
+ int ret;
+
+ skb = rtw89_fw_h2c_alloc_skb_with_hdr(rtwdev, len);
+ if (!skb) {
+ rtw89_err(rtwdev, "failed to alloc skb for ap info\n");
+ return -ENOMEM;
+ }
+
+ skb_put(skb, len);
+ h2c = (struct rtw89_h2c_ap_info *)skb->data;
+
+ h2c->w0 = le32_encode_bits(en, RTW89_H2C_AP_INFO_W0_PWR_INT_EN);
+
+ rtw89_h2c_pkt_set_hdr(rtwdev, skb, FWCMD_TYPE_H2C,
+ H2C_CAT_MAC,
+ H2C_CL_AP,
+ H2C_FUNC_AP_INFO, 0, 0,
+ len);
+
+ ret = rtw89_h2c_tx(rtwdev, skb, false);
+ if (ret) {
+ rtw89_err(rtwdev, "failed to send h2c\n");
+ dev_kfree_skb_any(skb);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+int rtw89_fw_h2c_ap_info_refcount(struct rtw89_dev *rtwdev, bool en)
+{
+ int ret;
+
+ if (en) {
+ if (refcount_inc_not_zero(&rtwdev->refcount_ap_info))
+ return 0;
+ } else {
+ if (!refcount_dec_and_test(&rtwdev->refcount_ap_info))
+ return 0;
+ }
+
+ ret = rtw89_fw_h2c_ap_info(rtwdev, en);
+ if (ret) {
+ if (!test_bit(RTW89_FLAG_SER_HANDLING, rtwdev->flags))
+ return ret;
+
+ /* During recovery, neither driver nor stack has full error
+ * handling, so show a warning, but return 0 with refcount
+ * increased normally. It can avoid underflow when calling
+ * with @en == false later.
+ */
+ rtw89_warn(rtwdev, "h2c ap_info failed during SER\n");
+ }
+
+ if (en)
+ refcount_set(&rtwdev->refcount_ap_info, 1);
+
+ return 0;
+}
+
static bool __fw_txpwr_entry_zero_ext(const void *ext_ptr, u8 ext_len)
{
static const u8 zeros[U8_MAX] = {};
diff --git a/drivers/net/wireless/realtek/rtw89/fw.h b/drivers/net/wireless/realtek/rtw89/fw.h
index efa63d444821..a3fe183c2ab0 100644
--- a/drivers/net/wireless/realtek/rtw89/fw.h
+++ b/drivers/net/wireless/realtek/rtw89/fw.h
@@ -310,9 +310,12 @@ struct rtw89_fw_macid_pause_sleep_grp {
#define RTW89_SCANOFLD_DEBUG_MASK 0x1F
#define RTW89_CHAN_INVALID 0xFF
#define RTW89_MAC_CHINFO_SIZE 28
+#define RTW89_MAC_CHINFO_SIZE_BE 32
#define RTW89_SCAN_LIST_GUARD 4
-#define RTW89_SCAN_LIST_LIMIT \
- ((RTW89_H2C_MAX_SIZE / RTW89_MAC_CHINFO_SIZE) - RTW89_SCAN_LIST_GUARD)
+#define RTW89_SCAN_LIST_LIMIT(size) \
+ ((RTW89_H2C_MAX_SIZE / (size)) - RTW89_SCAN_LIST_GUARD)
+#define RTW89_SCAN_LIST_LIMIT_AX RTW89_SCAN_LIST_LIMIT(RTW89_MAC_CHINFO_SIZE)
+#define RTW89_SCAN_LIST_LIMIT_BE RTW89_SCAN_LIST_LIMIT(RTW89_MAC_CHINFO_SIZE_BE)
#define RTW89_BCN_LOSS_CNT 10
@@ -1780,6 +1783,21 @@ struct rtw89_h2c_lps_ch_info {
__le32 mlo_dbcc_mode_lps;
} __packed;
+struct rtw89_h2c_lps_ml_cmn_info {
+ u8 fmt_id;
+ u8 rsvd0[3];
+ __le32 mlo_dbcc_mode;
+ u8 central_ch[RTW89_PHY_MAX];
+ u8 pri_ch[RTW89_PHY_MAX];
+ u8 bw[RTW89_PHY_MAX];
+ u8 band[RTW89_PHY_MAX];
+ u8 bcn_rate_type[RTW89_PHY_MAX];
+ u8 rsvd1[2];
+ __le16 tia_gain[RTW89_PHY_MAX][TIA_GAIN_NUM];
+ u8 lna_gain[RTW89_PHY_MAX][LNA_GAIN_NUM];
+ u8 rsvd2[2];
+} __packed;
+
static inline void RTW89_SET_FWCMD_CPU_EXCEPTION_TYPE(void *cmd, u32 val)
{
le32p_replace_bits((__le32 *)cmd, val, GENMASK(31, 0));
@@ -2647,6 +2665,7 @@ struct rtw89_h2c_chinfo_elem_be {
__le32 w4;
__le32 w5;
__le32 w6;
+ __le32 w7;
} __packed;
#define RTW89_H2C_CHINFO_BE_W0_PERIOD GENMASK(7, 0)
@@ -2678,6 +2697,7 @@ struct rtw89_h2c_chinfo_elem_be {
#define RTW89_H2C_CHINFO_BE_W5_FW_PROBE0_SSIDS GENMASK(31, 16)
#define RTW89_H2C_CHINFO_BE_W6_FW_PROBE0_SHORTSSIDS GENMASK(15, 0)
#define RTW89_H2C_CHINFO_BE_W6_FW_PROBE0_BSSIDS GENMASK(31, 16)
+#define RTW89_H2C_CHINFO_BE_W7_PERIOD_V1 GENMASK(15, 0)
struct rtw89_h2c_chinfo {
u8 ch_num;
@@ -2687,6 +2707,14 @@ struct rtw89_h2c_chinfo {
struct rtw89_h2c_chinfo_elem elem[] __counted_by(ch_num);
} __packed;
+struct rtw89_h2c_chinfo_be {
+ u8 ch_num;
+ u8 elem_size;
+ u8 arg;
+ u8 rsvd0;
+ struct rtw89_h2c_chinfo_elem_be elem[] __counted_by(ch_num);
+} __packed;
+
#define RTW89_H2C_CHINFO_ARG_MAC_IDX_MASK BIT(0)
#define RTW89_H2C_CHINFO_ARG_APPEND_MASK BIT(1)
@@ -2733,6 +2761,7 @@ struct rtw89_h2c_scanofld_be_opch {
__le32 w1;
__le32 w2;
__le32 w3;
+ __le32 w4;
} __packed;
#define RTW89_H2C_SCANOFLD_BE_OPCH_W0_MACID GENMASK(15, 0)
@@ -2754,6 +2783,7 @@ struct rtw89_h2c_scanofld_be_opch {
#define RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT1 GENMASK(15, 8)
#define RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT2 GENMASK(23, 16)
#define RTW89_H2C_SCANOFLD_BE_OPCH_W3_PKT3 GENMASK(31, 24)
+#define RTW89_H2C_SCANOFLD_BE_OPCH_W4_DURATION_V1 GENMASK(15, 0)
struct rtw89_h2c_scanofld_be {
__le32 w0;
@@ -3466,6 +3496,12 @@ struct rtw89_h2c_wow_aoac {
__le32 w0;
} __packed;
+struct rtw89_h2c_ap_info {
+ __le32 w0;
+} __packed;
+
+#define RTW89_H2C_AP_INFO_W0_PWR_INT_EN BIT(0)
+
#define RTW89_C2H_HEADER_LEN 8
struct rtw89_c2h_hdr {
@@ -3590,6 +3626,7 @@ struct rtw89_c2h_scanofld {
__le32 w5;
__le32 w6;
__le32 w7;
+ __le32 w8;
} __packed;
#define RTW89_C2H_SCANOFLD_W2_PRI_CH GENMASK(7, 0)
@@ -3604,6 +3641,8 @@ struct rtw89_c2h_scanofld {
#define RTW89_C2H_SCANOFLD_W6_EXPECT_PERIOD GENMASK(15, 8)
#define RTW89_C2H_SCANOFLD_W6_FW_DEF GENMASK(23, 16)
#define RTW89_C2H_SCANOFLD_W7_REPORT_TSF GENMASK(31, 0)
+#define RTW89_C2H_SCANOFLD_W8_PERIOD_V1 GENMASK(15, 0)
+#define RTW89_C2H_SCANOFLD_W8_EXPECT_PERIOD_V1 GENMASK(31, 16)
#define RTW89_GET_MAC_C2H_MCC_RCV_ACK_GROUP(c2h) \
le32_get_bits(*((const __le32 *)(c2h) + 2), GENMASK(1, 0))
@@ -3725,6 +3764,14 @@ struct rtw89_c2h_wow_aoac_report {
#define RTW89_C2H_WOW_AOAC_RPT_REKEY_IDX BIT(0)
+struct rtw89_c2h_pwr_int_notify {
+ struct rtw89_c2h_hdr hdr;
+ __le32 w2;
+} __packed;
+
+#define RTW89_C2H_PWR_INT_NOTIFY_W2_MACID GENMASK(15, 0)
+#define RTW89_C2H_PWR_INT_NOTIFY_W2_PWR_STATUS BIT(16)
+
struct rtw89_h2c_tx_duty {
__le32 w0;
__le32 w1;
@@ -4168,6 +4215,10 @@ enum rtw89_mrc_h2c_func {
#define RTW89_MRC_WAIT_COND_REQ_TSF \
RTW89_MRC_WAIT_COND(0 /* don't care */, H2C_FUNC_MRC_REQ_TSF)
+/* CLASS 36 - AP */
+#define H2C_CL_AP 0x24
+#define H2C_FUNC_AP_INFO 0x0
+
#define H2C_CAT_OUTSRC 0x2
#define H2C_CL_OUTSRC_RA 0x1
@@ -4175,6 +4226,7 @@ enum rtw89_mrc_h2c_func {
#define H2C_CL_OUTSRC_DM 0x2
#define H2C_FUNC_FW_LPS_CH_INFO 0xb
+#define H2C_FUNC_FW_LPS_ML_CMN_INFO 0xe
#define H2C_CL_OUTSRC_RF_REG_A 0x8
#define H2C_CL_OUTSRC_RF_REG_B 0x9
@@ -4241,11 +4293,16 @@ struct rtw89_fw_h2c_rfk_pre_info_v0 {
} __packed mlo;
} __packed;
-struct rtw89_fw_h2c_rfk_pre_info {
+struct rtw89_fw_h2c_rfk_pre_info_v1 {
struct rtw89_fw_h2c_rfk_pre_info_common common;
__le32 mlo_1_1;
} __packed;
+struct rtw89_fw_h2c_rfk_pre_info {
+ struct rtw89_fw_h2c_rfk_pre_info_v1 base_v1;
+ __le32 cur_bandwidth[NUM_OF_RTW89_FW_RFK_PATH];
+} __packed;
+
struct rtw89_h2c_rf_tssi {
__le16 len;
u8 phy;
@@ -4602,8 +4659,9 @@ int rtw89_fw_h2c_init_ba_cam_users(struct rtw89_dev *rtwdev, u8 users,
int rtw89_fw_h2c_lps_parm(struct rtw89_dev *rtwdev,
struct rtw89_lps_parm *lps_param);
-int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev,
- struct rtw89_vif_link *rtwvif_link);
+int rtw89_fw_h2c_lps_ch_info(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif);
+int rtw89_fw_h2c_lps_ml_cmn_info(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif);
int rtw89_fw_h2c_fwips(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
bool enable);
struct sk_buff *rtw89_fw_h2c_alloc_skb_with_hdr(struct rtw89_dev *rtwdev, u32 len);
@@ -4697,6 +4755,7 @@ int rtw89_fw_h2c_mrc_sync(struct rtw89_dev *rtwdev,
const struct rtw89_fw_mrc_sync_arg *arg);
int rtw89_fw_h2c_mrc_upd_duration(struct rtw89_dev *rtwdev,
const struct rtw89_fw_mrc_upd_duration_arg *arg);
+int rtw89_fw_h2c_ap_info_refcount(struct rtw89_dev *rtwdev, bool en);
static inline void rtw89_fw_h2c_init_ba_cam(struct rtw89_dev *rtwdev)
{
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 7907b84d204b..c78066fd4504 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -4788,9 +4788,11 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
struct rtw89_vif_link *rtwvif_link = rtwdev->scan_info.scanning_vif;
struct rtw89_vif *rtwvif;
struct rtw89_chan new;
- u8 reason, status, tx_fail, band, actual_period, expect_period;
u32 last_chan = rtwdev->scan_info.last_chan_idx, report_tsf;
+ u16 actual_period, expect_period;
+ u8 reason, status, tx_fail, band;
u8 mac_idx, sw_def, fw_def;
+ u8 ver = U8_MAX;
u16 chan;
int ret;
@@ -4799,6 +4801,9 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
rtwvif = rtwvif_link->rtwvif;
+ if (RTW89_CHK_FW_FEATURE(CH_INFO_BE_V0, &rtwdev->fw))
+ ver = 0;
+
tx_fail = le32_get_bits(c2h->w5, RTW89_C2H_SCANOFLD_W5_TX_FAIL);
status = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_STATUS);
chan = le32_get_bits(c2h->w2, RTW89_C2H_SCANOFLD_W2_PRI_CH);
@@ -4811,21 +4816,28 @@ rtw89_mac_c2h_scanofld_rsp(struct rtw89_dev *rtwdev, struct sk_buff *skb,
if (!(rtwdev->chip->support_bands & BIT(NL80211_BAND_6GHZ)))
band = chan > 14 ? RTW89_BAND_5G : RTW89_BAND_2G;
- rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN,
- "mac_idx[%d] band: %d, chan: %d, reason: %d, status: %d, tx_fail: %d, actual: %d\n",
- mac_idx, band, chan, reason, status, tx_fail, actual_period);
-
if (rtwdev->chip->chip_gen == RTW89_CHIP_BE) {
sw_def = le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_SW_DEF);
- expect_period = le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_EXPECT_PERIOD);
fw_def = le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_FW_DEF);
report_tsf = le32_get_bits(c2h->w7, RTW89_C2H_SCANOFLD_W7_REPORT_TSF);
+ if (ver == 0) {
+ expect_period =
+ le32_get_bits(c2h->w6, RTW89_C2H_SCANOFLD_W6_EXPECT_PERIOD);
+ } else {
+ actual_period = le32_get_bits(c2h->w8, RTW89_C2H_SCANOFLD_W8_PERIOD_V1);
+ expect_period =
+ le32_get_bits(c2h->w8, RTW89_C2H_SCANOFLD_W8_EXPECT_PERIOD_V1);
+ }
rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN,
"sw_def: %d, fw_def: %d, tsf: %x, expect: %d\n",
sw_def, fw_def, report_tsf, expect_period);
}
+ rtw89_debug(rtwdev, RTW89_DBG_HW_SCAN,
+ "mac_idx[%d] band: %d, chan: %d, reason: %d, status: %d, tx_fail: %d, actual: %d\n",
+ mac_idx, band, chan, reason, status, tx_fail, actual_period);
+
switch (reason) {
case RTW89_SCAN_LEAVE_OP_NOTIFY:
case RTW89_SCAN_LEAVE_CH_NOTIFY:
@@ -5364,6 +5376,39 @@ rtw89_mac_c2h_mrc_status_rpt(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32
rtw89_complete_cond(wait, cond, &data);
}
+static void
+rtw89_mac_c2h_pwr_int_notify(struct rtw89_dev *rtwdev, struct sk_buff *skb, u32 len)
+{
+ const struct rtw89_c2h_pwr_int_notify *c2h;
+ struct rtw89_sta_link *rtwsta_link;
+ struct ieee80211_sta *sta;
+ struct rtw89_sta *rtwsta;
+ u16 macid;
+ bool ps;
+
+ c2h = (const struct rtw89_c2h_pwr_int_notify *)skb->data;
+ macid = le32_get_bits(c2h->w2, RTW89_C2H_PWR_INT_NOTIFY_W2_MACID);
+ ps = le32_get_bits(c2h->w2, RTW89_C2H_PWR_INT_NOTIFY_W2_PWR_STATUS);
+
+ rcu_read_lock();
+
+ rtwsta_link = rtw89_assoc_link_rcu_dereference(rtwdev, macid);
+ if (unlikely(!rtwsta_link))
+ goto out;
+
+ rtwsta = rtwsta_link->rtwsta;
+ if (ps)
+ set_bit(RTW89_REMOTE_STA_IN_PS, rtwsta->flags);
+ else
+ clear_bit(RTW89_REMOTE_STA_IN_PS, rtwsta->flags);
+
+ sta = rtwsta_to_sta(rtwsta);
+ ieee80211_sta_ps_transition(sta, ps);
+
+out:
+ rcu_read_unlock();
+}
+
static
void (* const rtw89_mac_c2h_ofld_handler[])(struct rtw89_dev *rtwdev,
struct sk_buff *c2h, u32 len) = {
@@ -5409,6 +5454,12 @@ void (* const rtw89_mac_c2h_wow_handler[])(struct rtw89_dev *rtwdev,
[RTW89_MAC_C2H_FUNC_AOAC_REPORT] = rtw89_mac_c2h_wow_aoac_rpt,
};
+static
+void (* const rtw89_mac_c2h_ap_handler[])(struct rtw89_dev *rtwdev,
+ struct sk_buff *c2h, u32 len) = {
+ [RTW89_MAC_C2H_FUNC_PWR_INT_NOTIFY] = rtw89_mac_c2h_pwr_int_notify,
+};
+
static void rtw89_mac_c2h_scanofld_rsp_atomic(struct rtw89_dev *rtwdev,
struct sk_buff *skb)
{
@@ -5463,6 +5514,13 @@ bool rtw89_mac_c2h_chk_atomic(struct rtw89_dev *rtwdev, struct sk_buff *c2h,
return true;
case RTW89_MAC_C2H_CLASS_WOW:
return true;
+ case RTW89_MAC_C2H_CLASS_AP:
+ switch (func) {
+ default:
+ return false;
+ case RTW89_MAC_C2H_FUNC_PWR_INT_NOTIFY:
+ return true;
+ }
}
}
@@ -5493,14 +5551,18 @@ void rtw89_mac_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
if (func < NUM_OF_RTW89_MAC_C2H_FUNC_WOW)
handler = rtw89_mac_c2h_wow_handler[func];
break;
+ case RTW89_MAC_C2H_CLASS_AP:
+ if (func < NUM_OF_RTW89_MAC_C2H_FUNC_AP)
+ handler = rtw89_mac_c2h_ap_handler[func];
+ break;
case RTW89_MAC_C2H_CLASS_FWDBG:
return;
default:
- rtw89_info(rtwdev, "c2h class %d not support\n", class);
+ rtw89_info(rtwdev, "MAC c2h class %d not support\n", class);
return;
}
if (!handler) {
- rtw89_info(rtwdev, "c2h class %d func %d not support\n", class,
+ rtw89_info(rtwdev, "MAC c2h class %d func %d not support\n", class,
func);
return;
}
@@ -6674,6 +6736,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_ax = {
.typ_fltr_opt = rtw89_mac_typ_fltr_opt_ax,
.cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_ax,
+ .cfg_phy_rpt = NULL,
.dle_mix_cfg = dle_mix_cfg_ax,
.chk_dle_rdy = chk_dle_rdy_ax,
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index 18579c020548..8edea96d037f 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -169,6 +169,20 @@ enum rtw89_mac_ax_l0_to_l1_event {
MAC_AX_L0_TO_L1_EVENT_MAX = 15,
};
+enum rtw89_mac_phy_rpt_size {
+ MAC_AX_PHY_RPT_SIZE_0 = 0,
+ MAC_AX_PHY_RPT_SIZE_8 = 1,
+ MAC_AX_PHY_RPT_SIZE_16 = 2,
+ MAC_AX_PHY_RPT_SIZE_24 = 3,
+};
+
+enum rtw89_mac_hdr_cnv_size {
+ MAC_AX_HDR_CNV_SIZE_0 = 0,
+ MAC_AX_HDR_CNV_SIZE_32 = 1,
+ MAC_AX_HDR_CNV_SIZE_64 = 2,
+ MAC_AX_HDR_CNV_SIZE_96 = 3,
+};
+
enum rtw89_mac_wow_fw_status {
WOWLAN_NOT_READY = 0x00,
WOWLAN_SLEEP_READY = 0x01,
@@ -426,6 +440,12 @@ enum rtw89_mac_c2h_wow_func {
NUM_OF_RTW89_MAC_C2H_FUNC_WOW,
};
+enum rtw89_mac_c2h_ap_func {
+ RTW89_MAC_C2H_FUNC_PWR_INT_NOTIFY = 0,
+
+ NUM_OF_RTW89_MAC_C2H_FUNC_AP,
+};
+
enum rtw89_mac_c2h_class {
RTW89_MAC_C2H_CLASS_INFO = 0x0,
RTW89_MAC_C2H_CLASS_OFLD = 0x1,
@@ -434,6 +454,7 @@ enum rtw89_mac_c2h_class {
RTW89_MAC_C2H_CLASS_MCC = 0x4,
RTW89_MAC_C2H_CLASS_FWDBG = 0x5,
RTW89_MAC_C2H_CLASS_MRC = 0xe,
+ RTW89_MAC_C2H_CLASS_AP = 0x18,
RTW89_MAC_C2H_CLASS_MAX,
};
@@ -961,6 +982,7 @@ struct rtw89_mac_gen_def {
enum rtw89_mac_fwd_target fwd_target,
u8 mac_idx);
int (*cfg_ppdu_status)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable);
+ void (*cfg_phy_rpt)(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable);
int (*dle_mix_cfg)(struct rtw89_dev *rtwdev, const struct rtw89_dle_mem *cfg);
int (*chk_dle_rdy)(struct rtw89_dev *rtwdev, bool wde_or_ple);
@@ -1216,6 +1238,27 @@ int rtw89_mac_stop_sch_tx_v2(struct rtw89_dev *rtwdev, u8 mac_idx,
int rtw89_mac_resume_sch_tx(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en);
int rtw89_mac_resume_sch_tx_v1(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en);
int rtw89_mac_resume_sch_tx_v2(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en);
+void rtw89_mac_cfg_phy_rpt_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable);
+
+static inline
+void rtw89_mac_cfg_phy_rpt(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
+{
+ const struct rtw89_mac_gen_def *mac = rtwdev->chip->mac_def;
+
+ if (mac->cfg_phy_rpt)
+ mac->cfg_phy_rpt(rtwdev, mac_idx, enable);
+}
+
+static inline
+void rtw89_mac_cfg_phy_rpt_bands(struct rtw89_dev *rtwdev, bool enable)
+{
+ rtw89_mac_cfg_phy_rpt(rtwdev, RTW89_MAC_0, enable);
+
+ if (!rtwdev->dbcc_en)
+ return;
+
+ rtw89_mac_cfg_phy_rpt(rtwdev, RTW89_MAC_1, enable);
+}
static inline
int rtw89_mac_cfg_ppdu_status(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 619d2d3771d5..5eac0b524060 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -202,7 +202,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
rtw89_traffic_stats_init(rtwdev, &rtwvif->stats);
- rtwvif_link = rtw89_vif_set_link(rtwvif, 0);
+ rtwvif_link = rtw89_vif_set_link(rtwvif, RTW89_VIF_IDLE_LINK_ID);
if (!rtwvif_link) {
ret = -EINVAL;
goto release_port;
@@ -218,7 +218,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
return 0;
unset_link:
- rtw89_vif_unset_link(rtwvif, 0);
+ rtw89_vif_unset_link(rtwvif, RTW89_VIF_IDLE_LINK_ID);
release_port:
list_del_init(&rtwvif->list);
rtw89_core_release_bit_map(rtwdev->hw_port, port);
@@ -246,17 +246,17 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
mutex_lock(&rtwdev->mutex);
- rtwvif_link = rtwvif->links[0];
+ rtwvif_link = rtwvif->links[RTW89_VIF_IDLE_LINK_ID];
if (unlikely(!rtwvif_link)) {
rtw89_err(rtwdev,
"%s: rtwvif link (link_id %u) is not active\n",
- __func__, 0);
+ __func__, RTW89_VIF_IDLE_LINK_ID);
goto bottom;
}
__rtw89_ops_remove_iface_link(rtwdev, rtwvif_link);
- rtw89_vif_unset_link(rtwvif, 0);
+ rtw89_vif_unset_link(rtwvif, RTW89_VIF_IDLE_LINK_ID);
bottom:
list_del_init(&rtwvif->list);
@@ -509,6 +509,7 @@ static int __rtw89_ops_sta_add(struct rtw89_dev *rtwdev,
rtw89_core_txq_init(rtwdev, sta->txq[i]);
skb_queue_head_init(&rtwsta->roc_queue);
+ bitmap_zero(rtwsta->pairwise_sec_cam_map, RTW89_MAX_SEC_CAM_NUM);
rtwsta_link = rtw89_sta_set_link(rtwsta, sta->deflink.link_id);
if (!rtwsta_link) {
@@ -775,6 +776,7 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
struct rtw89_vif_link *rtwvif_link;
const struct rtw89_chan *chan;
+ int ret = 0;
mutex_lock(&rtwdev->mutex);
@@ -783,6 +785,7 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
rtw89_err(rtwdev,
"%s: rtwvif link (link_id %u) is not active\n",
__func__, link_conf->link_id);
+ ret = -ENOLINK;
goto out;
}
@@ -804,12 +807,18 @@ static int rtw89_ops_start_ap(struct ieee80211_hw *hw,
rtw89_fw_h2c_cam(rtwdev, rtwvif_link, NULL, NULL);
rtw89_chip_rfk_channel(rtwdev, rtwvif_link);
+ if (RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &rtwdev->fw)) {
+ ret = rtw89_fw_h2c_ap_info_refcount(rtwdev, true);
+ if (ret)
+ goto out;
+ }
+
rtw89_queue_chanctx_work(rtwdev);
out:
mutex_unlock(&rtwdev->mutex);
- return 0;
+ return ret;
}
static
@@ -830,6 +839,9 @@ void rtw89_ops_stop_ap(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
goto out;
}
+ if (RTW89_CHK_FW_FEATURE(NOTIFY_AP_INFO, &rtwdev->fw))
+ rtw89_fw_h2c_ap_info_refcount(rtwdev, false);
+
rtw89_mac_stop_ap(rtwdev, rtwvif_link);
rtw89_chip_h2c_assoc_cmac_tbl(rtwdev, rtwvif_link, NULL);
rtw89_fw_h2c_join_info(rtwdev, rtwvif_link, NULL, true);
@@ -1295,10 +1307,15 @@ static void rtw89_ops_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_link_sta *link_sta,
u32 changed)
{
- struct ieee80211_sta *sta = link_sta->sta;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(link_sta->sta);
struct rtw89_dev *rtwdev = hw->priv;
+ struct rtw89_sta_link *rtwsta_link;
- rtw89_phy_ra_update_sta(rtwdev, sta, changed);
+ rtwsta_link = rtwsta->links[link_sta->link_id];
+ if (unlikely(!rtwsta_link))
+ return;
+
+ rtw89_phy_ra_update_sta_link(rtwdev, rtwsta_link, changed);
}
static int rtw89_ops_add_chanctx(struct ieee80211_hw *hw,
@@ -1473,6 +1490,259 @@ static int rtw89_ops_set_tid_config(struct ieee80211_hw *hw,
return 0;
}
+static bool rtw89_can_work_on_links(struct rtw89_dev *rtwdev,
+ struct ieee80211_vif *vif, u16 links)
+{
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ u8 w = hweight16(links);
+
+ if (vif->type != NL80211_IFTYPE_STATION &&
+ w > RTW89_MLD_NON_STA_LINK_NUM)
+ return false;
+
+ return w <= rtwvif->links_inst_valid_num;
+}
+
+static bool rtw89_ops_can_activate_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 active_links)
+{
+ struct rtw89_dev *rtwdev = hw->priv;
+
+ guard(mutex)(&rtwdev->mutex);
+
+ return rtw89_can_work_on_links(rtwdev, vif, active_links);
+}
+
+static void __rtw89_ops_clr_vif_links(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif,
+ unsigned long clr_links)
+{
+ struct rtw89_vif_link *rtwvif_link;
+ unsigned int link_id;
+
+ for_each_set_bit(link_id, &clr_links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ rtwvif_link = rtwvif->links[link_id];
+ if (unlikely(!rtwvif_link))
+ continue;
+
+ __rtw89_ops_remove_iface_link(rtwdev, rtwvif_link);
+
+ rtw89_vif_unset_link(rtwvif, link_id);
+ }
+}
+
+static int __rtw89_ops_set_vif_links(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif,
+ unsigned long set_links)
+{
+ struct rtw89_vif_link *rtwvif_link;
+ unsigned int link_id;
+ int ret;
+
+ for_each_set_bit(link_id, &set_links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ rtwvif_link = rtw89_vif_set_link(rtwvif, link_id);
+ if (!rtwvif_link)
+ return -EINVAL;
+
+ ret = __rtw89_ops_add_iface_link(rtwdev, rtwvif_link);
+ if (ret) {
+ rtw89_err(rtwdev, "%s: failed to add iface (link id %u)\n",
+ __func__, link_id);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static
+int rtw89_ops_change_vif_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ u16 old_links, u16 new_links,
+ struct ieee80211_bss_conf *old[IEEE80211_MLD_MAX_NUM_LINKS])
+{
+ struct rtw89_dev *rtwdev = hw->priv;
+ struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
+ unsigned long clr_links = old_links & ~new_links;
+ unsigned long set_links = new_links & ~old_links;
+ bool removing_links = !old_links || clr_links;
+ struct rtw89_link_conf_container *snap;
+ int ret = 0;
+ int i;
+
+ guard(mutex)(&rtwdev->mutex);
+
+ rtw89_debug(rtwdev, RTW89_DBG_STATE,
+ "%s: old_links (0x%08x) -> new_links (0x%08x)\n",
+ __func__, old_links, new_links);
+
+ if (!rtw89_can_work_on_links(rtwdev, vif, new_links))
+ return -EOPNOTSUPP;
+
+ if (removing_links) {
+ snap = kzalloc(sizeof(*snap), GFP_KERNEL);
+ if (!snap)
+ return -ENOMEM;
+
+ for (i = 0; i < ARRAY_SIZE(snap->link_conf); i++)
+ snap->link_conf[i] = old[i];
+
+ rcu_assign_pointer(rtwvif->snap_link_confs, snap);
+ }
+
+ /* might depend on @snap; don't change order */
+ rtw89_leave_ips_by_hwflags(rtwdev);
+
+ if (rtwdev->scanning)
+ rtw89_hw_scan_abort(rtwdev, rtwdev->scan_info.scanning_vif);
+
+ if (!old_links)
+ __rtw89_ops_clr_vif_links(rtwdev, rtwvif,
+ BIT(RTW89_VIF_IDLE_LINK_ID));
+ else if (clr_links)
+ __rtw89_ops_clr_vif_links(rtwdev, rtwvif, clr_links);
+
+ if (removing_links) {
+ /* @snap is required if and only if during removing links.
+ * However, it's done here. So, cleanup @snap immediately.
+ */
+ rcu_assign_pointer(rtwvif->snap_link_confs, NULL);
+
+ /* The pointers in @old will free after this function return,
+ * so synchronously wait for all readers of snap to be done.
+ */
+ synchronize_rcu();
+ kfree(snap);
+ }
+
+ if (set_links) {
+ ret = __rtw89_ops_set_vif_links(rtwdev, rtwvif, set_links);
+ if (ret)
+ __rtw89_ops_clr_vif_links(rtwdev, rtwvif, set_links);
+ } else if (!new_links) {
+ ret = __rtw89_ops_set_vif_links(rtwdev, rtwvif,
+ BIT(RTW89_VIF_IDLE_LINK_ID));
+ if (ret)
+ __rtw89_ops_clr_vif_links(rtwdev, rtwvif,
+ BIT(RTW89_VIF_IDLE_LINK_ID));
+ }
+
+ rtw89_enter_ips_by_hwflags(rtwdev);
+ return ret;
+}
+
+static void __rtw89_ops_clr_sta_links(struct rtw89_dev *rtwdev,
+ struct rtw89_sta *rtwsta,
+ unsigned long clr_links)
+{
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+
+ for_each_set_bit(link_id, &clr_links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ rtwsta_link = rtwsta->links[link_id];
+ if (unlikely(!rtwsta_link))
+ continue;
+
+ rtwvif_link = rtwsta_link->rtwvif_link;
+
+ rtw89_core_sta_link_disassoc(rtwdev, rtwvif_link, rtwsta_link);
+ rtw89_core_sta_link_disconnect(rtwdev, rtwvif_link, rtwsta_link);
+ rtw89_core_sta_link_remove(rtwdev, rtwvif_link, rtwsta_link);
+
+ rtw89_sta_unset_link(rtwsta, link_id);
+ }
+}
+
+static int __rtw89_ops_set_sta_links(struct rtw89_dev *rtwdev,
+ struct rtw89_sta *rtwsta,
+ unsigned long set_links)
+{
+ struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_sta_link *rtwsta_link;
+ unsigned int link_id;
+ u8 sec_cam_idx;
+ int ret;
+
+ for_each_set_bit(link_id, &set_links, IEEE80211_MLD_MAX_NUM_LINKS) {
+ rtwsta_link = rtw89_sta_set_link(rtwsta, link_id);
+ if (!rtwsta_link)
+ return -EINVAL;
+
+ rtwvif_link = rtwsta_link->rtwvif_link;
+
+ ret = rtw89_core_sta_link_add(rtwdev, rtwvif_link, rtwsta_link);
+ if (ret) {
+ rtw89_err(rtwdev, "%s: failed to add sta (link id %u)\n",
+ __func__, link_id);
+ return ret;
+ }
+
+ rtw89_vif_type_mapping(rtwvif_link, true);
+
+ ret = rtw89_core_sta_link_assoc(rtwdev, rtwvif_link, rtwsta_link);
+ if (ret) {
+ rtw89_err(rtwdev, "%s: failed to assoc sta (link id %u)\n",
+ __func__, link_id);
+ return ret;
+ }
+
+ __rtw89_ops_bss_link_assoc(rtwdev, rtwvif_link);
+
+ for_each_set_bit(sec_cam_idx, rtwsta->pairwise_sec_cam_map,
+ RTW89_MAX_SEC_CAM_NUM) {
+ ret = rtw89_cam_attach_link_sec_cam(rtwdev,
+ rtwvif_link,
+ rtwsta_link,
+ sec_cam_idx);
+ if (ret) {
+ rtw89_err(rtwdev,
+ "%s: failed to apply pairwise key (link id %u)\n",
+ __func__, link_id);
+ return ret;
+ }
+ }
+ }
+
+ return 0;
+}
+
+static
+int rtw89_ops_change_sta_links(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct ieee80211_sta *sta,
+ u16 old_links, u16 new_links)
+{
+ struct rtw89_dev *rtwdev = hw->priv;
+ struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
+ unsigned long clr_links = old_links & ~new_links;
+ unsigned long set_links = new_links & ~old_links;
+ int ret = 0;
+
+ guard(mutex)(&rtwdev->mutex);
+
+ rtw89_debug(rtwdev, RTW89_DBG_STATE,
+ "%s: old_links (0x%08x) -> new_links (0x%08x)\n",
+ __func__, old_links, new_links);
+
+ if (!rtw89_can_work_on_links(rtwdev, vif, new_links))
+ return -EOPNOTSUPP;
+
+ rtw89_leave_ps_mode(rtwdev);
+
+ if (clr_links)
+ __rtw89_ops_clr_sta_links(rtwdev, rtwsta, clr_links);
+
+ if (set_links) {
+ ret = __rtw89_ops_set_sta_links(rtwdev, rtwsta, set_links);
+ if (ret)
+ __rtw89_ops_clr_sta_links(rtwdev, rtwsta, set_links);
+ }
+
+ return ret;
+}
+
#ifdef CONFIG_PM
static int rtw89_ops_suspend(struct ieee80211_hw *hw,
struct cfg80211_wowlan *wowlan)
@@ -1600,6 +1870,9 @@ const struct ieee80211_ops rtw89_ops = {
.set_sar_specs = rtw89_ops_set_sar_specs,
.link_sta_rc_update = rtw89_ops_sta_rc_update,
.set_tid_config = rtw89_ops_set_tid_config,
+ .can_activate_links = rtw89_ops_can_activate_links,
+ .change_vif_links = rtw89_ops_change_vif_links,
+ .change_sta_links = rtw89_ops_change_sta_links,
#ifdef CONFIG_PM
.suspend = rtw89_ops_suspend,
.resume = rtw89_ops_resume,
diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index f7a396c8a3cd..2dbdeae904ad 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -1988,6 +1988,20 @@ int rtw89_mac_resume_sch_tx_v2(struct rtw89_dev *rtwdev, u8 mac_idx, u32 tx_en)
}
EXPORT_SYMBOL(rtw89_mac_resume_sch_tx_v2);
+void rtw89_mac_cfg_phy_rpt_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
+{
+ u32 reg, val;
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RCR, mac_idx);
+ val = enable ? MAC_AX_PHY_RPT_SIZE_8 : MAC_AX_PHY_RPT_SIZE_0;
+ rtw89_write32_mask(rtwdev, reg, B_BE_PHY_RPT_SZ_MASK, val);
+ rtw89_write32_mask(rtwdev, reg, B_BE_HDR_CNV_SZ_MASK, MAC_AX_HDR_CNV_SIZE_0);
+
+ reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_DRV_INFO_OPTION, mac_idx);
+ rtw89_write32_mask(rtwdev, reg, B_BE_DRV_INFO_PHYRPT_EN, enable);
+}
+EXPORT_SYMBOL(rtw89_mac_cfg_phy_rpt_be);
+
static
int rtw89_mac_cfg_ppdu_status_be(struct rtw89_dev *rtwdev, u8 mac_idx, bool enable)
{
@@ -2583,6 +2597,7 @@ const struct rtw89_mac_gen_def rtw89_mac_gen_be = {
.typ_fltr_opt = rtw89_mac_typ_fltr_opt_be,
.cfg_ppdu_status = rtw89_mac_cfg_ppdu_status_be,
+ .cfg_phy_rpt = rtw89_mac_cfg_phy_rpt_be,
.dle_mix_cfg = dle_mix_cfg_be,
.chk_dle_rdy = chk_dle_rdy_be,
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index f923bec03d41..c3a027735d0f 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -2516,7 +2516,7 @@ static int rtw89_pci_dphy_delay(struct rtw89_dev *rtwdev)
PCIE_DPHY_DLY_25US, PCIE_PHY_GEN1);
}
-static void rtw89_pci_power_wake(struct rtw89_dev *rtwdev, bool pwr_up)
+static void rtw89_pci_power_wake_ax(struct rtw89_dev *rtwdev, bool pwr_up)
{
if (pwr_up)
rtw89_write32_set(rtwdev, R_AX_HCI_OPT_CTRL, BIT_WAKE_CTRL);
@@ -2825,6 +2825,8 @@ static int rtw89_pci_ops_deinit(struct rtw89_dev *rtwdev)
{
const struct rtw89_pci_info *info = rtwdev->pci_info;
+ rtw89_pci_power_wake(rtwdev, false);
+
if (rtwdev->chip->chip_id == RTL8852A) {
/* ltr sw trigger */
rtw89_write32_set(rtwdev, R_AX_LTR_CTRL_0, B_AX_APP_LTR_IDLE);
@@ -2867,7 +2869,7 @@ static int rtw89_pci_ops_mac_pre_init_ax(struct rtw89_dev *rtwdev)
return ret;
}
- rtw89_pci_power_wake(rtwdev, true);
+ rtw89_pci_power_wake_ax(rtwdev, true);
rtw89_pci_autoload_hang(rtwdev);
rtw89_pci_l12_vmain(rtwdev);
rtw89_pci_gen2_force_ib(rtwdev);
@@ -2912,6 +2914,13 @@ static int rtw89_pci_ops_mac_pre_init_ax(struct rtw89_dev *rtwdev)
return 0;
}
+static int rtw89_pci_ops_mac_pre_deinit_ax(struct rtw89_dev *rtwdev)
+{
+ rtw89_pci_power_wake_ax(rtwdev, false);
+
+ return 0;
+}
+
int rtw89_pci_ltr_set(struct rtw89_dev *rtwdev, bool en)
{
u32 val;
@@ -4325,7 +4334,7 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_ax = {
B_AX_RDU_INT},
.mac_pre_init = rtw89_pci_ops_mac_pre_init_ax,
- .mac_pre_deinit = NULL,
+ .mac_pre_deinit = rtw89_pci_ops_mac_pre_deinit_ax,
.mac_post_init = rtw89_pci_ops_mac_post_init_ax,
.clr_idx_all = rtw89_pci_clr_idx_all_ax,
@@ -4343,6 +4352,7 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_ax = {
.l1ss_set = rtw89_pci_l1ss_set_ax,
.disable_eq = rtw89_pci_disable_eq_ax,
+ .power_wake = rtw89_pci_power_wake_ax,
};
EXPORT_SYMBOL(rtw89_pci_gen_ax);
diff --git a/drivers/net/wireless/realtek/rtw89/pci.h b/drivers/net/wireless/realtek/rtw89/pci.h
index b68e2d82eea9..d52db4ca1b99 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.h
+++ b/drivers/net/wireless/realtek/rtw89/pci.h
@@ -1290,6 +1290,7 @@ struct rtw89_pci_gen_def {
void (*l1ss_set)(struct rtw89_dev *rtwdev, bool enable);
void (*disable_eq)(struct rtw89_dev *rtwdev);
+ void (*power_wake)(struct rtw89_dev *rtwdev, bool pwr_up);
};
#define RTW89_PCI_SSID(v, d, ssv, ssd, cust) \
@@ -1805,4 +1806,12 @@ static inline void rtw89_pci_disable_eq(struct rtw89_dev *rtwdev)
gen_def->disable_eq(rtwdev);
}
+static inline void rtw89_pci_power_wake(struct rtw89_dev *rtwdev, bool pwr_up)
+{
+ const struct rtw89_pci_info *info = rtwdev->pci_info;
+ const struct rtw89_pci_gen_def *gen_def = info->gen_def;
+
+ gen_def->power_wake(rtwdev, pwr_up);
+}
+
#endif
diff --git a/drivers/net/wireless/realtek/rtw89/pci_be.c b/drivers/net/wireless/realtek/rtw89/pci_be.c
index 34154506f5d4..cd39eebe8186 100644
--- a/drivers/net/wireless/realtek/rtw89/pci_be.c
+++ b/drivers/net/wireless/realtek/rtw89/pci_be.c
@@ -691,5 +691,6 @@ const struct rtw89_pci_gen_def rtw89_pci_gen_be = {
.l1ss_set = rtw89_pci_l1ss_set_be,
.disable_eq = rtw89_pci_disable_eq_be,
+ .power_wake = _patch_pcie_power_wake_be,
};
EXPORT_SYMBOL(rtw89_pci_gen_be);
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index f24aca663cf0..4e3754fd18fd 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -2,6 +2,7 @@
/* Copyright(c) 2019-2020 Realtek Corporation
*/
+#include "acpi.h"
#include "chan.h"
#include "coex.h"
#include "debug.h"
@@ -263,16 +264,26 @@ rtw89_ra_mask_eht_rates[4] = {RA_MASK_EHT_1SS_RATES, RA_MASK_EHT_2SS_RATES,
static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
struct rtw89_sta_link *rtwsta_link,
+ struct ieee80211_link_sta *link_sta,
const struct rtw89_chan *chan,
bool *fix_giltf_en, u8 *fix_giltf)
{
struct cfg80211_bitrate_mask *mask = &rtwsta_link->mask;
u8 band = chan->band_type;
enum nl80211_band nl_band = rtw89_hw_to_nl80211_band(band);
- u8 he_gi = mask->control[nl_band].he_gi;
u8 he_ltf = mask->control[nl_band].he_ltf;
+ u8 he_gi = mask->control[nl_band].he_gi;
- if (!rtwsta_link->use_cfg_mask)
+ *fix_giltf_en = true;
+
+ if (rtwdev->chip->chip_id == RTL8852C &&
+ chan->band_width == RTW89_CHANNEL_WIDTH_160 &&
+ rtw89_sta_link_has_su_mu_4xhe08(link_sta))
+ *fix_giltf = RTW89_GILTF_SGI_4XHE08;
+ else
+ *fix_giltf = RTW89_GILTF_2XHE08;
+
+ if (!(rtwsta_link->use_cfg_mask && link_sta->he_cap.has_he))
return;
if (he_ltf == 2 && he_gi == 2) {
@@ -287,12 +298,7 @@ static void rtw89_phy_ra_gi_ltf(struct rtw89_dev *rtwdev,
*fix_giltf = RTW89_GILTF_1XHE16;
} else if (he_ltf == 0 && he_gi == 0) {
*fix_giltf = RTW89_GILTF_1XHE08;
- } else {
- *fix_giltf_en = false;
- return;
}
-
- *fix_giltf_en = true;
}
static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
@@ -325,6 +331,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
mode |= RTW89_RA_MODE_EHT;
ra_mask |= get_eht_ra_mask(link_sta);
high_rate_masks = rtw89_ra_mask_eht_rates;
+ rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, link_sta,
+ chan, &fix_giltf_en, &fix_giltf);
} else if (link_sta->he_cap.has_he) {
mode |= RTW89_RA_MODE_HE;
csi_mode = RTW89_RA_RPT_MODE_HE;
@@ -336,7 +344,8 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
if (link_sta->he_cap.he_cap_elem.phy_cap_info[1] &
IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)
ldpc_en = 1;
- rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, chan, &fix_giltf_en, &fix_giltf);
+ rtw89_phy_ra_gi_ltf(rtwdev, rtwsta_link, link_sta,
+ chan, &fix_giltf_en, &fix_giltf);
} else if (link_sta->vht_cap.vht_supported) {
u16 mcs_map = le16_to_cpu(link_sta->vht_cap.vht_mcs.rx_mcs_map);
@@ -466,11 +475,11 @@ static void rtw89_phy_ra_sta_update(struct rtw89_dev *rtwdev,
ra->csi_mode = csi_mode;
}
-static void __rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev,
- struct rtw89_vif_link *rtwvif_link,
- struct rtw89_sta_link *rtwsta_link,
- u32 changed)
+void rtw89_phy_ra_update_sta_link(struct rtw89_dev *rtwdev,
+ struct rtw89_sta_link *rtwsta_link,
+ u32 changed)
{
+ struct rtw89_vif_link *rtwvif_link = rtwsta_link->rtwvif_link;
struct ieee80211_vif *vif = rtwvif_link_to_vif(rtwvif_link);
struct rtw89_ra_info *ra = &rtwsta_link->ra;
struct ieee80211_link_sta *link_sta;
@@ -503,14 +512,11 @@ void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta
u32 changed)
{
struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
- struct rtw89_vif_link *rtwvif_link;
struct rtw89_sta_link *rtwsta_link;
unsigned int link_id;
- rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id) {
- rtwvif_link = rtwsta_link->rtwvif_link;
- __rtw89_phy_ra_update_sta(rtwdev, rtwvif_link, rtwsta_link, changed);
- }
+ rtw89_sta_for_each_link(rtwsta, rtwsta_link, link_id)
+ rtw89_phy_ra_update_sta_link(rtwdev, rtwsta_link, changed);
}
static bool __check_rate_pattern(struct rtw89_phy_rate_pattern *next,
@@ -1854,6 +1860,228 @@ void rtw89_phy_write_reg3_tbl(struct rtw89_dev *rtwdev,
}
EXPORT_SYMBOL(rtw89_phy_write_reg3_tbl);
+static u8 rtw89_phy_ant_gain_domain_to_regd(struct rtw89_dev *rtwdev, u8 ant_gain_regd)
+{
+ switch (ant_gain_regd) {
+ case RTW89_ANT_GAIN_ETSI:
+ return RTW89_ETSI;
+ default:
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "unknown antenna gain domain: %d\n",
+ ant_gain_regd);
+ return RTW89_REGD_NUM;
+ }
+}
+
+/* antenna gain in unit of 0.25 dbm */
+#define RTW89_ANT_GAIN_2GHZ_MIN -8
+#define RTW89_ANT_GAIN_2GHZ_MAX 14
+#define RTW89_ANT_GAIN_5GHZ_MIN -8
+#define RTW89_ANT_GAIN_5GHZ_MAX 20
+#define RTW89_ANT_GAIN_6GHZ_MIN -8
+#define RTW89_ANT_GAIN_6GHZ_MAX 20
+
+#define RTW89_ANT_GAIN_REF_2GHZ 14
+#define RTW89_ANT_GAIN_REF_5GHZ 20
+#define RTW89_ANT_GAIN_REF_6GHZ 20
+
+void rtw89_phy_ant_gain_init(struct rtw89_dev *rtwdev)
+{
+ struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ struct rtw89_acpi_rtag_result res = {};
+ u32 domain;
+ int ret;
+ u8 i, j;
+ u8 regd;
+ u8 val;
+
+ if (!chip->support_ant_gain)
+ return;
+
+ ret = rtw89_acpi_evaluate_rtag(rtwdev, &res);
+ if (ret) {
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "acpi: cannot eval rtag: %d\n", ret);
+ return;
+ }
+
+ if (res.revision != 0) {
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "unknown rtag revision: %d\n", res.revision);
+ return;
+ }
+
+ domain = get_unaligned_le32(&res.domain);
+
+ for (i = 0; i < RTW89_ANT_GAIN_DOMAIN_NUM; i++) {
+ if (!(domain & BIT(i)))
+ continue;
+
+ regd = rtw89_phy_ant_gain_domain_to_regd(rtwdev, i);
+ if (regd >= RTW89_REGD_NUM)
+ continue;
+ ant_gain->regd_enabled |= BIT(regd);
+ }
+
+ for (i = 0; i < RTW89_ANT_GAIN_CHAIN_NUM; i++) {
+ for (j = 0; j < RTW89_ANT_GAIN_SUBBAND_NR; j++) {
+ val = res.ant_gain_table[i][j];
+ switch (j) {
+ default:
+ case RTW89_ANT_GAIN_2GHZ_SUBBAND:
+ val = RTW89_ANT_GAIN_REF_2GHZ -
+ clamp_t(s8, val,
+ RTW89_ANT_GAIN_2GHZ_MIN,
+ RTW89_ANT_GAIN_2GHZ_MAX);
+ break;
+ case RTW89_ANT_GAIN_5GHZ_SUBBAND_1:
+ case RTW89_ANT_GAIN_5GHZ_SUBBAND_2:
+ case RTW89_ANT_GAIN_5GHZ_SUBBAND_2E:
+ case RTW89_ANT_GAIN_5GHZ_SUBBAND_3_4:
+ val = RTW89_ANT_GAIN_REF_5GHZ -
+ clamp_t(s8, val,
+ RTW89_ANT_GAIN_5GHZ_MIN,
+ RTW89_ANT_GAIN_5GHZ_MAX);
+ break;
+ case RTW89_ANT_GAIN_6GHZ_SUBBAND_5_L:
+ case RTW89_ANT_GAIN_6GHZ_SUBBAND_5_H:
+ case RTW89_ANT_GAIN_6GHZ_SUBBAND_6:
+ case RTW89_ANT_GAIN_6GHZ_SUBBAND_7_L:
+ case RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H:
+ case RTW89_ANT_GAIN_6GHZ_SUBBAND_8:
+ val = RTW89_ANT_GAIN_REF_6GHZ -
+ clamp_t(s8, val,
+ RTW89_ANT_GAIN_6GHZ_MIN,
+ RTW89_ANT_GAIN_6GHZ_MAX);
+ }
+ ant_gain->offset[i][j] = val;
+ }
+ }
+}
+
+static
+enum rtw89_ant_gain_subband rtw89_phy_ant_gain_get_subband(struct rtw89_dev *rtwdev,
+ u32 center_freq)
+{
+ switch (center_freq) {
+ default:
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "center freq: %u to antenna gain subband is unhandled\n",
+ center_freq);
+ fallthrough;
+ case 2412 ... 2484:
+ return RTW89_ANT_GAIN_2GHZ_SUBBAND;
+ case 5180 ... 5240:
+ return RTW89_ANT_GAIN_5GHZ_SUBBAND_1;
+ case 5250 ... 5320:
+ return RTW89_ANT_GAIN_5GHZ_SUBBAND_2;
+ case 5500 ... 5720:
+ return RTW89_ANT_GAIN_5GHZ_SUBBAND_2E;
+ case 5745 ... 5885:
+ return RTW89_ANT_GAIN_5GHZ_SUBBAND_3_4;
+ case 5955 ... 6155:
+ return RTW89_ANT_GAIN_6GHZ_SUBBAND_5_L;
+ case 6175 ... 6415:
+ return RTW89_ANT_GAIN_6GHZ_SUBBAND_5_H;
+ case 6435 ... 6515:
+ return RTW89_ANT_GAIN_6GHZ_SUBBAND_6;
+ case 6535 ... 6695:
+ return RTW89_ANT_GAIN_6GHZ_SUBBAND_7_L;
+ case 6715 ... 6855:
+ return RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H;
+
+ /* freq 6875 (ch 185, 20MHz) spans RTW89_ANT_GAIN_6GHZ_SUBBAND_7_H
+ * and RTW89_ANT_GAIN_6GHZ_SUBBAND_8, so directly describe it with
+ * struct rtw89_6ghz_span.
+ */
+
+ case 6895 ... 7115:
+ return RTW89_ANT_GAIN_6GHZ_SUBBAND_8;
+ }
+}
+
+static s8 rtw89_phy_ant_gain_query(struct rtw89_dev *rtwdev,
+ enum rtw89_rf_path path, u32 center_freq)
+{
+ struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
+ enum rtw89_ant_gain_subband subband_l, subband_h;
+ const struct rtw89_6ghz_span *span;
+
+ span = rtw89_get_6ghz_span(rtwdev, center_freq);
+
+ if (span && RTW89_ANT_GAIN_SPAN_VALID(span)) {
+ subband_l = span->ant_gain_subband_low;
+ subband_h = span->ant_gain_subband_high;
+ } else {
+ subband_l = rtw89_phy_ant_gain_get_subband(rtwdev, center_freq);
+ subband_h = subband_l;
+ }
+
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
+ "center_freq %u: antenna gain subband {%u, %u}\n",
+ center_freq, subband_l, subband_h);
+
+ return min(ant_gain->offset[path][subband_l],
+ ant_gain->offset[path][subband_h]);
+}
+
+static s8 rtw89_phy_ant_gain_offset(struct rtw89_dev *rtwdev, u8 band, u32 center_freq)
+{
+ struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ u8 regd = rtw89_regd_get(rtwdev, band);
+ s8 offset_patha, offset_pathb;
+
+ if (!chip->support_ant_gain)
+ return 0;
+
+ if (!(ant_gain->regd_enabled & BIT(regd)))
+ return 0;
+
+ offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, center_freq);
+ offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, center_freq);
+
+ return max(offset_patha, offset_pathb);
+}
+
+s16 rtw89_phy_ant_gain_pwr_offset(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan)
+{
+ struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
+ u8 regd = rtw89_regd_get(rtwdev, chan->band_type);
+ s8 offset_patha, offset_pathb;
+
+ if (!(ant_gain->regd_enabled & BIT(regd)))
+ return 0;
+
+ offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, chan->freq);
+ offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, chan->freq);
+
+ return rtw89_phy_txpwr_rf_to_bb(rtwdev, offset_patha - offset_pathb);
+}
+EXPORT_SYMBOL(rtw89_phy_ant_gain_pwr_offset);
+
+void rtw89_print_ant_gain(struct seq_file *m, struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan)
+{
+ struct rtw89_ant_gain_info *ant_gain = &rtwdev->ant_gain;
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+ u8 regd = rtw89_regd_get(rtwdev, chan->band_type);
+ s8 offset_patha, offset_pathb;
+
+ if (!chip->support_ant_gain || !(ant_gain->regd_enabled & BIT(regd))) {
+ seq_puts(m, "no DAG is applied\n");
+ return;
+ }
+
+ offset_patha = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_A, chan->freq);
+ offset_pathb = rtw89_phy_ant_gain_query(rtwdev, RF_PATH_B, chan->freq);
+
+ seq_printf(m, "ChainA offset: %d dBm\n", offset_patha);
+ seq_printf(m, "ChainB offset: %d dBm\n", offset_pathb);
+}
+
static const u8 rtw89_rs_idx_num_ax[] = {
[RTW89_RS_CCK] = RTW89_RATE_CCK_NUM,
[RTW89_RS_OFDM] = RTW89_RATE_OFDM_NUM,
@@ -1917,20 +2145,6 @@ void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
}
EXPORT_SYMBOL(rtw89_phy_load_txpwr_byrate);
-static s8 rtw89_phy_txpwr_rf_to_mac(struct rtw89_dev *rtwdev, s8 txpwr_rf)
-{
- const struct rtw89_chip_info *chip = rtwdev->chip;
-
- return txpwr_rf >> (chip->txpwr_factor_rf - chip->txpwr_factor_mac);
-}
-
-static s8 rtw89_phy_txpwr_dbm_to_mac(struct rtw89_dev *rtwdev, s8 dbm)
-{
- const struct rtw89_chip_info *chip = rtwdev->chip;
-
- return clamp_t(s16, dbm << chip->txpwr_factor_mac, -64, 63);
-}
-
static s8 rtw89_phy_txpwr_dbm_without_tolerance(s8 dbm)
{
const u8 tssi_deviation_point = 0;
@@ -2027,7 +2241,7 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
u8 regd = rtw89_regd_get(rtwdev, band);
u8 reg6 = regulatory->reg_6ghz_power;
- s8 lmt = 0, sar;
+ s8 lmt = 0, sar, offset;
s8 cstr;
switch (band) {
@@ -2059,7 +2273,8 @@ s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
return 0;
}
- lmt = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt);
+ offset = rtw89_phy_ant_gain_offset(rtwdev, band, freq);
+ lmt = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt + offset);
sar = rtw89_query_sar(rtwdev, freq);
cstr = rtw89_phy_get_tpe_constraint(rtwdev, band);
@@ -2286,7 +2501,7 @@ s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
u8 ch_idx = rtw89_channel_to_idx(rtwdev, band, ch);
u8 regd = rtw89_regd_get(rtwdev, band);
u8 reg6 = regulatory->reg_6ghz_power;
- s8 lmt_ru = 0, sar;
+ s8 lmt_ru = 0, sar, offset;
s8 cstr;
switch (band) {
@@ -2318,7 +2533,8 @@ s8 rtw89_phy_read_txpwr_limit_ru(struct rtw89_dev *rtwdev, u8 band,
return 0;
}
- lmt_ru = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt_ru);
+ offset = rtw89_phy_ant_gain_offset(rtwdev, band, freq);
+ lmt_ru = rtw89_phy_txpwr_rf_to_mac(rtwdev, lmt_ru + offset);
sar = rtw89_query_sar(rtwdev, freq);
cstr = rtw89_phy_get_tpe_constraint(rtwdev, band);
@@ -3228,10 +3444,16 @@ rtw89_phy_c2h_rfk_report_state(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u3
(int)(len - sizeof(report->hdr)), &report->state);
}
+static void
+rtw89_phy_c2h_rfk_log_tas_pwr(struct rtw89_dev *rtwdev, struct sk_buff *c2h, u32 len)
+{
+}
+
static
void (* const rtw89_phy_c2h_rfk_report_handler[])(struct rtw89_dev *rtwdev,
struct sk_buff *c2h, u32 len) = {
[RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE] = rtw89_phy_c2h_rfk_report_state,
+ [RTW89_PHY_C2H_RFK_LOG_TAS_PWR] = rtw89_phy_c2h_rfk_log_tas_pwr,
};
bool rtw89_phy_c2h_chk_atomic(struct rtw89_dev *rtwdev, u8 class, u8 func)
@@ -3285,11 +3507,11 @@ void rtw89_phy_c2h_handle(struct rtw89_dev *rtwdev, struct sk_buff *skb,
return;
fallthrough;
default:
- rtw89_info(rtwdev, "c2h class %d not support\n", class);
+ rtw89_info(rtwdev, "PHY c2h class %d not support\n", class);
return;
}
if (!handler) {
- rtw89_info(rtwdev, "c2h class %d func %d not support\n", class,
+ rtw89_info(rtwdev, "PHY c2h class %d func %d not support\n", class,
func);
return;
}
@@ -4058,7 +4280,6 @@ static void rtw89_phy_cfo_set_crystal_cap(struct rtw89_dev *rtwdev,
if (!force && cfo->crystal_cap == crystal_cap)
return;
- crystal_cap = clamp_t(u8, crystal_cap, 0, 127);
if (chip->chip_id == RTL8852A || chip->chip_id == RTL8851B) {
rtw89_phy_cfo_set_xcap_reg(rtwdev, true, crystal_cap);
rtw89_phy_cfo_set_xcap_reg(rtwdev, false, crystal_cap);
@@ -4181,7 +4402,7 @@ static void rtw89_phy_cfo_crystal_cap_adjust(struct rtw89_dev *rtwdev,
s32 curr_cfo)
{
struct rtw89_cfo_tracking_info *cfo = &rtwdev->cfo_tracking;
- s8 crystal_cap = cfo->crystal_cap;
+ int crystal_cap = cfo->crystal_cap;
s32 cfo_abs = abs(curr_cfo);
int sign;
@@ -4202,15 +4423,17 @@ static void rtw89_phy_cfo_crystal_cap_adjust(struct rtw89_dev *rtwdev,
}
sign = curr_cfo > 0 ? 1 : -1;
if (cfo_abs > CFO_TRK_STOP_TH_4)
- crystal_cap += 7 * sign;
+ crystal_cap += 3 * sign;
else if (cfo_abs > CFO_TRK_STOP_TH_3)
- crystal_cap += 5 * sign;
- else if (cfo_abs > CFO_TRK_STOP_TH_2)
crystal_cap += 3 * sign;
+ else if (cfo_abs > CFO_TRK_STOP_TH_2)
+ crystal_cap += 1 * sign;
else if (cfo_abs > CFO_TRK_STOP_TH_1)
crystal_cap += 1 * sign;
else
return;
+
+ crystal_cap = clamp(crystal_cap, 0, 127);
rtw89_phy_cfo_set_crystal_cap(rtwdev, (u8)crystal_cap, false);
rtw89_debug(rtwdev, RTW89_DBG_CFO,
"X_cap{Curr,Default}={0x%x,0x%x}\n",
@@ -6310,6 +6533,12 @@ void rtw89_phy_dm_init(struct rtw89_dev *rtwdev)
rtw89_chip_cfg_txrx_path(rtwdev);
}
+void rtw89_phy_dm_reinit(struct rtw89_dev *rtwdev)
+{
+ rtw89_phy_env_monitor_init(rtwdev);
+ rtw89_physts_parsing_init(rtwdev);
+}
+
void rtw89_phy_set_bss_color(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link)
{
diff --git a/drivers/net/wireless/realtek/rtw89/phy.h b/drivers/net/wireless/realtek/rtw89/phy.h
index c683f4d7d29b..697ee47fe325 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.h
+++ b/drivers/net/wireless/realtek/rtw89/phy.h
@@ -57,7 +57,7 @@
#define CFO_TRK_STOP_TH_4 (30 << 2)
#define CFO_TRK_STOP_TH_3 (20 << 2)
#define CFO_TRK_STOP_TH_2 (10 << 2)
-#define CFO_TRK_STOP_TH_1 (00 << 2)
+#define CFO_TRK_STOP_TH_1 (03 << 2)
#define CFO_TRK_STOP_TH (2 << 2)
#define CFO_SW_COMP_FINE_TUNE (2 << 2)
#define CFO_PERIOD_CNT 15
@@ -151,6 +151,7 @@ enum rtw89_phy_c2h_rfk_log_func {
enum rtw89_phy_c2h_rfk_report_func {
RTW89_PHY_C2H_RFK_REPORT_FUNC_STATE = 0,
+ RTW89_PHY_C2H_RFK_LOG_TAS_PWR = 6,
};
enum rtw89_phy_c2h_dm_func {
@@ -813,6 +814,7 @@ void rtw89_phy_config_rf_reg_v1(struct rtw89_dev *rtwdev,
enum rtw89_rf_path rf_path,
void *extra_data);
void rtw89_phy_dm_init(struct rtw89_dev *rtwdev);
+void rtw89_phy_dm_reinit(struct rtw89_dev *rtwdev);
void rtw89_phy_write32_idx(struct rtw89_dev *rtwdev, u32 addr, u32 mask,
u32 data, enum rtw89_phy_idx phy_idx);
void rtw89_phy_write32_idx_set(struct rtw89_dev *rtwdev, u32 addr, u32 bits,
@@ -826,6 +828,11 @@ s8 *rtw89_phy_raw_byr_seek(struct rtw89_dev *rtwdev,
const struct rtw89_rate_desc *desc);
s8 rtw89_phy_read_txpwr_byrate(struct rtw89_dev *rtwdev, u8 band, u8 bw,
const struct rtw89_rate_desc *rate_desc);
+void rtw89_phy_ant_gain_init(struct rtw89_dev *rtwdev);
+s16 rtw89_phy_ant_gain_pwr_offset(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan);
+void rtw89_print_ant_gain(struct seq_file *m, struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan);
void rtw89_phy_load_txpwr_byrate(struct rtw89_dev *rtwdev,
const struct rtw89_txpwr_table *tbl);
s8 rtw89_phy_read_txpwr_limit(struct rtw89_dev *rtwdev, u8 band,
@@ -896,10 +903,34 @@ void rtw89_phy_set_txpwr_limit_ru(struct rtw89_dev *rtwdev,
phy->set_txpwr_limit_ru(rtwdev, chan, phy_idx);
}
+static inline s8 rtw89_phy_txpwr_rf_to_bb(struct rtw89_dev *rtwdev, s8 txpwr_rf)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ return txpwr_rf << (chip->txpwr_factor_bb - chip->txpwr_factor_rf);
+}
+
+static inline s8 rtw89_phy_txpwr_rf_to_mac(struct rtw89_dev *rtwdev, s8 txpwr_rf)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ return txpwr_rf >> (chip->txpwr_factor_rf - chip->txpwr_factor_mac);
+}
+
+static inline s8 rtw89_phy_txpwr_dbm_to_mac(struct rtw89_dev *rtwdev, s8 dbm)
+{
+ const struct rtw89_chip_info *chip = rtwdev->chip;
+
+ return clamp_t(s16, dbm << chip->txpwr_factor_mac, -64, 63);
+}
+
void rtw89_phy_ra_assoc(struct rtw89_dev *rtwdev, struct rtw89_sta_link *rtwsta_link);
void rtw89_phy_ra_update(struct rtw89_dev *rtwdev);
void rtw89_phy_ra_update_sta(struct rtw89_dev *rtwdev, struct ieee80211_sta *sta,
u32 changed);
+void rtw89_phy_ra_update_sta_link(struct rtw89_dev *rtwdev,
+ struct rtw89_sta_link *rtwsta_link,
+ 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/ps.c b/drivers/net/wireless/realtek/rtw89/ps.c
index c1c12abc2ea9..96ea04d90cd3 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.c
+++ b/drivers/net/wireless/realtek/rtw89/ps.c
@@ -8,6 +8,7 @@
#include "debug.h"
#include "fw.h"
#include "mac.h"
+#include "phy.h"
#include "ps.h"
#include "reg.h"
#include "util.h"
@@ -62,11 +63,8 @@ static void rtw89_ps_power_mode_change(struct rtw89_dev *rtwdev, bool enter)
rtw89_mac_power_mode_change(rtwdev, enter);
}
-void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link)
+void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev)
{
- if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT)
- return;
-
if (!rtwdev->ps_mode)
return;
@@ -85,8 +83,8 @@ void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
rtw89_ps_power_mode_change(rtwdev, false);
}
-static void __rtw89_enter_lps(struct rtw89_dev *rtwdev,
- struct rtw89_vif_link *rtwvif_link)
+static void __rtw89_enter_lps_link(struct rtw89_dev *rtwdev,
+ struct rtw89_vif_link *rtwvif_link)
{
struct rtw89_lps_parm lps_param = {
.macid = rtwvif_link->mac_id,
@@ -96,7 +94,6 @@ static void __rtw89_enter_lps(struct rtw89_dev *rtwdev,
rtw89_btc_ntfy_radio_state(rtwdev, BTC_RFCTRL_FW_CTRL);
rtw89_fw_h2c_lps_parm(rtwdev, &lps_param);
- rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif_link);
}
static void __rtw89_leave_lps(struct rtw89_dev *rtwdev,
@@ -121,17 +118,32 @@ void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev)
__rtw89_leave_ps_mode(rtwdev);
}
-void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
+void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
bool ps_mode)
{
+ struct rtw89_vif_link *rtwvif_link;
+ bool can_ps_mode = true;
+ unsigned int link_id;
+
lockdep_assert_held(&rtwdev->mutex);
if (test_and_set_bit(RTW89_FLAG_LEISURE_PS, rtwdev->flags))
return;
- __rtw89_enter_lps(rtwdev, rtwvif_link);
- if (ps_mode)
- __rtw89_enter_ps_mode(rtwdev, rtwvif_link);
+ rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id) {
+ __rtw89_enter_lps_link(rtwdev, rtwvif_link);
+
+ if (rtwvif_link->wifi_role == RTW89_WIFI_ROLE_P2P_CLIENT)
+ can_ps_mode = false;
+ }
+
+ if (RTW89_CHK_FW_FEATURE(LPS_CH_INFO, &rtwdev->fw))
+ rtw89_fw_h2c_lps_ch_info(rtwdev, rtwvif);
+ else
+ rtw89_fw_h2c_lps_ml_cmn_info(rtwdev, rtwvif);
+
+ if (ps_mode && can_ps_mode)
+ __rtw89_enter_ps_mode(rtwdev);
}
static void rtw89_leave_lps_vif(struct rtw89_dev *rtwdev,
@@ -157,6 +169,8 @@ void rtw89_leave_lps(struct rtw89_dev *rtwdev)
__rtw89_leave_ps_mode(rtwdev);
+ rtw89_phy_dm_reinit(rtwdev);
+
rtw89_for_each_rtwvif(rtwdev, rtwvif)
rtw89_vif_for_each_link(rtwvif, rtwvif_link, link_id)
rtw89_leave_lps_vif(rtwdev, rtwvif_link);
@@ -282,12 +296,6 @@ void rtw89_recalc_lps(struct rtw89_dev *rtwdev)
enum rtw89_entity_mode mode;
int count = 0;
- /* FIXME: Fix rtw89_enter_lps() and __rtw89_enter_ps_mode()
- * to take MLO cases into account before doing the following.
- */
- if (rtwdev->support_mlo)
- goto disable_lps;
-
mode = rtw89_get_entity_mode(rtwdev);
if (mode == RTW89_ENTITY_MODE_MCC)
goto disable_lps;
diff --git a/drivers/net/wireless/realtek/rtw89/ps.h b/drivers/net/wireless/realtek/rtw89/ps.h
index cdd712966b09..2b88f254a32d 100644
--- a/drivers/net/wireless/realtek/rtw89/ps.h
+++ b/drivers/net/wireless/realtek/rtw89/ps.h
@@ -5,11 +5,11 @@
#ifndef __RTW89_PS_H_
#define __RTW89_PS_H_
-void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link,
+void rtw89_enter_lps(struct rtw89_dev *rtwdev, struct rtw89_vif *rtwvif,
bool ps_mode);
void rtw89_leave_lps(struct rtw89_dev *rtwdev);
void __rtw89_leave_ps_mode(struct rtw89_dev *rtwdev);
-void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev, struct rtw89_vif_link *rtwvif_link);
+void __rtw89_enter_ps_mode(struct rtw89_dev *rtwdev);
void rtw89_leave_ps_mode(struct rtw89_dev *rtwdev);
void rtw89_enter_ips(struct rtw89_dev *rtwdev);
void rtw89_leave_ips(struct rtw89_dev *rtwdev);
diff --git a/drivers/net/wireless/realtek/rtw89/reg.h b/drivers/net/wireless/realtek/rtw89/reg.h
index 18ec7c0252fb..10d0efa7a58e 100644
--- a/drivers/net/wireless/realtek/rtw89/reg.h
+++ b/drivers/net/wireless/realtek/rtw89/reg.h
@@ -7447,6 +7447,10 @@
#define B_BE_CSIPRT_HESU_AID_EN BIT(25)
#define B_BE_CSIPRT_VHTSU_AID_EN BIT(24)
+#define R_BE_DRV_INFO_OPTION 0x11470
+#define R_BE_DRV_INFO_OPTION_C1 0x15470
+#define B_BE_DRV_INFO_PHYRPT_EN BIT(0)
+
#define R_BE_RX_ERR_ISR 0x114F4
#define R_BE_RX_ERR_ISR_C1 0x154F4
#define B_BE_RX_ERR_TRIG_ACT_TO BIT(9)
diff --git a/drivers/net/wireless/realtek/rtw89/regd.c b/drivers/net/wireless/realtek/rtw89/regd.c
index cad5189708e7..80b2f74589eb 100644
--- a/drivers/net/wireless/realtek/rtw89/regd.c
+++ b/drivers/net/wireless/realtek/rtw89/regd.c
@@ -17,7 +17,7 @@ static const struct rtw89_regd rtw89_ww_regd =
static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("AR", RTW89_MEXICO, RTW89_MEXICO, RTW89_FCC),
- COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("BO", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("BR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("CL", RTW89_CHILE, RTW89_CHILE, RTW89_CHILE),
COUNTRY_REGD("CO", RTW89_FCC, RTW89_FCC, RTW89_FCC),
@@ -35,7 +35,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("UY", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("VE", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("PR", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("DO", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("DO", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("AT", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("BE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
@@ -72,7 +72,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("BA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("BG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("HR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
- COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("EG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("GH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("IQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("IL", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
@@ -82,13 +82,13 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("KW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("KG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LB", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
- COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("LS", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
- COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("MZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("NA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("NG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("OM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("QA", RTW89_QATAR, RTW89_QATAR, RTW89_QATAR),
COUNTRY_REGD("RO", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("RU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -101,7 +101,7 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("UA", RTW89_UKRAINE, RTW89_UKRAINE, RTW89_UKRAINE),
COUNTRY_REGD("AE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("YE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("ZW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("ZW", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("BD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("KH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CN", RTW89_CN, RTW89_CN, RTW89_CN),
@@ -110,12 +110,12 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("ID", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("KR", RTW89_KCC, RTW89_KCC, RTW89_KCC),
COUNTRY_REGD("MY", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
- COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("PK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("PH", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("SG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("TW", RTW89_FCC, RTW89_FCC, RTW89_ETSI),
- COUNTRY_REGD("TH", RTW89_ETSI, RTW89_ETSI, RTW89_THAILAND),
+ COUNTRY_REGD("TH", RTW89_THAILAND, RTW89_THAILAND, RTW89_THAILAND),
COUNTRY_REGD("VN", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("AU", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA),
COUNTRY_REGD("NZ", RTW89_ACMA, RTW89_ACMA, RTW89_ACMA),
@@ -158,9 +158,9 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("TD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CX", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
COUNTRY_REGD("CC", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
- COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
- COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("KM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("CG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("CD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("CK", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("CI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("DJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
@@ -176,12 +176,12 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("TF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GA", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GM", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
- COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("GE", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
+ COUNTRY_REGD("GI", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("GL", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GD", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("GP", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("GU", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("GG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("GN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("GW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -194,19 +194,19 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("KI", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("XK", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LA", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
- COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("LR", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("LY", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MV", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ML", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("MH", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("MQ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("MU", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("YT", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("FM", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("MD", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MN", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("MS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -216,15 +216,15 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("NE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("NU", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
COUNTRY_REGD("NF", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
- COUNTRY_REGD("MP", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("PW", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("MP", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("PW", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("RE", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("RW", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("KN", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("LC", RTW89_FCC, RTW89_FCC, RTW89_FCC),
- COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_NA),
- COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("MF", RTW89_FCC, RTW89_FCC, RTW89_FCC),
+ COUNTRY_REGD("SX", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("PM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("VC", RTW89_FCC, RTW89_FCC, RTW89_NA),
COUNTRY_REGD("WS", RTW89_FCC, RTW89_FCC, RTW89_NA),
@@ -237,9 +237,9 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("GS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("SR", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("SJ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("SZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("TJ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
- COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("TZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("TG", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("TK", RTW89_ACMA, RTW89_ACMA, RTW89_NA),
COUNTRY_REGD("TO", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
@@ -247,13 +247,16 @@ static const struct rtw89_regd rtw89_regd_map[] = {
COUNTRY_REGD("TC", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("TV", RTW89_ETSI, RTW89_NA, RTW89_NA),
COUNTRY_REGD("UG", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
- COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_NA),
+ COUNTRY_REGD("VI", RTW89_FCC, RTW89_FCC, RTW89_FCC),
COUNTRY_REGD("UZ", RTW89_ETSI, RTW89_ETSI, RTW89_ETSI),
COUNTRY_REGD("VU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("WF", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("EH", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("ZM", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("CU", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("IR", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
+ COUNTRY_REGD("SY", RTW89_ETSI, RTW89_NA, RTW89_NA),
+ COUNTRY_REGD("SD", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
COUNTRY_REGD("PS", RTW89_ETSI, RTW89_ETSI, RTW89_NA),
};
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b.c b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
index 68c67a763f4d..c56f70267882 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b.c
@@ -2298,7 +2298,8 @@ static void rtw8851b_query_ppdu(struct rtw89_dev *rtwdev,
u8 path;
u8 *rx_power = phy_ppdu->rssi;
- status->signal = RTW89_RSSI_RAW_TO_DBM(rx_power[RF_PATH_A]);
+ if (!status->signal)
+ status->signal = RTW89_RSSI_RAW_TO_DBM(rx_power[RF_PATH_A]);
for (path = 0; path < rtwdev->chip->rf_path_num; path++) {
status->chains |= BIT(path);
@@ -2391,6 +2392,7 @@ static const struct rtw89_chip_ops rtw8851b_chip_ops = {
.ctrl_btg_bt_rx = rtw8851b_ctrl_btg_bt_rx,
.query_ppdu = rtw8851b_query_ppdu,
.convert_rpl_to_rssi = NULL,
+ .phy_rpt_to_rssi = NULL,
.ctrl_nbtg_bt_tx = rtw8851b_ctrl_nbtg_bt_tx,
.cfg_txrx_path = rtw8851b_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = rtw8851b_set_txpwr_ul_tb_offset,
@@ -2464,6 +2466,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
.nctl_post_table = &rtw8851b_nctl_post_defs_tbl,
.dflt_parms = &rtw89_8851b_dflt_parms,
.rfe_parms_conf = rtw89_8851b_rfe_parms_conf,
+ .txpwr_factor_bb = 3,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
.dig_table = NULL,
@@ -2479,6 +2482,7 @@ const struct rtw89_chip_info rtw8851b_chip_info = {
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80),
.support_unii4 = true,
+ .support_ant_gain = false,
.ul_tb_waveform_ctrl = true,
.ul_tb_pwr_diff = false,
.hw_sec_hdr = false,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c
index 364e36354225..f72b3ac6f149 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851b_rfk.c
@@ -2199,7 +2199,7 @@ static u8 _dpk_agc(struct rtw89_dev *rtwdev, enum rtw89_phy_idx phy,
if (dgain > 0x5fc || dgain < 0x556) {
_dpk_one_shot(rtwdev, phy, path, D_SYNC);
- dgain = _dpk_dgain_read(rtwdev);
+ _dpk_dgain_read(rtwdev);
}
if (agc_cnt == 0) {
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852a.c b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
index e647759ebd69..9bd2842c27d5 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852a.c
@@ -2068,7 +2068,9 @@ static void rtw8852a_query_ppdu(struct rtw89_dev *rtwdev,
u8 path;
u8 *rx_power = phy_ppdu->rssi;
- status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], rx_power[RF_PATH_B]));
+ if (!status->signal)
+ status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A],
+ rx_power[RF_PATH_B]));
for (path = 0; path < rtwdev->chip->rf_path_num; path++) {
status->chains |= BIT(path);
status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]);
@@ -2116,6 +2118,7 @@ static const struct rtw89_chip_ops rtw8852a_chip_ops = {
.ctrl_btg_bt_rx = rtw8852a_ctrl_btg_bt_rx,
.query_ppdu = rtw8852a_query_ppdu,
.convert_rpl_to_rssi = NULL,
+ .phy_rpt_to_rssi = NULL,
.ctrl_nbtg_bt_tx = rtw8852a_ctrl_nbtg_bt_tx,
.cfg_txrx_path = NULL,
.set_txpwr_ul_tb_offset = rtw8852a_set_txpwr_ul_tb_offset,
@@ -2181,6 +2184,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
.nctl_post_table = NULL,
.dflt_parms = &rtw89_8852a_dflt_parms,
.rfe_parms_conf = NULL,
+ .txpwr_factor_bb = 3,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
.dig_table = &rtw89_8852a_phy_dig_table,
@@ -2196,6 +2200,7 @@ const struct rtw89_chip_info rtw8852a_chip_info = {
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80),
.support_unii4 = false,
+ .support_ant_gain = false,
.ul_tb_waveform_ctrl = false,
.ul_tb_pwr_diff = false,
.hw_sec_hdr = false,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
index 49a319128316..dfb2bf61b0b8 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
@@ -745,6 +745,7 @@ static const struct rtw89_chip_ops rtw8852b_chip_ops = {
.ctrl_btg_bt_rx = rtw8852bx_ctrl_btg_bt_rx,
.query_ppdu = rtw8852bx_query_ppdu,
.convert_rpl_to_rssi = rtw8852bx_convert_rpl_to_rssi,
+ .phy_rpt_to_rssi = NULL,
.ctrl_nbtg_bt_tx = rtw8852bx_ctrl_nbtg_bt_tx,
.cfg_txrx_path = rtw8852bx_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = rtw8852bx_set_txpwr_ul_tb_offset,
@@ -819,6 +820,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
.nctl_post_table = NULL,
.dflt_parms = &rtw89_8852b_dflt_parms,
.rfe_parms_conf = NULL,
+ .txpwr_factor_bb = 3,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
.dig_table = NULL,
@@ -834,6 +836,7 @@ const struct rtw89_chip_info rtw8852b_chip_info = {
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80),
.support_unii4 = true,
+ .support_ant_gain = true,
.ul_tb_waveform_ctrl = true,
.ul_tb_pwr_diff = false,
.hw_sec_hdr = false,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
index f4aa4437fb75..0e094ce9c9b0 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852b_common.c
@@ -1206,24 +1206,25 @@ void __rtw8852bx_set_channel_bb(struct rtw89_dev *rtwdev, const struct rtw89_cha
}
static u32 rtw8852bx_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
- enum rtw89_phy_idx phy_idx, s16 ref)
+ enum rtw89_phy_idx phy_idx,
+ s16 ref, u16 pwr_ofst_decrease)
{
const u16 tssi_16dbm_cw = 0x12c;
const u8 base_cw_0db = 0x27;
- const s8 ofst_int = 0;
s16 pwr_s10_3;
s16 rf_pwr_cw;
u16 bb_pwr_cw;
u32 pwr_cw;
u32 tssi_ofst_cw;
- pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3);
+ pwr_s10_3 = (ref << 1) + (s16)(base_cw_0db << 3) - pwr_ofst_decrease;
bb_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(2, 0));
rf_pwr_cw = u16_get_bits(pwr_s10_3, GENMASK(8, 3));
rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63);
pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw;
- tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3));
+ tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)) -
+ pwr_ofst_decrease;
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
"[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n",
tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw);
@@ -1234,10 +1235,11 @@ static u32 rtw8852bx_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
}
static void rtw8852bx_set_txpwr_ref(struct rtw89_dev *rtwdev,
- enum rtw89_phy_idx phy_idx)
+ enum rtw89_phy_idx phy_idx, s16 pwr_ofst)
{
static const u32 addr[RF_PATH_NUM_8852BX] = {0x5800, 0x7800};
const u32 mask = B_DPD_TSSI_CW | B_DPD_PWR_CW | B_DPD_REF;
+ u16 ofst_dec[RF_PATH_NUM_8852BX];
const u8 ofst_ofdm = 0x4;
const u8 ofst_cck = 0x8;
const s16 ref_ofdm = 0;
@@ -1250,19 +1252,20 @@ static void rtw8852bx_set_txpwr_ref(struct rtw89_dev *rtwdev,
rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL,
B_AX_PWR_REF, 0x0);
- rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n");
- val = rtw8852bx_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm);
+ ofst_dec[RF_PATH_A] = pwr_ofst > 0 ? 0 : abs(pwr_ofst);
+ ofst_dec[RF_PATH_B] = pwr_ofst > 0 ? pwr_ofst : 0;
- for (i = 0; i < RF_PATH_NUM_8852BX; i++)
- rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val,
- phy_idx);
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n");
+ for (i = 0; i < RF_PATH_NUM_8852BX; i++) {
+ val = rtw8852bx_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm, ofst_dec[i]);
+ rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, phy_idx);
+ }
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n");
- val = rtw8852bx_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck);
-
- for (i = 0; i < RF_PATH_NUM_8852BX; i++)
- rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val,
- phy_idx);
+ for (i = 0; i < RF_PATH_NUM_8852BX; i++) {
+ val = rtw8852bx_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck, ofst_dec[i]);
+ rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, phy_idx);
+ }
}
static void rtw8852bx_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev,
@@ -1333,6 +1336,16 @@ static void rtw8852bx_set_tx_shape(struct rtw89_dev *rtwdev,
tx_shape_ofdm);
}
+static void rtw8852bx_set_txpwr_diff(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ s16 pwr_ofst;
+
+ pwr_ofst = rtw89_phy_ant_gain_pwr_offset(rtwdev, chan);
+ rtw8852bx_set_txpwr_ref(rtwdev, phy_idx, pwr_ofst);
+}
+
static void __rtw8852bx_set_txpwr(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
@@ -1342,12 +1355,13 @@ static void __rtw8852bx_set_txpwr(struct rtw89_dev *rtwdev,
rtw8852bx_set_tx_shape(rtwdev, chan, phy_idx);
rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx);
rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
+ rtw8852bx_set_txpwr_diff(rtwdev, chan, phy_idx);
}
static void __rtw8852bx_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx)
{
- rtw8852bx_set_txpwr_ref(rtwdev, phy_idx);
+ rtw8852bx_set_txpwr_ref(rtwdev, phy_idx, 0);
}
static
@@ -1936,7 +1950,9 @@ static void __rtw8852bx_query_ppdu(struct rtw89_dev *rtwdev,
u8 path;
u8 *rx_power = phy_ppdu->rssi;
- status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], rx_power[RF_PATH_B]));
+ if (!status->signal)
+ status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A],
+ rx_power[RF_PATH_B]));
for (path = 0; path < rtwdev->chip->rf_path_num; path++) {
status->chains |= BIT(path);
status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]);
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
index 876725133228..bde3e1fb7ca6 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bt.c
@@ -679,6 +679,7 @@ static const struct rtw89_chip_ops rtw8852bt_chip_ops = {
.ctrl_btg_bt_rx = rtw8852bx_ctrl_btg_bt_rx,
.query_ppdu = rtw8852bx_query_ppdu,
.convert_rpl_to_rssi = rtw8852bx_convert_rpl_to_rssi,
+ .phy_rpt_to_rssi = NULL,
.ctrl_nbtg_bt_tx = rtw8852bx_ctrl_nbtg_bt_tx,
.cfg_txrx_path = rtw8852bx_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = rtw8852bx_set_txpwr_ul_tb_offset,
@@ -752,6 +753,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
.nctl_post_table = NULL,
.dflt_parms = NULL,
.rfe_parms_conf = NULL,
+ .txpwr_factor_bb = 3,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
.dig_table = NULL,
@@ -767,6 +769,7 @@ const struct rtw89_chip_info rtw8852bt_chip_info = {
BIT(NL80211_CHAN_WIDTH_40) |
BIT(NL80211_CHAN_WIDTH_80),
.support_unii4 = true,
+ .support_ant_gain = true,
.ul_tb_waveform_ctrl = true,
.ul_tb_pwr_diff = false,
.hw_sec_hdr = false,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c.c b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
index cde34f8e1e67..bc84b15e7826 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c.c
@@ -1882,9 +1882,9 @@ static void rtw8852c_rfk_track(struct rtw89_dev *rtwdev)
}
static u32 rtw8852c_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
- enum rtw89_phy_idx phy_idx, s16 ref)
+ enum rtw89_phy_idx phy_idx,
+ s16 ref, u16 pwr_ofst_decrease)
{
- s8 ofst_int = 0;
u8 base_cw_0db = 0x27;
u16 tssi_16dbm_cw = 0x12c;
s16 pwr_s10_3 = 0;
@@ -1893,13 +1893,14 @@ static u32 rtw8852c_bb_cal_txpwr_ref(struct rtw89_dev *rtwdev,
u32 pwr_cw = 0;
u32 tssi_ofst_cw = 0;
- pwr_s10_3 = (ref << 1) + (s16)(ofst_int) + (s16)(base_cw_0db << 3);
+ pwr_s10_3 = (ref << 1) + (s16)(base_cw_0db << 3) - pwr_ofst_decrease;
bb_pwr_cw = FIELD_GET(GENMASK(2, 0), pwr_s10_3);
rf_pwr_cw = FIELD_GET(GENMASK(8, 3), pwr_s10_3);
rf_pwr_cw = clamp_t(s16, rf_pwr_cw, 15, 63);
pwr_cw = (rf_pwr_cw << 3) | bb_pwr_cw;
- tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3));
+ tssi_ofst_cw = (u32)((s16)tssi_16dbm_cw + (ref << 1) - (16 << 3)) -
+ pwr_ofst_decrease;
rtw89_debug(rtwdev, RTW89_DBG_TXPWR,
"[TXPWR] tssi_ofst_cw=%d rf_cw=0x%x bb_cw=0x%x\n",
tssi_ofst_cw, rf_pwr_cw, bb_pwr_cw);
@@ -1943,9 +1944,10 @@ void rtw8852c_set_txpwr_ul_tb_offset(struct rtw89_dev *rtwdev,
}
static void rtw8852c_set_txpwr_ref(struct rtw89_dev *rtwdev,
- enum rtw89_phy_idx phy_idx)
+ enum rtw89_phy_idx phy_idx, s16 pwr_ofst)
{
static const u32 addr[RF_PATH_NUM_8852C] = {0x5800, 0x7800};
+ u16 ofst_dec[RF_PATH_NUM_8852C];
const u32 mask = 0x7FFFFFF;
const u8 ofst_ofdm = 0x4;
const u8 ofst_cck = 0x8;
@@ -1959,19 +1961,20 @@ static void rtw8852c_set_txpwr_ref(struct rtw89_dev *rtwdev,
rtw89_mac_txpwr_write32_mask(rtwdev, phy_idx, R_AX_PWR_RATE_CTRL,
GENMASK(27, 10), 0x0);
- rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n");
- val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm);
+ ofst_dec[RF_PATH_A] = pwr_ofst > 0 ? 0 : abs(pwr_ofst);
+ ofst_dec[RF_PATH_B] = pwr_ofst > 0 ? pwr_ofst : 0;
- for (i = 0; i < RF_PATH_NUM_8852C; i++)
- rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val,
- phy_idx);
+ rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb ofdm txpwr ref\n");
+ for (i = 0; i < RF_PATH_NUM_8852C; i++) {
+ val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_ofdm, ofst_dec[i]);
+ rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_ofdm, mask, val, phy_idx);
+ }
rtw89_debug(rtwdev, RTW89_DBG_TXPWR, "[TXPWR] set bb cck txpwr ref\n");
- val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck);
-
- for (i = 0; i < RF_PATH_NUM_8852C; i++)
- rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val,
- phy_idx);
+ for (i = 0; i < RF_PATH_NUM_8852C; i++) {
+ val = rtw8852c_bb_cal_txpwr_ref(rtwdev, phy_idx, ref_cck, ofst_dec[i]);
+ rtw89_phy_write32_idx(rtwdev, addr[i] + ofst_cck, mask, val, phy_idx);
+ }
}
static void rtw8852c_bb_set_tx_shape_dfir(struct rtw89_dev *rtwdev,
@@ -2052,6 +2055,16 @@ static void rtw8852c_set_tx_shape(struct rtw89_dev *rtwdev,
B_P1_DAC_COMP_POST_DPD_EN);
}
+static void rtw8852c_set_txpwr_diff(struct rtw89_dev *rtwdev,
+ const struct rtw89_chan *chan,
+ enum rtw89_phy_idx phy_idx)
+{
+ s16 pwr_ofst;
+
+ pwr_ofst = rtw89_phy_ant_gain_pwr_offset(rtwdev, chan);
+ rtw8852c_set_txpwr_ref(rtwdev, phy_idx, pwr_ofst);
+}
+
static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev,
const struct rtw89_chan *chan,
enum rtw89_phy_idx phy_idx)
@@ -2061,12 +2074,13 @@ static void rtw8852c_set_txpwr(struct rtw89_dev *rtwdev,
rtw8852c_set_tx_shape(rtwdev, chan, phy_idx);
rtw89_phy_set_txpwr_limit(rtwdev, chan, phy_idx);
rtw89_phy_set_txpwr_limit_ru(rtwdev, chan, phy_idx);
+ rtw8852c_set_txpwr_diff(rtwdev, chan, phy_idx);
}
static void rtw8852c_set_txpwr_ctrl(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx)
{
- rtw8852c_set_txpwr_ref(rtwdev, phy_idx);
+ rtw8852c_set_txpwr_ref(rtwdev, phy_idx, 0);
}
static void
@@ -2793,7 +2807,10 @@ static void rtw8852c_query_ppdu(struct rtw89_dev *rtwdev,
u8 path;
u8 *rx_power = phy_ppdu->rssi;
- status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], rx_power[RF_PATH_B]));
+ if (!status->signal)
+ status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A],
+ rx_power[RF_PATH_B]));
+
for (path = 0; path < rtwdev->chip->rf_path_num; path++) {
status->chains |= BIT(path);
status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]);
@@ -2893,6 +2910,7 @@ static const struct rtw89_chip_ops rtw8852c_chip_ops = {
.ctrl_btg_bt_rx = rtw8852c_ctrl_btg_bt_rx,
.query_ppdu = rtw8852c_query_ppdu,
.convert_rpl_to_rssi = NULL,
+ .phy_rpt_to_rssi = NULL,
.ctrl_nbtg_bt_tx = rtw8852c_ctrl_nbtg_bt_tx,
.cfg_txrx_path = rtw8852c_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = rtw8852c_set_txpwr_ul_tb_offset,
@@ -2959,6 +2977,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
.dflt_parms = &rtw89_8852c_dflt_parms,
.rfe_parms_conf = NULL,
.chanctx_listener = &rtw8852c_chanctx_listener,
+ .txpwr_factor_bb = 3,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
.dig_table = NULL,
@@ -2976,6 +2995,7 @@ const struct rtw89_chip_info rtw8852c_chip_info = {
BIT(NL80211_CHAN_WIDTH_80) |
BIT(NL80211_CHAN_WIDTH_160),
.support_unii4 = true,
+ .support_ant_gain = true,
.ul_tb_waveform_ctrl = false,
.ul_tb_pwr_diff = true,
.hw_sec_hdr = true,
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
index bd17c0a1c684..b92e2ce4f4ad 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852c_rfk.c
@@ -1769,10 +1769,10 @@ u8 _rx_dck_channel_calc(struct rtw89_dev *rtwdev, const struct rtw89_chan *chan)
target_ch = chan->channel - 33;
}
} else if (chan->band_type == RTW89_BAND_6G) {
- if (chan->channel >= 1 && chan->channel <= 125)
- target_ch = chan->channel + 32;
- else
+ if (chan->channel > 125)
target_ch = chan->channel - 32;
+ else
+ target_ch = chan->channel + 32;
} else {
target_ch = chan->channel;
}
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922a.c b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
index 9a4db04a1967..f04cb3b11372 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922a.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922a.c
@@ -14,7 +14,7 @@
#include "rtw8922a_rfk.h"
#include "util.h"
-#define RTW8922A_FW_FORMAT_MAX 2
+#define RTW8922A_FW_FORMAT_MAX 3
#define RTW8922A_FW_BASENAME "rtw89/rtw8922a_fw"
#define RTW8922A_MODULE_FIRMWARE \
RTW8922A_FW_BASENAME "-" __stringify(RTW8922A_FW_FORMAT_MAX) ".bin"
@@ -2565,8 +2565,10 @@ static void rtw8922a_query_ppdu(struct rtw89_dev *rtwdev,
u8 path;
u8 *rx_power = phy_ppdu->rssi;
- status->signal =
- RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A], rx_power[RF_PATH_B]));
+ if (!status->signal)
+ status->signal = RTW89_RSSI_RAW_TO_DBM(max(rx_power[RF_PATH_A],
+ rx_power[RF_PATH_B]));
+
for (path = 0; path < rtwdev->chip->rf_path_num; path++) {
status->chains |= BIT(path);
status->chain_signal[path] = RTW89_RSSI_RAW_TO_DBM(rx_power[path]);
@@ -2607,6 +2609,16 @@ static void rtw8922a_convert_rpl_to_rssi(struct rtw89_dev *rtwdev,
phy_ppdu->rssi_avg = phy_ppdu->rpl_avg;
}
+static void rtw8922a_phy_rpt_to_rssi(struct rtw89_dev *rtwdev,
+ struct rtw89_rx_desc_info *desc_info,
+ struct ieee80211_rx_status *rx_status)
+{
+ if (desc_info->rssi <= 0x1 || (desc_info->rssi >> 2) > MAX_RSSI)
+ return;
+
+ rx_status->signal = (desc_info->rssi >> 2) - MAX_RSSI;
+}
+
static int rtw8922a_mac_enable_bb_rf(struct rtw89_dev *rtwdev)
{
rtw89_write8_set(rtwdev, R_BE_FEN_RST_ENABLE,
@@ -2665,6 +2677,7 @@ static const struct rtw89_chip_ops rtw8922a_chip_ops = {
.ctrl_btg_bt_rx = rtw8922a_ctrl_btg_bt_rx,
.query_ppdu = rtw8922a_query_ppdu,
.convert_rpl_to_rssi = rtw8922a_convert_rpl_to_rssi,
+ .phy_rpt_to_rssi = rtw8922a_phy_rpt_to_rssi,
.ctrl_nbtg_bt_tx = rtw8922a_ctrl_nbtg_bt_tx,
.cfg_txrx_path = rtw8922a_bb_cfg_txrx_path,
.set_txpwr_ul_tb_offset = NULL,
@@ -2729,6 +2742,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
.nctl_post_table = NULL,
.dflt_parms = NULL, /* load parm from fw */
.rfe_parms_conf = NULL, /* load parm from fw */
+ .txpwr_factor_bb = 3,
.txpwr_factor_rf = 2,
.txpwr_factor_mac = 1,
.dig_table = NULL,
@@ -2746,6 +2760,7 @@ const struct rtw89_chip_info rtw8922a_chip_info = {
BIT(NL80211_CHAN_WIDTH_80) |
BIT(NL80211_CHAN_WIDTH_160),
.support_unii4 = true,
+ .support_ant_gain = false,
.ul_tb_waveform_ctrl = false,
.ul_tb_pwr_diff = false,
.hw_sec_hdr = true,
diff --git a/drivers/net/wireless/realtek/rtw89/sar.c b/drivers/net/wireless/realtek/rtw89/sar.c
index bcc287771b2a..871f45a6508c 100644
--- a/drivers/net/wireless/realtek/rtw89/sar.c
+++ b/drivers/net/wireless/realtek/rtw89/sar.c
@@ -42,7 +42,7 @@ static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev,
/* freq 6875 (ch 185, 20MHz) spans RTW89_SAR_6GHZ_SUBBAND_7_H
* and RTW89_SAR_6GHZ_SUBBAND_8, so directly describe it with
- * struct rtw89_sar_span in the following.
+ * struct rtw89_6ghz_span.
*/
case 6895 ... 7115:
@@ -50,63 +50,18 @@ static enum rtw89_sar_subband rtw89_sar_get_subband(struct rtw89_dev *rtwdev,
}
}
-struct rtw89_sar_span {
- enum rtw89_sar_subband subband_low;
- enum rtw89_sar_subband subband_high;
-};
-
-#define RTW89_SAR_SPAN_VALID(span) ((span)->subband_high)
-
-#define RTW89_SAR_6GHZ_SPAN_HEAD 6145
-#define RTW89_SAR_6GHZ_SPAN_IDX(center_freq) \
- ((((int)(center_freq) - RTW89_SAR_6GHZ_SPAN_HEAD) / 5) / 2)
-
-#define RTW89_DECL_SAR_6GHZ_SPAN(center_freq, subband_l, subband_h) \
- [RTW89_SAR_6GHZ_SPAN_IDX(center_freq)] = { \
- .subband_low = RTW89_SAR_6GHZ_ ## subband_l, \
- .subband_high = RTW89_SAR_6GHZ_ ## subband_h, \
- }
-
-/* Since 6GHz SAR subbands are not edge aligned, some cases span two SAR
- * subbands. In the following, we describe each of them with rtw89_sar_span.
- */
-static const struct rtw89_sar_span rtw89_sar_overlapping_6ghz[] = {
- RTW89_DECL_SAR_6GHZ_SPAN(6145, SUBBAND_5_L, SUBBAND_5_H),
- RTW89_DECL_SAR_6GHZ_SPAN(6165, SUBBAND_5_L, SUBBAND_5_H),
- RTW89_DECL_SAR_6GHZ_SPAN(6185, SUBBAND_5_L, SUBBAND_5_H),
- RTW89_DECL_SAR_6GHZ_SPAN(6505, SUBBAND_6, SUBBAND_7_L),
- RTW89_DECL_SAR_6GHZ_SPAN(6525, SUBBAND_6, SUBBAND_7_L),
- RTW89_DECL_SAR_6GHZ_SPAN(6545, SUBBAND_6, SUBBAND_7_L),
- RTW89_DECL_SAR_6GHZ_SPAN(6665, SUBBAND_7_L, SUBBAND_7_H),
- RTW89_DECL_SAR_6GHZ_SPAN(6705, SUBBAND_7_L, SUBBAND_7_H),
- RTW89_DECL_SAR_6GHZ_SPAN(6825, SUBBAND_7_H, SUBBAND_8),
- RTW89_DECL_SAR_6GHZ_SPAN(6865, SUBBAND_7_H, SUBBAND_8),
- RTW89_DECL_SAR_6GHZ_SPAN(6875, SUBBAND_7_H, SUBBAND_8),
- RTW89_DECL_SAR_6GHZ_SPAN(6885, SUBBAND_7_H, SUBBAND_8),
-};
-
static int rtw89_query_sar_config_common(struct rtw89_dev *rtwdev,
u32 center_freq, s32 *cfg)
{
struct rtw89_sar_cfg_common *rtwsar = &rtwdev->sar.cfg_common;
- const struct rtw89_sar_span *span = NULL;
enum rtw89_sar_subband subband_l, subband_h;
- int idx;
-
- if (center_freq >= RTW89_SAR_6GHZ_SPAN_HEAD) {
- idx = RTW89_SAR_6GHZ_SPAN_IDX(center_freq);
- /* To decrease size of rtw89_sar_overlapping_6ghz[],
- * RTW89_SAR_6GHZ_SPAN_IDX() truncates the leading NULLs
- * to make first span as index 0 of the table. So, if center
- * frequency is less than the first one, it will get netative.
- */
- if (idx >= 0 && idx < ARRAY_SIZE(rtw89_sar_overlapping_6ghz))
- span = &rtw89_sar_overlapping_6ghz[idx];
- }
+ const struct rtw89_6ghz_span *span;
+
+ span = rtw89_get_6ghz_span(rtwdev, center_freq);
if (span && RTW89_SAR_SPAN_VALID(span)) {
- subband_l = span->subband_low;
- subband_h = span->subband_high;
+ subband_l = span->sar_subband_low;
+ subband_h = span->sar_subband_high;
} else {
subband_l = rtw89_sar_get_subband(rtwdev, center_freq);
subband_h = subband_l;
diff --git a/drivers/net/wireless/realtek/rtw89/ser.c b/drivers/net/wireless/realtek/rtw89/ser.c
index 7b203bb7f151..26a944d3b672 100644
--- a/drivers/net/wireless/realtek/rtw89/ser.c
+++ b/drivers/net/wireless/realtek/rtw89/ser.c
@@ -365,6 +365,7 @@ static void ser_reset_mac_binding(struct rtw89_dev *rtwdev)
ser_reset_vif(rtwdev, rtwvif);
rtwdev->total_sta_assoc = 0;
+ refcount_set(&rtwdev->refcount_ap_info, 0);
}
/* hal function */
diff --git a/drivers/net/wireless/realtek/rtw89/txrx.h b/drivers/net/wireless/realtek/rtw89/txrx.h
index b2e47829983f..70fe7cebc9d5 100644
--- a/drivers/net/wireless/realtek/rtw89/txrx.h
+++ b/drivers/net/wireless/realtek/rtw89/txrx.h
@@ -560,6 +560,9 @@ struct rtw89_phy_sts_iehdr {
#define BE_RXD_HDR_OFFSET_MASK GENMASK(20, 16)
#define BE_RXD_WL_HD_IV_LEN_MASK GENMASK(26, 21)
+/* BE RXD - PHY RPT dword0 */
+#define BE_RXD_PHY_RSSI GENMASK(11, 0)
+
struct rtw89_phy_sts_ie00 {
__le32 w0;
__le32 w1;
diff --git a/drivers/net/wireless/realtek/rtw89/wow.c b/drivers/net/wireless/realtek/rtw89/wow.c
index 3e81fd974ec1..01754d031bb4 100644
--- a/drivers/net/wireless/realtek/rtw89/wow.c
+++ b/drivers/net/wireless/realtek/rtw89/wow.c
@@ -620,7 +620,10 @@ static struct ieee80211_key_conf *rtw89_wow_gtk_rekey(struct rtw89_dev *rtwdev,
* need to unlock mutex
*/
mutex_unlock(&rtwdev->mutex);
- key = ieee80211_gtk_rekey_add(wow_vif, rekey_conf, -1);
+ if (ieee80211_vif_is_mld(wow_vif))
+ key = ieee80211_gtk_rekey_add(wow_vif, rekey_conf, rtwvif_link->link_id);
+ else
+ key = ieee80211_gtk_rekey_add(wow_vif, rekey_conf, -1);
mutex_lock(&rtwdev->mutex);
kfree(rekey_conf);
@@ -691,9 +694,7 @@ static void rtw89_wow_leave_deep_ps(struct rtw89_dev *rtwdev)
static void rtw89_wow_enter_deep_ps(struct rtw89_dev *rtwdev)
{
- struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
-
- __rtw89_enter_ps_mode(rtwdev, rtwvif_link);
+ __rtw89_enter_ps_mode(rtwdev);
}
static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev)
@@ -701,7 +702,7 @@ static void rtw89_wow_enter_ps(struct rtw89_dev *rtwdev)
struct rtw89_vif_link *rtwvif_link = rtwdev->wow.rtwvif_link;
if (rtw89_wow_mgd_linked(rtwdev))
- rtw89_enter_lps(rtwdev, rtwvif_link, false);
+ rtw89_enter_lps(rtwdev, rtwvif_link->rtwvif, false);
else if (rtw89_wow_no_link(rtwdev))
rtw89_fw_h2c_fwips(rtwdev, rtwvif_link, true);
}
diff --git a/drivers/net/wireless/st/cw1200/cw1200_spi.c b/drivers/net/wireless/st/cw1200/cw1200_spi.c
index 862964a8cc87..52386dfb5f4a 100644
--- a/drivers/net/wireless/st/cw1200/cw1200_spi.c
+++ b/drivers/net/wireless/st/cw1200/cw1200_spi.c
@@ -442,8 +442,8 @@ static void cw1200_spi_disconnect(struct spi_device *func)
cw1200_core_release(self->core);
self->core = NULL;
}
+ cw1200_spi_off(self, dev_get_platdata(&func->dev));
}
- cw1200_spi_off(self, dev_get_platdata(&func->dev));
}
static int __maybe_unused cw1200_spi_suspend(struct device *dev)
diff --git a/drivers/net/wireless/ti/wlcore/sysfs.c b/drivers/net/wireless/ti/wlcore/sysfs.c
index c07acfcbbd9c..7c57d4c8744a 100644
--- a/drivers/net/wireless/ti/wlcore/sysfs.c
+++ b/drivers/net/wireless/ti/wlcore/sysfs.c
@@ -88,7 +88,7 @@ static ssize_t hw_pg_ver_show(struct device *dev,
static DEVICE_ATTR_RO(hw_pg_ver);
static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
char *buffer, loff_t pos, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -121,7 +121,7 @@ static ssize_t wl1271_sysfs_read_fwlog(struct file *filp, struct kobject *kobj,
static const struct bin_attribute fwlog_attr = {
.attr = { .name = "fwlog", .mode = 0400 },
- .read = wl1271_sysfs_read_fwlog,
+ .read_new = wl1271_sysfs_read_fwlog,
};
int wlcore_sysfs_init(struct wl1271 *wl)
diff --git a/drivers/net/wireless/ti/wlcore/testmode.c b/drivers/net/wireless/ti/wlcore/testmode.c
index 3f338b8096c7..fc8ea58bc165 100644
--- a/drivers/net/wireless/ti/wlcore/testmode.c
+++ b/drivers/net/wireless/ti/wlcore/testmode.c
@@ -45,7 +45,7 @@ enum wl1271_tm_attrs {
};
#define WL1271_TM_ATTR_MAX (__WL1271_TM_ATTR_AFTER_LAST - 1)
-static struct nla_policy wl1271_tm_policy[WL1271_TM_ATTR_MAX + 1] = {
+static const struct nla_policy wl1271_tm_policy[WL1271_TM_ATTR_MAX + 1] = {
[WL1271_TM_ATTR_CMD_ID] = { .type = NLA_U32 },
[WL1271_TM_ATTR_ANSWER] = { .type = NLA_U8 },
[WL1271_TM_ATTR_DATA] = { .type = NLA_BINARY,
diff --git a/drivers/net/wireless/virtual/mac80211_hwsim.c b/drivers/net/wireless/virtual/mac80211_hwsim.c
index 347a15544afe..cf6a331d4042 100644
--- a/drivers/net/wireless/virtual/mac80211_hwsim.c
+++ b/drivers/net/wireless/virtual/mac80211_hwsim.c
@@ -5048,6 +5048,45 @@ static const struct ieee80211_sband_iftype_data sband_capa_6ghz[] = {
.tx_mcs_80p80 = cpu_to_le16(0xfffa),
},
},
+ .eht_cap = {
+ .has_eht = true,
+ .eht_cap_elem = {
+ .mac_cap_info[0] = IEEE80211_EHT_MAC_CAP0_OM_CONTROL |
+ IEEE80211_EHT_MAC_CAP0_TRIG_TXOP_SHARING_MODE1,
+ .phy_cap_info[0] = IEEE80211_EHT_PHY_CAP0_320MHZ_IN_6GHZ,
+ /* Leave all the other PHY capability bytes
+ * unset, as DCM, beam forming, RU and PPE
+ * threshold information are not supported
+ */
+ },
+ /* For all MCS and bandwidth, set 8 NSS for both Tx and
+ * Rx
+ */
+ .eht_mcs_nss_supp = {
+ /* As B1 and B2 are set in the supported
+ * channel width set field in the HE PHY
+ * capabilities information field and 320MHz in
+ * 6GHz is supported include all the following
+ * MCS/NSS.
+ */
+ .bw._80 = {
+ .rx_tx_mcs9_max_nss = 0x88,
+ .rx_tx_mcs11_max_nss = 0x88,
+ .rx_tx_mcs13_max_nss = 0x88,
+ },
+ .bw._160 = {
+ .rx_tx_mcs9_max_nss = 0x88,
+ .rx_tx_mcs11_max_nss = 0x88,
+ .rx_tx_mcs13_max_nss = 0x88,
+ },
+ .bw._320 = {
+ .rx_tx_mcs9_max_nss = 0x88,
+ .rx_tx_mcs11_max_nss = 0x88,
+ .rx_tx_mcs13_max_nss = 0x88,
+ },
+ },
+ /* PPE threshold information is not supported */
+ },
},
#endif
};
diff --git a/drivers/net/wwan/iosm/iosm_ipc_mmio.c b/drivers/net/wwan/iosm/iosm_ipc_mmio.c
index 63eb08c43c05..6764c13530b9 100644
--- a/drivers/net/wwan/iosm/iosm_ipc_mmio.c
+++ b/drivers/net/wwan/iosm/iosm_ipc_mmio.c
@@ -104,7 +104,7 @@ struct iosm_mmio *ipc_mmio_init(void __iomem *mmio, struct device *dev)
break;
msleep(20);
- } while (retries-- > 0);
+ } while (--retries > 0);
if (!retries) {
dev_err(ipc_mmio->dev, "invalid exec stage %X", stage);
diff --git a/drivers/net/wwan/t7xx/t7xx_pci.c b/drivers/net/wwan/t7xx/t7xx_pci.c
index 8381b0dc7acb..02f2ec7cf4ce 100644
--- a/drivers/net/wwan/t7xx/t7xx_pci.c
+++ b/drivers/net/wwan/t7xx/t7xx_pci.c
@@ -43,6 +43,8 @@
#include "t7xx_state_monitor.h"
#include "t7xx_port_proxy.h"
+#define DRIVER_NAME "mtk_t7xx"
+
#define T7XX_PCI_IREG_BASE 0
#define T7XX_PCI_EREG_BASE 2
@@ -833,6 +835,7 @@ static void t7xx_pci_infracfg_ao_calc(struct t7xx_pci_dev *t7xx_dev)
static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct t7xx_pci_dev *t7xx_dev;
+ void __iomem *iomem;
int ret;
t7xx_dev = devm_kzalloc(&pdev->dev, sizeof(*t7xx_dev), GFP_KERNEL);
@@ -848,12 +851,21 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
pci_set_master(pdev);
- ret = pcim_iomap_regions(pdev, BIT(T7XX_PCI_IREG_BASE) | BIT(T7XX_PCI_EREG_BASE),
- pci_name(pdev));
+ iomem = pcim_iomap_region(pdev, T7XX_PCI_IREG_BASE, DRIVER_NAME);
+ ret = PTR_ERR_OR_ZERO(iomem);
+ if (ret) {
+ dev_err(&pdev->dev, "Could not request IREG BAR: %d\n", ret);
+ return -ENOMEM;
+ }
+ IREG_BASE(t7xx_dev) = iomem;
+
+ iomem = pcim_iomap_region(pdev, T7XX_PCI_EREG_BASE, DRIVER_NAME);
+ ret = PTR_ERR_OR_ZERO(iomem);
if (ret) {
- dev_err(&pdev->dev, "Could not request BARs: %d\n", ret);
+ dev_err(&pdev->dev, "Could not request EREG BAR: %d\n", ret);
return -ENOMEM;
}
+ t7xx_dev->base_addr.pcie_ext_reg_base = iomem;
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
if (ret) {
@@ -867,9 +879,6 @@ static int t7xx_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return ret;
}
- IREG_BASE(t7xx_dev) = pcim_iomap_table(pdev)[T7XX_PCI_IREG_BASE];
- t7xx_dev->base_addr.pcie_ext_reg_base = pcim_iomap_table(pdev)[T7XX_PCI_EREG_BASE];
-
ret = t7xx_pci_pm_init(t7xx_dev);
if (ret)
return ret;
@@ -937,7 +946,7 @@ static const struct pci_device_id t7xx_pci_table[] = {
MODULE_DEVICE_TABLE(pci, t7xx_pci_table);
static struct pci_driver t7xx_pci_driver = {
- .name = "mtk_t7xx",
+ .name = DRIVER_NAME,
.id_table = t7xx_pci_table,
.probe = t7xx_pci_probe,
.remove = t7xx_pci_remove,
diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.c b/drivers/net/wwan/t7xx/t7xx_state_monitor.c
index 3931c7a13f5a..cbdbb91e8381 100644
--- a/drivers/net/wwan/t7xx/t7xx_state_monitor.c
+++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.c
@@ -104,14 +104,21 @@ void t7xx_fsm_broadcast_state(struct t7xx_fsm_ctl *ctl, enum md_state state)
fsm_state_notify(ctl->md, state);
}
+static void fsm_release_command(struct kref *ref)
+{
+ struct t7xx_fsm_command *cmd = container_of(ref, typeof(*cmd), refcnt);
+
+ kfree(cmd);
+}
+
static void fsm_finish_command(struct t7xx_fsm_ctl *ctl, struct t7xx_fsm_command *cmd, int result)
{
if (cmd->flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
- *cmd->ret = result;
- complete_all(cmd->done);
+ cmd->result = result;
+ complete_all(&cmd->done);
}
- kfree(cmd);
+ kref_put(&cmd->refcnt, fsm_release_command);
}
static void fsm_del_kf_event(struct t7xx_fsm_event *event)
@@ -475,7 +482,6 @@ static int fsm_main_thread(void *data)
int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id, unsigned int flag)
{
- DECLARE_COMPLETION_ONSTACK(done);
struct t7xx_fsm_command *cmd;
unsigned long flags;
int ret;
@@ -487,11 +493,13 @@ int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id
INIT_LIST_HEAD(&cmd->entry);
cmd->cmd_id = cmd_id;
cmd->flag = flag;
+ kref_init(&cmd->refcnt);
if (flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
- cmd->done = &done;
- cmd->ret = &ret;
+ init_completion(&cmd->done);
+ kref_get(&cmd->refcnt);
}
+ kref_get(&cmd->refcnt);
spin_lock_irqsave(&ctl->command_lock, flags);
list_add_tail(&cmd->entry, &ctl->command_queue);
spin_unlock_irqrestore(&ctl->command_lock, flags);
@@ -501,11 +509,11 @@ int t7xx_fsm_append_cmd(struct t7xx_fsm_ctl *ctl, enum t7xx_fsm_cmd_state cmd_id
if (flag & FSM_CMD_FLAG_WAIT_FOR_COMPLETION) {
unsigned long wait_ret;
- wait_ret = wait_for_completion_timeout(&done,
+ wait_ret = wait_for_completion_timeout(&cmd->done,
msecs_to_jiffies(FSM_CMD_TIMEOUT_MS));
- if (!wait_ret)
- return -ETIMEDOUT;
+ ret = wait_ret ? cmd->result : -ETIMEDOUT;
+ kref_put(&cmd->refcnt, fsm_release_command);
return ret;
}
diff --git a/drivers/net/wwan/t7xx/t7xx_state_monitor.h b/drivers/net/wwan/t7xx/t7xx_state_monitor.h
index 7b0a9baf488c..6e0601bb752e 100644
--- a/drivers/net/wwan/t7xx/t7xx_state_monitor.h
+++ b/drivers/net/wwan/t7xx/t7xx_state_monitor.h
@@ -110,8 +110,9 @@ struct t7xx_fsm_command {
struct list_head entry;
enum t7xx_fsm_cmd_state cmd_id;
unsigned int flag;
- struct completion *done;
- int *ret;
+ struct completion done;
+ int result;
+ struct kref refcnt;
};
struct t7xx_fsm_notifier {
diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c
index 4265c1cd0ff7..63fe51d0e64d 100644
--- a/drivers/net/xen-netfront.c
+++ b/drivers/net/xen-netfront.c
@@ -867,7 +867,7 @@ static netdev_tx_t xennet_start_xmit(struct sk_buff *skb, struct net_device *dev
static int xennet_close(struct net_device *dev)
{
struct netfront_info *np = netdev_priv(dev);
- unsigned int num_queues = dev->real_num_tx_queues;
+ unsigned int num_queues = np->queues ? dev->real_num_tx_queues : 0;
unsigned int i;
struct netfront_queue *queue;
netif_tx_stop_all_queues(np->netdev);
@@ -882,6 +882,9 @@ static void xennet_destroy_queues(struct netfront_info *info)
{
unsigned int i;
+ if (!info->queues)
+ return;
+
for (i = 0; i < info->netdev->real_num_tx_queues; i++) {
struct netfront_queue *queue = &info->queues[i];
diff --git a/drivers/nfc/st21nfca/dep.c b/drivers/nfc/st21nfca/dep.c
index 1ec651e31064..3425b68f0ddc 100644
--- a/drivers/nfc/st21nfca/dep.c
+++ b/drivers/nfc/st21nfca/dep.c
@@ -116,18 +116,16 @@ static void st21nfca_tx_work(struct work_struct *work)
struct nfc_dev *dev;
struct sk_buff *skb;
- if (info) {
- dev = info->hdev->ndev;
- skb = info->dep_info.tx_pending;
+ dev = info->hdev->ndev;
+ skb = info->dep_info.tx_pending;
- device_lock(&dev->dev);
+ device_lock(&dev->dev);
- nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE,
- ST21NFCA_WR_XCHG_DATA, skb->data, skb->len,
- info->async_cb, info);
- device_unlock(&dev->dev);
- kfree_skb(skb);
- }
+ nfc_hci_send_cmd_async(info->hdev, ST21NFCA_RF_READER_F_GATE,
+ ST21NFCA_WR_XCHG_DATA, skb->data, skb->len,
+ info->async_cb, info);
+ device_unlock(&dev->dev);
+ kfree_skb(skb);
}
static void st21nfca_im_send_pdu(struct st21nfca_hci_info *info,
diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
index 0982215371ba..41c67dfa8015 100644
--- a/drivers/nvdimm/e820.c
+++ b/drivers/nvdimm/e820.c
@@ -59,7 +59,7 @@ err:
static struct platform_driver e820_pmem_driver = {
.probe = e820_pmem_probe,
- .remove_new = e820_pmem_remove,
+ .remove = e820_pmem_remove,
.driver = {
.name = "e820_pmem",
},
diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
index b4a1cf70e8b7..68bddab3fb46 100644
--- a/drivers/nvdimm/of_pmem.c
+++ b/drivers/nvdimm/of_pmem.c
@@ -100,7 +100,7 @@ static const struct of_device_id of_pmem_region_match[] = {
static struct platform_driver of_pmem_region_driver = {
.probe = of_pmem_region_probe,
- .remove_new = of_pmem_region_remove,
+ .remove = of_pmem_region_remove,
.driver = {
.name = "of_pmem",
.of_match_table = of_pmem_region_match,
diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
index 9e4f7ff024a0..37417ce5ec7b 100644
--- a/drivers/nvdimm/region_devs.c
+++ b/drivers/nvdimm/region_devs.c
@@ -1270,4 +1270,4 @@ int nd_region_conflict(struct nd_region *nd_region, resource_size_t start,
return device_for_each_child(&nvdimm_bus->dev, &ctx, region_conflict);
}
-MODULE_IMPORT_NS(DEVMEM);
+MODULE_IMPORT_NS("DEVMEM");
diff --git a/drivers/nvme/host/apple.c b/drivers/nvme/host/apple.c
index 7cd1102a8d2c..4319ab50c10d 100644
--- a/drivers/nvme/host/apple.c
+++ b/drivers/nvme/host/apple.c
@@ -1618,7 +1618,7 @@ static struct platform_driver apple_nvme_driver = {
.pm = pm_sleep_ptr(&apple_nvme_pm_ops),
},
.probe = apple_nvme_probe,
- .remove_new = apple_nvme_remove,
+ .remove = apple_nvme_remove,
.shutdown = apple_nvme_shutdown,
};
module_platform_driver(apple_nvme_driver);
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
index 1a8d32a4a5c3..a970168a3014 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -702,7 +702,7 @@ void nvme_put_ns(struct nvme_ns *ns)
{
kref_put(&ns->kref, nvme_free_ns);
}
-EXPORT_SYMBOL_NS_GPL(nvme_put_ns, NVME_TARGET_PASSTHRU);
+EXPORT_SYMBOL_NS_GPL(nvme_put_ns, "NVME_TARGET_PASSTHRU");
static inline void nvme_clear_nvme_request(struct request *req)
{
@@ -1123,7 +1123,7 @@ int nvme_execute_rq(struct request *rq, bool at_head)
return nvme_req(rq)->status;
return blk_status_to_errno(status);
}
-EXPORT_SYMBOL_NS_GPL(nvme_execute_rq, NVME_TARGET_PASSTHRU);
+EXPORT_SYMBOL_NS_GPL(nvme_execute_rq, "NVME_TARGET_PASSTHRU");
/*
* Returns 0 on success. If the result is negative, it's a Linux error code;
@@ -1203,7 +1203,7 @@ u32 nvme_command_effects(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode)
return effects;
}
-EXPORT_SYMBOL_NS_GPL(nvme_command_effects, NVME_TARGET_PASSTHRU);
+EXPORT_SYMBOL_NS_GPL(nvme_command_effects, "NVME_TARGET_PASSTHRU");
u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode)
{
@@ -1223,7 +1223,7 @@ u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u8 opcode)
}
return effects;
}
-EXPORT_SYMBOL_NS_GPL(nvme_passthru_start, NVME_TARGET_PASSTHRU);
+EXPORT_SYMBOL_NS_GPL(nvme_passthru_start, "NVME_TARGET_PASSTHRU");
void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects,
struct nvme_command *cmd, int status)
@@ -1268,7 +1268,7 @@ void nvme_passthru_end(struct nvme_ctrl *ctrl, struct nvme_ns *ns, u32 effects,
break;
}
}
-EXPORT_SYMBOL_NS_GPL(nvme_passthru_end, NVME_TARGET_PASSTHRU);
+EXPORT_SYMBOL_NS_GPL(nvme_passthru_end, "NVME_TARGET_PASSTHRU");
/*
* Recommended frequency for KATO commands per NVMe 1.4 section 7.12.1:
@@ -1305,9 +1305,10 @@ static void nvme_queue_keep_alive_work(struct nvme_ctrl *ctrl)
queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
}
-static void nvme_keep_alive_finish(struct request *rq,
- blk_status_t status, struct nvme_ctrl *ctrl)
+static enum rq_end_io_ret nvme_keep_alive_end_io(struct request *rq,
+ blk_status_t status)
{
+ struct nvme_ctrl *ctrl = rq->end_io_data;
unsigned long rtt = jiffies - (rq->deadline - rq->timeout);
unsigned long delay = nvme_keep_alive_work_period(ctrl);
enum nvme_ctrl_state state = nvme_ctrl_state(ctrl);
@@ -1324,17 +1325,20 @@ static void nvme_keep_alive_finish(struct request *rq,
delay = 0;
}
+ blk_mq_free_request(rq);
+
if (status) {
dev_err(ctrl->device,
"failed nvme_keep_alive_end_io error=%d\n",
status);
- return;
+ return RQ_END_IO_NONE;
}
ctrl->ka_last_check_time = jiffies;
ctrl->comp_seen = false;
if (state == NVME_CTRL_LIVE || state == NVME_CTRL_CONNECTING)
queue_delayed_work(nvme_wq, &ctrl->ka_work, delay);
+ return RQ_END_IO_NONE;
}
static void nvme_keep_alive_work(struct work_struct *work)
@@ -1343,7 +1347,6 @@ static void nvme_keep_alive_work(struct work_struct *work)
struct nvme_ctrl, ka_work);
bool comp_seen = ctrl->comp_seen;
struct request *rq;
- blk_status_t status;
ctrl->ka_last_check_time = jiffies;
@@ -1366,9 +1369,9 @@ static void nvme_keep_alive_work(struct work_struct *work)
nvme_init_request(rq, &ctrl->ka_cmd);
rq->timeout = ctrl->kato * HZ;
- status = blk_execute_rq(rq, false);
- nvme_keep_alive_finish(rq, status, ctrl);
- blk_mq_free_request(rq);
+ rq->end_io = nvme_keep_alive_end_io;
+ rq->end_io_data = ctrl;
+ blk_execute_rq_nowait(rq, false);
}
static void nvme_start_keep_alive(struct nvme_ctrl *ctrl)
@@ -2031,7 +2034,7 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id,
* or smaller than a sector size yet, so catch this early and don't
* allow block I/O.
*/
- if (head->lba_shift > PAGE_SHIFT || head->lba_shift < SECTOR_SHIFT) {
+ if (blk_validate_block_size(bs)) {
bs = (1 << 9);
valid = false;
}
@@ -2068,7 +2071,8 @@ static bool nvme_update_disk_info(struct nvme_ns *ns, struct nvme_id_ns *id,
lim->physical_block_size = min(phys_bs, atomic_bs);
lim->io_min = phys_bs;
lim->io_opt = io_opt;
- if (ns->ctrl->quirks & NVME_QUIRK_DEALLOCATE_ZEROES)
+ if ((ns->ctrl->quirks & NVME_QUIRK_DEALLOCATE_ZEROES) &&
+ (ns->ctrl->oncs & NVME_CTRL_ONCS_DSM))
lim->max_write_zeroes_sectors = UINT_MAX;
else
lim->max_write_zeroes_sectors = ns->ctrl->max_zeroes_sectors;
@@ -3257,8 +3261,9 @@ static int nvme_check_ctrl_fabric_info(struct nvme_ctrl *ctrl, struct nvme_id_ct
}
if (!ctrl->maxcmd) {
- dev_err(ctrl->device, "Maximum outstanding commands is 0\n");
- return -EINVAL;
+ dev_warn(ctrl->device,
+ "Firmware bug: maximum outstanding commands is 0\n");
+ ctrl->maxcmd = ctrl->sqsize + 1;
}
return 0;
@@ -3817,7 +3822,7 @@ struct nvme_ns *nvme_find_get_ns(struct nvme_ctrl *ctrl, unsigned nsid)
srcu_read_unlock(&ctrl->srcu, srcu_idx);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(nvme_find_get_ns, NVME_TARGET_PASSTHRU);
+EXPORT_SYMBOL_NS_GPL(nvme_find_get_ns, "NVME_TARGET_PASSTHRU");
/*
* Add the namespace to the controller list while keeping the list ordered.
@@ -4600,6 +4605,11 @@ EXPORT_SYMBOL_GPL(nvme_alloc_admin_tag_set);
void nvme_remove_admin_tag_set(struct nvme_ctrl *ctrl)
{
+ /*
+ * As we're about to destroy the queue and free tagset
+ * we can not have keep-alive work running.
+ */
+ nvme_stop_keep_alive(ctrl);
blk_mq_destroy_queue(ctrl->admin_q);
blk_put_queue(ctrl->admin_q);
if (ctrl->ops->flags & NVME_F_FABRICS) {
@@ -5022,7 +5032,7 @@ struct nvme_ctrl *nvme_ctrl_from_file(struct file *file)
return NULL;
return file->private_data;
}
-EXPORT_SYMBOL_NS_GPL(nvme_ctrl_from_file, NVME_TARGET_PASSTHRU);
+EXPORT_SYMBOL_NS_GPL(nvme_ctrl_from_file, "NVME_TARGET_PASSTHRU");
/*
* Check we didn't inadvertently grow the command structure sizes:
diff --git a/drivers/nvme/host/ioctl.c b/drivers/nvme/host/ioctl.c
index 6522ae16531c..e8930146847a 100644
--- a/drivers/nvme/host/ioctl.c
+++ b/drivers/nvme/host/ioctl.c
@@ -120,12 +120,20 @@ static int nvme_map_user_request(struct request *req, u64 ubuffer,
struct nvme_ns *ns = q->queuedata;
struct block_device *bdev = ns ? ns->disk->part0 : NULL;
bool supports_metadata = bdev && blk_get_integrity(bdev->bd_disk);
+ struct nvme_ctrl *ctrl = nvme_req(req)->ctrl;
bool has_metadata = meta_buffer && meta_len;
struct bio *bio = NULL;
int ret;
- if (has_metadata && !supports_metadata)
- return -EINVAL;
+ if (!nvme_ctrl_sgl_supported(ctrl))
+ dev_warn_once(ctrl->device, "using unchecked data buffer\n");
+ if (has_metadata) {
+ if (!supports_metadata)
+ return -EINVAL;
+ if (!nvme_ctrl_meta_sgl_supported(ctrl))
+ dev_warn_once(ctrl->device,
+ "using unchecked metadata buffer\n");
+ }
if (ioucmd && (ioucmd->flags & IORING_URING_CMD_FIXED)) {
struct iov_iter iter;
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
index f04cfe3fb936..a85d190942bd 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -165,7 +165,8 @@ void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
if (!ns->head->disk)
continue;
kblockd_schedule_work(&ns->head->requeue_work);
@@ -209,7 +210,8 @@ void nvme_mpath_clear_ctrl_paths(struct nvme_ctrl *ctrl)
int srcu_idx;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
nvme_mpath_clear_current_path(ns);
kblockd_schedule_work(&ns->head->requeue_work);
}
@@ -224,7 +226,8 @@ void nvme_mpath_revalidate_paths(struct nvme_ns *ns)
int srcu_idx;
srcu_idx = srcu_read_lock(&head->srcu);
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (capacity != get_capacity(ns->disk))
clear_bit(NVME_NS_READY, &ns->flags);
}
@@ -257,7 +260,8 @@ static struct nvme_ns *__nvme_find_path(struct nvme_ns_head *head, int node)
int found_distance = INT_MAX, fallback_distance = INT_MAX, distance;
struct nvme_ns *found = NULL, *fallback = NULL, *ns;
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (nvme_path_is_disabled(ns))
continue;
@@ -356,7 +360,8 @@ static struct nvme_ns *nvme_queue_depth_path(struct nvme_ns_head *head)
unsigned int min_depth_opt = UINT_MAX, min_depth_nonopt = UINT_MAX;
unsigned int depth;
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (nvme_path_is_disabled(ns))
continue;
@@ -424,7 +429,8 @@ static bool nvme_available_path(struct nvme_ns_head *head)
if (!test_bit(NVME_NSHEAD_DISK_LIVE, &head->flags))
return NULL;
- list_for_each_entry_rcu(ns, &head->list, siblings) {
+ list_for_each_entry_srcu(ns, &head->list, siblings,
+ srcu_read_lock_held(&head->srcu)) {
if (test_bit(NVME_CTRL_FAILFAST_EXPIRED, &ns->ctrl->flags))
continue;
switch (nvme_ctrl_state(ns->ctrl)) {
@@ -783,7 +789,8 @@ static int nvme_update_ana_state(struct nvme_ctrl *ctrl,
return 0;
srcu_idx = srcu_read_lock(&ctrl->srcu);
- list_for_each_entry_rcu(ns, &ctrl->namespaces, list) {
+ list_for_each_entry_srcu(ns, &ctrl->namespaces, list,
+ srcu_read_lock_held(&ctrl->srcu)) {
unsigned nsid;
again:
nsid = le32_to_cpu(desc->nsids[n]);
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
index 900719c4c70c..c4bb8dfe1a45 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -173,6 +173,11 @@ enum nvme_quirks {
* MSI (but not MSI-X) interrupts are broken and never fire.
*/
NVME_QUIRK_BROKEN_MSI = (1 << 21),
+
+ /*
+ * Align dma pool segment size to 512 bytes
+ */
+ NVME_QUIRK_DMAPOOL_ALIGN_512 = (1 << 22),
};
/*
@@ -1123,7 +1128,15 @@ static inline void nvme_start_request(struct request *rq)
static inline bool nvme_ctrl_sgl_supported(struct nvme_ctrl *ctrl)
{
- return ctrl->sgls & ((1 << 0) | (1 << 1));
+ return ctrl->sgls & (NVME_CTRL_SGLS_BYTE_ALIGNED |
+ NVME_CTRL_SGLS_DWORD_ALIGNED);
+}
+
+static inline bool nvme_ctrl_meta_sgl_supported(struct nvme_ctrl *ctrl)
+{
+ if (ctrl->ops->flags & NVME_F_FABRICS)
+ return true;
+ return ctrl->sgls & NVME_CTRL_SGLS_MSDS;
}
#ifdef CONFIG_NVME_HOST_AUTH
diff --git a/drivers/nvme/host/pci.c b/drivers/nvme/host/pci.c
index 5f2e3ad2cc52..e2634f437f33 100644
--- a/drivers/nvme/host/pci.c
+++ b/drivers/nvme/host/pci.c
@@ -43,6 +43,7 @@
*/
#define NVME_MAX_KB_SZ 8192
#define NVME_MAX_SEGS 128
+#define NVME_MAX_META_SEGS 15
#define NVME_MAX_NR_ALLOCATIONS 5
static int use_threaded_interrupts;
@@ -144,6 +145,7 @@ struct nvme_dev {
struct sg_table *hmb_sgt;
mempool_t *iod_mempool;
+ mempool_t *iod_meta_mempool;
/* shadow doorbell buffer support: */
__le32 *dbbuf_dbs;
@@ -239,6 +241,8 @@ struct nvme_iod {
dma_addr_t first_dma;
dma_addr_t meta_dma;
struct sg_table sgt;
+ struct sg_table meta_sgt;
+ union nvme_descriptor meta_list;
union nvme_descriptor list[NVME_MAX_NR_ALLOCATIONS];
};
@@ -506,6 +510,15 @@ static void nvme_commit_rqs(struct blk_mq_hw_ctx *hctx)
spin_unlock(&nvmeq->sq_lock);
}
+static inline bool nvme_pci_metadata_use_sgls(struct nvme_dev *dev,
+ struct request *req)
+{
+ if (!nvme_ctrl_meta_sgl_supported(&dev->ctrl))
+ return false;
+ return req->nr_integrity_segments > 1 ||
+ nvme_req(req)->flags & NVME_REQ_USERCMD;
+}
+
static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req,
int nseg)
{
@@ -518,8 +531,10 @@ static inline bool nvme_pci_use_sgls(struct nvme_dev *dev, struct request *req,
return false;
if (!nvmeq->qid)
return false;
+ if (nvme_pci_metadata_use_sgls(dev, req))
+ return true;
if (!sgl_threshold || avg_seg_size < sgl_threshold)
- return false;
+ return nvme_req(req)->flags & NVME_REQ_USERCMD;
return true;
}
@@ -780,7 +795,8 @@ static blk_status_t nvme_map_data(struct nvme_dev *dev, struct request *req,
struct bio_vec bv = req_bvec(req);
if (!is_pci_p2pdma_page(bv.bv_page)) {
- if ((bv.bv_offset & (NVME_CTRL_PAGE_SIZE - 1)) +
+ if (!nvme_pci_metadata_use_sgls(dev, req) &&
+ (bv.bv_offset & (NVME_CTRL_PAGE_SIZE - 1)) +
bv.bv_len <= NVME_CTRL_PAGE_SIZE * 2)
return nvme_setup_prp_simple(dev, req,
&cmnd->rw, &bv);
@@ -824,11 +840,69 @@ out_free_sg:
return ret;
}
-static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req,
- struct nvme_command *cmnd)
+static blk_status_t nvme_pci_setup_meta_sgls(struct nvme_dev *dev,
+ struct request *req)
+{
+ struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+ struct nvme_rw_command *cmnd = &iod->cmd.rw;
+ struct nvme_sgl_desc *sg_list;
+ struct scatterlist *sgl, *sg;
+ unsigned int entries;
+ dma_addr_t sgl_dma;
+ int rc, i;
+
+ iod->meta_sgt.sgl = mempool_alloc(dev->iod_meta_mempool, GFP_ATOMIC);
+ if (!iod->meta_sgt.sgl)
+ return BLK_STS_RESOURCE;
+
+ sg_init_table(iod->meta_sgt.sgl, req->nr_integrity_segments);
+ iod->meta_sgt.orig_nents = blk_rq_map_integrity_sg(req,
+ iod->meta_sgt.sgl);
+ if (!iod->meta_sgt.orig_nents)
+ goto out_free_sg;
+
+ rc = dma_map_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req),
+ DMA_ATTR_NO_WARN);
+ if (rc)
+ goto out_free_sg;
+
+ sg_list = dma_pool_alloc(dev->prp_small_pool, GFP_ATOMIC, &sgl_dma);
+ if (!sg_list)
+ goto out_unmap_sg;
+
+ entries = iod->meta_sgt.nents;
+ iod->meta_list.sg_list = sg_list;
+ iod->meta_dma = sgl_dma;
+
+ cmnd->flags = NVME_CMD_SGL_METASEG;
+ cmnd->metadata = cpu_to_le64(sgl_dma);
+
+ sgl = iod->meta_sgt.sgl;
+ if (entries == 1) {
+ nvme_pci_sgl_set_data(sg_list, sgl);
+ return BLK_STS_OK;
+ }
+
+ sgl_dma += sizeof(*sg_list);
+ nvme_pci_sgl_set_seg(sg_list, sgl_dma, entries);
+ for_each_sg(sgl, sg, entries, i)
+ nvme_pci_sgl_set_data(&sg_list[i + 1], sg);
+
+ return BLK_STS_OK;
+
+out_unmap_sg:
+ dma_unmap_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req), 0);
+out_free_sg:
+ mempool_free(iod->meta_sgt.sgl, dev->iod_meta_mempool);
+ return BLK_STS_RESOURCE;
+}
+
+static blk_status_t nvme_pci_setup_meta_mptr(struct nvme_dev *dev,
+ struct request *req)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
struct bio_vec bv = rq_integrity_vec(req);
+ struct nvme_command *cmnd = &iod->cmd;
iod->meta_dma = dma_map_bvec(dev->dev, &bv, rq_dma_dir(req), 0);
if (dma_mapping_error(dev->dev, iod->meta_dma))
@@ -837,6 +911,13 @@ static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req,
return BLK_STS_OK;
}
+static blk_status_t nvme_map_metadata(struct nvme_dev *dev, struct request *req)
+{
+ if (nvme_pci_metadata_use_sgls(dev, req))
+ return nvme_pci_setup_meta_sgls(dev, req);
+ return nvme_pci_setup_meta_mptr(dev, req);
+}
+
static blk_status_t nvme_prep_rq(struct nvme_dev *dev, struct request *req)
{
struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
@@ -845,6 +926,7 @@ static blk_status_t nvme_prep_rq(struct nvme_dev *dev, struct request *req)
iod->aborted = false;
iod->nr_allocations = -1;
iod->sgt.nents = 0;
+ iod->meta_sgt.nents = 0;
ret = nvme_setup_cmd(req->q->queuedata, req);
if (ret)
@@ -857,7 +939,7 @@ static blk_status_t nvme_prep_rq(struct nvme_dev *dev, struct request *req)
}
if (blk_integrity_rq(req)) {
- ret = nvme_map_metadata(dev, req, &iod->cmd);
+ ret = nvme_map_metadata(dev, req);
if (ret)
goto out_unmap_data;
}
@@ -955,17 +1037,31 @@ static void nvme_queue_rqs(struct rq_list *rqlist)
*rqlist = requeue_list;
}
+static __always_inline void nvme_unmap_metadata(struct nvme_dev *dev,
+ struct request *req)
+{
+ struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
+
+ if (!iod->meta_sgt.nents) {
+ dma_unmap_page(dev->dev, iod->meta_dma,
+ rq_integrity_vec(req).bv_len,
+ rq_dma_dir(req));
+ return;
+ }
+
+ dma_pool_free(dev->prp_small_pool, iod->meta_list.sg_list,
+ iod->meta_dma);
+ dma_unmap_sgtable(dev->dev, &iod->meta_sgt, rq_dma_dir(req), 0);
+ mempool_free(iod->meta_sgt.sgl, dev->iod_meta_mempool);
+}
+
static __always_inline void nvme_pci_unmap_rq(struct request *req)
{
struct nvme_queue *nvmeq = req->mq_hctx->driver_data;
struct nvme_dev *dev = nvmeq->dev;
- if (blk_integrity_rq(req)) {
- struct nvme_iod *iod = blk_mq_rq_to_pdu(req);
-
- dma_unmap_page(dev->dev, iod->meta_dma,
- rq_integrity_vec(req).bv_len, rq_dma_dir(req));
- }
+ if (blk_integrity_rq(req))
+ nvme_unmap_metadata(dev, req);
if (blk_rq_nr_phys_segments(req))
nvme_unmap_data(dev, req);
@@ -2076,6 +2172,7 @@ out:
static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred)
{
+ unsigned long dma_merge_boundary = dma_get_merge_boundary(dev->dev);
u64 min_chunk = min_t(u64, preferred, PAGE_SIZE * MAX_ORDER_NR_PAGES);
u64 hmminds = max_t(u32, dev->ctrl.hmminds * 4096, PAGE_SIZE * 2);
u64 chunk_size;
@@ -2084,7 +2181,7 @@ static int nvme_alloc_host_mem(struct nvme_dev *dev, u64 min, u64 preferred)
* If there is an IOMMU that can merge pages, try a virtually
* non-contiguous allocation for a single segment first.
*/
- if (!(PAGE_SIZE & dma_get_merge_boundary(dev->dev))) {
+ if (dma_merge_boundary && (PAGE_SIZE & dma_merge_boundary) == 0) {
if (!nvme_alloc_host_mem_single(dev, preferred))
return 0;
}
@@ -2737,15 +2834,20 @@ static int nvme_disable_prepare_reset(struct nvme_dev *dev, bool shutdown)
static int nvme_setup_prp_pools(struct nvme_dev *dev)
{
+ size_t small_align = 256;
+
dev->prp_page_pool = dma_pool_create("prp list page", dev->dev,
NVME_CTRL_PAGE_SIZE,
NVME_CTRL_PAGE_SIZE, 0);
if (!dev->prp_page_pool)
return -ENOMEM;
+ if (dev->ctrl.quirks & NVME_QUIRK_DMAPOOL_ALIGN_512)
+ small_align = 512;
+
/* Optimisation for I/Os between 4k and 128k */
dev->prp_small_pool = dma_pool_create("prp list 256", dev->dev,
- 256, 256, 0);
+ 256, small_align, 0);
if (!dev->prp_small_pool) {
dma_pool_destroy(dev->prp_page_pool);
return -ENOMEM;
@@ -2761,6 +2863,7 @@ static void nvme_release_prp_pools(struct nvme_dev *dev)
static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
{
+ size_t meta_size = sizeof(struct scatterlist) * (NVME_MAX_META_SEGS + 1);
size_t alloc_size = sizeof(struct scatterlist) * NVME_MAX_SEGS;
dev->iod_mempool = mempool_create_node(1,
@@ -2769,7 +2872,18 @@ static int nvme_pci_alloc_iod_mempool(struct nvme_dev *dev)
dev_to_node(dev->dev));
if (!dev->iod_mempool)
return -ENOMEM;
+
+ dev->iod_meta_mempool = mempool_create_node(1,
+ mempool_kmalloc, mempool_kfree,
+ (void *)meta_size, GFP_KERNEL,
+ dev_to_node(dev->dev));
+ if (!dev->iod_meta_mempool)
+ goto free;
+
return 0;
+free:
+ mempool_destroy(dev->iod_mempool);
+ return -ENOMEM;
}
static void nvme_free_tagset(struct nvme_dev *dev)
@@ -2834,6 +2948,11 @@ static void nvme_reset_work(struct work_struct *work)
if (result)
goto out;
+ if (nvme_ctrl_meta_sgl_supported(&dev->ctrl))
+ dev->ctrl.max_integrity_segments = NVME_MAX_META_SEGS;
+ else
+ dev->ctrl.max_integrity_segments = 1;
+
nvme_dbbuf_dma_alloc(dev);
result = nvme_setup_host_mem(dev);
@@ -3101,11 +3220,6 @@ static struct nvme_dev *nvme_pci_alloc_dev(struct pci_dev *pdev,
dev->ctrl.max_hw_sectors = min_t(u32,
NVME_MAX_KB_SZ << 1, dma_opt_mapping_size(&pdev->dev) >> 9);
dev->ctrl.max_segments = NVME_MAX_SEGS;
-
- /*
- * There is no support for SGLs for metadata (yet), so we are limited to
- * a single integrity segment for the separate metadata pointer.
- */
dev->ctrl.max_integrity_segments = 1;
return dev;
@@ -3168,6 +3282,11 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (result)
goto out_disable;
+ if (nvme_ctrl_meta_sgl_supported(&dev->ctrl))
+ dev->ctrl.max_integrity_segments = NVME_MAX_META_SEGS;
+ else
+ dev->ctrl.max_integrity_segments = 1;
+
nvme_dbbuf_dma_alloc(dev);
result = nvme_setup_host_mem(dev);
@@ -3210,6 +3329,7 @@ out_disable:
nvme_free_queues(dev, 0);
out_release_iod_mempool:
mempool_destroy(dev->iod_mempool);
+ mempool_destroy(dev->iod_meta_mempool);
out_release_prp_pools:
nvme_release_prp_pools(dev);
out_dev_unmap:
@@ -3275,6 +3395,7 @@ static void nvme_remove(struct pci_dev *pdev)
nvme_dbbuf_dma_free(dev);
nvme_free_queues(dev, 0);
mempool_destroy(dev->iod_mempool);
+ mempool_destroy(dev->iod_meta_mempool);
nvme_release_prp_pools(dev);
nvme_dev_unmap(dev);
nvme_uninit_ctrl(&dev->ctrl);
@@ -3473,12 +3594,10 @@ static const struct pci_device_id nvme_id_table[] = {
NVME_QUIRK_DEALLOCATE_ZEROES, },
{ PCI_VDEVICE(INTEL, 0x0a54), /* Intel P4500/P4600 */
.driver_data = NVME_QUIRK_STRIPE_SIZE |
- NVME_QUIRK_DEALLOCATE_ZEROES |
NVME_QUIRK_IGNORE_DEV_SUBNQN |
NVME_QUIRK_BOGUS_NID, },
{ PCI_VDEVICE(INTEL, 0x0a55), /* Dell Express Flash P4600 */
- .driver_data = NVME_QUIRK_STRIPE_SIZE |
- NVME_QUIRK_DEALLOCATE_ZEROES, },
+ .driver_data = NVME_QUIRK_STRIPE_SIZE, },
{ PCI_VDEVICE(INTEL, 0xf1a5), /* Intel 600P/P3100 */
.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
NVME_QUIRK_MEDIUM_PRIO_SQ |
@@ -3493,7 +3612,7 @@ static const struct pci_device_id nvme_id_table[] = {
{ PCI_VDEVICE(REDHAT, 0x0010), /* Qemu emulated controller */
.driver_data = NVME_QUIRK_BOGUS_NID, },
{ PCI_DEVICE(0x1217, 0x8760), /* O2 Micro 64GB Steam Deck */
- .driver_data = NVME_QUIRK_QDEPTH_ONE },
+ .driver_data = NVME_QUIRK_DMAPOOL_ALIGN_512, },
{ PCI_DEVICE(0x126f, 0x2262), /* Silicon Motion generic */
.driver_data = NVME_QUIRK_NO_DEEPEST_PS |
NVME_QUIRK_BOGUS_NID, },
diff --git a/drivers/nvme/host/pr.c b/drivers/nvme/host/pr.c
index dc7922f22600..cf2d2c5039dd 100644
--- a/drivers/nvme/host/pr.c
+++ b/drivers/nvme/host/pr.c
@@ -94,109 +94,137 @@ static int nvme_status_to_pr_err(int status)
}
}
-static int nvme_send_pr_command(struct block_device *bdev,
- struct nvme_command *c, void *data, unsigned int data_len)
+static int __nvme_send_pr_command(struct block_device *bdev, u32 cdw10,
+ u32 cdw11, u8 op, void *data, unsigned int data_len)
{
- if (nvme_disk_is_ns_head(bdev->bd_disk))
- return nvme_send_ns_head_pr_command(bdev, c, data, data_len);
+ struct nvme_command c = { 0 };
- return nvme_send_ns_pr_command(bdev->bd_disk->private_data, c, data,
- data_len);
+ c.common.opcode = op;
+ c.common.cdw10 = cpu_to_le32(cdw10);
+ c.common.cdw11 = cpu_to_le32(cdw11);
+
+ if (nvme_disk_is_ns_head(bdev->bd_disk))
+ return nvme_send_ns_head_pr_command(bdev, &c, data, data_len);
+ return nvme_send_ns_pr_command(bdev->bd_disk->private_data, &c,
+ data, data_len);
}
-static int nvme_pr_command(struct block_device *bdev, u32 cdw10,
- u64 key, u64 sa_key, u8 op)
+static int nvme_send_pr_command(struct block_device *bdev, u32 cdw10, u32 cdw11,
+ u8 op, void *data, unsigned int data_len)
{
- struct nvme_command c = { };
- u8 data[16] = { 0, };
int ret;
- put_unaligned_le64(key, &data[0]);
- put_unaligned_le64(sa_key, &data[8]);
-
- c.common.opcode = op;
- c.common.cdw10 = cpu_to_le32(cdw10);
-
- ret = nvme_send_pr_command(bdev, &c, data, sizeof(data));
- if (ret < 0)
- return ret;
-
- return nvme_status_to_pr_err(ret);
+ ret = __nvme_send_pr_command(bdev, cdw10, cdw11, op, data, data_len);
+ return ret < 0 ? ret : nvme_status_to_pr_err(ret);
}
-static int nvme_pr_register(struct block_device *bdev, u64 old,
- u64 new, unsigned flags)
+static int nvme_pr_register(struct block_device *bdev, u64 old_key, u64 new_key,
+ unsigned int flags)
{
+ struct nvmet_pr_register_data data = { 0 };
u32 cdw10;
if (flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
- cdw10 = old ? 2 : 0;
- cdw10 |= (flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0;
- cdw10 |= (1 << 30) | (1 << 31); /* PTPL=1 */
- return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_register);
+ data.crkey = cpu_to_le64(old_key);
+ data.nrkey = cpu_to_le64(new_key);
+
+ cdw10 = old_key ? NVME_PR_REGISTER_ACT_REPLACE :
+ NVME_PR_REGISTER_ACT_REG;
+ cdw10 |= (flags & PR_FL_IGNORE_KEY) ? NVME_PR_IGNORE_KEY : 0;
+ cdw10 |= NVME_PR_CPTPL_PERSIST;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_register,
+ &data, sizeof(data));
}
static int nvme_pr_reserve(struct block_device *bdev, u64 key,
enum pr_type type, unsigned flags)
{
+ struct nvmet_pr_acquire_data data = { 0 };
u32 cdw10;
if (flags & ~PR_FL_IGNORE_KEY)
return -EOPNOTSUPP;
- cdw10 = nvme_pr_type_from_blk(type) << 8;
- cdw10 |= ((flags & PR_FL_IGNORE_KEY) ? 1 << 3 : 0);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_acquire);
+ data.crkey = cpu_to_le64(key);
+
+ cdw10 = NVME_PR_ACQUIRE_ACT_ACQUIRE;
+ cdw10 |= nvme_pr_type_from_blk(type) << 8;
+ cdw10 |= (flags & PR_FL_IGNORE_KEY) ? NVME_PR_IGNORE_KEY : 0;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_acquire,
+ &data, sizeof(data));
}
static int nvme_pr_preempt(struct block_device *bdev, u64 old, u64 new,
enum pr_type type, bool abort)
{
- u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (abort ? 2 : 1);
+ struct nvmet_pr_acquire_data data = { 0 };
+ u32 cdw10;
+
+ data.crkey = cpu_to_le64(old);
+ data.prkey = cpu_to_le64(new);
- return nvme_pr_command(bdev, cdw10, old, new, nvme_cmd_resv_acquire);
+ cdw10 = abort ? NVME_PR_ACQUIRE_ACT_PREEMPT_AND_ABORT :
+ NVME_PR_ACQUIRE_ACT_PREEMPT;
+ cdw10 |= nvme_pr_type_from_blk(type) << 8;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_acquire,
+ &data, sizeof(data));
}
static int nvme_pr_clear(struct block_device *bdev, u64 key)
{
- u32 cdw10 = 1 | (key ? 0 : 1 << 3);
+ struct nvmet_pr_release_data data = { 0 };
+ u32 cdw10;
+
+ data.crkey = cpu_to_le64(key);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+ cdw10 = NVME_PR_RELEASE_ACT_CLEAR;
+ cdw10 |= key ? 0 : NVME_PR_IGNORE_KEY;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_release,
+ &data, sizeof(data));
}
static int nvme_pr_release(struct block_device *bdev, u64 key, enum pr_type type)
{
- u32 cdw10 = nvme_pr_type_from_blk(type) << 8 | (key ? 0 : 1 << 3);
+ struct nvmet_pr_release_data data = { 0 };
+ u32 cdw10;
+
+ data.crkey = cpu_to_le64(key);
- return nvme_pr_command(bdev, cdw10, key, 0, nvme_cmd_resv_release);
+ cdw10 = NVME_PR_RELEASE_ACT_RELEASE;
+ cdw10 |= nvme_pr_type_from_blk(type) << 8;
+ cdw10 |= key ? 0 : NVME_PR_IGNORE_KEY;
+
+ return nvme_send_pr_command(bdev, cdw10, 0, nvme_cmd_resv_release,
+ &data, sizeof(data));
}
static int nvme_pr_resv_report(struct block_device *bdev, void *data,
u32 data_len, bool *eds)
{
- struct nvme_command c = { };
+ u32 cdw10, cdw11;
int ret;
- c.common.opcode = nvme_cmd_resv_report;
- c.common.cdw10 = cpu_to_le32(nvme_bytes_to_numd(data_len));
- c.common.cdw11 = cpu_to_le32(NVME_EXTENDED_DATA_STRUCT);
+ cdw10 = nvme_bytes_to_numd(data_len);
+ cdw11 = NVME_EXTENDED_DATA_STRUCT;
*eds = true;
retry:
- ret = nvme_send_pr_command(bdev, &c, data, data_len);
+ ret = __nvme_send_pr_command(bdev, cdw10, cdw11, nvme_cmd_resv_report,
+ data, data_len);
if (ret == NVME_SC_HOST_ID_INCONSIST &&
- c.common.cdw11 == cpu_to_le32(NVME_EXTENDED_DATA_STRUCT)) {
- c.common.cdw11 = 0;
+ cdw11 == NVME_EXTENDED_DATA_STRUCT) {
+ cdw11 = 0;
*eds = false;
goto retry;
}
- if (ret < 0)
- return ret;
-
- return nvme_status_to_pr_err(ret);
+ return ret < 0 ? ret : nvme_status_to_pr_err(ret);
}
static int nvme_pr_read_keys(struct block_device *bdev,
diff --git a/drivers/nvme/host/rdma.c b/drivers/nvme/host/rdma.c
index 24a2759798d0..86a2891d9bcc 100644
--- a/drivers/nvme/host/rdma.c
+++ b/drivers/nvme/host/rdma.c
@@ -1019,7 +1019,7 @@ static int nvme_rdma_setup_ctrl(struct nvme_rdma_ctrl *ctrl, bool new)
goto destroy_admin;
}
- if (!(ctrl->ctrl.sgls & (1 << 2))) {
+ if (!(ctrl->ctrl.sgls & NVME_CTRL_SGLS_KSDBDS)) {
ret = -EOPNOTSUPP;
dev_err(ctrl->ctrl.device,
"Mandatory keyed sgls are not supported!\n");
@@ -1051,7 +1051,7 @@ static int nvme_rdma_setup_ctrl(struct nvme_rdma_ctrl *ctrl, bool new)
ctrl->ctrl.sqsize = ctrl->ctrl.maxcmd - 1;
}
- if (ctrl->ctrl.sgls & (1 << 20))
+ if (ctrl->ctrl.sgls & NVME_CTRL_SGLS_SAOS)
ctrl->use_inline_data = true;
if (ctrl->ctrl.queue_count > 1) {
@@ -1091,13 +1091,7 @@ destroy_io:
}
destroy_admin:
nvme_stop_keep_alive(&ctrl->ctrl);
- nvme_quiesce_admin_queue(&ctrl->ctrl);
- blk_sync_queue(ctrl->ctrl.admin_q);
- nvme_rdma_stop_queue(&ctrl->queues[0]);
- nvme_cancel_admin_tagset(&ctrl->ctrl);
- if (new)
- nvme_remove_admin_tag_set(&ctrl->ctrl);
- nvme_rdma_destroy_admin_queue(ctrl);
+ nvme_rdma_teardown_admin_queue(ctrl, new);
return ret;
}
diff --git a/drivers/nvme/host/tcp.c b/drivers/nvme/host/tcp.c
index 3e416af2659f..b127d41dbbfe 100644
--- a/drivers/nvme/host/tcp.c
+++ b/drivers/nvme/host/tcp.c
@@ -2024,14 +2024,6 @@ static int nvme_tcp_alloc_io_queues(struct nvme_ctrl *ctrl)
return __nvme_tcp_alloc_io_queues(ctrl);
}
-static void nvme_tcp_destroy_io_queues(struct nvme_ctrl *ctrl, bool remove)
-{
- nvme_tcp_stop_io_queues(ctrl);
- if (remove)
- nvme_remove_io_tag_set(ctrl);
- nvme_tcp_free_io_queues(ctrl);
-}
-
static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
{
int ret, nr_queues;
@@ -2101,14 +2093,6 @@ out_free_io_queues:
return ret;
}
-static void nvme_tcp_destroy_admin_queue(struct nvme_ctrl *ctrl, bool remove)
-{
- nvme_tcp_stop_queue(ctrl, 0);
- if (remove)
- nvme_remove_admin_tag_set(ctrl);
- nvme_tcp_free_admin_queue(ctrl);
-}
-
static int nvme_tcp_configure_admin_queue(struct nvme_ctrl *ctrl, bool new)
{
int error;
@@ -2163,9 +2147,11 @@ static void nvme_tcp_teardown_admin_queue(struct nvme_ctrl *ctrl,
blk_sync_queue(ctrl->admin_q);
nvme_tcp_stop_queue(ctrl, 0);
nvme_cancel_admin_tagset(ctrl);
- if (remove)
+ if (remove) {
nvme_unquiesce_admin_queue(ctrl);
- nvme_tcp_destroy_admin_queue(ctrl, remove);
+ nvme_remove_admin_tag_set(ctrl);
+ }
+ nvme_tcp_free_admin_queue(ctrl);
if (ctrl->tls_pskid) {
dev_dbg(ctrl->device, "Wipe negotiated TLS_PSK %08x\n",
ctrl->tls_pskid);
@@ -2178,14 +2164,15 @@ static void nvme_tcp_teardown_io_queues(struct nvme_ctrl *ctrl,
{
if (ctrl->queue_count <= 1)
return;
- nvme_quiesce_admin_queue(ctrl);
nvme_quiesce_io_queues(ctrl);
nvme_sync_io_queues(ctrl);
nvme_tcp_stop_io_queues(ctrl);
nvme_cancel_tagset(ctrl);
- if (remove)
+ if (remove) {
nvme_unquiesce_io_queues(ctrl);
- nvme_tcp_destroy_io_queues(ctrl, remove);
+ nvme_remove_io_tag_set(ctrl);
+ }
+ nvme_tcp_free_io_queues(ctrl);
}
static void nvme_tcp_reconnect_or_remove(struct nvme_ctrl *ctrl,
@@ -2274,11 +2261,13 @@ destroy_io:
nvme_sync_io_queues(ctrl);
nvme_tcp_stop_io_queues(ctrl);
nvme_cancel_tagset(ctrl);
- nvme_tcp_destroy_io_queues(ctrl, new);
+ if (new)
+ nvme_remove_io_tag_set(ctrl);
+ nvme_tcp_free_io_queues(ctrl);
}
destroy_admin:
nvme_stop_keep_alive(ctrl);
- nvme_tcp_teardown_admin_queue(ctrl, false);
+ nvme_tcp_teardown_admin_queue(ctrl, new);
return ret;
}
diff --git a/drivers/nvme/target/admin-cmd.c b/drivers/nvme/target/admin-cmd.c
index 934b401fbc2f..fa89b0549c36 100644
--- a/drivers/nvme/target/admin-cmd.c
+++ b/drivers/nvme/target/admin-cmd.c
@@ -139,7 +139,7 @@ static u16 nvmet_get_smart_log_all(struct nvmet_req *req,
unsigned long idx;
ctrl = req->sq->ctrl;
- xa_for_each(&ctrl->subsys->namespaces, idx, ns) {
+ nvmet_for_each_enabled_ns(&ctrl->subsys->namespaces, idx, ns) {
/* we don't have the right data for file backed ns */
if (!ns->bdev)
continue;
@@ -331,9 +331,10 @@ static u32 nvmet_format_ana_group(struct nvmet_req *req, u32 grpid,
u32 count = 0;
if (!(req->cmd->get_log_page.lsp & NVME_ANA_LOG_RGO)) {
- xa_for_each(&ctrl->subsys->namespaces, idx, ns)
+ nvmet_for_each_enabled_ns(&ctrl->subsys->namespaces, idx, ns) {
if (ns->anagrpid == grpid)
desc->nsids[count++] = cpu_to_le32(ns->nsid);
+ }
}
desc->grpid = cpu_to_le32(grpid);
@@ -601,11 +602,12 @@ static void nvmet_execute_identify_ctrl(struct nvmet_req *req)
id->awun = 0;
id->awupf = 0;
- id->sgls = cpu_to_le32(1 << 0); /* we always support SGLs */
+ /* we always support SGLs */
+ id->sgls = cpu_to_le32(NVME_CTRL_SGLS_BYTE_ALIGNED);
if (ctrl->ops->flags & NVMF_KEYED_SGLS)
- id->sgls |= cpu_to_le32(1 << 2);
+ id->sgls |= cpu_to_le32(NVME_CTRL_SGLS_KSDBDS);
if (req->port->inline_data_size)
- id->sgls |= cpu_to_le32(1 << 20);
+ id->sgls |= cpu_to_le32(NVME_CTRL_SGLS_SAOS);
strscpy(id->subnqn, ctrl->subsys->subsysnqn, sizeof(id->subnqn));
@@ -771,7 +773,7 @@ static void nvmet_execute_identify_endgrp_list(struct nvmet_req *req)
goto out;
}
- xa_for_each(&ctrl->subsys->namespaces, idx, ns) {
+ nvmet_for_each_enabled_ns(&ctrl->subsys->namespaces, idx, ns) {
if (ns->nsid <= min_endgid)
continue;
@@ -814,7 +816,7 @@ static void nvmet_execute_identify_nslist(struct nvmet_req *req, bool match_css)
goto out;
}
- xa_for_each(&ctrl->subsys->namespaces, idx, ns) {
+ nvmet_for_each_enabled_ns(&ctrl->subsys->namespaces, idx, ns) {
if (ns->nsid <= min_nsid)
continue;
if (match_css && req->ns->csi != req->cmd->identify.csi)
@@ -901,13 +903,18 @@ static void nvmet_execute_identify_ctrl_nvm(struct nvmet_req *req)
static void nvme_execute_identify_ns_nvm(struct nvmet_req *req)
{
u16 status;
+ struct nvme_id_ns_nvm *id;
status = nvmet_req_find_ns(req);
if (status)
goto out;
- status = nvmet_copy_to_sgl(req, 0, ZERO_PAGE(0),
- NVME_IDENTIFY_DATA_SIZE);
+ id = kzalloc(sizeof(*id), GFP_KERNEL);
+ if (!id) {
+ status = NVME_SC_INTERNAL;
+ goto out;
+ }
+ status = nvmet_copy_to_sgl(req, 0, id, sizeof(*id));
out:
nvmet_req_complete(req, status);
}
diff --git a/drivers/nvme/target/configfs.c b/drivers/nvme/target/configfs.c
index eeee9e9b854c..2b030f0efc38 100644
--- a/drivers/nvme/target/configfs.c
+++ b/drivers/nvme/target/configfs.c
@@ -810,18 +810,6 @@ static struct configfs_attribute *nvmet_ns_attrs[] = {
NULL,
};
-bool nvmet_subsys_nsid_exists(struct nvmet_subsys *subsys, u32 nsid)
-{
- struct config_item *ns_item;
- char name[12];
-
- snprintf(name, sizeof(name), "%u", nsid);
- mutex_lock(&subsys->namespaces_group.cg_subsys->su_mutex);
- ns_item = config_group_find_item(&subsys->namespaces_group, name);
- mutex_unlock(&subsys->namespaces_group.cg_subsys->su_mutex);
- return ns_item != NULL;
-}
-
static void nvmet_ns_release(struct config_item *item)
{
struct nvmet_ns *ns = to_nvmet_ns(item);
@@ -2254,12 +2242,17 @@ static ssize_t nvmet_root_discovery_nqn_store(struct config_item *item,
const char *page, size_t count)
{
struct list_head *entry;
+ char *old_nqn, *new_nqn;
size_t len;
len = strcspn(page, "\n");
if (!len || len > NVMF_NQN_FIELD_LEN - 1)
return -EINVAL;
+ new_nqn = kstrndup(page, len, GFP_KERNEL);
+ if (!new_nqn)
+ return -ENOMEM;
+
down_write(&nvmet_config_sem);
list_for_each(entry, &nvmet_subsystems_group.cg_children) {
struct config_item *item =
@@ -2268,13 +2261,15 @@ static ssize_t nvmet_root_discovery_nqn_store(struct config_item *item,
if (!strncmp(config_item_name(item), page, len)) {
pr_err("duplicate NQN %s\n", config_item_name(item));
up_write(&nvmet_config_sem);
+ kfree(new_nqn);
return -EINVAL;
}
}
- memset(nvmet_disc_subsys->subsysnqn, 0, NVMF_NQN_FIELD_LEN);
- memcpy(nvmet_disc_subsys->subsysnqn, page, len);
+ old_nqn = nvmet_disc_subsys->subsysnqn;
+ nvmet_disc_subsys->subsysnqn = new_nqn;
up_write(&nvmet_config_sem);
+ kfree(old_nqn);
return len;
}
diff --git a/drivers/nvme/target/core.c b/drivers/nvme/target/core.c
index 1f4e9989663b..fde6c555af61 100644
--- a/drivers/nvme/target/core.c
+++ b/drivers/nvme/target/core.c
@@ -127,7 +127,7 @@ static u32 nvmet_max_nsid(struct nvmet_subsys *subsys)
unsigned long idx;
u32 nsid = 0;
- xa_for_each(&subsys->namespaces, idx, cur)
+ nvmet_for_each_enabled_ns(&subsys->namespaces, idx, cur)
nsid = cur->nsid;
return nsid;
@@ -441,11 +441,14 @@ u16 nvmet_req_find_ns(struct nvmet_req *req)
struct nvmet_subsys *subsys = nvmet_req_subsys(req);
req->ns = xa_load(&subsys->namespaces, nsid);
- if (unlikely(!req->ns)) {
+ if (unlikely(!req->ns || !req->ns->enabled)) {
req->error_loc = offsetof(struct nvme_common_command, nsid);
- if (nvmet_subsys_nsid_exists(subsys, nsid))
- return NVME_SC_INTERNAL_PATH_ERROR;
- return NVME_SC_INVALID_NS | NVME_STATUS_DNR;
+ if (!req->ns) /* ns doesn't exist! */
+ return NVME_SC_INVALID_NS | NVME_STATUS_DNR;
+
+ /* ns exists but it's disabled */
+ req->ns = NULL;
+ return NVME_SC_INTERNAL_PATH_ERROR;
}
percpu_ref_get(&req->ns->ref);
@@ -583,8 +586,6 @@ int nvmet_ns_enable(struct nvmet_ns *ns)
goto out_unlock;
ret = -EMFILE;
- if (subsys->nr_namespaces == NVMET_MAX_NAMESPACES)
- goto out_unlock;
ret = nvmet_bdev_ns_enable(ns);
if (ret == -ENOTBLK)
@@ -599,38 +600,19 @@ int nvmet_ns_enable(struct nvmet_ns *ns)
list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
nvmet_p2pmem_ns_add_p2p(ctrl, ns);
- ret = percpu_ref_init(&ns->ref, nvmet_destroy_namespace,
- 0, GFP_KERNEL);
- if (ret)
- goto out_dev_put;
-
- if (ns->nsid > subsys->max_nsid)
- subsys->max_nsid = ns->nsid;
-
- ret = xa_insert(&subsys->namespaces, ns->nsid, ns, GFP_KERNEL);
- if (ret)
- goto out_restore_subsys_maxnsid;
-
if (ns->pr.enable) {
ret = nvmet_pr_init_ns(ns);
if (ret)
- goto out_remove_from_subsys;
+ goto out_dev_put;
}
- subsys->nr_namespaces++;
-
nvmet_ns_changed(subsys, ns->nsid);
ns->enabled = true;
+ xa_set_mark(&subsys->namespaces, ns->nsid, NVMET_NS_ENABLED);
ret = 0;
out_unlock:
mutex_unlock(&subsys->lock);
return ret;
-
-out_remove_from_subsys:
- xa_erase(&subsys->namespaces, ns->nsid);
-out_restore_subsys_maxnsid:
- subsys->max_nsid = nvmet_max_nsid(subsys);
- percpu_ref_exit(&ns->ref);
out_dev_put:
list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
pci_dev_put(radix_tree_delete(&ctrl->p2p_ns_map, ns->nsid));
@@ -649,15 +631,37 @@ void nvmet_ns_disable(struct nvmet_ns *ns)
goto out_unlock;
ns->enabled = false;
- xa_erase(&ns->subsys->namespaces, ns->nsid);
- if (ns->nsid == subsys->max_nsid)
- subsys->max_nsid = nvmet_max_nsid(subsys);
+ xa_clear_mark(&subsys->namespaces, ns->nsid, NVMET_NS_ENABLED);
list_for_each_entry(ctrl, &subsys->ctrls, subsys_entry)
pci_dev_put(radix_tree_delete(&ctrl->p2p_ns_map, ns->nsid));
mutex_unlock(&subsys->lock);
+ if (ns->pr.enable)
+ nvmet_pr_exit_ns(ns);
+
+ mutex_lock(&subsys->lock);
+ nvmet_ns_changed(subsys, ns->nsid);
+ nvmet_ns_dev_disable(ns);
+out_unlock:
+ mutex_unlock(&subsys->lock);
+}
+
+void nvmet_ns_free(struct nvmet_ns *ns)
+{
+ struct nvmet_subsys *subsys = ns->subsys;
+
+ nvmet_ns_disable(ns);
+
+ mutex_lock(&subsys->lock);
+
+ xa_erase(&subsys->namespaces, ns->nsid);
+ if (ns->nsid == subsys->max_nsid)
+ subsys->max_nsid = nvmet_max_nsid(subsys);
+
+ mutex_unlock(&subsys->lock);
+
/*
* Now that we removed the namespaces from the lookup list, we
* can kill the per_cpu ref and wait for any remaining references
@@ -671,21 +675,9 @@ void nvmet_ns_disable(struct nvmet_ns *ns)
wait_for_completion(&ns->disable_done);
percpu_ref_exit(&ns->ref);
- if (ns->pr.enable)
- nvmet_pr_exit_ns(ns);
-
mutex_lock(&subsys->lock);
-
subsys->nr_namespaces--;
- nvmet_ns_changed(subsys, ns->nsid);
- nvmet_ns_dev_disable(ns);
-out_unlock:
mutex_unlock(&subsys->lock);
-}
-
-void nvmet_ns_free(struct nvmet_ns *ns)
-{
- nvmet_ns_disable(ns);
down_write(&nvmet_ana_sem);
nvmet_ana_group_enabled[ns->anagrpid]--;
@@ -699,15 +691,33 @@ struct nvmet_ns *nvmet_ns_alloc(struct nvmet_subsys *subsys, u32 nsid)
{
struct nvmet_ns *ns;
+ mutex_lock(&subsys->lock);
+
+ if (subsys->nr_namespaces == NVMET_MAX_NAMESPACES)
+ goto out_unlock;
+
ns = kzalloc(sizeof(*ns), GFP_KERNEL);
if (!ns)
- return NULL;
+ goto out_unlock;
init_completion(&ns->disable_done);
ns->nsid = nsid;
ns->subsys = subsys;
+ if (percpu_ref_init(&ns->ref, nvmet_destroy_namespace, 0, GFP_KERNEL))
+ goto out_free;
+
+ if (ns->nsid > subsys->max_nsid)
+ subsys->max_nsid = nsid;
+
+ if (xa_insert(&subsys->namespaces, ns->nsid, ns, GFP_KERNEL))
+ goto out_exit;
+
+ subsys->nr_namespaces++;
+
+ mutex_unlock(&subsys->lock);
+
down_write(&nvmet_ana_sem);
ns->anagrpid = NVMET_DEFAULT_ANA_GRPID;
nvmet_ana_group_enabled[ns->anagrpid]++;
@@ -718,6 +728,14 @@ struct nvmet_ns *nvmet_ns_alloc(struct nvmet_subsys *subsys, u32 nsid)
ns->csi = NVME_CSI_NVM;
return ns;
+out_exit:
+ subsys->max_nsid = nvmet_max_nsid(subsys);
+ percpu_ref_exit(&ns->ref);
+out_free:
+ kfree(ns);
+out_unlock:
+ mutex_unlock(&subsys->lock);
+ return NULL;
}
static void nvmet_update_sq_head(struct nvmet_req *req)
@@ -1394,7 +1412,7 @@ static void nvmet_setup_p2p_ns_map(struct nvmet_ctrl *ctrl,
ctrl->p2p_client = get_device(req->p2p_client);
- xa_for_each(&ctrl->subsys->namespaces, idx, ns)
+ nvmet_for_each_enabled_ns(&ctrl->subsys->namespaces, idx, ns)
nvmet_p2pmem_ns_add_p2p(ctrl, ns);
}
diff --git a/drivers/nvme/target/io-cmd-bdev.c b/drivers/nvme/target/io-cmd-bdev.c
index 0bda83d0fc3e..eaf31c823cbe 100644
--- a/drivers/nvme/target/io-cmd-bdev.c
+++ b/drivers/nvme/target/io-cmd-bdev.c
@@ -36,7 +36,7 @@ void nvmet_bdev_set_limits(struct block_device *bdev, struct nvme_id_ns *id)
*/
id->nsfeat |= 1 << 4;
/* NPWG = Namespace Preferred Write Granularity. 0's based */
- id->npwg = lpp0b;
+ id->npwg = to0based(bdev_io_min(bdev) / bdev_logical_block_size(bdev));
/* NPWA = Namespace Preferred Write Alignment. 0's based */
id->npwa = id->npwg;
/* NPDG = Namespace Preferred Deallocate Granularity. 0's based */
diff --git a/drivers/nvme/target/nvmet.h b/drivers/nvme/target/nvmet.h
index 58328b35dc96..7233549f7c8a 100644
--- a/drivers/nvme/target/nvmet.h
+++ b/drivers/nvme/target/nvmet.h
@@ -24,6 +24,7 @@
#define NVMET_DEFAULT_VS NVME_VS(2, 1, 0)
+#define NVMET_NS_ENABLED XA_MARK_1
#define NVMET_ASYNC_EVENTS 4
#define NVMET_ERROR_LOG_SLOTS 128
#define NVMET_NO_ERROR_LOC ((u16)-1)
@@ -33,6 +34,12 @@
#define NVMET_FR_MAX_SIZE 8
#define NVMET_PR_LOG_QUEUE_SIZE 64
+#define nvmet_for_each_ns(xa, index, entry) \
+ xa_for_each(xa, index, entry)
+
+#define nvmet_for_each_enabled_ns(xa, index, entry) \
+ xa_for_each_marked(xa, index, entry, NVMET_NS_ENABLED)
+
/*
* Supported optional AENs:
*/
diff --git a/drivers/nvme/target/passthru.c b/drivers/nvme/target/passthru.c
index 0f9b280c438d..30b21936b0c6 100644
--- a/drivers/nvme/target/passthru.c
+++ b/drivers/nvme/target/passthru.c
@@ -13,7 +13,7 @@
#include "../host/nvme.h"
#include "nvmet.h"
-MODULE_IMPORT_NS(NVME_TARGET_PASSTHRU);
+MODULE_IMPORT_NS("NVME_TARGET_PASSTHRU");
/*
* xarray to maintain one passthru subsystem per nvme controller.
diff --git a/drivers/nvme/target/pr.c b/drivers/nvme/target/pr.c
index 25a02b50d9f3..cd22d8333314 100644
--- a/drivers/nvme/target/pr.c
+++ b/drivers/nvme/target/pr.c
@@ -60,7 +60,7 @@ u16 nvmet_set_feat_resv_notif_mask(struct nvmet_req *req, u32 mask)
goto success;
}
- xa_for_each(&ctrl->subsys->namespaces, idx, ns) {
+ nvmet_for_each_enabled_ns(&ctrl->subsys->namespaces, idx, ns) {
if (ns->pr.enable)
WRITE_ONCE(ns->pr.notify_mask, mask);
}
@@ -828,12 +828,11 @@ static void nvmet_execute_pr_report(struct nvmet_req *req)
goto out;
}
- data = kmalloc(num_bytes, GFP_KERNEL);
+ data = kzalloc(num_bytes, GFP_KERNEL);
if (!data) {
status = NVME_SC_INTERNAL;
goto out;
}
- memset(data, 0, num_bytes);
data->gen = cpu_to_le32(atomic_read(&pr->generation));
data->ptpls = 0;
ctrl_eds = data->regctl_eds;
@@ -1057,7 +1056,7 @@ int nvmet_ctrl_init_pr(struct nvmet_ctrl *ctrl)
* nvmet_pr_init_ns(), see more details in nvmet_ns_enable().
* So just check ns->pr.enable.
*/
- xa_for_each(&subsys->namespaces, idx, ns) {
+ nvmet_for_each_enabled_ns(&subsys->namespaces, idx, ns) {
if (ns->pr.enable) {
ret = nvmet_pr_alloc_and_insert_pc_ref(ns, ctrl->cntlid,
&ctrl->hostid);
@@ -1068,7 +1067,7 @@ int nvmet_ctrl_init_pr(struct nvmet_ctrl *ctrl)
return 0;
free_per_ctrl_refs:
- xa_for_each(&subsys->namespaces, idx, ns) {
+ nvmet_for_each_enabled_ns(&subsys->namespaces, idx, ns) {
if (ns->pr.enable) {
pc_ref = xa_erase(&ns->pr_per_ctrl_refs, ctrl->cntlid);
if (pc_ref)
@@ -1088,7 +1087,7 @@ void nvmet_ctrl_destroy_pr(struct nvmet_ctrl *ctrl)
kfifo_free(&ctrl->pr_log_mgr.log_queue);
mutex_destroy(&ctrl->pr_log_mgr.lock);
- xa_for_each(&ctrl->subsys->namespaces, idx, ns) {
+ nvmet_for_each_enabled_ns(&ctrl->subsys->namespaces, idx, ns) {
if (ns->pr.enable) {
pc_ref = xa_erase(&ns->pr_per_ctrl_refs, ctrl->cntlid);
if (pc_ref)
diff --git a/drivers/nvmem/Kconfig b/drivers/nvmem/Kconfig
index d2c384f58028..8671b7c974b9 100644
--- a/drivers/nvmem/Kconfig
+++ b/drivers/nvmem/Kconfig
@@ -246,6 +246,17 @@ config NVMEM_RAVE_SP_EEPROM
help
Say y here to enable Rave SP EEPROM support.
+config NVMEM_RCAR_EFUSE
+ tristate "Renesas R-Car Gen4 E-FUSE support"
+ depends on (ARCH_RENESAS && ARM64) || COMPILE_TEST
+ depends on NVMEM
+ help
+ Enable support for reading the fuses in the E-FUSE or OTP
+ non-volatile memory block on Renesas R-Car Gen4 SoCs.
+
+ This driver can also be built as a module. If so, the module
+ will be called nvmem-rcar-efuse.
+
config NVMEM_RMEM
tristate "Reserved Memory Based Driver Support"
depends on HAS_IOMEM
diff --git a/drivers/nvmem/Makefile b/drivers/nvmem/Makefile
index cdd01fbf1313..5b77bbb6488b 100644
--- a/drivers/nvmem/Makefile
+++ b/drivers/nvmem/Makefile
@@ -52,6 +52,8 @@ obj-$(CONFIG_NVMEM_QCOM_SEC_QFPROM) += nvmem_sec_qfprom.o
nvmem_sec_qfprom-y := sec-qfprom.o
obj-$(CONFIG_NVMEM_RAVE_SP_EEPROM) += nvmem-rave-sp-eeprom.o
nvmem-rave-sp-eeprom-y := rave-sp-eeprom.o
+obj-$(CONFIG_NVMEM_RCAR_EFUSE) += nvmem-rcar-efuse.o
+nvmem-rcar-efuse-y := rcar-efuse.o
obj-$(CONFIG_NVMEM_RMEM) += nvmem-rmem.o
nvmem-rmem-y := rmem.o
obj-$(CONFIG_NVMEM_ROCKCHIP_EFUSE) += nvmem_rockchip_efuse.o
diff --git a/drivers/nvmem/brcm_nvram.c b/drivers/nvmem/brcm_nvram.c
index 3d8c87835f4d..b810df727b44 100644
--- a/drivers/nvmem/brcm_nvram.c
+++ b/drivers/nvmem/brcm_nvram.c
@@ -22,7 +22,7 @@
*
* @dev: NVMEM device pointer
* @nvmem_size: Size of the whole space available for NVRAM
- * @data: NVRAM data copy stored to avoid poking underlaying flash controller
+ * @data: NVRAM data copy stored to avoid poking underlying flash controller
* @data_len: NVRAM data size
* @padding_byte: Padding value used to fill remaining space
* @cells: Array of discovered NVMEM cells
diff --git a/drivers/nvmem/core.c b/drivers/nvmem/core.c
index 33ffa2aa4c11..d6494dfc20a7 100644
--- a/drivers/nvmem/core.c
+++ b/drivers/nvmem/core.c
@@ -267,7 +267,7 @@ static ssize_t bin_attr_nvmem_write(struct file *filp, struct kobject *kobj,
count = round_down(count, nvmem->word_size);
- if (!nvmem->reg_write)
+ if (!nvmem->reg_write || nvmem->read_only)
return -EPERM;
rc = nvmem_reg_write(nvmem, pos, buf, count);
@@ -298,16 +298,25 @@ static umode_t nvmem_bin_attr_get_umode(struct nvmem_device *nvmem)
}
static umode_t nvmem_bin_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr, int i)
+ const struct bin_attribute *attr,
+ int i)
{
struct device *dev = kobj_to_dev(kobj);
struct nvmem_device *nvmem = to_nvmem_device(dev);
- attr->size = nvmem->size;
-
return nvmem_bin_attr_get_umode(nvmem);
}
+static size_t nvmem_bin_attr_size(struct kobject *kobj,
+ const struct bin_attribute *attr,
+ int i)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct nvmem_device *nvmem = to_nvmem_device(dev);
+
+ return nvmem->size;
+}
+
static umode_t nvmem_attr_is_visible(struct kobject *kobj,
struct attribute *attr, int i)
{
@@ -383,6 +392,7 @@ static const struct attribute_group nvmem_bin_group = {
.bin_attrs = nvmem_bin_attributes,
.attrs = nvmem_attrs,
.is_bin_visible = nvmem_bin_attr_is_visible,
+ .bin_size = nvmem_bin_attr_size,
.is_visible = nvmem_attr_is_visible,
};
@@ -1247,7 +1257,7 @@ static void devm_nvmem_device_release(struct device *dev, void *res)
}
/**
- * devm_nvmem_device_put() - put alredy got nvmem device
+ * devm_nvmem_device_put() - put already got nvmem device
*
* @dev: Device that uses the nvmem device.
* @nvmem: pointer to nvmem device allocated by devm_nvmem_cell_get(),
@@ -1265,7 +1275,7 @@ void devm_nvmem_device_put(struct device *dev, struct nvmem_device *nvmem)
EXPORT_SYMBOL_GPL(devm_nvmem_device_put);
/**
- * nvmem_device_put() - put alredy got nvmem device
+ * nvmem_device_put() - put already got nvmem device
*
* @nvmem: pointer to nvmem device that needs to be released.
*/
diff --git a/drivers/nvmem/imx-iim.c b/drivers/nvmem/imx-iim.c
index f13bbd164086..8cfbe55a56cb 100644
--- a/drivers/nvmem/imx-iim.c
+++ b/drivers/nvmem/imx-iim.c
@@ -115,11 +115,11 @@ static int imx_iim_probe(struct platform_device *pdev)
if (IS_ERR(iim->clk))
return PTR_ERR(iim->clk);
- cfg.name = "imx-iim",
- cfg.read_only = true,
- cfg.word_size = 1,
- cfg.stride = 1,
- cfg.reg_read = imx_iim_read,
+ cfg.name = "imx-iim";
+ cfg.read_only = true;
+ cfg.word_size = 1;
+ cfg.stride = 1;
+ cfg.reg_read = imx_iim_read;
cfg.dev = dev;
cfg.size = drvdata->nregs;
cfg.priv = iim;
diff --git a/drivers/nvmem/lpc18xx_eeprom.c b/drivers/nvmem/lpc18xx_eeprom.c
index a73acc7377d2..aa43f5f612f9 100644
--- a/drivers/nvmem/lpc18xx_eeprom.c
+++ b/drivers/nvmem/lpc18xx_eeprom.c
@@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_eeprom_of_match);
static struct platform_driver lpc18xx_eeprom_driver = {
.probe = lpc18xx_eeprom_probe,
- .remove_new = lpc18xx_eeprom_remove,
+ .remove = lpc18xx_eeprom_remove,
.driver = {
.name = "lpc18xx-eeprom",
.of_match_table = lpc18xx_eeprom_of_match,
diff --git a/drivers/nvmem/lpc18xx_otp.c b/drivers/nvmem/lpc18xx_otp.c
index adc9948e7b2e..c41a0c58bec7 100644
--- a/drivers/nvmem/lpc18xx_otp.c
+++ b/drivers/nvmem/lpc18xx_otp.c
@@ -21,7 +21,7 @@
* LPC18xx OTP memory contains 4 banks with 4 32-bit words. Bank 0 starts
* at offset 0 from the base.
*
- * Bank 0 contains the part ID for Flashless devices and is reseverd for
+ * Bank 0 contains the part ID for Flashless devices and is reserved for
* devices with Flash.
* Bank 1/2 is generale purpose or AES key storage for secure devices.
* Bank 3 contains control data, USB ID and generale purpose words.
diff --git a/drivers/nvmem/microchip-otpc.c b/drivers/nvmem/microchip-otpc.c
index 7cf81738a3e0..df979e8549fd 100644
--- a/drivers/nvmem/microchip-otpc.c
+++ b/drivers/nvmem/microchip-otpc.c
@@ -156,7 +156,7 @@ static int mchp_otpc_read(void *priv, unsigned int off, void *val,
/*
* We reach this point with off being multiple of stride = 4 to
* be able to cross the subsystem. Inside the driver we use continuous
- * unsigned integer numbers for packet id, thus devide off by 4
+ * unsigned integer numbers for packet id, thus divide off by 4
* before passing it to mchp_otpc_id_to_packet().
*/
packet = mchp_otpc_id_to_packet(otpc, off / 4);
diff --git a/drivers/nvmem/mtk-efuse.c b/drivers/nvmem/mtk-efuse.c
index 9caf04667341..af953e1d9230 100644
--- a/drivers/nvmem/mtk-efuse.c
+++ b/drivers/nvmem/mtk-efuse.c
@@ -127,7 +127,7 @@ static void mtk_efuse_remove(struct platform_device *pdev)
static struct platform_driver mtk_efuse_driver = {
.probe = mtk_efuse_probe,
- .remove_new = mtk_efuse_remove,
+ .remove = mtk_efuse_remove,
.driver = {
.name = "mediatek,efuse",
.of_match_table = mtk_efuse_of_match,
diff --git a/drivers/nvmem/rcar-efuse.c b/drivers/nvmem/rcar-efuse.c
new file mode 100644
index 000000000000..f24bdb9cb5a7
--- /dev/null
+++ b/drivers/nvmem/rcar-efuse.c
@@ -0,0 +1,142 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Renesas R-Car E-FUSE/OTP Driver
+ *
+ * Copyright (C) 2024 Glider bv
+ */
+
+#include <linux/device.h>
+#include <linux/export.h>
+#include <linux/io.h>
+#include <linux/mod_devicetable.h>
+#include <linux/nvmem-provider.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/property.h>
+
+struct rcar_fuse {
+ struct nvmem_keepout keepouts[2];
+ struct nvmem_device *nvmem;
+ struct device *dev;
+ void __iomem *base;
+};
+
+struct rcar_fuse_data {
+ unsigned int bank; /* 0: PFC + E-FUSE, 1: OPT_MEM + E-FUSE */
+ unsigned int start; /* inclusive */
+ unsigned int end; /* exclusive */
+};
+
+static int rcar_fuse_reg_read(void *priv, unsigned int offset, void *val,
+ size_t bytes)
+{
+ struct rcar_fuse *fuse = priv;
+ int ret;
+
+ ret = pm_runtime_resume_and_get(fuse->dev);
+ if (ret < 0)
+ return ret;
+
+ __ioread32_copy(val, fuse->base + offset, bytes / 4);
+
+ pm_runtime_put(fuse->dev);
+
+ return 0;
+}
+
+static int rcar_fuse_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ const struct rcar_fuse_data *data = device_get_match_data(dev);
+ struct nvmem_config config = {
+ .dev = dev,
+ .name = "rcar-fuse",
+ .id = NVMEM_DEVID_NONE,
+ .owner = THIS_MODULE,
+ .type = NVMEM_TYPE_OTP,
+ .read_only = true,
+ .root_only = true,
+ .reg_read = rcar_fuse_reg_read,
+ .word_size = 4,
+ .stride = 4,
+ };
+ struct rcar_fuse *fuse;
+ struct resource *res;
+ int ret;
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret < 0)
+ return ret;
+
+ fuse = devm_kzalloc(dev, sizeof(*fuse), GFP_KERNEL);
+ if (!fuse)
+ return -ENOMEM;
+
+ fuse->base = devm_platform_get_and_ioremap_resource(pdev, data->bank,
+ &res);
+ if (IS_ERR(fuse->base))
+ return PTR_ERR(fuse->base);
+
+ fuse->dev = dev;
+ fuse->keepouts[0].start = 0;
+ fuse->keepouts[0].end = data->start;
+ fuse->keepouts[1].start = data->end;
+ fuse->keepouts[1].end = resource_size(res);
+
+ config.keepout = fuse->keepouts;
+ config.nkeepout = ARRAY_SIZE(fuse->keepouts);
+ config.size = resource_size(res);
+ config.priv = fuse;
+
+ fuse->nvmem = devm_nvmem_register(dev, &config);
+ if (IS_ERR(fuse->nvmem))
+ return dev_err_probe(dev, PTR_ERR(fuse->nvmem),
+ "Failed to register NVMEM device\n");
+
+ return 0;
+}
+
+static const struct rcar_fuse_data rcar_fuse_v3u = {
+ .bank = 0,
+ .start = 0x0c0,
+ .end = 0x0e8,
+};
+
+static const struct rcar_fuse_data rcar_fuse_s4 = {
+ .bank = 0,
+ .start = 0x0c0,
+ .end = 0x14c,
+};
+
+static const struct rcar_fuse_data rcar_fuse_v4h = {
+ .bank = 1,
+ .start = 0x100,
+ .end = 0x1a0,
+};
+
+static const struct rcar_fuse_data rcar_fuse_v4m = {
+ .bank = 1,
+ .start = 0x100,
+ .end = 0x110,
+};
+
+static const struct of_device_id rcar_fuse_match[] = {
+ { .compatible = "renesas,r8a779a0-efuse", .data = &rcar_fuse_v3u },
+ { .compatible = "renesas,r8a779f0-efuse", .data = &rcar_fuse_s4 },
+ { .compatible = "renesas,r8a779g0-otp", .data = &rcar_fuse_v4h },
+ { .compatible = "renesas,r8a779h0-otp", .data = &rcar_fuse_v4m },
+ { /* sentinel */ }
+};
+
+static struct platform_driver rcar_fuse_driver = {
+ .probe = rcar_fuse_probe,
+ .driver = {
+ .name = "rcar_fuse",
+ .of_match_table = rcar_fuse_match,
+ },
+};
+module_platform_driver(rcar_fuse_driver);
+
+MODULE_DESCRIPTION("Renesas R-Car E-FUSE/OTP driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Geert Uytterhoeven");
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index f0b8cc23c46d..50697cc3b07e 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -2,6 +2,12 @@
config DTC
bool
+config GENERIC_BUILTIN_DTB
+ bool
+
+config BUILTIN_DTB_ALL
+ bool
+
menuconfig OF
bool "Device Tree and Open Firmware support"
help
diff --git a/drivers/of/address.c b/drivers/of/address.c
index c5b925ac469f..c1f1c810e810 100644
--- a/drivers/of/address.c
+++ b/drivers/of/address.c
@@ -459,7 +459,8 @@ static int of_translate_one(const struct device_node *parent, const struct of_bu
}
if (ranges == NULL || rlen == 0) {
offset = of_read_number(addr, na);
- memset(addr, 0, pna * 4);
+ /* set address to zero, pass flags through */
+ memset(addr + pbus->flag_cells, 0, (pna - pbus->flag_cells) * 4);
pr_debug("empty ranges; 1:1 translation\n");
goto finish;
}
@@ -619,7 +620,7 @@ struct device_node *__of_get_dma_parent(const struct device_node *np)
if (ret < 0)
return of_get_parent(np);
- return of_node_get(args.np);
+ return args.np;
}
#endif
diff --git a/drivers/of/base.c b/drivers/of/base.c
index a8b0c42bdc8e..6f5abea2462a 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -88,7 +88,8 @@ static bool __of_node_is_type(const struct device_node *np, const char *type)
}
#define EXCLUDED_DEFAULT_CELLS_PLATFORMS ( \
- IS_ENABLED(CONFIG_SPARC) \
+ IS_ENABLED(CONFIG_SPARC) || \
+ of_find_compatible_node(NULL, NULL, "coreboot") \
)
int of_bus_n_addr_cells(struct device_node *np)
@@ -644,6 +645,42 @@ struct device_node *of_get_next_child(const struct device_node *node,
}
EXPORT_SYMBOL(of_get_next_child);
+/**
+ * of_get_next_child_with_prefix - Find the next child node with prefix
+ * @node: parent node
+ * @prev: previous child of the parent node, or NULL to get first
+ * @prefix: prefix that the node name should have
+ *
+ * This function is like of_get_next_child(), except that it automatically
+ * skips any nodes whose name doesn't have the given prefix.
+ *
+ * Return: A node pointer with refcount incremented, use
+ * of_node_put() on it when done.
+ */
+struct device_node *of_get_next_child_with_prefix(const struct device_node *node,
+ struct device_node *prev,
+ const char *prefix)
+{
+ struct device_node *next;
+ unsigned long flags;
+
+ if (!node)
+ return NULL;
+
+ raw_spin_lock_irqsave(&devtree_lock, flags);
+ next = prev ? prev->sibling : node->child;
+ for (; next; next = next->sibling) {
+ if (!of_node_name_prefix(next, prefix))
+ continue;
+ if (of_node_get(next))
+ break;
+ }
+ of_node_put(prev);
+ raw_spin_unlock_irqrestore(&devtree_lock, flags);
+ return next;
+}
+EXPORT_SYMBOL(of_get_next_child_with_prefix);
+
static struct device_node *of_get_next_status_child(const struct device_node *node,
struct device_node *prev,
bool (*checker)(const struct device_node *))
@@ -1471,8 +1508,10 @@ int of_parse_phandle_with_args_map(const struct device_node *np,
map_len--;
/* Check if not found */
- if (!new)
+ if (!new) {
+ ret = -EINVAL;
goto put;
+ }
if (!of_device_is_available(new))
match = 0;
@@ -1482,17 +1521,20 @@ int of_parse_phandle_with_args_map(const struct device_node *np,
goto put;
/* Check for malformed properties */
- if (WARN_ON(new_size > MAX_PHANDLE_ARGS))
- goto put;
- if (map_len < new_size)
+ if (WARN_ON(new_size > MAX_PHANDLE_ARGS) ||
+ map_len < new_size) {
+ ret = -EINVAL;
goto put;
+ }
/* Move forward by new node's #<list>-cells amount */
map += new_size;
map_len -= new_size;
}
- if (!match)
+ if (!match) {
+ ret = -ENOENT;
goto put;
+ }
/* Get the <list>-map-pass-thru property (optional) */
pass = of_get_property(cur, pass_name, NULL);
diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c
index d45a8df61380..0aba760f7577 100644
--- a/drivers/of/dynamic.c
+++ b/drivers/of/dynamic.c
@@ -1072,3 +1072,47 @@ int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np,
return of_changeset_add_prop_helper(ocs, np, &prop);
}
EXPORT_SYMBOL_GPL(of_changeset_add_prop_bool);
+
+static int of_changeset_update_prop_helper(struct of_changeset *ocs,
+ struct device_node *np,
+ const struct property *pp)
+{
+ struct property *new_pp;
+ int ret;
+
+ new_pp = __of_prop_dup(pp, GFP_KERNEL);
+ if (!new_pp)
+ return -ENOMEM;
+
+ ret = of_changeset_update_property(ocs, np, new_pp);
+ if (ret)
+ __of_prop_free(new_pp);
+
+ return ret;
+}
+
+/**
+ * of_changeset_update_prop_string - Add a string property update to a changeset
+ *
+ * @ocs: changeset pointer
+ * @np: device node pointer
+ * @prop_name: name of the property to be updated
+ * @str: pointer to null terminated string
+ *
+ * Create a string property to be updated and add it to a changeset.
+ *
+ * Return: 0 on success, a negative error value in case of an error.
+ */
+int of_changeset_update_prop_string(struct of_changeset *ocs,
+ struct device_node *np,
+ const char *prop_name, const char *str)
+{
+ struct property prop = {
+ .name = (char *)prop_name,
+ .length = strlen(str) + 1,
+ .value = (void *)str,
+ };
+
+ return of_changeset_update_prop_helper(ocs, np, &prop);
+}
+EXPORT_SYMBOL_GPL(of_changeset_update_prop_string);
diff --git a/drivers/of/empty_root.dts b/drivers/of/empty_root.dts
index cf9e97a60f48..cbe169ba3db5 100644
--- a/drivers/of/empty_root.dts
+++ b/drivers/of/empty_root.dts
@@ -2,5 +2,12 @@
/dts-v1/;
/ {
-
+ /*
+ * #address-cells/#size-cells are required properties at root node.
+ * Use 2 cells for both address cells and size cells in order to fully
+ * support 64-bit addresses and sizes on systems using this empty root
+ * node.
+ */
+ #address-cells = <0x02>;
+ #size-cells = <0x02>;
};
diff --git a/drivers/of/irq.c b/drivers/of/irq.c
index 67fc0ceaa5f5..98b1cf78ecac 100644
--- a/drivers/of/irq.c
+++ b/drivers/of/irq.c
@@ -111,6 +111,7 @@ const __be32 *of_irq_parse_imap_parent(const __be32 *imap, int len, struct of_ph
else
np = of_find_node_by_phandle(be32_to_cpup(imap));
imap++;
+ len--;
/* Check if not found */
if (!np) {
@@ -354,6 +355,7 @@ int of_irq_parse_one(struct device_node *device, int index, struct of_phandle_ar
return of_irq_parse_oldworld(device, index, out_irq);
/* Get the reg property (if any) */
+ addr_len = 0;
addr = of_get_property(device, "reg", &addr_len);
/* Prevent out-of-bounds read in case of longer interrupt parent address size */
diff --git a/drivers/of/property.c b/drivers/of/property.c
index 519bf9229e61..cfc8aea002e4 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -1286,7 +1286,6 @@ DEFINE_SIMPLE_PROP(iommus, "iommus", "#iommu-cells")
DEFINE_SIMPLE_PROP(mboxes, "mboxes", "#mbox-cells")
DEFINE_SIMPLE_PROP(io_channels, "io-channels", "#io-channel-cells")
DEFINE_SIMPLE_PROP(io_backends, "io-backends", "#io-backend-cells")
-DEFINE_SIMPLE_PROP(interrupt_parent, "interrupt-parent", NULL)
DEFINE_SIMPLE_PROP(dmas, "dmas", "#dma-cells")
DEFINE_SIMPLE_PROP(power_domains, "power-domains", "#power-domain-cells")
DEFINE_SIMPLE_PROP(hwlocks, "hwlocks", "#hwlock-cells")
@@ -1432,7 +1431,6 @@ static const struct supplier_bindings of_supplier_bindings[] = {
{ .parse_prop = parse_mboxes, },
{ .parse_prop = parse_io_channels, },
{ .parse_prop = parse_io_backends, },
- { .parse_prop = parse_interrupt_parent, },
{ .parse_prop = parse_dmas, .optional = true, },
{ .parse_prop = parse_power_domains, },
{ .parse_prop = parse_hwlocks, },
diff --git a/drivers/of/unittest-data/tests-address.dtsi b/drivers/of/unittest-data/tests-address.dtsi
index 3344f15c3755..f02a181bb125 100644
--- a/drivers/of/unittest-data/tests-address.dtsi
+++ b/drivers/of/unittest-data/tests-address.dtsi
@@ -114,6 +114,7 @@
device_type = "pci";
ranges = <0x82000000 0 0xe8000000 0 0xe8000000 0 0x7f00000>,
<0x81000000 0 0x00000000 0 0xefff0000 0 0x0010000>;
+ dma-ranges = <0x43000000 0x10 0x00 0x00 0x00 0x00 0x10000000>;
reg = <0x00000000 0xd1070000 0x20000>;
pci@0,0 {
@@ -142,6 +143,7 @@
#size-cells = <0x01>;
ranges = <0xa0000000 0 0 0 0x2000000>,
<0xb0000000 1 0 0 0x1000000>;
+ dma-ranges = <0xc0000000 0x43000000 0x10 0x00 0x10000000>;
dev@e0000000 {
reg = <0xa0001000 0x1000>,
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index daf9a2dddd7e..438fd70fa995 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -1213,6 +1213,44 @@ static void __init of_unittest_pci_dma_ranges(void)
of_node_put(np);
}
+static void __init of_unittest_pci_empty_dma_ranges(void)
+{
+ struct device_node *np;
+ struct of_pci_range range;
+ struct of_pci_range_parser parser;
+
+ if (!IS_ENABLED(CONFIG_PCI))
+ return;
+
+ np = of_find_node_by_path("/testcase-data/address-tests2/pcie@d1070000/pci@0,0/dev@0,0/local-bus@0");
+ if (!np) {
+ pr_err("missing testcase data\n");
+ return;
+ }
+
+ if (of_pci_dma_range_parser_init(&parser, np)) {
+ pr_err("missing dma-ranges property\n");
+ return;
+ }
+
+ /*
+ * Get the dma-ranges from the device tree
+ */
+ for_each_of_pci_range(&parser, &range) {
+ unittest(range.size == 0x10000000,
+ "for_each_of_pci_range wrong size on node %pOF size=%llx\n",
+ np, range.size);
+ unittest(range.cpu_addr == 0x00000000,
+ "for_each_of_pci_range wrong CPU addr (%llx) on node %pOF",
+ range.cpu_addr, np);
+ unittest(range.pci_addr == 0xc0000000,
+ "for_each_of_pci_range wrong DMA addr (%llx) on node %pOF",
+ range.pci_addr, np);
+ }
+
+ of_node_put(np);
+}
+
static void __init of_unittest_bus_ranges(void)
{
struct device_node *np;
@@ -1970,7 +2008,7 @@ static const struct of_device_id unittest_match[] = {
static struct platform_driver unittest_driver = {
.probe = unittest_probe,
- .remove_new = unittest_remove,
+ .remove = unittest_remove,
.driver = {
.name = "unittest",
.of_match_table = unittest_match,
@@ -2071,7 +2109,7 @@ static const struct of_device_id unittest_gpio_id[] = {
static struct platform_driver unittest_gpio_driver = {
.probe = unittest_gpio_probe,
- .remove_new = unittest_gpio_remove,
+ .remove = unittest_gpio_remove,
.driver = {
.name = "unittest-gpio",
.of_match_table = unittest_gpio_id,
@@ -2891,7 +2929,7 @@ static const struct of_device_id unittest_i2c_bus_match[] = {
static struct platform_driver unittest_i2c_bus_driver = {
.probe = unittest_i2c_bus_probe,
- .remove_new = unittest_i2c_bus_remove,
+ .remove = unittest_i2c_bus_remove,
.driver = {
.name = "unittest-i2c-bus",
.of_match_table = unittest_i2c_bus_match,
@@ -4272,6 +4310,7 @@ static int __init of_unittest(void)
of_unittest_dma_get_max_cpu_address();
of_unittest_parse_dma_ranges();
of_unittest_pci_dma_ranges();
+ of_unittest_pci_empty_dma_ranges();
of_unittest_bus_ranges();
of_unittest_bus_3cell_ranges();
of_unittest_reg();
diff --git a/drivers/parisc/led.c b/drivers/parisc/led.c
index b49cb010a4d8..e71674753711 100644
--- a/drivers/parisc/led.c
+++ b/drivers/parisc/led.c
@@ -369,7 +369,7 @@ MODULE_ALIAS("platform:platform-leds");
static struct platform_driver hppa_mainboard_led_driver = {
.probe = platform_led_probe,
- .remove_new = platform_led_remove,
+ .remove = platform_led_remove,
.driver = {
.name = "platform-leds",
},
diff --git a/drivers/parport/parport_amiga.c b/drivers/parport/parport_amiga.c
index e06c7b2aac5c..6a819bd00866 100644
--- a/drivers/parport/parport_amiga.c
+++ b/drivers/parport/parport_amiga.c
@@ -236,7 +236,7 @@ static void __exit amiga_parallel_remove(struct platform_device *pdev)
* triggering a section mismatch warning.
*/
static struct platform_driver amiga_parallel_driver __refdata = {
- .remove_new = __exit_p(amiga_parallel_remove),
+ .remove = __exit_p(amiga_parallel_remove),
.driver = {
.name = "amiga-parallel",
},
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c
index 949236a7a27c..d6495f2f90a7 100644
--- a/drivers/parport/parport_sunbpp.c
+++ b/drivers/parport/parport_sunbpp.c
@@ -368,7 +368,7 @@ static struct platform_driver bpp_sbus_driver = {
.of_match_table = bpp_match,
},
.probe = bpp_probe,
- .remove_new = bpp_remove,
+ .remove = bpp_remove,
};
module_platform_driver(bpp_sbus_driver);
diff --git a/drivers/pci/msi/irqdomain.c b/drivers/pci/msi/irqdomain.c
index 569125726b3e..d7ba8795d60f 100644
--- a/drivers/pci/msi/irqdomain.c
+++ b/drivers/pci/msi/irqdomain.c
@@ -350,8 +350,11 @@ bool pci_msi_domain_supports(struct pci_dev *pdev, unsigned int feature_mask,
domain = dev_get_msi_domain(&pdev->dev);
- if (!domain || !irq_domain_is_hierarchy(domain))
- return mode == ALLOW_LEGACY;
+ if (!domain || !irq_domain_is_hierarchy(domain)) {
+ if (IS_ENABLED(CONFIG_PCI_MSI_ARCH_FALLBACKS))
+ return mode == ALLOW_LEGACY;
+ return false;
+ }
if (!irq_domain_is_msi_parent(domain)) {
/*
diff --git a/drivers/pci/msi/msi.c b/drivers/pci/msi/msi.c
index 3a45879d85db..2f647cac4cae 100644
--- a/drivers/pci/msi/msi.c
+++ b/drivers/pci/msi/msi.c
@@ -433,6 +433,10 @@ int __pci_enable_msi_range(struct pci_dev *dev, int minvec, int maxvec,
if (WARN_ON_ONCE(dev->msi_enabled))
return -EINVAL;
+ /* Test for the availability of MSI support */
+ if (!pci_msi_domain_supports(dev, 0, ALLOW_LEGACY))
+ return -ENOTSUPP;
+
nvec = pci_msi_vec_count(dev);
if (nvec < 0)
return nvec;
diff --git a/drivers/pci/p2pdma.c b/drivers/pci/p2pdma.c
index 4f47a13cb500..7abd4f546d3c 100644
--- a/drivers/pci/p2pdma.c
+++ b/drivers/pci/p2pdma.c
@@ -90,7 +90,7 @@ static ssize_t published_show(struct device *dev, struct device_attribute *attr,
static DEVICE_ATTR_RO(published);
static int p2pmem_alloc_mmap(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, struct vm_area_struct *vma)
+ const struct bin_attribute *attr, struct vm_area_struct *vma)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
size_t len = vma->vm_end - vma->vm_start;
diff --git a/drivers/pci/pci-sysfs.c b/drivers/pci/pci-sysfs.c
index 3e5a117f5b5d..7679d75d71e5 100644
--- a/drivers/pci/pci-sysfs.c
+++ b/drivers/pci/pci-sysfs.c
@@ -844,21 +844,20 @@ static struct bin_attribute *pci_dev_config_attrs[] = {
NULL,
};
-static umode_t pci_dev_config_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+static size_t pci_dev_config_attr_bin_size(struct kobject *kobj,
+ const struct bin_attribute *a,
+ int n)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
- a->size = PCI_CFG_SPACE_SIZE;
if (pdev->cfg_size > PCI_CFG_SPACE_SIZE)
- a->size = PCI_CFG_SPACE_EXP_SIZE;
-
- return a->attr.mode;
+ return PCI_CFG_SPACE_EXP_SIZE;
+ return PCI_CFG_SPACE_SIZE;
}
static const struct attribute_group pci_dev_config_attr_group = {
.bin_attrs = pci_dev_config_attrs,
- .is_bin_visible = pci_dev_config_attr_is_visible,
+ .bin_size = pci_dev_config_attr_bin_size,
};
/*
@@ -868,7 +867,7 @@ static const struct attribute_group pci_dev_config_attr_group = {
static __maybe_unused loff_t
pci_llseek_resource(struct file *filep,
struct kobject *kobj __always_unused,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
loff_t offset, int whence)
{
return fixed_size_llseek(filep, offset, whence, attr->size);
@@ -937,7 +936,7 @@ static ssize_t pci_write_legacy_io(struct file *filp, struct kobject *kobj,
* memory space.
*/
static int pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
@@ -957,7 +956,7 @@ static int pci_mmap_legacy_mem(struct file *filp, struct kobject *kobj,
* memory space. Returns -ENOSYS if the operation isn't supported
*/
static int pci_mmap_legacy_io(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct pci_bus *bus = to_pci_bus(kobj_to_dev(kobj));
@@ -1061,7 +1060,7 @@ void pci_remove_legacy_files(struct pci_bus *b)
*
* Use the regular PCI mapping routines to map a PCI resource into userspace.
*/
-static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
+static int pci_mmap_resource(struct kobject *kobj, const struct bin_attribute *attr,
struct vm_area_struct *vma, int write_combine)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
@@ -1086,14 +1085,14 @@ static int pci_mmap_resource(struct kobject *kobj, struct bin_attribute *attr,
}
static int pci_mmap_resource_uc(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
return pci_mmap_resource(kobj, attr, vma, 0);
}
static int pci_mmap_resource_wc(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
return pci_mmap_resource(kobj, attr, vma, 1);
@@ -1353,24 +1352,29 @@ static struct bin_attribute *pci_dev_rom_attrs[] = {
};
static umode_t pci_dev_rom_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+ const struct bin_attribute *a, int n)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
- size_t rom_size;
/* If the device has a ROM, try to expose it in sysfs. */
- rom_size = pci_resource_len(pdev, PCI_ROM_RESOURCE);
- if (!rom_size)
+ if (!pci_resource_end(pdev, PCI_ROM_RESOURCE))
return 0;
- a->size = rom_size;
-
return a->attr.mode;
}
+static size_t pci_dev_rom_attr_bin_size(struct kobject *kobj,
+ const struct bin_attribute *a, int n)
+{
+ struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
+
+ return pci_resource_len(pdev, PCI_ROM_RESOURCE);
+}
+
static const struct attribute_group pci_dev_rom_attr_group = {
.bin_attrs = pci_dev_rom_attrs,
.is_bin_visible = pci_dev_rom_attr_is_visible,
+ .bin_size = pci_dev_rom_attr_bin_size,
};
static ssize_t reset_store(struct device *dev, struct device_attribute *attr,
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 0b29ec6e8e5e..661f98c6c63a 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -6232,12 +6232,14 @@ u8 pcie_get_supported_speeds(struct pci_dev *dev)
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP2, &lnkcap2);
speeds = lnkcap2 & PCI_EXP_LNKCAP2_SLS;
+ /* Ignore speeds higher than Max Link Speed */
+ pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
+ speeds &= GENMASK(lnkcap & PCI_EXP_LNKCAP_SLS, 0);
+
/* PCIe r3.0-compliant */
if (speeds)
return speeds;
- pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &lnkcap);
-
/* Synthesize from the Max Link Speed field */
if ((lnkcap & PCI_EXP_LNKCAP_SLS) == PCI_EXP_LNKCAP_SLS_5_0GB)
speeds = PCI_EXP_LNKCAP2_SLS_5_0GB | PCI_EXP_LNKCAP2_SLS_2_5GB;
diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
index 80c5ba8d8296..34ce9f834d0c 100644
--- a/drivers/pci/pcie/aer.c
+++ b/drivers/pci/pcie/aer.c
@@ -231,7 +231,7 @@ int pcie_aer_is_native(struct pci_dev *dev)
return pcie_ports_native || host->native_aer;
}
-EXPORT_SYMBOL_NS_GPL(pcie_aer_is_native, CXL);
+EXPORT_SYMBOL_NS_GPL(pcie_aer_is_native, "CXL");
static int pci_enable_pcie_error_reporting(struct pci_dev *dev)
{
@@ -802,7 +802,7 @@ void pci_print_aer(struct pci_dev *dev, int aer_severity,
trace_aer_event(dev_name(&dev->dev), (status & ~mask),
aer_severity, tlp_header_valid, &aer->header_log);
}
-EXPORT_SYMBOL_NS_GPL(pci_print_aer, CXL);
+EXPORT_SYMBOL_NS_GPL(pci_print_aer, "CXL");
/**
* add_error_device - list device to be handled
diff --git a/drivers/pci/pcie/portdrv.c b/drivers/pci/pcie/portdrv.c
index 5e10306b6308..02e73099bad0 100644
--- a/drivers/pci/pcie/portdrv.c
+++ b/drivers/pci/pcie/portdrv.c
@@ -265,12 +265,14 @@ static int get_port_device_capability(struct pci_dev *dev)
(pcie_ports_dpc_native || (services & PCIE_PORT_SERVICE_AER)))
services |= PCIE_PORT_SERVICE_DPC;
+ /* Enable bandwidth control if more than one speed is supported. */
if (pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM ||
pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT) {
u32 linkcap;
pcie_capability_read_dword(dev, PCI_EXP_LNKCAP, &linkcap);
- if (linkcap & PCI_EXP_LNKCAP_LBNC)
+ if (linkcap & PCI_EXP_LNKCAP_LBNC &&
+ hweight8(dev->supported_speeds) > 1)
services |= PCIE_PORT_SERVICE_BWCTRL;
}
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 963b8d2855c1..efc37fcb73e2 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -19,14 +19,19 @@ static void pci_free_resources(struct pci_dev *dev)
static void pci_pwrctrl_unregister(struct device *dev)
{
+ struct device_node *np;
struct platform_device *pdev;
- pdev = of_find_device_by_node(dev_of_node(dev));
+ np = dev_of_node(dev);
+ if (!np)
+ return;
+
+ pdev = of_find_device_by_node(np);
if (!pdev)
return;
of_device_unregister(pdev);
- of_node_clear_flag(dev_of_node(dev), OF_POPULATED);
+ of_node_clear_flag(np, OF_POPULATED);
}
static void pci_stop_dev(struct pci_dev *dev)
diff --git a/drivers/pci/vpd.c b/drivers/pci/vpd.c
index e4300f5f304f..a469bcbc0da7 100644
--- a/drivers/pci/vpd.c
+++ b/drivers/pci/vpd.c
@@ -325,7 +325,7 @@ static struct bin_attribute *vpd_attrs[] = {
};
static umode_t vpd_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+ const struct bin_attribute *a, int n)
{
struct pci_dev *pdev = to_pci_dev(kobj_to_dev(kobj));
diff --git a/drivers/pcmcia/bcm63xx_pcmcia.c b/drivers/pcmcia/bcm63xx_pcmcia.c
index 5bda3e6d43d8..85874b7a9f36 100644
--- a/drivers/pcmcia/bcm63xx_pcmcia.c
+++ b/drivers/pcmcia/bcm63xx_pcmcia.c
@@ -453,7 +453,7 @@ static void bcm63xx_drv_pcmcia_remove(struct platform_device *pdev)
struct platform_driver bcm63xx_pcmcia_driver = {
.probe = bcm63xx_drv_pcmcia_probe,
- .remove_new = bcm63xx_drv_pcmcia_remove,
+ .remove = bcm63xx_drv_pcmcia_remove,
.driver = {
.name = "bcm63xx_pcmcia",
},
diff --git a/drivers/pcmcia/db1xxx_ss.c b/drivers/pcmcia/db1xxx_ss.c
index 509713b9a502..85d2616061dd 100644
--- a/drivers/pcmcia/db1xxx_ss.c
+++ b/drivers/pcmcia/db1xxx_ss.c
@@ -592,7 +592,7 @@ static struct platform_driver db1x_pcmcia_socket_driver = {
.name = "db1xxx_pcmcia",
},
.probe = db1x_pcmcia_socket_probe,
- .remove_new = db1x_pcmcia_socket_remove,
+ .remove = db1x_pcmcia_socket_remove,
};
module_platform_driver(db1x_pcmcia_socket_driver);
diff --git a/drivers/pcmcia/electra_cf.c b/drivers/pcmcia/electra_cf.c
index 5ae826e54811..3bdd939dd2f4 100644
--- a/drivers/pcmcia/electra_cf.c
+++ b/drivers/pcmcia/electra_cf.c
@@ -342,7 +342,7 @@ static struct platform_driver electra_cf_driver = {
.of_match_table = electra_cf_match,
},
.probe = electra_cf_probe,
- .remove_new = electra_cf_remove,
+ .remove = electra_cf_remove,
};
module_platform_driver(electra_cf_driver);
diff --git a/drivers/pcmcia/omap_cf.c b/drivers/pcmcia/omap_cf.c
index 80137c7afe0d..f0ccf479f36e 100644
--- a/drivers/pcmcia/omap_cf.c
+++ b/drivers/pcmcia/omap_cf.c
@@ -306,7 +306,7 @@ static struct platform_driver omap_cf_driver = {
.driver = {
.name = driver_name,
},
- .remove_new = __exit_p(omap_cf_remove),
+ .remove = __exit_p(omap_cf_remove),
};
static int __init omap_cf_init(void)
diff --git a/drivers/pcmcia/pxa2xx_base.c b/drivers/pcmcia/pxa2xx_base.c
index 457fb81b497a..370a8e16dc81 100644
--- a/drivers/pcmcia/pxa2xx_base.c
+++ b/drivers/pcmcia/pxa2xx_base.c
@@ -336,7 +336,7 @@ static const struct dev_pm_ops pxa2xx_drv_pcmcia_pm_ops = {
static struct platform_driver pxa2xx_pcmcia_driver = {
.probe = pxa2xx_drv_pcmcia_probe,
- .remove_new = pxa2xx_drv_pcmcia_remove,
+ .remove = pxa2xx_drv_pcmcia_remove,
.driver = {
.name = "pxa2xx-pcmcia",
.pm = &pxa2xx_drv_pcmcia_pm_ops,
diff --git a/drivers/pcmcia/sa1100_generic.c b/drivers/pcmcia/sa1100_generic.c
index ccb219c38761..7b5ac8fe811d 100644
--- a/drivers/pcmcia/sa1100_generic.c
+++ b/drivers/pcmcia/sa1100_generic.c
@@ -177,7 +177,7 @@ static struct platform_driver sa11x0_pcmcia_driver = {
.name = "sa11x0-pcmcia",
},
.probe = sa11x0_drv_pcmcia_probe,
- .remove_new = sa11x0_drv_pcmcia_remove,
+ .remove = sa11x0_drv_pcmcia_remove,
};
/* sa11x0_pcmcia_init()
diff --git a/drivers/pcmcia/xxs1500_ss.c b/drivers/pcmcia/xxs1500_ss.c
index 2a93fbbd128d..f84dd5914a6b 100644
--- a/drivers/pcmcia/xxs1500_ss.c
+++ b/drivers/pcmcia/xxs1500_ss.c
@@ -316,7 +316,7 @@ static struct platform_driver xxs1500_pcmcia_socket_driver = {
.name = "xxs1500_pcmcia",
},
.probe = xxs1500_pcmcia_probe,
- .remove_new = xxs1500_pcmcia_remove,
+ .remove = xxs1500_pcmcia_remove,
};
module_platform_driver(xxs1500_pcmcia_socket_driver);
diff --git a/drivers/peci/controller/peci-aspeed.c b/drivers/peci/controller/peci-aspeed.c
index b93eb6f43b98..ad3a7d71ed4c 100644
--- a/drivers/peci/controller/peci-aspeed.c
+++ b/drivers/peci/controller/peci-aspeed.c
@@ -597,4 +597,4 @@ MODULE_AUTHOR("Ryan Chen <ryan_chen@aspeedtech.com>");
MODULE_AUTHOR("Jae Hyun Yoo <jae.hyun.yoo@linux.intel.com>");
MODULE_DESCRIPTION("ASPEED PECI driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PECI);
+MODULE_IMPORT_NS("PECI");
diff --git a/drivers/peci/controller/peci-npcm.c b/drivers/peci/controller/peci-npcm.c
index ec613d35c796..c77591ca583d 100644
--- a/drivers/peci/controller/peci-npcm.c
+++ b/drivers/peci/controller/peci-npcm.c
@@ -224,7 +224,7 @@ static const struct regmap_config npcm_peci_regmap_config = {
.fast_io = true,
};
-static struct peci_controller_ops npcm_ops = {
+static const struct peci_controller_ops npcm_ops = {
.xfer = npcm_peci_xfer,
};
@@ -295,4 +295,4 @@ module_platform_driver(npcm_peci_driver);
MODULE_AUTHOR("Tomer Maimon <tomer.maimon@nuvoton.com>");
MODULE_DESCRIPTION("NPCM PECI driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PECI);
+MODULE_IMPORT_NS("PECI");
diff --git a/drivers/peci/core.c b/drivers/peci/core.c
index 25e46579dd9c..936c1fadefe5 100644
--- a/drivers/peci/core.c
+++ b/drivers/peci/core.c
@@ -158,7 +158,7 @@ err_put:
return ERR_PTR(ret);
}
-EXPORT_SYMBOL_NS_GPL(devm_peci_controller_add, PECI);
+EXPORT_SYMBOL_NS_GPL(devm_peci_controller_add, "PECI");
static const struct peci_device_id *
peci_bus_match_device_id(const struct peci_device_id *id, struct peci_device *device)
diff --git a/drivers/peci/cpu.c b/drivers/peci/cpu.c
index 152bbd8e717a..2dac8ba82787 100644
--- a/drivers/peci/cpu.c
+++ b/drivers/peci/cpu.c
@@ -32,7 +32,7 @@ int peci_temp_read(struct peci_device *device, s16 *temp_raw)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(peci_temp_read, PECI_CPU);
+EXPORT_SYMBOL_NS_GPL(peci_temp_read, "PECI_CPU");
/**
* peci_pcs_read() - read PCS register
@@ -64,7 +64,7 @@ out_req_free:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(peci_pcs_read, PECI_CPU);
+EXPORT_SYMBOL_NS_GPL(peci_pcs_read, "PECI_CPU");
/**
* peci_pci_local_read() - read 32-bit memory location using raw address
@@ -99,7 +99,7 @@ out_req_free:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(peci_pci_local_read, PECI_CPU);
+EXPORT_SYMBOL_NS_GPL(peci_pci_local_read, "PECI_CPU");
/**
* peci_ep_pci_local_read() - read 32-bit memory location using raw address
@@ -135,7 +135,7 @@ out_req_free:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(peci_ep_pci_local_read, PECI_CPU);
+EXPORT_SYMBOL_NS_GPL(peci_ep_pci_local_read, "PECI_CPU");
/**
* peci_mmio_read() - read 32-bit memory location using 64-bit bar offset address
@@ -172,7 +172,7 @@ out_req_free:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(peci_mmio_read, PECI_CPU);
+EXPORT_SYMBOL_NS_GPL(peci_mmio_read, "PECI_CPU");
static const char * const peci_adev_types[] = {
"cputemp",
@@ -337,4 +337,4 @@ module_peci_driver(peci_cpu_driver);
MODULE_AUTHOR("Iwona Winiarska <iwona.winiarska@intel.com>");
MODULE_DESCRIPTION("PECI CPU driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(PECI);
+MODULE_IMPORT_NS("PECI");
diff --git a/drivers/peci/device.c b/drivers/peci/device.c
index 37ca7dd61807..416635029f55 100644
--- a/drivers/peci/device.c
+++ b/drivers/peci/device.c
@@ -230,13 +230,13 @@ int __peci_driver_register(struct peci_driver *driver, struct module *owner,
return driver_register(&driver->driver);
}
-EXPORT_SYMBOL_NS_GPL(__peci_driver_register, PECI);
+EXPORT_SYMBOL_NS_GPL(__peci_driver_register, "PECI");
void peci_driver_unregister(struct peci_driver *driver)
{
driver_unregister(&driver->driver);
}
-EXPORT_SYMBOL_NS_GPL(peci_driver_unregister, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_driver_unregister, "PECI");
static void peci_device_release(struct device *dev)
{
diff --git a/drivers/peci/request.c b/drivers/peci/request.c
index 87eefe66743f..e6327af45fc7 100644
--- a/drivers/peci/request.c
+++ b/drivers/peci/request.c
@@ -128,7 +128,7 @@ int peci_request_status(struct peci_request *req)
return -EIO;
}
-EXPORT_SYMBOL_NS_GPL(peci_request_status, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_request_status, "PECI");
static int peci_request_xfer(struct peci_request *req)
{
@@ -213,7 +213,7 @@ struct peci_request *peci_request_alloc(struct peci_device *device, u8 tx_len, u
return req;
}
-EXPORT_SYMBOL_NS_GPL(peci_request_alloc, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_request_alloc, "PECI");
/**
* peci_request_free() - free peci_request
@@ -223,7 +223,7 @@ void peci_request_free(struct peci_request *req)
{
kfree(req);
}
-EXPORT_SYMBOL_NS_GPL(peci_request_free, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_request_free, "PECI");
struct peci_request *peci_xfer_get_dib(struct peci_device *device)
{
@@ -244,7 +244,7 @@ struct peci_request *peci_xfer_get_dib(struct peci_device *device)
return req;
}
-EXPORT_SYMBOL_NS_GPL(peci_xfer_get_dib, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_xfer_get_dib, "PECI");
struct peci_request *peci_xfer_get_temp(struct peci_device *device)
{
@@ -265,7 +265,7 @@ struct peci_request *peci_xfer_get_temp(struct peci_device *device)
return req;
}
-EXPORT_SYMBOL_NS_GPL(peci_xfer_get_temp, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_xfer_get_temp, "PECI");
static struct peci_request *
__pkg_cfg_read(struct peci_device *device, u8 index, u16 param, u8 len)
@@ -397,44 +397,44 @@ u8 peci_request_data_readb(struct peci_request *req)
{
return req->rx.buf[1];
}
-EXPORT_SYMBOL_NS_GPL(peci_request_data_readb, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_request_data_readb, "PECI");
u16 peci_request_data_readw(struct peci_request *req)
{
return get_unaligned_le16(&req->rx.buf[1]);
}
-EXPORT_SYMBOL_NS_GPL(peci_request_data_readw, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_request_data_readw, "PECI");
u32 peci_request_data_readl(struct peci_request *req)
{
return get_unaligned_le32(&req->rx.buf[1]);
}
-EXPORT_SYMBOL_NS_GPL(peci_request_data_readl, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_request_data_readl, "PECI");
u64 peci_request_data_readq(struct peci_request *req)
{
return get_unaligned_le64(&req->rx.buf[1]);
}
-EXPORT_SYMBOL_NS_GPL(peci_request_data_readq, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_request_data_readq, "PECI");
u64 peci_request_dib_read(struct peci_request *req)
{
return get_unaligned_le64(&req->rx.buf[0]);
}
-EXPORT_SYMBOL_NS_GPL(peci_request_dib_read, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_request_dib_read, "PECI");
s16 peci_request_temp_read(struct peci_request *req)
{
return get_unaligned_le16(&req->rx.buf[0]);
}
-EXPORT_SYMBOL_NS_GPL(peci_request_temp_read, PECI);
+EXPORT_SYMBOL_NS_GPL(peci_request_temp_read, "PECI");
#define __read_pkg_config(x, type) \
struct peci_request *peci_xfer_pkg_cfg_##x(struct peci_device *device, u8 index, u16 param) \
{ \
return __pkg_cfg_read(device, index, param, sizeof(type)); \
} \
-EXPORT_SYMBOL_NS_GPL(peci_xfer_pkg_cfg_##x, PECI)
+EXPORT_SYMBOL_NS_GPL(peci_xfer_pkg_cfg_##x, "PECI")
__read_pkg_config(readb, u8);
__read_pkg_config(readw, u16);
@@ -447,7 +447,7 @@ peci_xfer_pci_cfg_local_##x(struct peci_device *device, u8 bus, u8 dev, u8 func,
{ \
return __pci_cfg_local_read(device, bus, dev, func, reg, sizeof(type)); \
} \
-EXPORT_SYMBOL_NS_GPL(peci_xfer_pci_cfg_local_##x, PECI)
+EXPORT_SYMBOL_NS_GPL(peci_xfer_pci_cfg_local_##x, "PECI")
__read_pci_config_local(readb, u8);
__read_pci_config_local(readw, u16);
@@ -459,7 +459,7 @@ peci_xfer_ep_pci_cfg_##x(struct peci_device *device, u8 seg, u8 bus, u8 dev, u8
{ \
return __ep_pci_cfg_read(device, msg_type, seg, bus, dev, func, reg, sizeof(type)); \
} \
-EXPORT_SYMBOL_NS_GPL(peci_xfer_ep_pci_cfg_##x, PECI)
+EXPORT_SYMBOL_NS_GPL(peci_xfer_ep_pci_cfg_##x, "PECI")
__read_ep_pci_config(local_readb, PECI_ENDPTCFG_TYPE_LOCAL_PCI, u8);
__read_ep_pci_config(local_readw, PECI_ENDPTCFG_TYPE_LOCAL_PCI, u16);
@@ -476,7 +476,7 @@ struct peci_request *peci_xfer_ep_mmio##y##_##x(struct peci_device *device, u8 b
offset, PECI_RDENDPTCFG_MMIO_WR_LEN_BASE + sizeof(type1), \
sizeof(type2)); \
} \
-EXPORT_SYMBOL_NS_GPL(peci_xfer_ep_mmio##y##_##x, PECI)
+EXPORT_SYMBOL_NS_GPL(peci_xfer_ep_mmio##y##_##x, "PECI")
__read_ep_mmio(readl, 32, PECI_ENDPTCFG_ADDR_TYPE_MMIO_D, u32, u32);
__read_ep_mmio(readl, 64, PECI_ENDPTCFG_ADDR_TYPE_MMIO_Q, u64, u32);
diff --git a/drivers/perf/arm-cmn.c b/drivers/perf/arm-cmn.c
index 49bd811c6fd6..b20fa600e510 100644
--- a/drivers/perf/arm-cmn.c
+++ b/drivers/perf/arm-cmn.c
@@ -2178,8 +2178,6 @@ static int arm_cmn_init_dtcs(struct arm_cmn *cmn)
continue;
xp = arm_cmn_node_to_xp(cmn, dn);
- dn->portid_bits = xp->portid_bits;
- dn->deviceid_bits = xp->deviceid_bits;
dn->dtc = xp->dtc;
dn->dtm = xp->dtm;
if (cmn->multi_dtm)
@@ -2420,6 +2418,8 @@ static int arm_cmn_discover(struct arm_cmn *cmn, unsigned int rgn_offset)
}
arm_cmn_init_node_info(cmn, reg & CMN_CHILD_NODE_ADDR, dn);
+ dn->portid_bits = xp->portid_bits;
+ dn->deviceid_bits = xp->deviceid_bits;
switch (dn->type) {
case CMN_TYPE_DTC:
diff --git a/drivers/perf/arm-ni.c b/drivers/perf/arm-ni.c
index 90fcfe693439..fd7a5e60e963 100644
--- a/drivers/perf/arm-ni.c
+++ b/drivers/perf/arm-ni.c
@@ -247,7 +247,6 @@ static struct attribute *arm_ni_other_attrs[] = {
static const struct attribute_group arm_ni_other_attr_group = {
.attrs = arm_ni_other_attrs,
- NULL
};
static const struct attribute_group *arm_ni_attr_groups[] = {
diff --git a/drivers/perf/arm_smmuv3_pmu.c b/drivers/perf/arm_smmuv3_pmu.c
index b1510f660c7a..621f02a7f43b 100644
--- a/drivers/perf/arm_smmuv3_pmu.c
+++ b/drivers/perf/arm_smmuv3_pmu.c
@@ -431,6 +431,17 @@ static int smmu_pmu_event_init(struct perf_event *event)
return -EINVAL;
}
+ /*
+ * Ensure all events are on the same cpu so all events are in the
+ * same cpu context, to avoid races on pmu_enable etc.
+ */
+ event->cpu = smmu_pmu->on_cpu;
+
+ hwc->idx = -1;
+
+ if (event->group_leader == event)
+ return 0;
+
for_each_sibling_event(sibling, event->group_leader) {
if (is_software_event(sibling))
continue;
@@ -442,14 +453,6 @@ static int smmu_pmu_event_init(struct perf_event *event)
return -EINVAL;
}
- hwc->idx = -1;
-
- /*
- * Ensure all events are on the same cpu so all events are in the
- * same cpu context, to avoid races on pmu_enable etc.
- */
- event->cpu = smmu_pmu->on_cpu;
-
return 0;
}
diff --git a/drivers/perf/cxl_pmu.c b/drivers/perf/cxl_pmu.c
index bee4b5b52ec6..d6693519eaee 100644
--- a/drivers/perf/cxl_pmu.c
+++ b/drivers/perf/cxl_pmu.c
@@ -977,7 +977,7 @@ static __exit void cxl_pmu_exit(void)
MODULE_DESCRIPTION("CXL Performance Monitor Driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("CXL");
module_init(cxl_pmu_init);
module_exit(cxl_pmu_exit);
MODULE_ALIAS_CXL(CXL_DEVICE_PMU);
diff --git a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
index 950b7ae1d1a8..dc452610934a 100644
--- a/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
+++ b/drivers/phy/broadcom/phy-brcm-usb-init-synopsys.c
@@ -325,6 +325,12 @@ static void usb_init_common_7216(struct brcm_usb_init_params *params)
void __iomem *ctrl = params->regs[BRCM_REGS_CTRL];
USB_CTRL_UNSET(ctrl, USB_PM, XHC_S2_CLK_SWITCH_EN);
+
+ /*
+ * The PHY might be in a bad state if it is already powered
+ * up. Toggle the power just in case.
+ */
+ USB_CTRL_SET(ctrl, USB_PM, USB_PWRDN);
USB_CTRL_UNSET(ctrl, USB_PM, USB_PWRDN);
/* 1 millisecond - for USB clocks to settle down */
diff --git a/drivers/phy/freescale/phy-fsl-samsung-hdmi.c b/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
index 2c8038864357..d3ccf547ba1c 100644
--- a/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
+++ b/drivers/phy/freescale/phy-fsl-samsung-hdmi.c
@@ -424,8 +424,7 @@ static unsigned long fsl_samsung_hdmi_phy_find_pms(unsigned long fout, u8 *p, u1
* Fvco = (M * f_ref) / P,
* where f_ref is 24MHz.
*/
- tmp = (u64)_m * 24 * MHZ;
- do_div(tmp, _p);
+ tmp = div64_ul((u64)_m * 24 * MHZ, _p);
if (tmp < 750 * MHZ ||
tmp > 3000 * MHZ)
continue;
diff --git a/drivers/phy/mediatek/Kconfig b/drivers/phy/mediatek/Kconfig
index 60e00057e8bc..ba6461350951 100644
--- a/drivers/phy/mediatek/Kconfig
+++ b/drivers/phy/mediatek/Kconfig
@@ -65,6 +65,7 @@ config PHY_MTK_HDMI
depends on ARCH_MEDIATEK || COMPILE_TEST
depends on COMMON_CLK
depends on OF
+ depends on REGULATOR
select GENERIC_PHY
help
Support HDMI PHY for Mediatek SoCs.
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index f053b525ccff..413f76e2d174 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -145,8 +145,10 @@ static struct phy_provider *of_phy_provider_lookup(struct device_node *node)
return phy_provider;
for_each_child_of_node(phy_provider->children, child)
- if (child == node)
+ if (child == node) {
+ of_node_put(child);
return phy_provider;
+ }
}
return ERR_PTR(-EPROBE_DEFER);
@@ -629,8 +631,10 @@ static struct phy *_of_phy_get(struct device_node *np, int index)
return ERR_PTR(-ENODEV);
/* This phy type handled by the usb-phy subsystem for now */
- if (of_device_is_compatible(args.np, "usb-nop-xceiv"))
- return ERR_PTR(-ENODEV);
+ if (of_device_is_compatible(args.np, "usb-nop-xceiv")) {
+ phy = ERR_PTR(-ENODEV);
+ goto out_put_node;
+ }
mutex_lock(&phy_provider_mutex);
phy_provider = of_phy_provider_lookup(args.np);
@@ -652,6 +656,7 @@ out_put_module:
out_unlock:
mutex_unlock(&phy_provider_mutex);
+out_put_node:
of_node_put(args.np);
return phy;
@@ -737,7 +742,7 @@ void devm_phy_put(struct device *dev, struct phy *phy)
if (!phy)
return;
- r = devres_destroy(dev, devm_phy_release, devm_phy_match, phy);
+ r = devres_release(dev, devm_phy_release, devm_phy_match, phy);
dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
}
EXPORT_SYMBOL_GPL(devm_phy_put);
@@ -1121,7 +1126,7 @@ void devm_phy_destroy(struct device *dev, struct phy *phy)
{
int r;
- r = devres_destroy(dev, devm_phy_consume, devm_phy_match, phy);
+ r = devres_release(dev, devm_phy_consume, devm_phy_match, phy);
dev_WARN_ONCE(dev, r, "couldn't find PHY resource\n");
}
EXPORT_SYMBOL_GPL(devm_phy_destroy);
@@ -1259,12 +1264,12 @@ EXPORT_SYMBOL_GPL(of_phy_provider_unregister);
* of_phy_provider_unregister to unregister the phy provider.
*/
void devm_of_phy_provider_unregister(struct device *dev,
- struct phy_provider *phy_provider)
+ struct phy_provider *phy_provider)
{
int r;
- r = devres_destroy(dev, devm_phy_provider_release, devm_phy_match,
- phy_provider);
+ r = devres_release(dev, devm_phy_provider_release, devm_phy_match,
+ phy_provider);
dev_WARN_ONCE(dev, r, "couldn't find PHY provider device resource\n");
}
EXPORT_SYMBOL_GPL(devm_of_phy_provider_unregister);
diff --git a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
index acd6075bf6d9..c9c337840715 100644
--- a/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
+++ b/drivers/phy/qualcomm/phy-qcom-qmp-usb.c
@@ -1052,7 +1052,7 @@ static const struct qmp_phy_init_tbl sc8280xp_usb3_uniphy_rx_tbl[] = {
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_FO_GAIN, 0x2f),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_LOW, 0xff),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FASTLOCK_COUNT_HIGH, 0x0f),
- QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_SO_GAIN, 0x0a),
+ QMP_PHY_INIT_CFG(QSERDES_V5_RX_UCDR_FO_GAIN, 0x0a),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL1, 0x54),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_VGA_CAL_CNTRL2, 0x0f),
QMP_PHY_INIT_CFG(QSERDES_V5_RX_RX_EQU_ADAPTOR_CNTRL2, 0x0f),
diff --git a/drivers/phy/realtek/phy-rtk-usb2.c b/drivers/phy/realtek/phy-rtk-usb2.c
index c3e131a64131..248550ef98ca 100644
--- a/drivers/phy/realtek/phy-rtk-usb2.c
+++ b/drivers/phy/realtek/phy-rtk-usb2.c
@@ -1023,6 +1023,8 @@ static int rtk_usb2phy_probe(struct platform_device *pdev)
rtk_phy->dev = &pdev->dev;
rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
+ if (!rtk_phy->phy_cfg)
+ return -ENOMEM;
memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
diff --git a/drivers/phy/realtek/phy-rtk-usb3.c b/drivers/phy/realtek/phy-rtk-usb3.c
index 0cef29a7ddd9..cce453686db2 100644
--- a/drivers/phy/realtek/phy-rtk-usb3.c
+++ b/drivers/phy/realtek/phy-rtk-usb3.c
@@ -577,6 +577,8 @@ static int rtk_usb3phy_probe(struct platform_device *pdev)
rtk_phy->dev = &pdev->dev;
rtk_phy->phy_cfg = devm_kzalloc(dev, sizeof(*phy_cfg), GFP_KERNEL);
+ if (!rtk_phy->phy_cfg)
+ return -ENOMEM;
memcpy(rtk_phy->phy_cfg, phy_cfg, sizeof(*phy_cfg));
diff --git a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
index 0a9989e41237..2eb3329ca23f 100644
--- a/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
+++ b/drivers/phy/rockchip/phy-rockchip-naneng-combphy.c
@@ -309,7 +309,7 @@ static int rockchip_combphy_parse_dt(struct device *dev, struct rockchip_combphy
priv->ext_refclk = device_property_present(dev, "rockchip,ext-refclk");
- priv->phy_rst = devm_reset_control_array_get_exclusive(dev);
+ priv->phy_rst = devm_reset_control_get(dev, "phy");
if (IS_ERR(priv->phy_rst))
return dev_err_probe(dev, PTR_ERR(priv->phy_rst), "failed to get phy reset\n");
diff --git a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
index ceab9c71d3b5..0965b9d4f9cf 100644
--- a/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
+++ b/drivers/phy/rockchip/phy-rockchip-samsung-hdptx.c
@@ -1101,6 +1101,8 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(hdptx->grf),
"Could not get GRF syscon\n");
+ platform_set_drvdata(pdev, hdptx);
+
ret = devm_pm_runtime_enable(dev);
if (ret)
return dev_err_probe(dev, ret, "Failed to enable runtime PM\n");
@@ -1110,7 +1112,6 @@ static int rk_hdptx_phy_probe(struct platform_device *pdev)
return dev_err_probe(dev, PTR_ERR(hdptx->phy),
"Failed to create HDMI PHY\n");
- platform_set_drvdata(pdev, hdptx);
phy_set_drvdata(hdptx->phy, hdptx);
phy_set_bus_width(hdptx->phy, 8);
diff --git a/drivers/phy/st/phy-stm32-combophy.c b/drivers/phy/st/phy-stm32-combophy.c
index 765bb34fe358..49e9fa90a681 100644
--- a/drivers/phy/st/phy-stm32-combophy.c
+++ b/drivers/phy/st/phy-stm32-combophy.c
@@ -122,6 +122,7 @@ static int stm32_impedance_tune(struct stm32_combophy *combophy)
u32 max_vswing = imp_lookup[imp_size - 1].vswing[vswing_size - 1];
u32 min_vswing = imp_lookup[0].vswing[0];
u32 val;
+ u32 regval;
if (!of_property_read_u32(combophy->dev->of_node, "st,output-micro-ohms", &val)) {
if (val < min_imp || val > max_imp) {
@@ -129,16 +130,20 @@ static int stm32_impedance_tune(struct stm32_combophy *combophy)
return -EINVAL;
}
- for (imp_of = 0; imp_of < ARRAY_SIZE(imp_lookup); imp_of++)
- if (imp_lookup[imp_of].microohm <= val)
+ regval = 0;
+ for (imp_of = 0; imp_of < ARRAY_SIZE(imp_lookup); imp_of++) {
+ if (imp_lookup[imp_of].microohm <= val) {
+ regval = FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_OHM, imp_of);
break;
+ }
+ }
dev_dbg(combophy->dev, "Set %u micro-ohms output impedance\n",
imp_lookup[imp_of].microohm);
regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
STM32MP25_PCIEPRG_IMPCTRL_OHM,
- FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_OHM, imp_of));
+ regval);
} else {
regmap_read(combophy->regmap, SYSCFG_PCIEPRGCR, &val);
imp_of = FIELD_GET(STM32MP25_PCIEPRG_IMPCTRL_OHM, val);
@@ -150,16 +155,20 @@ static int stm32_impedance_tune(struct stm32_combophy *combophy)
return -EINVAL;
}
- for (vswing_of = 0; vswing_of < ARRAY_SIZE(imp_lookup[imp_of].vswing); vswing_of++)
- if (imp_lookup[imp_of].vswing[vswing_of] >= val)
+ regval = 0;
+ for (vswing_of = 0; vswing_of < ARRAY_SIZE(imp_lookup[imp_of].vswing); vswing_of++) {
+ if (imp_lookup[imp_of].vswing[vswing_of] >= val) {
+ regval = FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_VSWING, vswing_of);
break;
+ }
+ }
dev_dbg(combophy->dev, "Set %u microvolt swing\n",
imp_lookup[imp_of].vswing[vswing_of]);
regmap_update_bits(combophy->regmap, SYSCFG_PCIEPRGCR,
STM32MP25_PCIEPRG_IMPCTRL_VSWING,
- FIELD_PREP(STM32MP25_PCIEPRG_IMPCTRL_VSWING, vswing_of));
+ regval);
}
return 0;
diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c
index f9b862c1c438..79d4814d758d 100644
--- a/drivers/phy/tegra/xusb.c
+++ b/drivers/phy/tegra/xusb.c
@@ -543,7 +543,7 @@ static int tegra_xusb_port_init(struct tegra_xusb_port *port,
device_initialize(&port->dev);
port->dev.type = &tegra_xusb_port_type;
- port->dev.of_node = of_node_get(np);
+ device_set_node(&port->dev, of_fwnode_handle(of_node_get(np)));
port->dev.parent = padctl->dev;
err = dev_set_name(&port->dev, "%s-%u", name, index);
diff --git a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
index fd5ce52d05b1..c9a3d3aa8c10 100644
--- a/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
+++ b/drivers/pinctrl/bcm/pinctrl-iproc-gpio.c
@@ -309,7 +309,7 @@ static void iproc_gpio_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct iproc_gpio *chip = gpiochip_get_data(gc);
- seq_printf(p, dev_name(chip->dev));
+ seq_puts(p, dev_name(chip->dev));
}
static const struct irq_chip iproc_gpio_irq_chip = {
diff --git a/drivers/pinctrl/intel/pinctrl-alderlake.c b/drivers/pinctrl/intel/pinctrl-alderlake.c
index 7d9948e5f422..108eac205aa9 100644
--- a/drivers/pinctrl/intel/pinctrl-alderlake.c
+++ b/drivers/pinctrl/intel/pinctrl-alderlake.c
@@ -747,4 +747,4 @@ module_platform_driver(adl_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Alder Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-baytrail.c b/drivers/pinctrl/intel/pinctrl-baytrail.c
index 4533c4d0a9e7..7340dc20349c 100644
--- a/drivers/pinctrl/intel/pinctrl-baytrail.c
+++ b/drivers/pinctrl/intel/pinctrl-baytrail.c
@@ -1723,4 +1723,4 @@ static int __init byt_gpio_init(void)
}
subsys_initcall(byt_gpio_init);
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-broxton.c b/drivers/pinctrl/intel/pinctrl-broxton.c
index d99541676630..140b29956340 100644
--- a/drivers/pinctrl/intel/pinctrl-broxton.c
+++ b/drivers/pinctrl/intel/pinctrl-broxton.c
@@ -1026,4 +1026,4 @@ module_exit(bxt_pinctrl_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Broxton SoC pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-cannonlake.c b/drivers/pinctrl/intel/pinctrl-cannonlake.c
index 1aa09f950be1..14a5d339385d 100644
--- a/drivers/pinctrl/intel/pinctrl-cannonlake.c
+++ b/drivers/pinctrl/intel/pinctrl-cannonlake.c
@@ -838,4 +838,4 @@ module_platform_driver(cnl_pinctrl_driver);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Cannon Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-cedarfork.c b/drivers/pinctrl/intel/pinctrl-cedarfork.c
index 48af8930dd1f..2ce97abeb0e4 100644
--- a/drivers/pinctrl/intel/pinctrl-cedarfork.c
+++ b/drivers/pinctrl/intel/pinctrl-cedarfork.c
@@ -350,4 +350,4 @@ module_exit(cdf_pinctrl_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Cedar Fork PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-cherryview.c b/drivers/pinctrl/intel/pinctrl-cherryview.c
index 9f938718927b..c673e262e1db 100644
--- a/drivers/pinctrl/intel/pinctrl-cherryview.c
+++ b/drivers/pinctrl/intel/pinctrl-cherryview.c
@@ -1815,4 +1815,4 @@ module_exit(chv_pinctrl_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Cherryview/Braswell pinctrl driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-denverton.c b/drivers/pinctrl/intel/pinctrl-denverton.c
index 666507f54f27..fef44c663be6 100644
--- a/drivers/pinctrl/intel/pinctrl-denverton.c
+++ b/drivers/pinctrl/intel/pinctrl-denverton.c
@@ -287,4 +287,4 @@ module_exit(dnv_pinctrl_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Denverton SoC pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-elkhartlake.c b/drivers/pinctrl/intel/pinctrl-elkhartlake.c
index 3e45d7fb003a..ab414e07555a 100644
--- a/drivers/pinctrl/intel/pinctrl-elkhartlake.c
+++ b/drivers/pinctrl/intel/pinctrl-elkhartlake.c
@@ -537,4 +537,4 @@ module_platform_driver(ehl_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Elkhart Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-emmitsburg.c b/drivers/pinctrl/intel/pinctrl-emmitsburg.c
index e4798d32492c..9d8a32aca177 100644
--- a/drivers/pinctrl/intel/pinctrl-emmitsburg.c
+++ b/drivers/pinctrl/intel/pinctrl-emmitsburg.c
@@ -372,4 +372,4 @@ module_platform_driver(ebg_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Emmitsburg PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-geminilake.c b/drivers/pinctrl/intel/pinctrl-geminilake.c
index 6dcf0ac2059f..8dcac4fe8493 100644
--- a/drivers/pinctrl/intel/pinctrl-geminilake.c
+++ b/drivers/pinctrl/intel/pinctrl-geminilake.c
@@ -472,4 +472,4 @@ module_exit(glk_pinctrl_exit);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Gemini Lake SoC pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-icelake.c b/drivers/pinctrl/intel/pinctrl-icelake.c
index fe3042de891a..7e028c61ed0f 100644
--- a/drivers/pinctrl/intel/pinctrl-icelake.c
+++ b/drivers/pinctrl/intel/pinctrl-icelake.c
@@ -690,4 +690,4 @@ MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Ice Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-intel-platform.c b/drivers/pinctrl/intel/pinctrl-intel-platform.c
index 016a9f62eecc..dd5dbede0f59 100644
--- a/drivers/pinctrl/intel/pinctrl-intel-platform.c
+++ b/drivers/pinctrl/intel/pinctrl-intel-platform.c
@@ -221,4 +221,4 @@ module_platform_driver(intel_platform_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index 04b438f63ccb..527e4b87ae52 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -158,7 +158,7 @@ const struct intel_community *intel_get_community(const struct intel_pinctrl *pc
dev_warn(pctrl->dev, "failed to find community for pin %u\n", pin);
return NULL;
}
-EXPORT_SYMBOL_NS_GPL(intel_get_community, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_get_community, "PINCTRL_INTEL");
static const struct intel_padgroup *
intel_community_get_padgroup(const struct intel_community *community,
@@ -315,7 +315,7 @@ int intel_get_groups_count(struct pinctrl_dev *pctldev)
return pctrl->soc->ngroups;
}
-EXPORT_SYMBOL_NS_GPL(intel_get_groups_count, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_get_groups_count, "PINCTRL_INTEL");
const char *intel_get_group_name(struct pinctrl_dev *pctldev, unsigned int group)
{
@@ -323,7 +323,7 @@ const char *intel_get_group_name(struct pinctrl_dev *pctldev, unsigned int group
return pctrl->soc->groups[group].grp.name;
}
-EXPORT_SYMBOL_NS_GPL(intel_get_group_name, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_get_group_name, "PINCTRL_INTEL");
int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
const unsigned int **pins, unsigned int *npins)
@@ -334,7 +334,7 @@ int intel_get_group_pins(struct pinctrl_dev *pctldev, unsigned int group,
*npins = pctrl->soc->groups[group].grp.npins;
return 0;
}
-EXPORT_SYMBOL_NS_GPL(intel_get_group_pins, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_get_group_pins, "PINCTRL_INTEL");
static void intel_pin_dbg_show(struct pinctrl_dev *pctldev, struct seq_file *s,
unsigned int pin)
@@ -400,7 +400,7 @@ int intel_get_functions_count(struct pinctrl_dev *pctldev)
return pctrl->soc->nfunctions;
}
-EXPORT_SYMBOL_NS_GPL(intel_get_functions_count, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_get_functions_count, "PINCTRL_INTEL");
const char *intel_get_function_name(struct pinctrl_dev *pctldev, unsigned int function)
{
@@ -408,7 +408,7 @@ const char *intel_get_function_name(struct pinctrl_dev *pctldev, unsigned int fu
return pctrl->soc->functions[function].func.name;
}
-EXPORT_SYMBOL_NS_GPL(intel_get_function_name, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_get_function_name, "PINCTRL_INTEL");
int intel_get_function_groups(struct pinctrl_dev *pctldev, unsigned int function,
const char * const **groups, unsigned int * const ngroups)
@@ -419,7 +419,7 @@ int intel_get_function_groups(struct pinctrl_dev *pctldev, unsigned int function
*ngroups = pctrl->soc->functions[function].func.ngroups;
return 0;
}
-EXPORT_SYMBOL_NS_GPL(intel_get_function_groups, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_get_function_groups, "PINCTRL_INTEL");
static int intel_pinmux_set_mux(struct pinctrl_dev *pctldev,
unsigned int function, unsigned int group)
@@ -1676,7 +1676,7 @@ int intel_pinctrl_probe(struct platform_device *pdev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(intel_pinctrl_probe, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_pinctrl_probe, "PINCTRL_INTEL");
int intel_pinctrl_probe_by_hid(struct platform_device *pdev)
{
@@ -1688,7 +1688,7 @@ int intel_pinctrl_probe_by_hid(struct platform_device *pdev)
return intel_pinctrl_probe(pdev, data);
}
-EXPORT_SYMBOL_NS_GPL(intel_pinctrl_probe_by_hid, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_pinctrl_probe_by_hid, "PINCTRL_INTEL");
int intel_pinctrl_probe_by_uid(struct platform_device *pdev)
{
@@ -1700,7 +1700,7 @@ int intel_pinctrl_probe_by_uid(struct platform_device *pdev)
return intel_pinctrl_probe(pdev, data);
}
-EXPORT_SYMBOL_NS_GPL(intel_pinctrl_probe_by_uid, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_pinctrl_probe_by_uid, "PINCTRL_INTEL");
const struct intel_pinctrl_soc_data *intel_pinctrl_get_soc_data(struct platform_device *pdev)
{
@@ -1731,7 +1731,7 @@ const struct intel_pinctrl_soc_data *intel_pinctrl_get_soc_data(struct platform_
return data ?: ERR_PTR(-ENODATA);
}
-EXPORT_SYMBOL_NS_GPL(intel_pinctrl_get_soc_data, PINCTRL_INTEL);
+EXPORT_SYMBOL_NS_GPL(intel_pinctrl_get_soc_data, "PINCTRL_INTEL");
static bool __intel_gpio_is_direct_irq(u32 value)
{
diff --git a/drivers/pinctrl/intel/pinctrl-jasperlake.c b/drivers/pinctrl/intel/pinctrl-jasperlake.c
index 3525480428ea..aef0e7f92154 100644
--- a/drivers/pinctrl/intel/pinctrl-jasperlake.c
+++ b/drivers/pinctrl/intel/pinctrl-jasperlake.c
@@ -340,4 +340,4 @@ module_platform_driver(jsl_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Jasper Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-lakefield.c b/drivers/pinctrl/intel/pinctrl-lakefield.c
index adef85db82ca..60281f421608 100644
--- a/drivers/pinctrl/intel/pinctrl-lakefield.c
+++ b/drivers/pinctrl/intel/pinctrl-lakefield.c
@@ -361,4 +361,4 @@ module_platform_driver(lkf_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Lakefield PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-lewisburg.c b/drivers/pinctrl/intel/pinctrl-lewisburg.c
index a304d30ea9ed..9fe651370f32 100644
--- a/drivers/pinctrl/intel/pinctrl-lewisburg.c
+++ b/drivers/pinctrl/intel/pinctrl-lewisburg.c
@@ -321,4 +321,4 @@ module_platform_driver(lbg_pinctrl_driver);
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Lewisburg pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-lynxpoint.c b/drivers/pinctrl/intel/pinctrl-lynxpoint.c
index bcce97f3b897..cc5ede17c383 100644
--- a/drivers/pinctrl/intel/pinctrl-lynxpoint.c
+++ b/drivers/pinctrl/intel/pinctrl-lynxpoint.c
@@ -859,4 +859,4 @@ MODULE_AUTHOR("Andy Shevchenko (Intel)");
MODULE_DESCRIPTION("Intel Lynxpoint pinctrl driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:lp_gpio");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-merrifield.c b/drivers/pinctrl/intel/pinctrl-merrifield.c
index 1a556f5822b6..2f4d73dda41d 100644
--- a/drivers/pinctrl/intel/pinctrl-merrifield.c
+++ b/drivers/pinctrl/intel/pinctrl-merrifield.c
@@ -380,4 +380,4 @@ MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Merrifield SoC pinctrl driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:pinctrl-merrifield");
-MODULE_IMPORT_NS(PINCTRL_TANGIER);
+MODULE_IMPORT_NS("PINCTRL_TANGIER");
diff --git a/drivers/pinctrl/intel/pinctrl-meteorlake.c b/drivers/pinctrl/intel/pinctrl-meteorlake.c
index 885fa3b0d6d9..f564376ce437 100644
--- a/drivers/pinctrl/intel/pinctrl-meteorlake.c
+++ b/drivers/pinctrl/intel/pinctrl-meteorlake.c
@@ -604,4 +604,4 @@ module_platform_driver(mtl_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Meteor Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-meteorpoint.c b/drivers/pinctrl/intel/pinctrl-meteorpoint.c
index 77e97775a60b..ab46ac5f3b15 100644
--- a/drivers/pinctrl/intel/pinctrl-meteorpoint.c
+++ b/drivers/pinctrl/intel/pinctrl-meteorpoint.c
@@ -462,4 +462,4 @@ module_platform_driver(mtp_pinctrl_driver);
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Meteor Point PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-moorefield.c b/drivers/pinctrl/intel/pinctrl-moorefield.c
index 7b995fbf5c84..6a79207e6b2a 100644
--- a/drivers/pinctrl/intel/pinctrl-moorefield.c
+++ b/drivers/pinctrl/intel/pinctrl-moorefield.c
@@ -341,4 +341,4 @@ MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("Intel Moorefield SoC pinctrl driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:pinctrl-moorefield");
-MODULE_IMPORT_NS(PINCTRL_TANGIER);
+MODULE_IMPORT_NS("PINCTRL_TANGIER");
diff --git a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
index 55df9d2cfb1b..a7a5fa65fd9d 100644
--- a/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
+++ b/drivers/pinctrl/intel/pinctrl-sunrisepoint.c
@@ -605,4 +605,4 @@ MODULE_AUTHOR("Mathias Nyman <mathias.nyman@linux.intel.com>");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Sunrisepoint PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/intel/pinctrl-tangier.c b/drivers/pinctrl/intel/pinctrl-tangier.c
index 2cb0b4758269..d3baf0f4eea0 100644
--- a/drivers/pinctrl/intel/pinctrl-tangier.c
+++ b/drivers/pinctrl/intel/pinctrl-tangier.c
@@ -579,7 +579,7 @@ int devm_tng_pinctrl_probe(struct platform_device *pdev)
return tng_pinctrl_probe(pdev, data);
}
-EXPORT_SYMBOL_NS_GPL(devm_tng_pinctrl_probe, PINCTRL_TANGIER);
+EXPORT_SYMBOL_NS_GPL(devm_tng_pinctrl_probe, "PINCTRL_TANGIER");
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_AUTHOR("Raag Jadav <raag.jadav@intel.com>");
diff --git a/drivers/pinctrl/intel/pinctrl-tigerlake.c b/drivers/pinctrl/intel/pinctrl-tigerlake.c
index 80cd7a06fe5a..c43576e10273 100644
--- a/drivers/pinctrl/intel/pinctrl-tigerlake.c
+++ b/drivers/pinctrl/intel/pinctrl-tigerlake.c
@@ -758,4 +758,4 @@ MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@linux.intel.com>");
MODULE_DESCRIPTION("Intel Tiger Lake PCH pinctrl/GPIO driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PINCTRL_INTEL);
+MODULE_IMPORT_NS("PINCTRL_INTEL");
diff --git a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
index 4c4ada06423d..335744ac8310 100644
--- a/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
+++ b/drivers/pinctrl/mvebu/pinctrl-armada-37xx.c
@@ -734,7 +734,7 @@ static void armada_37xx_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
struct armada_37xx_pinctrl *info = gpiochip_get_data(chip);
- seq_printf(p, info->data->name);
+ seq_puts(p, info->data->name);
}
static const struct irq_chip armada_37xx_irqchip = {
diff --git a/drivers/pinctrl/pinctrl-mcp23s08.c b/drivers/pinctrl/pinctrl-mcp23s08.c
index 737d0ae3d0b6..b96e6368a956 100644
--- a/drivers/pinctrl/pinctrl-mcp23s08.c
+++ b/drivers/pinctrl/pinctrl-mcp23s08.c
@@ -86,6 +86,7 @@ const struct regmap_config mcp23x08_regmap = {
.num_reg_defaults = ARRAY_SIZE(mcp23x08_defaults),
.cache_type = REGCACHE_FLAT,
.max_register = MCP_OLAT,
+ .disable_locking = true, /* mcp->lock protects the regmap */
};
EXPORT_SYMBOL_GPL(mcp23x08_regmap);
@@ -132,6 +133,7 @@ const struct regmap_config mcp23x17_regmap = {
.num_reg_defaults = ARRAY_SIZE(mcp23x17_defaults),
.cache_type = REGCACHE_FLAT,
.val_format_endian = REGMAP_ENDIAN_LITTLE,
+ .disable_locking = true, /* mcp->lock protects the regmap */
};
EXPORT_SYMBOL_GPL(mcp23x17_regmap);
@@ -228,7 +230,9 @@ static int mcp_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin,
switch (param) {
case PIN_CONFIG_BIAS_PULL_UP:
+ mutex_lock(&mcp->lock);
ret = mcp_read(mcp, MCP_GPPU, &data);
+ mutex_unlock(&mcp->lock);
if (ret < 0)
return ret;
status = (data & BIT(pin)) ? 1 : 0;
@@ -257,7 +261,9 @@ static int mcp_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin,
switch (param) {
case PIN_CONFIG_BIAS_PULL_UP:
+ mutex_lock(&mcp->lock);
ret = mcp_set_bit(mcp, MCP_GPPU, pin, arg);
+ mutex_unlock(&mcp->lock);
break;
default:
dev_dbg(mcp->dev, "Invalid config param %04x\n", param);
@@ -569,7 +575,7 @@ static void mcp23s08_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct mcp23s08 *mcp = gpiochip_get_data(gc);
- seq_printf(p, dev_name(mcp->dev));
+ seq_puts(p, dev_name(mcp->dev));
}
static const struct irq_chip mcp23s08_irq_chip = {
diff --git a/drivers/pinctrl/pinctrl-stmfx.c b/drivers/pinctrl/pinctrl-stmfx.c
index bfeb2edbeec5..521f6fef0b9f 100644
--- a/drivers/pinctrl/pinctrl-stmfx.c
+++ b/drivers/pinctrl/pinctrl-stmfx.c
@@ -599,7 +599,7 @@ static void stmfx_pinctrl_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gpio_chip = irq_data_get_irq_chip_data(d);
struct stmfx_pinctrl *pctl = gpiochip_get_data(gpio_chip);
- seq_printf(p, dev_name(pctl->dev));
+ seq_puts(p, dev_name(pctl->dev));
}
static const struct irq_chip stmfx_pinctrl_irq_chip = {
diff --git a/drivers/pinctrl/pinctrl-sx150x.c b/drivers/pinctrl/pinctrl-sx150x.c
index ab87de319ad8..98262b8ce43a 100644
--- a/drivers/pinctrl/pinctrl-sx150x.c
+++ b/drivers/pinctrl/pinctrl-sx150x.c
@@ -584,7 +584,7 @@ static void sx150x_irq_print_chip(struct irq_data *d, struct seq_file *p)
struct gpio_chip *gc = irq_data_get_irq_chip_data(d);
struct sx150x_pinctrl *pctl = gpiochip_get_data(gc);
- seq_printf(p, pctl->client->name);
+ seq_puts(p, pctl->client->name);
}
static const struct irq_chip sx150x_irq_chip = {
diff --git a/drivers/pinctrl/renesas/pinctrl-rzg2l.c b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
index 8ffb9430a134..1df9cec2873f 100644
--- a/drivers/pinctrl/renesas/pinctrl-rzg2l.c
+++ b/drivers/pinctrl/renesas/pinctrl-rzg2l.c
@@ -2332,7 +2332,7 @@ static void rzg2l_gpio_irq_print_chip(struct irq_data *data, struct seq_file *p)
{
struct gpio_chip *gc = irq_data_get_irq_chip_data(data);
- seq_printf(p, dev_name(gc->parent));
+ seq_puts(p, dev_name(gc->parent));
}
static int rzg2l_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
diff --git a/drivers/platform/chrome/Kconfig b/drivers/platform/chrome/Kconfig
index 7dbeb786352a..b7dbaf77b6db 100644
--- a/drivers/platform/chrome/Kconfig
+++ b/drivers/platform/chrome/Kconfig
@@ -61,6 +61,17 @@ config CHROMEOS_TBMC
To compile this driver as a module, choose M here: the
module will be called chromeos_tbmc.
+config CHROMEOS_OF_HW_PROBER
+ tristate "ChromeOS Device Tree Hardware Prober"
+ depends on OF
+ depends on I2C
+ select OF_DYNAMIC
+ default OF
+ help
+ This option enables the device tree hardware prober for ChromeOS
+ devices. The driver will probe the correct component variant in
+ devices that have multiple drop-in options for one component.
+
config CROS_EC
tristate "ChromeOS Embedded Controller"
select CROS_EC_PROTO
diff --git a/drivers/platform/chrome/Makefile b/drivers/platform/chrome/Makefile
index 2dcc6ccc2302..fb8335458a22 100644
--- a/drivers/platform/chrome/Makefile
+++ b/drivers/platform/chrome/Makefile
@@ -6,6 +6,7 @@ CFLAGS_cros_ec_sensorhub_ring.o:= -I$(src)
obj-$(CONFIG_CHROMEOS_ACPI) += chromeos_acpi.o
obj-$(CONFIG_CHROMEOS_LAPTOP) += chromeos_laptop.o
+obj-$(CONFIG_CHROMEOS_OF_HW_PROBER) += chromeos_of_hw_prober.o
obj-$(CONFIG_CHROMEOS_PRIVACY_SCREEN) += chromeos_privacy_screen.o
obj-$(CONFIG_CHROMEOS_PSTORE) += chromeos_pstore.o
obj-$(CONFIG_CHROMEOS_TBMC) += chromeos_tbmc.o
diff --git a/drivers/platform/chrome/chromeos_of_hw_prober.c b/drivers/platform/chrome/chromeos_of_hw_prober.c
new file mode 100644
index 000000000000..c6992f5cdc76
--- /dev/null
+++ b/drivers/platform/chrome/chromeos_of_hw_prober.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * ChromeOS Device Tree Hardware Prober
+ *
+ * Copyright (c) 2024 Google LLC
+ */
+
+#include <linux/array_size.h>
+#include <linux/errno.h>
+#include <linux/i2c-of-prober.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/stddef.h>
+
+#define DRV_NAME "chromeos_of_hw_prober"
+
+/**
+ * struct hw_prober_entry - Holds an entry for the hardware prober
+ *
+ * @compatible: compatible string to match against the machine
+ * @prober: prober function to call when machine matches
+ * @data: extra data for the prober function
+ */
+struct hw_prober_entry {
+ const char *compatible;
+ int (*prober)(struct device *dev, const void *data);
+ const void *data;
+};
+
+struct chromeos_i2c_probe_data {
+ const struct i2c_of_probe_cfg *cfg;
+ const struct i2c_of_probe_simple_opts *opts;
+};
+
+static int chromeos_i2c_component_prober(struct device *dev, const void *_data)
+{
+ const struct chromeos_i2c_probe_data *data = _data;
+ struct i2c_of_probe_simple_ctx ctx = {
+ .opts = data->opts,
+ };
+
+ return i2c_of_probe_component(dev, data->cfg, &ctx);
+}
+
+#define DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(_type) \
+ static const struct i2c_of_probe_cfg chromeos_i2c_probe_simple_ ## _type ## _cfg = { \
+ .type = #_type, \
+ .ops = &i2c_of_probe_simple_ops, \
+ }
+
+#define DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(_type) \
+ static const struct chromeos_i2c_probe_data chromeos_i2c_probe_dumb_ ## _type = { \
+ .cfg = &(const struct i2c_of_probe_cfg) { \
+ .type = #_type, \
+ }, \
+ }
+
+DEFINE_CHROMEOS_I2C_PROBE_DATA_DUMB_BY_TYPE(touchscreen);
+
+DEFINE_CHROMEOS_I2C_PROBE_CFG_SIMPLE_BY_TYPE(trackpad);
+
+static const struct chromeos_i2c_probe_data chromeos_i2c_probe_hana_trackpad = {
+ .cfg = &chromeos_i2c_probe_simple_trackpad_cfg,
+ .opts = &(const struct i2c_of_probe_simple_opts) {
+ .res_node_compatible = "elan,ekth3000",
+ .supply_name = "vcc",
+ /*
+ * ELAN trackpad needs 2 ms for H/W init and 100 ms for F/W init.
+ * Synaptics trackpad needs 100 ms.
+ * However, the regulator is set to "always-on", presumably to
+ * avoid this delay. The ELAN driver is also missing delays.
+ */
+ .post_power_on_delay_ms = 0,
+ },
+};
+
+static const struct hw_prober_entry hw_prober_platforms[] = {
+ {
+ .compatible = "google,hana",
+ .prober = chromeos_i2c_component_prober,
+ .data = &chromeos_i2c_probe_dumb_touchscreen,
+ }, {
+ .compatible = "google,hana",
+ .prober = chromeos_i2c_component_prober,
+ .data = &chromeos_i2c_probe_hana_trackpad,
+ },
+};
+
+static int chromeos_of_hw_prober_probe(struct platform_device *pdev)
+{
+ for (size_t i = 0; i < ARRAY_SIZE(hw_prober_platforms); i++) {
+ int ret;
+
+ if (!of_machine_is_compatible(hw_prober_platforms[i].compatible))
+ continue;
+
+ ret = hw_prober_platforms[i].prober(&pdev->dev, hw_prober_platforms[i].data);
+ /* Ignore unrecoverable errors and keep going through other probers */
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct platform_driver chromeos_of_hw_prober_driver = {
+ .probe = chromeos_of_hw_prober_probe,
+ .driver = {
+ .name = DRV_NAME,
+ },
+};
+
+static struct platform_device *chromeos_of_hw_prober_pdev;
+
+static int chromeos_of_hw_prober_driver_init(void)
+{
+ size_t i;
+ int ret;
+
+ for (i = 0; i < ARRAY_SIZE(hw_prober_platforms); i++)
+ if (of_machine_is_compatible(hw_prober_platforms[i].compatible))
+ break;
+ if (i == ARRAY_SIZE(hw_prober_platforms))
+ return -ENODEV;
+
+ ret = platform_driver_register(&chromeos_of_hw_prober_driver);
+ if (ret)
+ return ret;
+
+ chromeos_of_hw_prober_pdev =
+ platform_device_register_simple(DRV_NAME, PLATFORM_DEVID_NONE, NULL, 0);
+ if (IS_ERR(chromeos_of_hw_prober_pdev))
+ goto err;
+
+ return 0;
+
+err:
+ platform_driver_unregister(&chromeos_of_hw_prober_driver);
+
+ return PTR_ERR(chromeos_of_hw_prober_pdev);
+}
+module_init(chromeos_of_hw_prober_driver_init);
+
+static void chromeos_of_hw_prober_driver_exit(void)
+{
+ platform_device_unregister(chromeos_of_hw_prober_pdev);
+ platform_driver_unregister(&chromeos_of_hw_prober_driver);
+}
+module_exit(chromeos_of_hw_prober_driver_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("ChromeOS device tree hardware prober");
+MODULE_IMPORT_NS("I2C_OF_PROBER");
diff --git a/drivers/platform/chrome/cros_ec_lpc.c b/drivers/platform/chrome/cros_ec_lpc.c
index 924bf4d3cc77..8470b7f2b135 100644
--- a/drivers/platform/chrome/cros_ec_lpc.c
+++ b/drivers/platform/chrome/cros_ec_lpc.c
@@ -707,7 +707,7 @@ static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = {
/* Framework Laptop (12th Gen Intel Core) */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "12th Gen Intel Core"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Laptop (12th Gen Intel Core)"),
},
.driver_data = (void *)&framework_laptop_mec_lpc_driver_data,
},
@@ -715,7 +715,7 @@ static const struct dmi_system_id cros_ec_lpc_dmi_table[] __initconst = {
/* Framework Laptop (13th Gen Intel Core) */
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Framework"),
- DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "13th Gen Intel Core"),
+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Laptop (13th Gen Intel Core)"),
},
.driver_data = (void *)&framework_laptop_mec_lpc_driver_data,
},
diff --git a/drivers/platform/goldfish/goldfish_pipe.c b/drivers/platform/goldfish/goldfish_pipe.c
index c2aab0cfab33..abc31971fe6a 100644
--- a/drivers/platform/goldfish/goldfish_pipe.c
+++ b/drivers/platform/goldfish/goldfish_pipe.c
@@ -61,7 +61,6 @@
#include <linux/io.h>
#include <linux/dma-mapping.h>
#include <linux/mm.h>
-#include <linux/acpi.h>
#include <linux/bug.h>
#include "goldfish_pipe_qemu.h"
@@ -936,11 +935,11 @@ MODULE_DEVICE_TABLE(of, goldfish_pipe_of_match);
static struct platform_driver goldfish_pipe_driver = {
.probe = goldfish_pipe_probe,
- .remove_new = goldfish_pipe_remove,
+ .remove = goldfish_pipe_remove,
.driver = {
.name = "goldfish_pipe",
.of_match_table = goldfish_pipe_of_match,
- .acpi_match_table = ACPI_PTR(goldfish_pipe_acpi_match),
+ .acpi_match_table = goldfish_pipe_acpi_match,
}
};
diff --git a/drivers/platform/loongarch/Kconfig b/drivers/platform/loongarch/Kconfig
index 5633e4d73991..447528797d07 100644
--- a/drivers/platform/loongarch/Kconfig
+++ b/drivers/platform/loongarch/Kconfig
@@ -18,7 +18,7 @@ if LOONGARCH_PLATFORM_DEVICES
config LOONGSON_LAPTOP
tristate "Generic Loongson-3 Laptop Driver"
- depends on ACPI
+ depends on ACPI_EC
depends on BACKLIGHT_CLASS_DEVICE
depends on INPUT
depends on MACH_LOONGSON64
diff --git a/drivers/platform/mellanox/mlxbf-bootctl.c b/drivers/platform/mellanox/mlxbf-bootctl.c
index dd5f370c3168..c5b36837e694 100644
--- a/drivers/platform/mellanox/mlxbf-bootctl.c
+++ b/drivers/platform/mellanox/mlxbf-bootctl.c
@@ -1049,7 +1049,7 @@ static void mlxbf_bootctl_remove(struct platform_device *pdev)
static struct platform_driver mlxbf_bootctl_driver = {
.probe = mlxbf_bootctl_probe,
- .remove_new = mlxbf_bootctl_remove,
+ .remove = mlxbf_bootctl_remove,
.driver = {
.name = "mlxbf-bootctl",
.dev_groups = mlxbf_bootctl_groups,
diff --git a/drivers/platform/mellanox/mlxbf-tmfifo.c b/drivers/platform/mellanox/mlxbf-tmfifo.c
index 6c834e39352d..300cdaa75a17 100644
--- a/drivers/platform/mellanox/mlxbf-tmfifo.c
+++ b/drivers/platform/mellanox/mlxbf-tmfifo.c
@@ -1446,7 +1446,7 @@ MODULE_DEVICE_TABLE(acpi, mlxbf_tmfifo_acpi_match);
static struct platform_driver mlxbf_tmfifo_driver = {
.probe = mlxbf_tmfifo_probe,
- .remove_new = mlxbf_tmfifo_remove,
+ .remove = mlxbf_tmfifo_remove,
.driver = {
.name = "bf-tmfifo",
.acpi_match_table = mlxbf_tmfifo_acpi_match,
diff --git a/drivers/platform/mellanox/mlxreg-hotplug.c b/drivers/platform/mellanox/mlxreg-hotplug.c
index 0ce9fff1f7d4..6aa2a4650367 100644
--- a/drivers/platform/mellanox/mlxreg-hotplug.c
+++ b/drivers/platform/mellanox/mlxreg-hotplug.c
@@ -786,7 +786,7 @@ static struct platform_driver mlxreg_hotplug_driver = {
.name = "mlxreg-hotplug",
},
.probe = mlxreg_hotplug_probe,
- .remove_new = mlxreg_hotplug_remove,
+ .remove = mlxreg_hotplug_remove,
};
module_platform_driver(mlxreg_hotplug_driver);
diff --git a/drivers/platform/mellanox/mlxreg-io.c b/drivers/platform/mellanox/mlxreg-io.c
index ee7bd623ba44..595276206baf 100644
--- a/drivers/platform/mellanox/mlxreg-io.c
+++ b/drivers/platform/mellanox/mlxreg-io.c
@@ -275,7 +275,7 @@ static struct platform_driver mlxreg_io_driver = {
.name = "mlxreg-io",
},
.probe = mlxreg_io_probe,
- .remove_new = mlxreg_io_remove,
+ .remove = mlxreg_io_remove,
};
module_platform_driver(mlxreg_io_driver);
diff --git a/drivers/platform/mellanox/mlxreg-lc.c b/drivers/platform/mellanox/mlxreg-lc.c
index 43d119e3a473..aee395bb48ae 100644
--- a/drivers/platform/mellanox/mlxreg-lc.c
+++ b/drivers/platform/mellanox/mlxreg-lc.c
@@ -944,7 +944,7 @@ static void mlxreg_lc_remove(struct platform_device *pdev)
static struct platform_driver mlxreg_lc_driver = {
.probe = mlxreg_lc_probe,
- .remove_new = mlxreg_lc_remove,
+ .remove = mlxreg_lc_remove,
.driver = {
.name = "mlxreg-lc",
},
diff --git a/drivers/platform/mellanox/nvsw-sn2201.c b/drivers/platform/mellanox/nvsw-sn2201.c
index abe7be602f84..0c047aa2345b 100644
--- a/drivers/platform/mellanox/nvsw-sn2201.c
+++ b/drivers/platform/mellanox/nvsw-sn2201.c
@@ -1253,7 +1253,7 @@ MODULE_DEVICE_TABLE(acpi, nvsw_sn2201_acpi_ids);
static struct platform_driver nvsw_sn2201_driver = {
.probe = nvsw_sn2201_probe,
- .remove_new = nvsw_sn2201_remove,
+ .remove = nvsw_sn2201_remove,
.driver = {
.name = "nvsw-sn2201",
.acpi_match_table = nvsw_sn2201_acpi_ids,
diff --git a/drivers/platform/surface/surface3-wmi.c b/drivers/platform/surface/surface3-wmi.c
index c15ed7a12784..6c8fb7a4dde4 100644
--- a/drivers/platform/surface/surface3-wmi.c
+++ b/drivers/platform/surface/surface3-wmi.c
@@ -247,7 +247,7 @@ static struct platform_driver s3_wmi_driver = {
.name = "surface3-wmi",
.pm = &s3_wmi_pm,
},
- .remove_new = s3_wmi_remove,
+ .remove = s3_wmi_remove,
};
static int __init s3_wmi_init(void)
diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c
index 14a9d8a267cb..3b30cfe3466b 100644
--- a/drivers/platform/surface/surface_acpi_notify.c
+++ b/drivers/platform/surface/surface_acpi_notify.c
@@ -850,7 +850,7 @@ MODULE_DEVICE_TABLE(acpi, san_match);
static struct platform_driver surface_acpi_notify = {
.probe = san_probe,
- .remove_new = san_remove,
+ .remove = san_remove,
.driver = {
.name = "surface_acpi_notify",
.acpi_match_table = san_match,
diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c
index 165b1416230d..bfaa09d1648b 100644
--- a/drivers/platform/surface/surface_aggregator_cdev.c
+++ b/drivers/platform/surface/surface_aggregator_cdev.c
@@ -762,7 +762,7 @@ static struct platform_device *ssam_cdev_device;
static struct platform_driver ssam_cdev_driver = {
.probe = ssam_dbg_device_probe,
- .remove_new = ssam_dbg_device_remove,
+ .remove = ssam_dbg_device_remove,
.driver = {
.name = SSAM_CDEV_DEVICE_NAME,
.probe_type = PROBE_PREFER_ASYNCHRONOUS,
diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
index 06e45f0b9817..d4f32ad66530 100644
--- a/drivers/platform/surface/surface_aggregator_registry.c
+++ b/drivers/platform/surface/surface_aggregator_registry.c
@@ -554,7 +554,7 @@ static void ssam_platform_hub_remove(struct platform_device *pdev)
static struct platform_driver ssam_platform_hub_driver = {
.probe = ssam_platform_hub_probe,
- .remove_new = ssam_platform_hub_remove,
+ .remove = ssam_platform_hub_remove,
.driver = {
.name = "surface_aggregator_platform_hub",
.acpi_match_table = ssam_platform_hub_acpi_match,
diff --git a/drivers/platform/surface/surface_dtx.c b/drivers/platform/surface/surface_dtx.c
index 89ca6b50e812..97ae010069e4 100644
--- a/drivers/platform/surface/surface_dtx.c
+++ b/drivers/platform/surface/surface_dtx.c
@@ -1180,7 +1180,7 @@ MODULE_DEVICE_TABLE(acpi, surface_dtx_acpi_match);
static struct platform_driver surface_dtx_platform_driver = {
.probe = surface_dtx_platform_probe,
- .remove_new = surface_dtx_platform_remove,
+ .remove = surface_dtx_platform_remove,
.driver = {
.name = "surface_dtx_pltf",
.acpi_match_table = surface_dtx_acpi_match,
diff --git a/drivers/platform/surface/surface_gpe.c b/drivers/platform/surface/surface_gpe.c
index 62fd4004db31..b359413903b1 100644
--- a/drivers/platform/surface/surface_gpe.c
+++ b/drivers/platform/surface/surface_gpe.c
@@ -278,7 +278,7 @@ static void surface_gpe_remove(struct platform_device *pdev)
static struct platform_driver surface_gpe_driver = {
.probe = surface_gpe_probe,
- .remove_new = surface_gpe_remove,
+ .remove = surface_gpe_remove,
.driver = {
.name = "surface_gpe",
.pm = &surface_gpe_pm,
diff --git a/drivers/platform/surface/surface_hotplug.c b/drivers/platform/surface/surface_hotplug.c
index a404f26cfae8..c0d83ed5a208 100644
--- a/drivers/platform/surface/surface_hotplug.c
+++ b/drivers/platform/surface/surface_hotplug.c
@@ -259,7 +259,7 @@ MODULE_DEVICE_TABLE(acpi, surface_hotplug_acpi_match);
static struct platform_driver surface_hotplug_driver = {
.probe = surface_hotplug_probe,
- .remove_new = surface_hotplug_remove,
+ .remove = surface_hotplug_remove,
.driver = {
.name = "surface_hotplug",
.acpi_match_table = surface_hotplug_acpi_match,
diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c
index 4aa4d66f491a..e981d45e1c12 100644
--- a/drivers/platform/x86/amd/hsmp/acpi.c
+++ b/drivers/platform/x86/amd/hsmp/acpi.c
@@ -236,7 +236,7 @@ static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj
}
static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
- struct bin_attribute *battr, int id)
+ const struct bin_attribute *battr, int id)
{
if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6)
return battr->attr.mode;
@@ -372,7 +372,7 @@ static struct platform_driver amd_hsmp_driver = {
module_platform_driver(amd_hsmp_driver);
-MODULE_IMPORT_NS(AMD_HSMP);
+MODULE_IMPORT_NS("AMD_HSMP");
MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c
index f29dd93fbf0b..227b4ad4a51a 100644
--- a/drivers/platform/x86/amd/hsmp/hsmp.c
+++ b/drivers/platform/x86/amd/hsmp/hsmp.c
@@ -206,7 +206,7 @@ int hsmp_send_message(struct hsmp_message *msg)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(hsmp_send_message, AMD_HSMP);
+EXPORT_SYMBOL_NS_GPL(hsmp_send_message, "AMD_HSMP");
int hsmp_test(u16 sock_ind, u32 value)
{
@@ -237,7 +237,7 @@ int hsmp_test(u16 sock_ind, u32 value)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(hsmp_test, AMD_HSMP);
+EXPORT_SYMBOL_NS_GPL(hsmp_test, "AMD_HSMP");
long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
{
@@ -319,7 +319,7 @@ ssize_t hsmp_metric_tbl_read(struct hsmp_socket *sock, char *buf, size_t size)
return size;
}
-EXPORT_SYMBOL_NS_GPL(hsmp_metric_tbl_read, AMD_HSMP);
+EXPORT_SYMBOL_NS_GPL(hsmp_metric_tbl_read, "AMD_HSMP");
int hsmp_get_tbl_dram_base(u16 sock_ind)
{
@@ -353,7 +353,7 @@ int hsmp_get_tbl_dram_base(u16 sock_ind)
}
return 0;
}
-EXPORT_SYMBOL_NS_GPL(hsmp_get_tbl_dram_base, AMD_HSMP);
+EXPORT_SYMBOL_NS_GPL(hsmp_get_tbl_dram_base, "AMD_HSMP");
int hsmp_cache_proto_ver(u16 sock_ind)
{
@@ -370,7 +370,7 @@ int hsmp_cache_proto_ver(u16 sock_ind)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(hsmp_cache_proto_ver, AMD_HSMP);
+EXPORT_SYMBOL_NS_GPL(hsmp_cache_proto_ver, "AMD_HSMP");
static const struct file_operations hsmp_fops = {
.owner = THIS_MODULE,
@@ -389,19 +389,19 @@ int hsmp_misc_register(struct device *dev)
return misc_register(&hsmp_pdev.mdev);
}
-EXPORT_SYMBOL_NS_GPL(hsmp_misc_register, AMD_HSMP);
+EXPORT_SYMBOL_NS_GPL(hsmp_misc_register, "AMD_HSMP");
void hsmp_misc_deregister(void)
{
misc_deregister(&hsmp_pdev.mdev);
}
-EXPORT_SYMBOL_NS_GPL(hsmp_misc_deregister, AMD_HSMP);
+EXPORT_SYMBOL_NS_GPL(hsmp_misc_deregister, "AMD_HSMP");
struct hsmp_plat_device *get_hsmp_pdev(void)
{
return &hsmp_pdev;
}
-EXPORT_SYMBOL_NS_GPL(get_hsmp_pdev, AMD_HSMP);
+EXPORT_SYMBOL_NS_GPL(get_hsmp_pdev, "AMD_HSMP");
MODULE_DESCRIPTION("AMD HSMP Common driver");
MODULE_VERSION(DRIVER_VERSION);
diff --git a/drivers/platform/x86/amd/hsmp/plat.c b/drivers/platform/x86/amd/hsmp/plat.c
index f8e74c0392ba..a61f815c9f80 100644
--- a/drivers/platform/x86/amd/hsmp/plat.c
+++ b/drivers/platform/x86/amd/hsmp/plat.c
@@ -75,7 +75,7 @@ static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj
}
static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
- struct bin_attribute *battr, int id)
+ const struct bin_attribute *battr, int id)
{
u16 sock_ind;
@@ -332,7 +332,7 @@ static void __exit hsmp_plt_exit(void)
device_initcall(hsmp_plt_init);
module_exit(hsmp_plt_exit);
-MODULE_IMPORT_NS(AMD_HSMP);
+MODULE_IMPORT_NS("AMD_HSMP");
MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c
index ef04d396f61c..a5933980ade3 100644
--- a/drivers/platform/x86/asus-nb-wmi.c
+++ b/drivers/platform/x86/asus-nb-wmi.c
@@ -623,6 +623,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = {
{ KE_KEY, 0xC4, { KEY_KBDILLUMUP } },
{ KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } },
{ KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */
+ { KE_IGNORE, 0xCF, }, /* AC mode */
{ KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */
{ KE_KEY, 0xBD, { KEY_PROG2 } }, /* Lid flip action on ROG xflow laptops */
{ KE_END, 0},
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index ba8b6d028f9f..8bd187e8b47f 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -3696,7 +3696,6 @@ static int asus_wmi_custom_fan_curve_init(struct asus_wmi *asus)
/* Throttle thermal policy ****************************************************/
static int throttle_thermal_policy_write(struct asus_wmi *asus)
{
- u32 retval;
u8 value;
int err;
@@ -3718,8 +3717,8 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus)
value = asus->throttle_thermal_policy_mode;
}
- err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev,
- value, &retval);
+ /* Some machines do not return an error code as a result, so we ignore it */
+ err = asus_wmi_set_devstate(asus->throttle_thermal_policy_dev, value, NULL);
sysfs_notify(&asus->platform_device->dev.kobj, NULL,
"throttle_thermal_policy");
@@ -3729,12 +3728,6 @@ static int throttle_thermal_policy_write(struct asus_wmi *asus)
return err;
}
- if (retval != 1) {
- pr_warn("Failed to set throttle thermal policy (retval): 0x%x\n",
- retval);
- return -EIO;
- }
-
/* Must set to disabled if mode is toggled */
if (asus->cpu_fan_curve_available)
asus->custom_fan_curves[FAN_CURVE_DEV_CPU].enabled = false;
diff --git a/drivers/platform/x86/dell/alienware-wmi.c b/drivers/platform/x86/dell/alienware-wmi.c
index 77465ed9b449..341d01d3e3e4 100644
--- a/drivers/platform/x86/dell/alienware-wmi.c
+++ b/drivers/platform/x86/dell/alienware-wmi.c
@@ -190,7 +190,7 @@ static struct quirk_entry quirk_asm201 = {
};
static struct quirk_entry quirk_g_series = {
- .num_zones = 2,
+ .num_zones = 0,
.hdmi_mux = 0,
.amplifier = 0,
.deepslp = 0,
@@ -199,7 +199,7 @@ static struct quirk_entry quirk_g_series = {
};
static struct quirk_entry quirk_x_series = {
- .num_zones = 2,
+ .num_zones = 0,
.hdmi_mux = 0,
.amplifier = 0,
.deepslp = 0,
@@ -243,6 +243,15 @@ static const struct dmi_system_id alienware_quirks[] __initconst = {
},
{
.callback = dmi_matched,
+ .ident = "Alienware m16 R1 AMD",
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m16 R1 AMD"),
+ },
+ .driver_data = &quirk_x_series,
+ },
+ {
+ .callback = dmi_matched,
.ident = "Alienware m17 R5",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "Alienware"),
@@ -687,6 +696,9 @@ static void alienware_zone_exit(struct platform_device *dev)
{
u8 zone;
+ if (!quirks->num_zones)
+ return;
+
sysfs_remove_group(&dev->dev.kobj, &zone_attribute_group);
led_classdev_unregister(&global_led);
if (zone_dev_attrs) {
@@ -1229,9 +1241,11 @@ static int __init alienware_wmi_init(void)
goto fail_prep_thermal_profile;
}
- ret = alienware_zone_init(platform_device);
- if (ret)
- goto fail_prep_zones;
+ if (quirks->num_zones > 0) {
+ ret = alienware_zone_init(platform_device);
+ if (ret)
+ goto fail_prep_zones;
+ }
return 0;
diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c
index 81ccc96ffe40..20c55bab3b8c 100644
--- a/drivers/platform/x86/hp/hp-wmi.c
+++ b/drivers/platform/x86/hp/hp-wmi.c
@@ -64,7 +64,7 @@ static const char * const omen_thermal_profile_boards[] = {
"874A", "8603", "8604", "8748", "886B", "886C", "878A", "878B", "878C",
"88C8", "88CB", "8786", "8787", "8788", "88D1", "88D2", "88F4", "88FD",
"88F5", "88F6", "88F7", "88FE", "88FF", "8900", "8901", "8902", "8912",
- "8917", "8918", "8949", "894A", "89EB", "8BAD", "8A42"
+ "8917", "8918", "8949", "894A", "89EB", "8BAD", "8A42", "8A15"
};
/* DMI Board names of Omen laptops that are specifically set to be thermal
@@ -80,7 +80,7 @@ static const char * const omen_thermal_profile_force_v0_boards[] = {
* "balanced" when reaching zero.
*/
static const char * const omen_timed_thermal_profile_boards[] = {
- "8BAD", "8A42"
+ "8BAD", "8A42", "8A15"
};
/* DMI Board names of Victus laptops */
diff --git a/drivers/platform/x86/ideapad-laptop.c b/drivers/platform/x86/ideapad-laptop.c
index 5d2c1f0d1e9f..e980dd18e5f6 100644
--- a/drivers/platform/x86/ideapad-laptop.c
+++ b/drivers/platform/x86/ideapad-laptop.c
@@ -1826,19 +1826,19 @@ int ideapad_laptop_register_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_register(&ideapad_laptop_chain_head, nb);
}
-EXPORT_SYMBOL_NS_GPL(ideapad_laptop_register_notifier, IDEAPAD_LAPTOP);
+EXPORT_SYMBOL_NS_GPL(ideapad_laptop_register_notifier, "IDEAPAD_LAPTOP");
int ideapad_laptop_unregister_notifier(struct notifier_block *nb)
{
return blocking_notifier_chain_unregister(&ideapad_laptop_chain_head, nb);
}
-EXPORT_SYMBOL_NS_GPL(ideapad_laptop_unregister_notifier, IDEAPAD_LAPTOP);
+EXPORT_SYMBOL_NS_GPL(ideapad_laptop_unregister_notifier, "IDEAPAD_LAPTOP");
void ideapad_laptop_call_notifier(unsigned long action, void *data)
{
blocking_notifier_call_chain(&ideapad_laptop_chain_head, action, data);
}
-EXPORT_SYMBOL_NS_GPL(ideapad_laptop_call_notifier, IDEAPAD_LAPTOP);
+EXPORT_SYMBOL_NS_GPL(ideapad_laptop_call_notifier, "IDEAPAD_LAPTOP");
static void ideapad_acpi_notify(acpi_handle handle, u32 event, void *data)
{
diff --git a/drivers/platform/x86/intel/ifs/core.c b/drivers/platform/x86/intel/ifs/core.c
index bc252b883210..1ae50702bdb7 100644
--- a/drivers/platform/x86/intel/ifs/core.c
+++ b/drivers/platform/x86/intel/ifs/core.c
@@ -20,6 +20,7 @@ static const struct x86_cpu_id ifs_cpu_ids[] __initconst = {
X86_MATCH(INTEL_GRANITERAPIDS_X, ARRAY_GEN0),
X86_MATCH(INTEL_GRANITERAPIDS_D, ARRAY_GEN0),
X86_MATCH(INTEL_ATOM_CRESTMONT_X, ARRAY_GEN1),
+ X86_MATCH(INTEL_ATOM_DARKMONT_X, ARRAY_GEN1),
{}
};
MODULE_DEVICE_TABLE(x86cpu, ifs_cpu_ids);
diff --git a/drivers/platform/x86/intel/plr_tpmi.c b/drivers/platform/x86/intel/plr_tpmi.c
index 69ace6a629bc..691d43c3592c 100644
--- a/drivers/platform/x86/intel/plr_tpmi.c
+++ b/drivers/platform/x86/intel/plr_tpmi.c
@@ -348,7 +348,7 @@ static struct auxiliary_driver intel_plr_aux_driver = {
};
module_auxiliary_driver(intel_plr_aux_driver);
-MODULE_IMPORT_NS(INTEL_TPMI);
-MODULE_IMPORT_NS(INTEL_TPMI_POWER_DOMAIN);
+MODULE_IMPORT_NS("INTEL_TPMI");
+MODULE_IMPORT_NS("INTEL_TPMI_POWER_DOMAIN");
MODULE_DESCRIPTION("Intel TPMI PLR Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel/pmc/core_ssram.c b/drivers/platform/x86/intel/pmc/core_ssram.c
index 8504154b649f..50ebfd586d3f 100644
--- a/drivers/platform/x86/intel/pmc/core_ssram.c
+++ b/drivers/platform/x86/intel/pmc/core_ssram.c
@@ -324,5 +324,5 @@ release_dev:
return ret;
}
-MODULE_IMPORT_NS(INTEL_VSEC);
-MODULE_IMPORT_NS(INTEL_PMT_TELEMETRY);
+MODULE_IMPORT_NS("INTEL_VSEC");
+MODULE_IMPORT_NS("INTEL_PMT_TELEMETRY");
diff --git a/drivers/platform/x86/intel/pmt/class.c b/drivers/platform/x86/intel/pmt/class.c
index 375695cc0d60..8ed54b7a3333 100644
--- a/drivers/platform/x86/intel/pmt/class.c
+++ b/drivers/platform/x86/intel/pmt/class.c
@@ -33,7 +33,7 @@ bool intel_pmt_is_early_client_hw(struct device *dev)
*/
return !!(ivdev->quirks & VSEC_QUIRK_EARLY_HW);
}
-EXPORT_SYMBOL_NS_GPL(intel_pmt_is_early_client_hw, INTEL_PMT);
+EXPORT_SYMBOL_NS_GPL(intel_pmt_is_early_client_hw, "INTEL_PMT");
static inline int
pmt_memcpy64_fromio(void *to, const u64 __iomem *from, size_t count)
@@ -74,7 +74,7 @@ int pmt_telem_read_mmio(struct pci_dev *pdev, struct pmt_callbacks *cb, u32 guid
return count;
}
-EXPORT_SYMBOL_NS_GPL(pmt_telem_read_mmio, INTEL_PMT);
+EXPORT_SYMBOL_NS_GPL(pmt_telem_read_mmio, "INTEL_PMT");
/*
* sysfs
@@ -105,7 +105,7 @@ intel_pmt_read(struct file *filp, struct kobject *kobj,
static int
intel_pmt_mmap(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr, struct vm_area_struct *vma)
+ const struct bin_attribute *attr, struct vm_area_struct *vma)
{
struct intel_pmt_entry *entry = container_of(attr,
struct intel_pmt_entry,
@@ -359,7 +359,7 @@ int intel_pmt_dev_create(struct intel_pmt_entry *entry, struct intel_pmt_namespa
return intel_pmt_dev_register(entry, ns, dev);
}
-EXPORT_SYMBOL_NS_GPL(intel_pmt_dev_create, INTEL_PMT);
+EXPORT_SYMBOL_NS_GPL(intel_pmt_dev_create, "INTEL_PMT");
void intel_pmt_dev_destroy(struct intel_pmt_entry *entry,
struct intel_pmt_namespace *ns)
@@ -375,7 +375,7 @@ void intel_pmt_dev_destroy(struct intel_pmt_entry *entry,
device_unregister(dev);
xa_erase(ns->xa, entry->devid);
}
-EXPORT_SYMBOL_NS_GPL(intel_pmt_dev_destroy, INTEL_PMT);
+EXPORT_SYMBOL_NS_GPL(intel_pmt_dev_destroy, "INTEL_PMT");
static int __init pmt_class_init(void)
{
diff --git a/drivers/platform/x86/intel/pmt/crashlog.c b/drivers/platform/x86/intel/pmt/crashlog.c
index 9079d5dffc03..6a9eb3c4b313 100644
--- a/drivers/platform/x86/intel/pmt/crashlog.c
+++ b/drivers/platform/x86/intel/pmt/crashlog.c
@@ -328,4 +328,4 @@ module_exit(pmt_crashlog_exit);
MODULE_AUTHOR("Alexander Duyck <alexander.h.duyck@linux.intel.com>");
MODULE_DESCRIPTION("Intel PMT Crashlog driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(INTEL_PMT);
+MODULE_IMPORT_NS("INTEL_PMT");
diff --git a/drivers/platform/x86/intel/pmt/telemetry.c b/drivers/platform/x86/intel/pmt/telemetry.c
index 0cea617c6c2e..ac3a9bdf5601 100644
--- a/drivers/platform/x86/intel/pmt/telemetry.c
+++ b/drivers/platform/x86/intel/pmt/telemetry.c
@@ -153,7 +153,7 @@ unsigned long pmt_telem_get_next_endpoint(unsigned long start)
return found_idx == start ? 0 : found_idx;
}
-EXPORT_SYMBOL_NS_GPL(pmt_telem_get_next_endpoint, INTEL_PMT_TELEMETRY);
+EXPORT_SYMBOL_NS_GPL(pmt_telem_get_next_endpoint, "INTEL_PMT_TELEMETRY");
struct telem_endpoint *pmt_telem_register_endpoint(int devid)
{
@@ -172,13 +172,13 @@ struct telem_endpoint *pmt_telem_register_endpoint(int devid)
return entry->ep;
}
-EXPORT_SYMBOL_NS_GPL(pmt_telem_register_endpoint, INTEL_PMT_TELEMETRY);
+EXPORT_SYMBOL_NS_GPL(pmt_telem_register_endpoint, "INTEL_PMT_TELEMETRY");
void pmt_telem_unregister_endpoint(struct telem_endpoint *ep)
{
kref_put(&ep->kref, pmt_telem_ep_release);
}
-EXPORT_SYMBOL_NS_GPL(pmt_telem_unregister_endpoint, INTEL_PMT_TELEMETRY);
+EXPORT_SYMBOL_NS_GPL(pmt_telem_unregister_endpoint, "INTEL_PMT_TELEMETRY");
int pmt_telem_get_endpoint_info(int devid, struct telem_endpoint_info *info)
{
@@ -204,7 +204,7 @@ unlock:
return err;
}
-EXPORT_SYMBOL_NS_GPL(pmt_telem_get_endpoint_info, INTEL_PMT_TELEMETRY);
+EXPORT_SYMBOL_NS_GPL(pmt_telem_get_endpoint_info, "INTEL_PMT_TELEMETRY");
int pmt_telem_read(struct telem_endpoint *ep, u32 id, u64 *data, u32 count)
{
@@ -224,7 +224,7 @@ int pmt_telem_read(struct telem_endpoint *ep, u32 id, u64 *data, u32 count)
return ep->present ? 0 : -EPIPE;
}
-EXPORT_SYMBOL_NS_GPL(pmt_telem_read, INTEL_PMT_TELEMETRY);
+EXPORT_SYMBOL_NS_GPL(pmt_telem_read, "INTEL_PMT_TELEMETRY");
int pmt_telem_read32(struct telem_endpoint *ep, u32 id, u32 *data, u32 count)
{
@@ -243,7 +243,7 @@ int pmt_telem_read32(struct telem_endpoint *ep, u32 id, u32 *data, u32 count)
return ep->present ? 0 : -EPIPE;
}
-EXPORT_SYMBOL_NS_GPL(pmt_telem_read32, INTEL_PMT_TELEMETRY);
+EXPORT_SYMBOL_NS_GPL(pmt_telem_read32, "INTEL_PMT_TELEMETRY");
struct telem_endpoint *
pmt_telem_find_and_register_endpoint(struct pci_dev *pcidev, u32 guid, u16 pos)
@@ -268,7 +268,7 @@ pmt_telem_find_and_register_endpoint(struct pci_dev *pcidev, u32 guid, u16 pos)
return ERR_PTR(-ENXIO);
}
-EXPORT_SYMBOL_NS_GPL(pmt_telem_find_and_register_endpoint, INTEL_PMT_TELEMETRY);
+EXPORT_SYMBOL_NS_GPL(pmt_telem_find_and_register_endpoint, "INTEL_PMT_TELEMETRY");
static void pmt_telem_remove(struct auxiliary_device *auxdev)
{
@@ -347,4 +347,4 @@ module_exit(pmt_telem_exit);
MODULE_AUTHOR("David E. Box <david.e.box@linux.intel.com>");
MODULE_DESCRIPTION("Intel PMT Telemetry driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(INTEL_PMT);
+MODULE_IMPORT_NS("INTEL_PMT");
diff --git a/drivers/platform/x86/intel/sdsi.c b/drivers/platform/x86/intel/sdsi.c
index 9d137621f0e6..33f33b1070fd 100644
--- a/drivers/platform/x86/intel/sdsi.c
+++ b/drivers/platform/x86/intel/sdsi.c
@@ -541,7 +541,7 @@ static struct bin_attribute *sdsi_bin_attrs[] = {
};
static umode_t
-sdsi_battr_is_visible(struct kobject *kobj, struct bin_attribute *attr, int n)
+sdsi_battr_is_visible(struct kobject *kobj, const struct bin_attribute *attr, int n)
{
struct device *dev = kobj_to_dev(kobj);
struct sdsi_priv *priv = dev_get_drvdata(dev);
diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi.c
index 17972191538a..bcf0a5cbc68d 100644
--- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi.c
@@ -67,6 +67,6 @@ static struct auxiliary_driver intel_sst_aux_driver = {
module_auxiliary_driver(intel_sst_aux_driver);
-MODULE_IMPORT_NS(INTEL_TPMI_SST);
+MODULE_IMPORT_NS("INTEL_TPMI_SST");
MODULE_DESCRIPTION("Intel TPMI SST Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
index 404582307109..9978cdd19851 100644
--- a/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
+++ b/drivers/platform/x86/intel/speed_select_if/isst_tpmi_core.c
@@ -1593,7 +1593,7 @@ unlock_exit:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_sst_dev_add, INTEL_TPMI_SST);
+EXPORT_SYMBOL_NS_GPL(tpmi_sst_dev_add, "INTEL_TPMI_SST");
void tpmi_sst_dev_remove(struct auxiliary_device *auxdev)
{
@@ -1614,7 +1614,7 @@ void tpmi_sst_dev_remove(struct auxiliary_device *auxdev)
}
mutex_unlock(&isst_tpmi_dev_lock);
}
-EXPORT_SYMBOL_NS_GPL(tpmi_sst_dev_remove, INTEL_TPMI_SST);
+EXPORT_SYMBOL_NS_GPL(tpmi_sst_dev_remove, "INTEL_TPMI_SST");
void tpmi_sst_dev_suspend(struct auxiliary_device *auxdev)
{
@@ -1642,7 +1642,7 @@ void tpmi_sst_dev_suspend(struct auxiliary_device *auxdev)
power_domain_info->sst_header.pp_offset +
SST_PP_CONTROL_OFFSET);
}
-EXPORT_SYMBOL_NS_GPL(tpmi_sst_dev_suspend, INTEL_TPMI_SST);
+EXPORT_SYMBOL_NS_GPL(tpmi_sst_dev_suspend, "INTEL_TPMI_SST");
void tpmi_sst_dev_resume(struct auxiliary_device *auxdev)
{
@@ -1669,7 +1669,7 @@ void tpmi_sst_dev_resume(struct auxiliary_device *auxdev)
writeq(power_domain_info->saved_pp_control, power_domain_info->sst_base +
power_domain_info->sst_header.pp_offset + SST_PP_CONTROL_OFFSET);
}
-EXPORT_SYMBOL_NS_GPL(tpmi_sst_dev_resume, INTEL_TPMI_SST);
+EXPORT_SYMBOL_NS_GPL(tpmi_sst_dev_resume, "INTEL_TPMI_SST");
#define ISST_TPMI_API_VERSION 0x03
@@ -1709,7 +1709,7 @@ init_done:
mutex_unlock(&isst_tpmi_dev_lock);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_sst_init, INTEL_TPMI_SST);
+EXPORT_SYMBOL_NS_GPL(tpmi_sst_init, "INTEL_TPMI_SST");
void tpmi_sst_exit(void)
{
@@ -1723,10 +1723,10 @@ void tpmi_sst_exit(void)
}
mutex_unlock(&isst_tpmi_dev_lock);
}
-EXPORT_SYMBOL_NS_GPL(tpmi_sst_exit, INTEL_TPMI_SST);
+EXPORT_SYMBOL_NS_GPL(tpmi_sst_exit, "INTEL_TPMI_SST");
-MODULE_IMPORT_NS(INTEL_TPMI);
-MODULE_IMPORT_NS(INTEL_TPMI_POWER_DOMAIN);
+MODULE_IMPORT_NS("INTEL_TPMI");
+MODULE_IMPORT_NS("INTEL_TPMI_POWER_DOMAIN");
MODULE_DESCRIPTION("ISST TPMI interface module");
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel/tpmi_power_domains.c b/drivers/platform/x86/intel/tpmi_power_domains.c
index 0609a8320f7e..603e7ded06a9 100644
--- a/drivers/platform/x86/intel/tpmi_power_domains.c
+++ b/drivers/platform/x86/intel/tpmi_power_domains.c
@@ -110,7 +110,7 @@ int tpmi_get_linux_cpu_number(int package_id, int domain_id, int punit_core_id)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_get_linux_cpu_number, INTEL_TPMI_POWER_DOMAIN);
+EXPORT_SYMBOL_NS_GPL(tpmi_get_linux_cpu_number, "INTEL_TPMI_POWER_DOMAIN");
int tpmi_get_punit_core_number(int cpu_no)
{
@@ -119,7 +119,7 @@ int tpmi_get_punit_core_number(int cpu_no)
return per_cpu(tpmi_cpu_info, cpu_no).punit_core_id;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_get_punit_core_number, INTEL_TPMI_POWER_DOMAIN);
+EXPORT_SYMBOL_NS_GPL(tpmi_get_punit_core_number, "INTEL_TPMI_POWER_DOMAIN");
int tpmi_get_power_domain_id(int cpu_no)
{
@@ -128,7 +128,7 @@ int tpmi_get_power_domain_id(int cpu_no)
return per_cpu(tpmi_cpu_info, cpu_no).punit_domain_id;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_get_power_domain_id, INTEL_TPMI_POWER_DOMAIN);
+EXPORT_SYMBOL_NS_GPL(tpmi_get_power_domain_id, "INTEL_TPMI_POWER_DOMAIN");
cpumask_t *tpmi_get_power_domain_mask(int cpu_no)
{
@@ -149,7 +149,7 @@ cpumask_t *tpmi_get_power_domain_mask(int cpu_no)
return mask;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_get_power_domain_mask, INTEL_TPMI_POWER_DOMAIN);
+EXPORT_SYMBOL_NS_GPL(tpmi_get_power_domain_mask, "INTEL_TPMI_POWER_DOMAIN");
static int tpmi_get_logical_id(unsigned int cpu, struct tpmi_cpu_info *info)
{
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
index e22b683a7a43..4e2c6a2d7e6e 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-common.c
@@ -257,7 +257,7 @@ uncore_unlock:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(uncore_freq_add_entry, INTEL_UNCORE_FREQUENCY);
+EXPORT_SYMBOL_NS_GPL(uncore_freq_add_entry, "INTEL_UNCORE_FREQUENCY");
void uncore_freq_remove_die_entry(struct uncore_data *data)
{
@@ -270,7 +270,7 @@ void uncore_freq_remove_die_entry(struct uncore_data *data)
mutex_unlock(&uncore_lock);
}
-EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, INTEL_UNCORE_FREQUENCY);
+EXPORT_SYMBOL_NS_GPL(uncore_freq_remove_die_entry, "INTEL_UNCORE_FREQUENCY");
int uncore_freq_common_init(int (*read)(struct uncore_data *data, unsigned int *value,
enum uncore_index index),
@@ -297,7 +297,7 @@ int uncore_freq_common_init(int (*read)(struct uncore_data *data, unsigned int *
return uncore_root_kobj ? 0 : -ENOMEM;
}
-EXPORT_SYMBOL_NS_GPL(uncore_freq_common_init, INTEL_UNCORE_FREQUENCY);
+EXPORT_SYMBOL_NS_GPL(uncore_freq_common_init, "INTEL_UNCORE_FREQUENCY");
void uncore_freq_common_exit(void)
{
@@ -309,7 +309,7 @@ void uncore_freq_common_exit(void)
}
mutex_unlock(&uncore_lock);
}
-EXPORT_SYMBOL_NS_GPL(uncore_freq_common_exit, INTEL_UNCORE_FREQUENCY);
+EXPORT_SYMBOL_NS_GPL(uncore_freq_common_exit, "INTEL_UNCORE_FREQUENCY");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
index 0591053813a2..4aa6c227ec82 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency-tpmi.c
@@ -629,7 +629,7 @@ static struct auxiliary_driver intel_uncore_aux_driver = {
module_auxiliary_driver(intel_uncore_aux_driver);
-MODULE_IMPORT_NS(INTEL_TPMI);
-MODULE_IMPORT_NS(INTEL_UNCORE_FREQUENCY);
+MODULE_IMPORT_NS("INTEL_TPMI");
+MODULE_IMPORT_NS("INTEL_UNCORE_FREQUENCY");
MODULE_DESCRIPTION("Intel TPMI UFS Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
index a450b8a6bcec..40bbf8e45fa4 100644
--- a/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
+++ b/drivers/platform/x86/intel/uncore-frequency/uncore-frequency.c
@@ -316,6 +316,6 @@ static void __exit intel_uncore_exit(void)
}
module_exit(intel_uncore_exit)
-MODULE_IMPORT_NS(INTEL_UNCORE_FREQUENCY);
+MODULE_IMPORT_NS("INTEL_UNCORE_FREQUENCY");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel Uncore Frequency Limits Driver");
diff --git a/drivers/platform/x86/intel/vsec.c b/drivers/platform/x86/intel/vsec.c
index 9e0f8e38178c..8272f1dd0fbc 100644
--- a/drivers/platform/x86/intel/vsec.c
+++ b/drivers/platform/x86/intel/vsec.c
@@ -137,7 +137,7 @@ int intel_vsec_add_aux(struct pci_dev *pdev, struct device *parent,
return devm_add_action_or_reset(parent, intel_vsec_remove_aux,
auxdev);
}
-EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, INTEL_VSEC);
+EXPORT_SYMBOL_NS_GPL(intel_vsec_add_aux, "INTEL_VSEC");
static int intel_vsec_add_dev(struct pci_dev *pdev, struct intel_vsec_header *header,
struct intel_vsec_platform_info *info)
@@ -340,7 +340,7 @@ void intel_vsec_register(struct pci_dev *pdev,
intel_vsec_walk_header(pdev, info);
}
-EXPORT_SYMBOL_NS_GPL(intel_vsec_register, INTEL_VSEC);
+EXPORT_SYMBOL_NS_GPL(intel_vsec_register, "INTEL_VSEC");
static int intel_vsec_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
@@ -423,6 +423,7 @@ static const struct intel_vsec_platform_info lnl_info = {
#define PCI_DEVICE_ID_INTEL_VSEC_RPL 0xa77d
#define PCI_DEVICE_ID_INTEL_VSEC_TGL 0x9a0d
#define PCI_DEVICE_ID_INTEL_VSEC_LNL_M 0x647d
+#define PCI_DEVICE_ID_INTEL_VSEC_PTL 0xb07d
static const struct pci_device_id intel_vsec_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, VSEC_ADL, &tgl_info) },
{ PCI_DEVICE_DATA(INTEL, VSEC_DG1, &dg1_info) },
@@ -432,6 +433,7 @@ static const struct pci_device_id intel_vsec_pci_ids[] = {
{ PCI_DEVICE_DATA(INTEL, VSEC_RPL, &tgl_info) },
{ PCI_DEVICE_DATA(INTEL, VSEC_TGL, &tgl_info) },
{ PCI_DEVICE_DATA(INTEL, VSEC_LNL_M, &lnl_info) },
+ { PCI_DEVICE_DATA(INTEL, VSEC_PTL, &mtl_info) },
{ }
};
MODULE_DEVICE_TABLE(pci, intel_vsec_pci_ids);
diff --git a/drivers/platform/x86/intel/vsec_tpmi.c b/drivers/platform/x86/intel/vsec_tpmi.c
index c637e32048a3..5c383a27bbe8 100644
--- a/drivers/platform/x86/intel/vsec_tpmi.c
+++ b/drivers/platform/x86/intel/vsec_tpmi.c
@@ -193,7 +193,7 @@ struct intel_tpmi_plat_info *tpmi_get_platform_data(struct auxiliary_device *aux
return vsec_dev->priv_data;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_get_platform_data, INTEL_TPMI);
+EXPORT_SYMBOL_NS_GPL(tpmi_get_platform_data, "INTEL_TPMI");
int tpmi_get_resource_count(struct auxiliary_device *auxdev)
{
@@ -204,7 +204,7 @@ int tpmi_get_resource_count(struct auxiliary_device *auxdev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_count, INTEL_TPMI);
+EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_count, "INTEL_TPMI");
struct resource *tpmi_get_resource_at_index(struct auxiliary_device *auxdev, int index)
{
@@ -215,7 +215,7 @@ struct resource *tpmi_get_resource_at_index(struct auxiliary_device *auxdev, int
return NULL;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, INTEL_TPMI);
+EXPORT_SYMBOL_NS_GPL(tpmi_get_resource_at_index, "INTEL_TPMI");
/* TPMI Control Interface */
@@ -354,7 +354,7 @@ int tpmi_get_feature_status(struct auxiliary_device *auxdev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_get_feature_status, INTEL_TPMI);
+EXPORT_SYMBOL_NS_GPL(tpmi_get_feature_status, "INTEL_TPMI");
struct dentry *tpmi_get_debugfs_dir(struct auxiliary_device *auxdev)
{
@@ -363,7 +363,7 @@ struct dentry *tpmi_get_debugfs_dir(struct auxiliary_device *auxdev)
return tpmi_info->dbgfs_dir;
}
-EXPORT_SYMBOL_NS_GPL(tpmi_get_debugfs_dir, INTEL_TPMI);
+EXPORT_SYMBOL_NS_GPL(tpmi_get_debugfs_dir, "INTEL_TPMI");
static int tpmi_pfs_dbg_show(struct seq_file *s, void *unused)
{
@@ -852,6 +852,6 @@ static struct auxiliary_driver tpmi_aux_driver = {
module_auxiliary_driver(tpmi_aux_driver);
-MODULE_IMPORT_NS(INTEL_VSEC);
+MODULE_IMPORT_NS("INTEL_VSEC");
MODULE_DESCRIPTION("Intel TPMI enumeration module");
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/lenovo-ymc.c b/drivers/platform/x86/lenovo-ymc.c
index bd9f95404c7c..470d53e3c9d2 100644
--- a/drivers/platform/x86/lenovo-ymc.c
+++ b/drivers/platform/x86/lenovo-ymc.c
@@ -162,4 +162,4 @@ module_wmi_driver(lenovo_ymc_driver);
MODULE_AUTHOR("Gergo Koteles <soyer@irl.hu>");
MODULE_DESCRIPTION("Lenovo Yoga Mode Control driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IDEAPAD_LAPTOP);
+MODULE_IMPORT_NS("IDEAPAD_LAPTOP");
diff --git a/drivers/platform/x86/mlx-platform.c b/drivers/platform/x86/mlx-platform.c
index 671021cd1f59..9c7f30a47f1f 100644
--- a/drivers/platform/x86/mlx-platform.c
+++ b/drivers/platform/x86/mlx-platform.c
@@ -6237,6 +6237,7 @@ fail_pci_set_dma_mask:
fail_pci_request_regions:
pci_disable_device(pci_dev);
fail_pci_enable_device:
+ pci_dev_put(pci_dev);
return err;
}
@@ -6247,6 +6248,7 @@ mlxplat_pci_fpga_device_exit(struct pci_dev *pci_bridge,
iounmap(pci_bridge_addr);
pci_release_regions(pci_bridge);
pci_disable_device(pci_bridge);
+ pci_dev_put(pci_bridge);
}
static int
diff --git a/drivers/platform/x86/p2sb.c b/drivers/platform/x86/p2sb.c
index d51eb0db0626..cbbb0f809704 100644
--- a/drivers/platform/x86/p2sb.c
+++ b/drivers/platform/x86/p2sb.c
@@ -43,6 +43,7 @@ struct p2sb_res_cache {
};
static struct p2sb_res_cache p2sb_resources[NR_P2SB_RES_CACHE];
+static bool p2sb_hidden_by_bios;
static void p2sb_get_devfn(unsigned int *devfn)
{
@@ -97,6 +98,12 @@ static void p2sb_scan_and_cache_devfn(struct pci_bus *bus, unsigned int devfn)
static int p2sb_scan_and_cache(struct pci_bus *bus, unsigned int devfn)
{
+ /*
+ * The BIOS prevents the P2SB device from being enumerated by the PCI
+ * subsystem, so we need to unhide and hide it back to lookup the BAR.
+ */
+ pci_bus_write_config_dword(bus, devfn, P2SBC, 0);
+
/* Scan the P2SB device and cache its BAR0 */
p2sb_scan_and_cache_devfn(bus, devfn);
@@ -104,6 +111,8 @@ static int p2sb_scan_and_cache(struct pci_bus *bus, unsigned int devfn)
if (devfn == P2SB_DEVFN_GOLDMONT)
p2sb_scan_and_cache_devfn(bus, SPI_DEVFN_GOLDMONT);
+ pci_bus_write_config_dword(bus, devfn, P2SBC, P2SBC_HIDE);
+
if (!p2sb_valid_resource(&p2sb_resources[PCI_FUNC(devfn)].res))
return -ENOENT;
@@ -129,7 +138,7 @@ static int p2sb_cache_resources(void)
u32 value = P2SBC_HIDE;
struct pci_bus *bus;
u16 class;
- int ret;
+ int ret = 0;
/* Get devfn for P2SB device itself */
p2sb_get_devfn(&devfn_p2sb);
@@ -152,22 +161,53 @@ static int p2sb_cache_resources(void)
*/
pci_lock_rescan_remove();
+ pci_bus_read_config_dword(bus, devfn_p2sb, P2SBC, &value);
+ p2sb_hidden_by_bios = value & P2SBC_HIDE;
+
/*
- * The BIOS prevents the P2SB device from being enumerated by the PCI
- * subsystem, so we need to unhide and hide it back to lookup the BAR.
- * Unhide the P2SB device here, if needed.
+ * If the BIOS does not hide the P2SB device then its resources
+ * are accesilble. Cache them only if the P2SB device is hidden.
*/
- pci_bus_read_config_dword(bus, devfn_p2sb, P2SBC, &value);
- if (value & P2SBC_HIDE)
- pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, 0);
+ if (p2sb_hidden_by_bios)
+ ret = p2sb_scan_and_cache(bus, devfn_p2sb);
- ret = p2sb_scan_and_cache(bus, devfn_p2sb);
+ pci_unlock_rescan_remove();
- /* Hide the P2SB device, if it was hidden */
- if (value & P2SBC_HIDE)
- pci_bus_write_config_dword(bus, devfn_p2sb, P2SBC, P2SBC_HIDE);
+ return ret;
+}
- pci_unlock_rescan_remove();
+static int p2sb_read_from_cache(struct pci_bus *bus, unsigned int devfn,
+ struct resource *mem)
+{
+ struct p2sb_res_cache *cache = &p2sb_resources[PCI_FUNC(devfn)];
+
+ if (cache->bus_dev_id != bus->dev.id)
+ return -ENODEV;
+
+ if (!p2sb_valid_resource(&cache->res))
+ return -ENOENT;
+
+ memcpy(mem, &cache->res, sizeof(*mem));
+
+ return 0;
+}
+
+static int p2sb_read_from_dev(struct pci_bus *bus, unsigned int devfn,
+ struct resource *mem)
+{
+ struct pci_dev *pdev;
+ int ret = 0;
+
+ pdev = pci_get_slot(bus, devfn);
+ if (!pdev)
+ return -ENODEV;
+
+ if (p2sb_valid_resource(pci_resource_n(pdev, 0)))
+ p2sb_read_bar0(pdev, mem);
+ else
+ ret = -ENOENT;
+
+ pci_dev_put(pdev);
return ret;
}
@@ -188,8 +228,6 @@ static int p2sb_cache_resources(void)
*/
int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem)
{
- struct p2sb_res_cache *cache;
-
bus = p2sb_get_bus(bus);
if (!bus)
return -ENODEV;
@@ -197,15 +235,10 @@ int p2sb_bar(struct pci_bus *bus, unsigned int devfn, struct resource *mem)
if (!devfn)
p2sb_get_devfn(&devfn);
- cache = &p2sb_resources[PCI_FUNC(devfn)];
- if (cache->bus_dev_id != bus->dev.id)
- return -ENODEV;
+ if (p2sb_hidden_by_bios)
+ return p2sb_read_from_cache(bus, devfn, mem);
- if (!p2sb_valid_resource(&cache->res))
- return -ENOENT;
-
- memcpy(mem, &cache->res, sizeof(*mem));
- return 0;
+ return p2sb_read_from_dev(bus, devfn, mem);
}
EXPORT_SYMBOL_GPL(p2sb_bar);
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
index 0d3e3ca20b1b..decde4c9a3d9 100644
--- a/drivers/platform/x86/samsung-laptop.c
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -1653,5 +1653,5 @@ module_init(samsung_init);
module_exit(samsung_exit);
MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
-MODULE_DESCRIPTION("Samsung Backlight driver");
+MODULE_DESCRIPTION("Samsung Laptop driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/thinkpad_acpi.c b/drivers/platform/x86/thinkpad_acpi.c
index 6371a9f765c1..2cfb2ac3f465 100644
--- a/drivers/platform/x86/thinkpad_acpi.c
+++ b/drivers/platform/x86/thinkpad_acpi.c
@@ -184,7 +184,8 @@ enum tpacpi_hkey_event_t {
*/
TP_HKEY_EV_AMT_TOGGLE = 0x131a, /* Toggle AMT on/off */
TP_HKEY_EV_DOUBLETAP_TOGGLE = 0x131c, /* Toggle trackpoint doubletap on/off */
- TP_HKEY_EV_PROFILE_TOGGLE = 0x131f, /* Toggle platform profile */
+ TP_HKEY_EV_PROFILE_TOGGLE = 0x131f, /* Toggle platform profile in 2024 systems */
+ TP_HKEY_EV_PROFILE_TOGGLE2 = 0x1401, /* Toggle platform profile in 2025 + systems */
/* Reasons for waking up from S3/S4 */
TP_HKEY_EV_WKUP_S3_UNDOCK = 0x2304, /* undock requested, S3 */
@@ -11200,6 +11201,7 @@ static bool tpacpi_driver_event(const unsigned int hkey_event)
tp_features.trackpoint_doubletap = !tp_features.trackpoint_doubletap;
return true;
case TP_HKEY_EV_PROFILE_TOGGLE:
+ case TP_HKEY_EV_PROFILE_TOGGLE2:
platform_profile_cycle();
return true;
}
diff --git a/drivers/platform/x86/touchscreen_dmi.c b/drivers/platform/x86/touchscreen_dmi.c
index 0a39f68c641d..bdc19cd8d3ed 100644
--- a/drivers/platform/x86/touchscreen_dmi.c
+++ b/drivers/platform/x86/touchscreen_dmi.c
@@ -855,6 +855,23 @@ static const struct ts_dmi_data rwc_nanote_next_data = {
.properties = rwc_nanote_next_props,
};
+static const struct property_entry sary_tab_3_props[] = {
+ PROPERTY_ENTRY_U32("touchscreen-size-x", 1730),
+ PROPERTY_ENTRY_U32("touchscreen-size-y", 1151),
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-x"),
+ PROPERTY_ENTRY_BOOL("touchscreen-inverted-y"),
+ PROPERTY_ENTRY_BOOL("touchscreen-swapped-x-y"),
+ PROPERTY_ENTRY_STRING("firmware-name", "gsl1680-sary-tab-3.fw"),
+ PROPERTY_ENTRY_U32("silead,max-fingers", 10),
+ PROPERTY_ENTRY_BOOL("silead,home-button"),
+ { }
+};
+
+static const struct ts_dmi_data sary_tab_3_data = {
+ .acpi_name = "MSSL1680:00",
+ .properties = sary_tab_3_props,
+};
+
static const struct property_entry schneider_sct101ctm_props[] = {
PROPERTY_ENTRY_U32("touchscreen-size-x", 1715),
PROPERTY_ENTRY_U32("touchscreen-size-y", 1140),
@@ -1616,6 +1633,15 @@ const struct dmi_system_id touchscreen_dmi_table[] = {
},
},
{
+ /* SARY Tab 3 */
+ .driver_data = (void *)&sary_tab_3_data,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "SARY"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "C210C"),
+ DMI_MATCH(DMI_PRODUCT_SKU, "TAB3"),
+ },
+ },
+ {
/* Schneider SCT101CTM */
.driver_data = (void *)&schneider_sct101ctm_data,
.matches = {
diff --git a/drivers/pmdomain/core.c b/drivers/pmdomain/core.c
index a6c8b85dd024..20a9efebbcb7 100644
--- a/drivers/pmdomain/core.c
+++ b/drivers/pmdomain/core.c
@@ -2142,6 +2142,11 @@ static int genpd_set_default_power_state(struct generic_pm_domain *genpd)
return 0;
}
+static void genpd_provider_release(struct device *dev)
+{
+ /* nothing to be done here */
+}
+
static int genpd_alloc_data(struct generic_pm_domain *genpd)
{
struct genpd_governor_data *gd = NULL;
@@ -2172,8 +2177,25 @@ static int genpd_alloc_data(struct generic_pm_domain *genpd)
}
genpd->gd = gd;
- return 0;
+ device_initialize(&genpd->dev);
+ genpd->dev.release = genpd_provider_release;
+
+ if (!genpd_is_dev_name_fw(genpd)) {
+ dev_set_name(&genpd->dev, "%s", genpd->name);
+ } else {
+ ret = ida_alloc(&genpd_ida, GFP_KERNEL);
+ if (ret < 0)
+ goto put;
+
+ genpd->device_id = ret;
+ dev_set_name(&genpd->dev, "%s_%u", genpd->name, genpd->device_id);
+ }
+ return 0;
+put:
+ put_device(&genpd->dev);
+ if (genpd->free_states == genpd_free_default_power_state)
+ kfree(genpd->states);
free:
if (genpd_is_cpu_domain(genpd))
free_cpumask_var(genpd->cpus);
@@ -2183,6 +2205,9 @@ free:
static void genpd_free_data(struct generic_pm_domain *genpd)
{
+ put_device(&genpd->dev);
+ if (genpd->device_id != -ENXIO)
+ ida_free(&genpd_ida, genpd->device_id);
if (genpd_is_cpu_domain(genpd))
free_cpumask_var(genpd->cpus);
if (genpd->free_states)
@@ -2271,20 +2296,6 @@ int pm_genpd_init(struct generic_pm_domain *genpd,
if (ret)
return ret;
- device_initialize(&genpd->dev);
-
- if (!genpd_is_dev_name_fw(genpd)) {
- dev_set_name(&genpd->dev, "%s", genpd->name);
- } else {
- ret = ida_alloc(&genpd_ida, GFP_KERNEL);
- if (ret < 0) {
- put_device(&genpd->dev);
- return ret;
- }
- genpd->device_id = ret;
- dev_set_name(&genpd->dev, "%s_%u", genpd->name, genpd->device_id);
- }
-
mutex_lock(&gpd_list_lock);
list_add(&genpd->gpd_list_node, &gpd_list);
mutex_unlock(&gpd_list_lock);
@@ -2325,8 +2336,6 @@ static int genpd_remove(struct generic_pm_domain *genpd)
genpd_unlock(genpd);
genpd_debug_remove(genpd);
cancel_work_sync(&genpd->power_off_work);
- if (genpd->device_id != -ENXIO)
- ida_free(&genpd_ida, genpd->device_id);
genpd_free_data(genpd);
pr_debug("%s: removed %s\n", __func__, dev_name(&genpd->dev));
diff --git a/drivers/pmdomain/imx/gpc.c b/drivers/pmdomain/imx/gpc.c
index fbb4c90b72c4..f18c7e6e75dd 100644
--- a/drivers/pmdomain/imx/gpc.c
+++ b/drivers/pmdomain/imx/gpc.c
@@ -233,7 +233,7 @@ static struct platform_driver imx_pgc_power_domain_driver = {
.name = "imx-pgc-pd",
},
.probe = imx_pgc_power_domain_probe,
- .remove_new = imx_pgc_power_domain_remove,
+ .remove = imx_pgc_power_domain_remove,
.id_table = imx_pgc_power_domain_id,
};
builtin_platform_driver(imx_pgc_power_domain_driver)
@@ -545,6 +545,6 @@ static struct platform_driver imx_gpc_driver = {
.of_match_table = imx_gpc_dt_ids,
},
.probe = imx_gpc_probe,
- .remove_new = imx_gpc_remove,
+ .remove = imx_gpc_remove,
};
builtin_platform_driver(imx_gpc_driver)
diff --git a/drivers/pmdomain/imx/gpcv2.c b/drivers/pmdomain/imx/gpcv2.c
index 6e6ecbf2e152..9bdb80fd7210 100644
--- a/drivers/pmdomain/imx/gpcv2.c
+++ b/drivers/pmdomain/imx/gpcv2.c
@@ -403,7 +403,7 @@ static int imx_pgc_power_up(struct generic_pm_domain *genpd)
* already reaches target before udelay()
*/
regmap_read_bypassed(domain->regmap, domain->regs->hsk, &reg_val);
- udelay(5);
+ udelay(10);
}
/* Disable reset clocks for all devices in the domain */
@@ -1439,7 +1439,7 @@ static struct platform_driver imx_pgc_domain_driver = {
.pm = &imx_pgc_domain_pm_ops,
},
.probe = imx_pgc_domain_probe,
- .remove_new = imx_pgc_domain_remove,
+ .remove = imx_pgc_domain_remove,
.id_table = imx_pgc_domain_id,
};
builtin_platform_driver(imx_pgc_domain_driver)
@@ -1458,12 +1458,12 @@ static int imx_gpcv2_probe(struct platform_device *pdev)
.max_register = SZ_4K,
};
struct device *dev = &pdev->dev;
- struct device_node *pgc_np;
+ struct device_node *pgc_np __free(device_node) =
+ of_get_child_by_name(dev->of_node, "pgc");
struct regmap *regmap;
void __iomem *base;
int ret;
- pgc_np = of_get_child_by_name(dev->of_node, "pgc");
if (!pgc_np) {
dev_err(dev, "No power domains specified in DT\n");
return -EINVAL;
diff --git a/drivers/pmdomain/imx/imx8m-blk-ctrl.c b/drivers/pmdomain/imx/imx8m-blk-ctrl.c
index ca942d7929c2..23db85b7aa9e 100644
--- a/drivers/pmdomain/imx/imx8m-blk-ctrl.c
+++ b/drivers/pmdomain/imx/imx8m-blk-ctrl.c
@@ -889,7 +889,7 @@ MODULE_DEVICE_TABLE(of, imx8m_blk_ctrl_of_match);
static struct platform_driver imx8m_blk_ctrl_driver = {
.probe = imx8m_blk_ctrl_probe,
- .remove_new = imx8m_blk_ctrl_remove,
+ .remove = imx8m_blk_ctrl_remove,
.driver = {
.name = "imx8m-blk-ctrl",
.pm = &imx8m_blk_ctrl_pm_ops,
diff --git a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
index 77e889165eed..e3a0f64c144c 100644
--- a/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
+++ b/drivers/pmdomain/imx/imx8mp-blk-ctrl.c
@@ -857,7 +857,7 @@ MODULE_DEVICE_TABLE(of, imx8mp_blk_ctrl_of_match);
static struct platform_driver imx8mp_blk_ctrl_driver = {
.probe = imx8mp_blk_ctrl_probe,
- .remove_new = imx8mp_blk_ctrl_remove,
+ .remove = imx8mp_blk_ctrl_remove,
.driver = {
.name = "imx8mp-blk-ctrl",
.pm = &imx8mp_blk_ctrl_pm_ops,
diff --git a/drivers/pmdomain/imx/imx93-blk-ctrl.c b/drivers/pmdomain/imx/imx93-blk-ctrl.c
index b10348ac10f0..0e2ba8ec55d7 100644
--- a/drivers/pmdomain/imx/imx93-blk-ctrl.c
+++ b/drivers/pmdomain/imx/imx93-blk-ctrl.c
@@ -438,7 +438,7 @@ MODULE_DEVICE_TABLE(of, imx93_blk_ctrl_of_match);
static struct platform_driver imx93_blk_ctrl_driver = {
.probe = imx93_blk_ctrl_probe,
- .remove_new = imx93_blk_ctrl_remove,
+ .remove = imx93_blk_ctrl_remove,
.driver = {
.name = "imx93-blk-ctrl",
.of_match_table = imx93_blk_ctrl_of_match,
diff --git a/drivers/pmdomain/imx/imx93-pd.c b/drivers/pmdomain/imx/imx93-pd.c
index 25ab592945bd..d68273330687 100644
--- a/drivers/pmdomain/imx/imx93-pd.c
+++ b/drivers/pmdomain/imx/imx93-pd.c
@@ -162,7 +162,7 @@ static struct platform_driver imx93_power_domain_driver = {
.of_match_table = imx93_pd_ids,
},
.probe = imx93_pd_probe,
- .remove_new = imx93_pd_remove,
+ .remove = imx93_pd_remove,
};
module_platform_driver(imx93_power_domain_driver);
diff --git a/drivers/pmdomain/qcom/cpr.c b/drivers/pmdomain/qcom/cpr.c
index 26a60a101e42..3ee8184e4be3 100644
--- a/drivers/pmdomain/qcom/cpr.c
+++ b/drivers/pmdomain/qcom/cpr.c
@@ -1717,7 +1717,7 @@ MODULE_DEVICE_TABLE(of, cpr_match_table);
static struct platform_driver cpr_driver = {
.probe = cpr_probe,
- .remove_new = cpr_remove,
+ .remove = cpr_remove,
.driver = {
.name = "qcom-cpr",
.of_match_table = cpr_match_table,
diff --git a/drivers/pmdomain/xilinx/zynqmp-pm-domains.c b/drivers/pmdomain/xilinx/zynqmp-pm-domains.c
index 0b5831e5ba1b..d579220a4500 100644
--- a/drivers/pmdomain/xilinx/zynqmp-pm-domains.c
+++ b/drivers/pmdomain/xilinx/zynqmp-pm-domains.c
@@ -313,7 +313,7 @@ static struct platform_driver zynqmp_power_domain_driver = {
.sync_state = zynqmp_gpd_sync_state,
},
.probe = zynqmp_gpd_probe,
- .remove_new = zynqmp_gpd_remove,
+ .remove = zynqmp_gpd_remove,
};
module_platform_driver(zynqmp_power_domain_driver);
diff --git a/drivers/power/supply/bq24190_charger.c b/drivers/power/supply/bq24190_charger.c
index 2b393eb5c282..c47f32f152e6 100644
--- a/drivers/power/supply/bq24190_charger.c
+++ b/drivers/power/supply/bq24190_charger.c
@@ -567,6 +567,7 @@ static int bq24190_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)
static int bq24296_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)
{
+ union power_supply_propval val = { .intval = bdi->charge_type };
int ret;
ret = pm_runtime_resume_and_get(bdi->dev);
@@ -587,13 +588,18 @@ static int bq24296_set_otg_vbus(struct bq24190_dev_info *bdi, bool enable)
ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
BQ24296_REG_POC_OTG_CONFIG_MASK,
- BQ24296_REG_POC_CHG_CONFIG_SHIFT,
+ BQ24296_REG_POC_OTG_CONFIG_SHIFT,
BQ24296_REG_POC_OTG_CONFIG_OTG);
- } else
+ } else {
ret = bq24190_write_mask(bdi, BQ24190_REG_POC,
BQ24296_REG_POC_OTG_CONFIG_MASK,
- BQ24296_REG_POC_CHG_CONFIG_SHIFT,
+ BQ24296_REG_POC_OTG_CONFIG_SHIFT,
BQ24296_REG_POC_OTG_CONFIG_DISABLE);
+ if (ret < 0)
+ goto out;
+
+ ret = bq24190_charger_set_charge_type(bdi, &val);
+ }
out:
pm_runtime_mark_last_busy(bdi->dev);
diff --git a/drivers/power/supply/cros_charge-control.c b/drivers/power/supply/cros_charge-control.c
index 17c53591ce19..9b0a7500296b 100644
--- a/drivers/power/supply/cros_charge-control.c
+++ b/drivers/power/supply/cros_charge-control.c
@@ -7,8 +7,10 @@
#include <acpi/battery.h>
#include <linux/container_of.h>
#include <linux/dmi.h>
+#include <linux/lockdep.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
+#include <linux/mutex.h>
#include <linux/platform_data/cros_ec_commands.h>
#include <linux/platform_data/cros_ec_proto.h>
#include <linux/platform_device.h>
@@ -49,6 +51,7 @@ struct cros_chctl_priv {
struct attribute *attributes[_CROS_CHCTL_ATTR_COUNT];
struct attribute_group group;
+ struct mutex lock; /* protects fields below and cros_ec */
enum power_supply_charge_behaviour current_behaviour;
u8 current_start_threshold, current_end_threshold;
};
@@ -85,6 +88,8 @@ static int cros_chctl_configure_ec(struct cros_chctl_priv *priv)
{
struct ec_params_charge_control req = {};
+ lockdep_assert_held(&priv->lock);
+
req.cmd = EC_CHARGE_CONTROL_CMD_SET;
switch (priv->current_behaviour) {
@@ -134,11 +139,15 @@ static ssize_t cros_chctl_store_threshold(struct device *dev, struct cros_chctl_
return -EINVAL;
if (is_end_threshold) {
- if (val <= priv->current_start_threshold)
+ /* Start threshold is not exposed, use fixed value */
+ if (priv->cmd_version == 2)
+ priv->current_start_threshold = val == 100 ? 0 : val;
+
+ if (val < priv->current_start_threshold)
return -EINVAL;
priv->current_end_threshold = val;
} else {
- if (val >= priv->current_end_threshold)
+ if (val > priv->current_end_threshold)
return -EINVAL;
priv->current_start_threshold = val;
}
@@ -159,6 +168,7 @@ static ssize_t charge_control_start_threshold_show(struct device *dev,
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
CROS_CHCTL_ATTR_START_THRESHOLD);
+ guard(mutex)(&priv->lock);
return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_start_threshold);
}
@@ -169,6 +179,7 @@ static ssize_t charge_control_start_threshold_store(struct device *dev,
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
CROS_CHCTL_ATTR_START_THRESHOLD);
+ guard(mutex)(&priv->lock);
return cros_chctl_store_threshold(dev, priv, 0, buf, count);
}
@@ -178,6 +189,7 @@ static ssize_t charge_control_end_threshold_show(struct device *dev, struct devi
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
CROS_CHCTL_ATTR_END_THRESHOLD);
+ guard(mutex)(&priv->lock);
return sysfs_emit(buf, "%u\n", (unsigned int)priv->current_end_threshold);
}
@@ -187,6 +199,7 @@ static ssize_t charge_control_end_threshold_store(struct device *dev, struct dev
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
CROS_CHCTL_ATTR_END_THRESHOLD);
+ guard(mutex)(&priv->lock);
return cros_chctl_store_threshold(dev, priv, 1, buf, count);
}
@@ -195,6 +208,7 @@ static ssize_t charge_behaviour_show(struct device *dev, struct device_attribute
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(&attr->attr,
CROS_CHCTL_ATTR_CHARGE_BEHAVIOUR);
+ guard(mutex)(&priv->lock);
return power_supply_charge_behaviour_show(dev, EC_CHARGE_CONTROL_BEHAVIOURS,
priv->current_behaviour, buf);
}
@@ -210,6 +224,7 @@ static ssize_t charge_behaviour_store(struct device *dev, struct device_attribut
if (ret < 0)
return ret;
+ guard(mutex)(&priv->lock);
priv->current_behaviour = ret;
ret = cros_chctl_configure_ec(priv);
@@ -223,12 +238,10 @@ static umode_t cros_chtl_attr_is_visible(struct kobject *kobj, struct attribute
{
struct cros_chctl_priv *priv = cros_chctl_attr_to_priv(attr, n);
- if (priv->cmd_version < 2) {
- if (n == CROS_CHCTL_ATTR_START_THRESHOLD)
- return 0;
- if (n == CROS_CHCTL_ATTR_END_THRESHOLD)
- return 0;
- }
+ if (n == CROS_CHCTL_ATTR_START_THRESHOLD && priv->cmd_version < 3)
+ return 0;
+ else if (n == CROS_CHCTL_ATTR_END_THRESHOLD && priv->cmd_version < 2)
+ return 0;
return attr->mode;
}
@@ -290,6 +303,10 @@ static int cros_chctl_probe(struct platform_device *pdev)
if (!priv)
return -ENOMEM;
+ ret = devm_mutex_init(dev, &priv->lock);
+ if (ret)
+ return ret;
+
ret = cros_ec_get_cmd_versions(cros_ec, EC_CMD_CHARGE_CONTROL);
if (ret < 0)
return ret;
@@ -327,7 +344,8 @@ static int cros_chctl_probe(struct platform_device *pdev)
priv->current_end_threshold = 100;
/* Bring EC into well-known state */
- ret = cros_chctl_configure_ec(priv);
+ scoped_guard(mutex, &priv->lock)
+ ret = cros_chctl_configure_ec(priv);
if (ret < 0)
return ret;
diff --git a/drivers/power/supply/gpio-charger.c b/drivers/power/supply/gpio-charger.c
index 68212b39785b..6139f736ecbe 100644
--- a/drivers/power/supply/gpio-charger.c
+++ b/drivers/power/supply/gpio-charger.c
@@ -67,6 +67,14 @@ static int set_charge_current_limit(struct gpio_charger *gpio_charger, int val)
if (gpio_charger->current_limit_map[i].limit_ua <= val)
break;
}
+
+ /*
+ * If a valid charge current limit isn't found, default to smallest
+ * current limitation for safety reasons.
+ */
+ if (i >= gpio_charger->current_limit_map_size)
+ i = gpio_charger->current_limit_map_size - 1;
+
mapping = gpio_charger->current_limit_map[i];
for (i = 0; i < ndescs; i++) {
diff --git a/drivers/powercap/idle_inject.c b/drivers/powercap/idle_inject.c
index bafc59904ed3..04c212953ded 100644
--- a/drivers/powercap/idle_inject.c
+++ b/drivers/powercap/idle_inject.c
@@ -179,7 +179,7 @@ void idle_inject_set_duration(struct idle_inject_device *ii_dev,
if (!run_duration_us)
pr_debug("CPU is forced to 100 percent idle\n");
}
-EXPORT_SYMBOL_NS_GPL(idle_inject_set_duration, IDLE_INJECT);
+EXPORT_SYMBOL_NS_GPL(idle_inject_set_duration, "IDLE_INJECT");
/**
* idle_inject_get_duration - idle and run duration retrieval helper
@@ -194,7 +194,7 @@ void idle_inject_get_duration(struct idle_inject_device *ii_dev,
*run_duration_us = READ_ONCE(ii_dev->run_duration_us);
*idle_duration_us = READ_ONCE(ii_dev->idle_duration_us);
}
-EXPORT_SYMBOL_NS_GPL(idle_inject_get_duration, IDLE_INJECT);
+EXPORT_SYMBOL_NS_GPL(idle_inject_get_duration, "IDLE_INJECT");
/**
* idle_inject_set_latency - set the maximum latency allowed
@@ -206,7 +206,7 @@ void idle_inject_set_latency(struct idle_inject_device *ii_dev,
{
WRITE_ONCE(ii_dev->latency_us, latency_us);
}
-EXPORT_SYMBOL_NS_GPL(idle_inject_set_latency, IDLE_INJECT);
+EXPORT_SYMBOL_NS_GPL(idle_inject_set_latency, "IDLE_INJECT");
/**
* idle_inject_start - start idle injections
@@ -238,7 +238,7 @@ int idle_inject_start(struct idle_inject_device *ii_dev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(idle_inject_start, IDLE_INJECT);
+EXPORT_SYMBOL_NS_GPL(idle_inject_start, "IDLE_INJECT");
/**
* idle_inject_stop - stops idle injections
@@ -285,7 +285,7 @@ void idle_inject_stop(struct idle_inject_device *ii_dev)
cpu_hotplug_enable();
}
-EXPORT_SYMBOL_NS_GPL(idle_inject_stop, IDLE_INJECT);
+EXPORT_SYMBOL_NS_GPL(idle_inject_stop, "IDLE_INJECT");
/**
* idle_inject_setup - prepare the current task for idle injection
@@ -367,7 +367,7 @@ out_rollback:
return NULL;
}
-EXPORT_SYMBOL_NS_GPL(idle_inject_register_full, IDLE_INJECT);
+EXPORT_SYMBOL_NS_GPL(idle_inject_register_full, "IDLE_INJECT");
/**
* idle_inject_register - initialize idle injection on a set of CPUs
@@ -384,7 +384,7 @@ struct idle_inject_device *idle_inject_register(struct cpumask *cpumask)
{
return idle_inject_register_full(cpumask, NULL);
}
-EXPORT_SYMBOL_NS_GPL(idle_inject_register, IDLE_INJECT);
+EXPORT_SYMBOL_NS_GPL(idle_inject_register, "IDLE_INJECT");
/**
* idle_inject_unregister - unregister idle injection control device
@@ -405,7 +405,7 @@ void idle_inject_unregister(struct idle_inject_device *ii_dev)
kfree(ii_dev);
}
-EXPORT_SYMBOL_NS_GPL(idle_inject_unregister, IDLE_INJECT);
+EXPORT_SYMBOL_NS_GPL(idle_inject_unregister, "IDLE_INJECT");
static struct smp_hotplug_thread idle_inject_threads = {
.store = &idle_inject_thread.tsk,
diff --git a/drivers/powercap/intel_rapl_msr.c b/drivers/powercap/intel_rapl_msr.c
index cbe07450de93..2b81aabdb0db 100644
--- a/drivers/powercap/intel_rapl_msr.c
+++ b/drivers/powercap/intel_rapl_msr.c
@@ -213,7 +213,7 @@ MODULE_DEVICE_TABLE(platform, rapl_msr_ids);
static struct platform_driver intel_rapl_msr_driver = {
.probe = rapl_msr_probe,
- .remove_new = rapl_msr_remove,
+ .remove = rapl_msr_remove,
.id_table = rapl_msr_ids,
.driver = {
.name = "intel_rapl_msr",
diff --git a/drivers/powercap/intel_rapl_tpmi.c b/drivers/powercap/intel_rapl_tpmi.c
index 645fd1dc51a9..af2368f4db10 100644
--- a/drivers/powercap/intel_rapl_tpmi.c
+++ b/drivers/powercap/intel_rapl_tpmi.c
@@ -347,7 +347,7 @@ static struct auxiliary_driver intel_rapl_tpmi_driver = {
module_auxiliary_driver(intel_rapl_tpmi_driver)
-MODULE_IMPORT_NS(INTEL_TPMI);
+MODULE_IMPORT_NS("INTEL_TPMI");
MODULE_DESCRIPTION("Intel RAPL TPMI Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/pps/clients/pps-gpio.c b/drivers/pps/clients/pps-gpio.c
index 791fdc9326dd..634c3b2f8c26 100644
--- a/drivers/pps/clients/pps-gpio.c
+++ b/drivers/pps/clients/pps-gpio.c
@@ -239,7 +239,7 @@ MODULE_DEVICE_TABLE(of, pps_gpio_dt_ids);
static struct platform_driver pps_gpio_driver = {
.probe = pps_gpio_probe,
- .remove_new = pps_gpio_remove,
+ .remove = pps_gpio_remove,
.driver = {
.name = PPS_GPIO_NAME,
.of_match_table = pps_gpio_dt_ids,
diff --git a/drivers/ptp/ptp_clock.c b/drivers/ptp/ptp_clock.c
index c56cd0f63909..77a36e7bddd5 100644
--- a/drivers/ptp/ptp_clock.c
+++ b/drivers/ptp/ptp_clock.c
@@ -150,7 +150,8 @@ static int ptp_clock_adjtime(struct posix_clock *pc, struct __kernel_timex *tx)
if (ppb > ops->max_adj || ppb < -ops->max_adj)
return -ERANGE;
err = ops->adjfine(ops, tx->freq);
- ptp->dialed_frequency = tx->freq;
+ if (!err)
+ ptp->dialed_frequency = tx->freq;
} else if (tx->modes & ADJ_OFFSET) {
if (ops->adjphase) {
s32 max_phase_adj = ops->getmaxphase(ops);
diff --git a/drivers/ptp/ptp_clockmatrix.c b/drivers/ptp/ptp_clockmatrix.c
index b6f1941308b1..fbb3fa8fc60b 100644
--- a/drivers/ptp/ptp_clockmatrix.c
+++ b/drivers/ptp/ptp_clockmatrix.c
@@ -2471,7 +2471,7 @@ static struct platform_driver idtcm_driver = {
.name = "8a3400x-phc",
},
.probe = idtcm_probe,
- .remove_new = idtcm_remove,
+ .remove = idtcm_remove,
};
module_platform_driver(idtcm_driver);
diff --git a/drivers/ptp/ptp_dte.c b/drivers/ptp/ptp_dte.c
index 449ff90927be..847276c69008 100644
--- a/drivers/ptp/ptp_dte.c
+++ b/drivers/ptp/ptp_dte.c
@@ -327,7 +327,7 @@ static struct platform_driver ptp_dte_driver = {
.of_match_table = ptp_dte_of_match,
},
.probe = ptp_dte_probe,
- .remove_new = ptp_dte_remove,
+ .remove = ptp_dte_remove,
};
module_platform_driver(ptp_dte_driver);
diff --git a/drivers/ptp/ptp_fc3.c b/drivers/ptp/ptp_fc3.c
index 879b82f03535..cfced36c70bc 100644
--- a/drivers/ptp/ptp_fc3.c
+++ b/drivers/ptp/ptp_fc3.c
@@ -1003,7 +1003,7 @@ static struct platform_driver idtfc3_driver = {
.name = "rc38xxx-phc",
},
.probe = idtfc3_probe,
- .remove_new = idtfc3_remove,
+ .remove = idtfc3_remove,
};
module_platform_driver(idtfc3_driver);
diff --git a/drivers/ptp/ptp_idt82p33.c b/drivers/ptp/ptp_idt82p33.c
index d5732490ed9d..b2fd94d4f863 100644
--- a/drivers/ptp/ptp_idt82p33.c
+++ b/drivers/ptp/ptp_idt82p33.c
@@ -1461,7 +1461,7 @@ static struct platform_driver idt82p33_driver = {
.name = "82p33x1x-phc",
},
.probe = idt82p33_probe,
- .remove_new = idt82p33_remove,
+ .remove = idt82p33_remove,
};
module_platform_driver(idt82p33_driver);
diff --git a/drivers/ptp/ptp_ines.c b/drivers/ptp/ptp_ines.c
index 14a23d3a27f2..68f1f7fdaa9d 100644
--- a/drivers/ptp/ptp_ines.c
+++ b/drivers/ptp/ptp_ines.c
@@ -782,7 +782,7 @@ MODULE_DEVICE_TABLE(of, ines_ptp_ctrl_of_match);
static struct platform_driver ines_ptp_ctrl_driver = {
.probe = ines_ptp_ctrl_probe,
- .remove_new = ines_ptp_ctrl_remove,
+ .remove = ines_ptp_ctrl_remove,
.driver = {
.name = "ines_ptp_ctrl",
.of_match_table = ines_ptp_ctrl_of_match,
diff --git a/drivers/ptp/ptp_kvm_x86.c b/drivers/ptp/ptp_kvm_x86.c
index 617c8d6706d3..6cea4fe39bcf 100644
--- a/drivers/ptp/ptp_kvm_x86.c
+++ b/drivers/ptp/ptp_kvm_x86.c
@@ -26,7 +26,7 @@ int kvm_arch_ptp_init(void)
long ret;
if (!kvm_para_available())
- return -ENODEV;
+ return -EOPNOTSUPP;
if (cc_platform_has(CC_ATTR_GUEST_MEM_ENCRYPT)) {
p = alloc_page(GFP_KERNEL | __GFP_ZERO);
@@ -46,14 +46,14 @@ int kvm_arch_ptp_init(void)
clock_pair_gpa = slow_virt_to_phys(clock_pair);
if (!pvclock_get_pvti_cpu0_va()) {
- ret = -ENODEV;
+ ret = -EOPNOTSUPP;
goto err;
}
ret = kvm_hypercall2(KVM_HC_CLOCK_PAIRING, clock_pair_gpa,
KVM_CLOCK_PAIRING_WALLCLOCK);
if (ret == -KVM_ENOSYS) {
- ret = -ENODEV;
+ ret = -EOPNOTSUPP;
goto err;
}
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 5feecaadde8e..7f08c70d8123 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -3692,7 +3692,7 @@ DEVICE_FREQ_GROUP(freq4, 3);
static ssize_t
disciplining_config_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
@@ -3727,7 +3727,7 @@ out:
static ssize_t
disciplining_config_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
@@ -3750,11 +3750,11 @@ disciplining_config_write(struct file *filp, struct kobject *kobj,
return err;
}
-static BIN_ATTR_RW(disciplining_config, OCP_ART_CONFIG_SIZE);
+static const BIN_ATTR_RW(disciplining_config, OCP_ART_CONFIG_SIZE);
static ssize_t
temperature_table_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
@@ -3789,7 +3789,7 @@ out:
static ssize_t
temperature_table_write(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr, char *buf,
+ const struct bin_attribute *bin_attr, char *buf,
loff_t off, size_t count)
{
struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
@@ -3812,7 +3812,7 @@ temperature_table_write(struct file *filp, struct kobject *kobj,
return err;
}
-static BIN_ATTR_RW(temperature_table, OCP_ART_TEMP_TABLE_SIZE);
+static const BIN_ATTR_RW(temperature_table, OCP_ART_TEMP_TABLE_SIZE);
static struct attribute *fb_timecard_attrs[] = {
&dev_attr_serialnum.attr,
@@ -3867,7 +3867,7 @@ static struct attribute *art_timecard_attrs[] = {
NULL,
};
-static struct bin_attribute *bin_art_timecard_attrs[] = {
+static const struct bin_attribute *const bin_art_timecard_attrs[] = {
&bin_attr_disciplining_config,
&bin_attr_temperature_table,
NULL,
@@ -3875,7 +3875,7 @@ static struct bin_attribute *bin_art_timecard_attrs[] = {
static const struct attribute_group art_timecard_group = {
.attrs = art_timecard_attrs,
- .bin_attrs = bin_art_timecard_attrs,
+ .bin_attrs_new = bin_art_timecard_attrs,
};
static const struct ocp_attr_group art_timecard_groups[] = {
diff --git a/drivers/ptp/ptp_qoriq.c b/drivers/ptp/ptp_qoriq.c
index 879cfc1537ac..4d488c1f1941 100644
--- a/drivers/ptp/ptp_qoriq.c
+++ b/drivers/ptp/ptp_qoriq.c
@@ -670,7 +670,7 @@ static struct platform_driver ptp_qoriq_driver = {
.of_match_table = match_table,
},
.probe = ptp_qoriq_probe,
- .remove_new = ptp_qoriq_remove,
+ .remove = ptp_qoriq_remove,
};
module_platform_driver(ptp_qoriq_driver);
diff --git a/drivers/ptp/ptp_vmclock.c b/drivers/ptp/ptp_vmclock.c
index cdca8a3ad1aa..0a2cfc8ad3c5 100644
--- a/drivers/ptp/ptp_vmclock.c
+++ b/drivers/ptp/ptp_vmclock.c
@@ -601,7 +601,7 @@ MODULE_DEVICE_TABLE(acpi, vmclock_acpi_ids);
static struct platform_driver vmclock_platform_driver = {
.probe = vmclock_probe,
- .remove_new = vmclock_remove,
+ .remove = vmclock_remove,
.driver = {
.name = "vmclock",
.acpi_match_table = vmclock_acpi_ids,
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 9c733877e98e..675b252d9c8c 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -6,7 +6,7 @@
* Copyright (C) 2011-2012 Avionic Design GmbH
*/
-#define DEFAULT_SYMBOL_NAMESPACE PWM
+#define DEFAULT_SYMBOL_NAMESPACE "PWM"
#include <linux/acpi.h>
#include <linux/module.h>
diff --git a/drivers/pwm/pwm-dwc-core.c b/drivers/pwm/pwm-dwc-core.c
index c8425493b95d..6dabec93a3c6 100644
--- a/drivers/pwm/pwm-dwc-core.c
+++ b/drivers/pwm/pwm-dwc-core.c
@@ -9,7 +9,7 @@
* Author: Raymond Tan <raymond.tan@intel.com>
*/
-#define DEFAULT_SYMBOL_NAMESPACE dwc_pwm
+#define DEFAULT_SYMBOL_NAMESPACE "dwc_pwm"
#include <linux/bitops.h>
#include <linux/export.h>
diff --git a/drivers/pwm/pwm-dwc.h b/drivers/pwm/pwm-dwc.h
index c6e2df5a6122..1562594e7f85 100644
--- a/drivers/pwm/pwm-dwc.h
+++ b/drivers/pwm/pwm-dwc.h
@@ -9,7 +9,7 @@
* Author: Raymond Tan <raymond.tan@intel.com>
*/
-MODULE_IMPORT_NS(dwc_pwm);
+MODULE_IMPORT_NS("dwc_pwm");
#define DWC_TIM_LD_CNT(n) ((n) * 0x14)
#define DWC_TIM_LD_CNT2(n) (((n) * 4) + 0xb0)
diff --git a/drivers/pwm/pwm-lpss-pci.c b/drivers/pwm/pwm-lpss-pci.c
index f7ece2809e6b..ddc2a4ca90fd 100644
--- a/drivers/pwm/pwm-lpss-pci.c
+++ b/drivers/pwm/pwm-lpss-pci.c
@@ -70,4 +70,4 @@ module_pci_driver(pwm_lpss_driver_pci);
MODULE_DESCRIPTION("PWM PCI driver for Intel LPSS");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PWM_LPSS);
+MODULE_IMPORT_NS("PWM_LPSS");
diff --git a/drivers/pwm/pwm-lpss-platform.c b/drivers/pwm/pwm-lpss-platform.c
index 5130238a4567..653ec9d0c8bf 100644
--- a/drivers/pwm/pwm-lpss-platform.c
+++ b/drivers/pwm/pwm-lpss-platform.c
@@ -78,5 +78,5 @@ module_platform_driver(pwm_lpss_driver_platform);
MODULE_DESCRIPTION("PWM platform driver for Intel LPSS");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(PWM_LPSS);
+MODULE_IMPORT_NS("PWM_LPSS");
MODULE_ALIAS("platform:pwm-lpss");
diff --git a/drivers/pwm/pwm-lpss.c b/drivers/pwm/pwm-lpss.c
index 867e2bc8c601..3b99feb3bb49 100644
--- a/drivers/pwm/pwm-lpss.c
+++ b/drivers/pwm/pwm-lpss.c
@@ -19,7 +19,7 @@
#include <linux/pm_runtime.h>
#include <linux/time.h>
-#define DEFAULT_SYMBOL_NAMESPACE PWM_LPSS
+#define DEFAULT_SYMBOL_NAMESPACE "PWM_LPSS"
#include "pwm-lpss.h"
diff --git a/drivers/pwm/pwm-stm32.c b/drivers/pwm/pwm-stm32.c
index b889e64522c3..17e591f61efb 100644
--- a/drivers/pwm/pwm-stm32.c
+++ b/drivers/pwm/pwm-stm32.c
@@ -84,7 +84,7 @@ static int stm32_pwm_round_waveform_tohw(struct pwm_chip *chip,
wfhw->ccer = TIM_CCER_CCxE(ch + 1);
if (priv->have_complementary_output)
- wfhw->ccer = TIM_CCER_CCxNE(ch + 1);
+ wfhw->ccer |= TIM_CCER_CCxNE(ch + 1);
rate = clk_get_rate(priv->clk);
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index e3cc59b82ea6..dca99cfb7cbb 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -371,8 +371,8 @@
.ops = &axp20x_ops, \
}
-#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
- _vmask, _ereg, _emask) \
+#define AXP_DESC_DELAY(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, _ramp_delay) \
[_family##_##_id] = { \
.name = (_match), \
.supply_name = (_supply), \
@@ -388,9 +388,15 @@
.vsel_mask = (_vmask), \
.enable_reg = (_ereg), \
.enable_mask = (_emask), \
+ .ramp_delay = (_ramp_delay), \
.ops = &axp20x_ops, \
}
+#define AXP_DESC(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask) \
+ AXP_DESC_DELAY(_family, _id, _match, _supply, _min, _max, _step, _vreg, \
+ _vmask, _ereg, _emask, 0)
+
#define AXP_DESC_SW(_family, _id, _match, _supply, _ereg, _emask) \
[_family##_##_id] = { \
.name = (_match), \
@@ -419,8 +425,8 @@
.ops = &axp20x_ops_fixed \
}
-#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages, \
- _vreg, _vmask, _ereg, _emask) \
+#define AXP_DESC_RANGES_DELAY(_family, _id, _match, _supply, _ranges, _n_voltages, \
+ _vreg, _vmask, _ereg, _emask, _ramp_delay) \
[_family##_##_id] = { \
.name = (_match), \
.supply_name = (_supply), \
@@ -436,9 +442,15 @@
.enable_mask = (_emask), \
.linear_ranges = (_ranges), \
.n_linear_ranges = ARRAY_SIZE(_ranges), \
+ .ramp_delay = (_ramp_delay), \
.ops = &axp20x_ops_range, \
}
+#define AXP_DESC_RANGES(_family, _id, _match, _supply, _ranges, _n_voltages, \
+ _vreg, _vmask, _ereg, _emask) \
+ AXP_DESC_RANGES_DELAY(_family, _id, _match, _supply, _ranges, \
+ _n_voltages, _vreg, _vmask, _ereg, _emask, 0)
+
static const int axp209_dcdc2_ldo3_slew_rates[] = {
1600,
800,
@@ -781,21 +793,21 @@ static const struct linear_range axp717_dcdc3_ranges[] = {
};
static const struct regulator_desc axp717_regulators[] = {
- AXP_DESC_RANGES(AXP717, DCDC1, "dcdc1", "vin1",
+ AXP_DESC_RANGES_DELAY(AXP717, DCDC1, "dcdc1", "vin1",
axp717_dcdc1_ranges, AXP717_DCDC1_NUM_VOLTAGES,
AXP717_DCDC1_CONTROL, AXP717_DCDC_V_OUT_MASK,
- AXP717_DCDC_OUTPUT_CONTROL, BIT(0)),
- AXP_DESC_RANGES(AXP717, DCDC2, "dcdc2", "vin2",
+ AXP717_DCDC_OUTPUT_CONTROL, BIT(0), 640),
+ AXP_DESC_RANGES_DELAY(AXP717, DCDC2, "dcdc2", "vin2",
axp717_dcdc2_ranges, AXP717_DCDC2_NUM_VOLTAGES,
AXP717_DCDC2_CONTROL, AXP717_DCDC_V_OUT_MASK,
- AXP717_DCDC_OUTPUT_CONTROL, BIT(1)),
- AXP_DESC_RANGES(AXP717, DCDC3, "dcdc3", "vin3",
+ AXP717_DCDC_OUTPUT_CONTROL, BIT(1), 640),
+ AXP_DESC_RANGES_DELAY(AXP717, DCDC3, "dcdc3", "vin3",
axp717_dcdc3_ranges, AXP717_DCDC3_NUM_VOLTAGES,
AXP717_DCDC3_CONTROL, AXP717_DCDC_V_OUT_MASK,
- AXP717_DCDC_OUTPUT_CONTROL, BIT(2)),
- AXP_DESC(AXP717, DCDC4, "dcdc4", "vin4", 1000, 3700, 100,
+ AXP717_DCDC_OUTPUT_CONTROL, BIT(2), 640),
+ AXP_DESC_DELAY(AXP717, DCDC4, "dcdc4", "vin4", 1000, 3700, 100,
AXP717_DCDC4_CONTROL, AXP717_DCDC_V_OUT_MASK,
- AXP717_DCDC_OUTPUT_CONTROL, BIT(3)),
+ AXP717_DCDC_OUTPUT_CONTROL, BIT(3), 6400),
AXP_DESC(AXP717, ALDO1, "aldo1", "aldoin", 500, 3500, 100,
AXP717_ALDO1_CONTROL, AXP717_LDO_V_OUT_MASK,
AXP717_LDO0_OUTPUT_CONTROL, BIT(0)),
diff --git a/drivers/regulator/of_regulator.c b/drivers/regulator/of_regulator.c
index 3d85762beda6..e5b4b93c07e3 100644
--- a/drivers/regulator/of_regulator.c
+++ b/drivers/regulator/of_regulator.c
@@ -175,7 +175,7 @@ static int of_get_regulation_constraints(struct device *dev,
if (!ret)
constraints->enable_time = pval;
- ret = of_property_read_u32(np, "regulator-uv-survival-time-ms", &pval);
+ ret = of_property_read_u32(np, "regulator-uv-less-critical-window-ms", &pval);
if (!ret)
constraints->uv_less_critical_window_ms = pval;
else
diff --git a/drivers/reset/amlogic/reset-meson-audio-arb.c b/drivers/reset/amlogic/reset-meson-audio-arb.c
index 421ccb40da8c..6ec253976bed 100644
--- a/drivers/reset/amlogic/reset-meson-audio-arb.c
+++ b/drivers/reset/amlogic/reset-meson-audio-arb.c
@@ -180,7 +180,7 @@ static int meson_audio_arb_probe(struct platform_device *pdev)
static struct platform_driver meson_audio_arb_pdrv = {
.probe = meson_audio_arb_probe,
- .remove_new = meson_audio_arb_remove,
+ .remove = meson_audio_arb_remove,
.driver = {
.name = "meson-audio-arb-reset",
.of_match_table = meson_audio_arb_of_match,
diff --git a/drivers/reset/amlogic/reset-meson-aux.c b/drivers/reset/amlogic/reset-meson-aux.c
index dd8453001db9..61ce515d92a2 100644
--- a/drivers/reset/amlogic/reset-meson-aux.c
+++ b/drivers/reset/amlogic/reset-meson-aux.c
@@ -133,4 +133,4 @@ EXPORT_SYMBOL_GPL(devm_meson_rst_aux_register);
MODULE_DESCRIPTION("Amlogic Meson Reset Auxiliary driver");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_IMPORT_NS(MESON_RESET);
+MODULE_IMPORT_NS("MESON_RESET");
diff --git a/drivers/reset/amlogic/reset-meson-common.c b/drivers/reset/amlogic/reset-meson-common.c
index 38a767c06fc7..a90e0ecaaadf 100644
--- a/drivers/reset/amlogic/reset-meson-common.c
+++ b/drivers/reset/amlogic/reset-meson-common.c
@@ -105,7 +105,7 @@ const struct reset_control_ops meson_reset_ops = {
.deassert = meson_reset_deassert,
.status = meson_reset_status,
};
-EXPORT_SYMBOL_NS_GPL(meson_reset_ops, MESON_RESET);
+EXPORT_SYMBOL_NS_GPL(meson_reset_ops, "MESON_RESET");
const struct reset_control_ops meson_reset_toggle_ops = {
.reset = meson_reset_level_toggle,
@@ -113,7 +113,7 @@ const struct reset_control_ops meson_reset_toggle_ops = {
.deassert = meson_reset_deassert,
.status = meson_reset_status,
};
-EXPORT_SYMBOL_NS_GPL(meson_reset_toggle_ops, MESON_RESET);
+EXPORT_SYMBOL_NS_GPL(meson_reset_toggle_ops, "MESON_RESET");
int meson_reset_controller_register(struct device *dev, struct regmap *map,
const struct meson_reset_param *param)
@@ -133,10 +133,10 @@ int meson_reset_controller_register(struct device *dev, struct regmap *map,
return devm_reset_controller_register(dev, &data->rcdev);
}
-EXPORT_SYMBOL_NS_GPL(meson_reset_controller_register, MESON_RESET);
+EXPORT_SYMBOL_NS_GPL(meson_reset_controller_register, "MESON_RESET");
MODULE_DESCRIPTION("Amlogic Meson Reset Core function");
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_IMPORT_NS(MESON_RESET);
+MODULE_IMPORT_NS("MESON_RESET");
diff --git a/drivers/reset/amlogic/reset-meson.c b/drivers/reset/amlogic/reset-meson.c
index 6ae4ed6b7f8b..84610365a823 100644
--- a/drivers/reset/amlogic/reset-meson.c
+++ b/drivers/reset/amlogic/reset-meson.c
@@ -102,4 +102,4 @@ MODULE_DESCRIPTION("Amlogic Meson Reset Controller driver");
MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_IMPORT_NS(MESON_RESET);
+MODULE_IMPORT_NS("MESON_RESET");
diff --git a/drivers/reset/reset-mpfs.c b/drivers/reset/reset-mpfs.c
index 710f9c1676f9..574e59db83a4 100644
--- a/drivers/reset/reset-mpfs.c
+++ b/drivers/reset/reset-mpfs.c
@@ -212,7 +212,7 @@ int mpfs_reset_controller_register(struct device *clk_dev, void __iomem *base)
return devm_add_action_or_reset(clk_dev, mpfs_reset_unregister_adev, adev);
}
-EXPORT_SYMBOL_NS_GPL(mpfs_reset_controller_register, MCHP_CLK_MPFS);
+EXPORT_SYMBOL_NS_GPL(mpfs_reset_controller_register, "MCHP_CLK_MPFS");
static const struct auxiliary_device_id mpfs_reset_ids[] = {
{
@@ -231,4 +231,4 @@ module_auxiliary_driver(mpfs_reset_driver);
MODULE_DESCRIPTION("Microchip PolarFire SoC Reset Driver");
MODULE_AUTHOR("Conor Dooley <conor.dooley@microchip.com>");
-MODULE_IMPORT_NS(MCHP_CLK_MPFS);
+MODULE_IMPORT_NS("MCHP_CLK_MPFS");
diff --git a/drivers/reset/reset-rzg2l-usbphy-ctrl.c b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
index 1cd157f4f03b..12d0535a874b 100644
--- a/drivers/reset/reset-rzg2l-usbphy-ctrl.c
+++ b/drivers/reset/reset-rzg2l-usbphy-ctrl.c
@@ -208,7 +208,7 @@ static struct platform_driver rzg2l_usbphy_ctrl_driver = {
.of_match_table = rzg2l_usbphy_ctrl_match_table,
},
.probe = rzg2l_usbphy_ctrl_probe,
- .remove_new = rzg2l_usbphy_ctrl_remove,
+ .remove = rzg2l_usbphy_ctrl_remove,
};
module_platform_driver(rzg2l_usbphy_ctrl_driver);
diff --git a/drivers/reset/reset-ti-sci.c b/drivers/reset/reset-ti-sci.c
index d384da0982fa..1dc5b766aac1 100644
--- a/drivers/reset/reset-ti-sci.c
+++ b/drivers/reset/reset-ti-sci.c
@@ -246,7 +246,7 @@ static void ti_sci_reset_remove(struct platform_device *pdev)
static struct platform_driver ti_sci_reset_driver = {
.probe = ti_sci_reset_probe,
- .remove_new = ti_sci_reset_remove,
+ .remove = ti_sci_reset_remove,
.driver = {
.name = "ti-sci-reset",
.of_match_table = ti_sci_reset_of_match,
diff --git a/drivers/rpmsg/qcom_glink_rpm.c b/drivers/rpmsg/qcom_glink_rpm.c
index 357272d7062e..e3ba2c63a5fc 100644
--- a/drivers/rpmsg/qcom_glink_rpm.c
+++ b/drivers/rpmsg/qcom_glink_rpm.c
@@ -381,7 +381,7 @@ MODULE_DEVICE_TABLE(of, glink_rpm_of_match);
static struct platform_driver glink_rpm_driver = {
.probe = glink_rpm_probe,
- .remove_new = glink_rpm_remove,
+ .remove = glink_rpm_remove,
.driver = {
.name = "qcom_glink_rpm",
.of_match_table = glink_rpm_of_match,
diff --git a/drivers/rpmsg/qcom_smd.c b/drivers/rpmsg/qcom_smd.c
index 43f601c84b4f..40d386809d6b 100644
--- a/drivers/rpmsg/qcom_smd.c
+++ b/drivers/rpmsg/qcom_smd.c
@@ -1596,7 +1596,7 @@ MODULE_DEVICE_TABLE(of, qcom_smd_of_match);
static struct platform_driver qcom_smd_driver = {
.probe = qcom_smd_probe,
- .remove_new = qcom_smd_remove,
+ .remove = qcom_smd_remove,
.driver = {
.name = "qcom-smd",
.of_match_table = qcom_smd_of_match,
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 66eb1122248b..a60bcc791a48 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -182,6 +182,16 @@ config RTC_DRV_88PM80X
This driver can also be built as a module. If so, the module
will be called rtc-88pm80x.
+config RTC_DRV_88PM886
+ tristate "Marvell 88PM886 RTC driver"
+ depends on MFD_88PM886_PMIC
+ help
+ If you say yes here you will get support for the RTC function in the
+ Marvell 88PM886 chip.
+
+ This driver can also be built as a module. If so, the module
+ will be called rtc-88pm886.
+
config RTC_DRV_ABB5ZES3
select REGMAP_I2C
tristate "Abracon AB-RTCMC-32.768kHz-B5ZE-S3"
@@ -496,6 +506,7 @@ config RTC_DRV_PCF85363
config RTC_DRV_PCF8563
tristate "Philips PCF8563/Epson RTC8564"
+ select REGMAP_I2C
help
If you say yes here you get support for the
Philips PCF8563 RTC chip. The Epson RTC8564
@@ -2005,6 +2016,16 @@ config RTC_DRV_MA35D1
This driver can also be built as a module, if so, the module
will be called "rtc-ma35d1".
+config RTC_DRV_RENESAS_RTCA3
+ tristate "Renesas RTCA-3 RTC"
+ depends on ARCH_RENESAS
+ help
+ If you say yes here you get support for the Renesas RTCA-3 RTC
+ available on the Renesas RZ/G3S SoC.
+
+ This driver can also be built as a module, if so, the module
+ will be called "rtc-rtca3".
+
comment "HID Sensor RTC drivers"
config RTC_DRV_HID_SENSOR_TIME
@@ -2070,4 +2091,16 @@ config RTC_DRV_SSD202D
This driver can also be built as a module, if so, the module
will be called "rtc-ssd20xd".
+config RTC_DRV_AMLOGIC_A4
+ tristate "Amlogic RTC"
+ depends on ARCH_MESON || COMPILE_TEST
+ select REGMAP_MMIO
+ default y
+ help
+ If you say yes here you get support for the RTC block on the
+ Amlogic A113L2(A4) and A113X2(A5) SoCs.
+
+ This driver can also be built as a module. If so, the module
+ will be called "rtc-amlogic-a4".
+
endif # RTC_CLASS
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile
index f62340ecc534..489b4ab07068 100644
--- a/drivers/rtc/Makefile
+++ b/drivers/rtc/Makefile
@@ -21,11 +21,13 @@ obj-$(CONFIG_RTC_LIB_KUNIT_TEST) += lib_test.o
obj-$(CONFIG_RTC_DRV_88PM80X) += rtc-88pm80x.o
obj-$(CONFIG_RTC_DRV_88PM860X) += rtc-88pm860x.o
+obj-$(CONFIG_RTC_DRV_88PM886) += rtc-88pm886.o
obj-$(CONFIG_RTC_DRV_AB8500) += rtc-ab8500.o
obj-$(CONFIG_RTC_DRV_ABB5ZES3) += rtc-ab-b5ze-s3.o
obj-$(CONFIG_RTC_DRV_ABEOZ9) += rtc-ab-eoz9.o
obj-$(CONFIG_RTC_DRV_ABX80X) += rtc-abx80x.o
obj-$(CONFIG_RTC_DRV_AC100) += rtc-ac100.o
+obj-$(CONFIG_RTC_DRV_AMLOGIC_A4) += rtc-amlogic-a4.o
obj-$(CONFIG_RTC_DRV_ARMADA38X) += rtc-armada38x.o
obj-$(CONFIG_RTC_DRV_AS3722) += rtc-as3722.o
obj-$(CONFIG_RTC_DRV_ASM9260) += rtc-asm9260.o
@@ -158,13 +160,14 @@ obj-$(CONFIG_RTC_DRV_RX8025) += rtc-rx8025.o
obj-$(CONFIG_RTC_DRV_RX8111) += rtc-rx8111.o
obj-$(CONFIG_RTC_DRV_RX8581) += rtc-rx8581.o
obj-$(CONFIG_RTC_DRV_RZN1) += rtc-rzn1.o
+obj-$(CONFIG_RTC_DRV_RENESAS_RTCA3) += rtc-renesas-rtca3.o
obj-$(CONFIG_RTC_DRV_S35390A) += rtc-s35390a.o
obj-$(CONFIG_RTC_DRV_S3C) += rtc-s3c.o
obj-$(CONFIG_RTC_DRV_S5M) += rtc-s5m.o
obj-$(CONFIG_RTC_DRV_SA1100) += rtc-sa1100.o
obj-$(CONFIG_RTC_DRV_SC27XX) += rtc-sc27xx.o
obj-$(CONFIG_RTC_DRV_SD2405AL) += rtc-sd2405al.o
-obj-$(CONFIG_RTC_DRV_SD3078) += rtc-sd3078.o
+obj-$(CONFIG_RTC_DRV_SD3078) += rtc-sd3078.o
obj-$(CONFIG_RTC_DRV_SH) += rtc-sh.o
obj-$(CONFIG_RTC_DRV_SNVS) += rtc-snvs.o
obj-$(CONFIG_RTC_DRV_SPEAR) += rtc-spear.o
diff --git a/drivers/rtc/interface.c b/drivers/rtc/interface.c
index cca650b2e0b9..aaf76406cd7d 100644
--- a/drivers/rtc/interface.c
+++ b/drivers/rtc/interface.c
@@ -904,13 +904,18 @@ void rtc_timer_do_work(struct work_struct *work)
struct timerqueue_node *next;
ktime_t now;
struct rtc_time tm;
+ int err;
struct rtc_device *rtc =
container_of(work, struct rtc_device, irqwork);
mutex_lock(&rtc->ops_lock);
again:
- __rtc_read_time(rtc, &tm);
+ err = __rtc_read_time(rtc, &tm);
+ if (err) {
+ mutex_unlock(&rtc->ops_lock);
+ return;
+ }
now = rtc_tm_to_ktime(tm);
while ((next = timerqueue_getnext(&rtc->timerqueue))) {
if (next->expires > now)
diff --git a/drivers/rtc/rtc-88pm80x.c b/drivers/rtc/rtc-88pm80x.c
index f40cc06b0979..5c39cf252392 100644
--- a/drivers/rtc/rtc-88pm80x.c
+++ b/drivers/rtc/rtc-88pm80x.c
@@ -329,7 +329,7 @@ static struct platform_driver pm80x_rtc_driver = {
.pm = &pm80x_rtc_pm_ops,
},
.probe = pm80x_rtc_probe,
- .remove_new = pm80x_rtc_remove,
+ .remove = pm80x_rtc_remove,
};
module_platform_driver(pm80x_rtc_driver);
diff --git a/drivers/rtc/rtc-88pm860x.c b/drivers/rtc/rtc-88pm860x.c
index 0f124ed5b3e5..814230d61842 100644
--- a/drivers/rtc/rtc-88pm860x.c
+++ b/drivers/rtc/rtc-88pm860x.c
@@ -371,7 +371,7 @@ static struct platform_driver pm860x_rtc_driver = {
.pm = &pm860x_rtc_pm_ops,
},
.probe = pm860x_rtc_probe,
- .remove_new = pm860x_rtc_remove,
+ .remove = pm860x_rtc_remove,
};
module_platform_driver(pm860x_rtc_driver);
diff --git a/drivers/rtc/rtc-88pm886.c b/drivers/rtc/rtc-88pm886.c
new file mode 100644
index 000000000000..57e9b0a66eed
--- /dev/null
+++ b/drivers/rtc/rtc-88pm886.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#include <linux/limits.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/rtc.h>
+
+#include <linux/mfd/88pm886.h>
+
+/*
+ * Time is calculated as the sum of a 32-bit read-only advancing counter and a
+ * writeable constant offset stored in the chip's spare registers.
+ */
+
+static int pm886_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct regmap *regmap = dev_get_drvdata(dev);
+ u32 time;
+ u32 buf;
+ int ret;
+
+ ret = regmap_bulk_read(regmap, PM886_REG_RTC_SPARE1, &buf, 4);
+ if (ret)
+ return ret;
+ time = buf;
+
+ ret = regmap_bulk_read(regmap, PM886_REG_RTC_CNT1, &buf, 4);
+ if (ret)
+ return ret;
+ time += buf;
+
+ rtc_time64_to_tm(time, tm);
+
+ return 0;
+}
+
+static int pm886_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct regmap *regmap = dev_get_drvdata(dev);
+ u32 buf;
+ int ret;
+
+ ret = regmap_bulk_read(regmap, PM886_REG_RTC_CNT1, &buf, 4);
+ if (ret)
+ return ret;
+
+ buf = rtc_tm_to_time64(tm) - buf;
+
+ return regmap_bulk_write(regmap, PM886_REG_RTC_SPARE1, &buf, 4);
+}
+
+static const struct rtc_class_ops pm886_rtc_ops = {
+ .read_time = pm886_rtc_read_time,
+ .set_time = pm886_rtc_set_time,
+};
+
+static int pm886_rtc_probe(struct platform_device *pdev)
+{
+ struct pm886_chip *chip = dev_get_drvdata(pdev->dev.parent);
+ struct device *dev = &pdev->dev;
+ struct rtc_device *rtc;
+ int ret;
+
+ platform_set_drvdata(pdev, chip->regmap);
+
+ rtc = devm_rtc_allocate_device(dev);
+ if (IS_ERR(rtc))
+ return dev_err_probe(dev, PTR_ERR(rtc),
+ "Failed to allocate RTC device\n");
+
+ rtc->ops = &pm886_rtc_ops;
+ rtc->range_max = U32_MAX;
+
+ ret = devm_rtc_register_device(rtc);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to register RTC device\n");
+
+ return 0;
+}
+
+static const struct platform_device_id pm886_rtc_id_table[] = {
+ { "88pm886-rtc", },
+ { }
+};
+MODULE_DEVICE_TABLE(platform, pm886_rtc_id_table);
+
+static struct platform_driver pm886_rtc_driver = {
+ .driver = {
+ .name = "88pm886-rtc",
+ },
+ .probe = pm886_rtc_probe,
+ .id_table = pm886_rtc_id_table,
+};
+module_platform_driver(pm886_rtc_driver);
+
+MODULE_DESCRIPTION("Marvell 88PM886 RTC driver");
+MODULE_AUTHOR("Karel Balej <balejk@matfyz.cz>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-ab-eoz9.c b/drivers/rtc/rtc-ab-eoz9.c
index 02f7d0711287..d2b60487d462 100644
--- a/drivers/rtc/rtc-ab-eoz9.c
+++ b/drivers/rtc/rtc-ab-eoz9.c
@@ -64,7 +64,7 @@
#define ABEOZ9_BIT_ALARM_MIN GENMASK(6, 0)
#define ABEOZ9_REG_ALARM_HOURS 0x12
#define ABEOZ9_BIT_ALARM_HOURS_PM BIT(5)
-#define ABEOZ9_BIT_ALARM_HOURS GENMASK(4, 0)
+#define ABEOZ9_BIT_ALARM_HOURS GENMASK(5, 0)
#define ABEOZ9_REG_ALARM_DAYS 0x13
#define ABEOZ9_BIT_ALARM_DAYS GENMASK(5, 0)
#define ABEOZ9_REG_ALARM_WEEKDAYS 0x14
@@ -231,8 +231,6 @@ static int abeoz9_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
alarm->time.tm_sec = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_SEC, regs[0]));
alarm->time.tm_min = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_MIN, regs[1]));
alarm->time.tm_hour = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_HOURS, regs[2]));
- if (FIELD_GET(ABEOZ9_BIT_ALARM_HOURS_PM, regs[2]))
- alarm->time.tm_hour += 12;
alarm->time.tm_mday = bcd2bin(FIELD_GET(ABEOZ9_BIT_ALARM_DAYS, regs[3]));
@@ -396,13 +394,6 @@ static int abeoz9z3_temp_read(struct device *dev,
if (ret < 0)
return ret;
- if ((val & ABEOZ9_REG_CTRL_STATUS_V1F) ||
- (val & ABEOZ9_REG_CTRL_STATUS_V2F)) {
- dev_err(dev,
- "thermometer might be disabled due to low voltage\n");
- return -EINVAL;
- }
-
switch (attr) {
case hwmon_temp_input:
ret = regmap_read(regmap, ABEOZ9_REG_REG_TEMP, &val);
diff --git a/drivers/rtc/rtc-ab8500.c b/drivers/rtc/rtc-ab8500.c
index 75bb2ac9005c..2dcda96f4a8e 100644
--- a/drivers/rtc/rtc-ab8500.c
+++ b/drivers/rtc/rtc-ab8500.c
@@ -403,7 +403,7 @@ static struct platform_driver ab8500_rtc_driver = {
.name = "ab8500-rtc",
},
.probe = ab8500_rtc_probe,
- .remove_new = ab8500_rtc_remove,
+ .remove = ab8500_rtc_remove,
.id_table = ab85xx_rtc_ids,
};
diff --git a/drivers/rtc/rtc-abx80x.c b/drivers/rtc/rtc-abx80x.c
index 1298962402ff..3fee27914ba8 100644
--- a/drivers/rtc/rtc-abx80x.c
+++ b/drivers/rtc/rtc-abx80x.c
@@ -39,7 +39,7 @@
#define ABX8XX_REG_STATUS 0x0f
#define ABX8XX_STATUS_AF BIT(2)
#define ABX8XX_STATUS_BLF BIT(4)
-#define ABX8XX_STATUS_WDT BIT(6)
+#define ABX8XX_STATUS_WDT BIT(5)
#define ABX8XX_REG_CTRL1 0x10
#define ABX8XX_CTRL_WRITE BIT(0)
diff --git a/drivers/rtc/rtc-ac100.c b/drivers/rtc/rtc-ac100.c
index fa642bba3cee..33626311fa78 100644
--- a/drivers/rtc/rtc-ac100.c
+++ b/drivers/rtc/rtc-ac100.c
@@ -628,7 +628,7 @@ MODULE_DEVICE_TABLE(of, ac100_rtc_match);
static struct platform_driver ac100_rtc_driver = {
.probe = ac100_rtc_probe,
- .remove_new = ac100_rtc_remove,
+ .remove = ac100_rtc_remove,
.driver = {
.name = "ac100-rtc",
.of_match_table = of_match_ptr(ac100_rtc_match),
diff --git a/drivers/rtc/rtc-amlogic-a4.c b/drivers/rtc/rtc-amlogic-a4.c
new file mode 100644
index 000000000000..2278b4c98a71
--- /dev/null
+++ b/drivers/rtc/rtc-amlogic-a4.c
@@ -0,0 +1,465 @@
+// SPDX-License-Identifier: (GPL-2.0-only OR MIT)
+/*
+ * Copyright (C) 2024 Amlogic, Inc. All rights reserved
+ * Author: Yiting Deng <yiting.deng@amlogic.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/time64.h>
+
+/* rtc oscillator rate */
+#define OSC_32K 32768
+#define OSC_24M 24000000
+
+#define RTC_CTRL (0x0 << 2) /* Control RTC */
+#define RTC_ALRM0_EN BIT(0)
+#define RTC_OSC_SEL BIT(8)
+#define RTC_ENABLE BIT(12)
+
+#define RTC_COUNTER_REG (0x1 << 2) /* Program RTC counter initial value */
+
+#define RTC_ALARM0_REG (0x2 << 2) /* Program RTC alarm0 value */
+
+#define RTC_SEC_ADJUST_REG (0x6 << 2) /* Control second-based timing adjustment */
+#define RTC_MATCH_COUNTER GENMASK(18, 0)
+#define RTC_SEC_ADJUST_CTRL GENMASK(20, 19)
+#define RTC_ADJ_VALID BIT(23)
+
+#define RTC_INT_MASK (0x8 << 2) /* RTC interrupt mask */
+#define RTC_ALRM0_IRQ_MSK BIT(0)
+
+#define RTC_INT_CLR (0x9 << 2) /* Clear RTC interrupt */
+#define RTC_ALRM0_IRQ_CLR BIT(0)
+
+#define RTC_OSCIN_CTRL0 (0xa << 2) /* Control RTC clk from 24M */
+#define RTC_OSCIN_CTRL1 (0xb << 2) /* Control RTC clk from 24M */
+#define RTC_OSCIN_IN_EN BIT(31)
+#define RTC_OSCIN_OUT_CFG GENMASK(29, 28)
+#define RTC_OSCIN_OUT_N0M0 GENMASK(11, 0)
+#define RTC_OSCIN_OUT_N1M1 GENMASK(23, 12)
+
+#define RTC_INT_STATUS (0xc << 2) /* RTC interrupt status */
+#define RTC_ALRM0_IRQ_STATUS BIT(0)
+
+#define RTC_REAL_TIME (0xd << 2) /* RTC time value */
+
+#define RTC_OSCIN_OUT_32K_N0 0x2dc
+#define RTC_OSCIN_OUT_32K_N1 0x2db
+#define RTC_OSCIN_OUT_32K_M0 0x1
+#define RTC_OSCIN_OUT_32K_M1 0x2
+
+#define RTC_SWALLOW_SECOND 0x2
+#define RTC_INSERT_SECOND 0x3
+
+struct aml_rtc_config {
+ bool gray_stored;
+};
+
+struct aml_rtc_data {
+ struct regmap *map;
+ struct rtc_device *rtc_dev;
+ int irq;
+ struct clk *rtc_clk;
+ struct clk *sys_clk;
+ int rtc_enabled;
+ const struct aml_rtc_config *config;
+};
+
+static const struct regmap_config aml_rtc_regmap_config = {
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .max_register = RTC_REAL_TIME,
+};
+
+static inline u32 gray_to_binary(u32 gray)
+{
+ u32 bcd = gray;
+ int size = sizeof(bcd) * 8;
+ int i;
+
+ for (i = 0; (1 << i) < size; i++)
+ bcd ^= bcd >> (1 << i);
+
+ return bcd;
+}
+
+static inline u32 binary_to_gray(u32 bcd)
+{
+ return bcd ^ (bcd >> 1);
+}
+
+static int aml_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ u32 time_sec;
+
+ /* if RTC disabled, read time failed */
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+
+ regmap_read(rtc->map, RTC_REAL_TIME, &time_sec);
+ if (rtc->config->gray_stored)
+ time_sec = gray_to_binary(time_sec);
+ rtc_time64_to_tm(time_sec, tm);
+ dev_dbg(dev, "%s: read time = %us\n", __func__, time_sec);
+
+ return 0;
+}
+
+static int aml_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ u32 time_sec;
+
+ /* if RTC disabled, first enable it */
+ if (!rtc->rtc_enabled) {
+ regmap_write_bits(rtc->map, RTC_CTRL, RTC_ENABLE, RTC_ENABLE);
+ usleep_range(100, 200);
+ rtc->rtc_enabled = regmap_test_bits(rtc->map, RTC_CTRL, RTC_ENABLE);
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+ }
+
+ time_sec = rtc_tm_to_time64(tm);
+ if (rtc->config->gray_stored)
+ time_sec = binary_to_gray(time_sec);
+ regmap_write(rtc->map, RTC_COUNTER_REG, time_sec);
+ dev_dbg(dev, "%s: set time = %us\n", __func__, time_sec);
+
+ return 0;
+}
+
+static int aml_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ time64_t alarm_sec;
+
+ /* if RTC disabled, set alarm failed */
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+
+ regmap_update_bits(rtc->map, RTC_CTRL,
+ RTC_ALRM0_EN, RTC_ALRM0_EN);
+ regmap_update_bits(rtc->map, RTC_INT_MASK,
+ RTC_ALRM0_IRQ_MSK, 0);
+
+ alarm_sec = rtc_tm_to_time64(&alarm->time);
+ if (rtc->config->gray_stored)
+ alarm_sec = binary_to_gray(alarm_sec);
+ regmap_write(rtc->map, RTC_ALARM0_REG, alarm_sec);
+
+ dev_dbg(dev, "%s: alarm->enabled=%d alarm_set=%llds\n", __func__,
+ alarm->enabled, alarm_sec);
+
+ return 0;
+}
+
+static int aml_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ u32 alarm_sec;
+ int alarm_enable;
+ int alarm_mask;
+
+ /* if RTC disabled, read alarm failed */
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+
+ regmap_read(rtc->map, RTC_ALARM0_REG, &alarm_sec);
+ if (rtc->config->gray_stored)
+ alarm_sec = gray_to_binary(alarm_sec);
+ rtc_time64_to_tm(alarm_sec, &alarm->time);
+
+ alarm_enable = regmap_test_bits(rtc->map, RTC_CTRL, RTC_ALRM0_EN);
+ alarm_mask = regmap_test_bits(rtc->map, RTC_INT_MASK, RTC_ALRM0_IRQ_MSK);
+ alarm->enabled = (alarm_enable && !alarm_mask) ? 1 : 0;
+ dev_dbg(dev, "%s: alarm->enabled=%d alarm=%us\n", __func__,
+ alarm->enabled, alarm_sec);
+
+ return 0;
+}
+
+static int aml_rtc_read_offset(struct device *dev, long *offset)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ u32 reg_val;
+ long val;
+ int sign, match_counter, enable;
+
+ /* if RTC disabled, read offset failed */
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+
+ regmap_read(rtc->map, RTC_SEC_ADJUST_REG, &reg_val);
+ enable = FIELD_GET(RTC_ADJ_VALID, reg_val);
+ if (!enable) {
+ val = 0;
+ } else {
+ sign = FIELD_GET(RTC_SEC_ADJUST_CTRL, reg_val);
+ match_counter = FIELD_GET(RTC_MATCH_COUNTER, reg_val);
+ val = 1000000000 / (match_counter + 1);
+ if (sign == RTC_SWALLOW_SECOND)
+ val = -val;
+ }
+ *offset = val;
+
+ return 0;
+}
+
+static int aml_rtc_set_offset(struct device *dev, long offset)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+ int sign = 0;
+ int match_counter = 0;
+ int enable = 0;
+ u32 reg_val;
+
+ /* if RTC disabled, set offset failed */
+ if (!rtc->rtc_enabled)
+ return -EINVAL;
+
+ if (offset) {
+ enable = 1;
+ sign = offset < 0 ? RTC_SWALLOW_SECOND : RTC_INSERT_SECOND;
+ match_counter = 1000000000 / abs(offset) - 1;
+ if (match_counter < 0 || match_counter > RTC_MATCH_COUNTER)
+ return -EINVAL;
+ }
+
+ reg_val = FIELD_PREP(RTC_ADJ_VALID, enable) |
+ FIELD_PREP(RTC_SEC_ADJUST_CTRL, sign) |
+ FIELD_PREP(RTC_MATCH_COUNTER, match_counter);
+ regmap_write(rtc->map, RTC_SEC_ADJUST_REG, reg_val);
+
+ return 0;
+}
+
+static int aml_rtc_alarm_enable(struct device *dev, unsigned int enabled)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+
+ if (enabled) {
+ regmap_update_bits(rtc->map, RTC_CTRL,
+ RTC_ALRM0_EN, RTC_ALRM0_EN);
+ regmap_update_bits(rtc->map, RTC_INT_MASK,
+ RTC_ALRM0_IRQ_MSK, 0);
+ } else {
+ regmap_update_bits(rtc->map, RTC_INT_MASK,
+ RTC_ALRM0_IRQ_MSK, RTC_ALRM0_IRQ_MSK);
+ regmap_update_bits(rtc->map, RTC_CTRL,
+ RTC_ALRM0_EN, 0);
+ }
+
+ return 0;
+}
+
+static const struct rtc_class_ops aml_rtc_ops = {
+ .read_time = aml_rtc_read_time,
+ .set_time = aml_rtc_set_time,
+ .read_alarm = aml_rtc_read_alarm,
+ .set_alarm = aml_rtc_set_alarm,
+ .alarm_irq_enable = aml_rtc_alarm_enable,
+ .read_offset = aml_rtc_read_offset,
+ .set_offset = aml_rtc_set_offset,
+};
+
+static irqreturn_t aml_rtc_handler(int irq, void *data)
+{
+ struct aml_rtc_data *rtc = (struct aml_rtc_data *)data;
+
+ regmap_write(rtc->map, RTC_ALARM0_REG, 0);
+ regmap_write(rtc->map, RTC_INT_CLR, RTC_ALRM0_IRQ_STATUS);
+
+ rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+
+ return IRQ_HANDLED;
+}
+
+static void aml_rtc_init(struct aml_rtc_data *rtc)
+{
+ u32 reg_val = 0;
+
+ rtc->rtc_enabled = regmap_test_bits(rtc->map, RTC_CTRL, RTC_ENABLE);
+ if (!rtc->rtc_enabled) {
+ if (clk_get_rate(rtc->rtc_clk) == OSC_24M) {
+ /* select 24M oscillator */
+ regmap_write_bits(rtc->map, RTC_CTRL, RTC_OSC_SEL, RTC_OSC_SEL);
+
+ /*
+ * Set RTC oscillator to freq_out to freq_in/((N0*M0+N1*M1)/(M0+M1))
+ * Enable clock_in gate of oscillator 24MHz
+ * Set N0 to 733, N1 to 732
+ */
+ reg_val = FIELD_PREP(RTC_OSCIN_IN_EN, 1)
+ | FIELD_PREP(RTC_OSCIN_OUT_CFG, 1)
+ | FIELD_PREP(RTC_OSCIN_OUT_N0M0, RTC_OSCIN_OUT_32K_N0)
+ | FIELD_PREP(RTC_OSCIN_OUT_N1M1, RTC_OSCIN_OUT_32K_N1);
+ regmap_write_bits(rtc->map, RTC_OSCIN_CTRL0, RTC_OSCIN_IN_EN
+ | RTC_OSCIN_OUT_CFG | RTC_OSCIN_OUT_N0M0
+ | RTC_OSCIN_OUT_N1M1, reg_val);
+
+ /* Set M0 to 2, M1 to 3, so freq_out = 32768 Hz*/
+ reg_val = FIELD_PREP(RTC_OSCIN_OUT_N0M0, RTC_OSCIN_OUT_32K_M0)
+ | FIELD_PREP(RTC_OSCIN_OUT_N1M1, RTC_OSCIN_OUT_32K_M1);
+ regmap_write_bits(rtc->map, RTC_OSCIN_CTRL1, RTC_OSCIN_OUT_N0M0
+ | RTC_OSCIN_OUT_N1M1, reg_val);
+ } else {
+ /* select 32K oscillator */
+ regmap_write_bits(rtc->map, RTC_CTRL, RTC_OSC_SEL, 0);
+ }
+ }
+ regmap_write_bits(rtc->map, RTC_INT_MASK,
+ RTC_ALRM0_IRQ_MSK, RTC_ALRM0_IRQ_MSK);
+ regmap_write_bits(rtc->map, RTC_CTRL, RTC_ALRM0_EN, 0);
+}
+
+static int aml_rtc_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct aml_rtc_data *rtc;
+ void __iomem *base;
+ int ret = 0;
+
+ rtc = devm_kzalloc(dev, sizeof(*rtc), GFP_KERNEL);
+ if (!rtc)
+ return -ENOMEM;
+
+ rtc->config = of_device_get_match_data(dev);
+ if (!rtc->config)
+ return -ENODEV;
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return dev_err_probe(dev, PTR_ERR(base), "resource ioremap failed\n");
+
+ rtc->map = devm_regmap_init_mmio(dev, base, &aml_rtc_regmap_config);
+ if (IS_ERR(rtc->map))
+ return dev_err_probe(dev, PTR_ERR(rtc->map), "regmap init failed\n");
+
+ rtc->irq = platform_get_irq(pdev, 0);
+ if (rtc->irq < 0)
+ return rtc->irq;
+
+ rtc->rtc_clk = devm_clk_get(dev, "osc");
+ if (IS_ERR(rtc->rtc_clk))
+ return dev_err_probe(dev, PTR_ERR(rtc->rtc_clk),
+ "failed to find rtc clock\n");
+ if (clk_get_rate(rtc->rtc_clk) != OSC_32K && clk_get_rate(rtc->rtc_clk) != OSC_24M)
+ return dev_err_probe(dev, -EINVAL, "Invalid clock configuration\n");
+
+ rtc->sys_clk = devm_clk_get_enabled(dev, "sys");
+ if (IS_ERR(rtc->sys_clk))
+ return dev_err_probe(dev, PTR_ERR(rtc->sys_clk),
+ "failed to get_enable rtc sys clk\n");
+ aml_rtc_init(rtc);
+
+ device_init_wakeup(dev, 1);
+ platform_set_drvdata(pdev, rtc);
+
+ rtc->rtc_dev = devm_rtc_allocate_device(dev);
+ if (IS_ERR(rtc->rtc_dev)) {
+ ret = PTR_ERR(rtc->rtc_dev);
+ goto err_clk;
+ }
+
+ ret = devm_request_irq(dev, rtc->irq, aml_rtc_handler,
+ IRQF_ONESHOT, "aml-rtc alarm", rtc);
+ if (ret) {
+ dev_err_probe(dev, ret, "IRQ%d request failed, ret = %d\n",
+ rtc->irq, ret);
+ goto err_clk;
+ }
+
+ rtc->rtc_dev->ops = &aml_rtc_ops;
+ rtc->rtc_dev->range_min = 0;
+ rtc->rtc_dev->range_max = U32_MAX;
+
+ ret = devm_rtc_register_device(rtc->rtc_dev);
+ if (ret) {
+ dev_err_probe(&pdev->dev, ret, "Failed to register RTC device: %d\n", ret);
+ goto err_clk;
+ }
+
+ return 0;
+err_clk:
+ clk_disable_unprepare(rtc->sys_clk);
+ device_init_wakeup(dev, 0);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int aml_rtc_suspend(struct device *dev)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ enable_irq_wake(rtc->irq);
+
+ return 0;
+}
+
+static int aml_rtc_resume(struct device *dev)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(dev);
+
+ if (device_may_wakeup(dev))
+ disable_irq_wake(rtc->irq);
+
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(aml_rtc_pm_ops,
+ aml_rtc_suspend, aml_rtc_resume);
+
+static void aml_rtc_remove(struct platform_device *pdev)
+{
+ struct aml_rtc_data *rtc = dev_get_drvdata(&pdev->dev);
+
+ clk_disable_unprepare(rtc->sys_clk);
+ device_init_wakeup(&pdev->dev, 0);
+}
+
+static const struct aml_rtc_config a5_rtc_config = {
+};
+
+static const struct aml_rtc_config a4_rtc_config = {
+ .gray_stored = true,
+};
+
+static const struct of_device_id aml_rtc_device_id[] = {
+ {
+ .compatible = "amlogic,a4-rtc",
+ .data = &a4_rtc_config,
+ },
+ {
+ .compatible = "amlogic,a5-rtc",
+ .data = &a5_rtc_config,
+ },
+ { }
+};
+MODULE_DEVICE_TABLE(of, aml_rtc_device_id);
+
+static struct platform_driver aml_rtc_driver = {
+ .probe = aml_rtc_probe,
+ .remove = aml_rtc_remove,
+ .driver = {
+ .name = "aml-rtc",
+ .pm = &aml_rtc_pm_ops,
+ .of_match_table = aml_rtc_device_id,
+ },
+};
+
+module_platform_driver(aml_rtc_driver);
+MODULE_DESCRIPTION("Amlogic RTC driver");
+MODULE_AUTHOR("Yiting Deng <yiting.deng@amlogic.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-asm9260.c b/drivers/rtc/rtc-asm9260.c
index a83b47e0d8f5..705470ae8428 100644
--- a/drivers/rtc/rtc-asm9260.c
+++ b/drivers/rtc/rtc-asm9260.c
@@ -325,7 +325,7 @@ MODULE_DEVICE_TABLE(of, asm9260_dt_ids);
static struct platform_driver asm9260_rtc_driver = {
.probe = asm9260_rtc_probe,
- .remove_new = asm9260_rtc_remove,
+ .remove = asm9260_rtc_remove,
.driver = {
.name = "asm9260-rtc",
.of_match_table = asm9260_dt_ids,
diff --git a/drivers/rtc/rtc-at91rm9200.c b/drivers/rtc/rtc-at91rm9200.c
index c16fe711a0d9..9b3898b8de7c 100644
--- a/drivers/rtc/rtc-at91rm9200.c
+++ b/drivers/rtc/rtc-at91rm9200.c
@@ -640,7 +640,7 @@ static SIMPLE_DEV_PM_OPS(at91_rtc_pm_ops, at91_rtc_suspend, at91_rtc_resume);
* triggering a section mismatch warning.
*/
static struct platform_driver at91_rtc_driver __refdata = {
- .remove_new = __exit_p(at91_rtc_remove),
+ .remove = __exit_p(at91_rtc_remove),
.shutdown = at91_rtc_shutdown,
.driver = {
.name = "at91_rtc",
diff --git a/drivers/rtc/rtc-at91sam9.c b/drivers/rtc/rtc-at91sam9.c
index 993c0878fb66..15b21da2788f 100644
--- a/drivers/rtc/rtc-at91sam9.c
+++ b/drivers/rtc/rtc-at91sam9.c
@@ -530,7 +530,7 @@ MODULE_DEVICE_TABLE(of, at91_rtc_dt_ids);
static struct platform_driver at91_rtc_driver = {
.probe = at91_rtc_probe,
- .remove_new = at91_rtc_remove,
+ .remove = at91_rtc_remove,
.shutdown = at91_rtc_shutdown,
.driver = {
.name = "rtc-at91sam9",
diff --git a/drivers/rtc/rtc-brcmstb-waketimer.c b/drivers/rtc/rtc-brcmstb-waketimer.c
index 1a65a4e0dc00..fb47c32ab5ff 100644
--- a/drivers/rtc/rtc-brcmstb-waketimer.c
+++ b/drivers/rtc/rtc-brcmstb-waketimer.c
@@ -17,7 +17,6 @@
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/pm.h>
-#include <linux/pm_wakeup.h>
#include <linux/reboot.h>
#include <linux/rtc.h>
#include <linux/stat.h>
@@ -417,7 +416,7 @@ static const __maybe_unused struct of_device_id brcmstb_waketmr_of_match[] = {
static struct platform_driver brcmstb_waketmr_driver = {
.probe = brcmstb_waketmr_probe,
- .remove_new = brcmstb_waketmr_remove,
+ .remove = brcmstb_waketmr_remove,
.driver = {
.name = "brcmstb-waketimer",
.pm = &brcmstb_waketmr_pm_ops,
diff --git a/drivers/rtc/rtc-cadence.c b/drivers/rtc/rtc-cadence.c
index 4ca60b519836..bf2a9a1fdea7 100644
--- a/drivers/rtc/rtc-cadence.c
+++ b/drivers/rtc/rtc-cadence.c
@@ -402,7 +402,7 @@ static struct platform_driver cdns_rtc_driver = {
.pm = &cdns_rtc_pm_ops,
},
.probe = cdns_rtc_probe,
- .remove_new = cdns_rtc_remove,
+ .remove = cdns_rtc_remove,
};
module_platform_driver(cdns_rtc_driver);
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index 35dca2accbb8..78f2ce12c75a 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -645,18 +645,17 @@ static int cmos_nvram_read(void *priv, unsigned int off, void *val,
unsigned char *buf = val;
off += NVRAM_OFFSET;
- spin_lock_irq(&rtc_lock);
- for (; count; count--, off++) {
+ for (; count; count--, off++, buf++) {
+ guard(spinlock_irq)(&rtc_lock);
if (off < 128)
- *buf++ = CMOS_READ(off);
+ *buf = CMOS_READ(off);
else if (can_bank2)
- *buf++ = cmos_read_bank2(off);
+ *buf = cmos_read_bank2(off);
else
- break;
+ return -EIO;
}
- spin_unlock_irq(&rtc_lock);
- return count ? -EIO : 0;
+ return 0;
}
static int cmos_nvram_write(void *priv, unsigned int off, void *val,
@@ -671,23 +670,23 @@ static int cmos_nvram_write(void *priv, unsigned int off, void *val,
* NVRAM to update, updating checksums is also part of its job.
*/
off += NVRAM_OFFSET;
- spin_lock_irq(&rtc_lock);
- for (; count; count--, off++) {
+ for (; count; count--, off++, buf++) {
/* don't trash RTC registers */
if (off == cmos->day_alrm
|| off == cmos->mon_alrm
|| off == cmos->century)
- buf++;
- else if (off < 128)
- CMOS_WRITE(*buf++, off);
+ continue;
+
+ guard(spinlock_irq)(&rtc_lock);
+ if (off < 128)
+ CMOS_WRITE(*buf, off);
else if (can_bank2)
- cmos_write_bank2(*buf++, off);
+ cmos_write_bank2(*buf, off);
else
- break;
+ return -EIO;
}
- spin_unlock_irq(&rtc_lock);
- return count ? -EIO : 0;
+ return 0;
}
/*----------------------------------------------------------------*/
@@ -1528,7 +1527,7 @@ static void cmos_platform_shutdown(struct platform_device *pdev)
MODULE_ALIAS("platform:rtc_cmos");
static struct platform_driver cmos_platform_driver = {
- .remove_new = cmos_platform_remove,
+ .remove = cmos_platform_remove,
.shutdown = cmos_platform_shutdown,
.driver = {
.name = driver_name,
diff --git a/drivers/rtc/rtc-cros-ec.c b/drivers/rtc/rtc-cros-ec.c
index f57462c7b2c6..60a48c3ba3ca 100644
--- a/drivers/rtc/rtc-cros-ec.c
+++ b/drivers/rtc/rtc-cros-ec.c
@@ -401,7 +401,7 @@ MODULE_DEVICE_TABLE(platform, cros_ec_rtc_id);
static struct platform_driver cros_ec_rtc_driver = {
.probe = cros_ec_rtc_probe,
- .remove_new = cros_ec_rtc_remove,
+ .remove = cros_ec_rtc_remove,
.driver = {
.name = DRV_NAME,
.pm = &cros_ec_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-ds1685.c b/drivers/rtc/rtc-ds1685.c
index 04dbf35cf3b7..38e25f63597a 100644
--- a/drivers/rtc/rtc-ds1685.c
+++ b/drivers/rtc/rtc-ds1685.c
@@ -1354,7 +1354,7 @@ static struct platform_driver ds1685_rtc_driver = {
.name = "rtc-ds1685",
},
.probe = ds1685_rtc_probe,
- .remove_new = ds1685_rtc_remove,
+ .remove = ds1685_rtc_remove,
};
module_platform_driver(ds1685_rtc_driver);
/* ----------------------------------------------------------------------- */
diff --git a/drivers/rtc/rtc-ftrtc010.c b/drivers/rtc/rtc-ftrtc010.c
index 8bfe7378f653..cb4a5d101f53 100644
--- a/drivers/rtc/rtc-ftrtc010.c
+++ b/drivers/rtc/rtc-ftrtc010.c
@@ -214,7 +214,7 @@ static struct platform_driver ftrtc010_rtc_driver = {
.of_match_table = ftrtc010_rtc_dt_match,
},
.probe = ftrtc010_rtc_probe,
- .remove_new = ftrtc010_rtc_remove,
+ .remove = ftrtc010_rtc_remove,
};
module_platform_driver_probe(ftrtc010_rtc_driver, ftrtc010_rtc_probe);
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index b81cea505ee9..6228d0b2486e 100644
--- a/drivers/rtc/rtc-hid-sensor-time.c
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -319,11 +319,11 @@ static struct platform_driver hid_time_platform_driver = {
.name = KBUILD_MODNAME,
},
.probe = hid_time_probe,
- .remove_new = hid_time_remove,
+ .remove = hid_time_remove,
};
module_platform_driver(hid_time_platform_driver);
MODULE_DESCRIPTION("HID Sensor Time");
MODULE_AUTHOR("Alexander Holler <holler@ahsoftware.de>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(IIO_HID);
+MODULE_IMPORT_NS("IIO_HID");
diff --git a/drivers/rtc/rtc-imxdi.c b/drivers/rtc/rtc-imxdi.c
index 284011c419db..ca4a0af95e8c 100644
--- a/drivers/rtc/rtc-imxdi.c
+++ b/drivers/rtc/rtc-imxdi.c
@@ -860,7 +860,7 @@ static struct platform_driver dryice_rtc_driver __refdata = {
.name = "imxdi_rtc",
.of_match_table = dryice_dt_ids,
},
- .remove_new = __exit_p(dryice_rtc_remove),
+ .remove = __exit_p(dryice_rtc_remove),
};
module_platform_driver_probe(dryice_rtc_driver, dryice_rtc_probe);
diff --git a/drivers/rtc/rtc-isl12022.c b/drivers/rtc/rtc-isl12022.c
index 6fa9a68af9d9..9b44839a7402 100644
--- a/drivers/rtc/rtc-isl12022.c
+++ b/drivers/rtc/rtc-isl12022.c
@@ -21,7 +21,7 @@
#include <asm/byteorder.h>
-/* ISL register offsets */
+/* RTC - Real time clock registers */
#define ISL12022_REG_SC 0x00
#define ISL12022_REG_MN 0x01
#define ISL12022_REG_HR 0x02
@@ -30,21 +30,36 @@
#define ISL12022_REG_YR 0x05
#define ISL12022_REG_DW 0x06
+/* CSR - Control and status registers */
#define ISL12022_REG_SR 0x07
#define ISL12022_REG_INT 0x08
-
#define ISL12022_REG_PWR_VBAT 0x0a
-
#define ISL12022_REG_BETA 0x0d
+
+/* ALARM - Alarm registers */
+#define ISL12022_REG_SCA0 0x10
+#define ISL12022_REG_MNA0 0x11
+#define ISL12022_REG_HRA0 0x12
+#define ISL12022_REG_DTA0 0x13
+#define ISL12022_REG_MOA0 0x14
+#define ISL12022_REG_DWA0 0x15
+#define ISL12022_ALARM ISL12022_REG_SCA0
+#define ISL12022_ALARM_LEN (ISL12022_REG_DWA0 - ISL12022_REG_SCA0 + 1)
+
+/* TEMP - Temperature sensor registers */
#define ISL12022_REG_TEMP_L 0x28
/* ISL register bits */
#define ISL12022_HR_MIL (1 << 7) /* military or 24 hour time */
+#define ISL12022_SR_ALM (1 << 4)
#define ISL12022_SR_LBAT85 (1 << 2)
#define ISL12022_SR_LBAT75 (1 << 1)
+#define ISL12022_INT_ARST (1 << 7)
#define ISL12022_INT_WRTC (1 << 6)
+#define ISL12022_INT_IM (1 << 5)
+#define ISL12022_INT_FOBATB (1 << 4)
#define ISL12022_INT_FO_MASK GENMASK(3, 0)
#define ISL12022_INT_FO_OFF 0x0
#define ISL12022_INT_FO_32K 0x1
@@ -52,8 +67,19 @@
#define ISL12022_REG_VB85_MASK GENMASK(5, 3)
#define ISL12022_REG_VB75_MASK GENMASK(2, 0)
+#define ISL12022_ALARM_ENABLE (1 << 7) /* for all ALARM registers */
+
#define ISL12022_BETA_TSE (1 << 7)
+static struct i2c_driver isl12022_driver;
+
+struct isl12022 {
+ struct rtc_device *rtc;
+ struct regmap *regmap;
+ int irq;
+ bool irq_enabled;
+};
+
static umode_t isl12022_hwmon_is_visible(const void *data,
enum hwmon_sensor_types type,
u32 attr, int channel)
@@ -116,7 +142,8 @@ static const struct hwmon_chip_info isl12022_hwmon_chip_info = {
static void isl12022_hwmon_register(struct device *dev)
{
- struct regmap *regmap = dev_get_drvdata(dev);
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
struct device *hwmon;
int ret;
@@ -143,8 +170,9 @@ static void isl12022_hwmon_register(struct device *dev)
*/
static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct regmap *regmap = dev_get_drvdata(dev);
- uint8_t buf[ISL12022_REG_INT + 1];
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
+ u8 buf[ISL12022_REG_INT + 1];
int ret;
ret = regmap_bulk_read(regmap, ISL12022_REG_SC, buf, sizeof(buf));
@@ -178,9 +206,10 @@ static int isl12022_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct regmap *regmap = dev_get_drvdata(dev);
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
int ret;
- uint8_t buf[ISL12022_REG_DW + 1];
+ u8 buf[ISL12022_REG_DW + 1];
dev_dbg(dev, "%s: %ptR\n", __func__, tm);
@@ -208,9 +237,198 @@ static int isl12022_rtc_set_time(struct device *dev, struct rtc_time *tm)
return regmap_bulk_write(regmap, ISL12022_REG_SC, buf, sizeof(buf));
}
+static int isl12022_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct rtc_time *tm = &alarm->time;
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
+ u8 buf[ISL12022_ALARM_LEN];
+ unsigned int i, yr;
+ int ret;
+
+ ret = regmap_bulk_read(regmap, ISL12022_ALARM, buf, sizeof(buf));
+ if (ret) {
+ dev_dbg(dev, "%s: reading ALARM registers failed\n",
+ __func__);
+ return ret;
+ }
+
+ /* The alarm doesn't store the year so get it from the rtc section */
+ ret = regmap_read(regmap, ISL12022_REG_YR, &yr);
+ if (ret) {
+ dev_dbg(dev, "%s: reading YR register failed\n", __func__);
+ return ret;
+ }
+
+ dev_dbg(dev,
+ "%s: sc=%02x, mn=%02x, hr=%02x, dt=%02x, mo=%02x, dw=%02x yr=%u\n",
+ __func__, buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], yr);
+
+ tm->tm_sec = bcd2bin(buf[ISL12022_REG_SCA0 - ISL12022_ALARM] & 0x7F);
+ tm->tm_min = bcd2bin(buf[ISL12022_REG_MNA0 - ISL12022_ALARM] & 0x7F);
+ tm->tm_hour = bcd2bin(buf[ISL12022_REG_HRA0 - ISL12022_ALARM] & 0x3F);
+ tm->tm_mday = bcd2bin(buf[ISL12022_REG_DTA0 - ISL12022_ALARM] & 0x3F);
+ tm->tm_mon = bcd2bin(buf[ISL12022_REG_MOA0 - ISL12022_ALARM] & 0x1F) - 1;
+ tm->tm_wday = buf[ISL12022_REG_DWA0 - ISL12022_ALARM] & 0x07;
+ tm->tm_year = bcd2bin(yr) + 100;
+
+ for (i = 0; i < ISL12022_ALARM_LEN; i++) {
+ if (buf[i] & ISL12022_ALARM_ENABLE) {
+ alarm->enabled = 1;
+ break;
+ }
+ }
+
+ dev_dbg(dev, "%s: %ptR\n", __func__, tm);
+
+ return 0;
+}
+
+static int isl12022_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+ struct rtc_time *alarm_tm = &alarm->time;
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
+ u8 regs[ISL12022_ALARM_LEN] = { 0, };
+ struct rtc_time rtc_tm;
+ int ret, enable, dw;
+
+ ret = isl12022_rtc_read_time(dev, &rtc_tm);
+ if (ret)
+ return ret;
+
+ /* If the alarm time is before the current time disable the alarm */
+ if (!alarm->enabled || rtc_tm_sub(alarm_tm, &rtc_tm) <= 0)
+ enable = 0;
+ else
+ enable = ISL12022_ALARM_ENABLE;
+
+ /*
+ * Set non-matching day of the week to safeguard against early false
+ * matching while setting all the alarm registers (this rtc lacks a
+ * general alarm/irq enable/disable bit).
+ */
+ ret = regmap_read(regmap, ISL12022_REG_DW, &dw);
+ if (ret) {
+ dev_dbg(dev, "%s: reading DW failed\n", __func__);
+ return ret;
+ }
+ /* ~4 days into the future should be enough to avoid match */
+ dw = ((dw + 4) % 7) | ISL12022_ALARM_ENABLE;
+ ret = regmap_write(regmap, ISL12022_REG_DWA0, dw);
+ if (ret) {
+ dev_dbg(dev, "%s: writing DWA0 failed\n", __func__);
+ return ret;
+ }
+
+ /* Program the alarm and enable it for each setting */
+ regs[ISL12022_REG_SCA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_sec) | enable;
+ regs[ISL12022_REG_MNA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_min) | enable;
+ regs[ISL12022_REG_HRA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_hour) | enable;
+ regs[ISL12022_REG_DTA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_mday) | enable;
+ regs[ISL12022_REG_MOA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_mon + 1) | enable;
+ regs[ISL12022_REG_DWA0 - ISL12022_ALARM] = bin2bcd(alarm_tm->tm_wday & 7) | enable;
+
+ /* write ALARM registers */
+ ret = regmap_bulk_write(regmap, ISL12022_ALARM, &regs, sizeof(regs));
+ if (ret) {
+ dev_dbg(dev, "%s: writing ALARM registers failed\n", __func__);
+ return ret;
+ }
+
+ return 0;
+}
+
+static irqreturn_t isl12022_rtc_interrupt(int irq, void *data)
+{
+ struct isl12022 *isl12022 = data;
+ struct rtc_device *rtc = isl12022->rtc;
+ struct device *dev = &rtc->dev;
+ struct regmap *regmap = isl12022->regmap;
+ u32 val = 0;
+ unsigned long events = 0;
+ int ret;
+
+ ret = regmap_read(regmap, ISL12022_REG_SR, &val);
+ if (ret) {
+ dev_dbg(dev, "%s: reading SR failed\n", __func__);
+ return IRQ_HANDLED;
+ }
+
+ if (val & ISL12022_SR_ALM)
+ events |= RTC_IRQF | RTC_AF;
+
+ if (events & RTC_AF)
+ dev_dbg(dev, "alarm!\n");
+
+ if (!events)
+ return IRQ_NONE;
+
+ rtc_update_irq(rtc, 1, events);
+ return IRQ_HANDLED;
+}
+
+static int isl12022_rtc_alarm_irq_enable(struct device *dev,
+ unsigned int enabled)
+{
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+
+ /* Make sure enabled is 0 or 1 */
+ enabled = !!enabled;
+
+ if (isl12022->irq_enabled == enabled)
+ return 0;
+
+ if (enabled)
+ enable_irq(isl12022->irq);
+ else
+ disable_irq(isl12022->irq);
+
+ isl12022->irq_enabled = enabled;
+
+ return 0;
+}
+
+static int isl12022_setup_irq(struct device *dev, int irq)
+{
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
+ unsigned int reg_mask, reg_val;
+ u8 buf[ISL12022_ALARM_LEN] = { 0, };
+ int ret;
+
+ /* Clear and disable all alarm registers */
+ ret = regmap_bulk_write(regmap, ISL12022_ALARM, buf, sizeof(buf));
+ if (ret)
+ return ret;
+
+ /*
+ * Enable automatic reset of ALM bit and enable single event interrupt
+ * mode.
+ */
+ reg_mask = ISL12022_INT_ARST | ISL12022_INT_IM | ISL12022_INT_FO_MASK;
+ reg_val = ISL12022_INT_ARST | ISL12022_INT_FO_OFF;
+ ret = regmap_write_bits(regmap, ISL12022_REG_INT,
+ reg_mask, reg_val);
+ if (ret)
+ return ret;
+
+ ret = devm_request_threaded_irq(dev, irq, NULL,
+ isl12022_rtc_interrupt,
+ IRQF_SHARED | IRQF_ONESHOT,
+ isl12022_driver.driver.name,
+ isl12022);
+ if (ret)
+ return dev_err_probe(dev, ret, "Unable to request irq %d\n", irq);
+
+ isl12022->irq = irq;
+ return 0;
+}
+
static int isl12022_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
- struct regmap *regmap = dev_get_drvdata(dev);
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
u32 user, val;
int ret;
@@ -238,6 +456,9 @@ static const struct rtc_class_ops isl12022_rtc_ops = {
.ioctl = isl12022_rtc_ioctl,
.read_time = isl12022_rtc_read_time,
.set_time = isl12022_rtc_set_time,
+ .read_alarm = isl12022_rtc_read_alarm,
+ .set_alarm = isl12022_rtc_set_alarm,
+ .alarm_irq_enable = isl12022_rtc_alarm_irq_enable,
};
static const struct regmap_config regmap_config = {
@@ -248,7 +469,8 @@ static const struct regmap_config regmap_config = {
static int isl12022_register_clock(struct device *dev)
{
- struct regmap *regmap = dev_get_drvdata(dev);
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
struct clk_hw *hw;
int ret;
@@ -288,7 +510,8 @@ static const u32 trip_levels[2][7] = {
static void isl12022_set_trip_levels(struct device *dev)
{
- struct regmap *regmap = dev_get_drvdata(dev);
+ struct isl12022 *isl12022 = dev_get_drvdata(dev);
+ struct regmap *regmap = isl12022->regmap;
u32 levels[2] = {0, 0};
int ret, i, j, x[2];
u8 val, mask;
@@ -325,6 +548,7 @@ static void isl12022_set_trip_levels(struct device *dev)
static int isl12022_probe(struct i2c_client *client)
{
+ struct isl12022 *isl12022;
struct rtc_device *rtc;
struct regmap *regmap;
int ret;
@@ -332,13 +556,17 @@ static int isl12022_probe(struct i2c_client *client)
if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
return -ENODEV;
+ /* Allocate driver state */
+ isl12022 = devm_kzalloc(&client->dev, sizeof(*isl12022), GFP_KERNEL);
+ if (!isl12022)
+ return -ENOMEM;
+
regmap = devm_regmap_init_i2c(client, &regmap_config);
- if (IS_ERR(regmap)) {
- dev_err(&client->dev, "regmap allocation failed\n");
- return PTR_ERR(regmap);
- }
+ if (IS_ERR(regmap))
+ return dev_err_probe(&client->dev, PTR_ERR(regmap), "regmap allocation failed\n");
+ isl12022->regmap = regmap;
- dev_set_drvdata(&client->dev, regmap);
+ dev_set_drvdata(&client->dev, isl12022);
ret = isl12022_register_clock(&client->dev);
if (ret)
@@ -350,11 +578,20 @@ static int isl12022_probe(struct i2c_client *client)
rtc = devm_rtc_allocate_device(&client->dev);
if (IS_ERR(rtc))
return PTR_ERR(rtc);
+ isl12022->rtc = rtc;
rtc->ops = &isl12022_rtc_ops;
rtc->range_min = RTC_TIMESTAMP_BEGIN_2000;
rtc->range_max = RTC_TIMESTAMP_END_2099;
+ if (client->irq > 0) {
+ ret = isl12022_setup_irq(&client->dev, client->irq);
+ if (ret)
+ return ret;
+ } else {
+ clear_bit(RTC_FEATURE_ALARM, rtc->features);
+ }
+
return devm_rtc_register_device(rtc);
}
diff --git a/drivers/rtc/rtc-loongson.c b/drivers/rtc/rtc-loongson.c
index e8ffc1ab90b0..8d713e563d7c 100644
--- a/drivers/rtc/rtc-loongson.c
+++ b/drivers/rtc/rtc-loongson.c
@@ -381,7 +381,7 @@ MODULE_DEVICE_TABLE(acpi, loongson_rtc_acpi_match);
static struct platform_driver loongson_rtc_driver = {
.probe = loongson_rtc_probe,
- .remove_new = loongson_rtc_remove,
+ .remove = loongson_rtc_remove,
.driver = {
.name = "loongson-rtc",
.of_match_table = loongson_rtc_of_match,
diff --git a/drivers/rtc/rtc-lpc24xx.c b/drivers/rtc/rtc-lpc24xx.c
index df17c48ff086..2dcdc77ff646 100644
--- a/drivers/rtc/rtc-lpc24xx.c
+++ b/drivers/rtc/rtc-lpc24xx.c
@@ -285,7 +285,7 @@ MODULE_DEVICE_TABLE(of, lpc24xx_rtc_match);
static struct platform_driver lpc24xx_rtc_driver = {
.probe = lpc24xx_rtc_probe,
- .remove_new = lpc24xx_rtc_remove,
+ .remove = lpc24xx_rtc_remove,
.driver = {
.name = "lpc24xx-rtc",
.of_match_table = lpc24xx_rtc_match,
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c
index 5d30ce8e13ca..4e608bc8bbd3 100644
--- a/drivers/rtc/rtc-m48t59.c
+++ b/drivers/rtc/rtc-m48t59.c
@@ -71,7 +71,7 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
/* Issue the READ command */
M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
- tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR));
+ tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)) + pdata->yy_offset;
/* tm_mon is 0-11 */
tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
tm->tm_mday = bcd2bin(M48T59_READ(M48T59_MDAY));
@@ -82,10 +82,6 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm)
dev_dbg(dev, "Century bit is enabled\n");
tm->tm_year += 100; /* one century */
}
-#ifdef CONFIG_SPARC
- /* Sun SPARC machines count years since 1968 */
- tm->tm_year += 68;
-#endif
tm->tm_wday = bcd2bin(val & 0x07);
tm->tm_hour = bcd2bin(M48T59_READ(M48T59_HOUR) & 0x3F);
@@ -106,12 +102,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm)
struct m48t59_private *m48t59 = dev_get_drvdata(dev);
unsigned long flags;
u8 val = 0;
- int year = tm->tm_year;
-
-#ifdef CONFIG_SPARC
- /* Sun SPARC machines count years since 1968 */
- year -= 68;
-#endif
+ int year = tm->tm_year - pdata->yy_offset;
dev_dbg(dev, "RTC set time %04d-%02d-%02d %02d/%02d/%02d\n",
year + 1900, tm->tm_mon, tm->tm_mday,
@@ -162,11 +153,7 @@ static int m48t59_rtc_readalarm(struct device *dev, struct rtc_wkalrm *alrm)
/* Issue the READ command */
M48T59_SET_BITS(M48T59_CNTL_READ, M48T59_CNTL);
- tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR));
-#ifdef CONFIG_SPARC
- /* Sun SPARC machines count years since 1968 */
- tm->tm_year += 68;
-#endif
+ tm->tm_year = bcd2bin(M48T59_READ(M48T59_YEAR)) + pdata->yy_offset;
/* tm_mon is 0-11 */
tm->tm_mon = bcd2bin(M48T59_READ(M48T59_MONTH)) - 1;
@@ -197,12 +184,7 @@ static int m48t59_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
struct rtc_time *tm = &alrm->time;
u8 mday, hour, min, sec;
unsigned long flags;
- int year = tm->tm_year;
-
-#ifdef CONFIG_SPARC
- /* Sun SPARC machines count years since 1968 */
- year -= 68;
-#endif
+ int year = tm->tm_year - pdata->yy_offset;
/* If no irq, we don't support ALARM */
if (m48t59->irq == NO_IRQ)
diff --git a/drivers/rtc/rtc-max77686.c b/drivers/rtc/rtc-max77686.c
index 35a6021d9ba4..a8f4b645c09d 100644
--- a/drivers/rtc/rtc-max77686.c
+++ b/drivers/rtc/rtc-max77686.c
@@ -875,7 +875,7 @@ static struct platform_driver max77686_rtc_driver = {
.pm = &max77686_rtc_pm_ops,
},
.probe = max77686_rtc_probe,
- .remove_new = max77686_rtc_remove,
+ .remove = max77686_rtc_remove,
.id_table = rtc_id,
};
diff --git a/drivers/rtc/rtc-mc13xxx.c b/drivers/rtc/rtc-mc13xxx.c
index 763a42f422eb..e7b87130e624 100644
--- a/drivers/rtc/rtc-mc13xxx.c
+++ b/drivers/rtc/rtc-mc13xxx.c
@@ -350,7 +350,7 @@ MODULE_DEVICE_TABLE(platform, mc13xxx_rtc_idtable);
static struct platform_driver mc13xxx_rtc_driver = {
.id_table = mc13xxx_rtc_idtable,
- .remove_new = mc13xxx_rtc_remove,
+ .remove = mc13xxx_rtc_remove,
.driver = {
.name = DRIVER_NAME,
},
diff --git a/drivers/rtc/rtc-mc146818-lib.c b/drivers/rtc/rtc-mc146818-lib.c
index 651bf3c279c7..dbd2d5835f00 100644
--- a/drivers/rtc/rtc-mc146818-lib.c
+++ b/drivers/rtc/rtc-mc146818-lib.c
@@ -216,7 +216,7 @@ int mc146818_set_time(struct rtc_time *time)
unsigned char save_control, save_freq_select;
unsigned int yrs;
#ifdef CONFIG_MACH_DECSTATION
- unsigned int real_yrs, leap_yr;
+ unsigned int real_yrs;
#endif
unsigned char century = 0;
@@ -232,8 +232,6 @@ int mc146818_set_time(struct rtc_time *time)
#ifdef CONFIG_MACH_DECSTATION
real_yrs = yrs;
- leap_yr = ((!((yrs + 1900) % 4) && ((yrs + 1900) % 100)) ||
- !((yrs + 1900) % 400));
yrs = 72;
/*
@@ -241,7 +239,7 @@ int mc146818_set_time(struct rtc_time *time)
* for non-leap years, so that Feb, 29th is handled
* correctly.
*/
- if (!leap_yr && mon < 3) {
+ if (!is_leap_year(real_yrs + 1900) && mon < 3) {
real_yrs--;
yrs = 73;
}
diff --git a/drivers/rtc/rtc-mpc5121.c b/drivers/rtc/rtc-mpc5121.c
index 71eafe4fbc72..600328131603 100644
--- a/drivers/rtc/rtc-mpc5121.c
+++ b/drivers/rtc/rtc-mpc5121.c
@@ -398,7 +398,7 @@ static struct platform_driver mpc5121_rtc_driver = {
.of_match_table = of_match_ptr(mpc5121_rtc_match),
},
.probe = mpc5121_rtc_probe,
- .remove_new = mpc5121_rtc_remove,
+ .remove = mpc5121_rtc_remove,
};
module_platform_driver(mpc5121_rtc_driver);
diff --git a/drivers/rtc/rtc-mpfs.c b/drivers/rtc/rtc-mpfs.c
index 5b96a6d39210..3892b0f9917f 100644
--- a/drivers/rtc/rtc-mpfs.c
+++ b/drivers/rtc/rtc-mpfs.c
@@ -288,7 +288,7 @@ MODULE_DEVICE_TABLE(of, mpfs_rtc_of_match);
static struct platform_driver mpfs_rtc_driver = {
.probe = mpfs_rtc_probe,
- .remove_new = mpfs_rtc_remove,
+ .remove = mpfs_rtc_remove,
.driver = {
.name = "mpfs_rtc",
.of_match_table = mpfs_rtc_of_match,
diff --git a/drivers/rtc/rtc-mt6397.c b/drivers/rtc/rtc-mt6397.c
index 1617063669cc..152699219a2b 100644
--- a/drivers/rtc/rtc-mt6397.c
+++ b/drivers/rtc/rtc-mt6397.c
@@ -75,6 +75,7 @@ static int __mtk_rtc_read_time(struct mt6397_rtc *rtc,
tm->tm_min = data[RTC_OFFSET_MIN];
tm->tm_hour = data[RTC_OFFSET_HOUR];
tm->tm_mday = data[RTC_OFFSET_DOM];
+ tm->tm_wday = data[RTC_OFFSET_DOW];
tm->tm_mon = data[RTC_OFFSET_MTH] & RTC_TC_MTH_MASK;
tm->tm_year = data[RTC_OFFSET_YEAR];
@@ -86,9 +87,8 @@ exit:
static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- time64_t time;
struct mt6397_rtc *rtc = dev_get_drvdata(dev);
- int days, sec, ret;
+ int sec, ret;
do {
ret = __mtk_rtc_read_time(rtc, tm, &sec);
@@ -96,21 +96,9 @@ static int mtk_rtc_read_time(struct device *dev, struct rtc_time *tm)
goto exit;
} while (sec < tm->tm_sec);
- /* HW register use 7 bits to store year data, minus
- * RTC_MIN_YEAR_OFFSET before write year data to register, and plus
- * RTC_MIN_YEAR_OFFSET back after read year from register
- */
- tm->tm_year += RTC_MIN_YEAR_OFFSET;
-
- /* HW register start mon from one, but tm_mon start from zero. */
+ /* HW register start mon/wday from one, but tm_mon/tm_wday start from zero. */
tm->tm_mon--;
- time = rtc_tm_to_time64(tm);
-
- /* rtc_tm_to_time64 covert Gregorian date to seconds since
- * 01-01-1970 00:00:00, and this date is Thursday.
- */
- days = div_s64(time, 86400);
- tm->tm_wday = (days + 4) % 7;
+ tm->tm_wday--;
exit:
return ret;
@@ -122,13 +110,14 @@ static int mtk_rtc_set_time(struct device *dev, struct rtc_time *tm)
int ret;
u16 data[RTC_OFFSET_COUNT];
- tm->tm_year -= RTC_MIN_YEAR_OFFSET;
tm->tm_mon++;
+ tm->tm_wday++;
data[RTC_OFFSET_SEC] = tm->tm_sec;
data[RTC_OFFSET_MIN] = tm->tm_min;
data[RTC_OFFSET_HOUR] = tm->tm_hour;
data[RTC_OFFSET_DOM] = tm->tm_mday;
+ data[RTC_OFFSET_DOW] = tm->tm_wday;
data[RTC_OFFSET_MTH] = tm->tm_mon;
data[RTC_OFFSET_YEAR] = tm->tm_year;
@@ -178,7 +167,6 @@ static int mtk_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
tm->tm_mon = data[RTC_OFFSET_MTH] & RTC_AL_MTH_MASK;
tm->tm_year = data[RTC_OFFSET_YEAR] & RTC_AL_YEA_MASK;
- tm->tm_year += RTC_MIN_YEAR_OFFSET;
tm->tm_mon--;
return 0;
@@ -194,7 +182,6 @@ static int mtk_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alm)
int ret;
u16 data[RTC_OFFSET_COUNT];
- tm->tm_year -= RTC_MIN_YEAR_OFFSET;
tm->tm_mon++;
mutex_lock(&rtc->lock);
@@ -302,6 +289,10 @@ static int mtk_rtc_probe(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 1);
rtc->rtc_dev->ops = &mtk_rtc_ops;
+ rtc->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_1900;
+ rtc->rtc_dev->range_max = mktime64(2027, 12, 31, 23, 59, 59);
+ rtc->rtc_dev->start_secs = mktime64(1968, 1, 2, 0, 0, 0);
+ rtc->rtc_dev->set_start_time = true;
return devm_rtc_register_device(rtc->rtc_dev);
}
diff --git a/drivers/rtc/rtc-mt7622.c b/drivers/rtc/rtc-mt7622.c
index 094c649fc137..4cf0cbb31a31 100644
--- a/drivers/rtc/rtc-mt7622.c
+++ b/drivers/rtc/rtc-mt7622.c
@@ -394,7 +394,7 @@ static SIMPLE_DEV_PM_OPS(mtk_rtc_pm_ops, mtk_rtc_suspend, mtk_rtc_resume);
static struct platform_driver mtk_rtc_driver = {
.probe = mtk_rtc_probe,
- .remove_new = mtk_rtc_remove,
+ .remove = mtk_rtc_remove,
.driver = {
.name = MTK_RTC_DEV,
.of_match_table = mtk_rtc_match,
diff --git a/drivers/rtc/rtc-mv.c b/drivers/rtc/rtc-mv.c
index db31da56bfa7..51029c536244 100644
--- a/drivers/rtc/rtc-mv.c
+++ b/drivers/rtc/rtc-mv.c
@@ -308,7 +308,7 @@ MODULE_DEVICE_TABLE(of, rtc_mv_of_match_table);
* triggering a section mismatch warning.
*/
static struct platform_driver mv_rtc_driver __refdata = {
- .remove_new = __exit_p(mv_rtc_remove),
+ .remove = __exit_p(mv_rtc_remove),
.driver = {
.name = "rtc-mv",
.of_match_table = of_match_ptr(rtc_mv_of_match_table),
diff --git a/drivers/rtc/rtc-mxc_v2.c b/drivers/rtc/rtc-mxc_v2.c
index 6934bce4b29f..13c041bb79f1 100644
--- a/drivers/rtc/rtc-mxc_v2.c
+++ b/drivers/rtc/rtc-mxc_v2.c
@@ -381,7 +381,7 @@ static struct platform_driver mxc_rtc_driver = {
.of_match_table = mxc_ids,
},
.probe = mxc_rtc_probe,
- .remove_new = mxc_rtc_remove,
+ .remove = mxc_rtc_remove,
};
module_platform_driver(mxc_rtc_driver);
diff --git a/drivers/rtc/rtc-nxp-bbnsm.c b/drivers/rtc/rtc-nxp-bbnsm.c
index acbfbeb8b070..fa3b0328c7a2 100644
--- a/drivers/rtc/rtc-nxp-bbnsm.c
+++ b/drivers/rtc/rtc-nxp-bbnsm.c
@@ -197,13 +197,28 @@ static int bbnsm_rtc_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "failed to request irq %d: %d\n",
bbnsm->irq, ret);
- return ret;
+ goto err;
}
bbnsm->rtc->ops = &bbnsm_rtc_ops;
bbnsm->rtc->range_max = U32_MAX;
- return devm_rtc_register_device(bbnsm->rtc);
+ ret = devm_rtc_register_device(bbnsm->rtc);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ dev_pm_clear_wake_irq(&pdev->dev);
+ device_init_wakeup(&pdev->dev, false);
+ return ret;
+}
+
+static void bbnsm_rtc_remove(struct platform_device *pdev)
+{
+ dev_pm_clear_wake_irq(&pdev->dev);
+ device_init_wakeup(&pdev->dev, false);
}
static const struct of_device_id bbnsm_dt_ids[] = {
@@ -218,6 +233,7 @@ static struct platform_driver bbnsm_rtc_driver = {
.of_match_table = bbnsm_dt_ids,
},
.probe = bbnsm_rtc_probe,
+ .remove = bbnsm_rtc_remove,
};
module_platform_driver(bbnsm_rtc_driver);
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index e6b2a9c15b54..c123778e2d9b 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -1014,7 +1014,7 @@ static void omap_rtc_shutdown(struct platform_device *pdev)
static struct platform_driver omap_rtc_driver = {
.probe = omap_rtc_probe,
- .remove_new = omap_rtc_remove,
+ .remove = omap_rtc_remove,
.shutdown = omap_rtc_shutdown,
.driver = {
.name = "omap_rtc",
diff --git a/drivers/rtc/rtc-palmas.c b/drivers/rtc/rtc-palmas.c
index 6971e47c6021..7256a88b490c 100644
--- a/drivers/rtc/rtc-palmas.c
+++ b/drivers/rtc/rtc-palmas.c
@@ -346,7 +346,7 @@ MODULE_DEVICE_TABLE(of, of_palmas_rtc_match);
static struct platform_driver palmas_rtc_driver = {
.probe = palmas_rtc_probe,
- .remove_new = palmas_rtc_remove,
+ .remove = palmas_rtc_remove,
.driver = {
.name = "palmas-rtc",
.pm = &palmas_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-pcf50633.c b/drivers/rtc/rtc-pcf50633.c
index 23edd11aa40c..c019c4d91c7d 100644
--- a/drivers/rtc/rtc-pcf50633.c
+++ b/drivers/rtc/rtc-pcf50633.c
@@ -273,7 +273,7 @@ static struct platform_driver pcf50633_rtc_driver = {
.name = "pcf50633-rtc",
},
.probe = pcf50633_rtc_probe,
- .remove_new = pcf50633_rtc_remove,
+ .remove = pcf50633_rtc_remove,
};
module_platform_driver(pcf50633_rtc_driver);
diff --git a/drivers/rtc/rtc-pcf8563.c b/drivers/rtc/rtc-pcf8563.c
index 647d52f1f5c5..5a084d426e58 100644
--- a/drivers/rtc/rtc-pcf8563.c
+++ b/drivers/rtc/rtc-pcf8563.c
@@ -11,14 +11,15 @@
* https://www.nxp.com/docs/en/data-sheet/PCF8563.pdf
*/
+#include <linux/bcd.h>
#include <linux/clk-provider.h>
+#include <linux/err.h>
#include <linux/i2c.h>
-#include <linux/bcd.h>
-#include <linux/rtc.h>
-#include <linux/slab.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
#define PCF8563_REG_ST1 0x00 /* status */
#define PCF8563_REG_ST2 0x01
@@ -77,64 +78,18 @@ struct pcf8563 {
*/
int c_polarity; /* 0: MO_C=1 means 19xx, otherwise MO_C=1 means 20xx */
- struct i2c_client *client;
+ struct regmap *regmap;
#ifdef CONFIG_COMMON_CLK
struct clk_hw clkout_hw;
#endif
};
-static int pcf8563_read_block_data(struct i2c_client *client, unsigned char reg,
- unsigned char length, unsigned char *buf)
-{
- struct i2c_msg msgs[] = {
- {/* setup read ptr */
- .addr = client->addr,
- .len = 1,
- .buf = &reg,
- },
- {
- .addr = client->addr,
- .flags = I2C_M_RD,
- .len = length,
- .buf = buf
- },
- };
-
- if ((i2c_transfer(client->adapter, msgs, 2)) != 2) {
- dev_err(&client->dev, "%s: read error\n", __func__);
- return -EIO;
- }
-
- return 0;
-}
-
-static int pcf8563_write_block_data(struct i2c_client *client,
- unsigned char reg, unsigned char length,
- unsigned char *buf)
-{
- int i, err;
-
- for (i = 0; i < length; i++) {
- unsigned char data[2] = { reg + i, buf[i] };
-
- err = i2c_master_send(client, data, sizeof(data));
- if (err != sizeof(data)) {
- dev_err(&client->dev,
- "%s: err=%d addr=%02x, data=%02x\n",
- __func__, err, data[0], data[1]);
- return -EIO;
- }
- }
-
- return 0;
-}
-
-static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on)
+static int pcf8563_set_alarm_mode(struct pcf8563 *pcf8563, bool on)
{
- unsigned char buf;
+ u32 buf;
int err;
- err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf);
+ err = regmap_read(pcf8563->regmap, PCF8563_REG_ST2, &buf);
if (err < 0)
return err;
@@ -145,23 +100,17 @@ static int pcf8563_set_alarm_mode(struct i2c_client *client, bool on)
buf &= ~(PCF8563_BIT_AF | PCF8563_BITS_ST2_N);
- err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf);
- if (err < 0) {
- dev_err(&client->dev, "%s: write error\n", __func__);
- return -EIO;
- }
-
- return 0;
+ return regmap_write(pcf8563->regmap, PCF8563_REG_ST2, buf);
}
-static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en,
+static int pcf8563_get_alarm_mode(struct pcf8563 *pcf8563, unsigned char *en,
unsigned char *pen)
{
- unsigned char buf;
+ u32 buf;
int err;
- err = pcf8563_read_block_data(client, PCF8563_REG_ST2, 1, &buf);
- if (err)
+ err = regmap_read(pcf8563->regmap, PCF8563_REG_ST2, &buf);
+ if (err < 0)
return err;
if (en)
@@ -174,17 +123,17 @@ static int pcf8563_get_alarm_mode(struct i2c_client *client, unsigned char *en,
static irqreturn_t pcf8563_irq(int irq, void *dev_id)
{
- struct pcf8563 *pcf8563 = i2c_get_clientdata(dev_id);
- int err;
+ struct pcf8563 *pcf8563 = dev_id;
char pending;
+ int err;
- err = pcf8563_get_alarm_mode(pcf8563->client, NULL, &pending);
+ err = pcf8563_get_alarm_mode(pcf8563, NULL, &pending);
if (err)
return IRQ_NONE;
if (pending) {
rtc_update_irq(pcf8563->rtc, 1, RTC_IRQF | RTC_AF);
- pcf8563_set_alarm_mode(pcf8563->client, 1);
+ pcf8563_set_alarm_mode(pcf8563, 1);
return IRQ_HANDLED;
}
@@ -197,22 +146,22 @@ static irqreturn_t pcf8563_irq(int irq, void *dev_id)
*/
static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
unsigned char buf[9];
int err;
- err = pcf8563_read_block_data(client, PCF8563_REG_ST1, 9, buf);
- if (err)
+ err = regmap_bulk_read(pcf8563->regmap, PCF8563_REG_ST1, buf,
+ sizeof(buf));
+ if (err < 0)
return err;
if (buf[PCF8563_REG_SC] & PCF8563_SC_LV) {
- dev_err(&client->dev,
+ dev_err(dev,
"low voltage detected, date/time is not reliable.\n");
return -EINVAL;
}
- dev_dbg(&client->dev,
+ dev_dbg(dev,
"%s: raw data is st1=%02x, st2=%02x, sec=%02x, min=%02x, hr=%02x, "
"mday=%02x, wday=%02x, mon=%02x, year=%02x\n",
__func__,
@@ -220,7 +169,6 @@ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
buf[4], buf[5], buf[6], buf[7],
buf[8]);
-
tm->tm_sec = bcd2bin(buf[PCF8563_REG_SC] & 0x7F);
tm->tm_min = bcd2bin(buf[PCF8563_REG_MN] & 0x7F);
tm->tm_hour = bcd2bin(buf[PCF8563_REG_HR] & 0x3F); /* rtc hr 0-23 */
@@ -232,7 +180,7 @@ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
pcf8563->c_polarity = (buf[PCF8563_REG_MO] & PCF8563_MO_C) ?
(tm->tm_year >= 100) : (tm->tm_year < 100);
- dev_dbg(&client->dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
+ dev_dbg(dev, "%s: tm is secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
@@ -243,11 +191,10 @@ static int pcf8563_rtc_read_time(struct device *dev, struct rtc_time *tm)
static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
{
- struct i2c_client *client = to_i2c_client(dev);
- struct pcf8563 *pcf8563 = i2c_get_clientdata(client);
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
unsigned char buf[9];
- dev_dbg(&client->dev, "%s: secs=%d, mins=%d, hours=%d, "
+ dev_dbg(dev, "%s: secs=%d, mins=%d, hours=%d, "
"mday=%d, mon=%d, year=%d, wday=%d\n",
__func__,
tm->tm_sec, tm->tm_min, tm->tm_hour,
@@ -270,22 +217,24 @@ static int pcf8563_rtc_set_time(struct device *dev, struct rtc_time *tm)
buf[PCF8563_REG_DW] = tm->tm_wday & 0x07;
- return pcf8563_write_block_data(client, PCF8563_REG_SC,
- 9 - PCF8563_REG_SC, buf + PCF8563_REG_SC);
+ return regmap_bulk_write(pcf8563->regmap, PCF8563_REG_SC,
+ buf + PCF8563_REG_SC,
+ sizeof(buf) - PCF8563_REG_SC);
}
static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
int ret;
switch (cmd) {
case RTC_VL_READ:
- ret = i2c_smbus_read_byte_data(client, PCF8563_REG_SC);
+ ret = regmap_test_bits(pcf8563->regmap, PCF8563_REG_SC,
+ PCF8563_SC_LV);
if (ret < 0)
return ret;
- return put_user(ret & PCF8563_SC_LV ? RTC_VL_DATA_INVALID : 0,
+ return put_user(ret ? RTC_VL_DATA_INVALID : 0,
(unsigned int __user *)arg);
default:
return -ENOIOCTLCMD;
@@ -294,15 +243,16 @@ static int pcf8563_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long
static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
unsigned char buf[4];
int err;
- err = pcf8563_read_block_data(client, PCF8563_REG_AMN, 4, buf);
- if (err)
+ err = regmap_bulk_read(pcf8563->regmap, PCF8563_REG_AMN, buf,
+ sizeof(buf));
+ if (err < 0)
return err;
- dev_dbg(&client->dev,
+ dev_dbg(dev,
"%s: raw data is min=%02x, hr=%02x, mday=%02x, wday=%02x\n",
__func__, buf[0], buf[1], buf[2], buf[3]);
@@ -312,11 +262,11 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
tm->time.tm_mday = bcd2bin(buf[2] & 0x3F);
tm->time.tm_wday = bcd2bin(buf[3] & 0x7);
- err = pcf8563_get_alarm_mode(client, &tm->enabled, &tm->pending);
+ err = pcf8563_get_alarm_mode(pcf8563, &tm->enabled, &tm->pending);
if (err < 0)
return err;
- dev_dbg(&client->dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d,"
+ dev_dbg(dev, "%s: tm is mins=%d, hours=%d, mday=%d, wday=%d,"
" enabled=%d, pending=%d\n", __func__, tm->time.tm_min,
tm->time.tm_hour, tm->time.tm_mday, tm->time.tm_wday,
tm->enabled, tm->pending);
@@ -326,7 +276,7 @@ static int pcf8563_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *tm)
static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
{
- struct i2c_client *client = to_i2c_client(dev);
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
unsigned char buf[4];
int err;
@@ -335,17 +285,20 @@ static int pcf8563_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *tm)
buf[2] = bin2bcd(tm->time.tm_mday);
buf[3] = tm->time.tm_wday & 0x07;
- err = pcf8563_write_block_data(client, PCF8563_REG_AMN, 4, buf);
+ err = regmap_bulk_write(pcf8563->regmap, PCF8563_REG_SC, buf,
+ sizeof(buf));
if (err)
return err;
- return pcf8563_set_alarm_mode(client, !!tm->enabled);
+ return pcf8563_set_alarm_mode(pcf8563, !!tm->enabled);
}
static int pcf8563_irq_enable(struct device *dev, unsigned int enabled)
{
+ struct pcf8563 *pcf8563 = dev_get_drvdata(dev);
+
dev_dbg(dev, "%s: en=%d\n", __func__, enabled);
- return pcf8563_set_alarm_mode(to_i2c_client(dev), !!enabled);
+ return pcf8563_set_alarm_mode(pcf8563, !!enabled);
}
#ifdef CONFIG_COMMON_CLK
@@ -366,10 +319,10 @@ static unsigned long pcf8563_clkout_recalc_rate(struct clk_hw *hw,
unsigned long parent_rate)
{
struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
- struct i2c_client *client = pcf8563->client;
- unsigned char buf;
- int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ u32 buf;
+ int ret;
+ ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf);
if (ret < 0)
return 0;
@@ -393,11 +346,10 @@ static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
unsigned long parent_rate)
{
struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
- struct i2c_client *client = pcf8563->client;
- unsigned char buf;
- int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
- int i;
+ int i, ret;
+ u32 buf;
+ ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf);
if (ret < 0)
return ret;
@@ -405,10 +357,10 @@ static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
if (clkout_rates[i] == rate) {
buf &= ~PCF8563_REG_CLKO_F_MASK;
buf |= i;
- ret = pcf8563_write_block_data(client,
- PCF8563_REG_CLKO, 1,
- &buf);
- return ret;
+ return regmap_update_bits(pcf8563->regmap,
+ PCF8563_REG_CLKO,
+ PCF8563_REG_CLKO_F_MASK,
+ buf);
}
return -EINVAL;
@@ -417,10 +369,10 @@ static int pcf8563_clkout_set_rate(struct clk_hw *hw, unsigned long rate,
static int pcf8563_clkout_control(struct clk_hw *hw, bool enable)
{
struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
- struct i2c_client *client = pcf8563->client;
- unsigned char buf;
- int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ u32 buf;
+ int ret;
+ ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf);
if (ret < 0)
return ret;
@@ -429,8 +381,8 @@ static int pcf8563_clkout_control(struct clk_hw *hw, bool enable)
else
buf &= ~PCF8563_REG_CLKO_FE;
- ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
- return ret;
+ return regmap_update_bits(pcf8563->regmap, PCF8563_REG_CLKO,
+ PCF8563_REG_CLKO_FE, buf);
}
static int pcf8563_clkout_prepare(struct clk_hw *hw)
@@ -446,10 +398,10 @@ static void pcf8563_clkout_unprepare(struct clk_hw *hw)
static int pcf8563_clkout_is_prepared(struct clk_hw *hw)
{
struct pcf8563 *pcf8563 = clkout_hw_to_pcf8563(hw);
- struct i2c_client *client = pcf8563->client;
- unsigned char buf;
- int ret = pcf8563_read_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ u32 buf;
+ int ret;
+ ret = regmap_read(pcf8563->regmap, PCF8563_REG_CLKO, &buf);
if (ret < 0)
return ret;
@@ -467,16 +419,14 @@ static const struct clk_ops pcf8563_clkout_ops = {
static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
{
- struct i2c_client *client = pcf8563->client;
- struct device_node *node = client->dev.of_node;
- struct clk *clk;
+ struct device_node *node = pcf8563->rtc->dev.of_node;
struct clk_init_data init;
+ struct clk *clk;
int ret;
- unsigned char buf;
/* disable the clkout output */
- buf = 0;
- ret = pcf8563_write_block_data(client, PCF8563_REG_CLKO, 1, &buf);
+ ret = regmap_clear_bits(pcf8563->regmap, PCF8563_REG_CLKO,
+ PCF8563_REG_CLKO_FE);
if (ret < 0)
return ERR_PTR(ret);
@@ -491,7 +441,7 @@ static struct clk *pcf8563_clkout_register_clk(struct pcf8563 *pcf8563)
of_property_read_string(node, "clock-output-names", &init.name);
/* register the clock */
- clk = devm_clk_register(&client->dev, &pcf8563->clkout_hw);
+ clk = devm_clk_register(&pcf8563->rtc->dev, &pcf8563->clkout_hw);
if (!IS_ERR(clk))
of_clk_add_provider(node, of_clk_src_simple_get, clk);
@@ -509,11 +459,16 @@ static const struct rtc_class_ops pcf8563_rtc_ops = {
.alarm_irq_enable = pcf8563_irq_enable,
};
+static const struct regmap_config regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = 0xF,
+};
+
static int pcf8563_probe(struct i2c_client *client)
{
struct pcf8563 *pcf8563;
int err;
- unsigned char buf;
dev_dbg(&client->dev, "%s\n", __func__);
@@ -525,20 +480,23 @@ static int pcf8563_probe(struct i2c_client *client)
if (!pcf8563)
return -ENOMEM;
+ pcf8563->regmap = devm_regmap_init_i2c(client, &regmap_config);
+ if (IS_ERR(pcf8563->regmap))
+ return PTR_ERR(pcf8563->regmap);
+
i2c_set_clientdata(client, pcf8563);
- pcf8563->client = client;
+ device_set_wakeup_capable(&client->dev, 1);
/* Set timer to lowest frequency to save power (ref Haoyu datasheet) */
- buf = PCF8563_TMRC_1_60;
- err = pcf8563_write_block_data(client, PCF8563_REG_TMRC, 1, &buf);
+ err = regmap_set_bits(pcf8563->regmap, PCF8563_REG_TMRC,
+ PCF8563_TMRC_1_60);
if (err < 0) {
dev_err(&client->dev, "%s: write error\n", __func__);
return err;
}
/* Clear flags and disable interrupts */
- buf = 0;
- err = pcf8563_write_block_data(client, PCF8563_REG_ST2, 1, &buf);
+ err = regmap_write(pcf8563->regmap, PCF8563_REG_ST2, 0);
if (err < 0) {
dev_err(&client->dev, "%s: write error\n", __func__);
return err;
diff --git a/drivers/rtc/rtc-pic32.c b/drivers/rtc/rtc-pic32.c
index 4f85e0c3d757..bed3c27e665f 100644
--- a/drivers/rtc/rtc-pic32.c
+++ b/drivers/rtc/rtc-pic32.c
@@ -371,7 +371,7 @@ MODULE_DEVICE_TABLE(of, pic32_rtc_dt_ids);
static struct platform_driver pic32_rtc_driver = {
.probe = pic32_rtc_probe,
- .remove_new = pic32_rtc_remove,
+ .remove = pic32_rtc_remove,
.driver = {
.name = "pic32-rtc",
.of_match_table = of_match_ptr(pic32_rtc_dt_ids),
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
index c32fba550c8e..2f32187ecc8d 100644
--- a/drivers/rtc/rtc-pm8xxx.c
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -537,7 +537,7 @@ static void pm8xxx_remove(struct platform_device *pdev)
static struct platform_driver pm8xxx_rtc_driver = {
.probe = pm8xxx_rtc_probe,
- .remove_new = pm8xxx_remove,
+ .remove = pm8xxx_remove,
.driver = {
.name = "rtc-pm8xxx",
.of_match_table = pm8xxx_id_table,
diff --git a/drivers/rtc/rtc-pxa.c b/drivers/rtc/rtc-pxa.c
index cdb39fc4cab5..34d8545c8e15 100644
--- a/drivers/rtc/rtc-pxa.c
+++ b/drivers/rtc/rtc-pxa.c
@@ -409,7 +409,7 @@ static SIMPLE_DEV_PM_OPS(pxa_rtc_pm_ops, pxa_rtc_suspend, pxa_rtc_resume);
* triggering a section mismatch warning.
*/
static struct platform_driver pxa_rtc_driver __refdata = {
- .remove_new = __exit_p(pxa_rtc_remove),
+ .remove = __exit_p(pxa_rtc_remove),
.driver = {
.name = "pxa-rtc",
.of_match_table = of_match_ptr(pxa_rtc_dt_ids),
diff --git a/drivers/rtc/rtc-rc5t583.c b/drivers/rtc/rtc-rc5t583.c
index 115c46f862f9..eecb49bab56a 100644
--- a/drivers/rtc/rtc-rc5t583.c
+++ b/drivers/rtc/rtc-rc5t583.c
@@ -298,7 +298,7 @@ static SIMPLE_DEV_PM_OPS(rc5t583_rtc_pm_ops, rc5t583_rtc_suspend,
static struct platform_driver rc5t583_rtc_driver = {
.probe = rc5t583_rtc_probe,
- .remove_new = rc5t583_rtc_remove,
+ .remove = rc5t583_rtc_remove,
.driver = {
.name = "rtc-rc5t583",
.pm = &rc5t583_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-renesas-rtca3.c b/drivers/rtc/rtc-renesas-rtca3.c
new file mode 100644
index 000000000000..d127933bfc8a
--- /dev/null
+++ b/drivers/rtc/rtc-renesas-rtca3.c
@@ -0,0 +1,900 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * On-Chip RTC Support available on RZ/G3S SoC
+ *
+ * Copyright (C) 2024 Renesas Electronics Corp.
+ */
+#include <linux/bcd.h>
+#include <linux/bitfield.h>
+#include <linux/cleanup.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/iopoll.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/reset.h>
+#include <linux/rtc.h>
+
+/* Counter registers. */
+#define RTCA3_RSECCNT 0x2
+#define RTCA3_RSECCNT_SEC GENMASK(6, 0)
+#define RTCA3_RMINCNT 0x4
+#define RTCA3_RMINCNT_MIN GENMASK(6, 0)
+#define RTCA3_RHRCNT 0x6
+#define RTCA3_RHRCNT_HR GENMASK(5, 0)
+#define RTCA3_RHRCNT_PM BIT(6)
+#define RTCA3_RWKCNT 0x8
+#define RTCA3_RWKCNT_WK GENMASK(2, 0)
+#define RTCA3_RDAYCNT 0xa
+#define RTCA3_RDAYCNT_DAY GENMASK(5, 0)
+#define RTCA3_RMONCNT 0xc
+#define RTCA3_RMONCNT_MONTH GENMASK(4, 0)
+#define RTCA3_RYRCNT 0xe
+#define RTCA3_RYRCNT_YEAR GENMASK(7, 0)
+
+/* Alarm registers. */
+#define RTCA3_RSECAR 0x10
+#define RTCA3_RSECAR_SEC GENMASK(6, 0)
+#define RTCA3_RMINAR 0x12
+#define RTCA3_RMINAR_MIN GENMASK(6, 0)
+#define RTCA3_RHRAR 0x14
+#define RTCA3_RHRAR_HR GENMASK(5, 0)
+#define RTCA3_RHRAR_PM BIT(6)
+#define RTCA3_RWKAR 0x16
+#define RTCA3_RWKAR_DAYW GENMASK(2, 0)
+#define RTCA3_RDAYAR 0x18
+#define RTCA3_RDAYAR_DATE GENMASK(5, 0)
+#define RTCA3_RMONAR 0x1a
+#define RTCA3_RMONAR_MON GENMASK(4, 0)
+#define RTCA3_RYRAR 0x1c
+#define RTCA3_RYRAR_YR GENMASK(7, 0)
+#define RTCA3_RYRAREN 0x1e
+
+/* Alarm enable bit (for all alarm registers). */
+#define RTCA3_AR_ENB BIT(7)
+
+/* Control registers. */
+#define RTCA3_RCR1 0x22
+#define RTCA3_RCR1_AIE BIT(0)
+#define RTCA3_RCR1_CIE BIT(1)
+#define RTCA3_RCR1_PIE BIT(2)
+#define RTCA3_RCR1_PES GENMASK(7, 4)
+#define RTCA3_RCR1_PES_1_64_SEC 0x8
+#define RTCA3_RCR2 0x24
+#define RTCA3_RCR2_START BIT(0)
+#define RTCA3_RCR2_RESET BIT(1)
+#define RTCA3_RCR2_AADJE BIT(4)
+#define RTCA3_RCR2_ADJP BIT(5)
+#define RTCA3_RCR2_HR24 BIT(6)
+#define RTCA3_RCR2_CNTMD BIT(7)
+#define RTCA3_RSR 0x20
+#define RTCA3_RSR_AF BIT(0)
+#define RTCA3_RSR_CF BIT(1)
+#define RTCA3_RSR_PF BIT(2)
+#define RTCA3_RADJ 0x2e
+#define RTCA3_RADJ_ADJ GENMASK(5, 0)
+#define RTCA3_RADJ_ADJ_MAX 0x3f
+#define RTCA3_RADJ_PMADJ GENMASK(7, 6)
+#define RTCA3_RADJ_PMADJ_NONE 0
+#define RTCA3_RADJ_PMADJ_ADD 1
+#define RTCA3_RADJ_PMADJ_SUB 2
+
+/* Polling operation timeouts. */
+#define RTCA3_DEFAULT_TIMEOUT_US 150
+#define RTCA3_IRQSET_TIMEOUT_US 5000
+#define RTCA3_START_TIMEOUT_US 150000
+#define RTCA3_RESET_TIMEOUT_US 200000
+
+/**
+ * enum rtca3_alrm_set_step - RTCA3 alarm set steps
+ * @RTCA3_ALRM_SSTEP_DONE: alarm setup done step
+ * @RTCA3_ALRM_SSTEP_IRQ: two 1/64 periodic IRQs were generated step
+ * @RTCA3_ALRM_SSTEP_INIT: alarm setup initialization step
+ */
+enum rtca3_alrm_set_step {
+ RTCA3_ALRM_SSTEP_DONE = 0,
+ RTCA3_ALRM_SSTEP_IRQ = 1,
+ RTCA3_ALRM_SSTEP_INIT = 3,
+};
+
+/**
+ * struct rtca3_ppb_per_cycle - PPB per cycle
+ * @ten_sec: PPB per cycle in 10 seconds adjutment mode
+ * @sixty_sec: PPB per cycle in 60 seconds adjustment mode
+ */
+struct rtca3_ppb_per_cycle {
+ int ten_sec;
+ int sixty_sec;
+};
+
+/**
+ * struct rtca3_priv - RTCA3 private data structure
+ * @base: base address
+ * @rtc_dev: RTC device
+ * @rstc: reset control
+ * @set_alarm_completion: alarm setup completion
+ * @alrm_sstep: alarm setup step (see enum rtca3_alrm_set_step)
+ * @lock: device lock
+ * @ppb: ppb per cycle for each the available adjustment modes
+ * @wakeup_irq: wakeup IRQ
+ */
+struct rtca3_priv {
+ void __iomem *base;
+ struct rtc_device *rtc_dev;
+ struct reset_control *rstc;
+ struct completion set_alarm_completion;
+ atomic_t alrm_sstep;
+ spinlock_t lock;
+ struct rtca3_ppb_per_cycle ppb;
+ int wakeup_irq;
+};
+
+static void rtca3_byte_update_bits(struct rtca3_priv *priv, u8 off, u8 mask, u8 val)
+{
+ u8 tmp;
+
+ tmp = readb(priv->base + off);
+ tmp &= ~mask;
+ tmp |= (val & mask);
+ writeb(tmp, priv->base + off);
+}
+
+static u8 rtca3_alarm_handler_helper(struct rtca3_priv *priv)
+{
+ u8 val, pending;
+
+ val = readb(priv->base + RTCA3_RSR);
+ pending = val & RTCA3_RSR_AF;
+ writeb(val & ~pending, priv->base + RTCA3_RSR);
+
+ if (pending)
+ rtc_update_irq(priv->rtc_dev, 1, RTC_AF | RTC_IRQF);
+
+ return pending;
+}
+
+static irqreturn_t rtca3_alarm_handler(int irq, void *dev_id)
+{
+ struct rtca3_priv *priv = dev_id;
+ u8 pending;
+
+ guard(spinlock)(&priv->lock);
+
+ pending = rtca3_alarm_handler_helper(priv);
+
+ return IRQ_RETVAL(pending);
+}
+
+static irqreturn_t rtca3_periodic_handler(int irq, void *dev_id)
+{
+ struct rtca3_priv *priv = dev_id;
+ u8 val, pending;
+
+ guard(spinlock)(&priv->lock);
+
+ val = readb(priv->base + RTCA3_RSR);
+ pending = val & RTCA3_RSR_PF;
+
+ if (pending) {
+ writeb(val & ~pending, priv->base + RTCA3_RSR);
+
+ if (atomic_read(&priv->alrm_sstep) > RTCA3_ALRM_SSTEP_IRQ) {
+ /* Alarm setup in progress. */
+ atomic_dec(&priv->alrm_sstep);
+
+ if (atomic_read(&priv->alrm_sstep) == RTCA3_ALRM_SSTEP_IRQ) {
+ /*
+ * We got 2 * 1/64 periodic interrupts. Disable
+ * interrupt and let alarm setup continue.
+ */
+ rtca3_byte_update_bits(priv, RTCA3_RCR1,
+ RTCA3_RCR1_PIE, 0);
+ readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, val,
+ !(val & RTCA3_RCR1_PIE),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ complete(&priv->set_alarm_completion);
+ }
+ }
+ }
+
+ return IRQ_RETVAL(pending);
+}
+
+static void rtca3_prepare_cntalrm_regs_for_read(struct rtca3_priv *priv, bool cnt)
+{
+ /* Offset b/w time and alarm registers. */
+ u8 offset = cnt ? 0 : 0xe;
+
+ /*
+ * According to HW manual (section 22.6.4. Notes on writing to and
+ * reading from registers) after writing to count registers, alarm
+ * registers, year alarm enable register, bits RCR2.AADJE, AADJP,
+ * and HR24 register, we need to do 3 empty reads before being
+ * able to fetch the registers content.
+ */
+ for (u8 i = 0; i < 3; i++) {
+ readb(priv->base + RTCA3_RSECCNT + offset);
+ readb(priv->base + RTCA3_RMINCNT + offset);
+ readb(priv->base + RTCA3_RHRCNT + offset);
+ readb(priv->base + RTCA3_RWKCNT + offset);
+ readb(priv->base + RTCA3_RDAYCNT + offset);
+ readw(priv->base + RTCA3_RYRCNT + offset);
+ if (!cnt)
+ readb(priv->base + RTCA3_RYRAREN);
+ }
+}
+
+static int rtca3_read_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ u8 sec, min, hour, wday, mday, month, tmp;
+ u8 trials = 0;
+ u32 year100;
+ u16 year;
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ tmp = readb(priv->base + RTCA3_RCR2);
+ if (!(tmp & RTCA3_RCR2_START))
+ return -EINVAL;
+
+ do {
+ /* Clear carry interrupt. */
+ rtca3_byte_update_bits(priv, RTCA3_RSR, RTCA3_RSR_CF, 0);
+
+ /* Read counters. */
+ sec = readb(priv->base + RTCA3_RSECCNT);
+ min = readb(priv->base + RTCA3_RMINCNT);
+ hour = readb(priv->base + RTCA3_RHRCNT);
+ wday = readb(priv->base + RTCA3_RWKCNT);
+ mday = readb(priv->base + RTCA3_RDAYCNT);
+ month = readb(priv->base + RTCA3_RMONCNT);
+ year = readw(priv->base + RTCA3_RYRCNT);
+
+ tmp = readb(priv->base + RTCA3_RSR);
+
+ /*
+ * We cannot generate carries due to reading 64Hz counter as
+ * the driver doesn't implement carry, thus, carries will be
+ * generated once per seconds. Add a timeout of 5 trials here
+ * to avoid infinite loop, if any.
+ */
+ } while ((tmp & RTCA3_RSR_CF) && ++trials < 5);
+
+ if (trials >= 5)
+ return -ETIMEDOUT;
+
+ tm->tm_sec = bcd2bin(FIELD_GET(RTCA3_RSECCNT_SEC, sec));
+ tm->tm_min = bcd2bin(FIELD_GET(RTCA3_RMINCNT_MIN, min));
+ tm->tm_hour = bcd2bin(FIELD_GET(RTCA3_RHRCNT_HR, hour));
+ tm->tm_wday = bcd2bin(FIELD_GET(RTCA3_RWKCNT_WK, wday));
+ tm->tm_mday = bcd2bin(FIELD_GET(RTCA3_RDAYCNT_DAY, mday));
+ tm->tm_mon = bcd2bin(FIELD_GET(RTCA3_RMONCNT_MONTH, month)) - 1;
+ year = FIELD_GET(RTCA3_RYRCNT_YEAR, year);
+ year100 = bcd2bin((year == 0x99) ? 0x19 : 0x20);
+ tm->tm_year = (year100 * 100 + bcd2bin(year)) - 1900;
+
+ return 0;
+}
+
+static int rtca3_set_time(struct device *dev, struct rtc_time *tm)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ u8 rcr2, tmp;
+ int ret;
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ /* Stop the RTC. */
+ rcr2 = readb(priv->base + RTCA3_RCR2);
+ writeb(rcr2 & ~RTCA3_RCR2_START, priv->base + RTCA3_RCR2);
+ ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR2, tmp,
+ !(tmp & RTCA3_RCR2_START),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /* Update time. */
+ writeb(bin2bcd(tm->tm_sec), priv->base + RTCA3_RSECCNT);
+ writeb(bin2bcd(tm->tm_min), priv->base + RTCA3_RMINCNT);
+ writeb(bin2bcd(tm->tm_hour), priv->base + RTCA3_RHRCNT);
+ writeb(bin2bcd(tm->tm_wday), priv->base + RTCA3_RWKCNT);
+ writeb(bin2bcd(tm->tm_mday), priv->base + RTCA3_RDAYCNT);
+ writeb(bin2bcd(tm->tm_mon + 1), priv->base + RTCA3_RMONCNT);
+ writew(bin2bcd(tm->tm_year % 100), priv->base + RTCA3_RYRCNT);
+
+ /* Make sure we can read back the counters. */
+ rtca3_prepare_cntalrm_regs_for_read(priv, true);
+
+ /* Start RTC. */
+ writeb(rcr2 | RTCA3_RCR2_START, priv->base + RTCA3_RCR2);
+ return readb_poll_timeout_atomic(priv->base + RTCA3_RCR2, tmp,
+ (tmp & RTCA3_RCR2_START),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+}
+
+static int rtca3_alarm_irq_set_helper(struct rtca3_priv *priv,
+ u8 interrupts,
+ unsigned int enabled)
+{
+ u8 tmp, val;
+
+ if (enabled) {
+ /*
+ * AIE, CIE, PIE bit indexes in RSR corresponds with
+ * those on RCR1. Same interrupts mask can be used.
+ */
+ rtca3_byte_update_bits(priv, RTCA3_RSR, interrupts, 0);
+ val = interrupts;
+ } else {
+ val = 0;
+ }
+
+ rtca3_byte_update_bits(priv, RTCA3_RCR1, interrupts, val);
+ return readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp,
+ ((tmp & interrupts) == val),
+ 10, RTCA3_IRQSET_TIMEOUT_US);
+}
+
+static int rtca3_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ return rtca3_alarm_irq_set_helper(priv, RTCA3_RCR1_AIE, enabled);
+}
+
+static int rtca3_read_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ u8 sec, min, hour, wday, mday, month;
+ struct rtc_time *tm = &wkalrm->time;
+ u32 year100;
+ u16 year;
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ sec = readb(priv->base + RTCA3_RSECAR);
+ min = readb(priv->base + RTCA3_RMINAR);
+ hour = readb(priv->base + RTCA3_RHRAR);
+ wday = readb(priv->base + RTCA3_RWKAR);
+ mday = readb(priv->base + RTCA3_RDAYAR);
+ month = readb(priv->base + RTCA3_RMONAR);
+ year = readw(priv->base + RTCA3_RYRAR);
+
+ tm->tm_sec = bcd2bin(FIELD_GET(RTCA3_RSECAR_SEC, sec));
+ tm->tm_min = bcd2bin(FIELD_GET(RTCA3_RMINAR_MIN, min));
+ tm->tm_hour = bcd2bin(FIELD_GET(RTCA3_RHRAR_HR, hour));
+ tm->tm_wday = bcd2bin(FIELD_GET(RTCA3_RWKAR_DAYW, wday));
+ tm->tm_mday = bcd2bin(FIELD_GET(RTCA3_RDAYAR_DATE, mday));
+ tm->tm_mon = bcd2bin(FIELD_GET(RTCA3_RMONAR_MON, month)) - 1;
+ year = FIELD_GET(RTCA3_RYRAR_YR, year);
+ year100 = bcd2bin((year == 0x99) ? 0x19 : 0x20);
+ tm->tm_year = (year100 * 100 + bcd2bin(year)) - 1900;
+
+ wkalrm->enabled = !!(readb(priv->base + RTCA3_RCR1) & RTCA3_RCR1_AIE);
+
+ return 0;
+}
+
+static int rtca3_set_alarm(struct device *dev, struct rtc_wkalrm *wkalrm)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ struct rtc_time *tm = &wkalrm->time;
+ u8 rcr1, tmp;
+ int ret;
+
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ tmp = readb(priv->base + RTCA3_RCR2);
+ if (!(tmp & RTCA3_RCR2_START))
+ return -EPERM;
+
+ /* Disable AIE to prevent false interrupts. */
+ rcr1 = readb(priv->base + RTCA3_RCR1);
+ rcr1 &= ~RTCA3_RCR1_AIE;
+ writeb(rcr1, priv->base + RTCA3_RCR1);
+ ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp,
+ !(tmp & RTCA3_RCR1_AIE),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /* Set the time and enable the alarm. */
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_sec), priv->base + RTCA3_RSECAR);
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_min), priv->base + RTCA3_RMINAR);
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_hour), priv->base + RTCA3_RHRAR);
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_wday), priv->base + RTCA3_RWKAR);
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_mday), priv->base + RTCA3_RDAYAR);
+ writeb(RTCA3_AR_ENB | bin2bcd(tm->tm_mon + 1), priv->base + RTCA3_RMONAR);
+
+ writew(bin2bcd(tm->tm_year % 100), priv->base + RTCA3_RYRAR);
+ writeb(RTCA3_AR_ENB, priv->base + RTCA3_RYRAREN);
+
+ /* Make sure we can read back the counters. */
+ rtca3_prepare_cntalrm_regs_for_read(priv, false);
+
+ /* Need to wait for 2 * 1/64 periodic interrupts to be generated. */
+ atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_INIT);
+ reinit_completion(&priv->set_alarm_completion);
+
+ /* Enable periodic interrupt. */
+ rcr1 |= RTCA3_RCR1_PIE;
+ writeb(rcr1, priv->base + RTCA3_RCR1);
+ ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp,
+ (tmp & RTCA3_RCR1_PIE),
+ 10, RTCA3_IRQSET_TIMEOUT_US);
+ }
+
+ if (ret)
+ goto setup_failed;
+
+ /* Wait for the 2 * 1/64 periodic interrupts. */
+ ret = wait_for_completion_interruptible_timeout(&priv->set_alarm_completion,
+ msecs_to_jiffies(500));
+ if (ret <= 0) {
+ ret = -ETIMEDOUT;
+ goto setup_failed;
+ }
+
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ ret = rtca3_alarm_irq_set_helper(priv, RTCA3_RCR1_AIE, wkalrm->enabled);
+ atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE);
+ }
+
+ return ret;
+
+setup_failed:
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ /*
+ * Disable PIE to avoid interrupt storm in case HW needed more than
+ * specified timeout for setup.
+ */
+ writeb(rcr1 & ~RTCA3_RCR1_PIE, priv->base + RTCA3_RCR1);
+ readb_poll_timeout_atomic(priv->base + RTCA3_RCR1, tmp, !(tmp & ~RTCA3_RCR1_PIE),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE);
+ }
+
+ return ret;
+}
+
+static int rtca3_read_offset(struct device *dev, long *offset)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ u8 val, radj, cycles;
+ u32 ppb_per_cycle;
+
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ radj = readb(priv->base + RTCA3_RADJ);
+ val = readb(priv->base + RTCA3_RCR2);
+ }
+
+ cycles = FIELD_GET(RTCA3_RADJ_ADJ, radj);
+
+ if (!cycles) {
+ *offset = 0;
+ return 0;
+ }
+
+ if (val & RTCA3_RCR2_ADJP)
+ ppb_per_cycle = priv->ppb.ten_sec;
+ else
+ ppb_per_cycle = priv->ppb.sixty_sec;
+
+ *offset = cycles * ppb_per_cycle;
+ val = FIELD_GET(RTCA3_RADJ_PMADJ, radj);
+ if (val == RTCA3_RADJ_PMADJ_SUB)
+ *offset = -(*offset);
+
+ return 0;
+}
+
+static int rtca3_set_offset(struct device *dev, long offset)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ int cycles, cycles10, cycles60;
+ u8 radj, adjp, tmp;
+ int ret;
+
+ /*
+ * Automatic time error adjustment could be set at intervals of 10
+ * or 60 seconds.
+ */
+ cycles10 = DIV_ROUND_CLOSEST(offset, priv->ppb.ten_sec);
+ cycles60 = DIV_ROUND_CLOSEST(offset, priv->ppb.sixty_sec);
+
+ /* We can set b/w 1 and 63 clock cycles. */
+ if (cycles60 >= -RTCA3_RADJ_ADJ_MAX &&
+ cycles60 <= RTCA3_RADJ_ADJ_MAX) {
+ cycles = cycles60;
+ adjp = 0;
+ } else if (cycles10 >= -RTCA3_RADJ_ADJ_MAX &&
+ cycles10 <= RTCA3_RADJ_ADJ_MAX) {
+ cycles = cycles10;
+ adjp = RTCA3_RCR2_ADJP;
+ } else {
+ return -ERANGE;
+ }
+
+ radj = FIELD_PREP(RTCA3_RADJ_ADJ, abs(cycles));
+ if (!cycles)
+ radj |= FIELD_PREP(RTCA3_RADJ_PMADJ, RTCA3_RADJ_PMADJ_NONE);
+ else if (cycles > 0)
+ radj |= FIELD_PREP(RTCA3_RADJ_PMADJ, RTCA3_RADJ_PMADJ_ADD);
+ else
+ radj |= FIELD_PREP(RTCA3_RADJ_PMADJ, RTCA3_RADJ_PMADJ_SUB);
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ tmp = readb(priv->base + RTCA3_RCR2);
+
+ if ((tmp & RTCA3_RCR2_ADJP) != adjp) {
+ /* RADJ.PMADJ need to be set to zero before setting RCR2.ADJP. */
+ writeb(0, priv->base + RTCA3_RADJ);
+ ret = readb_poll_timeout_atomic(priv->base + RTCA3_RADJ, tmp, !tmp,
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ rtca3_byte_update_bits(priv, RTCA3_RCR2, RTCA3_RCR2_ADJP, adjp);
+ ret = readb_poll_timeout_atomic(priv->base + RTCA3_RCR2, tmp,
+ ((tmp & RTCA3_RCR2_ADJP) == adjp),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+ }
+
+ writeb(radj, priv->base + RTCA3_RADJ);
+ return readb_poll_timeout_atomic(priv->base + RTCA3_RADJ, tmp, (tmp == radj),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+}
+
+static const struct rtc_class_ops rtca3_ops = {
+ .read_time = rtca3_read_time,
+ .set_time = rtca3_set_time,
+ .read_alarm = rtca3_read_alarm,
+ .set_alarm = rtca3_set_alarm,
+ .alarm_irq_enable = rtca3_alarm_irq_enable,
+ .set_offset = rtca3_set_offset,
+ .read_offset = rtca3_read_offset,
+};
+
+static int rtca3_initial_setup(struct clk *clk, struct rtca3_priv *priv)
+{
+ unsigned long osc32k_rate;
+ u8 val, tmp, mask;
+ u32 sleep_us;
+ int ret;
+
+ osc32k_rate = clk_get_rate(clk);
+ if (!osc32k_rate)
+ return -EINVAL;
+
+ sleep_us = DIV_ROUND_UP_ULL(1000000ULL, osc32k_rate) * 6;
+
+ priv->ppb.ten_sec = DIV_ROUND_CLOSEST_ULL(1000000000ULL, (osc32k_rate * 10));
+ priv->ppb.sixty_sec = DIV_ROUND_CLOSEST_ULL(1000000000ULL, (osc32k_rate * 60));
+
+ /*
+ * According to HW manual (section 22.4.2. Clock and count mode setting procedure)
+ * we need to wait at least 6 cycles of the 32KHz clock after clock was enabled.
+ */
+ usleep_range(sleep_us, sleep_us + 10);
+
+ /* Disable all interrupts. */
+ mask = RTCA3_RCR1_AIE | RTCA3_RCR1_CIE | RTCA3_RCR1_PIE;
+ ret = rtca3_alarm_irq_set_helper(priv, mask, 0);
+ if (ret)
+ return ret;
+
+ mask = RTCA3_RCR2_START | RTCA3_RCR2_HR24;
+ val = readb(priv->base + RTCA3_RCR2);
+ /* Nothing to do if already started in 24 hours and calendar count mode. */
+ if ((val & mask) == mask)
+ return 0;
+
+ /* Reconfigure the RTC in 24 hours and calendar count mode. */
+ mask = RTCA3_RCR2_START | RTCA3_RCR2_CNTMD;
+ writeb(0, priv->base + RTCA3_RCR2);
+ ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, !(tmp & mask),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /*
+ * Set 24 hours mode. According to HW manual (section 22.3.19. RTC Control
+ * Register 2) this needs to be done separate from stop operation.
+ */
+ mask = RTCA3_RCR2_HR24;
+ val = RTCA3_RCR2_HR24;
+ writeb(val, priv->base + RTCA3_RCR2);
+ ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, (tmp & mask),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /* Execute reset. */
+ mask = RTCA3_RCR2_RESET;
+ writeb(val | RTCA3_RCR2_RESET, priv->base + RTCA3_RCR2);
+ ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, !(tmp & mask),
+ 10, RTCA3_RESET_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /*
+ * According to HW manual (section 22.6.3. Notes on writing to and reading
+ * from registers) after reset we need to wait 6 clock cycles before
+ * writing to RTC registers.
+ */
+ usleep_range(sleep_us, sleep_us + 10);
+
+ /* Set no adjustment. */
+ writeb(0, priv->base + RTCA3_RADJ);
+ ret = readb_poll_timeout(priv->base + RTCA3_RADJ, tmp, !tmp, 10,
+ RTCA3_DEFAULT_TIMEOUT_US);
+
+ /* Start the RTC and enable automatic time error adjustment. */
+ mask = RTCA3_RCR2_START | RTCA3_RCR2_AADJE;
+ val |= RTCA3_RCR2_START | RTCA3_RCR2_AADJE;
+ writeb(val, priv->base + RTCA3_RCR2);
+ ret = readb_poll_timeout(priv->base + RTCA3_RCR2, tmp, ((tmp & mask) == mask),
+ 10, RTCA3_START_TIMEOUT_US);
+ if (ret)
+ return ret;
+
+ /*
+ * According to HW manual (section 22.6.4. Notes on writing to and reading
+ * from registers) we need to wait 1/128 seconds while the clock is operating
+ * (RCR2.START bit = 1) to be able to read the counters after a return from
+ * reset.
+ */
+ usleep_range(8000, 9000);
+
+ /* Set period interrupt to 1/64 seconds. It is necessary for alarm setup. */
+ val = FIELD_PREP(RTCA3_RCR1_PES, RTCA3_RCR1_PES_1_64_SEC);
+ rtca3_byte_update_bits(priv, RTCA3_RCR1, RTCA3_RCR1_PES, val);
+ return readb_poll_timeout(priv->base + RTCA3_RCR1, tmp, ((tmp & RTCA3_RCR1_PES) == val),
+ 10, RTCA3_DEFAULT_TIMEOUT_US);
+}
+
+static int rtca3_request_irqs(struct platform_device *pdev, struct rtca3_priv *priv)
+{
+ struct device *dev = &pdev->dev;
+ int ret, irq;
+
+ irq = platform_get_irq_byname(pdev, "alarm");
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "Failed to get alarm IRQ!\n");
+
+ ret = devm_request_irq(dev, irq, rtca3_alarm_handler, 0, "rtca3-alarm", priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to request alarm IRQ!\n");
+ priv->wakeup_irq = irq;
+
+ irq = platform_get_irq_byname(pdev, "period");
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "Failed to get period IRQ!\n");
+
+ ret = devm_request_irq(dev, irq, rtca3_periodic_handler, 0, "rtca3-period", priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to request period IRQ!\n");
+
+ /*
+ * Driver doesn't implement carry handler. Just get the IRQ here
+ * for backward compatibility, in case carry support will be added later.
+ */
+ irq = platform_get_irq_byname(pdev, "carry");
+ if (irq < 0)
+ return dev_err_probe(dev, irq, "Failed to get carry IRQ!\n");
+
+ return 0;
+}
+
+static void rtca3_action(void *data)
+{
+ struct device *dev = data;
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+ int ret;
+
+ ret = reset_control_assert(priv->rstc);
+ if (ret)
+ dev_err(dev, "Failed to de-assert reset!");
+
+ ret = pm_runtime_put_sync(dev);
+ if (ret < 0)
+ dev_err(dev, "Failed to runtime suspend!");
+}
+
+static int rtca3_probe(struct platform_device *pdev)
+{
+ struct device *dev = &pdev->dev;
+ struct rtca3_priv *priv;
+ struct clk *clk;
+ int ret;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ priv->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(priv->base))
+ return PTR_ERR(priv->base);
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+ priv->rstc = devm_reset_control_get_shared(dev, NULL);
+ if (IS_ERR(priv->rstc))
+ return PTR_ERR(priv->rstc);
+
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return ret;
+
+ ret = reset_control_deassert(priv->rstc);
+ if (ret) {
+ pm_runtime_put_sync(dev);
+ return ret;
+ }
+
+ dev_set_drvdata(dev, priv);
+ ret = devm_add_action_or_reset(dev, rtca3_action, dev);
+ if (ret)
+ return ret;
+
+ /*
+ * This must be an always-on clock to keep the RTC running even after
+ * driver is unbinded.
+ */
+ clk = devm_clk_get_enabled(dev, "counter");
+ if (IS_ERR(clk))
+ return PTR_ERR(clk);
+
+ spin_lock_init(&priv->lock);
+ atomic_set(&priv->alrm_sstep, RTCA3_ALRM_SSTEP_DONE);
+ init_completion(&priv->set_alarm_completion);
+
+ ret = rtca3_initial_setup(clk, priv);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to setup the RTC!\n");
+
+ ret = rtca3_request_irqs(pdev, priv);
+ if (ret)
+ return ret;
+
+ device_init_wakeup(&pdev->dev, 1);
+
+ priv->rtc_dev = devm_rtc_allocate_device(&pdev->dev);
+ if (IS_ERR(priv->rtc_dev))
+ return PTR_ERR(priv->rtc_dev);
+
+ priv->rtc_dev->ops = &rtca3_ops;
+ priv->rtc_dev->max_user_freq = 256;
+ priv->rtc_dev->range_min = RTC_TIMESTAMP_BEGIN_2000;
+ priv->rtc_dev->range_max = RTC_TIMESTAMP_END_2099;
+
+ return devm_rtc_register_device(priv->rtc_dev);
+}
+
+static void rtca3_remove(struct platform_device *pdev)
+{
+ struct rtca3_priv *priv = platform_get_drvdata(pdev);
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ /*
+ * Disable alarm, periodic interrupts. The RTC device cannot
+ * power up the system.
+ */
+ rtca3_alarm_irq_set_helper(priv, RTCA3_RCR1_AIE | RTCA3_RCR1_PIE, 0);
+}
+
+static int rtca3_suspend(struct device *dev)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+
+ if (!device_may_wakeup(dev))
+ return 0;
+
+ /* Alarm setup in progress. */
+ if (atomic_read(&priv->alrm_sstep) != RTCA3_ALRM_SSTEP_DONE)
+ return -EBUSY;
+
+ enable_irq_wake(priv->wakeup_irq);
+
+ return 0;
+}
+
+static int rtca3_clean_alarm(struct rtca3_priv *priv)
+{
+ struct rtc_device *rtc_dev = priv->rtc_dev;
+ time64_t alarm_time, now;
+ struct rtc_wkalrm alarm;
+ struct rtc_time tm;
+ u8 pending;
+ int ret;
+
+ ret = rtc_read_alarm(rtc_dev, &alarm);
+ if (ret)
+ return ret;
+
+ if (!alarm.enabled)
+ return 0;
+
+ ret = rtc_read_time(rtc_dev, &tm);
+ if (ret)
+ return ret;
+
+ alarm_time = rtc_tm_to_time64(&alarm.time);
+ now = rtc_tm_to_time64(&tm);
+ if (alarm_time >= now)
+ return 0;
+
+ /*
+ * Heuristically, it has been determined that when returning from deep
+ * sleep state the RTCA3_RSR.AF is zero even though the alarm expired.
+ * Call again the rtc_update_irq() if alarm helper detects this.
+ */
+
+ guard(spinlock_irqsave)(&priv->lock);
+
+ pending = rtca3_alarm_handler_helper(priv);
+ if (!pending)
+ rtc_update_irq(priv->rtc_dev, 1, RTC_AF | RTC_IRQF);
+
+ return 0;
+}
+
+static int rtca3_resume(struct device *dev)
+{
+ struct rtca3_priv *priv = dev_get_drvdata(dev);
+
+ if (!device_may_wakeup(dev))
+ return 0;
+
+ disable_irq_wake(priv->wakeup_irq);
+
+ /*
+ * According to the HW manual (section 22.6.4 Notes on writing to
+ * and reading from registers) we need to wait 1/128 seconds while
+ * RCR2.START = 1 to be able to read the counters after a return from low
+ * power consumption state.
+ */
+ mdelay(8);
+
+ /*
+ * The alarm cannot wake the system from deep sleep states. In case
+ * we return from deep sleep states and the alarm expired we need
+ * to disable it to avoid failures when setting another alarm.
+ */
+ return rtca3_clean_alarm(priv);
+}
+
+static DEFINE_SIMPLE_DEV_PM_OPS(rtca3_pm_ops, rtca3_suspend, rtca3_resume);
+
+static const struct of_device_id rtca3_of_match[] = {
+ { .compatible = "renesas,rz-rtca3", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, rtca3_of_match);
+
+static struct platform_driver rtca3_platform_driver = {
+ .driver = {
+ .name = "rtc-rtca3",
+ .pm = pm_ptr(&rtca3_pm_ops),
+ .of_match_table = rtca3_of_match,
+ },
+ .probe = rtca3_probe,
+ .remove = rtca3_remove,
+};
+module_platform_driver(rtca3_platform_driver);
+
+MODULE_DESCRIPTION("Renesas RTCA-3 RTC driver");
+MODULE_AUTHOR("Claudiu Beznea <claudiu.beznea.uj@bp.renesas.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-rtd119x.c b/drivers/rtc/rtc-rtd119x.c
index 29662dfd56fe..85a138db81d7 100644
--- a/drivers/rtc/rtc-rtd119x.c
+++ b/drivers/rtc/rtc-rtd119x.c
@@ -228,7 +228,7 @@ static void rtd119x_rtc_remove(struct platform_device *pdev)
static struct platform_driver rtd119x_rtc_driver = {
.probe = rtd119x_rtc_probe,
- .remove_new = rtd119x_rtc_remove,
+ .remove = rtd119x_rtc_remove,
.driver = {
.name = "rtd1295-rtc",
.of_match_table = rtd119x_rtc_dt_ids,
diff --git a/drivers/rtc/rtc-rv3028.c b/drivers/rtc/rtc-rv3028.c
index 2f001c59c61d..868d1b1eb0f4 100644
--- a/drivers/rtc/rtc-rv3028.c
+++ b/drivers/rtc/rtc-rv3028.c
@@ -120,8 +120,9 @@ static ssize_t timestamp0_show(struct device *dev,
{
struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
struct rtc_time tm;
- int ret, count;
+ unsigned int count;
u8 date[6];
+ int ret;
ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
if (ret)
@@ -156,7 +157,8 @@ static ssize_t timestamp0_count_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct rv3028_data *rv3028 = dev_get_drvdata(dev->parent);
- int ret, count;
+ unsigned int count;
+ int ret;
ret = regmap_read(rv3028->regmap, RV3028_TS_COUNT, &count);
if (ret)
diff --git a/drivers/rtc/rtc-rzn1.c b/drivers/rtc/rtc-rzn1.c
index 56ebbd4d0481..cb220807d925 100644
--- a/drivers/rtc/rtc-rzn1.c
+++ b/drivers/rtc/rtc-rzn1.c
@@ -7,7 +7,7 @@
* - 2022 Schneider Electric
*
* Authors:
- * - Michel Pollet <michel.pollet@bp.renesas.com>, <buserror@gmail.com>
+ * - Michel Pollet <buserror@gmail.com>
* - Miquel Raynal <miquel.raynal@bootlin.com>
*/
@@ -35,13 +35,13 @@
#define RZN1_RTC_CTL2_WUST BIT(5)
#define RZN1_RTC_CTL2_STOPPED (RZN1_RTC_CTL2_WAIT | RZN1_RTC_CTL2_WST)
-#define RZN1_RTC_SEC 0x14
-#define RZN1_RTC_MIN 0x18
-#define RZN1_RTC_HOUR 0x1c
-#define RZN1_RTC_WEEK 0x20
-#define RZN1_RTC_DAY 0x24
-#define RZN1_RTC_MONTH 0x28
-#define RZN1_RTC_YEAR 0x2c
+#define RZN1_RTC_TIME 0x30
+#define RZN1_RTC_TIME_MIN_SHIFT 8
+#define RZN1_RTC_TIME_HOUR_SHIFT 16
+#define RZN1_RTC_CAL 0x34
+#define RZN1_RTC_CAL_DAY_SHIFT 8
+#define RZN1_RTC_CAL_MON_SHIFT 16
+#define RZN1_RTC_CAL_YEAR_SHIFT 24
#define RZN1_RTC_SUBU 0x38
#define RZN1_RTC_SUBU_DEV BIT(7)
@@ -52,12 +52,8 @@
#define RZN1_RTC_ALW 0x48
#define RZN1_RTC_SECC 0x4c
-#define RZN1_RTC_MINC 0x50
-#define RZN1_RTC_HOURC 0x54
-#define RZN1_RTC_WEEKC 0x58
-#define RZN1_RTC_DAYC 0x5c
-#define RZN1_RTC_MONTHC 0x60
-#define RZN1_RTC_YEARC 0x64
+#define RZN1_RTC_TIMEC 0x68
+#define RZN1_RTC_CALC 0x6c
struct rzn1_rtc {
struct rtc_device *rtcdev;
@@ -66,26 +62,18 @@ struct rzn1_rtc {
static void rzn1_rtc_get_time_snapshot(struct rzn1_rtc *rtc, struct rtc_time *tm)
{
- tm->tm_sec = readl(rtc->base + RZN1_RTC_SECC);
- tm->tm_min = readl(rtc->base + RZN1_RTC_MINC);
- tm->tm_hour = readl(rtc->base + RZN1_RTC_HOURC);
- tm->tm_wday = readl(rtc->base + RZN1_RTC_WEEKC);
- tm->tm_mday = readl(rtc->base + RZN1_RTC_DAYC);
- tm->tm_mon = readl(rtc->base + RZN1_RTC_MONTHC);
- tm->tm_year = readl(rtc->base + RZN1_RTC_YEARC);
-}
-
-static unsigned int rzn1_rtc_tm_to_wday(struct rtc_time *tm)
-{
- time64_t time;
- unsigned int days;
- u32 secs;
+ u32 val;
- time = rtc_tm_to_time64(tm);
- days = div_s64_rem(time, 86400, &secs);
+ val = readl(rtc->base + RZN1_RTC_TIMEC);
+ tm->tm_sec = bcd2bin(val);
+ tm->tm_min = bcd2bin(val >> RZN1_RTC_TIME_MIN_SHIFT);
+ tm->tm_hour = bcd2bin(val >> RZN1_RTC_TIME_HOUR_SHIFT);
- /* day of the week, 1970-01-01 was a Thursday */
- return (days + 4) % 7;
+ val = readl(rtc->base + RZN1_RTC_CALC);
+ tm->tm_wday = val & 0x0f;
+ tm->tm_mday = bcd2bin(val >> RZN1_RTC_CAL_DAY_SHIFT);
+ tm->tm_mon = bcd2bin(val >> RZN1_RTC_CAL_MON_SHIFT) - 1;
+ tm->tm_year = bcd2bin(val >> RZN1_RTC_CAL_YEAR_SHIFT) + 100;
}
static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm)
@@ -103,17 +91,9 @@ static int rzn1_rtc_read_time(struct device *dev, struct rtc_time *tm)
rzn1_rtc_get_time_snapshot(rtc, tm);
secs = readl(rtc->base + RZN1_RTC_SECC);
- if (tm->tm_sec != secs)
+ if (tm->tm_sec != bcd2bin(secs))
rzn1_rtc_get_time_snapshot(rtc, tm);
- tm->tm_sec = bcd2bin(tm->tm_sec);
- tm->tm_min = bcd2bin(tm->tm_min);
- tm->tm_hour = bcd2bin(tm->tm_hour);
- tm->tm_wday = bcd2bin(tm->tm_wday);
- tm->tm_mday = bcd2bin(tm->tm_mday);
- tm->tm_mon = bcd2bin(tm->tm_mon);
- tm->tm_year = bcd2bin(tm->tm_year);
-
return 0;
}
@@ -123,14 +103,6 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
u32 val;
int ret;
- tm->tm_sec = bin2bcd(tm->tm_sec);
- tm->tm_min = bin2bcd(tm->tm_min);
- tm->tm_hour = bin2bcd(tm->tm_hour);
- tm->tm_wday = bin2bcd(rzn1_rtc_tm_to_wday(tm));
- tm->tm_mday = bin2bcd(tm->tm_mday);
- tm->tm_mon = bin2bcd(tm->tm_mon);
- tm->tm_year = bin2bcd(tm->tm_year);
-
val = readl(rtc->base + RZN1_RTC_CTL2);
if (!(val & RZN1_RTC_CTL2_STOPPED)) {
/* Hold the counter if it was counting up */
@@ -144,13 +116,17 @@ static int rzn1_rtc_set_time(struct device *dev, struct rtc_time *tm)
return ret;
}
- writel(tm->tm_sec, rtc->base + RZN1_RTC_SEC);
- writel(tm->tm_min, rtc->base + RZN1_RTC_MIN);
- writel(tm->tm_hour, rtc->base + RZN1_RTC_HOUR);
- writel(tm->tm_wday, rtc->base + RZN1_RTC_WEEK);
- writel(tm->tm_mday, rtc->base + RZN1_RTC_DAY);
- writel(tm->tm_mon, rtc->base + RZN1_RTC_MONTH);
- writel(tm->tm_year, rtc->base + RZN1_RTC_YEAR);
+ val = bin2bcd(tm->tm_sec);
+ val |= bin2bcd(tm->tm_min) << RZN1_RTC_TIME_MIN_SHIFT;
+ val |= bin2bcd(tm->tm_hour) << RZN1_RTC_TIME_HOUR_SHIFT;
+ writel(val, rtc->base + RZN1_RTC_TIME);
+
+ val = tm->tm_wday;
+ val |= bin2bcd(tm->tm_mday) << RZN1_RTC_CAL_DAY_SHIFT;
+ val |= bin2bcd(tm->tm_mon + 1) << RZN1_RTC_CAL_MON_SHIFT;
+ val |= bin2bcd(tm->tm_year - 100) << RZN1_RTC_CAL_YEAR_SHIFT;
+ writel(val, rtc->base + RZN1_RTC_CAL);
+
writel(0, rtc->base + RZN1_RTC_CTL2);
return 0;
@@ -405,7 +381,7 @@ MODULE_DEVICE_TABLE(of, rzn1_rtc_of_match);
static struct platform_driver rzn1_rtc_driver = {
.probe = rzn1_rtc_probe,
- .remove_new = rzn1_rtc_remove,
+ .remove = rzn1_rtc_remove,
.driver = {
.name = "rzn1-rtc",
.of_match_table = rzn1_rtc_of_match,
@@ -413,7 +389,7 @@ static struct platform_driver rzn1_rtc_driver = {
};
module_platform_driver(rzn1_rtc_driver);
-MODULE_AUTHOR("Michel Pollet <Michel.Pollet@bp.renesas.com");
+MODULE_AUTHOR("Michel Pollet <buserror@gmail.com>");
MODULE_AUTHOR("Miquel Raynal <miquel.raynal@bootlin.com");
MODULE_DESCRIPTION("RZ/N1 RTC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-s3c.c b/drivers/rtc/rtc-s3c.c
index 282238818f63..c0ac3bdb2f42 100644
--- a/drivers/rtc/rtc-s3c.c
+++ b/drivers/rtc/rtc-s3c.c
@@ -597,7 +597,7 @@ MODULE_DEVICE_TABLE(of, s3c_rtc_dt_match);
static struct platform_driver s3c_rtc_driver = {
.probe = s3c_rtc_probe,
- .remove_new = s3c_rtc_remove,
+ .remove = s3c_rtc_remove,
.driver = {
.name = "s3c-rtc",
.pm = &s3c_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-sa1100.c b/drivers/rtc/rtc-sa1100.c
index 0b2cfa8ca05b..13799b1abca1 100644
--- a/drivers/rtc/rtc-sa1100.c
+++ b/drivers/rtc/rtc-sa1100.c
@@ -341,7 +341,7 @@ MODULE_DEVICE_TABLE(of, sa1100_rtc_dt_ids);
static struct platform_driver sa1100_rtc_driver = {
.probe = sa1100_rtc_probe,
- .remove_new = sa1100_rtc_remove,
+ .remove = sa1100_rtc_remove,
.driver = {
.name = "sa1100-rtc",
.pm = &sa1100_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-sh.c b/drivers/rtc/rtc-sh.c
index 27a191fa3704..a5df521876ba 100644
--- a/drivers/rtc/rtc-sh.c
+++ b/drivers/rtc/rtc-sh.c
@@ -678,7 +678,7 @@ static struct platform_driver sh_rtc_platform_driver __refdata = {
.pm = &sh_rtc_pm_ops,
.of_match_table = sh_rtc_of_match,
},
- .remove_new = __exit_p(sh_rtc_remove),
+ .remove = __exit_p(sh_rtc_remove),
};
module_platform_driver_probe(sh_rtc_platform_driver, sh_rtc_probe);
diff --git a/drivers/rtc/rtc-spear.c b/drivers/rtc/rtc-spear.c
index 1df5c7e94198..26eed927f8b3 100644
--- a/drivers/rtc/rtc-spear.c
+++ b/drivers/rtc/rtc-spear.c
@@ -475,7 +475,7 @@ MODULE_DEVICE_TABLE(of, spear_rtc_id_table);
static struct platform_driver spear_rtc_driver = {
.probe = spear_rtc_probe,
- .remove_new = spear_rtc_remove,
+ .remove = spear_rtc_remove,
.shutdown = spear_rtc_shutdown,
.driver = {
.name = "rtc-spear",
diff --git a/drivers/rtc/rtc-st-lpc.c b/drivers/rtc/rtc-st-lpc.c
index d492a2d26600..c6d4522411b3 100644
--- a/drivers/rtc/rtc-st-lpc.c
+++ b/drivers/rtc/rtc-st-lpc.c
@@ -218,15 +218,14 @@ static int st_rtc_probe(struct platform_device *pdev)
return -EINVAL;
}
- ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler, 0,
- pdev->name, rtc);
+ ret = devm_request_irq(&pdev->dev, rtc->irq, st_rtc_handler,
+ IRQF_NO_AUTOEN, pdev->name, rtc);
if (ret) {
dev_err(&pdev->dev, "Failed to request irq %i\n", rtc->irq);
return ret;
}
enable_irq_wake(rtc->irq);
- disable_irq(rtc->irq);
rtc->clk = devm_clk_get_enabled(&pdev->dev, NULL);
if (IS_ERR(rtc->clk))
diff --git a/drivers/rtc/rtc-stm32.c b/drivers/rtc/rtc-stm32.c
index 3e4f2ee22b0b..9f1a019ec8af 100644
--- a/drivers/rtc/rtc-stm32.c
+++ b/drivers/rtc/rtc-stm32.c
@@ -1287,7 +1287,7 @@ static const struct dev_pm_ops stm32_rtc_pm_ops = {
static struct platform_driver stm32_rtc_driver = {
.probe = stm32_rtc_probe,
- .remove_new = stm32_rtc_remove,
+ .remove = stm32_rtc_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &stm32_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-stmp3xxx.c b/drivers/rtc/rtc-stmp3xxx.c
index 7566d0a44af8..7afcd14aeee5 100644
--- a/drivers/rtc/rtc-stmp3xxx.c
+++ b/drivers/rtc/rtc-stmp3xxx.c
@@ -403,7 +403,7 @@ MODULE_DEVICE_TABLE(of, rtc_dt_ids);
static struct platform_driver stmp3xxx_rtcdrv = {
.probe = stmp3xxx_rtc_probe,
- .remove_new = stmp3xxx_rtc_remove,
+ .remove = stmp3xxx_rtc_remove,
.driver = {
.name = "stmp3xxx-rtc",
.pm = &stmp3xxx_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-sunplus.c b/drivers/rtc/rtc-sunplus.c
index 20c7e97c2fc8..9b1ce0e8ba27 100644
--- a/drivers/rtc/rtc-sunplus.c
+++ b/drivers/rtc/rtc-sunplus.c
@@ -344,7 +344,7 @@ static SIMPLE_DEV_PM_OPS(sp_rtc_pm_ops, sp_rtc_suspend, sp_rtc_resume);
static struct platform_driver sp_rtc_driver = {
.probe = sp_rtc_probe,
- .remove_new = sp_rtc_remove,
+ .remove = sp_rtc_remove,
.driver = {
.name = "sp7021-rtc",
.of_match_table = sp_rtc_of_match,
diff --git a/drivers/rtc/rtc-tegra.c b/drivers/rtc/rtc-tegra.c
index 441e0a66b215..79a3102c8354 100644
--- a/drivers/rtc/rtc-tegra.c
+++ b/drivers/rtc/rtc-tegra.c
@@ -399,7 +399,7 @@ static void tegra_rtc_shutdown(struct platform_device *pdev)
static struct platform_driver tegra_rtc_driver = {
.probe = tegra_rtc_probe,
- .remove_new = tegra_rtc_remove,
+ .remove = tegra_rtc_remove,
.shutdown = tegra_rtc_shutdown,
.driver = {
.name = "tegra_rtc",
diff --git a/drivers/rtc/rtc-tps6586x.c b/drivers/rtc/rtc-tps6586x.c
index 20faf08c254c..e796729fc817 100644
--- a/drivers/rtc/rtc-tps6586x.c
+++ b/drivers/rtc/rtc-tps6586x.c
@@ -317,7 +317,7 @@ static struct platform_driver tps6586x_rtc_driver = {
.pm = &tps6586x_pm_ops,
},
.probe = tps6586x_rtc_probe,
- .remove_new = tps6586x_rtc_remove,
+ .remove = tps6586x_rtc_remove,
};
module_platform_driver(tps6586x_rtc_driver);
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index 4e24c12004f1..794429182b34 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -673,7 +673,7 @@ MODULE_DEVICE_TABLE(of, twl_rtc_of_match);
static struct platform_driver twl4030rtc_driver = {
.probe = twl_rtc_probe,
- .remove_new = twl_rtc_remove,
+ .remove = twl_rtc_remove,
.shutdown = twl_rtc_shutdown,
.driver = {
.name = "twl_rtc",
diff --git a/drivers/rtc/rtc-vt8500.c b/drivers/rtc/rtc-vt8500.c
index ccfa76513a2c..c8b568498016 100644
--- a/drivers/rtc/rtc-vt8500.c
+++ b/drivers/rtc/rtc-vt8500.c
@@ -251,7 +251,7 @@ MODULE_DEVICE_TABLE(of, wmt_dt_ids);
static struct platform_driver vt8500_rtc_driver = {
.probe = vt8500_rtc_probe,
- .remove_new = vt8500_rtc_remove,
+ .remove = vt8500_rtc_remove,
.driver = {
.name = "vt8500-rtc",
.of_match_table = wmt_dt_ids,
diff --git a/drivers/rtc/rtc-wm8350.c b/drivers/rtc/rtc-wm8350.c
index 3c773cff2b39..6797eb4d2e49 100644
--- a/drivers/rtc/rtc-wm8350.c
+++ b/drivers/rtc/rtc-wm8350.c
@@ -459,7 +459,7 @@ static SIMPLE_DEV_PM_OPS(wm8350_rtc_pm_ops, wm8350_rtc_suspend,
static struct platform_driver wm8350_rtc_driver = {
.probe = wm8350_rtc_probe,
- .remove_new = wm8350_rtc_remove,
+ .remove = wm8350_rtc_remove,
.driver = {
.name = "wm8350-rtc",
.pm = &wm8350_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-xgene.c b/drivers/rtc/rtc-xgene.c
index f78efc9760c0..0813ea1a03c2 100644
--- a/drivers/rtc/rtc-xgene.c
+++ b/drivers/rtc/rtc-xgene.c
@@ -263,7 +263,7 @@ MODULE_DEVICE_TABLE(of, xgene_rtc_of_match);
static struct platform_driver xgene_rtc_driver = {
.probe = xgene_rtc_probe,
- .remove_new = xgene_rtc_remove,
+ .remove = xgene_rtc_remove,
.driver = {
.name = "xgene-rtc",
.pm = &xgene_rtc_pm_ops,
diff --git a/drivers/rtc/rtc-zynqmp.c b/drivers/rtc/rtc-zynqmp.c
index 08ed171bdab4..af1abb69d1e3 100644
--- a/drivers/rtc/rtc-zynqmp.c
+++ b/drivers/rtc/rtc-zynqmp.c
@@ -382,7 +382,7 @@ MODULE_DEVICE_TABLE(of, xlnx_rtc_of_match);
static struct platform_driver xlnx_rtc_driver = {
.probe = xlnx_rtc_probe,
- .remove_new = xlnx_rtc_remove,
+ .remove = xlnx_rtc_remove,
.driver = {
.name = KBUILD_MODNAME,
.pm = &xlnx_rtc_pm_ops,
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index dcb3c32f027a..c763c50d1454 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -803,7 +803,6 @@ static struct attribute *con3215_drv_attrs[] = {
static struct attribute_group con3215_drv_attr_group = {
.attrs = con3215_drv_attrs,
- NULL,
};
static const struct attribute_group *con3215_drv_attr_groups[] = {
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index e14638936de6..26e1ea1940ec 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -453,7 +453,7 @@ static void ap_tasklet_fn(unsigned long dummy)
* important that no requests on any AP get lost.
*/
if (ap_irq_flag)
- xchg(ap_airq.lsi_ptr, 0);
+ WRITE_ONCE(*ap_airq.lsi_ptr, 0);
spin_lock_bh(&ap_queues_lock);
hash_for_each(ap_queues, bkt, aq, hnode) {
diff --git a/drivers/s390/crypto/vfio_ap_ops.c b/drivers/s390/crypto/vfio_ap_ops.c
index 8c0b40d8eb39..a52c2690933f 100644
--- a/drivers/s390/crypto/vfio_ap_ops.c
+++ b/drivers/s390/crypto/vfio_ap_ops.c
@@ -360,10 +360,26 @@ static int vfio_ap_validate_nib(struct kvm_vcpu *vcpu, dma_addr_t *nib)
return 0;
}
-static int ensure_nib_shared(unsigned long addr, struct gmap *gmap)
+/**
+ * ensure_nib_shared() - Ensure the address of the NIB is secure and shared
+ * @addr: the physical (absolute) address of the NIB
+ *
+ * This function checks whether the NIB page, which has been pinned with
+ * vfio_pin_pages(), is a shared page belonging to a secure guest.
+ *
+ * It will call uv_pin_shared() on it; if the page was already pinned shared
+ * (i.e. if the NIB belongs to a secure guest and is shared), then 0
+ * (success) is returned. If the NIB was not shared, vfio_pin_pages() had
+ * exported it and now it does not belong to the secure guest anymore. In
+ * that case, an error is returned.
+ *
+ * Context: the NIB (at physical address @addr) has to be pinned with
+ * vfio_pin_pages() before calling this function.
+ *
+ * Return: 0 in case of success, otherwise an error < 0.
+ */
+static int ensure_nib_shared(unsigned long addr)
{
- int ret;
-
/*
* The nib has to be located in shared storage since guest and
* host access it. vfio_pin_pages() will do a pin shared and
@@ -374,12 +390,7 @@ static int ensure_nib_shared(unsigned long addr, struct gmap *gmap)
*
* If the page is already pinned shared the UV will return a success.
*/
- ret = uv_pin_shared(addr);
- if (ret) {
- /* vfio_pin_pages() likely exported the page so let's re-import */
- gmap_convert_to_secure(gmap, addr);
- }
- return ret;
+ return uv_pin_shared(addr);
}
/**
@@ -425,6 +436,7 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
return status;
}
+ /* The pin will probably be successful even if the NIB was not shared */
ret = vfio_pin_pages(&q->matrix_mdev->vdev, nib, 1,
IOMMU_READ | IOMMU_WRITE, &h_page);
switch (ret) {
@@ -447,7 +459,7 @@ static struct ap_queue_status vfio_ap_irq_enable(struct vfio_ap_queue *q,
/* NIB in non-shared storage is a rc 6 for PV guests */
if (kvm_s390_pv_cpu_is_protected(vcpu) &&
- ensure_nib_shared(h_nib & PAGE_MASK, kvm->arch.gmap)) {
+ ensure_nib_shared(h_nib & PAGE_MASK)) {
vfio_unpin_pages(&q->matrix_mdev->vdev, nib, 1);
status.response_code = AP_RESPONSE_INVALID_ADDRESS;
return status;
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c
index d7fcde692f46..90e71ce4bab8 100644
--- a/drivers/sbus/char/bbc_i2c.c
+++ b/drivers/sbus/char/bbc_i2c.c
@@ -413,7 +413,7 @@ static struct platform_driver bbc_i2c_driver = {
.of_match_table = bbc_i2c_match,
},
.probe = bbc_i2c_probe,
- .remove_new = bbc_i2c_remove,
+ .remove = bbc_i2c_remove,
};
module_platform_driver(bbc_i2c_driver);
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c
index 521cf8affe65..e94222b3523c 100644
--- a/drivers/sbus/char/display7seg.c
+++ b/drivers/sbus/char/display7seg.c
@@ -261,7 +261,7 @@ static struct platform_driver d7s_driver = {
.of_match_table = d7s_match,
},
.probe = d7s_probe,
- .remove_new = d7s_remove,
+ .remove = d7s_remove,
};
module_platform_driver(d7s_driver);
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c
index b543e9bcc785..81918aa67109 100644
--- a/drivers/sbus/char/envctrl.c
+++ b/drivers/sbus/char/envctrl.c
@@ -1125,7 +1125,7 @@ static struct platform_driver envctrl_driver = {
.of_match_table = envctrl_match,
},
.probe = envctrl_probe,
- .remove_new = envctrl_remove,
+ .remove = envctrl_remove,
};
module_platform_driver(envctrl_driver);
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c
index ddd449dfda31..6524a4a19109 100644
--- a/drivers/sbus/char/flash.c
+++ b/drivers/sbus/char/flash.c
@@ -206,7 +206,7 @@ static struct platform_driver flash_driver = {
.of_match_table = flash_match,
},
.probe = flash_probe,
- .remove_new = flash_remove,
+ .remove = flash_remove,
};
module_platform_driver(flash_driver);
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c
index 8bbed7a7afb7..e3dec78f51e9 100644
--- a/drivers/sbus/char/uctrl.c
+++ b/drivers/sbus/char/uctrl.c
@@ -424,7 +424,7 @@ static struct platform_driver uctrl_driver = {
.of_match_table = uctrl_match,
},
.probe = uctrl_probe,
- .remove_new = uctrl_remove,
+ .remove = uctrl_remove,
};
diff --git a/drivers/scsi/bfa/bfa_fcbuild.c b/drivers/scsi/bfa/bfa_fcbuild.c
index 52303e8c716d..c44fd096ee68 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.c
+++ b/drivers/scsi/bfa/bfa_fcbuild.c
@@ -220,44 +220,6 @@ fc_plogi_x_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
}
u16
-fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
- u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size,
- u8 set_npiv, u8 set_auth, u16 local_bb_credits)
-{
- u32 d_id = bfa_hton3b(FC_FABRIC_PORT);
- __be32 *vvl_info;
-
- memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
-
- flogi->els_cmd.els_code = FC_ELS_FLOGI;
- fc_els_req_build(fchs, d_id, s_id, ox_id);
-
- flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
- flogi->port_name = port_name;
- flogi->node_name = node_name;
-
- /*
- * Set the NPIV Capability Bit ( word 1, bit 31) of Common
- * Service Parameters.
- */
- flogi->csp.ciro = set_npiv;
-
- /* set AUTH capability */
- flogi->csp.security = set_auth;
-
- flogi->csp.bbcred = cpu_to_be16(local_bb_credits);
-
- /* Set brcd token in VVL */
- vvl_info = (u32 *)&flogi->vvl[0];
-
- /* set the flag to indicate the presence of VVL */
- flogi->csp.npiv_supp = 1; /* @todo. field name is not correct */
- vvl_info[0] = cpu_to_be32(FLOGI_VVL_BRCD);
-
- return sizeof(struct fc_logi_s);
-}
-
-u16
fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
__be16 ox_id, wwn_t port_name, wwn_t node_name,
u16 pdu_size, u16 local_bb_credits, u8 bb_scn)
@@ -280,24 +242,6 @@ fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
}
u16
-fc_fdisc_build(struct fchs_s *fchs, struct fc_logi_s *flogi, u32 s_id,
- u16 ox_id, wwn_t port_name, wwn_t node_name, u16 pdu_size)
-{
- u32 d_id = bfa_hton3b(FC_FABRIC_PORT);
-
- memcpy(flogi, &plogi_tmpl, sizeof(struct fc_logi_s));
-
- flogi->els_cmd.els_code = FC_ELS_FDISC;
- fc_els_req_build(fchs, d_id, s_id, ox_id);
-
- flogi->csp.rxsz = flogi->class3.rxsz = cpu_to_be16(pdu_size);
- flogi->port_name = port_name;
- flogi->node_name = node_name;
-
- return sizeof(struct fc_logi_s);
-}
-
-u16
fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
u16 ox_id, wwn_t port_name, wwn_t node_name,
u16 pdu_size, u16 bb_cr)
@@ -316,40 +260,6 @@ fc_plogi_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
}
enum fc_parse_status
-fc_plogi_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
-{
- struct fc_els_cmd_s *els_cmd = (struct fc_els_cmd_s *) (fchs + 1);
- struct fc_logi_s *plogi;
- struct fc_ls_rjt_s *ls_rjt;
-
- switch (els_cmd->els_code) {
- case FC_ELS_LS_RJT:
- ls_rjt = (struct fc_ls_rjt_s *) (fchs + 1);
- if (ls_rjt->reason_code == FC_LS_RJT_RSN_LOGICAL_BUSY)
- return FC_PARSE_BUSY;
- else
- return FC_PARSE_FAILURE;
- case FC_ELS_ACC:
- plogi = (struct fc_logi_s *) (fchs + 1);
- if (len < sizeof(struct fc_logi_s))
- return FC_PARSE_FAILURE;
-
- if (!wwn_is_equal(plogi->port_name, port_name))
- return FC_PARSE_FAILURE;
-
- if (!plogi->class3.class_valid)
- return FC_PARSE_FAILURE;
-
- if (be16_to_cpu(plogi->class3.rxsz) < (FC_MIN_PDUSZ))
- return FC_PARSE_FAILURE;
-
- return FC_PARSE_OK;
- default:
- return FC_PARSE_FAILURE;
- }
-}
-
-enum fc_parse_status
fc_plogi_parse(struct fchs_s *fchs)
{
struct fc_logi_s *plogi = (struct fc_logi_s *) (fchs + 1);
@@ -421,21 +331,6 @@ fc_prli_rsp_parse(struct fc_prli_s *prli, int len)
return FC_PARSE_OK;
}
-enum fc_parse_status
-fc_prli_parse(struct fc_prli_s *prli)
-{
- if (prli->parampage.type != FC_TYPE_FCP)
- return FC_PARSE_FAILURE;
-
- if (!prli->parampage.imagepair)
- return FC_PARSE_FAILURE;
-
- if (!prli->parampage.servparams.initiator)
- return FC_PARSE_FAILURE;
-
- return FC_PARSE_OK;
-}
-
u16
fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id, u32 s_id,
u16 ox_id, wwn_t port_name)
@@ -506,84 +401,6 @@ fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len, wwn_t port_name,
return FC_PARSE_OK;
}
-enum fc_parse_status
-fc_adisc_parse(struct fchs_s *fchs, void *pld, u32 host_dap, wwn_t node_name,
- wwn_t port_name)
-{
- struct fc_adisc_s *adisc = (struct fc_adisc_s *) pld;
-
- if (adisc->els_cmd.els_code != FC_ELS_ACC)
- return FC_PARSE_FAILURE;
-
- if ((adisc->nport_id == (host_dap))
- && wwn_is_equal(adisc->orig_port_name, port_name)
- && wwn_is_equal(adisc->orig_node_name, node_name))
- return FC_PARSE_OK;
-
- return FC_PARSE_FAILURE;
-}
-
-enum fc_parse_status
-fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name, wwn_t port_name)
-{
- struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
-
- if (pdisc->class3.class_valid != 1)
- return FC_PARSE_FAILURE;
-
- if ((be16_to_cpu(pdisc->class3.rxsz) <
- (FC_MIN_PDUSZ - sizeof(struct fchs_s)))
- || (pdisc->class3.rxsz == 0))
- return FC_PARSE_FAILURE;
-
- if (!wwn_is_equal(pdisc->port_name, port_name))
- return FC_PARSE_FAILURE;
-
- if (!wwn_is_equal(pdisc->node_name, node_name))
- return FC_PARSE_FAILURE;
-
- return FC_PARSE_OK;
-}
-
-u16
-fc_abts_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id)
-{
- memcpy(fchs, &fc_bls_req_tmpl, sizeof(struct fchs_s));
- fchs->cat_info = FC_CAT_ABTS;
- fchs->d_id = (d_id);
- fchs->s_id = (s_id);
- fchs->ox_id = cpu_to_be16(ox_id);
-
- return sizeof(struct fchs_s);
-}
-
-enum fc_parse_status
-fc_abts_rsp_parse(struct fchs_s *fchs, int len)
-{
- if ((fchs->cat_info == FC_CAT_BA_ACC)
- || (fchs->cat_info == FC_CAT_BA_RJT))
- return FC_PARSE_OK;
-
- return FC_PARSE_FAILURE;
-}
-
-u16
-fc_rrq_build(struct fchs_s *fchs, struct fc_rrq_s *rrq, u32 d_id, u32 s_id,
- u16 ox_id, u16 rrq_oxid)
-{
- fc_els_req_build(fchs, d_id, s_id, ox_id);
-
- /*
- * build rrq payload
- */
- memcpy(rrq, &rrq_tmpl, sizeof(struct fc_rrq_s));
- rrq->s_id = (s_id);
- rrq->ox_id = cpu_to_be16(rrq_oxid);
- rrq->rx_id = FC_RXID_ANY;
-
- return sizeof(struct fc_rrq_s);
-}
-
u16
fc_logo_acc_build(struct fchs_s *fchs, void *pld, u32 d_id, u32 s_id,
__be16 ox_id)
@@ -659,30 +476,6 @@ fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code)
}
u16
-fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
- u32 d_id, u32 s_id, __be16 ox_id, int num_pages)
-{
- int page;
-
- fc_els_rsp_build(fchs, d_id, s_id, ox_id);
-
- memset(tprlo_acc, 0, (num_pages * 16) + 4);
- tprlo_acc->command = FC_ELS_ACC;
-
- tprlo_acc->page_len = 0x10;
- tprlo_acc->payload_len = cpu_to_be16((num_pages * 16) + 4);
-
- for (page = 0; page < num_pages; page++) {
- tprlo_acc->tprlo_acc_params[page].opa_valid = 0;
- tprlo_acc->tprlo_acc_params[page].rpa_valid = 0;
- tprlo_acc->tprlo_acc_params[page].fc4type_csp = FC_TYPE_FCP;
- tprlo_acc->tprlo_acc_params[page].orig_process_assc = 0;
- tprlo_acc->tprlo_acc_params[page].resp_process_assc = 0;
- }
- return be16_to_cpu(tprlo_acc->payload_len);
-}
-
-u16
fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
u32 s_id, __be16 ox_id, int num_pages)
{
@@ -707,20 +500,6 @@ fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc, u32 d_id,
}
u16
-fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid, u32 d_id,
- u32 s_id, u16 ox_id, u32 data_format)
-{
- fc_els_req_build(fchs, d_id, s_id, ox_id);
-
- memset(rnid, 0, sizeof(struct fc_rnid_cmd_s));
-
- rnid->els_cmd.els_code = FC_ELS_RNID;
- rnid->node_id_data_format = data_format;
-
- return sizeof(struct fc_rnid_cmd_s);
-}
-
-u16
fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
u32 s_id, __be16 ox_id, u32 data_format,
struct fc_rnid_common_id_data_s *common_id_data,
@@ -749,18 +528,6 @@ fc_rnid_acc_build(struct fchs_s *fchs, struct fc_rnid_acc_s *rnid_acc, u32 d_id,
}
u16
-fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc, u32 d_id,
- u32 s_id, u16 ox_id)
-{
- fc_els_req_build(fchs, d_id, s_id, ox_id);
-
- memset(rpsc, 0, sizeof(struct fc_rpsc_cmd_s));
-
- rpsc->els_cmd.els_code = FC_ELS_RPSC;
- return sizeof(struct fc_rpsc_cmd_s);
-}
-
-u16
fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rpsc2, u32 d_id,
u32 s_id, u32 *pid_list, u16 npids)
{
@@ -801,115 +568,6 @@ fc_rpsc_acc_build(struct fchs_s *fchs, struct fc_rpsc_acc_s *rpsc_acc,
return sizeof(struct fc_rpsc_acc_s);
}
-u16
-fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
- wwn_t port_name, wwn_t node_name, u16 pdu_size)
-{
- struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
-
- memcpy(pdisc, &plogi_tmpl, sizeof(struct fc_logi_s));
-
- pdisc->els_cmd.els_code = FC_ELS_PDISC;
- fc_els_req_build(fchs, d_id, s_id, ox_id);
-
- pdisc->csp.rxsz = pdisc->class3.rxsz = cpu_to_be16(pdu_size);
- pdisc->port_name = port_name;
- pdisc->node_name = node_name;
-
- return sizeof(struct fc_logi_s);
-}
-
-u16
-fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name)
-{
- struct fc_logi_s *pdisc = (struct fc_logi_s *) (fchs + 1);
-
- if (len < sizeof(struct fc_logi_s))
- return FC_PARSE_LEN_INVAL;
-
- if (pdisc->els_cmd.els_code != FC_ELS_ACC)
- return FC_PARSE_ACC_INVAL;
-
- if (!wwn_is_equal(pdisc->port_name, port_name))
- return FC_PARSE_PWWN_NOT_EQUAL;
-
- if (!pdisc->class3.class_valid)
- return FC_PARSE_NWWN_NOT_EQUAL;
-
- if (be16_to_cpu(pdisc->class3.rxsz) < (FC_MIN_PDUSZ))
- return FC_PARSE_RXSZ_INVAL;
-
- return FC_PARSE_OK;
-}
-
-u16
-fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
- int num_pages)
-{
- struct fc_prlo_s *prlo = (struct fc_prlo_s *) (fchs + 1);
- int page;
-
- fc_els_req_build(fchs, d_id, s_id, ox_id);
- memset(prlo, 0, (num_pages * 16) + 4);
- prlo->command = FC_ELS_PRLO;
- prlo->page_len = 0x10;
- prlo->payload_len = cpu_to_be16((num_pages * 16) + 4);
-
- for (page = 0; page < num_pages; page++) {
- prlo->prlo_params[page].type = FC_TYPE_FCP;
- prlo->prlo_params[page].opa_valid = 0;
- prlo->prlo_params[page].rpa_valid = 0;
- prlo->prlo_params[page].orig_process_assc = 0;
- prlo->prlo_params[page].resp_process_assc = 0;
- }
-
- return be16_to_cpu(prlo->payload_len);
-}
-
-u16
-fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id, u16 ox_id,
- int num_pages, enum fc_tprlo_type tprlo_type, u32 tpr_id)
-{
- struct fc_tprlo_s *tprlo = (struct fc_tprlo_s *) (fchs + 1);
- int page;
-
- fc_els_req_build(fchs, d_id, s_id, ox_id);
- memset(tprlo, 0, (num_pages * 16) + 4);
- tprlo->command = FC_ELS_TPRLO;
- tprlo->page_len = 0x10;
- tprlo->payload_len = cpu_to_be16((num_pages * 16) + 4);
-
- for (page = 0; page < num_pages; page++) {
- tprlo->tprlo_params[page].type = FC_TYPE_FCP;
- tprlo->tprlo_params[page].opa_valid = 0;
- tprlo->tprlo_params[page].rpa_valid = 0;
- tprlo->tprlo_params[page].orig_process_assc = 0;
- tprlo->tprlo_params[page].resp_process_assc = 0;
- if (tprlo_type == FC_GLOBAL_LOGO) {
- tprlo->tprlo_params[page].global_process_logout = 1;
- } else if (tprlo_type == FC_TPR_LOGO) {
- tprlo->tprlo_params[page].tpo_nport_valid = 1;
- tprlo->tprlo_params[page].tpo_nport_id = (tpr_id);
- }
- }
-
- return be16_to_cpu(tprlo->payload_len);
-}
-
-u16
-fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id, __be16 ox_id,
- u32 reason_code, u32 reason_expl)
-{
- struct fc_ba_rjt_s *ba_rjt = (struct fc_ba_rjt_s *) (fchs + 1);
-
- fc_bls_rsp_build(fchs, d_id, s_id, ox_id);
-
- fchs->cat_info = FC_CAT_BA_RJT;
- ba_rjt->reason_code = reason_code;
- ba_rjt->reason_expl = reason_expl;
- return sizeof(struct fc_ba_rjt_s);
-}
-
static void
fc_gs_cthdr_build(struct ct_hdr_s *cthdr, u32 s_id, u16 cmd_code)
{
@@ -974,35 +632,6 @@ fc_gpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
}
u16
-fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
- u32 port_id)
-{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- fcgs_gnnid_req_t *gnnid = (fcgs_gnnid_req_t *) (cthdr + 1);
- u32 d_id = bfa_hton3b(FC_NAME_SERVER);
-
- fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
- fc_gs_cthdr_build(cthdr, s_id, GS_GNN_ID);
-
- memset(gnnid, 0, sizeof(fcgs_gnnid_req_t));
- gnnid->dap = port_id;
- return sizeof(fcgs_gnnid_req_t) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_ct_rsp_parse(struct ct_hdr_s *cthdr)
-{
- if (be16_to_cpu(cthdr->cmd_rsp_code) != CT_RSP_ACCEPT) {
- if (cthdr->reason_code == CT_RSN_LOGICAL_BUSY)
- return FC_PARSE_BUSY;
- else
- return FC_PARSE_FAILURE;
- }
-
- return FC_PARSE_OK;
-}
-
-u16
fc_gs_rjt_build(struct fchs_s *fchs, struct ct_hdr_s *cthdr,
u32 d_id, u32 s_id, u16 ox_id, u8 reason_code,
u8 reason_code_expl)
@@ -1035,26 +664,6 @@ fc_scr_build(struct fchs_s *fchs, struct fc_scr_s *scr,
}
u16
-fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn,
- u32 s_id, u16 ox_id)
-{
- u32 d_id = bfa_hton3b(FC_FABRIC_CONTROLLER);
- u16 payldlen;
-
- fc_els_req_build(fchs, d_id, s_id, ox_id);
- rscn->command = FC_ELS_RSCN;
- rscn->pagelen = sizeof(rscn->event[0]);
-
- payldlen = sizeof(u32) + rscn->pagelen;
- rscn->payldlen = cpu_to_be16(payldlen);
-
- rscn->event[0].format = FC_RSCN_FORMAT_PORTID;
- rscn->event[0].portid = s_id;
-
- return struct_size(rscn, event, 1);
-}
-
-u16
fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
enum bfa_lport_role roles)
{
@@ -1079,26 +688,6 @@ fc_rftid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
}
u16
-fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
- u8 *fc4_bitmap, u32 bitmap_size)
-{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_rftid_req_s *rftid = (struct fcgs_rftid_req_s *)(cthdr + 1);
- u32 d_id = bfa_hton3b(FC_NAME_SERVER);
-
- fc_gs_fchdr_build(fchs, d_id, s_id, ox_id);
- fc_gs_cthdr_build(cthdr, s_id, GS_RFT_ID);
-
- memset(rftid, 0, sizeof(struct fcgs_rftid_req_s));
-
- rftid->dap = s_id;
- memcpy((void *)rftid->fc4_type, (void *)fc4_bitmap,
- (bitmap_size < 32 ? bitmap_size : 32));
-
- return sizeof(struct fcgs_rftid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
u8 fc4_type, u8 fc4_ftrs)
{
@@ -1182,24 +771,6 @@ fc_gid_ft_build(struct fchs_s *fchs, void *pyld, u32 s_id, u8 fc4_type)
}
u16
-fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
- wwn_t port_name)
-{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_rpnid_req_s *rpnid = (struct fcgs_rpnid_req_s *)(cthdr + 1);
- u32 d_id = bfa_hton3b(FC_NAME_SERVER);
-
- fc_gs_fchdr_build(fchs, d_id, s_id, 0);
- fc_gs_cthdr_build(cthdr, s_id, GS_RPN_ID);
-
- memset(rpnid, 0, sizeof(struct fcgs_rpnid_req_s));
- rpnid->port_id = port_id;
- rpnid->port_name = port_name;
-
- return sizeof(struct fcgs_rpnid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
wwn_t node_name)
{
@@ -1217,59 +788,6 @@ fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
return sizeof(struct fcgs_rnnid_req_s) + sizeof(struct ct_hdr_s);
}
-u16
-fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
- u32 cos)
-{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_rcsid_req_s *rcsid =
- (struct fcgs_rcsid_req_s *) (cthdr + 1);
- u32 d_id = bfa_hton3b(FC_NAME_SERVER);
-
- fc_gs_fchdr_build(fchs, d_id, s_id, 0);
- fc_gs_cthdr_build(cthdr, s_id, GS_RCS_ID);
-
- memset(rcsid, 0, sizeof(struct fcgs_rcsid_req_s));
- rcsid->port_id = port_id;
- rcsid->cos = cos;
-
- return sizeof(struct fcgs_rcsid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id,
- u8 port_type)
-{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_rptid_req_s *rptid = (struct fcgs_rptid_req_s *)(cthdr + 1);
- u32 d_id = bfa_hton3b(FC_NAME_SERVER);
-
- fc_gs_fchdr_build(fchs, d_id, s_id, 0);
- fc_gs_cthdr_build(cthdr, s_id, GS_RPT_ID);
-
- memset(rptid, 0, sizeof(struct fcgs_rptid_req_s));
- rptid->port_id = port_id;
- rptid->port_type = port_type;
-
- return sizeof(struct fcgs_rptid_req_s) + sizeof(struct ct_hdr_s);
-}
-
-u16
-fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id, u32 port_id)
-{
- struct ct_hdr_s *cthdr = (struct ct_hdr_s *) pyld;
- struct fcgs_ganxt_req_s *ganxt = (struct fcgs_ganxt_req_s *)(cthdr + 1);
- u32 d_id = bfa_hton3b(FC_NAME_SERVER);
-
- fc_gs_fchdr_build(fchs, d_id, s_id, 0);
- fc_gs_cthdr_build(cthdr, s_id, GS_GA_NXT);
-
- memset(ganxt, 0, sizeof(struct fcgs_ganxt_req_s));
- ganxt->port_id = port_id;
-
- return sizeof(struct ct_hdr_s) + sizeof(struct fcgs_ganxt_req_s);
-}
-
/*
* Builds fc hdr and ct hdr for FDMI requests.
*/
diff --git a/drivers/scsi/bfa/bfa_fcbuild.h b/drivers/scsi/bfa/bfa_fcbuild.h
index 49e0ee4a7334..51da37b2ae6b 100644
--- a/drivers/scsi/bfa/bfa_fcbuild.h
+++ b/drivers/scsi/bfa/bfa_fcbuild.h
@@ -127,15 +127,6 @@ struct fc_templates_s {
void fcbuild_init(void);
-u16 fc_flogi_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
- u32 s_id, u16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size, u8 set_npiv, u8 set_auth,
- u16 local_bb_credits);
-
-u16 fc_fdisc_build(struct fchs_s *buf, struct fc_logi_s *flogi, u32 s_id,
- u16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size);
-
u16 fc_flogi_acc_build(struct fchs_s *fchs, struct fc_logi_s *flogi,
u32 s_id, __be16 ox_id,
wwn_t port_name, wwn_t node_name,
@@ -148,14 +139,6 @@ u16 fc_plogi_build(struct fchs_s *fchs, void *pld, u32 d_id,
enum fc_parse_status fc_plogi_parse(struct fchs_s *fchs);
-u16 fc_abts_build(struct fchs_s *buf, u32 d_id, u32 s_id,
- u16 ox_id);
-
-enum fc_parse_status fc_abts_rsp_parse(struct fchs_s *buf, int len);
-
-u16 fc_rrq_build(struct fchs_s *buf, struct fc_rrq_s *rrq, u32 d_id,
- u32 s_id, u16 ox_id, u16 rrq_oxid);
-
u16 fc_rspnid_build(struct fchs_s *fchs, void *pld, u32 s_id,
u16 ox_id, u8 *name);
u16 fc_rsnn_nn_build(struct fchs_s *fchs, void *pld, u32 s_id,
@@ -164,10 +147,6 @@ u16 fc_rsnn_nn_build(struct fchs_s *fchs, void *pld, u32 s_id,
u16 fc_rftid_build(struct fchs_s *fchs, void *pld, u32 s_id,
u16 ox_id, enum bfa_lport_role role);
-u16 fc_rftid_build_sol(struct fchs_s *fchs, void *pyld, u32 s_id,
- u16 ox_id, u8 *fc4_bitmap,
- u32 bitmap_size);
-
u16 fc_rffid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u16 ox_id, u8 fc4_type, u8 fc4_ftrs);
@@ -193,9 +172,6 @@ u16 fc_adisc_build(struct fchs_s *fchs, struct fc_adisc_s *adisc,
u32 d_id, u32 s_id, __be16 ox_id, wwn_t port_name,
wwn_t node_name);
-enum fc_parse_status fc_adisc_parse(struct fchs_s *fchs, void *pld,
- u32 host_dap, wwn_t node_name, wwn_t port_name);
-
enum fc_parse_status fc_adisc_rsp_parse(struct fc_adisc_s *adisc, int len,
wwn_t port_name, wwn_t node_name);
@@ -216,10 +192,6 @@ u16 fc_prli_acc_build(struct fchs_s *fchs, void *pld, u32 d_id,
u32 s_id, __be16 ox_id,
enum bfa_lport_role role);
-u16 fc_rnid_build(struct fchs_s *fchs, struct fc_rnid_cmd_s *rnid,
- u32 d_id, u32 s_id, u16 ox_id,
- u32 data_format);
-
u16 fc_rnid_acc_build(struct fchs_s *fchs,
struct fc_rnid_acc_s *rnid_acc, u32 d_id, u32 s_id,
__be16 ox_id, u32 data_format,
@@ -228,29 +200,15 @@ u16 fc_rnid_acc_build(struct fchs_s *fchs,
u16 fc_rpsc2_build(struct fchs_s *fchs, struct fc_rpsc2_cmd_s *rps2c,
u32 d_id, u32 s_id, u32 *pid_list, u16 npids);
-u16 fc_rpsc_build(struct fchs_s *fchs, struct fc_rpsc_cmd_s *rpsc,
- u32 d_id, u32 s_id, u16 ox_id);
u16 fc_rpsc_acc_build(struct fchs_s *fchs,
struct fc_rpsc_acc_s *rpsc_acc, u32 d_id, u32 s_id,
__be16 ox_id, struct fc_rpsc_speed_info_s *oper_speed);
u16 fc_gid_ft_build(struct fchs_s *fchs, void *pld, u32 s_id,
u8 fc4_type);
-u16 fc_rpnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u32 port_id, wwn_t port_name);
-
u16 fc_rnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
u32 port_id, wwn_t node_name);
-u16 fc_rcsid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u32 port_id, u32 cos);
-
-u16 fc_rptid_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u32 port_id, u8 port_type);
-
-u16 fc_ganxt_build(struct fchs_s *fchs, void *pyld, u32 s_id,
- u32 port_id);
-
u16 fc_logo_build(struct fchs_s *fchs, struct fc_logo_s *logo, u32 d_id,
u32 s_id, u16 ox_id, wwn_t port_name);
@@ -267,46 +225,16 @@ void fc_get_fc4type_bitmask(u8 fc4_type, u8 *bit_mask);
void fc_els_req_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
__be16 ox_id);
-enum fc_parse_status fc_plogi_rsp_parse(struct fchs_s *fchs, int len,
- wwn_t port_name);
-
-enum fc_parse_status fc_prli_parse(struct fc_prli_s *prli);
-
-enum fc_parse_status fc_pdisc_parse(struct fchs_s *fchs, wwn_t node_name,
- wwn_t port_name);
-
u16 fc_ba_acc_build(struct fchs_s *fchs, struct fc_ba_acc_s *ba_acc, u32 d_id,
u32 s_id, __be16 ox_id, u16 rx_id);
int fc_logout_params_pages(struct fchs_s *fc_frame, u8 els_code);
-u16 fc_tprlo_acc_build(struct fchs_s *fchs, struct fc_tprlo_acc_s *tprlo_acc,
- u32 d_id, u32 s_id, __be16 ox_id, int num_pages);
-
u16 fc_prlo_acc_build(struct fchs_s *fchs, struct fc_prlo_acc_s *prlo_acc,
u32 d_id, u32 s_id, __be16 ox_id, int num_pages);
-u16 fc_pdisc_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id, wwn_t port_name, wwn_t node_name,
- u16 pdu_size);
-
-u16 fc_pdisc_rsp_parse(struct fchs_s *fchs, int len, wwn_t port_name);
-
-u16 fc_prlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- u16 ox_id, int num_pages);
-
u16 fc_tprlo_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
u16 ox_id, int num_pages, enum fc_tprlo_type tprlo_type,
u32 tpr_id);
-u16 fc_ba_rjt_build(struct fchs_s *fchs, u32 d_id, u32 s_id,
- __be16 ox_id, u32 reason_code, u32 reason_expl);
-
-u16 fc_gnnid_build(struct fchs_s *fchs, void *pyld, u32 s_id, u16 ox_id,
- u32 port_id);
-
-u16 fc_ct_rsp_parse(struct ct_hdr_s *cthdr);
-
-u16 fc_rscn_build(struct fchs_s *fchs, struct fc_rscn_pl_s *rscn, u32 s_id,
- u16 ox_id);
#endif
diff --git a/drivers/scsi/lpfc/lpfc_nvme.c b/drivers/scsi/lpfc/lpfc_nvme.c
index 49dd78ed8a9a..43dc1da4a156 100644
--- a/drivers/scsi/lpfc/lpfc_nvme.c
+++ b/drivers/scsi/lpfc/lpfc_nvme.c
@@ -242,7 +242,7 @@ lpfc_nvme_remoteport_delete(struct nvme_fc_remote_port *remoteport)
* @phba: pointer to lpfc hba data structure.
* @axchg: pointer to exchange context for the NVME LS request
*
- * This routine is used for processing an asychronously received NVME LS
+ * This routine is used for processing an asynchronously received NVME LS
* request. Any remaining validation is done and the LS is then forwarded
* to the nvme-fc transport via nvme_fc_rcv_ls_req().
*
diff --git a/drivers/scsi/lpfc/lpfc_nvmet.c b/drivers/scsi/lpfc/lpfc_nvmet.c
index e6c9112a8862..fba2e62027b7 100644
--- a/drivers/scsi/lpfc/lpfc_nvmet.c
+++ b/drivers/scsi/lpfc/lpfc_nvmet.c
@@ -2142,7 +2142,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
* @phba: pointer to lpfc hba data structure.
* @axchg: pointer to exchange context for the NVME LS request
*
- * This routine is used for processing an asychronously received NVME LS
+ * This routine is used for processing an asynchronously received NVME LS
* request. Any remaining validation is done and the LS is then forwarded
* to the nvmet-fc transport via nvmet_fc_rcv_ls_req().
*
diff --git a/drivers/scsi/megaraid/megaraid_sas_base.c b/drivers/scsi/megaraid/megaraid_sas_base.c
index 8e75e2e279a4..50f1dcb6d584 100644
--- a/drivers/scsi/megaraid/megaraid_sas_base.c
+++ b/drivers/scsi/megaraid/megaraid_sas_base.c
@@ -8907,8 +8907,11 @@ megasas_aen_polling(struct work_struct *work)
(ld_target_id / MEGASAS_MAX_DEV_PER_CHANNEL),
(ld_target_id % MEGASAS_MAX_DEV_PER_CHANNEL),
0);
- if (sdev1)
+ if (sdev1) {
+ mutex_unlock(&instance->reset_mutex);
megasas_remove_scsi_device(sdev1);
+ mutex_lock(&instance->reset_mutex);
+ }
event_type = SCAN_VD_CHANNEL;
break;
diff --git a/drivers/scsi/mpi3mr/mpi3mr.h b/drivers/scsi/mpi3mr/mpi3mr.h
index 81bb408ce56d..0c3e1ac076b5 100644
--- a/drivers/scsi/mpi3mr/mpi3mr.h
+++ b/drivers/scsi/mpi3mr/mpi3mr.h
@@ -57,8 +57,8 @@ extern struct list_head mrioc_list;
extern int prot_mask;
extern atomic64_t event_counter;
-#define MPI3MR_DRIVER_VERSION "8.12.0.0.50"
-#define MPI3MR_DRIVER_RELDATE "05-Sept-2024"
+#define MPI3MR_DRIVER_VERSION "8.12.0.3.50"
+#define MPI3MR_DRIVER_RELDATE "11-November-2024"
#define MPI3MR_DRIVER_NAME "mpi3mr"
#define MPI3MR_DRIVER_LICENSE "GPL"
@@ -134,8 +134,6 @@ extern atomic64_t event_counter;
#define MPI3MR_WATCHDOG_INTERVAL 1000 /* in milli seconds */
-#define MPI3MR_DEFAULT_CFG_PAGE_SZ 1024 /* in bytes */
-
#define MPI3MR_RESET_TOPOLOGY_SETTLE_TIME 10
#define MPI3MR_SCMD_TIMEOUT (60 * HZ)
@@ -1133,9 +1131,6 @@ struct scmd_priv {
* @io_throttle_low: I/O size to stop throttle in 512b blocks
* @num_io_throttle_group: Maximum number of throttle groups
* @throttle_groups: Pointer to throttle group info structures
- * @cfg_page: Default memory for configuration pages
- * @cfg_page_dma: Configuration page DMA address
- * @cfg_page_sz: Default configuration page memory size
* @sas_transport_enabled: SAS transport enabled or not
* @scsi_device_channel: Channel ID for SCSI devices
* @transport_cmds: Command tracker for SAS transport commands
@@ -1332,10 +1327,6 @@ struct mpi3mr_ioc {
u16 num_io_throttle_group;
struct mpi3mr_throttle_group_info *throttle_groups;
- void *cfg_page;
- dma_addr_t cfg_page_dma;
- u16 cfg_page_sz;
-
u8 sas_transport_enabled;
u8 scsi_device_channel;
struct mpi3mr_drv_cmd transport_cmds;
diff --git a/drivers/scsi/mpi3mr/mpi3mr_app.c b/drivers/scsi/mpi3mr/mpi3mr_app.c
index 01f035f9330e..10b8e4dc64f8 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_app.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_app.c
@@ -2329,6 +2329,15 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
if (!mrioc)
return -ENODEV;
+ if (mutex_lock_interruptible(&mrioc->bsg_cmds.mutex))
+ return -ERESTARTSYS;
+
+ if (mrioc->bsg_cmds.state & MPI3MR_CMD_PENDING) {
+ dprint_bsg_err(mrioc, "%s: command is in use\n", __func__);
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
+ return -EAGAIN;
+ }
+
if (!mrioc->ioctl_sges_allocated) {
dprint_bsg_err(mrioc, "%s: DMA memory was not allocated\n",
__func__);
@@ -2339,13 +2348,16 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
karg->timeout = MPI3MR_APP_DEFAULT_TIMEOUT;
mpi_req = kzalloc(MPI3MR_ADMIN_REQ_FRAME_SZ, GFP_KERNEL);
- if (!mpi_req)
+ if (!mpi_req) {
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
return -ENOMEM;
+ }
mpi_header = (struct mpi3_request_header *)mpi_req;
bufcnt = karg->buf_entry_list.num_of_entries;
drv_bufs = kzalloc((sizeof(*drv_bufs) * bufcnt), GFP_KERNEL);
if (!drv_bufs) {
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -ENOMEM;
goto out;
}
@@ -2353,6 +2365,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
dout_buf = kzalloc(job->request_payload.payload_len,
GFP_KERNEL);
if (!dout_buf) {
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -ENOMEM;
goto out;
}
@@ -2360,6 +2373,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
din_buf = kzalloc(job->reply_payload.payload_len,
GFP_KERNEL);
if (!din_buf) {
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -ENOMEM;
goto out;
}
@@ -2435,6 +2449,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
(mpi_msg_size > MPI3MR_ADMIN_REQ_FRAME_SZ)) {
dprint_bsg_err(mrioc, "%s: invalid MPI message size\n",
__func__);
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
@@ -2447,6 +2462,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
if (invalid_be) {
dprint_bsg_err(mrioc, "%s: invalid buffer entries passed\n",
__func__);
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
@@ -2454,12 +2470,14 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
if (sgl_dout_iter > (dout_buf + job->request_payload.payload_len)) {
dprint_bsg_err(mrioc, "%s: data_out buffer length mismatch\n",
__func__);
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
if (sgl_din_iter > (din_buf + job->reply_payload.payload_len)) {
dprint_bsg_err(mrioc, "%s: data_in buffer length mismatch\n",
__func__);
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
@@ -2472,6 +2490,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
dprint_bsg_err(mrioc, "%s:%d: invalid data transfer size passed for function 0x%x din_size = %d, dout_size = %d\n",
__func__, __LINE__, mpi_header->function, din_size,
dout_size);
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
@@ -2480,6 +2499,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
dprint_bsg_err(mrioc,
"%s:%d: invalid data transfer size passed for function 0x%x din_size=%d\n",
__func__, __LINE__, mpi_header->function, din_size);
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
@@ -2487,6 +2507,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
dprint_bsg_err(mrioc,
"%s:%d: invalid data transfer size passed for function 0x%x dout_size = %d\n",
__func__, __LINE__, mpi_header->function, dout_size);
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
@@ -2497,6 +2518,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
dprint_bsg_err(mrioc, "%s:%d: invalid message size passed:%d:%d:%d:%d\n",
__func__, __LINE__, din_cnt, dout_cnt, din_size,
dout_size);
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
rval = -EINVAL;
goto out;
}
@@ -2544,6 +2566,7 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
continue;
if (mpi3mr_map_data_buffer_dma(mrioc, drv_buf_iter, desc_count)) {
rval = -ENOMEM;
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
dprint_bsg_err(mrioc, "%s:%d: mapping data buffers failed\n",
__func__, __LINE__);
goto out;
@@ -2556,20 +2579,11 @@ static long mpi3mr_bsg_process_mpt_cmds(struct bsg_job *job)
sense_buff_k = kzalloc(erbsz, GFP_KERNEL);
if (!sense_buff_k) {
rval = -ENOMEM;
+ mutex_unlock(&mrioc->bsg_cmds.mutex);
goto out;
}
}
- if (mutex_lock_interruptible(&mrioc->bsg_cmds.mutex)) {
- rval = -ERESTARTSYS;
- goto out;
- }
- if (mrioc->bsg_cmds.state & MPI3MR_CMD_PENDING) {
- rval = -EAGAIN;
- dprint_bsg_err(mrioc, "%s: command is in use\n", __func__);
- mutex_unlock(&mrioc->bsg_cmds.mutex);
- goto out;
- }
if (mrioc->unrecoverable) {
dprint_bsg_err(mrioc, "%s: unrecoverable controller\n",
__func__);
diff --git a/drivers/scsi/mpi3mr/mpi3mr_fw.c b/drivers/scsi/mpi3mr/mpi3mr_fw.c
index f1ab76351bd8..5ed31fe57474 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_fw.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_fw.c
@@ -1036,6 +1036,36 @@ static const char *mpi3mr_reset_type_name(u16 reset_type)
}
/**
+ * mpi3mr_is_fault_recoverable - Read fault code and decide
+ * whether the controller can be recoverable
+ * @mrioc: Adapter instance reference
+ * Return: true if fault is recoverable, false otherwise.
+ */
+static inline bool mpi3mr_is_fault_recoverable(struct mpi3mr_ioc *mrioc)
+{
+ u32 fault;
+
+ fault = (readl(&mrioc->sysif_regs->fault) &
+ MPI3_SYSIF_FAULT_CODE_MASK);
+
+ switch (fault) {
+ case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED:
+ case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED:
+ ioc_warn(mrioc,
+ "controller requires system power cycle, marking controller as unrecoverable\n");
+ return false;
+ case MPI3_SYSIF_FAULT_CODE_INSUFFICIENT_PCI_SLOT_POWER:
+ ioc_warn(mrioc,
+ "controller faulted due to insufficient power,\n"
+ " try by connecting it to a different slot\n");
+ return false;
+ default:
+ break;
+ }
+ return true;
+}
+
+/**
* mpi3mr_print_fault_info - Display fault information
* @mrioc: Adapter instance reference
*
@@ -1373,6 +1403,11 @@ retry_bring_ioc_ready:
ioc_info(mrioc, "ioc_status(0x%08x), ioc_config(0x%08x), ioc_info(0x%016llx) at the bringup\n",
ioc_status, ioc_config, base_info);
+ if (!mpi3mr_is_fault_recoverable(mrioc)) {
+ mrioc->unrecoverable = 1;
+ goto out_device_not_present;
+ }
+
/*The timeout value is in 2sec unit, changing it to seconds*/
mrioc->ready_timeout =
((base_info & MPI3_SYSIF_IOC_INFO_LOW_TIMEOUT_MASK) >>
@@ -2734,6 +2769,11 @@ static void mpi3mr_watchdog_work(struct work_struct *work)
mpi3mr_print_fault_info(mrioc);
mrioc->diagsave_timeout = 0;
+ if (!mpi3mr_is_fault_recoverable(mrioc)) {
+ mrioc->unrecoverable = 1;
+ goto schedule_work;
+ }
+
switch (trigger_data.fault) {
case MPI3_SYSIF_FAULT_CODE_COMPLETE_RESET_NEEDED:
case MPI3_SYSIF_FAULT_CODE_POWER_CYCLE_REQUIRED:
@@ -4186,17 +4226,6 @@ retry_init:
mpi3mr_read_tsu_interval(mrioc);
mpi3mr_print_ioc_info(mrioc);
- if (!mrioc->cfg_page) {
- dprint_init(mrioc, "allocating config page buffers\n");
- mrioc->cfg_page_sz = MPI3MR_DEFAULT_CFG_PAGE_SZ;
- mrioc->cfg_page = dma_alloc_coherent(&mrioc->pdev->dev,
- mrioc->cfg_page_sz, &mrioc->cfg_page_dma, GFP_KERNEL);
- if (!mrioc->cfg_page) {
- retval = -1;
- goto out_failed_noretry;
- }
- }
-
dprint_init(mrioc, "allocating host diag buffers\n");
mpi3mr_alloc_diag_bufs(mrioc);
@@ -4768,11 +4797,7 @@ void mpi3mr_free_mem(struct mpi3mr_ioc *mrioc)
mrioc->admin_req_base, mrioc->admin_req_dma);
mrioc->admin_req_base = NULL;
}
- if (mrioc->cfg_page) {
- dma_free_coherent(&mrioc->pdev->dev, mrioc->cfg_page_sz,
- mrioc->cfg_page, mrioc->cfg_page_dma);
- mrioc->cfg_page = NULL;
- }
+
if (mrioc->pel_seqnum_virt) {
dma_free_coherent(&mrioc->pdev->dev, mrioc->pel_seqnum_sz,
mrioc->pel_seqnum_virt, mrioc->pel_seqnum_dma);
@@ -5392,55 +5417,6 @@ out:
return retval;
}
-
-/**
- * mpi3mr_free_config_dma_memory - free memory for config page
- * @mrioc: Adapter instance reference
- * @mem_desc: memory descriptor structure
- *
- * Check whether the size of the buffer specified by the memory
- * descriptor is greater than the default page size if so then
- * free the memory pointed by the descriptor.
- *
- * Return: Nothing.
- */
-static void mpi3mr_free_config_dma_memory(struct mpi3mr_ioc *mrioc,
- struct dma_memory_desc *mem_desc)
-{
- if ((mem_desc->size > mrioc->cfg_page_sz) && mem_desc->addr) {
- dma_free_coherent(&mrioc->pdev->dev, mem_desc->size,
- mem_desc->addr, mem_desc->dma_addr);
- mem_desc->addr = NULL;
- }
-}
-
-/**
- * mpi3mr_alloc_config_dma_memory - Alloc memory for config page
- * @mrioc: Adapter instance reference
- * @mem_desc: Memory descriptor to hold dma memory info
- *
- * This function allocates new dmaable memory or provides the
- * default config page dmaable memory based on the memory size
- * described by the descriptor.
- *
- * Return: 0 on success, non-zero on failure.
- */
-static int mpi3mr_alloc_config_dma_memory(struct mpi3mr_ioc *mrioc,
- struct dma_memory_desc *mem_desc)
-{
- if (mem_desc->size > mrioc->cfg_page_sz) {
- mem_desc->addr = dma_alloc_coherent(&mrioc->pdev->dev,
- mem_desc->size, &mem_desc->dma_addr, GFP_KERNEL);
- if (!mem_desc->addr)
- return -ENOMEM;
- } else {
- mem_desc->addr = mrioc->cfg_page;
- mem_desc->dma_addr = mrioc->cfg_page_dma;
- memset(mem_desc->addr, 0, mrioc->cfg_page_sz);
- }
- return 0;
-}
-
/**
* mpi3mr_post_cfg_req - Issue config requests and wait
* @mrioc: Adapter instance reference
@@ -5596,8 +5572,12 @@ static int mpi3mr_process_cfg_req(struct mpi3mr_ioc *mrioc,
cfg_req->page_length = cfg_hdr->page_length;
cfg_req->page_version = cfg_hdr->page_version;
}
- if (mpi3mr_alloc_config_dma_memory(mrioc, &mem_desc))
- goto out;
+
+ mem_desc.addr = dma_alloc_coherent(&mrioc->pdev->dev,
+ mem_desc.size, &mem_desc.dma_addr, GFP_KERNEL);
+
+ if (!mem_desc.addr)
+ return retval;
mpi3mr_add_sg_single(&cfg_req->sgl, sgl_flags, mem_desc.size,
mem_desc.dma_addr);
@@ -5626,7 +5606,12 @@ static int mpi3mr_process_cfg_req(struct mpi3mr_ioc *mrioc,
}
out:
- mpi3mr_free_config_dma_memory(mrioc, &mem_desc);
+ if (mem_desc.addr) {
+ dma_free_coherent(&mrioc->pdev->dev, mem_desc.size,
+ mem_desc.addr, mem_desc.dma_addr);
+ mem_desc.addr = NULL;
+ }
+
return retval;
}
diff --git a/drivers/scsi/mpi3mr/mpi3mr_os.c b/drivers/scsi/mpi3mr/mpi3mr_os.c
index 5f2f67acf8bf..1bef88130d0c 100644
--- a/drivers/scsi/mpi3mr/mpi3mr_os.c
+++ b/drivers/scsi/mpi3mr/mpi3mr_os.c
@@ -5215,7 +5215,7 @@ mpi3mr_probe(struct pci_dev *pdev, const struct pci_device_id *id)
}
mrioc = shost_priv(shost);
- retval = ida_alloc_range(&mrioc_ida, 1, U8_MAX, GFP_KERNEL);
+ retval = ida_alloc_range(&mrioc_ida, 0, U8_MAX, GFP_KERNEL);
if (retval < 0)
goto id_alloc_failed;
mrioc->id = (u8)retval;
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.c b/drivers/scsi/mpt3sas/mpt3sas_base.c
index ed5046593fda..16ac2267c71e 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.c
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.c
@@ -7041,11 +7041,12 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
int i;
u8 failed;
__le32 *mfp;
+ int ret_val;
/* make sure doorbell is not in use */
if ((ioc->base_readl_ext_retry(&ioc->chip->Doorbell) & MPI2_DOORBELL_USED)) {
ioc_err(ioc, "doorbell is in use (line=%d)\n", __LINE__);
- return -EFAULT;
+ goto doorbell_diag_reset;
}
/* clear pending doorbell interrupts from previous state changes */
@@ -7135,6 +7136,10 @@ _base_handshake_req_reply_wait(struct MPT3SAS_ADAPTER *ioc, int request_bytes,
le32_to_cpu(mfp[i]));
}
return 0;
+
+doorbell_diag_reset:
+ ret_val = _base_diag_reset(ioc);
+ return ret_val;
}
/**
diff --git a/drivers/scsi/mpt3sas/mpt3sas_base.h b/drivers/scsi/mpt3sas/mpt3sas_base.h
index eceb5eeb4651..d8d1a64b4764 100644
--- a/drivers/scsi/mpt3sas/mpt3sas_base.h
+++ b/drivers/scsi/mpt3sas/mpt3sas_base.h
@@ -77,11 +77,11 @@
#define MPT3SAS_DRIVER_NAME "mpt3sas"
#define MPT3SAS_AUTHOR "Avago Technologies <MPT-FusionLinux.pdl@avagotech.com>"
#define MPT3SAS_DESCRIPTION "LSI MPT Fusion SAS 3.0 Device Driver"
-#define MPT3SAS_DRIVER_VERSION "48.100.00.00"
-#define MPT3SAS_MAJOR_VERSION 48
+#define MPT3SAS_DRIVER_VERSION "51.100.00.00"
+#define MPT3SAS_MAJOR_VERSION 51
#define MPT3SAS_MINOR_VERSION 100
-#define MPT3SAS_BUILD_VERSION 0
-#define MPT3SAS_RELEASE_VERSION 00
+#define MPT3SAS_BUILD_VERSION 00
+#define MPT3SAS_RELEASE_VERSION 00
#define MPT2SAS_DRIVER_NAME "mpt2sas"
#define MPT2SAS_DESCRIPTION "LSI MPT Fusion SAS 2.0 Device Driver"
diff --git a/drivers/scsi/qla1280.h b/drivers/scsi/qla1280.h
index d309e2ca14de..dea2290b37d4 100644
--- a/drivers/scsi/qla1280.h
+++ b/drivers/scsi/qla1280.h
@@ -116,12 +116,12 @@ struct device_reg {
uint16_t id_h; /* ID high */
uint16_t cfg_0; /* Configuration 0 */
#define ISP_CFG0_HWMSK 0x000f /* Hardware revision mask */
-#define ISP_CFG0_1020 BIT_0 /* ISP1020 */
-#define ISP_CFG0_1020A BIT_1 /* ISP1020A */
-#define ISP_CFG0_1040 BIT_2 /* ISP1040 */
-#define ISP_CFG0_1040A BIT_3 /* ISP1040A */
-#define ISP_CFG0_1040B BIT_4 /* ISP1040B */
-#define ISP_CFG0_1040C BIT_5 /* ISP1040C */
+#define ISP_CFG0_1020 1 /* ISP1020 */
+#define ISP_CFG0_1020A 2 /* ISP1020A */
+#define ISP_CFG0_1040 3 /* ISP1040 */
+#define ISP_CFG0_1040A 4 /* ISP1040A */
+#define ISP_CFG0_1040B 5 /* ISP1040B */
+#define ISP_CFG0_1040C 6 /* ISP1040C */
uint16_t cfg_1; /* Configuration 1 */
#define ISP_CFG1_F128 BIT_6 /* 128-byte FIFO threshold */
#define ISP_CFG1_F64 BIT_4|BIT_5 /* 128-byte FIFO threshold */
diff --git a/drivers/scsi/qla2xxx/qla_attr.c b/drivers/scsi/qla2xxx/qla_attr.c
index 2810608acd96..e6ece30c4348 100644
--- a/drivers/scsi/qla2xxx/qla_attr.c
+++ b/drivers/scsi/qla2xxx/qla_attr.c
@@ -3304,6 +3304,7 @@ struct fc_function_template qla2xxx_transport_vport_functions = {
.show_host_node_name = 1,
.show_host_port_name = 1,
.show_host_supported_classes = 1,
+ .show_host_supported_speeds = 1,
.get_host_port_id = qla2x00_get_host_port_id,
.show_host_port_id = 1,
diff --git a/drivers/scsi/qla2xxx/qla_bsg.c b/drivers/scsi/qla2xxx/qla_bsg.c
index 52dc9604f567..10431a67d202 100644
--- a/drivers/scsi/qla2xxx/qla_bsg.c
+++ b/drivers/scsi/qla2xxx/qla_bsg.c
@@ -24,6 +24,7 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
{
struct bsg_job *bsg_job = sp->u.bsg_job;
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ struct completion *comp = sp->comp;
ql_dbg(ql_dbg_user, sp->vha, 0x7009,
"%s: sp hdl %x, result=%x bsg ptr %p\n",
@@ -35,6 +36,9 @@ void qla2x00_bsg_job_done(srb_t *sp, int res)
bsg_reply->result = res;
bsg_job_done(bsg_job, bsg_reply->result,
bsg_reply->reply_payload_rcv_len);
+
+ if (comp)
+ complete(comp);
}
void qla2x00_bsg_sp_free(srb_t *sp)
@@ -490,16 +494,6 @@ qla2x00_process_ct(struct bsg_job *bsg_job)
goto done;
}
- if ((req_sg_cnt != bsg_job->request_payload.sg_cnt) ||
- (rsp_sg_cnt != bsg_job->reply_payload.sg_cnt)) {
- ql_log(ql_log_warn, vha, 0x7011,
- "request_sg_cnt: %x dma_request_sg_cnt: %x reply_sg_cnt:%x "
- "dma_reply_sg_cnt: %x\n", bsg_job->request_payload.sg_cnt,
- req_sg_cnt, bsg_job->reply_payload.sg_cnt, rsp_sg_cnt);
- rval = -EAGAIN;
- goto done_unmap_sg;
- }
-
if (!vha->flags.online) {
ql_log(ql_log_warn, vha, 0x7012,
"Host is not online.\n");
@@ -3061,7 +3055,7 @@ skip_chip_chk:
static bool qla_bsg_found(struct qla_qpair *qpair, struct bsg_job *bsg_job)
{
- bool found = false;
+ bool found, do_bsg_done;
struct fc_bsg_reply *bsg_reply = bsg_job->reply;
scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
struct qla_hw_data *ha = vha->hw;
@@ -3069,6 +3063,11 @@ static bool qla_bsg_found(struct qla_qpair *qpair, struct bsg_job *bsg_job)
int cnt;
unsigned long flags;
struct req_que *req;
+ int rval;
+ DECLARE_COMPLETION_ONSTACK(comp);
+ uint32_t ratov_j;
+
+ found = do_bsg_done = false;
spin_lock_irqsave(qpair->qp_lock_ptr, flags);
req = qpair->req;
@@ -3080,42 +3079,104 @@ static bool qla_bsg_found(struct qla_qpair *qpair, struct bsg_job *bsg_job)
sp->type == SRB_ELS_CMD_HST ||
sp->type == SRB_ELS_CMD_HST_NOLOGIN) &&
sp->u.bsg_job == bsg_job) {
- req->outstanding_cmds[cnt] = NULL;
- spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
-
- if (!ha->flags.eeh_busy && ha->isp_ops->abort_command(sp)) {
- ql_log(ql_log_warn, vha, 0x7089,
- "mbx abort_command failed.\n");
- bsg_reply->result = -EIO;
- } else {
- ql_dbg(ql_dbg_user, vha, 0x708a,
- "mbx abort_command success.\n");
- bsg_reply->result = 0;
- }
- /* ref: INIT */
- kref_put(&sp->cmd_kref, qla2x00_sp_release);
found = true;
- goto done;
+ sp->comp = &comp;
+ break;
}
}
spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
-done:
- return found;
+ if (!found)
+ return false;
+
+ if (ha->flags.eeh_busy) {
+ /* skip over abort. EEH handling will return the bsg. Wait for it */
+ rval = QLA_SUCCESS;
+ ql_dbg(ql_dbg_user, vha, 0x802c,
+ "eeh encounter. bsg %p sp=%p handle=%x \n",
+ bsg_job, sp, sp->handle);
+ } else {
+ rval = ha->isp_ops->abort_command(sp);
+ ql_dbg(ql_dbg_user, vha, 0x802c,
+ "Aborting bsg %p sp=%p handle=%x rval=%x\n",
+ bsg_job, sp, sp->handle, rval);
+ }
+
+ switch (rval) {
+ case QLA_SUCCESS:
+ /* Wait for the command completion. */
+ ratov_j = ha->r_a_tov / 10 * 4 * 1000;
+ ratov_j = msecs_to_jiffies(ratov_j);
+
+ if (!wait_for_completion_timeout(&comp, ratov_j)) {
+ ql_log(ql_log_info, vha, 0x7089,
+ "bsg abort timeout. bsg=%p sp=%p handle %#x .\n",
+ bsg_job, sp, sp->handle);
+
+ do_bsg_done = true;
+ } else {
+ /* fw had returned the bsg */
+ ql_dbg(ql_dbg_user, vha, 0x708a,
+ "bsg abort success. bsg %p sp=%p handle=%#x\n",
+ bsg_job, sp, sp->handle);
+ do_bsg_done = false;
+ }
+ break;
+ default:
+ ql_log(ql_log_info, vha, 0x704f,
+ "bsg abort fail. bsg=%p sp=%p rval=%x.\n",
+ bsg_job, sp, rval);
+
+ do_bsg_done = true;
+ break;
+ }
+
+ if (!do_bsg_done)
+ return true;
+
+ spin_lock_irqsave(qpair->qp_lock_ptr, flags);
+ /*
+ * recheck to make sure it's still the same bsg_job due to
+ * qp_lock_ptr was released earlier.
+ */
+ if (req->outstanding_cmds[cnt] &&
+ req->outstanding_cmds[cnt]->u.bsg_job != bsg_job) {
+ /* fw had returned the bsg */
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+ return true;
+ }
+ req->outstanding_cmds[cnt] = NULL;
+ spin_unlock_irqrestore(qpair->qp_lock_ptr, flags);
+
+ /* ref: INIT */
+ sp->comp = NULL;
+ kref_put(&sp->cmd_kref, qla2x00_sp_release);
+ bsg_reply->result = -ENXIO;
+ bsg_reply->reply_payload_rcv_len = 0;
+
+ ql_dbg(ql_dbg_user, vha, 0x7051,
+ "%s bsg_job_done : bsg %p result %#x sp %p.\n",
+ __func__, bsg_job, bsg_reply->result, sp);
+
+ bsg_job_done(bsg_job, bsg_reply->result, bsg_reply->reply_payload_rcv_len);
+
+ return true;
}
int
qla24xx_bsg_timeout(struct bsg_job *bsg_job)
{
- struct fc_bsg_reply *bsg_reply = bsg_job->reply;
+ struct fc_bsg_request *bsg_request = bsg_job->request;
scsi_qla_host_t *vha = shost_priv(fc_bsg_to_shost(bsg_job));
struct qla_hw_data *ha = vha->hw;
int i;
struct qla_qpair *qpair;
- ql_log(ql_log_info, vha, 0x708b, "%s CMD timeout. bsg ptr %p.\n",
- __func__, bsg_job);
+ ql_log(ql_log_info, vha, 0x708b,
+ "%s CMD timeout. bsg ptr %p msgcode %x vendor cmd %x\n",
+ __func__, bsg_job, bsg_request->msgcode,
+ bsg_request->rqst_data.h_vendor.vendor_cmd[0]);
if (qla2x00_isp_reg_stat(ha)) {
ql_log(ql_log_info, vha, 0x9007,
@@ -3136,7 +3197,6 @@ qla24xx_bsg_timeout(struct bsg_job *bsg_job)
}
ql_log(ql_log_info, vha, 0x708b, "SRB not found to abort.\n");
- bsg_reply->result = -ENXIO;
done:
return 0;
diff --git a/drivers/scsi/qla2xxx/qla_mid.c b/drivers/scsi/qla2xxx/qla_mid.c
index 76703f2706b8..79879c4743e6 100644
--- a/drivers/scsi/qla2xxx/qla_mid.c
+++ b/drivers/scsi/qla2xxx/qla_mid.c
@@ -506,6 +506,7 @@ qla24xx_create_vhost(struct fc_vport *fc_vport)
return(NULL);
}
+ vha->irq_offset = QLA_BASE_VECTORS;
host = vha->host;
fc_vport->dd_data = vha;
/* New host info */
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index 7f980e6141c2..7ab717ed7232 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -6902,12 +6902,15 @@ qla2x00_do_dpc(void *data)
set_user_nice(current, MIN_NICE);
set_current_state(TASK_INTERRUPTIBLE);
- while (!kthread_should_stop()) {
+ while (1) {
ql_dbg(ql_dbg_dpc, base_vha, 0x4000,
"DPC handler sleeping.\n");
schedule();
+ if (kthread_should_stop())
+ break;
+
if (test_and_clear_bit(DO_EEH_RECOVERY, &base_vha->dpc_flags))
qla_pci_set_eeh_busy(base_vha);
@@ -6920,15 +6923,16 @@ qla2x00_do_dpc(void *data)
goto end_loop;
}
+ if (test_bit(UNLOADING, &base_vha->dpc_flags))
+ /* don't do any work. Wait to be terminated by kthread_stop */
+ goto end_loop;
+
ha->dpc_active = 1;
ql_dbg(ql_dbg_dpc + ql_dbg_verbose, base_vha, 0x4001,
"DPC handler waking up, dpc_flags=0x%lx.\n",
base_vha->dpc_flags);
- if (test_bit(UNLOADING, &base_vha->dpc_flags))
- break;
-
if (IS_P3P_TYPE(ha)) {
if (IS_QLA8044(ha)) {
if (test_and_clear_bit(ISP_UNRECOVERABLE,
@@ -7241,9 +7245,6 @@ end_loop:
*/
ha->dpc_active = 0;
- /* Cleanup any residual CTX SRBs. */
- qla2x00_abort_all_cmds(base_vha, DID_NO_CONNECT << 16);
-
return 0;
}
diff --git a/drivers/scsi/qla2xxx/qla_version.h b/drivers/scsi/qla2xxx/qla_version.h
index cf0f9d9db645..a491d6ee5c94 100644
--- a/drivers/scsi/qla2xxx/qla_version.h
+++ b/drivers/scsi/qla2xxx/qla_version.h
@@ -6,9 +6,9 @@
/*
* Driver version
*/
-#define QLA2XXX_VERSION "10.02.09.300-k"
+#define QLA2XXX_VERSION "10.02.09.400-k"
#define QLA_DRIVER_MAJOR_VER 10
#define QLA_DRIVER_MINOR_VER 2
#define QLA_DRIVER_PATCH_VER 9
-#define QLA_DRIVER_BETA_VER 300
+#define QLA_DRIVER_BETA_VER 400
diff --git a/drivers/scsi/scsi_debug.c b/drivers/scsi/scsi_debug.c
index b52513eeeafa..680ba180a672 100644
--- a/drivers/scsi/scsi_debug.c
+++ b/drivers/scsi/scsi_debug.c
@@ -6447,7 +6447,7 @@ static int schedule_resp(struct scsi_cmnd *cmnd, struct sdebug_dev_info *devip,
}
sd_dp = &sqcp->sd_dp;
- if (polled)
+ if (polled || (ndelay > 0 && ndelay < INCLUSIVE_TIMING_MAX_NS))
ns_from_boot = ktime_get_boottime_ns();
/* one of the resp_*() response functions is called here */
diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c
index 32f94db6d6bf..f3a1ecb42128 100644
--- a/drivers/scsi/scsi_sysfs.c
+++ b/drivers/scsi/scsi_sysfs.c
@@ -1274,7 +1274,7 @@ static umode_t scsi_sdev_attr_is_visible(struct kobject *kobj,
}
static umode_t scsi_sdev_bin_attr_is_visible(struct kobject *kobj,
- struct bin_attribute *attr, int i)
+ const struct bin_attribute *attr, int i)
{
struct device *dev = kobj_to_dev(kobj);
struct scsi_device *sdev = to_scsi_device(dev);
diff --git a/drivers/scsi/sg.c b/drivers/scsi/sg.c
index 84334ab39c81..94127868bedf 100644
--- a/drivers/scsi/sg.c
+++ b/drivers/scsi/sg.c
@@ -386,7 +386,6 @@ sg_release(struct inode *inode, struct file *filp)
SCSI_LOG_TIMEOUT(3, sg_printk(KERN_INFO, sdp, "sg_release\n"));
mutex_lock(&sdp->open_rel_lock);
- kref_put(&sfp->f_ref, sg_remove_sfp);
sdp->open_cnt--;
/* possibly many open()s waiting on exlude clearing, start many;
@@ -398,6 +397,7 @@ sg_release(struct inode *inode, struct file *filp)
wake_up_interruptible(&sdp->open_wait);
}
mutex_unlock(&sdp->open_rel_lock);
+ kref_put(&sfp->f_ref, sg_remove_sfp);
return 0;
}
diff --git a/drivers/scsi/storvsc_drv.c b/drivers/scsi/storvsc_drv.c
index 7ceb982040a5..d0b55c1fa908 100644
--- a/drivers/scsi/storvsc_drv.c
+++ b/drivers/scsi/storvsc_drv.c
@@ -149,6 +149,8 @@ struct hv_fc_wwn_packet {
*/
static int vmstor_proto_version;
+static bool hv_dev_is_fc(struct hv_device *hv_dev);
+
#define STORVSC_LOGGING_NONE 0
#define STORVSC_LOGGING_ERROR 1
#define STORVSC_LOGGING_WARN 2
@@ -1138,6 +1140,7 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device,
* not correctly handle:
* INQUIRY command with page code parameter set to 0x80
* MODE_SENSE command with cmd[2] == 0x1c
+ * MAINTENANCE_IN is not supported by HyperV FC passthrough
*
* Setup srb and scsi status so this won't be fatal.
* We do this so we can distinguish truly fatal failues
@@ -1145,7 +1148,9 @@ static void storvsc_on_io_completion(struct storvsc_device *stor_device,
*/
if ((stor_pkt->vm_srb.cdb[0] == INQUIRY) ||
- (stor_pkt->vm_srb.cdb[0] == MODE_SENSE)) {
+ (stor_pkt->vm_srb.cdb[0] == MODE_SENSE) ||
+ (stor_pkt->vm_srb.cdb[0] == MAINTENANCE_IN &&
+ hv_dev_is_fc(device))) {
vstor_packet->vm_srb.scsi_status = 0;
vstor_packet->vm_srb.srb_status = SRB_STATUS_SUCCESS;
}
diff --git a/drivers/sh/intc/core.c b/drivers/sh/intc/core.c
index 74350b5871dc..ea571eeb3078 100644
--- a/drivers/sh/intc/core.c
+++ b/drivers/sh/intc/core.c
@@ -209,7 +209,6 @@ int __init register_intc_controller(struct intc_desc *desc)
goto err0;
INIT_LIST_HEAD(&d->list);
- list_add_tail(&d->list, &intc_list);
raw_spin_lock_init(&d->lock);
INIT_RADIX_TREE(&d->tree, GFP_ATOMIC);
@@ -369,6 +368,7 @@ int __init register_intc_controller(struct intc_desc *desc)
d->skip_suspend = desc->skip_syscore_suspend;
+ list_add_tail(&d->list, &intc_list);
nr_intc_controllers++;
return 0;
diff --git a/drivers/slimbus/qcom-ctrl.c b/drivers/slimbus/qcom-ctrl.c
index e25f9bdd9b23..ab344f7472f2 100644
--- a/drivers/slimbus/qcom-ctrl.c
+++ b/drivers/slimbus/qcom-ctrl.c
@@ -722,7 +722,7 @@ MODULE_DEVICE_TABLE(of, qcom_slim_dt_match);
static struct platform_driver qcom_slim_driver = {
.probe = qcom_slim_probe,
- .remove_new = qcom_slim_remove,
+ .remove = qcom_slim_remove,
.driver = {
.name = "qcom_slim_ctrl",
.of_match_table = qcom_slim_dt_match,
diff --git a/drivers/slimbus/qcom-ngd-ctrl.c b/drivers/slimbus/qcom-ngd-ctrl.c
index 1ac8e2912fd1..4fb66986cc22 100644
--- a/drivers/slimbus/qcom-ngd-ctrl.c
+++ b/drivers/slimbus/qcom-ngd-ctrl.c
@@ -1743,7 +1743,7 @@ static const struct dev_pm_ops qcom_slim_ngd_dev_pm_ops = {
static struct platform_driver qcom_slim_ngd_ctrl_driver = {
.probe = qcom_slim_ngd_ctrl_probe,
- .remove_new = qcom_slim_ngd_ctrl_remove,
+ .remove = qcom_slim_ngd_ctrl_remove,
.driver = {
.name = "qcom,slim-ngd-ctrl",
.of_match_table = qcom_slim_ngd_dt_match,
@@ -1752,7 +1752,7 @@ static struct platform_driver qcom_slim_ngd_ctrl_driver = {
static struct platform_driver qcom_slim_ngd_driver = {
.probe = qcom_slim_ngd_probe,
- .remove_new = qcom_slim_ngd_remove,
+ .remove = qcom_slim_ngd_remove,
.driver = {
.name = QCOM_SLIM_NGD_DRV_NAME,
.pm = &qcom_slim_ngd_dev_pm_ops,
diff --git a/drivers/soundwire/amd_init.c b/drivers/soundwire/amd_init.c
index d11b60efda33..643e94524fe6 100644
--- a/drivers/soundwire/amd_init.c
+++ b/drivers/soundwire/amd_init.c
@@ -173,7 +173,7 @@ int sdw_amd_probe(struct sdw_amd_res *res, struct sdw_amd_ctx **sdw_ctx)
return sdw_amd_startup(*sdw_ctx);
}
-EXPORT_SYMBOL_NS(sdw_amd_probe, SOUNDWIRE_AMD_INIT);
+EXPORT_SYMBOL_NS(sdw_amd_probe, "SOUNDWIRE_AMD_INIT");
void sdw_amd_exit(struct sdw_amd_ctx *ctx)
{
@@ -181,7 +181,7 @@ void sdw_amd_exit(struct sdw_amd_ctx *ctx)
kfree(ctx->peripherals);
kfree(ctx);
}
-EXPORT_SYMBOL_NS(sdw_amd_exit, SOUNDWIRE_AMD_INIT);
+EXPORT_SYMBOL_NS(sdw_amd_exit, "SOUNDWIRE_AMD_INIT");
int sdw_amd_get_slave_info(struct sdw_amd_ctx *ctx)
{
@@ -224,7 +224,7 @@ int sdw_amd_get_slave_info(struct sdw_amd_ctx *ctx)
}
return 0;
}
-EXPORT_SYMBOL_NS(sdw_amd_get_slave_info, SOUNDWIRE_AMD_INIT);
+EXPORT_SYMBOL_NS(sdw_amd_get_slave_info, "SOUNDWIRE_AMD_INIT");
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
MODULE_DESCRIPTION("AMD SoundWire Init Library");
diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c
index 5a4bfaef65fb..96a7f9709720 100644
--- a/drivers/soundwire/amd_manager.c
+++ b/drivers/soundwire/amd_manager.c
@@ -1221,7 +1221,7 @@ static const struct dev_pm_ops amd_pm = {
static struct platform_driver amd_sdw_driver = {
.probe = &amd_sdw_manager_probe,
- .remove_new = &amd_sdw_manager_remove,
+ .remove = &amd_sdw_manager_remove,
.driver = {
.name = "amd_sdw_manager",
.pm = &amd_pm,
diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c
index 421da0f86fad..9db78f3d7615 100644
--- a/drivers/soundwire/intel.c
+++ b/drivers/soundwire/intel.c
@@ -1111,4 +1111,4 @@ const struct sdw_intel_hw_ops sdw_intel_cnl_hw_ops = {
.sync_go = intel_shim_sync_go,
.sync_check_cmdsync_unlocked = intel_check_cmdsync_unlocked,
};
-EXPORT_SYMBOL_NS(sdw_intel_cnl_hw_ops, SOUNDWIRE_INTEL);
+EXPORT_SYMBOL_NS(sdw_intel_cnl_hw_ops, "SOUNDWIRE_INTEL");
diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c
index a005b63582e9..e305c6258ca9 100644
--- a/drivers/soundwire/intel_ace2x.c
+++ b/drivers/soundwire/intel_ace2x.c
@@ -754,6 +754,6 @@ const struct sdw_intel_hw_ops sdw_intel_lnl_hw_ops = {
.program_sdi = intel_program_sdi,
};
-EXPORT_SYMBOL_NS(sdw_intel_lnl_hw_ops, SOUNDWIRE_INTEL);
+EXPORT_SYMBOL_NS(sdw_intel_lnl_hw_ops, "SOUNDWIRE_INTEL");
-MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK);
+MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK");
diff --git a/drivers/soundwire/intel_init.c b/drivers/soundwire/intel_init.c
index 12e7a98f319f..5f53666514a4 100644
--- a/drivers/soundwire/intel_init.c
+++ b/drivers/soundwire/intel_init.c
@@ -149,7 +149,7 @@ irqreturn_t sdw_intel_thread(int irq, void *dev_id)
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS(sdw_intel_thread, SOUNDWIRE_INTEL_INIT);
+EXPORT_SYMBOL_NS(sdw_intel_thread, "SOUNDWIRE_INTEL_INIT");
static struct sdw_intel_ctx
*sdw_intel_probe_controller(struct sdw_intel_res *res)
@@ -334,7 +334,7 @@ struct sdw_intel_ctx
{
return sdw_intel_probe_controller(res);
}
-EXPORT_SYMBOL_NS(sdw_intel_probe, SOUNDWIRE_INTEL_INIT);
+EXPORT_SYMBOL_NS(sdw_intel_probe, "SOUNDWIRE_INTEL_INIT");
/**
* sdw_intel_startup() - SoundWire Intel startup
@@ -347,7 +347,7 @@ int sdw_intel_startup(struct sdw_intel_ctx *ctx)
{
return sdw_intel_startup_controller(ctx);
}
-EXPORT_SYMBOL_NS(sdw_intel_startup, SOUNDWIRE_INTEL_INIT);
+EXPORT_SYMBOL_NS(sdw_intel_startup, "SOUNDWIRE_INTEL_INIT");
/**
* sdw_intel_exit() - SoundWire Intel exit
* @ctx: SoundWire context allocated in the probe
@@ -374,7 +374,7 @@ void sdw_intel_exit(struct sdw_intel_ctx *ctx)
kfree(ctx->ldev);
kfree(ctx);
}
-EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT);
+EXPORT_SYMBOL_NS(sdw_intel_exit, "SOUNDWIRE_INTEL_INIT");
void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx)
{
@@ -397,7 +397,7 @@ void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx)
intel_link_process_wakeen_event(&ldev->auxdev);
}
}
-EXPORT_SYMBOL_NS(sdw_intel_process_wakeen_event, SOUNDWIRE_INTEL_INIT);
+EXPORT_SYMBOL_NS(sdw_intel_process_wakeen_event, "SOUNDWIRE_INTEL_INIT");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("Intel Soundwire Init Library");
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index 2b403b14066c..e00c5ac496a6 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -1779,7 +1779,7 @@ MODULE_DEVICE_TABLE(of, qcom_swrm_of_match);
static struct platform_driver qcom_swrm_driver = {
.probe = &qcom_swrm_probe,
- .remove_new = qcom_swrm_remove,
+ .remove = qcom_swrm_remove,
.driver = {
.name = "qcom-soundwire",
.of_match_table = qcom_swrm_of_match,
diff --git a/drivers/soundwire/slave.c b/drivers/soundwire/slave.c
index 97cf8bcca047..4869b073b11c 100644
--- a/drivers/soundwire/slave.c
+++ b/drivers/soundwire/slave.c
@@ -272,4 +272,4 @@ int sdw_of_find_slaves(struct sdw_bus *bus)
return 0;
}
-MODULE_IMPORT_NS(SND_SOC_SDCA);
+MODULE_IMPORT_NS("SND_SOC_SDCA");
diff --git a/drivers/spi/spi-apple.c b/drivers/spi/spi-apple.c
index d4b126c8701a..6273352a2b28 100644
--- a/drivers/spi/spi-apple.c
+++ b/drivers/spi/spi-apple.c
@@ -493,6 +493,7 @@ static int apple_spi_probe(struct platform_device *pdev)
ctlr->prepare_message = apple_spi_prepare_message;
ctlr->set_cs = apple_spi_set_cs;
ctlr->transfer_one = apple_spi_transfer_one;
+ ctlr->use_gpio_descriptors = true;
ctlr->auto_runtime_pm = true;
pm_runtime_set_active(&pdev->dev);
diff --git a/drivers/spi/spi-aspeed-smc.c b/drivers/spi/spi-aspeed-smc.c
index 8eb843ddb25f..e9beae95dded 100644
--- a/drivers/spi/spi-aspeed-smc.c
+++ b/drivers/spi/spi-aspeed-smc.c
@@ -239,7 +239,7 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip,
ret = aspeed_spi_send_cmd_addr(chip, op->addr.nbytes, offset, op->cmd.opcode);
if (ret < 0)
- return ret;
+ goto stop_user;
if (op->dummy.buswidth && op->dummy.nbytes) {
for (i = 0; i < op->dummy.nbytes / op->dummy.buswidth; i++)
@@ -249,8 +249,9 @@ static ssize_t aspeed_spi_read_user(struct aspeed_spi_chip *chip,
aspeed_spi_set_io_mode(chip, io_mode);
aspeed_spi_read_from_ahb(buf, chip->ahb_base, len);
+stop_user:
aspeed_spi_stop_user(chip);
- return 0;
+ return ret;
}
static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip,
@@ -261,10 +262,11 @@ static ssize_t aspeed_spi_write_user(struct aspeed_spi_chip *chip,
aspeed_spi_start_user(chip);
ret = aspeed_spi_send_cmd_addr(chip, op->addr.nbytes, op->addr.val, op->cmd.opcode);
if (ret < 0)
- return ret;
+ goto stop_user;
aspeed_spi_write_to_ahb(chip->ahb_base, op->data.buf.out, op->data.nbytes);
+stop_user:
aspeed_spi_stop_user(chip);
- return 0;
+ return ret;
}
/* support for 1-1-1, 1-1-2 or 1-1-4 */
diff --git a/drivers/spi/spi-cadence-quadspi.c b/drivers/spi/spi-cadence-quadspi.c
index 0b45b7b2b3ab..a031ecb358e0 100644
--- a/drivers/spi/spi-cadence-quadspi.c
+++ b/drivers/spi/spi-cadence-quadspi.c
@@ -43,6 +43,7 @@ static_assert(CQSPI_MAX_CHIPSELECT <= SPI_CS_CNT_MAX);
#define CQSPI_SLOW_SRAM BIT(4)
#define CQSPI_NEEDS_APB_AHB_HAZARD_WAR BIT(5)
#define CQSPI_RD_NO_IRQ BIT(6)
+#define CQSPI_DISABLE_STIG_MODE BIT(7)
/* Capabilities */
#define CQSPI_SUPPORTS_OCTAL BIT(0)
@@ -103,6 +104,7 @@ struct cqspi_st {
bool apb_ahb_hazard;
bool is_jh7110; /* Flag for StarFive JH7110 SoC */
+ bool disable_stig_mode;
const struct cqspi_driver_platdata *ddata;
};
@@ -1416,7 +1418,8 @@ static int cqspi_mem_process(struct spi_mem *mem, const struct spi_mem_op *op)
* reads, prefer STIG mode for such small reads.
*/
if (!op->addr.nbytes ||
- op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX)
+ (op->data.nbytes <= CQSPI_STIG_DATA_LEN_MAX &&
+ !cqspi->disable_stig_mode))
return cqspi_command_read(f_pdata, op);
return cqspi_read(f_pdata, op);
@@ -1880,6 +1883,8 @@ static int cqspi_probe(struct platform_device *pdev)
if (ret)
goto probe_reset_failed;
}
+ if (ddata->quirks & CQSPI_DISABLE_STIG_MODE)
+ cqspi->disable_stig_mode = true;
if (of_device_is_compatible(pdev->dev.of_node,
"xlnx,versal-ospi-1.0")) {
@@ -2043,7 +2048,8 @@ static const struct cqspi_driver_platdata intel_lgm_qspi = {
static const struct cqspi_driver_platdata socfpga_qspi = {
.quirks = CQSPI_DISABLE_DAC_MODE
| CQSPI_NO_SUPPORT_WR_COMPLETION
- | CQSPI_SLOW_SRAM,
+ | CQSPI_SLOW_SRAM
+ | CQSPI_DISABLE_STIG_MODE,
};
static const struct cqspi_driver_platdata versal_ospi = {
diff --git a/drivers/spi/spi-cs42l43.c b/drivers/spi/spi-cs42l43.c
index d0b55a26c31b..ceefc253c549 100644
--- a/drivers/spi/spi-cs42l43.c
+++ b/drivers/spi/spi-cs42l43.c
@@ -462,7 +462,7 @@ static struct platform_driver cs42l43_spi_driver = {
};
module_platform_driver(cs42l43_spi_driver);
-MODULE_IMPORT_NS(GPIO_SWNODE);
+MODULE_IMPORT_NS("GPIO_SWNODE");
MODULE_DESCRIPTION("CS42L43 SPI Driver");
MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
MODULE_AUTHOR("Maciej Strozek <mstrozek@opensource.cirrus.com>");
diff --git a/drivers/spi/spi-dw-bt1.c b/drivers/spi/spi-dw-bt1.c
index abe6410f0e99..4a5be813efa7 100644
--- a/drivers/spi/spi-dw-bt1.c
+++ b/drivers/spi/spi-dw-bt1.c
@@ -328,4 +328,4 @@ module_platform_driver(dw_spi_bt1_driver);
MODULE_AUTHOR("Serge Semin <Sergey.Semin@baikalelectronics.ru>");
MODULE_DESCRIPTION("Baikal-T1 System Boot SPI Controller driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SPI_DW_CORE);
+MODULE_IMPORT_NS("SPI_DW_CORE");
diff --git a/drivers/spi/spi-dw-core.c b/drivers/spi/spi-dw-core.c
index 431788dd848c..ea517af9435f 100644
--- a/drivers/spi/spi-dw-core.c
+++ b/drivers/spi/spi-dw-core.c
@@ -104,7 +104,7 @@ void dw_spi_set_cs(struct spi_device *spi, bool enable)
else
dw_writel(dws, DW_SPI_SER, 0);
}
-EXPORT_SYMBOL_NS_GPL(dw_spi_set_cs, SPI_DW_CORE);
+EXPORT_SYMBOL_NS_GPL(dw_spi_set_cs, "SPI_DW_CORE");
/* Return the max entries we can fill into tx fifo */
static inline u32 dw_spi_tx_max(struct dw_spi *dws)
@@ -208,7 +208,7 @@ int dw_spi_check_status(struct dw_spi *dws, bool raw)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(dw_spi_check_status, SPI_DW_CORE);
+EXPORT_SYMBOL_NS_GPL(dw_spi_check_status, "SPI_DW_CORE");
static irqreturn_t dw_spi_transfer_handler(struct dw_spi *dws)
{
@@ -351,7 +351,7 @@ void dw_spi_update_config(struct dw_spi *dws, struct spi_device *spi,
dws->cur_rx_sample_dly = chip->rx_sample_dly;
}
}
-EXPORT_SYMBOL_NS_GPL(dw_spi_update_config, SPI_DW_CORE);
+EXPORT_SYMBOL_NS_GPL(dw_spi_update_config, "SPI_DW_CORE");
static void dw_spi_irq_setup(struct dw_spi *dws)
{
@@ -982,7 +982,7 @@ err_free_host:
spi_controller_put(host);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(dw_spi_add_host, SPI_DW_CORE);
+EXPORT_SYMBOL_NS_GPL(dw_spi_add_host, "SPI_DW_CORE");
void dw_spi_remove_host(struct dw_spi *dws)
{
@@ -997,7 +997,7 @@ void dw_spi_remove_host(struct dw_spi *dws)
free_irq(dws->irq, dws->host);
}
-EXPORT_SYMBOL_NS_GPL(dw_spi_remove_host, SPI_DW_CORE);
+EXPORT_SYMBOL_NS_GPL(dw_spi_remove_host, "SPI_DW_CORE");
int dw_spi_suspend_host(struct dw_spi *dws)
{
@@ -1010,14 +1010,14 @@ int dw_spi_suspend_host(struct dw_spi *dws)
dw_spi_shutdown_chip(dws);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(dw_spi_suspend_host, SPI_DW_CORE);
+EXPORT_SYMBOL_NS_GPL(dw_spi_suspend_host, "SPI_DW_CORE");
int dw_spi_resume_host(struct dw_spi *dws)
{
dw_spi_hw_init(&dws->host->dev, dws);
return spi_controller_resume(dws->host);
}
-EXPORT_SYMBOL_NS_GPL(dw_spi_resume_host, SPI_DW_CORE);
+EXPORT_SYMBOL_NS_GPL(dw_spi_resume_host, "SPI_DW_CORE");
MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
MODULE_DESCRIPTION("Driver for DesignWare SPI controller core");
diff --git a/drivers/spi/spi-dw-dma.c b/drivers/spi/spi-dw-dma.c
index f4c209e5f52b..b5bed02b7e50 100644
--- a/drivers/spi/spi-dw-dma.c
+++ b/drivers/spi/spi-dw-dma.c
@@ -693,7 +693,7 @@ void dw_spi_dma_setup_mfld(struct dw_spi *dws)
{
dws->dma_ops = &dw_spi_dma_mfld_ops;
}
-EXPORT_SYMBOL_NS_GPL(dw_spi_dma_setup_mfld, SPI_DW_CORE);
+EXPORT_SYMBOL_NS_GPL(dw_spi_dma_setup_mfld, "SPI_DW_CORE");
static const struct dw_spi_dma_ops dw_spi_dma_generic_ops = {
.dma_init = dw_spi_dma_init_generic,
@@ -708,4 +708,4 @@ void dw_spi_dma_setup_generic(struct dw_spi *dws)
{
dws->dma_ops = &dw_spi_dma_generic_ops;
}
-EXPORT_SYMBOL_NS_GPL(dw_spi_dma_setup_generic, SPI_DW_CORE);
+EXPORT_SYMBOL_NS_GPL(dw_spi_dma_setup_generic, "SPI_DW_CORE");
diff --git a/drivers/spi/spi-dw-mmio.c b/drivers/spi/spi-dw-mmio.c
index 863040cf5db7..f0f576fac77a 100644
--- a/drivers/spi/spi-dw-mmio.c
+++ b/drivers/spi/spi-dw-mmio.c
@@ -445,4 +445,4 @@ module_platform_driver(dw_spi_mmio_driver);
MODULE_AUTHOR("Jean-Hugues Deschenes <jean-hugues.deschenes@octasic.com>");
MODULE_DESCRIPTION("Memory-mapped I/O interface driver for DW SPI Core");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SPI_DW_CORE);
+MODULE_IMPORT_NS("SPI_DW_CORE");
diff --git a/drivers/spi/spi-dw-pci.c b/drivers/spi/spi-dw-pci.c
index 6b8cc26e06f8..b32d6648a32e 100644
--- a/drivers/spi/spi-dw-pci.c
+++ b/drivers/spi/spi-dw-pci.c
@@ -211,4 +211,4 @@ module_pci_driver(dw_spi_pci_driver);
MODULE_AUTHOR("Feng Tang <feng.tang@intel.com>");
MODULE_DESCRIPTION("PCI interface driver for DW SPI Core");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SPI_DW_CORE);
+MODULE_IMPORT_NS("SPI_DW_CORE");
diff --git a/drivers/spi/spi-intel-pci.c b/drivers/spi/spi-intel-pci.c
index c3b54928143d..4d9ffec900bb 100644
--- a/drivers/spi/spi-intel-pci.c
+++ b/drivers/spi/spi-intel-pci.c
@@ -86,6 +86,8 @@ static const struct pci_device_id intel_spi_pci_ids[] = {
{ PCI_VDEVICE(INTEL, 0xa324), (unsigned long)&cnl_info },
{ PCI_VDEVICE(INTEL, 0xa3a4), (unsigned long)&cnl_info },
{ PCI_VDEVICE(INTEL, 0xa823), (unsigned long)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0xe323), (unsigned long)&cnl_info },
+ { PCI_VDEVICE(INTEL, 0xe423), (unsigned long)&cnl_info },
{ },
};
MODULE_DEVICE_TABLE(pci, intel_spi_pci_ids);
diff --git a/drivers/spi/spi-ljca.c b/drivers/spi/spi-ljca.c
index 1cc1422ddba0..2cab79ad2b98 100644
--- a/drivers/spi/spi-ljca.c
+++ b/drivers/spi/spi-ljca.c
@@ -294,4 +294,4 @@ MODULE_AUTHOR("Zhifeng Wang <zhifeng.wang@intel.com>");
MODULE_AUTHOR("Lixu Zhang <lixu.zhang@intel.com>");
MODULE_DESCRIPTION("Intel La Jolla Cove Adapter USB-SPI driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(LJCA);
+MODULE_IMPORT_NS("LJCA");
diff --git a/drivers/spi/spi-loongson-core.c b/drivers/spi/spi-loongson-core.c
index f97800b6fd65..4fec226456d1 100644
--- a/drivers/spi/spi-loongson-core.c
+++ b/drivers/spi/spi-loongson-core.c
@@ -227,7 +227,7 @@ int loongson_spi_init_controller(struct device *dev, void __iomem *regs)
return devm_spi_register_controller(dev, controller);
}
-EXPORT_SYMBOL_NS_GPL(loongson_spi_init_controller, SPI_LOONGSON_CORE);
+EXPORT_SYMBOL_NS_GPL(loongson_spi_init_controller, "SPI_LOONGSON_CORE");
static int __maybe_unused loongson_spi_suspend(struct device *dev)
{
@@ -273,7 +273,7 @@ const struct dev_pm_ops loongson_spi_dev_pm_ops = {
.suspend = loongson_spi_suspend,
.resume = loongson_spi_resume,
};
-EXPORT_SYMBOL_NS_GPL(loongson_spi_dev_pm_ops, SPI_LOONGSON_CORE);
+EXPORT_SYMBOL_NS_GPL(loongson_spi_dev_pm_ops, "SPI_LOONGSON_CORE");
MODULE_DESCRIPTION("Loongson SPI core driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/spi/spi-loongson-pci.c b/drivers/spi/spi-loongson-pci.c
index 892cf1eba1cf..cbcde153260e 100644
--- a/drivers/spi/spi-loongson-pci.c
+++ b/drivers/spi/spi-loongson-pci.c
@@ -51,4 +51,4 @@ module_pci_driver(loongson_spi_pci_driver);
MODULE_DESCRIPTION("Loongson spi pci driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SPI_LOONGSON_CORE);
+MODULE_IMPORT_NS("SPI_LOONGSON_CORE");
diff --git a/drivers/spi/spi-loongson-plat.c b/drivers/spi/spi-loongson-plat.c
index c066e5f5891e..64a7270f9a64 100644
--- a/drivers/spi/spi-loongson-plat.c
+++ b/drivers/spi/spi-loongson-plat.c
@@ -44,4 +44,4 @@ module_platform_driver(loongson_spi_plat_driver);
MODULE_DESCRIPTION("Loongson spi platform driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SPI_LOONGSON_CORE);
+MODULE_IMPORT_NS("SPI_LOONGSON_CORE");
diff --git a/drivers/spi/spi-mpc52xx.c b/drivers/spi/spi-mpc52xx.c
index 036bfb7bf189..6d4dde15ac54 100644
--- a/drivers/spi/spi-mpc52xx.c
+++ b/drivers/spi/spi-mpc52xx.c
@@ -520,6 +520,7 @@ static void mpc52xx_spi_remove(struct platform_device *op)
struct mpc52xx_spi *ms = spi_controller_get_devdata(host);
int i;
+ cancel_work_sync(&ms->work);
free_irq(ms->irq0, ms);
free_irq(ms->irq1, ms);
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index e2400a067a95..add6247d3481 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -1561,10 +1561,10 @@ static int omap2_mcspi_probe(struct platform_device *pdev)
}
mcspi->ref_clk = devm_clk_get_optional_enabled(&pdev->dev, NULL);
- if (mcspi->ref_clk)
- mcspi->ref_clk_hz = clk_get_rate(mcspi->ref_clk);
- else
+ if (IS_ERR(mcspi->ref_clk))
mcspi->ref_clk_hz = OMAP2_MCSPI_MAX_FREQ;
+ else
+ mcspi->ref_clk_hz = clk_get_rate(mcspi->ref_clk);
ctlr->max_speed_hz = mcspi->ref_clk_hz;
ctlr->min_speed_hz = mcspi->ref_clk_hz >> 15;
diff --git a/drivers/spi/spi-pxa2xx-pci.c b/drivers/spi/spi-pxa2xx-pci.c
index e51c1b492283..cae77ac18520 100644
--- a/drivers/spi/spi-pxa2xx-pci.c
+++ b/drivers/spi/spi-pxa2xx-pci.c
@@ -346,5 +346,5 @@ module_pci_driver(pxa2xx_spi_pci_driver);
MODULE_DESCRIPTION("CE4100/LPSS PCI-SPI glue code for PXA's driver");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SPI_PXA2xx);
+MODULE_IMPORT_NS("SPI_PXA2xx");
MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff --git a/drivers/spi/spi-pxa2xx-platform.c b/drivers/spi/spi-pxa2xx-platform.c
index b88b7de7a005..45e159e75a52 100644
--- a/drivers/spi/spi-pxa2xx-platform.c
+++ b/drivers/spi/spi-pxa2xx-platform.c
@@ -225,6 +225,6 @@ module_exit(pxa2xx_spi_exit);
MODULE_AUTHOR("Stephen Street");
MODULE_DESCRIPTION("PXA2xx SSP SPI Controller platform driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SPI_PXA2xx);
+MODULE_IMPORT_NS("SPI_PXA2xx");
MODULE_ALIAS("platform:pxa2xx-spi");
MODULE_SOFTDEP("pre: dw_dmac");
diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index bf1f34b0ffc8..903d76145272 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -1468,7 +1468,7 @@ out_error_dma_irq_alloc:
return status;
}
-EXPORT_SYMBOL_NS_GPL(pxa2xx_spi_probe, SPI_PXA2xx);
+EXPORT_SYMBOL_NS_GPL(pxa2xx_spi_probe, "SPI_PXA2xx");
void pxa2xx_spi_remove(struct device *dev)
{
@@ -1488,7 +1488,7 @@ void pxa2xx_spi_remove(struct device *dev)
/* Release IRQ */
free_irq(ssp->irq, drv_data);
}
-EXPORT_SYMBOL_NS_GPL(pxa2xx_spi_remove, SPI_PXA2xx);
+EXPORT_SYMBOL_NS_GPL(pxa2xx_spi_remove, "SPI_PXA2xx");
static int pxa2xx_spi_suspend(struct device *dev)
{
diff --git a/drivers/spi/spi-rockchip-sfc.c b/drivers/spi/spi-rockchip-sfc.c
index 69d0f2175568..70bbb459caa4 100644
--- a/drivers/spi/spi-rockchip-sfc.c
+++ b/drivers/spi/spi-rockchip-sfc.c
@@ -182,6 +182,7 @@ struct rockchip_sfc {
bool use_dma;
u32 max_iosize;
u16 version;
+ struct spi_controller *host;
};
static int rockchip_sfc_reset(struct rockchip_sfc *sfc)
@@ -574,6 +575,7 @@ static int rockchip_sfc_probe(struct platform_device *pdev)
sfc = spi_controller_get_devdata(host);
sfc->dev = dev;
+ sfc->host = host;
sfc->regbase = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(sfc->regbase))
@@ -651,8 +653,8 @@ err_hclk:
static void rockchip_sfc_remove(struct platform_device *pdev)
{
- struct spi_controller *host = platform_get_drvdata(pdev);
struct rockchip_sfc *sfc = platform_get_drvdata(pdev);
+ struct spi_controller *host = sfc->host;
spi_unregister_controller(host);
diff --git a/drivers/spi/spi-rockchip.c b/drivers/spi/spi-rockchip.c
index 864e58167417..1bc012fce7cb 100644
--- a/drivers/spi/spi-rockchip.c
+++ b/drivers/spi/spi-rockchip.c
@@ -241,6 +241,20 @@ static void rockchip_spi_set_cs(struct spi_device *spi, bool enable)
struct spi_controller *ctlr = spi->controller;
struct rockchip_spi *rs = spi_controller_get_devdata(ctlr);
bool cs_asserted = spi->mode & SPI_CS_HIGH ? enable : !enable;
+ bool cs_actual;
+
+ /*
+ * SPI subsystem tries to avoid no-op calls that would break the PM
+ * refcount below. It can't however for the first time it is used.
+ * To detect this case we read it here and bail out early for no-ops.
+ */
+ if (spi_get_csgpiod(spi, 0))
+ cs_actual = !!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) & 1);
+ else
+ cs_actual = !!(readl_relaxed(rs->regs + ROCKCHIP_SPI_SER) &
+ BIT(spi_get_chipselect(spi, 0)));
+ if (unlikely(cs_actual == cs_asserted))
+ return;
if (cs_asserted) {
/* Keep things powered as long as CS is asserted */
diff --git a/drivers/spmi/spmi-mtk-pmif.c b/drivers/spmi/spmi-mtk-pmif.c
index 5079442f8ea1..160d36f7d238 100644
--- a/drivers/spmi/spmi-mtk-pmif.c
+++ b/drivers/spmi/spmi-mtk-pmif.c
@@ -545,7 +545,7 @@ static struct platform_driver mtk_spmi_driver = {
.of_match_table = mtk_spmi_match_table,
},
.probe = mtk_spmi_probe,
- .remove_new = mtk_spmi_remove,
+ .remove = mtk_spmi_remove,
};
module_platform_driver(mtk_spmi_driver);
diff --git a/drivers/spmi/spmi-pmic-arb.c b/drivers/spmi/spmi-pmic-arb.c
index 9ba9495fcc4b..5c058db21821 100644
--- a/drivers/spmi/spmi-pmic-arb.c
+++ b/drivers/spmi/spmi-pmic-arb.c
@@ -1763,14 +1763,13 @@ static int spmi_pmic_arb_register_buses(struct spmi_pmic_arb *pmic_arb,
{
struct device *dev = &pdev->dev;
struct device_node *node = dev->of_node;
- struct device_node *child;
int ret;
/* legacy mode doesn't provide child node for the bus */
if (of_device_is_compatible(node, "qcom,spmi-pmic-arb"))
return spmi_pmic_arb_bus_init(pdev, node, pmic_arb);
- for_each_available_child_of_node(node, child) {
+ for_each_available_child_of_node_scoped(node, child) {
if (of_node_name_eq(child, "spmi")) {
ret = spmi_pmic_arb_bus_init(pdev, child, pmic_arb);
if (ret)
@@ -1882,7 +1881,7 @@ MODULE_DEVICE_TABLE(of, spmi_pmic_arb_match_table);
static struct platform_driver spmi_pmic_arb_driver = {
.probe = spmi_pmic_arb_probe,
- .remove_new = spmi_pmic_arb_remove,
+ .remove = spmi_pmic_arb_remove,
.driver = {
.name = "spmi_pmic_arb",
.of_match_table = spmi_pmic_arb_match_table,
diff --git a/drivers/staging/Kconfig b/drivers/staging/Kconfig
index fcdd559a8acf..075e775d3868 100644
--- a/drivers/staging/Kconfig
+++ b/drivers/staging/Kconfig
@@ -24,20 +24,10 @@ menuconfig STAGING
if STAGING
-source "drivers/staging/olpc_dcon/Kconfig"
-
source "drivers/staging/rtl8723bs/Kconfig"
-source "drivers/staging/rtl8712/Kconfig"
-
-source "drivers/staging/rts5208/Kconfig"
-
source "drivers/staging/octeon/Kconfig"
-source "drivers/staging/vt6655/Kconfig"
-
-source "drivers/staging/vt6656/Kconfig"
-
source "drivers/staging/iio/Kconfig"
source "drivers/staging/sm750fb/Kconfig"
@@ -46,8 +36,6 @@ source "drivers/staging/nvec/Kconfig"
source "drivers/staging/media/Kconfig"
-source "drivers/staging/gdm724x/Kconfig"
-
source "drivers/staging/fbtft/Kconfig"
source "drivers/staging/most/Kconfig"
@@ -58,8 +46,8 @@ source "drivers/staging/vc04_services/Kconfig"
source "drivers/staging/axis-fifo/Kconfig"
-source "drivers/staging/fieldbus/Kconfig"
-
source "drivers/staging/vme_user/Kconfig"
+source "drivers/staging/gpib/Kconfig"
+
endif # STAGING
diff --git a/drivers/staging/Makefile b/drivers/staging/Makefile
index 4a84c4848664..e681e403509c 100644
--- a/drivers/staging/Makefile
+++ b/drivers/staging/Makefile
@@ -2,21 +2,15 @@
# Makefile for staging directory
obj-y += media/
-obj-$(CONFIG_FB_OLPC_DCON) += olpc_dcon/
obj-$(CONFIG_RTL8723BS) += rtl8723bs/
-obj-$(CONFIG_R8712U) += rtl8712/
-obj-$(CONFIG_RTS5208) += rts5208/
obj-$(CONFIG_OCTEON_ETHERNET) += octeon/
-obj-$(CONFIG_VT6655) += vt6655/
-obj-$(CONFIG_VT6656) += vt6656/
obj-$(CONFIG_VME_BUS) += vme_user/
obj-$(CONFIG_IIO) += iio/
obj-$(CONFIG_FB_SM750) += sm750fb/
obj-$(CONFIG_MFD_NVEC) += nvec/
-obj-$(CONFIG_LTE_GDM724X) += gdm724x/
obj-$(CONFIG_FB_TFT) += fbtft/
obj-$(CONFIG_MOST) += most/
obj-$(CONFIG_GREYBUS) += greybus/
obj-$(CONFIG_BCM2835_VCHIQ) += vc04_services/
obj-$(CONFIG_XIL_AXIS_FIFO) += axis-fifo/
-obj-$(CONFIG_FIELDBUS_DEV) += fieldbus/
+obj-$(CONFIG_GPIB) += gpib/
diff --git a/drivers/staging/axis-fifo/axis-fifo.c b/drivers/staging/axis-fifo/axis-fifo.c
index 1bbb9a6db597..7540c20090c7 100644
--- a/drivers/staging/axis-fifo/axis-fifo.c
+++ b/drivers/staging/axis-fifo/axis-fifo.c
@@ -919,7 +919,7 @@ static struct platform_driver axis_fifo_driver = {
.of_match_table = axis_fifo_of_match,
},
.probe = axis_fifo_probe,
- .remove_new = axis_fifo_remove,
+ .remove = axis_fifo_remove,
};
static int __init axis_fifo_init(void)
diff --git a/drivers/staging/fbtft/Kconfig b/drivers/staging/fbtft/Kconfig
index 77ab44362f16..dcf6a70455cc 100644
--- a/drivers/staging/fbtft/Kconfig
+++ b/drivers/staging/fbtft/Kconfig
@@ -3,6 +3,7 @@ menuconfig FB_TFT
tristate "Support for small TFT LCD display modules"
depends on FB && SPI
depends on FB_DEVICE
+ depends on BACKLIGHT_CLASS_DEVICE
depends on GPIOLIB || COMPILE_TEST
select FB_BACKLIGHT
select FB_SYSMEM_HELPERS_DEFERRED
diff --git a/drivers/staging/fbtft/fbtft.h b/drivers/staging/fbtft/fbtft.h
index 3e00a26a29d5..317be17b95c1 100644
--- a/drivers/staging/fbtft/fbtft.h
+++ b/drivers/staging/fbtft/fbtft.h
@@ -330,7 +330,7 @@ static struct platform_driver fbtft_driver_platform_driver = { \
.of_match_table = dt_ids, \
}, \
.probe = fbtft_driver_probe_pdev, \
- .remove_new = fbtft_driver_remove_pdev, \
+ .remove = fbtft_driver_remove_pdev, \
}; \
\
static int __init fbtft_driver_module_init(void) \
diff --git a/drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev b/drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev
deleted file mode 100644
index 45f631ea32a6..000000000000
--- a/drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev
+++ /dev/null
@@ -1,31 +0,0 @@
-What: /dev/fieldbus_devX
-Date: December 2018
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- The cdev interface to drivers for Fieldbus Device Memory
- (aka. Process Memory).
-
- The following file operations are supported:
-
- open(2)
- Create an I/O context associated with the file descriptor.
-
- read(2)
- Read from Process Memory's "read area".
- Clears POLLERR | POLLPRI from the file descriptor.
-
- write(2)
- Write to Process Memory's "write area".
-
- poll(2), select(2), epoll_wait(2) etc.
- When a "Process Memory Read Area Changed" event occurs,
- POLLERR | POLLPRI will be set on the file descriptor.
- Note that POLLIN | POLLOUT events are always set, because the
- process memory area is always readable and writable.
-
- close(2)
- Free up the I/O context that was associated
- with the file descriptor.
-
-Users: TBD
diff --git a/drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev b/drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev
deleted file mode 100644
index 439f14d33c3b..000000000000
--- a/drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev
+++ /dev/null
@@ -1,62 +0,0 @@
-What: /sys/class/fieldbus_dev/fieldbus_devX/card_name
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- Human-readable name of the Fieldbus Device.
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/fieldbus_type
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- The type of fieldbus implemented by this device.
- Possible values:
- 'unknown'
- 'profinet'
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/fieldbus_id
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- The unique fieldbus id associated with this device.
- The exact format of this id is fieldbus type dependent, e.g.
- a mac address for profinet.
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/read_area_size
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- The size, in bytes, of the Process Memory read area.
- Note: this area is accessible by reading from the associated
- character device (/dev/fieldbus_devX).
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/write_area_size
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- The size, in bytes, of the Process Memory write area.
- Note: this area is accessible by writing to the associated
- character device (/dev/fieldbus_devX)
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/online
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- Whether the fieldbus is online or offline.
- Possible values:
- '1' meaning 'online'
- '0' meaning 'offline'
- Note: an uevent is generated when this property changes.
-
-What: /sys/class/fieldbus_dev/fieldbus_devX/enabled
-KernelVersion: 5.1 (staging)
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
-Description:
- Whether the device is enabled (power on) or
- disabled (power off).
- Possible values:
- '1' meaning enabled
- '0' meaning disabled
- Normally a r/o property, but optionally r/w:
- Writing '1' enables the device (power on) with default
- settings.
- Writing '0' disables the card (power off).
diff --git a/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt b/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt
deleted file mode 100644
index f34a95611645..000000000000
--- a/drivers/staging/fieldbus/Documentation/devicetree/bindings/fieldbus/arcx,anybus-controller.txt
+++ /dev/null
@@ -1,71 +0,0 @@
-* Arcx Anybus-S controller
-
-This chip communicates with the SoC over a parallel bus. It is
-expected that its Device Tree node is specified as the child of a node
-corresponding to the parallel bus used for communication.
-
-Required properties:
---------------------
-
- - compatible : The following chip-specific string:
- "arcx,anybus-controller"
-
- - reg : three areas:
- index 0: bus memory area where the cpld registers are located.
- index 1: bus memory area of the first host's dual-port ram.
- index 2: bus memory area of the second host's dual-port ram.
-
- - reset-gpios : the GPIO pin connected to the reset line of the controller.
-
- - interrupts : two interrupts:
- index 0: interrupt connected to the first host
- index 1: interrupt connected to the second host
- Generic interrupt client node bindings are described in
- interrupt-controller/interrupts.txt
-
-Optional: use of subnodes
--------------------------
-
-The card connected to a host may need additional properties. These can be
-specified in subnodes to the controller node.
-
-The subnodes are identified by the standard 'reg' property. Which information
-exactly can be specified depends on the bindings for the function driver
-for the subnode.
-
-Required controller node properties when using subnodes:
-- #address-cells: should be one.
-- #size-cells: should be zero.
-
-Required subnode properties:
-- reg: Must contain the host index of the card this subnode describes:
- <0> for the first host on the controller
- <1> for the second host on the controller
- Note that only a single card can be plugged into a host, so the host
- index uniquely describes the card location.
-
-Example of usage:
------------------
-
-This example places the bridge on top of the i.MX WEIM parallel bus, see:
-Documentation/devicetree/bindings/memory-controllers/fsl/fsl,imx-weim.yaml
-
-&weim {
- controller@0,0 {
- compatible = "arcx,anybus-controller";
- reg = <0 0 0x100>, <0 0x400000 0x800>, <1 0x400000 0x800>;
- reset-gpios = <&gpio5 2 GPIO_ACTIVE_HIGH>;
- interrupt-parent = <&gpio1>;
- interrupts = <1 IRQ_TYPE_LEVEL_LOW>, <5 IRQ_TYPE_LEVEL_LOW>;
- /* fsl,weim-cs-timing is a i.MX WEIM bus specific property */
- fsl,weim-cs-timing = <0x024400b1 0x00001010 0x20081100
- 0x00000000 0xa0000240 0x00000000>;
- /* optional subnode for a card plugged into the first host */
- #address-cells = <1>;
- #size-cells = <0>;
- card@0 {
- reg = <0>;
- /* card specific properties go here */
- };
- };
-};
diff --git a/drivers/staging/fieldbus/Documentation/fieldbus_dev.txt b/drivers/staging/fieldbus/Documentation/fieldbus_dev.txt
deleted file mode 100644
index 89fb8e14676f..000000000000
--- a/drivers/staging/fieldbus/Documentation/fieldbus_dev.txt
+++ /dev/null
@@ -1,66 +0,0 @@
- Fieldbus-Device Subsystem
- ============================================
-
-Part 0 - What is a Fieldbus Device ?
-------------------------------------
-
-Fieldbus is the name of a family of industrial computer network protocols used
-for real-time distributed control, standardized as IEC 61158.
-
-A complex automated industrial system -- such as manufacturing assembly line --
-usually needs a distributed control system -- an organized hierarchy of
-controller systems -- to function. In this hierarchy, there is usually a
-Human Machine Interface (HMI) at the top, where an operator can monitor or
-operate the system. This is typically linked to a middle layer of programmable
-logic controllers (PLC) via a non-time-critical communications system
-(e.g. Ethernet). At the bottom of the control chain is the fieldbus that links
-the PLCs to the components that actually do the work, such as sensors,
-actuators, electric motors, console lights, switches, valves and contactors.
-
-(Source: Wikipedia)
-
-A "Fieldbus Device" is such an actuator, motor, console light, switch, ...
-controlled via the Fieldbus by a PLC aka "Fieldbus Controller".
-
-Communication between PLC and device typically happens via process data memory,
-separated into input and output areas. The Fieldbus then cyclically transfers
-the PLC's output area to the device's input area, and vice versa.
-
-Part I - Why do we need this subsystem?
----------------------------------------
-
-Fieldbus device (client) adapters are commercially available. They allow data
-exchange with a PLC aka "Fieldbus Controller" via process data memory.
-
-They are typically used when a Linux device wants to expose itself as an
-actuator, motor, console light, switch, etc. over the fieldbus.
-
-The purpose of this subsystem is:
-a) present a general, standardized, extensible API/ABI to userspace; and
-b) present a convenient interface to drivers.
-
-Part II - How can drivers use the subsystem?
---------------------------------------------
-
-Any driver that wants to register as a Fieldbus Device should allocate and
-populate a 'struct fieldbus_dev' (from include/linux/fieldbus_dev.h).
-Registration then happens by calling fieldbus_dev_register().
-
-Part III - How can userspace use the subsystem?
------------------------------------------------
-
-Fieldbus protocols and adapters are diverse and varied. However, they share
-a limited few common behaviours and properties. This allows us to define
-a simple interface consisting of a character device and a set of sysfs files:
-
-See:
-drivers/staging/fieldbus/Documentation/ABI/sysfs-class-fieldbus-dev
-drivers/staging/fieldbus/Documentation/ABI/fieldbus-dev-cdev
-
-Note that this simple interface does not provide a way to modify adapter
-configuration settings. It is therefore useful only for adapters that get their
-configuration settings some other way, e.g. non-volatile memory on the adapter,
-through the network, ...
-
-At a later phase, this simple interface can easily co-exist with a future
-(netlink-based ?) configuration settings interface.
diff --git a/drivers/staging/fieldbus/Kconfig b/drivers/staging/fieldbus/Kconfig
deleted file mode 100644
index b0b865acccfb..000000000000
--- a/drivers/staging/fieldbus/Kconfig
+++ /dev/null
@@ -1,19 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-menuconfig FIELDBUS_DEV
- tristate "Fieldbus Device Support"
- help
- Support for Fieldbus Device Adapters.
-
- Fieldbus device (client) adapters allow data exchange with a PLC aka.
- "Fieldbus Controller" over a fieldbus (Profinet, FLNet, etc.)
-
- They are typically used when a Linux device wants to expose itself
- as an actuator, motor, console light, switch, etc. over the fieldbus.
-
- This framework is designed to provide a generic interface to Fieldbus
- Devices from both the Linux Kernel and the userspace.
-
- If unsure, say no.
-
-source "drivers/staging/fieldbus/anybuss/Kconfig"
-
diff --git a/drivers/staging/fieldbus/Makefile b/drivers/staging/fieldbus/Makefile
deleted file mode 100644
index bdf645d41344..000000000000
--- a/drivers/staging/fieldbus/Makefile
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for fieldbus_dev drivers.
-#
-
-obj-$(CONFIG_FIELDBUS_DEV) += fieldbus_dev.o anybuss/
-fieldbus_dev-y := dev_core.o
diff --git a/drivers/staging/fieldbus/TODO b/drivers/staging/fieldbus/TODO
deleted file mode 100644
index 6d6626af4ec7..000000000000
--- a/drivers/staging/fieldbus/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-TODO:
--Get more people/drivers to use the Fieldbus userspace ABI. It requires
- verification/sign-off by multiple users.
-
-Contact: Sven Van Asbroeck <TheSven73@gmail.com>
diff --git a/drivers/staging/fieldbus/anybuss/Kconfig b/drivers/staging/fieldbus/anybuss/Kconfig
deleted file mode 100644
index 635a0a7b7dd2..000000000000
--- a/drivers/staging/fieldbus/anybuss/Kconfig
+++ /dev/null
@@ -1,41 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0-only
-config HMS_ANYBUSS_BUS
- tristate "HMS Anybus-S Bus Support"
- select REGMAP
- depends on OF && FIELDBUS_DEV
- help
- Driver for the HMS Industrial Networks Anybus-S bus.
- You can attach a single Anybus-S compatible card to it, which
- typically provides fieldbus and industrial ethernet
- functionality.
-
-if HMS_ANYBUSS_BUS
-
-config ARCX_ANYBUS_CONTROLLER
- tristate "Arcx Anybus-S Controller"
- depends on OF && GPIOLIB && HAS_IOMEM && REGULATOR
- select REGMAP_MMIO
- help
- Select this to get support for the Arcx Anybus controller.
- It connects to the SoC via a parallel memory bus, and
- embeds up to two Anybus-S buses (slots).
- There is also a CAN power readout, unrelated to the Anybus,
- modelled as a regulator.
-
-config HMS_PROFINET
- tristate "HMS Profinet IRT Controller (Anybus-S)"
- depends on FIELDBUS_DEV && HMS_ANYBUSS_BUS
- help
- If you say yes here you get support for the HMS Industrial
- Networks Profinet IRT Controller.
-
- It will be registered with the kernel as a fieldbus_dev,
- so userspace can interact with it via the fieldbus_dev userspace
- interface(s).
-
- This driver can also be built as a module. If so, the module
- will be called hms-profinet.
-
- If unsure, say N.
-
-endif
diff --git a/drivers/staging/fieldbus/anybuss/Makefile b/drivers/staging/fieldbus/anybuss/Makefile
deleted file mode 100644
index 3ad3dcc6be56..000000000000
--- a/drivers/staging/fieldbus/anybuss/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# Makefile for anybuss drivers.
-#
-
-obj-$(CONFIG_HMS_ANYBUSS_BUS) += anybuss_core.o
-anybuss_core-y += host.o
-
-obj-$(CONFIG_ARCX_ANYBUS_CONTROLLER) += arcx-anybus.o
-obj-$(CONFIG_HMS_PROFINET) += hms-profinet.o
diff --git a/drivers/staging/fieldbus/anybuss/anybuss-client.h b/drivers/staging/fieldbus/anybuss/anybuss-client.h
deleted file mode 100644
index c21c4bebfb84..000000000000
--- a/drivers/staging/fieldbus/anybuss/anybuss-client.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Anybus-S client adapter definitions
- *
- * Copyright 2018 Arcx Inc
- */
-
-#ifndef __LINUX_ANYBUSS_CLIENT_H__
-#define __LINUX_ANYBUSS_CLIENT_H__
-
-#include <linux/device.h>
-#include <linux/types.h>
-#include <linux/poll.h>
-
-/* move to <linux/fieldbus_dev.h> when taking this out of staging */
-#include "../fieldbus_dev.h"
-
-struct anybuss_host;
-
-struct anybuss_client {
- struct device dev;
- struct anybuss_host *host;
- __be16 anybus_id;
- /*
- * these can be optionally set by the client to receive event
- * notifications from the host.
- */
- void (*on_area_updated)(struct anybuss_client *client);
- void (*on_online_changed)(struct anybuss_client *client, bool online);
-};
-
-struct anybuss_client_driver {
- struct device_driver driver;
- int (*probe)(struct anybuss_client *adev);
- void (*remove)(struct anybuss_client *adev);
- u16 anybus_id;
-};
-
-int anybuss_client_driver_register(struct anybuss_client_driver *drv);
-void anybuss_client_driver_unregister(struct anybuss_client_driver *drv);
-
-static inline struct anybuss_client *to_anybuss_client(struct device *dev)
-{
- return container_of(dev, struct anybuss_client, dev);
-}
-
-#define to_anybuss_client_driver(__drv) container_of_const(__drv, struct anybuss_client_driver, driver)
-
-static inline void *
-anybuss_get_drvdata(const struct anybuss_client *client)
-{
- return dev_get_drvdata(&client->dev);
-}
-
-static inline void
-anybuss_set_drvdata(struct anybuss_client *client, void *data)
-{
- dev_set_drvdata(&client->dev, data);
-}
-
-int anybuss_set_power(struct anybuss_client *client, bool power_on);
-
-struct anybuss_memcfg {
- u16 input_io;
- u16 input_dpram;
- u16 input_total;
-
- u16 output_io;
- u16 output_dpram;
- u16 output_total;
-
- enum fieldbus_dev_offl_mode offl_mode;
-};
-
-int anybuss_start_init(struct anybuss_client *client,
- const struct anybuss_memcfg *cfg);
-int anybuss_finish_init(struct anybuss_client *client);
-int anybuss_read_fbctrl(struct anybuss_client *client, u16 addr,
- void *buf, size_t count);
-int anybuss_send_msg(struct anybuss_client *client, u16 cmd_num,
- const void *buf, size_t count);
-int anybuss_send_ext(struct anybuss_client *client, u16 cmd_num,
- const void *buf, size_t count);
-int anybuss_recv_msg(struct anybuss_client *client, u16 cmd_num,
- void *buf, size_t count);
-
-/* these help clients make a struct file_operations */
-int anybuss_write_input(struct anybuss_client *client,
- const char __user *buf, size_t size,
- loff_t *offset);
-int anybuss_read_output(struct anybuss_client *client,
- char __user *buf, size_t size,
- loff_t *offset);
-
-#endif /* __LINUX_ANYBUSS_CLIENT_H__ */
diff --git a/drivers/staging/fieldbus/anybuss/anybuss-controller.h b/drivers/staging/fieldbus/anybuss/anybuss-controller.h
deleted file mode 100644
index 02fa0749043b..000000000000
--- a/drivers/staging/fieldbus/anybuss/anybuss-controller.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Anybus-S controller definitions
- *
- * Copyright 2018 Arcx Inc
- */
-
-#ifndef __LINUX_ANYBUSS_CONTROLLER_H__
-#define __LINUX_ANYBUSS_CONTROLLER_H__
-
-#include <linux/device.h>
-#include <linux/regmap.h>
-
-/*
- * To instantiate an Anybus-S host, a controller should provide the following:
- * - a reset function which resets the attached card;
- * - a regmap which provides access to the attached card's dpram;
- * - the irq of the attached card
- */
-/**
- * struct anybuss_ops - Controller resources to instantiate an Anybus-S host
- *
- * @reset: asserts/deasserts the anybus card's reset line.
- * @regmap: provides access to the card's dual-port RAM area.
- * @irq: number of the interrupt connected to the card's interrupt line.
- * @host_idx: for multi-host controllers, the host index:
- * 0 for the first host on the controller, 1 for the second, etc.
- */
-struct anybuss_ops {
- void (*reset)(struct device *dev, bool assert);
- struct regmap *regmap;
- int irq;
- int host_idx;
-};
-
-struct anybuss_host;
-
-struct anybuss_host * __must_check
-anybuss_host_common_probe(struct device *dev,
- const struct anybuss_ops *ops);
-void anybuss_host_common_remove(struct anybuss_host *host);
-
-struct anybuss_host * __must_check
-devm_anybuss_host_common_probe(struct device *dev,
- const struct anybuss_ops *ops);
-
-#endif /* __LINUX_ANYBUSS_CONTROLLER_H__ */
diff --git a/drivers/staging/fieldbus/anybuss/arcx-anybus.c b/drivers/staging/fieldbus/anybuss/arcx-anybus.c
deleted file mode 100644
index fcd3e3722ae0..000000000000
--- a/drivers/staging/fieldbus/anybuss/arcx-anybus.c
+++ /dev/null
@@ -1,379 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Arcx Anybus-S Controller driver
- *
- * Copyright (C) 2018 Arcx Inc
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/gpio/consumer.h>
-#include <linux/io.h>
-#include <linux/of.h>
-#include <linux/delay.h>
-#include <linux/idr.h>
-#include <linux/mutex.h>
-#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/regmap.h>
-
-/* move to <linux/anybuss-controller.h> when taking this out of staging */
-#include "anybuss-controller.h"
-
-#define CPLD_STATUS1 0x80
-#define CPLD_CONTROL 0x80
-#define CPLD_CONTROL_CRST 0x40
-#define CPLD_CONTROL_RST1 0x04
-#define CPLD_CONTROL_RST2 0x80
-#define CPLD_STATUS1_AB 0x02
-#define CPLD_STATUS1_CAN_POWER 0x01
-#define CPLD_DESIGN_LO 0x81
-#define CPLD_DESIGN_HI 0x82
-#define CPLD_CAP 0x83
-#define CPLD_CAP_COMPAT 0x01
-#define CPLD_CAP_SEP_RESETS 0x02
-
-struct controller_priv {
- struct device *class_dev;
- bool common_reset;
- struct gpio_desc *reset_gpiod;
- void __iomem *cpld_base;
- struct mutex ctrl_lock; /* protects CONTROL register */
- u8 control_reg;
- char version[3];
- u16 design_no;
-};
-
-static void do_reset(struct controller_priv *cd, u8 rst_bit, bool reset)
-{
- mutex_lock(&cd->ctrl_lock);
- /*
- * CPLD_CONTROL is write-only, so cache its value in
- * cd->control_reg
- */
- if (reset)
- cd->control_reg &= ~rst_bit;
- else
- cd->control_reg |= rst_bit;
- writeb(cd->control_reg, cd->cpld_base + CPLD_CONTROL);
- /*
- * h/w work-around:
- * the hardware is 'too fast', so a reset followed by an immediate
- * not-reset will _not_ change the anybus reset line in any way,
- * losing the reset. to prevent this from happening, introduce
- * a minimum reset duration.
- * Verified minimum safe duration required using a scope
- * on 14-June-2018: 100 us.
- */
- if (reset)
- usleep_range(100, 200);
- mutex_unlock(&cd->ctrl_lock);
-}
-
-static int anybuss_reset(struct controller_priv *cd,
- unsigned long id, bool reset)
-{
- if (id >= 2)
- return -EINVAL;
- if (cd->common_reset)
- do_reset(cd, CPLD_CONTROL_CRST, reset);
- else
- do_reset(cd, id ? CPLD_CONTROL_RST2 : CPLD_CONTROL_RST1, reset);
- return 0;
-}
-
-static void export_reset_0(struct device *dev, bool assert)
-{
- struct controller_priv *cd = dev_get_drvdata(dev);
-
- anybuss_reset(cd, 0, assert);
-}
-
-static void export_reset_1(struct device *dev, bool assert)
-{
- struct controller_priv *cd = dev_get_drvdata(dev);
-
- anybuss_reset(cd, 1, assert);
-}
-
-/*
- * parallel bus limitation:
- *
- * the anybus is 8-bit wide. we can't assume that the hardware will translate
- * word accesses on the parallel bus to multiple byte-accesses on the anybus.
- *
- * the imx WEIM bus does not provide this type of translation.
- *
- * to be safe, we will limit parallel bus accesses to a single byte
- * at a time for now.
- */
-
-static const struct regmap_config arcx_regmap_cfg = {
- .reg_bits = 16,
- .val_bits = 8,
- .max_register = 0x7ff,
- .use_single_read = true,
- .use_single_write = true,
- /*
- * single-byte parallel bus accesses are atomic, so don't
- * require any synchronization.
- */
- .disable_locking = true,
-};
-
-static struct regmap *create_parallel_regmap(struct platform_device *pdev,
- int idx)
-{
- void __iomem *base;
- struct device *dev = &pdev->dev;
-
- base = devm_platform_ioremap_resource(pdev, idx + 1);
- if (IS_ERR(base))
- return ERR_CAST(base);
- return devm_regmap_init_mmio(dev, base, &arcx_regmap_cfg);
-}
-
-static struct anybuss_host *
-create_anybus_host(struct platform_device *pdev, int idx)
-{
- struct anybuss_ops ops = {};
-
- switch (idx) {
- case 0:
- ops.reset = export_reset_0;
- break;
- case 1:
- ops.reset = export_reset_1;
- break;
- default:
- return ERR_PTR(-EINVAL);
- }
- ops.host_idx = idx;
- ops.regmap = create_parallel_regmap(pdev, idx);
- if (IS_ERR(ops.regmap))
- return ERR_CAST(ops.regmap);
- ops.irq = platform_get_irq(pdev, idx);
- if (ops.irq < 0)
- return ERR_PTR(ops.irq);
- return devm_anybuss_host_common_probe(&pdev->dev, &ops);
-}
-
-static ssize_t version_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct controller_priv *cd = dev_get_drvdata(dev);
-
- return sprintf(buf, "%s\n", cd->version);
-}
-static DEVICE_ATTR_RO(version);
-
-static ssize_t design_number_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct controller_priv *cd = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", cd->design_no);
-}
-static DEVICE_ATTR_RO(design_number);
-
-static struct attribute *controller_attributes[] = {
- &dev_attr_version.attr,
- &dev_attr_design_number.attr,
- NULL,
-};
-
-static const struct attribute_group controller_attribute_group = {
- .attrs = controller_attributes,
-};
-
-static const struct attribute_group *controller_attribute_groups[] = {
- &controller_attribute_group,
- NULL,
-};
-
-static void controller_device_release(struct device *dev)
-{
- kfree(dev);
-}
-
-static int can_power_is_enabled(struct regulator_dev *rdev)
-{
- struct controller_priv *cd = rdev_get_drvdata(rdev);
-
- return !(readb(cd->cpld_base + CPLD_STATUS1) & CPLD_STATUS1_CAN_POWER);
-}
-
-static const struct regulator_ops can_power_ops = {
- .is_enabled = can_power_is_enabled,
-};
-
-static const struct regulator_desc can_power_desc = {
- .name = "regulator-can-power",
- .id = -1,
- .type = REGULATOR_VOLTAGE,
- .owner = THIS_MODULE,
- .ops = &can_power_ops,
-};
-
-static const struct class controller_class = {
- .name = "arcx_anybus_controller",
-};
-
-static DEFINE_IDA(controller_index_ida);
-
-static int controller_probe(struct platform_device *pdev)
-{
- struct controller_priv *cd;
- struct device *dev = &pdev->dev;
- struct regulator_config config = { };
- struct regulator_dev *regulator;
- int err, id;
- struct anybuss_host *host;
- u8 status1, cap;
-
- cd = devm_kzalloc(dev, sizeof(*cd), GFP_KERNEL);
- if (!cd)
- return -ENOMEM;
- dev_set_drvdata(dev, cd);
- mutex_init(&cd->ctrl_lock);
- cd->reset_gpiod = devm_gpiod_get(dev, "reset", GPIOD_OUT_LOW);
- if (IS_ERR(cd->reset_gpiod))
- return PTR_ERR(cd->reset_gpiod);
-
- /* CPLD control memory, sits at index 0 */
- cd->cpld_base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(cd->cpld_base)) {
- dev_err(dev,
- "failed to map cpld base address\n");
- err = PTR_ERR(cd->cpld_base);
- goto out_reset;
- }
-
- /* identify cpld */
- status1 = readb(cd->cpld_base + CPLD_STATUS1);
- cd->design_no = (readb(cd->cpld_base + CPLD_DESIGN_HI) << 8) |
- readb(cd->cpld_base + CPLD_DESIGN_LO);
- snprintf(cd->version, sizeof(cd->version), "%c%d",
- 'A' + ((status1 >> 5) & 0x7),
- (status1 >> 2) & 0x7);
- dev_info(dev, "design number %d, revision %s\n",
- cd->design_no,
- cd->version);
- cap = readb(cd->cpld_base + CPLD_CAP);
- if (!(cap & CPLD_CAP_COMPAT)) {
- dev_err(dev, "unsupported controller [cap=0x%02X]", cap);
- err = -ENODEV;
- goto out_reset;
- }
-
- if (status1 & CPLD_STATUS1_AB) {
- dev_info(dev, "has anybus-S slot(s)");
- cd->common_reset = !(cap & CPLD_CAP_SEP_RESETS);
- dev_info(dev, "supports %s", cd->common_reset ?
- "a common reset" : "separate resets");
- for (id = 0; id < 2; id++) {
- host = create_anybus_host(pdev, id);
- if (!IS_ERR(host))
- continue;
- err = PTR_ERR(host);
- /* -ENODEV is fine, it just means no card detected */
- if (err != -ENODEV)
- goto out_reset;
- }
- }
-
- id = ida_alloc(&controller_index_ida, GFP_KERNEL);
- if (id < 0) {
- err = id;
- goto out_reset;
- }
- /* export can power readout as a regulator */
- config.dev = dev;
- config.driver_data = cd;
- regulator = devm_regulator_register(dev, &can_power_desc, &config);
- if (IS_ERR(regulator)) {
- err = PTR_ERR(regulator);
- goto out_ida;
- }
- /* make controller info visible to userspace */
- cd->class_dev = kzalloc(sizeof(*cd->class_dev), GFP_KERNEL);
- if (!cd->class_dev) {
- err = -ENOMEM;
- goto out_ida;
- }
- cd->class_dev->class = &controller_class;
- cd->class_dev->groups = controller_attribute_groups;
- cd->class_dev->parent = dev;
- cd->class_dev->id = id;
- cd->class_dev->release = controller_device_release;
- dev_set_name(cd->class_dev, "%d", cd->class_dev->id);
- dev_set_drvdata(cd->class_dev, cd);
- err = device_register(cd->class_dev);
- if (err)
- goto out_dev;
- return 0;
-out_dev:
- put_device(cd->class_dev);
-out_ida:
- ida_free(&controller_index_ida, id);
-out_reset:
- gpiod_set_value_cansleep(cd->reset_gpiod, 1);
- return err;
-}
-
-static void controller_remove(struct platform_device *pdev)
-{
- struct controller_priv *cd = platform_get_drvdata(pdev);
- int id = cd->class_dev->id;
-
- device_unregister(cd->class_dev);
- ida_free(&controller_index_ida, id);
- gpiod_set_value_cansleep(cd->reset_gpiod, 1);
-}
-
-static const struct of_device_id controller_of_match[] = {
- { .compatible = "arcx,anybus-controller" },
- { }
-};
-
-MODULE_DEVICE_TABLE(of, controller_of_match);
-
-static struct platform_driver controller_driver = {
- .probe = controller_probe,
- .remove_new = controller_remove,
- .driver = {
- .name = "arcx-anybus-controller",
- .of_match_table = controller_of_match,
- },
-};
-
-static int __init controller_init(void)
-{
- int err;
-
- err = class_register(&controller_class);
- if (err)
- return err;
- err = platform_driver_register(&controller_driver);
- if (err)
- class_unregister(&controller_class);
-
- return err;
-}
-
-static void __exit controller_exit(void)
-{
- platform_driver_unregister(&controller_driver);
- class_unregister(&controller_class);
- ida_destroy(&controller_index_ida);
-}
-
-module_init(controller_init);
-module_exit(controller_exit);
-
-MODULE_DESCRIPTION("Arcx Anybus-S Controller driver");
-MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/fieldbus/anybuss/hms-profinet.c b/drivers/staging/fieldbus/anybuss/hms-profinet.c
deleted file mode 100644
index e691736a53f1..000000000000
--- a/drivers/staging/fieldbus/anybuss/hms-profinet.c
+++ /dev/null
@@ -1,224 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * HMS Profinet Client Driver
- *
- * Copyright (C) 2018 Arcx Inc
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-
-/* move to <linux/fieldbus_dev.h> when taking this out of staging */
-#include "../fieldbus_dev.h"
-
-/* move to <linux/anybuss-client.h> when taking this out of staging */
-#include "anybuss-client.h"
-
-#define PROFI_DPRAM_SIZE 512
-
-/*
- * ---------------------------------------------------------------
- * Anybus Profinet mailbox messages - definitions
- * ---------------------------------------------------------------
- * note that we're depending on the layout of these structures being
- * exactly as advertised.
- */
-
-struct msg_mac_addr {
- u8 addr[6];
-};
-
-struct profi_priv {
- struct fieldbus_dev fbdev;
- struct anybuss_client *client;
- struct mutex enable_lock; /* serializes card enable */
- bool power_on;
-};
-
-static ssize_t
-profi_read_area(struct fieldbus_dev *fbdev, char __user *buf, size_t size,
- loff_t *offset)
-{
- struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
-
- return anybuss_read_output(priv->client, buf, size, offset);
-}
-
-static ssize_t
-profi_write_area(struct fieldbus_dev *fbdev, const char __user *buf,
- size_t size, loff_t *offset)
-{
- struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
-
- return anybuss_write_input(priv->client, buf, size, offset);
-}
-
-static int profi_id_get(struct fieldbus_dev *fbdev, char *buf,
- size_t max_size)
-{
- struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
- struct msg_mac_addr response;
- int ret;
-
- ret = anybuss_recv_msg(priv->client, 0x0010, &response,
- sizeof(response));
- if (ret < 0)
- return ret;
- return snprintf(buf, max_size, "%pM\n", response.addr);
-}
-
-static bool profi_enable_get(struct fieldbus_dev *fbdev)
-{
- struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
- bool power_on;
-
- mutex_lock(&priv->enable_lock);
- power_on = priv->power_on;
- mutex_unlock(&priv->enable_lock);
-
- return power_on;
-}
-
-static int __profi_enable(struct profi_priv *priv)
-{
- int ret;
- struct anybuss_client *client = priv->client;
- /* Initialization Sequence, Generic Anybus Mode */
- const struct anybuss_memcfg mem_cfg = {
- .input_io = 220,
- .input_dpram = PROFI_DPRAM_SIZE,
- .input_total = PROFI_DPRAM_SIZE,
- .output_io = 220,
- .output_dpram = PROFI_DPRAM_SIZE,
- .output_total = PROFI_DPRAM_SIZE,
- .offl_mode = FIELDBUS_DEV_OFFL_MODE_CLEAR,
- };
-
- /*
- * switch anybus off then on, this ensures we can do a complete
- * configuration cycle in case anybus was already on.
- */
- anybuss_set_power(client, false);
- ret = anybuss_set_power(client, true);
- if (ret)
- goto err;
- ret = anybuss_start_init(client, &mem_cfg);
- if (ret)
- goto err;
- ret = anybuss_finish_init(client);
- if (ret)
- goto err;
- priv->power_on = true;
- return 0;
-
-err:
- anybuss_set_power(client, false);
- priv->power_on = false;
- return ret;
-}
-
-static int __profi_disable(struct profi_priv *priv)
-{
- struct anybuss_client *client = priv->client;
-
- anybuss_set_power(client, false);
- priv->power_on = false;
- return 0;
-}
-
-static int profi_simple_enable(struct fieldbus_dev *fbdev, bool enable)
-{
- int ret;
- struct profi_priv *priv = container_of(fbdev, struct profi_priv, fbdev);
-
- mutex_lock(&priv->enable_lock);
- if (enable)
- ret = __profi_enable(priv);
- else
- ret = __profi_disable(priv);
- mutex_unlock(&priv->enable_lock);
-
- return ret;
-}
-
-static void profi_on_area_updated(struct anybuss_client *client)
-{
- struct profi_priv *priv = anybuss_get_drvdata(client);
-
- fieldbus_dev_area_updated(&priv->fbdev);
-}
-
-static void profi_on_online_changed(struct anybuss_client *client, bool online)
-{
- struct profi_priv *priv = anybuss_get_drvdata(client);
-
- fieldbus_dev_online_changed(&priv->fbdev, online);
-}
-
-static int profinet_probe(struct anybuss_client *client)
-{
- struct profi_priv *priv;
- struct device *dev = &client->dev;
- int err;
-
- client->on_area_updated = profi_on_area_updated;
- client->on_online_changed = profi_on_online_changed;
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
- mutex_init(&priv->enable_lock);
- priv->client = client;
- priv->fbdev.read_area_sz = PROFI_DPRAM_SIZE;
- priv->fbdev.write_area_sz = PROFI_DPRAM_SIZE;
- priv->fbdev.card_name = "HMS Profinet IRT (Anybus-S)";
- priv->fbdev.fieldbus_type = FIELDBUS_DEV_TYPE_PROFINET;
- priv->fbdev.read_area = profi_read_area;
- priv->fbdev.write_area = profi_write_area;
- priv->fbdev.fieldbus_id_get = profi_id_get;
- priv->fbdev.enable_get = profi_enable_get;
- priv->fbdev.simple_enable_set = profi_simple_enable;
- priv->fbdev.parent = dev;
- err = fieldbus_dev_register(&priv->fbdev);
- if (err < 0)
- return err;
- dev_info(dev, "card detected, registered as %s",
- dev_name(priv->fbdev.dev));
- anybuss_set_drvdata(client, priv);
-
- return 0;
-}
-
-static void profinet_remove(struct anybuss_client *client)
-{
- struct profi_priv *priv = anybuss_get_drvdata(client);
-
- fieldbus_dev_unregister(&priv->fbdev);
-}
-
-static struct anybuss_client_driver profinet_driver = {
- .probe = profinet_probe,
- .remove = profinet_remove,
- .driver = {
- .name = "hms-profinet",
- .owner = THIS_MODULE,
- },
- .anybus_id = 0x0089,
-};
-
-static int __init profinet_init(void)
-{
- return anybuss_client_driver_register(&profinet_driver);
-}
-module_init(profinet_init);
-
-static void __exit profinet_exit(void)
-{
- return anybuss_client_driver_unregister(&profinet_driver);
-}
-module_exit(profinet_exit);
-
-MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
-MODULE_DESCRIPTION("HMS Profinet IRT Driver (Anybus-S)");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/fieldbus/anybuss/host.c b/drivers/staging/fieldbus/anybuss/host.c
deleted file mode 100644
index 4f2b2fce92ee..000000000000
--- a/drivers/staging/fieldbus/anybuss/host.c
+++ /dev/null
@@ -1,1452 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * HMS Anybus-S Host Driver
- *
- * Copyright (C) 2018 Arcx Inc
- */
-
-/*
- * Architecture Overview
- * =====================
- * This driver (running on the CPU/SoC) and the Anybus-S card communicate
- * by reading and writing data to/from the Anybus-S Dual-Port RAM (dpram).
- * This is memory connected to both the SoC and Anybus-S card, which both sides
- * can access freely and concurrently.
- *
- * Synchronization happens by means of two registers located in the dpram:
- * IND_AB: written exclusively by the Anybus card; and
- * IND_AP: written exclusively by this driver.
- *
- * Communication happens using one of the following mechanisms:
- * 1. reserve, read/write, release dpram memory areas:
- * using an IND_AB/IND_AP protocol, the driver is able to reserve certain
- * memory areas. no dpram memory can be read or written except if reserved.
- * (with a few limited exceptions)
- * 2. send and receive data structures via a shared mailbox:
- * using an IND_AB/IND_AP protocol, the driver and Anybus card are able to
- * exchange commands and responses using a shared mailbox.
- * 3. receive software interrupts:
- * using an IND_AB/IND_AP protocol, the Anybus card is able to notify the
- * driver of certain events such as: bus online/offline, data available.
- * note that software interrupt event bits are located in a memory area
- * which must be reserved before it can be accessed.
- *
- * The manual[1] is silent on whether these mechanisms can happen concurrently,
- * or how they should be synchronized. However, section 13 (Driver Example)
- * provides the following suggestion for developing a driver:
- * a) an interrupt handler which updates global variables;
- * b) a continuously-running task handling area requests (1 above)
- * c) a continuously-running task handling mailbox requests (2 above)
- * The example conspicuously leaves out software interrupts (3 above), which
- * is the thorniest issue to get right (see below).
- *
- * The naive, straightforward way to implement this would be:
- * - create an isr which updates shared variables;
- * - create a work_struct which handles software interrupts on a queue;
- * - create a function which does reserve/update/unlock in a loop;
- * - create a function which does mailbox send/receive in a loop;
- * - call the above functions from the driver's read/write/ioctl;
- * - synchronize using mutexes/spinlocks:
- * + only one area request at a time
- * + only one mailbox request at a time
- * + protect AB_IND, AB_IND against data hazards (e.g. read-after-write)
- *
- * Unfortunately, the presence of the software interrupt causes subtle yet
- * considerable synchronization issues; especially problematic is the
- * requirement to reserve/release the area which contains the status bits.
- *
- * The driver architecture presented here sidesteps these synchronization issues
- * by accessing the dpram from a single kernel thread only. User-space throws
- * "tasks" (i.e. 1, 2 above) into a task queue, waits for their completion,
- * and the kernel thread runs them to completion.
- *
- * Each task has a task_function, which is called/run by the queue thread.
- * That function communicates with the Anybus card, and returns either
- * 0 (OK), a negative error code (error), or -EINPROGRESS (waiting).
- * On OK or error, the queue thread completes and dequeues the task,
- * which also releases the user space thread which may still be waiting for it.
- * On -EINPROGRESS (waiting), the queue thread will leave the task on the queue,
- * and revisit (call again) whenever an interrupt event comes in.
- *
- * Each task has a state machine, which is run by calling its task_function.
- * It ensures that the task will go through its various stages over time,
- * returning -EINPROGRESS if it wants to wait for an event to happen.
- *
- * Note that according to the manual's driver example, the following operations
- * may run independent of each other:
- * - area reserve/read/write/release (point 1 above)
- * - mailbox operations (point 2 above)
- * - switching power on/off
- *
- * To allow them to run independently, each operation class gets its own queue.
- *
- * Userspace processes A, B, C, D post tasks to the appropriate queue,
- * and wait for task completion:
- *
- * process A B C D
- * | | | |
- * v v v v
- * |<----- ========================================
- * | | | |
- * | v v v-------<-------+
- * | +--------------------------------------+ |
- * | | power q | mbox q | area q | |
- * | |------------|------------|------------| |
- * | | task | task | task | |
- * | | task | task | task | |
- * | | task wait | task wait | task wait | |
- * | +--------------------------------------+ |
- * | ^ ^ ^ |
- * | | | | ^
- * | +--------------------------------------+ |
- * | | queue thread | |
- * | |--------------------------------------| |
- * | | single-threaded: | |
- * | | loop: | |
- * v | for each queue: | |
- * | | run task state machine | |
- * | | if task waiting: | |
- * | | leave on queue | |
- * | | if task done: | |
- * | | complete task, remove from q | |
- * | | if software irq event bits set: | |
- * | | notify userspace | |
- * | | post clear event bits task------>|>-------+
- * | | wait for IND_AB changed event OR |
- * | | task added event OR |
- * | | timeout |
- * | | end loop |
- * | +--------------------------------------+
- * | + wake up +
- * | +--------------------------------------+
- * | ^ ^
- * | | |
- * +-------->------- |
- * |
- * +--------------------------------------+
- * | interrupt service routine |
- * |--------------------------------------|
- * | wake up queue thread on IND_AB change|
- * +--------------------------------------+
- *
- * Note that the Anybus interrupt is dual-purpose:
- * - after a reset, triggered when the card becomes ready;
- * - during normal operation, triggered when AB_IND changes.
- * This is why the interrupt service routine doesn't just wake up the
- * queue thread, but also completes the card_boot completion.
- *
- * [1] https://www.anybus.com/docs/librariesprovider7/default-document-library/
- * manuals-design-guides/hms-hmsi-27-275.pdf
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/atomic.h>
-#include <linux/kthread.h>
-#include <linux/kfifo.h>
-#include <linux/spinlock.h>
-#include <linux/uaccess.h>
-#include <linux/regmap.h>
-#include <linux/of.h>
-#include <linux/random.h>
-#include <linux/kref.h>
-#include <linux/of_address.h>
-
-/* move to <linux/anybuss-*.h> when taking this out of staging */
-#include "anybuss-client.h"
-#include "anybuss-controller.h"
-
-#define DPRAM_SIZE 0x800
-#define MAX_MBOX_MSG_SZ 0x0FF
-#define TIMEOUT (HZ * 2)
-#define MAX_DATA_AREA_SZ 0x200
-#define MAX_FBCTRL_AREA_SZ 0x1BE
-
-#define REG_BOOTLOADER_V 0x7C0
-#define REG_API_V 0x7C2
-#define REG_FIELDBUS_V 0x7C4
-#define REG_SERIAL_NO 0x7C6
-#define REG_FIELDBUS_TYPE 0x7CC
-#define REG_MODULE_SW_V 0x7CE
-#define REG_IND_AB 0x7FF
-#define REG_IND_AP 0x7FE
-#define REG_EVENT_CAUSE 0x7ED
-#define MBOX_IN_AREA 0x400
-#define MBOX_OUT_AREA 0x520
-#define DATA_IN_AREA 0x000
-#define DATA_OUT_AREA 0x200
-#define FBCTRL_AREA 0x640
-
-#define EVENT_CAUSE_DC 0x01
-#define EVENT_CAUSE_FBOF 0x02
-#define EVENT_CAUSE_FBON 0x04
-
-#define IND_AB_UPDATED 0x08
-#define IND_AX_MIN 0x80
-#define IND_AX_MOUT 0x40
-#define IND_AX_IN 0x04
-#define IND_AX_OUT 0x02
-#define IND_AX_FBCTRL 0x01
-#define IND_AP_LOCK 0x08
-#define IND_AP_ACTION 0x10
-#define IND_AX_EVNT 0x20
-#define IND_AP_ABITS (IND_AX_IN | IND_AX_OUT | \
- IND_AX_FBCTRL | \
- IND_AP_ACTION | IND_AP_LOCK)
-
-#define INFO_TYPE_FB 0x0002
-#define INFO_TYPE_APP 0x0001
-#define INFO_COMMAND 0x4000
-
-#define OP_MODE_FBFC 0x0002
-#define OP_MODE_FBS 0x0004
-#define OP_MODE_CD 0x0200
-
-#define CMD_START_INIT 0x0001
-#define CMD_ANYBUS_INIT 0x0002
-#define CMD_END_INIT 0x0003
-
-/*
- * ---------------------------------------------------------------
- * Anybus mailbox messages - definitions
- * ---------------------------------------------------------------
- * note that we're depending on the layout of these structures being
- * exactly as advertised.
- */
-
-struct anybus_mbox_hdr {
- __be16 id;
- __be16 info;
- __be16 cmd_num;
- __be16 data_size;
- __be16 frame_count;
- __be16 frame_num;
- __be16 offset_high;
- __be16 offset_low;
- __be16 extended[8];
-};
-
-struct msg_anybus_init {
- __be16 input_io_len;
- __be16 input_dpram_len;
- __be16 input_total_len;
- __be16 output_io_len;
- __be16 output_dpram_len;
- __be16 output_total_len;
- __be16 op_mode;
- __be16 notif_config;
- __be16 wd_val;
-};
-
-/* ------------- ref counted tasks ------------- */
-
-struct ab_task;
-typedef int (*ab_task_fn_t)(struct anybuss_host *cd,
- struct ab_task *t);
-typedef void (*ab_done_fn_t)(struct anybuss_host *cd);
-
-struct area_priv {
- bool is_write;
- u16 flags;
- u16 addr;
- size_t count;
- u8 buf[MAX_DATA_AREA_SZ];
-};
-
-struct mbox_priv {
- struct anybus_mbox_hdr hdr;
- size_t msg_out_sz;
- size_t msg_in_sz;
- u8 msg[MAX_MBOX_MSG_SZ];
-};
-
-struct ab_task {
- struct kmem_cache *cache;
- struct kref refcount;
- ab_task_fn_t task_fn;
- ab_done_fn_t done_fn;
- int result;
- struct completion done;
- unsigned long start_jiffies;
- union {
- struct area_priv area_pd;
- struct mbox_priv mbox_pd;
- };
-};
-
-static struct ab_task *ab_task_create_get(struct kmem_cache *cache,
- ab_task_fn_t task_fn)
-{
- struct ab_task *t;
-
- t = kmem_cache_alloc(cache, GFP_KERNEL);
- if (!t)
- return NULL;
- t->cache = cache;
- kref_init(&t->refcount);
- t->task_fn = task_fn;
- t->done_fn = NULL;
- t->result = 0;
- init_completion(&t->done);
- return t;
-}
-
-static void __ab_task_destroy(struct kref *refcount)
-{
- struct ab_task *t = container_of(refcount, struct ab_task, refcount);
- struct kmem_cache *cache = t->cache;
-
- kmem_cache_free(cache, t);
-}
-
-static void ab_task_put(struct ab_task *t)
-{
- kref_put(&t->refcount, __ab_task_destroy);
-}
-
-static struct ab_task *__ab_task_get(struct ab_task *t)
-{
- kref_get(&t->refcount);
- return t;
-}
-
-static void __ab_task_finish(struct ab_task *t, struct anybuss_host *cd)
-{
- if (t->done_fn)
- t->done_fn(cd);
- complete(&t->done);
-}
-
-static void
-ab_task_dequeue_finish_put(struct kfifo *q, struct anybuss_host *cd)
-{
- int ret;
- struct ab_task *t;
-
- ret = kfifo_out(q, &t, sizeof(t));
- WARN_ON(!ret);
- __ab_task_finish(t, cd);
- ab_task_put(t);
-}
-
-static int
-ab_task_enqueue(struct ab_task *t, struct kfifo *q, spinlock_t *slock,
- wait_queue_head_t *wq)
-{
- int ret;
-
- t->start_jiffies = jiffies;
- __ab_task_get(t);
- ret = kfifo_in_spinlocked(q, &t, sizeof(t), slock);
- if (!ret) {
- ab_task_put(t);
- return -ENOMEM;
- }
- wake_up(wq);
- return 0;
-}
-
-static int
-ab_task_enqueue_wait(struct ab_task *t, struct kfifo *q, spinlock_t *slock,
- wait_queue_head_t *wq)
-{
- int ret;
-
- ret = ab_task_enqueue(t, q, slock, wq);
- if (ret)
- return ret;
- ret = wait_for_completion_interruptible(&t->done);
- if (ret)
- return ret;
- return t->result;
-}
-
-/* ------------------------ anybus hardware ------------------------ */
-
-struct anybuss_host {
- struct device *dev;
- struct anybuss_client *client;
- void (*reset)(struct device *dev, bool assert);
- struct regmap *regmap;
- int irq;
- int host_idx;
- struct task_struct *qthread;
- wait_queue_head_t wq;
- struct completion card_boot;
- atomic_t ind_ab;
- spinlock_t qlock; /* protects IN side of powerq, mboxq, areaq */
- struct kmem_cache *qcache;
- struct kfifo qs[3];
- struct kfifo *powerq;
- struct kfifo *mboxq;
- struct kfifo *areaq;
- bool power_on;
- bool softint_pending;
-};
-
-static void reset_assert(struct anybuss_host *cd)
-{
- cd->reset(cd->dev, true);
-}
-
-static void reset_deassert(struct anybuss_host *cd)
-{
- cd->reset(cd->dev, false);
-}
-
-static int test_dpram(struct regmap *regmap)
-{
- int i;
- unsigned int val;
-
- for (i = 0; i < DPRAM_SIZE; i++)
- regmap_write(regmap, i, (u8)i);
- for (i = 0; i < DPRAM_SIZE; i++) {
- regmap_read(regmap, i, &val);
- if ((u8)val != (u8)i)
- return -EIO;
- }
- return 0;
-}
-
-static int read_ind_ab(struct regmap *regmap)
-{
- unsigned long timeout = jiffies + HZ / 2;
- unsigned int a, b, i = 0;
-
- while (time_before_eq(jiffies, timeout)) {
- regmap_read(regmap, REG_IND_AB, &a);
- regmap_read(regmap, REG_IND_AB, &b);
- if (likely(a == b))
- return (int)a;
- if (i < 10) {
- cpu_relax();
- i++;
- } else {
- usleep_range(500, 1000);
- }
- }
- WARN(1, "IND_AB register not stable");
- return -ETIMEDOUT;
-}
-
-static int write_ind_ap(struct regmap *regmap, unsigned int ind_ap)
-{
- unsigned long timeout = jiffies + HZ / 2;
- unsigned int v, i = 0;
-
- while (time_before_eq(jiffies, timeout)) {
- regmap_write(regmap, REG_IND_AP, ind_ap);
- regmap_read(regmap, REG_IND_AP, &v);
- if (likely(ind_ap == v))
- return 0;
- if (i < 10) {
- cpu_relax();
- i++;
- } else {
- usleep_range(500, 1000);
- }
- }
- WARN(1, "IND_AP register not stable");
- return -ETIMEDOUT;
-}
-
-static irqreturn_t irq_handler(int irq, void *data)
-{
- struct anybuss_host *cd = data;
- int ind_ab;
-
- /*
- * irq handler needs exclusive access to the IND_AB register,
- * because the act of reading the register acks the interrupt.
- *
- * store the register value in cd->ind_ab (an atomic_t), so that the
- * queue thread is able to read it without causing an interrupt ack
- * side-effect (and without spuriously acking an interrupt).
- */
- ind_ab = read_ind_ab(cd->regmap);
- if (ind_ab < 0)
- return IRQ_NONE;
- atomic_set(&cd->ind_ab, ind_ab);
- complete(&cd->card_boot);
- wake_up(&cd->wq);
- return IRQ_HANDLED;
-}
-
-/* ------------------------ power on/off tasks --------------------- */
-
-static int task_fn_power_off(struct anybuss_host *cd,
- struct ab_task *t)
-{
- struct anybuss_client *client = cd->client;
-
- if (!cd->power_on)
- return 0;
- disable_irq(cd->irq);
- reset_assert(cd);
- atomic_set(&cd->ind_ab, IND_AB_UPDATED);
- if (client->on_online_changed)
- client->on_online_changed(client, false);
- cd->power_on = false;
- return 0;
-}
-
-static int task_fn_power_on_2(struct anybuss_host *cd,
- struct ab_task *t)
-{
- if (completion_done(&cd->card_boot)) {
- cd->power_on = true;
- return 0;
- }
- if (time_after(jiffies, t->start_jiffies + TIMEOUT)) {
- disable_irq(cd->irq);
- reset_assert(cd);
- dev_err(cd->dev, "power on timed out");
- return -ETIMEDOUT;
- }
- return -EINPROGRESS;
-}
-
-static int task_fn_power_on(struct anybuss_host *cd,
- struct ab_task *t)
-{
- unsigned int dummy;
-
- if (cd->power_on)
- return 0;
- /*
- * anybus docs: prevent false 'init done' interrupt by
- * doing a dummy read of IND_AB register while in reset.
- */
- regmap_read(cd->regmap, REG_IND_AB, &dummy);
- reinit_completion(&cd->card_boot);
- enable_irq(cd->irq);
- reset_deassert(cd);
- t->task_fn = task_fn_power_on_2;
- return -EINPROGRESS;
-}
-
-int anybuss_set_power(struct anybuss_client *client, bool power_on)
-{
- struct anybuss_host *cd = client->host;
- struct ab_task *t;
- int err;
-
- t = ab_task_create_get(cd->qcache, power_on ?
- task_fn_power_on : task_fn_power_off);
- if (!t)
- return -ENOMEM;
- err = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq);
- ab_task_put(t);
- return err;
-}
-EXPORT_SYMBOL_GPL(anybuss_set_power);
-
-/* ---------------------------- area tasks ------------------------ */
-
-static int task_fn_area_3(struct anybuss_host *cd, struct ab_task *t)
-{
- struct area_priv *pd = &t->area_pd;
-
- if (!cd->power_on)
- return -EIO;
- if (atomic_read(&cd->ind_ab) & pd->flags) {
- /* area not released yet */
- if (time_after(jiffies, t->start_jiffies + TIMEOUT))
- return -ETIMEDOUT;
- return -EINPROGRESS;
- }
- return 0;
-}
-
-static int task_fn_area_2(struct anybuss_host *cd, struct ab_task *t)
-{
- struct area_priv *pd = &t->area_pd;
- unsigned int ind_ap;
- int ret;
-
- if (!cd->power_on)
- return -EIO;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- if (!(atomic_read(&cd->ind_ab) & pd->flags)) {
- /* we don't own the area yet */
- if (time_after(jiffies, t->start_jiffies + TIMEOUT)) {
- dev_warn(cd->dev, "timeout waiting for area");
- dump_stack();
- return -ETIMEDOUT;
- }
- return -EINPROGRESS;
- }
- /* we own the area, do what we're here to do */
- if (pd->is_write)
- regmap_bulk_write(cd->regmap, pd->addr, pd->buf,
- pd->count);
- else
- regmap_bulk_read(cd->regmap, pd->addr, pd->buf,
- pd->count);
- /* ask to release the area, must use unlocked release */
- ind_ap &= ~IND_AP_ABITS;
- ind_ap |= pd->flags;
- ret = write_ind_ap(cd->regmap, ind_ap);
- if (ret)
- return ret;
- t->task_fn = task_fn_area_3;
- return -EINPROGRESS;
-}
-
-static int task_fn_area(struct anybuss_host *cd, struct ab_task *t)
-{
- struct area_priv *pd = &t->area_pd;
- unsigned int ind_ap;
- int ret;
-
- if (!cd->power_on)
- return -EIO;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- /* ask to take the area */
- ind_ap &= ~IND_AP_ABITS;
- ind_ap |= pd->flags | IND_AP_ACTION | IND_AP_LOCK;
- ret = write_ind_ap(cd->regmap, ind_ap);
- if (ret)
- return ret;
- t->task_fn = task_fn_area_2;
- return -EINPROGRESS;
-}
-
-static struct ab_task *
-create_area_reader(struct kmem_cache *qcache, u16 flags, u16 addr,
- size_t count)
-{
- struct ab_task *t;
- struct area_priv *ap;
-
- t = ab_task_create_get(qcache, task_fn_area);
- if (!t)
- return NULL;
- ap = &t->area_pd;
- ap->flags = flags;
- ap->addr = addr;
- ap->is_write = false;
- ap->count = count;
- return t;
-}
-
-static struct ab_task *
-create_area_writer(struct kmem_cache *qcache, u16 flags, u16 addr,
- const void *buf, size_t count)
-{
- struct ab_task *t;
- struct area_priv *ap;
-
- t = ab_task_create_get(qcache, task_fn_area);
- if (!t)
- return NULL;
- ap = &t->area_pd;
- ap->flags = flags;
- ap->addr = addr;
- ap->is_write = true;
- ap->count = count;
- memcpy(ap->buf, buf, count);
- return t;
-}
-
-static struct ab_task *
-create_area_user_writer(struct kmem_cache *qcache, u16 flags, u16 addr,
- const void __user *buf, size_t count)
-{
- struct ab_task *t;
- struct area_priv *ap;
-
- t = ab_task_create_get(qcache, task_fn_area);
- if (!t)
- return ERR_PTR(-ENOMEM);
- ap = &t->area_pd;
- ap->flags = flags;
- ap->addr = addr;
- ap->is_write = true;
- ap->count = count;
- if (copy_from_user(ap->buf, buf, count)) {
- ab_task_put(t);
- return ERR_PTR(-EFAULT);
- }
- return t;
-}
-
-static bool area_range_ok(u16 addr, size_t count, u16 area_start,
- size_t area_sz)
-{
- u16 area_end_ex = area_start + area_sz;
- u16 addr_end_ex;
-
- if (addr < area_start)
- return false;
- if (addr >= area_end_ex)
- return false;
- addr_end_ex = addr + count;
- if (addr_end_ex > area_end_ex)
- return false;
- return true;
-}
-
-/* -------------------------- mailbox tasks ----------------------- */
-
-static int task_fn_mbox_2(struct anybuss_host *cd, struct ab_task *t)
-{
- struct mbox_priv *pd = &t->mbox_pd;
- unsigned int ind_ap;
-
- if (!cd->power_on)
- return -EIO;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- if (((atomic_read(&cd->ind_ab) ^ ind_ap) & IND_AX_MOUT) == 0) {
- /* output message not here */
- if (time_after(jiffies, t->start_jiffies + TIMEOUT))
- return -ETIMEDOUT;
- return -EINPROGRESS;
- }
- /* grab the returned header and msg */
- regmap_bulk_read(cd->regmap, MBOX_OUT_AREA, &pd->hdr,
- sizeof(pd->hdr));
- regmap_bulk_read(cd->regmap, MBOX_OUT_AREA + sizeof(pd->hdr),
- pd->msg, pd->msg_in_sz);
- /* tell anybus we've consumed the message */
- ind_ap ^= IND_AX_MOUT;
- return write_ind_ap(cd->regmap, ind_ap);
-}
-
-static int task_fn_mbox(struct anybuss_host *cd, struct ab_task *t)
-{
- struct mbox_priv *pd = &t->mbox_pd;
- unsigned int ind_ap;
- int ret;
-
- if (!cd->power_on)
- return -EIO;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- if ((atomic_read(&cd->ind_ab) ^ ind_ap) & IND_AX_MIN) {
- /* mbox input area busy */
- if (time_after(jiffies, t->start_jiffies + TIMEOUT))
- return -ETIMEDOUT;
- return -EINPROGRESS;
- }
- /* write the header and msg to input area */
- regmap_bulk_write(cd->regmap, MBOX_IN_AREA, &pd->hdr,
- sizeof(pd->hdr));
- regmap_bulk_write(cd->regmap, MBOX_IN_AREA + sizeof(pd->hdr),
- pd->msg, pd->msg_out_sz);
- /* tell anybus we gave it a message */
- ind_ap ^= IND_AX_MIN;
- ret = write_ind_ap(cd->regmap, ind_ap);
- if (ret)
- return ret;
- t->start_jiffies = jiffies;
- t->task_fn = task_fn_mbox_2;
- return -EINPROGRESS;
-}
-
-static void log_invalid_other(struct device *dev,
- struct anybus_mbox_hdr *hdr)
-{
- size_t ext_offs = ARRAY_SIZE(hdr->extended) - 1;
- u16 code = be16_to_cpu(hdr->extended[ext_offs]);
-
- dev_err(dev, " Invalid other: [0x%02X]", code);
-}
-
-static const char * const EMSGS[] = {
- "Invalid Message ID",
- "Invalid Message Type",
- "Invalid Command",
- "Invalid Data Size",
- "Message Header Malformed (offset 008h)",
- "Message Header Malformed (offset 00Ah)",
- "Message Header Malformed (offset 00Ch - 00Dh)",
- "Invalid Address",
- "Invalid Response",
- "Flash Config Error",
-};
-
-static int mbox_cmd_err(struct device *dev, struct mbox_priv *mpriv)
-{
- int i;
- u8 ecode;
- struct anybus_mbox_hdr *hdr = &mpriv->hdr;
- u16 info = be16_to_cpu(hdr->info);
- u8 *phdr = (u8 *)hdr;
- u8 *pmsg = mpriv->msg;
-
- if (!(info & 0x8000))
- return 0;
- ecode = (info >> 8) & 0x0F;
- dev_err(dev, "mailbox command failed:");
- if (ecode == 0x0F)
- log_invalid_other(dev, hdr);
- else if (ecode < ARRAY_SIZE(EMSGS))
- dev_err(dev, " Error code: %s (0x%02X)",
- EMSGS[ecode], ecode);
- else
- dev_err(dev, " Error code: 0x%02X\n", ecode);
- dev_err(dev, "Failed command:");
- dev_err(dev, "Message Header:");
- for (i = 0; i < sizeof(mpriv->hdr); i += 2)
- dev_err(dev, "%02X%02X", phdr[i], phdr[i + 1]);
- dev_err(dev, "Message Data:");
- for (i = 0; i < mpriv->msg_in_sz; i += 2)
- dev_err(dev, "%02X%02X", pmsg[i], pmsg[i + 1]);
- dev_err(dev, "Stack dump:");
- dump_stack();
- return -EIO;
-}
-
-static int _anybus_mbox_cmd(struct anybuss_host *cd,
- u16 cmd_num, bool is_fb_cmd,
- const void *msg_out, size_t msg_out_sz,
- void *msg_in, size_t msg_in_sz,
- const void *ext, size_t ext_sz)
-{
- struct ab_task *t;
- struct mbox_priv *pd;
- struct anybus_mbox_hdr *h;
- size_t msg_sz = max(msg_in_sz, msg_out_sz);
- u16 info;
- int err;
-
- if (msg_sz > MAX_MBOX_MSG_SZ)
- return -EINVAL;
- if (ext && ext_sz > sizeof(h->extended))
- return -EINVAL;
- t = ab_task_create_get(cd->qcache, task_fn_mbox);
- if (!t)
- return -ENOMEM;
- pd = &t->mbox_pd;
- h = &pd->hdr;
- info = is_fb_cmd ? INFO_TYPE_FB : INFO_TYPE_APP;
- /*
- * prevent uninitialized memory in the header from being sent
- * across the anybus
- */
- memset(h, 0, sizeof(*h));
- h->info = cpu_to_be16(info | INFO_COMMAND);
- h->cmd_num = cpu_to_be16(cmd_num);
- h->data_size = cpu_to_be16(msg_out_sz);
- h->frame_count = cpu_to_be16(1);
- h->frame_num = cpu_to_be16(1);
- h->offset_high = cpu_to_be16(0);
- h->offset_low = cpu_to_be16(0);
- if (ext)
- memcpy(h->extended, ext, ext_sz);
- memcpy(pd->msg, msg_out, msg_out_sz);
- pd->msg_out_sz = msg_out_sz;
- pd->msg_in_sz = msg_in_sz;
- err = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq);
- if (err)
- goto out;
- /*
- * mailbox mechanism worked ok, but maybe the mbox response
- * contains an error ?
- */
- err = mbox_cmd_err(cd->dev, pd);
- if (err)
- goto out;
- memcpy(msg_in, pd->msg, msg_in_sz);
-out:
- ab_task_put(t);
- return err;
-}
-
-/* ------------------------ anybus queues ------------------------ */
-
-static void process_q(struct anybuss_host *cd, struct kfifo *q)
-{
- struct ab_task *t;
- int ret;
-
- ret = kfifo_out_peek(q, &t, sizeof(t));
- if (!ret)
- return;
- t->result = t->task_fn(cd, t);
- if (t->result != -EINPROGRESS)
- ab_task_dequeue_finish_put(q, cd);
-}
-
-static bool qs_have_work(struct kfifo *qs, size_t num)
-{
- size_t i;
- struct ab_task *t;
- int ret;
-
- for (i = 0; i < num; i++, qs++) {
- ret = kfifo_out_peek(qs, &t, sizeof(t));
- if (ret && (t->result != -EINPROGRESS))
- return true;
- }
- return false;
-}
-
-static void process_qs(struct anybuss_host *cd)
-{
- size_t i;
- struct kfifo *qs = cd->qs;
- size_t nqs = ARRAY_SIZE(cd->qs);
-
- for (i = 0; i < nqs; i++, qs++)
- process_q(cd, qs);
-}
-
-static void softint_ack(struct anybuss_host *cd)
-{
- unsigned int ind_ap;
-
- cd->softint_pending = false;
- if (!cd->power_on)
- return;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- ind_ap &= ~IND_AX_EVNT;
- ind_ap |= atomic_read(&cd->ind_ab) & IND_AX_EVNT;
- write_ind_ap(cd->regmap, ind_ap);
-}
-
-static void process_softint(struct anybuss_host *cd)
-{
- struct anybuss_client *client = cd->client;
- static const u8 zero;
- int ret;
- unsigned int ind_ap, ev;
- struct ab_task *t;
-
- if (!cd->power_on)
- return;
- if (cd->softint_pending)
- return;
- regmap_read(cd->regmap, REG_IND_AP, &ind_ap);
- if (!((atomic_read(&cd->ind_ab) ^ ind_ap) & IND_AX_EVNT))
- return;
- /* process software interrupt */
- regmap_read(cd->regmap, REG_EVENT_CAUSE, &ev);
- if (ev & EVENT_CAUSE_FBON) {
- if (client->on_online_changed)
- client->on_online_changed(client, true);
- dev_dbg(cd->dev, "Fieldbus ON");
- }
- if (ev & EVENT_CAUSE_FBOF) {
- if (client->on_online_changed)
- client->on_online_changed(client, false);
- dev_dbg(cd->dev, "Fieldbus OFF");
- }
- if (ev & EVENT_CAUSE_DC) {
- if (client->on_area_updated)
- client->on_area_updated(client);
- dev_dbg(cd->dev, "Fieldbus data changed");
- }
- /*
- * reset the event cause bits.
- * this must be done while owning the fbctrl area, so we'll
- * enqueue a task to do that.
- */
- t = create_area_writer(cd->qcache, IND_AX_FBCTRL,
- REG_EVENT_CAUSE, &zero, sizeof(zero));
- if (!t) {
- ret = -ENOMEM;
- goto out;
- }
- t->done_fn = softint_ack;
- ret = ab_task_enqueue(t, cd->powerq, &cd->qlock, &cd->wq);
- ab_task_put(t);
- cd->softint_pending = true;
-out:
- WARN_ON(ret);
- if (ret)
- softint_ack(cd);
-}
-
-static int qthread_fn(void *data)
-{
- struct anybuss_host *cd = data;
- struct kfifo *qs = cd->qs;
- size_t nqs = ARRAY_SIZE(cd->qs);
- unsigned int ind_ab;
-
- /*
- * this kernel thread has exclusive access to the anybus's memory.
- * only exception: the IND_AB register, which is accessed exclusively
- * by the interrupt service routine (ISR). This thread must not touch
- * the IND_AB register, but it does require access to its value.
- *
- * the interrupt service routine stores the register's value in
- * cd->ind_ab (an atomic_t), where we may safely access it, with the
- * understanding that it can be modified by the ISR at any time.
- */
-
- while (!kthread_should_stop()) {
- /*
- * make a local copy of IND_AB, so we can go around the loop
- * again in case it changed while processing queues and softint.
- */
- ind_ab = atomic_read(&cd->ind_ab);
- process_qs(cd);
- process_softint(cd);
- wait_event_timeout(cd->wq,
- (atomic_read(&cd->ind_ab) != ind_ab) ||
- qs_have_work(qs, nqs) ||
- kthread_should_stop(),
- HZ);
- /*
- * time out so even 'stuck' tasks will run eventually,
- * and can time out.
- */
- }
-
- return 0;
-}
-
-/* ------------------------ anybus exports ------------------------ */
-
-int anybuss_start_init(struct anybuss_client *client,
- const struct anybuss_memcfg *cfg)
-{
- int ret;
- u16 op_mode;
- struct anybuss_host *cd = client->host;
- struct msg_anybus_init msg = {
- .input_io_len = cpu_to_be16(cfg->input_io),
- .input_dpram_len = cpu_to_be16(cfg->input_dpram),
- .input_total_len = cpu_to_be16(cfg->input_total),
- .output_io_len = cpu_to_be16(cfg->output_io),
- .output_dpram_len = cpu_to_be16(cfg->output_dpram),
- .output_total_len = cpu_to_be16(cfg->output_total),
- .notif_config = cpu_to_be16(0x000F),
- .wd_val = cpu_to_be16(0),
- };
-
- switch (cfg->offl_mode) {
- case FIELDBUS_DEV_OFFL_MODE_CLEAR:
- op_mode = 0;
- break;
- case FIELDBUS_DEV_OFFL_MODE_FREEZE:
- op_mode = OP_MODE_FBFC;
- break;
- case FIELDBUS_DEV_OFFL_MODE_SET:
- op_mode = OP_MODE_FBS;
- break;
- default:
- return -EINVAL;
- }
- msg.op_mode = cpu_to_be16(op_mode | OP_MODE_CD);
- ret = _anybus_mbox_cmd(cd, CMD_START_INIT, false, NULL, 0,
- NULL, 0, NULL, 0);
- if (ret)
- return ret;
- return _anybus_mbox_cmd(cd, CMD_ANYBUS_INIT, false,
- &msg, sizeof(msg), NULL, 0, NULL, 0);
-}
-EXPORT_SYMBOL_GPL(anybuss_start_init);
-
-int anybuss_finish_init(struct anybuss_client *client)
-{
- struct anybuss_host *cd = client->host;
-
- return _anybus_mbox_cmd(cd, CMD_END_INIT, false, NULL, 0,
- NULL, 0, NULL, 0);
-}
-EXPORT_SYMBOL_GPL(anybuss_finish_init);
-
-int anybuss_read_fbctrl(struct anybuss_client *client, u16 addr,
- void *buf, size_t count)
-{
- struct anybuss_host *cd = client->host;
- struct ab_task *t;
- int ret;
-
- if (count == 0)
- return 0;
- if (!area_range_ok(addr, count, FBCTRL_AREA,
- MAX_FBCTRL_AREA_SZ))
- return -EFAULT;
- t = create_area_reader(cd->qcache, IND_AX_FBCTRL, addr, count);
- if (!t)
- return -ENOMEM;
- ret = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq);
- if (ret)
- goto out;
- memcpy(buf, t->area_pd.buf, count);
-out:
- ab_task_put(t);
- return ret;
-}
-EXPORT_SYMBOL_GPL(anybuss_read_fbctrl);
-
-int anybuss_write_input(struct anybuss_client *client,
- const char __user *buf, size_t size,
- loff_t *offset)
-{
- ssize_t len = min_t(loff_t, MAX_DATA_AREA_SZ - *offset, size);
- struct anybuss_host *cd = client->host;
- struct ab_task *t;
- int ret;
-
- if (len <= 0)
- return 0;
- t = create_area_user_writer(cd->qcache, IND_AX_IN,
- DATA_IN_AREA + *offset, buf, len);
- if (IS_ERR(t))
- return PTR_ERR(t);
- ret = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq);
- ab_task_put(t);
- if (ret)
- return ret;
- /* success */
- *offset += len;
- return len;
-}
-EXPORT_SYMBOL_GPL(anybuss_write_input);
-
-int anybuss_read_output(struct anybuss_client *client,
- char __user *buf, size_t size,
- loff_t *offset)
-{
- ssize_t len = min_t(loff_t, MAX_DATA_AREA_SZ - *offset, size);
- struct anybuss_host *cd = client->host;
- struct ab_task *t;
- int ret;
-
- if (len <= 0)
- return 0;
- t = create_area_reader(cd->qcache, IND_AX_OUT,
- DATA_OUT_AREA + *offset, len);
- if (!t)
- return -ENOMEM;
- ret = ab_task_enqueue_wait(t, cd->powerq, &cd->qlock, &cd->wq);
- if (ret)
- goto out;
- if (copy_to_user(buf, t->area_pd.buf, len))
- ret = -EFAULT;
-out:
- ab_task_put(t);
- if (ret)
- return ret;
- /* success */
- *offset += len;
- return len;
-}
-EXPORT_SYMBOL_GPL(anybuss_read_output);
-
-int anybuss_send_msg(struct anybuss_client *client, u16 cmd_num,
- const void *buf, size_t count)
-{
- struct anybuss_host *cd = client->host;
-
- return _anybus_mbox_cmd(cd, cmd_num, true, buf, count, NULL, 0,
- NULL, 0);
-}
-EXPORT_SYMBOL_GPL(anybuss_send_msg);
-
-int anybuss_send_ext(struct anybuss_client *client, u16 cmd_num,
- const void *buf, size_t count)
-{
- struct anybuss_host *cd = client->host;
-
- return _anybus_mbox_cmd(cd, cmd_num, true, NULL, 0, NULL, 0,
- buf, count);
-}
-EXPORT_SYMBOL_GPL(anybuss_send_ext);
-
-int anybuss_recv_msg(struct anybuss_client *client, u16 cmd_num,
- void *buf, size_t count)
-{
- struct anybuss_host *cd = client->host;
-
- return _anybus_mbox_cmd(cd, cmd_num, true, NULL, 0, buf, count,
- NULL, 0);
-}
-EXPORT_SYMBOL_GPL(anybuss_recv_msg);
-
-/* ------------------------ bus functions ------------------------ */
-
-static int anybus_bus_match(struct device *dev,
- const struct device_driver *drv)
-{
- const struct anybuss_client_driver *adrv =
- to_anybuss_client_driver(drv);
- struct anybuss_client *adev =
- to_anybuss_client(dev);
-
- return adrv->anybus_id == be16_to_cpu(adev->anybus_id);
-}
-
-static int anybus_bus_probe(struct device *dev)
-{
- struct anybuss_client_driver *adrv =
- to_anybuss_client_driver(dev->driver);
- struct anybuss_client *adev =
- to_anybuss_client(dev);
-
- return adrv->probe(adev);
-}
-
-static void anybus_bus_remove(struct device *dev)
-{
- struct anybuss_client_driver *adrv =
- to_anybuss_client_driver(dev->driver);
-
- if (adrv->remove)
- adrv->remove(to_anybuss_client(dev));
-}
-
-static const struct bus_type anybus_bus = {
- .name = "anybuss",
- .match = anybus_bus_match,
- .probe = anybus_bus_probe,
- .remove = anybus_bus_remove,
-};
-
-int anybuss_client_driver_register(struct anybuss_client_driver *drv)
-{
- if (!drv->probe)
- return -ENODEV;
-
- drv->driver.bus = &anybus_bus;
- return driver_register(&drv->driver);
-}
-EXPORT_SYMBOL_GPL(anybuss_client_driver_register);
-
-void anybuss_client_driver_unregister(struct anybuss_client_driver *drv)
-{
- return driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL_GPL(anybuss_client_driver_unregister);
-
-static void client_device_release(struct device *dev)
-{
- kfree(to_anybuss_client(dev));
-}
-
-static int taskq_alloc(struct device *dev, struct kfifo *q)
-{
- void *buf;
- size_t size = 64 * sizeof(struct ab_task *);
-
- buf = devm_kzalloc(dev, size, GFP_KERNEL);
- if (!buf)
- return -EIO;
- return kfifo_init(q, buf, size);
-}
-
-static int anybus_of_get_host_idx(struct device_node *np)
-{
- const __be32 *host_idx;
-
- host_idx = of_get_address(np, 0, NULL, NULL);
- if (!host_idx)
- return -ENOENT;
- return __be32_to_cpu(*host_idx);
-}
-
-static struct device_node *
-anybus_of_find_child_device(struct device *dev, int host_idx)
-{
- struct device_node *node;
-
- if (!dev || !dev->of_node)
- return NULL;
- for_each_child_of_node(dev->of_node, node) {
- if (anybus_of_get_host_idx(node) == host_idx)
- return node;
- }
- return NULL;
-}
-
-struct anybuss_host * __must_check
-anybuss_host_common_probe(struct device *dev,
- const struct anybuss_ops *ops)
-{
- int ret, i;
- u8 val[4];
- __be16 fieldbus_type;
- struct anybuss_host *cd;
-
- cd = devm_kzalloc(dev, sizeof(*cd), GFP_KERNEL);
- if (!cd)
- return ERR_PTR(-ENOMEM);
- cd->dev = dev;
- cd->host_idx = ops->host_idx;
- init_completion(&cd->card_boot);
- init_waitqueue_head(&cd->wq);
- for (i = 0; i < ARRAY_SIZE(cd->qs); i++) {
- ret = taskq_alloc(dev, &cd->qs[i]);
- if (ret)
- return ERR_PTR(ret);
- }
- if (WARN_ON(ARRAY_SIZE(cd->qs) < 3))
- return ERR_PTR(-EINVAL);
- cd->powerq = &cd->qs[0];
- cd->mboxq = &cd->qs[1];
- cd->areaq = &cd->qs[2];
- cd->reset = ops->reset;
- if (!cd->reset)
- return ERR_PTR(-EINVAL);
- cd->regmap = ops->regmap;
- if (!cd->regmap)
- return ERR_PTR(-EINVAL);
- spin_lock_init(&cd->qlock);
- cd->qcache = kmem_cache_create(dev_name(dev),
- sizeof(struct ab_task), 0, 0, NULL);
- if (!cd->qcache)
- return ERR_PTR(-ENOMEM);
- cd->irq = ops->irq;
- if (cd->irq <= 0) {
- ret = -EINVAL;
- goto err_qcache;
- }
- /*
- * use a dpram test to check if a card is present, this is only
- * possible while in reset.
- */
- reset_assert(cd);
- if (test_dpram(cd->regmap)) {
- dev_err(dev, "no Anybus-S card in slot");
- ret = -ENODEV;
- goto err_qcache;
- }
- ret = devm_request_threaded_irq(dev, cd->irq, NULL, irq_handler,
- IRQF_ONESHOT, dev_name(dev), cd);
- if (ret) {
- dev_err(dev, "could not request irq");
- goto err_qcache;
- }
- /*
- * startup sequence:
- * a) perform dummy IND_AB read to prevent false 'init done' irq
- * (already done by test_dpram() above)
- * b) release reset
- * c) wait for first interrupt
- * d) interrupt came in: ready to go !
- */
- reset_deassert(cd);
- if (!wait_for_completion_timeout(&cd->card_boot, TIMEOUT)) {
- ret = -ETIMEDOUT;
- goto err_reset;
- }
- /*
- * according to the anybus docs, we're allowed to read these
- * without handshaking / reserving the area
- */
- dev_info(dev, "Anybus-S card detected");
- regmap_bulk_read(cd->regmap, REG_BOOTLOADER_V, val, 2);
- dev_info(dev, "Bootloader version: %02X%02X",
- val[0], val[1]);
- regmap_bulk_read(cd->regmap, REG_API_V, val, 2);
- dev_info(dev, "API version: %02X%02X", val[0], val[1]);
- regmap_bulk_read(cd->regmap, REG_FIELDBUS_V, val, 2);
- dev_info(dev, "Fieldbus version: %02X%02X", val[0], val[1]);
- regmap_bulk_read(cd->regmap, REG_SERIAL_NO, val, 4);
- dev_info(dev, "Serial number: %02X%02X%02X%02X",
- val[0], val[1], val[2], val[3]);
- add_device_randomness(&val, 4);
- regmap_bulk_read(cd->regmap, REG_FIELDBUS_TYPE, &fieldbus_type,
- sizeof(fieldbus_type));
- dev_info(dev, "Fieldbus type: %04X", be16_to_cpu(fieldbus_type));
- regmap_bulk_read(cd->regmap, REG_MODULE_SW_V, val, 2);
- dev_info(dev, "Module SW version: %02X%02X",
- val[0], val[1]);
- /* put card back reset until a client driver releases it */
- disable_irq(cd->irq);
- reset_assert(cd);
- atomic_set(&cd->ind_ab, IND_AB_UPDATED);
- /* fire up the queue thread */
- cd->qthread = kthread_run(qthread_fn, cd, dev_name(dev));
- if (IS_ERR(cd->qthread)) {
- dev_err(dev, "could not create kthread");
- ret = PTR_ERR(cd->qthread);
- goto err_reset;
- }
- /*
- * now advertise that we've detected a client device (card).
- * the bus infrastructure will match it to a client driver.
- */
- cd->client = kzalloc(sizeof(*cd->client), GFP_KERNEL);
- if (!cd->client) {
- ret = -ENOMEM;
- goto err_kthread;
- }
- cd->client->anybus_id = fieldbus_type;
- cd->client->host = cd;
- cd->client->dev.bus = &anybus_bus;
- cd->client->dev.parent = dev;
- cd->client->dev.release = client_device_release;
- cd->client->dev.of_node =
- anybus_of_find_child_device(dev, cd->host_idx);
- dev_set_name(&cd->client->dev, "anybuss.card%d", cd->host_idx);
- ret = device_register(&cd->client->dev);
- if (ret)
- goto err_device;
- return cd;
-err_device:
- put_device(&cd->client->dev);
-err_kthread:
- kthread_stop(cd->qthread);
-err_reset:
- reset_assert(cd);
-err_qcache:
- kmem_cache_destroy(cd->qcache);
- return ERR_PTR(ret);
-}
-EXPORT_SYMBOL_GPL(anybuss_host_common_probe);
-
-void anybuss_host_common_remove(struct anybuss_host *host)
-{
- struct anybuss_host *cd = host;
-
- device_unregister(&cd->client->dev);
- kthread_stop(cd->qthread);
- reset_assert(cd);
- kmem_cache_destroy(cd->qcache);
-}
-EXPORT_SYMBOL_GPL(anybuss_host_common_remove);
-
-static void host_release(void *res)
-{
- anybuss_host_common_remove(res);
-}
-
-struct anybuss_host * __must_check
-devm_anybuss_host_common_probe(struct device *dev,
- const struct anybuss_ops *ops)
-{
- struct anybuss_host *host;
- int ret;
-
- host = anybuss_host_common_probe(dev, ops);
- if (IS_ERR(host))
- return host;
-
- ret = devm_add_action_or_reset(dev, host_release, host);
- if (ret)
- return ERR_PTR(ret);
-
- return host;
-}
-EXPORT_SYMBOL_GPL(devm_anybuss_host_common_probe);
-
-static int __init anybus_init(void)
-{
- int ret;
-
- ret = bus_register(&anybus_bus);
- if (ret)
- pr_err("could not register Anybus-S bus: %d\n", ret);
- return ret;
-}
-module_init(anybus_init);
-
-static void __exit anybus_exit(void)
-{
- bus_unregister(&anybus_bus);
-}
-module_exit(anybus_exit);
-
-MODULE_DESCRIPTION("HMS Anybus-S Host Driver");
-MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/fieldbus/dev_core.c b/drivers/staging/fieldbus/dev_core.c
deleted file mode 100644
index 0053ebd91442..000000000000
--- a/drivers/staging/fieldbus/dev_core.c
+++ /dev/null
@@ -1,344 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Fieldbus Device Driver Core
- *
- */
-
-#include <linux/mutex.h>
-#include <linux/module.h>
-#include <linux/device.h>
-#include <linux/idr.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-#include <linux/poll.h>
-
-/* move to <linux/fieldbus_dev.h> when taking this out of staging */
-#include "fieldbus_dev.h"
-
-/* Maximum number of fieldbus devices */
-#define MAX_FIELDBUSES 32
-
-/* the dev_t structure to store the dynamically allocated fieldbus devices */
-static dev_t fieldbus_devt;
-static DEFINE_IDA(fieldbus_ida);
-static DEFINE_MUTEX(fieldbus_mtx);
-
-static ssize_t online_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%d\n", !!fb->online);
-}
-static DEVICE_ATTR_RO(online);
-
-static ssize_t enabled_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- if (!fb->enable_get)
- return -EINVAL;
- return sysfs_emit(buf, "%d\n", !!fb->enable_get(fb));
-}
-
-static ssize_t enabled_store(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t n)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
- bool value;
- int ret;
-
- if (!fb->simple_enable_set)
- return -ENOTSUPP;
- ret = kstrtobool(buf, &value);
- if (ret)
- return ret;
- ret = fb->simple_enable_set(fb, value);
- if (ret < 0)
- return ret;
- return n;
-}
-static DEVICE_ATTR_RW(enabled);
-
-static ssize_t card_name_show(struct device *dev, struct device_attribute *attr,
- char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- /* card_name was provided by child driver. */
- return sysfs_emit(buf, "%s\n", fb->card_name);
-}
-static DEVICE_ATTR_RO(card_name);
-
-static ssize_t read_area_size_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%zu\n", fb->read_area_sz);
-}
-static DEVICE_ATTR_RO(read_area_size);
-
-static ssize_t write_area_size_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- return sysfs_emit(buf, "%zu\n", fb->write_area_sz);
-}
-static DEVICE_ATTR_RO(write_area_size);
-
-static ssize_t fieldbus_id_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
-
- return fb->fieldbus_id_get(fb, buf, PAGE_SIZE);
-}
-static DEVICE_ATTR_RO(fieldbus_id);
-
-static ssize_t fieldbus_type_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
- const char *t;
-
- switch (fb->fieldbus_type) {
- case FIELDBUS_DEV_TYPE_PROFINET:
- t = "profinet";
- break;
- default:
- t = "unknown";
- break;
- }
-
- return sysfs_emit(buf, "%s\n", t);
-}
-static DEVICE_ATTR_RO(fieldbus_type);
-
-static struct attribute *fieldbus_attrs[] = {
- &dev_attr_enabled.attr,
- &dev_attr_card_name.attr,
- &dev_attr_fieldbus_id.attr,
- &dev_attr_read_area_size.attr,
- &dev_attr_write_area_size.attr,
- &dev_attr_online.attr,
- &dev_attr_fieldbus_type.attr,
- NULL,
-};
-
-static umode_t fieldbus_is_visible(struct kobject *kobj, struct attribute *attr,
- int n)
-{
- struct device *dev = kobj_to_dev(kobj);
- struct fieldbus_dev *fb = dev_get_drvdata(dev);
- umode_t mode = attr->mode;
-
- if (attr == &dev_attr_enabled.attr) {
- mode = 0;
- if (fb->enable_get)
- mode |= 0444;
- if (fb->simple_enable_set)
- mode |= 0200;
- }
-
- return mode;
-}
-
-static const struct attribute_group fieldbus_group = {
- .attrs = fieldbus_attrs,
- .is_visible = fieldbus_is_visible,
-};
-__ATTRIBUTE_GROUPS(fieldbus);
-
-static const struct class fieldbus_class = {
- .name = "fieldbus_dev",
- .dev_groups = fieldbus_groups,
-};
-
-struct fb_open_file {
- struct fieldbus_dev *fbdev;
- int dc_event;
-};
-
-static int fieldbus_open(struct inode *inode, struct file *filp)
-{
- struct fb_open_file *of;
- struct fieldbus_dev *fbdev = container_of(inode->i_cdev,
- struct fieldbus_dev,
- cdev);
-
- of = kzalloc(sizeof(*of), GFP_KERNEL);
- if (!of)
- return -ENOMEM;
- of->fbdev = fbdev;
- filp->private_data = of;
- return 0;
-}
-
-static int fieldbus_release(struct inode *node, struct file *filp)
-{
- struct fb_open_file *of = filp->private_data;
-
- kfree(of);
- return 0;
-}
-
-static ssize_t fieldbus_read(struct file *filp, char __user *buf, size_t size,
- loff_t *offset)
-{
- struct fb_open_file *of = filp->private_data;
- struct fieldbus_dev *fbdev = of->fbdev;
-
- of->dc_event = fbdev->dc_event;
- return fbdev->read_area(fbdev, buf, size, offset);
-}
-
-static ssize_t fieldbus_write(struct file *filp, const char __user *buf,
- size_t size, loff_t *offset)
-{
- struct fb_open_file *of = filp->private_data;
- struct fieldbus_dev *fbdev = of->fbdev;
-
- return fbdev->write_area(fbdev, buf, size, offset);
-}
-
-static __poll_t fieldbus_poll(struct file *filp, poll_table *wait)
-{
- struct fb_open_file *of = filp->private_data;
- struct fieldbus_dev *fbdev = of->fbdev;
- __poll_t mask = EPOLLIN | EPOLLRDNORM | EPOLLOUT | EPOLLWRNORM;
-
- poll_wait(filp, &fbdev->dc_wq, wait);
- /* data changed ? */
- if (fbdev->dc_event != of->dc_event)
- mask |= EPOLLPRI | EPOLLERR;
- return mask;
-}
-
-static const struct file_operations fieldbus_fops = {
- .open = fieldbus_open,
- .release = fieldbus_release,
- .read = fieldbus_read,
- .write = fieldbus_write,
- .poll = fieldbus_poll,
- .llseek = generic_file_llseek,
- .owner = THIS_MODULE,
-};
-
-void fieldbus_dev_area_updated(struct fieldbus_dev *fb)
-{
- fb->dc_event++;
- wake_up_all(&fb->dc_wq);
-}
-EXPORT_SYMBOL_GPL(fieldbus_dev_area_updated);
-
-void fieldbus_dev_online_changed(struct fieldbus_dev *fb, bool online)
-{
- fb->online = online;
- kobject_uevent(&fb->dev->kobj, KOBJ_CHANGE);
-}
-EXPORT_SYMBOL_GPL(fieldbus_dev_online_changed);
-
-static void __fieldbus_dev_unregister(struct fieldbus_dev *fb)
-{
- if (!fb)
- return;
- device_destroy(&fieldbus_class, fb->cdev.dev);
- cdev_del(&fb->cdev);
- ida_free(&fieldbus_ida, fb->id);
-}
-
-void fieldbus_dev_unregister(struct fieldbus_dev *fb)
-{
- mutex_lock(&fieldbus_mtx);
- __fieldbus_dev_unregister(fb);
- mutex_unlock(&fieldbus_mtx);
-}
-EXPORT_SYMBOL_GPL(fieldbus_dev_unregister);
-
-static int __fieldbus_dev_register(struct fieldbus_dev *fb)
-{
- dev_t devno;
- int err;
-
- if (!fb)
- return -EINVAL;
- if (!fb->read_area || !fb->write_area || !fb->fieldbus_id_get)
- return -EINVAL;
- fb->id = ida_alloc_max(&fieldbus_ida, MAX_FIELDBUSES - 1, GFP_KERNEL);
- if (fb->id < 0)
- return fb->id;
- devno = MKDEV(MAJOR(fieldbus_devt), fb->id);
- init_waitqueue_head(&fb->dc_wq);
- cdev_init(&fb->cdev, &fieldbus_fops);
- err = cdev_add(&fb->cdev, devno, 1);
- if (err) {
- pr_err("fieldbus_dev%d unable to add device %d:%d\n",
- fb->id, MAJOR(fieldbus_devt), fb->id);
- goto err_cdev;
- }
- fb->dev = device_create(&fieldbus_class, fb->parent, devno, fb,
- "fieldbus_dev%d", fb->id);
- if (IS_ERR(fb->dev)) {
- err = PTR_ERR(fb->dev);
- goto err_dev_create;
- }
- return 0;
-
-err_dev_create:
- cdev_del(&fb->cdev);
-err_cdev:
- ida_free(&fieldbus_ida, fb->id);
- return err;
-}
-
-int fieldbus_dev_register(struct fieldbus_dev *fb)
-{
- int err;
-
- mutex_lock(&fieldbus_mtx);
- err = __fieldbus_dev_register(fb);
- mutex_unlock(&fieldbus_mtx);
-
- return err;
-}
-EXPORT_SYMBOL_GPL(fieldbus_dev_register);
-
-static int __init fieldbus_init(void)
-{
- int err;
-
- err = class_register(&fieldbus_class);
- if (err < 0) {
- pr_err("fieldbus_dev: could not register class\n");
- return err;
- }
- err = alloc_chrdev_region(&fieldbus_devt, 0,
- MAX_FIELDBUSES, "fieldbus_dev");
- if (err < 0) {
- pr_err("fieldbus_dev: unable to allocate char dev region\n");
- goto err_alloc;
- }
- return 0;
-
-err_alloc:
- class_unregister(&fieldbus_class);
- return err;
-}
-
-static void __exit fieldbus_exit(void)
-{
- unregister_chrdev_region(fieldbus_devt, MAX_FIELDBUSES);
- class_unregister(&fieldbus_class);
- ida_destroy(&fieldbus_ida);
-}
-
-subsys_initcall(fieldbus_init);
-module_exit(fieldbus_exit);
-
-MODULE_AUTHOR("Sven Van Asbroeck <TheSven73@gmail.com>");
-MODULE_AUTHOR("Jonathan Stiles <jonathans@arcx.com>");
-MODULE_DESCRIPTION("Fieldbus Device Driver Core");
-MODULE_LICENSE("GPL v2");
diff --git a/drivers/staging/fieldbus/fieldbus_dev.h b/drivers/staging/fieldbus/fieldbus_dev.h
deleted file mode 100644
index 301dca3b8d71..000000000000
--- a/drivers/staging/fieldbus/fieldbus_dev.h
+++ /dev/null
@@ -1,114 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Fieldbus Device Driver Core
- *
- */
-
-#ifndef __FIELDBUS_DEV_H
-#define __FIELDBUS_DEV_H
-
-#include <linux/cdev.h>
-#include <linux/wait.h>
-
-enum fieldbus_dev_type {
- FIELDBUS_DEV_TYPE_UNKNOWN = 0,
- FIELDBUS_DEV_TYPE_PROFINET,
-};
-
-enum fieldbus_dev_offl_mode {
- FIELDBUS_DEV_OFFL_MODE_CLEAR = 0,
- FIELDBUS_DEV_OFFL_MODE_FREEZE,
- FIELDBUS_DEV_OFFL_MODE_SET
-};
-
-/**
- * struct fieldbus_dev - Fieldbus device
- * @read_area: [DRIVER] function to read the process data area of the
- * device. same parameters/return values as
- * the read function in struct file_operations
- * @write_area: [DRIVER] function to write to the process data area of
- * the device. same parameters/return values as
- * the write function in struct file_operations
- * @write_area_sz [DRIVER] size of the writable process data area
- * @read_area_sz [DRIVER] size of the readable process data area
- * @card_name [DRIVER] name of the card, e.g. "ACME Inc. profinet"
- * @fieldbus_type [DRIVER] fieldbus type of this device, e.g.
- * FIELDBUS_DEV_TYPE_PROFINET
- * @enable_get [DRIVER] function which returns true if the card
- * is enabled, false otherwise
- * @fieldbus_id_get [DRIVER] function to retrieve the unique fieldbus id
- * by which this device can be identified;
- * return value follows the snprintf convention
- * @simple_enable_set [DRIVER] (optional) function to enable the device
- * according to its default settings
- * @parent [DRIVER] (optional) the device's parent device
- */
-struct fieldbus_dev {
- ssize_t (*read_area)(struct fieldbus_dev *fbdev, char __user *buf,
- size_t size, loff_t *offset);
- ssize_t (*write_area)(struct fieldbus_dev *fbdev,
- const char __user *buf, size_t size,
- loff_t *offset);
- size_t write_area_sz, read_area_sz;
- const char *card_name;
- enum fieldbus_dev_type fieldbus_type;
- bool (*enable_get)(struct fieldbus_dev *fbdev);
- int (*fieldbus_id_get)(struct fieldbus_dev *fbdev, char *buf,
- size_t max_size);
- int (*simple_enable_set)(struct fieldbus_dev *fbdev, bool enable);
- struct device *parent;
-
- /* private data */
- int id;
- struct cdev cdev;
- struct device *dev;
- int dc_event;
- wait_queue_head_t dc_wq;
- bool online;
-};
-
-#if IS_ENABLED(CONFIG_FIELDBUS_DEV)
-
-/**
- * fieldbus_dev_unregister()
- * - unregister a previously registered fieldbus device
- * @fb: Device structure previously registered
- **/
-void fieldbus_dev_unregister(struct fieldbus_dev *fb);
-
-/**
- * fieldbus_dev_register()
- * - register a device with the fieldbus device subsystem
- * @fb: Device structure filled by the device driver
- **/
-int __must_check fieldbus_dev_register(struct fieldbus_dev *fb);
-
-/**
- * fieldbus_dev_area_updated()
- * - notify the subsystem that an external fieldbus controller updated
- * the process data area
- * @fb: Device structure
- **/
-void fieldbus_dev_area_updated(struct fieldbus_dev *fb);
-
-/**
- * fieldbus_dev_online_changed()
- * - notify the subsystem that the fieldbus online status changed
- * @fb: Device structure
- **/
-void fieldbus_dev_online_changed(struct fieldbus_dev *fb, bool online);
-
-#else /* IS_ENABLED(CONFIG_FIELDBUS_DEV) */
-
-static inline void fieldbus_dev_unregister(struct fieldbus_dev *fb) {}
-static inline int __must_check fieldbus_dev_register(struct fieldbus_dev *fb)
-{
- return -ENOTSUPP;
-}
-
-static inline void fieldbus_dev_area_updated(struct fieldbus_dev *fb) {}
-static inline void fieldbus_dev_online_changed(struct fieldbus_dev *fb,
- bool online) {}
-
-#endif /* IS_ENABLED(CONFIG_FIELDBUS_DEV) */
-#endif /* __FIELDBUS_DEV_H */
diff --git a/drivers/staging/gdm724x/Kconfig b/drivers/staging/gdm724x/Kconfig
deleted file mode 100644
index 1f403ecd9608..000000000000
--- a/drivers/staging/gdm724x/Kconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-#
-# GCT GDM724x LTE driver configuration
-#
-
-config LTE_GDM724X
- tristate "GCT GDM724x LTE support"
- depends on NET && USB && TTY && m
- help
- This driver supports GCT GDM724x LTE chip based USB modem devices.
- It exposes 4 network devices to be used per PDN and 2 tty devices to be
- used for AT commands and DM monitoring applications.
- The modules will be called gdmulte.ko and gdmtty.ko
-
- GCT-ATCx can be used for AT Commands
- GCT-DMx can be used for LTE protocol monitoring
diff --git a/drivers/staging/gdm724x/Makefile b/drivers/staging/gdm724x/Makefile
deleted file mode 100644
index e61b95788c9f..000000000000
--- a/drivers/staging/gdm724x/Makefile
+++ /dev/null
@@ -1,8 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_LTE_GDM724X) := gdmulte.o
-gdmulte-y += gdm_lte.o netlink_k.o
-gdmulte-y += gdm_usb.o gdm_endian.o
-
-obj-$(CONFIG_LTE_GDM724X) += gdmtty.o
-gdmtty-y := gdm_tty.o gdm_mux.o
-
diff --git a/drivers/staging/gdm724x/TODO b/drivers/staging/gdm724x/TODO
deleted file mode 100644
index b2b571ecb063..000000000000
--- a/drivers/staging/gdm724x/TODO
+++ /dev/null
@@ -1,16 +0,0 @@
-TODO:
-- Clean up coding style to meet kernel standard. (80 line limit, netdev_err)
-- Remove test for host endian
-- Remove confusing macros (endian, hci_send, sdu_send, rcv_with_cb)
-- Fixes for every instances of function returning -1
-- Check for skb->len in gdm_lte_emulate_arp()
-- Use ALIGN() macro for dummy_cnt in up_to_host()
-- Error handling in init_usb()
-- Explain reason for multiples of 512 bytes in alloc_tx_struct()
-- Review use of atomic allocation for tx structs
-- No error checking for alloc_tx_struct in do_tx()
-- fix up static tty port allocation to be dynamic
-
-Patches to:
- Jonathan Kim <jonathankim@gctsemi.com>
- Dean ahn <deanahn@gctsemi.com>
diff --git a/drivers/staging/gdm724x/gdm_endian.c b/drivers/staging/gdm724x/gdm_endian.c
deleted file mode 100644
index ae39e59daf70..000000000000
--- a/drivers/staging/gdm724x/gdm_endian.c
+++ /dev/null
@@ -1,37 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#include <linux/kernel.h>
-#include "gdm_endian.h"
-
-__dev16 gdm_cpu_to_dev16(u8 dev_ed, u16 x)
-{
- if (dev_ed == ENDIANNESS_LITTLE)
- return (__force __dev16)cpu_to_le16(x);
- else
- return (__force __dev16)cpu_to_be16(x);
-}
-
-u16 gdm_dev16_to_cpu(u8 dev_ed, __dev16 x)
-{
- if (dev_ed == ENDIANNESS_LITTLE)
- return le16_to_cpu((__force __le16)x);
- else
- return be16_to_cpu((__force __be16)x);
-}
-
-__dev32 gdm_cpu_to_dev32(u8 dev_ed, u32 x)
-{
- if (dev_ed == ENDIANNESS_LITTLE)
- return (__force __dev32)cpu_to_le32(x);
- else
- return (__force __dev32)cpu_to_be32(x);
-}
-
-u32 gdm_dev32_to_cpu(u8 dev_ed, __dev32 x)
-{
- if (dev_ed == ENDIANNESS_LITTLE)
- return le32_to_cpu((__force __le32)x);
- else
- return be32_to_cpu((__force __be32)x);
-}
diff --git a/drivers/staging/gdm724x/gdm_endian.h b/drivers/staging/gdm724x/gdm_endian.h
deleted file mode 100644
index f373dc3a19bf..000000000000
--- a/drivers/staging/gdm724x/gdm_endian.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef __GDM_ENDIAN_H__
-#define __GDM_ENDIAN_H__
-
-#include <linux/types.h>
-
-/*
- * For data in "device-endian" byte order (device endianness is model
- * dependent). Analogous to __leXX or __beXX.
- */
-typedef __u32 __bitwise __dev32;
-typedef __u16 __bitwise __dev16;
-
-enum {
- ENDIANNESS_MIN = 0,
- ENDIANNESS_UNKNOWN,
- ENDIANNESS_LITTLE,
- ENDIANNESS_BIG,
- ENDIANNESS_MIDDLE,
- ENDIANNESS_MAX
-};
-
-__dev16 gdm_cpu_to_dev16(u8 dev_ed, u16 x);
-u16 gdm_dev16_to_cpu(u8 dev_ed, __dev16 x);
-__dev32 gdm_cpu_to_dev32(u8 dev_ed, u32 x);
-u32 gdm_dev32_to_cpu(u8 dev_ed, __dev32 x);
-
-#endif /*__GDM_ENDIAN_H__*/
diff --git a/drivers/staging/gdm724x/gdm_lte.c b/drivers/staging/gdm724x/gdm_lte.c
deleted file mode 100644
index eb754b231429..000000000000
--- a/drivers/staging/gdm724x/gdm_lte.c
+++ /dev/null
@@ -1,937 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/etherdevice.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/udp.h>
-#include <linux/in.h>
-#include <linux/if_arp.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <linux/in6.h>
-#include <linux/tcp.h>
-#include <linux/icmp.h>
-#include <linux/icmpv6.h>
-#include <linux/uaccess.h>
-#include <linux/errno.h>
-#include <net/ndisc.h>
-
-#include "gdm_lte.h"
-#include "netlink_k.h"
-#include "hci.h"
-#include "hci_packet.h"
-#include "gdm_endian.h"
-
-/*
- * Netlink protocol number
- */
-#define NETLINK_LTE 30
-
-/*
- * Default MTU Size
- */
-#define DEFAULT_MTU_SIZE 1500
-
-#define IP_VERSION_4 4
-#define IP_VERSION_6 6
-
-static struct {
- int ref_cnt;
- struct sock *sock;
-} lte_event;
-
-static const struct device_type wwan_type = {
- .name = "wwan",
-};
-
-static int gdm_lte_open(struct net_device *dev)
-{
- netif_start_queue(dev);
- return 0;
-}
-
-static int gdm_lte_close(struct net_device *dev)
-{
- netif_stop_queue(dev);
- return 0;
-}
-
-static int gdm_lte_set_config(struct net_device *dev, struct ifmap *map)
-{
- if (dev->flags & IFF_UP)
- return -EBUSY;
- return 0;
-}
-
-static void tx_complete(void *arg)
-{
- struct nic *nic = arg;
-
- if (netif_queue_stopped(nic->netdev))
- netif_wake_queue(nic->netdev);
-}
-
-static int gdm_lte_rx(struct sk_buff *skb, struct nic *nic, int nic_type)
-{
- int ret, len;
-
- len = skb->len + ETH_HLEN;
- ret = netif_rx(skb);
- if (ret == NET_RX_DROP) {
- nic->stats.rx_dropped++;
- } else {
- nic->stats.rx_packets++;
- nic->stats.rx_bytes += len;
- }
-
- return 0;
-}
-
-static int gdm_lte_emulate_arp(struct sk_buff *skb_in, u32 nic_type)
-{
- struct nic *nic = netdev_priv(skb_in->dev);
- struct sk_buff *skb_out;
- struct ethhdr eth;
- struct vlan_ethhdr vlan_eth;
- struct arphdr *arp_in;
- struct arphdr *arp_out;
- struct arpdata {
- u8 ar_sha[ETH_ALEN];
- u8 ar_sip[4];
- u8 ar_tha[ETH_ALEN];
- u8 ar_tip[4];
- };
- struct arpdata *arp_data_in;
- struct arpdata *arp_data_out;
- u8 arp_temp[60];
- void *mac_header_data;
- u32 mac_header_len;
-
- /* Check for skb->len, discard if empty */
- if (skb_in->len == 0)
- return -ENODATA;
-
- /* Format the mac header so that it can be put to skb */
- if (ntohs(((struct ethhdr *)skb_in->data)->h_proto) == ETH_P_8021Q) {
- memcpy(&vlan_eth, skb_in->data, sizeof(struct vlan_ethhdr));
- mac_header_data = &vlan_eth;
- mac_header_len = VLAN_ETH_HLEN;
- } else {
- memcpy(&eth, skb_in->data, sizeof(struct ethhdr));
- mac_header_data = &eth;
- mac_header_len = ETH_HLEN;
- }
-
- /* Get the pointer of the original request */
- arp_in = (struct arphdr *)(skb_in->data + mac_header_len);
- arp_data_in = (struct arpdata *)(skb_in->data + mac_header_len +
- sizeof(struct arphdr));
-
- /* Get the pointer of the outgoing response */
- arp_out = (struct arphdr *)arp_temp;
- arp_data_out = (struct arpdata *)(arp_temp + sizeof(struct arphdr));
-
- /* Copy the arp header */
- memcpy(arp_out, arp_in, sizeof(struct arphdr));
- arp_out->ar_op = htons(ARPOP_REPLY);
-
- /* Copy the arp payload: based on 2 bytes of mac and fill the IP */
- arp_data_out->ar_sha[0] = arp_data_in->ar_sha[0];
- arp_data_out->ar_sha[1] = arp_data_in->ar_sha[1];
- memcpy(&arp_data_out->ar_sha[2], &arp_data_in->ar_tip[0], 4);
- memcpy(&arp_data_out->ar_sip[0], &arp_data_in->ar_tip[0], 4);
- memcpy(&arp_data_out->ar_tha[0], &arp_data_in->ar_sha[0], 6);
- memcpy(&arp_data_out->ar_tip[0], &arp_data_in->ar_sip[0], 4);
-
- /* Fill the destination mac with source mac of the received packet */
- memcpy(mac_header_data, mac_header_data + ETH_ALEN, ETH_ALEN);
- /* Fill the source mac with nic's source mac */
- memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN);
-
- /* Alloc skb and reserve align */
- skb_out = dev_alloc_skb(skb_in->len);
- if (!skb_out)
- return -ENOMEM;
- skb_reserve(skb_out, NET_IP_ALIGN);
-
- skb_put_data(skb_out, mac_header_data, mac_header_len);
- skb_put_data(skb_out, arp_out, sizeof(struct arphdr));
- skb_put_data(skb_out, arp_data_out, sizeof(struct arpdata));
-
- skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
- skb_out->dev = skb_in->dev;
- skb_reset_mac_header(skb_out);
- skb_pull(skb_out, ETH_HLEN);
-
- gdm_lte_rx(skb_out, nic, nic_type);
-
- return 0;
-}
-
-static __sum16 icmp6_checksum(struct ipv6hdr *ipv6, u16 *ptr, int len)
-{
- unsigned short *w;
- __wsum sum = 0;
- int i;
- u16 pa;
-
- union {
- struct {
- u8 ph_src[16];
- u8 ph_dst[16];
- u32 ph_len;
- u8 ph_zero[3];
- u8 ph_nxt;
- } ph __packed;
- u16 pa[20];
- } pseudo_header;
-
- memset(&pseudo_header, 0, sizeof(pseudo_header));
- memcpy(&pseudo_header.ph.ph_src, &ipv6->saddr.in6_u.u6_addr8, 16);
- memcpy(&pseudo_header.ph.ph_dst, &ipv6->daddr.in6_u.u6_addr8, 16);
- pseudo_header.ph.ph_len = be16_to_cpu(ipv6->payload_len);
- pseudo_header.ph.ph_nxt = ipv6->nexthdr;
-
- for (i = 0; i < ARRAY_SIZE(pseudo_header.pa); i++) {
- pa = pseudo_header.pa[i];
- sum = csum_add(sum, csum_unfold((__force __sum16)pa));
- }
-
- w = ptr;
- while (len > 1) {
- sum = csum_add(sum, csum_unfold((__force __sum16)*w++));
- len -= 2;
- }
-
- return csum_fold(sum);
-}
-
-static int gdm_lte_emulate_ndp(struct sk_buff *skb_in, u32 nic_type)
-{
- struct nic *nic = netdev_priv(skb_in->dev);
- struct sk_buff *skb_out;
- struct ethhdr eth;
- struct vlan_ethhdr vlan_eth;
- struct neighbour_advertisement {
- u8 target_address[16];
- u8 type;
- u8 length;
- u8 link_layer_address[6];
- };
- struct neighbour_advertisement na;
- struct neighbour_solicitation {
- u8 target_address[16];
- };
- struct neighbour_solicitation *ns;
- struct ipv6hdr *ipv6_in;
- struct ipv6hdr ipv6_out;
- struct icmp6hdr *icmp6_in;
- struct icmp6hdr icmp6_out;
-
- void *mac_header_data;
- u32 mac_header_len;
-
- /* Format the mac header so that it can be put to skb */
- if (ntohs(((struct ethhdr *)skb_in->data)->h_proto) == ETH_P_8021Q) {
- memcpy(&vlan_eth, skb_in->data, sizeof(struct vlan_ethhdr));
- if (ntohs(vlan_eth.h_vlan_encapsulated_proto) != ETH_P_IPV6)
- return -EPROTONOSUPPORT;
- mac_header_data = &vlan_eth;
- mac_header_len = VLAN_ETH_HLEN;
- } else {
- memcpy(&eth, skb_in->data, sizeof(struct ethhdr));
- if (ntohs(eth.h_proto) != ETH_P_IPV6)
- return -EPROTONOSUPPORT;
- mac_header_data = &eth;
- mac_header_len = ETH_HLEN;
- }
-
- /* Check if this is IPv6 ICMP packet */
- ipv6_in = (struct ipv6hdr *)(skb_in->data + mac_header_len);
- if (ipv6_in->version != 6 || ipv6_in->nexthdr != IPPROTO_ICMPV6)
- return -EPROTONOSUPPORT;
-
- /* Check if this is NDP packet */
- icmp6_in = (struct icmp6hdr *)(skb_in->data + mac_header_len +
- sizeof(struct ipv6hdr));
- if (icmp6_in->icmp6_type == NDISC_ROUTER_SOLICITATION) { /* Check RS */
- return -EPROTONOSUPPORT;
- } else if (icmp6_in->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
- /* Check NS */
- u8 icmp_na[sizeof(struct icmp6hdr) +
- sizeof(struct neighbour_advertisement)];
- u8 zero_addr8[16] = {0,};
-
- if (memcmp(ipv6_in->saddr.in6_u.u6_addr8, zero_addr8, 16) == 0)
- /* Duplicate Address Detection: Source IP is all zero */
- return 0;
-
- icmp6_out.icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT;
- icmp6_out.icmp6_code = 0;
- icmp6_out.icmp6_cksum = 0;
- /* R=0, S=1, O=1 */
- icmp6_out.icmp6_dataun.un_data32[0] = htonl(0x60000000);
-
- ns = (struct neighbour_solicitation *)
- (skb_in->data + mac_header_len +
- sizeof(struct ipv6hdr) + sizeof(struct icmp6hdr));
- memcpy(&na.target_address, ns->target_address, 16);
- na.type = 0x02;
- na.length = 1;
- na.link_layer_address[0] = 0x00;
- na.link_layer_address[1] = 0x0a;
- na.link_layer_address[2] = 0x3b;
- na.link_layer_address[3] = 0xaf;
- na.link_layer_address[4] = 0x63;
- na.link_layer_address[5] = 0xc7;
-
- memcpy(&ipv6_out, ipv6_in, sizeof(struct ipv6hdr));
- memcpy(ipv6_out.saddr.in6_u.u6_addr8, &na.target_address, 16);
- memcpy(ipv6_out.daddr.in6_u.u6_addr8,
- ipv6_in->saddr.in6_u.u6_addr8, 16);
- ipv6_out.payload_len = htons(sizeof(struct icmp6hdr) +
- sizeof(struct neighbour_advertisement));
-
- memcpy(icmp_na, &icmp6_out, sizeof(struct icmp6hdr));
- memcpy(icmp_na + sizeof(struct icmp6hdr), &na,
- sizeof(struct neighbour_advertisement));
-
- icmp6_out.icmp6_cksum = icmp6_checksum(&ipv6_out,
- (u16 *)icmp_na,
- sizeof(icmp_na));
- } else {
- return -EINVAL;
- }
-
- /* Fill the destination mac with source mac of the received packet */
- memcpy(mac_header_data, mac_header_data + ETH_ALEN, ETH_ALEN);
- /* Fill the source mac with nic's source mac */
- memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN);
-
- /* Alloc skb and reserve align */
- skb_out = dev_alloc_skb(skb_in->len);
- if (!skb_out)
- return -ENOMEM;
- skb_reserve(skb_out, NET_IP_ALIGN);
-
- skb_put_data(skb_out, mac_header_data, mac_header_len);
- skb_put_data(skb_out, &ipv6_out, sizeof(struct ipv6hdr));
- skb_put_data(skb_out, &icmp6_out, sizeof(struct icmp6hdr));
- skb_put_data(skb_out, &na, sizeof(struct neighbour_advertisement));
-
- skb_out->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
- skb_out->dev = skb_in->dev;
- skb_reset_mac_header(skb_out);
- skb_pull(skb_out, ETH_HLEN);
-
- gdm_lte_rx(skb_out, nic, nic_type);
-
- return 0;
-}
-
-static s32 gdm_lte_tx_nic_type(struct net_device *dev, struct sk_buff *skb)
-{
- struct nic *nic = netdev_priv(dev);
- struct ethhdr *eth;
- struct vlan_ethhdr *vlan_eth;
- struct iphdr *ip;
- struct ipv6hdr *ipv6;
- int mac_proto;
- void *network_data;
- u32 nic_type;
-
- /* NIC TYPE is based on the nic_id of this net_device */
- nic_type = 0x00000010 | nic->nic_id;
-
- /* Get ethernet protocol */
- eth = (struct ethhdr *)skb->data;
- if (ntohs(eth->h_proto) == ETH_P_8021Q) {
- vlan_eth = skb_vlan_eth_hdr(skb);
- mac_proto = ntohs(vlan_eth->h_vlan_encapsulated_proto);
- network_data = skb->data + VLAN_ETH_HLEN;
- nic_type |= NIC_TYPE_F_VLAN;
- } else {
- mac_proto = ntohs(eth->h_proto);
- network_data = skb->data + ETH_HLEN;
- }
-
- /* Process packet for nic type */
- switch (mac_proto) {
- case ETH_P_ARP:
- nic_type |= NIC_TYPE_ARP;
- break;
- case ETH_P_IP:
- nic_type |= NIC_TYPE_F_IPV4;
- ip = network_data;
-
- /* Check DHCPv4 */
- if (ip->protocol == IPPROTO_UDP) {
- struct udphdr *udp =
- network_data + sizeof(struct iphdr);
- if (ntohs(udp->dest) == 67 || ntohs(udp->dest) == 68)
- nic_type |= NIC_TYPE_F_DHCP;
- }
- break;
- case ETH_P_IPV6:
- nic_type |= NIC_TYPE_F_IPV6;
- ipv6 = network_data;
-
- if (ipv6->nexthdr == IPPROTO_ICMPV6) /* Check NDP request */ {
- struct icmp6hdr *icmp6 =
- network_data + sizeof(struct ipv6hdr);
- if (icmp6->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION)
- nic_type |= NIC_TYPE_ICMPV6;
- } else if (ipv6->nexthdr == IPPROTO_UDP) /* Check DHCPv6 */ {
- struct udphdr *udp =
- network_data + sizeof(struct ipv6hdr);
- if (ntohs(udp->dest) == 546 || ntohs(udp->dest) == 547)
- nic_type |= NIC_TYPE_F_DHCP;
- }
- break;
- default:
- break;
- }
-
- return nic_type;
-}
-
-static netdev_tx_t gdm_lte_tx(struct sk_buff *skb, struct net_device *dev)
-{
- struct nic *nic = netdev_priv(dev);
- u32 nic_type;
- void *data_buf;
- int data_len;
- int idx;
- int ret = 0;
-
- nic_type = gdm_lte_tx_nic_type(dev, skb);
- if (nic_type == 0) {
- netdev_err(dev, "tx - invalid nic_type\n");
- return -EMEDIUMTYPE;
- }
-
- if (nic_type & NIC_TYPE_ARP) {
- if (gdm_lte_emulate_arp(skb, nic_type) == 0) {
- dev_kfree_skb(skb);
- return 0;
- }
- }
-
- if (nic_type & NIC_TYPE_ICMPV6) {
- if (gdm_lte_emulate_ndp(skb, nic_type) == 0) {
- dev_kfree_skb(skb);
- return 0;
- }
- }
-
- /*
- * Need byte shift (that is, remove VLAN tag) if there is one
- * For the case of ARP, this breaks the offset as vlan_ethhdr+4
- * is treated as ethhdr However, it shouldn't be a problem as
- * the response starts from arp_hdr and ethhdr is created by this
- * driver based on the NIC mac
- */
- if (nic_type & NIC_TYPE_F_VLAN) {
- struct vlan_ethhdr *vlan_eth = skb_vlan_eth_hdr(skb);
-
- nic->vlan_id = ntohs(vlan_eth->h_vlan_TCI) & VLAN_VID_MASK;
- data_buf = skb->data + (VLAN_ETH_HLEN - ETH_HLEN);
- data_len = skb->len - (VLAN_ETH_HLEN - ETH_HLEN);
- } else {
- nic->vlan_id = 0;
- data_buf = skb->data;
- data_len = skb->len;
- }
-
- /* If it is a ICMPV6 packet, clear all the other bits :
- * for backward compatibility with the firmware
- */
- if (nic_type & NIC_TYPE_ICMPV6)
- nic_type = NIC_TYPE_ICMPV6;
-
- /* If it is not a dhcp packet, clear all the flag bits :
- * original NIC, otherwise the special flag (IPVX | DHCP)
- */
- if (!(nic_type & NIC_TYPE_F_DHCP))
- nic_type &= NIC_TYPE_MASK;
-
- ret = sscanf(dev->name, "lte%d", &idx);
- if (ret != 1) {
- dev_kfree_skb(skb);
- return -EINVAL;
- }
-
- ret = nic->phy_dev->send_sdu_func(nic->phy_dev->priv_dev,
- data_buf, data_len,
- nic->pdn_table.dft_eps_id, 0,
- tx_complete, nic, idx,
- nic_type);
-
- if (ret == TX_NO_BUFFER || ret == TX_NO_SPC) {
- netif_stop_queue(dev);
- if (ret == TX_NO_BUFFER)
- ret = 0;
- else
- ret = -ENOSPC;
- } else if (ret == TX_NO_DEV) {
- ret = -ENODEV;
- }
-
- /* Updates tx stats */
- if (ret) {
- nic->stats.tx_dropped++;
- } else {
- nic->stats.tx_packets++;
- nic->stats.tx_bytes += data_len;
- }
- dev_kfree_skb(skb);
-
- return 0;
-}
-
-static struct net_device_stats *gdm_lte_stats(struct net_device *dev)
-{
- struct nic *nic = netdev_priv(dev);
-
- return &nic->stats;
-}
-
-static int gdm_lte_event_send(struct net_device *dev, char *buf, int len)
-{
- struct phy_dev *phy_dev = ((struct nic *)netdev_priv(dev))->phy_dev;
- struct hci_packet *hci = (struct hci_packet *)buf;
- int length;
- int idx;
- int ret;
-
- ret = sscanf(dev->name, "lte%d", &idx);
- if (ret != 1)
- return -EINVAL;
-
- length = gdm_dev16_to_cpu(phy_dev->get_endian(phy_dev->priv_dev),
- hci->len) + HCI_HEADER_SIZE;
- return netlink_send(lte_event.sock, idx, 0, buf, length, dev);
-}
-
-static void gdm_lte_event_rcv(struct net_device *dev, u16 type,
- void *msg, int len)
-{
- struct nic *nic = netdev_priv(dev);
-
- nic->phy_dev->send_hci_func(nic->phy_dev->priv_dev, msg, len, NULL,
- NULL);
-}
-
-int gdm_lte_event_init(void)
-{
- if (lte_event.ref_cnt == 0)
- lte_event.sock = netlink_init(NETLINK_LTE, gdm_lte_event_rcv);
-
- if (lte_event.sock) {
- lte_event.ref_cnt++;
- return 0;
- }
-
- pr_err("event init failed\n");
- return -ENODATA;
-}
-
-void gdm_lte_event_exit(void)
-{
- if (lte_event.sock && --lte_event.ref_cnt == 0) {
- sock_release(lte_event.sock->sk_socket);
- lte_event.sock = NULL;
- }
-}
-
-static int find_dev_index(u32 nic_type)
-{
- u8 index;
-
- index = (u8)(nic_type & 0x0000000f);
- if (index >= MAX_NIC_TYPE)
- return -EINVAL;
-
- return index;
-}
-
-static void gdm_lte_netif_rx(struct net_device *dev, char *buf,
- int len, int flagged_nic_type)
-{
- u32 nic_type;
- struct nic *nic;
- struct sk_buff *skb;
- struct ethhdr eth;
- struct vlan_ethhdr vlan_eth;
- void *mac_header_data;
- u32 mac_header_len;
- char ip_version = 0;
-
- nic_type = flagged_nic_type & NIC_TYPE_MASK;
- nic = netdev_priv(dev);
-
- if (flagged_nic_type & NIC_TYPE_F_DHCP) {
- /* Change the destination mac address
- * with the one requested the IP
- */
- if (flagged_nic_type & NIC_TYPE_F_IPV4) {
- struct dhcp_packet {
- u8 op; /* BOOTREQUEST or BOOTREPLY */
- u8 htype; /* hardware address type.
- * 1 = 10mb ethernet
- */
- u8 hlen; /* hardware address length */
- u8 hops; /* used by relay agents only */
- u32 xid; /* unique id */
- u16 secs; /* elapsed since client began
- * acquisition/renewal
- */
- u16 flags; /* only one flag so far: */
- #define BROADCAST_FLAG 0x8000
- /* "I need broadcast replies" */
- u32 ciaddr; /* client IP (if client is in
- * BOUND, RENEW or REBINDING state)
- */
- u32 yiaddr; /* 'your' (client) IP address */
- /* IP address of next server to use in
- * bootstrap, returned in DHCPOFFER,
- * DHCPACK by server
- */
- u32 siaddr_nip;
- u32 gateway_nip; /* relay agent IP address */
- u8 chaddr[16]; /* link-layer client hardware
- * address (MAC)
- */
- u8 sname[64]; /* server host name (ASCIZ) */
- u8 file[128]; /* boot file name (ASCIZ) */
- u32 cookie; /* fixed first four option
- * bytes (99,130,83,99 dec)
- */
- } __packed;
- int offset = sizeof(struct iphdr) +
- sizeof(struct udphdr) +
- offsetof(struct dhcp_packet, chaddr);
- if (offset + ETH_ALEN > len)
- return;
- ether_addr_copy(nic->dest_mac_addr, buf + offset);
- }
- }
-
- if (nic->vlan_id > 0) {
- mac_header_data = (void *)&vlan_eth;
- mac_header_len = VLAN_ETH_HLEN;
- } else {
- mac_header_data = (void *)&eth;
- mac_header_len = ETH_HLEN;
- }
-
- /* Format the data so that it can be put to skb */
- ether_addr_copy(mac_header_data, nic->dest_mac_addr);
- memcpy(mac_header_data + ETH_ALEN, nic->src_mac_addr, ETH_ALEN);
-
- vlan_eth.h_vlan_TCI = htons(nic->vlan_id);
- vlan_eth.h_vlan_proto = htons(ETH_P_8021Q);
-
- if (nic_type == NIC_TYPE_ARP) {
- /* Should be response: Only happens because
- * there was a request from the host
- */
- eth.h_proto = htons(ETH_P_ARP);
- vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_ARP);
- } else {
- ip_version = buf[0] >> 4;
- if (ip_version == IP_VERSION_4) {
- eth.h_proto = htons(ETH_P_IP);
- vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IP);
- } else if (ip_version == IP_VERSION_6) {
- eth.h_proto = htons(ETH_P_IPV6);
- vlan_eth.h_vlan_encapsulated_proto = htons(ETH_P_IPV6);
- } else {
- netdev_err(dev, "Unknown IP version %d\n", ip_version);
- return;
- }
- }
-
- /* Alloc skb and reserve align */
- skb = dev_alloc_skb(len + mac_header_len + NET_IP_ALIGN);
- if (!skb)
- return;
- skb_reserve(skb, NET_IP_ALIGN);
-
- skb_put_data(skb, mac_header_data, mac_header_len);
- skb_put_data(skb, buf, len);
-
- skb->protocol = ((struct ethhdr *)mac_header_data)->h_proto;
- skb->dev = dev;
- skb_reset_mac_header(skb);
- skb_pull(skb, ETH_HLEN);
-
- gdm_lte_rx(skb, nic, nic_type);
-}
-
-static void gdm_lte_multi_sdu_pkt(struct phy_dev *phy_dev, char *buf, int len)
-{
- struct net_device *dev;
- struct multi_sdu *multi_sdu = (struct multi_sdu *)buf;
- struct sdu *sdu = NULL;
- u8 endian = phy_dev->get_endian(phy_dev->priv_dev);
- u8 *data = (u8 *)multi_sdu->data;
- int copied;
- u16 i = 0;
- u16 num_packet;
- u16 hci_len;
- u16 cmd_evt;
- u32 nic_type;
- int index;
-
- num_packet = gdm_dev16_to_cpu(endian, multi_sdu->num_packet);
-
- for (i = 0; i < num_packet; i++) {
- copied = data - multi_sdu->data;
- if (len < copied + sizeof(*sdu)) {
- pr_err("rx prevent buffer overflow");
- return;
- }
-
- sdu = (struct sdu *)data;
-
- cmd_evt = gdm_dev16_to_cpu(endian, sdu->cmd_evt);
- hci_len = gdm_dev16_to_cpu(endian, sdu->len);
- nic_type = gdm_dev32_to_cpu(endian, sdu->nic_type);
-
- if (cmd_evt != LTE_RX_SDU) {
- pr_err("rx sdu wrong hci %04x\n", cmd_evt);
- return;
- }
- if (hci_len < 12 ||
- len < copied + sizeof(*sdu) + (hci_len - 12)) {
- pr_err("rx sdu invalid len %d\n", hci_len);
- return;
- }
-
- index = find_dev_index(nic_type);
- if (index < 0) {
- pr_err("rx sdu invalid nic_type :%x\n", nic_type);
- return;
- }
- dev = phy_dev->dev[index];
- gdm_lte_netif_rx(dev, (char *)sdu->data,
- (int)(hci_len - 12), nic_type);
-
- data += ((hci_len + 3) & 0xfffc) + HCI_HEADER_SIZE;
- }
-}
-
-static void gdm_lte_pdn_table(struct net_device *dev, char *buf, int len)
-{
- struct nic *nic = netdev_priv(dev);
- struct hci_pdn_table_ind *pdn_table = (struct hci_pdn_table_ind *)buf;
- u8 ed = nic->phy_dev->get_endian(nic->phy_dev->priv_dev);
-
- if (!pdn_table->activate) {
- memset(&nic->pdn_table, 0x00, sizeof(struct pdn_table));
- netdev_info(dev, "pdn deactivated\n");
-
- return;
- }
-
- nic->pdn_table.activate = pdn_table->activate;
- nic->pdn_table.dft_eps_id = gdm_dev32_to_cpu(ed, pdn_table->dft_eps_id);
- nic->pdn_table.nic_type = gdm_dev32_to_cpu(ed, pdn_table->nic_type);
-
- netdev_info(dev, "pdn activated, nic_type=0x%x\n",
- nic->pdn_table.nic_type);
-}
-
-static int gdm_lte_receive_pkt(struct phy_dev *phy_dev, char *buf, int len)
-{
- struct hci_packet *hci = (struct hci_packet *)buf;
- struct hci_pdn_table_ind *pdn_table = (struct hci_pdn_table_ind *)buf;
- struct sdu *sdu;
- struct net_device *dev;
- u8 endian = phy_dev->get_endian(phy_dev->priv_dev);
- int ret = 0;
- u16 cmd_evt;
- u32 nic_type;
- int index;
-
- if (!len)
- return ret;
-
- cmd_evt = gdm_dev16_to_cpu(endian, hci->cmd_evt);
-
- dev = phy_dev->dev[0];
- if (!dev)
- return 0;
-
- switch (cmd_evt) {
- case LTE_RX_SDU:
- sdu = (struct sdu *)hci->data;
- nic_type = gdm_dev32_to_cpu(endian, sdu->nic_type);
- index = find_dev_index(nic_type);
- if (index < 0)
- return index;
- dev = phy_dev->dev[index];
- gdm_lte_netif_rx(dev, hci->data, len, nic_type);
- break;
- case LTE_RX_MULTI_SDU:
- gdm_lte_multi_sdu_pkt(phy_dev, buf, len);
- break;
- case LTE_LINK_ON_OFF_INDICATION:
- netdev_info(dev, "link %s\n",
- ((struct hci_connect_ind *)buf)->connect
- ? "on" : "off");
- break;
- case LTE_PDN_TABLE_IND:
- pdn_table = (struct hci_pdn_table_ind *)buf;
- nic_type = gdm_dev32_to_cpu(endian, pdn_table->nic_type);
- index = find_dev_index(nic_type);
- if (index < 0)
- return index;
- dev = phy_dev->dev[index];
- gdm_lte_pdn_table(dev, buf, len);
- fallthrough;
- default:
- ret = gdm_lte_event_send(dev, buf, len);
- break;
- }
-
- return ret;
-}
-
-static int rx_complete(void *arg, void *data, int len, int context)
-{
- struct phy_dev *phy_dev = arg;
-
- return gdm_lte_receive_pkt(phy_dev, data, len);
-}
-
-void start_rx_proc(struct phy_dev *phy_dev)
-{
- int i;
-
- for (i = 0; i < MAX_RX_SUBMIT_COUNT; i++)
- phy_dev->rcv_func(phy_dev->priv_dev,
- rx_complete, phy_dev, USB_COMPLETE);
-}
-
-static const struct net_device_ops gdm_netdev_ops = {
- .ndo_open = gdm_lte_open,
- .ndo_stop = gdm_lte_close,
- .ndo_set_config = gdm_lte_set_config,
- .ndo_start_xmit = gdm_lte_tx,
- .ndo_get_stats = gdm_lte_stats,
-};
-
-static u8 gdm_lte_macaddr[ETH_ALEN] = {0x00, 0x0a, 0x3b, 0x00, 0x00, 0x00};
-
-static void form_mac_address(u8 *dev_addr, u8 *nic_src, u8 *nic_dest,
- u8 *mac_address, u8 index)
-{
- /* Form the dev_addr */
- if (!mac_address)
- ether_addr_copy(dev_addr, gdm_lte_macaddr);
- else
- ether_addr_copy(dev_addr, mac_address);
-
- /* The last byte of the mac address
- * should be less than or equal to 0xFC
- */
- dev_addr[ETH_ALEN - 1] += index;
-
- /* Create random nic src and copy the first
- * 3 bytes to be the same as dev_addr
- */
- eth_random_addr(nic_src);
- memcpy(nic_src, dev_addr, 3);
-
- /* Copy the nic_dest from dev_addr*/
- ether_addr_copy(nic_dest, dev_addr);
-}
-
-static void validate_mac_address(u8 *mac_address)
-{
- /* if zero address or multicast bit set, restore the default value */
- if (is_zero_ether_addr(mac_address) || (mac_address[0] & 0x01)) {
- pr_err("MAC invalid, restoring default\n");
- memcpy(mac_address, gdm_lte_macaddr, 6);
- }
-}
-
-int register_lte_device(struct phy_dev *phy_dev,
- struct device *dev, u8 *mac_address)
-{
- struct nic *nic;
- struct net_device *net;
- char pdn_dev_name[16];
- u8 addr[ETH_ALEN];
- int ret = 0;
- u8 index;
-
- validate_mac_address(mac_address);
-
- for (index = 0; index < MAX_NIC_TYPE; index++) {
- /* Create device name lteXpdnX */
- sprintf(pdn_dev_name, "lte%%dpdn%d", index);
-
- /* Allocate netdev */
- net = alloc_netdev(sizeof(struct nic), pdn_dev_name,
- NET_NAME_UNKNOWN, ether_setup);
- if (!net) {
- ret = -ENOMEM;
- goto err;
- }
- net->netdev_ops = &gdm_netdev_ops;
- net->flags &= ~IFF_MULTICAST;
- net->mtu = DEFAULT_MTU_SIZE;
-
- nic = netdev_priv(net);
- memset(nic, 0, sizeof(struct nic));
- nic->netdev = net;
- nic->phy_dev = phy_dev;
- nic->nic_id = index;
-
- form_mac_address(addr,
- nic->src_mac_addr,
- nic->dest_mac_addr,
- mac_address,
- index);
- eth_hw_addr_set(net, addr);
-
- SET_NETDEV_DEV(net, dev);
- SET_NETDEV_DEVTYPE(net, &wwan_type);
-
- ret = register_netdev(net);
- if (ret)
- goto err;
-
- netif_carrier_on(net);
-
- phy_dev->dev[index] = net;
- }
-
- return 0;
-
-err:
- unregister_lte_device(phy_dev);
-
- return ret;
-}
-
-void unregister_lte_device(struct phy_dev *phy_dev)
-{
- struct net_device *net;
- int index;
-
- for (index = 0; index < MAX_NIC_TYPE; index++) {
- net = phy_dev->dev[index];
- if (!net)
- continue;
-
- unregister_netdev(net);
- free_netdev(net);
- }
-}
diff --git a/drivers/staging/gdm724x/gdm_lte.h b/drivers/staging/gdm724x/gdm_lte.h
deleted file mode 100644
index f2143a6e0e99..000000000000
--- a/drivers/staging/gdm724x/gdm_lte.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _GDM_LTE_H_
-#define _GDM_LTE_H_
-
-#include <linux/netdevice.h>
-#include <linux/types.h>
-
-#include "gdm_endian.h"
-
-#define MAX_NIC_TYPE 4
-#define MAX_RX_SUBMIT_COUNT 3
-#define DRIVER_VERSION "3.7.17.0"
-
-enum TX_ERROR_CODE {
- TX_NO_ERROR = 0,
- TX_NO_DEV,
- TX_NO_SPC,
- TX_NO_BUFFER,
-};
-
-enum CALLBACK_CONTEXT {
- KERNEL_THREAD = 0,
- USB_COMPLETE,
-};
-
-struct pdn_table {
- u8 activate;
- u32 dft_eps_id;
- u32 nic_type;
-} __packed;
-
-struct nic;
-
-struct phy_dev {
- void *priv_dev;
- struct net_device *dev[MAX_NIC_TYPE];
- int (*send_hci_func)(void *priv_dev, void *data, int len,
- void (*cb)(void *cb_data), void *cb_data);
- int (*send_sdu_func)(void *priv_dev, void *data, int len,
- unsigned int dft_eps_id, unsigned int eps_id,
- void (*cb)(void *cb_data), void *cb_data,
- int dev_idx, int nic_type);
- int (*rcv_func)(void *priv_dev,
- int (*cb)(void *cb_data, void *data, int len,
- int context),
- void *cb_data, int context);
- u8 (*get_endian)(void *priv_dev);
-};
-
-struct nic {
- struct net_device *netdev;
- struct phy_dev *phy_dev;
- struct net_device_stats stats;
- struct pdn_table pdn_table;
- u8 dest_mac_addr[ETH_ALEN];
- u8 src_mac_addr[ETH_ALEN];
- u32 nic_id;
- u16 vlan_id;
-};
-
-int gdm_lte_event_init(void);
-void gdm_lte_event_exit(void);
-
-void start_rx_proc(struct phy_dev *phy_dev);
-int register_lte_device(struct phy_dev *phy_dev, struct device *dev,
- u8 *mac_address);
-void unregister_lte_device(struct phy_dev *phy_dev);
-
-#endif /* _GDM_LTE_H_ */
diff --git a/drivers/staging/gdm724x/gdm_mux.c b/drivers/staging/gdm724x/gdm_mux.c
deleted file mode 100644
index 9b12619671a1..000000000000
--- a/drivers/staging/gdm724x/gdm_mux.c
+++ /dev/null
@@ -1,668 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/slab.h>
-#include <linux/usb/cdc.h>
-
-#include "gdm_mux.h"
-
-static u16 packet_type_for_tty_index[TTY_MAX_COUNT] = {0xF011, 0xF010};
-
-#define USB_DEVICE_CDC_DATA(vid, pid) \
- .match_flags = \
- USB_DEVICE_ID_MATCH_DEVICE |\
- USB_DEVICE_ID_MATCH_INT_CLASS |\
- USB_DEVICE_ID_MATCH_INT_SUBCLASS,\
- .idVendor = vid,\
- .idProduct = pid,\
- .bInterfaceClass = USB_CLASS_COMM,\
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM
-
-static const struct usb_device_id id_table[] = {
- { USB_DEVICE_CDC_DATA(0x1076, 0x8000) }, /* GCT GDM7240 */
- { USB_DEVICE_CDC_DATA(0x1076, 0x8f00) }, /* GCT GDM7243 */
- { USB_DEVICE_CDC_DATA(0x1076, 0x9000) }, /* GCT GDM7243 */
- { USB_DEVICE_CDC_DATA(0x1d74, 0x2300) }, /* LGIT Phoenix */
- {}
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static int packet_type_to_tty_index(u16 packet_type)
-{
- int i;
-
- for (i = 0; i < TTY_MAX_COUNT; i++) {
- if (packet_type_for_tty_index[i] == packet_type)
- return i;
- }
-
- return -1;
-}
-
-static struct mux_tx *alloc_mux_tx(int len)
-{
- struct mux_tx *t;
-
- t = kzalloc(sizeof(*t), GFP_ATOMIC);
- if (!t)
- return NULL;
-
- t->urb = usb_alloc_urb(0, GFP_ATOMIC);
- t->buf = kmalloc(MUX_TX_MAX_SIZE, GFP_ATOMIC);
- if (!t->urb || !t->buf) {
- usb_free_urb(t->urb);
- kfree(t->buf);
- kfree(t);
- return NULL;
- }
-
- return t;
-}
-
-static void free_mux_tx(struct mux_tx *t)
-{
- if (t) {
- usb_free_urb(t->urb);
- kfree(t->buf);
- kfree(t);
- }
-}
-
-static struct mux_rx *alloc_mux_rx(void)
-{
- struct mux_rx *r;
-
- r = kzalloc(sizeof(*r), GFP_KERNEL);
- if (!r)
- return NULL;
-
- r->urb = usb_alloc_urb(0, GFP_KERNEL);
- r->buf = kmalloc(MUX_RX_MAX_SIZE, GFP_KERNEL);
- if (!r->urb || !r->buf) {
- usb_free_urb(r->urb);
- kfree(r->buf);
- kfree(r);
- return NULL;
- }
-
- return r;
-}
-
-static void free_mux_rx(struct mux_rx *r)
-{
- if (r) {
- usb_free_urb(r->urb);
- kfree(r->buf);
- kfree(r);
- }
-}
-
-static struct mux_rx *get_rx_struct(struct rx_cxt *rx)
-{
- struct mux_rx *r;
- unsigned long flags;
-
- spin_lock_irqsave(&rx->free_list_lock, flags);
-
- if (list_empty(&rx->rx_free_list)) {
- spin_unlock_irqrestore(&rx->free_list_lock, flags);
- return NULL;
- }
-
- r = list_entry(rx->rx_free_list.prev, struct mux_rx, free_list);
- list_del(&r->free_list);
-
- spin_unlock_irqrestore(&rx->free_list_lock, flags);
-
- return r;
-}
-
-static void put_rx_struct(struct rx_cxt *rx, struct mux_rx *r)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&rx->free_list_lock, flags);
- list_add_tail(&r->free_list, &rx->rx_free_list);
- spin_unlock_irqrestore(&rx->free_list_lock, flags);
-}
-
-static int up_to_host(struct mux_rx *r)
-{
- struct mux_dev *mux_dev = r->mux_dev;
- struct mux_pkt_header *mux_header;
- unsigned int start_flag;
- unsigned int payload_size;
- unsigned short packet_type;
- int total_len;
- u32 packet_size_sum = r->offset;
- int index;
- int ret = TO_HOST_INVALID_PACKET;
- int len = r->len;
-
- while (1) {
- mux_header = (struct mux_pkt_header *)(r->buf +
- packet_size_sum);
- start_flag = __le32_to_cpu(mux_header->start_flag);
- payload_size = __le32_to_cpu(mux_header->payload_size);
- packet_type = __le16_to_cpu(mux_header->packet_type);
-
- if (start_flag != START_FLAG) {
- pr_err("invalid START_FLAG %x\n", start_flag);
- break;
- }
-
- total_len = ALIGN(MUX_HEADER_SIZE + payload_size, 4);
-
- if (len - packet_size_sum < total_len) {
- pr_err("invalid payload : %d %d %04x\n",
- payload_size, len, packet_type);
- break;
- }
-
- index = packet_type_to_tty_index(packet_type);
- if (index < 0) {
- pr_err("invalid index %d\n", index);
- break;
- }
-
- ret = r->callback(mux_header->data,
- payload_size,
- index,
- mux_dev->tty_dev,
- RECV_PACKET_PROCESS_CONTINUE
- );
- if (ret == TO_HOST_BUFFER_REQUEST_FAIL) {
- r->offset += packet_size_sum;
- break;
- }
-
- packet_size_sum += total_len;
- if (len - packet_size_sum <= MUX_HEADER_SIZE + 2) {
- ret = r->callback(NULL,
- 0,
- index,
- mux_dev->tty_dev,
- RECV_PACKET_PROCESS_COMPLETE
- );
- break;
- }
- }
-
- return ret;
-}
-
-static void do_rx(struct work_struct *work)
-{
- struct mux_dev *mux_dev =
- container_of(work, struct mux_dev, work_rx.work);
- struct mux_rx *r;
- struct rx_cxt *rx = &mux_dev->rx;
- unsigned long flags;
- int ret = 0;
-
- while (1) {
- spin_lock_irqsave(&rx->to_host_lock, flags);
- if (list_empty(&rx->to_host_list)) {
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
- break;
- }
- r = list_entry(rx->to_host_list.next, struct mux_rx,
- to_host_list);
- list_del(&r->to_host_list);
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
-
- ret = up_to_host(r);
- if (ret == TO_HOST_BUFFER_REQUEST_FAIL)
- pr_err("failed to send mux data to host\n");
- else
- put_rx_struct(rx, r);
- }
-}
-
-static void remove_rx_submit_list(struct mux_rx *r, struct rx_cxt *rx)
-{
- unsigned long flags;
- struct mux_rx *r_remove, *r_remove_next;
-
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- list_for_each_entry_safe(r_remove, r_remove_next, &rx->rx_submit_list,
- rx_submit_list) {
- if (r == r_remove)
- list_del(&r->rx_submit_list);
- }
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
-}
-
-static void gdm_mux_rcv_complete(struct urb *urb)
-{
- struct mux_rx *r = urb->context;
- struct mux_dev *mux_dev = r->mux_dev;
- struct rx_cxt *rx = &mux_dev->rx;
- unsigned long flags;
-
- remove_rx_submit_list(r, rx);
-
- if (urb->status) {
- if (mux_dev->usb_state == PM_NORMAL)
- dev_err(&urb->dev->dev, "%s: urb status error %d\n",
- __func__, urb->status);
- put_rx_struct(rx, r);
- } else {
- r->len = r->urb->actual_length;
- spin_lock_irqsave(&rx->to_host_lock, flags);
- list_add_tail(&r->to_host_list, &rx->to_host_list);
- schedule_work(&mux_dev->work_rx.work);
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
- }
-}
-
-static int gdm_mux_recv(void *priv_dev,
- int (*cb)(void *data, int len, int tty_index,
- struct tty_dev *tty_dev, int complete))
-{
- struct mux_dev *mux_dev = priv_dev;
- struct usb_device *usbdev = mux_dev->usbdev;
- struct mux_rx *r;
- struct rx_cxt *rx = &mux_dev->rx;
- unsigned long flags;
- int ret;
-
- if (!usbdev) {
- pr_err("device is disconnected\n");
- return -ENODEV;
- }
-
- r = get_rx_struct(rx);
- if (!r) {
- pr_err("get_rx_struct fail\n");
- return -ENOMEM;
- }
-
- r->offset = 0;
- r->mux_dev = (void *)mux_dev;
- r->callback = cb;
- mux_dev->rx_cb = cb;
-
- usb_fill_bulk_urb(r->urb,
- usbdev,
- usb_rcvbulkpipe(usbdev, 0x86),
- r->buf,
- MUX_RX_MAX_SIZE,
- gdm_mux_rcv_complete,
- r);
-
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- list_add_tail(&r->rx_submit_list, &rx->rx_submit_list);
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
-
- ret = usb_submit_urb(r->urb, GFP_KERNEL);
-
- if (ret) {
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- list_del(&r->rx_submit_list);
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
-
- put_rx_struct(rx, r);
-
- pr_err("usb_submit_urb ret=%d\n", ret);
- }
-
- usb_mark_last_busy(usbdev);
-
- return ret;
-}
-
-static void gdm_mux_send_complete(struct urb *urb)
-{
- struct mux_tx *t = urb->context;
-
- if (urb->status == -ECONNRESET) {
- dev_info(&urb->dev->dev, "CONNRESET\n");
- free_mux_tx(t);
- return;
- }
-
- if (t->callback)
- t->callback(t->cb_data);
-
- free_mux_tx(t);
-}
-
-static int gdm_mux_send(void *priv_dev, void *data, int len, int tty_index,
- void (*cb)(void *data), void *cb_data)
-{
- struct mux_dev *mux_dev = priv_dev;
- struct usb_device *usbdev = mux_dev->usbdev;
- struct mux_pkt_header *mux_header;
- struct mux_tx *t = NULL;
- static u32 seq_num = 1;
- int total_len;
- int ret;
- unsigned long flags;
-
- if (mux_dev->usb_state == PM_SUSPEND) {
- ret = usb_autopm_get_interface(mux_dev->intf);
- if (!ret)
- usb_autopm_put_interface(mux_dev->intf);
- }
-
- spin_lock_irqsave(&mux_dev->write_lock, flags);
-
- total_len = ALIGN(MUX_HEADER_SIZE + len, 4);
-
- t = alloc_mux_tx(total_len);
- if (!t) {
- pr_err("alloc_mux_tx fail\n");
- spin_unlock_irqrestore(&mux_dev->write_lock, flags);
- return -ENOMEM;
- }
-
- mux_header = (struct mux_pkt_header *)t->buf;
- mux_header->start_flag = __cpu_to_le32(START_FLAG);
- mux_header->seq_num = __cpu_to_le32(seq_num++);
- mux_header->payload_size = __cpu_to_le32((u32)len);
- mux_header->packet_type = __cpu_to_le16(packet_type_for_tty_index[tty_index]);
-
- memcpy(t->buf + MUX_HEADER_SIZE, data, len);
- memset(t->buf + MUX_HEADER_SIZE + len, 0,
- total_len - MUX_HEADER_SIZE - len);
-
- t->len = total_len;
- t->callback = cb;
- t->cb_data = cb_data;
-
- usb_fill_bulk_urb(t->urb,
- usbdev,
- usb_sndbulkpipe(usbdev, 5),
- t->buf,
- total_len,
- gdm_mux_send_complete,
- t);
-
- ret = usb_submit_urb(t->urb, GFP_ATOMIC);
-
- spin_unlock_irqrestore(&mux_dev->write_lock, flags);
-
- if (ret)
- pr_err("usb_submit_urb Error: %d\n", ret);
-
- usb_mark_last_busy(usbdev);
-
- return ret;
-}
-
-static int gdm_mux_send_control(void *priv_dev, int request, int value,
- void *buf, int len)
-{
- struct mux_dev *mux_dev = priv_dev;
- struct usb_device *usbdev = mux_dev->usbdev;
- int ret;
-
- ret = usb_control_msg(usbdev,
- usb_sndctrlpipe(usbdev, 0),
- request,
- USB_RT_ACM,
- value,
- 2,
- buf,
- len,
- 5000
- );
-
- if (ret < 0)
- pr_err("usb_control_msg error: %d\n", ret);
-
- return min(ret, 0);
-}
-
-static void release_usb(struct mux_dev *mux_dev)
-{
- struct rx_cxt *rx = &mux_dev->rx;
- struct mux_rx *r, *r_next;
- unsigned long flags;
-
- cancel_delayed_work(&mux_dev->work_rx);
-
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
- rx_submit_list) {
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
- usb_kill_urb(r->urb);
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- }
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
-
- spin_lock_irqsave(&rx->free_list_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->rx_free_list, free_list) {
- list_del(&r->free_list);
- free_mux_rx(r);
- }
- spin_unlock_irqrestore(&rx->free_list_lock, flags);
-
- spin_lock_irqsave(&rx->to_host_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) {
- if (r->mux_dev == (void *)mux_dev) {
- list_del(&r->to_host_list);
- free_mux_rx(r);
- }
- }
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
-}
-
-static int init_usb(struct mux_dev *mux_dev)
-{
- struct mux_rx *r;
- struct rx_cxt *rx = &mux_dev->rx;
- int ret = 0;
- int i;
-
- spin_lock_init(&mux_dev->write_lock);
- INIT_LIST_HEAD(&rx->to_host_list);
- INIT_LIST_HEAD(&rx->rx_submit_list);
- INIT_LIST_HEAD(&rx->rx_free_list);
- spin_lock_init(&rx->to_host_lock);
- spin_lock_init(&rx->submit_list_lock);
- spin_lock_init(&rx->free_list_lock);
-
- for (i = 0; i < MAX_ISSUE_NUM * 2; i++) {
- r = alloc_mux_rx();
- if (!r) {
- ret = -ENOMEM;
- break;
- }
-
- list_add(&r->free_list, &rx->rx_free_list);
- }
-
- INIT_DELAYED_WORK(&mux_dev->work_rx, do_rx);
-
- return ret;
-}
-
-static int gdm_mux_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- struct mux_dev *mux_dev;
- struct tty_dev *tty_dev;
- u16 idVendor, idProduct;
- int bInterfaceNumber;
- int ret;
- int i;
- struct usb_device *usbdev = interface_to_usbdev(intf);
-
- bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
-
- idVendor = __le16_to_cpu(usbdev->descriptor.idVendor);
- idProduct = __le16_to_cpu(usbdev->descriptor.idProduct);
-
- pr_info("mux vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct);
-
- if (bInterfaceNumber != 2)
- return -ENODEV;
-
- mux_dev = kzalloc(sizeof(*mux_dev), GFP_KERNEL);
- if (!mux_dev)
- return -ENOMEM;
-
- tty_dev = kzalloc(sizeof(*tty_dev), GFP_KERNEL);
- if (!tty_dev) {
- ret = -ENOMEM;
- goto err_free_mux;
- }
-
- mux_dev->usbdev = usbdev;
- mux_dev->control_intf = intf;
-
- ret = init_usb(mux_dev);
- if (ret)
- goto err_free_usb;
-
- tty_dev->priv_dev = (void *)mux_dev;
- tty_dev->send_func = gdm_mux_send;
- tty_dev->recv_func = gdm_mux_recv;
- tty_dev->send_control = gdm_mux_send_control;
-
- ret = register_lte_tty_device(tty_dev, &intf->dev);
- if (ret)
- goto err_unregister_tty;
-
- for (i = 0; i < TTY_MAX_COUNT; i++)
- mux_dev->tty_dev = tty_dev;
-
- mux_dev->intf = intf;
- mux_dev->usb_state = PM_NORMAL;
-
- usb_get_dev(usbdev);
- usb_set_intfdata(intf, tty_dev);
-
- return 0;
-
-err_unregister_tty:
- unregister_lte_tty_device(tty_dev);
-err_free_usb:
- release_usb(mux_dev);
- kfree(tty_dev);
-err_free_mux:
- kfree(mux_dev);
-
- return ret;
-}
-
-static void gdm_mux_disconnect(struct usb_interface *intf)
-{
- struct tty_dev *tty_dev;
- struct mux_dev *mux_dev;
- struct usb_device *usbdev = interface_to_usbdev(intf);
-
- tty_dev = usb_get_intfdata(intf);
-
- mux_dev = tty_dev->priv_dev;
-
- release_usb(mux_dev);
- unregister_lte_tty_device(tty_dev);
-
- kfree(mux_dev);
- kfree(tty_dev);
-
- usb_put_dev(usbdev);
-}
-
-static int gdm_mux_suspend(struct usb_interface *intf, pm_message_t pm_msg)
-{
- struct tty_dev *tty_dev;
- struct mux_dev *mux_dev;
- struct rx_cxt *rx;
- struct mux_rx *r, *r_next;
- unsigned long flags;
-
- tty_dev = usb_get_intfdata(intf);
- mux_dev = tty_dev->priv_dev;
- rx = &mux_dev->rx;
-
- cancel_work_sync(&mux_dev->work_rx.work);
-
- if (mux_dev->usb_state != PM_NORMAL) {
- dev_err(intf->usb_dev, "usb suspend - invalid state\n");
- return -1;
- }
-
- mux_dev->usb_state = PM_SUSPEND;
-
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
- rx_submit_list) {
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
- usb_kill_urb(r->urb);
- spin_lock_irqsave(&rx->submit_list_lock, flags);
- }
- spin_unlock_irqrestore(&rx->submit_list_lock, flags);
-
- return 0;
-}
-
-static int gdm_mux_resume(struct usb_interface *intf)
-{
- struct tty_dev *tty_dev;
- struct mux_dev *mux_dev;
- u8 i;
-
- tty_dev = usb_get_intfdata(intf);
- mux_dev = tty_dev->priv_dev;
-
- if (mux_dev->usb_state != PM_SUSPEND) {
- dev_err(intf->usb_dev, "usb resume - invalid state\n");
- return -1;
- }
-
- mux_dev->usb_state = PM_NORMAL;
-
- for (i = 0; i < MAX_ISSUE_NUM; i++)
- gdm_mux_recv(mux_dev, mux_dev->rx_cb);
-
- return 0;
-}
-
-static struct usb_driver gdm_mux_driver = {
- .name = "gdm_mux",
- .probe = gdm_mux_probe,
- .disconnect = gdm_mux_disconnect,
- .id_table = id_table,
- .supports_autosuspend = 1,
- .suspend = gdm_mux_suspend,
- .resume = gdm_mux_resume,
- .reset_resume = gdm_mux_resume,
-};
-
-static int __init gdm_usb_mux_init(void)
-{
- int ret;
-
- ret = register_lte_tty_driver();
- if (ret)
- return ret;
-
- return usb_register(&gdm_mux_driver);
-}
-
-static void __exit gdm_usb_mux_exit(void)
-{
- usb_deregister(&gdm_mux_driver);
- unregister_lte_tty_driver();
-}
-
-module_init(gdm_usb_mux_init);
-module_exit(gdm_usb_mux_exit);
-
-MODULE_DESCRIPTION("GCT LTE TTY Device Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gdm724x/gdm_mux.h b/drivers/staging/gdm724x/gdm_mux.h
deleted file mode 100644
index 87b8d921fdc8..000000000000
--- a/drivers/staging/gdm724x/gdm_mux.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _GDM_MUX_H_
-#define _GDM_MUX_H_
-
-#include <linux/types.h>
-#include <linux/usb.h>
-#include <linux/list.h>
-
-#include "gdm_tty.h"
-
-#define PM_NORMAL 0
-#define PM_SUSPEND 1
-
-#define USB_RT_ACM (USB_TYPE_CLASS | USB_RECIP_INTERFACE)
-
-#define START_FLAG 0xA512485A
-#define MUX_HEADER_SIZE 14
-#define MUX_TX_MAX_SIZE (1024 * 10)
-#define MUX_RX_MAX_SIZE (1024 * 30)
-#define AT_PKT_TYPE 0xF011
-#define DM_PKT_TYPE 0xF010
-
-#define RETRY_TIMER 30 /* msec */
-
-struct mux_pkt_header {
- __le32 start_flag;
- __le32 seq_num;
- __le32 payload_size;
- __le16 packet_type;
- unsigned char data[];
-};
-
-struct mux_tx {
- struct urb *urb;
- u8 *buf;
- int len;
- void (*callback)(void *cb_data);
- void *cb_data;
-};
-
-struct mux_rx {
- struct list_head free_list;
- struct list_head rx_submit_list;
- struct list_head to_host_list;
- struct urb *urb;
- u8 *buf;
- void *mux_dev;
- u32 offset;
- u32 len;
- int (*callback)(void *data,
- int len,
- int tty_index,
- struct tty_dev *tty_dev,
- int complete);
-};
-
-struct rx_cxt {
- struct list_head to_host_list;
- struct list_head rx_submit_list;
- struct list_head rx_free_list;
- spinlock_t to_host_lock;
- spinlock_t submit_list_lock;
- spinlock_t free_list_lock;
-};
-
-struct mux_dev {
- struct usb_device *usbdev;
- struct usb_interface *control_intf;
- struct usb_interface *data_intf;
- struct rx_cxt rx;
- struct delayed_work work_rx;
- struct usb_interface *intf;
- int usb_state;
- int (*rx_cb)(void *data,
- int len,
- int tty_index,
- struct tty_dev *tty_dev,
- int complete);
- spinlock_t write_lock;
- struct tty_dev *tty_dev;
-};
-
-#endif /* _GDM_MUX_H_ */
diff --git a/drivers/staging/gdm724x/gdm_tty.c b/drivers/staging/gdm724x/gdm_tty.c
deleted file mode 100644
index 15c246d3b1a3..000000000000
--- a/drivers/staging/gdm724x/gdm_tty.c
+++ /dev/null
@@ -1,316 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/usb/cdc.h>
-#include <linux/serial.h>
-#include "gdm_tty.h"
-
-#define GDM_TTY_MAJOR 0
-#define GDM_TTY_MINOR 32
-
-#define WRITE_SIZE 2048
-
-#define MUX_TX_MAX_SIZE 2048
-
-static inline bool gdm_tty_ready(struct gdm *gdm)
-{
- return gdm && gdm->tty_dev && gdm->port.count;
-}
-
-static struct tty_driver *gdm_driver[TTY_MAX_COUNT];
-static struct gdm *gdm_table[TTY_MAX_COUNT][GDM_TTY_MINOR];
-static DEFINE_MUTEX(gdm_table_lock);
-
-static const char *DRIVER_STRING[TTY_MAX_COUNT] = {"GCTATC", "GCTDM"};
-static char *DEVICE_STRING[TTY_MAX_COUNT] = {"GCT-ATC", "GCT-DM"};
-
-static void gdm_port_destruct(struct tty_port *port)
-{
- struct gdm *gdm = container_of(port, struct gdm, port);
-
- mutex_lock(&gdm_table_lock);
- gdm_table[gdm->index][gdm->minor] = NULL;
- mutex_unlock(&gdm_table_lock);
-
- kfree(gdm);
-}
-
-static const struct tty_port_operations gdm_port_ops = {
- .destruct = gdm_port_destruct,
-};
-
-static int gdm_tty_install(struct tty_driver *driver, struct tty_struct *tty)
-{
- struct gdm *gdm = NULL;
- int ret;
-
- ret = match_string(DRIVER_STRING, TTY_MAX_COUNT,
- tty->driver->driver_name);
- if (ret < 0)
- return -ENODEV;
-
- mutex_lock(&gdm_table_lock);
- gdm = gdm_table[ret][tty->index];
- if (!gdm) {
- mutex_unlock(&gdm_table_lock);
- return -ENODEV;
- }
-
- tty_port_get(&gdm->port);
-
- ret = tty_standard_install(driver, tty);
- if (ret) {
- tty_port_put(&gdm->port);
- mutex_unlock(&gdm_table_lock);
- return ret;
- }
-
- tty->driver_data = gdm;
- mutex_unlock(&gdm_table_lock);
-
- return 0;
-}
-
-static int gdm_tty_open(struct tty_struct *tty, struct file *filp)
-{
- struct gdm *gdm = tty->driver_data;
-
- return tty_port_open(&gdm->port, tty, filp);
-}
-
-static void gdm_tty_cleanup(struct tty_struct *tty)
-{
- struct gdm *gdm = tty->driver_data;
-
- tty_port_put(&gdm->port);
-}
-
-static void gdm_tty_hangup(struct tty_struct *tty)
-{
- struct gdm *gdm = tty->driver_data;
-
- tty_port_hangup(&gdm->port);
-}
-
-static void gdm_tty_close(struct tty_struct *tty, struct file *filp)
-{
- struct gdm *gdm = tty->driver_data;
-
- tty_port_close(&gdm->port, tty, filp);
-}
-
-static int gdm_tty_recv_complete(void *data,
- int len,
- int index,
- struct tty_dev *tty_dev,
- int complete)
-{
- struct gdm *gdm = tty_dev->gdm[index];
-
- if (!gdm_tty_ready(gdm)) {
- if (complete == RECV_PACKET_PROCESS_COMPLETE)
- gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
- gdm_tty_recv_complete);
- return TO_HOST_PORT_CLOSE;
- }
-
- if (data && len) {
- if (tty_buffer_request_room(&gdm->port, len) == len) {
- tty_insert_flip_string(&gdm->port, data, len);
- tty_flip_buffer_push(&gdm->port);
- } else {
- return TO_HOST_BUFFER_REQUEST_FAIL;
- }
- }
-
- if (complete == RECV_PACKET_PROCESS_COMPLETE)
- gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
- gdm_tty_recv_complete);
-
- return 0;
-}
-
-static void gdm_tty_send_complete(void *arg)
-{
- struct gdm *gdm = arg;
-
- if (!gdm_tty_ready(gdm))
- return;
-
- tty_port_tty_wakeup(&gdm->port);
-}
-
-static ssize_t gdm_tty_write(struct tty_struct *tty, const u8 *buf, size_t len)
-{
- struct gdm *gdm = tty->driver_data;
- size_t remain = len;
- size_t sent_len = 0;
-
- if (!gdm_tty_ready(gdm))
- return -ENODEV;
-
- while (remain) {
- size_t sending_len = min_t(size_t, MUX_TX_MAX_SIZE, remain);
-
- gdm->tty_dev->send_func(gdm->tty_dev->priv_dev,
- (void *)(buf + sent_len),
- sending_len,
- gdm->index,
- gdm_tty_send_complete,
- gdm);
- sent_len += sending_len;
- remain -= sending_len;
- }
-
- return len;
-}
-
-static unsigned int gdm_tty_write_room(struct tty_struct *tty)
-{
- struct gdm *gdm = tty->driver_data;
-
- if (!gdm_tty_ready(gdm))
- return 0;
-
- return WRITE_SIZE;
-}
-
-int register_lte_tty_device(struct tty_dev *tty_dev, struct device *device)
-{
- struct gdm *gdm;
- int i;
- int j;
-
- for (i = 0; i < TTY_MAX_COUNT; i++) {
- gdm = kmalloc(sizeof(*gdm), GFP_KERNEL);
- if (!gdm)
- return -ENOMEM;
-
- mutex_lock(&gdm_table_lock);
- for (j = 0; j < GDM_TTY_MINOR; j++) {
- if (!gdm_table[i][j])
- break;
- }
-
- if (j == GDM_TTY_MINOR) {
- kfree(gdm);
- mutex_unlock(&gdm_table_lock);
- return -EINVAL;
- }
-
- gdm_table[i][j] = gdm;
- mutex_unlock(&gdm_table_lock);
-
- tty_dev->gdm[i] = gdm;
- tty_port_init(&gdm->port);
-
- gdm->port.ops = &gdm_port_ops;
- gdm->index = i;
- gdm->minor = j;
- gdm->tty_dev = tty_dev;
-
- tty_port_register_device(&gdm->port, gdm_driver[i],
- gdm->minor, device);
- }
-
- for (i = 0; i < MAX_ISSUE_NUM; i++)
- gdm->tty_dev->recv_func(gdm->tty_dev->priv_dev,
- gdm_tty_recv_complete);
-
- return 0;
-}
-
-void unregister_lte_tty_device(struct tty_dev *tty_dev)
-{
- struct gdm *gdm;
- struct tty_struct *tty;
- int i;
-
- for (i = 0; i < TTY_MAX_COUNT; i++) {
- gdm = tty_dev->gdm[i];
- if (!gdm)
- continue;
-
- mutex_lock(&gdm_table_lock);
- gdm_table[gdm->index][gdm->minor] = NULL;
- mutex_unlock(&gdm_table_lock);
-
- tty = tty_port_tty_get(&gdm->port);
- if (tty) {
- tty_vhangup(tty);
- tty_kref_put(tty);
- }
-
- tty_unregister_device(gdm_driver[i], gdm->minor);
- tty_port_put(&gdm->port);
- }
-}
-
-static const struct tty_operations gdm_tty_ops = {
- .install = gdm_tty_install,
- .open = gdm_tty_open,
- .close = gdm_tty_close,
- .cleanup = gdm_tty_cleanup,
- .hangup = gdm_tty_hangup,
- .write = gdm_tty_write,
- .write_room = gdm_tty_write_room,
-};
-
-int register_lte_tty_driver(void)
-{
- struct tty_driver *tty_driver;
- int i;
- int ret;
-
- for (i = 0; i < TTY_MAX_COUNT; i++) {
- tty_driver = tty_alloc_driver(GDM_TTY_MINOR,
- TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV);
- if (IS_ERR(tty_driver))
- return PTR_ERR(tty_driver);
-
- tty_driver->owner = THIS_MODULE;
- tty_driver->driver_name = DRIVER_STRING[i];
- tty_driver->name = DEVICE_STRING[i];
- tty_driver->major = GDM_TTY_MAJOR;
- tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
- tty_driver->subtype = SERIAL_TYPE_NORMAL;
- tty_driver->init_termios = tty_std_termios;
- tty_driver->init_termios.c_cflag = B9600 | CS8 | HUPCL | CLOCAL;
- tty_driver->init_termios.c_lflag = ISIG | ICANON | IEXTEN;
- tty_set_operations(tty_driver, &gdm_tty_ops);
-
- ret = tty_register_driver(tty_driver);
- if (ret) {
- tty_driver_kref_put(tty_driver);
- return ret;
- }
-
- gdm_driver[i] = tty_driver;
- }
-
- return ret;
-}
-
-void unregister_lte_tty_driver(void)
-{
- struct tty_driver *tty_driver;
- int i;
-
- for (i = 0; i < TTY_MAX_COUNT; i++) {
- tty_driver = gdm_driver[i];
- if (tty_driver) {
- tty_unregister_driver(tty_driver);
- tty_driver_kref_put(tty_driver);
- }
- }
-}
-
diff --git a/drivers/staging/gdm724x/gdm_tty.h b/drivers/staging/gdm724x/gdm_tty.h
deleted file mode 100644
index afec97ced476..000000000000
--- a/drivers/staging/gdm724x/gdm_tty.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _GDM_TTY_H_
-#define _GDM_TTY_H_
-
-#include <linux/types.h>
-#include <linux/tty.h>
-
-#define TTY_MAX_COUNT 2
-
-#define MAX_ISSUE_NUM 3
-
-enum TO_HOST_RESULT {
- TO_HOST_BUFFER_REQUEST_FAIL = 1,
- TO_HOST_PORT_CLOSE = 2,
- TO_HOST_INVALID_PACKET = 3,
-};
-
-enum RECV_PACKET_PROCESS {
- RECV_PACKET_PROCESS_COMPLETE = 0,
- RECV_PACKET_PROCESS_CONTINUE = 1,
-};
-
-struct gdm {
- struct tty_dev *tty_dev;
- struct tty_port port;
- unsigned int index;
- unsigned int minor;
-};
-
-struct tty_dev {
- void *priv_dev;
- int (*send_func)(void *priv_dev,
- void *data,
- int len,
- int tty_index,
- void (*cb)(void *cb_data),
- void *cb_data);
- int (*recv_func)(void *priv_dev,
- int (*cb)(void *data,
- int len,
- int tty_index,
- struct tty_dev *tty_dev,
- int complete));
- int (*send_control)(void *priv_dev,
- int request,
- int value,
- void *data,
- int len);
- struct gdm *gdm[2];
-};
-
-int register_lte_tty_driver(void);
-void unregister_lte_tty_driver(void);
-int register_lte_tty_device(struct tty_dev *tty_dev, struct device *dev);
-void unregister_lte_tty_device(struct tty_dev *tty_dev);
-
-#endif /* _GDM_USB_H_ */
-
diff --git a/drivers/staging/gdm724x/gdm_usb.c b/drivers/staging/gdm724x/gdm_usb.c
deleted file mode 100644
index 54bdb64f52e8..000000000000
--- a/drivers/staging/gdm724x/gdm_usb.c
+++ /dev/null
@@ -1,1012 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/usb.h>
-#include <linux/sched.h>
-#include <linux/kthread.h>
-#include <linux/usb/cdc.h>
-#include <linux/wait.h>
-#include <linux/if_ether.h>
-#include <linux/pm_runtime.h>
-
-#include "gdm_usb.h"
-#include "gdm_lte.h"
-#include "hci.h"
-#include "hci_packet.h"
-#include "gdm_endian.h"
-
-#define USB_DEVICE_CDC_DATA(vid, pid) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
- USB_DEVICE_ID_MATCH_INT_CLASS | \
- USB_DEVICE_ID_MATCH_INT_SUBCLASS,\
- .idVendor = vid,\
- .idProduct = pid,\
- .bInterfaceClass = USB_CLASS_COMM,\
- .bInterfaceSubClass = USB_CDC_SUBCLASS_ETHERNET
-
-#define USB_DEVICE_MASS_DATA(vid, pid) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
- USB_DEVICE_ID_MATCH_INT_INFO,\
- .idVendor = vid,\
- .idProduct = pid,\
- .bInterfaceSubClass = USB_SC_SCSI, \
- .bInterfaceClass = USB_CLASS_MASS_STORAGE,\
- .bInterfaceProtocol = USB_PR_BULK
-
-static const struct usb_device_id id_table[] = {
- { USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7240) }, /* GCT GDM7240 */
- { USB_DEVICE_CDC_DATA(VID_GCT, PID_GDM7243) }, /* GCT GDM7243 */
- { }
-};
-
-MODULE_DEVICE_TABLE(usb, id_table);
-
-static void do_tx(struct work_struct *work);
-static void do_rx(struct work_struct *work);
-
-static int gdm_usb_recv(void *priv_dev,
- int (*cb)(void *cb_data,
- void *data, int len, int context),
- void *cb_data,
- int context);
-
-static int request_mac_address(struct lte_udev *udev)
-{
- struct hci_packet *hci;
- struct usb_device *usbdev = udev->usbdev;
- int actual;
- int ret = -1;
-
- hci = kmalloc(struct_size(hci, data, 1), GFP_KERNEL);
- if (!hci)
- return -ENOMEM;
-
- hci->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_GET_INFORMATION);
- hci->len = gdm_cpu_to_dev16(udev->gdm_ed, 1);
- hci->data[0] = MAC_ADDRESS;
-
- ret = usb_bulk_msg(usbdev, usb_sndbulkpipe(usbdev, 2), hci, 5,
- &actual, 1000);
-
- udev->request_mac_addr = 1;
- kfree(hci);
-
- return ret;
-}
-
-static struct usb_tx *alloc_tx_struct(int len)
-{
- struct usb_tx *t = NULL;
- int ret = 0;
-
- t = kzalloc(sizeof(*t), GFP_ATOMIC);
- if (!t) {
- ret = -ENOMEM;
- goto out;
- }
-
- t->urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!(len % 512))
- len++;
-
- t->buf = kmalloc(len, GFP_ATOMIC);
- if (!t->urb || !t->buf) {
- ret = -ENOMEM;
- goto out;
- }
-
-out:
- if (ret < 0) {
- if (t) {
- usb_free_urb(t->urb);
- kfree(t->buf);
- kfree(t);
- }
- return NULL;
- }
-
- return t;
-}
-
-static struct usb_tx_sdu *alloc_tx_sdu_struct(void)
-{
- struct usb_tx_sdu *t_sdu;
-
- t_sdu = kzalloc(sizeof(*t_sdu), GFP_KERNEL);
- if (!t_sdu)
- return NULL;
-
- t_sdu->buf = kmalloc(SDU_BUF_SIZE, GFP_KERNEL);
- if (!t_sdu->buf) {
- kfree(t_sdu);
- return NULL;
- }
-
- return t_sdu;
-}
-
-static void free_tx_struct(struct usb_tx *t)
-{
- if (t) {
- usb_free_urb(t->urb);
- kfree(t->buf);
- kfree(t);
- }
-}
-
-static void free_tx_sdu_struct(struct usb_tx_sdu *t_sdu)
-{
- if (t_sdu) {
- kfree(t_sdu->buf);
- kfree(t_sdu);
- }
-}
-
-static struct usb_tx_sdu *get_tx_sdu_struct(struct tx_cxt *tx, int *no_spc)
-{
- struct usb_tx_sdu *t_sdu;
-
- if (list_empty(&tx->free_list))
- return NULL;
-
- t_sdu = list_entry(tx->free_list.next, struct usb_tx_sdu, list);
- list_del(&t_sdu->list);
-
- tx->avail_count--;
-
- *no_spc = list_empty(&tx->free_list) ? 1 : 0;
-
- return t_sdu;
-}
-
-static void put_tx_struct(struct tx_cxt *tx, struct usb_tx_sdu *t_sdu)
-{
- list_add_tail(&t_sdu->list, &tx->free_list);
- tx->avail_count++;
-}
-
-static struct usb_rx *alloc_rx_struct(void)
-{
- struct usb_rx *r = NULL;
- int ret = 0;
-
- r = kmalloc(sizeof(*r), GFP_KERNEL);
- if (!r) {
- ret = -ENOMEM;
- goto out;
- }
-
- r->urb = usb_alloc_urb(0, GFP_KERNEL);
- r->buf = kmalloc(RX_BUF_SIZE, GFP_KERNEL);
- if (!r->urb || !r->buf) {
- ret = -ENOMEM;
- goto out;
- }
-out:
-
- if (ret < 0) {
- if (r) {
- usb_free_urb(r->urb);
- kfree(r->buf);
- kfree(r);
- }
- return NULL;
- }
-
- return r;
-}
-
-static void free_rx_struct(struct usb_rx *r)
-{
- if (r) {
- usb_free_urb(r->urb);
- kfree(r->buf);
- kfree(r);
- }
-}
-
-static struct usb_rx *get_rx_struct(struct rx_cxt *rx, int *no_spc)
-{
- struct usb_rx *r;
- unsigned long flags;
-
- spin_lock_irqsave(&rx->rx_lock, flags);
-
- if (list_empty(&rx->free_list)) {
- spin_unlock_irqrestore(&rx->rx_lock, flags);
- return NULL;
- }
-
- r = list_entry(rx->free_list.next, struct usb_rx, free_list);
- list_del(&r->free_list);
-
- rx->avail_count--;
-
- *no_spc = list_empty(&rx->free_list) ? 1 : 0;
-
- spin_unlock_irqrestore(&rx->rx_lock, flags);
-
- return r;
-}
-
-static void put_rx_struct(struct rx_cxt *rx, struct usb_rx *r)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&rx->rx_lock, flags);
-
- list_add_tail(&r->free_list, &rx->free_list);
- rx->avail_count++;
-
- spin_unlock_irqrestore(&rx->rx_lock, flags);
-}
-
-static void release_usb(struct lte_udev *udev)
-{
- struct rx_cxt *rx = &udev->rx;
- struct tx_cxt *tx = &udev->tx;
- struct usb_tx *t, *t_next;
- struct usb_rx *r, *r_next;
- struct usb_tx_sdu *t_sdu, *t_sdu_next;
- unsigned long flags;
-
- spin_lock_irqsave(&tx->lock, flags);
- list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->sdu_list, list) {
- list_del(&t_sdu->list);
- free_tx_sdu_struct(t_sdu);
- }
-
- list_for_each_entry_safe(t, t_next, &tx->hci_list, list) {
- list_del(&t->list);
- free_tx_struct(t);
- }
-
- list_for_each_entry_safe(t_sdu, t_sdu_next, &tx->free_list, list) {
- list_del(&t_sdu->list);
- free_tx_sdu_struct(t_sdu);
- }
- spin_unlock_irqrestore(&tx->lock, flags);
-
- spin_lock_irqsave(&rx->submit_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
- rx_submit_list) {
- spin_unlock_irqrestore(&rx->submit_lock, flags);
- usb_kill_urb(r->urb);
- spin_lock_irqsave(&rx->submit_lock, flags);
- }
- spin_unlock_irqrestore(&rx->submit_lock, flags);
-
- spin_lock_irqsave(&rx->rx_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->free_list, free_list) {
- list_del(&r->free_list);
- free_rx_struct(r);
- }
- spin_unlock_irqrestore(&rx->rx_lock, flags);
-
- spin_lock_irqsave(&rx->to_host_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->to_host_list, to_host_list) {
- if (r->index == (void *)udev) {
- list_del(&r->to_host_list);
- free_rx_struct(r);
- }
- }
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
-}
-
-static int init_usb(struct lte_udev *udev)
-{
- int ret = 0;
- int i;
- struct tx_cxt *tx = &udev->tx;
- struct rx_cxt *rx = &udev->rx;
- struct usb_tx_sdu *t_sdu = NULL;
- struct usb_rx *r = NULL;
-
- udev->send_complete = 1;
- udev->tx_stop = 0;
- udev->request_mac_addr = 0;
- udev->usb_state = PM_NORMAL;
-
- INIT_LIST_HEAD(&tx->sdu_list);
- INIT_LIST_HEAD(&tx->hci_list);
- INIT_LIST_HEAD(&tx->free_list);
- INIT_LIST_HEAD(&rx->rx_submit_list);
- INIT_LIST_HEAD(&rx->free_list);
- INIT_LIST_HEAD(&rx->to_host_list);
- spin_lock_init(&tx->lock);
- spin_lock_init(&rx->rx_lock);
- spin_lock_init(&rx->submit_lock);
- spin_lock_init(&rx->to_host_lock);
-
- tx->avail_count = 0;
- rx->avail_count = 0;
-
- udev->rx_cb = NULL;
-
- for (i = 0; i < MAX_NUM_SDU_BUF; i++) {
- t_sdu = alloc_tx_sdu_struct();
- if (!t_sdu) {
- ret = -ENOMEM;
- goto fail;
- }
-
- list_add(&t_sdu->list, &tx->free_list);
- tx->avail_count++;
- }
-
- for (i = 0; i < MAX_RX_SUBMIT_COUNT * 2; i++) {
- r = alloc_rx_struct();
- if (!r) {
- ret = -ENOMEM;
- goto fail;
- }
-
- list_add(&r->free_list, &rx->free_list);
- rx->avail_count++;
- }
- INIT_DELAYED_WORK(&udev->work_tx, do_tx);
- INIT_DELAYED_WORK(&udev->work_rx, do_rx);
- return 0;
-fail:
- release_usb(udev);
- return ret;
-}
-
-static int set_mac_address(u8 *data, void *arg)
-{
- struct phy_dev *phy_dev = arg;
- struct lte_udev *udev = phy_dev->priv_dev;
- struct tlv *tlv = (struct tlv *)data;
- u8 mac_address[ETH_ALEN] = {0, };
-
- if (tlv->type == MAC_ADDRESS && udev->request_mac_addr) {
- memcpy(mac_address, tlv->data, tlv->len);
-
- if (register_lte_device(phy_dev,
- &udev->intf->dev, mac_address) < 0)
- pr_err("register lte device failed\n");
-
- udev->request_mac_addr = 0;
-
- return 1;
- }
-
- return 0;
-}
-
-static void do_rx(struct work_struct *work)
-{
- struct lte_udev *udev =
- container_of(work, struct lte_udev, work_rx.work);
- struct rx_cxt *rx = &udev->rx;
- struct usb_rx *r;
- struct hci_packet *hci;
- struct phy_dev *phy_dev;
- u16 cmd_evt;
- int ret;
- unsigned long flags;
-
- while (1) {
- spin_lock_irqsave(&rx->to_host_lock, flags);
- if (list_empty(&rx->to_host_list)) {
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
- break;
- }
- r = list_entry(rx->to_host_list.next,
- struct usb_rx, to_host_list);
- list_del(&r->to_host_list);
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
-
- phy_dev = r->cb_data;
- udev = phy_dev->priv_dev;
- hci = (struct hci_packet *)r->buf;
- cmd_evt = gdm_dev16_to_cpu(udev->gdm_ed, hci->cmd_evt);
-
- switch (cmd_evt) {
- case LTE_GET_INFORMATION_RESULT:
- if (set_mac_address(hci->data, r->cb_data) == 0) {
- r->callback(r->cb_data,
- r->buf,
- r->urb->actual_length,
- KERNEL_THREAD);
- }
- break;
-
- default:
- if (r->callback) {
- ret = r->callback(r->cb_data,
- r->buf,
- r->urb->actual_length,
- KERNEL_THREAD);
-
- if (ret == -EAGAIN)
- pr_err("failed to send received data\n");
- }
- break;
- }
-
- put_rx_struct(rx, r);
-
- gdm_usb_recv(udev,
- r->callback,
- r->cb_data,
- USB_COMPLETE);
- }
-}
-
-static void remove_rx_submit_list(struct usb_rx *r, struct rx_cxt *rx)
-{
- unsigned long flags;
- struct usb_rx *r_remove, *r_remove_next;
-
- spin_lock_irqsave(&rx->submit_lock, flags);
- list_for_each_entry_safe(r_remove, r_remove_next,
- &rx->rx_submit_list, rx_submit_list) {
- if (r == r_remove) {
- list_del(&r->rx_submit_list);
- break;
- }
- }
- spin_unlock_irqrestore(&rx->submit_lock, flags);
-}
-
-static void gdm_usb_rcv_complete(struct urb *urb)
-{
- struct usb_rx *r = urb->context;
- struct rx_cxt *rx = r->rx;
- unsigned long flags;
- struct lte_udev *udev = container_of(r->rx, struct lte_udev, rx);
- struct usb_device *usbdev = udev->usbdev;
-
- remove_rx_submit_list(r, rx);
-
- if (!urb->status && r->callback) {
- spin_lock_irqsave(&rx->to_host_lock, flags);
- list_add_tail(&r->to_host_list, &rx->to_host_list);
- schedule_work(&udev->work_rx.work);
- spin_unlock_irqrestore(&rx->to_host_lock, flags);
- } else {
- if (urb->status && udev->usb_state == PM_NORMAL)
- dev_err(&urb->dev->dev, "%s: urb status error %d\n",
- __func__, urb->status);
-
- put_rx_struct(rx, r);
- }
-
- usb_mark_last_busy(usbdev);
-}
-
-static int gdm_usb_recv(void *priv_dev,
- int (*cb)(void *cb_data,
- void *data, int len, int context),
- void *cb_data,
- int context)
-{
- struct lte_udev *udev = priv_dev;
- struct usb_device *usbdev = udev->usbdev;
- struct rx_cxt *rx = &udev->rx;
- struct usb_rx *r;
- int no_spc;
- int ret;
- unsigned long flags;
-
- if (!udev->usbdev) {
- pr_err("invalid device\n");
- return -ENODEV;
- }
-
- r = get_rx_struct(rx, &no_spc);
- if (!r) {
- pr_err("Out of Memory\n");
- return -ENOMEM;
- }
-
- udev->rx_cb = cb;
- r->callback = cb;
- r->cb_data = cb_data;
- r->index = (void *)udev;
- r->rx = rx;
-
- usb_fill_bulk_urb(r->urb,
- usbdev,
- usb_rcvbulkpipe(usbdev, 0x83),
- r->buf,
- RX_BUF_SIZE,
- gdm_usb_rcv_complete,
- r);
-
- spin_lock_irqsave(&rx->submit_lock, flags);
- list_add_tail(&r->rx_submit_list, &rx->rx_submit_list);
- spin_unlock_irqrestore(&rx->submit_lock, flags);
-
- if (context == KERNEL_THREAD)
- ret = usb_submit_urb(r->urb, GFP_KERNEL);
- else
- ret = usb_submit_urb(r->urb, GFP_ATOMIC);
-
- if (ret) {
- spin_lock_irqsave(&rx->submit_lock, flags);
- list_del(&r->rx_submit_list);
- spin_unlock_irqrestore(&rx->submit_lock, flags);
-
- pr_err("usb_submit_urb failed (%p)\n", r);
- put_rx_struct(rx, r);
- }
-
- return ret;
-}
-
-static void gdm_usb_send_complete(struct urb *urb)
-{
- struct usb_tx *t = urb->context;
- struct tx_cxt *tx = t->tx;
- struct lte_udev *udev = container_of(tx, struct lte_udev, tx);
- unsigned long flags;
-
- if (urb->status == -ECONNRESET) {
- dev_info(&urb->dev->dev, "CONNRESET\n");
- return;
- }
-
- if (t->callback)
- t->callback(t->cb_data);
-
- free_tx_struct(t);
-
- spin_lock_irqsave(&tx->lock, flags);
- udev->send_complete = 1;
- schedule_work(&udev->work_tx.work);
- spin_unlock_irqrestore(&tx->lock, flags);
-}
-
-static int send_tx_packet(struct usb_device *usbdev, struct usb_tx *t, u32 len)
-{
- int ret = 0;
-
- if (!(len % 512))
- len++;
-
- usb_fill_bulk_urb(t->urb,
- usbdev,
- usb_sndbulkpipe(usbdev, 2),
- t->buf,
- len,
- gdm_usb_send_complete,
- t);
-
- ret = usb_submit_urb(t->urb, GFP_ATOMIC);
-
- if (ret)
- dev_err(&usbdev->dev, "usb_submit_urb failed: %d\n",
- ret);
-
- usb_mark_last_busy(usbdev);
-
- return ret;
-}
-
-static u32 packet_aggregation(struct lte_udev *udev, u8 *send_buf)
-{
- struct tx_cxt *tx = &udev->tx;
- struct usb_tx_sdu *t_sdu = NULL;
- struct multi_sdu *multi_sdu = (struct multi_sdu *)send_buf;
- u16 send_len = 0;
- u16 num_packet = 0;
- unsigned long flags;
-
- multi_sdu->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_TX_MULTI_SDU);
-
- while (num_packet < MAX_PACKET_IN_MULTI_SDU) {
- spin_lock_irqsave(&tx->lock, flags);
- if (list_empty(&tx->sdu_list)) {
- spin_unlock_irqrestore(&tx->lock, flags);
- break;
- }
-
- t_sdu = list_entry(tx->sdu_list.next, struct usb_tx_sdu, list);
- if (send_len + t_sdu->len > MAX_SDU_SIZE) {
- spin_unlock_irqrestore(&tx->lock, flags);
- break;
- }
-
- list_del(&t_sdu->list);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- memcpy(multi_sdu->data + send_len, t_sdu->buf, t_sdu->len);
-
- send_len += (t_sdu->len + 3) & 0xfffc;
- num_packet++;
-
- if (tx->avail_count > 10)
- t_sdu->callback(t_sdu->cb_data);
-
- spin_lock_irqsave(&tx->lock, flags);
- put_tx_struct(tx, t_sdu);
- spin_unlock_irqrestore(&tx->lock, flags);
- }
-
- multi_sdu->len = gdm_cpu_to_dev16(udev->gdm_ed, send_len);
- multi_sdu->num_packet = gdm_cpu_to_dev16(udev->gdm_ed, num_packet);
-
- return send_len + offsetof(struct multi_sdu, data);
-}
-
-static void do_tx(struct work_struct *work)
-{
- struct lte_udev *udev =
- container_of(work, struct lte_udev, work_tx.work);
- struct usb_device *usbdev = udev->usbdev;
- struct tx_cxt *tx = &udev->tx;
- struct usb_tx *t = NULL;
- int is_send = 0;
- u32 len = 0;
- unsigned long flags;
-
- if (!usb_autopm_get_interface(udev->intf))
- usb_autopm_put_interface(udev->intf);
-
- if (udev->usb_state == PM_SUSPEND)
- return;
-
- spin_lock_irqsave(&tx->lock, flags);
- if (!udev->send_complete) {
- spin_unlock_irqrestore(&tx->lock, flags);
- return;
- }
- udev->send_complete = 0;
-
- if (!list_empty(&tx->hci_list)) {
- t = list_entry(tx->hci_list.next, struct usb_tx, list);
- list_del(&t->list);
- len = t->len;
- t->is_sdu = 0;
- is_send = 1;
- } else if (!list_empty(&tx->sdu_list)) {
- if (udev->tx_stop) {
- udev->send_complete = 1;
- spin_unlock_irqrestore(&tx->lock, flags);
- return;
- }
-
- t = alloc_tx_struct(TX_BUF_SIZE);
- if (!t) {
- spin_unlock_irqrestore(&tx->lock, flags);
- return;
- }
- t->callback = NULL;
- t->tx = tx;
- t->is_sdu = 1;
- is_send = 1;
- }
-
- if (!is_send) {
- udev->send_complete = 1;
- spin_unlock_irqrestore(&tx->lock, flags);
- return;
- }
- spin_unlock_irqrestore(&tx->lock, flags);
-
- if (t->is_sdu)
- len = packet_aggregation(udev, t->buf);
-
- if (send_tx_packet(usbdev, t, len)) {
- pr_err("send_tx_packet failed\n");
- t->callback = NULL;
- gdm_usb_send_complete(t->urb);
- }
-}
-
-#define SDU_PARAM_LEN 12
-static int gdm_usb_sdu_send(void *priv_dev, void *data, int len,
- unsigned int dft_eps_ID, unsigned int eps_ID,
- void (*cb)(void *data), void *cb_data,
- int dev_idx, int nic_type)
-{
- struct lte_udev *udev = priv_dev;
- struct tx_cxt *tx = &udev->tx;
- struct usb_tx_sdu *t_sdu;
- struct sdu *sdu = NULL;
- unsigned long flags;
- int no_spc = 0;
- u16 send_len;
-
- if (!udev->usbdev) {
- pr_err("sdu send - invalid device\n");
- return TX_NO_DEV;
- }
-
- spin_lock_irqsave(&tx->lock, flags);
- t_sdu = get_tx_sdu_struct(tx, &no_spc);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- if (!t_sdu) {
- pr_err("sdu send - free list empty\n");
- return TX_NO_SPC;
- }
-
- sdu = (struct sdu *)t_sdu->buf;
- sdu->cmd_evt = gdm_cpu_to_dev16(udev->gdm_ed, LTE_TX_SDU);
- if (nic_type == NIC_TYPE_ARP) {
- send_len = len + SDU_PARAM_LEN;
- memcpy(sdu->data, data, len);
- } else {
- send_len = len - ETH_HLEN;
- send_len += SDU_PARAM_LEN;
- memcpy(sdu->data, data + ETH_HLEN, len - ETH_HLEN);
- }
-
- sdu->len = gdm_cpu_to_dev16(udev->gdm_ed, send_len);
- sdu->dft_eps_ID = gdm_cpu_to_dev32(udev->gdm_ed, dft_eps_ID);
- sdu->bearer_ID = gdm_cpu_to_dev32(udev->gdm_ed, eps_ID);
- sdu->nic_type = gdm_cpu_to_dev32(udev->gdm_ed, nic_type);
-
- t_sdu->len = send_len + HCI_HEADER_SIZE;
- t_sdu->callback = cb;
- t_sdu->cb_data = cb_data;
-
- spin_lock_irqsave(&tx->lock, flags);
- list_add_tail(&t_sdu->list, &tx->sdu_list);
- schedule_work(&udev->work_tx.work);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- if (no_spc)
- return TX_NO_BUFFER;
-
- return 0;
-}
-
-static int gdm_usb_hci_send(void *priv_dev, void *data, int len,
- void (*cb)(void *data), void *cb_data)
-{
- struct lte_udev *udev = priv_dev;
- struct tx_cxt *tx = &udev->tx;
- struct usb_tx *t;
- unsigned long flags;
-
- if (!udev->usbdev) {
- pr_err("hci send - invalid device\n");
- return -ENODEV;
- }
-
- t = alloc_tx_struct(len);
- if (!t) {
- pr_err("hci_send - out of memory\n");
- return -ENOMEM;
- }
-
- memcpy(t->buf, data, len);
- t->callback = cb;
- t->cb_data = cb_data;
- t->len = len;
- t->tx = tx;
- t->is_sdu = 0;
-
- spin_lock_irqsave(&tx->lock, flags);
- list_add_tail(&t->list, &tx->hci_list);
- schedule_work(&udev->work_tx.work);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- return 0;
-}
-
-static u8 gdm_usb_get_endian(void *priv_dev)
-{
- struct lte_udev *udev = priv_dev;
-
- return udev->gdm_ed;
-}
-
-static int gdm_usb_probe(struct usb_interface *intf,
- const struct usb_device_id *id)
-{
- int ret = 0;
- struct phy_dev *phy_dev = NULL;
- struct lte_udev *udev = NULL;
- u16 idVendor, idProduct;
- int bInterfaceNumber;
- struct usb_device *usbdev = interface_to_usbdev(intf);
-
- bInterfaceNumber = intf->cur_altsetting->desc.bInterfaceNumber;
- idVendor = __le16_to_cpu(usbdev->descriptor.idVendor);
- idProduct = __le16_to_cpu(usbdev->descriptor.idProduct);
-
- pr_info("net vid = 0x%04x pid = 0x%04x\n", idVendor, idProduct);
-
- if (bInterfaceNumber > NETWORK_INTERFACE) {
- pr_info("not a network device\n");
- return -ENODEV;
- }
-
- phy_dev = kzalloc(sizeof(*phy_dev), GFP_KERNEL);
- if (!phy_dev)
- return -ENOMEM;
-
- udev = kzalloc(sizeof(*udev), GFP_KERNEL);
- if (!udev) {
- ret = -ENOMEM;
- goto err_udev;
- }
-
- phy_dev->priv_dev = (void *)udev;
- phy_dev->send_hci_func = gdm_usb_hci_send;
- phy_dev->send_sdu_func = gdm_usb_sdu_send;
- phy_dev->rcv_func = gdm_usb_recv;
- phy_dev->get_endian = gdm_usb_get_endian;
-
- udev->usbdev = usbdev;
- ret = init_usb(udev);
- if (ret < 0) {
- dev_err(intf->usb_dev, "init_usb func failed\n");
- goto err_init_usb;
- }
- udev->intf = intf;
-
- intf->needs_remote_wakeup = 1;
- usb_enable_autosuspend(usbdev);
- pm_runtime_set_autosuspend_delay(&usbdev->dev, AUTO_SUSPEND_TIMER);
-
- /* List up hosts with big endians, otherwise,
- * defaults to little endian
- */
- if (idProduct == PID_GDM7243)
- udev->gdm_ed = ENDIANNESS_BIG;
- else
- udev->gdm_ed = ENDIANNESS_LITTLE;
-
- ret = request_mac_address(udev);
- if (ret < 0) {
- dev_err(intf->usb_dev, "request Mac address failed\n");
- goto err_mac_address;
- }
-
- start_rx_proc(phy_dev);
- usb_get_dev(usbdev);
- usb_set_intfdata(intf, phy_dev);
-
- return 0;
-
-err_mac_address:
- release_usb(udev);
-err_init_usb:
- kfree(udev);
-err_udev:
- kfree(phy_dev);
-
- return ret;
-}
-
-static void gdm_usb_disconnect(struct usb_interface *intf)
-{
- struct phy_dev *phy_dev;
- struct lte_udev *udev;
- struct usb_device *usbdev;
-
- usbdev = interface_to_usbdev(intf);
- phy_dev = usb_get_intfdata(intf);
-
- udev = phy_dev->priv_dev;
- unregister_lte_device(phy_dev);
-
- release_usb(udev);
-
- kfree(udev);
- udev = NULL;
-
- kfree(phy_dev);
- phy_dev = NULL;
-
- usb_put_dev(usbdev);
-}
-
-static int gdm_usb_suspend(struct usb_interface *intf, pm_message_t pm_msg)
-{
- struct phy_dev *phy_dev;
- struct lte_udev *udev;
- struct rx_cxt *rx;
- struct usb_rx *r;
- struct usb_rx *r_next;
- unsigned long flags;
-
- phy_dev = usb_get_intfdata(intf);
- udev = phy_dev->priv_dev;
- rx = &udev->rx;
- if (udev->usb_state != PM_NORMAL) {
- dev_err(intf->usb_dev, "usb suspend - invalid state\n");
- return -1;
- }
-
- udev->usb_state = PM_SUSPEND;
-
- spin_lock_irqsave(&rx->submit_lock, flags);
- list_for_each_entry_safe(r, r_next, &rx->rx_submit_list,
- rx_submit_list) {
- spin_unlock_irqrestore(&rx->submit_lock, flags);
- usb_kill_urb(r->urb);
- spin_lock_irqsave(&rx->submit_lock, flags);
- }
- spin_unlock_irqrestore(&rx->submit_lock, flags);
-
- cancel_work_sync(&udev->work_tx.work);
- cancel_work_sync(&udev->work_rx.work);
-
- return 0;
-}
-
-static int gdm_usb_resume(struct usb_interface *intf)
-{
- struct phy_dev *phy_dev;
- struct lte_udev *udev;
- struct tx_cxt *tx;
- struct rx_cxt *rx;
- unsigned long flags;
- int issue_count;
- int i;
-
- phy_dev = usb_get_intfdata(intf);
- udev = phy_dev->priv_dev;
- rx = &udev->rx;
-
- if (udev->usb_state != PM_SUSPEND) {
- dev_err(intf->usb_dev, "usb resume - invalid state\n");
- return -1;
- }
- udev->usb_state = PM_NORMAL;
-
- spin_lock_irqsave(&rx->rx_lock, flags);
- issue_count = rx->avail_count - MAX_RX_SUBMIT_COUNT;
- spin_unlock_irqrestore(&rx->rx_lock, flags);
-
- if (issue_count >= 0) {
- for (i = 0; i < issue_count; i++)
- gdm_usb_recv(phy_dev->priv_dev,
- udev->rx_cb,
- phy_dev,
- USB_COMPLETE);
- }
-
- tx = &udev->tx;
- spin_lock_irqsave(&tx->lock, flags);
- schedule_work(&udev->work_tx.work);
- spin_unlock_irqrestore(&tx->lock, flags);
-
- return 0;
-}
-
-static struct usb_driver gdm_usb_lte_driver = {
- .name = "gdm_lte",
- .probe = gdm_usb_probe,
- .disconnect = gdm_usb_disconnect,
- .id_table = id_table,
- .supports_autosuspend = 1,
- .suspend = gdm_usb_suspend,
- .resume = gdm_usb_resume,
- .reset_resume = gdm_usb_resume,
-};
-
-static int __init gdm_usb_lte_init(void)
-{
- if (gdm_lte_event_init() < 0) {
- pr_err("error creating event\n");
- return -1;
- }
-
- return usb_register(&gdm_usb_lte_driver);
-}
-
-static void __exit gdm_usb_lte_exit(void)
-{
- gdm_lte_event_exit();
-
- usb_deregister(&gdm_usb_lte_driver);
-}
-
-module_init(gdm_usb_lte_init);
-module_exit(gdm_usb_lte_exit);
-
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_DESCRIPTION("GCT LTE USB Device Driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/gdm724x/gdm_usb.h b/drivers/staging/gdm724x/gdm_usb.h
deleted file mode 100644
index db689b091c4f..000000000000
--- a/drivers/staging/gdm724x/gdm_usb.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _GDM_USB_H_
-#define _GDM_USB_H_
-
-#include <linux/types.h>
-#include <linux/usb.h>
-#include <linux/list.h>
-#include <linux/time.h>
-
-#include "gdm_endian.h"
-#include "hci_packet.h"
-
-#define PM_NORMAL 0
-#define PM_SUSPEND 1
-#define AUTO_SUSPEND_TIMER 5000 /* ms */
-
-#define RX_BUF_SIZE (1024 * 32)
-#define TX_BUF_SIZE (1024 * 32)
-#define SDU_BUF_SIZE 2048
-#define MAX_SDU_SIZE (1024 * 30)
-#define MAX_PACKET_IN_MULTI_SDU 256
-
-#define VID_GCT 0x1076
-#define PID_GDM7240 0x8000
-#define PID_GDM7243 0x9000
-
-#define NETWORK_INTERFACE 1
-#define USB_SC_SCSI 0x06
-#define USB_PR_BULK 0x50
-
-#define MAX_NUM_SDU_BUF 64
-
-struct usb_tx {
- struct list_head list;
- struct urb *urb;
- u8 *buf;
- u32 len;
- void (*callback)(void *cb_data);
- void *cb_data;
- struct tx_cxt *tx;
- u8 is_sdu;
-};
-
-struct usb_tx_sdu {
- struct list_head list;
- u8 *buf;
- u32 len;
- void (*callback)(void *cb_data);
- void *cb_data;
-};
-
-struct usb_rx {
- struct list_head to_host_list;
- struct list_head free_list;
- struct list_head rx_submit_list;
- struct rx_cxt *rx;
- struct urb *urb;
- u8 *buf;
- int (*callback)(void *cb_data, void *data, int len, int context);
- void *cb_data;
- void *index;
-};
-
-struct tx_cxt {
- struct list_head sdu_list;
- struct list_head hci_list;
- struct list_head free_list;
- u32 avail_count;
- spinlock_t lock;
-};
-
-struct rx_cxt {
- struct list_head to_host_list;
- struct list_head rx_submit_list;
- struct list_head free_list;
- u32 avail_count;
- spinlock_t to_host_lock;
- spinlock_t rx_lock;
- spinlock_t submit_lock;
-};
-
-struct lte_udev {
- struct usb_device *usbdev;
- struct tx_cxt tx;
- struct rx_cxt rx;
- struct delayed_work work_tx;
- struct delayed_work work_rx;
- u8 gdm_ed;
- u8 send_complete;
- u8 tx_stop;
- struct usb_interface *intf;
- int (*rx_cb)(void *cb_data, void *data, int len, int context);
- int usb_state;
- u8 request_mac_addr;
-};
-
-#endif /* _GDM_USB_H_ */
diff --git a/drivers/staging/gdm724x/hci.h b/drivers/staging/gdm724x/hci.h
deleted file mode 100644
index b30945daf3a5..000000000000
--- a/drivers/staging/gdm724x/hci.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _HCI_H_
-#define _HCI_H_
-
-#define LTE_GET_INFORMATION 0x3002
-#define LTE_GET_INFORMATION_RESULT 0xB003
- #define MAC_ADDRESS 0xA2
-
-#define LTE_LINK_ON_OFF_INDICATION 0xB133
-#define LTE_PDN_TABLE_IND 0xB143
-
-#define LTE_TX_SDU 0x3200
-#define LTE_RX_SDU 0xB201
-#define LTE_TX_MULTI_SDU 0x3202
-#define LTE_RX_MULTI_SDU 0xB203
-
-#define LTE_DL_SDU_FLOW_CONTROL 0x3305
-#define LTE_UL_SDU_FLOW_CONTROL 0xB306
-
-#define LTE_AT_CMD_TO_DEVICE 0x3307
-#define LTE_AT_CMD_FROM_DEVICE 0xB308
-
-#define LTE_SDIO_DM_SEND_PKT 0x3312
-#define LTE_SDIO_DM_RECV_PKT 0xB313
-
-#define LTE_NV_RESTORE_REQUEST 0xB30C
-#define LTE_NV_RESTORE_RESPONSE 0x330D
-#define LTE_NV_SAVE_REQUEST 0xB30E
- #define NV_TYPE_LTE_INFO 0x00
- #define NV_TYPE_BOARD_CONFIG 0x01
- #define NV_TYPE_RF_CAL 0x02
- #define NV_TYPE_TEMP 0x03
- #define NV_TYPE_NET_INFO 0x04
- #define NV_TYPE_SAFETY_INFO 0x05
- #define NV_TYPE_CDMA_CAL 0x06
- #define NV_TYPE_VENDOR 0x07
- #define NV_TYPE_ALL 0xff
-#define LTE_NV_SAVE_RESPONSE 0x330F
-
-#define LTE_AT_CMD_TO_DEVICE_EXT 0x3323
-#define LTE_AT_CMD_FROM_DEVICE_EXT 0xB324
-
-#endif /* _HCI_H_ */
diff --git a/drivers/staging/gdm724x/hci_packet.h b/drivers/staging/gdm724x/hci_packet.h
deleted file mode 100644
index 3bb01e94f3b5..000000000000
--- a/drivers/staging/gdm724x/hci_packet.h
+++ /dev/null
@@ -1,82 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _HCI_PACKET_H_
-#define _HCI_PACKET_H_
-
-#define HCI_HEADER_SIZE 4
-
-/*
- * The NIC type definition:
- * For backward compatibility, lower 16 bits used as they were.
- * Lower 16 bit: NIC_TYPE values
- * Uppoer 16 bit: NIC_TYPE Flags
- */
-#define NIC_TYPE_NIC0 0x00000010
-#define NIC_TYPE_NIC1 0x00000011
-#define NIC_TYPE_NIC2 0x00000012
-#define NIC_TYPE_NIC3 0x00000013
-#define NIC_TYPE_ARP 0x00000100
-#define NIC_TYPE_ICMPV6 0x00000200
-#define NIC_TYPE_MASK 0x0000FFFF
-#define NIC_TYPE_F_IPV4 0x00010000
-#define NIC_TYPE_F_IPV6 0x00020000
-#define NIC_TYPE_F_DHCP 0x00040000
-#define NIC_TYPE_F_NDP 0x00080000
-#define NIC_TYPE_F_VLAN 0x00100000
-
-struct hci_packet {
- __dev16 cmd_evt;
- __dev16 len;
- u8 data[];
-} __packed;
-
-struct tlv {
- u8 type;
- u8 len;
- u8 *data[];
-} __packed;
-
-struct sdu_header {
- __dev16 cmd_evt;
- __dev16 len;
- __dev32 dft_eps_id;
- __dev32 bearer_ID;
- __dev32 nic_type;
-} __packed;
-
-struct sdu {
- __dev16 cmd_evt;
- __dev16 len;
- __dev32 dft_eps_ID;
- __dev32 bearer_ID;
- __dev32 nic_type;
- u8 data[];
-} __packed;
-
-struct multi_sdu {
- __dev16 cmd_evt;
- __dev16 len;
- __dev16 num_packet;
- __dev16 reserved;
- u8 data[];
-} __packed;
-
-struct hci_pdn_table_ind {
- __dev16 cmd_evt;
- __dev16 len;
- u8 activate;
- __dev32 dft_eps_id;
- __dev32 nic_type;
- u8 pdn_type;
- u8 ipv4_addr[4];
- u8 ipv6_intf_id[8];
-} __packed;
-
-struct hci_connect_ind {
- __dev16 cmd_evt;
- __dev16 len;
- __dev32 connect;
-} __packed;
-
-#endif /* _HCI_PACKET_H_ */
diff --git a/drivers/staging/gdm724x/netlink_k.c b/drivers/staging/gdm724x/netlink_k.c
deleted file mode 100644
index 8f39cc5617aa..000000000000
--- a/drivers/staging/gdm724x/netlink_k.c
+++ /dev/null
@@ -1,128 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/export.h>
-#include <linux/mutex.h>
-#include <linux/etherdevice.h>
-#include <linux/netlink.h>
-#include <asm/byteorder.h>
-#include <net/sock.h>
-
-#include "netlink_k.h"
-
-static DEFINE_MUTEX(netlink_mutex);
-
-#define ND_MAX_GROUP 30
-#define ND_IFINDEX_LEN sizeof(int)
-#define ND_NLMSG_SPACE(len) (NLMSG_SPACE(len) + ND_IFINDEX_LEN)
-#define ND_NLMSG_DATA(nlh) ((void *)((char *)NLMSG_DATA(nlh) + \
- ND_IFINDEX_LEN))
-#define ND_NLMSG_S_LEN(len) ((len) + ND_IFINDEX_LEN)
-#define ND_NLMSG_R_LEN(nlh) ((nlh)->nlmsg_len - ND_IFINDEX_LEN)
-#define ND_NLMSG_IFIDX(nlh) NLMSG_DATA(nlh)
-#define ND_MAX_MSG_LEN (1024 * 32)
-
-static void (*rcv_cb)(struct net_device *dev, u16 type, void *msg, int len);
-
-static void netlink_rcv_cb(struct sk_buff *skb)
-{
- struct nlmsghdr *nlh;
- struct net_device *dev;
- u32 mlen;
- void *msg;
- int ifindex;
-
- if (!rcv_cb) {
- pr_err("nl cb - unregistered\n");
- return;
- }
-
- if (skb->len < NLMSG_HDRLEN) {
- pr_err("nl cb - invalid skb length\n");
- return;
- }
-
- nlh = (struct nlmsghdr *)skb->data;
-
- if (skb->len < nlh->nlmsg_len || nlh->nlmsg_len > ND_MAX_MSG_LEN) {
- pr_err("nl cb - invalid length (%d,%d)\n",
- skb->len, nlh->nlmsg_len);
- return;
- }
-
- memcpy(&ifindex, ND_NLMSG_IFIDX(nlh), ND_IFINDEX_LEN);
- msg = ND_NLMSG_DATA(nlh);
- mlen = ND_NLMSG_R_LEN(nlh);
-
- dev = dev_get_by_index(&init_net, ifindex);
- if (dev) {
- rcv_cb(dev, nlh->nlmsg_type, msg, mlen);
- dev_put(dev);
- } else {
- pr_err("nl cb - dev (%d) not found\n", ifindex);
- }
-}
-
-static void netlink_rcv(struct sk_buff *skb)
-{
- mutex_lock(&netlink_mutex);
- netlink_rcv_cb(skb);
- mutex_unlock(&netlink_mutex);
-}
-
-struct sock *netlink_init(int unit,
- void (*cb)(struct net_device *dev, u16 type,
- void *msg, int len))
-{
- struct sock *sock;
- struct netlink_kernel_cfg cfg = {
- .input = netlink_rcv,
- };
-
- sock = netlink_kernel_create(&init_net, unit, &cfg);
-
- if (sock)
- rcv_cb = cb;
-
- return sock;
-}
-
-int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len,
- struct net_device *dev)
-{
- static u32 seq;
- struct sk_buff *skb = NULL;
- struct nlmsghdr *nlh;
- int ret = 0;
-
- if (group > ND_MAX_GROUP)
- return -EINVAL;
-
- if (!netlink_has_listeners(sock, group + 1))
- return -ESRCH;
-
- skb = alloc_skb(NLMSG_SPACE(len), GFP_ATOMIC);
- if (!skb)
- return -ENOMEM;
-
- seq++;
-
- nlh = nlmsg_put(skb, 0, seq, type, len, 0);
- memcpy(NLMSG_DATA(nlh), msg, len);
- NETLINK_CB(skb).portid = 0;
- NETLINK_CB(skb).dst_group = 0;
-
- ret = netlink_broadcast(sock, skb, 0, group + 1, GFP_ATOMIC);
- if (!ret)
- return len;
-
- if (ret != -ESRCH)
- netdev_err(dev, "nl broadcast g=%d, t=%d, l=%d, r=%d\n",
- group, type, len, ret);
- else if (netlink_has_listeners(sock, group + 1))
- return -EAGAIN;
-
- return ret;
-}
diff --git a/drivers/staging/gdm724x/netlink_k.h b/drivers/staging/gdm724x/netlink_k.h
deleted file mode 100644
index d42eea9bea3e..000000000000
--- a/drivers/staging/gdm724x/netlink_k.h
+++ /dev/null
@@ -1,16 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/* Copyright (c) 2012 GCT Semiconductor, Inc. All rights reserved. */
-
-#ifndef _NETLINK_K_H
-#define _NETLINK_K_H
-
-#include <linux/netdevice.h>
-#include <net/sock.h>
-
-struct sock *netlink_init(int unit,
- void (*cb)(struct net_device *dev,
- u16 type, void *msg, int len));
-int netlink_send(struct sock *sock, int group, u16 type, void *msg, int len,
- struct net_device *dev);
-
-#endif /* _NETLINK_K_H_ */
diff --git a/drivers/staging/gpib/Kconfig b/drivers/staging/gpib/Kconfig
new file mode 100644
index 000000000000..259f3ff33646
--- /dev/null
+++ b/drivers/staging/gpib/Kconfig
@@ -0,0 +1,256 @@
+# SPDX-License-Identifier: GPL-2.0
+menuconfig GPIB
+ tristate "Linux GPIB drivers"
+ help
+ Enable support for GPIB cards and dongles for Linux. GPIB
+ is the General Purpose Interface Bus which conforms to the
+ IEEE488 standard.
+
+ This set of drivers can be used with the corresponding user
+ space library that can be found on Sourceforge under linux-gpib.
+ Select the drivers for your hardware from the list.
+
+if GPIB
+
+config GPIB_COMMON
+ tristate "GPIB core"
+ help
+
+ Core common driver for all GPIB drivers. It provides the
+ interface for the userland library
+
+ To compile this driver as a module, choose M here: the module will be
+ called gpib_common
+
+config GPIB_AGILENT_82350B
+ tristate "Agilent 8235xx PCI(e) adapters"
+ depends on PCI
+ select GPIB_COMMON
+ select GPIB_TMS9914
+ help
+ Enable support for HP/Agilent/Keysight boards
+ 82350A
+ 82350B
+ 82351A
+
+ To compile this driver as a module, choose M here: the module will be
+ called agilent_82350b.
+
+config GPIB_AGILENT_82357A
+ tristate "Agilent 82357a/b USB dongles"
+ select GPIB_COMMON
+ depends on USB
+ help
+ Enable support for Agilent/Keysight 82357x USB dongles.
+
+ To compile this driver as a module, choose M here: the module will be
+ called agilent_82357a.
+
+config GPIB_CEC_PCI
+ tristate "CEC PCI board"
+ depends on PCI
+ depends on HAS_IOPORT
+ depends on !X86_PAE
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ Enable support for Capital Equipment Corporation PCI-488
+ and Keithly KPCI-488 boards.
+
+ To compile this driver as a module, choose M here: the module will be
+ called cec_gpib.
+
+config GPIB_NI_PCI_ISA
+ tristate "NI PCI/ISA compatible boards"
+ depends on ISA_BUS || PCI || PCMCIA
+ depends on HAS_IOPORT
+ depends on !X86_PAE
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ Enable support for National Instruments boards based
+ on TNT4882 chips:
+ AT-GPIB (with NAT4882 chip)
+ AT-GPIB (with NEC7210 chip)
+ AT-GPIB/TNT
+ PCI-GPIB
+ PCIe-GPIB
+ PCI-GPIB+
+ PCM-GPIB
+ PXI-GPIB
+ PCMCIA-GPIB
+ and Capital Equipment Corporation CEC-488 board.
+
+ To compile this driver as a module, choose M here: the module will be
+ called tnt4882.
+
+config GPIB_CB7210
+ tristate "Measurement Computing compatible boards"
+ depends on HAS_IOPORT
+ depends on ISA_BUS || PCI || PCMCIA
+ depends on !X86_PAE
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ Enable support for Measurement Computing (Computer Boards):
+ CPCI_GPIB, ISA-GPIB, ISA-GPIB/LC, PCI-GPIB/1M, PCI-GPIB/300K and
+ PCMCIA-GPIB
+ Quancom PCIGPIB-1 with MC cb7210 chip
+
+ To compile this driver as a module, choose M here: the module will be
+
+config GPIB_NI_USB
+ tristate "NI USB dongles"
+ select GPIB_COMMON
+ depends on USB
+ help
+ Enable support for National Instruments
+ GPIB-USB-B
+ GPIB-USB-HS
+ GPIB-USB-HS+
+ Keithly
+ KUSB-488
+ KUSB-488A
+ Measurement Computing (Computer Boards)
+ USB-488
+
+ To compile this driver as a module, choose M here: the module will be
+ called ni_usb.
+
+config GPIB_FLUKE
+ tristate "Fluke"
+ depends on OF
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ GPIB driver for Fluke based cda devices.
+
+ To compile this driver as a module, choose M here: the module will be
+ called fluke_gpib
+
+config GPIB_FMH
+ tristate "FMH FPGA based devices"
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ depends on !PPC
+ depends on OF && PCI
+ help
+ GPIB driver for fmhess FPGA based devices
+
+ To compile this driver as a module, choose M here: the module will be
+ called fmh_gpib
+
+config GPIB_GPIO
+ tristate "RPi GPIO bitbang"
+ depends on ARCH_BCM2835 || COMPILE_TEST
+ select GPIB_COMMON
+ help
+ GPIB bitbang driver Raspberry Pi GPIO adapters
+
+ To compile this driver as a module, choose M here: the module will be
+ called gpib_bitbang
+
+config GPIB_HP82335
+ tristate "HP82335/HP27209"
+ depends on ISA_BUS
+ select GPIB_COMMON
+ select GPIB_TMS9914
+ help
+ GPIB driver for HP82335 and HP27209 boards
+
+ To compile this driver as a module, choose M here: the module will be
+ called hp82335
+
+
+config GPIB_HP82341
+ tristate "HP82341x"
+ select GPIB_COMMON
+ select GPIB_TMS9914
+ depends on BROKEN
+ depends on ISA_BUS || EISA
+ help
+ GPIB driver for HP82341 A/B/C/D boards
+
+ To compile this driver as a module, choose M here: the module will be
+ called hp82341
+
+config GPIB_INES
+ tristate "INES"
+ depends on PCI || ISA_BUS || PCMCIA
+ depends on HAS_IOPORT
+ depends on !X86_PAE
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ GPIB driver for Ines compatible boards
+ Ines
+ GPIB-HS-NT
+ GPIB for Compact PCI
+ GPIB for PCI
+ GPIB for PCMCIA
+ GPIB PC/104
+ Hameg
+ HO80-2
+ Quancom
+ PCIGPIB-1 based on Ines iGPIB 72010 chip
+
+ To compile this driver as a module, choose M here: the module will be
+ called ines_gpib
+ called cb7210.
+
+config GPIB_PCMCIA
+ bool "PCMCIA/Cardbus support for NI MC and Ines boards"
+ depends on PCCARD && (GPIB_NI_PCI_ISA || GPIB_CB7210 || GPIB_INES)
+ help
+ Enable PCMCIA/CArdbus support for National Instruments,
+ measurement computing boards and Ines boards.
+
+config GPIB_LPVO
+ tristate "LPVO DIY USB GPIB"
+ select GPIB_COMMON
+ depends on USB
+ help
+ Enable support for LPVO Self-made usb-gpib adapter
+
+ To compile this driver as a module, choose M here: the module will be
+ called lpvo_usb_gpib
+
+config GPIB_PC2
+ tristate "PC2 PC2a"
+ depends on ISA_BUS
+ depends on HAS_IOPORT
+ select GPIB_COMMON
+ select GPIB_NEC7210
+ help
+ Enable support for pc2 and pc2a compatible adapters
+ Capital Equipment Corporation PC-488
+ CONTEC GP-IB(PC)
+ Hameg HO80
+ Iotech GP488B
+ Keithly MBC-488
+ Measurement Computing ISA-GPIB-PCA2
+ National Instruments PCII, PCIIa and PCII/IIa
+
+ To compile this driver as a module, choose M here: the module will be
+ called pc2_gpib
+
+
+config GPIB_TMS9914
+ tristate
+ select GPIB_COMMON
+ help
+ Enable support for TMS 9914 chip.
+
+ To compile this driver as a module, choose M here: the module will be
+ called tms9914
+
+config GPIB_NEC7210
+ tristate
+ select GPIB_COMMON
+ help
+ Enable support for NEC 7210 compatible chips.
+
+ To compile this driver as a module, choose M here: the module will be
+ called nec7210
+
+endif # GPIB
diff --git a/drivers/staging/gpib/Makefile b/drivers/staging/gpib/Makefile
new file mode 100644
index 000000000000..d0e88f5c0844
--- /dev/null
+++ b/drivers/staging/gpib/Makefile
@@ -0,0 +1,20 @@
+
+subdir-ccflags-y += -I$(src)/include -I$(src)/uapi
+
+obj-$(CONFIG_GPIB_AGILENT_82350B) += agilent_82350b/
+obj-$(CONFIG_GPIB_AGILENT_82357A) += agilent_82357a/
+obj-$(CONFIG_GPIB_CB7210) += cb7210/
+obj-$(CONFIG_GPIB_CEC_PCI) += cec/
+obj-$(CONFIG_GPIB_COMMON) += common/
+obj-$(CONFIG_GPIB_FLUKE) += eastwood/
+obj-$(CONFIG_GPIB_FMH) += fmh_gpib/
+obj-$(CONFIG_GPIB_GPIO) += gpio/
+obj-$(CONFIG_GPIB_HP82335) += hp_82335/
+obj-$(CONFIG_GPIB_HP82341) += hp_82341/
+obj-$(CONFIG_GPIB_INES) += ines/
+obj-$(CONFIG_GPIB_LPVO) += lpvo_usb_gpib/
+obj-$(CONFIG_GPIB_NEC7210) += nec7210/
+obj-$(CONFIG_GPIB_NI_USB) += ni_usb/
+obj-$(CONFIG_GPIB_PC2) += pc2/
+obj-$(CONFIG_GPIB_TMS9914) += tms9914/
+obj-$(CONFIG_GPIB_NI_PCI_ISA) += tnt4882/
diff --git a/drivers/staging/gpib/TODO b/drivers/staging/gpib/TODO
new file mode 100644
index 000000000000..bf2c39742548
--- /dev/null
+++ b/drivers/staging/gpib/TODO
@@ -0,0 +1,21 @@
+TODO:
+- checkpatch.pl fixes
+- fix device drivers that are broken ("depends on BROKEN" in Kconfig)
+- tidy-up comments:
+ - there are some "//comments" and "// comments" scattered around
+ - sometimes they are misaligned
+ - sometimes "// comments" are interleaved with "/* comments */"
+ - multiline comments should start with initial almost-blank line:
+ /*
+ * Good
+ * multiline
+ * comment
+ */
+ /* Bad
+ * multiline
+ * comment
+ */
+- resolve XXX notes where possible
+- fix FIXME notes
+- clean-up commented-out code
+- fix typos
diff --git a/drivers/staging/gpib/agilent_82350b/Makefile b/drivers/staging/gpib/agilent_82350b/Makefile
new file mode 100644
index 000000000000..d9236c92e04b
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82350b/Makefile
@@ -0,0 +1,2 @@
+
+obj-m += agilent_82350b.o
diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.c b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c
new file mode 100644
index 000000000000..53006d0cc79c
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82350b/agilent_82350b.c
@@ -0,0 +1,932 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2002, 2004 by Frank Mori Hess *
+ ***************************************************************************/
+
+#include "agilent_82350b.h"
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/dma.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for Agilent 82350b");
+
+int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &a_priv->tms9914_priv;
+ int retval = 0;
+ unsigned short event_status;
+ int i, num_fifo_bytes;
+ //hardware doesn't support checking for end-of-string character when using fifo
+ if (tms_priv->eos_flags & REOS) {
+ //pr_info("ag-rd: using tms9914 read for REOS %x EOS %x\n",tms_priv->eos_flags,
+ // tms_priv->eos);
+ return tms9914_read(board, tms_priv, buffer, length, end, bytes_read);
+ }
+
+ clear_bit(DEV_CLEAR_BN, &tms_priv->state);
+
+ read_and_clear_event_status(board);
+ *end = 0;
+ *bytes_read = 0;
+ if (length == 0)
+ return 0;
+ //disable fifo for the moment
+ writeb(DIRECTION_GPIB_TO_HOST, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+ // handle corner case of board not in holdoff and one byte might slip in early
+ if (tms_priv->holdoff_active == 0 && length > 1) {
+ size_t num_bytes;
+
+ retval = tms9914_read(board, tms_priv, buffer, 1, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ dev_err(board->gpib_dev, "%s: tms9914_read failed retval=%i\n",
+ driver_name, retval);
+ if (retval < 0 || *end)
+ return retval;
+ ++buffer;
+ --length;
+ }
+ tms9914_set_holdoff_mode(tms_priv, TMS9914_HOLDOFF_EOI);
+ tms9914_release_holdoff(tms_priv);
+ i = 0;
+ num_fifo_bytes = length - 1;
+ write_byte(tms_priv, tms_priv->imr0_bits & ~HR_BIIE, IMR0); // disable BI interrupts
+ while (i < num_fifo_bytes && *end == 0) {
+ int block_size;
+ int j;
+ int count;
+
+ if (num_fifo_bytes - i < agilent_82350b_fifo_size)
+ block_size = num_fifo_bytes - i;
+ else
+ block_size = agilent_82350b_fifo_size;
+ set_transfer_counter(a_priv, block_size);
+ writeb(ENABLE_TI_TO_SRAM | DIRECTION_GPIB_TO_HOST,
+ a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+ if (agilent_82350b_fifo_is_halted(a_priv))
+ writeb(RESTART_STREAM_BIT, a_priv->gpib_base + STREAM_STATUS_REG);
+
+ clear_bit(READ_READY_BN, &tms_priv->state);
+
+ retval = wait_event_interruptible(board->wait,
+ ((event_status =
+ read_and_clear_event_status(board)) &
+ (TERM_COUNT_STATUS_BIT |
+ BUFFER_END_STATUS_BIT)) ||
+ test_bit(DEV_CLEAR_BN, &tms_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ if (retval) {
+ dev_dbg(board->gpib_dev, "%s: read wait interrupted\n", driver_name);
+ retval = -ERESTARTSYS;
+ break;
+ }
+ count = block_size - read_transfer_counter(a_priv);
+ for (j = 0; j < count && i < num_fifo_bytes; ++j)
+ buffer[i++] = readb(a_priv->sram_base + j);
+ if (event_status & BUFFER_END_STATUS_BIT) {
+ clear_bit(RECEIVED_END_BN, &tms_priv->state);
+
+ tms_priv->holdoff_active = 1;
+ *end = 1;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ dev_err(board->gpib_dev, "%s: read timed out\n", driver_name);
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) {
+ dev_err(board->gpib_dev, "%s: device clear interrupted read\n",
+ driver_name);
+ retval = -EINTR;
+ break;
+ }
+ }
+ write_byte(tms_priv, tms_priv->imr0_bits, IMR0); // re-enable BI interrupts
+ *bytes_read += i;
+ buffer += i;
+ length -= i;
+ writeb(DIRECTION_GPIB_TO_HOST, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+ if (retval < 0)
+ return retval;
+ // read last bytes if we havn't received an END yet
+ if (*end == 0) {
+ size_t num_bytes;
+ // try to make sure we holdoff after last byte read
+ retval = tms9914_read(board, tms_priv, buffer, length, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+static int translate_wait_return_value(gpib_board_t *board, int retval)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &a_priv->tms9914_priv;
+
+ if (retval) {
+ dev_err(board->gpib_dev, "%s: write wait interrupted\n", driver_name);
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ dev_err(board->gpib_dev, "%s: write timed out\n", driver_name);
+ return -ETIMEDOUT;
+ }
+ if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) {
+ dev_err(board->gpib_dev, "%s: device clear interrupted write\n", driver_name);
+ return -EINTR;
+ }
+ return 0;
+}
+
+int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &a_priv->tms9914_priv;
+ int i, j;
+ unsigned short event_status;
+ int retval = 0;
+ int fifotransferlength = length;
+ int block_size = 0;
+ size_t num_bytes;
+
+ *bytes_written = 0;
+ if (send_eoi)
+ --fifotransferlength;
+
+ clear_bit(DEV_CLEAR_BN, &tms_priv->state);
+
+ writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+
+ event_status = read_and_clear_event_status(board);
+
+ //pr_info("ag_ac_wr: event status 0x%x tms state 0x%lx\n", event_status, tms_priv->state);
+
+#ifdef EXPERIMENTAL
+ pr_info("ag_ac_wr: wait for previous BO to complete if any\n");
+ retval = wait_event_interruptible(board->wait,
+ test_bit(DEV_CLEAR_BN, &tms_priv->state) ||
+ test_bit(WRITE_READY_BN, &tms_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ retval = translate_wait_return_value(board, retval);
+
+ if (retval)
+ return retval;
+#endif
+
+ //pr_info("ag_ac_wr: sending first byte\n");
+ retval = agilent_82350b_write(board, buffer, 1, 0, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+
+ //pr_info("ag_ac_wr: %ld bytes eoi %d tms state 0x%lx\n",length, send_eoi, tms_priv->state);
+
+ write_byte(tms_priv, tms_priv->imr0_bits & ~HR_BOIE, IMR0);
+ for (i = 1; i < fifotransferlength;) {
+ clear_bit(WRITE_READY_BN, &tms_priv->state);
+
+ if (fifotransferlength - i < agilent_82350b_fifo_size)
+ block_size = fifotransferlength - i;
+ else
+ block_size = agilent_82350b_fifo_size;
+ set_transfer_counter(a_priv, block_size);
+ for (j = 0; j < block_size; ++j, ++i) {
+ // load data into board's sram
+ writeb(buffer[i], a_priv->sram_base + j);
+ }
+ writeb(ENABLE_TI_TO_SRAM, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+
+ //pr_info("ag_ac_wr: send block: %d bytes tms 0x%lx\n", block_size,
+ // tms_priv->state);
+
+ if (agilent_82350b_fifo_is_halted(a_priv)) {
+ writeb(RESTART_STREAM_BIT, a_priv->gpib_base + STREAM_STATUS_REG);
+ // pr_info("ag_ac_wr: needed restart\n");
+ }
+
+ retval = wait_event_interruptible(board->wait,
+ ((event_status =
+ read_and_clear_event_status(board)) &
+ TERM_COUNT_STATUS_BIT) ||
+ test_bit(DEV_CLEAR_BN, &tms_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+ num_bytes = block_size - read_transfer_counter(a_priv);
+ //pr_info("ag_ac_wr: sent %ld bytes tms 0x%lx\n", num_bytes, tms_priv->state);
+
+ *bytes_written += num_bytes;
+ retval = translate_wait_return_value(board, retval);
+ if (retval)
+ break;
+ }
+ write_byte(tms_priv, tms_priv->imr0_bits, IMR0);
+ if (retval)
+ return retval;
+
+ if (send_eoi) {
+ //pr_info("ag_ac_wr: sending last byte with eoi byte no: %d\n",
+ // fifotransferlength+1);
+
+ retval = agilent_82350b_write(board, buffer + fifotransferlength, 1, send_eoi,
+ &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+unsigned short read_and_clear_event_status(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ unsigned long flags;
+ unsigned short status;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ status = a_priv->event_status_bits;
+ a_priv->event_status_bits = 0;
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return status;
+}
+
+irqreturn_t agilent_82350b_interrupt(int irq, void *arg)
+
+{
+ int tms9914_status1 = 0, tms9914_status2 = 0;
+ int event_status;
+ gpib_board_t *board = arg;
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ unsigned long flags;
+ irqreturn_t retval = IRQ_NONE;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ event_status = readb(a_priv->gpib_base + EVENT_STATUS_REG);
+ if (event_status & IRQ_STATUS_BIT)
+ retval = IRQ_HANDLED;
+
+ if (event_status & TMS9914_IRQ_STATUS_BIT) {
+ tms9914_status1 = read_byte(&a_priv->tms9914_priv, ISR0);
+ tms9914_status2 = read_byte(&a_priv->tms9914_priv, ISR1);
+ tms9914_interrupt_have_status(board, &a_priv->tms9914_priv, tms9914_status1,
+ tms9914_status2);
+ }
+//pr_info("event_status=0x%x s1 %x s2 %x\n", event_status,tms9914_status1,tms9914_status2);
+//write-clear status bits
+ if (event_status & (BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT)) {
+ writeb(event_status & (BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT),
+ a_priv->gpib_base + EVENT_STATUS_REG);
+ a_priv->event_status_bits |= event_status;
+ wake_up_interruptible(&board->wait);
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+void agilent_82350b_detach(gpib_board_t *board);
+
+const char *driver_name = "agilent_82350b";
+
+int read_transfer_counter(struct agilent_82350b_priv *a_priv)
+
+{
+ int lo, mid, value;
+
+ lo = readb(a_priv->gpib_base + XFER_COUNT_LO_REG);
+ mid = readb(a_priv->gpib_base + XFER_COUNT_MID_REG);
+ value = (lo & 0xff) | ((mid << 8) & 0x7f00);
+ value = ~(value - 1) & 0x7fff;
+ return value;
+}
+
+void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count)
+
+{
+ int complement = -count;
+
+ writeb(complement & 0xff, a_priv->gpib_base + XFER_COUNT_LO_REG);
+ writeb((complement >> 8) & 0xff, a_priv->gpib_base + XFER_COUNT_MID_REG);
+ //I don't think the hi count reg is even used, but oh well
+ writeb((complement >> 16) & 0xf, a_priv->gpib_base + XFER_COUNT_HI_REG);
+}
+
+// wrappers for interface functions
+int agilent_82350b_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read);
+}
+
+int agilent_82350b_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int agilent_82350b_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written);
+}
+
+int agilent_82350b_take_control(gpib_board_t *board, int synchronous)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_take_control_workaround(board, &priv->tms9914_priv, synchronous);
+}
+
+int agilent_82350b_go_to_standby(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_go_to_standby(board, &priv->tms9914_priv);
+}
+
+void agilent_82350b_request_system_control(gpib_board_t *board, int request_control)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+
+ if (request_control) {
+ a_priv->card_mode_bits |= CM_SYSTEM_CONTROLLER_BIT;
+ if (a_priv->model != MODEL_82350A)
+ writeb(IC_SYSTEM_CONTROLLER_BIT, a_priv->gpib_base + INTERNAL_CONFIG_REG);
+ } else {
+ a_priv->card_mode_bits &= ~CM_SYSTEM_CONTROLLER_BIT;
+ if (a_priv->model != MODEL_82350A)
+ writeb(0, a_priv->gpib_base + INTERNAL_CONFIG_REG);
+ }
+ writeb(a_priv->card_mode_bits, a_priv->gpib_base + CARD_MODE_REG);
+ tms9914_request_system_control(board, &a_priv->tms9914_priv, request_control);
+}
+
+void agilent_82350b_interface_clear(gpib_board_t *board, int assert)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_interface_clear(board, &priv->tms9914_priv, assert);
+}
+
+void agilent_82350b_remote_enable(gpib_board_t *board, int enable)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_remote_enable(board, &priv->tms9914_priv, enable);
+}
+
+int agilent_82350b_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits);
+}
+
+void agilent_82350b_disable_eos(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_disable_eos(board, &priv->tms9914_priv);
+}
+
+unsigned int agilent_82350b_update_status(gpib_board_t *board, unsigned int clear_mask)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_update_status(board, &priv->tms9914_priv, clear_mask);
+}
+
+int agilent_82350b_primary_address(gpib_board_t *board, unsigned int address)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_primary_address(board, &priv->tms9914_priv, address);
+}
+
+int agilent_82350b_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable);
+}
+
+int agilent_82350b_parallel_poll(gpib_board_t *board, uint8_t *result)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_parallel_poll(board, &priv->tms9914_priv, result);
+}
+
+void agilent_82350b_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config);
+}
+
+void agilent_82350b_parallel_poll_response(gpib_board_t *board, int ist)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist);
+}
+
+void agilent_82350b_serial_poll_response(gpib_board_t *board, uint8_t status)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_serial_poll_response(board, &priv->tms9914_priv, status);
+}
+
+uint8_t agilent_82350b_serial_poll_status(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_serial_poll_status(board, &priv->tms9914_priv);
+}
+
+int agilent_82350b_line_status(const gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ return tms9914_line_status(board, &priv->tms9914_priv);
+}
+
+unsigned int agilent_82350b_t1_delay(gpib_board_t *board, unsigned int nanosec)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ static const int nanosec_per_clock = 30;
+ unsigned int value;
+
+ tms9914_t1_delay(board, &a_priv->tms9914_priv, nanosec);
+
+ value = (nanosec + nanosec_per_clock - 1) / nanosec_per_clock;
+ if (value > 0xff)
+ value = 0xff;
+ writeb(value, a_priv->gpib_base + T1_DELAY_REG);
+ return value * nanosec_per_clock;
+}
+
+void agilent_82350b_return_to_local(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *priv = board->private_data;
+
+ tms9914_return_to_local(board, &priv->tms9914_priv);
+}
+
+int agilent_82350b_allocate_private(gpib_board_t *board)
+
+{
+ board->private_data = kzalloc(sizeof(struct agilent_82350b_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ return 0;
+}
+
+void agilent_82350b_free_private(gpib_board_t *board)
+
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+static int init_82350a_hardware(gpib_board_t *board, const gpib_board_config_t *config)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ static const unsigned int firmware_length = 5302;
+ unsigned int borg_status;
+ static const unsigned int timeout = 1000;
+ int i, j;
+ const char *firmware_data = config->init_data;
+ const unsigned int plx_cntrl_static_bits = PLX9050_WAITO_NOT_USER0_SELECT_BIT |
+ PLX9050_USER0_OUTPUT_BIT |
+ PLX9050_LLOCK_NOT_USER1_SELECT_BIT |
+ PLX9050_USER1_OUTPUT_BIT |
+ PLX9050_USER2_OUTPUT_BIT |
+ PLX9050_USER3_OUTPUT_BIT |
+ PLX9050_PCI_READ_MODE_BIT |
+ PLX9050_PCI_WRITE_MODE_BIT |
+ PLX9050_PCI_RETRY_DELAY_BITS(64) |
+ PLX9050_DIRECT_SLAVE_LOCK_ENABLE_BIT;
+
+// load borg data
+ borg_status = readb(a_priv->borg_base);
+ if ((borg_status & BORG_DONE_BIT))
+ return 0;
+ // need to programme borg
+ if (!config->init_data || config->init_data_length != firmware_length) {
+ dev_err(board->gpib_dev, "%s: the 82350A board requires firmware after powering on.\n",
+ driver_name);
+ return -EIO;
+ }
+ dev_info(board->gpib_dev, "%s: Loading firmware...\n", driver_name);
+
+ // tickle the borg
+ writel(plx_cntrl_static_bits | PLX9050_USER3_DATA_BIT,
+ a_priv->plx_base + PLX9050_CNTRL_REG);
+ usleep_range(1000, 2000);
+ writel(plx_cntrl_static_bits, a_priv->plx_base + PLX9050_CNTRL_REG);
+ usleep_range(1000, 2000);
+ writel(plx_cntrl_static_bits | PLX9050_USER3_DATA_BIT,
+ a_priv->plx_base + PLX9050_CNTRL_REG);
+ usleep_range(1000, 2000);
+
+ for (i = 0; i < config->init_data_length; ++i) {
+ for (j = 0; j < timeout && (readb(a_priv->borg_base) & BORG_READY_BIT) == 0; ++j) {
+ if (need_resched())
+ schedule();
+ usleep_range(10, 20);
+ }
+ if (j == timeout) {
+ dev_err(board->gpib_dev, "%s: timed out loading firmware.\n", driver_name);
+ return -ETIMEDOUT;
+ }
+ writeb(firmware_data[i], a_priv->gpib_base + CONFIG_DATA_REG);
+ }
+ for (j = 0; j < timeout && (readb(a_priv->borg_base) & BORG_DONE_BIT) == 0; ++j) {
+ if (need_resched())
+ schedule();
+ usleep_range(10, 20);
+ }
+ if (j == timeout) {
+ dev_err(board->gpib_dev, "%s: timed out waiting for firmware load to complete.\n",
+ driver_name);
+ return -ETIMEDOUT;
+ }
+ dev_info(board->gpib_dev, "%s: ...done.\n", driver_name);
+ return 0;
+}
+
+static int test_sram(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ unsigned int i;
+ const unsigned int sram_length = pci_resource_len(a_priv->pci_device, SRAM_82350A_REGION);
+ // test SRAM
+ const unsigned int byte_mask = 0xff;
+
+ for (i = 0; i < sram_length; ++i) {
+ writeb(i & byte_mask, a_priv->sram_base + i);
+ if (need_resched())
+ schedule();
+ }
+ for (i = 0; i < sram_length; ++i) {
+ unsigned int read_value = readb(a_priv->sram_base + i);
+
+ if ((i & byte_mask) != read_value) {
+ dev_err(board->gpib_dev, "%s: SRAM test failed at %d wanted %d got %d\n",
+ driver_name, i, (i & byte_mask), read_value);
+ return -EIO;
+ }
+ if (need_resched())
+ schedule();
+ }
+ dev_info(board->gpib_dev, "%s: SRAM test passed 0x%x bytes checked\n",
+ driver_name, sram_length);
+ return 0;
+}
+
+static int agilent_82350b_generic_attach(gpib_board_t *board, const gpib_board_config_t *config,
+ int use_fifos)
+
+{
+ struct agilent_82350b_priv *a_priv;
+ struct tms9914_priv *tms_priv;
+ int retval;
+
+ board->status = 0;
+
+ if (agilent_82350b_allocate_private(board))
+ return -ENOMEM;
+ a_priv = board->private_data;
+ a_priv->using_fifos = use_fifos;
+ tms_priv = &a_priv->tms9914_priv;
+ tms_priv->read_byte = tms9914_iomem_read_byte;
+ tms_priv->write_byte = tms9914_iomem_write_byte;
+ tms_priv->offset = 1;
+
+ // find board
+ a_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_AGILENT,
+ PCI_DEVICE_ID_82350B, NULL);
+ if (a_priv->pci_device) {
+ a_priv->model = MODEL_82350B;
+ dev_info(board->gpib_dev, "%s: Agilent 82350B board found\n", driver_name);
+
+ } else {
+ a_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_AGILENT,
+ PCI_DEVICE_ID_82351A, NULL);
+ if (a_priv->pci_device) {
+ a_priv->model = MODEL_82351A;
+ dev_info(board->gpib_dev, "%s: Agilent 82351B board found\n", driver_name);
+
+ } else {
+ a_priv->pci_device = gpib_pci_get_subsys(config, PCI_VENDOR_ID_PLX,
+ PCI_DEVICE_ID_PLX_9050,
+ PCI_VENDOR_ID_HP,
+ PCI_SUBDEVICE_ID_82350A,
+ a_priv->pci_device);
+ if (a_priv->pci_device) {
+ a_priv->model = MODEL_82350A;
+ dev_info(board->gpib_dev, "%s: HP/Agilent 82350A board found\n",
+ driver_name);
+ } else {
+ dev_err(board->gpib_dev, "%s: no 82350/82351 board found\n",
+ driver_name);
+ return -ENODEV;
+ }
+ }
+ }
+ if (pci_enable_device(a_priv->pci_device)) {
+ dev_err(board->gpib_dev, "%s: error enabling pci device\n", driver_name);
+ return -EIO;
+ }
+ if (pci_request_regions(a_priv->pci_device, driver_name))
+ return -EIO;
+ switch (a_priv->model) {
+ case MODEL_82350A:
+ a_priv->plx_base = ioremap(pci_resource_start(a_priv->pci_device, PLX_MEM_REGION),
+ pci_resource_len(a_priv->pci_device, PLX_MEM_REGION));
+ dev_dbg(board->gpib_dev, "%s: plx base address remapped to 0x%p\n",
+ driver_name, a_priv->plx_base);
+ a_priv->gpib_base = ioremap(pci_resource_start(a_priv->pci_device,
+ GPIB_82350A_REGION),
+ pci_resource_len(a_priv->pci_device,
+ GPIB_82350A_REGION));
+ dev_dbg(board->gpib_dev, "%s: gpib base address remapped to 0x%p\n",
+ driver_name, a_priv->gpib_base);
+ tms_priv->iobase = a_priv->gpib_base + TMS9914_BASE_REG;
+ a_priv->sram_base = ioremap(pci_resource_start(a_priv->pci_device,
+ SRAM_82350A_REGION),
+ pci_resource_len(a_priv->pci_device,
+ SRAM_82350A_REGION));
+ dev_dbg(board->gpib_dev, "%s: sram base address remapped to 0x%p\n",
+ driver_name, a_priv->sram_base);
+ a_priv->borg_base = ioremap(pci_resource_start(a_priv->pci_device,
+ BORG_82350A_REGION),
+ pci_resource_len(a_priv->pci_device,
+ BORG_82350A_REGION));
+ dev_dbg(board->gpib_dev, "%s: borg base address remapped to 0x%p\n",
+ driver_name, a_priv->borg_base);
+
+ retval = init_82350a_hardware(board, config);
+ if (retval < 0)
+ return retval;
+ break;
+ case MODEL_82350B:
+ case MODEL_82351A:
+ a_priv->gpib_base = ioremap(pci_resource_start(a_priv->pci_device, GPIB_REGION),
+ pci_resource_len(a_priv->pci_device, GPIB_REGION));
+ dev_dbg(board->gpib_dev, "%s: gpib base address remapped to 0x%p\n",
+ driver_name, a_priv->gpib_base);
+ tms_priv->iobase = a_priv->gpib_base + TMS9914_BASE_REG;
+ a_priv->sram_base = ioremap(pci_resource_start(a_priv->pci_device, SRAM_REGION),
+ pci_resource_len(a_priv->pci_device, SRAM_REGION));
+ dev_dbg(board->gpib_dev, "%s: sram base address remapped to 0x%p\n",
+ driver_name, a_priv->sram_base);
+ a_priv->misc_base = ioremap(pci_resource_start(a_priv->pci_device, MISC_REGION),
+ pci_resource_len(a_priv->pci_device, MISC_REGION));
+ dev_dbg(board->gpib_dev, "%s: misc base address remapped to 0x%p\n",
+ driver_name, a_priv->misc_base);
+ break;
+ default:
+ pr_err("%s: invalid board\n", driver_name);
+ return -1;
+ }
+
+ retval = test_sram(board);
+ if (retval < 0)
+ return retval;
+
+ if (request_irq(a_priv->pci_device->irq, agilent_82350b_interrupt,
+ IRQF_SHARED, driver_name, board)) {
+ pr_err("%s: can't request IRQ %d\n", driver_name, a_priv->pci_device->irq);
+ return -EIO;
+ }
+ a_priv->irq = a_priv->pci_device->irq;
+ dev_dbg(board->gpib_dev, "%s: IRQ %d\n", driver_name, a_priv->irq);
+
+ writeb(0, a_priv->gpib_base + SRAM_ACCESS_CONTROL_REG);
+ a_priv->card_mode_bits = ENABLE_PCI_IRQ_BIT;
+ writeb(a_priv->card_mode_bits, a_priv->gpib_base + CARD_MODE_REG);
+
+ if (a_priv->model == MODEL_82350A) {
+ // enable PCI interrupts for 82350a
+ writel(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR2_POLARITY_BIT |
+ PLX9050_PCI_INTR_EN_BIT,
+ a_priv->plx_base + PLX9050_INTCSR_REG);
+ }
+
+ if (use_fifos) {
+ writeb(ENABLE_BUFFER_END_EVENTS_BIT | ENABLE_TERM_COUNT_EVENTS_BIT,
+ a_priv->gpib_base + EVENT_ENABLE_REG);
+ writeb(ENABLE_TERM_COUNT_INTERRUPT_BIT | ENABLE_BUFFER_END_INTERRUPT_BIT |
+ ENABLE_TMS9914_INTERRUPTS_BIT, a_priv->gpib_base + INTERRUPT_ENABLE_REG);
+ //write-clear event status bits
+ writeb(BUFFER_END_STATUS_BIT | TERM_COUNT_STATUS_BIT,
+ a_priv->gpib_base + EVENT_STATUS_REG);
+ } else {
+ writeb(0, a_priv->gpib_base + EVENT_ENABLE_REG);
+ writeb(ENABLE_TMS9914_INTERRUPTS_BIT,
+ a_priv->gpib_base + INTERRUPT_ENABLE_REG);
+ }
+ board->t1_nano_sec = agilent_82350b_t1_delay(board, 2000);
+ tms9914_board_reset(tms_priv);
+
+ tms9914_online(board, tms_priv);
+
+ return 0;
+}
+
+int agilent_82350b_unaccel_attach(gpib_board_t *board, const gpib_board_config_t *config)
+
+{
+ return agilent_82350b_generic_attach(board, config, 0);
+}
+
+int agilent_82350b_accel_attach(gpib_board_t *board, const gpib_board_config_t *config)
+
+{
+ return agilent_82350b_generic_attach(board, config, 1);
+}
+
+void agilent_82350b_detach(gpib_board_t *board)
+
+{
+ struct agilent_82350b_priv *a_priv = board->private_data;
+ struct tms9914_priv *tms_priv;
+
+ if (a_priv) {
+ if (a_priv->plx_base) // disable interrupts
+ writel(0, a_priv->plx_base + PLX9050_INTCSR_REG);
+
+ tms_priv = &a_priv->tms9914_priv;
+ if (a_priv->irq)
+ free_irq(a_priv->irq, board);
+ if (a_priv->gpib_base) {
+ tms9914_board_reset(tms_priv);
+ if (a_priv->misc_base)
+ iounmap((void *)a_priv->misc_base);
+ if (a_priv->borg_base)
+ iounmap((void *)a_priv->borg_base);
+ if (a_priv->sram_base)
+ iounmap((void *)a_priv->sram_base);
+ if (a_priv->gpib_base)
+ iounmap((void *)a_priv->gpib_base);
+ if (a_priv->plx_base)
+ iounmap((void *)a_priv->plx_base);
+ pci_release_regions(a_priv->pci_device);
+ }
+ if (a_priv->pci_device)
+ pci_dev_put(a_priv->pci_device);
+ }
+ agilent_82350b_free_private(board);
+}
+
+gpib_interface_t agilent_82350b_unaccel_interface = {
+name: "agilent_82350b_unaccel",
+attach : agilent_82350b_unaccel_attach,
+detach : agilent_82350b_detach,
+read : agilent_82350b_read,
+write : agilent_82350b_write,
+command : agilent_82350b_command,
+request_system_control : agilent_82350b_request_system_control,
+take_control : agilent_82350b_take_control,
+go_to_standby : agilent_82350b_go_to_standby,
+interface_clear : agilent_82350b_interface_clear,
+remote_enable : agilent_82350b_remote_enable,
+enable_eos : agilent_82350b_enable_eos,
+disable_eos : agilent_82350b_disable_eos,
+parallel_poll : agilent_82350b_parallel_poll,
+parallel_poll_configure : agilent_82350b_parallel_poll_configure,
+parallel_poll_response : agilent_82350b_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : agilent_82350b_line_status,
+update_status : agilent_82350b_update_status,
+primary_address : agilent_82350b_primary_address,
+secondary_address : agilent_82350b_secondary_address,
+serial_poll_response : agilent_82350b_serial_poll_response,
+t1_delay : agilent_82350b_t1_delay,
+return_to_local : agilent_82350b_return_to_local,
+};
+
+gpib_interface_t agilent_82350b_interface = {
+name: "agilent_82350b",
+attach : agilent_82350b_accel_attach,
+detach : agilent_82350b_detach,
+read : agilent_82350b_accel_read,
+write : agilent_82350b_accel_write,
+command : agilent_82350b_command,
+request_system_control : agilent_82350b_request_system_control,
+take_control : agilent_82350b_take_control,
+go_to_standby : agilent_82350b_go_to_standby,
+interface_clear : agilent_82350b_interface_clear,
+remote_enable : agilent_82350b_remote_enable,
+enable_eos : agilent_82350b_enable_eos,
+disable_eos : agilent_82350b_disable_eos,
+parallel_poll : agilent_82350b_parallel_poll,
+parallel_poll_configure : agilent_82350b_parallel_poll_configure,
+parallel_poll_response : agilent_82350b_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : agilent_82350b_line_status,
+update_status : agilent_82350b_update_status,
+primary_address : agilent_82350b_primary_address,
+secondary_address : agilent_82350b_secondary_address,
+serial_poll_response : agilent_82350b_serial_poll_response,
+t1_delay : agilent_82350b_t1_delay,
+return_to_local : agilent_82350b_return_to_local,
+};
+
+static int agilent_82350b_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+
+{
+ return 0;
+}
+
+static const struct pci_device_id agilent_82350b_pci_table[] = {
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_HP,
+ PCI_SUBDEVICE_ID_82350A, 0, 0, 0 },
+ { PCI_VENDOR_ID_AGILENT, PCI_DEVICE_ID_82350B, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { PCI_VENDOR_ID_AGILENT, PCI_DEVICE_ID_82351A, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, agilent_82350b_pci_table);
+
+static struct pci_driver agilent_82350b_pci_driver = {
+ .name = "agilent_82350b",
+ .id_table = agilent_82350b_pci_table,
+ .probe = &agilent_82350b_pci_probe
+};
+
+static int __init agilent_82350b_init_module(void)
+
+{
+ int result;
+
+ result = pci_register_driver(&agilent_82350b_pci_driver);
+ if (result) {
+ pr_err("agilent_82350b: pci_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&agilent_82350b_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&agilent_82350b_interface, THIS_MODULE);
+ return 0;
+}
+
+static void __exit agilent_82350b_exit_module(void)
+
+{
+ gpib_unregister_driver(&agilent_82350b_interface);
+ gpib_unregister_driver(&agilent_82350b_unaccel_interface);
+
+ pci_unregister_driver(&agilent_82350b_pci_driver);
+}
+
+module_init(agilent_82350b_init_module);
+module_exit(agilent_82350b_exit_module);
diff --git a/drivers/staging/gpib/agilent_82350b/agilent_82350b.h b/drivers/staging/gpib/agilent_82350b/agilent_82350b.h
new file mode 100644
index 000000000000..30683d67d170
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82350b/agilent_82350b.h
@@ -0,0 +1,209 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002, 2004 by Frank Mori Hess *
+ ***************************************************************************/
+
+#include "gpibP.h"
+#include "plx9050.h"
+#include "tms9914.h"
+
+enum pci_vendor_ids {
+ PCI_VENDOR_ID_AGILENT = 0x15bc,
+};
+
+enum pci_device_ids {
+ PCI_DEVICE_ID_82350B = 0x0b01,
+ PCI_DEVICE_ID_82351A = 0x1218
+};
+
+enum pci_subdevice_ids {
+ PCI_SUBDEVICE_ID_82350A = 0x10b0,
+};
+
+enum pci_regions_82350a {
+ PLX_MEM_REGION = 0,
+ PLX_IO_REGION = 1,
+ GPIB_82350A_REGION = 2,
+ SRAM_82350A_REGION = 3,
+ BORG_82350A_REGION = 4
+};
+
+enum pci_regions_82350b {
+ GPIB_REGION = 0,
+ SRAM_REGION = 1,
+ MISC_REGION = 2,
+};
+
+enum board_model {
+ MODEL_82350A,
+ MODEL_82350B,
+ MODEL_82351A
+};
+
+// struct which defines private_data for board
+struct agilent_82350b_priv {
+ struct tms9914_priv tms9914_priv;
+ struct pci_dev *pci_device;
+ void *plx_base; //82350a only
+ void *gpib_base;
+ void *sram_base;
+ void *misc_base;
+ void *borg_base;
+ int irq;
+ unsigned short card_mode_bits;
+ unsigned short event_status_bits;
+ enum board_model model;
+ bool using_fifos;
+};
+
+// driver name
+extern const char *driver_name;
+
+// interfaces
+extern gpib_interface_t agilent_82350b_interface;
+// init functions
+
+int agilent_82350b_unaccel_attach(gpib_board_t *board, const gpib_board_config_t *config);
+int agilent_82350b_accel_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+// interface functions
+int agilent_82350b_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read);
+int agilent_82350b_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+int agilent_82350b_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read);
+int agilent_82350b_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+int agilent_82350b_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written);
+int agilent_82350b_take_control(gpib_board_t *board, int synchronous);
+int agilent_82350b_go_to_standby(gpib_board_t *board);
+void agilent_82350b_request_system_control(gpib_board_t *board, int request_control);
+void agilent_82350b_interface_clear(gpib_board_t *board, int assert);
+void agilent_82350b_remote_enable(gpib_board_t *board, int enable);
+int agilent_82350b_enable_eos(gpib_board_t *board, uint8_t eos_byte, int
+ compare_8_bits);
+void agilent_82350b_disable_eos(gpib_board_t *board);
+unsigned int agilent_82350b_update_status(gpib_board_t *board, unsigned int clear_mask);
+int agilent_82350b_primary_address(gpib_board_t *board, unsigned int address);
+int agilent_82350b_secondary_address(gpib_board_t *board, unsigned int address, int
+ enable);
+int agilent_82350b_parallel_poll(gpib_board_t *board, uint8_t *result);
+void agilent_82350b_parallel_poll_configure(gpib_board_t *board, uint8_t config);
+void agilent_82350b_parallel_poll_response(gpib_board_t *board, int ist);
+void agilent_82350b_serial_poll_response(gpib_board_t *board, uint8_t status);
+void agilent_82350b_return_to_local(gpib_board_t *board);
+uint8_t agilent_82350b_serial_poll_status(gpib_board_t *board);
+int agilent_82350b_line_status(const gpib_board_t *board);
+unsigned int agilent_82350b_t1_delay(gpib_board_t *board, unsigned int nanosec);
+
+// interrupt service routines
+irqreturn_t agilent_82350b_interrupt(int irq, void *arg);
+
+// utility functions
+int agilent_82350b_allocate_private(gpib_board_t *board);
+void agilent_82350b_free_private(gpib_board_t *board);
+unsigned short read_and_clear_event_status(gpib_board_t *board);
+int read_transfer_counter(struct agilent_82350b_priv *a_priv);
+void set_transfer_counter(struct agilent_82350b_priv *a_priv, int count);
+
+//registers
+enum agilent_82350b_gpib_registers
+
+{
+ CARD_MODE_REG = 0x1,
+ CONFIG_DATA_REG = 0x2, // 82350A specific
+ INTERRUPT_ENABLE_REG = 0x3,
+ EVENT_STATUS_REG = 0x4,
+ EVENT_ENABLE_REG = 0x5,
+ STREAM_STATUS_REG = 0x7,
+ DEBUG_RAM0_REG = 0x8,
+ DEBUG_RAM1_REG = 0x9,
+ DEBUG_RAM2_REG = 0xa,
+ DEBUG_RAM3_REG = 0xb,
+ XFER_COUNT_LO_REG = 0xc,
+ XFER_COUNT_MID_REG = 0xd,
+ XFER_COUNT_HI_REG = 0xe,
+ TMS9914_BASE_REG = 0x10,
+ INTERNAL_CONFIG_REG = 0x18,
+ IMR0_READ_REG = 0x19, //read
+ T1_DELAY_REG = 0x19, // write
+ IMR1_READ_REG = 0x1a,
+ ADR_READ_REG = 0x1b,
+ SPMR_READ_REG = 0x1c,
+ PPR_READ_REG = 0x1d,
+ CDOR_READ_REG = 0x1e,
+ SRAM_ACCESS_CONTROL_REG = 0x1f,
+};
+
+enum card_mode_bits
+
+{
+ ACTIVE_CONTROLLER_BIT = 0x2, // read-only
+ CM_SYSTEM_CONTROLLER_BIT = 0x8,
+ ENABLE_BUS_MONITOR_BIT = 0x10,
+ ENABLE_PCI_IRQ_BIT = 0x20,
+};
+
+enum interrupt_enable_bits
+
+{
+ ENABLE_TMS9914_INTERRUPTS_BIT = 0x1,
+ ENABLE_BUFFER_END_INTERRUPT_BIT = 0x10,
+ ENABLE_TERM_COUNT_INTERRUPT_BIT = 0x20,
+};
+
+enum event_enable_bits
+
+{
+ ENABLE_BUFFER_END_EVENTS_BIT = 0x10,
+ ENABLE_TERM_COUNT_EVENTS_BIT = 0x20,
+};
+
+enum event_status_bits
+
+{
+ TMS9914_IRQ_STATUS_BIT = 0x1,
+ IRQ_STATUS_BIT = 0x2,
+ BUFFER_END_STATUS_BIT = 0x10, // write-clear
+ TERM_COUNT_STATUS_BIT = 0x20, // write-clear
+};
+
+enum stream_status_bits
+
+{
+ HALTED_STATUS_BIT = 0x1, //read
+ RESTART_STREAM_BIT = 0x1, //write
+};
+
+enum internal_config_bits
+
+{
+ IC_SYSTEM_CONTROLLER_BIT = 0x80,
+};
+
+enum sram_access_control_bits
+
+{
+ DIRECTION_GPIB_TO_HOST = 0x20, // transfer direction
+ ENABLE_TI_TO_SRAM = 0x40, // enable fifo
+ ENABLE_FAST_TALKER = 0x80 // added for 82350A (not used)
+};
+
+enum borg_bits
+
+{
+ BORG_READY_BIT = 0x40,
+ BORG_DONE_BIT = 0x80
+};
+
+static const int agilent_82350b_fifo_size = 0x8000;
+
+static inline int agilent_82350b_fifo_is_halted(struct agilent_82350b_priv *a_priv)
+
+{
+ return readb(a_priv->gpib_base + STREAM_STATUS_REG) & HALTED_STATUS_BIT;
+}
+
diff --git a/drivers/staging/gpib/agilent_82357a/Makefile b/drivers/staging/gpib/agilent_82357a/Makefile
new file mode 100644
index 000000000000..4a1d940fce2b
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82357a/Makefile
@@ -0,0 +1,4 @@
+
+obj-m += agilent_82357a.o
+
+
diff --git a/drivers/staging/gpib/agilent_82357a/agilent_82357a.c b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c
new file mode 100644
index 000000000000..bf05fb4a736b
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82357a/agilent_82357a.c
@@ -0,0 +1,1712 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * driver for Agilent 82357A/B usb to gpib adapters *
+ * copyright : (C) 2004 by Frank Mori Hess *
+ ***************************************************************************/
+
+#define _GNU_SOURCE
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "agilent_82357a.h"
+#include "gpibP.h"
+#include "tms9914.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for Agilent 82357A/B usb adapters");
+
+#define MAX_NUM_82357A_INTERFACES 128
+static struct usb_interface *agilent_82357a_driver_interfaces[MAX_NUM_82357A_INTERFACES];
+DEFINE_MUTEX(agilent_82357a_hotplug_lock); // protect board insertion and removal
+
+static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned int clear_mask);
+
+static int agilent_82357a_take_control_internal(gpib_board_t *board, int synchronous);
+
+static void agilent_82357a_bulk_complete(struct urb *urb)
+{
+ struct agilent_82357a_urb_ctx *context = urb->context;
+
+ up(&context->complete);
+}
+
+static void agilent_82357a_timeout_handler(struct timer_list *t)
+{
+ struct agilent_82357a_priv *a_priv = from_timer(a_priv, t, bulk_timer);
+ struct agilent_82357a_urb_ctx *context = &a_priv->context;
+
+ context->timed_out = 1;
+ up(&context->complete);
+}
+
+static int agilent_82357a_send_bulk_msg(struct agilent_82357a_priv *a_priv, void *data,
+ int data_length, int *actual_data_length,
+ int timeout_msecs)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int out_pipe;
+ struct agilent_82357a_urb_ctx *context = &a_priv->context;
+
+ *actual_data_length = 0;
+ retval = mutex_lock_interruptible(&a_priv->bulk_alloc_lock);
+ if (retval)
+ return retval;
+ if (!a_priv->bus_interface) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -ENODEV;
+ }
+ if (a_priv->bulk_urb) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -EAGAIN;
+ }
+ a_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!a_priv->bulk_urb) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -ENOMEM;
+ }
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ out_pipe = usb_sndbulkpipe(usb_dev, a_priv->bulk_out_endpoint);
+ sema_init(&context->complete, 0);
+ context->timed_out = 0;
+ usb_fill_bulk_urb(a_priv->bulk_urb, usb_dev, out_pipe, data, data_length,
+ &agilent_82357a_bulk_complete, context);
+
+ if (timeout_msecs)
+ mod_timer(&a_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs));
+
+ retval = usb_submit_urb(a_priv->bulk_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ goto cleanup;
+ }
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ if (down_interruptible(&context->complete)) {
+ dev_err(&usb_dev->dev, "%s: interrupted\n", __func__);
+ retval = -ERESTARTSYS;
+ goto cleanup;
+ }
+ if (context->timed_out) {
+ retval = -ETIMEDOUT;
+ } else {
+ retval = a_priv->bulk_urb->status;
+ *actual_data_length = a_priv->bulk_urb->actual_length;
+ }
+cleanup:
+ if (timeout_msecs) {
+ if (timer_pending(&a_priv->bulk_timer))
+ del_timer_sync(&a_priv->bulk_timer);
+ }
+ mutex_lock(&a_priv->bulk_alloc_lock);
+ if (a_priv->bulk_urb) {
+ usb_kill_urb(a_priv->bulk_urb);
+ usb_free_urb(a_priv->bulk_urb);
+ a_priv->bulk_urb = NULL;
+ }
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return retval;
+}
+
+static int agilent_82357a_receive_bulk_msg(struct agilent_82357a_priv *a_priv, void *data,
+ int data_length, int *actual_data_length,
+ int timeout_msecs)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int in_pipe;
+ struct agilent_82357a_urb_ctx *context = &a_priv->context;
+
+ *actual_data_length = 0;
+ retval = mutex_lock_interruptible(&a_priv->bulk_alloc_lock);
+ if (retval)
+ return retval;
+ if (!a_priv->bus_interface) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -ENODEV;
+ }
+ if (a_priv->bulk_urb) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -EAGAIN;
+ }
+ a_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!a_priv->bulk_urb) {
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return -ENOMEM;
+ }
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ in_pipe = usb_rcvbulkpipe(usb_dev, AGILENT_82357_BULK_IN_ENDPOINT);
+ sema_init(&context->complete, 0);
+ context->timed_out = 0;
+ usb_fill_bulk_urb(a_priv->bulk_urb, usb_dev, in_pipe, data, data_length,
+ &agilent_82357a_bulk_complete, context);
+
+ if (timeout_msecs)
+ mod_timer(&a_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs));
+
+ retval = usb_submit_urb(a_priv->bulk_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ goto cleanup;
+ }
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ if (down_interruptible(&context->complete)) {
+ dev_err(&usb_dev->dev, "%s: interrupted\n", __func__);
+ retval = -ERESTARTSYS;
+ goto cleanup;
+ }
+ if (context->timed_out) {
+ retval = -ETIMEDOUT;
+ goto cleanup;
+ }
+ retval = a_priv->bulk_urb->status;
+ *actual_data_length = a_priv->bulk_urb->actual_length;
+cleanup:
+ if (timeout_msecs)
+ del_timer_sync(&a_priv->bulk_timer);
+
+ mutex_lock(&a_priv->bulk_alloc_lock);
+ if (a_priv->bulk_urb) {
+ usb_kill_urb(a_priv->bulk_urb);
+ usb_free_urb(a_priv->bulk_urb);
+ a_priv->bulk_urb = NULL;
+ }
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ return retval;
+}
+
+static int agilent_82357a_receive_control_msg(struct agilent_82357a_priv *a_priv, __u8 request,
+ __u8 requesttype, __u16 value, __u16 index,
+ void *data, __u16 size, int timeout_msecs)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int in_pipe;
+
+ retval = mutex_lock_interruptible(&a_priv->control_alloc_lock);
+ if (retval)
+ return retval;
+ if (!a_priv->bus_interface) {
+ mutex_unlock(&a_priv->control_alloc_lock);
+ return -ENODEV;
+ }
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ in_pipe = usb_rcvctrlpipe(usb_dev, AGILENT_82357_CONTROL_ENDPOINT);
+ retval = usb_control_msg(usb_dev, in_pipe, request, requesttype, value, index, data,
+ size, timeout_msecs);
+ mutex_unlock(&a_priv->control_alloc_lock);
+ return retval;
+}
+
+static void agilent_82357a_dump_raw_block(const u8 *raw_data, int length)
+{
+ pr_info("hex block dump\n");
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 8, 1, raw_data, length, true);
+}
+
+static int agilent_82357a_write_registers(struct agilent_82357a_priv *a_priv,
+ const struct agilent_82357a_register_pairlet *writes,
+ int num_writes)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ int retval;
+ u8 *out_data, *in_data;
+ int out_data_length, in_data_length;
+ int bytes_written, bytes_read;
+ int i = 0;
+ int j;
+ static const int bytes_per_write = 2;
+ static const int header_length = 2;
+ static const int max_writes = 31;
+
+ if (num_writes > max_writes) {
+ dev_err(&usb_dev->dev, "%s: bug! num_writes=%i too large\n", __func__, num_writes);
+ return -EIO;
+ }
+ out_data_length = num_writes * bytes_per_write + header_length;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+
+ out_data[i++] = DATA_PIPE_CMD_WR_REGS;
+ out_data[i++] = num_writes;
+ for (j = 0; j < num_writes; j++) {
+ out_data[i++] = writes[j].address;
+ out_data[i++] = writes[j].value;
+ }
+ if (i > out_data_length)
+ dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__);
+ retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock);
+ if (retval) {
+ kfree(out_data);
+ return retval;
+ }
+ retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return retval;
+ }
+ in_data_length = 0x20;
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+ retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length,
+ &bytes_read, 1000);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ agilent_82357a_dump_raw_block(in_data, bytes_read);
+ kfree(in_data);
+ return -EIO;
+ }
+ if (in_data[0] != (0xff & ~DATA_PIPE_CMD_WR_REGS)) {
+ dev_err(&usb_dev->dev, "%s: error, bulk command=0x%x != ~DATA_PIPE_CMD_WR_REGS\n",
+ __func__, in_data[0]);
+ return -EIO;
+ }
+ if (in_data[1]) {
+ dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x in DATA_PIPE_CMD_WR_REGS response\n",
+ __func__, in_data[1]);
+ return -EIO;
+ }
+ kfree(in_data);
+ return 0;
+}
+
+static int agilent_82357a_read_registers(struct agilent_82357a_priv *a_priv,
+ struct agilent_82357a_register_pairlet *reads,
+ int num_reads, int blocking)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ int retval;
+ u8 *out_data, *in_data;
+ int out_data_length, in_data_length;
+ int bytes_written, bytes_read;
+ int i = 0;
+ int j;
+ static const int header_length = 2;
+ static const int max_reads = 62;
+
+ if (num_reads > max_reads)
+ dev_err(&usb_dev->dev, "%s: bug! num_reads=%i too large\n", __func__, num_reads);
+
+ out_data_length = num_reads + header_length;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+
+ out_data[i++] = DATA_PIPE_CMD_RD_REGS;
+ out_data[i++] = num_reads;
+ for (j = 0; j < num_reads; j++)
+ out_data[i++] = reads[j].address;
+ if (i > out_data_length)
+ dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__);
+ if (blocking) {
+ retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock);
+ if (retval) {
+ kfree(out_data);
+ return retval;
+ }
+ } else {
+ retval = mutex_trylock(&a_priv->bulk_transfer_lock);
+ if (retval == 0) {
+ kfree(out_data);
+ return -EAGAIN;
+ }
+ }
+ retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return retval;
+ }
+ in_data_length = 0x20;
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+ retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length,
+ &bytes_read, 10000);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ agilent_82357a_dump_raw_block(in_data, bytes_read);
+ kfree(in_data);
+ return -EIO;
+ }
+ i = 0;
+ if (in_data[i++] != (0xff & ~DATA_PIPE_CMD_RD_REGS)) {
+ dev_err(&usb_dev->dev, "%s: error, bulk command=0x%x != ~DATA_PIPE_CMD_RD_REGS\n",
+ __func__, in_data[0]);
+ return -EIO;
+ }
+ if (in_data[i++]) {
+ dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x in DATA_PIPE_CMD_RD_REGS response\n",
+ __func__, in_data[1]);
+ return -EIO;
+ }
+ for (j = 0; j < num_reads; j++)
+ reads[j].value = in_data[i++];
+ kfree(in_data);
+ return 0;
+}
+
+static int agilent_82357a_abort(struct agilent_82357a_priv *a_priv, int flush)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ int retval = 0;
+ int receive_control_retval;
+ u16 wIndex = 0;
+ u8 *status_data;
+ static const unsigned int status_data_len = 2;
+
+ status_data = kmalloc(status_data_len, GFP_KERNEL);
+ if (!status_data)
+ return -ENOMEM;
+
+ if (flush)
+ wIndex |= XA_FLUSH;
+ receive_control_retval = agilent_82357a_receive_control_msg(a_priv,
+ agilent_82357a_control_request,
+ USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_DEVICE, XFER_ABORT,
+ wIndex, status_data,
+ status_data_len, 100);
+ if (receive_control_retval < 0) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_control_msg() returned %i\n",
+ __func__, receive_control_retval);
+ retval = -EIO;
+ goto cleanup;
+ }
+ if (status_data[0] != (~XFER_ABORT & 0xff)) {
+ dev_err(&usb_dev->dev, "%s: error, major code=0x%x != ~XFER_ABORT\n",
+ __func__, status_data[0]);
+ retval = -EIO;
+ goto cleanup;
+ }
+ switch (status_data[1]) {
+ case UGP_SUCCESS:
+ retval = 0;
+ break;
+ case UGP_ERR_FLUSHING:
+ if (flush) {
+ retval = 0;
+ break;
+ }
+ fallthrough;
+ case UGP_ERR_FLUSHING_ALREADY:
+ default:
+ dev_err(&usb_dev->dev, "%s: abort returned error code=0x%x\n",
+ __func__, status_data[1]);
+ retval = -EIO;
+ break;
+ }
+
+cleanup:
+ kfree(status_data);
+ return retval;
+}
+
+// interface functions
+int agilent_82357a_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written);
+
+static int agilent_82357a_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *nbytes)
+{
+ int retval;
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ u8 *out_data, *in_data;
+ int out_data_length, in_data_length;
+ int bytes_written, bytes_read;
+ int i = 0;
+ u8 trailing_flags;
+ unsigned long start_jiffies = jiffies;
+ int msec_timeout;
+
+ *nbytes = 0;
+ *end = 0;
+ out_data_length = 0x9;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = DATA_PIPE_CMD_READ;
+ out_data[i++] = 0; //primary address when ARF_NO_ADDR is not set
+ out_data[i++] = 0; //secondary address when ARF_NO_ADDR is not set
+ out_data[i] = ARF_NO_ADDRESS | ARF_END_ON_EOI;
+ if (a_priv->eos_mode & REOS)
+ out_data[i] |= ARF_END_ON_EOS_CHAR;
+ ++i;
+ out_data[i++] = length & 0xff;
+ out_data[i++] = (length >> 8) & 0xff;
+ out_data[i++] = (length >> 16) & 0xff;
+ out_data[i++] = (length >> 24) & 0xff;
+ out_data[i++] = a_priv->eos_char;
+ msec_timeout = (board->usec_timeout + 999) / 1000;
+ retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock);
+ if (retval) {
+ kfree(out_data);
+ return retval;
+ }
+ retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &bytes_written, msec_timeout);
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ if (retval < 0)
+ return retval;
+ return -EIO;
+ }
+ in_data_length = length + 1;
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+ if (board->usec_timeout != 0)
+ msec_timeout -= jiffies_to_msecs(jiffies - start_jiffies) - 1;
+ if (msec_timeout >= 0) {
+ retval = agilent_82357a_receive_bulk_msg(a_priv, in_data, in_data_length,
+ &bytes_read, msec_timeout);
+ } else {
+ retval = -ETIMEDOUT;
+ bytes_read = 0;
+ }
+ if (retval == -ETIMEDOUT) {
+ int extra_bytes_read;
+ int extra_bytes_retval;
+
+ agilent_82357a_abort(a_priv, 1);
+ extra_bytes_retval = agilent_82357a_receive_bulk_msg(a_priv, in_data + bytes_read,
+ in_data_length - bytes_read,
+ &extra_bytes_read, 100);
+ bytes_read += extra_bytes_read;
+ if (extra_bytes_retval) {
+ dev_err(&usb_dev->dev, "%s: extra_bytes_retval=%i, bytes_read=%i\n",
+ __func__, extra_bytes_retval, bytes_read);
+ agilent_82357a_abort(a_priv, 0);
+ }
+ } else if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ agilent_82357a_abort(a_priv, 0);
+ }
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ if (bytes_read > length + 1) {
+ bytes_read = length + 1;
+ pr_warn("%s: bytes_read > length? truncating", __func__);
+ }
+
+ if (bytes_read >= 1) {
+ memcpy(buffer, in_data, bytes_read - 1);
+ trailing_flags = in_data[bytes_read - 1];
+ *nbytes = bytes_read - 1;
+ if (trailing_flags & (ATRF_EOI | ATRF_EOS))
+ *end = 1;
+ }
+ kfree(in_data);
+
+ /* Fix for a bug in 9914A that does not return the contents of ADSR
+ * when the board is in listener active state and ATN is not asserted.
+ * Set ATN here to obtain a valid board level ibsta
+ */
+ agilent_82357a_take_control_internal(board, 0);
+
+ //FIXME check trailing flags for error
+ return retval;
+}
+
+static ssize_t agilent_82357a_generic_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_commands, int send_eoi, size_t *bytes_written)
+{
+ int retval;
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ u8 *out_data = NULL;
+ u8 *status_data = NULL;
+ int out_data_length;
+ int raw_bytes_written;
+ int i = 0, j;
+ int msec_timeout;
+ unsigned short bsr, adsr;
+ struct agilent_82357a_register_pairlet read_reg;
+
+ *bytes_written = 0;
+ out_data_length = length + 0x8;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = DATA_PIPE_CMD_WRITE;
+ out_data[i++] = 0; // primary address when AWF_NO_ADDRESS is not set
+ out_data[i++] = 0; // secondary address when AWF_NO_ADDRESS is not set
+ out_data[i] = AWF_NO_ADDRESS | AWF_NO_FAST_TALKER_FIRST_BYTE;
+ if (send_commands)
+ out_data[i] |= AWF_ATN | AWF_NO_FAST_TALKER;
+ if (send_eoi)
+ out_data[i] |= AWF_SEND_EOI;
+ ++i;
+ out_data[i++] = length & 0xff;
+ out_data[i++] = (length >> 8) & 0xff;
+ out_data[i++] = (length >> 16) & 0xff;
+ out_data[i++] = (length >> 24) & 0xff;
+ for (j = 0; j < length; j++)
+ out_data[i++] = buffer[j];
+
+ clear_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags);
+
+ msec_timeout = (board->usec_timeout + 999) / 1000;
+ retval = mutex_lock_interruptible(&a_priv->bulk_transfer_lock);
+ if (retval) {
+ kfree(out_data);
+ return retval;
+ }
+ retval = agilent_82357a_send_bulk_msg(a_priv, out_data, i, &raw_bytes_written,
+ msec_timeout);
+ kfree(out_data);
+ if (retval || raw_bytes_written != i) {
+ agilent_82357a_abort(a_priv, 0);
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_send_bulk_msg returned %i, raw_bytes_written=%i, i=%i\n",
+ __func__, retval, raw_bytes_written, i);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ if (retval < 0)
+ return retval;
+ return -EIO;
+ }
+
+ retval = wait_event_interruptible(board->wait,
+ test_bit(AIF_WRITE_COMPLETE_BN,
+ &a_priv->interrupt_flags) ||
+ test_bit(TIMO_NUM, &board->status));
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: wait write complete interrupted\n", __func__);
+ agilent_82357a_abort(a_priv, 0);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return -ERESTARTSYS;
+ }
+
+ if (test_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags) == 0) {
+ dev_dbg(&usb_dev->dev, "write timed out ibs %i, tmo %i\n",
+ test_bit(TIMO_NUM, &board->status), msec_timeout);
+
+ agilent_82357a_abort(a_priv, 0);
+
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+
+ read_reg.address = BSR;
+ retval = agilent_82357a_read_registers(a_priv, &read_reg, 1, 1);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+
+ bsr = read_reg.value;
+ dev_dbg(&usb_dev->dev, "write aborted bsr 0x%x\n", bsr);
+
+ if (send_commands) {/* check for no listeners */
+ if ((bsr & BSR_ATN_BIT) && !(bsr & (BSR_NDAC_BIT | BSR_NRFD_BIT))) {
+ dev_dbg(&usb_dev->dev, "No listener on command\n");
+ clear_bit(TIMO_NUM, &board->status);
+ return -ENOTCONN; // no listener on bus
+ }
+ } else {
+ read_reg.address = ADSR;
+ retval = agilent_82357a_read_registers(a_priv, &read_reg, 1, 1);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return -ETIMEDOUT;
+ }
+ adsr = read_reg.value;
+ if ((adsr & HR_TA) && !(bsr & (BSR_NDAC_BIT | BSR_NRFD_BIT))) {
+ dev_dbg(&usb_dev->dev, "No listener on write\n");
+ clear_bit(TIMO_NUM, &board->status);
+ return -ECOMM;
+ }
+ }
+
+ return -ETIMEDOUT;
+ }
+
+ status_data = kmalloc(STATUS_DATA_LEN, GFP_KERNEL);
+ if (!status_data) {
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+
+ retval = agilent_82357a_receive_control_msg(a_priv, agilent_82357a_control_request,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ XFER_STATUS, 0, status_data, STATUS_DATA_LEN,
+ 100);
+ mutex_unlock(&a_priv->bulk_transfer_lock);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_receive_control_msg() returned %i\n",
+ __func__, retval);
+ kfree(status_data);
+ return -EIO;
+ }
+ *bytes_written = (u32)status_data[2];
+ *bytes_written |= (u32)status_data[3] << 8;
+ *bytes_written |= (u32)status_data[4] << 16;
+ *bytes_written |= (u32)status_data[5] << 24;
+
+ kfree(status_data);
+ return 0;
+}
+
+static int agilent_82357a_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ return agilent_82357a_generic_write(board, buffer, length, 0, send_eoi, bytes_written);
+}
+
+int agilent_82357a_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+{
+ return agilent_82357a_generic_write(board, buffer, length, 1, 0, bytes_written);
+}
+
+int agilent_82357a_take_control_internal(gpib_board_t *board, int synchronous)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ write.address = AUXCR;
+ if (synchronous)
+ write.value = AUX_TCS;
+ else
+ write.value = AUX_TCA;
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+
+ return retval;
+}
+
+static int agilent_82357a_take_control(gpib_board_t *board, int synchronous)
+{
+ const int timeout = 10;
+ int i;
+
+/* It looks like the 9914 does not handle tcs properly.
+ * See comment above tms9914_take_control_workaround() in
+ * drivers/gpib/tms9914/tms9914_aux.c
+ */
+ if (synchronous)
+ return -ETIMEDOUT;
+
+ agilent_82357a_take_control_internal(board, synchronous);
+ // busy wait until ATN is asserted
+ for (i = 0; i < timeout; ++i) {
+ agilent_82357a_update_status(board, 0);
+ if (test_bit(ATN_NUM, &board->status))
+ break;
+ udelay(1);
+ }
+ if (i == timeout)
+ return -ETIMEDOUT;
+ return 0;
+}
+
+static int agilent_82357a_go_to_standby(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ write.address = AUXCR;
+ write.value = AUX_GTS;
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return 0;
+}
+
+//FIXME should change prototype to return int
+static void agilent_82357a_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet writes[2];
+ int retval;
+ int i = 0;
+
+ /* 82357B needs bit to be set in 9914 AUXCR register */
+ writes[i].address = AUXCR;
+ if (request_control) {
+ writes[i].value = AUX_RQC;
+ a_priv->hw_control_bits |= SYSTEM_CONTROLLER;
+ } else {
+ writes[i].value = AUX_RLC;
+ a_priv->is_cic = 0;
+ a_priv->hw_control_bits &= ~SYSTEM_CONTROLLER;
+ }
+ ++i;
+ writes[i].address = HW_CONTROL;
+ writes[i].value = a_priv->hw_control_bits;
+ ++i;
+ retval = agilent_82357a_write_registers(a_priv, writes, i);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return;// retval;
+}
+
+static void agilent_82357a_interface_clear(gpib_board_t *board, int assert)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ write.address = AUXCR;
+ write.value = AUX_SIC;
+ if (assert) {
+ write.value |= AUX_CS;
+ a_priv->is_cic = 1;
+ }
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+}
+
+static void agilent_82357a_remote_enable(gpib_board_t *board, int enable)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ write.address = AUXCR;
+ write.value = AUX_SRE;
+ if (enable)
+ write.value |= AUX_CS;
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ a_priv->ren_state = enable;
+ return;// 0;
+}
+
+static int agilent_82357a_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+
+ if (compare_8_bits == 0) {
+ pr_warn("%s: hardware only supports 8-bit EOS compare", __func__);
+ return -EOPNOTSUPP;
+ }
+ a_priv->eos_char = eos_byte;
+ a_priv->eos_mode = REOS | BIN;
+ return 0;
+}
+
+static void agilent_82357a_disable_eos(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+
+ a_priv->eos_mode &= ~REOS;
+}
+
+static unsigned int agilent_82357a_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet address_status, bus_status;
+ int retval;
+
+ board->status &= ~clear_mask;
+ if (a_priv->is_cic)
+ set_bit(CIC_NUM, &board->status);
+ else
+ clear_bit(CIC_NUM, &board->status);
+ address_status.address = ADSR;
+ retval = agilent_82357a_read_registers(a_priv, &address_status, 1, 0);
+ if (retval) {
+ if (retval != -EAGAIN)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return board->status;
+ }
+ // check for remote/local
+ if (address_status.value & HR_REM)
+ set_bit(REM_NUM, &board->status);
+ else
+ clear_bit(REM_NUM, &board->status);
+ // check for lockout
+ if (address_status.value & HR_LLO)
+ set_bit(LOK_NUM, &board->status);
+ else
+ clear_bit(LOK_NUM, &board->status);
+ // check for ATN
+ if (address_status.value & HR_ATN)
+ set_bit(ATN_NUM, &board->status);
+ else
+ clear_bit(ATN_NUM, &board->status);
+ // check for talker/listener addressed
+ if (address_status.value & HR_TA)
+ set_bit(TACS_NUM, &board->status);
+ else
+ clear_bit(TACS_NUM, &board->status);
+ if (address_status.value & HR_LA)
+ set_bit(LACS_NUM, &board->status);
+ else
+ clear_bit(LACS_NUM, &board->status);
+
+ bus_status.address = BSR;
+ retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0);
+ if (retval) {
+ if (retval != -EAGAIN)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return board->status;
+ }
+ if (bus_status.value & BSR_SRQ_BIT)
+ set_bit(SRQI_NUM, &board->status);
+ else
+ clear_bit(SRQI_NUM, &board->status);
+
+ return board->status;
+}
+
+static int agilent_82357a_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ // put primary address in address0
+ write.address = ADR;
+ write.value = address & ADDRESS_MASK;
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return retval;
+ }
+ return retval;
+}
+
+static int agilent_82357a_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ if (enable)
+ pr_warn("%s: warning: assigning a secondary address not supported\n", __func__);
+ return -EOPNOTSUPP;
+}
+
+static int agilent_82357a_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet writes[2];
+ struct agilent_82357a_register_pairlet read;
+ int retval;
+
+ // execute parallel poll
+ writes[0].address = AUXCR;
+ writes[0].value = AUX_CS | AUX_RPP;
+ writes[1].address = HW_CONTROL;
+ writes[1].value = a_priv->hw_control_bits & ~NOT_PARALLEL_POLL;
+ retval = agilent_82357a_write_registers(a_priv, writes, 2);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return retval;
+ }
+ udelay(2); //silly, since usb write will take way longer
+ read.address = CPTR;
+ retval = agilent_82357a_read_registers(a_priv, &read, 1, 1);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return retval;
+ }
+ *result = read.value;
+ // clear parallel poll state
+ writes[0].address = HW_CONTROL;
+ writes[0].value = a_priv->hw_control_bits | NOT_PARALLEL_POLL;
+ writes[1].address = AUXCR;
+ writes[1].value = AUX_RPP;
+ retval = agilent_82357a_write_registers(a_priv, writes, 2);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return retval;
+ }
+ return 0;
+}
+
+static void agilent_82357a_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ //board can only be system controller
+ return;// 0;
+}
+
+static void agilent_82357a_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ //board can only be system controller
+ return;// 0;
+}
+
+static void agilent_82357a_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ //board can only be system controller
+ return;// 0;
+}
+
+static uint8_t agilent_82357a_serial_poll_status(gpib_board_t *board)
+{
+ //board can only be system controller
+ return 0;
+}
+
+static void agilent_82357a_return_to_local(gpib_board_t *board)
+{
+ //board can only be system controller
+ return;// 0;
+}
+
+static int agilent_82357a_line_status(const gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet bus_status;
+ int retval;
+ int status = ValidALL;
+
+ bus_status.address = BSR;
+ retval = agilent_82357a_read_registers(a_priv, &bus_status, 1, 0);
+ if (retval) {
+ if (retval != -EAGAIN)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return retval;
+ }
+ if (bus_status.value & BSR_REN_BIT)
+ status |= BusREN;
+ if (bus_status.value & BSR_IFC_BIT)
+ status |= BusIFC;
+ if (bus_status.value & BSR_SRQ_BIT)
+ status |= BusSRQ;
+ if (bus_status.value & BSR_EOI_BIT)
+ status |= BusEOI;
+ if (bus_status.value & BSR_NRFD_BIT)
+ status |= BusNRFD;
+ if (bus_status.value & BSR_NDAC_BIT)
+ status |= BusNDAC;
+ if (bus_status.value & BSR_DAV_BIT)
+ status |= BusDAV;
+ if (bus_status.value & BSR_ATN_BIT)
+ status |= BusATN;
+ return status;
+}
+
+static unsigned short nanosec_to_fast_talker_bits(unsigned int *nanosec)
+{
+ static const int nanosec_per_bit = 21;
+ static const int max_value = 0x72;
+ static const int min_value = 0x11;
+ unsigned short bits;
+
+ bits = (*nanosec + nanosec_per_bit / 2) / nanosec_per_bit;
+ if (bits < min_value)
+ bits = min_value;
+ if (bits > max_value)
+ bits = max_value;
+ *nanosec = bits * nanosec_per_bit;
+ return bits;
+}
+
+static unsigned int agilent_82357a_t1_delay(gpib_board_t *board, unsigned int nanosec)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet write;
+ int retval;
+
+ write.address = FAST_TALKER_T1;
+ write.value = nanosec_to_fast_talker_bits(&nanosec);
+ retval = agilent_82357a_write_registers(a_priv, &write, 1);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return nanosec;
+}
+
+static void agilent_82357a_interrupt_complete(struct urb *urb)
+{
+ gpib_board_t *board = urb->context;
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ int retval;
+ u8 *transfer_buffer = urb->transfer_buffer;
+ unsigned long interrupt_flags;
+
+ switch (urb->status) {
+ /* success */
+ case 0:
+ break;
+ /* unlinked, don't resubmit */
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default: /* other error, resubmit */
+ retval = usb_submit_urb(a_priv->interrupt_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__);
+ return;
+ }
+
+ interrupt_flags = transfer_buffer[0];
+ if (test_bit(AIF_READ_COMPLETE_BN, &interrupt_flags))
+ set_bit(AIF_READ_COMPLETE_BN, &a_priv->interrupt_flags);
+ if (test_bit(AIF_WRITE_COMPLETE_BN, &interrupt_flags))
+ set_bit(AIF_WRITE_COMPLETE_BN, &a_priv->interrupt_flags);
+ if (test_bit(AIF_SRQ_BN, &interrupt_flags))
+ set_bit(SRQI_NUM, &board->status);
+
+ wake_up_interruptible(&board->wait);
+
+ retval = usb_submit_urb(a_priv->interrupt_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__);
+}
+
+static int agilent_82357a_setup_urbs(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev;
+ int int_pipe;
+ int retval;
+
+ retval = mutex_lock_interruptible(&a_priv->interrupt_alloc_lock);
+ if (retval)
+ return retval;
+ if (!a_priv->bus_interface) {
+ retval = -ENODEV;
+ goto setup_exit;
+ }
+
+ a_priv->interrupt_buffer = kmalloc(INTERRUPT_BUF_LEN, GFP_KERNEL);
+ if (!a_priv->interrupt_buffer) {
+ retval = -ENOMEM;
+ goto setup_exit;
+ }
+ a_priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!a_priv->interrupt_urb) {
+ retval = -ENOMEM;
+ goto setup_exit;
+ }
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ int_pipe = usb_rcvintpipe(usb_dev, a_priv->interrupt_in_endpoint);
+ usb_fill_int_urb(a_priv->interrupt_urb, usb_dev, int_pipe, a_priv->interrupt_buffer,
+ INTERRUPT_BUF_LEN, &agilent_82357a_interrupt_complete, board, 1);
+ retval = usb_submit_urb(a_priv->interrupt_urb, GFP_KERNEL);
+ if (retval) {
+ usb_free_urb(a_priv->interrupt_urb);
+ a_priv->interrupt_urb = NULL;
+ dev_err(&usb_dev->dev, "%s: failed to submit first interrupt urb, retval=%i\n",
+ __func__, retval);
+ goto setup_exit;
+ }
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ return 0;
+
+setup_exit:
+ kfree(a_priv->interrupt_buffer);
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ return retval;
+}
+
+#ifdef RESET_USB_CONFIG
+static int agilent_82357a_reset_usb_configuration(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct usb_device *usb_dev;
+ int retval;
+
+ if (!a_priv->bus_interface)
+ return -ENODEV;
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ retval = usb_reset_configuration(usb_dev);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: usb_reset_configuration() returned %i\n",
+ __func__, retval);
+ return retval;
+}
+#endif
+
+static void agilent_82357a_cleanup_urbs(struct agilent_82357a_priv *a_priv)
+{
+ if (a_priv && a_priv->bus_interface) {
+ if (a_priv->interrupt_urb)
+ usb_kill_urb(a_priv->interrupt_urb);
+ if (a_priv->bulk_urb)
+ usb_kill_urb(a_priv->bulk_urb);
+ }
+};
+
+static int agilent_82357a_allocate_private(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv;
+
+ board->private_data = kmalloc(sizeof(struct agilent_82357a_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ a_priv = board->private_data;
+ memset(a_priv, 0, sizeof(struct agilent_82357a_priv));
+ mutex_init(&a_priv->bulk_transfer_lock);
+ mutex_init(&a_priv->bulk_alloc_lock);
+ mutex_init(&a_priv->control_alloc_lock);
+ mutex_init(&a_priv->interrupt_alloc_lock);
+ return 0;
+}
+
+static void agilent_82357a_free_private(struct agilent_82357a_priv *a_priv)
+{
+ usb_free_urb(a_priv->interrupt_urb);
+ kfree(a_priv->interrupt_buffer);
+ kfree(a_priv);
+}
+
+static int agilent_82357a_init(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet hw_control;
+ struct agilent_82357a_register_pairlet writes[0x20];
+ int retval;
+ int i;
+ unsigned int nanosec;
+
+ i = 0;
+ writes[i].address = LED_CONTROL;
+ writes[i].value = FAIL_LED_ON;
+ ++i;
+ writes[i].address = RESET_TO_POWERUP;
+ writes[i].value = RESET_SPACEBALL;
+ ++i;
+ retval = agilent_82357a_write_registers(a_priv, writes, i);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return -EIO;
+ }
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (schedule_timeout(usec_to_jiffies(2000)))
+ return -ERESTARTSYS;
+ i = 0;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_NBAF;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_HLDE;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_TON;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_LON;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_RSV2;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_INVAL;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_RPP;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_STDL;
+ ++i;
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_VSTDL;
+ ++i;
+ writes[i].address = FAST_TALKER_T1;
+ nanosec = board->t1_nano_sec;
+ writes[i].value = nanosec_to_fast_talker_bits(&nanosec);
+ board->t1_nano_sec = nanosec;
+ ++i;
+ writes[i].address = ADR;
+ writes[i].value = board->pad & ADDRESS_MASK;
+ ++i;
+ writes[i].address = PPR;
+ writes[i].value = 0;
+ ++i;
+ writes[i].address = SPMR;
+ writes[i].value = 0;
+ ++i;
+ writes[i].address = PROTOCOL_CONTROL;
+ writes[i].value = WRITE_COMPLETE_INTERRUPT_EN;
+ ++i;
+ writes[i].address = IMR0;
+ writes[i].value = HR_BOIE | HR_BIIE;
+ ++i;
+ writes[i].address = IMR1;
+ writes[i].value = HR_SRQIE;
+ ++i;
+ // turn off reset state
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_CHIP_RESET;
+ ++i;
+ writes[i].address = LED_CONTROL;
+ writes[i].value = FIRMWARE_LED_CONTROL;
+ ++i;
+ if (i > ARRAY_SIZE(writes)) {
+ dev_err(&usb_dev->dev, "%s: bug! writes[] overflow\n", __func__);
+ return -EFAULT;
+ }
+ retval = agilent_82357a_write_registers(a_priv, writes, i);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return -EIO;
+ }
+ hw_control.address = HW_CONTROL;
+ retval = agilent_82357a_read_registers(a_priv, &hw_control, 1, 1);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_read_registers() returned error\n",
+ __func__);
+ return -EIO;
+ }
+ a_priv->hw_control_bits = (hw_control.value & ~0x7) | NOT_TI_RESET | NOT_PARALLEL_POLL;
+
+ return 0;
+}
+
+static inline int agilent_82357a_device_match(struct usb_interface *interface,
+ const gpib_board_config_t *config)
+{
+ struct usb_device * const usbdev = interface_to_usbdev(interface);
+
+ if (gpib_match_device_path(&interface->dev, config->device_path) == 0)
+ return 0;
+ if (config->serial_number &&
+ strcmp(usbdev->serial, config->serial_number) != 0)
+ return 0;
+
+ return 1;
+}
+
+static int agilent_82357a_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int retval;
+ int i;
+ unsigned int product_id;
+ struct agilent_82357a_priv *a_priv;
+ struct usb_device *usb_dev;
+
+ if (mutex_lock_interruptible(&agilent_82357a_hotplug_lock))
+ return -ERESTARTSYS;
+
+ retval = agilent_82357a_allocate_private(board);
+ if (retval < 0) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+ a_priv = board->private_data;
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
+ if (agilent_82357a_driver_interfaces[i] &&
+ !usb_get_intfdata(agilent_82357a_driver_interfaces[i]) &&
+ agilent_82357a_device_match(agilent_82357a_driver_interfaces[i], config)) {
+ a_priv->bus_interface = agilent_82357a_driver_interfaces[i];
+ usb_set_intfdata(agilent_82357a_driver_interfaces[i], board);
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d attached to gpib minor %d, agilent usb interface %i\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ break;
+ }
+ }
+ if (i == MAX_NUM_82357A_INTERFACES) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ pr_err("No Agilent 82357 gpib adapters found, have you loaded its firmware?\n");
+ return -ENODEV;
+ }
+ product_id = le16_to_cpu(interface_to_usbdev(a_priv->bus_interface)->descriptor.idProduct);
+ switch (product_id) {
+ case USB_DEVICE_ID_AGILENT_82357A:
+ a_priv->bulk_out_endpoint = AGILENT_82357A_BULK_OUT_ENDPOINT;
+ a_priv->interrupt_in_endpoint = AGILENT_82357A_INTERRUPT_IN_ENDPOINT;
+ break;
+ case USB_DEVICE_ID_AGILENT_82357B:
+ a_priv->bulk_out_endpoint = AGILENT_82357B_BULK_OUT_ENDPOINT;
+ a_priv->interrupt_in_endpoint = AGILENT_82357B_INTERRUPT_IN_ENDPOINT;
+ break;
+ default:
+ dev_err(&usb_dev->dev, "bug, unhandled product_id in switch?\n");
+ return -EIO;
+ }
+#ifdef RESET_USB_CONFIG
+ retval = agilent_82357a_reset_usb_configuration(board);
+ if (retval < 0) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+#endif
+ retval = agilent_82357a_setup_urbs(board);
+ if (retval < 0) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+
+ timer_setup(&a_priv->bulk_timer, agilent_82357a_timeout_handler, 0);
+
+ board->t1_nano_sec = 800;
+
+ retval = agilent_82357a_init(board);
+
+ if (retval < 0) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+
+ dev_info(&usb_dev->dev, "%s: attached\n", __func__);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+}
+
+static int agilent_82357a_go_idle(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ struct agilent_82357a_register_pairlet writes[0x20];
+ int retval;
+ int i;
+
+ i = 0;
+ // turn on tms9914 reset state
+ writes[i].address = AUXCR;
+ writes[i].value = AUX_CS | AUX_CHIP_RESET;
+ ++i;
+ a_priv->hw_control_bits &= ~NOT_TI_RESET;
+ writes[i].address = HW_CONTROL;
+ writes[i].value = a_priv->hw_control_bits;
+ ++i;
+ writes[i].address = PROTOCOL_CONTROL;
+ writes[i].value = 0;
+ ++i;
+ writes[i].address = IMR0;
+ writes[i].value = 0;
+ ++i;
+ writes[i].address = IMR1;
+ writes[i].value = 0;
+ ++i;
+ writes[i].address = LED_CONTROL;
+ writes[i].value = 0;
+ ++i;
+ if (i > ARRAY_SIZE(writes)) {
+ dev_err(&usb_dev->dev, "%s: bug! writes[] overflow\n", __func__);
+ return -EFAULT;
+ }
+ retval = agilent_82357a_write_registers(a_priv, writes, i);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: agilent_82357a_write_registers() returned error\n",
+ __func__);
+ return -EIO;
+ }
+ return 0;
+}
+
+static void agilent_82357a_detach(gpib_board_t *board)
+{
+ struct agilent_82357a_priv *a_priv;
+ struct usb_device *usb_dev;
+
+ mutex_lock(&agilent_82357a_hotplug_lock);
+
+ a_priv = board->private_data;
+ usb_dev = interface_to_usbdev(a_priv->bus_interface);
+ if (a_priv) {
+ if (a_priv->bus_interface) {
+ agilent_82357a_go_idle(board);
+ usb_set_intfdata(a_priv->bus_interface, NULL);
+ }
+ mutex_lock(&a_priv->control_alloc_lock);
+ mutex_lock(&a_priv->bulk_alloc_lock);
+ mutex_lock(&a_priv->interrupt_alloc_lock);
+ agilent_82357a_cleanup_urbs(a_priv);
+ agilent_82357a_free_private(a_priv);
+ }
+ dev_info(&usb_dev->dev, "%s: detached\n", __func__);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+}
+
+gpib_interface_t agilent_82357a_gpib_interface = {
+name: "agilent_82357a",
+attach : agilent_82357a_attach,
+detach : agilent_82357a_detach,
+read : agilent_82357a_read,
+write : agilent_82357a_write,
+command : agilent_82357a_command,
+take_control : agilent_82357a_take_control,
+go_to_standby : agilent_82357a_go_to_standby,
+request_system_control : agilent_82357a_request_system_control,
+interface_clear : agilent_82357a_interface_clear,
+remote_enable : agilent_82357a_remote_enable,
+enable_eos : agilent_82357a_enable_eos,
+disable_eos : agilent_82357a_disable_eos,
+parallel_poll : agilent_82357a_parallel_poll,
+parallel_poll_configure : agilent_82357a_parallel_poll_configure,
+parallel_poll_response : agilent_82357a_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : agilent_82357a_line_status,
+update_status : agilent_82357a_update_status,
+primary_address : agilent_82357a_primary_address,
+secondary_address : agilent_82357a_secondary_address,
+serial_poll_response : agilent_82357a_serial_poll_response,
+serial_poll_status : agilent_82357a_serial_poll_status,
+t1_delay : agilent_82357a_t1_delay,
+return_to_local : agilent_82357a_return_to_local,
+no_7_bit_eos : 1,
+skip_check_for_command_acceptors : 1
+};
+
+// Table with the USB-devices: just now only testing IDs
+static struct usb_device_id agilent_82357a_driver_device_table[] = {
+ {USB_DEVICE(USB_VENDOR_ID_AGILENT, USB_DEVICE_ID_AGILENT_82357A)},
+ {USB_DEVICE(USB_VENDOR_ID_AGILENT, USB_DEVICE_ID_AGILENT_82357B)},
+ {} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, agilent_82357a_driver_device_table);
+
+static int agilent_82357a_driver_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ int i;
+ char *path;
+ static const int path_length = 1024;
+ struct usb_device *usb_dev;
+
+ if (mutex_lock_interruptible(&agilent_82357a_hotplug_lock))
+ return -ERESTARTSYS;
+ usb_dev = usb_get_dev(interface_to_usbdev(interface));
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
+ if (!agilent_82357a_driver_interfaces[i]) {
+ agilent_82357a_driver_interfaces[i] = interface;
+ usb_set_intfdata(interface, NULL);
+ dev_dbg(&usb_dev->dev, "set bus interface %i to address 0x%p\n",
+ i, interface);
+ break;
+ }
+ }
+ if (i == MAX_NUM_82357A_INTERFACES) {
+ usb_put_dev(usb_dev);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ dev_err(&usb_dev->dev, "%s: out of space in agilent_82357a_driver_interfaces[]\n",
+ __func__);
+ return -1;
+ }
+ path = kmalloc(path_length, GFP_KERNEL);
+ if (!path) {
+ usb_put_dev(usb_dev);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return -ENOMEM;
+ }
+ usb_make_path(usb_dev, path, path_length);
+ dev_info(&usb_dev->dev, "probe succeeded for path: %s\n", path);
+ kfree(path);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return 0;
+}
+
+static void agilent_82357a_driver_disconnect(struct usb_interface *interface)
+{
+ int i;
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+
+ mutex_lock(&agilent_82357a_hotplug_lock);
+
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
+ if (agilent_82357a_driver_interfaces[i] == interface) {
+ gpib_board_t *board = usb_get_intfdata(interface);
+
+ if (board) {
+ struct agilent_82357a_priv *a_priv = board->private_data;
+
+ if (a_priv) {
+ mutex_lock(&a_priv->control_alloc_lock);
+ mutex_lock(&a_priv->bulk_alloc_lock);
+ mutex_lock(&a_priv->interrupt_alloc_lock);
+ agilent_82357a_cleanup_urbs(a_priv);
+ a_priv->bus_interface = NULL;
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ mutex_unlock(&a_priv->bulk_alloc_lock);
+ mutex_unlock(&a_priv->control_alloc_lock);
+ }
+ }
+ dev_dbg(&usb_dev->dev, "nulled agilent_82357a_driver_interfaces[%i]\n", i);
+ agilent_82357a_driver_interfaces[i] = NULL;
+ break;
+ }
+ }
+ if (i == MAX_NUM_82357A_INTERFACES)
+ dev_err(&usb_dev->dev, "unable to find interface in agilent_82357a_driver_interfaces[]? bug?\n");
+ usb_put_dev(usb_dev);
+
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+}
+
+static int agilent_82357a_driver_suspend(struct usb_interface *interface, pm_message_t message)
+{
+ int i, retval;
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+
+ mutex_lock(&agilent_82357a_hotplug_lock);
+
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
+ if (agilent_82357a_driver_interfaces[i] == interface) {
+ gpib_board_t *board = usb_get_intfdata(interface);
+
+ if (board) {
+ struct agilent_82357a_priv *a_priv = board->private_data;
+
+ if (a_priv) {
+ agilent_82357a_abort(a_priv, 0);
+ agilent_82357a_abort(a_priv, 0);
+ retval = agilent_82357a_go_idle(board);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to go idle, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+ mutex_lock(&a_priv->interrupt_alloc_lock);
+ agilent_82357a_cleanup_urbs(a_priv);
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d gpib minor %d, agilent usb interface %i suspended\n",
+ usb_dev->bus->busnum, usb_dev->devnum,
+ board->minor, i);
+ }
+ }
+ break;
+ }
+ }
+
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+
+ return 0;
+}
+
+static int agilent_82357a_driver_resume(struct usb_interface *interface)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+ gpib_board_t *board;
+ int i, retval;
+
+ mutex_lock(&agilent_82357a_hotplug_lock);
+
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i) {
+ if (agilent_82357a_driver_interfaces[i] == interface) {
+ board = usb_get_intfdata(interface);
+ if (board)
+ break;
+ }
+ }
+ if (i == MAX_NUM_82357A_INTERFACES)
+ goto resume_exit;
+
+ struct agilent_82357a_priv *a_priv = board->private_data;
+
+ if (a_priv) {
+ if (a_priv->interrupt_urb) {
+ mutex_lock(&a_priv->interrupt_alloc_lock);
+ retval = usb_submit_urb(a_priv->interrupt_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+ mutex_unlock(&a_priv->interrupt_alloc_lock);
+ }
+ retval = agilent_82357a_init(board);
+ if (retval < 0) {
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+ return retval;
+ }
+ // set/unset system controller
+ agilent_82357a_request_system_control(board, board->master);
+ // toggle ifc if master
+ if (board->master) {
+ agilent_82357a_interface_clear(board, 1);
+ usleep_range(200, 250);
+ agilent_82357a_interface_clear(board, 0);
+ }
+ // assert/unassert REN
+ agilent_82357a_remote_enable(board, a_priv->ren_state);
+
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d gpib minor %d, agilent usb interface %i resumed\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ }
+
+resume_exit:
+ mutex_unlock(&agilent_82357a_hotplug_lock);
+
+ return 0;
+}
+
+static struct usb_driver agilent_82357a_bus_driver = {
+ .name = "agilent_82357a_gpib",
+ .probe = agilent_82357a_driver_probe,
+ .disconnect = agilent_82357a_driver_disconnect,
+ .suspend = agilent_82357a_driver_suspend,
+ .resume = agilent_82357a_driver_resume,
+ .id_table = agilent_82357a_driver_device_table,
+};
+
+static int __init agilent_82357a_init_module(void)
+{
+ int i;
+
+ pr_info("agilent_82357a_gpib driver loading");
+ for (i = 0; i < MAX_NUM_82357A_INTERFACES; ++i)
+ agilent_82357a_driver_interfaces[i] = NULL;
+ usb_register(&agilent_82357a_bus_driver);
+ gpib_register_driver(&agilent_82357a_gpib_interface, THIS_MODULE);
+
+ return 0;
+}
+
+static void __exit agilent_82357a_exit_module(void)
+{
+ pr_info("agilent_82357a_gpib driver unloading");
+ gpib_unregister_driver(&agilent_82357a_gpib_interface);
+ usb_deregister(&agilent_82357a_bus_driver);
+}
+
+module_init(agilent_82357a_init_module);
+module_exit(agilent_82357a_exit_module);
diff --git a/drivers/staging/gpib/agilent_82357a/agilent_82357a.h b/drivers/staging/gpib/agilent_82357a/agilent_82357a.h
new file mode 100644
index 000000000000..cdbc3ec5d8bd
--- /dev/null
+++ b/drivers/staging/gpib/agilent_82357a/agilent_82357a.h
@@ -0,0 +1,182 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2004 by Frank Mori Hess *
+ ***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/mutex.h>
+#include <linux/semaphore.h>
+#include <linux/usb.h>
+#include <linux/timer.h>
+#include <linux/compiler_attributes.h>
+#include "gpibP.h"
+#include "tms9914.h"
+
+enum usb_vendor_ids {
+ USB_VENDOR_ID_AGILENT = 0x0957
+};
+
+enum usb_device_ids {
+ USB_DEVICE_ID_AGILENT_82357A = 0x0107,
+ USB_DEVICE_ID_AGILENT_82357A_PREINIT = 0x0007, // device id before firmware is loaded
+ USB_DEVICE_ID_AGILENT_82357B = 0x0718, // device id before firmware is loaded
+ USB_DEVICE_ID_AGILENT_82357B_PREINIT = 0x0518, // device id before firmware is loaded
+};
+
+enum endpoint_addresses {
+ AGILENT_82357_CONTROL_ENDPOINT = 0x0,
+ AGILENT_82357_BULK_IN_ENDPOINT = 0x2,
+ AGILENT_82357A_BULK_OUT_ENDPOINT = 0x4,
+ AGILENT_82357A_INTERRUPT_IN_ENDPOINT = 0x6,
+ AGILENT_82357B_BULK_OUT_ENDPOINT = 0x6,
+ AGILENT_82357B_INTERRUPT_IN_ENDPOINT = 0x8,
+};
+
+enum bulk_commands {
+ DATA_PIPE_CMD_WRITE = 0x1,
+ DATA_PIPE_CMD_READ = 0x3,
+ DATA_PIPE_CMD_WR_REGS = 0x4,
+ DATA_PIPE_CMD_RD_REGS = 0x5
+};
+
+enum agilent_82357a_read_flags {
+ ARF_END_ON_EOI = 0x1,
+ ARF_NO_ADDRESS = 0x2,
+ ARF_END_ON_EOS_CHAR = 0x4,
+ ARF_SPOLL = 0x8
+};
+
+enum agilent_82357a_trailing_read_flags {
+ ATRF_EOI = 0x1,
+ ATRF_ATN = 0x2,
+ ATRF_IFC = 0x4,
+ ATRF_EOS = 0x8,
+ ATRF_ABORT = 0x10,
+ ATRF_COUNT = 0x20,
+ ATRF_DEAD_BUS = 0x40,
+ ATRF_UNADDRESSED = 0x80
+};
+
+enum agilent_82357a_write_flags {
+ AWF_SEND_EOI = 0x1,
+ AWF_NO_FAST_TALKER_FIRST_BYTE = 0x2,
+ AWF_NO_FAST_TALKER = 0x4,
+ AWF_NO_ADDRESS = 0x8,
+ AWF_ATN = 0x10,
+ AWF_SEPARATE_HEADER = 0x80
+};
+
+enum agilent_82357a_interrupt_flag_bit_numbers {
+ AIF_SRQ_BN = 0,
+ AIF_WRITE_COMPLETE_BN = 1,
+ AIF_READ_COMPLETE_BN = 2,
+};
+
+enum agilent_82357_error_codes {
+ UGP_SUCCESS = 0,
+ UGP_ERR_INVALID_CMD = 1,
+ UGP_ERR_INVALID_PARAM = 2,
+ UGP_ERR_INVALID_REG = 3,
+ UGP_ERR_GPIB_READ = 4,
+ UGP_ERR_GPIB_WRITE = 5,
+ UGP_ERR_FLUSHING = 6,
+ UGP_ERR_FLUSHING_ALREADY = 7,
+ UGP_ERR_UNSUPPORTED = 8,
+ UGP_ERR_OTHER = 9
+};
+
+enum agilent_82357_control_values {
+ XFER_ABORT = 0xa0,
+ XFER_STATUS = 0xb0,
+};
+
+enum xfer_status_bits {
+ XS_COMPLETED = 0x1,
+ XS_READ = 0x2,
+};
+
+enum xfer_status_completion_bits {
+ XSC_EOI = 0x1,
+ XSC_ATN = 0x2,
+ XSC_IFC = 0x4,
+ XSC_EOS = 0x8,
+ XSC_ABORT = 0x10,
+ XSC_COUNT = 0x20,
+ XSC_DEAD_BUS = 0x40,
+ XSC_BUS_NOT_ADDRESSED = 0x80
+};
+
+enum xfer_abort_type {
+ XA_FLUSH = 0x1
+};
+
+#define STATUS_DATA_LEN 8
+#define INTERRUPT_BUF_LEN 8
+
+struct agilent_82357a_urb_ctx {
+ struct semaphore complete;
+ unsigned timed_out : 1;
+};
+
+// struct which defines local data for each 82357 device
+struct agilent_82357a_priv {
+ struct usb_interface *bus_interface;
+ unsigned short eos_char;
+ unsigned short eos_mode;
+ unsigned short hw_control_bits;
+ unsigned long interrupt_flags;
+ struct urb *bulk_urb;
+ struct urb *interrupt_urb;
+ u8 *interrupt_buffer;
+ struct mutex bulk_transfer_lock; // bulk transfer lock
+ struct mutex bulk_alloc_lock; // bulk transfer allocation lock
+ struct mutex interrupt_alloc_lock; // interrupt allocation lock
+ struct mutex control_alloc_lock; // control message allocation lock
+ struct timer_list bulk_timer;
+ struct agilent_82357a_urb_ctx context;
+ unsigned int bulk_out_endpoint;
+ unsigned int interrupt_in_endpoint;
+ unsigned is_cic : 1;
+ unsigned ren_state : 1;
+};
+
+struct agilent_82357a_register_pairlet {
+ short address;
+ unsigned short value;
+};
+
+enum firmware_registers {
+ HW_CONTROL = 0xa,
+ LED_CONTROL = 0xb,
+ RESET_TO_POWERUP = 0xc,
+ PROTOCOL_CONTROL = 0xd,
+ FAST_TALKER_T1 = 0xe
+};
+
+enum hardware_control_bits {
+ NOT_TI_RESET = 0x1,
+ SYSTEM_CONTROLLER = 0x2,
+ NOT_PARALLEL_POLL = 0x4,
+ OSCILLATOR_5V_ON = 0x8,
+ OUTPUT_5V_ON = 0x20,
+ CPLD_3V_ON = 0x80,
+};
+
+enum led_control_bits {
+ FIRMWARE_LED_CONTROL = 0x1,
+ FAIL_LED_ON = 0x20,
+ READY_LED_ON = 0x40,
+ ACCESS_LED_ON = 0x80
+};
+
+enum reset_to_powerup_bits {
+ RESET_SPACEBALL = 0x1, // wait 2 millisec after sending
+};
+
+enum protocol_control_bits {
+ WRITE_COMPLETE_INTERRUPT_EN = 0x1,
+};
+
+static const int agilent_82357a_control_request = 0x4;
+
diff --git a/drivers/staging/gpib/cb7210/Makefile b/drivers/staging/gpib/cb7210/Makefile
new file mode 100644
index 000000000000..22e0214fc17d
--- /dev/null
+++ b/drivers/staging/gpib/cb7210/Makefile
@@ -0,0 +1,4 @@
+ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA
+obj-m += cb7210.o
+
+
diff --git a/drivers/staging/gpib/cb7210/cb7210.c b/drivers/staging/gpib/cb7210/cb7210.c
new file mode 100644
index 000000000000..63df7f3eb3f3
--- /dev/null
+++ b/drivers/staging/gpib/cb7210/cb7210.c
@@ -0,0 +1,1556 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * Measurement Computing boards using cb7210.2 and cbi488.2 chips
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "cb7210.h"
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/dma.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include "gpib_pci_ids.h"
+#include "quancom_pci.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver Measurement Computing boards using cb7210.2 and cbi488.2");
+
+static inline int have_fifo_word(const struct cb7210_priv *cb_priv)
+{
+ if (((cb7210_read_byte(cb_priv, HS_STATUS)) &
+ (HS_RX_MSB_NOT_EMPTY | HS_RX_LSB_NOT_EMPTY)) ==
+ (HS_RX_MSB_NOT_EMPTY | HS_RX_LSB_NOT_EMPTY))
+ return 1;
+ else
+ return 0;
+}
+
+static inline void input_fifo_enable(gpib_board_t *board, int enable)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ if (enable) {
+ cb_priv->in_fifo_half_full = 0;
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+
+ cb7210_write_byte(cb_priv, HS_RX_ENABLE | HS_TX_ENABLE | HS_CLR_SRQ_INT |
+ HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT | cb_priv->hs_mode_bits,
+ HS_MODE);
+
+ cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+
+ cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL);
+
+ cb_priv->hs_mode_bits |= HS_RX_ENABLE;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+ } else {
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+
+ cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, nec7210_iobase(cb_priv) +
+ HS_MODE);
+
+ clear_bit(READ_READY_BN, &nec_priv->state);
+ }
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+static int fifo_read(gpib_board_t *board, struct cb7210_priv *cb_priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ int hs_status;
+ u16 word;
+ unsigned long flags;
+
+ *bytes_read = 0;
+ if (cb_priv->fifo_iobase == 0) {
+ pr_err("cb7210: fifo iobase is zero!\n");
+ return -EIO;
+ }
+ *end = 0;
+ if (length <= cb7210_fifo_size) {
+ pr_err("cb7210: bug! %s with length < fifo size\n", __func__);
+ return -EINVAL;
+ }
+
+ input_fifo_enable(board, 1);
+
+ while (*bytes_read + cb7210_fifo_size < length) {
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI);
+
+ if (wait_event_interruptible(board->wait,
+ (cb_priv->in_fifo_half_full &&
+ have_fifo_word(cb_priv)) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("cb7210: fifo half full wait interrupted\n");
+ retval = -ERESTARTSYS;
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ break;
+ }
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+
+ while (have_fifo_word(cb_priv)) {
+ word = inw(cb_priv->fifo_iobase + DIR);
+ buffer[(*bytes_read)++] = word & 0xff;
+ buffer[(*bytes_read)++] = (word >> 8) & 0xff;
+ }
+
+ cb_priv->in_fifo_half_full = 0;
+
+ hs_status = cb7210_read_byte(cb_priv, HS_STATUS);
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state)) {
+ *end = 1;
+ break;
+ }
+ if (hs_status & HS_FIFO_FULL)
+ break;
+ if (test_bit(TIMO_NUM, &board->status)) {
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) {
+ retval = -EINTR;
+ break;
+ }
+ }
+ hs_status = cb7210_read_byte(cb_priv, HS_STATUS);
+ if (hs_status & HS_RX_LSB_NOT_EMPTY) {
+ word = inw(cb_priv->fifo_iobase + DIR);
+ buffer[(*bytes_read)++] = word & 0xff;
+ }
+
+ input_fifo_enable(board, 0);
+
+ if (wait_event_interruptible(board->wait,
+ test_bit(READ_READY_BN, &nec_priv->state) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("cb7210: fifo half full wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ if (test_bit(READ_READY_BN, &nec_priv->state)) {
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDA);
+ buffer[(*bytes_read)++] = nec7210_read_data_in(board, nec_priv, end);
+ }
+
+ return retval;
+}
+
+int cb7210_accel_read(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval;
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ size_t num_bytes;
+
+ *bytes_read = 0;
+ // deal with limitations of fifo
+ if (length < cb7210_fifo_size + 3 || (nec_priv->auxa_bits & HR_REOS))
+ return cb7210_read(board, buffer, length, end, bytes_read);
+ *end = 0;
+
+ nec7210_release_rfd_holdoff(board, nec_priv);
+
+ if (wait_event_interruptible(board->wait,
+ test_bit(READ_READY_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("cb7210: read ready wait interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ return -EINTR;
+
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDE);
+ buffer[(*bytes_read)++] = nec7210_read_data_in(board, nec_priv, end);
+ if (*end)
+ return 0;
+
+ nec7210_release_rfd_holdoff(board, nec_priv);
+
+ retval = fifo_read(board, cb_priv, &buffer[*bytes_read], length - *bytes_read - 1,
+ end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+ if (*end)
+ return 0;
+
+ retval = cb7210_read(board, &buffer[*bytes_read], 1, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+
+ return 0;
+}
+
+static int output_fifo_empty(const struct cb7210_priv *cb_priv)
+{
+ if ((cb7210_read_byte(cb_priv, HS_STATUS) & (HS_TX_MSB_NOT_EMPTY | HS_TX_LSB_NOT_EMPTY))
+ == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static inline void output_fifo_enable(gpib_board_t *board, int enable)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ if (enable) {
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO);
+
+ cb7210_write_byte(cb_priv, HS_RX_ENABLE | HS_TX_ENABLE | HS_CLR_SRQ_INT |
+ HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT | cb_priv->hs_mode_bits,
+ HS_MODE);
+
+ cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK;
+ cb_priv->hs_mode_bits |= HS_TX_ENABLE;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+
+ cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL);
+
+ clear_bit(WRITE_READY_BN, &nec_priv->state);
+
+ } else {
+ cb_priv->hs_mode_bits &= ~HS_ENABLE_MASK;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, HR_DOIE);
+ }
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+static int fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ size_t count = 0;
+ ssize_t retval = 0;
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned int num_bytes, i;
+ unsigned long flags;
+
+ *bytes_written = 0;
+ if (cb_priv->fifo_iobase == 0) {
+ pr_err("cb7210: fifo iobase is zero!\n");
+ return -EINVAL;
+ }
+ if (length == 0)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state);
+ clear_bit(BUS_ERROR_BN, &nec_priv->state);
+
+ output_fifo_enable(board, 1);
+
+ while (count < length) {
+ // wait until byte is ready to be sent
+ if (wait_event_interruptible(board->wait,
+ cb_priv->out_fifo_half_empty ||
+ output_fifo_empty(cb_priv) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("cb7210: fifo wait interrupted\n");
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state))
+ break;
+
+ if (output_fifo_empty(cb_priv))
+ num_bytes = cb7210_fifo_size - cb7210_fifo_width;
+ else
+ num_bytes = cb7210_fifo_size / 2;
+ if (num_bytes + count > length)
+ num_bytes = length - count;
+ if (num_bytes % cb7210_fifo_width) {
+ pr_err("cb7210: bug! %s with odd number of bytes\n", __func__);
+ retval = -EINVAL;
+ break;
+ }
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ for (i = 0; i < num_bytes / cb7210_fifo_width; i++) {
+ u16 word;
+
+ word = buffer[count++] & 0xff;
+ word |= (buffer[count++] << 8) & 0xff00;
+ outw(word, cb_priv->fifo_iobase + CDOR);
+ }
+ cb_priv->out_fifo_half_empty = 0;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits |
+ HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT, HS_MODE);
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ }
+ // wait last byte has been sent
+ if (wait_event_interruptible(board->wait,
+ output_fifo_empty(cb_priv) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_err("cb7210: wait for last byte interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_bit(BUS_ERROR_BN, &nec_priv->state))
+ retval = -EIO;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+
+ output_fifo_enable(board, 0);
+
+ *bytes_written = count;
+ return retval;
+}
+
+int cb7210_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned long fast_chunk_size, leftover;
+ int retval;
+ size_t num_bytes;
+
+ *bytes_written = 0;
+ if (length > cb7210_fifo_width)
+ fast_chunk_size = length - 1;
+ else
+ fast_chunk_size = 0;
+ fast_chunk_size -= fast_chunk_size % cb7210_fifo_width;
+ leftover = length - fast_chunk_size;
+
+ retval = fifo_write(board, buffer, fast_chunk_size, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+
+ retval = nec7210_write(board, nec_priv, buffer + fast_chunk_size, leftover,
+ send_eoi, &num_bytes);
+ *bytes_written += num_bytes;
+ return retval;
+}
+
+int cb7210_line_status(const gpib_board_t *board)
+{
+ int status = ValidALL;
+ int bsr_bits;
+ struct cb7210_priv *cb_priv;
+ struct nec7210_priv *nec_priv;
+
+ cb_priv = board->private_data;
+ nec_priv = &cb_priv->nec7210_priv;
+
+ bsr_bits = cb7210_paged_read_byte(cb_priv, BUS_STATUS, BUS_STATUS_PAGE);
+
+ if ((bsr_bits & BSR_REN_BIT) == 0)
+ status |= BusREN;
+ if ((bsr_bits & BSR_IFC_BIT) == 0)
+ status |= BusIFC;
+ if ((bsr_bits & BSR_SRQ_BIT) == 0)
+ status |= BusSRQ;
+ if ((bsr_bits & BSR_EOI_BIT) == 0)
+ status |= BusEOI;
+ if ((bsr_bits & BSR_NRFD_BIT) == 0)
+ status |= BusNRFD;
+ if ((bsr_bits & BSR_NDAC_BIT) == 0)
+ status |= BusNDAC;
+ if ((bsr_bits & BSR_DAV_BIT) == 0)
+ status |= BusDAV;
+ if ((bsr_bits & BSR_ATN_BIT) == 0)
+ status |= BusATN;
+
+ return status;
+}
+
+unsigned int cb7210_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned int retval;
+
+ retval = nec7210_t1_delay(board, nec_priv, nano_sec);
+
+ if (nano_sec <= 350) {
+ write_byte(nec_priv, AUX_HI_SPEED, AUXMR);
+ retval = 350;
+ } else {
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ }
+ return retval;
+}
+
+irqreturn_t cb7210_locked_internal_interrupt(gpib_board_t *board);
+
+/*
+ * GPIB interrupt service routines
+ */
+
+irqreturn_t cb_pci_interrupt(int irq, void *arg)
+{
+ int bits;
+ gpib_board_t *board = arg;
+ struct cb7210_priv *priv = board->private_data;
+
+ // first task check if this is really our interrupt in a shared irq environment
+ switch (priv->pci_chip) {
+ case PCI_CHIP_AMCC_S5933:
+ if ((inl(priv->amcc_iobase + INTCSR_REG) &
+ (INBOX_INTR_CS_BIT | INTR_ASSERTED_BIT)) == 0)
+ return IRQ_NONE;
+
+ // read incoming mailbox to clear mailbox full flag
+ inl(priv->amcc_iobase + INCOMING_MAILBOX_REG(3));
+ // clear amccs5933 interrupt
+ bits = INBOX_FULL_INTR_BIT | INBOX_BYTE_BITS(3) |
+ INBOX_SELECT_BITS(3) | INBOX_INTR_CS_BIT;
+ outl(bits, priv->amcc_iobase + INTCSR_REG);
+ break;
+ case PCI_CHIP_QUANCOM:
+ if ((inb(nec7210_iobase(priv) + QUANCOM_IRQ_CONTROL_STATUS_REG) &
+ QUANCOM_IRQ_ASSERTED_BIT))
+ outb(QUANCOM_IRQ_ENABLE_BIT, nec7210_iobase(priv) +
+ QUANCOM_IRQ_CONTROL_STATUS_REG);
+ break;
+ default:
+ break;
+ }
+ return cb7210_locked_internal_interrupt(arg);
+}
+
+irqreturn_t cb7210_internal_interrupt(gpib_board_t *board)
+{
+ int hs_status, status1, status2;
+ struct cb7210_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ int clear_bits;
+
+ if ((priv->hs_mode_bits & HS_ENABLE_MASK)) {
+ status1 = 0;
+ hs_status = cb7210_read_byte(priv, HS_STATUS);
+ } else {
+ hs_status = 0;
+ status1 = read_byte(nec_priv, ISR1);
+ }
+ status2 = read_byte(nec_priv, ISR2);
+ nec7210_interrupt_have_status(board, nec_priv, status1, status2);
+
+ dev_dbg(board->gpib_dev, "cb7210: status 0x%x, mode 0x%x\n", hs_status, priv->hs_mode_bits);
+
+ clear_bits = 0;
+
+ if (hs_status & HS_HALF_FULL) {
+ if (priv->hs_mode_bits & HS_TX_ENABLE)
+ priv->out_fifo_half_empty = 1;
+ else if (priv->hs_mode_bits & HS_RX_ENABLE)
+ priv->in_fifo_half_full = 1;
+ clear_bits |= HS_CLR_HF_INT;
+ }
+
+ if (hs_status & HS_SRQ_INT) {
+ set_bit(SRQI_NUM, &board->status);
+ clear_bits |= HS_CLR_SRQ_INT;
+ }
+
+ if ((hs_status & HS_EOI_INT)) {
+ clear_bits |= HS_CLR_EOI_EMPTY_INT;
+ set_bit(RECEIVED_END_BN, &nec_priv->state);
+ if ((nec_priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDE)
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ }
+
+ if ((priv->hs_mode_bits & HS_TX_ENABLE) &&
+ (hs_status & (HS_TX_MSB_NOT_EMPTY | HS_TX_LSB_NOT_EMPTY)) == 0)
+ clear_bits |= HS_CLR_EOI_EMPTY_INT;
+
+ if (clear_bits) {
+ cb7210_write_byte(priv, priv->hs_mode_bits | clear_bits, HS_MODE);
+ cb7210_write_byte(priv, priv->hs_mode_bits, HS_MODE);
+ wake_up_interruptible(&board->wait);
+ }
+
+ return IRQ_HANDLED;
+}
+
+irqreturn_t cb7210_locked_internal_interrupt(gpib_board_t *board)
+{
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = cb7210_internal_interrupt(board);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+irqreturn_t cb7210_interrupt(int irq, void *arg)
+{
+ return cb7210_internal_interrupt(arg);
+}
+
+static int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int cb_isa_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void cb_pci_detach(gpib_board_t *board);
+static void cb_isa_detach(gpib_board_t *board);
+
+// wrappers for interface functions
+int cb7210_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+}
+
+int cb7210_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int cb7210_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+int cb7210_take_control(gpib_board_t *board, int synchronous)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+int cb7210_go_to_standby(gpib_board_t *board)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+void cb7210_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct cb7210_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ if (request_control)
+ priv->hs_mode_bits |= HS_SYS_CONTROL;
+ else
+ priv->hs_mode_bits &= ~HS_SYS_CONTROL;
+
+ cb7210_write_byte(priv, priv->hs_mode_bits, HS_MODE);
+ nec7210_request_system_control(board, nec_priv, request_control);
+}
+
+void cb7210_interface_clear(gpib_board_t *board, int assert)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+void cb7210_remote_enable(gpib_board_t *board, int enable)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+int cb7210_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+void cb7210_disable_eos(gpib_board_t *board)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+unsigned int cb7210_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+int cb7210_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+int cb7210_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+int cb7210_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+void cb7210_parallel_poll_configure(gpib_board_t *board, uint8_t configuration)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration);
+}
+
+void cb7210_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+void cb7210_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+uint8_t cb7210_serial_poll_status(gpib_board_t *board)
+{
+ struct cb7210_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+void cb7210_return_to_local(gpib_board_t *board)
+{
+ struct cb7210_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ write_byte(nec_priv, AUX_RTL2, AUXMR);
+ udelay(1);
+ write_byte(nec_priv, AUX_RTL, AUXMR);
+}
+
+gpib_interface_t cb_pci_unaccel_interface = {
+name: "cbi_pci_unaccel",
+attach : cb_pci_attach,
+detach : cb_pci_detach,
+read : cb7210_read,
+write : cb7210_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_pci_accel_interface = {
+name: "cbi_pci_accel",
+attach : cb_pci_attach,
+detach : cb_pci_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_pci_interface = {
+name: "cbi_pci",
+attach : cb_pci_attach,
+detach : cb_pci_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_isa_unaccel_interface = {
+name: "cbi_isa_unaccel",
+attach : cb_isa_attach,
+detach : cb_isa_detach,
+read : cb7210_read,
+write : cb7210_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_isa_interface = {
+name: "cbi_isa",
+attach : cb_isa_attach,
+detach : cb_isa_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_isa_accel_interface = {
+name: "cbi_isa_accel",
+attach : cb_isa_attach,
+detach : cb_isa_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+static int cb7210_allocate_private(gpib_board_t *board)
+{
+ struct cb7210_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct cb7210_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct cb7210_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ return 0;
+}
+
+void cb7210_generic_detach(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+// generic part of attach functions shared by all cb7210 boards
+int cb7210_generic_attach(gpib_board_t *board)
+{
+ struct cb7210_priv *cb_priv;
+ struct nec7210_priv *nec_priv;
+
+ board->status = 0;
+
+ if (cb7210_allocate_private(board))
+ return -ENOMEM;
+ cb_priv = board->private_data;
+ nec_priv = &cb_priv->nec7210_priv;
+ nec_priv->read_byte = nec7210_locking_ioport_read_byte;
+ nec_priv->write_byte = nec7210_locking_ioport_write_byte;
+ nec_priv->offset = cb7210_reg_offset;
+ nec_priv->type = CB7210;
+ return 0;
+}
+
+int cb7210_init(struct cb7210_priv *cb_priv, gpib_board_t *board)
+{
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+
+ cb7210_write_byte(cb_priv, HS_RESET7210, HS_INT_LEVEL);
+ cb7210_write_byte(cb_priv, irq_bits(cb_priv->irq), HS_INT_LEVEL);
+
+ nec7210_board_reset(nec_priv, board);
+ cb7210_write_byte(cb_priv, HS_TX_ENABLE | HS_RX_ENABLE | HS_CLR_SRQ_INT |
+ HS_CLR_EOI_EMPTY_INT | HS_CLR_HF_INT, HS_MODE);
+
+ cb_priv->hs_mode_bits = HS_HF_INT_EN;
+ cb7210_write_byte(cb_priv, cb_priv->hs_mode_bits, HS_MODE);
+
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ /* set clock register for maximum (20 MHz) driving frequency
+ * ICR should be set to clock in megahertz (1-15) and to zero
+ * for clocks faster than 15 MHz (max 20MHz)
+ */
+ write_byte(nec_priv, ICR | 0, AUXMR);
+
+ if (cb_priv->pci_chip == PCI_CHIP_QUANCOM) {
+ /* change interrupt polarity */
+ nec_priv->auxb_bits |= HR_INV;
+ write_byte(nec_priv, nec_priv->auxb_bits, AUXMR);
+ }
+ nec7210_board_online(nec_priv, board);
+
+ /* poll so we can detect assertion of ATN */
+ if (gpib_request_pseudo_irq(board, cb_pci_interrupt)) {
+ pr_err("pc2_gpib: failed to allocate pseudo_irq\n");
+ return -1;
+ }
+ return 0;
+}
+
+int cb_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct cb7210_priv *cb_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ int bits;
+ int retval;
+
+ retval = cb7210_generic_attach(board);
+ if (retval)
+ return retval;
+
+ cb_priv = board->private_data;
+ nec_priv = &cb_priv->nec7210_priv;
+
+ cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_CBOARDS,
+ PCI_DEVICE_ID_CBOARDS_PCI_GPIB, NULL);
+ if (cb_priv->pci_device)
+ cb_priv->pci_chip = PCI_CHIP_AMCC_S5933;
+ if (!cb_priv->pci_device) {
+ cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_CBOARDS,
+ PCI_DEVICE_ID_CBOARDS_CPCI_GPIB, NULL);
+ if (cb_priv->pci_device)
+ cb_priv->pci_chip = PCI_CHIP_AMCC_S5933;
+ }
+ if (!cb_priv->pci_device) {
+ cb_priv->pci_device = gpib_pci_get_device(config, PCI_VENDOR_ID_QUANCOM,
+ PCI_DEVICE_ID_QUANCOM_GPIB, NULL);
+ if (cb_priv->pci_device) {
+ cb_priv->pci_chip = PCI_CHIP_QUANCOM;
+ nec_priv->offset = 4;
+ }
+ }
+ if (!cb_priv->pci_device) {
+ pr_warn("cb7210: no supported boards found.\n");
+ return -1;
+ }
+
+ if (pci_enable_device(cb_priv->pci_device)) {
+ pr_err("cb7210: error enabling pci device\n");
+ return -1;
+ }
+
+ if (pci_request_regions(cb_priv->pci_device, "cb7210"))
+ return -1;
+ switch (cb_priv->pci_chip) {
+ case PCI_CHIP_AMCC_S5933:
+ cb_priv->amcc_iobase = pci_resource_start(cb_priv->pci_device, 0);
+ nec_priv->iobase = (void *)(pci_resource_start(cb_priv->pci_device, 1));
+ cb_priv->fifo_iobase = pci_resource_start(cb_priv->pci_device, 2);
+ break;
+ case PCI_CHIP_QUANCOM:
+ nec_priv->iobase = (void *)(pci_resource_start(cb_priv->pci_device, 0));
+ cb_priv->fifo_iobase = (unsigned long)nec_priv->iobase;
+ break;
+ default:
+ pr_err("cb7210: bug! unhandled pci_chip=%i\n", cb_priv->pci_chip);
+ return -EIO;
+ }
+ isr_flags |= IRQF_SHARED;
+ if (request_irq(cb_priv->pci_device->irq, cb_pci_interrupt, isr_flags, "cb7210", board)) {
+ pr_err("cb7210: can't request IRQ %d\n", cb_priv->pci_device->irq);
+ return -1;
+ }
+ cb_priv->irq = cb_priv->pci_device->irq;
+
+ switch (cb_priv->pci_chip) {
+ case PCI_CHIP_AMCC_S5933:
+ // make sure mailbox flags are clear
+ inl(cb_priv->amcc_iobase + INCOMING_MAILBOX_REG(3));
+ // enable interrupts on amccs5933 chip
+ bits = INBOX_FULL_INTR_BIT | INBOX_BYTE_BITS(3) | INBOX_SELECT_BITS(3) |
+ INBOX_INTR_CS_BIT;
+ outl(bits, cb_priv->amcc_iobase + INTCSR_REG);
+ break;
+ default:
+ break;
+ }
+ return cb7210_init(cb_priv, board);
+}
+
+void cb_pci_detach(gpib_board_t *board)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (cb_priv) {
+ gpib_free_pseudo_irq(board);
+ nec_priv = &cb_priv->nec7210_priv;
+ if (cb_priv->irq) {
+ // disable amcc interrupts
+ outl(0, cb_priv->amcc_iobase + INTCSR_REG);
+ free_irq(cb_priv->irq, board);
+ }
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ pci_release_regions(cb_priv->pci_device);
+ }
+ if (cb_priv->pci_device)
+ pci_dev_put(cb_priv->pci_device);
+ }
+ cb7210_generic_detach(board);
+}
+
+int cb_isa_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int isr_flags = 0;
+ struct cb7210_priv *cb_priv;
+ struct nec7210_priv *nec_priv;
+ unsigned int bits;
+ int retval;
+
+ retval = cb7210_generic_attach(board);
+ if (retval)
+ return retval;
+ cb_priv = board->private_data;
+ nec_priv = &cb_priv->nec7210_priv;
+ if (request_region((unsigned long)config->ibbase, cb7210_iosize, "cb7210") == 0) {
+ pr_err("gpib: ioports starting at 0x%p are already in use\n", config->ibbase);
+ return -EIO;
+ }
+ nec_priv->iobase = config->ibbase;
+ cb_priv->fifo_iobase = nec7210_iobase(cb_priv);
+
+ bits = irq_bits(config->ibirq);
+ if (bits == 0)
+ pr_err("board incapable of using irq %i, try 2-5, 7, 10, or 11\n", config->ibirq);
+
+ // install interrupt handler
+ if (request_irq(config->ibirq, cb7210_interrupt, isr_flags, "cb7210", board)) {
+ pr_err("gpib: can't request IRQ %d\n", config->ibirq);
+ return -EBUSY;
+ }
+ cb_priv->irq = config->ibirq;
+
+ return cb7210_init(cb_priv, board);
+}
+
+void cb_isa_detach(gpib_board_t *board)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (cb_priv) {
+ gpib_free_pseudo_irq(board);
+ nec_priv = &cb_priv->nec7210_priv;
+ if (cb_priv->irq)
+ free_irq(cb_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ release_region(nec7210_iobase(cb_priv), cb7210_iosize);
+ }
+ }
+ cb7210_generic_detach(board);
+}
+
+static int cb7210_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static const struct pci_device_id cb7210_pci_table[] = {
+ {PCI_VENDOR_ID_CBOARDS, PCI_DEVICE_ID_CBOARDS_PCI_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ {PCI_VENDOR_ID_CBOARDS, PCI_DEVICE_ID_CBOARDS_CPCI_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ {PCI_VENDOR_ID_QUANCOM, PCI_DEVICE_ID_QUANCOM_GPIB, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, cb7210_pci_table);
+
+static struct pci_driver cb7210_pci_driver = {
+ .name = "cb7210",
+ .id_table = cb7210_pci_table,
+ .probe = &cb7210_pci_probe
+};
+
+/***************************************************************************
+ * Support for computer boards pcmcia-gpib card
+ *
+ * Based on gpib PCMCIA client driver written by Claus Schroeter
+ * (clausi@chemie.fu-berlin.de), which was adapted from the
+ * pcmcia skeleton example (presumably David Hinds)
+ ***************************************************************************/
+
+#ifdef GPIB_PCMCIA
+
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/io.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+
+/*
+ * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
+ * you do not define PCMCIA_DEBUG at all, all the debug code will be
+ * left out. If you compile with PCMCIA_DEBUG=0, the debug code will
+ * be present but disabled -- but it can then be enabled for specific
+ * modules at load time with a 'pc_debug=#' option to insmod.
+ */
+
+#define PCMCIA_DEBUG 1
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+#define DEBUG(n, args...) do {if (pc_debug > (n)) pr_debug(args); } while (0)
+#else
+#define DEBUG(args...)
+#endif
+
+/*
+ * The event() function is this driver's Card Services event handler.
+ * It will be called by Card Services when an appropriate card status
+ * event is received. The config() and release() entry points are
+ * used to configure or release a socket, in response to card insertion
+ * and ejection events. They are invoked from the gpib event
+ * handler.
+ */
+
+static int cb_gpib_config(struct pcmcia_device *link);
+static void cb_gpib_release(struct pcmcia_device *link);
+static int cb_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static void cb_pcmcia_detach(gpib_board_t *board);
+
+/*
+ * A linked list of "instances" of the gpib device. Each actual
+ * PCMCIA card corresponds to one device instance, and is described
+ * by one dev_link_t structure (defined in ds.h).
+ *
+ * You may not want to use a linked list for this -- for example, the
+ * memory card driver uses an array of dev_link_t pointers, where minor
+ * device numbers are used to derive the corresponding array index.
+ */
+
+static struct pcmcia_device *curr_dev;
+
+/*
+ * A dev_link_t structure has fields for most things that are needed
+ * to keep track of a socket, but there will usually be some device
+ * specific information that also needs to be kept track of. The
+ * 'priv' pointer in a dev_link_t structure can be used to point to
+ * a device-specific private data structure, like this.
+ *
+ * A driver needs to provide a dev_node_t structure for each device
+ * on a card. In some cases, there is only one device per card (for
+ * example, ethernet cards, modems). In other cases, there may be
+ * many actual or logical devices (SCSI adapters, memory cards with
+ * multiple partitions). The dev_node_t structures need to be kept
+ * in a linked list starting at the 'dev' field of a dev_link_t
+ * structure. We allocate them in the card's private data structure,
+ * because they generally can't be allocated dynamically.
+ */
+
+struct local_info {
+ struct pcmcia_device *p_dev;
+ gpib_board_t *dev;
+};
+
+/*
+ * gpib_attach() creates an "instance" of the driver, allocating
+ * local data structures for one device. The device is registered
+ * with Card Services.
+ *
+ * The dev_link structure is initialized, but we don't actually
+ * configure the card at this point -- we wait until we receive a
+ * card insertion event.
+ */
+
+static int cb_gpib_probe(struct pcmcia_device *link)
+{
+ struct local_info *info;
+
+// int ret, i;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ /* Allocate space for private device-specific data */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->p_dev = link;
+ link->priv = info;
+
+ /* The io structure describes IO port mapping */
+ link->resource[0]->end = 16;
+ link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
+ link->resource[1]->end = 16;
+ link->resource[1]->flags &= ~IO_DATA_PATH_WIDTH;
+ link->resource[1]->flags |= IO_DATA_PATH_WIDTH_16;
+ link->io_lines = 10;
+
+ /* General socket configuration */
+ link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+ link->config_index = 1;
+ link->config_regs = PRESENT_OPTION;
+
+ /* Register with Card Services */
+ curr_dev = link;
+ return cb_gpib_config(link);
+} /* gpib_attach */
+
+/*
+ * This deletes a driver "instance". The device is de-registered
+ * with Card Services. If it has been released, all local data
+ * structures are freed. Otherwise, the structures will be freed
+ * when the device is released.
+ */
+
+static void cb_gpib_remove(struct pcmcia_device *link)
+{
+ struct local_info *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ if (info->dev)
+ cb_pcmcia_detach(info->dev);
+ cb_gpib_release(link);
+
+ //free_netdev(dev);
+ kfree(info);
+}
+
+static int cb_gpib_config_iteration(struct pcmcia_device *link, void *priv_data)
+{
+ return pcmcia_request_io(link);
+}
+
+/*
+ * gpib_config() is scheduled to run after a CARD_INSERTION event
+ * is received, to configure the PCMCIA socket, and to make the
+ * ethernet device available to the system.
+ */
+
+static int cb_gpib_config(struct pcmcia_device *link)
+{
+ struct pcmcia_device *handle;
+ struct local_info *dev;
+ int retval;
+
+ handle = link;
+ dev = link->priv;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ retval = pcmcia_loop_config(link, &cb_gpib_config_iteration, NULL);
+ if (retval) {
+ dev_warn(&link->dev, "no configuration found\n");
+ cb_gpib_release(link);
+ return -ENODEV;
+ }
+
+ DEBUG(0, "gpib_cs: manufacturer: 0x%x card: 0x%x\n", link->manf_id, link->card_id);
+
+ /*
+ * This actually configures the PCMCIA socket -- setting up
+ * the I/O windows and the interrupt mapping.
+ */
+ retval = pcmcia_enable_device(link);
+ if (retval) {
+ dev_warn(&link->dev, "pcmcia_enable_device failed\n");
+ cb_gpib_release(link);
+ return -ENODEV;
+ }
+
+ pr_info("gpib device loaded\n");
+ return 0;
+} /* gpib_config */
+
+/*
+ * After a card is removed, gpib_release() will unregister the net
+ * device, and release the PCMCIA configuration. If the device is
+ * still open, this will be postponed until it is closed.
+ */
+
+static void cb_gpib_release(struct pcmcia_device *link)
+{
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+ pcmcia_disable_device(link);
+}
+
+static int cb_gpib_suspend(struct pcmcia_device *link)
+{
+ //struct local_info *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ if (link->open)
+ pr_warn("Device still open ???\n");
+ //netif_device_detach(dev);
+
+ return 0;
+}
+
+static int cb_gpib_resume(struct pcmcia_device *link)
+{
+ //struct local_info *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ /*if (link->open) {
+ * ni_gpib_probe(dev); / really?
+ * printk("Gpib resumed ???\n");
+ * //netif_device_attach(dev);
+ *
+ */
+ return cb_gpib_config(link);
+}
+
+/*====================================================================*/
+
+static struct pcmcia_device_id cb_pcmcia_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x01c5, 0x0005),
+ PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, cb_pcmcia_ids);
+
+static struct pcmcia_driver cb_gpib_cs_driver = {
+ .owner = THIS_MODULE,
+ .drv = { .name = "cb_gpib_cs", },
+ .id_table = cb_pcmcia_ids,
+ .probe = cb_gpib_probe,
+ .remove = cb_gpib_remove,
+ .suspend = cb_gpib_suspend,
+ .resume = cb_gpib_resume,
+};
+
+int cb_pcmcia_init_module(void)
+{
+ pcmcia_register_driver(&cb_gpib_cs_driver);
+ return 0;
+}
+
+void cb_pcmcia_cleanup_module(void)
+{
+ DEBUG(0, "cb_gpib_cs: unloading\n");
+ pcmcia_unregister_driver(&cb_gpib_cs_driver);
+}
+
+gpib_interface_t cb_pcmcia_unaccel_interface = {
+name: "cbi_pcmcia_unaccel",
+attach : cb_pcmcia_attach,
+detach : cb_pcmcia_detach,
+read : cb7210_read,
+write : cb7210_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_pcmcia_interface = {
+name: "cbi_pcmcia",
+attach : cb_pcmcia_attach,
+detach : cb_pcmcia_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+gpib_interface_t cb_pcmcia_accel_interface = {
+name: "cbi_pcmcia_accel",
+attach : cb_pcmcia_attach,
+detach : cb_pcmcia_detach,
+read : cb7210_accel_read,
+write : cb7210_accel_write,
+command : cb7210_command,
+take_control : cb7210_take_control,
+go_to_standby : cb7210_go_to_standby,
+request_system_control : cb7210_request_system_control,
+interface_clear : cb7210_interface_clear,
+remote_enable : cb7210_remote_enable,
+enable_eos : cb7210_enable_eos,
+disable_eos : cb7210_disable_eos,
+parallel_poll : cb7210_parallel_poll,
+parallel_poll_configure : cb7210_parallel_poll_configure,
+parallel_poll_response : cb7210_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : cb7210_line_status,
+update_status : cb7210_update_status,
+primary_address : cb7210_primary_address,
+secondary_address : cb7210_secondary_address,
+serial_poll_response : cb7210_serial_poll_response,
+serial_poll_status : cb7210_serial_poll_status,
+t1_delay : cb7210_t1_delay,
+return_to_local : cb7210_return_to_local,
+};
+
+int cb_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct cb7210_priv *cb_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ if (!curr_dev) {
+ pr_err("no cb pcmcia cards found\n");
+ return -1;
+ }
+
+ retval = cb7210_generic_attach(board);
+ if (retval)
+ return retval;
+
+ cb_priv = board->private_data;
+ nec_priv = &cb_priv->nec7210_priv;
+
+ if (request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]),
+ "cb7210") == 0) {
+ pr_err("gpib: ioports starting at 0x%lx are already in use\n",
+ (unsigned long)curr_dev->resource[0]->start);
+ return -EIO;
+ }
+ nec_priv->iobase = (void *)(unsigned long)curr_dev->resource[0]->start;
+ cb_priv->fifo_iobase = curr_dev->resource[0]->start;
+
+ if (request_irq(curr_dev->irq, cb7210_interrupt, IRQF_SHARED,
+ "cb7210", board)) {
+ pr_err("cb7210: failed to request IRQ %d\n", curr_dev->irq);
+ return -1;
+ }
+ cb_priv->irq = curr_dev->irq;
+
+ return cb7210_init(cb_priv, board);
+}
+
+void cb_pcmcia_detach(gpib_board_t *board)
+{
+ struct cb7210_priv *cb_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (cb_priv) {
+ nec_priv = &cb_priv->nec7210_priv;
+ gpib_free_pseudo_irq(board);
+ if (cb_priv->irq)
+ free_irq(cb_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ release_region(nec7210_iobase(cb_priv), cb7210_iosize);
+ }
+ }
+ cb7210_generic_detach(board);
+}
+
+#endif /* GPIB_PCMCIA */
+
+static int __init cb7210_init_module(void)
+{
+ int err = 0;
+ int result;
+
+ result = pci_register_driver(&cb7210_pci_driver);
+ if (result) {
+ pr_err("cb7210: pci_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&cb_pci_interface, THIS_MODULE);
+ gpib_register_driver(&cb_isa_interface, THIS_MODULE);
+ gpib_register_driver(&cb_pci_accel_interface, THIS_MODULE);
+ gpib_register_driver(&cb_pci_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&cb_isa_accel_interface, THIS_MODULE);
+ gpib_register_driver(&cb_isa_unaccel_interface, THIS_MODULE);
+
+#ifdef GPIB__PCMCIA
+ gpib_register_driver(&cb_pcmcia_interface, THIS_MODULE);
+ gpib_register_driver(&cb_pcmcia_accel_interface, THIS_MODULE);
+ gpib_register_driver(&cb_pcmcia_unaccel_interface, THIS_MODULE);
+ err += cb_pcmcia_init_module();
+#endif
+ if (err)
+ return -1;
+
+ return 0;
+}
+
+static void __exit cb7210_exit_module(void)
+{
+ gpib_unregister_driver(&cb_pci_interface);
+ gpib_unregister_driver(&cb_isa_interface);
+ gpib_unregister_driver(&cb_pci_accel_interface);
+ gpib_unregister_driver(&cb_pci_unaccel_interface);
+ gpib_unregister_driver(&cb_isa_accel_interface);
+ gpib_unregister_driver(&cb_isa_unaccel_interface);
+#ifdef GPIB_PCMCIA
+ gpib_unregister_driver(&cb_pcmcia_interface);
+ gpib_unregister_driver(&cb_pcmcia_accel_interface);
+ gpib_unregister_driver(&cb_pcmcia_unaccel_interface);
+ cb_pcmcia_cleanup_module();
+#endif
+
+ pci_unregister_driver(&cb7210_pci_driver);
+}
+
+module_init(cb7210_init_module);
+module_exit(cb7210_exit_module);
diff --git a/drivers/staging/gpib/cb7210/cb7210.h b/drivers/staging/gpib/cb7210/cb7210.h
new file mode 100644
index 000000000000..4ad976de2b68
--- /dev/null
+++ b/drivers/staging/gpib/cb7210/cb7210.h
@@ -0,0 +1,251 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "nec7210.h"
+#include "gpibP.h"
+#include "amccs5933.h"
+
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+
+enum {
+ PCI_DEVICE_ID_CBOARDS_PCI_GPIB = 0x6,
+ PCI_DEVICE_ID_CBOARDS_CPCI_GPIB = 0xe,
+};
+
+enum pci_chip {
+ PCI_CHIP_NONE = 0,
+ PCI_CHIP_AMCC_S5933,
+ PCI_CHIP_QUANCOM
+};
+
+// struct which defines private_data for cb7210 boards
+struct cb7210_priv {
+ struct nec7210_priv nec7210_priv;
+ struct pci_dev *pci_device;
+ // base address of amccs5933 pci chip
+ unsigned long amcc_iobase;
+ unsigned long fifo_iobase;
+ unsigned int irq;
+ enum pci_chip pci_chip;
+ u8 hs_mode_bits;
+ unsigned out_fifo_half_empty : 1;
+ unsigned in_fifo_half_full : 1;
+};
+
+// interfaces
+extern gpib_interface_t cb_pcmcia_interface;
+extern gpib_interface_t cb_pcmcia_accel_interface;
+extern gpib_interface_t cb_pcmcia_unaccel_interface;
+
+// interrupt service routines
+irqreturn_t cb_pci_interrupt(int irq, void *arg);
+irqreturn_t cb7210_interrupt(int irq, void *arg);
+irqreturn_t cb7210_internal_interrupt(gpib_board_t *board);
+
+// interface functions
+int cb7210_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read);
+int cb7210_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read);
+int cb7210_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+int cb7210_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+int cb7210_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written);
+int cb7210_take_control(gpib_board_t *board, int synchronous);
+int cb7210_go_to_standby(gpib_board_t *board);
+void cb7210_request_system_control(gpib_board_t *board, int request_control);
+void cb7210_interface_clear(gpib_board_t *board, int assert);
+void cb7210_remote_enable(gpib_board_t *board, int enable);
+int cb7210_enable_eos(gpib_board_t *board, uint8_t eos_byte,
+ int compare_8_bits);
+void cb7210_disable_eos(gpib_board_t *board);
+unsigned int cb7210_update_status(gpib_board_t *board, unsigned int clear_mask);
+int cb7210_primary_address(gpib_board_t *board, unsigned int address);
+int cb7210_secondary_address(gpib_board_t *board, unsigned int address,
+ int enable);
+int cb7210_parallel_poll(gpib_board_t *board, uint8_t *result);
+void cb7210_serial_poll_response(gpib_board_t *board, uint8_t status);
+uint8_t cb7210_serial_poll_status(gpib_board_t *board);
+void cb7210_parallel_poll_configure(gpib_board_t *board, uint8_t configuration);
+void cb7210_parallel_poll_response(gpib_board_t *board, int ist);
+int cb7210_line_status(const gpib_board_t *board);
+unsigned int cb7210_t1_delay(gpib_board_t *board, unsigned int nano_sec);
+void cb7210_return_to_local(gpib_board_t *board);
+
+// utility functions
+void cb7210_generic_detach(gpib_board_t *board);
+int cb7210_generic_attach(gpib_board_t *board);
+int cb7210_init(struct cb7210_priv *priv, gpib_board_t *board);
+
+// pcmcia init/cleanup
+int cb_pcmcia_init_module(void);
+void cb_pcmcia_cleanup_module(void);
+
+// pci-gpib register offset
+static const int cb7210_reg_offset = 1;
+
+// uses 10 ioports
+static const int cb7210_iosize = 10;
+
+// fifo size in bytes
+static const int cb7210_fifo_size = 2048;
+static const int cb7210_fifo_width = 2;
+
+// cb7210 specific registers and bits
+enum cb7210_regs {
+ BUS_STATUS = 0x7,
+};
+
+enum cb7210_page_in {
+ BUS_STATUS_PAGE = 1,
+};
+
+enum hs_regs {
+ //write registers
+ HS_MODE = 0x8, /* HS_MODE register */
+ HS_INT_LEVEL = 0x9, /* HS_INT_LEVEL register */
+ //read registers
+ HS_STATUS = 0x8, /* HS_STATUS register */
+};
+
+static inline unsigned long nec7210_iobase(const struct cb7210_priv *cb_priv)
+{
+ return (unsigned long)(cb_priv->nec7210_priv.iobase);
+}
+
+static inline int cb7210_page_in_bits(unsigned int page)
+{
+ return 0x50 | (page & 0xf);
+}
+
+static inline uint8_t cb7210_paged_read_byte(struct cb7210_priv *cb_priv,
+ unsigned int register_num, unsigned int page)
+{
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ u8 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset);
+ udelay(1);
+ retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+ return retval;
+}
+
+// don't use for register_num < 8, since it doesn't lock
+static inline uint8_t cb7210_read_byte(const struct cb7210_priv *cb_priv,
+ enum hs_regs register_num)
+{
+ const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ u8 retval;
+
+ retval = inb(nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
+ return retval;
+}
+
+static inline void cb7210_paged_write_byte(struct cb7210_priv *cb_priv, uint8_t data,
+ unsigned int register_num, unsigned int page)
+{
+ struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ outb(cb7210_page_in_bits(page), nec7210_iobase(cb_priv) + AUXMR * nec_priv->offset);
+ udelay(1);
+ outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+}
+
+// don't use for register_num < 8, since it doesn't lock
+static inline void cb7210_write_byte(const struct cb7210_priv *cb_priv, uint8_t data,
+ enum hs_regs register_num)
+{
+ const struct nec7210_priv *nec_priv = &cb_priv->nec7210_priv;
+
+ outb(data, nec7210_iobase(cb_priv) + register_num * nec_priv->offset);
+}
+
+enum bus_status_bits {
+ BSR_ATN_BIT = 0x1,
+ BSR_EOI_BIT = 0x2,
+ BSR_SRQ_BIT = 0x4,
+ BSR_IFC_BIT = 0x8,
+ BSR_REN_BIT = 0x10,
+ BSR_DAV_BIT = 0x20,
+ BSR_NRFD_BIT = 0x40,
+ BSR_NDAC_BIT = 0x80,
+};
+
+/* CBI 488.2 HS control */
+
+/* when both bit 0 and 1 are set, it
+ * 1 clears the transmit state machine to an initial condition
+ * 2 clears any residual interrupts left latched on cbi488.2
+ * 3 resets all control bits in HS_MODE to zero
+ * 4 enables TX empty interrupts
+ * when both bit 0 and 1 are zero, then the high speed mode is disabled
+ */
+enum hs_mode_bits {
+ HS_ENABLE_MASK = 0x3,
+ HS_TX_ENABLE = (1 << 0),
+ HS_RX_ENABLE = (1 << 1),
+ HS_HF_INT_EN = (1 << 3),
+ HS_CLR_SRQ_INT = (1 << 4),
+ HS_CLR_EOI_EMPTY_INT = (1 << 5),
+ HS_CLR_HF_INT = (1 << 6),
+ HS_SYS_CONTROL = (1 << 7),
+};
+
+/* CBI 488.2 status */
+enum hs_status_bits {
+ HS_FIFO_FULL = (1 << 0),
+ HS_HALF_FULL = (1 << 1),
+ HS_SRQ_INT = (1 << 2),
+ HS_EOI_INT = (1 << 3),
+ HS_TX_MSB_NOT_EMPTY = (1 << 4),
+ HS_RX_MSB_NOT_EMPTY = (1 << 5),
+ HS_TX_LSB_NOT_EMPTY = (1 << 6),
+ HS_RX_LSB_NOT_EMPTY = (1 << 7),
+};
+
+/* CBI488.2 hs_int_level register */
+enum hs_int_level_bits {
+ HS_RESET7210 = (1 << 7),
+};
+
+static inline unsigned int irq_bits(unsigned int irq)
+{
+ switch (irq) {
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ return irq - 1;
+ case 7:
+ return 0x5;
+ case 10:
+ return 0x6;
+ case 11:
+ return 0x7;
+ default:
+ return 0;
+ }
+}
+
+enum cb7210_aux_cmds {
+/* AUX_RTL2 is an undocumented aux command which causes cb7210 to assert
+ * (and keep asserted) local rtl message. This is used in conjunction
+ * with the (stupid) cb7210 implementation
+ * of the normal nec7210 AUX_RTL aux command, which
+ * causes the rtl message to toggle between on and off.
+ */
+ AUX_RTL2 = 0xd,
+ AUX_LO_SPEED = 0x40,
+ AUX_HI_SPEED = 0x41,
+};
diff --git a/drivers/staging/gpib/cec/Makefile b/drivers/staging/gpib/cec/Makefile
new file mode 100644
index 000000000000..f4638628ff29
--- /dev/null
+++ b/drivers/staging/gpib/cec/Makefile
@@ -0,0 +1,3 @@
+
+obj-m += cec_gpib.o
+
diff --git a/drivers/staging/gpib/cec/cec.h b/drivers/staging/gpib/cec/cec.h
new file mode 100644
index 000000000000..352cf83d8328
--- /dev/null
+++ b/drivers/staging/gpib/cec/cec.h
@@ -0,0 +1,53 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "nec7210.h"
+#include "gpibP.h"
+#include "plx9050.h"
+
+struct cec_priv {
+ struct nec7210_priv nec7210_priv;
+ struct pci_dev *pci_device;
+ // base address for plx9052 pci chip
+ unsigned long plx_iobase;
+ unsigned int irq;
+};
+
+// interfaces
+extern gpib_interface_t cec_pci_interface;
+extern gpib_interface_t cec_pcmcia_interface;
+
+// interface functions
+int cec_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read);
+int cec_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+int cec_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written);
+int cec_take_control(gpib_board_t *board, int synchronous);
+int cec_go_to_standby(gpib_board_t *board);
+void cec_request_system_control(gpib_board_t *board, int request_control);
+void cec_interface_clear(gpib_board_t *board, int assert);
+void cec_remote_enable(gpib_board_t *board, int enable);
+int cec_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits);
+void cec_disable_eos(gpib_board_t *board);
+unsigned int cec_update_status(gpib_board_t *board, unsigned int clear_mask);
+int cec_primary_address(gpib_board_t *board, unsigned int address);
+int cec_secondary_address(gpib_board_t *board, unsigned int address, int enable);
+int cec_parallel_poll(gpib_board_t *board, uint8_t *result);
+void cec_parallel_poll_configure(gpib_board_t *board, uint8_t configuration);
+void cec_parallel_poll_response(gpib_board_t *board, int ist);
+void cec_serial_poll_response(gpib_board_t *board, uint8_t status);
+void cec_return_to_local(gpib_board_t *board);
+
+// interrupt service routines
+irqreturn_t cec_interrupt(int irq, void *arg);
+
+// utility functions
+void cec_free_private(gpib_board_t *board);
+int cec_generic_attach(gpib_board_t *board);
+void cec_init(struct cec_priv *priv, const gpib_board_t *board);
+
+// offset between consecutive nec7210 registers
+static const int cec_reg_offset = 1;
diff --git a/drivers/staging/gpib/cec/cec_gpib.c b/drivers/staging/gpib/cec/cec_gpib.c
new file mode 100644
index 000000000000..3dc933deb401
--- /dev/null
+++ b/drivers/staging/gpib/cec/cec_gpib.c
@@ -0,0 +1,385 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "cec.h"
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <asm/dma.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for CEC PCI and PCMCIA boards");
+
+/*
+ * GPIB interrupt service routines
+ */
+
+irqreturn_t cec_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct cec_priv *priv = board->private_data;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = nec7210_interrupt(board, &priv->nec7210_priv);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+#define CEC_VENDOR_ID 0x12fc
+#define CEC_DEV_ID 0x5cec
+#define CEC_SUBID 0x9050
+
+static int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void cec_pci_detach(gpib_board_t *board);
+
+// wrappers for interface functions
+int cec_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+}
+
+int cec_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int cec_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+int cec_take_control(gpib_board_t *board, int synchronous)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+int cec_go_to_standby(gpib_board_t *board)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+void cec_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_request_system_control(board, &priv->nec7210_priv, request_control);
+}
+
+void cec_interface_clear(gpib_board_t *board, int assert)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+void cec_remote_enable(gpib_board_t *board, int enable)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+int cec_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+void cec_disable_eos(gpib_board_t *board)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+unsigned int cec_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+int cec_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+int cec_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+int cec_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+void cec_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config);
+}
+
+void cec_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+void cec_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+static uint8_t cec_serial_poll_status(gpib_board_t *board)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+static unsigned int cec_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct cec_priv *priv = board->private_data;
+
+ return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec);
+}
+
+void cec_return_to_local(gpib_board_t *board)
+{
+ struct cec_priv *priv = board->private_data;
+
+ nec7210_return_to_local(board, &priv->nec7210_priv);
+}
+
+gpib_interface_t cec_pci_interface = {
+name: "cec_pci",
+attach : cec_pci_attach,
+detach : cec_pci_detach,
+read : cec_read,
+write : cec_write,
+command : cec_command,
+take_control : cec_take_control,
+go_to_standby : cec_go_to_standby,
+request_system_control : cec_request_system_control,
+interface_clear : cec_interface_clear,
+remote_enable : cec_remote_enable,
+enable_eos : cec_enable_eos,
+disable_eos : cec_disable_eos,
+parallel_poll : cec_parallel_poll,
+parallel_poll_configure : cec_parallel_poll_configure,
+parallel_poll_response : cec_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL, //XXX
+update_status : cec_update_status,
+primary_address : cec_primary_address,
+secondary_address : cec_secondary_address,
+serial_poll_response : cec_serial_poll_response,
+serial_poll_status : cec_serial_poll_status,
+t1_delay : cec_t1_delay,
+return_to_local : cec_return_to_local,
+};
+
+static int cec_allocate_private(gpib_board_t *board)
+{
+ struct cec_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct cec_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct cec_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ return 0;
+}
+
+void cec_free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+int cec_generic_attach(gpib_board_t *board)
+{
+ struct cec_priv *cec_priv;
+ struct nec7210_priv *nec_priv;
+
+ board->status = 0;
+
+ if (cec_allocate_private(board))
+ return -ENOMEM;
+ cec_priv = board->private_data;
+ nec_priv = &cec_priv->nec7210_priv;
+ nec_priv->read_byte = nec7210_ioport_read_byte;
+ nec_priv->write_byte = nec7210_ioport_write_byte;
+ nec_priv->offset = cec_reg_offset;
+ nec_priv->type = NEC7210; // guess
+ return 0;
+}
+
+void cec_init(struct cec_priv *cec_priv, const gpib_board_t *board)
+{
+ struct nec7210_priv *nec_priv = &cec_priv->nec7210_priv;
+
+ nec7210_board_reset(nec_priv, board);
+
+ /* set internal counter register for 8 MHz input clock */
+ write_byte(nec_priv, ICR | 8, AUXMR);
+
+ nec7210_board_online(nec_priv, board);
+}
+
+int cec_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct cec_priv *cec_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ int retval;
+
+ retval = cec_generic_attach(board);
+ if (retval)
+ return retval;
+
+ cec_priv = board->private_data;
+ nec_priv = &cec_priv->nec7210_priv;
+
+ // find board
+ cec_priv->pci_device = NULL;
+ while ((cec_priv->pci_device =
+ gpib_pci_get_device(config, CEC_VENDOR_ID,
+ CEC_DEV_ID, cec_priv->pci_device))) {
+ // check for board with plx9050 controller
+ if (cec_priv->pci_device->subsystem_device == CEC_SUBID)
+ break;
+ }
+ if (!cec_priv->pci_device) {
+ pr_err("gpib: no cec PCI board found\n");
+ return -1;
+ }
+
+ if (pci_enable_device(cec_priv->pci_device)) {
+ pr_err("error enabling pci device\n");
+ return -1;
+ }
+
+ if (pci_request_regions(cec_priv->pci_device, "cec-gpib"))
+ return -1;
+
+ cec_priv->plx_iobase = pci_resource_start(cec_priv->pci_device, 1);
+ pr_info(" plx9050 base address 0x%lx\n", cec_priv->plx_iobase);
+ nec_priv->iobase = (void *)(pci_resource_start(cec_priv->pci_device, 3));
+ pr_info(" nec7210 base address 0x%p\n", nec_priv->iobase);
+
+ isr_flags |= IRQF_SHARED;
+ if (request_irq(cec_priv->pci_device->irq, cec_interrupt, isr_flags, "pci-gpib", board)) {
+ pr_err("gpib: can't request IRQ %d\n", cec_priv->pci_device->irq);
+ return -1;
+ }
+ cec_priv->irq = cec_priv->pci_device->irq;
+ if (gpib_request_pseudo_irq(board, cec_interrupt)) {
+ pr_err("cec: failed to allocate pseudo irq\n");
+ return -1;
+ }
+ cec_init(cec_priv, board);
+
+ // enable interrupts on plx chip
+ outl(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR1_POLARITY_BIT | PLX9050_PCI_INTR_EN_BIT,
+ cec_priv->plx_iobase + PLX9050_INTCSR_REG);
+
+ return 0;
+}
+
+void cec_pci_detach(gpib_board_t *board)
+{
+ struct cec_priv *cec_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (cec_priv) {
+ nec_priv = &cec_priv->nec7210_priv;
+ gpib_free_pseudo_irq(board);
+ if (cec_priv->irq) {
+ // disable plx9050 interrupts
+ outl(0, cec_priv->plx_iobase + PLX9050_INTCSR_REG);
+ free_irq(cec_priv->irq, board);
+ }
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ pci_release_regions(cec_priv->pci_device);
+ }
+ if (cec_priv->pci_device)
+ pci_dev_put(cec_priv->pci_device);
+ }
+ cec_free_private(board);
+}
+
+static int cec_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static const struct pci_device_id cec_pci_table[] = {
+ {CEC_VENDOR_ID, CEC_DEV_ID, PCI_ANY_ID, CEC_SUBID, 0, 0, 0 },
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, cec_pci_table);
+
+static struct pci_driver cec_pci_driver = {
+ .name = "cec_gpib",
+ .id_table = cec_pci_table,
+ .probe = &cec_pci_probe
+};
+
+static int __init cec_init_module(void)
+{
+ int result;
+
+ result = pci_register_driver(&cec_pci_driver);
+ if (result) {
+ pr_err("cec_gpib: pci_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&cec_pci_interface, THIS_MODULE);
+
+ return 0;
+}
+
+static void cec_exit_module(void)
+{
+ gpib_unregister_driver(&cec_pci_interface);
+
+ pci_unregister_driver(&cec_pci_driver);
+}
+
+module_init(cec_init_module);
+module_exit(cec_exit_module);
diff --git a/drivers/staging/gpib/common/Makefile b/drivers/staging/gpib/common/Makefile
new file mode 100644
index 000000000000..460586edb574
--- /dev/null
+++ b/drivers/staging/gpib/common/Makefile
@@ -0,0 +1,6 @@
+
+obj-$(CONFIG_GPIB_COMMON) += gpib_common.o
+
+gpib_common-objs := gpib_os.o iblib.o
+
+
diff --git a/drivers/staging/gpib/common/gpib_os.c b/drivers/staging/gpib/common/gpib_os.c
new file mode 100644
index 000000000000..405237d8cb47
--- /dev/null
+++ b/drivers/staging/gpib/common/gpib_os.c
@@ -0,0 +1,2328 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2001, 2004 by Frank Mori Hess
+ ***************************************************************************
+ */
+
+#include "ibsys.h"
+#include <linux/module.h>
+#include <linux/wait.h>
+#include <linux/list.h>
+#include <linux/fs.h>
+#include <linux/pci.h>
+#include <linux/device.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/vmalloc.h>
+#include <linux/fcntl.h>
+#include <linux/kmod.h>
+#include <linux/uaccess.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB base support");
+MODULE_ALIAS_CHARDEV_MAJOR(GPIB_CODE);
+
+static int board_type_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg);
+static int read_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg);
+static int write_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg);
+static int command_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg);
+static int open_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg);
+static int close_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg);
+static int serial_poll_ioctl(gpib_board_t *board, unsigned long arg);
+static int wait_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg);
+static int parallel_poll_ioctl(gpib_board_t *board, unsigned long arg);
+static int online_ioctl(gpib_board_t *board, unsigned long arg);
+static int remote_enable_ioctl(gpib_board_t *board, unsigned long arg);
+static int take_control_ioctl(gpib_board_t *board, unsigned long arg);
+static int line_status_ioctl(gpib_board_t *board, unsigned long arg);
+static int pad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg);
+static int sad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg);
+static int eos_ioctl(gpib_board_t *board, unsigned long arg);
+static int request_service_ioctl(gpib_board_t *board, unsigned long arg);
+static int request_service2_ioctl(gpib_board_t *board, unsigned long arg);
+static int iobase_ioctl(gpib_board_config_t *config, unsigned long arg);
+static int irq_ioctl(gpib_board_config_t *config, unsigned long arg);
+static int dma_ioctl(gpib_board_config_t *config, unsigned long arg);
+static int autospoll_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg);
+static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg);
+static int timeout_ioctl(gpib_board_t *board, unsigned long arg);
+static int status_bytes_ioctl(gpib_board_t *board, unsigned long arg);
+static int board_info_ioctl(const gpib_board_t *board, unsigned long arg);
+static int ppc_ioctl(gpib_board_t *board, unsigned long arg);
+static int set_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg);
+static int get_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg);
+static int query_board_rsv_ioctl(gpib_board_t *board, unsigned long arg);
+static int interface_clear_ioctl(gpib_board_t *board, unsigned long arg);
+static int select_pci_ioctl(gpib_board_config_t *config, unsigned long arg);
+static int select_device_path_ioctl(gpib_board_config_t *config, unsigned long arg);
+static int event_ioctl(gpib_board_t *board, unsigned long arg);
+static int request_system_control_ioctl(gpib_board_t *board, unsigned long arg);
+static int t1_delay_ioctl(gpib_board_t *board, unsigned long arg);
+
+static int cleanup_open_devices(gpib_file_private_t *file_priv, gpib_board_t *board);
+
+static int pop_gpib_event_nolock(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type);
+
+/*
+ * Timer functions
+ */
+
+/* Watchdog timeout routine */
+
+static void watchdog_timeout(struct timer_list *t)
+{
+ gpib_board_t *board = from_timer(board, t, timer);
+
+ set_bit(TIMO_NUM, &board->status);
+ wake_up_interruptible(&board->wait);
+}
+
+/* install timer interrupt handler */
+void os_start_timer(gpib_board_t *board, unsigned int usec_timeout)
+/* Starts the timeout task */
+{
+ if (timer_pending(&board->timer)) {
+ pr_err("gpib: bug! timer already running?\n");
+ return;
+ }
+ clear_bit(TIMO_NUM, &board->status);
+
+ if (usec_timeout > 0) {
+ board->timer.function = watchdog_timeout;
+ /* set number of ticks */
+ mod_timer(&board->timer, jiffies + usec_to_jiffies(usec_timeout));
+ }
+}
+
+void os_remove_timer(gpib_board_t *board)
+/* Removes the timeout task */
+{
+ if (timer_pending(&board->timer))
+ del_timer_sync(&board->timer);
+}
+
+int io_timed_out(gpib_board_t *board)
+{
+ if (test_bit(TIMO_NUM, &board->status))
+ return 1;
+ return 0;
+}
+
+void writeb_wrapper(unsigned int value, void *address)
+{
+ writeb(value, address);
+};
+EXPORT_SYMBOL(writeb_wrapper);
+
+void writew_wrapper(unsigned int value, void *address)
+{
+ writew(value, address);
+};
+EXPORT_SYMBOL(writew_wrapper);
+
+unsigned int readb_wrapper(void *address)
+{
+ return readb(address);
+};
+EXPORT_SYMBOL(readb_wrapper);
+
+unsigned int readw_wrapper(void *address)
+{
+ return readw(address);
+};
+EXPORT_SYMBOL(readw_wrapper);
+
+#ifdef CONFIG_HAS_IOPORT
+void outb_wrapper(unsigned int value, void *address)
+{
+ outb(value, (unsigned long)(address));
+};
+EXPORT_SYMBOL(outb_wrapper);
+
+void outw_wrapper(unsigned int value, void *address)
+{
+ outw(value, (unsigned long)(address));
+};
+EXPORT_SYMBOL(outw_wrapper);
+
+unsigned int inb_wrapper(void *address)
+{
+ return inb((unsigned long)(address));
+};
+EXPORT_SYMBOL(inb_wrapper);
+
+unsigned int inw_wrapper(void *address)
+{
+ return inw((unsigned long)(address));
+};
+EXPORT_SYMBOL(inw_wrapper);
+#endif
+
+/* this is a function instead of a constant because of Suse
+ * defining HZ to be a function call to get_hz()
+ */
+static inline int pseudo_irq_period(void)
+{
+ return (HZ + 99) / 100;
+}
+
+static void pseudo_irq_handler(struct timer_list *t)
+{
+ struct gpib_pseudo_irq *pseudo_irq = from_timer(pseudo_irq, t, timer);
+
+ if (pseudo_irq->handler)
+ pseudo_irq->handler(0, pseudo_irq->board);
+ else
+ pr_err("gpib: bug! pseudo_irq.handler is NULL\n");
+
+ if (atomic_read(&pseudo_irq->active))
+ mod_timer(&pseudo_irq->timer, jiffies + pseudo_irq_period());
+}
+
+int gpib_request_pseudo_irq(gpib_board_t *board, irqreturn_t (*handler)(int, void *))
+{
+ if (timer_pending(&board->pseudo_irq.timer) || board->pseudo_irq.handler) {
+ pr_err("gpib: only one pseudo interrupt per board allowed\n");
+ return -1;
+ }
+
+ board->pseudo_irq.handler = handler;
+ board->pseudo_irq.timer.function = pseudo_irq_handler;
+ board->pseudo_irq.board = board;
+
+ atomic_set(&board->pseudo_irq.active, 1);
+
+ mod_timer(&board->pseudo_irq.timer, jiffies + pseudo_irq_period());
+
+ return 0;
+}
+EXPORT_SYMBOL(gpib_request_pseudo_irq);
+
+void gpib_free_pseudo_irq(gpib_board_t *board)
+{
+ atomic_set(&board->pseudo_irq.active, 0);
+
+ del_timer_sync(&board->pseudo_irq.timer);
+ board->pseudo_irq.handler = NULL;
+}
+EXPORT_SYMBOL(gpib_free_pseudo_irq);
+
+static const unsigned int serial_timeout = 1000000;
+
+unsigned int num_status_bytes(const gpib_status_queue_t *dev)
+{
+ if (!dev)
+ return 0;
+ return dev->num_status_bytes;
+}
+
+// push status byte onto back of status byte fifo
+int push_status_byte(gpib_board_t *board, gpib_status_queue_t *device, u8 poll_byte)
+{
+ struct list_head *head = &device->status_bytes;
+ status_byte_t *status;
+ static const unsigned int max_num_status_bytes = 1024;
+ int retval;
+
+ if (num_status_bytes(device) >= max_num_status_bytes) {
+ u8 lost_byte;
+
+ device->dropped_byte = 1;
+ retval = pop_status_byte(board, device, &lost_byte);
+ if (retval < 0)
+ return retval;
+ }
+
+ status = kmalloc(sizeof(status_byte_t), GFP_KERNEL);
+ if (!status)
+ return -ENOMEM;
+
+ INIT_LIST_HEAD(&status->list);
+ status->poll_byte = poll_byte;
+
+ list_add_tail(&status->list, head);
+
+ device->num_status_bytes++;
+
+ dev_dbg(board->gpib_dev, "pushed status byte 0x%x, %i in queue\n",
+ (int)poll_byte, num_status_bytes(device));
+
+ return 0;
+}
+
+// pop status byte from front of status byte fifo
+int pop_status_byte(gpib_board_t *board, gpib_status_queue_t *device, u8 *poll_byte)
+{
+ struct list_head *head = &device->status_bytes;
+ struct list_head *front = head->next;
+ status_byte_t *status;
+
+ if (num_status_bytes(device) == 0)
+ return -EIO;
+
+ if (front == head)
+ return -EIO;
+
+ if (device->dropped_byte) {
+ device->dropped_byte = 0;
+ return -EPIPE;
+ }
+
+ status = list_entry(front, status_byte_t, list);
+ *poll_byte = status->poll_byte;
+
+ list_del(front);
+ kfree(status);
+
+ device->num_status_bytes--;
+
+ dev_dbg(board->gpib_dev, "popped status byte 0x%x, %i in queue\n",
+ (int)*poll_byte, num_status_bytes(device));
+
+ return 0;
+}
+
+gpib_status_queue_t *get_gpib_status_queue(gpib_board_t *board, unsigned int pad, int sad)
+{
+ gpib_status_queue_t *device;
+ struct list_head *list_ptr;
+ const struct list_head *head = &board->device_list;
+
+ for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) {
+ device = list_entry(list_ptr, gpib_status_queue_t, list);
+ if (gpib_address_equal(device->pad, device->sad, pad, sad))
+ return device;
+ }
+
+ return NULL;
+}
+
+int get_serial_poll_byte(gpib_board_t *board, unsigned int pad, int sad, unsigned int usec_timeout,
+ uint8_t *poll_byte)
+{
+ gpib_status_queue_t *device;
+
+ dev_dbg(board->gpib_dev, "%s:()\n", __func__);
+
+ device = get_gpib_status_queue(board, pad, sad);
+ if (num_status_bytes(device))
+ return pop_status_byte(board, device, poll_byte);
+ else
+ return dvrsp(board, pad, sad, usec_timeout, poll_byte);
+}
+
+int autopoll_all_devices(gpib_board_t *board)
+{
+ int retval;
+
+ dev_dbg(board->gpib_dev, "entering %s()\n", __func__);
+ if (mutex_lock_interruptible(&board->user_mutex))
+ return -ERESTARTSYS;
+ if (mutex_lock_interruptible(&board->big_gpib_mutex)) {
+ mutex_unlock(&board->user_mutex);
+ return -ERESTARTSYS;
+ }
+
+ dev_dbg(board->gpib_dev, "autopoll has board lock\n");
+
+ retval = serial_poll_all(board, serial_timeout);
+ if (retval < 0) {
+ mutex_unlock(&board->big_gpib_mutex);
+ mutex_unlock(&board->user_mutex);
+ return retval;
+ }
+
+ dev_dbg(board->gpib_dev, "%s complete\n", __func__);
+ /* need to wake wait queue in case someone is
+ * waiting on RQS
+ */
+ wake_up_interruptible(&board->wait);
+ mutex_unlock(&board->big_gpib_mutex);
+ mutex_unlock(&board->user_mutex);
+
+ return retval;
+}
+
+static int setup_serial_poll(gpib_board_t *board, unsigned int usec_timeout)
+{
+ u8 cmd_string[8];
+ int i;
+ size_t bytes_written;
+ int ret;
+
+ dev_dbg(board->gpib_dev, "entering %s()\n", __func__);
+
+ os_start_timer(board, usec_timeout);
+ ret = ibcac(board, 1, 1);
+ if (ret < 0) {
+ os_remove_timer(board);
+ return ret;
+ }
+
+ i = 0;
+ cmd_string[i++] = UNL;
+ cmd_string[i++] = MLA(board->pad); /* controller's listen address */
+ if (board->sad >= 0)
+ cmd_string[i++] = MSA(board->sad);
+ cmd_string[i++] = SPE; //serial poll enable
+
+ ret = board->interface->command(board, cmd_string, i, &bytes_written);
+ if (ret < 0 || bytes_written < i) {
+ pr_err("gpib: failed to setup serial poll\n");
+ os_remove_timer(board);
+ return -EIO;
+ }
+ os_remove_timer(board);
+
+ return 0;
+}
+
+static int read_serial_poll_byte(gpib_board_t *board, unsigned int pad,
+ int sad, unsigned int usec_timeout, uint8_t *result)
+{
+ u8 cmd_string[8];
+ int end_flag;
+ int ret;
+ int i;
+ size_t nbytes;
+
+ dev_dbg(board->gpib_dev, "entering %s(), pad=%i sad=%i\n", __func__, pad, sad);
+
+ os_start_timer(board, usec_timeout);
+ ret = ibcac(board, 1, 1);
+ if (ret < 0) {
+ os_remove_timer(board);
+ return ret;
+ }
+
+ i = 0;
+ // send talk address
+ cmd_string[i++] = MTA(pad);
+ if (sad >= 0)
+ cmd_string[i++] = MSA(sad);
+
+ ret = board->interface->command(board, cmd_string, i, &nbytes);
+ if (ret < 0 || nbytes < i) {
+ pr_err("gpib: failed to setup serial poll\n");
+ os_remove_timer(board);
+ return -EIO;
+ }
+
+ ibgts(board);
+
+ // read poll result
+ ret = board->interface->read(board, result, 1, &end_flag, &nbytes);
+ if (ret < 0 || nbytes < 1) {
+ pr_err("gpib: serial poll failed\n");
+ os_remove_timer(board);
+ return -EIO;
+ }
+ os_remove_timer(board);
+
+ return 0;
+}
+
+static int cleanup_serial_poll(gpib_board_t *board, unsigned int usec_timeout)
+{
+ u8 cmd_string[8];
+ int ret;
+ size_t bytes_written;
+
+ dev_dbg(board->gpib_dev, "entering %s()\n", __func__);
+
+ os_start_timer(board, usec_timeout);
+ ret = ibcac(board, 1, 1);
+ if (ret < 0) {
+ os_remove_timer(board);
+ return ret;
+ }
+
+ cmd_string[0] = SPD; /* disable serial poll bytes */
+ cmd_string[1] = UNT;
+ ret = board->interface->command(board, cmd_string, 2, &bytes_written);
+ if (ret < 0 || bytes_written < 2) {
+ pr_err("gpib: failed to disable serial poll\n");
+ os_remove_timer(board);
+ return -EIO;
+ }
+ os_remove_timer(board);
+
+ return 0;
+}
+
+static int serial_poll_single(gpib_board_t *board, unsigned int pad, int sad,
+ unsigned int usec_timeout, uint8_t *result)
+{
+ int retval, cleanup_retval;
+
+ retval = setup_serial_poll(board, usec_timeout);
+ if (retval < 0)
+ return retval;
+ retval = read_serial_poll_byte(board, pad, sad, usec_timeout, result);
+ cleanup_retval = cleanup_serial_poll(board, usec_timeout);
+ if (retval < 0)
+ return retval;
+ if (cleanup_retval < 0)
+ return retval;
+
+ return 0;
+}
+
+int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout)
+{
+ int retval = 0;
+ struct list_head *cur;
+ const struct list_head *head = NULL;
+ gpib_status_queue_t *device;
+ u8 result;
+ unsigned int num_bytes = 0;
+
+ dev_dbg(board->gpib_dev, "entering %s()\n", __func__);
+
+ head = &board->device_list;
+ if (head->next == head)
+ return 0;
+
+ retval = setup_serial_poll(board, usec_timeout);
+ if (retval < 0)
+ return retval;
+
+ for (cur = head->next; cur != head; cur = cur->next) {
+ device = list_entry(cur, gpib_status_queue_t, list);
+ retval = read_serial_poll_byte(board,
+ device->pad, device->sad, usec_timeout, &result);
+ if (retval < 0)
+ continue;
+ if (result & request_service_bit) {
+ retval = push_status_byte(board, device, result);
+ if (retval < 0)
+ continue;
+ num_bytes++;
+ }
+ }
+
+ retval = cleanup_serial_poll(board, usec_timeout);
+ if (retval < 0)
+ return retval;
+
+ return num_bytes;
+}
+
+/*
+ * DVRSP
+ * This function performs a serial poll of the device with primary
+ * address pad and secondary address sad. If the device has no
+ * secondary address, pass a negative number in for this argument. At the
+ * end of a successful serial poll the response is returned in result.
+ * SPD and UNT are sent at the completion of the poll.
+ */
+
+int dvrsp(gpib_board_t *board, unsigned int pad, int sad,
+ unsigned int usec_timeout, uint8_t *result)
+{
+ int status = ibstatus(board);
+ int retval;
+
+ if ((status & CIC) == 0) {
+ pr_err("gpib: not CIC during serial poll\n");
+ return -1;
+ }
+
+ if (pad > MAX_GPIB_PRIMARY_ADDRESS || sad > MAX_GPIB_SECONDARY_ADDRESS) {
+ pr_err("gpib: bad address for serial poll");
+ return -1;
+ }
+
+ retval = serial_poll_single(board, pad, sad, usec_timeout, result);
+ if (io_timed_out(board))
+ retval = -ETIMEDOUT;
+
+ return retval;
+}
+
+static gpib_descriptor_t *handle_to_descriptor(const gpib_file_private_t *file_priv,
+ int handle)
+{
+ if (handle < 0 || handle >= GPIB_MAX_NUM_DESCRIPTORS) {
+ pr_err("gpib: invalid handle %i\n", handle);
+ return NULL;
+ }
+
+ return file_priv->descriptors[handle];
+}
+
+static int init_gpib_file_private(gpib_file_private_t *priv)
+{
+ memset(priv, 0, sizeof(*priv));
+ atomic_set(&priv->holding_mutex, 0);
+ priv->descriptors[0] = kmalloc(sizeof(gpib_descriptor_t), GFP_KERNEL);
+ if (!priv->descriptors[0]) {
+ pr_err("gpib: failed to allocate default board descriptor\n");
+ return -ENOMEM;
+ }
+ init_gpib_descriptor(priv->descriptors[0]);
+ priv->descriptors[0]->is_board = 1;
+ mutex_init(&priv->descriptors_mutex);
+ return 0;
+}
+
+int ibopen(struct inode *inode, struct file *filep)
+{
+ unsigned int minor = iminor(inode);
+ gpib_board_t *board;
+ gpib_file_private_t *priv;
+
+ if (minor >= GPIB_MAX_NUM_BOARDS) {
+ pr_err("gpib: invalid minor number of device file\n");
+ return -ENXIO;
+ }
+
+ board = &board_array[minor];
+
+ filep->private_data = kmalloc(sizeof(gpib_file_private_t), GFP_KERNEL);
+ if (!filep->private_data)
+ return -ENOMEM;
+
+ priv = filep->private_data;
+ init_gpib_file_private((gpib_file_private_t *)filep->private_data);
+
+ dev_dbg(board->gpib_dev, "pid %i, gpib: opening minor %d\n", current->pid, minor);
+
+ if (board->use_count == 0) {
+ int retval;
+
+ retval = request_module("gpib%i", minor);
+ if (retval) {
+ dev_dbg(board->gpib_dev, "pid %i, gpib: request module returned %i\n",
+ current->pid, retval);
+ }
+ }
+ if (board->interface) {
+ if (!try_module_get(board->provider_module)) {
+ pr_err("gpib: try_module_get() failed\n");
+ return -EIO;
+ }
+ board->use_count++;
+ priv->got_module = 1;
+ }
+ return 0;
+}
+
+int ibclose(struct inode *inode, struct file *filep)
+{
+ unsigned int minor = iminor(inode);
+ gpib_board_t *board;
+ gpib_file_private_t *priv = filep->private_data;
+ gpib_descriptor_t *desc;
+
+ if (minor >= GPIB_MAX_NUM_BOARDS) {
+ pr_err("gpib: invalid minor number of device file\n");
+ return -ENODEV;
+ }
+
+ board = &board_array[minor];
+
+ dev_dbg(board->gpib_dev, "pid %i, closing minor %d\n", current->pid, minor);
+
+ if (priv) {
+ desc = handle_to_descriptor(priv, 0);
+ if (desc) {
+ if (desc->autopoll_enabled) {
+ dev_dbg(board->gpib_dev, "pid %i, decrementing autospollers\n",
+ current->pid);
+ if (board->autospollers > 0)
+ board->autospollers--;
+ else
+ pr_err("gpib: Attempt to decrement zero autospollers\n");
+ }
+ } else {
+ pr_err("gpib: Unexpected null gpib_descriptor\n");
+ }
+
+ cleanup_open_devices(priv, board);
+
+ if (atomic_read(&priv->holding_mutex))
+ mutex_unlock(&board->user_mutex);
+
+ if (priv->got_module && board->use_count) {
+ module_put(board->provider_module);
+ --board->use_count;
+ }
+
+ kfree(filep->private_data);
+ filep->private_data = NULL;
+ }
+
+ return 0;
+}
+
+long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg)
+{
+ unsigned int minor = iminor(filep->f_path.dentry->d_inode);
+ gpib_board_t *board;
+ gpib_file_private_t *file_priv = filep->private_data;
+ long retval = -ENOTTY;
+
+ if (minor >= GPIB_MAX_NUM_BOARDS) {
+ pr_err("gpib: invalid minor number of device file\n");
+ return -ENODEV;
+ }
+ board = &board_array[minor];
+
+ if (mutex_lock_interruptible(&board->big_gpib_mutex))
+ return -ERESTARTSYS;
+
+ dev_dbg(board->gpib_dev, "pid %i, ioctl %d, interface=%s, use=%d, onl=%d\n",
+ current->pid, cmd & 0xff,
+ board->interface ? board->interface->name : "",
+ board->use_count,
+ board->online);
+
+ switch (cmd) {
+ case CFCBOARDTYPE:
+ retval = board_type_ioctl(file_priv, board, arg);
+ goto done;
+ case IBONL:
+ retval = online_ioctl(board, arg);
+ goto done;
+ default:
+ break;
+ }
+ if (!board->interface) {
+ pr_err("gpib: no gpib board configured on /dev/gpib%i\n", minor);
+ retval = -ENODEV;
+ goto done;
+ }
+ if (file_priv->got_module == 0) {
+ if (!try_module_get(board->provider_module)) {
+ pr_err("gpib: try_module_get() failed\n");
+ retval = -EIO;
+ goto done;
+ }
+ file_priv->got_module = 1;
+ board->use_count++;
+ }
+ switch (cmd) {
+ case CFCBASE:
+ retval = iobase_ioctl(&board->config, arg);
+ goto done;
+ case CFCIRQ:
+ retval = irq_ioctl(&board->config, arg);
+ goto done;
+ case CFCDMA:
+ retval = dma_ioctl(&board->config, arg);
+ goto done;
+ case IBAUTOSPOLL:
+ retval = autospoll_ioctl(board, file_priv, arg);
+ goto done;
+ case IBBOARD_INFO:
+ retval = board_info_ioctl(board, arg);
+ goto done;
+ case IBMUTEX:
+ /* Need to unlock board->big_gpib_mutex before potentially locking board->user_mutex
+ * to maintain consistent locking order
+ */
+ mutex_unlock(&board->big_gpib_mutex);
+ return mutex_ioctl(board, file_priv, arg);
+ case IBPAD:
+ retval = pad_ioctl(board, file_priv, arg);
+ goto done;
+ case IBSAD:
+ retval = sad_ioctl(board, file_priv, arg);
+ goto done;
+ case IBSELECT_PCI:
+ retval = select_pci_ioctl(&board->config, arg);
+ goto done;
+ case IBSELECT_DEVICE_PATH:
+ retval = select_device_path_ioctl(&board->config, arg);
+ goto done;
+ default:
+ break;
+ }
+
+ if (!board->online) {
+ pr_err("gpib: ioctl %i invalid for offline board\n",
+ cmd & 0xff);
+ retval = -EINVAL;
+ goto done;
+ }
+
+ switch (cmd) {
+ case IBEVENT:
+ retval = event_ioctl(board, arg);
+ goto done;
+ case IBCLOSEDEV:
+ retval = close_dev_ioctl(filep, board, arg);
+ goto done;
+ case IBOPENDEV:
+ retval = open_dev_ioctl(filep, board, arg);
+ goto done;
+ case IBSPOLL_BYTES:
+ retval = status_bytes_ioctl(board, arg);
+ goto done;
+ case IBWAIT:
+ retval = wait_ioctl(file_priv, board, arg);
+ if (retval == -ERESTARTSYS)
+ return retval;
+ goto done;
+ case IBLINES:
+ retval = line_status_ioctl(board, arg);
+ goto done;
+ case IBLOC:
+ board->interface->return_to_local(board);
+ retval = 0;
+ goto done;
+ default:
+ break;
+ }
+
+ spin_lock(&board->locking_pid_spinlock);
+ if (current->pid != board->locking_pid) {
+ spin_unlock(&board->locking_pid_spinlock);
+ pr_err("gpib: need to hold board lock to perform ioctl %i\n",
+ cmd & 0xff);
+ retval = -EPERM;
+ goto done;
+ }
+ spin_unlock(&board->locking_pid_spinlock);
+
+ switch (cmd) {
+ case IB_T1_DELAY:
+ retval = t1_delay_ioctl(board, arg);
+ goto done;
+ case IBCAC:
+ retval = take_control_ioctl(board, arg);
+ goto done;
+ case IBCMD:
+ /* IO ioctls can take a long time, we need to unlock board->big_gpib_mutex
+ * before we call them.
+ */
+ mutex_unlock(&board->big_gpib_mutex);
+ return command_ioctl(file_priv, board, arg);
+ case IBEOS:
+ retval = eos_ioctl(board, arg);
+ goto done;
+ case IBGTS:
+ retval = ibgts(board);
+ goto done;
+ case IBPPC:
+ retval = ppc_ioctl(board, arg);
+ goto done;
+ case IBPP2_SET:
+ retval = set_local_ppoll_mode_ioctl(board, arg);
+ goto done;
+ case IBPP2_GET:
+ retval = get_local_ppoll_mode_ioctl(board, arg);
+ goto done;
+ case IBQUERY_BOARD_RSV:
+ retval = query_board_rsv_ioctl(board, arg);
+ goto done;
+ case IBRD:
+ /* IO ioctls can take a long time, we need to unlock board->big_gpib_mutex
+ * before we call them.
+ */
+ mutex_unlock(&board->big_gpib_mutex);
+ return read_ioctl(file_priv, board, arg);
+ case IBRPP:
+ retval = parallel_poll_ioctl(board, arg);
+ goto done;
+ case IBRSC:
+ retval = request_system_control_ioctl(board, arg);
+ goto done;
+ case IBRSP:
+ retval = serial_poll_ioctl(board, arg);
+ goto done;
+ case IBRSV:
+ retval = request_service_ioctl(board, arg);
+ goto done;
+ case IBRSV2:
+ retval = request_service2_ioctl(board, arg);
+ goto done;
+ case IBSIC:
+ retval = interface_clear_ioctl(board, arg);
+ goto done;
+ case IBSRE:
+ retval = remote_enable_ioctl(board, arg);
+ goto done;
+ case IBTMO:
+ retval = timeout_ioctl(board, arg);
+ goto done;
+ case IBWRT:
+ /* IO ioctls can take a long time, we need to unlock board->big_gpib_mutex
+ * before we call them.
+ */
+ mutex_unlock(&board->big_gpib_mutex);
+ return write_ioctl(file_priv, board, arg);
+ default:
+ retval = -ENOTTY;
+ goto done;
+ }
+
+done:
+ mutex_unlock(&board->big_gpib_mutex);
+ dev_dbg(board->gpib_dev, "ioctl done status = 0x%lx\n", board->status);
+ return retval;
+}
+
+static int board_type_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board, unsigned long arg)
+{
+ struct list_head *list_ptr;
+ board_type_ioctl_t cmd;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+ if (board->online) {
+ pr_err("gpib: can't change board type while board is online.\n");
+ return -EBUSY;
+ }
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(board_type_ioctl_t));
+ if (retval)
+ return retval;
+
+ for (list_ptr = registered_drivers.next; list_ptr != &registered_drivers;
+ list_ptr = list_ptr->next) {
+ gpib_interface_list_t *entry;
+
+ entry = list_entry(list_ptr, gpib_interface_list_t, list);
+ if (strcmp(entry->interface->name, cmd.name) == 0) {
+ int i;
+ int had_module = file_priv->got_module;
+
+ if (board->use_count) {
+ for (i = 0; i < board->use_count; ++i)
+ module_put(board->provider_module);
+ board->interface = NULL;
+ file_priv->got_module = 0;
+ }
+ board->interface = entry->interface;
+ board->provider_module = entry->module;
+ for (i = 0; i < board->use_count; ++i) {
+ if (!try_module_get(entry->module)) {
+ board->use_count = i;
+ return -EIO;
+ }
+ }
+ if (had_module == 0) {
+ if (!try_module_get(entry->module))
+ return -EIO;
+ ++board->use_count;
+ }
+ file_priv->got_module = 1;
+ return 0;
+ }
+ }
+
+ return -EINVAL;
+}
+
+static int read_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg)
+{
+ read_write_ioctl_t read_cmd;
+ u8 *userbuf;
+ unsigned long remain;
+ int end_flag = 0;
+ int retval;
+ ssize_t read_ret = 0;
+ gpib_descriptor_t *desc;
+ size_t nbytes;
+
+ retval = copy_from_user(&read_cmd, (void *)arg, sizeof(read_cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (read_cmd.completed_transfer_count > read_cmd.requested_transfer_count)
+ return -EINVAL;
+
+ desc = handle_to_descriptor(file_priv, read_cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ if (WARN_ON_ONCE(sizeof(userbuf) > sizeof(read_cmd.buffer_ptr)))
+ return -EFAULT;
+
+ userbuf = (u8 *)(unsigned long)read_cmd.buffer_ptr;
+ userbuf += read_cmd.completed_transfer_count;
+
+ remain = read_cmd.requested_transfer_count - read_cmd.completed_transfer_count;
+
+ /* Check write access to buffer */
+ if (!access_ok(userbuf, remain))
+ return -EFAULT;
+
+ atomic_set(&desc->io_in_progress, 1);
+
+ /* Read buffer loads till we fill the user supplied buffer */
+ while (remain > 0 && end_flag == 0) {
+ nbytes = 0;
+ read_ret = ibrd(board, board->buffer, (board->buffer_length < remain) ?
+ board->buffer_length : remain, &end_flag, &nbytes);
+ if (nbytes == 0)
+ break;
+ retval = copy_to_user(userbuf, board->buffer, nbytes);
+ if (retval) {
+ retval = -EFAULT;
+ break;
+ }
+ remain -= nbytes;
+ userbuf += nbytes;
+ if (read_ret < 0)
+ break;
+ }
+ read_cmd.completed_transfer_count = read_cmd.requested_transfer_count - remain;
+ read_cmd.end = end_flag;
+ /* suppress errors (for example due to timeout or interruption by device clear)
+ * if all bytes got sent. This prevents races that can occur in the various drivers
+ * if a device receives a device clear immediately after a transfer completes and
+ * the driver code wasn't careful enough to handle that case.
+ */
+ if (remain == 0 || end_flag)
+ read_ret = 0;
+ if (retval == 0)
+ retval = copy_to_user((void *)arg, &read_cmd, sizeof(read_cmd));
+
+ atomic_set(&desc->io_in_progress, 0);
+
+ wake_up_interruptible(&board->wait);
+ if (retval)
+ return -EFAULT;
+
+ return read_ret;
+}
+
+static int command_ioctl(gpib_file_private_t *file_priv,
+ gpib_board_t *board, unsigned long arg)
+{
+ read_write_ioctl_t cmd;
+ u8 *userbuf;
+ unsigned long remain;
+ int retval;
+ int fault = 0;
+ gpib_descriptor_t *desc;
+ size_t bytes_written;
+ int no_clear_io_in_prog;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (cmd.completed_transfer_count > cmd.requested_transfer_count)
+ return -EINVAL;
+
+ desc = handle_to_descriptor(file_priv, cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ userbuf = (u8 *)(unsigned long)cmd.buffer_ptr;
+ userbuf += cmd.completed_transfer_count;
+
+ no_clear_io_in_prog = cmd.end;
+ cmd.end = 0;
+
+ remain = cmd.requested_transfer_count - cmd.completed_transfer_count;
+
+ /* Check read access to buffer */
+ if (!access_ok(userbuf, remain))
+ return -EFAULT;
+
+ /* Write buffer loads till we empty the user supplied buffer.
+ * Call drivers at least once, even if remain is zero, in
+ * order to allow them to insure previous commands were
+ * completely finished, in the case of a restarted ioctl.
+ */
+
+ atomic_set(&desc->io_in_progress, 1);
+
+ do {
+ fault = copy_from_user(board->buffer, userbuf, (board->buffer_length < remain) ?
+ board->buffer_length : remain);
+ if (fault) {
+ retval = -EFAULT;
+ bytes_written = 0;
+ } else {
+ retval = ibcmd(board, board->buffer, (board->buffer_length < remain) ?
+ board->buffer_length : remain, &bytes_written);
+ }
+ remain -= bytes_written;
+ userbuf += bytes_written;
+ if (retval < 0) {
+ atomic_set(&desc->io_in_progress, 0);
+
+ wake_up_interruptible(&board->wait);
+ break;
+ }
+ } while (remain > 0);
+
+ cmd.completed_transfer_count = cmd.requested_transfer_count - remain;
+
+ if (fault == 0)
+ fault = copy_to_user((void *)arg, &cmd, sizeof(cmd));
+
+ /*
+ * no_clear_io_in_prog (cmd.end) is true when io_in_progress should
+ * not be set to zero because the cmd in progress is the address setup
+ * operation for an async read or write. This causes CMPL not to be set
+ * in general_ibstatus until the async read or write completes.
+ */
+ if (!no_clear_io_in_prog || fault)
+ atomic_set(&desc->io_in_progress, 0);
+
+ wake_up_interruptible(&board->wait);
+ if (fault)
+ return -EFAULT;
+
+ return retval;
+}
+
+static int write_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg)
+{
+ read_write_ioctl_t write_cmd;
+ u8 *userbuf;
+ unsigned long remain;
+ int retval = 0;
+ int fault;
+ gpib_descriptor_t *desc;
+
+ fault = copy_from_user(&write_cmd, (void *)arg, sizeof(write_cmd));
+ if (fault)
+ return -EFAULT;
+
+ if (write_cmd.completed_transfer_count > write_cmd.requested_transfer_count)
+ return -EINVAL;
+
+ desc = handle_to_descriptor(file_priv, write_cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ userbuf = (u8 *)(unsigned long)write_cmd.buffer_ptr;
+ userbuf += write_cmd.completed_transfer_count;
+
+ remain = write_cmd.requested_transfer_count - write_cmd.completed_transfer_count;
+
+ /* Check read access to buffer */
+ if (!access_ok(userbuf, remain))
+ return -EFAULT;
+
+ atomic_set(&desc->io_in_progress, 1);
+
+ /* Write buffer loads till we empty the user supplied buffer */
+ while (remain > 0) {
+ int send_eoi;
+ size_t bytes_written = 0;
+
+ send_eoi = remain <= board->buffer_length && write_cmd.end;
+ fault = copy_from_user(board->buffer, userbuf, (board->buffer_length < remain) ?
+ board->buffer_length : remain);
+ if (fault) {
+ retval = -EFAULT;
+ break;
+ }
+ retval = ibwrt(board, board->buffer, (board->buffer_length < remain) ?
+ board->buffer_length : remain, send_eoi, &bytes_written);
+ remain -= bytes_written;
+ userbuf += bytes_written;
+ if (retval < 0)
+ break;
+ }
+ write_cmd.completed_transfer_count = write_cmd.requested_transfer_count - remain;
+ /* suppress errors (for example due to timeout or interruption by device clear)
+ * if all bytes got sent. This prevents races that can occur in the various drivers
+ * if a device receives a device clear immediately after a transfer completes and
+ * the driver code wasn't careful enough to handle that case.
+ */
+ if (remain == 0)
+ retval = 0;
+ if (fault == 0)
+ fault = copy_to_user((void *)arg, &write_cmd, sizeof(write_cmd));
+
+ atomic_set(&desc->io_in_progress, 0);
+
+ wake_up_interruptible(&board->wait);
+ if (fault)
+ return -EFAULT;
+
+ return retval;
+}
+
+static int status_bytes_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ gpib_status_queue_t *device;
+ spoll_bytes_ioctl_t cmd;
+ int retval;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ device = get_gpib_status_queue(board, cmd.pad, cmd.sad);
+ if (!device)
+ cmd.num_bytes = 0;
+ else
+ cmd.num_bytes = num_status_bytes(device);
+
+ retval = copy_to_user((void *)arg, &cmd, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int increment_open_device_count(gpib_board_t *board, struct list_head *head,
+ unsigned int pad, int sad)
+{
+ struct list_head *list_ptr;
+ gpib_status_queue_t *device;
+
+ /* first see if address has already been opened, then increment
+ * open count
+ */
+ for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) {
+ device = list_entry(list_ptr, gpib_status_queue_t, list);
+ if (gpib_address_equal(device->pad, device->sad, pad, sad)) {
+ dev_dbg(board->gpib_dev, "pid %i, incrementing open count for pad %i, sad %i\n",
+ current->pid, device->pad, device->sad);
+ device->reference_count++;
+ return 0;
+ }
+ }
+
+ /* otherwise we need to allocate a new gpib_status_queue_t */
+ device = kmalloc(sizeof(gpib_status_queue_t), GFP_ATOMIC);
+ if (!device)
+ return -ENOMEM;
+ init_gpib_status_queue(device);
+ device->pad = pad;
+ device->sad = sad;
+ device->reference_count = 1;
+
+ list_add(&device->list, head);
+
+ dev_dbg(board->gpib_dev, "pid %i, opened pad %i, sad %i\n",
+ current->pid, device->pad, device->sad);
+
+ return 0;
+}
+
+static int subtract_open_device_count(gpib_board_t *board, struct list_head *head,
+ unsigned int pad, int sad, unsigned int count)
+{
+ gpib_status_queue_t *device;
+ struct list_head *list_ptr;
+
+ for (list_ptr = head->next; list_ptr != head; list_ptr = list_ptr->next) {
+ device = list_entry(list_ptr, gpib_status_queue_t, list);
+ if (gpib_address_equal(device->pad, device->sad, pad, sad)) {
+ dev_dbg(board->gpib_dev, "pid %i, decrementing open count for pad %i, sad %i\n",
+ current->pid, device->pad, device->sad);
+ if (count > device->reference_count) {
+ pr_err("gpib: bug! in %s()\n", __func__);
+ return -EINVAL;
+ }
+ device->reference_count -= count;
+ if (device->reference_count == 0) {
+ dev_dbg(board->gpib_dev, "pid %i, closing pad %i, sad %i\n",
+ current->pid, device->pad, device->sad);
+ list_del(list_ptr);
+ kfree(device);
+ }
+ return 0;
+ }
+ }
+ pr_err("gpib: bug! tried to close address that was never opened!\n");
+ return -EINVAL;
+}
+
+static inline int decrement_open_device_count(gpib_board_t *board, struct list_head *head,
+ unsigned int pad, int sad)
+{
+ return subtract_open_device_count(board, head, pad, sad, 1);
+}
+
+static int cleanup_open_devices(gpib_file_private_t *file_priv, gpib_board_t *board)
+{
+ int retval = 0;
+ int i;
+
+ for (i = 0; i < GPIB_MAX_NUM_DESCRIPTORS; i++) {
+ gpib_descriptor_t *desc;
+
+ desc = file_priv->descriptors[i];
+ if (!desc)
+ continue;
+
+ if (desc->is_board == 0) {
+ retval = decrement_open_device_count(board, &board->device_list, desc->pad,
+ desc->sad);
+ if (retval < 0)
+ return retval;
+ }
+ kfree(desc);
+ file_priv->descriptors[i] = NULL;
+ }
+
+ return 0;
+}
+
+static int open_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg)
+{
+ open_dev_ioctl_t open_dev_cmd;
+ int retval;
+ gpib_file_private_t *file_priv = filep->private_data;
+ int i;
+
+ retval = copy_from_user(&open_dev_cmd, (void *)arg, sizeof(open_dev_cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (mutex_lock_interruptible(&file_priv->descriptors_mutex))
+ return -ERESTARTSYS;
+ for (i = 0; i < GPIB_MAX_NUM_DESCRIPTORS; i++)
+ if (!file_priv->descriptors[i])
+ break;
+ if (i == GPIB_MAX_NUM_DESCRIPTORS) {
+ mutex_unlock(&file_priv->descriptors_mutex);
+ return -ERANGE;
+ }
+ file_priv->descriptors[i] = kmalloc(sizeof(gpib_descriptor_t), GFP_KERNEL);
+ if (!file_priv->descriptors[i]) {
+ mutex_unlock(&file_priv->descriptors_mutex);
+ return -ENOMEM;
+ }
+ init_gpib_descriptor(file_priv->descriptors[i]);
+
+ file_priv->descriptors[i]->pad = open_dev_cmd.pad;
+ file_priv->descriptors[i]->sad = open_dev_cmd.sad;
+ file_priv->descriptors[i]->is_board = open_dev_cmd.is_board;
+ mutex_unlock(&file_priv->descriptors_mutex);
+
+ retval = increment_open_device_count(board, &board->device_list, open_dev_cmd.pad,
+ open_dev_cmd.sad);
+ if (retval < 0)
+ return retval;
+
+ /* clear stuck srq state, since we may be able to find service request on
+ * the new device
+ */
+ atomic_set(&board->stuck_srq, 0);
+
+ open_dev_cmd.handle = i;
+ retval = copy_to_user((void *)arg, &open_dev_cmd, sizeof(open_dev_cmd));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int close_dev_ioctl(struct file *filep, gpib_board_t *board, unsigned long arg)
+{
+ close_dev_ioctl_t cmd;
+ gpib_file_private_t *file_priv = filep->private_data;
+ int retval;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (cmd.handle >= GPIB_MAX_NUM_DESCRIPTORS)
+ return -EINVAL;
+ if (!file_priv->descriptors[cmd.handle])
+ return -EINVAL;
+
+ retval = decrement_open_device_count(board, &board->device_list,
+ file_priv->descriptors[cmd.handle]->pad,
+ file_priv->descriptors[cmd.handle]->sad);
+ if (retval < 0)
+ return retval;
+
+ kfree(file_priv->descriptors[cmd.handle]);
+ file_priv->descriptors[cmd.handle] = NULL;
+
+ return 0;
+}
+
+static int serial_poll_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ serial_poll_ioctl_t serial_cmd;
+ int retval;
+
+ dev_dbg(board->gpib_dev, "pid %i, entering %s()\n", current->pid, __func__);
+
+ retval = copy_from_user(&serial_cmd, (void *)arg, sizeof(serial_cmd));
+ if (retval)
+ return -EFAULT;
+
+ retval = get_serial_poll_byte(board, serial_cmd.pad, serial_cmd.sad, board->usec_timeout,
+ &serial_cmd.status_byte);
+ if (retval < 0)
+ return retval;
+
+ retval = copy_to_user((void *)arg, &serial_cmd, sizeof(serial_cmd));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int wait_ioctl(gpib_file_private_t *file_priv, gpib_board_t *board,
+ unsigned long arg)
+{
+ wait_ioctl_t wait_cmd;
+ int retval;
+ gpib_descriptor_t *desc;
+
+ retval = copy_from_user(&wait_cmd, (void *)arg, sizeof(wait_cmd));
+ if (retval)
+ return -EFAULT;
+
+ desc = handle_to_descriptor(file_priv, wait_cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ retval = ibwait(board, wait_cmd.wait_mask, wait_cmd.clear_mask,
+ wait_cmd.set_mask, &wait_cmd.ibsta, wait_cmd.usec_timeout, desc);
+ if (retval < 0)
+ return retval;
+
+ retval = copy_to_user((void *)arg, &wait_cmd, sizeof(wait_cmd));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int parallel_poll_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ u8 poll_byte;
+ int retval;
+
+ retval = ibrpp(board, &poll_byte);
+ if (retval < 0)
+ return retval;
+
+ retval = copy_to_user((void *)arg, &poll_byte, sizeof(poll_byte));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int online_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ online_ioctl_t online_cmd;
+ int retval;
+ void *init_data = NULL;
+
+ board->config.init_data = NULL;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ retval = copy_from_user(&online_cmd, (void *)arg, sizeof(online_cmd));
+ if (retval)
+ return -EFAULT;
+ if (online_cmd.init_data_length > 0) {
+ board->config.init_data = vmalloc(online_cmd.init_data_length);
+ if (!board->config.init_data)
+ return -ENOMEM;
+ if (WARN_ON_ONCE(sizeof(init_data) > sizeof(online_cmd.init_data_ptr)))
+ return -EFAULT;
+ init_data = (void *)(unsigned long)(online_cmd.init_data_ptr);
+ retval = copy_from_user(board->config.init_data, init_data,
+ online_cmd.init_data_length);
+ if (retval) {
+ vfree(board->config.init_data);
+ return -EFAULT;
+ }
+ board->config.init_data_length = online_cmd.init_data_length;
+ } else {
+ board->config.init_data = NULL;
+ board->config.init_data_length = 0;
+ }
+ if (online_cmd.online)
+ retval = ibonline(board);
+ else
+ retval = iboffline(board);
+ if (board->config.init_data) {
+ vfree(board->config.init_data);
+ board->config.init_data = NULL;
+ board->config.init_data_length = 0;
+ }
+ return retval;
+}
+
+static int remote_enable_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ int enable;
+ int retval;
+
+ retval = copy_from_user(&enable, (void *)arg, sizeof(enable));
+ if (retval)
+ return -EFAULT;
+
+ return ibsre(board, enable);
+}
+
+static int take_control_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ int synchronous;
+ int retval;
+
+ retval = copy_from_user(&synchronous, (void *)arg, sizeof(synchronous));
+ if (retval)
+ return -EFAULT;
+
+ return ibcac(board, synchronous, 1);
+}
+
+static int line_status_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ short lines;
+ int retval;
+
+ retval = iblines(board, &lines);
+ if (retval < 0)
+ return retval;
+
+ retval = copy_to_user((void *)arg, &lines, sizeof(lines));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int pad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg)
+{
+ pad_ioctl_t cmd;
+ int retval;
+ gpib_descriptor_t *desc;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ desc = handle_to_descriptor(file_priv, cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ if (desc->is_board) {
+ retval = ibpad(board, cmd.pad);
+ if (retval < 0)
+ return retval;
+ } else {
+ retval = decrement_open_device_count(board, &board->device_list, desc->pad,
+ desc->sad);
+ if (retval < 0)
+ return retval;
+
+ desc->pad = cmd.pad;
+
+ retval = increment_open_device_count(board, &board->device_list, desc->pad,
+ desc->sad);
+ if (retval < 0)
+ return retval;
+ }
+
+ return 0;
+}
+
+static int sad_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg)
+{
+ sad_ioctl_t cmd;
+ int retval;
+ gpib_descriptor_t *desc;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ desc = handle_to_descriptor(file_priv, cmd.handle);
+ if (!desc)
+ return -EINVAL;
+
+ if (desc->is_board) {
+ retval = ibsad(board, cmd.sad);
+ if (retval < 0)
+ return retval;
+ } else {
+ retval = decrement_open_device_count(board, &board->device_list, desc->pad,
+ desc->sad);
+ if (retval < 0)
+ return retval;
+
+ desc->sad = cmd.sad;
+
+ retval = increment_open_device_count(board, &board->device_list, desc->pad,
+ desc->sad);
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+static int eos_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ eos_ioctl_t eos_cmd;
+ int retval;
+
+ retval = copy_from_user(&eos_cmd, (void *)arg, sizeof(eos_cmd));
+ if (retval)
+ return -EFAULT;
+
+ return ibeos(board, eos_cmd.eos, eos_cmd.eos_flags);
+}
+
+static int request_service_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ u8 status_byte;
+ int retval;
+
+ retval = copy_from_user(&status_byte, (void *)arg, sizeof(status_byte));
+ if (retval)
+ return -EFAULT;
+
+ return ibrsv2(board, status_byte, status_byte & request_service_bit);
+}
+
+static int request_service2_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ request_service2_t request_service2_cmd;
+ int retval;
+
+ retval = copy_from_user(&request_service2_cmd, (void *)arg, sizeof(request_service2_t));
+ if (retval)
+ return -EFAULT;
+
+ return ibrsv2(board, request_service2_cmd.status_byte,
+ request_service2_cmd.new_reason_for_service);
+}
+
+static int iobase_ioctl(gpib_board_config_t *config, unsigned long arg)
+{
+ u64 base_addr;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ retval = copy_from_user(&base_addr, (void *)arg, sizeof(base_addr));
+ if (retval)
+ return -EFAULT;
+
+ if (WARN_ON_ONCE(sizeof(void *) > sizeof(base_addr)))
+ return -EFAULT;
+ config->ibbase = (void *)(unsigned long)(base_addr);
+
+ return 0;
+}
+
+static int irq_ioctl(gpib_board_config_t *config, unsigned long arg)
+{
+ unsigned int irq;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ retval = copy_from_user(&irq, (void *)arg, sizeof(irq));
+ if (retval)
+ return -EFAULT;
+
+ config->ibirq = irq;
+
+ return 0;
+}
+
+static int dma_ioctl(gpib_board_config_t *config, unsigned long arg)
+{
+ unsigned int dma_channel;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ retval = copy_from_user(&dma_channel, (void *)arg, sizeof(dma_channel));
+ if (retval)
+ return -EFAULT;
+
+ config->ibdma = dma_channel;
+
+ return 0;
+}
+
+static int autospoll_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg)
+{
+ autospoll_ioctl_t enable;
+ int retval;
+ gpib_descriptor_t *desc;
+
+ retval = copy_from_user(&enable, (void *)arg, sizeof(enable));
+ if (retval)
+ return -EFAULT;
+
+ desc = handle_to_descriptor(file_priv, 0); /* board handle is 0 */
+
+ if (enable) {
+ if (!desc->autopoll_enabled) {
+ board->autospollers++;
+ desc->autopoll_enabled = 1;
+ }
+ retval = 0;
+ } else {
+ if (desc->autopoll_enabled) {
+ desc->autopoll_enabled = 0;
+ if (board->autospollers > 0) {
+ board->autospollers--;
+ retval = 0;
+ } else {
+ pr_err("gpib: tried to set number of autospollers negative\n");
+ retval = -EINVAL;
+ }
+ } else {
+ pr_err("gpib: autopoll disable requested before enable\n");
+ retval = -EINVAL;
+ }
+ }
+ return retval;
+}
+
+static int mutex_ioctl(gpib_board_t *board, gpib_file_private_t *file_priv,
+ unsigned long arg)
+{
+ int retval, lock_mutex;
+
+ retval = copy_from_user(&lock_mutex, (void *)arg, sizeof(lock_mutex));
+ if (retval)
+ return -EFAULT;
+
+ if (lock_mutex) {
+ retval = mutex_lock_interruptible(&board->user_mutex);
+ if (retval) {
+ pr_warn("gpib: ioctl interrupted while waiting on lock\n");
+ return -ERESTARTSYS;
+ }
+
+ spin_lock(&board->locking_pid_spinlock);
+ board->locking_pid = current->pid;
+ spin_unlock(&board->locking_pid_spinlock);
+
+ atomic_set(&file_priv->holding_mutex, 1);
+
+ dev_dbg(board->gpib_dev, "pid %i, locked board %d mutex\n",
+ current->pid, board->minor);
+ } else {
+ spin_lock(&board->locking_pid_spinlock);
+ if (current->pid != board->locking_pid) {
+ pr_err("gpib: bug! pid %i tried to release mutex held by pid %i\n",
+ current->pid, board->locking_pid);
+ spin_unlock(&board->locking_pid_spinlock);
+ return -EPERM;
+ }
+ board->locking_pid = 0;
+ spin_unlock(&board->locking_pid_spinlock);
+
+ atomic_set(&file_priv->holding_mutex, 0);
+
+ mutex_unlock(&board->user_mutex);
+ dev_dbg(board->gpib_dev, "pid %i, unlocked board %i mutex\n",
+ current->pid, board->minor);
+ }
+ return 0;
+}
+
+static int timeout_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ unsigned int timeout;
+ int retval;
+
+ retval = copy_from_user(&timeout, (void *)arg, sizeof(timeout));
+ if (retval)
+ return -EFAULT;
+
+ board->usec_timeout = timeout;
+ dev_dbg(board->gpib_dev, "pid %i, timeout set to %i usec\n", current->pid, timeout);
+
+ return 0;
+}
+
+static int ppc_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ ppoll_config_ioctl_t cmd;
+ int retval;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (cmd.set_ist) {
+ board->ist = 1;
+ board->interface->parallel_poll_response(board, board->ist);
+ } else if (cmd.clear_ist) {
+ board->ist = 0;
+ board->interface->parallel_poll_response(board, board->ist);
+ }
+
+ if (cmd.config) {
+ retval = ibppc(board, cmd.config);
+ if (retval < 0)
+ return retval;
+ }
+
+ return 0;
+}
+
+static int set_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ local_ppoll_mode_ioctl_t cmd;
+ int retval;
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ if (!board->interface->local_parallel_poll_mode) {
+ pr_warn("gpib: local/remote parallel poll mode not supported by driver.");
+ return -EIO;
+ }
+ board->local_ppoll_mode = cmd != 0;
+ board->interface->local_parallel_poll_mode(board, board->local_ppoll_mode);
+
+ return 0;
+}
+
+static int get_local_ppoll_mode_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ local_ppoll_mode_ioctl_t cmd;
+ int retval;
+
+ cmd = board->local_ppoll_mode;
+ retval = copy_to_user((void *)arg, &cmd, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int query_board_rsv_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ int status;
+ int retval;
+
+ status = board->interface->serial_poll_status(board);
+
+ retval = copy_to_user((void *)arg, &status, sizeof(status));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int board_info_ioctl(const gpib_board_t *board, unsigned long arg)
+{
+ board_info_ioctl_t info;
+ int retval;
+
+ info.pad = board->pad;
+ info.sad = board->sad;
+ info.parallel_poll_configuration = board->parallel_poll_configuration;
+ info.is_system_controller = board->master;
+ if (board->autospollers)
+ info.autopolling = 1;
+ else
+ info.autopolling = 0;
+ info.t1_delay = board->t1_nano_sec;
+ info.ist = board->ist;
+ info.no_7_bit_eos = board->interface->no_7_bit_eos;
+ retval = copy_to_user((void *)arg, &info, sizeof(info));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int interface_clear_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ unsigned int usec_duration;
+ int retval;
+
+ retval = copy_from_user(&usec_duration, (void *)arg, sizeof(usec_duration));
+ if (retval)
+ return -EFAULT;
+
+ return ibsic(board, usec_duration);
+}
+
+static int select_pci_ioctl(gpib_board_config_t *config, unsigned long arg)
+{
+ select_pci_ioctl_t selection;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ retval = copy_from_user(&selection, (void *)arg, sizeof(selection));
+ if (retval)
+ return -EFAULT;
+
+ config->pci_bus = selection.pci_bus;
+ config->pci_slot = selection.pci_slot;
+
+ return 0;
+}
+
+static int select_device_path_ioctl(gpib_board_config_t *config, unsigned long arg)
+{
+ select_device_path_ioctl_t *selection;
+ int retval;
+
+ if (!capable(CAP_SYS_ADMIN))
+ return -EPERM;
+
+ selection = vmalloc(sizeof(select_device_path_ioctl_t));
+ if (!selection)
+ return -ENOMEM;
+
+ retval = copy_from_user(selection, (void *)arg, sizeof(select_device_path_ioctl_t));
+ if (retval) {
+ vfree(selection);
+ return -EFAULT;
+ }
+
+ selection->device_path[sizeof(selection->device_path) - 1] = '\0';
+ kfree(config->device_path);
+ config->device_path = NULL;
+ if (strlen(selection->device_path) > 0)
+ config->device_path = kstrdup(selection->device_path, GFP_KERNEL);
+
+ vfree(selection);
+ return 0;
+}
+
+unsigned int num_gpib_events(const gpib_event_queue_t *queue)
+{
+ return queue->num_events;
+}
+
+static int push_gpib_event_nolock(gpib_board_t *board, short event_type)
+{
+ gpib_event_queue_t *queue = &board->event_queue;
+ struct list_head *head = &queue->event_head;
+ gpib_event_t *event;
+ static const unsigned int max_num_events = 1024;
+ int retval;
+
+ if (num_gpib_events(queue) >= max_num_events) {
+ short lost_event;
+
+ queue->dropped_event = 1;
+ retval = pop_gpib_event_nolock(board, queue, &lost_event);
+ if (retval < 0)
+ return retval;
+ }
+
+ event = kmalloc(sizeof(gpib_event_t), GFP_ATOMIC);
+ if (!event) {
+ queue->dropped_event = 1;
+ pr_err("gpib: failed to allocate memory for event\n");
+ return -ENOMEM;
+ }
+
+ INIT_LIST_HEAD(&event->list);
+ event->event_type = event_type;
+
+ list_add_tail(&event->list, head);
+
+ queue->num_events++;
+
+ dev_dbg(board->gpib_dev, "pushed event %i, %i in queue\n",
+ (int)event_type, num_gpib_events(queue));
+
+ return 0;
+}
+
+// push event onto back of event queue
+int push_gpib_event(gpib_board_t *board, short event_type)
+{
+ unsigned long flags;
+ int retval;
+
+ spin_lock_irqsave(&board->event_queue.lock, flags);
+ retval = push_gpib_event_nolock(board, event_type);
+ spin_unlock_irqrestore(&board->event_queue.lock, flags);
+
+ if (event_type == EventDevTrg)
+ board->status |= DTAS;
+ if (event_type == EventDevClr)
+ board->status |= DCAS;
+
+ return retval;
+}
+EXPORT_SYMBOL(push_gpib_event);
+
+static int pop_gpib_event_nolock(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type)
+{
+ struct list_head *head = &queue->event_head;
+ struct list_head *front = head->next;
+ gpib_event_t *event;
+
+ if (num_gpib_events(queue) == 0) {
+ *event_type = EventNone;
+ return 0;
+ }
+
+ if (front == head)
+ return -EIO;
+
+ if (queue->dropped_event) {
+ queue->dropped_event = 0;
+ return -EPIPE;
+ }
+
+ event = list_entry(front, gpib_event_t, list);
+ *event_type = event->event_type;
+
+ list_del(front);
+ kfree(event);
+
+ queue->num_events--;
+
+ dev_dbg(board->gpib_dev, "popped event %i, %i in queue\n",
+ (int)*event_type, num_gpib_events(queue));
+
+ return 0;
+}
+
+// pop event from front of event queue
+int pop_gpib_event(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type)
+{
+ unsigned long flags;
+ int retval;
+
+ spin_lock_irqsave(&queue->lock, flags);
+ retval = pop_gpib_event_nolock(board, queue, event_type);
+ spin_unlock_irqrestore(&queue->lock, flags);
+ return retval;
+}
+
+static int event_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ event_ioctl_t user_event;
+ int retval;
+ short event;
+
+ retval = pop_gpib_event(board, &board->event_queue, &event);
+ if (retval < 0)
+ return retval;
+
+ user_event = event;
+
+ retval = copy_to_user((void *)arg, &user_event, sizeof(user_event));
+ if (retval)
+ return -EFAULT;
+
+ return 0;
+}
+
+static int request_system_control_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ rsc_ioctl_t request_control;
+ int retval;
+
+ retval = copy_from_user(&request_control, (void *)arg, sizeof(request_control));
+ if (retval)
+ return -EFAULT;
+
+ ibrsc(board, request_control);
+
+ return 0;
+}
+
+static int t1_delay_ioctl(gpib_board_t *board, unsigned long arg)
+{
+ t1_delay_ioctl_t cmd;
+ unsigned int delay;
+ int retval;
+
+ if (!board->interface->t1_delay) {
+ pr_warn("gpib: t1 delay not implemented in driver!\n");
+ return -EIO;
+ }
+
+ retval = copy_from_user(&cmd, (void *)arg, sizeof(cmd));
+ if (retval)
+ return -EFAULT;
+
+ delay = cmd;
+
+ board->t1_nano_sec = board->interface->t1_delay(board, delay);
+
+ return 0;
+}
+
+const struct file_operations ib_fops = {
+owner: THIS_MODULE,
+llseek : NULL,
+unlocked_ioctl : &ibioctl,
+compat_ioctl : &ibioctl,
+open : &ibopen,
+release : &ibclose,
+};
+
+gpib_board_t board_array[GPIB_MAX_NUM_BOARDS];
+
+LIST_HEAD(registered_drivers);
+
+void init_gpib_descriptor(gpib_descriptor_t *desc)
+{
+ desc->pad = 0;
+ desc->sad = -1;
+ desc->is_board = 0;
+ desc->autopoll_enabled = 0;
+ atomic_set(&desc->io_in_progress, 0);
+}
+
+void gpib_register_driver(gpib_interface_t *interface, struct module *provider_module)
+{
+ struct gpib_interface_list_struct *entry;
+
+ entry = kmalloc(sizeof(*entry), GFP_KERNEL);
+ if (!entry)
+ return;
+
+ entry->interface = interface;
+ entry->module = provider_module;
+ list_add(&entry->list, &registered_drivers);
+ pr_info("gpib: registered %s interface\n", interface->name);
+}
+EXPORT_SYMBOL(gpib_register_driver);
+
+void gpib_unregister_driver(gpib_interface_t *interface)
+{
+ int i;
+ struct list_head *list_ptr;
+
+ for (i = 0; i < GPIB_MAX_NUM_BOARDS; i++) {
+ gpib_board_t *board = &board_array[i];
+
+ if (board->interface == interface) {
+ if (board->use_count > 0)
+ pr_warn("gpib: Warning: deregistered interface %s in use\n",
+ interface->name);
+ iboffline(board);
+ board->interface = NULL;
+ }
+ }
+ for (list_ptr = registered_drivers.next; list_ptr != &registered_drivers;) {
+ gpib_interface_list_t *entry;
+
+ entry = list_entry(list_ptr, gpib_interface_list_t, list);
+ list_ptr = list_ptr->next;
+ if (entry->interface == interface) {
+ list_del(&entry->list);
+ kfree(entry);
+ }
+ }
+ pr_info("gpib: unregistered %s interface\n", interface->name);
+}
+EXPORT_SYMBOL(gpib_unregister_driver);
+
+static void init_gpib_board_config(gpib_board_config_t *config)
+{
+ memset(config, 0, sizeof(gpib_board_config_t));
+ config->pci_bus = -1;
+ config->pci_slot = -1;
+}
+
+void init_gpib_board(gpib_board_t *board)
+{
+ board->interface = NULL;
+ board->provider_module = NULL;
+ board->buffer = NULL;
+ board->buffer_length = 0;
+ board->status = 0;
+ init_waitqueue_head(&board->wait);
+ mutex_init(&board->user_mutex);
+ mutex_init(&board->big_gpib_mutex);
+ board->locking_pid = 0;
+ spin_lock_init(&board->locking_pid_spinlock);
+ spin_lock_init(&board->spinlock);
+ timer_setup(&board->timer, NULL, 0);
+ board->dev = NULL;
+ board->gpib_dev = NULL;
+ init_gpib_board_config(&board->config);
+ board->private_data = NULL;
+ board->use_count = 0;
+ INIT_LIST_HEAD(&board->device_list);
+ board->pad = 0;
+ board->sad = -1;
+ board->usec_timeout = 3000000;
+ board->parallel_poll_configuration = 0;
+ board->online = 0;
+ board->autospollers = 0;
+ board->autospoll_task = NULL;
+ init_event_queue(&board->event_queue);
+ board->minor = -1;
+ init_gpib_pseudo_irq(&board->pseudo_irq);
+ board->master = 1;
+ atomic_set(&board->stuck_srq, 0);
+ board->local_ppoll_mode = 0;
+}
+
+int gpib_allocate_board(gpib_board_t *board)
+{
+ if (!board->buffer) {
+ board->buffer_length = 0x4000;
+ board->buffer = vmalloc(board->buffer_length);
+ if (!board->buffer) {
+ board->buffer_length = 0;
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
+void gpib_deallocate_board(gpib_board_t *board)
+{
+ short dummy;
+
+ if (board->buffer) {
+ vfree(board->buffer);
+ board->buffer = NULL;
+ board->buffer_length = 0;
+ }
+ while (num_gpib_events(&board->event_queue))
+ pop_gpib_event(board, &board->event_queue, &dummy);
+}
+
+static void init_board_array(gpib_board_t *board_array, unsigned int length)
+{
+ int i;
+
+ for (i = 0; i < length; i++) {
+ init_gpib_board(&board_array[i]);
+ board_array[i].minor = i;
+ }
+}
+
+void init_gpib_status_queue(gpib_status_queue_t *device)
+{
+ INIT_LIST_HEAD(&device->list);
+ INIT_LIST_HEAD(&device->status_bytes);
+ device->num_status_bytes = 0;
+ device->reference_count = 0;
+ device->dropped_byte = 0;
+}
+
+static struct class *gpib_class;
+
+static int __init gpib_common_init_module(void)
+{
+ int i;
+
+ pr_info("Linux-GPIB core driver\n");
+ init_board_array(board_array, GPIB_MAX_NUM_BOARDS);
+ if (register_chrdev(GPIB_CODE, "gpib", &ib_fops)) {
+ pr_err("gpib: can't get major %d\n", GPIB_CODE);
+ return -EIO;
+ }
+ gpib_class = class_create("gpib_common");
+ if (IS_ERR(gpib_class)) {
+ pr_err("gpib: failed to create gpib class\n");
+ unregister_chrdev(GPIB_CODE, "gpib");
+ return PTR_ERR(gpib_class);
+ }
+ for (i = 0; i < GPIB_MAX_NUM_BOARDS; ++i)
+ board_array[i].gpib_dev = device_create(gpib_class, 0,
+ MKDEV(GPIB_CODE, i), NULL, "gpib%i", i);
+
+ return 0;
+}
+
+static void __exit gpib_common_exit_module(void)
+{
+ int i;
+
+ for (i = 0; i < GPIB_MAX_NUM_BOARDS; ++i)
+ device_destroy(gpib_class, MKDEV(GPIB_CODE, i));
+
+ class_destroy(gpib_class);
+ unregister_chrdev(GPIB_CODE, "gpib");
+}
+
+int gpib_match_device_path(struct device *dev, const char *device_path_in)
+{
+ if (device_path_in) {
+ char *device_path;
+
+ device_path = kobject_get_path(&dev->kobj, GFP_KERNEL);
+ if (!device_path) {
+ dev_err(dev, "kobject_get_path returned NULL.");
+ return 0;
+ }
+ if (strcmp(device_path_in, device_path) != 0) {
+ kfree(device_path);
+ return 0;
+ }
+ kfree(device_path);
+ }
+ return 1;
+}
+EXPORT_SYMBOL(gpib_match_device_path);
+
+struct pci_dev *gpib_pci_get_device(const gpib_board_config_t *config, unsigned int vendor_id,
+ unsigned int device_id, struct pci_dev *from)
+{
+ struct pci_dev *pci_device = from;
+
+ while ((pci_device = pci_get_device(vendor_id, device_id, pci_device))) {
+ if (config->pci_bus >= 0 && config->pci_bus != pci_device->bus->number)
+ continue;
+ if (config->pci_slot >= 0 && config->pci_slot !=
+ PCI_SLOT(pci_device->devfn))
+ continue;
+ if (gpib_match_device_path(&pci_device->dev, config->device_path) == 0)
+ continue;
+ return pci_device;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(gpib_pci_get_device);
+
+struct pci_dev *gpib_pci_get_subsys(const gpib_board_config_t *config, unsigned int vendor_id,
+ unsigned int device_id, unsigned int ss_vendor,
+ unsigned int ss_device,
+ struct pci_dev *from)
+{
+ struct pci_dev *pci_device = from;
+
+ while ((pci_device = pci_get_subsys(vendor_id, device_id,
+ ss_vendor, ss_device, pci_device))) {
+ if (config->pci_bus >= 0 && config->pci_bus != pci_device->bus->number)
+ continue;
+ if (config->pci_slot >= 0 && config->pci_slot !=
+ PCI_SLOT(pci_device->devfn))
+ continue;
+ if (gpib_match_device_path(&pci_device->dev, config->device_path) == 0)
+ continue;
+ return pci_device;
+ }
+ return NULL;
+}
+EXPORT_SYMBOL(gpib_pci_get_subsys);
+
+module_init(gpib_common_init_module);
+module_exit(gpib_common_exit_module);
+
diff --git a/drivers/staging/gpib/common/iblib.c b/drivers/staging/gpib/common/iblib.c
new file mode 100644
index 000000000000..db1911cc1b26
--- /dev/null
+++ b/drivers/staging/gpib/common/iblib.c
@@ -0,0 +1,740 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "ibsys.h"
+#include <linux/delay.h>
+#include <linux/kthread.h>
+#include <linux/vmalloc.h>
+
+/*
+ * IBCAC
+ * Return to the controller active state from the
+ * controller standby state, i.e., turn ATN on. Note
+ * that in order to enter the controller active state
+ * from the controller idle state, ibsic must be called.
+ * If sync is non-zero, attempt to take control synchronously.
+ * If fallback_to_async is non-zero, try to take control asynchronously
+ * if synchronous attempt fails.
+ */
+int ibcac(gpib_board_t *board, int sync, int fallback_to_async)
+{
+ int status = ibstatus(board);
+ int retval;
+
+ if ((status & CIC) == 0) {
+ pr_err("gpib: not CIC during %s()\n", __func__);
+ return -1;
+ }
+
+ if (status & ATN)
+ return 0;
+
+ if (sync && (status & LACS) == 0)
+ /* tcs (take control synchronously) can only possibly work when
+ * controller is listener. Error code also needs to be -ETIMEDOUT
+ * or it will giveout without doing fallback.
+ */
+ retval = -ETIMEDOUT;
+ else
+ retval = board->interface->take_control(board, sync);
+
+ if (retval < 0 && fallback_to_async) {
+ if (sync && retval == -ETIMEDOUT)
+ retval = board->interface->take_control(board, 0);
+ }
+ board->interface->update_status(board, 0);
+
+ return retval;
+}
+
+/* After ATN is asserted, it should cause any connected devices
+ * to start listening for command bytes and leave acceptor idle state.
+ * So if ATN is asserted and neither NDAC or NRFD are asserted,
+ * then there are no devices and ibcmd should error out immediately.
+ * Some gpib hardware sees itself asserting NDAC/NRFD when it
+ * is controller in charge, in which case this check will
+ * do nothing useful (but shouldn't cause any harm either).
+ * Drivers that don't need this check (ni_usb for example) may
+ * set the skip_check_for_command_acceptors flag in their
+ * gpib_interface_struct to avoid useless overhead.
+ */
+static int check_for_command_acceptors(gpib_board_t *board)
+{
+ int lines;
+
+ if (board->interface->skip_check_for_command_acceptors)
+ return 0;
+ if (!board->interface->line_status)
+ return 0;
+
+ udelay(2); // allow time for devices to respond to ATN if it was just asserted
+
+ lines = board->interface->line_status(board);
+ if (lines < 0)
+ return lines;
+
+ if (lines & ValidATN) {
+ if ((lines & BusATN) == 0) {
+ pr_err("gpib: ATN not asserted in %s()?", __func__);
+ return 0;
+ }
+ }
+
+ if ((lines & ValidNRFD) && (lines & ValidNDAC)) {
+ if ((lines & BusNRFD) == 0 && (lines & BusNDAC) == 0)
+ return -ENOTCONN;
+ }
+
+ return 0;
+}
+
+/*
+ * IBCMD
+ * Write cnt command bytes from buf to the GPIB. The
+ * command operation terminates only on I/O complete.
+ *
+ * NOTE:
+ * 1. Prior to beginning the command, the interface is
+ * placed in the controller active state.
+ * 2. Before calling ibcmd for the first time, ibsic
+ * must be called to initialize the GPIB and enable
+ * the interface to leave the controller idle state.
+ */
+int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_written)
+{
+ ssize_t ret = 0;
+ int status;
+
+ *bytes_written = 0;
+
+ status = ibstatus(board);
+
+ if ((status & CIC) == 0) {
+ pr_err("gpib: cannot send command when not controller-in-charge\n");
+ return -EIO;
+ }
+
+ os_start_timer(board, board->usec_timeout);
+
+ ret = ibcac(board, 1, 1);
+ if (ret == 0) {
+ ret = check_for_command_acceptors(board);
+ if (ret == 0)
+ ret = board->interface->command(board, buf, length, bytes_written);
+ }
+
+ os_remove_timer(board);
+
+ if (io_timed_out(board))
+ ret = -ETIMEDOUT;
+
+ return ret;
+}
+
+/*
+ * IBGTS
+ * Go to the controller standby state from the controller
+ * active state, i.e., turn ATN off.
+ */
+
+int ibgts(gpib_board_t *board)
+{
+ int status = ibstatus(board);
+ int retval;
+
+ if ((status & CIC) == 0) {
+ pr_err("gpib: not CIC during %s()\n", __func__);
+ return -1;
+ }
+
+ retval = board->interface->go_to_standby(board); /* go to standby */
+ if (retval < 0)
+ pr_err("gpib: error while going to standby\n");
+
+ board->interface->update_status(board, 0);
+
+ return retval;
+}
+
+static int autospoll_wait_should_wake_up(gpib_board_t *board)
+{
+ int retval;
+
+ mutex_lock(&board->big_gpib_mutex);
+
+ retval = board->master && board->autospollers > 0 &&
+ !atomic_read(&board->stuck_srq) &&
+ test_and_clear_bit(SRQI_NUM, &board->status);
+
+ mutex_unlock(&board->big_gpib_mutex);
+ return retval;
+}
+
+static int autospoll_thread(void *board_void)
+{
+ gpib_board_t *board = board_void;
+ int retval = 0;
+
+ dev_dbg(board->gpib_dev, "entering autospoll thread\n");
+
+ while (1) {
+ wait_event_interruptible(board->wait,
+ kthread_should_stop() ||
+ autospoll_wait_should_wake_up(board));
+ dev_dbg(board->gpib_dev, "autospoll wait satisfied\n");
+ if (kthread_should_stop())
+ break;
+
+ mutex_lock(&board->big_gpib_mutex);
+ /* make sure we are still good after we have lock */
+ if (board->autospollers <= 0 || board->master == 0) {
+ mutex_unlock(&board->big_gpib_mutex);
+ continue;
+ }
+ mutex_unlock(&board->big_gpib_mutex);
+
+ if (try_module_get(board->provider_module)) {
+ retval = autopoll_all_devices(board);
+ module_put(board->provider_module);
+ } else {
+ pr_err("gpib%i: %s: try_module_get() failed!\n", board->minor, __func__);
+ }
+ if (retval <= 0) {
+ pr_err("gpib%i: %s: stuck SRQ\n", board->minor, __func__);
+
+ atomic_set(&board->stuck_srq, 1); // XXX could be better
+ set_bit(SRQI_NUM, &board->status);
+ }
+ }
+ pr_info("gpib%i: exiting autospoll thread\n", board->minor);
+ return retval;
+}
+
+int ibonline(gpib_board_t *board)
+{
+ int retval;
+
+ if (board->online)
+ return -EBUSY;
+ if (!board->interface)
+ return -ENODEV;
+ retval = gpib_allocate_board(board);
+ if (retval < 0)
+ return retval;
+
+ board->dev = NULL;
+ board->local_ppoll_mode = 0;
+ retval = board->interface->attach(board, &board->config);
+ if (retval < 0) {
+ board->interface->detach(board);
+ pr_err("gpib: interface attach failed\n");
+ return retval;
+ }
+ /* nios2nommu on 2.6.11 uclinux kernel has weird problems
+ * with autospoll thread causing huge slowdowns
+ */
+#ifndef CONFIG_NIOS2
+ board->autospoll_task = kthread_run(&autospoll_thread, board,
+ "gpib%d_autospoll_kthread", board->minor);
+ retval = IS_ERR(board->autospoll_task);
+ if (retval) {
+ pr_err("gpib: failed to create autospoll thread\n");
+ board->interface->detach(board);
+ return retval;
+ }
+#endif
+ board->online = 1;
+ dev_dbg(board->gpib_dev, "gpib: board online\n");
+
+ return 0;
+}
+
+/* XXX need to make sure board is generally not in use (grab board lock?) */
+int iboffline(gpib_board_t *board)
+{
+ int retval;
+
+ if (board->online == 0)
+ return 0;
+ if (!board->interface)
+ return -ENODEV;
+
+ if (board->autospoll_task && !IS_ERR(board->autospoll_task)) {
+ retval = kthread_stop(board->autospoll_task);
+ if (retval)
+ pr_err("gpib: kthread_stop returned %i\n", retval);
+ board->autospoll_task = NULL;
+ }
+
+ board->interface->detach(board);
+ gpib_deallocate_board(board);
+ board->online = 0;
+ dev_dbg(board->gpib_dev, "gpib: board offline\n");
+
+ return 0;
+}
+
+/*
+ * IBLINES
+ * Poll the GPIB control lines and return their status in buf.
+ *
+ * LSB (bits 0-7) - VALID lines mask (lines that can be monitored).
+ * Next LSB (bits 8-15) - STATUS lines mask (lines that are currently set).
+ *
+ */
+int iblines(const gpib_board_t *board, short *lines)
+{
+ int retval;
+
+ *lines = 0;
+ if (!board->interface->line_status)
+ return 0;
+ retval = board->interface->line_status(board);
+ if (retval < 0)
+ return retval;
+ *lines = retval;
+ return 0;
+}
+
+/*
+ * IBRD
+ * Read up to 'length' bytes of data from the GPIB into buf. End
+ * on detection of END (EOI and or EOS) and set 'end_flag'.
+ *
+ * NOTE:
+ * 1. The interface is placed in the controller standby
+ * state prior to beginning the read.
+ * 2. Prior to calling ibrd, the intended devices as well
+ * as the interface board itself must be addressed by
+ * calling ibcmd.
+ */
+
+int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t *nbytes)
+{
+ ssize_t ret = 0;
+ int retval;
+ size_t bytes_read;
+
+ *nbytes = 0;
+ *end_flag = 0;
+ if (length == 0) {
+ pr_warn("gpib: %s() called with zero length?\n", __func__);
+ return 0;
+ }
+
+ if (board->master) {
+ retval = ibgts(board);
+ if (retval < 0)
+ return retval;
+ }
+ /* XXX resetting timer here could cause timeouts take longer than they should,
+ * since read_ioctl calls this
+ * function in a loop, there is probably a similar problem with writes/commands
+ */
+ os_start_timer(board, board->usec_timeout);
+
+ do {
+ ret = board->interface->read(board, buf, length - *nbytes, end_flag, &bytes_read);
+ if (ret < 0) {
+ pr_err("gpib read error\n");
+ goto ibrd_out;
+ }
+ buf += bytes_read;
+ *nbytes += bytes_read;
+ if (need_resched())
+ schedule();
+ } while (ret == 0 && *nbytes > 0 && *nbytes < length && *end_flag == 0);
+ibrd_out:
+ os_remove_timer(board);
+
+ return ret;
+}
+
+/*
+ * IBRPP
+ * Conduct a parallel poll and return the byte in buf.
+ *
+ * NOTE:
+ * 1. Prior to conducting the poll the interface is placed
+ * in the controller active state.
+ */
+int ibrpp(gpib_board_t *board, uint8_t *result)
+{
+ int retval = 0;
+
+ os_start_timer(board, board->usec_timeout);
+ retval = ibcac(board, 1, 1);
+ if (retval)
+ return -1;
+
+ if (board->interface->parallel_poll(board, result)) {
+ pr_err("gpib: parallel poll failed\n");
+ retval = -1;
+ }
+ os_remove_timer(board);
+ return retval;
+}
+
+int ibppc(gpib_board_t *board, uint8_t configuration)
+{
+ configuration &= 0x1f;
+ board->interface->parallel_poll_configure(board, configuration);
+ board->parallel_poll_configuration = configuration;
+
+ return 0;
+}
+
+int ibrsv2(gpib_board_t *board, uint8_t status_byte, int new_reason_for_service)
+{
+ int board_status = ibstatus(board);
+ const unsigned int MSS = status_byte & request_service_bit;
+
+ if ((board_status & CIC)) {
+ pr_err("gpib: interface requested service while CIC\n");
+ return -EINVAL;
+ }
+
+ if (MSS == 0 && new_reason_for_service)
+ return -EINVAL;
+
+ if (board->interface->serial_poll_response2) {
+ board->interface->serial_poll_response2(board, status_byte, new_reason_for_service);
+ // fall back on simpler serial_poll_response if the behavior would be the same
+ } else if (board->interface->serial_poll_response &&
+ (MSS == 0 || (MSS && new_reason_for_service))) {
+ board->interface->serial_poll_response(board, status_byte);
+ } else {
+ return -EOPNOTSUPP;
+ }
+
+ return 0;
+}
+
+/*
+ * IBSIC
+ * Send IFC for at least 100 microseconds.
+ *
+ * NOTE:
+ * 1. Ibsic must be called prior to the first call to
+ * ibcmd in order to initialize the bus and enable the
+ * interface to leave the controller idle state.
+ */
+int ibsic(gpib_board_t *board, unsigned int usec_duration)
+{
+ if (board->master == 0) {
+ pr_err("gpib: tried to assert IFC when not system controller\n");
+ return -1;
+ }
+
+ if (usec_duration < 100)
+ usec_duration = 100;
+ if (usec_duration > 1000) {
+ usec_duration = 1000;
+ pr_warn("gpib: warning, shortening long udelay\n");
+ }
+
+ dev_dbg(board->gpib_dev, "sending interface clear\n");
+ board->interface->interface_clear(board, 1);
+ udelay(usec_duration);
+ board->interface->interface_clear(board, 0);
+
+ return 0;
+}
+
+void ibrsc(gpib_board_t *board, int request_control)
+{
+ board->master = request_control != 0;
+ if (!board->interface->request_system_control) {
+ pr_err("gpib: bug! driver does not implement request_system_control()\n");
+ return;
+ }
+ board->interface->request_system_control(board, request_control);
+}
+
+/*
+ * IBSRE
+ * Send REN true if v is non-zero or false if v is zero.
+ */
+int ibsre(gpib_board_t *board, int enable)
+{
+ if (board->master == 0) {
+ pr_err("gpib: tried to set REN when not system controller\n");
+ return -1;
+ }
+
+ board->interface->remote_enable(board, enable); /* set or clear REN */
+ if (!enable)
+ usleep_range(100, 150);
+
+ return 0;
+}
+
+/*
+ * IBPAD
+ * change the GPIB address of the interface board. The address
+ * must be 0 through 30. ibonl resets the address to PAD.
+ */
+int ibpad(gpib_board_t *board, unsigned int addr)
+{
+ if (addr > MAX_GPIB_PRIMARY_ADDRESS) {
+ pr_err("gpib: invalid primary address %u\n", addr);
+ return -1;
+ }
+ board->pad = addr;
+ if (board->online)
+ board->interface->primary_address(board, board->pad);
+ dev_dbg(board->gpib_dev, "set primary addr to %i\n", board->pad);
+ return 0;
+}
+
+/*
+ * IBSAD
+ * change the secondary GPIB address of the interface board.
+ * The address must be 0 through 30, or negative disables. ibonl resets the
+ * address to SAD.
+ */
+int ibsad(gpib_board_t *board, int addr)
+{
+ if (addr > MAX_GPIB_SECONDARY_ADDRESS) {
+ pr_err("gpib: invalid secondary address %i\n", addr);
+ return -1;
+ }
+ board->sad = addr;
+ if (board->online) {
+ if (board->sad >= 0)
+ board->interface->secondary_address(board, board->sad, 1);
+ else
+ board->interface->secondary_address(board, 0, 0);
+ }
+ dev_dbg(board->gpib_dev, "set secondary addr to %i\n", board->sad);
+
+ return 0;
+}
+
+/*
+ * IBEOS
+ * Set the end-of-string modes for I/O operations to v.
+ *
+ */
+int ibeos(gpib_board_t *board, int eos, int eosflags)
+{
+ int retval;
+
+ if (eosflags & ~EOS_MASK) {
+ pr_err("bad EOS modes\n");
+ return -EINVAL;
+ }
+ if (eosflags & REOS) {
+ retval = board->interface->enable_eos(board, eos, eosflags & BIN);
+ } else {
+ board->interface->disable_eos(board);
+ retval = 0;
+ }
+ return retval;
+}
+
+int ibstatus(gpib_board_t *board)
+{
+ return general_ibstatus(board, NULL, 0, 0, NULL);
+}
+
+int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device,
+ int clear_mask, int set_mask, gpib_descriptor_t *desc)
+{
+ int status = 0;
+ short line_status;
+
+ if (board->private_data) {
+ status = board->interface->update_status(board, clear_mask);
+ /* XXX should probably stop having drivers use TIMO bit in
+ * board->status to avoid confusion
+ */
+ status &= ~TIMO;
+ /* get real SRQI status if we can */
+ if (iblines(board, &line_status) == 0) {
+ if ((line_status & ValidSRQ)) {
+ if ((line_status & BusSRQ))
+ status |= SRQI;
+ else
+ status &= ~SRQI;
+ }
+ }
+ }
+ if (device)
+ if (num_status_bytes(device))
+ status |= RQS;
+
+ if (desc) {
+ if (set_mask & CMPL)
+ atomic_set(&desc->io_in_progress, 0);
+ else if (clear_mask & CMPL)
+ atomic_set(&desc->io_in_progress, 1);
+
+ if (atomic_read(&desc->io_in_progress))
+ status &= ~CMPL;
+ else
+ status |= CMPL;
+ }
+ if (num_gpib_events(&board->event_queue))
+ status |= EVENT;
+ else
+ status &= ~EVENT;
+
+ return status;
+}
+
+struct wait_info {
+ gpib_board_t *board;
+ struct timer_list timer;
+ int timed_out;
+ unsigned long usec_timeout;
+};
+
+static void wait_timeout(struct timer_list *t)
+{
+ struct wait_info *winfo = from_timer(winfo, t, timer);
+
+ winfo->timed_out = 1;
+ wake_up_interruptible(&winfo->board->wait);
+}
+
+static void init_wait_info(struct wait_info *winfo)
+{
+ winfo->board = NULL;
+ winfo->timed_out = 0;
+ timer_setup_on_stack(&winfo->timer, wait_timeout, 0);
+}
+
+static int wait_satisfied(struct wait_info *winfo, gpib_status_queue_t *status_queue,
+ int wait_mask, int *status, gpib_descriptor_t *desc)
+{
+ gpib_board_t *board = winfo->board;
+ int temp_status;
+
+ if (mutex_lock_interruptible(&board->big_gpib_mutex))
+ return -ERESTARTSYS;
+
+ temp_status = general_ibstatus(board, status_queue, 0, 0, desc);
+
+ mutex_unlock(&board->big_gpib_mutex);
+
+ if (winfo->timed_out)
+ temp_status |= TIMO;
+ else
+ temp_status &= ~TIMO;
+ if (wait_mask & temp_status) {
+ *status = temp_status;
+ return 1;
+ }
+//XXX does wait for END work?
+ return 0;
+}
+
+/* install timer interrupt handler */
+static void start_wait_timer(struct wait_info *winfo)
+/* Starts the timeout task */
+{
+ winfo->timed_out = 0;
+
+ if (winfo->usec_timeout > 0)
+ mod_timer(&winfo->timer, jiffies + usec_to_jiffies(winfo->usec_timeout));
+}
+
+static void remove_wait_timer(struct wait_info *winfo)
+{
+ del_timer_sync(&winfo->timer);
+ destroy_timer_on_stack(&winfo->timer);
+}
+
+/*
+ * IBWAIT
+ * Check or wait for a GPIB event to occur. The mask argument
+ * is a bit vector corresponding to the status bit vector. It
+ * has a bit set for each condition which can terminate the wait
+ * If the mask is 0 then
+ * no condition is waited for.
+ */
+int ibwait(gpib_board_t *board, int wait_mask, int clear_mask, int set_mask,
+ int *status, unsigned long usec_timeout, gpib_descriptor_t *desc)
+{
+ int retval = 0;
+ gpib_status_queue_t *status_queue;
+ struct wait_info winfo;
+
+ if (desc->is_board)
+ status_queue = NULL;
+ else
+ status_queue = get_gpib_status_queue(board, desc->pad, desc->sad);
+
+ if (wait_mask == 0) {
+ *status = general_ibstatus(board, status_queue, clear_mask, set_mask, desc);
+ return 0;
+ }
+
+ mutex_unlock(&board->big_gpib_mutex);
+
+ init_wait_info(&winfo);
+ winfo.board = board;
+ winfo.usec_timeout = usec_timeout;
+ start_wait_timer(&winfo);
+
+ if (wait_event_interruptible(board->wait, wait_satisfied(&winfo, status_queue,
+ wait_mask, status, desc))) {
+ dev_dbg(board->gpib_dev, "wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ remove_wait_timer(&winfo);
+
+ if (retval)
+ return retval;
+ if (mutex_lock_interruptible(&board->big_gpib_mutex))
+ return -ERESTARTSYS;
+
+ /* make sure we only clear status bits that we are reporting */
+ if (*status & clear_mask || set_mask)
+ general_ibstatus(board, status_queue, *status & clear_mask, set_mask, 0);
+
+ return 0;
+}
+
+/*
+ * IBWRT
+ * Write cnt bytes of data from buf to the GPIB. The write
+ * operation terminates only on I/O complete.
+ *
+ * NOTE:
+ * 1. Prior to beginning the write, the interface is
+ * placed in the controller standby state.
+ * 2. Prior to calling ibwrt, the intended devices as
+ * well as the interface board itself must be
+ * addressed by calling ibcmd.
+ */
+int ibwrt(gpib_board_t *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written)
+{
+ int ret = 0;
+ int retval;
+
+ if (cnt == 0) {
+ pr_warn("gpib: %s() called with zero length?\n", __func__);
+ return 0;
+ }
+
+ if (board->master) {
+ retval = ibgts(board);
+ if (retval < 0)
+ return retval;
+ }
+ os_start_timer(board, board->usec_timeout);
+ ret = board->interface->write(board, buf, cnt, send_eoi, bytes_written);
+
+ if (io_timed_out(board))
+ ret = -ETIMEDOUT;
+
+ os_remove_timer(board);
+
+ return ret;
+}
+
diff --git a/drivers/staging/gpib/common/ibsys.h b/drivers/staging/gpib/common/ibsys.h
new file mode 100644
index 000000000000..da20971e9c7e
--- /dev/null
+++ b/drivers/staging/gpib/common/ibsys.h
@@ -0,0 +1,31 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include "gpibP.h"
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/major.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/timer.h>
+
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <asm/irq.h>
+#include <asm/dma.h>
+
+#define MAX_GPIB_PRIMARY_ADDRESS 30
+#define MAX_GPIB_SECONDARY_ADDRESS 31
+
+int gpib_allocate_board(gpib_board_t *board);
+void gpib_deallocate_board(gpib_board_t *board);
+
+unsigned int num_status_bytes(const gpib_status_queue_t *dev);
+int push_status_byte(gpib_board_t *board, gpib_status_queue_t *device, uint8_t poll_byte);
+int pop_status_byte(gpib_board_t *board, gpib_status_queue_t *device, uint8_t *poll_byte);
+gpib_status_queue_t *get_gpib_status_queue(gpib_board_t *board, unsigned int pad, int sad);
+int get_serial_poll_byte(gpib_board_t *board, unsigned int pad, int sad,
+ unsigned int usec_timeout, uint8_t *poll_byte);
+int autopoll_all_devices(gpib_board_t *board);
diff --git a/drivers/staging/gpib/eastwood/Makefile b/drivers/staging/gpib/eastwood/Makefile
new file mode 100644
index 000000000000..c74056f959d0
--- /dev/null
+++ b/drivers/staging/gpib/eastwood/Makefile
@@ -0,0 +1,3 @@
+
+obj-m += fluke_gpib.o
+
diff --git a/drivers/staging/gpib/eastwood/fluke_gpib.c b/drivers/staging/gpib/eastwood/fluke_gpib.c
new file mode 100644
index 000000000000..3f938ab0c84d
--- /dev/null
+++ b/drivers/staging/gpib/eastwood/fluke_gpib.c
@@ -0,0 +1,1179 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * GPIB Driver for Fluke cda devices. Basically, its a driver for a (bugfixed)
+ * cb7210 connected to channel 0 of a pl330 dma controller.
+ * Author: Frank Mori Hess <fmh6jj@gmail.com>
+ * copyright: (C) 2006, 2010, 2015 Fluke Corporation
+ ***************************************************************************/
+
+#include "fluke_gpib.h"
+
+#include "gpibP.h"
+#include <linux/dma-mapping.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB Driver for Fluke cda devices");
+
+static int fluke_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config);
+static int fluke_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config);
+static void fluke_detach(gpib_board_t *board);
+static int fluke_config_dma(gpib_board_t *board, int output);
+static irqreturn_t fluke_gpib_internal_interrupt(gpib_board_t *board);
+
+static struct platform_device *fluke_gpib_pdev;
+
+static uint8_t fluke_locking_read_byte(struct nec7210_priv *nec_priv, unsigned int register_number)
+{
+ u8 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ retval = fluke_read_byte_nolock(nec_priv, register_number);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+ return retval;
+}
+
+static void fluke_locking_write_byte(struct nec7210_priv *nec_priv, uint8_t byte,
+ unsigned int register_number)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ fluke_write_byte_nolock(nec_priv, byte, register_number);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+}
+
+// wrappers for interface functions
+static int fluke_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+}
+
+static int fluke_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+static int fluke_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+static int fluke_take_control(gpib_board_t *board, int synchronous)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+static int fluke_go_to_standby(gpib_board_t *board)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+static void fluke_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct fluke_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ nec7210_request_system_control(board, nec_priv, request_control);
+}
+
+static void fluke_interface_clear(gpib_board_t *board, int assert)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+static void fluke_remote_enable(gpib_board_t *board, int enable)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+static int fluke_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+static void fluke_disable_eos(gpib_board_t *board)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+static unsigned int fluke_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+static int fluke_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+static int fluke_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+static int fluke_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+static void fluke_parallel_poll_configure(gpib_board_t *board, uint8_t configuration)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration);
+}
+
+static void fluke_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+static void fluke_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+static uint8_t fluke_serial_poll_status(gpib_board_t *board)
+{
+ struct fluke_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+static void fluke_return_to_local(gpib_board_t *board)
+{
+ struct fluke_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ write_byte(nec_priv, AUX_RTL2, AUXMR);
+ udelay(1);
+ write_byte(nec_priv, AUX_RTL, AUXMR);
+}
+
+static int fluke_line_status(const gpib_board_t *board)
+{
+ int status = ValidALL;
+ int bsr_bits;
+ struct fluke_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+
+ bsr_bits = fluke_paged_read_byte(e_priv, BUS_STATUS, BUS_STATUS_PAGE);
+
+ if ((bsr_bits & BSR_REN_BIT) == 0)
+ status |= BusREN;
+ if ((bsr_bits & BSR_IFC_BIT) == 0)
+ status |= BusIFC;
+ if ((bsr_bits & BSR_SRQ_BIT) == 0)
+ status |= BusSRQ;
+ if ((bsr_bits & BSR_EOI_BIT) == 0)
+ status |= BusEOI;
+ if ((bsr_bits & BSR_NRFD_BIT) == 0)
+ status |= BusNRFD;
+ if ((bsr_bits & BSR_NDAC_BIT) == 0)
+ status |= BusNDAC;
+ if ((bsr_bits & BSR_DAV_BIT) == 0)
+ status |= BusDAV;
+ if ((bsr_bits & BSR_ATN_BIT) == 0)
+ status |= BusATN;
+
+ return status;
+}
+
+static unsigned int fluke_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned int retval;
+
+ retval = nec7210_t1_delay(board, nec_priv, nano_sec);
+
+ if (nano_sec <= 350) {
+ write_byte(nec_priv, AUX_HI_SPEED, AUXMR);
+ retval = 350;
+ } else {
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ }
+ return retval;
+}
+
+static int lacs_or_read_ready(gpib_board_t *board)
+{
+ const struct fluke_priv *e_priv = board->private_data;
+ const struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+ int retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = test_bit(LACS_NUM, &board->status) || test_bit(READ_READY_BN, &nec_priv->state);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+/* Wait until it is possible for a read to do something useful. This
+ * is not essential, it only exists to prevent RFD holdoff from being released pointlessly.
+ */
+static int wait_for_read(gpib_board_t *board)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+
+ if (wait_event_interruptible(board->wait,
+ lacs_or_read_ready(board) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ return retval;
+}
+
+/* Check if the SH state machine is in SGNS. We check twice since there is a very small chance
+ * we could be blowing through SGNS from SIDS to SDYS if there is already a
+ * byte available in the handshake state machine. We are interested
+ * in the case where the handshake is stuck in SGNS due to no byte being
+ * available to the chip (and thus we can be confident a dma transfer will
+ * result in at least one byte making it into the chip). This matters
+ * because we want to be confident before sending a "send eoi" auxilary
+ * command that we will be able to also put the associated data byte
+ * in the chip before any potential timeout.
+ */
+static int source_handshake_is_sgns(struct fluke_priv *e_priv)
+{
+ int i;
+
+ for (i = 0; i < 2; ++i) {
+ if ((fluke_paged_read_byte(e_priv, STATE1_REG, STATE1_PAGE) &
+ SOURCE_HANDSHAKE_MASK) != SOURCE_HANDSHAKE_SGNS_BITS) {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+static int source_handshake_is_sids_or_sgns(struct fluke_priv *e_priv)
+{
+ unsigned int source_handshake_bits;
+
+ source_handshake_bits = fluke_paged_read_byte(e_priv, STATE1_REG, STATE1_PAGE) &
+ SOURCE_HANDSHAKE_MASK;
+
+ return (source_handshake_bits == SOURCE_HANDSHAKE_SGNS_BITS) ||
+ (source_handshake_bits == SOURCE_HANDSHAKE_SIDS_BITS);
+}
+
+/* Wait until the gpib chip is ready to accept a data out byte.
+ * If the chip is SGNS it is probably waiting for a a byte to
+ * be written to it.
+ */
+static int wait_for_data_out_ready(gpib_board_t *board)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+// printk("%s: enter\n", __FUNCTION__);
+
+ if (wait_event_interruptible(board->wait,
+ (test_bit(TACS_NUM, &board->status) &&
+ source_handshake_is_sgns(e_priv)) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+// printk("%s: exit, retval=%i\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static int wait_for_sids_or_sgns(gpib_board_t *board)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+// printk("%s: enter\n", __FUNCTION__);
+
+ if (wait_event_interruptible(board->wait,
+ source_handshake_is_sids_or_sgns(e_priv) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+// printk("%s: exit, retval=%i\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static void fluke_dma_callback(void *arg)
+{
+ gpib_board_t *board = arg;
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+// printk("%s: enter\n", __FUNCTION__);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, HR_DOIE | HR_DIIE);
+ wake_up_interruptible(&board->wait);
+
+ fluke_gpib_internal_interrupt(board);
+ clear_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state);
+ clear_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state);
+// printk("%s: exit\n", __FUNCTION__);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+static int fluke_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+ int retval = 0;
+ dma_addr_t address;
+ struct dma_async_tx_descriptor *tx_desc;
+
+ *bytes_written = 0;
+// printk("%s: enter\n", __FUNCTION__);
+ if (WARN_ON_ONCE(length > e_priv->dma_buffer_size))
+ return -EFAULT;
+ dmaengine_terminate_all(e_priv->dma_channel);
+ // write-clear counter
+ writel(0x0, e_priv->write_transfer_counter);
+
+ memcpy(e_priv->dma_buffer, buffer, length);
+ address = dma_map_single(board->dev, e_priv->dma_buffer,
+ length, DMA_TO_DEVICE);
+ /* program dma controller */
+ retval = fluke_config_dma(board, 1);
+ if (retval)
+ goto cleanup;
+
+ tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, address, length, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx_desc) {
+ pr_err("fluke_gpib: failed to allocate dma transmit descriptor\n");
+ retval = -ENOMEM;
+ goto cleanup;
+ }
+ tx_desc->callback = fluke_dma_callback;
+ tx_desc->callback_param = board;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO);
+ dmaengine_submit(tx_desc);
+ dma_async_issue_pending(e_priv->dma_channel);
+
+ clear_bit(WRITE_READY_BN, &nec_priv->state);
+ set_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state);
+
+ // printk("%s: in spin lock\n", __FUNCTION__);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+// printk("%s: waiting for write.\n", __FUNCTION__);
+ // suspend until message is sent
+ if (wait_event_interruptible(board->wait,
+ ((readl(e_priv->write_transfer_counter) &
+ write_transfer_counter_mask) == length) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted!\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state))
+ retval = -EIO;
+ // disable board's dma
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0);
+
+ dmaengine_terminate_all(e_priv->dma_channel);
+ // make sure fluke_dma_callback got called
+ if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state))
+ fluke_dma_callback(board);
+
+ /* if everything went fine, try to wait until last byte is actually
+ * transmitted across gpib (but don't try _too_ hard)
+ */
+ if (retval == 0)
+ retval = wait_for_sids_or_sgns(board);
+
+ *bytes_written = readl(e_priv->write_transfer_counter) & write_transfer_counter_mask;
+ if (WARN_ON_ONCE(*bytes_written > length))
+ return -EFAULT;
+
+cleanup:
+ dma_unmap_single(board->dev, address, length, DMA_TO_DEVICE);
+// printk("%s: exit, retval=%d\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static int fluke_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remainder = length;
+ size_t transfer_size;
+ ssize_t retval = 0;
+ size_t dma_remainder = remainder;
+
+ if (!e_priv->dma_channel) {
+ pr_err("fluke_gpib: No dma channel available, cannot do accel write.");
+ return -ENXIO;
+ }
+
+ *bytes_written = 0;
+ if (length < 1)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+
+ if (send_eoi)
+ --dma_remainder;
+// printk("%s: entering while loop\n", __FUNCTION__);
+
+ while (dma_remainder > 0) {
+ size_t num_bytes;
+
+ retval = wait_for_data_out_ready(board);
+ if (retval < 0)
+ break;
+
+ transfer_size = (e_priv->dma_buffer_size < dma_remainder) ?
+ e_priv->dma_buffer_size : dma_remainder;
+ retval = fluke_dma_write(board, buffer, transfer_size, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ break;
+ dma_remainder -= num_bytes;
+ remainder -= num_bytes;
+ buffer += num_bytes;
+ if (need_resched())
+ schedule();
+ }
+ if (retval < 0)
+ return retval;
+ //handle sending of last byte with eoi
+ if (send_eoi) {
+ size_t num_bytes;
+ // printk("%s: handling last byte\n", __FUNCTION__);
+ if (WARN_ON_ONCE(remainder != 1))
+ return -EFAULT;
+
+ /* wait until we are sure we will be able to write the data byte
+ * into the chip before we send AUX_SEOI. This prevents a timeout
+ * scenerio where we send AUX_SEOI but then timeout without getting
+ * any bytes into the gpib chip. This will result in the first byte
+ * of the next write having a spurious EOI set on the first byte.
+ */
+ retval = wait_for_data_out_ready(board);
+ if (retval < 0)
+ return retval;
+
+ write_byte(nec_priv, AUX_SEOI, AUXMR);
+ retval = fluke_dma_write(board, buffer, remainder, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ remainder -= num_bytes;
+ }
+// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder));
+ return 0;
+}
+
+static int fluke_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie)
+{
+ struct dma_tx_state state;
+ int result;
+
+ result = dmaengine_pause(chan);
+ if (result < 0) {
+ pr_err("fluke_gpib: dma pause failed?\n");
+ return result;
+ }
+ dmaengine_tx_status(chan, cookie, &state);
+ // hardware doesn't support resume, so dont call this
+ // method unless the dma transfer is done.
+ return state.residue;
+}
+
+static int fluke_dma_read(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+ unsigned long flags;
+ int residue;
+ dma_addr_t bus_address;
+ struct dma_async_tx_descriptor *tx_desc;
+ dma_cookie_t dma_cookie;
+ int i;
+ static const int timeout = 10;
+
+ // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__,
+ // (unsigned)bus_address,
+ // (int)length);
+
+ *bytes_read = 0;
+ *end = 0;
+ if (length == 0)
+ return 0;
+
+ bus_address = dma_map_single(board->dev, e_priv->dma_buffer,
+ length, DMA_FROM_DEVICE);
+
+ /* program dma controller */
+ retval = fluke_config_dma(board, 0);
+ if (retval) {
+ dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE);
+ return retval;
+ }
+ tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel,
+ bus_address, length, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx_desc) {
+ pr_err("fluke_gpib: failed to allocate dma transmit descriptor\n");
+ dma_unmap_single(NULL, bus_address, length, DMA_FROM_DEVICE);
+ return -EIO;
+ }
+ tx_desc->callback = fluke_dma_callback;
+ tx_desc->callback_param = board;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ // enable nec7210 dma
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI);
+
+ dma_cookie = dmaengine_submit(tx_desc);
+ dma_async_issue_pending(e_priv->dma_channel);
+
+ set_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state);
+ clear_bit(READ_READY_BN, &nec_priv->state);
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+// printk("waiting for data transfer.\n");
+ // wait for data to transfer
+ if (wait_event_interruptible(board->wait,
+ test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) == 0 ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("fluke: dma read wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+
+ /* If we woke up because of end, wait until the dma transfer has pulled
+ * the data byte associated with the end before we cancel the dma transfer.
+ */
+ if (test_bit(RECEIVED_END_BN, &nec_priv->state)) {
+ for (i = 0; i < timeout; ++i) {
+ if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state) == 0)
+ break;
+ if ((read_byte(nec_priv, ADR0) & DATA_IN_STATUS) == 0)
+ break;
+ usleep_range(10, 15);
+ }
+ if (i == timeout)
+ pr_warn("fluke_gpib: timeout waiting for dma to transfer end data byte.\n");
+ }
+
+ // stop the dma transfer
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ /* delay a little just to make sure any bytes in dma controller's fifo get
+ * written to memory before we disable it
+ */
+ usleep_range(10, 15);
+ residue = fluke_get_dma_residue(e_priv->dma_channel, dma_cookie);
+ if (WARN_ON_ONCE(residue > length || residue < 0))
+ return -EFAULT;
+ *bytes_read += length - residue;
+ dmaengine_terminate_all(e_priv->dma_channel);
+ // make sure fluke_dma_callback got called
+ if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state))
+ fluke_dma_callback(board);
+
+ dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE);
+ memcpy(buffer, e_priv->dma_buffer, *bytes_read);
+
+ /* If we got an end interrupt, figure out if it was
+ * associated with the last byte we dma'd or with a
+ * byte still sitting on the cb7210.
+ */
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (test_bit(READ_READY_BN, &nec_priv->state) == 0) {
+ // There is no byte sitting on the cb7210. If we
+ // saw an end interrupt, we need to deal with it now
+ if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state))
+ *end = 1;
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return retval;
+}
+
+static int fluke_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remain = length;
+ size_t transfer_size;
+ int retval = 0;
+ size_t dma_nbytes;
+
+/* printk("%s: enter, buffer=0x%p, length=%i\n", __FUNCTION__,
+ * buffer, (int)length);
+ * printk("\t dma_buffer=0x%p\n", e_priv->dma_buffer);
+ */
+ *end = 0;
+ *bytes_read = 0;
+
+ smp_mb__before_atomic();
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+ smp_mb__after_atomic();
+
+ retval = wait_for_read(board);
+ if (retval < 0)
+ return retval;
+
+ nec7210_release_rfd_holdoff(board, nec_priv);
+
+// printk("%s: entering while loop\n", __FUNCTION__);
+ while (remain > 0) {
+ transfer_size = (e_priv->dma_buffer_size < remain) ?
+ e_priv->dma_buffer_size : remain;
+ retval = fluke_dma_read(board, buffer, transfer_size, end, &dma_nbytes);
+ remain -= dma_nbytes;
+ buffer += dma_nbytes;
+ *bytes_read += dma_nbytes;
+ if (*end)
+ break;
+ if (retval < 0) {
+// printk("%s: early exit, retval=%i\n", __FUNCTION__, (int)retval);
+ return retval;
+ }
+ if (need_resched())
+ schedule();
+ }
+// printk("%s: exit, retval=%i\n", __FUNCTION__, (int)retval);
+ return retval;
+}
+
+gpib_interface_t fluke_unaccel_interface = {
+name: "fluke_unaccel",
+attach : fluke_attach_holdoff_all,
+detach : fluke_detach,
+read : fluke_read,
+write : fluke_write,
+command : fluke_command,
+take_control : fluke_take_control,
+go_to_standby : fluke_go_to_standby,
+request_system_control : fluke_request_system_control,
+interface_clear : fluke_interface_clear,
+remote_enable : fluke_remote_enable,
+enable_eos : fluke_enable_eos,
+disable_eos : fluke_disable_eos,
+parallel_poll : fluke_parallel_poll,
+parallel_poll_configure : fluke_parallel_poll_configure,
+parallel_poll_response : fluke_parallel_poll_response,
+line_status : fluke_line_status,
+update_status : fluke_update_status,
+primary_address : fluke_primary_address,
+secondary_address : fluke_secondary_address,
+serial_poll_response : fluke_serial_poll_response,
+serial_poll_status : fluke_serial_poll_status,
+t1_delay : fluke_t1_delay,
+return_to_local : fluke_return_to_local,
+};
+
+/* fluke_hybrid uses dma for writes but not for reads. Added
+ * to deal with occasional corruption of bytes seen when doing dma
+ * reads. From looking at the cb7210 vhdl, I believe the corruption
+ * is due to a hardware bug triggered by the cpu reading a cb7210
+ * }
+ * register just as the dma controller is also doing a read.
+ */
+
+gpib_interface_t fluke_hybrid_interface = {
+name: "fluke_hybrid",
+attach : fluke_attach_holdoff_all,
+detach : fluke_detach,
+read : fluke_read,
+write : fluke_accel_write,
+command : fluke_command,
+take_control : fluke_take_control,
+go_to_standby : fluke_go_to_standby,
+request_system_control : fluke_request_system_control,
+interface_clear : fluke_interface_clear,
+remote_enable : fluke_remote_enable,
+enable_eos : fluke_enable_eos,
+disable_eos : fluke_disable_eos,
+parallel_poll : fluke_parallel_poll,
+parallel_poll_configure : fluke_parallel_poll_configure,
+parallel_poll_response : fluke_parallel_poll_response,
+line_status : fluke_line_status,
+update_status : fluke_update_status,
+primary_address : fluke_primary_address,
+secondary_address : fluke_secondary_address,
+serial_poll_response : fluke_serial_poll_response,
+serial_poll_status : fluke_serial_poll_status,
+t1_delay : fluke_t1_delay,
+return_to_local : fluke_return_to_local,
+};
+
+gpib_interface_t fluke_interface = {
+name: "fluke",
+attach : fluke_attach_holdoff_end,
+detach : fluke_detach,
+read : fluke_accel_read,
+write : fluke_accel_write,
+command : fluke_command,
+take_control : fluke_take_control,
+go_to_standby : fluke_go_to_standby,
+request_system_control : fluke_request_system_control,
+interface_clear : fluke_interface_clear,
+remote_enable : fluke_remote_enable,
+enable_eos : fluke_enable_eos,
+disable_eos : fluke_disable_eos,
+parallel_poll : fluke_parallel_poll,
+parallel_poll_configure : fluke_parallel_poll_configure,
+parallel_poll_response : fluke_parallel_poll_response,
+line_status : fluke_line_status,
+update_status : fluke_update_status,
+primary_address : fluke_primary_address,
+secondary_address : fluke_secondary_address,
+serial_poll_response : fluke_serial_poll_response,
+serial_poll_status : fluke_serial_poll_status,
+t1_delay : fluke_t1_delay,
+return_to_local : fluke_return_to_local,
+};
+
+irqreturn_t fluke_gpib_internal_interrupt(gpib_board_t *board)
+{
+ int status0, status1, status2;
+ struct fluke_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ int retval = IRQ_NONE;
+
+ if (read_byte(nec_priv, ADR0) & DATA_IN_STATUS)
+ set_bit(READ_READY_BN, &nec_priv->state);
+
+ status0 = fluke_paged_read_byte(priv, ISR0_IMR0, ISR0_IMR0_PAGE);
+ status1 = read_byte(nec_priv, ISR1);
+ status2 = read_byte(nec_priv, ISR2);
+
+ if (status0 & FLUKE_IFCI_BIT) {
+ push_gpib_event(board, EventIFC);
+ retval = IRQ_HANDLED;
+ }
+
+ if (nec7210_interrupt_have_status(board, nec_priv, status1, status2) == IRQ_HANDLED)
+ retval = IRQ_HANDLED;
+/*
+ * if((status1 & nec_priv->reg_bits[IMR1]) ||
+ * (status2 & (nec_priv->reg_bits[IMR2] & IMR2_ENABLE_INTR_MASK)))
+ * {
+ * printk("fluke: status1 0x%x, status2 0x%x\n", status1, status2);
+ * }
+ */
+
+ if (read_byte(nec_priv, ADR0) & DATA_IN_STATUS) {
+ if (test_bit(RFD_HOLDOFF_BN, &nec_priv->state))
+ set_bit(READ_READY_BN, &nec_priv->state);
+ else
+ clear_bit(READ_READY_BN, &nec_priv->state);
+ }
+
+ if (retval == IRQ_HANDLED)
+ wake_up_interruptible(&board->wait);
+
+ return retval;
+}
+
+static irqreturn_t fluke_gpib_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = fluke_gpib_internal_interrupt(board);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+static int fluke_allocate_private(gpib_board_t *board)
+{
+ struct fluke_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct fluke_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct fluke_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ priv->dma_buffer_size = 0x7ff;
+ priv->dma_buffer = kmalloc(priv->dma_buffer_size, GFP_KERNEL);
+ if (!priv->dma_buffer)
+ return -ENOMEM;
+ return 0;
+}
+
+static void fluke_generic_detach(gpib_board_t *board)
+{
+ if (board->private_data) {
+ struct fluke_priv *e_priv = board->private_data;
+
+ kfree(e_priv->dma_buffer);
+ kfree(board->private_data);
+ board->private_data = NULL;
+ }
+}
+
+// generic part of attach functions shared by all cb7210 boards
+static int fluke_generic_attach(gpib_board_t *board)
+{
+ struct fluke_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ board->status = 0;
+
+ retval = fluke_allocate_private(board);
+ if (retval < 0)
+ return retval;
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+ nec_priv->read_byte = fluke_locking_read_byte;
+ nec_priv->write_byte = fluke_locking_write_byte;
+ nec_priv->offset = fluke_reg_offset;
+ nec_priv->type = CB7210;
+ return 0;
+}
+
+static int fluke_config_dma(gpib_board_t *board, int output)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct dma_slave_config config;
+
+ config.src_maxburst = 1;
+ config.dst_maxburst = 1;
+ config.device_fc = true;
+
+ if (output) {
+ config.direction = DMA_MEM_TO_DEV;
+ config.src_addr = 0;
+ config.dst_addr = e_priv->dma_port_res->start;
+ config.src_addr_width = 1;
+ config.dst_addr_width = 1;
+ } else {
+ config.direction = DMA_DEV_TO_MEM;
+ config.src_addr = e_priv->dma_port_res->start;
+ config.dst_addr = 0;
+ config.src_addr_width = 1;
+ config.dst_addr_width = 1;
+ }
+ return dmaengine_slave_config(e_priv->dma_channel, &config);
+}
+
+static int fluke_init(struct fluke_priv *e_priv, gpib_board_t *board, int handshake_mode)
+{
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+
+ nec7210_board_reset(nec_priv, board);
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ /* set clock register for driving frequency
+ * ICR should be set to clock in megahertz (1-15) and to zero
+ * for clocks faster than 15 MHz (max 20MHz)
+ */
+ write_byte(nec_priv, ICR | 10, AUXMR);
+ nec7210_set_handshake_mode(board, nec_priv, handshake_mode);
+
+ nec7210_board_online(nec_priv, board);
+
+ /* poll so we can detect ATN changes */
+ if (gpib_request_pseudo_irq(board, fluke_gpib_interrupt)) {
+ pr_err("fluke_gpib: failed to allocate pseudo_irq\n");
+ return -EINVAL;
+ }
+
+ fluke_paged_write_byte(e_priv, FLUKE_IFCIE_BIT, ISR0_IMR0, ISR0_IMR0_PAGE);
+ return 0;
+}
+
+/* This function is passed to dma_request_channel() in order to
+ * select the pl330 dma channel which has been hardwired to
+ * the gpib controller.
+ */
+static bool gpib_dma_channel_filter(struct dma_chan *chan, void *filter_param)
+{
+ // select the channel which is wired to the gpib chip
+ return chan->chan_id == 0;
+}
+
+static int fluke_attach_impl(gpib_board_t *board, const gpib_board_config_t *config,
+ unsigned int handshake_mode)
+{
+ struct fluke_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ int retval;
+ int irq;
+ struct resource *res;
+ dma_cap_mask_t dma_cap;
+
+ if (!fluke_gpib_pdev) {
+ pr_err("No gpib platform device was found, attach failed.\n");
+ return -ENODEV;
+ }
+
+ retval = fluke_generic_attach(board);
+ if (retval)
+ return retval;
+
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+ nec_priv->offset = fluke_reg_offset;
+ board->dev = &fluke_gpib_pdev->dev;
+
+ res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for cb7210 gpib\n");
+ return -ENODEV;
+ }
+
+ if (request_mem_region(res->start,
+ resource_size(res),
+ fluke_gpib_pdev->name) == NULL) {
+ dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n");
+ return -ENXIO;
+ }
+ e_priv->gpib_iomem_res = res;
+
+ nec_priv->iobase = ioremap(e_priv->gpib_iomem_res->start,
+ resource_size(e_priv->gpib_iomem_res));
+ pr_info("gpib: iobase %lx remapped to %p, length=%d\n",
+ (unsigned long)e_priv->gpib_iomem_res->start,
+ nec_priv->iobase, (int)resource_size(e_priv->gpib_iomem_res));
+ if (!nec_priv->iobase) {
+ dev_err(&fluke_gpib_pdev->dev, "Could not map I/O memory\n");
+ return -ENOMEM;
+ }
+
+ res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 1);
+ if (!res) {
+ dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for gpib dma port\n");
+ return -ENODEV;
+ }
+ if (request_mem_region(res->start,
+ resource_size(res),
+ fluke_gpib_pdev->name) == NULL) {
+ dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n");
+ return -ENXIO;
+ }
+ e_priv->dma_port_res = res;
+
+ res = platform_get_resource(fluke_gpib_pdev, IORESOURCE_MEM, 2);
+ if (!res) {
+ dev_err(&fluke_gpib_pdev->dev, "Unable to locate mmio resource for write transfer counter\n");
+ return -ENODEV;
+ }
+
+ if (request_mem_region(res->start,
+ resource_size(res),
+ fluke_gpib_pdev->name) == NULL) {
+ dev_err(&fluke_gpib_pdev->dev, "cannot claim registers\n");
+ return -ENXIO;
+ }
+ e_priv->write_transfer_counter_res = res;
+
+ e_priv->write_transfer_counter = ioremap(e_priv->write_transfer_counter_res->start,
+ resource_size(e_priv->write_transfer_counter_res));
+ pr_info("gpib: write transfer counter %lx remapped to %p, length=%d\n",
+ (unsigned long)e_priv->write_transfer_counter_res->start,
+ e_priv->write_transfer_counter,
+ (int)resource_size(e_priv->write_transfer_counter_res));
+ if (!e_priv->write_transfer_counter) {
+ dev_err(&fluke_gpib_pdev->dev, "Could not map I/O memory\n");
+ return -ENOMEM;
+ }
+
+ irq = platform_get_irq(fluke_gpib_pdev, 0);
+ pr_info("gpib: irq %d\n", irq);
+ if (irq < 0) {
+ dev_err(&fluke_gpib_pdev->dev, "fluke_gpib: request for IRQ failed\n");
+ return -EBUSY;
+ }
+ retval = request_irq(irq, fluke_gpib_interrupt, isr_flags, fluke_gpib_pdev->name, board);
+ if (retval) {
+ dev_err(&fluke_gpib_pdev->dev,
+ "cannot register interrupt handler err=%d\n",
+ retval);
+ return retval;
+ }
+ e_priv->irq = irq;
+
+ dma_cap_zero(dma_cap);
+ dma_cap_set(DMA_SLAVE, dma_cap);
+ e_priv->dma_channel = dma_request_channel(dma_cap, gpib_dma_channel_filter, NULL);
+ if (!e_priv->dma_channel) {
+ pr_err("fluke_gpib: failed to allocate a dma channel.\n");
+ // we don't error out here because unaccel interface will still
+ // work without dma
+ }
+
+ return fluke_init(e_priv, board, handshake_mode);
+}
+
+int fluke_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return fluke_attach_impl(board, config, HR_HLDA);
+}
+
+int fluke_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return fluke_attach_impl(board, config, HR_HLDE);
+}
+
+void fluke_detach(gpib_board_t *board)
+{
+ struct fluke_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (e_priv) {
+ if (e_priv->dma_channel)
+ dma_release_channel(e_priv->dma_channel);
+ gpib_free_pseudo_irq(board);
+ nec_priv = &e_priv->nec7210_priv;
+
+ if (nec_priv->iobase) {
+ fluke_paged_write_byte(e_priv, 0, ISR0_IMR0, ISR0_IMR0_PAGE);
+ nec7210_board_reset(nec_priv, board);
+ }
+ if (e_priv->irq)
+ free_irq(e_priv->irq, board);
+ if (e_priv->write_transfer_counter_res) {
+ release_mem_region(e_priv->write_transfer_counter_res->start,
+ resource_size(e_priv->write_transfer_counter_res));
+ }
+ if (e_priv->dma_port_res) {
+ release_mem_region(e_priv->dma_port_res->start,
+ resource_size(e_priv->dma_port_res));
+ }
+ if (e_priv->gpib_iomem_res)
+ release_mem_region(e_priv->gpib_iomem_res->start,
+ resource_size(e_priv->gpib_iomem_res));
+ }
+ fluke_generic_detach(board);
+}
+
+static int fluke_gpib_probe(struct platform_device *pdev)
+{
+ fluke_gpib_pdev = pdev;
+ return 0;
+}
+
+static const struct of_device_id fluke_gpib_of_match[] = {
+ { .compatible = "flk,fgpib-4.0"},
+ { {0} }
+};
+MODULE_DEVICE_TABLE(of, fluke_gpib_of_match);
+
+static struct platform_driver fluke_gpib_platform_driver = {
+ .driver = {
+ .name = "fluke_gpib",
+ .owner = THIS_MODULE,
+ .of_match_table = fluke_gpib_of_match,
+ },
+ .probe = &fluke_gpib_probe
+};
+
+static int __init fluke_init_module(void)
+{
+ int result;
+
+ result = platform_driver_register(&fluke_gpib_platform_driver);
+ if (result) {
+ pr_err("fluke_gpib: platform_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&fluke_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&fluke_hybrid_interface, THIS_MODULE);
+ gpib_register_driver(&fluke_interface, THIS_MODULE);
+
+ pr_info("fluke_gpib\n");
+ return 0;
+}
+
+static void __exit fluke_exit_module(void)
+{
+ gpib_unregister_driver(&fluke_unaccel_interface);
+ gpib_unregister_driver(&fluke_hybrid_interface);
+ gpib_unregister_driver(&fluke_interface);
+ platform_driver_unregister(&fluke_gpib_platform_driver);
+}
+
+module_init(fluke_init_module);
+module_exit(fluke_exit_module);
diff --git a/drivers/staging/gpib/eastwood/fluke_gpib.h b/drivers/staging/gpib/eastwood/fluke_gpib.h
new file mode 100644
index 000000000000..fcbd42f8f9af
--- /dev/null
+++ b/drivers/staging/gpib/eastwood/fluke_gpib.h
@@ -0,0 +1,143 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Author: Frank Mori Hess <fmh6jj@gmail.com>
+ * copyright: (C) 2006, 2010, 2015 Fluke Corporation
+ ***************************************************************************/
+
+#include <linux/compiler.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include "nec7210.h"
+
+struct fluke_priv {
+ struct nec7210_priv nec7210_priv;
+ struct resource *gpib_iomem_res;
+ struct resource *write_transfer_counter_res;
+ struct resource *dma_port_res;
+ int irq;
+ struct dma_chan *dma_channel;
+ u8 *dma_buffer;
+ int dma_buffer_size;
+ void *write_transfer_counter;
+};
+
+// cb7210 specific registers and bits
+enum cb7210_regs {
+ STATE1_REG = 0x4,
+ ISR0_IMR0 = 0x6,
+ BUS_STATUS = 0x7
+};
+
+enum cb7210_page_in {
+ ISR0_IMR0_PAGE = 1,
+ BUS_STATUS_PAGE = 1,
+ STATE1_PAGE = 1
+};
+
+/* IMR0 -- Interrupt Mode Register 0 */
+enum imr0_bits {
+ FLUKE_IFCIE_BIT = 0x8, /* interface clear interrupt */
+};
+
+/* ISR0 -- Interrupt Status Register 0 */
+enum isr0_bits {
+ FLUKE_IFCI_BIT = 0x8, /* interface clear interrupt */
+};
+
+enum state1_bits {
+ SOURCE_HANDSHAKE_SIDS_BITS = 0x0, /* source idle state */
+ SOURCE_HANDSHAKE_SGNS_BITS = 0x1, /* source generate state */
+ SOURCE_HANDSHAKE_SDYS_BITS = 0x2, /* source delay state */
+ SOURCE_HANDSHAKE_STRS_BITS = 0x5, /* source transfer state */
+ SOURCE_HANDSHAKE_MASK = 0x7
+};
+
+// we customized the cb7210 vhdl to give the "data in" status
+// on the unused bit 7 of the address0 register.
+enum cb7210_address0 {
+ DATA_IN_STATUS = 0x80
+};
+
+static inline int cb7210_page_in_bits(unsigned int page)
+{
+ return 0x50 | (page & 0xf);
+}
+
+// don't use without locking nec_priv->register_page_lock
+static inline uint8_t fluke_read_byte_nolock(struct nec7210_priv *nec_priv,
+ int register_num)
+{
+ u8 retval;
+
+ retval = readl(nec_priv->iobase + register_num * nec_priv->offset);
+ return retval;
+}
+
+// don't use without locking nec_priv->register_page_lock
+static inline void fluke_write_byte_nolock(struct nec7210_priv *nec_priv, uint8_t data,
+ int register_num)
+{
+ writel(data, nec_priv->iobase + register_num * nec_priv->offset);
+}
+
+static inline uint8_t fluke_paged_read_byte(struct fluke_priv *e_priv,
+ unsigned int register_num, unsigned int page)
+{
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ u8 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ fluke_write_byte_nolock(nec_priv, cb7210_page_in_bits(page), AUXMR);
+ udelay(1);
+ /* chip auto clears the page after a read */
+ retval = fluke_read_byte_nolock(nec_priv, register_num);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+ return retval;
+}
+
+static inline void fluke_paged_write_byte(struct fluke_priv *e_priv, uint8_t data,
+ unsigned int register_num, unsigned int page)
+{
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&nec_priv->register_page_lock, flags);
+ fluke_write_byte_nolock(nec_priv, cb7210_page_in_bits(page), AUXMR);
+ udelay(1);
+ fluke_write_byte_nolock(nec_priv, data, register_num);
+ spin_unlock_irqrestore(&nec_priv->register_page_lock, flags);
+}
+
+enum bus_status_bits {
+ BSR_ATN_BIT = 0x1,
+ BSR_EOI_BIT = 0x2,
+ BSR_SRQ_BIT = 0x4,
+ BSR_IFC_BIT = 0x8,
+ BSR_REN_BIT = 0x10,
+ BSR_DAV_BIT = 0x20,
+ BSR_NRFD_BIT = 0x40,
+ BSR_NDAC_BIT = 0x80,
+};
+
+enum cb7210_aux_cmds {
+/* AUX_RTL2 is an undocumented aux command which causes cb7210 to assert
+ * (and keep asserted) local rtl message. This is used in conjunction
+ * with the (stupid) cb7210 implementation
+ * of the normal nec7210 AUX_RTL aux command, which
+ * causes the rtl message to toggle between on and off.
+ */
+ AUX_RTL2 = 0xd,
+ AUX_NBAF = 0xe, // new byte available false (also clears seoi)
+ AUX_LO_SPEED = 0x40,
+ AUX_HI_SPEED = 0x41,
+};
+
+enum {
+ fluke_reg_offset = 4,
+ fluke_num_regs = 8,
+ write_transfer_counter_mask = 0x7ff,
+};
diff --git a/drivers/staging/gpib/fmh_gpib/Makefile b/drivers/staging/gpib/fmh_gpib/Makefile
new file mode 100644
index 000000000000..cc4d9e7cd5cd
--- /dev/null
+++ b/drivers/staging/gpib/fmh_gpib/Makefile
@@ -0,0 +1,2 @@
+
+obj-$(CONFIG_GPIB_FMH) += fmh_gpib.o
diff --git a/drivers/staging/gpib/fmh_gpib/fmh_gpib.c b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c
new file mode 100644
index 000000000000..62791db1c34a
--- /dev/null
+++ b/drivers/staging/gpib/fmh_gpib/fmh_gpib.c
@@ -0,0 +1,1725 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * GPIB Driver for fmh_gpib_core, see
+ * https://github.com/fmhess/fmh_gpib_core
+ *
+ * More specifically, it is a driver for the hardware arrangement described by
+ * src/examples/fmh_gpib_top.vhd in the fmh_gpib_core repository.
+ *
+ * Author: Frank Mori Hess <fmh6jj@gmail.com>
+ * Copyright: (C) 2006, 2010, 2015 Fluke Corporation
+ * (C) 2017 Frank Mori Hess
+ ***************************************************************************/
+
+#include "fmh_gpib.h"
+
+#include "gpibP.h"
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+MODULE_LICENSE("GPL");
+
+static irqreturn_t fmh_gpib_interrupt(int irq, void *arg);
+static int fmh_gpib_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config);
+static int fmh_gpib_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config);
+static void fmh_gpib_detach(gpib_board_t *board);
+static int fmh_gpib_pci_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config);
+static int fmh_gpib_pci_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config);
+static void fmh_gpib_pci_detach(gpib_board_t *board);
+static int fmh_gpib_config_dma(gpib_board_t *board, int output);
+static irqreturn_t fmh_gpib_internal_interrupt(gpib_board_t *board);
+static struct platform_driver fmh_gpib_platform_driver;
+static struct pci_driver fmh_gpib_pci_driver;
+
+// wrappers for interface functions
+static int fmh_gpib_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+}
+
+static int fmh_gpib_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+static int fmh_gpib_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+static int fmh_gpib_take_control(gpib_board_t *board, int synchronous)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+static int fmh_gpib_go_to_standby(gpib_board_t *board)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+static void fmh_gpib_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct fmh_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ nec7210_request_system_control(board, nec_priv, request_control);
+}
+
+static void fmh_gpib_interface_clear(gpib_board_t *board, int assert)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+static void fmh_gpib_remote_enable(gpib_board_t *board, int enable)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+static int fmh_gpib_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+static void fmh_gpib_disable_eos(gpib_board_t *board)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+static unsigned int fmh_gpib_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+static int fmh_gpib_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+static int fmh_gpib_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+static int fmh_gpib_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+static void fmh_gpib_parallel_poll_configure(gpib_board_t *board, uint8_t configuration)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, configuration);
+}
+
+static void fmh_gpib_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+static void fmh_gpib_local_parallel_poll_mode(gpib_board_t *board, int local)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ if (local) {
+ write_byte(&priv->nec7210_priv, AUX_I_REG | LOCAL_PPOLL_MODE_BIT, AUXMR);
+ } else {
+ /* For fmh_gpib_core, remote parallel poll config mode is unaffected by the
+ * state of the disable bit of the parallel poll register (unlike the tnt4882).
+ * So, we don't need to worry about that.
+ */
+ write_byte(&priv->nec7210_priv, AUX_I_REG | 0x0, AUXMR);
+ }
+}
+
+static void fmh_gpib_serial_poll_response2(gpib_board_t *board, uint8_t status,
+ int new_reason_for_service)
+{
+ struct fmh_priv *priv = board->private_data;
+ unsigned long flags;
+ const int MSS = status & request_service_bit;
+ const int reqt = MSS && new_reason_for_service;
+ const int reqf = MSS == 0;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (reqt) {
+ priv->nec7210_priv.srq_pending = 1;
+ clear_bit(SPOLL_NUM, &board->status);
+ } else if (reqf) {
+ priv->nec7210_priv.srq_pending = 0;
+ }
+
+ if (reqt) {
+ /* It may seem like a race to issue reqt before updating
+ * the status byte, but it is not. The chip does not
+ * issue the reqt until the SPMR is written to at
+ * a later time.
+ */
+ write_byte(&priv->nec7210_priv, AUX_REQT, AUXMR);
+ } else if (reqf) {
+ write_byte(&priv->nec7210_priv, AUX_REQF, AUXMR);
+ }
+ /* We need to always zero bit 6 of the status byte before writing it to
+ * the SPMR to insure we are using
+ * serial poll mode SP1, and not accidentally triggering mode SP3.
+ */
+ write_byte(&priv->nec7210_priv, status & ~request_service_bit, SPMR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+static uint8_t fmh_gpib_serial_poll_status(gpib_board_t *board)
+{
+ struct fmh_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+static void fmh_gpib_return_to_local(gpib_board_t *board)
+{
+ struct fmh_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ write_byte(nec_priv, AUX_RTL2, AUXMR);
+ udelay(1);
+ write_byte(nec_priv, AUX_RTL, AUXMR);
+}
+
+static int fmh_gpib_line_status(const gpib_board_t *board)
+{
+ int status = ValidALL;
+ int bsr_bits;
+ struct fmh_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+
+ bsr_bits = read_byte(nec_priv, BUS_STATUS_REG);
+
+ if ((bsr_bits & BSR_REN_BIT) == 0)
+ status |= BusREN;
+ if ((bsr_bits & BSR_IFC_BIT) == 0)
+ status |= BusIFC;
+ if ((bsr_bits & BSR_SRQ_BIT) == 0)
+ status |= BusSRQ;
+ if ((bsr_bits & BSR_EOI_BIT) == 0)
+ status |= BusEOI;
+ if ((bsr_bits & BSR_NRFD_BIT) == 0)
+ status |= BusNRFD;
+ if ((bsr_bits & BSR_NDAC_BIT) == 0)
+ status |= BusNDAC;
+ if ((bsr_bits & BSR_DAV_BIT) == 0)
+ status |= BusDAV;
+ if ((bsr_bits & BSR_ATN_BIT) == 0)
+ status |= BusATN;
+
+ return status;
+}
+
+static unsigned int fmh_gpib_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned int retval;
+
+ retval = nec7210_t1_delay(board, nec_priv, nano_sec);
+
+ if (nano_sec <= 350) {
+ write_byte(nec_priv, AUX_HI_SPEED, AUXMR);
+ retval = 350;
+ } else {
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ }
+ return retval;
+}
+
+static int lacs_or_read_ready(gpib_board_t *board)
+{
+ const struct fmh_priv *e_priv = board->private_data;
+ const struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = test_bit(LACS_NUM, &board->status) ||
+ test_bit(READ_READY_BN, &nec_priv->state);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return retval;
+}
+
+static int wait_for_read(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+
+ if (wait_event_interruptible(board->wait,
+ lacs_or_read_ready(board) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ return retval;
+}
+
+static int wait_for_rx_fifo_half_full_or_end(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+
+ if (wait_event_interruptible(board->wait,
+ (fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) &
+ RX_FIFO_HALF_FULL) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ return retval;
+}
+
+/* Wait until the gpib chip is ready to accept a data out byte.
+ */
+static int wait_for_data_out_ready(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+// printk("%s: enter\n", __FUNCTION__);
+
+ if (wait_event_interruptible(board->wait,
+ (test_bit(TACS_NUM, &board->status) &&
+ (read_byte(nec_priv, EXT_STATUS_1_REG) &
+ DATA_OUT_STATUS_BIT)) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+// printk("%s: exit, retval=%i\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static void fmh_gpib_dma_callback(void *arg)
+{
+ gpib_board_t *board = arg;
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+// printk("%s: enter\n", __FUNCTION__);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, HR_DOIE | HR_DIIE);
+ wake_up_interruptible(&board->wait);
+
+ fmh_gpib_internal_interrupt(board);
+
+ clear_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state);
+ clear_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state);
+
+ // printk("%s: exit\n", __FUNCTION__);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+/* returns true when all the bytes of a write have been transferred to
+ * the chip and successfully transferred out over the gpib bus.
+ */
+static int fmh_gpib_all_bytes_are_sent(struct fmh_priv *e_priv)
+{
+ if (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) & fifo_xfer_counter_mask)
+ return 0;
+
+ if ((read_byte(&e_priv->nec7210_priv, EXT_STATUS_1_REG) & DATA_OUT_STATUS_BIT) == 0)
+ return 0;
+
+ return 1;
+}
+
+static int fmh_gpib_dma_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+ int retval = 0;
+ dma_addr_t address;
+ struct dma_async_tx_descriptor *tx_desc;
+
+ *bytes_written = 0;
+// printk("%s: enter\n", __FUNCTION__);
+ if (WARN_ON_ONCE(length > e_priv->dma_buffer_size))
+ return -EFAULT;
+ dmaengine_terminate_all(e_priv->dma_channel);
+ memcpy(e_priv->dma_buffer, buffer, length);
+ address = dma_map_single(board->dev, e_priv->dma_buffer, length, DMA_TO_DEVICE);
+ if (dma_mapping_error(board->dev, address))
+ pr_err("dma mapping error in dma write!\n");
+ /* program dma controller */
+ retval = fmh_gpib_config_dma(board, 1);
+ if (retval)
+ goto cleanup;
+
+ tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, address, length, DMA_MEM_TO_DEV,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx_desc) {
+ pr_err("fmh_gpib_gpib: failed to allocate dma transmit descriptor\n");
+ retval = -ENOMEM;
+ goto cleanup;
+ }
+ tx_desc->callback = fmh_gpib_dma_callback;
+ tx_desc->callback_param = board;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG);
+ fifos_write(e_priv, TX_FIFO_DMA_REQUEST_ENABLE | TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO);
+
+ dmaengine_submit(tx_desc);
+ dma_async_issue_pending(e_priv->dma_channel);
+ clear_bit(WRITE_READY_BN, &nec_priv->state);
+ set_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state);
+// printk("%s: in spin lock\n", __FUNCTION__);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+// printk("%s: waiting for write.\n", __FUNCTION__);
+ // suspend until message is sent
+ if (wait_event_interruptible(board->wait,
+ fmh_gpib_all_bytes_are_sent(e_priv) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted!\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state))
+ retval = -EIO;
+ // disable board's dma
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0);
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+
+ dmaengine_terminate_all(e_priv->dma_channel);
+ // make sure fmh_gpib_dma_callback got called
+ if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &nec_priv->state))
+ fmh_gpib_dma_callback(board);
+
+ *bytes_written = length - (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) &
+ fifo_xfer_counter_mask);
+ if (WARN_ON_ONCE(*bytes_written > length))
+ return -EFAULT;
+ /* printk("length=%i, *bytes_written=%i, residue=%i, retval=%i\n",
+ * length, *bytes_written, get_dma_residue(e_priv->dma_channel), retval);
+ */
+cleanup:
+ dma_unmap_single(board->dev, address, length, DMA_TO_DEVICE);
+// printk("%s: exit, retval=%d\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static int fmh_gpib_accel_write(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int send_eoi, size_t *bytes_written)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remainder = length;
+ size_t transfer_size;
+ ssize_t retval = 0;
+ size_t dma_remainder = remainder;
+
+ if (!e_priv->dma_channel) {
+ pr_err("fmh_gpib_gpib: No dma channel available, cannot do accel write.");
+ return -ENXIO;
+ }
+
+ *bytes_written = 0;
+ if (length < 1)
+ return 0;
+
+ smp_mb__before_atomic();
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+ smp_mb__after_atomic();
+
+ if (send_eoi)
+ --dma_remainder;
+// printk("%s: entering while loop\n", __FUNCTION__);
+
+ while (dma_remainder > 0) {
+ size_t num_bytes;
+
+ retval = wait_for_data_out_ready(board);
+ if (retval < 0)
+ break;
+
+ transfer_size = (e_priv->dma_buffer_size < dma_remainder) ?
+ e_priv->dma_buffer_size : dma_remainder;
+ retval = fmh_gpib_dma_write(board, buffer, transfer_size, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ break;
+ dma_remainder -= num_bytes;
+ remainder -= num_bytes;
+ buffer += num_bytes;
+ if (need_resched())
+ schedule();
+ }
+ if (retval < 0)
+ return retval;
+ //handle sending of last byte with eoi
+ if (send_eoi) {
+ size_t num_bytes;
+ // printk("%s: handling last byte\n", __FUNCTION__);
+ if (WARN_ON_ONCE(remainder != 1))
+ return -EFAULT;
+
+ /* wait until we are sure we will be able to write the data byte
+ * into the chip before we send AUX_SEOI. This prevents a timeout
+ * scenario where we send AUX_SEOI but then timeout without getting
+ * any bytes into the gpib chip. This will result in the first byte
+ * of the next write having a spurious EOI set on the first byte.
+ */
+ retval = wait_for_data_out_ready(board);
+ if (retval < 0)
+ return retval;
+
+ write_byte(nec_priv, AUX_SEOI, AUXMR);
+ retval = fmh_gpib_dma_write(board, buffer, remainder, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ remainder -= num_bytes;
+ }
+// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder));
+ return 0;
+}
+
+static int fmh_gpib_get_dma_residue(struct dma_chan *chan, dma_cookie_t cookie)
+{
+ struct dma_tx_state state;
+ int result;
+
+ result = dmaengine_pause(chan);
+ if (result < 0) {
+ pr_err("fmh_gpib_gpib: dma pause failed?\n");
+ return result;
+ }
+ dmaengine_tx_status(chan, cookie, &state);
+ // dma330 hardware doesn't support resume, so dont call this
+ // method unless the dma transfer is done.
+ return state.residue;
+}
+
+static int wait_for_tx_fifo_half_empty(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+// printk("%s: enter\n", __FUNCTION__);
+
+ if (wait_event_interruptible(board->wait,
+ (test_bit(TACS_NUM, &board->status) &&
+ (fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) &
+ TX_FIFO_HALF_EMPTY)) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+// printk("%s: exit, retval=%i\n", __FUNCTION__, retval);
+ return retval;
+}
+
+/* supports writing a chunk of data whose length must fit into the hardware'd xfer counter,
+ * called in a loop by fmh_gpib_fifo_write()
+ */
+static int fmh_gpib_fifo_write_countable(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int send_eoi, size_t *bytes_written)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+ unsigned int remainder;
+
+ *bytes_written = 0;
+// printk("%s: enter\n", __FUNCTION__);
+ if (WARN_ON_ONCE(length > fifo_xfer_counter_mask))
+ return -EFAULT;
+
+ fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG);
+ fifos_write(e_priv, TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO);
+
+ remainder = length;
+ while (remainder > 0) {
+ int i;
+
+ fifos_write(e_priv, TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE, FIFO_CONTROL_STATUS_REG);
+ retval = wait_for_tx_fifo_half_empty(board);
+ if (retval < 0)
+ goto cleanup;
+
+ for (i = 0; i < fmh_gpib_half_fifo_size(e_priv) && remainder > 0; ++i) {
+ unsigned int data_value = *buffer;
+
+ if (send_eoi && remainder == 1)
+ data_value |= FIFO_DATA_EOI_FLAG;
+ fifos_write(e_priv, data_value, FIFO_DATA_REG);
+ ++buffer;
+ --remainder;
+ }
+ }
+
+ // suspend until last byte is sent
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, HR_DOIE);
+ if (wait_event_interruptible(board->wait,
+ fmh_gpib_all_bytes_are_sent(e_priv) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted!\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state))
+ retval = -EIO;
+
+cleanup:
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0);
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+
+ *bytes_written = length - (fifos_read(e_priv, FIFO_XFER_COUNTER_REG) &
+ fifo_xfer_counter_mask);
+ if (WARN_ON_ONCE(*bytes_written > length))
+ return -EFAULT;
+ /* printk("length=%i, *bytes_written=%i, residue=%i, retval=%i\n",
+ * length, *bytes_written, get_dma_residue(e_priv->dma_channel), retval);
+ */
+
+// printk("%s: exit, retval=%d\n", __FUNCTION__, retval);
+ return retval;
+}
+
+static int fmh_gpib_fifo_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remainder = length;
+ size_t transfer_size;
+ ssize_t retval = 0;
+
+ *bytes_written = 0;
+ if (length < 1)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+
+// printk("%s: entering while loop\n", __FUNCTION__);
+
+ while (remainder > 0) {
+ size_t num_bytes;
+ int last_pass;
+
+ retval = wait_for_data_out_ready(board);
+ if (retval < 0)
+ break;
+
+ if (fifo_xfer_counter_mask < remainder) {
+ // round transfer size to a multiple of half fifo size
+ transfer_size = (fifo_xfer_counter_mask /
+ fmh_gpib_half_fifo_size(e_priv)) *
+ fmh_gpib_half_fifo_size(e_priv);
+ last_pass = 0;
+ } else {
+ transfer_size = remainder;
+ last_pass = 1;
+ }
+ retval = fmh_gpib_fifo_write_countable(board, buffer, transfer_size,
+ last_pass && send_eoi, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ break;
+ remainder -= num_bytes;
+ buffer += num_bytes;
+ if (need_resched())
+ schedule();
+ }
+// printk("%s: bytes send=%i\n", __FUNCTION__, (int)(length - remainder));
+ return retval;
+}
+
+static int fmh_gpib_dma_read(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+ unsigned long flags;
+ int residue;
+ int wait_retval;
+ dma_addr_t bus_address;
+ struct dma_async_tx_descriptor *tx_desc;
+ dma_cookie_t dma_cookie;
+
+ // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__,
+ //(unsigned)bus_address,
+// (int)length);
+
+ *bytes_read = 0;
+ *end = 0;
+ if (length == 0)
+ return 0;
+
+ bus_address = dma_map_single(board->dev, e_priv->dma_buffer,
+ length, DMA_FROM_DEVICE);
+ if (dma_mapping_error(board->dev, bus_address))
+ pr_err("dma mapping error in dma read!");
+
+ /* program dma controller */
+ retval = fmh_gpib_config_dma(board, 0);
+ if (retval) {
+ dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE);
+ return retval;
+ }
+ tx_desc = dmaengine_prep_slave_single(e_priv->dma_channel, bus_address,
+ length, DMA_DEV_TO_MEM,
+ DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ if (!tx_desc) {
+ pr_err("fmh_gpib_gpib: failed to allocate dma transmit descriptor\n");
+ dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE);
+ return -EIO;
+ }
+ tx_desc->callback = fmh_gpib_dma_callback;
+ tx_desc->callback_param = board;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ // enable nec7210 dma
+ fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG);
+ fifos_write(e_priv, RX_FIFO_DMA_REQUEST_ENABLE | RX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI);
+
+ dma_cookie = dmaengine_submit(tx_desc);
+ dma_async_issue_pending(e_priv->dma_channel);
+
+ set_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state);
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+// printk("waiting for data transfer.\n");
+ // wait for data to transfer
+ wait_retval = wait_event_interruptible(board->wait,
+ test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state)
+ == 0 ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ if (wait_retval) {
+ pr_warn("fmh_gpib: dma read wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ retval = -EINTR;
+ // stop the dma transfer
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+ // give time for pl330 to transfer any in-flight data, since
+ // pl330 will throw it away when dmaengine_pause is called.
+ usleep_range(10, 15);
+ residue = fmh_gpib_get_dma_residue(e_priv->dma_channel, dma_cookie);
+ if (WARN_ON_ONCE(residue > length || residue < 0))
+ return -EFAULT;
+ *bytes_read += length - residue;
+ dmaengine_terminate_all(e_priv->dma_channel);
+ // make sure fmh_gpib_dma_callback got called
+ if (test_bit(DMA_READ_IN_PROGRESS_BN, &nec_priv->state))
+ fmh_gpib_dma_callback(board);
+
+ dma_unmap_single(board->dev, bus_address, length, DMA_FROM_DEVICE);
+ memcpy(buffer, e_priv->dma_buffer, *bytes_read);
+
+ /* Manually read any dregs out of fifo. */
+ while ((fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & RX_FIFO_EMPTY) == 0) {
+ if ((*bytes_read) >= length) {
+ dev_err(board->dev, "unexpected extra bytes in rx fifo, discarding! bytes_read=%d length=%d residue=%d\n",
+ (int)(*bytes_read), (int)length, (int)residue);
+ break;
+ }
+ buffer[(*bytes_read)++] = fifos_read(e_priv, FIFO_DATA_REG) & fifo_data_mask;
+ }
+
+ /* If we got an end interrupt, figure out if it was
+ * associated with the last byte we dma'd or with a
+ * byte still sitting on the cb7210.
+ */
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (*bytes_read > 0 && test_bit(READ_READY_BN, &nec_priv->state) == 0) {
+ // If there is no byte sitting on the cb7210 and we
+ // saw an end, we need to deal with it now
+ if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state))
+ *end = 1;
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+// printk("\tbytes_read=%i, residue=%i, end=%i, retval=%i, wait_retval=%i\n",
+// *bytes_read, residue, *end, retval, wait_retval);
+
+ return retval;
+}
+
+static void fmh_gpib_release_rfd_holdoff(gpib_board_t *board, struct fmh_priv *e_priv)
+{
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned int ext_status_1;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ ext_status_1 = read_byte(nec_priv, EXT_STATUS_1_REG);
+
+ /* if there is an end byte sitting on the chip, don't release
+ * holdoff. We want it left set after we read out the end
+ * byte.
+ */
+ if ((ext_status_1 & (DATA_IN_STATUS_BIT | END_STATUS_BIT)) !=
+ (DATA_IN_STATUS_BIT | END_STATUS_BIT)) {
+ if (ext_status_1 & RFD_HOLDOFF_STATUS_BIT)
+ write_byte(nec_priv, AUX_FH, AUXMR);
+
+ /* Check if an end byte raced in before we executed the AUX_FH command.
+ * If it did, we want to make sure the rfd holdoff is in effect. The end
+ * byte can arrive since
+ * AUX_RFD_HOLDOFF_ASAP doesn't immediately force the acceptor handshake
+ * to leave ACRS.
+ */
+ if ((read_byte(nec_priv, EXT_STATUS_1_REG) &
+ (RFD_HOLDOFF_STATUS_BIT | DATA_IN_STATUS_BIT | END_STATUS_BIT)) ==
+ (DATA_IN_STATUS_BIT | END_STATUS_BIT)) {
+ write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR);
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ } else {
+ clear_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ }
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+static int fmh_gpib_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remain = length;
+ size_t transfer_size;
+ int retval = 0;
+ size_t dma_nbytes;
+ unsigned long flags;
+
+ smp_mb__before_atomic();
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+ smp_mb__after_atomic();
+ *end = 0;
+ *bytes_read = 0;
+
+ retval = wait_for_read(board);
+ if (retval < 0)
+ return retval;
+
+ fmh_gpib_release_rfd_holdoff(board, e_priv);
+ while (remain > 0) {
+ transfer_size = (e_priv->dma_buffer_size < remain) ?
+ e_priv->dma_buffer_size : remain;
+ retval = fmh_gpib_dma_read(board, buffer, transfer_size, end, &dma_nbytes);
+ remain -= dma_nbytes;
+ buffer += dma_nbytes;
+ *bytes_read += dma_nbytes;
+ if (*end)
+ break;
+ if (retval < 0)
+ break;
+ if (need_resched())
+ schedule();
+ }
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (test_bit(RFD_HOLDOFF_BN, &nec_priv->state) == 0) {
+ write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR);
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return retval;
+}
+
+/* Read a chunk of data whose length is within the limits of the hardware's
+ * xfer counter. Called in a loop from fmh_gpib_fifo_read().
+ */
+static int fmh_gpib_fifo_read_countable(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ int retval = 0;
+
+ // printk("%s: enter, bus_address=0x%x, length=%i\n", __FUNCTION__,
+ // (unsigned)bus_address,
+// (int)length);
+
+ *bytes_read = 0;
+ *end = 0;
+ if (length == 0)
+ return 0;
+
+ fifos_write(e_priv, length & fifo_xfer_counter_mask, FIFO_XFER_COUNTER_REG);
+ fifos_write(e_priv, RX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG);
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI);
+
+ while (*bytes_read < length && *end == 0) {
+ int i;
+
+ fifos_write(e_priv, RX_FIFO_HALF_FULL_INTERRUPT_ENABLE, FIFO_CONTROL_STATUS_REG);
+ retval = wait_for_rx_fifo_half_full_or_end(board);
+ if (retval < 0)
+ goto cleanup;
+
+ for (i = 0; i < fmh_gpib_half_fifo_size(e_priv) && *end == 0; ++i) {
+ unsigned int data_value;
+
+ data_value = fifos_read(e_priv, FIFO_DATA_REG);
+ buffer[(*bytes_read)++] = data_value & fifo_data_mask;
+ if (data_value & FIFO_DATA_EOI_FLAG)
+ *end = 1;
+ }
+ }
+
+cleanup:
+ // stop the transfer
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+
+ /* Manually read any dregs out of fifo. */
+ while ((fifos_read(e_priv, FIFO_CONTROL_STATUS_REG) & RX_FIFO_EMPTY) == 0) {
+ unsigned int data_value;
+
+ if ((*bytes_read) >= length) {
+ dev_err(board->dev, "unexpected extra bytes in rx fifo, discarding! bytes_read=%d length=%d\n",
+ (int)(*bytes_read), (int)length);
+ break;
+ }
+ data_value = fifos_read(e_priv, FIFO_DATA_REG);
+ buffer[(*bytes_read)++] = data_value & fifo_data_mask;
+ if (data_value & FIFO_DATA_EOI_FLAG)
+ *end = 1;
+ }
+
+// printk("\tbytes_read=%i, end=%i, retval=%i, wait_retval=%i\n",
+// *bytes_read, *end, retval, wait_retval);
+
+ return retval;
+}
+
+static int fmh_gpib_fifo_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ size_t remain = length;
+ size_t transfer_size;
+ int retval = 0;
+ size_t nbytes;
+ unsigned long flags;
+
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state); // XXX FIXME
+ *end = 0;
+ *bytes_read = 0;
+
+ /* Do a little prep with data in interrupt so that following wait_for_read()
+ * will wake up if a data byte is received.
+ */
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DIIE, HR_DIIE);
+ fmh_gpib_interrupt(0, board);
+
+ retval = wait_for_read(board);
+ if (retval < 0)
+ return retval;
+
+ fmh_gpib_release_rfd_holdoff(board, e_priv);
+ while (remain > 0) {
+ if (fifo_xfer_counter_mask < remain) {
+ // round transfer size to a multiple of half fifo size
+ transfer_size = (fifo_xfer_counter_mask /
+ fmh_gpib_half_fifo_size(e_priv)) *
+ fmh_gpib_half_fifo_size(e_priv);
+ } else {
+ transfer_size = remain;
+ }
+ retval = fmh_gpib_fifo_read_countable(board, buffer, transfer_size, end, &nbytes);
+ remain -= nbytes;
+ buffer += nbytes;
+ *bytes_read += nbytes;
+ if (*end)
+ break;
+ if (retval < 0)
+ break;
+ if (need_resched())
+ schedule();
+ }
+
+ if (*end == 0) {
+ spin_lock_irqsave(&board->spinlock, flags);
+ write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR);
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ }
+
+ return retval;
+}
+
+gpib_interface_t fmh_gpib_unaccel_interface = {
+name: "fmh_gpib_unaccel",
+attach : fmh_gpib_attach_holdoff_all,
+detach : fmh_gpib_detach,
+read : fmh_gpib_read,
+write : fmh_gpib_write,
+command : fmh_gpib_command,
+take_control : fmh_gpib_take_control,
+go_to_standby : fmh_gpib_go_to_standby,
+request_system_control : fmh_gpib_request_system_control,
+interface_clear : fmh_gpib_interface_clear,
+remote_enable : fmh_gpib_remote_enable,
+enable_eos : fmh_gpib_enable_eos,
+disable_eos : fmh_gpib_disable_eos,
+parallel_poll : fmh_gpib_parallel_poll,
+parallel_poll_configure : fmh_gpib_parallel_poll_configure,
+parallel_poll_response : fmh_gpib_parallel_poll_response,
+local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode,
+line_status : fmh_gpib_line_status,
+update_status : fmh_gpib_update_status,
+primary_address : fmh_gpib_primary_address,
+secondary_address : fmh_gpib_secondary_address,
+serial_poll_response2 : fmh_gpib_serial_poll_response2,
+serial_poll_status : fmh_gpib_serial_poll_status,
+t1_delay : fmh_gpib_t1_delay,
+return_to_local : fmh_gpib_return_to_local,
+};
+
+gpib_interface_t fmh_gpib_interface = {
+name: "fmh_gpib",
+attach : fmh_gpib_attach_holdoff_end,
+detach : fmh_gpib_detach,
+read : fmh_gpib_accel_read,
+write : fmh_gpib_accel_write,
+command : fmh_gpib_command,
+take_control : fmh_gpib_take_control,
+go_to_standby : fmh_gpib_go_to_standby,
+request_system_control : fmh_gpib_request_system_control,
+interface_clear : fmh_gpib_interface_clear,
+remote_enable : fmh_gpib_remote_enable,
+enable_eos : fmh_gpib_enable_eos,
+disable_eos : fmh_gpib_disable_eos,
+parallel_poll : fmh_gpib_parallel_poll,
+parallel_poll_configure : fmh_gpib_parallel_poll_configure,
+parallel_poll_response : fmh_gpib_parallel_poll_response,
+local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode,
+line_status : fmh_gpib_line_status,
+update_status : fmh_gpib_update_status,
+primary_address : fmh_gpib_primary_address,
+secondary_address : fmh_gpib_secondary_address,
+serial_poll_response2 : fmh_gpib_serial_poll_response2,
+serial_poll_status : fmh_gpib_serial_poll_status,
+t1_delay : fmh_gpib_t1_delay,
+return_to_local : fmh_gpib_return_to_local,
+};
+
+gpib_interface_t fmh_gpib_pci_interface = {
+name: "fmh_gpib_pci",
+attach : fmh_gpib_pci_attach_holdoff_end,
+detach : fmh_gpib_pci_detach,
+read : fmh_gpib_fifo_read,
+write : fmh_gpib_fifo_write,
+command : fmh_gpib_command,
+take_control : fmh_gpib_take_control,
+go_to_standby : fmh_gpib_go_to_standby,
+request_system_control : fmh_gpib_request_system_control,
+interface_clear : fmh_gpib_interface_clear,
+remote_enable : fmh_gpib_remote_enable,
+enable_eos : fmh_gpib_enable_eos,
+disable_eos : fmh_gpib_disable_eos,
+parallel_poll : fmh_gpib_parallel_poll,
+parallel_poll_configure : fmh_gpib_parallel_poll_configure,
+parallel_poll_response : fmh_gpib_parallel_poll_response,
+local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode,
+line_status : fmh_gpib_line_status,
+update_status : fmh_gpib_update_status,
+primary_address : fmh_gpib_primary_address,
+secondary_address : fmh_gpib_secondary_address,
+serial_poll_response2 : fmh_gpib_serial_poll_response2,
+serial_poll_status : fmh_gpib_serial_poll_status,
+t1_delay : fmh_gpib_t1_delay,
+return_to_local : fmh_gpib_return_to_local,
+};
+
+gpib_interface_t fmh_gpib_pci_unaccel_interface = {
+name: "fmh_gpib_pci_unaccel",
+attach : fmh_gpib_pci_attach_holdoff_all,
+detach : fmh_gpib_pci_detach,
+read : fmh_gpib_read,
+write : fmh_gpib_write,
+command : fmh_gpib_command,
+take_control : fmh_gpib_take_control,
+go_to_standby : fmh_gpib_go_to_standby,
+request_system_control : fmh_gpib_request_system_control,
+interface_clear : fmh_gpib_interface_clear,
+remote_enable : fmh_gpib_remote_enable,
+enable_eos : fmh_gpib_enable_eos,
+disable_eos : fmh_gpib_disable_eos,
+parallel_poll : fmh_gpib_parallel_poll,
+parallel_poll_configure : fmh_gpib_parallel_poll_configure,
+parallel_poll_response : fmh_gpib_parallel_poll_response,
+local_parallel_poll_mode : fmh_gpib_local_parallel_poll_mode,
+line_status : fmh_gpib_line_status,
+update_status : fmh_gpib_update_status,
+primary_address : fmh_gpib_primary_address,
+secondary_address : fmh_gpib_secondary_address,
+serial_poll_response2 : fmh_gpib_serial_poll_response2,
+serial_poll_status : fmh_gpib_serial_poll_status,
+t1_delay : fmh_gpib_t1_delay,
+return_to_local : fmh_gpib_return_to_local,
+};
+
+irqreturn_t fmh_gpib_internal_interrupt(gpib_board_t *board)
+{
+ unsigned int status0, status1, status2, ext_status_1, fifo_status;
+ struct fmh_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ int retval = IRQ_NONE;
+
+ status0 = read_byte(nec_priv, ISR0_IMR0_REG);
+ status1 = read_byte(nec_priv, ISR1);
+ status2 = read_byte(nec_priv, ISR2);
+ fifo_status = fifos_read(priv, FIFO_CONTROL_STATUS_REG);
+
+ if (status0 & IFC_INTERRUPT_BIT) {
+ push_gpib_event(board, EventIFC);
+ retval = IRQ_HANDLED;
+ }
+
+ if (nec7210_interrupt_have_status(board, nec_priv, status1, status2) == IRQ_HANDLED)
+ retval = IRQ_HANDLED;
+
+ ext_status_1 = read_byte(nec_priv, EXT_STATUS_1_REG);
+
+ if (ext_status_1 & DATA_IN_STATUS_BIT)
+ set_bit(READ_READY_BN, &nec_priv->state);
+ else
+ clear_bit(READ_READY_BN, &nec_priv->state);
+
+ if (ext_status_1 & DATA_OUT_STATUS_BIT)
+ set_bit(WRITE_READY_BN, &nec_priv->state);
+ else
+ clear_bit(WRITE_READY_BN, &nec_priv->state);
+
+ if (ext_status_1 & COMMAND_OUT_STATUS_BIT)
+ set_bit(COMMAND_READY_BN, &nec_priv->state);
+ else
+ clear_bit(COMMAND_READY_BN, &nec_priv->state);
+
+ if (ext_status_1 & RFD_HOLDOFF_STATUS_BIT)
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ else
+ clear_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+
+ if (ext_status_1 & END_STATUS_BIT) {
+ /* only set RECEIVED_END while there is still a data
+ * byte sitting in the chip, to avoid spuriously
+ * setting it multiple times after it has been cleared
+ * during a read.
+ */
+ if (ext_status_1 & DATA_IN_STATUS_BIT)
+ set_bit(RECEIVED_END_BN, &nec_priv->state);
+ } else {
+ clear_bit(RECEIVED_END_BN, &nec_priv->state);
+ }
+
+ if ((fifo_status & TX_FIFO_HALF_EMPTY_INTERRUPT_IS_ENABLED) &&
+ (fifo_status & TX_FIFO_HALF_EMPTY)) {
+ /* We really only want to clear the
+ * TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE bit in the
+ * FIFO_CONTROL_STATUS_REG. Since we are not being
+ * careful, this also has a side effect of disabling
+ * DMA requests and the RX fifo interrupt. That is
+ * fine though, since they should never be in use at
+ * the same time as the TX fifo interrupt.
+ */
+ fifos_write(priv, 0x0, FIFO_CONTROL_STATUS_REG);
+ retval = IRQ_HANDLED;
+ }
+
+ if ((fifo_status & RX_FIFO_HALF_FULL_INTERRUPT_IS_ENABLED) &&
+ (fifo_status & RX_FIFO_HALF_FULL)) {
+ /* We really only want to clear the
+ * RX_FIFO_HALF_FULL_INTERRUPT_ENABLE bit in the
+ * FIFO_CONTROL_STATUS_REG. Since we are not being
+ * careful, this also has a side effect of disabling
+ * DMA requests and the TX fifo interrupt. That is
+ * fine though, since they should never be in use at
+ * the same time as the RX fifo interrupt.
+ */
+ fifos_write(priv, 0x0, FIFO_CONTROL_STATUS_REG);
+ retval = IRQ_HANDLED;
+ }
+
+ if (retval == IRQ_HANDLED)
+ wake_up_interruptible(&board->wait);
+
+ return retval;
+}
+
+irqreturn_t fmh_gpib_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = fmh_gpib_internal_interrupt(board);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+static int fmh_gpib_allocate_private(gpib_board_t *board)
+{
+ struct fmh_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct fmh_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct fmh_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ priv->dma_buffer_size = 0x800;
+ priv->dma_buffer = kmalloc(priv->dma_buffer_size, GFP_KERNEL);
+ if (!priv->dma_buffer)
+ return -ENOMEM;
+ return 0;
+}
+
+static void fmh_gpib_generic_detach(gpib_board_t *board)
+{
+ if (board->private_data) {
+ struct fmh_priv *e_priv = board->private_data;
+
+ kfree(e_priv->dma_buffer);
+ kfree(board->private_data);
+ board->private_data = NULL;
+ }
+ if (board->dev)
+ dev_set_drvdata(board->dev, NULL);
+}
+
+// generic part of attach functions
+static int fmh_gpib_generic_attach(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ board->status = 0;
+
+ retval = fmh_gpib_allocate_private(board);
+ if (retval < 0)
+ return retval;
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+ nec_priv->read_byte = gpib_cs_read_byte;
+ nec_priv->write_byte = gpib_cs_write_byte;
+ nec_priv->offset = 1;
+ nec_priv->type = CB7210;
+ return 0;
+}
+
+static int fmh_gpib_config_dma(gpib_board_t *board, int output)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct dma_slave_config config;
+
+ config.device_fc = true;
+
+ if (e_priv->dma_burst_length < 1) {
+ config.src_maxburst = 1;
+ config.dst_maxburst = 1;
+ } else {
+ config.src_maxburst = e_priv->dma_burst_length;
+ config.dst_maxburst = e_priv->dma_burst_length;
+ }
+
+ config.src_addr_width = 1;
+ config.dst_addr_width = 1;
+
+ if (output) {
+ config.direction = DMA_MEM_TO_DEV;
+ config.src_addr = 0;
+ config.dst_addr = e_priv->dma_port_res->start + FIFO_DATA_REG * fifo_reg_offset;
+ } else {
+ config.direction = DMA_DEV_TO_MEM;
+ config.src_addr = e_priv->dma_port_res->start + FIFO_DATA_REG * fifo_reg_offset;
+ config.dst_addr = 0;
+ }
+ return dmaengine_slave_config(e_priv->dma_channel, &config);
+}
+
+static int fmh_gpib_init(struct fmh_priv *e_priv, gpib_board_t *board, int handshake_mode)
+{
+ struct nec7210_priv *nec_priv = &e_priv->nec7210_priv;
+ unsigned long flags;
+ unsigned int fifo_status_bits;
+
+ fifos_write(e_priv, RX_FIFO_CLEAR | TX_FIFO_CLEAR, FIFO_CONTROL_STATUS_REG);
+
+ nec7210_board_reset(nec_priv, board);
+ write_byte(nec_priv, AUX_LO_SPEED, AUXMR);
+ nec7210_set_handshake_mode(board, nec_priv, handshake_mode);
+
+ /* Hueristically check if hardware supports fifo half full/empty interrupts */
+ fifo_status_bits = fifos_read(e_priv, FIFO_CONTROL_STATUS_REG);
+ e_priv->supports_fifo_interrupts = (fifo_status_bits & TX_FIFO_EMPTY) &&
+ (fifo_status_bits & TX_FIFO_HALF_EMPTY);
+
+ nec7210_board_online(nec_priv, board);
+
+ write_byte(nec_priv, IFC_INTERRUPT_ENABLE_BIT | ATN_INTERRUPT_ENABLE_BIT, ISR0_IMR0_REG);
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ write_byte(nec_priv, AUX_RFD_HOLDOFF_ASAP, AUXMR);
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return 0;
+}
+
+/* Match callback for driver_find_device */
+static int fmh_gpib_device_match(struct device *dev, const void *data)
+{
+ const gpib_board_config_t *config = data;
+
+ if (dev_get_drvdata(dev))
+ return 0;
+
+ if (gpib_match_device_path(dev, config->device_path) == 0)
+ return 0;
+
+ // driver doesn't support selection by serial number
+ if (config->serial_number)
+ return 0;
+
+ dev_notice(dev, "matched: %s\n", of_node_full_name(dev_of_node((dev))));
+ return 1;
+}
+
+static int fmh_gpib_attach_impl(gpib_board_t *board, const gpib_board_config_t *config,
+ unsigned int handshake_mode, int acquire_dma)
+{
+ struct fmh_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+ int irq;
+ struct resource *res;
+ struct platform_device *pdev;
+
+ board->dev = driver_find_device(&fmh_gpib_platform_driver.driver,
+ NULL, (const void *)config, &fmh_gpib_device_match);
+ if (!board->dev) {
+ pr_err("No matching fmh_gpib_core device was found, attach failed.");
+ return -ENODEV;
+ }
+ // currently only used to mark the device as already attached
+ dev_set_drvdata(board->dev, board);
+ pdev = to_platform_device(board->dev);
+
+ retval = fmh_gpib_generic_attach(board);
+ if (retval)
+ return retval;
+
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gpib_control_status");
+ if (!res) {
+ dev_err(board->dev, "Unable to locate mmio resource for cb7210 gpib\n");
+ return -ENODEV;
+ }
+
+ if (request_mem_region(res->start,
+ resource_size(res),
+ pdev->name) == NULL) {
+ dev_err(board->dev, "cannot claim registers\n");
+ return -ENXIO;
+ }
+ e_priv->gpib_iomem_res = res;
+
+ nec_priv->iobase = ioremap(e_priv->gpib_iomem_res->start,
+ resource_size(e_priv->gpib_iomem_res));
+ if (!nec_priv->iobase) {
+ dev_err(board->dev, "Could not map I/O memory for gpib\n");
+ return -ENOMEM;
+ }
+ dev_info(board->dev, "iobase 0x%lx remapped to %p, length=%ld\n",
+ (unsigned long)e_priv->gpib_iomem_res->start,
+ nec_priv->iobase, (unsigned long)resource_size(e_priv->gpib_iomem_res));
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma_fifos");
+ if (!res) {
+ dev_err(board->dev, "Unable to locate mmio resource for gpib dma port\n");
+ return -ENODEV;
+ }
+ if (request_mem_region(res->start,
+ resource_size(res),
+ pdev->name) == NULL) {
+ dev_err(board->dev, "cannot claim registers\n");
+ return -ENXIO;
+ }
+ e_priv->dma_port_res = res;
+ e_priv->fifo_base = ioremap(e_priv->dma_port_res->start,
+ resource_size(e_priv->dma_port_res));
+ if (!e_priv->fifo_base) {
+ dev_err(board->dev, "Could not map I/O memory for fifos\n");
+ return -ENOMEM;
+ }
+ dev_info(board->dev, "dma fifos 0x%lx remapped to %p, length=%ld\n",
+ (unsigned long)e_priv->dma_port_res->start, e_priv->fifo_base,
+ (unsigned long)resource_size(e_priv->dma_port_res));
+
+ irq = platform_get_irq(pdev, 0);
+ pr_info("gpib: irq %d\n", irq);
+ if (irq < 0) {
+ dev_err(board->dev, "fmh_gpib_gpib: request for IRQ failed\n");
+ return -EBUSY;
+ }
+ retval = request_irq(irq, fmh_gpib_interrupt, IRQF_SHARED, pdev->name, board);
+ if (retval) {
+ dev_err(board->dev,
+ "cannot register interrupt handler err=%d\n",
+ retval);
+ return retval;
+ }
+ e_priv->irq = irq;
+
+ if (acquire_dma) {
+ e_priv->dma_channel = dma_request_slave_channel(board->dev, "rxtx");
+ if (!e_priv->dma_channel) {
+ dev_err(board->dev, "failed to acquire dma channel \"rxtx\".\n");
+ return -EIO;
+ }
+ }
+ /* in the future we might want to know the half-fifo size
+ * (dma_burst_length) even when not using dma, so go ahead an
+ * initialize it unconditionally.
+ */
+ e_priv->dma_burst_length = fifos_read(e_priv, FIFO_MAX_BURST_LENGTH_REG) &
+ fifo_max_burst_length_mask;
+
+ return fmh_gpib_init(e_priv, board, handshake_mode);
+}
+
+int fmh_gpib_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return fmh_gpib_attach_impl(board, config, HR_HLDA, 0);
+}
+
+int fmh_gpib_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return fmh_gpib_attach_impl(board, config, HR_HLDE, 1);
+}
+
+void fmh_gpib_detach(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (e_priv) {
+ if (e_priv->dma_channel)
+ dma_release_channel(e_priv->dma_channel);
+ nec_priv = &e_priv->nec7210_priv;
+
+ if (e_priv->irq)
+ free_irq(e_priv->irq, board);
+ if (e_priv->fifo_base)
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+ if (nec_priv->iobase) {
+ write_byte(nec_priv, 0, ISR0_IMR0_REG);
+ nec7210_board_reset(nec_priv, board);
+ }
+ if (e_priv->fifo_base)
+ iounmap(e_priv->fifo_base);
+ if (nec_priv->iobase)
+ iounmap(nec_priv->iobase);
+ if (e_priv->dma_port_res) {
+ release_mem_region(e_priv->dma_port_res->start,
+ resource_size(e_priv->dma_port_res));
+ }
+ if (e_priv->gpib_iomem_res)
+ release_mem_region(e_priv->gpib_iomem_res->start,
+ resource_size(e_priv->gpib_iomem_res));
+ }
+ fmh_gpib_generic_detach(board);
+}
+
+static int fmh_gpib_pci_attach_impl(gpib_board_t *board, const gpib_board_config_t *config,
+ unsigned int handshake_mode)
+{
+ struct fmh_priv *e_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+ struct pci_dev *pci_device;
+
+ retval = fmh_gpib_generic_attach(board);
+ if (retval)
+ return retval;
+
+ e_priv = board->private_data;
+ nec_priv = &e_priv->nec7210_priv;
+
+ // find board
+ pci_device = gpib_pci_get_device(config, BOGUS_PCI_VENDOR_ID_FLUKE,
+ BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER, NULL);
+ if (!pci_device) {
+ pr_err("No matching fmh_gpib_core pci device was found, attach failed.");
+ return -ENODEV;
+ }
+ board->dev = &pci_device->dev;
+
+ // bladerunner prototype has offset of 4 between gpib control/status registers
+ nec_priv->offset = 4;
+
+ if (pci_enable_device(pci_device)) {
+ dev_err(board->dev, "error enabling pci device\n");
+ return -EIO;
+ }
+ if (pci_request_regions(pci_device, KBUILD_MODNAME)) {
+ dev_err(board->dev, "pci_request_regions failed\n");
+ return -EIO;
+ }
+ e_priv->gpib_iomem_res = &pci_device->resource[gpib_control_status_pci_resource_index];
+ e_priv->dma_port_res = &pci_device->resource[gpib_fifo_pci_resource_index];
+
+ nec_priv->iobase = ioremap(pci_resource_start(pci_device,
+ gpib_control_status_pci_resource_index),
+ pci_resource_len(pci_device,
+ gpib_control_status_pci_resource_index));
+ dev_info(board->dev, "base address for gpib control/status registers remapped to 0x%p\n",
+ nec_priv->iobase);
+
+ if (e_priv->dma_port_res->flags & IORESOURCE_MEM) {
+ e_priv->fifo_base = ioremap(pci_resource_start(pci_device,
+ gpib_fifo_pci_resource_index),
+ pci_resource_len(pci_device,
+ gpib_fifo_pci_resource_index));
+ dev_info(board->dev, "base address for gpib fifo registers remapped to 0x%p\n",
+ e_priv->fifo_base);
+ } else {
+ e_priv->fifo_base = NULL;
+ dev_info(board->dev, "hardware has no gpib fifo registers.\n");
+ }
+
+ if (pci_device->irq) {
+ retval = request_irq(pci_device->irq, fmh_gpib_interrupt, IRQF_SHARED,
+ KBUILD_MODNAME, board);
+ if (retval) {
+ dev_err(board->dev,
+ "cannot register interrupt handler err=%d\n",
+ retval);
+ return retval;
+ }
+ }
+ e_priv->irq = pci_device->irq;
+
+ e_priv->dma_burst_length = fifos_read(e_priv, FIFO_MAX_BURST_LENGTH_REG) &
+ fifo_max_burst_length_mask;
+
+ return fmh_gpib_init(e_priv, board, handshake_mode);
+}
+
+int fmh_gpib_pci_attach_holdoff_all(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return fmh_gpib_pci_attach_impl(board, config, HR_HLDA);
+}
+
+int fmh_gpib_pci_attach_holdoff_end(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int retval;
+ struct fmh_priv *e_priv;
+
+ retval = fmh_gpib_pci_attach_impl(board, config, HR_HLDE);
+ e_priv = board->private_data;
+ if (retval == 0 && e_priv && e_priv->supports_fifo_interrupts == 0) {
+ pr_err("fmh_gpib: your fmh_gpib_core does not appear to support fifo interrupts. Try the fmh_gpib_pci_unaccel board type instead.");
+ return -EIO;
+ }
+ return retval;
+}
+
+void fmh_gpib_pci_detach(gpib_board_t *board)
+{
+ struct fmh_priv *e_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (e_priv) {
+ nec_priv = &e_priv->nec7210_priv;
+
+ if (e_priv->irq)
+ free_irq(e_priv->irq, board);
+ if (e_priv->fifo_base)
+ fifos_write(e_priv, 0, FIFO_CONTROL_STATUS_REG);
+ if (nec_priv->iobase) {
+ write_byte(nec_priv, 0, ISR0_IMR0_REG);
+ nec7210_board_reset(nec_priv, board);
+ }
+ if (e_priv->fifo_base)
+ iounmap(e_priv->fifo_base);
+ if (nec_priv->iobase)
+ iounmap(nec_priv->iobase);
+ if (e_priv->dma_port_res || e_priv->gpib_iomem_res)
+ pci_release_regions(to_pci_dev(board->dev));
+ if (board->dev)
+ pci_dev_put(to_pci_dev(board->dev));
+ }
+ fmh_gpib_generic_detach(board);
+}
+
+static int fmh_gpib_platform_probe(struct platform_device *pdev)
+{
+ return 0;
+}
+
+static const struct of_device_id fmh_gpib_of_match[] = {
+ { .compatible = "fmhess,fmh_gpib_core"},
+ { {0} }
+};
+MODULE_DEVICE_TABLE(of, fmh_gpib_of_match);
+
+static struct platform_driver fmh_gpib_platform_driver = {
+ .driver = {
+ .name = "fmh_gpib",
+ .owner = THIS_MODULE,
+ .of_match_table = fmh_gpib_of_match,
+ },
+ .probe = &fmh_gpib_platform_probe
+};
+
+static int fmh_gpib_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static const struct pci_device_id fmh_gpib_pci_match[] = {
+ { BOGUS_PCI_VENDOR_ID_FLUKE, BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER, 0, 0, 0 },
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, fmh_gpib_pci_match);
+
+static struct pci_driver fmh_gpib_pci_driver = {
+ .name = "fmh_gpib",
+ .id_table = fmh_gpib_pci_match,
+ .probe = &fmh_gpib_pci_probe
+};
+
+static int __init fmh_gpib_init_module(void)
+{
+ int result;
+
+ result = platform_driver_register(&fmh_gpib_platform_driver);
+ if (result) {
+ pr_err("fmh_gpib: platform_driver_register failed!\n");
+ return result;
+ }
+
+ result = pci_register_driver(&fmh_gpib_pci_driver);
+ if (result) {
+ pr_err("fmh_gpib: pci_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&fmh_gpib_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&fmh_gpib_interface, THIS_MODULE);
+ gpib_register_driver(&fmh_gpib_pci_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&fmh_gpib_pci_interface, THIS_MODULE);
+
+ pr_info("fmh_gpib\n");
+ return 0;
+}
+
+static void __exit fmh_gpib_exit_module(void)
+{
+ gpib_unregister_driver(&fmh_gpib_pci_interface);
+ gpib_unregister_driver(&fmh_gpib_pci_unaccel_interface);
+ gpib_unregister_driver(&fmh_gpib_unaccel_interface);
+ gpib_unregister_driver(&fmh_gpib_interface);
+
+ pci_unregister_driver(&fmh_gpib_pci_driver);
+ platform_driver_unregister(&fmh_gpib_platform_driver);
+}
+
+module_init(fmh_gpib_init_module);
+module_exit(fmh_gpib_exit_module);
diff --git a/drivers/staging/gpib/fmh_gpib/fmh_gpib.h b/drivers/staging/gpib/fmh_gpib/fmh_gpib.h
new file mode 100644
index 000000000000..43bfc89d2a6f
--- /dev/null
+++ b/drivers/staging/gpib/fmh_gpib/fmh_gpib.h
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Author: Frank Mori Hess <fmh6jj@gmail.com>
+ * Copyright: (C) 2006, 2010, 2015 Fluke Corporation
+ * (C) 2017 Frank Mori Hess
+ ***************************************************************************/
+
+#include <linux/dmaengine.h>
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include "nec7210.h"
+
+static const int fifo_reg_offset = 2;
+
+static const int gpib_control_status_pci_resource_index;
+static const int gpib_fifo_pci_resource_index = 1;
+
+/* We don't have a real pci vendor/device id, the following will need to be
+ * patched to match prototype hardware.
+ */
+#define BOGUS_PCI_VENDOR_ID_FLUKE 0xffff
+#define BOGUS_PCI_DEVICE_ID_FLUKE_BLADERUNNER 0x0
+
+struct fmh_priv {
+ struct nec7210_priv nec7210_priv;
+ struct resource *gpib_iomem_res;
+ struct resource *write_transfer_counter_res;
+ struct resource *dma_port_res;
+ int irq;
+ struct dma_chan *dma_channel;
+ u8 *dma_buffer;
+ int dma_buffer_size;
+ int dma_burst_length;
+ void *fifo_base;
+ unsigned supports_fifo_interrupts : 1;
+};
+
+static inline int fmh_gpib_half_fifo_size(struct fmh_priv *priv)
+{
+ return priv->dma_burst_length;
+}
+
+// registers beyond the nec7210 register set
+enum fmh_gpib_regs {
+ EXT_STATUS_1_REG = 0x9,
+ STATE1_REG = 0xc,
+ ISR0_IMR0_REG = 0xe,
+ BUS_STATUS_REG = 0xf
+};
+
+/* IMR0 -- Interrupt Mode Register 0 */
+enum imr0_bits {
+ ATN_INTERRUPT_ENABLE_BIT = 0x4,
+ IFC_INTERRUPT_ENABLE_BIT = 0x8
+};
+
+/* ISR0 -- Interrupt Status Register 0 */
+enum isr0_bits {
+ ATN_INTERRUPT_BIT = 0x4,
+ IFC_INTERRUPT_BIT = 0x8
+};
+
+enum state1_bits {
+ SOURCE_HANDSHAKE_SIDS_BITS = 0x0, /* source idle state */
+ SOURCE_HANDSHAKE_SGNS_BITS = 0x1, /* source generate state */
+ SOURCE_HANDSHAKE_SDYS_BITS = 0x2, /* source delay state */
+ SOURCE_HANDSHAKE_STRS_BITS = 0x5, /* source transfer state */
+ SOURCE_HANDSHAKE_MASK = 0x7
+};
+
+enum fmh_gpib_auxmr_bits {
+ AUX_I_REG = 0xe0,
+};
+
+enum aux_reg_i_bits {
+ LOCAL_PPOLL_MODE_BIT = 0x4
+};
+
+enum ext_status_1_bits {
+ DATA_IN_STATUS_BIT = 0x01,
+ DATA_OUT_STATUS_BIT = 0x02,
+ COMMAND_OUT_STATUS_BIT = 0x04,
+ RFD_HOLDOFF_STATUS_BIT = 0x08,
+ END_STATUS_BIT = 0x10
+};
+
+/* dma fifo reg and bits */
+enum dma_fifo_regs {
+ FIFO_DATA_REG = 0x0,
+ FIFO_CONTROL_STATUS_REG = 0x1,
+ FIFO_XFER_COUNTER_REG = 0x2,
+ FIFO_MAX_BURST_LENGTH_REG = 0x3
+};
+
+enum fifo_data_bits {
+ FIFO_DATA_EOI_FLAG = 0x100
+};
+
+enum fifo_control_bits {
+ TX_FIFO_DMA_REQUEST_ENABLE = 0x0001,
+ TX_FIFO_CLEAR = 0x0002,
+ TX_FIFO_HALF_EMPTY_INTERRUPT_ENABLE = 0x0008,
+ RX_FIFO_DMA_REQUEST_ENABLE = 0x0100,
+ RX_FIFO_CLEAR = 0x0200,
+ RX_FIFO_HALF_FULL_INTERRUPT_ENABLE = 0x0800
+};
+
+enum fifo_status_bits {
+ TX_FIFO_EMPTY = 0x0001,
+ TX_FIFO_FULL = 0x0002,
+ TX_FIFO_HALF_EMPTY = 0x0004,
+ TX_FIFO_HALF_EMPTY_INTERRUPT_IS_ENABLED = 0x0008,
+ TX_FIFO_DMA_REQUEST_IS_ENABLED = 0x0010,
+ RX_FIFO_EMPTY = 0x0100,
+ RX_FIFO_FULL = 0x0200,
+ RX_FIFO_HALF_FULL = 0x0400,
+ RX_FIFO_HALF_FULL_INTERRUPT_IS_ENABLED = 0x0800,
+ RX_FIFO_DMA_REQUEST_IS_ENABLED = 0x1000
+};
+
+static const unsigned int fifo_data_mask = 0x00ff;
+static const unsigned int fifo_xfer_counter_mask = 0x0fff;
+static const unsigned int fifo_max_burst_length_mask = 0x00ff;
+
+static inline uint8_t gpib_cs_read_byte(struct nec7210_priv *nec_priv,
+ unsigned int register_num)
+{
+ return readb(nec_priv->iobase + register_num * nec_priv->offset);
+}
+
+static inline void gpib_cs_write_byte(struct nec7210_priv *nec_priv, uint8_t data,
+ unsigned int register_num)
+{
+ writeb(data, nec_priv->iobase + register_num * nec_priv->offset);
+}
+
+static inline uint16_t fifos_read(struct fmh_priv *fmh_priv, int register_num)
+{
+ if (!fmh_priv->fifo_base)
+ return 0;
+ return readw(fmh_priv->fifo_base + register_num * fifo_reg_offset);
+}
+
+static inline void fifos_write(struct fmh_priv *fmh_priv, uint16_t data, int register_num)
+{
+ if (!fmh_priv->fifo_base)
+ return;
+ writew(data, fmh_priv->fifo_base + register_num * fifo_reg_offset);
+}
+
+enum bus_status_bits {
+ BSR_ATN_BIT = 0x01,
+ BSR_EOI_BIT = 0x02,
+ BSR_SRQ_BIT = 0x04,
+ BSR_IFC_BIT = 0x08,
+ BSR_REN_BIT = 0x10,
+ BSR_DAV_BIT = 0x20,
+ BSR_NRFD_BIT = 0x40,
+ BSR_NDAC_BIT = 0x80,
+};
+
+enum fmh_gpib_aux_cmds {
+ /* AUX_RTL2 is an auxiliary command which causes the cb7210 to assert
+ * (and keep asserted) the local rtl message. This is used in conjunction
+ * with the normal nec7210 AUX_RTL command, which
+ * pulses the rtl message, having the effect of clearing rtl if it was left
+ * asserted by AUX_RTL2.
+ */
+ AUX_RTL2 = 0x0d,
+ AUX_RFD_HOLDOFF_ASAP = 0x15,
+ AUX_REQT = 0x18,
+ AUX_REQF = 0x19,
+ AUX_LO_SPEED = 0x40,
+ AUX_HI_SPEED = 0x41
+};
diff --git a/drivers/staging/gpib/gpio/Makefile b/drivers/staging/gpib/gpio/Makefile
new file mode 100644
index 000000000000..a31ded6e5924
--- /dev/null
+++ b/drivers/staging/gpib/gpio/Makefile
@@ -0,0 +1,4 @@
+
+obj-m += gpib_bitbang.o
+
+
diff --git a/drivers/staging/gpib/gpio/gpib_bitbang.c b/drivers/staging/gpib/gpio/gpib_bitbang.c
new file mode 100644
index 000000000000..a2d562cbd65b
--- /dev/null
+++ b/drivers/staging/gpib/gpio/gpib_bitbang.c
@@ -0,0 +1,1476 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*************************************************************************
+ * This code has been developed at the Institute of Sensor and Actuator *
+ * Systems (Technical University of Vienna, Austria) to enable the GPIO *
+ * lines (e.g. of a raspberry pi) to function as a GPIO master device *
+ * *
+ * authors : Thomas Klima *
+ * Marcello Carla' *
+ * Dave Penkler *
+ * *
+ * copyright : (C) 2016 Thomas Klima *
+ * *
+ *************************************************************************/
+
+/*
+ * limitations:
+ * works only on RPi
+ * cannot function as non-CIC system controller with SN7516x because
+ * SN75161B cannot simultaneously make ATN input with IFC and REN as
+ * outputs.
+ * not implemented:
+ * parallel poll
+ * return2local
+ * device support (non master operation)
+ */
+
+#define NAME KBUILD_MODNAME
+
+#define ENABLE_IRQ(IRQ, TYPE) irq_set_irq_type(IRQ, TYPE)
+#define DISABLE_IRQ(IRQ) irq_set_irq_type(IRQ, IRQ_TYPE_NONE)
+
+/* Debug print levels:
+ * 0 = load/unload info and errors that make the driver fail;
+ * 1 = + warnings for unforeseen events that may break the current
+ * operation and lead to a timeout, but do not affect the
+ * driver integrity (mainly unexpected interrupts);
+ * 2 = + trace of function calls;
+ * 3 = + trace of protocol codes;
+ * 4 = + trace of interrupt operation.
+ */
+#define dbg_printk(level, frm, ...) \
+ do { if (debug >= (level)) \
+ pr_info("%s:%s - " frm, NAME, __func__, ## __VA_ARGS__); } \
+ while (0)
+
+#define LINVAL gpiod_get_value(DAV), \
+ gpiod_get_value(NRFD), \
+ gpiod_get_value(NDAC), \
+ gpiod_get_value(SRQ)
+#define LINFMT "DAV: %d NRFD:%d NDAC: %d SRQ: %d"
+
+#include "gpibP.h"
+#include "gpib_state_machines.h"
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/gpio/consumer.h>
+#include <linux/gpio/driver.h>
+#include <linux/gpio/machine.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/leds.h>
+
+static int sn7516x_used = 1, sn7516x;
+module_param(sn7516x_used, int, 0660);
+
+#define PINMAP_0 "elektronomikon"
+#define PINMAP_1 "gpib4pi-1.1"
+#define PINMAP_2 "yoga"
+static char *pin_map = PINMAP_0;
+module_param(pin_map, charp, 0660);
+MODULE_PARM_DESC(pin_map, " valid values: " PINMAP_0 " " PINMAP_1 " " PINMAP_2);
+
+/**********************************************
+ * Signal pairing and pin wiring between the *
+ * Raspberry-Pi connector and the GPIB bus *
+ * *
+ * signal pin wiring *
+ * GPIB Pi-gpio GPIB -> RPi *
+ **********************************************
+ */
+enum lines_t {
+ D01_pin_nr = 20, /* 1 -> 38 */
+ D02_pin_nr = 26, /* 2 -> 37 */
+ D03_pin_nr = 16, /* 3 -> 36 */
+ D04_pin_nr = 19, /* 4 -> 35 */
+ D05_pin_nr = 13, /* 13 -> 33 */
+ D06_pin_nr = 12, /* 14 -> 32 */
+ D07_pin_nr = 6, /* 15 -> 31 */
+ D08_pin_nr = 5, /* 16 -> 29 */
+ EOI_pin_nr = 9, /* 5 -> 21 */
+ DAV_pin_nr = 10, /* 6 -> 19 */
+ NRFD_pin_nr = 24, /* 7 -> 18 */
+ NDAC_pin_nr = 23, /* 8 -> 16 */
+ IFC_pin_nr = 22, /* 9 -> 15 */
+ SRQ_pin_nr = 11, /* 10 -> 23 */
+ _ATN_pin_nr = 25, /* 11 -> 22 */
+ REN_pin_nr = 27, /* 17 -> 13 */
+/*
+ * GROUND PINS
+ * 12,18,19,20,21,22,23,24 => 14,20,25,30,34,39
+ */
+
+/*
+ * These lines are used to control the external
+ * SN75160/161 driver chips when used.
+ * When not used there is reduced fan out;
+ * currently tested with up to 4 devices.
+ */
+
+/* Pi GPIO RPI 75161B 75160B Description */
+ PE_pin_nr = 7, /* 26 -> nc 11 Pullup Enable */
+ DC_pin_nr = 8, /* 24 -> 12 nc Direction control */
+ TE_pin_nr = 18, /* 12 -> 2 1 Talk Enable */
+ ACT_LED_pin_nr = 4, /* 7 -> LED */
+
+/* YOGA adapter uses different pinout to ease layout */
+ YOGA_D03_pin_nr = 13,
+ YOGA_D04_pin_nr = 12,
+ YOGA_D05_pin_nr = 21,
+ YOGA_D06_pin_nr = 19,
+};
+
+/*
+ * GPIO descriptors and pins - WARNING: STRICTLY KEEP ITEMS ORDER
+ */
+
+#define GPIB_PINS 16
+#define SN7516X_PINS 4
+#define NUM_PINS (GPIB_PINS + SN7516X_PINS)
+
+DEFINE_LED_TRIGGER(ledtrig_gpib);
+#define ACT_LED_ON do { \
+ if (ACT_LED) \
+ gpiod_direction_output(ACT_LED, 1); \
+ else \
+ led_trigger_event(ledtrig_gpib, LED_FULL); } \
+ while (0)
+#define ACT_LED_OFF do { \
+ if (ACT_LED) \
+ gpiod_direction_output(ACT_LED, 0); \
+ else \
+ led_trigger_event(ledtrig_gpib, LED_OFF); } \
+ while (0)
+
+struct gpio_desc *all_descriptors[GPIB_PINS + SN7516X_PINS];
+
+#define D01 all_descriptors[0]
+#define D02 all_descriptors[1]
+#define D03 all_descriptors[2]
+#define D04 all_descriptors[3]
+#define D05 all_descriptors[4]
+#define D06 all_descriptors[5]
+#define D07 all_descriptors[6]
+#define D08 all_descriptors[7]
+
+#define EOI all_descriptors[8]
+#define NRFD all_descriptors[9]
+#define IFC all_descriptors[10]
+#define _ATN all_descriptors[11]
+#define REN all_descriptors[12]
+#define DAV all_descriptors[13]
+#define NDAC all_descriptors[14]
+#define SRQ all_descriptors[15]
+
+#define PE all_descriptors[16]
+#define DC all_descriptors[17]
+#define TE all_descriptors[18]
+#define ACT_LED all_descriptors[19]
+
+/* YOGA dapter uses a global enable for the buffer chips, re-using the TE pin */
+#define YOGA_ENABLE TE
+
+int gpios_vector[] = {
+ D01_pin_nr,
+ D02_pin_nr,
+ D03_pin_nr,
+ D04_pin_nr,
+ D05_pin_nr,
+ D06_pin_nr,
+ D07_pin_nr,
+ D08_pin_nr,
+
+ EOI_pin_nr,
+ NRFD_pin_nr,
+ IFC_pin_nr,
+ _ATN_pin_nr,
+ REN_pin_nr,
+ DAV_pin_nr,
+ NDAC_pin_nr,
+ SRQ_pin_nr,
+
+ PE_pin_nr,
+ DC_pin_nr,
+ TE_pin_nr,
+ ACT_LED_pin_nr
+};
+
+/* Lookup table for general GPIOs */
+
+static struct gpiod_lookup_table gpib_gpio_table_1 = {
+ // for bcm2835/6
+ .dev_id = "", // device id of board device
+ .table = {
+ GPIO_LOOKUP_IDX("GPIO_GCLK", U16_MAX, NULL, 4, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO5", U16_MAX, NULL, 5, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO6", U16_MAX, NULL, 6, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("SPI_CE1_N", U16_MAX, NULL, 7, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("SPI_CE0_N", U16_MAX, NULL, 8, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("SPI_MISO", U16_MAX, NULL, 9, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("SPI_MOSI", U16_MAX, NULL, 10, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("SPI_SCLK", U16_MAX, NULL, 11, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO12", U16_MAX, NULL, 12, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO13", U16_MAX, NULL, 13, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO16", U16_MAX, NULL, 16, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO17", U16_MAX, NULL, 17, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO18", U16_MAX, NULL, 18, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO19", U16_MAX, NULL, 19, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO20", U16_MAX, NULL, 20, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO21", U16_MAX, NULL, 21, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO22", U16_MAX, NULL, 22, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO23", U16_MAX, NULL, 23, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO24", U16_MAX, NULL, 24, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO25", U16_MAX, NULL, 25, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO26", U16_MAX, NULL, 26, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO27", U16_MAX, NULL, 27, GPIO_ACTIVE_HIGH),
+ { }
+ },
+};
+
+static struct gpiod_lookup_table gpib_gpio_table_0 = {
+ .dev_id = "", // device id of board device
+ .table = {
+ // for bcm27xx based pis (b b+ 2b 3b 3b+ 4 5)
+ GPIO_LOOKUP_IDX("GPIO4", U16_MAX, NULL, 4, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO5", U16_MAX, NULL, 5, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO6", U16_MAX, NULL, 6, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO7", U16_MAX, NULL, 7, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO8", U16_MAX, NULL, 8, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO9", U16_MAX, NULL, 9, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO10", U16_MAX, NULL, 10, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO11", U16_MAX, NULL, 11, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO12", U16_MAX, NULL, 12, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO13", U16_MAX, NULL, 13, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO16", U16_MAX, NULL, 16, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO17", U16_MAX, NULL, 17, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO18", U16_MAX, NULL, 18, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO19", U16_MAX, NULL, 19, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO20", U16_MAX, NULL, 20, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO21", U16_MAX, NULL, 21, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO22", U16_MAX, NULL, 22, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO23", U16_MAX, NULL, 23, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO24", U16_MAX, NULL, 24, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO25", U16_MAX, NULL, 25, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO26", U16_MAX, NULL, 26, GPIO_ACTIVE_HIGH),
+ GPIO_LOOKUP_IDX("GPIO27", U16_MAX, NULL, 27, GPIO_ACTIVE_HIGH),
+ { }
+ },
+};
+
+static struct gpiod_lookup_table *lookup_tables[] = {
+ &gpib_gpio_table_0,
+ &gpib_gpio_table_1,
+ 0
+};
+
+/* struct which defines private_data for gpio driver */
+
+struct bb_priv {
+ int irq_NRFD;
+ int irq_NDAC;
+ int irq_DAV;
+ int irq_SRQ;
+ int dav_mode; /* dav interrupt mode 0/1 -> edge/levels */
+ int nrfd_mode; /* nrfd interrupt mode 0/1 -> edge/levels */
+ int ndac_mode; /* nrfd interrupt mode 0/1 -> edge/levels */
+ int dav_tx; /* keep trace of DAV status while sending */
+ int dav_rx; /* keep trace of DAV status while receiving */
+ u8 eos; // eos character
+ short eos_flags; // eos mode
+ short eos_check; /* eos check required in current operation ... */
+ short eos_check_8; /* ... with byte comparison */
+ short eos_mask_7; /* ... with 7 bit masked character */
+ short int end;
+ int request;
+ int count;
+ int direction;
+ int t1_delay;
+ u8 *rbuf;
+ u8 *wbuf;
+ int end_flag;
+ int r_busy; /* 0==idle 1==busy */
+ int w_busy;
+ int write_done;
+ int cmd; /* 1 = cmd write in progress */
+ size_t w_cnt;
+ size_t length;
+ u8 *w_buf;
+ spinlock_t rw_lock; // protect mods to rw_lock
+ int phase;
+ int ndac_idle;
+ int ndac_seq;
+ int nrfd_idle;
+ int nrfd_seq;
+ int dav_seq;
+ long all_irqs;
+ int dav_idle;
+ int atn_asserted;
+
+ enum talker_function_state talker_state;
+ enum listener_function_state listener_state;
+};
+
+inline long usec_diff(struct timespec64 *a, struct timespec64 *b);
+static void bb_buffer_print(unsigned char *buffer, size_t length, int cmd, int eoi);
+static void set_data_lines(u8 byte);
+static u8 get_data_lines(void);
+static void set_data_lines_input(void);
+static void set_data_lines_output(void);
+static inline int check_for_eos(struct bb_priv *priv, uint8_t byte);
+static void set_atn(struct bb_priv *priv, int atn_asserted);
+
+static inline void SET_DIR_WRITE(struct bb_priv *priv);
+static inline void SET_DIR_READ(struct bb_priv *priv);
+
+#define DIR_READ 0
+#define DIR_WRITE 1
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB helper functions for bitbanging I/O");
+
+/**** global variables ****/
+#ifdef CONFIG_GPIB_DEBUG
+static int debug = 1;
+#else
+static int debug;
+#endif
+module_param(debug, int, 0644);
+
+static char printable(char x)
+{
+ if (x < 32 || x > 126)
+ return ' ';
+ return x;
+}
+
+/***************************************************************************
+ * *
+ * READ *
+ * *
+ ***************************************************************************/
+
+static int bb_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ struct bb_priv *priv = board->private_data;
+ unsigned long flags;
+ int retval = 0;
+
+ ACT_LED_ON;
+ SET_DIR_READ(priv);
+
+ dbg_printk(2, "board: %p lock %d length: %zu\n",
+ board, mutex_is_locked(&board->user_mutex), length);
+
+ priv->end = 0;
+ priv->count = 0;
+ priv->rbuf = buffer;
+ if (length == 0)
+ goto read_end;
+ priv->request = length;
+ priv->eos_check = (priv->eos_flags & REOS) == 0; /* do eos check */
+ priv->eos_check_8 = priv->eos_flags & BIN; /* over 8 bits */
+ priv->eos_mask_7 = priv->eos & 0x7f; /* with this 7 bit eos */
+
+ dbg_printk(3, ".........." LINFMT "\n", LINVAL);
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+ priv->dav_mode = 1;
+ priv->dav_rx = 1;
+ ENABLE_IRQ(priv->irq_DAV, IRQ_TYPE_LEVEL_LOW);
+ priv->end_flag = 0;
+ gpiod_set_value(NRFD, 1); // ready for data
+ priv->r_busy = 1;
+ priv->phase = 100;
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+
+ /* wait for the interrupt routines finish their work */
+
+ retval = wait_event_interruptible(board->wait,
+ (priv->end_flag || board->status & TIMO));
+
+ dbg_printk(3, "awake from wait queue: %d\n", retval);
+
+ if (retval == 0 && board->status & TIMO) {
+ retval = -ETIMEDOUT;
+ dbg_printk(1, "timeout\n");
+ } else if (retval) {
+ retval = -ERESTARTSYS;
+ }
+
+ DISABLE_IRQ(priv->irq_DAV);
+ spin_lock_irqsave(&priv->rw_lock, flags);
+ gpiod_set_value(NRFD, 0); // DIR_READ line state
+ priv->r_busy = 0;
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+
+read_end:
+ ACT_LED_OFF;
+ *bytes_read = priv->count;
+ *end = priv->end;
+ priv->r_busy = 0;
+ dbg_printk(2, "return: %d eoi|eos: %d count: %d\n\n", retval, priv->end, priv->count);
+ return retval;
+}
+
+/***************************************************************************
+ * *
+ * READ interrupt routine (DAV line) *
+ * *
+ ***************************************************************************/
+
+static irqreturn_t bb_DAV_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct bb_priv *priv = board->private_data;
+ int val;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+
+ priv->all_irqs++;
+
+ if (priv->dav_mode) {
+ ENABLE_IRQ(priv->irq_DAV, IRQ_TYPE_EDGE_BOTH);
+ priv->dav_mode = 0;
+ }
+
+ if (priv->r_busy == 0) {
+ dbg_printk(1, "interrupt while idle after %d at %d\n",
+ priv->count, priv->phase);
+ priv->dav_idle++;
+ priv->phase = 200;
+ goto dav_exit; /* idle */
+ }
+
+ val = gpiod_get_value(DAV);
+ if (val == priv->dav_rx) {
+ dbg_printk(1, "out of order DAV interrupt %d/%d after %zu/%zu at %d cmd %d "
+ LINFMT ".\n", val, priv->dav_rx, priv->w_cnt, priv->length,
+ priv->phase, priv->cmd, LINVAL);
+ priv->dav_seq++;
+ }
+ priv->dav_rx = val;
+
+ dbg_printk(3, "> irq: %d DAV: %d st: %4lx dir: %d busy: %d:%d\n",
+ irq, val, board->status, priv->direction, priv->r_busy, priv->w_busy);
+
+ if (val == 0) {
+ gpiod_set_value(NRFD, 0); // not ready for data
+ priv->rbuf[priv->count++] = get_data_lines();
+ priv->end = !gpiod_get_value(EOI);
+ gpiod_set_value(NDAC, 1); // data accepted
+ priv->end |= check_for_eos(priv, priv->rbuf[priv->count - 1]);
+ priv->end_flag = ((priv->count >= priv->request) || priv->end);
+ priv->phase = 210;
+ } else {
+ gpiod_set_value(NDAC, 0); // data not accepted
+ if (priv->end_flag) {
+ priv->r_busy = 0;
+ wake_up_interruptible(&board->wait);
+ priv->phase = 220;
+ } else {
+ gpiod_set_value(NRFD, 1); // ready for data
+ priv->phase = 230;
+ }
+ }
+
+dav_exit:
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+ dbg_printk(3, "< irq: %d count %d\n", irq, priv->count);
+ return IRQ_HANDLED;
+}
+
+/***************************************************************************
+ * *
+ * WRITE *
+ * *
+ ***************************************************************************/
+
+static int bb_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ unsigned long flags;
+ int retval = 0;
+
+ struct bb_priv *priv = board->private_data;
+
+ ACT_LED_ON;
+
+ priv->w_cnt = 0;
+ priv->w_buf = buffer;
+ dbg_printk(2, "board %p lock %d length: %zu\n",
+ board, mutex_is_locked(&board->user_mutex), length);
+
+ if (debug > 1)
+ bb_buffer_print(buffer, length, priv->cmd, send_eoi);
+ priv->count = 0;
+ priv->phase = 300;
+
+ if (length == 0)
+ goto write_end;
+ priv->end = send_eoi;
+ priv->length = length;
+
+ SET_DIR_WRITE(priv);
+
+ dbg_printk(2, "Enabling interrupts - NRFD: %d NDAC: %d\n",
+ gpiod_get_value(NRFD), gpiod_get_value(NDAC));
+
+ if (gpiod_get_value(NRFD) && gpiod_get_value(NDAC)) { /* check for listener */
+ retval = -ENODEV;
+ goto write_end;
+ }
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+ priv->w_busy = 1; /* make the interrupt routines active */
+ priv->write_done = 0;
+ priv->nrfd_mode = 1;
+ priv->ndac_mode = 1;
+ priv->dav_tx = 1;
+ ENABLE_IRQ(priv->irq_NDAC, IRQ_TYPE_LEVEL_HIGH);
+ ENABLE_IRQ(priv->irq_NRFD, IRQ_TYPE_LEVEL_HIGH);
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+
+ /* wait for the interrupt routines finish their work */
+
+ retval = wait_event_interruptible(board->wait,
+ priv->write_done || (board->status & TIMO));
+
+ dbg_printk(3, "awake from wait queue: %d\n", retval);
+
+ if (retval == 0) {
+ if (board->status & TIMO) {
+ retval = -ETIMEDOUT;
+ dbg_printk(1, "timeout after %zu/%zu at %d " LINFMT " eoi: %d\n",
+ priv->w_cnt, length, priv->phase, LINVAL, send_eoi);
+ } else {
+ // dbg_printk(1,"written %zu\n", priv->w_cnt);
+ retval = priv->w_cnt;
+ }
+ } else {
+ retval = -ERESTARTSYS;
+ }
+
+ DISABLE_IRQ(priv->irq_NRFD);
+ DISABLE_IRQ(priv->irq_NDAC);
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+ priv->w_busy = 0;
+ gpiod_set_value(DAV, 1); // DIR_WRITE line state
+ gpiod_set_value(EOI, 1); // De-assert EOI (in case)
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+
+write_end:
+ *bytes_written = priv->w_cnt;
+ ACT_LED_OFF;
+ dbg_printk(2, "sent %zu bytes\r\n\r\n", *bytes_written);
+ priv->phase = 310;
+ return retval;
+}
+
+/***************************************************************************
+ * *
+ * WRITE interrupt routine (NRFD line) *
+ * *
+ ***************************************************************************/
+
+static irqreturn_t bb_NRFD_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct bb_priv *priv = board->private_data;
+ unsigned long flags;
+ int nrfd;
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+
+ nrfd = gpiod_get_value(NRFD);
+ priv->all_irqs++;
+
+ dbg_printk(3, "> irq: %d NRFD: %d NDAC: %d st: %4lx dir: %d busy: %d:%d\n",
+ irq, nrfd, gpiod_get_value(NDAC), board->status, priv->direction,
+ priv->w_busy, priv->r_busy);
+
+ if (priv->nrfd_mode) {
+ ENABLE_IRQ(priv->irq_NRFD, IRQ_TYPE_EDGE_RISING);
+ priv->nrfd_mode = 0;
+ }
+
+ if (priv->w_busy == 0) {
+ dbg_printk(1, "interrupt while idle after %zu/%zu at %d\n",
+ priv->w_cnt, priv->length, priv->phase);
+ priv->nrfd_idle++;
+ goto nrfd_exit; /* idle */
+ }
+ if (nrfd == 0) {
+ dbg_printk(1, "out of order interrupt after %zu/%zu at %d cmd %d " LINFMT ".\n",
+ priv->w_cnt, priv->length, priv->phase, priv->cmd, LINVAL);
+ priv->phase = 400;
+ priv->nrfd_seq++;
+ goto nrfd_exit;
+ }
+ if (!priv->dav_tx) {
+ dbg_printk(1, "DAV low after %zu/%zu cmd %d " LINFMT ". No action.\n",
+ priv->w_cnt, priv->length, priv->cmd, LINVAL);
+ priv->dav_seq++;
+ goto nrfd_exit;
+ }
+
+ if (priv->atn_asserted && priv->w_cnt >= priv->length) { // test for end of transfer
+ priv->write_done = 1;
+ priv->w_busy = 0;
+ wake_up_interruptible(&board->wait);
+ goto nrfd_exit;
+ }
+
+ dbg_printk(3, "sending %zu\n", priv->w_cnt);
+
+ set_data_lines(priv->w_buf[priv->w_cnt++]); // put the data on the lines
+
+ if (priv->w_cnt == priv->length && priv->end) {
+ dbg_printk(3, "Asserting EOI\n");
+ gpiod_set_value(EOI, 0); // Assert EOI
+ }
+
+ gpiod_set_value(DAV, 0); // Data available
+ priv->dav_tx = 0;
+ priv->phase = 410;
+
+nrfd_exit:
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+/***************************************************************************
+ * *
+ * WRITE interrupt routine (NDAC line) *
+ * *
+ ***************************************************************************/
+
+static irqreturn_t bb_NDAC_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct bb_priv *priv = board->private_data;
+ unsigned long flags;
+ int ndac;
+
+ spin_lock_irqsave(&priv->rw_lock, flags);
+
+ ndac = gpiod_get_value(NDAC);
+ priv->all_irqs++;
+ dbg_printk(3, "> irq: %d NRFD: %d NDAC: %d st: %4lx dir: %d busy: %d:%d\n",
+ irq, gpiod_get_value(NRFD), ndac, board->status, priv->direction,
+ priv->w_busy, priv->r_busy);
+
+ if (priv->ndac_mode) {
+ ENABLE_IRQ(priv->irq_NDAC, IRQ_TYPE_EDGE_RISING);
+ priv->ndac_mode = 0;
+ }
+
+ if (priv->w_busy == 0) {
+ dbg_printk(1, "interrupt while idle.\n");
+ priv->ndac_idle++;
+ goto ndac_exit;
+ }
+ if (ndac == 0) {
+ dbg_printk(1, "out of order interrupt at %zu:%d.\n", priv->w_cnt, priv->phase);
+ priv->phase = 500;
+ priv->ndac_seq++;
+ goto ndac_exit;
+ }
+ if (priv->dav_tx) {
+ dbg_printk(1, "DAV high after %zu/%zu cmd %d " LINFMT ". No action.\n",
+ priv->w_cnt, priv->length, priv->cmd, LINVAL);
+ priv->dav_seq++;
+ goto ndac_exit;
+ }
+
+ dbg_printk(3, "accepted %zu\n", priv->w_cnt - 1);
+
+ if (!priv->atn_asserted && priv->w_cnt >= priv->length) { // test for end of transfer
+ priv->write_done = 1;
+ priv->w_busy = 0;
+ wake_up_interruptible(&board->wait);
+ } else {
+ gpiod_set_value(DAV, 1); // Data not available
+ priv->dav_tx = 1;
+ priv->phase = 510;
+ }
+
+ndac_exit:
+ spin_unlock_irqrestore(&priv->rw_lock, flags);
+ return IRQ_HANDLED;
+}
+
+/***************************************************************************
+ * *
+ * interrupt routine for SRQ line *
+ * *
+ ***************************************************************************/
+
+static irqreturn_t bb_SRQ_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+
+ int val = gpiod_get_value(SRQ);
+
+ dbg_printk(3, "> %d st: %4lx\n", val, board->status);
+
+ if (!val)
+ set_bit(SRQI_NUM, &board->status); /* set_bit() is atomic */
+
+ wake_up_interruptible(&board->wait);
+
+ return IRQ_HANDLED;
+}
+
+static int bb_command(gpib_board_t *board, uint8_t *buffer,
+ size_t length, size_t *bytes_written)
+{
+ size_t ret;
+ struct bb_priv *priv = board->private_data;
+ int i;
+
+ dbg_printk(2, "%p %p\n", buffer, board->buffer);
+
+ /* the _ATN line has already been asserted by bb_take_control() */
+
+ priv->cmd = 1;
+
+ ret = bb_write(board, buffer, length, 0, bytes_written); // no eoi
+
+ for (i = 0; i < length; i++) {
+ if (buffer[i] == UNT) {
+ priv->talker_state = talker_idle;
+ } else {
+ if (buffer[i] == UNL) {
+ priv->listener_state = listener_idle;
+ } else {
+ if (buffer[i] == (MTA(board->pad))) {
+ priv->talker_state = talker_addressed;
+ priv->listener_state = listener_idle;
+ } else if (buffer[i] == (MLA(board->pad))) {
+ priv->listener_state = listener_addressed;
+ priv->talker_state = talker_idle;
+ }
+ }
+ }
+ }
+
+ /* the _ATN line will be released by bb_go_to_stby */
+
+ priv->cmd = 0;
+
+ return ret;
+}
+
+/***************************************************************************
+ * *
+ * Buffer print with decode for debug/trace *
+ * *
+ ***************************************************************************/
+
+static char *cmd_string[32] = {
+ "", // 0x00
+ "GTL", // 0x01
+ "", // 0x02
+ "", // 0x03
+ "SDC", // 0x04
+ "PPC", // 0x05
+ "", // 0x06
+ "", // 0x07
+ "GET", // 0x08
+ "TCT", // 0x09
+ "", // 0x0a
+ "", // 0x0b
+ "", // 0x0c
+ "", // 0x0d
+ "", // 0x0e
+ "", // 0x0f
+ "", // 0x10
+ "LLO", // 0x11
+ "", // 0x12
+ "", // 0x13
+ "DCL", // 0x14
+ "PPU", // 0x15
+ "", // 0x16
+ "", // 0x17
+ "SPE", // 0x18
+ "SPD", // 0x19
+ "", // 0x1a
+ "", // 0x1b
+ "", // 0x1c
+ "", // 0x1d
+ "", // 0x1e
+ "CFE" // 0x1f
+};
+
+static void bb_buffer_print(unsigned char *buffer, size_t length, int cmd, int eoi)
+{
+ int i;
+
+ if (cmd) {
+ dbg_printk(2, "<cmd len %zu>\n", length);
+ for (i = 0; i < length; i++) {
+ if (buffer[i] < 0x20) {
+ dbg_printk(3, "0x%x=%s\n", buffer[i], cmd_string[buffer[i]]);
+ } else if (buffer[i] == 0x3f) {
+ dbg_printk(3, "0x%x=%s\n", buffer[i], "UNL");
+ } else if (buffer[i] == 0x5f) {
+ dbg_printk(3, "0x%x=%s\n", buffer[i], "UNT");
+ } else if (buffer[i] < 0x60) {
+ dbg_printk(3, "0x%x=%s%d\n", buffer[i],
+ (buffer[i] & 0x40) ? "TLK" : "LSN", buffer[i] & 0x1F);
+ } else {
+ dbg_printk(3, "0x%x\n", buffer[i]);
+ }
+ }
+ } else {
+ dbg_printk(2, "<data len %zu %s>\n", length, (eoi) ? "w.EOI" : " ");
+ for (i = 0; i < length; i++)
+ dbg_printk(2, "%3d 0x%x->%c\n", i, buffer[i], printable(buffer[i]));
+ }
+}
+
+/***************************************************************************
+ * *
+ * STATUS Management *
+ * *
+ ***************************************************************************/
+static void set_atn(struct bb_priv *priv, int atn_asserted)
+{
+ if (priv->listener_state != listener_idle &&
+ priv->talker_state != talker_idle) {
+ dbg_printk(0, "listener/talker state machine conflict\n");
+ }
+ if (atn_asserted) {
+ if (priv->listener_state == listener_active)
+ priv->listener_state = listener_addressed;
+ if (priv->talker_state == talker_active)
+ priv->talker_state = talker_addressed;
+ } else {
+ if (priv->listener_state == listener_addressed) {
+ priv->listener_state = listener_active;
+ SET_DIR_READ(priv); // make sure holdoff is active when we unassert ATN
+ }
+ if (priv->talker_state == talker_addressed)
+ priv->talker_state = talker_active;
+ }
+ gpiod_direction_output(_ATN, !atn_asserted);
+ priv->atn_asserted = atn_asserted;
+}
+
+static int bb_take_control(gpib_board_t *board, int synchronous)
+{
+ dbg_printk(2, "%d\n", synchronous);
+ set_atn(board->private_data, 1);
+ set_bit(CIC_NUM, &board->status);
+ return 0;
+}
+
+static int bb_go_to_standby(gpib_board_t *board)
+{
+ dbg_printk(2, "\n");
+ set_atn(board->private_data, 0);
+ return 0;
+}
+
+static void bb_request_system_control(gpib_board_t *board, int request_control)
+{
+ dbg_printk(2, "%d\n", request_control);
+ if (request_control) {
+ set_bit(CIC_NUM, &board->status);
+ // drive DAV & EOI false, enable NRFD & NDAC irqs
+ SET_DIR_WRITE(board->private_data);
+ } else {
+ clear_bit(CIC_NUM, &board->status);
+ }
+}
+
+static void bb_interface_clear(gpib_board_t *board, int assert)
+{
+ struct bb_priv *priv = board->private_data;
+
+ dbg_printk(2, "%d\n", assert);
+ if (assert) {
+ gpiod_direction_output(IFC, 0);
+ priv->talker_state = talker_idle;
+ priv->listener_state = listener_idle;
+ } else {
+ gpiod_direction_output(IFC, 1);
+ }
+}
+
+static void bb_remote_enable(gpib_board_t *board, int enable)
+{
+ dbg_printk(2, "%d\n", enable);
+ if (enable) {
+ set_bit(REM_NUM, &board->status);
+ gpiod_direction_output(REN, 0);
+ } else {
+ clear_bit(REM_NUM, &board->status);
+ gpiod_direction_output(REN, 1);
+ }
+}
+
+static int bb_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct bb_priv *priv = board->private_data;
+
+ dbg_printk(2, "%s\n", "EOS_en");
+ priv->eos = eos_byte;
+ priv->eos_flags = REOS;
+ if (compare_8_bits)
+ priv->eos_flags |= BIN;
+
+ return 0;
+}
+
+static void bb_disable_eos(gpib_board_t *board)
+{
+ struct bb_priv *priv = board->private_data;
+
+ dbg_printk(2, "\n");
+ priv->eos_flags &= ~REOS;
+}
+
+static unsigned int bb_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct bb_priv *priv = board->private_data;
+
+ board->status &= ~clear_mask;
+
+ if (gpiod_get_value(SRQ)) /* SRQ asserted low */
+ clear_bit(SRQI_NUM, &board->status);
+ else
+ set_bit(SRQI_NUM, &board->status);
+ if (gpiod_get_value(_ATN)) /* ATN asserted low */
+ clear_bit(ATN_NUM, &board->status);
+ else
+ set_bit(ATN_NUM, &board->status);
+ if (priv->talker_state == talker_active ||
+ priv->talker_state == talker_addressed)
+ set_bit(TACS_NUM, &board->status);
+ else
+ clear_bit(TACS_NUM, &board->status);
+
+ if (priv->listener_state == listener_active ||
+ priv->listener_state == listener_addressed)
+ set_bit(LACS_NUM, &board->status);
+ else
+ clear_bit(LACS_NUM, &board->status);
+
+ dbg_printk(2, "0x%lx mask 0x%x\n", board->status, clear_mask);
+
+ return board->status;
+}
+
+static int bb_primary_address(gpib_board_t *board, unsigned int address)
+{
+ dbg_printk(2, "%d\n", address);
+ board->pad = address;
+ return 0;
+}
+
+static int bb_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ dbg_printk(2, "%d %d\n", address, enable);
+ if (enable)
+ board->sad = address;
+ return 0;
+}
+
+static int bb_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ dbg_printk(1, "%s\n", "not implemented");
+ return -EPERM;
+}
+
+static void bb_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ dbg_printk(1, "%s\n", "not implemented");
+}
+
+static void bb_parallel_poll_response(gpib_board_t *board, int ist)
+{
+}
+
+static void bb_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ dbg_printk(1, "%s\n", "not implemented");
+}
+
+static uint8_t bb_serial_poll_status(gpib_board_t *board)
+{
+ dbg_printk(1, "%s\n", "not implemented");
+ return 0; // -ENOSYS;
+}
+
+static unsigned int bb_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct bb_priv *priv = board->private_data;
+
+ if (nano_sec <= 350)
+ priv->t1_delay = 350;
+ else if (nano_sec <= 1100)
+ priv->t1_delay = 1100;
+ else
+ priv->t1_delay = 2000;
+
+ dbg_printk(2, "t1 delay set to %d nanosec\n", priv->t1_delay);
+
+ return priv->t1_delay;
+}
+
+static void bb_return_to_local(gpib_board_t *board)
+{
+ dbg_printk(1, "%s\n", "not implemented");
+}
+
+static int bb_line_status(const gpib_board_t *board)
+{
+ int line_status = ValidALL;
+
+// dbg_printk(1,"\n");
+
+ if (gpiod_get_value(REN) == 0)
+ line_status |= BusREN;
+ if (gpiod_get_value(IFC) == 0)
+ line_status |= BusIFC;
+ if (gpiod_get_value(NDAC) == 0)
+ line_status |= BusNDAC;
+ if (gpiod_get_value(NRFD) == 0)
+ line_status |= BusNRFD;
+ if (gpiod_get_value(DAV) == 0)
+ line_status |= BusDAV;
+ if (gpiod_get_value(EOI) == 0)
+ line_status |= BusEOI;
+ if (gpiod_get_value(_ATN) == 0)
+ line_status |= BusATN;
+ if (gpiod_get_value(SRQ) == 0)
+ line_status |= BusSRQ;
+
+ dbg_printk(2, "status lines: %4x\n", line_status);
+
+ return line_status;
+}
+
+/***************************************************************************
+ * *
+ * Module Management *
+ * *
+ ***************************************************************************/
+
+static int allocate_private(gpib_board_t *board)
+{
+ board->private_data = kzalloc(sizeof(struct bb_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ return 0;
+}
+
+static void free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+static int bb_get_irq(gpib_board_t *board, char *name,
+ struct gpio_desc *gpio, int *irq,
+ irq_handler_t handler, irq_handler_t thread_fn, unsigned long flags)
+{
+ if (!gpio)
+ return -1;
+ gpiod_direction_input(gpio);
+ *irq = gpiod_to_irq(gpio);
+ dbg_printk(2, "IRQ %s: %d\n", name, *irq);
+ if (*irq < 0) {
+ dbg_printk(0, "gpib: can't get IRQ for %s\n", name);
+ return -1;
+ }
+ if (request_threaded_irq(*irq, handler, thread_fn, flags, name, board)) {
+ dbg_printk(0, "gpib: can't request IRQ for %s %d\n", name, *irq);
+ *irq = 0;
+ return -1;
+ }
+ DISABLE_IRQ(*irq);
+ return 0;
+}
+
+static void bb_free_irq(gpib_board_t *board, int *irq, char *name)
+{
+ if (*irq) {
+ free_irq(*irq, board);
+ dbg_printk(2, "IRQ %d(%s) freed\n", *irq, name);
+ *irq = 0;
+ }
+}
+
+static void release_gpios(void)
+{
+ int j;
+
+ for (j = 0 ; j < NUM_PINS ; j++) {
+ if (all_descriptors[j]) {
+ gpiod_put(all_descriptors[j]);
+ all_descriptors[j] = 0;
+ }
+ }
+}
+
+static int allocate_gpios(gpib_board_t *board)
+{
+ int j, retval = 0;
+ bool error = false;
+ int table_index = 0;
+ char name[256];
+ struct gpio_desc *desc;
+ struct gpiod_lookup_table *lookup_table;
+
+ if (!board->gpib_dev) {
+ pr_err("NULL gpib dev for board\n");
+ return -ENOENT;
+ }
+
+ lookup_table = lookup_tables[0];
+ lookup_table->dev_id = dev_name(board->gpib_dev);
+ gpiod_add_lookup_table(lookup_table);
+ dbg_printk(1, "Allocating gpios using table index %d\n", table_index);
+
+ for (j = 0 ; j < NUM_PINS ; j++) {
+ if (gpios_vector[j] < 0)
+ continue;
+ /* name not really used in gpiod_get_index() */
+ sprintf(name, "GPIO%d", gpios_vector[j]);
+try_again:
+ dbg_printk(1, "Allocating gpio %s pin no %d\n", name, gpios_vector[j]);
+ desc = gpiod_get_index(board->gpib_dev, name, gpios_vector[j], GPIOD_IN);
+
+ if (IS_ERR(desc)) {
+ gpiod_remove_lookup_table(lookup_table);
+ table_index++;
+ lookup_table = lookup_tables[table_index];
+ if (lookup_table) {
+ dbg_printk(1, "Allocation failed, now using table_index %d\n",
+ table_index);
+ lookup_table->dev_id = dev_name(board->gpib_dev);
+ gpiod_add_lookup_table(lookup_table);
+ goto try_again;
+ }
+ dbg_printk(0, "Unable to obtain gpio descriptor for pin %d error %ld\n",
+ gpios_vector[j], PTR_ERR(desc));
+ error = true;
+ break;
+ }
+ all_descriptors[j] = desc;
+ }
+
+ if (error) { /* undo what already done */
+ release_gpios();
+ retval = -1;
+ }
+ if (lookup_table)
+ gpiod_remove_lookup_table(lookup_table);
+ // Initialize LED trigger
+ led_trigger_register_simple("gpib", &ledtrig_gpib);
+ return retval;
+}
+
+static void bb_detach(gpib_board_t *board)
+{
+ struct bb_priv *priv = board->private_data;
+
+ dbg_printk(2, "Enter with data %p\n", board->private_data);
+ if (!board->private_data)
+ return;
+
+ led_trigger_unregister_simple(ledtrig_gpib);
+
+ bb_free_irq(board, &priv->irq_DAV, NAME "_DAV");
+ bb_free_irq(board, &priv->irq_NRFD, NAME "_NRFD");
+ bb_free_irq(board, &priv->irq_NDAC, NAME "_NDAC");
+ bb_free_irq(board, &priv->irq_SRQ, NAME "_SRQ");
+
+ if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA */
+ gpiod_set_value(YOGA_ENABLE, 0);
+ }
+
+ release_gpios();
+
+ dbg_printk(2, "detached board: %d\n", board->minor);
+ dbg_printk(0, "NRFD: idle %d, seq %d, NDAC: idle %d, seq %d DAV: idle %d seq: %d all: %ld",
+ priv->nrfd_idle, priv->nrfd_seq,
+ priv->ndac_idle, priv->ndac_seq,
+ priv->dav_idle, priv->dav_seq, priv->all_irqs);
+
+ free_private(board);
+}
+
+static int bb_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct bb_priv *priv;
+ int retval = 0;
+
+ dbg_printk(2, "%s\n", "Enter ...");
+
+ board->status = 0;
+
+ if (allocate_private(board))
+ return -ENOMEM;
+ priv = board->private_data;
+ priv->direction = -1;
+ priv->t1_delay = 2000;
+ priv->listener_state = listener_idle;
+ priv->talker_state = talker_idle;
+
+ sn7516x = sn7516x_used;
+ if (strcmp(PINMAP_0, pin_map) == 0) {
+ if (!sn7516x) {
+ gpios_vector[&(PE) - &all_descriptors[0]] = -1;
+ gpios_vector[&(DC) - &all_descriptors[0]] = -1;
+ gpios_vector[&(TE) - &all_descriptors[0]] = -1;
+ }
+ } else if (strcmp(PINMAP_1, pin_map) == 0) {
+ if (!sn7516x) {
+ gpios_vector[&(PE) - &all_descriptors[0]] = -1;
+ gpios_vector[&(DC) - &all_descriptors[0]] = -1;
+ gpios_vector[&(TE) - &all_descriptors[0]] = -1;
+ }
+ gpios_vector[&(REN) - &all_descriptors[0]] = 0; /* 27 -> 0 REN on GPIB pin 0 */
+ } else if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA */
+ sn7516x = 0;
+ gpios_vector[&(D03) - &all_descriptors[0]] = YOGA_D03_pin_nr;
+ gpios_vector[&(D04) - &all_descriptors[0]] = YOGA_D04_pin_nr;
+ gpios_vector[&(D05) - &all_descriptors[0]] = YOGA_D05_pin_nr;
+ gpios_vector[&(D06) - &all_descriptors[0]] = YOGA_D06_pin_nr;
+ gpios_vector[&(PE) - &all_descriptors[0]] = -1;
+ gpios_vector[&(DC) - &all_descriptors[0]] = -1;
+ gpios_vector[&(ACT_LED) - &all_descriptors[0]] = -1;
+ } else {
+ dbg_printk(0, "Unrecognized pin mapping.\n");
+ goto bb_attach_fail;
+ }
+ dbg_printk(0, "Using pin map \"%s\" %s\n", pin_map, (sn7516x) ?
+ " with SN7516x driver support" : "");
+
+ if (allocate_gpios(board))
+ goto bb_attach_fail;
+
+/* Configure SN7516X control lines.
+ * drive ATN, IFC and REN as outputs only when master
+ * i.e. system controller. In this mode can only be the CIC
+ * When not master then enable device mode ATN, IFC & REN as inputs
+ */
+ if (sn7516x) {
+ gpiod_direction_output(DC, 0);
+ gpiod_direction_output(TE, 1);
+ gpiod_direction_output(PE, 1);
+ }
+
+ if (strcmp(PINMAP_2, pin_map) == 0) { /* YOGA: enable level shifters */
+ gpiod_direction_output(YOGA_ENABLE, 1);
+ }
+
+ spin_lock_init(&priv->rw_lock);
+
+ /* request DAV interrupt for read */
+ if (bb_get_irq(board, NAME "_DAV", DAV, &priv->irq_DAV, bb_DAV_interrupt, NULL,
+ IRQF_TRIGGER_NONE))
+ goto bb_attach_fail_r;
+
+ /* request NRFD interrupt for write */
+ if (bb_get_irq(board, NAME "_NRFD", NRFD, &priv->irq_NRFD, bb_NRFD_interrupt, NULL,
+ IRQF_TRIGGER_NONE))
+ goto bb_attach_fail_r;
+
+ /* request NDAC interrupt for write */
+ if (bb_get_irq(board, NAME "_NDAC", NDAC, &priv->irq_NDAC, bb_NDAC_interrupt, NULL,
+ IRQF_TRIGGER_NONE))
+ goto bb_attach_fail_r;
+
+ /* request SRQ interrupt for Service Request */
+ if (bb_get_irq(board, NAME "_SRQ", SRQ, &priv->irq_SRQ, bb_SRQ_interrupt, NULL,
+ IRQF_TRIGGER_NONE))
+ goto bb_attach_fail_r;
+
+ ENABLE_IRQ(priv->irq_SRQ, IRQ_TYPE_EDGE_FALLING);
+
+ dbg_printk(0, "attached board %d\n", board->minor);
+ goto bb_attach_out;
+
+bb_attach_fail_r:
+ release_gpios();
+bb_attach_fail:
+ retval = -1;
+bb_attach_out:
+ return retval;
+}
+
+gpib_interface_t bb_interface = {
+name: NAME,
+attach : bb_attach,
+detach : bb_detach,
+read : bb_read,
+write : bb_write,
+command : bb_command,
+take_control : bb_take_control,
+go_to_standby : bb_go_to_standby,
+request_system_control : bb_request_system_control,
+interface_clear : bb_interface_clear,
+remote_enable : bb_remote_enable,
+enable_eos : bb_enable_eos,
+disable_eos : bb_disable_eos,
+parallel_poll : bb_parallel_poll,
+parallel_poll_configure : bb_parallel_poll_configure,
+parallel_poll_response : bb_parallel_poll_response,
+line_status : bb_line_status,
+update_status : bb_update_status,
+primary_address : bb_primary_address,
+secondary_address : bb_secondary_address,
+serial_poll_response : bb_serial_poll_response,
+serial_poll_status : bb_serial_poll_status,
+t1_delay : bb_t1_delay,
+return_to_local : bb_return_to_local,
+};
+
+static int __init bb_init_module(void)
+{
+ gpib_register_driver(&bb_interface, THIS_MODULE);
+
+ dbg_printk(0, "module loaded with pin map \"%s\"%s\n",
+ pin_map, (sn7516x_used) ? " and SN7516x driver support" : "");
+ return 0;
+}
+
+static void __exit bb_exit_module(void)
+{
+ dbg_printk(0, "module unloaded!");
+
+ gpib_unregister_driver(&bb_interface);
+}
+
+module_init(bb_init_module);
+module_exit(bb_exit_module);
+
+/***************************************************************************
+ * *
+ * UTILITY Functions *
+ * *
+ ***************************************************************************/
+inline long usec_diff(struct timespec64 *a, struct timespec64 *b)
+{
+ return ((a->tv_sec - b->tv_sec) * 1000000 +
+ (a->tv_nsec - b->tv_nsec) / 1000);
+}
+
+static inline int check_for_eos(struct bb_priv *priv, uint8_t byte)
+{
+ if (priv->eos_check)
+ return 0;
+
+ if (priv->eos_check_8) {
+ if (priv->eos == byte)
+ return 1;
+ } else {
+ if (priv->eos_mask_7 == (byte & 0x7f))
+ return 1;
+ }
+ return 0;
+}
+
+static void set_data_lines_output(void)
+{
+ gpiod_direction_output(D01, 1);
+ gpiod_direction_output(D02, 1);
+ gpiod_direction_output(D03, 1);
+ gpiod_direction_output(D04, 1);
+ gpiod_direction_output(D05, 1);
+ gpiod_direction_output(D06, 1);
+ gpiod_direction_output(D07, 1);
+ gpiod_direction_output(D08, 1);
+}
+
+static void set_data_lines(u8 byte)
+{
+ gpiod_set_value(D01, !(byte & 0x01));
+ gpiod_set_value(D02, !(byte & 0x02));
+ gpiod_set_value(D03, !(byte & 0x04));
+ gpiod_set_value(D04, !(byte & 0x08));
+ gpiod_set_value(D05, !(byte & 0x10));
+ gpiod_set_value(D06, !(byte & 0x20));
+ gpiod_set_value(D07, !(byte & 0x40));
+ gpiod_set_value(D08, !(byte & 0x80));
+}
+
+static u8 get_data_lines(void)
+{
+ u8 ret;
+
+ ret = gpiod_get_value(D01);
+ ret |= gpiod_get_value(D02) << 1;
+ ret |= gpiod_get_value(D03) << 2;
+ ret |= gpiod_get_value(D04) << 3;
+ ret |= gpiod_get_value(D05) << 4;
+ ret |= gpiod_get_value(D06) << 5;
+ ret |= gpiod_get_value(D07) << 6;
+ ret |= gpiod_get_value(D08) << 7;
+ return ~ret;
+}
+
+static void set_data_lines_input(void)
+{
+ gpiod_direction_input(D01);
+ gpiod_direction_input(D02);
+ gpiod_direction_input(D03);
+ gpiod_direction_input(D04);
+ gpiod_direction_input(D05);
+ gpiod_direction_input(D06);
+ gpiod_direction_input(D07);
+ gpiod_direction_input(D08);
+}
+
+static inline void SET_DIR_WRITE(struct bb_priv *priv)
+{
+ if (priv->direction == DIR_WRITE)
+ return;
+
+ gpiod_direction_input(NRFD);
+ gpiod_direction_input(NDAC);
+ set_data_lines_output();
+ gpiod_direction_output(DAV, 1);
+ gpiod_direction_output(EOI, 1);
+
+ if (sn7516x) {
+ gpiod_set_value(PE, 1); /* set data lines to transmit on sn75160b */
+ gpiod_set_value(TE, 1); /* set NDAC and NRFD to receive and DAV to transmit */
+ }
+
+ priv->direction = DIR_WRITE;
+}
+
+static inline void SET_DIR_READ(struct bb_priv *priv)
+{
+ if (priv->direction == DIR_READ)
+ return;
+
+ gpiod_direction_input(DAV);
+ gpiod_direction_input(EOI);
+
+ set_data_lines_input();
+
+ if (sn7516x) {
+ gpiod_set_value(PE, 0); /* set data lines to receive on sn75160b */
+ gpiod_set_value(TE, 0); /* set NDAC and NRFD to transmit and DAV to receive */
+ }
+
+ gpiod_direction_output(NRFD, 0); // hold off the talker
+ gpiod_direction_output(NDAC, 0); // data not accepted
+
+ priv->direction = DIR_READ;
+}
diff --git a/drivers/staging/gpib/hp_82335/Makefile b/drivers/staging/gpib/hp_82335/Makefile
new file mode 100644
index 000000000000..8b7a552e9355
--- /dev/null
+++ b/drivers/staging/gpib/hp_82335/Makefile
@@ -0,0 +1,4 @@
+
+obj-m += hp82335.o
+
+
diff --git a/drivers/staging/gpib/hp_82335/hp82335.c b/drivers/staging/gpib/hp_82335/hp82335.c
new file mode 100644
index 000000000000..40afe42aea47
--- /dev/null
+++ b/drivers/staging/gpib/hp_82335/hp82335.c
@@ -0,0 +1,360 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess *
+ ***************************************************************************/
+
+/*should enable ATN interrupts (and update board->status on occurrence),
+ * implement recovery from bus errors (if necessary)
+ */
+
+#include "hp82335.h"
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/init.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for HP 82335 interface cards");
+
+static int hp82335_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void hp82335_detach(gpib_board_t *board);
+
+// wrappers for interface functions
+int hp82335_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read);
+}
+
+int hp82335_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int hp82335_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written);
+}
+
+int hp82335_take_control(gpib_board_t *board, int synchronous)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_take_control(board, &priv->tms9914_priv, synchronous);
+}
+
+int hp82335_go_to_standby(gpib_board_t *board)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_go_to_standby(board, &priv->tms9914_priv);
+}
+
+void hp82335_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_request_system_control(board, &priv->tms9914_priv, request_control);
+}
+
+void hp82335_interface_clear(gpib_board_t *board, int assert)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_interface_clear(board, &priv->tms9914_priv, assert);
+}
+
+void hp82335_remote_enable(gpib_board_t *board, int enable)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_remote_enable(board, &priv->tms9914_priv, enable);
+}
+
+int hp82335_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits);
+}
+
+void hp82335_disable_eos(gpib_board_t *board)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_disable_eos(board, &priv->tms9914_priv);
+}
+
+unsigned int hp82335_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_update_status(board, &priv->tms9914_priv, clear_mask);
+}
+
+int hp82335_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_primary_address(board, &priv->tms9914_priv, address);
+}
+
+int hp82335_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable);
+}
+
+int hp82335_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_parallel_poll(board, &priv->tms9914_priv, result);
+}
+
+void hp82335_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config);
+}
+
+void hp82335_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist);
+}
+
+void hp82335_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_serial_poll_response(board, &priv->tms9914_priv, status);
+}
+
+static uint8_t hp82335_serial_poll_status(gpib_board_t *board)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_serial_poll_status(board, &priv->tms9914_priv);
+}
+
+static int hp82335_line_status(const gpib_board_t *board)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_line_status(board, &priv->tms9914_priv);
+}
+
+static unsigned int hp82335_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec);
+}
+
+void hp82335_return_to_local(gpib_board_t *board)
+{
+ struct hp82335_priv *priv = board->private_data;
+
+ tms9914_return_to_local(board, &priv->tms9914_priv);
+}
+
+gpib_interface_t hp82335_interface = {
+name: "hp82335",
+attach : hp82335_attach,
+detach : hp82335_detach,
+read : hp82335_read,
+write : hp82335_write,
+command : hp82335_command,
+request_system_control : hp82335_request_system_control,
+take_control : hp82335_take_control,
+go_to_standby : hp82335_go_to_standby,
+interface_clear : hp82335_interface_clear,
+remote_enable : hp82335_remote_enable,
+enable_eos : hp82335_enable_eos,
+disable_eos : hp82335_disable_eos,
+parallel_poll : hp82335_parallel_poll,
+parallel_poll_configure : hp82335_parallel_poll_configure,
+parallel_poll_response : hp82335_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : hp82335_line_status,
+update_status : hp82335_update_status,
+primary_address : hp82335_primary_address,
+secondary_address : hp82335_secondary_address,
+serial_poll_response : hp82335_serial_poll_response,
+serial_poll_status : hp82335_serial_poll_status,
+t1_delay : hp82335_t1_delay,
+return_to_local : hp82335_return_to_local,
+};
+
+int hp82335_allocate_private(gpib_board_t *board)
+{
+ board->private_data = kzalloc(sizeof(struct hp82335_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ return 0;
+}
+
+void hp82335_free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+static inline unsigned int tms9914_to_hp82335_offset(unsigned int register_num)
+{
+ return 0x1ff8 + register_num;
+}
+
+static uint8_t hp82335_read_byte(struct tms9914_priv *priv, unsigned int register_num)
+{
+ return tms9914_iomem_read_byte(priv, tms9914_to_hp82335_offset(register_num));
+}
+
+static void hp82335_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num)
+{
+ tms9914_iomem_write_byte(priv, data, tms9914_to_hp82335_offset(register_num));
+}
+
+static void hp82335_clear_interrupt(struct hp82335_priv *hp_priv)
+{
+ struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
+
+ writeb(0, tms_priv->iobase + HPREG_INTR_CLEAR);
+}
+
+int hp82335_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct hp82335_priv *hp_priv;
+ struct tms9914_priv *tms_priv;
+ int retval;
+ const unsigned long upper_iomem_base = (unsigned long)config->ibbase + hp82335_rom_size;
+
+ board->status = 0;
+
+ if (hp82335_allocate_private(board))
+ return -ENOMEM;
+ hp_priv = board->private_data;
+ tms_priv = &hp_priv->tms9914_priv;
+ tms_priv->read_byte = hp82335_read_byte;
+ tms_priv->write_byte = hp82335_write_byte;
+ tms_priv->offset = 1;
+
+ switch ((unsigned long)(config->ibbase)) {
+ case 0xc4000:
+ case 0xc8000:
+ case 0xcc000:
+ case 0xd0000:
+ case 0xd4000:
+ case 0xd8000:
+ case 0xdc000:
+ case 0xe0000:
+ case 0xe4000:
+ case 0xe8000:
+ case 0xec000:
+ case 0xf0000:
+ case 0xf4000:
+ case 0xf8000:
+ case 0xfc000:
+ break;
+ default:
+ pr_err("hp82335: invalid base io address 0x%p\n", config->ibbase);
+ return -EINVAL;
+ }
+ if (!request_mem_region(upper_iomem_base, hp82335_upper_iomem_size, "hp82335")) {
+ pr_err("hp82335: failed to allocate io memory region 0x%lx-0x%lx\n",
+ upper_iomem_base, upper_iomem_base + hp82335_upper_iomem_size - 1);
+ return -EBUSY;
+ }
+ hp_priv->raw_iobase = upper_iomem_base;
+ tms_priv->iobase = ioremap(upper_iomem_base, hp82335_upper_iomem_size);
+ pr_info("hp82335: upper half of 82335 iomem region 0x%lx remapped to 0x%p\n",
+ hp_priv->raw_iobase, tms_priv->iobase);
+
+ retval = request_irq(config->ibirq, hp82335_interrupt, 0, "hp82335", board);
+ if (retval) {
+ pr_err("hp82335: can't request IRQ %d\n", config->ibirq);
+ return retval;
+ }
+ hp_priv->irq = config->ibirq;
+ pr_info("hp82335: IRQ %d\n", config->ibirq);
+
+ tms9914_board_reset(tms_priv);
+
+ hp82335_clear_interrupt(hp_priv);
+
+ writeb(INTR_ENABLE, tms_priv->iobase + HPREG_CCR);
+
+ tms9914_online(board, tms_priv);
+
+ return 0;
+}
+
+void hp82335_detach(gpib_board_t *board)
+{
+ struct hp82335_priv *hp_priv = board->private_data;
+ struct tms9914_priv *tms_priv;
+
+ if (hp_priv) {
+ tms_priv = &hp_priv->tms9914_priv;
+ if (hp_priv->irq)
+ free_irq(hp_priv->irq, board);
+ if (tms_priv->iobase) {
+ writeb(0, tms_priv->iobase + HPREG_CCR);
+ tms9914_board_reset(tms_priv);
+ iounmap((void *)tms_priv->iobase);
+ }
+ if (hp_priv->raw_iobase)
+ release_mem_region(hp_priv->raw_iobase, hp82335_upper_iomem_size);
+ }
+ hp82335_free_private(board);
+}
+
+static int __init hp82335_init_module(void)
+{
+ gpib_register_driver(&hp82335_interface, THIS_MODULE);
+ return 0;
+}
+
+static void __exit hp82335_exit_module(void)
+{
+ gpib_unregister_driver(&hp82335_interface);
+}
+
+module_init(hp82335_init_module);
+module_exit(hp82335_exit_module);
+
+/*
+ * GPIB interrupt service routines
+ */
+
+irqreturn_t hp82335_interrupt(int irq, void *arg)
+{
+ int status1, status2;
+ gpib_board_t *board = arg;
+ struct hp82335_priv *priv = board->private_data;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ status1 = read_byte(&priv->tms9914_priv, ISR0);
+ status2 = read_byte(&priv->tms9914_priv, ISR1);
+ hp82335_clear_interrupt(priv);
+ retval = tms9914_interrupt_have_status(board, &priv->tms9914_priv, status1, status2);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
diff --git a/drivers/staging/gpib/hp_82335/hp82335.h b/drivers/staging/gpib/hp_82335/hp82335.h
new file mode 100644
index 000000000000..5e5297af731a
--- /dev/null
+++ b/drivers/staging/gpib/hp_82335/hp82335.h
@@ -0,0 +1,85 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess *
+ ***************************************************************************/
+
+#ifndef _HP82335_H
+#define _HP82335_H
+
+#include "tms9914.h"
+#include "gpibP.h"
+
+// struct which defines private_data for board
+struct hp82335_priv {
+ struct tms9914_priv tms9914_priv;
+ unsigned int irq;
+ unsigned long raw_iobase;
+};
+
+// interfaces
+extern gpib_interface_t hp82335_interface;
+
+// interface functions
+int hp82335_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read);
+int hp82335_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+int hp82335_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written);
+int hp82335_take_control(gpib_board_t *board, int synchronous);
+int hp82335_go_to_standby(gpib_board_t *board);
+void hp82335_request_system_control(gpib_board_t *board, int request_control);
+void hp82335_interface_clear(gpib_board_t *board, int assert);
+void hp82335_remote_enable(gpib_board_t *board, int enable);
+int hp82335_enable_eos(gpib_board_t *board, uint8_t eos_byte, int
+ compare_8_bits);
+void hp82335_disable_eos(gpib_board_t *board);
+unsigned int hp82335_update_status(gpib_board_t *board, unsigned int clear_mask);
+int hp82335_primary_address(gpib_board_t *board, unsigned int address);
+int hp82335_secondary_address(gpib_board_t *board, unsigned int address, int
+ enable);
+int hp82335_parallel_poll(gpib_board_t *board, uint8_t *result);
+void hp82335_parallel_poll_configure(gpib_board_t *board, uint8_t config);
+void hp82335_parallel_poll_response(gpib_board_t *board, int ist);
+void hp82335_serial_poll_response(gpib_board_t *board, uint8_t status);
+void hp82335_return_to_local(gpib_board_t *board);
+
+// interrupt service routines
+irqreturn_t hp82335_interrupt(int irq, void *arg);
+
+// utility functions
+int hp82335_allocate_private(gpib_board_t *board);
+void hp82335_free_private(gpib_board_t *board);
+
+// size of io memory region used
+static const int hp82335_rom_size = 0x2000;
+static const int hp82335_upper_iomem_size = 0x2000;
+
+// hp82335 register offsets
+enum hp_read_regs {
+ HPREG_CSR = 0x17f8,
+ HPREG_STATUS = 0x1ffc,
+};
+
+enum hp_write_regs {
+ HPREG_INTR_CLEAR = 0x17f7,
+ HPREG_CCR = HPREG_CSR,
+};
+
+enum ccr_bits {
+ DMA_ENABLE = (1 << 0), /* DMA enable */
+ DMA_CHAN_SELECT = (1 << 1), /* DMA channel select O=3,1=2 */
+ INTR_ENABLE = (1 << 2), /* interrupt enable */
+ SYS_DISABLE = (1 << 3), /* system controller disable */
+};
+
+enum csr_bits {
+ SWITCH6 = (1 << 0), /* switch 6 position */
+ SWITCH5 = (1 << 1), /* switch 5 position */
+ SYS_CONTROLLER = (1 << 2), /* system controller bit */
+ DMA_ENABLE_STATUS = (1 << 4), /* DMA enabled */
+ DMA_CHAN_STATUS = (1 << 5), /* DMA channel 0=3,1=2 */
+ INTR_ENABLE_STATUS = (1 << 6), /* Interrupt enable */
+ INTR_PENDING = (1 << 7), /* Interrupt Pending */
+};
+
+#endif // _HP82335_H
diff --git a/drivers/staging/gpib/hp_82341/Makefile b/drivers/staging/gpib/hp_82341/Makefile
new file mode 100644
index 000000000000..1fe7db4f8ca4
--- /dev/null
+++ b/drivers/staging/gpib/hp_82341/Makefile
@@ -0,0 +1,2 @@
+
+obj-m += hp_82341.o
diff --git a/drivers/staging/gpib/hp_82341/hp_82341.c b/drivers/staging/gpib/hp_82341/hp_82341.c
new file mode 100644
index 000000000000..8ad1c885a9fb
--- /dev/null
+++ b/drivers/staging/gpib/hp_82341/hp_82341.c
@@ -0,0 +1,895 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * Driver for hp 82341a/b/c/d boards. *
+ * Might be worth merging with Agilent 82350b driver. *
+ * copyright : (C) 2002, 2005 by Frank Mori Hess *
+ ***************************************************************************/
+
+#include "hp_82341.h"
+#include <linux/delay.h>
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/isapnp.h>
+
+MODULE_LICENSE("GPL");
+
+int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+{
+ struct hp_82341_priv *hp_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
+ int retval = 0;
+ unsigned short event_status;
+ int i;
+ int num_fifo_bytes;
+ //hardware doesn't support checking for end-of-string character when using fifo
+ if (tms_priv->eos_flags & REOS)
+ return tms9914_read(board, tms_priv, buffer, length, end, bytes_read);
+
+ clear_bit(DEV_CLEAR_BN, &tms_priv->state);
+
+ read_and_clear_event_status(board);
+ *end = 0;
+ *bytes_read = 0;
+ if (length == 0)
+ return 0;
+ //disable fifo for the moment
+ outb(DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG);
+ // Handle corner case of board not in holdoff and one byte has slipped in already.
+ // Also, board sometimes has problems (spurious 1 byte reads) when read fifo is
+ // started up with board in
+ // TACS under certain data holdoff conditions. Doing a 1 byte tms9914-style
+ // read avoids these problems.
+ if (/*tms_priv->holdoff_active == 0 && */length > 1) {
+ size_t num_bytes;
+
+ retval = tms9914_read(board, tms_priv, buffer, 1, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ pr_err("tms9914_read failed retval=%i\n", retval);
+ if (retval < 0 || *end)
+ return retval;
+ ++buffer;
+ --length;
+ }
+ tms9914_set_holdoff_mode(tms_priv, TMS9914_HOLDOFF_EOI);
+ tms9914_release_holdoff(tms_priv);
+ outb(0x00, hp_priv->iobase[3] + BUFFER_FLUSH_REG);
+ i = 0;
+ num_fifo_bytes = length - 1;
+ while (i < num_fifo_bytes && *end == 0) {
+ int block_size;
+ int j;
+ int count;
+
+ if (num_fifo_bytes - i < hp_82341_fifo_size)
+ block_size = num_fifo_bytes - i;
+ else
+ block_size = hp_82341_fifo_size;
+ set_transfer_counter(hp_priv, block_size);
+ outb(ENABLE_TI_BUFFER_BIT | DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] +
+ BUFFER_CONTROL_REG);
+ if (inb(hp_priv->iobase[0] + STREAM_STATUS_REG) & HALTED_STATUS_BIT)
+ outb(RESTART_STREAM_BIT, hp_priv->iobase[0] + STREAM_STATUS_REG);
+
+ clear_bit(READ_READY_BN, &tms_priv->state);
+
+ retval = wait_event_interruptible(board->wait,
+ ((event_status =
+ read_and_clear_event_status(board)) &
+ (TERMINAL_COUNT_EVENT_BIT |
+ BUFFER_END_EVENT_BIT)) ||
+ test_bit(DEV_CLEAR_BN, &tms_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ if (retval) {
+ pr_warn("%s: read wait interrupted\n", __func__);
+ retval = -ERESTARTSYS;
+ break;
+ }
+ // have to disable buffer before we can read from buffer port
+ outb(DIRECTION_GPIB_TO_HOST_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG);
+ count = block_size - read_transfer_counter(hp_priv);
+ j = 0;
+ while (j < count && i < num_fifo_bytes) {
+ unsigned short data_word = inw(hp_priv->iobase[3] + BUFFER_PORT_LOW_REG);
+
+ buffer[i++] = data_word & 0xff;
+ ++j;
+ if (j < count && i < num_fifo_bytes) {
+ buffer[i++] = (data_word >> 8) & 0xff;
+ ++j;
+ }
+ }
+ if (event_status & BUFFER_END_EVENT_BIT) {
+ clear_bit(RECEIVED_END_BN, &tms_priv->state);
+
+ *end = 1;
+ tms_priv->holdoff_active = 1;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ pr_debug("%s: minor %i: read timed out\n", __FILE__, board->minor);
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) {
+ pr_warn("%s: device clear interrupted read\n", __FILE__);
+ retval = -EINTR;
+ break;
+ }
+ }
+ *bytes_read += i;
+ buffer += i;
+ length -= i;
+ if (retval < 0)
+ return retval;
+ // read last byte if we havn't received an END yet
+ if (*end == 0) {
+ size_t num_bytes;
+ // try to make sure we holdoff after last byte read
+ retval = tms9914_read(board, tms_priv, buffer, length, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+static int restart_write_fifo(gpib_board_t *board, struct hp_82341_priv *hp_priv)
+{
+ struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
+
+ if ((inb(hp_priv->iobase[0] + STREAM_STATUS_REG) & HALTED_STATUS_BIT) == 0)
+ return 0;
+ while (1) {
+ int status;
+
+ //restart doesn't work if data holdoff is in effect
+ status = tms9914_line_status(board, tms_priv);
+ if ((status & BusNRFD) == 0) {
+ outb(RESTART_STREAM_BIT, hp_priv->iobase[0] + STREAM_STATUS_REG);
+ return 0;
+ }
+ if (test_bit(DEV_CLEAR_BN, &tms_priv->state))
+ return -EINTR;
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+ if (msleep_interruptible(1))
+ return -EINTR;
+ }
+ return 0;
+}
+
+int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ struct hp_82341_priv *hp_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
+ int i, j;
+ unsigned short event_status;
+ int retval = 0;
+ int fifo_xfer_len = length;
+
+ *bytes_written = 0;
+ if (send_eoi)
+ --fifo_xfer_len;
+
+ clear_bit(DEV_CLEAR_BN, &tms_priv->state);
+
+ read_and_clear_event_status(board);
+ outb(0, hp_priv->iobase[3] + BUFFER_CONTROL_REG);
+ outb(0x00, hp_priv->iobase[3] + BUFFER_FLUSH_REG);
+ for (i = 0; i < fifo_xfer_len;) {
+ int block_size;
+
+ if (fifo_xfer_len - i < hp_82341_fifo_size)
+ block_size = fifo_xfer_len - i;
+ else
+ block_size = hp_82341_fifo_size;
+ set_transfer_counter(hp_priv, block_size);
+ // load data into board's fifo
+ for (j = 0; j < block_size;) {
+ unsigned short data_word = buffer[i++];
+ ++j;
+ if (j < block_size) {
+ data_word |= buffer[i++] << 8;
+ ++j;
+ }
+ outw(data_word, hp_priv->iobase[3] + BUFFER_PORT_LOW_REG);
+ }
+ clear_bit(WRITE_READY_BN, &tms_priv->state);
+ outb(ENABLE_TI_BUFFER_BIT, hp_priv->iobase[3] + BUFFER_CONTROL_REG);
+ retval = restart_write_fifo(board, hp_priv);
+ if (retval < 0) {
+ pr_err("hp82341: failed to restart write stream\n");
+ break;
+ }
+ retval = wait_event_interruptible(board->wait,
+ ((event_status =
+ read_and_clear_event_status(board)) &
+ TERMINAL_COUNT_EVENT_BIT) ||
+ test_bit(DEV_CLEAR_BN, &tms_priv->state) ||
+ test_bit(TIMO_NUM, &board->status));
+ outb(0, hp_priv->iobase[3] + BUFFER_CONTROL_REG);
+ *bytes_written += block_size - read_transfer_counter(hp_priv);
+ if (retval) {
+ pr_warn("%s: write wait interrupted\n", __FILE__);
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ pr_debug("%s: minor %i: write timed out\n", __FILE__, board->minor);
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &tms_priv->state)) {
+ pr_warn("%s: device clear interrupted write\n", __FILE__);
+ retval = -EINTR;
+ break;
+ }
+ }
+ if (retval)
+ return retval;
+ if (send_eoi) {
+ size_t num_bytes;
+
+ retval = hp_82341_write(board, buffer + fifo_xfer_len, 1, 1, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+static int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void hp_82341_detach(gpib_board_t *board);
+
+// wrappers for interface functions
+int hp_82341_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_read(board, &priv->tms9914_priv, buffer, length, end, bytes_read);
+}
+
+int hp_82341_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_write(board, &priv->tms9914_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int hp_82341_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_command(board, &priv->tms9914_priv, buffer, length, bytes_written);
+}
+
+int hp_82341_take_control(gpib_board_t *board, int synchronous)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_take_control(board, &priv->tms9914_priv, synchronous);
+}
+
+int hp_82341_go_to_standby(gpib_board_t *board)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_go_to_standby(board, &priv->tms9914_priv);
+}
+
+void hp_82341_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ if (request_control)
+ priv->mode_control_bits |= SYSTEM_CONTROLLER_BIT;
+ else
+ priv->mode_control_bits &= ~SYSTEM_CONTROLLER_BIT;
+ outb(priv->mode_control_bits, priv->iobase[0] + MODE_CONTROL_STATUS_REG);
+ tms9914_request_system_control(board, &priv->tms9914_priv, request_control);
+}
+
+void hp_82341_interface_clear(gpib_board_t *board, int assert)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_interface_clear(board, &priv->tms9914_priv, assert);
+}
+
+void hp_82341_remote_enable(gpib_board_t *board, int enable)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_remote_enable(board, &priv->tms9914_priv, enable);
+}
+
+int hp_82341_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_enable_eos(board, &priv->tms9914_priv, eos_byte, compare_8_bits);
+}
+
+void hp_82341_disable_eos(gpib_board_t *board)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_disable_eos(board, &priv->tms9914_priv);
+}
+
+unsigned int hp_82341_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_update_status(board, &priv->tms9914_priv, clear_mask);
+}
+
+int hp_82341_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_primary_address(board, &priv->tms9914_priv, address);
+}
+
+int hp_82341_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_secondary_address(board, &priv->tms9914_priv, address, enable);
+}
+
+int hp_82341_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_parallel_poll(board, &priv->tms9914_priv, result);
+}
+
+void hp_82341_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_configure(board, &priv->tms9914_priv, config);
+}
+
+void hp_82341_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_parallel_poll_response(board, &priv->tms9914_priv, ist);
+}
+
+void hp_82341_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_serial_poll_response(board, &priv->tms9914_priv, status);
+}
+
+static uint8_t hp_82341_serial_poll_status(gpib_board_t *board)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_serial_poll_status(board, &priv->tms9914_priv);
+}
+
+static int hp_82341_line_status(const gpib_board_t *board)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_line_status(board, &priv->tms9914_priv);
+}
+
+static unsigned int hp_82341_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ return tms9914_t1_delay(board, &priv->tms9914_priv, nano_sec);
+}
+
+void hp_82341_return_to_local(gpib_board_t *board)
+{
+ struct hp_82341_priv *priv = board->private_data;
+
+ tms9914_return_to_local(board, &priv->tms9914_priv);
+}
+
+gpib_interface_t hp_82341_unaccel_interface = {
+name: "hp_82341_unaccel",
+attach : hp_82341_attach,
+detach : hp_82341_detach,
+read : hp_82341_read,
+write : hp_82341_write,
+command : hp_82341_command,
+request_system_control : hp_82341_request_system_control,
+take_control : hp_82341_take_control,
+go_to_standby : hp_82341_go_to_standby,
+interface_clear : hp_82341_interface_clear,
+remote_enable : hp_82341_remote_enable,
+enable_eos : hp_82341_enable_eos,
+disable_eos : hp_82341_disable_eos,
+parallel_poll : hp_82341_parallel_poll,
+parallel_poll_configure : hp_82341_parallel_poll_configure,
+parallel_poll_response : hp_82341_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : hp_82341_line_status,
+update_status : hp_82341_update_status,
+primary_address : hp_82341_primary_address,
+secondary_address : hp_82341_secondary_address,
+serial_poll_response : hp_82341_serial_poll_response,
+serial_poll_status : hp_82341_serial_poll_status,
+t1_delay : hp_82341_t1_delay,
+return_to_local : hp_82341_return_to_local,
+};
+
+gpib_interface_t hp_82341_interface = {
+name: "hp_82341",
+attach : hp_82341_attach,
+detach : hp_82341_detach,
+read : hp_82341_accel_read,
+write : hp_82341_accel_write,
+command : hp_82341_command,
+request_system_control : hp_82341_request_system_control,
+take_control : hp_82341_take_control,
+go_to_standby : hp_82341_go_to_standby,
+interface_clear : hp_82341_interface_clear,
+remote_enable : hp_82341_remote_enable,
+enable_eos : hp_82341_enable_eos,
+disable_eos : hp_82341_disable_eos,
+parallel_poll : hp_82341_parallel_poll,
+parallel_poll_configure : hp_82341_parallel_poll_configure,
+parallel_poll_response : hp_82341_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : hp_82341_line_status,
+update_status : hp_82341_update_status,
+primary_address : hp_82341_primary_address,
+secondary_address : hp_82341_secondary_address,
+serial_poll_response : hp_82341_serial_poll_response,
+t1_delay : hp_82341_t1_delay,
+return_to_local : hp_82341_return_to_local,
+};
+
+int hp_82341_allocate_private(gpib_board_t *board)
+{
+ board->private_data = kzalloc(sizeof(struct hp_82341_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ return 0;
+}
+
+void hp_82341_free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+static uint8_t hp_82341_read_byte(struct tms9914_priv *priv, unsigned int register_num)
+{
+ return inb((unsigned long)(priv->iobase) + register_num);
+}
+
+static void hp_82341_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num)
+{
+ outb(data, (unsigned long)(priv->iobase) + register_num);
+}
+
+static int hp_82341_find_isapnp_board(struct pnp_dev **dev)
+{
+ *dev = pnp_find_dev(NULL, ISAPNP_VENDOR('H', 'W', 'P'),
+ ISAPNP_FUNCTION(0x1411), NULL);
+ if (!*dev || !(*dev)->card) {
+ pr_err("hp_82341: failed to find isapnp board\n");
+ return -ENODEV;
+ }
+ if (pnp_device_attach(*dev) < 0) {
+ pr_err("hp_82341: board already active, skipping\n");
+ return -EBUSY;
+ }
+ if (pnp_activate_dev(*dev) < 0) {
+ pnp_device_detach(*dev);
+ pr_err("hp_82341: failed to activate() atgpib/tnt, aborting\n");
+ return -EAGAIN;
+ }
+ if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) {
+ pnp_device_detach(*dev);
+ pr_err("hp_82341: invalid port or irq for atgpib/tnt, aborting\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int xilinx_ready(struct hp_82341_priv *hp_priv)
+{
+ switch (hp_priv->hw_version) {
+ case HW_VERSION_82341C:
+ if (inb(hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG) & XILINX_READY_BIT)
+ return 1;
+ else
+ return 0;
+ break;
+ case HW_VERSION_82341D:
+ if (isapnp_read_byte(PIO_DATA_REG) & HP_82341D_XILINX_READY_BIT)
+ return 1;
+ else
+ return 0;
+ default:
+ pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__);
+ break;
+ }
+ return 0;
+}
+
+static int xilinx_done(struct hp_82341_priv *hp_priv)
+{
+ switch (hp_priv->hw_version) {
+ case HW_VERSION_82341C:
+ if (inb(hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG) & DONE_PGL_BIT)
+ return 1;
+ else
+ return 0;
+ case HW_VERSION_82341D:
+ if (isapnp_read_byte(PIO_DATA_REG) & HP_82341D_XILINX_DONE_BIT)
+ return 1;
+ else
+ return 0;
+ default:
+ pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__);
+ break;
+ }
+ return 0;
+}
+
+static int irq_valid(struct hp_82341_priv *hp_priv, int irq)
+{
+ switch (hp_priv->hw_version) {
+ case HW_VERSION_82341C:
+ switch (irq) {
+ case 3:
+ case 5:
+ case 7:
+ case 9:
+ case 10:
+ case 11:
+ case 12:
+ case 15:
+ return 1;
+ default:
+ pr_err("hp_82341: invalid irq=%i for 82341C, irq must be 3, 5, 7, 9, 10, 11, 12, or 15.\n",
+ irq);
+ return 0;
+ }
+ break;
+ case HW_VERSION_82341D:
+ return 1;
+ default:
+ pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__);
+ break;
+ }
+ return 0;
+}
+
+static int hp_82341_load_firmware_array(struct hp_82341_priv *hp_priv,
+ const unsigned char *firmware_data,
+ unsigned int firmware_length)
+{
+ int i, j;
+ static const int timeout = 100;
+
+ for (i = 0; i < firmware_length; ++i) {
+ for (j = 0; j < timeout; ++j) {
+ if (need_resched())
+ schedule();
+ if (xilinx_ready(hp_priv))
+ break;
+ usleep_range(10, 15);
+ }
+ if (j == timeout) {
+ pr_err("hp_82341: timed out waiting for Xilinx ready.\n");
+ return -ETIMEDOUT;
+ }
+ outb(firmware_data[i], hp_priv->iobase[0] + XILINX_DATA_REG);
+ }
+ for (j = 0; j < timeout; ++j) {
+ if (xilinx_done(hp_priv))
+ break;
+ if (need_resched())
+ schedule();
+ usleep_range(10, 15);
+ }
+ if (j == timeout) {
+ pr_err("hp_82341: timed out waiting for Xilinx done.\n");
+ return -ETIMEDOUT;
+ }
+ return 0;
+}
+
+static int hp_82341_load_firmware(struct hp_82341_priv *hp_priv, const gpib_board_config_t *config)
+{
+ if (config->init_data_length == 0) {
+ if (xilinx_done(hp_priv))
+ return 0;
+ pr_err("hp_82341: board needs be initialized with firmware upload.\n"
+ "\tUse the --init-data option of gpib_config.\n");
+ return -EINVAL;
+ }
+ switch (hp_priv->hw_version) {
+ case HW_VERSION_82341C:
+ if (config->init_data_length != hp_82341c_firmware_length) {
+ pr_err("hp_82341: bad firmware length=%i for 82341c (expected %i).\n",
+ config->init_data_length, hp_82341c_firmware_length);
+ return -EINVAL;
+ }
+ break;
+ case HW_VERSION_82341D:
+ if (config->init_data_length != hp_82341d_firmware_length) {
+ pr_err("hp_82341: bad firmware length=%i for 82341d (expected %i).\n",
+ config->init_data_length, hp_82341d_firmware_length);
+ return -EINVAL;
+ }
+ break;
+ default:
+ pr_err("hp_82341: %s: bug! unknown hw_version\n", __func__);
+ break;
+ }
+ return hp_82341_load_firmware_array(hp_priv, config->init_data, config->init_data_length);
+}
+
+static void set_xilinx_not_prog(struct hp_82341_priv *hp_priv, int assert)
+{
+ switch (hp_priv->hw_version) {
+ case HW_VERSION_82341C:
+ if (assert)
+ hp_priv->config_control_bits |= DONE_PGL_BIT;
+ else
+ hp_priv->config_control_bits &= ~DONE_PGL_BIT;
+ outb(hp_priv->config_control_bits, hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG);
+ break;
+ case HW_VERSION_82341D:
+ if (assert)
+ isapnp_write_byte(PIO_DATA_REG, HP_82341D_NOT_PROG_BIT);
+ else
+ isapnp_write_byte(PIO_DATA_REG, 0x0);
+ break;
+ default:
+ break;
+ }
+}
+
+// clear xilinx firmware
+static int clear_xilinx(struct hp_82341_priv *hp_priv)
+{
+ set_xilinx_not_prog(hp_priv, 1);
+ if (msleep_interruptible(1))
+ return -EINTR;
+ set_xilinx_not_prog(hp_priv, 0);
+ if (msleep_interruptible(1))
+ return -EINTR;
+ set_xilinx_not_prog(hp_priv, 1);
+ if (msleep_interruptible(1))
+ return -EINTR;
+ return 0;
+}
+
+int hp_82341_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct hp_82341_priv *hp_priv;
+ struct tms9914_priv *tms_priv;
+ unsigned long start_addr;
+ void *iobase;
+ int irq;
+ int i;
+ int retval;
+
+ board->status = 0;
+ if (hp_82341_allocate_private(board))
+ return -ENOMEM;
+ hp_priv = board->private_data;
+ tms_priv = &hp_priv->tms9914_priv;
+ tms_priv->read_byte = hp_82341_read_byte;
+ tms_priv->write_byte = hp_82341_write_byte;
+ tms_priv->offset = 1;
+
+ if (config->ibbase == 0) {
+ struct pnp_dev *dev;
+ int retval = hp_82341_find_isapnp_board(&dev);
+
+ if (retval < 0)
+ return retval;
+ hp_priv->pnp_dev = dev;
+ iobase = (void *)(pnp_port_start(dev, 0));
+ irq = pnp_irq(dev, 0);
+ hp_priv->hw_version = HW_VERSION_82341D;
+ hp_priv->io_region_offset = 0x8;
+ } else {
+ iobase = config->ibbase;
+ irq = config->ibirq;
+ hp_priv->hw_version = HW_VERSION_82341C;
+ hp_priv->io_region_offset = 0x400;
+ }
+ pr_info("hp_82341: base io 0x%p\n", iobase);
+ for (i = 0; i < hp_82341_num_io_regions; ++i) {
+ start_addr = (unsigned long)(iobase) + i * hp_priv->io_region_offset;
+ if (!request_region(start_addr, hp_82341_region_iosize, "hp_82341")) {
+ pr_err("hp_82341: failed to allocate io ports 0x%lx-0x%lx\n",
+ start_addr,
+ start_addr + hp_82341_region_iosize - 1);
+ return -EIO;
+ }
+ hp_priv->iobase[i] = start_addr;
+ }
+ tms_priv->iobase = (void *)(hp_priv->iobase[2]);
+ if (hp_priv->hw_version == HW_VERSION_82341D) {
+ retval = isapnp_cfg_begin(hp_priv->pnp_dev->card->number,
+ hp_priv->pnp_dev->number);
+ if (retval < 0) {
+ pr_err("hp_82341: isapnp_cfg_begin returned error\n");
+ return retval;
+ }
+ isapnp_write_byte(PIO_DIRECTION_REG, HP_82341D_XILINX_READY_BIT |
+ HP_82341D_XILINX_DONE_BIT);
+ }
+ retval = clear_xilinx(hp_priv);
+ if (retval < 0)
+ return retval;
+ retval = hp_82341_load_firmware(hp_priv, config);
+ if (hp_priv->hw_version == HW_VERSION_82341D)
+ isapnp_cfg_end();
+ if (retval < 0)
+ return retval;
+ if (irq_valid(hp_priv, irq) == 0)
+ return -EINVAL;
+ if (request_irq(irq, hp_82341_interrupt, 0, "hp_82341", board)) {
+ pr_err("hp_82341: failed to allocate IRQ %d\n", irq);
+ return -EIO;
+ }
+ hp_priv->irq = irq;
+ pr_info("hp_82341: IRQ %d\n", irq);
+ hp_priv->config_control_bits &= ~IRQ_SELECT_MASK;
+ hp_priv->config_control_bits |= IRQ_SELECT_BITS(irq);
+ outb(hp_priv->config_control_bits, hp_priv->iobase[0] + CONFIG_CONTROL_STATUS_REG);
+ hp_priv->mode_control_bits |= ENABLE_IRQ_CONFIG_BIT;
+ outb(hp_priv->mode_control_bits, hp_priv->iobase[0] + MODE_CONTROL_STATUS_REG);
+ tms9914_board_reset(tms_priv);
+ outb(ENABLE_BUFFER_END_EVENT_BIT | ENABLE_TERMINAL_COUNT_EVENT_BIT |
+ ENABLE_TI_INTERRUPT_EVENT_BIT, hp_priv->iobase[0] + EVENT_ENABLE_REG);
+ outb(ENABLE_BUFFER_END_INTERRUPT_BIT | ENABLE_TERMINAL_COUNT_INTERRUPT_BIT |
+ ENABLE_TI_INTERRUPT_BIT, hp_priv->iobase[0] + INTERRUPT_ENABLE_REG);
+ //write clear event register
+ outb((TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT |
+ BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT),
+ hp_priv->iobase[0] + EVENT_STATUS_REG);
+
+ tms9914_online(board, tms_priv);
+ pr_info("hp_82341: board id %x %x %x %x\n", inb(hp_priv->iobase[1] + ID0_REG),
+ inb(hp_priv->iobase[1] + ID1_REG), inb(hp_priv->iobase[2] + ID2_REG),
+ inb(hp_priv->iobase[2] + ID3_REG));
+ return 0;
+}
+
+void hp_82341_detach(gpib_board_t *board)
+{
+ struct hp_82341_priv *hp_priv = board->private_data;
+ struct tms9914_priv *tms_priv;
+ int i;
+
+ if (hp_priv) {
+ tms_priv = &hp_priv->tms9914_priv;
+ if (hp_priv->iobase[0]) {
+ outb(0, hp_priv->iobase[0] + INTERRUPT_ENABLE_REG);
+ if (tms_priv->iobase)
+ tms9914_board_reset(tms_priv);
+ if (hp_priv->irq)
+ free_irq(hp_priv->irq, board);
+ }
+ for (i = 0; i < hp_82341_num_io_regions; ++i) {
+ if (hp_priv->iobase[i])
+ release_region(hp_priv->iobase[i], hp_82341_region_iosize);
+ }
+ if (hp_priv->pnp_dev)
+ pnp_device_detach(hp_priv->pnp_dev);
+ }
+ hp_82341_free_private(board);
+}
+
+static const struct pnp_device_id hp_82341_pnp_table[] = {
+ {.id = "HWP1411"},
+ {.id = ""}
+};
+MODULE_DEVICE_TABLE(pnp, hp_82341_pnp_table);
+
+static int __init hp_82341_init_module(void)
+{
+ gpib_register_driver(&hp_82341_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&hp_82341_interface, THIS_MODULE);
+ return 0;
+}
+
+static void __exit hp_82341_exit_module(void)
+{
+ gpib_unregister_driver(&hp_82341_interface);
+ gpib_unregister_driver(&hp_82341_unaccel_interface);
+}
+
+module_init(hp_82341_init_module);
+module_exit(hp_82341_exit_module);
+
+/*
+ * GPIB interrupt service routines
+ */
+unsigned short read_and_clear_event_status(gpib_board_t *board)
+{
+ struct hp_82341_priv *hp_priv = board->private_data;
+ unsigned long flags;
+ unsigned short status;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ status = hp_priv->event_status_bits;
+ hp_priv->event_status_bits = 0;
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return status;
+}
+
+irqreturn_t hp_82341_interrupt(int irq, void *arg)
+{
+ int status1, status2;
+ gpib_board_t *board = arg;
+ struct hp_82341_priv *hp_priv = board->private_data;
+ struct tms9914_priv *tms_priv = &hp_priv->tms9914_priv;
+ unsigned long flags;
+ irqreturn_t retval = IRQ_NONE;
+ int event_status;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ event_status = inb(hp_priv->iobase[0] + EVENT_STATUS_REG);
+// printk("hp_82341: interrupt event_status=0x%x\n", event_status);
+ if (event_status & INTERRUPT_PENDING_EVENT_BIT)
+ retval = IRQ_HANDLED;
+ //write-clear status bits
+ if (event_status & (TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT |
+ BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT)) {
+ outb(event_status & (TI_INTERRUPT_EVENT_BIT | POINTERS_EQUAL_EVENT_BIT |
+ BUFFER_END_EVENT_BIT | TERMINAL_COUNT_EVENT_BIT),
+ hp_priv->iobase[0] + EVENT_STATUS_REG);
+ hp_priv->event_status_bits |= event_status;
+ }
+ if (event_status & TI_INTERRUPT_EVENT_BIT) {
+ status1 = read_byte(tms_priv, ISR0);
+ status2 = read_byte(tms_priv, ISR1);
+ tms9914_interrupt_have_status(board, tms_priv, status1, status2);
+/* printk("hp_82341: interrupt status1=0x%x status2=0x%x\n",
+ * status1, status2);
+ */
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+int read_transfer_counter(struct hp_82341_priv *hp_priv)
+{
+ int lo, mid, value;
+
+ lo = inb(hp_priv->iobase[1] + TRANSFER_COUNT_LOW_REG);
+ mid = inb(hp_priv->iobase[1] + TRANSFER_COUNT_MID_REG);
+ value = (lo & 0xff) | ((mid << 8) & 0x7f00);
+ value = ~(value - 1) & 0x7fff;
+ return value;
+}
+
+void set_transfer_counter(struct hp_82341_priv *hp_priv, int count)
+{
+ int complement = -count;
+
+ outb(complement & 0xff, hp_priv->iobase[1] + TRANSFER_COUNT_LOW_REG);
+ outb((complement >> 8) & 0xff, hp_priv->iobase[1] + TRANSFER_COUNT_MID_REG);
+ //I don't think the hi count reg is even used, but oh well
+ outb((complement >> 16) & 0xf, hp_priv->iobase[1] + TRANSFER_COUNT_HIGH_REG);
+}
+
diff --git a/drivers/staging/gpib/hp_82341/hp_82341.h b/drivers/staging/gpib/hp_82341/hp_82341.h
new file mode 100644
index 000000000000..7c391860b399
--- /dev/null
+++ b/drivers/staging/gpib/hp_82341/hp_82341.h
@@ -0,0 +1,207 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002, 2005 by Frank Mori Hess *
+ ***************************************************************************/
+
+#include "tms9914.h"
+#include "gpibP.h"
+
+enum hp_82341_hardware_version {
+ HW_VERSION_UNKNOWN,
+ HW_VERSION_82341C,
+ HW_VERSION_82341D,
+};
+
+// struct which defines private_data for board
+struct hp_82341_priv {
+ struct tms9914_priv tms9914_priv;
+ unsigned int irq;
+ unsigned short config_control_bits;
+ unsigned short mode_control_bits;
+ unsigned short event_status_bits;
+ struct pnp_dev *pnp_dev;
+ unsigned long iobase[4];
+ unsigned long io_region_offset;
+ enum hp_82341_hardware_version hw_version;
+};
+
+// interfaces
+extern gpib_interface_t hp_82341_interface;
+
+// interface functions
+int hp_82341_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read);
+int hp_82341_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+int hp_82341_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read);
+int hp_82341_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+int hp_82341_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written);
+int hp_82341_take_control(gpib_board_t *board, int synchronous);
+int hp_82341_go_to_standby(gpib_board_t *board);
+void hp_82341_request_system_control(gpib_board_t *board, int request_control);
+void hp_82341_interface_clear(gpib_board_t *board, int assert);
+void hp_82341_remote_enable(gpib_board_t *board, int enable);
+int hp_82341_enable_eos(gpib_board_t *board, uint8_t eos_byte, int
+ compare_8_bits);
+void hp_82341_disable_eos(gpib_board_t *board);
+unsigned int hp_82341_update_status(gpib_board_t *board, unsigned int clear_mask);
+int hp_82341_primary_address(gpib_board_t *board, unsigned int address);
+int hp_82341_secondary_address(gpib_board_t *board, unsigned int address, int
+ enable);
+int hp_82341_parallel_poll(gpib_board_t *board, uint8_t *result);
+void hp_82341_parallel_poll_configure(gpib_board_t *board, uint8_t config);
+void hp_82341_parallel_poll_response(gpib_board_t *board, int ist);
+void hp_82341_serial_poll_response(gpib_board_t *board, uint8_t status);
+void hp_82341_return_to_local(gpib_board_t *board);
+
+// interrupt service routines
+irqreturn_t hp_82341_interrupt(int irq, void *arg);
+
+// utility functions
+int hp_82341_allocate_private(gpib_board_t *board);
+void hp_82341_free_private(gpib_board_t *board);
+
+static const int hp_82341_region_iosize = 0x8;
+static const int hp_82341_num_io_regions = 4;
+static const int hp_82341_fifo_size = 0xffe;
+static const int hp_82341c_firmware_length = 5764;
+static const int hp_82341d_firmware_length = 5302;
+
+// hp 82341 register offsets
+enum hp_82341_region_0_registers {
+ CONFIG_CONTROL_STATUS_REG = 0x0,
+ MODE_CONTROL_STATUS_REG = 0x1,
+ MONITOR_REG = 0x2, // after initialization
+ XILINX_DATA_REG = 0x2, // before initialization, write only
+ INTERRUPT_ENABLE_REG = 0x3,
+ EVENT_STATUS_REG = 0x4,
+ EVENT_ENABLE_REG = 0x5,
+ STREAM_STATUS_REG = 0x7,
+};
+
+enum hp_82341_region_1_registers {
+ ID0_REG = 0x2,
+ ID1_REG = 0x3,
+ TRANSFER_COUNT_LOW_REG = 0x4,
+ TRANSFER_COUNT_MID_REG = 0x5,
+ TRANSFER_COUNT_HIGH_REG = 0x6,
+};
+
+enum hp_82341_region_3_registers {
+ BUFFER_PORT_LOW_REG = 0x0,
+ BUFFER_PORT_HIGH_REG = 0x1,
+ ID2_REG = 0x2,
+ ID3_REG = 0x3,
+ BUFFER_FLUSH_REG = 0x4,
+ BUFFER_CONTROL_REG = 0x7
+};
+
+enum config_control_status_bits {
+ IRQ_SELECT_MASK = 0x7,
+ DMA_CONFIG_MASK = 0x18,
+ ENABLE_DMA_CONFIG_BIT = 0x20,
+ XILINX_READY_BIT = 0x40, //read only
+ DONE_PGL_BIT = 0x80
+};
+
+static inline unsigned int IRQ_SELECT_BITS(int irq)
+{
+ switch (irq) {
+ case 3:
+ return 0x3;
+ case 5:
+ return 0x2;
+ case 7:
+ return 0x1;
+ case 9:
+ return 0x0;
+ case 10:
+ return 0x7;
+ case 11:
+ return 0x6;
+ case 12:
+ return 0x5;
+ case 15:
+ return 0x4;
+ default:
+ return 0x0;
+ }
+};
+
+enum mode_control_status_bits {
+ SLOT8_BIT = 0x1, // read only
+ ACTIVE_CONTROLLER_BIT = 0x2, // read only
+ ENABLE_DMA_BIT = 0x4,
+ SYSTEM_CONTROLLER_BIT = 0x8,
+ MONITOR_BIT = 0x10,
+ ENABLE_IRQ_CONFIG_BIT = 0x20,
+ ENABLE_TI_STREAM_BIT = 0x40
+};
+
+enum monitor_bits {
+ MONITOR_INTERRUPT_PENDING_BIT = 0x1, // read only
+ MONITOR_CLEAR_HOLDOFF_BIT = 0x2, // write only
+ MONITOR_PPOLL_BIT = 0x4, // write clear
+ MONITOR_SRQ_BIT = 0x8, // write clear
+ MONITOR_IFC_BIT = 0x10, // write clear
+ MONITOR_REN_BIT = 0x20, // write clear
+ MONITOR_END_BIT = 0x40, // write clear
+ MONITOR_DAV_BIT = 0x80 // write clear
+};
+
+enum interrupt_enable_bits {
+ ENABLE_TI_INTERRUPT_BIT = 0x1,
+ ENABLE_POINTERS_EQUAL_INTERRUPT_BIT = 0x4,
+ ENABLE_BUFFER_END_INTERRUPT_BIT = 0x10,
+ ENABLE_TERMINAL_COUNT_INTERRUPT_BIT = 0x20,
+ ENABLE_DMA_TERMINAL_COUNT_INTERRUPT_BIT = 0x80,
+};
+
+enum event_status_bits {
+ TI_INTERRUPT_EVENT_BIT = 0x1, //write clear
+ INTERRUPT_PENDING_EVENT_BIT = 0x2, // read only
+ POINTERS_EQUAL_EVENT_BIT = 0x4, //write clear
+ BUFFER_END_EVENT_BIT = 0x10, //write clear
+ TERMINAL_COUNT_EVENT_BIT = 0x20, // write clear
+ DMA_TERMINAL_COUNT_EVENT_BIT = 0x80, // write clear
+};
+
+enum event_enable_bits {
+ ENABLE_TI_INTERRUPT_EVENT_BIT = 0x1, //write clear
+ ENABLE_POINTERS_EQUAL_EVENT_BIT = 0x4, //write clear
+ ENABLE_BUFFER_END_EVENT_BIT = 0x10, //write clear
+ ENABLE_TERMINAL_COUNT_EVENT_BIT = 0x20, // write clear
+ ENABLE_DMA_TERMINAL_COUNT_EVENT_BIT = 0x80, // write clear
+};
+
+enum stream_status_bits {
+ HALTED_STATUS_BIT = 0x1, //read
+ RESTART_STREAM_BIT = 0x1 //write
+};
+
+enum buffer_control_bits {
+ DIRECTION_GPIB_TO_HOST_BIT = 0x20, // transfer direction (set for gpib to host)
+ ENABLE_TI_BUFFER_BIT = 0x40, //enable fifo
+ FAST_WR_EN_BIT = 0x80, // 350 ns t1 delay?
+};
+
+// registers accessible through isapnp chip on 82341d
+enum hp_82341d_pnp_registers {
+ PIO_DATA_REG = 0x20, //read/write pio data lines
+ PIO_DIRECTION_REG = 0x21, // set pio data line directions (set for input)
+};
+
+enum hp_82341d_pnp_pio_bits {
+ HP_82341D_XILINX_READY_BIT = 0x1,
+ HP_82341D_XILINX_DONE_BIT = 0x2,
+ // use register layout compatible with C and older versions instead of 32 contiguous ioports
+ HP_82341D_LEGACY_MODE_BIT = 0x4,
+ HP_82341D_NOT_PROG_BIT = 0x8, // clear to reinitialize xilinx
+};
+
+unsigned short read_and_clear_event_status(gpib_board_t *board);
+int read_transfer_counter(struct hp_82341_priv *hp_priv);
+void set_transfer_counter(struct hp_82341_priv *hp_priv, int count);
diff --git a/drivers/staging/gpib/include/amcc5920.h b/drivers/staging/gpib/include/amcc5920.h
new file mode 100644
index 000000000000..766b3799223f
--- /dev/null
+++ b/drivers/staging/gpib/include/amcc5920.h
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Header for amcc5920 pci chip
+ *
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+// plx pci chip registers and bits
+enum amcc_registers {
+ AMCC_INTCS_REG = 0x38,
+ AMCC_PASS_THRU_REG = 0x60,
+};
+
+enum amcc_incsr_bits {
+ AMCC_ADDON_INTR_ENABLE_BIT = 0x2000,
+ AMCC_ADDON_INTR_ACTIVE_BIT = 0x400000,
+ AMCC_INTR_ACTIVE_BIT = 0x800000,
+};
+
+static const int bits_per_region = 8;
+
+static inline uint32_t amcc_wait_state_bits(unsigned int region, unsigned int num_wait_states)
+{
+ return (num_wait_states & 0x7) << (-region * bits_per_region);
+};
+
+enum amcc_prefetch_bits {
+ PREFETCH_DISABLED = 0x0,
+ PREFETCH_SMALL = 0x8,
+ PREFETCH_MEDIUM = 0x10,
+ PREFETCH_LARGE = 0x18,
+};
+
+static inline uint32_t amcc_prefetch_bits(unsigned int region, enum amcc_prefetch_bits prefetch)
+{
+ return prefetch << (--region * bits_per_region);
+};
+
+static inline uint32_t amcc_PTADR_mode_bit(unsigned int region)
+{
+ return 0x80 << (--region * bits_per_region);
+};
+
+static inline uint32_t amcc_disable_write_fifo_bit(unsigned int region)
+{
+ return 0x20 << (--region * bits_per_region);
+};
+
diff --git a/drivers/staging/gpib/include/amccs5933.h b/drivers/staging/gpib/include/amccs5933.h
new file mode 100644
index 000000000000..4de0f6797458
--- /dev/null
+++ b/drivers/staging/gpib/include/amccs5933.h
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Registers and bits for amccs5933 pci chip
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+// register offsets
+enum {
+ MBEF_REG = 0x34, // mailbux empty/full
+ INTCSR_REG = 0x38, // interrupt control and status
+ BMCSR_REG = 0x3c, // bus master control and status
+};
+
+// incoming mailbox 0-3 register offsets
+extern inline int INCOMING_MAILBOX_REG(unsigned int mailbox)
+{
+ return (0x10 + 4 * mailbox);
+};
+
+// bit definitions
+
+// INTCSR bits
+enum {
+ OUTBOX_EMPTY_INTR_BIT = 0x10, // enable outbox empty interrupt
+ INBOX_FULL_INTR_BIT = 0x1000, // enable inbox full interrupt
+ INBOX_INTR_CS_BIT = 0x20000, // read, or write clear inbox full interrupt
+ INTR_ASSERTED_BIT = 0x800000, // read only, interrupt asserted
+};
+
+// select byte 0 to 3 of incoming mailbox
+extern inline int INBOX_BYTE_BITS(unsigned int byte)
+{
+ return (byte & 0x3) << 8;
+};
+
+// select incoming mailbox 0 to 3
+extern inline int INBOX_SELECT_BITS(unsigned int mailbox)
+{
+ return (mailbox & 0x3) << 10;
+};
+
+// select byte 0 to 3 of outgoing mailbox
+extern inline int OUTBOX_BYTE_BITS(unsigned int byte)
+{
+ return (byte & 0x3);
+};
+
+// select outgoing mailbox 0 to 3
+extern inline int OUTBOX_SELECT_BITS(unsigned int mailbox)
+{
+ return (mailbox & 0x3) << 2;
+};
+
+//BMCSR bits
+enum {
+ MBOX_FLAGS_RESET_BIT = 0x08000000, // resets mailbox empty/full flags
+};
+
diff --git a/drivers/staging/gpib/include/gpibP.h b/drivers/staging/gpib/include/gpibP.h
new file mode 100644
index 000000000000..5fc42b645ab7
--- /dev/null
+++ b/drivers/staging/gpib/include/gpibP.h
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002,2003 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_P_H
+#define _GPIB_P_H
+
+#include <linux/types.h>
+
+#include "gpib_types.h"
+#include "gpib_proto.h"
+#include "gpib_user.h"
+#include "gpib_ioctl.h"
+
+#include <linux/fs.h>
+#include <linux/interrupt.h>
+
+void gpib_register_driver(gpib_interface_t *interface, struct module *mod);
+void gpib_unregister_driver(gpib_interface_t *interface);
+struct pci_dev *gpib_pci_get_device(const gpib_board_config_t *config, unsigned int vendor_id,
+ unsigned int device_id, struct pci_dev *from);
+struct pci_dev *gpib_pci_get_subsys(const gpib_board_config_t *config, unsigned int vendor_id,
+ unsigned int device_id, unsigned int ss_vendor,
+ unsigned int ss_device, struct pci_dev *from);
+unsigned int num_gpib_events(const gpib_event_queue_t *queue);
+int push_gpib_event(gpib_board_t *board, short event_type);
+int pop_gpib_event(gpib_board_t *board, gpib_event_queue_t *queue, short *event_type);
+int gpib_request_pseudo_irq(gpib_board_t *board, irqreturn_t (*handler)(int, void *));
+void gpib_free_pseudo_irq(gpib_board_t *board);
+int gpib_match_device_path(struct device *dev, const char *device_path_in);
+
+extern gpib_board_t board_array[GPIB_MAX_NUM_BOARDS];
+
+extern struct list_head registered_drivers;
+
+#include <linux/io.h>
+
+void writeb_wrapper(unsigned int value, void *address);
+unsigned int readb_wrapper(void *address);
+void outb_wrapper(unsigned int value, void *address);
+unsigned int inb_wrapper(void *address);
+void writew_wrapper(unsigned int value, void *address);
+unsigned int readw_wrapper(void *address);
+void outw_wrapper(unsigned int value, void *address);
+unsigned int inw_wrapper(void *address);
+
+#endif // _GPIB_P_H
+
diff --git a/drivers/staging/gpib/include/gpib_pci_ids.h b/drivers/staging/gpib/include/gpib_pci_ids.h
new file mode 100644
index 000000000000..52dcab07a7d1
--- /dev/null
+++ b/drivers/staging/gpib/include/gpib_pci_ids.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __GPIB_PCI_IDS_H
+#define __GPIB_PCI_IDS_H
+
+#ifndef PCI_VENDOR_ID_AMCC
+#define PCI_VENDOR_ID_AMCC 0x10e8
+#endif
+
+#ifndef PCI_VENDOR_ID_CBOARDS
+#define PCI_VENDOR_ID_CBOARDS 0x1307
+#endif
+
+#ifndef PCI_VENDOR_ID_QUANCOM
+#define PCI_VENDOR_ID_QUANCOM 0x8008
+#endif
+
+#ifndef PCI_DEVICE_ID_QUANCOM_GPIB
+#define PCI_DEVICE_ID_QUANCOM_GPIB 0x3302
+#endif
+
+#endif // __GPIB_PCI_IDS_H
+
diff --git a/drivers/staging/gpib/include/gpib_proto.h b/drivers/staging/gpib/include/gpib_proto.h
new file mode 100644
index 000000000000..1499f954210b
--- /dev/null
+++ b/drivers/staging/gpib/include/gpib_proto.h
@@ -0,0 +1,56 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef GPIB_PROTO_INCLUDED
+#define GPIB_PROTO_INCLUDED
+
+#include <linux/fs.h>
+
+int ibopen(struct inode *inode, struct file *filep);
+int ibclose(struct inode *inode, struct file *file);
+long ibioctl(struct file *filep, unsigned int cmd, unsigned long arg);
+int osInit(void);
+void osReset(void);
+void os_start_timer(gpib_board_t *board, unsigned int usec_timeout);
+void os_remove_timer(gpib_board_t *board);
+void osSendEOI(void);
+void osSendEOI(void);
+void init_gpib_board(gpib_board_t *board);
+static inline unsigned long usec_to_jiffies(unsigned int usec)
+{
+ unsigned long usec_per_jiffy = 1000000 / HZ;
+
+ return 1 + (usec + usec_per_jiffy - 1) / usec_per_jiffy;
+};
+
+int serial_poll_all(gpib_board_t *board, unsigned int usec_timeout);
+void init_gpib_descriptor(gpib_descriptor_t *desc);
+int dvrsp(gpib_board_t *board, unsigned int pad, int sad,
+ unsigned int usec_timeout, uint8_t *result);
+int ibAPWait(gpib_board_t *board, int pad);
+int ibAPrsp(gpib_board_t *board, int padsad, char *spb);
+void ibAPE(gpib_board_t *board, int pad, int v);
+int ibcac(gpib_board_t *board, int sync, int fallback_to_async);
+int ibcmd(gpib_board_t *board, uint8_t *buf, size_t length, size_t *bytes_written);
+int ibgts(gpib_board_t *board);
+int ibonline(gpib_board_t *board);
+int iboffline(gpib_board_t *board);
+int iblines(const gpib_board_t *board, short *lines);
+int ibrd(gpib_board_t *board, uint8_t *buf, size_t length, int *end_flag, size_t *bytes_read);
+int ibrpp(gpib_board_t *board, uint8_t *buf);
+int ibrsv2(gpib_board_t *board, uint8_t status_byte, int new_reason_for_service);
+void ibrsc(gpib_board_t *board, int request_control);
+int ibsic(gpib_board_t *board, unsigned int usec_duration);
+int ibsre(gpib_board_t *board, int enable);
+int ibpad(gpib_board_t *board, unsigned int addr);
+int ibsad(gpib_board_t *board, int addr);
+int ibeos(gpib_board_t *board, int eos, int eosflags);
+int ibwait(gpib_board_t *board, int wait_mask, int clear_mask, int set_mask,
+ int *status, unsigned long usec_timeout, gpib_descriptor_t *desc);
+int ibwrt(gpib_board_t *board, uint8_t *buf, size_t cnt, int send_eoi, size_t *bytes_written);
+int ibstatus(gpib_board_t *board);
+int general_ibstatus(gpib_board_t *board, const gpib_status_queue_t *device,
+ int clear_mask, int set_mask, gpib_descriptor_t *desc);
+int io_timed_out(gpib_board_t *board);
+int ibppc(gpib_board_t *board, uint8_t configuration);
+
+#endif /* GPIB_PROTO_INCLUDED */
diff --git a/drivers/staging/gpib/include/gpib_state_machines.h b/drivers/staging/gpib/include/gpib_state_machines.h
new file mode 100644
index 000000000000..7488c00f191e
--- /dev/null
+++ b/drivers/staging/gpib/include/gpib_state_machines.h
@@ -0,0 +1,23 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2006 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_STATE_MACHINES_H
+#define _GPIB_STATE_MACHINES_H
+
+enum talker_function_state {
+ talker_idle,
+ talker_addressed,
+ talker_active,
+ serial_poll_active
+};
+
+enum listener_function_state {
+ listener_idle,
+ listener_addressed,
+ listener_active
+};
+
+#endif // _GPIB_STATE_MACHINES_H
diff --git a/drivers/staging/gpib/include/gpib_types.h b/drivers/staging/gpib/include/gpib_types.h
new file mode 100644
index 000000000000..ee2643da6d71
--- /dev/null
+++ b/drivers/staging/gpib/include/gpib_types.h
@@ -0,0 +1,353 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_TYPES_H
+#define _GPIB_TYPES_H
+
+#ifdef __KERNEL__
+/* gpib_interface_t defines the interface
+ * between the board-specific details dealt with in the drivers
+ * and generic interface provided by gpib-common.
+ * This really should be in a different header file.
+ */
+#include "gpib_user.h"
+#include <linux/atomic.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+
+typedef struct gpib_interface_struct gpib_interface_t;
+typedef struct gpib_board_struct gpib_board_t;
+
+/* config parameters that are only used by driver attach functions */
+typedef struct {
+ /* firmware blob */
+ void *init_data;
+ int init_data_length;
+ /* IO base address to use for non-pnp cards (set by core, driver should make local copy) */
+ void *ibbase;
+ /* IRQ to use for non-pnp cards (set by core, driver should make local copy) */
+ unsigned int ibirq;
+ /* dma channel to use for non-pnp cards (set by core, driver should make local copy) */
+ unsigned int ibdma;
+ /* pci bus of card, useful for distinguishing multiple identical pci cards
+ * (negative means don't care)
+ */
+ int pci_bus;
+ /* pci slot of card, useful for distinguishing multiple identical pci cards
+ * (negative means don't care)
+ */
+ int pci_slot;
+ /* sysfs device path of hardware to attach */
+ char *device_path;
+ /* serial number of hardware to attach */
+ char *serial_number;
+} gpib_board_config_t;
+
+struct gpib_interface_struct {
+ /* name of board */
+ char *name;
+ /* attach() initializes board and allocates resources */
+ int (*attach)(gpib_board_t *board, const gpib_board_config_t *config);
+ /* detach() shuts down board and frees resources */
+ void (*detach)(gpib_board_t *board);
+ /* read() should read at most 'length' bytes from the bus into
+ * 'buffer'. It should return when it fills the buffer or
+ * encounters an END (EOI and or EOS if appropriate). It should set 'end'
+ * to be nonzero if the read was terminated by an END, otherwise 'end'
+ * should be zero.
+ * Ultimately, this will be changed into or replaced by an asynchronous
+ * read. Zero return value for success, negative
+ * return indicates error.
+ * nbytes returns number of bytes read
+ */
+ int (*read)(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read);
+ /* write() should write 'length' bytes from buffer to the bus.
+ * If the boolean value send_eoi is nonzero, then EOI should
+ * be sent along with the last byte. Returns number of bytes
+ * written or negative value on error.
+ */
+ int (*write)(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written);
+ /* command() writes the command bytes in 'buffer' to the bus
+ * Returns zero on success or negative value on error.
+ */
+ int (*command)(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written);
+ /* Take control (assert ATN). If 'asyncronous' is nonzero, take
+ * control asyncronously (assert ATN immediately without waiting
+ * for other processes to complete first). Should not return
+ * until board becomes controller in charge. Returns zero no success,
+ * nonzero on error.
+ */
+ int (*take_control)(gpib_board_t *board, int asyncronous);
+ /* De-assert ATN. Returns zero on success, nonzer on error.
+ */
+ int (*go_to_standby)(gpib_board_t *board);
+ /* request/release control of the IFC and REN lines (system controller) */
+ void (*request_system_control)(gpib_board_t *board, int request_control);
+ /* Asserts or de-asserts 'interface clear' (IFC) depending on
+ * boolean value of 'assert'
+ */
+ void (*interface_clear)(gpib_board_t *board, int assert);
+ /* Sends remote enable command if 'enable' is nonzero, disables remote mode
+ * if 'enable' is zero
+ */
+ void (*remote_enable)(gpib_board_t *board, int enable);
+ /* enable END for reads, when byte 'eos' is received. If
+ * 'compare_8_bits' is nonzero, then all 8 bits are compared
+ * with the eos bytes. Otherwise only the 7 least significant
+ * bits are compared.
+ */
+ int (*enable_eos)(gpib_board_t *board, uint8_t eos, int compare_8_bits);
+ /* disable END on eos byte (END on EOI only)*/
+ void (*disable_eos)(gpib_board_t *board);
+ /* configure parallel poll */
+ void (*parallel_poll_configure)(gpib_board_t *board, uint8_t configuration);
+ /* conduct parallel poll */
+ int (*parallel_poll)(gpib_board_t *board, uint8_t *result);
+ /* set/clear ist (individual status bit) */
+ void (*parallel_poll_response)(gpib_board_t *board, int ist);
+ /* select local parallel poll configuration mode PP2 versus remote PP1 */
+ void (*local_parallel_poll_mode)(gpib_board_t *board, int local);
+ /* Returns current status of the bus lines. Should be set to
+ * NULL if your board does not have the ability to query the
+ * state of the bus lines.
+ */
+ int (*line_status)(const gpib_board_t *board);
+ /* updates and returns the board's current status.
+ * The meaning of the bits are specified in gpib_user.h
+ * in the IBSTA section. The driver does not need to
+ * worry about setting the CMPL, END, TIMO, or ERR bits.
+ */
+ unsigned int (*update_status)(gpib_board_t *board, unsigned int clear_mask);
+ /* Sets primary address 0-30 for gpib interface card.
+ */
+ int (*primary_address)(gpib_board_t *board, unsigned int address);
+ /* Sets and enables, or disables secondary address 0-30
+ * for gpib interface card.
+ */
+ int (*secondary_address)(gpib_board_t *board, unsigned int address,
+ int enable);
+ /* Sets the byte the board should send in response to a serial poll.
+ * This function should also start or stop requests for service via
+ * IEEE 488.2 reqt/reqf, based on MSS (bit 6 of the status_byte).
+ * If the more flexible serial_poll_response2 is implemented by the
+ * driver, then this method should be left NULL since it will not
+ * be used. This method can generate spurious service requests
+ * which are allowed by IEEE 488.2, but not ideal.
+ *
+ * This method should implement the serial poll response method described
+ * by IEEE 488.2 section 11.3.3.4.3 "Allowed Coupled Control of
+ * STB, reqt, and reqf".
+ */
+ void (*serial_poll_response)(gpib_board_t *board, uint8_t status_byte);
+ /* Sets the byte the board should send in response to a serial poll.
+ * This function should also request service via IEEE 488.2 reqt/reqf
+ * based on MSS (bit 6 of the status_byte) and new_reason_for_service.
+ * reqt should be set true if new_reason_for_service is true,
+ * and reqf should be set true if MSS is false. This function
+ * will never be called with MSS false and new_reason_for_service
+ * true simultaneously, so don't worry about that case.
+ *
+ * This method implements the serial poll response method described
+ * by IEEE 488.2 section 11.3.3.4.1 "Preferred Implementation".
+ *
+ * If this method is left NULL by the driver, then the user library
+ * function ibrsv2 will not work.
+ */
+ void (*serial_poll_response2)(gpib_board_t *board, uint8_t status_byte,
+ int new_reason_for_service);
+ /* returns the byte the board will send in response to a serial poll.
+ */
+ uint8_t (*serial_poll_status)(gpib_board_t *board);
+ /* adjust T1 delay */
+ unsigned int (*t1_delay)(gpib_board_t *board, unsigned int nano_sec);
+ /* go to local mode */
+ void (*return_to_local)(gpib_board_t *board);
+ /* board does not support 7 bit eos comparisons */
+ unsigned no_7_bit_eos : 1;
+ /* skip check for listeners before trying to send command bytes */
+ unsigned skip_check_for_command_acceptors : 1;
+};
+
+typedef struct {
+ struct list_head event_head;
+ spinlock_t lock; // for access to event list
+ unsigned int num_events;
+ unsigned dropped_event : 1;
+} gpib_event_queue_t;
+
+static inline void init_event_queue(gpib_event_queue_t *queue)
+{
+ INIT_LIST_HEAD(&queue->event_head);
+ queue->num_events = 0;
+ queue->dropped_event = 0;
+ spin_lock_init(&queue->lock);
+}
+
+/* struct for supporting polling operation when irq is not available */
+struct gpib_pseudo_irq {
+ struct timer_list timer;
+ irqreturn_t (*handler)(int irq, void *arg);
+ gpib_board_t *board;
+ atomic_t active;
+};
+
+static inline void init_gpib_pseudo_irq(struct gpib_pseudo_irq *pseudo_irq)
+{
+ pseudo_irq->handler = NULL;
+ timer_setup(&pseudo_irq->timer, NULL, 0);
+ atomic_set(&pseudo_irq->active, 0);
+}
+
+/* list so we can make a linked list of drivers */
+typedef struct gpib_interface_list_struct {
+ struct list_head list;
+ gpib_interface_t *interface;
+ struct module *module;
+} gpib_interface_list_t;
+
+/* One gpib_board_t is allocated for each physical board in the computer.
+ * It provides storage for variables local to each board, and interface
+ * functions for performing operations on the board
+ */
+struct gpib_board_struct {
+ /* functions used by this board */
+ gpib_interface_t *interface;
+ /* Pointer to module whose use count we should increment when
+ * interface is in use
+ */
+ struct module *provider_module;
+ /* buffer used to store read/write data for this board */
+ u8 *buffer;
+ /* length of buffer */
+ unsigned int buffer_length;
+ /* Used to hold the board's current status (see update_status() above)
+ */
+ unsigned long status;
+ /* Driver should only sleep on this wait queue. It is special in that the
+ * core will wake this queue and set the TIMO bit in 'status' when the
+ * watchdog timer times out.
+ */
+ wait_queue_head_t wait;
+ /* Lock that only allows one process to access this board at a time.
+ * Has to be first in any locking order, since it can be locked over
+ * multiple ioctls.
+ */
+ struct mutex user_mutex;
+ /* Mutex which compensates for removal of "big kernel lock" from kernel.
+ * Should not be held for extended waits.
+ */
+ struct mutex big_gpib_mutex;
+ /* pid of last process to lock the board mutex */
+ pid_t locking_pid;
+ spinlock_t locking_pid_spinlock; // lock for setting locking pid
+ /* Spin lock for dealing with races with the interrupt handler */
+ spinlock_t spinlock;
+ /* Watchdog timer to enable timeouts */
+ struct timer_list timer;
+ /* device of attached driver if any */
+ struct device *dev;
+ /* gpib_common device gpibN */
+ struct device *gpib_dev;
+ /* 'private_data' can be used as seen fit by the driver to
+ * store additional variables for this board
+ */
+ void *private_data;
+ /* Number of open file descriptors using this board */
+ unsigned int use_count;
+ /* list of open devices connected to this board */
+ struct list_head device_list;
+ /* primary address */
+ unsigned int pad;
+ /* secondary address */
+ int sad;
+ /* timeout for io operations, in microseconds */
+ unsigned int usec_timeout;
+ /* board's parallel poll configuration byte */
+ u8 parallel_poll_configuration;
+ /* t1 delay we are using */
+ unsigned int t1_nano_sec;
+ /* Count that keeps track of whether board is up and running or not */
+ unsigned int online;
+ /* number of processes trying to autopoll */
+ int autospollers;
+ /* autospoll kernel thread */
+ struct task_struct *autospoll_task;
+ /* queue for recording received trigger/clear/ifc events */
+ gpib_event_queue_t event_queue;
+ /* minor number for this board's device file */
+ int minor;
+ /* struct to deal with polling mode*/
+ struct gpib_pseudo_irq pseudo_irq;
+ /* error dong autopoll */
+ atomic_t stuck_srq;
+ gpib_board_config_t config;
+ /* Flag that indicates whether board is system controller of the bus */
+ unsigned master : 1;
+ /* individual status bit */
+ unsigned ist : 1;
+ /* one means local parallel poll mode ieee 488.1 PP2 (or no parallel poll PP0),
+ * zero means remote parallel poll configuration mode ieee 488.1 PP1
+ */
+ unsigned local_ppoll_mode : 1;
+};
+
+/* element of event queue */
+typedef struct {
+ struct list_head list;
+ short event_type;
+} gpib_event_t;
+
+/* Each board has a list of gpib_status_queue_t to keep track of all open devices
+ * on the bus, so we know what address to poll when we get a service request
+ */
+typedef struct {
+ /* list_head so we can make a linked list of devices */
+ struct list_head list;
+ unsigned int pad; /* primary gpib address */
+ int sad; /* secondary gpib address (negative means disabled) */
+ /* stores serial poll bytes for this device */
+ struct list_head status_bytes;
+ unsigned int num_status_bytes;
+ /* number of times this address is opened */
+ unsigned int reference_count;
+ /* flags loss of status byte error due to limit on size of queue */
+ unsigned dropped_byte : 1;
+} gpib_status_queue_t;
+
+typedef struct {
+ struct list_head list;
+ u8 poll_byte;
+} status_byte_t;
+
+void init_gpib_status_queue(gpib_status_queue_t *device);
+
+/* Used to store device-descriptor-specific information */
+typedef struct {
+ unsigned int pad; /* primary gpib address */
+ int sad; /* secondary gpib address (negative means disabled) */
+ atomic_t io_in_progress;
+ unsigned is_board : 1;
+ unsigned autopoll_enabled : 1;
+} gpib_descriptor_t;
+
+typedef struct {
+ atomic_t holding_mutex;
+ gpib_descriptor_t *descriptors[GPIB_MAX_NUM_DESCRIPTORS];
+ /* locked while descriptors are being allocated/deallocated */
+ struct mutex descriptors_mutex;
+ unsigned got_module : 1;
+} gpib_file_private_t;
+
+#endif /* __KERNEL__ */
+
+#endif /* _GPIB_TYPES_H */
diff --git a/drivers/staging/gpib/include/nec7210.h b/drivers/staging/gpib/include/nec7210.h
new file mode 100644
index 000000000000..c00aba4ce846
--- /dev/null
+++ b/drivers/staging/gpib/include/nec7210.h
@@ -0,0 +1,138 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _NEC7210_H
+#define _NEC7210_H
+
+#include "gpib_state_machines.h"
+#include <linux/types.h>
+#include <linux/spinlock.h>
+#include <linux/string.h>
+#include <linux/interrupt.h>
+
+#include "gpib_types.h"
+#include "nec7210_registers.h"
+
+/* struct used to provide variables local to a nec7210 chip */
+struct nec7210_priv {
+ void *iobase;
+ unsigned int offset; // offset between successive nec7210 io addresses
+ unsigned int dma_channel;
+ u8 *dma_buffer;
+ unsigned int dma_buffer_length; // length of dma buffer
+ dma_addr_t dma_buffer_addr; // bus address of board->buffer for use with dma
+ // software copy of bits written to registers
+ u8 reg_bits[8];
+ u8 auxa_bits; // bits written to auxiliary register A
+ u8 auxb_bits; // bits written to auxiliary register B
+ // used to keep track of board's state, bit definitions given below
+ unsigned long state;
+ /* lock for chips that extend the nec7210 registers by paging in alternate regs */
+ spinlock_t register_page_lock;
+ // wrappers for outb, inb, readb, or writeb
+ u8 (*read_byte)(struct nec7210_priv *priv, unsigned int register_number);
+ void (*write_byte)(struct nec7210_priv *priv, u8 byte, unsigned int register_number);
+ enum nec7210_chipset type;
+ enum talker_function_state talker_state;
+ enum listener_function_state listener_state;
+ void *private;
+ unsigned srq_pending : 1;
+};
+
+static inline void init_nec7210_private(struct nec7210_priv *priv)
+{
+ memset(priv, 0, sizeof(struct nec7210_priv));
+ spin_lock_init(&priv->register_page_lock);
+}
+
+// slightly shorter way to access read_byte and write_byte
+static inline u8 read_byte(struct nec7210_priv *priv, unsigned int register_number)
+{
+ return priv->read_byte(priv, register_number);
+}
+
+static inline void write_byte(struct nec7210_priv *priv, u8 byte, unsigned int register_number)
+{
+ priv->write_byte(priv, byte, register_number);
+}
+
+// struct nec7210_priv.state bit numbers
+enum {
+ PIO_IN_PROGRESS_BN, // pio transfer in progress
+ DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress
+ DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress
+ READ_READY_BN, // board has data byte available to read
+ WRITE_READY_BN, // board is ready to send a data byte
+ COMMAND_READY_BN, // board is ready to send a command byte
+ RECEIVED_END_BN, // received END
+ BUS_ERROR_BN, // output error has occurred
+ RFD_HOLDOFF_BN, // rfd holdoff in effect
+ DEV_CLEAR_BN, // device clear received
+ ADR_CHANGE_BN, // address state change occurred
+};
+
+// interface functions
+int nec7210_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read);
+int nec7210_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, int send_eoi, size_t *bytes_written);
+int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written);
+int nec7210_take_control(gpib_board_t *board, struct nec7210_priv *priv, int syncronous);
+int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv);
+void nec7210_request_system_control(gpib_board_t *board,
+ struct nec7210_priv *priv, int request_control);
+void nec7210_interface_clear(gpib_board_t *board, struct nec7210_priv *priv, int assert);
+void nec7210_remote_enable(gpib_board_t *board, struct nec7210_priv *priv, int enable);
+int nec7210_enable_eos(gpib_board_t *board, struct nec7210_priv *priv, uint8_t eos_bytes,
+ int compare_8_bits);
+void nec7210_disable_eos(gpib_board_t *board, struct nec7210_priv *priv);
+unsigned int nec7210_update_status(gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int clear_mask);
+unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_priv *priv);
+int nec7210_primary_address(const gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int address);
+int nec7210_secondary_address(const gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int address, int enable);
+int nec7210_parallel_poll(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *result);
+void nec7210_serial_poll_response(gpib_board_t *board, struct nec7210_priv *priv, uint8_t status);
+void nec7210_parallel_poll_configure(gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int configuration);
+void nec7210_parallel_poll_response(gpib_board_t *board,
+ struct nec7210_priv *priv, int ist);
+uint8_t nec7210_serial_poll_status(gpib_board_t *board,
+ struct nec7210_priv *priv);
+unsigned int nec7210_t1_delay(gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int nano_sec);
+void nec7210_return_to_local(const gpib_board_t *board, struct nec7210_priv *priv);
+
+// utility functions
+void nec7210_board_reset(struct nec7210_priv *priv, const gpib_board_t *board);
+void nec7210_board_online(struct nec7210_priv *priv, const gpib_board_t *board);
+unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg,
+ unsigned int mask, unsigned int bits);
+void nec7210_set_handshake_mode(gpib_board_t *board, struct nec7210_priv *priv, int mode);
+void nec7210_release_rfd_holdoff(gpib_board_t *board, struct nec7210_priv *priv);
+uint8_t nec7210_read_data_in(gpib_board_t *board, struct nec7210_priv *priv, int *end);
+
+// wrappers for io functions
+uint8_t nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_ioport_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num);
+uint8_t nec7210_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_iomem_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num);
+uint8_t nec7210_locking_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_locking_ioport_write_byte(struct nec7210_priv *priv, uint8_t data,
+ unsigned int register_num);
+uint8_t nec7210_locking_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num);
+void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, uint8_t data,
+ unsigned int register_num);
+
+// interrupt service routine
+irqreturn_t nec7210_interrupt(gpib_board_t *board, struct nec7210_priv *priv);
+irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board,
+ struct nec7210_priv *priv, int status1, int status2);
+
+#endif //_NEC7210_H
diff --git a/drivers/staging/gpib/include/nec7210_registers.h b/drivers/staging/gpib/include/nec7210_registers.h
new file mode 100644
index 000000000000..888803dd97f9
--- /dev/null
+++ b/drivers/staging/gpib/include/nec7210_registers.h
@@ -0,0 +1,217 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _NEC7210_REGISTERS_H
+#define _NEC7210_REGISTERS_H
+
+enum nec7210_chipset {
+ NEC7210, // The original
+ TNT4882, // NI
+ NAT4882, // NI
+ CB7210, // measurement computing
+ IOT7210, // iotech
+ IGPIB7210, // Ines
+ TNT5004, // NI (minor differences to TNT4882)
+};
+
+/* nec7210 register numbers (might need to be multiplied by
+ * a board-dependent offset to get actually io address offset)
+ */
+// write registers
+enum nec7210_write_regs {
+ CDOR, // command/data out
+ IMR1, // interrupt mask 1
+ IMR2, // interrupt mask 2
+ SPMR, // serial poll mode
+ ADMR, // address mode
+ AUXMR, // auxiliary mode
+ ADR, // address
+ EOSR, // end-of-string
+
+ // nec7210 has 8 registers
+ nec7210_num_registers = 8,
+};
+
+// read registers
+enum nec7210_read_regs {
+ DIR, // data in
+ ISR1, // interrupt status 1
+ ISR2, // interrupt status 2
+ SPSR, // serial poll status
+ ADSR, // address status
+ CPTR, // command pass though
+ ADR0, // address 1
+ ADR1, // address 2
+};
+
+//bit definitions common to nec-7210 compatible registers
+
+// ISR1: interrupt status register 1
+enum isr1_bits {
+ HR_DI = (1 << 0),
+ HR_DO = (1 << 1),
+ HR_ERR = (1 << 2),
+ HR_DEC = (1 << 3),
+ HR_END = (1 << 4),
+ HR_DET = (1 << 5),
+ HR_APT = (1 << 6),
+ HR_CPT = (1 << 7),
+};
+
+// IMR1: interrupt mask register 1
+enum imr1_bits {
+ HR_DIIE = (1 << 0),
+ HR_DOIE = (1 << 1),
+ HR_ERRIE = (1 << 2),
+ HR_DECIE = (1 << 3),
+ HR_ENDIE = (1 << 4),
+ HR_DETIE = (1 << 5),
+ HR_APTIE = (1 << 6),
+ HR_CPTIE = (1 << 7),
+};
+
+// ISR2, interrupt status register 2
+enum isr2_bits {
+ HR_ADSC = (1 << 0),
+ HR_REMC = (1 << 1),
+ HR_LOKC = (1 << 2),
+ HR_CO = (1 << 3),
+ HR_REM = (1 << 4),
+ HR_LOK = (1 << 5),
+ HR_SRQI = (1 << 6),
+ HR_INT = (1 << 7),
+};
+
+// IMR2, interrupt mask register 2
+enum imr2_bits {
+ // all the bits in this register that enable interrupts
+ IMR2_ENABLE_INTR_MASK = 0x4f,
+ HR_ACIE = (1 << 0),
+ HR_REMIE = (1 << 1),
+ HR_LOKIE = (1 << 2),
+ HR_COIE = (1 << 3),
+ HR_DMAI = (1 << 4),
+ HR_DMAO = (1 << 5),
+ HR_SRQIE = (1 << 6),
+};
+
+// SPSR, serial poll status register
+enum spsr_bits {
+ HR_PEND = (1 << 6),
+};
+
+// SPMR, serial poll mode register
+enum spmr_bits {
+ HR_RSV = (1 << 6),
+};
+
+// ADSR, address status register
+enum adsr_bits {
+ HR_MJMN = (1 << 0),
+ HR_TA = (1 << 1),
+ HR_LA = (1 << 2),
+ HR_TPAS = (1 << 3),
+ HR_LPAS = (1 << 4),
+ HR_SPMS = (1 << 5),
+ HR_NATN = (1 << 6),
+ HR_CIC = (1 << 7),
+};
+
+// ADMR, address mode register
+enum admr_bits {
+ HR_ADM0 = (1 << 0),
+ HR_ADM1 = (1 << 1),
+ HR_TRM0 = (1 << 4),
+ HR_TRM1 = (1 << 5),
+ HR_TRM_EOIOE_TRIG = 0,
+ HR_TRM_CIC_TRIG = HR_TRM0,
+ HR_TRM_CIC_EOIOE = HR_TRM1,
+ HR_TRM_CIC_PE = HR_TRM0 | HR_TRM1,
+ HR_LON = (1 << 6),
+ HR_TON = (1 << 7),
+};
+
+// ADR, bits used in address0, address1 and address0/1 registers
+enum adr_bits {
+ ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits */
+ HR_DL = (1 << 5),
+ HR_DT = (1 << 6),
+ HR_ARS = (1 << 7),
+};
+
+// ADR1, address1 register
+enum adr1_bits {
+ HR_EOI = (1 << 7),
+};
+
+// AUXMR, auxiliary mode register
+enum auxmr_bits {
+ ICR = 0x20,
+ PPR = 0x60,
+ AUXRA = 0x80,
+ AUXRB = 0xa0,
+ AUXRE = 0xc0,
+};
+
+// auxra, auxiliary register A
+enum auxra_bits {
+ HR_HANDSHAKE_MASK = 0x3,
+ HR_HLDA = 0x1,
+ HR_HLDE = 0x2,
+ HR_LCM = 0x3, /* auxra listen continuous */
+ HR_REOS = 0x4,
+ HR_XEOS = 0x8,
+ HR_BIN = 0x10,
+};
+
+// auxrb, auxiliary register B
+enum auxrb_bits {
+ HR_CPTE = (1 << 0),
+ HR_SPEOI = (1 << 1),
+ HR_TRI = (1 << 2),
+ HR_INV = (1 << 3),
+ HR_ISS = (1 << 4),
+};
+
+enum auxre_bits {
+ HR_DAC_HLD_DCAS = 0x1, /* perform DAC holdoff on receiving clear */
+ HR_DAC_HLD_DTAS = 0x2, /* perform DAC holdoff on receiving trigger */
+};
+
+// parallel poll register
+enum ppr_bits {
+ HR_PPS = (1 << 3),
+ HR_PPU = (1 << 4),
+};
+
+/* 7210 Auxiliary Commands */
+enum aux_cmds {
+ AUX_PON = 0x0, /* Immediate Execute pon */
+ AUX_CPPF = 0x1, /* Clear Parallel Poll Flag */
+ AUX_CR = 0x2, /* Chip Reset */
+ AUX_FH = 0x3, /* Finish Handshake */
+ AUX_TRIG = 0x4, /* Trigger */
+ AUX_RTL = 0x5, /* Return to local */
+ AUX_SEOI = 0x6, /* Send EOI */
+ AUX_NVAL = 0x7, /* Non-Valid Secondary Command or Address */
+ AUX_SPPF = 0x9, /* Set Parallel Poll Flag */
+ AUX_VAL = 0xf, /* Valid Secondary Command or Address */
+ AUX_GTS = 0x10, /* Go To Standby */
+ AUX_TCA = 0x11, /* Take Control Asynchronously */
+ AUX_TCS = 0x12, /* Take Control Synchronously */
+ AUX_LTN = 0x13, /* Listen */
+ AUX_DSC = 0x14, /* Disable System Control */
+ AUX_CIFC = 0x16, /* Clear IFC */
+ AUX_CREN = 0x17, /* Clear REN */
+ AUX_TCSE = 0x1a, /* Take Control Synchronously on End */
+ AUX_LTNC = 0x1b, /* Listen in Continuous Mode */
+ AUX_LUN = 0x1c, /* Local Unlisten */
+ AUX_EPP = 0x1d, /* Execute Parallel Poll */
+ AUX_SIFC = 0x1e, /* Set IFC */
+ AUX_SREN = 0x1f, /* Set REN */
+};
+
+#endif //_NEC7210_REGISTERS_H
diff --git a/drivers/staging/gpib/include/plx9050.h b/drivers/staging/gpib/include/plx9050.h
new file mode 100644
index 000000000000..66c56335f5c0
--- /dev/null
+++ b/drivers/staging/gpib/include/plx9050.h
@@ -0,0 +1,72 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Header for plx9050 pci chip
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _PLX9050_GPIB_H
+#define _PLX9050_GPIB_H
+
+// plx pci chip registers and bits
+enum {
+ PLX9050_INTCSR_REG = 0x4c,
+ PLX9050_CNTRL_REG = 0x50
+};
+
+enum plx9050_intcsr_bits {
+ PLX9050_LINTR1_EN_BIT = 0x1,
+ PLX9050_LINTR1_POLARITY_BIT = 0x2,
+ PLX9050_LINTR1_STATUS_BIT = 0x4,
+ PLX9050_LINTR2_EN_BIT = 0x8,
+ PLX9050_LINTR2_POLARITY_BIT = 0x10,
+ PLX9050_LINTR2_STATUS_BIT = 0x20,
+ PLX9050_PCI_INTR_EN_BIT = 0x40,
+ PLX9050_SOFT_INTR_BIT = 0x80,
+ PLX9050_LINTR1_SELECT_ENABLE_BIT = 0x100, //9052 extension
+ PLX9050_LINTR2_SELECT_ENABLE_BIT = 0x200, //9052 extension
+ PLX9050_LINTR1_EDGE_CLEAR_BIT = 0x400, //9052 extension
+ PLX9050_LINTR2_EDGE_CLEAR_BIT = 0x800, //9052 extension
+};
+
+enum plx9050_cntrl_bits {
+ PLX9050_WAITO_NOT_USER0_SELECT_BIT = 0x1,
+ PLX9050_USER0_OUTPUT_BIT = 0x2,
+ PLX9050_USER0_DATA_BIT = 0x4,
+ PLX9050_LLOCK_NOT_USER1_SELECT_BIT = 0x8,
+ PLX9050_USER1_OUTPUT_BIT = 0x10,
+ PLX9050_USER1_DATA_BIT = 0x20,
+ PLX9050_CS2_NOT_USER2_SELECT_BIT = 0x40,
+ PLX9050_USER2_OUTPUT_BIT = 0x80,
+ PLX9050_USER2_DATA_BIT = 0x100,
+ PLX9050_CS3_NOT_USER3_SELECT_BIT = 0x200,
+ PLX9050_USER3_OUTPUT_BIT = 0x400,
+ PLX9050_USER3_DATA_BIT = 0x800,
+ PLX9050_PCIBAR_ENABLE_MASK = 0x3000,
+ PLX9050_PCIBAR_MEMORY_AND_IO_ENABLE_BITS = 0x0,
+ PLX9050_PCIBAR_MEMORY_NO_IO_ENABLE_BITS = 0x1000,
+ PLX9050_PCIBAR_IO_NO_MEMORY_ENABLE_BITS = 0x2000,
+ PLX9050_PCIBAR_MEMORY_AND_IO_TOO_ENABLE_BITS = 0x3000,
+ PLX9050_PCI_READ_MODE_BIT = 0x4000,
+ PLX9050_PCI_READ_WITH_WRITE_FLUSH_MODE_BIT = 0x8000,
+ PLX9050_PCI_READ_NO_FLUSH_MODE_BIT = 0x10000,
+ PLX9050_PCI_READ_NO_WRITE_MODE_BIT = 0x20000,
+ PLX9050_PCI_WRITE_MODE_BIT = 0x40000,
+ PLX9050_PCI_RETRY_DELAY_MASK = 0x780000,
+ PLX9050_DIRECT_SLAVE_LOCK_ENABLE_BIT = 0x800000,
+ PLX9050_EEPROM_CLOCK_BIT = 0x1000000,
+ PLX9050_EEPROM_CHIP_SELECT_BIT = 0x2000000,
+ PLX9050_WRITE_TO_EEPROM_BIT = 0x4000000,
+ PLX9050_READ_EEPROM_DATA_BIT = 0x8000000,
+ PLX9050_EEPROM_VALID_BIT = 0x10000000,
+ PLX9050_RELOAD_CONFIG_REGISTERS_BIT = 0x20000000,
+ PLX9050_PCI_SOFTWARE_RESET_BIT = 0x40000000,
+ PLX9050_MASK_REVISION_BIT = 0x80000000
+};
+
+static inline unsigned int PLX9050_PCI_RETRY_DELAY_BITS(unsigned int clocks)
+{
+ return ((clocks / 8) << 19) & PLX9050_PCI_RETRY_DELAY_MASK;
+}
+
+#endif // _PLX9050_GPIB_H
diff --git a/drivers/staging/gpib/include/quancom_pci.h b/drivers/staging/gpib/include/quancom_pci.h
new file mode 100644
index 000000000000..cdaf0d056be9
--- /dev/null
+++ b/drivers/staging/gpib/include/quancom_pci.h
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Quancom pci stuff
+ * copyright (C) 2005 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _QUANCOM_PCI_H
+#define _QUANCOM_PCI_H
+
+/* quancom registers */
+enum quancom_regs {
+ QUANCOM_IRQ_CONTROL_STATUS_REG = 0xfc,
+};
+
+enum quancom_irq_control_status_bits {
+ QUANCOM_IRQ_ASSERTED_BIT = 0x1, /* readable */
+ /* (any write to the register clears the interrupt)*/
+ QUANCOM_IRQ_ENABLE_BIT = 0x4, /* writeable */
+};
+
+#endif // _QUANCOM_PCI_H
diff --git a/drivers/staging/gpib/include/tms9914.h b/drivers/staging/gpib/include/tms9914.h
new file mode 100644
index 000000000000..456b488212d2
--- /dev/null
+++ b/drivers/staging/gpib/include/tms9914.h
@@ -0,0 +1,274 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _TMS9914_H
+#define _TMS9914_H
+
+#include <linux/types.h>
+#include <linux/interrupt.h>
+#include "gpib_state_machines.h"
+#include "gpib_types.h"
+
+enum tms9914_holdoff_mode {
+ TMS9914_HOLDOFF_NONE,
+ TMS9914_HOLDOFF_EOI,
+ TMS9914_HOLDOFF_ALL,
+};
+
+/* struct used to provide variables local to a tms9914 chip */
+struct tms9914_priv {
+ void *iobase;
+ unsigned int offset; // offset between successive tms9914 io addresses
+ unsigned int dma_channel;
+ // software copy of bits written to interrupt mask registers
+ u8 imr0_bits, imr1_bits;
+ // bits written to address mode register
+ u8 admr_bits;
+ u8 auxa_bits; // bits written to auxiliary register A
+ // used to keep track of board's state, bit definitions given below
+ unsigned long state;
+ u8 eos; // eos character
+ short eos_flags;
+ u8 spoll_status;
+ enum tms9914_holdoff_mode holdoff_mode;
+ unsigned int ppoll_line;
+ enum talker_function_state talker_state;
+ enum listener_function_state listener_state;
+ unsigned ppoll_sense : 1;
+ unsigned ppoll_enable : 1;
+ unsigned ppoll_configure_state : 1;
+ unsigned primary_listen_addressed : 1;
+ unsigned primary_talk_addressed : 1;
+ unsigned holdoff_on_end : 1;
+ unsigned holdoff_on_all : 1;
+ unsigned holdoff_active : 1;
+ // wrappers for outb, inb, readb, or writeb
+ u8 (*read_byte)(struct tms9914_priv *priv, unsigned int register_number);
+ void (*write_byte)(struct tms9914_priv *priv, u8 byte, unsigned int
+ register_number);
+};
+
+// slightly shorter way to access read_byte and write_byte
+static inline u8 read_byte(struct tms9914_priv *priv, unsigned int register_number)
+{
+ return priv->read_byte(priv, register_number);
+}
+
+static inline void write_byte(struct tms9914_priv *priv, u8 byte, unsigned int register_number)
+{
+ priv->write_byte(priv, byte, register_number);
+}
+
+// struct tms9914_priv.state bit numbers
+enum {
+ PIO_IN_PROGRESS_BN, // pio transfer in progress
+ DMA_READ_IN_PROGRESS_BN, // dma read transfer in progress
+ DMA_WRITE_IN_PROGRESS_BN, // dma write transfer in progress
+ READ_READY_BN, // board has data byte available to read
+ WRITE_READY_BN, // board is ready to send a data byte
+ COMMAND_READY_BN, // board is ready to send a command byte
+ RECEIVED_END_BN, // received END
+ BUS_ERROR_BN, // bus error
+ DEV_CLEAR_BN, // device clear received
+};
+
+// interface functions
+int tms9914_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read);
+int tms9914_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, int send_eoi, size_t *bytes_written);
+int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written);
+int tms9914_take_control(gpib_board_t *board, struct tms9914_priv *priv, int syncronous);
+/* alternate version of tms9914_take_control which works around buggy tcs
+ * implementation.
+ */
+int tms9914_take_control_workaround(gpib_board_t *board, struct tms9914_priv *priv,
+ int syncronous);
+int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv);
+void tms9914_request_system_control(gpib_board_t *board, struct tms9914_priv *priv,
+ int request_control);
+void tms9914_interface_clear(gpib_board_t *board, struct tms9914_priv *priv, int assert);
+void tms9914_remote_enable(gpib_board_t *board, struct tms9914_priv *priv, int enable);
+int tms9914_enable_eos(gpib_board_t *board, struct tms9914_priv *priv, uint8_t eos_bytes,
+ int compare_8_bits);
+void tms9914_disable_eos(gpib_board_t *board, struct tms9914_priv *priv);
+unsigned int tms9914_update_status(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int clear_mask);
+int tms9914_primary_address(gpib_board_t *board,
+ struct tms9914_priv *priv, unsigned int address);
+int tms9914_secondary_address(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int address, int enable);
+int tms9914_parallel_poll(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *result);
+void tms9914_parallel_poll_configure(gpib_board_t *board,
+ struct tms9914_priv *priv, uint8_t config);
+void tms9914_parallel_poll_response(gpib_board_t *board,
+ struct tms9914_priv *priv, int ist);
+void tms9914_serial_poll_response(gpib_board_t *board, struct tms9914_priv *priv, uint8_t status);
+uint8_t tms9914_serial_poll_status(gpib_board_t *board, struct tms9914_priv *priv);
+int tms9914_line_status(const gpib_board_t *board, struct tms9914_priv *priv);
+unsigned int tms9914_t1_delay(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int nano_sec);
+void tms9914_return_to_local(const gpib_board_t *board, struct tms9914_priv *priv);
+
+// utility functions
+void tms9914_board_reset(struct tms9914_priv *priv);
+void tms9914_online(gpib_board_t *board, struct tms9914_priv *priv);
+void tms9914_release_holdoff(struct tms9914_priv *priv);
+void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode);
+
+// wrappers for io functions
+uint8_t tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num);
+void tms9914_ioport_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num);
+uint8_t tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num);
+void tms9914_iomem_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num);
+
+// interrupt service routine
+irqreturn_t tms9914_interrupt(gpib_board_t *board, struct tms9914_priv *priv);
+irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_priv *priv,
+ int status1, int status2);
+
+// tms9914 has 8 registers
+enum {
+ ms9914_num_registers = 8,
+};
+
+/* tms9914 register numbers (might need to be multiplied by
+ * a board-dependent offset to get actually io address offset)
+ */
+// write registers
+enum {
+ IMR0 = 0, /* interrupt mask 0 */
+ IMR1 = 1, /* interrupt mask 1 */
+ AUXCR = 3, /* auxiliary command */
+ ADR = 4, // address register
+ SPMR = 5, // serial poll mode register
+ PPR = 6, /* parallel poll */
+ CDOR = 7, /* data out register */
+};
+
+// read registers
+enum {
+ ISR0 = 0, /* interrupt status 0 */
+ ISR1 = 1, /* interrupt status 1 */
+ ADSR = 2, /* address status */
+ BSR = 3, /* bus status */
+ CPTR = 6, /* command pass thru */
+ DIR = 7, /* data in register */
+};
+
+//bit definitions common to tms9914 compatible registers
+
+/* ISR0 - Register bits */
+enum isr0_bits {
+ HR_MAC = (1 << 0), /* My Address Change */
+ HR_RLC = (1 << 1), /* Remote/Local change */
+ HR_SPAS = (1 << 2), /* Serial Poll active State */
+ HR_END = (1 << 3), /* END (EOI or EOS) */
+ HR_BO = (1 << 4), /* Byte Out */
+ HR_BI = (1 << 5), /* Byte In */
+};
+
+/* IMR0 - Register bits */
+enum imr0_bits {
+ HR_MACIE = (1 << 0), /* */
+ HR_RLCIE = (1 << 1), /* */
+ HR_SPASIE = (1 << 2), /* */
+ HR_ENDIE = (1 << 3), /* */
+ HR_BOIE = (1 << 4), /* */
+ HR_BIIE = (1 << 5), /* */
+};
+
+/* ISR1 - Register bits */
+enum isr1_bits {
+ HR_IFC = (1 << 0), /* IFC asserted */
+ HR_SRQ = (1 << 1), /* SRQ asserted */
+ HR_MA = (1 << 2), /* My Address */
+ HR_DCAS = (1 << 3), /* Device Clear active State */
+ HR_APT = (1 << 4), /* Address pass Through */
+ HR_UNC = (1 << 5), /* Unrecognized Command */
+ HR_ERR = (1 << 6), /* Data Transmission Error */
+ HR_GET = (1 << 7), /* Group execute Trigger */
+};
+
+/* IMR1 - Register bits */
+enum imr1_bits {
+ HR_IFCIE = (1 << 0), /* */
+ HR_SRQIE = (1 << 1), /* */
+ HR_MAIE = (1 << 2), /* */
+ HR_DCASIE = (1 << 3), /* */
+ HR_APTIE = (1 << 4), /* */
+ HR_UNCIE = (1 << 5), /* */
+ HR_ERRIE = (1 << 6), /* */
+ HR_GETIE = (1 << 7), /* */
+};
+
+/* ADSR - Register bits */
+enum adsr_bits {
+ HR_ULPA = (1 << 0), /* Store last address LSB */
+ HR_TA = (1 << 1), /* Talker Adressed */
+ HR_LA = (1 << 2), /* Listener adressed */
+ HR_TPAS = (1 << 3), /* talker primary address state */
+ HR_LPAS = (1 << 4), /* listener " */
+ HR_ATN = (1 << 5), /* ATN active */
+ HR_LLO = (1 << 6), /* LLO active */
+ HR_REM = (1 << 7), /* REM active */
+};
+
+/* ADR - Register bits */
+enum adr_bits {
+ ADDRESS_MASK = 0x1f, /* mask to specify lower 5 bits for ADR */
+ HR_DAT = (1 << 5), /* disable talker */
+ HR_DAL = (1 << 6), /* disable listener */
+ HR_EDPA = (1 << 7), /* enable dual primary addressing */
+};
+
+enum bus_status_bits {
+ BSR_REN_BIT = 0x1,
+ BSR_IFC_BIT = 0x2,
+ BSR_SRQ_BIT = 0x4,
+ BSR_EOI_BIT = 0x8,
+ BSR_NRFD_BIT = 0x10,
+ BSR_NDAC_BIT = 0x20,
+ BSR_DAV_BIT = 0x40,
+ BSR_ATN_BIT = 0x80,
+};
+
+/*---------------------------------------------------------*/
+/* TMS 9914 Auxiliary Commands */
+/*---------------------------------------------------------*/
+
+enum aux_cmd_bits {
+ AUX_CS = 0x80, /* set bit instead of clearing it, used with commands marked 'd' below */
+ AUX_CHIP_RESET = 0x0, /* d Chip reset */
+ AUX_INVAL = 0x1, // release dac holdoff, invalid command byte
+ AUX_VAL = (AUX_INVAL | AUX_CS), // release dac holdoff, valid command byte
+ AUX_RHDF = 0x2, /* X Release RFD holdoff */
+ AUX_HLDA = 0x3, /* d holdoff on all data */
+ AUX_HLDE = 0x4, /* d holdoff on EOI only */
+ AUX_NBAF = 0x5, /* X Set new byte available false */
+ AUX_FGET = 0x6, /* d force GET */
+ AUX_RTL = 0x7, /* d return to local */
+ AUX_SEOI = 0x8, /* X send EOI with next byte */
+ AUX_LON = 0x9, /* d Listen only */
+ AUX_TON = 0xa, /* d Talk only */
+ AUX_GTS = 0xb, /* X goto standby */
+ AUX_TCA = 0xc, /* X take control asynchronously */
+ AUX_TCS = 0xd, /* X take " synchronously */
+ AUX_RPP = 0xe, /* d Request parallel poll */
+ AUX_SIC = 0xf, /* d send interface clear */
+ AUX_SRE = 0x10, /* d send remote enable */
+ AUX_RQC = 0x11, /* X request control */
+ AUX_RLC = 0x12, /* X release control */
+ AUX_DAI = 0x13, /* d disable all interrupts */
+ AUX_PTS = 0x14, /* X pass through next secondary */
+ AUX_STDL = 0x15, /* d short T1 delay */
+ AUX_SHDW = 0x16, /* d shadow handshake */
+ AUX_VSTDL = 0x17, /* d very short T1 delay (smj9914 extension) */
+ AUX_RSV2 = 0x18, /* d request service bit 2 (smj9914 extension) */
+};
+
+#endif //_TMS9914_H
diff --git a/drivers/staging/gpib/include/tnt4882_registers.h b/drivers/staging/gpib/include/tnt4882_registers.h
new file mode 100644
index 000000000000..1b1441cd03d5
--- /dev/null
+++ b/drivers/staging/gpib/include/tnt4882_registers.h
@@ -0,0 +1,192 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002, 2004 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _TNT4882_REGISTERS_H
+#define _TNT4882_REGISTERS_H
+
+// tnt4882 register offsets
+enum {
+ ACCWR = 0x5,
+ // offset of auxiliary command register in 9914 mode
+ AUXCR = 0x6,
+ INTRT = 0x7,
+ // register number for auxiliary command register when swap bit is set (9914 mode)
+ SWAPPED_AUXCR = 0xa,
+ HSSEL = 0xd, // handshake select register
+ CNT2 = 0x9,
+ CNT3 = 0xb,
+ CFG = 0x10,
+ SASR = 0x1b,
+ IMR0 = 0x1d,
+ IMR3 = 0x12,
+ CNT0 = 0x14,
+ CNT1 = 0x16,
+ KEYREG = 0x17, // key control register (7210 mode only)
+ CSR = KEYREG,
+ FIFOB = 0x18,
+ FIFOA = 0x19,
+ CCR = 0x1a, // carry cycle register
+ CMDR = 0x1c, // command register
+ TIMER = 0x1e, // timer register
+
+ STS1 = 0x10, /* T488 Status Register 1 */
+ STS2 = 0x1c, /* T488 Status Register 2 */
+ ISR0 = IMR0,
+ ISR3 = 0x1a, /* T488 Interrupt Status Register 3 */
+ BCR = 0x1f, /* bus control/status register */
+ BSR = BCR,
+};
+
+enum {
+ tnt_pagein_offset = 0x11,
+};
+
+/*============================================================*/
+
+/* TURBO-488 registers bit definitions */
+
+enum bus_control_status_bits {
+ BCSR_REN_BIT = 0x1,
+ BCSR_IFC_BIT = 0x2,
+ BCSR_SRQ_BIT = 0x4,
+ BCSR_EOI_BIT = 0x8,
+ BCSR_NRFD_BIT = 0x10,
+ BCSR_NDAC_BIT = 0x20,
+ BCSR_DAV_BIT = 0x40,
+ BCSR_ATN_BIT = 0x80,
+};
+
+/* CFG -- Configuration Register (write only) */
+enum cfg_bits {
+ TNT_COMMAND = 0x80, /* bytes are command bytes instead of data bytes
+ * (tnt4882 one-chip and newer only?)
+ */
+ TNT_TLCHE = (1 << 6), /* halt transfer on imr0, imr1, or imr2 interrupt */
+ TNT_IN = (1 << 5), /* transfer is GPIB read */
+ TNT_A_B = (1 << 4), /* order to use fifos 1=fifo A first(big endian),
+ * 0=fifo b first(little endian)
+ */
+ TNT_CCEN = (1 << 3), /* enable carry cycle */
+ TNT_TMOE = (1 << 2), /* enable CPU bus time limit */
+ TNT_TIM_BYTN = (1 << 1), /* tmot reg is: 1=125ns clocks, 0=num bytes */
+ TNT_B_16BIT = (1 << 0), /* 1=FIFO is 16-bit register, 0=8-bit */
+};
+
+/* CMDR -- Command Register */
+enum cmdr_bits {
+ CLRSC = 0x2, /* clear the system controller bit */
+ SETSC = 0x3, /* set the system controller bit */
+ GO = 0x4, /* start fifos */
+ STOP = 0x8, /* stop fifos */
+ RESET_FIFO = 0x10, /* reset the FIFOs */
+ SOFT_RESET = 0x22, /* issue a software reset */
+ HARD_RESET = 0x40 /* 500x only? */
+};
+
+/* HSSEL -- handshake select register (write only) */
+enum hssel_bits {
+ TNT_ONE_CHIP_BIT = 0x1,
+ NODMA = 0x10,
+ TNT_GO2SIDS_BIT = 0x20,
+};
+
+/* IMR0 -- Interrupt Mode Register 0 */
+enum imr0_bits {
+ TNT_SYNCIE_BIT = 0x1, /* handshake sync */
+ TNT_TOIE_BIT = 0x2, /* timeout */
+ TNT_ATNIE_BIT = 0x4, /* ATN interrupt */
+ TNT_IFCIE_BIT = 0x8, /* interface clear interrupt */
+ TNT_BTO_BIT = 0x10, /* byte timeout */
+ TNT_NLEN_BIT = 0x20, /* treat new line as EOS char */
+ TNT_STBOIE_BIT = 0x40, /* status byte out */
+ TNT_IMR0_ALWAYS_BITS = 0x80, /* always set this bit on write */
+};
+
+/* ISR0 -- Interrupt Status Register 0 */
+enum isr0_bits {
+ TNT_SYNC_BIT = 0x1, /* handshake sync */
+ TNT_TO_BIT = 0x2, /* timeout */
+ TNT_ATNI_BIT = 0x4, /* ATN interrupt */
+ TNT_IFCI_BIT = 0x8, /* interface clear interrupt */
+ TNT_EOS_BIT = 0x10, /* end of string */
+ TNT_NL_BIT = 0x20, /* new line receive */
+ TNT_STBO_BIT = 0x40, /* status byte out */
+ TNT_NBA_BIT = 0x80, /* new byte available */
+};
+
+/* ISR3 -- Interrupt Status Register 3 (read only) */
+enum isr3_bits {
+ HR_DONE = (1 << 0), /* transfer done */
+ HR_TLCI = (1 << 1), /* isr0, isr1, or isr2 interrupt asserted */
+ HR_NEF = (1 << 2), /* NOT empty fifo */
+ HR_NFF = (1 << 3), /* NOT full fifo */
+ HR_STOP = (1 << 4), /* fifo empty or STOP command issued */
+ HR_SRQI_CIC = (1 << 5), /* SRQ asserted and we are CIC (500x only?)*/
+ HR_INTR = (1 << 7), /* isr3 interrupt active */
+};
+
+enum keyreg_bits {
+ MSTD = 0x20, // enable 350ns T1 delay
+};
+
+/* STS1 -- Status Register 1 (read only) */
+enum sts1_bits {
+ S_DONE = 0x80, /* DMA done */
+ S_SC = 0x40, /* is system controller */
+ S_IN = 0x20, /* DMA in (to memory) */
+ S_DRQ = 0x10, /* DRQ line (for diagnostics) */
+ S_STOP = 0x08, /* DMA stopped */
+ S_NDAV = 0x04, /* inverse of DAV */
+ S_HALT = 0x02, /* status of transfer machine */
+ S_GSYNC = 0x01, /* indicates if GPIB is in sync w I/O */
+};
+
+/* STS2 -- Status Register 2 */
+enum sts2_bits {
+ AFFN = (1 << 3), /* "A full FIFO NOT" (0=FIFO full) */
+ AEFN = (1 << 2), /* "A empty FIFO NOT" (0=FIFO empty) */
+ BFFN = (1 << 1), /* "B full FIFO NOT" (0=FIFO full) */
+ BEFN = (1 << 0), /* "B empty FIFO NOT" (0=FIFO empty) */
+};
+
+// Auxiliary commands
+enum tnt4882_aux_cmds {
+ AUX_9914 = 0x15, // switch to 9914 mode
+ AUX_REQT = 0x18,
+ AUX_REQF = 0x19,
+ AUX_PAGEIN = 0x50, /* page in alternate registers */
+ AUX_HLDI = 0x51, // rfd holdoff immediately
+ AUX_CLEAR_END = 0x55,
+ AUX_7210 = 0x99, // switch to 7210 mode
+};
+
+enum tnt4882_aux_regs {
+ AUXRG = 0x40,
+ AUXRI = 0xe0,
+};
+
+enum auxg_bits {
+ /* no talking when no listeners bit (prevents bus errors when data written at wrong time) */
+ NTNL_BIT = 0x8,
+ RPP2_BIT = 0x4, /* set/clear local rpp message */
+ CHES_BIT = 0x1, /*clear holdoff on end select bit*/
+};
+
+enum auxi_bits {
+ SISB = 0x1, // static interrupt bits (don't clear isr1, isr2 on read)
+ PP2 = 0x4, // ignore remote parallel poll configuration
+ USTD = 0x8, // ultra short (1100 nanosec) T1 delay
+};
+
+enum sasr_bits {
+ ACRDY_BIT = 0x4, /* acceptor ready state */
+ ADHS_BIT = 0x8, /* acceptor data holdoff state */
+ ANHS2_BIT = 0x10, /* acceptor not ready holdoff immediately state */
+ ANHS1_BIT = 0x20, /* acceptor not ready holdoff state */
+ AEHS_BIT = 0x40, /* acceptor end holdoff state */
+};
+
+#endif // _TNT4882_REGISTERS_H
diff --git a/drivers/staging/gpib/ines/Makefile b/drivers/staging/gpib/ines/Makefile
new file mode 100644
index 000000000000..cdcaa59a4e39
--- /dev/null
+++ b/drivers/staging/gpib/ines/Makefile
@@ -0,0 +1,4 @@
+ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA
+obj-m += ines_gpib.o
+
+
diff --git a/drivers/staging/gpib/ines/ines.h b/drivers/staging/gpib/ines/ines.h
new file mode 100644
index 000000000000..7e8302619998
--- /dev/null
+++ b/drivers/staging/gpib/ines/ines.h
@@ -0,0 +1,215 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * Header for ines GPIB boards
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _INES_GPIB_H
+#define _INES_GPIB_H
+
+#include "nec7210.h"
+#include "gpibP.h"
+#include "plx9050.h"
+#include "amcc5920.h"
+#include "quancom_pci.h"
+#include <linux/interrupt.h>
+
+enum ines_pci_chip {
+ PCI_CHIP_NONE,
+ PCI_CHIP_PLX9050,
+ PCI_CHIP_AMCC5920,
+ PCI_CHIP_QUANCOM,
+ PCI_CHIP_QUICKLOGIC5030,
+};
+
+struct ines_priv {
+ struct nec7210_priv nec7210_priv;
+ struct pci_dev *pci_device;
+ // base address for plx9052 pci chip
+ unsigned long plx_iobase;
+ // base address for amcc5920 pci chip
+ unsigned long amcc_iobase;
+ unsigned int irq;
+ enum ines_pci_chip pci_chip_type;
+ u8 extend_mode_bits;
+};
+
+// interfaces
+extern gpib_interface_t ines_pci_interface;
+extern gpib_interface_t ines_pci_accel_interface;
+extern gpib_interface_t ines_pcmcia_interface;
+extern gpib_interface_t ines_pcmcia_accel_interface;
+extern gpib_interface_t ines_pcmcia_unaccel_interface;
+
+// interface functions
+int ines_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read);
+int ines_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+int ines_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read);
+int ines_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+int ines_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written);
+int ines_take_control(gpib_board_t *board, int synchronous);
+int ines_go_to_standby(gpib_board_t *board);
+void ines_request_system_control(gpib_board_t *board, int request_control);
+void ines_interface_clear(gpib_board_t *board, int assert);
+void ines_remote_enable(gpib_board_t *board, int enable);
+int ines_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits);
+void ines_disable_eos(gpib_board_t *board);
+unsigned int ines_update_status(gpib_board_t *board, unsigned int clear_mask);
+int ines_primary_address(gpib_board_t *board, unsigned int address);
+int ines_secondary_address(gpib_board_t *board, unsigned int address, int enable);
+int ines_parallel_poll(gpib_board_t *board, uint8_t *result);
+void ines_parallel_poll_configure(gpib_board_t *board, uint8_t config);
+void ines_parallel_poll_response(gpib_board_t *board, int ist);
+void ines_serial_poll_response(gpib_board_t *board, uint8_t status);
+uint8_t ines_serial_poll_status(gpib_board_t *board);
+int ines_line_status(const gpib_board_t *board);
+unsigned int ines_t1_delay(gpib_board_t *board, unsigned int nano_sec);
+void ines_return_to_local(gpib_board_t *board);
+
+// interrupt service routines
+irqreturn_t ines_pci_interrupt(int irq, void *arg);
+irqreturn_t ines_interrupt(gpib_board_t *board);
+
+// utility functions
+void ines_free_private(gpib_board_t *board);
+int ines_generic_attach(gpib_board_t *board);
+void ines_online(struct ines_priv *priv, const gpib_board_t *board, int use_accel);
+void ines_set_xfer_counter(struct ines_priv *priv, unsigned int count);
+
+/* inb/outb wrappers */
+static inline unsigned int ines_inb(struct ines_priv *priv, unsigned int register_number)
+{
+ return inb((unsigned long)(priv->nec7210_priv.iobase) +
+ register_number * priv->nec7210_priv.offset);
+}
+
+static inline void ines_outb(struct ines_priv *priv, unsigned int value,
+ unsigned int register_number)
+{
+ outb(value, (unsigned long)(priv->nec7210_priv.iobase) +
+ register_number * priv->nec7210_priv.offset);
+}
+
+// pcmcia init/cleanup
+
+int ines_pcmcia_init_module(void);
+void ines_pcmcia_cleanup_module(void);
+
+enum ines_regs {
+ // read
+ FIFO_STATUS = 0x8,
+ ISR3 = 0x9,
+ ISR4 = 0xa,
+ IN_FIFO_COUNT = 0x10,
+ OUT_FIFO_COUNT = 0x11,
+ EXTEND_STATUS = 0xf,
+
+ // write
+ XDMA_CONTROL = 0x8,
+ IMR3 = ISR3,
+ IMR4 = ISR4,
+ IN_FIFO_WATERMARK = IN_FIFO_COUNT,
+ OUT_FIFO_WATERMARK = OUT_FIFO_COUNT,
+ EXTEND_MODE = 0xf,
+
+ // read-write
+ XFER_COUNT_LOWER = 0xb,
+ XFER_COUNT_UPPER = 0xc,
+ BUS_CONTROL_MONITOR = 0x13,
+};
+
+enum isr3_imr3_bits {
+ HW_TIMEOUT_BIT = 0x1,
+ XFER_COUNT_BIT = 0x2,
+ CMD_RECEIVED_BIT = 0x4,
+ TCT_RECEIVED_BIT = 0x8,
+ IFC_ACTIVE_BIT = 0x10,
+ ATN_ACTIVE_BIT = 0x20,
+ FIFO_ERROR_BIT = 0x40,
+};
+
+enum isr4_imr4_bits {
+ IN_FIFO_WATERMARK_BIT = 0x1,
+ OUT_FIFO_WATERMARK_BIT = 0x2,
+ IN_FIFO_FULL_BIT = 0x4,
+ OUT_FIFO_EMPTY_BIT = 0x8,
+ IN_FIFO_READY_BIT = 0x10,
+ OUT_FIFO_READY_BIT = 0x20,
+ IN_FIFO_EXIT_WATERMARK_BIT = 0x40,
+ OUT_FIFO_EXIT_WATERMARK_BIT = 0x80,
+};
+
+enum extend_mode_bits {
+ TR3_TRIG_ENABLE_BIT = 0x1, // enable generation of trigger pulse T/R3 pin
+ // clear message available status bit when chip writes byte with EOI true
+ MAV_ENABLE_BIT = 0x2,
+ EOS1_ENABLE_BIT = 0x4, // enable eos register 1
+ EOS2_ENABLE_BIT = 0x8, // enable eos register 2
+ EOIDIS_BIT = 0x10, // disable EOI interrupt when doing rfd holdoff on end?
+ XFER_COUNTER_ENABLE_BIT = 0x20,
+ XFER_COUNTER_OUTPUT_BIT = 0x40, // use counter for output, clear for input
+ // when xfer counter hits 0, assert EOI on write or RFD holdoff on read
+ LAST_BYTE_HANDLING_BIT = 0x80,
+};
+
+enum extend_status_bits {
+ OUTPUT_MESSAGE_IN_PROGRESS_BIT = 0x1,
+ SCSEL_BIT = 0x2, // statue of SCSEL pin
+ LISTEN_DISABLED = 0x4,
+ IN_FIFO_EMPTY_BIT = 0x8,
+ OUT_FIFO_FULL_BIT = 0x10,
+};
+
+// ines adds fifo enable bits to address mode register
+enum ines_admr_bits {
+ IN_FIFO_ENABLE_BIT = 0x8,
+ OUT_FIFO_ENABLE_BIT = 0x4,
+};
+
+enum xdma_control_bits {
+ DMA_OUTPUT_BIT = 0x1, // use dma for output, clear for input
+ ENABLE_SYNC_DMA_BIT = 0x2,
+ DMA_ACCESS_EVERY_CYCLE = 0x4,// dma accesses fifo every cycle, clear for every other cycle
+ DMA_16BIT = 0x8, // clear for 8 bit transfers
+};
+
+enum bus_control_monitor_bits {
+ BCM_DAV_BIT = 0x1,
+ BCM_NRFD_BIT = 0x2,
+ BCM_NDAC_BIT = 0x4,
+ BCM_IFC_BIT = 0x8,
+ BCM_ATN_BIT = 0x10,
+ BCM_SRQ_BIT = 0x20,
+ BCM_REN_BIT = 0x40,
+ BCM_EOI_BIT = 0x80,
+};
+
+enum ines_aux_reg_bits {
+ INES_AUXD = 0x40,
+};
+
+enum ines_aux_cmds {
+ INES_RFD_HLD_IMMEDIATE = 0x4,
+ INES_AUX_CLR_OUT_FIFO = 0x5,
+ INES_AUX_CLR_IN_FIFO = 0x6,
+ INES_AUX_XMODE = 0xa,
+};
+
+enum ines_auxd_bits {
+ INES_FOLLOWING_T1_MASK = 0x3,
+ INES_FOLLOWING_T1_500ns = 0x0,
+ INES_FOLLOWING_T1_350ns = 0x1,
+ INES_FOLLOWING_T1_250ns = 0x2,
+ INES_INITIAL_TI_MASK = 0xc,
+ INES_INITIAL_T1_2000ns = 0x0,
+ INES_INITIAL_T1_1100ns = 0x4,
+ INES_INITIAL_T1_700ns = 0x8,
+ INES_T6_2us = 0x0,
+ INES_T6_50us = 0x10,
+};
+
+#endif // _INES_GPIB_H
diff --git a/drivers/staging/gpib/ines/ines_gpib.c b/drivers/staging/gpib/ines/ines_gpib.c
new file mode 100644
index 000000000000..9d8387c3bf01
--- /dev/null
+++ b/drivers/staging/gpib/ines/ines_gpib.c
@@ -0,0 +1,1464 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 1999 Axel Dziemba (axel.dziemba@ines.de)
+ * (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "ines.h"
+
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/bitops.h>
+#include <asm/dma.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include "gpib_pci_ids.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for Ines iGPIB 72010");
+
+int ines_line_status(const gpib_board_t *board)
+{
+ int status = ValidALL;
+ int bcm_bits;
+ struct ines_priv *ines_priv;
+ struct nec7210_priv *nec_priv;
+
+ ines_priv = board->private_data;
+ nec_priv = &ines_priv->nec7210_priv;
+
+ bcm_bits = ines_inb(ines_priv, BUS_CONTROL_MONITOR);
+
+ if (bcm_bits & BCM_REN_BIT)
+ status |= BusREN;
+ if (bcm_bits & BCM_IFC_BIT)
+ status |= BusIFC;
+ if (bcm_bits & BCM_SRQ_BIT)
+ status |= BusSRQ;
+ if (bcm_bits & BCM_EOI_BIT)
+ status |= BusEOI;
+ if (bcm_bits & BCM_NRFD_BIT)
+ status |= BusNRFD;
+ if (bcm_bits & BCM_NDAC_BIT)
+ status |= BusNDAC;
+ if (bcm_bits & BCM_DAV_BIT)
+ status |= BusDAV;
+ if (bcm_bits & BCM_ATN_BIT)
+ status |= BusATN;
+
+ return status;
+}
+
+void ines_set_xfer_counter(struct ines_priv *priv, unsigned int count)
+{
+ if (count > 0xffff) {
+ pr_err("ines: bug! tried to set xfer counter > 0xffff\n");
+ return;
+ }
+ ines_outb(priv, (count >> 8) & 0xff, XFER_COUNT_UPPER);
+ ines_outb(priv, count & 0xff, XFER_COUNT_LOWER);
+}
+
+unsigned int ines_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+ unsigned int retval;
+
+ retval = nec7210_t1_delay(board, nec_priv, nano_sec);
+
+ if (nano_sec <= 250) {
+ write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_250ns |
+ INES_INITIAL_T1_2000ns, AUXMR);
+ retval = 250;
+ } else if (nano_sec <= 350) {
+ write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_350ns |
+ INES_INITIAL_T1_2000ns, AUXMR);
+ retval = 350;
+ } else {
+ write_byte(nec_priv, INES_AUXD | INES_FOLLOWING_T1_500ns |
+ INES_INITIAL_T1_2000ns, AUXMR);
+ retval = 500;
+ }
+
+ return retval;
+}
+
+static inline unsigned short num_in_fifo_bytes(struct ines_priv *ines_priv)
+{
+ return ines_inb(ines_priv, IN_FIFO_COUNT);
+}
+
+static ssize_t pio_read(gpib_board_t *board, struct ines_priv *ines_priv, uint8_t *buffer,
+ size_t length, size_t *nbytes)
+{
+ ssize_t retval = 0;
+ unsigned int num_fifo_bytes, i;
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+
+ *nbytes = 0;
+ while (*nbytes < length) {
+ if (wait_event_interruptible(board->wait,
+ num_in_fifo_bytes(ines_priv) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_warn("gpib: pio read wait interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ return -EINTR;
+
+ num_fifo_bytes = num_in_fifo_bytes(ines_priv);
+ if (num_fifo_bytes + *nbytes > length) {
+ pr_warn("ines: counter allowed %li extra byte(s)\n",
+ (long)(num_fifo_bytes - (length - *nbytes)));
+ num_fifo_bytes = length - *nbytes;
+ }
+ for (i = 0; i < num_fifo_bytes; i++)
+ buffer[(*nbytes)++] = read_byte(nec_priv, DIR);
+ if (test_bit(RECEIVED_END_BN, &nec_priv->state) &&
+ num_in_fifo_bytes(ines_priv) == 0)
+ break;
+ if (need_resched())
+ schedule();
+ }
+ /* make sure RECEIVED_END is in sync */
+ ines_interrupt(board);
+ return retval;
+}
+
+int ines_accel_read(gpib_board_t *board, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+ int counter_setting;
+
+ *end = 0;
+ *bytes_read = 0;
+ if (length == 0)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state);
+
+ write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR);
+
+ //clear in fifo
+ nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT, 0);
+ nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT, IN_FIFO_ENABLE_BIT);
+
+ ines_priv->extend_mode_bits |= LAST_BYTE_HANDLING_BIT;
+ ines_priv->extend_mode_bits &= ~XFER_COUNTER_OUTPUT_BIT & ~XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+
+ counter_setting = length - num_in_fifo_bytes(ines_priv);
+ if (counter_setting > 0) {
+ ines_set_xfer_counter(ines_priv, length);
+ ines_priv->extend_mode_bits |= XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+
+ // holdoff on END
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDE);
+ /* release rfd holdoff */
+ write_byte(nec_priv, AUX_FH, AUXMR);
+ }
+
+ retval = pio_read(board, ines_priv, buffer, length, bytes_read);
+ ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+ if (retval < 0) {
+ write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR);
+ return retval;
+ }
+ if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state))
+ *end = 1;
+
+ return retval;
+}
+
+static const int out_fifo_size = 0xff;
+
+static inline unsigned short num_out_fifo_bytes(struct ines_priv *ines_priv)
+{
+ return ines_inb(ines_priv, OUT_FIFO_COUNT);
+}
+
+static int ines_write_wait(gpib_board_t *board, struct ines_priv *ines_priv,
+ unsigned int fifo_threshold)
+{
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+
+ // wait until byte is ready to be sent
+ if (wait_event_interruptible(board->wait,
+ num_out_fifo_bytes(ines_priv) < fifo_threshold ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(BUS_ERROR_BN, &nec_priv->state))
+ return -EIO;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state))
+ return -EINTR;
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+
+ return 0;
+}
+
+int ines_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ size_t count = 0;
+ ssize_t retval = 0;
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+ unsigned int num_bytes, i;
+
+ *bytes_written = 0;
+ //clear out fifo
+ nec7210_set_reg_bits(nec_priv, ADMR, OUT_FIFO_ENABLE_BIT, 0);
+ nec7210_set_reg_bits(nec_priv, ADMR, OUT_FIFO_ENABLE_BIT, OUT_FIFO_ENABLE_BIT);
+
+ ines_priv->extend_mode_bits |= XFER_COUNTER_OUTPUT_BIT;
+ ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT;
+ ines_priv->extend_mode_bits &= ~LAST_BYTE_HANDLING_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+
+ ines_set_xfer_counter(ines_priv, length);
+ if (send_eoi)
+ ines_priv->extend_mode_bits |= LAST_BYTE_HANDLING_BIT;
+ ines_priv->extend_mode_bits |= XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+
+ while (count < length) {
+ retval = ines_write_wait(board, ines_priv, out_fifo_size);
+ if (retval < 0)
+ break;
+
+ num_bytes = out_fifo_size - num_out_fifo_bytes(ines_priv);
+ if (num_bytes + count > length)
+ num_bytes = length - count;
+ for (i = 0; i < num_bytes; i++)
+ write_byte(nec_priv, buffer[count++], CDOR);
+ }
+ if (retval < 0) {
+ ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+ *bytes_written = length - num_out_fifo_bytes(ines_priv);
+ return retval;
+ }
+ // wait last byte has been sent
+ retval = ines_write_wait(board, ines_priv, 1);
+ ines_priv->extend_mode_bits &= ~XFER_COUNTER_ENABLE_BIT;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+ *bytes_written = length - num_out_fifo_bytes(ines_priv);
+
+ return retval;
+}
+
+irqreturn_t ines_pci_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct ines_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+
+ if (priv->pci_chip_type == PCI_CHIP_QUANCOM) {
+ if ((inb((unsigned long)nec_priv->iobase +
+ QUANCOM_IRQ_CONTROL_STATUS_REG) &
+ QUANCOM_IRQ_ASSERTED_BIT))
+ outb(QUANCOM_IRQ_ENABLE_BIT, (unsigned long)(nec_priv->iobase) +
+ QUANCOM_IRQ_CONTROL_STATUS_REG);
+ }
+
+ return ines_interrupt(board);
+}
+
+irqreturn_t ines_interrupt(gpib_board_t *board)
+{
+ struct ines_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ unsigned int isr3_bits, isr4_bits;
+ unsigned long flags;
+ int wake = 0;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ nec7210_interrupt(board, nec_priv);
+ isr3_bits = ines_inb(priv, ISR3);
+ isr4_bits = ines_inb(priv, ISR4);
+ if (isr3_bits & IFC_ACTIVE_BIT) {
+ push_gpib_event(board, EventIFC);
+ wake++;
+ }
+ if (isr3_bits & FIFO_ERROR_BIT)
+ pr_err("ines gpib: fifo error\n");
+ if (isr3_bits & XFER_COUNT_BIT)
+ wake++;
+
+ if (isr4_bits & (IN_FIFO_WATERMARK_BIT | IN_FIFO_FULL_BIT | OUT_FIFO_WATERMARK_BIT |
+ OUT_FIFO_EMPTY_BIT))
+ wake++;
+
+ if (wake)
+ wake_up_interruptible(&board->wait);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return IRQ_HANDLED;
+}
+
+static int ines_pci_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ines_pci_accel_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ines_isa_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void ines_pci_detach(gpib_board_t *board);
+static void ines_isa_detach(gpib_board_t *board);
+
+enum ines_pci_vendor_ids {
+ PCI_VENDOR_ID_INES_QUICKLOGIC = 0x16da
+};
+
+enum ines_pci_device_ids {
+ PCI_DEVICE_ID_INES_GPIB_AMCC = 0x8507,
+ PCI_DEVICE_ID_INES_GPIB_QL5030 = 0x11,
+};
+
+enum ines_pci_subdevice_ids {
+ PCI_SUBDEVICE_ID_INES_GPIB = 0x1072
+};
+
+static struct pci_device_id ines_pci_table[] = {
+ {PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_9050, PCI_VENDOR_ID_PLX,
+ PCI_SUBDEVICE_ID_INES_GPIB, 0, 0, 0},
+ {PCI_VENDOR_ID_AMCC, PCI_DEVICE_ID_INES_GPIB_AMCC, PCI_VENDOR_ID_AMCC,
+ PCI_SUBDEVICE_ID_INES_GPIB, 0, 0, 0},
+ {PCI_VENDOR_ID_INES_QUICKLOGIC, PCI_DEVICE_ID_INES_GPIB_QL5030,
+ PCI_VENDOR_ID_INES_QUICKLOGIC, PCI_DEVICE_ID_INES_GPIB_QL5030, 0, 0, 0},
+ {PCI_DEVICE(PCI_VENDOR_ID_QUANCOM, PCI_DEVICE_ID_QUANCOM_GPIB)},
+ {0}
+};
+MODULE_DEVICE_TABLE(pci, ines_pci_table);
+
+struct ines_pci_id {
+ unsigned int vendor_id;
+ unsigned int device_id;
+ int subsystem_vendor_id;
+ int subsystem_device_id;
+ unsigned int gpib_region;
+ unsigned int io_offset;
+ enum ines_pci_chip pci_chip_type;
+};
+
+struct ines_pci_id pci_ids[] = {
+ {vendor_id: PCI_VENDOR_ID_PLX,
+ device_id : PCI_DEVICE_ID_PLX_9050,
+ subsystem_vendor_id : PCI_VENDOR_ID_PLX,
+ subsystem_device_id : PCI_SUBDEVICE_ID_INES_GPIB,
+ gpib_region : 2,
+ io_offset : 1,
+ pci_chip_type : PCI_CHIP_PLX9050,
+ },
+ {vendor_id: PCI_VENDOR_ID_AMCC,
+ device_id : PCI_DEVICE_ID_INES_GPIB_AMCC,
+ subsystem_vendor_id : PCI_VENDOR_ID_AMCC,
+ subsystem_device_id : PCI_SUBDEVICE_ID_INES_GPIB,
+ gpib_region : 1,
+ io_offset : 1,
+ pci_chip_type : PCI_CHIP_AMCC5920,
+ },
+ {vendor_id: PCI_VENDOR_ID_INES_QUICKLOGIC,
+ device_id : PCI_DEVICE_ID_INES_GPIB_QL5030,
+ subsystem_vendor_id : PCI_VENDOR_ID_INES_QUICKLOGIC,
+ subsystem_device_id : PCI_DEVICE_ID_INES_GPIB_QL5030,
+ gpib_region : 1,
+ io_offset : 1,
+ pci_chip_type : PCI_CHIP_QUICKLOGIC5030,
+ },
+ {vendor_id: PCI_VENDOR_ID_QUANCOM,
+ device_id : PCI_DEVICE_ID_QUANCOM_GPIB,
+ subsystem_vendor_id : -1,
+ subsystem_device_id : -1,
+ gpib_region : 0,
+ io_offset : 4,
+ pci_chip_type : PCI_CHIP_QUANCOM,
+ },
+};
+
+static const int num_pci_chips = ARRAY_SIZE(pci_ids);
+
+// wrappers for interface functions
+int ines_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct ines_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ ssize_t retval;
+ int dummy;
+
+ retval = nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+ if (retval < 0) {
+ write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR);
+
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+
+ nec7210_read_data_in(board, nec_priv, &dummy);
+ }
+ return retval;
+}
+
+int ines_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int ines_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+int ines_take_control(gpib_board_t *board, int synchronous)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+int ines_go_to_standby(gpib_board_t *board)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+void ines_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_request_system_control(board, &priv->nec7210_priv, request_control);
+}
+
+void ines_interface_clear(gpib_board_t *board, int assert)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+void ines_remote_enable(gpib_board_t *board, int enable)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+int ines_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+void ines_disable_eos(gpib_board_t *board)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+unsigned int ines_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+int ines_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+int ines_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+int ines_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+void ines_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config);
+}
+
+void ines_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+void ines_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+uint8_t ines_serial_poll_status(gpib_board_t *board)
+{
+ struct ines_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+void ines_return_to_local(gpib_board_t *board)
+{
+ struct ines_priv *priv = board->private_data;
+
+ nec7210_return_to_local(board, &priv->nec7210_priv);
+}
+
+gpib_interface_t ines_pci_unaccel_interface = {
+name: "ines_pci_unaccel",
+attach : ines_pci_attach,
+detach : ines_pci_detach,
+read : ines_read,
+write : ines_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+gpib_interface_t ines_pci_interface = {
+name: "ines_pci",
+attach : ines_pci_accel_attach,
+detach : ines_pci_detach,
+read : ines_accel_read,
+write : ines_accel_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+gpib_interface_t ines_pci_accel_interface = {
+name: "ines_pci_accel",
+attach : ines_pci_accel_attach,
+detach : ines_pci_detach,
+read : ines_accel_read,
+write : ines_accel_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+gpib_interface_t ines_isa_interface = {
+name: "ines_isa",
+attach : ines_isa_attach,
+detach : ines_isa_detach,
+read : ines_accel_read,
+write : ines_accel_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+static int ines_allocate_private(gpib_board_t *board)
+{
+ struct ines_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct ines_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct ines_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ return 0;
+}
+
+void ines_free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+int ines_generic_attach(gpib_board_t *board)
+{
+ struct ines_priv *ines_priv;
+ struct nec7210_priv *nec_priv;
+
+ board->status = 0;
+
+ if (ines_allocate_private(board))
+ return -ENOMEM;
+ ines_priv = board->private_data;
+ nec_priv = &ines_priv->nec7210_priv;
+ nec_priv->read_byte = nec7210_ioport_read_byte;
+ nec_priv->write_byte = nec7210_ioport_write_byte;
+ nec_priv->offset = 1;
+ nec_priv->type = IGPIB7210;
+ ines_priv->pci_chip_type = PCI_CHIP_NONE;
+
+ return 0;
+}
+
+void ines_online(struct ines_priv *ines_priv, const gpib_board_t *board, int use_accel)
+{
+ struct nec7210_priv *nec_priv = &ines_priv->nec7210_priv;
+
+ /* ines doesn't seem to use internal count register */
+ write_byte(nec_priv, ICR | 0, AUXMR);
+
+ write_byte(nec_priv, INES_AUX_XMODE, AUXMR);
+ write_byte(nec_priv, INES_RFD_HLD_IMMEDIATE, AUXMR);
+
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+
+ write_byte(nec_priv, INES_AUXD | 0, AUXMR);
+ ines_outb(ines_priv, 0, XDMA_CONTROL);
+ ines_priv->extend_mode_bits = 0;
+ ines_outb(ines_priv, ines_priv->extend_mode_bits, EXTEND_MODE);
+ if (use_accel) {
+ ines_outb(ines_priv, 0x80, OUT_FIFO_WATERMARK);
+ ines_outb(ines_priv, 0x80, IN_FIFO_WATERMARK);
+ ines_outb(ines_priv, IFC_ACTIVE_BIT | ATN_ACTIVE_BIT |
+ FIFO_ERROR_BIT | XFER_COUNT_BIT, IMR3);
+ ines_outb(ines_priv, IN_FIFO_WATERMARK_BIT | IN_FIFO_FULL_BIT |
+ OUT_FIFO_WATERMARK_BIT | OUT_FIFO_EMPTY_BIT, IMR4);
+ } else {
+ nec7210_set_reg_bits(nec_priv, ADMR, IN_FIFO_ENABLE_BIT | OUT_FIFO_ENABLE_BIT, 0);
+ ines_outb(ines_priv, IFC_ACTIVE_BIT | FIFO_ERROR_BIT, IMR3);
+ ines_outb(ines_priv, 0, IMR4);
+ }
+
+ nec7210_board_online(nec_priv, board);
+ if (use_accel)
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_DOIE | HR_DIIE, 0);
+}
+
+static int ines_common_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ int retval;
+ struct ines_pci_id found_id;
+ unsigned int i;
+ struct pci_dev *pdev;
+
+ memset(&found_id, 0, sizeof(found_id));
+
+ retval = ines_generic_attach(board);
+ if (retval)
+ return retval;
+
+ ines_priv = board->private_data;
+ nec_priv = &ines_priv->nec7210_priv;
+
+ // find board
+ ines_priv->pci_device = NULL;
+ for (i = 0; i < num_pci_chips && !ines_priv->pci_device; i++) {
+ pdev = NULL;
+ do {
+ if (pci_ids[i].subsystem_vendor_id >= 0 &&
+ pci_ids[i].subsystem_device_id >= 0)
+ pdev = pci_get_subsys(pci_ids[i].vendor_id, pci_ids[i].device_id,
+ pci_ids[i].subsystem_vendor_id,
+ pci_ids[i].subsystem_device_id, pdev);
+ else
+ pdev = pci_get_device(pci_ids[i].vendor_id, pci_ids[i].device_id,
+ pdev);
+ if (!pdev)
+ break;
+ if (config->pci_bus >= 0 && config->pci_bus != pdev->bus->number)
+ continue;
+ if (config->pci_slot >= 0 && config->pci_slot != PCI_SLOT(pdev->devfn))
+ continue;
+ found_id = pci_ids[i];
+ ines_priv->pci_device = pdev;
+ break;
+ } while (1);
+ }
+ if (!ines_priv->pci_device) {
+ pr_err("gpib: could not find ines PCI board\n");
+ return -1;
+ }
+
+ if (pci_enable_device(ines_priv->pci_device)) {
+ pr_err("error enabling pci device\n");
+ return -1;
+ }
+
+ if (pci_request_regions(ines_priv->pci_device, "ines-gpib"))
+ return -1;
+ nec_priv->iobase = (void *)(pci_resource_start(ines_priv->pci_device,
+ found_id.gpib_region));
+
+ ines_priv->pci_chip_type = found_id.pci_chip_type;
+ nec_priv->offset = found_id.io_offset;
+ switch (ines_priv->pci_chip_type) {
+ case PCI_CHIP_PLX9050:
+ ines_priv->plx_iobase = pci_resource_start(ines_priv->pci_device, 1);
+ break;
+ case PCI_CHIP_AMCC5920:
+ ines_priv->amcc_iobase = pci_resource_start(ines_priv->pci_device, 0);
+ break;
+ case PCI_CHIP_QUANCOM:
+ break;
+ case PCI_CHIP_QUICKLOGIC5030:
+ break;
+ default:
+ pr_err("gpib: unspecified chip type? (bug)\n");
+ nec_priv->iobase = 0;
+ pci_release_regions(ines_priv->pci_device);
+ return -1;
+ }
+
+ nec7210_board_reset(nec_priv, board);
+#ifdef QUANCOM_PCI
+ if (ines_priv->pci_chip_type == PCI_CHIP_QUANCOM) {
+ /* change interrupt polarity */
+ nec_priv->auxb_bits |= HR_INV;
+ ines_outb(ines_priv, nec_priv->auxb_bits, AUXMR);
+ }
+#endif
+ isr_flags |= IRQF_SHARED;
+ if (request_irq(ines_priv->pci_device->irq, ines_pci_interrupt, isr_flags,
+ "pci-gpib", board)) {
+ pr_err("gpib: can't request IRQ %d\n", ines_priv->pci_device->irq);
+ return -1;
+ }
+ ines_priv->irq = ines_priv->pci_device->irq;
+
+ // enable interrupts on pci chip
+ switch (ines_priv->pci_chip_type) {
+ case PCI_CHIP_PLX9050:
+ outl(PLX9050_LINTR1_EN_BIT | PLX9050_LINTR1_POLARITY_BIT | PLX9050_PCI_INTR_EN_BIT,
+ ines_priv->plx_iobase + PLX9050_INTCSR_REG);
+ break;
+ case PCI_CHIP_AMCC5920:
+ {
+ static const int region = 1;
+ static const int num_wait_states = 7;
+ u32 bits;
+
+ bits = amcc_prefetch_bits(region, PREFETCH_DISABLED);
+ bits |= amcc_PTADR_mode_bit(region);
+ bits |= amcc_disable_write_fifo_bit(region);
+ bits |= amcc_wait_state_bits(region, num_wait_states);
+ outl(bits, ines_priv->amcc_iobase + AMCC_PASS_THRU_REG);
+ outl(AMCC_ADDON_INTR_ENABLE_BIT, ines_priv->amcc_iobase + AMCC_INTCS_REG);
+ }
+ break;
+ case PCI_CHIP_QUANCOM:
+ outb(QUANCOM_IRQ_ENABLE_BIT, (unsigned long)(nec_priv->iobase) +
+ QUANCOM_IRQ_CONTROL_STATUS_REG);
+ break;
+ case PCI_CHIP_QUICKLOGIC5030:
+ break;
+ default:
+ pr_err("gpib: unspecified chip type? (bug)\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+int ines_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ int retval;
+
+ retval = ines_common_pci_attach(board, config);
+ if (retval < 0)
+ return retval;
+
+ ines_priv = board->private_data;
+ ines_online(ines_priv, board, 0);
+
+ return 0;
+}
+
+int ines_pci_accel_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ int retval;
+
+ retval = ines_common_pci_attach(board, config);
+ if (retval < 0)
+ return retval;
+
+ ines_priv = board->private_data;
+ ines_online(ines_priv, board, 1);
+
+ return 0;
+}
+
+static const int ines_isa_iosize = 0x20;
+
+int ines_isa_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ int retval;
+
+ retval = ines_generic_attach(board);
+ if (retval)
+ return retval;
+
+ ines_priv = board->private_data;
+ nec_priv = &ines_priv->nec7210_priv;
+
+ if (!request_region((unsigned long)config->ibbase, ines_isa_iosize, "ines_gpib")) {
+ pr_err("ines_gpib: ioports at 0x%p already in use\n", config->ibbase);
+ return -1;
+ }
+ nec_priv->iobase = config->ibbase;
+ nec_priv->offset = 1;
+ nec7210_board_reset(nec_priv, board);
+ if (request_irq(config->ibirq, ines_pci_interrupt, isr_flags, "ines_gpib", board)) {
+ pr_err("ines_gpib: failed to allocate IRQ %d\n", config->ibirq);
+ return -1;
+ }
+ ines_priv->irq = config->ibirq;
+ ines_online(ines_priv, board, 1);
+ return 0;
+}
+
+void ines_pci_detach(gpib_board_t *board)
+{
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (ines_priv) {
+ nec_priv = &ines_priv->nec7210_priv;
+ if (ines_priv->irq) {
+ // disable interrupts
+ switch (ines_priv->pci_chip_type) {
+ case PCI_CHIP_AMCC5920:
+ if (ines_priv->plx_iobase)
+ outl(0, ines_priv->plx_iobase + PLX9050_INTCSR_REG);
+ break;
+ case PCI_CHIP_QUANCOM:
+ if (nec_priv->iobase)
+ outb(0, (unsigned long)(nec_priv->iobase) +
+ QUANCOM_IRQ_CONTROL_STATUS_REG);
+ break;
+ default:
+ break;
+ }
+ free_irq(ines_priv->irq, board);
+ }
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ pci_release_regions(ines_priv->pci_device);
+ }
+ if (ines_priv->pci_device)
+ pci_dev_put(ines_priv->pci_device);
+ }
+ ines_free_private(board);
+}
+
+void ines_isa_detach(gpib_board_t *board)
+{
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (ines_priv) {
+ nec_priv = &ines_priv->nec7210_priv;
+ if (ines_priv->irq)
+ free_irq(ines_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ release_region((unsigned long)(nec_priv->iobase), ines_isa_iosize);
+ }
+ }
+ ines_free_private(board);
+}
+
+static int ines_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static struct pci_driver ines_pci_driver = {
+ .name = "ines_gpib",
+ .id_table = ines_pci_table,
+ .probe = &ines_pci_probe
+};
+
+#ifdef GPIB_PCMCIA
+
+#include <linux/kernel.h>
+#include <linux/ptrace.h>
+#include <linux/string.h>
+#include <linux/timer.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/ds.h>
+#include <pcmcia/cisreg.h>
+
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+#define DEBUG(n, args...) do {if (pc_debug > (n)) pr_debug(args)} while (0)
+#else
+#define DEBUG(args...)
+#endif
+
+static const int ines_pcmcia_iosize = 0x20;
+
+/* The event() function is this driver's Card Services event handler.
+ * It will be called by Card Services when an appropriate card status
+ * event is received. The config() and release() entry points are
+ * used to configure or release a socket, in response to card insertion
+ * and ejection events. They are invoked from the gpib event
+ * handler.
+ */
+
+static int ines_gpib_config(struct pcmcia_device *link);
+static void ines_gpib_release(struct pcmcia_device *link);
+static int ines_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ines_pcmcia_accel_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static void ines_pcmcia_detach(gpib_board_t *board);
+static irqreturn_t ines_pcmcia_interrupt(int irq, void *arg);
+static int ines_common_pcmcia_attach(gpib_board_t *board);
+/*
+ * A linked list of "instances" of the gpib device. Each actual
+ * PCMCIA card corresponds to one device instance, and is described
+ * by one dev_link_t structure (defined in ds.h).
+ *
+ * You may not want to use a linked list for this -- for example, the
+ * memory card driver uses an array of dev_link_t pointers, where minor
+ * device numbers are used to derive the corresponding array index.
+ */
+
+static struct pcmcia_device *curr_dev;
+
+/*
+ * A dev_link_t structure has fields for most things that are needed
+ * to keep track of a socket, but there will usually be some device
+ * specific information that also needs to be kept track of. The
+ * 'priv' pointer in a dev_link_t structure can be used to point to
+ * a device-specific private data structure, like this.
+ *
+ * A driver needs to provide a dev_node_t structure for each device
+ * on a card. In some cases, there is only one device per card (for
+ * example, ethernet cards, modems). In other cases, there may be
+ * many actual or logical devices (SCSI adapters, memory cards with
+ * multiple partitions). The dev_node_t structures need to be kept
+ * in a linked list starting at the 'dev' field of a dev_link_t
+ * structure. We allocate them in the card's private data structure,
+ * because they generally can't be allocated dynamically.
+ */
+
+struct local_info {
+ struct pcmcia_device *p_dev;
+ gpib_board_t *dev;
+ u_short manfid;
+ u_short cardid;
+};
+
+/*
+ * gpib_attach() creates an "instance" of the driver, allocating
+ * local data structures for one device. The device is registered
+ * with Card Services.
+ *
+ * The dev_link structure is initialized, but we don't actually
+ * configure the card at this point -- we wait until we receive a
+ * card insertion event.
+ */
+static int ines_gpib_probe(struct pcmcia_device *link)
+{
+ struct local_info *info;
+
+// int ret, i;
+
+ DEBUG(0, "%s(0x%p)\n", __func__ link);
+
+ /* Allocate space for private device-specific data */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->p_dev = link;
+ link->priv = info;
+
+ /* The io structure describes IO port mapping */
+ link->resource[0]->end = 32;
+ link->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
+ link->resource[0]->flags |= IO_DATA_PATH_WIDTH_8;
+ link->io_lines = 5;
+
+ /* General socket configuration */
+ link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
+ /* Register with Card Services */
+ curr_dev = link;
+ return ines_gpib_config(link);
+}
+
+/*
+ * This deletes a driver "instance". The device is de-registered
+ * with Card Services. If it has been released, all local data
+ * structures are freed. Otherwise, the structures will be freed
+ * when the device is released.
+ */
+static void ines_gpib_remove(struct pcmcia_device *link)
+{
+ struct local_info *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ if (info->dev)
+ ines_pcmcia_detach(info->dev);
+ ines_gpib_release(link);
+
+ //free_netdev(dev);
+ kfree(info);
+}
+
+static int ines_gpib_config_iteration(struct pcmcia_device *link, void *priv_data)
+{
+ return pcmcia_request_io(link);
+}
+
+/*
+ * gpib_config() is scheduled to run after a CARD_INSERTION event
+ * is received, to configure the PCMCIA socket, and to make the
+ * device available to the system.
+ */
+static int ines_gpib_config(struct pcmcia_device *link)
+{
+ struct local_info *dev;
+ int retval;
+ void *virt;
+
+ dev = link->priv;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ retval = pcmcia_loop_config(link, &ines_gpib_config_iteration, NULL);
+ if (retval) {
+ dev_warn(&link->dev, "no configuration found\n");
+ ines_gpib_release(link);
+ return -ENODEV;
+ }
+
+ pr_debug("ines_cs: manufacturer: 0x%x card: 0x%x\n",
+ link->manf_id, link->card_id);
+
+ /* for the ines card we have to setup the configuration registers in
+ * attribute memory here
+ */
+ link->resource[2]->flags |= WIN_MEMORY_TYPE_AM | WIN_DATA_WIDTH_8 | WIN_ENABLE;
+ link->resource[2]->end = 0x1000;
+ retval = pcmcia_request_window(link, link->resource[2], 250);
+ if (retval) {
+ dev_warn(&link->dev, "pcmcia_request_window failed\n");
+ ines_gpib_release(link);
+ return -ENODEV;
+ }
+ retval = pcmcia_map_mem_page(link, link->resource[2], 0);
+ if (retval) {
+ dev_warn(&link->dev, "pcmcia_map_mem_page failed\n");
+ ines_gpib_release(link);
+ return -ENODEV;
+ }
+ virt = ioremap(link->resource[2]->start, resource_size(link->resource[2]));
+ writeb((link->resource[2]->start >> 2) & 0xff, virt + 0xf0); // IOWindow base
+ iounmap((void *)virt);
+
+ /*
+ * This actually configures the PCMCIA socket -- setting up
+ * the I/O windows and the interrupt mapping.
+ */
+ retval = pcmcia_enable_device(link);
+ if (retval) {
+ ines_gpib_release(link);
+ return -ENODEV;
+ }
+ pr_info("ines gpib device loaded\n");
+ return 0;
+} /* gpib_config */
+
+/*
+ * After a card is removed, gpib_release() will unregister the net
+ * device, and release the PCMCIA configuration. If the device is
+ * still open, this will be postponed until it is closed.
+ */
+
+static void ines_gpib_release(struct pcmcia_device *link)
+{
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+ pcmcia_disable_device(link);
+} /* gpib_release */
+
+static int ines_gpib_suspend(struct pcmcia_device *link)
+{
+ //struct local_info *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ if (link->open)
+ pr_err("Device still open ???\n");
+ //netif_device_detach(dev);
+
+ return 0;
+}
+
+static int ines_gpib_resume(struct pcmcia_device *link)
+{
+ //struct local_info_t *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ /*if (link->open) {
+ * ni_gpib_probe(dev); / really?
+ * printk("Gpib resumed ???\n");
+ * //netif_device_attach(dev);
+ *}
+ */
+ return ines_gpib_config(link);
+}
+
+static struct pcmcia_device_id ines_pcmcia_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x01b4, 0x4730),
+ PCMCIA_DEVICE_NULL
+};
+MODULE_DEVICE_TABLE(pcmcia, ines_pcmcia_ids);
+
+static struct pcmcia_driver ines_gpib_cs_driver = {
+ .owner = THIS_MODULE,
+ .name = "ines_gpib_cs",
+ .id_table = ines_pcmcia_ids,
+ .probe = ines_gpib_probe,
+ .remove = ines_gpib_remove,
+ .suspend = ines_gpib_suspend,
+ .resume = ines_gpib_resume,
+};
+
+int ines_pcmcia_init_module(void)
+{
+ pcmcia_register_driver(&ines_gpib_cs_driver);
+ return 0;
+}
+
+void ines_pcmcia_cleanup_module(void)
+{
+ DEBUG(0, "ines_cs: unloading\n");
+ pcmcia_unregister_driver(&ines_gpib_cs_driver);
+}
+
+gpib_interface_t ines_pcmcia_unaccel_interface = {
+name: "ines_pcmcia_unaccel",
+attach : ines_pcmcia_attach,
+detach : ines_pcmcia_detach,
+read : ines_read,
+write : ines_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+gpib_interface_t ines_pcmcia_accel_interface = {
+name: "ines_pcmcia_accel",
+attach : ines_pcmcia_accel_attach,
+detach : ines_pcmcia_detach,
+read : ines_accel_read,
+write : ines_accel_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+gpib_interface_t ines_pcmcia_interface = {
+name: "ines_pcmcia",
+attach : ines_pcmcia_accel_attach,
+detach : ines_pcmcia_detach,
+read : ines_accel_read,
+write : ines_accel_write,
+command : ines_command,
+take_control : ines_take_control,
+go_to_standby : ines_go_to_standby,
+request_system_control : ines_request_system_control,
+interface_clear : ines_interface_clear,
+remote_enable : ines_remote_enable,
+enable_eos : ines_enable_eos,
+disable_eos : ines_disable_eos,
+parallel_poll : ines_parallel_poll,
+parallel_poll_configure : ines_parallel_poll_configure,
+parallel_poll_response : ines_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ines_line_status,
+update_status : ines_update_status,
+primary_address : ines_primary_address,
+secondary_address : ines_secondary_address,
+serial_poll_response : ines_serial_poll_response,
+serial_poll_status : ines_serial_poll_status,
+t1_delay : ines_t1_delay,
+return_to_local : ines_return_to_local,
+};
+
+irqreturn_t ines_pcmcia_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+
+ return ines_interrupt(board);
+}
+
+int ines_common_pcmcia_attach(gpib_board_t *board)
+{
+ struct ines_priv *ines_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ if (!curr_dev) {
+ pr_err("no ines pcmcia cards found\n");
+ return -1;
+ }
+
+ retval = ines_generic_attach(board);
+ if (retval)
+ return retval;
+
+ ines_priv = board->private_data;
+ nec_priv = &ines_priv->nec7210_priv;
+
+ if (request_region(curr_dev->resource[0]->start,
+ resource_size(curr_dev->resource[0]), "ines_gpib") == 0) {
+ pr_err("ines_gpib: ioports at 0x%lx already in use\n",
+ (unsigned long)(curr_dev->resource[0]->start));
+ return -1;
+ }
+
+ nec_priv->iobase = (void *)(unsigned long)curr_dev->resource[0]->start;
+
+ nec7210_board_reset(nec_priv, board);
+
+ if (request_irq(curr_dev->irq, ines_pcmcia_interrupt, IRQF_SHARED,
+ "pcmcia-gpib", board)) {
+ pr_err("gpib: can't request IRQ %d\n", curr_dev->irq);
+ return -1;
+ }
+ ines_priv->irq = curr_dev->irq;
+
+ return 0;
+}
+
+int ines_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ int retval;
+
+ retval = ines_common_pcmcia_attach(board);
+ if (retval < 0)
+ return retval;
+
+ ines_priv = board->private_data;
+ ines_online(ines_priv, board, 0);
+
+ return 0;
+}
+
+int ines_pcmcia_accel_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct ines_priv *ines_priv;
+ int retval;
+
+ retval = ines_common_pcmcia_attach(board);
+ if (retval < 0)
+ return retval;
+
+ ines_priv = board->private_data;
+ ines_online(ines_priv, board, 1);
+
+ return 0;
+}
+
+void ines_pcmcia_detach(gpib_board_t *board)
+{
+ struct ines_priv *ines_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (ines_priv) {
+ nec_priv = &ines_priv->nec7210_priv;
+ if (ines_priv->irq)
+ free_irq(ines_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ release_region((unsigned long)(nec_priv->iobase), ines_pcmcia_iosize);
+ }
+ }
+ ines_free_private(board);
+}
+
+#endif /* GPIB_PCMCIA */
+
+static int __init ines_init_module(void)
+{
+ int err = 0;
+
+ err = pci_register_driver(&ines_pci_driver);
+ if (err) {
+ pr_err("ines_gpib: pci_driver_register failed!\n");
+ return err;
+ }
+
+ gpib_register_driver(&ines_pci_interface, THIS_MODULE);
+ gpib_register_driver(&ines_pci_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&ines_pci_accel_interface, THIS_MODULE);
+ gpib_register_driver(&ines_isa_interface, THIS_MODULE);
+#ifdef GPIB_PCMCIA
+ gpib_register_driver(&ines_pcmcia_interface, THIS_MODULE);
+ gpib_register_driver(&ines_pcmcia_unaccel_interface, THIS_MODULE);
+ gpib_register_driver(&ines_pcmcia_accel_interface, THIS_MODULE);
+ err += ines_pcmcia_init_module();
+#endif
+ if (err)
+ return -1;
+
+ return 0;
+}
+
+static void __exit ines_exit_module(void)
+{
+ gpib_unregister_driver(&ines_pci_interface);
+ gpib_unregister_driver(&ines_pci_unaccel_interface);
+ gpib_unregister_driver(&ines_pci_accel_interface);
+ gpib_unregister_driver(&ines_isa_interface);
+#ifdef GPIB__PCMCIA
+ gpib_unregister_driver(&ines_pcmcia_interface);
+ gpib_unregister_driver(&ines_pcmcia_unaccel_interface);
+ gpib_unregister_driver(&ines_pcmcia_accel_interface);
+ ines_pcmcia_cleanup_module();
+#endif
+
+ pci_unregister_driver(&ines_pci_driver);
+}
+
+module_init(ines_init_module);
+module_exit(ines_exit_module);
diff --git a/drivers/staging/gpib/lpvo_usb_gpib/Makefile b/drivers/staging/gpib/lpvo_usb_gpib/Makefile
new file mode 100644
index 000000000000..137511acce63
--- /dev/null
+++ b/drivers/staging/gpib/lpvo_usb_gpib/Makefile
@@ -0,0 +1,3 @@
+
+obj-m += lpvo_usb_gpib.o
+
diff --git a/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c b/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c
new file mode 100644
index 000000000000..267651a15fa0
--- /dev/null
+++ b/drivers/staging/gpib/lpvo_usb_gpib/lpvo_usb_gpib.c
@@ -0,0 +1,2136 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * This code has been developed at the Department of Physics (University *
+ * of Florence, Italy) to support in linux-gpib the open usb-gpib adapter *
+ * implemented at the University of Ljubljana (lpvo.fe.uni-lj.si/gpib) *
+ * *
+ * copyright : (C) 2011 Marcello Carla' *
+ ***************************************************************************/
+
+/* base module includes */
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/tty.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/spinlock.h>
+#include <linux/file.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/sched/signal.h>
+#include <linux/uaccess.h>
+#include <linux/usb.h>
+
+#include "gpibP.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for LPVO usb devices");
+
+#define NAME "lpvo_usb_gpib"
+
+/*
+ * Table of devices that work with this driver.
+ *
+ * Currently, only one device is known to be used in the
+ * lpvo_usb_gpib adapter (FTDI 0403:6001).
+ * If your adapter uses a different chip, insert a line
+ * in the following table with proper <Vendor-id>, <Product-id>.
+ *
+ * To have your chip automatically handled by the driver,
+ * update files "/usr/local/etc/modprobe.d/lpvo_usb_gpib.conf"
+ * and /usr/local/etc/udev/rules.d/99-lpvo_usb_gpib.rules.
+ *
+ */
+
+static const struct usb_device_id skel_table[] = {
+ { USB_DEVICE(0x0403, 0x6001) },
+ { } /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, skel_table);
+
+/*
+ * *** Diagnostics and Debug ***
+ *
+ * The module parameter "debug" controls the sending of debug messages to
+ * syslog. By default it is set to 0 or 1 according to GPIB_CONFIG_KERNEL_DEBUG.
+ * debug = 0: only register/deregister messages are generated
+ * 1: every action is logged
+ * 2: extended logging; each single exchanged byte is documented
+ * (about twice the log volume of [1])
+ * To switch debug level:
+ * At module loading: modprobe lpvo_usb_gpib debug={0,1,2}
+ * On the fly: echo {0,1,2} > /sys/modules/lpvo_usb_gpib/parameters/debug
+ */
+
+static int debug;
+module_param(debug, int, 0644);
+
+#define DIA_LOG(level, format, ...) \
+ do { if (debug >= (level)) \
+ pr_alert("%s:%s - " format, NAME, __func__, ## __VA_ARGS__); } \
+ while (0)
+
+/* standard and extended command sets of the usb-gpib adapter */
+
+#define USB_GPIB_ON "\nIB\n"
+#define USB_GPIB_OFF "\nIBO\n"
+#define USB_GPIB_IBm0 "\nIBm0\n" /* do not assert REN with IFC */
+#define USB_GPIB_IBm1 "\nIBm1\n" /* assert REN with IFC */
+#define USB_GPIB_IBCL "\nIBZ\n"
+#define USB_GPIB_STATUS "\nIBS\n"
+#define USB_GPIB_READ "\nIB?\n"
+#define USB_GPIB_READ_1 "\nIBB\n"
+#define USB_GPIB_EOI "\nIBe0\n"
+#define USB_GPIB_FTMO "\nIBf0\n" /* disable first byte timeout */
+#define USB_GPIB_TTMOZ "\nIBt0\n" /* disable byte timeout */
+
+/* incomplete commands */
+
+#define USB_GPIB_BTMO "\nIBt" /* set byte timeout */
+#define USB_GPIB_TTMO "\nIBT" /* set total timeout */
+
+#define USB_GPIB_DEBUG_ON "\nIBDE\xAA\n"
+#define USB_GPIB_SET_LISTEN "\nIBDT0\n"
+#define USB_GPIB_SET_TALK "\nIBDT1\n"
+#define USB_GPIB_SET_LINES "\nIBDC\n"
+#define USB_GPIB_SET_DATA "\nIBDM\n"
+#define USB_GPIB_READ_LINES "\nIBD?C\n"
+#define USB_GPIB_READ_DATA "\nIBD?M\n"
+#define USB_GPIB_READ_BUS "\nIBD??\n"
+
+/* command sequences */
+
+#define USB_GPIB_UNTALK "\nIBC_\n"
+#define USB_GPIB_UNLISTEN "\nIBC?\n"
+
+/* special characters used by the adapter */
+
+#define DLE ('\020')
+#define STX ('\02')
+#define ETX ('\03')
+#define ACK ('\06')
+#define NODATA ('\03')
+#define NODAV ('\011')
+
+#define IB_BUS_REN 0x01
+#define IB_BUS_IFC 0x02
+#define IB_BUS_NDAC 0x04
+#define IB_BUS_NRFD 0x08
+#define IB_BUS_DAV 0x10
+#define IB_BUS_EOI 0x20
+#define IB_BUS_ATN 0x40
+#define IB_BUS_SRQ 0x80
+
+#define INBUF_SIZE 128
+
+struct char_buf { /* used by one_char() routine */
+ char *inbuf;
+ int last;
+ int nchar;
+};
+
+struct usb_gpib_priv { /* private data to the device */
+ u8 eos; /* eos character */
+ short eos_flags; /* eos mode */
+ int timeout; /* current value for timeout */
+ void *dev; /* the usb device private data structure */
+};
+
+#define GPIB_DEV (((struct usb_gpib_priv *)board->private_data)->dev)
+
+#define SHOW_STATUS(board) { \
+ DIA_LOG(2, "# - board %p\n", board); \
+ DIA_LOG(2, "# - buffer_length %d\n", board->buffer_length); \
+ DIA_LOG(2, "# - status %lx\n", board->status); \
+ DIA_LOG(2, "# - use_count %d\n", board->use_count); \
+ DIA_LOG(2, "# - pad %x\n", board->pad); \
+ DIA_LOG(2, "# - sad %x\n", board->sad); \
+ DIA_LOG(2, "# - timeout %d\n", board->usec_timeout); \
+ DIA_LOG(2, "# - ppc %d\n", board->parallel_poll_configuration); \
+ DIA_LOG(2, "# - t1delay %d\n", board->t1_nano_sec); \
+ DIA_LOG(2, "# - online %d\n", board->online); \
+ DIA_LOG(2, "# - autopoll %d\n", board->autospollers); \
+ DIA_LOG(2, "# - autopoll task %p\n", board->autospoll_task); \
+ DIA_LOG(2, "# - minor %d\n", board->minor); \
+ DIA_LOG(2, "# - master %d\n", board->master); \
+ DIA_LOG(2, "# - list %d\n", board->ist); \
+ }
+/*
+ * n = 0;
+ * list_for_each (l, &board->device_list) n++;
+ * TTY_LOG ("%s:%s - devices in list %d\n", a, b, n);
+ */
+
+/*
+ * TTY_LOG - write a message to the current work terminal (if any)
+ */
+
+#define TTY_LOG(format, ...) { \
+ char buf[128]; \
+ struct tty_struct *tty = get_current_tty(); \
+ if (tty) { \
+ snprintf(buf, 128, format, __VA_ARGS__); \
+ tty->driver->ops->write(tty, buf, strlen(buf)); \
+ tty->driver->ops->write(tty, "\r", 1); \
+ } \
+ }
+
+/*
+ * GLOBAL VARIABLES: required for
+ * pairing among gpib minor and usb minor.
+ * MAX_DEV is the max number of usb-gpib adapters; free
+ * to change as you like, but no more than 32
+ */
+
+#define MAX_DEV 8
+static struct usb_interface *lpvo_usb_interfaces[MAX_DEV]; /* registered interfaces */
+static int usb_minors[MAX_DEV]; /* usb minors */
+static int assigned_usb_minors; /* mask of filled slots */
+static struct mutex minors_lock; /* operations on usb_minors are to be protected */
+
+/*
+ * usb-skeleton prototypes
+ */
+
+struct usb_skel;
+static ssize_t skel_do_write(struct usb_skel *, const char *, size_t);
+static ssize_t skel_do_read(struct usb_skel *, char *, size_t);
+static int skel_do_open(gpib_board_t *, int);
+static int skel_do_release(gpib_board_t *);
+
+/*
+ * usec_diff : take difference in MICROsec between two 'timespec'
+ * (unix time in sec and NANOsec)
+ */
+
+inline int usec_diff(struct timespec64 *a, struct timespec64 *b)
+{
+ return ((a->tv_sec - b->tv_sec) * 1000000 +
+ (a->tv_nsec - b->tv_nsec) / 1000);
+}
+
+/*
+ * *** these routines are specific to the usb-gpib adapter ***
+ */
+
+/**
+ * write_loop() - Send a byte sequence to the adapter
+ *
+ * @dev: the private device structure
+ * @msg: the byte sequence.
+ * @leng: the byte sequence length.
+ *
+ */
+
+static int write_loop(void *dev, char *msg, int leng)
+{
+// int nchar = 0, val;
+
+// do {
+
+ return skel_do_write(dev, msg, leng);
+
+// if (val < 1) {
+// printk (KERN_ALERT "%s:%s - write error: %d %d/%d\n",
+// NAME, __func__, val, nchar, leng);
+// return -EIO;
+// }
+// nchar +=val;
+// } while (nchar < leng);
+// return leng;
+}
+
+static char printable(char x)
+{
+ if (x < 32 || x > 126)
+ return ' ';
+ return x;
+}
+
+/**
+ * send_command() - Send a byte sequence and return a single byte reply.
+ *
+ * @board: the gpib_board_struct data area for this gpib interface
+ * @msg: the byte sequence.
+ * @leng the byte sequence length; can be given as zero and is
+ * computed automatically, but if 'msg' contains a zero byte,
+ * it has to be given explicitly.
+ */
+
+static int send_command(gpib_board_t *board, char *msg, int leng)
+{
+ char buffer[64];
+ int nchar, j;
+ int retval;
+ struct timespec64 before, after;
+
+ ktime_get_real_ts64 (&before);
+
+ if (!leng)
+ leng = strlen(msg);
+ retval = write_loop(GPIB_DEV, msg, leng);
+ if (retval < 0)
+ return retval;
+
+ nchar = skel_do_read(GPIB_DEV, buffer, 64);
+
+ if (nchar < 0) {
+ DIA_LOG(0, " return from read: %d\n", nchar);
+ return nchar;
+ } else if (nchar != 1) {
+ for (j = 0 ; j < leng ; j++) {
+ DIA_LOG(0, " Irregular reply to command: %d %x %c\n",
+ j, msg[j], printable(msg[j]));
+ }
+ for (j = 0 ; j < nchar ; j++) {
+ DIA_LOG(0, " Irregular command reply: %d %x %c\n",
+ j, buffer[j] & 0xff, printable(buffer[j]));
+ }
+ return -EIO;
+ }
+ ktime_get_real_ts64 (&after);
+
+ DIA_LOG(1, "Sent %d - done %d us.\n", leng, usec_diff(&after, &before));
+
+ return buffer[0] & 0xff;
+}
+
+/*
+ *
+ * set_control_line() - Set the value of a single gpib control line
+ *
+ * @board: the gpib_board_struct data area for this gpib interface
+ * @line: line mask
+ * @value: line new value (0/1)
+ *
+ */
+
+static int set_control_line(gpib_board_t *board, int line, int value)
+{
+ char msg[] = USB_GPIB_SET_LINES;
+ int retval;
+ int leng = strlen(msg);
+
+ DIA_LOG(1, "setting line %x to %x\n", line, value);
+
+ retval = send_command(board, USB_GPIB_READ_LINES, 0);
+
+ DIA_LOG(1, "old line values: %x\n", retval);
+
+ if (retval == -EIO)
+ return retval;
+
+ msg[leng - 2] = value ? (retval & ~line) : retval | line;
+
+ retval = send_command(board, msg, 0);
+
+ DIA_LOG(1, "operation result: %x\n", retval);
+
+ return retval;
+}
+
+/*
+ * one_char() - read one single byte from input buffer
+ *
+ * @board: the gpib_board_struct data area for this gpib interface
+ * @char_buf: the routine private data structure
+ */
+
+static int one_char(gpib_board_t *board, struct char_buf *b)
+{
+ struct timespec64 before, after;
+
+ if (b->nchar) {
+ DIA_LOG(2, "-> %x\n", b->inbuf[b->last - b->nchar]);
+ return b->inbuf[b->last - b->nchar--];
+ }
+ ktime_get_real_ts64 (&before);
+ b->nchar = skel_do_read(GPIB_DEV, b->inbuf, INBUF_SIZE);
+ b->last = b->nchar;
+ ktime_get_real_ts64 (&after);
+
+ DIA_LOG(2, "read %d bytes in %d usec\n",
+ b->nchar, usec_diff(&after, &before));
+
+ if (b->nchar > 0) {
+ DIA_LOG(2, "--> %x\n", b->inbuf[b->last - b->nchar]);
+ return b->inbuf[b->last - b->nchar--];
+ } else if (b->nchar == 0) {
+ dev_alert(board->gpib_dev, "%s:%s - read returned EOF\n", NAME, __func__);
+ return -EIO;
+ }
+ dev_alert(board->gpib_dev, "%s:%s - read error %d\n", NAME, __func__, b->nchar);
+ TTY_LOG("\n *** %s *** Read Error - %s\n", NAME,
+ "Reset the adapter with 'gpib_config'\n");
+ return -EIO;
+}
+
+/**
+ * set_timeout() - set single byte / total timeouts on the adapter
+ *
+ * @board: the gpib_board_struct data area for this gpib interface
+ *
+ * For sake of speed, the operation is performed only if it
+ * modifies the current (saved) value. Minimum allowed timeout
+ * is 30 ms (T30ms -> 8); timeout disable (TNONE -> 0) currently
+ * not supported.
+ */
+
+static void set_timeout(gpib_board_t *board)
+{
+ int n, val;
+ char command[sizeof(USB_GPIB_TTMO) + 6];
+ struct usb_gpib_priv *data = board->private_data;
+
+ if (data->timeout == board->usec_timeout)
+ return;
+
+ n = (board->usec_timeout + 32767) / 32768;
+ if (n < 2)
+ n = 2;
+
+ DIA_LOG(1, "Set timeout to %d us -> %d\n", board->usec_timeout, n);
+
+ sprintf(command, "%s%d\n", USB_GPIB_BTMO, n > 255 ? 255 : n);
+ val = send_command(board, command, 0);
+
+ if (val == ACK) {
+ if (n > 65535)
+ n = 65535;
+ sprintf(command, "%s%d\n", USB_GPIB_TTMO, n);
+ val = send_command(board, command, 0);
+ }
+
+ if (val != ACK) {
+ dev_alert(board->gpib_dev, "%s:%s - error in timeout set: <%s>\n",
+ NAME, __func__, command);
+ } else {
+ data->timeout = board->usec_timeout;
+ }
+}
+
+/*
+ * now the standard interface functions - attach and detach
+ */
+
+/**
+ * usb_gpib_attach() - activate the usb-gpib converter board
+ *
+ * @board: the gpib_board_struct data area for this gpib interface
+ * @config: firmware data, if any (from gpib_config -I <file>)
+ *
+ * The channel name is ttyUSBn, with n=0 by default. Other values for n
+ * passed with gpib_config -b <n>.
+ *
+ * In this routine I trust that when an error code is returned
+ * detach() will be called. Always.
+ */
+
+static int usb_gpib_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int retval, j;
+ int base = (long)config->ibbase;
+ char *device_path;
+ int match;
+ struct usb_device *udev;
+
+ DIA_LOG(0, "Board %p -t %s -m %d -a %p -u %d -l %d -b %d\n",
+ board, board->interface->name, board->minor, config->device_path,
+ config->pci_bus, config->pci_slot, base);
+
+ board->private_data = NULL; /* to be sure - we can detach before setting */
+
+ /* identify device to be attached */
+
+ mutex_lock(&minors_lock);
+
+ if (config->device_path) {
+ /* if config->device_path given, try that first */
+ dev_alert(board->gpib_dev, "%s:%s - Looking for device_path: %s\n",
+ NAME, __func__, config->device_path);
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ if ((assigned_usb_minors & 1 << j) == 0)
+ continue;
+ udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j]));
+ device_path = kobject_get_path(&udev->dev.kobj, GFP_KERNEL);
+ match = gpib_match_device_path(&lpvo_usb_interfaces[j]->dev,
+ config->device_path);
+ DIA_LOG(1, "dev. %d: minor %d path: %s --> %d\n", j,
+ lpvo_usb_interfaces[j]->minor, device_path, match);
+ kfree(device_path);
+ if (match)
+ break;
+ }
+ } else if (config->pci_bus != -1 && config->pci_slot != -1) {
+ /* second: look for bus and slot */
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ if ((assigned_usb_minors & 1 << j) == 0)
+ continue;
+ udev = usb_get_dev(interface_to_usbdev(lpvo_usb_interfaces[j]));
+ DIA_LOG(1, "dev. %d: bus %d -> %d dev: %d -> %d\n", j,
+ udev->bus->busnum, config->pci_bus, udev->devnum, config->pci_slot);
+ if (config->pci_bus == udev->bus->busnum &&
+ config->pci_slot == udev->devnum)
+ break;
+ }
+ } else { /* last chance: usb_minor, given as ibbase */
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ if (usb_minors[j] == base && assigned_usb_minors & 1 << j)
+ break;
+ }
+ }
+ mutex_unlock(&minors_lock);
+
+ if (j == MAX_DEV) {
+ dev_alert(board->gpib_dev, "%s:%s - Requested device is not registered.\n",
+ NAME, __func__);
+ return -EIO;
+ }
+
+ board->private_data = kzalloc(sizeof(struct usb_gpib_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+
+ retval = skel_do_open(board, usb_minors[j]);
+
+ DIA_LOG(1, "Skel open: %d\n", retval);
+
+ if (retval) {
+ TTY_LOG("%s:%s - skel open failed.\n", NAME, __func__);
+ kfree(board->private_data);
+ board->private_data = NULL;
+ return -ENODEV;
+ }
+
+ SHOW_STATUS(board);
+
+ retval = send_command(board, USB_GPIB_ON, 0);
+ DIA_LOG(1, "USB_GPIB_ON returns %x\n", retval);
+ if (retval != ACK)
+ return -EIO;
+
+ /* We must setup debug mode because we need the extended instruction
+ * set to cope with the Core (gpib_common) point of view
+ */
+
+ retval = send_command(board, USB_GPIB_DEBUG_ON, 0);
+ DIA_LOG(1, "USB_GPIB_DEBUG_ON returns %x\n", retval);
+ if (retval != ACK)
+ return -EIO;
+
+ /* We must keep REN off after an IFC because so it is
+ * assumed by the Core
+ */
+
+ retval = send_command(board, USB_GPIB_IBm0, 0);
+ DIA_LOG(1, "USB_GPIB_IBm0 returns %x\n", retval);
+ if (retval != ACK)
+ return -EIO;
+
+ retval = set_control_line(board, IB_BUS_REN, 0);
+ if (retval != ACK)
+ return -EIO;
+
+ retval = send_command(board, USB_GPIB_FTMO, 0);
+ DIA_LOG(1, "USB_GPIB_FTMO returns %x\n", retval);
+ if (retval != ACK)
+ return -EIO;
+
+ SHOW_STATUS(board);
+ TTY_LOG("Module '%s' has been sucesfully configured\n", NAME);
+ return 0;
+}
+
+/**
+ * usb_gpib_detach() - deactivate the usb-gpib converter board
+ *
+ * @board: the gpib_board data area for this gpib interface
+ *
+ */
+
+static void usb_gpib_detach(gpib_board_t *board)
+{
+ int retval;
+
+ SHOW_STATUS(board);
+
+ DIA_LOG(0, "detaching %p\n", board);
+
+ if (board->private_data) {
+ if (GPIB_DEV) {
+ write_loop(GPIB_DEV, USB_GPIB_OFF, strlen(USB_GPIB_OFF));
+ msleep(100);
+ DIA_LOG(1, "%s", "GPIB off\n");
+ retval = skel_do_release(board);
+ DIA_LOG(1, "skel release -> %d\n", retval);
+ }
+ kfree(board->private_data);
+ board->private_data = NULL;
+ }
+
+ DIA_LOG(0, "done %p\n", board);
+ TTY_LOG("Module '%s' has been detached\n", NAME);
+}
+
+/*
+ * Other functions follow in alphabetical order
+ */
+/* command */
+static int usb_gpib_command(gpib_board_t *board,
+ u8 *buffer,
+ size_t length,
+ size_t *bytes_written)
+{
+ int i, retval;
+ char command[6] = "IBc\n";
+
+ DIA_LOG(1, "enter %p\n", board);
+
+ set_timeout(board);
+
+ *bytes_written = 0;
+ for (i = 0 ; i < length ; i++) {
+ command[3] = buffer[i];
+ retval = send_command(board, command, 5);
+ DIA_LOG(2, "%d ==> %x %x\n", i, buffer[i], retval);
+ if (retval != 0x06)
+ return retval;
+ ++(*bytes_written);
+ }
+ return 0;
+}
+
+/**
+ * disable_eos() - Disable END on eos byte (END on EOI only)
+ *
+ * @board: the gpib_board data area for this gpib interface
+ *
+ * With the lpvo adapter eos can only be handled via software.
+ * Cannot do nothing here, but remember for future use.
+ */
+
+static void usb_gpib_disable_eos(gpib_board_t *board)
+{
+ ((struct usb_gpib_priv *)board->private_data)->eos_flags &= ~REOS;
+ DIA_LOG(1, "done: %x\n",
+ ((struct usb_gpib_priv *)board->private_data)->eos_flags);
+}
+
+/**
+ * enable_eos() - Enable END for reads when eos byte is received.
+ *
+ * @board: the gpib_board data area for this gpib interface
+ * @eos_byte: the 'eos' byte
+ * @compare_8_bits: if zero ignore eigthth bit when comparing
+ *
+ */
+
+static int usb_gpib_enable_eos(gpib_board_t *board,
+ u8 eos_byte,
+ int compare_8_bits)
+{
+ struct usb_gpib_priv *pd = (struct usb_gpib_priv *)board->private_data;
+
+ DIA_LOG(1, "enter with %x\n", eos_byte);
+ pd->eos = eos_byte;
+ pd->eos_flags = REOS;
+ if (compare_8_bits)
+ pd->eos_flags |= BIN;
+ return 0;
+}
+
+/**
+ * go_to_standby() - De-assert ATN
+ *
+ * @board: the gpib_board data area for this gpib interface
+ */
+
+static int usb_gpib_go_to_standby(gpib_board_t *board)
+{
+ int retval = set_control_line(board, IB_BUS_ATN, 0);
+
+ DIA_LOG(1, "done with %x\n", retval);
+
+ if (retval == ACK)
+ return 0;
+ return -EIO;
+}
+
+/**
+ * interface_clear() - Assert or de-assert IFC
+ *
+ * @board: the gpib_board data area for this gpib interface
+ * assert: 1: assert IFC; 0: de-assert IFC
+ *
+ * Currently on the assert request we issue the lpvo IBZ
+ * command that cycles IFC low for 100 usec, then we ignore
+ * the de-assert request.
+ */
+
+static void usb_gpib_interface_clear(gpib_board_t *board, int assert)
+{
+ int retval = 0;
+
+ DIA_LOG(1, "enter with %d\n", assert);
+
+ if (assert) {
+ retval = send_command(board, USB_GPIB_IBCL, 0);
+
+ set_bit(CIC_NUM, &board->status);
+ }
+
+ DIA_LOG(1, "done with %d %d\n", assert, retval);
+}
+
+/**
+ * line_status() - Read the status of the bus lines.
+ *
+ * @board: the gpib_board data area for this gpib interface
+ *
+ * We can read all lines.
+ */
+
+#define WQT wait_queue_entry_t
+#define WQH head
+#define WQE entry
+
+static int usb_gpib_line_status(const gpib_board_t *board)
+{
+ int buffer;
+ int line_status = ValidALL; /* all lines will be read */
+ struct list_head *p, *q;
+ WQT *item;
+ unsigned long flags;
+ int sleep = 0;
+
+ DIA_LOG(1, "%s\n", "request");
+
+ /* if we are on the wait queue (board->wait), do not hurry
+ * reading status line; instead, pause a little
+ */
+
+ spin_lock_irqsave((spinlock_t *)&board->wait.lock, flags);
+ q = (struct list_head *)&board->wait.WQH;
+ list_for_each(p, q) {
+ item = container_of(p, WQT, WQE);
+ if (item->private == current) {
+ sleep = 20;
+ break;
+ }
+ /* pid is: ((struct task_struct *) item->private)->pid); */
+ }
+ spin_unlock_irqrestore((spinlock_t *)&board->wait.lock, flags);
+ if (sleep) {
+ DIA_LOG(1, "we are on the wait queue - sleep %d ms\n", sleep);
+ msleep(sleep);
+ }
+
+ buffer = send_command((gpib_board_t *)board, USB_GPIB_STATUS, 0);
+
+ if (buffer < 0) {
+ dev_alert(board->gpib_dev, "%s:%s - line status read failed with %d\n",
+ NAME, __func__, buffer);
+ return -1;
+ }
+
+ if ((buffer & 0x01) == 0)
+ line_status |= BusREN;
+ if ((buffer & 0x02) == 0)
+ line_status |= BusIFC;
+ if ((buffer & 0x04) == 0)
+ line_status |= BusNDAC;
+ if ((buffer & 0x08) == 0)
+ line_status |= BusNRFD;
+ if ((buffer & 0x10) == 0)
+ line_status |= BusDAV;
+ if ((buffer & 0x20) == 0)
+ line_status |= BusEOI;
+ if ((buffer & 0x40) == 0)
+ line_status |= BusATN;
+ if ((buffer & 0x80) == 0)
+ line_status |= BusSRQ;
+
+ DIA_LOG(1, "done with %x %x\n", buffer, line_status);
+
+ return line_status;
+}
+
+/* parallel_poll */
+
+static int usb_gpib_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ /* request parallel poll asserting ATN | EOI;
+ * we suppose ATN already asserted
+ */
+
+ int retval;
+
+ DIA_LOG(1, "enter %p\n", board);
+
+ retval = set_control_line(board, IB_BUS_EOI, 1);
+ if (retval != ACK) {
+ dev_alert(board->gpib_dev, "%s:%s - assert EOI failed\n", NAME, __func__);
+ return -EIO;
+ }
+
+ *result = send_command(board, USB_GPIB_READ_DATA, 0);
+
+ DIA_LOG(1, "done with %x\n", *result);
+
+ retval = set_control_line(board, IB_BUS_EOI, 0);
+ if (retval != 0x06) {
+ dev_alert(board->gpib_dev, "%s:%s - unassert EOI failed\n", NAME, __func__);
+ return -EIO;
+ }
+
+ return 0;
+}
+
+/* read */
+
+static int usb_gpib_read(gpib_board_t *board,
+ u8 *buffer,
+ size_t length,
+ int *end,
+ size_t *bytes_read)
+{
+#define MAX_READ_EXCESS 16384
+
+ struct char_buf b = {NULL, 0};
+
+ int retval;
+ char c, nc;
+ int ic;
+ struct timespec64 before, after;
+ int read_count = MAX_READ_EXCESS;
+ struct usb_gpib_priv *pd = (struct usb_gpib_priv *)board->private_data;
+
+ DIA_LOG(1, "enter %p -> %zu\n", board, length);
+
+ *bytes_read = 0; /* by default, things go wrong */
+ *end = 0;
+
+ set_timeout(board);
+
+ /* single byte read has a special handling */
+
+ if (length == 1) {
+ char inbuf[2] = {0, 0};
+
+ /* read a single character */
+
+ ktime_get_real_ts64 (&before);
+
+ retval = write_loop(GPIB_DEV, USB_GPIB_READ_1, strlen(USB_GPIB_READ_1));
+ if (retval < 0)
+ return retval;
+
+ retval = skel_do_read(GPIB_DEV, inbuf, 1);
+ retval += skel_do_read(GPIB_DEV, inbuf + 1, 1);
+
+ ktime_get_real_ts64 (&after);
+
+ DIA_LOG(1, "single read: %x %x %x in %d\n", retval,
+ inbuf[0], inbuf[1],
+ usec_diff(&after, &before));
+
+ /* good char / last char? */
+
+ if (retval == 2 && inbuf[1] == ACK) {
+ buffer[0] = inbuf[0];
+ *bytes_read = 1;
+ return 0;
+ }
+ if (retval < 2)
+ return -EIO;
+ else
+ return -ETIME;
+ return 0;
+ }
+
+ /* allocate buffer for multibyte read */
+
+ b.inbuf = kmalloc(INBUF_SIZE, GFP_KERNEL);
+ if (!b.inbuf)
+ return -ENOMEM;
+
+ /* send read command and check <DLE><STX> sequence */
+
+ retval = write_loop(GPIB_DEV, USB_GPIB_READ, strlen(USB_GPIB_READ));
+ if (retval < 0)
+ goto read_return;
+
+ if (one_char(board, &b) != DLE || one_char(board, &b) != STX) {
+ dev_alert(board->gpib_dev, "%s:%s - wrong <DLE><STX> sequence\n",
+ NAME, __func__);
+ retval = -EIO;
+ goto read_return;
+ }
+
+ /* get data flow */
+
+ while (1) {
+ ic = one_char(board, &b);
+ if (ic == -EIO) {
+ retval = -EIO;
+ goto read_return;
+ }
+ c = ic;
+
+ if (c == DLE)
+ nc = one_char(board, &b);
+ if (c != DLE || nc == DLE) {
+ /* data byte - store into buffer */
+
+ if (*bytes_read == length)
+ break; /* data overflow */
+ if (c == DLE)
+ c = nc;
+ buffer[(*bytes_read)++] = c;
+ if (c == pd->eos) {
+ *end = 1;
+ break;
+ }
+
+ } else {
+ /* we are in the closing <DLE><ETX> sequence */
+ c = nc;
+ if (c == ETX) {
+ c = one_char(board, &b);
+ if (c == ACK) {
+ *end = 1;
+ retval = 0;
+ goto read_return;
+ } else {
+ dev_alert(board->gpib_dev, "%s:%s - %s %x\n",
+ NAME, __func__,
+ "Wrong end of message", c);
+ retval = -ETIME;
+ goto read_return;
+ }
+ } else {
+ dev_alert(board->gpib_dev, "%s:%s - %s\n", NAME, __func__,
+ "lone <DLE> in stream");
+ retval = -EIO;
+ goto read_return;
+ }
+ }
+ }
+
+ /* we had a data overflow - flush excess data */
+
+ while (read_count--) {
+ if (one_char(board, &b) != DLE)
+ continue;
+ c = one_char(board, &b);
+ if (c == DLE)
+ continue;
+ if (c == ETX) {
+ c = one_char(board, &b);
+ if (c == ACK) {
+ if (MAX_READ_EXCESS - read_count > 1)
+ dev_alert(board->gpib_dev, "%s:%s - %s\n", NAME, __func__,
+ "small buffer - maybe some data lost");
+ retval = 0;
+ goto read_return;
+ }
+ break;
+ }
+ }
+
+ dev_alert(board->gpib_dev, "%s:%s - no input end - GPIB board in odd state\n",
+ NAME, __func__);
+ retval = -EIO;
+
+read_return:
+ kfree(b.inbuf);
+
+ DIA_LOG(1, "done with byte/status: %d %x %d\n",
+ (int)*bytes_read, retval, *end);
+
+ if (retval == 0 || retval == -ETIME) {
+ if (send_command(board, USB_GPIB_UNTALK, sizeof(USB_GPIB_UNTALK)) == 0x06)
+ return retval;
+ return -EIO;
+ }
+
+ return retval;
+}
+
+/* remote_enable */
+
+static void usb_gpib_remote_enable(gpib_board_t *board, int enable)
+{
+ int retval;
+
+ retval = set_control_line(board, IB_BUS_REN, enable ? 1 : 0);
+ if (retval != ACK)
+ dev_alert(board->gpib_dev, "%s:%s - could not set REN line: %x\n",
+ NAME, __func__, retval);
+
+ DIA_LOG(1, "done with %x\n", retval);
+}
+
+/* request_system_control */
+
+static void usb_gpib_request_system_control(gpib_board_t *board,
+ int request_control)
+{
+ if (request_control)
+ set_bit(CIC_NUM, &board->status);
+ else
+ clear_bit(CIC_NUM, &board->status);
+
+ DIA_LOG(1, "done with %d -> %lx\n", request_control, board->status);
+}
+
+/* take_control */
+/* beware: the sync flag is ignored; what is its real meaning? */
+
+static int usb_gpib_take_control(gpib_board_t *board, int sync)
+{
+ int retval;
+
+ retval = set_control_line(board, IB_BUS_ATN, 1);
+
+ DIA_LOG(1, "done with %d %x\n", sync, retval);
+
+ if (retval == ACK)
+ return 0;
+ return -EIO;
+}
+
+/* update_status */
+
+static unsigned int usb_gpib_update_status(gpib_board_t *board,
+ unsigned int clear_mask)
+{
+ /* There is nothing we can do here, I guess */
+
+ board->status &= ~clear_mask;
+
+ DIA_LOG(1, "done with %x %lx\n", clear_mask, board->status);
+
+ return board->status;
+}
+
+/* write */
+/* beware: DLE characters are not escaped - can only send ASCII data */
+
+static int usb_gpib_write(gpib_board_t *board,
+ u8 *buffer,
+ size_t length,
+ int send_eoi,
+ size_t *bytes_written)
+{
+ int retval;
+ char *msg;
+
+ DIA_LOG(1, "enter %p -> %zu\n", board, length);
+
+ set_timeout(board);
+
+ msg = kmalloc(length + 8, GFP_KERNEL);
+ if (!msg)
+ return -ENOMEM;
+
+ memcpy(msg, "\nIB\020\002", 5);
+ memcpy(msg + 5, buffer, length);
+ memcpy(msg + 5 + length, "\020\003\n", 3);
+
+ retval = send_command(board, msg, length + 8);
+ kfree(msg);
+
+ DIA_LOG(1, "<%.*s> -> %x\n", (int)length, buffer, retval);
+
+ if (retval != ACK)
+ return -EPIPE;
+
+ *bytes_written = length;
+
+ if (send_command(board, USB_GPIB_UNLISTEN, sizeof(USB_GPIB_UNLISTEN))
+ != 0x06)
+ return -EPIPE;
+
+ return length;
+}
+
+/*
+ * *** following functions not implemented yet ***
+ */
+
+/* parallel_poll configure */
+
+static void usb_gpib_parallel_poll_configure(gpib_board_t *board,
+ uint8_t configuration)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+}
+
+/* parallel_poll_response */
+
+static void usb_gpib_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+}
+
+/* primary_address */
+
+static int usb_gpib_primary_address(gpib_board_t *board, unsigned int address)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+ return 0;
+}
+
+/* return_to_local */
+
+static void usb_gpib_return_to_local(gpib_board_t *board)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+}
+
+/* secondary_address */
+
+static int usb_gpib_secondary_address(gpib_board_t *board,
+ unsigned int address,
+ int enable)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+ return 0;
+}
+
+/* serial_poll_response */
+
+static void usb_gpib_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+}
+
+/* serial_poll_status */
+
+static uint8_t usb_gpib_serial_poll_status(gpib_board_t *board)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+ return 0;
+}
+
+/* t1_delay */
+
+static unsigned int usb_gpib_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ dev_alert(board->gpib_dev, "%s:%s - currently a NOP\n", NAME, __func__);
+ return 0;
+}
+
+/*
+ * *** module dispatch table and init/exit functions ***
+ */
+
+gpib_interface_t usb_gpib_interface = {
+name: NAME,
+attach : usb_gpib_attach,
+detach : usb_gpib_detach,
+read : usb_gpib_read,
+write : usb_gpib_write,
+command : usb_gpib_command,
+take_control : usb_gpib_take_control,
+go_to_standby : usb_gpib_go_to_standby,
+request_system_control : usb_gpib_request_system_control,
+interface_clear : usb_gpib_interface_clear,
+remote_enable : usb_gpib_remote_enable,
+enable_eos : usb_gpib_enable_eos,
+disable_eos : usb_gpib_disable_eos,
+parallel_poll : usb_gpib_parallel_poll,
+parallel_poll_configure : usb_gpib_parallel_poll_configure,
+parallel_poll_response : usb_gpib_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : usb_gpib_line_status,
+update_status : usb_gpib_update_status,
+primary_address : usb_gpib_primary_address,
+secondary_address : usb_gpib_secondary_address,
+serial_poll_response : usb_gpib_serial_poll_response,
+serial_poll_status : usb_gpib_serial_poll_status,
+t1_delay : usb_gpib_t1_delay,
+return_to_local : usb_gpib_return_to_local,
+skip_check_for_command_acceptors : 1
+};
+
+/*
+ * usb_gpib_init_module(), usb_gpib_exit_module()
+ *
+ * This functions are called every time a new device is detected
+ * and registered or is removed and unregistered.
+ * We must take note of created and destroyed usb minors to be used
+ * when usb_gpib_attach() and usb_gpib_detach() will be called on
+ * request by gpib_config.
+ */
+
+static int usb_gpib_init_module(struct usb_interface *interface)
+{
+ int j, mask, rv;
+
+ rv = mutex_lock_interruptible(&minors_lock);
+ if (rv < 0)
+ return rv;
+
+ if (!assigned_usb_minors) {
+ gpib_register_driver(&usb_gpib_interface, THIS_MODULE);
+ } else {
+ /* check if minor is already registered - maybe useless, but if
+ * it happens the code is inconsistent somewhere
+ */
+
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ if (usb_minors[j] == interface->minor && assigned_usb_minors & 1 << j) {
+ pr_alert("%s:%s - CODE BUG: USB minor %d registered at %d.\n",
+ NAME, __func__, interface->minor, j);
+ rv = -1;
+ goto exit;
+ }
+ }
+ }
+
+ /* find a free slot */
+
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ mask = 1 << j;
+ if ((assigned_usb_minors & mask) == 0) {
+ usb_minors[j] = interface->minor;
+ lpvo_usb_interfaces[j] = interface;
+ assigned_usb_minors |= mask;
+ DIA_LOG(0, "usb minor %d registered at %d\n", interface->minor, j);
+ rv = 0;
+ goto exit;
+ }
+ }
+ pr_alert("%s:%s - No slot available for interface %p minor %d\n",
+ NAME, __func__, interface, interface->minor);
+ rv = -1;
+
+exit:
+ mutex_unlock(&minors_lock);
+ return rv;
+}
+
+static void usb_gpib_exit_module(int minor)
+{
+ int j;
+
+ mutex_lock(&minors_lock);
+ for (j = 0 ; j < MAX_DEV ; j++) {
+ if (usb_minors[j] == minor && assigned_usb_minors & 1 << j) {
+ assigned_usb_minors &= ~(1 << j);
+ usb_minors[j] = -1;
+ if (assigned_usb_minors == 0)
+ gpib_unregister_driver(&usb_gpib_interface);
+ goto exit;
+ }
+ }
+ pr_alert("%s:%s - CODE BUG: USB minor %d not found.\n", NAME, __func__, minor);
+
+exit:
+ mutex_unlock(&minors_lock);
+}
+
+/*
+ * Default latency time (16 msec) is too long.
+ * We must use 1 msec (best); anyhow, no more than 5 msec.
+ *
+ * Defines and function taken and modified from the kernel tree
+ * (see ftdi_sio.h and ftdi_sio.c).
+ *
+ */
+
+#define FTDI_SIO_SET_LATENCY_TIMER 9 /* Set the latency timer */
+#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST FTDI_SIO_SET_LATENCY_TIMER
+#define FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE 0x40
+#define WDR_TIMEOUT 5000 /* default urb timeout */
+#define WDR_SHORT_TIMEOUT 1000 /* shorter urb timeout */
+
+#define LATENCY_TIMER 1 /* use a small latency timer: 1 ... 5 msec */
+#define LATENCY_CHANNEL 0 /* channel selection in multichannel devices */
+static int write_latency_timer(struct usb_device *udev)
+{
+ int rv = usb_control_msg(udev,
+ usb_sndctrlpipe(udev, 0),
+ FTDI_SIO_SET_LATENCY_TIMER_REQUEST,
+ FTDI_SIO_SET_LATENCY_TIMER_REQUEST_TYPE,
+ LATENCY_TIMER, LATENCY_CHANNEL,
+ NULL, 0, WDR_TIMEOUT);
+ if (rv < 0)
+ pr_alert("Unable to write latency timer: %i\n", rv);
+ return rv;
+}
+
+/*****************************************************************************
+ * *
+ * The following code is a modified version of the USB Skeleton driver *
+ * written by Greg Kroah-Hartman and available in the kernel tree. *
+ * *
+ * Functions skel_open() and skel_release() have been rewritten and named *
+ * skel_do_open() and skel_do_release() to process the attach and detach *
+ * requests coming from gpib_config. *
+ * *
+ * Functions skel_read() and skel_write() have been split into a *
+ * skel_do_read() and skel_do_write(), that cover the kernel stuff of read *
+ * and write operations, and the original skel_read() and skel_write(), *
+ * that handle communication with user space and call their _do_ companion. *
+ * *
+ * Only the _do_ versions are used by the lpvo_usb_gpib driver; other ones *
+ * can be (optionally) maintained in the compilation to have direct access *
+ * to a gpib controller for debug and diagnostics. *
+ * *
+ * To avoid collisions in names, devices in user space have been renamed *
+ * lpvo_raw1, lpvo_raw2 .... and the usb driver has been renamed with the *
+ * gpib module name. *
+ * *
+ *****************************************************************************/
+
+/*
+ * USB Skeleton driver - 2.2
+ *
+ * Copyright (C) 2001-2004 Greg Kroah-Hartman (greg@kroah.com)
+ *
+ * This driver is based on the 2.6.3 version of drivers/usb/usb-skeleton.c
+ * but has been rewritten to be easier to read and use.
+ */
+
+#include <linux/errno.h>
+#include <linux/kref.h>
+#include <linux/uaccess.h>
+#include <linux/mutex.h>
+
+/* Get a minor range for your devices from the usb maintainer */
+#define USB_SKEL_MINOR_BASE 192
+
+/* private defines */
+
+#define MAX_TRANSFER (PAGE_SIZE - 512)
+/* MAX_TRANSFER is chosen so that the VM is not stressed by
+ * allocations > PAGE_SIZE and the number of packets in a page
+ * is an integer 512 is the largest possible packet on EHCI
+ */
+
+#define WRITES_IN_FLIGHT 1 /* we do not want more than one pending write */
+#define USER_DEVICE 1 /* compile for device(s) in user space */
+
+/* Structure to hold all of our device specific stuff */
+struct usb_skel {
+ struct usb_device *udev; /* the usb device for this device */
+ struct usb_interface *interface; /* the interface for this device */
+ struct semaphore limit_sem; /* limiting the number of writes in progress */
+ struct usb_anchor submitted; /* in case need to retract our submissions */
+ struct urb *bulk_in_urb; /* the urb to read data with */
+ unsigned char *bulk_in_buffer; /* the buffer to receive data */
+ size_t bulk_in_size; /* the size of the receive buffer */
+ size_t bulk_in_filled; /* number of bytes in the buffer */
+ size_t bulk_in_copied; /* already copied to user space */
+ __u8 bulk_in_endpoint_addr; /* the address of the bulk in endpoint */
+ __u8 bulk_out_endpoint_addr; /* the address of the bulk out endpoint */
+ int errors; /* the last request tanked */
+ bool ongoing_read; /* a read is going on */
+ spinlock_t err_lock; /* lock for errors */
+ struct kref kref;
+ struct mutex io_mutex; /* synchronize I/O with disconnect */
+ wait_queue_head_t bulk_in_wait; /* to wait for an ongoing read */
+};
+
+#define to_skel_dev(d) container_of(d, struct usb_skel, kref)
+
+static struct usb_driver skel_driver;
+static void skel_draw_down(struct usb_skel *dev);
+
+static void skel_delete(struct kref *kref)
+{
+ struct usb_skel *dev = to_skel_dev(kref);
+
+ usb_free_urb(dev->bulk_in_urb);
+ usb_put_dev(dev->udev);
+ kfree(dev->bulk_in_buffer);
+ kfree(dev);
+}
+
+/*
+ * skel_do_open() - to be called by usb_gpib_attach
+ */
+
+static int skel_do_open(gpib_board_t *board, int subminor)
+{
+ struct usb_skel *dev;
+ struct usb_interface *interface;
+ int retval = 0;
+
+ DIA_LOG(0, "Required minor: %d\n", subminor);
+
+ interface = usb_find_interface(&skel_driver, subminor);
+ if (!interface) {
+ pr_err("%s - error, can't find device for minor %d\n",
+ __func__, subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ dev = usb_get_intfdata(interface);
+ if (!dev) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ retval = usb_autopm_get_interface(interface);
+ if (retval)
+ goto exit;
+
+ /* increment our usage count for the device */
+ kref_get(&dev->kref);
+
+ /* save our object in the file's private structure */
+ GPIB_DEV = dev;
+
+exit:
+ return retval;
+}
+
+/*
+ * skel_do_release() - to be called by usb_gpib_detach
+ */
+
+static int skel_do_release(gpib_board_t *board)
+{
+ struct usb_skel *dev;
+
+ dev = GPIB_DEV;
+ if (!dev)
+ return -ENODEV;
+
+ /* allow the device to be autosuspended */
+ mutex_lock(&dev->io_mutex);
+ if (dev->interface)
+ usb_autopm_put_interface(dev->interface);
+ mutex_unlock(&dev->io_mutex);
+
+ /* decrement the count on our device */
+ kref_put(&dev->kref, skel_delete);
+ return 0;
+}
+
+/*
+ * read functions
+ */
+
+static void skel_read_bulk_callback(struct urb *urb)
+{
+ struct usb_skel *dev;
+ unsigned long flags;
+
+ dev = urb->context;
+
+ spin_lock_irqsave(&dev->err_lock, flags);
+ /* sync/async unlink faults aren't errors */
+ if (urb->status) {
+ if (!(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))
+ dev_err(&dev->interface->dev,
+ "%s - nonzero read bulk status received: %d\n",
+ __func__, urb->status);
+
+ dev->errors = urb->status;
+ } else {
+ dev->bulk_in_filled = urb->actual_length;
+ }
+ dev->ongoing_read = 0;
+ spin_unlock_irqrestore(&dev->err_lock, flags);
+
+ wake_up_interruptible(&dev->bulk_in_wait);
+}
+
+static int skel_do_read_io(struct usb_skel *dev, size_t count)
+{
+ int rv;
+
+ /* prepare a read */
+ usb_fill_bulk_urb(dev->bulk_in_urb,
+ dev->udev,
+ usb_rcvbulkpipe(dev->udev,
+ dev->bulk_in_endpoint_addr),
+ dev->bulk_in_buffer,
+ min(dev->bulk_in_size, count),
+ skel_read_bulk_callback,
+ dev);
+ /* tell everybody to leave the URB alone */
+ spin_lock_irq(&dev->err_lock);
+ dev->ongoing_read = 1;
+ spin_unlock_irq(&dev->err_lock);
+
+ /* submit bulk in urb, which means no data to deliver */
+ dev->bulk_in_filled = 0;
+ dev->bulk_in_copied = 0;
+
+ /* do it */
+ rv = usb_submit_urb(dev->bulk_in_urb, GFP_KERNEL);
+ if (rv < 0) {
+ dev_err(&dev->interface->dev,
+ "%s - failed submitting read urb, error %d\n",
+ __func__, rv);
+ rv = (rv == -ENOMEM) ? rv : -EIO;
+ spin_lock_irq(&dev->err_lock);
+ dev->ongoing_read = 0;
+ spin_unlock_irq(&dev->err_lock);
+ }
+
+ return rv;
+}
+
+/*
+ * skel_do_read() - read operations from lpvo_usb_gpib
+ */
+
+static ssize_t skel_do_read(struct usb_skel *dev, char *buffer, size_t count)
+{
+ int rv;
+ bool ongoing_io;
+
+ /* if we cannot read at all, return EOF */
+
+ if (!dev->bulk_in_urb || !count)
+ return 0;
+
+ DIA_LOG(1, "enter for %zu.\n", count);
+
+restart: /* added to comply with ftdi timeout technique */
+
+ /* no concurrent readers */
+
+ DIA_LOG(2, "restart with %zd %zd.\n", dev->bulk_in_filled, dev->bulk_in_copied);
+
+ rv = mutex_lock_interruptible(&dev->io_mutex);
+ if (rv < 0)
+ return rv;
+
+ if (!dev->interface) { /* disconnect() was called */
+ rv = -ENODEV;
+ goto exit;
+ }
+
+retry:
+ /* if IO is under way, we must not touch things */
+ spin_lock_irq(&dev->err_lock);
+ ongoing_io = dev->ongoing_read;
+ spin_unlock_irq(&dev->err_lock);
+
+ DIA_LOG(2, "retry with %d.\n", ongoing_io);
+
+ if (ongoing_io) {
+// /* nonblocking IO shall not wait */
+// /* no file, no O_NONBLOCK; maybe provide when from user space */
+// if (file->f_flags & O_NONBLOCK) {
+// rv = -EAGAIN;
+// goto exit;
+// }
+
+ /*
+ * IO may take forever
+ * hence wait in an interruptible state
+ */
+ rv = wait_event_interruptible(dev->bulk_in_wait, (!dev->ongoing_read));
+ if (rv < 0)
+ goto exit;
+ }
+
+ /* errors must be reported */
+ rv = dev->errors;
+ if (rv < 0) {
+ /* any error is reported once */
+ dev->errors = 0;
+ /* to preserve notifications about reset */
+ rv = (rv == -EPIPE) ? rv : -EIO;
+ /* report it */
+ goto exit;
+ }
+
+ /*
+ * if the buffer is filled we may satisfy the read
+ * else we need to start IO
+ */
+
+ if (dev->bulk_in_filled) {
+ /* we had read data */
+
+ size_t available = dev->bulk_in_filled - dev->bulk_in_copied;
+// size_t chunk = min(available, count); /* compute chunk later */
+ size_t chunk;
+
+ DIA_LOG(2, "we have data: %zu %zu.\n", dev->bulk_in_filled, dev->bulk_in_copied);
+
+ if (!available) {
+ /*
+ * all data has been used
+ * actual IO needs to be done
+ */
+ /* it seems that requests for less than dev->bulk_in_size
+ * are not accepted
+ */
+ rv = skel_do_read_io(dev, dev->bulk_in_size);
+ if (rv < 0)
+ goto exit;
+ else
+ goto retry;
+ }
+
+ /*
+ * data is available - chunk tells us how much shall be copied
+ */
+
+ /* Condition dev->bulk_in_copied > 0 maybe will never happen. In case,
+ * signal the event and copy using the original procedure, i.e., copy
+ * first two bytes also
+ */
+
+ if (dev->bulk_in_copied) {
+ int j;
+
+ for (j = 0 ; j < dev->bulk_in_filled ; j++) {
+ pr_alert("copy -> %x %zu %x\n",
+ j, dev->bulk_in_copied, dev->bulk_in_buffer[j]);
+ }
+ chunk = min(available, count);
+ memcpy(buffer, dev->bulk_in_buffer + dev->bulk_in_copied, chunk);
+ rv = chunk;
+ dev->bulk_in_copied += chunk;
+
+ /* copy discarding first two bytes that contain ftdi chip status */
+
+ } else {
+ /* account for two bytes to be discarded */
+ chunk = min(available, count + 2);
+ if (chunk < 2) {
+ pr_alert("BAD READ - chunk: %zu\n", chunk);
+ rv = -EIO;
+ goto exit;
+ }
+
+ memcpy(buffer, dev->bulk_in_buffer + 2, chunk - 2);
+ rv = chunk;
+ dev->bulk_in_copied += chunk;
+ }
+
+ /*
+ * if we are asked for more than we have,
+ * we start IO but don't wait
+ *
+ * No, no read ahead allowed; if the case, more data will be
+ * asked for by the lpvo_usb_gpib layer.
+ */
+// if (available < count)
+// skel_do_read_io(dev, dev->bulk_in_size);
+ } else {
+ DIA_LOG(1, "no data - start read - copied: %zd.\n", dev->bulk_in_copied);
+
+ /* no data in the buffer */
+ rv = skel_do_read_io(dev, dev->bulk_in_size);
+ if (rv < 0)
+ goto exit;
+ else
+ goto retry;
+ }
+exit:
+ mutex_unlock(&dev->io_mutex);
+ if (rv == 2)
+ goto restart; /* ftdi chip returns two status bytes after a latency anyhow */
+ DIA_LOG(1, "exit with %d.\n", rv);
+ if (rv > 0)
+ return rv - 2; /* account for 2 discarded bytes in a valid buffer */
+ return rv;
+}
+
+/*
+ * write functions
+ */
+
+static void skel_write_bulk_callback(struct urb *urb)
+{
+ struct usb_skel *dev;
+ unsigned long flags;
+
+ dev = urb->context;
+
+ /* sync/async unlink faults aren't errors */
+ if (urb->status) {
+ if (!(urb->status == -ENOENT ||
+ urb->status == -ECONNRESET ||
+ urb->status == -ESHUTDOWN))
+ dev_err(&dev->interface->dev,
+ "%s - nonzero write bulk status received: %d\n",
+ __func__, urb->status);
+
+ spin_lock_irqsave(&dev->err_lock, flags);
+ dev->errors = urb->status;
+ spin_unlock_irqrestore(&dev->err_lock, flags);
+ }
+
+ /* free up our allocated buffer */
+ usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+ urb->transfer_buffer, urb->transfer_dma);
+ up(&dev->limit_sem);
+}
+
+/*
+ * skel_do_write() - write operations from lpvo_usb_gpib
+ */
+
+static ssize_t skel_do_write(struct usb_skel *dev, const char *buffer, size_t count)
+{
+ int retval = 0;
+ struct urb *urb = NULL;
+ char *buf = NULL;
+ size_t writesize = min_t(size_t, count, (size_t)MAX_TRANSFER);
+
+ /* verify that we actually have some data to write */
+ if (count == 0)
+ goto exit;
+
+ /*
+ * limit the number of URBs in flight to stop a user from using up all
+ * RAM
+ */
+ /* Only one URB is used, because we can't have a pending write() and go on */
+
+// if (!(file->f_flags & O_NONBLOCK)) { /* no NONBLOCK provided */
+ if (down_interruptible(&dev->limit_sem)) {
+ retval = -ERESTARTSYS;
+ goto exit;
+ }
+// } else {
+// if (down_trylock(&dev->limit_sem)) {
+// retval = -EAGAIN;
+// goto exit;
+// }
+// }
+
+ spin_lock_irq(&dev->err_lock);
+ retval = dev->errors;
+ if (retval < 0) {
+ /* any error is reported once */
+ dev->errors = 0;
+ /* to preserve notifications about reset */
+ retval = (retval == -EPIPE) ? retval : -EIO;
+ }
+ spin_unlock_irq(&dev->err_lock);
+ if (retval < 0)
+ goto error;
+
+ /* create a urb, and a buffer for it, and copy the data to the urb */
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ buf = usb_alloc_coherent(dev->udev, writesize, GFP_KERNEL,
+ &urb->transfer_dma);
+ if (!buf) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ memcpy(buf, buffer, count);
+
+ /* this lock makes sure we don't submit URBs to gone devices */
+ mutex_lock(&dev->io_mutex);
+ if (!dev->interface) { /* disconnect() was called */
+ mutex_unlock(&dev->io_mutex);
+ retval = -ENODEV;
+ goto error;
+ }
+
+ /* initialize the urb properly */
+ usb_fill_bulk_urb(urb, dev->udev,
+ usb_sndbulkpipe(dev->udev, dev->bulk_out_endpoint_addr),
+ buf, writesize, skel_write_bulk_callback, dev);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(urb, &dev->submitted);
+
+ /* send the data out the bulk port */
+ retval = usb_submit_urb(urb, GFP_KERNEL);
+ mutex_unlock(&dev->io_mutex);
+ if (retval) {
+ dev_err(&dev->interface->dev,
+ "%s - failed submitting write urb, error %d\n",
+ __func__, retval);
+ goto error_unanchor;
+ }
+
+ /*
+ * release our reference to this urb, the USB core will eventually free
+ * it entirely
+ */
+ usb_free_urb(urb);
+
+ return writesize;
+
+error_unanchor:
+ usb_unanchor_urb(urb);
+error:
+ if (urb) {
+ usb_free_coherent(dev->udev, writesize, buf, urb->transfer_dma);
+ usb_free_urb(urb);
+ }
+ up(&dev->limit_sem);
+
+exit:
+ return retval;
+}
+
+/*
+ * services for the user space devices
+ */
+
+#if USER_DEVICE /* conditional compilation of user space device */
+
+static int skel_flush(struct file *file, fl_owner_t id)
+{
+ struct usb_skel *dev;
+ int res;
+
+ dev = file->private_data;
+ if (!dev)
+ return -ENODEV;
+
+ /* wait for io to stop */
+ mutex_lock(&dev->io_mutex);
+ skel_draw_down(dev);
+
+ /* read out errors, leave subsequent opens a clean slate */
+ spin_lock_irq(&dev->err_lock);
+ res = dev->errors ? (dev->errors == -EPIPE ? -EPIPE : -EIO) : 0;
+ dev->errors = 0;
+ spin_unlock_irq(&dev->err_lock);
+
+ mutex_unlock(&dev->io_mutex);
+
+ return res;
+}
+
+static int skel_open(struct inode *inode, struct file *file)
+{
+ struct usb_skel *dev;
+ struct usb_interface *interface;
+ int subminor;
+ int retval = 0;
+
+ subminor = iminor(inode);
+
+ interface = usb_find_interface(&skel_driver, subminor);
+ if (!interface) {
+ pr_err("%s - error, can't find device for minor %d\n",
+ __func__, subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ dev = usb_get_intfdata(interface);
+ if (!dev) {
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ retval = usb_autopm_get_interface(interface);
+ if (retval)
+ goto exit;
+
+ /* increment our usage count for the device */
+ kref_get(&dev->kref);
+
+ /* save our object in the file's private structure */
+ file->private_data = dev;
+
+exit:
+ return retval;
+}
+
+static int skel_release(struct inode *inode, struct file *file)
+{
+ struct usb_skel *dev;
+
+ dev = file->private_data;
+ if (!dev)
+ return -ENODEV;
+
+ /* allow the device to be autosuspended */
+ mutex_lock(&dev->io_mutex);
+ if (dev->interface)
+ usb_autopm_put_interface(dev->interface);
+ mutex_unlock(&dev->io_mutex);
+
+ /* decrement the count on our device */
+ kref_put(&dev->kref, skel_delete);
+ return 0;
+}
+
+/*
+ * user space access to read function
+ */
+
+static ssize_t skel_read(struct file *file, char *buffer, size_t count,
+ loff_t *ppos)
+{
+ struct usb_skel *dev;
+ char *buf;
+ ssize_t rv;
+
+ dev = file->private_data;
+
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ rv = skel_do_read(dev, buf, count);
+
+ pr_alert("%s - return with %zu\n", __func__, rv);
+
+ if (rv > 0) {
+ if (copy_to_user(buffer, buf, rv)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+ }
+ kfree(buf);
+ return rv;
+}
+
+/*
+ * user space access to write function
+ */
+
+static ssize_t skel_write(struct file *file, const char *user_buffer,
+ size_t count, loff_t *ppos)
+{
+ struct usb_skel *dev;
+ char *buf;
+ ssize_t rv;
+
+ dev = file->private_data;
+
+ buf = kmalloc(count, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ if (copy_from_user(buf, user_buffer, count)) {
+ kfree(buf);
+ return -EFAULT;
+ }
+
+ rv = skel_do_write(dev, buf, count);
+ kfree(buf);
+ return rv;
+}
+#endif
+
+static const struct file_operations skel_fops = {
+ .owner = THIS_MODULE,
+#if USER_DEVICE
+ .read = skel_read,
+ .write = skel_write,
+ .open = skel_open,
+ .release = skel_release,
+ .flush = skel_flush,
+ .llseek = noop_llseek,
+#endif
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with the driver core
+ */
+#if USER_DEVICE
+static struct usb_class_driver skel_class = {
+ .name = "lpvo_raw%d",
+ .fops = &skel_fops,
+ .minor_base = USB_SKEL_MINOR_BASE,
+};
+#endif
+
+static int skel_probe(struct usb_interface *interface,
+ const struct usb_device_id *id)
+{
+ struct usb_skel *dev;
+ struct usb_endpoint_descriptor *bulk_in, *bulk_out;
+ int retval;
+ char *device_path;
+
+ mutex_init(&minors_lock); /* required for handling minor numbers table */
+
+ /* allocate memory for our device state and initialize it */
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
+
+ kref_init(&dev->kref);
+ sema_init(&dev->limit_sem, WRITES_IN_FLIGHT);
+ mutex_init(&dev->io_mutex);
+ spin_lock_init(&dev->err_lock);
+ init_usb_anchor(&dev->submitted);
+ init_waitqueue_head(&dev->bulk_in_wait);
+
+ dev->udev = usb_get_dev(interface_to_usbdev(interface));
+ dev->interface = interface;
+
+ /* set up the endpoint information */
+ /* use only the first bulk-in and bulk-out endpoints */
+ retval = usb_find_common_endpoints(interface->cur_altsetting,
+ &bulk_in, &bulk_out, NULL, NULL);
+ if (retval) {
+ dev_err(&interface->dev,
+ "Could not find both bulk-in and bulk-out endpoints\n");
+ goto error;
+ }
+
+ dev->bulk_in_size = usb_endpoint_maxp(bulk_in);
+ dev->bulk_in_endpoint_addr = bulk_in->bEndpointAddress;
+ dev->bulk_in_buffer = kmalloc(dev->bulk_in_size, GFP_KERNEL);
+ if (!dev->bulk_in_buffer) {
+ retval = -ENOMEM;
+ goto error;
+ }
+ dev->bulk_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->bulk_in_urb) {
+ retval = -ENOMEM;
+ goto error;
+ }
+
+ dev->bulk_out_endpoint_addr = bulk_out->bEndpointAddress;
+
+ /* save our data pointer in this interface device */
+ usb_set_intfdata(interface, dev);
+
+ /* let the world know */
+
+ device_path = kobject_get_path(&dev->udev->dev.kobj, GFP_KERNEL);
+ pr_alert("%s:%s - New lpvo_usb_device -> bus: %d dev: %d path: %s\n", NAME, __func__,
+ dev->udev->bus->busnum, dev->udev->devnum, device_path);
+ kfree(device_path);
+
+#if USER_DEVICE
+ /* we can register the device now, as it is ready */
+ retval = usb_register_dev(interface, &skel_class);
+ if (retval) {
+ /* something prevented us from registering this driver */
+ dev_err(&interface->dev,
+ "Not able to get a minor for this device.\n");
+ usb_set_intfdata(interface, NULL);
+ goto error;
+ }
+
+ /* let the user know what node this device is now attached to */
+ dev_info(&interface->dev,
+ "lpvo_usb_gpib device now attached to lpvo_raw%d",
+ interface->minor);
+#endif
+
+ write_latency_timer(dev->udev); /* adjust the latency timer */
+
+ usb_gpib_init_module(interface); /* last, init the lpvo for this minor */
+
+ return 0;
+
+error:
+ /* this frees allocated memory */
+ kref_put(&dev->kref, skel_delete);
+
+ return retval;
+}
+
+static void skel_disconnect(struct usb_interface *interface)
+{
+ struct usb_skel *dev;
+ int minor = interface->minor;
+
+ usb_gpib_exit_module(minor); /* first, disactivate the lpvo */
+
+ dev = usb_get_intfdata(interface);
+ usb_set_intfdata(interface, NULL);
+
+#if USER_DEVICE
+ /* give back our minor */
+ usb_deregister_dev(interface, &skel_class);
+#endif
+
+ /* prevent more I/O from starting */
+ mutex_lock(&dev->io_mutex);
+ dev->interface = NULL;
+ mutex_unlock(&dev->io_mutex);
+
+ usb_kill_anchored_urbs(&dev->submitted);
+
+ /* decrement our usage count */
+ kref_put(&dev->kref, skel_delete);
+
+ dev_info(&interface->dev, "USB lpvo_raw #%d now disconnected", minor);
+}
+
+static void skel_draw_down(struct usb_skel *dev)
+{
+ int time;
+
+ time = usb_wait_anchor_empty_timeout(&dev->submitted, 1000);
+ if (!time)
+ usb_kill_anchored_urbs(&dev->submitted);
+ usb_kill_urb(dev->bulk_in_urb);
+}
+
+static int skel_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ struct usb_skel *dev = usb_get_intfdata(intf);
+
+ if (!dev)
+ return 0;
+ skel_draw_down(dev);
+ return 0;
+}
+
+static int skel_resume(struct usb_interface *intf)
+{
+ return 0;
+}
+
+static int skel_pre_reset(struct usb_interface *intf)
+{
+ struct usb_skel *dev = usb_get_intfdata(intf);
+
+ mutex_lock(&dev->io_mutex);
+ skel_draw_down(dev);
+
+ return 0;
+}
+
+static int skel_post_reset(struct usb_interface *intf)
+{
+ struct usb_skel *dev = usb_get_intfdata(intf);
+
+ /* we are sure no URBs are active - no locking needed */
+ dev->errors = -EPIPE;
+ mutex_unlock(&dev->io_mutex);
+
+ return 0;
+}
+
+static struct usb_driver skel_driver = {
+ .name = NAME,
+ .probe = skel_probe,
+ .disconnect = skel_disconnect,
+ .suspend = skel_suspend,
+ .resume = skel_resume,
+ .pre_reset = skel_pre_reset,
+ .post_reset = skel_post_reset,
+ .id_table = skel_table,
+ .supports_autosuspend = 1,
+};
+
+module_usb_driver(skel_driver);
diff --git a/drivers/staging/gpib/nec7210/Makefile b/drivers/staging/gpib/nec7210/Makefile
new file mode 100644
index 000000000000..64330f2e89d1
--- /dev/null
+++ b/drivers/staging/gpib/nec7210/Makefile
@@ -0,0 +1,4 @@
+
+obj-$(CONFIG_GPIB_NEC7210) += nec7210.o
+
+
diff --git a/drivers/staging/gpib/nec7210/board.h b/drivers/staging/gpib/nec7210/board.h
new file mode 100644
index 000000000000..ac3fe38ade57
--- /dev/null
+++ b/drivers/staging/gpib/nec7210/board.h
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_PCIIA_BOARD_H
+#define _GPIB_PCIIA_BOARD_H
+
+#include "gpibP.h"
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+
+#include "nec7210.h"
+
+#endif //_GPIB_PCIIA_BOARD_H
+
diff --git a/drivers/staging/gpib/nec7210/nec7210.c b/drivers/staging/gpib/nec7210/nec7210.c
new file mode 100644
index 000000000000..1d9951035497
--- /dev/null
+++ b/drivers/staging/gpib/nec7210/nec7210.c
@@ -0,0 +1,1134 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include "board.h"
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/dma.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB library code for NEC uPD7210");
+
+int nec7210_enable_eos(gpib_board_t *board, struct nec7210_priv *priv, uint8_t eos_byte,
+ int compare_8_bits)
+{
+ write_byte(priv, eos_byte, EOSR);
+ priv->auxa_bits |= HR_REOS;
+ if (compare_8_bits)
+ priv->auxa_bits |= HR_BIN;
+ else
+ priv->auxa_bits &= ~HR_BIN;
+ write_byte(priv, priv->auxa_bits, AUXMR);
+ return 0;
+}
+EXPORT_SYMBOL(nec7210_enable_eos);
+
+void nec7210_disable_eos(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ priv->auxa_bits &= ~HR_REOS;
+ write_byte(priv, priv->auxa_bits, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_disable_eos);
+
+int nec7210_parallel_poll(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *result)
+{
+ int ret;
+
+ clear_bit(COMMAND_READY_BN, &priv->state);
+
+ // execute parallel poll
+ write_byte(priv, AUX_EPP, AUXMR);
+ // wait for result FIXME: support timeouts
+ ret = wait_event_interruptible(board->wait, test_bit(COMMAND_READY_BN, &priv->state));
+ if (ret) {
+ dev_dbg(board->gpib_dev, "gpib: parallel poll interrupted\n");
+ return -ERESTARTSYS;
+ }
+ *result = read_byte(priv, CPTR);
+
+ return 0;
+}
+EXPORT_SYMBOL(nec7210_parallel_poll);
+
+void nec7210_parallel_poll_configure(gpib_board_t *board,
+ struct nec7210_priv *priv, unsigned int configuration)
+{
+ write_byte(priv, PPR | configuration, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_parallel_poll_configure);
+
+void nec7210_parallel_poll_response(gpib_board_t *board, struct nec7210_priv *priv, int ist)
+{
+ if (ist)
+ write_byte(priv, AUX_SPPF, AUXMR);
+ else
+ write_byte(priv, AUX_CPPF, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_parallel_poll_response);
+/* This is really only adequate for chips that do a 488.2 style reqt/reqf
+ * based on bit 6 of the SPMR (see chapter 11.3.3 of 488.2). For simpler chips that simply
+ * set rsv directly based on bit 6, we either need to do more hardware setup to expose
+ * the 488.2 capability (for example with NI chips), or we need to implement the
+ * 488.2 set srv state machine in the driver (if that is even viable).
+ */
+void nec7210_serial_poll_response(gpib_board_t *board, struct nec7210_priv *priv, uint8_t status)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (status & request_service_bit) {
+ priv->srq_pending = 1;
+ clear_bit(SPOLL_NUM, &board->status);
+
+ } else {
+ priv->srq_pending = 0;
+ }
+ write_byte(priv, status, SPMR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+EXPORT_SYMBOL(nec7210_serial_poll_response);
+
+uint8_t nec7210_serial_poll_status(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ return read_byte(priv, SPSR);
+}
+EXPORT_SYMBOL(nec7210_serial_poll_status);
+
+int nec7210_primary_address(const gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int address)
+{
+ // put primary address in address0
+ write_byte(priv, address & ADDRESS_MASK, ADR);
+ return 0;
+}
+EXPORT_SYMBOL(nec7210_primary_address);
+
+int nec7210_secondary_address(const gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int address, int enable)
+{
+ if (enable) {
+ // put secondary address in address1
+ write_byte(priv, HR_ARS | (address & ADDRESS_MASK), ADR);
+ // go to address mode 2
+ priv->reg_bits[ADMR] &= ~HR_ADM0;
+ priv->reg_bits[ADMR] |= HR_ADM1;
+ } else {
+ // disable address1 register
+ write_byte(priv, HR_ARS | HR_DT | HR_DL, ADR);
+ // go to address mode 1
+ priv->reg_bits[ADMR] |= HR_ADM0;
+ priv->reg_bits[ADMR] &= ~HR_ADM1;
+ }
+ write_byte(priv, priv->reg_bits[ADMR], ADMR);
+ return 0;
+}
+EXPORT_SYMBOL(nec7210_secondary_address);
+
+static void update_talker_state(struct nec7210_priv *priv, unsigned int address_status_bits)
+{
+ if ((address_status_bits & HR_TA)) {
+ if ((address_status_bits & HR_NATN)) {
+ if (address_status_bits & HR_SPMS)
+ priv->talker_state = serial_poll_active;
+ else
+ priv->talker_state = talker_active;
+ } else {
+ priv->talker_state = talker_addressed;
+ }
+ } else {
+ priv->talker_state = talker_idle;
+ }
+}
+
+static void update_listener_state(struct nec7210_priv *priv, unsigned int address_status_bits)
+{
+ if (address_status_bits & HR_LA) {
+ if ((address_status_bits & HR_NATN))
+ priv->listener_state = listener_active;
+ else
+ priv->listener_state = listener_addressed;
+ } else {
+ priv->listener_state = listener_idle;
+ }
+}
+
+unsigned int nec7210_update_status_nolock(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ int address_status_bits;
+ u8 spoll_status;
+
+ if (!priv)
+ return 0;
+
+ address_status_bits = read_byte(priv, ADSR);
+ if (address_status_bits & HR_CIC)
+ set_bit(CIC_NUM, &board->status);
+ else
+ clear_bit(CIC_NUM, &board->status);
+ // check for talker/listener addressed
+ update_talker_state(priv, address_status_bits);
+ if (priv->talker_state == talker_active || priv->talker_state == talker_addressed)
+ set_bit(TACS_NUM, &board->status);
+ else
+ clear_bit(TACS_NUM, &board->status);
+ update_listener_state(priv, address_status_bits);
+ if (priv->listener_state == listener_active ||
+ priv->listener_state == listener_addressed)
+ set_bit(LACS_NUM, &board->status);
+ else
+ clear_bit(LACS_NUM, &board->status);
+ if (address_status_bits & HR_NATN)
+ clear_bit(ATN_NUM, &board->status);
+ else
+ set_bit(ATN_NUM, &board->status);
+ spoll_status = nec7210_serial_poll_status(board, priv);
+ if (priv->srq_pending && (spoll_status & request_service_bit) == 0) {
+ priv->srq_pending = 0;
+ set_bit(SPOLL_NUM, &board->status);
+ }
+// dev_dbg(board->gpib_dev, "status 0x%x, state 0x%x\n", board->status, priv->state);
+
+ /* we rely on the interrupt handler to set the
+ * rest of the status bits
+ */
+
+ return board->status;
+}
+EXPORT_SYMBOL(nec7210_update_status_nolock);
+
+unsigned int nec7210_update_status(gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int clear_mask)
+{
+ unsigned long flags;
+ unsigned int retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ board->status &= ~clear_mask;
+ retval = nec7210_update_status_nolock(board, priv);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_update_status);
+
+unsigned int nec7210_set_reg_bits(struct nec7210_priv *priv, unsigned int reg,
+ unsigned int mask, unsigned int bits)
+{
+ priv->reg_bits[reg] &= ~mask;
+ priv->reg_bits[reg] |= mask & bits;
+ write_byte(priv, priv->reg_bits[reg], reg);
+ return priv->reg_bits[reg];
+}
+EXPORT_SYMBOL(nec7210_set_reg_bits);
+
+void nec7210_set_handshake_mode(gpib_board_t *board, struct nec7210_priv *priv, int mode)
+{
+ unsigned long flags;
+
+ mode &= HR_HANDSHAKE_MASK;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if ((priv->auxa_bits & HR_HANDSHAKE_MASK) != mode) {
+ priv->auxa_bits &= ~HR_HANDSHAKE_MASK;
+ priv->auxa_bits |= mode;
+ write_byte(priv, priv->auxa_bits, AUXMR);
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+EXPORT_SYMBOL(nec7210_set_handshake_mode);
+
+uint8_t nec7210_read_data_in(gpib_board_t *board, struct nec7210_priv *priv, int *end)
+{
+ unsigned long flags;
+ u8 data;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ data = read_byte(priv, DIR);
+ clear_bit(READ_READY_BN, &priv->state);
+ if (test_and_clear_bit(RECEIVED_END_BN, &priv->state))
+ *end = 1;
+ else
+ *end = 0;
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return data;
+}
+EXPORT_SYMBOL(nec7210_read_data_in);
+
+int nec7210_take_control(gpib_board_t *board, struct nec7210_priv *priv, int syncronous)
+{
+ int i;
+ const int timeout = 100;
+ int retval = 0;
+ unsigned int adsr_bits = 0;
+
+ if (syncronous)
+ write_byte(priv, AUX_TCS, AUXMR);
+ else
+ write_byte(priv, AUX_TCA, AUXMR);
+ // busy wait until ATN is asserted
+ for (i = 0; i < timeout; i++) {
+ adsr_bits = read_byte(priv, ADSR);
+ if ((adsr_bits & HR_NATN) == 0)
+ break;
+ udelay(1);
+ }
+ if (i == timeout)
+ return -ETIMEDOUT;
+
+ clear_bit(WRITE_READY_BN, &priv->state);
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_take_control);
+
+int nec7210_go_to_standby(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ int i;
+ const int timeout = 1000;
+ unsigned int adsr_bits = 0;
+ int retval = 0;
+
+ write_byte(priv, AUX_GTS, AUXMR);
+ // busy wait until ATN is released
+ for (i = 0; i < timeout; i++) {
+ adsr_bits = read_byte(priv, ADSR);
+ if (adsr_bits & HR_NATN)
+ break;
+ udelay(1);
+ }
+ // if busy wait has failed, try sleeping
+ if (i == timeout) {
+ for (i = 0; i < HZ; i++) {
+ set_current_state(TASK_INTERRUPTIBLE);
+ if (schedule_timeout(1))
+ return -ERESTARTSYS;
+ adsr_bits = read_byte(priv, ADSR);
+ if (adsr_bits & HR_NATN)
+ break;
+ }
+ if (i == HZ) {
+ pr_err("nec7210: error waiting for NATN\n");
+ return -ETIMEDOUT;
+ }
+ }
+
+ clear_bit(COMMAND_READY_BN, &priv->state);
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_go_to_standby);
+
+void nec7210_request_system_control(gpib_board_t *board, struct nec7210_priv *priv,
+ int request_control)
+{
+ if (request_control == 0) {
+ write_byte(priv, AUX_CREN, AUXMR);
+ write_byte(priv, AUX_CIFC, AUXMR);
+ write_byte(priv, AUX_DSC, AUXMR);
+ }
+}
+EXPORT_SYMBOL(nec7210_request_system_control);
+
+void nec7210_interface_clear(gpib_board_t *board, struct nec7210_priv *priv, int assert)
+{
+ if (assert)
+ write_byte(priv, AUX_SIFC, AUXMR);
+ else
+ write_byte(priv, AUX_CIFC, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_interface_clear);
+
+void nec7210_remote_enable(gpib_board_t *board, struct nec7210_priv *priv, int enable)
+{
+ if (enable)
+ write_byte(priv, AUX_SREN, AUXMR);
+ else
+ write_byte(priv, AUX_CREN, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_remote_enable);
+
+void nec7210_release_rfd_holdoff(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (test_bit(RFD_HOLDOFF_BN, &priv->state) &&
+ test_bit(READ_READY_BN, &priv->state) == 0) {
+ write_byte(priv, AUX_FH, AUXMR);
+ clear_bit(RFD_HOLDOFF_BN, &priv->state);
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+EXPORT_SYMBOL(nec7210_release_rfd_holdoff);
+
+unsigned int nec7210_t1_delay(gpib_board_t *board, struct nec7210_priv *priv,
+ unsigned int nano_sec)
+{
+ unsigned int retval;
+
+ if (nano_sec <= 500) {
+ priv->auxb_bits |= HR_TRI;
+ retval = 500;
+ } else {
+ priv->auxb_bits &= ~HR_TRI;
+ retval = 2000;
+ }
+ write_byte(priv, priv->auxb_bits, AUXMR);
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_t1_delay);
+
+void nec7210_return_to_local(const gpib_board_t *board, struct nec7210_priv *priv)
+{
+ write_byte(priv, AUX_RTL, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_return_to_local);
+
+static inline short nec7210_atn_has_changed(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ short address_status_bits = read_byte(priv, ADSR);
+
+ if (address_status_bits & HR_NATN) {
+ if (test_bit(ATN_NUM, &board->status))
+ return 1;
+ else
+ return 0;
+ } else {
+ if (test_bit(ATN_NUM, &board->status))
+ return 0;
+ else
+ return 1;
+ }
+ return -1;
+}
+
+int nec7210_command(gpib_board_t *board, struct nec7210_priv *priv, uint8_t
+ *buffer, size_t length, size_t *bytes_written)
+{
+ int retval = 0;
+ unsigned long flags;
+
+ *bytes_written = 0;
+
+ clear_bit(BUS_ERROR_BN, &priv->state);
+
+ while (*bytes_written < length) {
+ if (wait_event_interruptible(board->wait,
+ test_bit(COMMAND_READY_BN, &priv->state) ||
+ test_bit(BUS_ERROR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib command wait interrupted\n");
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ break;
+ if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) {
+ pr_err("nec7210: bus error on command byte\n");
+ break;
+ }
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ clear_bit(COMMAND_READY_BN, &priv->state);
+ write_byte(priv, buffer[*bytes_written], CDOR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ ++(*bytes_written);
+
+ if (need_resched())
+ schedule();
+ }
+ // wait for last byte to get sent
+ if (wait_event_interruptible(board->wait, test_bit(COMMAND_READY_BN, &priv->state) ||
+ test_bit(BUS_ERROR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib command wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ dev_dbg(board->gpib_dev, "gpib command timed out\n");
+ retval = -ETIMEDOUT;
+ }
+ if (test_and_clear_bit(BUS_ERROR_BN, &priv->state)) {
+ pr_err("nec7210: bus error on command byte\n");
+ retval = -EIO;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_command);
+
+static int pio_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+
+ *bytes_read = 0;
+ *end = 0;
+
+ while (*bytes_read < length) {
+ if (wait_event_interruptible(board->wait,
+ test_bit(READ_READY_BN, &priv->state) ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "nec7210: pio read wait interrupted\n");
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (test_bit(READ_READY_BN, &priv->state)) {
+ if (*bytes_read == 0) {
+ /* We set the handshake mode here because we know
+ * no new bytes will arrive (it has already arrived
+ * and is awaiting being read out of the chip) while we are changing
+ * modes. This ensures we can reliably keep track
+ * of the holdoff state.
+ */
+ nec7210_set_handshake_mode(board, priv, HR_HLDA);
+ }
+ buffer[(*bytes_read)++] = nec7210_read_data_in(board, priv, end);
+ if (*end)
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ dev_dbg(board->gpib_dev, "interrupted by timeout\n");
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &priv->state)) {
+ dev_dbg(board->gpib_dev, "interrupted by device clear\n");
+ retval = -EINTR;
+ break;
+ }
+
+ if (*bytes_read < length)
+ nec7210_release_rfd_holdoff(board, priv);
+
+ if (need_resched())
+ schedule();
+ }
+ return retval;
+}
+
+#ifdef NEC_DMA
+static ssize_t __dma_read(gpib_board_t *board, struct nec7210_priv *priv, size_t length)
+{
+ ssize_t retval = 0;
+ size_t count = 0;
+ unsigned long flags, dma_irq_flags;
+
+ if (length == 0)
+ return 0;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ dma_irq_flags = claim_dma_lock();
+ disable_dma(priv->dma_channel);
+ /* program dma controller */
+ clear_dma_ff(priv->dma_channel);
+ set_dma_count(priv->dma_channel, length);
+ set_dma_addr(priv->dma_channel, priv->dma_buffer_addr);
+ set_dma_mode(priv->dma_channel, DMA_MODE_READ);
+ release_dma_lock(dma_irq_flags);
+
+ enable_dma(priv->dma_channel);
+
+ set_bit(DMA_READ_IN_PROGRESS_BN, &priv->state);
+ clear_bit(READ_READY_BN, &priv->state);
+
+ // enable nec7210 dma
+ nec7210_set_reg_bits(priv, IMR2, HR_DMAI, HR_DMAI);
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ // wait for data to transfer
+ if (wait_event_interruptible(board->wait,
+ test_bit(DMA_READ_IN_PROGRESS_BN, &priv->state) == 0 ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "nec7210: dma read wait interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &priv->state))
+ retval = -EINTR;
+
+ // disable nec7210 dma
+ nec7210_set_reg_bits(priv, IMR2, HR_DMAI, 0);
+
+ // record how many bytes we transferred
+ flags = claim_dma_lock();
+ clear_dma_ff(priv->dma_channel);
+ disable_dma(priv->dma_channel);
+ count += length - get_dma_residue(priv->dma_channel);
+ release_dma_lock(flags);
+
+ return retval ? retval : count;
+}
+
+static ssize_t dma_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length)
+{
+ size_t remain = length;
+ size_t transfer_size;
+ ssize_t retval = 0;
+
+ while (remain > 0) {
+ transfer_size = (priv->dma_buffer_length < remain) ?
+ priv->dma_buffer_length : remain;
+ retval = __dma_read(board, priv, transfer_size);
+ if (retval < 0)
+ break;
+ memcpy(buffer, priv->dma_buffer, transfer_size);
+ remain -= retval;
+ buffer += retval;
+ if (test_bit(RECEIVED_END_BN, &priv->state))
+ break;
+ }
+
+ if (retval < 0)
+ return retval;
+
+ return length - remain;
+}
+#endif
+
+int nec7210_read(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+
+ *end = 0;
+ *bytes_read = 0;
+
+ if (length == 0)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &priv->state); // XXX wrong
+
+ nec7210_release_rfd_holdoff(board, priv);
+
+ retval = pio_read(board, priv, buffer, length, end, bytes_read);
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_read);
+
+static int pio_write_wait(gpib_board_t *board, struct nec7210_priv *priv,
+ short wake_on_lacs, short wake_on_atn, short wake_on_bus_error)
+{
+ // wait until byte is ready to be sent
+ if (wait_event_interruptible(board->wait,
+ (test_bit(TACS_NUM, &board->status) &&
+ test_bit(WRITE_READY_BN, &priv->state)) ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ (wake_on_bus_error && test_bit(BUS_ERROR_BN, &priv->state)) ||
+ (wake_on_lacs && test_bit(LACS_NUM, &board->status)) ||
+ (wake_on_atn && test_bit(ATN_NUM, &board->status)) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ dev_dbg(board->gpib_dev, "nec7210: write timed out\n");
+ return -ETIMEDOUT;
+ }
+ if (test_bit(DEV_CLEAR_BN, &priv->state)) {
+ dev_dbg(board->gpib_dev, "nec7210: write interrupted by clear\n");
+ return -EINTR;
+ }
+ if (wake_on_bus_error && test_and_clear_bit(BUS_ERROR_BN, &priv->state)) {
+ dev_dbg(board->gpib_dev, "nec7210: bus error on write\n");
+ return -EIO;
+ }
+ return 0;
+}
+
+static int pio_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written)
+{
+ size_t last_count = 0;
+ ssize_t retval = 0;
+ unsigned long flags;
+ const int max_bus_errors = (length > 1000) ? length : 1000;
+ int bus_error_count = 0;
+ *bytes_written = 0;
+
+ clear_bit(BUS_ERROR_BN, &priv->state);
+
+ while (*bytes_written < length) {
+ if (need_resched())
+ schedule();
+
+ retval = pio_write_wait(board, priv, 0, 0, priv->type == NEC7210);
+ if (retval == -EIO) {
+ /* resend last byte on bus error */
+ *bytes_written = last_count;
+ dev_dbg(board->gpib_dev, "resending %c\n", buffer[*bytes_written]);
+ /* we can get unrecoverable bus errors,
+ * so give up after a while
+ */
+ bus_error_count++;
+ if (bus_error_count > max_bus_errors)
+ return retval;
+ continue;
+ } else {
+ if (retval < 0)
+ return retval;
+ }
+ spin_lock_irqsave(&board->spinlock, flags);
+ clear_bit(BUS_ERROR_BN, &priv->state);
+ clear_bit(WRITE_READY_BN, &priv->state);
+ last_count = *bytes_written;
+ write_byte(priv, buffer[(*bytes_written)++], CDOR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ }
+ retval = pio_write_wait(board, priv, 1, 1, priv->type == NEC7210);
+ return retval;
+}
+
+#ifdef NEC_DMA
+static ssize_t __dma_write(gpib_board_t *board, struct nec7210_priv *priv, dma_addr_t address,
+ size_t length)
+{
+ unsigned long flags, dma_irq_flags;
+ int residue = 0;
+ int retval = 0;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ /* program dma controller */
+ dma_irq_flags = claim_dma_lock();
+ disable_dma(priv->dma_channel);
+ clear_dma_ff(priv->dma_channel);
+ set_dma_count(priv->dma_channel, length);
+ set_dma_addr(priv->dma_channel, address);
+ set_dma_mode(priv->dma_channel, DMA_MODE_WRITE);
+ enable_dma(priv->dma_channel);
+ release_dma_lock(dma_irq_flags);
+
+ // enable board's dma for output
+ nec7210_set_reg_bits(priv, IMR2, HR_DMAO, HR_DMAO);
+
+ clear_bit(WRITE_READY_BN, &priv->state);
+ set_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state);
+
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ // suspend until message is sent
+ if (wait_event_interruptible(board->wait,
+ test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0 ||
+ test_bit(BUS_ERROR_BN, &priv->state) ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted!\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+ if (test_and_clear_bit(DEV_CLEAR_BN, &priv->state))
+ retval = -EINTR;
+ if (test_and_clear_bit(BUS_ERROR_BN, &priv->state))
+ retval = -EIO;
+
+ // disable board's dma
+ nec7210_set_reg_bits(priv, IMR2, HR_DMAO, 0);
+
+ dma_irq_flags = claim_dma_lock();
+ clear_dma_ff(priv->dma_channel);
+ disable_dma(priv->dma_channel);
+ residue = get_dma_residue(priv->dma_channel);
+ release_dma_lock(dma_irq_flags);
+
+ if (residue)
+ retval = -EPIPE;
+
+ return retval ? retval : length;
+}
+
+static ssize_t dma_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer,
+ size_t length)
+{
+ size_t remain = length;
+ size_t transfer_size;
+ ssize_t retval = 0;
+
+ while (remain > 0) {
+ transfer_size = (priv->dma_buffer_length < remain) ?
+ priv->dma_buffer_length : remain;
+ memcpy(priv->dma_buffer, buffer, transfer_size);
+ retval = __dma_write(board, priv, priv->dma_buffer_addr, transfer_size);
+ if (retval < 0)
+ break;
+ remain -= retval;
+ buffer += retval;
+ }
+
+ if (retval < 0)
+ return retval;
+
+ return length - remain;
+}
+#endif
+int nec7210_write(gpib_board_t *board, struct nec7210_priv *priv, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ int retval = 0;
+
+ *bytes_written = 0;
+
+ clear_bit(DEV_CLEAR_BN, &priv->state); //XXX
+
+ if (send_eoi)
+ length-- ; /* save the last byte for sending EOI */
+
+ if (length > 0) {
+ // isa dma transfer
+ if (0 /*priv->dma_channel*/) {
+/*
+ * dma writes are unreliable since they can't recover from bus errors
+ * (which happen when ATN is asserted in the middle of a write)
+ */
+#ifdef NEC_DMA
+ retval = dma_write(board, priv, buffer, length);
+ if (retval < 0)
+ return retval;
+ count += retval;
+#endif
+ } else { // PIO transfer
+ size_t num_bytes;
+
+ retval = pio_write(board, priv, buffer, length, &num_bytes);
+
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ }
+ if (send_eoi) {
+ size_t num_bytes;
+
+ /* We need to wait to make sure we will immediately be able to write the data byte
+ * into the chip before sending the associated AUX_SEOI command. This is really
+ * only needed for length==1 since otherwise the earlier calls to pio_write
+ * will have dont the wait already.
+ */
+ retval = pio_write_wait(board, priv, 0, 0, priv->type == NEC7210);
+ if (retval < 0)
+ return retval;
+ /*send EOI */
+ write_byte(priv, AUX_SEOI, AUXMR);
+
+ retval = pio_write(board, priv, &buffer[*bytes_written], 1, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_write);
+
+/*
+ * interrupt service routine
+ */
+irqreturn_t nec7210_interrupt(gpib_board_t *board, struct nec7210_priv *priv)
+{
+ int status1, status2;
+
+ // read interrupt status (also clears status)
+ status1 = read_byte(priv, ISR1);
+ status2 = read_byte(priv, ISR2);
+
+ return nec7210_interrupt_have_status(board, priv, status1, status2);
+}
+EXPORT_SYMBOL(nec7210_interrupt);
+
+irqreturn_t nec7210_interrupt_have_status(gpib_board_t *board,
+ struct nec7210_priv *priv, int status1, int status2)
+{
+#ifdef NEC_DMA
+ unsigned long dma_flags;
+#endif
+ int retval = IRQ_NONE;
+
+ // record service request in status
+ if (status2 & HR_SRQI)
+ set_bit(SRQI_NUM, &board->status);
+
+ // change in lockout status
+ if (status2 & HR_LOKC) {
+ if (status2 & HR_LOK)
+ set_bit(LOK_NUM, &board->status);
+ else
+ clear_bit(LOK_NUM, &board->status);
+ }
+
+ // change in remote status
+ if (status2 & HR_REMC) {
+ if (status2 & HR_REM)
+ set_bit(REM_NUM, &board->status);
+ else
+ clear_bit(REM_NUM, &board->status);
+ }
+
+ // record reception of END
+ if (status1 & HR_END) {
+ set_bit(RECEIVED_END_BN, &priv->state);
+ if ((priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDE)
+ set_bit(RFD_HOLDOFF_BN, &priv->state);
+ }
+
+ // get incoming data in PIO mode
+ if ((status1 & HR_DI)) {
+ set_bit(READ_READY_BN, &priv->state);
+ if ((priv->auxa_bits & HR_HANDSHAKE_MASK) == HR_HLDA)
+ set_bit(RFD_HOLDOFF_BN, &priv->state);
+ }
+#ifdef NEC_DMA
+ // check for dma read transfer complete
+ if (test_bit(DMA_READ_IN_PROGRESS_BN, &priv->state)) {
+ dma_flags = claim_dma_lock();
+ disable_dma(priv->dma_channel);
+ clear_dma_ff(priv->dma_channel);
+ if ((status1 & HR_END) || get_dma_residue(priv->dma_channel) == 0)
+ clear_bit(DMA_READ_IN_PROGRESS_BN, &priv->state);
+ else
+ enable_dma(priv->dma_channel);
+ release_dma_lock(dma_flags);
+ }
+#endif
+ if ((status1 & HR_DO)) {
+ if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state) == 0)
+ set_bit(WRITE_READY_BN, &priv->state);
+#ifdef NEC_DMA
+ if (test_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state)) { // write data, isa dma mode
+ // check if dma transfer is complete
+ dma_flags = claim_dma_lock();
+ disable_dma(priv->dma_channel);
+ clear_dma_ff(priv->dma_channel);
+ if (get_dma_residue(priv->dma_channel) == 0) {
+ clear_bit(DMA_WRITE_IN_PROGRESS_BN, &priv->state);
+ // XXX race? byte may still be in CDOR reg
+ } else {
+ clear_bit(WRITE_READY_BN, &priv->state);
+ enable_dma(priv->dma_channel);
+ }
+ release_dma_lock(dma_flags);
+ }
+#endif
+ }
+
+ // outgoing command can be sent
+ if (status2 & HR_CO)
+ set_bit(COMMAND_READY_BN, &priv->state);
+
+ // command pass through received
+ if (status1 & HR_CPT) {
+ unsigned int command;
+
+ command = read_byte(priv, CPTR) & gpib_command_mask;
+ write_byte(priv, AUX_NVAL, AUXMR);
+// printk("gpib: command pass through 0x%x\n", command);
+ }
+
+ if (status1 & HR_ERR)
+ set_bit(BUS_ERROR_BN, &priv->state);
+
+ if (status1 & HR_DEC) {
+ unsigned short address_status_bits = read_byte(priv, ADSR);
+
+ // ignore device clear events if we are controller in charge
+ if ((address_status_bits & HR_CIC) == 0) {
+ push_gpib_event(board, EventDevClr);
+ set_bit(DEV_CLEAR_BN, &priv->state);
+ }
+ }
+
+ if (status1 & HR_DET)
+ push_gpib_event(board, EventDevTrg);
+
+ // Addressing status has changed
+ if (status2 & HR_ADSC)
+ set_bit(ADR_CHANGE_BN, &priv->state);
+
+ if ((status1 & priv->reg_bits[IMR1]) ||
+ (status2 & (priv->reg_bits[IMR2] & IMR2_ENABLE_INTR_MASK)) ||
+ nec7210_atn_has_changed(board, priv)) {
+ nec7210_update_status_nolock(board, priv);
+ dev_dbg(board->gpib_dev, "minor %i, stat %lx, isr1 0x%x, imr1 0x%x, isr2 0x%x, imr2 0x%x\n",
+ board->minor, board->status, status1, priv->reg_bits[IMR1], status2,
+ priv->reg_bits[IMR2]);
+ wake_up_interruptible(&board->wait); /* wake up sleeping process */
+ retval = IRQ_HANDLED;
+ }
+
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_interrupt_have_status);
+
+void nec7210_board_reset(struct nec7210_priv *priv, const gpib_board_t *board)
+{
+ /* 7210 chip reset */
+ write_byte(priv, AUX_CR, AUXMR);
+
+ /* disable all interrupts */
+ priv->reg_bits[IMR1] = 0;
+ write_byte(priv, priv->reg_bits[IMR1], IMR1);
+ priv->reg_bits[IMR2] = 0;
+ write_byte(priv, priv->reg_bits[IMR2], IMR2);
+ write_byte(priv, 0, SPMR);
+
+ /* clear registers by reading */
+ read_byte(priv, CPTR);
+ read_byte(priv, ISR1);
+ read_byte(priv, ISR2);
+
+ /* parallel poll unconfigure */
+ write_byte(priv, PPR | HR_PPU, AUXMR);
+
+ priv->reg_bits[ADMR] = HR_TRM0 | HR_TRM1;
+
+ priv->auxa_bits = AUXRA | HR_HLDA;
+ write_byte(priv, priv->auxa_bits, AUXMR);
+
+ write_byte(priv, AUXRE | 0, AUXMR);
+
+ /* set INT pin to active high, enable command pass through of unknown commands */
+ priv->auxb_bits = AUXRB | HR_CPTE;
+ write_byte(priv, priv->auxb_bits, AUXMR);
+ write_byte(priv, AUXRE, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_board_reset);
+
+void nec7210_board_online(struct nec7210_priv *priv, const gpib_board_t *board)
+{
+ /* set GPIB address */
+ nec7210_primary_address(board, priv, board->pad);
+ nec7210_secondary_address(board, priv, board->sad, board->sad >= 0);
+
+ // enable interrupts
+ priv->reg_bits[IMR1] = HR_ERRIE | HR_DECIE | HR_ENDIE |
+ HR_DETIE | HR_CPTIE | HR_DOIE | HR_DIIE;
+ priv->reg_bits[IMR2] = IMR2_ENABLE_INTR_MASK;
+ write_byte(priv, priv->reg_bits[IMR1], IMR1);
+ write_byte(priv, priv->reg_bits[IMR2], IMR2);
+
+ write_byte(priv, AUX_PON, AUXMR);
+}
+EXPORT_SYMBOL(nec7210_board_online);
+
+#ifdef CONFIG_HAS_IOPORT
+/* wrappers for io */
+uint8_t nec7210_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num)
+{
+ return inb((unsigned long)(priv->iobase) + register_num * priv->offset);
+}
+EXPORT_SYMBOL(nec7210_ioport_read_byte);
+
+void nec7210_ioport_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num)
+{
+ if (register_num == AUXMR)
+ /* locking makes absolutely sure noone accesses the
+ * AUXMR register faster than once per microsecond
+ */
+ nec7210_locking_ioport_write_byte(priv, data, register_num);
+ else
+ outb(data, (unsigned long)(priv->iobase) + register_num * priv->offset);
+}
+EXPORT_SYMBOL(nec7210_ioport_write_byte);
+
+/* locking variants of io wrappers, for chips that page-in registers */
+uint8_t nec7210_locking_ioport_read_byte(struct nec7210_priv *priv, unsigned int register_num)
+{
+ u8 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->register_page_lock, flags);
+ retval = inb((unsigned long)(priv->iobase) + register_num * priv->offset);
+ spin_unlock_irqrestore(&priv->register_page_lock, flags);
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_locking_ioport_read_byte);
+
+void nec7210_locking_ioport_write_byte(struct nec7210_priv *priv, uint8_t data,
+ unsigned int register_num)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->register_page_lock, flags);
+ if (register_num == AUXMR)
+ udelay(1);
+ outb(data, (unsigned long)(priv->iobase) + register_num * priv->offset);
+ spin_unlock_irqrestore(&priv->register_page_lock, flags);
+}
+EXPORT_SYMBOL(nec7210_locking_ioport_write_byte);
+#endif
+
+uint8_t nec7210_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num)
+{
+ return readb(priv->iobase + register_num * priv->offset);
+}
+EXPORT_SYMBOL(nec7210_iomem_read_byte);
+
+void nec7210_iomem_write_byte(struct nec7210_priv *priv, uint8_t data, unsigned int register_num)
+{
+ if (register_num == AUXMR)
+ /* locking makes absolutely sure noone accesses the
+ * AUXMR register faster than once per microsecond
+ */
+ nec7210_locking_iomem_write_byte(priv, data, register_num);
+ else
+ writeb(data, priv->iobase + register_num * priv->offset);
+}
+EXPORT_SYMBOL(nec7210_iomem_write_byte);
+
+uint8_t nec7210_locking_iomem_read_byte(struct nec7210_priv *priv, unsigned int register_num)
+{
+ u8 retval;
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->register_page_lock, flags);
+ retval = readb(priv->iobase + register_num * priv->offset);
+ spin_unlock_irqrestore(&priv->register_page_lock, flags);
+ return retval;
+}
+EXPORT_SYMBOL(nec7210_locking_iomem_read_byte);
+
+void nec7210_locking_iomem_write_byte(struct nec7210_priv *priv, uint8_t data,
+ unsigned int register_num)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->register_page_lock, flags);
+ if (register_num == AUXMR)
+ udelay(1);
+ writeb(data, priv->iobase + register_num * priv->offset);
+ spin_unlock_irqrestore(&priv->register_page_lock, flags);
+}
+EXPORT_SYMBOL(nec7210_locking_iomem_write_byte);
+
+static int __init nec7210_init_module(void)
+{
+ return 0;
+}
+
+static void __exit nec7210_exit_module(void)
+{
+}
+
+module_init(nec7210_init_module);
+module_exit(nec7210_exit_module);
diff --git a/drivers/staging/gpib/ni_usb/Makefile b/drivers/staging/gpib/ni_usb/Makefile
new file mode 100644
index 000000000000..e22b3b21a62c
--- /dev/null
+++ b/drivers/staging/gpib/ni_usb/Makefile
@@ -0,0 +1,4 @@
+
+obj-m += ni_usb_gpib.o
+
+
diff --git a/drivers/staging/gpib/ni_usb/ni_usb_gpib.c b/drivers/staging/gpib/ni_usb/ni_usb_gpib.c
new file mode 100644
index 000000000000..b7b6fb1be379
--- /dev/null
+++ b/drivers/staging/gpib/ni_usb/ni_usb_gpib.c
@@ -0,0 +1,2640 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * driver for National Instruments usb to gpib adapters
+ * copyright : (C) 2004 by Frank Mori Hess
+ ***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include "ni_usb_gpib.h"
+#include "gpibP.h"
+#include "nec7210.h"
+#include "tnt4882_registers.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for National Instruments USB devices");
+
+#define MAX_NUM_NI_USB_INTERFACES 128
+static struct usb_interface *ni_usb_driver_interfaces[MAX_NUM_NI_USB_INTERFACES];
+
+static int ni_usb_parse_status_block(const u8 *buffer, struct ni_usb_status_block *status);
+static int ni_usb_set_interrupt_monitor(gpib_board_t *board, unsigned int monitored_bits);
+static void ni_usb_stop(struct ni_usb_priv *ni_priv);
+
+static DEFINE_MUTEX(ni_usb_hotplug_lock);
+
+//calculates a reasonable timeout in that can be passed to usb functions
+static inline unsigned long ni_usb_timeout_msecs(unsigned int usec)
+{
+ if (usec == 0)
+ return 0;
+ return 2000 + usec / 500;
+};
+
+// returns timeout code byte for use in ni-usb-b instructions
+static unsigned short ni_usb_timeout_code(unsigned int usec)
+{
+ if (usec == 0)
+ return 0xf0;
+ else if (usec <= 10)
+ return 0xf1;
+ else if (usec <= 30)
+ return 0xf2;
+ else if (usec <= 100)
+ return 0xf3;
+ else if (usec <= 300)
+ return 0xf4;
+ else if (usec <= 1000)
+ return 0xf5;
+ else if (usec <= 3000)
+ return 0xf6;
+ else if (usec <= 10000)
+ return 0xf7;
+ else if (usec <= 30000)
+ return 0xf8;
+ else if (usec <= 100000)
+ return 0xf9;
+ else if (usec <= 300000)
+ return 0xfa;
+ else if (usec <= 1000000)
+ return 0xfb;
+ else if (usec <= 3000000)
+ return 0xfc;
+ else if (usec <= 10000000)
+ return 0xfd;
+ else if (usec <= 30000000)
+ return 0xfe;
+ else if (usec <= 100000000)
+ return 0xff;
+ else if (usec <= 300000000)
+ return 0x01;
+ /* NI driver actually uses 0xff for timeout T1000s, which is a bug in their code.
+ * I've verified on a usb-b that a code of 0x2 is correct for a 1000 sec timeout
+ */
+ else if (usec <= 1000000000)
+ return 0x02;
+ pr_err("%s: bug? usec is greater than 1e9\n", __func__);
+ return 0xf0;
+}
+
+static void ni_usb_bulk_complete(struct urb *urb)
+{
+ struct ni_usb_urb_ctx *context = urb->context;
+
+// printk("debug: %s: status=0x%x, error_count=%i, actual_length=%i\n", __func__,
+// urb->status, urb->error_count, urb->actual_length);
+ up(&context->complete);
+}
+
+static void ni_usb_timeout_handler(struct timer_list *t)
+{
+ struct ni_usb_priv *ni_priv = from_timer(ni_priv, t, bulk_timer);
+ struct ni_usb_urb_ctx *context = &ni_priv->context;
+
+ context->timed_out = 1;
+ up(&context->complete);
+};
+
+// I'm using nonblocking loosely here, it only means -EAGAIN can be returned in certain cases
+static int ni_usb_nonblocking_send_bulk_msg(struct ni_usb_priv *ni_priv, void *data,
+ int data_length, int *actual_data_length,
+ int timeout_msecs)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int out_pipe;
+ struct ni_usb_urb_ctx *context = &ni_priv->context;
+
+ *actual_data_length = 0;
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ if (!ni_priv->bus_interface) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -ENODEV;
+ }
+ if (ni_priv->bulk_urb) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -EAGAIN;
+ }
+ ni_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ni_priv->bulk_urb) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+ usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ out_pipe = usb_sndbulkpipe(usb_dev, ni_priv->bulk_out_endpoint);
+ sema_init(&context->complete, 0);
+ context->timed_out = 0;
+ usb_fill_bulk_urb(ni_priv->bulk_urb, usb_dev, out_pipe, data, data_length,
+ &ni_usb_bulk_complete, context);
+
+ if (timeout_msecs)
+ mod_timer(&ni_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs));
+
+ retval = usb_submit_urb(ni_priv->bulk_urb, GFP_KERNEL);
+ if (retval) {
+ del_timer_sync(&ni_priv->bulk_timer);
+ usb_free_urb(ni_priv->bulk_urb);
+ ni_priv->bulk_urb = NULL;
+ dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return retval;
+ }
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ down(&context->complete); // wait for ni_usb_bulk_complete
+ if (context->timed_out) {
+ usb_kill_urb(ni_priv->bulk_urb);
+ dev_err(&usb_dev->dev, "%s: killed urb due to timeout\n", __func__);
+ retval = -ETIMEDOUT;
+ } else {
+ retval = ni_priv->bulk_urb->status;
+ }
+
+ del_timer_sync(&ni_priv->bulk_timer);
+ *actual_data_length = ni_priv->bulk_urb->actual_length;
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ usb_free_urb(ni_priv->bulk_urb);
+ ni_priv->bulk_urb = NULL;
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return retval;
+}
+
+static int ni_usb_send_bulk_msg(struct ni_usb_priv *ni_priv, void *data, int data_length,
+ int *actual_data_length, int timeout_msecs)
+{
+ int retval;
+ int timeout_msecs_remaining = timeout_msecs;
+
+ retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, data, data_length, actual_data_length,
+ timeout_msecs_remaining);
+ while (retval == -EAGAIN && (timeout_msecs == 0 || timeout_msecs_remaining > 0)) {
+ usleep_range(1000, 1500);
+ retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, data, data_length,
+ actual_data_length,
+ timeout_msecs_remaining);
+ if (timeout_msecs != 0)
+ --timeout_msecs_remaining;
+ }
+ if (timeout_msecs != 0 && timeout_msecs_remaining <= 0)
+ return -ETIMEDOUT;
+ return retval;
+}
+
+// I'm using nonblocking loosely here, it only means -EAGAIN can be returned in certain cases
+static int ni_usb_nonblocking_receive_bulk_msg(struct ni_usb_priv *ni_priv,
+ void *data, int data_length,
+ int *actual_data_length, int timeout_msecs,
+ int interruptible)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int in_pipe;
+ struct ni_usb_urb_ctx *context = &ni_priv->context;
+
+ *actual_data_length = 0;
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ if (!ni_priv->bus_interface) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -ENODEV;
+ }
+ if (ni_priv->bulk_urb) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -EAGAIN;
+ }
+ ni_priv->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ni_priv->bulk_urb) {
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return -ENOMEM;
+ }
+ usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ in_pipe = usb_rcvbulkpipe(usb_dev, ni_priv->bulk_in_endpoint);
+ sema_init(&context->complete, 0);
+ context->timed_out = 0;
+ usb_fill_bulk_urb(ni_priv->bulk_urb, usb_dev, in_pipe, data, data_length,
+ &ni_usb_bulk_complete, context);
+
+ if (timeout_msecs)
+ mod_timer(&ni_priv->bulk_timer, jiffies + msecs_to_jiffies(timeout_msecs));
+
+ //printk("%s: submitting urb\n", __func__);
+ retval = usb_submit_urb(ni_priv->bulk_urb, GFP_KERNEL);
+ if (retval) {
+ del_timer_sync(&ni_priv->bulk_timer);
+ usb_free_urb(ni_priv->bulk_urb);
+ ni_priv->bulk_urb = NULL;
+ dev_err(&usb_dev->dev, "%s: failed to submit bulk out urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return retval;
+ }
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ if (interruptible) {
+ if (down_interruptible(&context->complete)) {
+ /* If we got interrupted by a signal while
+ * waiting for the usb gpib to respond, we
+ * should send a stop command so it will
+ * finish up with whatever it was doing and
+ * send its response now.
+ */
+ ni_usb_stop(ni_priv);
+ retval = -ERESTARTSYS;
+ /* now do an uninterruptible wait, it shouldn't take long
+ * for the board to respond now.
+ */
+ down(&context->complete);
+ }
+ } else {
+ down(&context->complete);
+ }
+ if (context->timed_out) {
+ usb_kill_urb(ni_priv->bulk_urb);
+ dev_err(&usb_dev->dev, "%s: killed urb due to timeout\n", __func__);
+ retval = -ETIMEDOUT;
+ } else {
+ if (ni_priv->bulk_urb->status)
+ retval = ni_priv->bulk_urb->status;
+ }
+ del_timer_sync(&ni_priv->bulk_timer);
+ *actual_data_length = ni_priv->bulk_urb->actual_length;
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ usb_free_urb(ni_priv->bulk_urb);
+ ni_priv->bulk_urb = NULL;
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ return retval;
+}
+
+static int ni_usb_receive_bulk_msg(struct ni_usb_priv *ni_priv, void *data,
+ int data_length, int *actual_data_length, int timeout_msecs,
+ int interruptible)
+{
+ int retval;
+ int timeout_msecs_remaining = timeout_msecs;
+
+ retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, data, data_length,
+ actual_data_length, timeout_msecs_remaining,
+ interruptible);
+ while (retval == -EAGAIN && (timeout_msecs == 0 || timeout_msecs_remaining > 0)) {
+ usleep_range(1000, 1500);
+ retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, data, data_length,
+ actual_data_length,
+ timeout_msecs_remaining,
+ interruptible);
+ if (timeout_msecs != 0)
+ --timeout_msecs_remaining;
+ }
+ if (timeout_msecs && timeout_msecs_remaining <= 0)
+ return -ETIMEDOUT;
+ return retval;
+}
+
+static int ni_usb_receive_control_msg(struct ni_usb_priv *ni_priv, __u8 request,
+ __u8 requesttype, __u16 value, __u16 index,
+ void *data, __u16 size, int timeout_msecs)
+{
+ struct usb_device *usb_dev;
+ int retval;
+ unsigned int in_pipe;
+
+ mutex_lock(&ni_priv->control_transfer_lock);
+ if (!ni_priv->bus_interface) {
+ mutex_unlock(&ni_priv->control_transfer_lock);
+ return -ENODEV;
+ }
+ usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ in_pipe = usb_rcvctrlpipe(usb_dev, 0);
+ retval = usb_control_msg(usb_dev, in_pipe, request, requesttype, value, index, data,
+ size, timeout_msecs);
+ mutex_unlock(&ni_priv->control_transfer_lock);
+ return retval;
+}
+
+static void ni_usb_soft_update_status(gpib_board_t *board, unsigned int ni_usb_ibsta,
+ unsigned int clear_mask)
+{
+ static const unsigned int ni_usb_ibsta_mask = SRQI | ATN | CIC | REM | LACS | TACS | LOK;
+
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ unsigned int need_monitoring_bits = ni_usb_ibsta_monitor_mask;
+ unsigned long flags;
+
+ board->status &= ~clear_mask;
+ board->status &= ~ni_usb_ibsta_mask;
+ board->status |= ni_usb_ibsta & ni_usb_ibsta_mask;
+ //FIXME should generate events on DTAS and DCAS
+
+ spin_lock_irqsave(&board->spinlock, flags);
+/* remove set status bits from monitored set why ?***/
+ ni_priv->monitored_ibsta_bits &= ~ni_usb_ibsta;
+ need_monitoring_bits &= ~ni_priv->monitored_ibsta_bits; /* mm - monitored set */
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ dev_dbg(&usb_dev->dev, "%s: need_monitoring_bits=0x%x\n", __func__, need_monitoring_bits);
+
+ if (need_monitoring_bits & ~ni_usb_ibsta)
+ ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask);
+ else if (need_monitoring_bits & ni_usb_ibsta)
+ wake_up_interruptible(&board->wait);
+
+ dev_dbg(&usb_dev->dev, "%s: ni_usb_ibsta=0x%x\n", __func__, ni_usb_ibsta);
+}
+
+static int ni_usb_parse_status_block(const u8 *buffer, struct ni_usb_status_block *status)
+{
+ u16 count;
+
+ status->id = buffer[0];
+ status->ibsta = (buffer[1] << 8) | buffer[2];
+ status->error_code = buffer[3];
+ count = buffer[4] | (buffer[5] << 8);
+ count = ~count;
+ count++;
+ status->count = count;
+ return 8;
+};
+
+static void ni_usb_dump_raw_block(const u8 *raw_data, int length)
+{
+ print_hex_dump(KERN_INFO, "", DUMP_PREFIX_NONE, 8, 1, raw_data, length, true);
+}
+
+static int ni_usb_parse_register_read_block(const u8 *raw_data, unsigned int *results,
+ int num_results)
+{
+ int i = 0;
+ int j;
+ int unexpected = 0;
+ static const int results_per_chunk = 3;
+
+ for (j = 0; j < num_results;) {
+ int k;
+
+ if (raw_data[i++] != NIUSB_REGISTER_READ_DATA_START_ID) {
+ pr_err("%s: parse error: wrong start id\n", __func__);
+ unexpected = 1;
+ }
+ for (k = 0; k < results_per_chunk && j < num_results; ++k)
+ results[j++] = raw_data[i++];
+ }
+ while (i % 4)
+ i++;
+ if (raw_data[i++] != NIUSB_REGISTER_READ_DATA_END_ID) {
+ pr_err("%s: parse error: wrong end id\n", __func__);
+ unexpected = 1;
+ }
+ if (raw_data[i++] % results_per_chunk != num_results % results_per_chunk) {
+ pr_err("%s: parse error: wrong count=%i for NIUSB_REGISTER_READ_DATA_END\n",
+ __func__, (int)raw_data[i - 1]);
+ unexpected = 1;
+ }
+ while (i % 4) {
+ if (raw_data[i++] != 0) {
+ pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n",
+ __func__, i - 1, (int)raw_data[i - 1]);
+ unexpected = 1;
+ }
+ }
+ if (unexpected)
+ ni_usb_dump_raw_block(raw_data, i);
+ return i;
+}
+
+static int ni_usb_parse_termination_block(const u8 *buffer)
+{
+ int i = 0;
+
+ if (buffer[i++] != NIUSB_TERM_ID ||
+ buffer[i++] != 0x0 ||
+ buffer[i++] != 0x0 ||
+ buffer[i++] != 0x0) {
+ pr_err("%s: received unexpected termination block\n", __func__);
+ pr_err(" expected: 0x%x 0x%x 0x%x 0x%x\n",
+ NIUSB_TERM_ID, 0x0, 0x0, 0x0);
+ pr_err(" received: 0x%x 0x%x 0x%x 0x%x\n",
+ buffer[i - 4], buffer[i - 3], buffer[i - 2], buffer[i - 1]);
+ }
+ return i;
+};
+
+static int parse_board_ibrd_readback(const u8 *raw_data, struct ni_usb_status_block *status,
+ u8 *parsed_data, int parsed_data_length,
+ int *actual_bytes_read)
+{
+ static const int ibrd_data_block_length = 0xf;
+ static const int ibrd_extended_data_block_length = 0x1e;
+ int data_block_length = 0;
+ int i = 0;
+ int j = 0;
+ int k;
+ unsigned int adr1_bits;
+ int num_data_blocks = 0;
+ struct ni_usb_status_block register_write_status;
+ int unexpected = 0;
+
+ while (raw_data[i] == NIUSB_IBRD_DATA_ID || raw_data[i] == NIUSB_IBRD_EXTENDED_DATA_ID) {
+ if (raw_data[i] == NIUSB_IBRD_DATA_ID) {
+ data_block_length = ibrd_data_block_length;
+ } else if (raw_data[i] == NIUSB_IBRD_EXTENDED_DATA_ID) {
+ data_block_length = ibrd_extended_data_block_length;
+ if (raw_data[++i] != 0) {
+ pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n",
+ __func__, i, (int)raw_data[i]);
+ unexpected = 1;
+ }
+ } else {
+ pr_err("%s: logic bug!\n", __func__);
+ return -EINVAL;
+ }
+ ++i;
+ for (k = 0; k < data_block_length; k++) {
+ if (j < parsed_data_length)
+ parsed_data[j++] = raw_data[i++];
+ else
+ ++i;
+ }
+ ++num_data_blocks;
+ }
+ i += ni_usb_parse_status_block(&raw_data[i], status);
+ if (status->id != NIUSB_IBRD_STATUS_ID) {
+ pr_err("%s: bug: status->id=%i, != ibrd_status_id\n", __func__, status->id);
+ return -EIO;
+ }
+ adr1_bits = raw_data[i++];
+ if (num_data_blocks) {
+ *actual_bytes_read = (num_data_blocks - 1) * data_block_length + raw_data[i++];
+ } else {
+ ++i;
+ *actual_bytes_read = 0;
+ }
+ if (*actual_bytes_read > j)
+ pr_err("%s: bug: discarded data. actual_bytes_read=%i, j=%i\n",
+ __func__, *actual_bytes_read, j);
+ for (k = 0; k < 2; k++)
+ if (raw_data[i++] != 0) {
+ pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n",
+ __func__, i - 1, (int)raw_data[i - 1]);
+ unexpected = 1;
+ }
+ i += ni_usb_parse_status_block(&raw_data[i], &register_write_status);
+ if (register_write_status.id != NIUSB_REG_WRITE_ID) {
+ pr_err("%s: unexpected data: register write status id=0x%x, expected 0x%x\n",
+ __func__, register_write_status.id, NIUSB_REG_WRITE_ID);
+ unexpected = 1;
+ }
+ if (raw_data[i++] != 2) {
+ pr_err("%s: unexpected data: register write count=%i, expected 2\n",
+ __func__, (int)raw_data[i - 1]);
+ unexpected = 1;
+ }
+ for (k = 0; k < 3; k++)
+ if (raw_data[i++] != 0) {
+ pr_err("%s: unexpected data: raw_data[%i]=0x%x, expected 0\n",
+ __func__, i - 1, (int)raw_data[i - 1]);
+ unexpected = 1;
+ }
+ i += ni_usb_parse_termination_block(&raw_data[i]);
+ if (unexpected)
+ ni_usb_dump_raw_block(raw_data, i);
+ return i;
+}
+
+static int ni_usb_parse_reg_write_status_block(const u8 *raw_data,
+ struct ni_usb_status_block *status,
+ int *writes_completed)
+{
+ int i = 0;
+
+ i += ni_usb_parse_status_block(raw_data, status);
+ *writes_completed = raw_data[i++];
+ while (i % 4)
+ i++;
+ return i;
+}
+
+static int ni_usb_write_registers(struct ni_usb_priv *ni_priv,
+ const struct ni_usb_register *writes, int num_writes,
+ unsigned int *ibsta)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ u8 *out_data, *in_data;
+ int out_data_length;
+ static const int in_data_length = 0x20;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ int j;
+ struct ni_usb_status_block status;
+ static const int bytes_per_write = 3;
+ int reg_writes_completed;
+
+ out_data_length = num_writes * bytes_per_write + 0x10;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data) {
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ i += ni_usb_bulk_register_write_header(&out_data[i], num_writes);
+ for (j = 0; j < num_writes; j++)
+ i += ni_usb_bulk_register_write(&out_data[i], writes[j]);
+ while (i % 4)
+ out_data[i++] = 0x00;
+ i += ni_usb_bulk_termination(&out_data[i]);
+ if (i > out_data_length)
+ dev_err(&usb_dev->dev, "%s: bug! buffer overrun\n", __func__);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0);
+ if (retval || bytes_read != 16) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ ni_usb_dump_raw_block(in_data, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ ni_usb_parse_reg_write_status_block(in_data, &status, &reg_writes_completed);
+ //FIXME parse extra 09 status bits and termination
+ kfree(in_data);
+ if (status.id != NIUSB_REG_WRITE_ID) {
+ dev_err(&usb_dev->dev, "%s: parse error, id=0x%x != NIUSB_REG_WRITE_ID\n",
+ __func__, status.id);
+ return -EIO;
+ }
+ if (status.error_code) {
+ dev_err(&usb_dev->dev, "%s: nonzero error code 0x%x\n",
+ __func__, status.error_code);
+ return -EIO;
+ }
+ if (reg_writes_completed != num_writes) {
+ dev_err(&usb_dev->dev, "%s: reg_writes_completed=%i, num_writes=%i\n",
+ __func__, reg_writes_completed, num_writes);
+ return -EIO;
+ }
+ if (ibsta)
+ *ibsta = status.ibsta;
+ return 0;
+}
+
+// interface functions
+static int ni_usb_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read)
+{
+ int retval, parse_retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x20;
+ int in_data_length;
+ int usb_bytes_written = 0, usb_bytes_read = 0;
+ int i = 0;
+ int complement_count;
+ int actual_length;
+ struct ni_usb_status_block status;
+ static const int max_read_length = 0xffff;
+ struct ni_usb_register reg;
+
+ *bytes_read = 0;
+ if (length > max_read_length) {
+ length = max_read_length;
+ dev_err(&usb_dev->dev, "%s: read length too long\n", __func__);
+ }
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = 0x0a;
+ out_data[i++] = ni_priv->eos_mode >> 8;
+ out_data[i++] = ni_priv->eos_char;
+ out_data[i++] = ni_usb_timeout_code(board->usec_timeout);
+ complement_count = length - 1;
+ complement_count = ~complement_count;
+ out_data[i++] = complement_count & 0xff;
+ out_data[i++] = (complement_count >> 8) & 0xff;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_register_write_header(&out_data[i], 2);
+ reg.device = NIUSB_SUBDEV_TNT4882;
+ reg.address = nec7210_to_tnt4882_offset(AUXMR);
+ reg.value = AUX_HLDI;
+ i += ni_usb_bulk_register_write(&out_data[i], reg);
+ reg.value = AUX_CLEAR_END;
+ i += ni_usb_bulk_register_write(&out_data[i], reg);
+ while (i % 4) // pad with zeros to 4-byte boundary
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &usb_bytes_written, 1000);
+ kfree(out_data);
+ if (retval || usb_bytes_written != i) {
+ if (retval == 0)
+ retval = -EIO;
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n",
+ __func__, retval, usb_bytes_written, i);
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ return retval;
+ }
+
+ in_data_length = (length / 30 + 1) * 0x20 + 0x20;
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ return -ENOMEM;
+ }
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &usb_bytes_read,
+ ni_usb_timeout_msecs(board->usec_timeout), 1);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if (retval == -ERESTARTSYS) {
+ } else if (retval) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, usb_bytes_read=%i\n",
+ __func__, retval, usb_bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ parse_retval = parse_board_ibrd_readback(in_data, &status, buffer, length, &actual_length);
+ if (parse_retval != usb_bytes_read) {
+ if (parse_retval >= 0)
+ parse_retval = -EIO;
+ dev_err(&usb_dev->dev, "%s: retval=%i usb_bytes_read=%i\n",
+ __func__, parse_retval, usb_bytes_read);
+ kfree(in_data);
+ return parse_retval;
+ }
+ if (actual_length != length - status.count) {
+ dev_err(&usb_dev->dev, "%s: actual_length=%i expected=%li\n",
+ __func__, actual_length, (long)(length - status.count));
+ ni_usb_dump_raw_block(in_data, usb_bytes_read);
+ }
+ kfree(in_data);
+ switch (status.error_code) {
+ case NIUSB_NO_ERROR:
+ retval = 0;
+ break;
+ case NIUSB_ABORTED_ERROR:
+ /* this is expected if ni_usb_receive_bulk_msg got
+ * interrupted by a signal and returned -ERESTARTSYS
+ */
+ break;
+ case NIUSB_ATN_STATE_ERROR:
+ retval = -EIO;
+ dev_err(&usb_dev->dev, "%s: read when ATN set\n", __func__);
+ break;
+ case NIUSB_ADDRESSING_ERROR:
+ retval = -EIO;
+ break;
+ case NIUSB_TIMEOUT_ERROR:
+ retval = -ETIMEDOUT;
+ break;
+ case NIUSB_EOSMODE_ERROR:
+ dev_err(&usb_dev->dev, "%s: driver bug, we should have been able to avoid NIUSB_EOSMODE_ERROR.\n",
+ __func__);
+ retval = -EINVAL;
+ break;
+ default:
+ dev_err(&usb_dev->dev, "%s: unknown error code=%i\n", __func__, status.error_code);
+ retval = -EIO;
+ break;
+ }
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ if (status.ibsta & END)
+ *end = 1;
+ else
+ *end = 0;
+ *bytes_read = actual_length;
+ return retval;
+}
+
+static int ni_usb_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ int out_data_length;
+ static const int in_data_length = 0x10;
+ int usb_bytes_written = 0, usb_bytes_read = 0;
+ int i = 0, j;
+ int complement_count;
+ struct ni_usb_status_block status;
+ static const int max_write_length = 0xffff;
+
+ *bytes_written = 0;
+ if (length > max_write_length) {
+ length = max_write_length;
+ send_eoi = 0;
+ dev_err(&usb_dev->dev, "%s: write length too long\n", __func__);
+ }
+ out_data_length = length + 0x10;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = 0x0d;
+ complement_count = length - 1;
+ complement_count = ~complement_count;
+ out_data[i++] = complement_count & 0xff;
+ out_data[i++] = (complement_count >> 8) & 0xff;
+ out_data[i++] = ni_usb_timeout_code(board->usec_timeout);
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ if (send_eoi)
+ out_data[i++] = 0x8;
+ else
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ for (j = 0; j < length; j++)
+ out_data[i++] = buffer[j];
+ while (i % 4) // pad with zeros to 4-byte boundary
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &usb_bytes_written,
+ ni_usb_timeout_msecs(board->usec_timeout));
+ kfree(out_data);
+ if (retval || usb_bytes_written != i) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, usb_bytes_written=%i, i=%i\n",
+ __func__, retval, usb_bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data)
+ return -ENOMEM;
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &usb_bytes_read,
+ ni_usb_timeout_msecs(board->usec_timeout), 1);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if ((retval && retval != -ERESTARTSYS) || usb_bytes_read != 12) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, usb_bytes_read=%i\n",
+ __func__, retval, usb_bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ ni_usb_parse_status_block(in_data, &status);
+ kfree(in_data);
+ switch (status.error_code) {
+ case NIUSB_NO_ERROR:
+ retval = 0;
+ break;
+ case NIUSB_ABORTED_ERROR:
+ /* this is expected if ni_usb_receive_bulk_msg got
+ * interrupted by a signal and returned -ERESTARTSYS
+ */
+ break;
+ case NIUSB_ADDRESSING_ERROR:
+ dev_err(&usb_dev->dev, "%s: Addressing error retval %d error code=%i\n",
+ __func__, retval, status.error_code);
+ retval = -ENXIO;
+ break;
+ case NIUSB_NO_LISTENER_ERROR:
+ retval = -ECOMM;
+ break;
+ case NIUSB_TIMEOUT_ERROR:
+ retval = -ETIMEDOUT;
+ break;
+ default:
+ dev_err(&usb_dev->dev, "%s: unknown error code=%i\n",
+ __func__, status.error_code);
+ retval = -EPIPE;
+ break;
+ }
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ *bytes_written = length - status.count;
+ return retval;
+}
+
+static int ni_usb_command_chunk(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *command_bytes_written)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ int out_data_length;
+ static const int in_data_length = 0x10;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0, j;
+ unsigned int complement_count;
+ struct ni_usb_status_block status;
+ // usb-b gives error 4 if you try to send more than 16 command bytes at once
+ static const int max_command_length = 0x10;
+
+ *command_bytes_written = 0;
+ if (length > max_command_length)
+ length = max_command_length;
+ out_data_length = length + 0x10;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = 0x0c;
+ complement_count = length - 1;
+ complement_count = ~complement_count;
+ out_data[i++] = complement_count;
+ out_data[i++] = 0x0;
+ out_data[i++] = ni_usb_timeout_code(board->usec_timeout);
+ for (j = 0; j < length; j++)
+ out_data[i++] = buffer[j];
+ while (i % 4) // pad with zeros to 4-byte boundary
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written,
+ ni_usb_timeout_msecs(board->usec_timeout));
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ return -ENOMEM;
+ }
+
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read,
+ ni_usb_timeout_msecs(board->usec_timeout), 1);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if ((retval && retval != -ERESTARTSYS) || bytes_read != 12) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ ni_usb_parse_status_block(in_data, &status);
+ kfree(in_data);
+ *command_bytes_written = length - status.count;
+ switch (status.error_code) {
+ case NIUSB_NO_ERROR:
+ break;
+ case NIUSB_ABORTED_ERROR:
+ /* this is expected if ni_usb_receive_bulk_msg got
+ * interrupted by a signal and returned -ERESTARTSYS
+ */
+ break;
+ case NIUSB_NO_BUS_ERROR:
+ return -ENOTCONN;
+ case NIUSB_EOSMODE_ERROR:
+ dev_err(&usb_dev->dev, "%s: got eosmode error. Driver bug?\n", __func__);
+ return -EIO;
+ case NIUSB_TIMEOUT_ERROR:
+ return -ETIMEDOUT;
+ default:
+ dev_err(&usb_dev->dev, "%s: unknown error code=%i\n", __func__, status.error_code);
+ return -EIO;
+ }
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ return 0;
+}
+
+static int ni_usb_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written)
+{
+ size_t count;
+ int retval;
+
+ *bytes_written = 0;
+ while (*bytes_written < length) {
+ retval = ni_usb_command_chunk(board, buffer + *bytes_written,
+ length - *bytes_written, &count);
+ *bytes_written += count;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+
+static int ni_usb_take_control(gpib_board_t *board, int synchronous)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x10;
+ static const int in_data_length = 0x10;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ struct ni_usb_status_block status;
+
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+ out_data[i++] = NIUSB_IBCAC_ID;
+ if (synchronous)
+ out_data[i++] = 0x1;
+ else
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 1);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if ((retval && retval != -ERESTARTSYS) || bytes_read != 12) {
+ if (retval == 0)
+ retval = -EIO;
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ ni_usb_parse_status_block(in_data, &status);
+ kfree(in_data);
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ return retval;
+}
+
+static int ni_usb_go_to_standby(gpib_board_t *board)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x10;
+ static const int in_data_length = 0x20;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ struct ni_usb_status_block status;
+
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+
+ out_data[i++] = NIUSB_IBGTS_ID;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+
+ mutex_lock(&ni_priv->addressed_transfer_lock);
+
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if (retval || bytes_read != 12) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ ni_usb_parse_status_block(in_data, &status);
+ kfree(in_data);
+ if (status.id != NIUSB_IBGTS_ID)
+ dev_err(&usb_dev->dev, "%s: bug: status.id 0x%x != INUSB_IBGTS_ID\n",
+ __func__, status.id);
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ return 0;
+}
+
+static void ni_usb_request_system_control(gpib_board_t *board, int request_control)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[4];
+ unsigned int ibsta;
+
+ if (request_control) {
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = CMDR;
+ writes[i].value = SETSC;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CIFC;
+ i++;
+ } else {
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CREN;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CIFC;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_DSC;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = CMDR;
+ writes[i].value = CLRSC;
+ i++;
+ }
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return; // retval;
+ }
+ if (!request_control)
+ ni_priv->ren_state = 0;
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return; // 0;
+}
+
+//FIXME maybe the interface should have a "pulse interface clear" function that can return an error?
+static void ni_usb_interface_clear(gpib_board_t *board, int assert)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x10;
+ static const int in_data_length = 0x10;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ struct ni_usb_status_block status;
+
+ // FIXME: we are going to pulse when assert is true, and ignore otherwise
+ if (assert == 0)
+ return;
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data) {
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return;
+ }
+ out_data[i++] = NIUSB_IBSIC_ID;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return;
+ }
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data)
+ return;
+
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0);
+ if (retval || bytes_read != 12) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return;
+ }
+ ni_usb_parse_status_block(in_data, &status);
+ kfree(in_data);
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+}
+
+static void ni_usb_remote_enable(gpib_board_t *board, int enable)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ struct ni_usb_register reg;
+ unsigned int ibsta;
+
+ reg.device = NIUSB_SUBDEV_TNT4882;
+ reg.address = nec7210_to_tnt4882_offset(AUXMR);
+ if (enable)
+ reg.value = AUX_SREN;
+ else
+ reg.value = AUX_CREN;
+ retval = ni_usb_write_registers(ni_priv, &reg, 1, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return; //retval;
+ }
+ ni_priv->ren_state = enable;
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return;// 0;
+}
+
+static int ni_usb_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct ni_usb_priv *ni_priv = board->private_data;
+
+ ni_priv->eos_char = eos_byte;
+ ni_priv->eos_mode |= REOS;
+ if (compare_8_bits)
+ ni_priv->eos_mode |= BIN;
+ else
+ ni_priv->eos_mode &= ~BIN;
+ return 0;
+}
+
+static void ni_usb_disable_eos(gpib_board_t *board)
+{
+ struct ni_usb_priv *ni_priv = board->private_data;
+ /* adapter gets unhappy if you don't zero all the bits
+ * for the eos mode and eos char (returns error 4 on reads).
+ */
+ ni_priv->eos_mode = 0;
+ ni_priv->eos_char = 0;
+}
+
+static unsigned int ni_usb_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ static const int buffer_length = 8;
+ u8 *buffer;
+ struct ni_usb_status_block status;
+
+ //printk("%s: receive control pipe is %i\n", __func__, pipe);
+ buffer = kmalloc(buffer_length, GFP_KERNEL);
+ if (!buffer)
+ return board->status;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_WAIT_REQUEST, USB_DIR_IN |
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x200, 0x0, buffer, buffer_length, 1000);
+ if (retval != buffer_length) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval);
+ kfree(buffer);
+ return board->status;
+ }
+ ni_usb_parse_status_block(buffer, &status);
+ kfree(buffer);
+ ni_usb_soft_update_status(board, status.ibsta, clear_mask);
+ return board->status;
+}
+
+// tells ni-usb to immediately stop an ongoing i/o operation
+static void ni_usb_stop(struct ni_usb_priv *ni_priv)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ static const int buffer_length = 8;
+ u8 *buffer;
+ struct ni_usb_status_block status;
+
+ //printk("%s: receive control pipe is %i\n", __func__, pipe);
+ buffer = kmalloc(buffer_length, GFP_KERNEL);
+ if (!buffer)
+ return;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_STOP_REQUEST, USB_DIR_IN |
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0, 0x0, buffer, buffer_length, 1000);
+ if (retval != buffer_length) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval);
+ kfree(buffer);
+ return;
+ }
+ ni_usb_parse_status_block(buffer, &status);
+ kfree(buffer);
+}
+
+static int ni_usb_primary_address(gpib_board_t *board, unsigned int address)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[2];
+ unsigned int ibsta;
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(ADR);
+ writes[i].value = address;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN2;
+ writes[i].address = 0x0;
+ writes[i].value = address;
+ i++;
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return 0;
+}
+
+static int ni_usb_write_sad(struct ni_usb_register *writes, int address, int enable)
+{
+ unsigned int adr_bits, admr_bits;
+ int i = 0;
+
+ adr_bits = HR_ARS;
+ admr_bits = HR_TRM0 | HR_TRM1;
+ if (enable) {
+ adr_bits |= address;
+ admr_bits |= HR_ADM1;
+ } else {
+ adr_bits |= HR_DT | HR_DL;
+ admr_bits |= HR_ADM0;
+ }
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(ADR);
+ writes[i].value = adr_bits;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(ADMR);
+ writes[i].value = admr_bits;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN2;
+ writes[i].address = 0x1;
+ writes[i].value = enable ? MSA(address) : 0x0;
+ i++;
+ return i;
+}
+
+static int ni_usb_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[3];
+ unsigned int ibsta;
+
+ i += ni_usb_write_sad(writes, address, enable);
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return 0;
+}
+
+static int ni_usb_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x10;
+ static const int in_data_length = 0x20;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ int j = 0;
+ struct ni_usb_status_block status;
+
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+
+ out_data[i++] = NIUSB_IBRPP_ID;
+ out_data[i++] = 0xf0; //FIXME: this should be the parallel poll timeout code
+ out_data[i++] = 0x0;
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+ /*FIXME: 1000 should use parallel poll timeout (not supported yet)*/
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data)
+ return -ENOMEM;
+
+ /*FIXME: should use parallel poll timeout (not supported yet)*/
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length,
+ &bytes_read, 1000, 1);
+
+ if (retval && retval != -ERESTARTSYS) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+ j += ni_usb_parse_status_block(in_data, &status);
+ *result = in_data[j++];
+ kfree(in_data);
+ ni_usb_soft_update_status(board, status.ibsta, 0);
+ return retval;
+}
+
+static void ni_usb_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[1];
+ unsigned int ibsta;
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = PPR | config;
+ i++;
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return;// retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return;// 0;
+}
+
+static void ni_usb_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[1];
+ unsigned int ibsta;
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ if (ist)
+ writes[i].value = AUX_SPPF;
+ else
+ writes[i].value = AUX_CPPF;
+ i++;
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return;// retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return;// 0;
+}
+
+static void ni_usb_serial_poll_response(gpib_board_t *board, u8 status)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[1];
+ unsigned int ibsta;
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(SPMR);
+ writes[i].value = status;
+ i++;
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return;// retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return;// 0;
+}
+
+static uint8_t ni_usb_serial_poll_status(gpib_board_t *board)
+{
+ return 0;
+}
+
+static void ni_usb_return_to_local(gpib_board_t *board)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int i = 0;
+ struct ni_usb_register writes[1];
+ unsigned int ibsta;
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_RTL;
+ i++;
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return;// retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return;// 0;
+}
+
+static int ni_usb_line_status(const gpib_board_t *board)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ u8 *out_data, *in_data;
+ static const int out_data_length = 0x20;
+ static const int in_data_length = 0x20;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ unsigned int bsr_bits;
+ int line_status = ValidALL;
+ // NI windows driver reads 0xd(HSSEL), 0xc (ARD0), 0x1f (BSR)
+
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data)
+ return -ENOMEM;
+
+ /* line status gets called during ibwait */
+ retval = mutex_trylock(&ni_priv->addressed_transfer_lock);
+
+ if (retval == 0) {
+ kfree(out_data);
+ return -EBUSY;
+ }
+ i += ni_usb_bulk_register_read_header(&out_data[i], 1);
+ i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_TNT4882, BSR);
+ while (i % 4)
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+ retval = ni_usb_nonblocking_send_bulk_msg(ni_priv, out_data, i, &bytes_written, 1000);
+ kfree(out_data);
+ if (retval || bytes_written != i) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ if (retval != -EAGAIN)
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%i\n",
+ __func__, retval, bytes_written, i);
+ return retval;
+ }
+
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data) {
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+ dev_err(&usb_dev->dev, "%s: kmalloc failed\n", __func__);
+ return -ENOMEM;
+ }
+ retval = ni_usb_nonblocking_receive_bulk_msg(ni_priv, in_data, in_data_length,
+ &bytes_read, 1000, 0);
+
+ mutex_unlock(&ni_priv->addressed_transfer_lock);
+
+ if (retval) {
+ if (retval != -EAGAIN)
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ kfree(in_data);
+ return retval;
+ }
+
+ ni_usb_parse_register_read_block(in_data, &bsr_bits, 1);
+ kfree(in_data);
+ if (bsr_bits & BCSR_REN_BIT)
+ line_status |= BusREN;
+ if (bsr_bits & BCSR_IFC_BIT)
+ line_status |= BusIFC;
+ if (bsr_bits & BCSR_SRQ_BIT)
+ line_status |= BusSRQ;
+ if (bsr_bits & BCSR_EOI_BIT)
+ line_status |= BusEOI;
+ if (bsr_bits & BCSR_NRFD_BIT)
+ line_status |= BusNRFD;
+ if (bsr_bits & BCSR_NDAC_BIT)
+ line_status |= BusNDAC;
+ if (bsr_bits & BCSR_DAV_BIT)
+ line_status |= BusDAV;
+ if (bsr_bits & BCSR_ATN_BIT)
+ line_status |= BusATN;
+ return line_status;
+}
+
+static int ni_usb_setup_t1_delay(struct ni_usb_register *reg, unsigned int nano_sec,
+ unsigned int *actual_ns)
+{
+ int i = 0;
+
+ *actual_ns = 2000;
+
+ reg[i].device = NIUSB_SUBDEV_TNT4882;
+ reg[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ if (nano_sec <= 1100) {
+ reg[i].value = AUXRI | USTD | SISB;
+ *actual_ns = 1100;
+ } else {
+ reg[i].value = AUXRI | SISB;
+ }
+ i++;
+ reg[i].device = NIUSB_SUBDEV_TNT4882;
+ reg[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ if (nano_sec <= 500) {
+ reg[i].value = AUXRB | HR_TRI;
+ *actual_ns = 500;
+ } else {
+ reg[i].value = AUXRB;
+ }
+ i++;
+ reg[i].device = NIUSB_SUBDEV_TNT4882;
+ reg[i].address = KEYREG;
+ if (nano_sec <= 350) {
+ reg[i].value = MSTD;
+ *actual_ns = 350;
+ } else {
+ reg[i].value = 0x0;
+ }
+ i++;
+ return i;
+}
+
+static unsigned int ni_usb_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ struct ni_usb_register writes[3];
+ unsigned int ibsta;
+ unsigned int actual_ns;
+ int i;
+
+ i = ni_usb_setup_t1_delay(writes, nano_sec, &actual_ns);
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return -1; //FIXME should change return type to int for error reporting
+ }
+ board->t1_nano_sec = actual_ns;
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return actual_ns;
+}
+
+static int ni_usb_allocate_private(gpib_board_t *board)
+{
+ struct ni_usb_priv *ni_priv;
+
+ board->private_data = kmalloc(sizeof(struct ni_usb_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -ENOMEM;
+ ni_priv = board->private_data;
+ memset(ni_priv, 0, sizeof(struct ni_usb_priv));
+ mutex_init(&ni_priv->bulk_transfer_lock);
+ mutex_init(&ni_priv->control_transfer_lock);
+ mutex_init(&ni_priv->interrupt_transfer_lock);
+ mutex_init(&ni_priv->addressed_transfer_lock);
+ return 0;
+}
+
+static void ni_usb_free_private(struct ni_usb_priv *ni_priv)
+{
+ usb_free_urb(ni_priv->interrupt_urb);
+ kfree(ni_priv);
+}
+
+#define NUM_INIT_WRITES 26
+static int ni_usb_setup_init(gpib_board_t *board, struct ni_usb_register *writes)
+{
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ unsigned int mask, actual_ns;
+ int i = 0;
+
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN3;
+ writes[i].address = 0x10;
+ writes[i].value = 0x0;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = CMDR;
+ writes[i].value = SOFT_RESET;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ mask = AUXRA | HR_HLDA;
+ if (ni_priv->eos_mode & BIN)
+ mask |= HR_BIN;
+ writes[i].value = mask;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = AUXCR;
+ writes[i].value = mask;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = HSSEL;
+ writes[i].value = TNT_ONE_CHIP_BIT;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CR;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = IMR0;
+ writes[i].value = TNT_IMR0_ALWAYS_BITS;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(IMR1);
+ writes[i].value = 0x0;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(IMR2);
+ writes[i].value = 0x0;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = IMR3;
+ writes[i].value = 0x0;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_HLDI;
+ i++;
+
+ i += ni_usb_setup_t1_delay(&writes[i], board->t1_nano_sec, &actual_ns);
+
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUXRG | NTNL_BIT;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = CMDR;
+ if (board->master)
+ mask = SETSC; // set system controller
+ else
+ mask = CLRSC; // clear system controller
+ writes[i].value = mask;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CIFC;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(ADR);
+ writes[i].value = board->pad;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN2;
+ writes[i].address = 0x0;
+ writes[i].value = board->pad;
+ i++;
+
+ i += ni_usb_write_sad(&writes[i], board->sad, board->sad >= 0);
+
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN2;
+ writes[i].address = 0x2; // could this be a timeout ?
+ writes[i].value = 0xfd;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = 0xf; // undocumented address
+ writes[i].value = 0x11;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_PON;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CPPF;
+ i++;
+ if (i > NUM_INIT_WRITES) {
+ dev_err(&usb_dev->dev, "%s: bug!, buffer overrun, i=%i\n", __func__, i);
+ return 0;
+ }
+ return i;
+}
+
+static int ni_usb_init(gpib_board_t *board)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ struct ni_usb_register *writes;
+ unsigned int ibsta;
+ int writes_len;
+
+ writes = kmalloc_array(NUM_INIT_WRITES, sizeof(*writes), GFP_KERNEL);
+ if (!writes)
+ return -ENOMEM;
+
+ writes_len = ni_usb_setup_init(board, writes);
+ if (writes_len)
+ retval = ni_usb_write_registers(ni_priv, writes, writes_len, &ibsta);
+ else
+ return -EFAULT;
+ kfree(writes);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return retval;
+ }
+ ni_usb_soft_update_status(board, ibsta, 0);
+ return 0;
+}
+
+static void ni_usb_interrupt_complete(struct urb *urb)
+{
+ gpib_board_t *board = urb->context;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ struct ni_usb_status_block status;
+ unsigned long flags;
+
+// printk("debug: %s: status=0x%x, error_count=%i, actual_length=%i\n", __func__,
+// urb->status, urb->error_count, urb->actual_length);
+
+ switch (urb->status) {
+ /* success */
+ case 0:
+ break;
+ /* unlinked, don't resubmit */
+ case -ECONNRESET:
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default: /* other error, resubmit */
+ retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__);
+ return;
+ }
+
+ ni_usb_parse_status_block(urb->transfer_buffer, &status);
+// printk("debug: ibsta=0x%x\n", status.ibsta);
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ ni_priv->monitored_ibsta_bits &= ~status.ibsta;
+// printk("debug: monitored_ibsta_bits=0x%x\n", ni_priv->monitored_ibsta_bits);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ wake_up_interruptible(&board->wait);
+
+ retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_ATOMIC);
+ if (retval)
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb\n", __func__);
+}
+
+static int ni_usb_set_interrupt_monitor(gpib_board_t *board, unsigned int monitored_bits)
+{
+ int retval;
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ static const int buffer_length = 8;
+ u8 *buffer;
+ struct ni_usb_status_block status;
+ unsigned long flags;
+ //printk("%s: receive control pipe is %i\n", __func__, pipe);
+ buffer = kmalloc(buffer_length, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ ni_priv->monitored_ibsta_bits = ni_usb_ibsta_monitor_mask & monitored_bits;
+// dev_err(&usb_dev->dev, "debug: %s: monitored_ibsta_bits=0x%x\n",
+// __func__, ni_priv->monitored_ibsta_bits);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_WAIT_REQUEST, USB_DIR_IN |
+ USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x300, ni_usb_ibsta_monitor_mask & monitored_bits,
+ buffer, buffer_length, 1000);
+ if (retval != buffer_length) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg returned %i\n", __func__, retval);
+ kfree(buffer);
+ return -1;
+ }
+ ni_usb_parse_status_block(buffer, &status);
+ kfree(buffer);
+ return 0;
+}
+
+static int ni_usb_setup_urbs(gpib_board_t *board)
+{
+ struct ni_usb_priv *ni_priv = board->private_data;
+ struct usb_device *usb_dev;
+ int int_pipe;
+ int retval;
+
+ if (ni_priv->interrupt_in_endpoint < 0)
+ return 0;
+
+ mutex_lock(&ni_priv->interrupt_transfer_lock);
+ if (!ni_priv->bus_interface) {
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ return -ENODEV;
+ }
+ ni_priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!ni_priv->interrupt_urb) {
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ return -ENOMEM;
+ }
+ usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int_pipe = usb_rcvintpipe(usb_dev, ni_priv->interrupt_in_endpoint);
+ usb_fill_int_urb(ni_priv->interrupt_urb, usb_dev, int_pipe, ni_priv->interrupt_buffer,
+ sizeof(ni_priv->interrupt_buffer), &ni_usb_interrupt_complete, board, 1);
+ retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_KERNEL);
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to submit first interrupt urb, retval=%i\n",
+ __func__, retval);
+ return retval;
+ }
+ return 0;
+}
+
+static void ni_usb_cleanup_urbs(struct ni_usb_priv *ni_priv)
+{
+ if (ni_priv && ni_priv->bus_interface) {
+ if (ni_priv->interrupt_urb)
+ usb_kill_urb(ni_priv->interrupt_urb);
+ if (ni_priv->bulk_urb)
+ usb_kill_urb(ni_priv->bulk_urb);
+ }
+}
+
+static int ni_usb_b_read_serial_number(struct ni_usb_priv *ni_priv)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ u8 *out_data;
+ u8 *in_data;
+ static const int out_data_length = 0x20;
+ static const int in_data_length = 0x20;
+ int bytes_written = 0, bytes_read = 0;
+ int i = 0;
+ static const int num_reads = 4;
+ unsigned int results[4];
+ int j;
+ unsigned int serial_number;
+
+// printk("%s: %s\n", __func__);
+ in_data = kmalloc(in_data_length, GFP_KERNEL);
+ if (!in_data)
+ return -ENOMEM;
+
+ out_data = kmalloc(out_data_length, GFP_KERNEL);
+ if (!out_data) {
+ kfree(in_data);
+ return -ENOMEM;
+ }
+ i += ni_usb_bulk_register_read_header(&out_data[i], num_reads);
+ i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_1_REG);
+ i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_2_REG);
+ i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_3_REG);
+ i += ni_usb_bulk_register_read(&out_data[i], NIUSB_SUBDEV_UNKNOWN3, SERIAL_NUMBER_4_REG);
+ while (i % 4)
+ out_data[i++] = 0x0;
+ i += ni_usb_bulk_termination(&out_data[i]);
+ retval = ni_usb_send_bulk_msg(ni_priv, out_data, out_data_length, &bytes_written, 1000);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_send_bulk_msg returned %i, bytes_written=%i, i=%li\n",
+ __func__,
+ retval, bytes_written, (long)out_data_length);
+ goto serial_out;
+ }
+ retval = ni_usb_receive_bulk_msg(ni_priv, in_data, in_data_length, &bytes_read, 1000, 0);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: ni_usb_receive_bulk_msg returned %i, bytes_read=%i\n",
+ __func__, retval, bytes_read);
+ ni_usb_dump_raw_block(in_data, bytes_read);
+ goto serial_out;
+ }
+ if (ARRAY_SIZE(results) < num_reads) {
+ dev_err(&usb_dev->dev, "Setup bug\n");
+ retval = -EINVAL;
+ goto serial_out;
+ }
+ ni_usb_parse_register_read_block(in_data, results, num_reads);
+ serial_number = 0;
+ for (j = 0; j < num_reads; ++j)
+ serial_number |= (results[j] & 0xff) << (8 * j);
+ dev_info(&usb_dev->dev, "%s: board serial number is 0x%x\n", __func__, serial_number);
+ retval = 0;
+serial_out:
+ kfree(in_data);
+ kfree(out_data);
+ return retval;
+}
+
+static int ni_usb_hs_wait_for_ready(struct ni_usb_priv *ni_priv)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ static const int buffer_size = 0x10;
+ static const int timeout = 50;
+ static const int msec_sleep_duration = 100;
+ int i; int retval;
+ int j;
+ int unexpected = 0;
+ unsigned int serial_number;
+ u8 *buffer;
+
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_SERIAL_NUMBER_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0, 0x0, buffer, buffer_size, 1000);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n",
+ __func__, NI_USB_SERIAL_NUMBER_REQUEST, retval);
+ goto ready_out;
+ }
+ j = 0;
+ if (buffer[j] != NI_USB_SERIAL_NUMBER_REQUEST) {
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n",
+ __func__, j, (int)buffer[j], NI_USB_SERIAL_NUMBER_REQUEST);
+ unexpected = 1;
+ }
+ if (unexpected)
+ ni_usb_dump_raw_block(buffer, retval);
+ // NI-USB-HS+ pads the serial with 0x0 to make 16 bytes
+ if (retval != 5 && retval != 16) {
+ dev_err(&usb_dev->dev, "%s: received unexpected number of bytes = %i, expected 5 or 16\n",
+ __func__, retval);
+ ni_usb_dump_raw_block(buffer, retval);
+ }
+ serial_number = 0;
+ serial_number |= buffer[++j];
+ serial_number |= (buffer[++j] << 8);
+ serial_number |= (buffer[++j] << 16);
+ serial_number |= (buffer[++j] << 24);
+ dev_info(&usb_dev->dev, "%s: board serial number is 0x%x\n", __func__, serial_number);
+ for (i = 0; i < timeout; ++i) {
+ int ready = 0;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_POLL_READY_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0, 0x0, buffer, buffer_size, 100);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n",
+ __func__, NI_USB_POLL_READY_REQUEST, retval);
+ goto ready_out;
+ }
+ j = 0;
+ unexpected = 0;
+ if (buffer[j] != NI_USB_POLL_READY_REQUEST) { // [0]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n",
+ __func__, j, (int)buffer[j], NI_USB_POLL_READY_REQUEST);
+ unexpected = 1;
+ }
+ ++j;
+ if (buffer[j] != 0x1 && buffer[j] != 0x0) { // [1] HS+ sends 0x0
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ if (buffer[++j] != 0x0) { // [2]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x%x\n",
+ __func__, j, (int)buffer[j], 0x0);
+ unexpected = 1;
+ }
+ ++j;
+ // MC usb-488 (and sometimes NI-USB-HS?) sends 0x8 here; MC usb-488A sends 0x7 here
+ // NI-USB-HS+ sends 0x0
+ if (buffer[j] != 0x1 && buffer[j] != 0x8 && buffer[j] != 0x7 && buffer[j] != 0x0) {
+ // [3]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0, 0x1, 0x7 or 0x8\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ ++j;
+ // NI-USB-HS+ sends 0 here
+ if (buffer[j] != 0x30 && buffer[j] != 0x0) { // [4]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x30\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ ++j;
+ // MC usb-488 (and sometimes NI-USB-HS?) and NI-USB-HS+ sends 0x0 here
+ if (buffer[j] != 0x1 && buffer[j] != 0x0) { // [5]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x1 or 0x0\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ if (buffer[++j] != 0x0) { // [6]
+ ready = 1;
+ // NI-USB-HS+ sends 0xf here
+ if (buffer[j] != 0x2 && buffer[j] != 0xe && buffer[j] != 0xf &&
+ buffer[j] != 0x16) {
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x2, 0xe, 0xf or 0x16\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ }
+ if (buffer[++j] != 0x0) { // [7]
+ ready = 1;
+ // MC usb-488 sends 0x5 here; MC usb-488A sends 0x6 here
+ if (buffer[j] != 0x3 && buffer[j] != 0x5 && buffer[j] != 0x6 &&
+ buffer[j] != 0x8) {
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x3 or 0x5, 0x6 or 0x08\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ }
+ ++j;
+ if (buffer[j] != 0x0 && buffer[j] != 0x2) { // [8] MC usb-488 sends 0x2 here
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0 or 0x2\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ ++j;
+ // MC usb-488A and NI-USB-HS sends 0x3 here; NI-USB-HS+ sends 0x30 here
+ if (buffer[j] != 0x0 && buffer[j] != 0x3 && buffer[j] != 0x30) { // [9]
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x0, 0x3 or 0x30\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ if (buffer[++j] != 0x0) {
+ ready = 1;
+ if (buffer[j] != 0x96 && buffer[j] != 0x7 && buffer[j] != 0x6e) {
+// [10] MC usb-488 sends 0x7 here
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[%i]=0x%x, expected 0x96, 0x07 or 0x6e\n",
+ __func__, j, (int)buffer[j]);
+ unexpected = 1;
+ }
+ }
+ if (unexpected)
+ ni_usb_dump_raw_block(buffer, retval);
+ if (ready)
+ break;
+ retval = msleep_interruptible(msec_sleep_duration);
+ if (retval) {
+ dev_err(&usb_dev->dev, "ni_usb_gpib: msleep interrupted\n");
+ retval = -ERESTARTSYS;
+ goto ready_out;
+ }
+ }
+ retval = 0;
+
+ready_out:
+ kfree(buffer);
+ dev_dbg(&usb_dev->dev, "%s: exit retval=%d\n", __func__, retval);
+ return retval;
+}
+
+/* This does some extra init for HS+ models, as observed on Windows. One of the
+ * control requests causes the LED to stop blinking.
+ * I'm not sure what the other 2 requests do. None of these requests are actually required
+ * for the adapter to work, maybe they do some init for the analyzer interface
+ * (which we don't use).
+ */
+static int ni_usb_hs_plus_extra_init(struct ni_usb_priv *ni_priv)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ u8 *buffer;
+ static const int buffer_size = 16;
+ int transfer_size;
+
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ do {
+ transfer_size = 16;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_0x48_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x0, 0x0, buffer, transfer_size, 1000);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n",
+ __func__, NI_USB_HS_PLUS_0x48_REQUEST, retval);
+ break;
+ }
+ // expected response data: 48 f3 30 00 00 00 00 00 00 00 00 00 00 00 00 00
+ if (buffer[0] != NI_USB_HS_PLUS_0x48_REQUEST)
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n",
+ __func__, (int)buffer[0], NI_USB_HS_PLUS_0x48_REQUEST);
+
+ transfer_size = 2;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_LED_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+ 0x1, 0x0, buffer, transfer_size, 1000);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n",
+ __func__, NI_USB_HS_PLUS_LED_REQUEST, retval);
+ break;
+ }
+ // expected response data: 4b 00
+ if (buffer[0] != NI_USB_HS_PLUS_LED_REQUEST)
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n",
+ __func__, (int)buffer[0], NI_USB_HS_PLUS_LED_REQUEST);
+
+ transfer_size = 9;
+
+ retval = ni_usb_receive_control_msg(ni_priv, NI_USB_HS_PLUS_0xf8_REQUEST,
+ USB_DIR_IN | USB_TYPE_VENDOR |
+ USB_RECIP_INTERFACE,
+ 0x0, 0x1, buffer, transfer_size, 1000);
+ if (retval < 0) {
+ dev_err(&usb_dev->dev, "%s: usb_control_msg request 0x%x returned %i\n",
+ __func__, NI_USB_HS_PLUS_0xf8_REQUEST, retval);
+ break;
+ }
+ // expected response data: f8 01 00 00 00 01 00 00 00
+ if (buffer[0] != NI_USB_HS_PLUS_0xf8_REQUEST)
+ dev_err(&usb_dev->dev, "%s: unexpected data: buffer[0]=0x%x, expected 0x%x\n",
+ __func__, (int)buffer[0], NI_USB_HS_PLUS_0xf8_REQUEST);
+
+ } while (0);
+
+ // cleanup
+ kfree(buffer);
+ return retval;
+}
+
+static inline int ni_usb_device_match(struct usb_interface *interface,
+ const gpib_board_config_t *config)
+{
+ if (gpib_match_device_path(&interface->dev, config->device_path) == 0)
+ return 0;
+ return 1;
+}
+
+static int ni_usb_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int retval;
+ int i;
+ struct ni_usb_priv *ni_priv;
+ int product_id;
+ struct usb_device *usb_dev;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+ retval = ni_usb_allocate_private(board);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ ni_priv = board->private_data;
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
+ if (ni_usb_driver_interfaces[i] &&
+ !usb_get_intfdata(ni_usb_driver_interfaces[i]) &&
+ ni_usb_device_match(ni_usb_driver_interfaces[i], config)) {
+ ni_priv->bus_interface = ni_usb_driver_interfaces[i];
+ usb_set_intfdata(ni_usb_driver_interfaces[i], board);
+ usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d attached to gpib minor %d, NI usb interface %i\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ break;
+ }
+ }
+ if (i == MAX_NUM_NI_USB_INTERFACES) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ pr_err("No supported NI usb gpib adapters found, have you loaded its firmware?\n");
+ return -ENODEV;
+ }
+ if (usb_reset_configuration(interface_to_usbdev(ni_priv->bus_interface)))
+ dev_err(&usb_dev->dev, "ni_usb_gpib: usb_reset_configuration() failed.\n");
+
+ product_id = le16_to_cpu(usb_dev->descriptor.idProduct);
+ ni_priv->product_id = product_id;
+
+ timer_setup(&ni_priv->bulk_timer, ni_usb_timeout_handler, 0);
+
+ switch (product_id) {
+ case USB_DEVICE_ID_NI_USB_B:
+ ni_priv->bulk_out_endpoint = NIUSB_B_BULK_OUT_ENDPOINT;
+ ni_priv->bulk_in_endpoint = NIUSB_B_BULK_IN_ENDPOINT;
+ ni_priv->interrupt_in_endpoint = NIUSB_B_INTERRUPT_IN_ENDPOINT;
+ ni_usb_b_read_serial_number(ni_priv);
+ break;
+ case USB_DEVICE_ID_NI_USB_HS:
+ case USB_DEVICE_ID_MC_USB_488:
+ case USB_DEVICE_ID_KUSB_488A:
+ ni_priv->bulk_out_endpoint = NIUSB_HS_BULK_OUT_ENDPOINT;
+ ni_priv->bulk_in_endpoint = NIUSB_HS_BULK_IN_ENDPOINT;
+ ni_priv->interrupt_in_endpoint = NIUSB_HS_INTERRUPT_IN_ENDPOINT;
+ retval = ni_usb_hs_wait_for_ready(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ break;
+ case USB_DEVICE_ID_NI_USB_HS_PLUS:
+ ni_priv->bulk_out_endpoint = NIUSB_HS_PLUS_BULK_OUT_ENDPOINT;
+ ni_priv->bulk_in_endpoint = NIUSB_HS_PLUS_BULK_IN_ENDPOINT;
+ ni_priv->interrupt_in_endpoint = NIUSB_HS_PLUS_INTERRUPT_IN_ENDPOINT;
+ retval = ni_usb_hs_wait_for_ready(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ retval = ni_usb_hs_plus_extra_init(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ break;
+ default:
+ mutex_unlock(&ni_usb_hotplug_lock);
+ dev_err(&usb_dev->dev, "\tDriver bug: unknown endpoints for usb device id %x\n",
+ product_id);
+ return -EINVAL;
+ }
+
+ retval = ni_usb_setup_urbs(board);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ retval = ni_usb_set_interrupt_monitor(board, 0);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+
+ board->t1_nano_sec = 500;
+
+ retval = ni_usb_init(board);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ retval = ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+
+ mutex_unlock(&ni_usb_hotplug_lock);
+ dev_info(&usb_dev->dev, "%s: attached\n", __func__);
+ return retval;
+}
+
+static int ni_usb_shutdown_hardware(struct ni_usb_priv *ni_priv)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(ni_priv->bus_interface);
+ int retval;
+ int i = 0;
+ struct ni_usb_register writes[2];
+ static const int writes_length = ARRAY_SIZE(writes);
+ unsigned int ibsta;
+
+// printk("%s: %s\n", __func__);
+ writes[i].device = NIUSB_SUBDEV_TNT4882;
+ writes[i].address = nec7210_to_tnt4882_offset(AUXMR);
+ writes[i].value = AUX_CR;
+ i++;
+ writes[i].device = NIUSB_SUBDEV_UNKNOWN3;
+ writes[i].address = 0x10;
+ writes[i].value = 0x0;
+ i++;
+ if (i > writes_length) {
+ dev_err(&usb_dev->dev, "%s: bug!, buffer overrun, i=%i\n", __func__, i);
+ return -EINVAL;
+ }
+ retval = ni_usb_write_registers(ni_priv, writes, i, &ibsta);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: register write failed, retval=%i\n", __func__, retval);
+ return retval;
+ }
+ return 0;
+}
+
+static void ni_usb_detach(gpib_board_t *board)
+{
+ struct ni_usb_priv *ni_priv;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+// under windows, software unplug does chip_reset nec7210 aux command,
+// then writes 0x0 to address 0x10 of device 3
+ ni_priv = board->private_data;
+ if (ni_priv) {
+ if (ni_priv->bus_interface) {
+ ni_usb_set_interrupt_monitor(board, 0);
+ ni_usb_shutdown_hardware(ni_priv);
+ usb_set_intfdata(ni_priv->bus_interface, NULL);
+ }
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ mutex_lock(&ni_priv->control_transfer_lock);
+ mutex_lock(&ni_priv->interrupt_transfer_lock);
+ ni_usb_cleanup_urbs(ni_priv);
+ ni_usb_free_private(ni_priv);
+ }
+ mutex_unlock(&ni_usb_hotplug_lock);
+}
+
+gpib_interface_t ni_usb_gpib_interface = {
+name: "ni_usb_b",
+attach : ni_usb_attach,
+detach : ni_usb_detach,
+read : ni_usb_read,
+write : ni_usb_write,
+command : ni_usb_command,
+take_control : ni_usb_take_control,
+go_to_standby : ni_usb_go_to_standby,
+request_system_control : ni_usb_request_system_control,
+interface_clear : ni_usb_interface_clear,
+remote_enable : ni_usb_remote_enable,
+enable_eos : ni_usb_enable_eos,
+disable_eos : ni_usb_disable_eos,
+parallel_poll : ni_usb_parallel_poll,
+parallel_poll_configure : ni_usb_parallel_poll_configure,
+parallel_poll_response : ni_usb_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : ni_usb_line_status,
+update_status : ni_usb_update_status,
+primary_address : ni_usb_primary_address,
+secondary_address : ni_usb_secondary_address,
+serial_poll_response : ni_usb_serial_poll_response,
+serial_poll_status : ni_usb_serial_poll_status,
+t1_delay : ni_usb_t1_delay,
+return_to_local : ni_usb_return_to_local,
+skip_check_for_command_acceptors : 1
+};
+
+// Table with the USB-devices: just now only testing IDs
+static struct usb_device_id ni_usb_driver_device_table[] = {
+ {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_B)},
+ {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_HS)},
+ // gpib-usb-hs+ has a second interface for the analyzer, which we ignore
+ {USB_DEVICE_INTERFACE_NUMBER(USB_VENDOR_ID_NI, USB_DEVICE_ID_NI_USB_HS_PLUS, 0)},
+ {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_KUSB_488A)},
+ {USB_DEVICE(USB_VENDOR_ID_NI, USB_DEVICE_ID_MC_USB_488)},
+ {} /* Terminating entry */
+};
+MODULE_DEVICE_TABLE(usb, ni_usb_driver_device_table);
+
+static int ni_usb_driver_probe(struct usb_interface *interface, const struct usb_device_id *id)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+ int i;
+ char *path;
+ static const int path_length = 1024;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+ usb_get_dev(usb_dev);
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
+ if (!ni_usb_driver_interfaces[i]) {
+ ni_usb_driver_interfaces[i] = interface;
+ usb_set_intfdata(interface, NULL);
+ break;
+ }
+ }
+ if (i == MAX_NUM_NI_USB_INTERFACES) {
+ usb_put_dev(usb_dev);
+ mutex_unlock(&ni_usb_hotplug_lock);
+ dev_err(&usb_dev->dev, "%s: ni_usb_driver_interfaces[] full\n", __func__);
+ return -1;
+ }
+ path = kmalloc(path_length, GFP_KERNEL);
+ if (!path) {
+ usb_put_dev(usb_dev);
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return -ENOMEM;
+ }
+ usb_make_path(usb_dev, path, path_length);
+ dev_info(&usb_dev->dev, "ni_usb_gpib: probe succeeded for path: %s\n", path);
+ kfree(path);
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return 0;
+}
+
+static void ni_usb_driver_disconnect(struct usb_interface *interface)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+ int i;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
+ if (ni_usb_driver_interfaces[i] == interface) {
+ gpib_board_t *board = usb_get_intfdata(interface);
+
+ if (board) {
+ struct ni_usb_priv *ni_priv = board->private_data;
+
+ if (ni_priv) {
+ mutex_lock(&ni_priv->bulk_transfer_lock);
+ mutex_lock(&ni_priv->control_transfer_lock);
+ mutex_lock(&ni_priv->interrupt_transfer_lock);
+ ni_usb_cleanup_urbs(ni_priv);
+ ni_priv->bus_interface = NULL;
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ mutex_unlock(&ni_priv->control_transfer_lock);
+ mutex_unlock(&ni_priv->bulk_transfer_lock);
+ }
+ }
+ ni_usb_driver_interfaces[i] = NULL;
+ break;
+ }
+ }
+ if (i == MAX_NUM_NI_USB_INTERFACES)
+ dev_err(&usb_dev->dev, "%s: unable to find interface in ni_usb_driver_interfaces[]? bug?\n",
+ __func__);
+ usb_put_dev(usb_dev);
+ mutex_unlock(&ni_usb_hotplug_lock);
+}
+
+static int ni_usb_driver_suspend(struct usb_interface *interface, pm_message_t message)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+ gpib_board_t *board;
+ int i, retval;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
+ if (ni_usb_driver_interfaces[i] == interface) {
+ board = usb_get_intfdata(interface);
+ if (board)
+ break;
+ }
+ }
+ if (i == MAX_NUM_NI_USB_INTERFACES) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return 0;
+ }
+
+ struct ni_usb_priv *ni_priv = board->private_data;
+
+ if (ni_priv) {
+ ni_usb_set_interrupt_monitor(board, 0);
+ retval = ni_usb_shutdown_hardware(ni_priv);
+ if (retval) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ if (ni_priv->interrupt_urb) {
+ mutex_lock(&ni_priv->interrupt_transfer_lock);
+ ni_usb_cleanup_urbs(ni_priv);
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ }
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d gpib minor %d, ni usb interface %i suspended\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ }
+
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return 0;
+}
+
+static int ni_usb_driver_resume(struct usb_interface *interface)
+{
+ struct usb_device *usb_dev = interface_to_usbdev(interface);
+
+ gpib_board_t *board;
+ int i, retval;
+
+ mutex_lock(&ni_usb_hotplug_lock);
+
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++) {
+ if (ni_usb_driver_interfaces[i] == interface) {
+ board = usb_get_intfdata(interface);
+ if (board)
+ break;
+ }
+ }
+ if (i == MAX_NUM_NI_USB_INTERFACES) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return 0;
+ }
+
+ struct ni_usb_priv *ni_priv = board->private_data;
+
+ if (ni_priv) {
+ if (ni_priv->interrupt_urb) {
+ mutex_lock(&ni_priv->interrupt_transfer_lock);
+ retval = usb_submit_urb(ni_priv->interrupt_urb, GFP_KERNEL);
+ if (retval) {
+ dev_err(&usb_dev->dev, "%s: failed to resubmit interrupt urb, retval=%i\n",
+ __func__, retval);
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ mutex_unlock(&ni_priv->interrupt_transfer_lock);
+ } else {
+ dev_err(&usb_dev->dev, "%s: bug! int urb not set up\n", __func__);
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return -EINVAL;
+ }
+
+ switch (ni_priv->product_id) {
+ case USB_DEVICE_ID_NI_USB_B:
+ ni_usb_b_read_serial_number(ni_priv);
+ break;
+ case USB_DEVICE_ID_NI_USB_HS:
+ case USB_DEVICE_ID_MC_USB_488:
+ case USB_DEVICE_ID_KUSB_488A:
+ retval = ni_usb_hs_wait_for_ready(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ break;
+ case USB_DEVICE_ID_NI_USB_HS_PLUS:
+ retval = ni_usb_hs_wait_for_ready(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ retval = ni_usb_hs_plus_extra_init(ni_priv);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ break;
+ default:
+ mutex_unlock(&ni_usb_hotplug_lock);
+ dev_err(&usb_dev->dev, "\tDriver bug: unknown endpoints for usb device id\n");
+ return -EINVAL;
+ }
+
+ retval = ni_usb_set_interrupt_monitor(board, 0);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+
+ retval = ni_usb_init(board);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ retval = ni_usb_set_interrupt_monitor(board, ni_usb_ibsta_monitor_mask);
+ if (retval < 0) {
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return retval;
+ }
+ if (board->master)
+ ni_usb_interface_clear(board, 1); // this is a pulsed action
+ if (ni_priv->ren_state)
+ ni_usb_remote_enable(board, 1);
+
+ dev_info(&usb_dev->dev,
+ "bus %d dev num %d gpib minor %d, ni usb interface %i resumed\n",
+ usb_dev->bus->busnum, usb_dev->devnum, board->minor, i);
+ }
+
+ mutex_unlock(&ni_usb_hotplug_lock);
+ return 0;
+}
+
+static struct usb_driver ni_usb_bus_driver = {
+ .name = "ni_usb_gpib",
+ .probe = ni_usb_driver_probe,
+ .disconnect = ni_usb_driver_disconnect,
+ .suspend = ni_usb_driver_suspend,
+ .resume = ni_usb_driver_resume,
+ .id_table = ni_usb_driver_device_table,
+};
+
+static int __init ni_usb_init_module(void)
+{
+ int i;
+
+ pr_info("ni_usb_gpib driver loading\n");
+ for (i = 0; i < MAX_NUM_NI_USB_INTERFACES; i++)
+ ni_usb_driver_interfaces[i] = NULL;
+ usb_register(&ni_usb_bus_driver);
+ gpib_register_driver(&ni_usb_gpib_interface, THIS_MODULE);
+
+ return 0;
+}
+
+static void __exit ni_usb_exit_module(void)
+{
+ pr_info("ni_usb_gpib driver unloading\n");
+ gpib_unregister_driver(&ni_usb_gpib_interface);
+ usb_deregister(&ni_usb_bus_driver);
+}
+
+module_init(ni_usb_init_module);
+module_exit(ni_usb_exit_module);
diff --git a/drivers/staging/gpib/ni_usb/ni_usb_gpib.h b/drivers/staging/gpib/ni_usb/ni_usb_gpib.h
new file mode 100644
index 000000000000..9b21dfa0f3f6
--- /dev/null
+++ b/drivers/staging/gpib/ni_usb/ni_usb_gpib.h
@@ -0,0 +1,216 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2004 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _NI_USB_GPIB_H
+#define _NI_USB_GPIB_H
+
+#include <linux/mutex.h>
+#include <linux/semaphore.h>
+#include <linux/usb.h>
+#include <linux/timer.h>
+#include "gpibP.h"
+
+enum {
+ USB_VENDOR_ID_NI = 0x3923
+};
+
+enum {
+ USB_DEVICE_ID_NI_USB_B = 0x702a,
+ USB_DEVICE_ID_NI_USB_B_PREINIT = 0x702b, // device id before firmware is loaded
+ USB_DEVICE_ID_NI_USB_HS = 0x709b,
+ USB_DEVICE_ID_NI_USB_HS_PLUS = 0x7618,
+ USB_DEVICE_ID_KUSB_488A = 0x725c,
+ USB_DEVICE_ID_MC_USB_488 = 0x725d
+};
+
+enum ni_usb_device {
+ NIUSB_SUBDEV_TNT4882 = 1,
+ NIUSB_SUBDEV_UNKNOWN2 = 2,
+ NIUSB_SUBDEV_UNKNOWN3 = 3,
+};
+
+enum endpoint_addresses {
+ NIUSB_B_BULK_OUT_ENDPOINT = 0x2,
+ NIUSB_B_BULK_IN_ENDPOINT = 0x2,
+ NIUSB_B_BULK_IN_ALT_ENDPOINT = 0x6,
+ NIUSB_B_INTERRUPT_IN_ENDPOINT = 0x4,
+};
+
+enum hs_enpoint_addresses {
+ NIUSB_HS_BULK_OUT_ENDPOINT = 0x2,
+ NIUSB_HS_BULK_OUT_ALT_ENDPOINT = 0x6,
+ NIUSB_HS_BULK_IN_ENDPOINT = 0x4,
+ NIUSB_HS_BULK_IN_ALT_ENDPOINT = 0x8,
+ NIUSB_HS_INTERRUPT_IN_ENDPOINT = 0x1,
+};
+
+enum hs_plus_endpoint_addresses {
+ NIUSB_HS_PLUS_BULK_OUT_ENDPOINT = 0x1,
+ NIUSB_HS_PLUS_BULK_OUT_ALT_ENDPOINT = 0x4,
+ NIUSB_HS_PLUS_BULK_IN_ENDPOINT = 0x2,
+ NIUSB_HS_PLUS_BULK_IN_ALT_ENDPOINT = 0x5,
+ NIUSB_HS_PLUS_INTERRUPT_IN_ENDPOINT = 0x3,
+};
+
+struct ni_usb_urb_ctx {
+ struct semaphore complete;
+ unsigned timed_out : 1;
+};
+
+// struct which defines private_data for ni_usb devices
+struct ni_usb_priv {
+ struct usb_interface *bus_interface;
+ int bulk_out_endpoint;
+ int bulk_in_endpoint;
+ int interrupt_in_endpoint;
+ u8 eos_char;
+ unsigned short eos_mode;
+ unsigned int monitored_ibsta_bits;
+ struct urb *bulk_urb;
+ struct urb *interrupt_urb;
+ u8 interrupt_buffer[0x11];
+ struct mutex addressed_transfer_lock; // protect transfer lock
+ struct mutex bulk_transfer_lock; // protect bulk message sends
+ struct mutex control_transfer_lock; // protect control messages
+ struct mutex interrupt_transfer_lock; // protect interrupt messages
+ struct timer_list bulk_timer;
+ struct ni_usb_urb_ctx context;
+ int product_id;
+ unsigned short ren_state;
+};
+
+struct ni_usb_status_block {
+ short id;
+ unsigned short ibsta;
+ short error_code;
+ unsigned short count;
+};
+
+struct ni_usb_register {
+ enum ni_usb_device device;
+ short address;
+ unsigned short value;
+};
+
+enum ni_usb_bulk_ids {
+ NIUSB_IBCAC_ID = 0x1,
+ NIUSB_UNKNOWN3_ID = 0x3, // device level function id?
+ NIUSB_TERM_ID = 0x4,
+ NIUSB_IBGTS_ID = 0x6,
+ NIUSB_IBRPP_ID = 0x7,
+ NIUSB_REG_READ_ID = 0x8,
+ NIUSB_REG_WRITE_ID = 0x9,
+ NIUSB_IBSIC_ID = 0xf,
+ NIUSB_REGISTER_READ_DATA_START_ID = 0x34,
+ NIUSB_REGISTER_READ_DATA_END_ID = 0x35,
+ NIUSB_IBRD_DATA_ID = 0x36,
+ NIUSB_IBRD_EXTENDED_DATA_ID = 0x37,
+ NIUSB_IBRD_STATUS_ID = 0x38
+};
+
+enum ni_usb_error_codes {
+ NIUSB_NO_ERROR = 0,
+ /* NIUSB_ABORTED_ERROR occurs when I/O is interrupted early by
+ * doing a NI_USB_STOP_REQUEST on the control endpoint.
+ */
+ NIUSB_ABORTED_ERROR = 1,
+ // NIUSB_READ_ATN_ERROR occurs when you do a board read while
+ // ATN is set
+ NIUSB_ATN_STATE_ERROR = 2,
+ // NIUSB_ADDRESSING_ERROR occurs when you do a board
+ // read/write as CIC but are not in LACS/TACS
+ NIUSB_ADDRESSING_ERROR = 3,
+ /* NIUSB_EOSMODE_ERROR occurs on reads if any eos mode or char
+ * bits are set when REOS is not set.
+ * Have also seen error 4 if you try to send more than 16
+ * command bytes at once on a usb-b.
+ */
+ NIUSB_EOSMODE_ERROR = 4,
+ // NIUSB_NO_BUS_ERROR occurs when you try to write a command
+ // byte but there are no devices connected to the gpib bus
+ NIUSB_NO_BUS_ERROR = 5,
+ // NIUSB_NO_LISTENER_ERROR occurs when you do a board write as
+ // CIC with no listener
+ NIUSB_NO_LISTENER_ERROR = 8,
+ // get NIUSB_TIMEOUT_ERROR on board read/write timeout
+ NIUSB_TIMEOUT_ERROR = 10,
+};
+
+enum ni_usb_control_requests {
+ NI_USB_STOP_REQUEST = 0x20,
+ NI_USB_WAIT_REQUEST = 0x21,
+ NI_USB_POLL_READY_REQUEST = 0x40,
+ NI_USB_SERIAL_NUMBER_REQUEST = 0x41,
+ NI_USB_HS_PLUS_0x48_REQUEST = 0x48,
+ NI_USB_HS_PLUS_LED_REQUEST = 0x4b,
+ NI_USB_HS_PLUS_0xf8_REQUEST = 0xf8
+};
+
+static const unsigned int ni_usb_ibsta_monitor_mask =
+ SRQI | LOK | REM | CIC | ATN | TACS | LACS | DTAS | DCAS;
+
+static inline int nec7210_to_tnt4882_offset(int offset)
+{
+ return 2 * offset;
+};
+
+static inline int ni_usb_bulk_termination(u8 *buffer)
+{
+ int i = 0;
+
+ buffer[i++] = NIUSB_TERM_ID;
+ buffer[i++] = 0x0;
+ buffer[i++] = 0x0;
+ buffer[i++] = 0x0;
+ return i;
+}
+
+enum ni_usb_unknown3_register {
+ SERIAL_NUMBER_4_REG = 0x8,
+ SERIAL_NUMBER_3_REG = 0x9,
+ SERIAL_NUMBER_2_REG = 0xa,
+ SERIAL_NUMBER_1_REG = 0xb,
+};
+
+static inline int ni_usb_bulk_register_write_header(u8 *buffer, int num_writes)
+{
+ int i = 0;
+
+ buffer[i++] = NIUSB_REG_WRITE_ID;
+ buffer[i++] = num_writes;
+ buffer[i++] = 0x0;
+ return i;
+}
+
+static inline int ni_usb_bulk_register_write(u8 *buffer, struct ni_usb_register reg)
+{
+ int i = 0;
+
+ buffer[i++] = reg.device;
+ buffer[i++] = reg.address;
+ buffer[i++] = reg.value;
+ return i;
+}
+
+static inline int ni_usb_bulk_register_read_header(u8 *buffer, int num_reads)
+{
+ int i = 0;
+
+ buffer[i++] = NIUSB_REG_READ_ID;
+ buffer[i++] = num_reads;
+ return i;
+}
+
+static inline int ni_usb_bulk_register_read(u8 *buffer, int device, int address)
+{
+ int i = 0;
+
+ buffer[i++] = device;
+ buffer[i++] = address;
+ return i;
+}
+
+#endif // _NI_USB_GPIB_H
diff --git a/drivers/staging/gpib/pc2/Makefile b/drivers/staging/gpib/pc2/Makefile
new file mode 100644
index 000000000000..8148425e0f87
--- /dev/null
+++ b/drivers/staging/gpib/pc2/Makefile
@@ -0,0 +1,5 @@
+
+obj-m += pc2_gpib.o
+
+
+
diff --git a/drivers/staging/gpib/pc2/pc2_gpib.c b/drivers/staging/gpib/pc2/pc2_gpib.c
new file mode 100644
index 000000000000..7b3b34f47341
--- /dev/null
+++ b/drivers/staging/gpib/pc2/pc2_gpib.c
@@ -0,0 +1,656 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <asm/dma.h>
+#include <linux/dma-mapping.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include "nec7210.h"
+#include "gpibP.h"
+
+// struct which defines private_data for pc2 driver
+struct pc2_priv {
+ struct nec7210_priv nec7210_priv;
+ unsigned int irq;
+ // io address that clears interrupt for pc2a (0x2f0 + irq)
+ unsigned int clear_intr_addr;
+};
+
+// pc2 uses 8 consecutive io addresses
+static const int pc2_iosize = 8;
+static const int pc2a_iosize = 8;
+static const int pc2_2a_iosize = 16;
+
+// offset between io addresses of successive nec7210 registers
+static const int pc2a_reg_offset = 0x400;
+static const int pc2_reg_offset = 1;
+
+//interrupt service routine
+static irqreturn_t pc2_interrupt(int irq, void *arg);
+static irqreturn_t pc2a_interrupt(int irq, void *arg);
+
+// pc2 specific registers and bits
+
+// interrupt clear register address
+static const int pc2a_clear_intr_iobase = 0x2f0;
+static inline unsigned int CLEAR_INTR_REG(unsigned int irq)
+{
+ return pc2a_clear_intr_iobase + irq;
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for PC2/PC2a and compatible devices");
+
+static int pc2_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int pc2a_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int pc2a_cb7210_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int pc2_2a_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void pc2_detach(gpib_board_t *board);
+static void pc2a_detach(gpib_board_t *board);
+static void pc2_2a_detach(gpib_board_t *board);
+
+/*
+ * GPIB interrupt service routines
+ */
+
+irqreturn_t pc2_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct pc2_priv *priv = board->private_data;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = nec7210_interrupt(board, &priv->nec7210_priv);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+irqreturn_t pc2a_interrupt(int irq, void *arg)
+{
+ gpib_board_t *board = arg;
+ struct pc2_priv *priv = board->private_data;
+ int status1, status2;
+ unsigned long flags;
+ irqreturn_t retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ // read interrupt status (also clears status)
+ status1 = read_byte(&priv->nec7210_priv, ISR1);
+ status2 = read_byte(&priv->nec7210_priv, ISR2);
+ /* clear interrupt circuit */
+ if (priv->irq)
+ outb(0xff, CLEAR_INTR_REG(priv->irq));
+ retval = nec7210_interrupt_have_status(board, &priv->nec7210_priv, status1, status2);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return retval;
+}
+
+// wrappers for interface functions
+static int pc2_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+}
+
+static int pc2_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+static int pc2_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+static int pc2_take_control(gpib_board_t *board, int synchronous)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+static int pc2_go_to_standby(gpib_board_t *board)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+static void pc2_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_request_system_control(board, &priv->nec7210_priv, request_control);
+}
+
+static void pc2_interface_clear(gpib_board_t *board, int assert)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+static void pc2_remote_enable(gpib_board_t *board, int enable)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+static int pc2_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+static void pc2_disable_eos(gpib_board_t *board)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+static unsigned int pc2_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_update_status(board, &priv->nec7210_priv, clear_mask);
+}
+
+static int pc2_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+static int pc2_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+static int pc2_parallel_poll(gpib_board_t *board, uint8_t *result)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_parallel_poll(board, &priv->nec7210_priv, result);
+}
+
+static void pc2_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config);
+}
+
+static void pc2_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+static void pc2_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+static uint8_t pc2_serial_poll_status(gpib_board_t *board)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+static unsigned int pc2_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ return nec7210_t1_delay(board, &priv->nec7210_priv, nano_sec);
+}
+
+static void pc2_return_to_local(gpib_board_t *board)
+{
+ struct pc2_priv *priv = board->private_data;
+
+ nec7210_return_to_local(board, &priv->nec7210_priv);
+}
+
+gpib_interface_t pc2_interface = {
+name: "pcII",
+attach : pc2_attach,
+detach : pc2_detach,
+read : pc2_read,
+write : pc2_write,
+command : pc2_command,
+take_control : pc2_take_control,
+go_to_standby : pc2_go_to_standby,
+request_system_control : pc2_request_system_control,
+interface_clear : pc2_interface_clear,
+remote_enable : pc2_remote_enable,
+enable_eos : pc2_enable_eos,
+disable_eos : pc2_disable_eos,
+parallel_poll : pc2_parallel_poll,
+parallel_poll_configure : pc2_parallel_poll_configure,
+parallel_poll_response : pc2_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL,
+update_status : pc2_update_status,
+primary_address : pc2_primary_address,
+secondary_address : pc2_secondary_address,
+serial_poll_response : pc2_serial_poll_response,
+serial_poll_status : pc2_serial_poll_status,
+t1_delay : pc2_t1_delay,
+return_to_local : pc2_return_to_local,
+};
+
+gpib_interface_t pc2a_interface = {
+name: "pcIIa",
+attach : pc2a_attach,
+detach : pc2a_detach,
+read : pc2_read,
+write : pc2_write,
+command : pc2_command,
+take_control : pc2_take_control,
+go_to_standby : pc2_go_to_standby,
+request_system_control : pc2_request_system_control,
+interface_clear : pc2_interface_clear,
+remote_enable : pc2_remote_enable,
+enable_eos : pc2_enable_eos,
+disable_eos : pc2_disable_eos,
+parallel_poll : pc2_parallel_poll,
+parallel_poll_configure : pc2_parallel_poll_configure,
+parallel_poll_response : pc2_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL,
+update_status : pc2_update_status,
+primary_address : pc2_primary_address,
+secondary_address : pc2_secondary_address,
+serial_poll_response : pc2_serial_poll_response,
+serial_poll_status : pc2_serial_poll_status,
+t1_delay : pc2_t1_delay,
+return_to_local : pc2_return_to_local,
+};
+
+gpib_interface_t pc2a_cb7210_interface = {
+name: "pcIIa_cb7210",
+attach : pc2a_cb7210_attach,
+detach : pc2a_detach,
+read : pc2_read,
+write : pc2_write,
+command : pc2_command,
+take_control : pc2_take_control,
+go_to_standby : pc2_go_to_standby,
+request_system_control : pc2_request_system_control,
+interface_clear : pc2_interface_clear,
+remote_enable : pc2_remote_enable,
+enable_eos : pc2_enable_eos,
+disable_eos : pc2_disable_eos,
+parallel_poll : pc2_parallel_poll,
+parallel_poll_configure : pc2_parallel_poll_configure,
+parallel_poll_response : pc2_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL, //XXX
+update_status : pc2_update_status,
+primary_address : pc2_primary_address,
+secondary_address : pc2_secondary_address,
+serial_poll_response : pc2_serial_poll_response,
+serial_poll_status : pc2_serial_poll_status,
+t1_delay : pc2_t1_delay,
+return_to_local : pc2_return_to_local,
+};
+
+gpib_interface_t pc2_2a_interface = {
+name: "pcII_IIa",
+attach : pc2_2a_attach,
+detach : pc2_2a_detach,
+read : pc2_read,
+write : pc2_write,
+command : pc2_command,
+take_control : pc2_take_control,
+go_to_standby : pc2_go_to_standby,
+request_system_control : pc2_request_system_control,
+interface_clear : pc2_interface_clear,
+remote_enable : pc2_remote_enable,
+enable_eos : pc2_enable_eos,
+disable_eos : pc2_disable_eos,
+parallel_poll : pc2_parallel_poll,
+parallel_poll_configure : pc2_parallel_poll_configure,
+parallel_poll_response : pc2_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL,
+update_status : pc2_update_status,
+primary_address : pc2_primary_address,
+secondary_address : pc2_secondary_address,
+serial_poll_response : pc2_serial_poll_response,
+serial_poll_status : pc2_serial_poll_status,
+t1_delay : pc2_t1_delay,
+return_to_local : pc2_return_to_local,
+};
+
+static int allocate_private(gpib_board_t *board)
+{
+ struct pc2_priv *priv;
+
+ board->private_data = kmalloc(sizeof(struct pc2_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ priv = board->private_data;
+ memset(priv, 0, sizeof(struct pc2_priv));
+ init_nec7210_private(&priv->nec7210_priv);
+ return 0;
+}
+
+static void free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+static int pc2_generic_attach(gpib_board_t *board, const gpib_board_config_t *config,
+ enum nec7210_chipset chipset)
+{
+ struct pc2_priv *pc2_priv;
+ struct nec7210_priv *nec_priv;
+
+ board->status = 0;
+ if (allocate_private(board))
+ return -ENOMEM;
+ pc2_priv = board->private_data;
+ nec_priv = &pc2_priv->nec7210_priv;
+ nec_priv->read_byte = nec7210_ioport_read_byte;
+ nec_priv->write_byte = nec7210_ioport_write_byte;
+ nec_priv->type = chipset;
+
+#ifndef PC2_DMA
+ /* board->dev hasn't been initialized, so forget about DMA until this driver
+ * is adapted to use isa_register_driver.
+ */
+ if (config->ibdma)
+ pr_err("DMA disabled for pc2 gpib, driver needs to be adapted to use isa_register_driver to get a struct device*");
+#else
+ if (config->ibdma) {
+ nec_priv->dma_buffer_length = 0x1000;
+ nec_priv->dma_buffer = dma_alloc_coherent(board->dev,
+ nec_priv->dma_buffer_length, &
+ nec_priv->dma_buffer_addr, GFP_ATOMIC);
+ if (!nec_priv->dma_buffer)
+ return -ENOMEM;
+
+ // request isa dma channel
+ if (request_dma(config->ibdma, "pc2")) {
+ pr_err("gpib: can't request DMA %d\n", config->ibdma);
+ return -1;
+ }
+ nec_priv->dma_channel = config->ibdma;
+ }
+#endif
+
+ return 0;
+}
+
+int pc2_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ int isr_flags = 0;
+ struct pc2_priv *pc2_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ retval = pc2_generic_attach(board, config, NEC7210);
+ if (retval)
+ return retval;
+
+ pc2_priv = board->private_data;
+ nec_priv = &pc2_priv->nec7210_priv;
+ nec_priv->offset = pc2_reg_offset;
+
+ if (request_region((unsigned long)config->ibbase, pc2_iosize, "pc2") == 0) {
+ pr_err("gpib: ioports are already in use\n");
+ return -1;
+ }
+ nec_priv->iobase = config->ibbase;
+
+ nec7210_board_reset(nec_priv, board);
+
+ // install interrupt handler
+ if (config->ibirq) {
+ if (request_irq(config->ibirq, pc2_interrupt, isr_flags, "pc2", board)) {
+ pr_err("gpib: can't request IRQ %d\n", config->ibirq);
+ return -1;
+ }
+ }
+ pc2_priv->irq = config->ibirq;
+ /* poll so we can detect assertion of ATN */
+ if (gpib_request_pseudo_irq(board, pc2_interrupt)) {
+ pr_err("pc2_gpib: failed to allocate pseudo_irq\n");
+ return -1;
+ }
+ /* set internal counter register for 8 MHz input clock */
+ write_byte(nec_priv, ICR | 8, AUXMR);
+
+ nec7210_board_online(nec_priv, board);
+
+ return 0;
+}
+
+void pc2_detach(gpib_board_t *board)
+{
+ struct pc2_priv *pc2_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (pc2_priv) {
+ nec_priv = &pc2_priv->nec7210_priv;
+#ifdef PC2_DMA
+ if (nec_priv->dma_channel)
+ free_dma(nec_priv->dma_channel);
+#endif
+ gpib_free_pseudo_irq(board);
+ if (pc2_priv->irq)
+ free_irq(pc2_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ release_region((unsigned long)(nec_priv->iobase), pc2_iosize);
+ }
+ if (nec_priv->dma_buffer) {
+ dma_free_coherent(board->dev, nec_priv->dma_buffer_length,
+ nec_priv->dma_buffer, nec_priv->dma_buffer_addr);
+ nec_priv->dma_buffer = NULL;
+ }
+ }
+ free_private(board);
+}
+
+static int pc2a_common_attach(gpib_board_t *board, const gpib_board_config_t *config,
+ unsigned int num_registers, enum nec7210_chipset chipset)
+{
+ unsigned int i, j;
+ struct pc2_priv *pc2_priv;
+ struct nec7210_priv *nec_priv;
+ int retval;
+
+ retval = pc2_generic_attach(board, config, chipset);
+ if (retval)
+ return retval;
+
+ pc2_priv = board->private_data;
+ nec_priv = &pc2_priv->nec7210_priv;
+ nec_priv->offset = pc2a_reg_offset;
+
+ switch ((unsigned long)(config->ibbase)) {
+ case 0x02e1:
+ case 0x22e1:
+ case 0x42e1:
+ case 0x62e1:
+ break;
+ default:
+ pr_err("PCIIa base range invalid, must be one of 0x[0246]2e1, but is 0x%p\n",
+ config->ibbase);
+ return -1;
+ }
+
+ if (config->ibirq) {
+ if (config->ibirq < 2 || config->ibirq > 7) {
+ pr_err("pc2_gpib: illegal interrupt level %i\n", config->ibirq);
+ return -1;
+ }
+ } else {
+ pr_err("pc2_gpib: interrupt disabled, using polling mode (slow)\n");
+ }
+#ifdef CHECK_IOPORTS
+ unsigned int err = 0;
+
+ for (i = 0; i < num_registers; i++) {
+ if (check_region((unsigned long)config->ibbase + i * pc2a_reg_offset, 1))
+ err++;
+ }
+ if (config->ibirq && check_region(pc2a_clear_intr_iobase + config->ibirq, 1))
+ err++;
+ if (err) {
+ pr_err("gpib: ioports are already in use");
+ return -1;
+ }
+#endif
+ for (i = 0; i < num_registers; i++) {
+ if (!request_region((unsigned long)config->ibbase +
+ i * pc2a_reg_offset, 1, "pc2a")) {
+ pr_err("gpib: ioports are already in use");
+ for (j = 0; j < i; j++)
+ release_region((unsigned long)(config->ibbase) +
+ j * pc2a_reg_offset, 1);
+ return -1;
+ }
+ }
+ nec_priv->iobase = config->ibbase;
+ if (config->ibirq) {
+ if (!request_region(pc2a_clear_intr_iobase + config->ibirq, 1, "pc2a")) {
+ pr_err("gpib: ioports are already in use");
+ return -1;
+ }
+ pc2_priv->clear_intr_addr = pc2a_clear_intr_iobase + config->ibirq;
+ if (request_irq(config->ibirq, pc2a_interrupt, 0, "pc2a", board)) {
+ pr_err("gpib: can't request IRQ %d\n", config->ibirq);
+ return -1;
+ }
+ }
+ pc2_priv->irq = config->ibirq;
+ /* poll so we can detect assertion of ATN */
+ if (gpib_request_pseudo_irq(board, pc2_interrupt)) {
+ pr_err("pc2_gpib: failed to allocate pseudo_irq\n");
+ return -1;
+ }
+
+ // make sure interrupt is clear
+ if (pc2_priv->irq)
+ outb(0xff, CLEAR_INTR_REG(pc2_priv->irq));
+
+ nec7210_board_reset(nec_priv, board);
+
+ /* set internal counter register for 8 MHz input clock */
+ write_byte(nec_priv, ICR | 8, AUXMR);
+
+ nec7210_board_online(nec_priv, board);
+
+ return 0;
+}
+
+int pc2a_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return pc2a_common_attach(board, config, pc2a_iosize, NEC7210);
+}
+
+int pc2a_cb7210_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return pc2a_common_attach(board, config, pc2a_iosize, CB7210);
+}
+
+int pc2_2a_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return pc2a_common_attach(board, config, pc2_2a_iosize, NAT4882);
+}
+
+static void pc2a_common_detach(gpib_board_t *board, unsigned int num_registers)
+{
+ int i;
+ struct pc2_priv *pc2_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (pc2_priv) {
+ nec_priv = &pc2_priv->nec7210_priv;
+#ifdef PC2_DMA
+ if (nec_priv->dma_channel)
+ free_dma(nec_priv->dma_channel);
+#endif
+ gpib_free_pseudo_irq(board);
+ if (pc2_priv->irq)
+ free_irq(pc2_priv->irq, board);
+ if (nec_priv->iobase) {
+ nec7210_board_reset(nec_priv, board);
+ for (i = 0; i < num_registers; i++)
+ release_region((unsigned long)nec_priv->iobase +
+ i * pc2a_reg_offset, 1);
+ }
+ if (pc2_priv->clear_intr_addr)
+ release_region(pc2_priv->clear_intr_addr, 1);
+ if (nec_priv->dma_buffer) {
+ dma_free_coherent(board->dev, nec_priv->dma_buffer_length,
+ nec_priv->dma_buffer,
+ nec_priv->dma_buffer_addr);
+ nec_priv->dma_buffer = NULL;
+ }
+ }
+ free_private(board);
+}
+
+void pc2a_detach(gpib_board_t *board)
+{
+ pc2a_common_detach(board, pc2a_iosize);
+}
+
+void pc2_2a_detach(gpib_board_t *board)
+{
+ pc2a_common_detach(board, pc2_2a_iosize);
+}
+
+static int __init pc2_init_module(void)
+{
+ gpib_register_driver(&pc2_interface, THIS_MODULE);
+ gpib_register_driver(&pc2a_interface, THIS_MODULE);
+ gpib_register_driver(&pc2a_cb7210_interface, THIS_MODULE);
+ gpib_register_driver(&pc2_2a_interface, THIS_MODULE);
+
+ return 0;
+}
+
+static void __exit pc2_exit_module(void)
+{
+ gpib_unregister_driver(&pc2_interface);
+ gpib_unregister_driver(&pc2a_interface);
+ gpib_unregister_driver(&pc2a_cb7210_interface);
+ gpib_unregister_driver(&pc2_2a_interface);
+}
+
+module_init(pc2_init_module);
+module_exit(pc2_exit_module);
+
diff --git a/drivers/staging/gpib/tms9914/Makefile b/drivers/staging/gpib/tms9914/Makefile
new file mode 100644
index 000000000000..81b7e3cf104c
--- /dev/null
+++ b/drivers/staging/gpib/tms9914/Makefile
@@ -0,0 +1,6 @@
+
+obj-m += tms9914.o
+
+
+
+
diff --git a/drivers/staging/gpib/tms9914/tms9914.c b/drivers/staging/gpib/tms9914/tms9914.c
new file mode 100644
index 000000000000..152b243b845b
--- /dev/null
+++ b/drivers/staging/gpib/tms9914/tms9914.c
@@ -0,0 +1,910 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/dma.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+
+#include "gpibP.h"
+#include "tms9914.h"
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB library for tms9914");
+
+static unsigned int update_status_nolock(gpib_board_t *board, struct tms9914_priv *priv);
+
+int tms9914_take_control(gpib_board_t *board, struct tms9914_priv *priv, int synchronous)
+{
+ int i;
+ const int timeout = 100;
+
+ if (synchronous)
+ write_byte(priv, AUX_TCS, AUXCR);
+ else
+ write_byte(priv, AUX_TCA, AUXCR);
+ // busy wait until ATN is asserted
+ for (i = 0; i < timeout; i++) {
+ if ((read_byte(priv, ADSR) & HR_ATN))
+ break;
+ udelay(1);
+ }
+ if (i == timeout)
+ return -ETIMEDOUT;
+
+ clear_bit(WRITE_READY_BN, &priv->state);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tms9914_take_control);
+
+/* The agilent 82350B has a buggy implementation of tcs which interferes with the
+ * operation of tca. It appears to be based on the controller state machine
+ * described in the TI 9900 TMS9914A data manual published in 1982. This
+ * manual describes tcs as putting the controller into a CWAS
+ * state where it waits indefinitely for ANRS and ignores tca. Since a
+ * functioning tca is far more important than tcs, we work around the
+ * problem by never issuing tcs.
+ *
+ * I don't know if this problem exists in the real tms9914a or just in the fpga
+ * of the 82350B. For now, only the agilent_82350b uses this workaround.
+ * The rest of the tms9914 based drivers still use tms9914_take_control
+ * directly (which does issue tcs).
+ */
+int tms9914_take_control_workaround(gpib_board_t *board, struct tms9914_priv *priv, int synchronous)
+{
+ if (synchronous)
+ return -ETIMEDOUT;
+ return tms9914_take_control(board, priv, synchronous);
+}
+EXPORT_SYMBOL_GPL(tms9914_take_control_workaround);
+
+int tms9914_go_to_standby(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ int i;
+ const int timeout = 1000;
+
+ write_byte(priv, AUX_GTS, AUXCR);
+ // busy wait until ATN is released
+ for (i = 0; i < timeout; i++) {
+ if ((read_byte(priv, ADSR) & HR_ATN) == 0)
+ break;
+ udelay(1);
+ }
+ if (i == timeout) {
+ pr_err("error waiting for NATN\n");
+ return -ETIMEDOUT;
+ }
+
+ clear_bit(COMMAND_READY_BN, &priv->state);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(tms9914_go_to_standby);
+
+void tms9914_interface_clear(gpib_board_t *board, struct tms9914_priv *priv, int assert)
+{
+ if (assert) {
+ write_byte(priv, AUX_SIC | AUX_CS, AUXCR);
+
+ set_bit(CIC_NUM, &board->status);
+ } else {
+ write_byte(priv, AUX_SIC, AUXCR);
+ }
+}
+EXPORT_SYMBOL_GPL(tms9914_interface_clear);
+
+void tms9914_remote_enable(gpib_board_t *board, struct tms9914_priv *priv, int enable)
+{
+ if (enable)
+ write_byte(priv, AUX_SRE | AUX_CS, AUXCR);
+ else
+ write_byte(priv, AUX_SRE, AUXCR);
+}
+EXPORT_SYMBOL_GPL(tms9914_remote_enable);
+
+void tms9914_request_system_control(gpib_board_t *board, struct tms9914_priv *priv,
+ int request_control)
+{
+ if (request_control) {
+ write_byte(priv, AUX_RQC, AUXCR);
+ } else {
+ clear_bit(CIC_NUM, &board->status);
+ write_byte(priv, AUX_RLC, AUXCR);
+ }
+}
+EXPORT_SYMBOL_GPL(tms9914_request_system_control);
+
+unsigned int tms9914_t1_delay(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int nano_sec)
+{
+ static const int clock_period = 200; // assuming 5Mhz input clock
+ int num_cycles;
+
+ num_cycles = 12;
+
+ if (nano_sec <= 8 * clock_period) {
+ write_byte(priv, AUX_STDL | AUX_CS, AUXCR);
+ num_cycles = 8;
+ } else {
+ write_byte(priv, AUX_STDL, AUXCR);
+ }
+
+ if (nano_sec <= 4 * clock_period) {
+ write_byte(priv, AUX_VSTDL | AUX_CS, AUXCR);
+ num_cycles = 4;
+ } else {
+ write_byte(priv, AUX_VSTDL, AUXCR);
+ }
+
+ return num_cycles * clock_period;
+}
+EXPORT_SYMBOL_GPL(tms9914_t1_delay);
+
+void tms9914_return_to_local(const gpib_board_t *board, struct tms9914_priv *priv)
+{
+ write_byte(priv, AUX_RTL, AUXCR);
+}
+EXPORT_SYMBOL_GPL(tms9914_return_to_local);
+
+void tms9914_set_holdoff_mode(struct tms9914_priv *priv, enum tms9914_holdoff_mode mode)
+{
+ switch (mode) {
+ case TMS9914_HOLDOFF_NONE:
+ write_byte(priv, AUX_HLDE, AUXCR);
+ write_byte(priv, AUX_HLDA, AUXCR);
+ break;
+ case TMS9914_HOLDOFF_EOI:
+ write_byte(priv, AUX_HLDE | AUX_CS, AUXCR);
+ write_byte(priv, AUX_HLDA, AUXCR);
+ break;
+ case TMS9914_HOLDOFF_ALL:
+ write_byte(priv, AUX_HLDE, AUXCR);
+ write_byte(priv, AUX_HLDA | AUX_CS, AUXCR);
+ break;
+ default:
+ pr_err("%s: bug! bad holdoff mode %i\n", __func__, mode);
+ break;
+ }
+ priv->holdoff_mode = mode;
+}
+EXPORT_SYMBOL_GPL(tms9914_set_holdoff_mode);
+
+void tms9914_release_holdoff(struct tms9914_priv *priv)
+{
+ if (priv->holdoff_active) {
+ write_byte(priv, AUX_RHDF, AUXCR);
+ priv->holdoff_active = 0;
+ }
+}
+EXPORT_SYMBOL_GPL(tms9914_release_holdoff);
+
+int tms9914_enable_eos(gpib_board_t *board, struct tms9914_priv *priv, uint8_t eos_byte,
+ int compare_8_bits)
+{
+ priv->eos = eos_byte;
+ priv->eos_flags = REOS;
+ if (compare_8_bits)
+ priv->eos_flags |= BIN;
+ return 0;
+}
+EXPORT_SYMBOL(tms9914_enable_eos);
+
+void tms9914_disable_eos(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ priv->eos_flags &= ~REOS;
+}
+EXPORT_SYMBOL(tms9914_disable_eos);
+
+int tms9914_parallel_poll(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *result)
+{
+ // execute parallel poll
+ write_byte(priv, AUX_CS | AUX_RPP, AUXCR);
+ udelay(2);
+ *result = read_byte(priv, CPTR);
+ // clear parallel poll state
+ write_byte(priv, AUX_RPP, AUXCR);
+ return 0;
+}
+EXPORT_SYMBOL(tms9914_parallel_poll);
+
+static void set_ppoll_reg(struct tms9914_priv *priv, int enable,
+ unsigned int dio_line, int sense, int ist)
+{
+ u8 dio_byte;
+
+ if (enable && ((sense && ist) || (!sense && !ist))) {
+ dio_byte = 1 << (dio_line - 1);
+ write_byte(priv, dio_byte, PPR);
+ } else {
+ write_byte(priv, 0, PPR);
+ }
+}
+
+void tms9914_parallel_poll_configure(gpib_board_t *board,
+ struct tms9914_priv *priv, uint8_t config)
+{
+ priv->ppoll_enable = (config & PPC_DISABLE) == 0;
+ priv->ppoll_line = (config & PPC_DIO_MASK) + 1;
+ priv->ppoll_sense = (config & PPC_SENSE) != 0;
+ set_ppoll_reg(priv, priv->ppoll_enable, priv->ppoll_line, priv->ppoll_sense, board->ist);
+}
+EXPORT_SYMBOL(tms9914_parallel_poll_configure);
+
+void tms9914_parallel_poll_response(gpib_board_t *board,
+ struct tms9914_priv *priv, int ist)
+{
+ set_ppoll_reg(priv, priv->ppoll_enable, priv->ppoll_line, priv->ppoll_sense, ist);
+}
+EXPORT_SYMBOL(tms9914_parallel_poll_response);
+
+void tms9914_serial_poll_response(gpib_board_t *board, struct tms9914_priv *priv, uint8_t status)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ write_byte(priv, status, SPMR);
+ priv->spoll_status = status;
+ if (status & request_service_bit)
+ write_byte(priv, AUX_RSV2 | AUX_CS, AUXCR);
+ else
+ write_byte(priv, AUX_RSV2, AUXCR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+EXPORT_SYMBOL(tms9914_serial_poll_response);
+
+uint8_t tms9914_serial_poll_status(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ u8 status;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ status = priv->spoll_status;
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return status;
+}
+EXPORT_SYMBOL(tms9914_serial_poll_status);
+
+int tms9914_primary_address(gpib_board_t *board, struct tms9914_priv *priv, unsigned int address)
+{
+ // put primary address in address0
+ write_byte(priv, address & ADDRESS_MASK, ADR);
+ return 0;
+}
+EXPORT_SYMBOL(tms9914_primary_address);
+
+int tms9914_secondary_address(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int address, int enable)
+{
+ if (enable)
+ priv->imr1_bits |= HR_APTIE;
+ else
+ priv->imr1_bits &= ~HR_APTIE;
+
+ write_byte(priv, priv->imr1_bits, IMR1);
+ return 0;
+}
+EXPORT_SYMBOL(tms9914_secondary_address);
+
+unsigned int tms9914_update_status(gpib_board_t *board, struct tms9914_priv *priv,
+ unsigned int clear_mask)
+{
+ unsigned long flags;
+ unsigned int retval;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ retval = update_status_nolock(board, priv);
+ board->status &= ~clear_mask;
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return retval;
+}
+EXPORT_SYMBOL(tms9914_update_status);
+
+static void update_talker_state(struct tms9914_priv *priv, unsigned int address_status_bits)
+{
+ if (address_status_bits & HR_TA) {
+ if (address_status_bits & HR_ATN)
+ priv->talker_state = talker_addressed;
+ else
+ /* this could also be serial_poll_active, but the tms9914 provides no
+ * way to distinguish, so we'll assume talker_active
+ */
+ priv->talker_state = talker_active;
+ } else {
+ priv->talker_state = talker_idle;
+ }
+}
+
+static void update_listener_state(struct tms9914_priv *priv, unsigned int address_status_bits)
+{
+ if (address_status_bits & HR_LA) {
+ if (address_status_bits & HR_ATN)
+ priv->listener_state = listener_addressed;
+ else
+ priv->listener_state = listener_active;
+ } else {
+ priv->listener_state = listener_idle;
+ }
+}
+
+static unsigned int update_status_nolock(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ int address_status;
+ int bsr_bits;
+
+ address_status = read_byte(priv, ADSR);
+
+ // check for remote/local
+ if (address_status & HR_REM)
+ set_bit(REM_NUM, &board->status);
+ else
+ clear_bit(REM_NUM, &board->status);
+ // check for lockout
+ if (address_status & HR_LLO)
+ set_bit(LOK_NUM, &board->status);
+ else
+ clear_bit(LOK_NUM, &board->status);
+ // check for ATN
+ if (address_status & HR_ATN)
+ set_bit(ATN_NUM, &board->status);
+ else
+ clear_bit(ATN_NUM, &board->status);
+ // check for talker/listener addressed
+ update_talker_state(priv, address_status);
+ if (priv->talker_state == talker_active || priv->talker_state == talker_addressed)
+ set_bit(TACS_NUM, &board->status);
+ else
+ clear_bit(TACS_NUM, &board->status);
+
+ update_listener_state(priv, address_status);
+ if (priv->listener_state == listener_active || priv->listener_state == listener_addressed)
+ set_bit(LACS_NUM, &board->status);
+ else
+ clear_bit(LACS_NUM, &board->status);
+ // Check for SRQI - not reset elsewhere except in autospoll
+ if (board->status & SRQI) {
+ bsr_bits = read_byte(priv, BSR);
+ if (!(bsr_bits & BSR_SRQ_BIT))
+ clear_bit(SRQI_NUM, &board->status);
+ }
+
+ dev_dbg(board->gpib_dev, "status 0x%lx, state 0x%lx\n", board->status, priv->state);
+
+ return board->status;
+}
+
+int tms9914_line_status(const gpib_board_t *board, struct tms9914_priv *priv)
+{
+ int bsr_bits;
+ int status = ValidALL;
+
+ bsr_bits = read_byte(priv, BSR);
+
+ if (bsr_bits & BSR_REN_BIT)
+ status |= BusREN;
+ if (bsr_bits & BSR_IFC_BIT)
+ status |= BusIFC;
+ if (bsr_bits & BSR_SRQ_BIT)
+ status |= BusSRQ;
+ if (bsr_bits & BSR_EOI_BIT)
+ status |= BusEOI;
+ if (bsr_bits & BSR_NRFD_BIT)
+ status |= BusNRFD;
+ if (bsr_bits & BSR_NDAC_BIT)
+ status |= BusNDAC;
+ if (bsr_bits & BSR_DAV_BIT)
+ status |= BusDAV;
+ if (bsr_bits & BSR_ATN_BIT)
+ status |= BusATN;
+
+ return status;
+}
+EXPORT_SYMBOL(tms9914_line_status);
+
+static int check_for_eos(struct tms9914_priv *priv, uint8_t byte)
+{
+ static const u8 seven_bit_compare_mask = 0x7f;
+
+ if ((priv->eos_flags & REOS) == 0)
+ return 0;
+
+ if (priv->eos_flags & BIN) {
+ if (priv->eos == byte)
+ return 1;
+ } else {
+ if ((priv->eos & seven_bit_compare_mask) == (byte & seven_bit_compare_mask))
+ return 1;
+ }
+ return 0;
+}
+
+static int wait_for_read_byte(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ if (wait_event_interruptible(board->wait,
+ test_bit(READ_READY_BN, &priv->state) ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_debug("gpib: pio read wait interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+
+ if (test_bit(DEV_CLEAR_BN, &priv->state))
+ return -EINTR;
+ return 0;
+}
+
+static inline uint8_t tms9914_read_data_in(gpib_board_t *board, struct tms9914_priv *priv, int *end)
+{
+ unsigned long flags;
+ u8 data;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ clear_bit(READ_READY_BN, &priv->state);
+ data = read_byte(priv, DIR);
+ if (test_and_clear_bit(RECEIVED_END_BN, &priv->state))
+ *end = 1;
+ else
+ *end = 0;
+ switch (priv->holdoff_mode) {
+ case TMS9914_HOLDOFF_EOI:
+ if (*end)
+ priv->holdoff_active = 1;
+ break;
+ case TMS9914_HOLDOFF_ALL:
+ priv->holdoff_active = 1;
+ break;
+ case TMS9914_HOLDOFF_NONE:
+ break;
+ default:
+ pr_err("%s: bug! bad holdoff mode %i\n", __func__, priv->holdoff_mode);
+ break;
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ return data;
+}
+
+static int pio_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+
+ *bytes_read = 0;
+ *end = 0;
+ while (*bytes_read < length && *end == 0) {
+ tms9914_release_holdoff(priv);
+ retval = wait_for_read_byte(board, priv);
+ if (retval < 0)
+ return retval;
+ buffer[(*bytes_read)++] = tms9914_read_data_in(board, priv, end);
+
+ if (check_for_eos(priv, buffer[*bytes_read - 1]))
+ *end = 1;
+ }
+
+ return retval;
+}
+
+int tms9914_read(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, int *end, size_t *bytes_read)
+{
+ ssize_t retval = 0;
+ size_t num_bytes;
+
+ *end = 0;
+ *bytes_read = 0;
+ if (length == 0)
+ return 0;
+
+ clear_bit(DEV_CLEAR_BN, &priv->state);
+
+ // transfer data (except for last byte)
+ if (length > 1) {
+ if (priv->eos_flags & REOS)
+ tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL);
+ else
+ tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_EOI);
+ // PIO transfer
+ retval = pio_read(board, priv, buffer, length - 1, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+ buffer += num_bytes;
+ length -= num_bytes;
+ }
+ // read last bytes if we havn't received an END yet
+ if (*end == 0) {
+ // make sure we holdoff after last byte read
+ tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL);
+ retval = pio_read(board, priv, buffer, length, end, &num_bytes);
+ *bytes_read += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ return 0;
+}
+EXPORT_SYMBOL(tms9914_read);
+
+static int pio_write_wait(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ // wait until next byte is ready to be sent
+ if (wait_event_interruptible(board->wait,
+ test_bit(WRITE_READY_BN, &priv->state) ||
+ test_bit(BUS_ERROR_BN, &priv->state) ||
+ test_bit(DEV_CLEAR_BN, &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted!\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ return -ETIMEDOUT;
+ if (test_bit(BUS_ERROR_BN, &priv->state))
+ return -EIO;
+ if (test_bit(DEV_CLEAR_BN, &priv->state))
+ return -EINTR;
+
+ return 0;
+}
+
+static int pio_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written)
+{
+ ssize_t retval = 0;
+ unsigned long flags;
+
+ *bytes_written = 0;
+ while (*bytes_written < length) {
+ retval = pio_write_wait(board, priv);
+ if (retval < 0)
+ break;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ clear_bit(WRITE_READY_BN, &priv->state);
+ write_byte(priv, buffer[(*bytes_written)++], CDOR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ }
+ retval = pio_write_wait(board, priv);
+ if (retval < 0)
+ return retval;
+
+ return length;
+}
+
+int tms9914_write(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written)
+{
+ ssize_t retval = 0;
+
+ *bytes_written = 0;
+ if (length == 0)
+ return 0;
+
+ clear_bit(BUS_ERROR_BN, &priv->state);
+ clear_bit(DEV_CLEAR_BN, &priv->state);
+
+ if (send_eoi)
+ length-- ; /* save the last byte for sending EOI */
+
+ if (length > 0) {
+ size_t num_bytes;
+ // PIO transfer
+ retval = pio_write(board, priv, buffer, length, &num_bytes);
+ *bytes_written += num_bytes;
+ if (retval < 0)
+ return retval;
+ }
+ if (send_eoi) {
+ size_t num_bytes;
+ /*send EOI */
+ write_byte(priv, AUX_SEOI, AUXCR);
+
+ retval = pio_write(board, priv, &buffer[*bytes_written], 1, &num_bytes);
+ *bytes_written += num_bytes;
+ }
+ return retval;
+}
+EXPORT_SYMBOL(tms9914_write);
+
+static void check_my_address_state(gpib_board_t *board, struct tms9914_priv *priv, int cmd_byte)
+{
+ if (cmd_byte == MLA(board->pad)) {
+ priv->primary_listen_addressed = 1;
+ // become active listener
+ if (board->sad < 0)
+ write_byte(priv, AUX_LON | AUX_CS, AUXCR);
+ } else if (board->sad >= 0 && priv->primary_listen_addressed &&
+ cmd_byte == MSA(board->sad)) {
+ // become active listener
+ write_byte(priv, AUX_LON | AUX_CS, AUXCR);
+ } else if (cmd_byte != MLA(board->pad) && (cmd_byte & 0xe0) == LAD) {
+ priv->primary_listen_addressed = 0;
+ } else if (cmd_byte == UNL) {
+ priv->primary_listen_addressed = 0;
+ write_byte(priv, AUX_LON, AUXCR);
+ } else if (cmd_byte == MTA(board->pad)) {
+ priv->primary_talk_addressed = 1;
+ if (board->sad < 0)
+ //make active talker
+ write_byte(priv, AUX_TON | AUX_CS, AUXCR);
+ } else if (board->sad >= 0 && priv->primary_talk_addressed &&
+ cmd_byte == MSA(board->sad)) {
+ // become active talker
+ write_byte(priv, AUX_TON | AUX_CS, AUXCR);
+ } else if (cmd_byte != MTA(board->pad) && (cmd_byte & 0xe0) == TAD) {
+ // Other Talk Address
+ priv->primary_talk_addressed = 0;
+ write_byte(priv, AUX_TON, AUXCR);
+ } else if (cmd_byte == UNT) {
+ priv->primary_talk_addressed = 0;
+ write_byte(priv, AUX_TON, AUXCR);
+ }
+}
+
+int tms9914_command(gpib_board_t *board, struct tms9914_priv *priv, uint8_t *buffer,
+ size_t length, size_t *bytes_written)
+{
+ int retval = 0;
+ unsigned long flags;
+
+ *bytes_written = 0;
+ while (*bytes_written < length) {
+ if (wait_event_interruptible(board->wait,
+ test_bit(COMMAND_READY_BN,
+ &priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_debug("gpib command wait interrupted\n");
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ break;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ clear_bit(COMMAND_READY_BN, &priv->state);
+ write_byte(priv, buffer[*bytes_written], CDOR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ check_my_address_state(board, priv, buffer[*bytes_written]);
+
+ ++(*bytes_written);
+ }
+ // wait until last command byte is written
+ if (wait_event_interruptible(board->wait,
+ test_bit(COMMAND_READY_BN,
+ &priv->state) || test_bit(TIMO_NUM, &board->status)))
+ retval = -ERESTARTSYS;
+ if (test_bit(TIMO_NUM, &board->status))
+ retval = -ETIMEDOUT;
+
+ return retval;
+}
+EXPORT_SYMBOL(tms9914_command);
+
+irqreturn_t tms9914_interrupt(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ int status0, status1;
+
+ // read interrupt status (also clears status)
+ status0 = read_byte(priv, ISR0);
+ status1 = read_byte(priv, ISR1);
+ return tms9914_interrupt_have_status(board, priv, status0, status1);
+}
+EXPORT_SYMBOL(tms9914_interrupt);
+
+irqreturn_t tms9914_interrupt_have_status(gpib_board_t *board, struct tms9914_priv *priv,
+ int status0, int status1)
+{
+ // record reception of END
+ if (status0 & HR_END)
+ set_bit(RECEIVED_END_BN, &priv->state);
+ // get incoming data in PIO mode
+ if ((status0 & HR_BI))
+ set_bit(READ_READY_BN, &priv->state);
+ if ((status0 & HR_BO)) {
+ if (read_byte(priv, ADSR) & HR_ATN)
+ set_bit(COMMAND_READY_BN, &priv->state);
+ else
+ set_bit(WRITE_READY_BN, &priv->state);
+ }
+
+ if (status0 & HR_SPAS) {
+ priv->spoll_status &= ~request_service_bit;
+ write_byte(priv, priv->spoll_status, SPMR);
+ //FIXME: set SPOLL status bit
+ }
+ // record service request in status
+ if (status1 & HR_SRQ)
+ set_bit(SRQI_NUM, &board->status);
+ // have been addressed (with secondary addressing disabled)
+ if (status1 & HR_MA)
+ // clear dac holdoff
+ write_byte(priv, AUX_VAL, AUXCR);
+ // unrecognized command received
+ if (status1 & HR_UNC) {
+ unsigned short command_byte = read_byte(priv, CPTR) & gpib_command_mask;
+
+ switch (command_byte) {
+ case PPConfig:
+ priv->ppoll_configure_state = 1;
+ /* AUX_PTS generates another UNC interrupt on the next command byte
+ * if it is in the secondary address group (such as PPE and PPD).
+ */
+ write_byte(priv, AUX_PTS, AUXCR);
+ write_byte(priv, AUX_VAL, AUXCR);
+ break;
+ case PPU:
+ tms9914_parallel_poll_configure(board, priv, command_byte);
+ write_byte(priv, AUX_VAL, AUXCR);
+ break;
+ default:
+ if (is_PPE(command_byte) || is_PPD(command_byte)) {
+ if (priv->ppoll_configure_state) {
+ tms9914_parallel_poll_configure(board, priv, command_byte);
+ write_byte(priv, AUX_VAL, AUXCR);
+ } else {// bad parallel poll configure byte
+ // clear dac holdoff
+ write_byte(priv, AUX_INVAL, AUXCR);
+ }
+ } else {
+ // printk("tms9914: unrecognized gpib command pass thru 0x%x\n",
+ // command_byte);
+ // clear dac holdoff
+ write_byte(priv, AUX_INVAL, AUXCR);
+ }
+ break;
+ }
+
+ if (in_primary_command_group(command_byte) && command_byte != PPConfig)
+ priv->ppoll_configure_state = 0;
+ }
+
+ if (status1 & HR_ERR) {
+ dev_dbg(board->gpib_dev, "gpib bus error\n");
+ set_bit(BUS_ERROR_BN, &priv->state);
+ }
+
+ if (status1 & HR_IFC) {
+ push_gpib_event(board, EventIFC);
+ clear_bit(CIC_NUM, &board->status);
+ }
+
+ if (status1 & HR_GET) {
+ push_gpib_event(board, EventDevTrg);
+ // clear dac holdoff
+ write_byte(priv, AUX_VAL, AUXCR);
+ }
+
+ if (status1 & HR_DCAS) {
+ push_gpib_event(board, EventDevClr);
+ // clear dac holdoff
+ write_byte(priv, AUX_VAL, AUXCR);
+ set_bit(DEV_CLEAR_BN, &priv->state);
+ }
+
+ // check for being addressed with secondary addressing
+ if (status1 & HR_APT) {
+ if (board->sad < 0)
+ pr_err("tms9914: bug, APT interrupt without secondary addressing?\n");
+ if ((read_byte(priv, CPTR) & gpib_command_mask) == MSA(board->sad))
+ write_byte(priv, AUX_VAL, AUXCR);
+ else
+ write_byte(priv, AUX_INVAL, AUXCR);
+ }
+
+ if ((status0 & priv->imr0_bits) || (status1 & priv->imr1_bits)) {
+// dev_dbg(board->gpib_dev, "isr0 0x%x, imr0 0x%x, isr1 0x%x, imr1 0x%x\n",
+// status0, priv->imr0_bits, status1, priv->imr1_bits);
+ update_status_nolock(board, priv);
+ wake_up_interruptible(&board->wait);
+ }
+ return IRQ_HANDLED;
+}
+EXPORT_SYMBOL(tms9914_interrupt_have_status);
+
+void tms9914_board_reset(struct tms9914_priv *priv)
+{
+ /* chip reset */
+ write_byte(priv, AUX_CHIP_RESET | AUX_CS, AUXCR);
+
+ /* disable all interrupts */
+ priv->imr0_bits = 0;
+ write_byte(priv, priv->imr0_bits, IMR0);
+ priv->imr1_bits = 0;
+ write_byte(priv, priv->imr1_bits, IMR1);
+ write_byte(priv, AUX_DAI | AUX_CS, AUXCR);
+
+ /* clear registers by reading */
+ read_byte(priv, CPTR);
+ read_byte(priv, ISR0);
+ read_byte(priv, ISR1);
+
+ write_byte(priv, 0, SPMR);
+
+ /* parallel poll unconfigure */
+ write_byte(priv, 0, PPR);
+ // request for data holdoff
+ tms9914_set_holdoff_mode(priv, TMS9914_HOLDOFF_ALL);
+}
+EXPORT_SYMBOL_GPL(tms9914_board_reset);
+
+void tms9914_online(gpib_board_t *board, struct tms9914_priv *priv)
+{
+ /* set GPIB address */
+ tms9914_primary_address(board, priv, board->pad);
+ tms9914_secondary_address(board, priv, board->sad, board->sad >= 0);
+
+ // enable tms9914 interrupts
+ priv->imr0_bits |= HR_MACIE | HR_RLCIE | HR_ENDIE | HR_BOIE | HR_BIIE |
+ HR_SPASIE;
+ priv->imr1_bits |= HR_MAIE | HR_SRQIE | HR_UNCIE | HR_ERRIE | HR_IFCIE |
+ HR_GETIE | HR_DCASIE;
+ write_byte(priv, priv->imr0_bits, IMR0);
+ write_byte(priv, priv->imr1_bits, IMR1);
+ write_byte(priv, AUX_DAI, AUXCR);
+
+ // turn off reset state
+ write_byte(priv, AUX_CHIP_RESET, AUXCR);
+}
+EXPORT_SYMBOL_GPL(tms9914_online);
+
+#ifdef CONFIG_HAS_IOPORT
+// wrapper for inb
+uint8_t tms9914_ioport_read_byte(struct tms9914_priv *priv, unsigned int register_num)
+{
+ return inb((unsigned long)(priv->iobase) + register_num * priv->offset);
+}
+EXPORT_SYMBOL_GPL(tms9914_ioport_read_byte);
+
+// wrapper for outb
+void tms9914_ioport_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num)
+{
+ outb(data, (unsigned long)(priv->iobase) + register_num * priv->offset);
+ if (register_num == AUXCR)
+ udelay(1);
+}
+EXPORT_SYMBOL_GPL(tms9914_ioport_write_byte);
+#endif
+
+// wrapper for readb
+uint8_t tms9914_iomem_read_byte(struct tms9914_priv *priv, unsigned int register_num)
+{
+ return readb(priv->iobase + register_num * priv->offset);
+}
+EXPORT_SYMBOL_GPL(tms9914_iomem_read_byte);
+
+// wrapper for writeb
+void tms9914_iomem_write_byte(struct tms9914_priv *priv, uint8_t data, unsigned int register_num)
+{
+ writeb(data, priv->iobase + register_num * priv->offset);
+ if (register_num == AUXCR)
+ udelay(1);
+}
+EXPORT_SYMBOL_GPL(tms9914_iomem_write_byte);
+
+static int __init tms9914_init_module(void)
+{
+ return 0;
+}
+
+static void __exit tms9914_exit_module(void)
+{
+}
+
+module_init(tms9914_init_module);
+module_exit(tms9914_exit_module);
+
diff --git a/drivers/staging/gpib/tnt4882/Makefile b/drivers/staging/gpib/tnt4882/Makefile
new file mode 100644
index 000000000000..f767c990db7a
--- /dev/null
+++ b/drivers/staging/gpib/tnt4882/Makefile
@@ -0,0 +1,7 @@
+ccflags-$(CONFIG_GPIB_PCMCIA) := -DGPIB_PCMCIA
+obj-m += tnt4882.o
+
+tnt4882-objs := tnt4882_gpib.o mite.o
+
+
+
diff --git a/drivers/staging/gpib/tnt4882/mite.c b/drivers/staging/gpib/tnt4882/mite.c
new file mode 100644
index 000000000000..0edf34d243e9
--- /dev/null
+++ b/drivers/staging/gpib/tnt4882/mite.c
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2
+
+/*
+ * Hardware driver for NI Mite PCI interface chip,
+ * adapted from COMEDI
+ *
+ * Copyright (C) 1997-8 David A. Schleef
+ * Copyright (C) 2002 Frank Mori Hess
+ *
+ * The PCI-MIO E series driver was originally written by
+ * Tomasz Motylewski <...>, and ported to comedi by ds.
+ *
+ * References for specifications:
+ *
+ * 321747b.pdf Register Level Programmer Manual (obsolete)
+ * 321747c.pdf Register Level Programmer Manual (new)
+ * DAQ-STC reference manual
+ *
+ * Other possibly relevant info:
+ *
+ * 320517c.pdf User manual (obsolete)
+ * 320517f.pdf User manual (new)
+ * 320889a.pdf delete
+ * 320906c.pdf maximum signal ratings
+ * 321066a.pdf about 16x
+ * 321791a.pdf discontinuation of at-mio-16e-10 rev. c
+ * 321808a.pdf about at-mio-16e-10 rev P
+ * 321837a.pdf discontinuation of at-mio-16de-10 rev d
+ * 321838a.pdf about at-mio-16de-10 rev N
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include "mite.h"
+
+#define PCI_MITE_SIZE 4096
+#define PCI_DAQ_SIZE 4096
+
+struct mite_struct *mite_devices;
+
+#define TOP_OF_PAGE(x) ((x) | (~(PAGE_MASK)))
+
+void mite_init(void)
+{
+ struct pci_dev *pcidev;
+ struct mite_struct *mite;
+
+ for (pcidev = pci_get_device(PCI_VENDOR_ID_NATINST, PCI_ANY_ID, NULL);
+ pcidev;
+ pcidev = pci_get_device(PCI_VENDOR_ID_NATINST, PCI_ANY_ID, pcidev)) {
+ mite = kzalloc(sizeof(*mite), GFP_KERNEL);
+ if (!mite)
+ return;
+
+ mite->pcidev = pcidev;
+ pci_dev_get(mite->pcidev);
+ mite->next = mite_devices;
+ mite_devices = mite;
+ }
+}
+
+int mite_setup(struct mite_struct *mite)
+{
+ u32 addr;
+
+ if (pci_enable_device(mite->pcidev)) {
+ pr_err("mite: error enabling mite.\n");
+ return -EIO;
+ }
+ pci_set_master(mite->pcidev);
+ if (pci_request_regions(mite->pcidev, "mite")) {
+ pr_err("mite: failed to request mite io regions.\n");
+ return -EIO;
+ }
+ addr = pci_resource_start(mite->pcidev, 0);
+ mite->mite_phys_addr = addr;
+ mite->mite_io_addr = ioremap(addr, pci_resource_len(mite->pcidev, 0));
+ if (!mite->mite_io_addr) {
+ pr_err("mite: failed to remap mite io memory address.\n");
+ return -ENOMEM;
+ }
+ pr_info("mite: 0x%08lx mapped to %p\n", mite->mite_phys_addr, mite->mite_io_addr);
+ addr = pci_resource_start(mite->pcidev, 1);
+ mite->daq_phys_addr = addr;
+ mite->daq_io_addr = ioremap(mite->daq_phys_addr, pci_resource_len(mite->pcidev, 1));
+ if (!mite->daq_io_addr) {
+ pr_err("mite: failed to remap daq io memory address.\n");
+ return -ENOMEM;
+ }
+ pr_info("mite: daq: 0x%08lx mapped to %p\n", mite->daq_phys_addr, mite->daq_io_addr);
+ writel(mite->daq_phys_addr | WENAB, mite->mite_io_addr + MITE_IODWBSR);
+ mite->used = 1;
+ return 0;
+}
+
+void mite_cleanup(void)
+{
+ struct mite_struct *mite, *next;
+
+ for (mite = mite_devices; mite; mite = next) {
+ next = mite->next;
+ if (mite->pcidev)
+ pci_dev_put(mite->pcidev);
+ kfree(mite);
+ }
+}
+
+void mite_unsetup(struct mite_struct *mite)
+{
+ if (!mite)
+ return;
+ if (mite->mite_io_addr) {
+ iounmap(mite->mite_io_addr);
+ mite->mite_io_addr = NULL;
+ }
+ if (mite->daq_io_addr) {
+ iounmap(mite->daq_io_addr);
+ mite->daq_io_addr = NULL;
+ }
+ if (mite->mite_phys_addr) {
+ pci_release_regions(mite->pcidev);
+ pci_disable_device(mite->pcidev);
+ mite->mite_phys_addr = 0;
+ }
+ mite->used = 0;
+}
+
+void mite_list_devices(void)
+{
+ struct mite_struct *mite, *next;
+
+ pr_info("Available NI PCI device IDs:");
+ if (mite_devices)
+ for (mite = mite_devices; mite; mite = next) {
+ next = mite->next;
+ pr_info(" 0x%04x", mite_device_id(mite));
+ if (mite->used)
+ pr_info("(used)");
+ }
+ pr_info("\n");
+}
+
+int mite_bytes_transferred(struct mite_struct *mite, int chan)
+{
+ int dar, fcr;
+
+ dar = readl(mite->mite_io_addr + MITE_DAR + CHAN_OFFSET(chan));
+ fcr = readl(mite->mite_io_addr + MITE_FCR + CHAN_OFFSET(chan)) & 0x000000FF;
+ return dar - fcr;
+}
+
+int mite_dma_tcr(struct mite_struct *mite)
+{
+ int tcr;
+ int lkar;
+
+ lkar = readl(mite->mite_io_addr + CHAN_OFFSET(0) + MITE_LKAR);
+ tcr = readl(mite->mite_io_addr + CHAN_OFFSET(0) + MITE_TCR);
+ MDPRINTK("lkar=0x%08x tcr=%d\n", lkar, tcr);
+
+ return tcr;
+}
+
+void mite_dma_disarm(struct mite_struct *mite)
+{
+ int chor;
+
+ /* disarm */
+ chor = CHOR_ABORT;
+ writel(chor, mite->mite_io_addr + CHAN_OFFSET(0) + MITE_CHOR);
+}
+
+void mite_dump_regs(struct mite_struct *mite)
+{
+ void *addr = 0;
+ unsigned long temp = 0;
+
+ pr_info("mite address is =0x%p\n", mite->mite_io_addr);
+
+ addr = mite->mite_io_addr + MITE_CHOR + CHAN_OFFSET(0);
+ pr_info("mite status[CHOR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_CHOR_strings,temp);
+ addr = mite->mite_io_addr + MITE_CHCR + CHAN_OFFSET(0);
+ pr_info("mite status[CHCR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_CHCR_strings,temp);
+ addr = mite->mite_io_addr + MITE_TCR + CHAN_OFFSET(0);
+ pr_info("mite status[TCR] at 0x%p =0x%08x\n", addr, readl(addr));
+ addr = mite->mite_io_addr + MITE_MCR + CHAN_OFFSET(0);
+ pr_info("mite status[MCR] at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_MCR_strings,temp);
+ addr = mite->mite_io_addr + MITE_MAR + CHAN_OFFSET(0);
+ pr_info("mite status[MAR] at 0x%p =0x%08x\n", addr, readl(addr));
+ addr = mite->mite_io_addr + MITE_DCR + CHAN_OFFSET(0);
+ pr_info("mite status[DCR] at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_CR_strings,temp);
+ addr = mite->mite_io_addr + MITE_DAR + CHAN_OFFSET(0);
+ pr_info("mite status[DAR] at 0x%p =0x%08x\n", addr, readl(addr));
+ addr = mite->mite_io_addr + MITE_LKCR + CHAN_OFFSET(0);
+ pr_info("mite status[LKCR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_CR_strings,temp);
+ addr = mite->mite_io_addr + MITE_LKAR + CHAN_OFFSET(0);
+ pr_info("mite status[LKAR]at 0x%p =0x%08x\n", addr, readl(addr));
+
+ addr = mite->mite_io_addr + MITE_CHSR + CHAN_OFFSET(0);
+ pr_info("mite status[CHSR]at 0x%p =0x%08lx\n", addr, temp = readl(addr));
+ //mite_decode(mite_CHSR_strings,temp);
+ addr = mite->mite_io_addr + MITE_FCR + CHAN_OFFSET(0);
+ pr_info("mite status[FCR] at 0x%p =0x%08x\n\n", addr, readl(addr));
+}
+
diff --git a/drivers/staging/gpib/tnt4882/mite.h b/drivers/staging/gpib/tnt4882/mite.h
new file mode 100644
index 000000000000..6454d069b8cc
--- /dev/null
+++ b/drivers/staging/gpib/tnt4882/mite.h
@@ -0,0 +1,243 @@
+/* SPDX-License-Identifier: GPL-2 */
+
+/*
+ * Hardware driver for NI Mite PCI interface chip
+ *
+ * Copyright (C) 1999 David A. Schleef <ds@stm.lbl.gov>
+ */
+
+#ifndef _MITE_H_
+#define _MITE_H_
+
+#include <linux/pci.h>
+
+#define PCI_VENDOR_ID_NATINST 0x1093
+
+//#define DEBUG_MITE
+
+#ifdef DEBUG_MITE
+#define MDPRINTK(format, args...) pr_debug(format, ## args)
+#else
+#define MDPRINTK(args...)
+#endif
+
+#define MITE_RING_SIZE 3000
+struct mite_dma_chain {
+ u32 count;
+ u32 addr;
+ u32 next;
+};
+
+struct mite_struct {
+ struct mite_struct *next;
+ int used;
+
+ struct pci_dev *pcidev;
+ unsigned long mite_phys_addr;
+ void *mite_io_addr;
+ unsigned long daq_phys_addr;
+ void *daq_io_addr;
+
+ int DMA_CheckNearEnd;
+
+ struct mite_dma_chain ring[MITE_RING_SIZE];
+};
+
+extern struct mite_struct *mite_devices;
+
+extern inline unsigned int mite_irq(struct mite_struct *mite)
+{
+ return mite->pcidev->irq;
+};
+
+extern inline unsigned int mite_device_id(struct mite_struct *mite)
+{
+ return mite->pcidev->device;
+};
+
+void mite_init(void);
+void mite_cleanup(void);
+int mite_setup(struct mite_struct *mite);
+void mite_unsetup(struct mite_struct *mite);
+void mite_list_devices(void);
+
+int mite_dma_tcr(struct mite_struct *mite);
+
+void mite_dma_arm(struct mite_struct *mite);
+void mite_dma_disarm(struct mite_struct *mite);
+
+void mite_dump_regs(struct mite_struct *mite);
+void mite_setregs(struct mite_struct *mite, unsigned long ll_start, int chan, int dir);
+int mite_bytes_transferred(struct mite_struct *mite, int chan);
+
+#define CHAN_OFFSET(x) (0x100 * (x))
+
+/* DMA base for chan 0 is 0x500, chan 1 is 0x600 */
+
+#define MITE_CHOR 0x500
+#define CHOR_DMARESET BIT(31)
+#define CHOR_SET_SEND_TC BIT(11)
+#define CHOR_CLR_SEND_TC BIT(10)
+#define CHOR_SET_LPAUSE BIT(9)
+#define CHOR_CLR_LPAUSE BIT(8)
+#define CHOR_CLRDONE BIT(7)
+#define CHOR_CLRRB BIT(6)
+#define CHOR_CLRLC BIT(5)
+#define CHOR_FRESET BIT(4)
+#define CHOR_ABORT BIT(3)
+#define CHOR_STOP BIT(2)
+#define CHOR_CONT BIT(1)
+#define CHOR_START BIT(0)
+#define CHOR_PON (CHOR_CLR_SEND_TC | CHOR_CLR_LPAUSE)
+
+#define MITE_CHCR 0x504
+#define CHCR_SET_DMA_IE BIT(31)
+#define CHCR_CLR_DMA_IE BIT(30)
+#define CHCR_SET_LINKP_IE BIT(29)
+#define CHCR_CLR_LINKP_IE BIT(28)
+#define CHCR_SET_SAR_IE BIT(27)
+#define CHCR_CLR_SAR_IE BIT(26)
+#define CHCR_SET_DONE_IE BIT(25)
+#define CHCR_CLR_DONE_IE BIT(24)
+#define CHCR_SET_MRDY_IE BIT(23)
+#define CHCR_CLR_MRDY_IE BIT(22)
+#define CHCR_SET_DRDY_IE BIT(21)
+#define CHCR_CLR_DRDY_IE BIT(20)
+#define CHCR_SET_LC_IE BIT(19)
+#define CHCR_CLR_LC_IE BIT(18)
+#define CHCR_SET_CONT_RB_IE BIT(17)
+#define CHCR_CLR_CONT_RB_IE BIT(16)
+#define CHCR_FIFODIS BIT(15)
+#define CHCR_FIFO_ON 0
+#define CHCR_BURSTEN BIT(14)
+#define CHCR_NO_BURSTEN 0
+#define CHCR_NFTP(x) ((x) << 11)
+#define CHCR_NFTP0 CHCR_NFTP(0)
+#define CHCR_NFTP1 CHCR_NFTP(1)
+#define CHCR_NFTP2 CHCR_NFTP(2)
+#define CHCR_NFTP4 CHCR_NFTP(3)
+#define CHCR_NFTP8 CHCR_NFTP(4)
+#define CHCR_NFTP16 CHCR_NFTP(5)
+#define CHCR_NETP(x) ((x) << 11)
+#define CHCR_NETP0 CHCR_NETP(0)
+#define CHCR_NETP1 CHCR_NETP(1)
+#define CHCR_NETP2 CHCR_NETP(2)
+#define CHCR_NETP4 CHCR_NETP(3)
+#define CHCR_NETP8 CHCR_NETP(4)
+#define CHCR_CHEND1 BIT(5)
+#define CHCR_CHEND0 BIT(4)
+#define CHCR_DIR BIT(3)
+#define CHCR_DEV_TO_MEM CHCR_DIR
+#define CHCR_MEM_TO_DEV 0
+#define CHCR_NORMAL ((0) << 0)
+#define CHCR_CONTINUE ((1) << 0)
+#define CHCR_RINGBUFF ((2) << 0)
+#define CHCR_LINKSHORT ((4) << 0)
+#define CHCR_LINKLONG ((5) << 0)
+#define CHCRPON (CHCR_CLR_DMA_IE | CHCR_CLR_LINKP_IE | CHCR_CLR_SAR_IE | \
+ CHCR_CLR_DONE_IE | CHCR_CLR_MRDY_IE | CHCR_CLR_DRDY_IE | \
+ CHCR_CLR_LC_IE | CHCR_CLR_CONT_IE)
+
+#define MITE_TCR 0x508
+
+/* CR bits */
+#define CR_RL(x) ((x) << 21)
+#define CR_RL0 CR_RL(0)
+#define CR_RL1 CR_RL(1)
+#define CR_RL2 CR_RL(2)
+#define CR_RL4 CR_RL(3)
+#define CR_RL8 CR_RL(4)
+#define CR_RL16 CR_RL(5)
+#define CR_RL32 CR_RL(6)
+#define CR_RL64 CR_RL(7)
+#define CR_RD(x) ((x) << 19)
+#define CR_RD0 CR_RD(0)
+#define CR_RD32 CR_RD(1)
+#define CR_RD512 CR_RD(2)
+#define CR_RD8192 CR_RD(3)
+#define CR_REQS(x) ((x) << 16)
+#define CR_REQSDRQ0 CR_REQS(4)
+#define CR_REQSDRQ1 CR_REQS(5)
+#define CR_REQSDRQ2 CR_REQS(6)
+#define CR_REQSDRQ3 CR_REQS(7)
+#define CR_ASEQX(x) ((x) << 10)
+#define CR_ASEQX0 CR_ASEQX(0)
+#define CR_ASEQDONT CR_ASEQX0
+#define CR_ASEQXP1 CR_ASEQX(1)
+#define CR_ASEQUP CR_ASEQXP1
+#define CR_ASEQXP2 CR_ASEQX(2)
+#define CR_ASEQDOWN CR_ASEQXP2
+#define CR_ASEQXP4 CR_ASEQX(3)
+#define CR_ASEQXP8 CR_ASEQX(4)
+#define CR_ASEQXP16 CR_ASEQX(5)
+#define CR_ASEQXP32 CR_ASEQX(6)
+#define CR_ASEQXP64 CR_ASEQX(7)
+#define CR_ASEQXM1 CR_ASEQX(9)
+#define CR_ASEQXM2 CR_ASEQX(10)
+#define CR_ASEQXM4 CR_ASEQX(11)
+#define CR_ASEQXM8 CR_ASEQX(12)
+#define CR_ASEQXM16 CR_ASEQX(13)
+#define CR_ASEQXM32 CR_ASEQX(14)
+#define CR_ASEQXM64 CR_ASEQX(15)
+#define CR_PSIZEBYTE BIT(8)
+#define CR_PSIZEHALF (2 << 8)
+#define CR_PSIZEWORD (3 << 8)
+#define CR_PORTCPU (0 << 6)
+#define CR_PORTIO BIT(6)
+#define CR_PORTVXI (2 << 6)
+#define CR_PORTMXI (3 << 6)
+#define CR_AMDEVICE BIT(0)
+
+#define CHSR_INT 0x80000000
+#define CHSR_DONE 0x02000000
+#define CHSR_LINKC 0x00080000
+
+#define MITE_MCR 0x50c
+#define MCRPON 0
+
+#define MITE_MAR 0x510
+
+#define MITE_DCR 0x514
+#define DCR_NORMAL BIT(29)
+#define DCRPON 0
+
+#define MITE_DAR 0x518
+
+#define MITE_LKCR 0x51c
+
+#define MITE_LKAR 0x520
+#define MITE_LLKAR 0x524
+#define MITE_BAR 0x528
+#define MITE_BCR 0x52c
+#define MITE_SAR 0x530
+#define MITE_WSCR 0x534
+#define MITE_WSER 0x538
+#define MITE_CHSR 0x53c
+#define MITE_FCR 0x540
+
+#define MITE_FIFO 0x80
+#define MITE_FIFOEND 0xff
+
+#define MITE_AMRAM 0x00
+#define MITE_AMDEVICE 0x01
+#define MITE_AMHOST_A32_SINGLE 0x09
+#define MITE_AMHOST_A24_SINGLE 0x39
+#define MITE_AMHOST_A16_SINGLE 0x29
+#define MITE_AMHOST_A32_BLOCK 0x0b
+#define MITE_AMHOST_A32D64_BLOCK 0x08
+#define MITE_AMHOST_A24_BLOCK 0x3b
+
+enum mite_registers {
+ MITE_IODWBSR = 0xc0, //IO Device Window Base Size Register
+ MITE_CSIGR = 0x460, //chip signature
+ MITE_IODWBSR_1 = 0xc4, // IO Device Window Base Size Register 1 (used by 6602 boards)
+ MITE_IODWCR_1 = 0xf4
+};
+
+enum MITE_IODWBSR_bits {
+ WENAB = 0x80, // window enable
+ WENAB_6602 = 0x8c // window enable for 6602 boards
+};
+
+#endif
+
diff --git a/drivers/staging/gpib/tnt4882/tnt4882_gpib.c b/drivers/staging/gpib/tnt4882/tnt4882_gpib.c
new file mode 100644
index 000000000000..e49a952fa0d8
--- /dev/null
+++ b/drivers/staging/gpib/tnt4882/tnt4882_gpib.c
@@ -0,0 +1,1874 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/***************************************************************************
+ * National Instruments boards using tnt4882 or compatible chips (at-gpib, etc).
+ * copyright : (C) 2001, 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#include <linux/ioport.h>
+#include <linux/sched.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/isapnp.h>
+
+#include "nec7210.h"
+#include "gpibP.h"
+#include "mite.h"
+#include "tnt4882_registers.h"
+
+static const int ISAPNP_VENDOR_ID_NI = ISAPNP_VENDOR('N', 'I', 'C');
+static const int ISAPNP_ID_NI_ATGPIB_TNT = 0xc601;
+enum {
+ PCI_DEVICE_ID_NI_GPIB = 0xc801,
+ PCI_DEVICE_ID_NI_GPIB_PLUS = 0xc811,
+ PCI_DEVICE_ID_NI_GPIB_PLUS2 = 0x71ad,
+ PCI_DEVICE_ID_NI_PXIGPIB = 0xc821,
+ PCI_DEVICE_ID_NI_PMCGPIB = 0xc831,
+ PCI_DEVICE_ID_NI_PCIEGPIB = 0x70cf,
+ PCI_DEVICE_ID_NI_PCIE2GPIB = 0x710e,
+// Measurement Computing PCI-488 same design as PCI-GPIB with TNT5004
+ PCI_DEVICE_ID_MC_PCI488 = 0x7259,
+ PCI_DEVICE_ID_CEC_NI_GPIB = 0x7258
+};
+
+// struct which defines private_data for tnt4882 devices
+struct tnt4882_priv {
+ struct nec7210_priv nec7210_priv;
+ struct mite_struct *mite;
+ struct pnp_dev *pnp_dev;
+ unsigned int irq;
+ unsigned short imr0_bits;
+ unsigned short imr3_bits;
+ unsigned short auxg_bits; // bits written to auxiliary register G
+ void (*io_writeb)(unsigned int value, void *address);
+ void (*io_writew)(unsigned int value, void *address);
+ unsigned int (*io_readb)(void *address);
+ unsigned int (*io_readw)(void *address);
+};
+
+// interface functions
+static int tnt4882_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read);
+static int tnt4882_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int *end, size_t *bytes_read);
+static int tnt4882_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+static int tnt4882_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, size_t *bytes_written);
+static int tnt4882_command(gpib_board_t *board, uint8_t *buffer, size_t length,
+ size_t *bytes_written);
+static int tnt4882_command_unaccel(gpib_board_t *board, uint8_t *buffer,
+ size_t length, size_t *bytes_written);
+static int tnt4882_take_control(gpib_board_t *board, int synchronous);
+static int tnt4882_go_to_standby(gpib_board_t *board);
+static void tnt4882_request_system_control(gpib_board_t *board, int request_control);
+static void tnt4882_interface_clear(gpib_board_t *board, int assert);
+static void tnt4882_remote_enable(gpib_board_t *board, int enable);
+static int tnt4882_enable_eos(gpib_board_t *board, uint8_t eos_byte, int
+ compare_8_bits);
+static void tnt4882_disable_eos(gpib_board_t *board);
+static unsigned int tnt4882_update_status(gpib_board_t *board, unsigned int clear_mask);
+static int tnt4882_primary_address(gpib_board_t *board, unsigned int address);
+static int tnt4882_secondary_address(gpib_board_t *board, unsigned int address,
+ int enable);
+static int tnt4882_parallel_poll(gpib_board_t *board, uint8_t *result);
+static void tnt4882_parallel_poll_configure(gpib_board_t *board, uint8_t config);
+static void tnt4882_parallel_poll_response(gpib_board_t *board, int ist);
+static void tnt4882_serial_poll_response(gpib_board_t *board, uint8_t status);
+static uint8_t tnt4882_serial_poll_status(gpib_board_t *board);
+static int tnt4882_line_status(const gpib_board_t *board);
+static unsigned int tnt4882_t1_delay(gpib_board_t *board, unsigned int nano_sec);
+static void tnt4882_return_to_local(gpib_board_t *board);
+
+// interrupt service routines
+static irqreturn_t tnt4882_internal_interrupt(gpib_board_t *board);
+static irqreturn_t tnt4882_interrupt(int irq, void *arg);
+
+// utility functions
+static int tnt4882_allocate_private(gpib_board_t *board);
+static void tnt4882_free_private(gpib_board_t *board);
+static void tnt4882_init(struct tnt4882_priv *tnt_priv, const gpib_board_t *board);
+static void tnt4882_board_reset(struct tnt4882_priv *tnt_priv, gpib_board_t *board);
+
+// register offset for nec7210 compatible registers
+static const int atgpib_reg_offset = 2;
+
+// number of ioports used
+static const int atgpib_iosize = 32;
+
+/* paged io */
+static inline unsigned int tnt_paged_readb(struct tnt4882_priv *priv, unsigned long offset)
+{
+ priv->io_writeb(AUX_PAGEIN, priv->nec7210_priv.iobase + AUXMR * priv->nec7210_priv.offset);
+ udelay(1);
+ return priv->io_readb(priv->nec7210_priv.iobase + offset);
+}
+
+static inline void tnt_paged_writeb(struct tnt4882_priv *priv, unsigned int value,
+ unsigned long offset)
+{
+ priv->io_writeb(AUX_PAGEIN, priv->nec7210_priv.iobase + AUXMR * priv->nec7210_priv.offset);
+ udelay(1);
+ priv->io_writeb(value, priv->nec7210_priv.iobase + offset);
+}
+
+/* readb/writeb wrappers */
+static inline unsigned short tnt_readb(struct tnt4882_priv *priv, unsigned long offset)
+{
+ void *address = priv->nec7210_priv.iobase + offset;
+ unsigned long flags;
+ unsigned short retval;
+ spinlock_t *register_lock = &priv->nec7210_priv.register_page_lock;
+
+ spin_lock_irqsave(register_lock, flags);
+ switch (offset) {
+ case CSR:
+ case SASR:
+ case ISR0:
+ case BSR:
+ switch (priv->nec7210_priv.type) {
+ case TNT4882:
+ case TNT5004:
+ retval = priv->io_readb(address);
+ break;
+ case NAT4882:
+ retval = tnt_paged_readb(priv, offset - tnt_pagein_offset);
+ break;
+ case NEC7210:
+ retval = 0;
+ break;
+ default:
+ pr_err("tnt4882: bug! unsupported ni_chipset\n");
+ retval = 0;
+ break;
+ }
+ break;
+ default:
+ retval = priv->io_readb(address);
+ break;
+ }
+ spin_unlock_irqrestore(register_lock, flags);
+ return retval;
+}
+
+static inline void tnt_writeb(struct tnt4882_priv *priv, unsigned short value, unsigned long offset)
+{
+ void *address = priv->nec7210_priv.iobase + offset;
+ unsigned long flags;
+ spinlock_t *register_lock = &priv->nec7210_priv.register_page_lock;
+
+ spin_lock_irqsave(register_lock, flags);
+ switch (offset) {
+ case KEYREG:
+ case IMR0:
+ case BCR:
+ switch (priv->nec7210_priv.type) {
+ case TNT4882:
+ case TNT5004:
+ priv->io_writeb(value, address);
+ break;
+ case NAT4882:
+ tnt_paged_writeb(priv, value, offset - tnt_pagein_offset);
+ break;
+ case NEC7210:
+ break;
+ default:
+ pr_err("tnt4882: bug! unsupported ni_chipset\n");
+ break;
+ }
+ break;
+ default:
+ priv->io_writeb(value, address);
+ break;
+ }
+ spin_unlock_irqrestore(register_lock, flags);
+}
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("GPIB driver for National Instruments boards using tnt4882 or compatible chips");
+
+int tnt4882_line_status(const gpib_board_t *board)
+{
+ int status = ValidALL;
+ int bcsr_bits;
+ struct tnt4882_priv *tnt_priv;
+
+ tnt_priv = board->private_data;
+
+ bcsr_bits = tnt_readb(tnt_priv, BSR);
+
+ if (bcsr_bits & BCSR_REN_BIT)
+ status |= BusREN;
+ if (bcsr_bits & BCSR_IFC_BIT)
+ status |= BusIFC;
+ if (bcsr_bits & BCSR_SRQ_BIT)
+ status |= BusSRQ;
+ if (bcsr_bits & BCSR_EOI_BIT)
+ status |= BusEOI;
+ if (bcsr_bits & BCSR_NRFD_BIT)
+ status |= BusNRFD;
+ if (bcsr_bits & BCSR_NDAC_BIT)
+ status |= BusNDAC;
+ if (bcsr_bits & BCSR_DAV_BIT)
+ status |= BusDAV;
+ if (bcsr_bits & BCSR_ATN_BIT)
+ status |= BusATN;
+
+ return status;
+}
+
+unsigned int tnt4882_t1_delay(gpib_board_t *board, unsigned int nano_sec)
+{
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+ unsigned int retval;
+
+ retval = nec7210_t1_delay(board, nec_priv, nano_sec);
+ if (nec_priv->type == NEC7210)
+ return retval;
+
+ if (nano_sec <= 350) {
+ tnt_writeb(tnt_priv, MSTD, KEYREG);
+ retval = 350;
+ } else {
+ tnt_writeb(tnt_priv, 0, KEYREG);
+ }
+ if (nano_sec > 500 && nano_sec <= 1100) {
+ write_byte(nec_priv, AUXRI | USTD, AUXMR);
+ retval = 1100;
+ } else {
+ write_byte(nec_priv, AUXRI, AUXMR);
+ }
+ return retval;
+}
+
+static int fifo_word_available(struct tnt4882_priv *tnt_priv)
+{
+ int status2;
+ int retval;
+
+ status2 = tnt_readb(tnt_priv, STS2);
+ retval = (status2 & AEFN) && (status2 & BEFN);
+
+ return retval;
+}
+
+static int fifo_byte_available(struct tnt4882_priv *tnt_priv)
+{
+ int status2;
+ int retval;
+
+ status2 = tnt_readb(tnt_priv, STS2);
+ retval = (status2 & AEFN) || (status2 & BEFN);
+
+ return retval;
+}
+
+static int fifo_xfer_done(struct tnt4882_priv *tnt_priv)
+{
+ int status1;
+ int retval;
+
+ status1 = tnt_readb(tnt_priv, STS1);
+ retval = status1 & (S_DONE | S_HALT);
+
+ return retval;
+}
+
+static int drain_fifo_words(struct tnt4882_priv *tnt_priv, uint8_t *buffer, int num_bytes)
+{
+ int count = 0;
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+
+ while (fifo_word_available(tnt_priv) && count + 2 <= num_bytes) {
+ short word;
+
+ word = tnt_priv->io_readw(nec_priv->iobase + FIFOB);
+ buffer[count++] = word & 0xff;
+ buffer[count++] = (word >> 8) & 0xff;
+ }
+ return count;
+}
+
+static void tnt4882_release_holdoff(gpib_board_t *board, struct tnt4882_priv *tnt_priv)
+{
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+ unsigned short sasr_bits;
+
+ sasr_bits = tnt_readb(tnt_priv, SASR);
+
+ /*tnt4882 not in one-chip mode won't always release holdoff unless we
+ * are in the right mode when release handshake command is given
+ */
+ if (sasr_bits & AEHS_BIT) /* holding off due to holdoff on end mode*/ {
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDE);
+ write_byte(nec_priv, AUX_FH, AUXMR);
+ } else if (sasr_bits & ANHS1_BIT) { /* held off due to holdoff on all data mode*/
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDA);
+ write_byte(nec_priv, AUX_FH, AUXMR);
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDE);
+ } else { /* held off due to holdoff immediately command */
+ nec7210_set_handshake_mode(board, nec_priv, HR_HLDE);
+ write_byte(nec_priv, AUX_FH, AUXMR);
+ }
+}
+
+int tnt4882_accel_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end,
+ size_t *bytes_read)
+{
+ size_t count = 0;
+ ssize_t retval = 0;
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+ unsigned int bits;
+ s32 hw_count;
+ unsigned long flags;
+
+ *bytes_read = 0;
+ // FIXME: really, DEV_CLEAR_BN should happen elsewhere to prevent race
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state);
+ clear_bit(ADR_CHANGE_BN, &nec_priv->state);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_ENDIE, HR_ENDIE);
+ if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004)
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, HR_DMAI);
+ else
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ tnt_writeb(tnt_priv, nec_priv->auxa_bits | HR_HLDA, CCR);
+ bits = TNT_B_16BIT | TNT_IN | TNT_CCEN;
+ tnt_writeb(tnt_priv, bits, CFG);
+ tnt_writeb(tnt_priv, RESET_FIFO, CMDR);
+ udelay(1);
+ // load 2's complement of count into hardware counters
+ hw_count = -length;
+ tnt_writeb(tnt_priv, hw_count & 0xff, CNT0);
+ tnt_writeb(tnt_priv, (hw_count >> 8) & 0xff, CNT1);
+ tnt_writeb(tnt_priv, (hw_count >> 16) & 0xff, CNT2);
+ tnt_writeb(tnt_priv, (hw_count >> 24) & 0xff, CNT3);
+
+ tnt4882_release_holdoff(board, tnt_priv);
+
+ tnt_writeb(tnt_priv, GO, CMDR);
+ udelay(1);
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ tnt_priv->imr3_bits |= HR_DONE | HR_NEF;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ while (count + 2 <= length &&
+ test_bit(RECEIVED_END_BN, &nec_priv->state) == 0 &&
+ fifo_xfer_done(tnt_priv) == 0) {
+ // wait until a word is ready
+ if (wait_event_interruptible(board->wait,
+ fifo_word_available(tnt_priv) ||
+ fifo_xfer_done(tnt_priv) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(ADR_CHANGE_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_err("tnt4882: read interrupted\n");
+ retval = -ERESTARTSYS;
+ break;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ //pr_info("tnt4882: minor %i read timed out\n", board->minor);
+ retval = -ETIMEDOUT;
+ break;
+ }
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) {
+ pr_err("tnt4882: device clear interrupted read\n");
+ retval = -EINTR;
+ break;
+ }
+ if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) {
+ pr_err("tnt4882: address change interrupted read\n");
+ retval = -EINTR;
+ break;
+ }
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ count += drain_fifo_words(tnt_priv, &buffer[count], length - count);
+ tnt_priv->imr3_bits |= HR_NEF;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ if (need_resched())
+ schedule();
+ }
+ // wait for last byte
+ if (count < length) {
+ spin_lock_irqsave(&board->spinlock, flags);
+ tnt_priv->imr3_bits |= HR_DONE | HR_NEF;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ if (wait_event_interruptible(board->wait,
+ fifo_xfer_done(tnt_priv) ||
+ test_bit(RECEIVED_END_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(ADR_CHANGE_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ pr_err("tnt4882: read interrupted\n");
+ retval = -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status))
+ //pr_info("tnt4882: read timed out\n");
+ retval = -ETIMEDOUT;
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) {
+ pr_err("tnt4882: device clear interrupted read\n");
+ retval = -EINTR;
+ }
+ if (test_bit(ADR_CHANGE_BN, &nec_priv->state)) {
+ pr_err("tnt4882: address change interrupted read\n");
+ retval = -EINTR;
+ }
+ count += drain_fifo_words(tnt_priv, &buffer[count], length - count);
+ if (fifo_byte_available(tnt_priv) && count < length)
+ buffer[count++] = tnt_readb(tnt_priv, FIFOB);
+ }
+ if (count < length)
+ tnt_writeb(tnt_priv, STOP, CMDR);
+ udelay(1);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_ENDIE, 0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAI, 0);
+ /* force handling of any pending interrupts (seems to be needed
+ * to keep interrupts from getting hosed, plus for syncing
+ * with RECEIVED_END below)
+ */
+ tnt4882_internal_interrupt(board);
+ /* RECEIVED_END should be in sync now */
+ if (test_and_clear_bit(RECEIVED_END_BN, &nec_priv->state))
+ *end = 1;
+ if (retval < 0) {
+ // force immediate holdoff
+ write_byte(nec_priv, AUX_HLDI, AUXMR);
+
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+ }
+ *bytes_read = count;
+
+ return retval;
+}
+
+static int fifo_space_available(struct tnt4882_priv *tnt_priv)
+{
+ int status2;
+ int retval;
+
+ status2 = tnt_readb(tnt_priv, STS2);
+ retval = (status2 & AFFN) && (status2 & BFFN);
+
+ return retval;
+}
+
+static unsigned int tnt_transfer_count(struct tnt4882_priv *tnt_priv)
+{
+ unsigned int count = 0;
+
+ count |= tnt_readb(tnt_priv, CNT0) & 0xff;
+ count |= (tnt_readb(tnt_priv, CNT1) << 8) & 0xff00;
+ count |= (tnt_readb(tnt_priv, CNT2) << 16) & 0xff0000;
+ count |= (tnt_readb(tnt_priv, CNT3) << 24) & 0xff000000;
+ // return two's complement
+ return -count;
+};
+
+static int write_wait(gpib_board_t *board, struct tnt4882_priv *tnt_priv,
+ int wait_for_done, int send_commands)
+{
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+
+ if (wait_event_interruptible(board->wait,
+ (!wait_for_done && fifo_space_available(tnt_priv)) ||
+ fifo_xfer_done(tnt_priv) ||
+ test_bit(BUS_ERROR_BN, &nec_priv->state) ||
+ test_bit(DEV_CLEAR_BN, &nec_priv->state) ||
+ test_bit(TIMO_NUM, &board->status))) {
+ dev_dbg(board->gpib_dev, "gpib write interrupted\n");
+ return -ERESTARTSYS;
+ }
+ if (test_bit(TIMO_NUM, &board->status)) {
+ pr_info("tnt4882: write timed out\n");
+ return -ETIMEDOUT;
+ }
+ if (test_and_clear_bit(BUS_ERROR_BN, &nec_priv->state)) {
+ pr_err("tnt4882: write bus error\n");
+ return (send_commands) ? -ENOTCONN : -ECOMM;
+ }
+ if (test_bit(DEV_CLEAR_BN, &nec_priv->state)) {
+ pr_err("tnt4882: device clear interrupted write\n");
+ return -EINTR;
+ }
+ return 0;
+}
+
+static int generic_write(gpib_board_t *board, uint8_t *buffer, size_t length,
+ int send_eoi, int send_commands, size_t *bytes_written)
+{
+ size_t count = 0;
+ ssize_t retval = 0;
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+ unsigned int bits;
+ s32 hw_count;
+ unsigned long flags;
+
+ *bytes_written = 0;
+ // FIXME: really, DEV_CLEAR_BN should happen elsewhere to prevent race
+ clear_bit(DEV_CLEAR_BN, &nec_priv->state);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_ERRIE, HR_ERRIE);
+
+ if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004)
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, HR_DMAO);
+ else
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0);
+
+ tnt_writeb(tnt_priv, RESET_FIFO, CMDR);
+ udelay(1);
+
+ bits = TNT_B_16BIT;
+ if (send_eoi) {
+ bits |= TNT_CCEN;
+ if (nec_priv->type != TNT4882 && nec_priv->type != TNT5004)
+ tnt_writeb(tnt_priv, AUX_SEOI, CCR);
+ }
+ if (send_commands)
+ bits |= TNT_COMMAND;
+ tnt_writeb(tnt_priv, bits, CFG);
+
+ // load 2's complement of count into hardware counters
+ hw_count = -length;
+ tnt_writeb(tnt_priv, hw_count & 0xff, CNT0);
+ tnt_writeb(tnt_priv, (hw_count >> 8) & 0xff, CNT1);
+ tnt_writeb(tnt_priv, (hw_count >> 16) & 0xff, CNT2);
+ tnt_writeb(tnt_priv, (hw_count >> 24) & 0xff, CNT3);
+
+ tnt_writeb(tnt_priv, GO, CMDR);
+ udelay(1);
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ tnt_priv->imr3_bits |= HR_DONE;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ while (count < length) {
+ // wait until byte is ready to be sent
+ retval = write_wait(board, tnt_priv, 0, send_commands);
+ if (retval < 0)
+ break;
+ if (fifo_xfer_done(tnt_priv))
+ break;
+ spin_lock_irqsave(&board->spinlock, flags);
+ while (fifo_space_available(tnt_priv) && count < length) {
+ u16 word;
+
+ word = buffer[count++] & 0xff;
+ if (count < length)
+ word |= (buffer[count++] << 8) & 0xff00;
+ tnt_priv->io_writew(word, nec_priv->iobase + FIFOB);
+ }
+// avoid unnecessary HR_NFF interrupts
+// tnt_priv->imr3_bits |= HR_NFF;
+// tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+
+ if (need_resched())
+ schedule();
+ }
+ // wait last byte has been sent
+ if (retval == 0)
+ retval = write_wait(board, tnt_priv, 1, send_commands);
+
+ tnt_writeb(tnt_priv, STOP, CMDR);
+ udelay(1);
+
+ nec7210_set_reg_bits(nec_priv, IMR1, HR_ERR, 0x0);
+ nec7210_set_reg_bits(nec_priv, IMR2, HR_DMAO, 0x0);
+ /* force handling of any interrupts that happened
+ * while they were masked (this appears to be needed)
+ */
+ tnt4882_internal_interrupt(board);
+ *bytes_written = length - tnt_transfer_count(tnt_priv);
+ return retval;
+}
+
+int tnt4882_accel_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ return generic_write(board, buffer, length, send_eoi, 0, bytes_written);
+}
+
+int tnt4882_command(gpib_board_t *board, uint8_t *buffer, size_t length, size_t *bytes_written)
+{
+ return generic_write(board, buffer, length, 0, 1, bytes_written);
+}
+
+irqreturn_t tnt4882_internal_interrupt(gpib_board_t *board)
+{
+ struct tnt4882_priv *priv = board->private_data;
+ int isr0_bits, isr3_bits, imr3_bits;
+ unsigned long flags;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+
+ nec7210_interrupt(board, &priv->nec7210_priv);
+
+ isr0_bits = tnt_readb(priv, ISR0);
+ isr3_bits = tnt_readb(priv, ISR3);
+ imr3_bits = priv->imr3_bits;
+
+ if (isr0_bits & TNT_IFCI_BIT)
+ push_gpib_event(board, EventIFC);
+ //XXX don't need this wakeup, one below should do?
+// wake_up_interruptible(&board->wait);
+
+ if (isr3_bits & HR_NFF)
+ priv->imr3_bits &= ~HR_NFF;
+ if (isr3_bits & HR_NEF)
+ priv->imr3_bits &= ~HR_NEF;
+ if (isr3_bits & HR_DONE)
+ priv->imr3_bits &= ~HR_DONE;
+ if (isr3_bits & (HR_INTR | HR_TLCI)) {
+ dev_dbg(board->gpib_dev, "tnt4882: minor %i isr0 0x%x imr0 0x%x isr3 0x%x imr3 0x%x\n",
+ board->minor, isr0_bits, priv->imr0_bits, isr3_bits, imr3_bits);
+ tnt_writeb(priv, priv->imr3_bits, IMR3);
+ wake_up_interruptible(&board->wait);
+ }
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return IRQ_HANDLED;
+}
+
+irqreturn_t tnt4882_interrupt(int irq, void *arg)
+{
+ return tnt4882_internal_interrupt(arg);
+}
+
+static int ni_tnt_isa_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ni_nat4882_isa_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ni_nec_isa_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static int ni_pci_attach(gpib_board_t *board, const gpib_board_config_t *config);
+
+static void ni_isa_detach(gpib_board_t *board);
+static void ni_pci_detach(gpib_board_t *board);
+
+#ifdef GPIB_PCMCIA
+static int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static void ni_pcmcia_detach(gpib_board_t *board);
+static int init_ni_gpib_cs(void);
+static void __exit exit_ni_gpib_cs(void);
+#endif
+
+// wrappers for interface functions
+int tnt4882_read(gpib_board_t *board, uint8_t *buffer, size_t length, int *end, size_t *bytes_read)
+{
+ struct tnt4882_priv *priv = board->private_data;
+ struct nec7210_priv *nec_priv = &priv->nec7210_priv;
+ int retval;
+ int dummy;
+
+ retval = nec7210_read(board, &priv->nec7210_priv, buffer, length, end, bytes_read);
+
+ if (retval < 0) { // force immediate holdoff
+ write_byte(nec_priv, AUX_HLDI, AUXMR);
+
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+
+ nec7210_read_data_in(board, nec_priv, &dummy);
+ }
+ return retval;
+}
+
+int tnt4882_write(gpib_board_t *board, uint8_t *buffer, size_t length, int send_eoi,
+ size_t *bytes_written)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_write(board, &priv->nec7210_priv, buffer, length, send_eoi, bytes_written);
+}
+
+int tnt4882_command_unaccel(gpib_board_t *board, uint8_t *buffer,
+ size_t length, size_t *bytes_written)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_command(board, &priv->nec7210_priv, buffer, length, bytes_written);
+}
+
+int tnt4882_take_control(gpib_board_t *board, int synchronous)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_take_control(board, &priv->nec7210_priv, synchronous);
+}
+
+int tnt4882_go_to_standby(gpib_board_t *board)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_go_to_standby(board, &priv->nec7210_priv);
+}
+
+void tnt4882_request_system_control(gpib_board_t *board, int request_control)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ if (request_control) {
+ tnt_writeb(priv, SETSC, CMDR);
+ udelay(1);
+ }
+ nec7210_request_system_control(board, &priv->nec7210_priv, request_control);
+ if (!request_control) {
+ tnt_writeb(priv, CLRSC, CMDR);
+ udelay(1);
+ }
+}
+
+void tnt4882_interface_clear(gpib_board_t *board, int assert)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_interface_clear(board, &priv->nec7210_priv, assert);
+}
+
+void tnt4882_remote_enable(gpib_board_t *board, int enable)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_remote_enable(board, &priv->nec7210_priv, enable);
+}
+
+int tnt4882_enable_eos(gpib_board_t *board, uint8_t eos_byte, int compare_8_bits)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_enable_eos(board, &priv->nec7210_priv, eos_byte, compare_8_bits);
+}
+
+void tnt4882_disable_eos(gpib_board_t *board)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_disable_eos(board, &priv->nec7210_priv);
+}
+
+unsigned int tnt4882_update_status(gpib_board_t *board, unsigned int clear_mask)
+{
+ unsigned long flags;
+ u8 line_status;
+ unsigned int retval;
+ struct tnt4882_priv *priv = board->private_data;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ board->status &= ~clear_mask;
+ retval = nec7210_update_status_nolock(board, &priv->nec7210_priv);
+ /* set / clear SRQ state since it is not cleared by interrupt */
+ line_status = tnt_readb(priv, BSR);
+ if (line_status & BCSR_SRQ_BIT)
+ set_bit(SRQI_NUM, &board->status);
+ else
+ clear_bit(SRQI_NUM, &board->status);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+ return board->status;
+}
+
+int tnt4882_primary_address(gpib_board_t *board, unsigned int address)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_primary_address(board, &priv->nec7210_priv, address);
+}
+
+int tnt4882_secondary_address(gpib_board_t *board, unsigned int address, int enable)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_secondary_address(board, &priv->nec7210_priv, address, enable);
+}
+
+int tnt4882_parallel_poll(gpib_board_t *board, uint8_t *result)
+
+{
+ struct tnt4882_priv *tnt_priv = board->private_data;
+
+ if (tnt_priv->nec7210_priv.type != NEC7210) {
+ tnt_priv->auxg_bits |= RPP2_BIT;
+ write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR);
+ udelay(2); //FIXME use parallel poll timeout
+ *result = read_byte(&tnt_priv->nec7210_priv, CPTR);
+ tnt_priv->auxg_bits &= ~RPP2_BIT;
+ write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR);
+ return 0;
+ } else {
+ return nec7210_parallel_poll(board, &tnt_priv->nec7210_priv, result);
+ }
+}
+
+void tnt4882_parallel_poll_configure(gpib_board_t *board, uint8_t config)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ if (priv->nec7210_priv.type == TNT5004) {
+ /* configure locally */
+ write_byte(&priv->nec7210_priv, AUXRI | 0x4, AUXMR);
+ if (config)
+ /* set response + clear sense */
+ write_byte(&priv->nec7210_priv, PPR | config, AUXMR);
+ else
+ /* disable ppoll */
+ write_byte(&priv->nec7210_priv, PPR | 0x10, AUXMR);
+ } else {
+ nec7210_parallel_poll_configure(board, &priv->nec7210_priv, config);
+ }
+}
+
+void tnt4882_parallel_poll_response(gpib_board_t *board, int ist)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_parallel_poll_response(board, &priv->nec7210_priv, ist);
+}
+
+/* this is just used by the old nec7210 isa interfaces, the newer
+ * boards use tnt4882_serial_poll_response2
+ */
+void tnt4882_serial_poll_response(gpib_board_t *board, uint8_t status)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_serial_poll_response(board, &priv->nec7210_priv, status);
+}
+
+static void tnt4882_serial_poll_response2(gpib_board_t *board, uint8_t status,
+ int new_reason_for_service)
+{
+ struct tnt4882_priv *priv = board->private_data;
+ unsigned long flags;
+ const int MSS = status & request_service_bit;
+ const int reqt = MSS && new_reason_for_service;
+ const int reqf = MSS == 0;
+
+ spin_lock_irqsave(&board->spinlock, flags);
+ if (reqt) {
+ priv->nec7210_priv.srq_pending = 1;
+ clear_bit(SPOLL_NUM, &board->status);
+ } else {
+ if (reqf)
+ priv->nec7210_priv.srq_pending = 0;
+ }
+ if (reqt)
+ /* It may seem like a race to issue reqt before updating
+ * the status byte, but it is not. The chip does not
+ * issue the reqt until the SPMR is written to at
+ * a later time.
+ */
+ write_byte(&priv->nec7210_priv, AUX_REQT, AUXMR);
+ else if (reqf)
+ write_byte(&priv->nec7210_priv, AUX_REQF, AUXMR);
+ /* We need to always zero bit 6 of the status byte before writing it to
+ * the SPMR to insure we are using
+ * serial poll mode SP1, and not accidentally triggering mode SP3.
+ */
+ write_byte(&priv->nec7210_priv, status & ~request_service_bit, SPMR);
+ spin_unlock_irqrestore(&board->spinlock, flags);
+}
+
+uint8_t tnt4882_serial_poll_status(gpib_board_t *board)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ return nec7210_serial_poll_status(board, &priv->nec7210_priv);
+}
+
+void tnt4882_return_to_local(gpib_board_t *board)
+{
+ struct tnt4882_priv *priv = board->private_data;
+
+ nec7210_return_to_local(board, &priv->nec7210_priv);
+}
+
+gpib_interface_t ni_pci_interface = {
+name: "ni_pci",
+attach : ni_pci_attach,
+detach : ni_pci_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_pci_accel_interface = {
+name: "ni_pci_accel",
+attach : ni_pci_attach,
+detach : ni_pci_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_isa_interface = {
+name: "ni_isa",
+attach : ni_tnt_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_nat4882_isa_interface = {
+name: "ni_nat4882_isa",
+attach : ni_nat4882_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_read,
+write : tnt4882_write,
+command : tnt4882_command_unaccel,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_nec_isa_interface = {
+name: "ni_nec_isa",
+attach : ni_nec_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_read,
+write : tnt4882_write,
+command : tnt4882_command_unaccel,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response : tnt4882_serial_poll_response,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_isa_accel_interface = {
+name: "ni_isa_accel",
+attach : ni_tnt_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_nat4882_isa_accel_interface = {
+name: "ni_nat4882_isa_accel",
+attach : ni_nat4882_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command_unaccel,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response2 : tnt4882_serial_poll_response2,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_nec_isa_accel_interface = {
+name: "ni_nec_isa_accel",
+attach : ni_nec_isa_attach,
+detach : ni_isa_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command_unaccel,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : NULL,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response : tnt4882_serial_poll_response,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+#ifdef GPIB_PCMCIA
+gpib_interface_t ni_pcmcia_interface = {
+name: "ni_pcmcia",
+attach : ni_pcmcia_attach,
+detach : ni_pcmcia_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response : tnt4882_serial_poll_response,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+
+gpib_interface_t ni_pcmcia_accel_interface = {
+name: "ni_pcmcia_accel",
+attach : ni_pcmcia_attach,
+detach : ni_pcmcia_detach,
+read : tnt4882_accel_read,
+write : tnt4882_accel_write,
+command : tnt4882_command,
+take_control : tnt4882_take_control,
+go_to_standby : tnt4882_go_to_standby,
+request_system_control : tnt4882_request_system_control,
+interface_clear : tnt4882_interface_clear,
+remote_enable : tnt4882_remote_enable,
+enable_eos : tnt4882_enable_eos,
+disable_eos : tnt4882_disable_eos,
+parallel_poll : tnt4882_parallel_poll,
+parallel_poll_configure : tnt4882_parallel_poll_configure,
+parallel_poll_response : tnt4882_parallel_poll_response,
+local_parallel_poll_mode : NULL, // XXX
+line_status : tnt4882_line_status,
+update_status : tnt4882_update_status,
+primary_address : tnt4882_primary_address,
+secondary_address : tnt4882_secondary_address,
+serial_poll_response : tnt4882_serial_poll_response,
+serial_poll_status : tnt4882_serial_poll_status,
+t1_delay : tnt4882_t1_delay,
+return_to_local : tnt4882_return_to_local,
+};
+#endif
+
+void tnt4882_board_reset(struct tnt4882_priv *tnt_priv, gpib_board_t *board)
+{
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+
+ tnt_priv->imr0_bits = 0;
+ tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0);
+ tnt_priv->imr3_bits = 0;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+ tnt_readb(tnt_priv, IMR0);
+ tnt_readb(tnt_priv, IMR3);
+ nec7210_board_reset(nec_priv, board);
+}
+
+int tnt4882_allocate_private(gpib_board_t *board)
+{
+ struct tnt4882_priv *tnt_priv;
+
+ board->private_data = kmalloc(sizeof(struct tnt4882_priv), GFP_KERNEL);
+ if (!board->private_data)
+ return -1;
+ tnt_priv = board->private_data;
+ memset(tnt_priv, 0, sizeof(struct tnt4882_priv));
+ init_nec7210_private(&tnt_priv->nec7210_priv);
+ return 0;
+}
+
+void tnt4882_free_private(gpib_board_t *board)
+{
+ kfree(board->private_data);
+ board->private_data = NULL;
+}
+
+void tnt4882_init(struct tnt4882_priv *tnt_priv, const gpib_board_t *board)
+{
+ struct nec7210_priv *nec_priv = &tnt_priv->nec7210_priv;
+
+ /* Turbo488 software reset */
+ tnt_writeb(tnt_priv, SOFT_RESET, CMDR);
+ udelay(1);
+
+ // turn off one-chip mode
+ tnt_writeb(tnt_priv, NODMA, HSSEL);
+ tnt_writeb(tnt_priv, 0, ACCWR);
+ // make sure we are in 7210 mode
+ tnt_writeb(tnt_priv, AUX_7210, AUXCR);
+ udelay(1);
+ // registers might be swapped, so write it to the swapped address too
+ tnt_writeb(tnt_priv, AUX_7210, SWAPPED_AUXCR);
+ udelay(1);
+ // turn on one-chip mode
+ if (nec_priv->type == TNT4882 || nec_priv->type == TNT5004)
+ tnt_writeb(tnt_priv, NODMA | TNT_ONE_CHIP_BIT, HSSEL);
+ else
+ tnt_writeb(tnt_priv, NODMA, HSSEL);
+
+ nec7210_board_reset(nec_priv, board);
+ // read-clear isr0
+ tnt_readb(tnt_priv, ISR0);
+
+ // enable passing of nat4882 interrupts
+ tnt_priv->imr3_bits = HR_TLCI;
+ tnt_writeb(tnt_priv, tnt_priv->imr3_bits, IMR3);
+
+ // enable interrupt
+ tnt_writeb(tnt_priv, 0x1, INTRT);
+
+ // force immediate holdoff
+ write_byte(&tnt_priv->nec7210_priv, AUX_HLDI, AUXMR);
+
+ set_bit(RFD_HOLDOFF_BN, &nec_priv->state);
+
+ tnt_priv->auxg_bits = AUXRG | NTNL_BIT;
+ write_byte(&tnt_priv->nec7210_priv, tnt_priv->auxg_bits, AUXMR);
+
+ nec7210_board_online(nec_priv, board);
+ // enable interface clear interrupt for event queue
+ tnt_priv->imr0_bits = TNT_IMR0_ALWAYS_BITS | TNT_ATNI_BIT | TNT_IFCIE_BIT;
+ tnt_writeb(tnt_priv, tnt_priv->imr0_bits, IMR0);
+}
+
+int ni_pci_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct tnt4882_priv *tnt_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = IRQF_SHARED;
+ int retval;
+ struct mite_struct *mite;
+
+ board->status = 0;
+
+ if (tnt4882_allocate_private(board))
+ return -ENOMEM;
+ tnt_priv = board->private_data;
+ tnt_priv->io_writeb = writeb_wrapper;
+ tnt_priv->io_readb = readb_wrapper;
+ tnt_priv->io_writew = writew_wrapper;
+ tnt_priv->io_readw = readw_wrapper;
+ nec_priv = &tnt_priv->nec7210_priv;
+ nec_priv->type = TNT4882;
+ nec_priv->read_byte = nec7210_locking_iomem_read_byte;
+ nec_priv->write_byte = nec7210_locking_iomem_write_byte;
+ nec_priv->offset = atgpib_reg_offset;
+
+ if (!mite_devices) {
+ pr_err("no National Instruments PCI boards found\n");
+ return -1;
+ }
+
+ for (mite = mite_devices; mite; mite = mite->next) {
+ short found_board;
+
+ if (mite->used)
+ continue;
+ if (config->pci_bus >= 0 && config->pci_bus != mite->pcidev->bus->number)
+ continue;
+ if (config->pci_slot >= 0 && config->pci_slot != PCI_SLOT(mite->pcidev->devfn))
+ continue;
+ switch (mite_device_id(mite)) {
+ case PCI_DEVICE_ID_NI_GPIB:
+ case PCI_DEVICE_ID_NI_GPIB_PLUS:
+ case PCI_DEVICE_ID_NI_GPIB_PLUS2:
+ case PCI_DEVICE_ID_NI_PXIGPIB:
+ case PCI_DEVICE_ID_NI_PMCGPIB:
+ case PCI_DEVICE_ID_NI_PCIEGPIB:
+ case PCI_DEVICE_ID_NI_PCIE2GPIB:
+// support for Measurement Computing PCI-488
+ case PCI_DEVICE_ID_MC_PCI488:
+ case PCI_DEVICE_ID_CEC_NI_GPIB:
+ found_board = 1;
+ break;
+ default:
+ found_board = 0;
+ break;
+ }
+ if (found_board)
+ break;
+ }
+ if (!mite) {
+ pr_err("no NI PCI-GPIB boards found\n");
+ return -1;
+ }
+ tnt_priv->mite = mite;
+ retval = mite_setup(tnt_priv->mite);
+ if (retval < 0) {
+ pr_err("tnt4882: error setting up mite.\n");
+ return retval;
+ }
+
+ nec_priv->iobase = tnt_priv->mite->daq_io_addr;
+
+ // get irq
+ if (request_irq(mite_irq(tnt_priv->mite), tnt4882_interrupt, isr_flags,
+ "ni-pci-gpib", board)) {
+ pr_err("gpib: can't request IRQ %d\n", mite_irq(tnt_priv->mite));
+ return -1;
+ }
+ tnt_priv->irq = mite_irq(tnt_priv->mite);
+ pr_info("tnt4882: irq %i\n", tnt_priv->irq);
+
+ // TNT5004 detection
+ switch (tnt_readb(tnt_priv, CSR) & 0xf0) {
+ case 0x30:
+ nec_priv->type = TNT4882;
+ pr_info("tnt4882: TNT4882 chipset detected\n");
+ break;
+ case 0x40:
+ nec_priv->type = TNT5004;
+ pr_info("tnt4882: TNT5004 chipset detected\n");
+ break;
+ }
+ tnt4882_init(tnt_priv, board);
+
+ return 0;
+}
+
+void ni_pci_detach(gpib_board_t *board)
+{
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (tnt_priv) {
+ nec_priv = &tnt_priv->nec7210_priv;
+
+ if (nec_priv->iobase)
+ tnt4882_board_reset(tnt_priv, board);
+ if (tnt_priv->irq)
+ free_irq(tnt_priv->irq, board);
+ if (tnt_priv->mite)
+ mite_unsetup(tnt_priv->mite);
+ }
+ tnt4882_free_private(board);
+}
+
+static int ni_isapnp_find(struct pnp_dev **dev)
+{
+ *dev = pnp_find_dev(NULL, ISAPNP_VENDOR_ID_NI,
+ ISAPNP_FUNCTION(ISAPNP_ID_NI_ATGPIB_TNT), NULL);
+ if (!*dev || !(*dev)->card) {
+ pr_err("tnt4882: failed to find isapnp board\n");
+ return -ENODEV;
+ }
+ if (pnp_device_attach(*dev) < 0) {
+ pr_err("tnt4882: atgpib/tnt board already active, skipping\n");
+ return -EBUSY;
+ }
+ if (pnp_activate_dev(*dev) < 0) {
+ pnp_device_detach(*dev);
+ pr_err("tnt4882: failed to activate() atgpib/tnt, aborting\n");
+ return -EAGAIN;
+ }
+ if (!pnp_port_valid(*dev, 0) || !pnp_irq_valid(*dev, 0)) {
+ pnp_device_detach(*dev);
+ pr_err("tnt4882: invalid port or irq for atgpib/tnt, aborting\n");
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+static int ni_isa_attach_common(gpib_board_t *board, const gpib_board_config_t *config,
+ enum nec7210_chipset chipset)
+{
+ struct tnt4882_priv *tnt_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = 0;
+ void *iobase;
+ int irq;
+
+ board->status = 0;
+
+ if (tnt4882_allocate_private(board))
+ return -ENOMEM;
+ tnt_priv = board->private_data;
+ tnt_priv->io_writeb = outb_wrapper;
+ tnt_priv->io_readb = inb_wrapper;
+ tnt_priv->io_writew = outw_wrapper;
+ tnt_priv->io_readw = inw_wrapper;
+ nec_priv = &tnt_priv->nec7210_priv;
+ nec_priv->type = chipset;
+ nec_priv->read_byte = nec7210_locking_ioport_read_byte;
+ nec_priv->write_byte = nec7210_locking_ioport_write_byte;
+ nec_priv->offset = atgpib_reg_offset;
+
+ // look for plug-n-play board
+ if (config->ibbase == 0) {
+ struct pnp_dev *dev;
+ int retval;
+
+ retval = ni_isapnp_find(&dev);
+ if (retval < 0)
+ return retval;
+ tnt_priv->pnp_dev = dev;
+ iobase = (void *)(pnp_port_start(dev, 0));
+ irq = pnp_irq(dev, 0);
+ } else {
+ iobase = config->ibbase;
+ irq = config->ibirq;
+ }
+ // allocate ioports
+ if (!request_region((unsigned long)(iobase), atgpib_iosize, "atgpib")) {
+ pr_err("tnt4882: failed to allocate ioports\n");
+ return -1;
+ }
+ nec_priv->iobase = iobase;
+
+ // get irq
+ if (request_irq(irq, tnt4882_interrupt, isr_flags, "atgpib", board)) {
+ pr_err("gpib: can't request IRQ %d\n", irq);
+ return -1;
+ }
+ tnt_priv->irq = irq;
+
+ tnt4882_init(tnt_priv, board);
+
+ return 0;
+}
+
+int ni_tnt_isa_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return ni_isa_attach_common(board, config, TNT4882);
+}
+
+int ni_nat4882_isa_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return ni_isa_attach_common(board, config, NAT4882);
+}
+
+int ni_nec_isa_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ return ni_isa_attach_common(board, config, NEC7210);
+}
+
+void ni_isa_detach(gpib_board_t *board)
+{
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ if (tnt_priv) {
+ nec_priv = &tnt_priv->nec7210_priv;
+ if (nec_priv->iobase)
+ tnt4882_board_reset(tnt_priv, board);
+ if (tnt_priv->irq)
+ free_irq(tnt_priv->irq, board);
+ if (nec_priv->iobase)
+ release_region((unsigned long)(nec_priv->iobase), atgpib_iosize);
+ if (tnt_priv->pnp_dev)
+ pnp_device_detach(tnt_priv->pnp_dev);
+ }
+ tnt4882_free_private(board);
+}
+
+static int tnt4882_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+ return 0;
+}
+
+static const struct pci_device_id tnt4882_pci_table[] = {
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_GPIB_PLUS2)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PXIGPIB)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PMCGPIB)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIEGPIB)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_NI_PCIE2GPIB)},
+ // support for Measurement Computing PCI-488
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_MC_PCI488)},
+ {PCI_DEVICE(PCI_VENDOR_ID_NATINST, PCI_DEVICE_ID_CEC_NI_GPIB)},
+ { 0 }
+};
+MODULE_DEVICE_TABLE(pci, tnt4882_pci_table);
+
+static struct pci_driver tnt4882_pci_driver = {
+ .name = "tnt4882",
+ .id_table = tnt4882_pci_table,
+ .probe = &tnt4882_pci_probe
+};
+
+static const struct pnp_device_id tnt4882_pnp_table[] = {
+ {.id = "NICC601"},
+ {.id = ""}
+};
+MODULE_DEVICE_TABLE(pnp, tnt4882_pnp_table);
+
+static int __init tnt4882_init_module(void)
+{
+ int result;
+
+ result = pci_register_driver(&tnt4882_pci_driver);
+ if (result) {
+ pr_err("tnt4882: pci_driver_register failed!\n");
+ return result;
+ }
+
+ gpib_register_driver(&ni_isa_interface, THIS_MODULE);
+ gpib_register_driver(&ni_isa_accel_interface, THIS_MODULE);
+ gpib_register_driver(&ni_nat4882_isa_interface, THIS_MODULE);
+ gpib_register_driver(&ni_nat4882_isa_accel_interface, THIS_MODULE);
+ gpib_register_driver(&ni_nec_isa_interface, THIS_MODULE);
+ gpib_register_driver(&ni_nec_isa_accel_interface, THIS_MODULE);
+ gpib_register_driver(&ni_pci_interface, THIS_MODULE);
+ gpib_register_driver(&ni_pci_accel_interface, THIS_MODULE);
+#ifdef GPIB_PCMCIA
+ gpib_register_driver(&ni_pcmcia_interface, THIS_MODULE);
+ gpib_register_driver(&ni_pcmcia_accel_interface, THIS_MODULE);
+ if (init_ni_gpib_cs() < 0)
+ return -1;
+#endif
+
+ mite_init();
+ mite_list_devices();
+
+ return 0;
+}
+
+static void __exit tnt4882_exit_module(void)
+{
+ gpib_unregister_driver(&ni_isa_interface);
+ gpib_unregister_driver(&ni_isa_accel_interface);
+ gpib_unregister_driver(&ni_nat4882_isa_interface);
+ gpib_unregister_driver(&ni_nat4882_isa_accel_interface);
+ gpib_unregister_driver(&ni_nec_isa_interface);
+ gpib_unregister_driver(&ni_nec_isa_accel_interface);
+ gpib_unregister_driver(&ni_pci_interface);
+ gpib_unregister_driver(&ni_pci_accel_interface);
+#ifdef GPIB_PCMCIA
+ gpib_unregister_driver(&ni_pcmcia_interface);
+ gpib_unregister_driver(&ni_pcmcia_accel_interface);
+ exit_ni_gpib_cs();
+#endif
+
+ mite_cleanup();
+
+ pci_unregister_driver(&tnt4882_pci_driver);
+}
+
+#ifdef GPIB_PCMCIA
+
+#include <linux/kernel.h>
+#include <linux/moduleparam.h>
+#include <linux/ptrace.h>
+#include <linux/timer.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+
+#include <pcmcia/cistpl.h>
+#include <pcmcia/cisreg.h>
+#include <pcmcia/ds.h>
+
+/*
+ * All the PCMCIA modules use PCMCIA_DEBUG to control debugging. If
+ * you do not define PCMCIA_DEBUG at all, all the debug code will be
+ * left out. If you compile with PCMCIA_DEBUG=0, the debug code will
+ * be present but disabled -- but it can then be enabled for specific
+ * modules at load time with a 'pc_debug=#' option to insmod.
+ */
+#define PCMCIA_DEBUG 1
+#ifdef PCMCIA_DEBUG
+static int pc_debug = PCMCIA_DEBUG;
+module_param(pc_debug, int, 0);
+#define DEBUG(n, args...) \
+ do {if (pc_debug > (n)) \
+ pr_debug(args); } \
+ while (0)
+#else
+#define DEBUG(args...)
+#endif
+
+static int ni_gpib_config(struct pcmcia_device *link);
+static void ni_gpib_release(struct pcmcia_device *link);
+static int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config);
+static void ni_pcmcia_detach(gpib_board_t *board);
+
+/*
+ * A linked list of "instances" of the dummy device. Each actual
+ * PCMCIA card corresponds to one device instance, and is described
+ * by one dev_link_t structure (defined in ds.h).
+ *
+ * You may not want to use a linked list for this -- for example, the
+ * memory card driver uses an array of dev_link_t pointers, where minor
+ * device numbers are used to derive the corresponding array index.
+ *
+ * I think this dev_list is obsolete but the pointer is needed to keep
+ * the module instance for the ni_pcmcia_attach function.
+ */
+
+static struct pcmcia_device *curr_dev;
+
+struct local_info_t {
+ struct pcmcia_device *p_dev;
+ gpib_board_t *dev;
+ int stop;
+ struct bus_operations *bus;
+};
+
+/*
+ * ni_gpib_probe() creates an "instance" of the driver, allocating
+ * local data structures for one device. The device is registered
+ * with Card Services.
+ */
+
+static int ni_gpib_probe(struct pcmcia_device *link)
+{
+ struct local_info_t *info;
+ //struct gpib_board_t *dev;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ /* Allocate space for private device-specific data */
+ info = kzalloc(sizeof(*info), GFP_KERNEL);
+ if (!info)
+ return -ENOMEM;
+
+ info->p_dev = link;
+ link->priv = info;
+
+ /*
+ * General socket configuration defaults can go here. In this
+ * client, we assume very little, and rely on the CIS for almost
+ * everything. In most clients, many details (i.e., number, sizes,
+ * and attributes of IO windows) are fixed by the nature of the
+ * device, and can be hard-wired here.
+ */
+ link->config_flags = CONF_ENABLE_IRQ | CONF_AUTO_SET_IO;
+
+ /* Register with Card Services */
+ curr_dev = link;
+ return ni_gpib_config(link);
+}
+
+/*
+ * This deletes a driver "instance". The device is de-registered
+ * with Card Services. If it has been released, all local data
+ * structures are freed. Otherwise, the structures will be freed
+ * when the device is released.
+ */
+static void ni_gpib_remove(struct pcmcia_device *link)
+{
+ struct local_info_t *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+
+ DEBUG(0, "%s(%p)\n", __func__, link);
+
+ if (info->dev)
+ ni_pcmcia_detach(info->dev);
+ ni_gpib_release(link);
+
+ //free_netdev(dev);
+ kfree(info);
+}
+
+static int ni_gpib_config_iteration(struct pcmcia_device *link, void *priv_data)
+{
+ int retval;
+
+ retval = pcmcia_request_io(link);
+ if (retval != 0)
+ return retval;
+
+ return 0;
+}
+
+/*
+ * ni_gpib_config() is scheduled to run after a CARD_INSERTION event
+ * is received, to configure the PCMCIA socket, and to make the
+ * device available to the system.
+ */
+static int ni_gpib_config(struct pcmcia_device *link)
+{
+ //struct local_info_t *info = link->priv;
+ //gpib_board_t *dev = info->dev;
+ int last_ret;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ last_ret = pcmcia_loop_config(link, &ni_gpib_config_iteration, NULL);
+ if (last_ret) {
+ dev_warn(&link->dev, "no configuration found\n");
+ ni_gpib_release(link);
+ return last_ret;
+ }
+
+ last_ret = pcmcia_enable_device(link);
+ if (last_ret) {
+ ni_gpib_release(link);
+ return last_ret;
+ }
+ return 0;
+} /* ni_gpib_config */
+
+/*
+ * After a card is removed, ni_gpib_release() will unregister the
+ * device, and release the PCMCIA configuration. If the device is
+ * still open, this will be postponed until it is closed.
+ */
+static void ni_gpib_release(struct pcmcia_device *link)
+{
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+ pcmcia_disable_device(link);
+} /* ni_gpib_release */
+
+static int ni_gpib_suspend(struct pcmcia_device *link)
+{
+ //struct local_info_t *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ if (link->open)
+ pr_err("Device still open ???\n");
+ //netif_device_detach(dev);
+
+ return 0;
+}
+
+static int ni_gpib_resume(struct pcmcia_device *link)
+{
+ //struct local_info_t *info = link->priv;
+ //struct gpib_board_t *dev = info->dev;
+ DEBUG(0, "%s(0x%p)\n", __func__, link);
+
+ /*if (link->open) {
+ * ni_gpib_probe(dev); / really?
+ * printk("Gpib resumed ???\n");
+ * //netif_device_attach(dev);
+ *}
+ */
+ return ni_gpib_config(link);
+}
+
+static struct pcmcia_device_id ni_pcmcia_ids[] = {
+ PCMCIA_DEVICE_MANF_CARD(0x010b, 0x4882),
+ PCMCIA_DEVICE_MANF_CARD(0x010b, 0x0c71), // NI PCMCIA-GPIB+
+ PCMCIA_DEVICE_NULL
+};
+
+MODULE_DEVICE_TABLE(pcmcia, ni_pcmcia_ids);
+
+static struct pcmcia_driver ni_gpib_cs_driver = {
+ .name = "ni_gpib_cs",
+ .owner = THIS_MODULE,
+ .drv = { .name = "ni_gpib_cs", },
+ .id_table = ni_pcmcia_ids,
+ .probe = ni_gpib_probe,
+ .remove = ni_gpib_remove,
+ .suspend = ni_gpib_suspend,
+ .resume = ni_gpib_resume,
+};
+
+int __init init_ni_gpib_cs(void)
+{
+ return pcmcia_register_driver(&ni_gpib_cs_driver);
+}
+
+void __exit exit_ni_gpib_cs(void)
+{
+ DEBUG(0, "ni_gpib_cs: unloading\n");
+ pcmcia_unregister_driver(&ni_gpib_cs_driver);
+}
+
+static const int pcmcia_gpib_iosize = 32;
+
+int ni_pcmcia_attach(gpib_board_t *board, const gpib_board_config_t *config)
+{
+ struct local_info_t *info;
+ struct tnt4882_priv *tnt_priv;
+ struct nec7210_priv *nec_priv;
+ int isr_flags = IRQF_SHARED;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, board);
+
+ if (!curr_dev) {
+ pr_err("gpib: no NI PCMCIA board found\n");
+ return -1;
+ }
+
+ info = curr_dev->priv;
+ info->dev = board;
+
+ board->status = 0;
+
+ if (tnt4882_allocate_private(board))
+ return -ENOMEM;
+ tnt_priv = board->private_data;
+ tnt_priv->io_writeb = outb_wrapper;
+ tnt_priv->io_readb = inb_wrapper;
+ tnt_priv->io_writew = outw_wrapper;
+ tnt_priv->io_readw = inw_wrapper;
+ nec_priv = &tnt_priv->nec7210_priv;
+ nec_priv->type = TNT4882;
+ nec_priv->read_byte = nec7210_locking_ioport_read_byte;
+ nec_priv->write_byte = nec7210_locking_ioport_write_byte;
+ nec_priv->offset = atgpib_reg_offset;
+
+ DEBUG(0, "ioport1 window attributes: 0x%lx\n", curr_dev->resource[0]->flags);
+ if (request_region(curr_dev->resource[0]->start, resource_size(curr_dev->resource[0]),
+ "tnt4882") == 0) {
+ pr_err("gpib: ioports starting at 0x%lx are already in use\n",
+ (unsigned long)curr_dev->resource[0]->start);
+ return -EIO;
+ }
+
+ nec_priv->iobase = (void *)(unsigned long)curr_dev->resource[0]->start;
+
+ // get irq
+ if (request_irq(curr_dev->irq, tnt4882_interrupt, isr_flags, "tnt4882", board)) {
+ pr_err("gpib: can't request IRQ %d\n", curr_dev->irq);
+ return -1;
+ }
+ tnt_priv->irq = curr_dev->irq;
+
+ tnt4882_init(tnt_priv, board);
+
+ return 0;
+}
+
+void ni_pcmcia_detach(gpib_board_t *board)
+{
+ struct tnt4882_priv *tnt_priv = board->private_data;
+ struct nec7210_priv *nec_priv;
+
+ DEBUG(0, "%s(0x%p)\n", __func__, board);
+
+ if (tnt_priv) {
+ nec_priv = &tnt_priv->nec7210_priv;
+ if (tnt_priv->irq)
+ free_irq(tnt_priv->irq, board);
+ if (nec_priv->iobase) {
+ tnt4882_board_reset(tnt_priv, board);
+ release_region((unsigned long)nec_priv->iobase, pcmcia_gpib_iosize);
+ }
+ }
+ tnt4882_free_private(board);
+}
+
+#endif // GPIB_PCMCIA
+
+module_init(tnt4882_init_module);
+module_exit(tnt4882_exit_module);
diff --git a/drivers/staging/gpib/uapi/gpib_ioctl.h b/drivers/staging/gpib/uapi/gpib_ioctl.h
new file mode 100644
index 000000000000..6202865278ea
--- /dev/null
+++ b/drivers/staging/gpib/uapi/gpib_ioctl.h
@@ -0,0 +1,169 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_IOCTL_H
+#define _GPIB_IOCTL_H
+
+#include <asm/ioctl.h>
+#include <linux/types.h>
+
+#define GPIB_CODE 160
+
+typedef struct {
+ char name[100];
+} board_type_ioctl_t;
+
+/* argument for read/write/command ioctls */
+typedef struct {
+ uint64_t buffer_ptr;
+ unsigned int requested_transfer_count;
+ unsigned int completed_transfer_count;
+ int end; /* end flag return for reads, end io suppression request for cmd*/
+ int handle;
+} read_write_ioctl_t;
+
+typedef struct {
+ unsigned int handle;
+ unsigned int pad;
+ int sad;
+ unsigned is_board : 1;
+} open_dev_ioctl_t;
+
+typedef struct {
+ unsigned int handle;
+} close_dev_ioctl_t;
+
+typedef struct {
+ unsigned int pad;
+ int sad;
+ uint8_t status_byte;
+} serial_poll_ioctl_t;
+
+typedef struct {
+ int eos;
+ int eos_flags;
+} eos_ioctl_t;
+
+typedef struct {
+ int handle;
+ int wait_mask;
+ int clear_mask;
+ int set_mask;
+ int ibsta;
+ int pad;
+ int sad;
+ unsigned int usec_timeout;
+} wait_ioctl_t;
+
+typedef struct {
+ uint64_t init_data_ptr;
+ int init_data_length;
+ int online;
+} online_ioctl_t;
+
+typedef struct {
+ unsigned int num_bytes;
+ unsigned int pad;
+ int sad;
+} spoll_bytes_ioctl_t;
+
+typedef struct {
+ unsigned int pad;
+ int sad;
+ int parallel_poll_configuration;
+ int autopolling;
+ int is_system_controller;
+ unsigned int t1_delay;
+ unsigned ist : 1;
+ unsigned no_7_bit_eos : 1;
+} board_info_ioctl_t;
+
+typedef struct {
+ int pci_bus;
+ int pci_slot;
+} select_pci_ioctl_t;
+
+typedef struct {
+ uint8_t config;
+ unsigned set_ist : 1;
+ unsigned clear_ist : 1;
+} ppoll_config_ioctl_t;
+
+typedef struct {
+ unsigned int handle;
+ unsigned int pad;
+} pad_ioctl_t;
+
+typedef struct {
+ unsigned int handle;
+ int sad;
+} sad_ioctl_t;
+
+// select a piece of hardware to attach by its sysfs device path
+typedef struct {
+ char device_path[0x1000];
+} select_device_path_ioctl_t;
+
+typedef short event_ioctl_t;
+typedef int rsc_ioctl_t;
+typedef unsigned int t1_delay_ioctl_t;
+typedef short autospoll_ioctl_t;
+typedef short local_ppoll_mode_ioctl_t;
+
+// update status byte and request service
+typedef struct {
+ uint8_t status_byte;
+ int new_reason_for_service;
+} request_service2_t;
+
+/* Standard functions. */
+enum gpib_ioctl {
+ IBRD = _IOWR(GPIB_CODE, 100, read_write_ioctl_t),
+ IBWRT = _IOWR(GPIB_CODE, 101, read_write_ioctl_t),
+ IBCMD = _IOWR(GPIB_CODE, 102, read_write_ioctl_t),
+ IBOPENDEV = _IOWR(GPIB_CODE, 3, open_dev_ioctl_t),
+ IBCLOSEDEV = _IOW(GPIB_CODE, 4, close_dev_ioctl_t),
+ IBWAIT = _IOWR(GPIB_CODE, 5, wait_ioctl_t),
+ IBRPP = _IOWR(GPIB_CODE, 6, uint8_t),
+
+ IBSIC = _IOW(GPIB_CODE, 9, unsigned int),
+ IBSRE = _IOW(GPIB_CODE, 10, int),
+ IBGTS = _IO(GPIB_CODE, 11),
+ IBCAC = _IOW(GPIB_CODE, 12, int),
+ IBLINES = _IOR(GPIB_CODE, 14, short),
+ IBPAD = _IOW(GPIB_CODE, 15, pad_ioctl_t),
+ IBSAD = _IOW(GPIB_CODE, 16, sad_ioctl_t),
+ IBTMO = _IOW(GPIB_CODE, 17, unsigned int),
+ IBRSP = _IOWR(GPIB_CODE, 18, serial_poll_ioctl_t),
+ IBEOS = _IOW(GPIB_CODE, 19, eos_ioctl_t),
+ IBRSV = _IOW(GPIB_CODE, 20, uint8_t),
+ CFCBASE = _IOW(GPIB_CODE, 21, uint64_t),
+ CFCIRQ = _IOW(GPIB_CODE, 22, unsigned int),
+ CFCDMA = _IOW(GPIB_CODE, 23, unsigned int),
+ CFCBOARDTYPE = _IOW(GPIB_CODE, 24, board_type_ioctl_t),
+
+ IBMUTEX = _IOW(GPIB_CODE, 26, int),
+ IBSPOLL_BYTES = _IOWR(GPIB_CODE, 27, spoll_bytes_ioctl_t),
+ IBPPC = _IOW(GPIB_CODE, 28, ppoll_config_ioctl_t),
+ IBBOARD_INFO = _IOR(GPIB_CODE, 29, board_info_ioctl_t),
+
+ IBQUERY_BOARD_RSV = _IOR(GPIB_CODE, 31, int),
+ IBSELECT_PCI = _IOWR(GPIB_CODE, 32, select_pci_ioctl_t),
+ IBEVENT = _IOR(GPIB_CODE, 33, event_ioctl_t),
+ IBRSC = _IOW(GPIB_CODE, 34, rsc_ioctl_t),
+ IB_T1_DELAY = _IOW(GPIB_CODE, 35, t1_delay_ioctl_t),
+ IBLOC = _IO(GPIB_CODE, 36),
+
+ IBAUTOSPOLL = _IOW(GPIB_CODE, 38, autospoll_ioctl_t),
+ IBONL = _IOW(GPIB_CODE, 39, online_ioctl_t),
+ IBPP2_SET = _IOW(GPIB_CODE, 40, local_ppoll_mode_ioctl_t),
+ IBPP2_GET = _IOR(GPIB_CODE, 41, local_ppoll_mode_ioctl_t),
+ IBSELECT_DEVICE_PATH = _IOW(GPIB_CODE, 43, select_device_path_ioctl_t),
+ // 44 was IBSELECT_SERIAL_NUMBER
+ IBRSV2 = _IOW(GPIB_CODE, 45, request_service2_t)
+};
+
+#endif /* _GPIB_IOCTL_H */
diff --git a/drivers/staging/gpib/uapi/gpib_user.h b/drivers/staging/gpib/uapi/gpib_user.h
new file mode 100644
index 000000000000..0896a55a758f
--- /dev/null
+++ b/drivers/staging/gpib/uapi/gpib_user.h
@@ -0,0 +1,363 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+/***************************************************************************
+ * copyright : (C) 2002 by Frank Mori Hess
+ ***************************************************************************/
+
+#ifndef _GPIB_USER_H
+#define _GPIB_USER_H
+
+#define GPIB_MAX_NUM_BOARDS 16
+#define GPIB_MAX_NUM_DESCRIPTORS 0x1000
+
+enum ibsta_bit_numbers {
+ DCAS_NUM = 0,
+ DTAS_NUM = 1,
+ LACS_NUM = 2,
+ TACS_NUM = 3,
+ ATN_NUM = 4,
+ CIC_NUM = 5,
+ REM_NUM = 6,
+ LOK_NUM = 7,
+ CMPL_NUM = 8,
+ EVENT_NUM = 9,
+ SPOLL_NUM = 10,
+ RQS_NUM = 11,
+ SRQI_NUM = 12,
+ END_NUM = 13,
+ TIMO_NUM = 14,
+ ERR_NUM = 15
+};
+
+/* IBSTA status bits (returned by all functions) */
+enum ibsta_bits {
+ DCAS = (1 << DCAS_NUM), /* device clear state */
+ DTAS = (1 << DTAS_NUM), /* device trigger state */
+ LACS = (1 << LACS_NUM), /* GPIB interface is addressed as Listener */
+ TACS = (1 << TACS_NUM), /* GPIB interface is addressed as Talker */
+ ATN = (1 << ATN_NUM), /* Attention is asserted */
+ CIC = (1 << CIC_NUM), /* GPIB interface is Controller-in-Charge */
+ REM = (1 << REM_NUM), /* remote state */
+ LOK = (1 << LOK_NUM), /* lockout state */
+ CMPL = (1 << CMPL_NUM), /* I/O is complete */
+ EVENT = (1 << EVENT_NUM), /* DCAS, DTAS, or IFC has occurred */
+ SPOLL = (1 << SPOLL_NUM), /* board serial polled by busmaster */
+ RQS = (1 << RQS_NUM), /* Device requesting service */
+ SRQI = (1 << SRQI_NUM), /* SRQ is asserted */
+ END = (1 << END_NUM), /* EOI or EOS encountered */
+ TIMO = (1 << TIMO_NUM), /* Time limit on I/O or wait function exceeded */
+ ERR = (1 << ERR_NUM), /* Function call terminated on error */
+
+ device_status_mask = ERR | TIMO | END | CMPL | RQS,
+ board_status_mask = ERR | TIMO | END | CMPL | SPOLL |
+ EVENT | LOK | REM | CIC | ATN | TACS | LACS | DTAS | DCAS | SRQI,
+};
+
+/* IBERR error codes */
+enum iberr_code {
+ EDVR = 0, /* system error */
+ ECIC = 1, /* not CIC */
+ ENOL = 2, /* no listeners */
+ EADR = 3, /* CIC and not addressed before I/O */
+ EARG = 4, /* bad argument to function call */
+ ESAC = 5, /* not SAC */
+ EABO = 6, /* I/O operation was aborted */
+ ENEB = 7, /* non-existent board (GPIB interface offline) */
+ EDMA = 8, /* DMA hardware error detected */
+ EOIP = 10, /* new I/O attempted with old I/O in progress */
+ ECAP = 11, /* no capability for intended opeation */
+ EFSO = 12, /* file system operation error */
+ EBUS = 14, /* bus error */
+ ESTB = 15, /* lost serial poll bytes */
+ ESRQ = 16, /* SRQ stuck on */
+ ETAB = 20 /* Table Overflow */
+};
+
+/* Timeout values and meanings */
+enum gpib_timeout {
+ TNONE = 0, /* Infinite timeout (disabled) */
+ T10us = 1, /* Timeout of 10 usec (ideal) */
+ T30us = 2, /* Timeout of 30 usec (ideal) */
+ T100us = 3, /* Timeout of 100 usec (ideal) */
+ T300us = 4, /* Timeout of 300 usec (ideal) */
+ T1ms = 5, /* Timeout of 1 msec (ideal) */
+ T3ms = 6, /* Timeout of 3 msec (ideal) */
+ T10ms = 7, /* Timeout of 10 msec (ideal) */
+ T30ms = 8, /* Timeout of 30 msec (ideal) */
+ T100ms = 9, /* Timeout of 100 msec (ideal) */
+ T300ms = 10, /* Timeout of 300 msec (ideal) */
+ T1s = 11, /* Timeout of 1 sec (ideal) */
+ T3s = 12, /* Timeout of 3 sec (ideal) */
+ T10s = 13, /* Timeout of 10 sec (ideal) */
+ T30s = 14, /* Timeout of 30 sec (ideal) */
+ T100s = 15, /* Timeout of 100 sec (ideal) */
+ T300s = 16, /* Timeout of 300 sec (ideal) */
+ T1000s = 17 /* Timeout of 1000 sec (maximum) */
+};
+
+/* End-of-string (EOS) modes for use with ibeos */
+
+enum eos_flags {
+ EOS_MASK = 0x1c00,
+ REOS = 0x0400, /* Terminate reads on EOS */
+ XEOS = 0x800, /* assert EOI when EOS char is sent */
+ BIN = 0x1000 /* Do 8-bit compare on EOS */
+};
+
+/* GPIB Bus Control Lines bit vector */
+enum bus_control_line {
+ ValidDAV = 0x01,
+ ValidNDAC = 0x02,
+ ValidNRFD = 0x04,
+ ValidIFC = 0x08,
+ ValidREN = 0x10,
+ ValidSRQ = 0x20,
+ ValidATN = 0x40,
+ ValidEOI = 0x80,
+ ValidALL = 0xff,
+ BusDAV = 0x0100, /* DAV line status bit */
+ BusNDAC = 0x0200, /* NDAC line status bit */
+ BusNRFD = 0x0400, /* NRFD line status bit */
+ BusIFC = 0x0800, /* IFC line status bit */
+ BusREN = 0x1000, /* REN line status bit */
+ BusSRQ = 0x2000, /* SRQ line status bit */
+ BusATN = 0x4000, /* ATN line status bit */
+ BusEOI = 0x8000 /* EOI line status bit */
+};
+
+enum old_bus_control_line {
+ BUS_DAV = 0x0100, /* DAV line status bit */
+ BUS_NDAC = 0x0200, /* NDAC line status bit */
+ BUS_NRFD = 0x0400, /* NRFD line status bit */
+ BUS_IFC = 0x0800, /* IFC line status bit */
+ BUS_REN = 0x1000, /* REN line status bit */
+ BUS_SRQ = 0x2000, /* SRQ line status bit */
+ BUS_ATN = 0x4000, /* ATN line status bit */
+ BUS_EOI = 0x8000 /* EOI line status bit */
+};
+
+/* Possible GPIB command messages */
+
+enum cmd_byte {
+ GTL = 0x1, /* go to local */
+ SDC = 0x4, /* selected device clear */
+ PPConfig = 0x5,
+#ifndef PPC
+ PPC = PPConfig, /* parallel poll configure */
+#endif
+ GET = 0x8, /* group execute trigger */
+ TCT = 0x9, /* take control */
+ LLO = 0x11, /* local lockout */
+ DCL = 0x14, /* device clear */
+ PPU = 0x15, /* parallel poll unconfigure */
+ SPE = 0x18, /* serial poll enable */
+ SPD = 0x19, /* serial poll disable */
+ CFE = 0x1f, /* configure enable */
+ LAD = 0x20, /* value to be 'ored' in to obtain listen address */
+ UNL = 0x3F, /* unlisten */
+ TAD = 0x40, /* value to be 'ored' in to obtain talk address */
+ UNT = 0x5F, /* untalk */
+ SAD = 0x60, /* my secondary address (base) */
+ PPE = 0x60, /* parallel poll enable (base) */
+ PPD = 0x70 /* parallel poll disable */
+};
+
+enum ppe_bits {
+ PPC_DISABLE = 0x10,
+ PPC_SENSE = 0x8, /* parallel poll sense bit */
+ PPC_DIO_MASK = 0x7
+};
+
+/* confine address to range 0 to 30. */
+static inline unsigned int gpib_address_restrict(unsigned int addr)
+{
+ addr &= 0x1f;
+ if (addr == 0x1f)
+ addr = 0;
+ return addr;
+}
+
+static inline uint8_t MLA(unsigned int addr)
+{
+ return gpib_address_restrict(addr) | LAD;
+}
+
+static inline uint8_t MTA(unsigned int addr)
+{
+ return gpib_address_restrict(addr) | TAD;
+}
+
+static inline uint8_t MSA(unsigned int addr)
+{
+ return gpib_address_restrict(addr) | SAD;
+}
+
+static inline uint8_t PPE_byte(unsigned int dio_line, int sense)
+{
+ uint8_t cmd;
+
+ cmd = PPE;
+ if (sense)
+ cmd |= PPC_SENSE;
+ cmd |= (dio_line - 1) & 0x7;
+ return cmd;
+}
+
+static inline uint8_t CFGn(unsigned int meters)
+{
+ return 0x6 | (meters & 0xf);
+}
+
+/* mask of bits that actually matter in a command byte */
+enum {
+ gpib_command_mask = 0x7f,
+};
+
+static inline int is_PPE(uint8_t command)
+{
+ return (command & 0x70) == 0x60;
+}
+
+static inline int is_PPD(uint8_t command)
+{
+ return (command & 0x70) == 0x70;
+}
+
+static inline int in_addressed_command_group(uint8_t command)
+{
+ return (command & 0x70) == 0x0;
+}
+
+static inline int in_universal_command_group(uint8_t command)
+{
+ return (command & 0x70) == 0x10;
+}
+
+static inline int in_listen_address_group(uint8_t command)
+{
+ return (command & 0x60) == 0x20;
+}
+
+static inline int in_talk_address_group(uint8_t command)
+{
+ return (command & 0x60) == 0x40;
+}
+
+static inline int in_primary_command_group(uint8_t command)
+{
+ return in_addressed_command_group(command) ||
+ in_universal_command_group(command) ||
+ in_listen_address_group(command) ||
+ in_talk_address_group(command);
+}
+
+static inline int gpib_address_equal(unsigned int pad1, int sad1, unsigned int pad2, int sad2)
+{
+ if (pad1 == pad2) {
+ if (sad1 == sad2)
+ return 1;
+ if (sad1 < 0 && sad2 < 0)
+ return 1;
+ }
+
+ return 0;
+}
+
+enum ibask_option {
+ IbaPAD = 0x1,
+ IbaSAD = 0x2,
+ IbaTMO = 0x3,
+ IbaEOT = 0x4,
+ IbaPPC = 0x5, /* board only */
+ IbaREADDR = 0x6, /* device only */
+ IbaAUTOPOLL = 0x7, /* board only */
+ IbaCICPROT = 0x8, /* board only */
+ IbaIRQ = 0x9, /* board only */
+ IbaSC = 0xa, /* board only */
+ IbaSRE = 0xb, /* board only */
+ IbaEOSrd = 0xc,
+ IbaEOSwrt = 0xd,
+ IbaEOScmp = 0xe,
+ IbaEOSchar = 0xf,
+ IbaPP2 = 0x10, /* board only */
+ IbaTIMING = 0x11, /* board only */
+ IbaDMA = 0x12, /* board only */
+ IbaReadAdjust = 0x13,
+ IbaWriteAdjust = 0x14,
+ IbaEventQueue = 0x15, /* board only */
+ IbaSPollBit = 0x16, /* board only */
+ IbaSpollBit = 0x16, /* board only */
+ IbaSendLLO = 0x17, /* board only */
+ IbaSPollTime = 0x18, /* device only */
+ IbaPPollTime = 0x19, /* board only */
+ IbaEndBitIsNormal = 0x1a,
+ IbaUnAddr = 0x1b, /* device only */
+ IbaHSCableLength = 0x1f, /* board only */
+ IbaIst = 0x20, /* board only */
+ IbaRsv = 0x21, /* board only */
+ IbaBNA = 0x200, /* device only */
+ /* linux-gpib extensions */
+ Iba7BitEOS = 0x1000 /* board only. Returns 1 if board supports 7 bit eos compares*/
+};
+
+enum ibconfig_option {
+ IbcPAD = 0x1,
+ IbcSAD = 0x2,
+ IbcTMO = 0x3,
+ IbcEOT = 0x4,
+ IbcPPC = 0x5, /* board only */
+ IbcREADDR = 0x6, /* device only */
+ IbcAUTOPOLL = 0x7, /* board only */
+ IbcCICPROT = 0x8, /* board only */
+ IbcIRQ = 0x9, /* board only */
+ IbcSC = 0xa, /* board only */
+ IbcSRE = 0xb, /* board only */
+ IbcEOSrd = 0xc,
+ IbcEOSwrt = 0xd,
+ IbcEOScmp = 0xe,
+ IbcEOSchar = 0xf,
+ IbcPP2 = 0x10, /* board only */
+ IbcTIMING = 0x11, /* board only */
+ IbcDMA = 0x12, /* board only */
+ IbcReadAdjust = 0x13,
+ IbcWriteAdjust = 0x14,
+ IbcEventQueue = 0x15, /* board only */
+ IbcSPollBit = 0x16, /* board only */
+ IbcSpollBit = 0x16, /* board only */
+ IbcSendLLO = 0x17, /* board only */
+ IbcSPollTime = 0x18, /* device only */
+ IbcPPollTime = 0x19, /* board only */
+ IbcEndBitIsNormal = 0x1a,
+ IbcUnAddr = 0x1b, /* device only */
+ IbcHSCableLength = 0x1f, /* board only */
+ IbcIst = 0x20, /* board only */
+ IbcRsv = 0x21, /* board only */
+ IbcBNA = 0x200 /* device only */
+};
+
+enum t1_delays {
+ T1_DELAY_2000ns = 1,
+ T1_DELAY_500ns = 2,
+ T1_DELAY_350ns = 3
+};
+
+enum {
+ request_service_bit = 0x40,
+};
+
+enum gpib_events {
+ EventNone = 0,
+ EventDevTrg = 1,
+ EventDevClr = 2,
+ EventIFC = 3
+};
+
+enum gpib_stb {
+ IbStbRQS = 0x40, /* IEEE 488.1 & 2 */
+ IbStbESB = 0x20, /* IEEE 488.2 only */
+ IbStbMAV = 0x10 /* IEEE 488.2 only */
+};
+
+#endif /* _GPIB_USER_H */
+
+/* Check for errors */
diff --git a/drivers/staging/greybus/arche-apb-ctrl.c b/drivers/staging/greybus/arche-apb-ctrl.c
index aa6f266b62a1..90ab32638d3f 100644
--- a/drivers/staging/greybus/arche-apb-ctrl.c
+++ b/drivers/staging/greybus/arche-apb-ctrl.c
@@ -470,7 +470,7 @@ MODULE_DEVICE_TABLE(of, arche_apb_ctrl_of_match);
static struct platform_driver arche_apb_ctrl_device_driver = {
.probe = arche_apb_ctrl_probe,
- .remove_new = arche_apb_ctrl_remove,
+ .remove = arche_apb_ctrl_remove,
.shutdown = arche_apb_ctrl_shutdown,
.driver = {
.name = "arche-apb-ctrl",
diff --git a/drivers/staging/greybus/arche-platform.c b/drivers/staging/greybus/arche-platform.c
index b33977ccd527..d48464390f58 100644
--- a/drivers/staging/greybus/arche-platform.c
+++ b/drivers/staging/greybus/arche-platform.c
@@ -623,7 +623,7 @@ MODULE_DEVICE_TABLE(of, arche_platform_of_match);
static struct platform_driver arche_platform_device_driver = {
.probe = arche_platform_probe,
- .remove_new = arche_platform_remove,
+ .remove = arche_platform_remove,
.shutdown = arche_platform_shutdown,
.driver = {
.name = "arche-platform-ctrl",
diff --git a/drivers/staging/greybus/gpio.c b/drivers/staging/greybus/gpio.c
index 9b26e148d40f..16bcf7fc8158 100644
--- a/drivers/staging/greybus/gpio.c
+++ b/drivers/staging/greybus/gpio.c
@@ -42,11 +42,6 @@ struct gb_gpio_controller {
struct mutex irq_lock;
};
-static inline struct gb_gpio_controller *gpio_chip_to_gb_gpio_controller(struct gpio_chip *chip)
-{
- return container_of(chip, struct gb_gpio_controller, chip);
-}
-
static struct gpio_chip *irq_data_to_gpio_chip(struct irq_data *d)
{
return d->domain->host_data;
@@ -278,7 +273,7 @@ static void _gb_gpio_irq_set_type(struct gb_gpio_controller *ggc,
static void gb_gpio_irq_mask(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
line->masked = true;
@@ -288,7 +283,7 @@ static void gb_gpio_irq_mask(struct irq_data *d)
static void gb_gpio_irq_unmask(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
line->masked = false;
@@ -298,7 +293,7 @@ static void gb_gpio_irq_unmask(struct irq_data *d)
static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
struct device *dev = &ggc->gbphy_dev->dev;
u8 irq_type;
@@ -336,7 +331,7 @@ static int gb_gpio_irq_set_type(struct irq_data *d, unsigned int type)
static void gb_gpio_irq_bus_lock(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
mutex_lock(&ggc->irq_lock);
}
@@ -344,7 +339,7 @@ static void gb_gpio_irq_bus_lock(struct irq_data *d)
static void gb_gpio_irq_bus_sync_unlock(struct irq_data *d)
{
struct gpio_chip *chip = irq_data_to_gpio_chip(d);
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
struct gb_gpio_line *line = &ggc->lines[d->hwirq];
if (line->irq_type_pending) {
@@ -407,21 +402,21 @@ static int gb_gpio_request_handler(struct gb_operation *op)
static int gb_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
return gb_gpio_activate_operation(ggc, (u8)offset);
}
static void gb_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
gb_gpio_deactivate_operation(ggc, (u8)offset);
}
static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
u8 which;
int ret;
@@ -435,7 +430,7 @@ static int gb_gpio_get_direction(struct gpio_chip *chip, unsigned int offset)
static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
return gb_gpio_direction_in_operation(ggc, (u8)offset);
}
@@ -443,14 +438,14 @@ static int gb_gpio_direction_input(struct gpio_chip *chip, unsigned int offset)
static int gb_gpio_direction_output(struct gpio_chip *chip, unsigned int offset,
int value)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
return gb_gpio_direction_out_operation(ggc, (u8)offset, !!value);
}
static int gb_gpio_get(struct gpio_chip *chip, unsigned int offset)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
u8 which;
int ret;
@@ -464,7 +459,7 @@ static int gb_gpio_get(struct gpio_chip *chip, unsigned int offset)
static void gb_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
gb_gpio_set_value_operation(ggc, (u8)offset, !!value);
}
@@ -472,7 +467,7 @@ static void gb_gpio_set(struct gpio_chip *chip, unsigned int offset, int value)
static int gb_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
unsigned long config)
{
- struct gb_gpio_controller *ggc = gpio_chip_to_gb_gpio_controller(chip);
+ struct gb_gpio_controller *ggc = gpiochip_get_data(chip);
u32 debounce;
if (pinconf_to_config_param(config) != PIN_CONFIG_INPUT_DEBOUNCE)
@@ -579,7 +574,7 @@ static int gb_gpio_probe(struct gbphy_device *gbphy_dev,
if (ret)
goto exit_line_free;
- ret = gpiochip_add_data(gpio, NULL);
+ ret = gpiochip_add_data(gpio, ggc);
if (ret) {
dev_err(&gbphy_dev->dev, "failed to add gpio chip: %d\n", ret);
goto exit_line_free;
diff --git a/drivers/staging/greybus/uart.c b/drivers/staging/greybus/uart.c
index cdf4ebb93b10..8eab94cb06fa 100644
--- a/drivers/staging/greybus/uart.c
+++ b/drivers/staging/greybus/uart.c
@@ -596,11 +596,13 @@ static int get_serial_info(struct tty_struct *tty,
struct gb_tty *gb_tty = tty->driver_data;
ss->line = gb_tty->minor;
+ mutex_lock(&gb_tty->port.mutex);
ss->close_delay = jiffies_to_msecs(gb_tty->port.close_delay) / 10;
ss->closing_wait =
gb_tty->port.closing_wait == ASYNC_CLOSING_WAIT_NONE ?
ASYNC_CLOSING_WAIT_NONE :
jiffies_to_msecs(gb_tty->port.closing_wait) / 10;
+ mutex_unlock(&gb_tty->port.mutex);
return 0;
}
diff --git a/drivers/staging/iio/TODO b/drivers/staging/iio/TODO
deleted file mode 100644
index 0fa6a5500bdb..000000000000
--- a/drivers/staging/iio/TODO
+++ /dev/null
@@ -1,5 +0,0 @@
-2020-02-25
-
-
-Contact: Jonathan Cameron <jic23@kernel.org>.
-Mailing list: linux-iio@vger.kernel.org
diff --git a/drivers/staging/iio/accel/adis16203.c b/drivers/staging/iio/accel/adis16203.c
index c0e4c9266b5f..c1c73308800c 100644
--- a/drivers/staging/iio/accel/adis16203.c
+++ b/drivers/staging/iio/accel/adis16203.c
@@ -312,4 +312,4 @@ MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices ADIS16203 Programmable 360 Degrees Inclinometer");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:adis16203");
-MODULE_IMPORT_NS(IIO_ADISLIB);
+MODULE_IMPORT_NS("IIO_ADISLIB");
diff --git a/drivers/staging/iio/accel/adis16240.c b/drivers/staging/iio/accel/adis16240.c
index 337492785f04..3be3eaf5d9d4 100644
--- a/drivers/staging/iio/accel/adis16240.c
+++ b/drivers/staging/iio/accel/adis16240.c
@@ -440,4 +440,4 @@ MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>");
MODULE_DESCRIPTION("Analog Devices Programmable Impact Sensor and Recorder");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("spi:adis16240");
-MODULE_IMPORT_NS(IIO_ADISLIB);
+MODULE_IMPORT_NS("IIO_ADISLIB");
diff --git a/drivers/staging/iio/impedance-analyzer/ad5933.c b/drivers/staging/iio/impedance-analyzer/ad5933.c
index 4ae1a7039418..d5544fc2fe98 100644
--- a/drivers/staging/iio/impedance-analyzer/ad5933.c
+++ b/drivers/staging/iio/impedance-analyzer/ad5933.c
@@ -628,9 +628,9 @@ static void ad5933_work(struct work_struct *work)
int scan_count = bitmap_weight(indio_dev->active_scan_mask,
iio_get_masklength(indio_dev));
ret = ad5933_i2c_read(st->client,
- test_bit(1, indio_dev->active_scan_mask) ?
- AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
- scan_count * 2, (u8 *)buf);
+ test_bit(1, indio_dev->active_scan_mask) ?
+ AD5933_REG_REAL_DATA : AD5933_REG_IMAG_DATA,
+ scan_count * 2, (u8 *)buf);
if (ret)
return;
diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
index d92b5cce107a..2841824cd0ca 100644
--- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
+++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c
@@ -1482,4 +1482,4 @@ MODULE_AUTHOR("Wen Wang <wen.w.wang@intel.com>");
MODULE_AUTHOR("Xiaolin Zhang <xiaolin.zhang@intel.com>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Intel ATOM Platform ISP Driver");
-MODULE_IMPORT_NS(INTEL_IPU_BRIDGE);
+MODULE_IMPORT_NS("INTEL_IPU_BRIDGE");
diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
index 712f916f0935..71e6e278a4b3 100644
--- a/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
+++ b/drivers/staging/media/deprecated/atmel/atmel-sama5d2-isc.c
@@ -629,7 +629,7 @@ MODULE_DEVICE_TABLE(of, atmel_isc_of_match);
static struct platform_driver atmel_isc_driver = {
.probe = atmel_isc_probe,
- .remove_new = atmel_isc_remove,
+ .remove = atmel_isc_remove,
.driver = {
.name = "atmel-sama5d2-isc",
.pm = &atmel_isc_dev_pm_ops,
diff --git a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
index 9485167d5b7d..1f74c2dd044c 100644
--- a/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
+++ b/drivers/staging/media/deprecated/atmel/atmel-sama7g5-isc.c
@@ -592,7 +592,7 @@ MODULE_DEVICE_TABLE(of, microchip_xisc_of_match);
static struct platform_driver microchip_xisc_driver = {
.probe = microchip_xisc_probe,
- .remove_new = microchip_xisc_remove,
+ .remove = microchip_xisc_remove,
.driver = {
.name = "microchip-sama7g5-xisc",
.pm = &microchip_xisc_dev_pm_ops,
diff --git a/drivers/staging/media/imx/imx-media-csi.c b/drivers/staging/media/imx/imx-media-csi.c
index 785aac881922..3edbc57be2ca 100644
--- a/drivers/staging/media/imx/imx-media-csi.c
+++ b/drivers/staging/media/imx/imx-media-csi.c
@@ -2076,7 +2076,7 @@ MODULE_DEVICE_TABLE(platform, imx_csi_ids);
static struct platform_driver imx_csi_driver = {
.probe = imx_csi_probe,
- .remove_new = imx_csi_remove,
+ .remove = imx_csi_remove,
.id_table = imx_csi_ids,
.driver = {
.name = "imx-ipuv3-csi",
diff --git a/drivers/staging/media/imx/imx-media-dev.c b/drivers/staging/media/imx/imx-media-dev.c
index be54dca11465..a08389b99d14 100644
--- a/drivers/staging/media/imx/imx-media-dev.c
+++ b/drivers/staging/media/imx/imx-media-dev.c
@@ -129,7 +129,7 @@ MODULE_DEVICE_TABLE(of, imx_media_dt_ids);
static struct platform_driver imx_media_pdrv = {
.probe = imx_media_probe,
- .remove_new = imx_media_remove,
+ .remove = imx_media_remove,
.driver = {
.name = "imx-media",
.of_match_table = imx_media_dt_ids,
diff --git a/drivers/staging/media/imx/imx6-mipi-csi2.c b/drivers/staging/media/imx/imx6-mipi-csi2.c
index 0d8b42061623..dd8c7b3233bc 100644
--- a/drivers/staging/media/imx/imx6-mipi-csi2.c
+++ b/drivers/staging/media/imx/imx6-mipi-csi2.c
@@ -836,7 +836,7 @@ static struct platform_driver csi2_driver = {
.of_match_table = csi2_dt_ids,
},
.probe = csi2_probe,
- .remove_new = csi2_remove,
+ .remove = csi2_remove,
};
module_platform_driver(csi2_driver);
diff --git a/drivers/staging/media/meson/vdec/vdec.c b/drivers/staging/media/meson/vdec/vdec.c
index 52185090129b..6d34a482492e 100644
--- a/drivers/staging/media/meson/vdec/vdec.c
+++ b/drivers/staging/media/meson/vdec/vdec.c
@@ -1117,7 +1117,7 @@ static void vdec_remove(struct platform_device *pdev)
static struct platform_driver meson_vdec_driver = {
.probe = vdec_probe,
- .remove_new = vdec_remove,
+ .remove = vdec_remove,
.driver = {
.name = "meson-vdec",
.of_match_table = vdec_dt_match,
diff --git a/drivers/staging/media/rkvdec/rkvdec.c b/drivers/staging/media/rkvdec/rkvdec.c
index f468af64bbef..f9bef5173bf2 100644
--- a/drivers/staging/media/rkvdec/rkvdec.c
+++ b/drivers/staging/media/rkvdec/rkvdec.c
@@ -1101,7 +1101,7 @@ static const struct dev_pm_ops rkvdec_pm_ops = {
static struct platform_driver rkvdec_driver = {
.probe = rkvdec_probe,
- .remove_new = rkvdec_remove,
+ .remove = rkvdec_remove,
.driver = {
.name = "rkvdec",
.of_match_table = of_rkvdec_match,
diff --git a/drivers/staging/media/starfive/camss/stf-camss.c b/drivers/staging/media/starfive/camss/stf-camss.c
index b6d34145bc19..259aaad010d2 100644
--- a/drivers/staging/media/starfive/camss/stf-camss.c
+++ b/drivers/staging/media/starfive/camss/stf-camss.c
@@ -422,7 +422,7 @@ static const struct dev_pm_ops stfcamss_pm_ops = {
static struct platform_driver stfcamss_driver = {
.probe = stfcamss_probe,
- .remove_new = stfcamss_remove,
+ .remove = stfcamss_remove,
.driver = {
.name = "starfive-camss",
.pm = &stfcamss_pm_ops,
diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.c b/drivers/staging/media/sunxi/cedrus/cedrus.c
index f52df6836045..52a9588462ce 100644
--- a/drivers/staging/media/sunxi/cedrus/cedrus.c
+++ b/drivers/staging/media/sunxi/cedrus/cedrus.c
@@ -705,7 +705,7 @@ static const struct dev_pm_ops cedrus_dev_pm_ops = {
static struct platform_driver cedrus_driver = {
.probe = cedrus_probe,
- .remove_new = cedrus_remove,
+ .remove = cedrus_remove,
.driver = {
.name = CEDRUS_NAME,
.of_match_table = cedrus_dt_match,
diff --git a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c
index 58f8ae92320d..6877f2beee8c 100644
--- a/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c
+++ b/drivers/staging/media/sunxi/sun6i-isp/sun6i_isp.c
@@ -536,7 +536,7 @@ MODULE_DEVICE_TABLE(of, sun6i_isp_of_match);
static struct platform_driver sun6i_isp_platform_driver = {
.probe = sun6i_isp_probe,
- .remove_new = sun6i_isp_remove,
+ .remove = sun6i_isp_remove,
.driver = {
.name = SUN6I_ISP_NAME,
.of_match_table = sun6i_isp_of_match,
diff --git a/drivers/staging/media/tegra-video/csi.c b/drivers/staging/media/tegra-video/csi.c
index 255cccd0c5fd..604185c00a1a 100644
--- a/drivers/staging/media/tegra-video/csi.c
+++ b/drivers/staging/media/tegra-video/csi.c
@@ -858,5 +858,5 @@ struct platform_driver tegra_csi_driver = {
.pm = &tegra_csi_pm_ops,
},
.probe = tegra_csi_probe,
- .remove_new = tegra_csi_remove,
+ .remove = tegra_csi_remove,
};
diff --git a/drivers/staging/media/tegra-video/vi.c b/drivers/staging/media/tegra-video/vi.c
index ad481b35e618..c9276ff76157 100644
--- a/drivers/staging/media/tegra-video/vi.c
+++ b/drivers/staging/media/tegra-video/vi.c
@@ -1977,5 +1977,5 @@ struct platform_driver tegra_vi_driver = {
.pm = &tegra_vi_pm_ops,
},
.probe = tegra_vi_probe,
- .remove_new = tegra_vi_remove,
+ .remove = tegra_vi_remove,
};
diff --git a/drivers/staging/media/tegra-video/vip.c b/drivers/staging/media/tegra-video/vip.c
index 8504b9ea9cea..5ec717f3afd5 100644
--- a/drivers/staging/media/tegra-video/vip.c
+++ b/drivers/staging/media/tegra-video/vip.c
@@ -281,5 +281,5 @@ struct platform_driver tegra_vip_driver = {
.of_match_table = tegra_vip_of_id_table,
},
.probe = tegra_vip_probe,
- .remove_new = tegra_vip_remove,
+ .remove = tegra_vip_remove,
};
diff --git a/drivers/staging/most/TODO b/drivers/staging/most/TODO
index 4fa11a9d2cf7..a6448a05ed46 100644
--- a/drivers/staging/most/TODO
+++ b/drivers/staging/most/TODO
@@ -1,8 +1 @@
* Get through code review with Greg Kroah-Hartman
-
-Contact:
-To:
-Christian Gromm <christian.gromm@microchip.com>
-Cc:
-Michael Fabry <Michael.Fabry@microchip.com>
-Christian Gromm <chris@engineersdelight.de>
diff --git a/drivers/staging/most/dim2/dim2.c b/drivers/staging/most/dim2/dim2.c
index ed6a9cc88541..dad2abe6c0c9 100644
--- a/drivers/staging/most/dim2/dim2.c
+++ b/drivers/staging/most/dim2/dim2.c
@@ -1090,7 +1090,7 @@ MODULE_DEVICE_TABLE(of, dim2_of_match);
static struct platform_driver dim2_driver = {
.probe = dim2_probe,
- .remove_new = dim2_remove,
+ .remove = dim2_remove,
.driver = {
.name = "hdm_dim2",
.of_match_table = dim2_of_match,
diff --git a/drivers/staging/most/i2c/i2c.c b/drivers/staging/most/i2c/i2c.c
index ce869280a056..184b2dd11fc3 100644
--- a/drivers/staging/most/i2c/i2c.c
+++ b/drivers/staging/most/i2c/i2c.c
@@ -352,8 +352,8 @@ static void i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id i2c_id[] = {
- { "most_i2c", 0 },
- { }, /* Terminating entry */
+ { "most_i2c" },
+ { } /* Terminating entry */
};
MODULE_DEVICE_TABLE(i2c, i2c_id);
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 977f8fc29e63..263774e6a78c 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -952,7 +952,7 @@ MODULE_DEVICE_TABLE(of, nvidia_nvec_of_match);
static struct platform_driver nvec_device_driver = {
.probe = tegra_nvec_probe,
- .remove_new = tegra_nvec_remove,
+ .remove = tegra_nvec_remove,
.driver = {
.name = "nvec",
.pm = &nvec_pm_ops,
diff --git a/drivers/staging/nvec/nvec_kbd.c b/drivers/staging/nvec/nvec_kbd.c
index d0259c80f810..d2b91318f151 100644
--- a/drivers/staging/nvec/nvec_kbd.c
+++ b/drivers/staging/nvec/nvec_kbd.c
@@ -175,7 +175,7 @@ static void nvec_kbd_remove(struct platform_device *pdev)
static struct platform_driver nvec_kbd_driver = {
.probe = nvec_kbd_probe,
- .remove_new = nvec_kbd_remove,
+ .remove = nvec_kbd_remove,
.driver = {
.name = "nvec-kbd",
},
diff --git a/drivers/staging/nvec/nvec_power.c b/drivers/staging/nvec/nvec_power.c
index 9943b1fff190..e0e67a3eb722 100644
--- a/drivers/staging/nvec/nvec_power.c
+++ b/drivers/staging/nvec/nvec_power.c
@@ -433,7 +433,7 @@ static void nvec_power_remove(struct platform_device *pdev)
static struct platform_driver nvec_power_driver = {
.probe = nvec_power_probe,
- .remove_new = nvec_power_remove,
+ .remove = nvec_power_remove,
.driver = {
.name = "nvec-power",
}
diff --git a/drivers/staging/nvec/nvec_ps2.c b/drivers/staging/nvec/nvec_ps2.c
index f34016c4a26b..575233fa1677 100644
--- a/drivers/staging/nvec/nvec_ps2.c
+++ b/drivers/staging/nvec/nvec_ps2.c
@@ -175,7 +175,7 @@ static SIMPLE_DEV_PM_OPS(nvec_mouse_pm_ops, nvec_mouse_suspend,
static struct platform_driver nvec_mouse_driver = {
.probe = nvec_mouse_probe,
- .remove_new = nvec_mouse_remove,
+ .remove = nvec_mouse_remove,
.driver = {
.name = "nvec-mouse",
.pm = &nvec_mouse_pm_ops,
diff --git a/drivers/staging/octeon/ethernet-tx.c b/drivers/staging/octeon/ethernet-tx.c
index bbf33b88bb7c..261f8dbdc382 100644
--- a/drivers/staging/octeon/ethernet-tx.c
+++ b/drivers/staging/octeon/ethernet-tx.c
@@ -40,8 +40,8 @@
#define GET_SKBUFF_QOS(skb) 0
#endif
-static void cvm_oct_tx_do_cleanup(unsigned long arg);
-static DECLARE_TASKLET_OLD(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup);
+static void cvm_oct_tx_do_cleanup(struct tasklet_struct *clean);
+static DECLARE_TASKLET(cvm_oct_tx_cleanup_tasklet, cvm_oct_tx_do_cleanup);
/* Maximum number of SKBs to try to free per xmit packet. */
#define MAX_SKB_TO_FREE (MAX_OUT_QUEUE_DEPTH * 2)
@@ -670,7 +670,7 @@ void cvm_oct_tx_shutdown_dev(struct net_device *dev)
}
}
-static void cvm_oct_tx_do_cleanup(unsigned long arg)
+static void cvm_oct_tx_do_cleanup(struct tasklet_struct *clean)
{
int port;
diff --git a/drivers/staging/octeon/ethernet.c b/drivers/staging/octeon/ethernet.c
index a5e99cc78a45..eadb74fc14c8 100644
--- a/drivers/staging/octeon/ethernet.c
+++ b/drivers/staging/octeon/ethernet.c
@@ -977,7 +977,7 @@ MODULE_DEVICE_TABLE(of, cvm_oct_match);
static struct platform_driver cvm_oct_driver = {
.probe = cvm_oct_probe,
- .remove_new = cvm_oct_remove,
+ .remove = cvm_oct_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = cvm_oct_match,
diff --git a/drivers/staging/olpc_dcon/Kconfig b/drivers/staging/olpc_dcon/Kconfig
deleted file mode 100644
index d0ba34cc32f7..000000000000
--- a/drivers/staging/olpc_dcon/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config FB_OLPC_DCON
- tristate "One Laptop Per Child Display CONtroller support"
- depends on OLPC && FB && BROKEN
- depends on I2C
- depends on GPIO_CS5535 && ACPI
- select BACKLIGHT_CLASS_DEVICE
- help
- In order to support very low power operation, the XO laptop uses a
- secondary Display CONtroller, or DCON. This secondary controller
- is present in the video pipeline between the primary display
- controller (integrate into the processor or chipset) and the LCD
- panel. It allows the main processor/display controller to be
- completely powered off while still retaining an image on the display.
- This controller is only available on OLPC platforms. Unless you have
- one of these platforms, you will want to say 'N'.
-
diff --git a/drivers/staging/olpc_dcon/Makefile b/drivers/staging/olpc_dcon/Makefile
deleted file mode 100644
index 734b2ce26066..000000000000
--- a/drivers/staging/olpc_dcon/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-olpc-dcon-objs += olpc_dcon.o olpc_dcon_xo_1.o olpc_dcon_xo_1_5.o
-obj-$(CONFIG_FB_OLPC_DCON) += olpc-dcon.o
-
-
diff --git a/drivers/staging/olpc_dcon/TODO b/drivers/staging/olpc_dcon/TODO
deleted file mode 100644
index 7c263358b44a..000000000000
--- a/drivers/staging/olpc_dcon/TODO
+++ /dev/null
@@ -1,15 +0,0 @@
-TODO:
- - complete rewrite:
- 1. The underlying fbdev drivers need to be converted into drm kernel
- modesetting drivers.
- 2. The dcon low-power display mode can then be integrated using the
- drm damage tracking and self-refresh helpers.
- This bolted-on self-refresh support that digs around in fbdev
- internals, but isn't properly integrated, is not the correct solution.
- - see if vx855 gpio API can be made similar enough to cs5535 so we can
- share more code
-
-Please send patches to Greg Kroah-Hartman <greg@kroah.com> and
-copy:
- Daniel Drake <dsd@laptop.org>
- Jens Frederich <jfrederich@gmail.com>
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.c b/drivers/staging/olpc_dcon/olpc_dcon.c
deleted file mode 100644
index 4cb904a5f8f4..000000000000
--- a/drivers/staging/olpc_dcon/olpc_dcon.c
+++ /dev/null
@@ -1,807 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Mainly by David Woodhouse, somewhat modified by Jordan Crouse
- *
- * Copyright © 2006-2007 Red Hat, Inc.
- * Copyright © 2006-2007 Advanced Micro Devices, Inc.
- * Copyright © 2009 VIA Technology, Inc.
- * Copyright (c) 2010-2011 Andres Salomon <dilinger@queued.net>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/fb.h>
-#include <linux/console.h>
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/backlight.h>
-#include <linux/device.h>
-#include <linux/uaccess.h>
-#include <linux/ctype.h>
-#include <linux/panic_notifier.h>
-#include <linux/reboot.h>
-#include <linux/olpc-ec.h>
-#include <asm/tsc.h>
-#include <asm/olpc.h>
-
-#include "olpc_dcon.h"
-
-/* Module definitions */
-
-static ushort resumeline = 898;
-module_param(resumeline, ushort, 0444);
-
-static struct dcon_platform_data *pdata;
-
-/* I2C structures */
-
-/* Platform devices */
-static struct platform_device *dcon_device;
-
-static unsigned short normal_i2c[] = { 0x0d, I2C_CLIENT_END };
-
-static s32 dcon_write(struct dcon_priv *dcon, u8 reg, u16 val)
-{
- return i2c_smbus_write_word_data(dcon->client, reg, val);
-}
-
-static s32 dcon_read(struct dcon_priv *dcon, u8 reg)
-{
- return i2c_smbus_read_word_data(dcon->client, reg);
-}
-
-/* ===== API functions - these are called by a variety of users ==== */
-
-static int dcon_hw_init(struct dcon_priv *dcon, int is_init)
-{
- u16 ver;
- int rc = 0;
-
- ver = dcon_read(dcon, DCON_REG_ID);
- if ((ver >> 8) != 0xDC) {
- pr_err("DCON ID not 0xDCxx: 0x%04x instead.\n", ver);
- rc = -ENXIO;
- goto err;
- }
-
- if (is_init) {
- pr_info("Discovered DCON version %x\n", ver & 0xFF);
- rc = pdata->init(dcon);
- if (rc != 0) {
- pr_err("Unable to init.\n");
- goto err;
- }
- }
-
- if (ver < 0xdc02) {
- dev_err(&dcon->client->dev,
- "DCON v1 is unsupported, giving up..\n");
- rc = -ENODEV;
- goto err;
- }
-
- /* SDRAM setup/hold time */
- dcon_write(dcon, 0x3a, 0xc040);
- dcon_write(dcon, DCON_REG_MEM_OPT_A, 0x0000); /* clear option bits */
- dcon_write(dcon, DCON_REG_MEM_OPT_A,
- MEM_DLL_CLOCK_DELAY | MEM_POWER_DOWN);
- dcon_write(dcon, DCON_REG_MEM_OPT_B, MEM_SOFT_RESET);
-
- /* Colour swizzle, AA, no passthrough, backlight */
- if (is_init) {
- dcon->disp_mode = MODE_PASSTHRU | MODE_BL_ENABLE |
- MODE_CSWIZZLE | MODE_COL_AA;
- }
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
-
- /* Set the scanline to interrupt on during resume */
- dcon_write(dcon, DCON_REG_SCAN_INT, resumeline);
-
-err:
- return rc;
-}
-
-/*
- * The smbus doesn't always come back due to what is believed to be
- * hardware (power rail) bugs. For older models where this is known to
- * occur, our solution is to attempt to wait for the bus to stabilize;
- * if it doesn't happen, cut power to the dcon, repower it, and wait
- * for the bus to stabilize. Rinse, repeat until we have a working
- * smbus. For newer models, we simply BUG(); we want to know if this
- * still happens despite the power fixes that have been made!
- */
-static int dcon_bus_stabilize(struct dcon_priv *dcon, int is_powered_down)
-{
- unsigned long timeout;
- u8 pm;
- int x;
-
-power_up:
- if (is_powered_down) {
- pm = 1;
- x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
- if (x) {
- pr_warn("unable to force dcon to power up: %d!\n", x);
- return x;
- }
- usleep_range(10000, 11000); /* we'll be conservative */
- }
-
- pdata->bus_stabilize_wiggle();
-
- for (x = -1, timeout = 50; timeout && x < 0; timeout--) {
- usleep_range(1000, 1100);
- x = dcon_read(dcon, DCON_REG_ID);
- }
- if (x < 0) {
- pr_err("unable to stabilize dcon's smbus, reasserting power and praying.\n");
- BUG_ON(olpc_board_at_least(olpc_board(0xc2)));
- pm = 0;
- olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
- msleep(100);
- is_powered_down = 1;
- goto power_up; /* argh, stupid hardware.. */
- }
-
- if (is_powered_down)
- return dcon_hw_init(dcon, 0);
- return 0;
-}
-
-static void dcon_set_backlight(struct dcon_priv *dcon, u8 level)
-{
- dcon->bl_val = level;
- dcon_write(dcon, DCON_REG_BRIGHT, dcon->bl_val);
-
- /* Purposely turn off the backlight when we go to level 0 */
- if (dcon->bl_val == 0) {
- dcon->disp_mode &= ~MODE_BL_ENABLE;
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
- } else if (!(dcon->disp_mode & MODE_BL_ENABLE)) {
- dcon->disp_mode |= MODE_BL_ENABLE;
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
- }
-}
-
-/* Set the output type to either color or mono */
-static int dcon_set_mono_mode(struct dcon_priv *dcon, bool enable_mono)
-{
- if (dcon->mono == enable_mono)
- return 0;
-
- dcon->mono = enable_mono;
-
- if (enable_mono) {
- dcon->disp_mode &= ~(MODE_CSWIZZLE | MODE_COL_AA);
- dcon->disp_mode |= MODE_MONO_LUMA;
- } else {
- dcon->disp_mode &= ~(MODE_MONO_LUMA);
- dcon->disp_mode |= MODE_CSWIZZLE | MODE_COL_AA;
- }
-
- dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode);
- return 0;
-}
-
-/* For now, this will be really stupid - we need to address how
- * DCONLOAD works in a sleep and account for it accordingly
- */
-
-static void dcon_sleep(struct dcon_priv *dcon, bool sleep)
-{
- int x;
-
- /* Turn off the backlight and put the DCON to sleep */
-
- if (dcon->asleep == sleep)
- return;
-
- if (!olpc_board_at_least(olpc_board(0xc2)))
- return;
-
- if (sleep) {
- u8 pm = 0;
-
- x = olpc_ec_cmd(EC_DCON_POWER_MODE, &pm, 1, NULL, 0);
- if (x)
- pr_warn("unable to force dcon to power down: %d!\n", x);
- else
- dcon->asleep = sleep;
- } else {
- /* Only re-enable the backlight if the backlight value is set */
- if (dcon->bl_val != 0)
- dcon->disp_mode |= MODE_BL_ENABLE;
- x = dcon_bus_stabilize(dcon, 1);
- if (x)
- pr_warn("unable to reinit dcon hardware: %d!\n", x);
- else
- dcon->asleep = sleep;
-
- /* Restore backlight */
- dcon_set_backlight(dcon, dcon->bl_val);
- }
-
- /* We should turn off some stuff in the framebuffer - but what? */
-}
-
-/* the DCON seems to get confused if we change DCONLOAD too
- * frequently -- i.e., approximately faster than frame time.
- * normally we don't change it this fast, so in general we won't
- * delay here.
- */
-static void dcon_load_holdoff(struct dcon_priv *dcon)
-{
- ktime_t delta_t, now;
-
- while (1) {
- now = ktime_get();
- delta_t = ktime_sub(now, dcon->load_time);
- if (ktime_to_ns(delta_t) > NSEC_PER_MSEC * 20)
- break;
- mdelay(4);
- }
-}
-
-static bool dcon_blank_fb(struct dcon_priv *dcon, bool blank)
-{
- int err;
-
- console_lock();
- lock_fb_info(dcon->fbinfo);
-
- dcon->ignore_fb_events = true;
- err = fb_blank(dcon->fbinfo,
- blank ? FB_BLANK_POWERDOWN : FB_BLANK_UNBLANK);
- dcon->ignore_fb_events = false;
- unlock_fb_info(dcon->fbinfo);
- console_unlock();
-
- if (err) {
- dev_err(&dcon->client->dev, "couldn't %sblank framebuffer\n",
- blank ? "" : "un");
- return false;
- }
- return true;
-}
-
-/* Set the source of the display (CPU or DCON) */
-static void dcon_source_switch(struct work_struct *work)
-{
- struct dcon_priv *dcon = container_of(work, struct dcon_priv,
- switch_source);
- int source = dcon->pending_src;
-
- if (dcon->curr_src == source)
- return;
-
- dcon_load_holdoff(dcon);
-
- dcon->switched = false;
-
- switch (source) {
- case DCON_SOURCE_CPU:
- pr_info("%s to CPU\n", __func__);
- /* Enable the scanline interrupt bit */
- if (dcon_write(dcon, DCON_REG_MODE,
- dcon->disp_mode | MODE_SCAN_INT))
- pr_err("couldn't enable scanline interrupt!\n");
- else
- /* Wait up to one second for the scanline interrupt */
- wait_event_timeout(dcon->waitq, dcon->switched, HZ);
-
- if (!dcon->switched)
- pr_err("Timeout entering CPU mode; expect a screen glitch.\n");
-
- /* Turn off the scanline interrupt */
- if (dcon_write(dcon, DCON_REG_MODE, dcon->disp_mode))
- pr_err("couldn't disable scanline interrupt!\n");
-
- /*
- * Ideally we'd like to disable interrupts here so that the
- * fb unblanking and DCON turn on happen at a known time value;
- * however, we can't do that right now with fb_blank
- * messing with semaphores.
- *
- * For now, we just hope..
- */
- if (!dcon_blank_fb(dcon, false)) {
- pr_err("Failed to enter CPU mode\n");
- dcon->pending_src = DCON_SOURCE_DCON;
- return;
- }
-
- /* And turn off the DCON */
- pdata->set_dconload(1);
- dcon->load_time = ktime_get();
-
- pr_info("The CPU has control\n");
- break;
- case DCON_SOURCE_DCON:
- {
- ktime_t delta_t;
-
- pr_info("%s to DCON\n", __func__);
-
- /* Clear DCONLOAD - this implies that the DCON is in control */
- pdata->set_dconload(0);
- dcon->load_time = ktime_get();
-
- wait_event_timeout(dcon->waitq, dcon->switched, HZ / 2);
-
- if (!dcon->switched) {
- pr_err("Timeout entering DCON mode; expect a screen glitch.\n");
- } else {
- /* sometimes the DCON doesn't follow its own rules,
- * and doesn't wait for two vsync pulses before
- * ack'ing the frame load with an IRQ. the result
- * is that the display shows the *previously*
- * loaded frame. we can detect this by looking at
- * the time between asserting DCONLOAD and the IRQ --
- * if it's less than 20msec, then the DCON couldn't
- * have seen two VSYNC pulses. in that case we
- * deassert and reassert, and hope for the best.
- * see http://dev.laptop.org/ticket/9664
- */
- delta_t = ktime_sub(dcon->irq_time, dcon->load_time);
- if (dcon->switched && ktime_to_ns(delta_t)
- < NSEC_PER_MSEC * 20) {
- pr_err("missed loading, retrying\n");
- pdata->set_dconload(1);
- mdelay(41);
- pdata->set_dconload(0);
- dcon->load_time = ktime_get();
- mdelay(41);
- }
- }
-
- dcon_blank_fb(dcon, true);
- pr_info("The DCON has control\n");
- break;
- }
- default:
- BUG();
- }
-
- dcon->curr_src = source;
-}
-
-static void dcon_set_source(struct dcon_priv *dcon, int arg)
-{
- if (dcon->pending_src == arg)
- return;
-
- dcon->pending_src = arg;
-
- if (dcon->curr_src != arg)
- schedule_work(&dcon->switch_source);
-}
-
-static void dcon_set_source_sync(struct dcon_priv *dcon, int arg)
-{
- dcon_set_source(dcon, arg);
- flush_work(&dcon->switch_source);
-}
-
-static ssize_t dcon_mode_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%4.4X\n", dcon->disp_mode);
-}
-
-static ssize_t dcon_sleep_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", dcon->asleep);
-}
-
-static ssize_t dcon_freeze_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", dcon->curr_src == DCON_SOURCE_DCON ? 1 : 0);
-}
-
-static ssize_t dcon_mono_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
-
- return sprintf(buf, "%d\n", dcon->mono);
-}
-
-static ssize_t dcon_resumeline_show(struct device *dev,
- struct device_attribute *attr,
- char *buf)
-{
- return sprintf(buf, "%d\n", resumeline);
-}
-
-static ssize_t dcon_mono_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned long enable_mono;
- int rc;
-
- rc = kstrtoul(buf, 10, &enable_mono);
- if (rc)
- return rc;
-
- dcon_set_mono_mode(dev_get_drvdata(dev), enable_mono ? true : false);
-
- return count;
-}
-
-static ssize_t dcon_freeze_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct dcon_priv *dcon = dev_get_drvdata(dev);
- unsigned long output;
- int ret;
-
- ret = kstrtoul(buf, 10, &output);
- if (ret)
- return ret;
-
- switch (output) {
- case 0:
- dcon_set_source(dcon, DCON_SOURCE_CPU);
- break;
- case 1:
- dcon_set_source_sync(dcon, DCON_SOURCE_DCON);
- break;
- case 2: /* normally unused */
- dcon_set_source(dcon, DCON_SOURCE_DCON);
- break;
- default:
- return -EINVAL;
- }
-
- return count;
-}
-
-static ssize_t dcon_resumeline_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned short rl;
- int rc;
-
- rc = kstrtou16(buf, 10, &rl);
- if (rc)
- return rc;
-
- resumeline = rl;
- dcon_write(dev_get_drvdata(dev), DCON_REG_SCAN_INT, resumeline);
-
- return count;
-}
-
-static ssize_t dcon_sleep_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- unsigned long output;
- int ret;
-
- ret = kstrtoul(buf, 10, &output);
- if (ret)
- return ret;
-
- dcon_sleep(dev_get_drvdata(dev), output ? true : false);
- return count;
-}
-
-static struct device_attribute dcon_device_files[] = {
- __ATTR(mode, 0444, dcon_mode_show, NULL),
- __ATTR(sleep, 0644, dcon_sleep_show, dcon_sleep_store),
- __ATTR(freeze, 0644, dcon_freeze_show, dcon_freeze_store),
- __ATTR(monochrome, 0644, dcon_mono_show, dcon_mono_store),
- __ATTR(resumeline, 0644, dcon_resumeline_show, dcon_resumeline_store),
-};
-
-static int dcon_bl_update(struct backlight_device *dev)
-{
- struct dcon_priv *dcon = bl_get_data(dev);
- u8 level = backlight_get_brightness(dev) & 0x0F;
-
- if (level != dcon->bl_val)
- dcon_set_backlight(dcon, level);
-
- /* power down the DCON when the screen is blanked */
- if (!dcon->ignore_fb_events)
- dcon_sleep(dcon, !!(dev->props.state & BL_CORE_FBBLANK));
-
- return 0;
-}
-
-static int dcon_bl_get(struct backlight_device *dev)
-{
- struct dcon_priv *dcon = bl_get_data(dev);
-
- return dcon->bl_val;
-}
-
-static const struct backlight_ops dcon_bl_ops = {
- .update_status = dcon_bl_update,
- .get_brightness = dcon_bl_get,
-};
-
-static struct backlight_properties dcon_bl_props = {
- .max_brightness = 15,
- .type = BACKLIGHT_RAW,
- .power = BACKLIGHT_POWER_ON,
-};
-
-static int dcon_reboot_notify(struct notifier_block *nb,
- unsigned long foo, void *bar)
-{
- struct dcon_priv *dcon = container_of(nb, struct dcon_priv, reboot_nb);
-
- if (!dcon || !dcon->client)
- return NOTIFY_DONE;
-
- /* Turn off the DCON. Entirely. */
- dcon_write(dcon, DCON_REG_MODE, 0x39);
- dcon_write(dcon, DCON_REG_MODE, 0x32);
- return NOTIFY_DONE;
-}
-
-static int unfreeze_on_panic(struct notifier_block *nb,
- unsigned long e, void *p)
-{
- pdata->set_dconload(1);
- return NOTIFY_DONE;
-}
-
-static struct notifier_block dcon_panic_nb = {
- .notifier_call = unfreeze_on_panic,
-};
-
-static int dcon_detect(struct i2c_client *client, struct i2c_board_info *info)
-{
- strscpy(info->type, "olpc_dcon", I2C_NAME_SIZE);
-
- return 0;
-}
-
-static int dcon_probe(struct i2c_client *client)
-{
- struct dcon_priv *dcon;
- int rc, i, j;
-
- if (!pdata)
- return -ENXIO;
-
- dcon = kzalloc(sizeof(*dcon), GFP_KERNEL);
- if (!dcon)
- return -ENOMEM;
-
- dcon->client = client;
- init_waitqueue_head(&dcon->waitq);
- INIT_WORK(&dcon->switch_source, dcon_source_switch);
- dcon->reboot_nb.notifier_call = dcon_reboot_notify;
- dcon->reboot_nb.priority = -1;
-
- i2c_set_clientdata(client, dcon);
-
- if (num_registered_fb < 1) {
- dev_err(&client->dev, "DCON driver requires a registered fb\n");
- rc = -EIO;
- goto einit;
- }
- dcon->fbinfo = registered_fb[0];
-
- rc = dcon_hw_init(dcon, 1);
- if (rc)
- goto einit;
-
- /* Add the DCON device */
-
- dcon_device = platform_device_alloc("dcon", -1);
-
- if (!dcon_device) {
- pr_err("Unable to create the DCON device\n");
- rc = -ENOMEM;
- goto eirq;
- }
- rc = platform_device_add(dcon_device);
- platform_set_drvdata(dcon_device, dcon);
-
- if (rc) {
- pr_err("Unable to add the DCON device\n");
- goto edev;
- }
-
- for (i = 0; i < ARRAY_SIZE(dcon_device_files); i++) {
- rc = device_create_file(&dcon_device->dev,
- &dcon_device_files[i]);
- if (rc) {
- dev_err(&dcon_device->dev, "Cannot create sysfs file\n");
- goto ecreate;
- }
- }
-
- dcon->bl_val = dcon_read(dcon, DCON_REG_BRIGHT) & 0x0F;
-
- /* Add the backlight device for the DCON */
- dcon_bl_props.brightness = dcon->bl_val;
- dcon->bl_dev = backlight_device_register("dcon-bl", &dcon_device->dev,
- dcon, &dcon_bl_ops,
- &dcon_bl_props);
- if (IS_ERR(dcon->bl_dev)) {
- dev_err(&client->dev, "cannot register backlight dev (%ld)\n",
- PTR_ERR(dcon->bl_dev));
- dcon->bl_dev = NULL;
- }
-
- register_reboot_notifier(&dcon->reboot_nb);
- atomic_notifier_chain_register(&panic_notifier_list, &dcon_panic_nb);
-
- return 0;
-
- ecreate:
- for (j = 0; j < i; j++)
- device_remove_file(&dcon_device->dev, &dcon_device_files[j]);
- platform_device_del(dcon_device);
- edev:
- platform_device_put(dcon_device);
- dcon_device = NULL;
- eirq:
- free_irq(DCON_IRQ, dcon);
- einit:
- kfree(dcon);
- return rc;
-}
-
-static void dcon_remove(struct i2c_client *client)
-{
- struct dcon_priv *dcon = i2c_get_clientdata(client);
-
- unregister_reboot_notifier(&dcon->reboot_nb);
- atomic_notifier_chain_unregister(&panic_notifier_list, &dcon_panic_nb);
-
- free_irq(DCON_IRQ, dcon);
-
- backlight_device_unregister(dcon->bl_dev);
-
- if (dcon_device)
- platform_device_unregister(dcon_device);
- cancel_work_sync(&dcon->switch_source);
-
- kfree(dcon);
-}
-
-#ifdef CONFIG_PM
-static int dcon_suspend(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct dcon_priv *dcon = i2c_get_clientdata(client);
-
- if (!dcon->asleep) {
- /* Set up the DCON to have the source */
- dcon_set_source_sync(dcon, DCON_SOURCE_DCON);
- }
-
- return 0;
-}
-
-static int dcon_resume(struct device *dev)
-{
- struct i2c_client *client = to_i2c_client(dev);
- struct dcon_priv *dcon = i2c_get_clientdata(client);
-
- if (!dcon->asleep) {
- dcon_bus_stabilize(dcon, 0);
- dcon_set_source(dcon, DCON_SOURCE_CPU);
- }
-
- return 0;
-}
-
-#else
-
-#define dcon_suspend NULL
-#define dcon_resume NULL
-
-#endif /* CONFIG_PM */
-
-irqreturn_t dcon_interrupt(int irq, void *id)
-{
- struct dcon_priv *dcon = id;
- u8 status;
-
- if (pdata->read_status(&status))
- return IRQ_NONE;
-
- switch (status & 3) {
- case 3:
- pr_debug("DCONLOAD_MISSED interrupt\n");
- break;
-
- case 2: /* switch to DCON mode */
- case 1: /* switch to CPU mode */
- dcon->switched = true;
- dcon->irq_time = ktime_get();
- wake_up(&dcon->waitq);
- break;
-
- case 0:
- /* workaround resume case: the DCON (on 1.5) doesn't
- * ever assert status 0x01 when switching to CPU mode
- * during resume. this is because DCONLOAD is de-asserted
- * _immediately_ upon exiting S3, so the actual release
- * of the DCON happened long before this point.
- * see http://dev.laptop.org/ticket/9869
- */
- if (dcon->curr_src != dcon->pending_src && !dcon->switched) {
- dcon->switched = true;
- dcon->irq_time = ktime_get();
- wake_up(&dcon->waitq);
- pr_debug("switching w/ status 0/0\n");
- } else {
- pr_debug("scanline interrupt w/CPU\n");
- }
- }
-
- return IRQ_HANDLED;
-}
-
-static const struct dev_pm_ops dcon_pm_ops = {
- .suspend = dcon_suspend,
- .resume = dcon_resume,
-};
-
-static const struct i2c_device_id dcon_idtable[] = {
- { "olpc_dcon", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, dcon_idtable);
-
-static struct i2c_driver dcon_driver = {
- .driver = {
- .name = "olpc_dcon",
- .pm = &dcon_pm_ops,
- },
- .class = I2C_CLASS_HWMON,
- .id_table = dcon_idtable,
- .probe = dcon_probe,
- .remove = dcon_remove,
- .detect = dcon_detect,
- .address_list = normal_i2c,
-};
-
-static int __init olpc_dcon_init(void)
-{
- /* XO-1.5 */
- if (olpc_board_at_least(olpc_board(0xd0)))
- pdata = &dcon_pdata_xo_1_5;
- else
- pdata = &dcon_pdata_xo_1;
-
- return i2c_add_driver(&dcon_driver);
-}
-
-static void __exit olpc_dcon_exit(void)
-{
- i2c_del_driver(&dcon_driver);
-}
-
-module_init(olpc_dcon_init);
-module_exit(olpc_dcon_exit);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/staging/olpc_dcon/olpc_dcon.h b/drivers/staging/olpc_dcon/olpc_dcon.h
deleted file mode 100644
index 41bd1360b56e..000000000000
--- a/drivers/staging/olpc_dcon/olpc_dcon.h
+++ /dev/null
@@ -1,112 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef OLPC_DCON_H_
-#define OLPC_DCON_H_
-
-#include <linux/notifier.h>
-#include <linux/workqueue.h>
-
-/* DCON registers */
-
-#define DCON_REG_ID 0
-#define DCON_REG_MODE 1
-
-#define MODE_PASSTHRU BIT(0)
-#define MODE_SLEEP BIT(1)
-#define MODE_SLEEP_AUTO BIT(2)
-#define MODE_BL_ENABLE BIT(3)
-#define MODE_BLANK BIT(4)
-#define MODE_CSWIZZLE BIT(5)
-#define MODE_COL_AA BIT(6)
-#define MODE_MONO_LUMA BIT(7)
-#define MODE_SCAN_INT BIT(8)
-#define MODE_CLOCKDIV BIT(9)
-#define MODE_DEBUG BIT(14)
-#define MODE_SELFTEST BIT(15)
-
-#define DCON_REG_HRES 0x2
-#define DCON_REG_HTOTAL 0x3
-#define DCON_REG_HSYNC_WIDTH 0x4
-#define DCON_REG_VRES 0x5
-#define DCON_REG_VTOTAL 0x6
-#define DCON_REG_VSYNC_WIDTH 0x7
-#define DCON_REG_TIMEOUT 0x8
-#define DCON_REG_SCAN_INT 0x9
-#define DCON_REG_BRIGHT 0xa
-#define DCON_REG_MEM_OPT_A 0x41
-#define DCON_REG_MEM_OPT_B 0x42
-
-/* Load Delay Locked Loop (DLL) settings for clock delay */
-#define MEM_DLL_CLOCK_DELAY BIT(0)
-/* Memory controller power down function */
-#define MEM_POWER_DOWN BIT(8)
-/* Memory controller software reset */
-#define MEM_SOFT_RESET BIT(0)
-
-/* Status values */
-
-#define DCONSTAT_SCANINT 0
-#define DCONSTAT_SCANINT_DCON 1
-#define DCONSTAT_DISPLAYLOAD 2
-#define DCONSTAT_MISSED 3
-
-/* Source values */
-
-#define DCON_SOURCE_DCON 0
-#define DCON_SOURCE_CPU 1
-
-/* Interrupt */
-#define DCON_IRQ 6
-
-struct dcon_priv {
- struct i2c_client *client;
- struct fb_info *fbinfo;
- struct backlight_device *bl_dev;
-
- wait_queue_head_t waitq;
- struct work_struct switch_source;
- struct notifier_block reboot_nb;
-
- /* Shadow register for the DCON_REG_MODE register */
- u8 disp_mode;
-
- /* The current backlight value - this saves us some smbus traffic */
- u8 bl_val;
-
- /* Current source, initialized at probe time */
- int curr_src;
-
- /* Desired source */
- int pending_src;
-
- /* Variables used during switches */
- bool switched;
- ktime_t irq_time;
- ktime_t load_time;
-
- /* Current output type; true == mono, false == color */
- bool mono;
- bool asleep;
- /* This get set while controlling fb blank state from the driver */
- bool ignore_fb_events;
-};
-
-struct dcon_platform_data {
- int (*init)(struct dcon_priv *dcon);
- void (*bus_stabilize_wiggle)(void);
- void (*set_dconload)(int load);
- int (*read_status)(u8 *status);
-};
-
-struct dcon_gpio {
- const char *name;
- unsigned long flags;
-};
-
-#include <linux/interrupt.h>
-
-irqreturn_t dcon_interrupt(int irq, void *id);
-
-extern struct dcon_platform_data dcon_pdata_xo_1;
-extern struct dcon_platform_data dcon_pdata_xo_1_5;
-
-#endif
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
deleted file mode 100644
index 02c059897784..000000000000
--- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1.c
+++ /dev/null
@@ -1,201 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Mainly by David Woodhouse, somewhat modified by Jordan Crouse
- *
- * Copyright © 2006-2007 Red Hat, Inc.
- * Copyright © 2006-2007 Advanced Micro Devices, Inc.
- * Copyright © 2009 VIA Technology, Inc.
- * Copyright (c) 2010 Andres Salomon <dilinger@queued.net>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/cs5535.h>
-#include <linux/gpio/consumer.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <asm/olpc.h>
-
-#include "olpc_dcon.h"
-
-enum dcon_gpios {
- OLPC_DCON_STAT0,
- OLPC_DCON_STAT1,
- OLPC_DCON_IRQ,
- OLPC_DCON_LOAD,
- OLPC_DCON_BLANK,
-};
-
-static const struct dcon_gpio gpios_asis[] = {
- [OLPC_DCON_STAT0] = { .name = "dcon_stat0", .flags = GPIOD_ASIS },
- [OLPC_DCON_STAT1] = { .name = "dcon_stat1", .flags = GPIOD_ASIS },
- [OLPC_DCON_IRQ] = { .name = "dcon_irq", .flags = GPIOD_ASIS },
- [OLPC_DCON_LOAD] = { .name = "dcon_load", .flags = GPIOD_ASIS },
- [OLPC_DCON_BLANK] = { .name = "dcon_blank", .flags = GPIOD_ASIS },
-};
-
-static struct gpio_desc *gpios[5];
-
-static int dcon_init_xo_1(struct dcon_priv *dcon)
-{
- unsigned char lob;
- int ret, i;
- const struct dcon_gpio *pin = &gpios_asis[0];
-
- for (i = 0; i < ARRAY_SIZE(gpios_asis); i++) {
- gpios[i] = devm_gpiod_get(&dcon->client->dev, pin[i].name,
- pin[i].flags);
- if (IS_ERR(gpios[i])) {
- ret = PTR_ERR(gpios[i]);
- pr_err("failed to request %s GPIO: %d\n", pin[i].name,
- ret);
- return ret;
- }
- }
-
- /* Turn off the event enable for GPIO7 just to be safe */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE);
-
- /*
- * Determine the current state by reading the GPIO bit; earlier
- * stages of the boot process have established the state.
- *
- * Note that we read GPIO_OUTPUT_VAL rather than GPIO_READ_BACK here;
- * this is because OFW will disable input for the pin and set a value..
- * READ_BACK will only contain a valid value if input is enabled and
- * then a value is set. So, future readings of the pin can use
- * READ_BACK, but the first one cannot. Awesome, huh?
- */
- dcon->curr_src = cs5535_gpio_isset(OLPC_GPIO_DCON_LOAD, GPIO_OUTPUT_VAL)
- ? DCON_SOURCE_CPU
- : DCON_SOURCE_DCON;
- dcon->pending_src = dcon->curr_src;
-
- /* Set the directions for the GPIO pins */
- gpiod_direction_input(gpios[OLPC_DCON_STAT0]);
- gpiod_direction_input(gpios[OLPC_DCON_STAT1]);
- gpiod_direction_input(gpios[OLPC_DCON_IRQ]);
- gpiod_direction_input(gpios[OLPC_DCON_BLANK]);
- gpiod_direction_output(gpios[OLPC_DCON_LOAD],
- dcon->curr_src == DCON_SOURCE_CPU);
-
- /* Set up the interrupt mappings */
-
- /* Set the IRQ to pair 2 */
- cs5535_gpio_setup_event(OLPC_GPIO_DCON_IRQ, 2, 0);
-
- /* Enable group 2 to trigger the DCON interrupt */
- cs5535_gpio_set_irq(2, DCON_IRQ);
-
- /* Select edge level for interrupt (in PIC) */
- lob = inb(0x4d0);
- lob &= ~(1 << DCON_IRQ);
- outb(lob, 0x4d0);
-
- /* Register the interrupt handler */
- if (request_irq(DCON_IRQ, &dcon_interrupt, 0, "DCON", dcon)) {
- pr_err("failed to request DCON's irq\n");
- return -EIO;
- }
-
- /* Clear INV_EN for GPIO7 (DCONIRQ) */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_INVERT);
-
- /* Enable filter for GPIO12 (DCONBLANK) */
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_FILTER);
-
- /* Disable filter for GPIO7 */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_FILTER);
-
- /* Disable event counter for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */
- cs5535_gpio_clear(OLPC_GPIO_DCON_IRQ, GPIO_INPUT_EVENT_COUNT);
- cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_INPUT_EVENT_COUNT);
-
- /* Add GPIO12 to the Filter Event Pair #7 */
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_FE7_SEL);
-
- /* Turn off negative Edge Enable for GPIO12 */
- cs5535_gpio_clear(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_EN);
-
- /* Enable negative Edge Enable for GPIO7 */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_EN);
-
- /* Zero the filter amount for Filter Event Pair #7 */
- cs5535_gpio_set(0, GPIO_FLTR7_AMOUNT);
-
- /* Clear the negative edge status for GPIO7 and GPIO12 */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS);
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_NEGATIVE_EDGE_STS);
-
- /* FIXME: Clear the positive status as well, just to be sure */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_POSITIVE_EDGE_STS);
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_POSITIVE_EDGE_STS);
-
- /* Enable events for GPIO7 (DCONIRQ) and GPIO12 (DCONBLANK) */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_EVENTS_ENABLE);
- cs5535_gpio_set(OLPC_GPIO_DCON_BLANK, GPIO_EVENTS_ENABLE);
-
- return 0;
-}
-
-static void dcon_wiggle_xo_1(void)
-{
- int x;
-
- /*
- * According to HiMax, when powering the DCON up we should hold
- * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON
- * state machine to reset to a (sane) initial state. Mitch Bradley
- * did some testing and discovered that holding for 16 SMB_CLK cycles
- * worked a lot more reliably, so that's what we do here.
- *
- * According to the cs5536 spec, to set GPIO14 to SMB_CLK we must
- * simultaneously set AUX1 IN/OUT to GPIO14; ditto for SMB_DATA and
- * GPIO15.
- */
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_VAL);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_ENABLE);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_ENABLE);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1);
- cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX2);
- cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX2);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1);
- cs5535_gpio_clear(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1);
-
- for (x = 0; x < 16; x++) {
- udelay(5);
- cs5535_gpio_clear(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL);
- udelay(5);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_VAL);
- }
- udelay(5);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_OUTPUT_AUX1);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_OUTPUT_AUX1);
- cs5535_gpio_set(OLPC_GPIO_SMB_CLK, GPIO_INPUT_AUX1);
- cs5535_gpio_set(OLPC_GPIO_SMB_DATA, GPIO_INPUT_AUX1);
-}
-
-static void dcon_set_dconload_1(int val)
-{
- gpiod_set_value(gpios[OLPC_DCON_LOAD], val);
-}
-
-static int dcon_read_status_xo_1(u8 *status)
-{
- *status = gpiod_get_value(gpios[OLPC_DCON_STAT0]);
- *status |= gpiod_get_value(gpios[OLPC_DCON_STAT1]) << 1;
-
- /* Clear the negative edge status for GPIO7 */
- cs5535_gpio_set(OLPC_GPIO_DCON_IRQ, GPIO_NEGATIVE_EDGE_STS);
-
- return 0;
-}
-
-struct dcon_platform_data dcon_pdata_xo_1 = {
- .init = dcon_init_xo_1,
- .bus_stabilize_wiggle = dcon_wiggle_xo_1,
- .set_dconload = dcon_set_dconload_1,
- .read_status = dcon_read_status_xo_1,
-};
diff --git a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c b/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
deleted file mode 100644
index 52cdcd2a89d6..000000000000
--- a/drivers/staging/olpc_dcon/olpc_dcon_xo_1_5.c
+++ /dev/null
@@ -1,204 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (c) 2009,2010 One Laptop per Child
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/acpi.h>
-#include <linux/delay.h>
-#include <linux/i2c.h>
-#include <linux/gpio/consumer.h>
-#include <linux/gpio/machine.h>
-#include <asm/olpc.h>
-
-/* TODO: this eventually belongs in linux/vx855.h */
-#define NR_VX855_GPI 14
-#define NR_VX855_GPO 13
-#define NR_VX855_GPIO 15
-
-#define VX855_GPI(n) (n)
-#define VX855_GPO(n) (NR_VX855_GPI + (n))
-#define VX855_GPIO(n) (NR_VX855_GPI + NR_VX855_GPO + (n))
-
-#include "olpc_dcon.h"
-
-/* Hardware setup on the XO 1.5:
- * DCONLOAD connects to VX855_GPIO1 (not SMBCK2)
- * DCONBLANK connects to VX855_GPIO8 (not SSPICLK) unused in driver
- * DCONSTAT0 connects to VX855_GPI10 (not SSPISDI)
- * DCONSTAT1 connects to VX855_GPI11 (not nSSPISS)
- * DCONIRQ connects to VX855_GPIO12
- * DCONSMBDATA connects to VX855 graphics CRTSPD
- * DCONSMBCLK connects to VX855 graphics CRTSPCLK
- */
-
-#define VX855_GENL_PURPOSE_OUTPUT 0x44c /* PMIO_Rx4c-4f */
-#define VX855_GPI_STATUS_CHG 0x450 /* PMIO_Rx50 */
-#define VX855_GPI_SCI_SMI 0x452 /* PMIO_Rx52 */
-#define BIT_GPIO12 0x40
-
-#define PREFIX "OLPC DCON:"
-
-enum dcon_gpios {
- OLPC_DCON_STAT0,
- OLPC_DCON_STAT1,
- OLPC_DCON_LOAD,
-};
-
-struct gpiod_lookup_table gpios_table = {
- .dev_id = NULL,
- .table = {
- GPIO_LOOKUP("VX855 South Bridge", VX855_GPIO(1), "dcon_load",
- GPIO_ACTIVE_LOW),
- GPIO_LOOKUP("VX855 South Bridge", VX855_GPI(10), "dcon_stat0",
- GPIO_ACTIVE_LOW),
- GPIO_LOOKUP("VX855 South Bridge", VX855_GPI(11), "dcon_stat1",
- GPIO_ACTIVE_LOW),
- { },
- },
-};
-
-static const struct dcon_gpio gpios_asis[] = {
- [OLPC_DCON_STAT0] = { .name = "dcon_stat0", .flags = GPIOD_ASIS },
- [OLPC_DCON_STAT1] = { .name = "dcon_stat1", .flags = GPIOD_ASIS },
- [OLPC_DCON_LOAD] = { .name = "dcon_load", .flags = GPIOD_ASIS },
-};
-
-static struct gpio_desc *gpios[3];
-
-static void dcon_clear_irq(void)
-{
- /* irq status will appear in PMIO_Rx50[6] (RW1C) on gpio12 */
- outb(BIT_GPIO12, VX855_GPI_STATUS_CHG);
-}
-
-static int dcon_was_irq(void)
-{
- u8 tmp;
-
- /* irq status will appear in PMIO_Rx50[6] on gpio12 */
- tmp = inb(VX855_GPI_STATUS_CHG);
-
- return !!(tmp & BIT_GPIO12);
-}
-
-static int dcon_init_xo_1_5(struct dcon_priv *dcon)
-{
- unsigned int irq;
- const struct dcon_gpio *pin = &gpios_asis[0];
- int i;
- int ret;
-
- /* Add GPIO look up table */
- gpios_table.dev_id = dev_name(&dcon->client->dev);
- gpiod_add_lookup_table(&gpios_table);
-
- /* Get GPIO descriptor */
- for (i = 0; i < ARRAY_SIZE(gpios_asis); i++) {
- gpios[i] = devm_gpiod_get(&dcon->client->dev, pin[i].name,
- pin[i].flags);
- if (IS_ERR(gpios[i])) {
- ret = PTR_ERR(gpios[i]);
- pr_err("failed to request %s GPIO: %d\n", pin[i].name,
- ret);
- return ret;
- }
- }
-
- dcon_clear_irq();
-
- /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */
- outb(inb(VX855_GPI_SCI_SMI) | BIT_GPIO12, VX855_GPI_SCI_SMI);
-
- /* Determine the current state of DCONLOAD, likely set by firmware */
- /* GPIO1 */
- dcon->curr_src = (inl(VX855_GENL_PURPOSE_OUTPUT) & 0x1000) ?
- DCON_SOURCE_CPU : DCON_SOURCE_DCON;
- dcon->pending_src = dcon->curr_src;
-
- /* we're sharing the IRQ with ACPI */
- irq = acpi_gbl_FADT.sci_interrupt;
- if (request_irq(irq, &dcon_interrupt, IRQF_SHARED, "DCON", dcon)) {
- pr_err("DCON (IRQ%d) allocation failed\n", irq);
- return 1;
- }
-
- return 0;
-}
-
-static void set_i2c_line(int sda, int scl)
-{
- unsigned char tmp;
- unsigned int port = 0x26;
-
- /* FIXME: This directly accesses the CRT GPIO controller !!! */
- outb(port, 0x3c4);
- tmp = inb(0x3c5);
-
- if (scl)
- tmp |= 0x20;
- else
- tmp &= ~0x20;
-
- if (sda)
- tmp |= 0x10;
- else
- tmp &= ~0x10;
-
- tmp |= 0x01;
-
- outb(port, 0x3c4);
- outb(tmp, 0x3c5);
-}
-
-static void dcon_wiggle_xo_1_5(void)
-{
- int x;
-
- /*
- * According to HiMax, when powering the DCON up we should hold
- * SMB_DATA high for 8 SMB_CLK cycles. This will force the DCON
- * state machine to reset to a (sane) initial state. Mitch Bradley
- * did some testing and discovered that holding for 16 SMB_CLK cycles
- * worked a lot more reliably, so that's what we do here.
- */
- set_i2c_line(1, 1);
-
- for (x = 0; x < 16; x++) {
- udelay(5);
- set_i2c_line(1, 0);
- udelay(5);
- set_i2c_line(1, 1);
- }
- udelay(5);
-
- /* set PMIO_Rx52[6] to enable SCI/SMI on gpio12 */
- outb(inb(VX855_GPI_SCI_SMI) | BIT_GPIO12, VX855_GPI_SCI_SMI);
-}
-
-static void dcon_set_dconload_xo_1_5(int val)
-{
- gpiod_set_value(gpios[OLPC_DCON_LOAD], val);
-}
-
-static int dcon_read_status_xo_1_5(u8 *status)
-{
- if (!dcon_was_irq())
- return -1;
-
- /* i believe this is the same as "inb(0x44b) & 3" */
- *status = gpiod_get_value(gpios[OLPC_DCON_STAT0]);
- *status |= gpiod_get_value(gpios[OLPC_DCON_STAT1]) << 1;
-
- dcon_clear_irq();
-
- return 0;
-}
-
-struct dcon_platform_data dcon_pdata_xo_1_5 = {
- .init = dcon_init_xo_1_5,
- .bus_stabilize_wiggle = dcon_wiggle_xo_1_5,
- .set_dconload = dcon_set_dconload_xo_1_5,
- .read_status = dcon_read_status_xo_1_5,
-};
diff --git a/drivers/staging/rtl8712/Kconfig b/drivers/staging/rtl8712/Kconfig
deleted file mode 100644
index 8de26425225b..000000000000
--- a/drivers/staging/rtl8712/Kconfig
+++ /dev/null
@@ -1,21 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config R8712U
- tristate "RealTek RTL8712U (RTL8192SU) Wireless LAN NIC driver"
- depends on WLAN && USB && CFG80211
- select WIRELESS_EXT
- select WEXT_PRIV
- select FW_LOADER
- help
- This option adds the Realtek RTL8712 USB device such as the
- D-Link DWA-130.
-
- If built as a module, it will be called r8712u.
-
-config R8712_TX_AGGR
- bool "Realtek RTL8712U Transmit Aggregation code"
- depends on R8712U && BROKEN
- help
- This option provides transmit aggregation for the Realtek
- RTL8712 USB device.
-
-
diff --git a/drivers/staging/rtl8712/Makefile b/drivers/staging/rtl8712/Makefile
deleted file mode 100644
index 3ae216b6621b..000000000000
--- a/drivers/staging/rtl8712/Makefile
+++ /dev/null
@@ -1,35 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-r8712u-y := \
- rtl871x_cmd.o \
- rtl8712_cmd.o \
- rtl871x_security.o \
- rtl871x_eeprom.o \
- rtl8712_efuse.o \
- hal_init.o \
- usb_halinit.o \
- usb_ops.o \
- usb_ops_linux.o \
- rtl871x_io.o \
- rtl8712_io.o \
- rtl871x_ioctl_linux.o \
- rtl871x_ioctl_rtl.o \
- rtl871x_ioctl_set.o \
- rtl8712_led.o \
- rtl871x_mlme.o \
- ieee80211.o \
- rtl871x_mp_ioctl.o \
- rtl871x_mp.o \
- mlme_linux.o \
- recv_linux.o \
- xmit_linux.o \
- usb_intf.o \
- os_intfs.o \
- rtl871x_pwrctrl.o \
- rtl8712_recv.o \
- rtl871x_recv.o \
- rtl871x_sta_mgt.o \
- rtl871x_xmit.o \
- rtl8712_xmit.o
-
-obj-$(CONFIG_R8712U) := r8712u.o
-
diff --git a/drivers/staging/rtl8712/TODO b/drivers/staging/rtl8712/TODO
deleted file mode 100644
index 5aed36efa7cb..000000000000
--- a/drivers/staging/rtl8712/TODO
+++ /dev/null
@@ -1,12 +0,0 @@
-TODO:
-- merge Realtek's bugfixes and new features into the driver
-- switch to use MAC80211
-- checkpatch.pl fixes - only a few remain
-
-A replacement for this driver with MAC80211 support is available
-at https://github.com/chunkeey/rtl8192su
-
-Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
-Larry Finger <Larry.Finger@lwfinger.net>,
-Florian Schilhabel <florian.c.schilhabel@googlemail.com> and
-Linux Driver Project Developer List <driverdev-devel@linuxdriverproject.org>.
diff --git a/drivers/staging/rtl8712/basic_types.h b/drivers/staging/rtl8712/basic_types.h
deleted file mode 100644
index aecded87dd4c..000000000000
--- a/drivers/staging/rtl8712/basic_types.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __BASIC_TYPES_H__
-#define __BASIC_TYPES_H__
-
-#include <linux/types.h>
-
-#define sint signed int
-
-/* Should we extend this to be host_addr_t and target_addr_t for case:
- * host : x86_64
- * target : mips64
- */
-#define addr_t unsigned long
-
-#endif /*__BASIC_TYPES_H__*/
-
diff --git a/drivers/staging/rtl8712/drv_types.h b/drivers/staging/rtl8712/drv_types.h
deleted file mode 100644
index 76ac798642bd..000000000000
--- a/drivers/staging/rtl8712/drv_types.h
+++ /dev/null
@@ -1,175 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-/* ---------------------------------------------------------------------
- *
- * For type defines and data structure defines
- *
- * ---------------------------------------------------------------------
- */
-#ifndef __DRV_TYPES_H__
-#define __DRV_TYPES_H__
-
-struct _adapter;
-
-#include "osdep_service.h"
-#include "wlan_bssdef.h"
-#include "rtl8712_spec.h"
-#include "rtl8712_hal.h"
-#include <linux/mutex.h>
-#include <linux/completion.h>
-
-enum _NIC_VERSION {
- RTL8711_NIC,
- RTL8712_NIC,
- RTL8713_NIC,
- RTL8716_NIC
-};
-
-struct qos_priv {
- /* bit mask option: u-apsd, s-apsd, ts, block ack... */
- unsigned int qos_option;
-};
-
-#include "rtl871x_ht.h"
-#include "rtl871x_cmd.h"
-#include "rtl871x_xmit.h"
-#include "rtl871x_recv.h"
-#include "rtl871x_security.h"
-#include "rtl871x_pwrctrl.h"
-#include "rtl871x_io.h"
-#include "rtl871x_eeprom.h"
-#include "sta_info.h"
-#include "rtl871x_mlme.h"
-#include "rtl871x_mp.h"
-#include "rtl871x_debug.h"
-#include "rtl871x_rf.h"
-#include "rtl871x_event.h"
-#include "rtl871x_led.h"
-
-#define SPEC_DEV_ID_DISABLE_HT BIT(1)
-
-struct specific_device_id {
- u32 flags;
- u16 idVendor;
- u16 idProduct;
-
-};
-
-struct registry_priv {
- u8 chip_version;
- u8 rfintfs;
- u8 lbkmode;
- u8 hci;
- u8 network_mode; /*infra, ad-hoc, auto*/
- struct ndis_802_11_ssid ssid;
- u8 channel;/* ad-hoc support requirement */
- u8 wireless_mode;/* A, B, G, auto */
- u8 vrtl_carrier_sense; /*Enable, Disable, Auto*/
- u8 vcs_type;/*RTS/CTS, CTS-to-self*/
- u16 rts_thresh;
- u16 frag_thresh;
- u8 preamble;/*long, short, auto*/
- u8 scan_mode;/*active, passive*/
- u8 adhoc_tx_pwr;
- u8 soft_ap;
- u8 smart_ps;
- u8 power_mgnt;
- u8 radio_enable;
- u8 long_retry_lmt;
- u8 short_retry_lmt;
- u16 busy_thresh;
- u8 ack_policy;
- u8 mp_mode;
- u8 software_encrypt;
- u8 software_decrypt;
- /* UAPSD */
- u8 wmm_enable;
- u8 uapsd_enable;
- u8 uapsd_max_sp;
- u8 uapsd_acbk_en;
- u8 uapsd_acbe_en;
- u8 uapsd_acvi_en;
- u8 uapsd_acvo_en;
-
- struct wlan_bssid_ex dev_network;
-
- u8 ht_enable;
- u8 cbw40_enable;
- u8 ampdu_enable;/*for tx*/
- u8 rf_config;
- u8 low_power;
- u8 wifi_test;
-};
-
-struct dvobj_priv {
- struct _adapter *padapter;
- u32 nr_endpoint;
- u8 ishighspeed;
- uint (*inirp_init)(struct _adapter *adapter);
- uint (*inirp_deinit)(struct _adapter *adapter);
- struct usb_device *pusbdev;
-};
-
-/**
- * struct _adapter - the main adapter structure for this device.
- *
- * bup: True indicates that the interface is up.
- */
-struct _adapter {
- struct dvobj_priv dvobjpriv;
- struct mlme_priv mlmepriv;
- struct cmd_priv cmdpriv;
- struct evt_priv evtpriv;
- struct io_queue *pio_queue;
- struct xmit_priv xmitpriv;
- struct recv_priv recvpriv;
- struct sta_priv stapriv;
- struct security_priv securitypriv;
- struct registry_priv registrypriv;
- struct wlan_acl_pool acl_list;
- struct pwrctrl_priv pwrctrlpriv;
- struct eeprom_priv eeprompriv;
- struct hal_priv halpriv;
- struct led_priv ledpriv;
- struct mp_priv mppriv;
- bool driver_stopped;
- bool surprise_removed;
- bool suspended;
- u8 eeprom_address_size;
- u8 hw_init_completed;
- struct task_struct *cmd_thread;
- uint (*dvobj_init)(struct _adapter *adapter);
- void (*dvobj_deinit)(struct _adapter *adapter);
- struct net_device *pnetdev;
- int bup;
- struct net_device_stats stats;
- struct iw_statistics iwstats;
- int pid; /*process id from UI*/
- struct work_struct wk_filter_rx_ff0;
- const struct firmware *fw;
- struct usb_interface *pusb_intf;
- struct mutex mutex_start;
- struct completion rtl8712_fw_ready;
- struct completion rx_filter_ready;
-};
-
-static inline u8 *myid(struct eeprom_priv *peepriv)
-{
- return peepriv->mac_addr;
-}
-
-u8 r8712_usb_hal_bus_init(struct _adapter *adapter);
-
-#endif /*__DRV_TYPES_H__*/
-
diff --git a/drivers/staging/rtl8712/ethernet.h b/drivers/staging/rtl8712/ethernet.h
deleted file mode 100644
index 4b9b8a97a0bc..000000000000
--- a/drivers/staging/rtl8712/ethernet.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __INC_ETHERNET_H
-#define __INC_ETHERNET_H
-
-#define ETHERNET_HEADER_SIZE 14 /*!< Ethernet Header Length*/
-#define LLC_HEADER_SIZE 6 /*!< LLC Header Length*/
-
-#endif /* #ifndef __INC_ETHERNET_H */
-
diff --git a/drivers/staging/rtl8712/hal_init.c b/drivers/staging/rtl8712/hal_init.c
deleted file mode 100644
index 1148075f0cd6..000000000000
--- a/drivers/staging/rtl8712/hal_init.c
+++ /dev/null
@@ -1,401 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _HAL_INIT_C_
-
-#include <linux/usb.h>
-#include <linux/device.h>
-#include <linux/usb/ch9.h>
-#include <linux/firmware.h>
-#include <linux/module.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "usb_osintf.h"
-
-#define FWBUFF_ALIGN_SZ 512
-#define MAX_DUMP_FWSZ (48 * 1024)
-
-static void rtl871x_load_fw_fail(struct _adapter *adapter)
-{
- struct usb_device *udev = adapter->dvobjpriv.pusbdev;
- struct device *dev = &udev->dev;
- struct device *parent = dev->parent;
-
- complete(&adapter->rtl8712_fw_ready);
-
- dev_err(&udev->dev, "r8712u: Firmware request failed\n");
-
- if (parent)
- device_lock(parent);
-
- device_release_driver(dev);
-
- if (parent)
- device_unlock(parent);
-}
-
-static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
-{
- struct _adapter *adapter = context;
-
- if (!firmware) {
- rtl871x_load_fw_fail(adapter);
- return;
- }
- adapter->fw = firmware;
- /* firmware available - start netdev */
- register_netdev(adapter->pnetdev);
- complete(&adapter->rtl8712_fw_ready);
-}
-
-static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
-
-int rtl871x_load_fw(struct _adapter *padapter)
-{
- struct device *dev = &padapter->dvobjpriv.pusbdev->dev;
- int rc;
-
- init_completion(&padapter->rtl8712_fw_ready);
- dev_info(dev, "r8712u: Loading firmware from \"%s\"\n", firmware_file);
- rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev,
- GFP_KERNEL, padapter, rtl871x_load_fw_cb);
- if (rc)
- dev_err(dev, "r8712u: Firmware request error %d\n", rc);
- return rc;
-}
-MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
-
-static u32 rtl871x_open_fw(struct _adapter *adapter, const u8 **mappedfw)
-{
- if (adapter->fw->size > 200000) {
- dev_err(&adapter->pnetdev->dev, "r8712u: Bad fw->size of %zu\n",
- adapter->fw->size);
- return 0;
- }
- *mappedfw = adapter->fw->data;
- return adapter->fw->size;
-}
-
-static void fill_fwpriv(struct _adapter *adapter, struct fw_priv *fwpriv)
-{
- struct dvobj_priv *dvobj = &adapter->dvobjpriv;
- struct registry_priv *regpriv = &adapter->registrypriv;
-
- memset(fwpriv, 0, sizeof(struct fw_priv));
- /* todo: check if needs endian conversion */
- fwpriv->hci_sel = RTL8712_HCI_TYPE_72USB;
- fwpriv->usb_ep_num = (u8)dvobj->nr_endpoint;
- fwpriv->bw_40MHz_en = regpriv->cbw40_enable;
- switch (regpriv->rf_config) {
- case RTL8712_RF_1T1R:
- fwpriv->rf_config = RTL8712_RFC_1T1R;
- break;
- case RTL8712_RF_2T2R:
- fwpriv->rf_config = RTL8712_RFC_2T2R;
- break;
- case RTL8712_RF_1T2R:
- default:
- fwpriv->rf_config = RTL8712_RFC_1T2R;
- }
- fwpriv->mp_mode = (regpriv->mp_mode == 1);
- /* 0:off 1:on 2:auto */
- fwpriv->vcs_type = regpriv->vrtl_carrier_sense;
- fwpriv->vcs_mode = regpriv->vcs_type; /* 1:RTS/CTS 2:CTS to self */
- /* default enable turbo_mode */
- fwpriv->turbo_mode = (regpriv->wifi_test != 1);
- fwpriv->low_power_mode = regpriv->low_power;
-}
-
-static void update_fwhdr(struct fw_hdr *pfwhdr, const u8 *pmappedfw)
-{
- pfwhdr->signature = le16_to_cpu(*(__le16 *)pmappedfw);
- pfwhdr->version = le16_to_cpu(*(__le16 *)(pmappedfw + 2));
- /* define the size of boot loader */
- pfwhdr->dmem_size = le32_to_cpu(*(__le32 *)(pmappedfw + 4));
- /* define the size of FW in IMEM */
- pfwhdr->img_IMEM_size = le32_to_cpu(*(__le32 *)(pmappedfw + 8));
- /* define the size of FW in SRAM */
- pfwhdr->img_SRAM_size = le32_to_cpu(*(__le32 *)(pmappedfw + 12));
- /* define the size of DMEM variable */
- pfwhdr->fw_priv_sz = le32_to_cpu(*(__le32 *)(pmappedfw + 16));
-}
-
-static u8 chk_fwhdr(struct fw_hdr *pfwhdr, u32 ulfilelength)
-{
- u32 fwhdrsz, fw_sz;
-
- /* check signature */
- if ((pfwhdr->signature != 0x8712) && (pfwhdr->signature != 0x8192))
- return _FAIL;
- /* check fw_priv_sze & sizeof(struct fw_priv) */
- if (pfwhdr->fw_priv_sz != sizeof(struct fw_priv))
- return _FAIL;
- /* check fw_sz & image_fw_sz */
- fwhdrsz = offsetof(struct fw_hdr, fwpriv) + pfwhdr->fw_priv_sz;
- fw_sz = fwhdrsz + pfwhdr->img_IMEM_size + pfwhdr->img_SRAM_size +
- pfwhdr->dmem_size;
- if (fw_sz != ulfilelength)
- return _FAIL;
- return _SUCCESS;
-}
-
-static u8 rtl8712_dl_fw(struct _adapter *adapter)
-{
- sint i;
- u8 tmp8, tmp8_a;
- u16 tmp16;
- u32 maxlen = 0; /* for compare usage */
- uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz; /* max = 49152; */
- struct fw_hdr fwhdr;
- u32 ulfilelength; /* FW file size */
- const u8 *mappedfw = NULL;
- u8 *tmpchar = NULL, *payload, *ptr;
- struct tx_desc *txdesc;
- u32 txdscp_sz = sizeof(struct tx_desc);
- u8 ret = _FAIL;
-
- ulfilelength = rtl871x_open_fw(adapter, &mappedfw);
- if (mappedfw && (ulfilelength > 0)) {
- update_fwhdr(&fwhdr, mappedfw);
- if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL)
- return ret;
- fill_fwpriv(adapter, &fwhdr.fwpriv);
- /* firmware check ok */
- maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ?
- fwhdr.img_IMEM_size : fwhdr.img_SRAM_size;
- maxlen += txdscp_sz;
- tmpchar = kmalloc(maxlen + FWBUFF_ALIGN_SZ, GFP_KERNEL);
- if (!tmpchar)
- return ret;
-
- txdesc = (struct tx_desc *)(tmpchar + FWBUFF_ALIGN_SZ -
- ((addr_t)(tmpchar) & (FWBUFF_ALIGN_SZ - 1)));
- payload = (u8 *)(txdesc) + txdscp_sz;
- ptr = (u8 *)mappedfw + offsetof(struct fw_hdr, fwpriv) +
- fwhdr.fw_priv_sz;
- /* Download FirmWare */
- /* 1. determine IMEM code size and Load IMEM Code Section */
- imem_sz = fwhdr.img_IMEM_size;
- do {
- memset(txdesc, 0, TXDESC_SIZE);
- if (imem_sz > MAX_DUMP_FWSZ/*49152*/) {
- dump_imem_sz = MAX_DUMP_FWSZ;
- } else {
- dump_imem_sz = imem_sz;
- txdesc->txdw0 |= cpu_to_le32(BIT(28));
- }
- txdesc->txdw0 |= cpu_to_le32(dump_imem_sz &
- 0x0000ffff);
- memcpy(payload, ptr, dump_imem_sz);
- r8712_write_mem(adapter, RTL8712_DMA_VOQ,
- dump_imem_sz + TXDESC_SIZE,
- (u8 *)txdesc);
- ptr += dump_imem_sz;
- imem_sz -= dump_imem_sz;
- } while (imem_sz > 0);
- i = 10;
- tmp16 = r8712_read16(adapter, TCR);
- while (((tmp16 & _IMEM_CODE_DONE) == 0) && (i > 0)) {
- usleep_range(10, 1000);
- tmp16 = r8712_read16(adapter, TCR);
- i--;
- }
- if (i == 0 || (tmp16 & _IMEM_CHK_RPT) == 0)
- goto exit_fail;
-
- /* 2.Download EMEM code size and Load EMEM Code Section */
- emem_sz = fwhdr.img_SRAM_size;
- do {
- memset(txdesc, 0, TXDESC_SIZE);
- if (emem_sz > MAX_DUMP_FWSZ) { /* max=48k */
- dump_emem_sz = MAX_DUMP_FWSZ;
- } else {
- dump_emem_sz = emem_sz;
- txdesc->txdw0 |= cpu_to_le32(BIT(28));
- }
- txdesc->txdw0 |= cpu_to_le32(dump_emem_sz &
- 0x0000ffff);
- memcpy(payload, ptr, dump_emem_sz);
- r8712_write_mem(adapter, RTL8712_DMA_VOQ,
- dump_emem_sz + TXDESC_SIZE,
- (u8 *)txdesc);
- ptr += dump_emem_sz;
- emem_sz -= dump_emem_sz;
- } while (emem_sz > 0);
- i = 5;
- tmp16 = r8712_read16(adapter, TCR);
- while (((tmp16 & _EMEM_CODE_DONE) == 0) && (i > 0)) {
- usleep_range(10, 1000);
- tmp16 = r8712_read16(adapter, TCR);
- i--;
- }
- if (i == 0 || (tmp16 & _EMEM_CHK_RPT) == 0)
- goto exit_fail;
-
- /* 3.Enable CPU */
- tmp8 = r8712_read8(adapter, SYS_CLKR);
- r8712_write8(adapter, SYS_CLKR, tmp8 | BIT(2));
- tmp8_a = r8712_read8(adapter, SYS_CLKR);
- if (tmp8_a != (tmp8 | BIT(2)))
- goto exit_fail;
-
- tmp8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, tmp8 | BIT(2));
- tmp8_a = r8712_read8(adapter, SYS_FUNC_EN + 1);
- if (tmp8_a != (tmp8 | BIT(2)))
- goto exit_fail;
-
- r8712_read32(adapter, TCR);
-
- /* 4.polling IMEM Ready */
- i = 100;
- tmp16 = r8712_read16(adapter, TCR);
- while (((tmp16 & _IMEM_RDY) == 0) && (i > 0)) {
- msleep(20);
- tmp16 = r8712_read16(adapter, TCR);
- i--;
- }
- if (i == 0) {
- r8712_write16(adapter, 0x10250348, 0xc000);
- r8712_write16(adapter, 0x10250348, 0xc001);
- r8712_write16(adapter, 0x10250348, 0x2000);
- r8712_write16(adapter, 0x10250348, 0x2001);
- r8712_write16(adapter, 0x10250348, 0x2002);
- r8712_write16(adapter, 0x10250348, 0x2003);
- goto exit_fail;
- }
- /* 5.Download DMEM code size and Load EMEM Code Section */
- memset(txdesc, 0, TXDESC_SIZE);
- txdesc->txdw0 |= cpu_to_le32(fwhdr.fw_priv_sz & 0x0000ffff);
- txdesc->txdw0 |= cpu_to_le32(BIT(28));
- memcpy(payload, &fwhdr.fwpriv, fwhdr.fw_priv_sz);
- r8712_write_mem(adapter, RTL8712_DMA_VOQ,
- fwhdr.fw_priv_sz + TXDESC_SIZE, (u8 *)txdesc);
-
- /* polling dmem code done */
- i = 100;
- tmp16 = r8712_read16(adapter, TCR);
- while (((tmp16 & _DMEM_CODE_DONE) == 0) && (i > 0)) {
- msleep(20);
- tmp16 = r8712_read16(adapter, TCR);
- i--;
- }
- if (i == 0)
- goto exit_fail;
-
- tmp8 = r8712_read8(adapter, 0x1025000A);
- if (tmp8 & BIT(4)) /* When boot from EEPROM,
- * & FW need more time to read EEPROM
- */
- i = 60;
- else /* boot from EFUSE */
- i = 30;
- tmp16 = r8712_read16(adapter, TCR);
- while (((tmp16 & _FWRDY) == 0) && (i > 0)) {
- msleep(100);
- tmp16 = r8712_read16(adapter, TCR);
- i--;
- }
- if (i == 0)
- goto exit_fail;
- } else {
- goto exit_fail;
- }
- ret = _SUCCESS;
-
-exit_fail:
- kfree(tmpchar);
- return ret;
-}
-
-uint rtl8712_hal_init(struct _adapter *padapter)
-{
- u32 val32;
- int i;
-
- /* r8712 firmware download */
- if (rtl8712_dl_fw(padapter) != _SUCCESS)
- return _FAIL;
-
- netdev_info(padapter->pnetdev, "1 RCR=0x%x\n",
- r8712_read32(padapter, RCR));
- val32 = r8712_read32(padapter, RCR);
- r8712_write32(padapter, RCR, (val32 | BIT(26))); /* Enable RX TCP
- * Checksum offload
- */
- netdev_info(padapter->pnetdev, "2 RCR=0x%x\n",
- r8712_read32(padapter, RCR));
- val32 = r8712_read32(padapter, RCR);
- r8712_write32(padapter, RCR, (val32 | BIT(25))); /* Append PHY status */
- val32 = r8712_read32(padapter, 0x10250040);
- r8712_write32(padapter, 0x10250040, (val32 & 0x00FFFFFF));
- /* for usb rx aggregation */
- r8712_write8(padapter, 0x102500B5, r8712_read8(padapter, 0x102500B5) |
- BIT(0)); /* page = 128bytes */
- r8712_write8(padapter, 0x102500BD, r8712_read8(padapter, 0x102500BD) |
- BIT(7)); /* enable usb rx aggregation */
- r8712_write8(padapter, 0x102500D9, 1); /* TH=1 => means that invalidate
- * usb rx aggregation
- */
- r8712_write8(padapter, 0x1025FE5B, 0x04); /* 1.7ms/4 */
- /* Fix the RX FIFO issue(USB error) */
- r8712_write8(padapter, 0x1025fe5C, r8712_read8(padapter, 0x1025fe5C)
- | BIT(7));
- for (i = 0; i < ETH_ALEN; i++)
- padapter->eeprompriv.mac_addr[i] = r8712_read8(padapter,
- MACID + i);
- return _SUCCESS;
-}
-
-uint rtl8712_hal_deinit(struct _adapter *padapter)
-{
- r8712_write8(padapter, RF_CTRL, 0x00);
- /* Turn off BB */
- msleep(20);
- /* Turn off MAC */
- r8712_write8(padapter, SYS_CLKR + 1, 0x38); /* Switch Control Path */
- r8712_write8(padapter, SYS_FUNC_EN + 1, 0x70);
- r8712_write8(padapter, PMC_FSM, 0x06); /* Enable Loader Data Keep */
- r8712_write8(padapter, SYS_ISO_CTRL, 0xF9); /* Isolation signals from
- * CORE, PLL
- */
- r8712_write8(padapter, SYS_ISO_CTRL + 1, 0xe8); /* Enable EFUSE 1.2V */
- r8712_write8(padapter, AFE_PLL_CTRL, 0x00); /* Disable AFE PLL. */
- r8712_write8(padapter, LDOA15_CTRL, 0x54); /* Disable A15V */
- r8712_write8(padapter, SYS_FUNC_EN + 1, 0x50); /* Disable E-Fuse 1.2V */
- r8712_write8(padapter, LDOV12D_CTRL, 0x24); /* Disable LDO12(for CE) */
- r8712_write8(padapter, AFE_MISC, 0x30); /* Disable AFE BG&MB */
- /* Option for Disable 1.6V LDO. */
- r8712_write8(padapter, SPS0_CTRL, 0x56); /* Disable 1.6V LDO */
- r8712_write8(padapter, SPS0_CTRL + 1, 0x43); /* Set SW PFM */
- return _SUCCESS;
-}
-
-uint rtl871x_hal_init(struct _adapter *padapter)
-{
- padapter->hw_init_completed = false;
- if (!padapter->halpriv.hal_bus_init)
- return _FAIL;
- if (padapter->halpriv.hal_bus_init(padapter) != _SUCCESS)
- return _FAIL;
- if (rtl8712_hal_init(padapter) == _SUCCESS) {
- padapter->hw_init_completed = true;
- } else {
- padapter->hw_init_completed = false;
- return _FAIL;
- }
- return _SUCCESS;
-}
diff --git a/drivers/staging/rtl8712/ieee80211.c b/drivers/staging/rtl8712/ieee80211.c
deleted file mode 100644
index 7d8f1a29d18a..000000000000
--- a/drivers/staging/rtl8712/ieee80211.c
+++ /dev/null
@@ -1,415 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * ieee80211.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _IEEE80211_C
-
-#include "drv_types.h"
-#include "ieee80211.h"
-#include "wifi.h"
-#include "osdep_service.h"
-#include "wlan_bssdef.h"
-
-static const u8 WPA_OUI_TYPE[] = {0x00, 0x50, 0xf2, 1};
-static const u8 WPA_CIPHER_SUITE_NONE[] = {0x00, 0x50, 0xf2, 0};
-static const u8 WPA_CIPHER_SUITE_WEP40[] = {0x00, 0x50, 0xf2, 1};
-static const u8 WPA_CIPHER_SUITE_TKIP[] = {0x00, 0x50, 0xf2, 2};
-static const u8 WPA_CIPHER_SUITE_CCMP[] = {0x00, 0x50, 0xf2, 4};
-static const u8 WPA_CIPHER_SUITE_WEP104[] = {0x00, 0x50, 0xf2, 5};
-
-static const u8 RSN_CIPHER_SUITE_NONE[] = {0x00, 0x0f, 0xac, 0};
-static const u8 RSN_CIPHER_SUITE_WEP40[] = {0x00, 0x0f, 0xac, 1};
-static const u8 RSN_CIPHER_SUITE_TKIP[] = {0x00, 0x0f, 0xac, 2};
-static const u8 RSN_CIPHER_SUITE_CCMP[] = {0x00, 0x0f, 0xac, 4};
-static const u8 RSN_CIPHER_SUITE_WEP104[] = {0x00, 0x0f, 0xac, 5};
-
-/*-----------------------------------------------------------
- * for adhoc-master to generate ie and provide supported-rate to fw
- *-----------------------------------------------------------
- */
-
-static u8 WIFI_CCKRATES[] = {
- (IEEE80211_CCK_RATE_1MB | IEEE80211_BASIC_RATE_MASK),
- (IEEE80211_CCK_RATE_2MB | IEEE80211_BASIC_RATE_MASK),
- (IEEE80211_CCK_RATE_5MB | IEEE80211_BASIC_RATE_MASK),
- (IEEE80211_CCK_RATE_11MB | IEEE80211_BASIC_RATE_MASK)
-};
-
-static u8 WIFI_OFDMRATES[] = {
- (IEEE80211_OFDM_RATE_6MB),
- (IEEE80211_OFDM_RATE_9MB),
- (IEEE80211_OFDM_RATE_12MB),
- (IEEE80211_OFDM_RATE_18MB),
- (IEEE80211_OFDM_RATE_24MB),
- (IEEE80211_OFDM_RATE_36MB),
- (IEEE80211_OFDM_RATE_48MB),
- (IEEE80211_OFDM_RATE_54MB)
-};
-
-uint r8712_is_cckrates_included(u8 *rate)
-{
- u32 i = 0;
-
- while (rate[i] != 0) {
- if ((((rate[i]) & 0x7f) == 2) || (((rate[i]) & 0x7f) == 4) ||
- (((rate[i]) & 0x7f) == 11) || (((rate[i]) & 0x7f) == 22))
- return true;
- i++;
- }
- return false;
-}
-
-uint r8712_is_cckratesonly_included(u8 *rate)
-{
- u32 i = 0;
-
- while (rate[i] != 0) {
- if ((((rate[i]) & 0x7f) != 2) && (((rate[i]) & 0x7f) != 4) &&
- (((rate[i]) & 0x7f) != 11) && (((rate[i]) & 0x7f) != 22))
- return false;
- i++;
- }
- return true;
-}
-
-/* r8712_set_ie will update frame length */
-u8 *r8712_set_ie(u8 *pbuf, sint index, uint len, u8 *source, uint *frlen)
-{
- *pbuf = (u8)index;
- *(pbuf + 1) = (u8)len;
- if (len > 0)
- memcpy((void *)(pbuf + 2), (void *)source, len);
- *frlen = *frlen + (len + 2);
- return pbuf + len + 2;
-}
-
-/* ---------------------------------------------------------------------------
- * index: the information element id index, limit is the limit for search
- * ---------------------------------------------------------------------------
- */
-u8 *r8712_get_ie(u8 *pbuf, sint index, uint *len, sint limit)
-{
- sint tmp, i;
- u8 *p;
-
- if (limit < 1)
- return NULL;
- p = pbuf;
- i = 0;
- *len = 0;
- while (1) {
- if (*p == index) {
- *len = *(p + 1);
- return p;
- }
- tmp = *(p + 1);
- p += (tmp + 2);
- i += (tmp + 2);
- if (i >= limit)
- break;
- }
- return NULL;
-}
-
-static void set_supported_rate(u8 *rates, uint mode)
-{
- memset(rates, 0, NDIS_802_11_LENGTH_RATES_EX);
- switch (mode) {
- case WIRELESS_11B:
- memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
- break;
- case WIRELESS_11G:
- case WIRELESS_11A:
- memcpy(rates, WIFI_OFDMRATES, IEEE80211_NUM_OFDM_RATESLEN);
- break;
- case WIRELESS_11BG:
- memcpy(rates, WIFI_CCKRATES, IEEE80211_CCK_RATE_LEN);
- memcpy(rates + IEEE80211_CCK_RATE_LEN, WIFI_OFDMRATES,
- IEEE80211_NUM_OFDM_RATESLEN);
- break;
- }
-}
-
-static uint r8712_get_rateset_len(u8 *rateset)
-{
- uint i = 0;
-
- while (1) {
- if ((rateset[i]) == 0)
- break;
- if (i > 12)
- break;
- i++;
- }
- return i;
-}
-
-int r8712_generate_ie(struct registry_priv *registrypriv)
-{
- int rate_len;
- uint sz = 0;
- struct wlan_bssid_ex *dev_network = &registrypriv->dev_network;
- u8 *ie = dev_network->IEs;
- u16 beacon_period = (u16)dev_network->Configuration.BeaconPeriod;
-
- /*timestamp will be inserted by hardware*/
- sz += 8;
- ie += sz;
- /*beacon interval : 2bytes*/
- *(__le16 *)ie = cpu_to_le16(beacon_period);
- sz += 2;
- ie += 2;
- /*capability info*/
- *(u16 *)ie = 0;
- *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_IBSS);
- if (registrypriv->preamble == PREAMBLE_SHORT)
- *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_SHORT_PREAMBLE);
- if (dev_network->Privacy)
- *(__le16 *)ie |= cpu_to_le16(WLAN_CAPABILITY_PRIVACY);
- sz += 2;
- ie += 2;
- /*SSID*/
- ie = r8712_set_ie(ie, WLAN_EID_SSID, dev_network->Ssid.SsidLength,
- dev_network->Ssid.Ssid, &sz);
- /*supported rates*/
- set_supported_rate(dev_network->rates, registrypriv->wireless_mode);
- rate_len = r8712_get_rateset_len(dev_network->rates);
- if (rate_len > 8) {
- ie = r8712_set_ie(ie, WLAN_EID_SUPP_RATES, 8,
- dev_network->rates, &sz);
- ie = r8712_set_ie(ie, WLAN_EID_EXT_SUPP_RATES, (rate_len - 8),
- (dev_network->rates + 8), &sz);
- } else {
- ie = r8712_set_ie(ie, WLAN_EID_SUPP_RATES,
- rate_len, dev_network->rates, &sz);
- }
- /*DS parameter set*/
- ie = r8712_set_ie(ie, WLAN_EID_DS_PARAMS, 1,
- (u8 *)&dev_network->Configuration.DSConfig, &sz);
- /*IBSS Parameter Set*/
- ie = r8712_set_ie(ie, WLAN_EID_IBSS_PARAMS, 2,
- (u8 *)&dev_network->Configuration.ATIMWindow, &sz);
- return sz;
-}
-
-unsigned char *r8712_get_wpa_ie(unsigned char *ie, uint *wpa_ie_len, int limit)
-{
- u32 len;
- u16 val16;
- unsigned char wpa_oui_type[] = {0x00, 0x50, 0xf2, 0x01};
- u8 *buf = ie;
-
- while (1) {
- buf = r8712_get_ie(buf, _WPA_IE_ID_, &len, limit);
- if (buf) {
- /*check if oui matches...*/
- if (memcmp((buf + 2), wpa_oui_type,
- sizeof(wpa_oui_type)))
- goto check_next_ie;
- /*check version...*/
- memcpy((u8 *)&val16, (buf + 6), sizeof(val16));
- le16_to_cpus(&val16);
- if (val16 != 0x0001)
- goto check_next_ie;
- *wpa_ie_len = *(buf + 1);
- return buf;
- }
- *wpa_ie_len = 0;
- return NULL;
-check_next_ie:
- limit = limit - (buf - ie) - 2 - len;
- if (limit <= 0)
- break;
- buf += (2 + len);
- }
- *wpa_ie_len = 0;
- return NULL;
-}
-
-unsigned char *r8712_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len,
- int limit)
-{
- return r8712_get_ie(pie, _WPA2_IE_ID_, rsn_ie_len, limit);
-}
-
-static int r8712_get_wpa_cipher_suite(u8 *s)
-{
- if (!memcmp(s, (void *)WPA_CIPHER_SUITE_NONE, WPA_SELECTOR_LEN))
- return WPA_CIPHER_NONE;
- if (!memcmp(s, (void *)WPA_CIPHER_SUITE_WEP40, WPA_SELECTOR_LEN))
- return WPA_CIPHER_WEP40;
- if (!memcmp(s, (void *)WPA_CIPHER_SUITE_TKIP, WPA_SELECTOR_LEN))
- return WPA_CIPHER_TKIP;
- if (!memcmp(s, (void *)WPA_CIPHER_SUITE_CCMP, WPA_SELECTOR_LEN))
- return WPA_CIPHER_CCMP;
- if (!memcmp(s, (void *)WPA_CIPHER_SUITE_WEP104, WPA_SELECTOR_LEN))
- return WPA_CIPHER_WEP104;
- return 0;
-}
-
-static int r8712_get_wpa2_cipher_suite(u8 *s)
-{
- if (!memcmp(s, (void *)RSN_CIPHER_SUITE_NONE, RSN_SELECTOR_LEN))
- return WPA_CIPHER_NONE;
- if (!memcmp(s, (void *)RSN_CIPHER_SUITE_WEP40, RSN_SELECTOR_LEN))
- return WPA_CIPHER_WEP40;
- if (!memcmp(s, (void *)RSN_CIPHER_SUITE_TKIP, RSN_SELECTOR_LEN))
- return WPA_CIPHER_TKIP;
- if (!memcmp(s, (void *)RSN_CIPHER_SUITE_CCMP, RSN_SELECTOR_LEN))
- return WPA_CIPHER_CCMP;
- if (!memcmp(s, (void *)RSN_CIPHER_SUITE_WEP104, RSN_SELECTOR_LEN))
- return WPA_CIPHER_WEP104;
- return 0;
-}
-
-int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
- int *pairwise_cipher)
-{
- int i;
- int left, count;
- u8 *pos;
-
- if (wpa_ie_len <= 0) {
- /* No WPA IE - fail silently */
- return -EINVAL;
- }
- if ((*wpa_ie != _WPA_IE_ID_) ||
- (*(wpa_ie + 1) != (u8)(wpa_ie_len - 2)) ||
- (memcmp(wpa_ie + 2, (void *)WPA_OUI_TYPE, WPA_SELECTOR_LEN)))
- return -EINVAL;
- pos = wpa_ie;
- pos += 8;
- left = wpa_ie_len - 8;
- /*group_cipher*/
- if (left >= WPA_SELECTOR_LEN) {
- *group_cipher = r8712_get_wpa_cipher_suite(pos);
- pos += WPA_SELECTOR_LEN;
- left -= WPA_SELECTOR_LEN;
- } else if (left > 0) {
- return -EINVAL;
- }
- /*pairwise_cipher*/
- if (left >= 2) {
- count = le16_to_cpu(*(__le16 *)pos);
- pos += 2;
- left -= 2;
- if (count == 0 || left < count * WPA_SELECTOR_LEN)
- return -EINVAL;
- for (i = 0; i < count; i++) {
- *pairwise_cipher |= r8712_get_wpa_cipher_suite(pos);
- pos += WPA_SELECTOR_LEN;
- left -= WPA_SELECTOR_LEN;
- }
- } else if (left == 1) {
- return -EINVAL;
- }
- return 0;
-}
-
-int r8712_parse_wpa2_ie(u8 *rsn_ie, int rsn_ie_len, int *group_cipher,
- int *pairwise_cipher)
-{
- int i;
- int left, count;
- u8 *pos;
-
- if (rsn_ie_len <= 0) {
- /* No RSN IE - fail silently */
- return -EINVAL;
- }
- if ((*rsn_ie != _WPA2_IE_ID_) ||
- (*(rsn_ie + 1) != (u8)(rsn_ie_len - 2)))
- return -EINVAL;
- pos = rsn_ie;
- pos += 4;
- left = rsn_ie_len - 4;
- /*group_cipher*/
- if (left >= RSN_SELECTOR_LEN) {
- *group_cipher = r8712_get_wpa2_cipher_suite(pos);
- pos += RSN_SELECTOR_LEN;
- left -= RSN_SELECTOR_LEN;
- } else if (left > 0) {
- return -EINVAL;
- }
- /*pairwise_cipher*/
- if (left >= 2) {
- count = le16_to_cpu(*(__le16 *)pos);
- pos += 2;
- left -= 2;
- if (count == 0 || left < count * RSN_SELECTOR_LEN)
- return -EINVAL;
- for (i = 0; i < count; i++) {
- *pairwise_cipher |= r8712_get_wpa2_cipher_suite(pos);
- pos += RSN_SELECTOR_LEN;
- left -= RSN_SELECTOR_LEN;
- }
- } else if (left == 1) {
- return -EINVAL;
- }
- return 0;
-}
-
-int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
- u8 *wpa_ie, u16 *wpa_len)
-{
- u8 authmode;
- u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
- uint cnt;
-
- /*Search required WPA or WPA2 IE and copy to sec_ie[ ]*/
- cnt = _TIMESTAMP_ + _BEACON_ITERVAL_ + _CAPABILITY_;
- while (cnt < in_len) {
- authmode = in_ie[cnt];
- if ((authmode == _WPA_IE_ID_) &&
- (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
- memcpy(wpa_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
- *wpa_len = in_ie[cnt + 1] + 2;
- cnt += in_ie[cnt + 1] + 2; /*get next */
- } else {
- if (authmode == _WPA2_IE_ID_) {
- memcpy(rsn_ie, &in_ie[cnt],
- in_ie[cnt + 1] + 2);
- *rsn_len = in_ie[cnt + 1] + 2;
- cnt += in_ie[cnt + 1] + 2; /*get next*/
- } else {
- cnt += in_ie[cnt + 1] + 2; /*get next*/
- }
- }
- }
- return *rsn_len + *wpa_len;
-}
-
-int r8712_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen)
-{
- int match;
- uint cnt;
- u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-
- cnt = 12;
- match = false;
- while (cnt < in_len) {
- eid = in_ie[cnt];
- if ((eid == _WPA_IE_ID_) &&
- (!memcmp(&in_ie[cnt + 2], wps_oui, 4))) {
- memcpy(wps_ie, &in_ie[cnt], in_ie[cnt + 1] + 2);
- *wps_ielen = in_ie[cnt + 1] + 2;
- cnt += in_ie[cnt + 1] + 2;
- match = true;
- break;
- }
- cnt += in_ie[cnt + 1] + 2; /* goto next */
- }
- return match;
-}
diff --git a/drivers/staging/rtl8712/ieee80211.h b/drivers/staging/rtl8712/ieee80211.h
deleted file mode 100644
index 65ceaca9b51e..000000000000
--- a/drivers/staging/rtl8712/ieee80211.h
+++ /dev/null
@@ -1,165 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __IEEE80211_H
-#define __IEEE80211_H
-
-#include <linux/ieee80211.h>
-
-#define IEEE_CMD_SET_WPA_PARAM 1
-#define IEEE_CMD_SET_WPA_IE 2
-#define IEEE_CMD_SET_ENCRYPTION 3
-#define IEEE_CMD_MLME 4
-
-#define IEEE_PARAM_WPA_ENABLED 1
-#define IEEE_PARAM_TKIP_COUNTERMEASURES 2
-#define IEEE_PARAM_DROP_UNENCRYPTED 3
-#define IEEE_PARAM_PRIVACY_INVOKED 4
-#define IEEE_PARAM_AUTH_ALGS 5
-#define IEEE_PARAM_IEEE_802_1X 6
-#define IEEE_PARAM_WPAX_SELECT 7
-
-#define AUTH_ALG_OPEN_SYSTEM 0x1
-#define AUTH_ALG_SHARED_KEY 0x2
-#define AUTH_ALG_LEAP 0x00000004
-
-#define IEEE_MLME_STA_DEAUTH 1
-#define IEEE_MLME_STA_DISASSOC 2
-
-#define IEEE_CRYPT_ERR_UNKNOWN_ALG 2
-#define IEEE_CRYPT_ERR_UNKNOWN_ADDR 3
-#define IEEE_CRYPT_ERR_CRYPT_INIT_FAILED 4
-#define IEEE_CRYPT_ERR_KEY_SET_FAILED 5
-#define IEEE_CRYPT_ERR_TX_KEY_SET_FAILED 6
-#define IEEE_CRYPT_ERR_CARD_CONF_FAILED 7
-
-#define IEEE_CRYPT_ALG_NAME_LEN 16
-
-#define WPA_CIPHER_NONE BIT(0)
-#define WPA_CIPHER_WEP40 BIT(1)
-#define WPA_CIPHER_WEP104 BIT(2)
-#define WPA_CIPHER_TKIP BIT(3)
-#define WPA_CIPHER_CCMP BIT(4)
-
-#define WPA_SELECTOR_LEN 4
-#define RSN_HEADER_LEN 4
-
-#define RSN_SELECTOR_LEN 4
-
-enum NETWORK_TYPE {
- WIRELESS_INVALID = 0,
- WIRELESS_11B = 1,
- WIRELESS_11G = 2,
- WIRELESS_11BG = (WIRELESS_11B | WIRELESS_11G),
- WIRELESS_11A = 4,
- WIRELESS_11N = 8,
- WIRELESS_11GN = (WIRELESS_11G | WIRELESS_11N),
- WIRELESS_11BGN = (WIRELESS_11B | WIRELESS_11G | WIRELESS_11N),
-};
-
-struct ieee_param {
- u32 cmd;
- u8 sta_addr[ETH_ALEN];
- union {
- struct {
- u8 name;
- u32 value;
- } wpa_param;
- struct {
- u32 len;
- u8 reserved[32];
- u8 data[];
- } wpa_ie;
- struct {
- int command;
- int reason_code;
- } mlme;
- struct {
- u8 alg[IEEE_CRYPT_ALG_NAME_LEN];
- u8 set_tx;
- u32 err;
- u8 idx;
- u8 seq[8]; /* sequence counter (set: RX, get: TX) */
- u16 key_len;
- u8 key[];
- } crypt;
- } u;
-};
-
-#define MIN_FRAG_THRESHOLD 256U
-#define MAX_FRAG_THRESHOLD 2346U
-
-/* QoS,QOS */
-#define NORMAL_ACK 0
-
-/* IEEE 802.11 defines */
-
-#define P80211_OUI_LEN 3
-
-struct ieee80211_snap_hdr {
- u8 dsap; /* always 0xAA */
- u8 ssap; /* always 0xAA */
- u8 ctrl; /* always 0x03 */
- u8 oui[P80211_OUI_LEN]; /* organizational universal id */
-} __packed;
-
-#define SNAP_SIZE sizeof(struct ieee80211_snap_hdr)
-
-#define IEEE80211_CCK_RATE_LEN 4
-#define IEEE80211_NUM_OFDM_RATESLEN 8
-
-#define IEEE80211_CCK_RATE_1MB 0x02
-#define IEEE80211_CCK_RATE_2MB 0x04
-#define IEEE80211_CCK_RATE_5MB 0x0B
-#define IEEE80211_CCK_RATE_11MB 0x16
-#define IEEE80211_OFDM_RATE_6MB 0x0C
-#define IEEE80211_OFDM_RATE_9MB 0x12
-#define IEEE80211_OFDM_RATE_12MB 0x18
-#define IEEE80211_OFDM_RATE_18MB 0x24
-#define IEEE80211_OFDM_RATE_24MB 0x30
-#define IEEE80211_OFDM_RATE_36MB 0x48
-#define IEEE80211_OFDM_RATE_48MB 0x60
-#define IEEE80211_OFDM_RATE_54MB 0x6C
-#define IEEE80211_BASIC_RATE_MASK 0x80
-
-#define WEP_KEYS 4
-
-/* MAX_RATES_LENGTH needs to be 12. The spec says 8, and many APs
- * only use 8, and then use extended rates for the remaining supported
- * rates. Other APs, however, stick all of their supported rates on the
- * main rates information element...
- */
-#define MAX_RATES_LENGTH ((u8)12)
-#define MAX_WPA_IE_LEN 128
-
-struct registry_priv;
-
-u8 *r8712_set_ie(u8 *pbuf, sint index, uint len, u8 *source, uint *frlen);
-u8 *r8712_get_ie(u8 *pbuf, sint index, uint *len, sint limit);
-unsigned char *r8712_get_wpa_ie(unsigned char *pie, uint *rsn_ie_len,
- int limit);
-unsigned char *r8712_get_wpa2_ie(unsigned char *pie, uint *rsn_ie_len,
- int limit);
-int r8712_parse_wpa_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
- int *pairwise_cipher);
-int r8712_parse_wpa2_ie(u8 *wpa_ie, int wpa_ie_len, int *group_cipher,
- int *pairwise_cipher);
-int r8712_get_sec_ie(u8 *in_ie, uint in_len, u8 *rsn_ie, u16 *rsn_len,
- u8 *wpa_ie, u16 *wpa_len);
-int r8712_get_wps_ie(u8 *in_ie, uint in_len, u8 *wps_ie, uint *wps_ielen);
-int r8712_generate_ie(struct registry_priv *pregistrypriv);
-uint r8712_is_cckrates_included(u8 *rate);
-uint r8712_is_cckratesonly_included(u8 *rate);
-
-#endif /* IEEE80211_H */
-
diff --git a/drivers/staging/rtl8712/mlme_linux.c b/drivers/staging/rtl8712/mlme_linux.c
deleted file mode 100644
index 436816d14cdf..000000000000
--- a/drivers/staging/rtl8712/mlme_linux.c
+++ /dev/null
@@ -1,160 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * mlme_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _MLME_OSDEP_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "mlme_osdep.h"
-
-static void sitesurvey_ctrl_handler(struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t,
- mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer);
-
- _r8712_sitesurvey_ctrl_handler(adapter);
- mod_timer(&adapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer,
- jiffies + msecs_to_jiffies(3000));
-}
-
-static void join_timeout_handler (struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t, mlmepriv.assoc_timer);
-
- _r8712_join_timeout_handler(adapter);
-}
-
-static void _scan_timeout_handler (struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t, mlmepriv.scan_to_timer);
-
- r8712_scan_timeout_handler(adapter);
-}
-
-static void dhcp_timeout_handler (struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t, mlmepriv.dhcp_timer);
-
- _r8712_dhcp_timeout_handler(adapter);
-}
-
-static void wdg_timeout_handler (struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t, mlmepriv.wdg_timer);
-
- r8712_wdg_wk_cmd(adapter);
-
- mod_timer(&adapter->mlmepriv.wdg_timer,
- jiffies + msecs_to_jiffies(2000));
-}
-
-void r8712_init_mlme_timer(struct _adapter *adapter)
-{
- struct mlme_priv *mlmepriv = &adapter->mlmepriv;
-
- timer_setup(&mlmepriv->assoc_timer, join_timeout_handler, 0);
- timer_setup(&mlmepriv->sitesurveyctrl.sitesurvey_ctrl_timer,
- sitesurvey_ctrl_handler, 0);
- timer_setup(&mlmepriv->scan_to_timer, _scan_timeout_handler, 0);
- timer_setup(&mlmepriv->dhcp_timer, dhcp_timeout_handler, 0);
- timer_setup(&mlmepriv->wdg_timer, wdg_timeout_handler, 0);
-}
-
-void r8712_os_indicate_connect(struct _adapter *adapter)
-{
- r8712_indicate_wx_assoc_event(adapter);
- netif_carrier_on(adapter->pnetdev);
-}
-
-static struct RT_PMKID_LIST backup_PMKID_list[NUM_PMKID_CACHE];
-void r8712_os_indicate_disconnect(struct _adapter *adapter)
-{
- u8 backup_PMKID_index = 0;
- u8 backup_TKIP_countermeasure = 0x00;
-
- r8712_indicate_wx_disassoc_event(adapter);
- netif_carrier_off(adapter->pnetdev);
- if (adapter->securitypriv.AuthAlgrthm == 2) { /*/802.1x*/
- /* We have to backup the PMK information for WiFi PMK Caching
- * test item. Backup the btkip_countermeasure information.
- * When the countermeasure is trigger, the driver have to
- * disconnect with AP for 60 seconds.
- */
-
- memcpy(&backup_PMKID_list[0],
- &adapter->securitypriv.PMKIDList[0],
- sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
- backup_PMKID_index = adapter->securitypriv.PMKIDIndex;
- backup_TKIP_countermeasure =
- adapter->securitypriv.btkip_countermeasure;
- memset((unsigned char *)&adapter->securitypriv, 0,
- sizeof(struct security_priv));
- timer_setup(&adapter->securitypriv.tkip_timer,
- r8712_use_tkipkey_handler, 0);
- /* Restore the PMK information to securitypriv structure
- * for the following connection.
- */
- memcpy(&adapter->securitypriv.PMKIDList[0],
- &backup_PMKID_list[0],
- sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
- adapter->securitypriv.PMKIDIndex = backup_PMKID_index;
- adapter->securitypriv.btkip_countermeasure =
- backup_TKIP_countermeasure;
- } else { /*reset values in securitypriv*/
- struct security_priv *sec_priv = &adapter->securitypriv;
-
- sec_priv->AuthAlgrthm = 0; /*open system*/
- sec_priv->PrivacyAlgrthm = _NO_PRIVACY_;
- sec_priv->PrivacyKeyIndex = 0;
- sec_priv->XGrpPrivacy = _NO_PRIVACY_;
- sec_priv->XGrpKeyid = 1;
- sec_priv->ndisauthtype = Ndis802_11AuthModeOpen;
- sec_priv->ndisencryptstatus = Ndis802_11WEPDisabled;
- sec_priv->wps_phase = false;
- }
-}
-
-void r8712_report_sec_ie(struct _adapter *adapter, u8 authmode, u8 *sec_ie)
-{
- uint len;
- u8 *buff, *p, i;
- union iwreq_data wrqu;
-
- buff = NULL;
- if (authmode == _WPA_IE_ID_) {
- buff = kzalloc(IW_CUSTOM_MAX, GFP_ATOMIC);
- if (!buff)
- return;
- p = buff;
- p += sprintf(p, "ASSOCINFO(ReqIEs=");
- len = sec_ie[1] + 2;
- len = (len < IW_CUSTOM_MAX) ? len : IW_CUSTOM_MAX;
- for (i = 0; i < len; i++)
- p += sprintf(p, "%02x", sec_ie[i]);
- p += sprintf(p, ")");
- memset(&wrqu, 0, sizeof(wrqu));
- wrqu.data.length = p - buff;
- wrqu.data.length = (wrqu.data.length < IW_CUSTOM_MAX) ?
- wrqu.data.length : IW_CUSTOM_MAX;
- wireless_send_event(adapter->pnetdev, IWEVCUSTOM, &wrqu, buff);
- kfree(buff);
- }
-}
diff --git a/drivers/staging/rtl8712/mlme_osdep.h b/drivers/staging/rtl8712/mlme_osdep.h
deleted file mode 100644
index a02c782588dd..000000000000
--- a/drivers/staging/rtl8712/mlme_osdep.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __MLME_OSDEP_H_
-#define __MLME_OSDEP_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-void r8712_init_mlme_timer(struct _adapter *padapter);
-void r8712_os_indicate_disconnect(struct _adapter *adapter);
-void r8712_os_indicate_connect(struct _adapter *adapter);
-void r8712_report_sec_ie(struct _adapter *adapter, u8 authmode, u8 *sec_ie);
-int r8712_recv_indicatepkts_in_order(struct _adapter *adapter,
- struct recv_reorder_ctrl *precvreorder_ctrl,
- int bforced);
-void r8712_indicate_wx_assoc_event(struct _adapter *padapter);
-void r8712_indicate_wx_disassoc_event(struct _adapter *padapter);
-
-#endif /*_MLME_OSDEP_H_*/
-
diff --git a/drivers/staging/rtl8712/mp_custom_oid.h b/drivers/staging/rtl8712/mp_custom_oid.h
deleted file mode 100644
index a9fac87fcabc..000000000000
--- a/drivers/staging/rtl8712/mp_custom_oid.h
+++ /dev/null
@@ -1,287 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __CUSTOM_OID_H
-#define __CUSTOM_OID_H
-
-/* 0xFF818000 - 0xFF81802F RTL8180 Mass Production Kit
- * 0xFF818500 - 0xFF81850F RTL8185 Setup Utility
- * 0xFF818580 - 0xFF81858F RTL8185 Phy Status Utility
- *
- * by Owen for Production Kit
- * For Production Kit with Agilent Equipments
- * in order to make our custom oids hopefully somewhat unique
- * we will use 0xFF (indicating implementation specific OID)
- * 81(first byte of non zero Realtek unique identifier)
- * 80 (second byte of non zero Realtek unique identifier)
- * XX (the custom OID number - providing 255 possible custom oids)
- */
-#define OID_RT_PRO_RESET_DUT 0xFF818000
-#define OID_RT_PRO_SET_DATA_RATE 0xFF818001
-#define OID_RT_PRO_START_TEST 0xFF818002
-#define OID_RT_PRO_STOP_TEST 0xFF818003
-#define OID_RT_PRO_SET_PREAMBLE 0xFF818004
-#define OID_RT_PRO_SET_SCRAMBLER 0xFF818005
-#define OID_RT_PRO_SET_FILTER_BB 0xFF818006
-#define OID_RT_PRO_SET_MANUAL_DIVERSITY_BB 0xFF818007
-#define OID_RT_PRO_SET_CHANNEL_DIRECT_CALL 0xFF818008
-#define OID_RT_PRO_SET_SLEEP_MODE_DIRECT_CALL 0xFF818009
-#define OID_RT_PRO_SET_WAKE_MODE_DIRECT_CALL 0xFF81800A
-
-#define OID_RT_PRO_SET_TX_ANTENNA_BB 0xFF81800D
-#define OID_RT_PRO_SET_ANTENNA_BB 0xFF81800E
-#define OID_RT_PRO_SET_CR_SCRAMBLER 0xFF81800F
-#define OID_RT_PRO_SET_CR_NEW_FILTER 0xFF818010
-#define OID_RT_PRO_SET_TX_POWER_CONTROL 0xFF818011
-#define OID_RT_PRO_SET_CR_TX_CONFIG 0xFF818012
-#define OID_RT_PRO_GET_TX_POWER_CONTROL 0xFF818013
-#define OID_RT_PRO_GET_CR_SIGNAL_QUALITY 0xFF818014
-#define OID_RT_PRO_SET_CR_SETPOINT 0xFF818015
-#define OID_RT_PRO_SET_INTEGRATOR 0xFF818016
-#define OID_RT_PRO_SET_SIGNAL_QUALITY 0xFF818017
-#define OID_RT_PRO_GET_INTEGRATOR 0xFF818018
-#define OID_RT_PRO_GET_SIGNAL_QUALITY 0xFF818019
-#define OID_RT_PRO_QUERY_EEPROM_TYPE 0xFF81801A
-#define OID_RT_PRO_WRITE_MAC_ADDRESS 0xFF81801B
-#define OID_RT_PRO_READ_MAC_ADDRESS 0xFF81801C
-#define OID_RT_PRO_WRITE_CIS_DATA 0xFF81801D
-#define OID_RT_PRO_READ_CIS_DATA 0xFF81801E
-#define OID_RT_PRO_WRITE_POWER_CONTROL 0xFF81801F
-#define OID_RT_PRO_READ_POWER_CONTROL 0xFF818020
-#define OID_RT_PRO_WRITE_EEPROM 0xFF818021
-#define OID_RT_PRO_READ_EEPROM 0xFF818022
-#define OID_RT_PRO_RESET_TX_PACKET_SENT 0xFF818023
-#define OID_RT_PRO_QUERY_TX_PACKET_SENT 0xFF818024
-#define OID_RT_PRO_RESET_RX_PACKET_RECEIVED 0xFF818025
-#define OID_RT_PRO_QUERY_RX_PACKET_RECEIVED 0xFF818026
-#define OID_RT_PRO_QUERY_RX_PACKET_CRC32_ERROR 0xFF818027
-#define OID_RT_PRO_QUERY_CURRENT_ADDRESS 0xFF818028
-#define OID_RT_PRO_QUERY_PERMANENT_ADDRESS 0xFF818029
-#define OID_RT_PRO_SET_PHILIPS_RF_PARAMETERS 0xFF81802A
-#define OID_RT_PRO_RECEIVE_PACKET 0xFF81802C
-#define OID_RT_PRO_WRITE_EEPROM_BYTE 0xFF81802D
-#define OID_RT_PRO_READ_EEPROM_BYTE 0xFF81802E
-#define OID_RT_PRO_SET_MODULATION 0xFF81802F
-#define OID_RT_DRIVER_OPTION 0xFF818080
-#define OID_RT_RF_OFF 0xFF818081
-#define OID_RT_AUTH_STATUS 0xFF818082
-#define OID_RT_PRO_SET_CONTINUOUS_TX 0xFF81800B
-#define OID_RT_PRO_SET_SINGLE_CARRIER_TX 0xFF81800C
-#define OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX 0xFF81802B
-#define OID_RT_PRO_SET_SINGLE_TONE_TX 0xFF818043
-#define OID_RT_UTILITY_FALSE_ALARM_COUNTERS 0xFF818580
-#define OID_RT_UTILITY_SELECT_DEBUG_MODE 0xFF818581
-#define OID_RT_UTILITY_SELECT_SUBCARRIER_NUMBER 0xFF818582
-#define OID_RT_UTILITY_GET_RSSI_STATUS 0xFF818583
-#define OID_RT_UTILITY_GET_FRAME_DETECTION_STATUS 0xFF818584
-#define OID_RT_UTILITY_GET_AGC_AND_FREQUENCY_OFFSET_ESTIMATION_STATUS \
- 0xFF818585
-#define OID_RT_UTILITY_GET_CHANNEL_ESTIMATION_STATUS 0xFF818586
-#define OID_RT_WIRELESS_MODE 0xFF818500
-#define OID_RT_SUPPORTED_RATES 0xFF818501
-#define OID_RT_DESIRED_RATES 0xFF818502
-#define OID_RT_WIRELESS_MODE_STARTING_ADHOC 0xFF818503
-#define OID_RT_GET_CONNECT_STATE 0xFF030001
-#define OID_RT_RESCAN 0xFF030002
-#define OID_RT_SET_KEY_LENGTH 0xFF030003
-#define OID_RT_SET_DEFAULT_KEY_ID 0xFF030004
-#define OID_RT_SET_CHANNEL 0xFF010182
-#define OID_RT_SET_SNIFFER_MODE 0xFF010183
-#define OID_RT_GET_SIGNAL_QUALITY 0xFF010184
-#define OID_RT_GET_SMALL_PACKET_CRC 0xFF010185
-#define OID_RT_GET_MIDDLE_PACKET_CRC 0xFF010186
-#define OID_RT_GET_LARGE_PACKET_CRC 0xFF010187
-#define OID_RT_GET_TX_RETRY 0xFF010188
-#define OID_RT_GET_RX_RETRY 0xFF010189
-#define OID_RT_PRO_SET_FW_DIG_STATE 0xFF01018A
-#define OID_RT_PRO_SET_FW_RA_STATE 0xFF01018B
-#define OID_RT_GET_RX_TOTAL_PACKET 0xFF010190
-#define OID_RT_GET_TX_BEACON_OK 0xFF010191
-#define OID_RT_GET_TX_BEACON_ERR 0xFF010192
-#define OID_RT_GET_RX_ICV_ERR 0xFF010193
-#define OID_RT_SET_ENCRYPTION_ALGORITHM 0xFF010194
-#define OID_RT_SET_NO_AUTO_RESCAN 0xFF010195
-#define OID_RT_GET_PREAMBLE_MODE 0xFF010196
-#define OID_RT_GET_DRIVER_UP_DELTA_TIME 0xFF010197
-#define OID_RT_GET_AP_IP 0xFF010198
-#define OID_RT_GET_CHANNELPLAN 0xFF010199
-#define OID_RT_SET_PREAMBLE_MODE 0xFF01019A
-#define OID_RT_SET_BCN_INTVL 0xFF01019B
-#define OID_RT_GET_RF_VENDER 0xFF01019C
-#define OID_RT_DEDICATE_PROBE 0xFF01019D
-#define OID_RT_PRO_RX_FILTER_PATTERN 0xFF01019E
-#define OID_RT_GET_DCST_CURRENT_THRESHOLD 0xFF01019F
-#define OID_RT_GET_CCA_ERR 0xFF0101A0
-#define OID_RT_GET_CCA_UPGRADE_THRESHOLD 0xFF0101A1
-#define OID_RT_GET_CCA_FALLBACK_THRESHOLD 0xFF0101A2
-#define OID_RT_GET_CCA_UPGRADE_EVALUATE_TIMES 0xFF0101A3
-#define OID_RT_GET_CCA_FALLBACK_EVALUATE_TIMES 0xFF0101A4
-#define OID_RT_SET_RATE_ADAPTIVE 0xFF0101A5
-#define OID_RT_GET_DCST_EVALUATE_PERIOD 0xFF0101A5
-#define OID_RT_GET_DCST_TIME_UNIT_INDEX 0xFF0101A6
-#define OID_RT_GET_TOTAL_TX_BYTES 0xFF0101A7
-#define OID_RT_GET_TOTAL_RX_BYTES 0xFF0101A8
-#define OID_RT_CURRENT_TX_POWER_LEVEL 0xFF0101A9
-#define OID_RT_GET_ENC_KEY_MISMATCH_COUNT 0xFF0101AA
-#define OID_RT_GET_ENC_KEY_MATCH_COUNT 0xFF0101AB
-#define OID_RT_GET_CHANNEL 0xFF0101AC
-#define OID_RT_SET_CHANNELPLAN 0xFF0101AD
-#define OID_RT_GET_HARDWARE_RADIO_OFF 0xFF0101AE
-#define OID_RT_CHANNELPLAN_BY_COUNTRY 0xFF0101AF
-#define OID_RT_SCAN_AVAILABLE_BSSID 0xFF0101B0
-#define OID_RT_GET_HARDWARE_VERSION 0xFF0101B1
-#define OID_RT_GET_IS_ROAMING 0xFF0101B2
-#define OID_RT_GET_IS_PRIVACY 0xFF0101B3
-#define OID_RT_GET_KEY_MISMATCH 0xFF0101B4
-#define OID_RT_SET_RSSI_ROAM_TRAFFIC_TH 0xFF0101B5
-#define OID_RT_SET_RSSI_ROAM_SIGNAL_TH 0xFF0101B6
-#define OID_RT_RESET_LOG 0xFF0101B7
-#define OID_RT_GET_LOG 0xFF0101B8
-#define OID_RT_SET_INDICATE_HIDDEN_AP 0xFF0101B9
-#define OID_RT_GET_HEADER_FAIL 0xFF0101BA
-#define OID_RT_SUPPORTED_WIRELESS_MODE 0xFF0101BB
-#define OID_RT_GET_CHANNEL_LIST 0xFF0101BC
-#define OID_RT_GET_SCAN_IN_PROGRESS 0xFF0101BD
-#define OID_RT_GET_TX_INFO 0xFF0101BE
-#define OID_RT_RF_READ_WRITE_OFFSET 0xFF0101BF
-#define OID_RT_RF_READ_WRITE 0xFF0101C0
-#define OID_RT_FORCED_DATA_RATE 0xFF0101C1
-#define OID_RT_WIRELESS_MODE_FOR_SCAN_LIST 0xFF0101C2
-#define OID_RT_GET_BSS_WIRELESS_MODE 0xFF0101C3
-#define OID_RT_SCAN_WITH_MAGIC_PACKET 0xFF0101C4
-#define OID_RT_PRO_RX_FILTER 0xFF0111C0
-#define OID_CE_USB_WRITE_REGISTRY 0xFF0111C1
-#define OID_CE_USB_READ_REGISTRY 0xFF0111C2
-#define OID_RT_PRO_SET_INITIAL_GAIN 0xFF0111C3
-#define OID_RT_PRO_SET_BB_RF_STANDBY_MODE 0xFF0111C4
-#define OID_RT_PRO_SET_BB_RF_SHUTDOWN_MODE 0xFF0111C5
-#define OID_RT_PRO_SET_TX_CHARGE_PUMP 0xFF0111C6
-#define OID_RT_PRO_SET_RX_CHARGE_PUMP 0xFF0111C7
-#define OID_RT_PRO_RF_WRITE_REGISTRY 0xFF0111C8
-#define OID_RT_PRO_RF_READ_REGISTRY 0xFF0111C9
-#define OID_RT_PRO_QUERY_RF_TYPE 0xFF0111CA
-#define OID_RT_AP_GET_ASSOCIATED_STATION_LIST 0xFF010300
-#define OID_RT_AP_GET_CURRENT_TIME_STAMP 0xFF010301
-#define OID_RT_AP_SWITCH_INTO_AP_MODE 0xFF010302
-#define OID_RT_AP_SET_DTIM_PERIOD 0xFF010303
-#define OID_RT_AP_SUPPORTED 0xFF010304
-#define OID_RT_AP_SET_PASSPHRASE 0xFF010305
-#define OID_RT_PRO8187_WI_POLL 0xFF818780
-#define OID_RT_PRO_WRITE_BB_REG 0xFF818781
-#define OID_RT_PRO_READ_BB_REG 0xFF818782
-#define OID_RT_PRO_WRITE_RF_REG 0xFF818783
-#define OID_RT_PRO_READ_RF_REG 0xFF818784
-#define OID_RT_MH_VENDER_ID 0xFFEDC100
-#define OID_RT_PRO8711_JOIN_BSS 0xFF871100
-#define OID_RT_PRO_READ_REGISTER 0xFF871101
-#define OID_RT_PRO_WRITE_REGISTER 0xFF871102
-#define OID_RT_PRO_BURST_READ_REGISTER 0xFF871103
-#define OID_RT_PRO_BURST_WRITE_REGISTER 0xFF871104
-#define OID_RT_PRO_WRITE_TXCMD 0xFF871105
-#define OID_RT_PRO_READ16_EEPROM 0xFF871106
-#define OID_RT_PRO_WRITE16_EEPROM 0xFF871107
-#define OID_RT_PRO_H2C_SET_COMMAND 0xFF871108
-#define OID_RT_PRO_H2C_QUERY_RESULT 0xFF871109
-#define OID_RT_PRO8711_WI_POLL 0xFF87110A
-#define OID_RT_PRO8711_PKT_LOSS 0xFF87110B
-#define OID_RT_RD_ATTRIB_MEM 0xFF87110C
-#define OID_RT_WR_ATTRIB_MEM 0xFF87110D
-/*Method 2 for H2C/C2H*/
-#define OID_RT_PRO_H2C_CMD_MODE 0xFF871110
-#define OID_RT_PRO_H2C_CMD_RSP_MODE 0xFF871111
-#define OID_RT_PRO_H2C_CMD_EVENT_MODE 0xFF871112
-#define OID_RT_PRO_WAIT_C2H_EVENT 0xFF871113
-#define OID_RT_PRO_RW_ACCESS_PROTOCOL_TEST 0xFF871114
-#define OID_RT_PRO_SCSI_ACCESS_TEST 0xFF871115
-#define OID_RT_PRO_SCSI_TCPIPOFFLOAD_OUT 0xFF871116
-#define OID_RT_PRO_SCSI_TCPIPOFFLOAD_IN 0xFF871117
-#define OID_RT_RRO_RX_PKT_VIA_IOCTRL 0xFF871118
-#define OID_RT_RRO_RX_PKTARRAY_VIA_IOCTRL 0xFF871119
-#define OID_RT_RPO_SET_PWRMGT_TEST 0xFF87111A
-#define OID_RT_PRO_QRY_PWRMGT_TEST 0XFF87111B
-#define OID_RT_RPO_ASYNC_RWIO_TEST 0xFF87111C
-#define OID_RT_RPO_ASYNC_RWIO_POLL 0xFF87111D
-#define OID_RT_PRO_SET_RF_INTFS 0xFF87111E
-#define OID_RT_POLL_RX_STATUS 0xFF87111F
-#define OID_RT_PRO_CFG_DEBUG_MESSAGE 0xFF871120
-#define OID_RT_PRO_SET_DATA_RATE_EX 0xFF871121
-#define OID_RT_PRO_SET_BASIC_RATE 0xFF871122
-#define OID_RT_PRO_READ_TSSI 0xFF871123
-#define OID_RT_PRO_SET_POWER_TRACKING 0xFF871124
-#define OID_RT_PRO_QRY_PWRSTATE 0xFF871150
-#define OID_RT_PRO_SET_PWRSTATE 0xFF871151
-/*Method 2 , using workitem */
-#define OID_RT_SET_READ_REG 0xFF871181
-#define OID_RT_SET_WRITE_REG 0xFF871182
-#define OID_RT_SET_BURST_READ_REG 0xFF871183
-#define OID_RT_SET_BURST_WRITE_REG 0xFF871184
-#define OID_RT_SET_WRITE_TXCMD 0xFF871185
-#define OID_RT_SET_READ16_EEPROM 0xFF871186
-#define OID_RT_SET_WRITE16_EEPROM 0xFF871187
-#define OID_RT_QRY_POLL_WKITEM 0xFF871188
-
-/*For SDIO INTERFACE only*/
-#define OID_RT_PRO_SYNCPAGERW_SRAM 0xFF8711A0
-#define OID_RT_PRO_871X_DRV_EXT 0xFF8711A1
-
-/*For USB INTERFACE only*/
-#define OID_RT_PRO_USB_VENDOR_REQ 0xFF8711B0
-#define OID_RT_PRO_SCSI_AUTO_TEST 0xFF8711B1
-#define OID_RT_PRO_USB_MAC_AC_FIFO_WRITE 0xFF8711B2
-#define OID_RT_PRO_USB_MAC_RX_FIFO_READ 0xFF8711B3
-#define OID_RT_PRO_USB_MAC_RX_FIFO_POLLING 0xFF8711B4
-
-#define OID_RT_PRO_H2C_SET_RATE_TABLE 0xFF8711FB
-#define OID_RT_PRO_H2C_GET_RATE_TABLE 0xFF8711FC
-#define OID_RT_PRO_H2C_C2H_LBK_TEST 0xFF8711FE
-
-#define OID_RT_PRO_ENCRYPTION_CTRL 0xFF871200
-#define OID_RT_PRO_ADD_STA_INFO 0xFF871201
-#define OID_RT_PRO_DELE_STA_INFO 0xFF871202
-#define OID_RT_PRO_QUERY_DR_VARIABLE 0xFF871203
-
-#define OID_RT_PRO_RX_PACKET_TYPE 0xFF871204
-
-#define OID_RT_PRO_READ_EFUSE 0xFF871205
-#define OID_RT_PRO_WRITE_EFUSE 0xFF871206
-#define OID_RT_PRO_RW_EFUSE_PGPKT 0xFF871207
-#define OID_RT_GET_EFUSE_CURRENT_SIZE 0xFF871208
-
-#define OID_RT_SET_BANDWIDTH 0xFF871209
-#define OID_RT_SET_CRYSTAL_CAP 0xFF87120A
-
-#define OID_RT_SET_RX_PACKET_TYPE 0xFF87120B
-
-#define OID_RT_GET_EFUSE_MAX_SIZE 0xFF87120C
-
-#define OID_RT_PRO_SET_TX_AGC_OFFSET 0xFF87120D
-
-#define OID_RT_PRO_SET_PKT_TEST_MODE 0xFF87120E
-
-#define OID_RT_PRO_FOR_EVM_TEST_SETTING 0xFF87120F
-
-#define OID_RT_PRO_GET_THERMAL_METER 0xFF871210
-
-#define OID_RT_RESET_PHY_RX_PACKET_COUNT 0xFF871211
-#define OID_RT_GET_PHY_RX_PACKET_RECEIVED 0xFF871212
-#define OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR 0xFF871213
-
-#define OID_RT_SET_POWER_DOWN 0xFF871214
-
-#define OID_RT_GET_POWER_MODE 0xFF871215
-
-#define OID_RT_PRO_EFUSE 0xFF871216
-#define OID_RT_PRO_EFUSE_MAP 0xFF871217
-
-#endif /*#ifndef __CUSTOM_OID_H */
-
diff --git a/drivers/staging/rtl8712/os_intfs.c b/drivers/staging/rtl8712/os_intfs.c
deleted file mode 100644
index 1b11f8b04e13..000000000000
--- a/drivers/staging/rtl8712/os_intfs.c
+++ /dev/null
@@ -1,482 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * os_intfs.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _OS_INTFS_C_
-
-#include <linux/module.h>
-#include <linux/kthread.h>
-#include <linux/firmware.h>
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "xmit_osdep.h"
-#include "recv_osdep.h"
-#include "rtl871x_ioctl.h"
-#include "usb_osintf.h"
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("rtl871x wireless lan driver");
-MODULE_AUTHOR("Larry Finger");
-
-static char ifname[IFNAMSIZ] = "wlan%d";
-
-/* module param defaults */
-static int chip_version = RTL8712_2ndCUT;
-static int rfintfs = HWPI;
-static int lbkmode = RTL8712_AIR_TRX;
-static int hci = RTL8712_USB;
-static int ampdu_enable = 1;/*for enable tx_ampdu*/
-
-/* The video_mode variable is for video mode.*/
-/* It may be specify when inserting module with video_mode=1 parameter.*/
-static int video_mode = 1; /* enable video mode*/
-
-/*Ndis802_11Infrastructure; infra, ad-hoc, auto*/
-static int network_mode = Ndis802_11IBSS;
-static int channel = 1;/*ad-hoc support requirement*/
-static int wireless_mode = WIRELESS_11BG;
-static int vrtl_carrier_sense = AUTO_VCS;
-static int vcs_type = RTS_CTS;
-static int frag_thresh = 2346;
-static int preamble = PREAMBLE_LONG;/*long, short, auto*/
-static int scan_mode = 1;/*active, passive*/
-static int adhoc_tx_pwr = 1;
-static int soft_ap;
-static int smart_ps = 1;
-static int power_mgnt = PS_MODE_ACTIVE;
-static int radio_enable = 1;
-static int long_retry_lmt = 7;
-static int short_retry_lmt = 7;
-static int busy_thresh = 40;
-static int ack_policy = NORMAL_ACK;
-static int mp_mode;
-static int software_encrypt;
-static int software_decrypt;
-
-static int wmm_enable;/* default is set to disable the wmm.*/
-static int uapsd_enable;
-static int uapsd_max_sp = NO_LIMIT;
-static int uapsd_acbk_en;
-static int uapsd_acbe_en;
-static int uapsd_acvi_en;
-static int uapsd_acvo_en;
-
-static int ht_enable = 1;
-static int cbw40_enable = 1;
-static int rf_config = RTL8712_RF_1T2R; /* 1T2R*/
-static int low_power;
-/* mac address to use instead of the one stored in Efuse */
-char *r8712_initmac;
-static char *initmac;
-/* if wifi_test = 1, driver will disable the turbo mode and pass it to
- * firmware private.
- */
-static int wifi_test;
-
-module_param_string(ifname, ifname, sizeof(ifname), 0644);
-module_param(wifi_test, int, 0644);
-module_param(initmac, charp, 0644);
-module_param(video_mode, int, 0644);
-module_param(chip_version, int, 0644);
-module_param(rfintfs, int, 0644);
-module_param(lbkmode, int, 0644);
-module_param(hci, int, 0644);
-module_param(network_mode, int, 0644);
-module_param(channel, int, 0644);
-module_param(mp_mode, int, 0644);
-module_param(wmm_enable, int, 0644);
-module_param(vrtl_carrier_sense, int, 0644);
-module_param(vcs_type, int, 0644);
-module_param(busy_thresh, int, 0644);
-module_param(ht_enable, int, 0644);
-module_param(cbw40_enable, int, 0644);
-module_param(ampdu_enable, int, 0644);
-module_param(rf_config, int, 0644);
-module_param(power_mgnt, int, 0644);
-module_param(low_power, int, 0644);
-
-MODULE_PARM_DESC(ifname, " Net interface name, wlan%d=default");
-MODULE_PARM_DESC(initmac, "MAC-Address, default: use FUSE");
-
-static int netdev_open(struct net_device *pnetdev);
-static int netdev_close(struct net_device *pnetdev);
-
-static void loadparam(struct _adapter *padapter, struct net_device *pnetdev)
-{
- struct registry_priv *registry_par = &padapter->registrypriv;
-
- registry_par->chip_version = (u8)chip_version;
- registry_par->rfintfs = (u8)rfintfs;
- registry_par->lbkmode = (u8)lbkmode;
- registry_par->hci = (u8)hci;
- registry_par->network_mode = (u8)network_mode;
- memcpy(registry_par->ssid.Ssid, "ANY", 3);
- registry_par->ssid.SsidLength = 3;
- registry_par->channel = (u8)channel;
- registry_par->wireless_mode = (u8)wireless_mode;
- registry_par->vrtl_carrier_sense = (u8)vrtl_carrier_sense;
- registry_par->vcs_type = (u8)vcs_type;
- registry_par->frag_thresh = (u16)frag_thresh;
- registry_par->preamble = (u8)preamble;
- registry_par->scan_mode = (u8)scan_mode;
- registry_par->adhoc_tx_pwr = (u8)adhoc_tx_pwr;
- registry_par->soft_ap = (u8)soft_ap;
- registry_par->smart_ps = (u8)smart_ps;
- registry_par->power_mgnt = (u8)power_mgnt;
- registry_par->radio_enable = (u8)radio_enable;
- registry_par->long_retry_lmt = (u8)long_retry_lmt;
- registry_par->short_retry_lmt = (u8)short_retry_lmt;
- registry_par->busy_thresh = (u16)busy_thresh;
- registry_par->ack_policy = (u8)ack_policy;
- registry_par->mp_mode = (u8)mp_mode;
- registry_par->software_encrypt = (u8)software_encrypt;
- registry_par->software_decrypt = (u8)software_decrypt;
- /*UAPSD*/
- registry_par->wmm_enable = (u8)wmm_enable;
- registry_par->uapsd_enable = (u8)uapsd_enable;
- registry_par->uapsd_max_sp = (u8)uapsd_max_sp;
- registry_par->uapsd_acbk_en = (u8)uapsd_acbk_en;
- registry_par->uapsd_acbe_en = (u8)uapsd_acbe_en;
- registry_par->uapsd_acvi_en = (u8)uapsd_acvi_en;
- registry_par->uapsd_acvo_en = (u8)uapsd_acvo_en;
- registry_par->ht_enable = (u8)ht_enable;
- registry_par->cbw40_enable = (u8)cbw40_enable;
- registry_par->ampdu_enable = (u8)ampdu_enable;
- registry_par->rf_config = (u8)rf_config;
- registry_par->low_power = (u8)low_power;
- registry_par->wifi_test = (u8)wifi_test;
- r8712_initmac = initmac;
-}
-
-static int r871x_net_set_mac_address(struct net_device *pnetdev, void *p)
-{
- struct _adapter *padapter = netdev_priv(pnetdev);
- struct sockaddr *addr = p;
-
- if (!padapter->bup)
- eth_hw_addr_set(pnetdev, addr->sa_data);
- return 0;
-}
-
-static struct net_device_stats *r871x_net_get_stats(struct net_device *pnetdev)
-{
- struct _adapter *padapter = netdev_priv(pnetdev);
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- padapter->stats.tx_packets = pxmitpriv->tx_pkts;
- padapter->stats.rx_packets = precvpriv->rx_pkts;
- padapter->stats.tx_dropped = pxmitpriv->tx_drop;
- padapter->stats.rx_dropped = precvpriv->rx_drop;
- padapter->stats.tx_bytes = pxmitpriv->tx_bytes;
- padapter->stats.rx_bytes = precvpriv->rx_bytes;
- return &padapter->stats;
-}
-
-static const struct net_device_ops rtl8712_netdev_ops = {
- .ndo_open = netdev_open,
- .ndo_stop = netdev_close,
- .ndo_start_xmit = r8712_xmit_entry,
- .ndo_set_mac_address = r871x_net_set_mac_address,
- .ndo_get_stats = r871x_net_get_stats,
- .ndo_do_ioctl = r871x_ioctl,
-};
-
-struct net_device *r8712_init_netdev(void)
-{
- struct _adapter *padapter;
- struct net_device *pnetdev;
-
- pnetdev = alloc_etherdev(sizeof(struct _adapter));
- if (!pnetdev)
- return NULL;
- if (dev_alloc_name(pnetdev, ifname) < 0) {
- strscpy(ifname, "wlan%d", sizeof(ifname));
- dev_alloc_name(pnetdev, ifname);
- }
- padapter = netdev_priv(pnetdev);
- padapter->pnetdev = pnetdev;
- pr_info("r8712u: register rtl8712_netdev_ops to netdev_ops\n");
- pnetdev->netdev_ops = &rtl8712_netdev_ops;
- pnetdev->watchdog_timeo = HZ; /* 1 second timeout */
- pnetdev->wireless_handlers = (struct iw_handler_def *)
- &r871x_handlers_def;
- loadparam(padapter, pnetdev);
- netif_carrier_off(pnetdev);
- padapter->pid = 0; /* Initial the PID value used for HW PBC.*/
- return pnetdev;
-}
-
-static u32 start_drv_threads(struct _adapter *padapter)
-{
- padapter->cmd_thread = kthread_run(r8712_cmd_thread, padapter, "%s",
- padapter->pnetdev->name);
- if (IS_ERR(padapter->cmd_thread))
- return _FAIL;
- return _SUCCESS;
-}
-
-void r8712_stop_drv_threads(struct _adapter *padapter)
-{
- struct completion *completion =
- &padapter->cmdpriv.terminate_cmdthread_comp;
-
- /*Below is to terminate r8712_cmd_thread & event_thread...*/
- complete(&padapter->cmdpriv.cmd_queue_comp);
- if (padapter->cmd_thread)
- wait_for_completion_interruptible(completion);
- padapter->cmdpriv.cmd_seq = 1;
-}
-
-static void start_drv_timers(struct _adapter *padapter)
-{
- mod_timer(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer,
- jiffies + msecs_to_jiffies(5000));
- mod_timer(&padapter->mlmepriv.wdg_timer,
- jiffies + msecs_to_jiffies(2000));
-}
-
-void r8712_stop_drv_timers(struct _adapter *padapter)
-{
- del_timer_sync(&padapter->mlmepriv.assoc_timer);
- del_timer_sync(&padapter->securitypriv.tkip_timer);
- del_timer_sync(&padapter->mlmepriv.scan_to_timer);
- del_timer_sync(&padapter->mlmepriv.dhcp_timer);
- del_timer_sync(&padapter->mlmepriv.wdg_timer);
- del_timer_sync(&padapter->mlmepriv.sitesurveyctrl.sitesurvey_ctrl_timer);
-}
-
-static void init_default_value(struct _adapter *padapter)
-{
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- /*xmit_priv*/
- pxmitpriv->vcs_setting = pregistrypriv->vrtl_carrier_sense;
- pxmitpriv->vcs = pregistrypriv->vcs_type;
- pxmitpriv->vcs_type = pregistrypriv->vcs_type;
- pxmitpriv->rts_thresh = pregistrypriv->rts_thresh;
- pxmitpriv->frag_len = pregistrypriv->frag_thresh;
- /* mlme_priv */
- /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
- pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
- /*ht_priv*/
- {
- int i;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-
- phtpriv->ampdu_enable = false;/*set to disabled*/
- for (i = 0; i < 16; i++)
- phtpriv->baddbareq_issued[i] = false;
- }
- /*security_priv*/
- psecuritypriv->sw_encrypt = pregistrypriv->software_encrypt;
- psecuritypriv->sw_decrypt = pregistrypriv->software_decrypt;
- psecuritypriv->binstallGrpkey = _FAIL;
- /*pwrctrl_priv*/
- /*registry_priv*/
- r8712_init_registrypriv_dev_network(padapter);
- r8712_update_registrypriv_dev_network(padapter);
- /*misc.*/
-}
-
-int r8712_init_drv_sw(struct _adapter *padapter)
-{
- int ret;
-
- ret = r8712_init_cmd_priv(&padapter->cmdpriv);
- if (ret)
- return ret;
- padapter->cmdpriv.padapter = padapter;
- ret = r8712_init_evt_priv(&padapter->evtpriv);
- if (ret)
- goto free_cmd;
- ret = r8712_init_mlme_priv(padapter);
- if (ret)
- goto free_evt;
- ret = _r8712_init_xmit_priv(&padapter->xmitpriv, padapter);
- if (ret)
- goto free_mlme;
- ret = _r8712_init_recv_priv(&padapter->recvpriv, padapter);
- if (ret)
- goto free_xmit;
- memset((unsigned char *)&padapter->securitypriv, 0,
- sizeof(struct security_priv));
- timer_setup(&padapter->securitypriv.tkip_timer,
- r8712_use_tkipkey_handler, 0);
- ret = _r8712_init_sta_priv(&padapter->stapriv);
- if (ret)
- goto free_recv;
- padapter->stapriv.padapter = padapter;
- r8712_init_bcmc_stainfo(padapter);
- r8712_init_pwrctrl_priv(padapter);
- mp871xinit(padapter);
- init_default_value(padapter);
- r8712_InitSwLeds(padapter);
- mutex_init(&padapter->mutex_start);
-
- return 0;
-
-free_recv:
- _r8712_free_recv_priv(&padapter->recvpriv);
-free_xmit:
- _free_xmit_priv(&padapter->xmitpriv);
-free_mlme:
- r8712_free_mlme_priv(&padapter->mlmepriv);
-free_evt:
- r8712_free_evt_priv(&padapter->evtpriv);
-free_cmd:
- r8712_free_cmd_priv(&padapter->cmdpriv);
- return ret;
-}
-
-void r8712_free_drv_sw(struct _adapter *padapter)
-{
- r8712_free_cmd_priv(&padapter->cmdpriv);
- r8712_free_evt_priv(&padapter->evtpriv);
- r8712_DeInitSwLeds(padapter);
- r8712_free_mlme_priv(&padapter->mlmepriv);
- _free_xmit_priv(&padapter->xmitpriv);
- _r8712_free_sta_priv(&padapter->stapriv);
- _r8712_free_recv_priv(&padapter->recvpriv);
- mp871xdeinit(padapter);
-}
-
-static void enable_video_mode(struct _adapter *padapter, int cbw40_value)
-{
- /* bit 8:
- * 1 -> enable video mode to 96B AP
- * 0 -> disable video mode to 96B AP
- * bit 9:
- * 1 -> enable 40MHz mode
- * 0 -> disable 40MHz mode
- * bit 10:
- * 1 -> enable STBC
- * 0 -> disable STBC
- */
- u32 intcmd = 0xf4000500; /* enable bit8, bit10*/
-
- if (cbw40_value) {
- /* if the driver supports the 40M bandwidth,
- * we can enable the bit 9.
- */
- intcmd |= 0x200;
- }
- r8712_fw_cmd(padapter, intcmd);
-}
-
-/*
- *
- * This function intends to handle the activation of an interface
- * i.e. when it is brought Up/Active from a Down state.
- *
- */
-static int netdev_open(struct net_device *pnetdev)
-{
- struct _adapter *padapter = netdev_priv(pnetdev);
-
- mutex_lock(&padapter->mutex_start);
- if (!padapter->bup) {
- padapter->driver_stopped = false;
- padapter->surprise_removed = false;
- padapter->bup = true;
- if (rtl871x_hal_init(padapter) != _SUCCESS)
- goto netdev_open_error;
- if (!r8712_initmac) {
- /* Use the mac address stored in the Efuse */
- eth_hw_addr_set(pnetdev,
- padapter->eeprompriv.mac_addr);
- } else {
- /* We have to inform f/w to use user-supplied MAC
- * address.
- */
- msleep(200);
- r8712_setMacAddr_cmd(padapter,
- (const u8 *)pnetdev->dev_addr);
- /*
- * The "myid" function will get the wifi mac address
- * from eeprompriv structure instead of netdev
- * structure. So, we have to overwrite the mac_addr
- * stored in the eeprompriv structure. In this case,
- * the real mac address won't be used anymore. So that,
- * the eeprompriv.mac_addr should store the mac which
- * users specify.
- */
- memcpy(padapter->eeprompriv.mac_addr,
- pnetdev->dev_addr, ETH_ALEN);
- }
- if (start_drv_threads(padapter) != _SUCCESS)
- goto netdev_open_error;
- if (!padapter->dvobjpriv.inirp_init)
- goto netdev_open_error;
- else
- padapter->dvobjpriv.inirp_init(padapter);
- r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
- padapter->registrypriv.smart_ps);
- }
- if (!netif_queue_stopped(pnetdev))
- netif_start_queue(pnetdev);
- else
- netif_wake_queue(pnetdev);
-
- if (video_mode)
- enable_video_mode(padapter, cbw40_enable);
- /* start driver mlme relation timer */
- start_drv_timers(padapter);
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
- mutex_unlock(&padapter->mutex_start);
- return 0;
-netdev_open_error:
- padapter->bup = false;
- netif_carrier_off(pnetdev);
- netif_stop_queue(pnetdev);
- mutex_unlock(&padapter->mutex_start);
- return -1;
-}
-
-/*
- *
- * This function intends to handle the shutdown of an interface
- * i.e. when it is brought Down from an Up/Active state.
- *
- */
-static int netdev_close(struct net_device *pnetdev)
-{
- struct _adapter *padapter = netdev_priv(pnetdev);
-
- /* Close LED*/
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_POWER_OFF);
- msleep(200);
-
- /*s1.*/
- if (pnetdev) {
- if (!netif_queue_stopped(pnetdev))
- netif_stop_queue(pnetdev);
- }
- /*s2.*/
- /*s2-1. issue disassoc_cmd to fw*/
- r8712_disassoc_cmd(padapter);
- /*s2-2. indicate disconnect to os*/
- r8712_ind_disconnect(padapter);
- /*s2-3.*/
- r8712_free_assoc_resources(padapter);
- /*s2-4.*/
- r8712_free_network_queue(padapter);
- return 0;
-}
-
-#include "mlme_osdep.h"
diff --git a/drivers/staging/rtl8712/osdep_intf.h b/drivers/staging/rtl8712/osdep_intf.h
deleted file mode 100644
index 9e75116c987e..000000000000
--- a/drivers/staging/rtl8712/osdep_intf.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __OSDEP_INTF_H_
-#define __OSDEP_INTF_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#define RND4(x) (((x >> 2) + ((x & 3) != 0)) << 2)
-
-struct intf_priv {
- u8 *intf_dev;
- /* when in USB, IO is through interrupt in/out endpoints */
- struct usb_device *udev;
- struct urb *piorw_urb;
- struct completion io_retevt_comp;
-};
-
-int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
-
-#endif /*_OSDEP_INTF_H_*/
diff --git a/drivers/staging/rtl8712/osdep_service.h b/drivers/staging/rtl8712/osdep_service.h
deleted file mode 100644
index 0d9bb42cbc58..000000000000
--- a/drivers/staging/rtl8712/osdep_service.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __OSDEP_SERVICE_H_
-#define __OSDEP_SERVICE_H_
-
-#define _SUCCESS 1
-#define _FAIL 0
-
-#include <linux/spinlock.h>
-
-#include <linux/interrupt.h>
-#include <linux/semaphore.h>
-#include <linux/sched/signal.h>
-#include <linux/sem.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <net/iw_handler.h>
-#include <linux/proc_fs.h> /* Necessary because we use the proc fs */
-
-#include "basic_types.h"
-
-struct __queue {
- struct list_head queue;
- spinlock_t lock;
-};
-
-#define _pkt struct sk_buff
-#define _buffer unsigned char
-
-#define _init_queue(pqueue) \
- do { \
- INIT_LIST_HEAD(&((pqueue)->queue)); \
- spin_lock_init(&((pqueue)->lock)); \
- } while (0)
-
-static inline u32 end_of_queue_search(struct list_head *head,
- struct list_head *plist)
-{
- return (head == plist);
-}
-
-static inline void flush_signals_thread(void)
-{
- if (signal_pending(current))
- flush_signals(current);
-}
-
-#endif
-
diff --git a/drivers/staging/rtl8712/recv_linux.c b/drivers/staging/rtl8712/recv_linux.c
deleted file mode 100644
index 215fca4abb3a..000000000000
--- a/drivers/staging/rtl8712/recv_linux.c
+++ /dev/null
@@ -1,139 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * recv_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RECV_OSDEP_C_
-
-#include <linux/usb.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wifi.h"
-#include "recv_osdep.h"
-#include "osdep_intf.h"
-#include "ethernet.h"
-#include <linux/if_arp.h>
-#include "usb_ops.h"
-
-/*init os related resource in struct recv_priv*/
-/*alloc os related resource in union recv_frame*/
-void r8712_os_recv_resource_alloc(struct _adapter *padapter,
- union recv_frame *precvframe)
-{
- precvframe->u.hdr.pkt_newalloc = NULL;
- precvframe->u.hdr.pkt = NULL;
-}
-
-/*alloc os related resource in struct recv_buf*/
-int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter,
- struct recv_buf *precvbuf)
-{
- int res = 0;
-
- precvbuf->irp_pending = false;
- precvbuf->purb = usb_alloc_urb(0, GFP_KERNEL);
- if (!precvbuf->purb)
- res = -ENOMEM;
- precvbuf->pskb = NULL;
- precvbuf->pallocated_buf = NULL;
- precvbuf->pbuf = NULL;
- precvbuf->pdata = NULL;
- precvbuf->phead = NULL;
- precvbuf->ptail = NULL;
- precvbuf->pend = NULL;
- precvbuf->transfer_len = 0;
- precvbuf->len = 0;
- return res;
-}
-
-/*free os related resource in struct recv_buf*/
-void r8712_os_recvbuf_resource_free(struct _adapter *padapter,
- struct recv_buf *precvbuf)
-{
- if (precvbuf->pskb)
- dev_kfree_skb_any(precvbuf->pskb);
- if (precvbuf->purb) {
- usb_kill_urb(precvbuf->purb);
- usb_free_urb(precvbuf->purb);
- }
-}
-
-void r8712_handle_tkip_mic_err(struct _adapter *adapter, u8 bgroup)
-{
- union iwreq_data wrqu;
- struct iw_michaelmicfailure ev;
- struct mlme_priv *mlmepriv = &adapter->mlmepriv;
-
- memset(&ev, 0x00, sizeof(ev));
- if (bgroup)
- ev.flags |= IW_MICFAILURE_GROUP;
- else
- ev.flags |= IW_MICFAILURE_PAIRWISE;
- ev.src_addr.sa_family = ARPHRD_ETHER;
- ether_addr_copy(ev.src_addr.sa_data, &mlmepriv->assoc_bssid[0]);
- memset(&wrqu, 0x00, sizeof(wrqu));
- wrqu.data.length = sizeof(ev);
- wireless_send_event(adapter->pnetdev, IWEVMICHAELMICFAILURE, &wrqu,
- (char *)&ev);
-}
-
-void r8712_recv_indicatepkt(struct _adapter *adapter,
- union recv_frame *recvframe)
-{
- struct recv_priv *recvpriv;
- struct __queue *free_recv_queue;
- _pkt *skb;
- struct rx_pkt_attrib *attrib = &recvframe->u.hdr.attrib;
-
- recvpriv = &adapter->recvpriv;
- free_recv_queue = &recvpriv->free_recv_queue;
- skb = recvframe->u.hdr.pkt;
- if (!skb)
- goto _recv_indicatepkt_drop;
- skb->data = recvframe->u.hdr.rx_data;
- skb->len = recvframe->u.hdr.len;
- skb_set_tail_pointer(skb, skb->len);
- if ((attrib->tcpchk_valid == 1) && (attrib->tcp_chkrpt == 1))
- skb->ip_summed = CHECKSUM_UNNECESSARY;
- else
- skb->ip_summed = CHECKSUM_NONE;
- skb->dev = adapter->pnetdev;
- skb->protocol = eth_type_trans(skb, adapter->pnetdev);
- netif_rx(skb);
- recvframe->u.hdr.pkt = NULL; /* pointers to NULL before
- * r8712_free_recvframe()
- */
- r8712_free_recvframe(recvframe, free_recv_queue);
- return;
-_recv_indicatepkt_drop:
- /*enqueue back to free_recv_queue*/
- if (recvframe)
- r8712_free_recvframe(recvframe, free_recv_queue);
- recvpriv->rx_drop++;
-}
-
-static void _r8712_reordering_ctrl_timeout_handler (struct timer_list *t)
-{
- struct recv_reorder_ctrl *reorder_ctrl =
- from_timer(reorder_ctrl, t, reordering_ctrl_timer);
-
- r8712_reordering_ctrl_timeout_handler(reorder_ctrl);
-}
-
-void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl)
-{
- timer_setup(&preorder_ctrl->reordering_ctrl_timer,
- _r8712_reordering_ctrl_timeout_handler, 0);
-}
diff --git a/drivers/staging/rtl8712/recv_osdep.h b/drivers/staging/rtl8712/recv_osdep.h
deleted file mode 100644
index fbe3f2868506..000000000000
--- a/drivers/staging/rtl8712/recv_osdep.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RECV_OSDEP_H_
-#define __RECV_OSDEP_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include <linux/skbuff.h>
-
-int _r8712_init_recv_priv(struct recv_priv *precvpriv,
- struct _adapter *padapter);
-void _r8712_free_recv_priv(struct recv_priv *precvpriv);
-void r8712_recv_entry(union recv_frame *precv_frame);
-void r8712_recv_indicatepkt(struct _adapter *adapter,
- union recv_frame *precv_frame);
-void r8712_handle_tkip_mic_err(struct _adapter *padapter, u8 bgroup);
-int r8712_init_recv_priv(struct recv_priv *precvpriv,
- struct _adapter *padapter);
-void r8712_free_recv_priv(struct recv_priv *precvpriv);
-void r8712_os_recv_resource_alloc(struct _adapter *padapter,
- union recv_frame *precvframe);
-int r8712_os_recvbuf_resource_alloc(struct _adapter *padapter,
- struct recv_buf *precvbuf);
-void r8712_os_recvbuf_resource_free(struct _adapter *padapter,
- struct recv_buf *precvbuf);
-void r8712_init_recv_timer(struct recv_reorder_ctrl *preorder_ctrl);
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl8712_bitdef.h b/drivers/staging/rtl8712/rtl8712_bitdef.h
deleted file mode 100644
index a4a687dcc2e7..000000000000
--- a/drivers/staging/rtl8712/rtl8712_bitdef.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-
-#ifndef __RTL8712_BITDEF_H__
-#define __RTL8712_BITDEF_H__
-
-#include "rtl8712_cmdctrl_bitdef.h"
-#include "rtl8712_syscfg_bitdef.h"
-#include "rtl8712_macsetting_bitdef.h"
-#include "rtl8712_timectrl_bitdef.h"
-#include "rtl8712_fifoctrl_bitdef.h"
-#include "rtl8712_ratectrl_bitdef.h"
-#include "rtl8712_edcasetting_bitdef.h"
-#include "rtl8712_wmac_bitdef.h"
-#include "rtl8712_security_bitdef.h"
-#include "rtl8712_powersave_bitdef.h"
-#include "rtl8712_gp_bitdef.h"
-#include "rtl8712_interrupt_bitdef.h"
-#include "rtl8712_debugctrl_bitdef.h"
-
-#endif /* __RTL8712_BITDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_cmd.c b/drivers/staging/rtl8712/rtl8712_cmd.c
deleted file mode 100644
index bb7db96ed821..000000000000
--- a/drivers/staging/rtl8712/rtl8712_cmd.c
+++ /dev/null
@@ -1,409 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl8712_cmd.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL8712_CMD_C_
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/sched/signal.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-#include <linux/circ_buf.h>
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-#include <linux/atomic.h>
-#include <linux/semaphore.h>
-#include <linux/rtnetlink.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "mlme_osdep.h"
-#include "rtl871x_ioctl_set.h"
-
-static void check_hw_pbc(struct _adapter *padapter)
-{
- u8 tmp1byte;
-
- r8712_write8(padapter, MAC_PINMUX_CTRL, (GPIOMUX_EN | GPIOSEL_GPIO));
- tmp1byte = r8712_read8(padapter, GPIO_IO_SEL);
- tmp1byte &= ~(HAL_8192S_HW_GPIO_WPS_BIT);
- r8712_write8(padapter, GPIO_IO_SEL, tmp1byte);
- tmp1byte = r8712_read8(padapter, GPIO_CTRL);
- if (tmp1byte == 0xff)
- return;
- if (tmp1byte & HAL_8192S_HW_GPIO_WPS_BIT) {
- /* Here we only set bPbcPressed to true
- * After trigger PBC, the variable will be set to false
- */
- netdev_dbg(padapter->pnetdev, "CheckPbcGPIO - PBC is pressed !!!!\n");
- /* 0 is the default value and it means the application monitors
- * the HW PBC doesn't provide its pid to driver.
- */
- if (padapter->pid == 0)
- return;
- kill_pid(find_vpid(padapter->pid), SIGUSR1, 1);
- }
-}
-
-/* query rx phy status from fw.
- * Adhoc mode: beacon.
- * Infrastructure mode: beacon , data.
- */
-static void query_fw_rx_phy_status(struct _adapter *padapter)
-{
- u32 val32 = 0;
- int pollingcnts = 50;
-
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
- r8712_write32(padapter, IOCMD_CTRL_REG, 0xf4000001);
- msleep(100);
- /* Wait FW complete IO Cmd */
- while ((r8712_read32(padapter, IOCMD_CTRL_REG)) &&
- (pollingcnts > 0)) {
- pollingcnts--;
- msleep(20);
- }
- if (pollingcnts != 0)
- val32 = r8712_read32(padapter, IOCMD_DATA_REG);
- else /* time out */
- val32 = 0;
- val32 >>= 4;
- padapter->recvpriv.fw_rssi =
- (u8)r8712_signal_scale_mapping(val32);
- }
-}
-
-/* check mlme, hw, phy, or dynamic algorithm status. */
-static void StatusWatchdogCallback(struct _adapter *padapter)
-{
- check_hw_pbc(padapter);
- query_fw_rx_phy_status(padapter);
-}
-
-static void r871x_internal_cmd_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- struct drvint_cmd_parm *pdrvcmd;
-
- if (!pbuf)
- return;
- pdrvcmd = (struct drvint_cmd_parm *)pbuf;
- switch (pdrvcmd->i_cid) {
- case WDG_WK_CID:
- StatusWatchdogCallback(padapter);
- break;
- default:
- break;
- }
- kfree(pdrvcmd->pbuf);
-}
-
-static u8 read_bbreg_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
-
- r8712_free_cmd_obj(pcmd);
- return H2C_SUCCESS;
-}
-
-static u8 write_bbreg_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd);
- struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
-
- pcmd_callback = cmd_callback[pcmd->cmdcode].callback;
- if (!pcmd_callback)
- r8712_free_cmd_obj(pcmd);
- else
- pcmd_callback(padapter, pcmd);
- return H2C_SUCCESS;
-}
-
-static u8 read_rfreg_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- u32 val;
- void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd);
- struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
-
- if (pcmd->rsp && pcmd->rspsz > 0)
- memcpy(pcmd->rsp, (u8 *)&val, pcmd->rspsz);
- pcmd_callback = cmd_callback[pcmd->cmdcode].callback;
- if (!pcmd_callback)
- r8712_free_cmd_obj(pcmd);
- else
- pcmd_callback(padapter, pcmd);
- return H2C_SUCCESS;
-}
-
-static u8 write_rfreg_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd);
- struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
-
- pcmd_callback = cmd_callback[pcmd->cmdcode].callback;
- if (!pcmd_callback)
- r8712_free_cmd_obj(pcmd);
- else
- pcmd_callback(padapter, pcmd);
- return H2C_SUCCESS;
-}
-
-static u8 sys_suspend_hdl(struct _adapter *padapter, u8 *pbuf)
-{
- struct cmd_obj *pcmd = (struct cmd_obj *)pbuf;
-
- r8712_free_cmd_obj(pcmd);
- return H2C_SUCCESS;
-}
-
-static struct cmd_obj *cmd_hdl_filter(struct _adapter *padapter,
- struct cmd_obj *pcmd)
-{
- struct cmd_obj *pcmd_r;
-
- if (!pcmd)
- return pcmd;
- pcmd_r = NULL;
-
- switch (pcmd->cmdcode) {
- case GEN_CMD_CODE(_Read_BBREG):
- read_bbreg_hdl(padapter, (u8 *)pcmd);
- break;
- case GEN_CMD_CODE(_Write_BBREG):
- write_bbreg_hdl(padapter, (u8 *)pcmd);
- break;
- case GEN_CMD_CODE(_Read_RFREG):
- read_rfreg_hdl(padapter, (u8 *)pcmd);
- break;
- case GEN_CMD_CODE(_Write_RFREG):
- write_rfreg_hdl(padapter, (u8 *)pcmd);
- break;
- case GEN_CMD_CODE(_SetUsbSuspend):
- sys_suspend_hdl(padapter, (u8 *)pcmd);
- break;
- case GEN_CMD_CODE(_JoinBss):
- r8712_joinbss_reset(padapter);
- /* Before set JoinBss_CMD to FW, driver must ensure FW is in
- * PS_MODE_ACTIVE. Directly write rpwm to radio on and assign
- * new pwr_mode to Driver, instead of use workitem to change
- * state.
- */
- if (padapter->pwrctrlpriv.pwr_mode > PS_MODE_ACTIVE) {
- padapter->pwrctrlpriv.pwr_mode = PS_MODE_ACTIVE;
- mutex_lock(&padapter->pwrctrlpriv.mutex_lock);
- r8712_set_rpwm(padapter, PS_STATE_S4);
- mutex_unlock(&padapter->pwrctrlpriv.mutex_lock);
- }
- pcmd_r = pcmd;
- break;
- case _DRV_INT_CMD_:
- r871x_internal_cmd_hdl(padapter, pcmd->parmbuf);
- r8712_free_cmd_obj(pcmd);
- pcmd_r = NULL;
- break;
- default:
- pcmd_r = pcmd;
- break;
- }
- return pcmd_r; /* if returning pcmd_r == NULL, pcmd must be free. */
-}
-
-u8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd)
-{
- int pollingcnts = 50;
-
- r8712_write32(pAdapter, IOCMD_CTRL_REG, cmd);
- msleep(100);
- while ((r8712_read32(pAdapter, IOCMD_CTRL_REG != 0)) &&
- (pollingcnts > 0)) {
- pollingcnts--;
- msleep(20);
- }
- if (pollingcnts == 0)
- return false;
- return true;
-}
-
-void r8712_fw_cmd_data(struct _adapter *pAdapter, u32 *value, u8 flag)
-{
- if (flag == 0) /* set */
- r8712_write32(pAdapter, IOCMD_DATA_REG, *value);
- else /* query */
- *value = r8712_read32(pAdapter, IOCMD_DATA_REG);
-}
-
-int r8712_cmd_thread(void *context)
-{
- struct cmd_obj *pcmd;
- unsigned int cmdsz, wr_sz;
- __le32 *pcmdbuf;
- struct tx_desc *pdesc;
- void (*pcmd_callback)(struct _adapter *dev, struct cmd_obj *pcmd);
- struct _adapter *padapter = context;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct completion *cmd_queue_comp =
- &pcmdpriv->cmd_queue_comp;
- struct mutex *pwctrl_lock = &padapter->pwrctrlpriv.mutex_lock;
-
- allow_signal(SIGTERM);
- while (1) {
- if (wait_for_completion_interruptible(cmd_queue_comp))
- break;
- if (padapter->driver_stopped || padapter->surprise_removed)
- break;
- if (r8712_register_cmd_alive(padapter))
- continue;
-_next:
- pcmd = r8712_dequeue_cmd(&pcmdpriv->cmd_queue);
- if (!(pcmd)) {
- r8712_unregister_cmd_alive(padapter);
- continue;
- }
- pcmdbuf = (__le32 *)pcmdpriv->cmd_buf;
- pdesc = (struct tx_desc *)pcmdbuf;
- memset(pdesc, 0, TXDESC_SIZE);
- pcmd = cmd_hdl_filter(padapter, pcmd);
- if (pcmd) { /* if pcmd != NULL, cmd will be handled by f/w */
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
- u8 blnPending = 0;
- u16 cmdcode = pcmd->cmdcode;
-
- pcmdpriv->cmd_issued_cnt++;
- cmdsz = round_up(pcmd->cmdsz, 8);
- wr_sz = TXDESC_SIZE + 8 + cmdsz;
- pdesc->txdw0 |= cpu_to_le32((wr_sz - TXDESC_SIZE) &
- 0x0000ffff);
- if (pdvobj->ishighspeed) {
- if ((wr_sz % 512) == 0)
- blnPending = 1;
- } else {
- if ((wr_sz % 64) == 0)
- blnPending = 1;
- }
- if (blnPending) { /* 32 bytes for TX Desc - 8 offset */
- pdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE +
- OFFSET_SZ + 8) << OFFSET_SHT) &
- 0x00ff0000);
- } else {
- pdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE +
- OFFSET_SZ) <<
- OFFSET_SHT) &
- 0x00ff0000);
- }
- pdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
- pdesc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) &
- 0x00001f00);
- pcmdbuf += (TXDESC_SIZE >> 2);
- *pcmdbuf = cpu_to_le32((cmdsz & 0x0000ffff) |
- (pcmd->cmdcode << 16) |
- (pcmdpriv->cmd_seq << 24));
- pcmdbuf += 2; /* 8 bytes alignment */
- memcpy((u8 *)pcmdbuf, pcmd->parmbuf, pcmd->cmdsz);
- if (blnPending)
- wr_sz += 8; /* Append 8 bytes */
- r8712_write_mem(padapter, RTL8712_DMA_H2CCMD, wr_sz,
- (u8 *)pdesc);
- pcmdpriv->cmd_seq++;
- if (cmdcode == GEN_CMD_CODE(_CreateBss)) {
- pcmd->res = H2C_SUCCESS;
- pcmd_callback = cmd_callback[cmdcode].callback;
- if (pcmd_callback)
- pcmd_callback(padapter, pcmd);
- continue;
- }
- if (cmdcode == GEN_CMD_CODE(_SetPwrMode)) {
- if (padapter->pwrctrlpriv.bSleep) {
- mutex_lock(pwctrl_lock);
- r8712_set_rpwm(padapter, PS_STATE_S2);
- mutex_unlock(pwctrl_lock);
- }
- }
- r8712_free_cmd_obj(pcmd);
- if (list_empty(&pcmdpriv->cmd_queue.queue)) {
- r8712_unregister_cmd_alive(padapter);
- continue;
- } else {
- goto _next;
- }
- } else {
- goto _next;
- }
- flush_signals_thread();
- }
- /* free all cmd_obj resources */
- do {
- pcmd = r8712_dequeue_cmd(&pcmdpriv->cmd_queue);
- if (!pcmd)
- break;
- r8712_free_cmd_obj(pcmd);
- } while (1);
- complete(&pcmdpriv->terminate_cmdthread_comp);
- return 0;
-}
-
-void r8712_event_handle(struct _adapter *padapter, __le32 *peventbuf)
-{
- u8 evt_code, evt_seq;
- u16 evt_sz;
- void (*event_callback)(struct _adapter *dev, u8 *pbuf);
- struct evt_priv *pevt_priv = &padapter->evtpriv;
-
- if (!peventbuf)
- goto _abort_event_;
- evt_sz = (u16)(le32_to_cpu(*peventbuf) & 0xffff);
- evt_seq = (u8)((le32_to_cpu(*peventbuf) >> 24) & 0x7f);
- evt_code = (u8)((le32_to_cpu(*peventbuf) >> 16) & 0xff);
- /* checking event sequence... */
- if ((evt_seq & 0x7f) != pevt_priv->event_seq) {
- pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
- goto _abort_event_;
- }
- /* checking if event code is valid */
- if (evt_code >= MAX_C2HEVT) {
- pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
- goto _abort_event_;
- } else if ((evt_code == GEN_EVT_CODE(_Survey)) &&
- (evt_sz > sizeof(struct wlan_bssid_ex))) {
- pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
- goto _abort_event_;
- }
- /* checking if event size match the event parm size */
- if ((wlanevents[evt_code].parmsize) &&
- (wlanevents[evt_code].parmsize != evt_sz)) {
- pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
- goto _abort_event_;
- } else if ((evt_sz == 0) && (evt_code != GEN_EVT_CODE(_WPS_PBC))) {
- pevt_priv->event_seq = ((evt_seq + 1) & 0x7f);
- goto _abort_event_;
- }
- pevt_priv->event_seq++; /* update evt_seq */
- if (pevt_priv->event_seq > 127)
- pevt_priv->event_seq = 0;
- /* move to event content, 8 bytes alignment */
- peventbuf = peventbuf + 2;
- event_callback = wlanevents[evt_code].event_callback;
- if (event_callback)
- event_callback(padapter, (u8 *)peventbuf);
- pevt_priv->evt_done_cnt++;
-_abort_event_:
- return;
-}
diff --git a/drivers/staging/rtl8712/rtl8712_cmd.h b/drivers/staging/rtl8712/rtl8712_cmd.h
deleted file mode 100644
index a34d0dd023f3..000000000000
--- a/drivers/staging/rtl8712/rtl8712_cmd.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_CMD_H_
-#define __RTL8712_CMD_H_
-
-#define CMD_HDR_SZ 8
-
-u8 r8712_fw_cmd(struct _adapter *pAdapter, u32 cmd);
-void r8712_fw_cmd_data(struct _adapter *pAdapter, u32 *value, u8 flag);
-
-struct cmd_hdr {
- u32 cmd_dw0;
- u32 cmd_dw1;
-};
-
-enum rtl8712_h2c_cmd {
- GEN_CMD_CODE(_Read_MACREG), /*0*/
- GEN_CMD_CODE(_Write_MACREG),
- GEN_CMD_CODE(_Read_BBREG),
- GEN_CMD_CODE(_Write_BBREG),
- GEN_CMD_CODE(_Read_RFREG),
- GEN_CMD_CODE(_Write_RFREG), /*5*/
- GEN_CMD_CODE(_Read_EEPROM),
- GEN_CMD_CODE(_Write_EEPROM),
- GEN_CMD_CODE(_Read_EFUSE),
- GEN_CMD_CODE(_Write_EFUSE),
-
- GEN_CMD_CODE(_Read_CAM), /*10*/
- GEN_CMD_CODE(_Write_CAM),
- GEN_CMD_CODE(_setBCNITV),
- GEN_CMD_CODE(_setMBIDCFG),
- GEN_CMD_CODE(_JoinBss), /*14*/
- GEN_CMD_CODE(_DisConnect), /*15*/
- GEN_CMD_CODE(_CreateBss),
- GEN_CMD_CODE(_SetOpMode),
- GEN_CMD_CODE(_SiteSurvey), /*18*/
- GEN_CMD_CODE(_SetAuth),
-
- GEN_CMD_CODE(_SetKey), /*20*/
- GEN_CMD_CODE(_SetStaKey),
- GEN_CMD_CODE(_SetAssocSta),
- GEN_CMD_CODE(_DelAssocSta),
- GEN_CMD_CODE(_SetStaPwrState),
- GEN_CMD_CODE(_SetBasicRate), /*25*/
- GEN_CMD_CODE(_GetBasicRate),
- GEN_CMD_CODE(_SetDataRate),
- GEN_CMD_CODE(_GetDataRate),
- GEN_CMD_CODE(_SetPhyInfo),
-
- GEN_CMD_CODE(_GetPhyInfo), /*30*/
- GEN_CMD_CODE(_SetPhy),
- GEN_CMD_CODE(_GetPhy),
- GEN_CMD_CODE(_readRssi),
- GEN_CMD_CODE(_readGain),
- GEN_CMD_CODE(_SetAtim), /*35*/
- GEN_CMD_CODE(_SetPwrMode),
- GEN_CMD_CODE(_JoinbssRpt),
- GEN_CMD_CODE(_SetRaTable),
- GEN_CMD_CODE(_GetRaTable),
-
- GEN_CMD_CODE(_GetCCXReport), /*40*/
- GEN_CMD_CODE(_GetDTMReport),
- GEN_CMD_CODE(_GetTXRateStatistics),
- GEN_CMD_CODE(_SetUsbSuspend),
- GEN_CMD_CODE(_SetH2cLbk),
- GEN_CMD_CODE(_AddBAReq), /*45*/
-
- GEN_CMD_CODE(_SetChannel), /*46*/
-/* MP_OFFLOAD Start (47~54)*/
- GEN_CMD_CODE(_SetTxPower),
- GEN_CMD_CODE(_SwitchAntenna),
- GEN_CMD_CODE(_SetCrystalCap),
- GEN_CMD_CODE(_SetSingleCarrierTx), /*50*/
- GEN_CMD_CODE(_SetSingleToneTx),
- GEN_CMD_CODE(_SetCarrierSuppressionTx),
- GEN_CMD_CODE(_SetContinuousTx),
- GEN_CMD_CODE(_SwitchBandwidth), /*54*/
-/* MP_OFFLOAD End*/
- GEN_CMD_CODE(_TX_Beacon), /*55*/
- GEN_CMD_CODE(_SetPowerTracking),
- GEN_CMD_CODE(_AMSDU_TO_AMPDU), /*57*/
- GEN_CMD_CODE(_SetMacAddress), /*58*/
-
- GEN_CMD_CODE(_DisconnectCtrl), /*59*/
- GEN_CMD_CODE(_SetChannelPlan), /*60*/
- GEN_CMD_CODE(_DisconnectCtrlEx), /*61*/
-
- /* To do, modify these h2c cmd, add or delete */
- GEN_CMD_CODE(_GetH2cLbk),
-
- /* WPS extra IE */
- GEN_CMD_CODE(_SetProbeReqExtraIE),
- GEN_CMD_CODE(_SetAssocReqExtraIE),
- GEN_CMD_CODE(_SetProbeRspExtraIE),
- GEN_CMD_CODE(_SetAssocRspExtraIE),
-
- /* the following is driver will do */
- GEN_CMD_CODE(_GetCurDataRate),
-
- GEN_CMD_CODE(_GetTxRetrycnt), /* to record times that Tx retry to
- * transmit packet after association
- */
- GEN_CMD_CODE(_GetRxRetrycnt), /* to record total number of the
- * received frame with ReTry bit set in
- * the WLAN header
- */
-
- GEN_CMD_CODE(_GetBCNOKcnt),
- GEN_CMD_CODE(_GetBCNERRcnt),
- GEN_CMD_CODE(_GetCurTxPwrLevel),
-
- GEN_CMD_CODE(_SetDIG),
- GEN_CMD_CODE(_SetRA),
- GEN_CMD_CODE(_SetPT),
- GEN_CMD_CODE(_ReadTSSI),
-
- MAX_H2CCMD
-};
-
-#define _GetBBReg_CMD_ _Read_BBREG_CMD_
-#define _SetBBReg_CMD_ _Write_BBREG_CMD_
-#define _GetRFReg_CMD_ _Read_RFREG_CMD_
-#define _SetRFReg_CMD_ _Write_RFREG_CMD_
-#define _DRV_INT_CMD_ (MAX_H2CCMD + 1)
-#define _SetRFIntFs_CMD_ (MAX_H2CCMD + 2)
-
-#ifdef _RTL8712_CMD_C_
-static struct _cmd_callback cmd_callback[] = {
- {GEN_CMD_CODE(_Read_MACREG), NULL}, /*0*/
- {GEN_CMD_CODE(_Write_MACREG), NULL},
- {GEN_CMD_CODE(_Read_BBREG), NULL},
- {GEN_CMD_CODE(_Write_BBREG), NULL},
- {GEN_CMD_CODE(_Read_RFREG), &r8712_getbbrfreg_cmdrsp_callback},
- {GEN_CMD_CODE(_Write_RFREG), NULL}, /*5*/
- {GEN_CMD_CODE(_Read_EEPROM), NULL},
- {GEN_CMD_CODE(_Write_EEPROM), NULL},
- {GEN_CMD_CODE(_Read_EFUSE), NULL},
- {GEN_CMD_CODE(_Write_EFUSE), NULL},
-
- {GEN_CMD_CODE(_Read_CAM), NULL}, /*10*/
- {GEN_CMD_CODE(_Write_CAM), NULL},
- {GEN_CMD_CODE(_setBCNITV), NULL},
- {GEN_CMD_CODE(_setMBIDCFG), NULL},
- {GEN_CMD_CODE(_JoinBss), &r8712_joinbss_cmd_callback}, /*14*/
- {GEN_CMD_CODE(_DisConnect), &r8712_disassoc_cmd_callback}, /*15*/
- {GEN_CMD_CODE(_CreateBss), &r8712_createbss_cmd_callback},
- {GEN_CMD_CODE(_SetOpMode), NULL},
- {GEN_CMD_CODE(_SiteSurvey), &r8712_survey_cmd_callback}, /*18*/
- {GEN_CMD_CODE(_SetAuth), NULL},
-
- {GEN_CMD_CODE(_SetKey), NULL}, /*20*/
- {GEN_CMD_CODE(_SetStaKey), &r8712_setstaKey_cmdrsp_callback},
- {GEN_CMD_CODE(_SetAssocSta), &r8712_setassocsta_cmdrsp_callback},
- {GEN_CMD_CODE(_DelAssocSta), NULL},
- {GEN_CMD_CODE(_SetStaPwrState), NULL},
- {GEN_CMD_CODE(_SetBasicRate), NULL}, /*25*/
- {GEN_CMD_CODE(_GetBasicRate), NULL},
- {GEN_CMD_CODE(_SetDataRate), NULL},
- {GEN_CMD_CODE(_GetDataRate), NULL},
- {GEN_CMD_CODE(_SetPhyInfo), NULL},
-
- {GEN_CMD_CODE(_GetPhyInfo), NULL}, /*30*/
- {GEN_CMD_CODE(_SetPhy), NULL},
- {GEN_CMD_CODE(_GetPhy), NULL},
- {GEN_CMD_CODE(_readRssi), NULL},
- {GEN_CMD_CODE(_readGain), NULL},
- {GEN_CMD_CODE(_SetAtim), NULL}, /*35*/
- {GEN_CMD_CODE(_SetPwrMode), NULL},
- {GEN_CMD_CODE(_JoinbssRpt), NULL},
- {GEN_CMD_CODE(_SetRaTable), NULL},
- {GEN_CMD_CODE(_GetRaTable), NULL},
-
- {GEN_CMD_CODE(_GetCCXReport), NULL}, /*40*/
- {GEN_CMD_CODE(_GetDTMReport), NULL},
- {GEN_CMD_CODE(_GetTXRateStatistics), NULL},
- {GEN_CMD_CODE(_SetUsbSuspend), NULL},
- {GEN_CMD_CODE(_SetH2cLbk), NULL},
- {GEN_CMD_CODE(_AddBAReq), NULL}, /*45*/
-
- {GEN_CMD_CODE(_SetChannel), NULL}, /*46*/
-/* MP_OFFLOAD Start (47~54)*/
- {GEN_CMD_CODE(_SetTxPower), NULL},
- {GEN_CMD_CODE(_SwitchAntenna), NULL},
- {GEN_CMD_CODE(_SetCrystalCap), NULL},
- {GEN_CMD_CODE(_SetSingleCarrierTx), NULL}, /*50*/
- {GEN_CMD_CODE(_SetSingleToneTx), NULL},
- {GEN_CMD_CODE(_SetCarrierSuppressionTx), NULL},
- {GEN_CMD_CODE(_SetContinuousTx), NULL},
- {GEN_CMD_CODE(_SwitchBandwidth), NULL}, /*54*/
-/* MP_OFFLOAD End*/
- {GEN_CMD_CODE(_TX_Beacon), NULL}, /*55*/
- {GEN_CMD_CODE(_SetPowerTracking), NULL},
- {GEN_CMD_CODE(_AMSDU_TO_AMPDU), NULL}, /*57*/
- {GEN_CMD_CODE(_SetMacAddress), NULL}, /*58*/
-
- {GEN_CMD_CODE(_DisconnectCtrl), NULL}, /*59*/
- {GEN_CMD_CODE(_SetChannelPlan), NULL}, /*60*/
- {GEN_CMD_CODE(_DisconnectCtrlEx), NULL}, /*61*/
-
- /* To do, modify these h2c cmd, add or delete */
- {GEN_CMD_CODE(_GetH2cLbk), NULL},
-
- {_SetProbeReqExtraIE_CMD_, NULL},
- {_SetAssocReqExtraIE_CMD_, NULL},
- {_SetProbeRspExtraIE_CMD_, NULL},
- {_SetAssocRspExtraIE_CMD_, NULL},
- {_GetCurDataRate_CMD_, NULL},
- {_GetTxRetrycnt_CMD_, NULL},
- {_GetRxRetrycnt_CMD_, NULL},
- {_GetBCNOKcnt_CMD_, NULL},
- {_GetBCNERRcnt_CMD_, NULL},
- {_GetCurTxPwrLevel_CMD_, NULL},
- {_SetDIG_CMD_, NULL},
- {_SetRA_CMD_, NULL},
- {_SetPT_CMD_, NULL},
- {GEN_CMD_CODE(_ReadTSSI), &r8712_readtssi_cmdrsp_callback}
-};
-#endif
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h
deleted file mode 100644
index 68bdec07f51e..000000000000
--- a/drivers/staging/rtl8712/rtl8712_cmdctrl_bitdef.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_CMDCTRL_BITDEF_H__
-#define __RTL8712_CMDCTRL_BITDEF_H__
-
-/*
- * 2. Command Control Registers (Offset: 0x0040 - 0x004F)
- */
-/*--------------------------------------------------------------------------*/
-/* 8192S (CMD) command register bits (Offset 0x40, 16 bits)*/
-/*--------------------------------------------------------------------------*/
-#define _APSDOFF_STATUS BIT(15)
-#define _APSDOFF BIT(14)
-#define _BBRSTn BIT(13) /*Enable OFDM/CCK*/
-#define _BB_GLB_RSTn BIT(12) /*Enable BB*/
-#define _SCHEDULE_EN BIT(10) /*Enable MAC scheduler*/
-#define _MACRXEN BIT(9)
-#define _MACTXEN BIT(8)
-#define _DDMA_EN BIT(7) /*FW off load function enable*/
-#define _FW2HW_EN BIT(6) /*MAC every module reset */
-#define _RXDMA_EN BIT(5)
-#define _TXDMA_EN BIT(4)
-#define _HCI_RXDMA_EN BIT(3)
-#define _HCI_TXDMA_EN BIT(2)
-
-/*TXPAUSE*/
-#define _STOPHCCA BIT(6)
-#define _STOPHIGH BIT(5)
-#define _STOPMGT BIT(4)
-#define _STOPVO BIT(3)
-#define _STOPVI BIT(2)
-#define _STOPBE BIT(1)
-#define _STOPBK BIT(0)
-
-/*TCR*/
-#define _DISCW BIT(20)
-#define _ICV BIT(19)
-#define _CFEND_FMT BIT(17)
-#define _CRC BIT(16)
-#define _FWRDY BIT(7)
-#define _BASECHG BIT(6)
-#define _IMEM_RDY BIT(5)
-#define _DMEM_CODE_DONE BIT(4)
-#define _EMEM_CHK_RPT BIT(3)
-#define _EMEM_CODE_DONE BIT(2)
-#define _IMEM_CHK_RPT BIT(1)
-#define _IMEM_CODE_DONE BIT(0)
-
-#define _TXDMA_INIT_VALUE (_IMEM_CHK_RPT | _EMEM_CHK_RPT)
-
-/*RCR*/
-#define _ENMBID BIT(27)
-#define _APP_PHYST_RXFF BIT(25)
-#define _APP_PHYST_STAFF BIT(24)
-#define _CBSSID BIT(23)
-#define _APWRMGT BIT(22)
-#define _ADD3 BIT(21)
-#define _AMF BIT(20)
-#define _ACF BIT(19)
-#define _ADF BIT(18)
-#define _APP_MIC BIT(17)
-#define _APP_ICV BIT(16)
-#define _RXFTH_MSK 0x0000E000
-#define _RXFTH_SHT 13
-#define _AICV BIT(12)
-#define _RXPKTLMT_MSK 0x00000FC0
-#define _RXPKTLMT_SHT 6
-#define _ACRC32 BIT(5)
-#define _AB BIT(3)
-#define _AM BIT(2)
-#define _APM BIT(1)
-#define _AAP BIT(0)
-
-/*MSR*/
-#define _NETTYPE_MSK 0x03
-#define _NETTYPE_SHT 0
-
-/*BT*/
-#define _BTMODE_MSK 0x06
-#define _BTMODE_SHT 1
-#define _ENBT BIT(0)
-
-/*MBIDCTRL*/
-#define _ENMBID_MODE BIT(15)
-#define _BCNNO_MSK 0x7000
-#define _BCNNO_SHT 12
-#define _BCNSPACE_MSK 0x0FFF
-#define _BCNSPACE_SHT 0
-
-#endif /* __RTL8712_CMDCTRL_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h
deleted file mode 100644
index fc67771c89b7..000000000000
--- a/drivers/staging/rtl8712/rtl8712_cmdctrl_regdef.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_CMDCTRL_REGDEF_H__
-#define __RTL8712_CMDCTRL_REGDEF_H__
-
-#define CR (RTL8712_CMDCTRL_ + 0x0000)
-#define TXPAUSE (RTL8712_CMDCTRL_ + 0x0002)
-#define TCR (RTL8712_CMDCTRL_ + 0x0004)
-#define RCR (RTL8712_CMDCTRL_ + 0x0008)
-#define MSR (RTL8712_CMDCTRL_ + 0x000C)
-#define SYSF_CFG (RTL8712_CMDCTRL_ + 0x000D)
-#define MBIDCTRL (RTL8712_CMDCTRL_ + 0x000E)
-
-#endif /* __RTL8712_CMDCTRL_REGDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h
deleted file mode 100644
index bb3863467f0d..000000000000
--- a/drivers/staging/rtl8712/rtl8712_debugctrl_bitdef.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_DEBUGCTRL_BITDEF_H__
-#define __RTL8712_DEBUGCTRL_BITDEF_H__
-
-/*BIST*/
-#define _BIST_RST BIT(0)
-
-/*LMS*/
-#define _LMS_MSK 0x03
-
-/*WDG_CTRL*/
-#define _OVSEL_MSK 0x0600
-#define _OVSEL_SHT 9
-#define _WDGCLR BIT(8)
-#define _WDGEN_MSK 0x00FF
-#define _WDGEN_SHT 0
-
-/*INTM*/
-#define _TXTIMER_MSK 0xF000
-#define _TXTIMER_SHT 12
-#define _TXNUM_MSK 0x0F00
-#define _TXNUM_SHT 8
-#define _RXTIMER_MSK 0x00F0
-#define _RXTIMER_SHT 4
-#define _RXNUM_MSK 0x000F
-#define _RXNUM_SHT 0
-
-/*FDLOCKTURN0*/
-/*FDLOCKTURN1*/
-#define _TURN1 BIT(0)
-
-/*FDLOCKFLAG0*/
-/*FDLOCKFLAG1*/
-#define _LOCKFLAG1_MSK 0x03
-
-#endif /* __RTL8712_DEBUGCTRL_BITDEF_H__ */
diff --git a/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h
deleted file mode 100644
index 319220e9d53d..000000000000
--- a/drivers/staging/rtl8712/rtl8712_debugctrl_regdef.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_DEBUGCTRL_REGDEF_H__
-#define __RTL8712_DEBUGCTRL_REGDEF_H__
-
-#define BIST (RTL8712_DEBUGCTRL_ + 0x00)
-#define DBS (RTL8712_DEBUGCTRL_ + 0x04)
-#define LMS (RTL8712_DEBUGCTRL_ + 0x05)
-#define CPUINST (RTL8712_DEBUGCTRL_ + 0x08)
-#define CPUCAUSE (RTL8712_DEBUGCTRL_ + 0x0C)
-#define LBUS_ERR_ADDR (RTL8712_DEBUGCTRL_ + 0x10)
-#define LBUS_ERR_CMD (RTL8712_DEBUGCTRL_ + 0x14)
-#define LBUS_ERR_DATA_L (RTL8712_DEBUGCTRL_ + 0x18)
-#define LBUS_ERR_DATA_H (RTL8712_DEBUGCTRL_ + 0x1C)
-#define LBUS_EXCEPTION_ADDR (RTL8712_DEBUGCTRL_ + 0x20)
-#define WDG_CTRL (RTL8712_DEBUGCTRL_ + 0x24)
-#define INTMTU (RTL8712_DEBUGCTRL_ + 0x28)
-#define INTM (RTL8712_DEBUGCTRL_ + 0x2A)
-#define FDLOCKTURN0 (RTL8712_DEBUGCTRL_ + 0x2C)
-#define FDLOCKTURN1 (RTL8712_DEBUGCTRL_ + 0x2D)
-#define FDLOCKFLAG0 (RTL8712_DEBUGCTRL_ + 0x2E)
-#define FDLOCKFLAG1 (RTL8712_DEBUGCTRL_ + 0x2F)
-#define TRXPKTBUF_DBG_DATA (RTL8712_DEBUGCTRL_ + 0x30)
-#define TRXPKTBUF_DBG_CTRL (RTL8712_DEBUGCTRL_ + 0x38)
-#define DPLL_MON (RTL8712_DEBUGCTRL_ + 0x3A)
-
-#endif /* __RTL8712_DEBUGCTRL_REGDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h b/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h
deleted file mode 100644
index 9048d6a65296..000000000000
--- a/drivers/staging/rtl8712/rtl8712_edcasetting_bitdef.h
+++ /dev/null
@@ -1,65 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_EDCASETTING_BITDEF_H__
-#define __RTL8712_EDCASETTING_BITDEF_H__
-
-/*EDCAPARAM*/
-#define _TXOPLIMIT_MSK 0xFFFF0000
-#define _TXOPLIMIT_SHT 16
-#define _ECWIN_MSK 0x0000FF00
-#define _ECWIN_SHT 8
-#define _AIFS_MSK 0x000000FF
-#define _AIFS_SHT 0
-
-/*BCNTCFG*/
-#define _BCNECW_MSK 0xFF00
-#define _BCNECW_SHT 8
-#define _BCNIFS_MSK 0x00FF
-#define _BCNIFS_SHT 0
-
-/*CWRR*/
-#define _CWRR_MSK 0x03FF
-
-/*ACMAVG*/
-#define _AVG_TIME_UP BIT(3)
-#define _AVGPERIOD_MSK 0x03
-
-/*ACMHWCTRL*/
-#define _VOQ_ACM_STATUS BIT(6)
-#define _VIQ_ACM_STATUS BIT(5)
-#define _BEQ_ACM_STATUS BIT(4)
-#define _VOQ_ACM_EN BIT(3)
-#define _VIQ_ACM_EN BIT(2)
-#define _BEQ_ACM_EN BIT(1)
-#define _ACMHWEN BIT(0)
-
-/*VO_ADMTIME*/
-#define _VO_ACM_RUT BIT(18)
-#define _VO_ADMTIME_MSK 0x0003FFF
-
-/*VI_ADMTIME*/
-#define _VI_ACM_RUT BIT(18)
-#define _VI_ADMTIME_MSK 0x0003FFF
-
-/*BE_ADMTIME*/
-#define _BE_ACM_RUT BIT(18)
-#define _BE_ADMTIME_MSK 0x0003FFF
-
-/*Retry limit reg*/
-#define _SRL_MSK 0xFF00
-#define _SRL_SHT 8
-#define _LRL_MSK 0x00FF
-#define _LRL_SHT 0
-
-#endif /* __RTL8712_EDCASETTING_BITDEF_H__*/
diff --git a/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h b/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h
deleted file mode 100644
index 02ec9f3bba66..000000000000
--- a/drivers/staging/rtl8712/rtl8712_edcasetting_regdef.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_EDCASETTING_REGDEF_H__
-#define __RTL8712_EDCASETTING_REGDEF_H__
-
-#define EDCA_VO_PARAM (RTL8712_EDCASETTING_ + 0x00)
-#define EDCA_VI_PARAM (RTL8712_EDCASETTING_ + 0x04)
-#define EDCA_BE_PARAM (RTL8712_EDCASETTING_ + 0x08)
-#define EDCA_BK_PARAM (RTL8712_EDCASETTING_ + 0x0C)
-#define BCNTCFG (RTL8712_EDCASETTING_ + 0x10)
-#define CWRR (RTL8712_EDCASETTING_ + 0x12)
-#define ACMAVG (RTL8712_EDCASETTING_ + 0x16)
-#define ACMHWCTRL (RTL8712_EDCASETTING_ + 0x17)
-#define VO_ADMTIME (RTL8712_EDCASETTING_ + 0x18)
-#define VI_ADMTIME (RTL8712_EDCASETTING_ + 0x1C)
-#define BE_ADMTIME (RTL8712_EDCASETTING_ + 0x20)
-#define RL (RTL8712_EDCASETTING_ + 0x24)
-
-#endif /* __RTL8712_EDCASETTING_REGDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_efuse.c b/drivers/staging/rtl8712/rtl8712_efuse.c
deleted file mode 100644
index a39d6c06648f..000000000000
--- a/drivers/staging/rtl8712/rtl8712_efuse.c
+++ /dev/null
@@ -1,563 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * rtl8712_efuse.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL8712_EFUSE_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "rtl8712_efuse.h"
-
-/* reserve 3 bytes for HW stop read */
-static int efuse_available_max_size = EFUSE_MAX_SIZE - 3 /*0x1FD*/;
-
-static void efuse_reg_ctrl(struct _adapter *adapter, u8 bPowerOn)
-{
- u8 tmpu8 = 0;
-
- if (bPowerOn) {
- /* -----------------e-fuse pwr & clk reg ctrl ---------------
- * Enable LDOE25 Macro Block
- */
- tmpu8 = r8712_read8(adapter, EFUSE_TEST + 3);
- tmpu8 |= 0x80;
- r8712_write8(adapter, EFUSE_TEST + 3, tmpu8);
- msleep(20); /* for some platform , need some delay time */
- /* Change Efuse Clock for write action to 40MHZ */
- r8712_write8(adapter, EFUSE_CLK_CTRL, 0x03);
- msleep(20); /* for some platform , need some delay time */
- } else {
- /* -----------------e-fuse pwr & clk reg ctrl -----------------
- * Disable LDOE25 Macro Block
- */
- tmpu8 = r8712_read8(adapter, EFUSE_TEST + 3);
- tmpu8 &= 0x7F;
- r8712_write8(adapter, EFUSE_TEST + 3, tmpu8);
- /* Change Efuse Clock for write action to 500K */
- r8712_write8(adapter, EFUSE_CLK_CTRL, 0x02);
- }
-}
-
-/*
- * Before write E-Fuse, this function must be called.
- */
-u8 r8712_efuse_reg_init(struct _adapter *adapter)
-{
- return true;
-}
-
-void r8712_efuse_reg_uninit(struct _adapter *adapter)
-{
- efuse_reg_ctrl(adapter, false);
-}
-
-static u8 efuse_one_byte_read(struct _adapter *adapter, u16 addr, u8 *data)
-{
- u8 tmpidx = 0, bResult;
-
- /* -----------------e-fuse reg ctrl --------------------------------- */
- r8712_write8(adapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */
- r8712_write8(adapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
- (r8712_read8(adapter, EFUSE_CTRL + 2) & 0xFC));
- r8712_write8(adapter, EFUSE_CTRL + 3, 0x72); /* read cmd */
- /* wait for complete */
- while (!(0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) &&
- (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100) {
- *data = r8712_read8(adapter, EFUSE_CTRL);
- bResult = true;
- } else {
- *data = 0xff;
- bResult = false;
- }
- return bResult;
-}
-
-static u8 efuse_one_byte_write(struct _adapter *adapter, u16 addr, u8 data)
-{
- u8 tmpidx = 0, bResult;
-
- /* -----------------e-fuse reg ctrl -------------------------------- */
- r8712_write8(adapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */
- r8712_write8(adapter, EFUSE_CTRL + 2, ((u8)((addr >> 8) & 0x03)) |
- (r8712_read8(adapter, EFUSE_CTRL + 2) & 0xFC));
- r8712_write8(adapter, EFUSE_CTRL, data); /* data */
- r8712_write8(adapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */
- /* wait for complete */
- while ((0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) &&
- (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100)
- bResult = true;
- else
- bResult = false;
- return bResult;
-}
-
-static u8 efuse_one_byte_rw(struct _adapter *adapter, u8 bRead, u16 addr,
- u8 *data)
-{
- u8 tmpidx = 0, tmpv8 = 0, bResult;
-
- /* -----------------e-fuse reg ctrl --------------------------------- */
- r8712_write8(adapter, EFUSE_CTRL + 1, (u8)(addr & 0xFF)); /* address */
- tmpv8 = ((u8)((addr >> 8) & 0x03)) |
- (r8712_read8(adapter, EFUSE_CTRL + 2) & 0xFC);
- r8712_write8(adapter, EFUSE_CTRL + 2, tmpv8);
- if (bRead) {
- r8712_write8(adapter, EFUSE_CTRL + 3, 0x72); /* read cmd */
- while (!(0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) &&
- (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100) {
- *data = r8712_read8(adapter, EFUSE_CTRL);
- bResult = true;
- } else {
- *data = 0;
- bResult = false;
- }
- } else {
- r8712_write8(adapter, EFUSE_CTRL, *data); /* data */
- r8712_write8(adapter, EFUSE_CTRL + 3, 0xF2); /* write cmd */
- while ((0x80 & r8712_read8(adapter, EFUSE_CTRL + 3)) &&
- (tmpidx < 100))
- tmpidx++;
- if (tmpidx < 100)
- bResult = true;
- else
- bResult = false;
- }
- return bResult;
-}
-
-static u8 efuse_is_empty(struct _adapter *adapter, u8 *empty)
-{
- u8 value, ret = true;
-
- /* read one byte to check if E-Fuse is empty */
- if (efuse_one_byte_rw(adapter, true, 0, &value)) {
- if (value == 0xFF)
- *empty = true;
- else
- *empty = false;
- } else {
- ret = false;
- }
- return ret;
-}
-
-void r8712_efuse_change_max_size(struct _adapter *adapter)
-{
- u16 pre_pg_data_saddr = 0x1FB;
- u16 i;
- u16 pre_pg_data_size = 5;
- u8 pre_pg_data[5];
-
- for (i = 0; i < pre_pg_data_size; i++)
- efuse_one_byte_read(adapter, pre_pg_data_saddr + i,
- &pre_pg_data[i]);
- if ((pre_pg_data[0] == 0x03) && (pre_pg_data[1] == 0x00) &&
- (pre_pg_data[2] == 0x00) && (pre_pg_data[3] == 0x00) &&
- (pre_pg_data[4] == 0x0C))
- efuse_available_max_size -= pre_pg_data_size;
-}
-
-int r8712_efuse_get_max_size(struct _adapter *adapter)
-{
- return efuse_available_max_size;
-}
-
-static u8 calculate_word_cnts(const u8 word_en)
-{
- u8 word_cnts = 0;
- u8 word_idx;
-
- for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++)
- if (!(word_en & BIT(word_idx)))
- word_cnts++; /* 0 : write enable */
- return word_cnts;
-}
-
-static void pgpacket_copy_data(const u8 word_en, const u8 *sourdata,
- u8 *targetdata)
-{
- u8 tmpindex = 0;
- u8 word_idx, byte_idx;
-
- for (word_idx = 0; word_idx < PGPKG_MAX_WORDS; word_idx++) {
- if (!(word_en & BIT(word_idx))) {
- byte_idx = word_idx * 2;
- targetdata[byte_idx] = sourdata[tmpindex++];
- targetdata[byte_idx + 1] = sourdata[tmpindex++];
- }
- }
-}
-
-u16 r8712_efuse_get_current_size(struct _adapter *adapter)
-{
- int bContinual = true;
- u16 efuse_addr = 0;
- u8 hworden = 0;
- u8 efuse_data, word_cnts = 0;
-
- while (bContinual && efuse_one_byte_read(adapter, efuse_addr, &efuse_data) &&
- (efuse_addr < efuse_available_max_size)) {
- if (efuse_data != 0xFF) {
- hworden = efuse_data & 0x0F;
- word_cnts = calculate_word_cnts(hworden);
- /* read next header */
- efuse_addr = efuse_addr + (word_cnts * 2) + 1;
- } else {
- bContinual = false;
- }
- }
- return efuse_addr;
-}
-
-u8 r8712_efuse_pg_packet_read(struct _adapter *adapter, u8 offset, u8 *data)
-{
- u8 hoffset = 0, hworden = 0, word_cnts = 0;
- u16 efuse_addr = 0;
- u8 efuse_data;
- u8 tmpidx = 0;
- u8 tmpdata[PGPKT_DATA_SIZE];
- u8 ret = true;
-
- if (!data)
- return false;
- if (offset > 0x0f)
- return false;
- memset(data, 0xFF, sizeof(u8) * PGPKT_DATA_SIZE);
- while (efuse_addr < efuse_available_max_size) {
- if (efuse_one_byte_read(adapter, efuse_addr, &efuse_data)) {
- if (efuse_data == 0xFF)
- break;
- hoffset = (efuse_data >> 4) & 0x0F;
- hworden = efuse_data & 0x0F;
- word_cnts = calculate_word_cnts(hworden);
- if (hoffset == offset) {
- memset(tmpdata, 0xFF, PGPKT_DATA_SIZE);
- for (tmpidx = 0; tmpidx < word_cnts * 2;
- tmpidx++) {
- if (efuse_one_byte_read(adapter, efuse_addr + 1 + tmpidx,
- &efuse_data)) {
- tmpdata[tmpidx] = efuse_data;
- } else {
- ret = false;
- }
- }
- pgpacket_copy_data(hworden, tmpdata, data);
- }
- efuse_addr += 1 + (word_cnts * 2);
- } else {
- ret = false;
- break;
- }
- }
- return ret;
-}
-
-static u8 fix_header(struct _adapter *adapter, u8 header, u16 header_addr)
-{
- struct PGPKT_STRUCT pkt;
- u8 offset, word_en, value;
- u16 addr;
- int i;
- u8 ret = true;
-
- pkt.offset = GET_EFUSE_OFFSET(header);
- pkt.word_en = GET_EFUSE_WORD_EN(header);
- addr = header_addr + 1 + calculate_word_cnts(pkt.word_en) * 2;
- if (addr > efuse_available_max_size)
- return false;
- /* retrieve original data */
- addr = 0;
- while (addr < header_addr) {
- if (!efuse_one_byte_read(adapter, addr++, &value)) {
- ret = false;
- break;
- }
- offset = GET_EFUSE_OFFSET(value);
- word_en = GET_EFUSE_WORD_EN(value);
- if (pkt.offset != offset) {
- addr += calculate_word_cnts(word_en) * 2;
- continue;
- }
- for (i = 0; i < PGPKG_MAX_WORDS; i++) {
- if (!(BIT(i) & word_en))
- continue;
- if (BIT(i) & pkt.word_en) {
- if (efuse_one_byte_read(adapter,
- addr,
- &value))
- pkt.data[i * 2] = value;
- else
- return false;
- if (efuse_one_byte_read(adapter,
- addr + 1,
- &value))
- pkt.data[i * 2 + 1] = value;
- else
- return false;
- }
- addr += 2;
- }
- }
- if (addr != header_addr)
- return false;
- addr++;
- /* fill original data */
- for (i = 0; i < PGPKG_MAX_WORDS; i++) {
- if (BIT(i) & pkt.word_en) {
- efuse_one_byte_write(adapter, addr, pkt.data[i * 2]);
- efuse_one_byte_write(adapter, addr + 1,
- pkt.data[i * 2 + 1]);
- /* additional check */
- if (!efuse_one_byte_read(adapter, addr, &value)) {
- ret = false;
- } else if (pkt.data[i * 2] != value) {
- ret = false;
- if (value == 0xFF) /* write again */
- efuse_one_byte_write(adapter, addr,
- pkt.data[i * 2]);
- }
- if (!efuse_one_byte_read(adapter, addr + 1, &value)) {
- ret = false;
- } else if (pkt.data[i * 2 + 1] != value) {
- ret = false;
- if (value == 0xFF) /* write again */
- efuse_one_byte_write(adapter, addr + 1,
- pkt.data[i * 2 +
- 1]);
- }
- }
- addr += 2;
- }
- return ret;
-}
-
-u8 r8712_efuse_pg_packet_write(struct _adapter *adapter, const u8 offset,
- const u8 word_en, const u8 *data)
-{
- u8 pg_header = 0;
- u16 efuse_addr = 0, curr_size = 0;
- u8 efuse_data, target_word_cnts = 0;
- int repeat_times;
- int sub_repeat;
- u8 bResult = true;
-
- /* check if E-Fuse Clock Enable and E-Fuse Clock is 40M */
- efuse_data = r8712_read8(adapter, EFUSE_CLK_CTRL);
- if (efuse_data != 0x03)
- return false;
- pg_header = MAKE_EFUSE_HEADER(offset, word_en);
- target_word_cnts = calculate_word_cnts(word_en);
- repeat_times = 0;
- efuse_addr = 0;
- while (efuse_addr < efuse_available_max_size) {
- curr_size = r8712_efuse_get_current_size(adapter);
- if ((curr_size + 1 + target_word_cnts * 2) >
- efuse_available_max_size)
- return false; /*target_word_cnts + pg header(1 byte)*/
- efuse_addr = curr_size; /* current size is also the last addr*/
- efuse_one_byte_write(adapter, efuse_addr, pg_header); /*hdr*/
- sub_repeat = 0;
- /* check if what we read is what we write */
- while (!efuse_one_byte_read(adapter, efuse_addr,
- &efuse_data)) {
- if (++sub_repeat > _REPEAT_THRESHOLD_) {
- bResult = false; /* continue to blind write */
- break; /* continue to blind write */
- }
- }
- if ((sub_repeat > _REPEAT_THRESHOLD_) ||
- (pg_header == efuse_data)) {
- /* write header ok OR can't check header(creep) */
- u8 i;
-
- /* go to next address */
- efuse_addr++;
- for (i = 0; i < target_word_cnts * 2; i++) {
- efuse_one_byte_write(adapter,
- efuse_addr + i,
- *(data + i));
- if (!efuse_one_byte_read(adapter,
- efuse_addr + i,
- &efuse_data))
- bResult = false;
- else if (*(data + i) != efuse_data) /* fail */
- bResult = false;
- }
- break;
- }
- /* write header fail */
- bResult = false;
- if (efuse_data == 0xFF)
- return bResult; /* nothing damaged. */
- /* call rescue procedure */
- if (!fix_header(adapter, efuse_data, efuse_addr))
- return false; /* rescue fail */
-
- if (++repeat_times > _REPEAT_THRESHOLD_) /* fail */
- break;
- /* otherwise, take another risk... */
- }
- return bResult;
-}
-
-u8 r8712_efuse_access(struct _adapter *adapter, u8 bRead, u16 start_addr,
- u16 cnts, u8 *data)
-{
- int i;
- u8 res = true;
-
- if (start_addr > EFUSE_MAX_SIZE)
- return false;
- if (!bRead && ((start_addr + cnts) >
- efuse_available_max_size))
- return false;
- if (!bRead && !r8712_efuse_reg_init(adapter))
- return false;
- /* -----------------e-fuse one byte read / write ---------------------*/
- for (i = 0; i < cnts; i++) {
- if ((start_addr + i) > EFUSE_MAX_SIZE) {
- res = false;
- break;
- }
- res = efuse_one_byte_rw(adapter, bRead, start_addr + i,
- data + i);
- if (!bRead && !res)
- break;
- }
- if (!bRead)
- r8712_efuse_reg_uninit(adapter);
- return res;
-}
-
-u8 r8712_efuse_map_read(struct _adapter *adapter, u16 addr, u16 cnts, u8 *data)
-{
- u8 offset, ret = true;
- u8 pktdata[PGPKT_DATA_SIZE];
- int i, idx;
-
- if ((addr + cnts) > EFUSE_MAP_MAX_SIZE)
- return false;
- if (efuse_is_empty(adapter, &offset) && offset) {
- for (i = 0; i < cnts; i++)
- data[i] = 0xFF;
- return ret;
- }
- offset = (addr >> 3) & 0xF;
- ret = r8712_efuse_pg_packet_read(adapter, offset, pktdata);
- i = addr & 0x7; /* pktdata index */
- idx = 0; /* data index */
-
- do {
- for (; i < PGPKT_DATA_SIZE; i++) {
- data[idx++] = pktdata[i];
- if (idx == cnts)
- return ret;
- }
- offset++;
- if (!r8712_efuse_pg_packet_read(adapter, offset, pktdata))
- ret = false;
- i = 0;
- } while (1);
- return ret;
-}
-
-u8 r8712_efuse_map_write(struct _adapter *adapter, u16 addr, u16 cnts,
- u8 *data)
-{
- u8 offset, word_en, empty;
- u8 pktdata[PGPKT_DATA_SIZE], newdata[PGPKT_DATA_SIZE];
- int i, j, idx;
-
- if ((addr + cnts) > EFUSE_MAP_MAX_SIZE)
- return false;
- /* check if E-Fuse Clock Enable and E-Fuse Clock is 40M */
- empty = r8712_read8(adapter, EFUSE_CLK_CTRL);
- if (empty != 0x03)
- return false;
- if (efuse_is_empty(adapter, &empty)) {
- if (empty)
- memset(pktdata, 0xFF, PGPKT_DATA_SIZE);
- } else {
- return false;
- }
- offset = (addr >> 3) & 0xF;
- if (!empty)
- if (!r8712_efuse_pg_packet_read(adapter, offset, pktdata))
- return false;
- word_en = 0xF;
- memset(newdata, 0xFF, PGPKT_DATA_SIZE);
- i = addr & 0x7; /* pktdata index */
- j = 0; /* newdata index */
- idx = 0; /* data index */
-
- if (i & 0x1) {
- /* odd start */
- if (data[idx] != pktdata[i]) {
- word_en &= ~BIT(i >> 1);
- newdata[j++] = pktdata[i - 1];
- newdata[j++] = data[idx];
- }
- i++;
- idx++;
- }
- do {
- for (; i < PGPKT_DATA_SIZE; i += 2) {
- if ((cnts - idx) == 1) {
- if (data[idx] != pktdata[i]) {
- word_en &= ~BIT(i >> 1);
- newdata[j++] = data[idx];
- newdata[j++] = pktdata[1 + 1];
- }
- idx++;
- break;
- }
-
- if ((data[idx] != pktdata[i]) || (data[idx + 1] !=
- pktdata[i + 1])) {
- word_en &= ~BIT(i >> 1);
- newdata[j++] = data[idx];
- newdata[j++] = data[idx + 1];
- }
- idx += 2;
-
- if (idx == cnts)
- break;
- }
-
- if (word_en != 0xF)
- if (!r8712_efuse_pg_packet_write(adapter, offset,
- word_en, newdata))
- return false;
- if (idx == cnts)
- break;
- offset++;
- if (!empty)
- if (!r8712_efuse_pg_packet_read(adapter, offset,
- pktdata))
- return false;
- i = 0;
- j = 0;
- word_en = 0xF;
- memset(newdata, 0xFF, PGPKT_DATA_SIZE);
- } while (1);
-
- return true;
-}
diff --git a/drivers/staging/rtl8712/rtl8712_efuse.h b/drivers/staging/rtl8712/rtl8712_efuse.h
deleted file mode 100644
index 7a49740212eb..000000000000
--- a/drivers/staging/rtl8712/rtl8712_efuse.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __RTL8712_EFUSE_H__
-#define __RTL8712_EFUSE_H__
-
-#include "osdep_service.h"
-
-#define _REPEAT_THRESHOLD_ 3
-
-#define EFUSE_MAX_SIZE 512
-#define EFUSE_MAP_MAX_SIZE 128
-
-#define PGPKG_MAX_WORDS 4
-#define PGPKT_DATA_SIZE 8 /* PGPKG_MAX_WORDS*2; BYTES sizeof(u8)*8*/
-#define MAX_PGPKT_SIZE 9 /* 1 + PGPKT_DATA_SIZE; header + 2 * 4 words (BYTES)*/
-
-#define GET_EFUSE_OFFSET(header) ((header & 0xF0) >> 4)
-#define GET_EFUSE_WORD_EN(header) (header & 0x0F)
-#define MAKE_EFUSE_HEADER(offset, word_en) ((((offset) & 0x0F) << 4) | \
- ((word_en) & 0x0F))
-/*--------------------------------------------------------------------------*/
-struct PGPKT_STRUCT {
- u8 offset;
- u8 word_en;
- u8 data[PGPKT_DATA_SIZE];
-};
-
-/*--------------------------------------------------------------------------*/
-u8 r8712_efuse_reg_init(struct _adapter *padapter);
-void r8712_efuse_reg_uninit(struct _adapter *padapter);
-u16 r8712_efuse_get_current_size(struct _adapter *padapter);
-int r8712_efuse_get_max_size(struct _adapter *padapter);
-void r8712_efuse_change_max_size(struct _adapter *padapter);
-u8 r8712_efuse_pg_packet_read(struct _adapter *padapter,
- u8 offset, u8 *data);
-u8 r8712_efuse_pg_packet_write(struct _adapter *padapter,
- const u8 offset, const u8 word_en,
- const u8 *data);
-u8 r8712_efuse_access(struct _adapter *padapter, u8 bRead,
- u16 start_addr, u16 cnts, u8 *data);
-u8 r8712_efuse_map_read(struct _adapter *padapter, u16 addr,
- u16 cnts, u8 *data);
-u8 r8712_efuse_map_write(struct _adapter *padapter, u16 addr,
- u16 cnts, u8 *data);
-#endif
diff --git a/drivers/staging/rtl8712/rtl8712_event.h b/drivers/staging/rtl8712/rtl8712_event.h
deleted file mode 100644
index 0d3e5feadcc0..000000000000
--- a/drivers/staging/rtl8712/rtl8712_event.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL8712_EVENT_H_
-#define _RTL8712_EVENT_H_
-
-void r8712_event_handle(struct _adapter *padapter, __le32 *peventbuf);
-void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf);
-
-enum rtl8712_c2h_event {
- GEN_EVT_CODE(_Read_MACREG) = 0, /*0*/
- GEN_EVT_CODE(_Read_BBREG),
- GEN_EVT_CODE(_Read_RFREG),
- GEN_EVT_CODE(_Read_EEPROM),
- GEN_EVT_CODE(_Read_EFUSE),
- GEN_EVT_CODE(_Read_CAM), /*5*/
- GEN_EVT_CODE(_Get_BasicRate),
- GEN_EVT_CODE(_Get_DataRate),
- GEN_EVT_CODE(_Survey), /*8*/
- GEN_EVT_CODE(_SurveyDone), /*9*/
-
- GEN_EVT_CODE(_JoinBss), /*10*/
- GEN_EVT_CODE(_AddSTA),
- GEN_EVT_CODE(_DelSTA),
- GEN_EVT_CODE(_AtimDone),
- GEN_EVT_CODE(_TX_Report),
- GEN_EVT_CODE(_CCX_Report), /*15*/
- GEN_EVT_CODE(_DTM_Report),
- GEN_EVT_CODE(_TX_Rate_Statistics),
- GEN_EVT_CODE(_C2HLBK),
- GEN_EVT_CODE(_FWDBG),
- GEN_EVT_CODE(_C2HFEEDBACK), /*20*/
- GEN_EVT_CODE(_ADDBA),
- GEN_EVT_CODE(_C2HBCN),
- GEN_EVT_CODE(_ReportPwrState), /*filen: only for PCIE, USB*/
- GEN_EVT_CODE(_WPS_PBC), /*24*/
- GEN_EVT_CODE(_ADDBAReq_Report), /*25*/
- MAX_C2HEVT
-};
-
-#ifdef _RTL8712_CMD_C_
-
-static struct fwevent wlanevents[] = {
- {0, NULL}, /*0*/
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, &r8712_survey_event_callback}, /*8*/
- {sizeof(struct surveydone_event),
- &r8712_surveydone_event_callback}, /*9*/
-
- {0, &r8712_joinbss_event_callback}, /*10*/
- {sizeof(struct stassoc_event), &r8712_stassoc_event_callback},
- {sizeof(struct stadel_event), &r8712_stadel_event_callback},
- {0, &r8712_atimdone_event_callback},
- {0, NULL},
- {0, NULL}, /*15*/
- {0, NULL},
- {0, NULL},
- {0, NULL},
- {0, NULL}, /*fwdbg_event_callback},*/
- {0, NULL}, /*20*/
- {0, NULL},
- {0, NULL},
- {0, &r8712_cpwm_event_callback},
- {0, &r8712_wpspbc_event_callback},
- {0, &r8712_got_addbareq_event_callback},
-};
-
-#endif/*_RTL8712_CMD_C_*/
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h
deleted file mode 100644
index f09645fa1886..000000000000
--- a/drivers/staging/rtl8712/rtl8712_fifoctrl_bitdef.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_FIFOCTRL_BITDEF_H__
-#define __RTL8712_FIFOCTRL_BITDEF_H__
-
-/*PBP*/
-#define _PSTX_MSK 0xF0
-#define _PSTX_SHT 4
-#define _PSRX_MSK 0x0F
-#define _PSRX_SHT 0
-
-/*TXFF_STATUS*/
-#define _TXSTATUS_OVF BIT(15)
-
-/*RXFF_STATUS*/
-#define _STATUSFF1_OVF BIT(7)
-#define _STATUSFF1_EMPTY BIT(6)
-#define _STATUSFF0_OVF BIT(5)
-#define _STATUSFF0_EMPTY BIT(4)
-#define _RXFF1_OVF BIT(3)
-#define _RXFF1_EMPTY BIT(2)
-#define _RXFF0_OVF BIT(1)
-#define _RXFF0_EMPTY BIT(0)
-
-/*TXFF_EMPTY_TH*/
-#define _BKQ_EMPTY_TH_MSK 0x0F0000
-#define _BKQ_EMPTY_TH_SHT 16
-#define _BEQ_EMPTY_TH_MSK 0x00F000
-#define _BEQ_EMPTY_TH_SHT 12
-#define _VIQ_EMPTY_TH_MSK 0x000F00
-#define _VIQ_EMPTY_TH_SHT 8
-#define _VOQ_EMPTY_TH_MSK 0x0000F0
-#define _VOQ_EMPTY_TH_SHT 4
-#define _BMCQ_EMPTY_TH_MSK 0x00000F
-#define _BMCQ_EMPTY_TH_SHT 0
-
-/*SDIO_RX_BLKSZ*/
-#define _SDIO_RX_BLKSZ_MSK 0x07
-
-/*RXDMA_CTRL*/
-#define _C2HFF_POLL BIT(4)
-#define _RXPKT_POLL BIT(0)
-
-/*RXPKT_NUM*/
-#define _RXCMD_NUM_MSK 0xFF00
-#define _RXCMD_NUM_SHT 8
-#define _RXFF0_NUM_MSK 0x00FF
-#define _RXFF0_NUM_SHT 0
-
-/*FIFOPAGE2*/
-#define _PUB_AVAL_PG_MSK 0xFFFF0000
-#define _PUB_AVAL_PG_SHT 16
-#define _BCN_AVAL_PG_MSK 0x0000FFFF
-#define _BCN_AVAL_PG_SHT 0
-
-/*RX0PKTNUM*/
-#define _RXFF0_DEC_POLL BIT(15)
-#define _RXFF0_PKT_DEC_NUM_MSK 0x3F00
-#define _RXFF0_PKT_DEC_NUM_SHT 8
-#define _RXFF0_PKTNUM_RPT_MSK 0x00FF
-#define _RXFF0_PKTNUM_RPT_SHT 0
-
-/*RX1PKTNUM*/
-#define _RXFF1_DEC_POLL BIT(15)
-#define _RXFF1_PKT_DEC_NUM_MSK 0x3F00
-#define _RXFF1_PKT_DEC_NUM_SHT 8
-#define _RXFF1_PKTNUM_RPT_MSK 0x00FF
-#define _RXFF1_PKTNUM_RPT_SHT 0
-
-/*RXFLTMAP0*/
-#define _MGTFLT13EN BIT(13)
-#define _MGTFLT12EN BIT(12)
-#define _MGTFLT11EN BIT(11)
-#define _MGTFLT10EN BIT(10)
-#define _MGTFLT9EN BIT(9)
-#define _MGTFLT8EN BIT(8)
-#define _MGTFLT5EN BIT(5)
-#define _MGTFLT4EN BIT(4)
-#define _MGTFLT3EN BIT(3)
-#define _MGTFLT2EN BIT(2)
-#define _MGTFLT1EN BIT(1)
-#define _MGTFLT0EN BIT(0)
-
-/*RXFLTMAP1*/
-#define _CTRLFLT15EN BIT(15)
-#define _CTRLFLT14EN BIT(14)
-#define _CTRLFLT13EN BIT(13)
-#define _CTRLFLT12EN BIT(12)
-#define _CTRLFLT11EN BIT(11)
-#define _CTRLFLT10EN BIT(10)
-#define _CTRLFLT9EN BIT(9)
-#define _CTRLFLT8EN BIT(8)
-#define _CTRLFLT7EN BIT(7)
-#define _CTRLFLT6EN BIT(6)
-
-/*RXFLTMAP2*/
-#define _DATAFLT15EN BIT(15)
-#define _DATAFLT14EN BIT(14)
-#define _DATAFLT13EN BIT(13)
-#define _DATAFLT12EN BIT(12)
-#define _DATAFLT11EN BIT(11)
-#define _DATAFLT10EN BIT(10)
-#define _DATAFLT9EN BIT(9)
-#define _DATAFLT8EN BIT(8)
-#define _DATAFLT7EN BIT(7)
-#define _DATAFLT6EN BIT(6)
-#define _DATAFLT5EN BIT(5)
-#define _DATAFLT4EN BIT(4)
-#define _DATAFLT3EN BIT(3)
-#define _DATAFLT2EN BIT(2)
-#define _DATAFLT1EN BIT(1)
-#define _DATAFLT0EN BIT(0)
-
-/*RXFLTMAP3*/
-#define _MESHAFLT1EN BIT(1)
-#define _MESHAFLT0EN BIT(0)
-
-/*TXPKT_NUM_CTRL*/
-#define _TXPKTNUM_DEC BIT(8)
-#define _TXPKTNUM_MSK 0x00FF
-#define _TXPKTNUM_SHT 0
-
-/*TXFF_PG_NUM*/
-#define _TXFF_PG_NUM_MSK 0x0FFF
-
-#endif /* __RTL8712_FIFOCTRL_BITDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h b/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h
deleted file mode 100644
index 189fdeb16d7d..000000000000
--- a/drivers/staging/rtl8712/rtl8712_fifoctrl_regdef.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_FIFOCTRL_REGDEF_H__
-#define __RTL8712_FIFOCTRL_REGDEF_H__
-
-#define RQPN (RTL8712_FIFOCTRL_ + 0x00)
-#define RXFF_BNDY (RTL8712_FIFOCTRL_ + 0x0C)
-#define RXRPT_BNDY (RTL8712_FIFOCTRL_ + 0x10)
-#define TXPKTBUF_PGBNDY (RTL8712_FIFOCTRL_ + 0x14)
-#define PBP (RTL8712_FIFOCTRL_ + 0x15)
-#define RX_DRVINFO_SZ (RTL8712_FIFOCTRL_ + 0x16)
-#define TXFF_STATUS (RTL8712_FIFOCTRL_ + 0x17)
-#define RXFF_STATUS (RTL8712_FIFOCTRL_ + 0x18)
-#define TXFF_EMPTY_TH (RTL8712_FIFOCTRL_ + 0x19)
-#define SDIO_RX_BLKSZ (RTL8712_FIFOCTRL_ + 0x1C)
-#define RXDMA_RXCTRL (RTL8712_FIFOCTRL_ + 0x1D)
-#define RXPKT_NUM (RTL8712_FIFOCTRL_ + 0x1E)
-#define RXPKT_NUM_C2H (RTL8712_FIFOCTRL_ + 0x1F)
-#define C2HCMD_UDT_SIZE (RTL8712_FIFOCTRL_ + 0x20)
-#define C2HCMD_UDT_ADDR (RTL8712_FIFOCTRL_ + 0x22)
-#define FIFOPAGE2 (RTL8712_FIFOCTRL_ + 0x24)
-#define FIFOPAGE1 (RTL8712_FIFOCTRL_ + 0x28)
-#define FW_RSVD_PG_CTRL (RTL8712_FIFOCTRL_ + 0x30)
-#define TXRPTFF_RDPTR (RTL8712_FIFOCTRL_ + 0x40)
-#define TXRPTFF_WTPTR (RTL8712_FIFOCTRL_ + 0x44)
-#define C2HFF_RDPTR (RTL8712_FIFOCTRL_ + 0x48)
-#define C2HFF_WTPTR (RTL8712_FIFOCTRL_ + 0x4C)
-#define RXFF0_RDPTR (RTL8712_FIFOCTRL_ + 0x50)
-#define RXFF0_WTPTR (RTL8712_FIFOCTRL_ + 0x54)
-#define RXFF1_RDPTR (RTL8712_FIFOCTRL_ + 0x58)
-#define RXFF1_WTPTR (RTL8712_FIFOCTRL_ + 0x5C)
-#define RXRPT0FF_RDPTR (RTL8712_FIFOCTRL_ + 0x60)
-#define RXRPT0FF_WTPTR (RTL8712_FIFOCTRL_ + 0x64)
-#define RXRPT1FF_RDPTR (RTL8712_FIFOCTRL_ + 0x68)
-#define RXRPT1FF_WTPTR (RTL8712_FIFOCTRL_ + 0x6C)
-#define RX0PKTNUM (RTL8712_FIFOCTRL_ + 0x72)
-#define RX1PKTNUM (RTL8712_FIFOCTRL_ + 0x74)
-#define RXFLTMAP0 (RTL8712_FIFOCTRL_ + 0x76)
-#define RXFLTMAP1 (RTL8712_FIFOCTRL_ + 0x78)
-#define RXFLTMAP2 (RTL8712_FIFOCTRL_ + 0x7A)
-#define RXFLTMAP3 (RTL8712_FIFOCTRL_ + 0x7c)
-#define TBDA (RTL8712_FIFOCTRL_ + 0x84)
-#define THPDA (RTL8712_FIFOCTRL_ + 0x88)
-#define TCDA (RTL8712_FIFOCTRL_ + 0x8C)
-#define TMDA (RTL8712_FIFOCTRL_ + 0x90)
-#define HDA (RTL8712_FIFOCTRL_ + 0x94)
-#define TVODA (RTL8712_FIFOCTRL_ + 0x98)
-#define TVIDA (RTL8712_FIFOCTRL_ + 0x9C)
-#define TBEDA (RTL8712_FIFOCTRL_ + 0xA0)
-#define TBKDA (RTL8712_FIFOCTRL_ + 0xA4)
-#define RCDA (RTL8712_FIFOCTRL_ + 0xA8)
-#define RDSA (RTL8712_FIFOCTRL_ + 0xAC)
-#define TXPKT_NUM_CTRL (RTL8712_FIFOCTRL_ + 0xB0)
-#define TXQ_PGADD (RTL8712_FIFOCTRL_ + 0xB3)
-#define TXFF_PG_NUM (RTL8712_FIFOCTRL_ + 0xB4)
-
-#endif /* __RTL8712_FIFOCTRL_REGDEF_H__ */
diff --git a/drivers/staging/rtl8712/rtl8712_gp_bitdef.h b/drivers/staging/rtl8712/rtl8712_gp_bitdef.h
deleted file mode 100644
index ee651fb3fde3..000000000000
--- a/drivers/staging/rtl8712/rtl8712_gp_bitdef.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_GP_BITDEF_H__
-#define __RTL8712_GP_BITDEF_H__
-
-/*GPIO_CTRL*/
-#define _GPIO_MOD_MSK 0xFF000000
-#define _GPIO_MOD_SHT 24
-#define _GPIO_IO_SEL_MSK 0x00FF0000
-#define _GPIO_IO_SEL_SHT 16
-#define _GPIO_OUT_MSK 0x0000FF00
-#define _GPIO_OUT_SHT 8
-#define _GPIO_IN_MSK 0x000000FF
-#define _GPIO_IN_SHT 0
-
-/*SYS_PINMUX_CFG*/
-#define _GPIOSEL_MSK 0x0003
-#define _GPIOSEL_SHT 0
-
-/*LED_CFG*/
-#define _LED1SV BIT(7)
-#define _LED1CM_MSK 0x0070
-#define _LED1CM_SHT 4
-#define _LED0SV BIT(3)
-#define _LED0CM_MSK 0x0007
-#define _LED0CM_SHT 0
-
-/*PHY_REG*/
-#define _HST_RDRDY_SHT 0
-#define _HST_RDRDY_MSK 0xFF
-#define _HST_RDRDY BIT(_HST_RDRDY_SHT)
-#define _CPU_WTBUSY_SHT 1
-#define _CPU_WTBUSY_MSK 0xFF
-#define _CPU_WTBUSY BIT(_CPU_WTBUSY_SHT)
-
-/* 11. General Purpose Registers (Offset: 0x02E0 - 0x02FF)*/
-
-/* 8192S GPIO Config Setting (offset 0x2F1, 1 byte)*/
-
-/*----------------------------------------------------------------------------*/
-
-#define GPIOMUX_EN BIT(3) /* When this bit is set to "1",
- * GPIO PINs will switch to MAC
- * GPIO Function
- */
-#define GPIOSEL_GPIO 0 /* UART or JTAG or pure GPIO*/
-#define GPIOSEL_PHYDBG 1 /* PHYDBG*/
-#define GPIOSEL_BT 2 /* BT_coex*/
-#define GPIOSEL_WLANDBG 3 /* WLANDBG*/
-#define GPIOSEL_GPIO_MASK (~(BIT(0) | BIT(1)))
-/* HW Radio OFF switch (GPIO BIT) */
-#define HAL_8192S_HW_GPIO_OFF_BIT BIT(3)
-#define HAL_8192S_HW_GPIO_OFF_MASK 0xF7
-#define HAL_8192S_HW_GPIO_WPS_BIT BIT(4)
-
-#endif /*__RTL8712_GP_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_gp_regdef.h b/drivers/staging/rtl8712/rtl8712_gp_regdef.h
deleted file mode 100644
index 892a7fb13923..000000000000
--- a/drivers/staging/rtl8712/rtl8712_gp_regdef.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_GP_REGDEF_H__
-#define __RTL8712_GP_REGDEF_H__
-
-#define PSTIMER (RTL8712_GP_ + 0x00)
-#define TIMER1 (RTL8712_GP_ + 0x04)
-#define TIMER2 (RTL8712_GP_ + 0x08)
-#define GPIO_CTRL (RTL8712_GP_ + 0x0C)
-#define GPIO_IO_SEL (RTL8712_GP_ + 0x0E)
-#define GPIO_INTCTRL (RTL8712_GP_ + 0x10)
-#define MAC_PINMUX_CTRL (RTL8712_GP_ + 0x11)
-#define LEDCFG (RTL8712_GP_ + 0x12)
-#define PHY_REG_RPT (RTL8712_GP_ + 0x13)
-#define PHY_REG_DATA (RTL8712_GP_ + 0x14)
-
-#endif /*__RTL8712_GP_REGDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_hal.h b/drivers/staging/rtl8712/rtl8712_hal.h
deleted file mode 100644
index 66cc4645e2d1..000000000000
--- a/drivers/staging/rtl8712/rtl8712_hal.h
+++ /dev/null
@@ -1,142 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_HAL_H__
-#define __RTL8712_HAL_H__
-
-enum _HW_VERSION {
- RTL8712_FPGA,
- RTL8712_1stCUT, /*A Cut (RTL8712_ASIC)*/
- RTL8712_2ndCUT, /*B Cut*/
- RTL8712_3rdCUT, /*C Cut*/
-};
-
-enum _LOOPBACK_TYPE {
- RTL8712_AIR_TRX = 0,
- RTL8712_MAC_LBK,
- RTL8712_BB_LBK,
- RTL8712_MAC_FW_LBK = 4,
- RTL8712_BB_FW_LBK = 8,
-};
-
-enum RTL871X_HCI_TYPE {
- RTL8712_SDIO,
- RTL8712_USB,
-};
-
-enum RTL8712_RF_CONFIG {
- RTL8712_RF_1T1R,
- RTL8712_RF_1T2R,
- RTL8712_RF_2T2R
-};
-
-enum _RTL8712_HCI_TYPE_ {
- RTL8712_HCI_TYPE_PCIE = 0x01,
- RTL8712_HCI_TYPE_AP_PCIE = 0x81,
- RTL8712_HCI_TYPE_USB = 0x02,
- RTL8712_HCI_TYPE_92USB = 0x02,
- RTL8712_HCI_TYPE_AP_USB = 0x82,
- RTL8712_HCI_TYPE_72USB = 0x12,
- RTL8712_HCI_TYPE_SDIO = 0x04,
- RTL8712_HCI_TYPE_72SDIO = 0x14
-};
-
-struct fw_priv { /*8-bytes alignment required*/
- /*--- long word 0 ----*/
- unsigned char signature_0; /*0x12: CE product, 0x92: IT product*/
- unsigned char signature_1; /*0x87: CE product, 0x81: IT product*/
- unsigned char hci_sel; /*0x81: PCI-AP, 01:PCIe, 02: 92S-U, 0x82: USB-AP,
- * 0x12: 72S-U, 03:SDIO
- */
- unsigned char chip_version; /*the same value as register value*/
- unsigned char customer_ID_0; /*customer ID low byte*/
- unsigned char customer_ID_1; /*customer ID high byte*/
- unsigned char rf_config; /*0x11: 1T1R, 0x12: 1T2R, 0x92: 1T2R turbo,
- * 0x22: 2T2R
- */
- unsigned char usb_ep_num; /* 4: 4EP, 6: 6EP, 11: 11EP*/
- /*--- long word 1 ----*/
- unsigned char regulatory_class_0; /*regulatory class bit map 0*/
- unsigned char regulatory_class_1; /*regulatory class bit map 1*/
- unsigned char regulatory_class_2; /*regulatory class bit map 2*/
- unsigned char regulatory_class_3; /*regulatory class bit map 3*/
- unsigned char rfintfs; /* 0:SWSI, 1:HWSI, 2:HWPI*/
- unsigned char def_nettype;
- unsigned char turbo_mode;
- unsigned char low_power_mode;/* 0: normal mode, 1: low power mode*/
- /*--- long word 2 ----*/
- unsigned char lbk_mode; /*0x00: normal, 0x03: MACLBK, 0x01: PHYLBK*/
- unsigned char mp_mode; /* 1: for MP use, 0: for normal driver */
- unsigned char vcs_type; /* 0:off 1:on 2:auto */
- unsigned char vcs_mode; /* 1:RTS/CTS 2:CTS to self */
- unsigned char rsvd022;
- unsigned char rsvd023;
- unsigned char rsvd024;
- unsigned char rsvd025;
- /*--- long word 3 ----*/
- unsigned char qos_en; /*1: QoS enable*/
- unsigned char bw_40MHz_en; /*1: 40MHz BW enable*/
- unsigned char AMSDU2AMPDU_en; /*1: 4181 convert AMSDU to AMPDU,
- * 0: disable
- */
- unsigned char AMPDU_en; /*1: 11n AMPDU enable*/
- unsigned char rate_control_offload; /*1: FW offloads,0: driver handles*/
- unsigned char aggregation_offload; /*1: FW offloads,0: driver handles*/
- unsigned char rsvd030;
- unsigned char rsvd031;
- /*--- long word 4 ----*/
- unsigned char beacon_offload; /* 1. FW offloads, 0: driver handles*/
- unsigned char MLME_offload; /* 2. FW offloads, 0: driver handles*/
- unsigned char hwpc_offload; /* 3. FW offloads, 0: driver handles*/
- unsigned char tcp_checksum_offload; /*4. FW offloads,0: driver handles*/
- unsigned char tcp_offload; /* 5. FW offloads, 0: driver handles*/
- unsigned char ps_control_offload; /* 6. FW offloads, 0: driver handles*/
- unsigned char WWLAN_offload; /* 7. FW offloads, 0: driver handles*/
- unsigned char rsvd040;
- /*--- long word 5 ----*/
- unsigned char tcp_tx_frame_len_L; /*tcp tx packet length low byte*/
- unsigned char tcp_tx_frame_len_H; /*tcp tx packet length high byte*/
- unsigned char tcp_rx_frame_len_L; /*tcp rx packet length low byte*/
- unsigned char tcp_rx_frame_len_H; /*tcp rx packet length high byte*/
- unsigned char rsvd050;
- unsigned char rsvd051;
- unsigned char rsvd052;
- unsigned char rsvd053;
-};
-
-struct fw_hdr {/*8-byte alignment required*/
- unsigned short signature;
- unsigned short version; /* 0x8000 ~ 0x8FFF for FPGA version,
- * 0x0000 ~ 0x7FFF for ASIC version,
- */
- unsigned int dmem_size; /*define the size of boot loader*/
- unsigned int img_IMEM_size; /*define the size of FW in IMEM*/
- unsigned int img_SRAM_size; /*define the size of FW in SRAM*/
- unsigned int fw_priv_sz; /*define the size of DMEM variable*/
- unsigned short efuse_addr;
- unsigned short h2ccnd_resp_addr;
- unsigned int SVNRevision;
- unsigned int release_time; /*Mon:Day:Hr:Min*/
- struct fw_priv fwpriv;
-};
-
-struct hal_priv {
- /*Endpoint handles*/
- struct net_device *pipehdls_r8712[10];
- u8 (*hal_bus_init)(struct _adapter *adapter);
-};
-
-uint rtl8712_hal_init(struct _adapter *padapter);
-int rtl871x_load_fw(struct _adapter *padapter);
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h b/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h
deleted file mode 100644
index e9732a1bcd7e..000000000000
--- a/drivers/staging/rtl8712/rtl8712_interrupt_bitdef.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_INTERRUPT_BITDEF_H__
-#define __RTL8712_INTERRUPT_BITDEF_H__
-
-/*HIMR*/
-/*HISR*/
-#define _CPUERR BIT(29)
-#define _ATIMEND BIT(28)
-#define _TXBCNOK BIT(27)
-#define _TXBCNERR BIT(26)
-#define _BCNDMAINT4 BIT(25)
-#define _BCNDMAINT3 BIT(24)
-#define _BCNDMAINT2 BIT(23)
-#define _BCNDMAINT1 BIT(22)
-#define _BCNDOK4 BIT(21)
-#define _BCNDOK3 BIT(20)
-#define _BCNDOK2 BIT(19)
-#define _BCNDOK1 BIT(18)
-#define _TIMEOUT2 BIT(17)
-#define _TIMEOUT1 BIT(16)
-#define _TXFOVW BIT(15)
-#define _PSTIMEOUT BIT(14)
-#define _BCNDMAINT0 BIT(13)
-#define _FOVW BIT(12)
-#define _RDU BIT(11)
-#define _RXCMDOK BIT(10)
-#define _BCNDOK0 BIT(9)
-#define _HIGHDOK BIT(8)
-#define _COMDOK BIT(7)
-#define _MGTDOK BIT(6)
-#define _HCCADOK BIT(5)
-#define _BKDOK BIT(4)
-#define _BEDOK BIT(3)
-#define _VIDOK BIT(2)
-#define _VODOK BIT(1)
-#define _RXOK BIT(0)
-
-#endif /*__RTL8712_INTERRUPT_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_io.c b/drivers/staging/rtl8712/rtl8712_io.c
deleted file mode 100644
index 384cbdb05e19..000000000000
--- a/drivers/staging/rtl8712/rtl8712_io.c
+++ /dev/null
@@ -1,99 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl8712_io.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>.
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL8712_IO_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "rtl871x_io.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-
-u8 r8712_read8(struct _adapter *adapter, u32 addr)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- return hdl->io_ops._read8(hdl, addr);
-}
-
-u16 r8712_read16(struct _adapter *adapter, u32 addr)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- return hdl->io_ops._read16(hdl, addr);
-}
-
-u32 r8712_read32(struct _adapter *adapter, u32 addr)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- return hdl->io_ops._read32(hdl, addr);
-}
-
-void r8712_write8(struct _adapter *adapter, u32 addr, u8 val)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- hdl->io_ops._write8(hdl, addr, val);
-}
-
-void r8712_write16(struct _adapter *adapter, u32 addr, u16 val)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- hdl->io_ops._write16(hdl, addr, val);
-}
-
-void r8712_write32(struct _adapter *adapter, u32 addr, u32 val)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- hdl->io_ops._write32(hdl, addr, val);
-}
-
-void r8712_read_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- if (adapter->driver_stopped || adapter->surprise_removed)
- return;
-
- hdl->io_ops._read_mem(hdl, addr, cnt, pmem);
-}
-
-void r8712_write_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- hdl->io_ops._write_mem(hdl, addr, cnt, pmem);
-}
-
-void r8712_read_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- if (adapter->driver_stopped || adapter->surprise_removed)
- return;
-
- hdl->io_ops._read_port(hdl, addr, cnt, pmem);
-}
-
-void r8712_write_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem)
-{
- struct intf_hdl *hdl = &adapter->pio_queue->intf;
-
- hdl->io_ops._write_port(hdl, addr, cnt, pmem);
-}
diff --git a/drivers/staging/rtl8712/rtl8712_led.c b/drivers/staging/rtl8712/rtl8712_led.c
deleted file mode 100644
index 6d9be5dec4e7..000000000000
--- a/drivers/staging/rtl8712/rtl8712_led.c
+++ /dev/null
@@ -1,1830 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl8712_led.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#include "drv_types.h"
-
-/*===========================================================================
- * Constant.
- *===========================================================================
-
- *
- * Default LED behavior.
- */
-#define LED_BLINK_NORMAL_INTERVAL 100
-#define LED_BLINK_SLOWLY_INTERVAL 200
-#define LED_BLINK_LONG_INTERVAL 400
-
-#define LED_BLINK_NO_LINK_INTERVAL_ALPHA 1000
-#define LED_BLINK_LINK_INTERVAL_ALPHA 500
-#define LED_BLINK_SCAN_INTERVAL_ALPHA 180
-#define LED_BLINK_FASTER_INTERVAL_ALPHA 50
-#define LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA 5000
-
-/*===========================================================================
- * LED object.
- *===========================================================================
- */
-enum _LED_STATE_871x {
- LED_UNKNOWN = 0,
- LED_STATE_ON = 1,
- LED_STATE_OFF = 2,
- LED_BLINK_NORMAL = 3,
- LED_BLINK_SLOWLY = 4,
- LED_POWER_ON_BLINK = 5,
- LED_SCAN_BLINK = 6, /* LED is blinking during scanning period,
- * the # of times to blink is depend on time
- * for scanning.
- */
- LED_NO_LINK_BLINK = 7, /* LED is blinking during no link state. */
- LED_BLINK_StartToBlink = 8,/* Customized for Sercomm Printer
- * Server case
- */
- LED_BLINK_WPS = 9, /* LED is blinkg during WPS communication */
- LED_TXRX_BLINK = 10,
- LED_BLINK_WPS_STOP = 11, /*for ALPHA */
- LED_BLINK_WPS_STOP_OVERLAP = 12, /*for BELKIN */
-};
-
-/*===========================================================================
- * Prototype of protected function.
- *===========================================================================
- */
-static void BlinkTimerCallback(struct timer_list *t);
-
-static void BlinkWorkItemCallback(struct work_struct *work);
-/*===========================================================================
- * LED_819xUsb routines.
- *===========================================================================
- *
- *
- *
- * Description:
- * Initialize an LED_871x object.
- */
-static void InitLed871x(struct _adapter *padapter, struct LED_871x *pLed,
- enum LED_PIN_871x LedPin)
-{
- pLed->padapter = padapter;
- pLed->LedPin = LedPin;
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->bLedOn = false;
- pLed->bLedBlinkInProgress = false;
- pLed->BlinkTimes = 0;
- pLed->BlinkingLedState = LED_UNKNOWN;
- timer_setup(&pLed->BlinkTimer, BlinkTimerCallback, 0);
- INIT_WORK(&pLed->BlinkWorkItem, BlinkWorkItemCallback);
-}
-
-/*
- * Description:
- * DeInitialize an LED_871x object.
- */
-static void DeInitLed871x(struct LED_871x *pLed)
-{
- del_timer_sync(&pLed->BlinkTimer);
- /* We should reset bLedBlinkInProgress if we cancel
- * the LedControlTimer,
- */
- pLed->bLedBlinkInProgress = false;
-}
-
-/*
- * Description:
- * Turn on LED according to LedPin specified.
- */
-static void SwLedOn(struct _adapter *padapter, struct LED_871x *pLed)
-{
- u8 LedCfg;
-
- if (padapter->surprise_removed || padapter->driver_stopped)
- return;
- LedCfg = r8712_read8(padapter, LEDCFG);
- switch (pLed->LedPin) {
- case LED_PIN_GPIO0:
- break;
- case LED_PIN_LED0:
- /* SW control led0 on.*/
- r8712_write8(padapter, LEDCFG, LedCfg & 0xf0);
- break;
- case LED_PIN_LED1:
- /* SW control led1 on.*/
- r8712_write8(padapter, LEDCFG, LedCfg & 0x0f);
- break;
- default:
- break;
- }
- pLed->bLedOn = true;
-}
-
-/*
- * Description:
- * Turn off LED according to LedPin specified.
- */
-static void SwLedOff(struct _adapter *padapter, struct LED_871x *pLed)
-{
- u8 LedCfg;
-
- if (padapter->surprise_removed || padapter->driver_stopped)
- return;
- LedCfg = r8712_read8(padapter, LEDCFG);
- switch (pLed->LedPin) {
- case LED_PIN_GPIO0:
- break;
- case LED_PIN_LED0:
- LedCfg &= 0xf0; /* Set to software control.*/
- r8712_write8(padapter, LEDCFG, (LedCfg | BIT(3)));
- break;
- case LED_PIN_LED1:
- LedCfg &= 0x0f; /* Set to software control.*/
- r8712_write8(padapter, LEDCFG, (LedCfg | BIT(7)));
- break;
- default:
- break;
- }
- pLed->bLedOn = false;
-}
-
-/*===========================================================================
- * Interface to manipulate LED objects.
- *===========================================================================
- *
- * Description:
- * Initialize all LED_871x objects.
- */
-void r8712_InitSwLeds(struct _adapter *padapter)
-{
- struct led_priv *pledpriv = &padapter->ledpriv;
-
- pledpriv->LedControlHandler = LedControl871x;
- InitLed871x(padapter, &pledpriv->SwLed0, LED_PIN_LED0);
- InitLed871x(padapter, &pledpriv->SwLed1, LED_PIN_LED1);
-}
-
-/* Description:
- * DeInitialize all LED_819xUsb objects.
- */
-void r8712_DeInitSwLeds(struct _adapter *padapter)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
-
- DeInitLed871x(&ledpriv->SwLed0);
- DeInitLed871x(&ledpriv->SwLed1);
-}
-
-/* Description:
- * Implementation of LED blinking behavior.
- * It toggle off LED and schedule corresponding timer if necessary.
- */
-static void SwLedBlink(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- /* Determine if we shall change LED state again. */
- pLed->BlinkTimes--;
- switch (pLed->CurrLedState) {
- case LED_BLINK_NORMAL:
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- break;
- case LED_BLINK_StartToBlink:
- if (check_fwstate(pmlmepriv, _FW_LINKED) &&
- (pmlmepriv->fw_state & WIFI_STATION_STATE))
- bStopBlinking = true;
- if (check_fwstate(pmlmepriv, _FW_LINKED) &&
- ((pmlmepriv->fw_state & WIFI_ADHOC_STATE) ||
- (pmlmepriv->fw_state & WIFI_ADHOC_MASTER_STATE)))
- bStopBlinking = true;
- else if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- break;
- case LED_BLINK_WPS:
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- break;
- default:
- bStopBlinking = true;
- break;
- }
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED) &&
- !pLed->bLedOn)
- SwLedOn(padapter, pLed);
- else if (check_fwstate(pmlmepriv, _FW_LINKED) && pLed->bLedOn)
- SwLedOff(padapter, pLed);
- pLed->BlinkTimes = 0;
- pLed->bLedBlinkInProgress = false;
- } else {
- /* Assign LED state to toggle. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
-
- /* Schedule a timer to toggle LED state. */
- switch (pLed->CurrLedState) {
- case LED_BLINK_NORMAL:
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- break;
- case LED_BLINK_SLOWLY:
- case LED_BLINK_StartToBlink:
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- break;
- case LED_BLINK_WPS:
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LONG_INTERVAL));
- break;
- default:
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- break;
- }
- }
-}
-
-static void SwLedBlink1(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
- struct LED_871x *pLed1 = &ledpriv->SwLed1;
- u8 bStopBlinking = false;
-
- if (peeprompriv->CustomerID == RT_CID_819x_CAMEO)
- pLed = &ledpriv->SwLed1;
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- if (peeprompriv->CustomerID == RT_CID_DEFAULT) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (!pLed1->bSWLedCtrl) {
- SwLedOn(padapter, pLed1);
- pLed1->bSWLedCtrl = true;
- } else if (!pLed1->bLedOn) {
- SwLedOn(padapter, pLed1);
- }
- } else {
- if (!pLed1->bSWLedCtrl) {
- SwLedOff(padapter, pLed1);
- pLed1->bSWLedCtrl = true;
- } else if (pLed1->bLedOn) {
- SwLedOff(padapter, pLed1);
- }
- }
- }
- switch (pLed->CurrLedState) {
- case LED_BLINK_SLOWLY:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_BLINK_NORMAL:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- break;
- case LED_SCAN_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- }
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- }
- pLed->BlinkTimes = 0;
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_BLINK_WPS:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- break;
- case LED_BLINK_WPS_STOP: /* WPS success */
- if (pLed->BlinkingLedState == LED_STATE_ON) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
- bStopBlinking = false;
- } else {
- bStopBlinking = true;
- }
- if (bStopBlinking) {
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- }
- pLed->bLedWPSBlinkInProgress = false;
- break;
- default:
- break;
- }
-}
-
-static void SwLedBlink2(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- switch (pLed->CurrLedState) {
- case LED_SCAN_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- SwLedOn(padapter, pLed);
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- SwLedOff(padapter, pLed);
- }
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- SwLedOn(padapter, pLed);
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- SwLedOff(padapter, pLed);
- }
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- default:
- break;
- }
-}
-
-static void SwLedBlink3(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- if (pLed->CurrLedState != LED_BLINK_WPS_STOP)
- SwLedOff(padapter, pLed);
- switch (pLed->CurrLedState) {
- case LED_SCAN_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (!pLed->bLedOn)
- SwLedOn(padapter, pLed);
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedOn)
- SwLedOff(padapter, pLed);
- }
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (!pLed->bLedOn)
- SwLedOn(padapter, pLed);
- } else if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedOn)
- SwLedOff(padapter, pLed);
- }
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_BLINK_WPS:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- break;
- case LED_BLINK_WPS_STOP: /*WPS success*/
- if (pLed->BlinkingLedState == LED_STATE_ON) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
- bStopBlinking = false;
- } else {
- bStopBlinking = true;
- }
- if (bStopBlinking) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- SwLedOn(padapter, pLed);
- pLed->bLedWPSBlinkInProgress = false;
- }
- break;
- default:
- break;
- }
-}
-
-static void SwLedBlink4(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct LED_871x *pLed1 = &ledpriv->SwLed1;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- if (!pLed1->bLedWPSBlinkInProgress &&
- pLed1->BlinkingLedState == LED_UNKNOWN) {
- pLed1->BlinkingLedState = LED_STATE_OFF;
- pLed1->CurrLedState = LED_STATE_OFF;
- SwLedOff(padapter, pLed1);
- }
- switch (pLed->CurrLedState) {
- case LED_BLINK_SLOWLY:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_BLINK_StartToBlink:
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- }
- break;
- case LED_SCAN_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_BLINK_WPS:
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- }
- break;
- case LED_BLINK_WPS_STOP: /*WPS authentication fail*/
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- break;
- case LED_BLINK_WPS_STOP_OVERLAP: /*WPS session overlap */
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0) {
- if (pLed->bLedOn)
- pLed->BlinkTimes = 1;
- else
- bStopBlinking = true;
- }
- if (bStopBlinking) {
- pLed->BlinkTimes = 10;
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- }
- break;
- default:
- break;
- }
-}
-
-static void SwLedBlink5(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- switch (pLed->CurrLedState) {
- case LED_SCAN_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (!pLed->bLedOn)
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- pLed->bLedScanBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (!pLed->bLedOn)
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- default:
- break;
- }
-}
-
-static void SwLedBlink6(struct LED_871x *pLed)
-{
- struct _adapter *padapter = pLed->padapter;
- u8 bStopBlinking = false;
-
- /* Change LED according to BlinkingLedState specified. */
- if (pLed->BlinkingLedState == LED_STATE_ON)
- SwLedOn(padapter, pLed);
- else
- SwLedOff(padapter, pLed);
- switch (pLed->CurrLedState) {
- case LED_TXRX_BLINK:
- pLed->BlinkTimes--;
- if (pLed->BlinkTimes == 0)
- bStopBlinking = true;
- if (bStopBlinking) {
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (!pLed->bLedOn)
- SwLedOn(padapter, pLed);
- pLed->bLedBlinkInProgress = false;
- } else {
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_BLINK_WPS:
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- break;
-
- default:
- break;
- }
-}
-
-/* Description:
- * Callback function of LED BlinkTimer,
- * it just schedules to corresponding BlinkWorkItem.
- */
-static void BlinkTimerCallback(struct timer_list *t)
-{
- struct LED_871x *pLed = from_timer(pLed, t, BlinkTimer);
-
- /* This fixed the crash problem on Fedora 12 when trying to do the
- * insmod;ifconfig up;rmmod commands.
- */
- if (pLed->padapter->surprise_removed || pLed->padapter->driver_stopped)
- return;
- schedule_work(&pLed->BlinkWorkItem);
-}
-
-/* Description:
- * Callback function of LED BlinkWorkItem.
- * We dispatch actual LED blink action according to LedStrategy.
- */
-static void BlinkWorkItemCallback(struct work_struct *work)
-{
- struct LED_871x *pLed = container_of(work, struct LED_871x,
- BlinkWorkItem);
- struct led_priv *ledpriv = &pLed->padapter->ledpriv;
-
- switch (ledpriv->LedStrategy) {
- case SW_LED_MODE0:
- SwLedBlink(pLed);
- break;
- case SW_LED_MODE1:
- SwLedBlink1(pLed);
- break;
- case SW_LED_MODE2:
- SwLedBlink2(pLed);
- break;
- case SW_LED_MODE3:
- SwLedBlink3(pLed);
- break;
- case SW_LED_MODE4:
- SwLedBlink4(pLed);
- break;
- case SW_LED_MODE5:
- SwLedBlink5(pLed);
- break;
- case SW_LED_MODE6:
- SwLedBlink6(pLed);
- break;
- default:
- SwLedBlink(pLed);
- break;
- }
-}
-
-/*============================================================================
- * Default LED behavior.
- *============================================================================
- *
- * Description:
- * Implement each led action for SW_LED_MODE0.
- * This is default strategy.
- */
-
-static void SwLedControlMode1(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct sitesurvey_ctrl *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
-
- if (padapter->eeprompriv.CustomerID == RT_CID_819x_CAMEO)
- pLed = &ledpriv->SwLed1;
- switch (LedAction) {
- case LED_CTL_START_TO_LINK:
- case LED_CTL_NO_LINK:
- if (!pLed->bLedNoLinkBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_LINK:
- if (!pLed->bLedLinkBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_NORMAL;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_LINK_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_SITE_SURVEY:
- if (psitesurveyctrl->traffic_busy &&
- check_fwstate(pmlmepriv, _FW_LINKED))
- ; /* dummy branch */
- else if (!pLed->bLedScanBlinkInProgress) {
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_SCAN_BLINK;
- pLed->BlinkTimes = 24;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
-
- case LED_CTL_START_WPS: /*wait until xinpin finish */
- case LED_CTL_START_WPS_BOTTON:
- if (!pLed->bLedWPSBlinkInProgress) {
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_STOP_WPS:
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress)
- del_timer(&pLed->BlinkTimer);
- else
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS_STOP;
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
- case LED_CTL_STOP_WPS_FAIL:
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- default:
- break;
- }
-}
-
-static void SwLedControlMode2(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
-
- switch (LedAction) {
- case LED_CTL_SITE_SURVEY:
- if (pmlmepriv->sitesurveyctrl.traffic_busy)
- ; /* dummy branch */
- else if (!pLed->bLedScanBlinkInProgress) {
- if (IS_LED_WPS_BLINKING(pLed))
- return;
-
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_SCAN_BLINK;
- pLed->BlinkTimes = 24;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
-
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
-
- case LED_CTL_LINK:
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
-
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
-
- case LED_CTL_START_WPS: /*wait until xinpin finish*/
- case LED_CTL_START_WPS_BOTTON:
- if (!pLed->bLedWPSBlinkInProgress) {
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
-
- case LED_CTL_STOP_WPS:
- pLed->bLedWPSBlinkInProgress = false;
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
-
- case LED_CTL_STOP_WPS_FAIL:
- pLed->bLedWPSBlinkInProgress = false;
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
-
- case LED_CTL_START_TO_LINK:
- case LED_CTL_NO_LINK:
- if (!IS_LED_BLINKING(pLed)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- default:
- break;
- }
-}
-
-static void SwLedControlMode3(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
-
- switch (LedAction) {
- case LED_CTL_SITE_SURVEY:
- if (pmlmepriv->sitesurveyctrl.traffic_busy)
- ; /* dummy branch */
- else if (!pLed->bLedScanBlinkInProgress) {
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_SCAN_BLINK;
- pLed->BlinkTimes = 24;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_LINK:
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- case LED_CTL_START_WPS: /* wait until xinpin finish */
- case LED_CTL_START_WPS_BOTTON:
- if (!pLed->bLedWPSBlinkInProgress) {
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_STOP_WPS:
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- } else {
- pLed->bLedWPSBlinkInProgress = true;
- }
- pLed->CurrLedState = LED_BLINK_WPS_STOP;
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_WPS_SUCCESS_INTERVAL_ALPHA));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
- case LED_CTL_STOP_WPS_FAIL:
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- case LED_CTL_START_TO_LINK:
- case LED_CTL_NO_LINK:
- if (!IS_LED_BLINKING(pLed)) {
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- default:
- break;
- }
-}
-
-static void SwLedControlMode4(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
- struct LED_871x *pLed1 = &ledpriv->SwLed1;
-
- switch (LedAction) {
- case LED_CTL_START_TO_LINK:
- if (pLed1->bLedWPSBlinkInProgress) {
- pLed1->bLedWPSBlinkInProgress = false;
- del_timer(&pLed1->BlinkTimer);
- pLed1->BlinkingLedState = LED_STATE_OFF;
- pLed1->CurrLedState = LED_STATE_OFF;
- if (pLed1->bLedOn)
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- if (!pLed->bLedStartToLinkBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- pLed->bLedStartToLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_StartToBlink;
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- }
- }
- break;
- case LED_CTL_LINK:
- case LED_CTL_NO_LINK:
- /*LED1 settings*/
- if (LedAction == LED_CTL_LINK) {
- if (pLed1->bLedWPSBlinkInProgress) {
- pLed1->bLedWPSBlinkInProgress = false;
- del_timer(&pLed1->BlinkTimer);
- pLed1->BlinkingLedState = LED_STATE_OFF;
- pLed1->CurrLedState = LED_STATE_OFF;
- if (pLed1->bLedOn)
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- }
- if (!pLed->bLedNoLinkBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_SITE_SURVEY:
- if (pmlmepriv->sitesurveyctrl.traffic_busy &&
- check_fwstate(pmlmepriv, _FW_LINKED))
- ;
- else if (!pLed->bLedScanBlinkInProgress) {
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_SCAN_BLINK;
- pLed->BlinkTimes = 24;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK ||
- IS_LED_WPS_BLINKING(pLed))
- return;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_START_WPS: /*wait until xinpin finish*/
- case LED_CTL_START_WPS_BOTTON:
- if (pLed1->bLedWPSBlinkInProgress) {
- pLed1->bLedWPSBlinkInProgress = false;
- del_timer(&pLed1->BlinkTimer);
- pLed1->BlinkingLedState = LED_STATE_OFF;
- pLed1->CurrLedState = LED_STATE_OFF;
- if (pLed1->bLedOn)
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- }
- if (!pLed->bLedWPSBlinkInProgress) {
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS;
- if (pLed->bLedOn) {
- pLed->BlinkingLedState = LED_STATE_OFF;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SLOWLY_INTERVAL));
- } else {
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- }
- }
- break;
- case LED_CTL_STOP_WPS: /*WPS connect success*/
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- break;
- case LED_CTL_STOP_WPS_FAIL: /*WPS authentication fail*/
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- /*LED1 settings*/
- if (pLed1->bLedWPSBlinkInProgress)
- del_timer(&pLed1->BlinkTimer);
- else
- pLed1->bLedWPSBlinkInProgress = true;
- pLed1->CurrLedState = LED_BLINK_WPS_STOP;
- if (pLed1->bLedOn)
- pLed1->BlinkingLedState = LED_STATE_OFF;
- else
- pLed1->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- break;
- case LED_CTL_STOP_WPS_FAIL_OVERLAP: /*WPS session overlap*/
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->bLedNoLinkBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_SLOWLY;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NO_LINK_INTERVAL_ALPHA));
- /*LED1 settings*/
- if (pLed1->bLedWPSBlinkInProgress)
- del_timer(&pLed1->BlinkTimer);
- else
- pLed1->bLedWPSBlinkInProgress = true;
- pLed1->CurrLedState = LED_BLINK_WPS_STOP_OVERLAP;
- pLed1->BlinkTimes = 10;
- if (pLed1->bLedOn)
- pLed1->BlinkingLedState = LED_STATE_OFF;
- else
- pLed1->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_NORMAL_INTERVAL));
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedNoLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedNoLinkBlinkInProgress = false;
- }
- if (pLed->bLedLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedLinkBlinkInProgress = false;
- }
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- if (pLed->bLedScanBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedScanBlinkInProgress = false;
- }
- if (pLed->bLedStartToLinkBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedStartToLinkBlinkInProgress = false;
- }
- if (pLed1->bLedWPSBlinkInProgress) {
- del_timer(&pLed1->BlinkTimer);
- pLed1->bLedWPSBlinkInProgress = false;
- }
- pLed1->BlinkingLedState = LED_UNKNOWN;
- SwLedOff(padapter, pLed);
- SwLedOff(padapter, pLed1);
- break;
- default:
- break;
- }
-}
-
-static void SwLedControlMode5(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
-
- if (padapter->eeprompriv.CustomerID == RT_CID_819x_CAMEO)
- pLed = &ledpriv->SwLed1;
-
- switch (LedAction) {
- case LED_CTL_POWER_ON:
- case LED_CTL_NO_LINK:
- case LED_CTL_LINK: /* solid blue */
- if (pLed->CurrLedState == LED_SCAN_BLINK)
- return;
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- pLed->bLedBlinkInProgress = false;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- case LED_CTL_SITE_SURVEY:
- if (pmlmepriv->sitesurveyctrl.traffic_busy &&
- check_fwstate(pmlmepriv, _FW_LINKED))
- ; /* dummy branch */
- else if (!pLed->bLedScanBlinkInProgress) {
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedScanBlinkInProgress = true;
- pLed->CurrLedState = LED_SCAN_BLINK;
- pLed->BlinkTimes = 24;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress) {
- if (pLed->CurrLedState == LED_SCAN_BLINK)
- return;
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- SwLedOff(padapter, pLed);
- break;
- default:
- break;
- }
-}
-
-static void SwLedControlMode6(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct LED_871x *pLed = &ledpriv->SwLed0;
-
- switch (LedAction) {
- case LED_CTL_POWER_ON:
- case LED_CTL_NO_LINK:
- case LED_CTL_LINK: /*solid blue*/
- case LED_CTL_SITE_SURVEY:
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- pLed->bLedBlinkInProgress = false;
- mod_timer(&pLed->BlinkTimer, jiffies + msecs_to_jiffies(0));
- break;
- case LED_CTL_TX:
- case LED_CTL_RX:
- if (!pLed->bLedBlinkInProgress &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (IS_LED_WPS_BLINKING(pLed))
- return;
- pLed->bLedBlinkInProgress = true;
- pLed->CurrLedState = LED_TXRX_BLINK;
- pLed->BlinkTimes = 2;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_FASTER_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_START_WPS: /*wait until xinpin finish*/
- case LED_CTL_START_WPS_BOTTON:
- if (!pLed->bLedWPSBlinkInProgress) {
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- pLed->bLedWPSBlinkInProgress = true;
- pLed->CurrLedState = LED_BLINK_WPS;
- if (pLed->bLedOn)
- pLed->BlinkingLedState = LED_STATE_OFF;
- else
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer, jiffies +
- msecs_to_jiffies(LED_BLINK_SCAN_INTERVAL_ALPHA));
- }
- break;
- case LED_CTL_STOP_WPS_FAIL:
- case LED_CTL_STOP_WPS:
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- pLed->CurrLedState = LED_STATE_ON;
- pLed->BlinkingLedState = LED_STATE_ON;
- mod_timer(&pLed->BlinkTimer,
- jiffies + msecs_to_jiffies(0));
- break;
- case LED_CTL_POWER_OFF:
- pLed->CurrLedState = LED_STATE_OFF;
- pLed->BlinkingLedState = LED_STATE_OFF;
- if (pLed->bLedBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedBlinkInProgress = false;
- }
- if (pLed->bLedWPSBlinkInProgress) {
- del_timer(&pLed->BlinkTimer);
- pLed->bLedWPSBlinkInProgress = false;
- }
- SwLedOff(padapter, pLed);
- break;
- default:
- break;
- }
-}
-
-/* Description:
- * Dispatch LED action according to pHalData->LedStrategy.
- */
-void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction)
-{
- struct led_priv *ledpriv = &padapter->ledpriv;
-
- if (!ledpriv->bRegUseLed)
- return;
- switch (ledpriv->LedStrategy) {
- case SW_LED_MODE0:
- break;
- case SW_LED_MODE1:
- SwLedControlMode1(padapter, LedAction);
- break;
- case SW_LED_MODE2:
- SwLedControlMode2(padapter, LedAction);
- break;
- case SW_LED_MODE3:
- SwLedControlMode3(padapter, LedAction);
- break;
- case SW_LED_MODE4:
- SwLedControlMode4(padapter, LedAction);
- break;
- case SW_LED_MODE5:
- SwLedControlMode5(padapter, LedAction);
- break;
- case SW_LED_MODE6:
- SwLedControlMode6(padapter, LedAction);
- break;
- default:
- break;
- }
-}
-
-void r8712_flush_led_works(struct _adapter *padapter)
-{
- struct led_priv *pledpriv = &padapter->ledpriv;
-
- flush_work(&pledpriv->SwLed0.BlinkWorkItem);
- flush_work(&pledpriv->SwLed1.BlinkWorkItem);
-}
diff --git a/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h b/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h
deleted file mode 100644
index 46d758d3f3a4..000000000000
--- a/drivers/staging/rtl8712/rtl8712_macsetting_bitdef.h
+++ /dev/null
@@ -1,31 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_MACSETTING_BITDEF_H__
-#define __RTL8712_MACSETTING_BITDEF_H__
-
-/*MACID*/
-/*BSSID*/
-
-/*HWVID*/
-#define _HWVID_MSK 0x0F
-
-/*MAR*/
-/*MBIDCANCONTENT*/
-
-/*MBIDCANCFG*/
-#define _POOLING BIT(31)
-#define _WRITE_EN BIT(16)
-#define _CAM_ADDR_MSK 0x001F
-#define _CAM_ADDR_SHT 0
-
-/*BUILDTIME*/
-#define _BUILDTIME_MSK 0x3FFFFFFF
-
-/*BUILDUSER*/
-
-#endif /* __RTL8712_MACSETTING_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h b/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h
deleted file mode 100644
index 64740d99c252..000000000000
--- a/drivers/staging/rtl8712/rtl8712_macsetting_regdef.h
+++ /dev/null
@@ -1,20 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_MACSETTING_REGDEF_H__
-#define __RTL8712_MACSETTING_REGDEF_H__
-
-#define MACID (RTL8712_MACIDSETTING_ + 0x0000)
-#define BSSIDR (RTL8712_MACIDSETTING_ + 0x0008)
-#define HWVID (RTL8712_MACIDSETTING_ + 0x000E)
-#define MAR (RTL8712_MACIDSETTING_ + 0x0010)
-#define MBIDCANCONTENT (RTL8712_MACIDSETTING_ + 0x0018)
-#define MBIDCANCFG (RTL8712_MACIDSETTING_ + 0x0020)
-#define BUILDTIME (RTL8712_MACIDSETTING_ + 0x0024)
-#define BUILDUSER (RTL8712_MACIDSETTING_ + 0x0028)
-
-#endif /*__RTL8712_MACSETTING_REGDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h b/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h
deleted file mode 100644
index 53e0d6b440f3..000000000000
--- a/drivers/staging/rtl8712/rtl8712_powersave_bitdef.h
+++ /dev/null
@@ -1,39 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_POWERSAVE_BITDEF_H__
-#define __RTL8712_POWERSAVE_BITDEF_H__
-
-/*WOWCTRL*/
-#define _UWF BIT(3)
-#define _MAGIC BIT(2)
-#define _WOW_EN BIT(1)
-#define _PMEN BIT(0)
-
-/*PSSTATUS*/
-#define _PSSTATUS_SEL_MSK 0x0F
-
-/*PSSWITCH*/
-#define _PSSWITCH_ACT BIT(7)
-#define _PSSWITCH_SEL_MSK 0x0F
-#define _PSSWITCH_SEL_SHT 0
-
-/*LPNAV_CTRL*/
-#define _LPNAV_EN BIT(31)
-#define _LPNAV_EARLY_MSK 0x7FFF0000
-#define _LPNAV_EARLY_SHT 16
-#define _LPNAV_TH_MSK 0x0000FFFF
-#define _LPNAV_TH_SHT 0
-
-/*RPWM*/
-/*CPWM*/
-#define _TOGGLING BIT(7)
-#define _WWLAN BIT(3)
-#define _RPS_ST BIT(2)
-#define _WLAN_TRX BIT(1)
-#define _SYS_CLK BIT(0)
-
-#endif /* __RTL8712_POWERSAVE_BITDEF_H__*/
diff --git a/drivers/staging/rtl8712/rtl8712_powersave_regdef.h b/drivers/staging/rtl8712/rtl8712_powersave_regdef.h
deleted file mode 100644
index 1bcfde4b1c11..000000000000
--- a/drivers/staging/rtl8712/rtl8712_powersave_regdef.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_POWERSAVE_REGDEF_H__
-#define __RTL8712_POWERSAVE_REGDEF_H__
-
-#define WOWCTRL (RTL8712_POWERSAVE_ + 0x00)
-#define PSSTATUS (RTL8712_POWERSAVE_ + 0x01)
-#define PSSWITCH (RTL8712_POWERSAVE_ + 0x02)
-#define MIMOPS_WAITPERIOD (RTL8712_POWERSAVE_ + 0x03)
-#define LPNAV_CTRL (RTL8712_POWERSAVE_ + 0x04)
-#define WFM0 (RTL8712_POWERSAVE_ + 0x10)
-#define WFM1 (RTL8712_POWERSAVE_ + 0x20)
-#define WFM2 (RTL8712_POWERSAVE_ + 0x30)
-#define WFM3 (RTL8712_POWERSAVE_ + 0x40)
-#define WFM4 (RTL8712_POWERSAVE_ + 0x50)
-#define WFM5 (RTL8712_POWERSAVE_ + 0x60)
-#define WFCRC (RTL8712_POWERSAVE_ + 0x70)
-#define RPWM (RTL8712_POWERSAVE_ + 0x7C)
-#define CPWM (RTL8712_POWERSAVE_ + 0x7D)
-
-#endif /* __RTL8712_POWERSAVE_REGDEF_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h
deleted file mode 100644
index 1de51c48f9c1..000000000000
--- a/drivers/staging/rtl8712/rtl8712_ratectrl_bitdef.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_RATECTRL_BITDEF_H__
-#define __RTL8712_RATECTRL_BITDEF_H__
-
-/*INIRTSMCS_SEL*/
-#define _INIRTSMCS_SEL_MSK 0x3F
-
-/* RRSR*/
-#define _RRSR_SHORT BIT(23)
-#define _RRSR_RSC_MSK 0x600000
-#define _RRSR_RSC_SHT 21
-#define _RRSR_BITMAP_MSK 0x0FFFFF
-#define _RRSR_BITMAP_SHT 0
-
-/* AGGLEN_LMT_H*/
-#define _AGGLMT_MCS32_MSK 0xF0
-#define _AGGLMT_MCS32_SHT 4
-#define _AGGLMT_MCS15_SGI_MSK 0x0F
-#define _AGGLMT_MCS15_SGI_SHT 0
-
-/* DARFRC*/
-/* RARFRC*/
-/* MCS_TXAGC*/
-/* CCK_TXAGC*/
-#define _CCK_MSK 0xFF00
-#define _CCK_SHT 8
-#define _BARKER_MSK 0x00FF
-#define _BARKER_SHT 0
-
-#endif /* __RTL8712_RATECTRL_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h b/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h
deleted file mode 100644
index 9ed5653f3f7f..000000000000
--- a/drivers/staging/rtl8712/rtl8712_ratectrl_regdef.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_RATECTRL_REGDEF_H__
-#define __RTL8712_RATECTRL_REGDEF_H__
-
-#define INIMCS_SEL (RTL8712_RATECTRL_ + 0x00)
-#define INIRTSMCS_SEL (RTL8712_RATECTRL_ + 0x20)
-#define RRSR (RTL8712_RATECTRL_ + 0x21)
-#define ARFR0 (RTL8712_RATECTRL_ + 0x24)
-#define ARFR1 (RTL8712_RATECTRL_ + 0x28)
-#define ARFR2 (RTL8712_RATECTRL_ + 0x2C)
-#define ARFR3 (RTL8712_RATECTRL_ + 0x30)
-#define ARFR4 (RTL8712_RATECTRL_ + 0x34)
-#define ARFR5 (RTL8712_RATECTRL_ + 0x38)
-#define ARFR6 (RTL8712_RATECTRL_ + 0x3C)
-#define ARFR7 (RTL8712_RATECTRL_ + 0x40)
-#define AGGLEN_LMT_H (RTL8712_RATECTRL_ + 0x47)
-#define AGGLEN_LMT_L (RTL8712_RATECTRL_ + 0x48)
-#define DARFRC (RTL8712_RATECTRL_ + 0x50)
-#define RARFRC (RTL8712_RATECTRL_ + 0x58)
-#define MCS_TXAGC0 (RTL8712_RATECTRL_ + 0x60)
-#define MCS_TXAGC1 (RTL8712_RATECTRL_ + 0x61)
-#define MCS_TXAGC2 (RTL8712_RATECTRL_ + 0x62)
-#define MCS_TXAGC3 (RTL8712_RATECTRL_ + 0x63)
-#define MCS_TXAGC4 (RTL8712_RATECTRL_ + 0x64)
-#define MCS_TXAGC5 (RTL8712_RATECTRL_ + 0x65)
-#define MCS_TXAGC6 (RTL8712_RATECTRL_ + 0x66)
-#define MCS_TXAGC7 (RTL8712_RATECTRL_ + 0x67)
-#define CCK_TXAGC (RTL8712_RATECTRL_ + 0x68)
-
-#endif /*__RTL8712_RATECTRL_REGDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_recv.c b/drivers/staging/rtl8712/rtl8712_recv.c
deleted file mode 100644
index ab344d676bb9..000000000000
--- a/drivers/staging/rtl8712/rtl8712_recv.c
+++ /dev/null
@@ -1,1075 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl8712_recv.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL8712_RECV_C_
-
-#include <linux/if_ether.h>
-#include <linux/ip.h>
-#include <net/cfg80211.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "mlme_osdep.h"
-#include "ethernet.h"
-#include "usb_ops.h"
-#include "wifi.h"
-
-static void recv_tasklet(struct tasklet_struct *t);
-
-int r8712_init_recv_priv(struct recv_priv *precvpriv,
- struct _adapter *padapter)
-{
- int i;
- struct recv_buf *precvbuf;
- addr_t tmpaddr = 0;
- int alignment = 0;
- struct sk_buff *pskb = NULL;
-
- /*init recv_buf*/
- _init_queue(&precvpriv->free_recv_buf_queue);
- precvpriv->pallocated_recv_buf =
- kzalloc(NR_RECVBUFF * sizeof(struct recv_buf) + 4, GFP_ATOMIC);
- if (!precvpriv->pallocated_recv_buf)
- return -ENOMEM;
- precvpriv->precv_buf = precvpriv->pallocated_recv_buf + 4 -
- ((addr_t)(precvpriv->pallocated_recv_buf) & 3);
- precvbuf = (struct recv_buf *)precvpriv->precv_buf;
- for (i = 0; i < NR_RECVBUFF; i++) {
- INIT_LIST_HEAD(&precvbuf->list);
- spin_lock_init(&precvbuf->recvbuf_lock);
- if (r8712_os_recvbuf_resource_alloc(padapter, precvbuf))
- break;
- precvbuf->ref_cnt = 0;
- precvbuf->adapter = padapter;
- list_add_tail(&precvbuf->list,
- &precvpriv->free_recv_buf_queue.queue);
- precvbuf++;
- }
- precvpriv->free_recv_buf_queue_cnt = NR_RECVBUFF;
- tasklet_setup(&precvpriv->recv_tasklet, recv_tasklet);
- skb_queue_head_init(&precvpriv->rx_skb_queue);
-
- skb_queue_head_init(&precvpriv->free_recv_skb_queue);
- for (i = 0; i < NR_PREALLOC_RECV_SKB; i++) {
- pskb = netdev_alloc_skb(padapter->pnetdev, MAX_RECVBUF_SZ +
- RECVBUFF_ALIGN_SZ);
- if (pskb) {
- tmpaddr = (addr_t)pskb->data;
- alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
- skb_reserve(pskb, (RECVBUFF_ALIGN_SZ - alignment));
- skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
- }
- pskb = NULL;
- }
- return 0;
-}
-
-void r8712_free_recv_priv(struct recv_priv *precvpriv)
-{
- int i;
- struct recv_buf *precvbuf;
- struct _adapter *padapter = precvpriv->adapter;
-
- precvbuf = (struct recv_buf *)precvpriv->precv_buf;
- for (i = 0; i < NR_RECVBUFF; i++) {
- r8712_os_recvbuf_resource_free(padapter, precvbuf);
- precvbuf++;
- }
- kfree(precvpriv->pallocated_recv_buf);
- skb_queue_purge(&precvpriv->rx_skb_queue);
- if (skb_queue_len(&precvpriv->rx_skb_queue))
- netdev_warn(padapter->pnetdev, "r8712u: rx_skb_queue not empty\n");
- skb_queue_purge(&precvpriv->free_recv_skb_queue);
- if (skb_queue_len(&precvpriv->free_recv_skb_queue))
- netdev_warn(padapter->pnetdev, "r8712u: free_recv_skb_queue not empty %d\n",
- skb_queue_len(&precvpriv->free_recv_skb_queue));
-}
-
-void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf)
-{
- precvbuf->transfer_len = 0;
- precvbuf->len = 0;
- precvbuf->ref_cnt = 0;
- if (precvbuf->pbuf) {
- precvbuf->pdata = precvbuf->pbuf;
- precvbuf->phead = precvbuf->pbuf;
- precvbuf->ptail = precvbuf->pbuf;
- precvbuf->pend = precvbuf->pdata + MAX_RECVBUF_SZ;
- }
-}
-
-void r8712_free_recvframe(union recv_frame *precvframe,
- struct __queue *pfree_recv_queue)
-{
- unsigned long irqL;
- struct _adapter *padapter = precvframe->u.hdr.adapter;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- if (precvframe->u.hdr.pkt) {
- dev_kfree_skb_any(precvframe->u.hdr.pkt);/*free skb by driver*/
- precvframe->u.hdr.pkt = NULL;
- }
- spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
- list_del_init(&precvframe->u.hdr.list);
- list_add_tail(&precvframe->u.hdr.list, &pfree_recv_queue->queue);
- if (padapter) {
- if (pfree_recv_queue == &precvpriv->free_recv_queue)
- precvpriv->free_recvframe_cnt++;
- }
- spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL);
-}
-
-static void update_recvframe_attrib_from_recvstat(struct rx_pkt_attrib *pattrib,
- struct recv_stat *prxstat)
-{
- /*TODO:
- * Offset 0
- */
- pattrib->bdecrypted = (le32_to_cpu(prxstat->rxdw0) & BIT(27)) == 0;
- pattrib->crc_err = (le32_to_cpu(prxstat->rxdw0) & BIT(14)) != 0;
- /*Offset 4*/
- /*Offset 8*/
- /*Offset 12*/
- if (le32_to_cpu(prxstat->rxdw3) & BIT(13)) {
- pattrib->tcpchk_valid = 1; /* valid */
- if (le32_to_cpu(prxstat->rxdw3) & BIT(11))
- pattrib->tcp_chkrpt = 1; /* correct */
- else
- pattrib->tcp_chkrpt = 0; /* incorrect */
- if (le32_to_cpu(prxstat->rxdw3) & BIT(12))
- pattrib->ip_chkrpt = 1; /* correct */
- else
- pattrib->ip_chkrpt = 0; /* incorrect */
- } else {
- pattrib->tcpchk_valid = 0; /* invalid */
- }
- pattrib->mcs_rate = (u8)((le32_to_cpu(prxstat->rxdw3)) & 0x3f);
- pattrib->htc = (u8)((le32_to_cpu(prxstat->rxdw3) >> 14) & 0x1);
- /*Offset 16*/
- /*Offset 20*/
- /*phy_info*/
-}
-
-/*perform defrag*/
-static union recv_frame *recvframe_defrag(struct _adapter *adapter,
- struct __queue *defrag_q)
-{
- struct list_head *plist, *phead;
- u8 wlanhdr_offset;
- u8 curfragnum;
- struct recv_frame_hdr *pfhdr, *pnfhdr;
- union recv_frame *prframe, *pnextrframe;
- struct __queue *pfree_recv_queue;
-
- pfree_recv_queue = &adapter->recvpriv.free_recv_queue;
- phead = &defrag_q->queue;
- plist = phead->next;
- prframe = container_of(plist, union recv_frame, u.list);
- list_del_init(&prframe->u.list);
- pfhdr = &prframe->u.hdr;
- curfragnum = 0;
- if (curfragnum != pfhdr->attrib.frag_num) {
- /*the first fragment number must be 0
- *free the whole queue
- */
- r8712_free_recvframe(prframe, pfree_recv_queue);
- r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
- return NULL;
- }
- curfragnum++;
- plist = &defrag_q->queue;
- plist = plist->next;
- while (!end_of_queue_search(phead, plist)) {
- pnextrframe = container_of(plist, union recv_frame, u.list);
- pnfhdr = &pnextrframe->u.hdr;
- /*check the fragment sequence (2nd ~n fragment frame) */
- if (curfragnum != pnfhdr->attrib.frag_num) {
- /* the fragment number must increase (after decache)
- * release the defrag_q & prframe
- */
- r8712_free_recvframe(prframe, pfree_recv_queue);
- r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
- return NULL;
- }
- curfragnum++;
- /* copy the 2nd~n fragment frame's payload to the first fragment
- * get the 2nd~last fragment frame's payload
- */
- wlanhdr_offset = pnfhdr->attrib.hdrlen + pnfhdr->attrib.iv_len;
- recvframe_pull(pnextrframe, wlanhdr_offset);
- /* append to first fragment frame's tail (if privacy frame,
- * pull the ICV)
- */
- recvframe_pull_tail(prframe, pfhdr->attrib.icv_len);
- memcpy(pfhdr->rx_tail, pnfhdr->rx_data, pnfhdr->len);
- recvframe_put(prframe, pnfhdr->len);
- pfhdr->attrib.icv_len = pnfhdr->attrib.icv_len;
- plist = plist->next;
- }
- /* free the defrag_q queue and return the prframe */
- r8712_free_recvframe_queue(defrag_q, pfree_recv_queue);
- return prframe;
-}
-
-/* check if need to defrag, if needed queue the frame to defrag_q */
-union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *padapter,
- union recv_frame *precv_frame)
-{
- u8 ismfrag;
- u8 fragnum;
- u8 *psta_addr;
- struct recv_frame_hdr *pfhdr;
- struct sta_info *psta;
- struct sta_priv *pstapriv;
- struct list_head *phead;
- union recv_frame *prtnframe = NULL;
- struct __queue *pfree_recv_queue, *pdefrag_q;
-
- pstapriv = &padapter->stapriv;
- pfhdr = &precv_frame->u.hdr;
- pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
- /* need to define struct of wlan header frame ctrl */
- ismfrag = pfhdr->attrib.mfrag;
- fragnum = pfhdr->attrib.frag_num;
- psta_addr = pfhdr->attrib.ta;
- psta = r8712_get_stainfo(pstapriv, psta_addr);
- if (!psta)
- pdefrag_q = NULL;
- else
- pdefrag_q = &psta->sta_recvpriv.defrag_q;
-
- if ((ismfrag == 0) && (fragnum == 0))
- prtnframe = precv_frame;/*isn't a fragment frame*/
- if (ismfrag == 1) {
- /* 0~(n-1) fragment frame
- * enqueue to defraf_g
- */
- if (pdefrag_q) {
- if (fragnum == 0) {
- /*the first fragment*/
- if (!list_empty(&pdefrag_q->queue)) {
- /*free current defrag_q */
- r8712_free_recvframe_queue(pdefrag_q, pfree_recv_queue);
- }
- }
- /* Then enqueue the 0~(n-1) fragment to the defrag_q */
- phead = &pdefrag_q->queue;
- list_add_tail(&pfhdr->list, phead);
- prtnframe = NULL;
- } else {
- /* can't find this ta's defrag_queue, so free this
- * recv_frame
- */
- r8712_free_recvframe(precv_frame, pfree_recv_queue);
- prtnframe = NULL;
- }
- }
- if ((ismfrag == 0) && (fragnum != 0)) {
- /* the last fragment frame
- * enqueue the last fragment
- */
- if (pdefrag_q) {
- phead = &pdefrag_q->queue;
- list_add_tail(&pfhdr->list, phead);
- /*call recvframe_defrag to defrag*/
- precv_frame = recvframe_defrag(padapter, pdefrag_q);
- prtnframe = precv_frame;
- } else {
- /* can't find this ta's defrag_queue, so free this
- * recv_frame
- */
- r8712_free_recvframe(precv_frame, pfree_recv_queue);
- prtnframe = NULL;
- }
- }
- if (prtnframe && (prtnframe->u.hdr.attrib.privacy)) {
- /* after defrag we must check tkip mic code */
- if (r8712_recvframe_chkmic(padapter, prtnframe) == _FAIL) {
- r8712_free_recvframe(prtnframe, pfree_recv_queue);
- prtnframe = NULL;
- }
- }
- return prtnframe;
-}
-
-static void amsdu_to_msdu(struct _adapter *padapter, union recv_frame *prframe)
-{
- int a_len, padding_len;
- u16 eth_type, nSubframe_Length;
- u8 nr_subframes, i;
- unsigned char *pdata;
- struct rx_pkt_attrib *pattrib;
- _pkt *sub_skb, *subframes[MAX_SUBFRAME_COUNT];
- struct recv_priv *precvpriv = &padapter->recvpriv;
- struct __queue *pfree_recv_queue = &precvpriv->free_recv_queue;
-
- nr_subframes = 0;
- pattrib = &prframe->u.hdr.attrib;
- recvframe_pull(prframe, prframe->u.hdr.attrib.hdrlen);
- if (prframe->u.hdr.attrib.iv_len > 0)
- recvframe_pull(prframe, prframe->u.hdr.attrib.iv_len);
- a_len = prframe->u.hdr.len;
- pdata = prframe->u.hdr.rx_data;
- while (a_len > ETH_HLEN) {
- /* Offset 12 denote 2 mac address */
- nSubframe_Length = *((u16 *)(pdata + 12));
- /*==m==>change the length order*/
- nSubframe_Length = (nSubframe_Length >> 8) +
- (nSubframe_Length << 8);
- if (a_len < (ETHERNET_HEADER_SIZE + nSubframe_Length)) {
- netdev_warn(padapter->pnetdev, "r8712u: nRemain_Length is %d and nSubframe_Length is: %d\n",
- a_len, nSubframe_Length);
- goto exit;
- }
- /* move the data point to data content */
- pdata += ETH_HLEN;
- a_len -= ETH_HLEN;
- /* Allocate new skb for releasing to upper layer */
- sub_skb = dev_alloc_skb(nSubframe_Length + 12);
- if (!sub_skb)
- break;
- skb_reserve(sub_skb, 12);
- skb_put_data(sub_skb, pdata, nSubframe_Length);
- subframes[nr_subframes++] = sub_skb;
- if (nr_subframes >= MAX_SUBFRAME_COUNT) {
- netdev_warn(padapter->pnetdev, "r8712u: ParseSubframe(): Too many Subframes! Packets dropped!\n");
- break;
- }
- pdata += nSubframe_Length;
- a_len -= nSubframe_Length;
- if (a_len != 0) {
- padding_len = 4 - ((nSubframe_Length + ETH_HLEN) & 3);
- if (padding_len == 4)
- padding_len = 0;
- if (a_len < padding_len)
- goto exit;
- pdata += padding_len;
- a_len -= padding_len;
- }
- }
- for (i = 0; i < nr_subframes; i++) {
- sub_skb = subframes[i];
- /* convert hdr + possible LLC headers into Ethernet header */
- eth_type = (sub_skb->data[6] << 8) | sub_skb->data[7];
- if (sub_skb->len >= 8 &&
- ((!memcmp(sub_skb->data, rfc1042_header, SNAP_SIZE) &&
- eth_type != ETH_P_AARP && eth_type != ETH_P_IPX) ||
- !memcmp(sub_skb->data, bridge_tunnel_header, SNAP_SIZE))) {
- /* remove RFC1042 or Bridge-Tunnel encapsulation and
- * replace EtherType
- */
- skb_pull(sub_skb, SNAP_SIZE);
- memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src,
- ETH_ALEN);
- memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst,
- ETH_ALEN);
- } else {
- __be16 len;
- /* Leave Ethernet header part of hdr and full payload */
- len = htons(sub_skb->len);
- memcpy(skb_push(sub_skb, 2), &len, 2);
- memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->src,
- ETH_ALEN);
- memcpy(skb_push(sub_skb, ETH_ALEN), pattrib->dst,
- ETH_ALEN);
- }
- /* Indicate the packets to upper layer */
- if (sub_skb) {
- sub_skb->protocol =
- eth_type_trans(sub_skb, padapter->pnetdev);
- sub_skb->dev = padapter->pnetdev;
- if ((pattrib->tcpchk_valid == 1) &&
- (pattrib->tcp_chkrpt == 1)) {
- sub_skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else {
- sub_skb->ip_summed = CHECKSUM_NONE;
- }
- netif_rx(sub_skb);
- }
- }
-exit:
- prframe->u.hdr.len = 0;
- r8712_free_recvframe(prframe, pfree_recv_queue);
-}
-
-void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf)
-{
- __le32 voffset;
- u8 *poffset;
- u16 cmd_len, drvinfo_sz;
- struct recv_stat *prxstat;
-
- poffset = prxcmdbuf;
- voffset = *(__le32 *)poffset;
- prxstat = prxcmdbuf;
- drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
- drvinfo_sz <<= 3;
- poffset += RXDESC_SIZE + drvinfo_sz;
- do {
- voffset = *(__le32 *)poffset;
- cmd_len = (u16)(le32_to_cpu(voffset) & 0xffff);
- r8712_event_handle(padapter, (__le32 *)poffset);
- poffset += (cmd_len + 8);/*8 bytes alignment*/
- } while (le32_to_cpu(voffset) & BIT(31));
-}
-
-static int check_indicate_seq(struct recv_reorder_ctrl *preorder_ctrl,
- u16 seq_num)
-{
- u8 wsize = preorder_ctrl->wsize_b;
- u16 wend = (preorder_ctrl->indicate_seq + wsize - 1) % 4096;
-
- /* Rx Reorder initialize condition.*/
- if (preorder_ctrl->indicate_seq == 0xffff)
- preorder_ctrl->indicate_seq = seq_num;
- /* Drop out the packet which SeqNum is smaller than WinStart */
- if (SN_LESS(seq_num, preorder_ctrl->indicate_seq))
- return false;
- /*
- * Sliding window manipulation. Conditions includes:
- * 1. Incoming SeqNum is equal to WinStart =>Window shift 1
- * 2. Incoming SeqNum is larger than the WinEnd => Window shift N
- */
- if (SN_EQUAL(seq_num, preorder_ctrl->indicate_seq))
- preorder_ctrl->indicate_seq = (preorder_ctrl->indicate_seq +
- 1) % 4096;
- else if (SN_LESS(wend, seq_num)) {
- if (seq_num >= (wsize - 1))
- preorder_ctrl->indicate_seq = seq_num + 1 - wsize;
- else
- preorder_ctrl->indicate_seq = 4095 - (wsize -
- (seq_num + 1)) + 1;
- }
- return true;
-}
-
-static int enqueue_reorder_recvframe(struct recv_reorder_ctrl *preorder_ctrl,
- union recv_frame *prframe)
-{
- struct list_head *phead, *plist;
- union recv_frame *pnextrframe;
- struct rx_pkt_attrib *pnextattrib;
- struct __queue *ppending_recvframe_queue =
- &preorder_ctrl->pending_recvframe_queue;
- struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
-
- phead = &ppending_recvframe_queue->queue;
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- pnextrframe = container_of(plist, union recv_frame, u.list);
- pnextattrib = &pnextrframe->u.hdr.attrib;
-
- if (SN_EQUAL(pnextattrib->seq_num, pattrib->seq_num))
- return false;
-
- if (SN_LESS(pnextattrib->seq_num, pattrib->seq_num))
- plist = plist->next;
- else
- break;
- }
- list_del_init(&prframe->u.hdr.list);
- list_add_tail(&prframe->u.hdr.list, plist);
- return true;
-}
-
-int r8712_recv_indicatepkts_in_order(struct _adapter *padapter,
- struct recv_reorder_ctrl *preorder_ctrl,
- int bforced)
-{
- struct list_head *phead, *plist;
- union recv_frame *prframe;
- struct rx_pkt_attrib *pattrib;
- int bPktInBuf = false;
- struct __queue *ppending_recvframe_queue =
- &preorder_ctrl->pending_recvframe_queue;
-
- phead = &ppending_recvframe_queue->queue;
- plist = phead->next;
- /* Handling some condition for forced indicate case.*/
- if (bforced) {
- if (list_empty(phead))
- return true;
-
- prframe = container_of(plist, union recv_frame, u.list);
- pattrib = &prframe->u.hdr.attrib;
- preorder_ctrl->indicate_seq = pattrib->seq_num;
- }
- /* Prepare indication list and indication.
- * Check if there is any packet need indicate.
- */
- while (!list_empty(phead)) {
- prframe = container_of(plist, union recv_frame, u.list);
- pattrib = &prframe->u.hdr.attrib;
- if (!SN_LESS(preorder_ctrl->indicate_seq, pattrib->seq_num)) {
- plist = plist->next;
- list_del_init(&prframe->u.hdr.list);
- if (SN_EQUAL(preorder_ctrl->indicate_seq,
- pattrib->seq_num))
- preorder_ctrl->indicate_seq =
- (preorder_ctrl->indicate_seq + 1) % 4096;
- /*indicate this recv_frame*/
- if (!pattrib->amsdu) {
- if (!padapter->driver_stopped &&
- !padapter->surprise_removed) {
- /* indicate this recv_frame */
- r8712_recv_indicatepkt(padapter,
- prframe);
- }
- } else if (pattrib->amsdu == 1) {
- amsdu_to_msdu(padapter, prframe);
- }
- /* Update local variables. */
- bPktInBuf = false;
- } else {
- bPktInBuf = true;
- break;
- }
- }
- return bPktInBuf;
-}
-
-static int recv_indicatepkt_reorder(struct _adapter *padapter,
- union recv_frame *prframe)
-{
- unsigned long irql;
- struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
- struct recv_reorder_ctrl *preorder_ctrl = prframe->u.hdr.preorder_ctrl;
- struct __queue *ppending_recvframe_queue =
- &preorder_ctrl->pending_recvframe_queue;
-
- if (!pattrib->amsdu) {
- /* s1. */
- r8712_wlanhdr_to_ethhdr(prframe);
- if (pattrib->qos != 1) {
- if (!padapter->driver_stopped &&
- !padapter->surprise_removed) {
- r8712_recv_indicatepkt(padapter, prframe);
- return 0;
- } else {
- return -EINVAL;
- }
- }
- }
- spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
- /*s2. check if winstart_b(indicate_seq) needs to be updated*/
- if (!check_indicate_seq(preorder_ctrl, pattrib->seq_num))
- goto _err_exit;
- /*s3. Insert all packet into Reorder Queue to maintain its ordering.*/
- if (!enqueue_reorder_recvframe(preorder_ctrl, prframe))
- goto _err_exit;
- /*s4.
- * Indication process.
- * After Packet dropping and Sliding Window shifting as above, we can
- * now just indicate the packets with the SeqNum smaller than latest
- * WinStart and buffer other packets.
- *
- * For Rx Reorder condition:
- * 1. All packets with SeqNum smaller than WinStart => Indicate
- * 2. All packets with SeqNum larger than or equal to
- * WinStart => Buffer it.
- */
- if (r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, false)) {
- mod_timer(&preorder_ctrl->reordering_ctrl_timer,
- jiffies + msecs_to_jiffies(REORDER_WAIT_TIME));
- spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
- } else {
- spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
- del_timer(&preorder_ctrl->reordering_ctrl_timer);
- }
- return 0;
-_err_exit:
- spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
- return -ENOMEM;
-}
-
-void r8712_reordering_ctrl_timeout_handler(void *pcontext)
-{
- unsigned long irql;
- struct recv_reorder_ctrl *preorder_ctrl = pcontext;
- struct _adapter *padapter = preorder_ctrl->padapter;
- struct __queue *ppending_recvframe_queue =
- &preorder_ctrl->pending_recvframe_queue;
-
- if (padapter->driver_stopped || padapter->surprise_removed)
- return;
- spin_lock_irqsave(&ppending_recvframe_queue->lock, irql);
- r8712_recv_indicatepkts_in_order(padapter, preorder_ctrl, true);
- spin_unlock_irqrestore(&ppending_recvframe_queue->lock, irql);
-}
-
-static int r8712_process_recv_indicatepkts(struct _adapter *padapter,
- union recv_frame *prframe)
-{
- int retval = _SUCCESS;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-
- if (phtpriv->ht_option == 1) { /*B/G/N Mode*/
- if (recv_indicatepkt_reorder(padapter, prframe)) {
- /* including perform A-MPDU Rx Ordering Buffer Control*/
- if (!padapter->driver_stopped &&
- !padapter->surprise_removed)
- return _FAIL;
- }
- } else { /*B/G mode*/
- retval = r8712_wlanhdr_to_ethhdr(prframe);
- if (retval)
- return _FAIL;
- if (!padapter->driver_stopped && !padapter->surprise_removed) {
- /* indicate this recv_frame */
- r8712_recv_indicatepkt(padapter, prframe);
- } else {
- return _FAIL;
- }
- }
- return retval;
-}
-
-static u8 query_rx_pwr_percentage(s8 antpower)
-{
- if ((antpower <= -100) || (antpower >= 20))
- return 0;
- else if (antpower >= 0)
- return 100;
- else
- return 100 + antpower;
-}
-
-static u8 evm_db2percentage(s8 value)
-{
- /*
- * -33dB~0dB to 0%~99%
- */
- s8 ret_val = clamp(-value, 0, 33) * 3;
-
- if (ret_val == 99)
- ret_val = 100;
-
- return ret_val;
-}
-
-s32 r8712_signal_scale_mapping(s32 cur_sig)
-{
- s32 ret_sig;
-
- if (cur_sig >= 51 && cur_sig <= 100)
- ret_sig = 100;
- else if (cur_sig >= 41 && cur_sig <= 50)
- ret_sig = 80 + ((cur_sig - 40) * 2);
- else if (cur_sig >= 31 && cur_sig <= 40)
- ret_sig = 66 + (cur_sig - 30);
- else if (cur_sig >= 21 && cur_sig <= 30)
- ret_sig = 54 + (cur_sig - 20);
- else if (cur_sig >= 10 && cur_sig <= 20)
- ret_sig = 42 + (((cur_sig - 10) * 2) / 3);
- else if (cur_sig >= 5 && cur_sig <= 9)
- ret_sig = 22 + (((cur_sig - 5) * 3) / 2);
- else if (cur_sig >= 1 && cur_sig <= 4)
- ret_sig = 6 + (((cur_sig - 1) * 3) / 2);
- else
- ret_sig = cur_sig;
- return ret_sig;
-}
-
-static s32 translate2dbm(struct _adapter *padapter, u8 signal_strength_idx)
-{
- s32 signal_power; /* in dBm.*/
- /* Translate to dBm (x=0.5y-95).*/
- signal_power = (s32)((signal_strength_idx + 1) >> 1);
- signal_power -= 95;
- return signal_power;
-}
-
-static void query_rx_phy_status(struct _adapter *padapter,
- union recv_frame *prframe)
-{
- u8 i, max_spatial_stream, evm;
- struct recv_stat *prxstat = (struct recv_stat *)prframe->u.hdr.rx_head;
- struct phy_stat *pphy_stat = (struct phy_stat *)(prxstat + 1);
- u8 *pphy_head = (u8 *)(prxstat + 1);
- s8 rx_pwr[4], rx_pwr_all;
- u8 pwdb_all;
- u32 rssi, total_rssi = 0;
- u8 bcck_rate = 0, rf_rx_num = 0, cck_highpwr = 0;
- struct phy_cck_rx_status *pcck_buf;
- u8 sq;
-
- /* Record it for next packet processing*/
- bcck_rate = (prframe->u.hdr.attrib.mcs_rate <= 3 ? 1 : 0);
- if (bcck_rate) {
- u8 report;
-
- /* CCK Driver info Structure is not the same as OFDM packet.*/
- pcck_buf = (struct phy_cck_rx_status *)pphy_stat;
- /* (1)Hardware does not provide RSSI for CCK
- * (2)PWDB, Average PWDB calculated by hardware
- * (for rate adaptive)
- */
- if (!cck_highpwr) {
- report = pcck_buf->cck_agc_rpt & 0xc0;
- report >>= 6;
- switch (report) {
- /* Modify the RF RNA gain value to -40, -20,
- * -2, 14 by Jenyu's suggestion
- * Note: different RF with the different
- * RNA gain.
- */
- case 0x3:
- rx_pwr_all = -40 - (pcck_buf->cck_agc_rpt &
- 0x3e);
- break;
- case 0x2:
- rx_pwr_all = -20 - (pcck_buf->cck_agc_rpt &
- 0x3e);
- break;
- case 0x1:
- rx_pwr_all = -2 - (pcck_buf->cck_agc_rpt &
- 0x3e);
- break;
- case 0x0:
- rx_pwr_all = 14 - (pcck_buf->cck_agc_rpt &
- 0x3e);
- break;
- }
- } else {
- report = ((u8)(le32_to_cpu(pphy_stat->phydw1) >> 8)) &
- 0x60;
- report >>= 5;
- switch (report) {
- case 0x3:
- rx_pwr_all = -40 - ((pcck_buf->cck_agc_rpt &
- 0x1f) << 1);
- break;
- case 0x2:
- rx_pwr_all = -20 - ((pcck_buf->cck_agc_rpt &
- 0x1f) << 1);
- break;
- case 0x1:
- rx_pwr_all = -2 - ((pcck_buf->cck_agc_rpt &
- 0x1f) << 1);
- break;
- case 0x0:
- rx_pwr_all = 14 - ((pcck_buf->cck_agc_rpt &
- 0x1f) << 1);
- break;
- }
- }
- pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
- /* CCK gain is smaller than OFDM/MCS gain,*/
- /* so we add gain diff by experiences, the val is 6 */
- pwdb_all += 6;
- if (pwdb_all > 100)
- pwdb_all = 100;
- /* modify the offset to make the same gain index with OFDM.*/
- if (pwdb_all > 34 && pwdb_all <= 42)
- pwdb_all -= 2;
- else if (pwdb_all > 26 && pwdb_all <= 34)
- pwdb_all -= 6;
- else if (pwdb_all > 14 && pwdb_all <= 26)
- pwdb_all -= 8;
- else if (pwdb_all > 4 && pwdb_all <= 14)
- pwdb_all -= 4;
- /*
- * (3) Get Signal Quality (EVM)
- */
- if (pwdb_all > 40) {
- sq = 100;
- } else {
- sq = pcck_buf->sq_rpt;
- if (pcck_buf->sq_rpt > 64)
- sq = 0;
- else if (pcck_buf->sq_rpt < 20)
- sq = 100;
- else
- sq = ((64 - sq) * 100) / 44;
- }
- prframe->u.hdr.attrib.signal_qual = sq;
- prframe->u.hdr.attrib.rx_mimo_signal_qual[0] = sq;
- prframe->u.hdr.attrib.rx_mimo_signal_qual[1] = -1;
- } else {
- /* (1)Get RSSI for HT rate */
- for (i = 0; i < ((padapter->registrypriv.rf_config) &
- 0x0f); i++) {
- rf_rx_num++;
- rx_pwr[i] = ((pphy_head[PHY_STAT_GAIN_TRSW_SHT + i]
- & 0x3F) * 2) - 110;
- /* Translate DBM to percentage. */
- rssi = query_rx_pwr_percentage(rx_pwr[i]);
- total_rssi += rssi;
- }
- /* (2)PWDB, Average PWDB calculated by hardware (for
- * rate adaptive)
- */
- rx_pwr_all = (((pphy_head[PHY_STAT_PWDB_ALL_SHT]) >> 1) & 0x7f)
- - 106;
- pwdb_all = query_rx_pwr_percentage(rx_pwr_all);
-
- {
- /* (3)EVM of HT rate */
- if (prframe->u.hdr.attrib.htc &&
- prframe->u.hdr.attrib.mcs_rate >= 20 &&
- prframe->u.hdr.attrib.mcs_rate <= 27) {
- /* both spatial stream make sense */
- max_spatial_stream = 2;
- } else {
- /* only spatial stream 1 makes sense */
- max_spatial_stream = 1;
- }
- for (i = 0; i < max_spatial_stream; i++) {
- evm = evm_db2percentage((pphy_head
- [PHY_STAT_RXEVM_SHT + i]));/*dbm*/
- prframe->u.hdr.attrib.signal_qual =
- (u8)(evm & 0xff);
- prframe->u.hdr.attrib.rx_mimo_signal_qual[i] =
- (u8)(evm & 0xff);
- }
- }
- }
- /* UI BSS List signal strength(in percentage), make it good looking,
- * from 0~100. It is assigned to the BSS List in
- * GetValueFromBeaconOrProbeRsp().
- */
- if (bcck_rate) {
- prframe->u.hdr.attrib.signal_strength =
- (u8)r8712_signal_scale_mapping(pwdb_all);
- } else {
- if (rf_rx_num != 0)
- prframe->u.hdr.attrib.signal_strength =
- (u8)(r8712_signal_scale_mapping(total_rssi /=
- rf_rx_num));
- }
-}
-
-static void process_link_qual(struct _adapter *padapter,
- union recv_frame *prframe)
-{
- u32 last_evm = 0, avg_val;
- struct rx_pkt_attrib *pattrib;
- struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
-
- if (!prframe || !padapter)
- return;
- pattrib = &prframe->u.hdr.attrib;
- if (pattrib->signal_qual != 0) {
- /*
- * 1. Record the general EVM to the sliding window.
- */
- if (sqd->total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX) {
- sqd->total_num = PHY_LINKQUALITY_SLID_WIN_MAX;
- last_evm = sqd->elements[sqd->index];
- sqd->total_val -= last_evm;
- }
- sqd->total_val += pattrib->signal_qual;
- sqd->elements[sqd->index++] = pattrib->signal_qual;
- if (sqd->index >= PHY_LINKQUALITY_SLID_WIN_MAX)
- sqd->index = 0;
-
- /* <1> Showed on UI for user, in percentage. */
- avg_val = sqd->total_val / sqd->total_num;
- padapter->recvpriv.signal = (u8)avg_val;
- }
-}
-
-static void process_rssi(struct _adapter *padapter, union recv_frame *prframe)
-{
- u32 last_rssi, tmp_val;
- struct rx_pkt_attrib *pattrib = &prframe->u.hdr.attrib;
- struct smooth_rssi_data *ssd = &padapter->recvpriv.signal_strength_data;
-
- if (ssd->total_num++ >= PHY_RSSI_SLID_WIN_MAX) {
- ssd->total_num = PHY_RSSI_SLID_WIN_MAX;
- last_rssi = ssd->elements[ssd->index];
- ssd->total_val -= last_rssi;
- }
- ssd->total_val += pattrib->signal_strength;
- ssd->elements[ssd->index++] = pattrib->signal_strength;
- if (ssd->index >= PHY_RSSI_SLID_WIN_MAX)
- ssd->index = 0;
- tmp_val = ssd->total_val / ssd->total_num;
- padapter->recvpriv.rssi = (s8)translate2dbm(padapter, (u8)tmp_val);
-}
-
-static void process_phy_info(struct _adapter *padapter,
- union recv_frame *prframe)
-{
- query_rx_phy_status(padapter, prframe);
- process_rssi(padapter, prframe);
- process_link_qual(padapter, prframe);
-}
-
-int recv_func(struct _adapter *padapter, void *pcontext)
-{
- struct rx_pkt_attrib *pattrib;
- union recv_frame *prframe, *orig_prframe;
- int retval = _SUCCESS;
- struct __queue *pfree_recv_queue = &padapter->recvpriv.free_recv_queue;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- prframe = pcontext;
- orig_prframe = prframe;
- pattrib = &prframe->u.hdr.attrib;
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- if (pattrib->crc_err == 1)
- padapter->mppriv.rx_crcerrpktcount++;
- else
- padapter->mppriv.rx_pktcount++;
- if (!check_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE)) {
- /* free this recv_frame */
- r8712_free_recvframe(orig_prframe, pfree_recv_queue);
- goto _exit_recv_func;
- }
- }
- /* check the frame crtl field and decache */
- retval = r8712_validate_recv_frame(padapter, prframe);
- if (retval != _SUCCESS) {
- /* free this recv_frame */
- r8712_free_recvframe(orig_prframe, pfree_recv_queue);
- goto _exit_recv_func;
- }
- process_phy_info(padapter, prframe);
- prframe = r8712_decryptor(padapter, prframe);
- if (!prframe) {
- retval = _FAIL;
- goto _exit_recv_func;
- }
- prframe = r8712_recvframe_chk_defrag(padapter, prframe);
- if (!prframe)
- goto _exit_recv_func;
- prframe = r8712_portctrl(padapter, prframe);
- if (!prframe) {
- retval = _FAIL;
- goto _exit_recv_func;
- }
- retval = r8712_process_recv_indicatepkts(padapter, prframe);
- if (retval != _SUCCESS) {
- r8712_free_recvframe(orig_prframe, pfree_recv_queue);
- goto _exit_recv_func;
- }
-_exit_recv_func:
- return retval;
-}
-
-static void recvbuf2recvframe(struct _adapter *padapter, struct sk_buff *pskb)
-{
- u8 *pbuf, shift_sz = 0;
- u8 frag, mf;
- uint pkt_len;
- u32 transfer_len;
- struct recv_stat *prxstat;
- u16 pkt_cnt, drvinfo_sz, pkt_offset, tmp_len, alloc_sz;
- struct __queue *pfree_recv_queue;
- _pkt *pkt_copy = NULL;
- union recv_frame *precvframe = NULL;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- pfree_recv_queue = &precvpriv->free_recv_queue;
- pbuf = pskb->data;
- prxstat = (struct recv_stat *)pbuf;
- pkt_cnt = (le32_to_cpu(prxstat->rxdw2) >> 16) & 0xff;
- pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x00003fff;
- transfer_len = pskb->len;
- /* Test throughput with Netgear 3700 (No security) with Chariot 3T3R
- * pairs. The packet count will be a big number so that the containing
- * packet will effect the Rx reordering.
- */
- if (transfer_len < pkt_len) {
- /* In this case, it means the MAX_RECVBUF_SZ is too small to
- * get the data from 8712u.
- */
- return;
- }
- do {
- prxstat = (struct recv_stat *)pbuf;
- pkt_len = le32_to_cpu(prxstat->rxdw0) & 0x00003fff;
- /* more fragment bit */
- mf = (le32_to_cpu(prxstat->rxdw1) >> 27) & 0x1;
- /* ragmentation number */
- frag = (le32_to_cpu(prxstat->rxdw2) >> 12) & 0xf;
- /* uint 2^3 = 8 bytes */
- drvinfo_sz = (le32_to_cpu(prxstat->rxdw0) & 0x000f0000) >> 16;
- drvinfo_sz <<= 3;
- if (pkt_len <= 0)
- return;
- /* Qos data, wireless lan header length is 26 */
- if ((le32_to_cpu(prxstat->rxdw0) >> 23) & 0x01)
- shift_sz = 2;
- precvframe = r8712_alloc_recvframe(pfree_recv_queue);
- if (!precvframe)
- return;
- INIT_LIST_HEAD(&precvframe->u.hdr.list);
- precvframe->u.hdr.precvbuf = NULL; /*can't access the precvbuf*/
- precvframe->u.hdr.len = 0;
- tmp_len = pkt_len + drvinfo_sz + RXDESC_SIZE;
- pkt_offset = (u16)round_up(tmp_len, 128);
- /* for first fragment packet, driver need allocate 1536 +
- * drvinfo_sz + RXDESC_SIZE to defrag packet.
- */
- if ((mf == 1) && (frag == 0))
- /*1658+6=1664, 1664 is 128 alignment.*/
- alloc_sz = max_t(u16, tmp_len, 1658);
- else
- alloc_sz = tmp_len;
- /* 2 is for IP header 4 bytes alignment in QoS packet case.
- * 4 is for skb->data 4 bytes alignment.
- */
- alloc_sz += 6;
- pkt_copy = netdev_alloc_skb(padapter->pnetdev, alloc_sz);
- if (!pkt_copy)
- return;
-
- precvframe->u.hdr.pkt = pkt_copy;
- skb_reserve(pkt_copy, 4 - ((addr_t)(pkt_copy->data) % 4));
- skb_reserve(pkt_copy, shift_sz);
- memcpy(pkt_copy->data, pbuf, tmp_len);
- precvframe->u.hdr.rx_head = pkt_copy->data;
- precvframe->u.hdr.rx_data = pkt_copy->data;
- precvframe->u.hdr.rx_tail = pkt_copy->data;
- precvframe->u.hdr.rx_end = pkt_copy->data + alloc_sz;
-
- recvframe_put(precvframe, tmp_len);
- recvframe_pull(precvframe, drvinfo_sz + RXDESC_SIZE);
- /* because the endian issue, driver avoid reference to the
- * rxstat after calling update_recvframe_attrib_from_recvstat();
- */
- update_recvframe_attrib_from_recvstat(&precvframe->u.hdr.attrib,
- prxstat);
- r8712_recv_entry(precvframe);
- transfer_len -= pkt_offset;
- pbuf += pkt_offset;
- pkt_cnt--;
- precvframe = NULL;
- pkt_copy = NULL;
- } while ((transfer_len > 0) && pkt_cnt > 0);
-}
-
-static void recv_tasklet(struct tasklet_struct *t)
-{
- struct sk_buff *pskb;
- struct _adapter *padapter = from_tasklet(padapter, t,
- recvpriv.recv_tasklet);
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- while (NULL != (pskb = skb_dequeue(&precvpriv->rx_skb_queue))) {
- recvbuf2recvframe(padapter, pskb);
- skb_reset_tail_pointer(pskb);
- pskb->len = 0;
- if (!skb_cloned(pskb))
- skb_queue_tail(&precvpriv->free_recv_skb_queue, pskb);
- else
- consume_skb(pskb);
- }
-}
diff --git a/drivers/staging/rtl8712/rtl8712_recv.h b/drivers/staging/rtl8712/rtl8712_recv.h
deleted file mode 100644
index a1360dcf91ce..000000000000
--- a/drivers/staging/rtl8712/rtl8712_recv.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL8712_RECV_H_
-#define _RTL8712_RECV_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-/* Realtek's v2.6.6 reduced this to 4. However, under heavy network and CPU
- * loads, even 8 receive buffers might not be enough; cutting it to 4 seemed
- * unwise.
- */
-#define NR_RECVBUFF (8)
-
-#define NR_PREALLOC_RECV_SKB (8)
-#define RXDESC_SIZE 24
-#define RXDESC_OFFSET RXDESC_SIZE
-#define RECV_BLK_SZ 512
-#define RECV_BLK_CNT 16
-#define RECV_BLK_TH RECV_BLK_CNT
-#define MAX_RECVBUF_SZ 9100
-#define RECVBUFF_ALIGN_SZ 512
-#define RSVD_ROOM_SZ (0)
-/*These definition is used for Rx packet reordering.*/
-#define SN_LESS(a, b) (((a-b) & 0x800) != 0)
-#define SN_EQUAL(a, b) (a == b)
-#define REORDER_WAIT_TIME 30 /* (ms)*/
-
-struct recv_stat {
- __le32 rxdw0;
- __le32 rxdw1;
- __le32 rxdw2;
- __le32 rxdw3;
- __le32 rxdw4;
- __le32 rxdw5;
-};
-
-struct phy_cck_rx_status {
- /* For CCK rate descriptor. This is a unsigned 8:1 variable.
- * LSB bit present 0.5. And MSB 7 bts present a signed value.
- * Range from -64~+63.5.
- */
- u8 adc_pwdb_X[4];
- u8 sq_rpt;
- u8 cck_agc_rpt;
-};
-
-struct phy_stat {
- __le32 phydw0;
- __le32 phydw1;
- __le32 phydw2;
- __le32 phydw3;
- __le32 phydw4;
- __le32 phydw5;
- __le32 phydw6;
- __le32 phydw7;
-};
-
-#define PHY_STAT_GAIN_TRSW_SHT 0
-#define PHY_STAT_PWDB_ALL_SHT 4
-#define PHY_STAT_CFOSHO_SHT 5
-#define PHY_STAT_CCK_AGC_RPT_SHT 5
-#define PHY_STAT_CFOTAIL_SHT 9
-#define PHY_STAT_RXEVM_SHT 13
-#define PHY_STAT_RXSNR_SHT 15
-#define PHY_STAT_PDSNR_SHT 19
-#define PHY_STAT_CSI_CURRENT_SHT 21
-#define PHY_STAT_CSI_TARGET_SHT 23
-#define PHY_STAT_SIGEVM_SHT 25
-#define PHY_STAT_MAX_EX_PWR_SHT 26
-
-union recvstat {
- struct recv_stat recv_stat;
- unsigned int value[RXDESC_SIZE >> 2];
-};
-
-struct recv_buf {
- struct list_head list;
- spinlock_t recvbuf_lock;
- u32 ref_cnt;
- struct _adapter *adapter;
- struct urb *purb;
- _pkt *pskb;
- u8 irp_pending;
- u32 transfer_len;
- uint len;
- u8 *phead;
- u8 *pdata;
- u8 *ptail;
- u8 *pend;
- u8 *pbuf;
- u8 *pallocated_buf;
-};
-
-/*
- * head ----->
- * data ----->
- * payload
- * tail ----->
- * end ----->
- * len = (unsigned int )(tail - data);
- */
-struct recv_frame_hdr {
- struct list_head list;
- _pkt *pkt;
- _pkt *pkt_newalloc;
- struct _adapter *adapter;
- u8 fragcnt;
- struct rx_pkt_attrib attrib;
- uint len;
- u8 *rx_head;
- u8 *rx_data;
- u8 *rx_tail;
- u8 *rx_end;
- void *precvbuf;
- struct sta_info *psta;
- /*for A-MPDU Rx reordering buffer control*/
- struct recv_reorder_ctrl *preorder_ctrl;
-};
-
-union recv_frame {
- union {
- struct list_head list;
- struct recv_frame_hdr hdr;
- } u;
-};
-
-void r8712_init_recvbuf(struct _adapter *padapter, struct recv_buf *precvbuf);
-void r8712_rxcmd_event_hdl(struct _adapter *padapter, void *prxcmdbuf);
-s32 r8712_signal_scale_mapping(s32 cur_sig);
-void r8712_reordering_ctrl_timeout_handler(void *pcontext);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl8712_regdef.h b/drivers/staging/rtl8712/rtl8712_regdef.h
deleted file mode 100644
index 28aec9aa539f..000000000000
--- a/drivers/staging/rtl8712/rtl8712_regdef.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_REGDEF_H__
-#define __RTL8712_REGDEF_H__
-
-#include "rtl8712_syscfg_regdef.h"
-#include "rtl8712_cmdctrl_regdef.h"
-#include "rtl8712_macsetting_regdef.h"
-#include "rtl8712_timectrl_regdef.h"
-#include "rtl8712_fifoctrl_regdef.h"
-#include "rtl8712_ratectrl_regdef.h"
-#include "rtl8712_edcasetting_regdef.h"
-#include "rtl8712_wmac_regdef.h"
-#include "rtl8712_powersave_regdef.h"
-#include "rtl8712_gp_regdef.h"
-#include "rtl8712_debugctrl_regdef.h"
-
-#define HIMR (RTL8712_INTERRUPT_ + 0x08)
-
-#endif /* __RTL8712_REGDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_security_bitdef.h b/drivers/staging/rtl8712/rtl8712_security_bitdef.h
deleted file mode 100644
index 44275ef455a0..000000000000
--- a/drivers/staging/rtl8712/rtl8712_security_bitdef.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_SECURITY_BITDEF_H__
-#define __RTL8712_SECURITY_BITDEF_H__
-
-/*CAMCMD*/
-#define _SECCAM_POLLING BIT(31)
-#define _SECCAM_CLR BIT(30)
-#define _SECCAM_WE BIT(16)
-#define _SECCAM_ADR_MSK 0x000000FF
-#define _SECCAM_ADR_SHT 0
-
-/*CAMDBG*/
-#define _SECCAM_INFO BIT(31)
-#define _SEC_KEYFOUND BIT(30)
-#define _SEC_CONFIG_MSK 0x3F000000
-#define _SEC_CONFIG_SHT 24
-#define _SEC_KEYCONTENT_MSK 0x00FFFFFF
-#define _SEC_KEYCONTENT_SHT 0
-
-/*SECCFG*/
-#define _NOSKMC BIT(5)
-#define _SKBYA2 BIT(4)
-#define _RXDEC BIT(3)
-#define _TXENC BIT(2)
-#define _RXUSEDK BIT(1)
-#define _TXUSEDK BIT(0)
-
-#endif /*__RTL8712_SECURITY_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_spec.h b/drivers/staging/rtl8712/rtl8712_spec.h
deleted file mode 100644
index 613a410e5714..000000000000
--- a/drivers/staging/rtl8712/rtl8712_spec.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_SPEC_H__
-#define __RTL8712_SPEC_H__
-
-#define RTL8712_IOBASE_TXPKT 0x10200000 /*IOBASE_TXPKT*/
-#define RTL8712_IOBASE_RXPKT 0x10210000 /*IOBASE_RXPKT*/
-#define RTL8712_IOBASE_RXCMD 0x10220000 /*IOBASE_RXCMD*/
-#define RTL8712_IOBASE_TXSTATUS 0x10230000 /*IOBASE_TXSTATUS*/
-#define RTL8712_IOBASE_RXSTATUS 0x10240000 /*IOBASE_RXSTATUS*/
-#define RTL8712_IOBASE_IOREG 0x10250000 /*IOBASE_IOREG ADDR*/
-#define RTL8712_IOBASE_SCHEDULER 0x10260000 /*IOBASE_SCHEDULE*/
-
-#define RTL8712_IOBASE_TRXDMA 0x10270000 /*IOBASE_TRXDMA*/
-#define RTL8712_IOBASE_TXLLT 0x10280000 /*IOBASE_TXLLT*/
-#define RTL8712_IOBASE_WMAC 0x10290000 /*IOBASE_WMAC*/
-#define RTL8712_IOBASE_FW2HW 0x102A0000 /*IOBASE_FW2HW*/
-#define RTL8712_IOBASE_ACCESS_PHYREG 0x102B0000 /*IOBASE_ACCESS_PHYREG*/
-
-#define RTL8712_IOBASE_FF 0x10300000 /*IOBASE_FIFO 0x1031000~0x103AFFFF*/
-
-/*IOREG Offset for 8712*/
-#define RTL8712_SYSCFG_ RTL8712_IOBASE_IOREG
-#define RTL8712_CMDCTRL_ (RTL8712_IOBASE_IOREG + 0x40)
-#define RTL8712_MACIDSETTING_ (RTL8712_IOBASE_IOREG + 0x50)
-#define RTL8712_TIMECTRL_ (RTL8712_IOBASE_IOREG + 0x80)
-#define RTL8712_FIFOCTRL_ (RTL8712_IOBASE_IOREG + 0xA0)
-#define RTL8712_RATECTRL_ (RTL8712_IOBASE_IOREG + 0x160)
-#define RTL8712_EDCASETTING_ (RTL8712_IOBASE_IOREG + 0x1D0)
-#define RTL8712_WMAC_ (RTL8712_IOBASE_IOREG + 0x200)
-#define RTL8712_SECURITY_ (RTL8712_IOBASE_IOREG + 0x240)
-#define RTL8712_POWERSAVE_ (RTL8712_IOBASE_IOREG + 0x260)
-#define RTL8712_GP_ (RTL8712_IOBASE_IOREG + 0x2E0)
-#define RTL8712_INTERRUPT_ (RTL8712_IOBASE_IOREG + 0x300)
-#define RTL8712_DEBUGCTRL_ (RTL8712_IOBASE_IOREG + 0x310)
-#define RTL8712_OFFLOAD_ (RTL8712_IOBASE_IOREG + 0x2D0)
-
-/*FIFO for 8712*/
-#define RTL8712_DMA_BCNQ (RTL8712_IOBASE_FF + 0x10000)
-#define RTL8712_DMA_MGTQ (RTL8712_IOBASE_FF + 0x20000)
-#define RTL8712_DMA_BMCQ (RTL8712_IOBASE_FF + 0x30000)
-#define RTL8712_DMA_VOQ (RTL8712_IOBASE_FF + 0x40000)
-#define RTL8712_DMA_VIQ (RTL8712_IOBASE_FF + 0x50000)
-#define RTL8712_DMA_BEQ (RTL8712_IOBASE_FF + 0x60000)
-#define RTL8712_DMA_BKQ (RTL8712_IOBASE_FF + 0x70000)
-#define RTL8712_DMA_RX0FF (RTL8712_IOBASE_FF + 0x80000)
-#define RTL8712_DMA_H2CCMD (RTL8712_IOBASE_FF + 0x90000)
-#define RTL8712_DMA_C2HCMD (RTL8712_IOBASE_FF + 0xA0000)
-
-/*------------------------------*/
-
-/*BIT 16 15*/
-#define DID_SDIO_LOCAL 0 /* 0 0*/
-#define DID_WLAN_IOREG 1 /* 0 1*/
-#define DID_WLAN_FIFO 3 /* 1 1*/
-#define DID_UNDEFINE (-1)
-
-#define CMD_ADDR_MAPPING_SHIFT 2 /*SDIO CMD ADDR MAPPING,
- *shift 2 bit for match
- * offset[14:2]
- */
-
-/*Offset for SDIO LOCAL*/
-#define OFFSET_SDIO_LOCAL 0x0FFF
-
-/*Offset for WLAN IOREG*/
-#define OFFSET_WLAN_IOREG 0x0FFF
-
-/*Offset for WLAN FIFO*/
-#define OFFSET_TX_BCNQ 0x0300
-#define OFFSET_TX_HIQ 0x0310
-#define OFFSET_TX_CMDQ 0x0320
-#define OFFSET_TX_MGTQ 0x0330
-#define OFFSET_TX_HCCAQ 0x0340
-#define OFFSET_TX_VOQ 0x0350
-#define OFFSET_TX_VIQ 0x0360
-#define OFFSET_TX_BEQ 0x0370
-#define OFFSET_TX_BKQ 0x0380
-#define OFFSET_RX_RX0FFQ 0x0390
-#define OFFSET_RX_C2HFFQ 0x03A0
-
-#define BK_QID_01 1
-#define BK_QID_02 2
-#define BE_QID_01 0
-#define BE_QID_02 3
-#define VI_QID_01 4
-#define VI_QID_02 5
-#define VO_QID_01 6
-#define VO_QID_02 7
-#define HCCA_QID_01 8
-#define HCCA_QID_02 9
-#define HCCA_QID_03 10
-#define HCCA_QID_04 11
-#define HCCA_QID_05 12
-#define HCCA_QID_06 13
-#define HCCA_QID_07 14
-#define HCCA_QID_08 15
-#define HI_QID 17
-#define CMD_QID 19
-#define MGT_QID 18
-#define BCN_QID 16
-
-#include "rtl8712_regdef.h"
-
-#include "rtl8712_bitdef.h"
-
-#include "basic_types.h"
-
-#endif /* __RTL8712_SPEC_H__ */
-
diff --git a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h b/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h
deleted file mode 100644
index d92df3fbd2b1..000000000000
--- a/drivers/staging/rtl8712/rtl8712_syscfg_bitdef.h
+++ /dev/null
@@ -1,163 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_SYSCFG_BITDEF_H__
-#define __RTL8712_SYSCFG_BITDEF_H__
-
-/*SYS_PWR_CTRL*/
-/*SRCTRL0*/
-/*SRCTRL1*/
-/*SYS_CLKR*/
-
-/*SYS_IOS_CTRL*/
-#define iso_LDR2RP_SHT 8 /* EE Loader to Retention Path*/
-#define iso_LDR2RP BIT(iso_LDR2RP_SHT) /* 1:isolation, 0:attach*/
-
-/*SYS_CTRL*/
-#define FEN_DIO_SDIO_SHT 0
-#define FEN_DIO_SDIO BIT(FEN_DIO_SDIO_SHT)
-#define FEN_SDIO_SHT 1
-#define FEN_SDIO BIT(FEN_SDIO_SHT)
-#define FEN_USBA_SHT 2
-#define FEN_USBA BIT(FEN_USBA_SHT)
-#define FEN_UPLL_SHT 3
-#define FEN_UPLL BIT(FEN_UPLL_SHT)
-#define FEN_USBD_SHT 4
-#define FEN_USBD BIT(FEN_USBD_SHT)
-#define FEN_DIO_PCIE_SHT 5
-#define FEN_DIO_PCIE BIT(FEN_DIO_PCIE_SHT)
-#define FEN_PCIEA_SHT 6
-#define FEN_PCIEA BIT(FEN_PCIEA_SHT)
-#define FEN_PPLL_SHT 7
-#define FEN_PPLL BIT(FEN_PPLL_SHT)
-#define FEN_PCIED_SHT 8
-#define FEN_PCIED BIT(FEN_PCIED_SHT)
-#define FEN_CPUEN_SHT 10
-#define FEN_CPUEN BIT(FEN_CPUEN_SHT)
-#define FEN_DCORE_SHT 11
-#define FEN_DCORE BIT(FEN_DCORE_SHT)
-#define FEN_ELDR_SHT 12
-#define FEN_ELDR BIT(FEN_ELDR_SHT)
-#define PWC_DV2LDR_SHT 13
-#define PWC_DV2LDR BIT(PWC_DV2LDR_SHT) /* Loader Power Enable*/
-
-/*=== SYS_CLKR ===*/
-#define SYS_CLKSEL_SHT 0
-#define SYS_CLKSEL BIT(SYS_CLKSEL_SHT) /* System Clock 80MHz*/
-#define PS_CLKSEL_SHT 1
-#define PS_CLKSEL BIT(PS_CLKSEL_SHT) /*System power save
- * clock select.
- */
-#define CPU_CLKSEL_SHT 2
-#define CPU_CLKSEL BIT(CPU_CLKSEL_SHT) /* System Clock select,
- * 1: AFE source,
- * 0: System clock(L-Bus)
- */
-#define INT32K_EN_SHT 3
-#define INT32K_EN BIT(INT32K_EN_SHT)
-#define MACSLP_SHT 4
-#define MACSLP BIT(MACSLP_SHT)
-#define MAC_CLK_EN_SHT 11
-#define MAC_CLK_EN BIT(MAC_CLK_EN_SHT) /* MAC Clock Enable.*/
-#define SYS_CLK_EN_SHT 12
-#define SYS_CLK_EN BIT(SYS_CLK_EN_SHT)
-#define RING_CLK_EN_SHT 13
-#define RING_CLK_EN BIT(RING_CLK_EN_SHT)
-#define SWHW_SEL_SHT 14
-#define SWHW_SEL BIT(SWHW_SEL_SHT) /* Load done,
- * control path switch.
- */
-#define FWHW_SEL_SHT 15
-#define FWHW_SEL BIT(FWHW_SEL_SHT) /* Sleep exit,
- * control path switch.
- */
-
-/*9346CR*/
-#define _VPDIDX_MSK 0xFF00
-#define _VPDIDX_SHT 8
-#define _EEM_MSK 0x00C0
-#define _EEM_SHT 6
-#define _EEM0 BIT(6)
-#define _EEM1 BIT(7)
-#define _EEPROM_EN BIT(5)
-#define _9356SEL BIT(4)
-#define _EECS BIT(3)
-#define _EESK BIT(2)
-#define _EEDI BIT(1)
-#define _EEDO BIT(0)
-
-/*AFE_MISC*/
-#define AFE_MISC_USB_MBEN_SHT 7
-#define AFE_MISC_USB_MBEN BIT(AFE_MISC_USB_MBEN_SHT)
-#define AFE_MISC_USB_BGEN_SHT 6
-#define AFE_MISC_USB_BGEN BIT(AFE_MISC_USB_BGEN_SHT)
-#define AFE_MISC_LD12_VDAJ_SHT 4
-#define AFE_MISC_LD12_VDAJ_MSK 0X0030
-#define AFE_MISC_LD12_VDAJ BIT(AFE_MISC_LD12_VDAJ_SHT)
-#define AFE_MISC_I32_EN_SHT 3
-#define AFE_MISC_I32_EN BIT(AFE_MISC_I32_EN_SHT)
-#define AFE_MISC_E32_EN_SHT 2
-#define AFE_MISC_E32_EN BIT(AFE_MISC_E32_EN_SHT)
-#define AFE_MISC_MBEN_SHT 1
-#define AFE_MISC_MBEN BIT(AFE_MISC_MBEN_SHT)/* Enable AFE Macro
- * Block's Mbias.
- */
-#define AFE_MISC_BGEN_SHT 0
-#define AFE_MISC_BGEN BIT(AFE_MISC_BGEN_SHT)/* Enable AFE Macro
- * Block's Bandgap.
- */
-
-/*--------------------------------------------------------------------------*/
-/* SPS1_CTRL bits (Offset 0x18-1E, 56bits)*/
-/*--------------------------------------------------------------------------*/
-#define SPS1_SWEN BIT(1) /* Enable vsps18 SW Macro Block.*/
-#define SPS1_LDEN BIT(0) /* Enable VSPS12 LDO Macro block.*/
-
-/*----------------------------------------------------------------------------*/
-/* LDOA15_CTRL bits (Offset 0x20, 8bits)*/
-/*----------------------------------------------------------------------------*/
-#define LDA15_EN BIT(0) /* Enable LDOA15 Macro Block*/
-
-/*----------------------------------------------------------------------------*/
-/* 8192S LDOV12D_CTRL bit (Offset 0x21, 8bits)*/
-/*----------------------------------------------------------------------------*/
-#define LDV12_EN BIT(0) /* Enable LDOVD12 Macro Block*/
-#define LDV12_SDBY BIT(1) /* LDOVD12 standby mode*/
-
-/*CLK_PS_CTRL*/
-#define _CLK_GATE_EN BIT(0)
-
-/* EFUSE_CTRL*/
-#define EF_FLAG BIT(31) /* Access Flag, Write:1;
- * Read:0
- */
-#define EF_PGPD 0x70000000 /* E-fuse Program time*/
-#define EF_RDT 0x0F000000 /* E-fuse read time: in the
- * unit of cycle time
- */
-#define EF_PDN_EN BIT(19) /* EFuse Power down enable*/
-#define ALD_EN BIT(18) /* Autoload Enable*/
-#define EF_ADDR 0x0003FF00 /* Access Address*/
-#define EF_DATA 0x000000FF /* Access Data*/
-
-/* EFUSE_TEST*/
-#define LDOE25_EN BIT(31) /* Enable LDOE25 Macro Block*/
-
-/* EFUSE_CLK_CTRL*/
-#define EFUSE_CLK_EN BIT(1) /* E-Fuse Clock Enable*/
-#define EFUSE_CLK_SEL BIT(0) /* E-Fuse Clock Select,
- * 0:500K, 1:40M
- */
-
-#endif /*__RTL8712_SYSCFG_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h b/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h
deleted file mode 100644
index da5efcdedabe..000000000000
--- a/drivers/staging/rtl8712/rtl8712_syscfg_regdef.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_SYSCFG_REGDEF_H__
-#define __RTL8712_SYSCFG_REGDEF_H__
-
-#define SYS_ISO_CTRL (RTL8712_SYSCFG_ + 0x0000)
-#define SYS_FUNC_EN (RTL8712_SYSCFG_ + 0x0002)
-#define PMC_FSM (RTL8712_SYSCFG_ + 0x0004)
-#define SYS_CLKR (RTL8712_SYSCFG_ + 0x0008)
-#define EE_9346CR (RTL8712_SYSCFG_ + 0x000A)
-#define EE_VPD (RTL8712_SYSCFG_ + 0x000C)
-#define AFE_MISC (RTL8712_SYSCFG_ + 0x0010)
-#define SPS0_CTRL (RTL8712_SYSCFG_ + 0x0011)
-#define SPS1_CTRL (RTL8712_SYSCFG_ + 0x0018)
-#define RF_CTRL (RTL8712_SYSCFG_ + 0x001F)
-#define LDOA15_CTRL (RTL8712_SYSCFG_ + 0x0020)
-#define LDOV12D_CTRL (RTL8712_SYSCFG_ + 0x0021)
-#define LDOHCI12_CTRL (RTL8712_SYSCFG_ + 0x0022)
-#define LDO_USB_CTRL (RTL8712_SYSCFG_ + 0x0023)
-#define LPLDO_CTRL (RTL8712_SYSCFG_ + 0x0024)
-#define AFE_XTAL_CTRL (RTL8712_SYSCFG_ + 0x0026)
-#define AFE_PLL_CTRL (RTL8712_SYSCFG_ + 0x0028)
-#define EFUSE_CTRL (RTL8712_SYSCFG_ + 0x0030)
-#define EFUSE_TEST (RTL8712_SYSCFG_ + 0x0034)
-#define PWR_DATA (RTL8712_SYSCFG_ + 0x0038)
-#define DPS_TIMER (RTL8712_SYSCFG_ + 0x003C)
-#define RCLK_MON (RTL8712_SYSCFG_ + 0x003E)
-#define EFUSE_CLK_CTRL (RTL8712_SYSCFG_ + 0x02F8)
-
-#endif /*__RTL8712_SYSCFG_REGDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h b/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h
deleted file mode 100644
index d7bc9dd5cecd..000000000000
--- a/drivers/staging/rtl8712/rtl8712_timectrl_bitdef.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_TIMECTRL_BITDEF_H__
-#define __RTL8712_TIMECTRL_BITDEF_H__
-
-/*TSFTR*/
-/*SLOT*/
-/*USTIME*/
-
-/*TUBASE*/
-#define _TUBASE_MSK 0x07FF
-
-/*SIFS_CCK*/
-#define _SIFS_CCK_TRX_MSK 0xFF00
-#define _SIFS_CCK_TRX_SHT 0x8
-#define _SIFS_CCK_CTX_MSK 0x00FF
-#define _SIFS_CCK_CTX_SHT 0
-
-/*SIFS_OFDM*/
-#define _SIFS_OFDM_TRX_MSK 0xFF00
-#define _SIFS_OFDM_TRX_SHT 0x8
-#define _SIFS_OFDM_CTX_MSK 0x00FF
-#define _SIFS_OFDM_CTX_SHT 0
-
-/*PIFS*/
-/*ACKTO*/
-/*EIFS*/
-/*BCNITV*/
-/*ATIMWND*/
-
-/*DRVERLYINT*/
-#define _ENSWBCN BIT(15)
-#define _DRVERLY_TU_MSK 0x0FF0
-#define _DRVERLY_TU_SHT 4
-#define _DRVERLY_US_MSK 0x000F
-#define _DRVERLY_US_SHT 0
-
-/*BCNDMATIM*/
-#define _BCNDMATIM_MSK 0x03FF
-
-/*BCNERRTH*/
-/*MLT*/
-
-#endif /* __RTL8712_TIMECTRL_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h b/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h
deleted file mode 100644
index b51603f1b880..000000000000
--- a/drivers/staging/rtl8712/rtl8712_timectrl_regdef.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL8712_TIMECTRL_REGDEF_H__
-#define __RTL8712_TIMECTRL_REGDEF_H__
-
-#define TSFTR (RTL8712_TIMECTRL_ + 0x00)
-#define USTIME (RTL8712_TIMECTRL_ + 0x08)
-#define SLOT (RTL8712_TIMECTRL_ + 0x09)
-#define TUBASE (RTL8712_TIMECTRL_ + 0x0A)
-#define SIFS_CCK (RTL8712_TIMECTRL_ + 0x0C)
-#define SIFS_OFDM (RTL8712_TIMECTRL_ + 0x0E)
-#define PIFS (RTL8712_TIMECTRL_ + 0x10)
-#define ACKTO (RTL8712_TIMECTRL_ + 0x11)
-#define EIFS (RTL8712_TIMECTRL_ + 0x12)
-#define BCNITV (RTL8712_TIMECTRL_ + 0x14)
-#define ATIMWND (RTL8712_TIMECTRL_ + 0x16)
-#define DRVERLYINT (RTL8712_TIMECTRL_ + 0x18)
-#define BCNDMATIM (RTL8712_TIMECTRL_ + 0x1A)
-#define BCNERRTH (RTL8712_TIMECTRL_ + 0x1C)
-#define MLT (RTL8712_TIMECTRL_ + 0x1D)
-
-#endif /* __RTL8712_TIMECTRL_REGDEF_H__ */
diff --git a/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h b/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h
deleted file mode 100644
index ea164e482347..000000000000
--- a/drivers/staging/rtl8712/rtl8712_wmac_bitdef.h
+++ /dev/null
@@ -1,49 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_WMAC_BITDEF_H__
-#define __RTL8712_WMAC_BITDEF_H__
-
-/*NAVCTRL*/
-#define _NAV_UPPER_EN BIT(18)
-#define _NAV_MTO_EN BIT(17)
-#define _NAV_UPPER BIT(16)
-#define _NAV_MTO_MSK 0xFF00
-#define _NAV_MTO_SHT 8
-#define _RTSRST_MSK 0x00FF
-#define _RTSRST_SHT 0
-
-/*BWOPMODE*/
-#define _20MHZBW BIT(2)
-
-/*BACAMCMD*/
-#define _BACAM_POLL BIT(31)
-#define _BACAM_RST BIT(17)
-#define _BACAM_RW BIT(16)
-#define _BACAM_ADDR_MSK 0x0000007F
-#define _BACAM_ADDR_SHT 0
-
-/*LBDLY*/
-#define _LBDLY_MSK 0x1F
-
-/*FWDLY*/
-#define _FWDLY_MSK 0x0F
-
-/*RXERR_RPT*/
-#define _RXERR_RPT_SEL_MSK 0xF0000000
-#define _RXERR_RPT_SEL_SHT 28
-#define _RPT_CNT_MSK 0x000FFFFF
-#define _RPT_CNT_SHT 0
-
-#endif /*__RTL8712_WMAC_BITDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_wmac_regdef.h b/drivers/staging/rtl8712/rtl8712_wmac_regdef.h
deleted file mode 100644
index dfe3e9fbed43..000000000000
--- a/drivers/staging/rtl8712/rtl8712_wmac_regdef.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_WMAC_REGDEF_H__
-#define __RTL8712_WMAC_REGDEF_H__
-
-#define NAVCTRL (RTL8712_WMAC_ + 0x00)
-#define BWOPMODE (RTL8712_WMAC_ + 0x03)
-#define BACAMCMD (RTL8712_WMAC_ + 0x04)
-#define BACAMCONTENT (RTL8712_WMAC_ + 0x08)
-#define LBDLY (RTL8712_WMAC_ + 0x10)
-#define FWDLY (RTL8712_WMAC_ + 0x11)
-#define HWPC_RX_CTRL (RTL8712_WMAC_ + 0x18)
-#define MQ (RTL8712_WMAC_ + 0x20)
-#define MA (RTL8712_WMAC_ + 0x22)
-#define MS (RTL8712_WMAC_ + 0x24)
-#define CLM_RESULT (RTL8712_WMAC_ + 0x27)
-#define NHM_RPI_CNT (RTL8712_WMAC_ + 0x28)
-#define RXERR_RPT (RTL8712_WMAC_ + 0x30)
-#define NAV_PROT_LEN (RTL8712_WMAC_ + 0x34)
-#define CFEND_TH (RTL8712_WMAC_ + 0x36)
-#define AMPDU_MIN_SPACE (RTL8712_WMAC_ + 0x37)
-#define TXOP_STALL_CTRL (RTL8712_WMAC_ + 0x38)
-
-#endif /*__RTL8712_WMAC_REGDEF_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl8712_xmit.c b/drivers/staging/rtl8712/rtl8712_xmit.c
deleted file mode 100644
index 12f2fdb1b3cb..000000000000
--- a/drivers/staging/rtl8712/rtl8712_xmit.c
+++ /dev/null
@@ -1,732 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl8712_xmit.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL8712_XMIT_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wifi.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-
-static void dump_xframe(struct _adapter *padapter,
- struct xmit_frame *pxmitframe);
-static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz);
-
-sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag)
-{
- phw_txqueue->ac_tag = ac_tag;
- switch (ac_tag) {
- case BE_QUEUE_INX:
- phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ;
- break;
- case BK_QUEUE_INX:
- phw_txqueue->ff_hwaddr = RTL8712_DMA_BKQ;
- break;
- case VI_QUEUE_INX:
- phw_txqueue->ff_hwaddr = RTL8712_DMA_VIQ;
- break;
- case VO_QUEUE_INX:
- phw_txqueue->ff_hwaddr = RTL8712_DMA_VOQ;
- break;
- case BMC_QUEUE_INX:
- phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ;
- break;
- }
- return _SUCCESS;
-}
-
-int r8712_txframes_sta_ac_pending(struct _adapter *padapter,
- struct pkt_attrib *pattrib)
-{
- struct sta_info *psta;
- struct tx_servq *ptxservq;
- int priority = pattrib->priority;
-
- psta = pattrib->psta;
- switch (priority) {
- case 1:
- case 2:
- ptxservq = &psta->sta_xmitpriv.bk_q;
- break;
- case 4:
- case 5:
- ptxservq = &psta->sta_xmitpriv.vi_q;
- break;
- case 6:
- case 7:
- ptxservq = &psta->sta_xmitpriv.vo_q;
- break;
- case 0:
- case 3:
- default:
- ptxservq = &psta->sta_xmitpriv.be_q;
- break;
- }
- return ptxservq->qcnt;
-}
-
-static u32 get_ff_hwaddr(struct xmit_frame *pxmitframe)
-{
- u32 addr = 0;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct _adapter *padapter = pxmitframe->padapter;
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
-
- if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
- addr = RTL8712_DMA_H2CCMD;
- } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
- addr = RTL8712_DMA_MGTQ;
- } else if (pdvobj->nr_endpoint == 6) {
- switch (pattrib->priority) {
- case 0:
- case 3:
- addr = RTL8712_DMA_BEQ;
- break;
- case 1:
- case 2:
- addr = RTL8712_DMA_BKQ;
- break;
- case 4:
- case 5:
- addr = RTL8712_DMA_VIQ;
- break;
- case 6:
- case 7:
- addr = RTL8712_DMA_VOQ;
- break;
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- addr = RTL8712_DMA_H2CCMD;
- break;
- default:
- addr = RTL8712_DMA_BEQ;
- break;
- }
- } else if (pdvobj->nr_endpoint == 4) {
- switch (pattrib->qsel) {
- case 0:
- case 3:
- case 1:
- case 2:
- addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/
- break;
- case 4:
- case 5:
- case 6:
- case 7:
- addr = RTL8712_DMA_VOQ;/*RTL8712_EP_HI;*/
- break;
- case 0x10:
- case 0x11:
- case 0x12:
- case 0x13:
- addr = RTL8712_DMA_H2CCMD;
- break;
- default:
- addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/
- break;
- }
- }
- return addr;
-}
-
-static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv,
- struct hw_xmit *phwxmit, struct tx_servq *ptxservq,
- struct __queue *pframe_queue)
-{
- struct list_head *xmitframe_plist, *xmitframe_phead;
- struct xmit_frame *pxmitframe = NULL;
-
- xmitframe_phead = &pframe_queue->queue;
- xmitframe_plist = xmitframe_phead->next;
- if (!end_of_queue_search(xmitframe_phead, xmitframe_plist)) {
- pxmitframe = container_of(xmitframe_plist,
- struct xmit_frame, list);
- list_del_init(&pxmitframe->list);
- ptxservq->qcnt--;
- phwxmit->txcmdcnt++;
- }
- return pxmitframe;
-}
-
-static struct xmit_frame *dequeue_xframe_ex(struct xmit_priv *pxmitpriv,
- struct hw_xmit *phwxmit_i, sint entry)
-{
- unsigned long irqL0;
- struct list_head *sta_plist, *sta_phead;
- struct hw_xmit *phwxmit;
- struct tx_servq *ptxservq = NULL;
- struct __queue *pframe_queue = NULL;
- struct xmit_frame *pxmitframe = NULL;
- int i, inx[4];
- int j, acirp_cnt[4];
-
- /*entry indx: 0->vo, 1->vi, 2->be, 3->bk.*/
- inx[0] = 0; acirp_cnt[0] = pxmitpriv->voq_cnt;
- inx[1] = 1; acirp_cnt[1] = pxmitpriv->viq_cnt;
- inx[2] = 2; acirp_cnt[2] = pxmitpriv->beq_cnt;
- inx[3] = 3; acirp_cnt[3] = pxmitpriv->bkq_cnt;
- for (i = 0; i < 4; i++) {
- for (j = i + 1; j < 4; j++) {
- if (acirp_cnt[j] < acirp_cnt[i]) {
- swap(acirp_cnt[i], acirp_cnt[j]);
- swap(inx[i], inx[j]);
- }
- }
- }
- spin_lock_irqsave(&pxmitpriv->lock, irqL0);
- for (i = 0; i < entry; i++) {
- phwxmit = phwxmit_i + inx[i];
- sta_phead = &phwxmit->sta_queue->queue;
- sta_plist = sta_phead->next;
- while (!end_of_queue_search(sta_phead, sta_plist)) {
- ptxservq = container_of(sta_plist, struct tx_servq, tx_pending);
- pframe_queue = &ptxservq->sta_pending;
- pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, ptxservq,
- pframe_queue);
- if (pxmitframe) {
- phwxmit->accnt--;
- goto exit_dequeue_xframe_ex;
- }
- sta_plist = sta_plist->next;
- /*Remove sta node when there are no pending packets.*/
- if (list_empty(&pframe_queue->queue)) {
- /* must be done after sta_plist->next
- * and before break
- */
- list_del_init(&ptxservq->tx_pending);
- }
- }
- }
-exit_dequeue_xframe_ex:
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL0);
- return pxmitframe;
-}
-
-void r8712_do_queue_select(struct _adapter *padapter, struct pkt_attrib *pattrib)
-{
- unsigned int qsel = 0;
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
-
- if (pdvobj->nr_endpoint == 6) {
- qsel = (unsigned int)pattrib->priority;
- } else if (pdvobj->nr_endpoint == 4) {
- qsel = (unsigned int)pattrib->priority;
- if (qsel == 0 || qsel == 3)
- qsel = 3;
- else if (qsel == 1 || qsel == 2)
- qsel = 1;
- else if (qsel == 4 || qsel == 5)
- qsel = 5;
- else if (qsel == 6 || qsel == 7)
- qsel = 7;
- else
- qsel = 3;
- }
- pattrib->qsel = qsel;
-}
-
-#ifdef CONFIG_R8712_TX_AGGR
-void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf)
-{
- struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf;
-
- /* Fill up TxCmd Descriptor according as USB FW Tx Aggregation info.*/
- /* dw0 */
- ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ & 0xffff);
- ptx_desc->txdw0 |=
- cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) &
- 0x00ff0000);
- ptx_desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
-
- /* dw1 */
- ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00);
-}
-
-void r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf)
-{
- struct xmit_frame *pxmitframe = (struct xmit_frame *)
- pxmitbuf->priv_data;
- struct _adapter *padapter = pxmitframe->padapter;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *)
- (pxmitbuf->pbuf + TXDESC_SIZE);
-
- /* Fill up Cmd Header for USB FW Tx Aggregation.*/
- /* dw0 */
- pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) |
- (pcmdpriv->cmd_seq << 24));
- pcmdpriv->cmd_seq++;
-}
-
-void r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf,
- struct xmit_frame *pxmitframe)
-{
- struct _adapter *padapter = pxmitframe->padapter;
- struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf;
- int last_txcmdsz = 0;
- int padding_sz = 0;
-
- /* 802.3->802.11 converter */
- r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
- /* free skb struct */
- r8712_xmit_complete(padapter, pxmitframe);
- if (pxmitframe->attrib.ether_type != 0x0806) {
- if ((pxmitframe->attrib.ether_type != 0x888e) &&
- (pxmitframe->attrib.dhcp_pkt != 1)) {
- r8712_issue_addbareq_cmd(padapter, pxmitframe->attrib.priority);
- }
- }
- pxmitframe->last[0] = 1;
- update_txdesc(pxmitframe, (uint *)(pxmitframe->buf_addr), pxmitframe->attrib.last_txcmdsz);
- /*padding zero */
- last_txcmdsz = pxmitframe->attrib.last_txcmdsz;
- padding_sz = (8 - (last_txcmdsz % 8));
- if ((last_txcmdsz % 8) != 0) {
- int i;
-
- for (i = 0; i < padding_sz; i++)
- *(pxmitframe->buf_addr + TXDESC_SIZE + last_txcmdsz +
- i) = 0;
- }
- /* Add the new mpdu's length */
- ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0 & 0xffff0000) |
- ((ptx_desc->txdw0 & 0x0000ffff) +
- ((TXDESC_SIZE + last_txcmdsz + padding_sz) &
- 0x0000ffff)));
-}
-
-void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf,
- struct xmit_frame *pxmitframe)
-{
- /* linux complete context doesn't need to protect */
- pxmitframe->pxmitbuf = pxmitbuf;
- pxmitbuf->priv_data = pxmitframe;
- pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
- /* buffer addr assoc */
- pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + CMD_HDR_SZ;
- /*RTL8712_DMA_H2CCMD */
- r8712_construct_txaggr_cmd_desc(pxmitbuf);
- r8712_construct_txaggr_cmd_hdr(pxmitbuf);
- r8712_append_mpdu_unit(pxmitbuf, pxmitframe);
- pxmitbuf->aggr_nr = 1;
-}
-
-u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, struct xmit_frame *pxmitframe)
-{
- pxmitframe->pxmitbuf = pxmitbuf;
- pxmitbuf->priv_data = pxmitframe;
- pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
- /* buffer addr assoc */
- pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE +
- (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff);
- r8712_append_mpdu_unit(pxmitbuf, pxmitframe);
- r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv,
- pxmitframe);
- pxmitbuf->aggr_nr++;
-
- return TXDESC_SIZE +
- (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff);
-}
-
-void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf,
- struct xmit_frame *pxmitframe)
-{
- struct _adapter *padapter = pxmitframe->padapter;
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
- struct tx_desc *ptxdesc = pxmitbuf->pbuf;
- struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *)
- (pxmitbuf->pbuf + TXDESC_SIZE);
- u16 total_length = (u16)(ptxdesc->txdw0 & 0xffff);
-
- /* use 1st xmitframe as media */
- xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
- pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length - CMD_HDR_SZ) &
- 0x0000ffff) | (pcmd_hdr->cmd_dw0 &
- 0xffff0000));
-
- /* urb length in cmd_dw1 */
- pcmd_hdr->cmd_dw1 = cpu_to_le32((pxmitbuf->aggr_nr & 0xff) |
- ((total_length + TXDESC_SIZE) << 16));
- pxmitframe->last[0] = 1;
- pxmitframe->bpending[0] = false;
- pxmitframe->mem_addr = pxmitbuf->pbuf;
-
- if ((pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) % 0x200) == 0) ||
- ((!pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) %
- 0x40) == 0))) {
- ptxdesc->txdw0 |= cpu_to_le32
- (((TXDESC_SIZE + OFFSET_SZ + 8) << OFFSET_SHT) &
- 0x00ff0000);
- /*32 bytes for TX Desc + 8 bytes pending*/
- } else {
- ptxdesc->txdw0 |= cpu_to_le32
- (((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) &
- 0x00ff0000);
- /*default = 32 bytes for TX Desc*/
- }
- r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD, total_length + TXDESC_SIZE,
- (u8 *)pxmitframe);
-}
-
-#endif
-
-static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz)
-{
- uint qsel;
- struct _adapter *padapter = pxmitframe->padapter;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct tx_desc *ptxdesc = (struct tx_desc *)pmem;
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
-#ifdef CONFIG_R8712_TX_AGGR
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-#endif
- u8 blnSetTxDescOffset;
- bool bmcst = is_multicast_ether_addr(pattrib->ra);
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
- struct tx_desc txdesc_mp;
-
- memcpy(&txdesc_mp, ptxdesc, sizeof(struct tx_desc));
- memset(ptxdesc, 0, sizeof(struct tx_desc));
- /* offset 0 */
- ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff);
- if (pdvobj->ishighspeed) {
- if (((sz + TXDESC_SIZE) % 512) == 0)
- blnSetTxDescOffset = 1;
- else
- blnSetTxDescOffset = 0;
- } else {
- if (((sz + TXDESC_SIZE) % 64) == 0)
- blnSetTxDescOffset = 1;
- else
- blnSetTxDescOffset = 0;
- }
- if (blnSetTxDescOffset) {
- /* 32 bytes for TX Desc + 8 bytes pending */
- ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ + 8) <<
- OFFSET_SHT) & 0x00ff0000);
- } else {
- /* default = 32 bytes for TX Desc */
- ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) <<
- OFFSET_SHT) & 0x00ff0000);
- }
- ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
- if (pxmitframe->frame_tag == DATA_FRAMETAG) {
- /* offset 4 */
- ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x1f);
-
-#ifdef CONFIG_R8712_TX_AGGR
- /* dirty workaround, need to check if it is aggr cmd. */
- if ((u8 *)pmem != (u8 *)pxmitframe->pxmitbuf->pbuf) {
- ptxdesc->txdw0 |= cpu_to_le32
- ((0x3 << TYPE_SHT) & TYPE_MSK);
- qsel = (uint)(pattrib->qsel & 0x0000001f);
- if (qsel == 2)
- qsel = 0;
- ptxdesc->txdw1 |= cpu_to_le32
- ((qsel << QSEL_SHT) & 0x00001f00);
- ptxdesc->txdw2 = cpu_to_le32
- ((qsel << RTS_RC_SHT) & 0x001f0000);
- ptxdesc->txdw6 |= cpu_to_le32
- ((0x5 << RSVD6_SHT) & RSVD6_MSK);
- } else {
- ptxdesc->txdw0 |= cpu_to_le32
- ((0x3 << TYPE_SHT) & TYPE_MSK);
- ptxdesc->txdw1 |= cpu_to_le32
- ((0x13 << QSEL_SHT) & 0x00001f00);
- qsel = (uint)(pattrib->qsel & 0x0000001f);
- if (qsel == 2)
- qsel = 0;
- ptxdesc->txdw2 = cpu_to_le32
- ((qsel << RTS_RC_SHT) & 0x0001f000);
- ptxdesc->txdw7 |= cpu_to_le32
- (pcmdpriv->cmd_seq << 24);
- pcmdpriv->cmd_seq++;
- }
- pattrib->qsel = 0x13;
-#else
- qsel = (uint)(pattrib->qsel & 0x0000001f);
- ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
-#endif
- if (!pqospriv->qos_option)
- ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/*Non-QoS*/
- if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
- switch (pattrib->encrypt) { /*SEC_TYPE*/
- case _WEP40_:
- case _WEP104_:
- ptxdesc->txdw1 |= cpu_to_le32((0x01 << 22) &
- 0x00c00000);
- /*KEY_ID when WEP is used;*/
- ptxdesc->txdw1 |=
- cpu_to_le32((psecuritypriv->PrivacyKeyIndex << 17) &
- 0x00060000);
- break;
- case _TKIP_:
- case _TKIP_WTMIC_:
- ptxdesc->txdw1 |= cpu_to_le32((0x02 << 22) &
- 0x00c00000);
- break;
- case _AES_:
- ptxdesc->txdw1 |= cpu_to_le32((0x03 << 22) &
- 0x00c00000);
- break;
- case _NO_PRIVACY_:
- default:
- break;
- }
- }
- /*offset 8*/
- if (bmcst)
- ptxdesc->txdw2 |= cpu_to_le32(BMC);
-
- /*offset 12*/
- /* f/w will increase the seqnum by itself, driver pass the
- * correct priority to fw.
- * fw will check the correct priority for increasing the
- * seqnum per tid. about usb using 4-endpoint, qsel points out
- * the correct mapping between AC&Endpoint,
- * the purpose is that correct mapping lets the MAC release
- * the AC Queue list correctly.
- */
- ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) &
- 0x0fff0000);
- if ((pattrib->ether_type != 0x888e) &&
- (pattrib->ether_type != 0x0806) &&
- (pattrib->dhcp_pkt != 1)) {
- /*Not EAP & ARP type data packet*/
- if (phtpriv->ht_option == 1) { /*B/G/N Mode*/
- if (!phtpriv->ampdu_enable)
- ptxdesc->txdw2 |= cpu_to_le32(BK);
- }
- } else {
- /* EAP data packet and ARP packet.
- * Use the 1M data rate to send the EAP/ARP packet.
- * This will maybe make the handshake smooth.
- */
- /*driver uses data rate*/
- ptxdesc->txdw4 = cpu_to_le32(0x80000000);
- ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/*1M*/
- }
- if (pattrib->pctrl == 1) { /* mp tx packets */
- struct tx_desc *ptxdesc_mp;
-
- ptxdesc_mp = &txdesc_mp;
- /* offset 8 */
- ptxdesc->txdw2 = ptxdesc_mp->txdw2;
- if (bmcst)
- ptxdesc->txdw2 |= cpu_to_le32(BMC);
- ptxdesc->txdw2 |= cpu_to_le32(BK);
- /* offset 16 */
- ptxdesc->txdw4 = ptxdesc_mp->txdw4;
- /* offset 20 */
- ptxdesc->txdw5 = ptxdesc_mp->txdw5;
- pattrib->pctrl = 0;/* reset to zero; */
- }
- } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) {
- /* offset 4 */
- /* CAM_ID(MAC_ID), default=5; */
- ptxdesc->txdw1 |= cpu_to_le32((0x05) & 0x1f);
- qsel = (uint)(pattrib->qsel & 0x0000001f);
- ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
- ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/* Non-QoS */
- /* offset 8 */
- if (bmcst)
- ptxdesc->txdw2 |= cpu_to_le32(BMC);
- /* offset 12 */
- /* f/w will increase the seqnum by itself, driver pass the
- * correct priority to fw.
- * fw will check the correct priority for increasing the seqnum
- * per tid. about usb using 4-endpoint, qsel points out the
- * correct mapping between AC&Endpoint,
- * the purpose is that correct mapping let the MAC releases
- * the AC Queue list correctly.
- */
- ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) &
- 0x0fff0000);
- /* offset 16 */
- ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/
- /* offset 20 */
- ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/* gtest 1M */
- } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) {
- /* offset 4 */
- qsel = 0x13;
- ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
- } else {
- /* offset 4 */
- qsel = (uint)(pattrib->priority & 0x0000001f);
- ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
- /*offset 8*/
- /*offset 12*/
- ptxdesc->txdw3 = cpu_to_le32((pattrib->seqnum << SEQ_SHT) &
- 0x0fff0000);
- /*offset 16*/
- ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/
- /*offset 20*/
- ptxdesc->txdw5 = cpu_to_le32(0x001f9600);/*gtest*/
- }
-}
-
-int r8712_xmitframe_complete(struct _adapter *padapter,
- struct xmit_priv *pxmitpriv,
- struct xmit_buf *pxmitbuf)
-{
- struct hw_xmit *phwxmits;
- sint hwentry;
- struct xmit_frame *pxmitframe = NULL;
-#ifdef CONFIG_R8712_TX_AGGR
- struct xmit_frame *p2ndxmitframe = NULL;
-#else
- int res = _SUCCESS;
-#endif
-
- phwxmits = pxmitpriv->hwxmits;
- hwentry = pxmitpriv->hwxmit_entry;
- if (!pxmitbuf) {
- pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv);
- if (!pxmitbuf)
- return false;
-#ifdef CONFIG_R8712_TX_AGGR
- pxmitbuf->aggr_nr = 0;
-#endif
- }
- /* 1st frame dequeued */
- pxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry);
- /* need to remember the 1st frame */
- if (pxmitframe) {
-#ifdef CONFIG_R8712_TX_AGGR
- /* 1. dequeue 2nd frame
- * 2. aggr if 2nd xframe is dequeued, else dump directly
- */
- if (AGGR_NR_HIGH_BOUND > 1)
- p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry);
- if (pxmitframe->frame_tag != DATA_FRAMETAG) {
- r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
- return false;
- }
- if (p2ndxmitframe)
- if (p2ndxmitframe->frame_tag != DATA_FRAMETAG) {
- r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
- return false;
- }
- r8712_xmitframe_aggr_1st(pxmitbuf, pxmitframe);
- if (p2ndxmitframe) {
- u16 total_length;
-
- total_length = r8712_xmitframe_aggr_next(pxmitbuf, p2ndxmitframe);
- do {
- p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry);
- if (p2ndxmitframe)
- total_length =
- r8712_xmitframe_aggr_next(pxmitbuf, p2ndxmitframe);
- else
- break;
- } while (total_length <= 0x1800 &&
- pxmitbuf->aggr_nr <= AGGR_NR_HIGH_BOUND);
- }
- if (pxmitbuf->aggr_nr > 0)
- r8712_dump_aggr_xframe(pxmitbuf, pxmitframe);
-
-#else
-
- xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
- if (pxmitframe->frame_tag == DATA_FRAMETAG) {
- if (pxmitframe->attrib.priority <= 15)
- res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt,
- pxmitframe);
- /* always return ndis_packet after
- * r8712_xmitframe_coalesce
- */
- r8712_xmit_complete(padapter, pxmitframe);
- }
- if (res == _SUCCESS)
- dump_xframe(padapter, pxmitframe);
- else
- r8712_free_xmitframe_ex(pxmitpriv, pxmitframe);
-#endif
-
- } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */
- r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
- return false;
- }
- return true;
-}
-
-static void dump_xframe(struct _adapter *padapter,
- struct xmit_frame *pxmitframe)
-{
- int t, sz, w_sz;
- u8 *mem_addr;
- u32 ff_hwaddr;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- if (pxmitframe->attrib.ether_type != 0x0806) {
- if (pxmitframe->attrib.ether_type != 0x888e)
- r8712_issue_addbareq_cmd(padapter, pattrib->priority);
- }
- mem_addr = pxmitframe->buf_addr;
- for (t = 0; t < pattrib->nr_frags; t++) {
- if (t != (pattrib->nr_frags - 1)) {
- sz = pxmitpriv->frag_len;
- sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 :
- pattrib->icv_len);
- pxmitframe->last[t] = 0;
- } else {
- sz = pattrib->last_txcmdsz;
- pxmitframe->last[t] = 1;
- }
- update_txdesc(pxmitframe, (uint *)mem_addr, sz);
- w_sz = sz + TXDESC_SIZE;
- pxmitframe->mem_addr = mem_addr;
- pxmitframe->bpending[t] = false;
- ff_hwaddr = get_ff_hwaddr(pxmitframe);
-#ifdef CONFIG_R8712_TX_AGGR
- r8712_write_port(padapter, RTL8712_DMA_H2CCMD, w_sz,
- (unsigned char *)pxmitframe);
-#else
- r8712_write_port(padapter, ff_hwaddr, w_sz,
- (unsigned char *)pxmitframe);
-#endif
- mem_addr += w_sz;
- mem_addr = (u8 *)RND4(((addr_t)(mem_addr)));
- }
-}
-
-void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe)
-{
- int res;
-
- res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
- pxmitframe->pkt = NULL;
- if (res == _SUCCESS)
- dump_xframe(padapter, pxmitframe);
-}
-
-int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe)
-{
- if (r8712_xmit_classifier(padapter, pxmitframe)) {
- pxmitframe->pkt = NULL;
- return _FAIL;
- }
- return _SUCCESS;
-}
diff --git a/drivers/staging/rtl8712/rtl8712_xmit.h b/drivers/staging/rtl8712/rtl8712_xmit.h
deleted file mode 100644
index 5cd651a0de75..000000000000
--- a/drivers/staging/rtl8712/rtl8712_xmit.h
+++ /dev/null
@@ -1,108 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL8712_XMIT_H_
-#define _RTL8712_XMIT_H_
-
-#define HWXMIT_ENTRY 4
-
-#define VO_QUEUE_INX 0
-#define VI_QUEUE_INX 1
-#define BE_QUEUE_INX 2
-#define BK_QUEUE_INX 3
-#define TS_QUEUE_INX 4
-#define MGT_QUEUE_INX 5
-#define BMC_QUEUE_INX 6
-#define BCN_QUEUE_INX 7
-
-#define HW_QUEUE_ENTRY 8
-
-#define TXDESC_SIZE 32
-#define TXDESC_OFFSET TXDESC_SIZE
-
-#define NR_AMSDU_XMITFRAME 8
-#define NR_TXAGG_XMITFRAME 8
-
-#define MAX_AMSDU_XMITBUF_SZ 8704
-#define MAX_TXAGG_XMITBUF_SZ 16384 /*16k*/
-
-#define tx_cmd tx_desc
-
-/*
- *defined for TX DESC Operation
- */
-
-#define MAX_TID (15)
-
-/*OFFSET 0*/
-#define OFFSET_SZ (0)
-#define OFFSET_SHT (16)
-#define OWN BIT(31)
-#define FSG BIT(27)
-#define LSG BIT(26)
-#define TYPE_SHT (24)
-#define TYPE_MSK (0x03000000)
-
-/*OFFSET 4*/
-#define PKT_OFFSET_SZ (0)
-#define QSEL_SHT (8)
-#define HWPC BIT(31)
-
-/*OFFSET 8*/
-#define BMC BIT(7)
-#define BK BIT(30)
-#define AGG_EN BIT(29)
-#define RTS_RC_SHT (16)
-
-/*OFFSET 12*/
-#define SEQ_SHT (16)
-
-/*OFFSET 16*/
-#define TXBW BIT(18)
-
-/*OFFSET 20*/
-#define DISFB BIT(15)
-#define RSVD6_MSK (0x00E00000)
-#define RSVD6_SHT (21)
-
-struct tx_desc {
- /*DWORD 0*/
- __le32 txdw0;
- __le32 txdw1;
- __le32 txdw2;
- __le32 txdw3;
- __le32 txdw4;
- __le32 txdw5;
- __le32 txdw6;
- __le32 txdw7;
-};
-
-union txdesc {
- struct tx_desc txdesc;
- unsigned int value[TXDESC_SIZE >> 2];
-};
-
-int r8712_xmitframe_complete(struct _adapter *padapter,
- struct xmit_priv *pxmitpriv,
- struct xmit_buf *pxmitbuf);
-void r8712_do_queue_select(struct _adapter *padapter,
- struct pkt_attrib *pattrib);
-
-#ifdef CONFIG_R8712_TX_AGGR
-void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf,
- struct xmit_frame *pxmitframe);
-void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf,
- struct xmit_frame *pxmitframe);
-#endif
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.c b/drivers/staging/rtl8712/rtl871x_cmd.c
deleted file mode 100644
index ffeb91dd28c4..000000000000
--- a/drivers/staging/rtl8712/rtl871x_cmd.c
+++ /dev/null
@@ -1,750 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_cmd.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_CMD_C_
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/usb.h>
-#include <linux/usb/ch9.h>
-#include <linux/circ_buf.h>
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-#include <linux/atomic.h>
-#include <linux/semaphore.h>
-#include <linux/rtnetlink.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "mlme_osdep.h"
-
-/*
- * Caller and the r8712_cmd_thread can protect cmd_q by spin_lock.
- * No irqsave is necessary.
- */
-
-int r8712_init_cmd_priv(struct cmd_priv *pcmdpriv)
-{
- init_completion(&pcmdpriv->cmd_queue_comp);
- init_completion(&pcmdpriv->terminate_cmdthread_comp);
-
- _init_queue(&(pcmdpriv->cmd_queue));
-
- /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
- pcmdpriv->cmd_seq = 1;
- pcmdpriv->cmd_allocated_buf = kmalloc(MAX_CMDSZ + CMDBUFF_ALIGN_SZ,
- GFP_ATOMIC);
- if (!pcmdpriv->cmd_allocated_buf)
- return -ENOMEM;
- pcmdpriv->cmd_buf = pcmdpriv->cmd_allocated_buf + CMDBUFF_ALIGN_SZ -
- ((addr_t)(pcmdpriv->cmd_allocated_buf) &
- (CMDBUFF_ALIGN_SZ - 1));
- pcmdpriv->rsp_allocated_buf = kmalloc(MAX_RSPSZ + 4, GFP_ATOMIC);
- if (!pcmdpriv->rsp_allocated_buf) {
- kfree(pcmdpriv->cmd_allocated_buf);
- pcmdpriv->cmd_allocated_buf = NULL;
- return -ENOMEM;
- }
- pcmdpriv->rsp_buf = pcmdpriv->rsp_allocated_buf + 4 -
- ((addr_t)(pcmdpriv->rsp_allocated_buf) & 3);
- pcmdpriv->cmd_issued_cnt = 0;
- pcmdpriv->cmd_done_cnt = 0;
- pcmdpriv->rsp_cnt = 0;
- return 0;
-}
-
-int r8712_init_evt_priv(struct evt_priv *pevtpriv)
-{
- /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
- pevtpriv->event_seq = 0;
- pevtpriv->evt_allocated_buf = kmalloc(MAX_EVTSZ + 4, GFP_ATOMIC);
-
- if (!pevtpriv->evt_allocated_buf)
- return -ENOMEM;
- pevtpriv->evt_buf = pevtpriv->evt_allocated_buf + 4 -
- ((addr_t)(pevtpriv->evt_allocated_buf) & 3);
- pevtpriv->evt_done_cnt = 0;
- return 0;
-}
-
-void r8712_free_evt_priv(struct evt_priv *pevtpriv)
-{
- kfree(pevtpriv->evt_allocated_buf);
-}
-
-void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv)
-{
- if (pcmdpriv) {
- kfree(pcmdpriv->cmd_allocated_buf);
- kfree(pcmdpriv->rsp_allocated_buf);
- }
-}
-
-/*
- * Calling Context:
- *
- * r8712_enqueue_cmd can only be called between kernel thread,
- * since only spin_lock is used.
- *
- * ISR/Call-Back functions can't call this sub-function.
- *
- */
-
-void r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
-{
- struct __queue *queue;
- unsigned long irqL;
-
- if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag)
- return;
- if (!obj)
- return;
- queue = &pcmdpriv->cmd_queue;
- spin_lock_irqsave(&queue->lock, irqL);
- list_add_tail(&obj->list, &queue->queue);
- spin_unlock_irqrestore(&queue->lock, irqL);
- complete(&pcmdpriv->cmd_queue_comp);
-}
-
-struct cmd_obj *r8712_dequeue_cmd(struct __queue *queue)
-{
- unsigned long irqL;
- struct cmd_obj *obj;
-
- spin_lock_irqsave(&queue->lock, irqL);
- obj = list_first_entry_or_null(&queue->queue,
- struct cmd_obj, list);
- if (obj)
- list_del_init(&obj->list);
- spin_unlock_irqrestore(&queue->lock, irqL);
- return obj;
-}
-
-void r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj)
-{
- unsigned long irqL;
- struct __queue *queue;
-
- if (!obj)
- return;
- if (pcmdpriv->padapter->eeprompriv.bautoload_fail_flag)
- return;
- queue = &pcmdpriv->cmd_queue;
- spin_lock_irqsave(&queue->lock, irqL);
- list_add_tail(&obj->list, &queue->queue);
- spin_unlock_irqrestore(&queue->lock, irqL);
- complete(&pcmdpriv->cmd_queue_comp);
-}
-
-void r8712_free_cmd_obj(struct cmd_obj *pcmd)
-{
- if ((pcmd->cmdcode != _JoinBss_CMD_) &&
- (pcmd->cmdcode != _CreateBss_CMD_))
- kfree(pcmd->parmbuf);
- if (pcmd->rsp) {
- if (pcmd->rspsz != 0)
- kfree(pcmd->rsp);
- }
- kfree(pcmd);
-}
-
-u8 r8712_sitesurvey_cmd(struct _adapter *padapter,
- struct ndis_802_11_ssid *pssid)
- __must_hold(&padapter->mlmepriv.lock)
-{
- struct cmd_obj *ph2c;
- struct sitesurvey_parm *psurveyPara;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return _FAIL;
- psurveyPara = kmalloc(sizeof(*psurveyPara), GFP_ATOMIC);
- if (!psurveyPara) {
- kfree(ph2c);
- return _FAIL;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, psurveyPara,
- GEN_CMD_CODE(_SiteSurvey));
- psurveyPara->bsslimit = cpu_to_le32(48);
- psurveyPara->passive_mode = cpu_to_le32(pmlmepriv->passive_mode);
- psurveyPara->ss_ssidlen = 0;
- memset(psurveyPara->ss_ssid, 0, IW_ESSID_MAX_SIZE + 1);
- if (pssid && pssid->SsidLength) {
- int len = min_t(int, pssid->SsidLength, IW_ESSID_MAX_SIZE);
-
- memcpy(psurveyPara->ss_ssid, pssid->Ssid, len);
- psurveyPara->ss_ssidlen = cpu_to_le32(len);
- }
- set_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
- r8712_enqueue_cmd(pcmdpriv, ph2c);
- mod_timer(&pmlmepriv->scan_to_timer,
- jiffies + msecs_to_jiffies(SCANNING_TIMEOUT));
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_SITE_SURVEY);
- complete(&padapter->rx_filter_ready);
- return _SUCCESS;
-}
-
-int r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset)
-{
- struct cmd_obj *ph2c;
- struct setdatarate_parm *pbsetdataratepara;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return -ENOMEM;
- pbsetdataratepara = kmalloc(sizeof(*pbsetdataratepara), GFP_ATOMIC);
- if (!pbsetdataratepara) {
- kfree(ph2c);
- return -ENOMEM;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, pbsetdataratepara,
- GEN_CMD_CODE(_SetDataRate));
- pbsetdataratepara->mac_id = 5;
- memcpy(pbsetdataratepara->datarates, rateset, NumRates);
- r8712_enqueue_cmd(pcmdpriv, ph2c);
- return 0;
-}
-
-void r8712_set_chplan_cmd(struct _adapter *padapter, int chplan)
-{
- struct cmd_obj *ph2c;
- struct SetChannelPlan_param *psetchplanpara;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- psetchplanpara = kmalloc(sizeof(*psetchplanpara), GFP_ATOMIC);
- if (!psetchplanpara) {
- kfree(ph2c);
- return;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetchplanpara, GEN_CMD_CODE(_SetChannelPlan));
- psetchplanpara->ChannelPlan = chplan;
- r8712_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-int r8712_setrfreg_cmd(struct _adapter *padapter, u8 offset, u32 val)
-{
- struct cmd_obj *ph2c;
- struct writeRF_parm *pwriterfparm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return -ENOMEM;
- pwriterfparm = kmalloc(sizeof(*pwriterfparm), GFP_ATOMIC);
- if (!pwriterfparm) {
- kfree(ph2c);
- return -ENOMEM;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, pwriterfparm, GEN_CMD_CODE(_SetRFReg));
- pwriterfparm->offset = offset;
- pwriterfparm->value = val;
- r8712_enqueue_cmd(pcmdpriv, ph2c);
- return 0;
-}
-
-int r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval)
-{
- struct cmd_obj *ph2c;
- struct readRF_parm *prdrfparm;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return -ENOMEM;
- prdrfparm = kmalloc(sizeof(*prdrfparm), GFP_ATOMIC);
- if (!prdrfparm) {
- kfree(ph2c);
- return -ENOMEM;
- }
- INIT_LIST_HEAD(&ph2c->list);
- ph2c->cmdcode = GEN_CMD_CODE(_GetRFReg);
- ph2c->parmbuf = (unsigned char *)prdrfparm;
- ph2c->cmdsz = sizeof(struct readRF_parm);
- ph2c->rsp = pval;
- ph2c->rspsz = sizeof(struct readRF_rsp);
- prdrfparm->offset = offset;
- r8712_enqueue_cmd(pcmdpriv, ph2c);
- return 0;
-}
-
-void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter,
- struct cmd_obj *pcmd)
-{
- kfree(pcmd->parmbuf);
- kfree(pcmd);
- padapter->mppriv.workparam.bcompleted = true;
-}
-
-void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
-{
- kfree(pcmd->parmbuf);
- kfree(pcmd);
-
- padapter->mppriv.workparam.bcompleted = true;
-}
-
-int r8712_createbss_cmd(struct _adapter *padapter)
-{
- struct cmd_obj *pcmd;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct wlan_bssid_ex *pdev_network =
- &padapter->registrypriv.dev_network;
-
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
- pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd)
- return -ENOMEM;
- INIT_LIST_HEAD(&pcmd->list);
- pcmd->cmdcode = _CreateBss_CMD_;
- pcmd->parmbuf = (unsigned char *)pdev_network;
- pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(pdev_network);
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
- /* notes: translate IELength & Length after assign to cmdsz; */
- pdev_network->Length = pcmd->cmdsz;
- pdev_network->IELength = pdev_network->IELength;
- pdev_network->Ssid.SsidLength = pdev_network->Ssid.SsidLength;
- r8712_enqueue_cmd(pcmdpriv, pcmd);
- return 0;
-}
-
-int r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork)
-{
- struct wlan_bssid_ex *psecnetwork;
- struct cmd_obj *pcmd;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE ndis_network_mode =
- pnetwork->network.InfrastructureMode;
-
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_START_TO_LINK);
- pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd)
- return -ENOMEM;
-
- /* for hidden ap to set fw_state here */
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_ADHOC_STATE) !=
- true) {
- switch (ndis_network_mode) {
- case Ndis802_11IBSS:
- pmlmepriv->fw_state |= WIFI_ADHOC_STATE;
- break;
- case Ndis802_11Infrastructure:
- pmlmepriv->fw_state |= WIFI_STATION_STATE;
- break;
- case Ndis802_11APMode:
- case Ndis802_11AutoUnknown:
- case Ndis802_11InfrastructureMax:
- break;
- }
- }
- psecnetwork = &psecuritypriv->sec_bss;
- memcpy(psecnetwork, &pnetwork->network, sizeof(*psecnetwork));
- psecuritypriv->authenticator_ie[0] = (unsigned char)
- psecnetwork->IELength;
- if ((psecnetwork->IELength - 12) < (256 - 1))
- memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12],
- psecnetwork->IELength - 12);
- else
- memcpy(&psecuritypriv->authenticator_ie[1], &psecnetwork->IEs[12], (256 - 1));
- psecnetwork->IELength = 0;
- /*
- * If the driver wants to use the bssid to create the connection.
- * If not, we copy the connecting AP's MAC address to it so that
- * the driver just has the bssid information for PMKIDList searching.
- */
- if (!pmlmepriv->assoc_by_bssid)
- ether_addr_copy(&pmlmepriv->assoc_bssid[0],
- &pnetwork->network.MacAddress[0]);
- psecnetwork->IELength = r8712_restruct_sec_ie(padapter, &pnetwork->network.IEs[0],
- &psecnetwork->IEs[0], pnetwork->network.IELength);
- pqospriv->qos_option = 0;
- if (pregistrypriv->wmm_enable) {
- u32 tmp_len;
-
- tmp_len = r8712_restruct_wmm_ie(padapter, &pnetwork->network.IEs[0],
- &psecnetwork->IEs[0], pnetwork->network.IELength,
- psecnetwork->IELength);
- if (psecnetwork->IELength != tmp_len) {
- psecnetwork->IELength = tmp_len;
- pqospriv->qos_option = 1; /* WMM IE in beacon */
- } else {
- pqospriv->qos_option = 0; /* no WMM IE in beacon */
- }
- }
- if (pregistrypriv->ht_enable) {
- /*
- * For WEP mode, we will use the bg mode to do the connection
- * to avoid some IOT issues, especially for Realtek 8192u
- * SoftAP.
- */
- if ((padapter->securitypriv.PrivacyAlgrthm != _WEP40_) &&
- (padapter->securitypriv.PrivacyAlgrthm != _WEP104_)) {
- /* restructure_ht_ie */
- r8712_restructure_ht_ie(padapter,
- &pnetwork->network.IEs[0],
- &psecnetwork->IEs[0],
- pnetwork->network.IELength,
- &psecnetwork->IELength);
- }
- }
- psecuritypriv->supplicant_ie[0] = (u8)psecnetwork->IELength;
- if (psecnetwork->IELength < 255)
- memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
- psecnetwork->IELength);
- else
- memcpy(&psecuritypriv->supplicant_ie[1], &psecnetwork->IEs[0],
- 255);
- /* get cmdsz before endian conversion */
- pcmd->cmdsz = r8712_get_wlan_bssid_ex_sz(psecnetwork);
-#ifdef __BIG_ENDIAN
- /* wlan_network endian conversion */
- psecnetwork->Length = cpu_to_le32(psecnetwork->Length);
- psecnetwork->Ssid.SsidLength = cpu_to_le32(psecnetwork->Ssid.SsidLength);
- psecnetwork->Privacy = cpu_to_le32(psecnetwork->Privacy);
- psecnetwork->Rssi = cpu_to_le32(psecnetwork->Rssi);
- psecnetwork->NetworkTypeInUse = cpu_to_le32(psecnetwork->NetworkTypeInUse);
- psecnetwork->Configuration.ATIMWindow = cpu_to_le32(psecnetwork->Configuration.ATIMWindow);
- psecnetwork->Configuration.BeaconPeriod = cpu_to_le32(psecnetwork->Configuration.BeaconPeriod);
- psecnetwork->Configuration.DSConfig = cpu_to_le32(psecnetwork->Configuration.DSConfig);
- psecnetwork->Configuration.FHConfig.DwellTime = cpu_to_le32(psecnetwork->Configuration.FHConfig.DwellTime);
- psecnetwork->Configuration.FHConfig.HopPattern = cpu_to_le32(psecnetwork->Configuration.FHConfig.HopPattern);
- psecnetwork->Configuration.FHConfig.HopSet = cpu_to_le32(psecnetwork->Configuration.FHConfig.HopSet);
- psecnetwork->Configuration.FHConfig.Length = cpu_to_le32(psecnetwork->Configuration.FHConfig.Length);
- psecnetwork->Configuration.Length = cpu_to_le32(psecnetwork->Configuration.Length);
- psecnetwork->InfrastructureMode = cpu_to_le32(psecnetwork->InfrastructureMode);
- psecnetwork->IELength = cpu_to_le32(psecnetwork->IELength);
-#endif
- INIT_LIST_HEAD(&pcmd->list);
- pcmd->cmdcode = _JoinBss_CMD_;
- pcmd->parmbuf = (unsigned char *)psecnetwork;
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
- r8712_enqueue_cmd(pcmdpriv, pcmd);
- return 0;
-}
-
-void r8712_disassoc_cmd(struct _adapter *padapter) /* for sta_mode */
-{
- struct cmd_obj *pdisconnect_cmd;
- struct disconnect_parm *pdisconnect;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- pdisconnect_cmd = kmalloc(sizeof(*pdisconnect_cmd), GFP_ATOMIC);
- if (!pdisconnect_cmd)
- return;
- pdisconnect = kmalloc(sizeof(*pdisconnect), GFP_ATOMIC);
- if (!pdisconnect) {
- kfree(pdisconnect_cmd);
- return;
- }
- init_h2fwcmd_w_parm_no_rsp(pdisconnect_cmd, pdisconnect, _DisConnect_CMD_);
- r8712_enqueue_cmd(pcmdpriv, pdisconnect_cmd);
-}
-
-void r8712_setopmode_cmd(struct _adapter *padapter,
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
-{
- struct cmd_obj *ph2c;
- struct setopmode_parm *psetop;
-
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- psetop = kmalloc(sizeof(*psetop), GFP_ATOMIC);
- if (!psetop) {
- kfree(ph2c);
- return;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetop, _SetOpMode_CMD_);
- psetop->mode = (u8)networktype;
- r8712_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-void r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key)
-{
- struct cmd_obj *ph2c;
- struct set_stakey_parm *psetstakey_para;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct set_stakey_rsp *psetstakey_rsp = NULL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct sta_info *sta = (struct sta_info *)psta;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- psetstakey_para = kmalloc(sizeof(*psetstakey_para), GFP_ATOMIC);
- if (!psetstakey_para) {
- kfree(ph2c);
- return;
- }
- psetstakey_rsp = kmalloc(sizeof(*psetstakey_rsp), GFP_ATOMIC);
- if (!psetstakey_rsp) {
- kfree(ph2c);
- kfree(psetstakey_para);
- return;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetstakey_para, _SetStaKey_CMD_);
- ph2c->rsp = (u8 *)psetstakey_rsp;
- ph2c->rspsz = sizeof(struct set_stakey_rsp);
- ether_addr_copy(psetstakey_para->addr, sta->hwaddr);
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- psetstakey_para->algorithm = (unsigned char)
- psecuritypriv->PrivacyAlgrthm;
- else
- GET_ENCRY_ALGO(psecuritypriv, sta, psetstakey_para->algorithm, false);
- if (unicast_key)
- memcpy(&psetstakey_para->key, &sta->x_UncstKey, 16);
- else
- memcpy(&psetstakey_para->key,
- &psecuritypriv->XGrpKey[psecuritypriv->XGrpKeyid - 1].skey,
- 16);
- r8712_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-void r8712_setMacAddr_cmd(struct _adapter *padapter, const u8 *mac_addr)
-{
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct cmd_obj *ph2c;
- struct SetMacAddr_param *psetMacAddr_para;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- psetMacAddr_para = kmalloc(sizeof(*psetMacAddr_para), GFP_ATOMIC);
- if (!psetMacAddr_para) {
- kfree(ph2c);
- return;
- }
- init_h2fwcmd_w_parm_no_rsp(ph2c, psetMacAddr_para, _SetMacAddress_CMD_);
- ether_addr_copy(psetMacAddr_para->MacAddr, mac_addr);
- r8712_enqueue_cmd(pcmdpriv, ph2c);
-}
-
-void r8712_addbareq_cmd(struct _adapter *padapter, u8 tid)
-{
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
- struct cmd_obj *ph2c;
- struct addBaReq_parm *paddbareq_parm;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- paddbareq_parm = kmalloc(sizeof(*paddbareq_parm), GFP_ATOMIC);
- if (!paddbareq_parm) {
- kfree(ph2c);
- return;
- }
- paddbareq_parm->tid = tid;
- init_h2fwcmd_w_parm_no_rsp(ph2c, paddbareq_parm, GEN_CMD_CODE(_AddBAReq));
- r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
-}
-
-void r8712_wdg_wk_cmd(struct _adapter *padapter)
-{
- struct cmd_obj *ph2c;
- struct drvint_cmd_parm *pdrvintcmd_param;
- struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- pdrvintcmd_param = kmalloc(sizeof(*pdrvintcmd_param), GFP_ATOMIC);
- if (!pdrvintcmd_param) {
- kfree(ph2c);
- return;
- }
- pdrvintcmd_param->i_cid = WDG_WK_CID;
- pdrvintcmd_param->sz = 0;
- pdrvintcmd_param->pbuf = NULL;
- init_h2fwcmd_w_parm_no_rsp(ph2c, pdrvintcmd_param, _DRV_INT_CMD_);
- r8712_enqueue_cmd_ex(pcmdpriv, ph2c);
-}
-
-void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (pcmd->res != H2C_SUCCESS)
- clr_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_disassoc_cmd_callback(struct _adapter *padapter,
- struct cmd_obj *pcmd)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (pcmd->res != H2C_SUCCESS) {
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- set_fwstate(pmlmepriv, _FW_LINKED);
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- return;
- }
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (pcmd->res != H2C_SUCCESS)
- mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1));
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_createbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
-{
- unsigned long irqL;
- struct sta_info *psta = NULL;
- struct wlan_network *pwlan = NULL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pnetwork = (struct wlan_bssid_ex *)pcmd->parmbuf;
- struct wlan_network *tgt_network = &(pmlmepriv->cur_network);
-
- if (pcmd->res != H2C_SUCCESS)
- mod_timer(&pmlmepriv->assoc_timer, jiffies + msecs_to_jiffies(1));
- del_timer(&pmlmepriv->assoc_timer);
-#ifdef __BIG_ENDIAN
- /* endian_convert */
- pnetwork->Length = le32_to_cpu(pnetwork->Length);
- pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
- pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
- pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
- pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
- pnetwork->Configuration.ATIMWindow = le32_to_cpu(pnetwork->Configuration.ATIMWindow);
- pnetwork->Configuration.DSConfig = le32_to_cpu(pnetwork->Configuration.DSConfig);
- pnetwork->Configuration.FHConfig.DwellTime = le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
- pnetwork->Configuration.FHConfig.HopPattern = le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
- pnetwork->Configuration.FHConfig.HopSet = le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
- pnetwork->Configuration.FHConfig.Length = le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
- pnetwork->Configuration.Length = le32_to_cpu(pnetwork->Configuration.Length);
- pnetwork->InfrastructureMode = le32_to_cpu(pnetwork->InfrastructureMode);
- pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
-#endif
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if ((pmlmepriv->fw_state) & WIFI_AP_STATE) {
- psta = r8712_get_stainfo(&padapter->stapriv, pnetwork->MacAddress);
- if (!psta) {
- psta = r8712_alloc_stainfo(&padapter->stapriv, pnetwork->MacAddress);
- if (!psta)
- goto createbss_cmd_fail;
- }
- r8712_indicate_connect(padapter);
- } else {
- pwlan = _r8712_alloc_network(pmlmepriv);
- if (!pwlan) {
- pwlan = r8712_get_oldest_wlan_network(&pmlmepriv->scanned_queue);
- if (!pwlan)
- goto createbss_cmd_fail;
- pwlan->last_scanned = jiffies;
- } else {
- list_add_tail(&(pwlan->list), &pmlmepriv->scanned_queue.queue);
- }
- pnetwork->Length = r8712_get_wlan_bssid_ex_sz(pnetwork);
- memcpy(&(pwlan->network), pnetwork, pnetwork->Length);
- pwlan->fixed = true;
- memcpy(&tgt_network->network, pnetwork, (r8712_get_wlan_bssid_ex_sz(pnetwork)));
- if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
- pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
- /*
- * we will set _FW_LINKED when there is one more sat to
- * join us (stassoc_event_callback)
- */
- }
-createbss_cmd_fail:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd)
-{
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct set_stakey_rsp *psetstakey_rsp = (struct set_stakey_rsp *) (pcmd->rsp);
- struct sta_info *psta = r8712_get_stainfo(pstapriv, psetstakey_rsp->addr);
-
- if (!psta)
- goto exit;
- psta->aid = psta->mac_id = psetstakey_rsp->keyid; /*CAM_ID(CAM_ENTRY)*/
-exit:
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter,
- struct cmd_obj *pcmd)
-{
- unsigned long irqL;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct set_assocsta_parm *passocsta_parm = (struct set_assocsta_parm *)(pcmd->parmbuf);
- struct set_assocsta_rsp *passocsta_rsp = (struct set_assocsta_rsp *) (pcmd->rsp);
- struct sta_info *psta = r8712_get_stainfo(pstapriv, passocsta_parm->addr);
-
- if (!psta)
- return;
- psta->aid = psta->mac_id = passocsta_rsp->cam_id;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if ((check_fwstate(pmlmepriv, WIFI_MP_STATE)) && (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)))
- pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
- set_fwstate(pmlmepriv, _FW_LINKED);
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- r8712_free_cmd_obj(pcmd);
-}
-
-void r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl, u32 tryPktCnt,
- u32 tryPktInterval, u32 firstStageTO)
-{
- struct cmd_obj *ph2c;
- struct DisconnectCtrlEx_param *param;
- struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
-
- ph2c = kmalloc(sizeof(*ph2c), GFP_ATOMIC);
- if (!ph2c)
- return;
- param = kzalloc(sizeof(*param), GFP_ATOMIC);
- if (!param) {
- kfree(ph2c);
- return;
- }
-
- param->EnableDrvCtrl = (unsigned char)enableDrvCtrl;
- param->TryPktCnt = (unsigned char)tryPktCnt;
- param->TryPktInterval = (unsigned char)tryPktInterval;
- param->FirstStageTO = (unsigned int)firstStageTO;
-
- init_h2fwcmd_w_parm_no_rsp(ph2c, param, GEN_CMD_CODE(_DisconnectCtrlEx));
- r8712_enqueue_cmd(pcmdpriv, ph2c);
-}
diff --git a/drivers/staging/rtl8712/rtl871x_cmd.h b/drivers/staging/rtl8712/rtl871x_cmd.h
deleted file mode 100644
index 268844af57f0..000000000000
--- a/drivers/staging/rtl8712/rtl871x_cmd.h
+++ /dev/null
@@ -1,750 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_CMD_H_
-#define __RTL871X_CMD_H_
-
-#include "wlan_bssdef.h"
-#include "rtl871x_rf.h"
-#define C2H_MEM_SZ (16*1024)
-
-#include "osdep_service.h"
-#include "ieee80211.h"
-
-#define FREE_CMDOBJ_SZ 128
-#define MAX_CMDSZ 512
-#define MAX_RSPSZ 512
-#define MAX_EVTSZ 1024
-#define CMDBUFF_ALIGN_SZ 512
-
-struct cmd_obj {
- u16 cmdcode;
- u8 res;
- u8 *parmbuf;
- u32 cmdsz;
- u8 *rsp;
- u32 rspsz;
- struct list_head list;
-};
-
-struct cmd_priv {
- struct completion cmd_queue_comp;
- struct completion terminate_cmdthread_comp;
- struct __queue cmd_queue;
- u8 cmd_seq;
- u8 *cmd_buf; /*shall be non-paged, and 4 bytes aligned*/
- u8 *cmd_allocated_buf;
- u8 *rsp_buf; /*shall be non-paged, and 4 bytes aligned*/
- u8 *rsp_allocated_buf;
- u32 cmd_issued_cnt;
- u32 cmd_done_cnt;
- u32 rsp_cnt;
- struct _adapter *padapter;
-};
-
-struct evt_obj {
- u16 evtcode;
- u8 res;
- u8 *parmbuf;
- u32 evtsz;
- struct list_head list;
-};
-
-struct evt_priv {
- struct __queue evt_queue;
- u8 event_seq;
- u8 *evt_buf; /*shall be non-paged, and 4 bytes aligned*/
- u8 *evt_allocated_buf;
- u32 evt_done_cnt;
-};
-
-#define init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code) \
-do {\
- INIT_LIST_HEAD(&pcmd->list);\
- pcmd->cmdcode = code;\
- pcmd->parmbuf = (u8 *)(pparm);\
- pcmd->cmdsz = sizeof(*pparm);\
- pcmd->rsp = NULL;\
- pcmd->rspsz = 0;\
-} while (0)
-
-void r8712_enqueue_cmd(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
-void r8712_enqueue_cmd_ex(struct cmd_priv *pcmdpriv, struct cmd_obj *obj);
-struct cmd_obj *r8712_dequeue_cmd(struct __queue *queue);
-void r8712_free_cmd_obj(struct cmd_obj *pcmd);
-int r8712_cmd_thread(void *context);
-int r8712_init_cmd_priv(struct cmd_priv *pcmdpriv);
-void r8712_free_cmd_priv(struct cmd_priv *pcmdpriv);
-int r8712_init_evt_priv(struct evt_priv *pevtpriv);
-void r8712_free_evt_priv(struct evt_priv *pevtpriv);
-
-enum rtl871x_drvint_cid {
- NONE_WK_CID,
- WDG_WK_CID,
- MAX_WK_CID
-};
-
-enum RFINTFS {
- SWSI,
- HWSI,
- HWPI,
-};
-
-/*
- * Caller Mode: Infra, Ad-HoC(C)
- * Notes: To enter USB suspend mode
- * Command Mode
- */
-struct usb_suspend_parm {
- u32 action; /* 1: sleep, 0:resume */
-};
-
-/*
- * Caller Mode: Infra, Ad-HoC(C)
- * Notes: To disconnect the current associated BSS
- * Command Mode
- */
-struct disconnect_parm {
- u32 rsvd;
-};
-
-/*
- * Caller Mode: AP, Ad-HoC, Infra
- * Notes: To set the NIC mode of RTL8711
- * Command Mode
- * The definition of mode:
- *
- * #define IW_MODE_AUTO 0 // Let the driver decides which AP to join
- * #define IW_MODE_ADHOC 1 // Single cell network (Ad-Hoc Clients)
- * #define IW_MODE_INFRA 2 // Multi cell network, roaming, ..
- * #define IW_MODE_MASTER 3 // Synchronisation master or AP
- * #define IW_MODE_REPEAT 4 // Wireless Repeater (forwarder)
- * #define IW_MODE_SECOND 5 // Secondary master/repeater (backup)
- * #define IW_MODE_MONITOR 6 // Passive monitor (listen only)
- */
-struct setopmode_parm {
- u8 mode;
- u8 rsvd[3];
-};
-
-/*
- * Caller Mode: AP, Ad-HoC, Infra
- * Notes: To ask RTL8711 performing site-survey
- * Command-Event Mode
- */
-struct sitesurvey_parm {
- __le32 passive_mode; /*active: 1, passive: 0 */
- __le32 bsslimit; /* 1 ~ 48 */
- __le32 ss_ssidlen;
- u8 ss_ssid[IW_ESSID_MAX_SIZE + 1];
-};
-
-/*
- * Caller Mode: Any
- * Notes: To set the auth type of RTL8711. open/shared/802.1x
- * Command Mode
- */
-struct setauth_parm {
- u8 mode; /*0: legacy open, 1: legacy shared 2: 802.1x*/
- u8 _1x; /*0: PSK, 1: TLS*/
- u8 rsvd[2];
-};
-
-/*
- * Caller Mode: Infra
- * a. algorithm: wep40, wep104, tkip & aes
- * b. keytype: grp key/unicast key
- * c. key contents
- *
- * when shared key ==> keyid is the camid
- * when 802.1x ==> keyid [0:1] ==> grp key
- * when 802.1x ==> keyid > 2 ==> unicast key
- */
-struct setkey_parm {
- u8 algorithm; /* encryption algorithm, could be none, wep40,
- * TKIP, CCMP, wep104
- */
- u8 keyid;
- u8 grpkey; /* 1: this is the grpkey for 802.1x.
- * 0: this is the unicast key for 802.1x
- */
- u8 key[16]; /* this could be 40 or 104 */
-};
-
-/*
- * When in AP or Ad-Hoc mode, this is used to
- * allocate an sw/hw entry for a newly associated sta.
- * Command
- * when shared key ==> algorithm/keyid
- */
-struct set_stakey_parm {
- u8 addr[ETH_ALEN];
- u8 algorithm;
- u8 key[16];
-};
-
-struct set_stakey_rsp {
- u8 addr[ETH_ALEN];
- u8 keyid;
- u8 rsvd;
-};
-
-struct SetMacAddr_param {
- u8 MacAddr[ETH_ALEN];
-};
-
-/*
- * Caller Ad-Hoc/AP
- *
- * Command -Rsp(AID == CAMID) mode
- *
- * This is to force fw to add an sta_data entry per driver's request.
- *
- * FW will write an cam entry associated with it.
- *
- */
-struct set_assocsta_parm {
- u8 addr[ETH_ALEN];
-};
-
-struct set_assocsta_rsp {
- u8 cam_id;
- u8 rsvd[3];
-};
-
-/*
- * Caller Ad-Hoc/AP
- *
- * Command mode
- *
- * This is to force fw to del an sta_data entry per driver's request
- *
- * FW will invalidate the cam entry associated with it.
- *
- */
-struct del_assocsta_parm {
- u8 addr[ETH_ALEN];
-};
-
-/*
- * Caller Mode: AP/Ad-HoC(M)
- *
- * Notes: To notify fw that given staid has changed its power state
- *
- * Command Mode
- *
- */
-struct setstapwrstate_parm {
- u8 staid;
- u8 status;
- u8 hwaddr[6];
-};
-
-/*
- * Caller Mode: Any
- *
- * Notes: To setup the basic rate of RTL8711
- *
- * Command Mode
- *
- */
-struct setbasicrate_parm {
- u8 basicrates[NumRates];
-};
-
-/*
- * Caller Mode: Any
- *
- * Notes: To read the current basic rate
- *
- * Command-Rsp Mode
- *
- */
-struct getbasicrate_parm {
- u32 rsvd;
-};
-
-struct getbasicrate_rsp {
- u8 basicrates[NumRates];
-};
-
-/*
- * Caller Mode: Any
- *
- * Notes: To setup the data rate of RTL8711
- *
- * Command Mode
- *
- */
-struct setdatarate_parm {
- u8 mac_id;
- u8 datarates[NumRates];
-};
-
-enum _RT_CHANNEL_DOMAIN {
- RT_CHANNEL_DOMAIN_FCC = 0,
- RT_CHANNEL_DOMAIN_IC = 1,
- RT_CHANNEL_DOMAIN_ETSI = 2,
- RT_CHANNEL_DOMAIN_SPAIN = 3,
- RT_CHANNEL_DOMAIN_FRANCE = 4,
- RT_CHANNEL_DOMAIN_MKK = 5,
- RT_CHANNEL_DOMAIN_MKK1 = 6,
- RT_CHANNEL_DOMAIN_ISRAEL = 7,
- RT_CHANNEL_DOMAIN_TELEC = 8,
-
- /* Be compatible with old channel plan. No good! */
- RT_CHANNEL_DOMAIN_MIC = 9,
- RT_CHANNEL_DOMAIN_GLOBAL_DOAMIN = 10,
- RT_CHANNEL_DOMAIN_WORLD_WIDE_13 = 11,
- RT_CHANNEL_DOMAIN_TELEC_NETGEAR = 12,
-
- RT_CHANNEL_DOMAIN_NCC = 13,
- RT_CHANNEL_DOMAIN_5G = 14,
- RT_CHANNEL_DOMAIN_5G_40M = 15,
- /*===== Add new channel plan above this line===============*/
- RT_CHANNEL_DOMAIN_MAX,
-};
-
-struct SetChannelPlan_param {
- enum _RT_CHANNEL_DOMAIN ChannelPlan;
-};
-
-/*
- * Caller Mode: Any
- *
- * Notes: To read the current data rate
- *
- * Command-Rsp Mode
- *
- */
-struct getdatarate_parm {
- u32 rsvd;
-
-};
-
-struct getdatarate_rsp {
- u8 datarates[NumRates];
-};
-
-/*
- * Caller Mode: Any
- * AP: AP can use the info for the contents of beacon frame
- * Infra: STA can use the info when sitesurveying
- * Ad-HoC(M): Like AP
- * Ad-HoC(C): Like STA
- *
- *
- * Notes: To set the phy capability of the NIC
- *
- * Command Mode
- *
- */
-
-/*
- * Caller Mode: Any
- *
- * Notes: To set the channel/modem/band
- * This command will be used when channel/modem/band is changed.
- *
- * Command Mode
- *
- */
-/*
- * Caller Mode: Any
- *
- * Notes: To get the current setting of channel/modem/band
- *
- * Command-Rsp Mode
- *
- */
-struct getphy_rsp {
- u8 rfchannel;
- u8 modem;
-};
-
-struct readBB_parm {
- u8 offset;
-};
-
-struct readBB_rsp {
- u8 value;
-};
-
-struct readTSSI_parm {
- u8 offset;
-};
-
-struct readTSSI_rsp {
- u8 value;
-};
-
-struct writeBB_parm {
- u8 offset;
- u8 value;
-};
-
-struct writePTM_parm {
- u8 type;
-};
-
-struct readRF_parm {
- u8 offset;
-};
-
-struct readRF_rsp {
- u32 value;
-};
-
-struct writeRF_parm {
- u32 offset;
- u32 value;
-};
-
-struct setrfintfs_parm {
- u8 rfintfs;
-};
-
-struct getrfintfs_parm {
- u8 rfintfs;
-};
-
-/*
- * Notes: This command is used for H2C/C2H loopback testing
- *
- * mac[0] == 0
- * ==> CMD mode, return H2C_SUCCESS.
- * The following condition must be true under CMD mode
- * mac[1] == mac[4], mac[2] == mac[3], mac[0]=mac[5]= 0;
- * s0 == 0x1234, s1 == 0xabcd, w0 == 0x78563412, w1 == 0x5aa5def7;
- * s2 == (b1 << 8 | b0);
- *
- * mac[0] == 1
- * ==> CMD_RSP mode, return H2C_SUCCESS_RSP
- *
- * The rsp layout shall be:
- * rsp: parm:
- * mac[0] = mac[5];
- * mac[1] = mac[4];
- * mac[2] = mac[3];
- * mac[3] = mac[2];
- * mac[4] = mac[1];
- * mac[5] = mac[0];
- * s0 = s1;
- * s1 = swap16(s0);
- * w0 = swap32(w1);
- * b0 = b1
- * s2 = s0 + s1
- * b1 = b0
- * w1 = w0
- *
- * mac[0] == 2
- * ==> CMD_EVENT mode, return H2C_SUCCESS
- * The event layout shall be:
- * event: parm:
- * mac[0] = mac[5];
- * mac[1] = mac[4];
- * mac[2] = event's sequence number, starting from 1 to parm's marc[3]
- * mac[3] = mac[2];
- * mac[4] = mac[1];
- * mac[5] = mac[0];
- * s0 = swap16(s0) - event.mac[2];
- * s1 = s1 + event.mac[2];
- * w0 = swap32(w0);
- * b0 = b1
- * s2 = s0 + event.mac[2]
- * b1 = b0
- * w1 = swap32(w1) - event.mac[2];
- *
- * parm->mac[3] is the total event counts that host requested.
- *
- *
- * event will be the same with the cmd's param.
- *
- */
-
-/* CMD param Formart for DRV INTERNAL CMD HDL*/
-struct drvint_cmd_parm {
- int i_cid; /*internal cmd id*/
- int sz; /* buf sz*/
- unsigned char *pbuf;
-};
-
-/*------------------- Below are used for RF/BB tuning ---------------------*/
-
-struct setantenna_parm {
- u8 tx_antset;
- u8 rx_antset;
- u8 tx_antenna;
- u8 rx_antenna;
-};
-
-struct enrateadaptive_parm {
- u32 en;
-};
-
-struct settxagctbl_parm {
- u32 txagc[MAX_RATES_LENGTH];
-};
-
-struct gettxagctbl_parm {
- u32 rsvd;
-};
-
-struct gettxagctbl_rsp {
- u32 txagc[MAX_RATES_LENGTH];
-};
-
-struct setagcctrl_parm {
- u32 agcctrl; /* 0: pure hw, 1: fw */
-};
-
-struct setssup_parm {
- u32 ss_ForceUp[MAX_RATES_LENGTH];
-};
-
-struct getssup_parm {
- u32 rsvd;
-};
-
-struct getssup_rsp {
- u8 ss_ForceUp[MAX_RATES_LENGTH];
-};
-
-struct setssdlevel_parm {
- u8 ss_DLevel[MAX_RATES_LENGTH];
-};
-
-struct getssdlevel_parm {
- u32 rsvd;
-};
-
-struct getssdlevel_rsp {
- u8 ss_DLevel[MAX_RATES_LENGTH];
-};
-
-struct setssulevel_parm {
- u8 ss_ULevel[MAX_RATES_LENGTH];
-};
-
-struct getssulevel_parm {
- u32 rsvd;
-};
-
-struct getssulevel_rsp {
- u8 ss_ULevel[MAX_RATES_LENGTH];
-};
-
-struct setcountjudge_parm {
- u8 count_judge[MAX_RATES_LENGTH];
-};
-
-struct getcountjudge_parm {
- u32 rsvd;
-};
-
-struct getcountjudge_rsp {
- u8 count_judge[MAX_RATES_LENGTH];
-};
-
-struct setpwrmode_parm {
- u8 mode;
- u8 flag_low_traffic_en;
- u8 flag_lpnav_en;
- u8 flag_rf_low_snr_en;
- u8 flag_dps_en; /* 1: dps, 0: 32k */
- u8 bcn_rx_en;
- u8 bcn_pass_cnt; /* fw report one beacon information to
- * driver when it receives bcn_pass_cnt
- * beacons.
- */
- u8 bcn_to; /* beacon TO (ms). ¡§=0¡¨ no limit.*/
- u16 bcn_itv;
- u8 app_itv; /* only for VOIP mode. */
- u8 awake_bcn_itv;
- u8 smart_ps;
- u8 bcn_pass_time; /* unit: 100ms */
-};
-
-struct setatim_parm {
- u8 op; /*0: add, 1:del*/
- u8 txid; /* id of dest station.*/
-};
-
-struct setratable_parm {
- u8 ss_ForceUp[NumRates];
- u8 ss_ULevel[NumRates];
- u8 ss_DLevel[NumRates];
- u8 count_judge[NumRates];
-};
-
-struct getratable_parm {
- uint rsvd;
-};
-
-struct getratable_rsp {
- u8 ss_ForceUp[NumRates];
- u8 ss_ULevel[NumRates];
- u8 ss_DLevel[NumRates];
- u8 count_judge[NumRates];
-};
-
-/*to get TX,RX retry count*/
-struct gettxretrycnt_parm {
- unsigned int rsvd;
-};
-
-struct gettxretrycnt_rsp {
- unsigned long tx_retrycnt;
-};
-
-struct getrxretrycnt_parm {
- unsigned int rsvd;
-};
-
-struct getrxretrycnt_rsp {
- unsigned long rx_retrycnt;
-};
-
-/*to get BCNOK,BCNERR count*/
-struct getbcnokcnt_parm {
- unsigned int rsvd;
-};
-
-struct getbcnokcnt_rsp {
- unsigned long bcnokcnt;
-};
-
-struct getbcnerrcnt_parm {
- unsigned int rsvd;
-};
-
-struct getbcnerrcnt_rsp {
- unsigned long bcnerrcnt;
-};
-
-/* to get current TX power level*/
-struct getcurtxpwrlevel_parm {
- unsigned int rsvd;
-};
-
-struct getcurtxpwrlevel_rsp {
- unsigned short tx_power;
-};
-
-/*dynamic on/off DIG*/
-struct setdig_parm {
- unsigned char dig_on; /* 1:on , 0:off */
-};
-
-/*dynamic on/off RA*/
-struct setra_parm {
- unsigned char ra_on; /* 1:on , 0:off */
-};
-
-struct setprobereqextraie_parm {
- unsigned char e_id;
- unsigned char ie_len;
- unsigned char ie[];
-};
-
-struct setassocreqextraie_parm {
- unsigned char e_id;
- unsigned char ie_len;
- unsigned char ie[];
-};
-
-struct setproberspextraie_parm {
- unsigned char e_id;
- unsigned char ie_len;
- unsigned char ie[];
-};
-
-struct setassocrspextraie_parm {
- unsigned char e_id;
- unsigned char ie_len;
- unsigned char ie[];
-};
-
-struct addBaReq_parm {
- unsigned int tid;
-};
-
-/*H2C Handler index: 46 */
-struct SetChannel_parm {
- u32 curr_ch;
-};
-
-/*H2C Handler index: 61 */
-struct DisconnectCtrlEx_param {
- /* MAXTIME = (2 * FirstStageTO) + (TryPktCnt * TryPktInterval) */
- unsigned char EnableDrvCtrl;
- unsigned char TryPktCnt;
- unsigned char TryPktInterval; /* Unit: ms */
- unsigned char rsvd;
- unsigned int FirstStageTO; /* Unit: ms */
-};
-
-#define GEN_CMD_CODE(cmd) cmd ## _CMD_
-
-/*
- * Result:
- * 0x00: success
- * 0x01: success, and check Response.
- * 0x02: cmd ignored due to duplicated sequence number
- * 0x03: cmd dropped due to invalid cmd code
- * 0x04: reserved.
- */
-
-#define H2C_RSP_OFFSET 512
-#define H2C_SUCCESS 0x00
-#define H2C_SUCCESS_RSP 0x01
-#define H2C_DUPLICATED 0x02
-#define H2C_DROPPED 0x03
-#define H2C_PARAMETERS_ERROR 0x04
-#define H2C_REJECTED 0x05
-#define H2C_CMD_OVERFLOW 0x06
-#define H2C_RESERVED 0x07
-
-void r8712_setMacAddr_cmd(struct _adapter *padapter, const u8 *mac_addr);
-u8 r8712_sitesurvey_cmd(struct _adapter *padapter, struct ndis_802_11_ssid *pssid);
-int r8712_createbss_cmd(struct _adapter *padapter);
-void r8712_setstakey_cmd(struct _adapter *padapter, u8 *psta, u8 unicast_key);
-int r8712_joinbss_cmd(struct _adapter *padapter, struct wlan_network *pnetwork);
-void r8712_disassoc_cmd(struct _adapter *padapter);
-void r8712_setopmode_cmd(struct _adapter *padapter, enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype);
-int r8712_setdatarate_cmd(struct _adapter *padapter, u8 *rateset);
-void r8712_set_chplan_cmd(struct _adapter *padapter, int chplan);
-int r8712_getrfreg_cmd(struct _adapter *padapter, u8 offset, u8 *pval);
-int r8712_setrfreg_cmd(struct _adapter *padapter, u8 offset, u32 val);
-void r8712_addbareq_cmd(struct _adapter *padapter, u8 tid);
-void r8712_wdg_wk_cmd(struct _adapter *padapter);
-void r8712_survey_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_disassoc_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_joinbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_createbss_cmd_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_getbbrfreg_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_readtssi_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_setstaKey_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_setassocsta_cmdrsp_callback(struct _adapter *padapter, struct cmd_obj *pcmd);
-void r8712_disconnectCtrlEx_cmd(struct _adapter *adapter, u32 enableDrvCtrl, u32 tryPktCnt,
- u32 tryPktInterval, u32 firstStageTO);
-
-struct _cmd_callback {
- u32 cmd_code;
- void (*callback)(struct _adapter *padapter, struct cmd_obj *cmd);
-};
-
-#include "rtl8712_cmd.h"
-
-#endif /* _CMD_H_ */
-
diff --git a/drivers/staging/rtl8712/rtl871x_debug.h b/drivers/staging/rtl8712/rtl871x_debug.h
deleted file mode 100644
index 69c631af2a2a..000000000000
--- a/drivers/staging/rtl8712/rtl871x_debug.h
+++ /dev/null
@@ -1,130 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_DEBUG_H__
-#define __RTL871X_DEBUG_H__
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#define _drv_emerg_ 1
-#define _drv_alert_ 2
-#define _drv_crit_ 3
-#define _drv_err_ 4
-#define _drv_warning_ 5
-#define _drv_notice_ 6
-#define _drv_info_ 7
-#define _drv_dump_ 8
-#define _drv_debug_ 9
-
-#define _module_rtl871x_xmit_c_ BIT(0)
-#define _module_xmit_osdep_c_ BIT(1)
-#define _module_rtl871x_recv_c_ BIT(2)
-#define _module_recv_osdep_c_ BIT(3)
-#define _module_rtl871x_mlme_c_ BIT(4)
-#define _module_mlme_osdep_c_ BIT(5)
-#define _module_rtl871x_sta_mgt_c_ BIT(6)
-#define _module_rtl871x_cmd_c_ BIT(7)
-#define _module_cmd_osdep_c_ BIT(8)
-#define _module_rtl871x_io_c_ BIT(9)
-#define _module_io_osdep_c_ BIT(10)
-#define _module_os_intfs_c_ BIT(11)
-#define _module_rtl871x_security_c_ BIT(12)
-#define _module_rtl871x_eeprom_c_ BIT(13)
-#define _module_hal_init_c_ BIT(14)
-#define _module_hci_hal_init_c_ BIT(15)
-#define _module_rtl871x_ioctl_c_ BIT(16)
-#define _module_rtl871x_ioctl_set_c_ BIT(17)
-#define _module_rtl871x_pwrctrl_c_ BIT(19)
-#define _module_hci_intfs_c_ BIT(20)
-#define _module_hci_ops_c_ BIT(21)
-#define _module_osdep_service_c_ BIT(22)
-#define _module_rtl871x_mp_ioctl_c_ BIT(23)
-#define _module_hci_ops_os_c_ BIT(24)
-#define _module_rtl871x_ioctl_os_c BIT(25)
-#define _module_rtl8712_cmd_c_ BIT(26)
-#define _module_rtl871x_mp_c_ BIT(27)
-#define _module_rtl8712_xmit_c_ BIT(28)
-#define _module_rtl8712_efuse_c_ BIT(29)
-#define _module_rtl8712_recv_c_ BIT(30)
-#define _module_rtl8712_led_c_ BIT(31)
-
-#undef _MODULE_DEFINE_
-
-#if defined _RTL871X_XMIT_C_
- #define _MODULE_DEFINE_ _module_rtl871x_xmit_c_
-#elif defined _XMIT_OSDEP_C_
- #define _MODULE_DEFINE_ _module_xmit_osdep_c_
-#elif defined _RTL871X_RECV_C_
- #define _MODULE_DEFINE_ _module_rtl871x_recv_c_
-#elif defined _RECV_OSDEP_C_
- #define _MODULE_DEFINE_ _module_recv_osdep_c_
-#elif defined _RTL871X_MLME_C_
- #define _MODULE_DEFINE_ _module_rtl871x_mlme_c_
-#elif defined _MLME_OSDEP_C_
- #define _MODULE_DEFINE_ _module_mlme_osdep_c_
-#elif defined _RTL871X_STA_MGT_C_
- #define _MODULE_DEFINE_ _module_rtl871x_sta_mgt_c_
-#elif defined _RTL871X_CMD_C_
- #define _MODULE_DEFINE_ _module_rtl871x_cmd_c_
-#elif defined _CMD_OSDEP_C_
- #define _MODULE_DEFINE_ _module_cmd_osdep_c_
-#elif defined _RTL871X_IO_C_
- #define _MODULE_DEFINE_ _module_rtl871x_io_c_
-#elif defined _IO_OSDEP_C_
- #define _MODULE_DEFINE_ _module_io_osdep_c_
-#elif defined _OS_INTFS_C_
- #define _MODULE_DEFINE_ _module_os_intfs_c_
-#elif defined _RTL871X_SECURITY_C_
- #define _MODULE_DEFINE_ _module_rtl871x_security_c_
-#elif defined _RTL871X_EEPROM_C_
- #define _MODULE_DEFINE_ _module_rtl871x_eeprom_c_
-#elif defined _HAL_INIT_C_
- #define _MODULE_DEFINE_ _module_hal_init_c_
-#elif defined _HCI_HAL_INIT_C_
- #define _MODULE_DEFINE_ _module_hci_hal_init_c_
-#elif defined _RTL871X_IOCTL_C_
- #define _MODULE_DEFINE_ _module_rtl871x_ioctl_c_
-#elif defined _RTL871X_IOCTL_SET_C_
- #define _MODULE_DEFINE_ _module_rtl871x_ioctl_set_c_
-#elif defined _RTL871X_PWRCTRL_C_
- #define _MODULE_DEFINE_ _module_rtl871x_pwrctrl_c_
-#elif defined _HCI_INTF_C_
- #define _MODULE_DEFINE_ _module_hci_intfs_c_
-#elif defined _HCI_OPS_C_
- #define _MODULE_DEFINE_ _module_hci_ops_c_
-#elif defined _OSDEP_HCI_INTF_C_
- #define _MODULE_DEFINE_ _module_hci_intfs_c_
-#elif defined _OSDEP_SERVICE_C_
- #define _MODULE_DEFINE_ _module_osdep_service_c_
-#elif defined _RTL871X_MP_IOCTL_C_
- #define _MODULE_DEFINE_ _module_rtl871x_mp_ioctl_c_
-#elif defined _HCI_OPS_OS_C_
- #define _MODULE_DEFINE_ _module_hci_ops_os_c_
-#elif defined _RTL871X_IOCTL_LINUX_C_
- #define _MODULE_DEFINE_ _module_rtl871x_ioctl_os_c
-#elif defined _RTL871X_MP_C_
- #define _MODULE_DEFINE_ _module_rtl871x_mp_c_
-#elif defined _RTL8712_CMD_C_
- #define _MODULE_DEFINE_ _module_rtl8712_cmd_c_
-#elif defined _RTL8712_XMIT_C_
- #define _MODULE_DEFINE_ _module_rtl8712_xmit_c_
-#elif defined _RTL8712_EFUSE_C_
- #define _MODULE_DEFINE_ _module_rtl8712_efuse_c_
-#elif defined _RTL8712_RECV_C_
- #define _MODULE_DEFINE_ _module_rtl8712_recv_c_
-#else
- #undef _MODULE_DEFINE_
-#endif
-
-#endif /*__RTL871X_DEBUG_H__*/
diff --git a/drivers/staging/rtl8712/rtl871x_eeprom.c b/drivers/staging/rtl8712/rtl871x_eeprom.c
deleted file mode 100644
index 221bf92e1b1c..000000000000
--- a/drivers/staging/rtl8712/rtl871x_eeprom.c
+++ /dev/null
@@ -1,220 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_eeprom.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_EEPROM_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-static void up_clk(struct _adapter *padapter, u16 *x)
-{
- *x = *x | _EESK;
- r8712_write8(padapter, EE_9346CR, (u8)*x);
- udelay(CLOCK_RATE);
-}
-
-static void down_clk(struct _adapter *padapter, u16 *x)
-{
- *x = *x & ~_EESK;
- r8712_write8(padapter, EE_9346CR, (u8)*x);
- udelay(CLOCK_RATE);
-}
-
-static void shift_out_bits(struct _adapter *padapter, u16 data, u16 count)
-{
- u16 x, mask;
-
- if (padapter->surprise_removed)
- goto out;
- mask = 0x01 << (count - 1);
- x = r8712_read8(padapter, EE_9346CR);
- x &= ~(_EEDO | _EEDI);
- do {
- x &= ~_EEDI;
- if (data & mask)
- x |= _EEDI;
- if (padapter->surprise_removed)
- goto out;
- r8712_write8(padapter, EE_9346CR, (u8)x);
- udelay(CLOCK_RATE);
- up_clk(padapter, &x);
- down_clk(padapter, &x);
- mask >>= 1;
- } while (mask);
- if (padapter->surprise_removed)
- goto out;
- x &= ~_EEDI;
- r8712_write8(padapter, EE_9346CR, (u8)x);
-out:;
-}
-
-static u16 shift_in_bits(struct _adapter *padapter)
-{
- u16 x, d = 0, i;
-
- if (padapter->surprise_removed)
- goto out;
- x = r8712_read8(padapter, EE_9346CR);
- x &= ~(_EEDO | _EEDI);
- d = 0;
- for (i = 0; i < 16; i++) {
- d <<= 1;
- up_clk(padapter, &x);
- if (padapter->surprise_removed)
- goto out;
- x = r8712_read8(padapter, EE_9346CR);
- x &= ~(_EEDI);
- if (x & _EEDO)
- d |= 1;
- down_clk(padapter, &x);
- }
-out:
- return d;
-}
-
-static void standby(struct _adapter *padapter)
-{
- u8 x;
-
- x = r8712_read8(padapter, EE_9346CR);
- x &= ~(_EECS | _EESK);
- r8712_write8(padapter, EE_9346CR, x);
- udelay(CLOCK_RATE);
- x |= _EECS;
- r8712_write8(padapter, EE_9346CR, x);
- udelay(CLOCK_RATE);
-}
-
-static u16 wait_eeprom_cmd_done(struct _adapter *padapter)
-{
- u8 x;
- u16 i;
-
- standby(padapter);
- for (i = 0; i < 200; i++) {
- x = r8712_read8(padapter, EE_9346CR);
- if (x & _EEDO)
- return true;
- udelay(CLOCK_RATE);
- }
- return false;
-}
-
-static void eeprom_clean(struct _adapter *padapter)
-{
- u16 x;
-
- if (padapter->surprise_removed)
- return;
- x = r8712_read8(padapter, EE_9346CR);
- if (padapter->surprise_removed)
- return;
- x &= ~(_EECS | _EEDI);
- r8712_write8(padapter, EE_9346CR, (u8)x);
- if (padapter->surprise_removed)
- return;
- up_clk(padapter, &x);
- if (padapter->surprise_removed)
- return;
- down_clk(padapter, &x);
-}
-
-void r8712_eeprom_write16(struct _adapter *padapter, u16 reg, u16 data)
-{
- u8 x;
- u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new;
-
- tmp8_ori = r8712_read8(padapter, 0x102502f1);
- tmp8_new = tmp8_ori & 0xf7;
- if (tmp8_ori != tmp8_new)
- r8712_write8(padapter, 0x102502f1, tmp8_new);
- tmp8_clk_ori = r8712_read8(padapter, 0x10250003);
- tmp8_clk_new = tmp8_clk_ori | 0x20;
- if (tmp8_clk_new != tmp8_clk_ori)
- r8712_write8(padapter, 0x10250003, tmp8_clk_new);
- x = r8712_read8(padapter, EE_9346CR);
- x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
- x |= _EEM1 | _EECS;
- r8712_write8(padapter, EE_9346CR, x);
- shift_out_bits(padapter, EEPROM_EWEN_OPCODE, 5);
- if (padapter->eeprom_address_size == 8) /*CF+ and SDIO*/
- shift_out_bits(padapter, 0, 6);
- else /* USB */
- shift_out_bits(padapter, 0, 4);
- standby(padapter);
- /* Erase this particular word. Write the erase opcode and register
- * number in that order. The opcode is 3bits in length; reg is 6
- * bits long.
- */
- standby(padapter);
- /* write the new word to the EEPROM
- * send the write opcode the EEPORM
- */
- shift_out_bits(padapter, EEPROM_WRITE_OPCODE, 3);
- /* select which word in the EEPROM that we are writing to. */
- shift_out_bits(padapter, reg, padapter->eeprom_address_size);
- /* write the data to the selected EEPROM word. */
- shift_out_bits(padapter, data, 16);
- if (wait_eeprom_cmd_done(padapter)) {
- standby(padapter);
- shift_out_bits(padapter, EEPROM_EWDS_OPCODE, 5);
- shift_out_bits(padapter, reg, 4);
- eeprom_clean(padapter);
- }
- if (tmp8_clk_new != tmp8_clk_ori)
- r8712_write8(padapter, 0x10250003, tmp8_clk_ori);
- if (tmp8_new != tmp8_ori)
- r8712_write8(padapter, 0x102502f1, tmp8_ori);
-}
-
-u16 r8712_eeprom_read16(struct _adapter *padapter, u16 reg) /*ReadEEprom*/
-{
- u16 x;
- u16 data = 0;
- u8 tmp8_ori, tmp8_new, tmp8_clk_ori, tmp8_clk_new;
-
- tmp8_ori = r8712_read8(padapter, 0x102502f1);
- tmp8_new = tmp8_ori & 0xf7;
- if (tmp8_ori != tmp8_new)
- r8712_write8(padapter, 0x102502f1, tmp8_new);
- tmp8_clk_ori = r8712_read8(padapter, 0x10250003);
- tmp8_clk_new = tmp8_clk_ori | 0x20;
- if (tmp8_clk_new != tmp8_clk_ori)
- r8712_write8(padapter, 0x10250003, tmp8_clk_new);
- if (padapter->surprise_removed)
- goto out;
- /* select EEPROM, reset bits, set _EECS */
- x = r8712_read8(padapter, EE_9346CR);
- if (padapter->surprise_removed)
- goto out;
- x &= ~(_EEDI | _EEDO | _EESK | _EEM0);
- x |= _EEM1 | _EECS;
- r8712_write8(padapter, EE_9346CR, (unsigned char)x);
- /* write the read opcode and register number in that order
- * The opcode is 3bits in length, reg is 6 bits long
- */
- shift_out_bits(padapter, EEPROM_READ_OPCODE, 3);
- shift_out_bits(padapter, reg, padapter->eeprom_address_size);
- /* Now read the data (16 bits) in from the selected EEPROM word */
- data = shift_in_bits(padapter);
- eeprom_clean(padapter);
-out:
- if (tmp8_clk_new != tmp8_clk_ori)
- r8712_write8(padapter, 0x10250003, tmp8_clk_ori);
- if (tmp8_new != tmp8_ori)
- r8712_write8(padapter, 0x102502f1, tmp8_ori);
- return data;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_eeprom.h b/drivers/staging/rtl8712/rtl871x_eeprom.h
deleted file mode 100644
index 7bdeb2aaa025..000000000000
--- a/drivers/staging/rtl8712/rtl871x_eeprom.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- ******************************************************************************/
-#ifndef __RTL871X_EEPROM_H__
-#define __RTL871X_EEPROM_H__
-
-#include "osdep_service.h"
-
-#define RTL8712_EEPROM_ID 0x8712
-#define EEPROM_MAX_SIZE 256
-#define CLOCK_RATE 50 /*100us*/
-
-/*- EEPROM opcodes*/
-#define EEPROM_READ_OPCODE 06
-#define EEPROM_WRITE_OPCODE 05
-#define EEPROM_ERASE_OPCODE 07
-#define EEPROM_EWEN_OPCODE 19 /* Erase/write enable*/
-#define EEPROM_EWDS_OPCODE 16 /* Erase/write disable*/
-
-#define EEPROM_CID_DEFAULT 0x0
-#define EEPROM_CID_ALPHA 0x1
-#define EEPROM_CID_Senao 0x3
-#define EEPROM_CID_NetCore 0x5
-#define EEPROM_CID_CAMEO 0X8
-#define EEPROM_CID_SITECOM 0x9
-#define EEPROM_CID_COREGA 0xB
-#define EEPROM_CID_EDIMAX_BELKIN 0xC
-#define EEPROM_CID_SERCOMM_BELKIN 0xE
-#define EEPROM_CID_CAMEO1 0xF
-#define EEPROM_CID_WNC_COREGA 0x12
-#define EEPROM_CID_CLEVO 0x13
-#define EEPROM_CID_WHQL 0xFE
-
-enum RT_CUSTOMER_ID {
- RT_CID_DEFAULT = 0,
- RT_CID_8187_ALPHA0 = 1,
- RT_CID_8187_SERCOMM_PS = 2,
- RT_CID_8187_HW_LED = 3,
- RT_CID_8187_NETGEAR = 4,
- RT_CID_WHQL = 5,
- RT_CID_819x_CAMEO = 6,
- RT_CID_819x_RUNTOP = 7,
- RT_CID_819x_Senao = 8,
- RT_CID_TOSHIBA = 9,
- RT_CID_819x_Netcore = 10,
- RT_CID_Nettronix = 11,
- RT_CID_DLINK = 12,
- RT_CID_PRONET = 13,
- RT_CID_COREGA = 14,
- RT_CID_819x_ALPHA = 15,
- RT_CID_819x_Sitecom = 16,
- RT_CID_CCX = 17,
- RT_CID_819x_Lenovo = 18,
- RT_CID_819x_QMI = 19,
- RT_CID_819x_Edimax_Belkin = 20,
- RT_CID_819x_Sercomm_Belkin = 21,
- RT_CID_819x_CAMEO1 = 22,
- RT_CID_819x_MSI = 23,
- RT_CID_819x_Acer = 24,
- RT_CID_819x_AzWave_ASUS = 25,
- RT_CID_819x_AzWave = 26,
- RT_CID_819x_WNC_COREGA = 27,
- RT_CID_819x_CLEVO = 28,
-};
-
-struct eeprom_priv {
- u8 bautoload_fail_flag;
- u8 bempty;
- u8 sys_config;
- u8 mac_addr[6];
- u8 config0;
- u16 channel_plan;
- u8 country_string[3];
- u8 tx_power_b[15];
- u8 tx_power_g[15];
- u8 tx_power_a[201];
- u8 efuse_eeprom_data[EEPROM_MAX_SIZE];
- enum RT_CUSTOMER_ID CustomerID;
-};
-
-void r8712_eeprom_write16(struct _adapter *padapter, u16 reg, u16 data);
-u16 r8712_eeprom_read16(struct _adapter *padapter, u16 reg);
-
-#endif /*__RTL871X_EEPROM_H__*/
-
diff --git a/drivers/staging/rtl8712/rtl871x_event.h b/drivers/staging/rtl8712/rtl871x_event.h
deleted file mode 100644
index 0cc780cf4341..000000000000
--- a/drivers/staging/rtl8712/rtl871x_event.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871x_EVENT_H_
-#define _RTL871x_EVENT_H_
-
-#include "osdep_service.h"
-
-#include "wlan_bssdef.h"
-#include <linux/semaphore.h>
-#include <linux/sem.h>
-
-/*
- * Used to report a bss has been scanned
- */
-struct survey_event {
- struct wlan_bssid_ex bss;
-};
-
-/*
- * Used to report that the requested site survey has been done.
- * bss_cnt indicates the number of bss that has been reported.
- */
-struct surveydone_event {
- unsigned int bss_cnt;
-
-};
-
-/*
- * Used to report the link result of joining the given bss
- * join_res:
- * -1: authentication fail
- * -2: association fail
- * > 0: TID
- */
-struct joinbss_event {
- struct wlan_network network;
-};
-
-/*
- * Used to report a given STA has joinned the created BSS.
- * It is used in AP/Ad-HoC(M) mode.
- */
-struct stassoc_event {
- unsigned char macaddr[6];
- unsigned char rsvd[2];
- __le32 cam_id;
-};
-
-struct stadel_event {
- unsigned char macaddr[6];
- unsigned char rsvd[2];
-};
-
-struct addba_event {
- unsigned int tid;
-};
-
-#define GEN_EVT_CODE(event) event ## _EVT_
-
-struct fwevent {
- u32 parmsize;
- void (*event_callback)(struct _adapter *dev, u8 *pbuf);
-};
-
-#define C2HEVENT_SZ 32
-struct event_node {
- unsigned char *node;
- unsigned char evt_code;
- unsigned short evt_sz;
- /*volatile*/ int *caller_ff_tail;
- int caller_ff_sz;
-};
-
-struct c2hevent_queue {
- /*volatile*/ int head;
- /*volatile*/ int tail;
- struct event_node nodes[C2HEVENT_SZ];
- unsigned char seq;
-};
-
-#define NETWORK_QUEUE_SZ 4
-
-struct network_queue {
- /*volatile*/ int head;
- /*volatile*/ int tail;
- struct wlan_bssid_ex networks[NETWORK_QUEUE_SZ];
-};
-
-struct ADDBA_Req_Report_parm {
- unsigned char MacAddress[ETH_ALEN];
- unsigned short StartSeqNum;
- unsigned char tid;
-};
-
-#include "rtl8712_event.h"
-
-#endif /* _WLANEVENT_H_ */
-
diff --git a/drivers/staging/rtl8712/rtl871x_ht.h b/drivers/staging/rtl8712/rtl871x_ht.h
deleted file mode 100644
index ebd78665775d..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ht.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_HT_H_
-#define _RTL871X_HT_H_
-
-#include "osdep_service.h"
-#include "wifi.h"
-
-struct ht_priv {
- unsigned int ht_option;
- unsigned int ampdu_enable;/*for enable Tx A-MPDU*/
- unsigned char baddbareq_issued[16];
- unsigned int tx_amsdu_enable;/*for enable Tx A-MSDU */
- unsigned int tx_amdsu_maxlen; /* 1: 8k, 0:4k ; default:8k, for tx */
- unsigned int rx_ampdu_maxlen; /* for rx reordering ctrl win_sz,
- * updated when join_callback.
- */
- struct ieee80211_ht_cap ht_cap;
-};
-
-#endif /*_RTL871X_HT_H_ */
-
diff --git a/drivers/staging/rtl8712/rtl871x_io.c b/drivers/staging/rtl8712/rtl871x_io.c
deleted file mode 100644
index 20e080e284dd..000000000000
--- a/drivers/staging/rtl8712/rtl871x_io.c
+++ /dev/null
@@ -1,147 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_io.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-/*
- *
- * The purpose of rtl871x_io.c
- *
- * a. provides the API
- * b. provides the protocol engine
- * c. provides the software interface between caller and the hardware interface
- *
- * For r8712u, both sync/async operations are provided.
- *
- * Only sync read/write_mem operations are provided.
- *
- */
-
-#define _RTL871X_IO_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "rtl871x_io.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-
-static uint _init_intf_hdl(struct _adapter *padapter,
- struct intf_hdl *pintf_hdl)
-{
- struct intf_priv *pintf_priv;
- void (*set_intf_option)(u32 *poption) = NULL;
- void (*set_intf_funs)(struct intf_hdl *pintf_hdl);
- void (*set_intf_ops)(struct _io_ops *pops);
- uint (*init_intf_priv)(struct intf_priv *pintfpriv);
-
- set_intf_option = &(r8712_usb_set_intf_option);
- set_intf_funs = &(r8712_usb_set_intf_funs);
- set_intf_ops = &r8712_usb_set_intf_ops;
- init_intf_priv = &r8712_usb_init_intf_priv;
- pintf_priv = kmalloc(sizeof(*pintf_priv), GFP_ATOMIC);
- pintf_hdl->pintfpriv = pintf_priv;
- if (!pintf_priv)
- goto _init_intf_hdl_fail;
- pintf_hdl->adapter = (u8 *)padapter;
- set_intf_option(&pintf_hdl->intf_option);
- set_intf_funs(pintf_hdl);
- set_intf_ops(&pintf_hdl->io_ops);
- pintf_priv->intf_dev = (u8 *)&padapter->dvobjpriv;
- if (init_intf_priv(pintf_priv) == _FAIL)
- goto _init_intf_hdl_fail;
- return _SUCCESS;
-_init_intf_hdl_fail:
- kfree(pintf_priv);
- return _FAIL;
-}
-
-static void _unload_intf_hdl(struct intf_priv *pintfpriv)
-{
- void (*unload_intf_priv)(struct intf_priv *pintfpriv);
-
- unload_intf_priv = &r8712_usb_unload_intf_priv;
- unload_intf_priv(pintfpriv);
- kfree(pintfpriv);
-}
-
-static uint register_intf_hdl(u8 *dev, struct intf_hdl *pintfhdl)
-{
- struct _adapter *adapter = (struct _adapter *)dev;
-
- pintfhdl->intf_option = 0;
- pintfhdl->adapter = dev;
- pintfhdl->intf_dev = (u8 *)&adapter->dvobjpriv;
- if (!_init_intf_hdl(adapter, pintfhdl))
- goto register_intf_hdl_fail;
- return _SUCCESS;
-register_intf_hdl_fail:
- return false;
-}
-
-static void unregister_intf_hdl(struct intf_hdl *pintfhdl)
-{
- _unload_intf_hdl(pintfhdl->pintfpriv);
- memset((u8 *)pintfhdl, 0, sizeof(struct intf_hdl));
-}
-
-uint r8712_alloc_io_queue(struct _adapter *adapter)
-{
- u32 i;
- struct io_queue *pio_queue;
- struct io_req *pio_req;
-
- pio_queue = kmalloc(sizeof(*pio_queue), GFP_ATOMIC);
- if (!pio_queue)
- goto alloc_io_queue_fail;
- INIT_LIST_HEAD(&pio_queue->free_ioreqs);
- INIT_LIST_HEAD(&pio_queue->processing);
- INIT_LIST_HEAD(&pio_queue->pending);
- spin_lock_init(&pio_queue->lock);
- pio_queue->pallocated_free_ioreqs_buf = kzalloc(NUM_IOREQ *
- (sizeof(struct io_req)) + 4,
- GFP_ATOMIC);
- if ((pio_queue->pallocated_free_ioreqs_buf) == NULL)
- goto alloc_io_queue_fail;
- pio_queue->free_ioreqs_buf = pio_queue->pallocated_free_ioreqs_buf + 4
- - ((addr_t)(pio_queue->pallocated_free_ioreqs_buf)
- & 3);
- pio_req = (struct io_req *)(pio_queue->free_ioreqs_buf);
- for (i = 0; i < NUM_IOREQ; i++) {
- INIT_LIST_HEAD(&pio_req->list);
- list_add_tail(&pio_req->list, &pio_queue->free_ioreqs);
- pio_req++;
- }
- if ((register_intf_hdl((u8 *)adapter, &pio_queue->intf)) == _FAIL)
- goto alloc_io_queue_fail;
- adapter->pio_queue = pio_queue;
- return _SUCCESS;
-alloc_io_queue_fail:
- if (pio_queue) {
- kfree(pio_queue->pallocated_free_ioreqs_buf);
- kfree(pio_queue);
- }
- adapter->pio_queue = NULL;
- return _FAIL;
-}
-
-void r8712_free_io_queue(struct _adapter *adapter)
-{
- struct io_queue *pio_queue = adapter->pio_queue;
-
- if (pio_queue) {
- kfree(pio_queue->pallocated_free_ioreqs_buf);
- adapter->pio_queue = NULL;
- unregister_intf_hdl(&pio_queue->intf);
- kfree(pio_queue);
- }
-}
diff --git a/drivers/staging/rtl8712/rtl871x_io.h b/drivers/staging/rtl8712/rtl871x_io.h
deleted file mode 100644
index f09d50a29b82..000000000000
--- a/drivers/staging/rtl8712/rtl871x_io.h
+++ /dev/null
@@ -1,236 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_IO_H_
-#define _RTL871X_IO_H_
-
-#include "osdep_service.h"
-#include "osdep_intf.h"
-
-#define NUM_IOREQ 8
-
-#define MAX_PROT_SZ (64-16)
-
-#define _IOREADY 0
-#define _IO_WAIT_COMPLETE 1
-#define _IO_WAIT_RSP 2
-
-/* IO COMMAND TYPE */
-#define _IOSZ_MASK_ (0x7F)
-#define _IO_WRITE_ BIT(7)
-#define _IO_FIXED_ BIT(8)
-#define _IO_BURST_ BIT(9)
-#define _IO_BYTE_ BIT(10)
-#define _IO_HW_ BIT(11)
-#define _IO_WORD_ BIT(12)
-#define _IO_SYNC_ BIT(13)
-#define _IO_CMDMASK_ (0x1F80)
-
-/*
- * For prompt mode accessing, caller shall free io_req
- * Otherwise, io_handler will free io_req
- */
-/* IO STATUS TYPE */
-#define _IO_ERR_ BIT(2)
-#define _IO_SUCCESS_ BIT(1)
-#define _IO_DONE_ BIT(0)
-#define IO_RD32 (_IO_SYNC_ | _IO_WORD_)
-#define IO_RD16 (_IO_SYNC_ | _IO_HW_)
-#define IO_RD8 (_IO_SYNC_ | _IO_BYTE_)
-#define IO_RD32_ASYNC (_IO_WORD_)
-#define IO_RD16_ASYNC (_IO_HW_)
-#define IO_RD8_ASYNC (_IO_BYTE_)
-#define IO_WR32 (_IO_WRITE_ | _IO_SYNC_ | _IO_WORD_)
-#define IO_WR16 (_IO_WRITE_ | _IO_SYNC_ | _IO_HW_)
-#define IO_WR8 (_IO_WRITE_ | _IO_SYNC_ | _IO_BYTE_)
-#define IO_WR32_ASYNC (_IO_WRITE_ | _IO_WORD_)
-#define IO_WR16_ASYNC (_IO_WRITE_ | _IO_HW_)
-#define IO_WR8_ASYNC (_IO_WRITE_ | _IO_BYTE_)
-/*
- * Only Sync. burst accessing is provided.
- */
-#define IO_WR_BURST(x) (IO_WRITE_ | _IO_SYNC_ | _IO_BURST_ | \
- ((x) & _IOSZ_MASK_))
-#define IO_RD_BURST(x) (_IO_SYNC_ | _IO_BURST_ | ((x) & _IOSZ_MASK_))
-/*below is for the intf_option bit definition...*/
-#define _INTF_ASYNC_ BIT(0) /*support async io*/
-struct intf_priv;
-struct intf_hdl;
-struct io_queue;
-struct _io_ops {
- uint (*_sdbus_read_bytes_to_membuf)(struct intf_priv *pintfpriv,
- u32 addr, u32 cnt, u8 *pbuf);
- uint (*_sdbus_read_blocks_to_membuf)(struct intf_priv *pintfpriv,
- u32 addr, u32 cnt, u8 *pbuf);
- u8 (*_read8)(struct intf_hdl *pintfhdl, u32 addr);
- u16 (*_read16)(struct intf_hdl *pintfhdl, u32 addr);
- u32 (*_read32)(struct intf_hdl *pintfhdl, u32 addr);
- uint (*_sdbus_write_blocks_from_membuf)(struct intf_priv *pintfpriv,
- u32 addr, u32 cnt, u8 *pbuf,
- u8 async);
- uint (*_sdbus_write_bytes_from_membuf)(struct intf_priv *pintfpriv,
- u32 addr, u32 cnt, u8 *pbuf);
- u8 (*_cmd52r)(struct intf_priv *pintfpriv, u32 addr);
- void (*_cmd52w)(struct intf_priv *pintfpriv, u32 addr, u8 val8);
- u8 (*_cmdfunc152r)(struct intf_priv *pintfpriv, u32 addr);
- void (*_cmdfunc152w)(struct intf_priv *pintfpriv, u32 addr, u8 val8);
- void (*_write8)(struct intf_hdl *pintfhdl, u32 addr, u8 val);
- void (*_write16)(struct intf_hdl *pintfhdl, u32 addr, u16 val);
- void (*_write32)(struct intf_hdl *pintfhdl, u32 addr, u32 val);
- void (*_read_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
- void (*_write_mem)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
- void (*_sync_irp_protocol_rw)(struct io_queue *pio_q);
- u32 (*_read_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
- u32 (*_write_port)(struct intf_hdl *pintfhdl, u32 addr, u32 cnt,
- u8 *pmem);
-};
-
-struct io_req {
- struct list_head list;
- u32 addr;
- /*volatile*/ u32 val;
- u32 command;
- u32 status;
- u8 *pbuf;
- void (*_async_io_callback)(struct _adapter *padapter,
- struct io_req *pio_req, u8 *cnxt);
- u8 *cnxt;
-};
-
-struct intf_hdl {
- u32 intf_option;
- u8 *adapter;
- u8 *intf_dev;
- struct intf_priv *pintfpriv;
- void (*intf_hdl_init)(u8 *priv);
- void (*intf_hdl_unload)(u8 *priv);
- void (*intf_hdl_open)(u8 *priv);
- void (*intf_hdl_close)(u8 *priv);
- struct _io_ops io_ops;
-};
-
-struct reg_protocol_rd {
-#ifdef __LITTLE_ENDIAN
- /* DW1 */
- u32 NumOfTrans:4;
- u32 Reserved1:4;
- u32 Reserved2:24;
- /* DW2 */
- u32 ByteCount:7;
- u32 WriteEnable:1; /*0:read, 1:write*/
- u32 FixOrContinuous:1; /*0:continuous, 1: Fix*/
- u32 BurstMode:1;
- u32 Byte1Access:1;
- u32 Byte2Access:1;
- u32 Byte4Access:1;
- u32 Reserved3:3;
- u32 Reserved4:16;
- /*DW3*/
- u32 BusAddress;
- /*DW4*/
-#else
-/*DW1*/
- u32 Reserved1:4;
- u32 NumOfTrans:4;
- u32 Reserved2:24;
- /*DW2*/
- u32 WriteEnable:1;
- u32 ByteCount:7;
- u32 Reserved3:3;
- u32 Byte4Access:1;
- u32 Byte2Access:1;
- u32 Byte1Access:1;
- u32 BurstMode:1;
- u32 FixOrContinuous:1;
- u32 Reserved4:16;
- /*DW3*/
- u32 BusAddress;
- /*DW4*/
-#endif
-};
-
-struct reg_protocol_wt {
-#ifdef __LITTLE_ENDIAN
- /*DW1*/
- u32 NumOfTrans:4;
- u32 Reserved1:4;
- u32 Reserved2:24;
- /*DW2*/
- u32 ByteCount:7;
- u32 WriteEnable:1; /*0:read, 1:write*/
- u32 FixOrContinuous:1; /*0:continuous, 1: Fix*/
- u32 BurstMode:1;
- u32 Byte1Access:1;
- u32 Byte2Access:1;
- u32 Byte4Access:1;
- u32 Reserved3:3;
- u32 Reserved4:16;
- /*DW3*/
- u32 BusAddress;
- /*DW4*/
- u32 Value;
-#else
- /*DW1*/
- u32 Reserved1:4;
- u32 NumOfTrans:4;
- u32 Reserved2:24;
- /*DW2*/
- u32 WriteEnable:1;
- u32 ByteCount:7;
- u32 Reserved3:3;
- u32 Byte4Access:1;
- u32 Byte2Access:1;
- u32 Byte1Access:1;
- u32 BurstMode:1;
- u32 FixOrContinuous:1;
- u32 Reserved4:16;
- /*DW3*/
- u32 BusAddress;
- /*DW4*/
- u32 Value;
-#endif
-};
-
-/*
- * Below is the data structure used by _io_handler
- */
-
-struct io_queue {
- spinlock_t lock;
- struct list_head free_ioreqs;
- /*The io_req list that will be served in the single protocol r/w.*/
- struct list_head pending;
- struct list_head processing;
- u8 *free_ioreqs_buf; /* 4-byte aligned */
- u8 *pallocated_free_ioreqs_buf;
- struct intf_hdl intf;
-};
-
-u8 r8712_read8(struct _adapter *adapter, u32 addr);
-u16 r8712_read16(struct _adapter *adapter, u32 addr);
-u32 r8712_read32(struct _adapter *adapter, u32 addr);
-void r8712_read_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void r8712_read_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void r8712_write8(struct _adapter *adapter, u32 addr, u8 val);
-void r8712_write16(struct _adapter *adapter, u32 addr, u16 val);
-void r8712_write32(struct _adapter *adapter, u32 addr, u32 val);
-void r8712_write_mem(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-void r8712_write_port(struct _adapter *adapter, u32 addr, u32 cnt, u8 *pmem);
-/*ioreq */
-uint r8712_alloc_io_queue(struct _adapter *adapter);
-void r8712_free_io_queue(struct _adapter *adapter);
-
-#endif /*_RTL871X_IO_H_*/
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl.h b/drivers/staging/rtl8712/rtl871x_ioctl.h
deleted file mode 100644
index d6332a8c7f4f..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef __IOCTL_H
-#define __IOCTL_H
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#ifndef OID_802_11_CAPABILITY
- #define OID_802_11_CAPABILITY 0x0d010122
-#endif
-
-#ifndef OID_802_11_PMKID
- #define OID_802_11_PMKID 0x0d010123
-#endif
-
-/* For DDK-defined OIDs*/
-#define OID_NDIS_SEG1 0x00010100
-#define OID_NDIS_SEG2 0x00010200
-#define OID_NDIS_SEG3 0x00020100
-#define OID_NDIS_SEG4 0x01010100
-#define OID_NDIS_SEG5 0x01020100
-#define OID_NDIS_SEG6 0x01020200
-#define OID_NDIS_SEG7 0xFD010100
-#define OID_NDIS_SEG8 0x0D010100
-#define OID_NDIS_SEG9 0x0D010200
-#define OID_NDIS_SEG10 0x0D020200
-#define SZ_OID_NDIS_SEG1 23
-#define SZ_OID_NDIS_SEG2 3
-#define SZ_OID_NDIS_SEG3 6
-#define SZ_OID_NDIS_SEG4 6
-#define SZ_OID_NDIS_SEG5 4
-#define SZ_OID_NDIS_SEG6 8
-#define SZ_OID_NDIS_SEG7 7
-#define SZ_OID_NDIS_SEG8 36
-#define SZ_OID_NDIS_SEG9 24
-#define SZ_OID_NDIS_SEG10 19
-
-/* For Realtek-defined OIDs*/
-#define OID_MP_SEG1 0xFF871100
-#define OID_MP_SEG2 0xFF818000
-#define OID_MP_SEG3 0xFF818700
-#define OID_MP_SEG4 0xFF011100
-
-enum oid_type {
- QUERY_OID,
- SET_OID
-};
-
-struct oid_funs_node {
- unsigned int oid_start; /*the starting number for OID*/
- unsigned int oid_end; /*the ending number for OID*/
- struct oid_obj_priv *node_array;
- unsigned int array_sz; /*the size of node_array*/
- int query_counter; /*count the number of query hits for this segment*/
- int set_counter; /*count the number of set hits for this segment*/
-};
-
-struct oid_par_priv {
- void *adapter_context;
- uint oid;
- void *information_buf;
- unsigned long information_buf_len;
- unsigned long *bytes_rw;
- unsigned long *bytes_needed;
- enum oid_type type_of_oid;
- unsigned int dbg;
-};
-
-struct oid_obj_priv {
- unsigned char dbg; /* 0: without OID debug message
- * 1: with OID debug message
- */
- uint (*oidfuns)(struct oid_par_priv *poid_par_priv);
-};
-
-uint oid_null_function(struct oid_par_priv *poid_par_priv);
-
-extern struct iw_handler_def r871x_handlers_def;
-
-uint drv_query_info(struct net_device *MiniportAdapterContext,
- uint Oid,
- void *InformationBuffer,
- u32 InformationBufferLength,
- u32 *BytesWritten,
- u32 *BytesNeeded);
-
-uint drv_set_info(struct net_device *MiniportAdapterContext,
- uint Oid,
- void *InformationBuffer,
- u32 InformationBufferLength,
- u32 *BytesRead,
- u32 *BytesNeeded);
-
-#endif
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c b/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
deleted file mode 100644
index 0653aa27b1fa..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl_linux.c
+++ /dev/null
@@ -1,2275 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_ioctl_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_IOCTL_LINUX_C_
-#define _RTL871X_MP_IOCTL_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wlan_bssdef.h"
-#include "rtl871x_debug.h"
-#include "wifi.h"
-#include "rtl871x_mlme.h"
-#include "rtl871x_ioctl.h"
-#include "rtl871x_ioctl_set.h"
-#include "rtl871x_mp_ioctl.h"
-#include "mlme_osdep.h"
-#include <linux/wireless.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/io.h>
-#include <linux/semaphore.h>
-#include <net/iw_handler.h>
-#include <linux/if_arp.h>
-#include <linux/etherdevice.h>
-
-#define RTL_IOCTL_WPA_SUPPLICANT (SIOCIWFIRSTPRIV + 0x1E)
-
-#define SCAN_ITEM_SIZE 768
-#define MAX_CUSTOM_LEN 64
-#define RATE_COUNT 4
-
-static const u32 rtl8180_rates[] = {1000000, 2000000, 5500000, 11000000,
- 6000000, 9000000, 12000000, 18000000,
- 24000000, 36000000, 48000000, 54000000};
-
-static const long ieee80211_wlan_frequencies[] = {
- 2412, 2417, 2422, 2427,
- 2432, 2437, 2442, 2447,
- 2452, 2457, 2462, 2467,
- 2472, 2484
-};
-
-void r8712_indicate_wx_assoc_event(struct _adapter *padapter)
-{
- union iwreq_data wrqu;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- memcpy(wrqu.ap_addr.sa_data, pmlmepriv->cur_network.network.MacAddress, ETH_ALEN);
- wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
-}
-
-void r8712_indicate_wx_disassoc_event(struct _adapter *padapter)
-{
- union iwreq_data wrqu;
-
- wrqu.ap_addr.sa_family = ARPHRD_ETHER;
- eth_zero_addr(wrqu.ap_addr.sa_data);
- wireless_send_event(padapter->pnetdev, SIOCGIWAP, &wrqu, NULL);
-}
-
-static inline void handle_pairwise_key(struct sta_info *psta,
- struct ieee_param *param,
- struct _adapter *padapter)
-{
- /* pairwise key */
- memcpy(psta->x_UncstKey.skey, param->u.crypt.key,
- (param->u.crypt. key_len > 16 ? 16 : param->u.crypt.key_len));
- if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
- memcpy(psta->tkiptxmickey. skey,
- &param->u.crypt.key[16], 8);
- memcpy(psta->tkiprxmickey. skey,
- &param->u.crypt.key[24], 8);
- padapter->securitypriv. busetkipkey = false;
- mod_timer(&padapter->securitypriv.tkip_timer,
- jiffies + msecs_to_jiffies(50));
- }
- r8712_setstakey_cmd(padapter, (unsigned char *)psta, true);
-}
-
-static inline void handle_group_key(struct ieee_param *param,
- struct _adapter *padapter)
-{
- union Keytype *gk = padapter->securitypriv.XGrpKey;
- union Keytype *gtk = padapter->securitypriv.XGrptxmickey;
- union Keytype *grk = padapter->securitypriv.XGrprxmickey;
-
- if (param->u.crypt.idx > 0 &&
- param->u.crypt.idx < 3) {
- /* group key idx is 1 or 2 */
- memcpy(gk[param->u.crypt.idx - 1].skey,
- param->u.crypt.key,
- (param->u.crypt.key_len > 16 ? 16 :
- param->u.crypt.key_len));
- memcpy(gtk[param->u.crypt.idx - 1].skey,
- &param->u.crypt.key[16], 8);
- memcpy(grk[param->u.crypt.idx - 1].skey,
- &param->u.crypt.key[24], 8);
- padapter->securitypriv.binstallGrpkey = true;
- r8712_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx);
- if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE) {
- if (padapter->registrypriv.power_mgnt != padapter->pwrctrlpriv.pwr_mode)
- mod_timer(&padapter->mlmepriv.dhcp_timer,
- jiffies + msecs_to_jiffies(60000));
- }
- }
-}
-
-static noinline_for_stack char *translate_scan_wpa(struct iw_request_info *info,
- struct wlan_network *pnetwork,
- struct iw_event *iwe,
- char *start, char *stop)
-{
- /* parsing WPA/WPA2 IE */
- u8 buf[MAX_WPA_IE_LEN];
- u8 wpa_ie[255], rsn_ie[255];
- u16 wpa_len = 0, rsn_len = 0;
- int n, i;
-
- r8712_get_sec_ie(pnetwork->network.IEs,
- pnetwork->network.IELength, rsn_ie, &rsn_len,
- wpa_ie, &wpa_len);
- if (wpa_len > 0) {
- memset(buf, 0, MAX_WPA_IE_LEN);
- n = sprintf(buf, "wpa_ie=");
- for (i = 0; i < wpa_len; i++) {
- n += scnprintf(buf + n, MAX_WPA_IE_LEN - n,
- "%02x", wpa_ie[i]);
- if (n == MAX_WPA_IE_LEN - 1)
- break;
- }
- memset(iwe, 0, sizeof(*iwe));
- iwe->cmd = IWEVCUSTOM;
- iwe->u.data.length = (u16)strlen(buf);
- start = iwe_stream_add_point(info, start, stop, iwe, buf);
- memset(iwe, 0, sizeof(*iwe));
- iwe->cmd = IWEVGENIE;
- iwe->u.data.length = (u16)wpa_len;
- start = iwe_stream_add_point(info, start, stop, iwe, wpa_ie);
- }
- if (rsn_len > 0) {
- memset(buf, 0, MAX_WPA_IE_LEN);
- n = sprintf(buf, "rsn_ie=");
- for (i = 0; i < rsn_len; i++) {
- n += scnprintf(buf + n, MAX_WPA_IE_LEN - n,
- "%02x", rsn_ie[i]);
- if (n == MAX_WPA_IE_LEN - 1)
- break;
- }
- memset(iwe, 0, sizeof(*iwe));
- iwe->cmd = IWEVCUSTOM;
- iwe->u.data.length = strlen(buf);
- start = iwe_stream_add_point(info, start, stop, iwe, buf);
- memset(iwe, 0, sizeof(*iwe));
- iwe->cmd = IWEVGENIE;
- iwe->u.data.length = rsn_len;
- start = iwe_stream_add_point(info, start, stop, iwe, rsn_ie);
- }
-
- return start;
-}
-
-static noinline_for_stack char *translate_scan_wps(struct iw_request_info *info,
- struct wlan_network *pnetwork,
- struct iw_event *iwe,
- char *start, char *stop)
-{
- /* parsing WPS IE */
- u8 wps_ie[512];
- uint wps_ielen;
-
- if (r8712_get_wps_ie(pnetwork->network.IEs, pnetwork->network.IELength, wps_ie, &wps_ielen)) {
- if (wps_ielen > 2) {
- iwe->cmd = IWEVGENIE;
- iwe->u.data.length = (u16)wps_ielen;
- start = iwe_stream_add_point(info, start, stop, iwe, wps_ie);
- }
- }
-
- return start;
-}
-
-static char *translate_scan(struct _adapter *padapter,
- struct iw_request_info *info,
- struct wlan_network *pnetwork,
- char *start, char *stop)
-{
- struct iw_event iwe;
- char *current_val;
- s8 *p;
- u32 i = 0, ht_ielen = 0;
- u16 cap, ht_cap = false;
- u8 rssi;
-
- if ((pnetwork->network.Configuration.DSConfig < 1) ||
- (pnetwork->network.Configuration.DSConfig > 14)) {
- if (pnetwork->network.Configuration.DSConfig < 1)
- pnetwork->network.Configuration.DSConfig = 1;
- else
- pnetwork->network.Configuration.DSConfig = 14;
- }
- /* AP MAC address */
- iwe.cmd = SIOCGIWAP;
- iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
- ether_addr_copy(iwe.u.ap_addr.sa_data, pnetwork->network.MacAddress);
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_ADDR_LEN);
- /* Add the ESSID */
- iwe.cmd = SIOCGIWESSID;
- iwe.u.data.flags = 1;
- iwe.u.data.length = min_t(u32, pnetwork->network.Ssid.SsidLength, 32);
- start = iwe_stream_add_point(info, start, stop, &iwe,
- pnetwork->network.Ssid.Ssid);
- /* parsing HT_CAP_IE */
- p = r8712_get_ie(&pnetwork->network.IEs[12], WLAN_EID_HT_CAPABILITY,
- &ht_ielen, pnetwork->network.IELength - 12);
- if (p && ht_ielen > 0)
- ht_cap = true;
- /* Add the protocol name */
- iwe.cmd = SIOCGIWNAME;
- if (r8712_is_cckratesonly_included(pnetwork->network.rates)) {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11b");
- } else if (r8712_is_cckrates_included(pnetwork->network.rates)) {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bgn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11bg");
- } else {
- if (ht_cap)
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11gn");
- else
- snprintf(iwe.u.name, IFNAMSIZ, "IEEE 802.11g");
- }
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_CHAR_LEN);
- /* Add mode */
- iwe.cmd = SIOCGIWMODE;
- memcpy((u8 *)&cap, r8712_get_capability_from_ie(pnetwork->network.IEs), 2);
- le16_to_cpus(&cap);
- if (cap & (WLAN_CAPABILITY_IBSS | WLAN_CAPABILITY_ESS)) {
- if (cap & WLAN_CAPABILITY_ESS)
- iwe.u.mode = (u32)IW_MODE_MASTER;
- else
- iwe.u.mode = (u32)IW_MODE_ADHOC;
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_UINT_LEN);
- }
- /* Add frequency/channel */
- iwe.cmd = SIOCGIWFREQ;
- {
- /* check legal index */
- u8 dsconfig = pnetwork->network.Configuration.DSConfig;
-
- if (dsconfig >= 1 && dsconfig <= sizeof(ieee80211_wlan_frequencies) / sizeof(long))
- iwe.u.freq.m = (s32)(ieee80211_wlan_frequencies[dsconfig - 1] * 100000);
- else
- iwe.u.freq.m = 0;
- }
- iwe.u.freq.e = (s16)1;
- iwe.u.freq.i = (u8)pnetwork->network.Configuration.DSConfig;
- start = iwe_stream_add_event(info, start, stop, &iwe,
- IW_EV_FREQ_LEN);
- /* Add encryption capability */
- iwe.cmd = SIOCGIWENCODE;
- if (cap & WLAN_CAPABILITY_PRIVACY)
- iwe.u.data.flags = (u16)(IW_ENCODE_ENABLED | IW_ENCODE_NOKEY);
- else
- iwe.u.data.flags = (u16)(IW_ENCODE_DISABLED);
- iwe.u.data.length = (u16)0;
- start = iwe_stream_add_point(info, start, stop, &iwe, pnetwork->network.Ssid.Ssid);
- /*Add basic and extended rates */
- current_val = start + iwe_stream_lcp_len(info);
- iwe.cmd = SIOCGIWRATE;
- iwe.u.bitrate.fixed = 0;
- iwe.u.bitrate.disabled = 0;
- iwe.u.bitrate.value = 0;
- i = 0;
- while (pnetwork->network.rates[i] != 0) {
- /* Bit rate given in 500 kb/s units */
- iwe.u.bitrate.value = (pnetwork->network.rates[i++] & 0x7F) * 500000;
- current_val = iwe_stream_add_value(info, start, current_val, stop, &iwe,
- IW_EV_PARAM_LEN);
- }
- /* Check if we added any event */
- if ((current_val - start) > iwe_stream_lcp_len(info))
- start = current_val;
-
- start = translate_scan_wpa(info, pnetwork, &iwe, start, stop);
-
- start = translate_scan_wps(info, pnetwork, &iwe, start, stop);
-
- /* Add quality statistics */
- iwe.cmd = IWEVQUAL;
- rssi = r8712_signal_scale_mapping(pnetwork->network.Rssi);
- /* we only update signal_level (signal strength) that is rssi. */
- iwe.u.qual.updated = (u8)(IW_QUAL_QUAL_INVALID | IW_QUAL_LEVEL_UPDATED | IW_QUAL_NOISE_INVALID);
- iwe.u.qual.level = rssi; /* signal strength */
- iwe.u.qual.qual = 0; /* signal quality */
- iwe.u.qual.noise = 0; /* noise level */
- start = iwe_stream_add_event(info, start, stop, &iwe, IW_EV_QUAL_LEN);
- /* how to translate rssi to ?% */
- return start;
-}
-
-static int wpa_set_auth_algs(struct net_device *dev, u32 value)
-{
- struct _adapter *padapter = netdev_priv(dev);
- int ret = 0;
-
- if ((value & AUTH_ALG_SHARED_KEY) && (value & AUTH_ALG_OPEN_SYSTEM)) {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeAutoSwitch;
- padapter->securitypriv.AuthAlgrthm = 3;
- } else if (value & AUTH_ALG_SHARED_KEY) {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.ndisauthtype = Ndis802_11AuthModeShared;
- padapter->securitypriv.AuthAlgrthm = 1;
- } else if (value & AUTH_ALG_OPEN_SYSTEM) {
- if (padapter->securitypriv.ndisauthtype <
- Ndis802_11AuthModeWPAPSK) {
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeOpen;
- padapter->securitypriv.AuthAlgrthm = 0;
- }
- } else {
- ret = -EINVAL;
- }
- return ret;
-}
-
-static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
- u32 param_len)
-{
- int ret = 0;
- u32 wep_key_idx, wep_key_len = 0;
- struct NDIS_802_11_WEP *pwep = NULL;
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- param->u.crypt.err = 0;
- param->u.crypt.alg[IEEE_CRYPT_ALG_NAME_LEN - 1] = '\0';
- if (param_len != (u32)((u8 *) param->u.crypt.key - (u8 *)param) +
- param->u.crypt.key_len)
- return -EINVAL;
- if (!is_broadcast_ether_addr(param->sta_addr))
- return -EINVAL;
-
- if (param->u.crypt.idx >= WEP_KEYS) {
- /* for large key indices, set the default (0) */
- param->u.crypt.idx = 0;
- }
- if (strcmp(param->u.crypt.alg, "WEP") == 0) {
- netdev_info(dev, "r8712u: %s: crypt.alg = WEP\n", __func__);
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.XGrpPrivacy = _WEP40_;
- wep_key_idx = param->u.crypt.idx;
- wep_key_len = param->u.crypt.key_len;
- if (wep_key_idx >= WEP_KEYS)
- wep_key_idx = 0;
- if (wep_key_len <= 0)
- return -EINVAL;
-
- wep_key_len = wep_key_len <= 5 ? 5 : 13;
- pwep = kzalloc(sizeof(*pwep), GFP_ATOMIC);
- if (!pwep)
- return -ENOMEM;
- pwep->KeyLength = wep_key_len;
- pwep->Length = wep_key_len +
- offsetof(struct NDIS_802_11_WEP, KeyMaterial);
- if (wep_key_len == 13) {
- padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
- padapter->securitypriv.XGrpPrivacy = _WEP104_;
- }
- pwep->KeyIndex = wep_key_idx;
- pwep->KeyIndex |= 0x80000000;
- memcpy(pwep->KeyMaterial, param->u.crypt.key, pwep->KeyLength);
- if (param->u.crypt.set_tx) {
- if (r8712_set_802_11_add_wep(padapter, pwep))
- ret = -EOPNOTSUPP;
- } else {
- /* don't update "psecuritypriv->PrivacyAlgrthm" and
- * "psecuritypriv->PrivacyKeyIndex=keyid", but can
- * r8712_set_key to fw/cam
- */
- if (wep_key_idx >= WEP_KEYS) {
- ret = -EOPNOTSUPP;
- goto exit;
- }
- memcpy(&psecuritypriv->DefKey[wep_key_idx].skey[0],
- pwep->KeyMaterial,
- pwep->KeyLength);
- psecuritypriv->DefKeylen[wep_key_idx] =
- pwep->KeyLength;
- r8712_set_key(padapter, psecuritypriv, wep_key_idx);
- }
- goto exit;
- }
- if (padapter->securitypriv.AuthAlgrthm == 2) { /* 802_1x */
- struct sta_info *psta, *pbcmc_sta;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct security_priv *spriv = &padapter->securitypriv;
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE |
- WIFI_MP_STATE)) { /* sta mode */
- psta = r8712_get_stainfo(pstapriv,
- get_bssid(pmlmepriv));
- if (psta) {
- psta->ieee8021x_blocked = false;
- if (spriv->ndisencryptstatus ==
- Ndis802_11Encryption2Enabled ||
- spriv->ndisencryptstatus ==
- Ndis802_11Encryption3Enabled)
- psta->XPrivacy = spriv->PrivacyAlgrthm;
- if (param->u.crypt.set_tx == 1)
- handle_pairwise_key(psta, param,
- padapter);
- else /* group key */
- handle_group_key(param, padapter);
- }
- pbcmc_sta = r8712_get_bcmc_stainfo(padapter);
- if (pbcmc_sta) {
- pbcmc_sta->ieee8021x_blocked = false;
- if (spriv->ndisencryptstatus ==
- Ndis802_11Encryption2Enabled ||
- spriv->ndisencryptstatus ==
- Ndis802_11Encryption3Enabled)
- pbcmc_sta->XPrivacy =
- spriv->PrivacyAlgrthm;
- }
- }
- }
-exit:
- kfree(pwep);
- return ret;
-}
-
-static int r871x_set_wpa_ie(struct _adapter *padapter, char *pie,
- unsigned short ielen)
-{
- u8 *buf = NULL;
- int group_cipher = 0, pairwise_cipher = 0;
- int ret = 0;
-
- if (ielen > MAX_WPA_IE_LEN || !pie)
- return -EINVAL;
- if (ielen) {
- buf = kmemdup(pie, ielen, GFP_ATOMIC);
- if (!buf)
- return -ENOMEM;
- if (ielen < RSN_HEADER_LEN) {
- ret = -EINVAL;
- goto exit;
- }
- if (r8712_parse_wpa_ie(buf, ielen, &group_cipher,
- &pairwise_cipher) == 0) {
- padapter->securitypriv.AuthAlgrthm = 2;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeWPAPSK;
- }
- if (r8712_parse_wpa2_ie(buf, ielen, &group_cipher,
- &pairwise_cipher) == 0) {
- padapter->securitypriv.AuthAlgrthm = 2;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeWPA2PSK;
- }
- switch (group_cipher) {
- case WPA_CIPHER_NONE:
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- break;
- case WPA_CIPHER_WEP40:
- padapter->securitypriv.XGrpPrivacy = _WEP40_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- case WPA_CIPHER_TKIP:
- padapter->securitypriv.XGrpPrivacy = _TKIP_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
- break;
- case WPA_CIPHER_CCMP:
- padapter->securitypriv.XGrpPrivacy = _AES_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
- break;
- case WPA_CIPHER_WEP104:
- padapter->securitypriv.XGrpPrivacy = _WEP104_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- }
- switch (pairwise_cipher) {
- case WPA_CIPHER_NONE:
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11EncryptionDisabled;
- break;
- case WPA_CIPHER_WEP40:
- padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- case WPA_CIPHER_TKIP:
- padapter->securitypriv.PrivacyAlgrthm = _TKIP_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption2Enabled;
- break;
- case WPA_CIPHER_CCMP:
- padapter->securitypriv.PrivacyAlgrthm = _AES_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption3Enabled;
- break;
- case WPA_CIPHER_WEP104:
- padapter->securitypriv.PrivacyAlgrthm = _WEP104_;
- padapter->securitypriv.ndisencryptstatus = Ndis802_11Encryption1Enabled;
- break;
- }
- padapter->securitypriv.wps_phase = false;
- {/* set wps_ie */
- u16 cnt = 0;
- u8 eid, wps_oui[4] = {0x0, 0x50, 0xf2, 0x04};
-
- while (cnt < ielen) {
- eid = buf[cnt];
-
- if ((eid == WLAN_EID_VENDOR_SPECIFIC) &&
- (!memcmp(&buf[cnt + 2], wps_oui, 4))) {
- netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE\n");
- padapter->securitypriv.wps_ie_len =
- ((buf[cnt + 1] + 2) <
- (MAX_WPA_IE_LEN << 2)) ?
- (buf[cnt + 1] + 2) :
- (MAX_WPA_IE_LEN << 2);
- memcpy(padapter->securitypriv.wps_ie,
- &buf[cnt],
- padapter->securitypriv.wps_ie_len);
- padapter->securitypriv.wps_phase =
- true;
- netdev_info(padapter->pnetdev, "r8712u: SET WPS_IE, wps_phase==true\n");
- cnt += buf[cnt + 1] + 2;
- break;
- }
-
- cnt += buf[cnt + 1] + 2;
- }
- }
- }
-exit:
- kfree(buf);
- return ret;
-}
-
-static int r8711_wx_get_name(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- u32 ht_ielen = 0;
- char *p;
- u8 ht_cap = false;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- u8 *prates;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE) == true) {
- /* parsing HT_CAP_IE */
- p = r8712_get_ie(&pcur_bss->IEs[12], WLAN_EID_HT_CAPABILITY,
- &ht_ielen, pcur_bss->IELength - 12);
- if (p && ht_ielen > 0)
- ht_cap = true;
- prates = pcur_bss->rates;
- if (r8712_is_cckratesonly_included(prates)) {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11bn");
- else
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11b");
- } else if (r8712_is_cckrates_included(prates)) {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11bgn");
- else
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11bg");
- } else {
- if (ht_cap)
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11gn");
- else
- snprintf(wrqu->name, IFNAMSIZ,
- "IEEE 802.11g");
- }
- } else {
- snprintf(wrqu->name, IFNAMSIZ, "unassociated");
- }
- return 0;
-}
-
-static const long frequency_list[] = {
- 2412, 2417, 2422, 2427, 2432, 2437, 2442, 2447, 2452, 2457, 2462,
- 2467, 2472, 2484, 4915, 4920, 4925, 4935, 4940, 4945, 4960, 4980,
- 5035, 5040, 5045, 5055, 5060, 5080, 5170, 5180, 5190, 5200, 5210,
- 5220, 5230, 5240, 5260, 5280, 5300, 5320, 5500, 5520, 5540, 5560,
- 5580, 5600, 5620, 5640, 5660, 5680, 5700, 5745, 5765, 5785, 5805,
- 5825
-};
-
-static int r8711_wx_set_freq(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_freq *fwrq = &wrqu->freq;
- int rc = 0;
-
-/* If setting by frequency, convert to a channel */
- if ((fwrq->e == 1) && (fwrq->m >= 241200000) && (fwrq->m <= 248700000)) {
- int f = fwrq->m / 100000;
- int c = 0;
-
- while ((c < 14) && (f != frequency_list[c]))
- c++;
- fwrq->e = 0;
- fwrq->m = c + 1;
- }
- /* Setting by channel number */
- if ((fwrq->m > 14) || (fwrq->e > 0)) {
- rc = -EOPNOTSUPP;
- } else {
- int channel = fwrq->m;
-
- if ((channel < 1) || (channel > 14)) {
- rc = -EINVAL;
- } else {
- /* Yes ! We can set it !!! */
- padapter->registrypriv.channel = channel;
- }
- }
- return rc;
-}
-
-static int r8711_wx_get_freq(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-
- if (!check_fwstate(pmlmepriv, _FW_LINKED))
- return -ENOLINK;
-
- wrqu->freq.m = ieee80211_wlan_frequencies[
- pcur_bss->Configuration.DSConfig - 1] * 100000;
- wrqu->freq.e = 1;
- wrqu->freq.i = pcur_bss->Configuration.DSConfig;
-
- return 0;
-}
-
-static int r8711_wx_set_mode(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct _adapter *padapter = netdev_priv(dev);
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE networkType;
-
- switch (wrqu->mode) {
- case IW_MODE_AUTO:
- networkType = Ndis802_11AutoUnknown;
- break;
- case IW_MODE_ADHOC:
- networkType = Ndis802_11IBSS;
- break;
- case IW_MODE_MASTER:
- networkType = Ndis802_11APMode;
- break;
- case IW_MODE_INFRA:
- networkType = Ndis802_11Infrastructure;
- break;
- default:
- return -EINVAL;
- }
- if (Ndis802_11APMode == networkType)
- r8712_setopmode_cmd(padapter, networkType);
- else
- r8712_setopmode_cmd(padapter, Ndis802_11AutoUnknown);
-
- r8712_set_802_11_infrastructure_mode(padapter, networkType);
- return 0;
-}
-
-static int r8711_wx_get_mode(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- wrqu->mode = IW_MODE_INFRA;
- else if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE | WIFI_ADHOC_STATE))
- wrqu->mode = IW_MODE_ADHOC;
- else if (check_fwstate(pmlmepriv, WIFI_AP_STATE))
- wrqu->mode = IW_MODE_MASTER;
- else
- wrqu->mode = IW_MODE_AUTO;
- return 0;
-}
-
-static int r871x_wx_set_pmkid(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct iw_pmksa *pPMK = (struct iw_pmksa *) extra;
- struct RT_PMKID_LIST *pl = psecuritypriv->PMKIDList;
- u8 strZeroMacAddress[ETH_ALEN] = {0x00};
- u8 strIssueBssid[ETH_ALEN] = {0x00};
- u8 j, blInserted = false;
- int intReturn = false;
-
-/*
- * There are the BSSID information in the bssid.sa_data array.
- * If cmd is IW_PMKSA_FLUSH, it means the wpa_supplicant wants to clear
- * all the PMKID information. If cmd is IW_PMKSA_ADD, it means the
- * wpa_supplicant wants to add a PMKID/BSSID to driver.
- * If cmd is IW_PMKSA_REMOVE, it means the wpa_supplicant wants to
- * remove a PMKID/BSSID from driver.
- */
- if (!pPMK)
- return -EINVAL;
- memcpy(strIssueBssid, pPMK->bssid.sa_data, ETH_ALEN);
- switch (pPMK->cmd) {
- case IW_PMKSA_ADD:
- if (!memcmp(strIssueBssid, strZeroMacAddress, ETH_ALEN))
- return intReturn;
- intReturn = true;
- blInserted = false;
- /* overwrite PMKID */
- for (j = 0; j < NUM_PMKID_CACHE; j++) {
- if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) {
- /* BSSID is matched, the same AP => rewrite
- * with new PMKID.
- */
- netdev_info(dev, "r8712u: %s: BSSID exists in the PMKList.\n",
- __func__);
- memcpy(pl[j].PMKID, pPMK->pmkid, IW_PMKID_LEN);
- pl[j].bUsed = true;
- psecuritypriv->PMKIDIndex = j + 1;
- blInserted = true;
- break;
- }
- }
- if (!blInserted) {
- /* Find a new entry */
- netdev_info(dev, "r8712u: %s: Use the new entry index = %d for this PMKID.\n",
- __func__, psecuritypriv->PMKIDIndex);
- memcpy(pl[psecuritypriv->PMKIDIndex].Bssid,
- strIssueBssid, ETH_ALEN);
- memcpy(pl[psecuritypriv->PMKIDIndex].PMKID,
- pPMK->pmkid, IW_PMKID_LEN);
- pl[psecuritypriv->PMKIDIndex].bUsed = true;
- psecuritypriv->PMKIDIndex++;
- if (psecuritypriv->PMKIDIndex == NUM_PMKID_CACHE)
- psecuritypriv->PMKIDIndex = 0;
- }
- break;
- case IW_PMKSA_REMOVE:
- intReturn = true;
- for (j = 0; j < NUM_PMKID_CACHE; j++) {
- if (!memcmp(pl[j].Bssid, strIssueBssid, ETH_ALEN)) {
- /* BSSID is matched, the same AP => Remove
- * this PMKID information and reset it.
- */
- eth_zero_addr(pl[j].Bssid);
- pl[j].bUsed = false;
- break;
- }
- }
- break;
- case IW_PMKSA_FLUSH:
- memset(psecuritypriv->PMKIDList, 0,
- sizeof(struct RT_PMKID_LIST) * NUM_PMKID_CACHE);
- psecuritypriv->PMKIDIndex = 0;
- intReturn = true;
- break;
- default:
- netdev_info(dev, "r8712u: %s: unknown Command\n", __func__);
- intReturn = false;
- break;
- }
- return intReturn;
-}
-
-static int r8711_wx_get_sens(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- wrqu->sens.value = 0;
- wrqu->sens.fixed = 0; /* no auto select */
- wrqu->sens.disabled = 1;
- return 0;
-}
-
-static int r8711_wx_get_range(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iw_range *range = (struct iw_range *)extra;
- u16 val;
- int i;
-
- wrqu->data.length = sizeof(*range);
- memset(range, 0, sizeof(*range));
- /* Let's try to keep this struct in the same order as in
- * linux/include/wireless.h
- */
-
- /* TODO: See what values we can set, and remove the ones we can't
- * set, or fill them with some default data.
- */
- /* ~5 Mb/s real (802.11b) */
- range->throughput = 5 * 1000 * 1000;
- /* TODO: 8711 sensitivity ? */
- /* signal level threshold range */
- /* percent values between 0 and 100. */
- range->max_qual.qual = 100;
- range->max_qual.level = 100;
- range->max_qual.noise = 100;
- range->max_qual.updated = 7; /* Updated all three */
- range->avg_qual.qual = 92; /* > 8% missed beacons is 'bad' */
- /* TODO: Find real 'good' to 'bad' threshold value for RSSI */
- range->avg_qual.level = 0x100 - 78;
- range->avg_qual.noise = 0;
- range->avg_qual.updated = 7; /* Updated all three */
- range->num_bitrates = RATE_COUNT;
- for (i = 0; i < RATE_COUNT && i < IW_MAX_BITRATES; i++)
- range->bitrate[i] = rtl8180_rates[i];
- range->min_frag = MIN_FRAG_THRESHOLD;
- range->max_frag = MAX_FRAG_THRESHOLD;
- range->pm_capa = 0;
- range->we_version_compiled = WIRELESS_EXT;
- range->we_version_source = 16;
- range->num_channels = 14;
- for (i = 0, val = 0; i < 14; i++) {
- /* Include only legal frequencies for some countries */
- range->freq[val].i = i + 1;
- range->freq[val].m = ieee80211_wlan_frequencies[i] * 100000;
- range->freq[val].e = 1;
- val++;
- if (val == IW_MAX_FREQUENCIES)
- break;
- }
- range->num_frequency = val;
- range->enc_capa = IW_ENC_CAPA_WPA |
- IW_ENC_CAPA_WPA2 |
- IW_ENC_CAPA_CIPHER_TKIP |
- IW_ENC_CAPA_CIPHER_CCMP;
- return 0;
-}
-
-static int r8711_wx_get_rate(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra);
-
-static int r871x_wx_set_priv(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *awrq,
- char *extra)
-{
- int ret = 0, len = 0;
- char *ext;
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *dwrq = (struct iw_point *)awrq;
-
- len = dwrq->length;
- ext = strndup_user(dwrq->pointer, len);
- if (IS_ERR(ext))
- return PTR_ERR(ext);
-
- if (!strcasecmp(ext, "RSSI")) {
- /*Return received signal strength indicator in -db for */
- /* current AP */
- /*<ssid> Rssi xx */
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct wlan_network *pcur_network = &pmlmepriv->cur_network;
- /*static u8 xxxx; */
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- sprintf(ext, "%s rssi %d",
- pcur_network->network.Ssid.Ssid,
- /*(xxxx=xxxx+10) */
- ((padapter->recvpriv.fw_rssi) >> 1) - 95
- /*pcur_network->network.Rssi */
- );
- } else {
- sprintf(ext, "OK");
- }
- } else if (!strcasecmp(ext, "LINKSPEED")) {
- /*Return link speed in MBPS */
- /*LinkSpeed xx */
- union iwreq_data wrqd;
- int ret_inner;
- int mbps;
-
- ret_inner = r8711_wx_get_rate(dev, info, &wrqd, extra);
- if (ret_inner != 0)
- mbps = 0;
- else
- mbps = wrqd.bitrate.value / 1000000;
- sprintf(ext, "LINKSPEED %d", mbps);
- } else if (!strcasecmp(ext, "MACADDR")) {
- /*Return mac address of the station */
- /* Macaddr = xx:xx:xx:xx:xx:xx */
- sprintf(ext, "MACADDR = %pM", dev->dev_addr);
- } else if (!strcasecmp(ext, "SCAN-ACTIVE")) {
- /*Set scan type to active */
- /*OK if successful */
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- pmlmepriv->passive_mode = 1;
- sprintf(ext, "OK");
- } else if (!strcasecmp(ext, "SCAN-PASSIVE")) {
- /*Set scan type to passive */
- /*OK if successful */
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- pmlmepriv->passive_mode = 0;
- sprintf(ext, "OK");
- } else if (!strncmp(ext, "DCE-E", 5)) {
- /*Set scan type to passive */
- /*OK if successful */
- r8712_disconnectCtrlEx_cmd(padapter
- , 1 /*u32 enableDrvCtrl */
- , 5 /*u32 tryPktCnt */
- , 100 /*u32 tryPktInterval */
- , 5000 /*u32 firstStageTO */
- );
- sprintf(ext, "OK");
- } else if (!strncmp(ext, "DCE-D", 5)) {
- /*Set scan type to passive */
- /*OK if successfu */
- r8712_disconnectCtrlEx_cmd(padapter
- , 0 /*u32 enableDrvCtrl */
- , 5 /*u32 tryPktCnt */
- , 100 /*u32 tryPktInterval */
- , 5000 /*u32 firstStageTO */
- );
- sprintf(ext, "OK");
- } else {
- netdev_info(dev, "r8712u: %s: unknown Command %s.\n", __func__, ext);
- goto FREE_EXT;
- }
- if (copy_to_user(dwrq->pointer, ext, min(dwrq->length, (__u16)(strlen(ext) + 1))))
- ret = -EFAULT;
-
-FREE_EXT:
- kfree(ext);
- return ret;
-}
-
-/* set bssid flow
- * s1. set_802_11_infrastructure_mode()
- * s2. set_802_11_authentication_mode()
- * s3. set_802_11_encryption_mode()
- * s4. set_802_11_bssid()
- *
- * This function intends to handle the Set AP command, which specifies the
- * MAC# of a preferred Access Point.
- * Currently, the request comes via Wireless Extensions' SIOCSIWAP ioctl.
- *
- * For this operation to succeed, there is no need for the interface to be up.
- *
- */
-static int r8711_wx_set_wap(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *awrq, char *extra)
-{
- int ret = -EINPROGRESS;
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct sockaddr *temp = (struct sockaddr *)awrq;
- unsigned long irqL;
- struct list_head *phead;
- u8 *dst_bssid;
- struct wlan_network *pnetwork = NULL;
- enum NDIS_802_11_AUTHENTICATION_MODE authmode;
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- return -EBUSY;
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- return ret;
- if (temp->sa_family != ARPHRD_ETHER)
- return -EINVAL;
- authmode = padapter->securitypriv.ndisauthtype;
- spin_lock_irqsave(&queue->lock, irqL);
- phead = &queue->queue;
- pmlmepriv->pscanned = phead->next;
- while (1) {
- if (end_of_queue_search(phead, pmlmepriv->pscanned))
- break;
- pnetwork = container_of(pmlmepriv->pscanned,
- struct wlan_network, list);
- pmlmepriv->pscanned = pmlmepriv->pscanned->next;
- dst_bssid = pnetwork->network.MacAddress;
- if (!memcmp(dst_bssid, temp->sa_data, ETH_ALEN)) {
- r8712_set_802_11_infrastructure_mode(padapter,
- pnetwork->network.InfrastructureMode);
- break;
- }
- }
- spin_unlock_irqrestore(&queue->lock, irqL);
- if (!ret) {
- if (!r8712_set_802_11_authentication_mode(padapter, authmode)) {
- ret = -ENOMEM;
- } else {
- if (!r8712_set_802_11_bssid(padapter, temp->sa_data))
- ret = -1;
- }
- }
- return ret;
-}
-
-static int r8711_wx_get_wap(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
-
- wrqu->ap_addr.sa_family = ARPHRD_ETHER;
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
- ether_addr_copy(wrqu->ap_addr.sa_data, pcur_bss->MacAddress);
- else
- eth_zero_addr(wrqu->ap_addr.sa_data);
- return 0;
-}
-
-static int r871x_wx_set_mlme(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_mlme *mlme = (struct iw_mlme *) extra;
-
- if (!mlme)
- return -1;
- switch (mlme->cmd) {
- case IW_MLME_DEAUTH:
- if (!r8712_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- case IW_MLME_DISASSOC:
- if (!r8712_set_802_11_disassociate(padapter))
- ret = -1;
- break;
- default:
- return -EOPNOTSUPP;
- }
- return ret;
-}
-
-/*
- *
- * This function intends to handle the Set Scan command.
- * Currently, the request comes via Wireless Extensions' SIOCSIWSCAN ioctl.
- *
- * For this operation to succeed, the interface is brought Up beforehand.
- *
- */
-static int r8711_wx_set_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- u8 status = true;
-
- if (padapter->driver_stopped) {
- netdev_info(dev, "In %s: driver_stopped=%d\n",
- __func__, padapter->driver_stopped);
- return -1;
- }
- if (!padapter->bup)
- return -ENETDOWN;
- if (!padapter->hw_init_completed)
- return -1;
- if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) ||
- (pmlmepriv->sitesurveyctrl.traffic_busy))
- return 0;
- if (wrqu->data.length == sizeof(struct iw_scan_req)) {
- struct iw_scan_req *req = (struct iw_scan_req *)extra;
-
- if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- struct ndis_802_11_ssid ssid;
- unsigned long irqL;
- u32 len = min_t(u8, req->essid_len, IW_ESSID_MAX_SIZE);
-
- memset((unsigned char *)&ssid, 0, sizeof(struct ndis_802_11_ssid));
- memcpy(ssid.Ssid, req->essid, len);
- ssid.SsidLength = len;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if ((check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
- _FW_UNDER_LINKING)) ||
- (pmlmepriv->sitesurveyctrl.traffic_busy)) {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- status = false;
- } else {
- status = r8712_sitesurvey_cmd(padapter, &ssid);
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- }
- } else {
- status = r8712_set_802_11_bssid_list_scan(padapter);
- }
- if (!status)
- return -1;
- return 0;
-}
-
-static int r8711_wx_get_scan(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- unsigned long irqL;
- struct list_head *plist, *phead;
- char *ev = extra;
- char *stop = ev + wrqu->data.length;
- u32 ret = 0, cnt = 0;
-
- if (padapter->driver_stopped)
- return -EINVAL;
- while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
- msleep(30);
- cnt++;
- if (cnt > 100)
- break;
- }
- spin_lock_irqsave(&queue->lock, irqL);
- phead = &queue->queue;
- plist = phead->next;
- while (1) {
- if (end_of_queue_search(phead, plist))
- break;
- if ((stop - ev) < SCAN_ITEM_SIZE) {
- ret = -E2BIG;
- break;
- }
- pnetwork = container_of(plist, struct wlan_network, list);
- ev = translate_scan(padapter, a, pnetwork, ev, stop);
- plist = plist->next;
- }
- spin_unlock_irqrestore(&queue->lock, irqL);
- wrqu->data.length = ev - extra;
- wrqu->data.flags = 0;
- return ret;
-}
-
-/* set ssid flow
- * s1. set_802_11_infrastructure_mode()
- * s2. set_802_11_authenticaion_mode()
- * s3. set_802_11_encryption_mode()
- * s4. set_802_11_ssid()
- *
- * This function intends to handle the Set ESSID command.
- * Currently, the request comes via the Wireless Extensions' SIOCSIWESSID ioctl.
- *
- * For this operation to succeed, there is no need for the interface to be Up.
- *
- */
-static int r8711_wx_set_essid(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- enum NDIS_802_11_AUTHENTICATION_MODE authmode;
- struct ndis_802_11_ssid ndis_ssid;
- u8 *dst_ssid, *src_ssid;
- struct list_head *phead;
- u32 len;
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY))
- return -EBUSY;
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- return 0;
- if (wrqu->essid.length > IW_ESSID_MAX_SIZE)
- return -E2BIG;
- authmode = padapter->securitypriv.ndisauthtype;
- if (wrqu->essid.flags && wrqu->essid.length) {
- len = (wrqu->essid.length < IW_ESSID_MAX_SIZE) ?
- wrqu->essid.length : IW_ESSID_MAX_SIZE;
- memset(&ndis_ssid, 0, sizeof(struct ndis_802_11_ssid));
- ndis_ssid.SsidLength = len;
- memcpy(ndis_ssid.Ssid, extra, len);
- src_ssid = ndis_ssid.Ssid;
- phead = &queue->queue;
- pmlmepriv->pscanned = phead->next;
- while (1) {
- if (end_of_queue_search(phead, pmlmepriv->pscanned))
- break;
- pnetwork = container_of(pmlmepriv->pscanned,
- struct wlan_network, list);
- pmlmepriv->pscanned = pmlmepriv->pscanned->next;
- dst_ssid = pnetwork->network.Ssid.Ssid;
- if ((!memcmp(dst_ssid, src_ssid, ndis_ssid.SsidLength))
- && (pnetwork->network.Ssid.SsidLength ==
- ndis_ssid.SsidLength)) {
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- if (pnetwork->network.
- InfrastructureMode
- !=
- padapter->mlmepriv.
- cur_network.network.
- InfrastructureMode)
- continue;
- }
-
- r8712_set_802_11_infrastructure_mode(
- padapter,
- pnetwork->network.InfrastructureMode);
- break;
- }
- }
- r8712_set_802_11_authentication_mode(padapter, authmode);
- r8712_set_802_11_ssid(padapter, &ndis_ssid);
- }
- return -EINPROGRESS;
-}
-
-static int r8711_wx_get_essid(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- u32 len, ret = 0;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
- len = pcur_bss->Ssid.SsidLength;
- wrqu->essid.length = len;
- memcpy(extra, pcur_bss->Ssid.Ssid, len);
- wrqu->essid.flags = 1;
- } else {
- ret = -ENOLINK;
- }
- return ret;
-}
-
-static int r8711_wx_set_rate(struct net_device *dev, struct iw_request_info *a,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- u32 target_rate = wrqu->bitrate.value;
- u32 fixed = wrqu->bitrate.fixed;
- u32 ratevalue = 0;
- u8 datarates[NumRates];
- u8 mpdatarate[NumRates] = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0xff};
- int i;
-
- if (target_rate == -1) {
- ratevalue = 11;
- goto set_rate;
- }
- target_rate = target_rate / 100000;
- switch (target_rate) {
- case 10:
- ratevalue = 0;
- break;
- case 20:
- ratevalue = 1;
- break;
- case 55:
- ratevalue = 2;
- break;
- case 60:
- ratevalue = 3;
- break;
- case 90:
- ratevalue = 4;
- break;
- case 110:
- ratevalue = 5;
- break;
- case 120:
- ratevalue = 6;
- break;
- case 180:
- ratevalue = 7;
- break;
- case 240:
- ratevalue = 8;
- break;
- case 360:
- ratevalue = 9;
- break;
- case 480:
- ratevalue = 10;
- break;
- case 540:
- ratevalue = 11;
- break;
- default:
- ratevalue = 11;
- break;
- }
-set_rate:
- for (i = 0; i < NumRates; i++) {
- if (ratevalue == mpdatarate[i]) {
- datarates[i] = mpdatarate[i];
- if (fixed == 0)
- break;
- } else {
- datarates[i] = 0xff;
- }
- }
- return r8712_setdatarate_cmd(padapter, datarates);
-}
-
-static int r8711_wx_get_rate(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_bssid_ex *pcur_bss = &pmlmepriv->cur_network.network;
- struct ieee80211_ht_cap *pht_capie;
- unsigned char rf_type = padapter->registrypriv.rf_config;
- int i;
- u8 *p;
- u16 rate, max_rate = 0, ht_cap = false;
- u32 ht_ielen = 0;
- u8 bw_40MHz = 0, short_GI = 0;
- u16 mcs_rate = 0;
-
- i = 0;
- if (!check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE))
- return -ENOLINK;
- p = r8712_get_ie(&pcur_bss->IEs[12], WLAN_EID_HT_CAPABILITY, &ht_ielen,
- pcur_bss->IELength - 12);
- if (p && ht_ielen > 0) {
- ht_cap = true;
- pht_capie = (struct ieee80211_ht_cap *)(p + 2);
- memcpy(&mcs_rate, &pht_capie->mcs, 2);
- bw_40MHz = (le16_to_cpu(pht_capie->cap_info) &
- IEEE80211_HT_CAP_SUP_WIDTH_20_40) ? 1 : 0;
- short_GI = (le16_to_cpu(pht_capie->cap_info) &
- (IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40)) ? 1 : 0;
- }
- while ((pcur_bss->rates[i] != 0) &&
- (pcur_bss->rates[i] != 0xFF)) {
- rate = pcur_bss->rates[i] & 0x7F;
- if (rate > max_rate)
- max_rate = rate;
- wrqu->bitrate.fixed = 0; /* no auto select */
- wrqu->bitrate.value = rate * 500000;
- i++;
- }
- if (ht_cap) {
- if (mcs_rate & 0x8000 /* MCS15 */
- &&
- rf_type == RTL8712_RF_2T2R)
- max_rate = (bw_40MHz) ? ((short_GI) ? 300 : 270) :
- ((short_GI) ? 144 : 130);
- else /* default MCS7 */
- max_rate = (bw_40MHz) ? ((short_GI) ? 150 : 135) :
- ((short_GI) ? 72 : 65);
- max_rate *= 2; /* Mbps/2 */
- }
- wrqu->bitrate.value = max_rate * 500000;
- return 0;
-}
-
-static int r8711_wx_get_rts(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- wrqu->rts.value = padapter->registrypriv.rts_thresh;
- wrqu->rts.fixed = 0; /* no auto select */
- return 0;
-}
-
-static int r8711_wx_set_frag(struct net_device *dev, struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- if (wrqu->frag.disabled) {
- padapter->xmitpriv.frag_len = MAX_FRAG_THRESHOLD;
- } else {
- if (wrqu->frag.value < MIN_FRAG_THRESHOLD ||
- wrqu->frag.value > MAX_FRAG_THRESHOLD)
- return -EINVAL;
- padapter->xmitpriv.frag_len = wrqu->frag.value & ~0x1;
- }
- return 0;
-}
-
-static int r8711_wx_get_frag(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- wrqu->frag.value = padapter->xmitpriv.frag_len;
- wrqu->frag.fixed = 0; /* no auto select */
- return 0;
-}
-
-static int r8711_wx_get_retry(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- wrqu->retry.value = 7;
- wrqu->retry.fixed = 0; /* no auto select */
- wrqu->retry.disabled = 1;
- return 0;
-}
-
-static int r8711_wx_set_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- u32 key;
- u32 keyindex_provided;
- struct NDIS_802_11_WEP wep;
- enum NDIS_802_11_AUTHENTICATION_MODE authmode;
- struct iw_point *erq = &wrqu->encoding;
- struct _adapter *padapter = netdev_priv(dev);
-
- key = erq->flags & IW_ENCODE_INDEX;
- memset(&wep, 0, sizeof(struct NDIS_802_11_WEP));
- if (erq->flags & IW_ENCODE_DISABLED) {
- netdev_info(dev, "r8712u: %s: EncryptionDisabled\n", __func__);
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11EncryptionDisabled;
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- padapter->securitypriv.AuthAlgrthm = 0; /* open system */
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- return 0;
- }
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- keyindex_provided = 1;
- } else {
- keyindex_provided = 0;
- key = padapter->securitypriv.PrivacyKeyIndex;
- }
- /* set authentication mode */
- if (erq->flags & IW_ENCODE_OPEN) {
- netdev_info(dev, "r8712u: %s: IW_ENCODE_OPEN\n", __func__);
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.AuthAlgrthm = 0; /* open system */
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- } else if (erq->flags & IW_ENCODE_RESTRICTED) {
- netdev_info(dev,
- "r8712u: %s: IW_ENCODE_RESTRICTED\n", __func__);
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.AuthAlgrthm = 1; /* shared system */
- padapter->securitypriv.PrivacyAlgrthm = _WEP40_;
- padapter->securitypriv.XGrpPrivacy = _WEP40_;
- authmode = Ndis802_11AuthModeShared;
- padapter->securitypriv.ndisauthtype = authmode;
- } else {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption1Enabled;
- padapter->securitypriv.AuthAlgrthm = 0; /* open system */
- padapter->securitypriv.PrivacyAlgrthm = _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy = _NO_PRIVACY_;
- authmode = Ndis802_11AuthModeOpen;
- padapter->securitypriv.ndisauthtype = authmode;
- }
- wep.KeyIndex = key;
- if (erq->length > 0) {
- wep.KeyLength = erq->length <= 5 ? 5 : 13;
- wep.Length = wep.KeyLength +
- offsetof(struct NDIS_802_11_WEP, KeyMaterial);
- } else {
- wep.KeyLength = 0;
- if (keyindex_provided == 1) { /* set key_id only, no given
- * KeyMaterial(erq->length==0).
- */
- padapter->securitypriv.PrivacyKeyIndex = key;
- switch (padapter->securitypriv.DefKeylen[key]) {
- case 5:
- padapter->securitypriv.PrivacyAlgrthm =
- _WEP40_;
- break;
- case 13:
- padapter->securitypriv.PrivacyAlgrthm =
- _WEP104_;
- break;
- default:
- padapter->securitypriv.PrivacyAlgrthm =
- _NO_PRIVACY_;
- break;
- }
- return 0;
- }
- }
- wep.KeyIndex |= 0x80000000; /* transmit key */
- memcpy(wep.KeyMaterial, keybuf, wep.KeyLength);
- if (r8712_set_802_11_add_wep(padapter, &wep))
- return -EOPNOTSUPP;
- return 0;
-}
-
-static int r8711_wx_get_enc(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- uint key;
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *erq = &wrqu->encoding;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- union Keytype *dk = padapter->securitypriv.DefKey;
-
- if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (!check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- return 0;
- }
- }
- key = erq->flags & IW_ENCODE_INDEX;
- if (key) {
- if (key > WEP_KEYS)
- return -EINVAL;
- key--;
- } else {
- key = padapter->securitypriv.PrivacyKeyIndex;
- }
- erq->flags = key + 1;
- switch (padapter->securitypriv.ndisencryptstatus) {
- case Ndis802_11EncryptionNotSupported:
- case Ndis802_11EncryptionDisabled:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- break;
- case Ndis802_11Encryption1Enabled:
- erq->length = padapter->securitypriv.DefKeylen[key];
- if (erq->length) {
- memcpy(keybuf, dk[key].skey,
- padapter->securitypriv.DefKeylen[key]);
- erq->flags |= IW_ENCODE_ENABLED;
- if (padapter->securitypriv.ndisauthtype ==
- Ndis802_11AuthModeOpen)
- erq->flags |= IW_ENCODE_OPEN;
- else if (padapter->securitypriv.ndisauthtype ==
- Ndis802_11AuthModeShared)
- erq->flags |= IW_ENCODE_RESTRICTED;
- } else {
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- }
- break;
- case Ndis802_11Encryption2Enabled:
- case Ndis802_11Encryption3Enabled:
- erq->length = 16;
- erq->flags |= (IW_ENCODE_ENABLED | IW_ENCODE_OPEN |
- IW_ENCODE_NOKEY);
- break;
- default:
- erq->length = 0;
- erq->flags |= IW_ENCODE_DISABLED;
- break;
- }
- return 0;
-}
-
-static int r8711_wx_get_power(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- wrqu->power.value = 0;
- wrqu->power.fixed = 0; /* no auto select */
- wrqu->power.disabled = 1;
- return 0;
-}
-
-static int r871x_wx_set_gen_ie(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- return r871x_set_wpa_ie(padapter, extra, wrqu->data.length);
-}
-
-static int r871x_wx_set_auth(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_param *param = (struct iw_param *)&wrqu->param;
- int paramid;
- int paramval;
- int ret = 0;
-
- paramid = param->flags & IW_AUTH_INDEX;
- paramval = param->value;
- switch (paramid) {
- case IW_AUTH_WPA_VERSION:
- break;
- case IW_AUTH_CIPHER_PAIRWISE:
- break;
- case IW_AUTH_CIPHER_GROUP:
- break;
- case IW_AUTH_KEY_MGMT:
- /*
- * ??? does not use these parameters
- */
- break;
- case IW_AUTH_TKIP_COUNTERMEASURES:
- if (paramval) {
- /* wpa_supplicant is enabling tkip countermeasure. */
- padapter->securitypriv.btkip_countermeasure = true;
- } else {
- /* wpa_supplicant is disabling tkip countermeasure. */
- padapter->securitypriv.btkip_countermeasure = false;
- }
- break;
- case IW_AUTH_DROP_UNENCRYPTED:
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
- if (padapter->securitypriv.ndisencryptstatus ==
- Ndis802_11Encryption1Enabled) {
- /* it means init value, or using wep,
- * ndisencryptstatus =
- * Ndis802_11Encryption1Enabled,
- * then it needn't reset it;
- */
- break;
- }
-
- if (paramval) {
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11EncryptionDisabled;
- padapter->securitypriv.PrivacyAlgrthm =
- _NO_PRIVACY_;
- padapter->securitypriv.XGrpPrivacy =
- _NO_PRIVACY_;
- padapter->securitypriv.AuthAlgrthm = 0;
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeOpen;
- }
- break;
- case IW_AUTH_80211_AUTH_ALG:
- ret = wpa_set_auth_algs(dev, (u32)paramval);
- break;
- case IW_AUTH_WPA_ENABLED:
- break;
- case IW_AUTH_RX_UNENCRYPTED_EAPOL:
- break;
- case IW_AUTH_PRIVACY_INVOKED:
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- return ret;
-}
-
-static int r871x_wx_set_enc_ext(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct iw_point *pencoding = &wrqu->encoding;
- struct iw_encode_ext *pext = (struct iw_encode_ext *)extra;
- struct ieee_param *param = NULL;
- char *alg_name;
- u32 param_len;
- int ret = 0;
-
- switch (pext->alg) {
- case IW_ENCODE_ALG_NONE:
- alg_name = "none";
- break;
- case IW_ENCODE_ALG_WEP:
- alg_name = "WEP";
- break;
- case IW_ENCODE_ALG_TKIP:
- alg_name = "TKIP";
- break;
- case IW_ENCODE_ALG_CCMP:
- alg_name = "CCMP";
- break;
- default:
- return -EINVAL;
- }
-
- param_len = sizeof(struct ieee_param) + pext->key_len;
- param = kzalloc(param_len, GFP_ATOMIC);
- if (!param)
- return -ENOMEM;
- param->cmd = IEEE_CMD_SET_ENCRYPTION;
- eth_broadcast_addr(param->sta_addr);
- strscpy((char *)param->u.crypt.alg, alg_name, IEEE_CRYPT_ALG_NAME_LEN);
- if (pext->ext_flags & IW_ENCODE_EXT_GROUP_KEY)
- param->u.crypt.set_tx = 0;
- if (pext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY)
- param->u.crypt.set_tx = 1;
- param->u.crypt.idx = (pencoding->flags & 0x00FF) - 1;
- if (pext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID)
- memcpy(param->u.crypt.seq, pext->rx_seq, 8);
- if (pext->key_len) {
- param->u.crypt.key_len = pext->key_len;
- memcpy(param + 1, pext + 1, pext->key_len);
- }
- ret = wpa_set_encryption(dev, param, param_len);
- kfree(param);
- return ret;
-}
-
-static int r871x_wx_get_nick(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- if (extra) {
- wrqu->data.length = 8;
- wrqu->data.flags = 1;
- memcpy(extra, "rtl_wifi", 8);
- }
- return 0;
-}
-
-static int r8711_wx_read32(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- struct _adapter *padapter = netdev_priv(dev);
- u32 addr;
- u32 data32;
-
- get_user(addr, (u32 __user *)wrqu->data.pointer);
- data32 = r8712_read32(padapter, addr);
- put_user(data32, (u32 __user *)wrqu->data.pointer);
- wrqu->data.length = (data32 & 0xffff0000) >> 16;
- wrqu->data.flags = data32 & 0xffff;
- get_user(addr, (u32 __user *)wrqu->data.pointer);
- return 0;
-}
-
-static int r8711_wx_write32(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *keybuf)
-{
- struct _adapter *padapter = netdev_priv(dev);
- u32 addr;
- u32 data32;
-
- get_user(addr, (u32 __user *)wrqu->data.pointer);
- data32 = ((u32)wrqu->data.length << 16) | (u32)wrqu->data.flags;
- r8712_write32(padapter, addr, data32);
- return 0;
-}
-
-static int dummy(struct net_device *dev,
- struct iw_request_info *a,
- union iwreq_data *wrqu, char *b)
-{
- return -EINVAL;
-}
-
-static int r8711_drvext_hdl(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- return 0;
-}
-
-static int r871x_mp_ioctl_hdl(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *p = &wrqu->data;
- struct oid_par_priv oid_par;
- struct mp_ioctl_handler *phandler;
- struct mp_ioctl_param *poidparam;
- unsigned long BytesRead, BytesWritten, BytesNeeded;
- u8 *pparmbuf, bset;
- u16 len;
- uint status;
- int ret = 0;
-
- if ((!p->length) || (!p->pointer))
- return -EINVAL;
-
- bset = (u8)(p->flags & 0xFFFF);
- len = p->length;
- pparmbuf = memdup_user(p->pointer, len);
- if (IS_ERR(pparmbuf))
- return PTR_ERR(pparmbuf);
-
- poidparam = (struct mp_ioctl_param *)pparmbuf;
- if (poidparam->subcode >= MAX_MP_IOCTL_SUBCODE) {
- ret = -EINVAL;
- goto _r871x_mp_ioctl_hdl_exit;
- }
- phandler = mp_ioctl_hdl + poidparam->subcode;
- if ((phandler->paramsize != 0) &&
- (poidparam->len < phandler->paramsize)) {
- ret = -EINVAL;
- goto _r871x_mp_ioctl_hdl_exit;
- }
- if (phandler->oid == 0 && phandler->handler) {
- status = phandler->handler(&oid_par);
- } else if (phandler->handler) {
- oid_par.adapter_context = padapter;
- oid_par.oid = phandler->oid;
- oid_par.information_buf = poidparam->data;
- oid_par.information_buf_len = poidparam->len;
- oid_par.dbg = 0;
- BytesWritten = 0;
- BytesNeeded = 0;
- if (bset) {
- oid_par.bytes_rw = &BytesRead;
- oid_par.bytes_needed = &BytesNeeded;
- oid_par.type_of_oid = SET_OID;
- } else {
- oid_par.bytes_rw = &BytesWritten;
- oid_par.bytes_needed = &BytesNeeded;
- oid_par.type_of_oid = QUERY_OID;
- }
- status = phandler->handler(&oid_par);
- /* todo:check status, BytesNeeded, etc. */
- } else {
- netdev_info(dev, "r8712u: %s: err!, subcode=%d, oid=%d, handler=%p\n",
- __func__, poidparam->subcode, phandler->oid,
- phandler->handler);
- ret = -EFAULT;
- goto _r871x_mp_ioctl_hdl_exit;
- }
- if (bset == 0x00) { /* query info */
- if (copy_to_user(p->pointer, pparmbuf, len))
- ret = -EFAULT;
- }
- if (status) {
- ret = -EFAULT;
- goto _r871x_mp_ioctl_hdl_exit;
- }
-_r871x_mp_ioctl_hdl_exit:
- kfree(pparmbuf);
- return ret;
-}
-
-static int r871x_get_ap_info(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct iw_point *pdata = &wrqu->data;
- struct wlan_network *pnetwork = NULL;
- u32 cnt = 0, wpa_ielen;
- unsigned long irqL;
- struct list_head *plist, *phead;
- unsigned char *pbuf;
- u8 bssid[ETH_ALEN];
- char data[33];
-
- if (padapter->driver_stopped || !pdata)
- return -EINVAL;
- while (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
- _FW_UNDER_LINKING)) {
- msleep(30);
- cnt++;
- if (cnt > 100)
- break;
- }
- pdata->flags = 0;
- if (pdata->length < 32)
- return -EINVAL;
- if (copy_from_user(data, pdata->pointer, 32))
- return -EINVAL;
- data[32] = 0;
-
- spin_lock_irqsave(&pmlmepriv->scanned_queue.lock, irqL);
- phead = &queue->queue;
- plist = phead->next;
- while (1) {
- if (end_of_queue_search(phead, plist))
- break;
- pnetwork = container_of(plist, struct wlan_network, list);
- if (!mac_pton(data, bssid)) {
- netdev_info(dev, "r8712u: Invalid BSSID '%s'.\n",
- (u8 *)data);
- spin_unlock_irqrestore(&pmlmepriv->scanned_queue.lock,
- irqL);
- return -EINVAL;
- }
- netdev_info(dev, "r8712u: BSSID:%pM\n", bssid);
- if (ether_addr_equal(bssid, pnetwork->network.MacAddress)) {
- /* BSSID match, then check if supporting wpa/wpa2 */
- pbuf = r8712_get_wpa_ie(&pnetwork->network.IEs[12],
- &wpa_ielen, pnetwork->network.IELength - 12);
- if (pbuf && (wpa_ielen > 0)) {
- pdata->flags = 1;
- break;
- }
- pbuf = r8712_get_wpa2_ie(&pnetwork->network.IEs[12],
- &wpa_ielen, pnetwork->network.IELength - 12);
- if (pbuf && (wpa_ielen > 0)) {
- pdata->flags = 2;
- break;
- }
- }
- plist = plist->next;
- }
- spin_unlock_irqrestore(&pmlmepriv->scanned_queue.lock, irqL);
- if (pdata->length >= 34) {
- if (copy_to_user((u8 __user *)pdata->pointer + 32,
- (u8 *)&pdata->flags, 1))
- return -EINVAL;
- }
- return 0;
-}
-
-static int r871x_set_pid(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
-
- if (padapter->driver_stopped || !pdata)
- return -EINVAL;
- if (copy_from_user(&padapter->pid, pdata->pointer, sizeof(int)))
- return -EINVAL;
- return 0;
-}
-
-static int r871x_set_chplan(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- int ret = 0;
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- int ch_plan = -1;
-
- if (padapter->driver_stopped || !pdata) {
- ret = -EINVAL;
- goto exit;
- }
- ch_plan = (int)*extra;
- r8712_set_chplan_cmd(padapter, ch_plan);
-
-exit:
-
- return ret;
-}
-
-static int r871x_wps_start(struct net_device *dev,
- struct iw_request_info *info,
- union iwreq_data *wrqu, char *extra)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_point *pdata = &wrqu->data;
- u32 u32wps_start = 0;
-
- if (padapter->driver_stopped || !pdata)
- return -EINVAL;
- if (copy_from_user((void *)&u32wps_start, pdata->pointer, 4))
- return -EFAULT;
- if (u32wps_start == 0)
- u32wps_start = *extra;
- if (u32wps_start == 1) /* WPS Start */
- padapter->ledpriv.LedControlHandler(padapter,
- LED_CTL_START_WPS);
- else if (u32wps_start == 2) /* WPS Stop because of wps success */
- padapter->ledpriv.LedControlHandler(padapter,
- LED_CTL_STOP_WPS);
- else if (u32wps_start == 3) /* WPS Stop because of wps fail */
- padapter->ledpriv.LedControlHandler(padapter,
- LED_CTL_STOP_WPS_FAIL);
- return 0;
-}
-
-static int wpa_set_param(struct net_device *dev, u8 name, u32 value)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- switch (name) {
- case IEEE_PARAM_WPA_ENABLED:
- padapter->securitypriv.AuthAlgrthm = 2; /* 802.1x */
- switch ((value) & 0xff) {
- case 1: /* WPA */
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeWPAPSK; /* WPA_PSK */
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption2Enabled;
- break;
- case 2: /* WPA2 */
- padapter->securitypriv.ndisauthtype =
- Ndis802_11AuthModeWPA2PSK; /* WPA2_PSK */
- padapter->securitypriv.ndisencryptstatus =
- Ndis802_11Encryption3Enabled;
- break;
- }
- break;
- case IEEE_PARAM_TKIP_COUNTERMEASURES:
- break;
- case IEEE_PARAM_DROP_UNENCRYPTED:
- /* HACK:
- *
- * wpa_supplicant calls set_wpa_enabled when the driver
- * is loaded and unloaded, regardless of if WPA is being
- * used. No other calls are made which can be used to
- * determine if encryption will be used or not prior to
- * association being expected. If encryption is not being
- * used, drop_unencrypted is set to false, else true -- we
- * can use this to determine if the CAP_PRIVACY_ON bit should
- * be set.
- */
- break;
- case IEEE_PARAM_PRIVACY_INVOKED:
- break;
- case IEEE_PARAM_AUTH_ALGS:
- return wpa_set_auth_algs(dev, value);
- case IEEE_PARAM_IEEE_802_1X:
- break;
- case IEEE_PARAM_WPAX_SELECT:
- /* added for WPA2 mixed mode */
- break;
- default:
- return -EOPNOTSUPP;
- }
- return 0;
-}
-
-static int wpa_mlme(struct net_device *dev, u32 command, u32 reason)
-{
- struct _adapter *padapter = netdev_priv(dev);
-
- switch (command) {
- case IEEE_MLME_STA_DEAUTH:
- if (!r8712_set_802_11_disassociate(padapter))
- return -1;
- break;
- case IEEE_MLME_STA_DISASSOC:
- if (!r8712_set_802_11_disassociate(padapter))
- return -1;
- break;
- default:
- return -EOPNOTSUPP;
- }
- return 0;
-}
-
-static int wpa_supplicant_ioctl(struct net_device *dev, struct iw_point *p)
-{
- struct ieee_param *param;
- int ret = 0;
- struct _adapter *padapter = netdev_priv(dev);
-
- if (p->length < sizeof(struct ieee_param) || !p->pointer)
- return -EINVAL;
- param = memdup_user(p->pointer, p->length);
- if (IS_ERR(param))
- return PTR_ERR(param);
- switch (param->cmd) {
- case IEEE_CMD_SET_WPA_PARAM:
- ret = wpa_set_param(dev, param->u.wpa_param.name,
- param->u.wpa_param.value);
- break;
- case IEEE_CMD_SET_WPA_IE:
- ret = r871x_set_wpa_ie(padapter, (char *)param->u.wpa_ie.data,
- (u16)param->u.wpa_ie.len);
- break;
- case IEEE_CMD_SET_ENCRYPTION:
- ret = wpa_set_encryption(dev, param, p->length);
- break;
- case IEEE_CMD_MLME:
- ret = wpa_mlme(dev, param->u.mlme.command,
- param->u.mlme.reason_code);
- break;
- default:
- ret = -EOPNOTSUPP;
- break;
- }
- if (ret == 0 && copy_to_user(p->pointer, param, p->length))
- ret = -EFAULT;
- kfree(param);
- return ret;
-}
-
-/* based on "driver_ipw" and for hostapd */
-int r871x_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
-{
- struct iwreq *wrq = (struct iwreq *)rq;
-
- switch (cmd) {
- case RTL_IOCTL_WPA_SUPPLICANT:
- return wpa_supplicant_ioctl(dev, &wrq->u.data);
- default:
- return -EOPNOTSUPP;
- }
- return 0;
-}
-
-static iw_handler r8711_handlers[] = {
- NULL, /* SIOCSIWCOMMIT */
- r8711_wx_get_name, /* SIOCGIWNAME */
- dummy, /* SIOCSIWNWID */
- dummy, /* SIOCGIWNWID */
- r8711_wx_set_freq, /* SIOCSIWFREQ */
- r8711_wx_get_freq, /* SIOCGIWFREQ */
- r8711_wx_set_mode, /* SIOCSIWMODE */
- r8711_wx_get_mode, /* SIOCGIWMODE */
- dummy, /* SIOCSIWSENS */
- r8711_wx_get_sens, /* SIOCGIWSENS */
- NULL, /* SIOCSIWRANGE */
- r8711_wx_get_range, /* SIOCGIWRANGE */
- r871x_wx_set_priv, /* SIOCSIWPRIV */
- NULL, /* SIOCGIWPRIV */
- NULL, /* SIOCSIWSTATS */
- NULL, /* SIOCGIWSTATS */
- dummy, /* SIOCSIWSPY */
- dummy, /* SIOCGIWSPY */
- NULL, /* SIOCGIWTHRSPY */
- NULL, /* SIOCWIWTHRSPY */
- r8711_wx_set_wap, /* SIOCSIWAP */
- r8711_wx_get_wap, /* SIOCGIWAP */
- r871x_wx_set_mlme, /* request MLME operation;
- * uses struct iw_mlme
- */
- dummy, /* SIOCGIWAPLIST -- deprecated */
- r8711_wx_set_scan, /* SIOCSIWSCAN */
- r8711_wx_get_scan, /* SIOCGIWSCAN */
- r8711_wx_set_essid, /* SIOCSIWESSID */
- r8711_wx_get_essid, /* SIOCGIWESSID */
- dummy, /* SIOCSIWNICKN */
- r871x_wx_get_nick, /* SIOCGIWNICKN */
- NULL, /* -- hole -- */
- NULL, /* -- hole -- */
- r8711_wx_set_rate, /* SIOCSIWRATE */
- r8711_wx_get_rate, /* SIOCGIWRATE */
- dummy, /* SIOCSIWRTS */
- r8711_wx_get_rts, /* SIOCGIWRTS */
- r8711_wx_set_frag, /* SIOCSIWFRAG */
- r8711_wx_get_frag, /* SIOCGIWFRAG */
- dummy, /* SIOCSIWTXPOW */
- dummy, /* SIOCGIWTXPOW */
- dummy, /* SIOCSIWRETRY */
- r8711_wx_get_retry, /* SIOCGIWRETRY */
- r8711_wx_set_enc, /* SIOCSIWENCODE */
- r8711_wx_get_enc, /* SIOCGIWENCODE */
- dummy, /* SIOCSIWPOWER */
- r8711_wx_get_power, /* SIOCGIWPOWER */
- NULL, /*---hole---*/
- NULL, /*---hole---*/
- r871x_wx_set_gen_ie, /* SIOCSIWGENIE */
- NULL, /* SIOCGIWGENIE */
- r871x_wx_set_auth, /* SIOCSIWAUTH */
- NULL, /* SIOCGIWAUTH */
- r871x_wx_set_enc_ext, /* SIOCSIWENCODEEXT */
- NULL, /* SIOCGIWENCODEEXT */
- r871x_wx_set_pmkid, /* SIOCSIWPMKSA */
- NULL, /*---hole---*/
-};
-
-static const struct iw_priv_args r8711_private_args[] = {
- {
- SIOCIWFIRSTPRIV + 0x0,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "read32"
- },
- {
- SIOCIWFIRSTPRIV + 0x1,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "write32"
- },
- {
- SIOCIWFIRSTPRIV + 0x2, 0, 0, "driver_ext"
- },
- {
- SIOCIWFIRSTPRIV + 0x3, 0, 0, "mp_ioctl"
- },
- {
- SIOCIWFIRSTPRIV + 0x4,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "apinfo"
- },
- {
- SIOCIWFIRSTPRIV + 0x5,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "setpid"
- },
- {
- SIOCIWFIRSTPRIV + 0x6,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "wps_start"
- },
- {
- SIOCIWFIRSTPRIV + 0x7,
- IW_PRIV_TYPE_INT | IW_PRIV_SIZE_FIXED | 1, 0, "chplan"
- }
-};
-
-static iw_handler r8711_private_handler[] = {
- r8711_wx_read32,
- r8711_wx_write32,
- r8711_drvext_hdl,
- r871x_mp_ioctl_hdl,
- r871x_get_ap_info, /*for MM DTV platform*/
- r871x_set_pid,
- r871x_wps_start,
- r871x_set_chplan
-};
-
-static struct iw_statistics *r871x_get_wireless_stats(struct net_device *dev)
-{
- struct _adapter *padapter = netdev_priv(dev);
- struct iw_statistics *piwstats = &padapter->iwstats;
- int tmp_level = 0;
- int tmp_qual = 0;
- int tmp_noise = 0;
-
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) != true) {
- piwstats->qual.qual = 0;
- piwstats->qual.level = 0;
- piwstats->qual.noise = 0;
- } else {
- /* show percentage, we need transfer dbm to original value. */
- tmp_level = padapter->recvpriv.fw_rssi;
- tmp_qual = padapter->recvpriv.signal;
- tmp_noise = padapter->recvpriv.noise;
- piwstats->qual.level = tmp_level;
- piwstats->qual.qual = tmp_qual;
- piwstats->qual.noise = tmp_noise;
- }
- piwstats->qual.updated = IW_QUAL_ALL_UPDATED;
- return &padapter->iwstats;
-}
-
-struct iw_handler_def r871x_handlers_def = {
- .standard = r8711_handlers,
- .num_standard = ARRAY_SIZE(r8711_handlers),
- .private = r8711_private_handler,
- .private_args = (struct iw_priv_args *)r8711_private_args,
- .num_private = ARRAY_SIZE(r8711_private_handler),
- .num_private_args = sizeof(r8711_private_args) /
- sizeof(struct iw_priv_args),
- .get_wireless_stats = r871x_get_wireless_stats
-};
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c
deleted file mode 100644
index 2b539335206a..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.c
+++ /dev/null
@@ -1,519 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_ioctl_rtl.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_IOCTL_RTL_C_
-
-#include <linux/rndis.h>
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wlan_bssdef.h"
-#include "wifi.h"
-#include "rtl871x_ioctl.h"
-#include "rtl871x_ioctl_set.h"
-#include "rtl871x_ioctl_rtl.h"
-#include "mp_custom_oid.h"
-#include "rtl871x_mp.h"
-#include "rtl871x_mp_ioctl.h"
-
-uint oid_rt_get_signal_quality_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_small_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_smallpacket_crcerr;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_middle_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_middlepacket_crcerr;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_large_packet_crc_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_largepacket_crcerr;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_tx_retry_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_rx_retry_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_rx_total_packet_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_pkts +
- padapter->recvpriv.rx_drop;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_tx_beacon_ok_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_tx_beacon_err_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_rx_icv_err_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(uint *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_icv_err;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_encryption_algorithm_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_preamble_mode_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- u32 preamblemode = 0;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- if (padapter->registrypriv.preamble == PREAMBLE_LONG)
- preamblemode = 0;
- else if (padapter->registrypriv.preamble == PREAMBLE_AUTO)
- preamblemode = 1;
- else if (padapter->registrypriv.preamble == PREAMBLE_SHORT)
- preamblemode = 2;
- *(u32 *)poid_par_priv->information_buf = preamblemode;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_ap_ip_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_channelplan_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- *(u16 *)poid_par_priv->information_buf = peeprompriv->channel_plan;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_channelplan_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- struct eeprom_priv *peeprompriv = &padapter->eeprompriv;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- peeprompriv->channel_plan = *(u16 *)poid_par_priv->information_buf;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_preamble_mode_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- u32 preamblemode = 0;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- preamblemode = *(u32 *)poid_par_priv->information_buf;
- if (preamblemode == 0)
- padapter->registrypriv.preamble = PREAMBLE_LONG;
- else if (preamblemode == 1)
- padapter->registrypriv.preamble = PREAMBLE_AUTO;
- else if (preamblemode == 2)
- padapter->registrypriv.preamble = PREAMBLE_SHORT;
- *(u32 *)poid_par_priv->information_buf = preamblemode;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_bcn_intvl_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_dedicate_probe_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_total_tx_bytes_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->xmitpriv.tx_bytes;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_total_rx_bytes_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- padapter->recvpriv.rx_bytes;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_current_tx_power_level_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_enc_key_mismatch_count_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_enc_key_match_count_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_channel_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct NDIS_802_11_CONFIGURATION *pnic_Config;
- u32 channelnum;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (check_fwstate(pmlmepriv, _FW_LINKED) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE))
- pnic_Config = &pmlmepriv->cur_network.network.Configuration;
- else
- pnic_Config = &padapter->registrypriv.dev_network.Configuration;
- channelnum = pnic_Config->DSConfig;
- *(u32 *)poid_par_priv->information_buf = channelnum;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_hardware_radio_off_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_key_mismatch_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_supported_wireless_mode_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- u32 ulInfo = 0;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len >= sizeof(u32)) {
- ulInfo |= 0x0100; /* WIRELESS_MODE_B */
- ulInfo |= 0x0200; /* WIRELESS_MODE_G */
- ulInfo |= 0x0400; /* WIRELESS_MODE_A */
- *(u32 *) poid_par_priv->information_buf = ulInfo;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_channel_list_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_scan_in_progress_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_forced_data_rate_hdl(struct oid_par_priv *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_wireless_mode_for_scan_list_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_bss_wireless_mode_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_scan_with_magic_packet_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_ap_get_associated_station_list_hdl(struct oid_par_priv
- *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_ap_switch_into_ap_mode_hdl(struct oid_par_priv*
- poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_ap_supported_hdl(struct oid_par_priv *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_ap_set_passphrase_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_rf_write_registry_hdl(struct oid_par_priv*
- poid_par_priv)
-{
- uint status = RNDIS_STATUS_SUCCESS;
- struct _adapter *Adapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len ==
- (sizeof(unsigned long) * 3)) {
- if (r8712_setrfreg_cmd(Adapter,
- *(unsigned char *)poid_par_priv->information_buf,
- (unsigned long)(*((unsigned long *)
- poid_par_priv->information_buf + 2))))
- status = RNDIS_STATUS_NOT_ACCEPTED;
- } else {
- status = RNDIS_STATUS_INVALID_LENGTH;
- }
- return status;
-}
-
-uint oid_rt_pro_rf_read_registry_hdl(struct oid_par_priv *poid_par_priv)
-{
- uint status = RNDIS_STATUS_SUCCESS;
- struct _adapter *Adapter = poid_par_priv->adapter_context;
-
- if (poid_par_priv->type_of_oid != SET_OID) /* QUERY_OID */
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len == (sizeof(unsigned long) *
- 3)) {
- if (Adapter->mppriv.act_in_progress) {
- status = RNDIS_STATUS_NOT_ACCEPTED;
- } else {
- /* init workparam */
- Adapter->mppriv.act_in_progress = true;
- Adapter->mppriv.workparam.bcompleted = false;
- Adapter->mppriv.workparam.act_type = MPT_READ_RF;
- Adapter->mppriv.workparam.io_offset = *(unsigned long *)
- poid_par_priv->information_buf;
- Adapter->mppriv.workparam.io_value = 0xcccccccc;
-
- /* RegOffsetValue - The offset of RF register to read.
- * RegDataWidth - The data width of RF register to read.
- * RegDataValue - The value to read.
- * RegOffsetValue = *((unsigned long *)InformationBuffer);
- * RegDataWidth = *((unsigned long *)InformationBuffer+1);
- * RegDataValue = *((unsigned long *)InformationBuffer+2);
- */
- if (r8712_getrfreg_cmd(Adapter,
- *(unsigned char *)poid_par_priv->information_buf,
- (unsigned char *)&Adapter->mppriv.workparam.io_value
- ))
- status = RNDIS_STATUS_NOT_ACCEPTED;
- }
- } else {
- status = RNDIS_STATUS_INVALID_LENGTH;
- }
- return status;
-}
-
-enum _CONNECT_STATE_ {
- CHECKINGSTATUS,
- ASSOCIATED,
- ADHOCMODE,
- NOTASSOCIATED
-};
-
-uint oid_rt_get_connect_state_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *padapter = poid_par_priv->adapter_context;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- u32 ulInfo;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- /* nStatus==0 CheckingStatus
- * nStatus==1 Associated
- * nStatus==2 AdHocMode
- * nStatus==3 NotAssociated
- */
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- ulInfo = CHECKINGSTATUS;
- else if (check_fwstate(pmlmepriv, _FW_LINKED))
- ulInfo = ASSOCIATED;
- else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE))
- ulInfo = ADHOCMODE;
- else
- ulInfo = NOTASSOCIATED;
- *(u32 *)poid_par_priv->information_buf = ulInfo;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_default_key_id_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h b/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h
deleted file mode 100644
index 7c0b880ac686..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl_rtl.h
+++ /dev/null
@@ -1,109 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_IOCTL_RTL_H
-#define _RTL871X_IOCTL_RTL_H
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-/*************** oid_rtl_seg_01_01 **************/
-uint oid_rt_get_signal_quality_hdl(
- struct oid_par_priv *poid_par_priv);/*84*/
-uint oid_rt_get_small_packet_crc_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_middle_packet_crc_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_large_packet_crc_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_tx_retry_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_rx_retry_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_rx_total_packet_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_tx_beacon_ok_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_tx_beacon_err_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_rx_icv_err_hdl(
- struct oid_par_priv *poid_par_priv);/*93*/
-uint oid_rt_set_encryption_algorithm_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_preamble_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_ap_ip_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_channelplan_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_channelplan_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_preamble_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_bcn_intvl_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_dedicate_probe_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_total_tx_bytes_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_total_rx_bytes_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_current_tx_power_level_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_enc_key_mismatch_count_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_enc_key_match_count_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_channel_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_hardware_radio_off_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_key_mismatch_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_supported_wireless_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_channel_list_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_scan_in_progress_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_forced_data_rate_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_wireless_mode_for_scan_list_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_bss_wireless_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_scan_with_magic_packet_hdl(
- struct oid_par_priv *poid_par_priv);
-
-/************** oid_rtl_seg_01_03 section start **************/
-uint oid_rt_ap_get_associated_station_list_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_ap_switch_into_ap_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_ap_supported_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_ap_set_passphrase_hdl(
- struct oid_par_priv *poid_par_priv);
-/* oid_rtl_seg_01_11 */
-uint oid_rt_pro_rf_write_registry_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_rf_read_registry_hdl(
- struct oid_par_priv *poid_par_priv);
-/*************** oid_rtl_seg_03_00 section start **************/
-uint oid_rt_get_connect_state_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_default_key_id_hdl(
- struct oid_par_priv *poid_par_priv);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.c b/drivers/staging/rtl8712/rtl871x_ioctl_set.c
deleted file mode 100644
index 34c9a52b4c42..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl_set.c
+++ /dev/null
@@ -1,354 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_ioctl_set.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_IOCTL_SET_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "rtl871x_ioctl_set.h"
-#include "usb_osintf.h"
-#include "usb_ops.h"
-
-static u8 validate_ssid(struct ndis_802_11_ssid *ssid)
-{
- u8 i;
-
- if (ssid->SsidLength > 32)
- return false;
- for (i = 0; i < ssid->SsidLength; i++) {
- /* wifi, printable ascii code must be supported */
- if (!((ssid->Ssid[i] >= 0x20) && (ssid->Ssid[i] <= 0x7e)))
- return false;
- }
- return true;
-}
-
-static u8 do_join(struct _adapter *padapter)
-{
- struct list_head *plist, *phead;
- u8 *pibss = NULL;
- struct mlme_priv *pmlmepriv = &(padapter->mlmepriv);
- struct __queue *queue = &(pmlmepriv->scanned_queue);
- int ret;
-
- phead = &queue->queue;
- plist = phead->next;
- pmlmepriv->cur_network.join_res = -2;
- pmlmepriv->fw_state |= _FW_UNDER_LINKING;
- pmlmepriv->pscanned = plist;
- pmlmepriv->to_join = true;
-
- /* adhoc mode will start with an empty queue, but skip checking */
- if (!check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) &&
- list_empty(&queue->queue)) {
- if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
- pmlmepriv->fw_state ^= _FW_UNDER_LINKING;
- /* when set_ssid/set_bssid for do_join(), but scanning queue
- * is empty we try to issue sitesurvey firstly
- */
- if (!pmlmepriv->sitesurveyctrl.traffic_busy)
- r8712_sitesurvey_cmd(padapter, &pmlmepriv->assoc_ssid);
- return true;
- }
-
- ret = r8712_select_and_join_from_scan(pmlmepriv);
- if (!ret) {
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(MAX_JOIN_TIMEOUT));
- } else {
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- /* submit r8712_createbss_cmd to change to an
- * ADHOC_MASTER pmlmepriv->lock has been
- * acquired by caller...
- */
- struct wlan_bssid_ex *pdev_network =
- &padapter->registrypriv.dev_network;
- pmlmepriv->fw_state = WIFI_ADHOC_MASTER_STATE;
- pibss = padapter->registrypriv.dev_network.MacAddress;
- memcpy(&pdev_network->Ssid,
- &pmlmepriv->assoc_ssid,
- sizeof(struct ndis_802_11_ssid));
- r8712_update_registrypriv_dev_network(padapter);
- r8712_generate_random_ibss(pibss);
- if (r8712_createbss_cmd(padapter))
- return false;
- pmlmepriv->to_join = false;
- } else {
- /* can't associate ; reset under-linking */
- if (pmlmepriv->fw_state & _FW_UNDER_LINKING)
- pmlmepriv->fw_state ^=
- _FW_UNDER_LINKING;
- /* when set_ssid/set_bssid for do_join(), but
- * there are no desired bss in scanning queue
- * we try to issue sitesurvey first
- */
- if (!pmlmepriv->sitesurveyctrl.traffic_busy)
- r8712_sitesurvey_cmd(padapter,
- &pmlmepriv->assoc_ssid);
- }
- }
- return true;
-}
-
-u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid)
-{
- unsigned long irqL;
- u8 status = true;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (is_zero_ether_addr(bssid) || is_broadcast_ether_addr(bssid)) {
- status = false;
- return status;
- }
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY |
- _FW_UNDER_LINKING)) {
- status = check_fwstate(pmlmepriv, _FW_UNDER_LINKING);
- goto _Abort_Set_BSSID;
- }
- if (check_fwstate(pmlmepriv,
- _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
- if (!memcmp(&pmlmepriv->cur_network.network.MacAddress, bssid,
- ETH_ALEN)) {
- if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- /* driver is in
- * WIFI_ADHOC_MASTER_STATE
- */
- goto _Abort_Set_BSSID;
- } else {
- r8712_disassoc_cmd(padapter);
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- r8712_ind_disconnect(padapter);
- r8712_free_assoc_resources(padapter);
- if ((check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE))) {
- _clr_fwstate_(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE);
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- }
- }
- }
- memcpy(&pmlmepriv->assoc_bssid, bssid, ETH_ALEN);
- pmlmepriv->assoc_by_bssid = true;
- status = do_join(padapter);
- goto done;
-_Abort_Set_BSSID:
-done:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- return status;
-}
-
-void r8712_set_802_11_ssid(struct _adapter *padapter,
- struct ndis_802_11_ssid *ssid)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *pnetwork = &pmlmepriv->cur_network;
-
- if (!padapter->hw_init_completed)
- return;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING)) {
- check_fwstate(pmlmepriv, _FW_UNDER_LINKING);
- goto _Abort_Set_SSID;
- }
- if (check_fwstate(pmlmepriv, _FW_LINKED | WIFI_ADHOC_MASTER_STATE)) {
- if ((pmlmepriv->assoc_ssid.SsidLength == ssid->SsidLength) &&
- (!memcmp(&pmlmepriv->assoc_ssid.Ssid, ssid->Ssid,
- ssid->SsidLength))) {
- if (!check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- if (!r8712_is_same_ibss(padapter,
- pnetwork)) {
- /* if in WIFI_ADHOC_MASTER_STATE or
- * WIFI_ADHOC_STATE, create bss or
- * rejoin again
- */
- r8712_disassoc_cmd(padapter);
- if (check_fwstate(pmlmepriv,
- _FW_LINKED))
- r8712_ind_disconnect(padapter);
- r8712_free_assoc_resources(padapter);
- if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE)) {
- _clr_fwstate_(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE);
- set_fwstate(pmlmepriv,
- WIFI_ADHOC_STATE);
- }
- } else {
- /* driver is in
- * WIFI_ADHOC_MASTER_STATE
- */
- goto _Abort_Set_SSID;
- }
- }
- } else {
- r8712_disassoc_cmd(padapter);
- if (check_fwstate(pmlmepriv, _FW_LINKED))
- r8712_ind_disconnect(padapter);
- r8712_free_assoc_resources(padapter);
- if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE)) {
- _clr_fwstate_(pmlmepriv,
- WIFI_ADHOC_MASTER_STATE);
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- }
- }
- }
- if (padapter->securitypriv.btkip_countermeasure)
- goto _Abort_Set_SSID;
- if (!validate_ssid(ssid))
- goto _Abort_Set_SSID;
- memcpy(&pmlmepriv->assoc_ssid, ssid, sizeof(struct ndis_802_11_ssid));
- pmlmepriv->assoc_by_bssid = false;
- do_join(padapter);
- goto done;
-_Abort_Set_SSID:
-done:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *cur_network = &pmlmepriv->cur_network;
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE *pold_state =
- &(cur_network->network.InfrastructureMode);
-
- if (*pold_state != networktype) {
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_LINKED) ||
- (*pold_state == Ndis802_11IBSS))
- r8712_disassoc_cmd(padapter);
- if (check_fwstate(pmlmepriv,
- _FW_LINKED | WIFI_ADHOC_MASTER_STATE))
- r8712_free_assoc_resources(padapter);
- if (check_fwstate(pmlmepriv, _FW_LINKED) ||
- (*pold_state == Ndis802_11Infrastructure) ||
- (*pold_state == Ndis802_11IBSS)) {
- /* will clr Linked_state before this function,
- * we must have checked whether issue dis-assoc_cmd or
- * not
- */
- r8712_ind_disconnect(padapter);
- }
- *pold_state = networktype;
- /* clear WIFI_STATION_STATE; WIFI_AP_STATE; WIFI_ADHOC_STATE;
- * WIFI_ADHOC_MASTER_STATE
- */
- _clr_fwstate_(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE |
- WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE);
- switch (networktype) {
- case Ndis802_11IBSS:
- set_fwstate(pmlmepriv, WIFI_ADHOC_STATE);
- break;
- case Ndis802_11Infrastructure:
- set_fwstate(pmlmepriv, WIFI_STATION_STATE);
- break;
- case Ndis802_11APMode:
- set_fwstate(pmlmepriv, WIFI_AP_STATE);
- break;
- case Ndis802_11AutoUnknown:
- case Ndis802_11InfrastructureMax:
- break;
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- }
-}
-
-u8 r8712_set_802_11_disassociate(struct _adapter *padapter)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- r8712_disassoc_cmd(padapter);
- r8712_ind_disconnect(padapter);
- r8712_free_assoc_resources(padapter);
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- return true;
-}
-
-u8 r8712_set_802_11_bssid_list_scan(struct _adapter *padapter)
-{
- struct mlme_priv *pmlmepriv = NULL;
- unsigned long irqL;
- u8 ret = true;
-
- if (!padapter)
- return false;
- pmlmepriv = &padapter->mlmepriv;
- if (!padapter->hw_init_completed)
- return false;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY | _FW_UNDER_LINKING) ||
- pmlmepriv->sitesurveyctrl.traffic_busy) {
- /* Scan or linking is in progress, do nothing. */
- ret = (u8)check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
- } else {
- r8712_free_network_queue(padapter);
- ret = r8712_sitesurvey_cmd(padapter, NULL);
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- return ret;
-}
-
-u8 r8712_set_802_11_authentication_mode(struct _adapter *padapter,
- enum NDIS_802_11_AUTHENTICATION_MODE authmode)
-{
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- u8 ret;
-
- psecuritypriv->ndisauthtype = authmode;
- if (psecuritypriv->ndisauthtype > 3)
- psecuritypriv->AuthAlgrthm = 2; /* 802.1x */
- if (r8712_set_auth(padapter, psecuritypriv))
- ret = false;
- else
- ret = true;
- return ret;
-}
-
-int r8712_set_802_11_add_wep(struct _adapter *padapter,
- struct NDIS_802_11_WEP *wep)
-{
- sint keyid;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- keyid = wep->KeyIndex & 0x3fffffff;
- if (keyid >= WEP_KEYS)
- return -EINVAL;
- switch (wep->KeyLength) {
- case 5:
- psecuritypriv->PrivacyAlgrthm = _WEP40_;
- break;
- case 13:
- psecuritypriv->PrivacyAlgrthm = _WEP104_;
- break;
- default:
- psecuritypriv->PrivacyAlgrthm = _NO_PRIVACY_;
- break;
- }
- memcpy(psecuritypriv->DefKey[keyid].skey, &wep->KeyMaterial,
- wep->KeyLength);
- psecuritypriv->DefKeylen[keyid] = wep->KeyLength;
- psecuritypriv->PrivacyKeyIndex = keyid;
- return r8712_set_key(padapter, psecuritypriv, keyid);
-}
diff --git a/drivers/staging/rtl8712/rtl871x_ioctl_set.h b/drivers/staging/rtl8712/rtl871x_ioctl_set.h
deleted file mode 100644
index e2de820f61d9..000000000000
--- a/drivers/staging/rtl8712/rtl871x_ioctl_set.h
+++ /dev/null
@@ -1,45 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __IOCTL_SET_H
-#define __IOCTL_SET_H
-
-#include "drv_types.h"
-
-typedef u8 NDIS_802_11_PMKID_VALUE[16];
-
-struct BSSIDInfo {
- unsigned char BSSID[6];
- NDIS_802_11_PMKID_VALUE PMKID;
-};
-
-u8 r8712_set_802_11_authentication_mode(struct _adapter *pdapter,
- enum NDIS_802_11_AUTHENTICATION_MODE authmode);
-
-u8 r8712_set_802_11_bssid(struct _adapter *padapter, u8 *bssid);
-
-int r8712_set_802_11_add_wep(struct _adapter *padapter,
- struct NDIS_802_11_WEP *wep);
-
-u8 r8712_set_802_11_disassociate(struct _adapter *padapter);
-
-u8 r8712_set_802_11_bssid_list_scan(struct _adapter *padapter);
-
-void r8712_set_802_11_infrastructure_mode(struct _adapter *padapter,
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE networktype);
-
-void r8712_set_802_11_ssid(struct _adapter *padapter,
- struct ndis_802_11_ssid *ssid);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_led.h b/drivers/staging/rtl8712/rtl871x_led.h
deleted file mode 100644
index 2f0768132ad8..000000000000
--- a/drivers/staging/rtl8712/rtl871x_led.h
+++ /dev/null
@@ -1,118 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL8712_LED_H
-#define __RTL8712_LED_H
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-/*===========================================================================
- * LED customization.
- *===========================================================================
- */
-enum LED_CTL_MODE {
- LED_CTL_POWER_ON = 1,
- LED_CTL_LINK = 2,
- LED_CTL_NO_LINK = 3,
- LED_CTL_TX = 4,
- LED_CTL_RX = 5,
- LED_CTL_SITE_SURVEY = 6,
- LED_CTL_POWER_OFF = 7,
- LED_CTL_START_TO_LINK = 8,
- LED_CTL_START_WPS = 9,
- LED_CTL_STOP_WPS = 10,
- LED_CTL_START_WPS_BOTTON = 11,
- LED_CTL_STOP_WPS_FAIL = 12,
- LED_CTL_STOP_WPS_FAIL_OVERLAP = 13,
-};
-
-#define IS_LED_WPS_BLINKING(_LED_871x) \
- (((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS \
- || ((struct LED_871x *)_LED_871x)->CurrLedState == LED_BLINK_WPS_STOP \
- || ((struct LED_871x *)_LED_871x)->bLedWPSBlinkInProgress)
-
-#define IS_LED_BLINKING(_LED_871x) \
- (((struct LED_871x *)_LED_871x)->bLedWPSBlinkInProgress \
- || ((struct LED_871x *)_LED_871x)->bLedScanBlinkInProgress)
-
-enum LED_PIN_871x {
- LED_PIN_GPIO0,
- LED_PIN_LED0,
- LED_PIN_LED1
-};
-
-/*===========================================================================
- * LED customization.
- *===========================================================================
- */
-enum LED_STRATEGY_871x {
- SW_LED_MODE0, /* SW control 1 LED via GPIO0. It is default option. */
- SW_LED_MODE1, /* 2 LEDs, through LED0 and LED1. For ALPHA. */
- SW_LED_MODE2, /* SW control 1 LED via GPIO0,
- * custom for AzWave 8187 minicard.
- */
- SW_LED_MODE3, /* SW control 1 LED via GPIO0,
- * customized for Sercomm Printer Server case.
- */
- SW_LED_MODE4, /*for Edimax / Belkin*/
- SW_LED_MODE5, /*for Sercomm / Belkin*/
- SW_LED_MODE6, /*for WNC / Corega*/
- HW_LED, /* HW control 2 LEDs, LED0 and LED1 (there are 4 different
- * control modes, see MAC.CONFIG1 for details.)
- */
-};
-
-struct LED_871x {
- struct _adapter *padapter;
- enum LED_PIN_871x LedPin; /* Implementation for this SW led. */
- u32 CurrLedState; /* Current LED state. */
- u8 bLedOn; /* true if LED is ON */
- u8 bSWLedCtrl;
- u8 bLedBlinkInProgress; /*true if blinking */
- u8 bLedNoLinkBlinkInProgress;
- u8 bLedLinkBlinkInProgress;
- u8 bLedStartToLinkBlinkInProgress;
- u8 bLedScanBlinkInProgress;
- u8 bLedWPSBlinkInProgress;
- u32 BlinkTimes; /* No. times to toggle for blink.*/
- u32 BlinkingLedState; /* Next state for blinking,
- * either LED_ON or OFF.
- */
-
- struct timer_list BlinkTimer; /* Timer object for led blinking.*/
- struct work_struct BlinkWorkItem; /* Workitem used by BlinkTimer */
-};
-
-struct led_priv {
- /* add for led control */
- struct LED_871x SwLed0;
- struct LED_871x SwLed1;
- enum LED_STRATEGY_871x LedStrategy;
- u8 bRegUseLed;
- void (*LedControlHandler)(struct _adapter *padapter,
- enum LED_CTL_MODE LedAction);
- /* add for led control */
-};
-
-/*===========================================================================
- * Interface to manipulate LED objects.
- *===========================================================================
- */
-void r8712_InitSwLeds(struct _adapter *padapter);
-void r8712_DeInitSwLeds(struct _adapter *padapter);
-void LedControl871x(struct _adapter *padapter, enum LED_CTL_MODE LedAction);
-void r8712_flush_led_works(struct _adapter *padapter);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.c b/drivers/staging/rtl8712/rtl871x_mlme.c
deleted file mode 100644
index 70c295e97068..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mlme.c
+++ /dev/null
@@ -1,1710 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_mlme.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_MLME_C_
-
-#include <linux/etherdevice.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "xmit_osdep.h"
-#include "mlme_osdep.h"
-#include "sta_info.h"
-#include "wifi.h"
-#include "wlan_bssdef.h"
-
-static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len);
-
-int r8712_init_mlme_priv(struct _adapter *padapter)
-{
- sint i;
- u8 *pbuf;
- struct wlan_network *pnetwork;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- memset((u8 *)pmlmepriv, 0, sizeof(struct mlme_priv));
- pmlmepriv->nic_hdl = (u8 *)padapter;
- pmlmepriv->pscanned = NULL;
- pmlmepriv->fw_state = 0;
- pmlmepriv->cur_network.network.InfrastructureMode =
- Ndis802_11AutoUnknown;
- /* Maybe someday we should rename this variable to "active_mode"(Jeff)*/
- pmlmepriv->passive_mode = 1; /* 1: active, 0: passive. */
- spin_lock_init(&(pmlmepriv->lock));
- spin_lock_init(&(pmlmepriv->lock2));
- _init_queue(&(pmlmepriv->free_bss_pool));
- _init_queue(&(pmlmepriv->scanned_queue));
- set_scanned_network_val(pmlmepriv, 0);
- memset(&pmlmepriv->assoc_ssid, 0, sizeof(struct ndis_802_11_ssid));
- pbuf = kmalloc_array(MAX_BSS_CNT, sizeof(struct wlan_network),
- GFP_ATOMIC);
- if (!pbuf)
- return -ENOMEM;
- pmlmepriv->free_bss_buf = pbuf;
- pnetwork = (struct wlan_network *)pbuf;
- for (i = 0; i < MAX_BSS_CNT; i++) {
- INIT_LIST_HEAD(&(pnetwork->list));
- list_add_tail(&(pnetwork->list),
- &(pmlmepriv->free_bss_pool.queue));
- pnetwork++;
- }
- pmlmepriv->sitesurveyctrl.last_rx_pkts = 0;
- pmlmepriv->sitesurveyctrl.last_tx_pkts = 0;
- pmlmepriv->sitesurveyctrl.traffic_busy = false;
- /* allocate DMA-able/Non-Page memory for cmd_buf and rsp_buf */
- r8712_init_mlme_timer(padapter);
- return 0;
-}
-
-struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv)
-{
- unsigned long irqL;
- struct wlan_network *pnetwork;
- struct __queue *free_queue = &pmlmepriv->free_bss_pool;
-
- spin_lock_irqsave(&free_queue->lock, irqL);
- pnetwork = list_first_entry_or_null(&free_queue->queue,
- struct wlan_network, list);
- if (pnetwork) {
- list_del_init(&pnetwork->list);
- pnetwork->last_scanned = jiffies;
- pmlmepriv->num_of_scanned++;
- }
- spin_unlock_irqrestore(&free_queue->lock, irqL);
- return pnetwork;
-}
-
-static void _free_network(struct mlme_priv *pmlmepriv,
- struct wlan_network *pnetwork)
-{
- u32 curr_time, delta_time;
- unsigned long irqL;
- struct __queue *free_queue = &(pmlmepriv->free_bss_pool);
-
- if (!pnetwork)
- return;
- if (pnetwork->fixed)
- return;
- curr_time = jiffies;
- delta_time = (curr_time - (u32)pnetwork->last_scanned) / HZ;
- if (delta_time < SCANQUEUE_LIFETIME)
- return;
- spin_lock_irqsave(&free_queue->lock, irqL);
- list_del_init(&pnetwork->list);
- list_add_tail(&pnetwork->list, &free_queue->queue);
- pmlmepriv->num_of_scanned--;
- spin_unlock_irqrestore(&free_queue->lock, irqL);
-}
-
-static void free_network_nolock(struct mlme_priv *pmlmepriv,
- struct wlan_network *pnetwork)
-{
- struct __queue *free_queue = &pmlmepriv->free_bss_pool;
-
- if (!pnetwork)
- return;
- if (pnetwork->fixed)
- return;
- list_del_init(&pnetwork->list);
- list_add_tail(&pnetwork->list, &free_queue->queue);
- pmlmepriv->num_of_scanned--;
-}
-
-/* return the wlan_network with the matching addr
- * Shall be called under atomic context...
- * to avoid possible racing condition...
- */
-static struct wlan_network *r8712_find_network(struct __queue *scanned_queue,
- u8 *addr)
-{
- unsigned long irqL;
- struct list_head *phead, *plist;
- struct wlan_network *pnetwork = NULL;
-
- if (is_zero_ether_addr(addr))
- return NULL;
- spin_lock_irqsave(&scanned_queue->lock, irqL);
- phead = &scanned_queue->queue;
- list_for_each(plist, phead) {
- pnetwork = list_entry(plist, struct wlan_network, list);
- if (!memcmp(addr, pnetwork->network.MacAddress, ETH_ALEN))
- break;
- }
- if (plist == phead)
- pnetwork = NULL;
- spin_unlock_irqrestore(&scanned_queue->lock, irqL);
- return pnetwork;
-}
-
-void r8712_free_network_queue(struct _adapter *padapter)
-{
- unsigned long irqL;
- struct list_head *phead, *plist;
- struct wlan_network *pnetwork;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct __queue *scanned_queue = &pmlmepriv->scanned_queue;
-
- spin_lock_irqsave(&scanned_queue->lock, irqL);
- phead = &scanned_queue->queue;
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- pnetwork = container_of(plist, struct wlan_network, list);
- plist = plist->next;
- _free_network(pmlmepriv, pnetwork);
- }
- spin_unlock_irqrestore(&scanned_queue->lock, irqL);
-}
-
-sint r8712_if_up(struct _adapter *padapter)
-{
- sint res;
-
- if (padapter->driver_stopped || padapter->surprise_removed ||
- !check_fwstate(&padapter->mlmepriv, _FW_LINKED)) {
- res = false;
- } else {
- res = true;
- }
- return res;
-}
-
-void r8712_generate_random_ibss(u8 *pibss)
-{
- u32 curtime = jiffies;
-
- pibss[0] = 0x02; /*in ad-hoc mode bit1 must set to 1 */
- pibss[1] = 0x11;
- pibss[2] = 0x87;
- pibss[3] = (u8)(curtime & 0xff);
- pibss[4] = (u8)((curtime >> 8) & 0xff);
- pibss[5] = (u8)((curtime >> 16) & 0xff);
-}
-
-uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss)
-{
- return sizeof(*bss) + bss->IELength - MAX_IE_SZ;
-}
-
-u8 *r8712_get_capability_from_ie(u8 *ie)
-{
- return ie + 8 + 2;
-}
-
-void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv)
-{
- kfree(pmlmepriv->free_bss_buf);
-}
-
-static struct wlan_network *alloc_network(struct mlme_priv *pmlmepriv)
-{
- return _r8712_alloc_network(pmlmepriv);
-}
-
-int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork)
-{
- int ret = true;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
-
- if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
- (pnetwork->network.Privacy == cpu_to_le32(0)))
- ret = false;
- else if ((psecuritypriv->PrivacyAlgrthm == _NO_PRIVACY_) &&
- (pnetwork->network.Privacy == cpu_to_le32(1)))
- ret = false;
- else
- ret = true;
- return ret;
-
-}
-
-static int is_same_network(struct wlan_bssid_ex *src,
- struct wlan_bssid_ex *dst)
-{
- u16 s_cap, d_cap;
-
- memcpy((u8 *)&s_cap, r8712_get_capability_from_ie(src->IEs), 2);
- memcpy((u8 *)&d_cap, r8712_get_capability_from_ie(dst->IEs), 2);
- return (src->Ssid.SsidLength == dst->Ssid.SsidLength) &&
- (src->Configuration.DSConfig ==
- dst->Configuration.DSConfig) &&
- ((!memcmp(src->MacAddress, dst->MacAddress,
- ETH_ALEN))) &&
- ((!memcmp(src->Ssid.Ssid,
- dst->Ssid.Ssid,
- src->Ssid.SsidLength))) &&
- ((s_cap & WLAN_CAPABILITY_IBSS) ==
- (d_cap & WLAN_CAPABILITY_IBSS)) &&
- ((s_cap & WLAN_CAPABILITY_ESS) ==
- (d_cap & WLAN_CAPABILITY_ESS));
-
-}
-
-struct wlan_network *r8712_get_oldest_wlan_network(
- struct __queue *scanned_queue)
-{
- struct list_head *plist, *phead;
- struct wlan_network *pwlan = NULL;
- struct wlan_network *oldest = NULL;
-
- phead = &scanned_queue->queue;
- plist = phead->next;
- while (1) {
- if (end_of_queue_search(phead, plist))
- break;
- pwlan = container_of(plist, struct wlan_network, list);
- if (!pwlan->fixed) {
- if (!oldest ||
- time_after((unsigned long)oldest->last_scanned,
- (unsigned long)pwlan->last_scanned))
- oldest = pwlan;
- }
- plist = plist->next;
- }
- return oldest;
-}
-
-static void update_network(struct wlan_bssid_ex *dst,
- struct wlan_bssid_ex *src,
- struct _adapter *padapter)
-{
- u32 last_evm = 0, tmpVal;
- struct smooth_rssi_data *sqd = &padapter->recvpriv.signal_qual_data;
-
- if (check_fwstate(&padapter->mlmepriv, _FW_LINKED) &&
- is_same_network(&(padapter->mlmepriv.cur_network.network), src)) {
- if (padapter->recvpriv.signal_qual_data.total_num++ >=
- PHY_LINKQUALITY_SLID_WIN_MAX) {
- padapter->recvpriv.signal_qual_data.total_num =
- PHY_LINKQUALITY_SLID_WIN_MAX;
- last_evm = sqd->elements[sqd->index];
- padapter->recvpriv.signal_qual_data.total_val -=
- last_evm;
- }
- padapter->recvpriv.signal_qual_data.total_val += src->Rssi;
-
- sqd->elements[sqd->index++] = src->Rssi;
- if (padapter->recvpriv.signal_qual_data.index >=
- PHY_LINKQUALITY_SLID_WIN_MAX)
- padapter->recvpriv.signal_qual_data.index = 0;
- /* <1> Showed on UI for user, in percentage. */
- tmpVal = padapter->recvpriv.signal_qual_data.total_val /
- padapter->recvpriv.signal_qual_data.total_num;
- padapter->recvpriv.signal = (u8)tmpVal;
-
- src->Rssi = padapter->recvpriv.signal;
- } else {
- src->Rssi = (src->Rssi + dst->Rssi) / 2;
- }
- memcpy((u8 *)dst, (u8 *)src, r8712_get_wlan_bssid_ex_sz(src));
-}
-
-static void update_current_network(struct _adapter *adapter,
- struct wlan_bssid_ex *pnetwork)
-{
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- if (is_same_network(&(pmlmepriv->cur_network.network), pnetwork)) {
- update_network(&(pmlmepriv->cur_network.network),
- pnetwork, adapter);
- r8712_update_protection(adapter,
- (pmlmepriv->cur_network.network.IEs) +
- sizeof(struct NDIS_802_11_FIXED_IEs),
- pmlmepriv->cur_network.network.IELength);
- }
-}
-
-/* Caller must hold pmlmepriv->lock first */
-static void update_scanned_network(struct _adapter *adapter,
- struct wlan_bssid_ex *target)
-{
- struct list_head *plist, *phead;
-
- u32 bssid_ex_sz;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct __queue *queue = &pmlmepriv->scanned_queue;
- struct wlan_network *pnetwork = NULL;
- struct wlan_network *oldest = NULL;
-
- phead = &queue->queue;
- plist = phead->next;
-
- while (1) {
- if (end_of_queue_search(phead, plist))
- break;
-
- pnetwork = container_of(plist, struct wlan_network, list);
- if (is_same_network(&pnetwork->network, target))
- break;
- if ((oldest == ((struct wlan_network *)0)) ||
- time_after((unsigned long)oldest->last_scanned,
- (unsigned long)pnetwork->last_scanned))
- oldest = pnetwork;
-
- plist = plist->next;
- }
-
- /* If we didn't find a match, then get a new network slot to initialize
- * with this beacon's information
- */
- if (end_of_queue_search(phead, plist)) {
- if (list_empty(&pmlmepriv->free_bss_pool.queue)) {
- /* If there are no more slots, expire the oldest */
- pnetwork = oldest;
- target->Rssi = (pnetwork->network.Rssi +
- target->Rssi) / 2;
- memcpy(&pnetwork->network, target,
- r8712_get_wlan_bssid_ex_sz(target));
- pnetwork->last_scanned = jiffies;
- } else {
- /* Otherwise just pull from the free list */
- /* update scan_time */
- pnetwork = alloc_network(pmlmepriv);
- if (!pnetwork)
- return;
- bssid_ex_sz = r8712_get_wlan_bssid_ex_sz(target);
- target->Length = bssid_ex_sz;
- memcpy(&pnetwork->network, target, bssid_ex_sz);
- list_add_tail(&pnetwork->list, &queue->queue);
- }
- } else {
- /* we have an entry and we are going to update it. But
- * this entry may be already expired. In this case we
- * do the same as we found a new net and call the new_net
- * handler
- */
- update_network(&pnetwork->network, target, adapter);
- pnetwork->last_scanned = jiffies;
- }
-}
-
-static void rtl8711_add_network(struct _adapter *adapter,
- struct wlan_bssid_ex *pnetwork)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &(((struct _adapter *)adapter)->mlmepriv);
- struct __queue *queue = &pmlmepriv->scanned_queue;
-
- spin_lock_irqsave(&queue->lock, irqL);
- update_current_network(adapter, pnetwork);
- update_scanned_network(adapter, pnetwork);
- spin_unlock_irqrestore(&queue->lock, irqL);
-}
-
-/*select the desired network based on the capability of the (i)bss.
- * check items: (1) security
- * (2) network_type
- * (3) WMM
- * (4) HT
- * (5) others
- */
-static int is_desired_network(struct _adapter *adapter,
- struct wlan_network *pnetwork)
-{
- u8 wps_ie[512];
- uint wps_ielen;
- int bselected = true;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
-
- if (psecuritypriv->wps_phase) {
- if (r8712_get_wps_ie(pnetwork->network.IEs,
- pnetwork->network.IELength, wps_ie,
- &wps_ielen))
- return true;
- return false;
- }
- if ((psecuritypriv->PrivacyAlgrthm != _NO_PRIVACY_) &&
- (pnetwork->network.Privacy == 0))
- bselected = false;
- if (check_fwstate(&adapter->mlmepriv, WIFI_ADHOC_STATE)) {
- if (pnetwork->network.InfrastructureMode !=
- adapter->mlmepriv.cur_network.network.InfrastructureMode)
- bselected = false;
- }
- return bselected;
-}
-
-/* TODO: Perry : For Power Management */
-void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
-}
-
-void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- unsigned long flags;
- u32 len;
- struct wlan_bssid_ex *pnetwork;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- pnetwork = (struct wlan_bssid_ex *)pbuf;
-#ifdef __BIG_ENDIAN
- /* endian_convert */
- pnetwork->Length = le32_to_cpu(pnetwork->Length);
- pnetwork->Ssid.SsidLength = le32_to_cpu(pnetwork->Ssid.SsidLength);
- pnetwork->Privacy = le32_to_cpu(pnetwork->Privacy);
- pnetwork->Rssi = le32_to_cpu(pnetwork->Rssi);
- pnetwork->NetworkTypeInUse = le32_to_cpu(pnetwork->NetworkTypeInUse);
- pnetwork->Configuration.ATIMWindow =
- le32_to_cpu(pnetwork->Configuration.ATIMWindow);
- pnetwork->Configuration.BeaconPeriod =
- le32_to_cpu(pnetwork->Configuration.BeaconPeriod);
- pnetwork->Configuration.DSConfig =
- le32_to_cpu(pnetwork->Configuration.DSConfig);
- pnetwork->Configuration.FHConfig.DwellTime =
- le32_to_cpu(pnetwork->Configuration.FHConfig.DwellTime);
- pnetwork->Configuration.FHConfig.HopPattern =
- le32_to_cpu(pnetwork->Configuration.FHConfig.HopPattern);
- pnetwork->Configuration.FHConfig.HopSet =
- le32_to_cpu(pnetwork->Configuration.FHConfig.HopSet);
- pnetwork->Configuration.FHConfig.Length =
- le32_to_cpu(pnetwork->Configuration.FHConfig.Length);
- pnetwork->Configuration.Length =
- le32_to_cpu(pnetwork->Configuration.Length);
- pnetwork->InfrastructureMode =
- le32_to_cpu(pnetwork->InfrastructureMode);
- pnetwork->IELength = le32_to_cpu(pnetwork->IELength);
-#endif
- len = r8712_get_wlan_bssid_ex_sz(pnetwork);
- if (len > sizeof(struct wlan_bssid_ex))
- return;
- spin_lock_irqsave(&pmlmepriv->lock2, flags);
- /* update IBSS_network 's timestamp */
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- if (!memcmp(&(pmlmepriv->cur_network.network.MacAddress),
- pnetwork->MacAddress, ETH_ALEN)) {
- struct wlan_network *ibss_wlan = NULL;
-
- memcpy(pmlmepriv->cur_network.network.IEs,
- pnetwork->IEs, 8);
- ibss_wlan = r8712_find_network(
- &pmlmepriv->scanned_queue,
- pnetwork->MacAddress);
- if (ibss_wlan) {
- memcpy(ibss_wlan->network.IEs,
- pnetwork->IEs, 8);
- goto exit;
- }
- }
- }
- /* lock pmlmepriv->lock when you accessing network_q */
- if (!check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
- if (pnetwork->Ssid.Ssid[0] != 0) {
- rtl8711_add_network(adapter, pnetwork);
- } else {
- pnetwork->Ssid.SsidLength = 8;
- memcpy(pnetwork->Ssid.Ssid, "<hidden>", 8);
- rtl8711_add_network(adapter, pnetwork);
- }
- }
-exit:
- spin_unlock_irqrestore(&pmlmepriv->lock2, flags);
-}
-
-void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
-
- if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY)) {
- del_timer(&pmlmepriv->scan_to_timer);
-
- _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
- }
-
- if (pmlmepriv->to_join) {
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- if (!check_fwstate(pmlmepriv, _FW_LINKED)) {
- set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
-
- if (!r8712_select_and_join_from_scan(pmlmepriv)) {
- mod_timer(&pmlmepriv->assoc_timer, jiffies +
- msecs_to_jiffies(MAX_JOIN_TIMEOUT));
- } else {
- struct wlan_bssid_ex *pdev_network =
- &(adapter->registrypriv.dev_network);
- u8 *pibss =
- adapter->registrypriv.dev_network.MacAddress;
- pmlmepriv->fw_state ^= _FW_UNDER_SURVEY;
- memcpy(&pdev_network->Ssid,
- &pmlmepriv->assoc_ssid,
- sizeof(struct
- ndis_802_11_ssid));
- r8712_update_registrypriv_dev_network
- (adapter);
- r8712_generate_random_ibss(pibss);
- pmlmepriv->fw_state =
- WIFI_ADHOC_MASTER_STATE;
- pmlmepriv->to_join = false;
- }
- }
- } else {
- pmlmepriv->to_join = false;
- set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
- if (!r8712_select_and_join_from_scan(pmlmepriv))
- mod_timer(&pmlmepriv->assoc_timer, jiffies +
- msecs_to_jiffies(MAX_JOIN_TIMEOUT));
- else
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
- }
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-/*
- *r8712_free_assoc_resources: the caller has to lock pmlmepriv->lock
- */
-void r8712_free_assoc_resources(struct _adapter *adapter)
-{
- unsigned long irqL;
- struct wlan_network *pwlan = NULL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct wlan_network *tgt_network = &pmlmepriv->cur_network;
-
- pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
- tgt_network->network.MacAddress);
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_AP_STATE)) {
- struct sta_info *psta;
-
- psta = r8712_get_stainfo(&adapter->stapriv,
- tgt_network->network.MacAddress);
-
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
- r8712_free_stainfo(adapter, psta);
- spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
- }
-
- if (check_fwstate(pmlmepriv,
- WIFI_ADHOC_STATE | WIFI_ADHOC_MASTER_STATE | WIFI_AP_STATE))
- r8712_free_all_stainfo(adapter);
- if (pwlan)
- pwlan->fixed = false;
-
- if (((check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) &&
- (adapter->stapriv.asoc_sta_count == 1)))
- free_network_nolock(pmlmepriv, pwlan);
-}
-
-/*
- * r8712_indicate_connect: the caller has to lock pmlmepriv->lock
- */
-void r8712_indicate_connect(struct _adapter *padapter)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- pmlmepriv->to_join = false;
- set_fwstate(pmlmepriv, _FW_LINKED);
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_LINK);
- r8712_os_indicate_connect(padapter);
- if (padapter->registrypriv.power_mgnt > PS_MODE_ACTIVE)
- mod_timer(&pmlmepriv->dhcp_timer,
- jiffies + msecs_to_jiffies(60000));
-}
-
-/*
- * r8712_ind_disconnect: the caller has to lock pmlmepriv->lock
- */
-void r8712_ind_disconnect(struct _adapter *padapter)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
-
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- _clr_fwstate_(pmlmepriv, _FW_LINKED);
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_NO_LINK);
- r8712_os_indicate_disconnect(padapter);
- }
- if (padapter->pwrctrlpriv.pwr_mode !=
- padapter->registrypriv.power_mgnt) {
- del_timer(&pmlmepriv->dhcp_timer);
- r8712_set_ps_mode(padapter, padapter->registrypriv.power_mgnt,
- padapter->registrypriv.smart_ps);
- }
-}
-
-/*Notes:
- *pnetwork : returns from r8712_joinbss_event_callback
- *ptarget_wlan: found from scanned_queue
- *if join_res > 0, for (fw_state==WIFI_STATION_STATE), we check if
- * "ptarget_sta" & "ptarget_wlan" exist.
- *if join_res > 0, for (fw_state==WIFI_ADHOC_STATE), we only check
- * if "ptarget_wlan" exist.
- *if join_res > 0, update "cur_network->network" from
- * "pnetwork->network" if (ptarget_wlan !=NULL).
- */
-void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- unsigned long irqL = 0, irqL2;
- struct sta_info *ptarget_sta = NULL, *pcur_sta = NULL;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct wlan_network *cur_network = &pmlmepriv->cur_network;
- struct wlan_network *pcur_wlan = NULL, *ptarget_wlan = NULL;
- unsigned int the_same_macaddr = false;
- struct wlan_network *pnetwork;
-
- if (sizeof(struct list_head) == 4 * sizeof(u32)) {
- pnetwork = kmalloc(sizeof(struct wlan_network), GFP_ATOMIC);
- if (!pnetwork)
- return;
- memcpy((u8 *)pnetwork + 16, (u8 *)pbuf + 8,
- sizeof(struct wlan_network) - 16);
- } else {
- pnetwork = (struct wlan_network *)pbuf;
- }
-
-#ifdef __BIG_ENDIAN
- /* endian_convert */
- pnetwork->join_res = le32_to_cpu(pnetwork->join_res);
- pnetwork->network_type = le32_to_cpu(pnetwork->network_type);
- pnetwork->network.Length = le32_to_cpu(pnetwork->network.Length);
- pnetwork->network.Ssid.SsidLength =
- le32_to_cpu(pnetwork->network.Ssid.SsidLength);
- pnetwork->network.Privacy = le32_to_cpu(pnetwork->network.Privacy);
- pnetwork->network.Rssi = le32_to_cpu(pnetwork->network.Rssi);
- pnetwork->network.NetworkTypeInUse =
- le32_to_cpu(pnetwork->network.NetworkTypeInUse);
- pnetwork->network.Configuration.ATIMWindow =
- le32_to_cpu(pnetwork->network.Configuration.ATIMWindow);
- pnetwork->network.Configuration.BeaconPeriod =
- le32_to_cpu(pnetwork->network.Configuration.BeaconPeriod);
- pnetwork->network.Configuration.DSConfig =
- le32_to_cpu(pnetwork->network.Configuration.DSConfig);
- pnetwork->network.Configuration.FHConfig.DwellTime =
- le32_to_cpu(pnetwork->network.Configuration.FHConfig.DwellTime);
- pnetwork->network.Configuration.FHConfig.HopPattern =
- le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopPattern);
- pnetwork->network.Configuration.FHConfig.HopSet =
- le32_to_cpu(pnetwork->network.Configuration.FHConfig.HopSet);
- pnetwork->network.Configuration.FHConfig.Length =
- le32_to_cpu(pnetwork->network.Configuration.FHConfig.Length);
- pnetwork->network.Configuration.Length =
- le32_to_cpu(pnetwork->network.Configuration.Length);
- pnetwork->network.InfrastructureMode =
- le32_to_cpu(pnetwork->network.InfrastructureMode);
- pnetwork->network.IELength = le32_to_cpu(pnetwork->network.IELength);
-#endif
-
- the_same_macaddr = !memcmp(pnetwork->network.MacAddress,
- cur_network->network.MacAddress, ETH_ALEN);
- pnetwork->network.Length =
- r8712_get_wlan_bssid_ex_sz(&pnetwork->network);
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (pnetwork->network.Length > sizeof(struct wlan_bssid_ex))
- goto ignore_joinbss_callback;
- if (pnetwork->join_res > 0) {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
- /*s1. find ptarget_wlan*/
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (the_same_macaddr) {
- ptarget_wlan =
- r8712_find_network(&pmlmepriv->scanned_queue,
- cur_network->network.MacAddress);
- } else {
- pcur_wlan =
- r8712_find_network(&pmlmepriv->scanned_queue,
- cur_network->network.MacAddress);
- if (pcur_wlan)
- pcur_wlan->fixed = false;
-
- pcur_sta = r8712_get_stainfo(pstapriv,
- cur_network->network.MacAddress);
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL2);
- r8712_free_stainfo(adapter, pcur_sta);
- spin_unlock_irqrestore(&(pstapriv->sta_hash_lock), irqL2);
-
- ptarget_wlan =
- r8712_find_network(&pmlmepriv->scanned_queue,
- pnetwork->network.MacAddress);
- if (ptarget_wlan)
- ptarget_wlan->fixed = true;
- }
- } else {
- ptarget_wlan = r8712_find_network(&pmlmepriv->scanned_queue,
- pnetwork->network.MacAddress);
- if (ptarget_wlan)
- ptarget_wlan->fixed = true;
- }
-
- if (!ptarget_wlan) {
- if (check_fwstate(pmlmepriv,
- _FW_UNDER_LINKING))
- pmlmepriv->fw_state ^=
- _FW_UNDER_LINKING;
- goto ignore_joinbss_callback;
- }
-
- /*s2. find ptarget_sta & update ptarget_sta*/
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- if (the_same_macaddr) {
- ptarget_sta =
- r8712_get_stainfo(pstapriv,
- pnetwork->network.MacAddress);
- if (!ptarget_sta)
- ptarget_sta =
- r8712_alloc_stainfo(pstapriv,
- pnetwork->network.MacAddress);
- } else {
- ptarget_sta =
- r8712_alloc_stainfo(pstapriv,
- pnetwork->network.MacAddress);
- }
- if (ptarget_sta) /*update ptarget_sta*/ {
- ptarget_sta->aid = pnetwork->join_res;
- ptarget_sta->qos_option = 1;
- ptarget_sta->mac_id = 5;
- if (adapter->securitypriv.AuthAlgrthm == 2) {
- adapter->securitypriv.binstallGrpkey = false;
- adapter->securitypriv.busetkipkey = false;
- adapter->securitypriv.bgrpkey_handshake = false;
- ptarget_sta->ieee8021x_blocked = true;
- ptarget_sta->XPrivacy =
- adapter->securitypriv.PrivacyAlgrthm;
- memset((u8 *)&ptarget_sta->x_UncstKey,
- 0,
- sizeof(union Keytype));
- memset((u8 *)&ptarget_sta->tkiprxmickey,
- 0,
- sizeof(union Keytype));
- memset((u8 *)&ptarget_sta->tkiptxmickey,
- 0,
- sizeof(union Keytype));
- memset((u8 *)&ptarget_sta->txpn,
- 0,
- sizeof(union pn48));
- memset((u8 *)&ptarget_sta->rxpn,
- 0,
- sizeof(union pn48));
- }
- } else {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING))
- pmlmepriv->fw_state ^=
- _FW_UNDER_LINKING;
- goto ignore_joinbss_callback;
- }
- }
-
- /*s3. update cur_network & indicate connect*/
- memcpy(&cur_network->network, &pnetwork->network,
- pnetwork->network.Length);
- cur_network->aid = pnetwork->join_res;
- /*update fw_state will clr _FW_UNDER_LINKING*/
- switch (pnetwork->network.InfrastructureMode) {
- case Ndis802_11Infrastructure:
- pmlmepriv->fw_state = WIFI_STATION_STATE;
- break;
- case Ndis802_11IBSS:
- pmlmepriv->fw_state = WIFI_ADHOC_STATE;
- break;
- default:
- pmlmepriv->fw_state = WIFI_NULL_STATE;
- break;
- }
- r8712_update_protection(adapter,
- (cur_network->network.IEs) +
- sizeof(struct NDIS_802_11_FIXED_IEs),
- (cur_network->network.IELength));
- /*TODO: update HT_Capability*/
- update_ht_cap(adapter, cur_network->network.IEs,
- cur_network->network.IELength);
- /*indicate connect*/
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- r8712_indicate_connect(adapter);
- del_timer(&pmlmepriv->assoc_timer);
- } else {
- goto ignore_joinbss_callback;
- }
- } else {
- if (check_fwstate(pmlmepriv, _FW_UNDER_LINKING)) {
- mod_timer(&pmlmepriv->assoc_timer,
- jiffies + msecs_to_jiffies(1));
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
- }
- }
-ignore_joinbss_callback:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- if (sizeof(struct list_head) == 4 * sizeof(u32))
- kfree(pnetwork);
-}
-
-void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- unsigned long irqL;
- struct sta_info *psta;
- struct mlme_priv *pmlmepriv = &(adapter->mlmepriv);
- struct stassoc_event *pstassoc = (struct stassoc_event *)pbuf;
-
- /* to do: */
- if (!r8712_access_ctrl(&adapter->acl_list, pstassoc->macaddr))
- return;
- psta = r8712_get_stainfo(&adapter->stapriv, pstassoc->macaddr);
- if (psta) {
- /*the sta have been in sta_info_queue => do nothing
- *(between drv has received this event before and
- * fw have not yet to set key to CAM_ENTRY)
- */
- return;
- }
-
- psta = r8712_alloc_stainfo(&adapter->stapriv, pstassoc->macaddr);
- if (!psta)
- return;
- /* to do : init sta_info variable */
- psta->qos_option = 0;
- psta->mac_id = le32_to_cpu(pstassoc->cam_id);
- /* psta->aid = (uint)pstassoc->cam_id; */
-
- if (adapter->securitypriv.AuthAlgrthm == 2)
- psta->XPrivacy = adapter->securitypriv.PrivacyAlgrthm;
- psta->ieee8021x_blocked = false;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- if (adapter->stapriv.asoc_sta_count == 2) {
- /* a sta + bc/mc_stainfo (not Ibss_stainfo) */
- r8712_indicate_connect(adapter);
- }
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- unsigned long irqL, irqL2;
- struct sta_info *psta;
- struct wlan_network *pwlan = NULL;
- struct wlan_bssid_ex *pdev_network = NULL;
- u8 *pibss = NULL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct stadel_event *pstadel = (struct stadel_event *)pbuf;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct wlan_network *tgt_network = &pmlmepriv->cur_network;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL2);
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- r8712_ind_disconnect(adapter);
- r8712_free_assoc_resources(adapter);
- }
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE |
- WIFI_ADHOC_STATE)) {
- psta = r8712_get_stainfo(&adapter->stapriv, pstadel->macaddr);
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
- r8712_free_stainfo(adapter, psta);
- spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
- if (adapter->stapriv.asoc_sta_count == 1) {
- /*a sta + bc/mc_stainfo (not Ibss_stainfo) */
- pwlan = r8712_find_network(&pmlmepriv->scanned_queue,
- tgt_network->network.MacAddress);
- if (pwlan) {
- pwlan->fixed = false;
- free_network_nolock(pmlmepriv, pwlan);
- }
- /*re-create ibss*/
- pdev_network = &(adapter->registrypriv.dev_network);
- pibss = adapter->registrypriv.dev_network.MacAddress;
- memcpy(pdev_network, &tgt_network->network,
- r8712_get_wlan_bssid_ex_sz(&tgt_network->network));
- memcpy(&pdev_network->Ssid,
- &pmlmepriv->assoc_ssid,
- sizeof(struct ndis_802_11_ssid));
- r8712_update_registrypriv_dev_network(adapter);
- r8712_generate_random_ibss(pibss);
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE)) {
- _clr_fwstate_(pmlmepriv, WIFI_ADHOC_STATE);
- set_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE);
- }
- }
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL2);
-}
-
-void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- struct reportpwrstate_parm *preportpwrstate =
- (struct reportpwrstate_parm *)pbuf;
-
- preportpwrstate->state |= (u8)(adapter->pwrctrlpriv.cpwm_tog + 0x80);
- r8712_cpwm_int_hdl(adapter, preportpwrstate);
-}
-
-/* When the Netgear 3500 AP is with WPA2PSK-AES mode, it will send
- * the ADDBA req frame with start seq control = 0 to wifi client after
- * the WPA handshake and the sequence number of following data packet
- * will be 0. In this case, the Rx reorder sequence is not longer than 0
- * and the WiFi client will drop the data with seq number 0.
- * So, the 8712 firmware has to inform driver with receiving the
- * ADDBA-Req frame so that the driver can reset the
- * sequence value of Rx reorder control.
- */
-void r8712_got_addbareq_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- struct ADDBA_Req_Report_parm *pAddbareq_pram =
- (struct ADDBA_Req_Report_parm *)pbuf;
- struct sta_info *psta;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct recv_reorder_ctrl *precvreorder_ctrl = NULL;
-
- psta = r8712_get_stainfo(pstapriv, pAddbareq_pram->MacAddress);
- if (psta) {
- precvreorder_ctrl =
- &psta->recvreorder_ctrl[pAddbareq_pram->tid];
- /* set the indicate_seq to 0xffff so that the rx reorder
- * can store any following data packet.
- */
- precvreorder_ctrl->indicate_seq = 0xffff;
- }
-}
-
-void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf)
-{
- if (!adapter->securitypriv.wps_hw_pbc_pressed)
- adapter->securitypriv.wps_hw_pbc_pressed = true;
-}
-
-void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter)
-{
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct sitesurvey_ctrl *psitesurveyctrl = &pmlmepriv->sitesurveyctrl;
- struct registry_priv *pregistrypriv = &adapter->registrypriv;
- u64 current_tx_pkts;
- uint current_rx_pkts;
-
- current_tx_pkts = (adapter->xmitpriv.tx_pkts) -
- (psitesurveyctrl->last_tx_pkts);
- current_rx_pkts = (adapter->recvpriv.rx_pkts) -
- (psitesurveyctrl->last_rx_pkts);
- psitesurveyctrl->last_tx_pkts = adapter->xmitpriv.tx_pkts;
- psitesurveyctrl->last_rx_pkts = adapter->recvpriv.rx_pkts;
- if ((current_tx_pkts > pregistrypriv->busy_thresh) ||
- (current_rx_pkts > pregistrypriv->busy_thresh))
- psitesurveyctrl->traffic_busy = true;
- else
- psitesurveyctrl->traffic_busy = false;
-}
-
-void _r8712_join_timeout_handler(struct _adapter *adapter)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- if (adapter->driver_stopped || adapter->surprise_removed)
- return;
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
- pmlmepriv->to_join = false;
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- r8712_os_indicate_disconnect(adapter);
- _clr_fwstate_(pmlmepriv, _FW_LINKED);
- }
- if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt) {
- r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
- adapter->registrypriv.smart_ps);
- }
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-void r8712_scan_timeout_handler (struct _adapter *adapter)
-{
- unsigned long irqL;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- _clr_fwstate_(pmlmepriv, _FW_UNDER_SURVEY);
- pmlmepriv->to_join = false; /* scan fail, so clear to_join flag */
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-void _r8712_dhcp_timeout_handler (struct _adapter *adapter)
-{
- if (adapter->driver_stopped || adapter->surprise_removed)
- return;
- if (adapter->pwrctrlpriv.pwr_mode != adapter->registrypriv.power_mgnt)
- r8712_set_ps_mode(adapter, adapter->registrypriv.power_mgnt,
- adapter->registrypriv.smart_ps);
-}
-
-int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv)
-{
- struct list_head *phead;
- unsigned char *dst_ssid, *src_ssid;
- struct _adapter *adapter;
- struct __queue *queue = NULL;
- struct wlan_network *pnetwork = NULL;
- struct wlan_network *pnetwork_max_rssi = NULL;
-
- adapter = (struct _adapter *)pmlmepriv->nic_hdl;
- queue = &pmlmepriv->scanned_queue;
- phead = &queue->queue;
- pmlmepriv->pscanned = phead->next;
- while (1) {
- if (end_of_queue_search(phead, pmlmepriv->pscanned)) {
- if (pmlmepriv->assoc_by_rssi && pnetwork_max_rssi) {
- pnetwork = pnetwork_max_rssi;
- goto ask_for_joinbss;
- }
- return -EINVAL;
- }
- pnetwork = container_of(pmlmepriv->pscanned,
- struct wlan_network, list);
- pmlmepriv->pscanned = pmlmepriv->pscanned->next;
- if (pmlmepriv->assoc_by_bssid) {
- dst_ssid = pnetwork->network.MacAddress;
- src_ssid = pmlmepriv->assoc_bssid;
- if (!memcmp(dst_ssid, src_ssid, ETH_ALEN)) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- if (is_same_network(&pmlmepriv->cur_network.network,
- &pnetwork->network)) {
- _clr_fwstate_(pmlmepriv,
- _FW_UNDER_LINKING);
- /*r8712_indicate_connect again*/
- r8712_indicate_connect(adapter);
- return 2;
- }
- r8712_disassoc_cmd(adapter);
- r8712_ind_disconnect(adapter);
- r8712_free_assoc_resources(adapter);
- }
- goto ask_for_joinbss;
- }
- } else if (pmlmepriv->assoc_ssid.SsidLength == 0) {
- goto ask_for_joinbss;
- }
- dst_ssid = pnetwork->network.Ssid.Ssid;
- src_ssid = pmlmepriv->assoc_ssid.Ssid;
- if ((pnetwork->network.Ssid.SsidLength ==
- pmlmepriv->assoc_ssid.SsidLength) &&
- (!memcmp(dst_ssid, src_ssid,
- pmlmepriv->assoc_ssid.SsidLength))) {
- if (pmlmepriv->assoc_by_rssi) {
- /* if the ssid is the same, select the bss
- * which has the max rssi
- */
- if (pnetwork_max_rssi) {
- if (pnetwork->network.Rssi >
- pnetwork_max_rssi->network.Rssi)
- pnetwork_max_rssi = pnetwork;
- } else {
- pnetwork_max_rssi = pnetwork;
- }
- } else if (is_desired_network(adapter, pnetwork)) {
- if (check_fwstate(pmlmepriv, _FW_LINKED)) {
- r8712_disassoc_cmd(adapter);
- r8712_free_assoc_resources(adapter);
- }
- goto ask_for_joinbss;
- }
- }
- }
-
-ask_for_joinbss:
- return r8712_joinbss_cmd(adapter, pnetwork);
-}
-
-int r8712_set_auth(struct _adapter *adapter,
- struct security_priv *psecuritypriv)
-{
- struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
- struct cmd_obj *pcmd;
- struct setauth_parm *psetauthparm;
-
- pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd)
- return -ENOMEM;
-
- psetauthparm = kzalloc(sizeof(*psetauthparm), GFP_ATOMIC);
- if (!psetauthparm) {
- kfree(pcmd);
- return -ENOMEM;
- }
- psetauthparm->mode = (u8)psecuritypriv->AuthAlgrthm;
- pcmd->cmdcode = _SetAuth_CMD_;
- pcmd->parmbuf = (unsigned char *)psetauthparm;
- pcmd->cmdsz = sizeof(struct setauth_parm);
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
- INIT_LIST_HEAD(&pcmd->list);
- r8712_enqueue_cmd(pcmdpriv, pcmd);
- return 0;
-}
-
-int r8712_set_key(struct _adapter *adapter,
- struct security_priv *psecuritypriv,
- sint keyid)
-{
- struct cmd_priv *pcmdpriv = &adapter->cmdpriv;
- struct cmd_obj *pcmd;
- struct setkey_parm *psetkeyparm;
- u8 keylen;
- int ret;
-
- pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd)
- return -ENOMEM;
- psetkeyparm = kzalloc(sizeof(*psetkeyparm), GFP_ATOMIC);
- if (!psetkeyparm) {
- ret = -ENOMEM;
- goto err_free_cmd;
- }
- if (psecuritypriv->AuthAlgrthm == 2) { /* 802.1X */
- psetkeyparm->algorithm =
- (u8)psecuritypriv->XGrpPrivacy;
- } else { /* WEP */
- psetkeyparm->algorithm =
- (u8)psecuritypriv->PrivacyAlgrthm;
- }
- psetkeyparm->keyid = (u8)keyid;
-
- switch (psetkeyparm->algorithm) {
- case _WEP40_:
- keylen = 5;
- memcpy(psetkeyparm->key,
- psecuritypriv->DefKey[keyid].skey, keylen);
- break;
- case _WEP104_:
- keylen = 13;
- memcpy(psetkeyparm->key,
- psecuritypriv->DefKey[keyid].skey, keylen);
- break;
- case _TKIP_:
- if (keyid < 1 || keyid > 2) {
- ret = -EINVAL;
- goto err_free_parm;
- }
- keylen = 16;
- memcpy(psetkeyparm->key,
- &psecuritypriv->XGrpKey[keyid - 1], keylen);
- psetkeyparm->grpkey = 1;
- break;
- case _AES_:
- if (keyid < 1 || keyid > 2) {
- ret = -EINVAL;
- goto err_free_parm;
- }
- keylen = 16;
- memcpy(psetkeyparm->key,
- &psecuritypriv->XGrpKey[keyid - 1], keylen);
- psetkeyparm->grpkey = 1;
- break;
- default:
- ret = -EINVAL;
- goto err_free_parm;
- }
- pcmd->cmdcode = _SetKey_CMD_;
- pcmd->parmbuf = (u8 *)psetkeyparm;
- pcmd->cmdsz = (sizeof(struct setkey_parm));
- pcmd->rsp = NULL;
- pcmd->rspsz = 0;
- INIT_LIST_HEAD(&pcmd->list);
- r8712_enqueue_cmd(pcmdpriv, pcmd);
- return 0;
-
-err_free_parm:
- kfree(psetkeyparm);
-err_free_cmd:
- kfree(pcmd);
- return ret;
-}
-
-/* adjust IEs for r8712_joinbss_cmd in WMM */
-int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie, u8 *out_ie,
- uint in_len, uint initial_out_len)
-{
- unsigned int ielength = 0;
- unsigned int i, j;
-
- i = 12; /* after the fixed IE */
- while (i < in_len) {
- ielength = initial_out_len;
- if (in_ie[i] == 0xDD && in_ie[i + 2] == 0x00 &&
- in_ie[i + 3] == 0x50 && in_ie[i + 4] == 0xF2 &&
- in_ie[i + 5] == 0x02 && i + 5 < in_len) {
- /*WMM element ID and OUI*/
- for (j = i; j < i + 9; j++) {
- out_ie[ielength] = in_ie[j];
- ielength++;
- }
- out_ie[initial_out_len + 1] = 0x07;
- out_ie[initial_out_len + 6] = 0x00;
- out_ie[initial_out_len + 8] = 0x00;
- break;
- }
- i += (in_ie[i + 1] + 2); /* to the next IE element */
- }
- return ielength;
-}
-
-/*
- * Ported from 8185: IsInPreAuthKeyList().
- *
- * Search by BSSID,
- * Return Value:
- * -1 :if there is no pre-auth key in the table
- * >=0 :if there is pre-auth key, and return the entry id
- */
-static int SecIsInPMKIDList(struct _adapter *Adapter, u8 *bssid)
-{
- struct security_priv *p = &Adapter->securitypriv;
- int i;
-
- for (i = 0; i < NUM_PMKID_CACHE; i++)
- if (p->PMKIDList[i].bUsed && !memcmp(p->PMKIDList[i].Bssid, bssid, ETH_ALEN))
- return i;
- return -1;
-}
-
-sint r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
- u8 *out_ie, uint in_len)
-{
- u8 authmode = 0, match;
- u8 sec_ie[IW_CUSTOM_MAX], uncst_oui[4], bkup_ie[255];
- u8 wpa_oui[4] = {0x0, 0x50, 0xf2, 0x01};
- uint ielength, cnt, remove_cnt;
- int iEntry;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
- uint ndisauthmode = psecuritypriv->ndisauthtype;
- uint ndissecuritytype = psecuritypriv->ndisencryptstatus;
-
- if ((ndisauthmode == Ndis802_11AuthModeWPA) ||
- (ndisauthmode == Ndis802_11AuthModeWPAPSK)) {
- authmode = _WPA_IE_ID_;
- uncst_oui[0] = 0x0;
- uncst_oui[1] = 0x50;
- uncst_oui[2] = 0xf2;
- }
- if ((ndisauthmode == Ndis802_11AuthModeWPA2) ||
- (ndisauthmode == Ndis802_11AuthModeWPA2PSK)) {
- authmode = _WPA2_IE_ID_;
- uncst_oui[0] = 0x0;
- uncst_oui[1] = 0x0f;
- uncst_oui[2] = 0xac;
- }
- switch (ndissecuritytype) {
- case Ndis802_11Encryption1Enabled:
- case Ndis802_11Encryption1KeyAbsent:
- uncst_oui[3] = 0x1;
- break;
- case Ndis802_11Encryption2Enabled:
- case Ndis802_11Encryption2KeyAbsent:
- uncst_oui[3] = 0x2;
- break;
- case Ndis802_11Encryption3Enabled:
- case Ndis802_11Encryption3KeyAbsent:
- uncst_oui[3] = 0x4;
- break;
- default:
- break;
- }
- /*Search required WPA or WPA2 IE and copy to sec_ie[] */
- cnt = 12;
- match = false;
- while (cnt < in_len) {
- if (in_ie[cnt] == authmode) {
- if ((authmode == _WPA_IE_ID_) &&
- (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) {
- memcpy(&sec_ie[0], &in_ie[cnt],
- in_ie[cnt + 1] + 2);
- match = true;
- break;
- }
- if (authmode == _WPA2_IE_ID_) {
- memcpy(&sec_ie[0], &in_ie[cnt],
- in_ie[cnt + 1] + 2);
- match = true;
- break;
- }
- if (((authmode == _WPA_IE_ID_) &&
- (!memcmp(&in_ie[cnt + 2], &wpa_oui[0], 4))) ||
- (authmode == _WPA2_IE_ID_))
- memcpy(&bkup_ie[0], &in_ie[cnt],
- in_ie[cnt + 1] + 2);
- }
- cnt += in_ie[cnt + 1] + 2; /*get next*/
- }
- /*restruct WPA IE or WPA2 IE in sec_ie[] */
- if (match) {
- if (sec_ie[0] == _WPA_IE_ID_) {
- /* parsing SSN IE to select required encryption
- * algorithm, and set the bc/mc encryption algorithm
- */
- while (true) {
- /*check wpa_oui tag*/
- if (memcmp(&sec_ie[2], &wpa_oui[0], 4)) {
- match = false;
- break;
- }
- if ((sec_ie[6] != 0x01) || (sec_ie[7] != 0x0)) {
- /*IE Ver error*/
- match = false;
- break;
- }
- if (!memcmp(&sec_ie[8], &wpa_oui[0], 3)) {
- /* get bc/mc encryption type (group
- * key type)
- */
- switch (sec_ie[11]) {
- case 0x0: /*none*/
- psecuritypriv->XGrpPrivacy =
- _NO_PRIVACY_;
- break;
- case 0x1: /*WEP_40*/
- psecuritypriv->XGrpPrivacy =
- _WEP40_;
- break;
- case 0x2: /*TKIP*/
- psecuritypriv->XGrpPrivacy =
- _TKIP_;
- break;
- case 0x3: /*AESCCMP*/
- case 0x4:
- psecuritypriv->XGrpPrivacy =
- _AES_;
- break;
- case 0x5: /*WEP_104*/
- psecuritypriv->XGrpPrivacy =
- _WEP104_;
- break;
- }
- } else {
- match = false;
- break;
- }
- if (sec_ie[12] == 0x01) {
- /*check the unicast encryption type*/
- if (memcmp(&sec_ie[14],
- &uncst_oui[0], 4)) {
- match = false;
- break;
-
- } /*else the uncst_oui is match*/
- } else { /*mixed mode, unicast_enc_type > 1*/
- /*select the uncst_oui and remove
- * the other uncst_oui
- */
- cnt = sec_ie[12];
- remove_cnt = (cnt - 1) * 4;
- sec_ie[12] = 0x01;
- memcpy(&sec_ie[14], &uncst_oui[0], 4);
- /*remove the other unicast suit*/
- memcpy(&sec_ie[18],
- &sec_ie[18 + remove_cnt],
- sec_ie[1] - 18 + 2 -
- remove_cnt);
- sec_ie[1] = sec_ie[1] - remove_cnt;
- }
- break;
- }
- }
- if (authmode == _WPA2_IE_ID_) {
- /* parsing RSN IE to select required encryption
- * algorithm, and set the bc/mc encryption algorithm
- */
- while (true) {
- if ((sec_ie[2] != 0x01) || (sec_ie[3] != 0x0)) {
- /*IE Ver error*/
- match = false;
- break;
- }
- if (!memcmp(&sec_ie[4], &uncst_oui[0], 3)) {
- /*get bc/mc encryption type*/
- switch (sec_ie[7]) {
- case 0x1: /*WEP_40*/
- psecuritypriv->XGrpPrivacy =
- _WEP40_;
- break;
- case 0x2: /*TKIP*/
- psecuritypriv->XGrpPrivacy =
- _TKIP_;
- break;
- case 0x4: /*AESWRAP*/
- psecuritypriv->XGrpPrivacy =
- _AES_;
- break;
- case 0x5: /*WEP_104*/
- psecuritypriv->XGrpPrivacy =
- _WEP104_;
- break;
- default: /*one*/
- psecuritypriv->XGrpPrivacy =
- _NO_PRIVACY_;
- break;
- }
- } else {
- match = false;
- break;
- }
- if (sec_ie[8] == 0x01) {
- /*check the unicast encryption type*/
- if (memcmp(&sec_ie[10],
- &uncst_oui[0], 4)) {
- match = false;
- break;
- } /*else the uncst_oui is match*/
- } else { /*mixed mode, unicast_enc_type > 1*/
- /*select the uncst_oui and remove the
- * other uncst_oui
- */
- cnt = sec_ie[8];
- remove_cnt = (cnt - 1) * 4;
- sec_ie[8] = 0x01;
- memcpy(&sec_ie[10], &uncst_oui[0], 4);
- /*remove the other unicast suit*/
- memcpy(&sec_ie[14],
- &sec_ie[14 + remove_cnt],
- (sec_ie[1] - 14 + 2 -
- remove_cnt));
- sec_ie[1] = sec_ie[1] - remove_cnt;
- }
- break;
- }
- }
- }
- if ((authmode == _WPA_IE_ID_) || (authmode == _WPA2_IE_ID_)) {
- /*copy fixed ie*/
- memcpy(out_ie, in_ie, 12);
- ielength = 12;
- /*copy RSN or SSN*/
- if (match) {
- memcpy(&out_ie[ielength], &sec_ie[0], sec_ie[1] + 2);
- ielength += sec_ie[1] + 2;
- if (authmode == _WPA2_IE_ID_) {
- /*the Pre-Authentication bit should be zero*/
- out_ie[ielength - 1] = 0;
- out_ie[ielength - 2] = 0;
- }
- r8712_report_sec_ie(adapter, authmode, sec_ie);
- }
- } else {
- /*copy fixed ie only*/
- memcpy(out_ie, in_ie, 12);
- ielength = 12;
- if (psecuritypriv->wps_phase) {
- memcpy(out_ie + ielength, psecuritypriv->wps_ie,
- psecuritypriv->wps_ie_len);
- ielength += psecuritypriv->wps_ie_len;
- }
- }
- iEntry = SecIsInPMKIDList(adapter, pmlmepriv->assoc_bssid);
- if (iEntry < 0)
- return ielength;
- if (authmode == _WPA2_IE_ID_) {
- out_ie[ielength] = 1;
- ielength++;
- out_ie[ielength] = 0; /*PMKID count = 0x0100*/
- ielength++;
- memcpy(&out_ie[ielength],
- &psecuritypriv->PMKIDList[iEntry].PMKID, 16);
- ielength += 16;
- out_ie[13] += 18;/*PMKID length = 2+16*/
- }
- return ielength;
-}
-
-void r8712_init_registrypriv_dev_network(struct _adapter *adapter)
-{
- struct registry_priv *pregistrypriv = &adapter->registrypriv;
- struct eeprom_priv *peepriv = &adapter->eeprompriv;
- struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
- u8 *myhwaddr = myid(peepriv);
-
- memcpy(pdev_network->MacAddress, myhwaddr, ETH_ALEN);
- memcpy(&pdev_network->Ssid, &pregistrypriv->ssid,
- sizeof(struct ndis_802_11_ssid));
- pdev_network->Configuration.Length =
- sizeof(struct NDIS_802_11_CONFIGURATION);
- pdev_network->Configuration.BeaconPeriod = 100;
- pdev_network->Configuration.FHConfig.Length = 0;
- pdev_network->Configuration.FHConfig.HopPattern = 0;
- pdev_network->Configuration.FHConfig.HopSet = 0;
- pdev_network->Configuration.FHConfig.DwellTime = 0;
-}
-
-void r8712_update_registrypriv_dev_network(struct _adapter *adapter)
-{
- int sz = 0;
- struct registry_priv *pregistrypriv = &adapter->registrypriv;
- struct wlan_bssid_ex *pdev_network = &pregistrypriv->dev_network;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
- struct wlan_network *cur_network = &adapter->mlmepriv.cur_network;
-
- pdev_network->Privacy = cpu_to_le32(psecuritypriv->PrivacyAlgrthm
- > 0 ? 1 : 0); /* adhoc no 802.1x */
- pdev_network->Rssi = 0;
- switch (pregistrypriv->wireless_mode) {
- case WIRELESS_11B:
- pdev_network->NetworkTypeInUse = Ndis802_11DS;
- break;
- case WIRELESS_11G:
- case WIRELESS_11BG:
- pdev_network->NetworkTypeInUse = Ndis802_11OFDM24;
- break;
- case WIRELESS_11A:
- pdev_network->NetworkTypeInUse = Ndis802_11OFDM5;
- break;
- default:
- /* TODO */
- break;
- }
- pdev_network->Configuration.DSConfig = pregistrypriv->channel;
- if (cur_network->network.InfrastructureMode == Ndis802_11IBSS)
- pdev_network->Configuration.ATIMWindow = 3;
- pdev_network->InfrastructureMode = cur_network->network.InfrastructureMode;
- /* 1. Supported rates
- * 2. IE
- */
- sz = r8712_generate_ie(pregistrypriv);
- pdev_network->IELength = sz;
- pdev_network->Length = r8712_get_wlan_bssid_ex_sz(pdev_network);
-}
-
-/*the function is at passive_level*/
-void r8712_joinbss_reset(struct _adapter *padapter)
-{
- int i;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-
- /* todo: if you want to do something io/reg/hw setting before join_bss,
- * please add code here
- */
- phtpriv->ampdu_enable = false;/*reset to disabled*/
- for (i = 0; i < 16; i++)
- phtpriv->baddbareq_issued[i] = false;/*reset it*/
- if (phtpriv->ht_option) {
- /* validate usb rx aggregation */
- r8712_write8(padapter, 0x102500D9, 48);/*TH = 48 pages, 6k*/
- } else {
- /* invalidate usb rx aggregation */
- /* TH=1 => means that invalidate usb rx aggregation */
- r8712_write8(padapter, 0x102500D9, 1);
- }
-}
-
-/*the function is >= passive_level*/
-unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
- u8 *out_ie, uint in_len, uint *pout_len)
-{
- u32 ielen, out_len;
- unsigned char *p;
- struct ieee80211_ht_cap ht_capie;
- unsigned char WMM_IE[] = {0x00, 0x50, 0xf2, 0x02, 0x00, 0x01, 0x00};
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-
- phtpriv->ht_option = 0;
- p = r8712_get_ie(in_ie + 12, WLAN_EID_HT_CAPABILITY, &ielen, in_len - 12);
- if (p && (ielen > 0)) {
- if (pqospriv->qos_option == 0) {
- out_len = *pout_len;
- r8712_set_ie(out_ie + out_len, WLAN_EID_VENDOR_SPECIFIC,
- _WMM_IE_Length_, WMM_IE, pout_len);
- pqospriv->qos_option = 1;
- }
- out_len = *pout_len;
- memset(&ht_capie, 0, sizeof(struct ieee80211_ht_cap));
- ht_capie.cap_info = cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
- IEEE80211_HT_CAP_SGI_20 |
- IEEE80211_HT_CAP_SGI_40 |
- IEEE80211_HT_CAP_TX_STBC |
- IEEE80211_HT_CAP_MAX_AMSDU |
- IEEE80211_HT_CAP_DSSSCCK40);
- ht_capie.ampdu_params_info = (IEEE80211_HT_AMPDU_PARM_FACTOR &
- 0x03) | (IEEE80211_HT_AMPDU_PARM_DENSITY & 0x00);
- r8712_set_ie(out_ie + out_len, WLAN_EID_HT_CAPABILITY,
- sizeof(struct ieee80211_ht_cap),
- (unsigned char *)&ht_capie, pout_len);
- phtpriv->ht_option = 1;
- }
- return phtpriv->ht_option;
-}
-
-/* the function is > passive_level (in critical_section) */
-static void update_ht_cap(struct _adapter *padapter, u8 *pie, uint ie_len)
-{
- u8 *p, max_ampdu_sz;
- int i;
- uint len;
- struct sta_info *bmc_sta, *psta;
- struct ieee80211_ht_cap *pht_capie;
- struct recv_reorder_ctrl *preorder_ctrl;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
- struct wlan_network *pcur_network = &(pmlmepriv->cur_network);
-
- if (!phtpriv->ht_option)
- return;
- /* maybe needs check if ap supports rx ampdu. */
- if (!phtpriv->ampdu_enable &&
- (pregistrypriv->ampdu_enable == 1))
- phtpriv->ampdu_enable = true;
- /*check Max Rx A-MPDU Size*/
- len = 0;
- p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
- WLAN_EID_HT_CAPABILITY,
- &len, ie_len -
- sizeof(struct NDIS_802_11_FIXED_IEs));
- if (p && len > 0) {
- pht_capie = (struct ieee80211_ht_cap *)(p + 2);
- max_ampdu_sz = (pht_capie->ampdu_params_info &
- IEEE80211_HT_AMPDU_PARM_FACTOR);
- /* max_ampdu_sz (kbytes); */
- max_ampdu_sz = 1 << (max_ampdu_sz + 3);
- phtpriv->rx_ampdu_maxlen = max_ampdu_sz;
- }
- /* for A-MPDU Rx reordering buffer control for bmc_sta & sta_info
- * if A-MPDU Rx is enabled, resetting rx_ordering_ctrl
- * wstart_b(indicate_seq) to default value=0xffff
- * todo: check if AP can send A-MPDU packets
- */
- bmc_sta = r8712_get_bcmc_stainfo(padapter);
- if (bmc_sta) {
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &bmc_sta->recvreorder_ctrl[i];
- preorder_ctrl->indicate_seq = 0xffff;
- preorder_ctrl->wend_b = 0xffff;
- }
- }
- psta = r8712_get_stainfo(&padapter->stapriv,
- pcur_network->network.MacAddress);
- if (psta) {
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
- preorder_ctrl->indicate_seq = 0xffff;
- preorder_ctrl->wend_b = 0xffff;
- }
- }
- len = 0;
- p = r8712_get_ie(pie + sizeof(struct NDIS_802_11_FIXED_IEs),
- WLAN_EID_HT_OPERATION, &len,
- ie_len - sizeof(struct NDIS_802_11_FIXED_IEs));
-}
-
-void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority)
-{
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct ht_priv *phtpriv = &pmlmepriv->htpriv;
-
- if ((phtpriv->ht_option == 1) && (phtpriv->ampdu_enable)) {
- if (!phtpriv->baddbareq_issued[priority]) {
- r8712_addbareq_cmd(padapter, (u8)priority);
- phtpriv->baddbareq_issued[priority] = true;
- }
- }
-}
diff --git a/drivers/staging/rtl8712/rtl871x_mlme.h b/drivers/staging/rtl8712/rtl871x_mlme.h
deleted file mode 100644
index d7d25f240111..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mlme.h
+++ /dev/null
@@ -1,205 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_MLME_H_
-#define __RTL871X_MLME_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wlan_bssdef.h"
-
-#define MAX_BSS_CNT 64
-#define MAX_JOIN_TIMEOUT 6000
-
-#define SCANNING_TIMEOUT 4500
-
-#define SCANQUEUE_LIFETIME 20 /* unit:sec */
-
-#define WIFI_NULL_STATE 0x00000000
-#define WIFI_ASOC_STATE 0x00000001 /* Under Linked state...*/
-#define WIFI_REASOC_STATE 0x00000002
-#define WIFI_SLEEP_STATE 0x00000004
-#define WIFI_STATION_STATE 0x00000008
-#define WIFI_AP_STATE 0x00000010
-#define WIFI_ADHOC_STATE 0x00000020
-#define WIFI_ADHOC_MASTER_STATE 0x00000040
-#define WIFI_UNDER_LINKING 0x00000080
-#define WIFI_SITE_MONITOR 0x00000800 /* to indicate the station
- * is under site surveying
- */
-#define WIFI_MP_STATE 0x00010000
-#define WIFI_MP_CTX_BACKGROUND 0x00020000 /* in cont. tx background*/
-#define WIFI_MP_CTX_ST 0x00040000 /* in cont. tx with
- * single-tone
- */
-#define WIFI_MP_CTX_BACKGROUND_PENDING 0x00080000 /* pending in cont, tx
- * background due
- * to out of skb
- */
-#define WIFI_MP_CTX_CCK_HW 0x00100000 /* in continuous tx*/
-#define WIFI_MP_CTX_CCK_CS 0x00200000 /* in cont, tx with carrier
- * suppression
- */
-#define WIFI_MP_LPBK_STATE 0x00400000
-
-#define _FW_UNDER_LINKING WIFI_UNDER_LINKING
-#define _FW_LINKED WIFI_ASOC_STATE
-#define _FW_UNDER_SURVEY WIFI_SITE_MONITOR
-
-/*
- * there are several "locks" in mlme_priv,
- * since mlme_priv is a shared resource between many threads,
- * like ISR/Call-Back functions, the OID handlers, and even timer functions.
- * Each _queue has its own locks, already.
- * Other items are protected by mlme_priv.lock.
- * To avoid possible dead lock, any thread trying to modify mlme_priv
- * SHALL not lock up more than one lock at a time!
- */
-
-#define traffic_threshold 10
-#define traffic_scan_period 500
-
-struct sitesurvey_ctrl {
- u64 last_tx_pkts;
- uint last_rx_pkts;
- sint traffic_busy;
- struct timer_list sitesurvey_ctrl_timer;
-};
-
-struct mlme_priv {
- spinlock_t lock;
- spinlock_t lock2;
- sint fw_state; /*shall we protect this variable? */
- u8 to_join; /*flag*/
- u8 *nic_hdl;
- struct list_head *pscanned;
- struct __queue free_bss_pool;
- struct __queue scanned_queue;
- u8 *free_bss_buf;
- unsigned long num_of_scanned;
- u8 passive_mode; /*add for Android's SCAN-ACTIVE/SCAN-PASSIVE */
- struct ndis_802_11_ssid assoc_ssid;
- u8 assoc_bssid[6];
- struct wlan_network cur_network;
- struct sitesurvey_ctrl sitesurveyctrl;
- struct timer_list assoc_timer;
- uint assoc_by_bssid;
- uint assoc_by_rssi;
- struct timer_list scan_to_timer; /* driver handles scan_timeout.*/
- struct timer_list dhcp_timer; /* set dhcp to if driver in ps mode.*/
- struct qos_priv qospriv;
- struct ht_priv htpriv;
- struct timer_list wdg_timer; /*watchdog periodic timer*/
-};
-
-static inline u8 *get_bssid(struct mlme_priv *pmlmepriv)
-{
- return pmlmepriv->cur_network.network.MacAddress;
-}
-
-static inline u8 check_fwstate(struct mlme_priv *pmlmepriv, sint state)
-{
- if (pmlmepriv->fw_state & state)
- return true;
- return false;
-}
-
-static inline sint get_fwstate(struct mlme_priv *pmlmepriv)
-{
- return pmlmepriv->fw_state;
-}
-
-/*
- * No Limit on the calling context,
- * therefore set it to be the critical section...
- *
- * ### NOTE:#### (!!!!)
- * TAKE CARE BEFORE CALLING THIS FUNC, LOCK pmlmepriv->lock
- */
-static inline void set_fwstate(struct mlme_priv *pmlmepriv, sint state)
-{
- pmlmepriv->fw_state |= state;
-}
-
-static inline void _clr_fwstate_(struct mlme_priv *pmlmepriv, sint state)
-{
- pmlmepriv->fw_state &= ~state;
-}
-
-/*
- * No Limit on the calling context,
- * therefore set it to be the critical section...
- */
-static inline void clr_fwstate(struct mlme_priv *pmlmepriv, sint state)
-{
- unsigned long irqL;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, state))
- pmlmepriv->fw_state ^= state;
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-static inline void set_scanned_network_val(struct mlme_priv *pmlmepriv,
- sint val)
-{
- unsigned long irqL;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- pmlmepriv->num_of_scanned = val;
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
-}
-
-void r8712_survey_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_surveydone_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_joinbss_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_stassoc_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_stadel_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_atimdone_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_cpwm_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_wpspbc_event_callback(struct _adapter *adapter, u8 *pbuf);
-void r8712_free_network_queue(struct _adapter *adapter);
-int r8712_init_mlme_priv(struct _adapter *adapter);
-void r8712_free_mlme_priv(struct mlme_priv *pmlmepriv);
-int r8712_select_and_join_from_scan(struct mlme_priv *pmlmepriv);
-int r8712_set_key(struct _adapter *adapter,
- struct security_priv *psecuritypriv, sint keyid);
-int r8712_set_auth(struct _adapter *adapter,
- struct security_priv *psecuritypriv);
-uint r8712_get_wlan_bssid_ex_sz(struct wlan_bssid_ex *bss);
-void r8712_generate_random_ibss(u8 *pibss);
-u8 *r8712_get_capability_from_ie(u8 *ie);
-struct wlan_network *r8712_get_oldest_wlan_network(
- struct __queue *scanned_queue);
-void r8712_free_assoc_resources(struct _adapter *adapter);
-void r8712_ind_disconnect(struct _adapter *adapter);
-void r8712_indicate_connect(struct _adapter *adapter);
-int r8712_restruct_sec_ie(struct _adapter *adapter, u8 *in_ie,
- u8 *out_ie, uint in_len);
-int r8712_restruct_wmm_ie(struct _adapter *adapter, u8 *in_ie,
- u8 *out_ie, uint in_len, uint initial_out_len);
-void r8712_init_registrypriv_dev_network(struct _adapter *adapter);
-void r8712_update_registrypriv_dev_network(struct _adapter *adapter);
-void _r8712_sitesurvey_ctrl_handler(struct _adapter *adapter);
-void _r8712_join_timeout_handler(struct _adapter *adapter);
-void r8712_scan_timeout_handler(struct _adapter *adapter);
-void _r8712_dhcp_timeout_handler(struct _adapter *adapter);
-struct wlan_network *_r8712_alloc_network(struct mlme_priv *pmlmepriv);
-sint r8712_if_up(struct _adapter *padapter);
-void r8712_joinbss_reset(struct _adapter *padapter);
-unsigned int r8712_restructure_ht_ie(struct _adapter *padapter, u8 *in_ie,
- u8 *out_ie, uint in_len, uint *pout_len);
-void r8712_issue_addbareq_cmd(struct _adapter *padapter, int priority);
-int r8712_is_same_ibss(struct _adapter *adapter, struct wlan_network *pnetwork);
-
-#endif /*__RTL871X_MLME_H_*/
diff --git a/drivers/staging/rtl8712/rtl871x_mp.c b/drivers/staging/rtl8712/rtl871x_mp.c
deleted file mode 100644
index 099c512c8519..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mp.c
+++ /dev/null
@@ -1,724 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#define _RTL871X_MP_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "rtl871x_mp_phy_regdef.h"
-#include "rtl8712_cmd.h"
-
-static void _init_mp_priv_(struct mp_priv *pmp_priv)
-{
- pmp_priv->mode = _LOOPBOOK_MODE_;
- pmp_priv->curr_ch = 1;
- pmp_priv->curr_modem = MIXED_PHY;
- pmp_priv->curr_rateidx = 0;
- pmp_priv->curr_txpoweridx = 0x14;
- pmp_priv->antenna_tx = ANTENNA_A;
- pmp_priv->antenna_rx = ANTENNA_AB;
- pmp_priv->check_mp_pkt = 0;
- pmp_priv->tx_pktcount = 0;
- pmp_priv->rx_pktcount = 0;
- pmp_priv->rx_crcerrpktcount = 0;
-}
-
-static int init_mp_priv(struct mp_priv *pmp_priv)
-{
- int i;
- struct mp_xmit_frame *pmp_xmitframe;
-
- _init_mp_priv_(pmp_priv);
- _init_queue(&pmp_priv->free_mp_xmitqueue);
- pmp_priv->pallocated_mp_xmitframe_buf = NULL;
- pmp_priv->pallocated_mp_xmitframe_buf = kmalloc(NR_MP_XMITFRAME *
- sizeof(struct mp_xmit_frame) + 4,
- GFP_ATOMIC);
- if (!pmp_priv->pallocated_mp_xmitframe_buf)
- return -ENOMEM;
-
- pmp_priv->pmp_xmtframe_buf = pmp_priv->pallocated_mp_xmitframe_buf +
- 4 -
- ((addr_t)(pmp_priv->pallocated_mp_xmitframe_buf) & 3);
- pmp_xmitframe = (struct mp_xmit_frame *)pmp_priv->pmp_xmtframe_buf;
- for (i = 0; i < NR_MP_XMITFRAME; i++) {
- INIT_LIST_HEAD(&(pmp_xmitframe->list));
- list_add_tail(&(pmp_xmitframe->list),
- &(pmp_priv->free_mp_xmitqueue.queue));
- pmp_xmitframe->pkt = NULL;
- pmp_xmitframe->frame_tag = MP_FRAMETAG;
- pmp_xmitframe->padapter = pmp_priv->papdater;
- pmp_xmitframe++;
- }
- pmp_priv->free_mp_xmitframe_cnt = NR_MP_XMITFRAME;
- return 0;
-}
-
-static int free_mp_priv(struct mp_priv *pmp_priv)
-{
- kfree(pmp_priv->pallocated_mp_xmitframe_buf);
- return 0;
-}
-
-void mp871xinit(struct _adapter *padapter)
-{
- struct mp_priv *pmppriv = &padapter->mppriv;
-
- pmppriv->papdater = padapter;
- init_mp_priv(pmppriv);
-}
-
-void mp871xdeinit(struct _adapter *padapter)
-{
- struct mp_priv *pmppriv = &padapter->mppriv;
-
- free_mp_priv(pmppriv);
-}
-
-/*
- * Special for bb and rf reg read/write
- */
-static u32 fw_iocmd_read(struct _adapter *pAdapter, struct IOCMD_STRUCT iocmd)
-{
- u32 cmd32 = 0, val32 = 0;
- u8 iocmd_class = iocmd.cmdclass;
- u16 iocmd_value = iocmd.value;
- u8 iocmd_idx = iocmd.index;
-
- cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx;
- if (r8712_fw_cmd(pAdapter, cmd32))
- r8712_fw_cmd_data(pAdapter, &val32, 1);
- else
- val32 = 0;
- return val32;
-}
-
-static u8 fw_iocmd_write(struct _adapter *pAdapter,
- struct IOCMD_STRUCT iocmd, u32 value)
-{
- u32 cmd32 = 0;
- u8 iocmd_class = iocmd.cmdclass;
- u32 iocmd_value = iocmd.value;
- u8 iocmd_idx = iocmd.index;
-
- r8712_fw_cmd_data(pAdapter, &value, 0);
- msleep(100);
- cmd32 = (iocmd_class << 24) | (iocmd_value << 8) | iocmd_idx;
- return r8712_fw_cmd(pAdapter, cmd32);
-}
-
-/* offset : 0X800~0XFFF */
-u32 r8712_bb_reg_read(struct _adapter *pAdapter, u16 offset)
-{
- u8 shift = offset & 0x0003; /* 4 byte access */
- u16 bb_addr = offset & 0x0FFC; /* 4 byte access */
- u32 bb_val = 0;
- struct IOCMD_STRUCT iocmd;
-
- iocmd.cmdclass = IOCMD_CLASS_BB_RF;
- iocmd.value = bb_addr;
- iocmd.index = IOCMD_BB_READ_IDX;
- bb_val = fw_iocmd_read(pAdapter, iocmd);
- if (shift != 0) {
- u32 bb_val2 = 0;
-
- bb_val >>= (shift * 8);
- iocmd.value += 4;
- bb_val2 = fw_iocmd_read(pAdapter, iocmd);
- bb_val2 <<= ((4 - shift) * 8);
- bb_val |= bb_val2;
- }
- return bb_val;
-}
-
-/* offset : 0X800~0XFFF */
-u8 r8712_bb_reg_write(struct _adapter *pAdapter, u16 offset, u32 value)
-{
- u8 shift = offset & 0x0003; /* 4 byte access */
- u16 bb_addr = offset & 0x0FFC; /* 4 byte access */
- struct IOCMD_STRUCT iocmd;
-
- iocmd.cmdclass = IOCMD_CLASS_BB_RF;
- iocmd.value = bb_addr;
- iocmd.index = IOCMD_BB_WRITE_IDX;
- if (shift != 0) {
- u32 oldValue = 0;
- u32 newValue = value;
-
- oldValue = r8712_bb_reg_read(pAdapter, iocmd.value);
- oldValue &= (0xFFFFFFFF >> ((4 - shift) * 8));
- value = oldValue | (newValue << (shift * 8));
- if (!fw_iocmd_write(pAdapter, iocmd, value))
- return false;
- iocmd.value += 4;
- oldValue = r8712_bb_reg_read(pAdapter, iocmd.value);
- oldValue &= (0xFFFFFFFF << (shift * 8));
- value = oldValue | (newValue >> ((4 - shift) * 8));
- }
- return fw_iocmd_write(pAdapter, iocmd, value);
-}
-
-/* offset : 0x00 ~ 0xFF */
-u32 r8712_rf_reg_read(struct _adapter *pAdapter, u8 path, u8 offset)
-{
- u16 rf_addr = (path << 8) | offset;
- struct IOCMD_STRUCT iocmd;
-
- iocmd.cmdclass = IOCMD_CLASS_BB_RF;
- iocmd.value = rf_addr;
- iocmd.index = IOCMD_RF_READ_IDX;
- return fw_iocmd_read(pAdapter, iocmd);
-}
-
-u8 r8712_rf_reg_write(struct _adapter *pAdapter, u8 path, u8 offset, u32 value)
-{
- u16 rf_addr = (path << 8) | offset;
- struct IOCMD_STRUCT iocmd;
-
- iocmd.cmdclass = IOCMD_CLASS_BB_RF;
- iocmd.value = rf_addr;
- iocmd.index = IOCMD_RF_WRIT_IDX;
- return fw_iocmd_write(pAdapter, iocmd, value);
-}
-
-static u32 bitshift(u32 bitmask)
-{
- u32 i;
-
- for (i = 0; i <= 31; i++)
- if (((bitmask >> i) & 0x1) == 1)
- break;
- return i;
-}
-
-static u32 get_bb_reg(struct _adapter *pAdapter, u16 offset, u32 bitmask)
-{
- u32 org_value, bit_shift;
-
- org_value = r8712_bb_reg_read(pAdapter, offset);
- bit_shift = bitshift(bitmask);
- return (org_value & bitmask) >> bit_shift;
-}
-
-static u8 set_bb_reg(struct _adapter *pAdapter,
- u16 offset,
- u32 bitmask,
- u32 value)
-{
- u32 org_value, bit_shift, new_value;
-
- if (bitmask != bMaskDWord) {
- org_value = r8712_bb_reg_read(pAdapter, offset);
- bit_shift = bitshift(bitmask);
- new_value = (org_value & (~bitmask)) | (value << bit_shift);
- } else {
- new_value = value;
- }
- return r8712_bb_reg_write(pAdapter, offset, new_value);
-}
-
-static u32 get_rf_reg(struct _adapter *pAdapter, u8 path, u8 offset,
- u32 bitmask)
-{
- u32 org_value, bit_shift;
-
- org_value = r8712_rf_reg_read(pAdapter, path, offset);
- bit_shift = bitshift(bitmask);
- return (org_value & bitmask) >> bit_shift;
-}
-
-static u8 set_rf_reg(struct _adapter *pAdapter, u8 path, u8 offset, u32 bitmask,
- u32 value)
-{
- u32 org_value, bit_shift, new_value;
-
- if (bitmask != bMaskDWord) {
- org_value = r8712_rf_reg_read(pAdapter, path, offset);
- bit_shift = bitshift(bitmask);
- new_value = (org_value & (~bitmask)) | (value << bit_shift);
- } else {
- new_value = value;
- }
- return r8712_rf_reg_write(pAdapter, path, offset, new_value);
-}
-
-/*
- * SetChannel
- * Description
- * Use H2C command to change channel,
- * not only modify rf register, but also other setting need to be done.
- */
-void r8712_SetChannel(struct _adapter *pAdapter)
-{
- struct cmd_priv *pcmdpriv = &pAdapter->cmdpriv;
- struct cmd_obj *pcmd = NULL;
- struct SetChannel_parm *pparm = NULL;
- u16 code = GEN_CMD_CODE(_SetChannel);
-
- pcmd = kmalloc(sizeof(*pcmd), GFP_ATOMIC);
- if (!pcmd)
- return;
- pparm = kmalloc(sizeof(*pparm), GFP_ATOMIC);
- if (!pparm) {
- kfree(pcmd);
- return;
- }
- pparm->curr_ch = pAdapter->mppriv.curr_ch;
- init_h2fwcmd_w_parm_no_rsp(pcmd, pparm, code);
- r8712_enqueue_cmd(pcmdpriv, pcmd);
-}
-
-static void SetCCKTxPower(struct _adapter *pAdapter, u8 TxPower)
-{
- u16 TxAGC = 0;
-
- TxAGC = TxPower;
- set_bb_reg(pAdapter, rTxAGC_CCK_Mcs32, bTxAGCRateCCK, TxAGC);
-}
-
-static void SetOFDMTxPower(struct _adapter *pAdapter, u8 TxPower)
-{
- u32 TxAGC = 0;
-
- TxAGC |= ((TxPower << 24) | (TxPower << 16) | (TxPower << 8) |
- TxPower);
- set_bb_reg(pAdapter, rTxAGC_Rate18_06, bTxAGCRate18_06, TxAGC);
- set_bb_reg(pAdapter, rTxAGC_Rate54_24, bTxAGCRate54_24, TxAGC);
- set_bb_reg(pAdapter, rTxAGC_Mcs03_Mcs00, bTxAGCRateMCS3_MCS0, TxAGC);
- set_bb_reg(pAdapter, rTxAGC_Mcs07_Mcs04, bTxAGCRateMCS7_MCS4, TxAGC);
- set_bb_reg(pAdapter, rTxAGC_Mcs11_Mcs08, bTxAGCRateMCS11_MCS8, TxAGC);
- set_bb_reg(pAdapter, rTxAGC_Mcs15_Mcs12, bTxAGCRateMCS15_MCS12, TxAGC);
-}
-
-void r8712_SetTxPower(struct _adapter *pAdapter)
-{
- u8 TxPower = pAdapter->mppriv.curr_txpoweridx;
-
- SetCCKTxPower(pAdapter, TxPower);
- SetOFDMTxPower(pAdapter, TxPower);
-}
-
-void r8712_SetTxAGCOffset(struct _adapter *pAdapter, u32 ulTxAGCOffset)
-{
- u32 TxAGCOffset_B, TxAGCOffset_C, TxAGCOffset_D, tmpAGC;
-
- TxAGCOffset_B = ulTxAGCOffset & 0x000000ff;
- TxAGCOffset_C = (ulTxAGCOffset & 0x0000ff00) >> 8;
- TxAGCOffset_D = (ulTxAGCOffset & 0x00ff0000) >> 16;
- tmpAGC = TxAGCOffset_D << 8 | TxAGCOffset_C << 4 | TxAGCOffset_B;
- set_bb_reg(pAdapter, rFPGA0_TxGainStage,
- (bXBTxAGC | bXCTxAGC | bXDTxAGC), tmpAGC);
-}
-
-void r8712_SetDataRate(struct _adapter *pAdapter)
-{
- u8 path = RF_PATH_A;
- u8 offset = RF_SYN_G2;
- u32 value;
-
- value = (pAdapter->mppriv.curr_rateidx < 4) ? 0x4440 : 0xF200;
- r8712_rf_reg_write(pAdapter, path, offset, value);
-}
-
-void r8712_SwitchBandwidth(struct _adapter *pAdapter)
-{
- /* 3 1.Set MAC register : BWOPMODE bit2:1 20MhzBW */
- u8 regBwOpMode = 0;
- u8 Bandwidth = pAdapter->mppriv.curr_bandwidth;
-
- regBwOpMode = r8712_read8(pAdapter, 0x10250203);
- if (Bandwidth == HT_CHANNEL_WIDTH_20)
- regBwOpMode |= BIT(2);
- else
- regBwOpMode &= ~(BIT(2));
- r8712_write8(pAdapter, 0x10250203, regBwOpMode);
- /* 3 2.Set PHY related register */
- switch (Bandwidth) {
- /* 20 MHz channel*/
- case HT_CHANNEL_WIDTH_20:
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bRFMOD, 0x0);
- set_bb_reg(pAdapter, rFPGA1_RFMOD, bRFMOD, 0x0);
- /* Use PHY_REG.txt default value. Do not need to change.
- * Correct the tx power for CCK rate in 40M.
- * It is set in Tx descriptor for 8192x series
- */
- set_bb_reg(pAdapter, rFPGA0_AnalogParameter2, bMaskDWord, 0x58);
- break;
- /* 40 MHz channel*/
- case HT_CHANNEL_WIDTH_40:
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bRFMOD, 0x1);
- set_bb_reg(pAdapter, rFPGA1_RFMOD, bRFMOD, 0x1);
- /* Use PHY_REG.txt default value. Do not need to change.
- * Correct the tx power for CCK rate in 40M.
- * Set Control channel to upper or lower. These settings are
- * required only for 40MHz
- */
- set_bb_reg(pAdapter, rCCK0_System, bCCKSideBand,
- (HAL_PRIME_CHNL_OFFSET_DONT_CARE >> 1));
- set_bb_reg(pAdapter, rOFDM1_LSTF, 0xC00,
- HAL_PRIME_CHNL_OFFSET_DONT_CARE);
- set_bb_reg(pAdapter, rFPGA0_AnalogParameter2, bMaskDWord, 0x18);
- break;
- default:
- break;
- }
-
- /* 3 3.Set RF related register */
- switch (Bandwidth) {
- case HT_CHANNEL_WIDTH_20:
- set_rf_reg(pAdapter, RF_PATH_A, RF_CHNLBW,
- BIT(10) | BIT(11), 0x01);
- break;
- case HT_CHANNEL_WIDTH_40:
- set_rf_reg(pAdapter, RF_PATH_A, RF_CHNLBW,
- BIT(10) | BIT(11), 0x00);
- break;
- default:
- break;
- }
-}
-
-/*------------------------------Define structure----------------------------*/
-struct R_ANTENNA_SELECT_OFDM {
- u32 r_tx_antenna:4;
- u32 r_ant_l:4;
- u32 r_ant_non_ht:4;
- u32 r_ant_ht1:4;
- u32 r_ant_ht2:4;
- u32 r_ant_ht_s1:4;
- u32 r_ant_non_ht_s1:4;
- u32 OFDM_TXSC:2;
- u32 Reserved:2;
-};
-
-struct R_ANTENNA_SELECT_CCK {
- u8 r_cckrx_enable_2:2;
- u8 r_cckrx_enable:2;
- u8 r_ccktx_enable:4;
-};
-
-void r8712_SwitchAntenna(struct _adapter *pAdapter)
-{
- u32 ofdm_tx_en_val = 0, ofdm_tx_ant_sel_val = 0;
- u8 ofdm_rx_ant_sel_val = 0;
- u8 cck_ant_select_val = 0;
- u32 cck_ant_sel_val = 0;
- struct R_ANTENNA_SELECT_CCK *p_cck_txrx;
-
- p_cck_txrx = (struct R_ANTENNA_SELECT_CCK *)&cck_ant_select_val;
-
- switch (pAdapter->mppriv.antenna_tx) {
- case ANTENNA_A:
- /* From SD3 Willis suggestion !!! Set RF A=TX and B as standby*/
- set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2);
- set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 1);
- ofdm_tx_en_val = 0x3;
- ofdm_tx_ant_sel_val = 0x11111111;/* Power save */
- p_cck_txrx->r_ccktx_enable = 0x8;
- break;
- case ANTENNA_B:
- set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 1);
- set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2);
- ofdm_tx_en_val = 0x3;
- ofdm_tx_ant_sel_val = 0x22222222;/* Power save */
- p_cck_txrx->r_ccktx_enable = 0x4;
- break;
- case ANTENNA_AB: /* For 8192S */
- set_bb_reg(pAdapter, rFPGA0_XA_HSSIParameter2, 0xe, 2);
- set_bb_reg(pAdapter, rFPGA0_XB_HSSIParameter2, 0xe, 2);
- ofdm_tx_en_val = 0x3;
- ofdm_tx_ant_sel_val = 0x3321333; /* Disable Power save */
- p_cck_txrx->r_ccktx_enable = 0xC;
- break;
- default:
- break;
- }
- /*OFDM Tx*/
- set_bb_reg(pAdapter, rFPGA1_TxInfo, 0xffffffff, ofdm_tx_ant_sel_val);
- /*OFDM Tx*/
- set_bb_reg(pAdapter, rFPGA0_TxInfo, 0x0000000f, ofdm_tx_en_val);
- switch (pAdapter->mppriv.antenna_rx) {
- case ANTENNA_A:
- ofdm_rx_ant_sel_val = 0x1; /* A */
- p_cck_txrx->r_cckrx_enable = 0x0; /* default: A */
- p_cck_txrx->r_cckrx_enable_2 = 0x0; /* option: A */
- break;
- case ANTENNA_B:
- ofdm_rx_ant_sel_val = 0x2; /* B */
- p_cck_txrx->r_cckrx_enable = 0x1; /* default: B */
- p_cck_txrx->r_cckrx_enable_2 = 0x1; /* option: B */
- break;
- case ANTENNA_AB:
- ofdm_rx_ant_sel_val = 0x3; /* AB */
- p_cck_txrx->r_cckrx_enable = 0x0; /* default:A */
- p_cck_txrx->r_cckrx_enable_2 = 0x1; /* option:B */
- break;
- default:
- break;
- }
- /*OFDM Rx*/
- set_bb_reg(pAdapter, rOFDM0_TRxPathEnable, 0x0000000f,
- ofdm_rx_ant_sel_val);
- /*OFDM Rx*/
- set_bb_reg(pAdapter, rOFDM1_TRxPathEnable, 0x0000000f,
- ofdm_rx_ant_sel_val);
-
- cck_ant_sel_val = cck_ant_select_val;
- /*CCK TxRx*/
- set_bb_reg(pAdapter, rCCK0_AFESetting, bMaskByte3, cck_ant_sel_val);
-}
-
-static void TriggerRFThermalMeter(struct _adapter *pAdapter)
-{
- /* 0x24: RF Reg[6:5] */
- set_rf_reg(pAdapter, RF_PATH_A, RF_T_METER, bRFRegOffsetMask, 0x60);
-}
-
-static u32 ReadRFThermalMeter(struct _adapter *pAdapter)
-{
- /* 0x24: RF Reg[4:0] */
- return get_rf_reg(pAdapter, RF_PATH_A, RF_T_METER, 0x1F);
-}
-
-void r8712_GetThermalMeter(struct _adapter *pAdapter, u32 *value)
-{
- TriggerRFThermalMeter(pAdapter);
- msleep(1000);
- *value = ReadRFThermalMeter(pAdapter);
-}
-
-void r8712_SetSingleCarrierTx(struct _adapter *pAdapter, u8 bStart)
-{
- if (bStart) { /* Start Single Carrier. */
- /* 1. if OFDM block on? */
- if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn))
- /*set OFDM block on*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);
- /* 2. set CCK test mode off, set to CCK normal mode */
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, bDisable);
- /* 3. turn on scramble setting */
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
- /* 4. Turn On Single Carrier Tx and off the other test modes. */
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bEnable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
- } else { /* Stop Single Carrier.*/
- /* Turn off all test modes.*/
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier,
- bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
- msleep(20);
- /*BB Reset*/
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
- }
-}
-
-void r8712_SetSingleToneTx(struct _adapter *pAdapter, u8 bStart)
-{
- u8 rfPath;
-
- switch (pAdapter->mppriv.antenna_tx) {
- case ANTENNA_B:
- rfPath = RF_PATH_B;
- break;
- case ANTENNA_A:
- default:
- rfPath = RF_PATH_A;
- break;
- }
- if (bStart) { /* Start Single Tone.*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, bDisable);
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bDisable);
- set_rf_reg(pAdapter, rfPath, RF_TX_G2, bRFRegOffsetMask,
- 0xd4000);
- msleep(100);
- /* PAD all on.*/
- set_rf_reg(pAdapter, rfPath, RF_AC, bRFRegOffsetMask, 0x2001f);
- msleep(100);
- } else { /* Stop Single Tone.*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);
- set_rf_reg(pAdapter, rfPath, RF_TX_G2, bRFRegOffsetMask,
- 0x54000);
- msleep(100);
- /* PAD all on.*/
- set_rf_reg(pAdapter, rfPath, RF_AC, bRFRegOffsetMask, 0x30000);
- msleep(100);
- }
-}
-
-void r8712_SetCarrierSuppressionTx(struct _adapter *pAdapter, u8 bStart)
-{
- if (bStart) { /* Start Carrier Suppression.*/
- if (pAdapter->mppriv.curr_rateidx <= MPT_RATE_11M) {
- /* 1. if CCK block on? */
- if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn)) {
- /*set CCK block on*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn,
- bEnable);
- }
- /* Turn Off All Test Mode */
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx,
- bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier,
- bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone,
- bDisable);
- /*transmit mode*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x2);
- /*turn off scramble setting*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble,
- bDisable);
- /*Set CCK Tx Test Rate*/
- /*Set FTxRate to 1Mbps*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKTxRate, 0x0);
- }
- } else { /* Stop Carrier Suppression. */
- if (pAdapter->mppriv.curr_rateidx <= MPT_RATE_11M) {
- /*normal mode*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x0);
- /*turn on scramble setting*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble,
- bEnable);
- /*BB Reset*/
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
- }
- }
-}
-
-static void SetCCKContinuousTx(struct _adapter *pAdapter, u8 bStart)
-{
- u32 cckrate;
-
- if (bStart) {
- /* 1. if CCK block on? */
- if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn)) {
- /*set CCK block on*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bCCKEn, bEnable);
- }
- /* Turn Off All Test Mode */
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
- /*Set CCK Tx Test Rate*/
- cckrate = pAdapter->mppriv.curr_rateidx;
- set_bb_reg(pAdapter, rCCK0_System, bCCKTxRate, cckrate);
- /*transmit mode*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x2);
- /*turn on scramble setting*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
- } else {
- /*normal mode*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, 0x0);
- /*turn on scramble setting*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
- /*BB Reset*/
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
- }
-} /* mpt_StartCckContTx */
-
-static void SetOFDMContinuousTx(struct _adapter *pAdapter, u8 bStart)
-{
- if (bStart) {
- /* 1. if OFDM block on? */
- if (!get_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn)) {
- /*set OFDM block on*/
- set_bb_reg(pAdapter, rFPGA0_RFMOD, bOFDMEn, bEnable);
- }
- /* 2. set CCK test mode off, set to CCK normal mode*/
- set_bb_reg(pAdapter, rCCK0_System, bCCKBBMode, bDisable);
- /* 3. turn on scramble setting */
- set_bb_reg(pAdapter, rCCK0_System, bCCKScramble, bEnable);
- /* 4. Turn On Continue Tx and turn off the other test modes.*/
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bEnable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
- } else {
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMContinueTx, bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleCarrier,
- bDisable);
- set_bb_reg(pAdapter, rOFDM1_LSTF, bOFDMSingleTone, bDisable);
- msleep(20);
- /*BB Reset*/
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x0);
- set_bb_reg(pAdapter, rPMAC_Reset, bBBResetB, 0x1);
- }
-} /* mpt_StartOfdmContTx */
-
-void r8712_SetContinuousTx(struct _adapter *pAdapter, u8 bStart)
-{
- /* ADC turn off [bit24-21] adc port0 ~ port1 */
- if (bStart) {
- r8712_bb_reg_write(pAdapter, rRx_Wait_CCCA,
- r8712_bb_reg_read(pAdapter,
- rRx_Wait_CCCA) & 0xFE1FFFFF);
- msleep(100);
- }
- if (pAdapter->mppriv.curr_rateidx <= MPT_RATE_11M)
- SetCCKContinuousTx(pAdapter, bStart);
- else if ((pAdapter->mppriv.curr_rateidx >= MPT_RATE_6M) &&
- (pAdapter->mppriv.curr_rateidx <= MPT_RATE_MCS15))
- SetOFDMContinuousTx(pAdapter, bStart);
- /* ADC turn on [bit24-21] adc port0 ~ port1 */
- if (!bStart)
- r8712_bb_reg_write(pAdapter, rRx_Wait_CCCA,
- r8712_bb_reg_read(pAdapter,
- rRx_Wait_CCCA) | 0x01E00000);
-}
-
-void r8712_ResetPhyRxPktCount(struct _adapter *pAdapter)
-{
- u32 i, phyrx_set = 0;
-
- for (i = OFDM_PPDU_BIT; i <= HT_MPDU_FAIL_BIT; i++) {
- phyrx_set = 0;
- phyrx_set |= (i << 28); /*select*/
- phyrx_set |= 0x08000000; /* set counter to zero*/
- r8712_write32(pAdapter, RXERR_RPT, phyrx_set);
- }
-}
-
-static u32 GetPhyRxPktCounts(struct _adapter *pAdapter, u32 selbit)
-{
- /*selection*/
- u32 phyrx_set = 0;
- u32 SelectBit;
-
- SelectBit = selbit << 28;
- phyrx_set |= (SelectBit & 0xF0000000);
- r8712_write32(pAdapter, RXERR_RPT, phyrx_set);
- /*Read packet count*/
- return r8712_read32(pAdapter, RXERR_RPT) & RPTMaxCount;
-}
-
-u32 r8712_GetPhyRxPktReceived(struct _adapter *pAdapter)
-{
- u32 OFDM_cnt = GetPhyRxPktCounts(pAdapter, OFDM_MPDU_OK_BIT);
- u32 CCK_cnt = GetPhyRxPktCounts(pAdapter, CCK_MPDU_OK_BIT);
- u32 HT_cnt = GetPhyRxPktCounts(pAdapter, HT_MPDU_OK_BIT);
-
- return OFDM_cnt + CCK_cnt + HT_cnt;
-}
-
-u32 r8712_GetPhyRxPktCRC32Error(struct _adapter *pAdapter)
-{
- u32 OFDM_cnt = GetPhyRxPktCounts(pAdapter, OFDM_MPDU_FAIL_BIT);
- u32 CCK_cnt = GetPhyRxPktCounts(pAdapter, CCK_MPDU_FAIL_BIT);
- u32 HT_cnt = GetPhyRxPktCounts(pAdapter, HT_MPDU_FAIL_BIT);
-
- return OFDM_cnt + CCK_cnt + HT_cnt;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_mp.h b/drivers/staging/rtl8712/rtl871x_mp.h
deleted file mode 100644
index 0a60b1e6ccaf..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mp.h
+++ /dev/null
@@ -1,275 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_MP_H_
-#define __RTL871X_MP_H_
-
-#define MPT_NOOP 0
-#define MPT_READ_MAC_1BYTE 1
-#define MPT_READ_MAC_2BYTE 2
-#define MPT_READ_MAC_4BYTE 3
-#define MPT_WRITE_MAC_1BYTE 4
-#define MPT_WRITE_MAC_2BYTE 5
-#define MPT_WRITE_MAC_4BYTE 6
-#define MPT_READ_BB_CCK 7
-#define MPT_WRITE_BB_CCK 8
-#define MPT_READ_BB_OFDM 9
-#define MPT_WRITE_BB_OFDM 10
-#define MPT_READ_RF 11
-#define MPT_WRITE_RF 12
-#define MPT_READ_EEPROM_1BYTE 13
-#define MPT_WRITE_EEPROM_1BYTE 14
-#define MPT_READ_EEPROM_2BYTE 15
-#define MPT_WRITE_EEPROM_2BYTE 16
-#define MPT_SET_CSTHRESHOLD 21
-#define MPT_SET_INITGAIN 22
-#define MPT_SWITCH_BAND 23
-#define MPT_SWITCH_CHANNEL 24
-#define MPT_SET_DATARATE 25
-#define MPT_SWITCH_ANTENNA 26
-#define MPT_SET_TX_POWER 27
-#define MPT_SET_CONT_TX 28
-#define MPT_SET_SINGLE_CARRIER 29
-#define MPT_SET_CARRIER_SUPPRESSION 30
-#define MPT_GET_RATE_TABLE 31
-#define MPT_READ_TSSI 32
-#define MPT_GET_THERMAL_METER 33
-#define MAX_MP_XMITBUF_SZ 2048
-#define NR_MP_XMITFRAME 8
-
-struct mp_xmit_frame {
- struct list_head list;
- struct pkt_attrib attrib;
- _pkt *pkt;
- int frame_tag;
- struct _adapter *padapter;
- u8 *mem_addr;
- u16 sz[8];
- struct urb *pxmit_urb[8];
- u8 bpending[8];
- u8 last[8];
-};
-
-struct mp_wiparam {
- u32 bcompleted;
- u32 act_type;
- u32 io_offset;
- u32 io_value;
-};
-
-struct mp_priv {
- struct _adapter *papdater;
- /*OID cmd handler*/
- struct mp_wiparam workparam;
- u8 act_in_progress;
- /*Tx Section*/
- u8 TID;
- u32 tx_pktcount;
- /*Rx Section*/
- u32 rx_pktcount;
- u32 rx_crcerrpktcount;
- u32 rx_pktloss;
- struct recv_stat rxstat;
- /*RF/BB relative*/
- u32 curr_ch;
- u32 curr_rateidx;
- u8 curr_bandwidth;
- u8 curr_modem;
- u8 curr_txpoweridx;
- u32 curr_crystalcap;
- u16 antenna_tx;
- u16 antenna_rx;
- u8 curr_rfpath;
- u8 check_mp_pkt;
- uint ForcedDataRate;
- struct wlan_network mp_network;
- unsigned char network_macaddr[6];
- /*Testing Flag*/
- u32 mode;/*0 for normal type packet,
- * 1 for loopback packet (16bytes TXCMD)
- */
- sint prev_fw_state;
- u8 *pallocated_mp_xmitframe_buf;
- u8 *pmp_xmtframe_buf;
- struct __queue free_mp_xmitqueue;
- u32 free_mp_xmitframe_cnt;
-};
-
-struct IOCMD_STRUCT {
- u8 cmdclass;
- u16 value;
- u8 index;
-};
-
-struct rf_reg_param {
- u32 path;
- u32 offset;
- u32 value;
-};
-
-struct bb_reg_param {
- u32 offset;
- u32 value;
-};
-
-/* ======================================================================= */
-
-#define LOWER true
-#define RAISE false
-#define IOCMD_CTRL_REG 0x10250370
-#define IOCMD_DATA_REG 0x10250374
-#define IOCMD_GET_THERMAL_METER 0xFD000028
-#define IOCMD_CLASS_BB_RF 0xF0
-#define IOCMD_BB_READ_IDX 0x00
-#define IOCMD_BB_WRITE_IDX 0x01
-#define IOCMD_RF_READ_IDX 0x02
-#define IOCMD_RF_WRIT_IDX 0x03
-#define BB_REG_BASE_ADDR 0x800
-#define RF_PATH_A 0
-#define RF_PATH_B 1
-#define RF_PATH_C 2
-#define RF_PATH_D 3
-#define MAX_RF_PATH_NUMS 2
-#define _2MAC_MODE_ 0
-#define _LOOPBOOK_MODE_ 1
-
-/* MP set force data rate base on the definition. */
-enum {
- /* CCK rate. */
- MPT_RATE_1M, /* 0 */
- MPT_RATE_2M,
- MPT_RATE_55M,
- MPT_RATE_11M, /* 3 */
-
- /* OFDM rate. */
- MPT_RATE_6M, /* 4 */
- MPT_RATE_9M,
- MPT_RATE_12M,
- MPT_RATE_18M,
- MPT_RATE_24M,
- MPT_RATE_36M,
- MPT_RATE_48M,
- MPT_RATE_54M, /* 11 */
-
- /* HT rate. */
- MPT_RATE_MCS0, /* 12 */
- MPT_RATE_MCS1,
- MPT_RATE_MCS2,
- MPT_RATE_MCS3,
- MPT_RATE_MCS4,
- MPT_RATE_MCS5,
- MPT_RATE_MCS6,
- MPT_RATE_MCS7, /* 19 */
- MPT_RATE_MCS8,
- MPT_RATE_MCS9,
- MPT_RATE_MCS10,
- MPT_RATE_MCS11,
- MPT_RATE_MCS12,
- MPT_RATE_MCS13,
- MPT_RATE_MCS14,
- MPT_RATE_MCS15, /* 27 */
- MPT_RATE_LAST
-};
-
-/* Represent Channel Width in HT Capabilities */
-enum HT_CHANNEL_WIDTH {
- HT_CHANNEL_WIDTH_20 = 0,
- HT_CHANNEL_WIDTH_40 = 1,
-};
-
-#define MAX_TX_PWR_INDEX_N_MODE 64 /* 0x3F */
-
-enum POWER_MODE {
- POWER_LOW = 0,
- POWER_NORMAL
-};
-
-#define RX_PKT_BROADCAST 1
-#define RX_PKT_DEST_ADDR 2
-#define RX_PKT_PHY_MATCH 3
-
-#define RPTMaxCount 0x000FFFFF
-
-/* parameter 1 : BitMask
- * bit 0 : OFDM PPDU
- * bit 1 : OFDM False Alarm
- * bit 2 : OFDM MPDU OK
- * bit 3 : OFDM MPDU Fail
- * bit 4 : CCK PPDU
- * bit 5 : CCK False Alarm
- * bit 6 : CCK MPDU ok
- * bit 7 : CCK MPDU fail
- * bit 8 : HT PPDU counter
- * bit 9 : HT false alarm
- * bit 10 : HT MPDU total
- * bit 11 : HT MPDU OK
- * bit 12 : HT MPDU fail
- * bit 15 : RX full drop
- */
-enum RXPHY_BITMASK {
- OFDM_PPDU_BIT = 0,
- OFDM_MPDU_OK_BIT,
- OFDM_MPDU_FAIL_BIT,
- CCK_PPDU_BIT,
- CCK_MPDU_OK_BIT,
- CCK_MPDU_FAIL_BIT,
- HT_PPDU_BIT,
- HT_MPDU_BIT,
- HT_MPDU_OK_BIT,
- HT_MPDU_FAIL_BIT,
-};
-
-enum ENCRY_CTRL_STATE {
- HW_CONTROL, /*hw encryption& decryption*/
- SW_CONTROL, /*sw encryption& decryption*/
- HW_ENCRY_SW_DECRY, /*hw encryption & sw decryption*/
- SW_ENCRY_HW_DECRY /*sw encryption & hw decryption*/
-};
-
-/* Bandwidth Offset */
-#define HAL_PRIME_CHNL_OFFSET_DONT_CARE 0
-#define HAL_PRIME_CHNL_OFFSET_LOWER 1
-#define HAL_PRIME_CHNL_OFFSET_UPPER 2
-/*=======================================================================*/
-void mp871xinit(struct _adapter *padapter);
-void mp871xdeinit(struct _adapter *padapter);
-u32 r8712_bb_reg_read(struct _adapter *Adapter, u16 offset);
-u8 r8712_bb_reg_write(struct _adapter *Adapter, u16 offset, u32 value);
-u32 r8712_rf_reg_read(struct _adapter *Adapter, u8 path, u8 offset);
-u8 r8712_rf_reg_write(struct _adapter *Adapter, u8 path,
- u8 offset, u32 value);
-u32 r8712_get_bb_reg(struct _adapter *Adapter, u16 offset, u32 bitmask);
-u8 r8712_set_bb_reg(struct _adapter *Adapter, u16 offset,
- u32 bitmask, u32 value);
-u32 r8712_get_rf_reg(struct _adapter *Adapter, u8 path, u8 offset,
- u32 bitmask);
-u8 r8712_set_rf_reg(struct _adapter *Adapter, u8 path, u8 offset,
- u32 bitmask, u32 value);
-
-void r8712_SetChannel(struct _adapter *pAdapter);
-void r8712_SetTxPower(struct _adapter *pAdapte);
-void r8712_SetTxAGCOffset(struct _adapter *pAdapter, u32 ulTxAGCOffset);
-void r8712_SetDataRate(struct _adapter *pAdapter);
-void r8712_SwitchBandwidth(struct _adapter *pAdapter);
-void r8712_SwitchAntenna(struct _adapter *pAdapter);
-void r8712_GetThermalMeter(struct _adapter *pAdapter, u32 *value);
-void r8712_SetContinuousTx(struct _adapter *pAdapter, u8 bStart);
-void r8712_SetSingleCarrierTx(struct _adapter *pAdapter, u8 bStart);
-void r8712_SetSingleToneTx(struct _adapter *pAdapter, u8 bStart);
-void r8712_SetCarrierSuppressionTx(struct _adapter *pAdapter, u8 bStart);
-void r8712_ResetPhyRxPktCount(struct _adapter *pAdapter);
-u32 r8712_GetPhyRxPktReceived(struct _adapter *pAdapter);
-u32 r8712_GetPhyRxPktCRC32Error(struct _adapter *pAdapter);
-
-#endif /*__RTL871X_MP_H_*/
-
diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c b/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
deleted file mode 100644
index 26fa09b45c90..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.c
+++ /dev/null
@@ -1,883 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_mp_ioctl.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#include <linux/rndis.h>
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "mlme_osdep.h"
-#include "rtl871x_mp.h"
-#include "rtl871x_mp_ioctl.h"
-
-uint oid_null_function(struct oid_par_priv *poid_par_priv)
-{
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv)
-{
- uint status = RNDIS_STATUS_SUCCESS;
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid == SET_OID) {
- if (poid_par_priv->information_buf_len >= sizeof(u8))
- Adapter->registrypriv.wireless_mode =
- *(u8 *)poid_par_priv->information_buf;
- else
- status = RNDIS_STATUS_INVALID_LENGTH;
- } else if (poid_par_priv->type_of_oid == QUERY_OID) {
- if (poid_par_priv->information_buf_len >= sizeof(u8)) {
- *(u8 *)poid_par_priv->information_buf =
- Adapter->registrypriv.wireless_mode;
- *poid_par_priv->bytes_rw =
- poid_par_priv->information_buf_len;
- } else {
- status = RNDIS_STATUS_INVALID_LENGTH;
- }
- } else {
- status = RNDIS_STATUS_NOT_ACCEPTED;
- }
- return status;
-}
-
-uint oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- struct bb_reg_param *pbbreg;
- u16 offset;
- u32 value;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
- return RNDIS_STATUS_INVALID_LENGTH;
- pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
- offset = (u16)(pbbreg->offset) & 0xFFF; /*0ffset :0x800~0xfff*/
- if (offset < BB_REG_BASE_ADDR)
- offset |= BB_REG_BASE_ADDR;
- value = pbbreg->value;
- r8712_bb_reg_write(Adapter, offset, value);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- struct bb_reg_param *pbbreg;
- u16 offset;
- u32 value;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(struct bb_reg_param))
- return RNDIS_STATUS_INVALID_LENGTH;
- pbbreg = (struct bb_reg_param *)(poid_par_priv->information_buf);
- offset = (u16)(pbbreg->offset) & 0xFFF; /*0ffset :0x800~0xfff*/
- if (offset < BB_REG_BASE_ADDR)
- offset |= BB_REG_BASE_ADDR;
- value = r8712_bb_reg_read(Adapter, offset);
- pbbreg->value = value;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- struct rf_reg_param *pbbreg;
- u8 path;
- u8 offset;
- u32 value;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
- return RNDIS_STATUS_INVALID_LENGTH;
- pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
- path = (u8)pbbreg->path;
- if (path > RF_PATH_B)
- return RNDIS_STATUS_NOT_ACCEPTED;
- offset = (u8)pbbreg->offset;
- value = pbbreg->value;
- r8712_rf_reg_write(Adapter, path, offset, value);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- struct rf_reg_param *pbbreg;
- u8 path;
- u8 offset;
- u32 value;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(struct rf_reg_param))
- return RNDIS_STATUS_INVALID_LENGTH;
- pbbreg = (struct rf_reg_param *)(poid_par_priv->information_buf);
- path = (u8)pbbreg->path;
- if (path > RF_PATH_B) /* 1T2R path_a /path_b */
- return RNDIS_STATUS_NOT_ACCEPTED;
- offset = (u8)pbbreg->offset;
- value = r8712_rf_reg_read(Adapter, path, offset);
- pbbreg->value = value;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-/*This function initializes the DUT to the MP test mode*/
-static int mp_start_test(struct _adapter *padapter)
-{
- struct mp_priv *pmppriv = &padapter->mppriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *tgt_network = &pmlmepriv->cur_network;
- struct wlan_bssid_ex *bssid;
- struct sta_info *psta;
- unsigned long length;
- unsigned long irqL;
- int res = 0;
-
- bssid = kzalloc(sizeof(*bssid), GFP_KERNEL);
- if (!bssid)
- return -ENOMEM;
-
- /* 3 1. initialize a new struct wlan_bssid_ex */
- memcpy(bssid->MacAddress, pmppriv->network_macaddr, ETH_ALEN);
- bssid->Ssid.SsidLength = 16;
- memcpy(bssid->Ssid.Ssid, (unsigned char *)"mp_pseudo_adhoc",
- bssid->Ssid.SsidLength);
- bssid->InfrastructureMode = Ndis802_11IBSS;
- bssid->NetworkTypeInUse = Ndis802_11DS;
- bssid->IELength = 0;
- length = r8712_get_wlan_bssid_ex_sz(bssid);
- if (length % 4) {
- /*round up to multiple of 4 bytes.*/
- bssid->Length = ((length >> 2) + 1) << 2;
- } else {
- bssid->Length = length;
- }
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
- goto end_of_mp_start_test;
- /*init mp_start_test status*/
- pmppriv->prev_fw_state = get_fwstate(pmlmepriv);
- pmlmepriv->fw_state = WIFI_MP_STATE;
- if (pmppriv->mode == _LOOPBOOK_MODE_)
- set_fwstate(pmlmepriv, WIFI_MP_LPBK_STATE); /*append txdesc*/
- set_fwstate(pmlmepriv, _FW_UNDER_LINKING);
- /* 3 2. create a new psta for mp driver */
- /* clear psta in the cur_network, if any */
- psta = r8712_get_stainfo(&padapter->stapriv,
- tgt_network->network.MacAddress);
- if (psta)
- r8712_free_stainfo(padapter, psta);
- psta = r8712_alloc_stainfo(&padapter->stapriv, bssid->MacAddress);
- if (!psta) {
- res = -ENOMEM;
- goto end_of_mp_start_test;
- }
- /* 3 3. join pseudo AdHoc */
- tgt_network->join_res = 1;
- tgt_network->aid = psta->aid = 1;
- memcpy(&tgt_network->network, bssid, length);
- _clr_fwstate_(pmlmepriv, _FW_UNDER_LINKING);
- r8712_os_indicate_connect(padapter);
- /* Set to LINKED STATE for MP TRX Testing */
- set_fwstate(pmlmepriv, _FW_LINKED);
-end_of_mp_start_test:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- kfree(bssid);
- return res;
-}
-
-/*This function change the DUT from the MP test mode into normal mode */
-static int mp_stop_test(struct _adapter *padapter)
-{
- struct mp_priv *pmppriv = &padapter->mppriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct wlan_network *tgt_network = &pmlmepriv->cur_network;
- struct sta_info *psta;
- unsigned long irqL;
-
- spin_lock_irqsave(&pmlmepriv->lock, irqL);
- if (!check_fwstate(pmlmepriv, WIFI_MP_STATE))
- goto end_of_mp_stop_test;
- /* 3 1. disconnect pseudo AdHoc */
- r8712_os_indicate_disconnect(padapter);
- /* 3 2. clear psta used in mp test mode. */
- psta = r8712_get_stainfo(&padapter->stapriv,
- tgt_network->network.MacAddress);
- if (psta)
- r8712_free_stainfo(padapter, psta);
- /* 3 3. return to normal state (default:station mode) */
- pmlmepriv->fw_state = pmppriv->prev_fw_state; /* WIFI_STATION_STATE;*/
- /*flush the cur_network*/
- memset(tgt_network, 0, sizeof(struct wlan_network));
-end_of_mp_stop_test:
- spin_unlock_irqrestore(&pmlmepriv->lock, irqL);
- return _SUCCESS;
-}
-
-uint oid_rt_pro_set_data_rate_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 ratevalue;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- ratevalue = *((u32 *)poid_par_priv->information_buf);
- if (ratevalue >= MPT_RATE_LAST)
- return RNDIS_STATUS_INVALID_DATA;
- Adapter->mppriv.curr_rateidx = ratevalue;
- r8712_SetDataRate(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- uint status = RNDIS_STATUS_SUCCESS;
- u32 mode;
- u8 val8;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- mode = *((u32 *)poid_par_priv->information_buf);
- Adapter->mppriv.mode = mode;/* 1 for loopback*/
- if (mp_start_test(Adapter))
- status = RNDIS_STATUS_NOT_ACCEPTED;
- r8712_write8(Adapter, MSR, 1); /* Link in ad hoc network, 0x1025004C */
- r8712_write8(Adapter, RCR, 0); /* RCR : disable all pkt, 0x10250048 */
- /* RCR disable Check BSSID, 0x1025004a */
- r8712_write8(Adapter, RCR + 2, 0x57);
- /* disable RX filter map , mgt frames will put in RX FIFO 0 */
- r8712_write16(Adapter, RXFLTMAP0, 0x0);
- val8 = r8712_read8(Adapter, EE_9346CR);
- if (!(val8 & _9356SEL)) { /*boot from EFUSE*/
- r8712_efuse_reg_init(Adapter);
- r8712_efuse_change_max_size(Adapter);
- r8712_efuse_reg_uninit(Adapter);
- }
- return status;
-}
-
-uint oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (mp_stop_test(Adapter) == _FAIL)
- return RNDIS_STATUS_NOT_ACCEPTED;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_channel_direct_call_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 Channel;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- Channel = *((u32 *)poid_par_priv->information_buf);
- if (Channel > 14)
- return RNDIS_STATUS_NOT_ACCEPTED;
- Adapter->mppriv.curr_ch = Channel;
- r8712_SetChannel(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_antenna_bb_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 antenna;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- antenna = *((u32 *)poid_par_priv->information_buf);
- Adapter->mppriv.antenna_tx = (u16)((antenna & 0xFFFF0000) >> 16);
- Adapter->mppriv.antenna_rx = (u16)(antenna & 0x0000FFFF);
- r8712_SwitchAntenna(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_tx_power_control_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 tx_pwr_idx;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- tx_pwr_idx = *((u32 *)poid_par_priv->information_buf);
- if (tx_pwr_idx > MAX_TX_PWR_INDEX_N_MODE)
- return RNDIS_STATUS_NOT_ACCEPTED;
- Adapter->mppriv.curr_txpoweridx = (u8)tx_pwr_idx;
- r8712_SetTxPower(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_query_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- if (poid_par_priv->information_buf_len == sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- Adapter->mppriv.tx_pktcount;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_query_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- if (poid_par_priv->information_buf_len == sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- Adapter->mppriv.rx_pktcount;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_query_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- if (poid_par_priv->information_buf_len == sizeof(u32)) {
- *(u32 *)poid_par_priv->information_buf =
- Adapter->mppriv.rx_crcerrpktcount;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_reset_tx_packet_sent_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- Adapter->mppriv.tx_pktcount = 0;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_reset_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len == sizeof(u32)) {
- Adapter->mppriv.rx_pktcount = 0;
- Adapter->mppriv.rx_crcerrpktcount = 0;
- } else {
- return RNDIS_STATUS_INVALID_LENGTH;
- }
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_reset_phy_rx_packet_count_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- r8712_ResetPhyRxPktCount(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_phy_rx_packet_received_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- *(u32 *)poid_par_priv->information_buf =
- r8712_GetPhyRxPktReceived(Adapter);
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_phy_rx_packet_crc32_error_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len != sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- *(u32 *)poid_par_priv->information_buf =
- r8712_GetPhyRxPktCRC32Error(Adapter);
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- Adapter->mppriv.curr_modem = *((u8 *)poid_par_priv->information_buf);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_continuous_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 bStartTest;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- bStartTest = *((u32 *)poid_par_priv->information_buf);
- r8712_SetContinuousTx(Adapter, (u8)bStartTest);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_single_carrier_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 bStartTest;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- bStartTest = *((u32 *)poid_par_priv->information_buf);
- r8712_SetSingleCarrierTx(Adapter, (u8)bStartTest);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_carrier_suppression_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 bStartTest;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- bStartTest = *((u32 *)poid_par_priv->information_buf);
- r8712_SetCarrierSuppressionTx(Adapter, (u8)bStartTest);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_set_single_tone_tx_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 bStartTest;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- bStartTest = *((u32 *)poid_par_priv->information_buf);
- r8712_SetSingleToneTx(Adapter, (u8)bStartTest);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- uint status = RNDIS_STATUS_SUCCESS;
- struct mp_rw_reg *RegRWStruct;
- u16 offset;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
- if ((RegRWStruct->offset >= 0x10250800) &&
- (RegRWStruct->offset <= 0x10250FFF)) {
- /*baseband register*/
- /*0ffset :0x800~0xfff*/
- offset = (u16)(RegRWStruct->offset) & 0xFFF;
- RegRWStruct->value = r8712_bb_reg_read(Adapter, offset);
- } else {
- switch (RegRWStruct->width) {
- case 1:
- RegRWStruct->value = r8712_read8(Adapter,
- RegRWStruct->offset);
- break;
- case 2:
- RegRWStruct->value = r8712_read16(Adapter,
- RegRWStruct->offset);
- break;
- case 4:
- RegRWStruct->value = r8712_read32(Adapter,
- RegRWStruct->offset);
- break;
- default:
- status = RNDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- }
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return status;
-}
-
-uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- uint status = RNDIS_STATUS_SUCCESS;
- struct mp_rw_reg *RegRWStruct;
- u16 offset;
- u32 value;
- u32 oldValue = 0;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- RegRWStruct = (struct mp_rw_reg *)poid_par_priv->information_buf;
- if ((RegRWStruct->offset >= 0x10250800) &&
- (RegRWStruct->offset <= 0x10250FFF)) {
- /*baseband register*/
- offset = (u16)(RegRWStruct->offset) & 0xFFF;
- value = RegRWStruct->value;
- switch (RegRWStruct->width) {
- case 1:
- oldValue = r8712_bb_reg_read(Adapter, offset);
- oldValue &= 0xFFFFFF00;
- value &= 0x000000FF;
- value |= oldValue;
- break;
- case 2:
- oldValue = r8712_bb_reg_read(Adapter, offset);
- oldValue &= 0xFFFF0000;
- value &= 0x0000FFFF;
- value |= oldValue;
- break;
- }
- r8712_bb_reg_write(Adapter, offset, value);
- } else {
- switch (RegRWStruct->width) {
- case 1:
- r8712_write8(Adapter, RegRWStruct->offset,
- (unsigned char)RegRWStruct->value);
- break;
- case 2:
- r8712_write16(Adapter, RegRWStruct->offset,
- (unsigned short)RegRWStruct->value);
- break;
- case 4:
- r8712_write32(Adapter, RegRWStruct->offset,
- (unsigned int)RegRWStruct->value);
- break;
- default:
- status = RNDIS_STATUS_NOT_ACCEPTED;
- break;
- }
- }
- return status;
-}
-
-uint oid_rt_get_thermal_meter_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- if (Adapter->mppriv.act_in_progress)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- if (poid_par_priv->information_buf_len < sizeof(u8))
- return RNDIS_STATUS_INVALID_LENGTH;
- /*init workparam*/
- Adapter->mppriv.act_in_progress = true;
- Adapter->mppriv.workparam.bcompleted = false;
- Adapter->mppriv.workparam.act_type = MPT_GET_THERMAL_METER;
- Adapter->mppriv.workparam.io_offset = 0;
- Adapter->mppriv.workparam.io_value = 0xFFFFFFFF;
- r8712_GetThermalMeter(Adapter, &Adapter->mppriv.workparam.io_value);
- Adapter->mppriv.workparam.bcompleted = true;
- Adapter->mppriv.act_in_progress = false;
- *(u32 *)poid_par_priv->information_buf =
- Adapter->mppriv.workparam.io_value;
- *poid_par_priv->bytes_rw = sizeof(u32);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- uint status = RNDIS_STATUS_SUCCESS;
-
- struct EFUSE_ACCESS_STRUCT *pefuse;
- u8 *data;
- u16 addr = 0, cnts = 0;
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len <
- sizeof(struct EFUSE_ACCESS_STRUCT))
- return RNDIS_STATUS_INVALID_LENGTH;
- pefuse = (struct EFUSE_ACCESS_STRUCT *)poid_par_priv->information_buf;
- addr = pefuse->start_addr;
- cnts = pefuse->cnts;
- data = pefuse->data;
- memset(data, 0xFF, cnts);
- if ((addr > 511) || (cnts < 1) || (cnts > 512) || (addr + cnts) >
- EFUSE_MAX_SIZE)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (!r8712_efuse_access(Adapter, true, addr, cnts, data))
- status = RNDIS_STATUS_FAILURE;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return status;
-}
-
-/*------------------------------------------------------------------------*/
-uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- uint status = RNDIS_STATUS_SUCCESS;
-
- struct EFUSE_ACCESS_STRUCT *pefuse;
- u8 *data;
- u16 addr = 0, cnts = 0;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
-
- pefuse = (struct EFUSE_ACCESS_STRUCT *)poid_par_priv->information_buf;
- addr = pefuse->start_addr;
- cnts = pefuse->cnts;
- data = pefuse->data;
-
- if ((addr > 511) || (cnts < 1) || (cnts > 512) ||
- (addr + cnts) > r8712_efuse_get_max_size(Adapter))
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (!r8712_efuse_access(Adapter, false, addr, cnts, data))
- status = RNDIS_STATUS_FAILURE;
- return status;
-}
-
-/*----------------------------------------------------------------------*/
-
-uint oid_rt_get_efuse_current_size_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(int))
- return RNDIS_STATUS_INVALID_LENGTH;
- r8712_efuse_reg_init(Adapter);
- *(int *)poid_par_priv->information_buf =
- r8712_efuse_get_current_size(Adapter);
- r8712_efuse_reg_uninit(Adapter);
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- *(int *)poid_par_priv->information_buf =
- r8712_efuse_get_max_size(Adapter);
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv)
-{
- uint status = RNDIS_STATUS_SUCCESS;
-
- if (poid_par_priv->type_of_oid == QUERY_OID)
- status = oid_rt_pro_read_efuse_hdl(poid_par_priv);
- else
- status = oid_rt_pro_write_efuse_hdl(poid_par_priv);
- return status;
-}
-
-uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- uint status = RNDIS_STATUS_SUCCESS;
- u8 *data;
-
- *poid_par_priv->bytes_rw = 0;
- if (poid_par_priv->information_buf_len < EFUSE_MAP_MAX_SIZE)
- return RNDIS_STATUS_INVALID_LENGTH;
- data = (u8 *)poid_par_priv->information_buf;
- if (poid_par_priv->type_of_oid == QUERY_OID) {
- if (r8712_efuse_map_read(Adapter, 0, EFUSE_MAP_MAX_SIZE, data))
- *poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE;
- else
- status = RNDIS_STATUS_FAILURE;
- } else {
- /* SET_OID */
- if (r8712_efuse_reg_init(Adapter)) {
- if (r8712_efuse_map_write(Adapter, 0,
- EFUSE_MAP_MAX_SIZE, data))
- *poid_par_priv->bytes_rw = EFUSE_MAP_MAX_SIZE;
- else
- status = RNDIS_STATUS_FAILURE;
- r8712_efuse_reg_uninit(Adapter);
- } else {
- status = RNDIS_STATUS_FAILURE;
- }
- }
- return status;
-}
-
-uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u32 bandwidth;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- bandwidth = *((u32 *)poid_par_priv->information_buf);/*4*/
- if (bandwidth != HT_CHANNEL_WIDTH_20)
- bandwidth = HT_CHANNEL_WIDTH_40;
- Adapter->mppriv.curr_bandwidth = (u8)bandwidth;
- r8712_SwitchBandwidth(Adapter);
- return RNDIS_STATUS_SUCCESS;
-}
-
-uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
- u8 rx_pkt_type;
- u32 rcr_val32;
-
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(u8))
- return RNDIS_STATUS_INVALID_LENGTH;
- rx_pkt_type = *((u8 *)poid_par_priv->information_buf);/*4*/
- rcr_val32 = r8712_read32(Adapter, RCR);/*RCR = 0x10250048*/
- rcr_val32 &= ~(RCR_CBSSID | RCR_AB | RCR_AM | RCR_APM | RCR_AAP);
- switch (rx_pkt_type) {
- case RX_PKT_BROADCAST:
- rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32);
- break;
- case RX_PKT_DEST_ADDR:
- rcr_val32 |= (RCR_AB | RCR_AM | RCR_APM | RCR_AAP | RCR_ACRC32);
- break;
- case RX_PKT_PHY_MATCH:
- rcr_val32 |= (RCR_APM | RCR_ACRC32);
- break;
- default:
- rcr_val32 &= ~(RCR_AAP |
- RCR_APM |
- RCR_AM |
- RCR_AB |
- RCR_ACRC32);
- break;
- }
- if (rx_pkt_type == RX_PKT_DEST_ADDR)
- Adapter->mppriv.check_mp_pkt = 1;
- else
- Adapter->mppriv.check_mp_pkt = 0;
- r8712_write32(Adapter, RCR, rcr_val32);
- return RNDIS_STATUS_SUCCESS;
-}
-
-/*--------------------------------------------------------------------------*/
-/*Linux*/
-unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv)
-{
- return _SUCCESS;
-}
-
-/*-------------------------------------------------------------------------*/
-uint oid_rt_set_power_down_hdl(struct oid_par_priv *poid_par_priv)
-{
- if (poid_par_priv->type_of_oid != SET_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- /*CALL the power_down function*/
- return RNDIS_STATUS_SUCCESS;
-}
-
-/*-------------------------------------------------------------------------- */
-uint oid_rt_get_power_mode_hdl(struct oid_par_priv *poid_par_priv)
-{
- struct _adapter *Adapter = (struct _adapter *)
- (poid_par_priv->adapter_context);
-
- if (poid_par_priv->type_of_oid != QUERY_OID)
- return RNDIS_STATUS_NOT_ACCEPTED;
- if (poid_par_priv->information_buf_len < sizeof(u32))
- return RNDIS_STATUS_INVALID_LENGTH;
- *(int *)poid_par_priv->information_buf =
- Adapter->registrypriv.low_power ? POWER_LOW : POWER_NORMAL;
- *poid_par_priv->bytes_rw = poid_par_priv->information_buf_len;
- return RNDIS_STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h b/drivers/staging/rtl8712/rtl871x_mp_ioctl.h
deleted file mode 100644
index aa4d5ce471f2..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mp_ioctl.h
+++ /dev/null
@@ -1,328 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_MP_IOCTL_H
-#define _RTL871X_MP_IOCTL_H
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "mp_custom_oid.h"
-#include "rtl871x_ioctl.h"
-#include "rtl871x_ioctl_rtl.h"
-#include "rtl8712_efuse.h"
-
-#define TESTFWCMDNUMBER 1000000
-#define TEST_H2CINT_WAIT_TIME 500
-#define TEST_C2HINT_WAIT_TIME 500
-#define HCI_TEST_SYSCFG_HWMASK 1
-#define _BUSCLK_40M (4 << 2)
-
-struct CFG_DBG_MSG_STRUCT {
- u32 DebugLevel;
- u32 DebugComponent_H32;
- u32 DebugComponent_L32;
-};
-
-struct mp_rw_reg {
- uint offset;
- uint width;
- u32 value;
-};
-
-/* for OID_RT_PRO_READ16_EEPROM & OID_RT_PRO_WRITE16_EEPROM */
-struct eeprom_rw_param {
- uint offset;
- u16 value;
-};
-
-struct EFUSE_ACCESS_STRUCT {
- u16 start_addr;
- u16 cnts;
- u8 data[];
-};
-
-struct burst_rw_reg {
- uint offset;
- uint len;
- u8 Data[256];
-};
-
-struct usb_vendor_req {
- u8 bRequest;
- u16 wValue;
- u16 wIndex;
- u16 wLength;
- u8 u8Dir;/*0:OUT, 1:IN */
- u8 u8InData;
-};
-
-struct DR_VARIABLE_STRUCT {
- u8 offset;
- u32 variable;
-};
-
-/* oid_rtl_seg_87_11_00 */
-uint oid_rt_pro_read_register_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_write_register_hdl(struct oid_par_priv *poid_par_priv);
-/* oid_rtl_seg_81_80_00 */
-uint oid_rt_pro_set_data_rate_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_start_test_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_stop_test_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_channel_direct_call_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_antenna_bb_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_tx_power_control_hdl(
- struct oid_par_priv *poid_par_priv);
-/* oid_rtl_seg_81_80_20 */
-uint oid_rt_pro_query_tx_packet_sent_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_query_rx_packet_received_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_query_rx_packet_crc32_error_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_reset_tx_packet_sent_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_reset_rx_packet_received_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_modulation_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_continuous_tx_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_single_carrier_tx_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_carrier_suppression_tx_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_set_single_tone_tx_hdl(
- struct oid_par_priv *poid_par_priv);
-/* oid_rtl_seg_81_87 */
-uint oid_rt_pro_write_bb_reg_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_read_bb_reg_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_write_rf_reg_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_read_rf_reg_hdl(struct oid_par_priv *poid_par_priv);
-/* oid_rtl_seg_81_85 */
-uint oid_rt_wireless_mode_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_read_efuse_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_write_efuse_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_efuse_current_size_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_efuse_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_pro_efuse_map_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_bandwidth_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_rx_packet_type_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_efuse_max_size_hdl(struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_thermal_meter_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_reset_phy_rx_packet_count_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_phy_rx_packet_received_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_phy_rx_packet_crc32_error_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_set_power_down_hdl(
- struct oid_par_priv *poid_par_priv);
-uint oid_rt_get_power_mode_hdl(
- struct oid_par_priv *poid_par_priv);
-#ifdef _RTL871X_MP_IOCTL_C_ /* CAUTION!!! */
-/* This ifdef _MUST_ be left in!! */
-
-#else /* _RTL871X_MP_IOCTL_C_ */
-extern struct oid_obj_priv oid_rtl_seg_81_87[5];
-extern struct oid_obj_priv oid_rtl_seg_87_11_00[32];
-extern struct oid_obj_priv oid_rtl_seg_87_11_20[5];
-extern struct oid_obj_priv oid_rtl_seg_87_11_50[2];
-extern struct oid_obj_priv oid_rtl_seg_87_11_80[1];
-extern struct oid_obj_priv oid_rtl_seg_87_11_B0[1];
-extern struct oid_obj_priv oid_rtl_seg_87_11_F0[16];
-extern struct oid_obj_priv oid_rtl_seg_87_12_00[32];
-
-#endif /* _RTL871X_MP_IOCTL_C_ */
-
-enum MP_MODE {
- MP_START_MODE,
- MP_STOP_MODE,
- MP_ERR_MODE
-};
-
-struct rwreg_param {
- unsigned int offset;
- unsigned int width;
- unsigned int value;
-};
-
-struct bbreg_param {
- unsigned int offset;
- unsigned int phymask;
- unsigned int value;
-};
-
-struct txpower_param {
- unsigned int pwr_index;
-};
-
-struct datarate_param {
- unsigned int rate_index;
-};
-
-struct rfintfs_parm {
- unsigned int rfintfs;
-};
-
-struct mp_xmit_packet {
- unsigned int len;
-};
-
-struct psmode_param {
- unsigned int ps_mode;
- unsigned int smart_ps;
-};
-
-struct mp_ioctl_handler {
- unsigned int paramsize;
- unsigned int (*handler)(struct oid_par_priv *poid_par_priv);
- unsigned int oid;
-};
-
-struct mp_ioctl_param {
- unsigned int subcode;
- unsigned int len;
- unsigned char data[];
-};
-
-#define GEN_MP_IOCTL_SUBCODE(code) _MP_IOCTL_ ## code ## _CMD_
-
-enum RTL871X_MP_IOCTL_SUBCODE {
- GEN_MP_IOCTL_SUBCODE(MP_START), /*0*/
- GEN_MP_IOCTL_SUBCODE(MP_STOP), /*1*/
- GEN_MP_IOCTL_SUBCODE(READ_REG), /*2*/
- GEN_MP_IOCTL_SUBCODE(WRITE_REG),
- GEN_MP_IOCTL_SUBCODE(SET_CHANNEL), /*4*/
- GEN_MP_IOCTL_SUBCODE(SET_TXPOWER), /*5*/
- GEN_MP_IOCTL_SUBCODE(SET_DATARATE), /*6*/
- GEN_MP_IOCTL_SUBCODE(READ_BB_REG), /*7*/
- GEN_MP_IOCTL_SUBCODE(WRITE_BB_REG),
- GEN_MP_IOCTL_SUBCODE(READ_RF_REG), /*9*/
- GEN_MP_IOCTL_SUBCODE(WRITE_RF_REG),
- GEN_MP_IOCTL_SUBCODE(SET_RF_INTFS),
- GEN_MP_IOCTL_SUBCODE(IOCTL_XMIT_PACKET), /*12*/
- GEN_MP_IOCTL_SUBCODE(PS_STATE), /*13*/
- GEN_MP_IOCTL_SUBCODE(READ16_EEPROM), /*14*/
- GEN_MP_IOCTL_SUBCODE(WRITE16_EEPROM), /*15*/
- GEN_MP_IOCTL_SUBCODE(SET_PTM), /*16*/
- GEN_MP_IOCTL_SUBCODE(READ_TSSI), /*17*/
- GEN_MP_IOCTL_SUBCODE(CNTU_TX), /*18*/
- GEN_MP_IOCTL_SUBCODE(SET_BANDWIDTH), /*19*/
- GEN_MP_IOCTL_SUBCODE(SET_RX_PKT_TYPE), /*20*/
- GEN_MP_IOCTL_SUBCODE(RESET_PHY_RX_PKT_CNT), /*21*/
- GEN_MP_IOCTL_SUBCODE(GET_PHY_RX_PKT_RECV), /*22*/
- GEN_MP_IOCTL_SUBCODE(GET_PHY_RX_PKT_ERROR), /*23*/
- GEN_MP_IOCTL_SUBCODE(SET_POWER_DOWN), /*24*/
- GEN_MP_IOCTL_SUBCODE(GET_THERMAL_METER), /*25*/
- GEN_MP_IOCTL_SUBCODE(GET_POWER_MODE), /*26*/
- GEN_MP_IOCTL_SUBCODE(EFUSE), /*27*/
- GEN_MP_IOCTL_SUBCODE(EFUSE_MAP), /*28*/
- GEN_MP_IOCTL_SUBCODE(GET_EFUSE_MAX_SIZE), /*29*/
- GEN_MP_IOCTL_SUBCODE(GET_EFUSE_CURRENT_SIZE), /*30*/
- GEN_MP_IOCTL_SUBCODE(SC_TX), /*31*/
- GEN_MP_IOCTL_SUBCODE(CS_TX), /*32*/
- GEN_MP_IOCTL_SUBCODE(ST_TX), /*33*/
- GEN_MP_IOCTL_SUBCODE(SET_ANTENNA), /*34*/
- MAX_MP_IOCTL_SUBCODE,
-};
-
-unsigned int mp_ioctl_xmit_packet_hdl(struct oid_par_priv *poid_par_priv);
-
-#ifdef _RTL871X_MP_IOCTL_C_ /* CAUTION!!! */
-/* This ifdef _MUST_ be left in!! */
-
-static struct mp_ioctl_handler mp_ioctl_hdl[] = {
- {sizeof(u32), oid_rt_pro_start_test_hdl,
- OID_RT_PRO_START_TEST},/*0*/
- {sizeof(u32), oid_rt_pro_stop_test_hdl,
- OID_RT_PRO_STOP_TEST},/*1*/
- {sizeof(struct rwreg_param),
- oid_rt_pro_read_register_hdl,
- OID_RT_PRO_READ_REGISTER},/*2*/
- {sizeof(struct rwreg_param),
- oid_rt_pro_write_register_hdl,
- OID_RT_PRO_WRITE_REGISTER},
- {sizeof(u32),
- oid_rt_pro_set_channel_direct_call_hdl,
- OID_RT_PRO_SET_CHANNEL_DIRECT_CALL},
- {sizeof(struct txpower_param),
- oid_rt_pro_set_tx_power_control_hdl,
- OID_RT_PRO_SET_TX_POWER_CONTROL},
- {sizeof(u32),
- oid_rt_pro_set_data_rate_hdl,
- OID_RT_PRO_SET_DATA_RATE},
- {sizeof(struct bb_reg_param),
- oid_rt_pro_read_bb_reg_hdl,
- OID_RT_PRO_READ_BB_REG},/*7*/
- {sizeof(struct bb_reg_param),
- oid_rt_pro_write_bb_reg_hdl,
- OID_RT_PRO_WRITE_BB_REG},
- {sizeof(struct rwreg_param),
- oid_rt_pro_read_rf_reg_hdl,
- OID_RT_PRO_RF_READ_REGISTRY},/*9*/
- {sizeof(struct rwreg_param),
- oid_rt_pro_write_rf_reg_hdl,
- OID_RT_PRO_RF_WRITE_REGISTRY},
- {sizeof(struct rfintfs_parm), NULL, 0},
- {0, mp_ioctl_xmit_packet_hdl, 0},/*12*/
- {sizeof(struct psmode_param), NULL, 0},/*13*/
- {sizeof(struct eeprom_rw_param), NULL, 0},/*14*/
- {sizeof(struct eeprom_rw_param), NULL, 0},/*15*/
- {sizeof(unsigned char), NULL, 0},/*16*/
- {sizeof(u32), NULL, 0},/*17*/
- {sizeof(u32), oid_rt_pro_set_continuous_tx_hdl,
- OID_RT_PRO_SET_CONTINUOUS_TX},/*18*/
- {sizeof(u32), oid_rt_set_bandwidth_hdl,
- OID_RT_SET_BANDWIDTH},/*19*/
- {sizeof(u32), oid_rt_set_rx_packet_type_hdl,
- OID_RT_SET_RX_PACKET_TYPE},/*20*/
- {0, oid_rt_reset_phy_rx_packet_count_hdl,
- OID_RT_RESET_PHY_RX_PACKET_COUNT},/*21*/
- {sizeof(u32), oid_rt_get_phy_rx_packet_received_hdl,
- OID_RT_GET_PHY_RX_PACKET_RECEIVED},/*22*/
- {sizeof(u32), oid_rt_get_phy_rx_packet_crc32_error_hdl,
- OID_RT_GET_PHY_RX_PACKET_CRC32_ERROR},/*23*/
- {sizeof(unsigned char), oid_rt_set_power_down_hdl,
- OID_RT_SET_POWER_DOWN},/*24*/
- {sizeof(u32), oid_rt_get_thermal_meter_hdl,
- OID_RT_PRO_GET_THERMAL_METER},/*25*/
- {sizeof(u32), oid_rt_get_power_mode_hdl,
- OID_RT_GET_POWER_MODE},/*26*/
- {sizeof(struct EFUSE_ACCESS_STRUCT),
- oid_rt_pro_efuse_hdl, OID_RT_PRO_EFUSE},/*27*/
- {EFUSE_MAP_MAX_SIZE, oid_rt_pro_efuse_map_hdl,
- OID_RT_PRO_EFUSE_MAP},/*28*/
- {sizeof(u32), oid_rt_get_efuse_max_size_hdl,
- OID_RT_GET_EFUSE_MAX_SIZE},/*29*/
- {sizeof(u32), oid_rt_get_efuse_current_size_hdl,
- OID_RT_GET_EFUSE_CURRENT_SIZE},/*30*/
- {sizeof(u32), oid_rt_pro_set_single_carrier_tx_hdl,
- OID_RT_PRO_SET_SINGLE_CARRIER_TX},/*31*/
- {sizeof(u32), oid_rt_pro_set_carrier_suppression_tx_hdl,
- OID_RT_PRO_SET_CARRIER_SUPPRESSION_TX},/*32*/
- {sizeof(u32), oid_rt_pro_set_single_tone_tx_hdl,
- OID_RT_PRO_SET_SINGLE_TONE_TX},/*33*/
- {sizeof(u32), oid_rt_pro_set_antenna_bb_hdl,
- OID_RT_PRO_SET_ANTENNA_BB},/*34*/
-};
-
-#else /* _RTL871X_MP_IOCTL_C_ */
-extern struct mp_ioctl_handler mp_ioctl_hdl[];
-#endif /* _RTL871X_MP_IOCTL_C_ */
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h b/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h
deleted file mode 100644
index bb9f83d58225..000000000000
--- a/drivers/staging/rtl8712/rtl871x_mp_phy_regdef.h
+++ /dev/null
@@ -1,1034 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*****************************************************************************
- * Copyright(c) 2008, RealTEK Technology Inc. All Right Reserved.
- *
- * Module: __INC_HAL8192SPHYREG_H
- *
- *
- * Note: 1. Define PMAC/BB register map
- * 2. Define RF register map
- * 3. PMAC/BB register bit mask.
- * 4. RF reg bit mask.
- * 5. Other BB/RF relative definition.
- *
- *
- * Export: Constants, macro, functions(API), global variables(None).
- *
- * Abbrev:
- *
- * History:
- * Data Who Remark
- * 08/07/2007 MHC 1. Porting from 9x series PHYCFG.h.
- * 2. Reorganize code architecture.
- * 09/25/2008 MH 1. Add RL6052 register definition
- *
- *****************************************************************************/
-#ifndef __RTL871X_MP_PHY_REGDEF_H
-#define __RTL871X_MP_PHY_REGDEF_H
-
-/*--------------------------Define Parameters-------------------------------*/
-
-/*============================================================
- * 8192S Register offset definition
- *============================================================
- *
- *
- * BB-PHY register PMAC 0x100 PHY 0x800 - 0xEFF
- * 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF
- * 2. 0x800/0x900/0xA00/0xC00/0xD00/0xE00
- * 3. RF register 0x00-2E
- * 4. Bit Mask for BB/RF register
- * 5. Other definition for BB/RF R/W
- *
- * 1. PMAC duplicate register due to connection: RF_Mode, TRxRN, NumOf L-STF
- * 1. Page1(0x100)
- */
-#define rPMAC_Reset 0x100
-#define rPMAC_TxStart 0x104
-#define rPMAC_TxLegacySIG 0x108
-#define rPMAC_TxHTSIG1 0x10c
-#define rPMAC_TxHTSIG2 0x110
-#define rPMAC_PHYDebug 0x114
-#define rPMAC_TxPacketNum 0x118
-#define rPMAC_TxIdle 0x11c
-#define rPMAC_TxMACHeader0 0x120
-#define rPMAC_TxMACHeader1 0x124
-#define rPMAC_TxMACHeader2 0x128
-#define rPMAC_TxMACHeader3 0x12c
-#define rPMAC_TxMACHeader4 0x130
-#define rPMAC_TxMACHeader5 0x134
-#define rPMAC_TxDataType 0x138
-#define rPMAC_TxRandomSeed 0x13c
-#define rPMAC_CCKPLCPPreamble 0x140
-#define rPMAC_CCKPLCPHeader 0x144
-#define rPMAC_CCKCRC16 0x148
-#define rPMAC_OFDMRxCRC32OK 0x170
-#define rPMAC_OFDMRxCRC32Er 0x174
-#define rPMAC_OFDMRxParityEr 0x178
-#define rPMAC_OFDMRxCRC8Er 0x17c
-#define rPMAC_CCKCRxRC16Er 0x180
-#define rPMAC_CCKCRxRC32Er 0x184
-#define rPMAC_CCKCRxRC32OK 0x188
-#define rPMAC_TxStatus 0x18c
-
-/*
- * 2. Page2(0x200)
- *
- * The following two definition are only used for USB interface.
- *#define RF_BB_CMD_ADDR 0x02c0 // RF/BB read/write command address.
- *#define RF_BB_CMD_DATA 0x02c4 // RF/BB read/write command data.
- *
- *
- * 3. Page8(0x800)
- */
-#define rFPGA0_RFMOD 0x800 /*RF mode & CCK TxSC RF
- * BW Setting??
- */
-#define rFPGA0_TxInfo 0x804 /* Status report?? */
-#define rFPGA0_PSDFunction 0x808
-#define rFPGA0_TxGainStage 0x80c /* Set TX PWR init gain? */
-#define rFPGA0_RFTiming1 0x810 /* Useless now */
-#define rFPGA0_RFTiming2 0x814
-#define rFPGA0_XA_HSSIParameter1 0x820 /* RF 3 wire register */
-#define rFPGA0_XA_HSSIParameter2 0x824
-#define rFPGA0_XB_HSSIParameter1 0x828
-#define rFPGA0_XB_HSSIParameter2 0x82c
-#define rFPGA0_XC_HSSIParameter1 0x830
-#define rFPGA0_XC_HSSIParameter2 0x834
-#define rFPGA0_XD_HSSIParameter1 0x838
-#define rFPGA0_XD_HSSIParameter2 0x83c
-#define rFPGA0_XA_LSSIParameter 0x840
-#define rFPGA0_XB_LSSIParameter 0x844
-#define rFPGA0_XC_LSSIParameter 0x848
-#define rFPGA0_XD_LSSIParameter 0x84c
-
-#define rFPGA0_RFWakeUpParameter 0x850 /* Useless now */
-#define rFPGA0_RFSleepUpParameter 0x854
-
-#define rFPGA0_XAB_SwitchControl 0x858 /* RF Channel switch */
-#define rFPGA0_XCD_SwitchControl 0x85c
-
-#define rFPGA0_XA_RFInterfaceOE 0x860 /* RF Channel switch */
-#define rFPGA0_XB_RFInterfaceOE 0x864
-#define rFPGA0_XC_RFInterfaceOE 0x868
-#define rFPGA0_XD_RFInterfaceOE 0x86c
-#define rFPGA0_XAB_RFInterfaceSW 0x870 /* RF Interface Software Ctrl */
-#define rFPGA0_XCD_RFInterfaceSW 0x874
-
-#define rFPGA0_XAB_RFParameter 0x878 /* RF Parameter */
-#define rFPGA0_XCD_RFParameter 0x87c
-
-#define rFPGA0_AnalogParameter1 0x880 /* Crystal cap setting
- * RF-R/W protection
- * for parameter4??
- */
-#define rFPGA0_AnalogParameter2 0x884
-#define rFPGA0_AnalogParameter3 0x888 /* Useless now */
-#define rFPGA0_AnalogParameter4 0x88c
-
-#define rFPGA0_XA_LSSIReadBack 0x8a0 /* Transceiver LSSI Readback */
-#define rFPGA0_XB_LSSIReadBack 0x8a4
-#define rFPGA0_XC_LSSIReadBack 0x8a8
-#define rFPGA0_XD_LSSIReadBack 0x8ac
-
-#define rFPGA0_PSDReport 0x8b4 /* Useless now */
-#define rFPGA0_XAB_RFInterfaceRB 0x8e0 /* Useless now */
-#define rFPGA0_XCD_RFInterfaceRB 0x8e4 /* Useless now */
-
-/*
- * 4. Page9(0x900)
- */
-#define rFPGA1_RFMOD 0x900 /* RF mode & OFDM TxSC */
-
-#define rFPGA1_TxBlock 0x904 /* Useless now */
-#define rFPGA1_DebugSelect 0x908 /* Useless now */
-#define rFPGA1_TxInfo 0x90c /* Useless now */
-
-/*
- * 5. PageA(0xA00)
- *
- * Set Control channel to upper or lower.
- * These settings are required only for 40MHz
- */
-#define rCCK0_System 0xa00
-
-#define rCCK0_AFESetting 0xa04 /* Disable init gain now */
-#define rCCK0_CCA 0xa08 /* Disable init gain now */
-
-#define rCCK0_RxAGC1 0xa0c
-/* AGC default value, saturation level
- * Antenna Diversity, RX AGC, LNA Threshold, RX LNA Threshold useless now.
- * Not the same as 90 series
- */
-#define rCCK0_RxAGC2 0xa10 /* AGC & DAGC */
-
-#define rCCK0_RxHP 0xa14
-
-#define rCCK0_DSPParameter1 0xa18 /* Timing recovery & Channel
- * estimation threshold
- */
-#define rCCK0_DSPParameter2 0xa1c /* SQ threshold */
-
-#define rCCK0_TxFilter1 0xa20
-#define rCCK0_TxFilter2 0xa24
-#define rCCK0_DebugPort 0xa28 /* debug port and Tx filter3 */
-#define rCCK0_FalseAlarmReport 0xa2c /* 0xa2d useless now 0xa30-a4f
- * channel report
- */
-#define rCCK0_TRSSIReport 0xa50
-#define rCCK0_RxReport 0xa54 /* 0xa57 */
-#define rCCK0_FACounterLower 0xa5c /* 0xa5b */
-#define rCCK0_FACounterUpper 0xa58 /* 0xa5c */
-
-/*
- * 6. PageC(0xC00)
- */
-#define rOFDM0_LSTF 0xc00
-#define rOFDM0_TRxPathEnable 0xc04
-#define rOFDM0_TRMuxPar 0xc08
-#define rOFDM0_TRSWIsolation 0xc0c
-
-/*RxIQ DC offset, Rx digital filter, DC notch filter */
-#define rOFDM0_XARxAFE 0xc10
-#define rOFDM0_XARxIQImbalance 0xc14 /* RxIQ imbalance matrix */
-#define rOFDM0_XBRxAFE 0xc18
-#define rOFDM0_XBRxIQImbalance 0xc1c
-#define rOFDM0_XCRxAFE 0xc20
-#define rOFDM0_XCRxIQImbalance 0xc24
-#define rOFDM0_XDRxAFE 0xc28
-#define rOFDM0_XDRxIQImbalance 0xc2c
-
-#define rOFDM0_RxDetector1 0xc30 /* PD,BW & SBD DM tune
- * init gain
- */
-#define rOFDM0_RxDetector2 0xc34 /* SBD & Fame Sync. */
-#define rOFDM0_RxDetector3 0xc38 /* Frame Sync. */
-#define rOFDM0_RxDetector4 0xc3c /* PD, SBD, Frame Sync &
- * Short-GI
- */
-
-#define rOFDM0_RxDSP 0xc40 /* Rx Sync Path */
-#define rOFDM0_CFOandDAGC 0xc44 /* CFO & DAGC */
-#define rOFDM0_CCADropThreshold 0xc48 /* CCA Drop threshold */
-#define rOFDM0_ECCAThreshold 0xc4c /* energy CCA */
-
-#define rOFDM0_XAAGCCore1 0xc50 /* DIG */
-#define rOFDM0_XAAGCCore2 0xc54
-#define rOFDM0_XBAGCCore1 0xc58
-#define rOFDM0_XBAGCCore2 0xc5c
-#define rOFDM0_XCAGCCore1 0xc60
-#define rOFDM0_XCAGCCore2 0xc64
-#define rOFDM0_XDAGCCore1 0xc68
-#define rOFDM0_XDAGCCore2 0xc6c
-#define rOFDM0_AGCParameter1 0xc70
-#define rOFDM0_AGCParameter2 0xc74
-#define rOFDM0_AGCRSSITable 0xc78
-#define rOFDM0_HTSTFAGC 0xc7c
-
-#define rOFDM0_XATxIQImbalance 0xc80 /* TX PWR TRACK and DIG */
-#define rOFDM0_XATxAFE 0xc84
-#define rOFDM0_XBTxIQImbalance 0xc88
-#define rOFDM0_XBTxAFE 0xc8c
-#define rOFDM0_XCTxIQImbalance 0xc90
-#define rOFDM0_XCTxAFE 0xc94
-#define rOFDM0_XDTxIQImbalance 0xc98
-#define rOFDM0_XDTxAFE 0xc9c
-
-#define rOFDM0_RxHPParameter 0xce0
-#define rOFDM0_TxPseudoNoiseWgt 0xce4
-#define rOFDM0_FrameSync 0xcf0
-#define rOFDM0_DFSReport 0xcf4
-#define rOFDM0_TxCoeff1 0xca4
-#define rOFDM0_TxCoeff2 0xca8
-#define rOFDM0_TxCoeff3 0xcac
-#define rOFDM0_TxCoeff4 0xcb0
-#define rOFDM0_TxCoeff5 0xcb4
-#define rOFDM0_TxCoeff6 0xcb8
-
-/*
- * 7. PageD(0xD00)
- */
-#define rOFDM1_LSTF 0xd00
-#define rOFDM1_TRxPathEnable 0xd04
-
-#define rOFDM1_CFO 0xd08 /* No setting now */
-#define rOFDM1_CSI1 0xd10
-#define rOFDM1_SBD 0xd14
-#define rOFDM1_CSI2 0xd18
-#define rOFDM1_CFOTracking 0xd2c
-#define rOFDM1_TRxMesaure1 0xd34
-#define rOFDM1_IntfDet 0xd3c
-#define rOFDM1_PseudoNoiseStateAB 0xd50
-#define rOFDM1_PseudoNoiseStateCD 0xd54
-#define rOFDM1_RxPseudoNoiseWgt 0xd58
-
-#define rOFDM_PHYCounter1 0xda0 /* cca, parity fail */
-#define rOFDM_PHYCounter2 0xda4 /* rate illegal, crc8 fail */
-#define rOFDM_PHYCounter3 0xda8 /* MCS not support */
-#define rOFDM_ShortCFOAB 0xdac /* No setting now */
-#define rOFDM_ShortCFOCD 0xdb0
-#define rOFDM_LongCFOAB 0xdb4
-#define rOFDM_LongCFOCD 0xdb8
-#define rOFDM_TailCFOAB 0xdbc
-#define rOFDM_TailCFOCD 0xdc0
-#define rOFDM_PWMeasure1 0xdc4
-#define rOFDM_PWMeasure2 0xdc8
-#define rOFDM_BWReport 0xdcc
-#define rOFDM_AGCReport 0xdd0
-#define rOFDM_RxSNR 0xdd4
-#define rOFDM_RxEVMCSI 0xdd8
-#define rOFDM_SIGReport 0xddc
-
-/*
- * 8. PageE(0xE00)
- */
-#define rTxAGC_Rate18_06 0xe00
-#define rTxAGC_Rate54_24 0xe04
-#define rTxAGC_CCK_Mcs32 0xe08
-#define rTxAGC_Mcs03_Mcs00 0xe10
-#define rTxAGC_Mcs07_Mcs04 0xe14
-#define rTxAGC_Mcs11_Mcs08 0xe18
-#define rTxAGC_Mcs15_Mcs12 0xe1c
-
-/* Analog- control in RX_WAIT_CCA : REG: EE0
- * [Analog- Power & Control Register]
- */
-#define rRx_Wait_CCCA 0xe70
-#define rAnapar_Ctrl_BB 0xee0
-
-/*
- * 7. RF Register 0x00-0x2E (RF 8256)
- * RF-0222D 0x00-3F
- *
- * Zebra1
- */
-#define rZebra1_HSSIEnable 0x0 /* Useless now */
-#define rZebra1_TRxEnable1 0x1
-#define rZebra1_TRxEnable2 0x2
-#define rZebra1_AGC 0x4
-#define rZebra1_ChargePump 0x5
-#define rZebra1_Channel 0x7 /* RF channel switch */
-#define rZebra1_TxGain 0x8 /* Useless now */
-#define rZebra1_TxLPF 0x9
-#define rZebra1_RxLPF 0xb
-#define rZebra1_RxHPFCorner 0xc
-
-/* Zebra4 */
-#define rGlobalCtrl 0 /* Useless now */
-#define rRTL8256_TxLPF 19
-#define rRTL8256_RxLPF 11
-
-/* RTL8258 */
-#define rRTL8258_TxLPF 0x11 /* Useless now */
-#define rRTL8258_RxLPF 0x13
-#define rRTL8258_RSSILPF 0xa
-
-/* RL6052 Register definition */
-#define RF_AC 0x00
-#define RF_IQADJ_G1 0x01
-#define RF_IQADJ_G2 0x02
-#define RF_POW_TRSW 0x05
-
-#define RF_GAIN_RX 0x06
-#define RF_GAIN_TX 0x07
-
-#define RF_TXM_IDAC 0x08
-#define RF_BS_IQGEN 0x0F
-
-#define RF_MODE1 0x10
-#define RF_MODE2 0x11
-
-#define RF_RX_AGC_HP 0x12
-#define RF_TX_AGC 0x13
-#define RF_BIAS 0x14
-#define RF_IPA 0x15
-#define RF_POW_ABILITY 0x17
-#define RF_MODE_AG 0x18
-#define rRfChannel 0x18 /* RF channel and BW switch */
-#define RF_CHNLBW 0x18 /* RF channel and BW switch */
-#define RF_TOP 0x19
-#define RF_RX_G1 0x1A
-#define RF_RX_G2 0x1B
-#define RF_RX_BB2 0x1C
-#define RF_RX_BB1 0x1D
-
-#define RF_RCK1 0x1E
-#define RF_RCK2 0x1F
-
-#define RF_TX_G1 0x20
-#define RF_TX_G2 0x21
-#define RF_TX_G3 0x22
-
-#define RF_TX_BB1 0x23
-#define RF_T_METER 0x24
-
-#define RF_SYN_G1 0x25 /* RF TX Power control */
-#define RF_SYN_G2 0x26 /* RF TX Power control */
-#define RF_SYN_G3 0x27 /* RF TX Power control */
-#define RF_SYN_G4 0x28 /* RF TX Power control */
-#define RF_SYN_G5 0x29 /* RF TX Power control */
-#define RF_SYN_G6 0x2A /* RF TX Power control */
-#define RF_SYN_G7 0x2B /* RF TX Power control */
-#define RF_SYN_G8 0x2C /* RF TX Power control */
-
-#define RF_RCK_OS 0x30 /* RF TX PA control */
-
-#define RF_TXPA_G1 0x31 /* RF TX PA control */
-#define RF_TXPA_G2 0x32 /* RF TX PA control */
-#define RF_TXPA_G3 0x33 /* RF TX PA control */
-
-/*
- * Bit Mask
- *
- * 1. Page1(0x100)
- */
-#define bBBResetB 0x100 /* Useless now? */
-#define bGlobalResetB 0x200
-#define bOFDMTxStart 0x4
-#define bCCKTxStart 0x8
-#define bCRC32Debug 0x100
-#define bPMACLoopback 0x10
-#define bTxLSIG 0xffffff
-#define bOFDMTxRate 0xf
-#define bOFDMTxReserved 0x10
-#define bOFDMTxLength 0x1ffe0
-#define bOFDMTxParity 0x20000
-#define bTxHTSIG1 0xffffff
-#define bTxHTMCSRate 0x7f
-#define bTxHTBW 0x80
-#define bTxHTLength 0xffff00
-#define bTxHTSIG2 0xffffff
-#define bTxHTSmoothing 0x1
-#define bTxHTSounding 0x2
-#define bTxHTReserved 0x4
-#define bTxHTAggreation 0x8
-#define bTxHTSTBC 0x30
-#define bTxHTAdvanceCoding 0x40
-#define bTxHTShortGI 0x80
-#define bTxHTNumberHT_LTF 0x300
-#define bTxHTCRC8 0x3fc00
-#define bCounterReset 0x10000
-#define bNumOfOFDMTx 0xffff
-#define bNumOfCCKTx 0xffff0000
-#define bTxIdleInterval 0xffff
-#define bOFDMService 0xffff0000
-#define bTxMACHeader 0xffffffff
-#define bTxDataInit 0xff
-#define bTxHTMode 0x100
-#define bTxDataType 0x30000
-#define bTxRandomSeed 0xffffffff
-#define bCCKTxPreamble 0x1
-#define bCCKTxSFD 0xffff0000
-#define bCCKTxSIG 0xff
-#define bCCKTxService 0xff00
-#define bCCKLengthExt 0x8000
-#define bCCKTxLength 0xffff0000
-#define bCCKTxCRC16 0xffff
-#define bCCKTxStatus 0x1
-#define bOFDMTxStatus 0x2
-#define IS_BB_REG_OFFSET_92S(_Offset) ((_Offset >= 0x800) && \
- (_Offset <= 0xfff))
-
-/* 2. Page8(0x800) */
-#define bRFMOD 0x1 /* Reg 0x800 rFPGA0_RFMOD */
-#define bJapanMode 0x2
-#define bCCKTxSC 0x30
-#define bCCKEn 0x1000000
-#define bOFDMEn 0x2000000
-
-#define bOFDMRxADCPhase 0x10000 /* Useless now */
-#define bOFDMTxDACPhase 0x40000
-#define bXATxAGC 0x3f
-#define bXBTxAGC 0xf00 /* Reg 80c rFPGA0_TxGainStage */
-#define bXCTxAGC 0xf000
-#define bXDTxAGC 0xf0000
-
-#define bPAStart 0xf0000000 /* Useless now */
-#define bTRStart 0x00f00000
-#define bRFStart 0x0000f000
-#define bBBStart 0x000000f0
-#define bBBCCKStart 0x0000000f
-#define bPAEnd 0xf /* Reg0x814 */
-#define bTREnd 0x0f000000
-#define bRFEnd 0x000f0000
-#define bCCAMask 0x000000f0 /* T2R */
-#define bR2RCCAMask 0x00000f00
-#define bHSSI_R2TDelay 0xf8000000
-#define bHSSI_T2RDelay 0xf80000
-#define bContTxHSSI 0x400 /* change gain at continue Tx */
-#define bIGFromCCK 0x200
-#define bAGCAddress 0x3f
-#define bRxHPTx 0x7000
-#define bRxHPT2R 0x38000
-#define bRxHPCCKIni 0xc0000
-#define bAGCTxCode 0xc00000
-#define bAGCRxCode 0x300000
-#define b3WireDataLength 0x800 /* Reg 0x820~84f rFPGA0_XA_HSSIParm1 */
-#define b3WireAddressLength 0x400
-#define b3WireRFPowerDown 0x1 /* Useless now */
-#define b5GPAPEPolarity 0x40000000
-#define b2GPAPEPolarity 0x80000000
-#define bRFSW_TxDefaultAnt 0x3
-#define bRFSW_TxOptionAnt 0x30
-#define bRFSW_RxDefaultAnt 0x300
-#define bRFSW_RxOptionAnt 0x3000
-#define bRFSI_3WireData 0x1
-#define bRFSI_3WireClock 0x2
-#define bRFSI_3WireLoad 0x4
-#define bRFSI_3WireRW 0x8
-#define bRFSI_3Wire 0xf
-#define bRFSI_RFENV 0x10 /* Reg 0x870 rFPGA0_XAB_RFInterfaceSW */
-#define bRFSI_TRSW 0x20 /* Useless now */
-#define bRFSI_TRSWB 0x40
-#define bRFSI_ANTSW 0x100
-#define bRFSI_ANTSWB 0x200
-#define bRFSI_PAPE 0x400
-#define bRFSI_PAPE5G 0x800
-#define bBandSelect 0x1
-#define bHTSIG2_GI 0x80
-#define bHTSIG2_Smoothing 0x01
-#define bHTSIG2_Sounding 0x02
-#define bHTSIG2_Aggreaton 0x08
-#define bHTSIG2_STBC 0x30
-#define bHTSIG2_AdvCoding 0x40
-#define bHTSIG2_NumOfHTLTF 0x300
-#define bHTSIG2_CRC8 0x3fc
-#define bHTSIG1_MCS 0x7f
-#define bHTSIG1_BandWidth 0x80
-#define bHTSIG1_HTLength 0xffff
-#define bLSIG_Rate 0xf
-#define bLSIG_Reserved 0x10
-#define bLSIG_Length 0x1fffe
-#define bLSIG_Parity 0x20
-#define bCCKRxPhase 0x4
-#define bLSSIReadAddress 0x7f800000 /* T65 RF */
-#define bLSSIReadEdge 0x80000000 /* LSSI "Read" edge signal */
-#define bLSSIReadBackData 0xfffff /* T65 RF */
-#define bLSSIReadOKFlag 0x1000 /* Useless now */
-#define bCCKSampleRate 0x8 /*0: 44MHz, 1:88MHz*/
-#define bRegulator0Standby 0x1
-#define bRegulatorPLLStandby 0x2
-#define bRegulator1Standby 0x4
-#define bPLLPowerUp 0x8
-#define bDPLLPowerUp 0x10
-#define bDA10PowerUp 0x20
-#define bAD7PowerUp 0x200
-#define bDA6PowerUp 0x2000
-#define bXtalPowerUp 0x4000
-#define b40MDClkPowerUP 0x8000
-#define bDA6DebugMode 0x20000
-#define bDA6Swing 0x380000
-
-/* Reg 0x880 rFPGA0_AnalogParameter1 20/40 CCK support switch 40/80 BB MHZ */
-#define bADClkPhase 0x4000000
-
-#define b80MClkDelay 0x18000000 /* Useless */
-#define bAFEWatchDogEnable 0x20000000
-
-/* Reg 0x884 rFPGA0_AnalogParameter2 Crystal cap */
-#define bXtalCap01 0xc0000000
-#define bXtalCap23 0x3
-#define bXtalCap92x 0x0f000000
-#define bXtalCap 0x0f000000
-#define bIntDifClkEnable 0x400 /* Useless */
-#define bExtSigClkEnable 0x800
-#define bBandgapMbiasPowerUp 0x10000
-#define bAD11SHGain 0xc0000
-#define bAD11InputRange 0x700000
-#define bAD11OPCurrent 0x3800000
-#define bIPathLoopback 0x4000000
-#define bQPathLoopback 0x8000000
-#define bAFELoopback 0x10000000
-#define bDA10Swing 0x7e0
-#define bDA10Reverse 0x800
-#define bDAClkSource 0x1000
-#define bAD7InputRange 0x6000
-#define bAD7Gain 0x38000
-#define bAD7OutputCMMode 0x40000
-#define bAD7InputCMMode 0x380000
-#define bAD7Current 0xc00000
-#define bRegulatorAdjust 0x7000000
-#define bAD11PowerUpAtTx 0x1
-#define bDA10PSAtTx 0x10
-#define bAD11PowerUpAtRx 0x100
-#define bDA10PSAtRx 0x1000
-#define bCCKRxAGCFormat 0x200
-#define bPSDFFTSamplepPoint 0xc000
-#define bPSDAverageNum 0x3000
-#define bIQPathControl 0xc00
-#define bPSDFreq 0x3ff
-#define bPSDAntennaPath 0x30
-#define bPSDIQSwitch 0x40
-#define bPSDRxTrigger 0x400000
-#define bPSDTxTrigger 0x80000000
-#define bPSDSineToneScale 0x7f000000
-#define bPSDReport 0xffff
-
-/* 3. Page9(0x900) */
-#define bOFDMTxSC 0x30000000 /* Useless */
-#define bCCKTxOn 0x1
-#define bOFDMTxOn 0x2
-#define bDebugPage 0xfff /* reset debug page and HWord, LWord */
-#define bDebugItem 0xff /* reset debug page and LWord */
-#define bAntL 0x10
-#define bAntNonHT 0x100
-#define bAntHT1 0x1000
-#define bAntHT2 0x10000
-#define bAntHT1S1 0x100000
-#define bAntNonHTS1 0x1000000
-
-/* 4. PageA(0xA00) */
-#define bCCKBBMode 0x3 /* Useless */
-#define bCCKTxPowerSaving 0x80
-#define bCCKRxPowerSaving 0x40
-
-#define bCCKSideBand 0x10 /* Reg 0xa00 rCCK0_System 20/40 switch*/
-#define bCCKScramble 0x8 /* Useless */
-#define bCCKAntDiversity 0x8000
-#define bCCKCarrierRecovery 0x4000
-#define bCCKTxRate 0x3000
-#define bCCKDCCancel 0x0800
-#define bCCKISICancel 0x0400
-#define bCCKMatchFilter 0x0200
-#define bCCKEqualizer 0x0100
-#define bCCKPreambleDetect 0x800000
-#define bCCKFastFalseCCA 0x400000
-#define bCCKChEstStart 0x300000
-#define bCCKCCACount 0x080000
-#define bCCKcs_lim 0x070000
-#define bCCKBistMode 0x80000000
-#define bCCKCCAMask 0x40000000
-#define bCCKTxDACPhase 0x4
-#define bCCKRxADCPhase 0x20000000 /* r_rx_clk */
-#define bCCKr_cp_mode0 0x0100
-#define bCCKTxDCOffset 0xf0
-#define bCCKRxDCOffset 0xf
-#define bCCKCCAMode 0xc000
-#define bCCKFalseCS_lim 0x3f00
-#define bCCKCS_ratio 0xc00000
-#define bCCKCorgBit_sel 0x300000
-#define bCCKPD_lim 0x0f0000
-#define bCCKNewCCA 0x80000000
-#define bCCKRxHPofIG 0x8000
-#define bCCKRxIG 0x7f00
-#define bCCKLNAPolarity 0x800000
-#define bCCKRx1stGain 0x7f0000
-#define bCCKRFExtend 0x20000000 /* CCK Rx initial gain polarity */
-#define bCCKRxAGCSatLevel 0x1f000000
-#define bCCKRxAGCSatCount 0xe0
-#define bCCKRxRFSettle 0x1f /* AGCsamp_dly */
-#define bCCKFixedRxAGC 0x8000
-#define bCCKAntennaPolarity 0x2000
-#define bCCKTxFilterType 0x0c00
-#define bCCKRxAGCReportType 0x0300
-#define bCCKRxDAGCEn 0x80000000
-#define bCCKRxDAGCPeriod 0x20000000
-#define bCCKRxDAGCSatLevel 0x1f000000
-#define bCCKTimingRecovery 0x800000
-#define bCCKTxC0 0x3f0000
-#define bCCKTxC1 0x3f000000
-#define bCCKTxC2 0x3f
-#define bCCKTxC3 0x3f00
-#define bCCKTxC4 0x3f0000
-#define bCCKTxC5 0x3f000000
-#define bCCKTxC6 0x3f
-#define bCCKTxC7 0x3f00
-#define bCCKDebugPort 0xff0000
-#define bCCKDACDebug 0x0f000000
-#define bCCKFalseAlarmEnable 0x8000
-#define bCCKFalseAlarmRead 0x4000
-#define bCCKTRSSI 0x7f
-#define bCCKRxAGCReport 0xfe
-#define bCCKRxReport_AntSel 0x80000000
-#define bCCKRxReport_MFOff 0x40000000
-#define bCCKRxRxReport_SQLoss 0x20000000
-#define bCCKRxReport_Pktloss 0x10000000
-#define bCCKRxReport_Lockedbit 0x08000000
-#define bCCKRxReport_RateError 0x04000000
-#define bCCKRxReport_RxRate 0x03000000
-#define bCCKRxFACounterLower 0xff
-#define bCCKRxFACounterUpper 0xff000000
-#define bCCKRxHPAGCStart 0xe000
-#define bCCKRxHPAGCFinal 0x1c00
-#define bCCKRxFalseAlarmEnable 0x8000
-#define bCCKFACounterFreeze 0x4000
-#define bCCKTxPathSel 0x10000000
-#define bCCKDefaultRxPath 0xc000000
-#define bCCKOptionRxPath 0x3000000
-
-/* 5. PageC(0xC00) */
-#define bNumOfSTF 0x3 /* Useless */
-#define bShift_L 0xc0
-#define bGI_TH 0xc
-#define bRxPathA 0x1
-#define bRxPathB 0x2
-#define bRxPathC 0x4
-#define bRxPathD 0x8
-#define bTxPathA 0x1
-#define bTxPathB 0x2
-#define bTxPathC 0x4
-#define bTxPathD 0x8
-#define bTRSSIFreq 0x200
-#define bADCBackoff 0x3000
-#define bDFIRBackoff 0xc000
-#define bTRSSILatchPhase 0x10000
-#define bRxIDCOffset 0xff
-#define bRxQDCOffset 0xff00
-#define bRxDFIRMode 0x1800000
-#define bRxDCNFType 0xe000000
-#define bRXIQImb_A 0x3ff
-#define bRXIQImb_B 0xfc00
-#define bRXIQImb_C 0x3f0000
-#define bRXIQImb_D 0xffc00000
-#define bDC_dc_Notch 0x60000
-#define bRxNBINotch 0x1f000000
-#define bPD_TH 0xf
-#define bPD_TH_Opt2 0xc000
-#define bPWED_TH 0x700
-#define bIfMF_Win_L 0x800
-#define bPD_Option 0x1000
-#define bMF_Win_L 0xe000
-#define bBW_Search_L 0x30000
-#define bwin_enh_L 0xc0000
-#define bBW_TH 0x700000
-#define bED_TH2 0x3800000
-#define bBW_option 0x4000000
-#define bRatio_TH 0x18000000
-#define bWindow_L 0xe0000000
-#define bSBD_Option 0x1
-#define bFrame_TH 0x1c
-#define bFS_Option 0x60
-#define bDC_Slope_check 0x80
-#define bFGuard_Counter_DC_L 0xe00
-#define bFrame_Weight_Short 0x7000
-#define bSub_Tune 0xe00000
-#define bFrame_DC_Length 0xe000000
-#define bSBD_start_offset 0x30000000
-#define bFrame_TH_2 0x7
-#define bFrame_GI2_TH 0x38
-#define bGI2_Sync_en 0x40
-#define bSarch_Short_Early 0x300
-#define bSarch_Short_Late 0xc00
-#define bSarch_GI2_Late 0x70000
-#define bCFOAntSum 0x1
-#define bCFOAcc 0x2
-#define bCFOStartOffset 0xc
-#define bCFOLookBack 0x70
-#define bCFOSumWeight 0x80
-#define bDAGCEnable 0x10000
-#define bTXIQImb_A 0x3ff
-#define bTXIQImb_B 0xfc00
-#define bTXIQImb_C 0x3f0000
-#define bTXIQImb_D 0xffc00000
-#define bTxIDCOffset 0xff
-#define bTxQDCOffset 0xff00
-#define bTxDFIRMode 0x10000
-#define bTxPesudoNoiseOn 0x4000000
-#define bTxPesudoNoise_A 0xff
-#define bTxPesudoNoise_B 0xff00
-#define bTxPesudoNoise_C 0xff0000
-#define bTxPesudoNoise_D 0xff000000
-#define bCCADropOption 0x20000
-#define bCCADropThres 0xfff00000
-#define bEDCCA_H 0xf
-#define bEDCCA_L 0xf0
-#define bLambda_ED 0x300
-#define bRxInitialGain 0x7f
-#define bRxAntDivEn 0x80
-#define bRxAGCAddressForLNA 0x7f00
-#define bRxHighPowerFlow 0x8000
-#define bRxAGCFreezeThres 0xc0000
-#define bRxFreezeStep_AGC1 0x300000
-#define bRxFreezeStep_AGC2 0xc00000
-#define bRxFreezeStep_AGC3 0x3000000
-#define bRxFreezeStep_AGC0 0xc000000
-#define bRxRssi_Cmp_En 0x10000000
-#define bRxQuickAGCEn 0x20000000
-#define bRxAGCFreezeThresMode 0x40000000
-#define bRxOverFlowCheckType 0x80000000
-#define bRxAGCShift 0x7f
-#define bTRSW_Tri_Only 0x80
-#define bPowerThres 0x300
-#define bRxAGCEn 0x1
-#define bRxAGCTogetherEn 0x2
-#define bRxAGCMin 0x4
-#define bRxHP_Ini 0x7
-#define bRxHP_TRLNA 0x70
-#define bRxHP_RSSI 0x700
-#define bRxHP_BBP1 0x7000
-#define bRxHP_BBP2 0x70000
-#define bRxHP_BBP3 0x700000
-#define bRSSI_H 0x7f0000 /* the threshold for high power */
-#define bRSSI_Gen 0x7f000000 /* the threshold for ant divers */
-#define bRxSettle_TRSW 0x7
-#define bRxSettle_LNA 0x38
-#define bRxSettle_RSSI 0x1c0
-#define bRxSettle_BBP 0xe00
-#define bRxSettle_RxHP 0x7000
-#define bRxSettle_AntSW_RSSI 0x38000
-#define bRxSettle_AntSW 0xc0000
-#define bRxProcessTime_DAGC 0x300000
-#define bRxSettle_HSSI 0x400000
-#define bRxProcessTime_BBPPW 0x800000
-#define bRxAntennaPowerShift 0x3000000
-#define bRSSITableSelect 0xc000000
-#define bRxHP_Final 0x7000000
-#define bRxHTSettle_BBP 0x7
-#define bRxHTSettle_HSSI 0x8
-#define bRxHTSettle_RxHP 0x70
-#define bRxHTSettle_BBPPW 0x80
-#define bRxHTSettle_Idle 0x300
-#define bRxHTSettle_Reserved 0x1c00
-#define bRxHTRxHPEn 0x8000
-#define bRxHTAGCFreezeThres 0x30000
-#define bRxHTAGCTogetherEn 0x40000
-#define bRxHTAGCMin 0x80000
-#define bRxHTAGCEn 0x100000
-#define bRxHTDAGCEn 0x200000
-#define bRxHTRxHP_BBP 0x1c00000
-#define bRxHTRxHP_Final 0xe0000000
-#define bRxPWRatioTH 0x3
-#define bRxPWRatioEn 0x4
-#define bRxMFHold 0x3800
-#define bRxPD_Delay_TH1 0x38
-#define bRxPD_Delay_TH2 0x1c0
-#define bRxPD_DC_COUNT_MAX 0x600
-#define bRxPD_Delay_TH 0x8000
-#define bRxProcess_Delay 0xf0000
-#define bRxSearchrange_GI2_Early 0x700000
-#define bRxFrame_Guard_Counter_L 0x3800000
-#define bRxSGI_Guard_L 0xc000000
-#define bRxSGI_Search_L 0x30000000
-#define bRxSGI_TH 0xc0000000
-#define bDFSCnt0 0xff
-#define bDFSCnt1 0xff00
-#define bDFSFlag 0xf0000
-#define bMFWeightSum 0x300000
-#define bMinIdxTH 0x7f000000
-#define bDAFormat 0x40000
-#define bTxChEmuEnable 0x01000000
-#define bTRSWIsolation_A 0x7f
-#define bTRSWIsolation_B 0x7f00
-#define bTRSWIsolation_C 0x7f0000
-#define bTRSWIsolation_D 0x7f000000
-#define bExtLNAGain 0x7c00
-
-/* 6. PageE(0xE00) */
-#define bSTBCEn 0x4 /* Useless */
-#define bAntennaMapping 0x10
-#define bNss 0x20
-#define bCFOAntSumD 0x200
-#define bPHYCounterReset 0x8000000
-#define bCFOReportGet 0x4000000
-#define bOFDMContinueTx 0x10000000
-#define bOFDMSingleCarrier 0x20000000
-#define bOFDMSingleTone 0x40000000
-#define bHTDetect 0x100
-#define bCFOEn 0x10000
-#define bCFOValue 0xfff00000
-#define bSigTone_Re 0x3f
-#define bSigTone_Im 0x7f00
-#define bCounter_CCA 0xffff
-#define bCounter_ParityFail 0xffff0000
-#define bCounter_RateIllegal 0xffff
-#define bCounter_CRC8Fail 0xffff0000
-#define bCounter_MCSNoSupport 0xffff
-#define bCounter_FastSync 0xffff
-#define bShortCFO 0xfff
-#define bShortCFOTLength 12 /* total */
-#define bShortCFOFLength 11 /* fraction */
-#define bLongCFO 0x7ff
-#define bLongCFOTLength 11
-#define bLongCFOFLength 11
-#define bTailCFO 0x1fff
-#define bTailCFOTLength 13
-#define bTailCFOFLength 12
-#define bmax_en_pwdB 0xffff
-#define bCC_power_dB 0xffff0000
-#define bnoise_pwdB 0xffff
-#define bPowerMeasTLength 10
-#define bPowerMeasFLength 3
-#define bRx_HT_BW 0x1
-#define bRxSC 0x6
-#define bRx_HT 0x8
-#define bNB_intf_det_on 0x1
-#define bIntf_win_len_cfg 0x30
-#define bNB_Intf_TH_cfg 0x1c0
-#define bRFGain 0x3f
-#define bTableSel 0x40
-#define bTRSW 0x80
-#define bRxSNR_A 0xff
-#define bRxSNR_B 0xff00
-#define bRxSNR_C 0xff0000
-#define bRxSNR_D 0xff000000
-#define bSNREVMTLength 8
-#define bSNREVMFLength 1
-#define bCSI1st 0xff
-#define bCSI2nd 0xff00
-#define bRxEVM1st 0xff0000
-#define bRxEVM2nd 0xff000000
-#define bSIGEVM 0xff
-#define bPWDB 0xff00
-#define bSGIEN 0x10000
-
-#define bSFactorQAM1 0xf /* Useless */
-#define bSFactorQAM2 0xf0
-#define bSFactorQAM3 0xf00
-#define bSFactorQAM4 0xf000
-#define bSFactorQAM5 0xf0000
-#define bSFactorQAM6 0xf0000
-#define bSFactorQAM7 0xf00000
-#define bSFactorQAM8 0xf000000
-#define bSFactorQAM9 0xf0000000
-#define bCSIScheme 0x100000
-
-#define bNoiseLvlTopSet 0x3 /* Useless */
-#define bChSmooth 0x4
-#define bChSmoothCfg1 0x38
-#define bChSmoothCfg2 0x1c0
-#define bChSmoothCfg3 0xe00
-#define bChSmoothCfg4 0x7000
-#define bMRCMode 0x800000
-#define bTHEVMCfg 0x7000000
-
-#define bLoopFitType 0x1 /* Useless */
-#define bUpdCFO 0x40
-#define bUpdCFOOffData 0x80
-#define bAdvUpdCFO 0x100
-#define bAdvTimeCtrl 0x800
-#define bUpdClko 0x1000
-#define bFC 0x6000
-#define bTrackingMode 0x8000
-#define bPhCmpEnable 0x10000
-#define bUpdClkoLTF 0x20000
-#define bComChCFO 0x40000
-#define bCSIEstiMode 0x80000
-#define bAdvUpdEqz 0x100000
-#define bUChCfg 0x7000000
-#define bUpdEqz 0x8000000
-
-#define bTxAGCRate18_06 0x7f7f7f7f /* Useless */
-#define bTxAGCRate54_24 0x7f7f7f7f
-#define bTxAGCRateMCS32 0x7f
-#define bTxAGCRateCCK 0x7f00
-#define bTxAGCRateMCS3_MCS0 0x7f7f7f7f
-#define bTxAGCRateMCS7_MCS4 0x7f7f7f7f
-#define bTxAGCRateMCS11_MCS8 0x7f7f7f7f
-#define bTxAGCRateMCS15_MCS12 0x7f7f7f7f
-
-/* Rx Pseduo noise */
-#define bRxPesudoNoiseOn 0x20000000 /* Useless */
-#define bRxPesudoNoise_A 0xff
-#define bRxPesudoNoise_B 0xff00
-#define bRxPesudoNoise_C 0xff0000
-#define bRxPesudoNoise_D 0xff000000
-#define bPesudoNoiseState_A 0xffff
-#define bPesudoNoiseState_B 0xffff0000
-#define bPesudoNoiseState_C 0xffff
-#define bPesudoNoiseState_D 0xffff0000
-
-/* 7. RF Register
- * Zebra1
- */
-#define bZebra1_HSSIEnable 0x8 /* Useless */
-#define bZebra1_TRxControl 0xc00
-#define bZebra1_TRxGainSetting 0x07f
-#define bZebra1_RxCorner 0xc00
-#define bZebra1_TxChargePump 0x38
-#define bZebra1_RxChargePump 0x7
-#define bZebra1_ChannelNum 0xf80
-#define bZebra1_TxLPFBW 0x400
-#define bZebra1_RxLPFBW 0x600
-
-/*Zebra4 */
-#define bRTL8256RegModeCtrl1 0x100 /* Useless */
-#define bRTL8256RegModeCtrl0 0x40
-#define bRTL8256_TxLPFBW 0x18
-#define bRTL8256_RxLPFBW 0x600
-
-/* RTL8258 */
-#define bRTL8258_TxLPFBW 0xc /* Useless */
-#define bRTL8258_RxLPFBW 0xc00
-#define bRTL8258_RSSILPFBW 0xc0
-
-/*
- * Other Definition
- */
-
-/* byte endable for sb_write */
-#define bByte0 0x1 /* Useless */
-#define bByte1 0x2
-#define bByte2 0x4
-#define bByte3 0x8
-#define bWord0 0x3
-#define bWord1 0xc
-#define bDWord 0xf
-
-/* for PutRegsetting & GetRegSetting BitMask */
-#define bMaskByte0 0xff /* Reg 0xc50 rOFDM0_XAAGCCore~0xC6f */
-#define bMaskByte1 0xff00
-#define bMaskByte2 0xff0000
-#define bMaskByte3 0xff000000
-#define bMaskHWord 0xffff0000
-#define bMaskLWord 0x0000ffff
-#define bMaskDWord 0xffffffff
-
-/* for PutRFRegsetting & GetRFRegSetting BitMask */
-#define bRFRegOffsetMask 0xfffff
-#define bEnable 0x1 /* Useless */
-#define bDisable 0x0
-
-#define LeftAntenna 0x0 /* Useless */
-#define RightAntenna 0x1
-
-#define tCheckTxStatus 500 /* 500ms Useless */
-#define tUpdateRxCounter 100 /* 100ms */
-
-#define rateCCK 0 /* Useless */
-#define rateOFDM 1
-#define rateHT 2
-
-/* define Register-End */
-#define bPMAC_End 0x1ff /* Useless */
-#define bFPGAPHY0_End 0x8ff
-#define bFPGAPHY1_End 0x9ff
-#define bCCKPHY0_End 0xaff
-#define bOFDMPHY0_End 0xcff
-#define bOFDMPHY1_End 0xdff
-
-#define bPMACControl 0x0 /* Useless */
-#define bWMACControl 0x1
-#define bWNICControl 0x2
-
-#define ANTENNA_A 0x1 /* Useless */
-#define ANTENNA_B 0x2
-#define ANTENNA_AB 0x3 /* ANTENNA_A |ANTENNA_B */
-
-#define ANTENNA_C 0x4
-#define ANTENNA_D 0x8
-
-/* accept all physical address */
-#define RCR_AAP BIT(0)
-#define RCR_APM BIT(1) /* accept physical match */
-#define RCR_AM BIT(2) /* accept multicast */
-#define RCR_AB BIT(3) /* accept broadcast */
-#define RCR_ACRC32 BIT(5) /* accept error packet */
-#define RCR_9356SEL BIT(6)
-#define RCR_AICV BIT(12) /* Accept ICV error packet */
-#define RCR_RXFTH0 (BIT(13)|BIT(14)|BIT(15)) /* Rx FIFO threshold */
-#define RCR_ADF BIT(18) /* Accept Data(frame type) frame */
-#define RCR_ACF BIT(19) /* Accept control frame */
-#define RCR_AMF BIT(20) /* Accept management frame */
-#define RCR_ADD3 BIT(21)
-#define RCR_APWRMGT BIT(22) /* Accept power management packet */
-#define RCR_CBSSID BIT(23) /* Accept BSSID match packet */
-#define RCR_ENMARP BIT(28) /* enable mac auto reset phy */
-#define RCR_EnCS1 BIT(29) /* enable carrier sense method 1 */
-#define RCR_EnCS2 BIT(30) /* enable carrier sense method 2 */
-/* Rx Early mode is performed for packet size greater than 1536 */
-#define RCR_OnlyErlPkt BIT(31)
-
-/*--------------------------Define Parameters-------------------------------*/
-
-#endif /*__INC_HAL8192SPHYREG_H */
-
diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.c b/drivers/staging/rtl8712/rtl871x_pwrctrl.c
deleted file mode 100644
index cd6d9ff0bebc..000000000000
--- a/drivers/staging/rtl8712/rtl871x_pwrctrl.c
+++ /dev/null
@@ -1,234 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_pwrctrl.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_PWRCTRL_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-
-#define RTL8712_SDIO_LOCAL_BASE 0X10100000
-#define SDIO_HCPWM (RTL8712_SDIO_LOCAL_BASE + 0x0081)
-
-void r8712_set_rpwm(struct _adapter *padapter, u8 val8)
-{
- u8 rpwm;
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-
- if (pwrpriv->rpwm == val8) {
- if (pwrpriv->rpwm_retry == 0)
- return;
- }
- if (padapter->driver_stopped || padapter->surprise_removed)
- return;
- rpwm = val8 | pwrpriv->tog;
- switch (val8) {
- case PS_STATE_S1:
- pwrpriv->cpwm = val8;
- break;
- case PS_STATE_S2:/* only for USB normal powersave mode use,
- * temp mark some code.
- */
- case PS_STATE_S3:
- case PS_STATE_S4:
- pwrpriv->cpwm = val8;
- break;
- default:
- break;
- }
- pwrpriv->rpwm_retry = 0;
- pwrpriv->rpwm = val8;
- r8712_write8(padapter, 0x1025FE58, rpwm);
- pwrpriv->tog += 0x80;
-}
-
-void r8712_set_ps_mode(struct _adapter *padapter, uint ps_mode, uint smart_ps)
-{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-
- if (ps_mode > PM_Card_Disable)
- return;
- /* if driver is in active state, we dont need set smart_ps.*/
- if (ps_mode == PS_MODE_ACTIVE)
- smart_ps = 0;
- if ((pwrpriv->pwr_mode != ps_mode) || (pwrpriv->smart_ps != smart_ps)) {
- if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
- pwrpriv->bSleep = true;
- else
- pwrpriv->bSleep = false;
- pwrpriv->pwr_mode = ps_mode;
- pwrpriv->smart_ps = smart_ps;
- schedule_work(&pwrpriv->SetPSModeWorkItem);
- }
-}
-
-/*
- * Caller:ISR handler...
- *
- * This will be called when CPWM interrupt is up.
- *
- * using to update cpwn of drv; and drv will make a decision to up or
- * down pwr level
- */
-void r8712_cpwm_int_hdl(struct _adapter *padapter,
- struct reportpwrstate_parm *preportpwrstate)
-{
- struct pwrctrl_priv *pwrpriv = &(padapter->pwrctrlpriv);
- struct cmd_priv *pcmdpriv = &(padapter->cmdpriv);
-
- if (pwrpriv->cpwm_tog == ((preportpwrstate->state) & 0x80))
- return;
- del_timer(&padapter->pwrctrlpriv.rpwm_check_timer);
- mutex_lock(&pwrpriv->mutex_lock);
- pwrpriv->cpwm = (preportpwrstate->state) & 0xf;
- if (pwrpriv->cpwm >= PS_STATE_S2) {
- if (pwrpriv->alives & CMD_ALIVE)
- complete(&(pcmdpriv->cmd_queue_comp));
- }
- pwrpriv->cpwm_tog = (preportpwrstate->state) & 0x80;
- mutex_unlock(&pwrpriv->mutex_lock);
-}
-
-static inline void register_task_alive(struct pwrctrl_priv *pwrctrl, uint tag)
-{
- pwrctrl->alives |= tag;
-}
-
-static inline void unregister_task_alive(struct pwrctrl_priv *pwrctrl, uint tag)
-{
- if (pwrctrl->alives & tag)
- pwrctrl->alives ^= tag;
-}
-
-static void _rpwm_check_handler (struct _adapter *padapter)
-{
- struct pwrctrl_priv *pwrpriv = &padapter->pwrctrlpriv;
-
- if (padapter->driver_stopped || padapter->surprise_removed)
- return;
- if (pwrpriv->cpwm != pwrpriv->rpwm)
- schedule_work(&pwrpriv->rpwm_workitem);
-}
-
-static void SetPSModeWorkItemCallback(struct work_struct *work)
-{
- struct pwrctrl_priv *pwrpriv = container_of(work,
- struct pwrctrl_priv, SetPSModeWorkItem);
- struct _adapter *padapter = container_of(pwrpriv,
- struct _adapter, pwrctrlpriv);
- if (!pwrpriv->bSleep) {
- mutex_lock(&pwrpriv->mutex_lock);
- if (pwrpriv->pwr_mode == PS_MODE_ACTIVE)
- r8712_set_rpwm(padapter, PS_STATE_S4);
- mutex_unlock(&pwrpriv->mutex_lock);
- }
-}
-
-static void rpwm_workitem_callback(struct work_struct *work)
-{
- struct pwrctrl_priv *pwrpriv = container_of(work,
- struct pwrctrl_priv, rpwm_workitem);
- struct _adapter *padapter = container_of(pwrpriv,
- struct _adapter, pwrctrlpriv);
- if (pwrpriv->cpwm != pwrpriv->rpwm) {
- mutex_lock(&pwrpriv->mutex_lock);
- r8712_read8(padapter, SDIO_HCPWM);
- pwrpriv->rpwm_retry = 1;
- r8712_set_rpwm(padapter, pwrpriv->rpwm);
- mutex_unlock(&pwrpriv->mutex_lock);
- }
-}
-
-static void rpwm_check_handler (struct timer_list *t)
-{
- struct _adapter *adapter =
- from_timer(adapter, t, pwrctrlpriv.rpwm_check_timer);
-
- _rpwm_check_handler(adapter);
-}
-
-void r8712_init_pwrctrl_priv(struct _adapter *padapter)
-{
- struct pwrctrl_priv *pwrctrlpriv = &padapter->pwrctrlpriv;
-
- memset((unsigned char *)pwrctrlpriv, 0, sizeof(struct pwrctrl_priv));
- mutex_init(&pwrctrlpriv->mutex_lock);
- pwrctrlpriv->cpwm = PS_STATE_S4;
- pwrctrlpriv->pwr_mode = PS_MODE_ACTIVE;
- pwrctrlpriv->smart_ps = 0;
- pwrctrlpriv->tog = 0x80;
-/* clear RPWM to ensure driver and fw back to initial state. */
- r8712_write8(padapter, 0x1025FE58, 0);
- INIT_WORK(&pwrctrlpriv->SetPSModeWorkItem, SetPSModeWorkItemCallback);
- INIT_WORK(&pwrctrlpriv->rpwm_workitem, rpwm_workitem_callback);
- timer_setup(&pwrctrlpriv->rpwm_check_timer, rpwm_check_handler, 0);
-}
-
-/*
- * Caller: r8712_cmd_thread
- * Check if the fw_pwrstate is okay for issuing cmd.
- * If not (cpwm should be is less than P2 state), then the sub-routine
- * will raise the cpwm to be greater than or equal to P2.
- * Calling Context: Passive
- * Return Value:
- * 0: r8712_cmd_thread can issue cmds to firmware afterwards.
- * -EINVAL: r8712_cmd_thread can not do anything.
- */
-int r8712_register_cmd_alive(struct _adapter *padapter)
-{
- int res = 0;
- struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv;
-
- mutex_lock(&pwrctrl->mutex_lock);
- register_task_alive(pwrctrl, CMD_ALIVE);
- if (pwrctrl->cpwm < PS_STATE_S2) {
- r8712_set_rpwm(padapter, PS_STATE_S3);
- res = -EINVAL;
- }
- mutex_unlock(&pwrctrl->mutex_lock);
- return res;
-}
-
-/*
- * Caller: ISR
- * If ISR's txdone,
- * No more pkts for TX,
- * Then driver shall call this fun. to power down firmware again.
- */
-void r8712_unregister_cmd_alive(struct _adapter *padapter)
-{
- struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv;
-
- mutex_lock(&pwrctrl->mutex_lock);
- unregister_task_alive(pwrctrl, CMD_ALIVE);
- if ((pwrctrl->cpwm > PS_STATE_S2) &&
- (pwrctrl->pwr_mode > PS_MODE_ACTIVE)) {
- if ((pwrctrl->alives == 0) &&
- (check_fwstate(&padapter->mlmepriv,
- _FW_UNDER_LINKING) != true)) {
- r8712_set_rpwm(padapter, PS_STATE_S0);
- }
- }
- mutex_unlock(&pwrctrl->mutex_lock);
-}
-
-void r8712_flush_rwctrl_works(struct _adapter *padapter)
-{
- struct pwrctrl_priv *pwrctrl = &padapter->pwrctrlpriv;
-
- flush_work(&pwrctrl->SetPSModeWorkItem);
- flush_work(&pwrctrl->rpwm_workitem);
-}
diff --git a/drivers/staging/rtl8712/rtl871x_pwrctrl.h b/drivers/staging/rtl8712/rtl871x_pwrctrl.h
deleted file mode 100644
index b35b9c7920eb..000000000000
--- a/drivers/staging/rtl8712/rtl871x_pwrctrl.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_PWRCTRL_H_
-#define __RTL871X_PWRCTRL_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#define CMD_ALIVE BIT(2)
-
-enum Power_Mgnt {
- PS_MODE_ACTIVE = 0,
- PS_MODE_MIN,
- PS_MODE_MAX,
- PS_MODE_DTIM,
- PS_MODE_VOIP,
- PS_MODE_UAPSD_WMM,
- PS_MODE_UAPSD,
- PS_MODE_IBSS,
- PS_MODE_WWLAN,
- PM_Radio_Off,
- PM_Card_Disable,
- PS_MODE_NUM
-};
-
-/*
- * BIT[2:0] = HW state
- * BIT[3] = Protocol PS state, 0: register active state,
- * 1: register sleep state
- * BIT[4] = sub-state
- */
-
-#define PS_DPS BIT(0)
-#define PS_LCLK (PS_DPS)
-#define PS_RF_OFF BIT(1)
-#define PS_ALL_ON BIT(2)
-#define PS_ST_ACTIVE BIT(3)
-#define PS_LP BIT(4) /* low performance */
-
-#define PS_STATE_MASK (0x0F)
-#define PS_STATE_HW_MASK (0x07)
-#define PS_SEQ_MASK (0xc0)
-
-#define PS_STATE(x) (PS_STATE_MASK & (x))
-#define PS_STATE_HW(x) (PS_STATE_HW_MASK & (x))
-#define PS_SEQ(x) (PS_SEQ_MASK & (x))
-
-#define PS_STATE_S0 (PS_DPS)
-#define PS_STATE_S1 (PS_LCLK)
-#define PS_STATE_S2 (PS_RF_OFF)
-#define PS_STATE_S3 (PS_ALL_ON)
-#define PS_STATE_S4 ((PS_ST_ACTIVE) | (PS_ALL_ON))
-
-#define PS_IS_RF_ON(x) ((x) & (PS_ALL_ON))
-#define PS_IS_ACTIVE(x) ((x) & (PS_ST_ACTIVE))
-#define CLR_PS_STATE(x) ((x) = ((x) & (0xF0)))
-
-struct reportpwrstate_parm {
- unsigned char mode;
- unsigned char state; /* the CPWM value */
- unsigned short rsvd;
-};
-
-struct pwrctrl_priv {
- struct mutex mutex_lock;
- /*volatile*/ u8 rpwm; /* requested power state for fw */
- /* fw current power state. updated when 1. read from HCPWM or
- * 2. driver lowers power level
- */
- /*volatile*/ u8 cpwm;
- /*volatile*/ u8 tog; /* toggling */
- /*volatile*/ u8 cpwm_tog; /* toggling */
- /*volatile*/ u8 tgt_rpwm; /* wanted power state */
- uint pwr_mode;
- uint smart_ps;
- uint alives;
- uint ImrContent; /* used to store original imr. */
- uint bSleep; /* sleep -> active is different from active -> sleep. */
-
- struct work_struct SetPSModeWorkItem;
- struct work_struct rpwm_workitem;
- struct timer_list rpwm_check_timer;
- u8 rpwm_retry;
- uint bSetPSModeWorkItemInProgress;
-
- spinlock_t pnp_pwr_mgnt_lock;
- s32 pnp_current_pwr_state;
- u8 pnp_bstop_trx;
- u8 pnp_wwirp_pending;
-};
-
-void r8712_init_pwrctrl_priv(struct _adapter *adapter);
-int r8712_register_cmd_alive(struct _adapter *padapter);
-void r8712_unregister_cmd_alive(struct _adapter *padapter);
-void r8712_cpwm_int_hdl(struct _adapter *padapter,
- struct reportpwrstate_parm *preportpwrstate);
-void r8712_set_ps_mode(struct _adapter *padapter, uint ps_mode,
- uint smart_ps);
-void r8712_set_rpwm(struct _adapter *padapter, u8 val8);
-void r8712_flush_rwctrl_works(struct _adapter *padapter);
-
-#endif /* __RTL871X_PWRCTRL_H_ */
diff --git a/drivers/staging/rtl8712/rtl871x_recv.c b/drivers/staging/rtl8712/rtl871x_recv.c
deleted file mode 100644
index 8a3566214af7..000000000000
--- a/drivers/staging/rtl8712/rtl871x_recv.c
+++ /dev/null
@@ -1,671 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_recv.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_RECV_C_
-
-#include <linux/ip.h>
-#include <linux/if_ether.h>
-#include <linux/etherdevice.h>
-#include <linux/ieee80211.h>
-#include <net/cfg80211.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "mlme_osdep.h"
-#include "ethernet.h"
-#include "usb_ops.h"
-#include "wifi.h"
-
-static const u8 SNAP_ETH_TYPE_IPX[2] = {0x81, 0x37};
-
-/* Datagram Delivery Protocol */
-static const u8 SNAP_ETH_TYPE_APPLETALK_AARP[2] = {0x80, 0xf3};
-
-void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv)
-{
- memset((u8 *)psta_recvpriv, 0, sizeof(struct sta_recv_priv));
- spin_lock_init(&psta_recvpriv->lock);
- _init_queue(&psta_recvpriv->defrag_q);
-}
-
-int _r8712_init_recv_priv(struct recv_priv *precvpriv,
- struct _adapter *padapter)
-{
- int ret;
- sint i;
- union recv_frame *precvframe;
-
- memset((unsigned char *)precvpriv, 0, sizeof(struct recv_priv));
- spin_lock_init(&precvpriv->lock);
- _init_queue(&precvpriv->free_recv_queue);
- _init_queue(&precvpriv->recv_pending_queue);
- precvpriv->adapter = padapter;
- precvpriv->free_recvframe_cnt = NR_RECVFRAME;
- precvpriv->pallocated_frame_buf = kzalloc(NR_RECVFRAME *
- sizeof(union recv_frame) + RXFRAME_ALIGN_SZ,
- GFP_ATOMIC);
- if (!precvpriv->pallocated_frame_buf)
- return -ENOMEM;
- precvpriv->precv_frame_buf = precvpriv->pallocated_frame_buf +
- RXFRAME_ALIGN_SZ -
- ((addr_t)(precvpriv->pallocated_frame_buf) &
- (RXFRAME_ALIGN_SZ - 1));
- precvframe = (union recv_frame *)precvpriv->precv_frame_buf;
- for (i = 0; i < NR_RECVFRAME; i++) {
- INIT_LIST_HEAD(&(precvframe->u.list));
- list_add_tail(&(precvframe->u.list),
- &(precvpriv->free_recv_queue.queue));
- r8712_os_recv_resource_alloc(padapter, precvframe);
- precvframe->u.hdr.adapter = padapter;
- precvframe++;
- }
- precvpriv->rx_pending_cnt = 1;
- ret = r8712_init_recv_priv(precvpriv, padapter);
- if (ret)
- kfree(precvpriv->pallocated_frame_buf);
-
- return ret;
-}
-
-void _r8712_free_recv_priv(struct recv_priv *precvpriv)
-{
- kfree(precvpriv->pallocated_frame_buf);
- r8712_free_recv_priv(precvpriv);
-}
-
-union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue)
-{
- unsigned long irqL;
- union recv_frame *precvframe;
- struct _adapter *padapter;
- struct recv_priv *precvpriv;
-
- spin_lock_irqsave(&pfree_recv_queue->lock, irqL);
- precvframe = list_first_entry_or_null(&pfree_recv_queue->queue,
- union recv_frame, u.hdr.list);
- if (precvframe) {
- list_del_init(&precvframe->u.hdr.list);
- padapter = precvframe->u.hdr.adapter;
- if (padapter) {
- precvpriv = &padapter->recvpriv;
- if (pfree_recv_queue == &precvpriv->free_recv_queue)
- precvpriv->free_recvframe_cnt--;
- }
- }
- spin_unlock_irqrestore(&pfree_recv_queue->lock, irqL);
- return precvframe;
-}
-
-/*
- * caller : defrag; recvframe_chk_defrag in recv_thread (passive)
- * pframequeue: defrag_queue : will be accessed in recv_thread (passive)
- * using spin_lock to protect
- */
-void r8712_free_recvframe_queue(struct __queue *pframequeue,
- struct __queue *pfree_recv_queue)
-{
- union recv_frame *precvframe;
- struct list_head *plist, *phead;
-
- spin_lock(&pframequeue->lock);
- phead = &pframequeue->queue;
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- precvframe = container_of(plist, union recv_frame, u.list);
- plist = plist->next;
- r8712_free_recvframe(precvframe, pfree_recv_queue);
- }
- spin_unlock(&pframequeue->lock);
-}
-
-sint r8712_recvframe_chkmic(struct _adapter *adapter,
- union recv_frame *precvframe)
-{
- sint i, res = _SUCCESS;
- u32 datalen;
- u8 miccode[8];
- u8 bmic_err = false;
- u8 *pframe, *payload, *pframemic;
- u8 *mickey, idx, *iv;
- struct sta_info *stainfo;
- struct rx_pkt_attrib *prxattrib = &precvframe->u.hdr.attrib;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
-
- stainfo = r8712_get_stainfo(&adapter->stapriv, &prxattrib->ta[0]);
- if (prxattrib->encrypt == _TKIP_) {
- /* calculate mic code */
- if (stainfo) {
- if (is_multicast_ether_addr(prxattrib->ra)) {
- iv = precvframe->u.hdr.rx_data +
- prxattrib->hdrlen;
- idx = iv[3];
- mickey = &psecuritypriv->XGrprxmickey[(((idx >>
- 6) & 0x3)) - 1].skey[0];
- if (!psecuritypriv->binstallGrpkey)
- return _FAIL;
- } else {
- mickey = &stainfo->tkiprxmickey.skey[0];
- }
- /*icv_len included the mic code*/
- datalen = precvframe->u.hdr.len - prxattrib->hdrlen -
- prxattrib->iv_len - prxattrib->icv_len - 8;
- pframe = precvframe->u.hdr.rx_data;
- payload = pframe + prxattrib->hdrlen +
- prxattrib->iv_len;
- seccalctkipmic(mickey, pframe, payload, datalen,
- &miccode[0],
- (unsigned char)prxattrib->priority);
- pframemic = payload + datalen;
- bmic_err = false;
- for (i = 0; i < 8; i++) {
- if (miccode[i] != *(pframemic + i))
- bmic_err = true;
- }
- if (bmic_err) {
- if (prxattrib->bdecrypted)
- r8712_handle_tkip_mic_err(adapter,
- (u8)is_multicast_ether_addr(prxattrib->ra));
- res = _FAIL;
- } else {
- /* mic checked ok */
- if (!psecuritypriv->bcheck_grpkey &&
- is_multicast_ether_addr(prxattrib->ra))
- psecuritypriv->bcheck_grpkey = true;
- }
- recvframe_pull_tail(precvframe, 8);
- }
- }
- return res;
-}
-
-/* decrypt and set the ivlen,icvlen of the recv_frame */
-union recv_frame *r8712_decryptor(struct _adapter *padapter,
- union recv_frame *precv_frame)
-{
- struct rx_pkt_attrib *prxattrib = &precv_frame->u.hdr.attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- union recv_frame *return_packet = precv_frame;
-
- if ((prxattrib->encrypt > 0) && ((prxattrib->bdecrypted == 0) ||
- psecuritypriv->sw_decrypt)) {
- psecuritypriv->hw_decrypted = false;
- switch (prxattrib->encrypt) {
- case _WEP40_:
- case _WEP104_:
- r8712_wep_decrypt(padapter, (u8 *)precv_frame);
- break;
- case _TKIP_:
- r8712_tkip_decrypt(padapter, (u8 *)precv_frame);
- break;
- case _AES_:
- r8712_aes_decrypt(padapter, (u8 *)precv_frame);
- break;
- default:
- break;
- }
- } else if (prxattrib->bdecrypted == 1) {
- psecuritypriv->hw_decrypted = true;
- }
- return return_packet;
-}
-
-/*###set the security information in the recv_frame */
-union recv_frame *r8712_portctrl(struct _adapter *adapter,
- union recv_frame *precv_frame)
-{
- u8 *psta_addr, *ptr;
- uint auth_alg;
- struct recv_frame_hdr *pfhdr;
- struct sta_info *psta;
- struct sta_priv *pstapriv;
- union recv_frame *prtnframe;
- u16 ether_type;
-
- pstapriv = &adapter->stapriv;
- ptr = precv_frame->u.hdr.rx_data;
- pfhdr = &precv_frame->u.hdr;
- psta_addr = pfhdr->attrib.ta;
- psta = r8712_get_stainfo(pstapriv, psta_addr);
- auth_alg = adapter->securitypriv.AuthAlgrthm;
- if (auth_alg == 2) {
- /* get ether_type */
- ptr = ptr + pfhdr->attrib.hdrlen + LLC_HEADER_SIZE;
- ether_type = get_unaligned_be16(ptr);
-
- if (psta && psta->ieee8021x_blocked) {
- /* blocked
- * only accept EAPOL frame
- */
- if (ether_type == 0x888e) {
- prtnframe = precv_frame;
- } else {
- /*free this frame*/
- r8712_free_recvframe(precv_frame,
- &adapter->recvpriv.free_recv_queue);
- prtnframe = NULL;
- }
- } else {
- /* allowed
- * check decryption status, and decrypt the
- * frame if needed
- */
- prtnframe = precv_frame;
- /* check is the EAPOL frame or not (Rekey) */
- if (ether_type == 0x888e) {
- /* check Rekey */
- prtnframe = precv_frame;
- }
- }
- } else {
- prtnframe = precv_frame;
- }
- return prtnframe;
-}
-
-static sint recv_decache(union recv_frame *precv_frame, u8 bretry,
- struct stainfo_rxcache *prxcache)
-{
- sint tid = precv_frame->u.hdr.attrib.priority;
- u16 seq_ctrl = ((precv_frame->u.hdr.attrib.seq_num & 0xffff) << 4) |
- (precv_frame->u.hdr.attrib.frag_num & 0xf);
-
- if (tid > 15)
- return _FAIL;
- if (seq_ctrl == prxcache->tid_rxseq[tid])
- return _FAIL;
- prxcache->tid_rxseq[tid] = seq_ctrl;
- return _SUCCESS;
-}
-
-static sint sta2sta_data_frame(struct _adapter *adapter,
- union recv_frame *precv_frame,
- struct sta_info **psta)
-{
- u8 *ptr = precv_frame->u.hdr.rx_data;
- sint ret = _SUCCESS;
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- u8 *mybssid = get_bssid(pmlmepriv);
- u8 *myhwaddr = myid(&adapter->eeprompriv);
- u8 *sta_addr = NULL;
- bool bmcast = is_multicast_ether_addr(pattrib->dst);
-
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- /* filter packets that SA is myself or multicast or broadcast */
- if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
- return _FAIL;
- if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast))
- return _FAIL;
- if (is_zero_ether_addr(pattrib->bssid) ||
- is_zero_ether_addr(mybssid) ||
- (memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
- return _FAIL;
- sta_addr = pattrib->src;
- } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- /* For Station mode, sa and bssid should always be BSSID,
- * and DA is my mac-address
- */
- if (memcmp(pattrib->bssid, pattrib->src, ETH_ALEN))
- return _FAIL;
- sta_addr = pattrib->bssid;
- } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- if (bmcast) {
- /* For AP mode, if DA == MCAST, then BSSID should
- * be also MCAST
- */
- if (!is_multicast_ether_addr(pattrib->bssid))
- return _FAIL;
- } else { /* not mc-frame */
- /* For AP mode, if DA is non-MCAST, then it must be
- * BSSID, and bssid == BSSID
- */
- if (memcmp(pattrib->bssid, pattrib->dst, ETH_ALEN))
- return _FAIL;
- sta_addr = pattrib->src;
- }
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
- memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
- sta_addr = mybssid;
- } else {
- ret = _FAIL;
- }
- if (bmcast)
- *psta = r8712_get_bcmc_stainfo(adapter);
- else
- *psta = r8712_get_stainfo(pstapriv, sta_addr); /* get ap_info */
- if (!*psta) {
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
- adapter->mppriv.rx_pktloss++;
- return _FAIL;
- }
- return ret;
-}
-
-static sint ap2sta_data_frame(struct _adapter *adapter,
- union recv_frame *precv_frame,
- struct sta_info **psta)
-{
- u8 *ptr = precv_frame->u.hdr.rx_data;
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- u8 *mybssid = get_bssid(pmlmepriv);
- u8 *myhwaddr = myid(&adapter->eeprompriv);
- bool bmcast = is_multicast_ether_addr(pattrib->dst);
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE) &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- /* if NULL-frame, drop packet */
- if ((GetFrameSubType(ptr)) == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC))
- return _FAIL;
- /* drop QoS-SubType Data, including QoS NULL,
- * excluding QoS-Data
- */
- if ((GetFrameSubType(ptr) & WIFI_QOS_DATA_TYPE) ==
- WIFI_QOS_DATA_TYPE) {
- if (GetFrameSubType(ptr) & (BIT(4) | BIT(5) | BIT(6)))
- return _FAIL;
- }
-
- /* filter packets that SA is myself or multicast or broadcast */
- if (!memcmp(myhwaddr, pattrib->src, ETH_ALEN))
- return _FAIL;
-
- /* da should be for me */
- if ((memcmp(myhwaddr, pattrib->dst, ETH_ALEN)) && (!bmcast))
- return _FAIL;
- /* check BSSID */
- if (is_zero_ether_addr(pattrib->bssid) ||
- is_zero_ether_addr(mybssid) ||
- (memcmp(pattrib->bssid, mybssid, ETH_ALEN)))
- return _FAIL;
- if (bmcast)
- *psta = r8712_get_bcmc_stainfo(adapter);
- else
- *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
- if (!*psta)
- return _FAIL;
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE) &&
- check_fwstate(pmlmepriv, _FW_LINKED)) {
- memcpy(pattrib->dst, GetAddr1Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->src, GetAddr2Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->bssid, GetAddr3Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
- memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
- memcpy(pattrib->bssid, mybssid, ETH_ALEN);
- *psta = r8712_get_stainfo(pstapriv, pattrib->bssid);
- if (!*psta)
- return _FAIL;
- } else {
- return _FAIL;
- }
- return _SUCCESS;
-}
-
-static sint sta2ap_data_frame(struct _adapter *adapter,
- union recv_frame *precv_frame,
- struct sta_info **psta)
-{
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- struct sta_priv *pstapriv = &adapter->stapriv;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
- unsigned char *mybssid = get_bssid(pmlmepriv);
-
- if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- /* For AP mode, if DA is non-MCAST, then it must be BSSID,
- * and bssid == BSSID
- * For AP mode, RA=BSSID, TX=STA(SRC_ADDR), A3=DST_ADDR
- */
- if (memcmp(pattrib->bssid, mybssid, ETH_ALEN))
- return _FAIL;
- *psta = r8712_get_stainfo(pstapriv, pattrib->src);
- if (!*psta)
- return _FAIL;
- }
- return _SUCCESS;
-}
-
-static sint validate_recv_ctrl_frame(struct _adapter *adapter,
- union recv_frame *precv_frame)
-{
- return _FAIL;
-}
-
-static sint validate_recv_mgnt_frame(struct _adapter *adapter,
- union recv_frame *precv_frame)
-{
- return _FAIL;
-}
-
-static sint validate_recv_data_frame(struct _adapter *adapter,
- union recv_frame *precv_frame)
-{
- int res;
- u8 bretry;
- u8 *psa, *pda, *pbssid;
- struct sta_info *psta = NULL;
- u8 *ptr = precv_frame->u.hdr.rx_data;
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
- struct security_priv *psecuritypriv = &adapter->securitypriv;
-
- bretry = GetRetry(ptr);
- pda = ieee80211_get_DA((struct ieee80211_hdr *)ptr);
- psa = ieee80211_get_SA((struct ieee80211_hdr *)ptr);
- pbssid = get_hdr_bssid(ptr);
- if (!pbssid)
- return _FAIL;
- memcpy(pattrib->dst, pda, ETH_ALEN);
- memcpy(pattrib->src, psa, ETH_ALEN);
- memcpy(pattrib->bssid, pbssid, ETH_ALEN);
- switch (pattrib->to_fr_ds) {
- case 0:
- memcpy(pattrib->ra, pda, ETH_ALEN);
- memcpy(pattrib->ta, psa, ETH_ALEN);
- res = sta2sta_data_frame(adapter, precv_frame, &psta);
- break;
- case 1:
- memcpy(pattrib->ra, pda, ETH_ALEN);
- memcpy(pattrib->ta, pbssid, ETH_ALEN);
- res = ap2sta_data_frame(adapter, precv_frame, &psta);
- break;
- case 2:
- memcpy(pattrib->ra, pbssid, ETH_ALEN);
- memcpy(pattrib->ta, psa, ETH_ALEN);
- res = sta2ap_data_frame(adapter, precv_frame, &psta);
- break;
- case 3:
- memcpy(pattrib->ra, GetAddr1Ptr(ptr), ETH_ALEN);
- memcpy(pattrib->ta, GetAddr2Ptr(ptr), ETH_ALEN);
- return _FAIL;
- default:
- return _FAIL;
- }
- if (res == _FAIL)
- return _FAIL;
- if (!psta)
- return _FAIL;
- precv_frame->u.hdr.psta = psta;
- pattrib->amsdu = 0;
- /* parsing QC field */
- if (pattrib->qos == 1) {
- pattrib->priority = GetPriority((ptr + 24));
- pattrib->ack_policy = GetAckpolicy((ptr + 24));
- pattrib->amsdu = GetAMsdu((ptr + 24));
- pattrib->hdrlen = pattrib->to_fr_ds == 3 ? 32 : 26;
- } else {
- pattrib->priority = 0;
- pattrib->hdrlen = (pattrib->to_fr_ds == 3) ? 30 : 24;
- }
-
- if (pattrib->order)/*HT-CTRL 11n*/
- pattrib->hdrlen += 4;
- precv_frame->u.hdr.preorder_ctrl =
- &psta->recvreorder_ctrl[pattrib->priority];
-
- /* decache, drop duplicate recv packets */
- if (recv_decache(precv_frame, bretry, &psta->sta_recvpriv.rxcache) ==
- _FAIL)
- return _FAIL;
-
- if (pattrib->privacy) {
- GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt,
- is_multicast_ether_addr(pattrib->ra));
- SET_ICE_IV_LEN(pattrib->iv_len, pattrib->icv_len,
- pattrib->encrypt);
- } else {
- pattrib->encrypt = 0;
- pattrib->iv_len = pattrib->icv_len = 0;
- }
- return _SUCCESS;
-}
-
-sint r8712_validate_recv_frame(struct _adapter *adapter,
- union recv_frame *precv_frame)
-{
- /*shall check frame subtype, to / from ds, da, bssid */
- /*then call check if rx seq/frag. duplicated.*/
-
- u8 type;
- u8 subtype;
- sint retval = _SUCCESS;
- struct rx_pkt_attrib *pattrib = &precv_frame->u.hdr.attrib;
-
- u8 *ptr = precv_frame->u.hdr.rx_data;
- u8 ver = (unsigned char)(*ptr) & 0x3;
-
- /*add version chk*/
- if (ver != 0)
- return _FAIL;
- type = GetFrameType(ptr);
- subtype = GetFrameSubType(ptr); /*bit(7)~bit(2)*/
- pattrib->to_fr_ds = get_tofr_ds(ptr);
- pattrib->frag_num = GetFragNum(ptr);
- pattrib->seq_num = GetSequence(ptr);
- pattrib->pw_save = GetPwrMgt(ptr);
- pattrib->mfrag = GetMFrag(ptr);
- pattrib->mdata = GetMData(ptr);
- pattrib->privacy = GetPrivacy(ptr);
- pattrib->order = GetOrder(ptr);
- switch (type) {
- case IEEE80211_FTYPE_MGMT:
- retval = validate_recv_mgnt_frame(adapter, precv_frame);
- break;
- case IEEE80211_FTYPE_CTL:
- retval = validate_recv_ctrl_frame(adapter, precv_frame);
- break;
- case IEEE80211_FTYPE_DATA:
- pattrib->qos = (subtype & BIT(7)) ? 1 : 0;
- retval = validate_recv_data_frame(adapter, precv_frame);
- break;
- default:
- return _FAIL;
- }
- return retval;
-}
-
-int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe)
-{
- /*remove the wlanhdr and add the eth_hdr*/
- sint rmv_len;
- u16 len;
- u8 bsnaphdr;
- u8 *psnap_type;
- struct ieee80211_snap_hdr *psnap;
- struct _adapter *adapter = precvframe->u.hdr.adapter;
- struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
-
- u8 *ptr = precvframe->u.hdr.rx_data; /*point to frame_ctrl field*/
- struct rx_pkt_attrib *pattrib = &precvframe->u.hdr.attrib;
-
- if (pattrib->encrypt)
- recvframe_pull_tail(precvframe, pattrib->icv_len);
- psnap = (struct ieee80211_snap_hdr *)(ptr + pattrib->hdrlen +
- pattrib->iv_len);
- psnap_type = ptr + pattrib->hdrlen + pattrib->iv_len + SNAP_SIZE;
- /* convert hdr + possible LLC headers into Ethernet header */
- if ((!memcmp(psnap, (void *)rfc1042_header, SNAP_SIZE) &&
- (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_IPX, 2)) &&
- (memcmp(psnap_type, (void *)SNAP_ETH_TYPE_APPLETALK_AARP, 2))) ||
- !memcmp(psnap, (void *)bridge_tunnel_header, SNAP_SIZE)) {
- /* remove RFC1042 or Bridge-Tunnel encapsulation and
- * replace EtherType
- */
- bsnaphdr = true;
- } else {
- /* Leave Ethernet header part of hdr and full payload */
- bsnaphdr = false;
- }
- rmv_len = pattrib->hdrlen + pattrib->iv_len +
- (bsnaphdr ? SNAP_SIZE : 0);
- len = precvframe->u.hdr.len - rmv_len;
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- ptr += rmv_len;
- *ptr = 0x87;
- *(ptr + 1) = 0x12;
- /* append rx status for mp test packets */
- ptr = recvframe_pull(precvframe, (rmv_len -
- sizeof(struct ethhdr) + 2) - 24);
- if (!ptr)
- return -ENOMEM;
- memcpy(ptr, get_rxmem(precvframe), 24);
- ptr += 24;
- } else {
- ptr = recvframe_pull(precvframe, (rmv_len -
- sizeof(struct ethhdr) + (bsnaphdr ? 2 : 0)));
- if (!ptr)
- return -ENOMEM;
- }
-
- memcpy(ptr, pattrib->dst, ETH_ALEN);
- memcpy(ptr + ETH_ALEN, pattrib->src, ETH_ALEN);
- if (!bsnaphdr) {
- __be16 be_tmp = htons(len);
-
- memcpy(ptr + 12, &be_tmp, 2);
- }
- return 0;
-}
-
-void r8712_recv_entry(union recv_frame *precvframe)
-{
- struct _adapter *padapter;
- struct recv_priv *precvpriv;
-
- s32 ret = _SUCCESS;
-
- padapter = precvframe->u.hdr.adapter;
- precvpriv = &(padapter->recvpriv);
-
- padapter->ledpriv.LedControlHandler(padapter, LED_CTL_RX);
-
- ret = recv_func(padapter, precvframe);
- if (ret == _FAIL)
- goto _recv_entry_drop;
- precvpriv->rx_pkts++;
- precvpriv->rx_bytes += (uint)(precvframe->u.hdr.rx_tail -
- precvframe->u.hdr.rx_data);
- return;
-_recv_entry_drop:
- precvpriv->rx_drop++;
- padapter->mppriv.rx_pktloss = precvpriv->rx_drop;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_recv.h b/drivers/staging/rtl8712/rtl871x_recv.h
deleted file mode 100644
index 0760bccbf389..000000000000
--- a/drivers/staging/rtl8712/rtl871x_recv.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _RTL871X_RECV_H_
-#define _RTL871X_RECV_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#define NR_RECVFRAME 256
-
-#define RXFRAME_ALIGN 8
-#define RXFRAME_ALIGN_SZ (1 << RXFRAME_ALIGN)
-
-#define MAX_SUBFRAME_COUNT 64
-
-/* for Rx reordering buffer control */
-struct recv_reorder_ctrl {
- struct _adapter *padapter;
- u16 indicate_seq; /* =wstart_b, init_value=0xffff */
- u16 wend_b;
- u8 wsize_b;
- struct __queue pending_recvframe_queue;
- struct timer_list reordering_ctrl_timer;
-};
-
-struct stainfo_rxcache {
- u16 tid_rxseq[16];
-};
-
-#define PHY_RSSI_SLID_WIN_MAX 100
-#define PHY_LINKQUALITY_SLID_WIN_MAX 20
-
-struct smooth_rssi_data {
- u32 elements[100]; /* array to store values */
- u32 index; /* index to current array to store */
- u32 total_num; /* num of valid elements */
- u32 total_val; /* sum of valid elements */
-};
-
-struct rx_pkt_attrib {
- u8 amsdu;
- u8 order;
- u8 qos;
- u8 to_fr_ds;
- u8 frag_num;
- u16 seq_num;
- u8 pw_save;
- u8 mfrag;
- u8 mdata;
- u8 privacy; /* in frame_ctrl field */
- u8 bdecrypted;
- int hdrlen; /* the WLAN Header Len */
- int encrypt; /* 0 no encrypt. != 0 encrypt algorithm */
- int iv_len;
- int icv_len;
- int priority;
- int ack_policy;
- u8 crc_err;
- u8 dst[ETH_ALEN];
- u8 src[ETH_ALEN];
- u8 ta[ETH_ALEN];
- u8 ra[ETH_ALEN];
- u8 bssid[ETH_ALEN];
- u8 tcpchk_valid; /* 0: invalid, 1: valid */
- u8 ip_chkrpt; /* 0: incorrect, 1: correct */
- u8 tcp_chkrpt; /* 0: incorrect, 1: correct */
- u8 signal_qual;
- s8 rx_mimo_signal_qual[2];
- u8 mcs_rate;
- u8 htc;
- u8 signal_strength;
-};
-
-/*
- * accesser of recv_priv: recv_entry(dispatch / passive level);
- * recv_thread(passive) ; returnpkt(dispatch)
- * ; halt(passive) ;
- *
- * using enter_critical section to protect
- */
-struct recv_priv {
- spinlock_t lock;
- struct __queue free_recv_queue;
- struct __queue recv_pending_queue;
- u8 *pallocated_frame_buf;
- u8 *precv_frame_buf;
- uint free_recvframe_cnt;
- struct _adapter *adapter;
- uint rx_bytes;
- uint rx_pkts;
- uint rx_drop;
- uint rx_icv_err;
- uint rx_largepacket_crcerr;
- uint rx_smallpacket_crcerr;
- uint rx_middlepacket_crcerr;
- u8 rx_pending_cnt;
- uint ff_hwaddr;
- struct tasklet_struct recv_tasklet;
- struct sk_buff_head free_recv_skb_queue;
- struct sk_buff_head rx_skb_queue;
- u8 *pallocated_recv_buf;
- u8 *precv_buf; /* 4 alignment */
- struct __queue free_recv_buf_queue;
- u32 free_recv_buf_queue_cnt;
- /* For the phy information */
- s8 rssi;
- u8 signal;
- u8 noise;
- u8 fw_rssi;
- struct smooth_rssi_data signal_qual_data;
- struct smooth_rssi_data signal_strength_data;
-};
-
-struct sta_recv_priv {
- spinlock_t lock;
- sint option;
- struct __queue defrag_q; /* keeping the fragment frame until defrag */
- struct stainfo_rxcache rxcache;
- uint sta_rx_bytes;
- uint sta_rx_pkts;
- uint sta_rx_fail;
-};
-
-#include "rtl8712_recv.h"
-
-/* get a free recv_frame from pfree_recv_queue */
-union recv_frame *r8712_alloc_recvframe(struct __queue *pfree_recv_queue);
-void r8712_free_recvframe(union recv_frame *precvframe,
- struct __queue *pfree_recv_queue);
-void r8712_free_recvframe_queue(struct __queue *pframequeue,
- struct __queue *pfree_recv_queue);
-int r8712_wlanhdr_to_ethhdr(union recv_frame *precvframe);
-int recv_func(struct _adapter *padapter, void *pcontext);
-
-static inline u8 *get_rxmem(union recv_frame *precvframe)
-{
- /* always return rx_head... */
- if (!precvframe)
- return NULL;
- return precvframe->u.hdr.rx_head;
-}
-
-static inline u8 *recvframe_pull(union recv_frame *precvframe, sint sz)
-{
- /* used for extract sz bytes from rx_data, update rx_data and return
- * the updated rx_data to the caller
- */
- if (!precvframe)
- return NULL;
- precvframe->u.hdr.rx_data += sz;
- if (precvframe->u.hdr.rx_data > precvframe->u.hdr.rx_tail) {
- precvframe->u.hdr.rx_data -= sz;
- return NULL;
- }
- precvframe->u.hdr.len -= sz;
- return precvframe->u.hdr.rx_data;
-}
-
-static inline u8 *recvframe_put(union recv_frame *precvframe, sint sz)
-{
- /* used for append sz bytes from ptr to rx_tail, update rx_tail and
- * return the updated rx_tail to the caller
- * after putting, rx_tail must be still larger than rx_end.
- */
- if (!precvframe)
- return NULL;
- precvframe->u.hdr.rx_tail += sz;
- if (precvframe->u.hdr.rx_tail > precvframe->u.hdr.rx_end) {
- precvframe->u.hdr.rx_tail -= sz;
- return NULL;
- }
- precvframe->u.hdr.len += sz;
- return precvframe->u.hdr.rx_tail;
-}
-
-static inline u8 *recvframe_pull_tail(union recv_frame *precvframe, sint sz)
-{
- /* rmv data from rx_tail (by yitsen)
- * used for extract sz bytes from rx_end, update rx_end and return the
- * updated rx_end to the caller
- * after pulling, rx_end must be still larger than rx_data.
- */
- if (!precvframe)
- return NULL;
- precvframe->u.hdr.rx_tail -= sz;
- if (precvframe->u.hdr.rx_tail < precvframe->u.hdr.rx_data) {
- precvframe->u.hdr.rx_tail += sz;
- return NULL;
- }
- precvframe->u.hdr.len -= sz;
- return precvframe->u.hdr.rx_tail;
-}
-
-struct sta_info;
-
-void _r8712_init_sta_recv_priv(struct sta_recv_priv *psta_recvpriv);
-sint r8712_recvframe_chkmic(struct _adapter *adapter,
- union recv_frame *precvframe);
-union recv_frame *r8712_decryptor(struct _adapter *adapter,
- union recv_frame *precv_frame);
-union recv_frame *r8712_recvframe_chk_defrag(struct _adapter *adapter,
- union recv_frame *precv_frame);
-int r8712_validate_recv_frame(struct _adapter *adapter,
- union recv_frame *precv_frame);
-union recv_frame *r8712_portctrl(struct _adapter *adapter,
- union recv_frame *precv_frame);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_rf.h b/drivers/staging/rtl8712/rtl871x_rf.h
deleted file mode 100644
index 7d98921a48fa..000000000000
--- a/drivers/staging/rtl8712/rtl871x_rf.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_RF_H_
-#define __RTL871X_RF_H_
-
-#include "rtl871x_cmd.h"
-#include "rtl871x_mp_phy_regdef.h"
-
-#define OFDM_PHY 1
-#define MIXED_PHY 2
-#define CCK_PHY 3
-#define NumRates (13)
-#define RTL8711_RF_MAX_SENS 6
-#define RTL8711_RF_DEF_SENS 4
-#define NUM_CHANNELS 15
-
-struct regulatory_class {
- u32 starting_freq; /*MHz, */
- u8 channel_set[NUM_CHANNELS];
- u8 channel_cck_power[NUM_CHANNELS]; /*dbm*/
- u8 channel_ofdm_power[NUM_CHANNELS];/*dbm*/
- u8 txpower_limit; /*dbm*/
- u8 channel_spacing; /*MHz*/
- u8 modem;
-};
-
-enum _REG_PREAMBLE_MODE {
- PREAMBLE_LONG = 1,
- PREAMBLE_AUTO = 2,
- PREAMBLE_SHORT = 3,
-};
-
-enum {
- RTL8712_RFC_1T = 0x10,
- RTL8712_RFC_2T = 0x20,
- RTL8712_RFC_1R = 0x01,
- RTL8712_RFC_2R = 0x02,
- RTL8712_RFC_1T1R = 0x11,
- RTL8712_RFC_1T2R = 0x12,
- RTL8712_RFC_TURBO = 0x92,
- RTL8712_RFC_2T2R = 0x22
-};
-
-#endif /*__RTL871X_RF_H_*/
diff --git a/drivers/staging/rtl8712/rtl871x_security.c b/drivers/staging/rtl8712/rtl871x_security.c
deleted file mode 100644
index e46a5dbc7b65..000000000000
--- a/drivers/staging/rtl8712/rtl871x_security.c
+++ /dev/null
@@ -1,1386 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_security.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_SECURITY_C_
-
-#include <linux/compiler.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/netdevice.h>
-#include <linux/skbuff.h>
-#include <linux/circ_buf.h>
-#include <linux/uaccess.h>
-#include <asm/byteorder.h>
-#include <linux/atomic.h>
-#include <linux/crc32poly.h>
-#include <linux/semaphore.h>
-#include <linux/ieee80211.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-
-/* =====WEP related===== */
-
-struct arc4context {
- u32 x;
- u32 y;
- u8 state[256];
-};
-
-static void arcfour_init(struct arc4context *parc4ctx, u8 *key, u32 key_len)
-{
- u32 t, u;
- u32 keyindex;
- u32 stateindex;
- u8 *state;
- u32 counter;
-
- state = parc4ctx->state;
- parc4ctx->x = 0;
- parc4ctx->y = 0;
- for (counter = 0; counter < 256; counter++)
- state[counter] = (u8)counter;
- keyindex = 0;
- stateindex = 0;
- for (counter = 0; counter < 256; counter++) {
- t = state[counter];
- stateindex = (stateindex + key[keyindex] + t) & 0xff;
- u = state[stateindex];
- state[stateindex] = (u8)t;
- state[counter] = (u8)u;
- if (++keyindex >= key_len)
- keyindex = 0;
- }
-}
-
-static u32 arcfour_byte(struct arc4context *parc4ctx)
-{
- u32 x;
- u32 y;
- u32 sx, sy;
- u8 *state;
-
- state = parc4ctx->state;
- x = (parc4ctx->x + 1) & 0xff;
- sx = state[x];
- y = (sx + parc4ctx->y) & 0xff;
- sy = state[y];
- parc4ctx->x = x;
- parc4ctx->y = y;
- state[y] = (u8)sx;
- state[x] = (u8)sy;
- return state[(sx + sy) & 0xff];
-}
-
-static void arcfour_encrypt(struct arc4context *parc4ctx,
- u8 *dest, u8 *src, u32 len)
-{
- u32 i;
-
- for (i = 0; i < len; i++)
- dest[i] = src[i] ^ (unsigned char)arcfour_byte(parc4ctx);
-}
-
-static sint bcrc32initialized;
-static u32 crc32_table[256];
-
-static u8 crc32_reverseBit(u8 data)
-{
- return ((u8)(data << 7) & 0x80) | ((data << 5) & 0x40) | ((data << 3)
- & 0x20) | ((data << 1) & 0x10) | ((data >> 1) & 0x08) |
- ((data >> 3) & 0x04) | ((data >> 5) & 0x02) | ((data >> 7) &
- 0x01);
-}
-
-static void crc32_init(void)
-{
- sint i, j;
- u32 c;
- u8 *p = (u8 *)&c, *p1;
- u8 k;
-
- if (bcrc32initialized == 1)
- return;
-
- for (i = 0; i < 256; ++i) {
- k = crc32_reverseBit((u8)i);
- for (c = ((u32)k) << 24, j = 8; j > 0; --j)
- c = c & 0x80000000 ? (c << 1) ^ CRC32_POLY_BE : (c << 1);
- p1 = (u8 *)&crc32_table[i];
- p1[0] = crc32_reverseBit(p[3]);
- p1[1] = crc32_reverseBit(p[2]);
- p1[2] = crc32_reverseBit(p[1]);
- p1[3] = crc32_reverseBit(p[0]);
- }
- bcrc32initialized = 1;
-}
-
-static u32 getcrc32(u8 *buf, u32 len)
-{
- u8 *p;
- u32 crc;
-
- if (!bcrc32initialized)
- crc32_init();
- crc = 0xffffffff; /* preload shift register, per CRC-32 spec */
- for (p = buf; len > 0; ++p, --len)
- crc = crc32_table[(crc ^ *p) & 0xff] ^ (crc >> 8);
- return ~crc; /* transmit complement, per CRC-32 spec */
-}
-
-/*
- * Need to consider the fragment situation
- */
-void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe)
-{ /* exclude ICV */
- unsigned char crc[4];
- struct arc4context mycontext;
- u32 curfragnum, length, keylength, pki;
- u8 *pframe, *payload, *iv; /*,*wepkey*/
- u8 wepkey[16];
- struct pkt_attrib *pattrib = &((struct xmit_frame *)
- pxmitframe)->attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
- return;
- pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
- /*start to encrypt each fragment*/
- if ((pattrib->encrypt == _WEP40_) || (pattrib->encrypt == _WEP104_)) {
- pki = psecuritypriv->PrivacyKeyIndex;
- keylength = psecuritypriv->DefKeylen[pki];
- for (curfragnum = 0; curfragnum < pattrib->nr_frags;
- curfragnum++) {
- iv = pframe + pattrib->hdrlen;
- memcpy(&wepkey[0], iv, 3);
- memcpy(&wepkey[3], &psecuritypriv->DefKey[
- psecuritypriv->PrivacyKeyIndex].skey[0],
- keylength);
- payload = pframe + pattrib->iv_len + pattrib->hdrlen;
- if ((curfragnum + 1) == pattrib->nr_frags) {
- length = pattrib->last_txcmdsz -
- pattrib->hdrlen -
- pattrib->iv_len -
- pattrib->icv_len;
- *((__le32 *)crc) = cpu_to_le32(getcrc32(
- payload, length));
- arcfour_init(&mycontext, wepkey, 3 + keylength);
- arcfour_encrypt(&mycontext, payload, payload,
- length);
- arcfour_encrypt(&mycontext, payload + length,
- crc, 4);
- } else {
- length = pxmitpriv->frag_len -
- pattrib->hdrlen - pattrib->iv_len -
- pattrib->icv_len;
- *((__le32 *)crc) = cpu_to_le32(getcrc32(
- payload, length));
- arcfour_init(&mycontext, wepkey, 3 + keylength);
- arcfour_encrypt(&mycontext, payload, payload,
- length);
- arcfour_encrypt(&mycontext, payload + length,
- crc, 4);
- pframe += pxmitpriv->frag_len;
- pframe = (u8 *)RND4((addr_t)(pframe));
- }
- }
- }
-}
-
-void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe)
-{
- /* exclude ICV */
- u8 crc[4];
- struct arc4context mycontext;
- u32 length, keylength;
- u8 *pframe, *payload, *iv, wepkey[16];
- u8 keyindex;
- struct rx_pkt_attrib *prxattrib = &(((union recv_frame *)
- precvframe)->u.hdr.attrib);
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- pframe = (unsigned char *)((union recv_frame *)precvframe)->
- u.hdr.rx_data;
- /* start to decrypt recvframe */
- if ((prxattrib->encrypt == _WEP40_) || (prxattrib->encrypt ==
- _WEP104_)) {
- iv = pframe + prxattrib->hdrlen;
- keyindex = (iv[3] & 0x3);
- keylength = psecuritypriv->DefKeylen[keyindex];
- memcpy(&wepkey[0], iv, 3);
- memcpy(&wepkey[3], &psecuritypriv->DefKey[
- psecuritypriv->PrivacyKeyIndex].skey[0],
- keylength);
- length = ((union recv_frame *)precvframe)->
- u.hdr.len - prxattrib->hdrlen - prxattrib->iv_len;
- payload = pframe + prxattrib->iv_len + prxattrib->hdrlen;
- /* decrypt payload include icv */
- arcfour_init(&mycontext, wepkey, 3 + keylength);
- arcfour_encrypt(&mycontext, payload, payload, length);
- /* calculate icv and compare the icv */
- *((__le32 *)crc) = cpu_to_le32(getcrc32(payload, length - 4));
- }
-}
-
-/* 3 =====TKIP related===== */
-
-static u32 secmicgetuint32(u8 *p)
-/* Convert from Byte[] to Us4Byte32 in a portable way */
-{
- s32 i;
- u32 res = 0;
-
- for (i = 0; i < 4; i++)
- res |= ((u32)(*p++)) << (8 * i);
- return res;
-}
-
-static void secmicputuint32(u8 *p, u32 val)
-/* Convert from Us4Byte32 to Byte[] in a portable way */
-{
- long i;
-
- for (i = 0; i < 4; i++) {
- *p++ = (u8)(val & 0xff);
- val >>= 8;
- }
-}
-
-static void secmicclear(struct mic_data *pmicdata)
-{
-/* Reset the state to the empty message. */
- pmicdata->L = pmicdata->K0;
- pmicdata->R = pmicdata->K1;
- pmicdata->nBytesInM = 0;
- pmicdata->M = 0;
-}
-
-void r8712_secmicsetkey(struct mic_data *pmicdata, u8 *key)
-{
- /* Set the key */
- pmicdata->K0 = secmicgetuint32(key);
- pmicdata->K1 = secmicgetuint32(key + 4);
- /* and reset the message */
- secmicclear(pmicdata);
-}
-
-static void secmicappendbyte(struct mic_data *pmicdata, u8 b)
-{
- /* Append the byte to our word-sized buffer */
- pmicdata->M |= ((u32)b) << (8 * pmicdata->nBytesInM);
- pmicdata->nBytesInM++;
- /* Process the word if it is full. */
- if (pmicdata->nBytesInM >= 4) {
- pmicdata->L ^= pmicdata->M;
- pmicdata->R ^= ROL32(pmicdata->L, 17);
- pmicdata->L += pmicdata->R;
- pmicdata->R ^= ((pmicdata->L & 0xff00ff00) >> 8) |
- ((pmicdata->L & 0x00ff00ff) << 8);
- pmicdata->L += pmicdata->R;
- pmicdata->R ^= ROL32(pmicdata->L, 3);
- pmicdata->L += pmicdata->R;
- pmicdata->R ^= ROR32(pmicdata->L, 2);
- pmicdata->L += pmicdata->R;
- /* Clear the buffer */
- pmicdata->M = 0;
- pmicdata->nBytesInM = 0;
- }
-}
-
-void r8712_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nbytes)
-{
- /* This is simple */
- while (nbytes > 0) {
- secmicappendbyte(pmicdata, *src++);
- nbytes--;
- }
-}
-
-void r8712_secgetmic(struct mic_data *pmicdata, u8 *dst)
-{
- /* Append the minimum padding */
- secmicappendbyte(pmicdata, 0x5a);
- secmicappendbyte(pmicdata, 0);
- secmicappendbyte(pmicdata, 0);
- secmicappendbyte(pmicdata, 0);
- secmicappendbyte(pmicdata, 0);
- /* and then zeroes until the length is a multiple of 4 */
- while (pmicdata->nBytesInM != 0)
- secmicappendbyte(pmicdata, 0);
- /* The appendByte function has already computed the result. */
- secmicputuint32(dst, pmicdata->L);
- secmicputuint32(dst + 4, pmicdata->R);
- /* Reset to the empty message. */
- secmicclear(pmicdata);
-}
-
-void seccalctkipmic(u8 *key, u8 *header, u8 *data, u32 data_len, u8 *mic_code,
- u8 pri)
-{
-
- struct mic_data micdata;
- u8 priority[4] = {0x0, 0x0, 0x0, 0x0};
-
- r8712_secmicsetkey(&micdata, key);
- priority[0] = pri;
- /* Michael MIC pseudo header: DA, SA, 3 x 0, Priority */
- if (header[1] & 1) { /* ToDS==1 */
- r8712_secmicappend(&micdata, &header[16], 6); /* DA */
- if (header[1] & 2) /* From Ds==1 */
- r8712_secmicappend(&micdata, &header[24], 6);
- else
- r8712_secmicappend(&micdata, &header[10], 6);
- } else { /* ToDS==0 */
- r8712_secmicappend(&micdata, &header[4], 6); /* DA */
- if (header[1] & 2) /* From Ds==1 */
- r8712_secmicappend(&micdata, &header[16], 6);
- else
- r8712_secmicappend(&micdata, &header[10], 6);
- }
- r8712_secmicappend(&micdata, &priority[0], 4);
- r8712_secmicappend(&micdata, data, data_len);
- r8712_secgetmic(&micdata, mic_code);
-}
-
-/* macros for extraction/creation of unsigned char/unsigned short values */
-#define RotR1(v16) ((((v16) >> 1) & 0x7FFF) ^ (((v16) & 1) << 15))
-#define Lo8(v16) ((u8)((v16) & 0x00FF))
-#define Hi8(v16) ((u8)(((v16) >> 8) & 0x00FF))
-#define Lo16(v32) ((u16)((v32) & 0xFFFF))
-#define Hi16(v32) ((u16)(((v32) >> 16) & 0xFFFF))
-#define Mk16(hi, lo) ((lo) ^ (((u16)(hi)) << 8))
-
-/* select the Nth 16-bit word of the temporal key unsigned char array TK[] */
-#define TK16(N) Mk16(tk[2 * (N) + 1], tk[2 * (N)])
-
-/* S-box lookup: 16 bits --> 16 bits */
-#define _S_(v16) (Sbox1[0][Lo8(v16)] ^ Sbox1[1][Hi8(v16)])
-
-/* fixed algorithm "parameters" */
-#define PHASE1_LOOP_CNT 8 /* this needs to be "big enough" */
-#define TA_SIZE 6 /* 48-bit transmitter address */
-#define TK_SIZE 16 /* 128-bit temporal key */
-#define P1K_SIZE 10 /* 80-bit Phase1 key */
-#define RC4_KEY_SIZE 16 /* 128-bit RC4KEY (104 bits unknown) */
-
-/* 2-unsigned char by 2-unsigned char subset of the full AES S-box table */
-static const unsigned short Sbox1[2][256] = {/* Sbox for hash (can be in ROM) */
- {
- 0xC6A5, 0xF884, 0xEE99, 0xF68D, 0xFF0D, 0xD6BD, 0xDEB1, 0x9154,
- 0x6050, 0x0203, 0xCEA9, 0x567D, 0xE719, 0xB562, 0x4DE6, 0xEC9A,
- 0x8F45, 0x1F9D, 0x8940, 0xFA87, 0xEF15, 0xB2EB, 0x8EC9, 0xFB0B,
- 0x41EC, 0xB367, 0x5FFD, 0x45EA, 0x23BF, 0x53F7, 0xE496, 0x9B5B,
- 0x75C2, 0xE11C, 0x3DAE, 0x4C6A, 0x6C5A, 0x7E41, 0xF502, 0x834F,
- 0x685C, 0x51F4, 0xD134, 0xF908, 0xE293, 0xAB73, 0x6253, 0x2A3F,
- 0x080C, 0x9552, 0x4665, 0x9D5E, 0x3028, 0x37A1, 0x0A0F, 0x2FB5,
- 0x0E09, 0x2436, 0x1B9B, 0xDF3D, 0xCD26, 0x4E69, 0x7FCD, 0xEA9F,
- 0x121B, 0x1D9E, 0x5874, 0x342E, 0x362D, 0xDCB2, 0xB4EE, 0x5BFB,
- 0xA4F6, 0x764D, 0xB761, 0x7DCE, 0x527B, 0xDD3E, 0x5E71, 0x1397,
- 0xA6F5, 0xB968, 0x0000, 0xC12C, 0x4060, 0xE31F, 0x79C8, 0xB6ED,
- 0xD4BE, 0x8D46, 0x67D9, 0x724B, 0x94DE, 0x98D4, 0xB0E8, 0x854A,
- 0xBB6B, 0xC52A, 0x4FE5, 0xED16, 0x86C5, 0x9AD7, 0x6655, 0x1194,
- 0x8ACF, 0xE910, 0x0406, 0xFE81, 0xA0F0, 0x7844, 0x25BA, 0x4BE3,
- 0xA2F3, 0x5DFE, 0x80C0, 0x058A, 0x3FAD, 0x21BC, 0x7048, 0xF104,
- 0x63DF, 0x77C1, 0xAF75, 0x4263, 0x2030, 0xE51A, 0xFD0E, 0xBF6D,
- 0x814C, 0x1814, 0x2635, 0xC32F, 0xBEE1, 0x35A2, 0x88CC, 0x2E39,
- 0x9357, 0x55F2, 0xFC82, 0x7A47, 0xC8AC, 0xBAE7, 0x322B, 0xE695,
- 0xC0A0, 0x1998, 0x9ED1, 0xA37F, 0x4466, 0x547E, 0x3BAB, 0x0B83,
- 0x8CCA, 0xC729, 0x6BD3, 0x283C, 0xA779, 0xBCE2, 0x161D, 0xAD76,
- 0xDB3B, 0x6456, 0x744E, 0x141E, 0x92DB, 0x0C0A, 0x486C, 0xB8E4,
- 0x9F5D, 0xBD6E, 0x43EF, 0xC4A6, 0x39A8, 0x31A4, 0xD337, 0xF28B,
- 0xD532, 0x8B43, 0x6E59, 0xDAB7, 0x018C, 0xB164, 0x9CD2, 0x49E0,
- 0xD8B4, 0xACFA, 0xF307, 0xCF25, 0xCAAF, 0xF48E, 0x47E9, 0x1018,
- 0x6FD5, 0xF088, 0x4A6F, 0x5C72, 0x3824, 0x57F1, 0x73C7, 0x9751,
- 0xCB23, 0xA17C, 0xE89C, 0x3E21, 0x96DD, 0x61DC, 0x0D86, 0x0F85,
- 0xE090, 0x7C42, 0x71C4, 0xCCAA, 0x90D8, 0x0605, 0xF701, 0x1C12,
- 0xC2A3, 0x6A5F, 0xAEF9, 0x69D0, 0x1791, 0x9958, 0x3A27, 0x27B9,
- 0xD938, 0xEB13, 0x2BB3, 0x2233, 0xD2BB, 0xA970, 0x0789, 0x33A7,
- 0x2DB6, 0x3C22, 0x1592, 0xC920, 0x8749, 0xAAFF, 0x5078, 0xA57A,
- 0x038F, 0x59F8, 0x0980, 0x1A17, 0x65DA, 0xD731, 0x84C6, 0xD0B8,
- 0x82C3, 0x29B0, 0x5A77, 0x1E11, 0x7BCB, 0xA8FC, 0x6DD6, 0x2C3A,
- },
- { /* second half is unsigned char-reversed version of first! */
- 0xA5C6, 0x84F8, 0x99EE, 0x8DF6, 0x0DFF, 0xBDD6, 0xB1DE, 0x5491,
- 0x5060, 0x0302, 0xA9CE, 0x7D56, 0x19E7, 0x62B5, 0xE64D, 0x9AEC,
- 0x458F, 0x9D1F, 0x4089, 0x87FA, 0x15EF, 0xEBB2, 0xC98E, 0x0BFB,
- 0xEC41, 0x67B3, 0xFD5F, 0xEA45, 0xBF23, 0xF753, 0x96E4, 0x5B9B,
- 0xC275, 0x1CE1, 0xAE3D, 0x6A4C, 0x5A6C, 0x417E, 0x02F5, 0x4F83,
- 0x5C68, 0xF451, 0x34D1, 0x08F9, 0x93E2, 0x73AB, 0x5362, 0x3F2A,
- 0x0C08, 0x5295, 0x6546, 0x5E9D, 0x2830, 0xA137, 0x0F0A, 0xB52F,
- 0x090E, 0x3624, 0x9B1B, 0x3DDF, 0x26CD, 0x694E, 0xCD7F, 0x9FEA,
- 0x1B12, 0x9E1D, 0x7458, 0x2E34, 0x2D36, 0xB2DC, 0xEEB4, 0xFB5B,
- 0xF6A4, 0x4D76, 0x61B7, 0xCE7D, 0x7B52, 0x3EDD, 0x715E, 0x9713,
- 0xF5A6, 0x68B9, 0x0000, 0x2CC1, 0x6040, 0x1FE3, 0xC879, 0xEDB6,
- 0xBED4, 0x468D, 0xD967, 0x4B72, 0xDE94, 0xD498, 0xE8B0, 0x4A85,
- 0x6BBB, 0x2AC5, 0xE54F, 0x16ED, 0xC586, 0xD79A, 0x5566, 0x9411,
- 0xCF8A, 0x10E9, 0x0604, 0x81FE, 0xF0A0, 0x4478, 0xBA25, 0xE34B,
- 0xF3A2, 0xFE5D, 0xC080, 0x8A05, 0xAD3F, 0xBC21, 0x4870, 0x04F1,
- 0xDF63, 0xC177, 0x75AF, 0x6342, 0x3020, 0x1AE5, 0x0EFD, 0x6DBF,
- 0x4C81, 0x1418, 0x3526, 0x2FC3, 0xE1BE, 0xA235, 0xCC88, 0x392E,
- 0x5793, 0xF255, 0x82FC, 0x477A, 0xACC8, 0xE7BA, 0x2B32, 0x95E6,
- 0xA0C0, 0x9819, 0xD19E, 0x7FA3, 0x6644, 0x7E54, 0xAB3B, 0x830B,
- 0xCA8C, 0x29C7, 0xD36B, 0x3C28, 0x79A7, 0xE2BC, 0x1D16, 0x76AD,
- 0x3BDB, 0x5664, 0x4E74, 0x1E14, 0xDB92, 0x0A0C, 0x6C48, 0xE4B8,
- 0x5D9F, 0x6EBD, 0xEF43, 0xA6C4, 0xA839, 0xA431, 0x37D3, 0x8BF2,
- 0x32D5, 0x438B, 0x596E, 0xB7DA, 0x8C01, 0x64B1, 0xD29C, 0xE049,
- 0xB4D8, 0xFAAC, 0x07F3, 0x25CF, 0xAFCA, 0x8EF4, 0xE947, 0x1810,
- 0xD56F, 0x88F0, 0x6F4A, 0x725C, 0x2438, 0xF157, 0xC773, 0x5197,
- 0x23CB, 0x7CA1, 0x9CE8, 0x213E, 0xDD96, 0xDC61, 0x860D, 0x850F,
- 0x90E0, 0x427C, 0xC471, 0xAACC, 0xD890, 0x0506, 0x01F7, 0x121C,
- 0xA3C2, 0x5F6A, 0xF9AE, 0xD069, 0x9117, 0x5899, 0x273A, 0xB927,
- 0x38D9, 0x13EB, 0xB32B, 0x3322, 0xBBD2, 0x70A9, 0x8907, 0xA733,
- 0xB62D, 0x223C, 0x9215, 0x20C9, 0x4987, 0xFFAA, 0x7850, 0x7AA5,
- 0x8F03, 0xF859, 0x8009, 0x171A, 0xDA65, 0x31D7, 0xC684, 0xB8D0,
- 0xC382, 0xB029, 0x775A, 0x111E, 0xCB7B, 0xFCA8, 0xD66D, 0x3A2C,
- }
-};
-
-/*
- **********************************************************************
- * Routine: Phase 1 -- generate P1K, given TA, TK, IV32
- *
- * Inputs:
- * tk[] = temporal key [128 bits]
- * ta[] = transmitter's MAC address [ 48 bits]
- * iv32 = upper 32 bits of IV [ 32 bits]
- * Output:
- * p1k[] = Phase 1 key [ 80 bits]
- *
- * Note:
- * This function only needs to be called every 2**16 packets,
- * although in theory it could be called every packet.
- *
- **********************************************************************
- */
-static void phase1(u16 *p1k, const u8 *tk, const u8 *ta, u32 iv32)
-{
- sint i;
-
- /* Initialize the 80 bits of P1K[] from IV32 and TA[0..5] */
- p1k[0] = Lo16(iv32);
- p1k[1] = Hi16(iv32);
- p1k[2] = Mk16(ta[1], ta[0]); /* use TA[] as little-endian */
- p1k[3] = Mk16(ta[3], ta[2]);
- p1k[4] = Mk16(ta[5], ta[4]);
- /* Now compute an unbalanced Feistel cipher with 80-bit block */
- /* size on the 80-bit block P1K[], using the 128-bit key TK[] */
- for (i = 0; i < PHASE1_LOOP_CNT; i++) { /* Each add is mod 2**16 */
- p1k[0] += _S_(p1k[4] ^ TK16((i & 1) + 0));
- p1k[1] += _S_(p1k[0] ^ TK16((i & 1) + 2));
- p1k[2] += _S_(p1k[1] ^ TK16((i & 1) + 4));
- p1k[3] += _S_(p1k[2] ^ TK16((i & 1) + 6));
- p1k[4] += _S_(p1k[3] ^ TK16((i & 1) + 0));
- p1k[4] += (unsigned short)i; /* avoid "slide attacks" */
- }
-}
-
-/*
- **********************************************************************
- * Routine: Phase 2 -- generate RC4KEY, given TK, P1K, IV16
- *
- * Inputs:
- * tk[] = Temporal key [128 bits]
- * p1k[] = Phase 1 output key [ 80 bits]
- * iv16 = low 16 bits of IV counter [ 16 bits]
- * Output:
- * rc4key[] = the key used to encrypt the packet [128 bits]
- *
- * Note:
- * The value {TA,IV32,IV16} for Phase1/Phase2 must be unique
- * across all packets using the same key TK value. Then, for a
- * given value of TK[], this TKIP48 construction guarantees that
- * the final RC4KEY value is unique across all packets.
- *
- * Suggested implementation optimization: if PPK[] is "overlaid"
- * appropriately on RC4KEY[], there is no need for the final
- * for loop below that copies the PPK[] result into RC4KEY[].
- *
- **********************************************************************
- */
-static void phase2(u8 *rc4key, const u8 *tk, const u16 *p1k, u16 iv16)
-{
- sint i;
- u16 PPK[6]; /* temporary key for mixing */
-
- /* Note: all adds in the PPK[] equations below are mod 2**16 */
- for (i = 0; i < 5; i++)
- PPK[i] = p1k[i]; /* first, copy P1K to PPK */
- PPK[5] = p1k[4] + iv16; /* next, add in IV16 */
- /* Bijective non-linear mixing of the 96 bits of PPK[0..5] */
- PPK[0] += _S_(PPK[5] ^ TK16(0)); /* Mix key in each "round" */
- PPK[1] += _S_(PPK[0] ^ TK16(1));
- PPK[2] += _S_(PPK[1] ^ TK16(2));
- PPK[3] += _S_(PPK[2] ^ TK16(3));
- PPK[4] += _S_(PPK[3] ^ TK16(4));
- PPK[5] += _S_(PPK[4] ^ TK16(5)); /* Total # S-box lookups == 6 */
- /* Final sweep: bijective, "linear". Rotates kill LSB correlations */
- PPK[0] += RotR1(PPK[5] ^ TK16(6));
- PPK[1] += RotR1(PPK[0] ^ TK16(7)); /* Use all of TK[] in Phase2 */
- PPK[2] += RotR1(PPK[1]);
- PPK[3] += RotR1(PPK[2]);
- PPK[4] += RotR1(PPK[3]);
- PPK[5] += RotR1(PPK[4]);
- /* Note: At this point, for a given key TK[0..15], the 96-bit output */
- /* value PPK[0..5] is guaranteed to be unique, as a function */
- /* of the 96-bit "input" value {TA,IV32,IV16}. That is, P1K */
- /* is now a keyed permutation of {TA,IV32,IV16}. */
- /* Set RC4KEY[0..3], which includes "cleartext" portion of RC4 key */
- rc4key[0] = Hi8(iv16); /* RC4KEY[0..2] is the WEP IV */
- rc4key[1] = (Hi8(iv16) | 0x20) & 0x7F; /* Help avoid weak (FMS) keys */
- rc4key[2] = Lo8(iv16);
- rc4key[3] = Lo8((PPK[5] ^ TK16(0)) >> 1);
- /* Copy 96 bits of PPK[0..5] to RC4KEY[4..15] (little-endian) */
- for (i = 0; i < 6; i++) {
- rc4key[4 + 2 * i] = Lo8(PPK[i]);
- rc4key[5 + 2 * i] = Hi8(PPK[i]);
- }
-}
-
-/*The hlen isn't include the IV*/
-u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe)
-{ /* exclude ICV */
- u16 pnl;
- u32 pnh;
- u8 rc4key[16];
- u8 ttkey[16];
- u8 crc[4];
- struct arc4context mycontext;
- u32 curfragnum, length;
-
- u8 *pframe, *payload, *iv, *prwskey;
- union pn48 txpn;
- struct sta_info *stainfo;
- struct pkt_attrib *pattrib = &((struct xmit_frame *)pxmitframe)->attrib;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- u32 res = _SUCCESS;
-
- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
- return _FAIL;
-
- pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
- /* 4 start to encrypt each fragment */
- if (pattrib->encrypt == _TKIP_) {
- if (pattrib->psta)
- stainfo = pattrib->psta;
- else
- stainfo = r8712_get_stainfo(&padapter->stapriv,
- &pattrib->ra[0]);
- if (stainfo) {
- prwskey = &stainfo->x_UncstKey.skey[0];
- for (curfragnum = 0; curfragnum < pattrib->nr_frags;
- curfragnum++) {
- iv = pframe + pattrib->hdrlen;
- payload = pframe + pattrib->iv_len +
- pattrib->hdrlen;
- GET_TKIP_PN(iv, txpn);
- pnl = (u16)(txpn.val);
- pnh = (u32)(txpn.val >> 16);
- phase1((u16 *)&ttkey[0], prwskey,
- &pattrib->ta[0], pnh);
- phase2(&rc4key[0], prwskey, (u16 *)&ttkey[0],
- pnl);
- if ((curfragnum + 1) == pattrib->nr_frags) {
- /* 4 the last fragment */
- length = pattrib->last_txcmdsz -
- pattrib->hdrlen -
- pattrib->iv_len -
- pattrib->icv_len;
- *((__le32 *)crc) = cpu_to_le32(
- getcrc32(payload, length));
- arcfour_init(&mycontext, rc4key, 16);
- arcfour_encrypt(&mycontext, payload,
- payload, length);
- arcfour_encrypt(&mycontext, payload +
- length, crc, 4);
- } else {
- length = pxmitpriv->frag_len -
- pattrib->hdrlen -
- pattrib->iv_len -
- pattrib->icv_len;
- *((__le32 *)crc) = cpu_to_le32(getcrc32(
- payload, length));
- arcfour_init(&mycontext, rc4key, 16);
- arcfour_encrypt(&mycontext, payload,
- payload, length);
- arcfour_encrypt(&mycontext,
- payload + length, crc,
- 4);
- pframe += pxmitpriv->frag_len;
- pframe = (u8 *)RND4((addr_t)(pframe));
- }
- }
- } else {
- res = _FAIL;
- }
- }
- return res;
-}
-
-/* The hlen doesn't include the IV */
-void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe)
-{ /* exclude ICV */
- u16 pnl;
- u32 pnh;
- u8 rc4key[16];
- u8 ttkey[16];
- u8 crc[4];
- struct arc4context mycontext;
- u32 length;
- u8 *pframe, *payload, *iv, *prwskey, idx = 0;
- union pn48 txpn;
- struct sta_info *stainfo;
- struct rx_pkt_attrib *prxattrib = &((union recv_frame *)
- precvframe)->u.hdr.attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- pframe = (unsigned char *)((union recv_frame *)
- precvframe)->u.hdr.rx_data;
- /* 4 start to decrypt recvframe */
- if (prxattrib->encrypt == _TKIP_) {
- stainfo = r8712_get_stainfo(&padapter->stapriv,
- &prxattrib->ta[0]);
- if (stainfo) {
- iv = pframe + prxattrib->hdrlen;
- payload = pframe + prxattrib->iv_len +
- prxattrib->hdrlen;
- length = ((union recv_frame *)precvframe)->
- u.hdr.len - prxattrib->hdrlen -
- prxattrib->iv_len;
- if (is_multicast_ether_addr(prxattrib->ra)) {
- idx = iv[3];
- prwskey = &psecuritypriv->XGrpKey[
- ((idx >> 6) & 0x3) - 1].skey[0];
- if (!psecuritypriv->binstallGrpkey)
- return;
- } else {
- prwskey = &stainfo->x_UncstKey.skey[0];
- }
- GET_TKIP_PN(iv, txpn);
- pnl = (u16)(txpn.val);
- pnh = (u32)(txpn.val >> 16);
- phase1((u16 *)&ttkey[0], prwskey, &prxattrib->ta[0],
- pnh);
- phase2(&rc4key[0], prwskey, (unsigned short *)
- &ttkey[0], pnl);
- /* 4 decrypt payload include icv */
- arcfour_init(&mycontext, rc4key, 16);
- arcfour_encrypt(&mycontext, payload, payload, length);
- *((__le32 *)crc) = cpu_to_le32(getcrc32(payload,
- length - 4));
- }
- }
-}
-
-/* 3 =====AES related===== */
-
-#define MAX_MSG_SIZE 2048
-/*****************************/
-/******** SBOX Table *********/
-/*****************************/
-
-static const u8 sbox_table[256] = {
- 0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
- 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
- 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
- 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
- 0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
- 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
- 0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
- 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
- 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
- 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
- 0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
- 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
- 0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
- 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
- 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
- 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
- 0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
- 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
- 0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
- 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
- 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
- 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
- 0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
- 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
- 0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
- 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
- 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
- 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
- 0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
- 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
- 0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
- 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16
-};
-
-/****************************************/
-/* aes128k128d() */
-/* Performs a 128 bit AES encrypt with */
-/* 128 bit data. */
-/****************************************/
-static void xor_128(u8 *a, u8 *b, u8 *out)
-{
- sint i;
-
- for (i = 0; i < 16; i++)
- out[i] = a[i] ^ b[i];
-}
-
-static void xor_32(u8 *a, u8 *b, u8 *out)
-{
- sint i;
-
- for (i = 0; i < 4; i++)
- out[i] = a[i] ^ b[i];
-}
-
-static u8 sbox(u8 a)
-{
- return sbox_table[(sint)a];
-}
-
-static void next_key(u8 *key, sint round)
-{
- u8 rcon;
- u8 sbox_key[4];
- static const u8 rcon_table[12] = {
- 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
- 0x1b, 0x36, 0x36, 0x36
- };
-
- sbox_key[0] = sbox(key[13]);
- sbox_key[1] = sbox(key[14]);
- sbox_key[2] = sbox(key[15]);
- sbox_key[3] = sbox(key[12]);
- rcon = rcon_table[round];
- xor_32(&key[0], sbox_key, &key[0]);
- key[0] = key[0] ^ rcon;
- xor_32(&key[4], &key[0], &key[4]);
- xor_32(&key[8], &key[4], &key[8]);
- xor_32(&key[12], &key[8], &key[12]);
-}
-
-static void byte_sub(u8 *in, u8 *out)
-{
- sint i;
-
- for (i = 0; i < 16; i++)
- out[i] = sbox(in[i]);
-}
-
-static void shift_row(u8 *in, u8 *out)
-{
- out[0] = in[0];
- out[1] = in[5];
- out[2] = in[10];
- out[3] = in[15];
- out[4] = in[4];
- out[5] = in[9];
- out[6] = in[14];
- out[7] = in[3];
- out[8] = in[8];
- out[9] = in[13];
- out[10] = in[2];
- out[11] = in[7];
- out[12] = in[12];
- out[13] = in[1];
- out[14] = in[6];
- out[15] = in[11];
-}
-
-static void mix_column(u8 *in, u8 *out)
-{
- sint i;
- u8 add1b[4];
- u8 add1bf7[4];
- u8 rotl[4];
- u8 swap_halves[4];
- u8 andf7[4];
- u8 rotr[4];
- u8 temp[4];
- u8 tempb[4];
-
- for (i = 0; i < 4; i++) {
- if ((in[i] & 0x80) == 0x80)
- add1b[i] = 0x1b;
- else
- add1b[i] = 0x00;
- }
- swap_halves[0] = in[2]; /* Swap halves */
- swap_halves[1] = in[3];
- swap_halves[2] = in[0];
- swap_halves[3] = in[1];
- rotl[0] = in[3]; /* Rotate left 8 bits */
- rotl[1] = in[0];
- rotl[2] = in[1];
- rotl[3] = in[2];
- andf7[0] = in[0] & 0x7f;
- andf7[1] = in[1] & 0x7f;
- andf7[2] = in[2] & 0x7f;
- andf7[3] = in[3] & 0x7f;
- for (i = 3; i > 0; i--) { /* logical shift left 1 bit */
- andf7[i] = andf7[i] << 1;
- if ((andf7[i - 1] & 0x80) == 0x80)
- andf7[i] = (andf7[i] | 0x01);
- }
- andf7[0] = andf7[0] << 1;
- andf7[0] = andf7[0] & 0xfe;
- xor_32(add1b, andf7, add1bf7);
- xor_32(in, add1bf7, rotr);
- temp[0] = rotr[0]; /* Rotate right 8 bits */
- rotr[0] = rotr[1];
- rotr[1] = rotr[2];
- rotr[2] = rotr[3];
- rotr[3] = temp[0];
- xor_32(add1bf7, rotr, temp);
- xor_32(swap_halves, rotl, tempb);
- xor_32(temp, tempb, out);
-}
-
-static void aes128k128d(u8 *key, u8 *data, u8 *ciphertext)
-{
- sint round;
- sint i;
- u8 intermediatea[16];
- u8 intermediateb[16];
- u8 round_key[16];
-
- for (i = 0; i < 16; i++)
- round_key[i] = key[i];
- for (round = 0; round < 11; round++) {
- if (round == 0) {
- xor_128(round_key, data, ciphertext);
- next_key(round_key, round);
- } else if (round == 10) {
- byte_sub(ciphertext, intermediatea);
- shift_row(intermediatea, intermediateb);
- xor_128(intermediateb, round_key, ciphertext);
- } else { /* 1 - 9 */
- byte_sub(ciphertext, intermediatea);
- shift_row(intermediatea, intermediateb);
- mix_column(&intermediateb[0], &intermediatea[0]);
- mix_column(&intermediateb[4], &intermediatea[4]);
- mix_column(&intermediateb[8], &intermediatea[8]);
- mix_column(&intermediateb[12], &intermediatea[12]);
- xor_128(intermediatea, round_key, ciphertext);
- next_key(round_key, round);
- }
- }
-}
-
-/************************************************/
-/* construct_mic_iv() */
-/* Builds the MIC IV from header fields and PN */
-/************************************************/
-static void construct_mic_iv(u8 *mic_iv, sint qc_exists, sint a4_exists,
- u8 *mpdu, uint payload_length, u8 *pn_vector)
-{
- sint i;
-
- mic_iv[0] = 0x59;
- if (qc_exists && a4_exists)
- mic_iv[1] = mpdu[30] & 0x0f; /* QoS_TC */
- if (qc_exists && !a4_exists)
- mic_iv[1] = mpdu[24] & 0x0f; /* mute bits 7-4 */
- if (!qc_exists)
- mic_iv[1] = 0x00;
- for (i = 2; i < 8; i++)
- mic_iv[i] = mpdu[i + 8];
- for (i = 8; i < 14; i++)
- mic_iv[i] = pn_vector[13 - i]; /* mic_iv[8:13] = PN[5:0] */
- mic_iv[14] = (unsigned char)(payload_length / 256);
- mic_iv[15] = (unsigned char)(payload_length % 256);
-}
-
-/************************************************/
-/* construct_mic_header1() */
-/* Builds the first MIC header block from */
-/* header fields. */
-/************************************************/
-static void construct_mic_header1(u8 *mic_header1, sint header_length, u8 *mpdu)
-{
- mic_header1[0] = (u8)((header_length - 2) / 256);
- mic_header1[1] = (u8)((header_length - 2) % 256);
- mic_header1[2] = mpdu[0] & 0xcf; /* Mute CF poll & CF ack bits */
- /* Mute retry, more data and pwr mgt bits */
- mic_header1[3] = mpdu[1] & 0xc7;
- mic_header1[4] = mpdu[4]; /* A1 */
- mic_header1[5] = mpdu[5];
- mic_header1[6] = mpdu[6];
- mic_header1[7] = mpdu[7];
- mic_header1[8] = mpdu[8];
- mic_header1[9] = mpdu[9];
- mic_header1[10] = mpdu[10]; /* A2 */
- mic_header1[11] = mpdu[11];
- mic_header1[12] = mpdu[12];
- mic_header1[13] = mpdu[13];
- mic_header1[14] = mpdu[14];
- mic_header1[15] = mpdu[15];
-}
-
-/************************************************/
-/* construct_mic_header2() */
-/* Builds the last MIC header block from */
-/* header fields. */
-/************************************************/
-static void construct_mic_header2(u8 *mic_header2, u8 *mpdu, sint a4_exists,
- sint qc_exists)
-{
- sint i;
-
- for (i = 0; i < 16; i++)
- mic_header2[i] = 0x00;
- mic_header2[0] = mpdu[16]; /* A3 */
- mic_header2[1] = mpdu[17];
- mic_header2[2] = mpdu[18];
- mic_header2[3] = mpdu[19];
- mic_header2[4] = mpdu[20];
- mic_header2[5] = mpdu[21];
- mic_header2[6] = 0x00;
- mic_header2[7] = 0x00; /* mpdu[23]; */
- if (!qc_exists && a4_exists)
- for (i = 0; i < 6; i++)
- mic_header2[8 + i] = mpdu[24 + i]; /* A4 */
- if (qc_exists && !a4_exists) {
- mic_header2[8] = mpdu[24] & 0x0f; /* mute bits 15 - 4 */
- mic_header2[9] = mpdu[25] & 0x00;
- }
- if (qc_exists && a4_exists) {
- for (i = 0; i < 6; i++)
- mic_header2[8 + i] = mpdu[24 + i]; /* A4 */
- mic_header2[14] = mpdu[30] & 0x0f;
- mic_header2[15] = mpdu[31] & 0x00;
- }
-}
-
-/************************************************/
-/* construct_mic_header2() */
-/* Builds the last MIC header block from */
-/* header fields. */
-/************************************************/
-static void construct_ctr_preload(u8 *ctr_preload,
- sint a4_exists, sint qc_exists,
- u8 *mpdu, u8 *pn_vector, sint c)
-{
- sint i;
-
- for (i = 0; i < 16; i++)
- ctr_preload[i] = 0x00;
- i = 0;
- ctr_preload[0] = 0x01; /* flag */
- if (qc_exists && a4_exists)
- ctr_preload[1] = mpdu[30] & 0x0f;
- if (qc_exists && !a4_exists)
- ctr_preload[1] = mpdu[24] & 0x0f;
- for (i = 2; i < 8; i++)
- ctr_preload[i] = mpdu[i + 8];
- for (i = 8; i < 14; i++)
- ctr_preload[i] = pn_vector[13 - i];
- ctr_preload[14] = (unsigned char)(c / 256); /* Ctr */
- ctr_preload[15] = (unsigned char)(c % 256);
-}
-
-/************************************/
-/* bitwise_xor() */
-/* A 128 bit, bitwise exclusive or */
-/************************************/
-static void bitwise_xor(u8 *ina, u8 *inb, u8 *out)
-{
- sint i;
-
- for (i = 0; i < 16; i++)
- out[i] = ina[i] ^ inb[i];
-}
-
-static void aes_cipher(u8 *key, uint hdrlen,
- u8 *pframe, uint plen)
-{
- uint qc_exists, a4_exists, i, j, payload_remainder;
- uint num_blocks, payload_index;
-
- u8 pn_vector[6];
- u8 mic_iv[16];
- u8 mic_header1[16];
- u8 mic_header2[16];
- u8 ctr_preload[16];
-
- /* Intermediate Buffers */
- u8 chain_buffer[16];
- u8 aes_out[16];
- u8 padded_buffer[16];
- u8 mic[8];
- u16 frtype = GetFrameType(pframe);
- u16 frsubtype = GetFrameSubType(pframe);
-
- frsubtype >>= 4;
- memset((void *)mic_iv, 0, 16);
- memset((void *)mic_header1, 0, 16);
- memset((void *)mic_header2, 0, 16);
- memset((void *)ctr_preload, 0, 16);
- memset((void *)chain_buffer, 0, 16);
- memset((void *)aes_out, 0, 16);
- memset((void *)padded_buffer, 0, 16);
-
- if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
- a4_exists = 0;
- else
- a4_exists = 1;
-
- if ((frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACK)) ||
- (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFPOLL)) ||
- (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACKPOLL))) {
- qc_exists = 1;
- if (hdrlen != WLAN_HDR_A3_QOS_LEN)
- hdrlen += 2;
- } else if ((frsubtype == 0x08) ||
- (frsubtype == 0x09) ||
- (frsubtype == 0x0a) ||
- (frsubtype == 0x0b)) {
- if (hdrlen != WLAN_HDR_A3_QOS_LEN)
- hdrlen += 2;
- qc_exists = 1;
- } else {
- qc_exists = 0;
- }
- pn_vector[0] = pframe[hdrlen];
- pn_vector[1] = pframe[hdrlen + 1];
- pn_vector[2] = pframe[hdrlen + 4];
- pn_vector[3] = pframe[hdrlen + 5];
- pn_vector[4] = pframe[hdrlen + 6];
- pn_vector[5] = pframe[hdrlen + 7];
- construct_mic_iv(mic_iv, qc_exists, a4_exists, pframe, plen, pn_vector);
- construct_mic_header1(mic_header1, hdrlen, pframe);
- construct_mic_header2(mic_header2, pframe, a4_exists, qc_exists);
- payload_remainder = plen % 16;
- num_blocks = plen / 16;
- /* Find start of payload */
- payload_index = hdrlen + 8;
- /* Calculate MIC */
- aes128k128d(key, mic_iv, aes_out);
- bitwise_xor(aes_out, mic_header1, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- bitwise_xor(aes_out, mic_header2, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- for (i = 0; i < num_blocks; i++) {
- bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
- payload_index += 16;
- aes128k128d(key, chain_buffer, aes_out);
- }
- /* Add on the final payload block if it needs padding */
- if (payload_remainder > 0) {
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = pframe[payload_index++];
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- }
- for (j = 0; j < 8; j++)
- mic[j] = aes_out[j];
- /* Insert MIC into payload */
- for (j = 0; j < 8; j++)
- pframe[payload_index + j] = mic[j];
- payload_index = hdrlen + 8;
- for (i = 0; i < num_blocks; i++) {
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, i + 1);
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
- for (j = 0; j < 16; j++)
- pframe[payload_index++] = chain_buffer[j];
- }
- if (payload_remainder > 0) { /* If short final block, then pad it,*/
- /* encrypt and copy unpadded part back */
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, num_blocks + 1);
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = pframe[payload_index + j];
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- for (j = 0; j < payload_remainder; j++)
- pframe[payload_index++] = chain_buffer[j];
- }
- /* Encrypt the MIC */
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, 0);
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < 8; j++)
- padded_buffer[j] = pframe[j + hdrlen + 8 + plen];
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- for (j = 0; j < 8; j++)
- pframe[payload_index++] = chain_buffer[j];
-}
-
-u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe)
-{ /* exclude ICV */
- /* Intermediate Buffers */
- sint curfragnum, length;
- u8 *pframe, *prwskey;
- struct sta_info *stainfo;
- struct pkt_attrib *pattrib = &((struct xmit_frame *)
- pxmitframe)->attrib;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- u32 res = _SUCCESS;
-
- if (((struct xmit_frame *)pxmitframe)->buf_addr == NULL)
- return _FAIL;
- pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + TXDESC_OFFSET;
- /* 4 start to encrypt each fragment */
- if (pattrib->encrypt == _AES_) {
- if (pattrib->psta)
- stainfo = pattrib->psta;
- else
- stainfo = r8712_get_stainfo(&padapter->stapriv,
- &pattrib->ra[0]);
- if (stainfo) {
- prwskey = &stainfo->x_UncstKey.skey[0];
- for (curfragnum = 0; curfragnum < pattrib->nr_frags;
- curfragnum++) {
- if ((curfragnum + 1) == pattrib->nr_frags) {
- length = pattrib->last_txcmdsz -
- pattrib->hdrlen -
- pattrib->iv_len -
- pattrib->icv_len;
- aes_cipher(prwskey, pattrib->hdrlen,
- pframe, length);
- } else {
- length = pxmitpriv->frag_len -
- pattrib->hdrlen -
- pattrib->iv_len -
- pattrib->icv_len;
- aes_cipher(prwskey, pattrib->hdrlen,
- pframe, length);
- pframe += pxmitpriv->frag_len;
- pframe = (u8 *)RND4((addr_t)(pframe));
- }
- }
- } else {
- res = _FAIL;
- }
- }
- return res;
-}
-
-static void aes_decipher(u8 *key, uint hdrlen,
- u8 *pframe, uint plen)
-{
- static u8 message[MAX_MSG_SIZE];
- uint qc_exists, a4_exists, i, j, payload_remainder;
- uint num_blocks, payload_index;
- u8 pn_vector[6];
- u8 mic_iv[16];
- u8 mic_header1[16];
- u8 mic_header2[16];
- u8 ctr_preload[16];
- /* Intermediate Buffers */
- u8 chain_buffer[16];
- u8 aes_out[16];
- u8 padded_buffer[16];
- u8 mic[8];
- uint frtype = GetFrameType(pframe);
- uint frsubtype = GetFrameSubType(pframe);
-
- frsubtype >>= 4;
- memset((void *)mic_iv, 0, 16);
- memset((void *)mic_header1, 0, 16);
- memset((void *)mic_header2, 0, 16);
- memset((void *)ctr_preload, 0, 16);
- memset((void *)chain_buffer, 0, 16);
- memset((void *)aes_out, 0, 16);
- memset((void *)padded_buffer, 0, 16);
- /* start to decrypt the payload */
- /*(plen including llc, payload and mic) */
- num_blocks = (plen - 8) / 16;
- payload_remainder = (plen - 8) % 16;
- pn_vector[0] = pframe[hdrlen];
- pn_vector[1] = pframe[hdrlen + 1];
- pn_vector[2] = pframe[hdrlen + 4];
- pn_vector[3] = pframe[hdrlen + 5];
- pn_vector[4] = pframe[hdrlen + 6];
- pn_vector[5] = pframe[hdrlen + 7];
- if ((hdrlen == WLAN_HDR_A3_LEN) || (hdrlen == WLAN_HDR_A3_QOS_LEN))
- a4_exists = 0;
- else
- a4_exists = 1;
- if ((frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACK)) ||
- (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFPOLL)) ||
- (frtype == (IEEE80211_FTYPE_DATA | IEEE80211_STYPE_DATA_CFACKPOLL))) {
- qc_exists = 1;
- if (hdrlen != WLAN_HDR_A3_QOS_LEN)
- hdrlen += 2;
- } else if ((frsubtype == 0x08) ||
- (frsubtype == 0x09) ||
- (frsubtype == 0x0a) ||
- (frsubtype == 0x0b)) {
- if (hdrlen != WLAN_HDR_A3_QOS_LEN)
- hdrlen += 2;
- qc_exists = 1;
- } else {
- qc_exists = 0;
- }
- /* now, decrypt pframe with hdrlen offset and plen long */
- payload_index = hdrlen + 8; /* 8 is for extiv */
- for (i = 0; i < num_blocks; i++) {
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, i + 1);
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, &pframe[payload_index], chain_buffer);
- for (j = 0; j < 16; j++)
- pframe[payload_index++] = chain_buffer[j];
- }
- if (payload_remainder > 0) { /* If short final block, pad it,*/
- /* encrypt it and copy the unpadded part back */
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- pframe, pn_vector, num_blocks + 1);
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = pframe[payload_index + j];
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- for (j = 0; j < payload_remainder; j++)
- pframe[payload_index++] = chain_buffer[j];
- }
- /* start to calculate the mic */
- memcpy((void *)message, pframe, (hdrlen + plen + 8));
- pn_vector[0] = pframe[hdrlen];
- pn_vector[1] = pframe[hdrlen + 1];
- pn_vector[2] = pframe[hdrlen + 4];
- pn_vector[3] = pframe[hdrlen + 5];
- pn_vector[4] = pframe[hdrlen + 6];
- pn_vector[5] = pframe[hdrlen + 7];
- construct_mic_iv(mic_iv, qc_exists, a4_exists, message, plen - 8,
- pn_vector);
- construct_mic_header1(mic_header1, hdrlen, message);
- construct_mic_header2(mic_header2, message, a4_exists, qc_exists);
- payload_remainder = (plen - 8) % 16;
- num_blocks = (plen - 8) / 16;
- /* Find start of payload */
- payload_index = hdrlen + 8;
- /* Calculate MIC */
- aes128k128d(key, mic_iv, aes_out);
- bitwise_xor(aes_out, mic_header1, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- bitwise_xor(aes_out, mic_header2, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- for (i = 0; i < num_blocks; i++) {
- bitwise_xor(aes_out, &message[payload_index], chain_buffer);
- payload_index += 16;
- aes128k128d(key, chain_buffer, aes_out);
- }
- /* Add on the final payload block if it needs padding */
- if (payload_remainder > 0) {
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = message[payload_index++];
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- aes128k128d(key, chain_buffer, aes_out);
- }
- for (j = 0; j < 8; j++)
- mic[j] = aes_out[j];
- /* Insert MIC into payload */
- for (j = 0; j < 8; j++)
- message[payload_index + j] = mic[j];
- payload_index = hdrlen + 8;
- for (i = 0; i < num_blocks; i++) {
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- message, pn_vector, i + 1);
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, &message[payload_index], chain_buffer);
- for (j = 0; j < 16; j++)
- message[payload_index++] = chain_buffer[j];
- }
- if (payload_remainder > 0) { /* If short final block, pad it,*/
- /* encrypt and copy unpadded part back */
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists,
- message, pn_vector, num_blocks + 1);
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < payload_remainder; j++)
- padded_buffer[j] = message[payload_index + j];
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- for (j = 0; j < payload_remainder; j++)
- message[payload_index++] = chain_buffer[j];
- }
- /* Encrypt the MIC */
- construct_ctr_preload(ctr_preload, a4_exists, qc_exists, message,
- pn_vector, 0);
- for (j = 0; j < 16; j++)
- padded_buffer[j] = 0x00;
- for (j = 0; j < 8; j++)
- padded_buffer[j] = message[j + hdrlen + plen];
- aes128k128d(key, ctr_preload, aes_out);
- bitwise_xor(aes_out, padded_buffer, chain_buffer);
- for (j = 0; j < 8; j++)
- message[payload_index++] = chain_buffer[j];
- /* compare the mic */
-}
-
-void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe)
-{ /* exclude ICV */
- /* Intermediate Buffers */
- sint length;
- u8 *pframe, *prwskey, *iv, idx;
- struct sta_info *stainfo;
- struct rx_pkt_attrib *prxattrib = &((union recv_frame *)
- precvframe)->u.hdr.attrib;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
-
- pframe = (unsigned char *)((union recv_frame *)precvframe)->
- u.hdr.rx_data;
- /* 4 start to encrypt each fragment */
- if (prxattrib->encrypt == _AES_) {
- stainfo = r8712_get_stainfo(&padapter->stapriv,
- &prxattrib->ta[0]);
- if (stainfo) {
- if (is_multicast_ether_addr(prxattrib->ra)) {
- iv = pframe + prxattrib->hdrlen;
- idx = iv[3];
- prwskey = &psecuritypriv->XGrpKey[
- ((idx >> 6) & 0x3) - 1].skey[0];
- if (!psecuritypriv->binstallGrpkey)
- return;
-
- } else {
- prwskey = &stainfo->x_UncstKey.skey[0];
- }
- length = ((union recv_frame *)precvframe)->
- u.hdr.len - prxattrib->hdrlen -
- prxattrib->iv_len;
- aes_decipher(prwskey, prxattrib->hdrlen, pframe,
- length);
- }
- }
-}
-
-void r8712_use_tkipkey_handler(struct timer_list *t)
-{
- struct _adapter *padapter =
- from_timer(padapter, t, securitypriv.tkip_timer);
-
- padapter->securitypriv.busetkipkey = true;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_security.h b/drivers/staging/rtl8712/rtl871x_security.h
deleted file mode 100644
index 8461b7f05359..000000000000
--- a/drivers/staging/rtl8712/rtl871x_security.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __RTL871X_SECURITY_H_
-#define __RTL871X_SECURITY_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#define _NO_PRIVACY_ 0x0
-#define _WEP40_ 0x1
-#define _TKIP_ 0x2
-#define _TKIP_WTMIC_ 0x3
-#define _AES_ 0x4
-#define _WEP104_ 0x5
-
-#define _WPA_IE_ID_ 0xdd
-#define _WPA2_IE_ID_ 0x30
-
-#ifndef Ndis802_11AuthModeWPA2
-#define Ndis802_11AuthModeWPA2 (Ndis802_11AuthModeWPANone + 1)
-#endif
-
-#ifndef Ndis802_11AuthModeWPA2PSK
-#define Ndis802_11AuthModeWPA2PSK (Ndis802_11AuthModeWPANone + 2)
-#endif
-
-union pn48 {
- u64 val;
-#if defined(__BIG_ENDIAN)
- struct {
- u8 TSC7;
- u8 TSC6;
- u8 TSC5;
- u8 TSC4;
- u8 TSC3;
- u8 TSC2;
- u8 TSC1;
- u8 TSC0;
- } _byte_;
-#else
- struct {
- u8 TSC0;
- u8 TSC1;
- u8 TSC2;
- u8 TSC3;
- u8 TSC4;
- u8 TSC5;
- u8 TSC6;
- u8 TSC7;
- } _byte_;
-#endif
-};
-
-union Keytype {
- u8 skey[16];
- u32 lkey[4];
-};
-
-struct RT_PMKID_LIST {
- u8 bUsed;
- u8 Bssid[6];
- u8 PMKID[16];
- u8 SsidBuf[33];
- u8 *ssid_octet;
- u16 ssid_length;
-};
-
-struct security_priv {
- u32 AuthAlgrthm; /* 802.11 auth, could be open, shared,
- * 8021x and authswitch
- */
- u32 PrivacyAlgrthm; /* This specify the privacy for shared
- * auth. algorithm.
- */
- u32 PrivacyKeyIndex; /* this is only valid for legendary
- * wep, 0~3 for key id.
- */
- union Keytype DefKey[4]; /* this is only valid for def. key */
- u32 DefKeylen[4];
- u32 XGrpPrivacy; /* This specify the privacy algthm.
- * used for Grp key
- */
- u32 XGrpKeyid; /* key id used for Grp Key */
- union Keytype XGrpKey[2]; /* 802.1x Group Key, for
- * inx0 and inx1
- */
- union Keytype XGrptxmickey[2];
- union Keytype XGrprxmickey[2];
- union pn48 Grptxpn; /* PN48 used for Grp Key xmit. */
- union pn48 Grprxpn; /* PN48 used for Grp Key recv. */
- u8 wps_hw_pbc_pressed;/*for hw pbc pressed*/
- u8 wps_phase;/*for wps*/
- u8 wps_ie[MAX_WPA_IE_LEN << 2];
- int wps_ie_len;
- u8 binstallGrpkey;
- u8 busetkipkey;
- struct timer_list tkip_timer;
- u8 bcheck_grpkey;
- u8 bgrpkey_handshake;
- s32 sw_encrypt; /* from registry_priv */
- s32 sw_decrypt; /* from registry_priv */
- s32 hw_decrypted; /* if the rx packets is hw_decrypted==false,
- * it means the hw has not been ready.
- */
- u32 ndisauthtype; /* keeps the auth_type & enc_status from upper
- * layer ioctl(wpa_supplicant or wzc)
- */
- u32 ndisencryptstatus;
- struct wlan_bssid_ex sec_bss; /* for joinbss (h2c buffer) usage */
- struct NDIS_802_11_WEP ndiswep;
- u8 assoc_info[600];
- u8 szofcapability[256]; /* for wpa2 usage */
- u8 oidassociation[512]; /* for wpa/wpa2 usage */
- u8 authenticator_ie[256]; /* store ap security information element */
- u8 supplicant_ie[256]; /* store sta security information element */
- /* for tkip countermeasure */
- u32 last_mic_err_time;
- u8 btkip_countermeasure;
- u8 btkip_wait_report;
- u32 btkip_countermeasure_time;
- /*-------------------------------------------------------------------
- * For WPA2 Pre-Authentication.
- *------------------------------------------------------------------
- **/
- struct RT_PMKID_LIST PMKIDList[NUM_PMKID_CACHE];
- u8 PMKIDIndex;
-};
-
-#define GET_ENCRY_ALGO(psecuritypriv, psta, encry_algo, bmcst) \
-do { \
- switch (psecuritypriv->AuthAlgrthm) { \
- case 0: \
- case 1: \
- case 3: \
- encry_algo = (u8)psecuritypriv->PrivacyAlgrthm; \
- break; \
- case 2: \
- if (bmcst) \
- encry_algo = (u8)psecuritypriv->XGrpPrivacy; \
- else \
- encry_algo = (u8)psta->XPrivacy; \
- break; \
- } \
-} while (0)
-#define SET_ICE_IV_LEN(iv_len, icv_len, encrypt)\
-do {\
- switch (encrypt) { \
- case _WEP40_: \
- case _WEP104_: \
- iv_len = 4; \
- icv_len = 4; \
- break; \
- case _TKIP_: \
- iv_len = 8; \
- icv_len = 4; \
- break; \
- case _AES_: \
- iv_len = 8; \
- icv_len = 8; \
- break; \
- default: \
- iv_len = 0; \
- icv_len = 0; \
- break; \
- } \
-} while (0)
-#define GET_TKIP_PN(iv, txpn) \
-do {\
- txpn._byte_.TSC0 = iv[2];\
- txpn._byte_.TSC1 = iv[0];\
- txpn._byte_.TSC2 = iv[4];\
- txpn._byte_.TSC3 = iv[5];\
- txpn._byte_.TSC4 = iv[6];\
- txpn._byte_.TSC5 = iv[7];\
-} while (0)
-
-#define ROL32(A, n) (((A) << (n)) | (((A) >> (32 - (n))) & ((1UL << (n)) - 1)))
-#define ROR32(A, n) ROL32((A), 32 - (n))
-
-struct mic_data {
- u32 K0, K1; /* Key */
- u32 L, R; /* Current state */
- u32 M; /* Message accumulator (single word) */
- u32 nBytesInM; /* # bytes in M */
-};
-
-void seccalctkipmic(
- u8 *key,
- u8 *header,
- u8 *data,
- u32 data_len,
- u8 *Miccode,
- u8 priority);
-
-void r8712_secmicsetkey(struct mic_data *pmicdata, u8 *key);
-void r8712_secmicappend(struct mic_data *pmicdata, u8 *src, u32 nBytes);
-void r8712_secgetmic(struct mic_data *pmicdata, u8 *dst);
-u32 r8712_aes_encrypt(struct _adapter *padapter, u8 *pxmitframe);
-u32 r8712_tkip_encrypt(struct _adapter *padapter, u8 *pxmitframe);
-void r8712_wep_encrypt(struct _adapter *padapter, u8 *pxmitframe);
-void r8712_aes_decrypt(struct _adapter *padapter, u8 *precvframe);
-void r8712_tkip_decrypt(struct _adapter *padapter, u8 *precvframe);
-void r8712_wep_decrypt(struct _adapter *padapter, u8 *precvframe);
-void r8712_use_tkipkey_handler(struct timer_list *t);
-
-#endif /*__RTL871X_SECURITY_H_ */
-
diff --git a/drivers/staging/rtl8712/rtl871x_sta_mgt.c b/drivers/staging/rtl8712/rtl871x_sta_mgt.c
deleted file mode 100644
index 2c806a0105bf..000000000000
--- a/drivers/staging/rtl8712/rtl871x_sta_mgt.c
+++ /dev/null
@@ -1,263 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_sta_mgt.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_STA_MGT_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "xmit_osdep.h"
-#include "sta_info.h"
-
-static void _init_stainfo(struct sta_info *psta)
-{
- memset((u8 *)psta, 0, sizeof(struct sta_info));
- spin_lock_init(&psta->lock);
- INIT_LIST_HEAD(&psta->list);
- INIT_LIST_HEAD(&psta->hash_list);
- _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
- _r8712_init_sta_recv_priv(&psta->sta_recvpriv);
- INIT_LIST_HEAD(&psta->asoc_list);
- INIT_LIST_HEAD(&psta->auth_list);
-}
-
-int _r8712_init_sta_priv(struct sta_priv *pstapriv)
-{
- struct sta_info *psta;
- s32 i;
-
- pstapriv->pallocated_stainfo_buf = kmalloc(sizeof(struct sta_info) *
- NUM_STA + 4, GFP_ATOMIC);
- if (!pstapriv->pallocated_stainfo_buf)
- return -ENOMEM;
- pstapriv->pstainfo_buf = pstapriv->pallocated_stainfo_buf + 4 -
- ((addr_t)(pstapriv->pallocated_stainfo_buf) & 3);
- _init_queue(&pstapriv->free_sta_queue);
- spin_lock_init(&pstapriv->sta_hash_lock);
- pstapriv->asoc_sta_count = 0;
- _init_queue(&pstapriv->sleep_q);
- _init_queue(&pstapriv->wakeup_q);
- psta = (struct sta_info *)(pstapriv->pstainfo_buf);
- for (i = 0; i < NUM_STA; i++) {
- _init_stainfo(psta);
- INIT_LIST_HEAD(&(pstapriv->sta_hash[i]));
- list_add_tail(&psta->list, &pstapriv->free_sta_queue.queue);
- psta++;
- }
- INIT_LIST_HEAD(&pstapriv->asoc_list);
- INIT_LIST_HEAD(&pstapriv->auth_list);
- return 0;
-}
-
-/* this function is used to free the memory of lock || sema for all stainfos */
-static void mfree_all_stainfo(struct sta_priv *pstapriv)
-{
- unsigned long irqL;
- struct list_head *plist, *phead;
-
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
- phead = &pstapriv->free_sta_queue.queue;
- plist = phead->next;
- while (!end_of_queue_search(phead, plist))
- plist = plist->next;
-
- spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
-}
-
-void _r8712_free_sta_priv(struct sta_priv *pstapriv)
-{
- if (pstapriv) {
- /* be done before free sta_hash_lock */
- mfree_all_stainfo(pstapriv);
- kfree(pstapriv->pallocated_stainfo_buf);
- }
-}
-
-struct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
-{
- s32 index;
- struct list_head *phash_list;
- struct sta_info *psta;
- struct __queue *pfree_sta_queue;
- struct recv_reorder_ctrl *preorder_ctrl;
- int i = 0;
- u16 wRxSeqInitialValue = 0xffff;
- unsigned long flags;
-
- pfree_sta_queue = &pstapriv->free_sta_queue;
- spin_lock_irqsave(&pfree_sta_queue->lock, flags);
- psta = list_first_entry_or_null(&pfree_sta_queue->queue,
- struct sta_info, list);
- if (psta) {
- list_del_init(&psta->list);
- _init_stainfo(psta);
- memcpy(psta->hwaddr, hwaddr, ETH_ALEN);
- index = wifi_mac_hash(hwaddr);
- if (index >= NUM_STA) {
- psta = NULL;
- goto exit;
- }
- phash_list = &pstapriv->sta_hash[index];
- list_add_tail(&psta->hash_list, phash_list);
- pstapriv->asoc_sta_count++;
-
-/* For the SMC router, the sequence number of first packet of WPS handshake
- * will be 0. In this case, this packet will be dropped by recv_decache function
- * if we use the 0x00 as the default value for tid_rxseq variable. So, we
- * initialize the tid_rxseq variable as the 0xffff.
- */
- for (i = 0; i < 16; i++)
- memcpy(&psta->sta_recvpriv.rxcache.tid_rxseq[i],
- &wRxSeqInitialValue, 2);
- /* for A-MPDU Rx reordering buffer control */
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
- preorder_ctrl->padapter = pstapriv->padapter;
- preorder_ctrl->indicate_seq = 0xffff;
- preorder_ctrl->wend_b = 0xffff;
- preorder_ctrl->wsize_b = 64;
- _init_queue(&preorder_ctrl->pending_recvframe_queue);
- r8712_init_recv_timer(preorder_ctrl);
- }
- }
-exit:
- spin_unlock_irqrestore(&pfree_sta_queue->lock, flags);
- return psta;
-}
-
-/* using pstapriv->sta_hash_lock to protect */
-void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta)
-{
- int i;
- unsigned long irqL0;
- struct __queue *pfree_sta_queue;
- struct recv_reorder_ctrl *preorder_ctrl;
- struct sta_xmit_priv *pstaxmitpriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- if (!psta)
- return;
- pfree_sta_queue = &pstapriv->free_sta_queue;
- pstaxmitpriv = &psta->sta_xmitpriv;
- spin_lock_irqsave(&(pxmitpriv->vo_pending.lock), irqL0);
- r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vo_q.sta_pending);
- list_del_init(&(pstaxmitpriv->vo_q.tx_pending));
- spin_unlock_irqrestore(&(pxmitpriv->vo_pending.lock), irqL0);
- spin_lock_irqsave(&(pxmitpriv->vi_pending.lock), irqL0);
- r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->vi_q.sta_pending);
- list_del_init(&(pstaxmitpriv->vi_q.tx_pending));
- spin_unlock_irqrestore(&(pxmitpriv->vi_pending.lock), irqL0);
- spin_lock_irqsave(&(pxmitpriv->bk_pending.lock), irqL0);
- r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->bk_q.sta_pending);
- list_del_init(&(pstaxmitpriv->bk_q.tx_pending));
- spin_unlock_irqrestore(&(pxmitpriv->bk_pending.lock), irqL0);
- spin_lock_irqsave(&(pxmitpriv->be_pending.lock), irqL0);
- r8712_free_xmitframe_queue(pxmitpriv, &pstaxmitpriv->be_q.sta_pending);
- list_del_init(&(pstaxmitpriv->be_q.tx_pending));
- spin_unlock_irqrestore(&(pxmitpriv->be_pending.lock), irqL0);
- list_del_init(&psta->hash_list);
- pstapriv->asoc_sta_count--;
- /* re-init sta_info; 20061114 */
- _r8712_init_sta_xmit_priv(&psta->sta_xmitpriv);
- _r8712_init_sta_recv_priv(&psta->sta_recvpriv);
- /* for A-MPDU Rx reordering buffer control,
- * cancel reordering_ctrl_timer
- */
- for (i = 0; i < 16; i++) {
- preorder_ctrl = &psta->recvreorder_ctrl[i];
- del_timer(&preorder_ctrl->reordering_ctrl_timer);
- }
- spin_lock(&(pfree_sta_queue->lock));
- /* insert into free_sta_queue; 20061114 */
- list_add_tail(&psta->list, &pfree_sta_queue->queue);
- spin_unlock(&(pfree_sta_queue->lock));
-}
-
-/* free all stainfo which in sta_hash[all] */
-void r8712_free_all_stainfo(struct _adapter *padapter)
-{
- unsigned long irqL;
- struct list_head *plist, *phead;
- s32 index;
- struct sta_info *psta = NULL;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct sta_info *pbcmc_stainfo = r8712_get_bcmc_stainfo(padapter);
-
- if (pstapriv->asoc_sta_count == 1)
- return;
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
- for (index = 0; index < NUM_STA; index++) {
- phead = &(pstapriv->sta_hash[index]);
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- psta = container_of(plist,
- struct sta_info, hash_list);
- plist = plist->next;
- if (pbcmc_stainfo != psta)
- r8712_free_stainfo(padapter, psta);
- }
- }
- spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
-}
-
-/* any station allocated can be searched by hash list */
-struct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr)
-{
- unsigned long irqL;
- struct list_head *plist, *phead;
- struct sta_info *psta = NULL;
- u32 index;
-
- if (!hwaddr)
- return NULL;
- index = wifi_mac_hash(hwaddr);
- spin_lock_irqsave(&pstapriv->sta_hash_lock, irqL);
- phead = &(pstapriv->sta_hash[index]);
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- psta = container_of(plist, struct sta_info, hash_list);
- if ((!memcmp(psta->hwaddr, hwaddr, ETH_ALEN))) {
- /* if found the matched address */
- break;
- }
- psta = NULL;
- plist = plist->next;
- }
- spin_unlock_irqrestore(&pstapriv->sta_hash_lock, irqL);
- return psta;
-}
-
-void r8712_init_bcmc_stainfo(struct _adapter *padapter)
-{
- unsigned char bcast_addr[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- struct sta_priv *pstapriv = &padapter->stapriv;
-
- r8712_alloc_stainfo(pstapriv, bcast_addr);
-}
-
-struct sta_info *r8712_get_bcmc_stainfo(struct _adapter *padapter)
-{
- struct sta_priv *pstapriv = &padapter->stapriv;
- u8 bc_addr[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-
- return r8712_get_stainfo(pstapriv, bc_addr);
-}
-
-u8 r8712_access_ctrl(struct wlan_acl_pool *pacl_list, u8 *mac_addr)
-{
- return true;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_wlan_sme.h b/drivers/staging/rtl8712/rtl871x_wlan_sme.h
deleted file mode 100644
index 97ea1451426c..000000000000
--- a/drivers/staging/rtl8712/rtl871x_wlan_sme.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_WLAN_SME_H_
-#define _RTL871X_WLAN_SME_H_
-
-#define MSR_APMODE 0x0C
-#define MSR_STAMODE 0x08
-#define MSR_ADHOCMODE 0x04
-#define MSR_NOLINKMODE 0x00
-#define _1M_RATE_ 0
-#define _2M_RATE_ 1
-#define _5M_RATE_ 2
-#define _11M_RATE_ 3
-#define _6M_RATE_ 4
-#define _9M_RATE_ 5
-#define _12M_RATE_ 6
-#define _18M_RATE_ 7
-#define _24M_RATE_ 8
-#define _36M_RATE_ 9
-#define _48M_RATE_ 10
-#define _54M_RATE_ 11
-
-#endif
-
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.c b/drivers/staging/rtl8712/rtl871x_xmit.c
deleted file mode 100644
index 408616e9afcf..000000000000
--- a/drivers/staging/rtl8712/rtl871x_xmit.c
+++ /dev/null
@@ -1,1056 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * rtl871x_xmit.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _RTL871X_XMIT_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-
-#include <linux/usb.h>
-#include <linux/ieee80211.h>
-
-static const u8 P802_1H_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0xf8};
-static const u8 RFC1042_OUI[P80211_OUI_LEN] = {0x00, 0x00, 0x00};
-static void init_hwxmits(struct hw_xmit *phwxmit, sint entry);
-static void alloc_hwxmits(struct _adapter *padapter);
-static void free_hwxmits(struct _adapter *padapter);
-
-static void _init_txservq(struct tx_servq *ptxservq)
-{
- INIT_LIST_HEAD(&ptxservq->tx_pending);
- _init_queue(&ptxservq->sta_pending);
- ptxservq->qcnt = 0;
-}
-
-void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv)
-{
- memset((unsigned char *)psta_xmitpriv, 0,
- sizeof(struct sta_xmit_priv));
- spin_lock_init(&psta_xmitpriv->lock);
- _init_txservq(&psta_xmitpriv->be_q);
- _init_txservq(&psta_xmitpriv->bk_q);
- _init_txservq(&psta_xmitpriv->vi_q);
- _init_txservq(&psta_xmitpriv->vo_q);
- INIT_LIST_HEAD(&psta_xmitpriv->legacy_dz);
- INIT_LIST_HEAD(&psta_xmitpriv->apsd);
-}
-
-int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
- struct _adapter *padapter)
-{
- sint i;
- struct xmit_buf *pxmitbuf;
- struct xmit_frame *pxframe;
- int j;
-
- memset((unsigned char *)pxmitpriv, 0, sizeof(struct xmit_priv));
- spin_lock_init(&pxmitpriv->lock);
- /*
- *Please insert all the queue initialization using _init_queue below
- */
- pxmitpriv->adapter = padapter;
- _init_queue(&pxmitpriv->be_pending);
- _init_queue(&pxmitpriv->bk_pending);
- _init_queue(&pxmitpriv->vi_pending);
- _init_queue(&pxmitpriv->vo_pending);
- _init_queue(&pxmitpriv->bm_pending);
- _init_queue(&pxmitpriv->legacy_dz_queue);
- _init_queue(&pxmitpriv->apsd_queue);
- _init_queue(&pxmitpriv->free_xmit_queue);
- /*
- * Please allocate memory with sz = (struct xmit_frame) * NR_XMITFRAME,
- * and initialize free_xmit_frame below.
- * Please also apply free_txobj to link_up all the xmit_frames...
- */
- pxmitpriv->pallocated_frame_buf =
- kmalloc(NR_XMITFRAME * sizeof(struct xmit_frame) + 4,
- GFP_ATOMIC);
- if (!pxmitpriv->pallocated_frame_buf) {
- pxmitpriv->pxmit_frame_buf = NULL;
- return -ENOMEM;
- }
- pxmitpriv->pxmit_frame_buf = pxmitpriv->pallocated_frame_buf + 4 -
- ((addr_t) (pxmitpriv->pallocated_frame_buf) & 3);
- pxframe = (struct xmit_frame *) pxmitpriv->pxmit_frame_buf;
- for (i = 0; i < NR_XMITFRAME; i++) {
- INIT_LIST_HEAD(&(pxframe->list));
- pxframe->padapter = padapter;
- pxframe->frame_tag = DATA_FRAMETAG;
- pxframe->pkt = NULL;
- pxframe->buf_addr = NULL;
- pxframe->pxmitbuf = NULL;
- list_add_tail(&(pxframe->list),
- &(pxmitpriv->free_xmit_queue.queue));
- pxframe++;
- }
- pxmitpriv->free_xmitframe_cnt = NR_XMITFRAME;
- /*
- * init xmit hw_txqueue
- */
- _r8712_init_hw_txqueue(&pxmitpriv->be_txqueue, BE_QUEUE_INX);
- _r8712_init_hw_txqueue(&pxmitpriv->bk_txqueue, BK_QUEUE_INX);
- _r8712_init_hw_txqueue(&pxmitpriv->vi_txqueue, VI_QUEUE_INX);
- _r8712_init_hw_txqueue(&pxmitpriv->vo_txqueue, VO_QUEUE_INX);
- _r8712_init_hw_txqueue(&pxmitpriv->bmc_txqueue, BMC_QUEUE_INX);
- pxmitpriv->frag_len = MAX_FRAG_THRESHOLD;
- pxmitpriv->txirp_cnt = 1;
- /*per AC pending irp*/
- pxmitpriv->beq_cnt = 0;
- pxmitpriv->bkq_cnt = 0;
- pxmitpriv->viq_cnt = 0;
- pxmitpriv->voq_cnt = 0;
- /*init xmit_buf*/
- _init_queue(&pxmitpriv->free_xmitbuf_queue);
- _init_queue(&pxmitpriv->pending_xmitbuf_queue);
- pxmitpriv->pxmitbuf = kmalloc(NR_XMITBUFF * sizeof(struct xmit_buf), GFP_ATOMIC);
- if (!pxmitpriv->pxmitbuf)
- goto clean_up_frame_buf;
- pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
- for (i = 0; i < NR_XMITBUFF; i++) {
- INIT_LIST_HEAD(&pxmitbuf->list);
- pxmitbuf->pallocated_buf =
- kmalloc(MAX_XMITBUF_SZ + XMITBUF_ALIGN_SZ, GFP_ATOMIC);
- if (!pxmitbuf->pallocated_buf) {
- j = 0;
- goto clean_up_alloc_buf;
- }
- pxmitbuf->pbuf = pxmitbuf->pallocated_buf + XMITBUF_ALIGN_SZ -
- ((addr_t) (pxmitbuf->pallocated_buf) &
- (XMITBUF_ALIGN_SZ - 1));
- if (r8712_xmit_resource_alloc(padapter, pxmitbuf)) {
- j = 1;
- goto clean_up_alloc_buf;
- }
- list_add_tail(&pxmitbuf->list,
- &(pxmitpriv->free_xmitbuf_queue.queue));
- pxmitbuf++;
- }
- pxmitpriv->free_xmitbuf_cnt = NR_XMITBUFF;
- INIT_WORK(&padapter->wk_filter_rx_ff0, r8712_SetFilter);
- alloc_hwxmits(padapter);
- init_hwxmits(pxmitpriv->hwxmits, pxmitpriv->hwxmit_entry);
- tasklet_setup(&pxmitpriv->xmit_tasklet, r8712_xmit_bh);
- return 0;
-
-clean_up_alloc_buf:
- if (j) {
- /* failure happened in r8712_xmit_resource_alloc()
- * delete extra pxmitbuf->pallocated_buf
- */
- kfree(pxmitbuf->pallocated_buf);
- }
- for (j = 0; j < i; j++) {
- int k;
-
- pxmitbuf--; /* reset pointer */
- kfree(pxmitbuf->pallocated_buf);
- for (k = 0; k < 8; k++) /* delete xmit urb's */
- usb_free_urb(pxmitbuf->pxmit_urb[k]);
- }
- kfree(pxmitpriv->pxmitbuf);
- pxmitpriv->pxmitbuf = NULL;
-clean_up_frame_buf:
- kfree(pxmitpriv->pallocated_frame_buf);
- pxmitpriv->pallocated_frame_buf = NULL;
- return -ENOMEM;
-}
-
-void _free_xmit_priv(struct xmit_priv *pxmitpriv)
-{
- int i;
- struct _adapter *padapter = pxmitpriv->adapter;
- struct xmit_frame *pxmitframe = (struct xmit_frame *)
- pxmitpriv->pxmit_frame_buf;
- struct xmit_buf *pxmitbuf = (struct xmit_buf *)pxmitpriv->pxmitbuf;
-
- if (!pxmitpriv->pxmit_frame_buf)
- return;
- for (i = 0; i < NR_XMITFRAME; i++) {
- r8712_xmit_complete(padapter, pxmitframe);
- pxmitframe++;
- }
- for (i = 0; i < NR_XMITBUFF; i++) {
- r8712_xmit_resource_free(padapter, pxmitbuf);
- kfree(pxmitbuf->pallocated_buf);
- pxmitbuf++;
- }
- kfree(pxmitpriv->pallocated_frame_buf);
- kfree(pxmitpriv->pxmitbuf);
- free_hwxmits(padapter);
-}
-
-int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
- struct pkt_attrib *pattrib)
-{
- struct pkt_file pktfile;
- struct sta_info *psta = NULL;
- struct ethhdr etherhdr;
-
- struct tx_cmd txdesc;
-
- bool bmcast;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct security_priv *psecuritypriv = &padapter->securitypriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
-
- _r8712_open_pktfile(pkt, &pktfile);
-
- _r8712_pktfile_read(&pktfile, (unsigned char *)&etherhdr, ETH_HLEN);
-
- pattrib->ether_type = ntohs(etherhdr.h_proto);
-
- /*
- * If driver xmit ARP packet, driver can set ps mode to initial
- * setting. It stands for getting DHCP or fix IP.
- */
- if (pattrib->ether_type == 0x0806) {
- if (padapter->pwrctrlpriv.pwr_mode !=
- padapter->registrypriv.power_mgnt) {
- del_timer_sync(&pmlmepriv->dhcp_timer);
- r8712_set_ps_mode(padapter,
- padapter->registrypriv.power_mgnt,
- padapter->registrypriv.smart_ps);
- }
- }
-
- memcpy(pattrib->dst, &etherhdr.h_dest, ETH_ALEN);
- memcpy(pattrib->src, &etherhdr.h_source, ETH_ALEN);
- pattrib->pctrl = 0;
- if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
- memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
- } else if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- memcpy(pattrib->ra, get_bssid(pmlmepriv), ETH_ALEN);
- memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
- } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
- memcpy(pattrib->ta, get_bssid(pmlmepriv), ETH_ALEN);
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- /*firstly, filter packet not belongs to mp*/
- if (pattrib->ether_type != 0x8712)
- return -EINVAL;
- /* for mp storing the txcmd per packet,
- * according to the info of txcmd to update pattrib
- */
- /*get MP_TXDESC_SIZE bytes txcmd per packet*/
- _r8712_pktfile_read(&pktfile, (u8 *)&txdesc, TXDESC_SIZE);
- memcpy(pattrib->ra, pattrib->dst, ETH_ALEN);
- memcpy(pattrib->ta, pattrib->src, ETH_ALEN);
- pattrib->pctrl = 1;
- }
- /* r8712_xmitframe_coalesce() overwrite this!*/
- pattrib->pktlen = pktfile.pkt_len;
- if (pattrib->ether_type == ETH_P_IP) {
- /* The following is for DHCP and ARP packet, we use cck1M to
- * tx these packets and let LPS awake some time
- * to prevent DHCP protocol fail
- */
- u8 tmp[24];
-
- _r8712_pktfile_read(&pktfile, &tmp[0], 24);
- pattrib->dhcp_pkt = 0;
- if (pktfile.pkt_len > 282) {/*MINIMUM_DHCP_PACKET_SIZE)*/
- if (pattrib->ether_type == ETH_P_IP) {/* IP header*/
- if (((tmp[21] == 68) && (tmp[23] == 67)) ||
- ((tmp[21] == 67) && (tmp[23] == 68))) {
- /* 68 : UDP BOOTP client
- * 67 : UDP BOOTP server
- * Use low rate to send DHCP packet.
- */
- pattrib->dhcp_pkt = 1;
- }
- }
- }
- }
- bmcast = is_multicast_ether_addr(pattrib->ra);
- /* get sta_info*/
- if (bmcast) {
- psta = r8712_get_bcmc_stainfo(padapter);
- pattrib->mac_id = 4;
- } else {
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- psta = r8712_get_stainfo(pstapriv,
- get_bssid(pmlmepriv));
- pattrib->mac_id = 5;
- } else {
- psta = r8712_get_stainfo(pstapriv, pattrib->ra);
- if (!psta) /* drop the pkt */
- return -ENOMEM;
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE))
- pattrib->mac_id = 5;
- else
- pattrib->mac_id = psta->mac_id;
- }
- }
-
- if (psta) {
- pattrib->psta = psta;
- } else {
- /* if we cannot get psta => drrp the pkt */
- return -ENOMEM;
- }
-
- pattrib->ack_policy = 0;
- /* get ether_hdr_len */
- pattrib->pkt_hdrlen = ETH_HLEN;
-
- if (pqospriv->qos_option) {
- r8712_set_qos(&pktfile, pattrib);
- } else {
- pattrib->hdrlen = WLAN_HDR_A3_LEN;
- pattrib->subtype = IEEE80211_FTYPE_DATA;
- pattrib->priority = 0;
- }
- if (psta->ieee8021x_blocked) {
- pattrib->encrypt = 0;
- if ((pattrib->ether_type != 0x888e) &&
- !check_fwstate(pmlmepriv, WIFI_MP_STATE))
- return -EINVAL;
- } else {
- GET_ENCRY_ALGO(psecuritypriv, psta, pattrib->encrypt, bmcast);
- }
- switch (pattrib->encrypt) {
- case _WEP40_:
- case _WEP104_:
- pattrib->iv_len = 4;
- pattrib->icv_len = 4;
- break;
- case _TKIP_:
- pattrib->iv_len = 8;
- pattrib->icv_len = 4;
- if (padapter->securitypriv.busetkipkey == _FAIL)
- return -EINVAL;
- break;
- case _AES_:
- pattrib->iv_len = 8;
- pattrib->icv_len = 8;
- break;
- default:
- pattrib->iv_len = 0;
- pattrib->icv_len = 0;
- break;
- }
-
- if (pattrib->encrypt &&
- (padapter->securitypriv.sw_encrypt ||
- !psecuritypriv->hw_decrypted))
- pattrib->bswenc = true;
- else
- pattrib->bswenc = false;
- /* if in MP_STATE, update pkt_attrib from mp_txcmd, and overwrite
- * some settings above.
- */
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
- pattrib->priority =
- (le32_to_cpu(txdesc.txdw1) >> QSEL_SHT) & 0x1f;
- return 0;
-}
-
-static int xmitframe_addmic(struct _adapter *padapter,
- struct xmit_frame *pxmitframe)
-{
- u32 curfragnum, length;
- u8 *pframe, *payload, mic[8];
- struct mic_data micdata;
- struct sta_info *stainfo;
- struct qos_priv *pqospriv = &(padapter->mlmepriv.qospriv);
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct security_priv *psecpriv = &padapter->securitypriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- u8 priority[4] = {};
- bool bmcst = is_multicast_ether_addr(pattrib->ra);
-
- if (pattrib->psta)
- stainfo = pattrib->psta;
- else
- stainfo = r8712_get_stainfo(&padapter->stapriv,
- &pattrib->ra[0]);
- if (pattrib->encrypt == _TKIP_) {
- /*encode mic code*/
- if (stainfo) {
- u8 null_key[16] = {};
-
- pframe = pxmitframe->buf_addr + TXDESC_OFFSET;
- if (bmcst) {
- if (!memcmp(psecpriv->XGrptxmickey
- [psecpriv->XGrpKeyid].skey,
- null_key, 16))
- return -ENOMEM;
- /*start to calculate the mic code*/
- r8712_secmicsetkey(&micdata,
- psecpriv->XGrptxmickey
- [psecpriv->XGrpKeyid].skey);
- } else {
- if (!memcmp(&stainfo->tkiptxmickey.skey[0],
- null_key, 16))
- return -ENOMEM;
- /* start to calculate the mic code */
- r8712_secmicsetkey(&micdata,
- &stainfo->tkiptxmickey.skey[0]);
- }
- if (pframe[1] & 1) { /* ToDS==1 */
- r8712_secmicappend(&micdata,
- &pframe[16], 6); /*DA*/
- if (pframe[1] & 2) /* From Ds==1 */
- r8712_secmicappend(&micdata,
- &pframe[24], 6);
- else
- r8712_secmicappend(&micdata,
- &pframe[10], 6);
- } else { /* ToDS==0 */
- r8712_secmicappend(&micdata,
- &pframe[4], 6); /* DA */
- if (pframe[1] & 2) /* From Ds==1 */
- r8712_secmicappend(&micdata,
- &pframe[16], 6);
- else
- r8712_secmicappend(&micdata,
- &pframe[10], 6);
- }
- if (pqospriv->qos_option == 1)
- priority[0] = (u8)pxmitframe->attrib.priority;
- r8712_secmicappend(&micdata, &priority[0], 4);
- payload = pframe;
- for (curfragnum = 0; curfragnum < pattrib->nr_frags;
- curfragnum++) {
- payload = (u8 *)RND4((addr_t)(payload));
- payload += pattrib->hdrlen + pattrib->iv_len;
- if ((curfragnum + 1) == pattrib->nr_frags) {
- length = pattrib->last_txcmdsz -
- pattrib->hdrlen -
- pattrib->iv_len -
- ((psecpriv->sw_encrypt)
- ? pattrib->icv_len : 0);
- r8712_secmicappend(&micdata, payload,
- length);
- payload = payload + length;
- } else {
- length = pxmitpriv->frag_len -
- pattrib->hdrlen - pattrib->iv_len -
- ((psecpriv->sw_encrypt) ?
- pattrib->icv_len : 0);
- r8712_secmicappend(&micdata, payload,
- length);
- payload = payload + length +
- pattrib->icv_len;
- }
- }
- r8712_secgetmic(&micdata, &(mic[0]));
- /* add mic code and add the mic code length in
- * last_txcmdsz
- */
- memcpy(payload, &(mic[0]), 8);
- pattrib->last_txcmdsz += 8;
- payload = payload - pattrib->last_txcmdsz + 8;
- }
- }
- return 0;
-}
-
-static sint xmitframe_swencrypt(struct _adapter *padapter,
- struct xmit_frame *pxmitframe)
-{
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
-
- if (pattrib->bswenc) {
- switch (pattrib->encrypt) {
- case _WEP40_:
- case _WEP104_:
- r8712_wep_encrypt(padapter, (u8 *)pxmitframe);
- break;
- case _TKIP_:
- r8712_tkip_encrypt(padapter, (u8 *)pxmitframe);
- break;
- case _AES_:
- r8712_aes_encrypt(padapter, (u8 *)pxmitframe);
- break;
- default:
- break;
- }
- }
- return _SUCCESS;
-}
-
-static int make_wlanhdr(struct _adapter *padapter, u8 *hdr,
- struct pkt_attrib *pattrib)
-{
- u16 *qc;
-
- struct ieee80211_hdr *pwlanhdr = (struct ieee80211_hdr *)hdr;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct qos_priv *pqospriv = &pmlmepriv->qospriv;
- __le16 *fctrl = &pwlanhdr->frame_control;
- u8 *bssid;
-
- memset(hdr, 0, WLANHDR_OFFSET);
- SetFrameSubType(fctrl, pattrib->subtype);
- if (!(pattrib->subtype & IEEE80211_FTYPE_DATA))
- return 0;
-
- bssid = get_bssid(pmlmepriv);
-
- if (check_fwstate(pmlmepriv, WIFI_STATION_STATE)) {
- /* to_ds = 1, fr_ds = 0; */
- SetToDs(fctrl);
- ether_addr_copy(pwlanhdr->addr1, bssid);
- ether_addr_copy(pwlanhdr->addr2, pattrib->src);
- ether_addr_copy(pwlanhdr->addr3, pattrib->dst);
- } else if (check_fwstate(pmlmepriv, WIFI_AP_STATE)) {
- /* to_ds = 0, fr_ds = 1; */
- SetFrDs(fctrl);
- ether_addr_copy(pwlanhdr->addr1, pattrib->dst);
- ether_addr_copy(pwlanhdr->addr2, bssid);
- ether_addr_copy(pwlanhdr->addr3, pattrib->src);
- } else if (check_fwstate(pmlmepriv, WIFI_ADHOC_STATE) ||
- check_fwstate(pmlmepriv, WIFI_ADHOC_MASTER_STATE)) {
- ether_addr_copy(pwlanhdr->addr1, pattrib->dst);
- ether_addr_copy(pwlanhdr->addr2, pattrib->src);
- ether_addr_copy(pwlanhdr->addr3, bssid);
- } else if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- ether_addr_copy(pwlanhdr->addr1, pattrib->dst);
- ether_addr_copy(pwlanhdr->addr2, pattrib->src);
- ether_addr_copy(pwlanhdr->addr3, bssid);
- } else {
- return -EINVAL;
- }
-
- if (pattrib->encrypt)
- SetPrivacy(fctrl);
- if (pqospriv->qos_option) {
- qc = (unsigned short *)(hdr + pattrib->hdrlen - 2);
- if (pattrib->priority)
- SetPriority(qc, pattrib->priority);
- SetAckpolicy(qc, pattrib->ack_policy);
- }
- /* TODO: fill HT Control Field */
- /* Update Seq Num will be handled by f/w */
- {
- struct sta_info *psta;
- bool bmcst = is_multicast_ether_addr(pattrib->ra);
-
- if (pattrib->psta)
- psta = pattrib->psta;
- else if (bmcst)
- psta = r8712_get_bcmc_stainfo(padapter);
- else
- psta = r8712_get_stainfo(&padapter->stapriv,
- pattrib->ra);
-
- if (psta) {
- u16 *txtid = psta->sta_xmitpriv.txseq_tid;
-
- txtid[pattrib->priority]++;
- txtid[pattrib->priority] &= 0xFFF;
- pattrib->seqnum = txtid[pattrib->priority];
- SetSeqNum(hdr, pattrib->seqnum);
- }
- }
-
- return 0;
-}
-
-static sint r8712_put_snap(u8 *data, u16 h_proto)
-{
- struct ieee80211_snap_hdr *snap;
- const u8 *oui;
-
- snap = (struct ieee80211_snap_hdr *)data;
- snap->dsap = 0xaa;
- snap->ssap = 0xaa;
- snap->ctrl = 0x03;
- if (h_proto == 0x8137 || h_proto == 0x80f3)
- oui = P802_1H_OUI;
- else
- oui = RFC1042_OUI;
- snap->oui[0] = oui[0];
- snap->oui[1] = oui[1];
- snap->oui[2] = oui[2];
- *(__be16 *)(data + SNAP_SIZE) = htons(h_proto);
- return SNAP_SIZE + sizeof(u16);
-}
-
-/*
- * This sub-routine will perform all the following:
- * 1. remove 802.3 header.
- * 2. create wlan_header, based on the info in pxmitframe
- * 3. append sta's iv/ext-iv
- * 4. append LLC
- * 5. move frag chunk from pframe to pxmitframe->mem
- * 6. apply sw-encrypt, if necessary.
- */
-sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt,
- struct xmit_frame *pxmitframe)
-{
- struct pkt_file pktfile;
-
- sint frg_len, mpdu_len, llc_sz;
- u32 mem_sz;
- u8 frg_inx;
- addr_t addr;
- u8 *pframe, *mem_start, *ptxdesc;
- struct sta_info *psta;
- struct security_priv *psecpriv = &padapter->securitypriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- u8 *pbuf_start;
- bool bmcst = is_multicast_ether_addr(pattrib->ra);
-
- if (!pattrib->psta)
- return _FAIL;
- psta = pattrib->psta;
- if (!pxmitframe->buf_addr)
- return _FAIL;
- pbuf_start = pxmitframe->buf_addr;
- ptxdesc = pbuf_start;
- mem_start = pbuf_start + TXDESC_OFFSET;
- if (make_wlanhdr(padapter, mem_start, pattrib))
- return _FAIL;
- _r8712_open_pktfile(pkt, &pktfile);
- _r8712_pktfile_read(&pktfile, NULL, (uint) pattrib->pkt_hdrlen);
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE)) {
- /* truncate TXDESC_SIZE bytes txcmd if at mp mode for 871x */
- if (pattrib->ether_type == 0x8712) {
- /* take care - update_txdesc overwrite this */
- _r8712_pktfile_read(&pktfile, ptxdesc, TXDESC_SIZE);
- }
- }
- pattrib->pktlen = pktfile.pkt_len;
- frg_inx = 0;
- frg_len = pxmitpriv->frag_len - 4;
- while (1) {
- llc_sz = 0;
- mpdu_len = frg_len;
- pframe = mem_start;
- SetMFrag(mem_start);
- pframe += pattrib->hdrlen;
- mpdu_len -= pattrib->hdrlen;
- /* adding icv, if necessary...*/
- if (pattrib->iv_len) {
- if (psta) {
- switch (pattrib->encrypt) {
- case _WEP40_:
- case _WEP104_:
- WEP_IV(pattrib->iv, psta->txpn,
- (u8)psecpriv->PrivacyKeyIndex);
- break;
- case _TKIP_:
- if (bmcst)
- TKIP_IV(pattrib->iv,
- psta->txpn,
- (u8)psecpriv->XGrpKeyid);
- else
- TKIP_IV(pattrib->iv, psta->txpn,
- 0);
- break;
- case _AES_:
- if (bmcst)
- AES_IV(pattrib->iv, psta->txpn,
- (u8)psecpriv->XGrpKeyid);
- else
- AES_IV(pattrib->iv, psta->txpn,
- 0);
- break;
- }
- }
- memcpy(pframe, pattrib->iv, pattrib->iv_len);
- pframe += pattrib->iv_len;
- mpdu_len -= pattrib->iv_len;
- }
- if (frg_inx == 0) {
- llc_sz = r8712_put_snap(pframe, pattrib->ether_type);
- pframe += llc_sz;
- mpdu_len -= llc_sz;
- }
- if ((pattrib->icv_len > 0) && (pattrib->bswenc))
- mpdu_len -= pattrib->icv_len;
- if (bmcst)
- mem_sz = _r8712_pktfile_read(&pktfile, pframe,
- pattrib->pktlen);
- else
- mem_sz = _r8712_pktfile_read(&pktfile, pframe,
- mpdu_len);
- pframe += mem_sz;
- if ((pattrib->icv_len > 0) && (pattrib->bswenc)) {
- memcpy(pframe, pattrib->icv, pattrib->icv_len);
- pframe += pattrib->icv_len;
- }
- frg_inx++;
- if (bmcst || r8712_endofpktfile(&pktfile)) {
- pattrib->nr_frags = frg_inx;
- pattrib->last_txcmdsz = pattrib->hdrlen +
- pattrib->iv_len +
- ((pattrib->nr_frags == 1) ?
- llc_sz : 0) +
- ((pattrib->bswenc) ?
- pattrib->icv_len : 0) + mem_sz;
- ClearMFrag(mem_start);
- break;
- }
- addr = (addr_t)(pframe);
- mem_start = (unsigned char *)RND4(addr) + TXDESC_OFFSET;
- memcpy(mem_start, pbuf_start + TXDESC_OFFSET, pattrib->hdrlen);
- }
-
- if (xmitframe_addmic(padapter, pxmitframe))
- return _FAIL;
- xmitframe_swencrypt(padapter, pxmitframe);
- return _SUCCESS;
-}
-
-void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len)
-{
- uint protection;
- u8 *perp;
- uint erp_len;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct registry_priv *pregistrypriv = &padapter->registrypriv;
-
- switch (pxmitpriv->vcs_setting) {
- case DISABLE_VCS:
- pxmitpriv->vcs = NONE_VCS;
- break;
- case ENABLE_VCS:
- break;
- case AUTO_VCS:
- default:
- perp = r8712_get_ie(ie, WLAN_EID_ERP_INFO, &erp_len, ie_len);
- if (!perp) {
- pxmitpriv->vcs = NONE_VCS;
- } else {
- protection = (*(perp + 2)) & BIT(1);
- if (protection) {
- if (pregistrypriv->vcs_type == RTS_CTS)
- pxmitpriv->vcs = RTS_CTS;
- else
- pxmitpriv->vcs = CTS_TO_SELF;
- } else {
- pxmitpriv->vcs = NONE_VCS;
- }
- }
- break;
- }
-}
-
-struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv)
-{
- unsigned long irqL;
- struct xmit_buf *pxmitbuf;
- struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
-
- spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
- pxmitbuf = list_first_entry_or_null(&pfree_xmitbuf_queue->queue,
- struct xmit_buf, list);
- if (pxmitbuf) {
- list_del_init(&pxmitbuf->list);
- pxmitpriv->free_xmitbuf_cnt--;
- }
- spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
- return pxmitbuf;
-}
-
-void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv, struct xmit_buf *pxmitbuf)
-{
- unsigned long irqL;
- struct __queue *pfree_xmitbuf_queue = &pxmitpriv->free_xmitbuf_queue;
-
- if (!pxmitbuf)
- return;
- spin_lock_irqsave(&pfree_xmitbuf_queue->lock, irqL);
- list_del_init(&pxmitbuf->list);
- list_add_tail(&(pxmitbuf->list), &pfree_xmitbuf_queue->queue);
- pxmitpriv->free_xmitbuf_cnt++;
- spin_unlock_irqrestore(&pfree_xmitbuf_queue->lock, irqL);
-}
-
-/*
- * Calling context:
- * 1. OS_TXENTRY
- * 2. RXENTRY (rx_thread or RX_ISR/RX_CallBack)
- *
- * If we turn on USE_RXTHREAD, then, no need for critical section.
- * Otherwise, we must use _enter/_exit critical to protect free_xmit_queue...
- *
- * Must be very very cautious...
- *
- */
-struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv)
-{
- /*
- * Please remember to use all the osdep_service api,
- * and lock/unlock or _enter/_exit critical to protect
- * pfree_xmit_queue
- */
- unsigned long irqL;
- struct xmit_frame *pxframe;
- struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
-
- spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
- pxframe = list_first_entry_or_null(&pfree_xmit_queue->queue,
- struct xmit_frame, list);
- if (pxframe) {
- list_del_init(&pxframe->list);
- pxmitpriv->free_xmitframe_cnt--;
- pxframe->buf_addr = NULL;
- pxframe->pxmitbuf = NULL;
- pxframe->attrib.psta = NULL;
- pxframe->pkt = NULL;
- }
- spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL);
- return pxframe;
-}
-
-void r8712_free_xmitframe(struct xmit_priv *pxmitpriv,
- struct xmit_frame *pxmitframe)
-{
- unsigned long irqL;
- struct __queue *pfree_xmit_queue = &pxmitpriv->free_xmit_queue;
- struct _adapter *padapter = pxmitpriv->adapter;
-
- if (!pxmitframe)
- return;
- spin_lock_irqsave(&pfree_xmit_queue->lock, irqL);
- list_del_init(&pxmitframe->list);
- if (pxmitframe->pkt)
- pxmitframe->pkt = NULL;
- list_add_tail(&pxmitframe->list, &pfree_xmit_queue->queue);
- pxmitpriv->free_xmitframe_cnt++;
- spin_unlock_irqrestore(&pfree_xmit_queue->lock, irqL);
- if (netif_queue_stopped(padapter->pnetdev))
- netif_wake_queue(padapter->pnetdev);
-}
-
-void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv,
- struct xmit_frame *pxmitframe)
-{
- if (!pxmitframe)
- return;
- if (pxmitframe->frame_tag == DATA_FRAMETAG)
- r8712_free_xmitframe(pxmitpriv, pxmitframe);
-}
-
-void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv,
- struct __queue *pframequeue)
-{
- unsigned long irqL;
- struct list_head *plist, *phead;
- struct xmit_frame *pxmitframe;
-
- spin_lock_irqsave(&(pframequeue->lock), irqL);
- phead = &pframequeue->queue;
- plist = phead->next;
- while (!end_of_queue_search(phead, plist)) {
- pxmitframe = container_of(plist, struct xmit_frame, list);
- plist = plist->next;
- r8712_free_xmitframe(pxmitpriv, pxmitframe);
- }
- spin_unlock_irqrestore(&(pframequeue->lock), irqL);
-}
-
-static inline struct tx_servq *get_sta_pending(struct _adapter *padapter,
- struct __queue **ppstapending,
- struct sta_info *psta, sint up)
-{
- struct tx_servq *ptxservq;
- struct hw_xmit *phwxmits = padapter->xmitpriv.hwxmits;
-
- switch (up) {
- case 1:
- case 2:
- ptxservq = &(psta->sta_xmitpriv.bk_q);
- *ppstapending = &padapter->xmitpriv.bk_pending;
- (phwxmits + 3)->accnt++;
- break;
- case 4:
- case 5:
- ptxservq = &(psta->sta_xmitpriv.vi_q);
- *ppstapending = &padapter->xmitpriv.vi_pending;
- (phwxmits + 1)->accnt++;
- break;
- case 6:
- case 7:
- ptxservq = &(psta->sta_xmitpriv.vo_q);
- *ppstapending = &padapter->xmitpriv.vo_pending;
- (phwxmits + 0)->accnt++;
- break;
- case 0:
- case 3:
- default:
- ptxservq = &(psta->sta_xmitpriv.be_q);
- *ppstapending = &padapter->xmitpriv.be_pending;
- (phwxmits + 2)->accnt++;
- break;
- }
- return ptxservq;
-}
-
-/*
- * Will enqueue pxmitframe to the proper queue, and indicate it
- * to xx_pending list.....
- */
-int r8712_xmit_classifier(struct _adapter *padapter,
- struct xmit_frame *pxmitframe)
-{
- unsigned long irqL0;
- struct __queue *pstapending;
- struct sta_info *psta;
- struct tx_servq *ptxservq;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
- struct sta_priv *pstapriv = &padapter->stapriv;
- struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
- bool bmcst = is_multicast_ether_addr(pattrib->ra);
-
- if (pattrib->psta) {
- psta = pattrib->psta;
- } else {
- if (bmcst) {
- psta = r8712_get_bcmc_stainfo(padapter);
- } else {
- if (check_fwstate(pmlmepriv, WIFI_MP_STATE))
- psta = r8712_get_stainfo(pstapriv,
- get_bssid(pmlmepriv));
- else
- psta = r8712_get_stainfo(pstapriv, pattrib->ra);
- }
- }
- if (!psta)
- return -EINVAL;
- ptxservq = get_sta_pending(padapter, &pstapending,
- psta, pattrib->priority);
- spin_lock_irqsave(&pstapending->lock, irqL0);
- if (list_empty(&ptxservq->tx_pending))
- list_add_tail(&ptxservq->tx_pending, &pstapending->queue);
- list_add_tail(&pxmitframe->list, &ptxservq->sta_pending.queue);
- ptxservq->qcnt++;
- spin_unlock_irqrestore(&pstapending->lock, irqL0);
- return 0;
-}
-
-static void alloc_hwxmits(struct _adapter *padapter)
-{
- struct hw_xmit *hwxmits;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- pxmitpriv->hwxmit_entry = HWXMIT_ENTRY;
- pxmitpriv->hwxmits = kmalloc_array(pxmitpriv->hwxmit_entry,
- sizeof(struct hw_xmit), GFP_ATOMIC);
- if (!pxmitpriv->hwxmits)
- return;
- hwxmits = pxmitpriv->hwxmits;
- if (pxmitpriv->hwxmit_entry == 5) {
- pxmitpriv->bmc_txqueue.head = 0;
- hwxmits[0] .phwtxqueue = &pxmitpriv->bmc_txqueue;
- hwxmits[0] .sta_queue = &pxmitpriv->bm_pending;
- pxmitpriv->vo_txqueue.head = 0;
- hwxmits[1] .phwtxqueue = &pxmitpriv->vo_txqueue;
- hwxmits[1] .sta_queue = &pxmitpriv->vo_pending;
- pxmitpriv->vi_txqueue.head = 0;
- hwxmits[2] .phwtxqueue = &pxmitpriv->vi_txqueue;
- hwxmits[2] .sta_queue = &pxmitpriv->vi_pending;
- pxmitpriv->bk_txqueue.head = 0;
- hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue;
- hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
- pxmitpriv->be_txqueue.head = 0;
- hwxmits[4] .phwtxqueue = &pxmitpriv->be_txqueue;
- hwxmits[4] .sta_queue = &pxmitpriv->be_pending;
- } else if (pxmitpriv->hwxmit_entry == 4) {
- pxmitpriv->vo_txqueue.head = 0;
- hwxmits[0] .phwtxqueue = &pxmitpriv->vo_txqueue;
- hwxmits[0] .sta_queue = &pxmitpriv->vo_pending;
- pxmitpriv->vi_txqueue.head = 0;
- hwxmits[1] .phwtxqueue = &pxmitpriv->vi_txqueue;
- hwxmits[1] .sta_queue = &pxmitpriv->vi_pending;
- pxmitpriv->be_txqueue.head = 0;
- hwxmits[2] .phwtxqueue = &pxmitpriv->be_txqueue;
- hwxmits[2] .sta_queue = &pxmitpriv->be_pending;
- pxmitpriv->bk_txqueue.head = 0;
- hwxmits[3] .phwtxqueue = &pxmitpriv->bk_txqueue;
- hwxmits[3] .sta_queue = &pxmitpriv->bk_pending;
- }
-}
-
-static void free_hwxmits(struct _adapter *padapter)
-{
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- kfree(pxmitpriv->hwxmits);
-}
-
-static void init_hwxmits(struct hw_xmit *phwxmit, sint entry)
-{
- sint i;
-
- for (i = 0; i < entry; i++, phwxmit++) {
- spin_lock_init(&phwxmit->xmit_lock);
- INIT_LIST_HEAD(&phwxmit->pending);
- phwxmit->txcmdcnt = 0;
- phwxmit->accnt = 0;
- }
-}
-
-void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe,
- struct xmit_buf *pxmitbuf)
-{
- /* pxmitbuf attach to pxmitframe */
- pxmitframe->pxmitbuf = pxmitbuf;
- /* urb and irp connection */
- pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0];
- /* buffer addr assoc */
- pxmitframe->buf_addr = pxmitbuf->pbuf;
- /* pxmitframe attach to pxmitbuf */
- pxmitbuf->priv_data = pxmitframe;
-}
-
-/*
- * tx_action == 0 == no frames to transmit
- * tx_action > 0 ==> we have frames to transmit
- * tx_action < 0 ==> we have frames to transmit, but TXFF is not even enough
- * to transmit 1 frame.
- */
-
-int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe)
-{
- unsigned long irqL;
- int ret;
- struct xmit_buf *pxmitbuf = NULL;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
-
- r8712_do_queue_select(padapter, pattrib);
- spin_lock_irqsave(&pxmitpriv->lock, irqL);
- if (r8712_txframes_sta_ac_pending(padapter, pattrib) > 0) {
- ret = false;
- r8712_xmit_enqueue(padapter, pxmitframe);
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
- return ret;
- }
- pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv);
- if (!pxmitbuf) { /*enqueue packet*/
- ret = false;
- r8712_xmit_enqueue(padapter, pxmitframe);
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
- } else { /*dump packet directly*/
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
- ret = true;
- xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf);
- r8712_xmit_direct(padapter, pxmitframe);
- }
- return ret;
-}
diff --git a/drivers/staging/rtl8712/rtl871x_xmit.h b/drivers/staging/rtl8712/rtl871x_xmit.h
deleted file mode 100644
index 784172c385e3..000000000000
--- a/drivers/staging/rtl8712/rtl871x_xmit.h
+++ /dev/null
@@ -1,287 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _RTL871X_XMIT_H_
-#define _RTL871X_XMIT_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "xmit_osdep.h"
-
-#ifdef CONFIG_R8712_TX_AGGR
-#define MAX_XMITBUF_SZ (16384)
-#else
-#define MAX_XMITBUF_SZ (2048)
-#endif
-
-#define NR_XMITBUFF (4)
-
-#ifdef CONFIG_R8712_TX_AGGR
-#define AGGR_NR_HIGH_BOUND (4) /*(8) */
-#define AGGR_NR_LOW_BOUND (2)
-#endif
-
-#define XMITBUF_ALIGN_SZ 512
-#define TX_GUARD_BAND 5
-#define MAX_NUMBLKS (1)
-
-/* Fixed the Big Endian bug when using the software driver encryption.*/
-#define WEP_IV(pattrib_iv, txpn, keyidx)\
-do { \
- pattrib_iv[0] = txpn._byte_.TSC0;\
- pattrib_iv[1] = txpn._byte_.TSC1;\
- pattrib_iv[2] = txpn._byte_.TSC2;\
- pattrib_iv[3] = ((keyidx & 0x3) << 6);\
- txpn.val = (txpn.val == 0xffffff) ? 0 : (txpn.val + 1);\
-} while (0)
-
-/* Fixed the Big Endian bug when doing the Tx.
- * The Linksys WRH54G will check this.
- */
-#define TKIP_IV(pattrib_iv, txpn, keyidx)\
-do { \
- pattrib_iv[0] = txpn._byte_.TSC1;\
- pattrib_iv[1] = (txpn._byte_.TSC1 | 0x20) & 0x7f;\
- pattrib_iv[2] = txpn._byte_.TSC0;\
- pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6);\
- pattrib_iv[4] = txpn._byte_.TSC2;\
- pattrib_iv[5] = txpn._byte_.TSC3;\
- pattrib_iv[6] = txpn._byte_.TSC4;\
- pattrib_iv[7] = txpn._byte_.TSC5;\
- txpn.val = txpn.val == 0xffffffffffffULL ? 0 : \
- (txpn.val + 1);\
-} while (0)
-
-#define AES_IV(pattrib_iv, txpn, keyidx)\
-do { \
- pattrib_iv[0] = txpn._byte_.TSC0;\
- pattrib_iv[1] = txpn._byte_.TSC1;\
- pattrib_iv[2] = 0;\
- pattrib_iv[3] = BIT(5) | ((keyidx & 0x3) << 6);\
- pattrib_iv[4] = txpn._byte_.TSC2;\
- pattrib_iv[5] = txpn._byte_.TSC3;\
- pattrib_iv[6] = txpn._byte_.TSC4;\
- pattrib_iv[7] = txpn._byte_.TSC5;\
- txpn.val = txpn.val == 0xffffffffffffULL ? 0 : \
- (txpn.val + 1);\
-} while (0)
-
-struct hw_xmit {
- spinlock_t xmit_lock;
- struct list_head pending;
- struct __queue *sta_queue;
- struct hw_txqueue *phwtxqueue;
- sint txcmdcnt;
- int accnt;
-};
-
-struct pkt_attrib {
- u8 type;
- u8 subtype;
- u8 bswenc;
- u8 dhcp_pkt;
-
- u16 seqnum;
- u16 ether_type;
- u16 pktlen; /* the original 802.3 pkt raw_data len
- * (not include ether_hdr data)
- */
- u16 last_txcmdsz;
-
- u8 pkt_hdrlen; /*the original 802.3 pkt header len*/
- u8 hdrlen; /*the WLAN Header Len*/
- u8 nr_frags;
- u8 ack_policy;
- u8 mac_id;
- u8 vcs_mode; /*virtual carrier sense method*/
- u8 pctrl;/*per packet txdesc control enable*/
- u8 qsel;
-
- u8 priority;
- u8 encrypt; /* when 0 indicate no encrypt. when non-zero,
- * indicate the encrypt algorithm
- */
- u8 iv_len;
- u8 icv_len;
- unsigned char iv[8];
- unsigned char icv[8];
- u8 dst[ETH_ALEN] __aligned(2); /* for ether_addr_copy */
- u8 src[ETH_ALEN];
- u8 ta[ETH_ALEN];
- u8 ra[ETH_ALEN];
- struct sta_info *psta;
-};
-
-#define WLANHDR_OFFSET 64
-#define DATA_FRAMETAG 0x01
-#define L2_FRAMETAG 0x02
-#define MGNT_FRAMETAG 0x03
-#define AMSDU_FRAMETAG 0x04
-#define EII_FRAMETAG 0x05
-#define IEEE8023_FRAMETAG 0x06
-#define MP_FRAMETAG 0x07
-#define TXAGG_FRAMETAG 0x08
-
-struct xmit_buf {
- struct list_head list;
-
- u8 *pallocated_buf;
- u8 *pbuf;
- void *priv_data;
- struct urb *pxmit_urb[8];
- u32 aggr_nr;
-};
-
-struct xmit_frame {
- struct list_head list;
- struct pkt_attrib attrib;
- _pkt *pkt;
- int frame_tag;
- struct _adapter *padapter;
- u8 *buf_addr;
- struct xmit_buf *pxmitbuf;
- u8 *mem_addr;
- u16 sz[8];
- struct urb *pxmit_urb[8];
- u8 bpending[8];
- u8 last[8];
-};
-
-struct tx_servq {
- struct list_head tx_pending;
- struct __queue sta_pending;
- int qcnt;
-};
-
-struct sta_xmit_priv {
- spinlock_t lock;
- sint option;
- sint apsd_setting; /* When bit mask is on, the associated edca
- * queue supports APSD.
- */
- struct tx_servq be_q; /* priority == 0,3 */
- struct tx_servq bk_q; /* priority == 1,2*/
- struct tx_servq vi_q; /*priority == 4,5*/
- struct tx_servq vo_q; /*priority == 6,7*/
- struct list_head legacy_dz;
- struct list_head apsd;
- u16 txseq_tid[16];
- uint sta_tx_bytes;
- u64 sta_tx_pkts;
- uint sta_tx_fail;
-};
-
-struct hw_txqueue {
- sint head;
- sint tail;
- sint free_sz; /* in units of 64 bytes */
- sint free_cmdsz;
- sint txsz[8];
- uint ff_hwaddr;
- uint cmd_hwaddr;
- sint ac_tag;
-};
-
-struct xmit_priv {
- spinlock_t lock;
- struct __queue be_pending;
- struct __queue bk_pending;
- struct __queue vi_pending;
- struct __queue vo_pending;
- struct __queue bm_pending;
- struct __queue legacy_dz_queue;
- struct __queue apsd_queue;
- u8 *pallocated_frame_buf;
- u8 *pxmit_frame_buf;
- uint free_xmitframe_cnt;
- uint mapping_addr;
- uint pkt_sz;
- struct __queue free_xmit_queue;
- struct hw_txqueue be_txqueue;
- struct hw_txqueue bk_txqueue;
- struct hw_txqueue vi_txqueue;
- struct hw_txqueue vo_txqueue;
- struct hw_txqueue bmc_txqueue;
- uint frag_len;
- struct _adapter *adapter;
- u8 vcs_setting;
- u8 vcs;
- u8 vcs_type;
- u16 rts_thresh;
- uint tx_bytes;
- u64 tx_pkts;
- uint tx_drop;
- struct hw_xmit *hwxmits;
- u8 hwxmit_entry;
- u8 txirp_cnt;
- struct tasklet_struct xmit_tasklet;
- struct work_struct xmit_pipe4_reset_wi;
- struct work_struct xmit_pipe6_reset_wi;
- struct work_struct xmit_piped_reset_wi;
- /*per AC pending irp*/
- int beq_cnt;
- int bkq_cnt;
- int viq_cnt;
- int voq_cnt;
- struct __queue free_amsdu_xmit_queue;
- u8 *pallocated_amsdu_frame_buf;
- u8 *pxmit_amsdu_frame_buf;
- uint free_amsdu_xmitframe_cnt;
- struct __queue free_txagg_xmit_queue;
- u8 *pallocated_txagg_frame_buf;
- u8 *pxmit_txagg_frame_buf;
- uint free_txagg_xmitframe_cnt;
- int cmdseq;
- struct __queue free_xmitbuf_queue;
- struct __queue pending_xmitbuf_queue;
- u8 *pxmitbuf;
- uint free_xmitbuf_cnt;
-};
-
-void r8712_free_xmitbuf(struct xmit_priv *pxmitpriv,
- struct xmit_buf *pxmitbuf);
-struct xmit_buf *r8712_alloc_xmitbuf(struct xmit_priv *pxmitpriv);
-void r8712_update_protection(struct _adapter *padapter, u8 *ie, uint ie_len);
-struct xmit_frame *r8712_alloc_xmitframe(struct xmit_priv *pxmitpriv);
-void r8712_free_xmitframe(struct xmit_priv *pxmitpriv,
- struct xmit_frame *pxmitframe);
-void r8712_free_xmitframe_queue(struct xmit_priv *pxmitpriv,
- struct __queue *pframequeue);
-int r8712_xmit_classifier(struct _adapter *padapter,
- struct xmit_frame *pxmitframe);
-sint r8712_xmitframe_coalesce(struct _adapter *padapter, _pkt *pkt,
- struct xmit_frame *pxmitframe);
-sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag);
-void _r8712_init_sta_xmit_priv(struct sta_xmit_priv *psta_xmitpriv);
-int r8712_update_attrib(struct _adapter *padapter, _pkt *pkt,
- struct pkt_attrib *pattrib);
-int r8712_txframes_sta_ac_pending(struct _adapter *padapter,
- struct pkt_attrib *pattrib);
-int _r8712_init_xmit_priv(struct xmit_priv *pxmitpriv,
- struct _adapter *padapter);
-void _free_xmit_priv(struct xmit_priv *pxmitpriv);
-void r8712_free_xmitframe_ex(struct xmit_priv *pxmitpriv,
- struct xmit_frame *pxmitframe);
-int r8712_pre_xmit(struct _adapter *padapter, struct xmit_frame *pxmitframe);
-int r8712_xmit_enqueue(struct _adapter *padapter,
- struct xmit_frame *pxmitframe);
-void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe);
-void r8712_xmit_bh(struct tasklet_struct *t);
-
-void xmitframe_xmitbuf_attach(struct xmit_frame *pxmitframe,
- struct xmit_buf *pxmitbuf);
-
-#include "rtl8712_xmit.h"
-
-#endif /*_RTL871X_XMIT_H_*/
-
diff --git a/drivers/staging/rtl8712/sta_info.h b/drivers/staging/rtl8712/sta_info.h
deleted file mode 100644
index 6286c622475e..000000000000
--- a/drivers/staging/rtl8712/sta_info.h
+++ /dev/null
@@ -1,132 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __STA_INFO_H_
-#define __STA_INFO_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "wifi.h"
-
-#define NUM_STA 32
-#define NUM_ACL 64
-
-/* if mode ==0, then the sta is allowed once the addr is hit.
- * if mode ==1, then the sta is rejected once the addr is non-hit.
- */
-struct wlan_acl_node {
- struct list_head list;
- u8 addr[ETH_ALEN];
- u8 mode;
-};
-
-struct wlan_acl_pool {
- struct wlan_acl_node aclnode[NUM_ACL];
-};
-
-struct stainfo_stats {
- uint rx_pkts;
- uint rx_bytes;
- u64 tx_pkts;
- uint tx_bytes;
-};
-
-struct sta_info {
- spinlock_t lock;
- struct list_head list; /*free_sta_queue*/
- struct list_head hash_list; /*sta_hash*/
- struct sta_xmit_priv sta_xmitpriv;
- struct sta_recv_priv sta_recvpriv;
- uint state;
- uint aid;
- uint mac_id;
- uint qos_option;
- u8 hwaddr[ETH_ALEN];
- uint ieee8021x_blocked; /*0: allowed, 1:blocked */
- uint XPrivacy; /*aes, tkip...*/
- union Keytype tkiptxmickey;
- union Keytype tkiprxmickey;
- union Keytype x_UncstKey;
- union pn48 txpn; /* PN48 used for Unicast xmit.*/
- union pn48 rxpn; /* PN48 used for Unicast recv.*/
- u8 bssrateset[16];
- uint bssratelen;
- s32 rssi;
- s32 signal_quality;
- struct stainfo_stats sta_stats;
- /*for A-MPDU Rx reordering buffer control */
- struct recv_reorder_ctrl recvreorder_ctrl[16];
- struct ht_priv htpriv;
- /* Notes:
- * STA_Mode:
- * curr_network(mlme_priv/security_priv/qos/ht)
- * + sta_info: (STA & AP) CAP/INFO
- * scan_q: AP CAP/INFO
- * AP_Mode:
- * curr_network(mlme_priv/security_priv/qos/ht) : AP CAP/INFO
- * sta_info: (AP & STA) CAP/INFO
- */
- struct list_head asoc_list;
- struct list_head auth_list;
- unsigned int expire_to;
- unsigned int auth_seq;
- unsigned int authalg;
- unsigned char chg_txt[128];
- unsigned int tx_ra_bitmap;
-};
-
-struct sta_priv {
- u8 *pallocated_stainfo_buf;
- u8 *pstainfo_buf;
- struct __queue free_sta_queue;
- spinlock_t sta_hash_lock;
- struct list_head sta_hash[NUM_STA];
- int asoc_sta_count;
- struct __queue sleep_q;
- struct __queue wakeup_q;
- struct _adapter *padapter;
- struct list_head asoc_list;
- struct list_head auth_list;
- unsigned int auth_to; /* sec, time to expire in authenticating. */
- unsigned int assoc_to; /* sec, time to expire before associating. */
- unsigned int expire_to; /* sec , time to expire after associated. */
-};
-
-static inline u32 wifi_mac_hash(u8 *mac)
-{
- u32 x;
-
- x = mac[0];
- x = (x << 2) ^ mac[1];
- x = (x << 2) ^ mac[2];
- x = (x << 2) ^ mac[3];
- x = (x << 2) ^ mac[4];
- x = (x << 2) ^ mac[5];
- x ^= x >> 8;
- x = x & (NUM_STA - 1);
- return x;
-}
-
-int _r8712_init_sta_priv(struct sta_priv *pstapriv);
-void _r8712_free_sta_priv(struct sta_priv *pstapriv);
-struct sta_info *r8712_alloc_stainfo(struct sta_priv *pstapriv,
- u8 *hwaddr);
-void r8712_free_stainfo(struct _adapter *padapter, struct sta_info *psta);
-void r8712_free_all_stainfo(struct _adapter *padapter);
-struct sta_info *r8712_get_stainfo(struct sta_priv *pstapriv, u8 *hwaddr);
-void r8712_init_bcmc_stainfo(struct _adapter *padapter);
-struct sta_info *r8712_get_bcmc_stainfo(struct _adapter *padapter);
-u8 r8712_access_ctrl(struct wlan_acl_pool *pacl_list, u8 *mac_addr);
-
-#endif /* _STA_INFO_H_ */
-
diff --git a/drivers/staging/rtl8712/usb_halinit.c b/drivers/staging/rtl8712/usb_halinit.c
deleted file mode 100644
index 313c569748e9..000000000000
--- a/drivers/staging/rtl8712/usb_halinit.c
+++ /dev/null
@@ -1,307 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * usb_halinit.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _HCI_HAL_INIT_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "usb_ops.h"
-#include "usb_osintf.h"
-
-u8 r8712_usb_hal_bus_init(struct _adapter *adapter)
-{
- u8 val8 = 0;
- u8 ret = _SUCCESS;
- int PollingCnt = 20;
- struct registry_priv *registrypriv = &adapter->registrypriv;
-
- if (registrypriv->chip_version == RTL8712_FPGA) {
- val8 = 0x01;
- /* switch to 80M clock */
- r8712_write8(adapter, SYS_CLKR, val8);
- val8 = r8712_read8(adapter, SPS1_CTRL);
- val8 = val8 | 0x01;
- /* enable VSPS12 LDO Macro block */
- r8712_write8(adapter, SPS1_CTRL, val8);
- val8 = r8712_read8(adapter, AFE_MISC);
- val8 = val8 | 0x01;
- /* Enable AFE Macro Block's Bandgap */
- r8712_write8(adapter, AFE_MISC, val8);
- val8 = r8712_read8(adapter, LDOA15_CTRL);
- val8 = val8 | 0x01;
- /* enable LDOA15 block */
- r8712_write8(adapter, LDOA15_CTRL, val8);
- val8 = r8712_read8(adapter, SPS1_CTRL);
- val8 = val8 | 0x02;
- /* Enable VSPS12_SW Macro Block */
- r8712_write8(adapter, SPS1_CTRL, val8);
- val8 = r8712_read8(adapter, AFE_MISC);
- val8 = val8 | 0x02;
- /* Enable AFE Macro Block's Mbias */
- r8712_write8(adapter, AFE_MISC, val8);
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- val8 = val8 | 0x08;
- /* isolate PCIe Analog 1.2V to PCIe 3.3V and PCIE Digital */
- r8712_write8(adapter, SYS_ISO_CTRL + 1, val8);
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- val8 = val8 & 0xEF;
- /* attach AFE PLL to MACTOP/BB/PCIe Digital */
- r8712_write8(adapter, SYS_ISO_CTRL + 1, val8);
- val8 = r8712_read8(adapter, AFE_XTAL_CTRL + 1);
- val8 = val8 & 0xFB;
- /* enable AFE clock */
- r8712_write8(adapter, AFE_XTAL_CTRL + 1, val8);
- val8 = r8712_read8(adapter, AFE_PLL_CTRL);
- val8 = val8 | 0x01;
- /* Enable AFE PLL Macro Block */
- r8712_write8(adapter, AFE_PLL_CTRL, val8);
- val8 = 0xEE;
- /* release isolation AFE PLL & MD */
- r8712_write8(adapter, SYS_ISO_CTRL, val8);
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- val8 = val8 | 0x08;
- /* enable MAC clock */
- r8712_write8(adapter, SYS_CLKR + 1, val8);
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- val8 = val8 | 0x08;
- /* enable Core digital and enable IOREG R/W */
- r8712_write8(adapter, SYS_FUNC_EN + 1, val8);
- val8 = val8 | 0x80;
- /* enable REG_EN */
- r8712_write8(adapter, SYS_FUNC_EN + 1, val8);
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- val8 = (val8 | 0x80) & 0xBF;
- /* switch the control path */
- r8712_write8(adapter, SYS_CLKR + 1, val8);
- val8 = 0xFC;
- r8712_write8(adapter, CR, val8);
- val8 = 0x37;
- r8712_write8(adapter, CR + 1, val8);
- /* reduce EndPoint & init it */
- r8712_write8(adapter, 0x102500ab, r8712_read8(adapter,
- 0x102500ab) | BIT(6) | BIT(7));
- /* consideration of power consumption - init */
- r8712_write8(adapter, 0x10250008, r8712_read8(adapter,
- 0x10250008) & 0xfffffffb);
- } else if (registrypriv->chip_version == RTL8712_1stCUT) {
- /* Initialization for power on sequence, */
- r8712_write8(adapter, SPS0_CTRL + 1, 0x53);
- r8712_write8(adapter, SPS0_CTRL, 0x57);
- /* Enable AFE Macro Block's Bandgap and Enable AFE Macro
- * Block's Mbias
- */
- val8 = r8712_read8(adapter, AFE_MISC);
- r8712_write8(adapter, AFE_MISC, (val8 | AFE_MISC_BGEN |
- AFE_MISC_MBEN));
- /* Enable LDOA15 block */
- val8 = r8712_read8(adapter, LDOA15_CTRL);
- r8712_write8(adapter, LDOA15_CTRL, (val8 | LDA15_EN));
- val8 = r8712_read8(adapter, SPS1_CTRL);
- r8712_write8(adapter, SPS1_CTRL, (val8 | SPS1_LDEN));
- msleep(20);
- /* Enable Switch Regulator Block */
- val8 = r8712_read8(adapter, SPS1_CTRL);
- r8712_write8(adapter, SPS1_CTRL, (val8 | SPS1_SWEN));
- r8712_write32(adapter, SPS1_CTRL, 0x00a7b267);
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 | 0x08));
- /* Engineer Packet CP test Enable */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x20));
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 & 0x6F));
- /* Enable AFE clock */
- val8 = r8712_read8(adapter, AFE_XTAL_CTRL + 1);
- r8712_write8(adapter, AFE_XTAL_CTRL + 1, (val8 & 0xfb));
- /* Enable AFE PLL Macro Block */
- val8 = r8712_read8(adapter, AFE_PLL_CTRL);
- r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x11));
- /* Attach AFE PLL to MACTOP/BB/PCIe Digital */
- val8 = r8712_read8(adapter, SYS_ISO_CTRL);
- r8712_write8(adapter, SYS_ISO_CTRL, (val8 & 0xEE));
- /* Switch to 40M clock */
- val8 = r8712_read8(adapter, SYS_CLKR);
- r8712_write8(adapter, SYS_CLKR, val8 & (~SYS_CLKSEL));
- /* SSC Disable */
- val8 = r8712_read8(adapter, SYS_CLKR);
- /* Enable MAC clock */
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x18));
- /* Revised POS, */
- r8712_write8(adapter, PMC_FSM, 0x02);
- /* Enable Core digital and enable IOREG R/W */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x08));
- /* Enable REG_EN */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x80));
- /* Switch the control path to FW */
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x80) & 0xBF);
- r8712_write8(adapter, CR, 0xFC);
- r8712_write8(adapter, CR + 1, 0x37);
- /* Fix the RX FIFO issue(usb error), */
- val8 = r8712_read8(adapter, 0x1025FE5c);
- r8712_write8(adapter, 0x1025FE5c, (val8 | BIT(7)));
- val8 = r8712_read8(adapter, 0x102500ab);
- r8712_write8(adapter, 0x102500ab, (val8 | BIT(6) | BIT(7)));
- /* For power save, used this in the bit file after 970621 */
- val8 = r8712_read8(adapter, SYS_CLKR);
- r8712_write8(adapter, SYS_CLKR, val8 & (~CPU_CLKSEL));
- } else if (registrypriv->chip_version == RTL8712_2ndCUT ||
- registrypriv->chip_version == RTL8712_3rdCUT) {
- /* Initialization for power on sequence,
- * E-Fuse leakage prevention sequence
- */
- r8712_write8(adapter, 0x37, 0xb0);
- msleep(20);
- r8712_write8(adapter, 0x37, 0x30);
- /* Set control path switch to HW control and reset Digital Core,
- * CPU Core and MAC I/O to solve FW download fail when system
- * from resume sate.
- */
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- if (val8 & 0x80) {
- val8 &= 0x3f;
- r8712_write8(adapter, SYS_CLKR + 1, val8);
- }
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- val8 &= 0x73;
- r8712_write8(adapter, SYS_FUNC_EN + 1, val8);
- msleep(20);
- /* Revised POS, */
- /* Enable AFE Macro Block's Bandgap and Enable AFE Macro
- * Block's Mbias
- */
- r8712_write8(adapter, SPS0_CTRL + 1, 0x53);
- r8712_write8(adapter, SPS0_CTRL, 0x57);
- val8 = r8712_read8(adapter, AFE_MISC);
- /*Bandgap*/
- r8712_write8(adapter, AFE_MISC, (val8 | AFE_MISC_BGEN));
- r8712_write8(adapter, AFE_MISC, (val8 | AFE_MISC_BGEN |
- AFE_MISC_MBEN | AFE_MISC_I32_EN));
- /* Enable PLL Power (LDOA15V) */
- val8 = r8712_read8(adapter, LDOA15_CTRL);
- r8712_write8(adapter, LDOA15_CTRL, (val8 | LDA15_EN));
- /* Enable LDOV12D block */
- val8 = r8712_read8(adapter, LDOV12D_CTRL);
- r8712_write8(adapter, LDOV12D_CTRL, (val8 | LDV12_EN));
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 | 0x08));
- /* Engineer Packet CP test Enable */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x20));
- /* Support 64k IMEM */
- val8 = r8712_read8(adapter, SYS_ISO_CTRL + 1);
- r8712_write8(adapter, SYS_ISO_CTRL + 1, (val8 & 0x68));
- /* Enable AFE clock */
- val8 = r8712_read8(adapter, AFE_XTAL_CTRL + 1);
- r8712_write8(adapter, AFE_XTAL_CTRL + 1, (val8 & 0xfb));
- /* Enable AFE PLL Macro Block */
- val8 = r8712_read8(adapter, AFE_PLL_CTRL);
- r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x11));
- /* Some sample will download fw failure. The clock will be
- * stable with 500 us delay after reset the PLL
- * TODO: When usleep is added to kernel, change next 3
- * udelay(500) to usleep(500)
- */
- udelay(500);
- r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x51));
- udelay(500);
- r8712_write8(adapter, AFE_PLL_CTRL, (val8 | 0x11));
- udelay(500);
- /* Attach AFE PLL to MACTOP/BB/PCIe Digital */
- val8 = r8712_read8(adapter, SYS_ISO_CTRL);
- r8712_write8(adapter, SYS_ISO_CTRL, (val8 & 0xEE));
- /* Switch to 40M clock */
- r8712_write8(adapter, SYS_CLKR, 0x00);
- /* CPU Clock and 80M Clock SSC Disable to overcome FW download
- * fail timing issue.
- */
- val8 = r8712_read8(adapter, SYS_CLKR);
- r8712_write8(adapter, SYS_CLKR, (val8 | 0xa0));
- /* Enable MAC clock */
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x18));
- /* Revised POS, */
- r8712_write8(adapter, PMC_FSM, 0x02);
- /* Enable Core digital and enable IOREG R/W */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x08));
- /* Enable REG_EN */
- val8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
- r8712_write8(adapter, SYS_FUNC_EN + 1, (val8 | 0x80));
- /* Switch the control path to FW */
- val8 = r8712_read8(adapter, SYS_CLKR + 1);
- r8712_write8(adapter, SYS_CLKR + 1, (val8 | 0x80) & 0xBF);
- r8712_write8(adapter, CR, 0xFC);
- r8712_write8(adapter, CR + 1, 0x37);
- /* Fix the RX FIFO issue(usb error), 970410 */
- val8 = r8712_read8(adapter, 0x1025FE5c);
- r8712_write8(adapter, 0x1025FE5c, (val8 | BIT(7)));
- /* For power save, used this in the bit file after 970621 */
- val8 = r8712_read8(adapter, SYS_CLKR);
- r8712_write8(adapter, SYS_CLKR, val8 & (~CPU_CLKSEL));
- /* Revised for 8051 ROM code wrong operation. */
- r8712_write8(adapter, 0x1025fe1c, 0x80);
- /* To make sure that TxDMA can ready to download FW.
- * We should reset TxDMA if IMEM RPT was not ready.
- */
- do {
- val8 = r8712_read8(adapter, TCR);
- if ((val8 & _TXDMA_INIT_VALUE) == _TXDMA_INIT_VALUE)
- break;
- udelay(5); /* PlatformStallExecution(5); */
- } while (PollingCnt--); /* Delay 1ms */
-
- if (PollingCnt <= 0) {
- val8 = r8712_read8(adapter, CR);
- r8712_write8(adapter, CR, val8 & (~_TXDMA_EN));
- udelay(2); /* PlatformStallExecution(2); */
- /* Reset TxDMA */
- r8712_write8(adapter, CR, val8 | _TXDMA_EN);
- }
- } else {
- ret = _FAIL;
- }
- return ret;
-}
-
-unsigned int r8712_usb_inirp_init(struct _adapter *adapter)
-{
- u8 i;
- struct recv_buf *recvbuf;
- struct intf_hdl *intfhdl = &adapter->pio_queue->intf;
- struct recv_priv *recvpriv = &(adapter->recvpriv);
-
- recvpriv->ff_hwaddr = RTL8712_DMA_RX0FF; /* mapping rx fifo address */
- /* issue Rx irp to receive data */
- recvbuf = (struct recv_buf *)recvpriv->precv_buf;
- for (i = 0; i < NR_RECVBUFF; i++) {
- if (r8712_usb_read_port(intfhdl, recvpriv->ff_hwaddr, 0,
- (unsigned char *)recvbuf) == false)
- return _FAIL;
- recvbuf++;
- recvpriv->free_recv_buf_queue_cnt--;
- }
- return _SUCCESS;
-}
-
-unsigned int r8712_usb_inirp_deinit(struct _adapter *adapter)
-{
- r8712_usb_read_port_cancel(adapter);
- return _SUCCESS;
-}
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
deleted file mode 100644
index df05213f922f..000000000000
--- a/drivers/staging/rtl8712/usb_intf.c
+++ /dev/null
@@ -1,638 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * usb_intf.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _HCI_INTF_C_
-
-#include <linux/usb.h>
-#include <linux/module.h>
-#include <linux/firmware.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "recv_osdep.h"
-#include "xmit_osdep.h"
-#include "rtl8712_efuse.h"
-#include "usb_ops.h"
-#include "usb_osintf.h"
-
-static struct usb_interface *pintf;
-
-static int r871xu_drv_init(struct usb_interface *pusb_intf,
- const struct usb_device_id *pdid);
-
-static void r871xu_dev_remove(struct usb_interface *pusb_intf);
-
-static const struct usb_device_id rtl871x_usb_id_tbl[] = {
-/* RTL8188SU */
- /* Realtek */
- {USB_DEVICE(0x0BDA, 0x8171)},
- {USB_DEVICE(0x0bda, 0x8173)},
- {USB_DEVICE(0x0bda, 0x8712)},
- {USB_DEVICE(0x0bda, 0x8713)},
- {USB_DEVICE(0x0bda, 0xC512)},
- /* Abocom */
- {USB_DEVICE(0x07B8, 0x8188)},
- /* ASUS */
- {USB_DEVICE(0x0B05, 0x1786)},
- {USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */
- /* Belkin */
- {USB_DEVICE(0x050D, 0x945A)},
- /* ISY IWL - Belkin clone */
- {USB_DEVICE(0x050D, 0x11F1)},
- /* Corega */
- {USB_DEVICE(0x07AA, 0x0047)},
- /* D-Link */
- {USB_DEVICE(0x2001, 0x3306)},
- {USB_DEVICE(0x07D1, 0x3306)}, /* 11n mode disable */
- /* Edimax */
- {USB_DEVICE(0x7392, 0x7611)},
- /* EnGenius */
- {USB_DEVICE(0x1740, 0x9603)},
- /* Hawking */
- {USB_DEVICE(0x0E66, 0x0016)},
- /* Hercules */
- {USB_DEVICE(0x06F8, 0xE034)},
- {USB_DEVICE(0x06F8, 0xE032)},
- /* Logitec */
- {USB_DEVICE(0x0789, 0x0167)},
- /* PCI */
- {USB_DEVICE(0x2019, 0xAB28)},
- {USB_DEVICE(0x2019, 0xED16)},
- /* Sitecom */
- {USB_DEVICE(0x0DF6, 0x0057)},
- {USB_DEVICE(0x0DF6, 0x0045)},
- {USB_DEVICE(0x0DF6, 0x0059)}, /* 11n mode disable */
- {USB_DEVICE(0x0DF6, 0x004B)},
- {USB_DEVICE(0x0DF6, 0x005B)},
- {USB_DEVICE(0x0DF6, 0x005D)},
- {USB_DEVICE(0x0DF6, 0x0063)},
- /* Sweex */
- {USB_DEVICE(0x177F, 0x0154)},
- /* Thinkware */
- {USB_DEVICE(0x0BDA, 0x5077)},
- /* Toshiba */
- {USB_DEVICE(0x1690, 0x0752)},
- /* - */
- {USB_DEVICE(0x20F4, 0x646B)},
- {USB_DEVICE(0x083A, 0xC512)},
- {USB_DEVICE(0x25D4, 0x4CA1)},
- {USB_DEVICE(0x25D4, 0x4CAB)},
-
-/* RTL8191SU */
- /* Realtek */
- {USB_DEVICE(0x0BDA, 0x8172)},
- {USB_DEVICE(0x0BDA, 0x8192)},
- /* Amigo */
- {USB_DEVICE(0x0EB0, 0x9061)},
- /* ASUS/EKB */
- {USB_DEVICE(0x13D3, 0x3323)},
- {USB_DEVICE(0x13D3, 0x3311)}, /* 11n mode disable */
- {USB_DEVICE(0x13D3, 0x3342)},
- /* ASUS/EKBLenovo */
- {USB_DEVICE(0x13D3, 0x3333)},
- {USB_DEVICE(0x13D3, 0x3334)},
- {USB_DEVICE(0x13D3, 0x3335)}, /* 11n mode disable */
- {USB_DEVICE(0x13D3, 0x3336)}, /* 11n mode disable */
- /* ASUS/Media BOX */
- {USB_DEVICE(0x13D3, 0x3309)},
- /* Belkin */
- {USB_DEVICE(0x050D, 0x815F)},
- /* D-Link */
- {USB_DEVICE(0x07D1, 0x3302)},
- {USB_DEVICE(0x07D1, 0x3300)},
- {USB_DEVICE(0x07D1, 0x3303)},
- /* Edimax */
- {USB_DEVICE(0x7392, 0x7612)},
- /* EnGenius */
- {USB_DEVICE(0x1740, 0x9605)},
- /* Guillemot */
- {USB_DEVICE(0x06F8, 0xE031)},
- /* Hawking */
- {USB_DEVICE(0x0E66, 0x0015)},
- /* Mediao */
- {USB_DEVICE(0x13D3, 0x3306)},
- /* PCI */
- {USB_DEVICE(0x2019, 0xED18)},
- {USB_DEVICE(0x2019, 0x4901)},
- /* Sitecom */
- {USB_DEVICE(0x0DF6, 0x0058)},
- {USB_DEVICE(0x0DF6, 0x0049)},
- {USB_DEVICE(0x0DF6, 0x004C)},
- {USB_DEVICE(0x0DF6, 0x006C)},
- {USB_DEVICE(0x0DF6, 0x0064)},
- /* Skyworth */
- {USB_DEVICE(0x14b2, 0x3300)},
- {USB_DEVICE(0x14b2, 0x3301)},
- {USB_DEVICE(0x14B2, 0x3302)},
- /* - */
- {USB_DEVICE(0x04F2, 0xAFF2)},
- {USB_DEVICE(0x04F2, 0xAFF5)},
- {USB_DEVICE(0x04F2, 0xAFF6)},
- {USB_DEVICE(0x13D3, 0x3339)},
- {USB_DEVICE(0x13D3, 0x3340)}, /* 11n mode disable */
- {USB_DEVICE(0x13D3, 0x3341)}, /* 11n mode disable */
- {USB_DEVICE(0x13D3, 0x3310)},
- {USB_DEVICE(0x13D3, 0x3325)},
-
-/* RTL8192SU */
- /* Realtek */
- {USB_DEVICE(0x0BDA, 0x8174)},
- /* Belkin */
- {USB_DEVICE(0x050D, 0x845A)},
- /* Corega */
- {USB_DEVICE(0x07AA, 0x0051)},
- /* Edimax */
- {USB_DEVICE(0x7392, 0x7622)},
- /* NEC */
- {USB_DEVICE(0x0409, 0x02B6)},
- {}
-};
-
-MODULE_DEVICE_TABLE(usb, rtl871x_usb_id_tbl);
-
-static struct specific_device_id specific_device_id_tbl[] = {
- {.idVendor = 0x0b05, .idProduct = 0x1791,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x0df6, .idProduct = 0x0059,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13d3, .idProduct = 0x3306,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13D3, .idProduct = 0x3311,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13d3, .idProduct = 0x3335,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13d3, .idProduct = 0x3336,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13d3, .idProduct = 0x3340,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {.idVendor = 0x13d3, .idProduct = 0x3341,
- .flags = SPEC_DEV_ID_DISABLE_HT},
- {}
-};
-
-struct drv_priv {
- struct usb_driver r871xu_drv;
- int drv_registered;
-};
-
-#ifdef CONFIG_PM
-static int r871x_suspend(struct usb_interface *pusb_intf, pm_message_t state)
-{
- struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
- struct _adapter *padapter = netdev_priv(pnetdev);
-
- netdev_info(pnetdev, "Suspending...\n");
- padapter->suspended = true;
- rtl871x_intf_stop(padapter);
- if (pnetdev->netdev_ops->ndo_stop)
- pnetdev->netdev_ops->ndo_stop(pnetdev);
- mdelay(10);
- netif_device_detach(pnetdev);
- return 0;
-}
-
-static void rtl871x_intf_resume(struct _adapter *padapter)
-{
- if (padapter->dvobjpriv.inirp_init)
- padapter->dvobjpriv.inirp_init(padapter);
-}
-
-static int r871x_resume(struct usb_interface *pusb_intf)
-{
- struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
- struct _adapter *padapter = netdev_priv(pnetdev);
-
- netdev_info(pnetdev, "Resuming...\n");
- netif_device_attach(pnetdev);
- if (pnetdev->netdev_ops->ndo_open)
- pnetdev->netdev_ops->ndo_open(pnetdev);
- padapter->suspended = false;
- rtl871x_intf_resume(padapter);
- return 0;
-}
-#endif
-
-static struct drv_priv drvpriv = {
- .r871xu_drv.name = "r8712u",
- .r871xu_drv.id_table = rtl871x_usb_id_tbl,
- .r871xu_drv.probe = r871xu_drv_init,
- .r871xu_drv.disconnect = r871xu_dev_remove,
-#ifdef CONFIG_PM
- .r871xu_drv.suspend = r871x_suspend,
- .r871xu_drv.resume = r871x_resume,
-#endif
-};
-
-static uint r8712_usb_dvobj_init(struct _adapter *padapter)
-{
- uint status = _SUCCESS;
- struct usb_host_interface *phost_iface;
- struct usb_interface_descriptor *piface_desc;
- struct dvobj_priv *pdvobjpriv = &padapter->dvobjpriv;
- struct usb_device *pusbd = pdvobjpriv->pusbdev;
-
- pdvobjpriv->padapter = padapter;
- padapter->eeprom_address_size = 6;
- phost_iface = pintf->cur_altsetting;
- piface_desc = &phost_iface->desc;
- pdvobjpriv->nr_endpoint = piface_desc->bNumEndpoints;
- if (pusbd->speed == USB_SPEED_HIGH) {
- pdvobjpriv->ishighspeed = true;
- dev_info(&pusbd->dev, "r8712u: USB_SPEED_HIGH with %d endpoints\n",
- pdvobjpriv->nr_endpoint);
- } else {
- pdvobjpriv->ishighspeed = false;
- dev_info(&pusbd->dev, "r8712u: USB_SPEED_LOW with %d endpoints\n",
- pdvobjpriv->nr_endpoint);
- }
- if ((r8712_alloc_io_queue(padapter)) == _FAIL)
- status = _FAIL;
- return status;
-}
-
-static void r8712_usb_dvobj_deinit(struct _adapter *padapter)
-{
- r8712_free_io_queue(padapter);
-}
-
-void rtl871x_intf_stop(struct _adapter *padapter)
-{
- /*disable_hw_interrupt*/
- if (!padapter->surprise_removed) {
- /*device still exists, so driver can do i/o operation
- * TODO:
- */
- }
-
- /* cancel in irp */
- if (padapter->dvobjpriv.inirp_deinit)
- padapter->dvobjpriv.inirp_deinit(padapter);
- /* cancel out irp */
- r8712_usb_write_port_cancel(padapter);
- /* TODO:cancel other irps */
-}
-
-void r871x_dev_unload(struct _adapter *padapter)
-{
- if (padapter->bup) {
- /*s1.*/
- padapter->driver_stopped = true;
-
- /*s3.*/
- rtl871x_intf_stop(padapter);
-
- /*s4.*/
- r8712_stop_drv_threads(padapter);
-
- /*s5.*/
- if (!padapter->surprise_removed) {
- padapter->hw_init_completed = false;
- rtl8712_hal_deinit(padapter);
- }
-
- padapter->bup = false;
- }
-}
-
-static void disable_ht_for_spec_devid(const struct usb_device_id *pdid,
- struct _adapter *padapter)
-{
- u16 vid, pid;
- u32 flags;
- int i;
- int num = ARRAY_SIZE(specific_device_id_tbl);
-
- for (i = 0; i < num; i++) {
- vid = specific_device_id_tbl[i].idVendor;
- pid = specific_device_id_tbl[i].idProduct;
- flags = specific_device_id_tbl[i].flags;
-
- if ((pdid->idVendor == vid) && (pdid->idProduct == pid) &&
- (flags & SPEC_DEV_ID_DISABLE_HT)) {
- padapter->registrypriv.ht_enable = 0;
- padapter->registrypriv.cbw40_enable = 0;
- padapter->registrypriv.ampdu_enable = 0;
- }
- }
-}
-
-static const struct device_type wlan_type = {
- .name = "wlan",
-};
-
-/*
- * drv_init() - a device potentially for us
- *
- * notes: drv_init() is called when the bus driver has located a card for us
- * to support. We accept the new device by returning 0.
- */
-static int r871xu_drv_init(struct usb_interface *pusb_intf,
- const struct usb_device_id *pdid)
-{
- uint status;
- struct _adapter *padapter = NULL;
- struct dvobj_priv *pdvobjpriv;
- struct net_device *pnetdev;
- struct usb_device *udev;
-
- /* In this probe function, O.S. will provide the usb interface pointer
- * to driver. We have to increase the reference count of the usb device
- * structure by using the usb_get_dev function.
- */
- udev = interface_to_usbdev(pusb_intf);
- usb_get_dev(udev);
- pintf = pusb_intf;
- /* step 1. */
- pnetdev = r8712_init_netdev();
- if (!pnetdev)
- goto put_dev;
- padapter = netdev_priv(pnetdev);
- disable_ht_for_spec_devid(pdid, padapter);
- pdvobjpriv = &padapter->dvobjpriv;
- pdvobjpriv->padapter = padapter;
- padapter->dvobjpriv.pusbdev = udev;
- padapter->pusb_intf = pusb_intf;
- usb_set_intfdata(pusb_intf, pnetdev);
- SET_NETDEV_DEV(pnetdev, &pusb_intf->dev);
- pnetdev->dev.type = &wlan_type;
- /* step 2. */
- padapter->dvobj_init = r8712_usb_dvobj_init;
- padapter->dvobj_deinit = r8712_usb_dvobj_deinit;
- padapter->halpriv.hal_bus_init = r8712_usb_hal_bus_init;
- padapter->dvobjpriv.inirp_init = r8712_usb_inirp_init;
- padapter->dvobjpriv.inirp_deinit = r8712_usb_inirp_deinit;
- /* step 3.
- * initialize the dvobj_priv
- */
-
- status = padapter->dvobj_init(padapter);
- if (status != _SUCCESS)
- goto free_netdev;
-
- /* step 4. */
- status = r8712_init_drv_sw(padapter);
- if (status)
- goto dvobj_deinit;
- /* step 5. read efuse/eeprom data and get mac_addr */
- {
- int i, offset;
- u8 mac[6];
- u8 tmpU1b, AutoloadFail, eeprom_CustomerID;
- u8 *pdata = padapter->eeprompriv.efuse_eeprom_data;
-
- tmpU1b = r8712_read8(padapter, EE_9346CR);/*CR9346*/
-
- /* To check system boot selection.*/
- dev_info(&udev->dev, "r8712u: Boot from %s: Autoload %s\n",
- (tmpU1b & _9356SEL) ? "EEPROM" : "EFUSE",
- (tmpU1b & _EEPROM_EN) ? "OK" : "Failed");
-
- /* To check autoload success or not.*/
- if (tmpU1b & _EEPROM_EN) {
- AutoloadFail = true;
- /* The following operations prevent Efuse leakage by
- * turning on 2.5V.
- */
- tmpU1b = r8712_read8(padapter, EFUSE_TEST + 3);
- r8712_write8(padapter, EFUSE_TEST + 3, tmpU1b | 0x80);
- msleep(20);
- r8712_write8(padapter, EFUSE_TEST + 3,
- (tmpU1b & (~BIT(7))));
-
- /* Retrieve Chip version.
- * Recognize IC version by Reg0x4 BIT15.
- */
- tmpU1b = (u8)((r8712_read32(padapter, PMC_FSM) >> 15) &
- 0x1F);
- if (tmpU1b == 0x3)
- padapter->registrypriv.chip_version =
- RTL8712_3rdCUT;
- else
- padapter->registrypriv.chip_version =
- (tmpU1b >> 1) + 1;
- switch (padapter->registrypriv.chip_version) {
- case RTL8712_1stCUT:
- case RTL8712_2ndCUT:
- case RTL8712_3rdCUT:
- break;
- default:
- padapter->registrypriv.chip_version =
- RTL8712_2ndCUT;
- break;
- }
-
- for (i = 0, offset = 0; i < 128; i += 8, offset++)
- r8712_efuse_pg_packet_read(padapter, offset,
- &pdata[i]);
-
- if (!r8712_initmac || !mac_pton(r8712_initmac, mac)) {
- /* Use the mac address stored in the Efuse
- * offset = 0x12 for usb in efuse
- */
- ether_addr_copy(mac, &pdata[0x12]);
- }
- eeprom_CustomerID = pdata[0x52];
- switch (eeprom_CustomerID) {
- case EEPROM_CID_ALPHA:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_ALPHA;
- break;
- case EEPROM_CID_CAMEO:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_CAMEO;
- break;
- case EEPROM_CID_SITECOM:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_Sitecom;
- break;
- case EEPROM_CID_COREGA:
- padapter->eeprompriv.CustomerID =
- RT_CID_COREGA;
- break;
- case EEPROM_CID_Senao:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_Senao;
- break;
- case EEPROM_CID_EDIMAX_BELKIN:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_Edimax_Belkin;
- break;
- case EEPROM_CID_SERCOMM_BELKIN:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_Sercomm_Belkin;
- break;
- case EEPROM_CID_WNC_COREGA:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_WNC_COREGA;
- break;
- case EEPROM_CID_WHQL:
- break;
- case EEPROM_CID_NetCore:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_Netcore;
- break;
- case EEPROM_CID_CAMEO1:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_CAMEO1;
- break;
- case EEPROM_CID_CLEVO:
- padapter->eeprompriv.CustomerID =
- RT_CID_819x_CLEVO;
- break;
- default:
- padapter->eeprompriv.CustomerID =
- RT_CID_DEFAULT;
- break;
- }
- dev_info(&udev->dev, "r8712u: CustomerID = 0x%.4x\n",
- padapter->eeprompriv.CustomerID);
- /* Led mode */
- switch (padapter->eeprompriv.CustomerID) {
- case RT_CID_DEFAULT:
- case RT_CID_819x_ALPHA:
- case RT_CID_819x_CAMEO:
- padapter->ledpriv.LedStrategy = SW_LED_MODE1;
- padapter->ledpriv.bRegUseLed = true;
- break;
- case RT_CID_819x_Sitecom:
- padapter->ledpriv.LedStrategy = SW_LED_MODE2;
- padapter->ledpriv.bRegUseLed = true;
- break;
- case RT_CID_COREGA:
- case RT_CID_819x_Senao:
- padapter->ledpriv.LedStrategy = SW_LED_MODE3;
- padapter->ledpriv.bRegUseLed = true;
- break;
- case RT_CID_819x_Edimax_Belkin:
- padapter->ledpriv.LedStrategy = SW_LED_MODE4;
- padapter->ledpriv.bRegUseLed = true;
- break;
- case RT_CID_819x_Sercomm_Belkin:
- padapter->ledpriv.LedStrategy = SW_LED_MODE5;
- padapter->ledpriv.bRegUseLed = true;
- break;
- case RT_CID_819x_WNC_COREGA:
- padapter->ledpriv.LedStrategy = SW_LED_MODE6;
- padapter->ledpriv.bRegUseLed = true;
- break;
- default:
- padapter->ledpriv.LedStrategy = SW_LED_MODE0;
- padapter->ledpriv.bRegUseLed = false;
- break;
- }
- } else {
- AutoloadFail = false;
- }
- if ((!AutoloadFail) ||
- ((mac[0] == 0xff) && (mac[1] == 0xff) &&
- (mac[2] == 0xff) && (mac[3] == 0xff) &&
- (mac[4] == 0xff) && (mac[5] == 0xff)) ||
- ((mac[0] == 0x00) && (mac[1] == 0x00) &&
- (mac[2] == 0x00) && (mac[3] == 0x00) &&
- (mac[4] == 0x00) && (mac[5] == 0x00))) {
- mac[0] = 0x00;
- mac[1] = 0xe0;
- mac[2] = 0x4c;
- mac[3] = 0x87;
- mac[4] = 0x00;
- mac[5] = 0x00;
- }
- if (r8712_initmac) {
- /* Make sure the user did not select a multicast
- * address by setting bit 1 of first octet.
- */
- mac[0] &= 0xFE;
- dev_info(&udev->dev,
- "r8712u: MAC Address from user = %pM\n", mac);
- } else {
- dev_info(&udev->dev,
- "r8712u: MAC Address from efuse = %pM\n", mac);
- }
- eth_hw_addr_set(pnetdev, mac);
- }
- /* step 6. Load the firmware asynchronously */
- if (rtl871x_load_fw(padapter))
- goto deinit_drv_sw;
- init_completion(&padapter->rx_filter_ready);
- return 0;
-
-deinit_drv_sw:
- r8712_free_drv_sw(padapter);
-dvobj_deinit:
- padapter->dvobj_deinit(padapter);
-free_netdev:
- free_netdev(pnetdev);
-put_dev:
- usb_put_dev(udev);
- usb_set_intfdata(pusb_intf, NULL);
- return -ENODEV;
-}
-
-/* rmmod module & unplug(SurpriseRemoved) will call r871xu_dev_remove()
- * => how to recognize both
- */
-static void r871xu_dev_remove(struct usb_interface *pusb_intf)
-{
- struct net_device *pnetdev = usb_get_intfdata(pusb_intf);
- struct usb_device *udev = interface_to_usbdev(pusb_intf);
- struct _adapter *padapter = netdev_priv(pnetdev);
-
- /* never exit with a firmware callback pending */
- wait_for_completion(&padapter->rtl8712_fw_ready);
- if (pnetdev->reg_state != NETREG_UNINITIALIZED)
- unregister_netdev(pnetdev); /* will call netdev_close() */
- usb_set_intfdata(pusb_intf, NULL);
- release_firmware(padapter->fw);
- if (drvpriv.drv_registered)
- padapter->surprise_removed = true;
- r8712_flush_rwctrl_works(padapter);
- r8712_flush_led_works(padapter);
- udelay(1);
- /* Stop driver mlme relation timer */
- r8712_stop_drv_timers(padapter);
- r871x_dev_unload(padapter);
- if (padapter->dvobj_deinit)
- padapter->dvobj_deinit(padapter);
- r8712_free_drv_sw(padapter);
- free_netdev(pnetdev);
-
- /* decrease the reference count of the usb device structure
- * when disconnect
- */
- usb_put_dev(udev);
-
- /* If we didn't unplug usb dongle and remove/insert module, driver
- * fails on sitesurvey for the first time when device is up.
- * Reset usb port for sitesurvey fail issue.
- */
- if (udev->state != USB_STATE_NOTATTACHED)
- usb_reset_device(udev);
-}
-
-static int __init r8712u_drv_entry(void)
-{
- drvpriv.drv_registered = true;
- return usb_register(&drvpriv.r871xu_drv);
-}
-
-static void __exit r8712u_drv_halt(void)
-{
- drvpriv.drv_registered = false;
- usb_deregister(&drvpriv.r871xu_drv);
-}
-
-module_init(r8712u_drv_entry);
-module_exit(r8712u_drv_halt);
diff --git a/drivers/staging/rtl8712/usb_ops.c b/drivers/staging/rtl8712/usb_ops.c
deleted file mode 100644
index af9966d03979..000000000000
--- a/drivers/staging/rtl8712/usb_ops.c
+++ /dev/null
@@ -1,195 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * usb_ops.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _HCI_OPS_C_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-#include "recv_osdep.h"
-
-static u8 usb_read8(struct intf_hdl *intfhdl, u32 addr)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- int status;
- __le32 data = 0;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x01; /* read_in */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 1;
- status = r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index,
- &data, len, requesttype);
- if (status < 0)
- return 0;
- return (u8)(le32_to_cpu(data) & 0x0ff);
-}
-
-static u16 usb_read16(struct intf_hdl *intfhdl, u32 addr)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- int status;
- __le32 data = 0;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x01; /* read_in */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 2;
- status = r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index,
- &data, len, requesttype);
- if (status < 0)
- return 0;
- return (u16)(le32_to_cpu(data) & 0xffff);
-}
-
-static u32 usb_read32(struct intf_hdl *intfhdl, u32 addr)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- int status;
- __le32 data = 0;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x01; /* read_in */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 4;
- status = r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index,
- &data, len, requesttype);
- if (status < 0)
- return 0;
- return le32_to_cpu(data);
-}
-
-static void usb_write8(struct intf_hdl *intfhdl, u32 addr, u8 val)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- __le32 data;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x00; /* write_out */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 1;
- data = cpu_to_le32((u32)val & 0x000000ff);
- r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, &data, len,
- requesttype);
-}
-
-static void usb_write16(struct intf_hdl *intfhdl, u32 addr, u16 val)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- __le32 data;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x00; /* write_out */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 2;
- data = cpu_to_le32((u32)val & 0x0000ffff);
- r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, &data, len,
- requesttype);
-}
-
-static void usb_write32(struct intf_hdl *intfhdl, u32 addr, u32 val)
-{
- u8 request;
- u8 requesttype;
- u16 wvalue;
- u16 index;
- u16 len;
- __le32 data;
- struct intf_priv *intfpriv = intfhdl->pintfpriv;
-
- request = 0x05;
- requesttype = 0x00; /* write_out */
- index = 0;
- wvalue = (u16)(addr & 0x0000ffff);
- len = 4;
- data = cpu_to_le32(val);
- r8712_usbctrl_vendorreq(intfpriv, request, wvalue, index, &data, len,
- requesttype);
-}
-
-void r8712_usb_set_intf_option(u32 *option)
-{
- *option = ((*option) | _INTF_ASYNC_);
-}
-
-static void usb_intf_hdl_init(u8 *priv)
-{
-}
-
-static void usb_intf_hdl_unload(u8 *priv)
-{
-}
-
-static void usb_intf_hdl_open(u8 *priv)
-{
-}
-
-static void usb_intf_hdl_close(u8 *priv)
-{
-}
-
-void r8712_usb_set_intf_funs(struct intf_hdl *intfhdl)
-{
- intfhdl->intf_hdl_init = usb_intf_hdl_init;
- intfhdl->intf_hdl_unload = usb_intf_hdl_unload;
- intfhdl->intf_hdl_open = usb_intf_hdl_open;
- intfhdl->intf_hdl_close = usb_intf_hdl_close;
-}
-
-void r8712_usb_set_intf_ops(struct _io_ops *ops)
-{
- memset((u8 *)ops, 0, sizeof(struct _io_ops));
- ops->_read8 = usb_read8;
- ops->_read16 = usb_read16;
- ops->_read32 = usb_read32;
- ops->_read_port = r8712_usb_read_port;
- ops->_write8 = usb_write8;
- ops->_write16 = usb_write16;
- ops->_write32 = usb_write32;
- ops->_write_mem = r8712_usb_write_mem;
- ops->_write_port = r8712_usb_write_port;
-}
diff --git a/drivers/staging/rtl8712/usb_ops.h b/drivers/staging/rtl8712/usb_ops.h
deleted file mode 100644
index 7a6b619b73fa..000000000000
--- a/drivers/staging/rtl8712/usb_ops.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __USB_OPS_H_
-#define __USB_OPS_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-
-void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr,
- u32 cnt, u8 *wmem);
-u32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr,
- u32 cnt, u8 *wmem);
-u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr,
- u32 cnt, u8 *rmem);
-void r8712_usb_set_intf_option(u32 *poption);
-void r8712_usb_set_intf_funs(struct intf_hdl *pintf_hdl);
-uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv);
-void r8712_usb_unload_intf_priv(struct intf_priv *pintfpriv);
-void r8712_usb_set_intf_ops(struct _io_ops *pops);
-void r8712_usb_read_port_cancel(struct _adapter *padapter);
-void r8712_usb_write_port_cancel(struct _adapter *padapter);
-int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value,
- u16 index, void *pdata, u16 len, u8 requesttype);
-
-#endif
-
diff --git a/drivers/staging/rtl8712/usb_ops_linux.c b/drivers/staging/rtl8712/usb_ops_linux.c
deleted file mode 100644
index 4a34824830e3..000000000000
--- a/drivers/staging/rtl8712/usb_ops_linux.c
+++ /dev/null
@@ -1,508 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * usb_ops_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _HCI_OPS_OS_C_
-
-#include <linux/usb.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-#include "osdep_intf.h"
-#include "usb_ops.h"
-
-#define RTL871X_VENQT_READ 0xc0
-#define RTL871X_VENQT_WRITE 0x40
-
-uint r8712_usb_init_intf_priv(struct intf_priv *pintfpriv)
-{
- pintfpriv->piorw_urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!pintfpriv->piorw_urb)
- return _FAIL;
- init_completion(&pintfpriv->io_retevt_comp);
- return _SUCCESS;
-}
-
-void r8712_usb_unload_intf_priv(struct intf_priv *pintfpriv)
-{
- if (pintfpriv->piorw_urb) {
- usb_kill_urb(pintfpriv->piorw_urb);
- usb_free_urb(pintfpriv->piorw_urb);
- }
-}
-
-static unsigned int ffaddr2pipehdl(struct dvobj_priv *pdvobj, u32 addr)
-{
- unsigned int pipe = 0;
- struct usb_device *pusbd = pdvobj->pusbdev;
-
- if (pdvobj->nr_endpoint == 11) {
- switch (addr) {
- case RTL8712_DMA_BKQ:
- pipe = usb_sndbulkpipe(pusbd, 0x07);
- break;
- case RTL8712_DMA_BEQ:
- pipe = usb_sndbulkpipe(pusbd, 0x06);
- break;
- case RTL8712_DMA_VIQ:
- pipe = usb_sndbulkpipe(pusbd, 0x05);
- break;
- case RTL8712_DMA_VOQ:
- pipe = usb_sndbulkpipe(pusbd, 0x04);
- break;
- case RTL8712_DMA_BCNQ:
- pipe = usb_sndbulkpipe(pusbd, 0x0a);
- break;
- case RTL8712_DMA_BMCQ: /* HI Queue */
- pipe = usb_sndbulkpipe(pusbd, 0x0b);
- break;
- case RTL8712_DMA_MGTQ:
- pipe = usb_sndbulkpipe(pusbd, 0x0c);
- break;
- case RTL8712_DMA_RX0FF:
- pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */
- break;
- case RTL8712_DMA_C2HCMD:
- pipe = usb_rcvbulkpipe(pusbd, 0x09); /* in */
- break;
- case RTL8712_DMA_H2CCMD:
- pipe = usb_sndbulkpipe(pusbd, 0x0d);
- break;
- }
- } else if (pdvobj->nr_endpoint == 6) {
- switch (addr) {
- case RTL8712_DMA_BKQ:
- pipe = usb_sndbulkpipe(pusbd, 0x07);
- break;
- case RTL8712_DMA_BEQ:
- pipe = usb_sndbulkpipe(pusbd, 0x06);
- break;
- case RTL8712_DMA_VIQ:
- pipe = usb_sndbulkpipe(pusbd, 0x05);
- break;
- case RTL8712_DMA_VOQ:
- pipe = usb_sndbulkpipe(pusbd, 0x04);
- break;
- case RTL8712_DMA_RX0FF:
- case RTL8712_DMA_C2HCMD:
- pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */
- break;
- case RTL8712_DMA_H2CCMD:
- case RTL8712_DMA_BCNQ:
- case RTL8712_DMA_BMCQ:
- case RTL8712_DMA_MGTQ:
- pipe = usb_sndbulkpipe(pusbd, 0x0d);
- break;
- }
- } else if (pdvobj->nr_endpoint == 4) {
- switch (addr) {
- case RTL8712_DMA_BEQ:
- pipe = usb_sndbulkpipe(pusbd, 0x06);
- break;
- case RTL8712_DMA_VOQ:
- pipe = usb_sndbulkpipe(pusbd, 0x04);
- break;
- case RTL8712_DMA_RX0FF:
- case RTL8712_DMA_C2HCMD:
- pipe = usb_rcvbulkpipe(pusbd, 0x03); /* in */
- break;
- case RTL8712_DMA_H2CCMD:
- case RTL8712_DMA_BCNQ:
- case RTL8712_DMA_BMCQ:
- case RTL8712_DMA_MGTQ:
- pipe = usb_sndbulkpipe(pusbd, 0x0d);
- break;
- }
- } else {
- pipe = 0;
- }
- return pipe;
-}
-
-static void usb_write_mem_complete(struct urb *purb)
-{
- struct io_queue *pio_q = (struct io_queue *)purb->context;
- struct intf_hdl *pintf = &(pio_q->intf);
- struct intf_priv *pintfpriv = pintf->pintfpriv;
- struct _adapter *padapter = (struct _adapter *)pintf->adapter;
-
- if (purb->status != 0) {
- if (purb->status == (-ESHUTDOWN))
- padapter->driver_stopped = true;
- else
- padapter->surprise_removed = true;
- }
- complete(&pintfpriv->io_retevt_comp);
-}
-
-void r8712_usb_write_mem(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
-{
- unsigned int pipe;
- struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter;
- struct intf_priv *pintfpriv = pintfhdl->pintfpriv;
- struct io_queue *pio_queue = padapter->pio_queue;
- struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev;
- struct usb_device *pusbd = pdvobj->pusbdev;
- struct urb *piorw_urb = pintfpriv->piorw_urb;
-
- if ((padapter->driver_stopped) || (padapter->surprise_removed) ||
- (padapter->pwrctrlpriv.pnp_bstop_trx))
- return;
- /* translate DMA FIFO addr to pipehandle */
- pipe = ffaddr2pipehdl(pdvobj, addr);
- if (pipe == 0)
- return;
- usb_fill_bulk_urb(piorw_urb, pusbd, pipe,
- wmem, cnt, usb_write_mem_complete,
- pio_queue);
- usb_submit_urb(piorw_urb, GFP_ATOMIC);
- wait_for_completion_interruptible(&pintfpriv->io_retevt_comp);
-}
-
-static void r8712_usb_read_port_complete(struct urb *purb)
-{
- uint isevt;
- __le32 *pbuf;
- struct recv_buf *precvbuf = (struct recv_buf *)purb->context;
- struct _adapter *padapter = (struct _adapter *)precvbuf->adapter;
- struct recv_priv *precvpriv = &padapter->recvpriv;
-
- if (padapter->surprise_removed || padapter->driver_stopped)
- return;
- if (purb->status == 0) { /* SUCCESS */
- if ((purb->actual_length > (MAX_RECVBUF_SZ)) ||
- (purb->actual_length < RXDESC_SIZE)) {
- r8712_read_port(padapter, precvpriv->ff_hwaddr, 0,
- (unsigned char *)precvbuf);
- } else {
- _pkt *pskb = precvbuf->pskb;
-
- precvbuf->transfer_len = purb->actual_length;
- pbuf = (__le32 *)precvbuf->pbuf;
- isevt = le32_to_cpu(*(pbuf + 1)) & 0x1ff;
- if ((isevt & 0x1ff) == 0x1ff) {
- r8712_rxcmd_event_hdl(padapter, pbuf);
- skb_queue_tail(&precvpriv->rx_skb_queue, pskb);
- r8712_read_port(padapter, precvpriv->ff_hwaddr,
- 0, (unsigned char *)precvbuf);
- } else {
- skb_put(pskb, purb->actual_length);
- skb_queue_tail(&precvpriv->rx_skb_queue, pskb);
- tasklet_hi_schedule(&precvpriv->recv_tasklet);
- r8712_read_port(padapter, precvpriv->ff_hwaddr,
- 0, (unsigned char *)precvbuf);
- }
- }
- } else {
- switch (purb->status) {
- case -EINVAL:
- case -EPIPE:
- case -ENODEV:
- case -ESHUTDOWN:
- padapter->driver_stopped = true;
- break;
- case -ENOENT:
- if (!padapter->suspended) {
- padapter->driver_stopped = true;
- break;
- }
- fallthrough;
- case -EPROTO:
- r8712_read_port(padapter, precvpriv->ff_hwaddr, 0,
- (unsigned char *)precvbuf);
- break;
- case -EINPROGRESS:
- netdev_err(padapter->pnetdev, "ERROR: URB IS IN PROGRESS!\n");
- break;
- default:
- break;
- }
- }
-}
-
-u32 r8712_usb_read_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *rmem)
-{
- unsigned int pipe;
- int err;
- u32 tmpaddr = 0;
- int alignment = 0;
- u32 ret = _SUCCESS;
- struct urb *purb = NULL;
- struct recv_buf *precvbuf = (struct recv_buf *)rmem;
- struct intf_priv *pintfpriv = pintfhdl->pintfpriv;
- struct dvobj_priv *pdvobj = (struct dvobj_priv *)pintfpriv->intf_dev;
- struct _adapter *adapter = pdvobj->padapter;
- struct recv_priv *precvpriv = &adapter->recvpriv;
- struct usb_device *pusbd = pdvobj->pusbdev;
-
- if (adapter->driver_stopped || adapter->surprise_removed ||
- adapter->pwrctrlpriv.pnp_bstop_trx || !precvbuf)
- return _FAIL;
- r8712_init_recvbuf(adapter, precvbuf);
- /* Try to use skb from the free queue */
- precvbuf->pskb = skb_dequeue(&precvpriv->free_recv_skb_queue);
-
- if (!precvbuf->pskb) {
- precvbuf->pskb = netdev_alloc_skb(adapter->pnetdev,
- MAX_RECVBUF_SZ + RECVBUFF_ALIGN_SZ);
- if (!precvbuf->pskb)
- return _FAIL;
- tmpaddr = (addr_t)precvbuf->pskb->data;
- alignment = tmpaddr & (RECVBUFF_ALIGN_SZ - 1);
- skb_reserve(precvbuf->pskb,
- (RECVBUFF_ALIGN_SZ - alignment));
- precvbuf->phead = precvbuf->pskb->head;
- precvbuf->pdata = precvbuf->pskb->data;
- precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
- precvbuf->pend = skb_end_pointer(precvbuf->pskb);
- precvbuf->pbuf = precvbuf->pskb->data;
- } else { /* skb is reused */
- precvbuf->phead = precvbuf->pskb->head;
- precvbuf->pdata = precvbuf->pskb->data;
- precvbuf->ptail = skb_tail_pointer(precvbuf->pskb);
- precvbuf->pend = skb_end_pointer(precvbuf->pskb);
- precvbuf->pbuf = precvbuf->pskb->data;
- }
- purb = precvbuf->purb;
- /* translate DMA FIFO addr to pipehandle */
- pipe = ffaddr2pipehdl(pdvobj, addr);
- usb_fill_bulk_urb(purb, pusbd, pipe,
- precvbuf->pbuf, MAX_RECVBUF_SZ,
- r8712_usb_read_port_complete,
- precvbuf);
- err = usb_submit_urb(purb, GFP_ATOMIC);
- if ((err) && (err != (-EPERM)))
- ret = _FAIL;
- return ret;
-}
-
-void r8712_usb_read_port_cancel(struct _adapter *padapter)
-{
- int i;
- struct recv_buf *precvbuf;
-
- precvbuf = (struct recv_buf *)padapter->recvpriv.precv_buf;
- for (i = 0; i < NR_RECVBUFF; i++) {
- if (precvbuf->purb)
- usb_kill_urb(precvbuf->purb);
- precvbuf++;
- }
-}
-
-void r8712_xmit_bh(struct tasklet_struct *t)
-{
- int ret = false;
- struct _adapter *padapter = from_tasklet(padapter, t,
- xmitpriv.xmit_tasklet);
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
-
- if (padapter->driver_stopped ||
- padapter->surprise_removed) {
- netdev_err(padapter->pnetdev, "xmit_bh => driver_stopped or surprise_removed\n");
- return;
- }
- ret = r8712_xmitframe_complete(padapter, pxmitpriv, NULL);
- if (!ret)
- return;
- tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
-}
-
-static void usb_write_port_complete(struct urb *purb)
-{
- int i;
- struct xmit_frame *pxmitframe = (struct xmit_frame *)purb->context;
- struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
- struct _adapter *padapter = pxmitframe->padapter;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
-
- switch (pattrib->priority) {
- case 1:
- case 2:
- pxmitpriv->bkq_cnt--;
- break;
- case 4:
- case 5:
- pxmitpriv->viq_cnt--;
- break;
- case 6:
- case 7:
- pxmitpriv->voq_cnt--;
- break;
- case 0:
- case 3:
- default:
- pxmitpriv->beq_cnt--;
- break;
- }
- pxmitpriv->txirp_cnt--;
- for (i = 0; i < 8; i++) {
- if (purb == pxmitframe->pxmit_urb[i]) {
- pxmitframe->bpending[i] = false;
- break;
- }
- }
- if (padapter->surprise_removed)
- return;
- switch (purb->status) {
- case 0:
- break;
- default:
- netdev_warn(padapter->pnetdev,
- "r8712u: pipe error: (%d)\n", purb->status);
- break;
- }
- /* not to consider tx fragment */
- r8712_free_xmitframe_ex(pxmitpriv, pxmitframe);
- r8712_free_xmitbuf(pxmitpriv, pxmitbuf);
- tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
-}
-
-u32 r8712_usb_write_port(struct intf_hdl *pintfhdl, u32 addr, u32 cnt, u8 *wmem)
-{
- unsigned long irqL;
- int i, status;
- unsigned int pipe;
- u32 ret, bwritezero;
- struct urb *purb = NULL;
- struct _adapter *padapter = (struct _adapter *)pintfhdl->adapter;
- struct dvobj_priv *pdvobj = &padapter->dvobjpriv;
- struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
- struct xmit_frame *pxmitframe = (struct xmit_frame *)wmem;
- struct usb_device *pusbd = pdvobj->pusbdev;
- struct pkt_attrib *pattrib = &pxmitframe->attrib;
-
- if ((padapter->driver_stopped) || (padapter->surprise_removed) ||
- (padapter->pwrctrlpriv.pnp_bstop_trx))
- return _FAIL;
- for (i = 0; i < 8; i++) {
- if (!pxmitframe->bpending[i]) {
- spin_lock_irqsave(&pxmitpriv->lock, irqL);
- pxmitpriv->txirp_cnt++;
- pxmitframe->bpending[i] = true;
- switch (pattrib->priority) {
- case 1:
- case 2:
- pxmitpriv->bkq_cnt++;
- break;
- case 4:
- case 5:
- pxmitpriv->viq_cnt++;
- break;
- case 6:
- case 7:
- pxmitpriv->voq_cnt++;
- break;
- case 0:
- case 3:
- default:
- pxmitpriv->beq_cnt++;
- break;
- }
- spin_unlock_irqrestore(&pxmitpriv->lock, irqL);
- pxmitframe->sz[i] = (u16)cnt;
- purb = pxmitframe->pxmit_urb[i];
- break;
- }
- }
- bwritezero = false;
- if (pdvobj->ishighspeed) {
- if (cnt > 0 && cnt % 512 == 0)
- bwritezero = true;
- } else {
- if (cnt > 0 && cnt % 64 == 0)
- bwritezero = true;
- }
- /* translate DMA FIFO addr to pipehandle */
- pipe = ffaddr2pipehdl(pdvobj, addr);
- if (pxmitpriv->free_xmitbuf_cnt % NR_XMITBUFF == 0)
- purb->transfer_flags &= (~URB_NO_INTERRUPT);
- else
- purb->transfer_flags |= URB_NO_INTERRUPT;
- if (bwritezero)
- cnt += 8;
- usb_fill_bulk_urb(purb, pusbd, pipe,
- pxmitframe->mem_addr,
- cnt, usb_write_port_complete,
- pxmitframe); /* context is xmit_frame */
- status = usb_submit_urb(purb, GFP_ATOMIC);
- if (!status)
- ret = _SUCCESS;
- else
- ret = _FAIL;
- return ret;
-}
-
-void r8712_usb_write_port_cancel(struct _adapter *padapter)
-{
- int i, j;
- struct xmit_buf *pxmitbuf = (struct xmit_buf *)
- padapter->xmitpriv.pxmitbuf;
-
- for (i = 0; i < NR_XMITBUFF; i++) {
- for (j = 0; j < 8; j++) {
- if (pxmitbuf->pxmit_urb[j])
- usb_kill_urb(pxmitbuf->pxmit_urb[j]);
- }
- pxmitbuf++;
- }
-}
-
-int r8712_usbctrl_vendorreq(struct intf_priv *pintfpriv, u8 request, u16 value,
- u16 index, void *pdata, u16 len, u8 requesttype)
-{
- unsigned int pipe;
- int status;
- u8 reqtype;
- struct dvobj_priv *pdvobjpriv = (struct dvobj_priv *)
- pintfpriv->intf_dev;
- struct usb_device *udev = pdvobjpriv->pusbdev;
- /* For mstar platform, mstar suggests the address for USB IO
- * should be 16 bytes alignment. Trying to fix it here.
- */
- u8 *palloc_buf, *pIo_buf;
-
- palloc_buf = kmalloc((u32)len + 16, GFP_ATOMIC);
- if (!palloc_buf)
- return -ENOMEM;
- pIo_buf = palloc_buf + 16 - ((addr_t)(palloc_buf) & 0x0f);
- if (requesttype == 0x01) {
- pipe = usb_rcvctrlpipe(udev, 0); /* read_in */
- reqtype = RTL871X_VENQT_READ;
- } else {
- pipe = usb_sndctrlpipe(udev, 0); /* write_out */
- reqtype = RTL871X_VENQT_WRITE;
- memcpy(pIo_buf, pdata, len);
- }
- status = usb_control_msg(udev, pipe, request, reqtype, value, index,
- pIo_buf, len, 500);
- if (status < 0)
- goto free;
- if (status != len) {
- status = -EREMOTEIO;
- goto free;
- }
- /* Success this control transfer. */
- if (requesttype == 0x01) {
- /* For Control read transfer, we have to copy the read
- * data from pIo_buf to pdata.
- */
- memcpy(pdata, pIo_buf, status);
- }
-
-free:
- kfree(palloc_buf);
- return status;
-}
diff --git a/drivers/staging/rtl8712/usb_osintf.h b/drivers/staging/rtl8712/usb_osintf.h
deleted file mode 100644
index 2e512b4a564c..000000000000
--- a/drivers/staging/rtl8712/usb_osintf.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __USB_OSINTF_H
-#define __USB_OSINTF_H
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-extern char *r8712_initmac;
-
-unsigned int r8712_usb_inirp_init(struct _adapter *padapter);
-unsigned int r8712_usb_inirp_deinit(struct _adapter *padapter);
-uint rtl871x_hal_init(struct _adapter *padapter);
-uint rtl8712_hal_deinit(struct _adapter *padapter);
-
-void rtl871x_intf_stop(struct _adapter *padapter);
-void r871x_dev_unload(struct _adapter *padapter);
-void r8712_stop_drv_threads(struct _adapter *padapter);
-void r8712_stop_drv_timers(struct _adapter *padapter);
-int r8712_init_drv_sw(struct _adapter *padapter);
-void r8712_free_drv_sw(struct _adapter *padapter);
-struct net_device *r8712_init_netdev(void);
-
-#endif
diff --git a/drivers/staging/rtl8712/wifi.h b/drivers/staging/rtl8712/wifi.h
deleted file mode 100644
index 498e6dec7e67..000000000000
--- a/drivers/staging/rtl8712/wifi.h
+++ /dev/null
@@ -1,196 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef _WIFI_H_
-#define _WIFI_H_
-
-#include <linux/compiler.h>
-#include <linux/ieee80211.h>
-
-#define WLAN_HDR_A3_LEN 24
-#define WLAN_HDR_A3_QOS_LEN 26
-
-enum WIFI_FRAME_TYPE {
- WIFI_QOS_DATA_TYPE = (BIT(7) | BIT(3)), /*!< QoS Data */
-};
-
-#define SetToDs(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_TODS); \
-})
-
-#define GetToDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_TODS)) != 0)
-
-#define ClearToDs(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_TODS)); \
-})
-
-#define SetFrDs(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_FROMDS); \
-})
-
-#define GetFrDs(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_FROMDS)) != 0)
-
-#define ClearFrDs(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_FROMDS)); \
-})
-
-static inline unsigned char get_tofr_ds(unsigned char *pframe)
-{
- return ((GetToDs(pframe) << 1) | GetFrDs(pframe));
-}
-
-#define SetMFrag(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREFRAGS); \
-})
-
-#define GetMFrag(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) != 0)
-
-#define ClearMFrag(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)); \
-})
-
-#define SetRetry(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_RETRY); \
-})
-
-#define GetRetry(pbuf) (((*(__le16 *)(pbuf)) & cpu_to_le16(IEEE80211_FCTL_RETRY)) != 0)
-
-#define ClearRetry(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_RETRY)); \
-})
-
-#define SetPwrMgt(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PM); \
-})
-
-#define GetPwrMgt(pbuf) (((*(__le16 *)(pbuf)) & \
- cpu_to_le16(IEEE80211_FCTL_PM)) != 0)
-
-#define ClearPwrMgt(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_PM)); \
-})
-
-#define SetMData(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_MOREDATA); \
-})
-
-#define GetMData(pbuf) (((*(__le16 *)(pbuf)) & \
- cpu_to_le16(IEEE80211_FCTL_MOREDATA)) != 0)
-
-#define ClearMData(pbuf) ({ \
- *(__le16 *)(pbuf) &= (~cpu_to_le16(IEEE80211_FCTL_MOREDATA)); \
-})
-
-#define SetPrivacy(pbuf) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(IEEE80211_FCTL_PROTECTED); \
-})
-
-#define GetPrivacy(pbuf) (((*(__le16 *)(pbuf)) & \
- cpu_to_le16(IEEE80211_FCTL_PROTECTED)) != 0)
-
-#define GetOrder(pbuf) (((*(__le16 *)(pbuf)) & \
- cpu_to_le16(IEEE80211_FCTL_ORDER)) != 0)
-
-#define GetFrameType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & \
- (BIT(3) | BIT(2)))
-
-#define SetFrameType(pbuf, type) \
- do { \
- *(__le16 *)(pbuf) &= cpu_to_le16(~(BIT(3) | \
- BIT(2))); \
- *(__le16 *)(pbuf) |= cpu_to_le16(type); \
- } while (0)
-
-#define GetFrameSubType(pbuf) (le16_to_cpu(*(__le16 *)(pbuf)) & \
- (BIT(7) | BIT(6) | BIT(5) | BIT(4) | BIT(3) | \
- BIT(2)))
-
-#define SetFrameSubType(pbuf, type) \
- do { \
- *(__le16 *)(pbuf) &= cpu_to_le16(~(BIT(7) | BIT(6) | \
- BIT(5) | BIT(4) | BIT(3) | BIT(2))); \
- *(__le16 *)(pbuf) |= cpu_to_le16(type); \
- } while (0)
-
-#define GetSequence(pbuf) (le16_to_cpu(*(__le16 *)\
- ((addr_t)(pbuf) + 22)) >> 4)
-
-#define GetFragNum(pbuf) (le16_to_cpu(*(__le16 *)((addr_t)\
- (pbuf) + 22)) & 0x0f)
-
-#define SetSeqNum(pbuf, num) ({ \
- *(__le16 *)((addr_t)(pbuf) + 22) = \
- cpu_to_le16((le16_to_cpu(*(__le16 *)((addr_t)(pbuf) + 22)) & \
- 0x000f) | (0xfff0 & (num << 4))); \
-})
-
-#define SetPriority(pbuf, tid) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16(tid & 0xf); \
-})
-
-#define GetPriority(pbuf) ((le16_to_cpu(*(__le16 *)(pbuf))) & 0xf)
-
-#define SetAckpolicy(pbuf, ack) ({ \
- *(__le16 *)(pbuf) |= cpu_to_le16((ack & 3) << 5); \
-})
-
-#define GetAckpolicy(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 5) & 0x3)
-
-#define GetAMsdu(pbuf) (((le16_to_cpu(*(__le16 *)pbuf)) >> 7) & 0x1)
-
-#define GetAddr1Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 4))
-
-#define GetAddr2Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 10))
-
-#define GetAddr3Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 16))
-
-#define GetAddr4Ptr(pbuf) ((unsigned char *)((addr_t)(pbuf) + 24))
-
-static inline unsigned char *get_hdr_bssid(unsigned char *pframe)
-{
- unsigned char *sa;
- unsigned int to_fr_ds = (GetToDs(pframe) << 1) | GetFrDs(pframe);
-
- switch (to_fr_ds) {
- case 0x00: /* ToDs=0, FromDs=0 */
- sa = GetAddr3Ptr(pframe);
- break;
- case 0x01: /* ToDs=0, FromDs=1 */
- sa = GetAddr2Ptr(pframe);
- break;
- case 0x02: /* ToDs=1, FromDs=0 */
- sa = GetAddr1Ptr(pframe);
- break;
- default: /* ToDs=1, FromDs=1 */
- sa = NULL;
- break;
- }
- return sa;
-}
-
-/* ---------------------------------------------------------------------------
- * Below is the fixed elements...
- * ---------------------------------------------------------------------------
- */
-#define _BEACON_ITERVAL_ 2
-#define _CAPABILITY_ 2
-#define _TIMESTAMP_ 8
-
-/*-----------------------------------------------------------------------------
- * Below is the definition for WMM
- *------------------------------------------------------------------------------
- */
-#define _WMM_IE_Length_ 7 /* for WMM STA */
-
-#endif /* _WIFI_H_ */
-
diff --git a/drivers/staging/rtl8712/wlan_bssdef.h b/drivers/staging/rtl8712/wlan_bssdef.h
deleted file mode 100644
index ec3749813728..000000000000
--- a/drivers/staging/rtl8712/wlan_bssdef.h
+++ /dev/null
@@ -1,223 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __WLAN_BSSDEF_H__
-#define __WLAN_BSSDEF_H__
-
-#define MAX_IE_SZ 768
-
-#define NDIS_802_11_LENGTH_SSID 32
-#define NDIS_802_11_LENGTH_RATES 8
-#define NDIS_802_11_LENGTH_RATES_EX 16
-
-struct ndis_802_11_ssid {
- u32 SsidLength;
- u8 Ssid[32];
-};
-
-enum NDIS_802_11_NETWORK_TYPE {
- Ndis802_11FH,
- Ndis802_11DS,
- Ndis802_11OFDM5,
- Ndis802_11OFDM24,
- Ndis802_11NetworkTypeMax /* not a real type, defined as an upper bound*/
-};
-
-struct NDIS_802_11_CONFIGURATION_FH {
- u32 Length; /* Length of structure */
- u32 HopPattern; /* As defined by 802.11, MSB set */
- u32 HopSet; /* to one if non-802.11 */
- u32 DwellTime; /* units are Kusec */
-};
-
-/*
- * FW will only save the channel number in DSConfig.
- * ODI Handler will convert the channel number to freq. number.
- */
-struct NDIS_802_11_CONFIGURATION {
- u32 Length; /* Length of structure */
- u32 BeaconPeriod; /* units are Kusec */
- u32 ATIMWindow; /* units are Kusec */
- u32 DSConfig; /* Frequency, units are kHz */
- struct NDIS_802_11_CONFIGURATION_FH FHConfig;
-};
-
-enum NDIS_802_11_NETWORK_INFRASTRUCTURE {
- Ndis802_11IBSS,
- Ndis802_11Infrastructure,
- Ndis802_11AutoUnknown,
- Ndis802_11InfrastructureMax, /*Not a real value,defined as upper bound*/
- Ndis802_11APMode
-};
-
-struct NDIS_802_11_FIXED_IEs {
- u8 Timestamp[8];
- u16 BeaconInterval;
- u16 Capabilities;
-};
-
-struct wlan_bssid_ex {
- u32 Length;
- unsigned char MacAddress[6];
- u8 Reserved[2];
- struct ndis_802_11_ssid Ssid;
- __le32 Privacy;
- s32 Rssi;
- enum NDIS_802_11_NETWORK_TYPE NetworkTypeInUse;
- struct NDIS_802_11_CONFIGURATION Configuration;
- enum NDIS_802_11_NETWORK_INFRASTRUCTURE InfrastructureMode;
- u8 rates[NDIS_802_11_LENGTH_RATES_EX];
- /* number of content bytes in EIs, which varies */
- u32 IELength;
- /*(timestamp, beacon interval, and capability information) */
- u8 IEs[MAX_IE_SZ];
-};
-
-enum NDIS_802_11_AUTHENTICATION_MODE {
- Ndis802_11AuthModeOpen,
- Ndis802_11AuthModeShared,
- Ndis802_11AuthModeAutoSwitch,
- Ndis802_11AuthModeWPA,
- Ndis802_11AuthModeWPAPSK,
- Ndis802_11AuthModeWPANone,
- Ndis802_11AuthModeMax /* Not a real mode, defined as upper bound */
-};
-
-enum {
- Ndis802_11WEPEnabled,
- Ndis802_11Encryption1Enabled = Ndis802_11WEPEnabled,
- Ndis802_11WEPDisabled,
- Ndis802_11EncryptionDisabled = Ndis802_11WEPDisabled,
- Ndis802_11WEPKeyAbsent,
- Ndis802_11Encryption1KeyAbsent = Ndis802_11WEPKeyAbsent,
- Ndis802_11WEPNotSupported,
- Ndis802_11EncryptionNotSupported = Ndis802_11WEPNotSupported,
- Ndis802_11Encryption2Enabled,
- Ndis802_11Encryption2KeyAbsent,
- Ndis802_11Encryption3Enabled,
- Ndis802_11Encryption3KeyAbsent
-};
-
-#define NDIS_802_11_AI_REQFI_CAPABILITIES 1
-#define NDIS_802_11_AI_REQFI_LISTENINTERVAL 2
-#define NDIS_802_11_AI_REQFI_CURRENTAPADDRESS 4
-
-#define NDIS_802_11_AI_RESFI_CAPABILITIES 1
-#define NDIS_802_11_AI_RESFI_STATUSCODE 2
-#define NDIS_802_11_AI_RESFI_ASSOCIATIONID 4
-
-struct NDIS_802_11_AI_REQFI {
- u16 Capabilities;
- u16 ListenInterval;
- unsigned char CurrentAPAddress[6];
-};
-
-struct NDIS_802_11_AI_RESFI {
- u16 Capabilities;
- u16 StatusCode;
- u16 AssociationId;
-};
-
-struct NDIS_802_11_ASSOCIATION_INFORMATION {
- u32 Length;
- u16 AvailableRequestFixedIEs;
- struct NDIS_802_11_AI_REQFI RequestFixedIEs;
- u32 RequestIELength;
- u32 OffsetRequestIEs;
- u16 AvailableResponseFixedIEs;
- struct NDIS_802_11_AI_RESFI ResponseFixedIEs;
- u32 ResponseIELength;
- u32 OffsetResponseIEs;
-};
-
-/* Key mapping keys require a BSSID*/
-struct NDIS_802_11_KEY {
- u32 Length; /* Length of this structure */
- u32 KeyIndex;
- u32 KeyLength; /* length of key in bytes */
- unsigned char BSSID[6];
- unsigned long long KeyRSC;
- u8 KeyMaterial[32]; /* variable length */
-};
-
-struct NDIS_802_11_REMOVE_KEY {
- u32 Length; /* Length of this structure */
- u32 KeyIndex;
- unsigned char BSSID[6];
-};
-
-struct NDIS_802_11_WEP {
- u32 Length; /* Length of this structure */
- u32 KeyIndex; /* 0 is the per-client key,
- * 1-N are the global keys
- */
- u32 KeyLength; /* length of key in bytes */
- u8 KeyMaterial[16]; /* variable length depending on above field */
-};
-
-/* mask for authentication/integrity fields */
-#define NDIS_802_11_AUTH_REQUEST_AUTH_FIELDS 0x0f
-#define NDIS_802_11_AUTH_REQUEST_REAUTH 0x01
-#define NDIS_802_11_AUTH_REQUEST_KEYUPDATE 0x02
-#define NDIS_802_11_AUTH_REQUEST_PAIRWISE_ERROR 0x06
-#define NDIS_802_11_AUTH_REQUEST_GROUP_ERROR 0x0E
-
-/* MIC check time, 60 seconds. */
-#define MIC_CHECK_TIME 60000000
-
-#ifndef Ndis802_11APMode
-#define Ndis802_11APMode (Ndis802_11InfrastructureMax + 1)
-#endif
-
-struct wlan_network {
- struct list_head list;
- int network_type; /*refer to ieee80211.h for WIRELESS_11A/B/G */
- int fixed; /* set to fixed when not to be removed asi
- * site-surveying
- */
- unsigned int last_scanned; /*timestamp for the network */
- int aid; /*will only be valid when a BSS is joined. */
- int join_res;
- struct wlan_bssid_ex network; /*must be the last item */
-};
-
-enum VRTL_CARRIER_SENSE {
- DISABLE_VCS,
- ENABLE_VCS,
- AUTO_VCS
-};
-
-enum VCS_TYPE {
- NONE_VCS,
- RTS_CTS,
- CTS_TO_SELF
-};
-
-#define PWR_CAM 0
-#define PWR_MINPS 1
-#define PWR_MAXPS 2
-#define PWR_UAPSD 3
-#define PWR_VOIP 4
-
-enum UAPSD_MAX_SP {
- NO_LIMIT,
- TWO_MSDU,
- FOUR_MSDU,
- SIX_MSDU
-};
-
-#define NUM_PRE_AUTH_KEY 16
-#define NUM_PMKID_CACHE NUM_PRE_AUTH_KEY
-
-#endif /* #ifndef WLAN_BSSDEF_H_ */
-
diff --git a/drivers/staging/rtl8712/xmit_linux.c b/drivers/staging/rtl8712/xmit_linux.c
deleted file mode 100644
index ceb6b590b310..000000000000
--- a/drivers/staging/rtl8712/xmit_linux.c
+++ /dev/null
@@ -1,181 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/******************************************************************************
- * xmit_linux.c
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- * Linux device driver for RTL8192SU
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-
-#define _XMIT_OSDEP_C_
-
-#include <linux/usb.h>
-#include <linux/ip.h>
-#include <linux/if_ether.h>
-#include <linux/kmemleak.h>
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-#include "wifi.h"
-#include "mlme_osdep.h"
-#include "xmit_osdep.h"
-#include "osdep_intf.h"
-
-static uint remainder_len(struct pkt_file *pfile)
-{
- return (uint)(pfile->buf_len - ((addr_t)(pfile->cur_addr) -
- (addr_t)(pfile->buf_start)));
-}
-
-void _r8712_open_pktfile(_pkt *pktptr, struct pkt_file *pfile)
-{
- pfile->pkt = pktptr;
- pfile->cur_addr = pfile->buf_start = pktptr->data;
- pfile->pkt_len = pfile->buf_len = pktptr->len;
- pfile->cur_buffer = pfile->buf_start;
-}
-
-uint _r8712_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen)
-{
- uint len;
-
- len = remainder_len(pfile);
- len = (rlen > len) ? len : rlen;
- if (rmem)
- skb_copy_bits(pfile->pkt, pfile->buf_len - pfile->pkt_len,
- rmem, len);
- pfile->cur_addr += len;
- pfile->pkt_len -= len;
- return len;
-}
-
-sint r8712_endofpktfile(struct pkt_file *pfile)
-{
- return (pfile->pkt_len == 0);
-}
-
-void r8712_set_qos(struct pkt_file *ppktfile, struct pkt_attrib *pattrib)
-{
- struct ethhdr etherhdr;
- struct iphdr ip_hdr;
- u16 user_priority = 0;
-
- _r8712_open_pktfile(ppktfile->pkt, ppktfile);
- _r8712_pktfile_read(ppktfile, (unsigned char *)&etherhdr, ETH_HLEN);
-
- /* get user_priority from IP hdr*/
- if (pattrib->ether_type == 0x0800) {
- _r8712_pktfile_read(ppktfile, (u8 *)&ip_hdr, sizeof(ip_hdr));
- /*user_priority = (ntohs(ip_hdr.tos) >> 5) & 0x3 ;*/
- user_priority = ip_hdr.tos >> 5;
- } else {
- /* "When priority processing of data frames is supported,
- * a STA's SME should send EAPOL-Key frames at the highest
- * priority."
- */
-
- if (pattrib->ether_type == 0x888e)
- user_priority = 7;
- }
- pattrib->priority = user_priority;
- pattrib->hdrlen = WLAN_HDR_A3_QOS_LEN;
- pattrib->subtype = WIFI_QOS_DATA_TYPE;
-}
-
-void r8712_SetFilter(struct work_struct *work)
-{
- struct _adapter *adapter = container_of(work, struct _adapter,
- wk_filter_rx_ff0);
- u8 oldvalue = 0x00, newvalue = 0x00;
-
- oldvalue = r8712_read8(adapter, 0x117);
- newvalue = oldvalue & 0xfe;
- r8712_write8(adapter, 0x117, newvalue);
-
- wait_for_completion(&adapter->rx_filter_ready);
- r8712_write8(adapter, 0x117, oldvalue);
-}
-
-int r8712_xmit_resource_alloc(struct _adapter *padapter,
- struct xmit_buf *pxmitbuf)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- pxmitbuf->pxmit_urb[i] = usb_alloc_urb(0, GFP_KERNEL);
- if (!pxmitbuf->pxmit_urb[i]) {
- int k;
-
- for (k = i - 1; k >= 0; k--) {
- /* handle allocation errors part way through loop */
- usb_free_urb(pxmitbuf->pxmit_urb[k]);
- }
- netdev_err(padapter->pnetdev, "pxmitbuf->pxmit_urb[i] == NULL\n");
- return -ENOMEM;
- }
- kmemleak_not_leak(pxmitbuf->pxmit_urb[i]);
- }
- return 0;
-}
-
-void r8712_xmit_resource_free(struct _adapter *padapter,
- struct xmit_buf *pxmitbuf)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- if (pxmitbuf->pxmit_urb[i]) {
- usb_kill_urb(pxmitbuf->pxmit_urb[i]);
- usb_free_urb(pxmitbuf->pxmit_urb[i]);
- }
- }
-}
-
-void r8712_xmit_complete(struct _adapter *padapter, struct xmit_frame *pxframe)
-{
- if (pxframe->pkt)
- dev_kfree_skb_any(pxframe->pkt);
- pxframe->pkt = NULL;
-}
-
-netdev_tx_t r8712_xmit_entry(_pkt *pkt, struct net_device *netdev)
-{
- struct xmit_frame *xmitframe = NULL;
- struct _adapter *adapter = netdev_priv(netdev);
- struct xmit_priv *xmitpriv = &(adapter->xmitpriv);
-
- if (!r8712_if_up(adapter))
- goto _xmit_entry_drop;
-
- xmitframe = r8712_alloc_xmitframe(xmitpriv);
- if (!xmitframe)
- goto _xmit_entry_drop;
-
- if (r8712_update_attrib(adapter, pkt, &xmitframe->attrib))
- goto _xmit_entry_drop;
-
- adapter->ledpriv.LedControlHandler(adapter, LED_CTL_TX);
- xmitframe->pkt = pkt;
- if (r8712_pre_xmit(adapter, xmitframe)) {
- /*dump xmitframe directly or drop xframe*/
- dev_kfree_skb_any(pkt);
- xmitframe->pkt = NULL;
- }
- xmitpriv->tx_pkts++;
- xmitpriv->tx_bytes += xmitframe->attrib.last_txcmdsz;
- return NETDEV_TX_OK;
-_xmit_entry_drop:
- if (xmitframe)
- r8712_free_xmitframe(xmitpriv, xmitframe);
- xmitpriv->tx_drop++;
- dev_kfree_skb_any(pkt);
- return NETDEV_TX_OK;
-}
diff --git a/drivers/staging/rtl8712/xmit_osdep.h b/drivers/staging/rtl8712/xmit_osdep.h
deleted file mode 100644
index 1ad42658c883..000000000000
--- a/drivers/staging/rtl8712/xmit_osdep.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/******************************************************************************
- *
- * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved.
- *
- * Modifications for inclusion into the Linux staging tree are
- * Copyright(c) 2010 Larry Finger. All rights reserved.
- *
- * Contact information:
- * WLAN FAE <wlanfae@realtek.com>
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- ******************************************************************************/
-#ifndef __XMIT_OSDEP_H_
-#define __XMIT_OSDEP_H_
-
-#include "osdep_service.h"
-#include "drv_types.h"
-
-struct pkt_file {
- _pkt *pkt;
- u32 pkt_len; /*the remainder length of the open_file*/
- _buffer *cur_buffer;
- u8 *buf_start;
- u8 *cur_addr;
- u32 buf_len;
-};
-
-#define NR_XMITFRAME 256
-
-struct xmit_priv;
-struct pkt_attrib;
-struct sta_xmit_priv;
-struct xmit_frame;
-struct xmit_buf;
-
-netdev_tx_t r8712_xmit_entry(_pkt *pkt, struct net_device *pnetdev);
-void r8712_SetFilter(struct work_struct *work);
-int r8712_xmit_resource_alloc(struct _adapter *padapter,
- struct xmit_buf *pxmitbuf);
-void r8712_xmit_resource_free(struct _adapter *padapter,
- struct xmit_buf *pxmitbuf);
-
-void r8712_set_qos(struct pkt_file *ppktfile,
- struct pkt_attrib *pattrib);
-void _r8712_open_pktfile(_pkt *pktptr, struct pkt_file *pfile);
-uint _r8712_pktfile_read(struct pkt_file *pfile, u8 *rmem, uint rlen);
-sint r8712_endofpktfile(struct pkt_file *pfile);
-void r8712_xmit_complete(struct _adapter *padapter,
- struct xmit_frame *pxframe);
-
-#endif
diff --git a/drivers/staging/rtl8723bs/TODO b/drivers/staging/rtl8723bs/TODO
index 4c413f9d3df0..050dcd0bffab 100644
--- a/drivers/staging/rtl8723bs/TODO
+++ b/drivers/staging/rtl8723bs/TODO
@@ -6,6 +6,3 @@ TODO:
of them will require refactoring
- merge Realtek's bugfixes and new features into the driver
- switch to use MAC80211
-
-Please send any patches to Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
-Hans de Goede <hdegoede@redhat.com> and Larry Finger <Larry.Finger@lwfinger.net>.
diff --git a/drivers/staging/rtl8723bs/core/rtw_cmd.c b/drivers/staging/rtl8723bs/core/rtw_cmd.c
index 84ce7307d8f3..64ce33c6fba1 100644
--- a/drivers/staging/rtl8723bs/core/rtw_cmd.c
+++ b/drivers/staging/rtl8723bs/core/rtw_cmd.c
@@ -382,7 +382,7 @@ int rtw_cmd_thread(void *context)
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
struct drvextra_cmd_parm *extra_parm = NULL;
- thread_enter("RTW_CMD_THREAD");
+ allow_signal(SIGTERM);
pcmdbuf = pcmdpriv->cmd_buf;
@@ -1258,8 +1258,7 @@ static void dynamic_chk_wk_hdl(struct adapter *padapter)
/* always call rtw_ps_processor() at last one. */
- if (is_primary_adapter(padapter))
- rtw_ps_processor(padapter);
+ rtw_ps_processor(padapter);
}
void lps_ctrl_wk_hdl(struct adapter *padapter, u8 lps_ctrl_type);
@@ -1465,6 +1464,7 @@ u8 rtw_ps_cmd(struct adapter *padapter)
struct drvextra_cmd_parm *pdrvextra_cmd_parm;
struct cmd_priv *pcmdpriv = &padapter->cmdpriv;
u8 res = _SUCCESS;
+
ppscmd = rtw_zmalloc(sizeof(struct cmd_obj));
if (!ppscmd) {
res = _FAIL;
diff --git a/drivers/staging/rtl8723bs/core/rtw_efuse.c b/drivers/staging/rtl8723bs/core/rtw_efuse.c
index 8b671f8a7965..7a74b011dedc 100644
--- a/drivers/staging/rtl8723bs/core/rtw_efuse.c
+++ b/drivers/staging/rtl8723bs/core/rtw_efuse.c
@@ -77,33 +77,7 @@ struct adapter *padapter,
u8 bWrite,
u8 PwrState)
{
- padapter->HalFunc.EfusePowerSwitch(padapter, bWrite, PwrState);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: Efuse_GetCurrentSize
- *
- * Overview: Get current efuse size!!!
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 11/16/2008 MHC Create Version 0.
- *
- *---------------------------------------------------------------------------*/
-u16
-Efuse_GetCurrentSize(
- struct adapter *padapter,
- u8 efuseType,
- bool bPseudoTest)
-{
- return padapter->HalFunc.EfuseGetCurrentSize(padapter, efuseType,
- bPseudoTest);
+ Hal_EfusePowerSwitch(padapter, bWrite, PwrState);
}
/* 11/16/2008 MH Add description. Get current efuse area enabled word!!. */
@@ -159,7 +133,7 @@ efuse_ReadEFuse(
bool bPseudoTest
)
{
- Adapter->HalFunc.ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
+ Hal_ReadEFuse(Adapter, efuseType, _offset, _size_byte, pbuf, bPseudoTest);
}
void
@@ -171,7 +145,7 @@ EFUSE_GetEfuseDefinition(
bool bPseudoTest
)
{
- padapter->HalFunc.EFUSEGetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest);
+ Hal_GetEfuseDefinition(padapter, efuseType, type, pOut, bPseudoTest);
}
/*-----------------------------------------------------------------------------
@@ -312,68 +286,6 @@ u8 efuse_OneByteWrite(struct adapter *padapter, u16 addr, u8 data, bool bPseudoT
return bResult;
}
-int
-Efuse_PgPacketRead(struct adapter *padapter,
- u8 offset,
- u8 *data,
- bool bPseudoTest)
-{
- return padapter->HalFunc.Efuse_PgPacketRead(padapter, offset, data,
- bPseudoTest);
-}
-
-int
-Efuse_PgPacketWrite(struct adapter *padapter,
- u8 offset,
- u8 word_en,
- u8 *data,
- bool bPseudoTest)
-{
- return padapter->HalFunc.Efuse_PgPacketWrite(padapter, offset, word_en,
- data, bPseudoTest);
-}
-
-/*-----------------------------------------------------------------------------
- * Function: efuse_WordEnableDataRead
- *
- * Overview: Read allowed word in current efuse section data.
- *
- * Input: NONE
- *
- * Output: NONE
- *
- * Return: NONE
- *
- * Revised History:
- * When Who Remark
- * 11/16/2008 MHC Create Version 0.
- * 11/21/2008 MHC Fix Write bug when we only enable late word.
- *
- *---------------------------------------------------------------------------*/
-void
-efuse_WordEnableDataRead(u8 word_en,
- u8 *sourdata,
- u8 *targetdata)
-{
- if (!(word_en & BIT(0))) {
- targetdata[0] = sourdata[0];
- targetdata[1] = sourdata[1];
- }
- if (!(word_en & BIT(1))) {
- targetdata[2] = sourdata[2];
- targetdata[3] = sourdata[3];
- }
- if (!(word_en & BIT(2))) {
- targetdata[4] = sourdata[4];
- targetdata[5] = sourdata[5];
- }
- if (!(word_en & BIT(3))) {
- targetdata[6] = sourdata[6];
- targetdata[7] = sourdata[7];
- }
-}
-
-
u8
Efuse_WordEnableDataWrite(struct adapter *padapter,
u16 efuse_addr,
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme.c b/drivers/staging/rtl8723bs/core/rtw_mlme.c
index cbdb134278d3..5ded183aa08c 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme.c
@@ -911,8 +911,7 @@ inline void rtw_indicate_scan_done(struct adapter *padapter, bool aborted)
{
rtw_os_indicate_scan_done(padapter, aborted);
- if (is_primary_adapter(padapter) &&
- (!adapter_to_pwrctl(padapter)->bInSuspend) &&
+ if ((!adapter_to_pwrctl(padapter)->bInSuspend) &&
(!check_fwstate(&padapter->mlmepriv,
WIFI_ASOC_STATE|WIFI_UNDER_LINKING))) {
rtw_set_ips_deny(padapter, 0);
@@ -1589,8 +1588,7 @@ void rtw_dynamic_check_timer_handler(struct adapter *adapter)
}
} else {
- if (is_primary_adapter(adapter))
- rtw_dynamic_chk_wk_cmd(adapter);
+ rtw_dynamic_chk_wk_cmd(adapter);
}
/* auto site survey */
diff --git a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
index 4d4bec47d187..317f3db19397 100644
--- a/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
+++ b/drivers/staging/rtl8723bs/core/rtw_mlme_ext.c
@@ -1870,10 +1870,10 @@ unsigned int OnAction_sa_query(struct adapter *padapter, union recv_frame *precv
if (0) {
int pp;
- printk("pattrib->pktlen = %d =>", pattrib->pkt_len);
+ netdev_dbg(padapter->pnetdev, "pattrib->pktlen = %d =>", pattrib->pkt_len);
for (pp = 0; pp < pattrib->pkt_len; pp++)
- printk(" %02x ", pframe[pp]);
- printk("\n");
+ pr_cont(" %02x ", pframe[pp]);
+ pr_cont("\n");
}
return _SUCCESS;
@@ -4872,8 +4872,7 @@ void mlmeext_joinbss_event_callback(struct adapter *padapter, int join_res)
/* set_link_timer(pmlmeext, DISCONNECT_TO); */
}
- if (get_iface_type(padapter) == IFACE_PORT0)
- rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
+ rtw_lps_ctrl_wk_cmd(padapter, LPS_CTRL_CONNECT, 0);
}
/* currently only adhoc mode will go here */
@@ -5638,7 +5637,7 @@ u8 setkey_hdl(struct adapter *padapter, u8 *pbuf)
rtw_hal_set_hwreg(padapter, HW_VAR_SEC_DK_CFG, (u8 *)true);
/* allow multicast packets to driver */
- padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_ON_RCR_AM, null_addr);
+ SetHwReg8723BS(padapter, HW_VAR_ON_RCR_AM, null_addr);
return H2C_SUCCESS;
}
diff --git a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c
index dbfcbac3d855..c60e179bb2e1 100644
--- a/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c
+++ b/drivers/staging/rtl8723bs/core/rtw_pwrctrl.c
@@ -73,9 +73,6 @@ int ips_leave(struct adapter *padapter)
struct pwrctrl_priv *pwrpriv = adapter_to_pwrctl(padapter);
int ret;
- if (!is_primary_adapter(padapter))
- return _SUCCESS;
-
mutex_lock(&pwrpriv->lock);
ret = _ips_leave(padapter);
mutex_unlock(&pwrpriv->lock);
@@ -455,10 +452,6 @@ void LPS_Enter(struct adapter *padapter, const char *msg)
if (n_assoc_iface != 1)
return;
- /* Skip lps enter request for adapter not port0 */
- if (get_iface_type(padapter) != IFACE_PORT0)
- return;
-
if (!PS_RDY_CHECK(dvobj->padapters))
return;
diff --git a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
index f37fec1efaf9..73c70b016f00 100644
--- a/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
+++ b/drivers/staging/rtl8723bs/core/rtw_wlan_util.c
@@ -290,21 +290,11 @@ inline void rtw_set_oper_ch(struct adapter *adapter, u8 ch)
dvobj->oper_channel = ch;
}
-inline u8 rtw_get_oper_bw(struct adapter *adapter)
-{
- return adapter_to_dvobj(adapter)->oper_bwmode;
-}
-
inline void rtw_set_oper_bw(struct adapter *adapter, u8 bw)
{
adapter_to_dvobj(adapter)->oper_bwmode = bw;
}
-inline u8 rtw_get_oper_choffset(struct adapter *adapter)
-{
- return adapter_to_dvobj(adapter)->oper_ch_offset;
-}
-
inline void rtw_set_oper_choffset(struct adapter *adapter, u8 offset)
{
adapter_to_dvobj(adapter)->oper_ch_offset = offset;
@@ -445,34 +435,6 @@ void invalidate_cam_all(struct adapter *padapter)
spin_unlock_bh(&cam_ctl->lock);
}
-static u32 _ReadCAM(struct adapter *padapter, u32 addr)
-{
- u32 count = 0, cmd;
-
- cmd = CAM_POLLINIG | addr;
- rtw_write32(padapter, RWCAM, cmd);
-
- do {
- if (0 == (rtw_read32(padapter, REG_CAMCMD) & CAM_POLLINIG))
- break;
- } while (count++ < 100);
-
- return rtw_read32(padapter, REG_CAMREAD);
-}
-
-void read_cam(struct adapter *padapter, u8 entry, u8 *get_key)
-{
- u32 j, addr, cmd;
-
- addr = entry << 3;
-
- for (j = 0; j < 6; j++) {
- cmd = _ReadCAM(padapter, addr+j);
- if (j > 1) /* get key from cam */
- memcpy(get_key+(j-2)*4, &cmd, 4);
- }
-}
-
void _write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key)
{
unsigned int i, val, addr;
@@ -1613,9 +1575,9 @@ void update_wireless_mode(struct adapter *padapter)
SIFS_Timer = 0x0a0a0808; /* 0x0808 -> for CCK, 0x0a0a -> for OFDM */
/* change this value if having IOT issues. */
- padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer);
+ SetHwReg8723BS(padapter, HW_VAR_RESP_SIFS, (u8 *)&SIFS_Timer);
- padapter->HalFunc.SetHwRegHandler(padapter, HW_VAR_WIRELESS_MODE, (u8 *)&(pmlmeext->cur_wireless_mode));
+ SetHwReg8723BS(padapter, HW_VAR_WIRELESS_MODE, (u8 *)&(pmlmeext->cur_wireless_mode));
if (pmlmeext->cur_wireless_mode & WIRELESS_11B)
update_mgnt_tx_rate(padapter, IEEE80211_CCK_RATE_1MB);
@@ -1822,29 +1784,3 @@ void rtw_release_macid(struct adapter *padapter, struct sta_info *psta)
}
spin_unlock_bh(&pdvobj->lock);
}
-
-/* For 8188E RA */
-u8 rtw_search_max_mac_id(struct adapter *padapter)
-{
- u8 max_mac_id = 0;
- struct dvobj_priv *pdvobj = adapter_to_dvobj(padapter);
- int i;
-
- spin_lock_bh(&pdvobj->lock);
- for (i = (NUM_STA-1); i >= 0 ; i--) {
- if (pdvobj->macid[i] == true)
- break;
- }
- max_mac_id = i;
- spin_unlock_bh(&pdvobj->lock);
-
- return max_mac_id;
-}
-
-struct adapter *dvobj_get_port0_adapter(struct dvobj_priv *dvobj)
-{
- if (get_iface_type(dvobj->padapters[i]) != IFACE_PORT0)
- return NULL;
-
- return dvobj->padapters;
-}
diff --git a/drivers/staging/rtl8723bs/core/rtw_xmit.c b/drivers/staging/rtl8723bs/core/rtw_xmit.c
index 3e88f14e3bf7..699cff7b0ac9 100644
--- a/drivers/staging/rtl8723bs/core/rtw_xmit.c
+++ b/drivers/staging/rtl8723bs/core/rtw_xmit.c
@@ -2489,7 +2489,7 @@ int rtw_xmit_thread(void *context)
err = _SUCCESS;
padapter = context;
- thread_enter("RTW_XMIT_THREAD");
+ allow_signal(SIGTERM);
do {
err = rtw_hal_xmit_thread_handler(padapter);
diff --git a/drivers/staging/rtl8723bs/hal/hal_com.c b/drivers/staging/rtl8723bs/hal/hal_com.c
index 719dd116d807..95fb38283c58 100644
--- a/drivers/staging/rtl8723bs/hal/hal_com.c
+++ b/drivers/staging/rtl8723bs/hal/hal_com.c
@@ -13,23 +13,20 @@
u8 rtw_hal_data_init(struct adapter *padapter)
{
- if (is_primary_adapter(padapter)) { /* if (padapter->isprimary) */
- padapter->hal_data_sz = sizeof(struct hal_com_data);
- padapter->HalData = vzalloc(padapter->hal_data_sz);
- if (!padapter->HalData)
- return _FAIL;
- }
+ padapter->hal_data_sz = sizeof(struct hal_com_data);
+ padapter->HalData = vzalloc(padapter->hal_data_sz);
+ if (!padapter->HalData)
+ return _FAIL;
+
return _SUCCESS;
}
void rtw_hal_data_deinit(struct adapter *padapter)
{
- if (is_primary_adapter(padapter)) { /* if (padapter->isprimary) */
- if (padapter->HalData) {
- vfree(padapter->HalData);
- padapter->HalData = NULL;
- padapter->hal_data_sz = 0;
- }
+ if (padapter->HalData) {
+ vfree(padapter->HalData);
+ padapter->HalData = NULL;
+ padapter->hal_data_sz = 0;
}
}
@@ -796,19 +793,6 @@ u8 GetHalDefVar(
return bResult;
}
-void GetHalODMVar(
- struct adapter *Adapter,
- enum hal_odm_variable eVariable,
- void *pValue1,
- void *pValue2
-)
-{
- switch (eVariable) {
- default:
- break;
- }
-}
-
void SetHalODMVar(
struct adapter *Adapter,
enum hal_odm_variable eVariable,
@@ -883,7 +867,6 @@ void rtw_hal_check_rxfifo_full(struct adapter *adapter)
int save_cnt = false;
/* switch counter to RX fifo */
- /* printk("8723b or 8192e , MAC_667 set 0xf0\n"); */
rtw_write8(adapter, REG_RXERR_RPT+3, rtw_read8(adapter, REG_RXERR_RPT+3)|0xf0);
save_cnt = true;
/* todo: other chips */
@@ -910,10 +893,9 @@ void rtw_dump_raw_rssi_info(struct adapter *padapter)
for (rf_path = 0; rf_path < pHalData->NumTotalRFPath; rf_path++) {
if (!isCCKrate) {
- printk(", rx_ofdm_pwr:%d(dBm), rx_ofdm_snr:%d(dB)\n",
- psample_pkt_rssi->ofdm_pwr[rf_path], psample_pkt_rssi->ofdm_snr[rf_path]);
- } else {
- printk("\n");
+ netdev_dbg(padapter->pnetdev, ", rx_ofdm_pwr:%d(dBm), rx_ofdm_snr:%d(dB)\n",
+ psample_pkt_rssi->ofdm_pwr[rf_path],
+ psample_pkt_rssi->ofdm_snr[rf_path]);
}
}
}
diff --git a/drivers/staging/rtl8723bs/hal/hal_intf.c b/drivers/staging/rtl8723bs/hal/hal_intf.c
index 0a3900548fd2..0db8f623b805 100644
--- a/drivers/staging/rtl8723bs/hal/hal_intf.c
+++ b/drivers/staging/rtl8723bs/hal/hal_intf.c
@@ -9,52 +9,37 @@
void rtw_hal_chip_configure(struct adapter *padapter)
{
- if (padapter->HalFunc.intf_chip_configure)
- padapter->HalFunc.intf_chip_configure(padapter);
+ rtl8723bs_interface_configure(padapter);
}
void rtw_hal_read_chip_info(struct adapter *padapter)
{
- if (padapter->HalFunc.read_adapter_info)
- padapter->HalFunc.read_adapter_info(padapter);
+ ReadAdapterInfo8723BS(padapter);
}
void rtw_hal_read_chip_version(struct adapter *padapter)
{
- if (padapter->HalFunc.read_chip_version)
- padapter->HalFunc.read_chip_version(padapter);
+ rtl8723b_read_chip_version(padapter);
}
void rtw_hal_def_value_init(struct adapter *padapter)
{
- if (is_primary_adapter(padapter))
- if (padapter->HalFunc.init_default_value)
- padapter->HalFunc.init_default_value(padapter);
+ rtl8723bs_init_default_value(padapter);
}
void rtw_hal_free_data(struct adapter *padapter)
{
/* free HAL Data */
rtw_hal_data_deinit(padapter);
-
- if (is_primary_adapter(padapter))
- if (padapter->HalFunc.free_hal_data)
- padapter->HalFunc.free_hal_data(padapter);
}
void rtw_hal_dm_init(struct adapter *padapter)
{
- if (is_primary_adapter(padapter))
- if (padapter->HalFunc.dm_init)
- padapter->HalFunc.dm_init(padapter);
+ rtl8723b_init_dm_priv(padapter);
}
void rtw_hal_dm_deinit(struct adapter *padapter)
{
- /* cancel dm timer */
- if (is_primary_adapter(padapter))
- if (padapter->HalFunc.dm_deinit)
- padapter->HalFunc.dm_deinit(padapter);
}
static void rtw_hal_init_opmode(struct adapter *padapter)
@@ -82,7 +67,7 @@ uint rtw_hal_init(struct adapter *padapter)
uint status;
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
- status = padapter->HalFunc.hal_init(padapter);
+ status = rtl8723bs_hal_init(padapter);
if (status == _SUCCESS) {
rtw_hal_init_opmode(padapter);
@@ -111,7 +96,7 @@ uint rtw_hal_deinit(struct adapter *padapter)
uint status = _SUCCESS;
struct dvobj_priv *dvobj = adapter_to_dvobj(padapter);
- status = padapter->HalFunc.hal_deinit(padapter);
+ status = rtl8723bs_hal_deinit(padapter);
if (status == _SUCCESS) {
padapter = dvobj->padapters;
@@ -123,34 +108,27 @@ uint rtw_hal_deinit(struct adapter *padapter)
void rtw_hal_set_hwreg(struct adapter *padapter, u8 variable, u8 *val)
{
- if (padapter->HalFunc.SetHwRegHandler)
- padapter->HalFunc.SetHwRegHandler(padapter, variable, val);
+ SetHwReg8723BS(padapter, variable, val);
}
void rtw_hal_get_hwreg(struct adapter *padapter, u8 variable, u8 *val)
{
- if (padapter->HalFunc.GetHwRegHandler)
- padapter->HalFunc.GetHwRegHandler(padapter, variable, val);
+ GetHwReg8723BS(padapter, variable, val);
}
void rtw_hal_set_hwreg_with_buf(struct adapter *padapter, u8 variable, u8 *pbuf, int len)
{
- if (padapter->HalFunc.SetHwRegHandlerWithBuf)
- padapter->HalFunc.SetHwRegHandlerWithBuf(padapter, variable, pbuf, len);
+ SetHwRegWithBuf8723B(padapter, variable, pbuf, len);
}
u8 rtw_hal_set_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue)
{
- if (padapter->HalFunc.SetHalDefVarHandler)
- return padapter->HalFunc.SetHalDefVarHandler(padapter, eVariable, pValue);
- return _FAIL;
+ return SetHalDefVar8723BSDIO(padapter, eVariable, pValue);
}
u8 rtw_hal_get_def_var(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue)
{
- if (padapter->HalFunc.GetHalDefVarHandler)
- return padapter->HalFunc.GetHalDefVarHandler(padapter, eVariable, pValue);
- return _FAIL;
+ return GetHalDefVar8723BSDIO(padapter, eVariable, pValue);
}
void rtw_hal_set_odm_var(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet)
@@ -161,40 +139,27 @@ void rtw_hal_set_odm_var(struct adapter *padapter, enum hal_odm_variable eVariab
void rtw_hal_enable_interrupt(struct adapter *padapter)
{
- if (padapter->HalFunc.enable_interrupt)
- padapter->HalFunc.enable_interrupt(padapter);
+ EnableInterrupt8723BSdio(padapter);
}
void rtw_hal_disable_interrupt(struct adapter *padapter)
{
- if (padapter->HalFunc.disable_interrupt)
- padapter->HalFunc.disable_interrupt(padapter);
+ DisableInterrupt8723BSdio(padapter);
}
u8 rtw_hal_check_ips_status(struct adapter *padapter)
{
- u8 val = false;
-
- if (padapter->HalFunc.check_ips_status)
- val = padapter->HalFunc.check_ips_status(padapter);
-
- return val;
+ return CheckIPSStatus(padapter);
}
s32 rtw_hal_xmitframe_enqueue(struct adapter *padapter, struct xmit_frame *pxmitframe)
{
- if (padapter->HalFunc.hal_xmitframe_enqueue)
- return padapter->HalFunc.hal_xmitframe_enqueue(padapter, pxmitframe);
-
- return false;
+ return rtl8723bs_hal_xmitframe_enqueue(padapter, pxmitframe);
}
s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe)
{
- if (padapter->HalFunc.hal_xmit)
- return padapter->HalFunc.hal_xmit(padapter, pxmitframe);
-
- return false;
+ return rtl8723bs_hal_xmit(padapter, pxmitframe);
}
/*
@@ -202,8 +167,6 @@ s32 rtw_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe)
*/
s32 rtw_hal_mgnt_xmit(struct adapter *padapter, struct xmit_frame *pmgntframe)
{
- s32 ret = _FAIL;
-
update_mgntframe_attrib_addr(padapter, pmgntframe);
/* pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET; */
/* pwlanhdr = (struct rtw_ieee80211_hdr *)pframe; */
@@ -220,36 +183,27 @@ s32 rtw_hal_mgnt_xmit(struct adapter *padapter, struct xmit_frame *pmgntframe)
rtw_mgmt_xmitframe_coalesce(padapter, pmgntframe->pkt, pmgntframe);
}
- if (padapter->HalFunc.mgnt_xmit)
- ret = padapter->HalFunc.mgnt_xmit(padapter, pmgntframe);
- return ret;
+ return rtl8723bs_mgnt_xmit(padapter, pmgntframe);
}
s32 rtw_hal_init_xmit_priv(struct adapter *padapter)
{
- if (padapter->HalFunc.init_xmit_priv)
- return padapter->HalFunc.init_xmit_priv(padapter);
- return _FAIL;
+ return rtl8723bs_init_xmit_priv(padapter);
}
void rtw_hal_free_xmit_priv(struct adapter *padapter)
{
- if (padapter->HalFunc.free_xmit_priv)
- padapter->HalFunc.free_xmit_priv(padapter);
+ rtl8723bs_free_xmit_priv(padapter);
}
s32 rtw_hal_init_recv_priv(struct adapter *padapter)
{
- if (padapter->HalFunc.init_recv_priv)
- return padapter->HalFunc.init_recv_priv(padapter);
-
- return _FAIL;
+ return rtl8723bs_init_recv_priv(padapter);
}
void rtw_hal_free_recv_priv(struct adapter *padapter)
{
- if (padapter->HalFunc.free_recv_priv)
- padapter->HalFunc.free_recv_priv(padapter);
+ rtl8723bs_free_recv_priv(padapter);
}
void rtw_hal_update_ra_mask(struct sta_info *psta, u8 rssi_level)
@@ -267,91 +221,70 @@ void rtw_hal_update_ra_mask(struct sta_info *psta, u8 rssi_level)
if (check_fwstate(pmlmepriv, WIFI_AP_STATE) == true)
add_RATid(padapter, psta, rssi_level);
else {
- if (padapter->HalFunc.UpdateRAMaskHandler)
- padapter->HalFunc.UpdateRAMaskHandler(padapter, psta->mac_id, rssi_level);
+ UpdateHalRAMask8723B(padapter, psta->mac_id, rssi_level);
}
}
void rtw_hal_add_ra_tid(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_level)
{
- if (padapter->HalFunc.Add_RateATid)
- padapter->HalFunc.Add_RateATid(padapter, bitmap, arg, rssi_level);
+ rtl8723b_Add_RateATid(padapter, bitmap, arg, rssi_level);
}
/*Start specifical interface thread */
void rtw_hal_start_thread(struct adapter *padapter)
{
- if (padapter->HalFunc.run_thread)
- padapter->HalFunc.run_thread(padapter);
+ rtl8723b_start_thread(padapter);
}
/*Start specifical interface thread */
void rtw_hal_stop_thread(struct adapter *padapter)
{
- if (padapter->HalFunc.cancel_thread)
- padapter->HalFunc.cancel_thread(padapter);
+ rtl8723b_stop_thread(padapter);
}
u32 rtw_hal_read_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask)
{
- u32 data = 0;
-
- if (padapter->HalFunc.read_bbreg)
- data = padapter->HalFunc.read_bbreg(padapter, RegAddr, BitMask);
- return data;
+ return PHY_QueryBBReg_8723B(padapter, RegAddr, BitMask);
}
void rtw_hal_write_bbreg(struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data)
{
- if (padapter->HalFunc.write_bbreg)
- padapter->HalFunc.write_bbreg(padapter, RegAddr, BitMask, Data);
+ PHY_SetBBReg_8723B(padapter, RegAddr, BitMask, Data);
}
u32 rtw_hal_read_rfreg(struct adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask)
{
- u32 data = 0;
-
- if (padapter->HalFunc.read_rfreg)
- data = padapter->HalFunc.read_rfreg(padapter, eRFPath, RegAddr, BitMask);
- return data;
+ return PHY_QueryRFReg_8723B(padapter, eRFPath, RegAddr, BitMask);
}
void rtw_hal_write_rfreg(struct adapter *padapter, u32 eRFPath, u32 RegAddr, u32 BitMask, u32 Data)
{
- if (padapter->HalFunc.write_rfreg)
- padapter->HalFunc.write_rfreg(padapter, eRFPath, RegAddr, BitMask, Data);
+ PHY_SetRFReg_8723B(padapter, eRFPath, RegAddr, BitMask, Data);
}
void rtw_hal_set_chan(struct adapter *padapter, u8 channel)
{
- if (padapter->HalFunc.set_channel_handler)
- padapter->HalFunc.set_channel_handler(padapter, channel);
+ PHY_SwChnl8723B(padapter, channel);
}
void rtw_hal_set_chnl_bw(struct adapter *padapter, u8 channel,
enum channel_width Bandwidth, u8 Offset40, u8 Offset80)
{
- if (padapter->HalFunc.set_chnl_bw_handler)
- padapter->HalFunc.set_chnl_bw_handler(padapter, channel,
- Bandwidth, Offset40,
- Offset80);
+ PHY_SetSwChnlBWMode8723B(padapter, channel, Bandwidth, Offset40, Offset80);
}
void rtw_hal_dm_watchdog(struct adapter *padapter)
{
- if (padapter->HalFunc.hal_dm_watchdog)
- padapter->HalFunc.hal_dm_watchdog(padapter);
+ rtl8723b_HalDmWatchDog(padapter);
}
void rtw_hal_dm_watchdog_in_lps(struct adapter *padapter)
{
if (adapter_to_pwrctl(padapter)->fw_current_in_ps_mode) {
- if (padapter->HalFunc.hal_dm_watchdog_in_lps)
- padapter->HalFunc.hal_dm_watchdog_in_lps(padapter); /* this function caller is in interrupt context */
+ rtl8723b_HalDmWatchDog_in_LPS(padapter); /* this function caller is in interrupt context */
}
}
void beacon_timing_control(struct adapter *padapter)
{
- if (padapter->HalFunc.SetBeaconRelatedRegistersHandler)
- padapter->HalFunc.SetBeaconRelatedRegistersHandler(padapter);
+ rtl8723b_SetBeaconRelatedRegisters(padapter);
}
diff --git a/drivers/staging/rtl8723bs/hal/odm.c b/drivers/staging/rtl8723bs/hal/odm.c
index ea3b4cd32360..8d6131f0ad47 100644
--- a/drivers/staging/rtl8723bs/hal/odm.c
+++ b/drivers/staging/rtl8723bs/hal/odm.c
@@ -417,13 +417,11 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm)
u8 i;
struct adapter *padapter = pDM_Odm->Adapter;
- if (padapter->bDriverStopped) {
+ if (padapter->bDriverStopped)
return;
- }
- if (!pDM_Odm->bUseRAMask) {
+ if (!pDM_Odm->bUseRAMask)
return;
- }
for (i = 0; i < ODM_ASSOCIATE_ENTRY_NUM; i++) {
PSTA_INFO_T pstat = pDM_Odm->pODM_StaInfo[i];
@@ -433,7 +431,6 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm)
continue;
if (true == ODM_RAStateCheck(pDM_Odm, pstat->rssi_stat.UndecoratedSmoothedPWDB, false, &pstat->rssi_level)) {
- /* printk("RSSI:%d, RSSI_LEVEL:%d\n", pstat->rssi_stat.UndecoratedSmoothedPWDB, pstat->rssi_level); */
rtw_hal_update_ra_mask(pstat, pstat->rssi_level);
}
@@ -461,9 +458,9 @@ static void odm_RefreshRateAdaptiveMaskCE(struct dm_odm_t *pDM_Odm)
static void odm_RefreshRateAdaptiveMask(struct dm_odm_t *pDM_Odm)
{
- if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK)) {
+ if (!(pDM_Odm->SupportAbility & ODM_BB_RA_MASK))
return;
- }
+
odm_RefreshRateAdaptiveMaskCE(pDM_Odm);
}
@@ -512,7 +509,6 @@ bool ODM_RAStateCheck(
RATRState = DM_RATR_STA_MIDDLE;
else
RATRState = DM_RATR_STA_LOW;
- /* printk("==>%s, RATRState:0x%02x , RSSI:%d\n", __func__, RATRState, RSSI); */
if (*pRATRState != RATRState || bForceUpdate) {
*pRATRState = RATRState;
@@ -593,8 +589,6 @@ static void odm_RSSIMonitorCheckCE(struct dm_odm_t *pDM_Odm)
}
}
- /* printk("%s ==> sta_cnt(%d)\n", __func__, sta_cnt); */
-
for (i = 0; i < sta_cnt; i++) {
if (PWDB_rssi[i] != (0)) {
if (pHalData->fw_ractrl == true)/* Report every sta's RSSI to FW */
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
index 37ebbbf408ec..e15ec6452fd0 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_hal_init.c
@@ -53,8 +53,6 @@ static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
u8 *bufferPtr = buffer;
u32 i = 0, offset = 0;
-/* printk("====>%s %d\n", __func__, __LINE__); */
-
/* 3 Phase #1 */
blockCount_p1 = buffSize / blockSize_p1;
remainSize_p1 = buffSize % blockSize_p1;
@@ -62,7 +60,8 @@ static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
for (i = 0; i < blockCount_p1; i++) {
ret = rtw_write32(padapter, (FW_8723B_START_ADDRESS + i * blockSize_p1), *((u32 *)(bufferPtr + i * blockSize_p1)));
if (ret == _FAIL) {
- printk("====>%s %d i:%d\n", __func__, __LINE__, i);
+ netdev_dbg(padapter->pnetdev, "write failed at %s %d, block:%d\n",
+ __func__, __LINE__, i);
goto exit;
}
}
@@ -85,7 +84,8 @@ static int _BlockWrite(struct adapter *padapter, void *buffer, u32 buffSize)
ret = rtw_write8(padapter, (FW_8723B_START_ADDRESS + offset + i), *(bufferPtr + offset + i));
if (ret == _FAIL) {
- printk("====>%s %d i:%d\n", __func__, __LINE__, i);
+ netdev_dbg(padapter->pnetdev, "write failed at %s %d, block:%d\n",
+ __func__, __LINE__, i);
goto exit;
}
}
@@ -127,7 +127,8 @@ static int _WriteFW(struct adapter *padapter, void *buffer, u32 size)
ret = _PageWrite(padapter, page, bufferPtr+offset, MAX_DLFW_PAGE_SIZE);
if (ret == _FAIL) {
- printk("====>%s %d\n", __func__, __LINE__);
+ netdev_dbg(padapter->pnetdev, "page write failed at %s %d\n",
+ __func__, __LINE__);
goto exit;
}
}
@@ -138,7 +139,8 @@ static int _WriteFW(struct adapter *padapter, void *buffer, u32 size)
ret = _PageWrite(padapter, page, bufferPtr+offset, remainSize);
if (ret == _FAIL) {
- printk("====>%s %d\n", __func__, __LINE__);
+ netdev_dbg(padapter->pnetdev, "remaining page write failed at %s %d\n",
+ __func__, __LINE__);
goto exit;
}
}
@@ -439,10 +441,6 @@ void rtl8723b_InitializeFirmwareVars(struct adapter *padapter)
/* pHalData->H2CStopInsertQueue = false; */
}
-static void rtl8723b_free_hal_data(struct adapter *padapter)
-{
-}
-
/* */
/* Efuse related code */
/* */
@@ -492,7 +490,7 @@ static u8 hal_EfuseSwitchToBank(
return bRet;
}
-static void Hal_GetEfuseDefinition(
+void Hal_GetEfuseDefinition(
struct adapter *padapter,
u8 efuseType,
u8 type,
@@ -604,46 +602,7 @@ static void Hal_GetEfuseDefinition(
#define EFUSE_ACCESS_ON_8723 0x69 /* For RTL8723 only. */
#define REG_EFUSE_ACCESS_8723 0x00CF /* Efuse access protection for RTL8723 */
-/* */
-static void Hal_BT_EfusePowerSwitch(
- struct adapter *padapter, u8 bWrite, u8 PwrState
-)
-{
- u8 tempval;
- if (PwrState) {
- /* enable BT power cut */
- /* 0x6A[14] = 1 */
- tempval = rtw_read8(padapter, 0x6B);
- tempval |= BIT(6);
- rtw_write8(padapter, 0x6B, tempval);
-
- /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */
- /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */
- msleep(1);
- /* disable BT output isolation */
- /* 0x6A[15] = 0 */
- tempval = rtw_read8(padapter, 0x6B);
- tempval &= ~BIT(7);
- rtw_write8(padapter, 0x6B, tempval);
- } else {
- /* enable BT output isolation */
- /* 0x6A[15] = 1 */
- tempval = rtw_read8(padapter, 0x6B);
- tempval |= BIT(7);
- rtw_write8(padapter, 0x6B, tempval);
-
- /* Attention!! Between 0x6A[14] and 0x6A[15] setting need 100us delay */
- /* So don't write 0x6A[14]= 1 and 0x6A[15]= 0 together! */
-
- /* disable BT power cut */
- /* 0x6A[14] = 1 */
- tempval = rtw_read8(padapter, 0x6B);
- tempval &= ~BIT(6);
- rtw_write8(padapter, 0x6B, tempval);
- }
-
-}
-static void Hal_EfusePowerSwitch(
+void Hal_EfusePowerSwitch(
struct adapter *padapter, u8 bWrite, u8 PwrState
)
{
@@ -928,7 +887,7 @@ exit:
kfree(efuseTbl);
}
-static void Hal_ReadEFuse(
+void Hal_ReadEFuse(
struct adapter *padapter,
u8 efuseType,
u16 _offset,
@@ -1069,7 +1028,6 @@ static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest)
/* only when bank is switched we have to reset the efuse_addr. */
if (bank != startBank)
efuse_addr = 0;
-#if 1
while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
if (efuse_OneByteRead(padapter, efuse_addr,
@@ -1098,33 +1056,6 @@ static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest)
/* read next header */
efuse_addr += (word_cnts*2)+1;
}
-#else
- while (
- bContinual &&
- efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest) &&
- AVAILABLE_EFUSE_ADDR(efuse_addr)
- ) {
- if (efuse_data != 0xFF) {
- if ((efuse_data&0x1F) == 0x0F) { /* extended header */
- efuse_addr++;
- efuse_OneByteRead(padapter, efuse_addr, &efuse_data, bPseudoTest);
- if ((efuse_data & 0x0F) == 0x0F) {
- efuse_addr++;
- continue;
- } else {
- hworden = efuse_data & 0x0F;
- }
- } else {
- hworden = efuse_data & 0x0F;
- }
- word_cnts = Efuse_CalculateWordCnts(hworden);
- /* read next header */
- efuse_addr = efuse_addr + (word_cnts*2)+1;
- } else
- bContinual = false;
- }
-#endif
-
/* Check if we need to check next bank efuse */
if (efuse_addr < retU2)
@@ -1141,7 +1072,7 @@ static u16 hal_EfuseGetCurrentSize_BT(struct adapter *padapter, u8 bPseudoTest)
return retU2;
}
-static u16 Hal_EfuseGetCurrentSize(
+u16 Hal_EfuseGetCurrentSize(
struct adapter *padapter, u8 efuseType, bool bPseudoTest
)
{
@@ -1220,403 +1151,6 @@ static u8 Hal_EfuseWordEnableDataWrite(
return badworden;
}
-static s32 Hal_EfusePgPacketRead(
- struct adapter *padapter,
- u8 offset,
- u8 *data,
- bool bPseudoTest
-)
-{
- u8 efuse_data, word_cnts = 0;
- u16 efuse_addr = 0;
- u8 hoffset = 0, hworden = 0;
- u8 i;
- u8 max_section = 0;
- s32 ret;
-
-
- if (!data)
- return false;
-
- EFUSE_GetEfuseDefinition(padapter, EFUSE_WIFI, TYPE_EFUSE_MAX_SECTION, &max_section, bPseudoTest);
- if (offset > max_section)
- return false;
-
- memset(data, 0xFF, PGPKT_DATA_SIZE);
- ret = true;
-
- /* */
- /* <Roger_TODO> Efuse has been pre-programmed dummy 5Bytes at the end of Efuse by CP. */
- /* Skip dummy parts to prevent unexpected data read from Efuse. */
- /* By pass right now. 2009.02.19. */
- /* */
- while (AVAILABLE_EFUSE_ADDR(efuse_addr)) {
- if (efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest) == false) {
- ret = false;
- break;
- }
-
- if (efuse_data == 0xFF)
- break;
-
- if (EXT_HEADER(efuse_data)) {
- hoffset = GET_HDR_OFFSET_2_0(efuse_data);
- efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
- if (ALL_WORDS_DISABLED(efuse_data))
- continue;
-
- hoffset |= ((efuse_data & 0xF0) >> 1);
- hworden = efuse_data & 0x0F;
- } else {
- hoffset = (efuse_data>>4) & 0x0F;
- hworden = efuse_data & 0x0F;
- }
-
- if (hoffset == offset) {
- for (i = 0; i < EFUSE_MAX_WORD_UNIT; i++) {
- /* Check word enable condition in the section */
- if (!(hworden & (0x01<<i))) {
- efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
- data[i*2] = efuse_data;
-
- efuse_OneByteRead(padapter, efuse_addr++, &efuse_data, bPseudoTest);
- data[(i*2)+1] = efuse_data;
- }
- }
- } else {
- word_cnts = Efuse_CalculateWordCnts(hworden);
- efuse_addr += word_cnts*2;
- }
- }
-
- return ret;
-}
-
-static u8 hal_EfusePgCheckAvailableAddr(
- struct adapter *padapter, u8 efuseType, u8 bPseudoTest
-)
-{
- u16 max_available = 0;
- u16 current_size;
-
-
- EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &max_available, bPseudoTest);
-
- current_size = Efuse_GetCurrentSize(padapter, efuseType, bPseudoTest);
- if (current_size >= max_available)
- return false;
-
- return true;
-}
-
-static void hal_EfuseConstructPGPkt(
- u8 offset,
- u8 word_en,
- u8 *pData,
- struct pgpkt_struct *pTargetPkt
-)
-{
- memset(pTargetPkt->data, 0xFF, PGPKT_DATA_SIZE);
- pTargetPkt->offset = offset;
- pTargetPkt->word_en = word_en;
- efuse_WordEnableDataRead(word_en, pData, pTargetPkt->data);
- pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
-}
-
-static u8 hal_EfusePartialWriteCheck(
- struct adapter *padapter,
- u8 efuseType,
- u16 *pAddr,
- struct pgpkt_struct *pTargetPkt,
- u8 bPseudoTest
-)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
- struct efuse_hal *pEfuseHal = &pHalData->EfuseHal;
- u8 bRet = false;
- u16 startAddr = 0, efuse_max_available_len = 0, efuse_max = 0;
- u8 efuse_data = 0;
-
- EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_TOTAL, &efuse_max_available_len, bPseudoTest);
- EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_EFUSE_CONTENT_LEN_BANK, &efuse_max, bPseudoTest);
-
- if (efuseType == EFUSE_WIFI) {
- if (bPseudoTest) {
-#ifdef HAL_EFUSE_MEMORY
- startAddr = (u16)pEfuseHal->fakeEfuseUsedBytes;
-#else
- startAddr = (u16)fakeEfuseUsedBytes;
-#endif
- } else
- rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BYTES, (u8 *)&startAddr);
- } else {
- if (bPseudoTest) {
-#ifdef HAL_EFUSE_MEMORY
- startAddr = (u16)pEfuseHal->fakeBTEfuseUsedBytes;
-#else
- startAddr = (u16)fakeBTEfuseUsedBytes;
-#endif
- } else
- rtw_hal_get_hwreg(padapter, HW_VAR_EFUSE_BT_BYTES, (u8 *)&startAddr);
- }
- startAddr %= efuse_max;
-
- while (1) {
- if (startAddr >= efuse_max_available_len) {
- bRet = false;
- break;
- }
-
- if (efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest) && (efuse_data != 0xFF)) {
-#if 1
- bRet = false;
- break;
-#else
- if (EXT_HEADER(efuse_data)) {
- cur_header = efuse_data;
- startAddr++;
- efuse_OneByteRead(padapter, startAddr, &efuse_data, bPseudoTest);
- if (ALL_WORDS_DISABLED(efuse_data)) {
- bRet = false;
- break;
- } else {
- curPkt.offset = ((cur_header & 0xE0) >> 5) | ((efuse_data & 0xF0) >> 1);
- curPkt.word_en = efuse_data & 0x0F;
- }
- } else {
- cur_header = efuse_data;
- curPkt.offset = (cur_header>>4) & 0x0F;
- curPkt.word_en = cur_header & 0x0F;
- }
-
- curPkt.word_cnts = Efuse_CalculateWordCnts(curPkt.word_en);
- /* if same header is found but no data followed */
- /* write some part of data followed by the header. */
- if (
- (curPkt.offset == pTargetPkt->offset) &&
- (hal_EfuseCheckIfDatafollowed(padapter, curPkt.word_cnts, startAddr+1, bPseudoTest) == false) &&
- wordEnMatched(pTargetPkt, &curPkt, &matched_wden) == true
- ) {
- /* Here to write partial data */
- badworden = Efuse_WordEnableDataWrite(padapter, startAddr+1, matched_wden, pTargetPkt->data, bPseudoTest);
- if (badworden != 0x0F) {
- u32 PgWriteSuccess = 0;
- /* if write fail on some words, write these bad words again */
- if (efuseType == EFUSE_WIFI)
- PgWriteSuccess = Efuse_PgPacketWrite(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
- else
- PgWriteSuccess = Efuse_PgPacketWrite_BT(padapter, pTargetPkt->offset, badworden, pTargetPkt->data, bPseudoTest);
-
- if (!PgWriteSuccess) {
- bRet = false; /* write fail, return */
- break;
- }
- }
- /* partial write ok, update the target packet for later use */
- for (i = 0; i < 4; i++) {
- if ((matched_wden & (0x1<<i)) == 0) { /* this word has been written */
- pTargetPkt->word_en |= (0x1<<i); /* disable the word */
- }
- }
- pTargetPkt->word_cnts = Efuse_CalculateWordCnts(pTargetPkt->word_en);
- }
- /* read from next header */
- startAddr = startAddr + (curPkt.word_cnts*2) + 1;
-#endif
- } else {
- /* not used header, 0xff */
- *pAddr = startAddr;
- bRet = true;
- break;
- }
- }
-
- return bRet;
-}
-
-static u8 hal_EfusePgPacketWrite1ByteHeader(
- struct adapter *padapter,
- u8 efuseType,
- u16 *pAddr,
- struct pgpkt_struct *pTargetPkt,
- u8 bPseudoTest
-)
-{
- u8 pg_header = 0, tmp_header = 0;
- u16 efuse_addr = *pAddr;
- u8 repeatcnt = 0;
-
- pg_header = ((pTargetPkt->offset << 4) & 0xf0) | pTargetPkt->word_en;
-
- do {
- efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
- efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
- if (tmp_header != 0xFF)
- break;
- if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
- return false;
-
- } while (1);
-
- if (tmp_header != pg_header)
- return false;
-
- *pAddr = efuse_addr;
-
- return true;
-}
-
-static u8 hal_EfusePgPacketWrite2ByteHeader(
- struct adapter *padapter,
- u8 efuseType,
- u16 *pAddr,
- struct pgpkt_struct *pTargetPkt,
- u8 bPseudoTest
-)
-{
- u16 efuse_addr, efuse_max_available_len = 0;
- u8 pg_header = 0, tmp_header = 0;
- u8 repeatcnt = 0;
-
- EFUSE_GetEfuseDefinition(padapter, efuseType, TYPE_AVAILABLE_EFUSE_BYTES_BANK, &efuse_max_available_len, bPseudoTest);
-
- efuse_addr = *pAddr;
- if (efuse_addr >= efuse_max_available_len)
- return false;
-
- pg_header = ((pTargetPkt->offset & 0x07) << 5) | 0x0F;
-
- do {
- efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
- efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
- if (tmp_header != 0xFF)
- break;
- if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
- return false;
-
- } while (1);
-
- if (tmp_header != pg_header)
- return false;
-
- /* to write ext_header */
- efuse_addr++;
- pg_header = ((pTargetPkt->offset & 0x78) << 1) | pTargetPkt->word_en;
-
- do {
- efuse_OneByteWrite(padapter, efuse_addr, pg_header, bPseudoTest);
- efuse_OneByteRead(padapter, efuse_addr, &tmp_header, bPseudoTest);
- if (tmp_header != 0xFF)
- break;
- if (repeatcnt++ > EFUSE_REPEAT_THRESHOLD_)
- return false;
-
- } while (1);
-
- if (tmp_header != pg_header) /* offset PG fail */
- return false;
-
- *pAddr = efuse_addr;
-
- return true;
-}
-
-static u8 hal_EfusePgPacketWriteHeader(
- struct adapter *padapter,
- u8 efuseType,
- u16 *pAddr,
- struct pgpkt_struct *pTargetPkt,
- u8 bPseudoTest
-)
-{
- u8 bRet = false;
-
- if (pTargetPkt->offset >= EFUSE_MAX_SECTION_BASE)
- bRet = hal_EfusePgPacketWrite2ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
- else
- bRet = hal_EfusePgPacketWrite1ByteHeader(padapter, efuseType, pAddr, pTargetPkt, bPseudoTest);
-
- return bRet;
-}
-
-static u8 hal_EfusePgPacketWriteData(
- struct adapter *padapter,
- u8 efuseType,
- u16 *pAddr,
- struct pgpkt_struct *pTargetPkt,
- u8 bPseudoTest
-)
-{
- u16 efuse_addr;
- u8 badworden;
-
-
- efuse_addr = *pAddr;
- badworden = Efuse_WordEnableDataWrite(padapter, efuse_addr+1, pTargetPkt->word_en, pTargetPkt->data, bPseudoTest);
- if (badworden != 0x0F)
- return false;
-
- return true;
-}
-
-static s32 Hal_EfusePgPacketWrite(
- struct adapter *padapter,
- u8 offset,
- u8 word_en,
- u8 *pData,
- bool bPseudoTest
-)
-{
- struct pgpkt_struct targetPkt;
- u16 startAddr = 0;
- u8 efuseType = EFUSE_WIFI;
-
- if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest))
- return false;
-
- hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
-
- if (!hal_EfusePartialWriteCheck(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- if (!hal_EfusePgPacketWriteData(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- return true;
-}
-
-static bool Hal_EfusePgPacketWrite_BT(
- struct adapter *padapter,
- u8 offset,
- u8 word_en,
- u8 *pData,
- bool bPseudoTest
-)
-{
- struct pgpkt_struct targetPkt;
- u16 startAddr = 0;
- u8 efuseType = EFUSE_BT;
-
- if (!hal_EfusePgCheckAvailableAddr(padapter, efuseType, bPseudoTest))
- return false;
-
- hal_EfuseConstructPGPkt(offset, word_en, pData, &targetPkt);
-
- if (!hal_EfusePartialWriteCheck(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- if (!hal_EfusePgPacketWriteHeader(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- if (!hal_EfusePgPacketWriteData(padapter, efuseType, &startAddr, &targetPkt, bPseudoTest))
- return false;
-
- return true;
-}
-
static struct hal_version ReadChipVersion8723B(struct adapter *padapter)
{
u32 value32;
@@ -1645,15 +1179,15 @@ static struct hal_version ReadChipVersion8723B(struct adapter *padapter)
pHalData->MultiFunc |= ((value32 & BT_FUNC_EN) ? RT_MULTI_FUNC_BT : 0);
pHalData->MultiFunc |= ((value32 & GPS_FUNC_EN) ? RT_MULTI_FUNC_GPS : 0);
pHalData->PolarityCtl = ((value32 & WL_HWPDN_SL) ? RT_POLARITY_HIGH_ACT : RT_POLARITY_LOW_ACT);
-#if 1
+
dump_chip_info(ChipVersion);
-#endif
+
pHalData->VersionID = ChipVersion;
return ChipVersion;
}
-static void rtl8723b_read_chip_version(struct adapter *padapter)
+void rtl8723b_read_chip_version(struct adapter *padapter)
{
ReadChipVersion8723B(padapter);
}
@@ -1747,7 +1281,7 @@ static void _BeaconFunctionEnable(struct adapter *padapter, u8 Enable, u8 Linked
rtw_write8(padapter, REG_RD_CTRL+1, 0x6F);
}
-static void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter)
+void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter)
{
u8 val8;
u32 value32;
@@ -1808,16 +1342,6 @@ static void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter)
rtw_write8(padapter, bcn_ctrl_reg, val8);
}
-static void rtl8723b_GetHalODMVar(
- struct adapter *Adapter,
- enum hal_odm_variable eVariable,
- void *pValue1,
- void *pValue2
-)
-{
- GetHalODMVar(Adapter, eVariable, pValue1, pValue2);
-}
-
static void rtl8723b_SetHalODMVar(
struct adapter *Adapter,
enum hal_odm_variable eVariable,
@@ -1836,7 +1360,7 @@ static void hal_notch_filter_8723b(struct adapter *adapter, bool enable)
rtw_write8(adapter, rOFDM0_RxDSP+1, rtw_read8(adapter, rOFDM0_RxDSP+1) & ~BIT1);
}
-static void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level)
+void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level)
{
u32 mask, rate_bitmap;
u8 shortGIrate = false;
@@ -1876,49 +1400,9 @@ static void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_l
void rtl8723b_set_hal_ops(struct hal_ops *pHalFunc)
{
- pHalFunc->free_hal_data = &rtl8723b_free_hal_data;
-
- pHalFunc->dm_init = &rtl8723b_init_dm_priv;
-
- pHalFunc->read_chip_version = &rtl8723b_read_chip_version;
-
- pHalFunc->UpdateRAMaskHandler = &UpdateHalRAMask8723B;
-
- pHalFunc->set_bwmode_handler = &PHY_SetBWMode8723B;
- pHalFunc->set_channel_handler = &PHY_SwChnl8723B;
- pHalFunc->set_chnl_bw_handler = &PHY_SetSwChnlBWMode8723B;
-
- pHalFunc->set_tx_power_level_handler = &PHY_SetTxPowerLevel8723B;
- pHalFunc->get_tx_power_level_handler = &PHY_GetTxPowerLevel8723B;
-
- pHalFunc->hal_dm_watchdog = &rtl8723b_HalDmWatchDog;
- pHalFunc->hal_dm_watchdog_in_lps = &rtl8723b_HalDmWatchDog_in_LPS;
-
-
- pHalFunc->SetBeaconRelatedRegistersHandler = &rtl8723b_SetBeaconRelatedRegisters;
-
- pHalFunc->Add_RateATid = &rtl8723b_Add_RateATid;
-
- pHalFunc->run_thread = &rtl8723b_start_thread;
- pHalFunc->cancel_thread = &rtl8723b_stop_thread;
-
- pHalFunc->read_bbreg = &PHY_QueryBBReg_8723B;
- pHalFunc->write_bbreg = &PHY_SetBBReg_8723B;
- pHalFunc->read_rfreg = &PHY_QueryRFReg_8723B;
- pHalFunc->write_rfreg = &PHY_SetRFReg_8723B;
-
/* Efuse related function */
- pHalFunc->BTEfusePowerSwitch = &Hal_BT_EfusePowerSwitch;
- pHalFunc->EfusePowerSwitch = &Hal_EfusePowerSwitch;
- pHalFunc->ReadEFuse = &Hal_ReadEFuse;
- pHalFunc->EFUSEGetEfuseDefinition = &Hal_GetEfuseDefinition;
- pHalFunc->EfuseGetCurrentSize = &Hal_EfuseGetCurrentSize;
- pHalFunc->Efuse_PgPacketRead = &Hal_EfusePgPacketRead;
- pHalFunc->Efuse_PgPacketWrite = &Hal_EfusePgPacketWrite;
pHalFunc->Efuse_WordEnableDataWrite = &Hal_EfuseWordEnableDataWrite;
- pHalFunc->Efuse_PgPacketWrite_BT = &Hal_EfusePgPacketWrite_BT;
- pHalFunc->GetHalODMVarHandler = &rtl8723b_GetHalODMVar;
pHalFunc->SetHalODMVarHandler = &rtl8723b_SetHalODMVar;
pHalFunc->xmit_thread_handler = &hal_xmit_handler;
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
index 4ff092b7c9c9..d8709d40cb33 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723b_phycfg.c
@@ -575,10 +575,6 @@ void PHY_SetTxPowerLevel8723B(struct adapter *Adapter, u8 Channel)
PHY_SetTxPowerLevelByPath(Adapter, Channel, RFPath);
}
-void PHY_GetTxPowerLevel8723B(struct adapter *Adapter, s32 *powerlevel)
-{
-}
-
static void phy_SetRegBW_8723B(
struct adapter *Adapter, enum channel_width CurrentBW
)
@@ -764,17 +760,6 @@ static void PHY_HandleSwChnlAndSetBW8723B(
}
}
-void PHY_SetBWMode8723B(
- struct adapter *Adapter,
- enum channel_width Bandwidth, /* 20M or 40M */
- unsigned char Offset /* Upper, Lower, or Don't care */
-)
-{
- struct hal_com_data *pHalData = GET_HAL_DATA(Adapter);
-
- PHY_HandleSwChnlAndSetBW8723B(Adapter, false, true, pHalData->CurrentChannel, Bandwidth, Offset, Offset, pHalData->CurrentChannel);
-}
-
/* Call after initialization */
void PHY_SwChnl8723B(struct adapter *Adapter, u8 channel)
{
diff --git a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
index 78298e63edce..5dc1c12fe03e 100644
--- a/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
+++ b/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c
@@ -411,14 +411,12 @@ int rtl8723bs_xmit_thread(void *context)
s32 ret;
struct adapter *padapter;
struct xmit_priv *pxmitpriv;
- u8 thread_name[20];
ret = _SUCCESS;
padapter = context;
pxmitpriv = &padapter->xmitpriv;
- rtw_sprintf(thread_name, 20, "RTWHALXT-%s", ADPT_ARG(padapter));
- thread_enter(thread_name);
+ allow_signal(SIGTERM);
do {
ret = rtl8723bs_xmit_handler(padapter);
diff --git a/drivers/staging/rtl8723bs/hal/sdio_halinit.c b/drivers/staging/rtl8723bs/hal/sdio_halinit.c
index d3aae413fc0f..af9a2b068796 100644
--- a/drivers/staging/rtl8723bs/hal/sdio_halinit.c
+++ b/drivers/staging/rtl8723bs/hal/sdio_halinit.c
@@ -583,7 +583,7 @@ static bool HalDetectPwrDownMode(struct adapter *Adapter)
return pHalData->pwrdown;
} /* HalDetectPwrDownMode */
-static u32 rtl8723bs_hal_init(struct adapter *padapter)
+u32 rtl8723bs_hal_init(struct adapter *padapter)
{
s32 ret;
struct hal_com_data *pHalData;
@@ -884,7 +884,7 @@ static void CardDisableRTL8723BSdio(struct adapter *padapter)
HalPwrSeqCmdParsing(padapter, PWR_CUT_ALL_MSK, PWR_FAB_ALL_MSK, PWR_INTF_SDIO_MSK, rtl8723B_card_disable_flow);
}
-static u32 rtl8723bs_hal_deinit(struct adapter *padapter)
+u32 rtl8723bs_hal_deinit(struct adapter *padapter)
{
struct dvobj_priv *psdpriv = padapter->dvobj;
struct debug_priv *pdbgpriv = &psdpriv->drv_dbg;
@@ -937,17 +937,7 @@ static u32 rtl8723bs_hal_deinit(struct adapter *padapter)
return _SUCCESS;
}
-static u32 rtl8723bs_inirp_init(struct adapter *padapter)
-{
- return _SUCCESS;
-}
-
-static u32 rtl8723bs_inirp_deinit(struct adapter *padapter)
-{
- return _SUCCESS;
-}
-
-static void rtl8723bs_init_default_value(struct adapter *padapter)
+void rtl8723bs_init_default_value(struct adapter *padapter)
{
struct hal_com_data *pHalData;
@@ -960,7 +950,7 @@ static void rtl8723bs_init_default_value(struct adapter *padapter)
pHalData->SdioRxFIFOCnt = 0;
}
-static void rtl8723bs_interface_configure(struct adapter *padapter)
+void rtl8723bs_interface_configure(struct adapter *padapter)
{
struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
@@ -1142,7 +1132,7 @@ static s32 _ReadAdapterInfo8723BS(struct adapter *padapter)
return _SUCCESS;
}
-static void ReadAdapterInfo8723BS(struct adapter *padapter)
+void ReadAdapterInfo8723BS(struct adapter *padapter)
{
/* Read EEPROM size before call any EEPROM function */
padapter->EepromAddressSize = GetEEPROMSize8723B(padapter);
@@ -1154,7 +1144,7 @@ static void ReadAdapterInfo8723BS(struct adapter *padapter)
* If variable not handled here,
* some variables will be processed in SetHwReg8723B()
*/
-static void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
+void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
{
u8 val8;
@@ -1195,7 +1185,7 @@ static void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
* If variable not handled here,
* some variables will be processed in GetHwReg8723B()
*/
-static void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
+void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
{
switch (variable) {
case HW_VAR_CPWM:
@@ -1214,7 +1204,7 @@ static void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val)
}
}
-static void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len)
+void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len)
{
switch (variable) {
case HW_VAR_C2H_HANDLE:
@@ -1229,7 +1219,7 @@ static void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf
/* Description: */
/* Query setting of specified variable. */
/* */
-static u8 GetHalDefVar8723BSDIO(
+u8 GetHalDefVar8723BSDIO(
struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue
)
{
@@ -1257,8 +1247,7 @@ static u8 GetHalDefVar8723BSDIO(
/* Description: */
/* Change default setting of specified variable. */
/* */
-static u8 SetHalDefVar8723BSDIO(struct adapter *Adapter,
- enum hal_def_variable eVariable, void *pValue)
+u8 SetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue)
{
return SetHalDefVar8723B(Adapter, eVariable, pValue);
}
@@ -1269,32 +1258,4 @@ void rtl8723bs_set_hal_ops(struct adapter *padapter)
rtl8723b_set_hal_ops(pHalFunc);
- pHalFunc->hal_init = &rtl8723bs_hal_init;
- pHalFunc->hal_deinit = &rtl8723bs_hal_deinit;
-
- pHalFunc->inirp_init = &rtl8723bs_inirp_init;
- pHalFunc->inirp_deinit = &rtl8723bs_inirp_deinit;
-
- pHalFunc->init_xmit_priv = &rtl8723bs_init_xmit_priv;
- pHalFunc->free_xmit_priv = &rtl8723bs_free_xmit_priv;
-
- pHalFunc->init_recv_priv = &rtl8723bs_init_recv_priv;
- pHalFunc->free_recv_priv = &rtl8723bs_free_recv_priv;
-
- pHalFunc->init_default_value = &rtl8723bs_init_default_value;
- pHalFunc->intf_chip_configure = &rtl8723bs_interface_configure;
- pHalFunc->read_adapter_info = &ReadAdapterInfo8723BS;
-
- pHalFunc->enable_interrupt = &EnableInterrupt8723BSdio;
- pHalFunc->disable_interrupt = &DisableInterrupt8723BSdio;
- pHalFunc->check_ips_status = &CheckIPSStatus;
- pHalFunc->SetHwRegHandler = &SetHwReg8723BS;
- pHalFunc->GetHwRegHandler = &GetHwReg8723BS;
- pHalFunc->SetHwRegHandlerWithBuf = &SetHwRegWithBuf8723B;
- pHalFunc->GetHalDefVarHandler = &GetHalDefVar8723BSDIO;
- pHalFunc->SetHalDefVarHandler = &SetHalDefVar8723BSDIO;
-
- pHalFunc->hal_xmit = &rtl8723bs_hal_xmit;
- pHalFunc->mgnt_xmit = &rtl8723bs_mgnt_xmit;
- pHalFunc->hal_xmitframe_enqueue = &rtl8723bs_hal_xmitframe_enqueue;
}
diff --git a/drivers/staging/rtl8723bs/include/drv_types.h b/drivers/staging/rtl8723bs/include/drv_types.h
index 0b35c97843cc..7b0e824e05a9 100644
--- a/drivers/staging/rtl8723bs/include/drv_types.h
+++ b/drivers/staging/rtl8723bs/include/drv_types.h
@@ -182,8 +182,6 @@ struct registry_priv {
#include <drv_types_sdio.h>
-#define is_primary_adapter(adapter) (1)
-#define get_iface_type(adapter) (IFACE_PORT0)
#define GET_PRIMARY_ADAPTER(padapter) (((struct adapter *)padapter)->dvobj->if1)
#define GET_IFACE_NUMS(padapter) (((struct adapter *)padapter)->dvobj->iface_nums)
#define GET_ADAPTER(padapter, iface_id) (((struct adapter *)padapter)->dvobj->padapters[iface_id])
@@ -320,14 +318,6 @@ static inline struct device *dvobj_to_dev(struct dvobj_priv *dvobj)
return &dvobj->intf_data.func->dev;
}
-struct adapter *dvobj_get_port0_adapter(struct dvobj_priv *dvobj);
-
-enum {
- IFACE_PORT0, /* mapping to port0 for C/D series chips */
- IFACE_PORT1, /* mapping to port1 for C/D series chip */
- MAX_IFACE_PORT,
-};
-
enum {
DRIVER_NORMAL = 0,
DRIVER_DISAPPEAR = 1,
diff --git a/drivers/staging/rtl8723bs/include/hal_com.h b/drivers/staging/rtl8723bs/include/hal_com.h
index 17d5cfb66a36..4db93484725f 100644
--- a/drivers/staging/rtl8723bs/include/hal_com.h
+++ b/drivers/staging/rtl8723bs/include/hal_com.h
@@ -158,10 +158,6 @@ void rtw_dump_raw_rssi_info(struct adapter *padapter);
void rtw_bb_rf_gain_offset(struct adapter *padapter);
-void GetHalODMVar(struct adapter *Adapter,
- enum hal_odm_variable eVariable,
- void *pValue1,
- void *pValue2);
void SetHalODMVar(
struct adapter *Adapter,
enum hal_odm_variable eVariable,
diff --git a/drivers/staging/rtl8723bs/include/hal_intf.h b/drivers/staging/rtl8723bs/include/hal_intf.h
index efdd1f912b5d..282e141616b0 100644
--- a/drivers/staging/rtl8723bs/include/hal_intf.h
+++ b/drivers/staging/rtl8723bs/include/hal_intf.h
@@ -162,91 +162,9 @@ enum hal_intf_ps_func {
typedef s32 (*c2h_id_filter)(u8 *c2h_evt);
struct hal_ops {
- u32 (*hal_power_on)(struct adapter *padapter);
- void (*hal_power_off)(struct adapter *padapter);
- u32 (*hal_init)(struct adapter *padapter);
- u32 (*hal_deinit)(struct adapter *padapter);
-
- void (*free_hal_data)(struct adapter *padapter);
-
- u32 (*inirp_init)(struct adapter *padapter);
- u32 (*inirp_deinit)(struct adapter *padapter);
- void (*irp_reset)(struct adapter *padapter);
-
- s32 (*init_xmit_priv)(struct adapter *padapter);
- void (*free_xmit_priv)(struct adapter *padapter);
-
- s32 (*init_recv_priv)(struct adapter *padapter);
- void (*free_recv_priv)(struct adapter *padapter);
-
- void (*dm_init)(struct adapter *padapter);
- void (*dm_deinit)(struct adapter *padapter);
- void (*read_chip_version)(struct adapter *padapter);
-
- void (*init_default_value)(struct adapter *padapter);
-
- void (*intf_chip_configure)(struct adapter *padapter);
-
- void (*read_adapter_info)(struct adapter *padapter);
-
- void (*enable_interrupt)(struct adapter *padapter);
- void (*disable_interrupt)(struct adapter *padapter);
- u8 (*check_ips_status)(struct adapter *padapter);
- s32 (*interrupt_handler)(struct adapter *padapter);
- void (*clear_interrupt)(struct adapter *padapter);
- void (*set_bwmode_handler)(struct adapter *padapter, enum channel_width Bandwidth, u8 Offset);
- void (*set_channel_handler)(struct adapter *padapter, u8 channel);
- void (*set_chnl_bw_handler)(struct adapter *padapter, u8 channel, enum channel_width Bandwidth, u8 Offset40, u8 Offset80);
-
- void (*set_tx_power_level_handler)(struct adapter *padapter, u8 channel);
- void (*get_tx_power_level_handler)(struct adapter *padapter, s32 *powerlevel);
-
- void (*hal_dm_watchdog)(struct adapter *padapter);
- void (*hal_dm_watchdog_in_lps)(struct adapter *padapter);
-
-
- void (*SetHwRegHandler)(struct adapter *padapter, u8 variable, u8 *val);
- void (*GetHwRegHandler)(struct adapter *padapter, u8 variable, u8 *val);
-
- void (*SetHwRegHandlerWithBuf)(struct adapter *padapter, u8 variable, u8 *pbuf, int len);
-
- u8 (*GetHalDefVarHandler)(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue);
- u8 (*SetHalDefVarHandler)(struct adapter *padapter, enum hal_def_variable eVariable, void *pValue);
-
- void (*GetHalODMVarHandler)(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, void *pValue2);
void (*SetHalODMVarHandler)(struct adapter *padapter, enum hal_odm_variable eVariable, void *pValue1, bool bSet);
- void (*UpdateRAMaskHandler)(struct adapter *padapter, u32 mac_id, u8 rssi_level);
- void (*SetBeaconRelatedRegistersHandler)(struct adapter *padapter);
-
- void (*Add_RateATid)(struct adapter *padapter, u32 bitmap, u8 *arg, u8 rssi_level);
-
- void (*run_thread)(struct adapter *padapter);
- void (*cancel_thread)(struct adapter *padapter);
-
- u8 (*interface_ps_func)(struct adapter *padapter, enum hal_intf_ps_func efunc_id, u8 *val);
-
- s32 (*hal_xmit)(struct adapter *padapter, struct xmit_frame *pxmitframe);
- /*
- * mgnt_xmit should be implemented to run in interrupt context
- */
- s32 (*mgnt_xmit)(struct adapter *padapter, struct xmit_frame *pmgntframe);
- s32 (*hal_xmitframe_enqueue)(struct adapter *padapter, struct xmit_frame *pxmitframe);
-
- u32 (*read_bbreg)(struct adapter *padapter, u32 RegAddr, u32 BitMask);
- void (*write_bbreg)(struct adapter *padapter, u32 RegAddr, u32 BitMask, u32 Data);
- u32 (*read_rfreg)(struct adapter *padapter, u8 eRFPath, u32 RegAddr, u32 BitMask);
- void (*write_rfreg)(struct adapter *padapter, u8 eRFPath, u32 RegAddr, u32 BitMask, u32 Data);
-
- void (*EfusePowerSwitch)(struct adapter *padapter, u8 bWrite, u8 PwrState);
- void (*BTEfusePowerSwitch)(struct adapter *padapter, u8 bWrite, u8 PwrState);
- void (*ReadEFuse)(struct adapter *padapter, u8 efuseType, u16 _offset, u16 _size_byte, u8 *pbuf, bool bPseudoTest);
- void (*EFUSEGetEfuseDefinition)(struct adapter *padapter, u8 efuseType, u8 type, void *pOut, bool bPseudoTest);
- u16 (*EfuseGetCurrentSize)(struct adapter *padapter, u8 efuseType, bool bPseudoTest);
- int (*Efuse_PgPacketRead)(struct adapter *padapter, u8 offset, u8 *data, bool bPseudoTest);
- int (*Efuse_PgPacketWrite)(struct adapter *padapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest);
u8 (*Efuse_WordEnableDataWrite)(struct adapter *padapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest);
- bool (*Efuse_PgPacketWrite_BT)(struct adapter *padapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest);
s32 (*xmit_thread_handler)(struct adapter *padapter);
void (*hal_notch_filter)(struct adapter *adapter, bool enable);
@@ -357,4 +275,17 @@ s32 rtw_hal_macid_wakeup(struct adapter *padapter, u32 macid);
s32 rtw_hal_fill_h2c_cmd(struct adapter *, u8 ElementID, u32 CmdLen, u8 *pCmdBuffer);
+void SetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val);
+void GetHwReg8723BS(struct adapter *padapter, u8 variable, u8 *val);
+void SetHwRegWithBuf8723B(struct adapter *padapter, u8 variable, u8 *pbuf, int len);
+u8 GetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue);
+u8 SetHalDefVar8723BSDIO(struct adapter *Adapter, enum hal_def_variable eVariable, void *pValue);
+void UpdateHalRAMask8723B(struct adapter *padapter, u32 mac_id, u8 rssi_level);
+void rtl8723b_SetBeaconRelatedRegisters(struct adapter *padapter);
+void Hal_EfusePowerSwitch(struct adapter *padapter, u8 bWrite, u8 PwrState);
+void Hal_ReadEFuse(struct adapter *padapter, u8 efuseType, u16 _offset,
+ u16 _size_byte, u8 *pbuf, bool bPseudoTest);
+void Hal_GetEfuseDefinition(struct adapter *padapter, u8 efuseType, u8 type,
+ void *pOut, bool bPseudoTest);
+u16 Hal_EfuseGetCurrentSize(struct adapter *padapter, u8 efuseType, bool bPseudoTest);
#endif /* __HAL_INTF_H__ */
diff --git a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h
index ea494bcf830b..07bf0a8d019a 100644
--- a/drivers/staging/rtl8723bs/include/hal_phy_cfg.h
+++ b/drivers/staging/rtl8723bs/include/hal_phy_cfg.h
@@ -49,13 +49,8 @@ void PHY_SetTxPowerIndex(struct adapter *Adapter, u32 PowerIndex,
u8 PHY_GetTxPowerIndex(struct adapter *padapter, u8 RFPath, u8 Rate,
enum channel_width BandWidth, u8 Channel);
-void PHY_GetTxPowerLevel8723B(struct adapter *Adapter, s32 *powerlevel);
-
void PHY_SetTxPowerLevel8723B(struct adapter *Adapter, u8 channel);
-void PHY_SetBWMode8723B(struct adapter *Adapter, enum channel_width Bandwidth,
- unsigned char Offset);
-
/* Call after initialization */
void PHY_SwChnl8723B(struct adapter *Adapter, u8 channel);
diff --git a/drivers/staging/rtl8723bs/include/osdep_intf.h b/drivers/staging/rtl8723bs/include/osdep_intf.h
index 111e0179712a..215ece612f71 100644
--- a/drivers/staging/rtl8723bs/include/osdep_intf.h
+++ b/drivers/staging/rtl8723bs/include/osdep_intf.h
@@ -55,9 +55,6 @@ void rtw_unregister_netdevs(struct dvobj_priv *dvobj);
u16 rtw_recv_select_queue(struct sk_buff *skb);
-int rtw_ndev_notifier_register(void);
-void rtw_ndev_notifier_unregister(void);
-
void rtw_ips_dev_unload(struct adapter *padapter);
int rtw_ips_pwr_up(struct adapter *padapter);
diff --git a/drivers/staging/rtl8723bs/include/osdep_service.h b/drivers/staging/rtl8723bs/include/osdep_service.h
index b21267d7ef72..8b1634f4091e 100644
--- a/drivers/staging/rtl8723bs/include/osdep_service.h
+++ b/drivers/staging/rtl8723bs/include/osdep_service.h
@@ -73,11 +73,6 @@ int _rtw_netif_rx(struct net_device *ndev, struct sk_buff *skb);
extern void _rtw_init_queue(struct __queue *pqueue);
-static inline void thread_enter(char *name)
-{
- allow_signal(SIGTERM);
-}
-
static inline void flush_signals_thread(void)
{
if (signal_pending(current))
diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_recv.h b/drivers/staging/rtl8723bs/include/rtl8723b_recv.h
index a108ce89bce4..783f64de0aec 100644
--- a/drivers/staging/rtl8723bs/include/rtl8723b_recv.h
+++ b/drivers/staging/rtl8723bs/include/rtl8723b_recv.h
@@ -87,4 +87,9 @@ void rtl8723bs_free_recv_priv(struct adapter *padapter);
void rtl8723b_query_rx_phy_status(union recv_frame *prframe, struct phy_stat *pphy_stat);
void rtl8723b_process_phy_info(struct adapter *padapter, void *prframe);
+void rtl8723b_read_chip_version(struct adapter *padapter);
+void rtl8723bs_init_default_value(struct adapter *padapter);
+void rtl8723bs_interface_configure(struct adapter *padapter);
+void ReadAdapterInfo8723BS(struct adapter *padapter);
+
#endif
diff --git a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h
index ad2542d0cabe..ac4ca7e05b9b 100644
--- a/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h
+++ b/drivers/staging/rtl8723bs/include/rtl8723b_xmit.h
@@ -405,6 +405,8 @@ struct txdesc_8723b {
void rtl8723b_update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem);
void rtl8723b_fill_fake_txdesc(struct adapter *padapter, u8 *pDesc, u32 BufferLen, u8 IsPsPoll, u8 IsBTQosNull, u8 bDataFrame);
+u32 rtl8723bs_hal_init(struct adapter *padapter);
+u32 rtl8723bs_hal_deinit(struct adapter *padapter);
s32 rtl8723bs_init_xmit_priv(struct adapter *padapter);
void rtl8723bs_free_xmit_priv(struct adapter *padapter);
s32 rtl8723bs_hal_xmit(struct adapter *padapter, struct xmit_frame *pxmitframe);
diff --git a/drivers/staging/rtl8723bs/include/rtw_efuse.h b/drivers/staging/rtl8723bs/include/rtw_efuse.h
index 0cb8c6f6d34d..d6ea8a4a856f 100644
--- a/drivers/staging/rtl8723bs/include/rtw_efuse.h
+++ b/drivers/staging/rtl8723bs/include/rtw_efuse.h
@@ -90,16 +90,12 @@ extern u8 fakeBTEfuseInitMap[];
extern u8 fakeBTEfuseModifiedMap[];
/*------------------------Export global variable----------------------------*/
-u16 Efuse_GetCurrentSize(struct adapter *padapter, u8 efuseType, bool bPseudoTest);
u8 Efuse_CalculateWordCnts(u8 word_en);
void EFUSE_GetEfuseDefinition(struct adapter *padapter, u8 efuseType, u8 type, void *pOut, bool bPseudoTest);
u8 efuse_OneByteRead(struct adapter *padapter, u16 addr, u8 *data, bool bPseudoTest);
u8 efuse_OneByteWrite(struct adapter *padapter, u16 addr, u8 data, bool bPseudoTest);
void Efuse_PowerSwitch(struct adapter *padapter, u8 bWrite, u8 PwrState);
-int Efuse_PgPacketRead(struct adapter *padapter, u8 offset, u8 *data, bool bPseudoTest);
-int Efuse_PgPacketWrite(struct adapter *padapter, u8 offset, u8 word_en, u8 *data, bool bPseudoTest);
-void efuse_WordEnableDataRead(u8 word_en, u8 *sourdata, u8 *targetdata);
u8 Efuse_WordEnableDataWrite(struct adapter *padapter, u16 efuse_addr, u8 word_en, u8 *data, bool bPseudoTest);
u8 EFUSE_Read1Byte(struct adapter *padapter, u16 Address);
diff --git a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h
index 8315399b64fd..2080408743ef 100644
--- a/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h
+++ b/drivers/staging/rtl8723bs/include/rtw_mlme_ext.h
@@ -447,9 +447,7 @@ void Set_MSR(struct adapter *padapter, u8 type);
u8 rtw_get_oper_ch(struct adapter *adapter);
void rtw_set_oper_ch(struct adapter *adapter, u8 ch);
-u8 rtw_get_oper_bw(struct adapter *adapter);
void rtw_set_oper_bw(struct adapter *adapter, u8 bw);
-u8 rtw_get_oper_choffset(struct adapter *adapter);
void rtw_set_oper_choffset(struct adapter *adapter, u8 offset);
u8 rtw_get_center_ch(u8 channel, u8 chnl_bw, u8 chnl_offset);
unsigned long rtw_get_on_cur_ch_time(struct adapter *adapter);
@@ -459,8 +457,6 @@ void r8723bs_select_channel(struct adapter *padapter, unsigned char channel);
unsigned int decide_wait_for_beacon_timeout(unsigned int bcn_interval);
-void read_cam(struct adapter *padapter, u8 entry, u8 *get_key);
-
/* modify HW only */
void _write_cam(struct adapter *padapter, u8 entry, u16 ctrl, u8 *mac, u8 *key);
void _clear_cam_entry(struct adapter *padapter, u8 entry);
@@ -528,7 +524,6 @@ void rtw_camid_free(struct adapter *adapter, u8 cam_id);
extern void rtw_alloc_macid(struct adapter *padapter, struct sta_info *psta);
extern void rtw_release_macid(struct adapter *padapter, struct sta_info *psta);
-extern u8 rtw_search_max_mac_id(struct adapter *padapter);
void report_join_res(struct adapter *padapter, int res);
void report_survey_event(struct adapter *padapter, union recv_frame *precv_frame);
diff --git a/drivers/staging/rtl8723bs/include/rtw_mp.h b/drivers/staging/rtl8723bs/include/rtw_mp.h
index f94bb18479da..5a1cbd2ed851 100644
--- a/drivers/staging/rtl8723bs/include/rtw_mp.h
+++ b/drivers/staging/rtl8723bs/include/rtw_mp.h
@@ -276,10 +276,6 @@ void _write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 bitmask, u3
u32 read_macreg(struct adapter *padapter, u32 addr, u32 sz);
void write_macreg(struct adapter *padapter, u32 addr, u32 val, u32 sz);
-u32 read_bbreg(struct adapter *padapter, u32 addr, u32 bitmask);
-void write_bbreg(struct adapter *padapter, u32 addr, u32 bitmask, u32 val);
-u32 read_rfreg(struct adapter *padapter, u8 rfpath, u32 addr);
-void write_rfreg(struct adapter *padapter, u8 rfpath, u32 addr, u32 val);
void SetChannel(struct adapter *padapter);
void SetBandwidth(struct adapter *padapter);
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
index b63a74e669bc..7fcc46a0bb48 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_cfg80211.c
@@ -581,7 +581,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(txkey, &(param->u.crypt.key[16]), 8);
memcpy(rxkey, &(param->u.crypt.key[24]), 8);
@@ -626,7 +625,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
psta->dot118021XPrivacy = _TKIP_;
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
@@ -657,7 +655,6 @@ static int rtw_cfg80211_ap_set_encryption(struct net_device *dev, struct ieee_pa
memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(txkey, &(param->u.crypt.key[16]), 8);
memcpy(rxkey, &(param->u.crypt.key[24]), 8);
@@ -785,7 +782,6 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
- /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
memcpy(psta->dot11tkiptxmickey.skey, &(param->u.crypt.key[16]), 8);
memcpy(psta->dot11tkiprxmickey.skey, &(param->u.crypt.key[24]), 8);
@@ -806,10 +802,6 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
} else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
/* save the IGTK key, length 16 bytes */
memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /*
- for (no = 0;no<16;no++)
- printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
- */
padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
padapter->securitypriv.binstallBIPkey = true;
}
@@ -817,9 +809,7 @@ static int rtw_cfg80211_set_encryption(struct net_device *dev, struct ieee_param
}
pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
- if (!pbcmc_sta) {
- /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
- } else {
+ if (pbcmc_sta) {
/* Jeff: don't disable ieee8021x_blocked while clearing key */
if (strcmp(param->u.crypt.alg, "none") != 0)
pbcmc_sta->ieee8021x_blocked = false;
@@ -1812,7 +1802,8 @@ static int cfg80211_rtw_set_txpower(struct wiphy *wiphy,
}
static int cfg80211_rtw_get_txpower(struct wiphy *wiphy,
- struct wireless_dev *wdev, int *dbm)
+ struct wireless_dev *wdev,
+ unsigned int link_id, int *dbm)
{
*dbm = (12);
diff --git a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
index a9e481e182ad..793b051536f3 100644
--- a/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
+++ b/drivers/staging/rtl8723bs/os_dep/ioctl_linux.c
@@ -138,9 +138,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
if (check_fwstate(pmlmepriv, WIFI_STATION_STATE | WIFI_MP_STATE) == true) { /* sta mode */
psta = rtw_get_stainfo(pstapriv, get_bssid(pmlmepriv));
- if (!psta) {
- /* DEBUG_ERR(("Set wpa_set_encryption: Obtain Sta_info fail\n")); */
- } else {
+ if (psta) {
/* Jeff: don't disable ieee8021x_blocked while clearing key */
if (strcmp(param->u.crypt.alg, "none") != 0)
psta->ieee8021x_blocked = false;
@@ -154,7 +152,6 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
memcpy(psta->dot118021x_UncstKey.skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
if (strcmp(param->u.crypt.alg, "TKIP") == 0) { /* set mic key */
- /* DEBUG_ERR(("\nset key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len)); */
memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
@@ -177,13 +174,8 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
rtw_set_key(padapter, &padapter->securitypriv, param->u.crypt.idx, 1, true);
} else if (strcmp(param->u.crypt.alg, "BIP") == 0) {
- /* printk("BIP key_len =%d , index =%d @@@@@@@@@@@@@@@@@@\n", param->u.crypt.key_len, param->u.crypt.idx); */
/* save the IGTK key, length 16 bytes */
memcpy(padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /*printk("IGTK key below:\n");
- for (no = 0;no<16;no++)
- printk(" %02x ", padapter->securitypriv.dot11wBIPKey[param->u.crypt.idx].skey[no]);
- printk("\n");*/
padapter->securitypriv.dot11wBIPKeyid = param->u.crypt.idx;
padapter->securitypriv.binstallBIPkey = true;
}
@@ -191,9 +183,7 @@ static int wpa_set_encryption(struct net_device *dev, struct ieee_param *param,
}
pbcmc_sta = rtw_get_bcmc_stainfo(padapter);
- if (!pbcmc_sta) {
- /* DEBUG_ERR(("Set OID_802_11_ADD_KEY: bcmc stainfo is null\n")); */
- } else {
+ if (pbcmc_sta) {
/* Jeff: don't disable ieee8021x_blocked while clearing key */
if (strcmp(param->u.crypt.alg, "none") != 0)
pbcmc_sta->ieee8021x_blocked = false;
@@ -629,7 +619,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(txkey, &param->u.crypt.key[16], 8);
memcpy(psecuritypriv->dot118021XGrprxmickey[param->u.crypt.idx].skey, &param->u.crypt.key[24], 8);
@@ -674,7 +663,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
} else if (strcmp(param->u.crypt.alg, "TKIP") == 0) {
psta->dot118021XPrivacy = _TKIP_;
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(psta->dot11tkiptxmickey.skey, &param->u.crypt.key[16], 8);
memcpy(psta->dot11tkiprxmickey.skey, &param->u.crypt.key[24], 8);
@@ -703,7 +691,6 @@ static int rtw_set_encryption(struct net_device *dev, struct ieee_param *param,
memcpy(grpkey, param->u.crypt.key, (param->u.crypt.key_len > 16 ? 16 : param->u.crypt.key_len));
- /* DEBUG_ERR("set key length :param->u.crypt.key_len =%d\n", param->u.crypt.key_len); */
/* set mic key */
memcpy(txkey, &param->u.crypt.key[16], 8);
memcpy(rxkey, &param->u.crypt.key[24], 8);
diff --git a/drivers/staging/rtl8723bs/os_dep/os_intfs.c b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
index fc9b9c5efb50..4e1917c05402 100644
--- a/drivers/staging/rtl8723bs/os_dep/os_intfs.c
+++ b/drivers/staging/rtl8723bs/os_dep/os_intfs.c
@@ -381,34 +381,6 @@ u16 rtw_recv_select_queue(struct sk_buff *skb)
return rtw_1d_to_queue[priority];
}
-static int rtw_ndev_notifier_call(struct notifier_block *nb, unsigned long state, void *ptr)
-{
- struct net_device *dev = netdev_notifier_info_to_dev(ptr);
-
- if (dev->netdev_ops->ndo_do_ioctl != rtw_ioctl)
- return NOTIFY_DONE;
-
- netdev_dbg(dev, FUNC_NDEV_FMT " state:%lu\n", FUNC_NDEV_ARG(dev),
- state);
-
- return NOTIFY_DONE;
-}
-
-static struct notifier_block rtw_ndev_notifier = {
- .notifier_call = rtw_ndev_notifier_call,
-};
-
-int rtw_ndev_notifier_register(void)
-{
- return register_netdevice_notifier(&rtw_ndev_notifier);
-}
-
-void rtw_ndev_notifier_unregister(void)
-{
- unregister_netdevice_notifier(&rtw_ndev_notifier);
-}
-
-
static int rtw_ndev_init(struct net_device *dev)
{
struct adapter *adapter = rtw_netdev_priv(dev);
@@ -633,8 +605,7 @@ void rtw_reset_drv_sw(struct adapter *padapter)
struct pwrctrl_priv *pwrctrlpriv = adapter_to_pwrctl(padapter);
/* hal_priv */
- if (is_primary_adapter(padapter))
- rtw_hal_def_value_init(padapter);
+ rtw_hal_def_value_init(padapter);
RTW_ENABLE_FUNC(padapter, DF_RX_BIT);
RTW_ENABLE_FUNC(padapter, DF_TX_BIT);
diff --git a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
index d18fde4e5d6c..5a7238e661ff 100644
--- a/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
+++ b/drivers/staging/rtl8723bs/os_dep/sdio_intf.c
@@ -72,7 +72,7 @@ static int sdio_alloc_irq(struct dvobj_priv *dvobj)
err = sdio_claim_irq(func, &sd_sync_int_hdl);
if (err) {
dvobj->drv_dbg.dbg_sdio_alloc_irq_error_cnt++;
- printk(KERN_CRIT "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err);
+ netdev_crit(dvobj->if1->pnetdev, "%s: sdio_claim_irq FAIL(%d)!\n", __func__, err);
} else {
dvobj->drv_dbg.dbg_sdio_alloc_irq_cnt++;
dvobj->irq_alloc = 1;
@@ -382,7 +382,6 @@ static int rtw_drv_init(
if (sdio_alloc_irq(dvobj) != _SUCCESS)
goto free_if1;
- rtw_ndev_notifier_register();
status = _SUCCESS;
free_if1:
@@ -484,22 +483,12 @@ static int rtw_sdio_resume(struct device *dev)
static int __init rtw_drv_entry(void)
{
- int ret;
-
- ret = sdio_register_driver(&rtl8723bs_sdio_driver);
- if (ret != 0)
- rtw_ndev_notifier_unregister();
-
- return ret;
+ return sdio_register_driver(&rtl8723bs_sdio_driver);
}
+module_init(rtw_drv_entry);
static void __exit rtw_drv_halt(void)
{
sdio_unregister_driver(&rtl8723bs_sdio_driver);
-
- rtw_ndev_notifier_unregister();
}
-
-
-module_init(rtw_drv_entry);
module_exit(rtw_drv_halt);
diff --git a/drivers/staging/rts5208/Kconfig b/drivers/staging/rts5208/Kconfig
deleted file mode 100644
index b864023d3ccb..000000000000
--- a/drivers/staging/rts5208/Kconfig
+++ /dev/null
@@ -1,9 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config RTS5208
- tristate "Realtek PCI-E Card Reader RTS5208/5288 support"
- depends on PCI && SCSI
- help
- Say Y here to include driver code to support the Realtek
- PCI-E card reader rts5208/rts5288.
-
- If this driver is compiled as a module, it will be named rts5208.
diff --git a/drivers/staging/rts5208/Makefile b/drivers/staging/rts5208/Makefile
deleted file mode 100644
index 3c9e9797d3d9..000000000000
--- a/drivers/staging/rts5208/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_RTS5208) := rts5208.o
-
-rts5208-y := rtsx.o rtsx_chip.o rtsx_transport.o rtsx_scsi.o \
- rtsx_card.o general.o sd.o xd.o ms.o spi.o
diff --git a/drivers/staging/rts5208/TODO b/drivers/staging/rts5208/TODO
deleted file mode 100644
index 9cec0d8dd0b6..000000000000
--- a/drivers/staging/rts5208/TODO
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
-- use kernel coding style
-- checkpatch.pl fixes
-- We will use the stack in drivers/mmc to implement
- rts5208/5288 in the future
-
-Micky Ching <micky_ching@realsil.com.cn>
diff --git a/drivers/staging/rts5208/general.c b/drivers/staging/rts5208/general.c
deleted file mode 100644
index 0f912b011064..000000000000
--- a/drivers/staging/rts5208/general.c
+++ /dev/null
@@ -1,25 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include "general.h"
-
-int bit1cnt_long(u32 data)
-{
- int i, cnt = 0;
-
- for (i = 0; i < 32; i++) {
- if (data & 0x01)
- cnt++;
- data >>= 1;
- }
- return cnt;
-}
-
diff --git a/drivers/staging/rts5208/general.h b/drivers/staging/rts5208/general.h
deleted file mode 100644
index 53e2dbabf04b..000000000000
--- a/drivers/staging/rts5208/general.h
+++ /dev/null
@@ -1,19 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __RTSX_GENERAL_H
-#define __RTSX_GENERAL_H
-
-#include "rtsx.h"
-
-int bit1cnt_long(u32 data);
-
-#endif /* __RTSX_GENERAL_H */
diff --git a/drivers/staging/rts5208/ms.c b/drivers/staging/rts5208/ms.c
deleted file mode 100644
index bfeb5873bf3b..000000000000
--- a/drivers/staging/rts5208/ms.c
+++ /dev/null
@@ -1,4311 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "ms.h"
-
-static inline void ms_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct ms_info *ms_card = &chip->ms_card;
-
- ms_card->err_code = err_code;
-}
-
-static inline int ms_check_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct ms_info *ms_card = &chip->ms_card;
-
- return (ms_card->err_code == err_code);
-}
-
-static int ms_parse_err_code(struct rtsx_chip *chip)
-{
- return STATUS_FAIL;
-}
-
-static int ms_transfer_tpc(struct rtsx_chip *chip, u8 trans_mode,
- u8 tpc, u8 cnt, u8 cfg)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- u8 *ptr;
-
- dev_dbg(rtsx_dev(chip), "%s: tpc = 0x%x\n", __func__, tpc);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER,
- 0xFF, MS_TRANSFER_START | trans_mode);
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_add_cmd(chip, READ_REG_CMD, MS_TRANS_CFG, 0, 0);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 5000);
- if (retval < 0) {
- rtsx_clear_ms_error(chip);
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- if (!(tpc & 0x08)) { /* Read Packet */
- if (*ptr & MS_CRC16_ERR) {
- ms_set_err_code(chip, MS_CRC16_ERROR);
- return ms_parse_err_code(chip);
- }
- } else { /* Write Packet */
- if (CHK_MSPRO(ms_card) && !(*ptr & 0x80)) {
- if (*ptr & (MS_INT_ERR | MS_INT_CMDNK)) {
- ms_set_err_code(chip, MS_CMD_NK);
- return ms_parse_err_code(chip);
- }
- }
- }
-
- if (*ptr & MS_RDY_TIMEOUT) {
- rtsx_clear_ms_error(chip);
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_transfer_data(struct rtsx_chip *chip, u8 trans_mode,
- u8 tpc, u16 sec_cnt, u8 cfg, bool mode_2k,
- int use_sg, void *buf, int buf_len)
-{
- int retval;
- u8 val, err_code = 0;
- enum dma_data_direction dir;
-
- if (!buf || !buf_len)
- return STATUS_FAIL;
-
- if (trans_mode == MS_TM_AUTO_READ) {
- dir = DMA_FROM_DEVICE;
- err_code = MS_FLASH_READ_ERROR;
- } else if (trans_mode == MS_TM_AUTO_WRITE) {
- dir = DMA_TO_DEVICE;
- err_code = MS_FLASH_WRITE_ERROR;
- } else {
- return STATUS_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- MS_SECTOR_CNT_H, 0xFF, (u8)(sec_cnt >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_SECTOR_CNT_L, 0xFF, (u8)sec_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
-
- if (mode_2k) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- MS_CFG, MS_2K_SECTOR_MODE, MS_2K_SECTOR_MODE);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_CFG, MS_2K_SECTOR_MODE, 0);
- }
-
- trans_dma_enable(dir, chip, sec_cnt * 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- MS_TRANSFER, 0xFF, MS_TRANSFER_START | trans_mode);
- rtsx_add_cmd(chip, CHECK_REG_CMD,
- MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data(chip, MS_CARD, buf, buf_len,
- use_sg, dir, chip->mspro_timeout);
- if (retval < 0) {
- ms_set_err_code(chip, err_code);
- if (retval == -ETIMEDOUT)
- retval = STATUS_TIMEDOUT;
- else
- retval = STATUS_FAIL;
-
- return retval;
- }
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval)
- return retval;
-
- if (val & (MS_INT_CMDNK | MS_INT_ERR | MS_CRC16_ERR | MS_RDY_TIMEOUT))
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_write_bytes(struct rtsx_chip *chip,
- u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
-
- if (!data || data_len < cnt)
- return STATUS_ERROR;
-
- rtsx_init_cmd(chip);
-
- for (i = 0; i < cnt; i++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- PPBUF_BASE2 + i, 0xFF, data[i]);
- }
- if (cnt % 2)
- rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2 + i, 0xFF, 0xFF);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- MS_TRANSFER, 0xFF, MS_TRANSFER_START | MS_TM_WRITE_BYTES);
- rtsx_add_cmd(chip, CHECK_REG_CMD,
- MS_TRANSFER, MS_TRANSFER_END, MS_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 5000);
- if (retval < 0) {
- u8 val = 0;
-
- rtsx_read_register(chip, MS_TRANS_CFG, &val);
- dev_dbg(rtsx_dev(chip), "MS_TRANS_CFG: 0x%02x\n", val);
-
- rtsx_clear_ms_error(chip);
-
- if (!(tpc & 0x08)) {
- if (val & MS_CRC16_ERR) {
- ms_set_err_code(chip, MS_CRC16_ERROR);
- return ms_parse_err_code(chip);
- }
- } else {
- if (CHK_MSPRO(ms_card) && !(val & 0x80)) {
- if (val & (MS_INT_ERR | MS_INT_CMDNK)) {
- ms_set_err_code(chip, MS_CMD_NK);
- return ms_parse_err_code(chip);
- }
- }
- }
-
- if (val & MS_RDY_TIMEOUT) {
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_read_bytes(struct rtsx_chip *chip,
- u8 tpc, u8 cnt, u8 cfg, u8 *data, int data_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 *ptr;
-
- if (!data)
- return STATUS_ERROR;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, tpc);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_BYTE_CNT, 0xFF, cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, cfg);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
- MS_TRANSFER_START | MS_TM_READ_BYTES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- for (i = 0; i < data_len - 1; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + i, 0, 0);
-
- if (data_len % 2)
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len, 0, 0);
- else
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + data_len - 1,
- 0, 0);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 5000);
- if (retval < 0) {
- u8 val = 0;
-
- rtsx_read_register(chip, MS_TRANS_CFG, &val);
- rtsx_clear_ms_error(chip);
-
- if (!(tpc & 0x08)) {
- if (val & MS_CRC16_ERR) {
- ms_set_err_code(chip, MS_CRC16_ERROR);
- return ms_parse_err_code(chip);
- }
- } else {
- if (CHK_MSPRO(ms_card) && !(val & 0x80)) {
- if (val & (MS_INT_ERR | MS_INT_CMDNK)) {
- ms_set_err_code(chip, MS_CMD_NK);
- return ms_parse_err_code(chip);
- }
- }
- }
-
- if (val & MS_RDY_TIMEOUT) {
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- ms_set_err_code(chip, MS_TO_ERROR);
- return ms_parse_err_code(chip);
- }
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- for (i = 0; i < data_len; i++)
- data[i] = ptr[i];
-
- if (tpc == PRO_READ_SHORT_DATA && data_len == 8) {
- dev_dbg(rtsx_dev(chip), "Read format progress:\n");
- print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, ptr,
- cnt);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_set_rw_reg_addr(struct rtsx_chip *chip, u8 read_start,
- u8 read_cnt, u8 write_start, u8 write_cnt)
-{
- int retval, i;
- u8 data[4];
-
- data[0] = read_start;
- data[1] = read_cnt;
- data[2] = write_start;
- data[3] = write_cnt;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, SET_RW_REG_ADRS, 4,
- NO_WAIT_INT, data, 4);
- if (retval == STATUS_SUCCESS)
- return STATUS_SUCCESS;
- rtsx_clear_ms_error(chip);
- }
-
- return STATUS_FAIL;
-}
-
-static int ms_send_cmd(struct rtsx_chip *chip, u8 cmd, u8 cfg)
-{
- u8 data[2];
-
- data[0] = cmd;
- data[1] = 0;
-
- return ms_write_bytes(chip, PRO_SET_CMD, 1, cfg, data, 1);
-}
-
-static int ms_set_init_para(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
- if (CHK_HG8BIT(ms_card)) {
- if (chip->asic_code)
- ms_card->ms_clock = chip->asic_ms_hg_clk;
- else
- ms_card->ms_clock = chip->fpga_ms_hg_clk;
-
- } else if (CHK_MSPRO(ms_card) || CHK_MS4BIT(ms_card)) {
- if (chip->asic_code)
- ms_card->ms_clock = chip->asic_ms_4bit_clk;
- else
- ms_card->ms_clock = chip->fpga_ms_4bit_clk;
-
- } else {
- if (chip->asic_code)
- ms_card->ms_clock = chip->asic_ms_1bit_clk;
- else
- ms_card->ms_clock = chip->fpga_ms_1bit_clk;
- }
-
- retval = switch_clock(chip, ms_card->ms_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = select_card(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_switch_clock(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
- retval = select_card(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = switch_clock(chip, ms_card->ms_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_pull_ctl_disable(struct rtsx_chip *chip)
-{
- int retval;
-
- if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF,
- MS_D1_PD | MS_D2_PD | MS_CLK_PD |
- MS_D6_PD);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF,
- MS_D3_PD | MS_D0_PD | MS_BS_PD |
- XD_D4_PD);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF,
- MS_D7_PD | XD_CE_PD | XD_CLE_PD |
- XD_CD_PU);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD | SD_D3_PD | SD_D2_PD |
- XD_ALE_PD);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PD | SD_CD_PU |
- SD_CMD_PD);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- if (retval)
- return retval;
-
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1,
- 0xFF, 0x55);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL2,
- 0xFF, 0x55);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL3,
- 0xFF, 0x4B);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_PULL_CTL4,
- 0xFF, 0x69);
- if (retval)
- return retval;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_pull_ctl_enable(struct rtsx_chip *chip)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
- MS_D1_PD | MS_D2_PD | MS_CLK_NP | MS_D6_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
- MS_D3_PD | MS_D0_PD | MS_BS_NP | XD_D4_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
- MS_D7_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD | SD_D3_PD | SD_D2_PD | XD_ALE_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- CARD_PULL_CTL1, 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- CARD_PULL_CTL2, 0xFF, 0x45);
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- CARD_PULL_CTL3, 0xFF, 0x4B);
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- CARD_PULL_CTL4, 0xFF, 0x29);
- }
- }
-
- retval = rtsx_send_cmd(chip, MS_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_prepare_reset(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- u8 oc_mask = 0;
-
- ms_card->ms_type = 0;
- ms_card->check_ms_flow = 0;
- ms_card->switch_8bit_fail = 0;
- ms_card->delay_write.delay_write_flag = 0;
-
- ms_card->pro_under_formatting = 0;
-
- retval = ms_power_off_card3v3(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!chip->ft2_fast_mode)
- wait_timeout(250);
-
- retval = enable_card_clock(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (chip->asic_code) {
- retval = ms_pull_ctl_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- FPGA_MS_PULL_CTL_BIT | 0x20, 0);
- if (retval)
- return retval;
- }
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_on(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- wait_timeout(150);
-
-#ifdef SUPPORT_OCP
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- oc_mask = MS_OC_NOW | MS_OC_EVER;
- else
- oc_mask = SD_OC_NOW | SD_OC_EVER;
-
- if (chip->ocp_stat & oc_mask) {
- dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
- chip->ocp_stat);
- return STATUS_FAIL;
- }
-#endif
- }
-
- retval = rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN,
- MS_OUTPUT_EN);
- if (retval)
- return retval;
-
- if (chip->asic_code) {
- retval = rtsx_write_register(chip, MS_CFG, 0xFF,
- SAMPLE_TIME_RISING |
- PUSH_TIME_DEFAULT |
- NO_EXTEND_TOGGLE |
- MS_BUS_WIDTH_1);
- if (retval)
- return retval;
-
- } else {
- retval = rtsx_write_register(chip, MS_CFG, 0xFF,
- SAMPLE_TIME_FALLING |
- PUSH_TIME_DEFAULT |
- NO_EXTEND_TOGGLE |
- MS_BUS_WIDTH_1);
- if (retval)
- return retval;
- }
- retval = rtsx_write_register(chip, MS_TRANS_CFG, 0xFF,
- NO_WAIT_INT | NO_AUTO_READ_INT_REG);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
- MS_STOP | MS_CLR_ERR);
- if (retval)
- return retval;
-
- retval = ms_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_identify_media_type(struct rtsx_chip *chip, int switch_8bit_bus)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 val;
-
- retval = ms_set_rw_reg_addr(chip, PRO_STATUS_REG, 6, SYSTEM_PARAM, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, READ_REG,
- 6, NO_WAIT_INT);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, PPBUF_BASE2 + 2, &val);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "Type register: 0x%x\n", val);
- if (val != 0x01) {
- if (val != 0x02)
- ms_card->check_ms_flow = 1;
-
- return STATUS_FAIL;
- }
-
- retval = rtsx_read_register(chip, PPBUF_BASE2 + 4, &val);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "Category register: 0x%x\n", val);
- if (val != 0) {
- ms_card->check_ms_flow = 1;
- return STATUS_FAIL;
- }
-
- retval = rtsx_read_register(chip, PPBUF_BASE2 + 5, &val);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "Class register: 0x%x\n", val);
- if (val == 0) {
- retval = rtsx_read_register(chip, PPBUF_BASE2, &val);
- if (retval)
- return retval;
-
- if (val & WRT_PRTCT)
- chip->card_wp |= MS_CARD;
- else
- chip->card_wp &= ~MS_CARD;
-
- } else if ((val == 0x01) || (val == 0x02) || (val == 0x03)) {
- chip->card_wp |= MS_CARD;
- } else {
- ms_card->check_ms_flow = 1;
- return STATUS_FAIL;
- }
-
- ms_card->ms_type |= TYPE_MSPRO;
-
- retval = rtsx_read_register(chip, PPBUF_BASE2 + 3, &val);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "IF Mode register: 0x%x\n", val);
- if (val == 0) {
- ms_card->ms_type &= 0x0F;
- } else if (val == 7) {
- if (switch_8bit_bus)
- ms_card->ms_type |= MS_HG;
- else
- ms_card->ms_type &= 0x0F;
-
- } else {
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_confirm_cpu_startup(struct rtsx_chip *chip)
-{
- int retval, i, k;
- u8 val;
-
- /* Confirm CPU StartUp */
- k = 0;
- do {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_read_bytes(chip, GET_INT, 1,
- NO_WAIT_INT, &val, 1);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- if (k > 100)
- return STATUS_FAIL;
-
- k++;
- wait_timeout(100);
- } while (!(val & INT_REG_CED));
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- if (val & INT_REG_ERR) {
- if (val & INT_REG_CMDNK)
- chip->card_wp |= (MS_CARD);
- else
- return STATUS_FAIL;
- }
- /* -- end confirm CPU startup */
-
- return STATUS_SUCCESS;
-}
-
-static int ms_switch_parallel_bus(struct rtsx_chip *chip)
-{
- int retval, i;
- u8 data[2];
-
- data[0] = PARALLEL_4BIT_IF;
- data[1] = 0;
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, WRITE_REG, 1, NO_WAIT_INT,
- data, 2);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_switch_8bit_bus(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 data[2];
-
- data[0] = PARALLEL_8BIT_IF;
- data[1] = 0;
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, WRITE_REG, 1,
- NO_WAIT_INT, data, 2);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, MS_CFG, 0x98,
- MS_BUS_WIDTH_8 | SAMPLE_TIME_FALLING);
- if (retval)
- return retval;
-
- ms_card->ms_type |= MS_8BIT;
- retval = ms_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT,
- 1, NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_pro_reset_flow(struct rtsx_chip *chip, int switch_8bit_bus)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
-
- for (i = 0; i < 3; i++) {
- retval = ms_prepare_reset(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_identify_media_type(chip, switch_8bit_bus);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_confirm_cpu_startup(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_switch_parallel_bus(chip);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
- continue;
- } else {
- break;
- }
- }
-
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* Switch MS-PRO into Parallel mode */
- retval = rtsx_write_register(chip, MS_CFG, 0x18, MS_BUS_WIDTH_4);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, MS_CFG, PUSH_TIME_ODD,
- PUSH_TIME_ODD);
- if (retval)
- return retval;
-
- retval = ms_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* If MSPro HG Card, We shall try to switch to 8-bit bus */
- if (CHK_MSHG(ms_card) && chip->support_ms_8bit && switch_8bit_bus) {
- retval = ms_switch_8bit_bus(chip);
- if (retval != STATUS_SUCCESS) {
- ms_card->switch_8bit_fail = 1;
- return STATUS_FAIL;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-#ifdef XC_POWERCLASS
-static int msxc_change_power(struct rtsx_chip *chip, u8 mode)
-{
- int retval;
- u8 buf[6];
-
- ms_cleanup_work(chip);
-
- retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_DATA_COUNT1, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf[0] = 0;
- buf[1] = mode;
- buf[2] = 0;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = 0;
-
- retval = ms_write_bytes(chip, PRO_WRITE_REG, 6, NO_WAIT_INT, buf, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, XC_CHG_POWER, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, buf);
- if (retval)
- return retval;
-
- if (buf[0] & (MS_INT_CMDNK | MS_INT_ERR))
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-#endif
-
-static int ms_read_attribute_info(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 val, *buf, class_code, device_type, sub_class, data[16];
- u16 total_blk = 0, blk_size = 0;
-#ifdef SUPPORT_MSXC
- u32 xc_total_blk = 0, xc_blk_size = 0;
-#endif
- u32 sys_info_addr = 0, sys_info_size;
-#ifdef SUPPORT_PCGL_1P18
- u32 model_name_addr = 0, model_name_size;
- int found_sys_info = 0, found_model_name = 0;
-#endif
-
- retval = ms_set_rw_reg_addr(chip, PRO_INT_REG, 2, PRO_SYSTEM_PARAM, 7);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS8BIT(ms_card))
- data[0] = PARALLEL_8BIT_IF;
- else
- data[0] = PARALLEL_4BIT_IF;
-
- data[1] = 0;
-
- data[2] = 0x40;
- data[3] = 0;
- data[4] = 0;
- data[5] = 0;
- data[6] = 0;
- data[7] = 0;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, PRO_WRITE_REG, 7, NO_WAIT_INT,
- data, 8);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf = kmalloc(64 * 512, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_send_cmd(chip, PRO_READ_ATRB, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- continue;
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
- if (!(val & MS_INT_BREQ)) {
- kfree(buf);
- return STATUS_FAIL;
- }
- retval = ms_transfer_data(chip, MS_TM_AUTO_READ,
- PRO_READ_LONG_DATA, 0x40, WAIT_INT,
- 0, 0, buf, 64 * 512);
- if (retval == STATUS_SUCCESS)
- break;
-
- rtsx_clear_ms_error(chip);
- }
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- i = 0;
- do {
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- if ((val & MS_INT_CED) || !(val & MS_INT_BREQ))
- break;
-
- retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ,
- PRO_READ_LONG_DATA, 0, WAIT_INT);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- i++;
- } while (i < 1024);
-
- if (buf[0] != 0xa5 && buf[1] != 0xc3) {
- /* Signature code is wrong */
- kfree(buf);
- return STATUS_FAIL;
- }
-
- if (buf[4] < 1 || buf[4] > 12) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- for (i = 0; i < buf[4]; i++) {
- int cur_addr_off = 16 + i * 12;
-
-#ifdef SUPPORT_MSXC
- if (buf[cur_addr_off + 8] == 0x10 ||
- buf[cur_addr_off + 8] == 0x13) {
-#else
- if (buf[cur_addr_off + 8] == 0x10) {
-#endif
- sys_info_addr = ((u32)buf[cur_addr_off + 0] << 24) |
- ((u32)buf[cur_addr_off + 1] << 16) |
- ((u32)buf[cur_addr_off + 2] << 8) |
- buf[cur_addr_off + 3];
- sys_info_size = ((u32)buf[cur_addr_off + 4] << 24) |
- ((u32)buf[cur_addr_off + 5] << 16) |
- ((u32)buf[cur_addr_off + 6] << 8) |
- buf[cur_addr_off + 7];
- dev_dbg(rtsx_dev(chip), "sys_info_addr = 0x%x, sys_info_size = 0x%x\n",
- sys_info_addr, sys_info_size);
- if (sys_info_size != 96) {
- kfree(buf);
- return STATUS_FAIL;
- }
- if (sys_info_addr < 0x1A0) {
- kfree(buf);
- return STATUS_FAIL;
- }
- if ((sys_info_size + sys_info_addr) > 0x8000) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
-#ifdef SUPPORT_MSXC
- if (buf[cur_addr_off + 8] == 0x13)
- ms_card->ms_type |= MS_XC;
-#endif
-#ifdef SUPPORT_PCGL_1P18
- found_sys_info = 1;
-#else
- break;
-#endif
- }
-#ifdef SUPPORT_PCGL_1P18
- if (buf[cur_addr_off + 8] == 0x15) {
- model_name_addr = ((u32)buf[cur_addr_off + 0] << 24) |
- ((u32)buf[cur_addr_off + 1] << 16) |
- ((u32)buf[cur_addr_off + 2] << 8) |
- buf[cur_addr_off + 3];
- model_name_size = ((u32)buf[cur_addr_off + 4] << 24) |
- ((u32)buf[cur_addr_off + 5] << 16) |
- ((u32)buf[cur_addr_off + 6] << 8) |
- buf[cur_addr_off + 7];
- dev_dbg(rtsx_dev(chip), "model_name_addr = 0x%x, model_name_size = 0x%x\n",
- model_name_addr, model_name_size);
- if (model_name_size != 48) {
- kfree(buf);
- return STATUS_FAIL;
- }
- if (model_name_addr < 0x1A0) {
- kfree(buf);
- return STATUS_FAIL;
- }
- if ((model_name_size + model_name_addr) > 0x8000) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- found_model_name = 1;
- }
-
- if (found_sys_info && found_model_name)
- break;
-#endif
- }
-
- if (i == buf[4]) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- class_code = buf[sys_info_addr + 0];
- device_type = buf[sys_info_addr + 56];
- sub_class = buf[sys_info_addr + 46];
-#ifdef SUPPORT_MSXC
- if (CHK_MSXC(ms_card)) {
- xc_total_blk = ((u32)buf[sys_info_addr + 6] << 24) |
- ((u32)buf[sys_info_addr + 7] << 16) |
- ((u32)buf[sys_info_addr + 8] << 8) |
- buf[sys_info_addr + 9];
- xc_blk_size = ((u32)buf[sys_info_addr + 32] << 24) |
- ((u32)buf[sys_info_addr + 33] << 16) |
- ((u32)buf[sys_info_addr + 34] << 8) |
- buf[sys_info_addr + 35];
- dev_dbg(rtsx_dev(chip), "xc_total_blk = 0x%x, xc_blk_size = 0x%x\n",
- xc_total_blk, xc_blk_size);
- } else {
- total_blk = ((u16)buf[sys_info_addr + 6] << 8) |
- buf[sys_info_addr + 7];
- blk_size = ((u16)buf[sys_info_addr + 2] << 8) |
- buf[sys_info_addr + 3];
- dev_dbg(rtsx_dev(chip), "total_blk = 0x%x, blk_size = 0x%x\n",
- total_blk, blk_size);
- }
-#else
- total_blk = ((u16)buf[sys_info_addr + 6] << 8) | buf[sys_info_addr + 7];
- blk_size = ((u16)buf[sys_info_addr + 2] << 8) | buf[sys_info_addr + 3];
- dev_dbg(rtsx_dev(chip), "total_blk = 0x%x, blk_size = 0x%x\n",
- total_blk, blk_size);
-#endif
-
- dev_dbg(rtsx_dev(chip), "class_code = 0x%x, device_type = 0x%x, sub_class = 0x%x\n",
- class_code, device_type, sub_class);
-
- memcpy(ms_card->raw_sys_info, buf + sys_info_addr, 96);
-#ifdef SUPPORT_PCGL_1P18
- memcpy(ms_card->raw_model_name, buf + model_name_addr, 48);
-#endif
-
- kfree(buf);
-
-#ifdef SUPPORT_MSXC
- if (CHK_MSXC(ms_card)) {
- if (class_code != 0x03)
- return STATUS_FAIL;
- } else {
- if (class_code != 0x02)
- return STATUS_FAIL;
- }
-#else
- if (class_code != 0x02)
- return STATUS_FAIL;
-#endif
-
- if (device_type != 0x00) {
- if (device_type == 0x01 || device_type == 0x02 ||
- device_type == 0x03) {
- chip->card_wp |= MS_CARD;
- } else {
- return STATUS_FAIL;
- }
- }
-
- if (sub_class & 0xC0)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "class_code: 0x%x, device_type: 0x%x, sub_class: 0x%x\n",
- class_code, device_type, sub_class);
-
-#ifdef SUPPORT_MSXC
- if (CHK_MSXC(ms_card)) {
- chip->capacity[chip->card2lun[MS_CARD]] =
- ms_card->capacity = xc_total_blk * xc_blk_size;
- } else {
- chip->capacity[chip->card2lun[MS_CARD]] =
- ms_card->capacity = total_blk * blk_size;
- }
-#else
- ms_card->capacity = total_blk * blk_size;
- chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity;
-#endif
-
- return STATUS_SUCCESS;
-}
-
-#ifdef SUPPORT_MAGIC_GATE
-static int mg_set_tpc_para_sub(struct rtsx_chip *chip,
- int type, u8 mg_entry_num);
-#endif
-
-static int reset_ms_pro(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-#ifdef XC_POWERCLASS
- u8 change_power_class;
-
- if (chip->ms_power_class_en & 0x02)
- change_power_class = 2;
- else if (chip->ms_power_class_en & 0x01)
- change_power_class = 1;
- else
- change_power_class = 0;
-#endif
-
-#ifdef XC_POWERCLASS
-retry:
-#endif
- retval = ms_pro_reset_flow(chip, 1);
- if (retval != STATUS_SUCCESS) {
- if (ms_card->switch_8bit_fail) {
- retval = ms_pro_reset_flow(chip, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- return STATUS_FAIL;
- }
- }
-
- retval = ms_read_attribute_info(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
-#ifdef XC_POWERCLASS
- if (CHK_HG8BIT(ms_card))
- change_power_class = 0;
-
- if (change_power_class && CHK_MSXC(ms_card)) {
- u8 power_class_en = chip->ms_power_class_en;
-
- dev_dbg(rtsx_dev(chip), "power_class_en = 0x%x\n",
- power_class_en);
- dev_dbg(rtsx_dev(chip), "change_power_class = %d\n",
- change_power_class);
-
- if (change_power_class)
- power_class_en &= (1 << (change_power_class - 1));
- else
- power_class_en = 0;
-
- if (power_class_en) {
- u8 power_class_mode =
- (ms_card->raw_sys_info[46] & 0x18) >> 3;
- dev_dbg(rtsx_dev(chip), "power_class_mode = 0x%x",
- power_class_mode);
- if (change_power_class > power_class_mode)
- change_power_class = power_class_mode;
- if (change_power_class) {
- retval = msxc_change_power(chip,
- change_power_class);
- if (retval != STATUS_SUCCESS) {
- change_power_class--;
- goto retry;
- }
- }
- }
- }
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
- retval = mg_set_tpc_para_sub(chip, 0, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-#endif
-
- if (CHK_HG8BIT(ms_card))
- chip->card_bus_width[chip->card2lun[MS_CARD]] = 8;
- else
- chip->card_bus_width[chip->card2lun[MS_CARD]] = 4;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_read_status_reg(struct rtsx_chip *chip)
-{
- int retval;
- u8 val[2];
-
- retval = ms_set_rw_reg_addr(chip, STATUS_REG0, 2, 0, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_read_bytes(chip, READ_REG, 2, NO_WAIT_INT, val, 2);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val[1] & (STS_UCDT | STS_UCEX | STS_UCFG)) {
- ms_set_err_code(chip, MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_read_extra_data(struct rtsx_chip *chip,
- u16 block_addr, u8 page_num, u8 *buf, int buf_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 val, data[10];
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS4BIT(ms_card)) {
- /* Parallel interface */
- data[0] = 0x88;
- } else {
- /* Serial interface */
- data[0] = 0x80;
- }
- data[1] = 0;
- data[2] = (u8)(block_addr >> 8);
- data[3] = (u8)block_addr;
- data[4] = 0x40;
- data[5] = page_num;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT,
- data, 6);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG,
- MS_EXTRA_SIZE, SYSTEM_PARAM,
- 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- }
-
- retval = ms_read_bytes(chip, READ_REG, MS_EXTRA_SIZE, NO_WAIT_INT,
- data, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (buf && buf_len) {
- if (buf_len > MS_EXTRA_SIZE)
- buf_len = MS_EXTRA_SIZE;
- memcpy(buf, data, buf_len);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_write_extra_data(struct rtsx_chip *chip, u16 block_addr,
- u8 page_num, u8 *buf, int buf_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 val, data[16];
-
- if (!buf || buf_len < MS_EXTRA_SIZE)
- return STATUS_FAIL;
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 6 + MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(block_addr >> 8);
- data[3] = (u8)block_addr;
- data[4] = 0x40;
- data[5] = page_num;
-
- for (i = 6; i < MS_EXTRA_SIZE + 6; i++)
- data[i] = buf[i - 6];
-
- retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE),
- NO_WAIT_INT, data, 16);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_read_page(struct rtsx_chip *chip, u16 block_addr, u8 page_num)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- u8 val, data[6];
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(block_addr >> 8);
- data[3] = (u8)block_addr;
- data[4] = 0x20;
- data[5] = page_num;
-
- retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- if (!(val & INT_REG_BREQ)) {
- ms_set_err_code(chip, MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS)
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
-
- } else {
- if (!(val & INT_REG_BREQ)) {
- ms_set_err_code(chip, MS_BREQ_ERROR);
- return STATUS_FAIL;
- }
- }
- }
-
- retval = ms_transfer_tpc(chip, MS_TM_NORMAL_READ, READ_PAGE_DATA,
- 0, NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR))
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_set_bad_block(struct rtsx_chip *chip, u16 phy_blk)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- u8 val, data[8], extra[MS_EXTRA_SIZE];
-
- retval = ms_read_extra_data(chip, phy_blk, 0, extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 7);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(phy_blk >> 8);
- data[3] = (u8)phy_blk;
- data[4] = 0x80;
- data[5] = 0;
- data[6] = extra[0] & 0x7F;
- data[7] = 0xFF;
-
- retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT, data, 7);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_erase_block(struct rtsx_chip *chip, u16 phy_blk)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i = 0;
- u8 val, data[6];
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(phy_blk >> 8);
- data[3] = (u8)phy_blk;
- data[4] = 0;
- data[5] = 0;
-
- retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT, data, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
-ERASE_RTY:
- retval = ms_send_cmd(chip, BLOCK_ERASE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- if (i < 3) {
- i++;
- goto ERASE_RTY;
- }
-
- ms_set_err_code(chip, MS_CMD_NK);
- ms_set_bad_block(chip, phy_blk);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static void ms_set_page_status(u16 log_blk, u8 type, u8 *extra, int extra_len)
-{
- if (!extra || extra_len < MS_EXTRA_SIZE)
- return;
-
- memset(extra, 0xFF, MS_EXTRA_SIZE);
-
- if (type == set_PS_NG) {
- /* set page status as 1:NG,and block status keep 1:OK */
- extra[0] = 0xB8;
- } else {
- /* set page status as 0:Data Error,and block status keep 1:OK */
- extra[0] = 0x98;
- }
-
- extra[2] = (u8)(log_blk >> 8);
- extra[3] = (u8)log_blk;
-}
-
-static int ms_init_page(struct rtsx_chip *chip, u16 phy_blk, u16 log_blk,
- u8 start_page, u8 end_page)
-{
- int retval;
- u8 extra[MS_EXTRA_SIZE], i;
-
- memset(extra, 0xff, MS_EXTRA_SIZE);
-
- extra[0] = 0xf8; /* Block, page OK, data erased */
- extra[1] = 0xff;
- extra[2] = (u8)(log_blk >> 8);
- extra[3] = (u8)log_blk;
-
- for (i = start_page; i < end_page; i++) {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = ms_write_extra_data(chip, phy_blk, i,
- extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_copy_page(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
- u16 log_blk, u8 start_page, u8 end_page)
-{
- struct ms_info *ms_card = &chip->ms_card;
- bool uncorrect_flag = false;
- int retval, rty_cnt;
- u8 extra[MS_EXTRA_SIZE], val, i, j, data[16];
-
- dev_dbg(rtsx_dev(chip), "Copy page from 0x%x to 0x%x, logical block is 0x%x\n",
- old_blk, new_blk, log_blk);
- dev_dbg(rtsx_dev(chip), "start_page = %d, end_page = %d\n",
- start_page, end_page);
-
- retval = ms_read_extra_data(chip, new_blk, 0, extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, PPBUF_BASE2, &val);
- if (retval)
- return retval;
-
- if (val & BUF_FULL) {
- retval = ms_send_cmd(chip, CLEAR_BUF, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!(val & INT_REG_CED)) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
-
- for (i = start_page; i < end_page; i++) {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = ms_read_extra_data(chip, old_blk, i, extra,
- MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG,
- MS_EXTRA_SIZE, SYSTEM_PARAM, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(old_blk >> 8);
- data[3] = (u8)old_blk;
- data[4] = 0x20;
- data[5] = i;
-
- retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT,
- data, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS) {
- uncorrect_flag = true;
- dev_dbg(rtsx_dev(chip), "Uncorrectable error\n");
- } else {
- uncorrect_flag = false;
- }
-
- retval = ms_transfer_tpc(chip,
- MS_TM_NORMAL_READ,
- READ_PAGE_DATA,
- 0, NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (uncorrect_flag) {
- ms_set_page_status(log_blk, set_PS_NG,
- extra,
- MS_EXTRA_SIZE);
- if (i == 0)
- extra[0] &= 0xEF;
-
- ms_write_extra_data(chip, old_blk, i,
- extra,
- MS_EXTRA_SIZE);
- dev_dbg(rtsx_dev(chip), "page %d : extra[0] = 0x%x\n",
- i, extra[0]);
- MS_SET_BAD_BLOCK_FLG(ms_card);
-
- ms_set_page_status(log_blk,
- set_PS_error, extra,
- MS_EXTRA_SIZE);
- ms_write_extra_data(chip, new_blk, i,
- extra,
- MS_EXTRA_SIZE);
- continue;
- }
-
- for (rty_cnt = 0; rty_cnt < MS_MAX_RETRY_COUNT;
- rty_cnt++) {
- retval = ms_transfer_tpc(chip,
- MS_TM_NORMAL_WRITE,
- WRITE_PAGE_DATA,
- 0, NO_WAIT_INT);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (rty_cnt == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
- }
-
- if (!(val & INT_REG_BREQ)) {
- ms_set_err_code(chip, MS_BREQ_ERROR);
- return STATUS_FAIL;
- }
- }
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, (6 + MS_EXTRA_SIZE));
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(new_blk >> 8);
- data[3] = (u8)new_blk;
- data[4] = 0x20;
- data[5] = i;
-
- if ((extra[0] & 0x60) != 0x60)
- data[6] = extra[0];
- else
- data[6] = 0xF8;
-
- data[6 + 1] = 0xFF;
- data[6 + 2] = (u8)(log_blk >> 8);
- data[6 + 3] = (u8)log_blk;
-
- for (j = 4; j <= MS_EXTRA_SIZE; j++)
- data[6 + j] = 0xFF;
-
- retval = ms_write_bytes(chip, WRITE_REG, (6 + MS_EXTRA_SIZE),
- NO_WAIT_INT, data, 16);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
-
- if (i == 0) {
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG,
- MS_EXTRA_SIZE, SYSTEM_PARAM,
- 7);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(old_blk >> 8);
- data[3] = (u8)old_blk;
- data[4] = 0x80;
- data[5] = 0;
- data[6] = 0xEF;
- data[7] = 0xFF;
-
- retval = ms_write_bytes(chip, WRITE_REG, 7,
- NO_WAIT_INT, data, 8);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_read_bytes(chip, GET_INT, 1,
- NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CED) {
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip,
- MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int reset_ms(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- u16 i, reg_addr, block_size;
- u8 val, extra[MS_EXTRA_SIZE], j, *ptr;
-#ifndef SUPPORT_MAGIC_GATE
- u16 eblock_cnt;
-#endif
-
- retval = ms_prepare_reset(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_card->ms_type |= TYPE_MS;
-
- retval = ms_send_cmd(chip, MS_RESET, NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, PPBUF_BASE2, &val);
- if (retval)
- return retval;
-
- if (val & WRT_PRTCT)
- chip->card_wp |= MS_CARD;
- else
- chip->card_wp &= ~MS_CARD;
-
- i = 0;
-
-RE_SEARCH:
- /* Search Boot Block */
- while (i < (MAX_DEFECTIVE_BLOCK + 2)) {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = ms_read_extra_data(chip, i, 0, extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS) {
- i++;
- continue;
- }
-
- if (extra[0] & BLOCK_OK) {
- if (!(extra[1] & NOT_BOOT_BLOCK)) {
- ms_card->boot_block = i;
- break;
- }
- }
- i++;
- }
-
- if (i == (MAX_DEFECTIVE_BLOCK + 2)) {
- dev_dbg(rtsx_dev(chip), "No boot block found!");
- return STATUS_FAIL;
- }
-
- for (j = 0; j < 3; j++) {
- retval = ms_read_page(chip, ms_card->boot_block, j);
- if (retval != STATUS_SUCCESS) {
- if (ms_check_err_code(chip, MS_FLASH_WRITE_ERROR)) {
- i = ms_card->boot_block + 1;
- ms_set_err_code(chip, MS_NO_ERROR);
- goto RE_SEARCH;
- }
- }
- }
-
- retval = ms_read_page(chip, ms_card->boot_block, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* Read MS system information as sys_info */
- rtsx_init_cmd(chip);
-
- for (i = 0; i < 96; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 0x1A0 + i, 0, 0);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- ptr = rtsx_get_cmd_data(chip);
- memcpy(ms_card->raw_sys_info, ptr, 96);
-
- /* Read useful block contents */
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID0, 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, HEADER_ID1, 0, 0);
-
- for (reg_addr = DISABLED_BLOCK0; reg_addr <= DISABLED_BLOCK3;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- for (reg_addr = BLOCK_SIZE_0; reg_addr <= PAGE_SIZE_1; reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- rtsx_add_cmd(chip, READ_REG_CMD, MS_device_type, 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, MS_4bit_support, 0, 0);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- ptr = rtsx_get_cmd_data(chip);
-
- dev_dbg(rtsx_dev(chip), "Boot block data:\n");
- dev_dbg(rtsx_dev(chip), "%*ph\n", 16, ptr);
-
- /* Block ID error
- * HEADER_ID0, HEADER_ID1
- */
- if (ptr[0] != 0x00 || ptr[1] != 0x01) {
- i = ms_card->boot_block + 1;
- goto RE_SEARCH;
- }
-
- /* Page size error
- * PAGE_SIZE_0, PAGE_SIZE_1
- */
- if (ptr[12] != 0x02 || ptr[13] != 0x00) {
- i = ms_card->boot_block + 1;
- goto RE_SEARCH;
- }
-
- if (ptr[14] == 1 || ptr[14] == 3)
- chip->card_wp |= MS_CARD;
-
- /* BLOCK_SIZE_0, BLOCK_SIZE_1 */
- block_size = ((u16)ptr[6] << 8) | ptr[7];
- if (block_size == 0x0010) {
- /* Block size 16KB */
- ms_card->block_shift = 5;
- ms_card->page_off = 0x1F;
- } else if (block_size == 0x0008) {
- /* Block size 8KB */
- ms_card->block_shift = 4;
- ms_card->page_off = 0x0F;
- }
-
- /* BLOCK_COUNT_0, BLOCK_COUNT_1 */
- ms_card->total_block = ((u16)ptr[8] << 8) | ptr[9];
-
-#ifdef SUPPORT_MAGIC_GATE
- j = ptr[10];
-
- if (ms_card->block_shift == 4) { /* 4MB or 8MB */
- if (j < 2) { /* Effective block for 4MB: 0x1F0 */
- ms_card->capacity = 0x1EE0;
- } else { /* Effective block for 8MB: 0x3E0 */
- ms_card->capacity = 0x3DE0;
- }
- } else { /* 16MB, 32MB, 64MB or 128MB */
- if (j < 5) { /* Effective block for 16MB: 0x3E0 */
- ms_card->capacity = 0x7BC0;
- } else if (j < 0xA) { /* Effective block for 32MB: 0x7C0 */
- ms_card->capacity = 0xF7C0;
- } else if (j < 0x11) { /* Effective block for 64MB: 0xF80 */
- ms_card->capacity = 0x1EF80;
- } else { /* Effective block for 128MB: 0x1F00 */
- ms_card->capacity = 0x3DF00;
- }
- }
-#else
- /* EBLOCK_COUNT_0, EBLOCK_COUNT_1 */
- eblock_cnt = ((u16)ptr[10] << 8) | ptr[11];
-
- ms_card->capacity = ((u32)eblock_cnt - 2) << ms_card->block_shift;
-#endif
-
- chip->capacity[chip->card2lun[MS_CARD]] = ms_card->capacity;
-
- /* Switch I/F Mode */
- if (ptr[15]) {
- retval = ms_set_rw_reg_addr(chip, 0, 0, SYSTEM_PARAM, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, PPBUF_BASE2, 0xFF, 0x88);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, PPBUF_BASE2 + 1, 0xFF, 0);
- if (retval)
- return retval;
-
- retval = ms_transfer_tpc(chip, MS_TM_WRITE_BYTES, WRITE_REG, 1,
- NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, MS_CFG,
- 0x58 | MS_NO_CHECK_INT,
- MS_BUS_WIDTH_4 |
- PUSH_TIME_ODD |
- MS_NO_CHECK_INT);
- if (retval)
- return retval;
-
- ms_card->ms_type |= MS_4BIT;
- }
-
- if (CHK_MS4BIT(ms_card))
- chip->card_bus_width[chip->card2lun[MS_CARD]] = 4;
- else
- chip->card_bus_width[chip->card2lun[MS_CARD]] = 1;
-
- return STATUS_SUCCESS;
-}
-
-static int ms_init_l2p_tbl(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int size, i, seg_no, retval;
- u16 defect_block, reg_addr;
- u8 val1, val2;
-
- ms_card->segment_cnt = ms_card->total_block >> 9;
- dev_dbg(rtsx_dev(chip), "ms_card->segment_cnt = %d\n",
- ms_card->segment_cnt);
-
- size = ms_card->segment_cnt * sizeof(struct zone_entry);
- ms_card->segment = vzalloc(size);
- if (!ms_card->segment)
- return STATUS_FAIL;
-
- retval = ms_read_page(chip, ms_card->boot_block, 1);
- if (retval != STATUS_SUCCESS)
- goto INIT_FAIL;
-
- reg_addr = PPBUF_BASE2;
- for (i = 0; i < (((ms_card->total_block >> 9) * 10) + 1); i++) {
- int block_no;
-
- retval = rtsx_read_register(chip, reg_addr++, &val1);
- if (retval != STATUS_SUCCESS)
- goto INIT_FAIL;
-
- retval = rtsx_read_register(chip, reg_addr++, &val2);
- if (retval != STATUS_SUCCESS)
- goto INIT_FAIL;
-
- defect_block = ((u16)val1 << 8) | val2;
- if (defect_block == 0xFFFF)
- break;
-
- seg_no = defect_block / 512;
-
- block_no = ms_card->segment[seg_no].disable_count++;
- ms_card->segment[seg_no].defect_list[block_no] = defect_block;
- }
-
- for (i = 0; i < ms_card->segment_cnt; i++) {
- ms_card->segment[i].build_flag = 0;
- ms_card->segment[i].l2p_table = NULL;
- ms_card->segment[i].free_table = NULL;
- ms_card->segment[i].get_index = 0;
- ms_card->segment[i].set_index = 0;
- ms_card->segment[i].unused_blk_cnt = 0;
-
- dev_dbg(rtsx_dev(chip), "defective block count of segment %d is %d\n",
- i, ms_card->segment[i].disable_count);
- }
-
- return STATUS_SUCCESS;
-
-INIT_FAIL:
- vfree(ms_card->segment);
- ms_card->segment = NULL;
-
- return STATUS_FAIL;
-}
-
-static u16 ms_get_l2p_tbl(struct rtsx_chip *chip, int seg_no, u16 log_off)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
-
- if (!ms_card->segment)
- return 0xFFFF;
-
- segment = &ms_card->segment[seg_no];
-
- if (segment->l2p_table)
- return segment->l2p_table[log_off];
-
- return 0xFFFF;
-}
-
-static void ms_set_l2p_tbl(struct rtsx_chip *chip,
- int seg_no, u16 log_off, u16 phy_blk)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
-
- if (!ms_card->segment)
- return;
-
- segment = &ms_card->segment[seg_no];
- if (segment->l2p_table)
- segment->l2p_table[log_off] = phy_blk;
-}
-
-static void ms_set_unused_block(struct rtsx_chip *chip, u16 phy_blk)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
- int seg_no;
-
- seg_no = (int)phy_blk >> 9;
- segment = &ms_card->segment[seg_no];
-
- segment->free_table[segment->set_index++] = phy_blk;
- if (segment->set_index >= MS_FREE_TABLE_CNT)
- segment->set_index = 0;
-
- segment->unused_blk_cnt++;
-}
-
-static u16 ms_get_unused_block(struct rtsx_chip *chip, int seg_no)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
- u16 phy_blk;
-
- segment = &ms_card->segment[seg_no];
-
- if (segment->unused_blk_cnt <= 0)
- return 0xFFFF;
-
- phy_blk = segment->free_table[segment->get_index];
- segment->free_table[segment->get_index++] = 0xFFFF;
- if (segment->get_index >= MS_FREE_TABLE_CNT)
- segment->get_index = 0;
-
- segment->unused_blk_cnt--;
-
- return phy_blk;
-}
-
-static const unsigned short ms_start_idx[] = {0, 494, 990, 1486, 1982, 2478,
- 2974, 3470, 3966, 4462, 4958,
- 5454, 5950, 6446, 6942, 7438,
- 7934};
-
-static int ms_arbitrate_l2p(struct rtsx_chip *chip, u16 phy_blk,
- u16 log_off, u8 us1, u8 us2)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
- int seg_no;
- u16 tmp_blk;
-
- seg_no = (int)phy_blk >> 9;
- segment = &ms_card->segment[seg_no];
- tmp_blk = segment->l2p_table[log_off];
-
- if (us1 != us2) {
- if (us1 == 0) {
- if (!(chip->card_wp & MS_CARD))
- ms_erase_block(chip, tmp_blk);
-
- ms_set_unused_block(chip, tmp_blk);
- segment->l2p_table[log_off] = phy_blk;
- } else {
- if (!(chip->card_wp & MS_CARD))
- ms_erase_block(chip, phy_blk);
-
- ms_set_unused_block(chip, phy_blk);
- }
- } else {
- if (phy_blk < tmp_blk) {
- if (!(chip->card_wp & MS_CARD))
- ms_erase_block(chip, phy_blk);
-
- ms_set_unused_block(chip, phy_blk);
- } else {
- if (!(chip->card_wp & MS_CARD))
- ms_erase_block(chip, tmp_blk);
-
- ms_set_unused_block(chip, tmp_blk);
- segment->l2p_table[log_off] = phy_blk;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_build_l2p_tbl(struct rtsx_chip *chip, int seg_no)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct zone_entry *segment;
- bool defect_flag;
- int retval, table_size, disable_cnt, i;
- u16 start, end, phy_blk, log_blk, tmp_blk, idx;
- u8 extra[MS_EXTRA_SIZE], us1, us2;
-
- dev_dbg(rtsx_dev(chip), "%s: %d\n", __func__, seg_no);
-
- if (!ms_card->segment) {
- retval = ms_init_l2p_tbl(chip);
- if (retval != STATUS_SUCCESS)
- return retval;
- }
-
- if (ms_card->segment[seg_no].build_flag) {
- dev_dbg(rtsx_dev(chip), "l2p table of segment %d has been built\n",
- seg_no);
- return STATUS_SUCCESS;
- }
-
- if (seg_no == 0)
- table_size = 494;
- else
- table_size = 496;
-
- segment = &ms_card->segment[seg_no];
-
- if (!segment->l2p_table) {
- segment->l2p_table = vmalloc(array_size(table_size, 2));
- if (!segment->l2p_table)
- goto BUILD_FAIL;
- }
- memset((u8 *)(segment->l2p_table), 0xff, array_size(table_size, 2));
-
- if (!segment->free_table) {
- segment->free_table = vmalloc(array_size(MS_FREE_TABLE_CNT, 2));
- if (!segment->free_table)
- goto BUILD_FAIL;
- }
- memset((u8 *)(segment->free_table), 0xff, array_size(MS_FREE_TABLE_CNT, 2));
-
- start = (u16)seg_no << 9;
- end = (u16)(seg_no + 1) << 9;
-
- disable_cnt = segment->disable_count;
-
- segment->get_index = 0;
- segment->set_index = 0;
- segment->unused_blk_cnt = 0;
-
- for (phy_blk = start; phy_blk < end; phy_blk++) {
- if (disable_cnt) {
- defect_flag = false;
- for (i = 0; i < segment->disable_count; i++) {
- if (phy_blk == segment->defect_list[i]) {
- defect_flag = true;
- break;
- }
- }
- if (defect_flag) {
- disable_cnt--;
- continue;
- }
- }
-
- retval = ms_read_extra_data(chip, phy_blk, 0,
- extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS) {
- dev_dbg(rtsx_dev(chip), "read extra data fail\n");
- ms_set_bad_block(chip, phy_blk);
- continue;
- }
-
- if (seg_no == ms_card->segment_cnt - 1) {
- if (!(extra[1] & NOT_TRANSLATION_TABLE)) {
- if (!(chip->card_wp & MS_CARD)) {
- retval = ms_erase_block(chip, phy_blk);
- if (retval != STATUS_SUCCESS)
- continue;
- extra[2] = 0xff;
- extra[3] = 0xff;
- }
- }
- }
-
- if (!(extra[0] & BLOCK_OK))
- continue;
- if (!(extra[1] & NOT_BOOT_BLOCK))
- continue;
- if ((extra[0] & PAGE_OK) != PAGE_OK)
- continue;
-
- log_blk = ((u16)extra[2] << 8) | extra[3];
-
- if (log_blk == 0xFFFF) {
- if (!(chip->card_wp & MS_CARD)) {
- retval = ms_erase_block(chip, phy_blk);
- if (retval != STATUS_SUCCESS)
- continue;
- }
- ms_set_unused_block(chip, phy_blk);
- continue;
- }
-
- if (log_blk < ms_start_idx[seg_no] ||
- log_blk >= ms_start_idx[seg_no + 1]) {
- if (!(chip->card_wp & MS_CARD)) {
- retval = ms_erase_block(chip, phy_blk);
- if (retval != STATUS_SUCCESS)
- continue;
- }
- ms_set_unused_block(chip, phy_blk);
- continue;
- }
-
- idx = log_blk - ms_start_idx[seg_no];
-
- if (segment->l2p_table[idx] == 0xFFFF) {
- segment->l2p_table[idx] = phy_blk;
- continue;
- }
-
- us1 = extra[0] & 0x10;
- tmp_blk = segment->l2p_table[idx];
- retval = ms_read_extra_data(chip, tmp_blk, 0,
- extra, MS_EXTRA_SIZE);
- if (retval != STATUS_SUCCESS)
- continue;
- us2 = extra[0] & 0x10;
-
- (void)ms_arbitrate_l2p(chip, phy_blk,
- log_blk - ms_start_idx[seg_no], us1, us2);
- }
-
- segment->build_flag = 1;
-
- dev_dbg(rtsx_dev(chip), "unused block count: %d\n",
- segment->unused_blk_cnt);
-
- /* Logical Address Confirmation Process */
- if (seg_no == ms_card->segment_cnt - 1) {
- if (segment->unused_blk_cnt < 2)
- chip->card_wp |= MS_CARD;
- } else {
- if (segment->unused_blk_cnt < 1)
- chip->card_wp |= MS_CARD;
- }
-
- if (chip->card_wp & MS_CARD)
- return STATUS_SUCCESS;
-
- for (log_blk = ms_start_idx[seg_no];
- log_blk < ms_start_idx[seg_no + 1]; log_blk++) {
- idx = log_blk - ms_start_idx[seg_no];
- if (segment->l2p_table[idx] == 0xFFFF) {
- phy_blk = ms_get_unused_block(chip, seg_no);
- if (phy_blk == 0xFFFF) {
- chip->card_wp |= MS_CARD;
- return STATUS_SUCCESS;
- }
- retval = ms_init_page(chip, phy_blk, log_blk, 0, 1);
- if (retval != STATUS_SUCCESS)
- goto BUILD_FAIL;
-
- segment->l2p_table[idx] = phy_blk;
- if (seg_no == ms_card->segment_cnt - 1) {
- if (segment->unused_blk_cnt < 2) {
- chip->card_wp |= MS_CARD;
- return STATUS_SUCCESS;
- }
- } else {
- if (segment->unused_blk_cnt < 1) {
- chip->card_wp |= MS_CARD;
- return STATUS_SUCCESS;
- }
- }
- }
- }
-
- /* Make boot block be the first normal block */
- if (seg_no == 0) {
- for (log_blk = 0; log_blk < 494; log_blk++) {
- tmp_blk = segment->l2p_table[log_blk];
- if (tmp_blk < ms_card->boot_block) {
- dev_dbg(rtsx_dev(chip), "Boot block is not the first normal block.\n");
-
- if (chip->card_wp & MS_CARD)
- break;
-
- phy_blk = ms_get_unused_block(chip, 0);
- retval = ms_copy_page(chip, tmp_blk, phy_blk,
- log_blk, 0,
- ms_card->page_off + 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- segment->l2p_table[log_blk] = phy_blk;
-
- retval = ms_set_bad_block(chip, tmp_blk);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- }
- }
-
- return STATUS_SUCCESS;
-
-BUILD_FAIL:
- segment->build_flag = 0;
- vfree(segment->l2p_table);
- segment->l2p_table = NULL;
- vfree(segment->free_table);
- segment->free_table = NULL;
-
- return STATUS_FAIL;
-}
-
-int reset_ms_card(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int seg_no = ms_card->total_block / 512 - 1;
- int retval;
-
- memset(ms_card, 0, sizeof(struct ms_info));
-
- retval = enable_card_clock(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = select_card(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_card->ms_type = 0;
-
- retval = reset_ms_pro(chip);
- if (retval != STATUS_SUCCESS) {
- if (ms_card->check_ms_flow) {
- retval = reset_ms(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- return STATUS_FAIL;
- }
- }
-
- retval = ms_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!CHK_MSPRO(ms_card)) {
- /* Build table for the last segment,
- * to check if L2P table block exists, erasing it
- */
- retval = ms_build_l2p_tbl(chip, seg_no);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- dev_dbg(rtsx_dev(chip), "ms_card->ms_type = 0x%x\n", ms_card->ms_type);
-
- return STATUS_SUCCESS;
-}
-
-static int mspro_set_rw_cmd(struct rtsx_chip *chip,
- u32 start_sec, u16 sec_cnt, u8 cmd)
-{
- int retval, i;
- u8 data[8];
-
- data[0] = cmd;
- data[1] = (u8)(sec_cnt >> 8);
- data[2] = (u8)sec_cnt;
- data[3] = (u8)(start_sec >> 24);
- data[4] = (u8)(start_sec >> 16);
- data[5] = (u8)(start_sec >> 8);
- data[6] = (u8)start_sec;
- data[7] = 0;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7,
- WAIT_INT, data, 8);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-void mspro_stop_seq_mode(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
- if (ms_card->seq_mode) {
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return;
-
- ms_card->seq_mode = 0;
- ms_card->total_sec_cnt = 0;
- ms_send_cmd(chip, PRO_STOP, WAIT_INT);
-
- rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
- }
-}
-
-static inline int ms_auto_tune_clock(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
- if (chip->asic_code) {
- if (ms_card->ms_clock > 30)
- ms_card->ms_clock -= 20;
- } else {
- if (ms_card->ms_clock == CLK_80)
- ms_card->ms_clock = CLK_60;
- else if (ms_card->ms_clock == CLK_60)
- ms_card->ms_clock = CLK_40;
- }
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int mspro_rw_multi_sector(struct scsi_cmnd *srb,
- struct rtsx_chip *chip, u32 start_sector,
- u16 sector_cnt)
-{
- struct ms_info *ms_card = &chip->ms_card;
- bool mode_2k = false;
- int retval;
- u16 count;
- u8 val, trans_mode, rw_tpc, rw_cmd;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- ms_card->cleanup_counter = 0;
-
- if (CHK_MSHG(ms_card)) {
- if ((start_sector % 4) || (sector_cnt % 4)) {
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- rw_tpc = PRO_READ_LONG_DATA;
- rw_cmd = PRO_READ_DATA;
- } else {
- rw_tpc = PRO_WRITE_LONG_DATA;
- rw_cmd = PRO_WRITE_DATA;
- }
- } else {
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- rw_tpc = PRO_READ_QUAD_DATA;
- rw_cmd = PRO_READ_2K_DATA;
- } else {
- rw_tpc = PRO_WRITE_QUAD_DATA;
- rw_cmd = PRO_WRITE_2K_DATA;
- }
- mode_2k = true;
- }
- } else {
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- rw_tpc = PRO_READ_LONG_DATA;
- rw_cmd = PRO_READ_DATA;
- } else {
- rw_tpc = PRO_WRITE_LONG_DATA;
- rw_cmd = PRO_WRITE_DATA;
- }
- }
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- trans_mode = MS_TM_AUTO_READ;
- else
- trans_mode = MS_TM_AUTO_WRITE;
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval)
- return retval;
-
- if (ms_card->seq_mode) {
- if (ms_card->pre_dir != srb->sc_data_direction ||
- ((ms_card->pre_sec_addr + ms_card->pre_sec_cnt) !=
- start_sector) ||
- (mode_2k && (ms_card->seq_mode & MODE_512_SEQ)) ||
- (!mode_2k && (ms_card->seq_mode & MODE_2K_SEQ)) ||
- !(val & MS_INT_BREQ) ||
- ((ms_card->total_sec_cnt + sector_cnt) > 0xFE00)) {
- ms_card->seq_mode = 0;
- ms_card->total_sec_cnt = 0;
- if (val & MS_INT_BREQ) {
- retval = ms_send_cmd(chip, PRO_STOP, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_write_register(chip, RBCTL, RB_FLUSH,
- RB_FLUSH);
- }
- }
- }
-
- if (!ms_card->seq_mode) {
- ms_card->total_sec_cnt = 0;
- if (sector_cnt >= SEQ_START_CRITERIA) {
- if ((ms_card->capacity - start_sector) > 0xFE00)
- count = 0xFE00;
- else
- count = (u16)(ms_card->capacity - start_sector);
-
- if (count > sector_cnt) {
- if (mode_2k)
- ms_card->seq_mode = MODE_2K_SEQ;
- else
- ms_card->seq_mode = MODE_512_SEQ;
- }
- } else {
- count = sector_cnt;
- }
- retval = mspro_set_rw_cmd(chip, start_sector, count, rw_cmd);
- if (retval != STATUS_SUCCESS) {
- ms_card->seq_mode = 0;
- return STATUS_FAIL;
- }
- }
-
- retval = ms_transfer_data(chip, trans_mode, rw_tpc, sector_cnt,
- WAIT_INT, mode_2k, scsi_sg_count(srb),
- scsi_sglist(srb), scsi_bufflen(srb));
- if (retval != STATUS_SUCCESS) {
- ms_card->seq_mode = 0;
- rtsx_read_register(chip, MS_TRANS_CFG, &val);
- rtsx_clear_ms_error(chip);
-
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- chip->rw_need_retry = 0;
- dev_dbg(rtsx_dev(chip), "No card exist, exit %s\n",
- __func__);
- return STATUS_FAIL;
- }
-
- if (val & MS_INT_BREQ)
- ms_send_cmd(chip, PRO_STOP, WAIT_INT);
-
- if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
- dev_dbg(rtsx_dev(chip), "MSPro CRC error, tune clock!\n");
- chip->rw_need_retry = 1;
- ms_auto_tune_clock(chip);
- }
-
- return retval;
- }
-
- if (ms_card->seq_mode) {
- ms_card->pre_sec_addr = start_sector;
- ms_card->pre_sec_cnt = sector_cnt;
- ms_card->pre_dir = srb->sc_data_direction;
- ms_card->total_sec_cnt += sector_cnt;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int mspro_read_format_progress(struct rtsx_chip *chip,
- const int short_data_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u32 total_progress, cur_progress;
- u8 cnt, tmp;
- u8 data[8];
-
- dev_dbg(rtsx_dev(chip), "%s, short_data_len = %d\n", __func__,
- short_data_len);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- if (!(tmp & MS_INT_BREQ)) {
- if ((tmp & (MS_INT_CED | MS_INT_BREQ | MS_INT_CMDNK |
- MS_INT_ERR)) == MS_INT_CED) {
- ms_card->format_status = FORMAT_SUCCESS;
- return STATUS_SUCCESS;
- }
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- if (short_data_len >= 256)
- cnt = 0;
- else
- cnt = (u8)short_data_len;
-
- retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT,
- MS_NO_CHECK_INT);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, cnt, WAIT_INT,
- data, 8);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- total_progress = (data[0] << 24) | (data[1] << 16) |
- (data[2] << 8) | data[3];
- cur_progress = (data[4] << 24) | (data[5] << 16) |
- (data[6] << 8) | data[7];
-
- dev_dbg(rtsx_dev(chip), "total_progress = %d, cur_progress = %d\n",
- total_progress, cur_progress);
-
- if (total_progress == 0) {
- ms_card->progress = 0;
- } else {
- u64 ulltmp = (u64)cur_progress * (u64)65535;
-
- do_div(ulltmp, total_progress);
- ms_card->progress = (u16)ulltmp;
- }
- dev_dbg(rtsx_dev(chip), "progress = %d\n", ms_card->progress);
-
- for (i = 0; i < 5000; i++) {
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
- if (tmp & (MS_INT_CED | MS_INT_CMDNK |
- MS_INT_BREQ | MS_INT_ERR))
- break;
-
- wait_timeout(1);
- }
-
- retval = rtsx_write_register(chip, MS_CFG, MS_NO_CHECK_INT, 0);
- if (retval != STATUS_SUCCESS) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- if (i == 5000) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- if (tmp & (MS_INT_CMDNK | MS_INT_ERR)) {
- ms_card->format_status = FORMAT_FAIL;
- return STATUS_FAIL;
- }
-
- if (tmp & MS_INT_CED) {
- ms_card->format_status = FORMAT_SUCCESS;
- ms_card->pro_under_formatting = 0;
- } else if (tmp & MS_INT_BREQ) {
- ms_card->format_status = FORMAT_IN_PROGRESS;
- } else {
- ms_card->format_status = FORMAT_FAIL;
- ms_card->pro_under_formatting = 0;
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-void mspro_polling_format_status(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int i;
-
- if (ms_card->pro_under_formatting &&
- (rtsx_get_stat(chip) != RTSX_STAT_SS)) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- for (i = 0; i < 65535; i++) {
- mspro_read_format_progress(chip, MS_SHORT_DATA_LEN);
- if (ms_card->format_status != FORMAT_IN_PROGRESS)
- break;
- }
- }
-}
-
-int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- int short_data_len, bool quick_format)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 buf[8], tmp;
- u16 para;
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_set_rw_reg_addr(chip, 0x00, 0x00, PRO_TPC_PARM, 0x01);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- memset(buf, 0, 2);
- switch (short_data_len) {
- case 32:
- buf[0] = 0;
- break;
- case 64:
- buf[0] = 1;
- break;
- case 128:
- buf[0] = 2;
- break;
- case 256:
- default:
- buf[0] = 3;
- break;
- }
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, PRO_WRITE_REG, 1,
- NO_WAIT_INT, buf, 2);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- if (quick_format)
- para = 0x0000;
- else
- para = 0x0001;
-
- retval = mspro_set_rw_cmd(chip, 0, para, PRO_FORMAT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &tmp);
- if (retval)
- return retval;
-
- if (tmp & (MS_INT_CMDNK | MS_INT_ERR))
- return STATUS_FAIL;
-
- if ((tmp & (MS_INT_BREQ | MS_INT_CED)) == MS_INT_BREQ) {
- ms_card->pro_under_formatting = 1;
- ms_card->progress = 0;
- ms_card->format_status = FORMAT_IN_PROGRESS;
- return STATUS_SUCCESS;
- }
-
- if (tmp & MS_INT_CED) {
- ms_card->pro_under_formatting = 0;
- ms_card->progress = 0;
- ms_card->format_status = FORMAT_SUCCESS;
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_NO_SENSE);
- return STATUS_SUCCESS;
- }
-
- return STATUS_FAIL;
-}
-
-static int ms_read_multiple_pages(struct rtsx_chip *chip, u16 phy_blk,
- u16 log_blk, u8 start_page, u8 end_page,
- u8 *buf, unsigned int *index,
- unsigned int *offset)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 extra[MS_EXTRA_SIZE], page_addr, val, trans_cfg, data[6];
- u8 *ptr;
-
- retval = ms_read_extra_data(chip, phy_blk, start_page,
- extra, MS_EXTRA_SIZE);
- if (retval == STATUS_SUCCESS) {
- if ((extra[1] & 0x30) != 0x30) {
- ms_set_err_code(chip, MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
- }
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(phy_blk >> 8);
- data[3] = (u8)phy_blk;
- data[4] = 0;
- data[5] = start_page;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, WRITE_REG, 6, NO_WAIT_INT,
- data, 6);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- retval = ms_send_cmd(chip, BLOCK_READ, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ptr = buf;
-
- for (page_addr = start_page; page_addr < end_page; page_addr++) {
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
- if (val & INT_REG_ERR) {
- if (val & INT_REG_BREQ) {
- retval = ms_read_status_reg(chip);
- if (retval != STATUS_SUCCESS) {
- if (!(chip->card_wp & MS_CARD)) {
- reset_ms(chip);
- ms_set_page_status
- (log_blk, set_PS_NG,
- extra,
- MS_EXTRA_SIZE);
- ms_write_extra_data
- (chip, phy_blk,
- page_addr, extra,
- MS_EXTRA_SIZE);
- }
- ms_set_err_code(chip,
- MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
- } else {
- ms_set_err_code(chip, MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
- } else {
- if (!(val & INT_REG_BREQ)) {
- ms_set_err_code(chip, MS_BREQ_ERROR);
- return STATUS_FAIL;
- }
- }
-
- if (page_addr == (end_page - 1)) {
- if (!(val & INT_REG_CED)) {
- retval = ms_send_cmd(chip, BLOCK_END, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT,
- &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!(val & INT_REG_CED)) {
- ms_set_err_code(chip, MS_FLASH_READ_ERROR);
- return STATUS_FAIL;
- }
-
- trans_cfg = NO_WAIT_INT;
- } else {
- trans_cfg = WAIT_INT;
- }
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC, 0xFF, READ_PAGE_DATA);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG,
- 0xFF, trans_cfg);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, RING_BUFFER);
-
- trans_dma_enable(DMA_FROM_DEVICE, chip, 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
- MS_TRANSFER_START | MS_TM_NORMAL_READ);
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512,
- scsi_sg_count(chip->srb),
- index, offset,
- DMA_FROM_DEVICE,
- chip->ms_timeout);
- if (retval < 0) {
- if (retval == -ETIMEDOUT) {
- ms_set_err_code(chip, MS_TO_ERROR);
- rtsx_clear_ms_error(chip);
- return STATUS_TIMEDOUT;
- }
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_TO_ERROR);
- rtsx_clear_ms_error(chip);
- return STATUS_TIMEDOUT;
- }
- if (val & (MS_CRC16_ERR | MS_RDY_TIMEOUT)) {
- ms_set_err_code(chip, MS_CRC16_ERROR);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
- }
-
- if (scsi_sg_count(chip->srb) == 0)
- ptr += 512;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_write_multiple_pages(struct rtsx_chip *chip, u16 old_blk,
- u16 new_blk, u16 log_blk, u8 start_page,
- u8 end_page, u8 *buf, unsigned int *index,
- unsigned int *offset)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, i;
- u8 page_addr, val, data[16];
- u8 *ptr;
-
- if (!start_page) {
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, 7);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(old_blk >> 8);
- data[3] = (u8)old_blk;
- data[4] = 0x80;
- data[5] = 0;
- data[6] = 0xEF;
- data[7] = 0xFF;
-
- retval = ms_write_bytes(chip, WRITE_REG, 7, NO_WAIT_INT,
- data, 8);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
- retval = ms_transfer_tpc(chip, MS_TM_READ_BYTES, GET_INT, 1,
- NO_WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = ms_set_rw_reg_addr(chip, OVERWRITE_FLAG, MS_EXTRA_SIZE,
- SYSTEM_PARAM, (6 + MS_EXTRA_SIZE));
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (CHK_MS4BIT(ms_card))
- data[0] = 0x88;
- else
- data[0] = 0x80;
-
- data[1] = 0;
- data[2] = (u8)(new_blk >> 8);
- data[3] = (u8)new_blk;
- if ((end_page - start_page) == 1)
- data[4] = 0x20;
- else
- data[4] = 0;
-
- data[5] = start_page;
- data[6] = 0xF8;
- data[7] = 0xFF;
- data[8] = (u8)(log_blk >> 8);
- data[9] = (u8)log_blk;
-
- for (i = 0x0A; i < 0x10; i++)
- data[i] = 0xFF;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, WRITE_REG, 6 + MS_EXTRA_SIZE,
- NO_WAIT_INT, data, 16);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_send_cmd(chip, BLOCK_WRITE, WAIT_INT);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ptr = buf;
- for (page_addr = start_page; page_addr < end_page; page_addr++) {
- ms_set_err_code(chip, MS_NO_ERROR);
-
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- ms_set_err_code(chip, MS_NO_CARD);
- return STATUS_FAIL;
- }
-
- if (val & INT_REG_CMDNK) {
- ms_set_err_code(chip, MS_CMD_NK);
- return STATUS_FAIL;
- }
- if (val & INT_REG_ERR) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- if (!(val & INT_REG_BREQ)) {
- ms_set_err_code(chip, MS_BREQ_ERROR);
- return STATUS_FAIL;
- }
-
- udelay(30);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC,
- 0xFF, WRITE_PAGE_DATA);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG,
- 0xFF, WAIT_INT);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, RING_BUFFER);
-
- trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
- MS_TRANSFER_START | MS_TM_NORMAL_WRITE);
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data_partial(chip, MS_CARD, ptr, 512,
- scsi_sg_count(chip->srb),
- index, offset,
- DMA_TO_DEVICE,
- chip->ms_timeout);
- if (retval < 0) {
- ms_set_err_code(chip, MS_TO_ERROR);
- rtsx_clear_ms_error(chip);
-
- if (retval == -ETIMEDOUT)
- return STATUS_TIMEDOUT;
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, GET_INT, 1, NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if ((end_page - start_page) == 1) {
- if (!(val & INT_REG_CED)) {
- ms_set_err_code(chip, MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- } else {
- if (page_addr == (end_page - 1)) {
- if (!(val & INT_REG_CED)) {
- retval = ms_send_cmd(chip, BLOCK_END,
- WAIT_INT);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, GET_INT, 1,
- NO_WAIT_INT, &val, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (page_addr == (end_page - 1) ||
- page_addr == ms_card->page_off) {
- if (!(val & INT_REG_CED)) {
- ms_set_err_code(chip,
- MS_FLASH_WRITE_ERROR);
- return STATUS_FAIL;
- }
- }
- }
-
- if (scsi_sg_count(chip->srb) == 0)
- ptr += 512;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int ms_finish_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
- u16 log_blk, u8 page_off)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval, seg_no;
-
- retval = ms_copy_page(chip, old_blk, new_blk, log_blk,
- page_off, ms_card->page_off + 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- seg_no = old_blk >> 9;
-
- if (MS_TST_BAD_BLOCK_FLG(ms_card)) {
- MS_CLR_BAD_BLOCK_FLG(ms_card);
- ms_set_bad_block(chip, old_blk);
- } else {
- retval = ms_erase_block(chip, old_blk);
- if (retval == STATUS_SUCCESS)
- ms_set_unused_block(chip, old_blk);
- }
-
- ms_set_l2p_tbl(chip, seg_no, log_blk - ms_start_idx[seg_no], new_blk);
-
- return STATUS_SUCCESS;
-}
-
-static int ms_prepare_write(struct rtsx_chip *chip, u16 old_blk, u16 new_blk,
- u16 log_blk, u8 start_page)
-{
- int retval;
-
- if (start_page) {
- retval = ms_copy_page(chip, old_blk, new_blk, log_blk,
- 0, start_page);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-#ifdef MS_DELAY_WRITE
-int ms_delay_write(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- struct ms_delay_write_tag *delay_write = &ms_card->delay_write;
- int retval;
-
- if (delay_write->delay_write_flag) {
- retval = ms_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- delay_write->delay_write_flag = 0;
- retval = ms_finish_write(chip,
- delay_write->old_phyblock,
- delay_write->new_phyblock,
- delay_write->logblock,
- delay_write->pageoff);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-#endif
-
-static inline void ms_rw_fail(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- else
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
-}
-
-static int ms_rw_multi_sector(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt)
-{
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval, seg_no;
- unsigned int index = 0, offset = 0;
- u16 old_blk = 0, new_blk = 0, log_blk, total_sec_cnt = sector_cnt;
- u8 start_page, end_page = 0, page_cnt;
- u8 *ptr;
-#ifdef MS_DELAY_WRITE
- struct ms_delay_write_tag *delay_write = &ms_card->delay_write;
-#endif
-
- ms_set_err_code(chip, MS_NO_ERROR);
-
- ms_card->cleanup_counter = 0;
-
- ptr = (u8 *)scsi_sglist(srb);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS) {
- ms_rw_fail(srb, chip);
- return STATUS_FAIL;
- }
-
- log_blk = (u16)(start_sector >> ms_card->block_shift);
- start_page = (u8)(start_sector & ms_card->page_off);
-
- for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1; seg_no++) {
- if (log_blk < ms_start_idx[seg_no + 1])
- break;
- }
-
- if (ms_card->segment[seg_no].build_flag == 0) {
- retval = ms_build_l2p_tbl(chip, seg_no);
- if (retval != STATUS_SUCCESS) {
- chip->card_fail |= MS_CARD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
-#ifdef MS_DELAY_WRITE
- if (delay_write->delay_write_flag &&
- delay_write->logblock == log_blk &&
- start_page > delay_write->pageoff) {
- delay_write->delay_write_flag = 0;
- retval = ms_copy_page(chip,
- delay_write->old_phyblock,
- delay_write->new_phyblock,
- log_blk,
- delay_write->pageoff, start_page);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
- old_blk = delay_write->old_phyblock;
- new_blk = delay_write->new_phyblock;
- } else if (delay_write->delay_write_flag &&
- (delay_write->logblock == log_blk) &&
- (start_page == delay_write->pageoff)) {
- delay_write->delay_write_flag = 0;
- old_blk = delay_write->old_phyblock;
- new_blk = delay_write->new_phyblock;
- } else {
- retval = ms_delay_write(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-#endif
- old_blk = ms_get_l2p_tbl
- (chip, seg_no,
- log_blk - ms_start_idx[seg_no]);
- new_blk = ms_get_unused_block(chip, seg_no);
- if (old_blk == 0xFFFF || new_blk == 0xFFFF) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-
- retval = ms_prepare_write(chip, old_blk, new_blk,
- log_blk, start_page);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, MS_CARD) !=
- STATUS_SUCCESS) {
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-#ifdef MS_DELAY_WRITE
- }
-#endif
- } else {
-#ifdef MS_DELAY_WRITE
- retval = ms_delay_write(chip);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return STATUS_FAIL;
- }
-#endif
- old_blk = ms_get_l2p_tbl(chip, seg_no,
- log_blk - ms_start_idx[seg_no]);
- if (old_blk == 0xFFFF) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return STATUS_FAIL;
- }
- }
-
- dev_dbg(rtsx_dev(chip), "seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n",
- seg_no, old_blk, new_blk);
-
- while (total_sec_cnt) {
- if ((start_page + total_sec_cnt) > (ms_card->page_off + 1))
- end_page = ms_card->page_off + 1;
- else
- end_page = start_page + (u8)total_sec_cnt;
-
- page_cnt = end_page - start_page;
-
- dev_dbg(rtsx_dev(chip), "start_page = %d, end_page = %d, page_cnt = %d\n",
- start_page, end_page, page_cnt);
-
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- retval = ms_read_multiple_pages(chip,
- old_blk, log_blk,
- start_page, end_page,
- ptr, &index, &offset);
- } else {
- retval = ms_write_multiple_pages(chip, old_blk, new_blk,
- log_blk, start_page,
- end_page, ptr, &index,
- &offset);
- }
-
- if (retval != STATUS_SUCCESS) {
- toggle_gpio(chip, 1);
- if (detect_card_cd(chip, MS_CARD) != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- ms_rw_fail(srb, chip);
- return STATUS_FAIL;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
- if (end_page == (ms_card->page_off + 1)) {
- retval = ms_erase_block(chip, old_blk);
- if (retval == STATUS_SUCCESS)
- ms_set_unused_block(chip, old_blk);
-
- ms_set_l2p_tbl(chip, seg_no,
- log_blk - ms_start_idx[seg_no],
- new_blk);
- }
- }
-
- total_sec_cnt -= page_cnt;
- if (scsi_sg_count(srb) == 0)
- ptr += page_cnt * 512;
-
- if (total_sec_cnt == 0)
- break;
-
- log_blk++;
-
- for (seg_no = 0; seg_no < ARRAY_SIZE(ms_start_idx) - 1;
- seg_no++) {
- if (log_blk < ms_start_idx[seg_no + 1])
- break;
- }
-
- if (ms_card->segment[seg_no].build_flag == 0) {
- retval = ms_build_l2p_tbl(chip, seg_no);
- if (retval != STATUS_SUCCESS) {
- chip->card_fail |= MS_CARD;
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- }
-
- old_blk = ms_get_l2p_tbl(chip, seg_no,
- log_blk - ms_start_idx[seg_no]);
- if (old_blk == 0xFFFF) {
- ms_rw_fail(srb, chip);
- return STATUS_FAIL;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
- new_blk = ms_get_unused_block(chip, seg_no);
- if (new_blk == 0xFFFF) {
- ms_rw_fail(srb, chip);
- return STATUS_FAIL;
- }
- }
-
- dev_dbg(rtsx_dev(chip), "seg_no = %d, old_blk = 0x%x, new_blk = 0x%x\n",
- seg_no, old_blk, new_blk);
-
- start_page = 0;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
- if (end_page < (ms_card->page_off + 1)) {
-#ifdef MS_DELAY_WRITE
- delay_write->delay_write_flag = 1;
- delay_write->old_phyblock = old_blk;
- delay_write->new_phyblock = new_blk;
- delay_write->logblock = log_blk;
- delay_write->pageoff = end_page;
-#else
- retval = ms_finish_write(chip, old_blk, new_blk,
- log_blk, end_page);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, MS_CARD) !=
- STATUS_SUCCESS) {
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
-
- ms_rw_fail(srb, chip);
- return STATUS_FAIL;
- }
-#endif
- }
- }
-
- scsi_set_resid(srb, 0);
-
- return STATUS_SUCCESS;
-}
-
-int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
- if (CHK_MSPRO(ms_card))
- retval = mspro_rw_multi_sector(srb, chip, start_sector,
- sector_cnt);
- else
- retval = ms_rw_multi_sector(srb, chip, start_sector,
- sector_cnt);
-
- return retval;
-}
-
-void ms_free_l2p_tbl(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int i = 0;
-
- if (ms_card->segment) {
- for (i = 0; i < ms_card->segment_cnt; i++) {
- vfree(ms_card->segment[i].l2p_table);
- ms_card->segment[i].l2p_table = NULL;
- vfree(ms_card->segment[i].free_table);
- ms_card->segment[i].free_table = NULL;
- }
- vfree(ms_card->segment);
- ms_card->segment = NULL;
- }
-}
-
-#ifdef SUPPORT_MAGIC_GATE
-
-#ifdef READ_BYTES_WAIT_INT
-static int ms_poll_int(struct rtsx_chip *chip)
-{
- int retval;
- u8 val;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANS_CFG, MS_INT_CED, MS_INT_CED);
-
- retval = rtsx_send_cmd(chip, MS_CARD, 5000);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- val = *rtsx_get_cmd_data(chip);
- if (val & MS_INT_ERR)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-#endif
-
-#ifdef MS_SAMPLE_INT_ERR
-static int check_ms_err(struct rtsx_chip *chip)
-{
- int retval;
- u8 val;
-
- retval = rtsx_read_register(chip, MS_TRANSFER, &val);
- if (retval != STATUS_SUCCESS)
- return 1;
- if (val & MS_TRANSFER_ERR)
- return 1;
-
- retval = rtsx_read_register(chip, MS_TRANS_CFG, &val);
- if (retval != STATUS_SUCCESS)
- return 1;
-
- if (val & (MS_INT_ERR | MS_INT_CMDNK))
- return 1;
-
- return 0;
-}
-#else
-static int check_ms_err(struct rtsx_chip *chip)
-{
- int retval;
- u8 val;
-
- retval = rtsx_read_register(chip, MS_TRANSFER, &val);
- if (retval != STATUS_SUCCESS)
- return 1;
- if (val & MS_TRANSFER_ERR)
- return 1;
-
- return 0;
-}
-#endif
-
-static int mg_send_ex_cmd(struct rtsx_chip *chip, u8 cmd, u8 entry_num)
-{
- int retval, i;
- u8 data[8];
-
- data[0] = cmd;
- data[1] = 0;
- data[2] = 0;
- data[3] = 0;
- data[4] = 0;
- data[5] = 0;
- data[6] = entry_num;
- data[7] = 0;
-
- for (i = 0; i < MS_MAX_RETRY_COUNT; i++) {
- retval = ms_write_bytes(chip, PRO_EX_SET_CMD, 7, WAIT_INT,
- data, 8);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i == MS_MAX_RETRY_COUNT)
- return STATUS_FAIL;
-
- if (check_ms_err(chip)) {
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int mg_set_tpc_para_sub(struct rtsx_chip *chip, int type,
- u8 mg_entry_num)
-{
- int retval;
- u8 buf[6];
-
- if (type == 0)
- retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_TPC_PARM, 1);
- else
- retval = ms_set_rw_reg_addr(chip, 0, 0, PRO_DATA_COUNT1, 6);
-
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf[0] = 0;
- buf[1] = 0;
- if (type == 1) {
- buf[2] = 0;
- buf[3] = 0;
- buf[4] = 0;
- buf[5] = mg_entry_num;
- }
- retval = ms_write_bytes(chip, PRO_WRITE_REG, (type == 0) ? 1 : 6,
- NO_WAIT_INT, buf, 6);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- int i;
- unsigned int lun = SCSI_LUN(srb);
- u8 buf1[32], buf2[12];
-
- if (scsi_bufflen(srb) < 12) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return STATUS_FAIL;
- }
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = mg_send_ex_cmd(chip, MG_SET_LID, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- return STATUS_FAIL;
- }
-
- memset(buf1, 0, 32);
- rtsx_stor_get_xfer_buf(buf2, min_t(int, 12, scsi_bufflen(srb)), srb);
- for (i = 0; i < 8; i++)
- buf1[8 + i] = buf2[4 + i];
-
- retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT,
- buf1, 32);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- return STATUS_FAIL;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- int bufflen;
- unsigned int lun = SCSI_LUN(srb);
- u8 *buf = NULL;
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf = kmalloc(1540, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- buf[0] = 0x04;
- buf[1] = 0x1A;
- buf[2] = 0x00;
- buf[3] = 0x00;
-
- retval = mg_send_ex_cmd(chip, MG_GET_LEKB, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- goto free_buffer;
- }
-
- retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
- 3, WAIT_INT, 0, 0, buf + 4, 1536);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- rtsx_clear_ms_error(chip);
- goto free_buffer;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- rtsx_clear_ms_error(chip);
- retval = STATUS_FAIL;
- goto free_buffer;
- }
-
- bufflen = min_t(int, 1052, scsi_bufflen(srb));
- rtsx_stor_set_xfer_buf(buf, bufflen, srb);
-
-free_buffer:
- kfree(buf);
- return retval;
-}
-
-int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- int bufflen;
- int i;
- unsigned int lun = SCSI_LUN(srb);
- u8 buf[32];
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = mg_send_ex_cmd(chip, MG_GET_ID, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT,
- buf, 32);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return STATUS_FAIL;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- memcpy(ms_card->magic_gate_id, buf, 16);
-
-#ifdef READ_BYTES_WAIT_INT
- retval = ms_poll_int(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return STATUS_FAIL;
- }
-#endif
-
- retval = mg_send_ex_cmd(chip, MG_SET_RD, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return STATUS_FAIL;
- }
-
- bufflen = min_t(int, 12, scsi_bufflen(srb));
- rtsx_stor_get_xfer_buf(buf, bufflen, srb);
-
- for (i = 0; i < 8; i++)
- buf[i] = buf[4 + i];
-
- for (i = 0; i < 24; i++)
- buf[8 + i] = 0;
-
- retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA,
- 32, WAIT_INT, buf, 32);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return STATUS_FAIL;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- ms_card->mg_auth = 0;
-
- return STATUS_SUCCESS;
-}
-
-int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- int bufflen;
- unsigned int lun = SCSI_LUN(srb);
- u8 buf1[32], buf2[36];
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = mg_send_ex_cmd(chip, MG_MAKE_RMS, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- return STATUS_FAIL;
- }
-
- retval = ms_read_bytes(chip, PRO_READ_SHORT_DATA, 32, WAIT_INT,
- buf1, 32);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- return STATUS_FAIL;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- buf2[0] = 0x00;
- buf2[1] = 0x22;
- buf2[2] = 0x00;
- buf2[3] = 0x00;
-
- memcpy(buf2 + 4, ms_card->magic_gate_id, 16);
- memcpy(buf2 + 20, buf1, 16);
-
- bufflen = min_t(int, 36, scsi_bufflen(srb));
- rtsx_stor_set_xfer_buf(buf2, bufflen, srb);
-
-#ifdef READ_BYTES_WAIT_INT
- retval = ms_poll_int(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- return STATUS_FAIL;
- }
-#endif
-
- return STATUS_SUCCESS;
-}
-
-int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- int i;
- int bufflen;
- unsigned int lun = SCSI_LUN(srb);
- u8 buf[32];
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = mg_send_ex_cmd(chip, MG_MAKE_KSE, 0);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- return STATUS_FAIL;
- }
-
- bufflen = min_t(int, 12, scsi_bufflen(srb));
- rtsx_stor_get_xfer_buf(buf, bufflen, srb);
-
- for (i = 0; i < 8; i++)
- buf[i] = buf[4 + i];
-
- for (i = 0; i < 24; i++)
- buf[8 + i] = 0;
-
- retval = ms_write_bytes(chip, PRO_WRITE_SHORT_DATA, 32, WAIT_INT,
- buf, 32);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- return STATUS_FAIL;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN);
- rtsx_clear_ms_error(chip);
- return STATUS_FAIL;
- }
-
- ms_card->mg_auth = 1;
-
- return STATUS_SUCCESS;
-}
-
-int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- int bufflen;
- unsigned int lun = SCSI_LUN(srb);
- u8 *buf = NULL;
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf = kmalloc(1028, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- buf[0] = 0x04;
- buf[1] = 0x02;
- buf[2] = 0x00;
- buf[3] = 0x00;
-
- retval = mg_send_ex_cmd(chip, MG_GET_IBD, ms_card->mg_entry_num);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- goto free_buffer;
- }
-
- retval = ms_transfer_data(chip, MS_TM_AUTO_READ, PRO_READ_LONG_DATA,
- 2, WAIT_INT, 0, 0, buf + 4, 1024);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- rtsx_clear_ms_error(chip);
- goto free_buffer;
- }
- if (check_ms_err(chip)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- rtsx_clear_ms_error(chip);
- retval = STATUS_FAIL;
- goto free_buffer;
- }
-
- bufflen = min_t(int, 1028, scsi_bufflen(srb));
- rtsx_stor_set_xfer_buf(buf, bufflen, srb);
-
-free_buffer:
- kfree(buf);
- return retval;
-}
-
-int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- int bufflen;
-#ifdef MG_SET_ICV_SLOW
- int i;
-#endif
- unsigned int lun = SCSI_LUN(srb);
- u8 *buf = NULL;
-
- ms_cleanup_work(chip);
-
- retval = ms_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf = kmalloc(1028, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- bufflen = min_t(int, 1028, scsi_bufflen(srb));
- rtsx_stor_get_xfer_buf(buf, bufflen, srb);
-
- retval = mg_send_ex_cmd(chip, MG_SET_IBD, ms_card->mg_entry_num);
- if (retval != STATUS_SUCCESS) {
- if (ms_card->mg_auth == 0) {
- if ((buf[5] & 0xC0) != 0)
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MG_WRITE_ERR);
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
- }
- goto set_ICV_finish;
- }
-
-#ifdef MG_SET_ICV_SLOW
- for (i = 0; i < 2; i++) {
- udelay(50);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TPC,
- 0xFF, PRO_WRITE_LONG_DATA);
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANS_CFG, 0xFF, WAIT_INT);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, RING_BUFFER);
-
- trans_dma_enable(DMA_TO_DEVICE, chip, 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, MS_TRANSFER, 0xFF,
- MS_TRANSFER_START | MS_TM_NORMAL_WRITE);
- rtsx_add_cmd(chip, CHECK_REG_CMD, MS_TRANSFER,
- MS_TRANSFER_END, MS_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data(chip, MS_CARD, buf + 4 + i * 512,
- 512, 0, DMA_TO_DEVICE, 3000);
- if (retval < 0 || check_ms_err(chip)) {
- rtsx_clear_ms_error(chip);
- if (ms_card->mg_auth == 0) {
- if ((buf[5] & 0xC0) != 0)
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MG_WRITE_ERR);
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MG_WRITE_ERR);
- }
- retval = STATUS_FAIL;
- goto set_ICV_finish;
- }
- }
-#else
- retval = ms_transfer_data(chip, MS_TM_AUTO_WRITE, PRO_WRITE_LONG_DATA,
- 2, WAIT_INT, 0, 0, buf + 4, 1024);
- if (retval != STATUS_SUCCESS || check_ms_err(chip)) {
- rtsx_clear_ms_error(chip);
- if (ms_card->mg_auth == 0) {
- if ((buf[5] & 0xC0) != 0)
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MG_WRITE_ERR);
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MG_WRITE_ERR);
- }
- goto set_ICV_finish;
- }
-#endif
-
-set_ICV_finish:
- kfree(buf);
- return retval;
-}
-
-#endif /* SUPPORT_MAGIC_GATE */
-
-void ms_cleanup_work(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
-
- if (CHK_MSPRO(ms_card)) {
- if (ms_card->seq_mode) {
- dev_dbg(rtsx_dev(chip), "MS Pro: stop transmission\n");
- mspro_stop_seq_mode(chip);
- ms_card->cleanup_counter = 0;
- }
- if (CHK_MSHG(ms_card)) {
- rtsx_write_register(chip, MS_CFG,
- MS_2K_SECTOR_MODE, 0x00);
- }
- }
-#ifdef MS_DELAY_WRITE
- else if ((!CHK_MSPRO(ms_card)) &&
- ms_card->delay_write.delay_write_flag) {
- dev_dbg(rtsx_dev(chip), "MS: delay write\n");
- ms_delay_write(chip);
- ms_card->cleanup_counter = 0;
- }
-#endif
-}
-
-int ms_power_off_card3v3(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = disable_card_clock(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (chip->asic_code) {
- retval = ms_pull_ctl_disable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- FPGA_MS_PULL_CTL_BIT | 0x20,
- FPGA_MS_PULL_CTL_BIT);
- if (retval)
- return retval;
- }
- retval = rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
- if (retval)
- return retval;
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_off(chip, MS_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int release_ms_card(struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
-
-#ifdef MS_DELAY_WRITE
- ms_card->delay_write.delay_write_flag = 0;
-#endif
- ms_card->pro_under_formatting = 0;
-
- chip->card_ready &= ~MS_CARD;
- chip->card_fail &= ~MS_CARD;
- chip->card_wp &= ~MS_CARD;
-
- ms_free_l2p_tbl(chip);
-
- memset(ms_card->raw_sys_info, 0, 96);
-#ifdef SUPPORT_PCGL_1P18
- memset(ms_card->raw_model_name, 0, 48);
-#endif
-
- retval = ms_power_off_card3v3(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts5208/ms.h b/drivers/staging/rts5208/ms.h
deleted file mode 100644
index 33bda9ce36b6..000000000000
--- a/drivers/staging/rts5208/ms.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_MS_H
-#define __REALTEK_RTSX_MS_H
-
-#define MS_DELAY_WRITE
-
-#define MS_MAX_RETRY_COUNT 3
-
-#define MS_EXTRA_SIZE 0x9
-
-#define WRT_PRTCT 0x01
-
-/* Error Code */
-#define MS_NO_ERROR 0x00
-#define MS_CRC16_ERROR 0x80
-#define MS_TO_ERROR 0x40
-#define MS_NO_CARD 0x20
-#define MS_NO_MEMORY 0x10
-#define MS_CMD_NK 0x08
-#define MS_FLASH_READ_ERROR 0x04
-#define MS_FLASH_WRITE_ERROR 0x02
-#define MS_BREQ_ERROR 0x01
-#define MS_NOT_FOUND 0x03
-
-/* Transfer Protocol Command */
-#define READ_PAGE_DATA 0x02
-#define READ_REG 0x04
-#define GET_INT 0x07
-#define WRITE_PAGE_DATA 0x0D
-#define WRITE_REG 0x0B
-#define SET_RW_REG_ADRS 0x08
-#define SET_CMD 0x0E
-
-#define PRO_READ_LONG_DATA 0x02
-#define PRO_READ_SHORT_DATA 0x03
-#define PRO_READ_REG 0x04
-#define PRO_READ_QUAD_DATA 0x05
-#define PRO_GET_INT 0x07
-#define PRO_WRITE_LONG_DATA 0x0D
-#define PRO_WRITE_SHORT_DATA 0x0C
-#define PRO_WRITE_QUAD_DATA 0x0A
-#define PRO_WRITE_REG 0x0B
-#define PRO_SET_RW_REG_ADRS 0x08
-#define PRO_SET_CMD 0x0E
-#define PRO_EX_SET_CMD 0x09
-
-#ifdef SUPPORT_MAGIC_GATE
-
-#define MG_GET_ID 0x40
-#define MG_SET_LID 0x41
-#define MG_GET_LEKB 0x42
-#define MG_SET_RD 0x43
-#define MG_MAKE_RMS 0x44
-#define MG_MAKE_KSE 0x45
-#define MG_SET_IBD 0x46
-#define MG_GET_IBD 0x47
-
-#endif
-
-#ifdef XC_POWERCLASS
-#define XC_CHG_POWER 0x16
-#endif
-
-#define BLOCK_READ 0xAA
-#define BLOCK_WRITE 0x55
-#define BLOCK_END 0x33
-#define BLOCK_ERASE 0x99
-#define FLASH_STOP 0xCC
-
-#define SLEEP 0x5A
-#define CLEAR_BUF 0xC3
-#define MS_RESET 0x3C
-
-#define PRO_READ_DATA 0x20
-#define PRO_WRITE_DATA 0x21
-#define PRO_READ_ATRB 0x24
-#define PRO_STOP 0x25
-#define PRO_ERASE 0x26
-#define PRO_READ_2K_DATA 0x27
-#define PRO_WRITE_2K_DATA 0x28
-
-#define PRO_FORMAT 0x10
-#define PRO_SLEEP 0x11
-
-#define INT_REG 0x01
-#define STATUS_REG0 0x02
-#define STATUS_REG1 0x03
-
-#define SYSTEM_PARAM 0x10
-#define BLOCK_ADRS 0x11
-#define CMD_PARM 0x14
-#define PAGE_ADRS 0x15
-
-#define OVERWRITE_FLAG 0x16
-#define MANAGEMEN_FLAG 0x17
-#define LOGICAL_ADRS 0x18
-#define RESERVE_AREA 0x1A
-
-#define PRO_INT_REG 0x01
-#define PRO_STATUS_REG 0x02
-#define PRO_TYPE_REG 0x04
-#define PRO_IF_mode_REG 0x05
-#define PRO_CATEGORY_REG 0x06
-#define PRO_CLASS_REG 0x07
-
-#define PRO_SYSTEM_PARAM 0x10
-#define PRO_DATA_COUNT1 0x11
-#define PRO_DATA_COUNT0 0x12
-#define PRO_DATA_ADDR3 0x13
-#define PRO_DATA_ADDR2 0x14
-#define PRO_DATA_ADDR1 0x15
-#define PRO_DATA_ADDR0 0x16
-
-#define PRO_TPC_PARM 0x17
-#define PRO_CMD_PARM 0x18
-
-#define INT_REG_CED 0x80
-#define INT_REG_ERR 0x40
-#define INT_REG_BREQ 0x20
-#define INT_REG_CMDNK 0x01
-
-#define BLOCK_BOOT 0xC0
-#define BLOCK_OK 0x80
-#define PAGE_OK 0x60
-#define DATA_COMPL 0x10
-
-#define NOT_BOOT_BLOCK 0x4
-#define NOT_TRANSLATION_TABLE 0x8
-
-#define HEADER_ID0 PPBUF_BASE2
-#define HEADER_ID1 (PPBUF_BASE2 + 1)
-#define DISABLED_BLOCK0 (PPBUF_BASE2 + 0x170 + 4)
-#define DISABLED_BLOCK1 (PPBUF_BASE2 + 0x170 + 5)
-#define DISABLED_BLOCK2 (PPBUF_BASE2 + 0x170 + 6)
-#define DISABLED_BLOCK3 (PPBUF_BASE2 + 0x170 + 7)
-#define BLOCK_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 2)
-#define BLOCK_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 3)
-#define BLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 4)
-#define BLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 5)
-#define EBLOCK_COUNT_0 (PPBUF_BASE2 + 0x1a0 + 6)
-#define EBLOCK_COUNT_1 (PPBUF_BASE2 + 0x1a0 + 7)
-#define PAGE_SIZE_0 (PPBUF_BASE2 + 0x1a0 + 8)
-#define PAGE_SIZE_1 (PPBUF_BASE2 + 0x1a0 + 9)
-
-#define MS_device_type (PPBUF_BASE2 + 0x1D8)
-
-#define MS_4bit_support (PPBUF_BASE2 + 0x1D3)
-
-#define set_PS_NG 1
-#define set_PS_error 0
-
-#define PARALLEL_8BIT_IF 0x40
-#define PARALLEL_4BIT_IF 0x00
-#define SERIAL_IF 0x80
-
-#define BUF_FULL 0x10
-#define BUF_EMPTY 0x20
-
-#define MEDIA_BUSY 0x80
-#define FLASH_BUSY 0x40
-#define DATA_ERROR 0x20
-#define STS_UCDT 0x10
-#define EXTRA_ERROR 0x08
-#define STS_UCEX 0x04
-#define FLAG_ERROR 0x02
-#define STS_UCFG 0x01
-
-#define MS_SHORT_DATA_LEN 32
-
-#define FORMAT_SUCCESS 0
-#define FORMAT_FAIL 1
-#define FORMAT_IN_PROGRESS 2
-
-#define MS_SET_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag |= 0x80)
-#define MS_CLR_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag &= 0x7F)
-#define MS_TST_BAD_BLOCK_FLG(ms_card) ((ms_card)->multi_flag & 0x80)
-
-void mspro_polling_format_status(struct rtsx_chip *chip);
-
-void mspro_stop_seq_mode(struct rtsx_chip *chip);
-int reset_ms_card(struct rtsx_chip *chip);
-int ms_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt);
-int mspro_format(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- int short_data_len, bool quick_format);
-void ms_free_l2p_tbl(struct rtsx_chip *chip);
-void ms_cleanup_work(struct rtsx_chip *chip);
-int ms_power_off_card3v3(struct rtsx_chip *chip);
-int release_ms_card(struct rtsx_chip *chip);
-#ifdef MS_DELAY_WRITE
-int ms_delay_write(struct rtsx_chip *chip);
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
-int mg_set_leaf_id(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_get_local_EKB(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_get_rsp_chg(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_get_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int mg_set_ICV(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-#endif
-
-#endif /* __REALTEK_RTSX_MS_H */
diff --git a/drivers/staging/rts5208/rtsx.c b/drivers/staging/rts5208/rtsx.c
deleted file mode 100644
index c4f54c311d05..000000000000
--- a/drivers/staging/rts5208/rtsx.c
+++ /dev/null
@@ -1,987 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-
-#include "rtsx.h"
-#include "ms.h"
-#include "sd.h"
-#include "xd.h"
-
-MODULE_DESCRIPTION("Realtek PCI-Express card reader rts5208/rts5288 driver");
-MODULE_LICENSE("GPL");
-
-static unsigned int delay_use = 1;
-module_param(delay_use, uint, 0644);
-MODULE_PARM_DESC(delay_use, "seconds to delay before using a new device");
-
-static int ss_en;
-module_param(ss_en, int, 0644);
-MODULE_PARM_DESC(ss_en, "enable selective suspend");
-
-static int ss_interval = 50;
-module_param(ss_interval, int, 0644);
-MODULE_PARM_DESC(ss_interval, "Interval to enter ss state in seconds");
-
-static int auto_delink_en;
-module_param(auto_delink_en, int, 0644);
-MODULE_PARM_DESC(auto_delink_en, "enable auto delink");
-
-static unsigned char aspm_l0s_l1_en;
-module_param(aspm_l0s_l1_en, byte, 0644);
-MODULE_PARM_DESC(aspm_l0s_l1_en, "enable device aspm");
-
-static int msi_en;
-module_param(msi_en, int, 0644);
-MODULE_PARM_DESC(msi_en, "enable msi");
-
-static irqreturn_t rtsx_interrupt(int irq, void *dev_id);
-
-/***********************************************************************
- * Host functions
- ***********************************************************************/
-
-static const char *host_info(struct Scsi_Host *host)
-{
- return "SCSI emulation for PCI-Express Mass Storage devices";
-}
-
-static int slave_alloc(struct scsi_device *sdev)
-{
- /*
- * Set the INQUIRY transfer length to 36. We don't use any of
- * the extra data and many devices choke if asked for more or
- * less than 36 bytes.
- */
- sdev->inquiry_len = 36;
- return 0;
-}
-
-static int slave_configure(struct scsi_device *sdev)
-{
- /* Set the SCSI level to at least 2. We'll leave it at 3 if that's
- * what is originally reported. We need this to avoid confusing
- * the SCSI layer with devices that report 0 or 1, but need 10-byte
- * commands (ala ATAPI devices behind certain bridges, or devices
- * which simply have broken INQUIRY data).
- *
- * NOTE: This means /dev/sg programs (ala cdrecord) will get the
- * actual information. This seems to be the preference for
- * programs like that.
- *
- * NOTE: This also means that /proc/scsi/scsi and sysfs may report
- * the actual value or the modified one, depending on where the
- * data comes from.
- */
- if (sdev->scsi_level < SCSI_2) {
- sdev->scsi_level = SCSI_2;
- sdev->sdev_target->scsi_level = SCSI_2;
- }
-
- return 0;
-}
-
-/***********************************************************************
- * /proc/scsi/ functions
- ***********************************************************************/
-
-/* we use this macro to help us write into the buffer */
-#undef SPRINTF
-#define SPRINTF(args...) \
- do { \
- if (pos < buffer + length) \
- pos += sprintf(pos, ## args); \
- } while (0)
-
-/* queue a command */
-/* This is always called with spin_lock_irq(host->host_lock) held */
-static int queuecommand_lck(struct scsi_cmnd *srb)
-{
- void (*done)(struct scsi_cmnd *) = scsi_done;
- struct rtsx_dev *dev = host_to_rtsx(srb->device->host);
- struct rtsx_chip *chip = dev->chip;
-
- /* check for state-transition errors */
- if (chip->srb) {
- dev_err(&dev->pci->dev, "Error: chip->srb = %p\n",
- chip->srb);
- return SCSI_MLQUEUE_HOST_BUSY;
- }
-
- /* fail the command if we are disconnecting */
- if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
- dev_info(&dev->pci->dev, "Fail command during disconnect\n");
- srb->result = DID_NO_CONNECT << 16;
- done(srb);
- return 0;
- }
-
- /* enqueue the command and wake up the control thread */
- chip->srb = srb;
- complete(&dev->cmnd_ready);
-
- return 0;
-}
-
-static DEF_SCSI_QCMD(queuecommand)
-
-/***********************************************************************
- * Error handling functions
- ***********************************************************************/
-
-/* Command timeout and abort */
-static int command_abort(struct scsi_cmnd *srb)
-{
- struct Scsi_Host *host = srb->device->host;
- struct rtsx_dev *dev = host_to_rtsx(host);
- struct rtsx_chip *chip = dev->chip;
-
- spin_lock_irq(host->host_lock);
-
- /* Is this command still active? */
- if (chip->srb != srb) {
- spin_unlock_irq(host->host_lock);
- dev_info(&dev->pci->dev, "-- nothing to abort\n");
- return FAILED;
- }
-
- rtsx_set_stat(chip, RTSX_STAT_ABORT);
-
- spin_unlock_irq(host->host_lock);
-
- /* Wait for the aborted command to finish */
- wait_for_completion(&dev->notify);
-
- return SUCCESS;
-}
-
-/*
- * This invokes the transport reset mechanism to reset the state of the
- * device
- */
-static int device_reset(struct scsi_cmnd *srb)
-{
- return SUCCESS;
-}
-
-/*
- * this defines our host template, with which we'll allocate hosts
- */
-
-static const struct scsi_host_template rtsx_host_template = {
- /* basic userland interface stuff */
- .name = CR_DRIVER_NAME,
- .proc_name = CR_DRIVER_NAME,
- .info = host_info,
-
- /* command interface -- queued only */
- .queuecommand = queuecommand,
-
- /* error and abort handlers */
- .eh_abort_handler = command_abort,
- .eh_device_reset_handler = device_reset,
-
- /* queue commands only, only one command per LUN */
- .can_queue = 1,
-
- /* unknown initiator id */
- .this_id = -1,
-
- .slave_alloc = slave_alloc,
- .slave_configure = slave_configure,
-
- /* lots of sg segments can be handled */
- .sg_tablesize = SG_ALL,
-
- /* limit the total size of a transfer to 120 KB */
- .max_sectors = 240,
-
- /*
- * Scatter-gather buffers (all but the last) must have a length
- * divisible by the bulk maxpacket size. Otherwise a data packet
- * would end up being short, causing a premature end to the data
- * transfer. Since high-speed bulk pipes have a maxpacket size
- * of 512, we'll use that as the scsi device queue's DMA alignment
- * mask. Guaranteeing proper alignment of the first buffer will
- * have the desired effect because, except at the beginning and
- * the end, scatter-gather buffers follow page boundaries.
- */
- .dma_alignment = 511,
-
- /* emulated HBA */
- .emulated = 1,
-
- /* we do our own delay after a device or bus reset */
- .skip_settle_delay = 1,
-
- /* module management */
- .module = THIS_MODULE
-};
-
-static int rtsx_acquire_irq(struct rtsx_dev *dev)
-{
- struct rtsx_chip *chip = dev->chip;
-
- dev_info(&dev->pci->dev, "%s: chip->msi_en = %d, pci->irq = %d\n",
- __func__, chip->msi_en, dev->pci->irq);
-
- if (request_irq(dev->pci->irq, rtsx_interrupt,
- chip->msi_en ? 0 : IRQF_SHARED,
- CR_DRIVER_NAME, dev)) {
- dev_err(&dev->pci->dev,
- "rtsx: unable to grab IRQ %d, disabling device\n",
- dev->pci->irq);
- return -1;
- }
-
- dev->irq = dev->pci->irq;
- pci_intx(dev->pci, !chip->msi_en);
-
- return 0;
-}
-
-/*
- * power management
- */
-static int __maybe_unused rtsx_suspend(struct device *dev_d)
-{
- struct pci_dev *pci = to_pci_dev(dev_d);
- struct rtsx_dev *dev = pci_get_drvdata(pci);
- struct rtsx_chip *chip;
-
- if (!dev)
- return 0;
-
- /* lock the device pointers */
- mutex_lock(&dev->dev_mutex);
-
- chip = dev->chip;
-
- rtsx_do_before_power_down(chip, PM_S3);
-
- if (dev->irq >= 0) {
- free_irq(dev->irq, (void *)dev);
- dev->irq = -1;
- }
-
- if (chip->msi_en)
- pci_free_irq_vectors(pci);
-
- device_wakeup_enable(dev_d);
-
- /* unlock the device pointers */
- mutex_unlock(&dev->dev_mutex);
-
- return 0;
-}
-
-static int __maybe_unused rtsx_resume(struct device *dev_d)
-{
- struct pci_dev *pci = to_pci_dev(dev_d);
- struct rtsx_dev *dev = pci_get_drvdata(pci);
- struct rtsx_chip *chip;
-
- if (!dev)
- return 0;
-
- chip = dev->chip;
-
- /* lock the device pointers */
- mutex_lock(&dev->dev_mutex);
-
- pci_set_master(pci);
-
- if (chip->msi_en) {
- if (pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) < 0)
- chip->msi_en = 0;
- }
-
- if (rtsx_acquire_irq(dev) < 0) {
- /* unlock the device pointers */
- mutex_unlock(&dev->dev_mutex);
- return -EIO;
- }
-
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00);
- rtsx_init_chip(chip);
-
- /* unlock the device pointers */
- mutex_unlock(&dev->dev_mutex);
-
- return 0;
-}
-
-static void rtsx_shutdown(struct pci_dev *pci)
-{
- struct rtsx_dev *dev = pci_get_drvdata(pci);
- struct rtsx_chip *chip;
-
- if (!dev)
- return;
-
- chip = dev->chip;
-
- rtsx_do_before_power_down(chip, PM_S1);
-
- if (dev->irq >= 0) {
- free_irq(dev->irq, (void *)dev);
- dev->irq = -1;
- }
-
- if (chip->msi_en)
- pci_free_irq_vectors(pci);
-
- pci_disable_device(pci);
-}
-
-static int rtsx_control_thread(void *__dev)
-{
- struct rtsx_dev *dev = __dev;
- struct rtsx_chip *chip = dev->chip;
- struct Scsi_Host *host = rtsx_to_host(dev);
-
- for (;;) {
- if (wait_for_completion_interruptible(&dev->cmnd_ready))
- break;
-
- /* lock the device pointers */
- mutex_lock(&dev->dev_mutex);
-
- /* if the device has disconnected, we are free to exit */
- if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
- dev_info(&dev->pci->dev, "-- rtsx-control exiting\n");
- mutex_unlock(&dev->dev_mutex);
- break;
- }
-
- /* lock access to the state */
- spin_lock_irq(host->host_lock);
-
- /* has the command aborted ? */
- if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
- chip->srb->result = DID_ABORT << 16;
- goto skip_for_abort;
- }
-
- spin_unlock_irq(host->host_lock);
-
- /* reject the command if the direction indicator
- * is UNKNOWN
- */
- if (chip->srb->sc_data_direction == DMA_BIDIRECTIONAL) {
- dev_err(&dev->pci->dev, "UNKNOWN data direction\n");
- chip->srb->result = DID_ERROR << 16;
- } else if (chip->srb->device->id) {
- /* reject if target != 0 or if LUN is higher than
- * the maximum known LUN
- */
- dev_err(&dev->pci->dev, "Bad target number (%d:%d)\n",
- chip->srb->device->id,
- (u8)chip->srb->device->lun);
- chip->srb->result = DID_BAD_TARGET << 16;
- } else if (chip->srb->device->lun > chip->max_lun) {
- dev_err(&dev->pci->dev, "Bad LUN (%d:%d)\n",
- chip->srb->device->id,
- (u8)chip->srb->device->lun);
- chip->srb->result = DID_BAD_TARGET << 16;
- } else {
- /* we've got a command, let's do it! */
- scsi_show_command(chip);
- rtsx_invoke_transport(chip->srb, chip);
- }
-
- /* lock access to the state */
- spin_lock_irq(host->host_lock);
-
- /* did the command already complete because of a disconnect? */
- if (!chip->srb)
- ; /* nothing to do */
-
- /* indicate that the command is done */
- else if (chip->srb->result != DID_ABORT << 16) {
- scsi_done(chip->srb);
- } else {
-skip_for_abort:
- dev_err(&dev->pci->dev, "scsi command aborted\n");
- }
-
- if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
- complete(&dev->notify);
-
- rtsx_set_stat(chip, RTSX_STAT_IDLE);
- }
-
- /* finished working on this command */
- chip->srb = NULL;
- spin_unlock_irq(host->host_lock);
-
- /* unlock the device pointers */
- mutex_unlock(&dev->dev_mutex);
- } /* for (;;) */
-
- /* notify the exit routine that we're actually exiting now
- *
- * complete()/wait_for_completion() is similar to up()/down(),
- * except that complete() is safe in the case where the structure
- * is getting deleted in a parallel mode of execution (i.e. just
- * after the down() -- that's necessary for the thread-shutdown
- * case.
- *
- * kthread_complete_and_exit() goes even further than this --
- * it is safe in the case that the thread of the caller is going away
- * (not just the structure) -- this is necessary for the module-remove
- * case. This is important in preemption kernels, which transfer the
- * flow of execution immediately upon a complete().
- */
- kthread_complete_and_exit(&dev->control_exit, 0);
-}
-
-static int rtsx_polling_thread(void *__dev)
-{
- struct rtsx_dev *dev = __dev;
- struct rtsx_chip *chip = dev->chip;
- struct sd_info *sd_card = &chip->sd_card;
- struct xd_info *xd_card = &chip->xd_card;
- struct ms_info *ms_card = &chip->ms_card;
-
- sd_card->cleanup_counter = 0;
- xd_card->cleanup_counter = 0;
- ms_card->cleanup_counter = 0;
-
- /* Wait until SCSI scan finished */
- wait_timeout((delay_use + 5) * 1000);
-
- for (;;) {
- set_current_state(TASK_INTERRUPTIBLE);
- schedule_timeout(msecs_to_jiffies(POLLING_INTERVAL));
-
- /* lock the device pointers */
- mutex_lock(&dev->dev_mutex);
-
- /* if the device has disconnected, we are free to exit */
- if (rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
- dev_info(&dev->pci->dev, "-- rtsx-polling exiting\n");
- mutex_unlock(&dev->dev_mutex);
- break;
- }
-
- mutex_unlock(&dev->dev_mutex);
-
- mspro_polling_format_status(chip);
-
- /* lock the device pointers */
- mutex_lock(&dev->dev_mutex);
-
- rtsx_polling_func(chip);
-
- /* unlock the device pointers */
- mutex_unlock(&dev->dev_mutex);
- }
-
- kthread_complete_and_exit(&dev->polling_exit, 0);
-}
-
-/*
- * interrupt handler
- */
-static irqreturn_t rtsx_interrupt(int irq, void *dev_id)
-{
- struct rtsx_dev *dev = dev_id;
- struct rtsx_chip *chip;
- int retval;
- u32 status;
-
- if (dev)
- chip = dev->chip;
- else
- return IRQ_NONE;
-
- if (!chip)
- return IRQ_NONE;
-
- spin_lock(&dev->reg_lock);
-
- retval = rtsx_pre_handle_interrupt(chip);
- if (retval == STATUS_FAIL) {
- spin_unlock(&dev->reg_lock);
- if (chip->int_reg == 0xFFFFFFFF)
- return IRQ_HANDLED;
- return IRQ_NONE;
- }
-
- status = chip->int_reg;
-
- if (dev->check_card_cd) {
- if (!(dev->check_card_cd & status)) {
- /* card not exist, return TRANS_RESULT_FAIL */
- dev->trans_result = TRANS_RESULT_FAIL;
- if (dev->done)
- complete(dev->done);
- goto exit;
- }
- }
-
- if (status & (NEED_COMPLETE_INT | DELINK_INT)) {
- if (status & (TRANS_FAIL_INT | DELINK_INT)) {
- if (status & DELINK_INT)
- RTSX_SET_DELINK(chip);
- dev->trans_result = TRANS_RESULT_FAIL;
- if (dev->done)
- complete(dev->done);
- } else if (status & TRANS_OK_INT) {
- dev->trans_result = TRANS_RESULT_OK;
- if (dev->done)
- complete(dev->done);
- } else if (status & DATA_DONE_INT) {
- dev->trans_result = TRANS_NOT_READY;
- if (dev->done && dev->trans_state == STATE_TRANS_SG)
- complete(dev->done);
- }
- }
-
-exit:
- spin_unlock(&dev->reg_lock);
- return IRQ_HANDLED;
-}
-
-/* Release all our dynamic resources */
-static void rtsx_release_resources(struct rtsx_dev *dev)
-{
- dev_info(&dev->pci->dev, "-- %s\n", __func__);
-
- /* Tell the control thread to exit. The SCSI host must
- * already have been removed so it won't try to queue
- * any more commands.
- */
- dev_info(&dev->pci->dev, "-- sending exit command to thread\n");
- complete(&dev->cmnd_ready);
- if (dev->ctl_thread)
- wait_for_completion(&dev->control_exit);
- if (dev->polling_thread)
- wait_for_completion(&dev->polling_exit);
-
- wait_timeout(200);
-
- if (dev->rtsx_resv_buf) {
- dev->chip->host_cmds_ptr = NULL;
- dev->chip->host_sg_tbl_ptr = NULL;
- }
-
- if (dev->irq > 0)
- free_irq(dev->irq, (void *)dev);
- if (dev->chip->msi_en)
- pci_free_irq_vectors(dev->pci);
- if (dev->remap_addr)
- iounmap(dev->remap_addr);
-
- rtsx_release_chip(dev->chip);
- kfree(dev->chip);
-}
-
-/*
- * First stage of disconnect processing: stop all commands and remove
- * the host
- */
-static void quiesce_and_remove_host(struct rtsx_dev *dev)
-{
- struct Scsi_Host *host = rtsx_to_host(dev);
- struct rtsx_chip *chip = dev->chip;
-
- /*
- * Prevent new transfers, stop the current command, and
- * interrupt a SCSI-scan or device-reset delay
- */
- mutex_lock(&dev->dev_mutex);
- spin_lock_irq(host->host_lock);
- rtsx_set_stat(chip, RTSX_STAT_DISCONNECT);
- spin_unlock_irq(host->host_lock);
- mutex_unlock(&dev->dev_mutex);
- wake_up(&dev->delay_wait);
- wait_for_completion(&dev->scanning_done);
-
- /* Wait some time to let other threads exist */
- wait_timeout(100);
-
- /*
- * queuecommand won't accept any new commands and the control
- * thread won't execute a previously-queued command. If there
- * is such a command pending, complete it with an error.
- */
- mutex_lock(&dev->dev_mutex);
- if (chip->srb) {
- chip->srb->result = DID_NO_CONNECT << 16;
- spin_lock_irq(host->host_lock);
- scsi_done(dev->chip->srb);
- chip->srb = NULL;
- spin_unlock_irq(host->host_lock);
- }
- mutex_unlock(&dev->dev_mutex);
-
- /* Now we own no commands so it's safe to remove the SCSI host */
- scsi_remove_host(host);
-}
-
-/* Second stage of disconnect processing: deallocate all resources */
-static void release_everything(struct rtsx_dev *dev)
-{
- rtsx_release_resources(dev);
-
- /*
- * Drop our reference to the host; the SCSI core will free it
- * when the refcount becomes 0.
- */
- scsi_host_put(rtsx_to_host(dev));
-}
-
-/* Thread to carry out delayed SCSI-device scanning */
-static int rtsx_scan_thread(void *__dev)
-{
- struct rtsx_dev *dev = __dev;
- struct rtsx_chip *chip = dev->chip;
-
- /* Wait for the timeout to expire or for a disconnect */
- if (delay_use > 0) {
- dev_info(&dev->pci->dev,
- "%s: waiting for device to settle before scanning\n",
- CR_DRIVER_NAME);
- wait_event_interruptible_timeout
- (dev->delay_wait,
- rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT),
- delay_use * HZ);
- }
-
- /* If the device is still connected, perform the scanning */
- if (!rtsx_chk_stat(chip, RTSX_STAT_DISCONNECT)) {
- scsi_scan_host(rtsx_to_host(dev));
- dev_info(&dev->pci->dev, "%s: device scan complete\n",
- CR_DRIVER_NAME);
-
- /* Should we unbind if no devices were detected? */
- }
-
- kthread_complete_and_exit(&dev->scanning_done, 0);
-}
-
-static void rtsx_init_options(struct rtsx_chip *chip)
-{
- chip->vendor_id = chip->rtsx->pci->vendor;
- chip->product_id = chip->rtsx->pci->device;
- chip->adma_mode = 1;
- chip->lun_mc = 0;
- chip->driver_first_load = 1;
-#ifdef HW_AUTO_SWITCH_SD_BUS
- chip->sdio_in_charge = 0;
-#endif
-
- chip->mspro_formatter_enable = 1;
- chip->ignore_sd = 0;
- chip->use_hw_setting = 0;
- chip->lun_mode = DEFAULT_SINGLE;
- chip->auto_delink_en = auto_delink_en;
- chip->ss_en = ss_en;
- chip->ss_idle_period = ss_interval * 1000;
- chip->remote_wakeup_en = 0;
- chip->aspm_l0s_l1_en = aspm_l0s_l1_en;
- chip->dynamic_aspm = 1;
- chip->fpga_sd_sdr104_clk = CLK_200;
- chip->fpga_sd_ddr50_clk = CLK_100;
- chip->fpga_sd_sdr50_clk = CLK_100;
- chip->fpga_sd_hs_clk = CLK_100;
- chip->fpga_mmc_52m_clk = CLK_80;
- chip->fpga_ms_hg_clk = CLK_80;
- chip->fpga_ms_4bit_clk = CLK_80;
- chip->fpga_ms_1bit_clk = CLK_40;
- chip->asic_sd_sdr104_clk = 203;
- chip->asic_sd_sdr50_clk = 98;
- chip->asic_sd_ddr50_clk = 98;
- chip->asic_sd_hs_clk = 98;
- chip->asic_mmc_52m_clk = 98;
- chip->asic_ms_hg_clk = 117;
- chip->asic_ms_4bit_clk = 78;
- chip->asic_ms_1bit_clk = 39;
- chip->ssc_depth_sd_sdr104 = SSC_DEPTH_2M;
- chip->ssc_depth_sd_sdr50 = SSC_DEPTH_2M;
- chip->ssc_depth_sd_ddr50 = SSC_DEPTH_1M;
- chip->ssc_depth_sd_hs = SSC_DEPTH_1M;
- chip->ssc_depth_mmc_52m = SSC_DEPTH_1M;
- chip->ssc_depth_ms_hg = SSC_DEPTH_1M;
- chip->ssc_depth_ms_4bit = SSC_DEPTH_512K;
- chip->ssc_depth_low_speed = SSC_DEPTH_512K;
- chip->ssc_en = 1;
- chip->sd_speed_prior = 0x01040203;
- chip->sd_current_prior = 0x00010203;
- chip->sd_ctl = SD_PUSH_POINT_AUTO |
- SD_SAMPLE_POINT_AUTO |
- SUPPORT_MMC_DDR_MODE;
- chip->sd_ddr_tx_phase = 0;
- chip->mmc_ddr_tx_phase = 1;
- chip->sd_default_tx_phase = 15;
- chip->sd_default_rx_phase = 15;
- chip->pmos_pwr_on_interval = 200;
- chip->sd_voltage_switch_delay = 1000;
- chip->ms_power_class_en = 3;
-
- chip->sd_400mA_ocp_thd = 1;
- chip->sd_800mA_ocp_thd = 5;
- chip->ms_ocp_thd = 2;
-
- chip->card_drive_sel = 0x55;
- chip->sd30_drive_sel_1v8 = 0x03;
- chip->sd30_drive_sel_3v3 = 0x01;
-
- chip->do_delink_before_power_down = 1;
- chip->auto_power_down = 1;
- chip->polling_config = 0;
-
- chip->force_clkreq_0 = 1;
- chip->ft2_fast_mode = 0;
-
- chip->sdio_retry_cnt = 1;
-
- chip->xd_timeout = 2000;
- chip->sd_timeout = 10000;
- chip->ms_timeout = 2000;
- chip->mspro_timeout = 15000;
-
- chip->power_down_in_ss = 1;
-
- chip->sdr104_en = 1;
- chip->sdr50_en = 1;
- chip->ddr50_en = 1;
-
- chip->delink_stage1_step = 100;
- chip->delink_stage2_step = 40;
- chip->delink_stage3_step = 20;
-
- chip->auto_delink_in_L1 = 1;
- chip->blink_led = 1;
- chip->msi_en = msi_en;
- chip->hp_watch_bios_hotplug = 0;
- chip->max_payload = 0;
- chip->phy_voltage = 0;
-
- chip->support_ms_8bit = 1;
- chip->s3_pwr_off_delay = 1000;
-}
-
-static int rtsx_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
-{
- struct Scsi_Host *host;
- struct rtsx_dev *dev;
- int err = 0;
- struct task_struct *th;
-
- dev_dbg(&pci->dev, "Realtek PCI-E card reader detected\n");
-
- err = pcim_enable_device(pci);
- if (err < 0) {
- dev_err(&pci->dev, "PCI enable device failed!\n");
- return err;
- }
-
- err = pci_request_regions(pci, CR_DRIVER_NAME);
- if (err < 0) {
- dev_err(&pci->dev, "PCI request regions for %s failed!\n",
- CR_DRIVER_NAME);
- return err;
- }
-
- /*
- * Ask the SCSI layer to allocate a host structure, with extra
- * space at the end for our private rtsx_dev structure.
- */
- host = scsi_host_alloc(&rtsx_host_template, sizeof(*dev));
- if (!host) {
- dev_err(&pci->dev, "Unable to allocate the scsi host\n");
- err = -ENOMEM;
- goto scsi_host_alloc_fail;
- }
-
- dev = host_to_rtsx(host);
- memset(dev, 0, sizeof(struct rtsx_dev));
-
- dev->chip = kzalloc(sizeof(*dev->chip), GFP_KERNEL);
- if (!dev->chip) {
- err = -ENOMEM;
- goto chip_alloc_fail;
- }
-
- spin_lock_init(&dev->reg_lock);
- mutex_init(&dev->dev_mutex);
- init_completion(&dev->cmnd_ready);
- init_completion(&dev->control_exit);
- init_completion(&dev->polling_exit);
- init_completion(&dev->notify);
- init_completion(&dev->scanning_done);
- init_waitqueue_head(&dev->delay_wait);
-
- dev->pci = pci;
- dev->irq = -1;
-
- dev_info(&pci->dev, "Resource length: 0x%x\n",
- (unsigned int)pci_resource_len(pci, 0));
- dev->addr = pci_resource_start(pci, 0);
- dev->remap_addr = ioremap(dev->addr, pci_resource_len(pci, 0));
- if (!dev->remap_addr) {
- dev_err(&pci->dev, "ioremap error\n");
- err = -ENXIO;
- goto ioremap_fail;
- }
-
- /*
- * Using "unsigned long" cast here to eliminate gcc warning in
- * 64-bit system
- */
- dev_info(&pci->dev, "Original address: 0x%lx, remapped address: 0x%lx\n",
- (unsigned long)(dev->addr), (unsigned long)(dev->remap_addr));
-
- dev->rtsx_resv_buf = dmam_alloc_coherent(&pci->dev, RTSX_RESV_BUF_LEN,
- &dev->rtsx_resv_buf_addr,
- GFP_KERNEL);
- if (!dev->rtsx_resv_buf) {
- dev_err(&pci->dev, "alloc dma buffer fail\n");
- err = -ENXIO;
- goto dma_alloc_fail;
- }
- dev->chip->host_cmds_ptr = dev->rtsx_resv_buf;
- dev->chip->host_cmds_addr = dev->rtsx_resv_buf_addr;
- dev->chip->host_sg_tbl_ptr = dev->rtsx_resv_buf + HOST_CMDS_BUF_LEN;
- dev->chip->host_sg_tbl_addr = dev->rtsx_resv_buf_addr +
- HOST_CMDS_BUF_LEN;
-
- dev->chip->rtsx = dev;
-
- rtsx_init_options(dev->chip);
-
- dev_info(&pci->dev, "pci->irq = %d\n", pci->irq);
-
- if (dev->chip->msi_en) {
- if (pci_alloc_irq_vectors(pci, 1, 1, PCI_IRQ_MSI) < 0)
- dev->chip->msi_en = 0;
- }
-
- if (rtsx_acquire_irq(dev) < 0) {
- err = -EBUSY;
- goto irq_acquire_fail;
- }
-
- pci_set_master(pci);
- synchronize_irq(dev->irq);
-
- rtsx_init_chip(dev->chip);
-
- /*
- * set the supported max_lun and max_id for the scsi host
- * NOTE: the minimal value of max_id is 1
- */
- host->max_id = 1;
- host->max_lun = dev->chip->max_lun;
-
- /* Start up our control thread */
- th = kthread_run(rtsx_control_thread, dev, CR_DRIVER_NAME);
- if (IS_ERR(th)) {
- dev_err(&pci->dev, "Unable to start control thread\n");
- err = PTR_ERR(th);
- goto control_thread_fail;
- }
- dev->ctl_thread = th;
-
- err = scsi_add_host(host, &pci->dev);
- if (err) {
- dev_err(&pci->dev, "Unable to add the scsi host\n");
- goto scsi_add_host_fail;
- }
-
- /* Start up the thread for delayed SCSI-device scanning */
- th = kthread_run(rtsx_scan_thread, dev, "rtsx-scan");
- if (IS_ERR(th)) {
- dev_err(&pci->dev, "Unable to start the device-scanning thread\n");
- complete(&dev->scanning_done);
- err = PTR_ERR(th);
- goto scan_thread_fail;
- }
-
- /* Start up the thread for polling thread */
- th = kthread_run(rtsx_polling_thread, dev, "rtsx-polling");
- if (IS_ERR(th)) {
- dev_err(&pci->dev, "Unable to start the device-polling thread\n");
- err = PTR_ERR(th);
- goto scan_thread_fail;
- }
- dev->polling_thread = th;
-
- pci_set_drvdata(pci, dev);
-
- return 0;
-
- /* We come here if there are any problems */
-scan_thread_fail:
- quiesce_and_remove_host(dev);
-scsi_add_host_fail:
- complete(&dev->cmnd_ready);
- wait_for_completion(&dev->control_exit);
-control_thread_fail:
- free_irq(dev->irq, (void *)dev);
- rtsx_release_chip(dev->chip);
-irq_acquire_fail:
- dev->chip->host_cmds_ptr = NULL;
- dev->chip->host_sg_tbl_ptr = NULL;
- if (dev->chip->msi_en)
- pci_free_irq_vectors(dev->pci);
-dma_alloc_fail:
- iounmap(dev->remap_addr);
-ioremap_fail:
- kfree(dev->chip);
-chip_alloc_fail:
- dev_err(&pci->dev, "%s failed\n", __func__);
- scsi_host_put(host);
-scsi_host_alloc_fail:
- pci_release_regions(pci);
- return err;
-}
-
-static void rtsx_remove(struct pci_dev *pci)
-{
- struct rtsx_dev *dev = pci_get_drvdata(pci);
-
- quiesce_and_remove_host(dev);
- release_everything(dev);
- pci_release_regions(pci);
-}
-
-/* PCI IDs */
-static const struct pci_device_id rtsx_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5208),
- PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0x5288),
- PCI_CLASS_OTHERS << 16, 0xFF0000 },
- { 0, },
-};
-
-MODULE_DEVICE_TABLE(pci, rtsx_ids);
-
-static SIMPLE_DEV_PM_OPS(rtsx_pm_ops, rtsx_suspend, rtsx_resume);
-
-/* pci_driver definition */
-static struct pci_driver rtsx_driver = {
- .name = CR_DRIVER_NAME,
- .id_table = rtsx_ids,
- .probe = rtsx_probe,
- .remove = rtsx_remove,
- .driver.pm = &rtsx_pm_ops,
- .shutdown = rtsx_shutdown,
-};
-
-module_pci_driver(rtsx_driver);
diff --git a/drivers/staging/rts5208/rtsx.h b/drivers/staging/rts5208/rtsx.h
deleted file mode 100644
index ec6f5b07390b..000000000000
--- a/drivers/staging/rts5208/rtsx.h
+++ /dev/null
@@ -1,164 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_H
-#define __REALTEK_RTSX_H
-
-#include <linux/io.h>
-#include <linux/bitops.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/mutex.h>
-#include <linux/cdrom.h>
-#include <linux/workqueue.h>
-#include <linux/timer.h>
-#include <linux/time64.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_devinfo.h>
-#include <scsi/scsi_eh.h>
-#include <scsi/scsi_host.h>
-
-#define CR_DRIVER_NAME "rts5208"
-
-/*
- * macros for easy use
- */
-#define wait_timeout_x(task_state, msecs) \
-do { \
- set_current_state((task_state)); \
- schedule_timeout((msecs) * HZ / 1000); \
-} while (0)
-#define wait_timeout(msecs) wait_timeout_x(TASK_INTERRUPTIBLE, (msecs))
-
-#define STATE_TRANS_NONE 0
-#define STATE_TRANS_CMD 1
-#define STATE_TRANS_BUF 2
-#define STATE_TRANS_SG 3
-
-#define TRANS_NOT_READY 0
-#define TRANS_RESULT_OK 1
-#define TRANS_RESULT_FAIL 2
-
-#define SCSI_LUN(srb) ((srb)->device->lun)
-
-struct rtsx_chip;
-
-struct rtsx_dev {
- struct pci_dev *pci;
-
- /* pci resources */
- unsigned long addr;
- void __iomem *remap_addr;
- int irq;
-
- /* locks */
- spinlock_t reg_lock;
-
- struct task_struct *ctl_thread; /* the control thread */
- struct task_struct *polling_thread; /* the polling thread */
-
- /* mutual exclusion and synchronization structures */
- struct completion cmnd_ready; /* to sleep thread on */
- struct completion control_exit; /* control thread exit */
- struct completion polling_exit; /* polling thread exit */
- struct completion notify; /* thread begin/end */
- struct completion scanning_done; /* wait for scan thread */
-
- wait_queue_head_t delay_wait; /* wait during scan, reset */
- struct mutex dev_mutex;
-
- /* host reserved buffer */
- void *rtsx_resv_buf;
- dma_addr_t rtsx_resv_buf_addr;
-
- char trans_result;
- char trans_state;
-
- struct completion *done;
- /* Whether interrupt handler should care card cd info */
- u32 check_card_cd;
-
- struct rtsx_chip *chip;
-};
-
-/* Convert between rtsx_dev and the corresponding Scsi_Host */
-static inline struct Scsi_Host *rtsx_to_host(struct rtsx_dev *dev)
-{
- return container_of((void *)dev, struct Scsi_Host, hostdata);
-}
-
-static inline struct rtsx_dev *host_to_rtsx(struct Scsi_Host *host)
-{
- return (struct rtsx_dev *)host->hostdata;
-}
-
-#define lock_state(chip) spin_lock_irq(&((chip)->rtsx->reg_lock))
-#define unlock_state(chip) spin_unlock_irq(&((chip)->rtsx->reg_lock))
-
-/* struct scsi_cmnd transfer buffer access utilities */
-enum xfer_buf_dir {TO_XFER_BUF, FROM_XFER_BUF};
-
-#include "rtsx_chip.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "rtsx_sys.h"
-#include "general.h"
-
-static inline void rtsx_writel(struct rtsx_chip *chip, u32 reg, u32 value)
-{
- iowrite32(value, chip->rtsx->remap_addr + reg);
-}
-
-static inline u32 rtsx_readl(struct rtsx_chip *chip, u32 reg)
-{
- return ioread32(chip->rtsx->remap_addr + reg);
-}
-
-static inline void rtsx_writew(struct rtsx_chip *chip, u32 reg, u16 value)
-{
- iowrite16(value, chip->rtsx->remap_addr + reg);
-}
-
-static inline u16 rtsx_readw(struct rtsx_chip *chip, u32 reg)
-{
- return ioread16(chip->rtsx->remap_addr + reg);
-}
-
-static inline void rtsx_writeb(struct rtsx_chip *chip, u32 reg, u8 value)
-{
- iowrite8(value, chip->rtsx->remap_addr + reg);
-}
-
-static inline u8 rtsx_readb(struct rtsx_chip *chip, u32 reg)
-{
- return ioread8((chip)->rtsx->remap_addr + reg);
-}
-
-static inline int rtsx_read_config_byte(struct rtsx_chip *chip, int where, u8 *val)
-{
- return pci_read_config_byte(chip->rtsx->pci, where, val);
-}
-
-static inline int rtsx_write_config_byte(struct rtsx_chip *chip, int where, u8 val)
-{
- return pci_write_config_byte(chip->rtsx->pci, where, val);
-}
-
-#endif /* __REALTEK_RTSX_H */
diff --git a/drivers/staging/rts5208/rtsx_card.c b/drivers/staging/rts5208/rtsx_card.c
deleted file mode 100644
index 326b04756f62..000000000000
--- a/drivers/staging/rts5208/rtsx_card.c
+++ /dev/null
@@ -1,1151 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/kernel.h>
-
-#include "rtsx.h"
-#include "sd.h"
-#include "xd.h"
-#include "ms.h"
-
-void do_remaining_work(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
-#ifdef XD_DELAY_WRITE
- struct xd_info *xd_card = &chip->xd_card;
-#endif
- struct ms_info *ms_card = &chip->ms_card;
-
- if (chip->card_ready & SD_CARD) {
- if (sd_card->seq_mode) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- sd_card->cleanup_counter++;
- } else {
- sd_card->cleanup_counter = 0;
- }
- }
-
-#ifdef XD_DELAY_WRITE
- if (chip->card_ready & XD_CARD) {
- if (xd_card->delay_write.delay_write_flag) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- xd_card->cleanup_counter++;
- } else {
- xd_card->cleanup_counter = 0;
- }
- }
-#endif
-
- if (chip->card_ready & MS_CARD) {
- if (CHK_MSPRO(ms_card)) {
- if (ms_card->seq_mode) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- ms_card->cleanup_counter++;
- } else {
- ms_card->cleanup_counter = 0;
- }
- } else {
-#ifdef MS_DELAY_WRITE
- if (ms_card->delay_write.delay_write_flag) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- ms_card->cleanup_counter++;
- } else {
- ms_card->cleanup_counter = 0;
- }
-#endif
- }
- }
-
- if (sd_card->cleanup_counter > POLLING_WAIT_CNT)
- sd_cleanup_work(chip);
-
- if (xd_card->cleanup_counter > POLLING_WAIT_CNT)
- xd_cleanup_work(chip);
-
- if (ms_card->cleanup_counter > POLLING_WAIT_CNT)
- ms_cleanup_work(chip);
-}
-
-void try_to_switch_sdio_ctrl(struct rtsx_chip *chip)
-{
- u8 reg1 = 0, reg2 = 0;
-
- rtsx_read_register(chip, 0xFF34, &reg1);
- rtsx_read_register(chip, 0xFF38, &reg2);
- dev_dbg(rtsx_dev(chip), "reg 0xFF34: 0x%x, reg 0xFF38: 0x%x\n",
- reg1, reg2);
- if ((reg1 & 0xC0) && (reg2 & 0xC0)) {
- chip->sd_int = 1;
- rtsx_write_register(chip, SDIO_CTRL, 0xFF,
- SDIO_BUS_CTRL | SDIO_CD_CTRL);
- rtsx_write_register(chip, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, LDO_ON);
- }
-}
-
-#ifdef SUPPORT_SDIO_ASPM
-void dynamic_configure_sdio_aspm(struct rtsx_chip *chip)
-{
- u8 buf[12], reg;
- int i;
-
- for (i = 0; i < 12; i++)
- rtsx_read_register(chip, 0xFF08 + i, &buf[i]);
- rtsx_read_register(chip, 0xFF25, &reg);
- if ((memcmp(buf, chip->sdio_raw_data, 12) != 0) || (reg & 0x03)) {
- chip->sdio_counter = 0;
- chip->sdio_idle = 0;
- } else {
- if (!chip->sdio_idle) {
- chip->sdio_counter++;
- if (chip->sdio_counter >= SDIO_IDLE_COUNT) {
- chip->sdio_counter = 0;
- chip->sdio_idle = 1;
- }
- }
- }
- memcpy(chip->sdio_raw_data, buf, 12);
-
- if (chip->sdio_idle) {
- if (!chip->sdio_aspm) {
- dev_dbg(rtsx_dev(chip), "SDIO enter ASPM!\n");
- rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC,
- 0x30 | (chip->aspm_level[1] << 2));
- chip->sdio_aspm = 1;
- }
- } else {
- if (chip->sdio_aspm) {
- dev_dbg(rtsx_dev(chip), "SDIO exit ASPM!\n");
- rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, 0x30);
- chip->sdio_aspm = 0;
- }
- }
-}
-#endif
-
-void do_reset_sd_card(struct rtsx_chip *chip)
-{
- int retval;
-
- dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__,
- chip->sd_reset_counter, chip->card2lun[SD_CARD]);
-
- if (chip->card2lun[SD_CARD] >= MAX_ALLOWED_LUN_CNT) {
- clear_bit(SD_NR, &chip->need_reset);
- chip->sd_reset_counter = 0;
- chip->sd_show_cnt = 0;
- return;
- }
-
- chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0;
-
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
-
- retval = reset_sd_card(chip);
- if (chip->need_release & SD_CARD)
- return;
- if (retval == STATUS_SUCCESS) {
- clear_bit(SD_NR, &chip->need_reset);
- chip->sd_reset_counter = 0;
- chip->sd_show_cnt = 0;
- chip->card_ready |= SD_CARD;
- chip->card_fail &= ~SD_CARD;
- chip->rw_card[chip->card2lun[SD_CARD]] = sd_rw;
- } else {
- if (chip->sd_io || chip->sd_reset_counter >= MAX_RESET_CNT) {
- clear_bit(SD_NR, &chip->need_reset);
- chip->sd_reset_counter = 0;
- chip->sd_show_cnt = 0;
- } else {
- chip->sd_reset_counter++;
- }
- chip->card_ready &= ~SD_CARD;
- chip->card_fail |= SD_CARD;
- chip->capacity[chip->card2lun[SD_CARD]] = 0;
- chip->rw_card[chip->card2lun[SD_CARD]] = NULL;
-
- rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
- if (!chip->ft2_fast_mode)
- card_power_off(chip, SD_CARD);
- if (chip->sd_io) {
- chip->sd_int = 0;
- try_to_switch_sdio_ctrl(chip);
- } else {
- disable_card_clock(chip, SD_CARD);
- }
- }
-}
-
-void do_reset_xd_card(struct rtsx_chip *chip)
-{
- int retval;
-
- dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__,
- chip->xd_reset_counter, chip->card2lun[XD_CARD]);
-
- if (chip->card2lun[XD_CARD] >= MAX_ALLOWED_LUN_CNT) {
- clear_bit(XD_NR, &chip->need_reset);
- chip->xd_reset_counter = 0;
- chip->xd_show_cnt = 0;
- return;
- }
-
- chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0;
-
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
-
- retval = reset_xd_card(chip);
- if (chip->need_release & XD_CARD)
- return;
- if (retval == STATUS_SUCCESS) {
- clear_bit(XD_NR, &chip->need_reset);
- chip->xd_reset_counter = 0;
- chip->card_ready |= XD_CARD;
- chip->card_fail &= ~XD_CARD;
- chip->rw_card[chip->card2lun[XD_CARD]] = xd_rw;
- } else {
- if (chip->xd_reset_counter >= MAX_RESET_CNT) {
- clear_bit(XD_NR, &chip->need_reset);
- chip->xd_reset_counter = 0;
- chip->xd_show_cnt = 0;
- } else {
- chip->xd_reset_counter++;
- }
- chip->card_ready &= ~XD_CARD;
- chip->card_fail |= XD_CARD;
- chip->capacity[chip->card2lun[XD_CARD]] = 0;
- chip->rw_card[chip->card2lun[XD_CARD]] = NULL;
-
- rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
- if (!chip->ft2_fast_mode)
- card_power_off(chip, XD_CARD);
- disable_card_clock(chip, XD_CARD);
- }
-}
-
-void do_reset_ms_card(struct rtsx_chip *chip)
-{
- int retval;
-
- dev_dbg(rtsx_dev(chip), "%s: %d, card2lun = 0x%x\n", __func__,
- chip->ms_reset_counter, chip->card2lun[MS_CARD]);
-
- if (chip->card2lun[MS_CARD] >= MAX_ALLOWED_LUN_CNT) {
- clear_bit(MS_NR, &chip->need_reset);
- chip->ms_reset_counter = 0;
- chip->ms_show_cnt = 0;
- return;
- }
-
- chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0;
-
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- rtsx_write_register(chip, SDIO_CTRL, 0xFF, 0);
-
- retval = reset_ms_card(chip);
- if (chip->need_release & MS_CARD)
- return;
- if (retval == STATUS_SUCCESS) {
- clear_bit(MS_NR, &chip->need_reset);
- chip->ms_reset_counter = 0;
- chip->card_ready |= MS_CARD;
- chip->card_fail &= ~MS_CARD;
- chip->rw_card[chip->card2lun[MS_CARD]] = ms_rw;
- } else {
- if (chip->ms_reset_counter >= MAX_RESET_CNT) {
- clear_bit(MS_NR, &chip->need_reset);
- chip->ms_reset_counter = 0;
- chip->ms_show_cnt = 0;
- } else {
- chip->ms_reset_counter++;
- }
- chip->card_ready &= ~MS_CARD;
- chip->card_fail |= MS_CARD;
- chip->capacity[chip->card2lun[MS_CARD]] = 0;
- chip->rw_card[chip->card2lun[MS_CARD]] = NULL;
-
- rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
- if (!chip->ft2_fast_mode)
- card_power_off(chip, MS_CARD);
- disable_card_clock(chip, MS_CARD);
- }
-}
-
-static void release_sdio(struct rtsx_chip *chip)
-{
- if (chip->sd_io) {
- rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
- SD_STOP | SD_CLR_ERR);
-
- if (chip->chip_insert_with_sdio) {
- chip->chip_insert_with_sdio = 0;
-
- if (CHECK_PID(chip, 0x5288))
- rtsx_write_register(chip, 0xFE5A, 0x08, 0x00);
- else
- rtsx_write_register(chip, 0xFE70, 0x80, 0x00);
- }
-
- rtsx_write_register(chip, SDIO_CTRL, SDIO_CD_CTRL, 0);
- chip->sd_io = 0;
- }
-}
-
-void rtsx_power_off_card(struct rtsx_chip *chip)
-{
- if ((chip->card_ready & SD_CARD) || chip->sd_io) {
- sd_cleanup_work(chip);
- sd_power_off_card3v3(chip);
- }
-
- if (chip->card_ready & XD_CARD) {
- xd_cleanup_work(chip);
- xd_power_off_card3v3(chip);
- }
-
- if (chip->card_ready & MS_CARD) {
- ms_cleanup_work(chip);
- ms_power_off_card3v3(chip);
- }
-}
-
-void rtsx_release_cards(struct rtsx_chip *chip)
-{
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if ((chip->card_ready & SD_CARD) || chip->sd_io) {
- if (chip->int_reg & SD_EXIST)
- sd_cleanup_work(chip);
- release_sd_card(chip);
- }
-
- if (chip->card_ready & XD_CARD) {
- if (chip->int_reg & XD_EXIST)
- xd_cleanup_work(chip);
- release_xd_card(chip);
- }
-
- if (chip->card_ready & MS_CARD) {
- if (chip->int_reg & MS_EXIST)
- ms_cleanup_work(chip);
- release_ms_card(chip);
- }
-}
-
-void rtsx_reset_cards(struct rtsx_chip *chip)
-{
- if (!chip->need_reset)
- return;
-
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
-
- rtsx_disable_aspm(chip);
-
- if ((chip->need_reset & SD_CARD) && chip->chip_insert_with_sdio)
- clear_bit(SD_NR, &chip->need_reset);
-
- if (chip->need_reset & XD_CARD) {
- chip->card_exist |= XD_CARD;
-
- if (chip->xd_show_cnt >= MAX_SHOW_CNT)
- do_reset_xd_card(chip);
- else
- chip->xd_show_cnt++;
- }
- if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) {
- if (chip->card_exist & XD_CARD) {
- clear_bit(SD_NR, &chip->need_reset);
- clear_bit(MS_NR, &chip->need_reset);
- }
- }
- if (chip->need_reset & SD_CARD) {
- chip->card_exist |= SD_CARD;
-
- if (chip->sd_show_cnt >= MAX_SHOW_CNT) {
- rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
- do_reset_sd_card(chip);
- } else {
- chip->sd_show_cnt++;
- }
- }
- if (chip->need_reset & MS_CARD) {
- chip->card_exist |= MS_CARD;
-
- if (chip->ms_show_cnt >= MAX_SHOW_CNT)
- do_reset_ms_card(chip);
- else
- chip->ms_show_cnt++;
- }
-}
-
-void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip)
-{
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
-
- if (reset_chip)
- rtsx_reset_chip(chip);
-
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if ((chip->int_reg & SD_EXIST) && (chip->need_reinit & SD_CARD)) {
- release_sdio(chip);
- release_sd_card(chip);
-
- wait_timeout(100);
-
- chip->card_exist |= SD_CARD;
- do_reset_sd_card(chip);
- }
-
- if ((chip->int_reg & XD_EXIST) && (chip->need_reinit & XD_CARD)) {
- release_xd_card(chip);
-
- wait_timeout(100);
-
- chip->card_exist |= XD_CARD;
- do_reset_xd_card(chip);
- }
-
- if ((chip->int_reg & MS_EXIST) && (chip->need_reinit & MS_CARD)) {
- release_ms_card(chip);
-
- wait_timeout(100);
-
- chip->card_exist |= MS_CARD;
- do_reset_ms_card(chip);
- }
-
- chip->need_reinit = 0;
-}
-
-#ifdef DISABLE_CARD_INT
-void card_cd_debounce(struct rtsx_chip *chip, unsigned long *need_reset,
- unsigned long *need_release)
-{
- u8 release_map = 0, reset_map = 0;
-
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if (chip->card_exist) {
- if (chip->card_exist & XD_CARD) {
- if (!(chip->int_reg & XD_EXIST))
- release_map |= XD_CARD;
- } else if (chip->card_exist & SD_CARD) {
- if (!(chip->int_reg & SD_EXIST))
- release_map |= SD_CARD;
- } else if (chip->card_exist & MS_CARD) {
- if (!(chip->int_reg & MS_EXIST))
- release_map |= MS_CARD;
- }
- } else {
- if (chip->int_reg & XD_EXIST)
- reset_map |= XD_CARD;
- else if (chip->int_reg & SD_EXIST)
- reset_map |= SD_CARD;
- else if (chip->int_reg & MS_EXIST)
- reset_map |= MS_CARD;
- }
-
- if (reset_map) {
- int xd_cnt = 0, sd_cnt = 0, ms_cnt = 0;
- int i;
-
- for (i = 0; i < (DEBOUNCE_CNT); i++) {
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if (chip->int_reg & XD_EXIST)
- xd_cnt++;
- else
- xd_cnt = 0;
-
- if (chip->int_reg & SD_EXIST)
- sd_cnt++;
- else
- sd_cnt = 0;
-
- if (chip->int_reg & MS_EXIST)
- ms_cnt++;
- else
- ms_cnt = 0;
-
- wait_timeout(30);
- }
-
- reset_map = 0;
- if (!(chip->card_exist & XD_CARD) &&
- (xd_cnt > (DEBOUNCE_CNT - 1)))
- reset_map |= XD_CARD;
- if (!(chip->card_exist & SD_CARD) &&
- (sd_cnt > (DEBOUNCE_CNT - 1)))
- reset_map |= SD_CARD;
- if (!(chip->card_exist & MS_CARD) &&
- (ms_cnt > (DEBOUNCE_CNT - 1)))
- reset_map |= MS_CARD;
- }
-
- if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN))
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0xC0, 0x00);
-
- if (need_reset)
- *need_reset = reset_map;
- if (need_release)
- *need_release = release_map;
-}
-#endif
-
-void rtsx_init_cards(struct rtsx_chip *chip)
-{
- if (RTSX_TST_DELINK(chip) && (rtsx_get_stat(chip) != RTSX_STAT_SS)) {
- dev_dbg(rtsx_dev(chip), "Reset chip in polling thread!\n");
- rtsx_reset_chip(chip);
- RTSX_CLR_DELINK(chip);
- }
-
-#ifdef DISABLE_CARD_INT
- card_cd_debounce(chip, &chip->need_reset, &chip->need_release);
-#endif
-
- if (chip->need_release) {
- if (CHECK_PID(chip, 0x5288) && CHECK_BARO_PKG(chip, QFN)) {
- if (chip->int_reg & XD_EXIST) {
- clear_bit(SD_NR, &chip->need_release);
- clear_bit(MS_NR, &chip->need_release);
- }
- }
-
- if (!(chip->card_exist & SD_CARD) && !chip->sd_io)
- clear_bit(SD_NR, &chip->need_release);
- if (!(chip->card_exist & XD_CARD))
- clear_bit(XD_NR, &chip->need_release);
- if (!(chip->card_exist & MS_CARD))
- clear_bit(MS_NR, &chip->need_release);
-
- dev_dbg(rtsx_dev(chip), "chip->need_release = 0x%x\n",
- (unsigned int)(chip->need_release));
-
-#ifdef SUPPORT_OCP
- if (chip->need_release) {
- if (chip->ocp_stat & (CARD_OC_NOW | CARD_OC_EVER))
- rtsx_write_register(chip, OCPCLR,
- CARD_OC_INT_CLR |
- CARD_OC_CLR,
- CARD_OC_INT_CLR |
- CARD_OC_CLR);
- chip->ocp_stat = 0;
- }
-#endif
- if (chip->need_release) {
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
- }
-
- if (chip->need_release & SD_CARD) {
- clear_bit(SD_NR, &chip->need_release);
- chip->card_exist &= ~SD_CARD;
- chip->card_ejected &= ~SD_CARD;
- chip->card_fail &= ~SD_CARD;
- CLR_BIT(chip->lun_mc, chip->card2lun[SD_CARD]);
- chip->rw_fail_cnt[chip->card2lun[SD_CARD]] = 0;
- rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
-
- release_sdio(chip);
- release_sd_card(chip);
- }
-
- if (chip->need_release & XD_CARD) {
- clear_bit(XD_NR, &chip->need_release);
- chip->card_exist &= ~XD_CARD;
- chip->card_ejected &= ~XD_CARD;
- chip->card_fail &= ~XD_CARD;
- CLR_BIT(chip->lun_mc, chip->card2lun[XD_CARD]);
- chip->rw_fail_cnt[chip->card2lun[XD_CARD]] = 0;
-
- release_xd_card(chip);
-
- if (CHECK_PID(chip, 0x5288) &&
- CHECK_BARO_PKG(chip, QFN))
- rtsx_write_register(chip, HOST_SLEEP_STATE,
- 0xC0, 0xC0);
- }
-
- if (chip->need_release & MS_CARD) {
- clear_bit(MS_NR, &chip->need_release);
- chip->card_exist &= ~MS_CARD;
- chip->card_ejected &= ~MS_CARD;
- chip->card_fail &= ~MS_CARD;
- CLR_BIT(chip->lun_mc, chip->card2lun[MS_CARD]);
- chip->rw_fail_cnt[chip->card2lun[MS_CARD]] = 0;
-
- release_ms_card(chip);
- }
-
- dev_dbg(rtsx_dev(chip), "chip->card_exist = 0x%x\n",
- chip->card_exist);
-
- if (!chip->card_exist)
- turn_off_led(chip, LED_GPIO);
- }
-
- if (chip->need_reset) {
- dev_dbg(rtsx_dev(chip), "chip->need_reset = 0x%x\n",
- (unsigned int)(chip->need_reset));
-
- rtsx_reset_cards(chip);
- }
-
- if (chip->need_reinit) {
- dev_dbg(rtsx_dev(chip), "chip->need_reinit = 0x%x\n",
- (unsigned int)(chip->need_reinit));
-
- rtsx_reinit_cards(chip, 0);
- }
-}
-
-int switch_ssc_clock(struct rtsx_chip *chip, int clk)
-{
- int retval;
- u8 n = (u8)(clk - 2), min_n, max_n;
- u8 mcu_cnt, div, max_div, ssc_depth, ssc_depth_mask;
- int sd_vpclk_phase_reset = 0;
-
- if (chip->cur_clk == clk)
- return STATUS_SUCCESS;
-
- min_n = 60;
- max_n = 120;
- max_div = CLK_DIV_4;
-
- dev_dbg(rtsx_dev(chip), "Switch SSC clock to %dMHz (cur_clk = %d)\n",
- clk, chip->cur_clk);
-
- if (clk <= 2 || n > max_n)
- return STATUS_FAIL;
-
- mcu_cnt = (u8)(125 / clk + 3);
- if (mcu_cnt > 7)
- mcu_cnt = 7;
-
- div = CLK_DIV_1;
- while ((n < min_n) && (div < max_div)) {
- n = (n + 2) * 2 - 2;
- div++;
- }
- dev_dbg(rtsx_dev(chip), "n = %d, div = %d\n", n, div);
-
- if (chip->ssc_en) {
- ssc_depth = 0x01;
- n -= 2;
- } else {
- ssc_depth = 0;
- }
-
- ssc_depth_mask = 0x03;
-
- dev_dbg(rtsx_dev(chip), "ssc_depth = %d\n", ssc_depth);
-
- rtsx_init_cmd(chip);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_CTL, CLK_LOW_FREQ, CLK_LOW_FREQ);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CLK_DIV, 0xFF, (div << 4) | mcu_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL2, ssc_depth_mask, ssc_depth);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_DIV_N_0, 0xFF, n);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SSC_CTL1, SSC_RSTB, SSC_RSTB);
- if (sd_vpclk_phase_reset) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, PHASE_NOT_RESET);
- }
-
- retval = rtsx_send_cmd(chip, 0, WAIT_TIME);
- if (retval < 0)
- return STATUS_ERROR;
-
- udelay(10);
- retval = rtsx_write_register(chip, CLK_CTL, CLK_LOW_FREQ, 0);
- if (retval)
- return retval;
-
- chip->cur_clk = clk;
-
- return STATUS_SUCCESS;
-}
-
-int switch_normal_clock(struct rtsx_chip *chip, int clk)
-{
- int retval;
- u8 sel, div, mcu_cnt;
- int sd_vpclk_phase_reset = 0;
-
- if (chip->cur_clk == clk)
- return STATUS_SUCCESS;
-
- switch (clk) {
- case CLK_20:
- dev_dbg(rtsx_dev(chip), "Switch clock to 20MHz\n");
- sel = SSC_80;
- div = CLK_DIV_4;
- mcu_cnt = 7;
- break;
-
- case CLK_30:
- dev_dbg(rtsx_dev(chip), "Switch clock to 30MHz\n");
- sel = SSC_120;
- div = CLK_DIV_4;
- mcu_cnt = 7;
- break;
-
- case CLK_40:
- dev_dbg(rtsx_dev(chip), "Switch clock to 40MHz\n");
- sel = SSC_80;
- div = CLK_DIV_2;
- mcu_cnt = 7;
- break;
-
- case CLK_50:
- dev_dbg(rtsx_dev(chip), "Switch clock to 50MHz\n");
- sel = SSC_100;
- div = CLK_DIV_2;
- mcu_cnt = 6;
- break;
-
- case CLK_60:
- dev_dbg(rtsx_dev(chip), "Switch clock to 60MHz\n");
- sel = SSC_120;
- div = CLK_DIV_2;
- mcu_cnt = 6;
- break;
-
- case CLK_80:
- dev_dbg(rtsx_dev(chip), "Switch clock to 80MHz\n");
- sel = SSC_80;
- div = CLK_DIV_1;
- mcu_cnt = 5;
- break;
-
- case CLK_100:
- dev_dbg(rtsx_dev(chip), "Switch clock to 100MHz\n");
- sel = SSC_100;
- div = CLK_DIV_1;
- mcu_cnt = 5;
- break;
-
- case CLK_120:
- dev_dbg(rtsx_dev(chip), "Switch clock to 120MHz\n");
- sel = SSC_120;
- div = CLK_DIV_1;
- mcu_cnt = 5;
- break;
-
- case CLK_150:
- dev_dbg(rtsx_dev(chip), "Switch clock to 150MHz\n");
- sel = SSC_150;
- div = CLK_DIV_1;
- mcu_cnt = 4;
- break;
-
- case CLK_200:
- dev_dbg(rtsx_dev(chip), "Switch clock to 200MHz\n");
- sel = SSC_200;
- div = CLK_DIV_1;
- mcu_cnt = 4;
- break;
-
- default:
- dev_dbg(rtsx_dev(chip), "Try to switch to an illegal clock (%d)\n",
- clk);
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, CLK_CTL, 0xFF, CLK_LOW_FREQ);
- if (retval)
- return retval;
- if (sd_vpclk_phase_reset) {
- retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, 0);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SD_VPCLK1_CTL,
- PHASE_NOT_RESET, 0);
- if (retval)
- return retval;
- }
- retval = rtsx_write_register(chip, CLK_DIV, 0xFF,
- (div << 4) | mcu_cnt);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CLK_SEL, 0xFF, sel);
- if (retval)
- return retval;
-
- if (sd_vpclk_phase_reset) {
- udelay(200);
- retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, PHASE_NOT_RESET);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SD_VPCLK1_CTL,
- PHASE_NOT_RESET, PHASE_NOT_RESET);
- if (retval)
- return retval;
- udelay(200);
- }
- retval = rtsx_write_register(chip, CLK_CTL, 0xFF, 0);
- if (retval)
- return retval;
-
- chip->cur_clk = clk;
-
- return STATUS_SUCCESS;
-}
-
-void trans_dma_enable(enum dma_data_direction dir, struct rtsx_chip *chip,
- u32 byte_cnt, u8 pack_size)
-{
- if (pack_size > DMA_1024)
- pack_size = DMA_512;
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, IRQSTAT0, DMA_DONE_INT, DMA_DONE_INT);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC3, 0xFF, (u8)(byte_cnt >> 24));
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC2, 0xFF, (u8)(byte_cnt >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC1, 0xFF, (u8)(byte_cnt >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMATC0, 0xFF, (u8)byte_cnt);
-
- if (dir == DMA_FROM_DEVICE) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL,
- 0x03 | DMA_PACK_SIZE_MASK,
- DMA_DIR_FROM_CARD | DMA_EN | pack_size);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, DMACTL,
- 0x03 | DMA_PACK_SIZE_MASK,
- DMA_DIR_TO_CARD | DMA_EN | pack_size);
- }
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-}
-
-int enable_card_clock(struct rtsx_chip *chip, u8 card)
-{
- int retval;
- u8 clk_en = 0;
-
- if (card & XD_CARD)
- clk_en |= XD_CLK_EN;
- if (card & SD_CARD)
- clk_en |= SD_CLK_EN;
- if (card & MS_CARD)
- clk_en |= MS_CLK_EN;
-
- retval = rtsx_write_register(chip, CARD_CLK_EN, clk_en, clk_en);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int disable_card_clock(struct rtsx_chip *chip, u8 card)
-{
- int retval;
- u8 clk_en = 0;
-
- if (card & XD_CARD)
- clk_en |= XD_CLK_EN;
- if (card & SD_CARD)
- clk_en |= SD_CLK_EN;
- if (card & MS_CARD)
- clk_en |= MS_CLK_EN;
-
- retval = rtsx_write_register(chip, CARD_CLK_EN, clk_en, 0);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int card_power_on(struct rtsx_chip *chip, u8 card)
-{
- int retval;
- u8 mask, val1, val2;
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && card == MS_CARD) {
- mask = MS_POWER_MASK;
- val1 = MS_PARTIAL_POWER_ON;
- val2 = MS_POWER_ON;
- } else {
- mask = SD_POWER_MASK;
- val1 = SD_PARTIAL_POWER_ON;
- val2 = SD_POWER_ON;
- }
-
- rtsx_init_cmd(chip);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val1);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- udelay(chip->pmos_pwr_on_interval);
-
- rtsx_init_cmd(chip);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PWR_CTL, mask, val2);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int card_power_off(struct rtsx_chip *chip, u8 card)
-{
- int retval;
- u8 mask, val;
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN) && card == MS_CARD) {
- mask = MS_POWER_MASK;
- val = MS_POWER_OFF;
- } else {
- mask = SD_POWER_MASK;
- val = SD_POWER_OFF;
- }
-
- retval = rtsx_write_register(chip, CARD_PWR_CTL, mask, val);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 sec_addr, u16 sec_cnt)
-{
- int retval;
- unsigned int lun = SCSI_LUN(srb);
- int i;
-
- if (!chip->rw_card[lun])
- return STATUS_FAIL;
-
- for (i = 0; i < 3; i++) {
- chip->rw_need_retry = 0;
-
- retval = chip->rw_card[lun](srb, chip, sec_addr, sec_cnt);
- if (retval != STATUS_SUCCESS) {
- if (rtsx_check_chip_exist(chip) != STATUS_SUCCESS) {
- rtsx_release_chip(chip);
- return STATUS_FAIL;
- }
- if (detect_card_cd(chip, chip->cur_card) !=
- STATUS_SUCCESS) {
- return STATUS_FAIL;
- }
-
- if (!chip->rw_need_retry) {
- dev_dbg(rtsx_dev(chip), "RW fail, but no need to retry\n");
- break;
- }
- } else {
- chip->rw_need_retry = 0;
- break;
- }
-
- dev_dbg(rtsx_dev(chip), "Retry RW, (i = %d)\n", i);
- }
-
- return retval;
-}
-
-int card_share_mode(struct rtsx_chip *chip, int card)
-{
- int retval;
- u8 mask, value;
-
- if (CHECK_PID(chip, 0x5208)) {
- mask = CARD_SHARE_MASK;
- if (card == SD_CARD)
- value = CARD_SHARE_48_SD;
- else if (card == MS_CARD)
- value = CARD_SHARE_48_MS;
- else if (card == XD_CARD)
- value = CARD_SHARE_48_XD;
- else
- return STATUS_FAIL;
-
- } else if (CHECK_PID(chip, 0x5288)) {
- mask = 0x03;
- if (card == SD_CARD)
- value = CARD_SHARE_BAROSSA_SD;
- else if (card == MS_CARD)
- value = CARD_SHARE_BAROSSA_MS;
- else if (card == XD_CARD)
- value = CARD_SHARE_BAROSSA_XD;
- else
- return STATUS_FAIL;
-
- } else {
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, CARD_SHARE_MODE, mask, value);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int select_card(struct rtsx_chip *chip, int card)
-{
- int retval;
-
- if (chip->cur_card != card) {
- u8 mod;
-
- if (card == SD_CARD)
- mod = SD_MOD_SEL;
- else if (card == MS_CARD)
- mod = MS_MOD_SEL;
- else if (card == XD_CARD)
- mod = XD_MOD_SEL;
- else if (card == SPI_CARD)
- mod = SPI_MOD_SEL;
- else
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_SELECT, 0x07, mod);
- if (retval)
- return retval;
- chip->cur_card = card;
-
- retval = card_share_mode(chip, card);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-void toggle_gpio(struct rtsx_chip *chip, u8 gpio)
-{
- u8 temp_reg;
-
- rtsx_read_register(chip, CARD_GPIO, &temp_reg);
- temp_reg ^= (0x01 << gpio);
- rtsx_write_register(chip, CARD_GPIO, 0xFF, temp_reg);
-}
-
-void turn_on_led(struct rtsx_chip *chip, u8 gpio)
-{
- if (CHECK_PID(chip, 0x5288))
- rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio),
- (u8)(1 << gpio));
- else
- rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0);
-}
-
-void turn_off_led(struct rtsx_chip *chip, u8 gpio)
-{
- if (CHECK_PID(chip, 0x5288))
- rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio), 0);
- else
- rtsx_write_register(chip, CARD_GPIO, (u8)(1 << gpio),
- (u8)(1 << gpio));
-}
-
-int detect_card_cd(struct rtsx_chip *chip, int card)
-{
- u32 card_cd, status;
-
- if (card == SD_CARD) {
- card_cd = SD_EXIST;
- } else if (card == MS_CARD) {
- card_cd = MS_EXIST;
- } else if (card == XD_CARD) {
- card_cd = XD_EXIST;
- } else {
- dev_dbg(rtsx_dev(chip), "Wrong card type: 0x%x\n", card);
- return STATUS_FAIL;
- }
-
- status = rtsx_readl(chip, RTSX_BIPR);
- if (!(status & card_cd))
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int check_card_exist(struct rtsx_chip *chip, unsigned int lun)
-{
- if (chip->card_exist & chip->lun2card[lun])
- return 1;
-
- return 0;
-}
-
-int check_card_ready(struct rtsx_chip *chip, unsigned int lun)
-{
- if (chip->card_ready & chip->lun2card[lun])
- return 1;
-
- return 0;
-}
-
-int check_card_wp(struct rtsx_chip *chip, unsigned int lun)
-{
- if (chip->card_wp & chip->lun2card[lun])
- return 1;
-
- return 0;
-}
-
-u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun)
-{
- if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD)
- return (u8)XD_CARD;
- else if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD)
- return (u8)SD_CARD;
- else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD)
- return (u8)MS_CARD;
-
- return 0;
-}
-
-void eject_card(struct rtsx_chip *chip, unsigned int lun)
-{
- do_remaining_work(chip);
-
- if ((chip->card_ready & chip->lun2card[lun]) == SD_CARD) {
- release_sd_card(chip);
- chip->card_ejected |= SD_CARD;
- chip->card_ready &= ~SD_CARD;
- chip->capacity[lun] = 0;
- } else if ((chip->card_ready & chip->lun2card[lun]) == XD_CARD) {
- release_xd_card(chip);
- chip->card_ejected |= XD_CARD;
- chip->card_ready &= ~XD_CARD;
- chip->capacity[lun] = 0;
- } else if ((chip->card_ready & chip->lun2card[lun]) == MS_CARD) {
- release_ms_card(chip);
- chip->card_ejected |= MS_CARD;
- chip->card_ready &= ~MS_CARD;
- chip->capacity[lun] = 0;
- }
-}
diff --git a/drivers/staging/rts5208/rtsx_card.h b/drivers/staging/rts5208/rtsx_card.h
deleted file mode 100644
index 39727371cd7a..000000000000
--- a/drivers/staging/rts5208/rtsx_card.h
+++ /dev/null
@@ -1,1087 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_CARD_H
-#define __REALTEK_RTSX_CARD_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-#include "rtsx_transport.h"
-#include "sd.h"
-
-#define SSC_POWER_DOWN 0x01
-#define SD_OC_POWER_DOWN 0x02
-#define MS_OC_POWER_DOWN 0x04
-#define ALL_POWER_DOWN 0x07
-#define OC_POWER_DOWN 0x06
-
-#define PMOS_STRG_MASK 0x10
-#define PMOS_STRG_800mA 0x10
-#define PMOS_STRG_400mA 0x00
-
-#define POWER_OFF 0x03
-#define PARTIAL_POWER_ON 0x01
-#define POWER_ON 0x00
-
-#define MS_POWER_OFF 0x0C
-#define MS_PARTIAL_POWER_ON 0x04
-#define MS_POWER_ON 0x00
-#define MS_POWER_MASK 0x0C
-
-#define SD_POWER_OFF 0x03
-#define SD_PARTIAL_POWER_ON 0x01
-#define SD_POWER_ON 0x00
-#define SD_POWER_MASK 0x03
-
-#define XD_OUTPUT_EN 0x02
-#define SD_OUTPUT_EN 0x04
-#define MS_OUTPUT_EN 0x08
-#define SPI_OUTPUT_EN 0x10
-
-#define CLK_LOW_FREQ 0x01
-
-#define CLK_DIV_1 0x01
-#define CLK_DIV_2 0x02
-#define CLK_DIV_4 0x03
-#define CLK_DIV_8 0x04
-
-#define SSC_80 0
-#define SSC_100 1
-#define SSC_120 2
-#define SSC_150 3
-#define SSC_200 4
-
-#define XD_CLK_EN 0x02
-#define SD_CLK_EN 0x04
-#define MS_CLK_EN 0x08
-#define SPI_CLK_EN 0x10
-
-#define XD_MOD_SEL 1
-#define SD_MOD_SEL 2
-#define MS_MOD_SEL 3
-#define SPI_MOD_SEL 4
-
-#define CHANGE_CLK 0x01
-
-#define SD_CRC7_ERR 0x80
-#define SD_CRC16_ERR 0x40
-#define SD_CRC_WRITE_ERR 0x20
-#define SD_CRC_WRITE_ERR_MASK 0x1C
-#define GET_CRC_TIME_OUT 0x02
-#define SD_TUNING_COMPARE_ERR 0x01
-
-#define SD_RSP_80CLK_TIMEOUT 0x01
-
-#define SD_CLK_TOGGLE_EN 0x80
-#define SD_CLK_FORCE_STOP 0x40
-#define SD_DAT3_STATUS 0x10
-#define SD_DAT2_STATUS 0x08
-#define SD_DAT1_STATUS 0x04
-#define SD_DAT0_STATUS 0x02
-#define SD_CMD_STATUS 0x01
-
-#define SD_IO_USING_1V8 0x80
-#define SD_IO_USING_3V3 0x7F
-#define TYPE_A_DRIVING 0x00
-#define TYPE_B_DRIVING 0x01
-#define TYPE_C_DRIVING 0x02
-#define TYPE_D_DRIVING 0x03
-
-#define DDR_FIX_RX_DAT 0x00
-#define DDR_VAR_RX_DAT 0x80
-#define DDR_FIX_RX_DAT_EDGE 0x00
-#define DDR_FIX_RX_DAT_14_DELAY 0x40
-#define DDR_FIX_RX_CMD 0x00
-#define DDR_VAR_RX_CMD 0x20
-#define DDR_FIX_RX_CMD_POS_EDGE 0x00
-#define DDR_FIX_RX_CMD_14_DELAY 0x10
-#define SD20_RX_POS_EDGE 0x00
-#define SD20_RX_14_DELAY 0x08
-#define SD20_RX_SEL_MASK 0x08
-
-#define DDR_FIX_TX_CMD_DAT 0x00
-#define DDR_VAR_TX_CMD_DAT 0x80
-#define DDR_FIX_TX_DAT_14_TSU 0x00
-#define DDR_FIX_TX_DAT_12_TSU 0x40
-#define DDR_FIX_TX_CMD_NEG_EDGE 0x00
-#define DDR_FIX_TX_CMD_14_AHEAD 0x20
-#define SD20_TX_NEG_EDGE 0x00
-#define SD20_TX_14_AHEAD 0x10
-#define SD20_TX_SEL_MASK 0x10
-#define DDR_VAR_SDCLK_POL_SWAP 0x01
-
-#define SD_TRANSFER_START 0x80
-#define SD_TRANSFER_END 0x40
-#define SD_STAT_IDLE 0x20
-#define SD_TRANSFER_ERR 0x10
-#define SD_TM_NORMAL_WRITE 0x00
-#define SD_TM_AUTO_WRITE_3 0x01
-#define SD_TM_AUTO_WRITE_4 0x02
-#define SD_TM_AUTO_READ_3 0x05
-#define SD_TM_AUTO_READ_4 0x06
-#define SD_TM_CMD_RSP 0x08
-#define SD_TM_AUTO_WRITE_1 0x09
-#define SD_TM_AUTO_WRITE_2 0x0A
-#define SD_TM_NORMAL_READ 0x0C
-#define SD_TM_AUTO_READ_1 0x0D
-#define SD_TM_AUTO_READ_2 0x0E
-#define SD_TM_AUTO_TUNING 0x0F
-
-#define PHASE_CHANGE 0x80
-#define PHASE_NOT_RESET 0x40
-
-#define DCMPS_CHANGE 0x80
-#define DCMPS_CHANGE_DONE 0x40
-#define DCMPS_ERROR 0x20
-#define DCMPS_CURRENT_PHASE 0x1F
-
-#define SD_CLK_DIVIDE_0 0x00
-#define SD_CLK_DIVIDE_256 0xC0
-#define SD_CLK_DIVIDE_128 0x80
-#define SD_BUS_WIDTH_1 0x00
-#define SD_BUS_WIDTH_4 0x01
-#define SD_BUS_WIDTH_8 0x02
-#define SD_ASYNC_FIFO_NOT_RST 0x10
-#define SD_20_MODE 0x00
-#define SD_DDR_MODE 0x04
-#define SD_30_MODE 0x08
-
-#define SD_CLK_DIVIDE_MASK 0xC0
-
-#define SD_CMD_IDLE 0x80
-
-#define SD_DATA_IDLE 0x80
-
-#define DCM_RESET 0x08
-#define DCM_LOCKED 0x04
-#define DCM_208M 0x00
-#define DCM_TX 0x01
-#define DCM_RX 0x02
-
-#define DRP_START 0x80
-#define DRP_DONE 0x40
-
-#define DRP_WRITE 0x80
-#define DRP_READ 0x00
-#define DCM_WRITE_ADDRESS_50 0x50
-#define DCM_WRITE_ADDRESS_51 0x51
-#define DCM_READ_ADDRESS_00 0x00
-#define DCM_READ_ADDRESS_51 0x51
-
-#define SD_CALCULATE_CRC7 0x00
-#define SD_NO_CALCULATE_CRC7 0x80
-#define SD_CHECK_CRC16 0x00
-#define SD_NO_CHECK_CRC16 0x40
-#define SD_NO_CHECK_WAIT_CRC_TO 0x20
-#define SD_WAIT_BUSY_END 0x08
-#define SD_NO_WAIT_BUSY_END 0x00
-#define SD_CHECK_CRC7 0x00
-#define SD_NO_CHECK_CRC7 0x04
-#define SD_RSP_LEN_0 0x00
-#define SD_RSP_LEN_6 0x01
-#define SD_RSP_LEN_17 0x02
-#define SD_RSP_TYPE_R0 0x04
-#define SD_RSP_TYPE_R1 0x01
-#define SD_RSP_TYPE_R1b 0x09
-#define SD_RSP_TYPE_R2 0x02
-#define SD_RSP_TYPE_R3 0x05
-#define SD_RSP_TYPE_R4 0x05
-#define SD_RSP_TYPE_R5 0x01
-#define SD_RSP_TYPE_R6 0x01
-#define SD_RSP_TYPE_R7 0x01
-
-#define SD_RSP_80CLK_TIMEOUT_EN 0x01
-
-#define SAMPLE_TIME_RISING 0x00
-#define SAMPLE_TIME_FALLING 0x80
-#define PUSH_TIME_DEFAULT 0x00
-#define PUSH_TIME_ODD 0x40
-#define NO_EXTEND_TOGGLE 0x00
-#define EXTEND_TOGGLE_CHK 0x20
-#define MS_BUS_WIDTH_1 0x00
-#define MS_BUS_WIDTH_4 0x10
-#define MS_BUS_WIDTH_8 0x18
-#define MS_2K_SECTOR_MODE 0x04
-#define MS_512_SECTOR_MODE 0x00
-#define MS_TOGGLE_TIMEOUT_EN 0x00
-#define MS_TOGGLE_TIMEOUT_DISEN 0x01
-#define MS_NO_CHECK_INT 0x02
-
-#define WAIT_INT 0x80
-#define NO_WAIT_INT 0x00
-#define NO_AUTO_READ_INT_REG 0x00
-#define AUTO_READ_INT_REG 0x40
-#define MS_CRC16_ERR 0x20
-#define MS_RDY_TIMEOUT 0x10
-#define MS_INT_CMDNK 0x08
-#define MS_INT_BREQ 0x04
-#define MS_INT_ERR 0x02
-#define MS_INT_CED 0x01
-
-#define MS_TRANSFER_START 0x80
-#define MS_TRANSFER_END 0x40
-#define MS_TRANSFER_ERR 0x20
-#define MS_BS_STATE 0x10
-#define MS_TM_READ_BYTES 0x00
-#define MS_TM_NORMAL_READ 0x01
-#define MS_TM_WRITE_BYTES 0x04
-#define MS_TM_NORMAL_WRITE 0x05
-#define MS_TM_AUTO_READ 0x08
-#define MS_TM_AUTO_WRITE 0x0C
-
-#define CARD_SHARE_MASK 0x0F
-#define CARD_SHARE_MULTI_LUN 0x00
-#define CARD_SHARE_NORMAL 0x00
-#define CARD_SHARE_48_XD 0x02
-#define CARD_SHARE_48_SD 0x04
-#define CARD_SHARE_48_MS 0x08
-#define CARD_SHARE_BAROSSA_XD 0x00
-#define CARD_SHARE_BAROSSA_SD 0x01
-#define CARD_SHARE_BAROSSA_MS 0x02
-
-#define MS_DRIVE_8 0x00
-#define MS_DRIVE_4 0x40
-#define MS_DRIVE_12 0x80
-#define SD_DRIVE_8 0x00
-#define SD_DRIVE_4 0x10
-#define SD_DRIVE_12 0x20
-#define XD_DRIVE_8 0x00
-#define XD_DRIVE_4 0x04
-#define XD_DRIVE_12 0x08
-
-#define SPI_STOP 0x01
-#define XD_STOP 0x02
-#define SD_STOP 0x04
-#define MS_STOP 0x08
-#define SPI_CLR_ERR 0x10
-#define XD_CLR_ERR 0x20
-#define SD_CLR_ERR 0x40
-#define MS_CLR_ERR 0x80
-
-#define CRC_FIX_CLK (0x00 << 0)
-#define CRC_VAR_CLK0 (0x01 << 0)
-#define CRC_VAR_CLK1 (0x02 << 0)
-#define SD30_FIX_CLK (0x00 << 2)
-#define SD30_VAR_CLK0 (0x01 << 2)
-#define SD30_VAR_CLK1 (0x02 << 2)
-#define SAMPLE_FIX_CLK (0x00 << 4)
-#define SAMPLE_VAR_CLK0 (0x01 << 4)
-#define SAMPLE_VAR_CLK1 (0x02 << 4)
-
-#define SDIO_VER_20 0x80
-#define SDIO_VER_10 0x00
-#define SDIO_VER_CHG 0x40
-#define SDIO_BUS_AUTO_SWITCH 0x10
-
-#define PINGPONG_BUFFER 0x01
-#define RING_BUFFER 0x00
-
-#define RB_FLUSH 0x80
-
-#define DMA_DONE_INT_EN 0x80
-#define SUSPEND_INT_EN 0x40
-#define LINK_RDY_INT_EN 0x20
-#define LINK_DOWN_INT_EN 0x10
-
-#define DMA_DONE_INT 0x80
-#define SUSPEND_INT 0x40
-#define LINK_RDY_INT 0x20
-#define LINK_DOWN_INT 0x10
-
-#define MRD_ERR_INT_EN 0x40
-#define MWR_ERR_INT_EN 0x20
-#define SCSI_CMD_INT_EN 0x10
-#define TLP_RCV_INT_EN 0x08
-#define TLP_TRSMT_INT_EN 0x04
-#define MRD_COMPLETE_INT_EN 0x02
-#define MWR_COMPLETE_INT_EN 0x01
-
-#define MRD_ERR_INT 0x40
-#define MWR_ERR_INT 0x20
-#define SCSI_CMD_INT 0x10
-#define TLP_RX_INT 0x08
-#define TLP_TX_INT 0x04
-#define MRD_COMPLETE_INT 0x02
-#define MWR_COMPLETE_INT 0x01
-
-#define MSG_RX_INT_EN 0x08
-#define MRD_RX_INT_EN 0x04
-#define MWR_RX_INT_EN 0x02
-#define CPLD_RX_INT_EN 0x01
-
-#define MSG_RX_INT 0x08
-#define MRD_RX_INT 0x04
-#define MWR_RX_INT 0x02
-#define CPLD_RX_INT 0x01
-
-#define MSG_TX_INT_EN 0x08
-#define MRD_TX_INT_EN 0x04
-#define MWR_TX_INT_EN 0x02
-#define CPLD_TX_INT_EN 0x01
-
-#define MSG_TX_INT 0x08
-#define MRD_TX_INT 0x04
-#define MWR_TX_INT 0x02
-#define CPLD_TX_INT 0x01
-
-#define DMA_RST 0x80
-#define DMA_BUSY 0x04
-#define DMA_DIR_TO_CARD 0x00
-#define DMA_DIR_FROM_CARD 0x02
-#define DMA_EN 0x01
-#define DMA_128 (0 << 4)
-#define DMA_256 (1 << 4)
-#define DMA_512 (2 << 4)
-#define DMA_1024 (3 << 4)
-#define DMA_PACK_SIZE_MASK 0x30
-
-#define XD_PWR_OFF_DELAY0 0x00
-#define XD_PWR_OFF_DELAY1 0x02
-#define XD_PWR_OFF_DELAY2 0x04
-#define XD_PWR_OFF_DELAY3 0x06
-#define XD_AUTO_PWR_OFF_EN 0xF7
-#define XD_NO_AUTO_PWR_OFF 0x08
-
-#define XD_TIME_RWN_1 0x00
-#define XD_TIME_RWN_STEP 0x20
-#define XD_TIME_RW_1 0x00
-#define XD_TIME_RW_STEP 0x04
-#define XD_TIME_SETUP_1 0x00
-#define XD_TIME_SETUP_STEP 0x01
-
-#define XD_ECC2_UNCORRECTABLE 0x80
-#define XD_ECC2_ERROR 0x40
-#define XD_ECC1_UNCORRECTABLE 0x20
-#define XD_ECC1_ERROR 0x10
-#define XD_RDY 0x04
-#define XD_CE_EN 0xFD
-#define XD_CE_DISEN 0x02
-#define XD_WP_EN 0xFE
-#define XD_WP_DISEN 0x01
-
-#define XD_TRANSFER_START 0x80
-#define XD_TRANSFER_END 0x40
-#define XD_PPB_EMPTY 0x20
-#define XD_RESET 0x00
-#define XD_ERASE 0x01
-#define XD_READ_STATUS 0x02
-#define XD_READ_ID 0x03
-#define XD_READ_REDUNDANT 0x04
-#define XD_READ_PAGES 0x05
-#define XD_SET_CMD 0x06
-#define XD_NORMAL_READ 0x07
-#define XD_WRITE_PAGES 0x08
-#define XD_NORMAL_WRITE 0x09
-#define XD_WRITE_REDUNDANT 0x0A
-#define XD_SET_ADDR 0x0B
-
-#define XD_PPB_TO_SIE 0x80
-#define XD_TO_PPB_ONLY 0x00
-#define XD_BA_TRANSFORM 0x40
-#define XD_BA_NO_TRANSFORM 0x00
-#define XD_NO_CALC_ECC 0x20
-#define XD_CALC_ECC 0x00
-#define XD_IGNORE_ECC 0x10
-#define XD_CHECK_ECC 0x00
-#define XD_DIRECT_TO_RB 0x08
-#define XD_ADDR_LENGTH_0 0x00
-#define XD_ADDR_LENGTH_1 0x01
-#define XD_ADDR_LENGTH_2 0x02
-#define XD_ADDR_LENGTH_3 0x03
-#define XD_ADDR_LENGTH_4 0x04
-
-#define XD_GPG 0xFF
-#define XD_BPG 0x00
-
-#define XD_GBLK 0xFF
-#define XD_LATER_BBLK 0xF0
-
-#define XD_ECC2_ALL1 0x80
-#define XD_ECC1_ALL1 0x40
-#define XD_BA2_ALL0 0x20
-#define XD_BA1_ALL0 0x10
-#define XD_BA1_BA2_EQL 0x04
-#define XD_BA2_VALID 0x02
-#define XD_BA1_VALID 0x01
-
-#define XD_PGSTS_ZEROBIT_OVER4 0x00
-#define XD_PGSTS_NOT_FF 0x02
-#define XD_AUTO_CHK_DATA_STATUS 0x01
-
-#define RSTB_MODE_DETECT 0x80
-#define MODE_OUT_VLD 0x40
-#define MODE_OUT_0_NONE 0x00
-#define MODE_OUT_10_NONE 0x04
-#define MODE_OUT_10_47 0x05
-#define MODE_OUT_10_180 0x06
-#define MODE_OUT_10_680 0x07
-#define MODE_OUT_16_NONE 0x08
-#define MODE_OUT_16_47 0x09
-#define MODE_OUT_16_180 0x0A
-#define MODE_OUT_16_680 0x0B
-#define MODE_OUT_NONE_NONE 0x0C
-#define MODE_OUT_NONE_47 0x0D
-#define MODE_OUT_NONE_180 0x0E
-#define MODE_OUT_NONE_680 0x0F
-
-#define CARD_OC_INT_EN 0x20
-#define CARD_DETECT_EN 0x08
-
-#define MS_DETECT_EN 0x80
-#define MS_OCP_INT_EN 0x40
-#define MS_OCP_INT_CLR 0x20
-#define MS_OC_CLR 0x10
-#define SD_DETECT_EN 0x08
-#define SD_OCP_INT_EN 0x04
-#define SD_OCP_INT_CLR 0x02
-#define SD_OC_CLR 0x01
-
-#define CARD_OCP_DETECT 0x80
-#define CARD_OC_NOW 0x08
-#define CARD_OC_EVER 0x04
-
-#define MS_OCP_DETECT 0x80
-#define MS_OC_NOW 0x40
-#define MS_OC_EVER 0x20
-#define SD_OCP_DETECT 0x08
-#define SD_OC_NOW 0x04
-#define SD_OC_EVER 0x02
-
-#define CARD_OC_INT_CLR 0x08
-#define CARD_OC_CLR 0x02
-
-#define SD_OCP_GLITCH_MASK 0x07
-#define SD_OCP_GLITCH_6_4 0x00
-#define SD_OCP_GLITCH_64 0x01
-#define SD_OCP_GLITCH_640 0x02
-#define SD_OCP_GLITCH_1000 0x03
-#define SD_OCP_GLITCH_2000 0x04
-#define SD_OCP_GLITCH_4000 0x05
-#define SD_OCP_GLITCH_8000 0x06
-#define SD_OCP_GLITCH_10000 0x07
-
-#define MS_OCP_GLITCH_MASK 0x70
-#define MS_OCP_GLITCH_6_4 (0x00 << 4)
-#define MS_OCP_GLITCH_64 (0x01 << 4)
-#define MS_OCP_GLITCH_640 (0x02 << 4)
-#define MS_OCP_GLITCH_1000 (0x03 << 4)
-#define MS_OCP_GLITCH_2000 (0x04 << 4)
-#define MS_OCP_GLITCH_4000 (0x05 << 4)
-#define MS_OCP_GLITCH_8000 (0x06 << 4)
-#define MS_OCP_GLITCH_10000 (0x07 << 4)
-
-#define OCP_TIME_60 0x00
-#define OCP_TIME_100 (0x01 << 3)
-#define OCP_TIME_200 (0x02 << 3)
-#define OCP_TIME_400 (0x03 << 3)
-#define OCP_TIME_600 (0x04 << 3)
-#define OCP_TIME_800 (0x05 << 3)
-#define OCP_TIME_1100 (0x06 << 3)
-#define OCP_TIME_MASK 0x38
-
-#define MS_OCP_TIME_60 0x00
-#define MS_OCP_TIME_100 (0x01 << 4)
-#define MS_OCP_TIME_200 (0x02 << 4)
-#define MS_OCP_TIME_400 (0x03 << 4)
-#define MS_OCP_TIME_600 (0x04 << 4)
-#define MS_OCP_TIME_800 (0x05 << 4)
-#define MS_OCP_TIME_1100 (0x06 << 4)
-#define MS_OCP_TIME_MASK 0x70
-
-#define SD_OCP_TIME_60 0x00
-#define SD_OCP_TIME_100 0x01
-#define SD_OCP_TIME_200 0x02
-#define SD_OCP_TIME_400 0x03
-#define SD_OCP_TIME_600 0x04
-#define SD_OCP_TIME_800 0x05
-#define SD_OCP_TIME_1100 0x06
-#define SD_OCP_TIME_MASK 0x07
-
-#define OCP_THD_315_417 0x00
-#define OCP_THD_283_783 (0x01 << 6)
-#define OCP_THD_244_946 (0x02 << 6)
-#define OCP_THD_191_1080 (0x03 << 6)
-#define OCP_THD_MASK 0xC0
-
-#define MS_OCP_THD_450 0x00
-#define MS_OCP_THD_550 (0x01 << 4)
-#define MS_OCP_THD_650 (0x02 << 4)
-#define MS_OCP_THD_750 (0x03 << 4)
-#define MS_OCP_THD_850 (0x04 << 4)
-#define MS_OCP_THD_950 (0x05 << 4)
-#define MS_OCP_THD_1050 (0x06 << 4)
-#define MS_OCP_THD_1150 (0x07 << 4)
-#define MS_OCP_THD_MASK 0x70
-
-#define SD_OCP_THD_450 0x00
-#define SD_OCP_THD_550 0x01
-#define SD_OCP_THD_650 0x02
-#define SD_OCP_THD_750 0x03
-#define SD_OCP_THD_850 0x04
-#define SD_OCP_THD_950 0x05
-#define SD_OCP_THD_1050 0x06
-#define SD_OCP_THD_1150 0x07
-#define SD_OCP_THD_MASK 0x07
-
-#define FPGA_MS_PULL_CTL_EN 0xEF
-#define FPGA_SD_PULL_CTL_EN 0xF7
-#define FPGA_XD_PULL_CTL_EN1 0xFE
-#define FPGA_XD_PULL_CTL_EN2 0xFD
-#define FPGA_XD_PULL_CTL_EN3 0xFB
-
-#define FPGA_MS_PULL_CTL_BIT 0x10
-#define FPGA_SD_PULL_CTL_BIT 0x08
-
-#define BLINK_EN 0x08
-#define LED_GPIO0 (0 << 4)
-#define LED_GPIO1 (1 << 4)
-#define LED_GPIO2 (2 << 4)
-
-#define SDIO_BUS_CTRL 0x01
-#define SDIO_CD_CTRL 0x02
-
-#define SSC_RSTB 0x80
-#define SSC_8X_EN 0x40
-#define SSC_FIX_FRAC 0x20
-#define SSC_SEL_1M 0x00
-#define SSC_SEL_2M 0x08
-#define SSC_SEL_4M 0x10
-#define SSC_SEL_8M 0x18
-
-#define SSC_DEPTH_MASK 0x07
-#define SSC_DEPTH_DISALBE 0x00
-#define SSC_DEPTH_4M 0x01
-#define SSC_DEPTH_2M 0x02
-#define SSC_DEPTH_1M 0x03
-#define SSC_DEPTH_512K 0x04
-#define SSC_DEPTH_256K 0x05
-#define SSC_DEPTH_128K 0x06
-#define SSC_DEPTH_64K 0x07
-
-#define XD_D3_NP 0x00
-#define XD_D3_PD (0x01 << 6)
-#define XD_D3_PU (0x02 << 6)
-#define XD_D2_NP 0x00
-#define XD_D2_PD (0x01 << 4)
-#define XD_D2_PU (0x02 << 4)
-#define XD_D1_NP 0x00
-#define XD_D1_PD (0x01 << 2)
-#define XD_D1_PU (0x02 << 2)
-#define XD_D0_NP 0x00
-#define XD_D0_PD 0x01
-#define XD_D0_PU 0x02
-
-#define SD_D7_NP 0x00
-#define SD_D7_PD (0x01 << 4)
-#define SD_DAT7_PU (0x02 << 4)
-#define SD_CLK_NP 0x00
-#define SD_CLK_PD (0x01 << 2)
-#define SD_CLK_PU (0x02 << 2)
-#define SD_D5_NP 0x00
-#define SD_D5_PD 0x01
-#define SD_D5_PU 0x02
-
-#define MS_D1_NP 0x00
-#define MS_D1_PD (0x01 << 6)
-#define MS_D1_PU (0x02 << 6)
-#define MS_D2_NP 0x00
-#define MS_D2_PD (0x01 << 4)
-#define MS_D2_PU (0x02 << 4)
-#define MS_CLK_NP 0x00
-#define MS_CLK_PD (0x01 << 2)
-#define MS_CLK_PU (0x02 << 2)
-#define MS_D6_NP 0x00
-#define MS_D6_PD 0x01
-#define MS_D6_PU 0x02
-
-#define XD_D7_NP 0x00
-#define XD_D7_PD (0x01 << 6)
-#define XD_D7_PU (0x02 << 6)
-#define XD_D6_NP 0x00
-#define XD_D6_PD (0x01 << 4)
-#define XD_D6_PU (0x02 << 4)
-#define XD_D5_NP 0x00
-#define XD_D5_PD (0x01 << 2)
-#define XD_D5_PU (0x02 << 2)
-#define XD_D4_NP 0x00
-#define XD_D4_PD 0x01
-#define XD_D4_PU 0x02
-
-#define SD_D6_NP 0x00
-#define SD_D6_PD (0x01 << 6)
-#define SD_D6_PU (0x02 << 6)
-#define SD_D0_NP 0x00
-#define SD_D0_PD (0x01 << 4)
-#define SD_D0_PU (0x02 << 4)
-#define SD_D1_NP 0x00
-#define SD_D1_PD 0x01
-#define SD_D1_PU 0x02
-
-#define MS_D3_NP 0x00
-#define MS_D3_PD (0x01 << 6)
-#define MS_D3_PU (0x02 << 6)
-#define MS_D0_NP 0x00
-#define MS_D0_PD (0x01 << 4)
-#define MS_D0_PU (0x02 << 4)
-#define MS_BS_NP 0x00
-#define MS_BS_PD (0x01 << 2)
-#define MS_BS_PU (0x02 << 2)
-
-#define XD_WP_NP 0x00
-#define XD_WP_PD (0x01 << 6)
-#define XD_WP_PU (0x02 << 6)
-#define XD_CE_NP 0x00
-#define XD_CE_PD (0x01 << 3)
-#define XD_CE_PU (0x02 << 3)
-#define XD_CLE_NP 0x00
-#define XD_CLE_PD (0x01 << 1)
-#define XD_CLE_PU (0x02 << 1)
-#define XD_CD_PD 0x00
-#define XD_CD_PU 0x01
-
-#define SD_D4_NP 0x00
-#define SD_D4_PD (0x01 << 6)
-#define SD_D4_PU (0x02 << 6)
-
-#define MS_D7_NP 0x00
-#define MS_D7_PD (0x01 << 6)
-#define MS_D7_PU (0x02 << 6)
-
-#define XD_RDY_NP 0x00
-#define XD_RDY_PD (0x01 << 6)
-#define XD_RDY_PU (0x02 << 6)
-#define XD_WE_NP 0x00
-#define XD_WE_PD (0x01 << 4)
-#define XD_WE_PU (0x02 << 4)
-#define XD_RE_NP 0x00
-#define XD_RE_PD (0x01 << 2)
-#define XD_RE_PU (0x02 << 2)
-#define XD_ALE_NP 0x00
-#define XD_ALE_PD 0x01
-#define XD_ALE_PU 0x02
-
-#define SD_D3_NP 0x00
-#define SD_D3_PD (0x01 << 4)
-#define SD_D3_PU (0x02 << 4)
-#define SD_D2_NP 0x00
-#define SD_D2_PD (0x01 << 2)
-#define SD_D2_PU (0x02 << 2)
-
-#define MS_INS_PD 0x00
-#define MS_INS_PU (0x01 << 7)
-#define SD_WP_NP 0x00
-#define SD_WP_PD (0x01 << 5)
-#define SD_WP_PU (0x02 << 5)
-#define SD_CD_PD 0x00
-#define SD_CD_PU (0x01 << 4)
-#define SD_CMD_NP 0x00
-#define SD_CMD_PD (0x01 << 2)
-#define SD_CMD_PU (0x02 << 2)
-
-#define MS_D5_NP 0x00
-#define MS_D5_PD (0x01 << 2)
-#define MS_D5_PU (0x02 << 2)
-#define MS_D4_NP 0x00
-#define MS_D4_PD 0x01
-#define MS_D4_PU 0x02
-
-#define FORCE_PM_CLOCK 0x10
-#define EN_CLOCK_PM 0x01
-
-#define HOST_ENTER_S3 0x02
-#define HOST_ENTER_S1 0x01
-
-#define AUX_PWR_DETECTED 0x01
-
-#define PHY_DEBUG_MODE 0x01
-
-#define SPI_COMMAND_BIT_8 0xE0
-#define SPI_ADDRESS_BIT_24 0x17
-#define SPI_ADDRESS_BIT_32 0x1F
-
-#define SPI_TRANSFER0_START 0x80
-#define SPI_TRANSFER0_END 0x40
-#define SPI_C_MODE0 0x00
-#define SPI_CA_MODE0 0x01
-#define SPI_CDO_MODE0 0x02
-#define SPI_CDI_MODE0 0x03
-#define SPI_CADO_MODE0 0x04
-#define SPI_CADI_MODE0 0x05
-#define SPI_POLLING_MODE0 0x06
-
-#define SPI_TRANSFER1_START 0x80
-#define SPI_TRANSFER1_END 0x40
-#define SPI_DO_MODE1 0x00
-#define SPI_DI_MODE1 0x01
-
-#define CS_POLARITY_HIGH 0x40
-#define CS_POLARITY_LOW 0x00
-#define DTO_MSB_FIRST 0x00
-#define DTO_LSB_FIRST 0x20
-#define SPI_MASTER 0x00
-#define SPI_SLAVE 0x10
-#define SPI_MODE0 0x00
-#define SPI_MODE1 0x04
-#define SPI_MODE2 0x08
-#define SPI_MODE3 0x0C
-#define SPI_MANUAL 0x00
-#define SPI_HALF_AUTO 0x01
-#define SPI_AUTO 0x02
-#define SPI_EEPROM_AUTO 0x03
-
-#define EDO_TIMING_MASK 0x03
-#define SAMPLE_RISING 0x00
-#define SAMPLE_DELAY_HALF 0x01
-#define SAMPLE_DELAY_ONE 0x02
-#define SAPMLE_DELAY_ONE_HALF 0x03
-#define TCS_MASK 0x0C
-
-#define NOT_BYPASS_SD 0x02
-#define DISABLE_SDIO_FUNC 0x04
-#define SELECT_1LUN 0x08
-
-#define PWR_GATE_EN 0x01
-#define LDO3318_PWR_MASK 0x06
-#define LDO_ON 0x00
-#define LDO_SUSPEND 0x04
-#define LDO_OFF 0x06
-
-#define SD_CFG1 0xFDA0
-#define SD_CFG2 0xFDA1
-#define SD_CFG3 0xFDA2
-#define SD_STAT1 0xFDA3
-#define SD_STAT2 0xFDA4
-#define SD_BUS_STAT 0xFDA5
-#define SD_PAD_CTL 0xFDA6
-#define SD_SAMPLE_POINT_CTL 0xFDA7
-#define SD_PUSH_POINT_CTL 0xFDA8
-#define SD_CMD0 0xFDA9
-#define SD_CMD1 0xFDAA
-#define SD_CMD2 0xFDAB
-#define SD_CMD3 0xFDAC
-#define SD_CMD4 0xFDAD
-#define SD_CMD5 0xFDAE
-#define SD_BYTE_CNT_L 0xFDAF
-#define SD_BYTE_CNT_H 0xFDB0
-#define SD_BLOCK_CNT_L 0xFDB1
-#define SD_BLOCK_CNT_H 0xFDB2
-#define SD_TRANSFER 0xFDB3
-#define SD_CMD_STATE 0xFDB5
-#define SD_DATA_STATE 0xFDB6
-
-#define DCM_DRP_CTL 0xFC23
-#define DCM_DRP_TRIG 0xFC24
-#define DCM_DRP_CFG 0xFC25
-#define DCM_DRP_WR_DATA_L 0xFC26
-#define DCM_DRP_WR_DATA_H 0xFC27
-#define DCM_DRP_RD_DATA_L 0xFC28
-#define DCM_DRP_RD_DATA_H 0xFC29
-#define SD_VPCLK0_CTL 0xFC2A
-#define SD_VPCLK1_CTL 0xFC2B
-#define SD_DCMPS0_CTL 0xFC2C
-#define SD_DCMPS1_CTL 0xFC2D
-#define SD_VPTX_CTL SD_VPCLK0_CTL
-#define SD_VPRX_CTL SD_VPCLK1_CTL
-#define SD_DCMPS_TX_CTL SD_DCMPS0_CTL
-#define SD_DCMPS_RX_CTL SD_DCMPS1_CTL
-
-#define CARD_CLK_SOURCE 0xFC2E
-
-#define CARD_PWR_CTL 0xFD50
-#define CARD_CLK_SWITCH 0xFD51
-#define CARD_SHARE_MODE 0xFD52
-#define CARD_DRIVE_SEL 0xFD53
-#define CARD_STOP 0xFD54
-#define CARD_OE 0xFD55
-#define CARD_AUTO_BLINK 0xFD56
-#define CARD_GPIO_DIR 0xFD57
-#define CARD_GPIO 0xFD58
-
-#define CARD_DATA_SOURCE 0xFD5B
-#define CARD_SELECT 0xFD5C
-#define SD30_DRIVE_SEL 0xFD5E
-
-#define CARD_CLK_EN 0xFD69
-
-#define SDIO_CTRL 0xFD6B
-
-#define FPDCTL 0xFC00
-#define PDINFO 0xFC01
-
-#define CLK_CTL 0xFC02
-#define CLK_DIV 0xFC03
-#define CLK_SEL 0xFC04
-
-#define SSC_DIV_N_0 0xFC0F
-#define SSC_DIV_N_1 0xFC10
-
-#define RCCTL 0xFC14
-
-#define FPGA_PULL_CTL 0xFC1D
-
-#define CARD_PULL_CTL1 0xFD60
-#define CARD_PULL_CTL2 0xFD61
-#define CARD_PULL_CTL3 0xFD62
-#define CARD_PULL_CTL4 0xFD63
-#define CARD_PULL_CTL5 0xFD64
-#define CARD_PULL_CTL6 0xFD65
-
-#define IRQEN0 0xFE20
-#define IRQSTAT0 0xFE21
-#define IRQEN1 0xFE22
-#define IRQSTAT1 0xFE23
-#define TLPRIEN 0xFE24
-#define TLPRISTAT 0xFE25
-#define TLPTIEN 0xFE26
-#define TLPTISTAT 0xFE27
-#define DMATC0 0xFE28
-#define DMATC1 0xFE29
-#define DMATC2 0xFE2A
-#define DMATC3 0xFE2B
-#define DMACTL 0xFE2C
-#define BCTL 0xFE2D
-#define RBBC0 0xFE2E
-#define RBBC1 0xFE2F
-#define RBDAT 0xFE30
-#define RBCTL 0xFE34
-#define CFGADDR0 0xFE35
-#define CFGADDR1 0xFE36
-#define CFGDATA0 0xFE37
-#define CFGDATA1 0xFE38
-#define CFGDATA2 0xFE39
-#define CFGDATA3 0xFE3A
-#define CFGRWCTL 0xFE3B
-#define PHYRWCTL 0xFE3C
-#define PHYDATA0 0xFE3D
-#define PHYDATA1 0xFE3E
-#define PHYADDR 0xFE3F
-#define MSGRXDATA0 0xFE40
-#define MSGRXDATA1 0xFE41
-#define MSGRXDATA2 0xFE42
-#define MSGRXDATA3 0xFE43
-#define MSGTXDATA0 0xFE44
-#define MSGTXDATA1 0xFE45
-#define MSGTXDATA2 0xFE46
-#define MSGTXDATA3 0xFE47
-#define MSGTXCTL 0xFE48
-#define PETXCFG 0xFE49
-
-#define CDRESUMECTL 0xFE52
-#define WAKE_SEL_CTL 0xFE54
-#define PME_FORCE_CTL 0xFE56
-#define ASPM_FORCE_CTL 0xFE57
-#define PM_CLK_FORCE_CTL 0xFE58
-#define PERST_GLITCH_WIDTH 0xFE5C
-#define CHANGE_LINK_STATE 0xFE5B
-#define RESET_LOAD_REG 0xFE5E
-#define HOST_SLEEP_STATE 0xFE60
-#define MAIN_PWR_OFF_CTL 0xFE70 /* RTS5208 */
-
-#define NFTS_TX_CTRL 0xFE72
-
-#define PWR_GATE_CTRL 0xFE75
-#define PWD_SUSPEND_EN 0xFE76
-
-#define EFUSE_CONTENT 0xFE5F
-
-#define XD_INIT 0xFD10
-#define XD_DTCTL 0xFD11
-#define XD_CTL 0xFD12
-#define XD_TRANSFER 0xFD13
-#define XD_CFG 0xFD14
-#define XD_ADDRESS0 0xFD15
-#define XD_ADDRESS1 0xFD16
-#define XD_ADDRESS2 0xFD17
-#define XD_ADDRESS3 0xFD18
-#define XD_ADDRESS4 0xFD19
-#define XD_DAT 0xFD1A
-#define XD_PAGE_CNT 0xFD1B
-#define XD_PAGE_STATUS 0xFD1C
-#define XD_BLOCK_STATUS 0xFD1D
-#define XD_BLOCK_ADDR1_L 0xFD1E
-#define XD_BLOCK_ADDR1_H 0xFD1F
-#define XD_BLOCK_ADDR2_L 0xFD20
-#define XD_BLOCK_ADDR2_H 0xFD21
-#define XD_BYTE_CNT_L 0xFD22
-#define XD_BYTE_CNT_H 0xFD23
-#define XD_PARITY 0xFD24
-#define XD_ECC_BIT1 0xFD25
-#define XD_ECC_BYTE1 0xFD26
-#define XD_ECC_BIT2 0xFD27
-#define XD_ECC_BYTE2 0xFD28
-#define XD_RESERVED0 0xFD29
-#define XD_RESERVED1 0xFD2A
-#define XD_RESERVED2 0xFD2B
-#define XD_RESERVED3 0xFD2C
-#define XD_CHK_DATA_STATUS 0xFD2D
-#define XD_CATCTL 0xFD2E
-
-#define MS_CFG 0xFD40
-#define MS_TPC 0xFD41
-#define MS_TRANS_CFG 0xFD42
-#define MS_TRANSFER 0xFD43
-#define MS_INT_REG 0xFD44
-#define MS_BYTE_CNT 0xFD45
-#define MS_SECTOR_CNT_L 0xFD46
-#define MS_SECTOR_CNT_H 0xFD47
-#define MS_DBUS_H 0xFD48
-
-#define SSC_CTL1 0xFC11
-#define SSC_CTL2 0xFC12
-
-#define OCPCTL 0xFC15
-#define OCPSTAT 0xFC16
-#define OCPCLR 0xFC17 /* 5208 */
-#define OCPPARA1 0xFC18
-#define OCPPARA2 0xFC19
-
-#define EFUSE_OP 0xFC20
-#define EFUSE_CTRL 0xFC21
-#define EFUSE_DATA 0xFC22
-
-#define SPI_COMMAND 0xFD80
-#define SPI_ADDR0 0xFD81
-#define SPI_ADDR1 0xFD82
-#define SPI_ADDR2 0xFD83
-#define SPI_ADDR3 0xFD84
-#define SPI_CA_NUMBER 0xFD85
-#define SPI_LENGTH0 0xFD86
-#define SPI_LENGTH1 0xFD87
-#define SPI_DATA 0xFD88
-#define SPI_DATA_NUMBER 0xFD89
-#define SPI_TRANSFER0 0xFD90
-#define SPI_TRANSFER1 0xFD91
-#define SPI_CONTROL 0xFD92
-#define SPI_SIG 0xFD93
-#define SPI_TCTL 0xFD94
-#define SPI_SLAVE_NUM 0xFD95
-#define SPI_CLK_DIVIDER0 0xFD96
-#define SPI_CLK_DIVIDER1 0xFD97
-
-#define SRAM_BASE 0xE600
-#define RBUF_BASE 0xF400
-#define PPBUF_BASE1 0xF800
-#define PPBUF_BASE2 0xFA00
-#define IMAGE_FLAG_ADDR0 0xCE80
-#define IMAGE_FLAG_ADDR1 0xCE81
-
-#define READ_OP 1
-#define WRITE_OP 2
-
-#define LCTLR 0x80
-
-#define POLLING_WAIT_CNT 1
-#define IDLE_MAX_COUNT 10
-#define SDIO_IDLE_COUNT 10
-
-#define DEBOUNCE_CNT 5
-
-void do_remaining_work(struct rtsx_chip *chip);
-void try_to_switch_sdio_ctrl(struct rtsx_chip *chip);
-void do_reset_sd_card(struct rtsx_chip *chip);
-void do_reset_xd_card(struct rtsx_chip *chip);
-void do_reset_ms_card(struct rtsx_chip *chip);
-void rtsx_power_off_card(struct rtsx_chip *chip);
-void rtsx_release_cards(struct rtsx_chip *chip);
-void rtsx_reset_cards(struct rtsx_chip *chip);
-void rtsx_reinit_cards(struct rtsx_chip *chip, int reset_chip);
-void rtsx_init_cards(struct rtsx_chip *chip);
-int switch_ssc_clock(struct rtsx_chip *chip, int clk);
-int switch_normal_clock(struct rtsx_chip *chip, int clk);
-int enable_card_clock(struct rtsx_chip *chip, u8 card);
-int disable_card_clock(struct rtsx_chip *chip, u8 card);
-int card_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 sec_addr, u16 sec_cnt);
-void trans_dma_enable(enum dma_data_direction dir,
- struct rtsx_chip *chip, u32 byte_cnt, u8 pack_size);
-void toggle_gpio(struct rtsx_chip *chip, u8 gpio);
-void turn_on_led(struct rtsx_chip *chip, u8 gpio);
-void turn_off_led(struct rtsx_chip *chip, u8 gpio);
-
-int card_share_mode(struct rtsx_chip *chip, int card);
-int select_card(struct rtsx_chip *chip, int card);
-int detect_card_cd(struct rtsx_chip *chip, int card);
-int check_card_exist(struct rtsx_chip *chip, unsigned int lun);
-int check_card_ready(struct rtsx_chip *chip, unsigned int lun);
-int check_card_wp(struct rtsx_chip *chip, unsigned int lun);
-void eject_card(struct rtsx_chip *chip, unsigned int lun);
-u8 get_lun_card(struct rtsx_chip *chip, unsigned int lun);
-
-static inline u32 get_card_size(struct rtsx_chip *chip, unsigned int lun)
-{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &chip->sd_card;
-
- if ((get_lun_card(chip, lun) == SD_CARD) &&
- (sd_card->sd_lock_status & SD_LOCKED))
- return 0;
-
- return chip->capacity[lun];
-#else
- return chip->capacity[lun];
-#endif
-}
-
-static inline int switch_clock(struct rtsx_chip *chip, int clk)
-{
- int retval = 0;
-
- if (chip->asic_code)
- retval = switch_ssc_clock(chip, clk);
- else
- retval = switch_normal_clock(chip, clk);
-
- return retval;
-}
-
-int card_power_on(struct rtsx_chip *chip, u8 card);
-int card_power_off(struct rtsx_chip *chip, u8 card);
-
-static inline int card_power_off_all(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = rtsx_write_register(chip, CARD_PWR_CTL, 0x0F, 0x0F);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static inline void rtsx_clear_xd_error(struct rtsx_chip *chip)
-{
- rtsx_write_register(chip, CARD_STOP, XD_STOP | XD_CLR_ERR,
- XD_STOP | XD_CLR_ERR);
-}
-
-static inline void rtsx_clear_sd_error(struct rtsx_chip *chip)
-{
- rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
- SD_STOP | SD_CLR_ERR);
-}
-
-static inline void rtsx_clear_ms_error(struct rtsx_chip *chip)
-{
- rtsx_write_register(chip, CARD_STOP, MS_STOP | MS_CLR_ERR,
- MS_STOP | MS_CLR_ERR);
-}
-
-static inline void rtsx_clear_spi_error(struct rtsx_chip *chip)
-{
- rtsx_write_register(chip, CARD_STOP, SPI_STOP | SPI_CLR_ERR,
- SPI_STOP | SPI_CLR_ERR);
-}
-
-#ifdef SUPPORT_SDIO_ASPM
-void dynamic_configure_sdio_aspm(struct rtsx_chip *chip);
-#endif
-
-#endif /* __REALTEK_RTSX_CARD_H */
diff --git a/drivers/staging/rts5208/rtsx_chip.c b/drivers/staging/rts5208/rtsx_chip.c
deleted file mode 100644
index 6375032918d4..000000000000
--- a/drivers/staging/rts5208/rtsx_chip.c
+++ /dev/null
@@ -1,2161 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/workqueue.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "sd.h"
-#include "xd.h"
-#include "ms.h"
-
-static void rtsx_calibration(struct rtsx_chip *chip)
-{
- rtsx_write_phy_register(chip, 0x1B, 0x135E);
- wait_timeout(10);
- rtsx_write_phy_register(chip, 0x00, 0x0280);
- rtsx_write_phy_register(chip, 0x01, 0x7112);
- rtsx_write_phy_register(chip, 0x01, 0x7110);
- rtsx_write_phy_register(chip, 0x01, 0x7112);
- rtsx_write_phy_register(chip, 0x01, 0x7113);
- rtsx_write_phy_register(chip, 0x00, 0x0288);
-}
-
-void rtsx_enable_card_int(struct rtsx_chip *chip)
-{
- u32 reg = rtsx_readl(chip, RTSX_BIER);
- int i;
-
- for (i = 0; i <= chip->max_lun; i++) {
- if (chip->lun2card[i] & XD_CARD)
- reg |= XD_INT_EN;
- if (chip->lun2card[i] & SD_CARD)
- reg |= SD_INT_EN;
- if (chip->lun2card[i] & MS_CARD)
- reg |= MS_INT_EN;
- }
- if (chip->hw_bypass_sd)
- reg &= ~((u32)SD_INT_EN);
-
- rtsx_writel(chip, RTSX_BIER, reg);
-}
-
-void rtsx_enable_bus_int(struct rtsx_chip *chip)
-{
- u32 reg = 0;
-#ifndef DISABLE_CARD_INT
- int i;
-#endif
-
- reg = TRANS_OK_INT_EN | TRANS_FAIL_INT_EN;
-
-#ifndef DISABLE_CARD_INT
- for (i = 0; i <= chip->max_lun; i++) {
- dev_dbg(rtsx_dev(chip), "lun2card[%d] = 0x%02x\n",
- i, chip->lun2card[i]);
-
- if (chip->lun2card[i] & XD_CARD)
- reg |= XD_INT_EN;
- if (chip->lun2card[i] & SD_CARD)
- reg |= SD_INT_EN;
- if (chip->lun2card[i] & MS_CARD)
- reg |= MS_INT_EN;
- }
- if (chip->hw_bypass_sd)
- reg &= ~((u32)SD_INT_EN);
-#endif
-
- if (chip->ic_version >= IC_VER_C)
- reg |= DELINK_INT_EN;
-#ifdef SUPPORT_OCP
- reg |= OC_INT_EN;
-#endif
- if (!chip->adma_mode)
- reg |= DATA_DONE_INT_EN;
-
- /* Enable Bus Interrupt */
- rtsx_writel(chip, RTSX_BIER, reg);
-
- dev_dbg(rtsx_dev(chip), "RTSX_BIER: 0x%08x\n", reg);
-}
-
-void rtsx_disable_bus_int(struct rtsx_chip *chip)
-{
- rtsx_writel(chip, RTSX_BIER, 0);
-}
-
-static int rtsx_pre_handle_sdio_old(struct rtsx_chip *chip)
-{
- int retval;
-
- if (chip->ignore_sd && CHK_SDIO_EXIST(chip)) {
- if (chip->asic_code) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL5,
- 0xFF,
- MS_INS_PU | SD_WP_PU |
- SD_CD_PU | SD_CMD_PU);
- if (retval)
- return retval;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- 0xFF,
- FPGA_SD_PULL_CTL_EN);
- if (retval)
- return retval;
- }
- retval = rtsx_write_register(chip, CARD_SHARE_MODE, 0xFF,
- CARD_SHARE_48_SD);
- if (retval)
- return retval;
-
- /* Enable SDIO internal clock */
- retval = rtsx_write_register(chip, 0xFF2C, 0x01, 0x01);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, SDIO_CTRL, 0xFF,
- SDIO_BUS_CTRL | SDIO_CD_CTRL);
- if (retval)
- return retval;
-
- chip->sd_int = 1;
- chip->sd_io = 1;
- } else {
- chip->need_reset |= SD_CARD;
- }
-
- return STATUS_SUCCESS;
-}
-
-#ifdef HW_AUTO_SWITCH_SD_BUS
-static int rtsx_pre_handle_sdio_new(struct rtsx_chip *chip)
-{
- u8 tmp;
- bool sw_bypass_sd = false;
- int retval;
-
- if (chip->driver_first_load) {
- if (CHECK_PID(chip, 0x5288)) {
- retval = rtsx_read_register(chip, 0xFE5A, &tmp);
- if (retval)
- return retval;
- if (tmp & 0x08)
- sw_bypass_sd = true;
- } else if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_read_register(chip, 0xFE70, &tmp);
- if (retval)
- return retval;
- if (tmp & 0x80)
- sw_bypass_sd = true;
- }
- } else {
- if (chip->sdio_in_charge)
- sw_bypass_sd = true;
- }
- dev_dbg(rtsx_dev(chip), "chip->sdio_in_charge = %d\n",
- chip->sdio_in_charge);
- dev_dbg(rtsx_dev(chip), "chip->driver_first_load = %d\n",
- chip->driver_first_load);
- dev_dbg(rtsx_dev(chip), "sw_bypass_sd = %d\n",
- sw_bypass_sd);
-
- if (sw_bypass_sd) {
- u8 cd_toggle_mask = 0;
-
- retval = rtsx_read_register(chip, TLPTISTAT, &tmp);
- if (retval)
- return retval;
- cd_toggle_mask = 0x08;
-
- if (tmp & cd_toggle_mask) {
- /* Disable sdio_bus_auto_switch */
- if (CHECK_PID(chip, 0x5288)) {
- retval = rtsx_write_register(chip, 0xFE5A,
- 0x08, 0x00);
- if (retval)
- return retval;
- } else if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_register(chip, 0xFE70,
- 0x80, 0x00);
- if (retval)
- return retval;
- }
-
- retval = rtsx_write_register(chip, TLPTISTAT, 0xFF,
- tmp);
- if (retval)
- return retval;
-
- chip->need_reset |= SD_CARD;
- } else {
- dev_dbg(rtsx_dev(chip), "Chip inserted with SDIO!\n");
-
- if (chip->asic_code) {
- retval = sd_pull_ctl_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register
- (chip, FPGA_PULL_CTL,
- FPGA_SD_PULL_CTL_BIT | 0x20,
- 0);
- if (retval)
- return retval;
- }
- retval = card_share_mode(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* Enable sdio_bus_auto_switch */
- if (CHECK_PID(chip, 0x5288)) {
- retval = rtsx_write_register(chip, 0xFE5A,
- 0x08, 0x08);
- if (retval)
- return retval;
- } else if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_register(chip, 0xFE70,
- 0x80, 0x80);
- if (retval)
- return retval;
- }
-
- chip->chip_insert_with_sdio = 1;
- chip->sd_io = 1;
- }
- } else {
- retval = rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
- if (retval)
- return retval;
-
- chip->need_reset |= SD_CARD;
- }
-
- return STATUS_SUCCESS;
-}
-#endif
-
-static int rtsx_reset_aspm(struct rtsx_chip *chip)
-{
- int ret;
-
- if (chip->dynamic_aspm) {
- if (!CHK_SDIO_EXIST(chip) || !CHECK_PID(chip, 0x5288))
- return STATUS_SUCCESS;
-
- ret = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFF,
- chip->aspm_l0s_l1_en);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
- }
-
- if (CHECK_PID(chip, 0x5208)) {
- ret = rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF, 0x3F);
- if (ret)
- return ret;
- }
- ret = rtsx_write_config_byte(chip, LCTLR, chip->aspm_l0s_l1_en);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- chip->aspm_level[0] = chip->aspm_l0s_l1_en;
- if (CHK_SDIO_EXIST(chip)) {
- chip->aspm_level[1] = chip->aspm_l0s_l1_en;
- ret = rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
- 0xC0, 0xFF, chip->aspm_l0s_l1_en);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- chip->aspm_enabled = 1;
-
- return STATUS_SUCCESS;
-}
-
-static int rtsx_enable_pcie_intr(struct rtsx_chip *chip)
-{
- int ret;
-
- if (!chip->asic_code || !CHECK_PID(chip, 0x5208)) {
- rtsx_enable_bus_int(chip);
- return STATUS_SUCCESS;
- }
-
- if (chip->phy_debug_mode) {
- ret = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
- if (ret)
- return ret;
- rtsx_disable_bus_int(chip);
- } else {
- rtsx_enable_bus_int(chip);
- }
-
- if (chip->ic_version >= IC_VER_D) {
- u16 reg;
-
- ret = rtsx_read_phy_register(chip, 0x00, &reg);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- reg &= 0xFE7F;
- reg |= 0x80;
- ret = rtsx_write_phy_register(chip, 0x00, reg);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- ret = rtsx_read_phy_register(chip, 0x1C, &reg);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- reg &= 0xFFF7;
- ret = rtsx_write_phy_register(chip, 0x1C, reg);
- if (ret != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (chip->driver_first_load && chip->ic_version < IC_VER_C)
- rtsx_calibration(chip);
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_reset_chip(struct rtsx_chip *chip)
-{
- int retval;
-
- rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
-
- rtsx_disable_aspm(chip);
-
- retval = rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 0x00);
- if (retval)
- return retval;
-
- /* Disable card clock */
- retval = rtsx_write_register(chip, CARD_CLK_EN, 0x1E, 0);
- if (retval)
- return retval;
-
-#ifdef SUPPORT_OCP
- /* SSC power on, OCD power on */
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
- retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN, 0);
- if (retval)
- return retval;
- } else {
- retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN,
- MS_OC_POWER_DOWN);
- if (retval)
- return retval;
- }
-
- retval = rtsx_write_register(chip, OCPPARA1, OCP_TIME_MASK,
- OCP_TIME_800);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, OCPPARA2, OCP_THD_MASK,
- OCP_THD_244_946);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, OCPCTL, 0xFF,
- CARD_OC_INT_EN | CARD_DETECT_EN);
- if (retval)
- return retval;
-#else
- /* OC power down */
- retval = rtsx_write_register(chip, FPDCTL, OC_POWER_DOWN,
- OC_POWER_DOWN);
- if (retval)
- return retval;
-#endif
-
- if (!CHECK_PID(chip, 0x5288)) {
- retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0xFF, 0x03);
- if (retval)
- return retval;
- }
-
- /* Turn off LED */
- retval = rtsx_write_register(chip, CARD_GPIO, 0xFF, 0x03);
- if (retval)
- return retval;
-
- /* Reset delink mode */
- retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0);
- if (retval)
- return retval;
-
- /* Card driving select */
- retval = rtsx_write_register(chip, CARD_DRIVE_SEL, 0xFF,
- chip->card_drive_sel);
- if (retval)
- return retval;
-
-#ifdef LED_AUTO_BLINK
- retval = rtsx_write_register(chip, CARD_AUTO_BLINK, 0xFF,
- LED_BLINK_SPEED | BLINK_EN | LED_GPIO0);
- if (retval)
- return retval;
-#endif
-
- if (chip->asic_code) {
- /* Enable SSC Clock */
- retval = rtsx_write_register(chip, SSC_CTL1, 0xFF,
- SSC_8X_EN | SSC_SEL_4M);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SSC_CTL2, 0xFF, 0x12);
- if (retval)
- return retval;
- }
-
- /*
- * Disable cd_pwr_save (u_force_rst_core_en=0, u_cd_rst_core_en=0)
- * 0xFE5B
- * bit[1] u_cd_rst_core_en rst_value = 0
- * bit[2] u_force_rst_core_en rst_value = 0
- * bit[5] u_mac_phy_rst_n_dbg rst_value = 1
- * bit[4] u_non_sticky_rst_n_dbg rst_value = 0
- */
- retval = rtsx_write_register(chip, CHANGE_LINK_STATE, 0x16, 0x10);
- if (retval)
- return retval;
-
- /* Enable ASPM */
- if (chip->aspm_l0s_l1_en) {
- retval = rtsx_reset_aspm(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_phy_register(chip, 0x07, 0x0129);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- retval = rtsx_write_config_byte(chip, LCTLR,
- chip->aspm_l0s_l1_en);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_config_byte(chip, 0x81, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_SDIO_EXIST(chip)) {
- retval = rtsx_write_cfg_dw(chip,
- CHECK_PID(chip, 0x5288) ? 2 : 1,
- 0xC0, 0xFF00, 0x0100);
-
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (CHECK_PID(chip, 0x5288) && !CHK_SDIO_EXIST(chip)) {
- retval = rtsx_write_cfg_dw(chip, 2, 0xC0, 0xFFFF, 0x0103);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_cfg_dw(chip, 2, 0x84, 0xFF, 0x03);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT,
- LINK_RDY_INT);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, PERST_GLITCH_WIDTH, 0xFF, 0x80);
- if (retval)
- return retval;
-
- retval = rtsx_enable_pcie_intr(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- chip->need_reset = 0;
-
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if (chip->hw_bypass_sd)
- goto nextcard;
- dev_dbg(rtsx_dev(chip), "In %s, chip->int_reg = 0x%x\n", __func__,
- chip->int_reg);
- if (chip->int_reg & SD_EXIST) {
-#ifdef HW_AUTO_SWITCH_SD_BUS
- if (CHECK_PID(chip, 0x5208) && chip->ic_version < IC_VER_C)
- retval = rtsx_pre_handle_sdio_old(chip);
- else
- retval = rtsx_pre_handle_sdio_new(chip);
-
- dev_dbg(rtsx_dev(chip), "chip->need_reset = 0x%x (%s)\n",
- (unsigned int)(chip->need_reset), __func__);
-#else /* HW_AUTO_SWITCH_SD_BUS */
- retval = rtsx_pre_handle_sdio_old(chip);
-#endif /* HW_AUTO_SWITCH_SD_BUS */
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- } else {
- chip->sd_io = 0;
- retval = rtsx_write_register(chip, SDIO_CTRL,
- SDIO_BUS_CTRL | SDIO_CD_CTRL, 0);
- if (retval)
- return retval;
- }
-
-nextcard:
- if (chip->int_reg & XD_EXIST)
- chip->need_reset |= XD_CARD;
- if (chip->int_reg & MS_EXIST)
- chip->need_reset |= MS_CARD;
- if (chip->int_reg & CARD_EXIST) {
- retval = rtsx_write_register(chip, SSC_CTL1, SSC_RSTB,
- SSC_RSTB);
- if (retval)
- return retval;
- }
-
- dev_dbg(rtsx_dev(chip), "In %s, chip->need_reset = 0x%x\n", __func__,
- (unsigned int)(chip->need_reset));
-
- retval = rtsx_write_register(chip, RCCTL, 0x01, 0x00);
- if (retval)
- return retval;
-
- if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
- /* Turn off main power when entering S3/S4 state */
- retval = rtsx_write_register(chip, MAIN_PWR_OFF_CTL, 0x03,
- 0x03);
- if (retval)
- return retval;
- }
-
- if (chip->remote_wakeup_en && !chip->auto_delink_en) {
- retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x07);
- if (retval)
- return retval;
- if (chip->aux_pwr_exist) {
- retval = rtsx_write_register(chip, PME_FORCE_CTL,
- 0xFF, 0x33);
- if (retval)
- return retval;
- }
- } else {
- retval = rtsx_write_register(chip, WAKE_SEL_CTL, 0x07, 0x04);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, PME_FORCE_CTL, 0xFF, 0x30);
- if (retval)
- return retval;
- }
-
- if (CHECK_PID(chip, 0x5208) && chip->ic_version >= IC_VER_D) {
- retval = rtsx_write_register(chip, PETXCFG, 0x1C, 0x14);
- if (retval)
- return retval;
- }
-
- if (chip->asic_code && CHECK_PID(chip, 0x5208)) {
- retval = rtsx_clr_phy_reg_bit(chip, 0x1C, 2);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (chip->ft2_fast_mode) {
- retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF,
- MS_PARTIAL_POWER_ON |
- SD_PARTIAL_POWER_ON);
- if (retval)
- return retval;
- udelay(chip->pmos_pwr_on_interval);
- retval = rtsx_write_register(chip, CARD_PWR_CTL, 0xFF,
- MS_POWER_ON | SD_POWER_ON);
- if (retval)
- return retval;
-
- wait_timeout(200);
- }
-
- /* Reset card */
- rtsx_reset_detected_cards(chip, 0);
-
- chip->driver_first_load = 0;
-
- return STATUS_SUCCESS;
-}
-
-static inline int valid_sd_speed_prior(u32 sd_speed_prior)
-{
- bool valid_para = true;
- int i;
-
- for (i = 0; i < 4; i++) {
- u8 tmp = (u8)(sd_speed_prior >> (i * 8));
-
- if (tmp < 0x01 || tmp > 0x04) {
- valid_para = false;
- break;
- }
- }
-
- return valid_para;
-}
-
-static inline int valid_sd_current_prior(u32 sd_current_prior)
-{
- bool valid_para = true;
- int i;
-
- for (i = 0; i < 4; i++) {
- u8 tmp = (u8)(sd_current_prior >> (i * 8));
-
- if (tmp > 0x03) {
- valid_para = false;
- break;
- }
- }
-
- return valid_para;
-}
-
-static int rts5208_init(struct rtsx_chip *chip)
-{
- int retval;
- u16 reg = 0;
- u8 val = 0;
-
- retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03);
- if (retval)
- return retval;
- retval = rtsx_read_register(chip, CLK_SEL, &val);
- if (retval)
- return retval;
- chip->asic_code = val == 0 ? 1 : 0;
-
- if (chip->asic_code) {
- retval = rtsx_read_phy_register(chip, 0x1C, &reg);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "Value of phy register 0x1C is 0x%x\n",
- reg);
- chip->ic_version = (reg >> 4) & 0x07;
- chip->phy_debug_mode = reg & PHY_DEBUG_MODE ? 1 : 0;
-
- } else {
- retval = rtsx_read_register(chip, 0xFE80, &val);
- if (retval)
- return retval;
- chip->ic_version = val;
- chip->phy_debug_mode = 0;
- }
-
- retval = rtsx_read_register(chip, PDINFO, &val);
- if (retval)
- return retval;
- dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val);
- chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0;
-
- retval = rtsx_read_register(chip, 0xFE50, &val);
- if (retval)
- return retval;
- chip->hw_bypass_sd = val & 0x01 ? 1 : 0;
-
- rtsx_read_config_byte(chip, 0x0E, &val);
- if (val & 0x80)
- SET_SDIO_EXIST(chip);
- else
- CLR_SDIO_EXIST(chip);
-
- if (chip->use_hw_setting) {
- retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val);
- if (retval)
- return retval;
- chip->auto_delink_en = val & 0x80 ? 1 : 0;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int rts5288_init(struct rtsx_chip *chip)
-{
- int retval;
- u8 val = 0, max_func;
- u32 lval = 0;
-
- retval = rtsx_write_register(chip, CLK_SEL, 0x03, 0x03);
- if (retval)
- return retval;
- retval = rtsx_read_register(chip, CLK_SEL, &val);
- if (retval)
- return retval;
- chip->asic_code = val == 0 ? 1 : 0;
-
- chip->ic_version = 0;
- chip->phy_debug_mode = 0;
-
- retval = rtsx_read_register(chip, PDINFO, &val);
- if (retval)
- return retval;
- dev_dbg(rtsx_dev(chip), "PDINFO: 0x%x\n", val);
- chip->aux_pwr_exist = val & AUX_PWR_DETECTED ? 1 : 0;
-
- retval = rtsx_read_register(chip, CARD_SHARE_MODE, &val);
- if (retval)
- return retval;
- dev_dbg(rtsx_dev(chip), "CARD_SHARE_MODE: 0x%x\n", val);
- chip->baro_pkg = val & 0x04 ? QFN : LQFP;
-
- retval = rtsx_read_register(chip, 0xFE5A, &val);
- if (retval)
- return retval;
- chip->hw_bypass_sd = val & 0x10 ? 1 : 0;
-
- retval = rtsx_read_cfg_dw(chip, 0, 0x718, &lval);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- max_func = (u8)((lval >> 29) & 0x07);
- dev_dbg(rtsx_dev(chip), "Max function number: %d\n", max_func);
- if (max_func == 0x02)
- SET_SDIO_EXIST(chip);
- else
- CLR_SDIO_EXIST(chip);
-
- if (chip->use_hw_setting) {
- retval = rtsx_read_register(chip, CHANGE_LINK_STATE, &val);
- if (retval)
- return retval;
- chip->auto_delink_en = val & 0x80 ? 1 : 0;
-
- if (CHECK_BARO_PKG(chip, LQFP))
- chip->lun_mode = SD_MS_1LUN;
- else
- chip->lun_mode = DEFAULT_SINGLE;
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_init_chip(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- struct xd_info *xd_card = &chip->xd_card;
- struct ms_info *ms_card = &chip->ms_card;
- int retval;
- unsigned int i;
-
- dev_dbg(rtsx_dev(chip), "Vendor ID: 0x%04x, Product ID: 0x%04x\n",
- chip->vendor_id, chip->product_id);
-
- chip->ic_version = 0;
-
- memset(xd_card, 0, sizeof(struct xd_info));
- memset(sd_card, 0, sizeof(struct sd_info));
- memset(ms_card, 0, sizeof(struct ms_info));
-
- chip->xd_reset_counter = 0;
- chip->sd_reset_counter = 0;
- chip->ms_reset_counter = 0;
-
- chip->xd_show_cnt = MAX_SHOW_CNT;
- chip->sd_show_cnt = MAX_SHOW_CNT;
- chip->ms_show_cnt = MAX_SHOW_CNT;
-
- chip->sd_io = 0;
- chip->auto_delink_cnt = 0;
- chip->auto_delink_allowed = 1;
- rtsx_set_stat(chip, RTSX_STAT_INIT);
-
- chip->aspm_enabled = 0;
- chip->chip_insert_with_sdio = 0;
- chip->sdio_aspm = 0;
- chip->sdio_idle = 0;
- chip->sdio_counter = 0;
- chip->cur_card = 0;
- chip->phy_debug_mode = 0;
- chip->sdio_func_exist = 0;
- memset(chip->sdio_raw_data, 0, 12);
-
- for (i = 0; i < MAX_ALLOWED_LUN_CNT; i++) {
- set_sense_type(chip, i, SENSE_TYPE_NO_SENSE);
- chip->rw_fail_cnt[i] = 0;
- }
-
- if (!valid_sd_speed_prior(chip->sd_speed_prior))
- chip->sd_speed_prior = 0x01040203;
-
- dev_dbg(rtsx_dev(chip), "sd_speed_prior = 0x%08x\n",
- chip->sd_speed_prior);
-
- if (!valid_sd_current_prior(chip->sd_current_prior))
- chip->sd_current_prior = 0x00010203;
-
- dev_dbg(rtsx_dev(chip), "sd_current_prior = 0x%08x\n",
- chip->sd_current_prior);
-
- if (chip->sd_ddr_tx_phase > 31 || chip->sd_ddr_tx_phase < 0)
- chip->sd_ddr_tx_phase = 0;
-
- if (chip->mmc_ddr_tx_phase > 31 || chip->mmc_ddr_tx_phase < 0)
- chip->mmc_ddr_tx_phase = 0;
-
- retval = rtsx_write_register(chip, FPDCTL, SSC_POWER_DOWN, 0);
- if (retval)
- return retval;
- wait_timeout(200);
- retval = rtsx_write_register(chip, CLK_DIV, 0x07, 0x07);
- if (retval)
- return retval;
- dev_dbg(rtsx_dev(chip), "chip->use_hw_setting = %d\n",
- chip->use_hw_setting);
-
- if (CHECK_PID(chip, 0x5208)) {
- retval = rts5208_init(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- } else if (CHECK_PID(chip, 0x5288)) {
- retval = rts5288_init(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (chip->ss_en == 2)
- chip->ss_en = 0;
-
- dev_dbg(rtsx_dev(chip), "chip->asic_code = %d\n", chip->asic_code);
- dev_dbg(rtsx_dev(chip), "chip->ic_version = 0x%x\n", chip->ic_version);
- dev_dbg(rtsx_dev(chip), "chip->phy_debug_mode = %d\n",
- chip->phy_debug_mode);
- dev_dbg(rtsx_dev(chip), "chip->aux_pwr_exist = %d\n",
- chip->aux_pwr_exist);
- dev_dbg(rtsx_dev(chip), "chip->sdio_func_exist = %d\n",
- chip->sdio_func_exist);
- dev_dbg(rtsx_dev(chip), "chip->hw_bypass_sd = %d\n",
- chip->hw_bypass_sd);
- dev_dbg(rtsx_dev(chip), "chip->aspm_l0s_l1_en = %d\n",
- chip->aspm_l0s_l1_en);
- dev_dbg(rtsx_dev(chip), "chip->lun_mode = %d\n", chip->lun_mode);
- dev_dbg(rtsx_dev(chip), "chip->auto_delink_en = %d\n",
- chip->auto_delink_en);
- dev_dbg(rtsx_dev(chip), "chip->ss_en = %d\n", chip->ss_en);
- dev_dbg(rtsx_dev(chip), "chip->baro_pkg = %d\n", chip->baro_pkg);
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
- chip->card2lun[SD_CARD] = 0;
- chip->card2lun[MS_CARD] = 1;
- chip->card2lun[XD_CARD] = 0xFF;
- chip->lun2card[0] = SD_CARD;
- chip->lun2card[1] = MS_CARD;
- chip->max_lun = 1;
- SET_SDIO_IGNORED(chip);
- } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
- chip->card2lun[SD_CARD] = 0;
- chip->card2lun[MS_CARD] = 0;
- chip->card2lun[XD_CARD] = 0xFF;
- chip->lun2card[0] = SD_CARD | MS_CARD;
- chip->max_lun = 0;
- } else {
- chip->card2lun[XD_CARD] = 0;
- chip->card2lun[SD_CARD] = 0;
- chip->card2lun[MS_CARD] = 0;
- chip->lun2card[0] = XD_CARD | SD_CARD | MS_CARD;
- chip->max_lun = 0;
- }
-
- retval = rtsx_reset_chip(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-void rtsx_release_chip(struct rtsx_chip *chip)
-{
- xd_free_l2p_tbl(chip);
- ms_free_l2p_tbl(chip);
- chip->card_exist = 0;
- chip->card_ready = 0;
-}
-
-#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
-static inline void rtsx_blink_led(struct rtsx_chip *chip)
-{
- if (chip->card_exist && chip->blink_led) {
- if (chip->led_toggle_counter < LED_TOGGLE_INTERVAL) {
- chip->led_toggle_counter++;
- } else {
- chip->led_toggle_counter = 0;
- toggle_gpio(chip, LED_GPIO);
- }
- }
-}
-#endif
-
-static void rtsx_monitor_aspm_config(struct rtsx_chip *chip)
-{
- bool reg_changed, maybe_support_aspm;
- u32 tmp = 0;
- u8 reg0 = 0, reg1 = 0;
-
- maybe_support_aspm = false;
- reg_changed = false;
- rtsx_read_config_byte(chip, LCTLR, &reg0);
- if (chip->aspm_level[0] != reg0) {
- reg_changed = true;
- chip->aspm_level[0] = reg0;
- }
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
- rtsx_read_cfg_dw(chip, 1, 0xC0, &tmp);
- reg1 = (u8)tmp;
- if (chip->aspm_level[1] != reg1) {
- reg_changed = true;
- chip->aspm_level[1] = reg1;
- }
-
- if ((reg0 & 0x03) && (reg1 & 0x03))
- maybe_support_aspm = true;
-
- } else {
- if (reg0 & 0x03)
- maybe_support_aspm = true;
- }
-
- if (reg_changed) {
- if (maybe_support_aspm)
- chip->aspm_l0s_l1_en = 0x03;
-
- dev_dbg(rtsx_dev(chip),
- "aspm_level[0] = 0x%02x, aspm_level[1] = 0x%02x\n",
- chip->aspm_level[0], chip->aspm_level[1]);
-
- if (chip->aspm_l0s_l1_en) {
- chip->aspm_enabled = 1;
- } else {
- chip->aspm_enabled = 0;
- chip->sdio_aspm = 0;
- }
- rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFF,
- 0x30 | chip->aspm_level[0] |
- (chip->aspm_level[1] << 2));
- }
-}
-
-static void rtsx_manage_ocp(struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_OCP
- if (!chip->ocp_int)
- return;
-
- rtsx_read_register(chip, OCPSTAT, &chip->ocp_stat);
-
- if (chip->card_exist & SD_CARD)
- sd_power_off_card3v3(chip);
- else if (chip->card_exist & MS_CARD)
- ms_power_off_card3v3(chip);
- else if (chip->card_exist & XD_CARD)
- xd_power_off_card3v3(chip);
-
- chip->ocp_int = 0;
-#endif
-}
-
-static void rtsx_manage_sd_lock(struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &chip->sd_card;
- u8 val;
-
- if (!sd_card->sd_erase_status)
- return;
-
- if (chip->card_exist & SD_CARD) {
- rtsx_read_register(chip, 0xFD30, &val);
- if (val & 0x02) {
- sd_card->sd_erase_status = SD_NOT_ERASE;
- sd_card->sd_lock_notify = 1;
- chip->need_reinit |= SD_CARD;
- }
- } else {
- sd_card->sd_erase_status = SD_NOT_ERASE;
- }
-#endif
-}
-
-static bool rtsx_is_ss_allowed(struct rtsx_chip *chip)
-{
- u32 val;
-
- if (!chip->ss_en || CHECK_PID(chip, 0x5288))
- return false;
-
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip)) {
- rtsx_read_cfg_dw(chip, 1, 0x04, &val);
- if (val & 0x07)
- return false;
- }
-
- return true;
-}
-
-static void rtsx_manage_ss(struct rtsx_chip *chip)
-{
- if (!rtsx_is_ss_allowed(chip) || chip->sd_io)
- return;
-
- if (rtsx_get_stat(chip) != RTSX_STAT_IDLE) {
- chip->ss_counter = 0;
- return;
- }
-
- if (chip->ss_counter < (chip->ss_idle_period / POLLING_INTERVAL))
- chip->ss_counter++;
- else
- rtsx_exclusive_enter_ss(chip);
-}
-
-static void rtsx_manage_aspm(struct rtsx_chip *chip)
-{
- u8 data;
-
- if (!CHECK_PID(chip, 0x5208))
- return;
-
- rtsx_monitor_aspm_config(chip);
-
-#ifdef SUPPORT_SDIO_ASPM
- if (!CHK_SDIO_EXIST(chip) || CHK_SDIO_IGNORED(chip) ||
- !chip->aspm_l0s_l1_en || !chip->dynamic_aspm)
- return;
-
- if (chip->sd_io) {
- dynamic_configure_sdio_aspm(chip);
- return;
- }
-
- if (chip->sdio_aspm)
- return;
-
- dev_dbg(rtsx_dev(chip), "SDIO enter ASPM!\n");
- data = 0x30 | (chip->aspm_level[1] << 2);
- rtsx_write_register(chip, ASPM_FORCE_CTL, 0xFC, data);
- chip->sdio_aspm = 1;
-#endif
-}
-
-static void rtsx_manage_idle(struct rtsx_chip *chip)
-{
- if (chip->idle_counter < IDLE_MAX_COUNT) {
- chip->idle_counter++;
- return;
- }
-
- if (rtsx_get_stat(chip) == RTSX_STAT_IDLE)
- return;
-
- dev_dbg(rtsx_dev(chip), "Idle state!\n");
- rtsx_set_stat(chip, RTSX_STAT_IDLE);
-
-#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
- chip->led_toggle_counter = 0;
-#endif
- rtsx_force_power_on(chip, SSC_PDCTL);
-
- turn_off_led(chip, LED_GPIO);
-
- if (chip->auto_power_down && !chip->card_ready && !chip->sd_io)
- rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
-}
-
-static void rtsx_manage_2lun_mode(struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_OCP
- u8 sd_oc, ms_oc;
-
- sd_oc = chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER);
- ms_oc = chip->ocp_stat & (MS_OC_NOW | MS_OC_EVER);
-
- if (sd_oc || ms_oc)
- dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
- chip->ocp_stat);
-
- if (sd_oc && (chip->card_exist & SD_CARD)) {
- rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
- card_power_off(chip, SD_CARD);
- chip->card_fail |= SD_CARD;
- }
-
- if (ms_oc && (chip->card_exist & MS_CARD)) {
- rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
- card_power_off(chip, MS_CARD);
- chip->card_fail |= MS_CARD;
- }
-#endif
-}
-
-static void rtsx_manage_1lun_mode(struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_OCP
- if (!(chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)))
- return;
-
- dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
- chip->ocp_stat);
-
- if (chip->card_exist & SD_CARD) {
- rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
- chip->card_fail |= SD_CARD;
- } else if (chip->card_exist & MS_CARD) {
- rtsx_write_register(chip, CARD_OE, MS_OUTPUT_EN, 0);
- chip->card_fail |= MS_CARD;
- } else if (chip->card_exist & XD_CARD) {
- rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
- chip->card_fail |= XD_CARD;
- }
- card_power_off(chip, SD_CARD);
-#endif
-}
-
-static void rtsx_delink_stage1(struct rtsx_chip *chip, int enter_L1,
- int stage3_cnt)
-{
- u8 val;
-
- rtsx_set_stat(chip, RTSX_STAT_DELINK);
-
- if (chip->asic_code && CHECK_PID(chip, 0x5208))
- rtsx_set_phy_reg_bit(chip, 0x1C, 2);
-
- if (chip->card_exist)
- dev_dbg(rtsx_dev(chip), "False card inserted, do force delink\n");
- else
- dev_dbg(rtsx_dev(chip), "No card inserted, do delink\n");
-
- if (enter_L1)
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03, 1);
-
- if (chip->card_exist)
- val = 0x02;
- else
- val = 0x0A;
-
- rtsx_write_register(chip, CHANGE_LINK_STATE, val, val);
-
- if (enter_L1)
- rtsx_enter_L1(chip);
-
- if (chip->card_exist)
- chip->auto_delink_cnt = stage3_cnt + 1;
-}
-
-static void rtsx_delink_stage(struct rtsx_chip *chip)
-{
- int delink_stage1_cnt, delink_stage2_cnt, delink_stage3_cnt;
- int enter_L1;
-
- if (!chip->auto_delink_en || !chip->auto_delink_allowed ||
- chip->card_ready || chip->card_ejected || chip->sd_io) {
- chip->auto_delink_cnt = 0;
- return;
- }
-
- enter_L1 = chip->auto_delink_in_L1 &&
- (chip->aspm_l0s_l1_en || chip->ss_en);
-
- delink_stage1_cnt = chip->delink_stage1_step;
- delink_stage2_cnt = delink_stage1_cnt + chip->delink_stage2_step;
- delink_stage3_cnt = delink_stage2_cnt + chip->delink_stage3_step;
-
- if (chip->auto_delink_cnt > delink_stage3_cnt)
- return;
-
- if (chip->auto_delink_cnt == delink_stage1_cnt)
- rtsx_delink_stage1(chip, enter_L1, delink_stage3_cnt);
-
- if (chip->auto_delink_cnt == delink_stage2_cnt) {
- dev_dbg(rtsx_dev(chip), "Try to do force delink\n");
-
- if (enter_L1)
- rtsx_exit_L1(chip);
-
- if (chip->asic_code && CHECK_PID(chip, 0x5208))
- rtsx_set_phy_reg_bit(chip, 0x1C, 2);
-
- rtsx_write_register(chip, CHANGE_LINK_STATE, 0x0A, 0x0A);
- }
-
- chip->auto_delink_cnt++;
-}
-
-void rtsx_polling_func(struct rtsx_chip *chip)
-{
- if (rtsx_chk_stat(chip, RTSX_STAT_SUSPEND))
- return;
-
- if (rtsx_chk_stat(chip, RTSX_STAT_DELINK))
- goto delink_stage;
-
- if (chip->polling_config) {
- u8 val;
-
- rtsx_read_config_byte(chip, 0, &val);
- }
-
- if (rtsx_chk_stat(chip, RTSX_STAT_SS))
- return;
-
- rtsx_manage_ocp(chip);
-
- rtsx_manage_sd_lock(chip);
-
- rtsx_init_cards(chip);
-
- rtsx_manage_ss(chip);
-
- rtsx_manage_aspm(chip);
-
- rtsx_manage_idle(chip);
-
- switch (rtsx_get_stat(chip)) {
- case RTSX_STAT_RUN:
-#if !defined(LED_AUTO_BLINK) && defined(REGULAR_BLINK)
- rtsx_blink_led(chip);
-#endif
- do_remaining_work(chip);
- break;
-
- case RTSX_STAT_IDLE:
- if (chip->sd_io && !chip->sd_int)
- try_to_switch_sdio_ctrl(chip);
-
- rtsx_enable_aspm(chip);
- break;
-
- default:
- break;
- }
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- rtsx_manage_2lun_mode(chip);
- else
- rtsx_manage_1lun_mode(chip);
-
-delink_stage:
- rtsx_delink_stage(chip);
-}
-
-/**
- * rtsx_stop_cmd - stop command transfer and DMA transfer
- * @chip: Realtek's card reader chip
- * @card: flash card type
- *
- * Stop command transfer and DMA transfer.
- * This function is called in error handler.
- */
-void rtsx_stop_cmd(struct rtsx_chip *chip, int card)
-{
- int i;
-
- for (i = 0; i <= 8; i++) {
- int addr = RTSX_HCBAR + i * 4;
- u32 reg;
-
- reg = rtsx_readl(chip, addr);
- dev_dbg(rtsx_dev(chip), "BAR (0x%02x): 0x%08x\n", addr, reg);
- }
- rtsx_writel(chip, RTSX_HCBCTLR, STOP_CMD);
- rtsx_writel(chip, RTSX_HDBCTLR, STOP_DMA);
-
- for (i = 0; i < 16; i++) {
- u16 addr = 0xFE20 + (u16)i;
- u8 val;
-
- rtsx_read_register(chip, addr, &val);
- dev_dbg(rtsx_dev(chip), "0x%04X: 0x%02x\n", addr, val);
- }
-
- rtsx_write_register(chip, DMACTL, 0x80, 0x80);
- rtsx_write_register(chip, RBCTL, 0x80, 0x80);
-}
-
-#define MAX_RW_REG_CNT 1024
-
-int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data)
-{
- int i;
- u32 val = 3 << 30;
-
- val |= (u32)(addr & 0x3FFF) << 16;
- val |= (u32)mask << 8;
- val |= (u32)data;
-
- rtsx_writel(chip, RTSX_HAIMR, val);
-
- for (i = 0; i < MAX_RW_REG_CNT; i++) {
- val = rtsx_readl(chip, RTSX_HAIMR);
- if ((val & BIT(31)) == 0) {
- if (data != (u8)val)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
- }
- }
-
- return STATUS_TIMEDOUT;
-}
-
-int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data)
-{
- u32 val = 2 << 30;
- int i;
-
- if (data)
- *data = 0;
-
- val |= (u32)(addr & 0x3FFF) << 16;
-
- rtsx_writel(chip, RTSX_HAIMR, val);
-
- for (i = 0; i < MAX_RW_REG_CNT; i++) {
- val = rtsx_readl(chip, RTSX_HAIMR);
- if ((val & BIT(31)) == 0)
- break;
- }
-
- if (i >= MAX_RW_REG_CNT)
- return STATUS_TIMEDOUT;
-
- if (data)
- *data = (u8)(val & 0xFF);
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_write_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 mask,
- u32 val)
-{
- int retval;
- u8 mode = 0, tmp;
- int i;
-
- for (i = 0; i < 4; i++) {
- if (mask & 0xFF) {
- retval = rtsx_write_register(chip, CFGDATA0 + i,
- 0xFF,
- (u8)(val & mask & 0xFF));
- if (retval)
- return retval;
- mode |= (1 << i);
- }
- mask >>= 8;
- val >>= 8;
- }
-
- if (mode) {
- retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CFGADDR1, 0xFF,
- (u8)(addr >> 8));
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CFGRWCTL, 0xFF,
- 0x80 | mode |
- ((func_no & 0x03) << 4));
- if (retval)
- return retval;
-
- for (i = 0; i < MAX_RW_REG_CNT; i++) {
- retval = rtsx_read_register(chip, CFGRWCTL, &tmp);
- if (retval)
- return retval;
- if ((tmp & 0x80) == 0)
- break;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val)
-{
- int retval;
- int i;
- u8 tmp;
- u32 data = 0;
-
- retval = rtsx_write_register(chip, CFGADDR0, 0xFF, (u8)addr);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CFGADDR1, 0xFF, (u8)(addr >> 8));
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CFGRWCTL, 0xFF,
- 0x80 | ((func_no & 0x03) << 4));
- if (retval)
- return retval;
-
- for (i = 0; i < MAX_RW_REG_CNT; i++) {
- retval = rtsx_read_register(chip, CFGRWCTL, &tmp);
- if (retval)
- return retval;
- if ((tmp & 0x80) == 0)
- break;
- }
-
- for (i = 0; i < 4; i++) {
- retval = rtsx_read_register(chip, CFGDATA0 + i, &tmp);
- if (retval)
- return retval;
- data |= (u32)tmp << (i * 8);
- }
-
- if (val)
- *val = data;
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_write_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
- int len)
-{
- u32 *data, *mask;
- u16 offset = addr % 4;
- u16 aligned_addr = addr - offset;
- int dw_len, i, j;
- int retval;
- size_t size;
-
- if (!buf)
- return STATUS_NOMEM;
-
- if ((len + offset) % 4)
- dw_len = (len + offset) / 4 + 1;
- else
- dw_len = (len + offset) / 4;
-
- dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
-
- size = array_size(dw_len, 4);
- data = vzalloc(size);
- if (!data)
- return STATUS_NOMEM;
-
- mask = vzalloc(size);
- if (!mask) {
- vfree(data);
- return STATUS_NOMEM;
- }
-
- j = 0;
- for (i = 0; i < len; i++) {
- mask[j] |= 0xFF << (offset * 8);
- data[j] |= buf[i] << (offset * 8);
- if (++offset == 4) {
- j++;
- offset = 0;
- }
- }
-
- print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, mask, size);
- print_hex_dump_bytes(KBUILD_MODNAME ": ", DUMP_PREFIX_NONE, data, size);
-
- for (i = 0; i < dw_len; i++) {
- retval = rtsx_write_cfg_dw(chip, func, aligned_addr + i * 4,
- mask[i], data[i]);
- if (retval != STATUS_SUCCESS) {
- vfree(data);
- vfree(mask);
- return STATUS_FAIL;
- }
- }
-
- vfree(data);
- vfree(mask);
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_read_cfg_seq(struct rtsx_chip *chip, u8 func, u16 addr, u8 *buf,
- int len)
-{
- u32 *data;
- u16 offset = addr % 4;
- u16 aligned_addr = addr - offset;
- int dw_len, i, j;
- int retval;
-
- if ((len + offset) % 4)
- dw_len = (len + offset) / 4 + 1;
- else
- dw_len = (len + offset) / 4;
-
- dev_dbg(rtsx_dev(chip), "dw_len = %d\n", dw_len);
-
- data = vmalloc(array_size(dw_len, 4));
- if (!data)
- return STATUS_NOMEM;
-
- for (i = 0; i < dw_len; i++) {
- retval = rtsx_read_cfg_dw(chip, func, aligned_addr + i * 4,
- data + i);
- if (retval != STATUS_SUCCESS) {
- vfree(data);
- return STATUS_FAIL;
- }
- }
-
- if (buf) {
- j = 0;
-
- for (i = 0; i < len; i++) {
- buf[i] = (u8)(data[j] >> (offset * 8));
- if (++offset == 4) {
- j++;
- offset = 0;
- }
- }
- }
-
- vfree(data);
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val)
-{
- int retval;
- bool finished = false;
- int i;
- u8 tmp;
-
- retval = rtsx_write_register(chip, PHYDATA0, 0xFF, (u8)val);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, PHYDATA1, 0xFF, (u8)(val >> 8));
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x81);
- if (retval)
- return retval;
-
- for (i = 0; i < 100000; i++) {
- retval = rtsx_read_register(chip, PHYRWCTL, &tmp);
- if (retval)
- return retval;
- if (!(tmp & 0x80)) {
- finished = true;
- break;
- }
- }
-
- if (!finished)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val)
-{
- int retval;
- bool finished = false;
- int i;
- u16 data = 0;
- u8 tmp;
-
- retval = rtsx_write_register(chip, PHYADDR, 0xFF, addr);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, PHYRWCTL, 0xFF, 0x80);
- if (retval)
- return retval;
-
- for (i = 0; i < 100000; i++) {
- retval = rtsx_read_register(chip, PHYRWCTL, &tmp);
- if (retval)
- return retval;
- if (!(tmp & 0x80)) {
- finished = true;
- break;
- }
- }
-
- if (!finished)
- return STATUS_FAIL;
-
- retval = rtsx_read_register(chip, PHYDATA0, &tmp);
- if (retval)
- return retval;
- data = tmp;
- retval = rtsx_read_register(chip, PHYDATA1, &tmp);
- if (retval)
- return retval;
- data |= (u16)tmp << 8;
-
- if (val)
- *val = data;
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val)
-{
- int retval;
- int i;
- u8 data = 0;
-
- retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF, 0x80 | addr);
- if (retval)
- return retval;
-
- for (i = 0; i < 100; i++) {
- retval = rtsx_read_register(chip, EFUSE_CTRL, &data);
- if (retval)
- return retval;
- if (!(data & 0x80))
- break;
- udelay(1);
- }
-
- if (data & 0x80)
- return STATUS_TIMEDOUT;
-
- retval = rtsx_read_register(chip, EFUSE_DATA, &data);
- if (retval)
- return retval;
- if (val)
- *val = data;
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val)
-{
- int retval;
- int i, j;
- u8 data = 0, tmp = 0xFF;
-
- for (i = 0; i < 8; i++) {
- if (val & (u8)(1 << i))
- continue;
-
- tmp &= (~(u8)(1 << i));
- dev_dbg(rtsx_dev(chip), "Write 0x%x to 0x%x\n", tmp, addr);
-
- retval = rtsx_write_register(chip, EFUSE_DATA, 0xFF, tmp);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, EFUSE_CTRL, 0xFF,
- 0xA0 | addr);
- if (retval)
- return retval;
-
- for (j = 0; j < 100; j++) {
- retval = rtsx_read_register(chip, EFUSE_CTRL, &data);
- if (retval)
- return retval;
- if (!(data & 0x80))
- break;
- wait_timeout(3);
- }
-
- if (data & 0x80)
- return STATUS_TIMEDOUT;
-
- wait_timeout(5);
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
-{
- int retval;
- u16 value;
-
- retval = rtsx_read_phy_register(chip, reg, &value);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (value & (1 << bit)) {
- value &= ~(1 << bit);
- retval = rtsx_write_phy_register(chip, reg, value);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit)
-{
- int retval;
- u16 value;
-
- retval = rtsx_read_phy_register(chip, reg, &value);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if ((value & (1 << bit)) == 0) {
- value |= (1 << bit);
- retval = rtsx_write_phy_register(chip, reg, value);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static void rtsx_handle_pm_dstate(struct rtsx_chip *chip, u8 dstate)
-{
- u32 ultmp;
-
- dev_dbg(rtsx_dev(chip), "%04x set pm_dstate to %d\n",
- chip->product_id, dstate);
-
- if (CHK_SDIO_EXIST(chip)) {
- u8 func_no;
-
- if (CHECK_PID(chip, 0x5288))
- func_no = 2;
- else
- func_no = 1;
-
- rtsx_read_cfg_dw(chip, func_no, 0x84, &ultmp);
- dev_dbg(rtsx_dev(chip), "pm_dstate of function %d: 0x%x\n",
- (int)func_no, ultmp);
- rtsx_write_cfg_dw(chip, func_no, 0x84, 0xFF, dstate);
- }
-
- rtsx_write_config_byte(chip, 0x44, dstate);
- rtsx_write_config_byte(chip, 0x45, 0);
-}
-
-void rtsx_enter_L1(struct rtsx_chip *chip)
-{
- rtsx_handle_pm_dstate(chip, 2);
-}
-
-void rtsx_exit_L1(struct rtsx_chip *chip)
-{
- rtsx_write_config_byte(chip, 0x44, 0);
- rtsx_write_config_byte(chip, 0x45, 0);
-}
-
-void rtsx_enter_ss(struct rtsx_chip *chip)
-{
- dev_dbg(rtsx_dev(chip), "Enter Selective Suspend State!\n");
-
- rtsx_write_register(chip, IRQSTAT0, LINK_RDY_INT, LINK_RDY_INT);
-
- if (chip->power_down_in_ss) {
- rtsx_power_off_card(chip);
- rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
- }
-
- if (CHK_SDIO_EXIST(chip))
- rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
- 0xC0, 0xFF00, 0x0100);
-
- if (chip->auto_delink_en) {
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0x01, 0x01);
- } else {
- if (!chip->phy_debug_mode) {
- u32 tmp;
-
- tmp = rtsx_readl(chip, RTSX_BIER);
- tmp |= CARD_INT;
- rtsx_writel(chip, RTSX_BIER, tmp);
- }
-
- rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 0);
- }
-
- rtsx_enter_L1(chip);
-
- RTSX_CLR_DELINK(chip);
- rtsx_set_stat(chip, RTSX_STAT_SS);
-}
-
-void rtsx_exit_ss(struct rtsx_chip *chip)
-{
- dev_dbg(rtsx_dev(chip), "Exit Selective Suspend State!\n");
-
- rtsx_exit_L1(chip);
-
- if (chip->power_down_in_ss) {
- rtsx_force_power_on(chip, SSC_PDCTL | OC_PDCTL);
- udelay(1000);
- }
-
- if (RTSX_TST_DELINK(chip)) {
- chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
- rtsx_reinit_cards(chip, 1);
- RTSX_CLR_DELINK(chip);
- } else if (chip->power_down_in_ss) {
- chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
- rtsx_reinit_cards(chip, 0);
- }
-}
-
-int rtsx_pre_handle_interrupt(struct rtsx_chip *chip)
-{
- u32 status, int_enable;
- bool exit_ss = false;
-#ifdef SUPPORT_OCP
- u32 ocp_int = 0;
-
- ocp_int = OC_INT;
-#endif
-
- if (chip->ss_en) {
- chip->ss_counter = 0;
- if (rtsx_get_stat(chip) == RTSX_STAT_SS) {
- exit_ss = true;
- rtsx_exit_L1(chip);
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- }
- }
-
- int_enable = rtsx_readl(chip, RTSX_BIER);
- chip->int_reg = rtsx_readl(chip, RTSX_BIPR);
-
- if (((chip->int_reg & int_enable) == 0) ||
- chip->int_reg == 0xFFFFFFFF)
- return STATUS_FAIL;
-
- status = chip->int_reg &= (int_enable | 0x7FFFFF);
-
- if (status & CARD_INT) {
- chip->auto_delink_cnt = 0;
-
- if (status & SD_INT) {
- if (status & SD_EXIST) {
- set_bit(SD_NR, &chip->need_reset);
- } else {
- set_bit(SD_NR, &chip->need_release);
- chip->sd_reset_counter = 0;
- chip->sd_show_cnt = 0;
- clear_bit(SD_NR, &chip->need_reset);
- }
- } else {
- /*
- * If multi-luns, it's possible that
- * when plugging/unplugging one card
- * there is another card which still
- * exists in the slot. In this case,
- * all existed cards should be reset.
- */
- if (exit_ss && (status & SD_EXIST))
- set_bit(SD_NR, &chip->need_reinit);
- }
- if (!CHECK_PID(chip, 0x5288) || CHECK_BARO_PKG(chip, QFN)) {
- if (status & XD_INT) {
- if (status & XD_EXIST) {
- set_bit(XD_NR, &chip->need_reset);
- } else {
- set_bit(XD_NR, &chip->need_release);
- chip->xd_reset_counter = 0;
- chip->xd_show_cnt = 0;
- clear_bit(XD_NR, &chip->need_reset);
- }
- } else {
- if (exit_ss && (status & XD_EXIST))
- set_bit(XD_NR, &chip->need_reinit);
- }
- }
- if (status & MS_INT) {
- if (status & MS_EXIST) {
- set_bit(MS_NR, &chip->need_reset);
- } else {
- set_bit(MS_NR, &chip->need_release);
- chip->ms_reset_counter = 0;
- chip->ms_show_cnt = 0;
- clear_bit(MS_NR, &chip->need_reset);
- }
- } else {
- if (exit_ss && (status & MS_EXIST))
- set_bit(MS_NR, &chip->need_reinit);
- }
- }
-
-#ifdef SUPPORT_OCP
- chip->ocp_int = ocp_int & status;
-#endif
-
- if (chip->sd_io && (chip->int_reg & DATA_DONE_INT))
- chip->int_reg &= ~(u32)DATA_DONE_INT;
-
- return STATUS_SUCCESS;
-}
-
-void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat)
-{
- int retval;
-
- dev_dbg(rtsx_dev(chip), "%s, pm_stat = %d\n", __func__, pm_stat);
-
- rtsx_set_stat(chip, RTSX_STAT_SUSPEND);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS)
- return;
-
- rtsx_release_cards(chip);
- rtsx_disable_bus_int(chip);
- turn_off_led(chip, LED_GPIO);
-
-#ifdef HW_AUTO_SWITCH_SD_BUS
- if (chip->sd_io) {
- chip->sdio_in_charge = 1;
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
- /* Enable sdio_bus_auto_switch */
- rtsx_write_register(chip, 0xFE70, 0x80, 0x80);
- } else if (CHECK_PID(chip, 0x5288)) {
- rtsx_write_register(chip, TLPTISTAT, 0x08, 0x08);
- /* Enable sdio_bus_auto_switch */
- rtsx_write_register(chip, 0xFE5A, 0x08, 0x08);
- }
- }
-#endif
-
- if (CHECK_PID(chip, 0x5208) && chip->ic_version >= IC_VER_D) {
- /* u_force_clkreq_0 */
- rtsx_write_register(chip, PETXCFG, 0x08, 0x08);
- }
-
- if (pm_stat == PM_S1) {
- dev_dbg(rtsx_dev(chip), "Host enter S1\n");
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03,
- HOST_ENTER_S1);
- } else if (pm_stat == PM_S3) {
- if (chip->s3_pwr_off_delay > 0)
- wait_timeout(chip->s3_pwr_off_delay);
-
- dev_dbg(rtsx_dev(chip), "Host enter S3\n");
- rtsx_write_register(chip, HOST_SLEEP_STATE, 0x03,
- HOST_ENTER_S3);
- }
-
- if (chip->do_delink_before_power_down && chip->auto_delink_en)
- rtsx_write_register(chip, CHANGE_LINK_STATE, 0x02, 2);
-
- rtsx_force_power_down(chip, SSC_PDCTL | OC_PDCTL);
-
- chip->cur_clk = 0;
- chip->cur_card = 0;
- chip->card_exist = 0;
-}
-
-void rtsx_enable_aspm(struct rtsx_chip *chip)
-{
- if (chip->aspm_l0s_l1_en && chip->dynamic_aspm && !chip->aspm_enabled) {
- dev_dbg(rtsx_dev(chip), "Try to enable ASPM\n");
- chip->aspm_enabled = 1;
-
- if (chip->asic_code && CHECK_PID(chip, 0x5208))
- rtsx_write_phy_register(chip, 0x07, 0);
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_write_register(chip, ASPM_FORCE_CTL, 0xF3,
- 0x30 | chip->aspm_level[0]);
- } else {
- rtsx_write_config_byte(chip, LCTLR,
- chip->aspm_l0s_l1_en);
- }
-
- if (CHK_SDIO_EXIST(chip)) {
- u16 val = chip->aspm_l0s_l1_en | 0x0100;
-
- rtsx_write_cfg_dw(chip, CHECK_PID(chip, 0x5288) ? 2 : 1,
- 0xC0, 0xFFF, val);
- }
- }
-}
-
-void rtsx_disable_aspm(struct rtsx_chip *chip)
-{
- if (CHECK_PID(chip, 0x5208))
- rtsx_monitor_aspm_config(chip);
-
- if (chip->aspm_l0s_l1_en && chip->dynamic_aspm && chip->aspm_enabled) {
- dev_dbg(rtsx_dev(chip), "Try to disable ASPM\n");
- chip->aspm_enabled = 0;
-
- if (chip->asic_code && CHECK_PID(chip, 0x5208))
- rtsx_write_phy_register(chip, 0x07, 0x0129);
- if (CHECK_PID(chip, 0x5208))
- rtsx_write_register(chip, ASPM_FORCE_CTL,
- 0xF3, 0x30);
- else
- rtsx_write_config_byte(chip, LCTLR, 0x00);
-
- wait_timeout(1);
- }
-}
-
-int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
-{
- int retval;
- int i, j;
- u16 reg_addr;
- u8 *ptr;
-
- if (!buf)
- return STATUS_ERROR;
-
- ptr = buf;
- reg_addr = PPBUF_BASE2;
- for (i = 0; i < buf_len / 256; i++) {
- rtsx_init_cmd(chip);
-
- for (j = 0; j < 256; j++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
-
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval < 0)
- return STATUS_FAIL;
-
- memcpy(ptr, rtsx_get_cmd_data(chip), 256);
- ptr += 256;
- }
-
- if (buf_len % 256) {
- rtsx_init_cmd(chip);
-
- for (j = 0; j < buf_len % 256; j++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr++, 0, 0);
-
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval < 0)
- return STATUS_FAIL;
- }
-
- memcpy(ptr, rtsx_get_cmd_data(chip), buf_len % 256);
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len)
-{
- int retval;
- int i, j;
- u16 reg_addr;
- u8 *ptr;
-
- if (!buf)
- return STATUS_ERROR;
-
- ptr = buf;
- reg_addr = PPBUF_BASE2;
- for (i = 0; i < buf_len / 256; i++) {
- rtsx_init_cmd(chip);
-
- for (j = 0; j < 256; j++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF,
- *ptr);
- ptr++;
- }
-
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval < 0)
- return STATUS_FAIL;
- }
-
- if (buf_len % 256) {
- rtsx_init_cmd(chip);
-
- for (j = 0; j < buf_len % 256; j++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, reg_addr++, 0xFF,
- *ptr);
- ptr++;
- }
-
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval < 0)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_check_chip_exist(struct rtsx_chip *chip)
-{
- if (rtsx_readl(chip, 0) == 0xFFFFFFFF)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl)
-{
- int retval;
- u8 mask = 0;
-
- if (ctl & SSC_PDCTL)
- mask |= SSC_POWER_DOWN;
-
-#ifdef SUPPORT_OCP
- if (ctl & OC_PDCTL) {
- mask |= SD_OC_POWER_DOWN;
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- mask |= MS_OC_POWER_DOWN;
- }
-#endif
-
- if (mask) {
- retval = rtsx_write_register(chip, FPDCTL, mask, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHECK_PID(chip, 0x5288))
- wait_timeout(200);
- }
-
- return STATUS_SUCCESS;
-}
-
-int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl)
-{
- int retval;
- u8 mask = 0, val = 0;
-
- if (ctl & SSC_PDCTL)
- mask |= SSC_POWER_DOWN;
-
-#ifdef SUPPORT_OCP
- if (ctl & OC_PDCTL) {
- mask |= SD_OC_POWER_DOWN;
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- mask |= MS_OC_POWER_DOWN;
- }
-#endif
-
- if (mask) {
- val = mask;
- retval = rtsx_write_register(chip, FPDCTL, mask, val);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts5208/rtsx_chip.h b/drivers/staging/rts5208/rtsx_chip.h
deleted file mode 100644
index bac65784d4a1..000000000000
--- a/drivers/staging/rts5208/rtsx_chip.h
+++ /dev/null
@@ -1,987 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_CHIP_H
-#define __REALTEK_RTSX_CHIP_H
-
-#include "rtsx.h"
-
-#define SUPPORT_CPRM
-#define SUPPORT_OCP
-#define SUPPORT_SDIO_ASPM
-#define SUPPORT_MAGIC_GATE
-#define SUPPORT_MSXC
-#define SUPPORT_SD_LOCK
-/* Hardware switch bus_ctl and cd_ctl automatically */
-#define HW_AUTO_SWITCH_SD_BUS
-/* Enable hardware interrupt write clear */
-#define HW_INT_WRITE_CLR
-/* #define LED_AUTO_BLINK */
-/* #define DISABLE_CARD_INT */
-
-#ifdef SUPPORT_MAGIC_GATE
- /* Using NORMAL_WRITE instead of AUTO_WRITE to set ICV */
- #define MG_SET_ICV_SLOW
- /* HW may miss ERR/CMDNK signal when sampling INT status. */
- #define MS_SAMPLE_INT_ERR
- /*
- * HW DO NOT support Wait_INT function
- * during READ_BYTES transfer mode
- */
- #define READ_BYTES_WAIT_INT
-#endif
-
-#ifdef SUPPORT_MSXC
-#define XC_POWERCLASS
-#define SUPPORT_PCGL_1P18
-#endif
-
-#ifndef LED_AUTO_BLINK
-#define REGULAR_BLINK
-#endif
-
-#define LED_BLINK_SPEED 5
-#define LED_TOGGLE_INTERVAL 6
-#define GPIO_TOGGLE_THRESHOLD 1024
-#define LED_GPIO 0
-
-#define POLLING_INTERVAL 30
-
-#define TRACE_ITEM_CNT 64
-
-#ifndef STATUS_SUCCESS
-#define STATUS_SUCCESS 0
-#endif
-#ifndef STATUS_FAIL
-#define STATUS_FAIL 1
-#endif
-#ifndef STATUS_TIMEDOUT
-#define STATUS_TIMEDOUT 2
-#endif
-#ifndef STATUS_NOMEM
-#define STATUS_NOMEM 3
-#endif
-#ifndef STATUS_READ_FAIL
-#define STATUS_READ_FAIL 4
-#endif
-#ifndef STATUS_WRITE_FAIL
-#define STATUS_WRITE_FAIL 5
-#endif
-#ifndef STATUS_ERROR
-#define STATUS_ERROR 10
-#endif
-
-#define PM_S1 1
-#define PM_S3 3
-
-/*
- * Transport return codes
- */
-
-#define TRANSPORT_GOOD 0 /* Transport good, command good */
-#define TRANSPORT_FAILED 1 /* Transport good, command failed */
-#define TRANSPORT_NO_SENSE 2 /* Command failed, no auto-sense */
-#define TRANSPORT_ERROR 3 /* Transport bad (i.e. device dead) */
-
-/*
- * Start-Stop-Unit
- */
-#define STOP_MEDIUM 0x00 /* access disable */
-#define MAKE_MEDIUM_READY 0x01 /* access enable */
-#define UNLOAD_MEDIUM 0x02 /* unload */
-#define LOAD_MEDIUM 0x03 /* load */
-
-/*
- * STANDARD_INQUIRY
- */
-#define QULIFIRE 0x00
-#define AENC_FNC 0x00
-#define TRML_IOP 0x00
-#define REL_ADR 0x00
-#define WBUS_32 0x00
-#define WBUS_16 0x00
-#define SYNC 0x00
-#define LINKED 0x00
-#define CMD_QUE 0x00
-#define SFT_RE 0x00
-
-#define VEN_ID_LEN 8 /* Vendor ID Length */
-#define PRDCT_ID_LEN 16 /* Product ID Length */
-#define PRDCT_REV_LEN 4 /* Product LOT Length */
-
-/* Dynamic flag definitions: used in set_bit() etc. */
-/* 0x00040000 transfer is active */
-#define RTSX_FLIDX_TRANS_ACTIVE 18
-/* 0x00100000 abort is in progress */
-#define RTSX_FLIDX_ABORTING 20
-/* 0x00200000 disconnect in progress */
-#define RTSX_FLIDX_DISCONNECTING 21
-
-#define ABORTING_OR_DISCONNECTING ((1UL << US_FLIDX_ABORTING) | \
- (1UL << US_FLIDX_DISCONNECTING))
-
-/* 0x00400000 device reset in progress */
-#define RTSX_FLIDX_RESETTING 22
-/* 0x00800000 SCSI midlayer timed out */
-#define RTSX_FLIDX_TIMED_OUT 23
-#define DRCT_ACCESS_DEV 0x00 /* Direct Access Device */
-#define RMB_DISC 0x80 /* The Device is Removable */
-#define ANSI_SCSI2 0x02 /* Based on ANSI-SCSI2 */
-
-#define SCSI 0x00 /* Interface ID */
-
-#define WRITE_PROTECTED_MEDIA 0x07
-
-/*---- sense key ----*/
-#define ILI 0x20 /* ILI bit is on */
-
-#define NO_SENSE 0x00 /* not exist sense key */
-#define RECOVER_ERR 0x01 /* Target/Logical unit is recoverd */
-#define NOT_READY 0x02 /* Logical unit is not ready */
-#define MEDIA_ERR 0x03 /* medium/data error */
-#define HARDWARE_ERR 0x04 /* hardware error */
-#define ILGAL_REQ 0x05 /* CDB/parameter/identify msg error */
-#define UNIT_ATTENTION 0x06 /* unit attention condition occur */
-#define DAT_PRTCT 0x07 /* read/write is desable */
-#define BLNC_CHK 0x08 /* find blank/DOF in read */
- /* write to unblank area */
-#define CPY_ABRT 0x0a /* Copy/Compare/Copy&Verify illegal */
-#define ABRT_CMD 0x0b /* Target make the command in error */
-#define EQUAL 0x0c /* Search Data end with Equal */
-#define VLM_OVRFLW 0x0d /* Some data are left in buffer */
-#define MISCMP 0x0e /* find inequality */
-
-#define READ_ERR -1
-#define WRITE_ERR -2
-
-#define FIRST_RESET 0x01
-#define USED_EXIST 0x02
-
-/*
- * SENSE_DATA
- */
-/*---- valid ----*/
-#define SENSE_VALID 0x80 /* Sense data is valid as SCSI2 */
-#define SENSE_INVALID 0x00 /* Sense data is invalid as SCSI2 */
-
-/*---- error code ----*/
-#define CUR_ERR 0x70 /* current error */
-#define DEF_ERR 0x71 /* specific command error */
-
-/*---- sense key Information ----*/
-#define SNSKEYINFO_LEN 3 /* length of sense key information */
-
-#define SKSV 0x80
-#define CDB_ILLEGAL 0x40
-#define DAT_ILLEGAL 0x00
-#define BPV 0x08
-#define BIT_ILLEGAL0 0 /* bit0 is illegal */
-#define BIT_ILLEGAL1 1 /* bit1 is illegal */
-#define BIT_ILLEGAL2 2 /* bit2 is illegal */
-#define BIT_ILLEGAL3 3 /* bit3 is illegal */
-#define BIT_ILLEGAL4 4 /* bit4 is illegal */
-#define BIT_ILLEGAL5 5 /* bit5 is illegal */
-#define BIT_ILLEGAL6 6 /* bit6 is illegal */
-#define BIT_ILLEGAL7 7 /* bit7 is illegal */
-
-/*---- ASC ----*/
-#define ASC_NO_INFO 0x00
-#define ASC_MISCMP 0x1d
-#define ASC_INVLD_CDB 0x24
-#define ASC_INVLD_PARA 0x26
-#define ASC_LU_NOT_READY 0x04
-#define ASC_WRITE_ERR 0x0c
-#define ASC_READ_ERR 0x11
-#define ASC_LOAD_EJCT_ERR 0x53
-#define ASC_MEDIA_NOT_PRESENT 0x3A
-#define ASC_MEDIA_CHANGED 0x28
-#define ASC_MEDIA_IN_PROCESS 0x04
-#define ASC_WRITE_PROTECT 0x27
-#define ASC_LUN_NOT_SUPPORTED 0x25
-
-/*---- ASQC ----*/
-#define ASCQ_NO_INFO 0x00
-#define ASCQ_MEDIA_IN_PROCESS 0x01
-#define ASCQ_MISCMP 0x00
-#define ASCQ_INVLD_CDB 0x00
-#define ASCQ_INVLD_PARA 0x02
-#define ASCQ_LU_NOT_READY 0x02
-#define ASCQ_WRITE_ERR 0x02
-#define ASCQ_READ_ERR 0x00
-#define ASCQ_LOAD_EJCT_ERR 0x00
-#define ASCQ_WRITE_PROTECT 0x00
-
-struct sense_data_t {
- unsigned char err_code; /* error code */
- /* bit7 : valid */
- /* (1 : SCSI2) */
- /* (0 : Vendor * specific) */
- /* bit6-0 : error * code */
- /* (0x70 : current * error) */
- /* (0x71 : specific command error) */
- unsigned char seg_no; /* segment No. */
- unsigned char sense_key; /* byte5 : ILI */
- /* bit3-0 : sense key */
- unsigned char info[4]; /* information */
- unsigned char ad_sense_len; /* additional sense data length */
- unsigned char cmd_info[4]; /* command specific information */
- unsigned char asc; /* ASC */
- unsigned char ascq; /* ASCQ */
- unsigned char rfu; /* FRU */
- unsigned char sns_key_info[3];/* sense key specific information */
-};
-
-/* PCI Operation Register Address */
-#define RTSX_HCBAR 0x00
-#define RTSX_HCBCTLR 0x04
-#define RTSX_HDBAR 0x08
-#define RTSX_HDBCTLR 0x0C
-#define RTSX_HAIMR 0x10
-#define RTSX_BIPR 0x14
-#define RTSX_BIER 0x18
-
-/* Host command buffer control register */
-#define STOP_CMD (0x01 << 28)
-
-/* Host data buffer control register */
-#define SDMA_MODE 0x00
-#define ADMA_MODE (0x02 << 26)
-#define STOP_DMA (0x01 << 28)
-#define TRIG_DMA (0x01 << 31)
-
-/* Bus interrupt pending register */
-#define CMD_DONE_INT BIT(31)
-#define DATA_DONE_INT BIT(30)
-#define TRANS_OK_INT BIT(29)
-#define TRANS_FAIL_INT BIT(28)
-#define XD_INT BIT(27)
-#define MS_INT BIT(26)
-#define SD_INT BIT(25)
-#define GPIO0_INT BIT(24)
-#define OC_INT BIT(23)
-#define SD_WRITE_PROTECT BIT(19)
-#define XD_EXIST BIT(18)
-#define MS_EXIST BIT(17)
-#define SD_EXIST BIT(16)
-#define DELINK_INT GPIO0_INT
-#define MS_OC_INT BIT(23)
-#define SD_OC_INT BIT(22)
-
-#define CARD_INT (XD_INT | MS_INT | SD_INT)
-#define NEED_COMPLETE_INT (DATA_DONE_INT | TRANS_OK_INT | TRANS_FAIL_INT)
-#define RTSX_INT (CMD_DONE_INT | NEED_COMPLETE_INT | CARD_INT | \
- GPIO0_INT | OC_INT)
-
-#define CARD_EXIST (XD_EXIST | MS_EXIST | SD_EXIST)
-
-/* Bus interrupt enable register */
-#define CMD_DONE_INT_EN BIT(31)
-#define DATA_DONE_INT_EN BIT(30)
-#define TRANS_OK_INT_EN BIT(29)
-#define TRANS_FAIL_INT_EN BIT(28)
-#define XD_INT_EN BIT(27)
-#define MS_INT_EN BIT(26)
-#define SD_INT_EN BIT(25)
-#define GPIO0_INT_EN BIT(24)
-#define OC_INT_EN BIT(23)
-#define DELINK_INT_EN GPIO0_INT_EN
-#define MS_OC_INT_EN BIT(23)
-#define SD_OC_INT_EN BIT(22)
-
-#define READ_REG_CMD 0
-#define WRITE_REG_CMD 1
-#define CHECK_REG_CMD 2
-
-#define HOST_TO_DEVICE 0
-#define DEVICE_TO_HOST 1
-
-#define RTSX_RESV_BUF_LEN 4096
-#define HOST_CMDS_BUF_LEN 1024
-#define HOST_SG_TBL_BUF_LEN (RTSX_RESV_BUF_LEN - HOST_CMDS_BUF_LEN)
-
-#define SD_NR 2
-#define MS_NR 3
-#define XD_NR 4
-#define SPI_NR 7
-#define SD_CARD BIT(SD_NR)
-#define MS_CARD BIT(MS_NR)
-#define XD_CARD BIT(XD_NR)
-#define SPI_CARD BIT(SPI_NR)
-
-#define MAX_ALLOWED_LUN_CNT 8
-
-#define XD_FREE_TABLE_CNT 1200
-#define MS_FREE_TABLE_CNT 512
-
-/* Bit Operation */
-#define SET_BIT(data, idx) ((data) |= 1 << (idx))
-#define CLR_BIT(data, idx) ((data) &= ~(1 << (idx)))
-#define CHK_BIT(data, idx) ((data) & (1 << (idx)))
-
-/* SG descriptor */
-#define RTSX_SG_INT 0x04
-#define RTSX_SG_END 0x02
-#define RTSX_SG_VALID 0x01
-
-#define RTSX_SG_NO_OP 0x00
-#define RTSX_SG_TRANS_DATA (0x02 << 4)
-#define RTSX_SG_LINK_DESC (0x03 << 4)
-
-struct rtsx_chip;
-
-typedef int (*card_rw_func)(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 sec_addr, u16 sec_cnt);
-
-/* Supported Clock */
-enum card_clock {CLK_20 = 1, CLK_30, CLK_40, CLK_50, CLK_60,
- CLK_80, CLK_100, CLK_120, CLK_150, CLK_200};
-
-enum RTSX_STAT {RTSX_STAT_INIT, RTSX_STAT_IDLE, RTSX_STAT_RUN, RTSX_STAT_SS,
- RTSX_STAT_DELINK, RTSX_STAT_SUSPEND,
- RTSX_STAT_ABORT, RTSX_STAT_DISCONNECT};
-enum IC_VER {IC_VER_AB, IC_VER_C = 2, IC_VER_D = 3};
-
-#define MAX_RESET_CNT 3
-
-/* For MS Card */
-#define MAX_DEFECTIVE_BLOCK 10
-
-struct zone_entry {
- u16 *l2p_table;
- u16 *free_table;
- u16 defect_list[MAX_DEFECTIVE_BLOCK]; /* For MS card only */
- int set_index;
- int get_index;
- int unused_blk_cnt;
- int disable_count;
- /* To indicate whether the L2P table of this zone has been built. */
- int build_flag;
-};
-
-#define TYPE_SD 0x0000
-#define TYPE_MMC 0x0001
-
-/* TYPE_SD */
-#define SD_HS 0x0100
-#define SD_SDR50 0x0200
-#define SD_DDR50 0x0400
-#define SD_SDR104 0x0800
-#define SD_HCXC 0x1000
-
-/* TYPE_MMC */
-#define MMC_26M 0x0100
-#define MMC_52M 0x0200
-#define MMC_4BIT 0x0400
-#define MMC_8BIT 0x0800
-#define MMC_SECTOR_MODE 0x1000
-#define MMC_DDR52 0x2000
-
-/* SD card */
-#define CHK_SD(sd_card) (((sd_card)->sd_type & 0xFF) == TYPE_SD)
-#define CHK_SD_HS(sd_card) (CHK_SD(sd_card) && \
- ((sd_card)->sd_type & SD_HS))
-#define CHK_SD_SDR50(sd_card) (CHK_SD(sd_card) && \
- ((sd_card)->sd_type & SD_SDR50))
-#define CHK_SD_DDR50(sd_card) (CHK_SD(sd_card) && \
- ((sd_card)->sd_type & SD_DDR50))
-#define CHK_SD_SDR104(sd_card) (CHK_SD(sd_card) && \
- ((sd_card)->sd_type & SD_SDR104))
-#define CHK_SD_HCXC(sd_card) (CHK_SD(sd_card) && \
- ((sd_card)->sd_type & SD_HCXC))
-#define CHK_SD_HC(sd_card) (CHK_SD_HCXC(sd_card) && \
- ((sd_card)->capacity <= 0x4000000))
-#define CHK_SD_XC(sd_card) (CHK_SD_HCXC(sd_card) && \
- ((sd_card)->capacity > 0x4000000))
-#define CHK_SD30_SPEED(sd_card) (CHK_SD_SDR50(sd_card) || \
- CHK_SD_DDR50(sd_card) || \
- CHK_SD_SDR104(sd_card))
-
-#define SET_SD(sd_card) ((sd_card)->sd_type = TYPE_SD)
-#define SET_SD_HS(sd_card) ((sd_card)->sd_type |= SD_HS)
-#define SET_SD_SDR50(sd_card) ((sd_card)->sd_type |= SD_SDR50)
-#define SET_SD_DDR50(sd_card) ((sd_card)->sd_type |= SD_DDR50)
-#define SET_SD_SDR104(sd_card) ((sd_card)->sd_type |= SD_SDR104)
-#define SET_SD_HCXC(sd_card) ((sd_card)->sd_type |= SD_HCXC)
-
-#define CLR_SD_HS(sd_card) ((sd_card)->sd_type &= ~SD_HS)
-#define CLR_SD_SDR50(sd_card) ((sd_card)->sd_type &= ~SD_SDR50)
-#define CLR_SD_DDR50(sd_card) ((sd_card)->sd_type &= ~SD_DDR50)
-#define CLR_SD_SDR104(sd_card) ((sd_card)->sd_type &= ~SD_SDR104)
-#define CLR_SD_HCXC(sd_card) ((sd_card)->sd_type &= ~SD_HCXC)
-
-/* MMC card */
-#define CHK_MMC(sd_card) (((sd_card)->sd_type & 0xFF) == \
- TYPE_MMC)
-#define CHK_MMC_26M(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_26M))
-#define CHK_MMC_52M(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_52M))
-#define CHK_MMC_4BIT(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_4BIT))
-#define CHK_MMC_8BIT(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_8BIT))
-#define CHK_MMC_SECTOR_MODE(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_SECTOR_MODE))
-#define CHK_MMC_DDR52(sd_card) (CHK_MMC(sd_card) && \
- ((sd_card)->sd_type & MMC_DDR52))
-
-#define SET_MMC(sd_card) ((sd_card)->sd_type = TYPE_MMC)
-#define SET_MMC_26M(sd_card) ((sd_card)->sd_type |= MMC_26M)
-#define SET_MMC_52M(sd_card) ((sd_card)->sd_type |= MMC_52M)
-#define SET_MMC_4BIT(sd_card) ((sd_card)->sd_type |= MMC_4BIT)
-#define SET_MMC_8BIT(sd_card) ((sd_card)->sd_type |= MMC_8BIT)
-#define SET_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type |= MMC_SECTOR_MODE)
-#define SET_MMC_DDR52(sd_card) ((sd_card)->sd_type |= MMC_DDR52)
-
-#define CLR_MMC_26M(sd_card) ((sd_card)->sd_type &= ~MMC_26M)
-#define CLR_MMC_52M(sd_card) ((sd_card)->sd_type &= ~MMC_52M)
-#define CLR_MMC_4BIT(sd_card) ((sd_card)->sd_type &= ~MMC_4BIT)
-#define CLR_MMC_8BIT(sd_card) ((sd_card)->sd_type &= ~MMC_8BIT)
-#define CLR_MMC_SECTOR_MODE(sd_card) ((sd_card)->sd_type &= ~MMC_SECTOR_MODE)
-#define CLR_MMC_DDR52(sd_card) ((sd_card)->sd_type &= ~MMC_DDR52)
-
-#define CHK_MMC_HS(sd_card) (CHK_MMC_52M(sd_card) && \
- CHK_MMC_26M(sd_card))
-#define CLR_MMC_HS(sd_card) \
-do { \
- CLR_MMC_DDR52(sd_card); \
- CLR_MMC_52M(sd_card); \
- CLR_MMC_26M(sd_card); \
-} while (0)
-
-#define SD_SUPPORT_CLASS_TEN 0x01
-#define SD_SUPPORT_1V8 0x02
-
-#define SD_SET_CLASS_TEN(sd_card) ((sd_card)->sd_setting |= \
- SD_SUPPORT_CLASS_TEN)
-#define SD_CHK_CLASS_TEN(sd_card) ((sd_card)->sd_setting & \
- SD_SUPPORT_CLASS_TEN)
-#define SD_CLR_CLASS_TEN(sd_card) ((sd_card)->sd_setting &= \
- ~SD_SUPPORT_CLASS_TEN)
-#define SD_SET_1V8(sd_card) ((sd_card)->sd_setting |= \
- SD_SUPPORT_1V8)
-#define SD_CHK_1V8(sd_card) ((sd_card)->sd_setting & \
- SD_SUPPORT_1V8)
-#define SD_CLR_1V8(sd_card) ((sd_card)->sd_setting &= \
- ~SD_SUPPORT_1V8)
-
-struct sd_info {
- u16 sd_type;
- u8 err_code;
- u8 sd_data_buf_ready;
- u32 sd_addr;
- u32 capacity;
-
- u8 raw_csd[16];
- u8 raw_scr[8];
-
- /* Sequential RW */
- int seq_mode;
- enum dma_data_direction pre_dir;
- u32 pre_sec_addr;
- u16 pre_sec_cnt;
-
- int cleanup_counter;
-
- int sd_clock;
-
- int mmc_dont_switch_bus;
-
-#ifdef SUPPORT_CPRM
- int sd_pass_thru_en;
- int pre_cmd_err;
- u8 last_rsp_type;
- u8 rsp[17];
-#endif
-
- u8 func_group1_mask;
- u8 func_group2_mask;
- u8 func_group3_mask;
- u8 func_group4_mask;
-
- u8 sd_switch_fail;
- u8 sd_read_phase;
-
-#ifdef SUPPORT_SD_LOCK
- u8 sd_lock_status;
- u8 sd_erase_status;
- u8 sd_lock_notify;
-#endif
- int need_retune;
-};
-
-struct xd_delay_write_tag {
- u32 old_phyblock;
- u32 new_phyblock;
- u32 logblock;
- u8 pageoff;
- u8 delay_write_flag;
-};
-
-struct xd_info {
- u8 maker_code;
- u8 device_code;
- u8 block_shift;
- u8 page_off;
- u8 addr_cycle;
- u16 cis_block;
- u8 multi_flag;
- u8 err_code;
- u32 capacity;
-
- struct zone_entry *zone;
- int zone_cnt;
-
- struct xd_delay_write_tag delay_write;
- int cleanup_counter;
-
- int xd_clock;
-};
-
-#define MODE_512_SEQ 0x01
-#define MODE_2K_SEQ 0x02
-
-#define TYPE_MS 0x0000
-#define TYPE_MSPRO 0x0001
-
-#define MS_4BIT 0x0100
-#define MS_8BIT 0x0200
-#define MS_HG 0x0400
-#define MS_XC 0x0800
-
-#define HG8BIT (MS_HG | MS_8BIT)
-
-#define CHK_MSPRO(ms_card) (((ms_card)->ms_type & 0xFF) == TYPE_MSPRO)
-#define CHK_HG8BIT(ms_card) (CHK_MSPRO(ms_card) && \
- (((ms_card)->ms_type & HG8BIT) == HG8BIT))
-#define CHK_MSXC(ms_card) (CHK_MSPRO(ms_card) && \
- ((ms_card)->ms_type & MS_XC))
-#define CHK_MSHG(ms_card) (CHK_MSPRO(ms_card) && \
- ((ms_card)->ms_type & MS_HG))
-
-#define CHK_MS8BIT(ms_card) (((ms_card)->ms_type & MS_8BIT))
-#define CHK_MS4BIT(ms_card) (((ms_card)->ms_type & MS_4BIT))
-
-struct ms_delay_write_tag {
- u16 old_phyblock;
- u16 new_phyblock;
- u16 logblock;
- u8 pageoff;
- u8 delay_write_flag;
-};
-
-struct ms_info {
- u16 ms_type;
- u8 block_shift;
- u8 page_off;
- u16 total_block;
- u16 boot_block;
- u32 capacity;
-
- u8 check_ms_flow;
- u8 switch_8bit_fail;
- u8 err_code;
-
- struct zone_entry *segment;
- int segment_cnt;
-
- int pro_under_formatting;
- int format_status;
- u16 progress;
- u8 raw_sys_info[96];
-#ifdef SUPPORT_PCGL_1P18
- u8 raw_model_name[48];
-#endif
-
- u8 multi_flag;
-
- /* Sequential RW */
- u8 seq_mode;
- enum dma_data_direction pre_dir;
- u32 pre_sec_addr;
- u16 pre_sec_cnt;
- u32 total_sec_cnt;
-
- struct ms_delay_write_tag delay_write;
-
- int cleanup_counter;
-
- int ms_clock;
-
-#ifdef SUPPORT_MAGIC_GATE
- u8 magic_gate_id[16];
- u8 mg_entry_num;
- int mg_auth; /* flag to indicate authentication process */
-#endif
-};
-
-struct spi_info {
- u8 use_clk;
- u8 write_en;
- u16 clk_div;
- u8 err_code;
-
- int spi_clock;
-};
-
-/************/
-/* LUN mode */
-/************/
-/* Single LUN, support xD/SD/MS */
-#define DEFAULT_SINGLE 0
-/* 2 LUN mode, support SD/MS */
-#define SD_MS_2LUN 1
-/* Single LUN, but only support SD/MS, for Barossa LQFP */
-#define SD_MS_1LUN 2
-
-#define LAST_LUN_MODE 2
-
-/* Barossa package */
-#define QFN 0
-#define LQFP 1
-
-/******************/
-/* sd_ctl bit map */
-/******************/
-/* SD push point control, bit 0, 1 */
-#define SD_PUSH_POINT_CTL_MASK 0x03
-#define SD_PUSH_POINT_DELAY 0x01
-#define SD_PUSH_POINT_AUTO 0x02
-/* SD sample point control, bit 2, 3 */
-#define SD_SAMPLE_POINT_CTL_MASK 0x0C
-#define SD_SAMPLE_POINT_DELAY 0x04
-#define SD_SAMPLE_POINT_AUTO 0x08
-/* SD DDR Tx phase set by user, bit 4 */
-#define SD_DDR_TX_PHASE_SET_BY_USER 0x10
-/* MMC DDR Tx phase set by user, bit 5 */
-#define MMC_DDR_TX_PHASE_SET_BY_USER 0x20
-/* Support MMC DDR mode, bit 6 */
-#define SUPPORT_MMC_DDR_MODE 0x40
-/* Reset MMC at first */
-#define RESET_MMC_FIRST 0x80
-
-#define SEQ_START_CRITERIA 0x20
-
-/* MS Power Class En */
-#define POWER_CLASS_2_EN 0x02
-#define POWER_CLASS_1_EN 0x01
-
-#define MAX_SHOW_CNT 10
-#define MAX_RESET_CNT 3
-
-#define SDIO_EXIST 0x01
-#define SDIO_IGNORED 0x02
-
-#define CHK_SDIO_EXIST(chip) ((chip)->sdio_func_exist & SDIO_EXIST)
-#define SET_SDIO_EXIST(chip) ((chip)->sdio_func_exist |= SDIO_EXIST)
-#define CLR_SDIO_EXIST(chip) ((chip)->sdio_func_exist &= ~SDIO_EXIST)
-
-#define CHK_SDIO_IGNORED(chip) ((chip)->sdio_func_exist & SDIO_IGNORED)
-#define SET_SDIO_IGNORED(chip) ((chip)->sdio_func_exist |= \
- SDIO_IGNORED)
-#define CLR_SDIO_IGNORED(chip) ((chip)->sdio_func_exist &= \
- ~SDIO_IGNORED)
-
-struct rtsx_chip {
- struct rtsx_dev *rtsx;
-
- u32 int_reg; /* Bus interrupt pending register */
- char max_lun;
- void *context;
-
- void *host_cmds_ptr; /* host commands buffer pointer */
- dma_addr_t host_cmds_addr;
- int ci; /* Command Index */
-
- void *host_sg_tbl_ptr; /* SG descriptor table */
- dma_addr_t host_sg_tbl_addr;
- int sgi; /* SG entry index */
-
- struct scsi_cmnd *srb; /* current srb */
- struct sense_data_t sense_buffer[MAX_ALLOWED_LUN_CNT];
-
- int cur_clk; /* current card clock */
-
- /* Current accessed card */
- int cur_card;
-
- unsigned long need_release; /* need release bit map */
- unsigned long need_reset; /* need reset bit map */
- /*
- * Flag to indicate that this card is just resumed from SS state,
- * and need released before being resetted
- */
- unsigned long need_reinit;
-
- int rw_need_retry;
-
-#ifdef SUPPORT_OCP
- u32 ocp_int;
- u8 ocp_stat;
-#endif
-
- u8 card_exist; /* card exist bit map (physical exist) */
- u8 card_ready; /* card ready bit map (reset successfully) */
- u8 card_fail; /* card reset fail bit map */
- u8 card_ejected; /* card ejected bit map */
- u8 card_wp; /* card write protected bit map */
-
- u8 lun_mc; /*
- * flag to indicate whether to answer
- * MediaChange
- */
-
-#ifndef LED_AUTO_BLINK
- int led_toggle_counter;
-#endif
-
- int sd_reset_counter;
- int xd_reset_counter;
- int ms_reset_counter;
-
- /* card bus width */
- u8 card_bus_width[MAX_ALLOWED_LUN_CNT];
- /* card capacity */
- u32 capacity[MAX_ALLOWED_LUN_CNT];
- /* read/write card function pointer */
- card_rw_func rw_card[MAX_ALLOWED_LUN_CNT];
- /* read/write capacity, used for GPIO Toggle */
- u32 rw_cap[MAX_ALLOWED_LUN_CNT];
- /* card to lun mapping table */
- u8 card2lun[32];
- /* lun to card mapping table */
- u8 lun2card[MAX_ALLOWED_LUN_CNT];
-
- int rw_fail_cnt[MAX_ALLOWED_LUN_CNT];
-
- int sd_show_cnt;
- int xd_show_cnt;
- int ms_show_cnt;
-
- /* card information */
- struct sd_info sd_card;
- struct xd_info xd_card;
- struct ms_info ms_card;
-
- struct spi_info spi;
-
- int auto_delink_cnt;
- int auto_delink_allowed;
-
- int aspm_enabled;
-
- int sdio_aspm;
- int sdio_idle;
- int sdio_counter;
- u8 sdio_raw_data[12];
-
- u8 sd_io;
- u8 sd_int;
-
- u8 rtsx_flag;
-
- int ss_counter;
- int idle_counter;
- enum RTSX_STAT rtsx_stat;
-
- u16 vendor_id;
- u16 product_id;
- u8 ic_version;
-
- int driver_first_load;
-
-#ifdef HW_AUTO_SWITCH_SD_BUS
- int sdio_in_charge;
-#endif
-
- u8 aspm_level[2];
-
- int chip_insert_with_sdio;
-
- /* Options */
-
- int adma_mode;
-
- int auto_delink_en;
- int ss_en;
- u8 lun_mode;
- u8 aspm_l0s_l1_en;
-
- int power_down_in_ss;
-
- int sdr104_en;
- int ddr50_en;
- int sdr50_en;
-
- int baro_pkg;
-
- int asic_code;
- int phy_debug_mode;
- int hw_bypass_sd;
- int sdio_func_exist;
- int aux_pwr_exist;
- u8 ms_power_class_en;
-
- int mspro_formatter_enable;
-
- int remote_wakeup_en;
-
- int ignore_sd;
- int use_hw_setting;
-
- int ss_idle_period;
-
- int dynamic_aspm;
-
- int fpga_sd_sdr104_clk;
- int fpga_sd_ddr50_clk;
- int fpga_sd_sdr50_clk;
- int fpga_sd_hs_clk;
- int fpga_mmc_52m_clk;
- int fpga_ms_hg_clk;
- int fpga_ms_4bit_clk;
- int fpga_ms_1bit_clk;
-
- int asic_sd_sdr104_clk;
- int asic_sd_ddr50_clk;
- int asic_sd_sdr50_clk;
- int asic_sd_hs_clk;
- int asic_mmc_52m_clk;
- int asic_ms_hg_clk;
- int asic_ms_4bit_clk;
- int asic_ms_1bit_clk;
-
- u8 ssc_depth_sd_sdr104;
- u8 ssc_depth_sd_ddr50;
- u8 ssc_depth_sd_sdr50;
- u8 ssc_depth_sd_hs;
- u8 ssc_depth_mmc_52m;
- u8 ssc_depth_ms_hg;
- u8 ssc_depth_ms_4bit;
- u8 ssc_depth_low_speed;
-
- u8 card_drive_sel;
- u8 sd30_drive_sel_1v8;
- u8 sd30_drive_sel_3v3;
-
- u8 sd_400mA_ocp_thd;
- u8 sd_800mA_ocp_thd;
- u8 ms_ocp_thd;
-
- int ssc_en;
- int msi_en;
-
- int xd_timeout;
- int sd_timeout;
- int ms_timeout;
- int mspro_timeout;
-
- int auto_power_down;
-
- int sd_ddr_tx_phase;
- int mmc_ddr_tx_phase;
- int sd_default_tx_phase;
- int sd_default_rx_phase;
-
- int pmos_pwr_on_interval;
- int sd_voltage_switch_delay;
- int s3_pwr_off_delay;
-
- int force_clkreq_0;
- int ft2_fast_mode;
-
- int do_delink_before_power_down;
- int polling_config;
- int sdio_retry_cnt;
-
- int delink_stage1_step;
- int delink_stage2_step;
- int delink_stage3_step;
-
- int auto_delink_in_L1;
- int hp_watch_bios_hotplug;
- int support_ms_8bit;
-
- u8 blink_led;
- u8 phy_voltage;
- u8 max_payload;
-
- u32 sd_speed_prior;
- u32 sd_current_prior;
- u32 sd_ctl;
-};
-
-static inline struct device *rtsx_dev(const struct rtsx_chip *chip)
-{
- return &chip->rtsx->pci->dev;
-}
-
-#define rtsx_set_stat(chip, stat) \
-do { \
- if ((stat) != RTSX_STAT_IDLE) { \
- (chip)->idle_counter = 0; \
- } \
- (chip)->rtsx_stat = (enum RTSX_STAT)(stat); \
-} while (0)
-#define rtsx_get_stat(chip) ((chip)->rtsx_stat)
-#define rtsx_chk_stat(chip, stat) ((chip)->rtsx_stat == (stat))
-
-#define RTSX_SET_DELINK(chip) ((chip)->rtsx_flag |= 0x01)
-#define RTSX_CLR_DELINK(chip) ((chip)->rtsx_flag &= 0xFE)
-#define RTSX_TST_DELINK(chip) ((chip)->rtsx_flag & 0x01)
-
-#define CHECK_PID(chip, pid) ((chip)->product_id == (pid))
-#define CHECK_BARO_PKG(chip, pkg) ((chip)->baro_pkg == (pkg))
-#define CHECK_LUN_MODE(chip, mode) ((chip)->lun_mode == (mode))
-
-/* Power down control */
-#define SSC_PDCTL 0x01
-#define OC_PDCTL 0x02
-
-int rtsx_force_power_on(struct rtsx_chip *chip, u8 ctl);
-int rtsx_force_power_down(struct rtsx_chip *chip, u8 ctl);
-
-void rtsx_enable_card_int(struct rtsx_chip *chip);
-void rtsx_enable_bus_int(struct rtsx_chip *chip);
-void rtsx_disable_bus_int(struct rtsx_chip *chip);
-int rtsx_reset_chip(struct rtsx_chip *chip);
-int rtsx_init_chip(struct rtsx_chip *chip);
-void rtsx_release_chip(struct rtsx_chip *chip);
-void rtsx_polling_func(struct rtsx_chip *chip);
-void rtsx_stop_cmd(struct rtsx_chip *chip, int card);
-int rtsx_write_register(struct rtsx_chip *chip, u16 addr, u8 mask, u8 data);
-int rtsx_read_register(struct rtsx_chip *chip, u16 addr, u8 *data);
-int rtsx_write_cfg_dw(struct rtsx_chip *chip,
- u8 func_no, u16 addr, u32 mask, u32 val);
-int rtsx_read_cfg_dw(struct rtsx_chip *chip, u8 func_no, u16 addr, u32 *val);
-int rtsx_write_cfg_seq(struct rtsx_chip *chip,
- u8 func, u16 addr, u8 *buf, int len);
-int rtsx_read_cfg_seq(struct rtsx_chip *chip,
- u8 func, u16 addr, u8 *buf, int len);
-int rtsx_write_phy_register(struct rtsx_chip *chip, u8 addr, u16 val);
-int rtsx_read_phy_register(struct rtsx_chip *chip, u8 addr, u16 *val);
-int rtsx_read_efuse(struct rtsx_chip *chip, u8 addr, u8 *val);
-int rtsx_write_efuse(struct rtsx_chip *chip, u8 addr, u8 val);
-int rtsx_clr_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit);
-int rtsx_set_phy_reg_bit(struct rtsx_chip *chip, u8 reg, u8 bit);
-void rtsx_enter_ss(struct rtsx_chip *chip);
-void rtsx_exit_ss(struct rtsx_chip *chip);
-int rtsx_pre_handle_interrupt(struct rtsx_chip *chip);
-void rtsx_enter_L1(struct rtsx_chip *chip);
-void rtsx_exit_L1(struct rtsx_chip *chip);
-void rtsx_do_before_power_down(struct rtsx_chip *chip, int pm_stat);
-void rtsx_enable_aspm(struct rtsx_chip *chip);
-void rtsx_disable_aspm(struct rtsx_chip *chip);
-int rtsx_read_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
-int rtsx_write_ppbuf(struct rtsx_chip *chip, u8 *buf, int buf_len);
-int rtsx_check_chip_exist(struct rtsx_chip *chip);
-
-#endif /* __REALTEK_RTSX_CHIP_H */
diff --git a/drivers/staging/rts5208/rtsx_scsi.c b/drivers/staging/rts5208/rtsx_scsi.c
deleted file mode 100644
index c27cffb9ad8f..000000000000
--- a/drivers/staging/rts5208/rtsx_scsi.c
+++ /dev/null
@@ -1,3279 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "sd.h"
-#include "ms.h"
-#include "spi.h"
-
-void scsi_show_command(struct rtsx_chip *chip)
-{
- struct scsi_cmnd *srb = chip->srb;
- char *what = NULL;
- bool unknown_cmd = false;
- int len;
-
- switch (srb->cmnd[0]) {
- case TEST_UNIT_READY:
- what = "TEST_UNIT_READY";
- break;
- case REZERO_UNIT:
- what = "REZERO_UNIT";
- break;
- case REQUEST_SENSE:
- what = "REQUEST_SENSE";
- break;
- case FORMAT_UNIT:
- what = "FORMAT_UNIT";
- break;
- case READ_BLOCK_LIMITS:
- what = "READ_BLOCK_LIMITS";
- break;
- case REASSIGN_BLOCKS:
- what = "REASSIGN_BLOCKS";
- break;
- case READ_6:
- what = "READ_6";
- break;
- case WRITE_6:
- what = "WRITE_6";
- break;
- case SEEK_6:
- what = "SEEK_6";
- break;
- case READ_REVERSE:
- what = "READ_REVERSE";
- break;
- case WRITE_FILEMARKS:
- what = "WRITE_FILEMARKS";
- break;
- case SPACE:
- what = "SPACE";
- break;
- case INQUIRY:
- what = "INQUIRY";
- break;
- case RECOVER_BUFFERED_DATA:
- what = "RECOVER_BUFFERED_DATA";
- break;
- case MODE_SELECT:
- what = "MODE_SELECT";
- break;
- case RESERVE:
- what = "RESERVE";
- break;
- case RELEASE:
- what = "RELEASE";
- break;
- case COPY:
- what = "COPY";
- break;
- case ERASE:
- what = "ERASE";
- break;
- case MODE_SENSE:
- what = "MODE_SENSE";
- break;
- case START_STOP:
- what = "START_STOP";
- break;
- case RECEIVE_DIAGNOSTIC:
- what = "RECEIVE_DIAGNOSTIC";
- break;
- case SEND_DIAGNOSTIC:
- what = "SEND_DIAGNOSTIC";
- break;
- case ALLOW_MEDIUM_REMOVAL:
- what = "ALLOW_MEDIUM_REMOVAL";
- break;
- case SET_WINDOW:
- what = "SET_WINDOW";
- break;
- case READ_CAPACITY:
- what = "READ_CAPACITY";
- break;
- case READ_10:
- what = "READ_10";
- break;
- case WRITE_10:
- what = "WRITE_10";
- break;
- case SEEK_10:
- what = "SEEK_10";
- break;
- case WRITE_VERIFY:
- what = "WRITE_VERIFY";
- break;
- case VERIFY:
- what = "VERIFY";
- break;
- case SEARCH_HIGH:
- what = "SEARCH_HIGH";
- break;
- case SEARCH_EQUAL:
- what = "SEARCH_EQUAL";
- break;
- case SEARCH_LOW:
- what = "SEARCH_LOW";
- break;
- case SET_LIMITS:
- what = "SET_LIMITS";
- break;
- case READ_POSITION:
- what = "READ_POSITION";
- break;
- case SYNCHRONIZE_CACHE:
- what = "SYNCHRONIZE_CACHE";
- break;
- case LOCK_UNLOCK_CACHE:
- what = "LOCK_UNLOCK_CACHE";
- break;
- case READ_DEFECT_DATA:
- what = "READ_DEFECT_DATA";
- break;
- case MEDIUM_SCAN:
- what = "MEDIUM_SCAN";
- break;
- case COMPARE:
- what = "COMPARE";
- break;
- case COPY_VERIFY:
- what = "COPY_VERIFY";
- break;
- case WRITE_BUFFER:
- what = "WRITE_BUFFER";
- break;
- case READ_BUFFER:
- what = "READ_BUFFER";
- break;
- case UPDATE_BLOCK:
- what = "UPDATE_BLOCK";
- break;
- case READ_LONG:
- what = "READ_LONG";
- break;
- case WRITE_LONG:
- what = "WRITE_LONG";
- break;
- case CHANGE_DEFINITION:
- what = "CHANGE_DEFINITION";
- break;
- case WRITE_SAME:
- what = "WRITE_SAME";
- break;
- case GPCMD_READ_SUBCHANNEL:
- what = "READ SUBCHANNEL";
- break;
- case READ_TOC:
- what = "READ_TOC";
- break;
- case GPCMD_READ_HEADER:
- what = "READ HEADER";
- break;
- case GPCMD_PLAY_AUDIO_10:
- what = "PLAY AUDIO (10)";
- break;
- case GPCMD_PLAY_AUDIO_MSF:
- what = "PLAY AUDIO MSF";
- break;
- case GPCMD_GET_EVENT_STATUS_NOTIFICATION:
- what = "GET EVENT/STATUS NOTIFICATION";
- break;
- case GPCMD_PAUSE_RESUME:
- what = "PAUSE/RESUME";
- break;
- case LOG_SELECT:
- what = "LOG_SELECT";
- break;
- case LOG_SENSE:
- what = "LOG_SENSE";
- break;
- case GPCMD_STOP_PLAY_SCAN:
- what = "STOP PLAY/SCAN";
- break;
- case GPCMD_READ_DISC_INFO:
- what = "READ DISC INFORMATION";
- break;
- case GPCMD_READ_TRACK_RZONE_INFO:
- what = "READ TRACK INFORMATION";
- break;
- case GPCMD_RESERVE_RZONE_TRACK:
- what = "RESERVE TRACK";
- break;
- case GPCMD_SEND_OPC:
- what = "SEND OPC";
- break;
- case MODE_SELECT_10:
- what = "MODE_SELECT_10";
- break;
- case GPCMD_REPAIR_RZONE_TRACK:
- what = "REPAIR TRACK";
- break;
- case 0x59:
- what = "READ MASTER CUE";
- break;
- case MODE_SENSE_10:
- what = "MODE_SENSE_10";
- break;
- case GPCMD_CLOSE_TRACK:
- what = "CLOSE TRACK/SESSION";
- break;
- case 0x5C:
- what = "READ BUFFER CAPACITY";
- break;
- case 0x5D:
- what = "SEND CUE SHEET";
- break;
- case GPCMD_BLANK:
- what = "BLANK";
- break;
- case REPORT_LUNS:
- what = "REPORT LUNS";
- break;
- case MOVE_MEDIUM:
- what = "MOVE_MEDIUM or PLAY AUDIO (12)";
- break;
- case READ_12:
- what = "READ_12";
- break;
- case WRITE_12:
- what = "WRITE_12";
- break;
- case WRITE_VERIFY_12:
- what = "WRITE_VERIFY_12";
- break;
- case SEARCH_HIGH_12:
- what = "SEARCH_HIGH_12";
- break;
- case SEARCH_EQUAL_12:
- what = "SEARCH_EQUAL_12";
- break;
- case SEARCH_LOW_12:
- what = "SEARCH_LOW_12";
- break;
- case SEND_VOLUME_TAG:
- what = "SEND_VOLUME_TAG";
- break;
- case READ_ELEMENT_STATUS:
- what = "READ_ELEMENT_STATUS";
- break;
- case GPCMD_READ_CD_MSF:
- what = "READ CD MSF";
- break;
- case GPCMD_SCAN:
- what = "SCAN";
- break;
- case GPCMD_SET_SPEED:
- what = "SET CD SPEED";
- break;
- case GPCMD_MECHANISM_STATUS:
- what = "MECHANISM STATUS";
- break;
- case GPCMD_READ_CD:
- what = "READ CD";
- break;
- case 0xE1:
- what = "WRITE CONTINUE";
- break;
- case WRITE_LONG_2:
- what = "WRITE_LONG_2";
- break;
- case VENDOR_CMND:
- what = "Realtek's vendor command";
- break;
- default:
- what = "(unknown command)";
- unknown_cmd = true;
- break;
- }
-
- if (srb->cmnd[0] != TEST_UNIT_READY)
- dev_dbg(rtsx_dev(chip), "Command %s (%d bytes)\n",
- what, srb->cmd_len);
-
- if (unknown_cmd) {
- len = min_t(unsigned short, srb->cmd_len, 16);
- dev_dbg(rtsx_dev(chip), "%*ph\n", len, srb->cmnd);
- }
-}
-
-void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type)
-{
- switch (sense_type) {
- case SENSE_TYPE_MEDIA_CHANGE:
- set_sense_data(chip, lun, CUR_ERR, 0x06, 0, 0x28, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_NOT_PRESENT:
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x3A, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_LBA_OVER_RANGE:
- set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x21, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT:
- set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x25, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_WRITE_PROTECT:
- set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x27, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR:
- set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x11, 0, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_WRITE_ERR:
- set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x02, 0, 0);
- break;
-
- case SENSE_TYPE_MEDIA_INVALID_CMD_FIELD:
- set_sense_data(chip, lun, CUR_ERR, ILGAL_REQ, 0,
- ASC_INVLD_CDB, ASCQ_INVLD_CDB, CDB_ILLEGAL, 1);
- break;
-
- case SENSE_TYPE_FORMAT_IN_PROGRESS:
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04, 0, 0);
- break;
-
- case SENSE_TYPE_FORMAT_CMD_FAILED:
- set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x31, 0x01, 0, 0);
- break;
-
-#ifdef SUPPORT_MAGIC_GATE
- case SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB:
- set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x02, 0, 0);
- break;
-
- case SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN:
- set_sense_data(chip, lun, CUR_ERR, 0x05, 0, 0x6F, 0x00, 0, 0);
- break;
-
- case SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM:
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x30, 0x00, 0, 0);
- break;
-
- case SENSE_TYPE_MG_WRITE_ERR:
- set_sense_data(chip, lun, CUR_ERR, 0x03, 0, 0x0C, 0x00, 0, 0);
- break;
-#endif
-
-#ifdef SUPPORT_SD_LOCK
- case SENSE_TYPE_MEDIA_READ_FORBIDDEN:
- set_sense_data(chip, lun, CUR_ERR, 0x07, 0, 0x11, 0x13, 0, 0);
- break;
-#endif
-
- case SENSE_TYPE_NO_SENSE:
- default:
- set_sense_data(chip, lun, CUR_ERR, 0, 0, 0, 0, 0, 0);
- break;
- }
-}
-
-void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code,
- u8 sense_key, u32 info, u8 asc, u8 ascq, u8 sns_key_info0,
- u16 sns_key_info1)
-{
- struct sense_data_t *sense = &chip->sense_buffer[lun];
-
- sense->err_code = err_code;
- sense->sense_key = sense_key;
- sense->info[0] = (u8)(info >> 24);
- sense->info[1] = (u8)(info >> 16);
- sense->info[2] = (u8)(info >> 8);
- sense->info[3] = (u8)info;
-
- sense->ad_sense_len = sizeof(struct sense_data_t) - 8;
- sense->asc = asc;
- sense->ascq = ascq;
- if (sns_key_info0 != 0) {
- sense->sns_key_info[0] = SKSV | sns_key_info0;
- sense->sns_key_info[1] = (sns_key_info1 & 0xf0) >> 4;
- sense->sns_key_info[2] = sns_key_info1 & 0x0f;
- }
-}
-
-static int test_unit_ready(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- if (!(CHK_BIT(chip->lun_mc, lun))) {
- SET_BIT(chip->lun_mc, lun);
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
-#ifdef SUPPORT_SD_LOCK
- if (get_lun_card(chip, SCSI_LUN(srb)) == SD_CARD) {
- struct sd_info *sd_card = &chip->sd_card;
-
- if (sd_card->sd_lock_notify) {
- sd_card->sd_lock_notify = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- } else if (sd_card->sd_lock_status & SD_LOCKED) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_READ_FORBIDDEN);
- return TRANSPORT_FAILED;
- }
- }
-#endif
-
- return TRANSPORT_GOOD;
-}
-
-static unsigned char formatter_inquiry_str[20] = {
- 'M', 'E', 'M', 'O', 'R', 'Y', 'S', 'T', 'I', 'C', 'K',
-#ifdef SUPPORT_MAGIC_GATE
- '-', 'M', 'G', /* Byte[47:49] */
-#else
- 0x20, 0x20, 0x20, /* Byte[47:49] */
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
- 0x0B, /* Byte[50]: MG, MS, MSPro, MSXC */
-#else
- 0x09, /* Byte[50]: MS, MSPro, MSXC */
-#endif
- 0x00, /* Byte[51]: Category Specific Commands */
- 0x00, /* Byte[52]: Access Control and feature */
- 0x20, 0x20, 0x20, /* Byte[53:55] */
-};
-
-static int inquiry(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
- char *inquiry_default = (char *)"Generic-xD/SD/M.S. 1.00";
- char *inquiry_sdms = (char *)"Generic-SD/MemoryStick 1.00";
- char *inquiry_sd = (char *)"Generic-SD/MMC 1.00";
- char *inquiry_ms = (char *)"Generic-MemoryStick 1.00";
- char *inquiry_string;
- unsigned char sendbytes;
- unsigned char *buf;
- u8 card = get_lun_card(chip, lun);
- bool pro_formatter_flag = false;
- unsigned char inquiry_buf[] = {
- QULIFIRE | DRCT_ACCESS_DEV,
- RMB_DISC | 0x0D,
- 0x00,
- 0x01,
- 0x1f,
- 0x02,
- 0,
- REL_ADR | WBUS_32 | WBUS_16 | SYNC | LINKED | CMD_QUE | SFT_RE,
- };
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
- if (chip->lun2card[lun] == SD_CARD)
- inquiry_string = inquiry_sd;
- else
- inquiry_string = inquiry_ms;
-
- } else if (CHECK_LUN_MODE(chip, SD_MS_1LUN)) {
- inquiry_string = inquiry_sdms;
- } else {
- inquiry_string = inquiry_default;
- }
-
- buf = vmalloc(scsi_bufflen(srb));
- if (!buf)
- return TRANSPORT_ERROR;
-
-#ifdef SUPPORT_MAGIC_GATE
- if (chip->mspro_formatter_enable &&
- (chip->lun2card[lun] & MS_CARD))
-#else
- if (chip->mspro_formatter_enable)
-#endif
- if (!card || card == MS_CARD)
- pro_formatter_flag = true;
-
- if (pro_formatter_flag) {
- if (scsi_bufflen(srb) < 56)
- sendbytes = (unsigned char)(scsi_bufflen(srb));
- else
- sendbytes = 56;
-
- } else {
- if (scsi_bufflen(srb) < 36)
- sendbytes = (unsigned char)(scsi_bufflen(srb));
- else
- sendbytes = 36;
- }
-
- if (sendbytes > 8) {
- memcpy(buf, inquiry_buf, 8);
- memcpy(buf + 8, inquiry_string, min(sendbytes, 36) - 8);
- if (pro_formatter_flag) {
- /* Additional Length */
- buf[4] = 0x33;
- }
- } else {
- memcpy(buf, inquiry_buf, sendbytes);
- }
-
- if (pro_formatter_flag) {
- if (sendbytes > 36)
- memcpy(buf + 36, formatter_inquiry_str, sendbytes - 36);
- }
-
- scsi_set_resid(srb, 0);
-
- rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int start_stop_unit(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
-
- scsi_set_resid(srb, scsi_bufflen(srb));
-
- if (srb->cmnd[1] == 1)
- return TRANSPORT_GOOD;
-
- switch (srb->cmnd[0x4]) {
- case STOP_MEDIUM:
- /* Media disabled */
- return TRANSPORT_GOOD;
-
- case UNLOAD_MEDIUM:
- /* Media shall be unload */
- if (check_card_ready(chip, lun))
- eject_card(chip, lun);
- return TRANSPORT_GOOD;
-
- case MAKE_MEDIUM_READY:
- case LOAD_MEDIUM:
- if (check_card_ready(chip, lun))
- return TRANSPORT_GOOD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
-
- break;
- }
-
- return TRANSPORT_ERROR;
-}
-
-static int allow_medium_removal(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int prevent;
-
- prevent = srb->cmnd[4] & 0x1;
-
- scsi_set_resid(srb, 0);
-
- if (prevent) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int request_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sense_data_t *sense;
- unsigned int lun = SCSI_LUN(srb);
- struct ms_info *ms_card = &chip->ms_card;
- unsigned char *tmp, *buf;
-
- sense = &chip->sense_buffer[lun];
-
- if ((get_lun_card(chip, lun) == MS_CARD) &&
- ms_card->pro_under_formatting) {
- if (ms_card->format_status == FORMAT_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- ms_card->pro_under_formatting = 0;
- ms_card->progress = 0;
- } else if (ms_card->format_status == FORMAT_IN_PROGRESS) {
- /* Logical Unit Not Ready Format in Progress */
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
- 0, (u16)(ms_card->progress));
- } else {
- /* Format Command Failed */
- set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
- ms_card->pro_under_formatting = 0;
- ms_card->progress = 0;
- }
-
- rtsx_set_stat(chip, RTSX_STAT_RUN);
- }
-
- buf = vmalloc(scsi_bufflen(srb));
- if (!buf)
- return TRANSPORT_ERROR;
-
- tmp = (unsigned char *)sense;
- memcpy(buf, tmp, scsi_bufflen(srb));
-
- rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
- vfree(buf);
-
- scsi_set_resid(srb, 0);
- /* Reset Sense Data */
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- return TRANSPORT_GOOD;
-}
-
-static void ms_mode_sense(struct rtsx_chip *chip, u8 cmd,
- int lun, u8 *buf, int buf_len)
-{
- struct ms_info *ms_card = &chip->ms_card;
- int sys_info_offset;
- int data_size = buf_len;
- bool support_format = false;
- int i = 0;
-
- if (cmd == MODE_SENSE) {
- sys_info_offset = 8;
- if (data_size > 0x68)
- data_size = 0x68;
-
- buf[i++] = 0x67; /* Mode Data Length */
- } else {
- sys_info_offset = 12;
- if (data_size > 0x6C)
- data_size = 0x6C;
-
- buf[i++] = 0x00; /* Mode Data Length (MSB) */
- buf[i++] = 0x6A; /* Mode Data Length (LSB) */
- }
-
- /* Medium Type Code */
- if (check_card_ready(chip, lun)) {
- if (CHK_MSXC(ms_card)) {
- support_format = true;
- buf[i++] = 0x40;
- } else if (CHK_MSPRO(ms_card)) {
- support_format = true;
- buf[i++] = 0x20;
- } else {
- buf[i++] = 0x10;
- }
-
- /* WP */
- if (check_card_wp(chip, lun))
- buf[i++] = 0x80;
- else
- buf[i++] = 0x00;
-
- } else {
- buf[i++] = 0x00; /* MediaType */
- buf[i++] = 0x00; /* WP */
- }
-
- buf[i++] = 0x00; /* Reserved */
-
- if (cmd == MODE_SENSE_10) {
- buf[i++] = 0x00; /* Reserved */
- buf[i++] = 0x00; /* Block descriptor length(MSB) */
- buf[i++] = 0x00; /* Block descriptor length(LSB) */
-
- /* The Following Data is the content of "Page 0x20" */
- if (data_size >= 9)
- buf[i++] = 0x20; /* Page Code */
- if (data_size >= 10)
- buf[i++] = 0x62; /* Page Length */
- if (data_size >= 11)
- buf[i++] = 0x00; /* No Access Control */
- if (data_size >= 12) {
- if (support_format)
- buf[i++] = 0xC0; /* SF, SGM */
- else
- buf[i++] = 0x00;
- }
- } else {
- /* The Following Data is the content of "Page 0x20" */
- if (data_size >= 5)
- buf[i++] = 0x20; /* Page Code */
- if (data_size >= 6)
- buf[i++] = 0x62; /* Page Length */
- if (data_size >= 7)
- buf[i++] = 0x00; /* No Access Control */
- if (data_size >= 8) {
- if (support_format)
- buf[i++] = 0xC0; /* SF, SGM */
- else
- buf[i++] = 0x00;
- }
- }
-
- if (data_size > sys_info_offset) {
- /* 96 Bytes Attribute Data */
- int len = data_size - sys_info_offset;
-
- len = (len < 96) ? len : 96;
-
- memcpy(buf + sys_info_offset, ms_card->raw_sys_info, len);
- }
-}
-
-static int mode_sense(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
- unsigned int data_size;
- int status;
- bool pro_formatter_flag;
- unsigned char page_code, *buf;
- u8 card = get_lun_card(chip, lun);
-
-#ifndef SUPPORT_MAGIC_GATE
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- scsi_set_resid(srb, scsi_bufflen(srb));
- return TRANSPORT_FAILED;
- }
-#endif
-
- pro_formatter_flag = false;
- data_size = 8;
-#ifdef SUPPORT_MAGIC_GATE
- if ((chip->lun2card[lun] & MS_CARD)) {
- if (!card || card == MS_CARD) {
- data_size = 108;
- if (chip->mspro_formatter_enable)
- pro_formatter_flag = true;
- }
- }
-#else
- if (card == MS_CARD) {
- if (chip->mspro_formatter_enable) {
- pro_formatter_flag = true;
- data_size = 108;
- }
- }
-#endif
-
- buf = kmalloc(data_size, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- page_code = srb->cmnd[2] & 0x3f;
-
- if (page_code == 0x3F || page_code == 0x1C ||
- page_code == 0x00 ||
- (pro_formatter_flag && page_code == 0x20)) {
- if (srb->cmnd[0] == MODE_SENSE) {
- if (page_code == 0x3F || page_code == 0x20) {
- ms_mode_sense(chip, srb->cmnd[0],
- lun, buf, data_size);
- } else {
- data_size = 4;
- buf[0] = 0x03;
- buf[1] = 0x00;
- if (check_card_wp(chip, lun))
- buf[2] = 0x80;
- else
- buf[2] = 0x00;
-
- buf[3] = 0x00;
- }
- } else {
- if (page_code == 0x3F || page_code == 0x20) {
- ms_mode_sense(chip, srb->cmnd[0],
- lun, buf, data_size);
- } else {
- data_size = 8;
- buf[0] = 0x00;
- buf[1] = 0x06;
- buf[2] = 0x00;
- if (check_card_wp(chip, lun))
- buf[3] = 0x80;
- else
- buf[3] = 0x00;
- buf[4] = 0x00;
- buf[5] = 0x00;
- buf[6] = 0x00;
- buf[7] = 0x00;
- }
- }
- status = TRANSPORT_GOOD;
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- scsi_set_resid(srb, scsi_bufflen(srb));
- status = TRANSPORT_FAILED;
- }
-
- if (status == TRANSPORT_GOOD) {
- unsigned int len = min_t(unsigned int, scsi_bufflen(srb),
- data_size);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
- }
- kfree(buf);
-
- return status;
-}
-
-static int read_write(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &chip->sd_card;
-#endif
- unsigned int lun = SCSI_LUN(srb);
- int retval;
- u32 start_sec;
- u16 sec_cnt;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- if (!check_card_ready(chip, lun) || (get_card_size(chip, lun) == 0)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- if (!(CHK_BIT(chip->lun_mc, lun))) {
- SET_BIT(chip->lun_mc, lun);
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_erase_status) {
- /* Accessing to any card is forbidden
- * until the erase procedure of SD is completed
- */
- dev_dbg(rtsx_dev(chip), "SD card being erased!\n");
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_READ_FORBIDDEN);
- return TRANSPORT_FAILED;
- }
-
- if (get_lun_card(chip, lun) == SD_CARD) {
- if (sd_card->sd_lock_status & SD_LOCKED) {
- dev_dbg(rtsx_dev(chip), "SD card locked!\n");
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_READ_FORBIDDEN);
- return TRANSPORT_FAILED;
- }
- }
-#endif
-
- if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10) {
- start_sec = ((u32)srb->cmnd[2] << 24) |
- ((u32)srb->cmnd[3] << 16) |
- ((u32)srb->cmnd[4] << 8) | ((u32)srb->cmnd[5]);
- sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
- } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
- start_sec = ((u32)(srb->cmnd[1] & 0x1F) << 16) |
- ((u32)srb->cmnd[2] << 8) | ((u32)srb->cmnd[3]);
- sec_cnt = srb->cmnd[4];
- if (sec_cnt == 0)
- sec_cnt = 256;
- } else if ((srb->cmnd[0] == VENDOR_CMND) &&
- (srb->cmnd[1] == SCSI_APP_CMD) &&
- ((srb->cmnd[2] == PP_READ10) || (srb->cmnd[2] == PP_WRITE10))) {
- start_sec = ((u32)srb->cmnd[4] << 24) |
- ((u32)srb->cmnd[5] << 16) |
- ((u32)srb->cmnd[6] << 8) | ((u32)srb->cmnd[7]);
- sec_cnt = ((u16)(srb->cmnd[9]) << 8) | srb->cmnd[10];
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- /* In some test, we will receive a start_sec like 0xFFFFFFFF.
- * In this situation, start_sec + sec_cnt will overflow, so we
- * need to judge start_sec at first
- */
- if (start_sec > get_card_size(chip, lun) ||
- ((start_sec + sec_cnt) > get_card_size(chip, lun))) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LBA_OVER_RANGE);
- return TRANSPORT_FAILED;
- }
-
- if (sec_cnt == 0) {
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
- }
-
- if (chip->rw_fail_cnt[lun] == 3) {
- dev_dbg(rtsx_dev(chip), "read/write fail three times in succession\n");
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- else
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-
- return TRANSPORT_FAILED;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
- if (check_card_wp(chip, lun)) {
- dev_dbg(rtsx_dev(chip), "Write protected card!\n");
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_PROTECT);
- return TRANSPORT_FAILED;
- }
- }
-
- retval = card_rw(srb, chip, start_sec, sec_cnt);
- if (retval != STATUS_SUCCESS) {
- if (chip->need_release & chip->lun2card[lun]) {
- chip->rw_fail_cnt[lun] = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- } else {
- chip->rw_fail_cnt[lun]++;
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- set_sense_type
- (chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- }
- retval = TRANSPORT_FAILED;
- goto exit;
- } else {
- chip->rw_fail_cnt[lun] = 0;
- retval = TRANSPORT_GOOD;
- }
-
- scsi_set_resid(srb, 0);
-
-exit:
- return retval;
-}
-
-static int read_format_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned char *buf;
- unsigned int lun = SCSI_LUN(srb);
- unsigned int buf_len;
- u8 card = get_lun_card(chip, lun);
- u32 card_size;
- int desc_cnt;
- int i = 0;
-
- if (!check_card_ready(chip, lun)) {
- if (!chip->mspro_formatter_enable) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- }
-
- buf_len = (scsi_bufflen(srb) > 12) ? 0x14 : 12;
-
- buf = kmalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- buf[i++] = 0;
- buf[i++] = 0;
- buf[i++] = 0;
-
- /* Capacity List Length */
- if (buf_len > 12 && chip->mspro_formatter_enable &&
- (chip->lun2card[lun] & MS_CARD) &&
- (!card || card == MS_CARD)) {
- buf[i++] = 0x10;
- desc_cnt = 2;
- } else {
- buf[i++] = 0x08;
- desc_cnt = 1;
- }
-
- while (desc_cnt) {
- if (check_card_ready(chip, lun)) {
- card_size = get_card_size(chip, lun);
- buf[i++] = (unsigned char)(card_size >> 24);
- buf[i++] = (unsigned char)(card_size >> 16);
- buf[i++] = (unsigned char)(card_size >> 8);
- buf[i++] = (unsigned char)card_size;
-
- if (desc_cnt == 2)
- buf[i++] = 2;
- else
- buf[i++] = 0;
- } else {
- buf[i++] = 0xFF;
- buf[i++] = 0xFF;
- buf[i++] = 0xFF;
- buf[i++] = 0xFF;
-
- if (desc_cnt == 2)
- buf[i++] = 3;
- else
- buf[i++] = 0;
- }
-
- buf[i++] = 0x00;
- buf[i++] = 0x02;
- buf[i++] = 0x00;
-
- desc_cnt--;
- }
-
- buf_len = min_t(unsigned int, scsi_bufflen(srb), buf_len);
- rtsx_stor_set_xfer_buf(buf, buf_len, srb);
- kfree(buf);
-
- scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
- return TRANSPORT_GOOD;
-}
-
-static int read_capacity(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned char *buf;
- unsigned int lun = SCSI_LUN(srb);
- u32 card_size;
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- if (!(CHK_BIT(chip->lun_mc, lun))) {
- SET_BIT(chip->lun_mc, lun);
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- buf = kmalloc(8, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- card_size = get_card_size(chip, lun);
- buf[0] = (unsigned char)((card_size - 1) >> 24);
- buf[1] = (unsigned char)((card_size - 1) >> 16);
- buf[2] = (unsigned char)((card_size - 1) >> 8);
- buf[3] = (unsigned char)(card_size - 1);
-
- buf[4] = 0x00;
- buf[5] = 0x00;
- buf[6] = 0x02;
- buf[7] = 0x00;
-
- rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
- kfree(buf);
-
- scsi_set_resid(srb, 0);
-
- return TRANSPORT_GOOD;
-}
-
-static int read_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = spi_read_eeprom(chip, i, buf + i);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_eeprom(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- if (len == 511) {
- retval = spi_erase_eeprom_chip(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- } else {
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb),
- len);
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- for (i = 0; i < len; i++) {
- retval = spi_write_eeprom(chip, i, buf[i]);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- vfree(buf);
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int read_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
- len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
- if (addr < 0xFC00) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = rtsx_read_register(chip, addr + i, buf + i);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_mem(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[2] << 8) | srb->cmnd[3];
- len = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
- if (addr < 0xFC00) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = rtsx_write_register(chip, addr + i, 0xFF, buf[i]);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int get_sd_csd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- if (get_lun_card(chip, lun) != SD_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- rtsx_stor_set_xfer_buf(sd_card->raw_csd, scsi_bufflen(srb), srb);
-
- return TRANSPORT_GOOD;
-}
-
-static int toggle_gpio_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- u8 gpio = srb->cmnd[2];
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- if (gpio > 3)
- gpio = 1;
- toggle_gpio(chip, gpio);
-
- return TRANSPORT_GOOD;
-}
-
-static int read_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- u8 addr, buf[4];
- u32 val;
- unsigned int len;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = srb->cmnd[4];
-
- val = rtsx_readl(chip, addr);
- dev_dbg(rtsx_dev(chip), "Host register (0x%x): 0x%x\n", addr, val);
-
- buf[0] = (u8)(val >> 24);
- buf[1] = (u8)(val >> 16);
- buf[2] = (u8)(val >> 8);
- buf[3] = (u8)val;
-
- len = min_t(unsigned int, scsi_bufflen(srb), 4);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_host_reg(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- u8 addr, buf[4];
- u32 val;
- unsigned int len;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = srb->cmnd[4];
-
- len = min_t(unsigned int, scsi_bufflen(srb), 4);
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- val = ((u32)buf[0] << 24) | ((u32)buf[1] << 16) | ((u32)buf[2]
- << 8) | buf[3];
-
- rtsx_writel(chip, addr, val);
-
- return TRANSPORT_GOOD;
-}
-
-static int set_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
-
- if (srb->cmnd[3] == 1) {
- /* Variable Clock */
- struct xd_info *xd_card = &chip->xd_card;
- struct sd_info *sd_card = &chip->sd_card;
- struct ms_info *ms_card = &chip->ms_card;
-
- switch (srb->cmnd[4]) {
- case XD_CARD:
- xd_card->xd_clock = srb->cmnd[5];
- break;
-
- case SD_CARD:
- sd_card->sd_clock = srb->cmnd[5];
- break;
-
- case MS_CARD:
- ms_card->ms_clock = srb->cmnd[5];
- break;
-
- default:
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- } else if (srb->cmnd[3] == 2) {
- if (srb->cmnd[4]) {
- chip->blink_led = 1;
- } else {
- int retval;
-
- chip->blink_led = 0;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en &&
- (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- turn_off_led(chip, LED_GPIO);
- }
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int get_variable(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
-
- if (srb->cmnd[3] == 1) {
- struct xd_info *xd_card = &chip->xd_card;
- struct sd_info *sd_card = &chip->sd_card;
- struct ms_info *ms_card = &chip->ms_card;
- u8 tmp;
-
- switch (srb->cmnd[4]) {
- case XD_CARD:
- tmp = (u8)(xd_card->xd_clock);
- break;
-
- case SD_CARD:
- tmp = (u8)(sd_card->sd_clock);
- break;
-
- case MS_CARD:
- tmp = (u8)(ms_card->ms_clock);
- break;
-
- default:
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- rtsx_stor_set_xfer_buf(&tmp, 1, srb);
- } else if (srb->cmnd[3] == 2) {
- u8 tmp = chip->blink_led;
-
- rtsx_stor_set_xfer_buf(&tmp, 1, srb);
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int dma_access_ring_buffer(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- unsigned int lun = SCSI_LUN(srb);
- u16 len;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- len = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
- len = min_t(u16, len, scsi_bufflen(srb));
-
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- dev_dbg(rtsx_dev(chip), "Read from device\n");
- else
- dev_dbg(rtsx_dev(chip), "Write to device\n");
-
- retval = rtsx_transfer_data(chip, 0, scsi_sglist(srb), len,
- scsi_sg_count(srb), srb->sc_data_direction,
- 1000);
- if (retval < 0) {
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
-
- return TRANSPORT_FAILED;
- }
- scsi_set_resid(srb, 0);
-
- return TRANSPORT_GOOD;
-}
-
-static int get_dev_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- struct ms_info *ms_card = &chip->ms_card;
- int buf_len;
- unsigned int lun = SCSI_LUN(srb);
- u8 card = get_lun_card(chip, lun);
- u8 status[32];
-#ifdef SUPPORT_OCP
- u8 oc_now_mask = 0, oc_ever_mask = 0;
-#endif
-
- memset(status, 0, 32);
-
- status[0] = (u8)(chip->product_id);
- status[1] = chip->ic_version;
-
- if (chip->auto_delink_en)
- status[2] = 0x10;
- else
- status[2] = 0x00;
-
- status[3] = 20;
- status[4] = 10;
- status[5] = 05;
- status[6] = 21;
-
- if (chip->card_wp)
- status[7] = 0x20;
- else
- status[7] = 0x00;
-
-#ifdef SUPPORT_OCP
- status[8] = 0;
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN) &&
- chip->lun2card[lun] == MS_CARD) {
- oc_now_mask = MS_OC_NOW;
- oc_ever_mask = MS_OC_EVER;
- } else {
- oc_now_mask = SD_OC_NOW;
- oc_ever_mask = SD_OC_EVER;
- }
-
- if (chip->ocp_stat & oc_now_mask)
- status[8] |= 0x02;
-
- if (chip->ocp_stat & oc_ever_mask)
- status[8] |= 0x01;
-#endif
-
- if (card == SD_CARD) {
- if (CHK_SD(sd_card)) {
- if (CHK_SD_HCXC(sd_card)) {
- if (sd_card->capacity > 0x4000000)
- status[0x0E] = 0x02;
- else
- status[0x0E] = 0x01;
- } else {
- status[0x0E] = 0x00;
- }
-
- if (CHK_SD_SDR104(sd_card))
- status[0x0F] = 0x03;
- else if (CHK_SD_DDR50(sd_card))
- status[0x0F] = 0x04;
- else if (CHK_SD_SDR50(sd_card))
- status[0x0F] = 0x02;
- else if (CHK_SD_HS(sd_card))
- status[0x0F] = 0x01;
- else
- status[0x0F] = 0x00;
- } else {
- if (CHK_MMC_SECTOR_MODE(sd_card))
- status[0x0E] = 0x01;
- else
- status[0x0E] = 0x00;
-
- if (CHK_MMC_DDR52(sd_card))
- status[0x0F] = 0x03;
- else if (CHK_MMC_52M(sd_card))
- status[0x0F] = 0x02;
- else if (CHK_MMC_26M(sd_card))
- status[0x0F] = 0x01;
- else
- status[0x0F] = 0x00;
- }
- } else if (card == MS_CARD) {
- if (CHK_MSPRO(ms_card)) {
- if (CHK_MSXC(ms_card))
- status[0x0E] = 0x01;
- else
- status[0x0E] = 0x00;
-
- if (CHK_HG8BIT(ms_card))
- status[0x0F] = 0x01;
- else
- status[0x0F] = 0x00;
- }
- }
-
-#ifdef SUPPORT_SD_LOCK
- if (card == SD_CARD) {
- status[0x17] = 0x80;
- if (sd_card->sd_erase_status)
- status[0x17] |= 0x01;
- if (sd_card->sd_lock_status & SD_LOCKED) {
- status[0x17] |= 0x02;
- status[0x07] |= 0x40;
- }
- if (sd_card->sd_lock_status & SD_PWD_EXIST)
- status[0x17] |= 0x04;
- } else {
- status[0x17] = 0x00;
- }
-
- dev_dbg(rtsx_dev(chip), "status[0x17] = 0x%x\n", status[0x17]);
-#endif
-
- status[0x18] = 0x8A;
- status[0x1A] = 0x28;
-#ifdef SUPPORT_SD_LOCK
- status[0x1F] = 0x01;
-#endif
-
- buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(status));
- rtsx_stor_set_xfer_buf(status, buf_len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
- return TRANSPORT_GOOD;
-}
-
-static int set_chip_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int phy_debug_mode;
- int retval;
- u16 reg;
-
- if (!CHECK_PID(chip, 0x5208)) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- phy_debug_mode = (int)(srb->cmnd[3]);
-
- if (phy_debug_mode) {
- chip->phy_debug_mode = 1;
- retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- rtsx_disable_bus_int(chip);
-
- retval = rtsx_read_phy_register(chip, 0x1C, &reg);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- reg |= 0x0001;
- retval = rtsx_write_phy_register(chip, 0x1C, reg);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
- } else {
- chip->phy_debug_mode = 0;
- retval = rtsx_write_register(chip, CDRESUMECTL, 0x77, 0x77);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- rtsx_enable_bus_int(chip);
-
- retval = rtsx_read_phy_register(chip, 0x1C, &reg);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- reg &= 0xFFFE;
- retval = rtsx_write_phy_register(chip, 0x1C, reg);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int rw_mem_cmd_buf(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval = STATUS_SUCCESS;
- unsigned int lun = SCSI_LUN(srb);
- u8 cmd_type, mask, value, idx;
- u16 addr;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- switch (srb->cmnd[3]) {
- case INIT_BATCHCMD:
- rtsx_init_cmd(chip);
- break;
-
- case ADD_BATCHCMD:
- cmd_type = srb->cmnd[4];
- if (cmd_type > 2) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- addr = (srb->cmnd[5] << 8) | srb->cmnd[6];
- mask = srb->cmnd[7];
- value = srb->cmnd[8];
- rtsx_add_cmd(chip, cmd_type, addr, mask, value);
- break;
-
- case SEND_BATCHCMD:
- retval = rtsx_send_cmd(chip, 0, 1000);
- break;
-
- case GET_BATCHRSP:
- idx = srb->cmnd[4];
- value = *(rtsx_get_cmd_data(chip) + idx);
- if (scsi_bufflen(srb) < 1) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- rtsx_stor_set_xfer_buf(&value, 1, srb);
- scsi_set_resid(srb, 0);
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int suit_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- switch (srb->cmnd[3]) {
- case INIT_BATCHCMD:
- case ADD_BATCHCMD:
- case SEND_BATCHCMD:
- case GET_BATCHRSP:
- return rw_mem_cmd_buf(srb, chip);
- default:
- return TRANSPORT_ERROR;
- }
-}
-
-static int read_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
- u16 val;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
- len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
- if (len % 2)
- len -= len % 2;
-
- if (len) {
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len / 2; i++) {
- retval = rtsx_read_phy_register(chip, addr + i, &val);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type
- (chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- buf[2 * i] = (u8)(val >> 8);
- buf[2 * i + 1] = (u8)val;
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb),
- len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int write_phy_register(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
- u16 val;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
- len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
- if (len % 2)
- len -= len % 2;
-
- if (len) {
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb),
- len);
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len / 2; i++) {
- val = ((u16)buf[2 * i] << 8) | buf[2 * i + 1];
- retval = rtsx_write_phy_register(chip, addr + i, val);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- vfree(buf);
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int erase_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr;
- int retval;
- u8 mode;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- mode = srb->cmnd[3];
- addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
-
- if (mode == 0) {
- retval = spi_erase_eeprom_chip(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- } else if (mode == 1) {
- retval = spi_erase_eeprom_byte(chip, addr);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- } else {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return TRANSPORT_GOOD;
-}
-
-static int read_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
- len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = spi_read_eeprom(chip, addr + i, buf + i);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_eeprom2(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned short addr, len, i;
- int retval;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = ((u16)srb->cmnd[4] << 8) | srb->cmnd[5];
- len = ((u16)srb->cmnd[6] << 8) | srb->cmnd[7];
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = spi_write_eeprom(chip, addr + i, buf[i]);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int read_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- u8 addr, len, i;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = srb->cmnd[4];
- len = srb->cmnd[5];
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- for (i = 0; i < len; i++) {
- retval = rtsx_read_efuse(chip, addr + i, buf + i);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
- }
-
- len = (u8)min_t(unsigned int, scsi_bufflen(srb), len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_efuse(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval, result = TRANSPORT_GOOD;
- u16 val;
- u8 addr, len, i;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- addr = srb->cmnd[4];
- len = srb->cmnd[5];
-
- len = (u8)min_t(unsigned int, scsi_bufflen(srb), len);
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- retval = rtsx_force_power_on(chip, SSC_PDCTL);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- if (chip->asic_code) {
- retval = rtsx_read_phy_register(chip, 0x08, &val);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- retval = rtsx_write_register(chip, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, LDO_OFF);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- wait_timeout(600);
-
- retval = rtsx_write_phy_register(chip, 0x08,
- 0x4C00 | chip->phy_voltage);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- retval = rtsx_write_register(chip, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, LDO_ON);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- wait_timeout(600);
- }
-
- retval = card_power_on(chip, SPI_CARD);
- if (retval != STATUS_SUCCESS) {
- vfree(buf);
- return TRANSPORT_ERROR;
- }
-
- wait_timeout(50);
-
- for (i = 0; i < len; i++) {
- retval = rtsx_write_efuse(chip, addr + i, buf[i]);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_WRITE_ERR);
- result = TRANSPORT_FAILED;
- goto exit;
- }
- }
-
-exit:
- vfree(buf);
-
- retval = card_power_off(chip, SPI_CARD);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_ERROR;
-
- if (chip->asic_code) {
- retval = rtsx_write_register(chip, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, LDO_OFF);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_ERROR;
-
- wait_timeout(600);
-
- retval = rtsx_write_phy_register(chip, 0x08, val);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_ERROR;
-
- retval = rtsx_write_register(chip, PWR_GATE_CTRL,
- LDO3318_PWR_MASK, LDO_ON);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_ERROR;
- }
-
- return result;
-}
-
-static int read_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- bool func_max;
- u8 func;
- u16 addr, len;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- func = srb->cmnd[3];
- addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
- len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
-
- dev_dbg(rtsx_dev(chip), "%s: func = %d, addr = 0x%x, len = %d\n",
- __func__, func, addr, len);
-
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
- func_max = true;
- else
- func_max = false;
-
- if (func > func_max) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = rtsx_read_cfg_seq(chip, func, addr, buf, len);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- vfree(buf);
- return TRANSPORT_FAILED;
- }
-
- len = (u16)min_t(unsigned int, scsi_bufflen(srb), len);
- rtsx_stor_set_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int write_cfg_byte(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- bool func_max;
- u8 func;
- u16 addr, len;
- u8 *buf;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- func = srb->cmnd[3];
- addr = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
- len = ((u16)(srb->cmnd[6]) << 8) | srb->cmnd[7];
-
- dev_dbg(rtsx_dev(chip), "%s: func = %d, addr = 0x%x\n",
- __func__, func, addr);
-
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
- func_max = true;
- else
- func_max = false;
-
- if (func > func_max) {
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- len = (unsigned short)min_t(unsigned int, scsi_bufflen(srb), len);
- buf = vmalloc(len);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - len);
-
- retval = rtsx_write_cfg_seq(chip, func, addr, buf, len);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, SCSI_LUN(srb), SENSE_TYPE_MEDIA_WRITE_ERR);
- vfree(buf);
- return TRANSPORT_FAILED;
- }
-
- vfree(buf);
-
- return TRANSPORT_GOOD;
-}
-
-static int app_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int result;
-
- switch (srb->cmnd[2]) {
- case PP_READ10:
- case PP_WRITE10:
- result = read_write(srb, chip);
- break;
-
- case READ_HOST_REG:
- result = read_host_reg(srb, chip);
- break;
-
- case WRITE_HOST_REG:
- result = write_host_reg(srb, chip);
- break;
-
- case GET_VAR:
- result = get_variable(srb, chip);
- break;
-
- case SET_VAR:
- result = set_variable(srb, chip);
- break;
-
- case DMA_READ:
- case DMA_WRITE:
- result = dma_access_ring_buffer(srb, chip);
- break;
-
- case READ_PHY:
- result = read_phy_register(srb, chip);
- break;
-
- case WRITE_PHY:
- result = write_phy_register(srb, chip);
- break;
-
- case ERASE_EEPROM2:
- result = erase_eeprom2(srb, chip);
- break;
-
- case READ_EEPROM2:
- result = read_eeprom2(srb, chip);
- break;
-
- case WRITE_EEPROM2:
- result = write_eeprom2(srb, chip);
- break;
-
- case READ_EFUSE:
- result = read_efuse(srb, chip);
- break;
-
- case WRITE_EFUSE:
- result = write_efuse(srb, chip);
- break;
-
- case READ_CFG:
- result = read_cfg_byte(srb, chip);
- break;
-
- case WRITE_CFG:
- result = write_cfg_byte(srb, chip);
- break;
-
- case SET_CHIP_MODE:
- result = set_chip_mode(srb, chip);
- break;
-
- case SUIT_CMD:
- result = suit_cmd(srb, chip);
- break;
-
- case GET_DEV_STATUS:
- result = get_dev_status(srb, chip);
- break;
-
- default:
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return result;
-}
-
-static int read_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- u8 rtsx_status[16];
- int buf_len;
- unsigned int lun = SCSI_LUN(srb);
-
- rtsx_status[0] = (u8)(chip->vendor_id >> 8);
- rtsx_status[1] = (u8)(chip->vendor_id);
-
- rtsx_status[2] = (u8)(chip->product_id >> 8);
- rtsx_status[3] = (u8)(chip->product_id);
-
- rtsx_status[4] = (u8)lun;
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
- if (chip->lun2card[lun] == SD_CARD)
- rtsx_status[5] = 2;
- else
- rtsx_status[5] = 3;
- } else {
- if (chip->card_exist) {
- if (chip->card_exist & XD_CARD)
- rtsx_status[5] = 4;
- else if (chip->card_exist & SD_CARD)
- rtsx_status[5] = 2;
- else if (chip->card_exist & MS_CARD)
- rtsx_status[5] = 3;
- else
- rtsx_status[5] = 7;
- } else {
- rtsx_status[5] = 7;
- }
- }
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- rtsx_status[6] = 2;
- else
- rtsx_status[6] = 1;
-
- rtsx_status[7] = (u8)(chip->product_id);
- rtsx_status[8] = chip->ic_version;
-
- if (check_card_exist(chip, lun))
- rtsx_status[9] = 1;
- else
- rtsx_status[9] = 0;
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN))
- rtsx_status[10] = 0;
- else
- rtsx_status[10] = 1;
-
- if (CHECK_LUN_MODE(chip, SD_MS_2LUN)) {
- if (chip->lun2card[lun] == SD_CARD)
- rtsx_status[11] = SD_CARD;
- else
- rtsx_status[11] = MS_CARD;
- } else {
- rtsx_status[11] = XD_CARD | SD_CARD | MS_CARD;
- }
-
- if (check_card_ready(chip, lun))
- rtsx_status[12] = 1;
- else
- rtsx_status[12] = 0;
-
- if (get_lun_card(chip, lun) == XD_CARD) {
- rtsx_status[13] = 0x40;
- } else if (get_lun_card(chip, lun) == SD_CARD) {
- struct sd_info *sd_card = &chip->sd_card;
-
- rtsx_status[13] = 0x20;
- if (CHK_SD(sd_card)) {
- if (CHK_SD_HCXC(sd_card))
- rtsx_status[13] |= 0x04;
- if (CHK_SD_HS(sd_card))
- rtsx_status[13] |= 0x02;
- } else {
- rtsx_status[13] |= 0x08;
- if (CHK_MMC_52M(sd_card))
- rtsx_status[13] |= 0x02;
- if (CHK_MMC_SECTOR_MODE(sd_card))
- rtsx_status[13] |= 0x04;
- }
- } else if (get_lun_card(chip, lun) == MS_CARD) {
- struct ms_info *ms_card = &chip->ms_card;
-
- if (CHK_MSPRO(ms_card)) {
- rtsx_status[13] = 0x38;
- if (CHK_HG8BIT(ms_card))
- rtsx_status[13] |= 0x04;
-#ifdef SUPPORT_MSXC
- if (CHK_MSXC(ms_card))
- rtsx_status[13] |= 0x01;
-#endif
- } else {
- rtsx_status[13] = 0x30;
- }
- } else {
- if (CHECK_LUN_MODE(chip, DEFAULT_SINGLE)) {
-#ifdef SUPPORT_SDIO
- if (chip->sd_io && chip->sd_int)
- rtsx_status[13] = 0x60;
- else
- rtsx_status[13] = 0x70;
-#else
- rtsx_status[13] = 0x70;
-#endif
- } else {
- if (chip->lun2card[lun] == SD_CARD)
- rtsx_status[13] = 0x20;
- else
- rtsx_status[13] = 0x30;
- }
- }
-
- rtsx_status[14] = 0x78;
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip))
- rtsx_status[15] = 0x83;
- else
- rtsx_status[15] = 0x82;
-
- buf_len = min_t(unsigned int, scsi_bufflen(srb), sizeof(rtsx_status));
- rtsx_stor_set_xfer_buf(rtsx_status, buf_len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
- return TRANSPORT_GOOD;
-}
-
-static int get_card_bus_width(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
- u8 card, bus_width;
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- card = get_lun_card(chip, lun);
- if (card == SD_CARD || card == MS_CARD) {
- bus_width = chip->card_bus_width[lun];
- } else {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- rtsx_stor_set_xfer_buf(&bus_width, scsi_bufflen(srb), srb);
-
- return TRANSPORT_GOOD;
-}
-
-static int spi_vendor_cmd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int result;
- unsigned int lun = SCSI_LUN(srb);
- u8 gpio_dir;
-
- if (CHECK_PID(chip, 0x5208) || CHECK_PID(chip, 0x5288)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- rtsx_force_power_on(chip, SSC_PDCTL);
-
- rtsx_read_register(chip, CARD_GPIO_DIR, &gpio_dir);
- rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir & 0x06);
-
- switch (srb->cmnd[2]) {
- case SCSI_SPI_GETSTATUS:
- result = spi_get_status(srb, chip);
- break;
-
- case SCSI_SPI_SETPARAMETER:
- result = spi_set_parameter(srb, chip);
- break;
-
- case SCSI_SPI_READFALSHID:
- result = spi_read_flash_id(srb, chip);
- break;
-
- case SCSI_SPI_READFLASH:
- result = spi_read_flash(srb, chip);
- break;
-
- case SCSI_SPI_WRITEFLASH:
- result = spi_write_flash(srb, chip);
- break;
-
- case SCSI_SPI_WRITEFLASHSTATUS:
- result = spi_write_flash_status(srb, chip);
- break;
-
- case SCSI_SPI_ERASEFLASH:
- result = spi_erase_flash(srb, chip);
- break;
-
- default:
- rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
-
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- rtsx_write_register(chip, CARD_GPIO_DIR, 0x07, gpio_dir);
-
- if (result != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- return TRANSPORT_GOOD;
-}
-
-static int vendor_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int result;
-
- switch (srb->cmnd[1]) {
- case READ_STATUS:
- result = read_status(srb, chip);
- break;
-
- case READ_MEM:
- result = read_mem(srb, chip);
- break;
-
- case WRITE_MEM:
- result = write_mem(srb, chip);
- break;
-
- case READ_EEPROM:
- result = read_eeprom(srb, chip);
- break;
-
- case WRITE_EEPROM:
- result = write_eeprom(srb, chip);
- break;
-
- case TOGGLE_GPIO:
- result = toggle_gpio_cmd(srb, chip);
- break;
-
- case GET_SD_CSD:
- result = get_sd_csd(srb, chip);
- break;
-
- case GET_BUS_WIDTH:
- result = get_card_bus_width(srb, chip);
- break;
-
- case SCSI_APP_CMD:
- result = app_cmd(srb, chip);
- break;
-
- case SPI_VENDOR_COMMAND:
- result = spi_vendor_cmd(srb, chip);
- break;
-
- default:
- set_sense_type(chip, SCSI_LUN(srb),
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return result;
-}
-
-#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
-void led_shine(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
- u16 sec_cnt;
-
- if (srb->cmnd[0] == READ_10 || srb->cmnd[0] == WRITE_10) {
- sec_cnt = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
- } else if ((srb->cmnd[0] == READ_6) || (srb->cmnd[0] == WRITE_6)) {
- sec_cnt = srb->cmnd[4];
- if (sec_cnt == 0)
- sec_cnt = 256;
- } else {
- return;
- }
-
- if (chip->rw_cap[lun] >= GPIO_TOGGLE_THRESHOLD) {
- toggle_gpio(chip, LED_GPIO);
- chip->rw_cap[lun] = 0;
- } else {
- chip->rw_cap[lun] += sec_cnt;
- }
-}
-#endif
-
-static int ms_format_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- bool quick_format;
- int retval;
-
- if (get_lun_card(chip, lun) != MS_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[3] != 0x4D || srb->cmnd[4] != 0x47 ||
- srb->cmnd[5] != 0x66 || srb->cmnd[6] != 0x6D ||
- srb->cmnd[7] != 0x74) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
-
- if (!check_card_ready(chip, lun) ||
- (get_card_size(chip, lun) == 0)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- if (srb->cmnd[8] & 0x01)
- quick_format = false;
- else
- quick_format = true;
-
- if (!(chip->card_ready & MS_CARD)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
-
- if (chip->card_wp & MS_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
- return TRANSPORT_FAILED;
- }
-
- if (!CHK_MSPRO(ms_card)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- retval = mspro_format(srb, chip, MS_SHORT_DATA_LEN, quick_format);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_FORMAT_CMD_FAILED);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-}
-
-#ifdef SUPPORT_PCGL_1P18
-static int get_ms_information(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- u8 dev_info_id, data_len;
- u8 *buf;
- unsigned int buf_len;
- int i;
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- if (get_lun_card(chip, lun) != MS_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[2] != 0xB0 || srb->cmnd[4] != 0x4D ||
- srb->cmnd[5] != 0x53 || srb->cmnd[6] != 0x49 ||
- srb->cmnd[7] != 0x44) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- dev_info_id = srb->cmnd[3];
- if ((CHK_MSXC(ms_card) && dev_info_id == 0x10) ||
- (!CHK_MSXC(ms_card) && dev_info_id == 0x13) ||
- !CHK_MSPRO(ms_card)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (dev_info_id == 0x15) {
- buf_len = 0x3C;
- data_len = 0x3A;
- } else {
- buf_len = 0x6C;
- data_len = 0x6A;
- }
-
- buf = kmalloc(buf_len, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- i = 0;
- /* GET Memory Stick Media Information Response Header */
- buf[i++] = 0x00; /* Data length MSB */
- buf[i++] = data_len; /* Data length LSB */
- /* Device Information Type Code */
- if (CHK_MSXC(ms_card))
- buf[i++] = 0x03;
- else
- buf[i++] = 0x02;
-
- /* SGM bit */
- buf[i++] = 0x01;
- /* Reserved */
- buf[i++] = 0x00;
- buf[i++] = 0x00;
- buf[i++] = 0x00;
- /* Number of Device Information */
- buf[i++] = 0x01;
-
- /* Device Information Body */
-
- /* Device Information ID Number */
- buf[i++] = dev_info_id;
- /* Device Information Length */
- if (dev_info_id == 0x15)
- data_len = 0x31;
- else
- data_len = 0x61;
-
- buf[i++] = 0x00; /* Data length MSB */
- buf[i++] = data_len; /* Data length LSB */
- /* Valid Bit */
- buf[i++] = 0x80;
- if (dev_info_id == 0x10 || dev_info_id == 0x13) {
- /* System Information */
- memcpy(buf + i, ms_card->raw_sys_info, 96);
- } else {
- /* Model Name */
- memcpy(buf + i, ms_card->raw_model_name, 48);
- }
-
- rtsx_stor_set_xfer_buf(buf, buf_len, srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - buf_len);
-
- kfree(buf);
- return STATUS_SUCCESS;
-}
-#endif
-
-static int ms_sp_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval = TRANSPORT_ERROR;
-
- if (srb->cmnd[2] == MS_FORMAT)
- retval = ms_format_cmnd(srb, chip);
-#ifdef SUPPORT_PCGL_1P18
- else if (srb->cmnd[2] == GET_MS_INFORMATION)
- retval = get_ms_information(srb, chip);
-#endif
-
- return retval;
-}
-
-#ifdef SUPPORT_CPRM
-static int sd_extension_cmnd(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- unsigned int lun = SCSI_LUN(srb);
- int result;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- sd_cleanup_work(chip);
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- if (get_lun_card(chip, lun) != SD_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- switch (srb->cmnd[0]) {
- case SD_PASS_THRU_MODE:
- result = sd_pass_thru_mode(srb, chip);
- break;
-
- case SD_EXECUTE_NO_DATA:
- result = sd_execute_no_data(srb, chip);
- break;
-
- case SD_EXECUTE_READ:
- result = sd_execute_read_data(srb, chip);
- break;
-
- case SD_EXECUTE_WRITE:
- result = sd_execute_write_data(srb, chip);
- break;
-
- case SD_GET_RSP:
- result = sd_get_cmd_rsp(srb, chip);
- break;
-
- case SD_HW_RST:
- result = sd_hw_rst(srb, chip);
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- return result;
-}
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
-static int mg_report_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval;
- u8 key_format;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- ms_cleanup_work(chip);
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- if (get_lun_card(chip, lun) != MS_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[7] != KC_MG_R_PRO) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (!CHK_MSPRO(ms_card)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return TRANSPORT_FAILED;
- }
-
- key_format = srb->cmnd[10] & 0x3F;
- dev_dbg(rtsx_dev(chip), "key_format = 0x%x\n", key_format);
-
- switch (key_format) {
- case KF_GET_LOC_EKB:
- if ((scsi_bufflen(srb) == 0x41C) &&
- srb->cmnd[8] == 0x04 &&
- srb->cmnd[9] == 0x1C) {
- retval = mg_get_local_EKB(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- case KF_RSP_CHG:
- if ((scsi_bufflen(srb) == 0x24) &&
- srb->cmnd[8] == 0x00 &&
- srb->cmnd[9] == 0x24) {
- retval = mg_get_rsp_chg(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- case KF_GET_ICV:
- ms_card->mg_entry_num = srb->cmnd[5];
- if ((scsi_bufflen(srb) == 0x404) &&
- srb->cmnd[8] == 0x04 &&
- srb->cmnd[9] == 0x04 &&
- srb->cmnd[2] == 0x00 &&
- srb->cmnd[3] == 0x00 &&
- srb->cmnd[4] == 0x00 &&
- srb->cmnd[5] < 32) {
- retval = mg_get_ICV(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-}
-
-static int mg_send_key(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval;
- u8 key_format;
-
- rtsx_disable_aspm(chip);
-
- if (chip->ss_en && (rtsx_get_stat(chip) == RTSX_STAT_SS)) {
- rtsx_exit_ss(chip);
- wait_timeout(100);
- }
- rtsx_set_stat(chip, RTSX_STAT_RUN);
-
- ms_cleanup_work(chip);
-
- if (!check_card_ready(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return TRANSPORT_FAILED;
- }
- if (check_card_wp(chip, lun)) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_PROTECT);
- return TRANSPORT_FAILED;
- }
- if (get_lun_card(chip, lun) != MS_CARD) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[7] != KC_MG_R_PRO) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (!CHK_MSPRO(ms_card)) {
- set_sense_type(chip, lun, SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM);
- return TRANSPORT_FAILED;
- }
-
- key_format = srb->cmnd[10] & 0x3F;
- dev_dbg(rtsx_dev(chip), "key_format = 0x%x\n", key_format);
-
- switch (key_format) {
- case KF_SET_LEAF_ID:
- if ((scsi_bufflen(srb) == 0x0C) &&
- srb->cmnd[8] == 0x00 &&
- srb->cmnd[9] == 0x0C) {
- retval = mg_set_leaf_id(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- case KF_CHG_HOST:
- if ((scsi_bufflen(srb) == 0x0C) &&
- srb->cmnd[8] == 0x00 &&
- srb->cmnd[9] == 0x0C) {
- retval = mg_chg(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- case KF_RSP_HOST:
- if ((scsi_bufflen(srb) == 0x0C) &&
- srb->cmnd[8] == 0x00 &&
- srb->cmnd[9] == 0x0C) {
- retval = mg_rsp(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- case KF_SET_ICV:
- ms_card->mg_entry_num = srb->cmnd[5];
- if ((scsi_bufflen(srb) == 0x404) &&
- srb->cmnd[8] == 0x04 &&
- srb->cmnd[9] == 0x04 &&
- srb->cmnd[2] == 0x00 &&
- srb->cmnd[3] == 0x00 &&
- srb->cmnd[4] == 0x00 &&
- srb->cmnd[5] < 32) {
- retval = mg_set_ICV(srb, chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-}
-#endif
-
-int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
-#ifdef SUPPORT_SD_LOCK
- struct sd_info *sd_card = &chip->sd_card;
-#endif
- struct ms_info *ms_card = &chip->ms_card;
- unsigned int lun = SCSI_LUN(srb);
- int result;
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_erase_status) {
- /* Block all SCSI command except for
- * REQUEST_SENSE and rs_ppstatus
- */
- if (!(srb->cmnd[0] == VENDOR_CMND &&
- srb->cmnd[1] == SCSI_APP_CMD &&
- srb->cmnd[2] == GET_DEV_STATUS) &&
- srb->cmnd[0] != REQUEST_SENSE) {
- /* Logical Unit Not Ready Format in Progress */
- set_sense_data(chip, lun, CUR_ERR,
- 0x02, 0, 0x04, 0x04, 0, 0);
- return TRANSPORT_FAILED;
- }
- }
-#endif
-
- if ((get_lun_card(chip, lun) == MS_CARD) &&
- ms_card->format_status == FORMAT_IN_PROGRESS) {
- if (srb->cmnd[0] != REQUEST_SENSE &&
- srb->cmnd[0] != INQUIRY) {
- /* Logical Unit Not Ready Format in Progress */
- set_sense_data(chip, lun, CUR_ERR, 0x02, 0, 0x04, 0x04,
- 0, (u16)(ms_card->progress));
- return TRANSPORT_FAILED;
- }
- }
-
- switch (srb->cmnd[0]) {
- case READ_10:
- case WRITE_10:
- case READ_6:
- case WRITE_6:
- result = read_write(srb, chip);
-#if !defined(LED_AUTO_BLINK) && !defined(REGULAR_BLINK)
- led_shine(srb, chip);
-#endif
- break;
-
- case TEST_UNIT_READY:
- result = test_unit_ready(srb, chip);
- break;
-
- case INQUIRY:
- result = inquiry(srb, chip);
- break;
-
- case READ_CAPACITY:
- result = read_capacity(srb, chip);
- break;
-
- case START_STOP:
- result = start_stop_unit(srb, chip);
- break;
-
- case ALLOW_MEDIUM_REMOVAL:
- result = allow_medium_removal(srb, chip);
- break;
-
- case REQUEST_SENSE:
- result = request_sense(srb, chip);
- break;
-
- case MODE_SENSE:
- case MODE_SENSE_10:
- result = mode_sense(srb, chip);
- break;
-
- case 0x23:
- result = read_format_capacity(srb, chip);
- break;
-
- case VENDOR_CMND:
- result = vendor_cmnd(srb, chip);
- break;
-
- case MS_SP_CMND:
- result = ms_sp_cmnd(srb, chip);
- break;
-
-#ifdef SUPPORT_CPRM
- case SD_PASS_THRU_MODE:
- case SD_EXECUTE_NO_DATA:
- case SD_EXECUTE_READ:
- case SD_EXECUTE_WRITE:
- case SD_GET_RSP:
- case SD_HW_RST:
- result = sd_extension_cmnd(srb, chip);
- break;
-#endif
-
-#ifdef SUPPORT_MAGIC_GATE
- case CMD_MSPRO_MG_RKEY:
- result = mg_report_key(srb, chip);
- break;
-
- case CMD_MSPRO_MG_SKEY:
- result = mg_send_key(srb, chip);
- break;
-#endif
-
- case FORMAT_UNIT:
- case MODE_SELECT:
- case VERIFY:
- result = TRANSPORT_GOOD;
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- result = TRANSPORT_FAILED;
- }
-
- return result;
-}
diff --git a/drivers/staging/rts5208/rtsx_scsi.h b/drivers/staging/rts5208/rtsx_scsi.h
deleted file mode 100644
index df6138c97aaa..000000000000
--- a/drivers/staging/rts5208/rtsx_scsi.h
+++ /dev/null
@@ -1,131 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_SCSI_H
-#define __REALTEK_RTSX_SCSI_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-
-#define MS_SP_CMND 0xFA
-#define MS_FORMAT 0xA0
-#define GET_MS_INFORMATION 0xB0
-
-#define VENDOR_CMND 0xF0
-
-#define READ_STATUS 0x09
-
-#define READ_EEPROM 0x04
-#define WRITE_EEPROM 0x05
-#define READ_MEM 0x0D
-#define WRITE_MEM 0x0E
-#define GET_BUS_WIDTH 0x13
-#define GET_SD_CSD 0x14
-#define TOGGLE_GPIO 0x15
-#define TRACE_MSG 0x18
-
-#define SCSI_APP_CMD 0x10
-
-#define PP_READ10 0x1A
-#define PP_WRITE10 0x0A
-#define READ_HOST_REG 0x1D
-#define WRITE_HOST_REG 0x0D
-#define SET_VAR 0x05
-#define GET_VAR 0x15
-#define DMA_READ 0x16
-#define DMA_WRITE 0x06
-#define GET_DEV_STATUS 0x10
-#define SET_CHIP_MODE 0x27
-#define SUIT_CMD 0xE0
-#define WRITE_PHY 0x07
-#define READ_PHY 0x17
-#define WRITE_EEPROM2 0x03
-#define READ_EEPROM2 0x13
-#define ERASE_EEPROM2 0x23
-#define WRITE_EFUSE 0x04
-#define READ_EFUSE 0x14
-#define WRITE_CFG 0x0E
-#define READ_CFG 0x1E
-
-#define SPI_VENDOR_COMMAND 0x1C
-
-#define SCSI_SPI_GETSTATUS 0x00
-#define SCSI_SPI_SETPARAMETER 0x01
-#define SCSI_SPI_READFALSHID 0x02
-#define SCSI_SPI_READFLASH 0x03
-#define SCSI_SPI_WRITEFLASH 0x04
-#define SCSI_SPI_WRITEFLASHSTATUS 0x05
-#define SCSI_SPI_ERASEFLASH 0x06
-
-#define INIT_BATCHCMD 0x41
-#define ADD_BATCHCMD 0x42
-#define SEND_BATCHCMD 0x43
-#define GET_BATCHRSP 0x44
-
-#define CHIP_NORMALMODE 0x00
-#define CHIP_DEBUGMODE 0x01
-
-/* SD Pass Through Command Extension */
-#define SD_PASS_THRU_MODE 0xD0
-#define SD_EXECUTE_NO_DATA 0xD1
-#define SD_EXECUTE_READ 0xD2
-#define SD_EXECUTE_WRITE 0xD3
-#define SD_GET_RSP 0xD4
-#define SD_HW_RST 0xD6
-
-#ifdef SUPPORT_MAGIC_GATE
-#define CMD_MSPRO_MG_RKEY 0xA4 /* Report Key Command */
-#define CMD_MSPRO_MG_SKEY 0xA3 /* Send Key Command */
-
-/* CBWCB field: key class */
-#define KC_MG_R_PRO 0xBE /* MG-R PRO*/
-
-/* CBWCB field: key format */
-#define KF_SET_LEAF_ID 0x31 /* Set Leaf ID */
-#define KF_GET_LOC_EKB 0x32 /* Get Local EKB */
-#define KF_CHG_HOST 0x33 /* Challenge (host) */
-#define KF_RSP_CHG 0x34 /* Response and Challenge (device) */
-#define KF_RSP_HOST 0x35 /* Response (host) */
-#define KF_GET_ICV 0x36 /* Get ICV */
-#define KF_SET_ICV 0x37 /* SSet ICV */
-#endif
-
-/* Sense type */
-#define SENSE_TYPE_NO_SENSE 0
-#define SENSE_TYPE_MEDIA_CHANGE 1
-#define SENSE_TYPE_MEDIA_NOT_PRESENT 2
-#define SENSE_TYPE_MEDIA_LBA_OVER_RANGE 3
-#define SENSE_TYPE_MEDIA_LUN_NOT_SUPPORT 4
-#define SENSE_TYPE_MEDIA_WRITE_PROTECT 5
-#define SENSE_TYPE_MEDIA_INVALID_CMD_FIELD 6
-#define SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR 7
-#define SENSE_TYPE_MEDIA_WRITE_ERR 8
-#define SENSE_TYPE_FORMAT_IN_PROGRESS 9
-#define SENSE_TYPE_FORMAT_CMD_FAILED 10
-#ifdef SUPPORT_MAGIC_GATE
-#define SENSE_TYPE_MG_KEY_FAIL_NOT_ESTAB 0x0b
-#define SENSE_TYPE_MG_KEY_FAIL_NOT_AUTHEN 0x0c
-#define SENSE_TYPE_MG_INCOMPATIBLE_MEDIUM 0x0d
-#define SENSE_TYPE_MG_WRITE_ERR 0x0e
-#endif
-#ifdef SUPPORT_SD_LOCK
-/* FOR Locked SD card*/
-#define SENSE_TYPE_MEDIA_READ_FORBIDDEN 0x10
-#endif
-
-void scsi_show_command(struct rtsx_chip *chip);
-void set_sense_type(struct rtsx_chip *chip, unsigned int lun, int sense_type);
-void set_sense_data(struct rtsx_chip *chip, unsigned int lun, u8 err_code,
- u8 sense_key, u32 info, u8 asc, u8 ascq,
- u8 sns_key_info0, u16 sns_key_info1);
-int rtsx_scsi_handler(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-
-#endif /* __REALTEK_RTSX_SCSI_H */
diff --git a/drivers/staging/rts5208/rtsx_sys.h b/drivers/staging/rts5208/rtsx_sys.h
deleted file mode 100644
index 77094809c814..000000000000
--- a/drivers/staging/rts5208/rtsx_sys.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __RTSX_SYS_H
-#define __RTSX_SYS_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-#include "rtsx_card.h"
-
-static inline void rtsx_exclusive_enter_ss(struct rtsx_chip *chip)
-{
- struct rtsx_dev *dev = chip->rtsx;
-
- spin_lock(&dev->reg_lock);
- rtsx_enter_ss(chip);
- spin_unlock(&dev->reg_lock);
-}
-
-static inline void rtsx_reset_detected_cards(struct rtsx_chip *chip, int flag)
-{
- rtsx_reset_cards(chip);
-}
-
-#define RTSX_MSG_IN_INT(x)
-
-#endif /* __RTSX_SYS_H */
-
diff --git a/drivers/staging/rts5208/rtsx_transport.c b/drivers/staging/rts5208/rtsx_transport.c
deleted file mode 100644
index d5ad49de4c56..000000000000
--- a/drivers/staging/rts5208/rtsx_transport.c
+++ /dev/null
@@ -1,768 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-
-#include "rtsx.h"
-
-/***********************************************************************
- * Scatter-gather transfer buffer access routines
- ***********************************************************************/
-
-/*
- * Copy a buffer of length buflen to/from the srb's transfer buffer.
- * (Note: for scatter-gather transfers (srb->use_sg > 0), srb->request_buffer
- * points to a list of s-g entries and we ignore srb->request_bufflen.
- * For non-scatter-gather transfers, srb->request_buffer points to the
- * transfer buffer itself and srb->request_bufflen is the buffer's length.)
- * Update the *index and *offset variables so that the next copy will
- * pick up from where this one left off.
- */
-
-unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
- unsigned int buflen,
- struct scsi_cmnd *srb,
- unsigned int *index,
- unsigned int *offset,
- enum xfer_buf_dir dir)
-{
- unsigned int cnt;
-
- /* If not using scatter-gather, just transfer the data directly. */
- if (scsi_sg_count(srb) == 0) {
- unsigned char *sgbuffer;
-
- if (*offset >= scsi_bufflen(srb))
- return 0;
- cnt = min(buflen, scsi_bufflen(srb) - *offset);
-
- sgbuffer = (unsigned char *)scsi_sglist(srb) + *offset;
-
- if (dir == TO_XFER_BUF)
- memcpy(sgbuffer, buffer, cnt);
- else
- memcpy(buffer, sgbuffer, cnt);
- *offset += cnt;
-
- /*
- * Using scatter-gather. We have to go through the list one entry
- * at a time. Each s-g entry contains some number of pages which
- * have to be copied one at a time.
- */
- } else {
- struct scatterlist *sg =
- (struct scatterlist *)scsi_sglist(srb)
- + *index;
-
- /*
- * This loop handles a single s-g list entry, which may
- * include multiple pages. Find the initial page structure
- * and the starting offset within the page, and update
- * the *offset and *index values for the next loop.
- */
- cnt = 0;
- while (cnt < buflen && *index < scsi_sg_count(srb)) {
- struct page *page = sg_page(sg) +
- ((sg->offset + *offset) >> PAGE_SHIFT);
- unsigned int poff = (sg->offset + *offset) &
- (PAGE_SIZE - 1);
- unsigned int sglen = sg->length - *offset;
-
- if (sglen > buflen - cnt) {
- /* Transfer ends within this s-g entry */
- sglen = buflen - cnt;
- *offset += sglen;
- } else {
- /* Transfer continues to next s-g entry */
- *offset = 0;
- ++*index;
- ++sg;
- }
-
- while (sglen > 0) {
- unsigned int plen = min(sglen, (unsigned int)
- PAGE_SIZE - poff);
-
- if (dir == TO_XFER_BUF)
- memcpy_to_page(page, poff, buffer + cnt, plen);
- else
- memcpy_from_page(buffer + cnt, page, poff, plen);
-
- /* Start at the beginning of the next page */
- poff = 0;
- ++page;
- cnt += plen;
- sglen -= plen;
- }
- }
- }
-
- /* Return the amount actually transferred */
- return cnt;
-}
-
-/*
- * Store the contents of buffer into srb's transfer buffer and set the
- * SCSI residue.
- */
-void rtsx_stor_set_xfer_buf(unsigned char *buffer,
- unsigned int buflen, struct scsi_cmnd *srb)
-{
- unsigned int index = 0, offset = 0;
-
- rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
- TO_XFER_BUF);
- if (buflen < scsi_bufflen(srb))
- scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
-}
-
-void rtsx_stor_get_xfer_buf(unsigned char *buffer,
- unsigned int buflen, struct scsi_cmnd *srb)
-{
- unsigned int index = 0, offset = 0;
-
- rtsx_stor_access_xfer_buf(buffer, buflen, srb, &index, &offset,
- FROM_XFER_BUF);
- if (buflen < scsi_bufflen(srb))
- scsi_set_resid(srb, scsi_bufflen(srb) - buflen);
-}
-
-/***********************************************************************
- * Transport routines
- ***********************************************************************/
-
-/*
- * Invoke the transport and basic error-handling/recovery methods
- *
- * This is used to send the message to the device and receive the response.
- */
-void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int result;
-
- result = rtsx_scsi_handler(srb, chip);
-
- /*
- * if the command gets aborted by the higher layers, we need to
- * short-circuit all other processing.
- */
- if (rtsx_chk_stat(chip, RTSX_STAT_ABORT)) {
- dev_dbg(rtsx_dev(chip), "-- command was aborted\n");
- srb->result = DID_ABORT << 16;
- goto handle_errors;
- }
-
- /* if there is a transport error, reset and don't auto-sense */
- if (result == TRANSPORT_ERROR) {
- dev_dbg(rtsx_dev(chip), "-- transport indicates error, resetting\n");
- srb->result = DID_ERROR << 16;
- goto handle_errors;
- }
-
- srb->result = SAM_STAT_GOOD;
-
- /*
- * If we have a failure, we're going to do a REQUEST_SENSE
- * automatically. Note that we differentiate between a command
- * "failure" and an "error" in the transport mechanism.
- */
- if (result == TRANSPORT_FAILED) {
- /* set the result so the higher layers expect this data */
- srb->result = SAM_STAT_CHECK_CONDITION;
- memcpy(srb->sense_buffer,
- (unsigned char *)&chip->sense_buffer[SCSI_LUN(srb)],
- sizeof(struct sense_data_t));
- }
-
- return;
-
-handle_errors:
- return;
-}
-
-void rtsx_add_cmd(struct rtsx_chip *chip,
- u8 cmd_type, u16 reg_addr, u8 mask, u8 data)
-{
- __le32 *cb = (__le32 *)(chip->host_cmds_ptr);
- u32 val = 0;
-
- val |= (u32)(cmd_type & 0x03) << 30;
- val |= (u32)(reg_addr & 0x3FFF) << 16;
- val |= (u32)mask << 8;
- val |= (u32)data;
-
- spin_lock_irq(&chip->rtsx->reg_lock);
- if (chip->ci < (HOST_CMDS_BUF_LEN / 4))
- cb[(chip->ci)++] = cpu_to_le32(val);
-
- spin_unlock_irq(&chip->rtsx->reg_lock);
-}
-
-void rtsx_send_cmd_no_wait(struct rtsx_chip *chip)
-{
- u32 val = BIT(31);
-
- rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
-
- val |= (u32)(chip->ci * 4) & 0x00FFFFFF;
- /* Hardware Auto Response */
- val |= 0x40000000;
- rtsx_writel(chip, RTSX_HCBCTLR, val);
-}
-
-int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout)
-{
- struct rtsx_dev *rtsx = chip->rtsx;
- struct completion trans_done;
- u32 val = BIT(31);
- long timeleft;
- int err = 0;
-
- if (card == SD_CARD)
- rtsx->check_card_cd = SD_EXIST;
- else if (card == MS_CARD)
- rtsx->check_card_cd = MS_EXIST;
- else if (card == XD_CARD)
- rtsx->check_card_cd = XD_EXIST;
- else
- rtsx->check_card_cd = 0;
-
- spin_lock_irq(&rtsx->reg_lock);
-
- /* set up data structures for the wakeup system */
- rtsx->done = &trans_done;
- rtsx->trans_result = TRANS_NOT_READY;
- init_completion(&trans_done);
- rtsx->trans_state = STATE_TRANS_CMD;
-
- rtsx_writel(chip, RTSX_HCBAR, chip->host_cmds_addr);
-
- val |= (u32)(chip->ci * 4) & 0x00FFFFFF;
- /* Hardware Auto Response */
- val |= 0x40000000;
- rtsx_writel(chip, RTSX_HCBCTLR, val);
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- /* Wait for TRANS_OK_INT */
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto finish_send_cmd;
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL)
- err = -EIO;
- else if (rtsx->trans_result == TRANS_RESULT_OK)
- err = 0;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
-finish_send_cmd:
- rtsx->done = NULL;
- rtsx->trans_state = STATE_TRANS_NONE;
-
- if (err < 0)
- rtsx_stop_cmd(chip, card);
-
- return err;
-}
-
-static inline void rtsx_add_sg_tbl(struct rtsx_chip *chip,
- u32 addr, u32 len, u8 option)
-{
- __le64 *sgb = (__le64 *)(chip->host_sg_tbl_ptr);
- u64 val = 0;
- u32 temp_len = 0;
- u8 temp_opt = 0;
-
- do {
- if (len > 0x80000) {
- temp_len = 0x80000;
- temp_opt = option & (~RTSX_SG_END);
- } else {
- temp_len = len;
- temp_opt = option;
- }
- val = ((u64)addr << 32) | ((u64)temp_len << 12) | temp_opt;
-
- if (chip->sgi < (HOST_SG_TBL_BUF_LEN / 8))
- sgb[(chip->sgi)++] = cpu_to_le64(val);
-
- len -= temp_len;
- addr += temp_len;
- } while (len);
-}
-
-static int rtsx_transfer_sglist_adma_partial(struct rtsx_chip *chip, u8 card,
- struct scatterlist *sg, int num_sg,
- unsigned int *index,
- unsigned int *offset, int size,
- enum dma_data_direction dma_dir,
- int timeout)
-{
- struct rtsx_dev *rtsx = chip->rtsx;
- struct completion trans_done;
- u8 dir;
- int sg_cnt, i, resid;
- int err = 0;
- long timeleft;
- struct scatterlist *sg_ptr;
- u32 val = TRIG_DMA;
-
- if (!sg || num_sg <= 0 || !offset || !index)
- return -EIO;
-
- if (dma_dir == DMA_TO_DEVICE)
- dir = HOST_TO_DEVICE;
- else if (dma_dir == DMA_FROM_DEVICE)
- dir = DEVICE_TO_HOST;
- else
- return -ENXIO;
-
- if (card == SD_CARD)
- rtsx->check_card_cd = SD_EXIST;
- else if (card == MS_CARD)
- rtsx->check_card_cd = MS_EXIST;
- else if (card == XD_CARD)
- rtsx->check_card_cd = XD_EXIST;
- else
- rtsx->check_card_cd = 0;
-
- spin_lock_irq(&rtsx->reg_lock);
-
- /* set up data structures for the wakeup system */
- rtsx->done = &trans_done;
-
- rtsx->trans_state = STATE_TRANS_SG;
- rtsx->trans_result = TRANS_NOT_READY;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- sg_cnt = dma_map_sg(&rtsx->pci->dev, sg, num_sg, dma_dir);
-
- resid = size;
- sg_ptr = sg;
- chip->sgi = 0;
- /*
- * Usually the next entry will be @sg@ + 1, but if this sg element
- * is part of a chained scatterlist, it could jump to the start of
- * a new scatterlist array. So here we use sg_next to move to
- * the proper sg.
- */
- for (i = 0; i < *index; i++)
- sg_ptr = sg_next(sg_ptr);
- for (i = *index; i < sg_cnt; i++) {
- dma_addr_t addr;
- unsigned int len;
- u8 option;
-
- addr = sg_dma_address(sg_ptr);
- len = sg_dma_len(sg_ptr);
-
- dev_dbg(rtsx_dev(chip), "DMA addr: 0x%x, Len: 0x%x\n",
- (unsigned int)addr, len);
- dev_dbg(rtsx_dev(chip), "*index = %d, *offset = %d\n",
- *index, *offset);
-
- addr += *offset;
-
- if ((len - *offset) > resid) {
- *offset += resid;
- len = resid;
- resid = 0;
- } else {
- resid -= (len - *offset);
- len -= *offset;
- *offset = 0;
- *index = *index + 1;
- }
- option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA;
- if ((i == sg_cnt - 1) || !resid)
- option |= RTSX_SG_END;
-
- rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option);
-
- if (!resid)
- break;
-
- sg_ptr = sg_next(sg_ptr);
- }
-
- dev_dbg(rtsx_dev(chip), "SG table count = %d\n", chip->sgi);
-
- val |= (u32)(dir & 0x01) << 29;
- val |= ADMA_MODE;
-
- spin_lock_irq(&rtsx->reg_lock);
-
- init_completion(&trans_done);
-
- rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr);
- rtsx_writel(chip, RTSX_HDBCTLR, val);
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
- __func__, __LINE__);
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto out;
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL) {
- err = -EIO;
- spin_unlock_irq(&rtsx->reg_lock);
- goto out;
- }
- spin_unlock_irq(&rtsx->reg_lock);
-
- /* Wait for TRANS_OK_INT */
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_NOT_READY) {
- init_completion(&trans_done);
- spin_unlock_irq(&rtsx->reg_lock);
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
- __func__, __LINE__);
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto out;
- }
- } else {
- spin_unlock_irq(&rtsx->reg_lock);
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL)
- err = -EIO;
- else if (rtsx->trans_result == TRANS_RESULT_OK)
- err = 0;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
-out:
- rtsx->done = NULL;
- rtsx->trans_state = STATE_TRANS_NONE;
- dma_unmap_sg(&rtsx->pci->dev, sg, num_sg, dma_dir);
-
- if (err < 0)
- rtsx_stop_cmd(chip, card);
-
- return err;
-}
-
-static int rtsx_transfer_sglist_adma(struct rtsx_chip *chip, u8 card,
- struct scatterlist *sg, int num_sg,
- enum dma_data_direction dma_dir,
- int timeout)
-{
- struct rtsx_dev *rtsx = chip->rtsx;
- struct completion trans_done;
- u8 dir;
- int buf_cnt, i;
- int err = 0;
- long timeleft;
- struct scatterlist *sg_ptr;
-
- if (!sg || num_sg <= 0)
- return -EIO;
-
- if (dma_dir == DMA_TO_DEVICE)
- dir = HOST_TO_DEVICE;
- else if (dma_dir == DMA_FROM_DEVICE)
- dir = DEVICE_TO_HOST;
- else
- return -ENXIO;
-
- if (card == SD_CARD)
- rtsx->check_card_cd = SD_EXIST;
- else if (card == MS_CARD)
- rtsx->check_card_cd = MS_EXIST;
- else if (card == XD_CARD)
- rtsx->check_card_cd = XD_EXIST;
- else
- rtsx->check_card_cd = 0;
-
- spin_lock_irq(&rtsx->reg_lock);
-
- /* set up data structures for the wakeup system */
- rtsx->done = &trans_done;
-
- rtsx->trans_state = STATE_TRANS_SG;
- rtsx->trans_result = TRANS_NOT_READY;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- buf_cnt = dma_map_sg(&rtsx->pci->dev, sg, num_sg, dma_dir);
-
- sg_ptr = sg;
-
- for (i = 0; i <= buf_cnt / (HOST_SG_TBL_BUF_LEN / 8); i++) {
- u32 val = TRIG_DMA;
- int sg_cnt, j;
-
- if (i == buf_cnt / (HOST_SG_TBL_BUF_LEN / 8))
- sg_cnt = buf_cnt % (HOST_SG_TBL_BUF_LEN / 8);
- else
- sg_cnt = HOST_SG_TBL_BUF_LEN / 8;
-
- chip->sgi = 0;
- for (j = 0; j < sg_cnt; j++) {
- dma_addr_t addr = sg_dma_address(sg_ptr);
- unsigned int len = sg_dma_len(sg_ptr);
- u8 option;
-
- dev_dbg(rtsx_dev(chip), "DMA addr: 0x%x, Len: 0x%x\n",
- (unsigned int)addr, len);
-
- option = RTSX_SG_VALID | RTSX_SG_TRANS_DATA;
- if (j == (sg_cnt - 1))
- option |= RTSX_SG_END;
-
- rtsx_add_sg_tbl(chip, (u32)addr, (u32)len, option);
-
- sg_ptr = sg_next(sg_ptr);
- }
-
- dev_dbg(rtsx_dev(chip), "SG table count = %d\n", chip->sgi);
-
- val |= (u32)(dir & 0x01) << 29;
- val |= ADMA_MODE;
-
- spin_lock_irq(&rtsx->reg_lock);
-
- init_completion(&trans_done);
-
- rtsx_writel(chip, RTSX_HDBAR, chip->host_sg_tbl_addr);
- rtsx_writel(chip, RTSX_HDBCTLR, val);
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
- __func__, __LINE__);
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto out;
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL) {
- err = -EIO;
- spin_unlock_irq(&rtsx->reg_lock);
- goto out;
- }
- spin_unlock_irq(&rtsx->reg_lock);
-
- sg_ptr += sg_cnt;
- }
-
- /* Wait for TRANS_OK_INT */
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_NOT_READY) {
- init_completion(&trans_done);
- spin_unlock_irq(&rtsx->reg_lock);
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
- __func__, __LINE__);
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto out;
- }
- } else {
- spin_unlock_irq(&rtsx->reg_lock);
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL)
- err = -EIO;
- else if (rtsx->trans_result == TRANS_RESULT_OK)
- err = 0;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
-out:
- rtsx->done = NULL;
- rtsx->trans_state = STATE_TRANS_NONE;
- dma_unmap_sg(&rtsx->pci->dev, sg, num_sg, dma_dir);
-
- if (err < 0)
- rtsx_stop_cmd(chip, card);
-
- return err;
-}
-
-static int rtsx_transfer_buf(struct rtsx_chip *chip, u8 card, void *buf,
- size_t len, enum dma_data_direction dma_dir,
- int timeout)
-{
- struct rtsx_dev *rtsx = chip->rtsx;
- struct completion trans_done;
- dma_addr_t addr;
- u8 dir;
- int err = 0;
- u32 val = BIT(31);
- long timeleft;
-
- if (!buf || len <= 0)
- return -EIO;
-
- if (dma_dir == DMA_TO_DEVICE)
- dir = HOST_TO_DEVICE;
- else if (dma_dir == DMA_FROM_DEVICE)
- dir = DEVICE_TO_HOST;
- else
- return -ENXIO;
-
- addr = dma_map_single(&rtsx->pci->dev, buf, len, dma_dir);
- if (dma_mapping_error(&rtsx->pci->dev, addr))
- return -ENOMEM;
-
- if (card == SD_CARD)
- rtsx->check_card_cd = SD_EXIST;
- else if (card == MS_CARD)
- rtsx->check_card_cd = MS_EXIST;
- else if (card == XD_CARD)
- rtsx->check_card_cd = XD_EXIST;
- else
- rtsx->check_card_cd = 0;
-
- val |= (u32)(dir & 0x01) << 29;
- val |= (u32)(len & 0x00FFFFFF);
-
- spin_lock_irq(&rtsx->reg_lock);
-
- /* set up data structures for the wakeup system */
- rtsx->done = &trans_done;
-
- init_completion(&trans_done);
-
- rtsx->trans_state = STATE_TRANS_BUF;
- rtsx->trans_result = TRANS_NOT_READY;
-
- rtsx_writel(chip, RTSX_HDBAR, addr);
- rtsx_writel(chip, RTSX_HDBCTLR, val);
-
- spin_unlock_irq(&rtsx->reg_lock);
-
- /* Wait for TRANS_OK_INT */
- timeleft = wait_for_completion_interruptible_timeout(&trans_done,
- msecs_to_jiffies(timeout));
- if (timeleft <= 0) {
- dev_dbg(rtsx_dev(chip), "Timeout (%s %d)\n",
- __func__, __LINE__);
- dev_dbg(rtsx_dev(chip), "chip->int_reg = 0x%x\n",
- chip->int_reg);
- err = -ETIMEDOUT;
- goto out;
- }
-
- spin_lock_irq(&rtsx->reg_lock);
- if (rtsx->trans_result == TRANS_RESULT_FAIL)
- err = -EIO;
- else if (rtsx->trans_result == TRANS_RESULT_OK)
- err = 0;
-
- spin_unlock_irq(&rtsx->reg_lock);
-
-out:
- rtsx->done = NULL;
- rtsx->trans_state = STATE_TRANS_NONE;
- dma_unmap_single(&rtsx->pci->dev, addr, len, dma_dir);
-
- if (err < 0)
- rtsx_stop_cmd(chip, card);
-
- return err;
-}
-
-int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card,
- void *buf, size_t len, int use_sg,
- unsigned int *index, unsigned int *offset,
- enum dma_data_direction dma_dir, int timeout)
-{
- int err = 0;
-
- /* don't transfer data during abort processing */
- if (rtsx_chk_stat(chip, RTSX_STAT_ABORT))
- return -EIO;
-
- if (use_sg) {
- struct scatterlist *sg = buf;
-
- err = rtsx_transfer_sglist_adma_partial(chip, card, sg, use_sg,
- index, offset, (int)len,
- dma_dir, timeout);
- } else {
- err = rtsx_transfer_buf(chip, card,
- buf, len, dma_dir, timeout);
- }
- if (err < 0) {
- if (RTSX_TST_DELINK(chip)) {
- RTSX_CLR_DELINK(chip);
- chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
- rtsx_reinit_cards(chip, 1);
- }
- }
-
- return err;
-}
-
-int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
- int use_sg, enum dma_data_direction dma_dir, int timeout)
-{
- int err = 0;
-
- dev_dbg(rtsx_dev(chip), "use_sg = %d\n", use_sg);
-
- /* don't transfer data during abort processing */
- if (rtsx_chk_stat(chip, RTSX_STAT_ABORT))
- return -EIO;
-
- if (use_sg) {
- err = rtsx_transfer_sglist_adma(chip, card, buf,
- use_sg, dma_dir, timeout);
- } else {
- err = rtsx_transfer_buf(chip, card, buf, len, dma_dir, timeout);
- }
-
- if (err < 0) {
- if (RTSX_TST_DELINK(chip)) {
- RTSX_CLR_DELINK(chip);
- chip->need_reinit = SD_CARD | MS_CARD | XD_CARD;
- rtsx_reinit_cards(chip, 1);
- }
- }
-
- return err;
-}
-
diff --git a/drivers/staging/rts5208/rtsx_transport.h b/drivers/staging/rts5208/rtsx_transport.h
deleted file mode 100644
index 097efed24b79..000000000000
--- a/drivers/staging/rts5208/rtsx_transport.h
+++ /dev/null
@@ -1,57 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_TRANSPORT_H
-#define __REALTEK_RTSX_TRANSPORT_H
-
-#include "rtsx.h"
-#include "rtsx_chip.h"
-
-#define WAIT_TIME 2000
-
-unsigned int rtsx_stor_access_xfer_buf(unsigned char *buffer,
- unsigned int buflen,
- struct scsi_cmnd *srb,
- unsigned int *index,
- unsigned int *offset,
- enum xfer_buf_dir dir);
-void rtsx_stor_set_xfer_buf(unsigned char *buffer, unsigned int buflen,
- struct scsi_cmnd *srb);
-void rtsx_stor_get_xfer_buf(unsigned char *buffer, unsigned int buflen,
- struct scsi_cmnd *srb);
-void rtsx_invoke_transport(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-
-#define rtsx_init_cmd(chip) ((chip)->ci = 0)
-
-void rtsx_add_cmd(struct rtsx_chip *chip, u8 cmd_type, u16 reg_addr, u8 mask,
- u8 data);
-void rtsx_send_cmd_no_wait(struct rtsx_chip *chip);
-int rtsx_send_cmd(struct rtsx_chip *chip, u8 card, int timeout);
-
-static inline u8 *rtsx_get_cmd_data(struct rtsx_chip *chip)
-{
-#ifdef CMD_USING_SG
- return (u8 *)(chip->host_sg_tbl_ptr);
-#else
- return (u8 *)(chip->host_cmds_ptr);
-#endif
-}
-
-int rtsx_transfer_data(struct rtsx_chip *chip, u8 card, void *buf, size_t len,
- int use_sg, enum dma_data_direction dma_dir,
- int timeout);
-
-int rtsx_transfer_data_partial(struct rtsx_chip *chip, u8 card, void *buf,
- size_t len, int use_sg, unsigned int *index,
- unsigned int *offset,
- enum dma_data_direction dma_dir, int timeout);
-
-#endif /* __REALTEK_RTSX_TRANSPORT_H */
diff --git a/drivers/staging/rts5208/sd.c b/drivers/staging/rts5208/sd.c
deleted file mode 100644
index 74c4f476b3a4..000000000000
--- a/drivers/staging/rts5208/sd.c
+++ /dev/null
@@ -1,4717 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-
-#include "rtsx.h"
-#include "sd.h"
-
-#define SD_MAX_RETRY_COUNT 3
-
-static u16 REG_SD_CFG1;
-static u16 REG_SD_CFG2;
-static u16 REG_SD_CFG3;
-static u16 REG_SD_STAT1;
-static u16 REG_SD_STAT2;
-static u16 REG_SD_BUS_STAT;
-static u16 REG_SD_PAD_CTL;
-static u16 REG_SD_SAMPLE_POINT_CTL;
-static u16 REG_SD_PUSH_POINT_CTL;
-static u16 REG_SD_CMD0;
-static u16 REG_SD_CMD1;
-static u16 REG_SD_CMD2;
-static u16 REG_SD_CMD3;
-static u16 REG_SD_CMD4;
-static u16 REG_SD_CMD5;
-static u16 REG_SD_BYTE_CNT_L;
-static u16 REG_SD_BYTE_CNT_H;
-static u16 REG_SD_BLOCK_CNT_L;
-static u16 REG_SD_BLOCK_CNT_H;
-static u16 REG_SD_TRANSFER;
-static u16 REG_SD_VPCLK0_CTL;
-static u16 REG_SD_VPCLK1_CTL;
-static u16 REG_SD_DCMPS0_CTL;
-static u16 REG_SD_DCMPS1_CTL;
-
-static inline void sd_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct sd_info *sd_card = &chip->sd_card;
-
- sd_card->err_code |= err_code;
-}
-
-static inline void sd_clr_err_code(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
-
- sd_card->err_code = 0;
-}
-
-static inline int sd_check_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct sd_info *sd_card = &chip->sd_card;
-
- return sd_card->err_code & err_code;
-}
-
-static void sd_init_reg_addr(struct rtsx_chip *chip)
-{
- REG_SD_CFG1 = 0xFD31;
- REG_SD_CFG2 = 0xFD33;
- REG_SD_CFG3 = 0xFD3E;
- REG_SD_STAT1 = 0xFD30;
- REG_SD_STAT2 = 0;
- REG_SD_BUS_STAT = 0;
- REG_SD_PAD_CTL = 0;
- REG_SD_SAMPLE_POINT_CTL = 0;
- REG_SD_PUSH_POINT_CTL = 0;
- REG_SD_CMD0 = 0xFD34;
- REG_SD_CMD1 = 0xFD35;
- REG_SD_CMD2 = 0xFD36;
- REG_SD_CMD3 = 0xFD37;
- REG_SD_CMD4 = 0xFD38;
- REG_SD_CMD5 = 0xFD5A;
- REG_SD_BYTE_CNT_L = 0xFD39;
- REG_SD_BYTE_CNT_H = 0xFD3A;
- REG_SD_BLOCK_CNT_L = 0xFD3B;
- REG_SD_BLOCK_CNT_H = 0xFD3C;
- REG_SD_TRANSFER = 0xFD32;
- REG_SD_VPCLK0_CTL = 0;
- REG_SD_VPCLK1_CTL = 0;
- REG_SD_DCMPS0_CTL = 0;
- REG_SD_DCMPS1_CTL = 0;
-}
-
-static int sd_check_data0_status(struct rtsx_chip *chip)
-{
- int retval;
- u8 stat;
-
- retval = rtsx_read_register(chip, REG_SD_STAT1, &stat);
- if (retval)
- return retval;
-
- if (!(stat & SD_DAT0_STATUS)) {
- sd_set_err_code(chip, SD_BUSY);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
- u32 arg, u8 rsp_type, u8 *rsp, int rsp_len)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int timeout = 100;
- u16 reg_addr;
- u8 *ptr;
- int stat_idx = 0;
- int rty_cnt = 0;
-
- sd_clr_err_code(chip);
-
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d, arg = 0x%08x\n", cmd_idx, arg);
-
- if (rsp_type == SD_RSP_TYPE_R1b)
- timeout = 3000;
-
-RTY_SEND_CMD:
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
- 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END | SD_STAT_IDLE, SD_TRANSFER_END |
- SD_STAT_IDLE);
-
- if (rsp_type == SD_RSP_TYPE_R2) {
- for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- stat_idx = 16;
- } else if (rsp_type != SD_RSP_TYPE_R0) {
- for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- stat_idx = 5;
- }
-
- rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
-
- retval = rtsx_send_cmd(chip, SD_CARD, timeout);
- if (retval < 0) {
- u8 val;
-
- rtsx_read_register(chip, REG_SD_STAT1, &val);
- dev_dbg(rtsx_dev(chip), "SD_STAT1: 0x%x\n", val);
-
- rtsx_read_register(chip, REG_SD_CFG3, &val);
- dev_dbg(rtsx_dev(chip), "SD_CFG3: 0x%x\n", val);
-
- if (retval == -ETIMEDOUT) {
- if (rsp_type & SD_WAIT_BUSY_END) {
- retval = sd_check_data0_status(chip);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- return retval;
- }
- } else {
- sd_set_err_code(chip, SD_TO_ERR);
- }
- retval = STATUS_TIMEDOUT;
- } else {
- retval = STATUS_FAIL;
- }
- rtsx_clear_sd_error(chip);
-
- return retval;
- }
-
- if (rsp_type == SD_RSP_TYPE_R0)
- return STATUS_SUCCESS;
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- if ((ptr[0] & 0xC0) != 0) {
- sd_set_err_code(chip, SD_STS_ERR);
- return STATUS_FAIL;
- }
-
- if (!(rsp_type & SD_NO_CHECK_CRC7)) {
- if (ptr[stat_idx] & SD_CRC7_ERR) {
- if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
- sd_set_err_code(chip, SD_CRC_ERR);
- return STATUS_FAIL;
- }
- if (rty_cnt < SD_MAX_RETRY_COUNT) {
- wait_timeout(20);
- rty_cnt++;
- goto RTY_SEND_CMD;
- } else {
- sd_set_err_code(chip, SD_CRC_ERR);
- return STATUS_FAIL;
- }
- }
- }
-
- if (rsp_type == SD_RSP_TYPE_R1 || rsp_type == SD_RSP_TYPE_R1b) {
- if (cmd_idx != SEND_RELATIVE_ADDR &&
- cmd_idx != SEND_IF_COND) {
- if (cmd_idx != STOP_TRANSMISSION) {
- if (ptr[1] & 0x80)
- return STATUS_FAIL;
- }
-#ifdef SUPPORT_SD_LOCK
- if (ptr[1] & 0x7D) {
-#else
- if (ptr[1] & 0x7F) {
-#endif
- dev_dbg(rtsx_dev(chip), "ptr[1]: 0x%02x\n",
- ptr[1]);
- return STATUS_FAIL;
- }
- if (ptr[2] & 0xFF) {
- dev_dbg(rtsx_dev(chip), "ptr[2]: 0x%02x\n",
- ptr[2]);
- return STATUS_FAIL;
- }
- if (ptr[3] & 0x80) {
- dev_dbg(rtsx_dev(chip), "ptr[3]: 0x%02x\n",
- ptr[3]);
- return STATUS_FAIL;
- }
- if (ptr[3] & 0x01)
- sd_card->sd_data_buf_ready = 1;
- else
- sd_card->sd_data_buf_ready = 0;
- }
- }
-
- if (rsp && rsp_len)
- memcpy(rsp, ptr, rsp_len);
-
- return STATUS_SUCCESS;
-}
-
-static int sd_read_data(struct rtsx_chip *chip,
- u8 trans_mode, u8 *cmd, int cmd_len, u16 byte_cnt,
- u16 blk_cnt, u8 bus_width, u8 *buf, int buf_len,
- int timeout)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i;
-
- sd_clr_err_code(chip);
-
- if (!buf)
- buf_len = 0;
-
- if (buf_len > 512)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- if (cmd_len) {
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", cmd[0] - 0x40);
- for (i = 0; i < (min(cmd_len, 6)); i++)
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0 + i,
- 0xFF, cmd[i]);
- }
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
- (u8)byte_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
- (u8)(byte_cnt >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
- (u8)blk_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
- (u8)(blk_cnt >> 8));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
- SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
- SD_CHECK_CRC7 | SD_RSP_LEN_6);
- if (trans_mode != SD_TM_AUTO_TUNING)
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- CARD_DATA_SOURCE, 0x01, PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- trans_mode | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
- SD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, SD_CARD, timeout);
- if (retval < 0) {
- if (retval == -ETIMEDOUT) {
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- }
-
- return STATUS_FAIL;
- }
-
- if (buf && buf_len) {
- retval = rtsx_read_ppbuf(chip, buf, buf_len);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_write_data(struct rtsx_chip *chip, u8 trans_mode,
- u8 *cmd, int cmd_len, u16 byte_cnt, u16 blk_cnt,
- u8 bus_width, u8 *buf, int buf_len, int timeout)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i;
-
- sd_clr_err_code(chip);
-
- if (!buf)
- buf_len = 0;
-
- if (buf_len > 512) {
- /* This function can't write data more than one page */
- return STATUS_FAIL;
- }
-
- if (buf && buf_len) {
- retval = rtsx_write_ppbuf(chip, buf, buf_len);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- if (cmd_len) {
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", cmd[0] - 0x40);
- for (i = 0; i < (min(cmd_len, 6)); i++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- REG_SD_CMD0 + i, 0xFF, cmd[i]);
- }
- }
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
- (u8)byte_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
- (u8)(byte_cnt >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
- (u8)blk_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
- (u8)(blk_cnt >> 8));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
- SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
- SD_CHECK_CRC7 | SD_RSP_LEN_6);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- trans_mode | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
- SD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, SD_CARD, timeout);
- if (retval < 0) {
- if (retval == -ETIMEDOUT) {
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- }
-
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_check_csd(struct rtsx_chip *chip, char check_wp)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i;
- u8 csd_ver, trans_speed;
- u8 rsp[16];
-
- for (i = 0; i < 6; i++) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = sd_send_cmd_get_rsp(chip, SEND_CSD, sd_card->sd_addr,
- SD_RSP_TYPE_R2, rsp, 16);
- if (retval == STATUS_SUCCESS)
- break;
- }
-
- if (i == 6)
- return STATUS_FAIL;
-
- memcpy(sd_card->raw_csd, rsp + 1, 15);
-
- dev_dbg(rtsx_dev(chip), "CSD Response:\n");
- dev_dbg(rtsx_dev(chip), "%*ph\n", 16, sd_card->raw_csd);
-
- csd_ver = (rsp[1] & 0xc0) >> 6;
- dev_dbg(rtsx_dev(chip), "csd_ver = %d\n", csd_ver);
-
- trans_speed = rsp[4];
- if ((trans_speed & 0x07) == 0x02) {
- if ((trans_speed & 0xf8) >= 0x30) {
- if (chip->asic_code)
- sd_card->sd_clock = 47;
- else
- sd_card->sd_clock = CLK_50;
-
- } else if ((trans_speed & 0xf8) == 0x28) {
- if (chip->asic_code)
- sd_card->sd_clock = 39;
- else
- sd_card->sd_clock = CLK_40;
-
- } else if ((trans_speed & 0xf8) == 0x20) {
- if (chip->asic_code)
- sd_card->sd_clock = 29;
- else
- sd_card->sd_clock = CLK_30;
-
- } else if ((trans_speed & 0xf8) >= 0x10) {
- if (chip->asic_code)
- sd_card->sd_clock = 23;
- else
- sd_card->sd_clock = CLK_20;
-
- } else if ((trans_speed & 0x08) >= 0x08) {
- if (chip->asic_code)
- sd_card->sd_clock = 19;
- else
- sd_card->sd_clock = CLK_20;
- } else {
- return STATUS_FAIL;
- }
- } else {
- return STATUS_FAIL;
- }
-
- if (CHK_MMC_SECTOR_MODE(sd_card)) {
- sd_card->capacity = 0;
- } else {
- if ((!CHK_SD_HCXC(sd_card)) || csd_ver == 0) {
- u8 blk_size, c_size_mult;
- u16 c_size;
-
- blk_size = rsp[6] & 0x0F;
- c_size = ((u16)(rsp[7] & 0x03) << 10)
- + ((u16)rsp[8] << 2)
- + ((u16)(rsp[9] & 0xC0) >> 6);
- c_size_mult = (u8)((rsp[10] & 0x03) << 1);
- c_size_mult += (rsp[11] & 0x80) >> 7;
- sd_card->capacity = (((u32)(c_size + 1)) *
- (1 << (c_size_mult + 2)))
- << (blk_size - 9);
- } else {
- u32 total_sector = 0;
-
- total_sector = (((u32)rsp[8] & 0x3f) << 16) |
- ((u32)rsp[9] << 8) | (u32)rsp[10];
- sd_card->capacity = (total_sector + 1) << 10;
- }
- }
-
- if (check_wp) {
- if (rsp[15] & 0x30)
- chip->card_wp |= SD_CARD;
-
- dev_dbg(rtsx_dev(chip), "CSD WP Status: 0x%x\n", rsp[15]);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_set_sample_push_timing(struct rtsx_chip *chip)
-{
- int retval;
- struct sd_info *sd_card = &chip->sd_card;
- u8 val = 0;
-
- if ((chip->sd_ctl & SD_PUSH_POINT_CTL_MASK) == SD_PUSH_POINT_DELAY)
- val |= 0x10;
-
- if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) == SD_SAMPLE_POINT_AUTO) {
- if (chip->asic_code) {
- if (CHK_SD_HS(sd_card) || CHK_MMC_52M(sd_card)) {
- if (val & 0x10)
- val |= 0x04;
- else
- val |= 0x08;
- }
- } else {
- if (val & 0x10)
- val |= 0x04;
- else
- val |= 0x08;
- }
- } else if ((chip->sd_ctl & SD_SAMPLE_POINT_CTL_MASK) ==
- SD_SAMPLE_POINT_DELAY) {
- if (val & 0x10)
- val |= 0x04;
- else
- val |= 0x08;
- }
-
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x1C, val);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static void sd_choose_proper_clock(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
-
- if (CHK_SD_SDR104(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = chip->asic_sd_sdr104_clk;
- else
- sd_card->sd_clock = chip->fpga_sd_sdr104_clk;
-
- } else if (CHK_SD_DDR50(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = chip->asic_sd_ddr50_clk;
- else
- sd_card->sd_clock = chip->fpga_sd_ddr50_clk;
-
- } else if (CHK_SD_SDR50(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = chip->asic_sd_sdr50_clk;
- else
- sd_card->sd_clock = chip->fpga_sd_sdr50_clk;
-
- } else if (CHK_SD_HS(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = chip->asic_sd_hs_clk;
- else
- sd_card->sd_clock = chip->fpga_sd_hs_clk;
-
- } else if (CHK_MMC_52M(sd_card) || CHK_MMC_DDR52(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = chip->asic_mmc_52m_clk;
- else
- sd_card->sd_clock = chip->fpga_mmc_52m_clk;
-
- } else if (CHK_MMC_26M(sd_card)) {
- if (chip->asic_code)
- sd_card->sd_clock = 48;
- else
- sd_card->sd_clock = CLK_50;
- }
-}
-
-static int sd_set_clock_divider(struct rtsx_chip *chip, u8 clk_div)
-{
- int retval;
- u8 mask = 0, val = 0;
-
- mask = 0x60;
- if (clk_div == SD_CLK_DIVIDE_0)
- val = 0x00;
- else if (clk_div == SD_CLK_DIVIDE_128)
- val = 0x40;
- else if (clk_div == SD_CLK_DIVIDE_256)
- val = 0x20;
-
- retval = rtsx_write_register(chip, REG_SD_CFG1, mask, val);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_set_init_para(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- retval = sd_set_sample_push_timing(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- sd_choose_proper_clock(chip);
-
- retval = switch_clock(chip, sd_card->sd_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int sd_select_card(struct rtsx_chip *chip, int select)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd_idx, cmd_type;
- u32 addr;
-
- if (select) {
- cmd_idx = SELECT_CARD;
- cmd_type = SD_RSP_TYPE_R1;
- addr = sd_card->sd_addr;
- } else {
- cmd_idx = DESELECT_CARD;
- cmd_type = SD_RSP_TYPE_R0;
- addr = 0;
- }
-
- retval = sd_send_cmd_get_rsp(chip, cmd_idx, addr, cmd_type, NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-#ifdef SUPPORT_SD_LOCK
-static int sd_update_lock_status(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 rsp[5];
-
- retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, rsp, 5);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (rsp[1] & 0x02)
- sd_card->sd_lock_status |= SD_LOCKED;
- else
- sd_card->sd_lock_status &= ~SD_LOCKED;
-
- dev_dbg(rtsx_dev(chip), "sd_card->sd_lock_status = 0x%x\n",
- sd_card->sd_lock_status);
-
- if (rsp[1] & 0x01)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-#endif
-
-static int sd_wait_state_data_ready(struct rtsx_chip *chip, u8 state,
- u8 data_ready, int polling_cnt)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval, i;
- u8 rsp[5];
-
- for (i = 0; i < polling_cnt; i++) {
- retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr, SD_RSP_TYPE_R1,
- rsp, 5);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (((rsp[3] & 0x1E) == state) &&
- ((rsp[3] & 0x01) == data_ready))
- return STATUS_SUCCESS;
- }
-
- return STATUS_FAIL;
-}
-
-static int sd_change_bank_voltage(struct rtsx_chip *chip, u8 voltage)
-{
- int retval;
-
- if (voltage == SD_IO_3V3) {
- if (chip->asic_code) {
- retval = rtsx_write_phy_register(chip, 0x08,
- 0x4FC0 |
- chip->phy_voltage);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, SD_PAD_CTL,
- SD_IO_USING_1V8, 0);
- if (retval)
- return retval;
- }
- } else if (voltage == SD_IO_1V8) {
- if (chip->asic_code) {
- retval = rtsx_write_phy_register(chip, 0x08,
- 0x4C40 |
- chip->phy_voltage);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, SD_PAD_CTL,
- SD_IO_USING_1V8,
- SD_IO_USING_1V8);
- if (retval)
- return retval;
- }
- } else {
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_voltage_switch(struct rtsx_chip *chip)
-{
- int retval;
- u8 stat;
-
- retval = rtsx_write_register(chip, SD_BUS_STAT,
- SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP,
- SD_CLK_TOGGLE_EN);
- if (retval)
- return retval;
-
- retval = sd_send_cmd_get_rsp(chip, VOLTAGE_SWITCH, 0, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- udelay(chip->sd_voltage_switch_delay);
-
- retval = rtsx_read_register(chip, SD_BUS_STAT, &stat);
- if (retval)
- return retval;
- if (stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
- SD_DAT1_STATUS | SD_DAT0_STATUS)) {
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, SD_BUS_STAT, 0xFF,
- SD_CLK_FORCE_STOP);
- if (retval)
- return retval;
- retval = sd_change_bank_voltage(chip, SD_IO_1V8);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- wait_timeout(50);
-
- retval = rtsx_write_register(chip, SD_BUS_STAT, 0xFF,
- SD_CLK_TOGGLE_EN);
- if (retval)
- return retval;
- wait_timeout(10);
-
- retval = rtsx_read_register(chip, SD_BUS_STAT, &stat);
- if (retval)
- return retval;
- if ((stat & (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
- SD_DAT1_STATUS | SD_DAT0_STATUS)) !=
- (SD_CMD_STATUS | SD_DAT3_STATUS | SD_DAT2_STATUS |
- SD_DAT1_STATUS | SD_DAT0_STATUS)) {
- dev_dbg(rtsx_dev(chip), "SD_BUS_STAT: 0x%x\n", stat);
- rtsx_write_register(chip, SD_BUS_STAT, SD_CLK_TOGGLE_EN |
- SD_CLK_FORCE_STOP, 0);
- rtsx_write_register(chip, CARD_CLK_EN, 0xFF, 0);
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, SD_BUS_STAT,
- SD_CLK_TOGGLE_EN | SD_CLK_FORCE_STOP, 0);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_reset_dcm(struct rtsx_chip *chip, u8 tune_dir)
-{
- int retval;
-
- if (tune_dir == TUNE_RX) {
- retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF,
- DCM_RESET | DCM_RX);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, DCM_RX);
- if (retval)
- return retval;
- } else {
- retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF,
- DCM_RESET | DCM_TX);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, DCM_DRP_CTL, 0xFF, DCM_TX);
- if (retval)
- return retval;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_change_phase(struct rtsx_chip *chip, u8 sample_point, u8 tune_dir)
-{
- struct sd_info *sd_card = &chip->sd_card;
- u16 SD_VP_CTL, SD_DCMPS_CTL;
- u8 val;
- int retval;
- bool ddr_rx = false;
-
- dev_dbg(rtsx_dev(chip), "%s (sample_point = %d, tune_dir = %d)\n",
- __func__, sample_point, tune_dir);
-
- if (tune_dir == TUNE_RX) {
- SD_VP_CTL = SD_VPRX_CTL;
- SD_DCMPS_CTL = SD_DCMPS_RX_CTL;
- if (CHK_SD_DDR50(sd_card))
- ddr_rx = true;
- } else {
- SD_VP_CTL = SD_VPTX_CTL;
- SD_DCMPS_CTL = SD_DCMPS_TX_CTL;
- }
-
- if (chip->asic_code) {
- retval = rtsx_write_register(chip, CLK_CTL, CHANGE_CLK,
- CHANGE_CLK);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SD_VP_CTL, 0x1F,
- sample_point);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, 0);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SD_VPCLK0_CTL,
- PHASE_NOT_RESET, PHASE_NOT_RESET);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CLK_CTL, CHANGE_CLK, 0);
- if (retval)
- return retval;
- } else {
- rtsx_read_register(chip, SD_VP_CTL, &val);
- dev_dbg(rtsx_dev(chip), "SD_VP_CTL: 0x%x\n", val);
- rtsx_read_register(chip, SD_DCMPS_CTL, &val);
- dev_dbg(rtsx_dev(chip), "SD_DCMPS_CTL: 0x%x\n", val);
-
- if (ddr_rx) {
- retval = rtsx_write_register(chip, SD_VP_CTL,
- PHASE_CHANGE,
- PHASE_CHANGE);
- if (retval)
- return retval;
- udelay(50);
- retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF,
- PHASE_CHANGE |
- PHASE_NOT_RESET |
- sample_point);
- if (retval)
- return retval;
- } else {
- retval = rtsx_write_register(chip, CLK_CTL,
- CHANGE_CLK, CHANGE_CLK);
- if (retval)
- return retval;
- udelay(50);
- retval = rtsx_write_register(chip, SD_VP_CTL, 0xFF,
- PHASE_NOT_RESET |
- sample_point);
- if (retval)
- return retval;
- }
- udelay(100);
-
- rtsx_init_cmd(chip);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SD_DCMPS_CTL, DCMPS_CHANGE,
- DCMPS_CHANGE);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SD_DCMPS_CTL,
- DCMPS_CHANGE_DONE, DCMPS_CHANGE_DONE);
- retval = rtsx_send_cmd(chip, SD_CARD, 100);
- if (retval != STATUS_SUCCESS)
- goto fail;
-
- val = *rtsx_get_cmd_data(chip);
- if (val & DCMPS_ERROR)
- goto fail;
-
- if ((val & DCMPS_CURRENT_PHASE) != sample_point)
- goto fail;
-
- retval = rtsx_write_register(chip, SD_DCMPS_CTL,
- DCMPS_CHANGE, 0);
- if (retval)
- return retval;
- if (ddr_rx) {
- retval = rtsx_write_register(chip, SD_VP_CTL,
- PHASE_CHANGE, 0);
- if (retval)
- return retval;
- } else {
- retval = rtsx_write_register(chip, CLK_CTL,
- CHANGE_CLK, 0);
- if (retval)
- return retval;
- }
-
- udelay(50);
- }
-
- retval = rtsx_write_register(chip, SD_CFG1, SD_ASYNC_FIFO_NOT_RST, 0);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-
-fail:
- rtsx_read_register(chip, SD_VP_CTL, &val);
- dev_dbg(rtsx_dev(chip), "SD_VP_CTL: 0x%x\n", val);
- rtsx_read_register(chip, SD_DCMPS_CTL, &val);
- dev_dbg(rtsx_dev(chip), "SD_DCMPS_CTL: 0x%x\n", val);
-
- rtsx_write_register(chip, SD_DCMPS_CTL, DCMPS_CHANGE, 0);
- rtsx_write_register(chip, SD_VP_CTL, PHASE_CHANGE, 0);
- mdelay(10);
- sd_reset_dcm(chip, tune_dir);
- return STATUS_FAIL;
-}
-
-static int sd_check_spec(struct rtsx_chip *chip, u8 bus_width)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5], buf[8];
-
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- cmd[0] = 0x40 | SEND_SCR;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 8, 1, bus_width,
- buf, 8, 250);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- memcpy(sd_card->raw_scr, buf, 8);
-
- if ((buf[0] & 0x0F) == 0)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_query_switch_result(struct rtsx_chip *chip, u8 func_group,
- u8 func_to_switch, u8 *buf, int buf_len)
-{
- u8 support_mask = 0, query_switch = 0, switch_busy = 0;
- int support_offset = 0, query_switch_offset = 0, check_busy_offset = 0;
-
- if (func_group == SD_FUNC_GROUP_1) {
- support_offset = FUNCTION_GROUP1_SUPPORT_OFFSET;
- query_switch_offset = FUNCTION_GROUP1_QUERY_SWITCH_OFFSET;
- check_busy_offset = FUNCTION_GROUP1_CHECK_BUSY_OFFSET;
-
- switch (func_to_switch) {
- case HS_SUPPORT:
- support_mask = HS_SUPPORT_MASK;
- query_switch = HS_QUERY_SWITCH_OK;
- switch_busy = HS_SWITCH_BUSY;
- break;
-
- case SDR50_SUPPORT:
- support_mask = SDR50_SUPPORT_MASK;
- query_switch = SDR50_QUERY_SWITCH_OK;
- switch_busy = SDR50_SWITCH_BUSY;
- break;
-
- case SDR104_SUPPORT:
- support_mask = SDR104_SUPPORT_MASK;
- query_switch = SDR104_QUERY_SWITCH_OK;
- switch_busy = SDR104_SWITCH_BUSY;
- break;
-
- case DDR50_SUPPORT:
- support_mask = DDR50_SUPPORT_MASK;
- query_switch = DDR50_QUERY_SWITCH_OK;
- switch_busy = DDR50_SWITCH_BUSY;
- break;
-
- default:
- return STATUS_FAIL;
- }
- } else if (func_group == SD_FUNC_GROUP_3) {
- support_offset = FUNCTION_GROUP3_SUPPORT_OFFSET;
- query_switch_offset = FUNCTION_GROUP3_QUERY_SWITCH_OFFSET;
- check_busy_offset = FUNCTION_GROUP3_CHECK_BUSY_OFFSET;
-
- switch (func_to_switch) {
- case DRIVING_TYPE_A:
- support_mask = DRIVING_TYPE_A_MASK;
- query_switch = TYPE_A_QUERY_SWITCH_OK;
- switch_busy = TYPE_A_SWITCH_BUSY;
- break;
-
- case DRIVING_TYPE_C:
- support_mask = DRIVING_TYPE_C_MASK;
- query_switch = TYPE_C_QUERY_SWITCH_OK;
- switch_busy = TYPE_C_SWITCH_BUSY;
- break;
-
- case DRIVING_TYPE_D:
- support_mask = DRIVING_TYPE_D_MASK;
- query_switch = TYPE_D_QUERY_SWITCH_OK;
- switch_busy = TYPE_D_SWITCH_BUSY;
- break;
-
- default:
- return STATUS_FAIL;
- }
- } else if (func_group == SD_FUNC_GROUP_4) {
- support_offset = FUNCTION_GROUP4_SUPPORT_OFFSET;
- query_switch_offset = FUNCTION_GROUP4_QUERY_SWITCH_OFFSET;
- check_busy_offset = FUNCTION_GROUP4_CHECK_BUSY_OFFSET;
-
- switch (func_to_switch) {
- case CURRENT_LIMIT_400:
- support_mask = CURRENT_LIMIT_400_MASK;
- query_switch = CURRENT_LIMIT_400_QUERY_SWITCH_OK;
- switch_busy = CURRENT_LIMIT_400_SWITCH_BUSY;
- break;
-
- case CURRENT_LIMIT_600:
- support_mask = CURRENT_LIMIT_600_MASK;
- query_switch = CURRENT_LIMIT_600_QUERY_SWITCH_OK;
- switch_busy = CURRENT_LIMIT_600_SWITCH_BUSY;
- break;
-
- case CURRENT_LIMIT_800:
- support_mask = CURRENT_LIMIT_800_MASK;
- query_switch = CURRENT_LIMIT_800_QUERY_SWITCH_OK;
- switch_busy = CURRENT_LIMIT_800_SWITCH_BUSY;
- break;
-
- default:
- return STATUS_FAIL;
- }
- } else {
- return STATUS_FAIL;
- }
-
- if (func_group == SD_FUNC_GROUP_1) {
- if (!(buf[support_offset] & support_mask) ||
- ((buf[query_switch_offset] & 0x0F) != query_switch)) {
- return STATUS_FAIL;
- }
- }
-
- /* Check 'Busy Status' */
- if (buf[DATA_STRUCTURE_VER_OFFSET] == 0x01 &&
- ((buf[check_busy_offset] & switch_busy) == switch_busy)) {
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_check_switch_mode(struct rtsx_chip *chip, u8 mode, u8 func_group,
- u8 func_to_switch, u8 bus_width)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5], buf[64];
-
- dev_dbg(rtsx_dev(chip), "%s (mode = %d, func_group = %d, func_to_switch = %d)\n",
- __func__, mode, func_group, func_to_switch);
-
- cmd[0] = 0x40 | SWITCH;
- cmd[1] = mode;
-
- if (func_group == SD_FUNC_GROUP_1) {
- cmd[2] = 0xFF;
- cmd[3] = 0xFF;
- cmd[4] = 0xF0 + func_to_switch;
- } else if (func_group == SD_FUNC_GROUP_3) {
- cmd[2] = 0xFF;
- cmd[3] = 0xF0 + func_to_switch;
- cmd[4] = 0xFF;
- } else if (func_group == SD_FUNC_GROUP_4) {
- cmd[2] = 0xFF;
- cmd[3] = 0x0F + (func_to_switch << 4);
- cmd[4] = 0xFF;
- } else {
- cmd[1] = SD_CHECK_MODE;
- cmd[2] = 0xFF;
- cmd[3] = 0xFF;
- cmd[4] = 0xFF;
- }
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1, bus_width,
- buf, 64, 250);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- dev_dbg(rtsx_dev(chip), "%*ph\n", 64, buf);
-
- if (func_group == NO_ARGUMENT) {
- sd_card->func_group1_mask = buf[0x0D];
- sd_card->func_group2_mask = buf[0x0B];
- sd_card->func_group3_mask = buf[0x09];
- sd_card->func_group4_mask = buf[0x07];
-
- dev_dbg(rtsx_dev(chip), "func_group1_mask = 0x%02x\n",
- buf[0x0D]);
- dev_dbg(rtsx_dev(chip), "func_group2_mask = 0x%02x\n",
- buf[0x0B]);
- dev_dbg(rtsx_dev(chip), "func_group3_mask = 0x%02x\n",
- buf[0x09]);
- dev_dbg(rtsx_dev(chip), "func_group4_mask = 0x%02x\n",
- buf[0x07]);
- } else {
- /* Maximum current consumption, check whether current is
- * acceptable; bit[511:496] = 0x0000 means some error happened.
- */
- u16 cc = ((u16)buf[0] << 8) | buf[1];
-
- dev_dbg(rtsx_dev(chip), "Maximum current consumption: %dmA\n",
- cc);
- if (cc == 0 || cc > 800)
- return STATUS_FAIL;
-
- retval = sd_query_switch_result(chip, func_group,
- func_to_switch, buf, 64);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (cc > 400 || func_to_switch > CURRENT_LIMIT_400) {
- retval = rtsx_write_register(chip, OCPPARA2,
- SD_OCP_THD_MASK,
- chip->sd_800mA_ocp_thd);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PWR_CTL,
- PMOS_STRG_MASK,
- PMOS_STRG_800mA);
- if (retval)
- return retval;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static u8 downgrade_switch_mode(u8 func_group, u8 func_to_switch)
-{
- if (func_group == SD_FUNC_GROUP_1) {
- if (func_to_switch > HS_SUPPORT)
- func_to_switch--;
-
- } else if (func_group == SD_FUNC_GROUP_4) {
- if (func_to_switch > CURRENT_LIMIT_200)
- func_to_switch--;
- }
-
- return func_to_switch;
-}
-
-static int sd_check_switch(struct rtsx_chip *chip,
- u8 func_group, u8 func_to_switch, u8 bus_width)
-{
- int retval;
- int i;
- bool switch_good = false;
-
- for (i = 0; i < 3; i++) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = sd_check_switch_mode(chip, SD_CHECK_MODE, func_group,
- func_to_switch, bus_width);
- if (retval == STATUS_SUCCESS) {
- u8 stat;
-
- retval = sd_check_switch_mode(chip, SD_SWITCH_MODE,
- func_group,
- func_to_switch,
- bus_width);
- if (retval == STATUS_SUCCESS) {
- switch_good = true;
- break;
- }
-
- retval = rtsx_read_register(chip, SD_STAT1, &stat);
- if (retval)
- return retval;
- if (stat & SD_CRC16_ERR) {
- dev_dbg(rtsx_dev(chip), "SD CRC16 error when switching mode\n");
- return STATUS_FAIL;
- }
- }
-
- func_to_switch = downgrade_switch_mode(func_group,
- func_to_switch);
-
- wait_timeout(20);
- }
-
- if (!switch_good)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_switch_function(struct rtsx_chip *chip, u8 bus_width)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i;
- u8 func_to_switch = 0;
-
- /* Get supported functions */
- retval = sd_check_switch_mode(chip, SD_CHECK_MODE, NO_ARGUMENT,
- NO_ARGUMENT, bus_width);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- sd_card->func_group1_mask &= ~(sd_card->sd_switch_fail);
-
- /* Function Group 1: Access Mode */
- for (i = 0; i < 4; i++) {
- switch ((u8)(chip->sd_speed_prior >> (i * 8))) {
- case SDR104_SUPPORT:
- if ((sd_card->func_group1_mask & SDR104_SUPPORT_MASK) &&
- chip->sdr104_en) {
- func_to_switch = SDR104_SUPPORT;
- }
- break;
-
- case DDR50_SUPPORT:
- if ((sd_card->func_group1_mask & DDR50_SUPPORT_MASK) &&
- chip->ddr50_en) {
- func_to_switch = DDR50_SUPPORT;
- }
- break;
-
- case SDR50_SUPPORT:
- if ((sd_card->func_group1_mask & SDR50_SUPPORT_MASK) &&
- chip->sdr50_en) {
- func_to_switch = SDR50_SUPPORT;
- }
- break;
-
- case HS_SUPPORT:
- if (sd_card->func_group1_mask & HS_SUPPORT_MASK)
- func_to_switch = HS_SUPPORT;
-
- break;
-
- default:
- continue;
- }
-
- if (func_to_switch)
- break;
- }
- dev_dbg(rtsx_dev(chip), "SD_FUNC_GROUP_1: func_to_switch = 0x%02x",
- func_to_switch);
-
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_SDR_RST) &&
- func_to_switch == DDR50_SUPPORT &&
- (sd_card->func_group1_mask & SDR50_SUPPORT_MASK)) {
- func_to_switch = SDR50_SUPPORT;
- dev_dbg(rtsx_dev(chip), "Using SDR50 instead of DDR50 for SD Lock\n");
- }
-#endif
-
- if (func_to_switch) {
- retval = sd_check_switch(chip, SD_FUNC_GROUP_1, func_to_switch,
- bus_width);
- if (retval != STATUS_SUCCESS) {
- if (func_to_switch == SDR104_SUPPORT) {
- sd_card->sd_switch_fail = SDR104_SUPPORT_MASK;
- } else if (func_to_switch == DDR50_SUPPORT) {
- sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
- DDR50_SUPPORT_MASK;
- } else if (func_to_switch == SDR50_SUPPORT) {
- sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
- DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK;
- }
- return STATUS_FAIL;
- }
-
- if (func_to_switch == SDR104_SUPPORT)
- SET_SD_SDR104(sd_card);
- else if (func_to_switch == DDR50_SUPPORT)
- SET_SD_DDR50(sd_card);
- else if (func_to_switch == SDR50_SUPPORT)
- SET_SD_SDR50(sd_card);
- else
- SET_SD_HS(sd_card);
- }
-
- if (CHK_SD_DDR50(sd_card)) {
- retval = rtsx_write_register(chip, SD_PUSH_POINT_CTL, 0x06,
- 0x04);
- if (retval)
- return retval;
- retval = sd_set_sample_push_timing(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- if (!func_to_switch || func_to_switch == HS_SUPPORT) {
- /* Do not try to switch current limit if the card doesn't
- * support UHS mode or we don't want it to support UHS mode
- */
- return STATUS_SUCCESS;
- }
-
- /* Function Group 4: Current Limit */
- func_to_switch = 0xFF;
-
- for (i = 0; i < 4; i++) {
- switch ((u8)(chip->sd_current_prior >> (i * 8))) {
- case CURRENT_LIMIT_800:
- if (sd_card->func_group4_mask & CURRENT_LIMIT_800_MASK)
- func_to_switch = CURRENT_LIMIT_800;
-
- break;
-
- case CURRENT_LIMIT_600:
- if (sd_card->func_group4_mask & CURRENT_LIMIT_600_MASK)
- func_to_switch = CURRENT_LIMIT_600;
-
- break;
-
- case CURRENT_LIMIT_400:
- if (sd_card->func_group4_mask & CURRENT_LIMIT_400_MASK)
- func_to_switch = CURRENT_LIMIT_400;
-
- break;
-
- case CURRENT_LIMIT_200:
- if (sd_card->func_group4_mask & CURRENT_LIMIT_200_MASK)
- func_to_switch = CURRENT_LIMIT_200;
-
- break;
-
- default:
- continue;
- }
-
- if (func_to_switch != 0xFF)
- break;
- }
-
- dev_dbg(rtsx_dev(chip), "SD_FUNC_GROUP_4: func_to_switch = 0x%02x",
- func_to_switch);
-
- if (func_to_switch <= CURRENT_LIMIT_800) {
- retval = sd_check_switch(chip, SD_FUNC_GROUP_4, func_to_switch,
- bus_width);
- if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_NO_CARD))
- return STATUS_FAIL;
- }
- dev_dbg(rtsx_dev(chip), "Switch current limit finished! (%d)\n",
- retval);
- }
-
- if (CHK_SD_DDR50(sd_card)) {
- retval = rtsx_write_register(chip, SD_PUSH_POINT_CTL, 0x06, 0);
- if (retval)
- return retval;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_wait_data_idle(struct rtsx_chip *chip)
-{
- int retval = STATUS_TIMEDOUT;
- int i;
- u8 val = 0;
-
- for (i = 0; i < 100; i++) {
- retval = rtsx_read_register(chip, SD_DATA_STATE, &val);
- if (retval)
- return retval;
- if (val & SD_DATA_IDLE) {
- retval = STATUS_SUCCESS;
- break;
- }
- udelay(100);
- }
- dev_dbg(rtsx_dev(chip), "SD_DATA_STATE: 0x%02x\n", val);
-
- return retval;
-}
-
-static int sd_sdr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
- int retval;
- u8 cmd[5];
-
- retval = sd_change_phase(chip, sample_point, TUNE_RX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- cmd[0] = 0x40 | SEND_TUNING_PATTERN;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_read_data(chip, SD_TM_AUTO_TUNING, cmd, 5, 0x40, 1,
- SD_BUS_WIDTH_4, NULL, 0, 100);
- if (retval != STATUS_SUCCESS) {
- (void)sd_wait_data_idle(chip);
-
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5];
-
- retval = sd_change_phase(chip, sample_point, TUNE_RX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "sd ddr tuning rx\n");
-
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- cmd[0] = 0x40 | SD_STATUS;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1,
- SD_BUS_WIDTH_4, NULL, 0, 100);
- if (retval != STATUS_SUCCESS) {
- (void)sd_wait_data_idle(chip);
-
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int mmc_ddr_tuning_rx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5], bus_width;
-
- if (CHK_MMC_8BIT(sd_card))
- bus_width = SD_BUS_WIDTH_8;
- else if (CHK_MMC_4BIT(sd_card))
- bus_width = SD_BUS_WIDTH_4;
- else
- bus_width = SD_BUS_WIDTH_1;
-
- retval = sd_change_phase(chip, sample_point, TUNE_RX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "mmc ddr tuning rx\n");
-
- cmd[0] = 0x40 | SEND_EXT_CSD;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 0x200, 1,
- bus_width, NULL, 0, 100);
- if (retval != STATUS_SUCCESS) {
- (void)sd_wait_data_idle(chip);
-
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_sdr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- retval = sd_change_phase(chip, sample_point, TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- SD_RSP_80CLK_TIMEOUT_EN);
- if (retval)
- return retval;
-
- retval = sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_RSP_TIMEOUT)) {
- rtsx_write_register(chip, SD_CFG3,
- SD_RSP_80CLK_TIMEOUT_EN, 0);
- return STATUS_FAIL;
- }
- }
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- 0);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_ddr_tuning_tx_cmd(struct rtsx_chip *chip, u8 sample_point)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5], bus_width;
-
- retval = sd_change_phase(chip, sample_point, TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (CHK_SD(sd_card)) {
- bus_width = SD_BUS_WIDTH_4;
- } else {
- if (CHK_MMC_8BIT(sd_card))
- bus_width = SD_BUS_WIDTH_8;
- else if (CHK_MMC_4BIT(sd_card))
- bus_width = SD_BUS_WIDTH_4;
- else
- bus_width = SD_BUS_WIDTH_1;
- }
-
- retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- SD_RSP_80CLK_TIMEOUT_EN);
- if (retval)
- return retval;
-
- cmd[0] = 0x40 | PROGRAM_CSD;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_write_data(chip, SD_TM_AUTO_WRITE_2, cmd, 5, 16, 1,
- bus_width, sd_card->raw_csd, 16, 100);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN, 0);
- return STATUS_FAIL;
- }
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- 0);
- if (retval)
- return retval;
-
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr, SD_RSP_TYPE_R1,
- NULL, 0);
-
- return STATUS_SUCCESS;
-}
-
-static u8 sd_search_final_phase(struct rtsx_chip *chip, u32 phase_map,
- u8 tune_dir)
-{
- struct sd_info *sd_card = &chip->sd_card;
- struct timing_phase_path path[MAX_PHASE + 1];
- int i, j, cont_path_cnt;
- bool new_block;
- int max_len, final_path_idx;
- u8 final_phase = 0xFF;
-
- if (phase_map == 0xFFFFFFFF) {
- if (tune_dir == TUNE_RX)
- final_phase = (u8)chip->sd_default_rx_phase;
- else
- final_phase = (u8)chip->sd_default_tx_phase;
-
- goto search_finish;
- }
-
- cont_path_cnt = 0;
- new_block = true;
- j = 0;
- for (i = 0; i < MAX_PHASE + 1; i++) {
- if (phase_map & (1 << i)) {
- if (new_block) {
- new_block = false;
- j = cont_path_cnt++;
- path[j].start = i;
- path[j].end = i;
- } else {
- path[j].end = i;
- }
- } else {
- new_block = true;
- if (cont_path_cnt) {
- int idx = cont_path_cnt - 1;
-
- path[idx].len = path[idx].end -
- path[idx].start + 1;
- path[idx].mid = path[idx].start +
- path[idx].len / 2;
- }
- }
- }
-
- if (cont_path_cnt == 0) {
- dev_dbg(rtsx_dev(chip), "No continuous phase path\n");
- goto search_finish;
- } else {
- int idx = cont_path_cnt - 1;
-
- path[idx].len = path[idx].end - path[idx].start + 1;
- path[idx].mid = path[idx].start + path[idx].len / 2;
- }
-
- if (path[0].start == 0 &&
- path[cont_path_cnt - 1].end == MAX_PHASE) {
- path[0].start = path[cont_path_cnt - 1].start - MAX_PHASE - 1;
- path[0].len += path[cont_path_cnt - 1].len;
- path[0].mid = path[0].start + path[0].len / 2;
- if (path[0].mid < 0)
- path[0].mid += MAX_PHASE + 1;
-
- cont_path_cnt--;
- }
-
- max_len = 0;
- final_phase = 0;
- final_path_idx = 0;
- for (i = 0; i < cont_path_cnt; i++) {
- if (path[i].len > max_len) {
- max_len = path[i].len;
- final_phase = (u8)path[i].mid;
- final_path_idx = i;
- }
-
- dev_dbg(rtsx_dev(chip), "path[%d].start = %d\n",
- i, path[i].start);
- dev_dbg(rtsx_dev(chip), "path[%d].end = %d\n", i, path[i].end);
- dev_dbg(rtsx_dev(chip), "path[%d].len = %d\n", i, path[i].len);
- dev_dbg(rtsx_dev(chip), "path[%d].mid = %d\n", i, path[i].mid);
- dev_dbg(rtsx_dev(chip), "\n");
- }
-
- if (tune_dir == TUNE_TX) {
- if (CHK_SD_SDR104(sd_card)) {
- if (max_len > 15) {
- int temp_mid = (max_len - 16) / 2;
- int temp_final_phase =
- path[final_path_idx].end -
- (max_len - (6 + temp_mid));
-
- if (temp_final_phase < 0)
- final_phase = (u8)(temp_final_phase +
- MAX_PHASE + 1);
- else
- final_phase = (u8)temp_final_phase;
- }
- } else if (CHK_SD_SDR50(sd_card)) {
- if (max_len > 12) {
- int temp_mid = (max_len - 13) / 2;
- int temp_final_phase =
- path[final_path_idx].end -
- (max_len - (3 + temp_mid));
-
- if (temp_final_phase < 0)
- final_phase = (u8)(temp_final_phase +
- MAX_PHASE + 1);
- else
- final_phase = (u8)temp_final_phase;
- }
- }
- }
-
-search_finish:
- dev_dbg(rtsx_dev(chip), "Final chosen phase: %d\n", final_phase);
- return final_phase;
-}
-
-static int sd_tuning_rx(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i, j;
- u32 raw_phase_map[3], phase_map;
- u8 final_phase;
- int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
-
- if (CHK_SD(sd_card)) {
- if (CHK_SD_DDR50(sd_card))
- tuning_cmd = sd_ddr_tuning_rx_cmd;
- else
- tuning_cmd = sd_sdr_tuning_rx_cmd;
-
- } else {
- if (CHK_MMC_DDR52(sd_card))
- tuning_cmd = mmc_ddr_tuning_rx_cmd;
- else
- return STATUS_FAIL;
- }
-
- for (i = 0; i < 3; i++) {
- raw_phase_map[i] = 0;
- for (j = MAX_PHASE; j >= 0; j--) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = tuning_cmd(chip, (u8)j);
- if (retval == STATUS_SUCCESS)
- raw_phase_map[i] |= 1 << j;
- }
- }
-
- phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
- for (i = 0; i < 3; i++)
- dev_dbg(rtsx_dev(chip), "RX raw_phase_map[%d] = 0x%08x\n",
- i, raw_phase_map[i]);
-
- dev_dbg(rtsx_dev(chip), "RX phase_map = 0x%08x\n", phase_map);
-
- final_phase = sd_search_final_phase(chip, phase_map, TUNE_RX);
- if (final_phase == 0xFF)
- return STATUS_FAIL;
-
- retval = sd_change_phase(chip, final_phase, TUNE_RX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_ddr_pre_tuning_tx(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i;
- u32 phase_map;
- u8 final_phase;
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- SD_RSP_80CLK_TIMEOUT_EN);
- if (retval)
- return retval;
-
- phase_map = 0;
- for (i = MAX_PHASE; i >= 0; i--) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- rtsx_write_register(chip, SD_CFG3,
- SD_RSP_80CLK_TIMEOUT_EN, 0);
- return STATUS_FAIL;
- }
-
- retval = sd_change_phase(chip, (u8)i, TUNE_TX);
- if (retval != STATUS_SUCCESS)
- continue;
-
- retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval == STATUS_SUCCESS ||
- !sd_check_err_code(chip, SD_RSP_TIMEOUT))
- phase_map |= 1 << i;
- }
-
- retval = rtsx_write_register(chip, SD_CFG3, SD_RSP_80CLK_TIMEOUT_EN,
- 0);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "DDR TX pre tune phase_map = 0x%08x\n",
- phase_map);
-
- final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
- if (final_phase == 0xFF)
- return STATUS_FAIL;
-
- retval = sd_change_phase(chip, final_phase, TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "DDR TX pre tune phase: %d\n",
- (int)final_phase);
-
- return STATUS_SUCCESS;
-}
-
-static int sd_tuning_tx(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int i, j;
- u32 raw_phase_map[3], phase_map;
- u8 final_phase;
- int (*tuning_cmd)(struct rtsx_chip *chip, u8 sample_point);
-
- if (CHK_SD(sd_card)) {
- if (CHK_SD_DDR50(sd_card))
- tuning_cmd = sd_ddr_tuning_tx_cmd;
- else
- tuning_cmd = sd_sdr_tuning_tx_cmd;
-
- } else {
- if (CHK_MMC_DDR52(sd_card))
- tuning_cmd = sd_ddr_tuning_tx_cmd;
- else
- return STATUS_FAIL;
- }
-
- for (i = 0; i < 3; i++) {
- raw_phase_map[i] = 0;
- for (j = MAX_PHASE; j >= 0; j--) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- rtsx_write_register(chip, SD_CFG3,
- SD_RSP_80CLK_TIMEOUT_EN, 0);
- return STATUS_FAIL;
- }
-
- retval = tuning_cmd(chip, (u8)j);
- if (retval == STATUS_SUCCESS)
- raw_phase_map[i] |= 1 << j;
- }
- }
-
- phase_map = raw_phase_map[0] & raw_phase_map[1] & raw_phase_map[2];
- for (i = 0; i < 3; i++)
- dev_dbg(rtsx_dev(chip), "TX raw_phase_map[%d] = 0x%08x\n",
- i, raw_phase_map[i]);
-
- dev_dbg(rtsx_dev(chip), "TX phase_map = 0x%08x\n", phase_map);
-
- final_phase = sd_search_final_phase(chip, phase_map, TUNE_TX);
- if (final_phase == 0xFF)
- return STATUS_FAIL;
-
- retval = sd_change_phase(chip, final_phase, TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_sdr_tuning(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = sd_tuning_tx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sd_tuning_rx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_ddr_tuning(struct rtsx_chip *chip)
-{
- int retval;
-
- if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
- retval = sd_ddr_pre_tuning_tx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = sd_change_phase(chip, (u8)chip->sd_ddr_tx_phase,
- TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = sd_tuning_rx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!(chip->sd_ctl & SD_DDR_TX_PHASE_SET_BY_USER)) {
- retval = sd_tuning_tx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int mmc_ddr_tuning(struct rtsx_chip *chip)
-{
- int retval;
-
- if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
- retval = sd_ddr_pre_tuning_tx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = sd_change_phase(chip, (u8)chip->mmc_ddr_tx_phase,
- TUNE_TX);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- retval = sd_tuning_rx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!(chip->sd_ctl & MMC_DDR_TX_PHASE_SET_BY_USER)) {
- retval = sd_tuning_tx(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int sd_switch_clock(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- int re_tuning = 0;
-
- retval = select_card(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = switch_clock(chip, sd_card->sd_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (re_tuning) {
- if (CHK_SD(sd_card)) {
- if (CHK_SD_DDR50(sd_card))
- retval = sd_ddr_tuning(chip);
- else
- retval = sd_sdr_tuning(chip);
- } else {
- if (CHK_MMC_DDR52(sd_card))
- retval = mmc_ddr_tuning(chip);
- }
-
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_prepare_reset(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- if (chip->asic_code)
- sd_card->sd_clock = 29;
- else
- sd_card->sd_clock = CLK_30;
-
- sd_card->sd_type = 0;
- sd_card->seq_mode = 0;
- sd_card->sd_data_buf_ready = 0;
- sd_card->capacity = 0;
-
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status = 0;
- sd_card->sd_erase_status = 0;
-#endif
-
- chip->capacity[chip->card2lun[SD_CARD]] = 0;
- chip->sd_io = 0;
-
- retval = sd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return retval;
-
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0xFF, 0x40);
- if (retval)
- return retval;
-
- retval = rtsx_write_register(chip, CARD_STOP, SD_STOP | SD_CLR_ERR,
- SD_STOP | SD_CLR_ERR);
- if (retval)
- return retval;
-
- retval = select_card(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_pull_ctl_disable(struct rtsx_chip *chip)
-{
- int retval;
-
- if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF,
- XD_D3_PD | SD_D7_PD | SD_CLK_PD |
- SD_D5_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF,
- SD_D6_PD | SD_D0_PD | SD_D1_PD |
- XD_D5_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF,
- SD_D4_PD | XD_CE_PD | XD_CLE_PD |
- XD_CD_PU);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD | SD_D3_PD | SD_D2_PD |
- XD_ALE_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PD | SD_CD_PU |
- SD_CMD_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- if (retval)
- return retval;
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1,
- 0xFF, 0x55);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL2,
- 0xFF, 0x55);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL3,
- 0xFF, 0x4B);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL4,
- 0xFF, 0x69);
- if (retval)
- return retval;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-int sd_pull_ctl_enable(struct rtsx_chip *chip)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
- XD_D3_PD | SD_DAT7_PU | SD_CLK_NP | SD_D5_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
- SD_D6_PU | SD_D0_PU | SD_D1_PU | XD_D5_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
- SD_D4_PU | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD | SD_D3_PU | SD_D2_PU | XD_ALE_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PU | SD_CD_PU | SD_CMD_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
- 0xA8);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
- 0x5A);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
- 0x95);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
- 0xAA);
- }
- }
-
- retval = rtsx_send_cmd(chip, SD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_init_power(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = sd_power_off_card3v3(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (!chip->ft2_fast_mode)
- wait_timeout(250);
-
- retval = enable_card_clock(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (chip->asic_code) {
- retval = sd_pull_ctl_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- FPGA_SD_PULL_CTL_BIT | 0x20, 0);
- if (retval)
- return retval;
- }
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_on(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- wait_timeout(260);
-
-#ifdef SUPPORT_OCP
- if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
- dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
- chip->ocp_stat);
- return STATUS_FAIL;
- }
-#endif
- }
-
- retval = rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN,
- SD_OUTPUT_EN);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_dummy_clock(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = rtsx_write_register(chip, REG_SD_CFG3, 0x01, 0x01);
- if (retval)
- return retval;
- wait_timeout(5);
- retval = rtsx_write_register(chip, REG_SD_CFG3, 0x01, 0);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int sd_read_lba0(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 cmd[5], bus_width;
-
- cmd[0] = 0x40 | READ_SINGLE_BLOCK;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- if (CHK_SD(sd_card)) {
- bus_width = SD_BUS_WIDTH_4;
- } else {
- if (CHK_MMC_8BIT(sd_card))
- bus_width = SD_BUS_WIDTH_8;
- else if (CHK_MMC_4BIT(sd_card))
- bus_width = SD_BUS_WIDTH_4;
- else
- bus_width = SD_BUS_WIDTH_1;
- }
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 512, 1,
- bus_width, NULL, 0, 100);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sd_check_wp_state(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u32 val;
- u16 sd_card_type;
- u8 cmd[5], buf[64];
-
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- cmd[0] = 0x40 | SD_STATUS;
- cmd[1] = 0;
- cmd[2] = 0;
- cmd[3] = 0;
- cmd[4] = 0;
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, 64, 1,
- SD_BUS_WIDTH_4, buf, 64, 250);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
-
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- return STATUS_FAIL;
- }
-
- dev_dbg(rtsx_dev(chip), "ACMD13:\n");
- dev_dbg(rtsx_dev(chip), "%*ph\n", 64, buf);
-
- sd_card_type = ((u16)buf[2] << 8) | buf[3];
- dev_dbg(rtsx_dev(chip), "sd_card_type = 0x%04x\n", sd_card_type);
- if (sd_card_type == 0x0001 || sd_card_type == 0x0002) {
- /* ROM card or OTP */
- chip->card_wp |= SD_CARD;
- }
-
- /* Check SD Machanical Write-Protect Switch */
- val = rtsx_readl(chip, RTSX_BIPR);
- if (val & SD_WRITE_PROTECT)
- chip->card_wp |= SD_CARD;
-
- return STATUS_SUCCESS;
-}
-
-static int reset_sd(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- bool hi_cap_flow = false;
- int retval, i = 0, j = 0, k = 0;
- bool sd_dont_switch = false;
- bool support_1v8 = false;
- bool try_sdio = true;
- u8 rsp[16];
- u8 switch_bus_width;
- u32 voltage = 0;
- bool sd20_mode = false;
-
- SET_SD(sd_card);
-
-switch_fail:
-
- i = 0;
- j = 0;
- k = 0;
- hi_cap_flow = false;
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
- goto SD_UNLOCK_ENTRY;
-#endif
-
- retval = sd_prepare_reset(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_dummy_clock(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- if (CHK_SDIO_EXIST(chip) && !CHK_SDIO_IGNORED(chip) && try_sdio) {
- int rty_cnt = 0;
-
- for (; rty_cnt < chip->sdio_retry_cnt; rty_cnt++) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- goto status_fail;
- }
-
- retval = sd_send_cmd_get_rsp(chip, IO_SEND_OP_COND, 0,
- SD_RSP_TYPE_R4, rsp, 5);
- if (retval == STATUS_SUCCESS) {
- int func_num = (rsp[1] >> 4) & 0x07;
-
- if (func_num) {
- dev_dbg(rtsx_dev(chip), "SD_IO card (Function number: %d)!\n",
- func_num);
- chip->sd_io = 1;
- goto status_fail;
- }
-
- break;
- }
-
- sd_init_power(chip);
-
- sd_dummy_clock(chip);
- }
-
- dev_dbg(rtsx_dev(chip), "Normal card!\n");
- }
-
- /* Start Initialization Process of SD Card */
-RTY_SD_RST:
- retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- wait_timeout(20);
-
- retval = sd_send_cmd_get_rsp(chip, SEND_IF_COND, 0x000001AA,
- SD_RSP_TYPE_R7, rsp, 5);
- if (retval == STATUS_SUCCESS) {
- if (rsp[4] == 0xAA && ((rsp[3] & 0x0f) == 0x01)) {
- hi_cap_flow = true;
- voltage = SUPPORT_VOLTAGE | 0x40000000;
- }
- }
-
- if (!hi_cap_flow) {
- voltage = SUPPORT_VOLTAGE;
-
- retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0,
- SD_RSP_TYPE_R0, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- wait_timeout(20);
- }
-
- do {
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, 0, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- goto status_fail;
- }
-
- j++;
- if (j < 3)
- goto RTY_SD_RST;
- else
- goto status_fail;
- }
-
- retval = sd_send_cmd_get_rsp(chip, SD_APP_OP_COND, voltage,
- SD_RSP_TYPE_R3, rsp, 5);
- if (retval != STATUS_SUCCESS) {
- k++;
- if (k < 3)
- goto RTY_SD_RST;
- else
- goto status_fail;
- }
-
- i++;
- wait_timeout(20);
- } while (!(rsp[1] & 0x80) && (i < 255));
-
- if (i == 255)
- goto status_fail;
-
- if (hi_cap_flow) {
- if (rsp[1] & 0x40)
- SET_SD_HCXC(sd_card);
- else
- CLR_SD_HCXC(sd_card);
-
- support_1v8 = false;
- } else {
- CLR_SD_HCXC(sd_card);
- support_1v8 = false;
- }
- dev_dbg(rtsx_dev(chip), "support_1v8 = %d\n", support_1v8);
-
- if (support_1v8) {
- retval = sd_voltage_switch(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
- }
-
- retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- for (i = 0; i < 3; i++) {
- retval = sd_send_cmd_get_rsp(chip, SEND_RELATIVE_ADDR, 0,
- SD_RSP_TYPE_R6, rsp, 5);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- sd_card->sd_addr = (u32)rsp[1] << 24;
- sd_card->sd_addr += (u32)rsp[2] << 16;
-
- if (sd_card->sd_addr)
- break;
- }
-
- retval = sd_check_csd(chip, 1);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_select_card(chip, 1);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
-#ifdef SUPPORT_SD_LOCK
-SD_UNLOCK_ENTRY:
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- if (sd_card->sd_lock_status & SD_LOCKED) {
- sd_card->sd_lock_status |= (SD_LOCK_1BIT_MODE | SD_PWD_EXIST);
- return STATUS_SUCCESS;
- } else if (!(sd_card->sd_lock_status & SD_UNLOCK_POW_ON)) {
- sd_card->sd_lock_status &= ~SD_PWD_EXIST;
- }
-#endif
-
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_send_cmd_get_rsp(chip, SET_CLR_CARD_DETECT, 0,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- if (support_1v8) {
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- switch_bus_width = SD_BUS_WIDTH_4;
- } else {
- switch_bus_width = SD_BUS_WIDTH_1;
- }
-
- retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- if (!(sd_card->raw_csd[4] & 0x40))
- sd_dont_switch = true;
-
- if (!sd_dont_switch) {
- if (sd20_mode) {
- /* Set sd_switch_fail here, because we needn't
- * switch to UHS mode
- */
- sd_card->sd_switch_fail = SDR104_SUPPORT_MASK |
- DDR50_SUPPORT_MASK | SDR50_SUPPORT_MASK;
- }
-
- /* Check the card whether follow SD1.1 spec or higher */
- retval = sd_check_spec(chip, switch_bus_width);
- if (retval == STATUS_SUCCESS) {
- retval = sd_switch_function(chip, switch_bus_width);
- if (retval != STATUS_SUCCESS) {
- sd_init_power(chip);
- sd_dont_switch = true;
- try_sdio = false;
-
- goto switch_fail;
- }
- } else {
- if (support_1v8) {
- sd_init_power(chip);
- sd_dont_switch = true;
- try_sdio = false;
-
- goto switch_fail;
- }
- }
- }
-
- if (!support_1v8) {
- retval = sd_send_cmd_get_rsp(chip, APP_CMD, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- retval = sd_send_cmd_get_rsp(chip, SET_BUS_WIDTH, 2,
- SD_RSP_TYPE_R1, NULL, 0);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
- }
-
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
-
- if (!sd20_mode && CHK_SD30_SPEED(sd_card)) {
- int read_lba0 = 1;
-
- retval = rtsx_write_register(chip, SD30_DRIVE_SEL, 0x07,
- chip->sd30_drive_sel_1v8);
- if (retval)
- return retval;
-
- retval = sd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- if (CHK_SD_DDR50(sd_card))
- retval = sd_ddr_tuning(chip);
- else
- retval = sd_sdr_tuning(chip);
-
- if (retval != STATUS_SUCCESS) {
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- try_sdio = false;
- sd20_mode = true;
- goto switch_fail;
- }
-
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
-
- if (CHK_SD_DDR50(sd_card)) {
- retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
- if (retval != STATUS_SUCCESS)
- read_lba0 = 0;
- }
-
- if (read_lba0) {
- retval = sd_read_lba0(chip);
- if (retval != STATUS_SUCCESS) {
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- try_sdio = false;
- sd20_mode = true;
- goto switch_fail;
- }
- }
- }
-
- retval = sd_check_wp_state(chip);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
- retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_H, 0xFF,
- 0x02);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_L, 0xFF,
- 0x00);
- if (retval)
- return retval;
- }
-#endif
-
- return STATUS_SUCCESS;
-
-status_fail:
- return STATUS_FAIL;
-}
-
-static int mmc_test_switch_bus(struct rtsx_chip *chip, u8 width)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 buf[8] = {0}, bus_width, *ptr;
- u16 byte_cnt;
- int len;
-
- retval = sd_send_cmd_get_rsp(chip, BUSTEST_W, 0, SD_RSP_TYPE_R1, NULL,
- 0);
- if (retval != STATUS_SUCCESS)
- return SWITCH_FAIL;
-
- if (width == MMC_8BIT_BUS) {
- buf[0] = 0x55;
- buf[1] = 0xAA;
- len = 8;
- byte_cnt = 8;
- bus_width = SD_BUS_WIDTH_8;
- } else {
- buf[0] = 0x5A;
- len = 4;
- byte_cnt = 4;
- bus_width = SD_BUS_WIDTH_4;
- }
-
- retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0x02);
- if (retval != STATUS_SUCCESS)
- return SWITCH_ERR;
-
- retval = sd_write_data(chip, SD_TM_AUTO_WRITE_3, NULL, 0, byte_cnt, 1,
- bus_width, buf, len, 100);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_sd_error(chip);
- rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
- return SWITCH_ERR;
- }
-
- retval = rtsx_write_register(chip, REG_SD_CFG3, 0x02, 0);
- if (retval != STATUS_SUCCESS)
- return SWITCH_ERR;
-
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", BUSTEST_R);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | BUSTEST_R);
-
- if (width == MMC_8BIT_BUS)
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L,
- 0xFF, 0x08);
- else
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L,
- 0xFF, 0x04);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, SD_CALCULATE_CRC7 |
- SD_NO_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
- SD_CHECK_CRC7 | SD_RSP_LEN_6);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_NORMAL_READ | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
- SD_TRANSFER_END);
-
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2, 0, 0);
- if (width == MMC_8BIT_BUS)
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 1, 0, 0);
-
- retval = rtsx_send_cmd(chip, SD_CARD, 100);
- if (retval < 0) {
- rtsx_clear_sd_error(chip);
- return SWITCH_ERR;
- }
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- if (width == MMC_8BIT_BUS) {
- dev_dbg(rtsx_dev(chip), "BUSTEST_R [8bits]: 0x%02x 0x%02x\n",
- ptr[0], ptr[1]);
- if (ptr[0] == 0xAA && ptr[1] == 0x55) {
- u8 rsp[5];
- u32 arg;
-
- if (CHK_MMC_DDR52(sd_card))
- arg = 0x03B70600;
- else
- arg = 0x03B70200;
-
- retval = sd_send_cmd_get_rsp(chip, SWITCH, arg,
- SD_RSP_TYPE_R1b, rsp, 5);
- if (retval == STATUS_SUCCESS &&
- !(rsp[4] & MMC_SWITCH_ERR))
- return SWITCH_SUCCESS;
- }
- } else {
- dev_dbg(rtsx_dev(chip), "BUSTEST_R [4bits]: 0x%02x\n", ptr[0]);
- if (ptr[0] == 0xA5) {
- u8 rsp[5];
- u32 arg;
-
- if (CHK_MMC_DDR52(sd_card))
- arg = 0x03B70500;
- else
- arg = 0x03B70100;
-
- retval = sd_send_cmd_get_rsp(chip, SWITCH, arg,
- SD_RSP_TYPE_R1b, rsp, 5);
- if (retval == STATUS_SUCCESS &&
- !(rsp[4] & MMC_SWITCH_ERR))
- return SWITCH_SUCCESS;
- }
- }
-
- return SWITCH_FAIL;
-}
-
-static int mmc_switch_timing_bus(struct rtsx_chip *chip, bool switch_ddr)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
- u8 *ptr, card_type, card_type_mask = 0;
-
- CLR_MMC_HS(sd_card);
-
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n", SEND_EXT_CSD);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
- 0x40 | SEND_EXT_CSD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, 0);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 2);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF, 0);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
- SD_CALCULATE_CRC7 | SD_CHECK_CRC16 | SD_NO_WAIT_BUSY_END |
- SD_CHECK_CRC7 | SD_RSP_LEN_6);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_NORMAL_READ | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
- SD_TRANSFER_END);
-
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 196, 0xFF, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 212, 0xFF, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 213, 0xFF, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 214, 0xFF, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + 215, 0xFF, 0);
-
- retval = rtsx_send_cmd(chip, SD_CARD, 1000);
- if (retval < 0) {
- if (retval == -ETIMEDOUT) {
- rtsx_clear_sd_error(chip);
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- }
- return STATUS_FAIL;
- }
-
- ptr = rtsx_get_cmd_data(chip);
- if (ptr[0] & SD_TRANSFER_ERR) {
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- return STATUS_FAIL;
- }
-
- if (CHK_MMC_SECTOR_MODE(sd_card)) {
- sd_card->capacity = ((u32)ptr[5] << 24) | ((u32)ptr[4] << 16) |
- ((u32)ptr[3] << 8) | ((u32)ptr[2]);
- }
-
- card_type_mask = 0x03;
- card_type = ptr[1] & card_type_mask;
- if (card_type) {
- u8 rsp[5];
-
- if (card_type & 0x04) {
- if (switch_ddr)
- SET_MMC_DDR52(sd_card);
- else
- SET_MMC_52M(sd_card);
- } else if (card_type & 0x02) {
- SET_MMC_52M(sd_card);
- } else {
- SET_MMC_26M(sd_card);
- }
-
- retval = sd_send_cmd_get_rsp(chip, SWITCH, 0x03B90100,
- SD_RSP_TYPE_R1b, rsp, 5);
- if (retval != STATUS_SUCCESS || (rsp[4] & MMC_SWITCH_ERR))
- CLR_MMC_HS(sd_card);
- }
-
- sd_choose_proper_clock(chip);
- retval = switch_clock(chip, sd_card->sd_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* Test Bus Procedure */
- retval = mmc_test_switch_bus(chip, MMC_8BIT_BUS);
- if (retval == SWITCH_SUCCESS) {
- SET_MMC_8BIT(sd_card);
- chip->card_bus_width[chip->card2lun[SD_CARD]] = 8;
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
- } else if (retval == SWITCH_FAIL) {
- retval = mmc_test_switch_bus(chip, MMC_4BIT_BUS);
- if (retval == SWITCH_SUCCESS) {
- SET_MMC_4BIT(sd_card);
- chip->card_bus_width[chip->card2lun[SD_CARD]] = 4;
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_LOCK_1BIT_MODE;
-#endif
- } else if (retval == SWITCH_FAIL) {
- CLR_MMC_8BIT(sd_card);
- CLR_MMC_4BIT(sd_card);
- } else {
- return STATUS_FAIL;
- }
- } else {
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int reset_mmc(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval, i = 0, j = 0, k = 0;
- bool switch_ddr = true;
- u8 rsp[16];
- u8 spec_ver = 0;
- u32 temp;
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON)
- goto MMC_UNLOCK_ENTRY;
-#endif
-
-switch_fail:
- retval = sd_prepare_reset(chip);
- if (retval != STATUS_SUCCESS)
- return retval;
-
- SET_MMC(sd_card);
-
-RTY_MMC_RST:
- retval = sd_send_cmd_get_rsp(chip, GO_IDLE_STATE, 0, SD_RSP_TYPE_R0,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- do {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- return STATUS_FAIL;
- }
-
- retval = sd_send_cmd_get_rsp(chip, SEND_OP_COND,
- (SUPPORT_VOLTAGE | 0x40000000),
- SD_RSP_TYPE_R3, rsp, 5);
- if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_BUSY) ||
- sd_check_err_code(chip, SD_TO_ERR)) {
- k++;
- if (k < 20) {
- sd_clr_err_code(chip);
- goto RTY_MMC_RST;
- } else {
- return STATUS_FAIL;
- }
- } else {
- j++;
- if (j < 100) {
- sd_clr_err_code(chip);
- goto RTY_MMC_RST;
- } else {
- return STATUS_FAIL;
- }
- }
- }
-
- wait_timeout(20);
- i++;
- } while (!(rsp[1] & 0x80) && (i < 255));
-
- if (i == 255)
- return STATUS_FAIL;
-
- if ((rsp[1] & 0x60) == 0x40)
- SET_MMC_SECTOR_MODE(sd_card);
- else
- CLR_MMC_SECTOR_MODE(sd_card);
-
- retval = sd_send_cmd_get_rsp(chip, ALL_SEND_CID, 0, SD_RSP_TYPE_R2,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- sd_card->sd_addr = 0x00100000;
- retval = sd_send_cmd_get_rsp(chip, SET_RELATIVE_ADDR, sd_card->sd_addr,
- SD_RSP_TYPE_R6, rsp, 5);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sd_check_csd(chip, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- spec_ver = (sd_card->raw_csd[0] & 0x3C) >> 2;
-
- retval = sd_select_card(chip, 1);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
-#ifdef SUPPORT_SD_LOCK
-MMC_UNLOCK_ENTRY:
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-#endif
-
- retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- chip->card_bus_width[chip->card2lun[SD_CARD]] = 1;
-
- if (!sd_card->mmc_dont_switch_bus) {
- if (spec_ver == 4) {
- /* MMC 4.x Cards */
- retval = mmc_switch_timing_bus(chip, switch_ddr);
- if (retval != STATUS_SUCCESS) {
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- sd_card->mmc_dont_switch_bus = 1;
- goto switch_fail;
- }
- }
-
- if (CHK_MMC_SECTOR_MODE(sd_card) && sd_card->capacity == 0)
- return STATUS_FAIL;
-
- if (switch_ddr && CHK_MMC_DDR52(sd_card)) {
- retval = sd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = mmc_ddr_tuning(chip);
- if (retval != STATUS_SUCCESS) {
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- switch_ddr = false;
- goto switch_fail;
- }
-
- retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
- if (retval == STATUS_SUCCESS) {
- retval = sd_read_lba0(chip);
- if (retval != STATUS_SUCCESS) {
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- switch_ddr = false;
- goto switch_fail;
- }
- }
- }
- }
-
-#ifdef SUPPORT_SD_LOCK
- if (sd_card->sd_lock_status & SD_UNLOCK_POW_ON) {
- retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_H, 0xFF,
- 0x02);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, REG_SD_BLOCK_CNT_L, 0xFF,
- 0x00);
- if (retval)
- return retval;
- }
-#endif
-
- temp = rtsx_readl(chip, RTSX_BIPR);
- if (temp & SD_WRITE_PROTECT)
- chip->card_wp |= SD_CARD;
-
- return STATUS_SUCCESS;
-}
-
-int reset_sd_card(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- sd_init_reg_addr(chip);
-
- memset(sd_card, 0, sizeof(struct sd_info));
- chip->capacity[chip->card2lun[SD_CARD]] = 0;
-
- retval = enable_card_clock(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (chip->ignore_sd && CHK_SDIO_EXIST(chip) &&
- !CHK_SDIO_IGNORED(chip)) {
- if (chip->asic_code) {
- retval = sd_pull_ctl_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- FPGA_SD_PULL_CTL_BIT |
- 0x20, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- retval = card_share_mode(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- chip->sd_io = 1;
- return STATUS_FAIL;
- }
-
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (chip->sd_ctl & RESET_MMC_FIRST) {
- retval = reset_mmc(chip);
- if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_NO_CARD))
- return STATUS_FAIL;
-
- retval = reset_sd(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- } else {
- retval = reset_sd(chip);
- if (retval != STATUS_SUCCESS) {
- if (sd_check_err_code(chip, SD_NO_CARD))
- return STATUS_FAIL;
-
- if (chip->sd_io)
- return STATUS_FAIL;
- retval = reset_mmc(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
- }
-
- retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
- if (retval)
- return retval;
-
- chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
-
- retval = sd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "sd_card->sd_type = 0x%x\n", sd_card->sd_type);
-
- return STATUS_SUCCESS;
-}
-
-static int reset_mmc_only(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- sd_card->sd_type = 0;
- sd_card->seq_mode = 0;
- sd_card->sd_data_buf_ready = 0;
- sd_card->capacity = 0;
- sd_card->sd_switch_fail = 0;
-
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status = 0;
- sd_card->sd_erase_status = 0;
-#endif
-
- chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity = 0;
-
- retval = enable_card_clock(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sd_init_power(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = reset_mmc(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sd_set_clock_divider(chip, SD_CLK_DIVIDE_0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_L, 0xFF, 0);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, REG_SD_BYTE_CNT_H, 0xFF, 2);
- if (retval)
- return retval;
-
- chip->capacity[chip->card2lun[SD_CARD]] = sd_card->capacity;
-
- retval = sd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "In %s, sd_card->sd_type = 0x%x\n",
- __func__, sd_card->sd_type);
-
- return STATUS_SUCCESS;
-}
-
-#define WAIT_DATA_READY_RTY_CNT 255
-
-static int wait_data_buf_ready(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int i, retval;
-
- for (i = 0; i < WAIT_DATA_READY_RTY_CNT; i++) {
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_NO_CARD);
- return STATUS_FAIL;
- }
-
- sd_card->sd_data_buf_ready = 0;
-
- retval = sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (sd_card->sd_data_buf_ready) {
- return sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr, SD_RSP_TYPE_R1, NULL, 0);
- }
- }
-
- sd_set_err_code(chip, SD_TO_ERR);
-
- return STATUS_FAIL;
-}
-
-void sd_stop_seq_mode(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- if (sd_card->seq_mode) {
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return;
-
- retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
- SD_RSP_TYPE_R1b, NULL, 0);
- if (retval != STATUS_SUCCESS)
- sd_set_err_code(chip, SD_STS_ERR);
-
- retval = sd_wait_state_data_ready(chip, 0x08, 1, 1000);
- if (retval != STATUS_SUCCESS)
- sd_set_err_code(chip, SD_STS_ERR);
-
- sd_card->seq_mode = 0;
-
- rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
- }
-}
-
-static inline int sd_auto_tune_clock(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- if (chip->asic_code) {
- if (sd_card->sd_clock > 30)
- sd_card->sd_clock -= 20;
- } else {
- switch (sd_card->sd_clock) {
- case CLK_200:
- sd_card->sd_clock = CLK_150;
- break;
-
- case CLK_150:
- sd_card->sd_clock = CLK_120;
- break;
-
- case CLK_120:
- sd_card->sd_clock = CLK_100;
- break;
-
- case CLK_100:
- sd_card->sd_clock = CLK_80;
- break;
-
- case CLK_80:
- sd_card->sd_clock = CLK_60;
- break;
-
- case CLK_60:
- sd_card->sd_clock = CLK_50;
- break;
-
- default:
- break;
- }
- }
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip, u32 start_sector,
- u16 sector_cnt)
-{
- struct sd_info *sd_card = &chip->sd_card;
- u32 data_addr;
- u8 cfg2;
- int retval;
-
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- dev_dbg(rtsx_dev(chip), "%s: Read %d %s from 0x%x\n", __func__,
- sector_cnt, (sector_cnt > 1) ? "sectors" : "sector",
- start_sector);
- } else {
- dev_dbg(rtsx_dev(chip), "%s: Write %d %s to 0x%x\n", __func__,
- sector_cnt, (sector_cnt > 1) ? "sectors" : "sector",
- start_sector);
- }
-
- sd_card->cleanup_counter = 0;
-
- if (!(chip->card_ready & SD_CARD)) {
- sd_card->seq_mode = 0;
-
- retval = reset_sd_card(chip);
- if (retval == STATUS_SUCCESS) {
- chip->card_ready |= SD_CARD;
- chip->card_fail &= ~SD_CARD;
- } else {
- chip->card_ready &= ~SD_CARD;
- chip->card_fail |= SD_CARD;
- chip->capacity[chip->card2lun[SD_CARD]] = 0;
- chip->rw_need_retry = 1;
- return STATUS_FAIL;
- }
- }
-
- if (!CHK_SD_HCXC(sd_card) && !CHK_MMC_SECTOR_MODE(sd_card))
- data_addr = start_sector << 9;
- else
- data_addr = start_sector;
-
- sd_clr_err_code(chip);
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_IO_ERR);
- goto RW_FAIL;
- }
-
- if (sd_card->seq_mode &&
- (sd_card->pre_dir != srb->sc_data_direction ||
- ((sd_card->pre_sec_addr + sd_card->pre_sec_cnt) !=
- start_sector))) {
- if (sd_card->pre_sec_cnt < 0x80 &&
- sd_card->pre_dir == DMA_FROM_DEVICE &&
- !CHK_SD30_SPEED(sd_card) &&
- !CHK_SD_HS(sd_card) &&
- !CHK_MMC_HS(sd_card)) {
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- }
-
- retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
- SD_RSP_TYPE_R1b, NULL, 0);
- if (retval != STATUS_SUCCESS) {
- chip->rw_need_retry = 1;
- sd_set_err_code(chip, SD_STS_ERR);
- goto RW_FAIL;
- }
-
- sd_card->seq_mode = 0;
-
- retval = rtsx_write_register(chip, RBCTL, RB_FLUSH, RB_FLUSH);
- if (retval != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_IO_ERR);
- goto RW_FAIL;
- }
-
- if (sd_card->pre_sec_cnt < 0x80 &&
- !CHK_SD30_SPEED(sd_card) &&
- !CHK_SD_HS(sd_card) &&
- !CHK_MMC_HS(sd_card)) {
- sd_send_cmd_get_rsp(chip, SEND_STATUS, sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0);
- }
- }
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF, 0x00);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF, 0x02);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
- (u8)sector_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
- (u8)(sector_cnt >> 8));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-
- if (CHK_MMC_8BIT(sd_card))
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1,
- 0x03, SD_BUS_WIDTH_8);
- else if (CHK_MMC_4BIT(sd_card) || CHK_SD(sd_card))
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1,
- 0x03, SD_BUS_WIDTH_4);
- else
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1,
- 0x03, SD_BUS_WIDTH_1);
-
- if (sd_card->seq_mode) {
- cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 |
- SD_NO_WAIT_BUSY_END | SD_NO_CHECK_CRC7 |
- SD_RSP_LEN_0;
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, cfg2);
-
- trans_dma_enable(srb->sc_data_direction, chip, sector_cnt * 512,
- DMA_512);
-
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_READ_3 | SD_TRANSFER_START);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
- }
-
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
- } else {
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- dev_dbg(rtsx_dev(chip), "SD/MMC CMD %d\n",
- READ_MULTIPLE_BLOCK);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
- 0x40 | READ_MULTIPLE_BLOCK);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF,
- (u8)(data_addr >> 24));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF,
- (u8)(data_addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF,
- (u8)(data_addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF,
- (u8)data_addr);
-
- cfg2 = SD_CALCULATE_CRC7 | SD_CHECK_CRC16 |
- SD_NO_WAIT_BUSY_END | SD_CHECK_CRC7 |
- SD_RSP_LEN_6;
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
- cfg2);
-
- trans_dma_enable(srb->sc_data_direction, chip,
- sector_cnt * 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
- } else {
- retval = rtsx_send_cmd(chip, SD_CARD, 50);
- if (retval < 0) {
- rtsx_clear_sd_error(chip);
-
- chip->rw_need_retry = 1;
- sd_set_err_code(chip, SD_TO_ERR);
- goto RW_FAIL;
- }
-
- retval = wait_data_buf_ready(chip);
- if (retval != STATUS_SUCCESS) {
- chip->rw_need_retry = 1;
- sd_set_err_code(chip, SD_TO_ERR);
- goto RW_FAIL;
- }
-
- retval = sd_send_cmd_get_rsp(chip, WRITE_MULTIPLE_BLOCK,
- data_addr, SD_RSP_TYPE_R1,
- NULL, 0);
- if (retval != STATUS_SUCCESS) {
- chip->rw_need_retry = 1;
- goto RW_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- cfg2 = SD_NO_CALCULATE_CRC7 | SD_CHECK_CRC16 |
- SD_NO_WAIT_BUSY_END |
- SD_NO_CHECK_CRC7 | SD_RSP_LEN_0;
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF,
- cfg2);
-
- trans_dma_enable(srb->sc_data_direction, chip,
- sector_cnt * 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
- }
-
- sd_card->seq_mode = 1;
- }
-
- retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb),
- scsi_bufflen(srb), scsi_sg_count(srb),
- srb->sc_data_direction, chip->sd_timeout);
- if (retval < 0) {
- u8 stat = 0;
- int err;
-
- sd_card->seq_mode = 0;
-
- if (retval == -ETIMEDOUT)
- err = STATUS_TIMEDOUT;
- else
- err = STATUS_FAIL;
-
- rtsx_read_register(chip, REG_SD_STAT1, &stat);
- rtsx_clear_sd_error(chip);
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- chip->rw_need_retry = 0;
- dev_dbg(rtsx_dev(chip), "No card exist, exit %s\n",
- __func__);
- return STATUS_FAIL;
- }
-
- chip->rw_need_retry = 1;
-
- retval = sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
- SD_RSP_TYPE_R1b, NULL, 0);
- if (retval != STATUS_SUCCESS) {
- sd_set_err_code(chip, SD_STS_ERR);
- goto RW_FAIL;
- }
-
- if (stat & (SD_CRC7_ERR | SD_CRC16_ERR | SD_CRC_WRITE_ERR)) {
- dev_dbg(rtsx_dev(chip), "SD CRC error, tune clock!\n");
- sd_set_err_code(chip, SD_CRC_ERR);
- goto RW_FAIL;
- }
-
- if (err == STATUS_TIMEDOUT) {
- sd_set_err_code(chip, SD_TO_ERR);
- goto RW_FAIL;
- }
-
- return err;
- }
-
- sd_card->pre_sec_addr = start_sector;
- sd_card->pre_sec_cnt = sector_cnt;
- sd_card->pre_dir = srb->sc_data_direction;
-
- return STATUS_SUCCESS;
-
-RW_FAIL:
- sd_card->seq_mode = 0;
-
- if (detect_card_cd(chip, SD_CARD) != STATUS_SUCCESS) {
- chip->rw_need_retry = 0;
- dev_dbg(rtsx_dev(chip), "No card exist, exit %s\n", __func__);
- return STATUS_FAIL;
- }
-
- if (sd_check_err_code(chip, SD_CRC_ERR)) {
- if (CHK_MMC_4BIT(sd_card) || CHK_MMC_8BIT(sd_card)) {
- sd_card->mmc_dont_switch_bus = 1;
- reset_mmc_only(chip);
- sd_card->mmc_dont_switch_bus = 0;
- } else {
- sd_card->need_retune = 1;
- sd_auto_tune_clock(chip);
- }
- } else if (sd_check_err_code(chip, SD_TO_ERR | SD_STS_ERR)) {
- retval = reset_sd_card(chip);
- if (retval != STATUS_SUCCESS) {
- chip->card_ready &= ~SD_CARD;
- chip->card_fail |= SD_CARD;
- chip->capacity[chip->card2lun[SD_CARD]] = 0;
- }
- }
-
- return STATUS_FAIL;
-}
-
-#ifdef SUPPORT_CPRM
-int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx, u32 arg,
- u8 rsp_type, u8 *rsp, int rsp_len,
- bool special_check)
-{
- int retval;
- int timeout = 100;
- u16 reg_addr;
- u8 *ptr;
- int stat_idx = 0;
- int rty_cnt = 0;
-
- dev_dbg(rtsx_dev(chip), "EXT SD/MMC CMD %d\n", cmd_idx);
-
- if (rsp_type == SD_RSP_TYPE_R1b)
- timeout = 3000;
-
-RTY_SEND_CMD:
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF, 0x40 | cmd_idx);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF, (u8)(arg >> 24));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF, (u8)(arg >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF, (u8)(arg >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF, (u8)arg);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
- 0xFF, SD_TM_CMD_RSP | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER, SD_TRANSFER_END,
- SD_TRANSFER_END);
-
- if (rsp_type == SD_RSP_TYPE_R2) {
- for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- stat_idx = 17;
- } else if (rsp_type != SD_RSP_TYPE_R0) {
- for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0, 0);
-
- stat_idx = 6;
- }
- rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0, 0);
-
- rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_STAT1, 0, 0);
-
- retval = rtsx_send_cmd(chip, SD_CARD, timeout);
- if (retval < 0) {
- if (retval == -ETIMEDOUT) {
- rtsx_clear_sd_error(chip);
-
- if (rsp_type & SD_WAIT_BUSY_END) {
- retval = sd_check_data0_status(chip);
- if (retval != STATUS_SUCCESS)
- return retval;
- } else {
- sd_set_err_code(chip, SD_TO_ERR);
- }
- }
- return STATUS_FAIL;
- }
-
- if (rsp_type == SD_RSP_TYPE_R0)
- return STATUS_SUCCESS;
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- if ((ptr[0] & 0xC0) != 0) {
- sd_set_err_code(chip, SD_STS_ERR);
- return STATUS_FAIL;
- }
-
- if (!(rsp_type & SD_NO_CHECK_CRC7)) {
- if (ptr[stat_idx] & SD_CRC7_ERR) {
- if (cmd_idx == WRITE_MULTIPLE_BLOCK) {
- sd_set_err_code(chip, SD_CRC_ERR);
- return STATUS_FAIL;
- }
- if (rty_cnt < SD_MAX_RETRY_COUNT) {
- wait_timeout(20);
- rty_cnt++;
- goto RTY_SEND_CMD;
- } else {
- sd_set_err_code(chip, SD_CRC_ERR);
- return STATUS_FAIL;
- }
- }
- }
-
- if (cmd_idx == SELECT_CARD || cmd_idx == APP_CMD ||
- cmd_idx == SEND_STATUS || cmd_idx == STOP_TRANSMISSION) {
- if (cmd_idx != STOP_TRANSMISSION && !special_check) {
- if (ptr[1] & 0x80)
- return STATUS_FAIL;
- }
-#ifdef SUPPORT_SD_LOCK
- if (ptr[1] & 0x7D) {
-#else
- if (ptr[1] & 0x7F) {
-#endif
- return STATUS_FAIL;
- }
- if (ptr[2] & 0xF8)
- return STATUS_FAIL;
-
- if (cmd_idx == SELECT_CARD) {
- if (rsp_type == SD_RSP_TYPE_R2) {
- if ((ptr[3] & 0x1E) != 0x04)
- return STATUS_FAIL;
- }
- }
- }
-
- if (rsp && rsp_len)
- memcpy(rsp, ptr, rsp_len);
-
- return STATUS_SUCCESS;
-}
-
-int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type)
-{
- int retval, rsp_len;
- u16 reg_addr;
-
- if (rsp_type == SD_RSP_TYPE_R0)
- return STATUS_SUCCESS;
-
- rtsx_init_cmd(chip);
-
- if (rsp_type == SD_RSP_TYPE_R2) {
- for (reg_addr = PPBUF_BASE2; reg_addr < PPBUF_BASE2 + 16;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
-
- rsp_len = 17;
- } else if (rsp_type != SD_RSP_TYPE_R0) {
- for (reg_addr = REG_SD_CMD0; reg_addr <= REG_SD_CMD4;
- reg_addr++)
- rtsx_add_cmd(chip, READ_REG_CMD, reg_addr, 0xFF, 0);
-
- rsp_len = 6;
- }
- rtsx_add_cmd(chip, READ_REG_CMD, REG_SD_CMD5, 0xFF, 0);
-
- retval = rtsx_send_cmd(chip, SD_CARD, 100);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (rsp) {
- int min_len = (rsp_len < len) ? rsp_len : len;
-
- memcpy(rsp, rtsx_get_cmd_data(chip), min_len);
-
- dev_dbg(rtsx_dev(chip), "min_len = %d\n", min_len);
- dev_dbg(rtsx_dev(chip), "Response in cmd buf: 0x%x 0x%x 0x%x 0x%x\n",
- rsp[0], rsp[1], rsp[2], rsp[3]);
- }
-
- return STATUS_SUCCESS;
-}
-
-int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int len;
- u8 buf[18] = {
- 0x00,
- 0x00,
- 0x00,
- 0x0E,
- 0x00,
- 0x00,
- 0x00,
- 0x00,
- 0x53,
- 0x44,
- 0x20,
- 0x43,
- 0x61,
- 0x72,
- 0x64,
- 0x00,
- 0x00,
- 0x00,
- };
-
- sd_card->pre_cmd_err = 0;
-
- if (!(CHK_BIT(chip->lun_mc, lun))) {
- SET_BIT(chip->lun_mc, lun);
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[2] != 0x53 || srb->cmnd[3] != 0x44 ||
- srb->cmnd[4] != 0x20 || srb->cmnd[5] != 0x43 ||
- srb->cmnd[6] != 0x61 || srb->cmnd[7] != 0x72 ||
- srb->cmnd[8] != 0x64) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- switch (srb->cmnd[1] & 0x0F) {
- case 0:
- sd_card->sd_pass_thru_en = 0;
- break;
-
- case 1:
- sd_card->sd_pass_thru_en = 1;
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- buf[5] = (CHK_SD(sd_card) == 1) ? 0x01 : 0x02;
- if (chip->card_wp & SD_CARD)
- buf[5] |= 0x80;
-
- buf[6] = (u8)(sd_card->sd_addr >> 16);
- buf[7] = (u8)(sd_card->sd_addr >> 24);
-
- buf[15] = chip->max_lun;
-
- len = min_t(int, 18, scsi_bufflen(srb));
- rtsx_stor_set_xfer_buf(buf, len, srb);
-
- return TRANSPORT_GOOD;
-}
-
-static inline int get_rsp_type(struct scsi_cmnd *srb, u8 *rsp_type,
- int *rsp_len)
-{
- if (!rsp_type || !rsp_len)
- return STATUS_FAIL;
-
- switch (srb->cmnd[10]) {
- case 0x03:
- *rsp_type = SD_RSP_TYPE_R0;
- *rsp_len = 0;
- break;
-
- case 0x04:
- *rsp_type = SD_RSP_TYPE_R1;
- *rsp_len = 6;
- break;
-
- case 0x05:
- *rsp_type = SD_RSP_TYPE_R1b;
- *rsp_len = 6;
- break;
-
- case 0x06:
- *rsp_type = SD_RSP_TYPE_R2;
- *rsp_len = 17;
- break;
-
- case 0x07:
- *rsp_type = SD_RSP_TYPE_R3;
- *rsp_len = 6;
- break;
-
- default:
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval, rsp_len;
- u8 cmd_idx, rsp_type;
- bool standby = false, acmd = false;
- u32 arg;
-
- if (!sd_card->sd_pass_thru_en) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- if (sd_card->pre_cmd_err) {
- sd_card->pre_cmd_err = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- cmd_idx = srb->cmnd[2] & 0x3F;
- if (srb->cmnd[1] & 0x02)
- standby = true;
-
- if (srb->cmnd[1] & 0x01)
- acmd = true;
-
- arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
- ((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
-
- retval = get_rsp_type(srb, &rsp_type, &rsp_len);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- sd_card->last_rsp_type = rsp_type;
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
- if (CHK_MMC_8BIT(sd_card)) {
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
- SD_BUS_WIDTH_8);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
- SD_BUS_WIDTH_4);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
- }
- }
-#else
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-#endif
-
- if (standby) {
- retval = sd_select_card(chip, 0);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_cmd_failed;
- }
-
- if (acmd) {
- retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
- sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_cmd_failed;
- }
-
- retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
- sd_card->rsp, rsp_len, false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_cmd_failed;
-
- if (standby) {
- retval = sd_select_card(chip, 1);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_cmd_failed;
- }
-
-#ifdef SUPPORT_SD_LOCK
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_cmd_failed;
-#endif
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-
-sd_execute_cmd_failed:
- sd_card->pre_cmd_err = 1;
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- release_sd_card(chip);
- do_reset_sd_card(chip);
- if (!(chip->card_ready & SD_CARD))
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-
- return TRANSPORT_FAILED;
-}
-
-int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval, rsp_len, i;
- bool read_err = false, cmd13_checkbit = false;
- u8 cmd_idx, rsp_type, bus_width;
- bool standby = false, send_cmd12 = false, acmd = false;
- u32 data_len;
-
- if (!sd_card->sd_pass_thru_en) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (sd_card->pre_cmd_err) {
- sd_card->pre_cmd_err = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- cmd_idx = srb->cmnd[2] & 0x3F;
- if (srb->cmnd[1] & 0x04)
- send_cmd12 = true;
-
- if (srb->cmnd[1] & 0x02)
- standby = true;
-
- if (srb->cmnd[1] & 0x01)
- acmd = true;
-
- data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8]
- << 8) | srb->cmnd[9];
-
- retval = get_rsp_type(srb, &rsp_type, &rsp_len);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- sd_card->last_rsp_type = rsp_type;
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
- if (CHK_MMC_8BIT(sd_card))
- bus_width = SD_BUS_WIDTH_8;
- else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card))
- bus_width = SD_BUS_WIDTH_4;
- else
- bus_width = SD_BUS_WIDTH_1;
- } else {
- bus_width = SD_BUS_WIDTH_4;
- }
- dev_dbg(rtsx_dev(chip), "bus_width = %d\n", bus_width);
-#else
- bus_width = SD_BUS_WIDTH_4;
-#endif
-
- if (data_len < 512) {
- retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if (standby) {
- retval = sd_select_card(chip, 0);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if (acmd) {
- retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
- sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if (data_len <= 512) {
- int min_len;
- u8 *buf;
- u16 byte_cnt, blk_cnt;
- u8 cmd[5];
-
- byte_cnt = ((u16)(srb->cmnd[8] & 0x03) << 8) | srb->cmnd[9];
- blk_cnt = 1;
-
- cmd[0] = 0x40 | cmd_idx;
- cmd[1] = srb->cmnd[3];
- cmd[2] = srb->cmnd[4];
- cmd[3] = srb->cmnd[5];
- cmd[4] = srb->cmnd[6];
-
- buf = kmalloc(data_len, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- retval = sd_read_data(chip, SD_TM_NORMAL_READ, cmd, 5, byte_cnt,
- blk_cnt, bus_width, buf, data_len, 2000);
- if (retval != STATUS_SUCCESS) {
- read_err = true;
- kfree(buf);
- rtsx_clear_sd_error(chip);
- goto sd_execute_read_cmd_failed;
- }
-
- min_len = min(data_len, scsi_bufflen(srb));
- rtsx_stor_set_xfer_buf(buf, min_len, srb);
-
- kfree(buf);
- } else if (!(data_len & 0x1FF)) {
- rtsx_init_cmd(chip);
-
- trans_dma_enable(DMA_FROM_DEVICE, chip, data_len, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
- 0x02);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
- 0x00);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
- 0xFF, (srb->cmnd[7] & 0xFE) >> 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
- 0xFF, (u8)((data_len & 0x0001FE00) >> 9));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD0, 0xFF,
- 0x40 | cmd_idx);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD1, 0xFF,
- srb->cmnd[3]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD2, 0xFF,
- srb->cmnd[4]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD3, 0xFF,
- srb->cmnd[5]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CMD4, 0xFF,
- srb->cmnd[6]);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG1, 0x03, bus_width);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_CFG2, 0xFF, rsp_type);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER,
- 0xFF, SD_TM_AUTO_READ_2 | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb),
- scsi_bufflen(srb),
- scsi_sg_count(srb),
- DMA_FROM_DEVICE, 10000);
- if (retval < 0) {
- read_err = true;
- rtsx_clear_sd_error(chip);
- goto sd_execute_read_cmd_failed;
- }
-
- } else {
- goto sd_execute_read_cmd_failed;
- }
-
- retval = ext_sd_get_rsp(chip, rsp_len, sd_card->rsp, rsp_type);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
-
- if (standby) {
- retval = sd_select_card(chip, 1);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if (send_cmd12) {
- retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
- SD_RSP_TYPE_R1b, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if (data_len < 512) {
- retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
-
- retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
-
- retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
- }
-
- if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04))
- cmd13_checkbit = true;
-
- for (i = 0; i < 3; i++) {
- retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0,
- cmd13_checkbit);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (retval != STATUS_SUCCESS)
- goto sd_execute_read_cmd_failed;
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-
-sd_execute_read_cmd_failed:
- sd_card->pre_cmd_err = 1;
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- if (read_err)
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
-
- release_sd_card(chip);
- do_reset_sd_card(chip);
- if (!(chip->card_ready & SD_CARD))
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-
- return TRANSPORT_FAILED;
-}
-
-int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval, rsp_len, i;
- bool write_err = false, cmd13_checkbit = false;
- u8 cmd_idx, rsp_type;
- bool standby = false, send_cmd12 = false, acmd = false;
- u32 data_len, arg;
-#ifdef SUPPORT_SD_LOCK
- int lock_cmd_fail = 0;
- u8 sd_lock_state = 0;
- u8 lock_cmd_type = 0;
-#endif
-
- if (!sd_card->sd_pass_thru_en) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (sd_card->pre_cmd_err) {
- sd_card->pre_cmd_err = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- cmd_idx = srb->cmnd[2] & 0x3F;
- if (srb->cmnd[1] & 0x04)
- send_cmd12 = true;
-
- if (srb->cmnd[1] & 0x02)
- standby = true;
-
- if (srb->cmnd[1] & 0x01)
- acmd = true;
-
- data_len = ((u32)srb->cmnd[7] << 16) | ((u32)srb->cmnd[8]
- << 8) | srb->cmnd[9];
- arg = ((u32)srb->cmnd[3] << 24) | ((u32)srb->cmnd[4] << 16) |
- ((u32)srb->cmnd[5] << 8) | srb->cmnd[6];
-
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK) {
- sd_lock_state = sd_card->sd_lock_status;
- sd_lock_state &= SD_LOCKED;
- }
-#endif
-
- retval = get_rsp_type(srb, &rsp_type, &rsp_len);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
- sd_card->last_rsp_type = rsp_type;
-
- retval = sd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
-#ifdef SUPPORT_SD_LOCK
- if ((sd_card->sd_lock_status & SD_LOCK_1BIT_MODE) == 0) {
- if (CHK_MMC_8BIT(sd_card)) {
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
- SD_BUS_WIDTH_8);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-
- } else if (CHK_SD(sd_card) || CHK_MMC_4BIT(sd_card)) {
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03,
- SD_BUS_WIDTH_4);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
- }
- }
-#else
- retval = rtsx_write_register(chip, REG_SD_CFG1, 0x03, SD_BUS_WIDTH_4);
- if (retval != STATUS_SUCCESS)
- return TRANSPORT_FAILED;
-#endif
-
- if (data_len < 512) {
- retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, data_len,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- if (standby) {
- retval = sd_select_card(chip, 0);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- if (acmd) {
- retval = ext_sd_send_cmd_get_rsp(chip, APP_CMD,
- sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- retval = ext_sd_send_cmd_get_rsp(chip, cmd_idx, arg, rsp_type,
- sd_card->rsp, rsp_len, false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
-
- if (data_len <= 512) {
- u16 i;
- u8 *buf;
-
- buf = kmalloc(data_len, GFP_KERNEL);
- if (!buf)
- return TRANSPORT_ERROR;
-
- rtsx_stor_get_xfer_buf(buf, data_len, srb);
-
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK)
- lock_cmd_type = buf[0] & 0x0F;
-#endif
-
- if (data_len > 256) {
- rtsx_init_cmd(chip);
- for (i = 0; i < 256; i++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- PPBUF_BASE2 + i, 0xFF, buf[i]);
- }
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- goto sd_execute_write_cmd_failed;
- }
-
- rtsx_init_cmd(chip);
- for (i = 256; i < data_len; i++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- PPBUF_BASE2 + i, 0xFF, buf[i]);
- }
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- goto sd_execute_write_cmd_failed;
- }
- } else {
- rtsx_init_cmd(chip);
- for (i = 0; i < data_len; i++) {
- rtsx_add_cmd(chip, WRITE_REG_CMD,
- PPBUF_BASE2 + i, 0xFF, buf[i]);
- }
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- goto sd_execute_write_cmd_failed;
- }
- }
-
- kfree(buf);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
- srb->cmnd[8] & 0x03);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
- srb->cmnd[9]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H, 0xFF,
- 0x00);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L, 0xFF,
- 0x01);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, SD_CARD, 250);
- } else if (!(data_len & 0x1FF)) {
- rtsx_init_cmd(chip);
-
- trans_dma_enable(DMA_TO_DEVICE, chip, data_len, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_H, 0xFF,
- 0x02);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BYTE_CNT_L, 0xFF,
- 0x00);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_H,
- 0xFF, (srb->cmnd[7] & 0xFE) >> 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_BLOCK_CNT_L,
- 0xFF, (u8)((data_len & 0x0001FE00) >> 9));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, REG_SD_TRANSFER, 0xFF,
- SD_TM_AUTO_WRITE_3 | SD_TRANSFER_START);
- rtsx_add_cmd(chip, CHECK_REG_CMD, REG_SD_TRANSFER,
- SD_TRANSFER_END, SD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data(chip, SD_CARD, scsi_sglist(srb),
- scsi_bufflen(srb),
- scsi_sg_count(srb),
- DMA_TO_DEVICE, 10000);
-
- } else {
- goto sd_execute_write_cmd_failed;
- }
-
- if (retval < 0) {
- write_err = true;
- rtsx_clear_sd_error(chip);
- goto sd_execute_write_cmd_failed;
- }
-
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK) {
- if (lock_cmd_type == SD_ERASE) {
- sd_card->sd_erase_status = SD_UNDER_ERASING;
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
- }
-
- rtsx_init_cmd(chip);
- rtsx_add_cmd(chip, CHECK_REG_CMD, 0xFD30, 0x02, 0x02);
-
- retval = rtsx_send_cmd(chip, SD_CARD, 250);
- if (retval < 0) {
- write_err = true;
- rtsx_clear_sd_error(chip);
- goto sd_execute_write_cmd_failed;
- }
-
- retval = sd_update_lock_status(chip);
- if (retval != STATUS_SUCCESS) {
- dev_dbg(rtsx_dev(chip), "Lock command fail!\n");
- lock_cmd_fail = 1;
- }
- }
-#endif /* SUPPORT_SD_LOCK */
-
- if (standby) {
- retval = sd_select_card(chip, 1);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- if (send_cmd12) {
- retval = ext_sd_send_cmd_get_rsp(chip, STOP_TRANSMISSION, 0,
- SD_RSP_TYPE_R1b, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- if (data_len < 512) {
- retval = ext_sd_send_cmd_get_rsp(chip, SET_BLOCKLEN, 0x200,
- SD_RSP_TYPE_R1, NULL, 0,
- false);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
-
- retval = rtsx_write_register(chip, SD_BYTE_CNT_H, 0xFF, 0x02);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
-
- retval = rtsx_write_register(chip, SD_BYTE_CNT_L, 0xFF, 0x00);
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
- }
-
- if ((srb->cmnd[1] & 0x02) || (srb->cmnd[1] & 0x04))
- cmd13_checkbit = true;
-
- for (i = 0; i < 3; i++) {
- retval = ext_sd_send_cmd_get_rsp(chip, SEND_STATUS,
- sd_card->sd_addr,
- SD_RSP_TYPE_R1, NULL, 0,
- cmd13_checkbit);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (retval != STATUS_SUCCESS)
- goto sd_execute_write_cmd_failed;
-
-#ifdef SUPPORT_SD_LOCK
- if (cmd_idx == LOCK_UNLOCK) {
- if (!lock_cmd_fail) {
- dev_dbg(rtsx_dev(chip), "lock_cmd_type = 0x%x\n",
- lock_cmd_type);
- if (lock_cmd_type & SD_CLR_PWD)
- sd_card->sd_lock_status &= ~SD_PWD_EXIST;
-
- if (lock_cmd_type & SD_SET_PWD)
- sd_card->sd_lock_status |= SD_PWD_EXIST;
- }
-
- dev_dbg(rtsx_dev(chip), "sd_lock_state = 0x%x, sd_card->sd_lock_status = 0x%x\n",
- sd_lock_state, sd_card->sd_lock_status);
- if (sd_lock_state ^ (sd_card->sd_lock_status & SD_LOCKED)) {
- sd_card->sd_lock_notify = 1;
- if (sd_lock_state &&
- (sd_card->sd_lock_status & SD_LOCK_1BIT_MODE)) {
- sd_card->sd_lock_status |= (SD_UNLOCK_POW_ON | SD_SDR_RST);
- if (CHK_SD(sd_card)) {
- retval = reset_sd(chip);
- if (retval != STATUS_SUCCESS) {
- sd_card->sd_lock_status &=
- ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
- goto sd_execute_write_cmd_failed;
- }
- }
-
- sd_card->sd_lock_status &= ~(SD_UNLOCK_POW_ON | SD_SDR_RST);
- }
- }
- }
-
- if (lock_cmd_fail) {
- scsi_set_resid(srb, 0);
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- return TRANSPORT_FAILED;
- }
-#endif /* SUPPORT_SD_LOCK */
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-
-sd_execute_write_cmd_failed:
- sd_card->pre_cmd_err = 1;
- set_sense_type(chip, lun, SENSE_TYPE_NO_SENSE);
- if (write_err)
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
-
- release_sd_card(chip);
- do_reset_sd_card(chip);
- if (!(chip->card_ready & SD_CARD))
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
-
- return TRANSPORT_FAILED;
-}
-
-int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int count;
- u16 data_len;
-
- if (!sd_card->sd_pass_thru_en) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (sd_card->pre_cmd_err) {
- sd_card->pre_cmd_err = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- data_len = ((u16)srb->cmnd[7] << 8) | srb->cmnd[8];
-
- if (sd_card->last_rsp_type == SD_RSP_TYPE_R0) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- } else if (sd_card->last_rsp_type == SD_RSP_TYPE_R2) {
- count = (data_len < 17) ? data_len : 17;
- } else {
- count = (data_len < 6) ? data_len : 6;
- }
- rtsx_stor_set_xfer_buf(sd_card->rsp, count, srb);
-
- dev_dbg(rtsx_dev(chip), "Response length: %d\n", data_len);
- dev_dbg(rtsx_dev(chip), "Response: 0x%x 0x%x 0x%x 0x%x\n",
- sd_card->rsp[0], sd_card->rsp[1],
- sd_card->rsp[2], sd_card->rsp[3]);
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-}
-
-int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- unsigned int lun = SCSI_LUN(srb);
- int retval;
-
- if (!sd_card->sd_pass_thru_en) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- if (sd_card->pre_cmd_err) {
- sd_card->pre_cmd_err = 0;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_CHANGE);
- return TRANSPORT_FAILED;
- }
-
- if (srb->cmnd[2] != 0x53 || srb->cmnd[3] != 0x44 ||
- srb->cmnd[4] != 0x20 || srb->cmnd[5] != 0x43 ||
- srb->cmnd[6] != 0x61 || srb->cmnd[7] != 0x72 ||
- srb->cmnd[8] != 0x64) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- switch (srb->cmnd[1] & 0x0F) {
- case 0:
-#ifdef SUPPORT_SD_LOCK
- if (srb->cmnd[9] == 0x64)
- sd_card->sd_lock_status |= SD_SDR_RST;
-#endif
- retval = reset_sd_card(chip);
- if (retval != STATUS_SUCCESS) {
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_SDR_RST;
-#endif
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- sd_card->pre_cmd_err = 1;
- return TRANSPORT_FAILED;
- }
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status &= ~SD_SDR_RST;
-#endif
- break;
-
- case 1:
- retval = reset_sd(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- sd_card->pre_cmd_err = 1;
- return TRANSPORT_FAILED;
- }
- break;
-
- default:
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_INVALID_CMD_FIELD);
- return TRANSPORT_FAILED;
- }
-
- scsi_set_resid(srb, 0);
- return TRANSPORT_GOOD;
-}
-#endif
-
-void sd_cleanup_work(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
-
- if (sd_card->seq_mode) {
- dev_dbg(rtsx_dev(chip), "SD: stop transmission\n");
- sd_stop_seq_mode(chip);
- sd_card->cleanup_counter = 0;
- }
-}
-
-int sd_power_off_card3v3(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = disable_card_clock(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_OE, SD_OUTPUT_EN, 0);
- if (retval)
- return retval;
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_off(chip, SD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- mdelay(50);
- }
-
- if (chip->asic_code) {
- retval = sd_pull_ctl_disable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL,
- FPGA_SD_PULL_CTL_BIT | 0x20,
- FPGA_SD_PULL_CTL_BIT);
- if (retval)
- return retval;
- }
-
- return STATUS_SUCCESS;
-}
-
-int release_sd_card(struct rtsx_chip *chip)
-{
- struct sd_info *sd_card = &chip->sd_card;
- int retval;
-
- chip->card_ready &= ~SD_CARD;
- chip->card_fail &= ~SD_CARD;
- chip->card_wp &= ~SD_CARD;
-
- chip->sd_io = 0;
- chip->sd_int = 0;
-
-#ifdef SUPPORT_SD_LOCK
- sd_card->sd_lock_status = 0;
- sd_card->sd_erase_status = 0;
-#endif
-
- memset(sd_card->raw_csd, 0, 16);
- memset(sd_card->raw_scr, 0, 8);
-
- retval = sd_power_off_card3v3(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts5208/sd.h b/drivers/staging/rts5208/sd.h
deleted file mode 100644
index f4ff62653b56..000000000000
--- a/drivers/staging/rts5208/sd.h
+++ /dev/null
@@ -1,289 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_SD_H
-#define __REALTEK_RTSX_SD_H
-
-#include "rtsx_chip.h"
-
-#define SUPPORT_VOLTAGE 0x003C0000
-
-/* Error Code */
-#define SD_NO_ERROR 0x0
-#define SD_CRC_ERR 0x80
-#define SD_TO_ERR 0x40
-#define SD_NO_CARD 0x20
-#define SD_BUSY 0x10
-#define SD_STS_ERR 0x08
-#define SD_RSP_TIMEOUT 0x04
-#define SD_IO_ERR 0x02
-
-/* Return code for MMC switch bus */
-#define SWITCH_SUCCESS 0
-#define SWITCH_ERR 1
-#define SWITCH_FAIL 2
-
-/* MMC/SD Command Index */
-/* Basic command (class 0) */
-#define GO_IDLE_STATE 0
-#define SEND_OP_COND 1
-#define ALL_SEND_CID 2
-#define SET_RELATIVE_ADDR 3
-#define SEND_RELATIVE_ADDR 3
-#define SET_DSR 4
-#define IO_SEND_OP_COND 5
-#define SWITCH 6
-#define SELECT_CARD 7
-#define DESELECT_CARD 7
-/* CMD8 is "SEND_EXT_CSD" for MMC4.x Spec
- * while is "SEND_IF_COND" for SD 2.0
- */
-#define SEND_EXT_CSD 8
-#define SEND_IF_COND 8
-
-#define SEND_CSD 9
-#define SEND_CID 10
-#define VOLTAGE_SWITCH 11
-#define READ_DAT_UTIL_STOP 11
-#define STOP_TRANSMISSION 12
-#define SEND_STATUS 13
-#define GO_INACTIVE_STATE 15
-
-#define SET_BLOCKLEN 16
-#define READ_SINGLE_BLOCK 17
-#define READ_MULTIPLE_BLOCK 18
-#define SEND_TUNING_PATTERN 19
-
-#define BUSTEST_R 14
-#define BUSTEST_W 19
-
-#define WRITE_BLOCK 24
-#define WRITE_MULTIPLE_BLOCK 25
-#define PROGRAM_CSD 27
-
-#define ERASE_WR_BLK_START 32
-#define ERASE_WR_BLK_END 33
-#define ERASE_CMD 38
-
-#define LOCK_UNLOCK 42
-#define IO_RW_DIRECT 52
-
-#define APP_CMD 55
-#define GEN_CMD 56
-
-#define SET_BUS_WIDTH 6
-#define SD_STATUS 13
-#define SEND_NUM_WR_BLOCKS 22
-#define SET_WR_BLK_ERASE_COUNT 23
-#define SD_APP_OP_COND 41
-#define SET_CLR_CARD_DETECT 42
-#define SEND_SCR 51
-
-#define SD_READ_COMPLETE 0x00
-#define SD_READ_TO 0x01
-#define SD_READ_ADVENCE 0x02
-
-#define SD_CHECK_MODE 0x00
-#define SD_SWITCH_MODE 0x80
-#define SD_FUNC_GROUP_1 0x01
-#define SD_FUNC_GROUP_2 0x02
-#define SD_FUNC_GROUP_3 0x03
-#define SD_FUNC_GROUP_4 0x04
-#define SD_CHECK_SPEC_V1_1 0xFF
-
-#define NO_ARGUMENT 0x00
-#define CHECK_PATTERN 0x000000AA
-#define VOLTAGE_SUPPLY_RANGE 0x00000100
-#define SUPPORT_HIGH_AND_EXTENDED_CAPACITY 0x40000000
-#define SUPPORT_MAX_POWER_PERMANCE 0x10000000
-#define SUPPORT_1V8 0x01000000
-
-#define SWITCH_NO_ERR 0x00
-#define CARD_NOT_EXIST 0x01
-#define SPEC_NOT_SUPPORT 0x02
-#define CHECK_MODE_ERR 0x03
-#define CHECK_NOT_READY 0x04
-#define SWITCH_CRC_ERR 0x05
-#define SWITCH_MODE_ERR 0x06
-#define SWITCH_PASS 0x07
-
-#ifdef SUPPORT_SD_LOCK
-#define SD_ERASE 0x08
-#define SD_LOCK 0x04
-#define SD_UNLOCK 0x00
-#define SD_CLR_PWD 0x02
-#define SD_SET_PWD 0x01
-
-#define SD_PWD_LEN 0x10
-
-#define SD_LOCKED 0x80
-#define SD_LOCK_1BIT_MODE 0x40
-#define SD_PWD_EXIST 0x20
-#define SD_UNLOCK_POW_ON 0x01
-#define SD_SDR_RST 0x02
-
-#define SD_NOT_ERASE 0x00
-#define SD_UNDER_ERASING 0x01
-#define SD_COMPLETE_ERASE 0x02
-
-#define SD_RW_FORBIDDEN 0x0F
-
-#endif
-
-#define HS_SUPPORT 0x01
-#define SDR50_SUPPORT 0x02
-#define SDR104_SUPPORT 0x03
-#define DDR50_SUPPORT 0x04
-
-#define HS_SUPPORT_MASK 0x02
-#define SDR50_SUPPORT_MASK 0x04
-#define SDR104_SUPPORT_MASK 0x08
-#define DDR50_SUPPORT_MASK 0x10
-
-#define HS_QUERY_SWITCH_OK 0x01
-#define SDR50_QUERY_SWITCH_OK 0x02
-#define SDR104_QUERY_SWITCH_OK 0x03
-#define DDR50_QUERY_SWITCH_OK 0x04
-
-#define HS_SWITCH_BUSY 0x02
-#define SDR50_SWITCH_BUSY 0x04
-#define SDR104_SWITCH_BUSY 0x08
-#define DDR50_SWITCH_BUSY 0x10
-
-#define FUNCTION_GROUP1_SUPPORT_OFFSET 0x0D
-#define FUNCTION_GROUP1_QUERY_SWITCH_OFFSET 0x10
-#define FUNCTION_GROUP1_CHECK_BUSY_OFFSET 0x1D
-
-#define DRIVING_TYPE_A 0x01
-#define DRIVING_TYPE_B 0x00
-#define DRIVING_TYPE_C 0x02
-#define DRIVING_TYPE_D 0x03
-
-#define DRIVING_TYPE_A_MASK 0x02
-#define DRIVING_TYPE_B_MASK 0x01
-#define DRIVING_TYPE_C_MASK 0x04
-#define DRIVING_TYPE_D_MASK 0x08
-
-#define TYPE_A_QUERY_SWITCH_OK 0x01
-#define TYPE_B_QUERY_SWITCH_OK 0x00
-#define TYPE_C_QUERY_SWITCH_OK 0x02
-#define TYPE_D_QUERY_SWITCH_OK 0x03
-
-#define TYPE_A_SWITCH_BUSY 0x02
-#define TYPE_B_SWITCH_BUSY 0x01
-#define TYPE_C_SWITCH_BUSY 0x04
-#define TYPE_D_SWITCH_BUSY 0x08
-
-#define FUNCTION_GROUP3_SUPPORT_OFFSET 0x09
-#define FUNCTION_GROUP3_QUERY_SWITCH_OFFSET 0x0F
-#define FUNCTION_GROUP3_CHECK_BUSY_OFFSET 0x19
-
-#define CURRENT_LIMIT_200 0x00
-#define CURRENT_LIMIT_400 0x01
-#define CURRENT_LIMIT_600 0x02
-#define CURRENT_LIMIT_800 0x03
-
-#define CURRENT_LIMIT_200_MASK 0x01
-#define CURRENT_LIMIT_400_MASK 0x02
-#define CURRENT_LIMIT_600_MASK 0x04
-#define CURRENT_LIMIT_800_MASK 0x08
-
-#define CURRENT_LIMIT_200_QUERY_SWITCH_OK 0x00
-#define CURRENT_LIMIT_400_QUERY_SWITCH_OK 0x01
-#define CURRENT_LIMIT_600_QUERY_SWITCH_OK 0x02
-#define CURRENT_LIMIT_800_QUERY_SWITCH_OK 0x03
-
-#define CURRENT_LIMIT_200_SWITCH_BUSY 0x01
-#define CURRENT_LIMIT_400_SWITCH_BUSY 0x02
-#define CURRENT_LIMIT_600_SWITCH_BUSY 0x04
-#define CURRENT_LIMIT_800_SWITCH_BUSY 0x08
-
-#define FUNCTION_GROUP4_SUPPORT_OFFSET 0x07
-#define FUNCTION_GROUP4_QUERY_SWITCH_OFFSET 0x0F
-#define FUNCTION_GROUP4_CHECK_BUSY_OFFSET 0x17
-
-#define DATA_STRUCTURE_VER_OFFSET 0x11
-
-#define MAX_PHASE 31
-
-#define MMC_8BIT_BUS 0x0010
-#define MMC_4BIT_BUS 0x0020
-
-#define MMC_SWITCH_ERR 0x80
-
-#define SD_IO_3V3 0
-#define SD_IO_1V8 1
-
-#define TUNE_TX 0x00
-#define TUNE_RX 0x01
-
-#define CHANGE_TX 0x00
-#define CHANGE_RX 0x01
-
-#define DCM_HIGH_FREQUENCY_MODE 0x00
-#define DCM_LOW_FREQUENCY_MODE 0x01
-
-#define DCM_HIGH_FREQUENCY_MODE_SET 0x0C
-#define DCM_LOW_FREQUENCY_MODE_SET 0x00
-
-#define MULTIPLY_BY_1 0x00
-#define MULTIPLY_BY_2 0x01
-#define MULTIPLY_BY_3 0x02
-#define MULTIPLY_BY_4 0x03
-#define MULTIPLY_BY_5 0x04
-#define MULTIPLY_BY_6 0x05
-#define MULTIPLY_BY_7 0x06
-#define MULTIPLY_BY_8 0x07
-#define MULTIPLY_BY_9 0x08
-#define MULTIPLY_BY_10 0x09
-
-#define DIVIDE_BY_2 0x01
-#define DIVIDE_BY_3 0x02
-#define DIVIDE_BY_4 0x03
-#define DIVIDE_BY_5 0x04
-#define DIVIDE_BY_6 0x05
-#define DIVIDE_BY_7 0x06
-#define DIVIDE_BY_8 0x07
-#define DIVIDE_BY_9 0x08
-#define DIVIDE_BY_10 0x09
-
-struct timing_phase_path {
- int start;
- int end;
- int mid;
- int len;
-};
-
-int sd_select_card(struct rtsx_chip *chip, int select);
-int sd_pull_ctl_enable(struct rtsx_chip *chip);
-int reset_sd_card(struct rtsx_chip *chip);
-int sd_switch_clock(struct rtsx_chip *chip);
-void sd_stop_seq_mode(struct rtsx_chip *chip);
-int sd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt);
-void sd_cleanup_work(struct rtsx_chip *chip);
-int sd_power_off_card3v3(struct rtsx_chip *chip);
-int release_sd_card(struct rtsx_chip *chip);
-#ifdef SUPPORT_CPRM
-int ext_sd_send_cmd_get_rsp(struct rtsx_chip *chip, u8 cmd_idx,
- u32 arg, u8 rsp_type, u8 *rsp, int rsp_len,
- bool special_check);
-int ext_sd_get_rsp(struct rtsx_chip *chip, int len, u8 *rsp, u8 rsp_type);
-
-int sd_pass_thru_mode(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_execute_no_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_execute_read_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_execute_write_data(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_get_cmd_rsp(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int sd_hw_rst(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-#endif
-
-#endif /* __REALTEK_RTSX_SD_H */
diff --git a/drivers/staging/rts5208/spi.c b/drivers/staging/rts5208/spi.c
deleted file mode 100644
index e88fe1a998f8..000000000000
--- a/drivers/staging/rts5208/spi.c
+++ /dev/null
@@ -1,906 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-
-#include "rtsx.h"
-#include "spi.h"
-
-static inline void spi_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct spi_info *spi = &chip->spi;
-
- spi->err_code = err_code;
-}
-
-static int spi_init(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF,
- CS_POLARITY_LOW | DTO_MSB_FIRST
- | SPI_MASTER | SPI_MODE0 | SPI_AUTO);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SPI_TCTL, EDO_TIMING_MASK,
- SAMPLE_DELAY_HALF);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int spi_set_init_para(struct rtsx_chip *chip)
-{
- struct spi_info *spi = &chip->spi;
- int retval;
-
- retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF,
- (u8)(spi->clk_div >> 8));
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF,
- (u8)(spi->clk_div));
- if (retval)
- return retval;
-
- retval = switch_clock(chip, spi->spi_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = select_card(chip, SPI_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN,
- SPI_CLK_EN);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN,
- SPI_OUTPUT_EN);
- if (retval)
- return retval;
-
- wait_timeout(10);
-
- retval = spi_init(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int sf_polling_status(struct rtsx_chip *chip, int msec)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, SPI_RDSR);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_POLLING_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, msec);
- if (retval < 0) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_BUSY_ERR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sf_enable_write(struct rtsx_chip *chip, u8 ins)
-{
- struct spi_info *spi = &chip->spi;
- int retval;
-
- if (!spi->write_en)
- return STATUS_SUCCESS;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_C_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int sf_disable_write(struct rtsx_chip *chip, u8 ins)
-{
- struct spi_info *spi = &chip->spi;
- int retval;
-
- if (!spi->write_en)
- return STATUS_SUCCESS;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_C_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static void sf_program(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr,
- u16 len)
-{
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, (u8)len);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, (u8)(len >> 8));
- if (addr_mode) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,
- (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,
- (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CADO_MODE0);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CDO_MODE0);
- }
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-}
-
-static int sf_erase(struct rtsx_chip *chip, u8 ins, u8 addr_mode, u32 addr)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- if (addr_mode) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,
- (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,
- (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CA_MODE0);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_C_MODE0);
- }
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int spi_init_eeprom(struct rtsx_chip *chip)
-{
- int retval;
- int clk;
-
- if (chip->asic_code)
- clk = 30;
- else
- clk = CLK_30;
-
- retval = rtsx_write_register(chip, SPI_CLK_DIVIDER1, 0xFF, 0x00);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SPI_CLK_DIVIDER0, 0xFF, 0x27);
- if (retval)
- return retval;
-
- retval = switch_clock(chip, clk);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = select_card(chip, SPI_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_CLK_EN, SPI_CLK_EN,
- SPI_CLK_EN);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_OE, SPI_OUTPUT_EN,
- SPI_OUTPUT_EN);
- if (retval)
- return retval;
-
- wait_timeout(10);
-
- retval = rtsx_write_register(chip, SPI_CONTROL, 0xFF,
- CS_POLARITY_HIGH | SPI_EEPROM_AUTO);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, SPI_TCTL, EDO_TIMING_MASK,
- SAMPLE_DELAY_HALF);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-static int spi_eeprom_program_enable(struct rtsx_chip *chip)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x86);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x13);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CA_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-int spi_erase_eeprom_chip(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = spi_init_eeprom(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = spi_eeprom_program_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x12);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x84);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CA_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr)
-{
- int retval;
-
- retval = spi_init_eeprom(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = spi_eeprom_program_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x07);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CA_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val)
-{
- int retval;
- u8 data;
-
- retval = spi_init_eeprom(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x06);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x46);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CADI_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- wait_timeout(5);
- retval = rtsx_read_register(chip, SPI_DATA, &data);
- if (retval)
- return retval;
-
- if (val)
- *val = data;
-
- retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val)
-{
- int retval;
-
- retval = spi_init_eeprom(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = spi_eeprom_program_enable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_GPIO_DIR, 0x01, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, 0x05);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, val);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF, 0x4E);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CA_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_GPIO_DIR, 0x01, 0x01);
- if (retval)
- return retval;
-
- return STATUS_SUCCESS;
-}
-
-int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct spi_info *spi = &chip->spi;
-
- dev_dbg(rtsx_dev(chip), "%s: err_code = 0x%x\n", __func__,
- spi->err_code);
- rtsx_stor_set_xfer_buf(&spi->err_code,
- min_t(int, scsi_bufflen(srb), 1), srb);
- scsi_set_resid(srb, scsi_bufflen(srb) - 1);
-
- return STATUS_SUCCESS;
-}
-
-int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- struct spi_info *spi = &chip->spi;
-
- spi_set_err_code(chip, SPI_NO_ERR);
-
- if (chip->asic_code)
- spi->spi_clock = ((u16)(srb->cmnd[8]) << 8) | srb->cmnd[9];
- else
- spi->spi_clock = srb->cmnd[3];
-
- spi->clk_div = ((u16)(srb->cmnd[4]) << 8) | srb->cmnd[5];
- spi->write_en = srb->cmnd[6];
-
- dev_dbg(rtsx_dev(chip), "spi_clock = %d, clk_div = %d, write_en = %d\n",
- spi->spi_clock, spi->clk_div, spi->write_en);
-
- return STATUS_SUCCESS;
-}
-
-int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- u16 len;
- u8 *buf;
-
- spi_set_err_code(chip, SPI_NO_ERR);
-
- len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
- if (len > 512) {
- spi_set_err_code(chip, SPI_INVALID_COMMAND);
- return STATUS_FAIL;
- }
-
- retval = spi_set_init_para(chip);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, srb->cmnd[3]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF, srb->cmnd[4]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF, srb->cmnd[5]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF, srb->cmnd[6]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, srb->cmnd[7]);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, srb->cmnd[8]);
-
- if (len == 0) {
- if (srb->cmnd[9]) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
- 0xFF, SPI_TRANSFER0_START | SPI_CA_MODE0);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0,
- 0xFF, SPI_TRANSFER0_START | SPI_C_MODE0);
- }
- } else {
- if (srb->cmnd[9]) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CADI_MODE0);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CDI_MODE0);
- }
- }
-
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- if (len) {
- buf = kmalloc(len, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- retval = rtsx_read_ppbuf(chip, buf, len);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_READ_ERR);
- kfree(buf);
- return STATUS_FAIL;
- }
-
- rtsx_stor_set_xfer_buf(buf, scsi_bufflen(srb), srb);
- scsi_set_resid(srb, 0);
-
- kfree(buf);
- }
-
- return STATUS_SUCCESS;
-}
-
-int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- unsigned int index = 0, offset = 0;
- u8 ins, slow_read;
- u32 addr;
- u16 len;
- u8 *buf;
-
- spi_set_err_code(chip, SPI_NO_ERR);
-
- ins = srb->cmnd[3];
- addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5])
- << 8) | srb->cmnd[6];
- len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
- slow_read = srb->cmnd[9];
-
- retval = spi_set_init_para(chip);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- while (len) {
- u16 pagelen = SF_PAGE_LEN - (u8)addr;
-
- if (pagelen > len)
- pagelen = len;
-
- rtsx_init_cmd(chip);
-
- trans_dma_enable(DMA_FROM_DEVICE, chip, 256, DMA_256);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
-
- if (slow_read) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR0, 0xFF,
- (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,
- (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,
- (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR1, 0xFF,
- (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR2, 0xFF,
- (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_ADDR3, 0xFF,
- (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_32);
- }
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF,
- (u8)(pagelen >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF,
- (u8)pagelen);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CADI_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0,
- SPI_TRANSFER0_END, SPI_TRANSFER0_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0,
- DMA_FROM_DEVICE, 10000);
- if (retval < 0) {
- kfree(buf);
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index, &offset,
- TO_XFER_BUF);
-
- addr += pagelen;
- len -= pagelen;
- }
-
- scsi_set_resid(srb, 0);
- kfree(buf);
-
- return STATUS_SUCCESS;
-}
-
-int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- u8 ins, program_mode;
- u32 addr;
- u16 len;
- u8 *buf;
- unsigned int index = 0, offset = 0;
-
- spi_set_err_code(chip, SPI_NO_ERR);
-
- ins = srb->cmnd[3];
- addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5])
- << 8) | srb->cmnd[6];
- len = ((u16)(srb->cmnd[7]) << 8) | srb->cmnd[8];
- program_mode = srb->cmnd[9];
-
- retval = spi_set_init_para(chip);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- if (program_mode == BYTE_PROGRAM) {
- buf = kmalloc(4, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- while (len) {
- retval = sf_enable_write(chip, SPI_WREN);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset,
- FROM_XFER_BUF);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF,
- buf[0]);
- sf_program(chip, ins, 1, addr, 1);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- kfree(buf);
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- retval = sf_polling_status(chip, 100);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- addr++;
- len--;
- }
-
- kfree(buf);
-
- } else if (program_mode == AAI_PROGRAM) {
- int first_byte = 1;
-
- retval = sf_enable_write(chip, SPI_WREN);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- buf = kmalloc(4, GFP_KERNEL);
- if (!buf)
- return STATUS_ERROR;
-
- while (len) {
- rtsx_stor_access_xfer_buf(buf, 1, srb, &index, &offset,
- FROM_XFER_BUF);
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF,
- buf[0]);
- if (first_byte) {
- sf_program(chip, ins, 1, addr, 1);
- first_byte = 0;
- } else {
- sf_program(chip, ins, 0, 0, 1);
- }
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval < 0) {
- kfree(buf);
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- retval = sf_polling_status(chip, 100);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- len--;
- }
-
- kfree(buf);
-
- retval = sf_disable_write(chip, SPI_WRDI);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sf_polling_status(chip, 100);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else if (program_mode == PAGE_PROGRAM) {
- buf = kmalloc(SF_PAGE_LEN, GFP_KERNEL);
- if (!buf)
- return STATUS_NOMEM;
-
- while (len) {
- u16 pagelen = SF_PAGE_LEN - (u8)addr;
-
- if (pagelen > len)
- pagelen = len;
-
- retval = sf_enable_write(chip, SPI_WREN);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- trans_dma_enable(DMA_TO_DEVICE, chip, 256, DMA_256);
- sf_program(chip, ins, 1, addr, pagelen);
-
- rtsx_send_cmd_no_wait(chip);
-
- rtsx_stor_access_xfer_buf(buf, pagelen, srb, &index,
- &offset, FROM_XFER_BUF);
-
- retval = rtsx_transfer_data(chip, 0, buf, pagelen, 0,
- DMA_TO_DEVICE, 100);
- if (retval < 0) {
- kfree(buf);
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- retval = sf_polling_status(chip, 100);
- if (retval != STATUS_SUCCESS) {
- kfree(buf);
- return STATUS_FAIL;
- }
-
- addr += pagelen;
- len -= pagelen;
- }
-
- kfree(buf);
- } else {
- spi_set_err_code(chip, SPI_INVALID_COMMAND);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- u8 ins, erase_mode;
- u32 addr;
-
- spi_set_err_code(chip, SPI_NO_ERR);
-
- ins = srb->cmnd[3];
- addr = ((u32)(srb->cmnd[4]) << 16) | ((u32)(srb->cmnd[5])
- << 8) | srb->cmnd[6];
- erase_mode = srb->cmnd[9];
-
- retval = spi_set_init_para(chip);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- if (erase_mode == PAGE_ERASE) {
- retval = sf_enable_write(chip, SPI_WREN);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sf_erase(chip, ins, 1, addr);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else if (erase_mode == CHIP_ERASE) {
- retval = sf_enable_write(chip, SPI_WREN);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = sf_erase(chip, ins, 0, 0);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- spi_set_err_code(chip, SPI_INVALID_COMMAND);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip)
-{
- int retval;
- u8 ins, status, ewsr;
-
- ins = srb->cmnd[3];
- status = srb->cmnd[4];
- ewsr = srb->cmnd[5];
-
- retval = spi_set_init_para(chip);
- if (retval != STATUS_SUCCESS) {
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- retval = sf_enable_write(chip, ewsr);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_COMMAND, 0xFF, ins);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_CA_NUMBER, 0xFF,
- SPI_COMMAND_BIT_8 | SPI_ADDRESS_BIT_24);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH1, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_LENGTH0, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, PPBUF_BASE2, 0xFF, status);
- rtsx_add_cmd(chip, WRITE_REG_CMD, SPI_TRANSFER0, 0xFF,
- SPI_TRANSFER0_START | SPI_CDO_MODE0);
- rtsx_add_cmd(chip, CHECK_REG_CMD, SPI_TRANSFER0, SPI_TRANSFER0_END,
- SPI_TRANSFER0_END);
-
- retval = rtsx_send_cmd(chip, 0, 100);
- if (retval != STATUS_SUCCESS) {
- rtsx_clear_spi_error(chip);
- spi_set_err_code(chip, SPI_HW_ERR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts5208/spi.h b/drivers/staging/rts5208/spi.h
deleted file mode 100644
index dcf93c80b2d5..000000000000
--- a/drivers/staging/rts5208/spi.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_SPI_H
-#define __REALTEK_RTSX_SPI_H
-
-/* SPI operation error */
-#define SPI_NO_ERR 0x00
-#define SPI_HW_ERR 0x01
-#define SPI_INVALID_COMMAND 0x02
-#define SPI_READ_ERR 0x03
-#define SPI_WRITE_ERR 0x04
-#define SPI_ERASE_ERR 0x05
-#define SPI_BUSY_ERR 0x06
-
-/* Serial flash instruction */
-#define SPI_READ 0x03
-#define SPI_FAST_READ 0x0B
-#define SPI_WREN 0x06
-#define SPI_WRDI 0x04
-#define SPI_RDSR 0x05
-
-#define SF_PAGE_LEN 256
-
-#define BYTE_PROGRAM 0
-#define AAI_PROGRAM 1
-#define PAGE_PROGRAM 2
-
-#define PAGE_ERASE 0
-#define CHIP_ERASE 1
-
-int spi_erase_eeprom_chip(struct rtsx_chip *chip);
-int spi_erase_eeprom_byte(struct rtsx_chip *chip, u16 addr);
-int spi_read_eeprom(struct rtsx_chip *chip, u16 addr, u8 *val);
-int spi_write_eeprom(struct rtsx_chip *chip, u16 addr, u8 val);
-int spi_get_status(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_set_parameter(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_read_flash_id(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_read_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_write_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_erase_flash(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-int spi_write_flash_status(struct scsi_cmnd *srb, struct rtsx_chip *chip);
-
-#endif /* __REALTEK_RTSX_SPI_H */
diff --git a/drivers/staging/rts5208/xd.c b/drivers/staging/rts5208/xd.c
deleted file mode 100644
index c0af378ada71..000000000000
--- a/drivers/staging/rts5208/xd.c
+++ /dev/null
@@ -1,2145 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#include <linux/blkdev.h>
-#include <linux/kthread.h>
-#include <linux/sched.h>
-#include <linux/vmalloc.h>
-
-#include "rtsx.h"
-#include "rtsx_transport.h"
-#include "rtsx_scsi.h"
-#include "rtsx_card.h"
-#include "xd.h"
-
-static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no);
-static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk, u16 logoff,
- u8 start_page, u8 end_page);
-
-static inline void xd_set_err_code(struct rtsx_chip *chip, u8 err_code)
-{
- struct xd_info *xd_card = &chip->xd_card;
-
- xd_card->err_code = err_code;
-}
-
-static int xd_set_init_para(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
-
- if (chip->asic_code)
- xd_card->xd_clock = 47;
- else
- xd_card->xd_clock = CLK_50;
-
- retval = switch_clock(chip, xd_card->xd_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int xd_switch_clock(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
-
- retval = select_card(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = switch_clock(chip, xd_card->xd_clock);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int xd_read_id(struct rtsx_chip *chip, u8 id_cmd, u8 *id_buf, u8 buf_len)
-{
- int retval, i;
- u8 *ptr;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, id_cmd);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_READ_ID);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
- XD_TRANSFER_END);
-
- for (i = 0; i < 4; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_ADDRESS1 + i), 0, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 20);
- if (retval < 0)
- return STATUS_FAIL;
-
- ptr = rtsx_get_cmd_data(chip) + 1;
- if (id_buf && buf_len) {
- if (buf_len > 4)
- buf_len = 4;
- memcpy(id_buf, ptr, buf_len);
- }
-
- return STATUS_SUCCESS;
-}
-
-static void xd_assign_phy_addr(struct rtsx_chip *chip, u32 addr, u8 mode)
-{
- struct xd_info *xd_card = &chip->xd_card;
-
- switch (mode) {
- case XD_RW_ADDR:
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2,
- 0xFF, (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS3,
- 0xFF, (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF,
- xd_card->addr_cycle |
- XD_CALC_ECC |
- XD_BA_NO_TRANSFORM);
- break;
-
- case XD_ERASE_ADDR:
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS0, 0xFF, (u8)addr);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS1,
- 0xFF, (u8)(addr >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_ADDRESS2,
- 0xFF, (u8)(addr >> 16));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, 0xFF,
- (xd_card->addr_cycle - 1) | XD_CALC_ECC |
- XD_BA_NO_TRANSFORM);
- break;
-
- default:
- break;
- }
-}
-
-static int xd_read_redundant(struct rtsx_chip *chip, u32 page_addr,
- u8 *buf, int buf_len)
-{
- int retval, i;
-
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER,
- 0xFF, XD_TRANSFER_START | XD_READ_REDUNDANT);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- for (i = 0; i < 6; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_PAGE_STATUS + i),
- 0, 0);
- for (i = 0; i < 4; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, (u16)(XD_RESERVED0 + i),
- 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, XD_PARITY, 0, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 500);
- if (retval < 0)
- return STATUS_FAIL;
-
- if (buf && buf_len) {
- u8 *ptr = rtsx_get_cmd_data(chip) + 1;
-
- if (buf_len > 11)
- buf_len = 11;
- memcpy(buf, ptr, buf_len);
- }
-
- return STATUS_SUCCESS;
-}
-
-static int xd_read_data_from_ppb(struct rtsx_chip *chip, int offset,
- u8 *buf, int buf_len)
-{
- int retval, i;
-
- if (!buf || buf_len < 0)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- for (i = 0; i < buf_len; i++)
- rtsx_add_cmd(chip, READ_REG_CMD, PPBUF_BASE2 + offset + i,
- 0, 0);
-
- retval = rtsx_send_cmd(chip, 0, 250);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- return STATUS_FAIL;
- }
-
- memcpy(buf, rtsx_get_cmd_data(chip), buf_len);
-
- return STATUS_SUCCESS;
-}
-
-static int xd_read_cis(struct rtsx_chip *chip, u32 page_addr, u8 *buf,
- int buf_len)
-{
- int retval;
- u8 reg;
-
- if (!buf || buf_len < 10)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE,
- 0x01, PINGPONG_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
- XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_READ_PAGES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER, XD_TRANSFER_END,
- XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 250);
- if (retval == -ETIMEDOUT) {
- rtsx_clear_xd_error(chip);
- return STATUS_FAIL;
- }
-
- retval = rtsx_read_register(chip, XD_PAGE_STATUS, &reg);
- if (retval)
- return retval;
- if (reg != XD_GPG) {
- rtsx_clear_xd_error(chip);
- return STATUS_FAIL;
- }
-
- retval = rtsx_read_register(chip, XD_CTL, &reg);
- if (retval)
- return retval;
- if (!(reg & XD_ECC1_ERROR) || !(reg & XD_ECC1_UNCORRECTABLE)) {
- retval = xd_read_data_from_ppb(chip, 0, buf, buf_len);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- if (reg & XD_ECC1_ERROR) {
- u8 ecc_bit, ecc_byte;
-
- retval = rtsx_read_register(chip, XD_ECC_BIT1,
- &ecc_bit);
- if (retval)
- return retval;
- retval = rtsx_read_register(chip, XD_ECC_BYTE1,
- &ecc_byte);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "ECC_BIT1 = 0x%x, ECC_BYTE1 = 0x%x\n",
- ecc_bit, ecc_byte);
- if (ecc_byte < buf_len) {
- dev_dbg(rtsx_dev(chip), "Before correct: 0x%x\n",
- buf[ecc_byte]);
- buf[ecc_byte] ^= (1 << ecc_bit);
- dev_dbg(rtsx_dev(chip), "After correct: 0x%x\n",
- buf[ecc_byte]);
- }
- }
- } else if (!(reg & XD_ECC2_ERROR) || !(reg & XD_ECC2_UNCORRECTABLE)) {
- rtsx_clear_xd_error(chip);
-
- retval = xd_read_data_from_ppb(chip, 256, buf, buf_len);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- if (reg & XD_ECC2_ERROR) {
- u8 ecc_bit, ecc_byte;
-
- retval = rtsx_read_register(chip, XD_ECC_BIT2,
- &ecc_bit);
- if (retval)
- return retval;
- retval = rtsx_read_register(chip, XD_ECC_BYTE2,
- &ecc_byte);
- if (retval)
- return retval;
-
- dev_dbg(rtsx_dev(chip), "ECC_BIT2 = 0x%x, ECC_BYTE2 = 0x%x\n",
- ecc_bit, ecc_byte);
- if (ecc_byte < buf_len) {
- dev_dbg(rtsx_dev(chip), "Before correct: 0x%x\n",
- buf[ecc_byte]);
- buf[ecc_byte] ^= (1 << ecc_bit);
- dev_dbg(rtsx_dev(chip), "After correct: 0x%x\n",
- buf[ecc_byte]);
- }
- }
- } else {
- rtsx_clear_xd_error(chip);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static void xd_fill_pull_ctl_disable(struct rtsx_chip *chip)
-{
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
- XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
- XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
- XD_WP_PD | XD_CE_PD | XD_CLE_PD | XD_CD_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD | XD_WE_PD | XD_RE_PD | XD_ALE_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1,
- 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2,
- 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3,
- 0xFF, 0x4B);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4,
- 0xFF, 0x69);
- }
- }
-}
-
-static void xd_fill_pull_ctl_stage1_barossa(struct rtsx_chip *chip)
-{
- if (CHECK_BARO_PKG(chip, QFN)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF, 0x4B);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF, 0x55);
- }
-}
-
-static void xd_fill_pull_ctl_enable(struct rtsx_chip *chip)
-{
- if (CHECK_PID(chip, 0x5208)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1, 0xFF,
- XD_D3_PD | XD_D2_PD | XD_D1_PD | XD_D0_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2, 0xFF,
- XD_D7_PD | XD_D6_PD | XD_D5_PD | XD_D4_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3, 0xFF,
- XD_WP_PD | XD_CE_PU | XD_CLE_PD | XD_CD_PU);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PU | XD_WE_PU | XD_RE_PU | XD_ALE_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU | SD_WP_PD | SD_CD_PU | SD_CMD_PD);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL1,
- 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL2,
- 0xFF, 0x55);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL3,
- 0xFF, 0x53);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_PULL_CTL4,
- 0xFF, 0xA9);
- }
- }
-}
-
-static int xd_pull_ctl_disable(struct rtsx_chip *chip)
-{
- int retval;
-
- if (CHECK_PID(chip, 0x5208)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1, 0xFF,
- XD_D3_PD |
- XD_D2_PD |
- XD_D1_PD |
- XD_D0_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL2, 0xFF,
- XD_D7_PD |
- XD_D6_PD |
- XD_D5_PD |
- XD_D4_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL3, 0xFF,
- XD_WP_PD |
- XD_CE_PD |
- XD_CLE_PD |
- XD_CD_PU);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL4, 0xFF,
- XD_RDY_PD |
- XD_WE_PD |
- XD_RE_PD |
- XD_ALE_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL5, 0xFF,
- MS_INS_PU |
- SD_WP_PD |
- SD_CD_PU |
- SD_CMD_PD);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL6, 0xFF,
- MS_D5_PD | MS_D4_PD);
- if (retval)
- return retval;
- } else if (CHECK_PID(chip, 0x5288)) {
- if (CHECK_BARO_PKG(chip, QFN)) {
- retval = rtsx_write_register(chip, CARD_PULL_CTL1,
- 0xFF, 0x55);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL2,
- 0xFF, 0x55);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL3,
- 0xFF, 0x4B);
- if (retval)
- return retval;
- retval = rtsx_write_register(chip, CARD_PULL_CTL4,
- 0xFF, 0x69);
- if (retval)
- return retval;
- }
- }
-
- return STATUS_SUCCESS;
-}
-
-static int reset_xd(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval, i, j;
- u8 *ptr, id_buf[4], redunt[11];
-
- retval = select_card(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS, 0xFF,
- XD_PGSTS_NOT_FF);
- if (chip->asic_code) {
- if (!CHECK_PID(chip, 0x5288))
- xd_fill_pull_ctl_disable(chip);
- else
- xd_fill_pull_ctl_stage1_barossa(chip);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
- (FPGA_XD_PULL_CTL_EN1 & FPGA_XD_PULL_CTL_EN3) |
- 0x20);
- }
-
- if (!chip->ft2_fast_mode)
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_INIT,
- XD_NO_AUTO_PWR_OFF, 0);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_off(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- wait_timeout(250);
-
- rtsx_init_cmd(chip);
-
- if (chip->asic_code) {
- xd_fill_pull_ctl_enable(chip);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
- (FPGA_XD_PULL_CTL_EN1 &
- FPGA_XD_PULL_CTL_EN2) |
- 0x20);
- }
-
- retval = rtsx_send_cmd(chip, XD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- retval = card_power_on(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
-#ifdef SUPPORT_OCP
- wait_timeout(50);
- if (chip->ocp_stat & (SD_OC_NOW | SD_OC_EVER)) {
- dev_dbg(rtsx_dev(chip), "Over current, OCPSTAT is 0x%x\n",
- chip->ocp_stat);
- return STATUS_FAIL;
- }
-#endif
- }
-
- rtsx_init_cmd(chip);
-
- if (chip->ft2_fast_mode) {
- if (chip->asic_code) {
- xd_fill_pull_ctl_enable(chip);
- } else {
- rtsx_add_cmd(chip, WRITE_REG_CMD, FPGA_PULL_CTL, 0xFF,
- (FPGA_XD_PULL_CTL_EN1 &
- FPGA_XD_PULL_CTL_EN2) |
- 0x20);
- }
- }
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_OE, XD_OUTPUT_EN, XD_OUTPUT_EN);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CTL, XD_CE_DISEN, XD_CE_DISEN);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- if (!chip->ft2_fast_mode)
- wait_timeout(200);
-
- retval = xd_set_init_para(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- /* Read ID to check if the timing setting is right */
- for (i = 0; i < 4; i++) {
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DTCTL, 0xFF,
- XD_TIME_SETUP_STEP * 3 +
- XD_TIME_RW_STEP * (2 + i) + XD_TIME_RWN_STEP * i);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CATCTL, 0xFF,
- XD_TIME_SETUP_STEP * 3 +
- XD_TIME_RW_STEP * (4 + i) +
- XD_TIME_RWN_STEP * (3 + i));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_RESET);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- ptr = rtsx_get_cmd_data(chip) + 1;
-
- dev_dbg(rtsx_dev(chip), "XD_DAT: 0x%x, XD_CTL: 0x%x\n",
- ptr[0], ptr[1]);
-
- if (((ptr[0] & READY_FLAG) != READY_STATE) ||
- !(ptr[1] & XD_RDY))
- continue;
-
- retval = xd_read_id(chip, READ_ID, id_buf, 4);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- dev_dbg(rtsx_dev(chip), "READ_ID: 0x%x 0x%x 0x%x 0x%x\n",
- id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
-
- xd_card->device_code = id_buf[1];
-
- /* Check if the xD card is supported */
- switch (xd_card->device_code) {
- case XD_4M_X8_512_1:
- case XD_4M_X8_512_2:
- xd_card->block_shift = 4;
- xd_card->page_off = 0x0F;
- xd_card->addr_cycle = 3;
- xd_card->zone_cnt = 1;
- xd_card->capacity = 8000;
- XD_SET_4MB(xd_card);
- break;
- case XD_8M_X8_512:
- xd_card->block_shift = 4;
- xd_card->page_off = 0x0F;
- xd_card->addr_cycle = 3;
- xd_card->zone_cnt = 1;
- xd_card->capacity = 16000;
- break;
- case XD_16M_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 3;
- xd_card->zone_cnt = 1;
- xd_card->capacity = 32000;
- break;
- case XD_32M_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 3;
- xd_card->zone_cnt = 2;
- xd_card->capacity = 64000;
- break;
- case XD_64M_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 4;
- xd_card->capacity = 128000;
- break;
- case XD_128M_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 8;
- xd_card->capacity = 256000;
- break;
- case XD_256M_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 16;
- xd_card->capacity = 512000;
- break;
- case XD_512M_X8:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 32;
- xd_card->capacity = 1024000;
- break;
- case XD_1G_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 64;
- xd_card->capacity = 2048000;
- break;
- case XD_2G_X8_512:
- XD_PAGE_512(xd_card);
- xd_card->addr_cycle = 4;
- xd_card->zone_cnt = 128;
- xd_card->capacity = 4096000;
- break;
- default:
- continue;
- }
-
- /* Confirm timing setting */
- for (j = 0; j < 10; j++) {
- retval = xd_read_id(chip, READ_ID, id_buf, 4);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (id_buf[1] != xd_card->device_code)
- break;
- }
-
- if (j == 10)
- break;
- }
-
- if (i == 4) {
- xd_card->block_shift = 0;
- xd_card->page_off = 0;
- xd_card->addr_cycle = 0;
- xd_card->capacity = 0;
-
- return STATUS_FAIL;
- }
-
- retval = xd_read_id(chip, READ_XD_ID, id_buf, 4);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- dev_dbg(rtsx_dev(chip), "READ_XD_ID: 0x%x 0x%x 0x%x 0x%x\n",
- id_buf[0], id_buf[1], id_buf[2], id_buf[3]);
- if (id_buf[2] != XD_ID_CODE)
- return STATUS_FAIL;
-
- /* Search CIS block */
- for (i = 0; i < 24; i++) {
- u32 page_addr;
-
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- page_addr = (u32)i << xd_card->block_shift;
-
- for (j = 0; j < 3; j++) {
- retval = xd_read_redundant(chip, page_addr, redunt, 11);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (j == 3)
- continue;
-
- if (redunt[BLOCK_STATUS] != XD_GBLK)
- continue;
-
- j = 0;
- if (redunt[PAGE_STATUS] != XD_GPG) {
- for (j = 1; j <= 8; j++) {
- retval = xd_read_redundant(chip, page_addr + j,
- redunt, 11);
- if (retval == STATUS_SUCCESS) {
- if (redunt[PAGE_STATUS] == XD_GPG)
- break;
- }
- }
-
- if (j == 9)
- break;
- }
-
- /* Check CIS data */
- if (redunt[BLOCK_STATUS] == XD_GBLK &&
- (redunt[PARITY] & XD_BA1_ALL0)) {
- u8 buf[10];
-
- page_addr += j;
-
- retval = xd_read_cis(chip, page_addr, buf, 10);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (buf[0] == 0x01 && buf[1] == 0x03 &&
- buf[2] == 0xD9 &&
- buf[3] == 0x01 && buf[4] == 0xFF &&
- buf[5] == 0x18 && buf[6] == 0x02 &&
- buf[7] == 0xDF && buf[8] == 0x01 &&
- buf[9] == 0x20) {
- xd_card->cis_block = (u16)i;
- }
- }
-
- break;
- }
-
- dev_dbg(rtsx_dev(chip), "CIS block: 0x%x\n", xd_card->cis_block);
- if (xd_card->cis_block == 0xFFFF)
- return STATUS_FAIL;
-
- chip->capacity[chip->card2lun[XD_CARD]] = xd_card->capacity;
-
- return STATUS_SUCCESS;
-}
-
-static int xd_check_data_blank(u8 *redunt)
-{
- int i;
-
- for (i = 0; i < 6; i++) {
- if (redunt[PAGE_STATUS + i] != 0xFF)
- return 0;
- }
-
- if ((redunt[PARITY] & (XD_ECC1_ALL1 | XD_ECC2_ALL1))
- != (XD_ECC1_ALL1 | XD_ECC2_ALL1))
- return 0;
-
- for (i = 0; i < 4; i++) {
- if (redunt[RESERVED0 + i] != 0xFF)
- return 0;
- }
-
- return 1;
-}
-
-static u16 xd_load_log_block_addr(u8 *redunt)
-{
- u16 addr = 0xFFFF;
-
- if (redunt[PARITY] & XD_BA1_BA2_EQL)
- addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) |
- redunt[BLOCK_ADDR1_L];
- else if (redunt[PARITY] & XD_BA1_VALID)
- addr = ((u16)redunt[BLOCK_ADDR1_H] << 8) |
- redunt[BLOCK_ADDR1_L];
- else if (redunt[PARITY] & XD_BA2_VALID)
- addr = ((u16)redunt[BLOCK_ADDR2_H] << 8) |
- redunt[BLOCK_ADDR2_L];
-
- return addr;
-}
-
-static int xd_init_l2p_tbl(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int size, i;
-
- dev_dbg(rtsx_dev(chip), "%s: zone_cnt = %d\n", __func__,
- xd_card->zone_cnt);
-
- if (xd_card->zone_cnt < 1)
- return STATUS_FAIL;
-
- size = xd_card->zone_cnt * sizeof(struct zone_entry);
- dev_dbg(rtsx_dev(chip), "Buffer size for l2p table is %d\n", size);
-
- xd_card->zone = vmalloc(size);
- if (!xd_card->zone)
- return STATUS_ERROR;
-
- for (i = 0; i < xd_card->zone_cnt; i++) {
- xd_card->zone[i].build_flag = 0;
- xd_card->zone[i].l2p_table = NULL;
- xd_card->zone[i].free_table = NULL;
- xd_card->zone[i].get_index = 0;
- xd_card->zone[i].set_index = 0;
- xd_card->zone[i].unused_blk_cnt = 0;
- }
-
- return STATUS_SUCCESS;
-}
-
-static inline void free_zone(struct zone_entry *zone)
-{
- if (!zone)
- return;
-
- zone->build_flag = 0;
- zone->set_index = 0;
- zone->get_index = 0;
- zone->unused_blk_cnt = 0;
- vfree(zone->l2p_table);
- zone->l2p_table = NULL;
- vfree(zone->free_table);
- zone->free_table = NULL;
-}
-
-static void xd_set_unused_block(struct rtsx_chip *chip, u32 phy_blk)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct zone_entry *zone;
- int zone_no;
-
- zone_no = (int)phy_blk >> 10;
- if (zone_no >= xd_card->zone_cnt) {
- dev_dbg(rtsx_dev(chip), "Set unused block to invalid zone (zone_no = %d, zone_cnt = %d)\n",
- zone_no, xd_card->zone_cnt);
- return;
- }
- zone = &xd_card->zone[zone_no];
-
- if (!zone->free_table) {
- if (xd_build_l2p_tbl(chip, zone_no) != STATUS_SUCCESS)
- return;
- }
-
- if (zone->set_index >= XD_FREE_TABLE_CNT ||
- zone->set_index < 0) {
- free_zone(zone);
- dev_dbg(rtsx_dev(chip), "Set unused block fail, invalid set_index\n");
- return;
- }
-
- dev_dbg(rtsx_dev(chip), "Set unused block to index %d\n",
- zone->set_index);
-
- zone->free_table[zone->set_index++] = (u16)(phy_blk & 0x3ff);
- if (zone->set_index >= XD_FREE_TABLE_CNT)
- zone->set_index = 0;
- zone->unused_blk_cnt++;
-}
-
-static u32 xd_get_unused_block(struct rtsx_chip *chip, int zone_no)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct zone_entry *zone;
- u32 phy_blk;
-
- if (zone_no >= xd_card->zone_cnt) {
- dev_dbg(rtsx_dev(chip), "Get unused block from invalid zone (zone_no = %d, zone_cnt = %d)\n",
- zone_no, xd_card->zone_cnt);
- return BLK_NOT_FOUND;
- }
- zone = &xd_card->zone[zone_no];
-
- if (zone->unused_blk_cnt == 0 ||
- zone->set_index == zone->get_index) {
- free_zone(zone);
- dev_dbg(rtsx_dev(chip), "Get unused block fail, no unused block available\n");
- return BLK_NOT_FOUND;
- }
- if (zone->get_index >= XD_FREE_TABLE_CNT || zone->get_index < 0) {
- free_zone(zone);
- dev_dbg(rtsx_dev(chip), "Get unused block fail, invalid get_index\n");
- return BLK_NOT_FOUND;
- }
-
- dev_dbg(rtsx_dev(chip), "Get unused block from index %d\n",
- zone->get_index);
-
- phy_blk = zone->free_table[zone->get_index];
- zone->free_table[zone->get_index++] = 0xFFFF;
- if (zone->get_index >= XD_FREE_TABLE_CNT)
- zone->get_index = 0;
- zone->unused_blk_cnt--;
-
- phy_blk += ((u32)(zone_no) << 10);
- return phy_blk;
-}
-
-static void xd_set_l2p_tbl(struct rtsx_chip *chip,
- int zone_no, u16 log_off, u16 phy_off)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct zone_entry *zone;
-
- zone = &xd_card->zone[zone_no];
- zone->l2p_table[log_off] = phy_off;
-}
-
-static u32 xd_get_l2p_tbl(struct rtsx_chip *chip, int zone_no, u16 log_off)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct zone_entry *zone;
- int retval;
-
- zone = &xd_card->zone[zone_no];
- if (zone->l2p_table[log_off] == 0xFFFF) {
- u32 phy_blk = 0;
- int i;
-
-#ifdef XD_DELAY_WRITE
- retval = xd_delay_write(chip);
- if (retval != STATUS_SUCCESS) {
- dev_dbg(rtsx_dev(chip), "In %s, delay write fail!\n",
- __func__);
- return BLK_NOT_FOUND;
- }
-#endif
-
- if (zone->unused_blk_cnt <= 0) {
- dev_dbg(rtsx_dev(chip), "No unused block!\n");
- return BLK_NOT_FOUND;
- }
-
- for (i = 0; i < zone->unused_blk_cnt; i++) {
- phy_blk = xd_get_unused_block(chip, zone_no);
- if (phy_blk == BLK_NOT_FOUND) {
- dev_dbg(rtsx_dev(chip), "No unused block available!\n");
- return BLK_NOT_FOUND;
- }
-
- retval = xd_init_page(chip, phy_blk, log_off,
- 0, xd_card->page_off + 1);
- if (retval == STATUS_SUCCESS)
- break;
- }
- if (i >= zone->unused_blk_cnt) {
- dev_dbg(rtsx_dev(chip), "No good unused block available!\n");
- return BLK_NOT_FOUND;
- }
-
- xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(phy_blk & 0x3FF));
- return phy_blk;
- }
-
- return (u32)zone->l2p_table[log_off] + ((u32)(zone_no) << 10);
-}
-
-int reset_xd_card(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
-
- memset(xd_card, 0, sizeof(struct xd_info));
-
- xd_card->block_shift = 0;
- xd_card->page_off = 0;
- xd_card->addr_cycle = 0;
- xd_card->capacity = 0;
- xd_card->zone_cnt = 0;
- xd_card->cis_block = 0xFFFF;
- xd_card->delay_write.delay_write_flag = 0;
-
- retval = enable_card_clock(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = reset_xd(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = xd_init_l2p_tbl(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int xd_mark_bad_block(struct rtsx_chip *chip, u32 phy_blk)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
- u32 page_addr;
- u8 reg = 0;
-
- dev_dbg(rtsx_dev(chip), "mark block 0x%x as bad block\n", phy_blk);
-
- if (phy_blk == BLK_NOT_FOUND)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_LATER_BBLK);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_H, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR2_L, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED0, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED1, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED2, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_RESERVED3, 0xFF, 0xFF);
-
- page_addr = phy_blk << xd_card->block_shift;
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF,
- xd_card->page_off + 1);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_WRITE_REDUNDANT);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 500);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- rtsx_read_register(chip, XD_DAT, &reg);
- if (reg & PROGRAM_ERROR)
- xd_set_err_code(chip, XD_PRG_ERROR);
- else
- xd_set_err_code(chip, XD_TO_ERROR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int xd_init_page(struct rtsx_chip *chip, u32 phy_blk,
- u16 logoff, u8 start_page, u8 end_page)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
- u32 page_addr;
- u8 reg = 0;
-
- dev_dbg(rtsx_dev(chip), "Init block 0x%x\n", phy_blk);
-
- if (start_page > end_page)
- return STATUS_FAIL;
- if (phy_blk == BLK_NOT_FOUND)
- return STATUS_FAIL;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, 0xFF);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H,
- 0xFF, (u8)(logoff >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)logoff);
-
- page_addr = (phy_blk << xd_card->block_shift) + start_page;
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG,
- XD_BA_TRANSFORM, XD_BA_TRANSFORM);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT,
- 0xFF, (end_page - start_page));
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER,
- 0xFF, XD_TRANSFER_START | XD_WRITE_REDUNDANT);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 500);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- rtsx_read_register(chip, XD_DAT, &reg);
- if (reg & PROGRAM_ERROR) {
- xd_mark_bad_block(chip, phy_blk);
- xd_set_err_code(chip, XD_PRG_ERROR);
- } else {
- xd_set_err_code(chip, XD_TO_ERROR);
- }
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int xd_copy_page(struct rtsx_chip *chip, u32 old_blk, u32 new_blk,
- u8 start_page, u8 end_page)
-{
- struct xd_info *xd_card = &chip->xd_card;
- u32 old_page, new_page;
- u8 i, reg = 0;
- int retval;
-
- dev_dbg(rtsx_dev(chip), "Copy page from block 0x%x to block 0x%x\n",
- old_blk, new_blk);
-
- if (start_page > end_page)
- return STATUS_FAIL;
-
- if (old_blk == BLK_NOT_FOUND || new_blk == BLK_NOT_FOUND)
- return STATUS_FAIL;
-
- old_page = (old_blk << xd_card->block_shift) + start_page;
- new_page = (new_blk << xd_card->block_shift) + start_page;
-
- XD_CLR_BAD_NEWBLK(xd_card);
-
- retval = rtsx_write_register(chip, CARD_DATA_SOURCE, 0x01,
- PINGPONG_BUFFER);
- if (retval)
- return retval;
-
- for (i = start_page; i < end_page; i++) {
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- rtsx_clear_xd_error(chip);
- xd_set_err_code(chip, XD_NO_CARD);
- return STATUS_FAIL;
- }
-
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, old_page, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
- XD_AUTO_CHK_DATA_STATUS, 0);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_READ_PAGES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 500);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- reg = 0;
- rtsx_read_register(chip, XD_CTL, &reg);
- if (reg & (XD_ECC1_ERROR | XD_ECC2_ERROR)) {
- mdelay(100);
-
- if (detect_card_cd(chip,
- XD_CARD) != STATUS_SUCCESS) {
- xd_set_err_code(chip, XD_NO_CARD);
- return STATUS_FAIL;
- }
-
- if (((reg & XD_ECC1_ERROR) &&
- (reg & XD_ECC1_UNCORRECTABLE)) ||
- ((reg & XD_ECC2_ERROR) &&
- (reg & XD_ECC2_UNCORRECTABLE))) {
- rtsx_write_register(chip,
- XD_PAGE_STATUS,
- 0xFF,
- XD_BPG);
- rtsx_write_register(chip,
- XD_BLOCK_STATUS,
- 0xFF,
- XD_GBLK);
- XD_SET_BAD_OLDBLK(xd_card);
- dev_dbg(rtsx_dev(chip), "old block 0x%x ecc error\n",
- old_blk);
- }
- } else {
- xd_set_err_code(chip, XD_TO_ERROR);
- return STATUS_FAIL;
- }
- }
-
- if (XD_CHK_BAD_OLDBLK(xd_card))
- rtsx_clear_xd_error(chip);
-
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, new_page, XD_RW_ADDR);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, 1);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_WRITE_PAGES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 300);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- reg = 0;
- rtsx_read_register(chip, XD_DAT, &reg);
- if (reg & PROGRAM_ERROR) {
- xd_mark_bad_block(chip, new_blk);
- xd_set_err_code(chip, XD_PRG_ERROR);
- XD_SET_BAD_NEWBLK(xd_card);
- } else {
- xd_set_err_code(chip, XD_TO_ERROR);
- }
- return STATUS_FAIL;
- }
-
- old_page++;
- new_page++;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int xd_reset_cmd(struct rtsx_chip *chip)
-{
- int retval;
- u8 *ptr;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER,
- 0xFF, XD_TRANSFER_START | XD_RESET);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
- rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
- rtsx_add_cmd(chip, READ_REG_CMD, XD_CTL, 0, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 100);
- if (retval < 0)
- return STATUS_FAIL;
-
- ptr = rtsx_get_cmd_data(chip) + 1;
- if (((ptr[0] & READY_FLAG) == READY_STATE) && (ptr[1] & XD_RDY))
- return STATUS_SUCCESS;
-
- return STATUS_FAIL;
-}
-
-static int xd_erase_block(struct rtsx_chip *chip, u32 phy_blk)
-{
- struct xd_info *xd_card = &chip->xd_card;
- u32 page_addr;
- u8 reg = 0, *ptr;
- int i, retval;
-
- if (phy_blk == BLK_NOT_FOUND)
- return STATUS_FAIL;
-
- page_addr = phy_blk << xd_card->block_shift;
-
- for (i = 0; i < 3; i++) {
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, page_addr, XD_ERASE_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_ERASE);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
- rtsx_add_cmd(chip, READ_REG_CMD, XD_DAT, 0, 0);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 250);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
- rtsx_read_register(chip, XD_DAT, &reg);
- if (reg & PROGRAM_ERROR) {
- xd_mark_bad_block(chip, phy_blk);
- xd_set_err_code(chip, XD_PRG_ERROR);
- return STATUS_FAIL;
- }
- xd_set_err_code(chip, XD_ERASE_FAIL);
- retval = xd_reset_cmd(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- continue;
- }
-
- ptr = rtsx_get_cmd_data(chip) + 1;
- if (*ptr & PROGRAM_ERROR) {
- xd_mark_bad_block(chip, phy_blk);
- xd_set_err_code(chip, XD_PRG_ERROR);
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
- }
-
- xd_mark_bad_block(chip, phy_blk);
- xd_set_err_code(chip, XD_ERASE_FAIL);
- return STATUS_FAIL;
-}
-
-static int xd_build_l2p_tbl(struct rtsx_chip *chip, int zone_no)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct zone_entry *zone;
- int retval;
- u32 start, end, i;
- u16 max_logoff, cur_fst_page_logoff;
- u16 cur_lst_page_logoff, ent_lst_page_logoff;
- u8 redunt[11];
-
- dev_dbg(rtsx_dev(chip), "%s: %d\n", __func__, zone_no);
-
- if (!xd_card->zone) {
- retval = xd_init_l2p_tbl(chip);
- if (retval != STATUS_SUCCESS)
- return retval;
- }
-
- if (xd_card->zone[zone_no].build_flag) {
- dev_dbg(rtsx_dev(chip), "l2p table of zone %d has been built\n",
- zone_no);
- return STATUS_SUCCESS;
- }
-
- zone = &xd_card->zone[zone_no];
-
- if (!zone->l2p_table) {
- zone->l2p_table = vmalloc(2000);
- if (!zone->l2p_table)
- goto build_fail;
- }
- memset((u8 *)(zone->l2p_table), 0xff, 2000);
-
- if (!zone->free_table) {
- zone->free_table = vmalloc(XD_FREE_TABLE_CNT * 2);
- if (!zone->free_table)
- goto build_fail;
- }
- memset((u8 *)(zone->free_table), 0xff, XD_FREE_TABLE_CNT * 2);
-
- if (zone_no == 0) {
- if (xd_card->cis_block == 0xFFFF)
- start = 0;
- else
- start = xd_card->cis_block + 1;
- if (XD_CHK_4MB(xd_card)) {
- end = 0x200;
- max_logoff = 499;
- } else {
- end = 0x400;
- max_logoff = 999;
- }
- } else {
- start = (u32)(zone_no) << 10;
- end = (u32)(zone_no + 1) << 10;
- max_logoff = 999;
- }
-
- dev_dbg(rtsx_dev(chip), "start block 0x%x, end block 0x%x\n",
- start, end);
-
- zone->set_index = 0;
- zone->get_index = 0;
- zone->unused_blk_cnt = 0;
-
- for (i = start; i < end; i++) {
- u32 page_addr = i << xd_card->block_shift;
- u32 phy_block;
-
- retval = xd_read_redundant(chip, page_addr, redunt, 11);
- if (retval != STATUS_SUCCESS)
- continue;
-
- if (redunt[BLOCK_STATUS] != 0xFF) {
- dev_dbg(rtsx_dev(chip), "bad block\n");
- continue;
- }
-
- if (xd_check_data_blank(redunt)) {
- dev_dbg(rtsx_dev(chip), "blank block\n");
- xd_set_unused_block(chip, i);
- continue;
- }
-
- cur_fst_page_logoff = xd_load_log_block_addr(redunt);
- if (cur_fst_page_logoff == 0xFFFF ||
- cur_fst_page_logoff > max_logoff) {
- retval = xd_erase_block(chip, i);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, i);
- continue;
- }
-
- if (zone_no == 0 && cur_fst_page_logoff == 0 &&
- redunt[PAGE_STATUS] != XD_GPG)
- XD_SET_MBR_FAIL(xd_card);
-
- if (zone->l2p_table[cur_fst_page_logoff] == 0xFFFF) {
- zone->l2p_table[cur_fst_page_logoff] = (u16)(i & 0x3FF);
- continue;
- }
-
- phy_block = zone->l2p_table[cur_fst_page_logoff] +
- ((u32)((zone_no) << 10));
-
- page_addr = ((i + 1) << xd_card->block_shift) - 1;
-
- retval = xd_read_redundant(chip, page_addr, redunt, 11);
- if (retval != STATUS_SUCCESS)
- continue;
-
- cur_lst_page_logoff = xd_load_log_block_addr(redunt);
- if (cur_lst_page_logoff == cur_fst_page_logoff) {
- int m;
-
- page_addr = ((phy_block + 1) <<
- xd_card->block_shift) - 1;
-
- for (m = 0; m < 3; m++) {
- retval = xd_read_redundant(chip, page_addr,
- redunt, 11);
- if (retval == STATUS_SUCCESS)
- break;
- }
-
- if (m == 3) {
- zone->l2p_table[cur_fst_page_logoff] =
- (u16)(i & 0x3FF);
- retval = xd_erase_block(chip, phy_block);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, phy_block);
- continue;
- }
-
- ent_lst_page_logoff = xd_load_log_block_addr(redunt);
- if (ent_lst_page_logoff != cur_fst_page_logoff) {
- zone->l2p_table[cur_fst_page_logoff] =
- (u16)(i & 0x3FF);
- retval = xd_erase_block(chip, phy_block);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, phy_block);
- continue;
- } else {
- retval = xd_erase_block(chip, i);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, i);
- }
- } else {
- retval = xd_erase_block(chip, i);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, i);
- }
- }
-
- if (XD_CHK_4MB(xd_card))
- end = 500;
- else
- end = 1000;
-
- i = 0;
- for (start = 0; start < end; start++) {
- if (zone->l2p_table[start] == 0xFFFF)
- i++;
- }
-
- dev_dbg(rtsx_dev(chip), "Block count %d, invalid L2P entry %d\n",
- end, i);
- dev_dbg(rtsx_dev(chip), "Total unused block: %d\n",
- zone->unused_blk_cnt);
-
- if ((zone->unused_blk_cnt - i) < 1)
- chip->card_wp |= XD_CARD;
-
- zone->build_flag = 1;
-
- return STATUS_SUCCESS;
-
-build_fail:
- vfree(zone->l2p_table);
- zone->l2p_table = NULL;
- vfree(zone->free_table);
- zone->free_table = NULL;
-
- return STATUS_FAIL;
-}
-
-static int xd_send_cmd(struct rtsx_chip *chip, u8 cmd)
-{
- int retval;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_DAT, 0xFF, cmd);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_SET_CMD);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- retval = rtsx_send_cmd(chip, XD_CARD, 200);
- if (retval < 0)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
-
-static int xd_read_multiple_pages(struct rtsx_chip *chip, u32 phy_blk,
- u32 log_blk, u8 start_page, u8 end_page,
- u8 *buf, unsigned int *index,
- unsigned int *offset)
-{
- struct xd_info *xd_card = &chip->xd_card;
- u32 page_addr, new_blk;
- u16 log_off;
- u8 reg_val, page_cnt;
- int zone_no, retval, i;
-
- if (start_page > end_page)
- goto status_fail;
-
- page_cnt = end_page - start_page;
- zone_no = (int)(log_blk / 1000);
- log_off = (u16)(log_blk % 1000);
-
- if ((phy_blk & 0x3FF) == 0x3FF) {
- for (i = 0; i < 256; i++) {
- page_addr = ((u32)i) << xd_card->block_shift;
-
- retval = xd_read_redundant(chip, page_addr, NULL, 0);
- if (retval == STATUS_SUCCESS)
- break;
-
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- xd_set_err_code(chip, XD_NO_CARD);
- goto status_fail;
- }
- }
- }
-
- page_addr = (phy_blk << xd_card->block_shift) + start_page;
-
- rtsx_init_cmd(chip);
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_PPB_TO_SIE, XD_PPB_TO_SIE);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CHK_DATA_STATUS,
- XD_AUTO_CHK_DATA_STATUS, XD_AUTO_CHK_DATA_STATUS);
-
- trans_dma_enable(chip->srb->sc_data_direction, chip,
- page_cnt * 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER, 0xFF,
- XD_TRANSFER_START | XD_READ_PAGES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END | XD_PPB_EMPTY,
- XD_TRANSFER_END | XD_PPB_EMPTY);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512,
- scsi_sg_count(chip->srb),
- index, offset, DMA_FROM_DEVICE,
- chip->xd_timeout);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
-
- if (retval == -ETIMEDOUT) {
- xd_set_err_code(chip, XD_TO_ERROR);
- goto status_fail;
- } else {
- goto fail;
- }
- }
-
- return STATUS_SUCCESS;
-
-fail:
- retval = rtsx_read_register(chip, XD_PAGE_STATUS, &reg_val);
- if (retval)
- return retval;
-
- if (reg_val != XD_GPG)
- xd_set_err_code(chip, XD_PRG_ERROR);
-
- retval = rtsx_read_register(chip, XD_CTL, &reg_val);
- if (retval)
- return retval;
-
- if (((reg_val & (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) ==
- (XD_ECC1_ERROR | XD_ECC1_UNCORRECTABLE)) ||
- ((reg_val & (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE)) ==
- (XD_ECC2_ERROR | XD_ECC2_UNCORRECTABLE))) {
- wait_timeout(100);
-
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- xd_set_err_code(chip, XD_NO_CARD);
- goto status_fail;
- }
-
- xd_set_err_code(chip, XD_ECC_ERROR);
-
- new_blk = xd_get_unused_block(chip, zone_no);
- if (new_blk == NO_NEW_BLK) {
- XD_CLR_BAD_OLDBLK(xd_card);
- goto status_fail;
- }
-
- retval = xd_copy_page(chip, phy_blk, new_blk, 0,
- xd_card->page_off + 1);
- if (retval != STATUS_SUCCESS) {
- if (!XD_CHK_BAD_NEWBLK(xd_card)) {
- retval = xd_erase_block(chip, new_blk);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, new_blk);
- } else {
- XD_CLR_BAD_NEWBLK(xd_card);
- }
- XD_CLR_BAD_OLDBLK(xd_card);
- goto status_fail;
- }
- xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
- xd_erase_block(chip, phy_blk);
- xd_mark_bad_block(chip, phy_blk);
- XD_CLR_BAD_OLDBLK(xd_card);
- }
-
-status_fail:
- return STATUS_FAIL;
-}
-
-static int xd_finish_write(struct rtsx_chip *chip,
- u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval, zone_no;
- u16 log_off;
-
- dev_dbg(rtsx_dev(chip), "old_blk = 0x%x, ", old_blk);
- dev_dbg(rtsx_dev(chip), "new_blk = 0x%x, ", new_blk);
- dev_dbg(rtsx_dev(chip), "log_blk = 0x%x\n", log_blk);
-
- if (page_off > xd_card->page_off)
- return STATUS_FAIL;
-
- zone_no = (int)(log_blk / 1000);
- log_off = (u16)(log_blk % 1000);
-
- if (old_blk == BLK_NOT_FOUND) {
- retval = xd_init_page(chip, new_blk, log_off,
- page_off, xd_card->page_off + 1);
- if (retval != STATUS_SUCCESS) {
- retval = xd_erase_block(chip, new_blk);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, new_blk);
- return STATUS_FAIL;
- }
- } else {
- retval = xd_copy_page(chip, old_blk, new_blk,
- page_off, xd_card->page_off + 1);
- if (retval != STATUS_SUCCESS) {
- if (!XD_CHK_BAD_NEWBLK(xd_card)) {
- retval = xd_erase_block(chip, new_blk);
- if (retval == STATUS_SUCCESS)
- xd_set_unused_block(chip, new_blk);
- }
- XD_CLR_BAD_NEWBLK(xd_card);
- return STATUS_FAIL;
- }
-
- retval = xd_erase_block(chip, old_blk);
- if (retval == STATUS_SUCCESS) {
- if (XD_CHK_BAD_OLDBLK(xd_card)) {
- xd_mark_bad_block(chip, old_blk);
- XD_CLR_BAD_OLDBLK(xd_card);
- } else {
- xd_set_unused_block(chip, old_blk);
- }
- } else {
- xd_set_err_code(chip, XD_NO_ERROR);
- XD_CLR_BAD_OLDBLK(xd_card);
- }
- }
-
- xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
-
- return STATUS_SUCCESS;
-}
-
-static int xd_prepare_write(struct rtsx_chip *chip,
- u32 old_blk, u32 new_blk, u32 log_blk, u8 page_off)
-{
- int retval;
-
- dev_dbg(rtsx_dev(chip), "%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x, page_off = %d\n",
- __func__, old_blk, new_blk, log_blk, (int)page_off);
-
- if (page_off) {
- retval = xd_copy_page(chip, old_blk, new_blk, 0, page_off);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-
-static int xd_write_multiple_pages(struct rtsx_chip *chip, u32 old_blk,
- u32 new_blk, u32 log_blk, u8 start_page,
- u8 end_page, u8 *buf, unsigned int *index,
- unsigned int *offset)
-{
- struct xd_info *xd_card = &chip->xd_card;
- u32 page_addr;
- int zone_no, retval;
- u16 log_off;
- u8 page_cnt, reg_val;
-
- dev_dbg(rtsx_dev(chip), "%s, old_blk = 0x%x, new_blk = 0x%x, log_blk = 0x%x\n",
- __func__, old_blk, new_blk, log_blk);
-
- if (start_page > end_page)
- goto status_fail;
-
- page_cnt = end_page - start_page;
- zone_no = (int)(log_blk / 1000);
- log_off = (u16)(log_blk % 1000);
-
- page_addr = (new_blk << xd_card->block_shift) + start_page;
-
- retval = xd_send_cmd(chip, READ1_1);
- if (retval != STATUS_SUCCESS)
- goto status_fail;
-
- rtsx_init_cmd(chip);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_H,
- 0xFF, (u8)(log_off >> 8));
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_ADDR1_L, 0xFF, (u8)log_off);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_BLOCK_STATUS, 0xFF, XD_GBLK);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_STATUS, 0xFF, XD_GPG);
-
- xd_assign_phy_addr(chip, page_addr, XD_RW_ADDR);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_CFG, XD_BA_TRANSFORM,
- XD_BA_TRANSFORM);
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_PAGE_CNT, 0xFF, page_cnt);
- rtsx_add_cmd(chip, WRITE_REG_CMD, CARD_DATA_SOURCE, 0x01, RING_BUFFER);
-
- trans_dma_enable(chip->srb->sc_data_direction, chip,
- page_cnt * 512, DMA_512);
-
- rtsx_add_cmd(chip, WRITE_REG_CMD, XD_TRANSFER,
- 0xFF, XD_TRANSFER_START | XD_WRITE_PAGES);
- rtsx_add_cmd(chip, CHECK_REG_CMD, XD_TRANSFER,
- XD_TRANSFER_END, XD_TRANSFER_END);
-
- rtsx_send_cmd_no_wait(chip);
-
- retval = rtsx_transfer_data_partial(chip, XD_CARD, buf, page_cnt * 512,
- scsi_sg_count(chip->srb),
- index, offset, DMA_TO_DEVICE, chip->xd_timeout);
- if (retval < 0) {
- rtsx_clear_xd_error(chip);
-
- if (retval == -ETIMEDOUT) {
- xd_set_err_code(chip, XD_TO_ERROR);
- goto status_fail;
- } else {
- goto fail;
- }
- }
-
- if (end_page == (xd_card->page_off + 1)) {
- xd_card->delay_write.delay_write_flag = 0;
-
- if (old_blk != BLK_NOT_FOUND) {
- retval = xd_erase_block(chip, old_blk);
- if (retval == STATUS_SUCCESS) {
- if (XD_CHK_BAD_OLDBLK(xd_card)) {
- xd_mark_bad_block(chip, old_blk);
- XD_CLR_BAD_OLDBLK(xd_card);
- } else {
- xd_set_unused_block(chip, old_blk);
- }
- } else {
- xd_set_err_code(chip, XD_NO_ERROR);
- XD_CLR_BAD_OLDBLK(xd_card);
- }
- }
- xd_set_l2p_tbl(chip, zone_no, log_off, (u16)(new_blk & 0x3FF));
- }
-
- return STATUS_SUCCESS;
-
-fail:
- retval = rtsx_read_register(chip, XD_DAT, &reg_val);
- if (retval)
- return retval;
- if (reg_val & PROGRAM_ERROR) {
- xd_set_err_code(chip, XD_PRG_ERROR);
- xd_mark_bad_block(chip, new_blk);
- }
-
-status_fail:
- return STATUS_FAIL;
-}
-
-#ifdef XD_DELAY_WRITE
-int xd_delay_write(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- struct xd_delay_write_tag *delay_write = &xd_card->delay_write;
- int retval;
-
- if (delay_write->delay_write_flag) {
- retval = xd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- delay_write->delay_write_flag = 0;
- retval = xd_finish_write(chip,
- delay_write->old_phyblock,
- delay_write->new_phyblock,
- delay_write->logblock,
- delay_write->pageoff);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- }
-
- return STATUS_SUCCESS;
-}
-#endif
-
-int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt)
-{
- struct xd_info *xd_card = &chip->xd_card;
- unsigned int lun = SCSI_LUN(srb);
-#ifdef XD_DELAY_WRITE
- struct xd_delay_write_tag *delay_write = &xd_card->delay_write;
-#endif
- int retval, zone_no;
- unsigned int index = 0, offset = 0;
- u32 log_blk, old_blk = 0, new_blk = 0;
- u16 log_off, total_sec_cnt = sector_cnt;
- u8 start_page, end_page = 0, page_cnt;
- u8 *ptr;
-
- xd_set_err_code(chip, XD_NO_ERROR);
-
- xd_card->cleanup_counter = 0;
-
- dev_dbg(rtsx_dev(chip), "%s: scsi_sg_count = %d\n", __func__,
- scsi_sg_count(srb));
-
- ptr = (u8 *)scsi_sglist(srb);
-
- retval = xd_switch_clock(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- chip->card_fail |= XD_CARD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
-
- log_blk = start_sector >> xd_card->block_shift;
- start_page = (u8)start_sector & xd_card->page_off;
- zone_no = (int)(log_blk / 1000);
- log_off = (u16)(log_blk % 1000);
-
- if (xd_card->zone[zone_no].build_flag == 0) {
- retval = xd_build_l2p_tbl(chip, zone_no);
- if (retval != STATUS_SUCCESS) {
- chip->card_fail |= XD_CARD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
-#ifdef XD_DELAY_WRITE
- if (delay_write->delay_write_flag &&
- delay_write->logblock == log_blk &&
- start_page > delay_write->pageoff) {
- delay_write->delay_write_flag = 0;
- if (delay_write->old_phyblock != BLK_NOT_FOUND) {
- retval = xd_copy_page(chip,
- delay_write->old_phyblock,
- delay_write->new_phyblock,
- delay_write->pageoff,
- start_page);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
- }
- old_blk = delay_write->old_phyblock;
- new_blk = delay_write->new_phyblock;
- } else if (delay_write->delay_write_flag &&
- (delay_write->logblock == log_blk) &&
- (start_page == delay_write->pageoff)) {
- delay_write->delay_write_flag = 0;
- old_blk = delay_write->old_phyblock;
- new_blk = delay_write->new_phyblock;
- } else {
- retval = xd_delay_write(chip);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-#endif
- old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
- new_blk = xd_get_unused_block(chip, zone_no);
- if (old_blk == BLK_NOT_FOUND ||
- new_blk == BLK_NOT_FOUND) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-
- retval = xd_prepare_write(chip, old_blk, new_blk,
- log_blk, start_page);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, XD_CARD) !=
- STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-#ifdef XD_DELAY_WRITE
- }
-#endif
- } else {
-#ifdef XD_DELAY_WRITE
- retval = xd_delay_write(chip);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return STATUS_FAIL;
- }
-#endif
-
- old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
- if (old_blk == BLK_NOT_FOUND) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return STATUS_FAIL;
- }
- }
-
- dev_dbg(rtsx_dev(chip), "old_blk = 0x%x\n", old_blk);
-
- while (total_sec_cnt) {
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- chip->card_fail |= XD_CARD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
-
- if ((start_page + total_sec_cnt) > (xd_card->page_off + 1))
- end_page = xd_card->page_off + 1;
- else
- end_page = start_page + (u8)total_sec_cnt;
-
- page_cnt = end_page - start_page;
- if (srb->sc_data_direction == DMA_FROM_DEVICE) {
- retval = xd_read_multiple_pages(chip, old_blk, log_blk,
- start_page, end_page,
- ptr, &index, &offset);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- return STATUS_FAIL;
- }
- } else {
- retval = xd_write_multiple_pages(chip, old_blk,
- new_blk, log_blk,
- start_page, end_page,
- ptr, &index, &offset);
- if (retval != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
- }
-
- total_sec_cnt -= page_cnt;
- if (scsi_sg_count(srb) == 0)
- ptr += page_cnt * 512;
-
- if (total_sec_cnt == 0)
- break;
-
- log_blk++;
- zone_no = (int)(log_blk / 1000);
- log_off = (u16)(log_blk % 1000);
-
- if (xd_card->zone[zone_no].build_flag == 0) {
- retval = xd_build_l2p_tbl(chip, zone_no);
- if (retval != STATUS_SUCCESS) {
- chip->card_fail |= XD_CARD;
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- }
-
- old_blk = xd_get_l2p_tbl(chip, zone_no, log_off);
- if (old_blk == BLK_NOT_FOUND) {
- if (srb->sc_data_direction == DMA_FROM_DEVICE)
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_UNRECOVER_READ_ERR);
- else
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
-
- return STATUS_FAIL;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE) {
- new_blk = xd_get_unused_block(chip, zone_no);
- if (new_blk == BLK_NOT_FOUND) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
- }
-
- start_page = 0;
- }
-
- if (srb->sc_data_direction == DMA_TO_DEVICE &&
- (end_page != (xd_card->page_off + 1))) {
-#ifdef XD_DELAY_WRITE
- delay_write->delay_write_flag = 1;
- delay_write->old_phyblock = old_blk;
- delay_write->new_phyblock = new_blk;
- delay_write->logblock = log_blk;
- delay_write->pageoff = end_page;
-#else
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- chip->card_fail |= XD_CARD;
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
-
- retval = xd_finish_write(chip, old_blk, new_blk,
- log_blk, end_page);
- if (retval != STATUS_SUCCESS) {
- if (detect_card_cd(chip, XD_CARD) != STATUS_SUCCESS) {
- set_sense_type(chip, lun,
- SENSE_TYPE_MEDIA_NOT_PRESENT);
- return STATUS_FAIL;
- }
- set_sense_type(chip, lun, SENSE_TYPE_MEDIA_WRITE_ERR);
- return STATUS_FAIL;
- }
-#endif
- }
-
- scsi_set_resid(srb, 0);
-
- return STATUS_SUCCESS;
-}
-
-void xd_free_l2p_tbl(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int i = 0;
-
- if (xd_card->zone) {
- for (i = 0; i < xd_card->zone_cnt; i++) {
- vfree(xd_card->zone[i].l2p_table);
- xd_card->zone[i].l2p_table = NULL;
- vfree(xd_card->zone[i].free_table);
- xd_card->zone[i].free_table = NULL;
- }
- vfree(xd_card->zone);
- xd_card->zone = NULL;
- }
-}
-
-void xd_cleanup_work(struct rtsx_chip *chip)
-{
-#ifdef XD_DELAY_WRITE
- struct xd_info *xd_card = &chip->xd_card;
-
- if (xd_card->delay_write.delay_write_flag) {
- dev_dbg(rtsx_dev(chip), "xD: delay write\n");
- xd_delay_write(chip);
- xd_card->cleanup_counter = 0;
- }
-#endif
-}
-
-int xd_power_off_card3v3(struct rtsx_chip *chip)
-{
- int retval;
-
- retval = disable_card_clock(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- retval = rtsx_write_register(chip, CARD_OE, XD_OUTPUT_EN, 0);
- if (retval)
- return retval;
-
- if (!chip->ft2_fast_mode) {
- retval = card_power_off(chip, XD_CARD);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- wait_timeout(50);
- }
-
- if (chip->asic_code) {
- retval = xd_pull_ctl_disable(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
- } else {
- retval = rtsx_write_register(chip, FPGA_PULL_CTL, 0xFF, 0xDF);
- if (retval)
- return retval;
- }
-
- return STATUS_SUCCESS;
-}
-
-int release_xd_card(struct rtsx_chip *chip)
-{
- struct xd_info *xd_card = &chip->xd_card;
- int retval;
-
- chip->card_ready &= ~XD_CARD;
- chip->card_fail &= ~XD_CARD;
- chip->card_wp &= ~XD_CARD;
-
- xd_card->delay_write.delay_write_flag = 0;
-
- xd_free_l2p_tbl(chip);
-
- retval = xd_power_off_card3v3(chip);
- if (retval != STATUS_SUCCESS)
- return STATUS_FAIL;
-
- return STATUS_SUCCESS;
-}
diff --git a/drivers/staging/rts5208/xd.h b/drivers/staging/rts5208/xd.h
deleted file mode 100644
index 98c00f268e56..000000000000
--- a/drivers/staging/rts5208/xd.h
+++ /dev/null
@@ -1,176 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Driver for Realtek PCI-Express card reader
- *
- * Copyright(c) 2009-2013 Realtek Semiconductor Corp. All rights reserved.
- *
- * Author:
- * Wei WANG (wei_wang@realsil.com.cn)
- * Micky Ching (micky_ching@realsil.com.cn)
- */
-
-#ifndef __REALTEK_RTSX_XD_H
-#define __REALTEK_RTSX_XD_H
-
-#define XD_DELAY_WRITE
-
-/* Error Codes */
-#define XD_NO_ERROR 0x00
-#define XD_NO_MEMORY 0x80
-#define XD_PRG_ERROR 0x40
-#define XD_NO_CARD 0x20
-#define XD_READ_FAIL 0x10
-#define XD_ERASE_FAIL 0x08
-#define XD_WRITE_FAIL 0x04
-#define XD_ECC_ERROR 0x02
-#define XD_TO_ERROR 0x01
-
-/* XD Commands */
-#define READ1_1 0x00
-#define READ1_2 0x01
-#define READ2 0x50
-#define READ_ID 0x90
-#define RESET 0xff
-#define PAGE_PRG_1 0x80
-#define PAGE_PRG_2 0x10
-#define BLK_ERASE_1 0x60
-#define BLK_ERASE_2 0xD0
-#define READ_STS 0x70
-#define READ_XD_ID 0x9A
-#define COPY_BACK_512 0x8A
-#define COPY_BACK_2K 0x85
-#define READ1_1_2 0x30
-#define READ1_1_3 0x35
-#define CHG_DAT_OUT_1 0x05
-#define RDM_DAT_OUT_1 0x05
-#define CHG_DAT_OUT_2 0xE0
-#define RDM_DAT_OUT_2 0xE0
-#define CHG_DAT_OUT_2 0xE0
-#define CHG_DAT_IN_1 0x85
-#define CACHE_PRG 0x15
-
-/* Redundant Area Related */
-#define XD_EXTRA_SIZE 0x10
-#define XD_2K_EXTRA_SIZE 0x40
-
-#define NOT_WRITE_PROTECTED 0x80
-#define READY_STATE 0x40
-#define PROGRAM_ERROR 0x01
-#define PROGRAM_ERROR_N_1 0x02
-#define INTERNAL_READY 0x20
-#define READY_FLAG 0x5F
-
-#define XD_8M_X8_512 0xE6
-#define XD_16M_X8_512 0x73
-#define XD_32M_X8_512 0x75
-#define XD_64M_X8_512 0x76
-#define XD_128M_X8_512 0x79
-#define XD_256M_X8_512 0x71
-#define XD_128M_X8_2048 0xF1
-#define XD_256M_X8_2048 0xDA
-#define XD_512M_X8 0xDC
-#define XD_128M_X16_2048 0xC1
-#define XD_4M_X8_512_1 0xE3
-#define XD_4M_X8_512_2 0xE5
-#define XD_1G_X8_512 0xD3
-#define XD_2G_X8_512 0xD5
-
-#define XD_ID_CODE 0xB5
-
-#define VENDOR_BLOCK 0xEFFF
-#define CIS_BLOCK 0xDFFF
-
-#define BLK_NOT_FOUND 0xFFFFFFFF
-
-#define NO_NEW_BLK 0xFFFFFFFF
-
-#define PAGE_CORRECTABLE 0x0
-#define PAGE_NOTCORRECTABLE 0x1
-
-#define NO_OFFSET 0x0
-#define WITH_OFFSET 0x1
-
-#define SECT_PER_PAGE 4
-#define XD_ADDR_MODE_2C XD_ADDR_MODE_2A
-
-#define ZONE0_BAD_BLOCK 23
-#define NOT_ZONE0_BAD_BLOCK 24
-
-#define XD_RW_ADDR 0x01
-#define XD_ERASE_ADDR 0x02
-
-#define XD_PAGE_512(xd_card) \
-do { \
- (xd_card)->block_shift = 5; \
- (xd_card)->page_off = 0x1F; \
-} while (0)
-
-#define XD_SET_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag |= 0x01)
-#define XD_CLR_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag &= ~0x01)
-#define XD_CHK_BAD_NEWBLK(xd_card) ((xd_card)->multi_flag & 0x01)
-
-#define XD_SET_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag |= 0x02)
-#define XD_CLR_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag &= ~0x02)
-#define XD_CHK_BAD_OLDBLK(xd_card) ((xd_card)->multi_flag & 0x02)
-
-#define XD_SET_MBR_FAIL(xd_card) ((xd_card)->multi_flag |= 0x04)
-#define XD_CLR_MBR_FAIL(xd_card) ((xd_card)->multi_flag &= ~0x04)
-#define XD_CHK_MBR_FAIL(xd_card) ((xd_card)->multi_flag & 0x04)
-
-#define XD_SET_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag |= 0x08)
-#define XD_CLR_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag &= ~0x08)
-#define XD_CHK_ECC_FLD_ERR(xd_card) ((xd_card)->multi_flag & 0x08)
-
-#define XD_SET_4MB(xd_card) ((xd_card)->multi_flag |= 0x10)
-#define XD_CLR_4MB(xd_card) ((xd_card)->multi_flag &= ~0x10)
-#define XD_CHK_4MB(xd_card) ((xd_card)->multi_flag & 0x10)
-
-#define XD_SET_ECC_ERR(xd_card) ((xd_card)->multi_flag |= 0x40)
-#define XD_CLR_ECC_ERR(xd_card) ((xd_card)->multi_flag &= ~0x40)
-#define XD_CHK_ECC_ERR(xd_card) ((xd_card)->multi_flag & 0x40)
-
-#define PAGE_STATUS 0
-#define BLOCK_STATUS 1
-#define BLOCK_ADDR1_L 2
-#define BLOCK_ADDR1_H 3
-#define BLOCK_ADDR2_L 4
-#define BLOCK_ADDR2_H 5
-#define RESERVED0 6
-#define RESERVED1 7
-#define RESERVED2 8
-#define RESERVED3 9
-#define PARITY 10
-
-#define CIS0_0 0
-#define CIS0_1 1
-#define CIS0_2 2
-#define CIS0_3 3
-#define CIS0_4 4
-#define CIS0_5 5
-#define CIS0_6 6
-#define CIS0_7 7
-#define CIS0_8 8
-#define CIS0_9 9
-#define CIS1_0 256
-#define CIS1_1 (256 + 1)
-#define CIS1_2 (256 + 2)
-#define CIS1_3 (256 + 3)
-#define CIS1_4 (256 + 4)
-#define CIS1_5 (256 + 5)
-#define CIS1_6 (256 + 6)
-#define CIS1_7 (256 + 7)
-#define CIS1_8 (256 + 8)
-#define CIS1_9 (256 + 9)
-
-int reset_xd_card(struct rtsx_chip *chip);
-#ifdef XD_DELAY_WRITE
-int xd_delay_write(struct rtsx_chip *chip);
-#endif
-int xd_rw(struct scsi_cmnd *srb, struct rtsx_chip *chip,
- u32 start_sector, u16 sector_cnt);
-void xd_free_l2p_tbl(struct rtsx_chip *chip);
-void xd_cleanup_work(struct rtsx_chip *chip);
-int xd_power_off_card3v3(struct rtsx_chip *chip);
-int release_xd_card(struct rtsx_chip *chip);
-
-#endif /* __REALTEK_RTSX_XD_H */
diff --git a/drivers/staging/sm750fb/TODO b/drivers/staging/sm750fb/TODO
index 481409eb3fb3..9dd57c566257 100644
--- a/drivers/staging/sm750fb/TODO
+++ b/drivers/staging/sm750fb/TODO
@@ -12,8 +12,3 @@ TODO:
Note:
- This driver will be removed from staging after the drm driver is ready
- The drm driver is getting ready at https://gitlab.com/sudipm/sm750/tree/sm750
-
-Please send any patches to
- Greg Kroah-Hartman <greg@kroah.com>
- Sudip Mukherjee <sudipm.mukherjee@gmail.com>
- Teddy Wang <teddy.wang@siliconmotion.com>
diff --git a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
index 133ed15f3dbc..dc0d715ed970 100644
--- a/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
+++ b/drivers/staging/vc04_services/bcm2835-audio/bcm2835-vchiq.c
@@ -96,7 +96,8 @@ static int bcm2835_audio_send_simple(struct bcm2835_audio_instance *instance,
static int audio_vchi_callback(struct vchiq_instance *vchiq_instance,
enum vchiq_reason reason,
struct vchiq_header *header,
- unsigned int handle, void *userdata)
+ unsigned int handle,
+ void *cb_data, void __user *cb_userdata)
{
struct bcm2835_audio_instance *instance = vchiq_get_service_userdata(vchiq_instance,
handle);
diff --git a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
index 6c40d8c1dde6..ee4469f4fc51 100644
--- a/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
+++ b/drivers/staging/vc04_services/include/linux/raspberrypi/vchiq.h
@@ -56,7 +56,7 @@ struct vchiq_service_base {
enum vchiq_reason reason,
struct vchiq_header *header,
unsigned int handle,
- void *bulk_userdata);
+ void *cb_data, void __user *cb_userdata);
void *userdata;
};
@@ -64,7 +64,8 @@ struct vchiq_completion_data_kernel {
enum vchiq_reason reason;
struct vchiq_header *header;
void *service_userdata;
- void *bulk_userdata;
+ void *cb_data;
+ void __user *cb_userdata;
};
struct vchiq_service_params_kernel {
@@ -73,7 +74,7 @@ struct vchiq_service_params_kernel {
enum vchiq_reason reason,
struct vchiq_header *header,
unsigned int handle,
- void *bulk_userdata);
+ void *cb_data, void __user *cb_userdata);
void *userdata;
short version; /* Increment for non-trivial changes */
short version_min; /* Update for incompatible changes */
diff --git a/drivers/staging/vc04_services/interface/TESTING b/drivers/staging/vc04_services/interface/TESTING
index 273952dc9d85..c98f688b07e0 100644
--- a/drivers/staging/vc04_services/interface/TESTING
+++ b/drivers/staging/vc04_services/interface/TESTING
@@ -52,10 +52,10 @@ Here are the most common kernel configurations:
* Ping test
- Command: vchiq_test -p 1
+ Command: vchiq_test -p
Expected output:
- Ping test - service:echo, iters:1, version 3
+ Ping test - service:echo, iters:1000, version 3
vchi ping (size 0) -> 57.000000us
vchi ping (size 0, 0 async, 0 oneway) -> 122.000000us
vchi bulk (size 0, 0 async, 0 oneway) -> 546.000000us
diff --git a/drivers/staging/vc04_services/interface/TODO b/drivers/staging/vc04_services/interface/TODO
index dfb1ee49633f..f6f24600aa86 100644
--- a/drivers/staging/vc04_services/interface/TODO
+++ b/drivers/staging/vc04_services/interface/TODO
@@ -26,16 +26,3 @@ kthreads, userspace, limitations) could be very helpful for reviewers.
The code follows the 80 characters limitation yet tends to go 3 or 4 levels of
indentation deep making it very unpleasant to read. This is specially relevant
in the character driver ioctl code and in the core thread functions.
-
-* Clean up Sparse warnings from __user annotations. See
-vchiq_irq_queue_bulk_tx_rx(). Ensure that the address of "&waiter->bulk_waiter"
-is never disclosed to userspace.
-
-* Fix behavior of message handling
-
-The polling behavior of vchiq_bulk_transmit(), vchiq_bulk_receive() and
-vchiq_queue_kernel_message() looks broken. A possible signal should be
-propagated back to user space to let the calling task handle it before
-retrying. Hopefully these msleep(1) shouldn't be necessary anymore.
-
-https://lore.kernel.org/linux-staging/CAK8P3a3HGm1cPo4sW9fOY4E8AN8yAq3tevXxU5m8bmtmsU8WKw@mail.gmail.com/
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
index 6c488b1e2624..a4e83e5d619b 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.c
@@ -14,7 +14,6 @@
#include <linux/device.h>
#include <linux/device/bus.h>
#include <linux/mm.h>
-#include <linux/highmem.h>
#include <linux/pagemap.h>
#include <linux/bug.h>
#include <linux/completion.h>
@@ -36,7 +35,6 @@
#include "vchiq_arm.h"
#include "vchiq_bus.h"
#include "vchiq_debugfs.h"
-#include "vchiq_pagelist.h"
#define DEVICE_NAME "vchiq"
@@ -48,7 +46,6 @@
#define VCHIQ_PLATFORM_FRAGMENTS_COUNT_IDX 1
#define BELL0 0x00
-#define BELL2 0x08
#define ARM_DS_ACTIVE BIT(2)
@@ -109,21 +106,9 @@ struct vchiq_arm_state {
int first_connect;
};
-struct vchiq_pagelist_info {
- struct pagelist *pagelist;
- size_t pagelist_buffer_size;
- dma_addr_t dma_addr;
- enum dma_data_direction dma_dir;
- unsigned int num_pages;
- unsigned int pages_need_release;
- struct page **pages;
- struct scatterlist *scatterlist;
- unsigned int scatterlist_mapped;
-};
-
static int
-vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, void *data,
- unsigned int size, enum vchiq_bulk_dir dir);
+vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk_params);
static irqreturn_t
vchiq_doorbell_irq(int irq, void *dev_id)
@@ -146,35 +131,6 @@ vchiq_doorbell_irq(int irq, void *dev_id)
return ret;
}
-static void
-cleanup_pagelistinfo(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo)
-{
- if (pagelistinfo->scatterlist_mapped) {
- dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist,
- pagelistinfo->num_pages, pagelistinfo->dma_dir);
- }
-
- if (pagelistinfo->pages_need_release)
- unpin_user_pages(pagelistinfo->pages, pagelistinfo->num_pages);
-
- dma_free_coherent(instance->state->dev, pagelistinfo->pagelist_buffer_size,
- pagelistinfo->pagelist, pagelistinfo->dma_addr);
-}
-
-static inline bool
-is_adjacent_block(u32 *addrs, dma_addr_t addr, unsigned int k)
-{
- u32 tmp;
-
- if (!k)
- return false;
-
- tmp = (addrs[k - 1] & PAGE_MASK) +
- (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT);
-
- return tmp == (addr & PAGE_MASK);
-}
-
/*
* This function is called by the vchiq stack once it has been connected to
* the videocore and clients can start to use the stack.
@@ -225,270 +181,6 @@ void vchiq_add_connected_callback(struct vchiq_device *device, void (*callback)(
}
EXPORT_SYMBOL(vchiq_add_connected_callback);
-/* There is a potential problem with partial cache lines (pages?)
- * at the ends of the block when reading. If the CPU accessed anything in
- * the same line (page?) then it may have pulled old data into the cache,
- * obscuring the new data underneath. We can solve this by transferring the
- * partial cache lines separately, and allowing the ARM to copy into the
- * cached area.
- */
-
-static struct vchiq_pagelist_info *
-create_pagelist(struct vchiq_instance *instance, char *buf, char __user *ubuf,
- size_t count, unsigned short type)
-{
- struct vchiq_drv_mgmt *drv_mgmt;
- struct pagelist *pagelist;
- struct vchiq_pagelist_info *pagelistinfo;
- struct page **pages;
- u32 *addrs;
- unsigned int num_pages, offset, i, k;
- int actual_pages;
- size_t pagelist_size;
- struct scatterlist *scatterlist, *sg;
- int dma_buffers;
- dma_addr_t dma_addr;
-
- if (count >= INT_MAX - PAGE_SIZE)
- return NULL;
-
- drv_mgmt = dev_get_drvdata(instance->state->dev);
-
- if (buf)
- offset = (uintptr_t)buf & (PAGE_SIZE - 1);
- else
- offset = (uintptr_t)ubuf & (PAGE_SIZE - 1);
- num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE);
-
- if ((size_t)num_pages > (SIZE_MAX - sizeof(struct pagelist) -
- sizeof(struct vchiq_pagelist_info)) /
- (sizeof(u32) + sizeof(pages[0]) +
- sizeof(struct scatterlist)))
- return NULL;
-
- pagelist_size = sizeof(struct pagelist) +
- (num_pages * sizeof(u32)) +
- (num_pages * sizeof(pages[0]) +
- (num_pages * sizeof(struct scatterlist))) +
- sizeof(struct vchiq_pagelist_info);
-
- /* Allocate enough storage to hold the page pointers and the page
- * list
- */
- pagelist = dma_alloc_coherent(instance->state->dev, pagelist_size, &dma_addr,
- GFP_KERNEL);
-
- dev_dbg(instance->state->dev, "arm: %pK\n", pagelist);
-
- if (!pagelist)
- return NULL;
-
- addrs = pagelist->addrs;
- pages = (struct page **)(addrs + num_pages);
- scatterlist = (struct scatterlist *)(pages + num_pages);
- pagelistinfo = (struct vchiq_pagelist_info *)
- (scatterlist + num_pages);
-
- pagelist->length = count;
- pagelist->type = type;
- pagelist->offset = offset;
-
- /* Populate the fields of the pagelistinfo structure */
- pagelistinfo->pagelist = pagelist;
- pagelistinfo->pagelist_buffer_size = pagelist_size;
- pagelistinfo->dma_addr = dma_addr;
- pagelistinfo->dma_dir = (type == PAGELIST_WRITE) ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE;
- pagelistinfo->num_pages = num_pages;
- pagelistinfo->pages_need_release = 0;
- pagelistinfo->pages = pages;
- pagelistinfo->scatterlist = scatterlist;
- pagelistinfo->scatterlist_mapped = 0;
-
- if (buf) {
- unsigned long length = count;
- unsigned int off = offset;
-
- for (actual_pages = 0; actual_pages < num_pages;
- actual_pages++) {
- struct page *pg =
- vmalloc_to_page((buf +
- (actual_pages * PAGE_SIZE)));
- size_t bytes = PAGE_SIZE - off;
-
- if (!pg) {
- cleanup_pagelistinfo(instance, pagelistinfo);
- return NULL;
- }
-
- if (bytes > length)
- bytes = length;
- pages[actual_pages] = pg;
- length -= bytes;
- off = 0;
- }
- /* do not try and release vmalloc pages */
- } else {
- actual_pages = pin_user_pages_fast((unsigned long)ubuf & PAGE_MASK, num_pages,
- type == PAGELIST_READ, pages);
-
- if (actual_pages != num_pages) {
- dev_dbg(instance->state->dev, "arm: Only %d/%d pages locked\n",
- actual_pages, num_pages);
-
- /* This is probably due to the process being killed */
- if (actual_pages > 0)
- unpin_user_pages(pages, actual_pages);
- cleanup_pagelistinfo(instance, pagelistinfo);
- return NULL;
- }
- /* release user pages */
- pagelistinfo->pages_need_release = 1;
- }
-
- /*
- * Initialize the scatterlist so that the magic cookie
- * is filled if debugging is enabled
- */
- sg_init_table(scatterlist, num_pages);
- /* Now set the pages for each scatterlist */
- for (i = 0; i < num_pages; i++) {
- unsigned int len = PAGE_SIZE - offset;
-
- if (len > count)
- len = count;
- sg_set_page(scatterlist + i, pages[i], len, offset);
- offset = 0;
- count -= len;
- }
-
- dma_buffers = dma_map_sg(instance->state->dev,
- scatterlist,
- num_pages,
- pagelistinfo->dma_dir);
-
- if (dma_buffers == 0) {
- cleanup_pagelistinfo(instance, pagelistinfo);
- return NULL;
- }
-
- pagelistinfo->scatterlist_mapped = 1;
-
- /* Combine adjacent blocks for performance */
- k = 0;
- for_each_sg(scatterlist, sg, dma_buffers, i) {
- unsigned int len = sg_dma_len(sg);
- dma_addr_t addr = sg_dma_address(sg);
-
- /* Note: addrs is the address + page_count - 1
- * The firmware expects blocks after the first to be page-
- * aligned and a multiple of the page size
- */
- WARN_ON(len == 0);
- WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
- WARN_ON(i && (addr & ~PAGE_MASK));
- if (is_adjacent_block(addrs, addr, k))
- addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
- else
- addrs[k++] = (addr & PAGE_MASK) |
- (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
- }
-
- /* Partial cache lines (fragments) require special measures */
- if ((type == PAGELIST_READ) &&
- ((pagelist->offset & (drv_mgmt->info->cache_line_size - 1)) ||
- ((pagelist->offset + pagelist->length) &
- (drv_mgmt->info->cache_line_size - 1)))) {
- char *fragments;
-
- if (down_interruptible(&drv_mgmt->free_fragments_sema)) {
- cleanup_pagelistinfo(instance, pagelistinfo);
- return NULL;
- }
-
- WARN_ON(!drv_mgmt->free_fragments);
-
- down(&drv_mgmt->free_fragments_mutex);
- fragments = drv_mgmt->free_fragments;
- WARN_ON(!fragments);
- drv_mgmt->free_fragments = *(char **)drv_mgmt->free_fragments;
- up(&drv_mgmt->free_fragments_mutex);
- pagelist->type = PAGELIST_READ_WITH_FRAGMENTS +
- (fragments - drv_mgmt->fragments_base) / drv_mgmt->fragments_size;
- }
-
- return pagelistinfo;
-}
-
-static void
-free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo,
- int actual)
-{
- struct vchiq_drv_mgmt *drv_mgmt;
- struct pagelist *pagelist = pagelistinfo->pagelist;
- struct page **pages = pagelistinfo->pages;
- unsigned int num_pages = pagelistinfo->num_pages;
-
- dev_dbg(instance->state->dev, "arm: %pK, %d\n", pagelistinfo->pagelist, actual);
-
- drv_mgmt = dev_get_drvdata(instance->state->dev);
-
- /*
- * NOTE: dma_unmap_sg must be called before the
- * cpu can touch any of the data/pages.
- */
- dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist,
- pagelistinfo->num_pages, pagelistinfo->dma_dir);
- pagelistinfo->scatterlist_mapped = 0;
-
- /* Deal with any partial cache lines (fragments) */
- if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS && drv_mgmt->fragments_base) {
- char *fragments = drv_mgmt->fragments_base +
- (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) *
- drv_mgmt->fragments_size;
- int head_bytes, tail_bytes;
-
- head_bytes = (drv_mgmt->info->cache_line_size - pagelist->offset) &
- (drv_mgmt->info->cache_line_size - 1);
- tail_bytes = (pagelist->offset + actual) &
- (drv_mgmt->info->cache_line_size - 1);
-
- if ((actual >= 0) && (head_bytes != 0)) {
- if (head_bytes > actual)
- head_bytes = actual;
-
- memcpy_to_page(pages[0],
- pagelist->offset,
- fragments,
- head_bytes);
- }
- if ((actual >= 0) && (head_bytes < actual) &&
- (tail_bytes != 0))
- memcpy_to_page(pages[num_pages - 1],
- (pagelist->offset + actual) &
- (PAGE_SIZE - 1) & ~(drv_mgmt->info->cache_line_size - 1),
- fragments + drv_mgmt->info->cache_line_size,
- tail_bytes);
-
- down(&drv_mgmt->free_fragments_mutex);
- *(char **)fragments = drv_mgmt->free_fragments;
- drv_mgmt->free_fragments = fragments;
- up(&drv_mgmt->free_fragments_mutex);
- up(&drv_mgmt->free_fragments_sema);
- }
-
- /* Need to mark all the pages dirty. */
- if (pagelist->type != PAGELIST_WRITE &&
- pagelistinfo->pages_need_release) {
- unsigned int i;
-
- for (i = 0; i < num_pages; i++)
- set_page_dirty(pages[i]);
- }
-
- cleanup_pagelistinfo(instance, pagelistinfo);
-}
-
static int vchiq_platform_init(struct platform_device *pdev, struct vchiq_state *state)
{
struct device *dev = &pdev->dev;
@@ -616,58 +308,6 @@ static struct vchiq_arm_state *vchiq_platform_get_arm_state(struct vchiq_state *
return (struct vchiq_arm_state *)state->platform_state;
}
-void
-remote_event_signal(struct vchiq_state *state, struct remote_event *event)
-{
- struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(state->dev);
-
- /*
- * Ensure that all writes to shared data structures have completed
- * before signalling the peer.
- */
- wmb();
-
- event->fired = 1;
-
- dsb(sy); /* data barrier operation */
-
- if (event->armed)
- writel(0, mgmt->regs + BELL2); /* trigger vc interrupt */
-}
-
-int
-vchiq_prepare_bulk_data(struct vchiq_instance *instance, struct vchiq_bulk *bulk, void *offset,
- void __user *uoffset, int size, int dir)
-{
- struct vchiq_pagelist_info *pagelistinfo;
-
- pagelistinfo = create_pagelist(instance, offset, uoffset, size,
- (dir == VCHIQ_BULK_RECEIVE)
- ? PAGELIST_READ
- : PAGELIST_WRITE);
-
- if (!pagelistinfo)
- return -ENOMEM;
-
- bulk->data = pagelistinfo->dma_addr;
-
- /*
- * Store the pagelistinfo address in remote_data,
- * which isn't used by the slave.
- */
- bulk->remote_data = pagelistinfo;
-
- return 0;
-}
-
-void
-vchiq_complete_bulk(struct vchiq_instance *instance, struct vchiq_bulk *bulk)
-{
- if (bulk && bulk->remote_data && bulk->actual)
- free_pagelist(instance, (struct vchiq_pagelist_info *)bulk->remote_data,
- bulk->actual);
-}
-
void vchiq_dump_platform_state(struct seq_file *f)
{
seq_puts(f, " Platform: 2835 (VC master)\n");
@@ -851,34 +491,31 @@ int
vchiq_bulk_transmit(struct vchiq_instance *instance, unsigned int handle, const void *data,
unsigned int size, void *userdata, enum vchiq_bulk_mode mode)
{
+ struct vchiq_bulk bulk_params = {};
int ret;
- while (1) {
- switch (mode) {
- case VCHIQ_BULK_MODE_NOCALLBACK:
- case VCHIQ_BULK_MODE_CALLBACK:
- ret = vchiq_bulk_xfer_callback_interruptible(instance, handle,
- (void *)data, NULL,
- size, mode, userdata,
- VCHIQ_BULK_TRANSMIT);
- break;
- case VCHIQ_BULK_MODE_BLOCKING:
- ret = vchiq_blocking_bulk_transfer(instance, handle, (void *)data, size,
- VCHIQ_BULK_TRANSMIT);
- break;
- default:
- return -EINVAL;
- }
-
- /*
- * vchiq_*_bulk_transfer() may return -EAGAIN, so we need
- * to implement a retry mechanism since this function is
- * supposed to block until queued
- */
- if (ret != -EAGAIN)
- break;
-
- msleep(1);
+ switch (mode) {
+ case VCHIQ_BULK_MODE_NOCALLBACK:
+ case VCHIQ_BULK_MODE_CALLBACK:
+
+ bulk_params.offset = (void *)data;
+ bulk_params.mode = mode;
+ bulk_params.size = size;
+ bulk_params.cb_data = userdata;
+ bulk_params.dir = VCHIQ_BULK_TRANSMIT;
+
+ ret = vchiq_bulk_xfer_callback(instance, handle, &bulk_params);
+ break;
+ case VCHIQ_BULK_MODE_BLOCKING:
+ bulk_params.offset = (void *)data;
+ bulk_params.mode = mode;
+ bulk_params.size = size;
+ bulk_params.dir = VCHIQ_BULK_TRANSMIT;
+
+ ret = vchiq_blocking_bulk_transfer(instance, handle, &bulk_params);
+ break;
+ default:
+ return -EINVAL;
}
return ret;
@@ -889,34 +526,31 @@ int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int handle,
void *data, unsigned int size, void *userdata,
enum vchiq_bulk_mode mode)
{
+ struct vchiq_bulk bulk_params = {};
int ret;
- while (1) {
- switch (mode) {
- case VCHIQ_BULK_MODE_NOCALLBACK:
- case VCHIQ_BULK_MODE_CALLBACK:
- ret = vchiq_bulk_xfer_callback_interruptible(instance, handle,
- (void *)data, NULL,
- size, mode, userdata,
- VCHIQ_BULK_RECEIVE);
- break;
- case VCHIQ_BULK_MODE_BLOCKING:
- ret = vchiq_blocking_bulk_transfer(instance, handle, (void *)data, size,
- VCHIQ_BULK_RECEIVE);
- break;
- default:
- return -EINVAL;
- }
-
- /*
- * vchiq_*_bulk_transfer() may return -EAGAIN, so we need
- * to implement a retry mechanism since this function is
- * supposed to block until queued
- */
- if (ret != -EAGAIN)
- break;
-
- msleep(1);
+ switch (mode) {
+ case VCHIQ_BULK_MODE_NOCALLBACK:
+ case VCHIQ_BULK_MODE_CALLBACK:
+
+ bulk_params.offset = (void *)data;
+ bulk_params.mode = mode;
+ bulk_params.size = size;
+ bulk_params.cb_data = userdata;
+ bulk_params.dir = VCHIQ_BULK_RECEIVE;
+
+ ret = vchiq_bulk_xfer_callback(instance, handle, &bulk_params);
+ break;
+ case VCHIQ_BULK_MODE_BLOCKING:
+ bulk_params.offset = (void *)data;
+ bulk_params.mode = mode;
+ bulk_params.size = size;
+ bulk_params.dir = VCHIQ_BULK_RECEIVE;
+
+ ret = vchiq_blocking_bulk_transfer(instance, handle, &bulk_params);
+ break;
+ default:
+ return -EINVAL;
}
return ret;
@@ -924,8 +558,8 @@ int vchiq_bulk_receive(struct vchiq_instance *instance, unsigned int handle,
EXPORT_SYMBOL(vchiq_bulk_receive);
static int
-vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle, void *data,
- unsigned int size, enum vchiq_bulk_dir dir)
+vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk_params)
{
struct vchiq_service *service;
struct bulk_waiter_node *waiter = NULL, *iter;
@@ -953,13 +587,14 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl
if (bulk) {
/* This thread has an outstanding bulk transfer. */
/* FIXME: why compare a dma address to a pointer? */
- if ((bulk->data != (dma_addr_t)(uintptr_t)data) || (bulk->size != size)) {
+ if ((bulk->dma_addr != (dma_addr_t)(uintptr_t)bulk_params->dma_addr) ||
+ (bulk->size != bulk_params->size)) {
/*
* This is not a retry of the previous one.
* Cancel the signal when the transfer completes.
*/
spin_lock(&service->state->bulk_waiter_spinlock);
- bulk->userdata = NULL;
+ bulk->waiter = NULL;
spin_unlock(&service->state->bulk_waiter_spinlock);
}
}
@@ -969,15 +604,16 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl
return -ENOMEM;
}
- ret = vchiq_bulk_xfer_blocking_interruptible(instance, handle, data, NULL, size,
- &waiter->bulk_waiter, dir);
+ bulk_params->waiter = &waiter->bulk_waiter;
+
+ ret = vchiq_bulk_xfer_blocking(instance, handle, bulk_params);
if ((ret != -EAGAIN) || fatal_signal_pending(current) || !waiter->bulk_waiter.bulk) {
struct vchiq_bulk *bulk = waiter->bulk_waiter.bulk;
if (bulk) {
/* Cancel the signal when the transfer completes. */
spin_lock(&service->state->bulk_waiter_spinlock);
- bulk->userdata = NULL;
+ bulk->waiter = NULL;
spin_unlock(&service->state->bulk_waiter_spinlock);
}
kfree(waiter);
@@ -996,7 +632,7 @@ vchiq_blocking_bulk_transfer(struct vchiq_instance *instance, unsigned int handl
static int
add_completion(struct vchiq_instance *instance, enum vchiq_reason reason,
struct vchiq_header *header, struct user_service *user_service,
- void *bulk_userdata)
+ void *cb_data, void __user *cb_userdata)
{
struct vchiq_completion_data_kernel *completion;
struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(instance->state->dev);
@@ -1026,7 +662,8 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason,
completion->reason = reason;
/* N.B. service_userdata is updated while processing AWAIT_COMPLETION */
completion->service_userdata = user_service->service;
- completion->bulk_userdata = bulk_userdata;
+ completion->cb_data = cb_data;
+ completion->cb_userdata = cb_userdata;
if (reason == VCHIQ_SERVICE_CLOSED) {
/*
@@ -1057,8 +694,8 @@ add_completion(struct vchiq_instance *instance, enum vchiq_reason reason,
static int
service_single_message(struct vchiq_instance *instance,
- enum vchiq_reason reason,
- struct vchiq_service *service, void *bulk_userdata)
+ enum vchiq_reason reason, struct vchiq_service *service,
+ void *cb_data, void __user *cb_userdata)
{
struct user_service *user_service;
@@ -1076,7 +713,7 @@ service_single_message(struct vchiq_instance *instance,
dev_dbg(instance->state->dev,
"arm: Inserting extra MESSAGE_AVAILABLE\n");
ret = add_completion(instance, reason, NULL, user_service,
- bulk_userdata);
+ cb_data, cb_userdata);
if (ret)
return ret;
}
@@ -1094,7 +731,8 @@ service_single_message(struct vchiq_instance *instance,
int
service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
- struct vchiq_header *header, unsigned int handle, void *bulk_userdata)
+ struct vchiq_header *header, unsigned int handle,
+ void *cb_data, void __user *cb_userdata)
{
/*
* How do we ensure the callback goes to the right client?
@@ -1133,9 +771,9 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
rcu_read_unlock();
dev_dbg(service->state->dev,
- "arm: service %p(%d,%p), reason %d, header %p, instance %p, bulk_userdata %p\n",
+ "arm: service %p(%d,%p), reason %d, header %p, instance %p, cb_data %p, cb_userdata %p\n",
user_service, service->localport, user_service->userdata,
- reason, header, instance, bulk_userdata);
+ reason, header, instance, cb_data, cb_userdata);
if (header && user_service->is_vchi) {
spin_lock(&service->state->msg_queue_spinlock);
@@ -1147,8 +785,8 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
DEBUG_COUNT(MSG_QUEUE_FULL_COUNT);
- ret = service_single_message(instance, reason,
- service, bulk_userdata);
+ ret = service_single_message(instance, reason, service,
+ cb_data, cb_userdata);
if (ret) {
DEBUG_TRACE(SERVICE_CALLBACK_LINE);
vchiq_service_put(service);
@@ -1186,7 +824,7 @@ service_callback(struct vchiq_instance *instance, enum vchiq_reason reason,
return 0;
return add_completion(instance, reason, header, user_service,
- bulk_userdata);
+ cb_data, cb_userdata);
}
void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f)
@@ -1273,7 +911,8 @@ static int
vchiq_keepalive_vchiq_callback(struct vchiq_instance *instance,
enum vchiq_reason reason,
struct vchiq_header *header,
- unsigned int service_user, void *bulk_user)
+ unsigned int service_user,
+ void *cb_data, void __user *cb_userdata)
{
dev_err(instance->state->dev, "suspend: %s: callback reason %d\n",
__func__, reason);
@@ -1715,7 +1354,6 @@ MODULE_DEVICE_TABLE(of, vchiq_of_match);
static int vchiq_probe(struct platform_device *pdev)
{
- struct device_node *fw_node;
const struct vchiq_platform_info *info;
struct vchiq_drv_mgmt *mgmt;
int ret;
@@ -1724,8 +1362,8 @@ static int vchiq_probe(struct platform_device *pdev)
if (!info)
return -EINVAL;
- fw_node = of_find_compatible_node(NULL, NULL,
- "raspberrypi,bcm2835-firmware");
+ struct device_node *fw_node __free(device_node) =
+ of_find_compatible_node(NULL, NULL, "raspberrypi,bcm2835-firmware");
if (!fw_node) {
dev_err(&pdev->dev, "Missing firmware node\n");
return -ENOENT;
@@ -1736,7 +1374,6 @@ static int vchiq_probe(struct platform_device *pdev)
return -ENOMEM;
mgmt->fw = devm_rpi_firmware_get(&pdev->dev, fw_node);
- of_node_put(fw_node);
if (!mgmt->fw)
return -EPROBE_DEFER;
@@ -1744,8 +1381,10 @@ static int vchiq_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mgmt);
ret = vchiq_platform_init(pdev, &mgmt->state);
- if (ret)
- goto failed_platform_init;
+ if (ret) {
+ dev_err(&pdev->dev, "arm: Could not initialize vchiq platform\n");
+ return ret;
+ }
vchiq_debugfs_init(&mgmt->state);
@@ -1759,18 +1398,13 @@ static int vchiq_probe(struct platform_device *pdev)
ret = vchiq_register_chrdev(&pdev->dev);
if (ret) {
dev_err(&pdev->dev, "arm: Failed to initialize vchiq cdev\n");
- goto error_exit;
+ return ret;
}
bcm2835_audio = vchiq_device_register(&pdev->dev, "bcm2835-audio");
bcm2835_camera = vchiq_device_register(&pdev->dev, "bcm2835-camera");
return 0;
-
-failed_platform_init:
- dev_err(&pdev->dev, "arm: Could not initialize vchiq platform\n");
-error_exit:
- return ret;
}
static void vchiq_remove(struct platform_device *pdev)
@@ -1797,7 +1431,7 @@ static struct platform_driver vchiq_driver = {
.of_match_table = vchiq_of_match,
},
.probe = vchiq_probe,
- .remove_new = vchiq_remove,
+ .remove = vchiq_remove,
};
static int __init vchiq_driver_init(void)
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
index b402aac333d9..e32b02f99024 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_arm.h
@@ -155,7 +155,8 @@ static inline int vchiq_register_chrdev(struct device *parent) { return 0; }
extern int
service_callback(struct vchiq_instance *vchiq_instance, enum vchiq_reason reason,
- struct vchiq_header *header, unsigned int handle, void *bulk_userdata);
+ struct vchiq_header *header, unsigned int handle,
+ void *cb_data, void __user *cb_userdata);
extern void
free_bulk_waiter(struct vchiq_instance *instance);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
index 1f94db6e0cd9..8d5795db4f39 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.c
@@ -5,6 +5,8 @@
#include <linux/completion.h>
#include <linux/mutex.h>
#include <linux/bitops.h>
+#include <linux/io.h>
+#include <linux/highmem.h>
#include <linux/kthread.h>
#include <linux/wait.h>
#include <linux/delay.h>
@@ -61,12 +63,16 @@
#define MAKE_REMOTE_USE (VCHIQ_MSG_REMOTE_USE << TYPE_SHIFT)
#define MAKE_REMOTE_USE_ACTIVE (VCHIQ_MSG_REMOTE_USE_ACTIVE << TYPE_SHIFT)
+#define PAGELIST_WRITE 0
+#define PAGELIST_READ 1
+#define PAGELIST_READ_WITH_FRAGMENTS 2
+
+#define BELL2 0x08
+
/* Ensure the fields are wide enough */
-static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX))
- == 0);
+static_assert(VCHIQ_MSG_SRCPORT(VCHIQ_MAKE_MSG(0, 0, VCHIQ_PORT_MAX)) == 0);
static_assert(VCHIQ_MSG_TYPE(VCHIQ_MAKE_MSG(0, VCHIQ_PORT_MAX, 0)) == 0);
-static_assert((unsigned int)VCHIQ_PORT_MAX <
- (unsigned int)VCHIQ_PORT_FREE);
+static_assert((unsigned int)VCHIQ_PORT_MAX < (unsigned int)VCHIQ_PORT_FREE);
#define VCHIQ_MSGID_PADDING VCHIQ_MAKE_MSG(VCHIQ_MSG_PADDING, 0, 0)
#define VCHIQ_MSGID_CLAIMED 0x40000000
@@ -449,15 +455,26 @@ mark_service_closing(struct vchiq_service *service)
static inline int
make_service_callback(struct vchiq_service *service, enum vchiq_reason reason,
- struct vchiq_header *header, void *bulk_userdata)
+ struct vchiq_header *header, struct vchiq_bulk *bulk)
{
+ void *cb_data = NULL;
+ void __user *cb_userdata = NULL;
int status;
- dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %pK, %pK)\n",
+ /*
+ * If a bulk transfer is in progress, pass bulk->cb_*data to the
+ * callback function.
+ */
+ if (bulk) {
+ cb_data = bulk->cb_data;
+ cb_userdata = bulk->cb_userdata;
+ }
+
+ dev_dbg(service->state->dev, "core: %d: callback:%d (%s, %pK, %pK %pK)\n",
service->state->id, service->localport, reason_names[reason],
- header, bulk_userdata);
+ header, cb_data, cb_userdata);
status = service->base.callback(service->instance, reason, header, service->handle,
- bulk_userdata);
+ cb_data, cb_userdata);
if (status && (status != -EAGAIN)) {
dev_warn(service->state->dev,
"core: %d: ignoring ERROR from callback to service %x\n",
@@ -526,6 +543,25 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
return ret;
}
+static void
+remote_event_signal(struct vchiq_state *state, struct remote_event *event)
+{
+ struct vchiq_drv_mgmt *mgmt = dev_get_drvdata(state->dev);
+
+ /*
+ * Ensure that all writes to shared data structures have completed
+ * before signalling the peer.
+ */
+ wmb();
+
+ event->fired = 1;
+
+ dsb(sy); /* data barrier operation */
+
+ if (event->armed)
+ writel(0, mgmt->regs + BELL2); /* trigger vc interrupt */
+}
+
/*
* Acknowledge that the event has been signalled, and wake any waiters. Usually
* called as a result of the doorbell being rung.
@@ -911,6 +947,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
struct vchiq_service_quota *quota = NULL;
struct vchiq_header *header;
int type = VCHIQ_MSG_TYPE(msgid);
+ int svc_fourcc;
size_t stride;
@@ -922,7 +959,7 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
if (!(flags & QMFLAGS_NO_MUTEX_LOCK) &&
mutex_lock_killable(&state->slot_mutex))
- return -EAGAIN;
+ return -EINTR;
if (type == VCHIQ_MSG_DATA) {
int tx_end_index;
@@ -962,8 +999,8 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
spin_unlock(&state->quota_spinlock);
mutex_unlock(&state->slot_mutex);
- if (wait_for_completion_interruptible(&state->data_quota_event))
- return -EAGAIN;
+ if (wait_for_completion_killable(&state->data_quota_event))
+ return -EINTR;
mutex_lock(&state->slot_mutex);
spin_lock(&state->quota_spinlock);
@@ -986,12 +1023,12 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
quota->message_use_count, quota->slot_use_count);
VCHIQ_SERVICE_STATS_INC(service, quota_stalls);
mutex_unlock(&state->slot_mutex);
- if (wait_for_completion_interruptible(&quota->quota_event))
- return -EAGAIN;
+ if (wait_for_completion_killable(&quota->quota_event))
+ return -EINTR;
if (service->closing)
return -EHOSTDOWN;
if (mutex_lock_killable(&state->slot_mutex))
- return -EAGAIN;
+ return -EINTR;
if (service->srvstate != VCHIQ_SRVSTATE_OPEN) {
/* The service has been closed */
mutex_unlock(&state->slot_mutex);
@@ -1103,17 +1140,13 @@ queue_message(struct vchiq_state *state, struct vchiq_service *service,
header->msgid = msgid;
header->size = size;
- {
- int svc_fourcc;
-
- svc_fourcc = service
- ? service->base.fourcc
- : VCHIQ_MAKE_FOURCC('?', '?', '?', '?');
+ svc_fourcc = service ? service->base.fourcc
+ : VCHIQ_MAKE_FOURCC('?', '?', '?', '?');
- dev_dbg(state->dev, "core_msg: Sent Msg %s(%u) to %p4cc s:%u d:%d len:%zu\n",
- msg_type_str(VCHIQ_MSG_TYPE(msgid)), VCHIQ_MSG_TYPE(msgid),
- &svc_fourcc, VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid), size);
- }
+ dev_dbg(state->dev, "core_msg: Sent Msg %s(%u) to %p4cc s:%u d:%d len:%zu\n",
+ msg_type_str(VCHIQ_MSG_TYPE(msgid)),
+ VCHIQ_MSG_TYPE(msgid), &svc_fourcc,
+ VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid), size);
/* Make sure the new header is visible to the peer. */
wmb();
@@ -1175,9 +1208,8 @@ queue_message_sync(struct vchiq_state *state, struct vchiq_service *service,
state->id, msg_type_str(VCHIQ_MSG_TYPE(msgid)), header, size,
VCHIQ_MSG_SRCPORT(msgid), VCHIQ_MSG_DSTPORT(msgid));
- callback_result =
- copy_message_data(copy_callback, context,
- header->data, size);
+ callback_result = copy_message_data(copy_callback, context,
+ header->data, size);
if (callback_result < 0) {
mutex_unlock(&state->slot_mutex);
@@ -1288,6 +1320,42 @@ get_bulk_reason(struct vchiq_bulk *bulk)
return VCHIQ_BULK_RECEIVE_DONE;
}
+static int service_notify_bulk(struct vchiq_service *service,
+ struct vchiq_bulk *bulk)
+{
+ if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) {
+ if (bulk->dir == VCHIQ_BULK_TRANSMIT) {
+ VCHIQ_SERVICE_STATS_INC(service, bulk_tx_count);
+ VCHIQ_SERVICE_STATS_ADD(service, bulk_tx_bytes,
+ bulk->actual);
+ } else {
+ VCHIQ_SERVICE_STATS_INC(service, bulk_rx_count);
+ VCHIQ_SERVICE_STATS_ADD(service, bulk_rx_bytes,
+ bulk->actual);
+ }
+ } else {
+ VCHIQ_SERVICE_STATS_INC(service, bulk_aborted_count);
+ }
+
+ if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) {
+ struct bulk_waiter *waiter;
+
+ spin_lock(&service->state->bulk_waiter_spinlock);
+ waiter = bulk->waiter;
+ if (waiter) {
+ waiter->actual = bulk->actual;
+ complete(&waiter->event);
+ }
+ spin_unlock(&service->state->bulk_waiter_spinlock);
+ } else if (bulk->mode == VCHIQ_BULK_MODE_CALLBACK) {
+ enum vchiq_reason reason = get_bulk_reason(bulk);
+
+ return make_service_callback(service, reason, NULL, bulk);
+ }
+
+ return 0;
+}
+
/* Called by the slot handler - don't hold the bulk mutex */
static int
notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue,
@@ -1311,38 +1379,10 @@ notify_bulks(struct vchiq_service *service, struct vchiq_bulk_queue *queue,
* Only generate callbacks for non-dummy bulk
* requests, and non-terminated services
*/
- if (bulk->data && service->instance) {
- if (bulk->actual != VCHIQ_BULK_ACTUAL_ABORTED) {
- if (bulk->dir == VCHIQ_BULK_TRANSMIT) {
- VCHIQ_SERVICE_STATS_INC(service, bulk_tx_count);
- VCHIQ_SERVICE_STATS_ADD(service, bulk_tx_bytes,
- bulk->actual);
- } else {
- VCHIQ_SERVICE_STATS_INC(service, bulk_rx_count);
- VCHIQ_SERVICE_STATS_ADD(service, bulk_rx_bytes,
- bulk->actual);
- }
- } else {
- VCHIQ_SERVICE_STATS_INC(service, bulk_aborted_count);
- }
- if (bulk->mode == VCHIQ_BULK_MODE_BLOCKING) {
- struct bulk_waiter *waiter;
-
- spin_lock(&service->state->bulk_waiter_spinlock);
- waiter = bulk->userdata;
- if (waiter) {
- waiter->actual = bulk->actual;
- complete(&waiter->event);
- }
- spin_unlock(&service->state->bulk_waiter_spinlock);
- } else if (bulk->mode == VCHIQ_BULK_MODE_CALLBACK) {
- enum vchiq_reason reason =
- get_bulk_reason(bulk);
- status = make_service_callback(service, reason, NULL,
- bulk->userdata);
- if (status == -EAGAIN)
- break;
- }
+ if (bulk->dma_addr && service->instance) {
+ status = service_notify_bulk(service, bulk);
+ if (status == -EAGAIN)
+ break;
}
queue->remove++;
@@ -1415,6 +1455,331 @@ poll_services(struct vchiq_state *state)
poll_services_of_group(state, group);
}
+static void
+cleanup_pagelistinfo(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo)
+{
+ if (pagelistinfo->scatterlist_mapped) {
+ dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist,
+ pagelistinfo->num_pages, pagelistinfo->dma_dir);
+ }
+
+ if (pagelistinfo->pages_need_release)
+ unpin_user_pages(pagelistinfo->pages, pagelistinfo->num_pages);
+
+ dma_free_coherent(instance->state->dev, pagelistinfo->pagelist_buffer_size,
+ pagelistinfo->pagelist, pagelistinfo->dma_addr);
+}
+
+static inline bool
+is_adjacent_block(u32 *addrs, dma_addr_t addr, unsigned int k)
+{
+ u32 tmp;
+
+ if (!k)
+ return false;
+
+ tmp = (addrs[k - 1] & PAGE_MASK) +
+ (((addrs[k - 1] & ~PAGE_MASK) + 1) << PAGE_SHIFT);
+
+ return tmp == (addr & PAGE_MASK);
+}
+
+/* There is a potential problem with partial cache lines (pages?)
+ * at the ends of the block when reading. If the CPU accessed anything in
+ * the same line (page?) then it may have pulled old data into the cache,
+ * obscuring the new data underneath. We can solve this by transferring the
+ * partial cache lines separately, and allowing the ARM to copy into the
+ * cached area.
+ */
+static struct vchiq_pagelist_info *
+create_pagelist(struct vchiq_instance *instance, struct vchiq_bulk *bulk)
+{
+ struct vchiq_drv_mgmt *drv_mgmt;
+ struct pagelist *pagelist;
+ struct vchiq_pagelist_info *pagelistinfo;
+ struct page **pages;
+ u32 *addrs;
+ unsigned int num_pages, offset, i, k;
+ int actual_pages;
+ size_t pagelist_size;
+ struct scatterlist *scatterlist, *sg;
+ int dma_buffers;
+ unsigned int cache_line_size;
+ dma_addr_t dma_addr;
+ size_t count = bulk->size;
+ unsigned short type = (bulk->dir == VCHIQ_BULK_RECEIVE)
+ ? PAGELIST_READ : PAGELIST_WRITE;
+
+ if (count >= INT_MAX - PAGE_SIZE)
+ return NULL;
+
+ drv_mgmt = dev_get_drvdata(instance->state->dev);
+
+ if (bulk->offset)
+ offset = (uintptr_t)bulk->offset & (PAGE_SIZE - 1);
+ else
+ offset = (uintptr_t)bulk->uoffset & (PAGE_SIZE - 1);
+ num_pages = DIV_ROUND_UP(count + offset, PAGE_SIZE);
+
+ if ((size_t)num_pages > (SIZE_MAX - sizeof(struct pagelist) -
+ sizeof(struct vchiq_pagelist_info)) /
+ (sizeof(u32) + sizeof(pages[0]) +
+ sizeof(struct scatterlist)))
+ return NULL;
+
+ pagelist_size = sizeof(struct pagelist) +
+ (num_pages * sizeof(u32)) +
+ (num_pages * sizeof(pages[0]) +
+ (num_pages * sizeof(struct scatterlist))) +
+ sizeof(struct vchiq_pagelist_info);
+
+ /* Allocate enough storage to hold the page pointers and the page
+ * list
+ */
+ pagelist = dma_alloc_coherent(instance->state->dev, pagelist_size, &dma_addr,
+ GFP_KERNEL);
+
+ dev_dbg(instance->state->dev, "arm: %pK\n", pagelist);
+
+ if (!pagelist)
+ return NULL;
+
+ addrs = pagelist->addrs;
+ pages = (struct page **)(addrs + num_pages);
+ scatterlist = (struct scatterlist *)(pages + num_pages);
+ pagelistinfo = (struct vchiq_pagelist_info *)
+ (scatterlist + num_pages);
+
+ pagelist->length = count;
+ pagelist->type = type;
+ pagelist->offset = offset;
+
+ /* Populate the fields of the pagelistinfo structure */
+ pagelistinfo->pagelist = pagelist;
+ pagelistinfo->pagelist_buffer_size = pagelist_size;
+ pagelistinfo->dma_addr = dma_addr;
+ pagelistinfo->dma_dir = (type == PAGELIST_WRITE) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ pagelistinfo->num_pages = num_pages;
+ pagelistinfo->pages_need_release = 0;
+ pagelistinfo->pages = pages;
+ pagelistinfo->scatterlist = scatterlist;
+ pagelistinfo->scatterlist_mapped = 0;
+
+ if (bulk->offset) {
+ unsigned long length = count;
+ unsigned int off = offset;
+
+ for (actual_pages = 0; actual_pages < num_pages;
+ actual_pages++) {
+ struct page *pg =
+ vmalloc_to_page(((unsigned int *)bulk->offset +
+ (actual_pages * PAGE_SIZE)));
+ size_t bytes = PAGE_SIZE - off;
+
+ if (!pg) {
+ cleanup_pagelistinfo(instance, pagelistinfo);
+ return NULL;
+ }
+
+ if (bytes > length)
+ bytes = length;
+ pages[actual_pages] = pg;
+ length -= bytes;
+ off = 0;
+ }
+ /* do not try and release vmalloc pages */
+ } else {
+ actual_pages =
+ pin_user_pages_fast((unsigned long)bulk->uoffset & PAGE_MASK, num_pages,
+ type == PAGELIST_READ, pages);
+
+ if (actual_pages != num_pages) {
+ dev_dbg(instance->state->dev, "arm: Only %d/%d pages locked\n",
+ actual_pages, num_pages);
+
+ /* This is probably due to the process being killed */
+ if (actual_pages > 0)
+ unpin_user_pages(pages, actual_pages);
+ cleanup_pagelistinfo(instance, pagelistinfo);
+ return NULL;
+ }
+ /* release user pages */
+ pagelistinfo->pages_need_release = 1;
+ }
+
+ /*
+ * Initialize the scatterlist so that the magic cookie
+ * is filled if debugging is enabled
+ */
+ sg_init_table(scatterlist, num_pages);
+ /* Now set the pages for each scatterlist */
+ for (i = 0; i < num_pages; i++) {
+ unsigned int len = PAGE_SIZE - offset;
+
+ if (len > count)
+ len = count;
+ sg_set_page(scatterlist + i, pages[i], len, offset);
+ offset = 0;
+ count -= len;
+ }
+
+ dma_buffers = dma_map_sg(instance->state->dev,
+ scatterlist,
+ num_pages,
+ pagelistinfo->dma_dir);
+
+ if (dma_buffers == 0) {
+ cleanup_pagelistinfo(instance, pagelistinfo);
+ return NULL;
+ }
+
+ pagelistinfo->scatterlist_mapped = 1;
+
+ /* Combine adjacent blocks for performance */
+ k = 0;
+ for_each_sg(scatterlist, sg, dma_buffers, i) {
+ unsigned int len = sg_dma_len(sg);
+ dma_addr_t addr = sg_dma_address(sg);
+
+ /* Note: addrs is the address + page_count - 1
+ * The firmware expects blocks after the first to be page-
+ * aligned and a multiple of the page size
+ */
+ WARN_ON(len == 0);
+ WARN_ON(i && (i != (dma_buffers - 1)) && (len & ~PAGE_MASK));
+ WARN_ON(i && (addr & ~PAGE_MASK));
+ if (is_adjacent_block(addrs, addr, k))
+ addrs[k - 1] += ((len + PAGE_SIZE - 1) >> PAGE_SHIFT);
+ else
+ addrs[k++] = (addr & PAGE_MASK) |
+ (((len + PAGE_SIZE - 1) >> PAGE_SHIFT) - 1);
+ }
+
+ /* Partial cache lines (fragments) require special measures */
+ cache_line_size = drv_mgmt->info->cache_line_size;
+ if ((type == PAGELIST_READ) &&
+ ((pagelist->offset & (cache_line_size - 1)) ||
+ ((pagelist->offset + pagelist->length) & (cache_line_size - 1)))) {
+ char *fragments;
+
+ if (down_interruptible(&drv_mgmt->free_fragments_sema)) {
+ cleanup_pagelistinfo(instance, pagelistinfo);
+ return NULL;
+ }
+
+ WARN_ON(!drv_mgmt->free_fragments);
+
+ down(&drv_mgmt->free_fragments_mutex);
+ fragments = drv_mgmt->free_fragments;
+ WARN_ON(!fragments);
+ drv_mgmt->free_fragments = *(char **)drv_mgmt->free_fragments;
+ up(&drv_mgmt->free_fragments_mutex);
+ pagelist->type = PAGELIST_READ_WITH_FRAGMENTS +
+ (fragments - drv_mgmt->fragments_base) / drv_mgmt->fragments_size;
+ }
+
+ return pagelistinfo;
+}
+
+static void
+free_pagelist(struct vchiq_instance *instance, struct vchiq_pagelist_info *pagelistinfo,
+ int actual)
+{
+ struct vchiq_drv_mgmt *drv_mgmt;
+ struct pagelist *pagelist = pagelistinfo->pagelist;
+ struct page **pages = pagelistinfo->pages;
+ unsigned int num_pages = pagelistinfo->num_pages;
+ unsigned int cache_line_size;
+
+ dev_dbg(instance->state->dev, "arm: %pK, %d\n", pagelistinfo->pagelist, actual);
+
+ drv_mgmt = dev_get_drvdata(instance->state->dev);
+
+ /*
+ * NOTE: dma_unmap_sg must be called before the
+ * cpu can touch any of the data/pages.
+ */
+ dma_unmap_sg(instance->state->dev, pagelistinfo->scatterlist,
+ pagelistinfo->num_pages, pagelistinfo->dma_dir);
+ pagelistinfo->scatterlist_mapped = 0;
+
+ /* Deal with any partial cache lines (fragments) */
+ cache_line_size = drv_mgmt->info->cache_line_size;
+ if (pagelist->type >= PAGELIST_READ_WITH_FRAGMENTS && drv_mgmt->fragments_base) {
+ char *fragments = drv_mgmt->fragments_base +
+ (pagelist->type - PAGELIST_READ_WITH_FRAGMENTS) *
+ drv_mgmt->fragments_size;
+ int head_bytes, tail_bytes;
+
+ head_bytes = (cache_line_size - pagelist->offset) &
+ (cache_line_size - 1);
+ tail_bytes = (pagelist->offset + actual) &
+ (cache_line_size - 1);
+
+ if ((actual >= 0) && (head_bytes != 0)) {
+ if (head_bytes > actual)
+ head_bytes = actual;
+
+ memcpy_to_page(pages[0], pagelist->offset,
+ fragments, head_bytes);
+ }
+ if ((actual >= 0) && (head_bytes < actual) &&
+ (tail_bytes != 0))
+ memcpy_to_page(pages[num_pages - 1],
+ (pagelist->offset + actual) &
+ (PAGE_SIZE - 1) & ~(cache_line_size - 1),
+ fragments + cache_line_size,
+ tail_bytes);
+
+ down(&drv_mgmt->free_fragments_mutex);
+ *(char **)fragments = drv_mgmt->free_fragments;
+ drv_mgmt->free_fragments = fragments;
+ up(&drv_mgmt->free_fragments_mutex);
+ up(&drv_mgmt->free_fragments_sema);
+ }
+
+ /* Need to mark all the pages dirty. */
+ if (pagelist->type != PAGELIST_WRITE &&
+ pagelistinfo->pages_need_release) {
+ unsigned int i;
+
+ for (i = 0; i < num_pages; i++)
+ set_page_dirty(pages[i]);
+ }
+
+ cleanup_pagelistinfo(instance, pagelistinfo);
+}
+
+static int
+vchiq_prepare_bulk_data(struct vchiq_instance *instance, struct vchiq_bulk *bulk)
+{
+ struct vchiq_pagelist_info *pagelistinfo;
+
+ pagelistinfo = create_pagelist(instance, bulk);
+
+ if (!pagelistinfo)
+ return -ENOMEM;
+
+ bulk->dma_addr = pagelistinfo->dma_addr;
+
+ /*
+ * Store the pagelistinfo address in remote_data,
+ * which isn't used by the slave.
+ */
+ bulk->remote_data = pagelistinfo;
+
+ return 0;
+}
+
+static void
+vchiq_complete_bulk(struct vchiq_instance *instance, struct vchiq_bulk *bulk)
+{
+ if (bulk && bulk->remote_data && bulk->actual)
+ free_pagelist(instance, (struct vchiq_pagelist_info *)bulk->remote_data,
+ bulk->actual);
+}
+
/* Called with the bulk_mutex held */
static void
abort_outstanding_bulks(struct vchiq_service *service,
@@ -1452,7 +1817,7 @@ abort_outstanding_bulks(struct vchiq_service *service,
service->remoteport, bulk->size, bulk->remote_size);
} else {
/* fabricate a matching dummy bulk */
- bulk->data = 0;
+ bulk->dma_addr = 0;
bulk->size = 0;
bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED;
bulk->dir = is_tx ? VCHIQ_BULK_TRANSMIT :
@@ -1468,8 +1833,10 @@ static int
parse_open(struct vchiq_state *state, struct vchiq_header *header)
{
const struct vchiq_open_payload *payload;
+ struct vchiq_openack_payload ack_payload;
struct vchiq_service *service = NULL;
int msgid, size;
+ int openack_id;
unsigned int localport, remoteport, fourcc;
short version, version_min;
@@ -1504,34 +1871,36 @@ parse_open(struct vchiq_state *state, struct vchiq_header *header)
}
service->peer_version = version;
- if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) {
- struct vchiq_openack_payload ack_payload = {
- service->version
- };
- int openack_id = MAKE_OPENACK(service->localport, remoteport);
+ if (service->srvstate != VCHIQ_SRVSTATE_LISTENING)
+ goto done;
- if (state->version_common <
- VCHIQ_VERSION_SYNCHRONOUS_MODE)
- service->sync = 0;
+ ack_payload.version = service->version;
+ openack_id = MAKE_OPENACK(service->localport, remoteport);
- /* Acknowledge the OPEN */
- if (service->sync) {
- if (queue_message_sync(state, NULL, openack_id, memcpy_copy_callback,
- &ack_payload, sizeof(ack_payload)) == -EAGAIN)
- goto bail_not_ready;
+ if (state->version_common < VCHIQ_VERSION_SYNCHRONOUS_MODE)
+ service->sync = 0;
- /* The service is now open */
- set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC);
- } else {
- if (queue_message(state, NULL, openack_id, memcpy_copy_callback,
- &ack_payload, sizeof(ack_payload), 0) == -EAGAIN)
- goto bail_not_ready;
+ /* Acknowledge the OPEN */
+ if (service->sync) {
+ if (queue_message_sync(state, NULL, openack_id,
+ memcpy_copy_callback,
+ &ack_payload,
+ sizeof(ack_payload)) == -EAGAIN)
+ goto bail_not_ready;
- /* The service is now open */
- set_service_state(service, VCHIQ_SRVSTATE_OPEN);
- }
+ /* The service is now open */
+ set_service_state(service, VCHIQ_SRVSTATE_OPENSYNC);
+ } else {
+ if (queue_message(state, NULL, openack_id,
+ memcpy_copy_callback, &ack_payload,
+ sizeof(ack_payload), 0) == -EINTR)
+ goto bail_not_ready;
+
+ /* The service is now open */
+ set_service_state(service, VCHIQ_SRVSTATE_OPEN);
}
+done:
/* Success - the message has been dealt with */
vchiq_service_put(service);
return 1;
@@ -1539,7 +1908,7 @@ parse_open(struct vchiq_state *state, struct vchiq_header *header)
fail_open:
/* No available service, or an invalid request - send a CLOSE */
if (queue_message(state, NULL, MAKE_CLOSE(0, VCHIQ_MSG_SRCPORT(msgid)),
- NULL, NULL, 0, 0) == -EAGAIN)
+ NULL, NULL, 0, 0) == -EINTR)
goto bail_not_ready;
return 1;
@@ -1753,7 +2122,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
dev_dbg(state->dev, "core: %d: prs %s@%pK (%d->%d) %x@%pad\n",
state->id, msg_type_str(type), header, remoteport,
- localport, bulk->actual, &bulk->data);
+ localport, bulk->actual, &bulk->dma_addr);
dev_dbg(state->dev, "core: %d: prs:%d %cx li=%x ri=%x p=%x\n",
state->id, localport,
@@ -1786,7 +2155,7 @@ parse_message(struct vchiq_state *state, struct vchiq_header *header)
if (state->conn_state != VCHIQ_CONNSTATE_PAUSE_SENT) {
/* Send a PAUSE in response */
if (queue_message(state, NULL, MAKE_PAUSE, NULL, NULL, 0,
- QMFLAGS_NO_MUTEX_UNLOCK) == -EAGAIN)
+ QMFLAGS_NO_MUTEX_UNLOCK) == -EINTR)
goto bail_not_ready;
}
/* At this point slot_mutex is held */
@@ -1903,7 +2272,7 @@ handle_poll(struct vchiq_state *state)
case VCHIQ_CONNSTATE_PAUSING:
if (queue_message(state, NULL, MAKE_PAUSE, NULL, NULL, 0,
- QMFLAGS_NO_MUTEX_UNLOCK) != -EAGAIN) {
+ QMFLAGS_NO_MUTEX_UNLOCK) != -EINTR) {
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_PAUSE_SENT);
} else {
/* Retry later */
@@ -1913,7 +2282,7 @@ handle_poll(struct vchiq_state *state)
case VCHIQ_CONNSTATE_RESUMING:
if (queue_message(state, NULL, MAKE_RESUME, NULL, NULL, 0,
- QMFLAGS_NO_MUTEX_LOCK) != -EAGAIN) {
+ QMFLAGS_NO_MUTEX_LOCK) != -EINTR) {
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTED);
} else {
/*
@@ -2662,56 +3031,58 @@ close_service_complete(struct vchiq_service *service, int failstate)
* returned to user context.
*/
static int
-vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service,
- void *offset, void __user *uoffset,
- int size, void *userdata,
- enum vchiq_bulk_mode mode,
- enum vchiq_bulk_dir dir)
+vchiq_bulk_xfer_queue_msg_killable(struct vchiq_service *service,
+ struct vchiq_bulk *bulk_params)
{
struct vchiq_bulk_queue *queue;
struct bulk_waiter *bulk_waiter = NULL;
struct vchiq_bulk *bulk;
struct vchiq_state *state = service->state;
- const char dir_char = (dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r';
- const int dir_msgtype = (dir == VCHIQ_BULK_TRANSMIT) ?
+ const char dir_char = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ? 't' : 'r';
+ const int dir_msgtype = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ?
VCHIQ_MSG_BULK_TX : VCHIQ_MSG_BULK_RX;
int status = -EINVAL;
int payload[2];
- if (mode == VCHIQ_BULK_MODE_BLOCKING) {
- bulk_waiter = userdata;
+ if (bulk_params->mode == VCHIQ_BULK_MODE_BLOCKING) {
+ bulk_waiter = bulk_params->waiter;
init_completion(&bulk_waiter->event);
bulk_waiter->actual = 0;
bulk_waiter->bulk = NULL;
}
- queue = (dir == VCHIQ_BULK_TRANSMIT) ?
+ queue = (bulk_params->dir == VCHIQ_BULK_TRANSMIT) ?
&service->bulk_tx : &service->bulk_rx;
if (mutex_lock_killable(&service->bulk_mutex))
- return -EAGAIN;
+ return -EINTR;
if (queue->local_insert == queue->remove + VCHIQ_NUM_SERVICE_BULKS) {
VCHIQ_SERVICE_STATS_INC(service, bulk_stalls);
do {
mutex_unlock(&service->bulk_mutex);
- if (wait_for_completion_interruptible(&service->bulk_remove_event))
- return -EAGAIN;
+ if (wait_for_completion_killable(&service->bulk_remove_event))
+ return -EINTR;
if (mutex_lock_killable(&service->bulk_mutex))
- return -EAGAIN;
+ return -EINTR;
} while (queue->local_insert == queue->remove +
VCHIQ_NUM_SERVICE_BULKS);
}
bulk = &queue->bulks[BULK_INDEX(queue->local_insert)];
- bulk->mode = mode;
- bulk->dir = dir;
- bulk->userdata = userdata;
- bulk->size = size;
+ /* Initiliaze the 'bulk' slot with bulk parameters passed in. */
+ bulk->mode = bulk_params->mode;
+ bulk->dir = bulk_params->dir;
+ bulk->waiter = bulk_params->waiter;
+ bulk->cb_data = bulk_params->cb_data;
+ bulk->cb_userdata = bulk_params->cb_userdata;
+ bulk->size = bulk_params->size;
+ bulk->offset = bulk_params->offset;
+ bulk->uoffset = bulk_params->uoffset;
bulk->actual = VCHIQ_BULK_ACTUAL_ABORTED;
- if (vchiq_prepare_bulk_data(service->instance, bulk, offset, uoffset, size, dir))
+ if (vchiq_prepare_bulk_data(service->instance, bulk))
goto unlock_error_exit;
/*
@@ -2722,21 +3093,21 @@ vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service,
dev_dbg(state->dev, "core: %d: bt (%d->%d) %cx %x@%pad %pK\n",
state->id, service->localport, service->remoteport,
- dir_char, size, &bulk->data, userdata);
+ dir_char, bulk->size, &bulk->dma_addr, bulk->cb_data);
/*
* The slot mutex must be held when the service is being closed, so
* claim it here to ensure that isn't happening
*/
if (mutex_lock_killable(&state->slot_mutex)) {
- status = -EAGAIN;
+ status = -EINTR;
goto cancel_bulk_error_exit;
}
if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
goto unlock_both_error_exit;
- payload[0] = lower_32_bits(bulk->data);
+ payload[0] = lower_32_bits(bulk->dma_addr);
payload[1] = bulk->size;
status = queue_message(state,
NULL,
@@ -2761,13 +3132,13 @@ vchiq_bulk_xfer_queue_msg_interruptible(struct vchiq_service *service,
state->id, service->localport, dir_char, queue->local_insert,
queue->remote_insert, queue->process);
- if (bulk_waiter) {
- bulk_waiter->bulk = bulk;
- if (wait_for_completion_interruptible(&bulk_waiter->event))
- status = -EAGAIN;
- else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
- status = -EINVAL;
- }
+ if (bulk_waiter) {
+ bulk_waiter->bulk = bulk;
+ if (wait_for_completion_killable(&bulk_waiter->event))
+ status = -EINTR;
+ else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
+ status = -EINVAL;
+ }
return status;
@@ -2803,19 +3174,21 @@ vchiq_close_service_internal(struct vchiq_service *service, int close_recvd)
if (close_recvd) {
dev_err(state->dev, "core: (1) called in state %s\n",
srvstate_names[service->srvstate]);
- } else if (is_server) {
- if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) {
- status = -EINVAL;
- } else {
- service->client_id = 0;
- service->remoteport = VCHIQ_PORT_FREE;
- if (service->srvstate == VCHIQ_SRVSTATE_CLOSEWAIT)
- set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
- }
- complete(&service->remove_event);
- } else {
+ break;
+ } else if (!is_server) {
vchiq_free_service_internal(service);
+ break;
+ }
+
+ if (service->srvstate == VCHIQ_SRVSTATE_LISTENING) {
+ status = -EINVAL;
+ } else {
+ service->client_id = 0;
+ service->remoteport = VCHIQ_PORT_FREE;
+ if (service->srvstate == VCHIQ_SRVSTATE_CLOSEWAIT)
+ set_service_state(service, VCHIQ_SRVSTATE_LISTENING);
}
+ complete(&service->remove_event);
break;
case VCHIQ_SRVSTATE_OPENING:
if (close_recvd) {
@@ -2945,6 +3318,7 @@ int
vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instance)
{
struct vchiq_service *service;
+ int status = 0;
int i;
/* Find all services registered to this client and enable them. */
@@ -2956,9 +3330,10 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc
}
if (state->conn_state == VCHIQ_CONNSTATE_DISCONNECTED) {
- if (queue_message(state, NULL, MAKE_CONNECT, NULL, NULL, 0,
- QMFLAGS_IS_BLOCKING) == -EAGAIN)
- return -EAGAIN;
+ status = queue_message(state, NULL, MAKE_CONNECT, NULL, NULL, 0,
+ QMFLAGS_IS_BLOCKING);
+ if (status)
+ return status;
vchiq_set_conn_state(state, VCHIQ_CONNSTATE_CONNECTING);
}
@@ -2971,7 +3346,7 @@ vchiq_connect_internal(struct vchiq_state *state, struct vchiq_instance *instanc
complete(&state->connect);
}
- return 0;
+ return status;
}
void
@@ -3105,12 +3480,10 @@ vchiq_remove_service(struct vchiq_instance *instance, unsigned int handle)
}
int
-vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned int handle,
- void *offset, void __user *uoffset, int size,
- void __user *userdata, enum vchiq_bulk_dir dir)
+vchiq_bulk_xfer_blocking(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk_params)
{
struct vchiq_service *service = find_service_by_handle(instance, handle);
- enum vchiq_bulk_mode mode = VCHIQ_BULK_MODE_BLOCKING;
int status = -EINVAL;
if (!service)
@@ -3119,15 +3492,13 @@ vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned
if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
goto error_exit;
- if (!offset && !uoffset)
+ if (!bulk_params->offset && !bulk_params->uoffset)
goto error_exit;
if (vchiq_check_service(service))
goto error_exit;
-
- status = vchiq_bulk_xfer_queue_msg_interruptible(service, offset, uoffset, size,
- userdata, mode, dir);
+ status = vchiq_bulk_xfer_queue_msg_killable(service, bulk_params);
error_exit:
vchiq_service_put(service);
@@ -3136,10 +3507,8 @@ error_exit:
}
int
-vchiq_bulk_xfer_callback_interruptible(struct vchiq_instance *instance, unsigned int handle,
- void *offset, void __user *uoffset, int size,
- enum vchiq_bulk_mode mode, void *userdata,
- enum vchiq_bulk_dir dir)
+vchiq_bulk_xfer_callback(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk_params)
{
struct vchiq_service *service = find_service_by_handle(instance, handle);
int status = -EINVAL;
@@ -3147,21 +3516,20 @@ vchiq_bulk_xfer_callback_interruptible(struct vchiq_instance *instance, unsigned
if (!service)
return -EINVAL;
- if (mode != VCHIQ_BULK_MODE_CALLBACK &&
- mode != VCHIQ_BULK_MODE_NOCALLBACK)
+ if (bulk_params->mode != VCHIQ_BULK_MODE_CALLBACK &&
+ bulk_params->mode != VCHIQ_BULK_MODE_NOCALLBACK)
goto error_exit;
if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
goto error_exit;
- if (!offset && !uoffset)
+ if (!bulk_params->offset && !bulk_params->uoffset)
goto error_exit;
if (vchiq_check_service(service))
goto error_exit;
- status = vchiq_bulk_xfer_queue_msg_interruptible(service, offset, uoffset,
- size, userdata, mode, dir);
+ status = vchiq_bulk_xfer_queue_msg_killable(service, bulk_params);
error_exit:
vchiq_service_put(service);
@@ -3175,8 +3543,8 @@ error_exit:
* and the call should be retried after being returned to user context.
*/
int
-vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance,
- unsigned int handle, struct bulk_waiter *userdata)
+vchiq_bulk_xfer_waiting(struct vchiq_instance *instance,
+ unsigned int handle, struct bulk_waiter *waiter)
{
struct vchiq_service *service = find_service_by_handle(instance, handle);
struct bulk_waiter *bulk_waiter;
@@ -3185,7 +3553,7 @@ vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance,
if (!service)
return -EINVAL;
- if (!userdata)
+ if (!waiter)
goto error_exit;
if (service->srvstate != VCHIQ_SRVSTATE_OPEN)
@@ -3194,14 +3562,14 @@ vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance,
if (vchiq_check_service(service))
goto error_exit;
- bulk_waiter = userdata;
+ bulk_waiter = waiter;
vchiq_service_put(service);
status = 0;
- if (wait_for_completion_interruptible(&bulk_waiter->event))
- return -EAGAIN;
+ if (wait_for_completion_killable(&bulk_waiter->event))
+ return -EINTR;
else if (bulk_waiter->actual == VCHIQ_BULK_ACTUAL_ABORTED)
return -EINVAL;
@@ -3267,24 +3635,8 @@ error_exit:
int vchiq_queue_kernel_message(struct vchiq_instance *instance, unsigned int handle, void *data,
unsigned int size)
{
- int status;
-
- while (1) {
- status = vchiq_queue_message(instance, handle, memcpy_copy_callback,
- data, size);
-
- /*
- * vchiq_queue_message() may return -EAGAIN, so we need to
- * implement a retry mechanism since this function is supposed
- * to block until queued
- */
- if (status != -EAGAIN)
- break;
-
- msleep(1);
- }
-
- return status;
+ return vchiq_queue_message(instance, handle, memcpy_copy_callback,
+ data, size);
}
EXPORT_SYMBOL(vchiq_queue_kernel_message);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
index 468463f31801..9b4e766990a4 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_core.h
@@ -6,11 +6,12 @@
#include <linux/mutex.h>
#include <linux/completion.h>
-#include <linux/debugfs.h>
+#include <linux/dma-mapping.h>
#include <linux/dev_printk.h>
#include <linux/kthread.h>
#include <linux/kref.h>
#include <linux/rcupdate.h>
+#include <linux/seq_file.h>
#include <linux/spinlock_types.h>
#include <linux/wait.h>
@@ -113,12 +114,16 @@ enum vchiq_bulk_dir {
struct vchiq_bulk {
short mode;
short dir;
- void *userdata;
- dma_addr_t data;
+ void *cb_data;
+ void __user *cb_userdata;
+ struct bulk_waiter *waiter;
+ dma_addr_t dma_addr;
int size;
void *remote_data;
int remote_size;
int actual;
+ void *offset;
+ void __user *uoffset;
};
struct vchiq_bulk_queue {
@@ -409,6 +414,28 @@ struct vchiq_state {
struct opaque_platform_state *platform_state;
};
+struct pagelist {
+ u32 length;
+ u16 type;
+ u16 offset;
+ u32 addrs[1]; /* N.B. 12 LSBs hold the number
+ * of following pages at consecutive
+ * addresses.
+ */
+};
+
+struct vchiq_pagelist_info {
+ struct pagelist *pagelist;
+ size_t pagelist_buffer_size;
+ dma_addr_t dma_addr;
+ enum dma_data_direction dma_dir;
+ unsigned int num_pages;
+ unsigned int pages_need_release;
+ struct page **pages;
+ struct scatterlist *scatterlist;
+ unsigned int scatterlist_mapped;
+};
+
static inline bool vchiq_remote_initialised(const struct vchiq_state *state)
{
return state->remote && state->remote->initialised;
@@ -471,19 +498,16 @@ extern void
remote_event_pollall(struct vchiq_state *state);
extern int
-vchiq_bulk_xfer_waiting_interruptible(struct vchiq_instance *instance,
- unsigned int handle, struct bulk_waiter *userdata);
+vchiq_bulk_xfer_waiting(struct vchiq_instance *instance, unsigned int handle,
+ struct bulk_waiter *userdata);
extern int
-vchiq_bulk_xfer_blocking_interruptible(struct vchiq_instance *instance, unsigned int handle,
- void *offset, void __user *uoffset, int size,
- void __user *userdata, enum vchiq_bulk_dir dir);
+vchiq_bulk_xfer_blocking(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk);
extern int
-vchiq_bulk_xfer_callback_interruptible(struct vchiq_instance *instance, unsigned int handle,
- void *offset, void __user *uoffset, int size,
- enum vchiq_bulk_mode mode, void *userdata,
- enum vchiq_bulk_dir dir);
+vchiq_bulk_xfer_callback(struct vchiq_instance *instance, unsigned int handle,
+ struct vchiq_bulk *bulk);
extern void
vchiq_dump_state(struct seq_file *f, struct vchiq_state *state);
@@ -529,13 +553,6 @@ vchiq_queue_message(struct vchiq_instance *instance, unsigned int handle,
void *context,
size_t size);
-int vchiq_prepare_bulk_data(struct vchiq_instance *instance, struct vchiq_bulk *bulk, void *offset,
- void __user *uoffset, int size, int dir);
-
-void vchiq_complete_bulk(struct vchiq_instance *instance, struct vchiq_bulk *bulk);
-
-void remote_event_signal(struct vchiq_state *state, struct remote_event *event);
-
void vchiq_dump_platform_state(struct seq_file *f);
void vchiq_dump_platform_instances(struct vchiq_state *state, struct seq_file *f);
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h
index fabffd81b1ec..b29e6693c949 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_debugfs.h
@@ -4,7 +4,8 @@
#ifndef VCHIQ_DEBUGFS_H
#define VCHIQ_DEBUGFS_H
-#include "vchiq_core.h"
+struct vchiq_state;
+struct vchiq_instance;
struct vchiq_debugfs_node {
struct dentry *dentry;
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
index d41a4624cc92..454f43416503 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_dev.c
@@ -288,7 +288,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
{
struct vchiq_service *service;
struct bulk_waiter_node *waiter = NULL, *iter;
- void *userdata;
+ struct vchiq_bulk bulk_params = {};
int status = 0;
int ret;
@@ -303,12 +303,14 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
goto out;
}
- userdata = &waiter->bulk_waiter;
-
- status = vchiq_bulk_xfer_blocking_interruptible(instance, args->handle,
- NULL, args->data, args->size,
- userdata, dir);
+ bulk_params.uoffset = args->data;
+ bulk_params.mode = args->mode;
+ bulk_params.size = args->size;
+ bulk_params.dir = dir;
+ bulk_params.waiter = &waiter->bulk_waiter;
+ status = vchiq_bulk_xfer_blocking(instance, args->handle,
+ &bulk_params);
} else if (args->mode == VCHIQ_BULK_MODE_WAITING) {
mutex_lock(&instance->bulk_waiter_list_mutex);
list_for_each_entry(iter, &instance->bulk_waiter_list,
@@ -328,16 +330,18 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
}
dev_dbg(service->state->dev, "arm: found bulk_waiter %pK for pid %d\n",
waiter, current->pid);
- userdata = &waiter->bulk_waiter;
- status = vchiq_bulk_xfer_waiting_interruptible(instance, args->handle, userdata);
+ status = vchiq_bulk_xfer_waiting(instance, args->handle,
+ &waiter->bulk_waiter);
} else {
- userdata = args->userdata;
-
- status = vchiq_bulk_xfer_callback_interruptible(instance, args->handle, NULL,
- args->data, args->size,
- args->mode, userdata, dir);
-
+ bulk_params.uoffset = args->data;
+ bulk_params.mode = args->mode;
+ bulk_params.size = args->size;
+ bulk_params.dir = dir;
+ bulk_params.cb_userdata = args->userdata;
+
+ status = vchiq_bulk_xfer_callback(instance, args->handle,
+ &bulk_params);
}
if (!waiter) {
@@ -350,7 +354,7 @@ static int vchiq_irq_queue_bulk_tx_rx(struct vchiq_instance *instance,
if (waiter->bulk_waiter.bulk) {
/* Cancel the signal when the transfer completes. */
spin_lock(&service->state->bulk_waiter_spinlock);
- waiter->bulk_waiter.bulk->userdata = NULL;
+ waiter->bulk_waiter.bulk->waiter = NULL;
spin_unlock(&service->state->bulk_waiter_spinlock);
}
kfree(waiter);
@@ -410,7 +414,7 @@ struct vchiq_completion_data32 {
enum vchiq_reason reason;
compat_uptr_t header;
compat_uptr_t service_userdata;
- compat_uptr_t bulk_userdata;
+ compat_uptr_t cb_data;
};
static int vchiq_put_completion(struct vchiq_completion_data __user *buf,
@@ -424,7 +428,7 @@ static int vchiq_put_completion(struct vchiq_completion_data __user *buf,
.reason = completion->reason,
.header = ptr_to_compat(completion->header),
.service_userdata = ptr_to_compat(completion->service_userdata),
- .bulk_userdata = ptr_to_compat(completion->bulk_userdata),
+ .cb_data = ptr_to_compat(completion->cb_userdata),
};
if (copy_to_user(&buf32[index], &tmp, sizeof(tmp)))
return -EFAULT;
@@ -545,11 +549,7 @@ static int vchiq_ioc_await_completion(struct vchiq_instance *instance,
!instance->use_close_delivered)
vchiq_service_put(service);
- /*
- * FIXME: address space mismatch, does bulk_userdata
- * actually point to user or kernel memory?
- */
- user_completion.bulk_userdata = completion->bulk_userdata;
+ user_completion.cb_userdata = completion->cb_userdata;
if (vchiq_put_completion(args->buf, &user_completion, ret)) {
if (ret == 0)
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
index 17550831f86c..afb71a83cfe7 100644
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
+++ b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_ioctl.h
@@ -47,7 +47,7 @@ struct vchiq_completion_data {
enum vchiq_reason reason;
struct vchiq_header __user *header;
void __user *service_userdata;
- void __user *bulk_userdata;
+ void __user *cb_userdata;
};
struct vchiq_await_completion {
diff --git a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h b/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h
deleted file mode 100644
index ebd12bfabb63..000000000000
--- a/drivers/staging/vc04_services/interface/vchiq_arm/vchiq_pagelist.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
-/* Copyright (c) 2010-2012 Broadcom. All rights reserved. */
-
-#ifndef VCHIQ_PAGELIST_H
-#define VCHIQ_PAGELIST_H
-
-#define PAGELIST_WRITE 0
-#define PAGELIST_READ 1
-#define PAGELIST_READ_WITH_FRAGMENTS 2
-
-struct pagelist {
- u32 length;
- u16 type;
- u16 offset;
- u32 addrs[1]; /* N.B. 12 LSBs hold the number
- * of following pages at consecutive
- * addresses.
- */
-};
-
-#endif /* VCHIQ_PAGELIST_H */
diff --git a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
index 67489c334f7b..3fe482bd2793 100644
--- a/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
+++ b/drivers/staging/vc04_services/vchiq-mmal/mmal-vchiq.c
@@ -551,7 +551,8 @@ static void bulk_abort_cb(struct vchiq_mmal_instance *instance,
/* incoming event service callback */
static int mmal_service_callback(struct vchiq_instance *vchiq_instance,
enum vchiq_reason reason, struct vchiq_header *header,
- unsigned int handle, void *bulk_ctx)
+ unsigned int handle, void *cb_data,
+ void __user *cb_userdata)
{
struct vchiq_mmal_instance *instance = vchiq_get_service_userdata(vchiq_instance, handle);
u32 msg_len;
@@ -626,11 +627,11 @@ static int mmal_service_callback(struct vchiq_instance *vchiq_instance,
break;
case VCHIQ_BULK_RECEIVE_DONE:
- bulk_receive_cb(instance, bulk_ctx);
+ bulk_receive_cb(instance, cb_data);
break;
case VCHIQ_BULK_RECEIVE_ABORTED:
- bulk_abort_cb(instance, bulk_ctx);
+ bulk_abort_cb(instance, cb_data);
break;
case VCHIQ_SERVICE_CLOSED:
diff --git a/drivers/staging/vme_user/vme_bridge.h b/drivers/staging/vme_user/vme_bridge.h
index 9bdc41bb6602..abf880d68b12 100644
--- a/drivers/staging/vme_user/vme_bridge.h
+++ b/drivers/staging/vme_user/vme_bridge.h
@@ -128,39 +128,49 @@ struct vme_bridge {
struct mutex irq_mtx;
/* Slave Functions */
- int (*slave_get)(struct vme_slave_resource *, int *, unsigned long long *,
- unsigned long long *, dma_addr_t *, u32 *, u32 *);
- int (*slave_set)(struct vme_slave_resource *, int, unsigned long long,
- unsigned long long, dma_addr_t, u32, u32);
+ int (*slave_get)(struct vme_slave_resource *image, int *enabled,
+ unsigned long long *vme_base, unsigned long long *size,
+ dma_addr_t *buf_base, u32 *aspace, u32 *cycle);
+ int (*slave_set)(struct vme_slave_resource *image, int enabled,
+ unsigned long long vme_base, unsigned long long size,
+ dma_addr_t buf_base, u32 aspace, u32 cycle);
/* Master Functions */
- int (*master_get)(struct vme_master_resource *, int *, unsigned long long *,
- unsigned long long *, u32 *, u32 *, u32 *);
- int (*master_set)(struct vme_master_resource *, int, unsigned long long,
- unsigned long long, u32, u32, u32);
- ssize_t (*master_read)(struct vme_master_resource *, void *, size_t, loff_t);
- ssize_t (*master_write)(struct vme_master_resource *, void *, size_t, loff_t);
- unsigned int (*master_rmw)(struct vme_master_resource *, unsigned int,
- unsigned int, unsigned int, loff_t);
+ int (*master_get)(struct vme_master_resource *image, int *enabled,
+ unsigned long long *vme_base, unsigned long long *size,
+ u32 *aspace, u32 *cycle, u32 *dwidth);
+ int (*master_set)(struct vme_master_resource *image, int enabled,
+ unsigned long long vme_base, unsigned long long size,
+ u32 aspace, u32 cycle, u32 dwidth);
+ ssize_t (*master_read)(struct vme_master_resource *image, void *buf,
+ size_t count, loff_t offset);
+ ssize_t (*master_write)(struct vme_master_resource *image, void *buf,
+ size_t count, loff_t offset);
+ unsigned int (*master_rmw)(struct vme_master_resource *image,
+ unsigned int mask, unsigned int compare,
+ unsigned int swap, loff_t offset);
/* DMA Functions */
- int (*dma_list_add)(struct vme_dma_list *, struct vme_dma_attr *,
- struct vme_dma_attr *, size_t);
- int (*dma_list_exec)(struct vme_dma_list *);
- int (*dma_list_empty)(struct vme_dma_list *);
+ int (*dma_list_add)(struct vme_dma_list *list, struct vme_dma_attr *src,
+ struct vme_dma_attr *dest, size_t count);
+ int (*dma_list_exec)(struct vme_dma_list *list);
+ int (*dma_list_empty)(struct vme_dma_list *list);
/* Interrupt Functions */
- void (*irq_set)(struct vme_bridge *, int, int, int);
- int (*irq_generate)(struct vme_bridge *, int, int);
+ void (*irq_set)(struct vme_bridge *bridge, int level, int state, int sync);
+ int (*irq_generate)(struct vme_bridge *bridge, int level, int statid);
/* Location monitor functions */
- int (*lm_set)(struct vme_lm_resource *, unsigned long long, u32, u32);
- int (*lm_get)(struct vme_lm_resource *, unsigned long long *, u32 *, u32 *);
- int (*lm_attach)(struct vme_lm_resource *, int, void (*callback)(void *), void *);
- int (*lm_detach)(struct vme_lm_resource *, int);
+ int (*lm_set)(struct vme_lm_resource *lm, unsigned long long lm_base,
+ u32 aspace, u32 cycle);
+ int (*lm_get)(struct vme_lm_resource *lm, unsigned long long *lm_base,
+ u32 *aspace, u32 *cycle);
+ int (*lm_attach)(struct vme_lm_resource *lm, int monitor,
+ void (*callback)(void *), void *data);
+ int (*lm_detach)(struct vme_lm_resource *lm, int monitor);
/* CR/CSR space functions */
- int (*slot_get)(struct vme_bridge *);
+ int (*slot_get)(struct vme_bridge *bridge);
/* Bridge parent interface */
void *(*alloc_consistent)(struct device *dev, size_t size, dma_addr_t *dma);
diff --git a/drivers/staging/vt6655/Kconfig b/drivers/staging/vt6655/Kconfig
deleted file mode 100644
index 077f62ebe80c..000000000000
--- a/drivers/staging/vt6655/Kconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config VT6655
- tristate "VIA Technologies VT6655 support"
- depends on PCI && HAS_IOPORT && MAC80211 && m
- help
- This is a vendor-written driver for VIA VT6655.
diff --git a/drivers/staging/vt6655/Makefile b/drivers/staging/vt6655/Makefile
deleted file mode 100644
index e70357ec0af8..000000000000
--- a/drivers/staging/vt6655/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-vt6655_stage-y += device_main.o \
- card.o \
- channel.o \
- mac.o \
- baseband.o \
- rxtx.o \
- dpc.o \
- power.o \
- srom.o \
- key.o \
- rf.o
-
-obj-$(CONFIG_VT6655) += vt6655_stage.o
diff --git a/drivers/staging/vt6655/TODO b/drivers/staging/vt6655/TODO
deleted file mode 100644
index 27654bd0ff5d..000000000000
--- a/drivers/staging/vt6655/TODO
+++ /dev/null
@@ -1,20 +0,0 @@
-TODO:
-- remove __cplusplus ifdefs -- done
-- prepare for merge with vt6656 driver:
- - rename DEVICE_PRT() to DBG_PRT() -- done
- - share 80211*.h includes
- - split rf.c
- - remove dead code
- - abstract VT3253 chipset specific code
-- add common vt665x infrastructure
-- kill ttype.h
-- switch to use MAC80211
-- verify unsigned long usage for x86-64 arch
-- reduce .data footprint
-- use kernel coding style
-- checkpatch.pl fixes
-- sparse fixes
-- integrate with drivers/net/wireless
-
-Please send any patches to Greg Kroah-Hartman <greg@kroah.com>
-and Philipp Hortmann <philipp.g.hortmann@gmail.com>.
diff --git a/drivers/staging/vt6655/baseband.c b/drivers/staging/vt6655/baseband.c
deleted file mode 100644
index f7824396c5ff..000000000000
--- a/drivers/staging/vt6655/baseband.c
+++ /dev/null
@@ -1,2257 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions to access baseband
- *
- * Author: Kyle Hsu
- *
- * Date: Aug.22, 2002
- *
- * Functions:
- * bb_get_frame_time - Calculate data frame transmitting time
- * bb_read_embedded - Embedded read baseband register via MAC
- * bb_write_embedded - Embedded write baseband register via MAC
- * bb_vt3253_init - VIA VT3253 baseband chip init code
- *
- * Revision History:
- * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-07-2003 Bryan YC Fan: Add MAXIM2827/2825 and RFMD2959 support.
- * 08-26-2003 Kyle Hsu : Modify BBuGetFrameTime() and
- * BBvCalculateParameter().
- * cancel the setting of MAC_REG_SOFTPWRCTL on
- * BBbVT3253Init().
- * Add the comments.
- * 09-01-2003 Bryan YC Fan: RF & BB tables updated.
- * Modified BBvLoopbackOn & BBvLoopbackOff().
- *
- *
- */
-
-#include "mac.h"
-#include "baseband.h"
-#include "srom.h"
-#include "rf.h"
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Variables --------------------------*/
-
-/*--------------------- Static Functions --------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Static Definitions -------------------------*/
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Variables --------------------------*/
-
-#define CB_VT3253_INIT_FOR_RFMD 446
-static const unsigned char by_vt3253_init_tab_rfmd[CB_VT3253_INIT_FOR_RFMD][2] = {
- {0x00, 0x30},
- {0x01, 0x00},
- {0x02, 0x00},
- {0x03, 0x00},
- {0x04, 0x00},
- {0x05, 0x00},
- {0x06, 0x00},
- {0x07, 0x00},
- {0x08, 0x70},
- {0x09, 0x45},
- {0x0a, 0x2a},
- {0x0b, 0x76},
- {0x0c, 0x00},
- {0x0d, 0x01},
- {0x0e, 0x80},
- {0x0f, 0x00},
- {0x10, 0x00},
- {0x11, 0x00},
- {0x12, 0x00},
- {0x13, 0x00},
- {0x14, 0x00},
- {0x15, 0x00},
- {0x16, 0x00},
- {0x17, 0x00},
- {0x18, 0x00},
- {0x19, 0x00},
- {0x1a, 0x00},
- {0x1b, 0x9d},
- {0x1c, 0x05},
- {0x1d, 0x00},
- {0x1e, 0x00},
- {0x1f, 0x00},
- {0x20, 0x00},
- {0x21, 0x00},
- {0x22, 0x00},
- {0x23, 0x00},
- {0x24, 0x00},
- {0x25, 0x4a},
- {0x26, 0x00},
- {0x27, 0x00},
- {0x28, 0x00},
- {0x29, 0x00},
- {0x2a, 0x00},
- {0x2b, 0x00},
- {0x2c, 0x00},
- {0x2d, 0xa8},
- {0x2e, 0x1a},
- {0x2f, 0x0c},
- {0x30, 0x26},
- {0x31, 0x5b},
- {0x32, 0x00},
- {0x33, 0x00},
- {0x34, 0x00},
- {0x35, 0x00},
- {0x36, 0xaa},
- {0x37, 0xaa},
- {0x38, 0xff},
- {0x39, 0xff},
- {0x3a, 0x00},
- {0x3b, 0x00},
- {0x3c, 0x00},
- {0x3d, 0x0d},
- {0x3e, 0x51},
- {0x3f, 0x04},
- {0x40, 0x00},
- {0x41, 0x08},
- {0x42, 0x00},
- {0x43, 0x08},
- {0x44, 0x06},
- {0x45, 0x14},
- {0x46, 0x05},
- {0x47, 0x08},
- {0x48, 0x00},
- {0x49, 0x00},
- {0x4a, 0x00},
- {0x4b, 0x00},
- {0x4c, 0x09},
- {0x4d, 0x80},
- {0x4e, 0x00},
- {0x4f, 0xc5},
- {0x50, 0x14},
- {0x51, 0x19},
- {0x52, 0x00},
- {0x53, 0x00},
- {0x54, 0x00},
- {0x55, 0x00},
- {0x56, 0x00},
- {0x57, 0x00},
- {0x58, 0x00},
- {0x59, 0xb0},
- {0x5a, 0x00},
- {0x5b, 0x00},
- {0x5c, 0x00},
- {0x5d, 0x00},
- {0x5e, 0x00},
- {0x5f, 0x00},
- {0x60, 0x44},
- {0x61, 0x04},
- {0x62, 0x00},
- {0x63, 0x00},
- {0x64, 0x00},
- {0x65, 0x00},
- {0x66, 0x04},
- {0x67, 0xb7},
- {0x68, 0x00},
- {0x69, 0x00},
- {0x6a, 0x00},
- {0x6b, 0x00},
- {0x6c, 0x00},
- {0x6d, 0x03},
- {0x6e, 0x01},
- {0x6f, 0x00},
- {0x70, 0x00},
- {0x71, 0x00},
- {0x72, 0x00},
- {0x73, 0x00},
- {0x74, 0x00},
- {0x75, 0x00},
- {0x76, 0x00},
- {0x77, 0x00},
- {0x78, 0x00},
- {0x79, 0x00},
- {0x7a, 0x00},
- {0x7b, 0x00},
- {0x7c, 0x00},
- {0x7d, 0x00},
- {0x7e, 0x00},
- {0x7f, 0x00},
- {0x80, 0x0b},
- {0x81, 0x00},
- {0x82, 0x3c},
- {0x83, 0x00},
- {0x84, 0x00},
- {0x85, 0x00},
- {0x86, 0x00},
- {0x87, 0x00},
- {0x88, 0x08},
- {0x89, 0x00},
- {0x8a, 0x08},
- {0x8b, 0xa6},
- {0x8c, 0x84},
- {0x8d, 0x47},
- {0x8e, 0xbb},
- {0x8f, 0x02},
- {0x90, 0x21},
- {0x91, 0x0c},
- {0x92, 0x04},
- {0x93, 0x22},
- {0x94, 0x00},
- {0x95, 0x00},
- {0x96, 0x00},
- {0x97, 0xeb},
- {0x98, 0x00},
- {0x99, 0x00},
- {0x9a, 0x00},
- {0x9b, 0x00},
- {0x9c, 0x00},
- {0x9d, 0x00},
- {0x9e, 0x00},
- {0x9f, 0x00},
- {0xa0, 0x00},
- {0xa1, 0x00},
- {0xa2, 0x00},
- {0xa3, 0x00},
- {0xa4, 0x00},
- {0xa5, 0x00},
- {0xa6, 0x10},
- {0xa7, 0x04},
- {0xa8, 0x10},
- {0xa9, 0x00},
- {0xaa, 0x8f},
- {0xab, 0x00},
- {0xac, 0x00},
- {0xad, 0x00},
- {0xae, 0x00},
- {0xaf, 0x80},
- {0xb0, 0x38},
- {0xb1, 0x00},
- {0xb2, 0x00},
- {0xb3, 0x00},
- {0xb4, 0xee},
- {0xb5, 0xff},
- {0xb6, 0x10},
- {0xb7, 0x00},
- {0xb8, 0x00},
- {0xb9, 0x00},
- {0xba, 0x00},
- {0xbb, 0x03},
- {0xbc, 0x00},
- {0xbd, 0x00},
- {0xbe, 0x00},
- {0xbf, 0x00},
- {0xc0, 0x10},
- {0xc1, 0x10},
- {0xc2, 0x18},
- {0xc3, 0x20},
- {0xc4, 0x10},
- {0xc5, 0x00},
- {0xc6, 0x22},
- {0xc7, 0x14},
- {0xc8, 0x0f},
- {0xc9, 0x08},
- {0xca, 0xa4},
- {0xcb, 0xa7},
- {0xcc, 0x3c},
- {0xcd, 0x10},
- {0xce, 0x20},
- {0xcf, 0x00},
- {0xd0, 0x00},
- {0xd1, 0x10},
- {0xd2, 0x00},
- {0xd3, 0x00},
- {0xd4, 0x10},
- {0xd5, 0x33},
- {0xd6, 0x70},
- {0xd7, 0x01},
- {0xd8, 0x00},
- {0xd9, 0x00},
- {0xda, 0x00},
- {0xdb, 0x00},
- {0xdc, 0x00},
- {0xdd, 0x00},
- {0xde, 0x00},
- {0xdf, 0x00},
- {0xe0, 0x00},
- {0xe1, 0x00},
- {0xe2, 0xcc},
- {0xe3, 0x04},
- {0xe4, 0x08},
- {0xe5, 0x10},
- {0xe6, 0x00},
- {0xe7, 0x0e},
- {0xe8, 0x88},
- {0xe9, 0xd4},
- {0xea, 0x05},
- {0xeb, 0xf0},
- {0xec, 0x79},
- {0xed, 0x0f},
- {0xee, 0x04},
- {0xef, 0x04},
- {0xf0, 0x00},
- {0xf1, 0x00},
- {0xf2, 0x00},
- {0xf3, 0x00},
- {0xf4, 0x00},
- {0xf5, 0x00},
- {0xf6, 0x00},
- {0xf7, 0x00},
- {0xf8, 0x00},
- {0xf9, 0x00},
- {0xF0, 0x00},
- {0xF1, 0xF8},
- {0xF0, 0x80},
- {0xF0, 0x00},
- {0xF1, 0xF4},
- {0xF0, 0x81},
- {0xF0, 0x01},
- {0xF1, 0xF0},
- {0xF0, 0x82},
- {0xF0, 0x02},
- {0xF1, 0xEC},
- {0xF0, 0x83},
- {0xF0, 0x03},
- {0xF1, 0xE8},
- {0xF0, 0x84},
- {0xF0, 0x04},
- {0xF1, 0xE4},
- {0xF0, 0x85},
- {0xF0, 0x05},
- {0xF1, 0xE0},
- {0xF0, 0x86},
- {0xF0, 0x06},
- {0xF1, 0xDC},
- {0xF0, 0x87},
- {0xF0, 0x07},
- {0xF1, 0xD8},
- {0xF0, 0x88},
- {0xF0, 0x08},
- {0xF1, 0xD4},
- {0xF0, 0x89},
- {0xF0, 0x09},
- {0xF1, 0xD0},
- {0xF0, 0x8A},
- {0xF0, 0x0A},
- {0xF1, 0xCC},
- {0xF0, 0x8B},
- {0xF0, 0x0B},
- {0xF1, 0xC8},
- {0xF0, 0x8C},
- {0xF0, 0x0C},
- {0xF1, 0xC4},
- {0xF0, 0x8D},
- {0xF0, 0x0D},
- {0xF1, 0xC0},
- {0xF0, 0x8E},
- {0xF0, 0x0E},
- {0xF1, 0xBC},
- {0xF0, 0x8F},
- {0xF0, 0x0F},
- {0xF1, 0xB8},
- {0xF0, 0x90},
- {0xF0, 0x10},
- {0xF1, 0xB4},
- {0xF0, 0x91},
- {0xF0, 0x11},
- {0xF1, 0xB0},
- {0xF0, 0x92},
- {0xF0, 0x12},
- {0xF1, 0xAC},
- {0xF0, 0x93},
- {0xF0, 0x13},
- {0xF1, 0xA8},
- {0xF0, 0x94},
- {0xF0, 0x14},
- {0xF1, 0xA4},
- {0xF0, 0x95},
- {0xF0, 0x15},
- {0xF1, 0xA0},
- {0xF0, 0x96},
- {0xF0, 0x16},
- {0xF1, 0x9C},
- {0xF0, 0x97},
- {0xF0, 0x17},
- {0xF1, 0x98},
- {0xF0, 0x98},
- {0xF0, 0x18},
- {0xF1, 0x94},
- {0xF0, 0x99},
- {0xF0, 0x19},
- {0xF1, 0x90},
- {0xF0, 0x9A},
- {0xF0, 0x1A},
- {0xF1, 0x8C},
- {0xF0, 0x9B},
- {0xF0, 0x1B},
- {0xF1, 0x88},
- {0xF0, 0x9C},
- {0xF0, 0x1C},
- {0xF1, 0x84},
- {0xF0, 0x9D},
- {0xF0, 0x1D},
- {0xF1, 0x80},
- {0xF0, 0x9E},
- {0xF0, 0x1E},
- {0xF1, 0x7C},
- {0xF0, 0x9F},
- {0xF0, 0x1F},
- {0xF1, 0x78},
- {0xF0, 0xA0},
- {0xF0, 0x20},
- {0xF1, 0x74},
- {0xF0, 0xA1},
- {0xF0, 0x21},
- {0xF1, 0x70},
- {0xF0, 0xA2},
- {0xF0, 0x22},
- {0xF1, 0x6C},
- {0xF0, 0xA3},
- {0xF0, 0x23},
- {0xF1, 0x68},
- {0xF0, 0xA4},
- {0xF0, 0x24},
- {0xF1, 0x64},
- {0xF0, 0xA5},
- {0xF0, 0x25},
- {0xF1, 0x60},
- {0xF0, 0xA6},
- {0xF0, 0x26},
- {0xF1, 0x5C},
- {0xF0, 0xA7},
- {0xF0, 0x27},
- {0xF1, 0x58},
- {0xF0, 0xA8},
- {0xF0, 0x28},
- {0xF1, 0x54},
- {0xF0, 0xA9},
- {0xF0, 0x29},
- {0xF1, 0x50},
- {0xF0, 0xAA},
- {0xF0, 0x2A},
- {0xF1, 0x4C},
- {0xF0, 0xAB},
- {0xF0, 0x2B},
- {0xF1, 0x48},
- {0xF0, 0xAC},
- {0xF0, 0x2C},
- {0xF1, 0x44},
- {0xF0, 0xAD},
- {0xF0, 0x2D},
- {0xF1, 0x40},
- {0xF0, 0xAE},
- {0xF0, 0x2E},
- {0xF1, 0x3C},
- {0xF0, 0xAF},
- {0xF0, 0x2F},
- {0xF1, 0x38},
- {0xF0, 0xB0},
- {0xF0, 0x30},
- {0xF1, 0x34},
- {0xF0, 0xB1},
- {0xF0, 0x31},
- {0xF1, 0x30},
- {0xF0, 0xB2},
- {0xF0, 0x32},
- {0xF1, 0x2C},
- {0xF0, 0xB3},
- {0xF0, 0x33},
- {0xF1, 0x28},
- {0xF0, 0xB4},
- {0xF0, 0x34},
- {0xF1, 0x24},
- {0xF0, 0xB5},
- {0xF0, 0x35},
- {0xF1, 0x20},
- {0xF0, 0xB6},
- {0xF0, 0x36},
- {0xF1, 0x1C},
- {0xF0, 0xB7},
- {0xF0, 0x37},
- {0xF1, 0x18},
- {0xF0, 0xB8},
- {0xF0, 0x38},
- {0xF1, 0x14},
- {0xF0, 0xB9},
- {0xF0, 0x39},
- {0xF1, 0x10},
- {0xF0, 0xBA},
- {0xF0, 0x3A},
- {0xF1, 0x0C},
- {0xF0, 0xBB},
- {0xF0, 0x3B},
- {0xF1, 0x08},
- {0xF0, 0x00},
- {0xF0, 0x3C},
- {0xF1, 0x04},
- {0xF0, 0xBD},
- {0xF0, 0x3D},
- {0xF1, 0x00},
- {0xF0, 0xBE},
- {0xF0, 0x3E},
- {0xF1, 0x00},
- {0xF0, 0xBF},
- {0xF0, 0x3F},
- {0xF1, 0x00},
- {0xF0, 0xC0},
- {0xF0, 0x00},
-};
-
-#define CB_VT3253B0_INIT_FOR_RFMD 256
-static const unsigned char vt3253b0_rfmd[CB_VT3253B0_INIT_FOR_RFMD][2] = {
- {0x00, 0x31},
- {0x01, 0x00},
- {0x02, 0x00},
- {0x03, 0x00},
- {0x04, 0x00},
- {0x05, 0x81},
- {0x06, 0x00},
- {0x07, 0x00},
- {0x08, 0x38},
- {0x09, 0x45},
- {0x0a, 0x2a},
- {0x0b, 0x76},
- {0x0c, 0x00},
- {0x0d, 0x00},
- {0x0e, 0x80},
- {0x0f, 0x00},
- {0x10, 0x00},
- {0x11, 0x00},
- {0x12, 0x00},
- {0x13, 0x00},
- {0x14, 0x00},
- {0x15, 0x00},
- {0x16, 0x00},
- {0x17, 0x00},
- {0x18, 0x00},
- {0x19, 0x00},
- {0x1a, 0x00},
- {0x1b, 0x8e},
- {0x1c, 0x06},
- {0x1d, 0x00},
- {0x1e, 0x00},
- {0x1f, 0x00},
- {0x20, 0x00},
- {0x21, 0x00},
- {0x22, 0x00},
- {0x23, 0x00},
- {0x24, 0x00},
- {0x25, 0x4a},
- {0x26, 0x00},
- {0x27, 0x00},
- {0x28, 0x00},
- {0x29, 0x00},
- {0x2a, 0x00},
- {0x2b, 0x00},
- {0x2c, 0x00},
- {0x2d, 0x34},
- {0x2e, 0x18},
- {0x2f, 0x0c},
- {0x30, 0x26},
- {0x31, 0x5b},
- {0x32, 0x00},
- {0x33, 0x00},
- {0x34, 0x00},
- {0x35, 0x00},
- {0x36, 0xaa},
- {0x37, 0xaa},
- {0x38, 0xff},
- {0x39, 0xff},
- {0x3a, 0xf8},
- {0x3b, 0x00},
- {0x3c, 0x00},
- {0x3d, 0x09},
- {0x3e, 0x0d},
- {0x3f, 0x04},
- {0x40, 0x00},
- {0x41, 0x08},
- {0x42, 0x00},
- {0x43, 0x08},
- {0x44, 0x08},
- {0x45, 0x14},
- {0x46, 0x05},
- {0x47, 0x08},
- {0x48, 0x00},
- {0x49, 0x00},
- {0x4a, 0x00},
- {0x4b, 0x00},
- {0x4c, 0x09},
- {0x4d, 0x80},
- {0x4e, 0x00},
- {0x4f, 0xc5},
- {0x50, 0x14},
- {0x51, 0x19},
- {0x52, 0x00},
- {0x53, 0x00},
- {0x54, 0x00},
- {0x55, 0x00},
- {0x56, 0x00},
- {0x57, 0x00},
- {0x58, 0x00},
- {0x59, 0xb0},
- {0x5a, 0x00},
- {0x5b, 0x00},
- {0x5c, 0x00},
- {0x5d, 0x00},
- {0x5e, 0x00},
- {0x5f, 0x00},
- {0x60, 0x39},
- {0x61, 0x83},
- {0x62, 0x00},
- {0x63, 0x00},
- {0x64, 0x00},
- {0x65, 0x00},
- {0x66, 0xc0},
- {0x67, 0x49},
- {0x68, 0x00},
- {0x69, 0x00},
- {0x6a, 0x00},
- {0x6b, 0x00},
- {0x6c, 0x00},
- {0x6d, 0x03},
- {0x6e, 0x01},
- {0x6f, 0x00},
- {0x70, 0x00},
- {0x71, 0x00},
- {0x72, 0x00},
- {0x73, 0x00},
- {0x74, 0x00},
- {0x75, 0x00},
- {0x76, 0x00},
- {0x77, 0x00},
- {0x78, 0x00},
- {0x79, 0x00},
- {0x7a, 0x00},
- {0x7b, 0x00},
- {0x7c, 0x00},
- {0x7d, 0x00},
- {0x7e, 0x00},
- {0x7f, 0x00},
- {0x80, 0x89},
- {0x81, 0x00},
- {0x82, 0x0e},
- {0x83, 0x00},
- {0x84, 0x00},
- {0x85, 0x00},
- {0x86, 0x00},
- {0x87, 0x00},
- {0x88, 0x08},
- {0x89, 0x00},
- {0x8a, 0x0e},
- {0x8b, 0xa7},
- {0x8c, 0x88},
- {0x8d, 0x47},
- {0x8e, 0xaa},
- {0x8f, 0x02},
- {0x90, 0x23},
- {0x91, 0x0c},
- {0x92, 0x06},
- {0x93, 0x08},
- {0x94, 0x00},
- {0x95, 0x00},
- {0x96, 0x00},
- {0x97, 0xeb},
- {0x98, 0x00},
- {0x99, 0x00},
- {0x9a, 0x00},
- {0x9b, 0x00},
- {0x9c, 0x00},
- {0x9d, 0x00},
- {0x9e, 0x00},
- {0x9f, 0x00},
- {0xa0, 0x00},
- {0xa1, 0x00},
- {0xa2, 0x00},
- {0xa3, 0xcd},
- {0xa4, 0x07},
- {0xa5, 0x33},
- {0xa6, 0x18},
- {0xa7, 0x00},
- {0xa8, 0x18},
- {0xa9, 0x00},
- {0xaa, 0x28},
- {0xab, 0x00},
- {0xac, 0x00},
- {0xad, 0x00},
- {0xae, 0x00},
- {0xaf, 0x18},
- {0xb0, 0x38},
- {0xb1, 0x30},
- {0xb2, 0x00},
- {0xb3, 0x00},
- {0xb4, 0x00},
- {0xb5, 0x00},
- {0xb6, 0x84},
- {0xb7, 0xfd},
- {0xb8, 0x00},
- {0xb9, 0x00},
- {0xba, 0x00},
- {0xbb, 0x03},
- {0xbc, 0x00},
- {0xbd, 0x00},
- {0xbe, 0x00},
- {0xbf, 0x00},
- {0xc0, 0x10},
- {0xc1, 0x20},
- {0xc2, 0x18},
- {0xc3, 0x20},
- {0xc4, 0x10},
- {0xc5, 0x2c},
- {0xc6, 0x1e},
- {0xc7, 0x10},
- {0xc8, 0x12},
- {0xc9, 0x01},
- {0xca, 0x6f},
- {0xcb, 0xa7},
- {0xcc, 0x3c},
- {0xcd, 0x10},
- {0xce, 0x00},
- {0xcf, 0x22},
- {0xd0, 0x00},
- {0xd1, 0x10},
- {0xd2, 0x00},
- {0xd3, 0x00},
- {0xd4, 0x10},
- {0xd5, 0x33},
- {0xd6, 0x80},
- {0xd7, 0x21},
- {0xd8, 0x00},
- {0xd9, 0x00},
- {0xda, 0x00},
- {0xdb, 0x00},
- {0xdc, 0x00},
- {0xdd, 0x00},
- {0xde, 0x00},
- {0xdf, 0x00},
- {0xe0, 0x00},
- {0xe1, 0xB3},
- {0xe2, 0x00},
- {0xe3, 0x00},
- {0xe4, 0x00},
- {0xe5, 0x10},
- {0xe6, 0x00},
- {0xe7, 0x18},
- {0xe8, 0x08},
- {0xe9, 0xd4},
- {0xea, 0x00},
- {0xeb, 0xff},
- {0xec, 0x79},
- {0xed, 0x10},
- {0xee, 0x30},
- {0xef, 0x02},
- {0xf0, 0x00},
- {0xf1, 0x09},
- {0xf2, 0x00},
- {0xf3, 0x00},
- {0xf4, 0x00},
- {0xf5, 0x00},
- {0xf6, 0x00},
- {0xf7, 0x00},
- {0xf8, 0x00},
- {0xf9, 0x00},
- {0xfa, 0x00},
- {0xfb, 0x00},
- {0xfc, 0x00},
- {0xfd, 0x00},
- {0xfe, 0x00},
- {0xff, 0x00},
-};
-
-#define CB_VT3253B0_AGC_FOR_RFMD2959 195
-/* For RFMD2959 */
-static
-unsigned char vt3253b0_agc4_rfmd2959[CB_VT3253B0_AGC_FOR_RFMD2959][2] = {
- {0xF0, 0x00},
- {0xF1, 0x3E},
- {0xF0, 0x80},
- {0xF0, 0x00},
- {0xF1, 0x3E},
- {0xF0, 0x81},
- {0xF0, 0x01},
- {0xF1, 0x3E},
- {0xF0, 0x82},
- {0xF0, 0x02},
- {0xF1, 0x3E},
- {0xF0, 0x83},
- {0xF0, 0x03},
- {0xF1, 0x3B},
- {0xF0, 0x84},
- {0xF0, 0x04},
- {0xF1, 0x39},
- {0xF0, 0x85},
- {0xF0, 0x05},
- {0xF1, 0x38},
- {0xF0, 0x86},
- {0xF0, 0x06},
- {0xF1, 0x37},
- {0xF0, 0x87},
- {0xF0, 0x07},
- {0xF1, 0x36},
- {0xF0, 0x88},
- {0xF0, 0x08},
- {0xF1, 0x35},
- {0xF0, 0x89},
- {0xF0, 0x09},
- {0xF1, 0x35},
- {0xF0, 0x8A},
- {0xF0, 0x0A},
- {0xF1, 0x34},
- {0xF0, 0x8B},
- {0xF0, 0x0B},
- {0xF1, 0x34},
- {0xF0, 0x8C},
- {0xF0, 0x0C},
- {0xF1, 0x33},
- {0xF0, 0x8D},
- {0xF0, 0x0D},
- {0xF1, 0x32},
- {0xF0, 0x8E},
- {0xF0, 0x0E},
- {0xF1, 0x31},
- {0xF0, 0x8F},
- {0xF0, 0x0F},
- {0xF1, 0x30},
- {0xF0, 0x90},
- {0xF0, 0x10},
- {0xF1, 0x2F},
- {0xF0, 0x91},
- {0xF0, 0x11},
- {0xF1, 0x2F},
- {0xF0, 0x92},
- {0xF0, 0x12},
- {0xF1, 0x2E},
- {0xF0, 0x93},
- {0xF0, 0x13},
- {0xF1, 0x2D},
- {0xF0, 0x94},
- {0xF0, 0x14},
- {0xF1, 0x2C},
- {0xF0, 0x95},
- {0xF0, 0x15},
- {0xF1, 0x2B},
- {0xF0, 0x96},
- {0xF0, 0x16},
- {0xF1, 0x2B},
- {0xF0, 0x97},
- {0xF0, 0x17},
- {0xF1, 0x2A},
- {0xF0, 0x98},
- {0xF0, 0x18},
- {0xF1, 0x29},
- {0xF0, 0x99},
- {0xF0, 0x19},
- {0xF1, 0x28},
- {0xF0, 0x9A},
- {0xF0, 0x1A},
- {0xF1, 0x27},
- {0xF0, 0x9B},
- {0xF0, 0x1B},
- {0xF1, 0x26},
- {0xF0, 0x9C},
- {0xF0, 0x1C},
- {0xF1, 0x25},
- {0xF0, 0x9D},
- {0xF0, 0x1D},
- {0xF1, 0x24},
- {0xF0, 0x9E},
- {0xF0, 0x1E},
- {0xF1, 0x24},
- {0xF0, 0x9F},
- {0xF0, 0x1F},
- {0xF1, 0x23},
- {0xF0, 0xA0},
- {0xF0, 0x20},
- {0xF1, 0x22},
- {0xF0, 0xA1},
- {0xF0, 0x21},
- {0xF1, 0x21},
- {0xF0, 0xA2},
- {0xF0, 0x22},
- {0xF1, 0x20},
- {0xF0, 0xA3},
- {0xF0, 0x23},
- {0xF1, 0x20},
- {0xF0, 0xA4},
- {0xF0, 0x24},
- {0xF1, 0x1F},
- {0xF0, 0xA5},
- {0xF0, 0x25},
- {0xF1, 0x1E},
- {0xF0, 0xA6},
- {0xF0, 0x26},
- {0xF1, 0x1D},
- {0xF0, 0xA7},
- {0xF0, 0x27},
- {0xF1, 0x1C},
- {0xF0, 0xA8},
- {0xF0, 0x28},
- {0xF1, 0x1B},
- {0xF0, 0xA9},
- {0xF0, 0x29},
- {0xF1, 0x1B},
- {0xF0, 0xAA},
- {0xF0, 0x2A},
- {0xF1, 0x1A},
- {0xF0, 0xAB},
- {0xF0, 0x2B},
- {0xF1, 0x1A},
- {0xF0, 0xAC},
- {0xF0, 0x2C},
- {0xF1, 0x19},
- {0xF0, 0xAD},
- {0xF0, 0x2D},
- {0xF1, 0x18},
- {0xF0, 0xAE},
- {0xF0, 0x2E},
- {0xF1, 0x17},
- {0xF0, 0xAF},
- {0xF0, 0x2F},
- {0xF1, 0x16},
- {0xF0, 0xB0},
- {0xF0, 0x30},
- {0xF1, 0x15},
- {0xF0, 0xB1},
- {0xF0, 0x31},
- {0xF1, 0x15},
- {0xF0, 0xB2},
- {0xF0, 0x32},
- {0xF1, 0x15},
- {0xF0, 0xB3},
- {0xF0, 0x33},
- {0xF1, 0x14},
- {0xF0, 0xB4},
- {0xF0, 0x34},
- {0xF1, 0x13},
- {0xF0, 0xB5},
- {0xF0, 0x35},
- {0xF1, 0x12},
- {0xF0, 0xB6},
- {0xF0, 0x36},
- {0xF1, 0x11},
- {0xF0, 0xB7},
- {0xF0, 0x37},
- {0xF1, 0x10},
- {0xF0, 0xB8},
- {0xF0, 0x38},
- {0xF1, 0x0F},
- {0xF0, 0xB9},
- {0xF0, 0x39},
- {0xF1, 0x0E},
- {0xF0, 0xBA},
- {0xF0, 0x3A},
- {0xF1, 0x0D},
- {0xF0, 0xBB},
- {0xF0, 0x3B},
- {0xF1, 0x0C},
- {0xF0, 0xBC},
- {0xF0, 0x3C},
- {0xF1, 0x0B},
- {0xF0, 0xBD},
- {0xF0, 0x3D},
- {0xF1, 0x0B},
- {0xF0, 0xBE},
- {0xF0, 0x3E},
- {0xF1, 0x0A},
- {0xF0, 0xBF},
- {0xF0, 0x3F},
- {0xF1, 0x09},
- {0xF0, 0x00},
-};
-
-#define CB_VT3253B0_INIT_FOR_AIROHA2230 256
-/* For AIROHA */
-static
-unsigned char vt3253b0_airoha2230[CB_VT3253B0_INIT_FOR_AIROHA2230][2] = {
- {0x00, 0x31},
- {0x01, 0x00},
- {0x02, 0x00},
- {0x03, 0x00},
- {0x04, 0x00},
- {0x05, 0x80},
- {0x06, 0x00},
- {0x07, 0x00},
- {0x08, 0x70},
- {0x09, 0x41},
- {0x0a, 0x2A},
- {0x0b, 0x76},
- {0x0c, 0x00},
- {0x0d, 0x00},
- {0x0e, 0x80},
- {0x0f, 0x00},
- {0x10, 0x00},
- {0x11, 0x00},
- {0x12, 0x00},
- {0x13, 0x00},
- {0x14, 0x00},
- {0x15, 0x00},
- {0x16, 0x00},
- {0x17, 0x00},
- {0x18, 0x00},
- {0x19, 0x00},
- {0x1a, 0x00},
- {0x1b, 0x8f},
- {0x1c, 0x09},
- {0x1d, 0x00},
- {0x1e, 0x00},
- {0x1f, 0x00},
- {0x20, 0x00},
- {0x21, 0x00},
- {0x22, 0x00},
- {0x23, 0x00},
- {0x24, 0x00},
- {0x25, 0x4a},
- {0x26, 0x00},
- {0x27, 0x00},
- {0x28, 0x00},
- {0x29, 0x00},
- {0x2a, 0x00},
- {0x2b, 0x00},
- {0x2c, 0x00},
- {0x2d, 0x4a},
- {0x2e, 0x00},
- {0x2f, 0x0a},
- {0x30, 0x26},
- {0x31, 0x5b},
- {0x32, 0x00},
- {0x33, 0x00},
- {0x34, 0x00},
- {0x35, 0x00},
- {0x36, 0xaa},
- {0x37, 0xaa},
- {0x38, 0xff},
- {0x39, 0xff},
- {0x3a, 0x79},
- {0x3b, 0x00},
- {0x3c, 0x00},
- {0x3d, 0x0b},
- {0x3e, 0x48},
- {0x3f, 0x04},
- {0x40, 0x00},
- {0x41, 0x08},
- {0x42, 0x00},
- {0x43, 0x08},
- {0x44, 0x08},
- {0x45, 0x14},
- {0x46, 0x05},
- {0x47, 0x09},
- {0x48, 0x00},
- {0x49, 0x00},
- {0x4a, 0x00},
- {0x4b, 0x00},
- {0x4c, 0x09},
- {0x4d, 0x73},
- {0x4e, 0x00},
- {0x4f, 0xc5},
- {0x50, 0x15},
- {0x51, 0x19},
- {0x52, 0x00},
- {0x53, 0x00},
- {0x54, 0x00},
- {0x55, 0x00},
- {0x56, 0x00},
- {0x57, 0x00},
- {0x58, 0x00},
- {0x59, 0xb0},
- {0x5a, 0x00},
- {0x5b, 0x00},
- {0x5c, 0x00},
- {0x5d, 0x00},
- {0x5e, 0x00},
- {0x5f, 0x00},
- {0x60, 0xe4},
- {0x61, 0x80},
- {0x62, 0x00},
- {0x63, 0x00},
- {0x64, 0x00},
- {0x65, 0x00},
- {0x66, 0x98},
- {0x67, 0x0a},
- {0x68, 0x00},
- {0x69, 0x00},
- {0x6a, 0x00},
- {0x6b, 0x00},
- {0x6c, 0x00}, /* RobertYu:20050125, request by JJSue */
- {0x6d, 0x03},
- {0x6e, 0x01},
- {0x6f, 0x00},
- {0x70, 0x00},
- {0x71, 0x00},
- {0x72, 0x00},
- {0x73, 0x00},
- {0x74, 0x00},
- {0x75, 0x00},
- {0x76, 0x00},
- {0x77, 0x00},
- {0x78, 0x00},
- {0x79, 0x00},
- {0x7a, 0x00},
- {0x7b, 0x00},
- {0x7c, 0x00},
- {0x7d, 0x00},
- {0x7e, 0x00},
- {0x7f, 0x00},
- {0x80, 0x8c},
- {0x81, 0x01},
- {0x82, 0x09},
- {0x83, 0x00},
- {0x84, 0x00},
- {0x85, 0x00},
- {0x86, 0x00},
- {0x87, 0x00},
- {0x88, 0x08},
- {0x89, 0x00},
- {0x8a, 0x0f},
- {0x8b, 0xb7},
- {0x8c, 0x88},
- {0x8d, 0x47},
- {0x8e, 0xaa},
- {0x8f, 0x02},
- {0x90, 0x22},
- {0x91, 0x00},
- {0x92, 0x00},
- {0x93, 0x00},
- {0x94, 0x00},
- {0x95, 0x00},
- {0x96, 0x00},
- {0x97, 0xeb},
- {0x98, 0x00},
- {0x99, 0x00},
- {0x9a, 0x00},
- {0x9b, 0x00},
- {0x9c, 0x00},
- {0x9d, 0x00},
- {0x9e, 0x00},
- {0x9f, 0x01},
- {0xa0, 0x00},
- {0xa1, 0x00},
- {0xa2, 0x00},
- {0xa3, 0x00},
- {0xa4, 0x00},
- {0xa5, 0x00},
- {0xa6, 0x10},
- {0xa7, 0x00},
- {0xa8, 0x18},
- {0xa9, 0x00},
- {0xaa, 0x00},
- {0xab, 0x00},
- {0xac, 0x00},
- {0xad, 0x00},
- {0xae, 0x00},
- {0xaf, 0x18},
- {0xb0, 0x38},
- {0xb1, 0x30},
- {0xb2, 0x00},
- {0xb3, 0x00},
- {0xb4, 0xff},
- {0xb5, 0x0f},
- {0xb6, 0xe4},
- {0xb7, 0xe2},
- {0xb8, 0x00},
- {0xb9, 0x00},
- {0xba, 0x00},
- {0xbb, 0x03},
- {0xbc, 0x01},
- {0xbd, 0x00},
- {0xbe, 0x00},
- {0xbf, 0x00},
- {0xc0, 0x18},
- {0xc1, 0x20},
- {0xc2, 0x07},
- {0xc3, 0x18},
- {0xc4, 0xff},
- {0xc5, 0x2c},
- {0xc6, 0x0c},
- {0xc7, 0x0a},
- {0xc8, 0x0e},
- {0xc9, 0x01},
- {0xca, 0x68},
- {0xcb, 0xa7},
- {0xcc, 0x3c},
- {0xcd, 0x10},
- {0xce, 0x00},
- {0xcf, 0x25},
- {0xd0, 0x40},
- {0xd1, 0x12},
- {0xd2, 0x00},
- {0xd3, 0x00},
- {0xd4, 0x10},
- {0xd5, 0x28},
- {0xd6, 0x80},
- {0xd7, 0x2A},
- {0xd8, 0x00},
- {0xd9, 0x00},
- {0xda, 0x00},
- {0xdb, 0x00},
- {0xdc, 0x00},
- {0xdd, 0x00},
- {0xde, 0x00},
- {0xdf, 0x00},
- {0xe0, 0x00},
- {0xe1, 0xB3},
- {0xe2, 0x00},
- {0xe3, 0x00},
- {0xe4, 0x00},
- {0xe5, 0x10},
- {0xe6, 0x00},
- {0xe7, 0x1C},
- {0xe8, 0x00},
- {0xe9, 0xf4},
- {0xea, 0x00},
- {0xeb, 0xff},
- {0xec, 0x79},
- {0xed, 0x20},
- {0xee, 0x30},
- {0xef, 0x01},
- {0xf0, 0x00},
- {0xf1, 0x3e},
- {0xf2, 0x00},
- {0xf3, 0x00},
- {0xf4, 0x00},
- {0xf5, 0x00},
- {0xf6, 0x00},
- {0xf7, 0x00},
- {0xf8, 0x00},
- {0xf9, 0x00},
- {0xfa, 0x00},
- {0xfb, 0x00},
- {0xfc, 0x00},
- {0xfd, 0x00},
- {0xfe, 0x00},
- {0xff, 0x00},
-};
-
-#define CB_VT3253B0_INIT_FOR_UW2451 256
-/* For UW2451 */
-static unsigned char vt3253b0_uw2451[CB_VT3253B0_INIT_FOR_UW2451][2] = {
- {0x00, 0x31},
- {0x01, 0x00},
- {0x02, 0x00},
- {0x03, 0x00},
- {0x04, 0x00},
- {0x05, 0x81},
- {0x06, 0x00},
- {0x07, 0x00},
- {0x08, 0x38},
- {0x09, 0x45},
- {0x0a, 0x28},
- {0x0b, 0x76},
- {0x0c, 0x00},
- {0x0d, 0x00},
- {0x0e, 0x80},
- {0x0f, 0x00},
- {0x10, 0x00},
- {0x11, 0x00},
- {0x12, 0x00},
- {0x13, 0x00},
- {0x14, 0x00},
- {0x15, 0x00},
- {0x16, 0x00},
- {0x17, 0x00},
- {0x18, 0x00},
- {0x19, 0x00},
- {0x1a, 0x00},
- {0x1b, 0x8f},
- {0x1c, 0x0f},
- {0x1d, 0x00},
- {0x1e, 0x00},
- {0x1f, 0x00},
- {0x20, 0x00},
- {0x21, 0x00},
- {0x22, 0x00},
- {0x23, 0x00},
- {0x24, 0x00},
- {0x25, 0x4a},
- {0x26, 0x00},
- {0x27, 0x00},
- {0x28, 0x00},
- {0x29, 0x00},
- {0x2a, 0x00},
- {0x2b, 0x00},
- {0x2c, 0x00},
- {0x2d, 0x18},
- {0x2e, 0x00},
- {0x2f, 0x0a},
- {0x30, 0x26},
- {0x31, 0x5b},
- {0x32, 0x00},
- {0x33, 0x00},
- {0x34, 0x00},
- {0x35, 0x00},
- {0x36, 0xaa},
- {0x37, 0xaa},
- {0x38, 0xff},
- {0x39, 0xff},
- {0x3a, 0x00},
- {0x3b, 0x00},
- {0x3c, 0x00},
- {0x3d, 0x03},
- {0x3e, 0x1d},
- {0x3f, 0x04},
- {0x40, 0x00},
- {0x41, 0x08},
- {0x42, 0x00},
- {0x43, 0x08},
- {0x44, 0x08},
- {0x45, 0x14},
- {0x46, 0x05},
- {0x47, 0x09},
- {0x48, 0x00},
- {0x49, 0x00},
- {0x4a, 0x00},
- {0x4b, 0x00},
- {0x4c, 0x09},
- {0x4d, 0x90},
- {0x4e, 0x00},
- {0x4f, 0xc5},
- {0x50, 0x15},
- {0x51, 0x19},
- {0x52, 0x00},
- {0x53, 0x00},
- {0x54, 0x00},
- {0x55, 0x00},
- {0x56, 0x00},
- {0x57, 0x00},
- {0x58, 0x00},
- {0x59, 0xb0},
- {0x5a, 0x00},
- {0x5b, 0x00},
- {0x5c, 0x00},
- {0x5d, 0x00},
- {0x5e, 0x00},
- {0x5f, 0x00},
- {0x60, 0xb3},
- {0x61, 0x81},
- {0x62, 0x00},
- {0x63, 0x00},
- {0x64, 0x00},
- {0x65, 0x00},
- {0x66, 0x57},
- {0x67, 0x6c},
- {0x68, 0x00},
- {0x69, 0x00},
- {0x6a, 0x00},
- {0x6b, 0x00},
- {0x6c, 0x00}, /* RobertYu:20050125, request by JJSue */
- {0x6d, 0x03},
- {0x6e, 0x01},
- {0x6f, 0x00},
- {0x70, 0x00},
- {0x71, 0x00},
- {0x72, 0x00},
- {0x73, 0x00},
- {0x74, 0x00},
- {0x75, 0x00},
- {0x76, 0x00},
- {0x77, 0x00},
- {0x78, 0x00},
- {0x79, 0x00},
- {0x7a, 0x00},
- {0x7b, 0x00},
- {0x7c, 0x00},
- {0x7d, 0x00},
- {0x7e, 0x00},
- {0x7f, 0x00},
- {0x80, 0x8c},
- {0x81, 0x00},
- {0x82, 0x0e},
- {0x83, 0x00},
- {0x84, 0x00},
- {0x85, 0x00},
- {0x86, 0x00},
- {0x87, 0x00},
- {0x88, 0x08},
- {0x89, 0x00},
- {0x8a, 0x0e},
- {0x8b, 0xa7},
- {0x8c, 0x88},
- {0x8d, 0x47},
- {0x8e, 0xaa},
- {0x8f, 0x02},
- {0x90, 0x00},
- {0x91, 0x00},
- {0x92, 0x00},
- {0x93, 0x00},
- {0x94, 0x00},
- {0x95, 0x00},
- {0x96, 0x00},
- {0x97, 0xe3},
- {0x98, 0x00},
- {0x99, 0x00},
- {0x9a, 0x00},
- {0x9b, 0x00},
- {0x9c, 0x00},
- {0x9d, 0x00},
- {0x9e, 0x00},
- {0x9f, 0x00},
- {0xa0, 0x00},
- {0xa1, 0x00},
- {0xa2, 0x00},
- {0xa3, 0x00},
- {0xa4, 0x00},
- {0xa5, 0x00},
- {0xa6, 0x10},
- {0xa7, 0x00},
- {0xa8, 0x18},
- {0xa9, 0x00},
- {0xaa, 0x00},
- {0xab, 0x00},
- {0xac, 0x00},
- {0xad, 0x00},
- {0xae, 0x00},
- {0xaf, 0x18},
- {0xb0, 0x18},
- {0xb1, 0x30},
- {0xb2, 0x00},
- {0xb3, 0x00},
- {0xb4, 0x00},
- {0xb5, 0x00},
- {0xb6, 0x00},
- {0xb7, 0x00},
- {0xb8, 0x00},
- {0xb9, 0x00},
- {0xba, 0x00},
- {0xbb, 0x03},
- {0xbc, 0x01},
- {0xbd, 0x00},
- {0xbe, 0x00},
- {0xbf, 0x00},
- {0xc0, 0x10},
- {0xc1, 0x20},
- {0xc2, 0x00},
- {0xc3, 0x20},
- {0xc4, 0x00},
- {0xc5, 0x2c},
- {0xc6, 0x1c},
- {0xc7, 0x10},
- {0xc8, 0x10},
- {0xc9, 0x01},
- {0xca, 0x68},
- {0xcb, 0xa7},
- {0xcc, 0x3c},
- {0xcd, 0x09},
- {0xce, 0x00},
- {0xcf, 0x20},
- {0xd0, 0x40},
- {0xd1, 0x10},
- {0xd2, 0x00},
- {0xd3, 0x00},
- {0xd4, 0x20},
- {0xd5, 0x28},
- {0xd6, 0xa0},
- {0xd7, 0x2a},
- {0xd8, 0x00},
- {0xd9, 0x00},
- {0xda, 0x00},
- {0xdb, 0x00},
- {0xdc, 0x00},
- {0xdd, 0x00},
- {0xde, 0x00},
- {0xdf, 0x00},
- {0xe0, 0x00},
- {0xe1, 0xd3},
- {0xe2, 0xc0},
- {0xe3, 0x00},
- {0xe4, 0x00},
- {0xe5, 0x10},
- {0xe6, 0x00},
- {0xe7, 0x12},
- {0xe8, 0x12},
- {0xe9, 0x34},
- {0xea, 0x00},
- {0xeb, 0xff},
- {0xec, 0x79},
- {0xed, 0x20},
- {0xee, 0x30},
- {0xef, 0x01},
- {0xf0, 0x00},
- {0xf1, 0x3e},
- {0xf2, 0x00},
- {0xf3, 0x00},
- {0xf4, 0x00},
- {0xf5, 0x00},
- {0xf6, 0x00},
- {0xf7, 0x00},
- {0xf8, 0x00},
- {0xf9, 0x00},
- {0xfa, 0x00},
- {0xfb, 0x00},
- {0xfc, 0x00},
- {0xfd, 0x00},
- {0xfe, 0x00},
- {0xff, 0x00},
-};
-
-#define CB_VT3253B0_AGC 193
-/* For AIROHA */
-static unsigned char vt3253b0_agc[CB_VT3253B0_AGC][2] = {
- {0xF0, 0x00},
- {0xF1, 0x00},
- {0xF0, 0x80},
- {0xF0, 0x01},
- {0xF1, 0x00},
- {0xF0, 0x81},
- {0xF0, 0x02},
- {0xF1, 0x02},
- {0xF0, 0x82},
- {0xF0, 0x03},
- {0xF1, 0x04},
- {0xF0, 0x83},
- {0xF0, 0x03},
- {0xF1, 0x04},
- {0xF0, 0x84},
- {0xF0, 0x04},
- {0xF1, 0x06},
- {0xF0, 0x85},
- {0xF0, 0x05},
- {0xF1, 0x06},
- {0xF0, 0x86},
- {0xF0, 0x06},
- {0xF1, 0x06},
- {0xF0, 0x87},
- {0xF0, 0x07},
- {0xF1, 0x08},
- {0xF0, 0x88},
- {0xF0, 0x08},
- {0xF1, 0x08},
- {0xF0, 0x89},
- {0xF0, 0x09},
- {0xF1, 0x0A},
- {0xF0, 0x8A},
- {0xF0, 0x0A},
- {0xF1, 0x0A},
- {0xF0, 0x8B},
- {0xF0, 0x0B},
- {0xF1, 0x0C},
- {0xF0, 0x8C},
- {0xF0, 0x0C},
- {0xF1, 0x0C},
- {0xF0, 0x8D},
- {0xF0, 0x0D},
- {0xF1, 0x0E},
- {0xF0, 0x8E},
- {0xF0, 0x0E},
- {0xF1, 0x0E},
- {0xF0, 0x8F},
- {0xF0, 0x0F},
- {0xF1, 0x10},
- {0xF0, 0x90},
- {0xF0, 0x10},
- {0xF1, 0x10},
- {0xF0, 0x91},
- {0xF0, 0x11},
- {0xF1, 0x12},
- {0xF0, 0x92},
- {0xF0, 0x12},
- {0xF1, 0x12},
- {0xF0, 0x93},
- {0xF0, 0x13},
- {0xF1, 0x14},
- {0xF0, 0x94},
- {0xF0, 0x14},
- {0xF1, 0x14},
- {0xF0, 0x95},
- {0xF0, 0x15},
- {0xF1, 0x16},
- {0xF0, 0x96},
- {0xF0, 0x16},
- {0xF1, 0x16},
- {0xF0, 0x97},
- {0xF0, 0x17},
- {0xF1, 0x18},
- {0xF0, 0x98},
- {0xF0, 0x18},
- {0xF1, 0x18},
- {0xF0, 0x99},
- {0xF0, 0x19},
- {0xF1, 0x1A},
- {0xF0, 0x9A},
- {0xF0, 0x1A},
- {0xF1, 0x1A},
- {0xF0, 0x9B},
- {0xF0, 0x1B},
- {0xF1, 0x1C},
- {0xF0, 0x9C},
- {0xF0, 0x1C},
- {0xF1, 0x1C},
- {0xF0, 0x9D},
- {0xF0, 0x1D},
- {0xF1, 0x1E},
- {0xF0, 0x9E},
- {0xF0, 0x1E},
- {0xF1, 0x1E},
- {0xF0, 0x9F},
- {0xF0, 0x1F},
- {0xF1, 0x20},
- {0xF0, 0xA0},
- {0xF0, 0x20},
- {0xF1, 0x20},
- {0xF0, 0xA1},
- {0xF0, 0x21},
- {0xF1, 0x22},
- {0xF0, 0xA2},
- {0xF0, 0x22},
- {0xF1, 0x22},
- {0xF0, 0xA3},
- {0xF0, 0x23},
- {0xF1, 0x24},
- {0xF0, 0xA4},
- {0xF0, 0x24},
- {0xF1, 0x24},
- {0xF0, 0xA5},
- {0xF0, 0x25},
- {0xF1, 0x26},
- {0xF0, 0xA6},
- {0xF0, 0x26},
- {0xF1, 0x26},
- {0xF0, 0xA7},
- {0xF0, 0x27},
- {0xF1, 0x28},
- {0xF0, 0xA8},
- {0xF0, 0x28},
- {0xF1, 0x28},
- {0xF0, 0xA9},
- {0xF0, 0x29},
- {0xF1, 0x2A},
- {0xF0, 0xAA},
- {0xF0, 0x2A},
- {0xF1, 0x2A},
- {0xF0, 0xAB},
- {0xF0, 0x2B},
- {0xF1, 0x2C},
- {0xF0, 0xAC},
- {0xF0, 0x2C},
- {0xF1, 0x2C},
- {0xF0, 0xAD},
- {0xF0, 0x2D},
- {0xF1, 0x2E},
- {0xF0, 0xAE},
- {0xF0, 0x2E},
- {0xF1, 0x2E},
- {0xF0, 0xAF},
- {0xF0, 0x2F},
- {0xF1, 0x30},
- {0xF0, 0xB0},
- {0xF0, 0x30},
- {0xF1, 0x30},
- {0xF0, 0xB1},
- {0xF0, 0x31},
- {0xF1, 0x32},
- {0xF0, 0xB2},
- {0xF0, 0x32},
- {0xF1, 0x32},
- {0xF0, 0xB3},
- {0xF0, 0x33},
- {0xF1, 0x34},
- {0xF0, 0xB4},
- {0xF0, 0x34},
- {0xF1, 0x34},
- {0xF0, 0xB5},
- {0xF0, 0x35},
- {0xF1, 0x36},
- {0xF0, 0xB6},
- {0xF0, 0x36},
- {0xF1, 0x36},
- {0xF0, 0xB7},
- {0xF0, 0x37},
- {0xF1, 0x38},
- {0xF0, 0xB8},
- {0xF0, 0x38},
- {0xF1, 0x38},
- {0xF0, 0xB9},
- {0xF0, 0x39},
- {0xF1, 0x3A},
- {0xF0, 0xBA},
- {0xF0, 0x3A},
- {0xF1, 0x3A},
- {0xF0, 0xBB},
- {0xF0, 0x3B},
- {0xF1, 0x3C},
- {0xF0, 0xBC},
- {0xF0, 0x3C},
- {0xF1, 0x3C},
- {0xF0, 0xBD},
- {0xF0, 0x3D},
- {0xF1, 0x3E},
- {0xF0, 0xBE},
- {0xF0, 0x3E},
- {0xF1, 0x3E},
- {0xF0, 0xBF},
- {0xF0, 0x00},
-};
-
-static const unsigned short awc_frame_time[MAX_RATE] = {
- 10, 20, 55, 110, 24, 36, 48, 72, 96, 144, 192, 216
-};
-
-/*--------------------- Export Variables --------------------------*/
-/*
- * Description: Calculate data frame transmitting time
- *
- * Parameters:
- * In:
- * preamble_type - Preamble Type
- * by_pkt_type - PK_TYPE_11A, PK_TYPE_11B, PK_TYPE_11GB, PK_TYPE_11GA
- * cb_frame_length - Baseband Type
- * tx_rate - Tx Rate
- * Out:
- *
- * Return Value: FrameTime
- *
- */
-unsigned int bb_get_frame_time(unsigned char preamble_type,
- unsigned char by_pkt_type,
- unsigned int cb_frame_length,
- unsigned short tx_rate)
-{
- unsigned int frame_time;
- unsigned int preamble;
- unsigned int tmp;
- unsigned int rate_idx = (unsigned int)tx_rate;
- unsigned int rate = 0;
-
- if (rate_idx > RATE_54M)
- return 0;
-
- rate = (unsigned int)awc_frame_time[rate_idx];
-
- if (rate_idx <= 3) { /* CCK mode */
- if (preamble_type == PREAMBLE_SHORT)
- preamble = 96;
- else
- preamble = 192;
- frame_time = (cb_frame_length * 80) / rate; /* ????? */
- tmp = (frame_time * rate) / 80;
- if (cb_frame_length != tmp)
- frame_time++;
-
- return preamble + frame_time;
- }
- frame_time = (cb_frame_length * 8 + 22) / rate; /* ???????? */
- tmp = ((frame_time * rate) - 22) / 8;
- if (cb_frame_length != tmp)
- frame_time++;
-
- frame_time = frame_time * 4; /* ??????? */
- if (by_pkt_type != PK_TYPE_11A)
- frame_time += 6; /* ?????? */
-
- return 20 + frame_time; /* ?????? */
-}
-
-/*
- * Description: Calculate Length, Service, and Signal fields of Phy for Tx
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * frame_length - Tx Frame Length
- * tx_rate - Tx Rate
- * Out:
- * struct vnt_phy_field *phy
- * - pointer to Phy Length field
- * - pointer to Phy Service field
- * - pointer to Phy Signal field
- *
- * Return Value: none
- *
- */
-void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length,
- u16 tx_rate, u8 pkt_type, struct vnt_phy_field *phy)
-{
- u32 bit_count;
- u32 count = 0;
- u32 tmp;
- int ext_bit;
- u8 preamble_type = priv->preamble_type;
-
- bit_count = frame_length * 8;
- ext_bit = false;
-
- switch (tx_rate) {
- case RATE_1M:
- count = bit_count;
-
- phy->signal = 0x00;
-
- break;
- case RATE_2M:
- count = bit_count / 2;
-
- if (preamble_type == PREAMBLE_SHORT)
- phy->signal = 0x09;
- else
- phy->signal = 0x01;
-
- break;
- case RATE_5M:
- count = (bit_count * 10) / 55;
- tmp = (count * 55) / 10;
-
- if (tmp != bit_count)
- count++;
-
- if (preamble_type == PREAMBLE_SHORT)
- phy->signal = 0x0a;
- else
- phy->signal = 0x02;
-
- break;
- case RATE_11M:
- count = bit_count / 11;
- tmp = count * 11;
-
- if (tmp != bit_count) {
- count++;
-
- if ((bit_count - tmp) <= 3)
- ext_bit = true;
- }
-
- if (preamble_type == PREAMBLE_SHORT)
- phy->signal = 0x0b;
- else
- phy->signal = 0x03;
-
- break;
- case RATE_6M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9b;
- else
- phy->signal = 0x8b;
-
- break;
- case RATE_9M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9f;
- else
- phy->signal = 0x8f;
-
- break;
- case RATE_12M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9a;
- else
- phy->signal = 0x8a;
-
- break;
- case RATE_18M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9e;
- else
- phy->signal = 0x8e;
-
- break;
- case RATE_24M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x99;
- else
- phy->signal = 0x89;
-
- break;
- case RATE_36M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9d;
- else
- phy->signal = 0x8d;
-
- break;
- case RATE_48M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x98;
- else
- phy->signal = 0x88;
-
- break;
- case RATE_54M:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9c;
- else
- phy->signal = 0x8c;
- break;
- default:
- if (pkt_type == PK_TYPE_11A)
- phy->signal = 0x9c;
- else
- phy->signal = 0x8c;
- break;
- }
-
- if (pkt_type == PK_TYPE_11B) {
- phy->service = 0x00;
- if (ext_bit)
- phy->service |= 0x80;
- phy->len = cpu_to_le16((u16)count);
- } else {
- phy->service = 0x00;
- phy->len = cpu_to_le16((u16)frame_length);
- }
-}
-
-/*
- * Description: Read a byte from BASEBAND, by embedded programming
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * by_bb_addr - address of register in Baseband
- * Out:
- * pby_data - data read
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool bb_read_embedded(struct vnt_private *priv, unsigned char by_bb_addr,
- unsigned char *pby_data)
-{
- void __iomem *iobase = priv->port_offset;
- unsigned short ww;
- unsigned char by_value;
-
- /* BB reg offset */
- iowrite8(by_bb_addr, iobase + MAC_REG_BBREGADR);
-
- /* turn on REGR */
- vt6655_mac_reg_bits_on(iobase, MAC_REG_BBREGCTL, BBREGCTL_REGR);
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- by_value = ioread8(iobase + MAC_REG_BBREGCTL);
- if (by_value & BBREGCTL_DONE)
- break;
- }
-
- /* get BB data */
- *pby_data = ioread8(iobase + MAC_REG_BBREGDATA);
-
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x30)\n");
- return false;
- }
- return true;
-}
-
-/*
- * Description: Write a Byte to BASEBAND, by embedded programming
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * by_bb_addr - address of register in Baseband
- * by_data - data to write
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool bb_write_embedded(struct vnt_private *priv, unsigned char by_bb_addr,
- unsigned char by_data)
-{
- void __iomem *iobase = priv->port_offset;
- unsigned short ww;
- unsigned char by_value;
-
- /* BB reg offset */
- iowrite8(by_bb_addr, iobase + MAC_REG_BBREGADR);
- /* set BB data */
- iowrite8(by_data, iobase + MAC_REG_BBREGDATA);
-
- /* turn on BBREGCTL_REGW */
- vt6655_mac_reg_bits_on(iobase, MAC_REG_BBREGCTL, BBREGCTL_REGW);
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- by_value = ioread8(iobase + MAC_REG_BBREGCTL);
- if (by_value & BBREGCTL_DONE)
- break;
- }
-
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x31)\n");
- return false;
- }
- return true;
-}
-
-/*
- * Description: VIA VT3253 Baseband chip init function
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * byRevId - Revision ID
- * rf_type - RF type
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-
-bool bb_vt3253_init(struct vnt_private *priv)
-{
- bool result = true;
- int ii;
- void __iomem *iobase = priv->port_offset;
- unsigned char rf_type = priv->rf_type;
- unsigned char by_local_id = priv->local_id;
-
- if (rf_type == RF_RFMD2959) {
- if (by_local_id <= REV_ID_VT3253_A1) {
- for (ii = 0; ii < CB_VT3253_INIT_FOR_RFMD; ii++)
- result &= bb_write_embedded(priv,
- by_vt3253_init_tab_rfmd[ii][0],
- by_vt3253_init_tab_rfmd[ii][1]);
-
- } else {
- for (ii = 0; ii < CB_VT3253B0_INIT_FOR_RFMD; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_rfmd[ii][0],
- vt3253b0_rfmd[ii][1]);
-
- for (ii = 0; ii < CB_VT3253B0_AGC_FOR_RFMD2959; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_agc4_rfmd2959[ii][0],
- vt3253b0_agc4_rfmd2959[ii][1]);
-
- iowrite32(0x23, iobase + MAC_REG_ITRTMSET);
- vt6655_mac_reg_bits_on(iobase, MAC_REG_PAPEDELAY, BIT(0));
- }
- priv->bbvga[0] = 0x18;
- priv->bbvga[1] = 0x0A;
- priv->bbvga[2] = 0x0;
- priv->bbvga[3] = 0x0;
- priv->dbm_threshold[0] = -70;
- priv->dbm_threshold[1] = -50;
- priv->dbm_threshold[2] = 0;
- priv->dbm_threshold[3] = 0;
- } else if ((rf_type == RF_AIROHA) || (rf_type == RF_AL2230S)) {
- for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_airoha2230[ii][0],
- vt3253b0_airoha2230[ii][1]);
-
- for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_agc[ii][0], vt3253b0_agc[ii][1]);
-
- priv->bbvga[0] = 0x1C;
- priv->bbvga[1] = 0x10;
- priv->bbvga[2] = 0x0;
- priv->bbvga[3] = 0x0;
- priv->dbm_threshold[0] = -70;
- priv->dbm_threshold[1] = -48;
- priv->dbm_threshold[2] = 0;
- priv->dbm_threshold[3] = 0;
- } else if (rf_type == RF_UW2451) {
- for (ii = 0; ii < CB_VT3253B0_INIT_FOR_UW2451; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_uw2451[ii][0],
- vt3253b0_uw2451[ii][1]);
-
- for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_agc[ii][0],
- vt3253b0_agc[ii][1]);
-
- iowrite8(0x23, iobase + MAC_REG_ITRTMSET);
- vt6655_mac_reg_bits_on(iobase, MAC_REG_PAPEDELAY, BIT(0));
-
- priv->bbvga[0] = 0x14;
- priv->bbvga[1] = 0x0A;
- priv->bbvga[2] = 0x0;
- priv->bbvga[3] = 0x0;
- priv->dbm_threshold[0] = -60;
- priv->dbm_threshold[1] = -50;
- priv->dbm_threshold[2] = 0;
- priv->dbm_threshold[3] = 0;
- } else if (rf_type == RF_VT3226) {
- for (ii = 0; ii < CB_VT3253B0_INIT_FOR_AIROHA2230; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_airoha2230[ii][0],
- vt3253b0_airoha2230[ii][1]);
-
- for (ii = 0; ii < CB_VT3253B0_AGC; ii++)
- result &= bb_write_embedded(priv,
- vt3253b0_agc[ii][0], vt3253b0_agc[ii][1]);
-
- priv->bbvga[0] = 0x1C;
- priv->bbvga[1] = 0x10;
- priv->bbvga[2] = 0x0;
- priv->bbvga[3] = 0x0;
- priv->dbm_threshold[0] = -70;
- priv->dbm_threshold[1] = -48;
- priv->dbm_threshold[2] = 0;
- priv->dbm_threshold[3] = 0;
- /* Fix VT3226 DFC system timing issue */
- vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_RFLEOPT);
- /* {{ RobertYu: 20050104 */
- } else {
- /* No VGA Table now */
- priv->update_bbvga = false;
- priv->bbvga[0] = 0x1C;
- }
-
- if (by_local_id > REV_ID_VT3253_A1) {
- bb_write_embedded(priv, 0x04, 0x7F);
- bb_write_embedded(priv, 0x0D, 0x01);
- }
-
- return result;
-}
-
-/*
- * Description: Set ShortSlotTime mode
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void
-bb_set_short_slot_time(struct vnt_private *priv)
-{
- unsigned char by_bb_rx_conf = 0;
- unsigned char by_bb_vga = 0;
-
- bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */
-
- if (priv->short_slot_time)
- by_bb_rx_conf &= 0xDF; /* 1101 1111 */
- else
- by_bb_rx_conf |= 0x20; /* 0010 0000 */
-
- /* patch for 3253B0 Baseband with Cardbus module */
- bb_read_embedded(priv, 0xE7, &by_bb_vga);
- if (by_bb_vga == priv->bbvga[0])
- by_bb_rx_conf |= 0x20; /* 0010 0000 */
-
- bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */
-}
-
-void bb_set_vga_gain_offset(struct vnt_private *priv, unsigned char by_data)
-{
- unsigned char by_bb_rx_conf = 0;
-
- bb_write_embedded(priv, 0xE7, by_data);
-
- bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */
- /* patch for 3253B0 Baseband with Cardbus module */
- if (by_data == priv->bbvga[0])
- by_bb_rx_conf |= 0x20; /* 0010 0000 */
- else if (priv->short_slot_time)
- by_bb_rx_conf &= 0xDF; /* 1101 1111 */
- else
- by_bb_rx_conf |= 0x20; /* 0010 0000 */
- priv->bbvga_current = by_data;
- bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */
-}
-
-/*
- * Description: Baseband SoftwareReset
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void
-bb_software_reset(struct vnt_private *priv)
-{
- bb_write_embedded(priv, 0x50, 0x40);
- bb_write_embedded(priv, 0x50, 0);
- bb_write_embedded(priv, 0x9C, 0x01);
- bb_write_embedded(priv, 0x9C, 0);
-}
-
-/*
- * Description: Set Tx Antenna mode
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * by_antenna_mode - Antenna Mode
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-
-void
-bb_set_tx_antenna_mode(struct vnt_private *priv, unsigned char by_antenna_mode)
-{
- unsigned char by_bb_tx_conf;
-
- bb_read_embedded(priv, 0x09, &by_bb_tx_conf); /* CR09 */
- if (by_antenna_mode == ANT_DIVERSITY) {
- /* bit 1 is diversity */
- by_bb_tx_conf |= 0x02;
- } else if (by_antenna_mode == ANT_A) {
- /* bit 2 is ANTSEL */
- by_bb_tx_conf &= 0xF9; /* 1111 1001 */
- } else if (by_antenna_mode == ANT_B) {
- by_bb_tx_conf &= 0xFD; /* 1111 1101 */
- by_bb_tx_conf |= 0x04;
- }
- bb_write_embedded(priv, 0x09, by_bb_tx_conf); /* CR09 */
-}
-
-/*
- * Description: Set Rx Antenna mode
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * by_antenna_mode - Antenna Mode
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-
-void
-bb_set_rx_antenna_mode(struct vnt_private *priv, unsigned char by_antenna_mode)
-{
- unsigned char by_bb_rx_conf;
-
- bb_read_embedded(priv, 0x0A, &by_bb_rx_conf); /* CR10 */
- if (by_antenna_mode == ANT_DIVERSITY) {
- by_bb_rx_conf |= 0x01;
-
- } else if (by_antenna_mode == ANT_A) {
- by_bb_rx_conf &= 0xFC; /* 1111 1100 */
- } else if (by_antenna_mode == ANT_B) {
- by_bb_rx_conf &= 0xFE; /* 1111 1110 */
- by_bb_rx_conf |= 0x02;
- }
- bb_write_embedded(priv, 0x0A, by_bb_rx_conf); /* CR10 */
-}
-
-/*
- * Description: bb_set_deep_sleep
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void
-bb_set_deep_sleep(struct vnt_private *priv, unsigned char by_local_id)
-{
- bb_write_embedded(priv, 0x0C, 0x17); /* CR12 */
- bb_write_embedded(priv, 0x0D, 0xB9); /* CR13 */
-}
-
diff --git a/drivers/staging/vt6655/baseband.h b/drivers/staging/vt6655/baseband.h
deleted file mode 100644
index e4a02c240a1c..000000000000
--- a/drivers/staging/vt6655/baseband.h
+++ /dev/null
@@ -1,72 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions to access baseband
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 5, 2002
- *
- */
-
-#ifndef __BASEBAND_H__
-#define __BASEBAND_H__
-
-#include "device.h"
-
-/*
- * Registers in the BASEBAND
- */
-#define BB_MAX_CONTEXT_SIZE 256
-
-/*
- * Baseband RF pair definition in eeprom (Bits 6..0)
- */
-
-#define PREAMBLE_LONG 0
-#define PREAMBLE_SHORT 1
-
-#define F5G 0
-#define F2_4G 1
-
-#define TOP_RATE_54M 0x80000000
-#define TOP_RATE_48M 0x40000000
-#define TOP_RATE_36M 0x20000000
-#define TOP_RATE_24M 0x10000000
-#define TOP_RATE_18M 0x08000000
-#define TOP_RATE_12M 0x04000000
-#define TOP_RATE_11M 0x02000000
-#define TOP_RATE_9M 0x01000000
-#define TOP_RATE_6M 0x00800000
-#define TOP_RATE_55M 0x00400000
-#define TOP_RATE_2M 0x00200000
-#define TOP_RATE_1M 0x00100000
-
-unsigned int bb_get_frame_time(unsigned char preamble_type,
- unsigned char by_pkt_type,
- unsigned int cb_frame_length,
- unsigned short w_rate);
-
-void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length,
- u16 tx_rate, u8 pkt_type, struct vnt_phy_field *phy);
-
-bool bb_read_embedded(struct vnt_private *priv, unsigned char by_bb_addr,
- unsigned char *pby_data);
-bool bb_write_embedded(struct vnt_private *priv, unsigned char by_bb_addr,
- unsigned char by_data);
-
-void bb_set_short_slot_time(struct vnt_private *priv);
-void bb_set_vga_gain_offset(struct vnt_private *priv, unsigned char by_data);
-
-/* VT3253 Baseband */
-bool bb_vt3253_init(struct vnt_private *priv);
-void bb_software_reset(struct vnt_private *priv);
-void bb_set_tx_antenna_mode(struct vnt_private *priv,
- unsigned char by_antenna_mode);
-void bb_set_rx_antenna_mode(struct vnt_private *priv,
- unsigned char by_antenna_mode);
-void bb_set_deep_sleep(struct vnt_private *priv, unsigned char by_local_id);
-
-#endif /* __BASEBAND_H__ */
diff --git a/drivers/staging/vt6655/card.c b/drivers/staging/vt6655/card.c
deleted file mode 100644
index 6a2e390e9493..000000000000
--- a/drivers/staging/vt6655/card.c
+++ /dev/null
@@ -1,836 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Provide functions to setup NIC operation mode
- * Functions:
- * s_vSafeResetTx - Rest Tx
- * card_set_rspinf - Set RSPINF
- * CARDvUpdateBasicTopRate - Update BasicTopRate
- * CARDbAddBasicRate - Add to BasicRateSet
- * CARDbIsOFDMinBasicRate - Check if any OFDM rate is in BasicRateSet
- * card_get_tsf_offset - Calculate TSFOffset
- * vt6655_get_current_tsf - Read Current NIC TSF counter
- * card_get_next_tbtt - Calculate Next Beacon TSF counter
- * CARDvSetFirstNextTBTT - Set NIC Beacon time
- * CARDvUpdateNextTBTT - Sync. NIC Beacon time
- * card_radio_power_off - Turn Off NIC Radio Power
- *
- * Revision History:
- * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-26-2003 Kyle Hsu: Modify the definition type of iobase.
- * 09-01-2003 Bryan YC Fan: Add vUpdateIFS().
- *
- */
-
-#include "card.h"
-#include "baseband.h"
-#include "mac.h"
-#include "desc.h"
-#include "rf.h"
-#include "power.h"
-
-/*--------------------- Static Definitions -------------------------*/
-
-#define C_SIFS_A 16 /* micro sec. */
-#define C_SIFS_BG 10
-
-#define C_EIFS 80 /* micro sec. */
-
-#define C_SLOT_SHORT 9 /* micro sec. */
-#define C_SLOT_LONG 20
-
-#define C_CWMIN_A 15 /* slot time */
-#define C_CWMIN_B 31
-
-#define C_CWMAX 1023 /* slot time */
-
-#define WAIT_BEACON_TX_DOWN_TMO 3 /* Times */
-
-/*--------------------- Static Variables --------------------------*/
-
-static const unsigned short rx_bcn_tsf_off[MAX_RATE] = {
- 17, 17, 17, 17, 34, 23, 17, 11, 8, 5, 4, 3};
-
-/*--------------------- Static Functions --------------------------*/
-
-static void vt6655_mac_set_bb_type(void __iomem *iobase, u32 mask)
-{
- u32 reg_value;
-
- reg_value = ioread32(iobase + MAC_REG_ENCFG);
- reg_value = reg_value & ~ENCFG_BBTYPE_MASK;
- reg_value = reg_value | mask;
- iowrite32(reg_value, iobase + MAC_REG_ENCFG);
-}
-
-/*--------------------- Export Functions --------------------------*/
-
-/*
- * Description: Calculate TxRate and RsvTime fields for RSPINF in OFDM mode.
- *
- * Parameters:
- * In:
- * wRate - Tx Rate
- * byPktType - Tx Packet type
- * Out:
- * tx_rate - pointer to RSPINF TxRate field
- * rsv_time - pointer to RSPINF RsvTime field
- *
- * Return Value: none
- */
-static void calculate_ofdmr_parameter(unsigned char rate,
- u8 bb_type,
- unsigned char *tx_rate,
- unsigned char *rsv_time)
-{
- switch (rate) {
- case RATE_6M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9B;
- *rsv_time = 44;
- } else {
- *tx_rate = 0x8B;
- *rsv_time = 50;
- }
- break;
-
- case RATE_9M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9F;
- *rsv_time = 36;
- } else {
- *tx_rate = 0x8F;
- *rsv_time = 42;
- }
- break;
-
- case RATE_12M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9A;
- *rsv_time = 32;
- } else {
- *tx_rate = 0x8A;
- *rsv_time = 38;
- }
- break;
-
- case RATE_18M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9E;
- *rsv_time = 28;
- } else {
- *tx_rate = 0x8E;
- *rsv_time = 34;
- }
- break;
-
- case RATE_36M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9D;
- *rsv_time = 24;
- } else {
- *tx_rate = 0x8D;
- *rsv_time = 30;
- }
- break;
-
- case RATE_48M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x98;
- *rsv_time = 24;
- } else {
- *tx_rate = 0x88;
- *rsv_time = 30;
- }
- break;
-
- case RATE_54M:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x9C;
- *rsv_time = 24;
- } else {
- *tx_rate = 0x8C;
- *rsv_time = 30;
- }
- break;
-
- case RATE_24M:
- default:
- if (bb_type == BB_TYPE_11A) { /* 5GHZ */
- *tx_rate = 0x99;
- *rsv_time = 28;
- } else {
- *tx_rate = 0x89;
- *rsv_time = 34;
- }
- break;
- }
-}
-
-/*--------------------- Export Functions --------------------------*/
-
-/*
- * Description: Update IFS
- *
- * Parameters:
- * In:
- * priv - The adapter to be set
- * Out:
- * none
- *
- * Return Value: None.
- */
-bool card_set_phy_parameter(struct vnt_private *priv, u8 bb_type)
-{
- unsigned char cw_max_min = 0;
- unsigned char slot = 0;
- unsigned char sifs = 0;
- unsigned char difs = 0;
- int i;
-
- /* Set SIFS, DIFS, EIFS, SlotTime, CwMin */
- if (bb_type == BB_TYPE_11A) {
- vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11A);
- bb_write_embedded(priv, 0x88, 0x03);
- slot = C_SLOT_SHORT;
- sifs = C_SIFS_A;
- difs = C_SIFS_A + 2 * C_SLOT_SHORT;
- cw_max_min = 0xA4;
- } else if (bb_type == BB_TYPE_11B) {
- vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11B);
- bb_write_embedded(priv, 0x88, 0x02);
- slot = C_SLOT_LONG;
- sifs = C_SIFS_BG;
- difs = C_SIFS_BG + 2 * C_SLOT_LONG;
- cw_max_min = 0xA5;
- } else { /* PK_TYPE_11GA & PK_TYPE_11GB */
- vt6655_mac_set_bb_type(priv->port_offset, BB_TYPE_11G);
- bb_write_embedded(priv, 0x88, 0x08);
- sifs = C_SIFS_BG;
-
- if (priv->short_slot_time) {
- slot = C_SLOT_SHORT;
- difs = C_SIFS_BG + 2 * C_SLOT_SHORT;
- } else {
- slot = C_SLOT_LONG;
- difs = C_SIFS_BG + 2 * C_SLOT_LONG;
- }
-
- cw_max_min = 0xa4;
-
- for (i = RATE_54M; i >= RATE_6M; i--) {
- if (priv->basic_rates & ((u32)(0x1 << i))) {
- cw_max_min |= 0x1;
- break;
- }
- }
- }
-
- if (priv->rf_type == RF_RFMD2959) {
- /*
- * bcs TX_PE will reserve 3 us hardware's processing
- * time here is 2 us.
- */
- sifs -= 3;
- difs -= 3;
- /*
- * TX_PE will reserve 3 us for MAX2829 A mode only, it is for
- * better TX throughput; MAC will need 2 us to process, so the
- * SIFS, DIFS can be shorter by 2 us.
- */
- }
-
- if (priv->sifs != sifs) {
- priv->sifs = sifs;
- iowrite8(priv->sifs, priv->port_offset + MAC_REG_SIFS);
- }
- if (priv->difs != difs) {
- priv->difs = difs;
- iowrite8(priv->difs, priv->port_offset + MAC_REG_DIFS);
- }
- if (priv->eifs != C_EIFS) {
- priv->eifs = C_EIFS;
- iowrite8(priv->eifs, priv->port_offset + MAC_REG_EIFS);
- }
- if (priv->slot != slot) {
- priv->slot = slot;
- iowrite8(priv->slot, priv->port_offset + MAC_REG_SLOT);
-
- bb_set_short_slot_time(priv);
- }
- if (priv->cw_max_min != cw_max_min) {
- priv->cw_max_min = cw_max_min;
- iowrite8(priv->cw_max_min, priv->port_offset + MAC_REG_CWMAXMIN0);
- }
-
- priv->packet_type = card_get_pkt_type(priv);
-
- card_set_rspinf(priv, bb_type);
-
- return true;
-}
-
-/*
- * Description: Sync. TSF counter to BSS
- * Get TSF offset and write to HW
- *
- * Parameters:
- * In:
- * priv - The adapter to be sync.
- * rx_rate - data rate of receive beacon
- * bss_timestamp - Rx BCN's TSF
- * qwLocalTSF - Local TSF
- * Out:
- * none
- *
- * Return Value: none
- */
-bool card_update_tsf(struct vnt_private *priv, unsigned char rx_rate,
- u64 bss_timestamp)
-{
- u64 local_tsf;
- u64 tsf_offset = 0;
-
- local_tsf = vt6655_get_current_tsf(priv);
-
- if (bss_timestamp != local_tsf) {
- tsf_offset = card_get_tsf_offset(rx_rate, bss_timestamp,
- local_tsf);
- /* adjust TSF, HW's TSF add TSF Offset reg */
- tsf_offset = le64_to_cpu(tsf_offset);
- iowrite32((u32)tsf_offset, priv->port_offset + MAC_REG_TSFOFST);
- iowrite32((u32)(tsf_offset >> 32), priv->port_offset + MAC_REG_TSFOFST + 4);
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TSFSYNCEN);
- }
- return true;
-}
-
-/*
- * Description: Set NIC TSF counter for first Beacon time
- * Get NEXTTBTT from adjusted TSF and Beacon Interval
- *
- * Parameters:
- * In:
- * priv - The adapter to be set.
- * beacon_interval - Beacon Interval
- * Out:
- * none
- *
- * Return Value: true if succeed; otherwise false
- */
-bool card_set_beacon_period(struct vnt_private *priv,
- unsigned short beacon_interval)
-{
- u64 next_tbtt;
-
- next_tbtt = vt6655_get_current_tsf(priv); /* Get Local TSF counter */
-
- next_tbtt = card_get_next_tbtt(next_tbtt, beacon_interval);
-
- /* set HW beacon interval */
- iowrite16(beacon_interval, priv->port_offset + MAC_REG_BI);
- priv->beacon_interval = beacon_interval;
- /* Set NextTBTT */
- next_tbtt = le64_to_cpu(next_tbtt);
- iowrite32((u32)next_tbtt, priv->port_offset + MAC_REG_NEXTTBTT);
- iowrite32((u32)(next_tbtt >> 32), priv->port_offset + MAC_REG_NEXTTBTT + 4);
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
-
- return true;
-}
-
-/*
- * Description: Turn off Radio power
- *
- * Parameters:
- * In:
- * priv - The adapter to be turned off
- * Out:
- * none
- *
- */
-void card_radio_power_off(struct vnt_private *priv)
-{
- if (priv->radio_off)
- return;
-
- switch (priv->rf_type) {
- case RF_RFMD2959:
- vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL,
- SOFTPWRCTL_TXPEINV);
- vt6655_mac_word_reg_bits_on(priv->port_offset, MAC_REG_SOFTPWRCTL,
- SOFTPWRCTL_SWPE1);
- break;
-
- case RF_AIROHA:
- case RF_AL2230S:
- vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL,
- SOFTPWRCTL_SWPE2);
- vt6655_mac_word_reg_bits_off(priv->port_offset, MAC_REG_SOFTPWRCTL,
- SOFTPWRCTL_SWPE3);
- break;
- }
-
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_RXON);
-
- bb_set_deep_sleep(priv, priv->local_id);
-
- priv->radio_off = true;
- pr_debug("chester power off\n");
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_GPIOCTL0, LED_ACTSET); /* LED issue */
-}
-
-void card_safe_reset_tx(struct vnt_private *priv)
-{
- unsigned int uu;
- struct vnt_tx_desc *curr_td;
-
- /* initialize TD index */
- priv->tail_td[0] = &priv->ap_td0_rings[0];
- priv->apCurrTD[0] = &priv->ap_td0_rings[0];
-
- priv->tail_td[1] = &priv->ap_td1_rings[0];
- priv->apCurrTD[1] = &priv->ap_td1_rings[0];
-
- for (uu = 0; uu < TYPE_MAXTD; uu++)
- priv->iTDUsed[uu] = 0;
-
- for (uu = 0; uu < priv->opts.tx_descs[0]; uu++) {
- curr_td = &priv->ap_td0_rings[uu];
- curr_td->td0.owner = OWNED_BY_HOST;
- /* init all Tx Packet pointer to NULL */
- }
- for (uu = 0; uu < priv->opts.tx_descs[1]; uu++) {
- curr_td = &priv->ap_td1_rings[uu];
- curr_td->td0.owner = OWNED_BY_HOST;
- /* init all Tx Packet pointer to NULL */
- }
-
- /* set MAC TD pointer */
- vt6655_mac_set_curr_tx_desc_addr(TYPE_TXDMA0, priv, priv->td0_pool_dma);
-
- vt6655_mac_set_curr_tx_desc_addr(TYPE_AC0DMA, priv, priv->td1_pool_dma);
-
- /* set MAC Beacon TX pointer */
- iowrite32((u32)priv->tx_beacon_dma, priv->port_offset + MAC_REG_BCNDMAPTR);
-}
-
-/*
- * Description:
- * Reset Rx
- *
- * Parameters:
- * In:
- * priv - Pointer to the adapter
- * Out:
- * none
- *
- * Return Value: none
- */
-void CARDvSafeResetRx(struct vnt_private *priv)
-{
- unsigned int uu;
- struct vnt_rx_desc *pDesc;
-
- /* initialize RD index */
- priv->pCurrRD[0] = &priv->aRD0Ring[0];
- priv->pCurrRD[1] = &priv->aRD1Ring[0];
-
- /* init state, all RD is chip's */
- for (uu = 0; uu < priv->opts.rx_descs0; uu++) {
- pDesc = &priv->aRD0Ring[uu];
- pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz);
- pDesc->rd0.owner = OWNED_BY_NIC;
- pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz);
- }
-
- /* init state, all RD is chip's */
- for (uu = 0; uu < priv->opts.rx_descs1; uu++) {
- pDesc = &priv->aRD1Ring[uu];
- pDesc->rd0.res_count = cpu_to_le16(priv->rx_buf_sz);
- pDesc->rd0.owner = OWNED_BY_NIC;
- pDesc->rd1.req_count = cpu_to_le16(priv->rx_buf_sz);
- }
-
- /* set perPkt mode */
- iowrite32(RX_PERPKT, priv->port_offset + MAC_REG_RXDMACTL0);
- iowrite32(RX_PERPKT, priv->port_offset + MAC_REG_RXDMACTL1);
- /* set MAC RD pointer */
- vt6655_mac_set_curr_rx_0_desc_addr(priv, priv->rd0_pool_dma);
-
- vt6655_mac_set_curr_rx_1_desc_addr(priv, priv->rd1_pool_dma);
-}
-
-/*
- * Description: Get response Control frame rate in CCK mode
- *
- * Parameters:
- * In:
- * priv - The adapter to be set
- * wRateIdx - Receiving data rate
- * Out:
- * none
- *
- * Return Value: response Control frame rate
- */
-static unsigned short CARDwGetCCKControlRate(struct vnt_private *priv,
- unsigned short wRateIdx)
-{
- unsigned int ui = (unsigned int)wRateIdx;
-
- while (ui > RATE_1M) {
- if (priv->basic_rates & ((u32)0x1 << ui))
- return (unsigned short)ui;
-
- ui--;
- }
- return (unsigned short)RATE_1M;
-}
-
-/*
- * Description: Get response Control frame rate in OFDM mode
- *
- * Parameters:
- * In:
- * priv - The adapter to be set
- * wRateIdx - Receiving data rate
- * Out:
- * none
- *
- * Return Value: response Control frame rate
- */
-static unsigned short CARDwGetOFDMControlRate(struct vnt_private *priv,
- unsigned short wRateIdx)
-{
- unsigned int ui = (unsigned int)wRateIdx;
-
- pr_debug("BASIC RATE: %X\n", priv->basic_rates);
-
- if (!CARDbIsOFDMinBasicRate((void *)priv)) {
- pr_debug("%s:(NO OFDM) %d\n", __func__, wRateIdx);
- if (wRateIdx > RATE_24M)
- wRateIdx = RATE_24M;
- return wRateIdx;
- }
- while (ui > RATE_11M) {
- if (priv->basic_rates & ((u32)0x1 << ui)) {
- pr_debug("%s : %d\n", __func__, ui);
- return (unsigned short)ui;
- }
- ui--;
- }
- pr_debug("%s: 6M\n", __func__);
- return (unsigned short)RATE_24M;
-}
-
-/*
- * Description: Set RSPINF
- *
- * Parameters:
- * In:
- * priv - The adapter to be set
- * Out:
- * none
- *
- * Return Value: None.
- */
-void card_set_rspinf(struct vnt_private *priv, u8 bb_type)
-{
- union vnt_phy_field_swap phy;
- unsigned char byTxRate, byRsvTime; /* For OFDM */
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Set to Page1 */
- VT6655_MAC_SELECT_PAGE1(priv->port_offset);
-
- /* RSPINF_b_1 */
- vnt_get_phy_field(priv, 14,
- CARDwGetCCKControlRate(priv, RATE_1M),
- PK_TYPE_11B, &phy.field_read);
-
- /* swap over to get correct write order */
- swap(phy.swap[0], phy.swap[1]);
-
- iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_1);
-
- /* RSPINF_b_2 */
- vnt_get_phy_field(priv, 14,
- CARDwGetCCKControlRate(priv, RATE_2M),
- PK_TYPE_11B, &phy.field_read);
-
- swap(phy.swap[0], phy.swap[1]);
-
- iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_2);
-
- /* RSPINF_b_5 */
- vnt_get_phy_field(priv, 14,
- CARDwGetCCKControlRate(priv, RATE_5M),
- PK_TYPE_11B, &phy.field_read);
-
- swap(phy.swap[0], phy.swap[1]);
-
- iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_5);
-
- /* RSPINF_b_11 */
- vnt_get_phy_field(priv, 14,
- CARDwGetCCKControlRate(priv, RATE_11M),
- PK_TYPE_11B, &phy.field_read);
-
- swap(phy.swap[0], phy.swap[1]);
-
- iowrite32(phy.field_write, priv->port_offset + MAC_REG_RSPINF_B_11);
-
- /* RSPINF_a_6 */
- calculate_ofdmr_parameter(RATE_6M,
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_6);
- /* RSPINF_a_9 */
- calculate_ofdmr_parameter(RATE_9M,
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_9);
- /* RSPINF_a_12 */
- calculate_ofdmr_parameter(RATE_12M,
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_12);
- /* RSPINF_a_18 */
- calculate_ofdmr_parameter(RATE_18M,
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_18);
- /* RSPINF_a_24 */
- calculate_ofdmr_parameter(RATE_24M,
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_24);
- /* RSPINF_a_36 */
- calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv,
- RATE_36M),
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_36);
- /* RSPINF_a_48 */
- calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv,
- RATE_48M),
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_48);
- /* RSPINF_a_54 */
- calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv,
- RATE_54M),
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_54);
- /* RSPINF_a_72 */
- calculate_ofdmr_parameter(CARDwGetOFDMControlRate((void *)priv,
- RATE_54M),
- bb_type,
- &byTxRate,
- &byRsvTime);
- iowrite16(MAKEWORD(byTxRate, byRsvTime), priv->port_offset + MAC_REG_RSPINF_A_72);
- /* Set to Page0 */
- VT6655_MAC_SELECT_PAGE0(priv->port_offset);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-void CARDvUpdateBasicTopRate(struct vnt_private *priv)
-{
- unsigned char byTopOFDM = RATE_24M, byTopCCK = RATE_1M;
- unsigned char ii;
-
- /* Determines the highest basic rate. */
- for (ii = RATE_54M; ii >= RATE_6M; ii--) {
- if ((priv->basic_rates) & ((u32)(1 << ii))) {
- byTopOFDM = ii;
- break;
- }
- }
- priv->byTopOFDMBasicRate = byTopOFDM;
-
- for (ii = RATE_11M;; ii--) {
- if ((priv->basic_rates) & ((u32)(1 << ii))) {
- byTopCCK = ii;
- break;
- }
- if (ii == RATE_1M)
- break;
- }
- priv->byTopCCKBasicRate = byTopCCK;
-}
-
-bool CARDbIsOFDMinBasicRate(struct vnt_private *priv)
-{
- int ii;
-
- for (ii = RATE_54M; ii >= RATE_6M; ii--) {
- if ((priv->basic_rates) & ((u32)BIT(ii)))
- return true;
- }
- return false;
-}
-
-unsigned char card_get_pkt_type(struct vnt_private *priv)
-{
- if (priv->byBBType == BB_TYPE_11A || priv->byBBType == BB_TYPE_11B)
- return (unsigned char)priv->byBBType;
- else if (CARDbIsOFDMinBasicRate((void *)priv))
- return PK_TYPE_11GA;
- else
- return PK_TYPE_11GB;
-}
-
-/*
- * Description: Calculate TSF offset of two TSF input
- * Get TSF Offset from RxBCN's TSF and local TSF
- *
- * Parameters:
- * In:
- * priv - The adapter to be sync.
- * qwTSF1 - Rx BCN's TSF
- * qwTSF2 - Local TSF
- * Out:
- * none
- *
- * Return Value: TSF Offset value
- */
-u64 card_get_tsf_offset(unsigned char rx_rate, u64 qwTSF1, u64 qwTSF2)
-{
- unsigned short wRxBcnTSFOffst;
-
- wRxBcnTSFOffst = rx_bcn_tsf_off[rx_rate % MAX_RATE];
-
- qwTSF2 += (u64)wRxBcnTSFOffst;
-
- return qwTSF1 - qwTSF2;
-}
-
-/*
- * Description: Read NIC TSF counter
- * Get local TSF counter
- *
- * Parameters:
- * In:
- * priv - The adapter to be read
- * Out:
- * none
- *
- * Return Value: Current TSF counter
- */
-u64 vt6655_get_current_tsf(struct vnt_private *priv)
-{
- void __iomem *iobase = priv->port_offset;
- unsigned short ww;
- unsigned char data;
- u32 low, high;
-
- vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TSFCNTRRD);
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- data = ioread8(iobase + MAC_REG_TFTCTL);
- if (!(data & TFTCTL_TSFCNTRRD))
- break;
- }
- if (ww == W_MAX_TIMEOUT)
- return 0;
- low = ioread32(iobase + MAC_REG_TSFCNTR);
- high = ioread32(iobase + MAC_REG_TSFCNTR + 4);
- return le64_to_cpu(low + ((u64)high << 32));
-}
-
-/*
- * Description: Read NIC TSF counter
- * Get NEXTTBTT from adjusted TSF and Beacon Interval
- *
- * Parameters:
- * In:
- * qwTSF - Current TSF counter
- * wbeaconInterval - Beacon Interval
- * Out:
- * qwCurrTSF - Current TSF counter
- *
- * Return Value: TSF value of next Beacon
- */
-u64 card_get_next_tbtt(u64 qwTSF, unsigned short beacon_interval)
-{
- u32 beacon_int;
-
- beacon_int = beacon_interval * 1024;
- if (beacon_int) {
- do_div(qwTSF, beacon_int);
- qwTSF += 1;
- qwTSF *= beacon_int;
- }
-
- return qwTSF;
-}
-
-/*
- * Description: Set NIC TSF counter for first Beacon time
- * Get NEXTTBTT from adjusted TSF and Beacon Interval
- *
- * Parameters:
- * In:
- * iobase - IO Base
- * beacon_interval - Beacon Interval
- * Out:
- * none
- *
- * Return Value: none
- */
-void CARDvSetFirstNextTBTT(struct vnt_private *priv,
- unsigned short beacon_interval)
-{
- void __iomem *iobase = priv->port_offset;
- u64 next_tbtt;
-
- next_tbtt = vt6655_get_current_tsf(priv); /* Get Local TSF counter */
-
- next_tbtt = card_get_next_tbtt(next_tbtt, beacon_interval);
- /* Set NextTBTT */
- next_tbtt = le64_to_cpu(next_tbtt);
- iowrite32((u32)next_tbtt, iobase + MAC_REG_NEXTTBTT);
- iowrite32((u32)(next_tbtt >> 32), iobase + MAC_REG_NEXTTBTT + 4);
- vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
-}
-
-/*
- * Description: Sync NIC TSF counter for Beacon time
- * Get NEXTTBTT and write to HW
- *
- * Parameters:
- * In:
- * priv - The adapter to be set
- * qwTSF - Current TSF counter
- * beacon_interval - Beacon Interval
- * Out:
- * none
- *
- * Return Value: none
- */
-void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF,
- unsigned short beacon_interval)
-{
- void __iomem *iobase = priv->port_offset;
-
- qwTSF = card_get_next_tbtt(qwTSF, beacon_interval);
- /* Set NextTBTT */
- qwTSF = le64_to_cpu(qwTSF);
- iowrite32((u32)qwTSF, iobase + MAC_REG_NEXTTBTT);
- iowrite32((u32)(qwTSF >> 32), iobase + MAC_REG_NEXTTBTT + 4);
- vt6655_mac_reg_bits_on(iobase, MAC_REG_TFTCTL, TFTCTL_TBTTSYNCEN);
- pr_debug("Card:Update Next TBTT[%8llx]\n", qwTSF);
-}
diff --git a/drivers/staging/vt6655/card.h b/drivers/staging/vt6655/card.h
deleted file mode 100644
index f6b462ebca51..000000000000
--- a/drivers/staging/vt6655/card.h
+++ /dev/null
@@ -1,62 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Provide functions to setup NIC operation mode
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- */
-
-#ifndef __CARD_H__
-#define __CARD_H__
-
-#include <linux/types.h>
-#include <linux/nl80211.h>
-
-/*
- * Loopback mode
- *
- * LOBYTE is MAC LB mode, HIBYTE is MII LB mode
- */
-#define CARD_LB_NONE MAKEWORD(MAC_LB_NONE, 0)
-/* PHY must ISO, avoid MAC loopback packet go out */
-#define CARD_LB_MAC MAKEWORD(MAC_LB_INTERNAL, 0)
-#define CARD_LB_PHY MAKEWORD(MAC_LB_EXT, 0)
-
-#define DEFAULT_MSDU_LIFETIME 512 /* ms */
-#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 /* 64us */
-
-#define DEFAULT_MGN_LIFETIME 8 /* ms */
-#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */
-
-#define CB_MAX_CHANNEL_24G 14
-#define CB_MAX_CHANNEL_5G 42
-#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G)
-
-struct vnt_private;
-
-void card_set_rspinf(struct vnt_private *priv, u8 bb_type);
-void CARDvUpdateBasicTopRate(struct vnt_private *priv);
-bool CARDbIsOFDMinBasicRate(struct vnt_private *priv);
-void CARDvSetFirstNextTBTT(struct vnt_private *priv,
- unsigned short beacon_interval);
-void CARDvUpdateNextTBTT(struct vnt_private *priv, u64 qwTSF,
- unsigned short beacon_interval);
-u64 vt6655_get_current_tsf(struct vnt_private *priv);
-u64 card_get_next_tbtt(u64 qwTSF, unsigned short beacon_interval);
-u64 card_get_tsf_offset(unsigned char rx_rate, u64 qwTSF1, u64 qwTSF2);
-unsigned char card_get_pkt_type(struct vnt_private *priv);
-void card_safe_reset_tx(struct vnt_private *priv);
-void CARDvSafeResetRx(struct vnt_private *priv);
-void card_radio_power_off(struct vnt_private *priv);
-bool card_set_phy_parameter(struct vnt_private *priv, u8 bb_type);
-bool card_update_tsf(struct vnt_private *priv, unsigned char rx_rate,
- u64 bss_timestamp);
-bool card_set_beacon_period(struct vnt_private *priv,
- unsigned short beacon_interval);
-
-#endif /* __CARD_H__ */
diff --git a/drivers/staging/vt6655/channel.c b/drivers/staging/vt6655/channel.c
deleted file mode 100644
index 771c1364b0f0..000000000000
--- a/drivers/staging/vt6655/channel.c
+++ /dev/null
@@ -1,135 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- */
-
-#include "baseband.h"
-#include "channel.h"
-#include "device.h"
-#include "rf.h"
-
-static struct ieee80211_rate vnt_rates_bg[] = {
- { .bitrate = 10, .hw_value = RATE_1M },
- { .bitrate = 20, .hw_value = RATE_2M },
- { .bitrate = 55, .hw_value = RATE_5M },
- { .bitrate = 110, .hw_value = RATE_11M },
- { .bitrate = 60, .hw_value = RATE_6M },
- { .bitrate = 90, .hw_value = RATE_9M },
- { .bitrate = 120, .hw_value = RATE_12M },
- { .bitrate = 180, .hw_value = RATE_18M },
- { .bitrate = 240, .hw_value = RATE_24M },
- { .bitrate = 360, .hw_value = RATE_36M },
- { .bitrate = 480, .hw_value = RATE_48M },
- { .bitrate = 540, .hw_value = RATE_54M },
-};
-
-static struct ieee80211_channel vnt_channels_2ghz[] = {
- { .center_freq = 2412, .hw_value = 1 },
- { .center_freq = 2417, .hw_value = 2 },
- { .center_freq = 2422, .hw_value = 3 },
- { .center_freq = 2427, .hw_value = 4 },
- { .center_freq = 2432, .hw_value = 5 },
- { .center_freq = 2437, .hw_value = 6 },
- { .center_freq = 2442, .hw_value = 7 },
- { .center_freq = 2447, .hw_value = 8 },
- { .center_freq = 2452, .hw_value = 9 },
- { .center_freq = 2457, .hw_value = 10 },
- { .center_freq = 2462, .hw_value = 11 },
- { .center_freq = 2467, .hw_value = 12 },
- { .center_freq = 2472, .hw_value = 13 },
- { .center_freq = 2484, .hw_value = 14 }
-};
-
-static struct ieee80211_supported_band vnt_supported_2ghz_band = {
- .channels = vnt_channels_2ghz,
- .n_channels = ARRAY_SIZE(vnt_channels_2ghz),
- .bitrates = vnt_rates_bg,
- .n_bitrates = ARRAY_SIZE(vnt_rates_bg),
-};
-
-static void vnt_init_band(struct vnt_private *priv,
- struct ieee80211_supported_band *supported_band,
- enum nl80211_band band)
-{
- int i;
-
- for (i = 0; i < supported_band->n_channels; i++) {
- supported_band->channels[i].max_power = 0x3f;
- supported_band->channels[i].flags =
- IEEE80211_CHAN_NO_HT40;
- }
-
- priv->hw->wiphy->bands[band] = supported_band;
-}
-
-void vnt_init_bands(struct vnt_private *priv)
-{
- vnt_init_band(priv, &vnt_supported_2ghz_band, NL80211_BAND_2GHZ);
-}
-
-/**
- * set_channel() - Set NIC media channel
- *
- * @priv: The adapter to be set
- * @ch: Channel to be set
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch)
-{
- bool ret = true;
-
- if (priv->current_ch == ch->hw_value)
- return ret;
-
- /* Set VGA to max sensitivity */
- if (priv->update_bbvga &&
- priv->bbvga_current != priv->bbvga[0]) {
- priv->bbvga_current = priv->bbvga[0];
-
- bb_set_vga_gain_offset(priv, priv->bbvga_current);
- }
-
- /* clear NAV */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_MACCR, MACCR_CLRNAV);
-
- /* TX_PE will reserve 3 us for MAX2829 A mode only,
- * it is for better TX throughput
- */
-
- priv->current_ch = ch->hw_value;
- ret &= RFbSelectChannel(priv, priv->rf_type,
- ch->hw_value);
-
- /* Init Synthesizer Table */
- if (priv->bEnablePSMode)
- rf_write_wake_prog_syn(priv, priv->rf_type, ch->hw_value);
-
- bb_software_reset(priv);
-
- if (priv->local_id > REV_ID_VT3253_B1) {
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* set HW default power register */
- VT6655_MAC_SELECT_PAGE1(priv->port_offset);
- RFbSetPower(priv, RATE_1M, priv->current_ch);
- iowrite8(priv->cur_pwr, priv->port_offset + MAC_REG_PWRCCK);
- RFbSetPower(priv, RATE_6M, priv->current_ch);
- iowrite8(priv->cur_pwr, priv->port_offset + MAC_REG_PWROFDM);
- VT6655_MAC_SELECT_PAGE0(priv->port_offset);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
- if (priv->byBBType == BB_TYPE_11B)
- RFbSetPower(priv, RATE_1M, priv->current_ch);
- else
- RFbSetPower(priv, RATE_6M, priv->current_ch);
-
- return ret;
-}
diff --git a/drivers/staging/vt6655/channel.h b/drivers/staging/vt6655/channel.h
deleted file mode 100644
index 78b2d82317e5..000000000000
--- a/drivers/staging/vt6655/channel.h
+++ /dev/null
@@ -1,17 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- */
-
-#ifndef _CHANNEL_H_
-#define _CHANNEL_H_
-
-#include "card.h"
-
-void vnt_init_bands(struct vnt_private *priv);
-
-bool set_channel(struct vnt_private *priv, struct ieee80211_channel *ch);
-
-#endif /* _CHANNEL_H_ */
diff --git a/drivers/staging/vt6655/desc.h b/drivers/staging/vt6655/desc.h
deleted file mode 100644
index 17a40c53b8ff..000000000000
--- a/drivers/staging/vt6655/desc.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:The header file of descriptor
- *
- * Revision History:
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- */
-
-#ifndef __DESC_H__
-#define __DESC_H__
-
-#include <linux/types.h>
-#include <linux/mm.h>
-#include "linux/ieee80211.h"
-
-#define B_OWNED_BY_CHIP 1
-#define B_OWNED_BY_HOST 0
-
-/* Bits in the RSR register */
-#define RSR_ADDRBROAD 0x80
-#define RSR_ADDRMULTI 0x40
-#define RSR_ADDRUNI 0x00
-#define RSR_IVLDTYP 0x20
-#define RSR_IVLDLEN 0x10 /* invalid len (> 2312 byte) */
-#define RSR_BSSIDOK 0x08
-#define RSR_CRCOK 0x04
-#define RSR_BCNSSIDOK 0x02
-#define RSR_ADDROK 0x01
-
-/* Bits in the new RSR register */
-#define NEWRSR_DECRYPTOK 0x10
-#define NEWRSR_CFPIND 0x08
-#define NEWRSR_HWUTSF 0x04
-#define NEWRSR_BCNHITAID 0x02
-#define NEWRSR_BCNHITAID0 0x01
-
-/* Bits in the TSR0 register */
-#define TSR0_PWRSTS1_2 0xC0
-#define TSR0_PWRSTS7 0x20
-#define TSR0_NCR 0x1F
-
-/* Bits in the TSR1 register */
-#define TSR1_TERR 0x80
-#define TSR1_PWRSTS4_6 0x70
-#define TSR1_RETRYTMO 0x08
-#define TSR1_TMO 0x04
-#define TSR1_PWRSTS3 0x02
-#define ACK_DATA 0x01
-
-/* Bits in the TCR register */
-#define EDMSDU 0x04 /* end of sdu */
-#define TCR_EDP 0x02 /* end of packet */
-#define TCR_STP 0x01 /* start of packet */
-
-/* max transmit or receive buffer size */
-#define CB_MAX_BUF_SIZE 2900U
- /* NOTE: must be multiple of 4 */
-#define CB_MAX_TX_BUF_SIZE CB_MAX_BUF_SIZE
-#define CB_MAX_RX_BUF_SIZE_NORMAL CB_MAX_BUF_SIZE
-
-#define CB_BEACON_BUF_SIZE 512U
-
-#define CB_MAX_RX_DESC 128
-#define CB_MIN_RX_DESC 16
-#define CB_MAX_TX_DESC 64
-#define CB_MIN_TX_DESC 16
-
-#define CB_MAX_RECEIVED_PACKETS 16
- /*
- * limit our receive routine to indicating
- * this many at a time for 2 reasons:
- * 1. driver flow control to protocol layer
- * 2. limit the time used in ISR routine
- */
-
-#define CB_EXTRA_RD_NUM 32
-#define CB_RD_NUM 32
-#define CB_TD_NUM 32
-
-/*
- * max number of physical segments in a single NDIS packet. Above this
- * threshold, the packet is copied into a single physically contiguous buffer
- */
-#define CB_MAX_SEGMENT 4
-
-#define CB_MIN_MAP_REG_NUM 4
-#define CB_MAX_MAP_REG_NUM CB_MAX_TX_DESC
-
-#define CB_PROTOCOL_RESERVED_SECTION 16
-
-/*
- * if retrys excess 15 times , tx will abort, and if tx fifo underflow,
- * tx will fail, we should try to resend it
- */
-#define CB_MAX_TX_ABORT_RETRY 3
-
-/* WMAC definition FIFO Control */
-#define FIFOCTL_AUTO_FB_1 0x1000
-#define FIFOCTL_AUTO_FB_0 0x0800
-#define FIFOCTL_GRPACK 0x0400
-#define FIFOCTL_11GA 0x0300
-#define FIFOCTL_11GB 0x0200
-#define FIFOCTL_11B 0x0100
-#define FIFOCTL_11A 0x0000
-#define FIFOCTL_RTS 0x0080
-#define FIFOCTL_ISDMA0 0x0040
-#define FIFOCTL_GENINT 0x0020
-#define FIFOCTL_TMOEN 0x0010
-#define FIFOCTL_LRETRY 0x0008
-#define FIFOCTL_CRCDIS 0x0004
-#define FIFOCTL_NEEDACK 0x0002
-#define FIFOCTL_LHEAD 0x0001
-
-/* WMAC definition Frag Control */
-#define FRAGCTL_AES 0x0300
-#define FRAGCTL_TKIP 0x0200
-#define FRAGCTL_LEGACY 0x0100
-#define FRAGCTL_NONENCRYPT 0x0000
-#define FRAGCTL_ENDFRAG 0x0003
-#define FRAGCTL_MIDFRAG 0x0002
-#define FRAGCTL_STAFRAG 0x0001
-#define FRAGCTL_NONFRAG 0x0000
-
-#define TYPE_TXDMA0 0
-#define TYPE_AC0DMA 1
-#define TYPE_ATIMDMA 2
-#define TYPE_SYNCDMA 3
-#define TYPE_MAXTD 2
-
-#define TYPE_BEACONDMA 4
-
-#define TYPE_RXDMA0 0
-#define TYPE_RXDMA1 1
-#define TYPE_MAXRD 2
-
-/* TD_INFO flags control bit */
-#define TD_FLAGS_NETIF_SKB 0x01 /* check if need release skb */
-/* check if called from private skb (hostap) */
-#define TD_FLAGS_PRIV_SKB 0x02
-#define TD_FLAGS_PS_RETRY 0x04 /* check if PS STA frame re-transmit */
-
-/*
- * ref_sk_buff is used for mapping the skb structure between pre-built
- * driver-obj & running kernel. Since different kernel version (2.4x) may
- * change skb structure, i.e. pre-built driver-obj may link to older skb that
- * leads error.
- */
-
-struct vnt_rd_info {
- struct sk_buff *skb;
- dma_addr_t skb_dma;
-};
-
-struct vnt_rdes0 {
- volatile __le16 res_count;
-#ifdef __BIG_ENDIAN
- union {
- volatile u16 f15_reserved;
- struct {
- volatile u8 f8_reserved1;
- volatile u8 owner:1;
- volatile u8 f7_reserved:7;
- } __packed;
- } __packed;
-#else
- u16 f15_reserved:15;
- u16 owner:1;
-#endif
-} __packed;
-
-struct vnt_rdes1 {
- __le16 req_count;
- u16 reserved;
-} __packed;
-
-/* Rx descriptor*/
-struct vnt_rx_desc {
- volatile struct vnt_rdes0 rd0;
- volatile struct vnt_rdes1 rd1;
- volatile __le32 buff_addr;
- volatile __le32 next_desc;
- struct vnt_rx_desc *next __aligned(8);
- struct vnt_rd_info *rd_info __aligned(8);
-} __packed;
-
-struct vnt_tdes0 {
- volatile u8 tsr0;
- volatile u8 tsr1;
-#ifdef __BIG_ENDIAN
- union {
- volatile u16 f15_txtime;
- struct {
- volatile u8 f8_reserved;
- volatile u8 owner:1;
- volatile u8 f7_reserved:7;
- } __packed;
- } __packed;
-#else
- volatile u16 f15_txtime:15;
- volatile u16 owner:1;
-#endif
-} __packed;
-
-struct vnt_tdes1 {
- volatile __le16 req_count;
- volatile u8 tcr;
- volatile u8 reserved;
-} __packed;
-
-struct vnt_td_info {
- void *mic_hdr;
- struct sk_buff *skb;
- unsigned char *buf;
- dma_addr_t buf_dma;
- u16 req_count;
- u8 flags;
-};
-
-/* transmit descriptor */
-struct vnt_tx_desc {
- volatile struct vnt_tdes0 td0;
- volatile struct vnt_tdes1 td1;
- volatile __le32 buff_addr;
- volatile __le32 next_desc;
- struct vnt_tx_desc *next __aligned(8);
- struct vnt_td_info *td_info __aligned(8);
-} __packed;
-
-/* Length, Service, and Signal fields of Phy for Tx */
-struct vnt_phy_field {
- u8 signal;
- u8 service;
- __le16 len;
-} __packed;
-
-union vnt_phy_field_swap {
- struct vnt_phy_field field_read;
- u16 swap[2];
- u32 field_write;
-};
-
-#endif /* __DESC_H__ */
diff --git a/drivers/staging/vt6655/device.h b/drivers/staging/vt6655/device.h
deleted file mode 100644
index 5eaab6b172d3..000000000000
--- a/drivers/staging/vt6655/device.h
+++ /dev/null
@@ -1,292 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC Data structure
- *
- * Author: Tevin Chen
- *
- * Date: Mar 17, 1997
- *
- */
-
-#ifndef __DEVICE_H__
-#define __DEVICE_H__
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/pci.h>
-#include <linux/etherdevice.h>
-#include <linux/skbuff.h>
-#include <linux/interrupt.h>
-#include <linux/crc32.h>
-#include <net/mac80211.h>
-
-/* device specific */
-
-#include "device_cfg.h"
-#include "card.h"
-#include "srom.h"
-#include "desc.h"
-#include "key.h"
-#include "mac.h"
-
-/*--------------------- Export Definitions -------------------------*/
-
-#define RATE_1M 0
-#define RATE_2M 1
-#define RATE_5M 2
-#define RATE_11M 3
-#define RATE_6M 4
-#define RATE_9M 5
-#define RATE_12M 6
-#define RATE_18M 7
-#define RATE_24M 8
-#define RATE_36M 9
-#define RATE_48M 10
-#define RATE_54M 11
-#define MAX_RATE 12
-
-#define AUTO_FB_NONE 0
-#define AUTO_FB_0 1
-#define AUTO_FB_1 2
-
-#define FB_RATE0 0
-#define FB_RATE1 1
-
-/* Antenna Mode */
-#define ANT_A 0
-#define ANT_B 1
-#define ANT_DIVERSITY 2
-#define ANT_RXD_TXA 3
-#define ANT_RXD_TXB 4
-#define ANT_UNKNOWN 0xFF
-
-#define BB_VGA_LEVEL 4
-#define BB_VGA_CHANGE_THRESHOLD 16
-
-#define MAKE_BEACON_RESERVED 10 /* (us) */
-
-/* BUILD OBJ mode */
-
-#define AVAIL_TD(p, q) ((p)->opts.tx_descs[(q)] - ((p)->iTDUsed[(q)]))
-
-/* 0:11A 1:11B 2:11G */
-#define BB_TYPE_11A 0
-#define BB_TYPE_11B 1
-#define BB_TYPE_11G 2
-
-/* 0:11a, 1:11b, 2:11gb (only CCK in BasicRate), 3:11ga (OFDM in BasicRate) */
-#define PK_TYPE_11A 0
-#define PK_TYPE_11B 1
-#define PK_TYPE_11GB 2
-#define PK_TYPE_11GA 3
-
-#define OWNED_BY_HOST 0
-#define OWNED_BY_NIC 1
-
-struct vnt_options {
- int rx_descs0; /* Number of RX descriptors0 */
- int rx_descs1; /* Number of RX descriptors1 */
- int tx_descs[2]; /* Number of TX descriptors 0, 1 */
- int int_works; /* interrupt limits */
- int short_retry;
- int long_retry;
- int bbp_type;
- u32 flags;
-};
-
-struct vnt_private {
- struct pci_dev *pcid;
- /* mac80211 */
- struct ieee80211_hw *hw;
- struct ieee80211_vif *vif;
- unsigned long key_entry_inuse;
- u32 basic_rates;
- u16 current_aid;
- int mc_list_count;
- u8 mac_hw;
-
-/* dma addr, rx/tx pool */
- dma_addr_t pool_dma;
- dma_addr_t rd0_pool_dma;
- dma_addr_t rd1_pool_dma;
-
- dma_addr_t td0_pool_dma;
- dma_addr_t td1_pool_dma;
-
- dma_addr_t tx_bufs_dma0;
- dma_addr_t tx_bufs_dma1;
- dma_addr_t tx_beacon_dma;
-
- unsigned char *tx0_bufs;
- unsigned char *tx1_bufs;
- unsigned char *tx_beacon_bufs;
-
- void __iomem *port_offset;
- u32 memaddr;
- u32 ioaddr;
-
- spinlock_t lock;
-
- volatile int iTDUsed[TYPE_MAXTD];
-
- struct vnt_tx_desc *apCurrTD[TYPE_MAXTD];
- struct vnt_tx_desc *tail_td[TYPE_MAXTD];
-
- struct vnt_tx_desc *ap_td0_rings;
- struct vnt_tx_desc *ap_td1_rings;
-
- struct vnt_rx_desc *aRD0Ring;
- struct vnt_rx_desc *aRD1Ring;
- struct vnt_rx_desc *pCurrRD[TYPE_MAXRD];
-
- struct vnt_options opts;
-
- u32 flags;
-
- u32 rx_buf_sz;
- u8 rx_rate;
-
- u32 rx_bytes;
-
- /* Version control */
- unsigned char local_id;
- unsigned char rf_type;
-
- unsigned char max_pwr_level;
- unsigned char byZoneType;
- bool bZoneRegExist;
- unsigned char byOriginalZonetype;
-
- unsigned char abyCurrentNetAddr[ETH_ALEN]; __aligned(2)
- bool bLinkPass; /* link status: OK or fail */
-
- unsigned int current_rssi;
- unsigned char byCurrSQ;
-
- unsigned long dwTxAntennaSel;
- unsigned long dwRxAntennaSel;
- unsigned char byAntennaCount;
- unsigned char byRxAntennaMode;
- unsigned char byTxAntennaMode;
- bool bTxRxAntInv;
-
- unsigned char *pbyTmpBuff;
- unsigned int uSIFS; /* Current SIFS */
- unsigned int uDIFS; /* Current DIFS */
- unsigned int uEIFS; /* Current EIFS */
- unsigned int uSlot; /* Current SlotTime */
- unsigned int uCwMin; /* Current CwMin */
- unsigned int uCwMax; /* CwMax is fixed on 1023. */
- /* PHY parameter */
- unsigned char sifs;
- unsigned char difs;
- unsigned char eifs;
- unsigned char slot;
- unsigned char cw_max_min;
-
- u8 byBBType; /* 0:11A, 1:11B, 2:11G */
- u8 packet_type; /*
- * 0:11a,1:11b,2:11gb (only CCK
- * in BasicRate), 3:11ga (OFDM in
- * Basic Rate)
- */
- unsigned short wBasicRate;
- unsigned char byACKRate;
- unsigned char byTopOFDMBasicRate;
- unsigned char byTopCCKBasicRate;
-
- unsigned char byMinChannel;
- unsigned char byMaxChannel;
-
- unsigned char preamble_type;
- unsigned char byShortPreamble;
-
- unsigned short wCurrentRate;
- unsigned char byShortRetryLimit;
- unsigned char byLongRetryLimit;
- enum nl80211_iftype op_mode;
- bool bBSSIDFilter;
- unsigned short wMaxTransmitMSDULifetime;
-
- bool bEncryptionEnable;
- bool bLongHeader;
- bool short_slot_time;
- bool bProtectMode;
- bool bNonERPPresent;
- bool bBarkerPreambleMd;
-
- bool bRadioControlOff;
- bool radio_off;
- bool bEnablePSMode;
- unsigned short wListenInterval;
- bool bPWBitOn;
-
- /* GPIO Radio Control */
- unsigned char byRadioCtl;
- unsigned char byGPIO;
- bool hw_radio_off;
- bool bPrvActive4RadioOFF;
- bool bGPIOBlockRead;
-
- /* Beacon related */
- unsigned short wSeqCounter;
- unsigned short wBCNBufLen;
- bool bBeaconBufReady;
- bool bBeaconSent;
- bool bIsBeaconBufReadySet;
- unsigned int cbBeaconBufReadySetCnt;
- bool bFixRate;
- u16 current_ch;
-
- bool bAES;
-
- unsigned char byAutoFBCtrl;
-
- /* For Update BaseBand VGA Gain Offset */
- bool update_bbvga;
- unsigned int uBBVGADiffCount;
- unsigned char bbvga_new;
- unsigned char bbvga_current;
- unsigned char bbvga[BB_VGA_LEVEL];
- long dbm_threshold[BB_VGA_LEVEL];
-
- unsigned char bb_pre_edrssi;
- unsigned char byBBPreEDIndex;
-
- unsigned long dwDiagRefCount;
-
- /* For FOE Tuning */
- unsigned char byFOETuning;
-
- /* For RF Power table */
- unsigned char byCCKPwr;
- unsigned char byOFDMPwrG;
- unsigned char cur_pwr;
- char byCurPwrdBm;
- unsigned char abyCCKPwrTbl[CB_MAX_CHANNEL_24G + 1];
- unsigned char abyOFDMPwrTbl[CB_MAX_CHANNEL + 1];
- char abyCCKDefaultPwr[CB_MAX_CHANNEL_24G + 1];
- char abyOFDMDefaultPwr[CB_MAX_CHANNEL + 1];
- char abyRegPwr[CB_MAX_CHANNEL + 1];
- char abyLocalPwr[CB_MAX_CHANNEL + 1];
-
- /* BaseBand Loopback Use */
- unsigned char byBBCR4d;
- unsigned char byBBCRc9;
- unsigned char byBBCR88;
- unsigned char byBBCR09;
-
- unsigned char abyEEPROM[EEP_MAX_CONTEXT_SIZE]; /* unsigned long alignment */
-
- unsigned short beacon_interval;
- u16 wake_up_count;
-
- struct work_struct interrupt_work;
-
- struct ieee80211_low_level_stats low_stats;
-};
-
-#endif
diff --git a/drivers/staging/vt6655/device_cfg.h b/drivers/staging/vt6655/device_cfg.h
deleted file mode 100644
index 2d647a3619ba..000000000000
--- a/drivers/staging/vt6655/device_cfg.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Driver configuration header
- * Author: Lyndon Chen
- *
- * Date: Dec 17, 2002
- *
- */
-
-#ifndef __DEVICE_CONFIG_H
-#define __DEVICE_CONFIG_H
-
-#include <linux/types.h>
-
-#define VID_TABLE_SIZE 64
-#define MCAST_TABLE_SIZE 64
-#define MCAM_SIZE 32
-#define VCAM_SIZE 32
-#define TX_QUEUE_NO 8
-
-#define DEVICE_NAME "vt6655"
-#define DEVICE_FULL_DRV_NAM "VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver"
-
-#ifndef MAJOR_VERSION
-#define MAJOR_VERSION 1
-#endif
-
-#ifndef MINOR_VERSION
-#define MINOR_VERSION 17
-#endif
-
-#ifndef DEVICE_VERSION
-#define DEVICE_VERSION "1.19.12"
-#endif
-
-#include <linux/fs.h>
-#include <linux/fcntl.h>
-
-#define PKT_BUF_SZ 2390
-
-#endif
diff --git a/drivers/staging/vt6655/device_main.c b/drivers/staging/vt6655/device_main.c
deleted file mode 100644
index bf3ecf720206..000000000000
--- a/drivers/staging/vt6655/device_main.c
+++ /dev/null
@@ -1,1868 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: driver entry for initial, open, close, tx and rx.
- *
- * Author: Lyndon Chen
- *
- * Date: Jan 8, 2003
- *
- * Functions:
- *
- * vt6655_probe - module initial (insmod) driver entry
- * vt6655_remove - module remove entry
- * device_free_info - device structure resource free function
- * device_print_info - print out resource
- * device_rx_srv - rx service function
- * device_alloc_rx_buf - rx buffer pre-allocated function
- * device_free_rx_buf - free rx buffer function
- * device_free_tx_buf - free tx buffer function
- * device_init_rd0_ring - initial rd dma0 ring
- * device_init_rd1_ring - initial rd dma1 ring
- * device_init_td0_ring - initial tx dma0 ring buffer
- * device_init_td1_ring - initial tx dma1 ring buffer
- * device_init_registers - initial MAC & BBP & RF internal registers.
- * device_init_rings - initial tx/rx ring buffer
- * device_free_rings - free all allocated ring buffer
- * device_tx_srv - tx interrupt service function
- *
- * Revision History:
- */
-
-#include <linux/file.h>
-#include "device.h"
-#include "card.h"
-#include "channel.h"
-#include "baseband.h"
-#include "mac.h"
-#include "power.h"
-#include "rxtx.h"
-#include "dpc.h"
-#include "rf.h"
-#include <linux/delay.h>
-#include <linux/kthread.h>
-#include <linux/slab.h>
-
-/*--------------------- Static Definitions -------------------------*/
-/*
- * Define module options
- */
-MODULE_AUTHOR("VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>");
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("VIA Networking Solomon-A/B/G Wireless LAN Adapter Driver");
-
-#define DEVICE_PARAM(N, D)
-
-#define RX_DESC_MIN0 16
-#define RX_DESC_MAX0 128
-#define RX_DESC_DEF0 32
-DEVICE_PARAM(RxDescriptors0, "Number of receive descriptors0");
-
-#define RX_DESC_MIN1 16
-#define RX_DESC_MAX1 128
-#define RX_DESC_DEF1 32
-DEVICE_PARAM(RxDescriptors1, "Number of receive descriptors1");
-
-#define TX_DESC_MIN0 16
-#define TX_DESC_MAX0 128
-#define TX_DESC_DEF0 32
-DEVICE_PARAM(TxDescriptors0, "Number of transmit descriptors0");
-
-#define TX_DESC_MIN1 16
-#define TX_DESC_MAX1 128
-#define TX_DESC_DEF1 64
-DEVICE_PARAM(TxDescriptors1, "Number of transmit descriptors1");
-
-#define INT_WORKS_DEF 20
-#define INT_WORKS_MIN 10
-#define INT_WORKS_MAX 64
-
-DEVICE_PARAM(int_works, "Number of packets per interrupt services");
-
-#define RTS_THRESH_DEF 2347
-
-#define FRAG_THRESH_DEF 2346
-
-#define SHORT_RETRY_MIN 0
-#define SHORT_RETRY_MAX 31
-#define SHORT_RETRY_DEF 8
-
-DEVICE_PARAM(ShortRetryLimit, "Short frame retry limits");
-
-#define LONG_RETRY_MIN 0
-#define LONG_RETRY_MAX 15
-#define LONG_RETRY_DEF 4
-
-DEVICE_PARAM(LongRetryLimit, "long frame retry limits");
-
-/* BasebandType[] baseband type selected
- * 0: indicate 802.11a type
- * 1: indicate 802.11b type
- * 2: indicate 802.11g type
- */
-#define BBP_TYPE_MIN 0
-#define BBP_TYPE_MAX 2
-#define BBP_TYPE_DEF 2
-
-DEVICE_PARAM(BasebandType, "baseband type");
-
-/*
- * Static vars definitions
- */
-static const struct pci_device_id vt6655_pci_id_table[] = {
- { PCI_VDEVICE(VIA, 0x3253) },
- { 0, }
-};
-
-/*--------------------- Static Functions --------------------------*/
-
-static int vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent);
-static void device_free_info(struct vnt_private *priv);
-static void device_print_info(struct vnt_private *priv);
-
-static void vt6655_mac_write_bssid_addr(void __iomem *iobase, const u8 *mac_addr);
-static void vt6655_mac_read_ether_addr(void __iomem *iobase, u8 *mac_addr);
-
-static int device_init_rd0_ring(struct vnt_private *priv);
-static int device_init_rd1_ring(struct vnt_private *priv);
-static int device_init_td0_ring(struct vnt_private *priv);
-static int device_init_td1_ring(struct vnt_private *priv);
-
-static int device_rx_srv(struct vnt_private *priv, unsigned int idx);
-static int device_tx_srv(struct vnt_private *priv, unsigned int idx);
-static bool device_alloc_rx_buf(struct vnt_private *, struct vnt_rx_desc *);
-static void device_free_rx_buf(struct vnt_private *priv,
- struct vnt_rx_desc *rd);
-static void device_init_registers(struct vnt_private *priv);
-static void device_free_tx_buf(struct vnt_private *, struct vnt_tx_desc *);
-static void device_free_td0_ring(struct vnt_private *priv);
-static void device_free_td1_ring(struct vnt_private *priv);
-static void device_free_rd0_ring(struct vnt_private *priv);
-static void device_free_rd1_ring(struct vnt_private *priv);
-static void device_free_rings(struct vnt_private *priv);
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-static void vt6655_remove(struct pci_dev *pcid)
-{
- struct vnt_private *priv = pci_get_drvdata(pcid);
-
- if (!priv)
- return;
- device_free_info(priv);
-}
-
-static void device_get_options(struct vnt_private *priv)
-{
- struct vnt_options *opts = &priv->opts;
-
- opts->rx_descs0 = RX_DESC_DEF0;
- opts->rx_descs1 = RX_DESC_DEF1;
- opts->tx_descs[0] = TX_DESC_DEF0;
- opts->tx_descs[1] = TX_DESC_DEF1;
- opts->int_works = INT_WORKS_DEF;
-
- opts->short_retry = SHORT_RETRY_DEF;
- opts->long_retry = LONG_RETRY_DEF;
- opts->bbp_type = BBP_TYPE_DEF;
-}
-
-static void
-device_set_options(struct vnt_private *priv)
-{
- priv->byShortRetryLimit = priv->opts.short_retry;
- priv->byLongRetryLimit = priv->opts.long_retry;
- priv->byBBType = priv->opts.bbp_type;
- priv->packet_type = priv->byBBType;
- priv->byAutoFBCtrl = AUTO_FB_0;
- priv->update_bbvga = true;
- priv->preamble_type = 0;
-
- pr_debug(" byShortRetryLimit= %d\n", (int)priv->byShortRetryLimit);
- pr_debug(" byLongRetryLimit= %d\n", (int)priv->byLongRetryLimit);
- pr_debug(" preamble_type= %d\n", (int)priv->preamble_type);
- pr_debug(" byShortPreamble= %d\n", (int)priv->byShortPreamble);
- pr_debug(" byBBType= %d\n", (int)priv->byBBType);
-}
-
-static void vt6655_mac_write_bssid_addr(void __iomem *iobase, const u8 *mac_addr)
-{
- iowrite8(1, iobase + MAC_REG_PAGE1SEL);
- for (int i = 0; i < 6; i++)
- iowrite8(mac_addr[i], iobase + MAC_REG_BSSID0 + i);
- iowrite8(0, iobase + MAC_REG_PAGE1SEL);
-}
-
-static void vt6655_mac_read_ether_addr(void __iomem *iobase, u8 *mac_addr)
-{
- iowrite8(1, iobase + MAC_REG_PAGE1SEL);
- for (int i = 0; i < 6; i++)
- mac_addr[i] = ioread8(iobase + MAC_REG_PAR0 + i);
- iowrite8(0, iobase + MAC_REG_PAGE1SEL);
-}
-
-static void vt6655_mac_dma_ctl(void __iomem *iobase, u8 reg_index)
-{
- u32 reg_value;
-
- reg_value = ioread32(iobase + reg_index);
- if (reg_value & DMACTL_RUN)
- iowrite32(DMACTL_WAKE, iobase + reg_index);
- else
- iowrite32(DMACTL_RUN, iobase + reg_index);
-}
-
-static void vt6655_mac_set_bits(void __iomem *iobase, u32 mask)
-{
- u32 reg_value;
-
- reg_value = ioread32(iobase + MAC_REG_ENCFG);
- reg_value = reg_value | mask;
- iowrite32(reg_value, iobase + MAC_REG_ENCFG);
-}
-
-static void vt6655_mac_clear_bits(void __iomem *iobase, u32 mask)
-{
- u32 reg_value;
-
- reg_value = ioread32(iobase + MAC_REG_ENCFG);
- reg_value = reg_value & ~mask;
- iowrite32(reg_value, iobase + MAC_REG_ENCFG);
-}
-
-static void vt6655_mac_en_protect_md(void __iomem *iobase)
-{
- vt6655_mac_set_bits(iobase, ENCFG_PROTECTMD);
-}
-
-static void vt6655_mac_dis_protect_md(void __iomem *iobase)
-{
- vt6655_mac_clear_bits(iobase, ENCFG_PROTECTMD);
-}
-
-static void vt6655_mac_en_barker_preamble_md(void __iomem *iobase)
-{
- vt6655_mac_set_bits(iobase, ENCFG_BARKERPREAM);
-}
-
-static void vt6655_mac_dis_barker_preamble_md(void __iomem *iobase)
-{
- vt6655_mac_clear_bits(iobase, ENCFG_BARKERPREAM);
-}
-
-/*
- * Initialisation of MAC & BBP registers
- */
-
-static void device_init_registers(struct vnt_private *priv)
-{
- unsigned long flags;
- unsigned int ii;
- unsigned char byValue;
- unsigned char byCCKPwrdBm = 0;
- unsigned char byOFDMPwrdBm = 0;
-
- MACbShutdown(priv);
- bb_software_reset(priv);
-
- /* Do MACbSoftwareReset in MACvInitialize */
- MACbSoftwareReset(priv);
-
- priv->bAES = false;
-
- /* Only used in 11g type, sync with ERP IE */
- priv->bProtectMode = false;
-
- priv->bNonERPPresent = false;
- priv->bBarkerPreambleMd = false;
- priv->wCurrentRate = RATE_1M;
- priv->byTopOFDMBasicRate = RATE_24M;
- priv->byTopCCKBasicRate = RATE_1M;
-
- /* init MAC */
- MACvInitialize(priv);
-
- /* Get Local ID */
- priv->local_id = ioread8(priv->port_offset + MAC_REG_LOCALID);
-
- spin_lock_irqsave(&priv->lock, flags);
-
- SROMvReadAllContents(priv->port_offset, priv->abyEEPROM);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- /* Get Channel range */
- priv->byMinChannel = 1;
- priv->byMaxChannel = CB_MAX_CHANNEL;
-
- /* Get Antena */
- byValue = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_ANTENNA);
- if (byValue & EEP_ANTINV)
- priv->bTxRxAntInv = true;
- else
- priv->bTxRxAntInv = false;
-
- byValue &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
- /* if not set default is All */
- if (byValue == 0)
- byValue = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
-
- if (byValue == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
- priv->byAntennaCount = 2;
- priv->byTxAntennaMode = ANT_B;
- priv->dwTxAntennaSel = 1;
- priv->dwRxAntennaSel = 1;
-
- if (priv->bTxRxAntInv)
- priv->byRxAntennaMode = ANT_A;
- else
- priv->byRxAntennaMode = ANT_B;
- } else {
- priv->byAntennaCount = 1;
- priv->dwTxAntennaSel = 0;
- priv->dwRxAntennaSel = 0;
-
- if (byValue & EEP_ANTENNA_AUX) {
- priv->byTxAntennaMode = ANT_A;
-
- if (priv->bTxRxAntInv)
- priv->byRxAntennaMode = ANT_B;
- else
- priv->byRxAntennaMode = ANT_A;
- } else {
- priv->byTxAntennaMode = ANT_B;
-
- if (priv->bTxRxAntInv)
- priv->byRxAntennaMode = ANT_A;
- else
- priv->byRxAntennaMode = ANT_B;
- }
- }
-
- /* Set initial antenna mode */
- bb_set_tx_antenna_mode(priv, priv->byTxAntennaMode);
- bb_set_rx_antenna_mode(priv, priv->byRxAntennaMode);
-
- /* zonetype initial */
- priv->byOriginalZonetype = priv->abyEEPROM[EEP_OFS_ZONETYPE];
-
- if (!priv->bZoneRegExist)
- priv->byZoneType = priv->abyEEPROM[EEP_OFS_ZONETYPE];
-
- pr_debug("priv->byZoneType = %x\n", priv->byZoneType);
-
- /* Init RF module */
- RFbInit(priv);
-
- /* Get Desire Power Value */
- priv->cur_pwr = 0xFF;
- priv->byCCKPwr = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_PWR_CCK);
- priv->byOFDMPwrG = SROMbyReadEmbedded(priv->port_offset,
- EEP_OFS_PWR_OFDMG);
-
- /* Load power Table */
- for (ii = 0; ii < CB_MAX_CHANNEL_24G; ii++) {
- priv->abyCCKPwrTbl[ii + 1] =
- SROMbyReadEmbedded(priv->port_offset,
- (unsigned char)(ii + EEP_OFS_CCK_PWR_TBL));
- if (priv->abyCCKPwrTbl[ii + 1] == 0)
- priv->abyCCKPwrTbl[ii + 1] = priv->byCCKPwr;
-
- priv->abyOFDMPwrTbl[ii + 1] =
- SROMbyReadEmbedded(priv->port_offset,
- (unsigned char)(ii + EEP_OFS_OFDM_PWR_TBL));
- if (priv->abyOFDMPwrTbl[ii + 1] == 0)
- priv->abyOFDMPwrTbl[ii + 1] = priv->byOFDMPwrG;
-
- priv->abyCCKDefaultPwr[ii + 1] = byCCKPwrdBm;
- priv->abyOFDMDefaultPwr[ii + 1] = byOFDMPwrdBm;
- }
-
- /* recover 12,13 ,14channel for EUROPE by 11 channel */
- for (ii = 11; ii < 14; ii++) {
- priv->abyCCKPwrTbl[ii] = priv->abyCCKPwrTbl[10];
- priv->abyOFDMPwrTbl[ii] = priv->abyOFDMPwrTbl[10];
- }
-
- /* Load OFDM A Power Table */
- for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) {
- priv->abyOFDMPwrTbl[ii + CB_MAX_CHANNEL_24G + 1] =
- SROMbyReadEmbedded(priv->port_offset,
- (unsigned char)(ii + EEP_OFS_OFDMA_PWR_TBL));
-
- priv->abyOFDMDefaultPwr[ii + CB_MAX_CHANNEL_24G + 1] =
- SROMbyReadEmbedded(priv->port_offset,
- (unsigned char)(ii + EEP_OFS_OFDMA_PWR_dBm));
- }
-
- if (priv->local_id > REV_ID_VT3253_B1) {
- VT6655_MAC_SELECT_PAGE1(priv->port_offset);
-
- iowrite8(MSRCTL1_TXPWR | MSRCTL1_CSAPAREN, priv->port_offset + MAC_REG_MSRCTL + 1);
-
- VT6655_MAC_SELECT_PAGE0(priv->port_offset);
- }
-
- /* use relative tx timeout and 802.11i D4 */
- vt6655_mac_word_reg_bits_on(priv->port_offset, MAC_REG_CFG,
- (CFG_TKIPOPT | CFG_NOTXTIMEOUT));
-
- /* set performance parameter by registry */
- vt6655_mac_set_short_retry_limit(priv, priv->byShortRetryLimit);
- MACvSetLongRetryLimit(priv, priv->byLongRetryLimit);
-
- /* reset TSF counter */
- iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL);
- /* enable TSF counter */
- iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL);
-
- /* initialize BBP registers */
- bb_vt3253_init(priv);
-
- if (priv->update_bbvga) {
- priv->bbvga_current = priv->bbvga[0];
- priv->bbvga_new = priv->bbvga_current;
- bb_set_vga_gain_offset(priv, priv->bbvga[0]);
- }
-
- bb_set_rx_antenna_mode(priv, priv->byRxAntennaMode);
- bb_set_tx_antenna_mode(priv, priv->byTxAntennaMode);
-
- /* Set BB and packet type at the same time. */
- /* Set Short Slot Time, xIFS, and RSPINF. */
- priv->wCurrentRate = RATE_54M;
-
- priv->radio_off = false;
-
- priv->byRadioCtl = SROMbyReadEmbedded(priv->port_offset,
- EEP_OFS_RADIOCTL);
- priv->hw_radio_off = false;
-
- if (priv->byRadioCtl & EEP_RADIOCTL_ENABLE) {
- /* Get GPIO */
- priv->byGPIO = ioread8(priv->port_offset + MAC_REG_GPIOCTL1);
-
- if (((priv->byGPIO & GPIO0_DATA) &&
- !(priv->byRadioCtl & EEP_RADIOCTL_INV)) ||
- (!(priv->byGPIO & GPIO0_DATA) &&
- (priv->byRadioCtl & EEP_RADIOCTL_INV)))
- priv->hw_radio_off = true;
- }
-
- if (priv->hw_radio_off || priv->bRadioControlOff)
- card_radio_power_off(priv);
-
- /* get Permanent network address */
- SROMvReadEtherAddress(priv->port_offset, priv->abyCurrentNetAddr);
- pr_debug("Network address = %pM\n", priv->abyCurrentNetAddr);
-
- /* reset Tx pointer */
- CARDvSafeResetRx(priv);
- /* reset Rx pointer */
- card_safe_reset_tx(priv);
-
- if (priv->local_id <= REV_ID_VT3253_A1)
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_RCR, RCR_WPAERR);
-
- /* Turn On Rx DMA */
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL0);
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL1);
-
- /* start the adapter */
- iowrite8(HOSTCR_MACEN | HOSTCR_RXON | HOSTCR_TXON, priv->port_offset + MAC_REG_HOSTCR);
-}
-
-static void device_print_info(struct vnt_private *priv)
-{
- dev_info(&priv->pcid->dev, "MAC=%pM IO=0x%lx Mem=0x%lx IRQ=%d\n",
- priv->abyCurrentNetAddr, (unsigned long)priv->ioaddr,
- (unsigned long)priv->port_offset, priv->pcid->irq);
-}
-
-static void device_free_info(struct vnt_private *priv)
-{
- if (!priv)
- return;
-
- if (priv->mac_hw)
- ieee80211_unregister_hw(priv->hw);
-
- if (priv->port_offset)
- iounmap(priv->port_offset);
-
- if (priv->pcid)
- pci_release_regions(priv->pcid);
-
- if (priv->hw)
- ieee80211_free_hw(priv->hw);
-}
-
-static bool device_init_rings(struct vnt_private *priv)
-{
- void *vir_pool;
-
- /*allocate all RD/TD rings a single pool*/
- vir_pool = dma_alloc_coherent(&priv->pcid->dev,
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
- priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
- priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
- priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
- &priv->pool_dma, GFP_ATOMIC);
- if (!vir_pool) {
- dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n");
- return false;
- }
-
- priv->aRD0Ring = vir_pool;
- priv->aRD1Ring = vir_pool +
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc);
-
- priv->rd0_pool_dma = priv->pool_dma;
- priv->rd1_pool_dma = priv->rd0_pool_dma +
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc);
-
- priv->tx0_bufs = dma_alloc_coherent(&priv->pcid->dev,
- priv->opts.tx_descs[0] * PKT_BUF_SZ +
- priv->opts.tx_descs[1] * PKT_BUF_SZ +
- CB_BEACON_BUF_SIZE +
- CB_MAX_BUF_SIZE,
- &priv->tx_bufs_dma0, GFP_ATOMIC);
- if (!priv->tx0_bufs) {
- dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n");
-
- dma_free_coherent(&priv->pcid->dev,
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
- priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
- priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
- priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
- vir_pool, priv->pool_dma);
- return false;
- }
-
- priv->td0_pool_dma = priv->rd1_pool_dma +
- priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc);
-
- priv->td1_pool_dma = priv->td0_pool_dma +
- priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc);
-
- /* vir_pool: pvoid type */
- priv->ap_td0_rings = vir_pool
- + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc)
- + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc);
-
- priv->ap_td1_rings = vir_pool
- + priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc)
- + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc)
- + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc);
-
- priv->tx1_bufs = priv->tx0_bufs +
- priv->opts.tx_descs[0] * PKT_BUF_SZ;
-
- priv->tx_beacon_bufs = priv->tx1_bufs +
- priv->opts.tx_descs[1] * PKT_BUF_SZ;
-
- priv->pbyTmpBuff = priv->tx_beacon_bufs +
- CB_BEACON_BUF_SIZE;
-
- priv->tx_bufs_dma1 = priv->tx_bufs_dma0 +
- priv->opts.tx_descs[0] * PKT_BUF_SZ;
-
- priv->tx_beacon_dma = priv->tx_bufs_dma1 +
- priv->opts.tx_descs[1] * PKT_BUF_SZ;
-
- return true;
-}
-
-static void device_free_rings(struct vnt_private *priv)
-{
- dma_free_coherent(&priv->pcid->dev,
- priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
- priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
- priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
- priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
- priv->aRD0Ring, priv->pool_dma);
-
- dma_free_coherent(&priv->pcid->dev,
- priv->opts.tx_descs[0] * PKT_BUF_SZ +
- priv->opts.tx_descs[1] * PKT_BUF_SZ +
- CB_BEACON_BUF_SIZE +
- CB_MAX_BUF_SIZE,
- priv->tx0_bufs, priv->tx_bufs_dma0);
-}
-
-static int device_init_rd0_ring(struct vnt_private *priv)
-{
- int i;
- dma_addr_t curr = priv->rd0_pool_dma;
- struct vnt_rx_desc *desc;
- int ret;
-
- /* Init the RD0 ring entries */
- for (i = 0; i < priv->opts.rx_descs0;
- i ++, curr += sizeof(struct vnt_rx_desc)) {
- desc = &priv->aRD0Ring[i];
- desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL);
- if (!desc->rd_info) {
- ret = -ENOMEM;
- goto err_free_desc;
- }
-
- if (!device_alloc_rx_buf(priv, desc)) {
- dev_err(&priv->pcid->dev, "can not alloc rx bufs\n");
- ret = -ENOMEM;
- goto err_free_rd;
- }
-
- desc->next = &priv->aRD0Ring[(i + 1) % priv->opts.rx_descs0];
- desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc));
- }
-
- if (i > 0)
- priv->aRD0Ring[i - 1].next_desc = cpu_to_le32(priv->rd0_pool_dma);
- priv->pCurrRD[0] = &priv->aRD0Ring[0];
-
- return 0;
-
-err_free_rd:
- kfree(desc->rd_info);
-
-err_free_desc:
- while (i--) {
- desc = &priv->aRD0Ring[i];
- device_free_rx_buf(priv, desc);
- kfree(desc->rd_info);
- }
-
- return ret;
-}
-
-static int device_init_rd1_ring(struct vnt_private *priv)
-{
- int i;
- dma_addr_t curr = priv->rd1_pool_dma;
- struct vnt_rx_desc *desc;
- int ret;
-
- /* Init the RD1 ring entries */
- for (i = 0; i < priv->opts.rx_descs1;
- i ++, curr += sizeof(struct vnt_rx_desc)) {
- desc = &priv->aRD1Ring[i];
- desc->rd_info = kzalloc(sizeof(*desc->rd_info), GFP_KERNEL);
- if (!desc->rd_info) {
- ret = -ENOMEM;
- goto err_free_desc;
- }
-
- if (!device_alloc_rx_buf(priv, desc)) {
- dev_err(&priv->pcid->dev, "can not alloc rx bufs\n");
- ret = -ENOMEM;
- goto err_free_rd;
- }
-
- desc->next = &priv->aRD1Ring[(i + 1) % priv->opts.rx_descs1];
- desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_rx_desc));
- }
-
- if (i > 0)
- priv->aRD1Ring[i - 1].next_desc = cpu_to_le32(priv->rd1_pool_dma);
- priv->pCurrRD[1] = &priv->aRD1Ring[0];
-
- return 0;
-
-err_free_rd:
- kfree(desc->rd_info);
-
-err_free_desc:
- while (i--) {
- desc = &priv->aRD1Ring[i];
- device_free_rx_buf(priv, desc);
- kfree(desc->rd_info);
- }
-
- return ret;
-}
-
-static void device_free_rd0_ring(struct vnt_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->opts.rx_descs0; i++) {
- struct vnt_rx_desc *desc = &priv->aRD0Ring[i];
-
- device_free_rx_buf(priv, desc);
- kfree(desc->rd_info);
- }
-}
-
-static void device_free_rd1_ring(struct vnt_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->opts.rx_descs1; i++) {
- struct vnt_rx_desc *desc = &priv->aRD1Ring[i];
-
- device_free_rx_buf(priv, desc);
- kfree(desc->rd_info);
- }
-}
-
-static int device_init_td0_ring(struct vnt_private *priv)
-{
- int i;
- dma_addr_t curr;
- struct vnt_tx_desc *desc;
- int ret;
-
- curr = priv->td0_pool_dma;
- for (i = 0; i < priv->opts.tx_descs[0];
- i++, curr += sizeof(struct vnt_tx_desc)) {
- desc = &priv->ap_td0_rings[i];
- desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL);
- if (!desc->td_info) {
- ret = -ENOMEM;
- goto err_free_desc;
- }
-
- desc->td_info->buf = priv->tx0_bufs + i * PKT_BUF_SZ;
- desc->td_info->buf_dma = priv->tx_bufs_dma0 + i * PKT_BUF_SZ;
-
- desc->next = &(priv->ap_td0_rings[(i + 1) % priv->opts.tx_descs[0]]);
- desc->next_desc = cpu_to_le32(curr +
- sizeof(struct vnt_tx_desc));
- }
-
- if (i > 0)
- priv->ap_td0_rings[i - 1].next_desc = cpu_to_le32(priv->td0_pool_dma);
- priv->tail_td[0] = priv->apCurrTD[0] = &priv->ap_td0_rings[0];
-
- return 0;
-
-err_free_desc:
- while (i--) {
- desc = &priv->ap_td0_rings[i];
- kfree(desc->td_info);
- }
-
- return ret;
-}
-
-static int device_init_td1_ring(struct vnt_private *priv)
-{
- int i;
- dma_addr_t curr;
- struct vnt_tx_desc *desc;
- int ret;
-
- /* Init the TD ring entries */
- curr = priv->td1_pool_dma;
- for (i = 0; i < priv->opts.tx_descs[1];
- i++, curr += sizeof(struct vnt_tx_desc)) {
- desc = &priv->ap_td1_rings[i];
- desc->td_info = kzalloc(sizeof(*desc->td_info), GFP_KERNEL);
- if (!desc->td_info) {
- ret = -ENOMEM;
- goto err_free_desc;
- }
-
- desc->td_info->buf = priv->tx1_bufs + i * PKT_BUF_SZ;
- desc->td_info->buf_dma = priv->tx_bufs_dma1 + i * PKT_BUF_SZ;
-
- desc->next = &(priv->ap_td1_rings[(i + 1) % priv->opts.tx_descs[1]]);
- desc->next_desc = cpu_to_le32(curr + sizeof(struct vnt_tx_desc));
- }
-
- if (i > 0)
- priv->ap_td1_rings[i - 1].next_desc = cpu_to_le32(priv->td1_pool_dma);
- priv->tail_td[1] = priv->apCurrTD[1] = &priv->ap_td1_rings[0];
-
- return 0;
-
-err_free_desc:
- while (i--) {
- desc = &priv->ap_td1_rings[i];
- kfree(desc->td_info);
- }
-
- return ret;
-}
-
-static void device_free_td0_ring(struct vnt_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->opts.tx_descs[0]; i++) {
- struct vnt_tx_desc *desc = &priv->ap_td0_rings[i];
- struct vnt_td_info *td_info = desc->td_info;
-
- dev_kfree_skb(td_info->skb);
- kfree(desc->td_info);
- }
-}
-
-static void device_free_td1_ring(struct vnt_private *priv)
-{
- int i;
-
- for (i = 0; i < priv->opts.tx_descs[1]; i++) {
- struct vnt_tx_desc *desc = &priv->ap_td1_rings[i];
- struct vnt_td_info *td_info = desc->td_info;
-
- dev_kfree_skb(td_info->skb);
- kfree(desc->td_info);
- }
-}
-
-/*-----------------------------------------------------------------*/
-
-static int device_rx_srv(struct vnt_private *priv, unsigned int idx)
-{
- struct vnt_rx_desc *rd;
- int works = 0;
-
- for (rd = priv->pCurrRD[idx];
- rd->rd0.owner == OWNED_BY_HOST;
- rd = rd->next) {
- if (works++ > 15)
- break;
-
- if (!rd->rd_info->skb)
- break;
-
- if (vnt_receive_frame(priv, rd)) {
- if (!device_alloc_rx_buf(priv, rd)) {
- dev_err(&priv->pcid->dev,
- "can not allocate rx buf\n");
- break;
- }
- }
- rd->rd0.owner = OWNED_BY_NIC;
- }
-
- priv->pCurrRD[idx] = rd;
-
- return works;
-}
-
-static bool device_alloc_rx_buf(struct vnt_private *priv,
- struct vnt_rx_desc *rd)
-{
- struct vnt_rd_info *rd_info = rd->rd_info;
-
- rd_info->skb = dev_alloc_skb((int)priv->rx_buf_sz);
- if (!rd_info->skb)
- return false;
-
- rd_info->skb_dma =
- dma_map_single(&priv->pcid->dev,
- skb_put(rd_info->skb, skb_tailroom(rd_info->skb)),
- priv->rx_buf_sz, DMA_FROM_DEVICE);
- if (dma_mapping_error(&priv->pcid->dev, rd_info->skb_dma)) {
- dev_kfree_skb(rd_info->skb);
- rd_info->skb = NULL;
- return false;
- }
-
- *((unsigned int *)&rd->rd0) = 0; /* FIX cast */
-
- rd->rd0.res_count = cpu_to_le16(priv->rx_buf_sz);
- rd->rd0.owner = OWNED_BY_NIC;
- rd->rd1.req_count = cpu_to_le16(priv->rx_buf_sz);
- rd->buff_addr = cpu_to_le32(rd_info->skb_dma);
-
- return true;
-}
-
-static void device_free_rx_buf(struct vnt_private *priv,
- struct vnt_rx_desc *rd)
-{
- struct vnt_rd_info *rd_info = rd->rd_info;
-
- dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma,
- priv->rx_buf_sz, DMA_FROM_DEVICE);
- dev_kfree_skb(rd_info->skb);
-}
-
-static const u8 fallback_rate0[5][5] = {
- {RATE_18M, RATE_18M, RATE_12M, RATE_12M, RATE_12M},
- {RATE_24M, RATE_24M, RATE_18M, RATE_12M, RATE_12M},
- {RATE_36M, RATE_36M, RATE_24M, RATE_18M, RATE_18M},
- {RATE_48M, RATE_48M, RATE_36M, RATE_24M, RATE_24M},
- {RATE_54M, RATE_54M, RATE_48M, RATE_36M, RATE_36M}
-};
-
-static const u8 fallback_rate1[5][5] = {
- {RATE_18M, RATE_18M, RATE_12M, RATE_6M, RATE_6M},
- {RATE_24M, RATE_24M, RATE_18M, RATE_6M, RATE_6M},
- {RATE_36M, RATE_36M, RATE_24M, RATE_12M, RATE_12M},
- {RATE_48M, RATE_48M, RATE_24M, RATE_12M, RATE_12M},
- {RATE_54M, RATE_54M, RATE_36M, RATE_18M, RATE_18M}
-};
-
-static int vnt_int_report_rate(struct vnt_private *priv,
- struct vnt_td_info *context, u8 tsr0, u8 tsr1)
-{
- struct vnt_tx_fifo_head *fifo_head;
- struct ieee80211_tx_info *info;
- struct ieee80211_rate *rate;
- u16 fb_option;
- u8 tx_retry = (tsr0 & TSR0_NCR);
- s8 idx;
-
- if (!context)
- return -ENOMEM;
-
- if (!context->skb)
- return -EINVAL;
-
- fifo_head = (struct vnt_tx_fifo_head *)context->buf;
- fb_option = (le16_to_cpu(fifo_head->fifo_ctl) &
- (FIFOCTL_AUTO_FB_0 | FIFOCTL_AUTO_FB_1));
-
- info = IEEE80211_SKB_CB(context->skb);
- idx = info->control.rates[0].idx;
-
- if (fb_option && !(tsr1 & TSR1_TERR)) {
- u8 tx_rate;
- u8 retry = tx_retry;
-
- rate = ieee80211_get_tx_rate(priv->hw, info);
- tx_rate = rate->hw_value - RATE_18M;
-
- if (retry > 4)
- retry = 4;
-
- if (fb_option & FIFOCTL_AUTO_FB_0)
- tx_rate = fallback_rate0[tx_rate][retry];
- else if (fb_option & FIFOCTL_AUTO_FB_1)
- tx_rate = fallback_rate1[tx_rate][retry];
-
- if (info->band == NL80211_BAND_5GHZ)
- idx = tx_rate - RATE_6M;
- else
- idx = tx_rate;
- }
-
- ieee80211_tx_info_clear_status(info);
-
- info->status.rates[0].count = tx_retry;
-
- if (!(tsr1 & TSR1_TERR)) {
- info->status.rates[0].idx = idx;
-
- if (info->flags & IEEE80211_TX_CTL_NO_ACK)
- info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
- else
- info->flags |= IEEE80211_TX_STAT_ACK;
- }
-
- return 0;
-}
-
-static int device_tx_srv(struct vnt_private *priv, unsigned int idx)
-{
- struct vnt_tx_desc *desc;
- int works = 0;
- unsigned char byTsr0;
- unsigned char byTsr1;
-
- for (desc = priv->tail_td[idx]; priv->iTDUsed[idx] > 0; desc = desc->next) {
- if (desc->td0.owner == OWNED_BY_NIC)
- break;
- if (works++ > 15)
- break;
-
- byTsr0 = desc->td0.tsr0;
- byTsr1 = desc->td0.tsr1;
-
- /* Only the status of first TD in the chain is correct */
- if (desc->td1.tcr & TCR_STP) {
- if ((desc->td_info->flags & TD_FLAGS_NETIF_SKB) != 0) {
- if (!(byTsr1 & TSR1_TERR)) {
- if (byTsr0 != 0) {
- pr_debug(" Tx[%d] OK but has error. tsr1[%02X] tsr0[%02X]\n",
- (int)idx, byTsr1,
- byTsr0);
- }
- } else {
- pr_debug(" Tx[%d] dropped & tsr1[%02X] tsr0[%02X]\n",
- (int)idx, byTsr1, byTsr0);
- }
- }
-
- if (byTsr1 & TSR1_TERR) {
- if ((desc->td_info->flags & TD_FLAGS_PRIV_SKB) != 0) {
- pr_debug(" Tx[%d] fail has error. tsr1[%02X] tsr0[%02X]\n",
- (int)idx, byTsr1, byTsr0);
- }
- }
-
- vnt_int_report_rate(priv, desc->td_info, byTsr0, byTsr1);
-
- device_free_tx_buf(priv, desc);
- priv->iTDUsed[idx]--;
- }
- }
-
- priv->tail_td[idx] = desc;
-
- return works;
-}
-
-static void device_error(struct vnt_private *priv, unsigned short status)
-{
- if (status & ISR_FETALERR) {
- dev_err(&priv->pcid->dev, "Hardware fatal error\n");
-
- MACbShutdown(priv);
- return;
- }
-}
-
-static void device_free_tx_buf(struct vnt_private *priv,
- struct vnt_tx_desc *desc)
-{
- struct vnt_td_info *td_info = desc->td_info;
- struct sk_buff *skb = td_info->skb;
-
- if (skb)
- ieee80211_tx_status_irqsafe(priv->hw, skb);
-
- td_info->skb = NULL;
- td_info->flags = 0;
-}
-
-static void vnt_check_bb_vga(struct vnt_private *priv)
-{
- long dbm;
- int i;
-
- if (!priv->update_bbvga)
- return;
-
- if (priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
- return;
-
- if (!(priv->vif->cfg.assoc && priv->current_rssi))
- return;
-
- RFvRSSITodBm(priv, (u8)priv->current_rssi, &dbm);
-
- for (i = 0; i < BB_VGA_LEVEL; i++) {
- if (dbm < priv->dbm_threshold[i]) {
- priv->bbvga_new = priv->bbvga[i];
- break;
- }
- }
-
- if (priv->bbvga_new == priv->bbvga_current) {
- priv->uBBVGADiffCount = 1;
- return;
- }
-
- priv->uBBVGADiffCount++;
-
- if (priv->uBBVGADiffCount == 1) {
- /* first VGA diff gain */
- bb_set_vga_gain_offset(priv, priv->bbvga_new);
-
- dev_dbg(&priv->pcid->dev,
- "First RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
- (int)dbm, priv->bbvga_new,
- priv->bbvga_current,
- (int)priv->uBBVGADiffCount);
- }
-
- if (priv->uBBVGADiffCount >= BB_VGA_CHANGE_THRESHOLD) {
- dev_dbg(&priv->pcid->dev,
- "RSSI[%d] NewGain[%d] OldGain[%d] Count[%d]\n",
- (int)dbm, priv->bbvga_new,
- priv->bbvga_current,
- (int)priv->uBBVGADiffCount);
-
- bb_set_vga_gain_offset(priv, priv->bbvga_new);
- }
-}
-
-static void vnt_interrupt_process(struct vnt_private *priv)
-{
- struct ieee80211_low_level_stats *low_stats = &priv->low_stats;
- int max_count = 0;
- u32 mib_counter;
- u32 isr;
- unsigned long flags;
-
- isr = ioread32(priv->port_offset + MAC_REG_ISR);
-
- if (isr == 0)
- return;
-
- if (isr == 0xffffffff) {
- pr_debug("isr = 0xffff\n");
- return;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-
- /* Read low level stats */
- mib_counter = ioread32(priv->port_offset + MAC_REG_MIBCNTR);
-
- low_stats->dot11RTSSuccessCount += mib_counter & 0xff;
- low_stats->dot11RTSFailureCount += (mib_counter >> 8) & 0xff;
- low_stats->dot11ACKFailureCount += (mib_counter >> 16) & 0xff;
- low_stats->dot11FCSErrorCount += (mib_counter >> 24) & 0xff;
-
- /*
- * TBD....
- * Must do this after doing rx/tx, cause ISR bit is slow
- * than RD/TD write back
- * update ISR counter
- */
- while (isr && priv->vif) {
- iowrite32(isr, priv->port_offset + MAC_REG_ISR);
-
- if (isr & ISR_FETALERR) {
- pr_debug(" ISR_FETALERR\n");
- iowrite8(0, priv->port_offset + MAC_REG_SOFTPWRCTL);
- iowrite16(SOFTPWRCTL_SWPECTI, priv->port_offset + MAC_REG_SOFTPWRCTL);
- device_error(priv, isr);
- }
-
- if (isr & ISR_TBTT) {
- if (priv->op_mode != NL80211_IFTYPE_ADHOC)
- vnt_check_bb_vga(priv);
-
- priv->bBeaconSent = false;
- if (priv->bEnablePSMode)
- PSbIsNextTBTTWakeUp((void *)priv);
-
- if ((priv->op_mode == NL80211_IFTYPE_AP ||
- priv->op_mode == NL80211_IFTYPE_ADHOC) &&
- priv->vif->bss_conf.enable_beacon)
- MACvOneShotTimer1MicroSec(priv,
- (priv->vif->bss_conf.beacon_int -
- MAKE_BEACON_RESERVED) << 10);
-
- /* TODO: adhoc PS mode */
- }
-
- if (isr & ISR_BNTX) {
- if (priv->op_mode == NL80211_IFTYPE_ADHOC) {
- priv->bIsBeaconBufReadySet = false;
- priv->cbBeaconBufReadySetCnt = 0;
- }
-
- priv->bBeaconSent = true;
- }
-
- if (isr & ISR_RXDMA0)
- max_count += device_rx_srv(priv, TYPE_RXDMA0);
-
- if (isr & ISR_RXDMA1)
- max_count += device_rx_srv(priv, TYPE_RXDMA1);
-
- if (isr & ISR_TXDMA0)
- max_count += device_tx_srv(priv, TYPE_TXDMA0);
-
- if (isr & ISR_AC0DMA)
- max_count += device_tx_srv(priv, TYPE_AC0DMA);
-
- if (isr & ISR_SOFTTIMER1) {
- if (priv->vif->bss_conf.enable_beacon)
- vnt_beacon_make(priv, priv->vif);
- }
-
- /* If both buffers available wake the queue */
- if (AVAIL_TD(priv, TYPE_TXDMA0) &&
- AVAIL_TD(priv, TYPE_AC0DMA) &&
- ieee80211_queue_stopped(priv->hw, 0))
- ieee80211_wake_queues(priv->hw);
-
- isr = ioread32(priv->port_offset + MAC_REG_ISR);
-
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL0);
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_RXDMACTL1);
-
- if (max_count > priv->opts.int_works)
- break;
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-static void vnt_interrupt_work(struct work_struct *work)
-{
- struct vnt_private *priv =
- container_of(work, struct vnt_private, interrupt_work);
-
- if (priv->vif)
- vnt_interrupt_process(priv);
-
- iowrite32(IMR_MASK_VALUE, priv->port_offset + MAC_REG_IMR);
-}
-
-static irqreturn_t vnt_interrupt(int irq, void *arg)
-{
- struct vnt_private *priv = arg;
-
- schedule_work(&priv->interrupt_work);
-
- iowrite32(0, priv->port_offset + MAC_REG_IMR);
-
- return IRQ_HANDLED;
-}
-
-static int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
-{
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct vnt_tx_desc *head_td;
- u32 dma_idx;
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- if (ieee80211_is_data(hdr->frame_control))
- dma_idx = TYPE_AC0DMA;
- else
- dma_idx = TYPE_TXDMA0;
-
- if (AVAIL_TD(priv, dma_idx) < 1) {
- spin_unlock_irqrestore(&priv->lock, flags);
- ieee80211_stop_queues(priv->hw);
- return -ENOMEM;
- }
-
- head_td = priv->apCurrTD[dma_idx];
-
- head_td->td1.tcr = 0;
-
- head_td->td_info->skb = skb;
-
- if (dma_idx == TYPE_AC0DMA)
- head_td->td_info->flags = TD_FLAGS_NETIF_SKB;
-
- priv->apCurrTD[dma_idx] = head_td->next;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- vnt_generate_fifo_header(priv, dma_idx, head_td, skb);
-
- spin_lock_irqsave(&priv->lock, flags);
-
- priv->bPWBitOn = false;
-
- /* Set TSR1 & ReqCount in TxDescHead */
- head_td->td1.tcr |= (TCR_STP | TCR_EDP | EDMSDU);
- head_td->td1.req_count = cpu_to_le16(head_td->td_info->req_count);
-
- head_td->buff_addr = cpu_to_le32(head_td->td_info->buf_dma);
-
- /* Poll Transmit the adapter */
- wmb();
- head_td->td0.owner = OWNED_BY_NIC;
- wmb(); /* second memory barrier */
-
- if (head_td->td_info->flags & TD_FLAGS_NETIF_SKB)
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_AC0DMACTL);
- else
- vt6655_mac_dma_ctl(priv->port_offset, MAC_REG_TXDMACTL0);
-
- priv->iTDUsed[dma_idx]++;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-static void vnt_tx_80211(struct ieee80211_hw *hw,
- struct ieee80211_tx_control *control,
- struct sk_buff *skb)
-{
- struct vnt_private *priv = hw->priv;
-
- if (vnt_tx_packet(priv, skb))
- ieee80211_free_txskb(hw, skb);
-}
-
-static int vnt_start(struct ieee80211_hw *hw)
-{
- struct vnt_private *priv = hw->priv;
- int ret;
-
- priv->rx_buf_sz = PKT_BUF_SZ;
- if (!device_init_rings(priv))
- return -ENOMEM;
-
- ret = request_irq(priv->pcid->irq, vnt_interrupt,
- IRQF_SHARED, "vt6655", priv);
- if (ret) {
- dev_dbg(&priv->pcid->dev, "failed to start irq\n");
- goto err_free_rings;
- }
-
- dev_dbg(&priv->pcid->dev, "call device init rd0 ring\n");
- ret = device_init_rd0_ring(priv);
- if (ret)
- goto err_free_irq;
- ret = device_init_rd1_ring(priv);
- if (ret)
- goto err_free_rd0_ring;
- ret = device_init_td0_ring(priv);
- if (ret)
- goto err_free_rd1_ring;
- ret = device_init_td1_ring(priv);
- if (ret)
- goto err_free_td0_ring;
-
- device_init_registers(priv);
-
- dev_dbg(&priv->pcid->dev, "enable MAC interrupt\n");
- iowrite32(IMR_MASK_VALUE, priv->port_offset + MAC_REG_IMR);
-
- ieee80211_wake_queues(hw);
-
- return 0;
-
-err_free_td0_ring:
- device_free_td0_ring(priv);
-err_free_rd1_ring:
- device_free_rd1_ring(priv);
-err_free_rd0_ring:
- device_free_rd0_ring(priv);
-err_free_irq:
- free_irq(priv->pcid->irq, priv);
-err_free_rings:
- device_free_rings(priv);
- return ret;
-}
-
-static void vnt_stop(struct ieee80211_hw *hw, bool suspend)
-{
- struct vnt_private *priv = hw->priv;
-
- ieee80211_stop_queues(hw);
-
- cancel_work_sync(&priv->interrupt_work);
-
- MACbShutdown(priv);
- MACbSoftwareReset(priv);
- card_radio_power_off(priv);
-
- device_free_td0_ring(priv);
- device_free_td1_ring(priv);
- device_free_rd0_ring(priv);
- device_free_rd1_ring(priv);
- device_free_rings(priv);
-
- free_irq(priv->pcid->irq, priv);
-}
-
-static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- priv->vif = vif;
-
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- break;
- case NL80211_IFTYPE_ADHOC:
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_RCR, RCR_UNICAST);
-
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
-
- break;
- case NL80211_IFTYPE_AP:
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_RCR, RCR_UNICAST);
-
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_AP);
-
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- priv->op_mode = vif->type;
-
- return 0;
-}
-
-static void vnt_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- break;
- case NL80211_IFTYPE_ADHOC:
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX);
- vt6655_mac_reg_bits_off(priv->port_offset,
- MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_ADHOC);
- break;
- case NL80211_IFTYPE_AP:
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX);
- vt6655_mac_reg_bits_off(priv->port_offset,
- MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_HOSTCR, HOSTCR_AP);
- break;
- default:
- break;
- }
-
- priv->op_mode = NL80211_IFTYPE_UNSPECIFIED;
-}
-
-static int vnt_config(struct ieee80211_hw *hw, u32 changed)
-{
- struct vnt_private *priv = hw->priv;
- struct ieee80211_conf *conf = &hw->conf;
- u8 bb_type;
-
- if (changed & IEEE80211_CONF_CHANGE_PS) {
- if (conf->flags & IEEE80211_CONF_PS)
- PSvEnablePowerSaving(priv, conf->listen_interval);
- else
- PSvDisablePowerSaving(priv);
- }
-
- if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) ||
- (conf->flags & IEEE80211_CONF_OFFCHANNEL)) {
- set_channel(priv, conf->chandef.chan);
-
- if (conf->chandef.chan->band == NL80211_BAND_5GHZ)
- bb_type = BB_TYPE_11A;
- else
- bb_type = BB_TYPE_11G;
-
- if (priv->byBBType != bb_type) {
- priv->byBBType = bb_type;
-
- card_set_phy_parameter(priv, priv->byBBType);
- }
- }
-
- if (changed & IEEE80211_CONF_CHANGE_POWER) {
- if (priv->byBBType == BB_TYPE_11B)
- priv->wCurrentRate = RATE_1M;
- else
- priv->wCurrentRate = RATE_54M;
-
- RFbSetPower(priv, priv->wCurrentRate,
- conf->chandef.chan->hw_value);
- }
-
- return 0;
-}
-
-static void vnt_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf, u64 changed)
-{
- struct vnt_private *priv = hw->priv;
-
- priv->current_aid = vif->cfg.aid;
-
- if (changed & BSS_CHANGED_BSSID && conf->bssid) {
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- vt6655_mac_write_bssid_addr(priv->port_offset, conf->bssid);
-
- spin_unlock_irqrestore(&priv->lock, flags);
- }
-
- if (changed & BSS_CHANGED_BASIC_RATES) {
- priv->basic_rates = conf->basic_rates;
-
- CARDvUpdateBasicTopRate(priv);
-
- dev_dbg(&priv->pcid->dev,
- "basic rates %x\n", conf->basic_rates);
- }
-
- if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- if (conf->use_short_preamble) {
- vt6655_mac_en_barker_preamble_md(priv->port_offset);
- priv->preamble_type = true;
- } else {
- vt6655_mac_dis_barker_preamble_md(priv->port_offset);
- priv->preamble_type = false;
- }
- }
-
- if (changed & BSS_CHANGED_ERP_CTS_PROT) {
- if (conf->use_cts_prot)
- vt6655_mac_en_protect_md(priv->port_offset);
- else
- vt6655_mac_dis_protect_md(priv->port_offset);
- }
-
- if (changed & BSS_CHANGED_ERP_SLOT) {
- if (conf->use_short_slot)
- priv->short_slot_time = true;
- else
- priv->short_slot_time = false;
-
- card_set_phy_parameter(priv, priv->byBBType);
- bb_set_vga_gain_offset(priv, priv->bbvga[0]);
- }
-
- if (changed & BSS_CHANGED_TXPOWER)
- RFbSetPower(priv, priv->wCurrentRate,
- conf->chanreq.oper.chan->hw_value);
-
- if (changed & BSS_CHANGED_BEACON_ENABLED) {
- dev_dbg(&priv->pcid->dev,
- "Beacon enable %d\n", conf->enable_beacon);
-
- if (conf->enable_beacon) {
- vnt_beacon_enable(priv, vif, conf);
-
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX);
- } else {
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TCR,
- TCR_AUTOBCNTX);
- }
- }
-
- if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) &&
- priv->op_mode != NL80211_IFTYPE_AP) {
- if (vif->cfg.assoc && conf->beacon_rate) {
- card_update_tsf(priv, conf->beacon_rate->hw_value,
- conf->sync_tsf);
-
- card_set_beacon_period(priv, conf->beacon_int);
-
- CARDvSetFirstNextTBTT(priv, conf->beacon_int);
- } else {
- iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL);
- iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL);
- }
- }
-}
-
-static u64 vnt_prepare_multicast(struct ieee80211_hw *hw,
- struct netdev_hw_addr_list *mc_list)
-{
- struct vnt_private *priv = hw->priv;
- struct netdev_hw_addr *ha;
- u64 mc_filter = 0;
- u32 bit_nr = 0;
-
- netdev_hw_addr_list_for_each(ha, mc_list) {
- bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
-
- mc_filter |= 1ULL << (bit_nr & 0x3f);
- }
-
- priv->mc_list_count = mc_list->count;
-
- return mc_filter;
-}
-
-static void vnt_configure(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags, u64 multicast)
-{
- struct vnt_private *priv = hw->priv;
- u8 rx_mode = 0;
-
- *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC;
-
- rx_mode = ioread8(priv->port_offset + MAC_REG_RCR);
-
- dev_dbg(&priv->pcid->dev, "rx mode in = %x\n", rx_mode);
-
- if (changed_flags & FIF_ALLMULTI) {
- if (*total_flags & FIF_ALLMULTI) {
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- if (priv->mc_list_count > 2) {
- VT6655_MAC_SELECT_PAGE1(priv->port_offset);
-
- iowrite32(0xffffffff, priv->port_offset + MAC_REG_MAR0);
- iowrite32(0xffffffff, priv->port_offset + MAC_REG_MAR0 + 4);
-
- VT6655_MAC_SELECT_PAGE0(priv->port_offset);
- } else {
- VT6655_MAC_SELECT_PAGE1(priv->port_offset);
-
- multicast = le64_to_cpu(multicast);
- iowrite32((u32)multicast, priv->port_offset + MAC_REG_MAR0);
- iowrite32((u32)(multicast >> 32),
- priv->port_offset + MAC_REG_MAR0 + 4);
-
- VT6655_MAC_SELECT_PAGE0(priv->port_offset);
- }
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- rx_mode |= RCR_MULTICAST | RCR_BROADCAST;
- } else {
- rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST);
- }
- }
-
- if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) {
- rx_mode |= RCR_MULTICAST | RCR_BROADCAST;
-
- if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC))
- rx_mode &= ~RCR_BSSID;
- else
- rx_mode |= RCR_BSSID;
- }
-
- iowrite8(rx_mode, priv->port_offset + MAC_REG_RCR);
-
- dev_dbg(&priv->pcid->dev, "rx mode out= %x\n", rx_mode);
-}
-
-static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
-{
- struct vnt_private *priv = hw->priv;
-
- switch (cmd) {
- case SET_KEY:
- if (vnt_set_keys(hw, sta, vif, key))
- return -EOPNOTSUPP;
- break;
- case DISABLE_KEY:
- if (test_bit(key->hw_key_idx, &priv->key_entry_inuse))
- clear_bit(key->hw_key_idx, &priv->key_entry_inuse);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
-static int vnt_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
-{
- struct vnt_private *priv = hw->priv;
-
- memcpy(stats, &priv->low_stats, sizeof(*stats));
-
- return 0;
-}
-
-static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
- u64 tsf;
-
- tsf = vt6655_get_current_tsf(priv);
-
- return tsf;
-}
-
-static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u64 tsf)
-{
- struct vnt_private *priv = hw->priv;
-
- CARDvUpdateNextTBTT(priv, tsf, vif->bss_conf.beacon_int);
-}
-
-static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- /* reset TSF counter */
- iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL);
-}
-
-static const struct ieee80211_ops vnt_mac_ops = {
- .add_chanctx = ieee80211_emulate_add_chanctx,
- .remove_chanctx = ieee80211_emulate_remove_chanctx,
- .change_chanctx = ieee80211_emulate_change_chanctx,
- .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
- .tx = vnt_tx_80211,
- .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = vnt_start,
- .stop = vnt_stop,
- .add_interface = vnt_add_interface,
- .remove_interface = vnt_remove_interface,
- .config = vnt_config,
- .bss_info_changed = vnt_bss_info_changed,
- .prepare_multicast = vnt_prepare_multicast,
- .configure_filter = vnt_configure,
- .set_key = vnt_set_key,
- .get_stats = vnt_get_stats,
- .get_tsf = vnt_get_tsf,
- .set_tsf = vnt_set_tsf,
- .reset_tsf = vnt_reset_tsf,
-};
-
-static int vnt_init(struct vnt_private *priv)
-{
- SET_IEEE80211_PERM_ADDR(priv->hw, priv->abyCurrentNetAddr);
-
- vnt_init_bands(priv);
-
- if (ieee80211_register_hw(priv->hw))
- return -ENODEV;
-
- priv->mac_hw = true;
-
- card_radio_power_off(priv);
-
- return 0;
-}
-
-static int
-vt6655_probe(struct pci_dev *pcid, const struct pci_device_id *ent)
-{
- struct vnt_private *priv;
- struct ieee80211_hw *hw;
- struct wiphy *wiphy;
- int rc;
-
- dev_notice(&pcid->dev,
- "%s Ver. %s\n", DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
-
- dev_notice(&pcid->dev,
- "Copyright (c) 2003 VIA Networking Technologies, Inc.\n");
-
- hw = ieee80211_alloc_hw(sizeof(*priv), &vnt_mac_ops);
- if (!hw) {
- dev_err(&pcid->dev, "could not register ieee80211_hw\n");
- return -ENOMEM;
- }
-
- priv = hw->priv;
- priv->pcid = pcid;
-
- spin_lock_init(&priv->lock);
-
- priv->hw = hw;
-
- SET_IEEE80211_DEV(priv->hw, &pcid->dev);
-
- if (pci_enable_device(pcid)) {
- device_free_info(priv);
- return -ENODEV;
- }
-
- dev_dbg(&pcid->dev,
- "Before get pci_info memaddr is %x\n", priv->memaddr);
-
- pci_set_master(pcid);
-
- priv->memaddr = pci_resource_start(pcid, 0);
- priv->ioaddr = pci_resource_start(pcid, 1);
- priv->port_offset = ioremap(priv->memaddr & PCI_BASE_ADDRESS_MEM_MASK,
- 256);
- if (!priv->port_offset) {
- dev_err(&pcid->dev, ": Failed to IO remapping ..\n");
- device_free_info(priv);
- return -ENODEV;
- }
-
- rc = pci_request_regions(pcid, DEVICE_NAME);
- if (rc) {
- dev_err(&pcid->dev, ": Failed to find PCI device\n");
- device_free_info(priv);
- return -ENODEV;
- }
-
- if (dma_set_mask(&pcid->dev, DMA_BIT_MASK(32))) {
- dev_err(&pcid->dev, ": Failed to set dma 32 bit mask\n");
- device_free_info(priv);
- return -ENODEV;
- }
-
- INIT_WORK(&priv->interrupt_work, vnt_interrupt_work);
-
- /* do reset */
- if (!MACbSoftwareReset(priv)) {
- dev_err(&pcid->dev, ": Failed to access MAC hardware..\n");
- device_free_info(priv);
- return -ENODEV;
- }
- /* initial to reload eeprom */
- MACvInitialize(priv);
- vt6655_mac_read_ether_addr(priv->port_offset, priv->abyCurrentNetAddr);
-
- /* Get RFType */
- priv->rf_type = SROMbyReadEmbedded(priv->port_offset, EEP_OFS_RFTYPE);
- priv->rf_type &= RF_MASK;
-
- dev_dbg(&pcid->dev, "RF Type = %x\n", priv->rf_type);
-
- device_get_options(priv);
- device_set_options(priv);
-
- wiphy = priv->hw->wiphy;
-
- wiphy->frag_threshold = FRAG_THRESH_DEF;
- wiphy->rts_threshold = RTS_THRESH_DEF;
- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
-
- ieee80211_hw_set(priv->hw, TIMING_BEACON_ONLY);
- ieee80211_hw_set(priv->hw, SIGNAL_DBM);
- ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS);
- ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS);
- ieee80211_hw_set(priv->hw, SUPPORTS_PS);
-
- priv->hw->max_signal = 100;
-
- if (vnt_init(priv)) {
- device_free_info(priv);
- return -ENODEV;
- }
-
- device_print_info(priv);
- pci_set_drvdata(pcid, priv);
-
- return 0;
-}
-
-/*------------------------------------------------------------------*/
-
-static int __maybe_unused vt6655_suspend(struct device *dev_d)
-{
- struct vnt_private *priv = dev_get_drvdata(dev_d);
- unsigned long flags;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- MACbShutdown(priv);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-static int __maybe_unused vt6655_resume(struct device *dev_d)
-{
- device_wakeup_disable(dev_d);
-
- return 0;
-}
-
-MODULE_DEVICE_TABLE(pci, vt6655_pci_id_table);
-
-static SIMPLE_DEV_PM_OPS(vt6655_pm_ops, vt6655_suspend, vt6655_resume);
-
-static struct pci_driver device_driver = {
- .name = DEVICE_NAME,
- .id_table = vt6655_pci_id_table,
- .probe = vt6655_probe,
- .remove = vt6655_remove,
- .driver.pm = &vt6655_pm_ops,
-};
-
-module_pci_driver(device_driver);
diff --git a/drivers/staging/vt6655/dpc.c b/drivers/staging/vt6655/dpc.c
deleted file mode 100644
index 7ada188e2048..000000000000
--- a/drivers/staging/vt6655/dpc.c
+++ /dev/null
@@ -1,145 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: handle dpc rx functions
- *
- * Author: Lyndon Chen
- *
- * Date: May 20, 2003
- *
- * Functions:
- *
- * Revision History:
- *
- */
-
-#include "device.h"
-#include "baseband.h"
-#include "rf.h"
-#include "dpc.h"
-
-static bool vnt_rx_data(struct vnt_private *priv, struct sk_buff *skb,
- u16 bytes_received)
-{
- struct ieee80211_hw *hw = priv->hw;
- struct ieee80211_supported_band *sband;
- struct ieee80211_rx_status rx_status = { 0 };
- struct ieee80211_hdr *hdr;
- __le16 fc;
- u8 *rsr, *new_rsr, *rssi;
- __le64 *tsf_time;
- u16 frame_size;
- int ii, r;
- u8 *rx_rate;
- u8 *skb_data;
- u8 rate_idx = 0;
- u8 rate[MAX_RATE] = {2, 4, 11, 22, 12, 18, 24, 36, 48, 72, 96, 108};
- long rx_dbm;
-
- /* [31:16]RcvByteCount ( not include 4-byte Status ) */
- frame_size = le16_to_cpu(*((__le16 *)(skb->data + 2)));
- if (frame_size > 2346 || frame_size < 14) {
- dev_dbg(&priv->pcid->dev, "------- WRONG Length 1\n");
- return false;
- }
-
- skb_data = (u8 *)skb->data;
-
- rx_rate = skb_data + 1;
-
- sband = hw->wiphy->bands[hw->conf.chandef.chan->band];
-
- for (r = RATE_1M; r < MAX_RATE; r++) {
- if (*rx_rate == rate[r])
- break;
- }
-
- priv->rx_rate = r;
-
- for (ii = 0; ii < sband->n_bitrates; ii++) {
- if (sband->bitrates[ii].hw_value == r) {
- rate_idx = ii;
- break;
- }
- }
-
- if (ii == sband->n_bitrates) {
- dev_dbg(&priv->pcid->dev, "Wrong RxRate %x\n", *rx_rate);
- return false;
- }
-
- tsf_time = (__le64 *)(skb_data + bytes_received - 12);
- new_rsr = skb_data + bytes_received - 3;
- rssi = skb_data + bytes_received - 2;
- rsr = skb_data + bytes_received - 1;
- if (*rsr & (RSR_IVLDTYP | RSR_IVLDLEN))
- return false;
-
- RFvRSSITodBm(priv, *rssi, &rx_dbm);
-
- priv->bb_pre_edrssi = (u8)rx_dbm + 1;
- priv->current_rssi = *rssi;
-
- skb_pull(skb, 4);
- skb_trim(skb, frame_size);
-
- rx_status.mactime = le64_to_cpu(*tsf_time);
- rx_status.band = hw->conf.chandef.chan->band;
- rx_status.signal = rx_dbm;
- rx_status.flag = 0;
- rx_status.freq = hw->conf.chandef.chan->center_freq;
-
- if (!(*rsr & RSR_CRCOK))
- rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
-
- hdr = (struct ieee80211_hdr *)(skb->data);
- fc = hdr->frame_control;
-
- rx_status.rate_idx = rate_idx;
-
- if (ieee80211_has_protected(fc)) {
- if (priv->local_id > REV_ID_VT3253_A1)
- rx_status.flag |= RX_FLAG_DECRYPTED;
-
- /* Drop packet */
- if (!(*new_rsr & NEWRSR_DECRYPTOK))
- return false;
- }
-
- memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
-
- ieee80211_rx_irqsafe(priv->hw, skb);
-
- return true;
-}
-
-bool vnt_receive_frame(struct vnt_private *priv, struct vnt_rx_desc *curr_rd)
-{
- struct vnt_rd_info *rd_info = curr_rd->rd_info;
- struct sk_buff *skb;
- u16 frame_size;
-
- skb = rd_info->skb;
-
- dma_unmap_single(&priv->pcid->dev, rd_info->skb_dma,
- priv->rx_buf_sz, DMA_FROM_DEVICE);
-
- frame_size = le16_to_cpu(curr_rd->rd1.req_count)
- - le16_to_cpu(curr_rd->rd0.res_count);
-
- if ((frame_size > 2364) || (frame_size < 33)) {
- /* Frame Size error drop this packet.*/
- dev_dbg(&priv->pcid->dev, "Wrong frame size %d\n", frame_size);
- dev_kfree_skb_irq(skb);
- return true;
- }
-
- if (vnt_rx_data(priv, skb, frame_size))
- return true;
-
- dev_kfree_skb_irq(skb);
-
- return true;
-}
diff --git a/drivers/staging/vt6655/dpc.h b/drivers/staging/vt6655/dpc.h
deleted file mode 100644
index 40364c0ab7f6..000000000000
--- a/drivers/staging/vt6655/dpc.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 27, 2002
- *
- */
-
-#ifndef __DPC_H__
-#define __DPC_H__
-
-#include "device.h"
-
-bool vnt_receive_frame(struct vnt_private *priv, struct vnt_rx_desc *curr_rd);
-
-#endif /* __RXTX_H__ */
diff --git a/drivers/staging/vt6655/key.c b/drivers/staging/vt6655/key.c
deleted file mode 100644
index 1469015eb5b4..000000000000
--- a/drivers/staging/vt6655/key.c
+++ /dev/null
@@ -1,143 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions for 802.11i Key management
- *
- * Author: Jerry Chen
- *
- * Date: May 29, 2003
- *
- */
-
-#include "key.h"
-#include "mac.h"
-
-static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr,
- struct ieee80211_key_conf *key, u32 key_type,
- u32 mode, bool onfly_latch)
-{
- struct vnt_private *priv = hw->priv;
- u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- u16 key_mode = 0;
- u32 entry = 0;
- u8 *bssid;
- u8 key_inx = key->keyidx;
- u8 i;
-
- if (mac_addr)
- bssid = mac_addr;
- else
- bssid = &broadcast[0];
-
- if (key_type != VNT_KEY_DEFAULTKEY) {
- for (i = 0; i < (MAX_KEY_TABLE - 1); i++) {
- if (!test_bit(i, &priv->key_entry_inuse)) {
- set_bit(i, &priv->key_entry_inuse);
-
- key->hw_key_idx = i;
- entry = key->hw_key_idx;
- break;
- }
- }
- }
-
- switch (key_type) {
- case VNT_KEY_DEFAULTKEY:
- /* default key last entry */
- entry = MAX_KEY_TABLE - 1;
- key->hw_key_idx = entry;
- fallthrough;
- case VNT_KEY_ALLGROUP:
- key_mode |= VNT_KEY_ALLGROUP;
- if (onfly_latch)
- key_mode |= VNT_KEY_ONFLY_ALL;
- fallthrough;
- case VNT_KEY_GROUP_ADDRESS:
- key_mode |= mode;
- fallthrough;
- case VNT_KEY_GROUP:
- key_mode |= (mode << 4);
- key_mode |= VNT_KEY_GROUP;
- break;
- case VNT_KEY_PAIRWISE:
- key_mode |= mode;
- key_inx = 4;
- break;
- default:
- return -EINVAL;
- }
-
- if (onfly_latch)
- key_mode |= VNT_KEY_ONFLY;
-
- if (mode == KEY_CTL_WEP) {
- if (key->keylen == WLAN_KEY_LEN_WEP40)
- key->key[15] &= 0x7f;
- if (key->keylen == WLAN_KEY_LEN_WEP104)
- key->key[15] |= 0x80;
- }
-
- MACvSetKeyEntry(priv, key_mode, entry, key_inx,
- bssid, (u32 *)key->key, priv->local_id);
-
- return 0;
-}
-
-int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- struct ieee80211_vif *vif, struct ieee80211_key_conf *key)
-{
- struct ieee80211_bss_conf *conf = &vif->bss_conf;
- struct vnt_private *priv = hw->priv;
- u8 *mac_addr = NULL;
- u8 key_dec_mode = 0;
- int ret = 0;
- u32 u;
-
- if (sta)
- mac_addr = &sta->addr[0];
-
- switch (key->cipher) {
- case 0:
- for (u = 0 ; u < MAX_KEY_TABLE; u++)
- MACvDisableKeyEntry(priv, u);
- return ret;
-
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- for (u = 0; u < MAX_KEY_TABLE; u++)
- MACvDisableKeyEntry(priv, u);
-
- vnt_set_keymode(hw, mac_addr,
- key, VNT_KEY_DEFAULTKEY, KEY_CTL_WEP, true);
-
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-
- return ret;
- case WLAN_CIPHER_SUITE_TKIP:
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-
- key_dec_mode = KEY_CTL_TKIP;
-
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- key_dec_mode = KEY_CTL_CCMP;
-
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- }
-
- if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
- vnt_set_keymode(hw, mac_addr,
- key, VNT_KEY_PAIRWISE, key_dec_mode, true);
- } else {
- vnt_set_keymode(hw, mac_addr,
- key, VNT_KEY_DEFAULTKEY, key_dec_mode, true);
-
- vnt_set_keymode(hw, (u8 *)conf->bssid,
- key, VNT_KEY_GROUP_ADDRESS, key_dec_mode, true);
- }
-
- return 0;
-}
diff --git a/drivers/staging/vt6655/key.h b/drivers/staging/vt6655/key.h
deleted file mode 100644
index d88da9dfb5c3..000000000000
--- a/drivers/staging/vt6655/key.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions for 802.11i Key management
- *
- * Author: Jerry Chen
- *
- * Date: May 29, 2003
- *
- */
-
-#ifndef __KEY_H__
-#define __KEY_H__
-
-#include <net/mac80211.h>
-
-/*--------------------- Export Definitions -------------------------*/
-#define MAX_GROUP_KEY 4
-#define MAX_KEY_TABLE 11
-#define MAX_KEY_LEN 32
-#define AES_KEY_LEN 16
-
-#define AUTHENTICATOR_KEY 0x10000000
-#define USE_KEYRSC 0x20000000
-#define PAIRWISE_KEY 0x40000000
-#define TRANSMIT_KEY 0x80000000
-
-#define GROUP_KEY 0x00000000
-
-#define KEY_CTL_WEP 0x00
-#define KEY_CTL_NONE 0x01
-#define KEY_CTL_TKIP 0x02
-#define KEY_CTL_CCMP 0x03
-#define KEY_CTL_INVALID 0xFF
-
-#define VNT_KEY_DEFAULTKEY 0x1
-#define VNT_KEY_GROUP_ADDRESS 0x2
-#define VNT_KEY_ALLGROUP 0x4
-#define VNT_KEY_GROUP 0x40
-#define VNT_KEY_PAIRWISE 0x00
-#define VNT_KEY_ONFLY 0x8000
-#define VNT_KEY_ONFLY_ALL 0x4000
-
-struct vnt_private;
-
-int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- struct ieee80211_vif *vif, struct ieee80211_key_conf *key);
-
-#endif /* __KEY_H__ */
diff --git a/drivers/staging/vt6655/mac.c b/drivers/staging/vt6655/mac.c
deleted file mode 100644
index b4ebc7d31961..000000000000
--- a/drivers/staging/vt6655/mac.c
+++ /dev/null
@@ -1,851 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC routines
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- * Functions:
- * vt6655_mac_is_reg_bits_off - Test if All test Bits Off
- * vt6655_mac_set_short_retry_limit - Set 802.11 Short Retry limit
- * MACvSetLongRetryLimit - Set 802.11 Long Retry limit
- * vt6655_mac_set_loopback_mode - Set MAC Loopback Mode
- * vt6655_mac_save_context - Save Context of MAC Registers
- * vt6655_mac_restore_context - Restore Context of MAC Registers
- * MACbSoftwareReset - Software Reset MAC
- * vt6655_mac_safe_rx_off - Turn Off MAC Rx
- * vt6655_mac_safe_tx_off - Turn Off MAC Tx
- * vt6655_mac_safe_stop - Stop MAC function
- * MACbShutdown - Shut down MAC
- * MACvInitialize - Initialize MAC
- * MACvSetCurrRxDescAddr - Set Rx Descriptors Address
- * MACvSetCurrTx0DescAddr - Set Tx0 Descriptors Address
- * MACvSetCurrTx1DescAddr - Set Tx1 Descriptors Address
- * MACvTimer0MicroSDelay - Micro Second Delay Loop by MAC
- *
- * Revision History:
- * 08-22-2003 Kyle Hsu : Porting MAC functions from sim53
- * 09-03-2003 Bryan YC Fan : Add MACvClearBusSusInd()&
- * MACvEnableBusSusEn()
- * 09-18-2003 Jerry Chen : Add MACvSetKeyEntry & MACvDisableKeyEntry
- *
- */
-
-#include "mac.h"
-
-void vt6655_mac_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask)
-{
- unsigned char reg_value;
-
- reg_value = ioread8(iobase + reg_offset);
- iowrite8(reg_value | bit_mask, iobase + reg_offset);
-}
-
-void vt6655_mac_word_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask)
-{
- unsigned short reg_value;
-
- reg_value = ioread16(iobase + reg_offset);
- iowrite16(reg_value | (bit_mask), iobase + reg_offset);
-}
-
-void vt6655_mac_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask)
-{
- unsigned char reg_value;
-
- reg_value = ioread8(iobase + reg_offset);
- iowrite8(reg_value & ~(bit_mask), iobase + reg_offset);
-}
-
-void vt6655_mac_word_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask)
-{
- unsigned short reg_value;
-
- reg_value = ioread16(iobase + reg_offset);
- iowrite16(reg_value & ~(bit_mask), iobase + reg_offset);
-}
-
-static void vt6655_mac_clear_stck_ds(void __iomem *iobase)
-{
- u8 reg_value;
-
- reg_value = ioread8(iobase + MAC_REG_STICKHW);
- reg_value = reg_value & 0xFC;
- iowrite8(reg_value, iobase + MAC_REG_STICKHW);
-}
-
-/*
- * Description:
- * Test if all test bits off
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * reg_offset - Offset of MAC Register
- * mask - Test bits
- * Out:
- * none
- *
- * Return Value: true if all test bits Off; otherwise false
- *
- */
-static bool vt6655_mac_is_reg_bits_off(struct vnt_private *priv,
- unsigned char reg_offset,
- unsigned char mask)
-{
- void __iomem *io_base = priv->port_offset;
-
- return !(ioread8(io_base + reg_offset) & mask);
-}
-
-/*
- * Description:
- * Set 802.11 Short Retry Limit
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * retry_limit - Retry Limit
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void vt6655_mac_set_short_retry_limit(struct vnt_private *priv, unsigned char retry_limit)
-{
- void __iomem *io_base = priv->port_offset;
- /* set SRT */
- iowrite8(retry_limit, io_base + MAC_REG_SRT);
-}
-
-/*
- * Description:
- * Set 802.11 Long Retry Limit
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * byRetryLimit- Retry Limit
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void MACvSetLongRetryLimit(struct vnt_private *priv,
- unsigned char byRetryLimit)
-{
- void __iomem *io_base = priv->port_offset;
- /* set LRT */
- iowrite8(byRetryLimit, io_base + MAC_REG_LRT);
-}
-
-/*
- * Description:
- * Set MAC Loopback mode
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * loopback_mode - Loopback Mode
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-static void vt6655_mac_set_loopback_mode(struct vnt_private *priv, u8 loopback_mode)
-{
- void __iomem *io_base = priv->port_offset;
-
- loopback_mode <<= 6;
- /* set TCR */
- iowrite8((ioread8(io_base + MAC_REG_TEST) & 0x3f) | loopback_mode, io_base + MAC_REG_TEST);
-}
-
-/*
- * Description:
- * Save MAC registers to context buffer
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * cxt_buf - Context buffer
- *
- * Return Value: none
- *
- */
-static void vt6655_mac_save_context(struct vnt_private *priv, u8 *cxt_buf)
-{
- void __iomem *io_base = priv->port_offset;
-
- /* read page0 register */
- memcpy_fromio(cxt_buf, io_base, MAC_MAX_CONTEXT_SIZE_PAGE0);
-
- VT6655_MAC_SELECT_PAGE1(io_base);
-
- /* read page1 register */
- memcpy_fromio(cxt_buf + MAC_MAX_CONTEXT_SIZE_PAGE0, io_base,
- MAC_MAX_CONTEXT_SIZE_PAGE1);
-
- VT6655_MAC_SELECT_PAGE0(io_base);
-}
-
-/*
- * Description:
- * Restore MAC registers from context buffer
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * cxt_buf - Context buffer
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-static void vt6655_mac_restore_context(struct vnt_private *priv, u8 *cxt_buf)
-{
- void __iomem *io_base = priv->port_offset;
-
- VT6655_MAC_SELECT_PAGE1(io_base);
- /* restore page1 */
- memcpy_toio(io_base, cxt_buf + MAC_MAX_CONTEXT_SIZE_PAGE0,
- MAC_MAX_CONTEXT_SIZE_PAGE1);
-
- VT6655_MAC_SELECT_PAGE0(io_base);
-
- /* restore RCR,TCR,IMR... */
- memcpy_toio(io_base + MAC_REG_RCR, cxt_buf + MAC_REG_RCR,
- MAC_REG_ISR - MAC_REG_RCR);
-
- /* restore MAC Config. */
- memcpy_toio(io_base + MAC_REG_LRT, cxt_buf + MAC_REG_LRT,
- MAC_REG_PAGE1SEL - MAC_REG_LRT);
-
- iowrite8(*(cxt_buf + MAC_REG_CFG), io_base + MAC_REG_CFG);
-
- /* restore PS Config. */
- memcpy_toio(io_base + MAC_REG_PSCFG, cxt_buf + MAC_REG_PSCFG,
- MAC_REG_BBREGCTL - MAC_REG_PSCFG);
-
- /* restore CURR_RX_DESC_ADDR, CURR_TX_DESC_ADDR */
- iowrite32(*(u32 *)(cxt_buf + MAC_REG_TXDMAPTR0),
- io_base + MAC_REG_TXDMAPTR0);
- iowrite32(*(u32 *)(cxt_buf + MAC_REG_AC0DMAPTR),
- io_base + MAC_REG_AC0DMAPTR);
- iowrite32(*(u32 *)(cxt_buf + MAC_REG_BCNDMAPTR),
- io_base + MAC_REG_BCNDMAPTR);
- iowrite32(*(u32 *)(cxt_buf + MAC_REG_RXDMAPTR0),
- io_base + MAC_REG_RXDMAPTR0);
- iowrite32(*(u32 *)(cxt_buf + MAC_REG_RXDMAPTR1),
- io_base + MAC_REG_RXDMAPTR1);
-}
-
-/*
- * Description:
- * Software Reset MAC
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if Reset Success; otherwise false
- *
- */
-bool MACbSoftwareReset(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
-
- /* turn on HOSTCR_SOFTRST, just write 0x01 to reset */
- iowrite8(0x01, io_base + MAC_REG_HOSTCR);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_SOFTRST))
- break;
- }
- if (ww == W_MAX_TIMEOUT)
- return false;
- return true;
-}
-
-/*
- * Description:
- * save some important register's value, then do reset, then restore
- * register's value
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-static void vt6655_mac_save_soft_reset(struct vnt_private *priv)
-{
- u8 tmp_reg_data[MAC_MAX_CONTEXT_SIZE_PAGE0 + MAC_MAX_CONTEXT_SIZE_PAGE1];
-
- /* PATCH....
- * save some important register's value, then do
- * reset, then restore register's value
- */
- /* save MAC context */
- vt6655_mac_save_context(priv, tmp_reg_data);
- /* do reset */
- MACbSoftwareReset(priv);
- /* restore MAC context, except CR0 */
- vt6655_mac_restore_context(priv, tmp_reg_data);
-}
-
-/*
- * Description:
- * Turn Off MAC Rx
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-static bool vt6655_mac_safe_rx_off(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
-
- /* turn off wow temp for turn off Rx safely */
-
- /* Clear RX DMA0,1 */
- iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_RXDMACTL0);
- iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_RXDMACTL1);
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread32(io_base + MAC_REG_RXDMACTL0) & DMACTL_RUN))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x10)\n");
- return false;
- }
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread32(io_base + MAC_REG_RXDMACTL1) & DMACTL_RUN))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x11)\n");
- return false;
- }
-
- /* try to safe shutdown RX */
- vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_RXON);
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_RXONST))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x12)\n");
- return false;
- }
- return true;
-}
-
-/*
- * Description:
- * Turn Off MAC Tx
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-static bool vt6655_mac_safe_tx_off(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
-
- /* Clear TX DMA */
- /* Tx0 */
- iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_TXDMACTL0);
- /* AC0 */
- iowrite32(DMACTL_CLRRUN, io_base + MAC_REG_AC0DMACTL);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread32(io_base + MAC_REG_TXDMACTL0) & DMACTL_RUN))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x20)\n");
- return false;
- }
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread32(io_base + MAC_REG_AC0DMACTL) & DMACTL_RUN))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x21)\n");
- return false;
- }
-
- /* try to safe shutdown TX */
- vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_TXON);
-
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_HOSTCR) & HOSTCR_TXONST))
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x24)\n");
- return false;
- }
- return true;
-}
-
-/*
- * Description:
- * Stop MAC function
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-static bool vt6655_mac_safe_stop(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
-
- vt6655_mac_reg_bits_off(io_base, MAC_REG_TCR, TCR_AUTOBCNTX);
-
- if (!vt6655_mac_safe_rx_off(priv)) {
- pr_debug(" vt6655_mac_safe_rx_off == false)\n");
- vt6655_mac_save_soft_reset(priv);
- return false;
- }
- if (!vt6655_mac_safe_tx_off(priv)) {
- pr_debug(" vt6655_mac_safe_tx_off == false)\n");
- vt6655_mac_save_soft_reset(priv);
- return false;
- }
-
- vt6655_mac_reg_bits_off(io_base, MAC_REG_HOSTCR, HOSTCR_MACEN);
-
- return true;
-}
-
-/*
- * Description:
- * Shut Down MAC
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-bool MACbShutdown(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- /* disable MAC IMR */
- iowrite32(0, io_base + MAC_REG_IMR);
- vt6655_mac_set_loopback_mode(priv, MAC_LB_INTERNAL);
- /* stop the adapter */
- if (!vt6655_mac_safe_stop(priv)) {
- vt6655_mac_set_loopback_mode(priv, MAC_LB_NONE);
- return false;
- }
- vt6655_mac_set_loopback_mode(priv, MAC_LB_NONE);
- return true;
-}
-
-/*
- * Description:
- * Initialize MAC
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void MACvInitialize(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- /* clear sticky bits */
- vt6655_mac_clear_stck_ds(io_base);
- /* disable force PME-enable */
- iowrite8(PME_OVR, io_base + MAC_REG_PMC1);
- /* only 3253 A */
-
- /* do reset */
- MACbSoftwareReset(priv);
-
- /* reset TSF counter */
- iowrite8(TFTCTL_TSFCNTRST, io_base + MAC_REG_TFTCTL);
- /* enable TSF counter */
- iowrite8(TFTCTL_TSFCNTREN, io_base + MAC_REG_TFTCTL);
-}
-
-/*
- * Description:
- * Set the chip with current rx descriptor address
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * curr_desc_addr - Descriptor Address
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void vt6655_mac_set_curr_rx_0_desc_addr(struct vnt_private *priv, u32 curr_desc_addr)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
- unsigned char org_dma_ctl;
-
- org_dma_ctl = ioread8(io_base + MAC_REG_RXDMACTL0);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL0 + 2);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_RXDMACTL0) & DMACTL_RUN))
- break;
- }
-
- iowrite32(curr_desc_addr, io_base + MAC_REG_RXDMAPTR0);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL0);
-}
-
-/*
- * Description:
- * Set the chip with current rx descriptor address
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * curr_desc_addr - Descriptor Address
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void vt6655_mac_set_curr_rx_1_desc_addr(struct vnt_private *priv, u32 curr_desc_addr)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
- unsigned char org_dma_ctl;
-
- org_dma_ctl = ioread8(io_base + MAC_REG_RXDMACTL1);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL1 + 2);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_RXDMACTL1) & DMACTL_RUN))
- break;
- }
-
- iowrite32(curr_desc_addr, io_base + MAC_REG_RXDMAPTR1);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_RXDMACTL1);
-}
-
-/*
- * Description:
- * Set the chip with current tx0 descriptor address
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * curr_desc_addr - Descriptor Address
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-static void vt6655_mac_set_curr_tx_0_desc_addr_ex(struct vnt_private *priv, u32 curr_desc_addr)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
- unsigned char org_dma_ctl;
-
- org_dma_ctl = ioread8(io_base + MAC_REG_TXDMACTL0);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_TXDMACTL0 + 2);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_TXDMACTL0) & DMACTL_RUN))
- break;
- }
-
- iowrite32(curr_desc_addr, io_base + MAC_REG_TXDMAPTR0);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_TXDMACTL0);
-}
-
-/*
- * Description:
- * Set the chip with current AC0 descriptor address
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * curr_desc_addr - Descriptor Address
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-/* TxDMA1 = AC0DMA */
-static void vt6655_mac_set_curr_ac_0_desc_addr_ex(struct vnt_private *priv, u32 curr_desc_addr)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short ww;
- unsigned char org_dma_ctl;
-
- org_dma_ctl = ioread8(io_base + MAC_REG_AC0DMACTL);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_AC0DMACTL + 2);
-
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (!(ioread8(io_base + MAC_REG_AC0DMACTL) & DMACTL_RUN))
- break;
- }
- if (ww == W_MAX_TIMEOUT)
- pr_debug(" DBG_PORT80(0x26)\n");
- iowrite32(curr_desc_addr, io_base + MAC_REG_AC0DMAPTR);
- if (org_dma_ctl & DMACTL_RUN)
- iowrite8(DMACTL_RUN, io_base + MAC_REG_AC0DMACTL);
-}
-
-void vt6655_mac_set_curr_tx_desc_addr(int tx_type, struct vnt_private *priv, u32 curr_desc_addr)
-{
- if (tx_type == TYPE_AC0DMA)
- vt6655_mac_set_curr_ac_0_desc_addr_ex(priv, curr_desc_addr);
- else if (tx_type == TYPE_TXDMA0)
- vt6655_mac_set_curr_tx_0_desc_addr_ex(priv, curr_desc_addr);
-}
-
-/*
- * Description:
- * Micro Second Delay via MAC
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * uDelay - Delay time (timer resolution is 4 us)
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned char byValue;
- unsigned int uu, ii;
-
- iowrite8(0, io_base + MAC_REG_TMCTL0);
- iowrite32(uDelay, io_base + MAC_REG_TMDATA0);
- iowrite8((TMCTL_TMD | TMCTL_TE), io_base + MAC_REG_TMCTL0);
- for (ii = 0; ii < 66; ii++) { /* assume max PCI clock is 66Mhz */
- for (uu = 0; uu < uDelay; uu++) {
- byValue = ioread8(io_base + MAC_REG_TMCTL0);
- if ((byValue == 0) ||
- (byValue & TMCTL_TSUSP)) {
- iowrite8(0, io_base + MAC_REG_TMCTL0);
- return;
- }
- }
- }
- iowrite8(0, io_base + MAC_REG_TMCTL0);
-}
-
-/*
- * Description:
- * Micro Second One shot timer via MAC
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- * uDelay - Delay time
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void MACvOneShotTimer1MicroSec(struct vnt_private *priv,
- unsigned int uDelayTime)
-{
- void __iomem *io_base = priv->port_offset;
-
- iowrite8(0, io_base + MAC_REG_TMCTL1);
- iowrite32(uDelayTime, io_base + MAC_REG_TMDATA1);
- iowrite8((TMCTL_TMD | TMCTL_TE), io_base + MAC_REG_TMCTL1);
-}
-
-void MACvSetMISCFifo(struct vnt_private *priv, unsigned short offset,
- u32 data)
-{
- void __iomem *io_base = priv->port_offset;
-
- if (offset > 273)
- return;
- iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
- iowrite32(data, io_base + MAC_REG_MISCFFDATA);
- iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
-}
-
-bool MACbPSWakeup(struct vnt_private *priv)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned int ww;
- /* Read PSCTL */
- if (vt6655_mac_is_reg_bits_off(priv, MAC_REG_PSCTL, PSCTL_PS))
- return true;
-
- /* Disable PS */
- vt6655_mac_reg_bits_off(io_base, MAC_REG_PSCTL, PSCTL_PSEN);
-
- /* Check if SyncFlushOK */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- if (ioread8(io_base + MAC_REG_PSCTL) & PSCTL_WAKEDONE)
- break;
- }
- if (ww == W_MAX_TIMEOUT) {
- pr_debug(" DBG_PORT80(0x33)\n");
- return false;
- }
- return true;
-}
-
-/*
- * Description:
- * Set the Key by MISCFIFO
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- *
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-
-void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl,
- unsigned int uEntryIdx, unsigned int uKeyIdx,
- unsigned char *pbyAddr, u32 *pdwKey,
- unsigned char local_id)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short offset;
- u32 data;
- int ii;
-
- if (local_id <= 1)
- return;
-
- offset = MISCFIFO_KEYETRY0;
- offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
-
- data = 0;
- data |= wKeyCtl;
- data <<= 16;
- data |= MAKEWORD(*(pbyAddr + 4), *(pbyAddr + 5));
- pr_debug("1. offset: %d, Data: %X, KeyCtl:%X\n",
- offset, data, wKeyCtl);
-
- iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
- iowrite32(data, io_base + MAC_REG_MISCFFDATA);
- iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
- offset++;
-
- data = 0;
- data |= *(pbyAddr + 3);
- data <<= 8;
- data |= *(pbyAddr + 2);
- data <<= 8;
- data |= *(pbyAddr + 1);
- data <<= 8;
- data |= *pbyAddr;
- pr_debug("2. offset: %d, Data: %X\n", offset, data);
-
- iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
- iowrite32(data, io_base + MAC_REG_MISCFFDATA);
- iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
- offset++;
-
- offset += (uKeyIdx * 4);
- for (ii = 0; ii < 4; ii++) {
- /* always push 128 bits */
- pr_debug("3.(%d) offset: %d, Data: %X\n",
- ii, offset + ii, *pdwKey);
- iowrite16(offset + ii, io_base + MAC_REG_MISCFFNDEX);
- iowrite32(*pdwKey++, io_base + MAC_REG_MISCFFDATA);
- iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
- }
-}
-
-/*
- * Description:
- * Disable the Key Entry by MISCFIFO
- *
- * Parameters:
- * In:
- * io_base - Base Address for MAC
- *
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx)
-{
- void __iomem *io_base = priv->port_offset;
- unsigned short offset;
-
- offset = MISCFIFO_KEYETRY0;
- offset += (uEntryIdx * MISCFIFO_KEYENTRYSIZE);
-
- iowrite16(offset, io_base + MAC_REG_MISCFFNDEX);
- iowrite32(0, io_base + MAC_REG_MISCFFDATA);
- iowrite16(MISCFFCTL_WRITE, io_base + MAC_REG_MISCFFCTL);
-}
diff --git a/drivers/staging/vt6655/mac.h b/drivers/staging/vt6655/mac.h
deleted file mode 100644
index a33af2852227..000000000000
--- a/drivers/staging/vt6655/mac.h
+++ /dev/null
@@ -1,580 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC routines
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- * Revision History:
- * 07-01-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-25-2003 Kyle Hsu: Porting MAC functions from sim53.
- * 09-03-2003 Bryan YC Fan: Add vt6655_mac_dis_protect_md & vt6655_mac_en_protect_md
- */
-
-#ifndef __MAC_H__
-#define __MAC_H__
-
-#include "device.h"
-
-/*--------------------- Export Definitions -------------------------*/
-/* Registers in the MAC */
-#define MAC_MAX_CONTEXT_SIZE_PAGE0 256
-#define MAC_MAX_CONTEXT_SIZE_PAGE1 128
-
-/* Registers not related to 802.11b */
-#define MAC_REG_BCFG0 0x00
-#define MAC_REG_BCFG1 0x01
-#define MAC_REG_FCR0 0x02
-#define MAC_REG_FCR1 0x03
-#define MAC_REG_BISTCMD 0x04
-#define MAC_REG_BISTSR0 0x05
-#define MAC_REG_BISTSR1 0x06
-#define MAC_REG_BISTSR2 0x07
-#define MAC_REG_I2MCSR 0x08
-#define MAC_REG_I2MTGID 0x09
-#define MAC_REG_I2MTGAD 0x0A
-#define MAC_REG_I2MCFG 0x0B
-#define MAC_REG_I2MDIPT 0x0C
-#define MAC_REG_I2MDOPT 0x0E
-#define MAC_REG_PMC0 0x10
-#define MAC_REG_PMC1 0x11
-#define MAC_REG_STICKHW 0x12
-#define MAC_REG_LOCALID 0x14
-#define MAC_REG_TESTCFG 0x15
-#define MAC_REG_JUMPER0 0x16
-#define MAC_REG_JUMPER1 0x17
-#define MAC_REG_TMCTL0 0x18
-#define MAC_REG_TMCTL1 0x19
-#define MAC_REG_TMDATA0 0x1C
-
-/* MAC Parameter related */
-#define MAC_REG_LRT 0x20
-#define MAC_REG_SRT 0x21
-#define MAC_REG_SIFS 0x22
-#define MAC_REG_DIFS 0x23
-#define MAC_REG_EIFS 0x24
-#define MAC_REG_SLOT 0x25
-#define MAC_REG_BI 0x26
-#define MAC_REG_CWMAXMIN0 0x28
-#define MAC_REG_LINKOFFTOTM 0x2A
-#define MAC_REG_SWTMOT 0x2B
-#define MAC_REG_MIBCNTR 0x2C
-#define MAC_REG_RTSOKCNT 0x2C
-#define MAC_REG_RTSFAILCNT 0x2D
-#define MAC_REG_ACKFAILCNT 0x2E
-#define MAC_REG_FCSERRCNT 0x2F
-
-/* TSF Related */
-#define MAC_REG_TSFCNTR 0x30
-#define MAC_REG_NEXTTBTT 0x38
-#define MAC_REG_TSFOFST 0x40
-#define MAC_REG_TFTCTL 0x48
-
-/* WMAC Control/Status Related */
-#define MAC_REG_ENCFG 0x4C
-#define MAC_REG_PAGE1SEL 0x4F
-#define MAC_REG_CFG 0x50
-#define MAC_REG_TEST 0x52
-#define MAC_REG_HOSTCR 0x54
-#define MAC_REG_MACCR 0x55
-#define MAC_REG_RCR 0x56
-#define MAC_REG_TCR 0x57
-#define MAC_REG_IMR 0x58
-#define MAC_REG_ISR 0x5C
-
-/* Power Saving Related */
-#define MAC_REG_PSCFG 0x60
-#define MAC_REG_PSCTL 0x61
-#define MAC_REG_PSPWRSIG 0x62
-#define MAC_REG_BBCR13 0x63
-#define MAC_REG_AIDATIM 0x64
-#define MAC_REG_PWBT 0x66
-#define MAC_REG_WAKEOKTMR 0x68
-#define MAC_REG_CALTMR 0x69
-#define MAC_REG_SYNSPACCNT 0x6A
-#define MAC_REG_WAKSYNOPT 0x6B
-
-/* Baseband/IF Control Group */
-#define MAC_REG_BBREGCTL 0x6C
-#define MAC_REG_CHANNEL 0x6D
-#define MAC_REG_BBREGADR 0x6E
-#define MAC_REG_BBREGDATA 0x6F
-#define MAC_REG_IFREGCTL 0x70
-#define MAC_REG_IFDATA 0x71
-#define MAC_REG_ITRTMSET 0x74
-#define MAC_REG_PAPEDELAY 0x77
-#define MAC_REG_SOFTPWRCTL 0x78
-#define MAC_REG_GPIOCTL0 0x7A
-#define MAC_REG_GPIOCTL1 0x7B
-
-/* MAC DMA Related Group */
-#define MAC_REG_TXDMACTL0 0x7C
-#define MAC_REG_TXDMAPTR0 0x80
-#define MAC_REG_AC0DMACTL 0x84
-#define MAC_REG_AC0DMAPTR 0x88
-#define MAC_REG_BCNDMACTL 0x8C
-#define MAC_REG_BCNDMAPTR 0x90
-#define MAC_REG_RXDMACTL0 0x94
-#define MAC_REG_RXDMAPTR0 0x98
-#define MAC_REG_RXDMACTL1 0x9C
-#define MAC_REG_RXDMAPTR1 0xA0
-#define MAC_REG_SYNCDMACTL 0xA4
-#define MAC_REG_SYNCDMAPTR 0xA8
-#define MAC_REG_ATIMDMACTL 0xAC
-#define MAC_REG_ATIMDMAPTR 0xB0
-
-/* MiscFF PIO related */
-#define MAC_REG_MISCFFNDEX 0xB4
-#define MAC_REG_MISCFFCTL 0xB6
-#define MAC_REG_MISCFFDATA 0xB8
-
-/* Extend SW Timer */
-#define MAC_REG_TMDATA1 0xBC
-
-/* WOW Related Group */
-#define MAC_REG_WAKEUPEN0 0xC0
-#define MAC_REG_WAKEUPEN1 0xC1
-#define MAC_REG_WAKEUPSR0 0xC2
-#define MAC_REG_WAKEUPSR1 0xC3
-#define MAC_REG_WAKE128_0 0xC4
-#define MAC_REG_WAKE128_1 0xD4
-#define MAC_REG_WAKE128_2 0xE4
-#define MAC_REG_WAKE128_3 0xF4
-
-/************** Page 1 ******************/
-#define MAC_REG_CRC_128_0 0x04
-#define MAC_REG_CRC_128_1 0x06
-#define MAC_REG_CRC_128_2 0x08
-#define MAC_REG_CRC_128_3 0x0A
-
-/* MAC Configuration Group */
-#define MAC_REG_PAR0 0x0C
-#define MAC_REG_PAR4 0x10
-#define MAC_REG_BSSID0 0x14
-#define MAC_REG_BSSID4 0x18
-#define MAC_REG_MAR0 0x1C
-#define MAC_REG_MAR4 0x20
-
-/* MAC RSPPKT INFO Group */
-#define MAC_REG_RSPINF_B_1 0x24
-#define MAC_REG_RSPINF_B_2 0x28
-#define MAC_REG_RSPINF_B_5 0x2C
-#define MAC_REG_RSPINF_B_11 0x30
-#define MAC_REG_RSPINF_A_6 0x34
-#define MAC_REG_RSPINF_A_9 0x36
-#define MAC_REG_RSPINF_A_12 0x38
-#define MAC_REG_RSPINF_A_18 0x3A
-#define MAC_REG_RSPINF_A_24 0x3C
-#define MAC_REG_RSPINF_A_36 0x3E
-#define MAC_REG_RSPINF_A_48 0x40
-#define MAC_REG_RSPINF_A_54 0x42
-#define MAC_REG_RSPINF_A_72 0x44
-
-/* 802.11h relative */
-#define MAC_REG_QUIETINIT 0x60
-#define MAC_REG_QUIETGAP 0x62
-#define MAC_REG_QUIETDUR 0x64
-#define MAC_REG_MSRCTL 0x66
-#define MAC_REG_MSRBBSTS 0x67
-#define MAC_REG_MSRSTART 0x68
-#define MAC_REG_MSRDURATION 0x70
-#define MAC_REG_CCAFRACTION 0x72
-#define MAC_REG_PWRCCK 0x73
-#define MAC_REG_PWROFDM 0x7C
-
-/* Bits in the BCFG0 register */
-#define BCFG0_PERROFF 0x40
-#define BCFG0_MRDMDIS 0x20
-#define BCFG0_MRDLDIS 0x10
-#define BCFG0_MWMEN 0x08
-#define BCFG0_VSERREN 0x02
-#define BCFG0_LATMEN 0x01
-
-/* Bits in the BCFG1 register */
-#define BCFG1_CFUNOPT 0x80
-#define BCFG1_CREQOPT 0x40
-#define BCFG1_DMA8 0x10
-#define BCFG1_ARBITOPT 0x08
-#define BCFG1_PCIMEN 0x04
-#define BCFG1_MIOEN 0x02
-#define BCFG1_CISDLYEN 0x01
-
-/* Bits in RAMBIST registers */
-#define BISTCMD_TSTPAT5 0x00
-#define BISTCMD_TSTPATA 0x80
-#define BISTCMD_TSTERR 0x20
-#define BISTCMD_TSTPATF 0x18
-#define BISTCMD_TSTPAT0 0x10
-#define BISTCMD_TSTMODE 0x04
-#define BISTCMD_TSTITTX 0x03
-#define BISTCMD_TSTATRX 0x02
-#define BISTCMD_TSTATTX 0x01
-#define BISTCMD_TSTRX 0x00
-#define BISTSR0_BISTGO 0x01
-#define BISTSR1_TSTSR 0x01
-#define BISTSR2_CMDPRTEN 0x02
-#define BISTSR2_RAMTSTEN 0x01
-
-/* Bits in the I2MCFG EEPROM register */
-#define I2MCFG_BOUNDCTL 0x80
-#define I2MCFG_WAITCTL 0x20
-#define I2MCFG_SCLOECTL 0x10
-#define I2MCFG_WBUSYCTL 0x08
-#define I2MCFG_NORETRY 0x04
-#define I2MCFG_I2MLDSEQ 0x02
-#define I2MCFG_I2CMFAST 0x01
-
-/* Bits in the I2MCSR EEPROM register */
-#define I2MCSR_EEMW 0x80
-#define I2MCSR_EEMR 0x40
-#define I2MCSR_AUTOLD 0x08
-#define I2MCSR_NACK 0x02
-#define I2MCSR_DONE 0x01
-
-/* Bits in the PMC1 register */
-#define SPS_RST 0x80
-#define PCISTIKY 0x40
-#define PME_OVR 0x02
-
-/* Bits in the STICKYHW register */
-#define STICKHW_DS1_SHADOW 0x02
-#define STICKHW_DS0_SHADOW 0x01
-
-/* Bits in the TMCTL register */
-#define TMCTL_TSUSP 0x04
-#define TMCTL_TMD 0x02
-#define TMCTL_TE 0x01
-
-/* Bits in the TFTCTL register */
-#define TFTCTL_HWUTSF 0x80
-#define TFTCTL_TBTTSYNC 0x40
-#define TFTCTL_HWUTSFEN 0x20
-#define TFTCTL_TSFCNTRRD 0x10
-#define TFTCTL_TBTTSYNCEN 0x08
-#define TFTCTL_TSFSYNCEN 0x04
-#define TFTCTL_TSFCNTRST 0x02
-#define TFTCTL_TSFCNTREN 0x01
-
-/* Bits in the EnhanceCFG register */
-#define ENCFG_BARKERPREAM 0x00020000
-#define ENCFG_NXTBTTCFPSTR 0x00010000
-#define ENCFG_BCNSUSCLR 0x00000200
-#define ENCFG_BCNSUSIND 0x00000100
-#define ENCFG_CFP_PROTECTEN 0x00000040
-#define ENCFG_PROTECTMD 0x00000020
-#define ENCFG_HWPARCFP 0x00000010
-#define ENCFG_CFNULRSP 0x00000004
-#define ENCFG_BBTYPE_MASK 0x00000003
-#define ENCFG_BBTYPE_G 0x00000002
-#define ENCFG_BBTYPE_B 0x00000001
-#define ENCFG_BBTYPE_A 0x00000000
-
-/* Bits in the Page1Sel register */
-#define PAGE1_SEL 0x01
-
-/* Bits in the CFG register */
-#define CFG_TKIPOPT 0x80
-#define CFG_RXDMAOPT 0x40
-#define CFG_TMOT_SW 0x20
-#define CFG_TMOT_HWLONG 0x10
-#define CFG_TMOT_HW 0x00
-#define CFG_CFPENDOPT 0x08
-#define CFG_BCNSUSEN 0x04
-#define CFG_NOTXTIMEOUT 0x02
-#define CFG_NOBUFOPT 0x01
-
-/* Bits in the TEST register */
-#define TEST_LBEXT 0x80
-#define TEST_LBINT 0x40
-#define TEST_LBNONE 0x00
-#define TEST_SOFTINT 0x20
-#define TEST_CONTTX 0x10
-#define TEST_TXPE 0x08
-#define TEST_NAVDIS 0x04
-#define TEST_NOCTS 0x02
-#define TEST_NOACK 0x01
-
-/* Bits in the HOSTCR register */
-#define HOSTCR_TXONST 0x80
-#define HOSTCR_RXONST 0x40
-#define HOSTCR_ADHOC 0x20 /* Network Type 1 = Ad-hoc */
-#define HOSTCR_AP 0x10 /* Port Type 1 = AP */
-#define HOSTCR_TXON 0x08 /* 0000 1000 */
-#define HOSTCR_RXON 0x04 /* 0000 0100 */
-#define HOSTCR_MACEN 0x02 /* 0000 0010 */
-#define HOSTCR_SOFTRST 0x01 /* 0000 0001 */
-
-/* Bits in the MACCR register */
-#define MACCR_SYNCFLUSHOK 0x04
-#define MACCR_SYNCFLUSH 0x02
-#define MACCR_CLRNAV 0x01
-
-/* Bits in the MAC_REG_GPIOCTL0 register */
-#define LED_ACTSET 0x01
-#define LED_RFOFF 0x02
-#define LED_NOCONNECT 0x04
-
-/* Bits in the RCR register */
-#define RCR_SSID 0x80
-#define RCR_RXALLTYPE 0x40
-#define RCR_UNICAST 0x20
-#define RCR_BROADCAST 0x10
-#define RCR_MULTICAST 0x08
-#define RCR_WPAERR 0x04
-#define RCR_ERRCRC 0x02
-#define RCR_BSSID 0x01
-
-/* Bits in the TCR register */
-#define TCR_SYNCDCFOPT 0x02
-#define TCR_AUTOBCNTX 0x01 /* Beacon automatically transmit enable */
-
-/* Bits in the IMR register */
-#define IMR_MEASURESTART 0x80000000
-#define IMR_QUIETSTART 0x20000000
-#define IMR_RADARDETECT 0x10000000
-#define IMR_MEASUREEND 0x08000000
-#define IMR_SOFTTIMER1 0x00200000
-#define IMR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */
-#define IMR_RXNOBUF 0x00000800
-#define IMR_MIBNEARFULL 0x00000400
-#define IMR_SOFTINT 0x00000200
-#define IMR_FETALERR 0x00000100
-#define IMR_WATCHDOG 0x00000080
-#define IMR_SOFTTIMER 0x00000040
-#define IMR_GPIO 0x00000020
-#define IMR_TBTT 0x00000010
-#define IMR_RXDMA0 0x00000008
-#define IMR_BNTX 0x00000004
-#define IMR_AC0DMA 0x00000002
-#define IMR_TXDMA0 0x00000001
-
-/* Bits in the ISR register */
-#define ISR_MEASURESTART 0x80000000
-#define ISR_QUIETSTART 0x20000000
-#define ISR_RADARDETECT 0x10000000
-#define ISR_MEASUREEND 0x08000000
-#define ISR_SOFTTIMER1 0x00200000
-#define ISR_RXDMA1 0x00001000 /* 0000 0000 0001 0000 0000 0000 */
-#define ISR_RXNOBUF 0x00000800 /* 0000 0000 0000 1000 0000 0000 */
-#define ISR_MIBNEARFULL 0x00000400 /* 0000 0000 0000 0100 0000 0000 */
-#define ISR_SOFTINT 0x00000200
-#define ISR_FETALERR 0x00000100
-#define ISR_WATCHDOG 0x00000080
-#define ISR_SOFTTIMER 0x00000040
-#define ISR_GPIO 0x00000020
-#define ISR_TBTT 0x00000010
-#define ISR_RXDMA0 0x00000008
-#define ISR_BNTX 0x00000004
-#define ISR_AC0DMA 0x00000002
-#define ISR_TXDMA0 0x00000001
-
-/* Bits in the PSCFG register */
-#define PSCFG_PHILIPMD 0x40
-#define PSCFG_WAKECALEN 0x20
-#define PSCFG_WAKETMREN 0x10
-#define PSCFG_BBPSPROG 0x08
-#define PSCFG_WAKESYN 0x04
-#define PSCFG_SLEEPSYN 0x02
-#define PSCFG_AUTOSLEEP 0x01
-
-/* Bits in the PSCTL register */
-#define PSCTL_WAKEDONE 0x20
-#define PSCTL_PS 0x10
-#define PSCTL_GO2DOZE 0x08
-#define PSCTL_LNBCN 0x04
-#define PSCTL_ALBCN 0x02
-#define PSCTL_PSEN 0x01
-
-/* Bits in the PSPWSIG register */
-#define PSSIG_WPE3 0x80
-#define PSSIG_WPE2 0x40
-#define PSSIG_WPE1 0x20
-#define PSSIG_WRADIOPE 0x10
-#define PSSIG_SPE3 0x08
-#define PSSIG_SPE2 0x04
-#define PSSIG_SPE1 0x02
-#define PSSIG_SRADIOPE 0x01
-
-/* Bits in the BBREGCTL register */
-#define BBREGCTL_DONE 0x04
-#define BBREGCTL_REGR 0x02
-#define BBREGCTL_REGW 0x01
-
-/* Bits in the IFREGCTL register */
-#define IFREGCTL_DONE 0x04
-#define IFREGCTL_IFRF 0x02
-#define IFREGCTL_REGW 0x01
-
-/* Bits in the SOFTPWRCTL register */
-#define SOFTPWRCTL_RFLEOPT 0x0800
-#define SOFTPWRCTL_TXPEINV 0x0200
-#define SOFTPWRCTL_SWPECTI 0x0100
-#define SOFTPWRCTL_SWPAPE 0x0020
-#define SOFTPWRCTL_SWCALEN 0x0010
-#define SOFTPWRCTL_SWRADIO_PE 0x0008
-#define SOFTPWRCTL_SWPE2 0x0004
-#define SOFTPWRCTL_SWPE1 0x0002
-#define SOFTPWRCTL_SWPE3 0x0001
-
-/* Bits in the GPIOCTL1 register */
-#define GPIO1_DATA1 0x20
-#define GPIO1_MD1 0x10
-#define GPIO1_DATA0 0x02
-#define GPIO1_MD0 0x01
-
-/* Bits in the DMACTL register */
-#define DMACTL_CLRRUN 0x00080000
-#define DMACTL_RUN 0x00000008
-#define DMACTL_WAKE 0x00000004
-#define DMACTL_DEAD 0x00000002
-#define DMACTL_ACTIVE 0x00000001
-
-/* Bits in the RXDMACTL0 register */
-#define RX_PERPKT 0x00000100
-#define RX_PERPKTCLR 0x01000000
-
-/* Bits in the BCNDMACTL register */
-#define BEACON_READY 0x01
-
-/* Bits in the MISCFFCTL register */
-#define MISCFFCTL_WRITE 0x0001
-
-/* Bits in WAKEUPEN0 */
-#define WAKEUPEN0_DIRPKT 0x10
-#define WAKEUPEN0_LINKOFF 0x08
-#define WAKEUPEN0_ATIMEN 0x04
-#define WAKEUPEN0_TIMEN 0x02
-#define WAKEUPEN0_MAGICEN 0x01
-
-/* Bits in WAKEUPEN1 */
-#define WAKEUPEN1_128_3 0x08
-#define WAKEUPEN1_128_2 0x04
-#define WAKEUPEN1_128_1 0x02
-#define WAKEUPEN1_128_0 0x01
-
-/* Bits in WAKEUPSR0 */
-#define WAKEUPSR0_DIRPKT 0x10
-#define WAKEUPSR0_LINKOFF 0x08
-#define WAKEUPSR0_ATIMEN 0x04
-#define WAKEUPSR0_TIMEN 0x02
-#define WAKEUPSR0_MAGICEN 0x01
-
-/* Bits in WAKEUPSR1 */
-#define WAKEUPSR1_128_3 0x08
-#define WAKEUPSR1_128_2 0x04
-#define WAKEUPSR1_128_1 0x02
-#define WAKEUPSR1_128_0 0x01
-
-/* Bits in the MAC_REG_GPIOCTL register */
-#define GPIO0_MD 0x01
-#define GPIO0_DATA 0x02
-#define GPIO0_INTMD 0x04
-#define GPIO1_MD 0x10
-#define GPIO1_DATA 0x20
-
-/* Bits in the MSRCTL register */
-#define MSRCTL_FINISH 0x80
-#define MSRCTL_READY 0x40
-#define MSRCTL_RADARDETECT 0x20
-#define MSRCTL_EN 0x10
-#define MSRCTL_QUIETTXCHK 0x08
-#define MSRCTL_QUIETRPT 0x04
-#define MSRCTL_QUIETINT 0x02
-#define MSRCTL_QUIETEN 0x01
-
-/* Bits in the MSRCTL1 register */
-#define MSRCTL1_TXPWR 0x08
-#define MSRCTL1_CSAPAREN 0x04
-#define MSRCTL1_TXPAUSE 0x01
-
-/* Loopback mode */
-#define MAC_LB_EXT 0x02
-#define MAC_LB_INTERNAL 0x01
-#define MAC_LB_NONE 0x00
-
-#define DEFAULT_BI 0x200
-
-/* MiscFIFO Offset */
-#define MISCFIFO_KEYETRY0 32
-#define MISCFIFO_KEYENTRYSIZE 22
-#define MISCFIFO_SYNINFO_IDX 10
-#define MISCFIFO_SYNDATA_IDX 11
-#define MISCFIFO_SYNDATASIZE 21
-
-/* enabled mask value of irq */
-#define IMR_MASK_VALUE (IMR_SOFTTIMER1 | \
- IMR_RXDMA1 | \
- IMR_RXNOBUF | \
- IMR_MIBNEARFULL | \
- IMR_SOFTINT | \
- IMR_FETALERR | \
- IMR_WATCHDOG | \
- IMR_SOFTTIMER | \
- IMR_GPIO | \
- IMR_TBTT | \
- IMR_RXDMA0 | \
- IMR_BNTX | \
- IMR_AC0DMA | \
- IMR_TXDMA0)
-
-/* max time out delay time */
-#define W_MAX_TIMEOUT 0xFFF0U
-
-/* wait time within loop */
-#define CB_DELAY_LOOP_WAIT 10 /* 10ms */
-
-/* revision id */
-#define REV_ID_VT3253_A0 0x00
-#define REV_ID_VT3253_A1 0x01
-#define REV_ID_VT3253_B0 0x08
-#define REV_ID_VT3253_B1 0x09
-
-/*--------------------- Export Types ------------------------------*/
-
-/*--------------------- Export Macros ------------------------------*/
-
-#define VT6655_MAC_SELECT_PAGE0(iobase) iowrite8(0, (iobase) + MAC_REG_PAGE1SEL)
-
-#define VT6655_MAC_SELECT_PAGE1(iobase) iowrite8(1, (iobase) + MAC_REG_PAGE1SEL)
-
-#define MAKEWORD(lb, hb) \
- ((unsigned short)(((unsigned char)(lb)) | (((unsigned short)((unsigned char)(hb))) << 8)))
-
-void vt6655_mac_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask);
-void vt6655_mac_word_reg_bits_on(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask);
-void vt6655_mac_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u8 bit_mask);
-void vt6655_mac_word_reg_bits_off(void __iomem *iobase, const u8 reg_offset, const u16 bit_mask);
-
-void vt6655_mac_set_short_retry_limit(struct vnt_private *priv, unsigned char retry_limit);
-
-void MACvSetLongRetryLimit(struct vnt_private *priv, unsigned char byRetryLimit);
-
-bool MACbSoftwareReset(struct vnt_private *priv);
-bool MACbShutdown(struct vnt_private *priv);
-void MACvInitialize(struct vnt_private *priv);
-void vt6655_mac_set_curr_rx_0_desc_addr(struct vnt_private *priv, u32 curr_desc_addr);
-void vt6655_mac_set_curr_rx_1_desc_addr(struct vnt_private *priv, u32 curr_desc_addr);
-void vt6655_mac_set_curr_tx_desc_addr(int tx_type, struct vnt_private *priv, u32 curr_desc_addr);
-void MACvSetCurrSyncDescAddrEx(struct vnt_private *priv,
- u32 curr_desc_addr);
-void MACvSetCurrATIMDescAddrEx(struct vnt_private *priv,
- u32 curr_desc_addr);
-void MACvTimer0MicroSDelay(struct vnt_private *priv, unsigned int uDelay);
-void MACvOneShotTimer1MicroSec(struct vnt_private *priv, unsigned int uDelayTime);
-
-void MACvSetMISCFifo(struct vnt_private *priv, unsigned short wOffset,
- u32 dwData);
-
-bool MACbPSWakeup(struct vnt_private *priv);
-
-void MACvSetKeyEntry(struct vnt_private *priv, unsigned short wKeyCtl,
- unsigned int uEntryIdx, unsigned int uKeyIdx,
- unsigned char *pbyAddr, u32 *pdwKey,
- unsigned char local_id);
-void MACvDisableKeyEntry(struct vnt_private *priv, unsigned int uEntryIdx);
-
-#endif /* __MAC_H__ */
diff --git a/drivers/staging/vt6655/power.c b/drivers/staging/vt6655/power.c
deleted file mode 100644
index 8527ad3eff48..000000000000
--- a/drivers/staging/vt6655/power.c
+++ /dev/null
@@ -1,144 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles 802.11 power management functions
- *
- * Author: Lyndon Chen
- *
- * Date: July 17, 2002
- *
- * Functions:
- * PSvEnablePowerSaving - Enable Power Saving Mode
- * PSvDiasblePowerSaving - Disable Power Saving Mode
- * PSbConsiderPowerDown - Decide if we can Power Down
- * PSvSendPSPOLL - Send PS-POLL packet
- * PSbSendNullPacket - Send Null packet
- * PSbIsNextTBTTWakeUp - Decide if we need to wake up at next Beacon
- *
- * Revision History:
- *
- */
-
-#include "mac.h"
-#include "device.h"
-#include "power.h"
-#include "card.h"
-
-/*--------------------- Static Definitions -------------------------*/
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Functions --------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-/*
- *
- * Routine Description:
- * Enable hw power saving functions
- *
- * Return Value:
- * None.
- *
- */
-
-void PSvEnablePowerSaving(struct vnt_private *priv,
- unsigned short wListenInterval)
-{
- u16 wAID = priv->current_aid | BIT(14) | BIT(15);
-
- /* set period of power up before TBTT */
- iowrite16(C_PWBT, priv->port_offset + MAC_REG_PWBT);
- if (priv->op_mode != NL80211_IFTYPE_ADHOC) {
- /* set AID */
- iowrite16(wAID, priv->port_offset + MAC_REG_AIDATIM);
- }
-
- /* Set AutoSleep */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
-
- /* Set HWUTSF */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
-
- if (wListenInterval >= 2) {
- /* clear always listen beacon */
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN);
- /* first time set listen next beacon */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_LNBCN);
- } else {
- /* always listen beacon */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN);
- }
-
- /* enable power saving hw function */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_PSEN);
- priv->bEnablePSMode = true;
-
- priv->bPWBitOn = true;
- pr_debug("PS:Power Saving Mode Enable...\n");
-}
-
-/*
- *
- * Routine Description:
- * Disable hw power saving functions
- *
- * Return Value:
- * None.
- *
- */
-
-void PSvDisablePowerSaving(struct vnt_private *priv)
-{
- /* disable power saving hw function */
- MACbPSWakeup(priv);
-
- /* clear AutoSleep */
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
-
- /* clear HWUTSF */
- vt6655_mac_reg_bits_off(priv->port_offset, MAC_REG_TFTCTL, TFTCTL_HWUTSF);
-
- /* set always listen beacon */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_ALBCN);
-
- priv->bEnablePSMode = false;
-
- priv->bPWBitOn = false;
-}
-
-/*
- *
- * Routine Description:
- * Check if Next TBTT must wake up
- *
- * Return Value:
- * None.
- *
- */
-
-bool PSbIsNextTBTTWakeUp(struct vnt_private *priv)
-{
- struct ieee80211_hw *hw = priv->hw;
- struct ieee80211_conf *conf = &hw->conf;
- bool wake_up = false;
-
- if (conf->listen_interval > 1) {
- if (!priv->wake_up_count)
- priv->wake_up_count = conf->listen_interval;
-
- --priv->wake_up_count;
-
- if (priv->wake_up_count == 1) {
- /* Turn on wake up to listen next beacon */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_PSCTL, PSCTL_LNBCN);
- wake_up = true;
- }
- }
-
- return wake_up;
-}
diff --git a/drivers/staging/vt6655/power.h b/drivers/staging/vt6655/power.h
deleted file mode 100644
index 060516f81f5b..000000000000
--- a/drivers/staging/vt6655/power.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles 802.11 power management functions
- *
- * Author: Lyndon Chen
- *
- * Date: July 17, 2002
- *
- */
-
-#ifndef __POWER_H__
-#define __POWER_H__
-
-#include "device.h"
-
-#define C_PWBT 1000 /* micro sec. power up before TBTT */
-#define PS_FAST_INTERVAL 1 /* Fast power saving listen interval */
-#define PS_MAX_INTERVAL 4 /* MAX power saving listen interval */
-
-void PSvDisablePowerSaving(struct vnt_private *priv);
-
-void PSvEnablePowerSaving(struct vnt_private *priv, unsigned short wListenInterval);
-
-bool PSbIsNextTBTTWakeUp(struct vnt_private *priv);
-
-#endif /* __POWER_H__ */
diff --git a/drivers/staging/vt6655/rf.c b/drivers/staging/vt6655/rf.c
deleted file mode 100644
index d319ec21c97b..000000000000
--- a/drivers/staging/vt6655/rf.c
+++ /dev/null
@@ -1,535 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: rf function code
- *
- * Author: Jerry Chen
- *
- * Date: Feb. 19, 2004
- *
- * Functions:
- * IFRFbWriteEmbedded - Embedded write RF register via MAC
- *
- * Revision History:
- * RobertYu 2005
- * chester 2008
- *
- */
-
-#include "mac.h"
-#include "srom.h"
-#include "rf.h"
-#include "baseband.h"
-
-#define BY_AL2230_REG_LEN 23 /* 24bit */
-#define CB_AL2230_INIT_SEQ 15
-#define SWITCH_CHANNEL_DELAY_AL2230 200 /* us */
-#define AL2230_PWR_IDX_LEN 64
-
-#define BY_AL7230_REG_LEN 23 /* 24bit */
-#define CB_AL7230_INIT_SEQ 16
-#define SWITCH_CHANNEL_DELAY_AL7230 200 /* us */
-#define AL7230_PWR_IDX_LEN 64
-
-static const unsigned long al2230_init_table[CB_AL2230_INIT_SEQ] = {
- 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x01A00200 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00FFF300 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0F4DC500 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0805B600 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0146C700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00068800 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0403B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00DBBA00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00099B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0BDFFC00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00000D00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x00580F00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW
-};
-
-static const unsigned long al2230_channel_table0[CB_MAX_CHANNEL] = {
- 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
- 0x03F79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
- 0x03E79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
- 0x03E79000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
- 0x03F7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
- 0x03F7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
- 0x03E7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
- 0x03E7A000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */
- 0x03F7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */
- 0x03F7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
- 0x03E7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
- 0x03E7B000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
- 0x03F7C000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
- 0x03E7C000 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */
-};
-
-static const unsigned long al2230_channel_table1[CB_MAX_CHANNEL] = {
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 1, Tf = 2412MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 2, Tf = 2417MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 3, Tf = 2422MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 4, Tf = 2427MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 5, Tf = 2432MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 6, Tf = 2437MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 7, Tf = 2442MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 8, Tf = 2447MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 9, Tf = 2452MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 10, Tf = 2457MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 11, Tf = 2462MHz */
- 0x0B333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 12, Tf = 2467MHz */
- 0x03333100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW, /* channel = 13, Tf = 2472MHz */
- 0x06666100 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW /* channel = 14, Tf = 2412M */
-};
-
-static unsigned long al2230_power_table[AL2230_PWR_IDX_LEN] = {
- 0x04040900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04041900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04042900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04043900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04044900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04045900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04046900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04047900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04048900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04049900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0404F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04050900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04051900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04052900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04053900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04054900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04055900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04056900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04057900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04058900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04059900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0405F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04060900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04061900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04062900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04063900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04064900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04065900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04066900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04067900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04068900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04069900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0406F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04070900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04071900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04072900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04073900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04074900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04075900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04076900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04077900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04078900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x04079900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407A900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407B900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407C900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407D900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407E900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW,
- 0x0407F900 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW
-};
-
-/*
- * Description: Write to IF/RF, by embedded programming
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * dwData - data to write
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData)
-{
- void __iomem *iobase = priv->port_offset;
- unsigned short ww;
- unsigned long dwValue;
-
- iowrite32((u32)dwData, iobase + MAC_REG_IFREGCTL);
-
- /* W_MAX_TIMEOUT is the timeout period */
- for (ww = 0; ww < W_MAX_TIMEOUT; ww++) {
- dwValue = ioread32(iobase + MAC_REG_IFREGCTL);
- if (dwValue & IFREGCTL_DONE)
- break;
- }
-
- if (ww == W_MAX_TIMEOUT)
- return false;
-
- return true;
-}
-
-/*
- * Description: AIROHA IFRF chip init function
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-static bool RFbAL2230Init(struct vnt_private *priv)
-{
- void __iomem *iobase = priv->port_offset;
- int ii;
- bool ret;
-
- ret = true;
-
- /* 3-wire control for normal mode */
- iowrite8(0, iobase + MAC_REG_SOFTPWRCTL);
-
- vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL,
- (SOFTPWRCTL_SWPECTI | SOFTPWRCTL_TXPEINV));
- /* PLL Off */
- vt6655_mac_word_reg_bits_off(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
-
- /* patch abnormal AL2230 frequency output */
- IFRFbWriteEmbedded(priv, (0x07168700 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW));
-
- for (ii = 0; ii < CB_AL2230_INIT_SEQ; ii++)
- ret &= IFRFbWriteEmbedded(priv, al2230_init_table[ii]);
- MACvTimer0MicroSDelay(priv, 30); /* delay 30 us */
-
- /* PLL On */
- vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, SOFTPWRCTL_SWPE3);
-
- MACvTimer0MicroSDelay(priv, 150);/* 150us */
- ret &= IFRFbWriteEmbedded(priv, (0x00d80f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW));
- MACvTimer0MicroSDelay(priv, 30);/* 30us */
- ret &= IFRFbWriteEmbedded(priv, (0x00780f00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW));
- MACvTimer0MicroSDelay(priv, 30);/* 30us */
- ret &= IFRFbWriteEmbedded(priv,
- al2230_init_table[CB_AL2230_INIT_SEQ - 1]);
-
- vt6655_mac_word_reg_bits_on(iobase, MAC_REG_SOFTPWRCTL, (SOFTPWRCTL_SWPE3 |
- SOFTPWRCTL_SWPE2 |
- SOFTPWRCTL_SWPECTI |
- SOFTPWRCTL_TXPEINV));
-
- /* 3-wire control for power saving mode */
- iowrite8(PSSIG_WPE3 | PSSIG_WPE2, iobase + MAC_REG_PSPWRSIG);
-
- return ret;
-}
-
-static bool RFbAL2230SelectChannel(struct vnt_private *priv, unsigned char byChannel)
-{
- void __iomem *iobase = priv->port_offset;
- bool ret;
-
- ret = true;
-
- ret &= IFRFbWriteEmbedded(priv, al2230_channel_table0[byChannel - 1]);
- ret &= IFRFbWriteEmbedded(priv, al2230_channel_table1[byChannel - 1]);
-
- /* Set Channel[7] = 0 to tell H/W channel is changing now. */
- iowrite8(byChannel & 0x7F, iobase + MAC_REG_CHANNEL);
- MACvTimer0MicroSDelay(priv, SWITCH_CHANNEL_DELAY_AL2230);
- /* Set Channel[7] = 1 to tell H/W channel change is done. */
- iowrite8(byChannel | 0x80, iobase + MAC_REG_CHANNEL);
-
- return ret;
-}
-
-/*
- * Description: RF init function
- *
- * Parameters:
- * In:
- * byBBType
- * rf_type
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool RFbInit(struct vnt_private *priv)
-{
- bool ret = true;
-
- switch (priv->rf_type) {
- case RF_AIROHA:
- case RF_AL2230S:
- priv->max_pwr_level = AL2230_PWR_IDX_LEN;
- ret = RFbAL2230Init(priv);
- break;
- case RF_NOTHING:
- ret = true;
- break;
- default:
- ret = false;
- break;
- }
- return ret;
-}
-
-/*
- * Description: Select channel
- *
- * Parameters:
- * In:
- * rf_type
- * byChannel - Channel number
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool RFbSelectChannel(struct vnt_private *priv, unsigned char rf_type,
- u16 byChannel)
-{
- bool ret = true;
-
- switch (rf_type) {
- case RF_AIROHA:
- case RF_AL2230S:
- ret = RFbAL2230SelectChannel(priv, byChannel);
- break;
- /*{{ RobertYu: 20050104 */
- case RF_NOTHING:
- ret = true;
- break;
- default:
- ret = false;
- break;
- }
- return ret;
-}
-
-/*
- * Description: Write WakeProgSyn
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * rf_type - RF type
- * channel - Channel number
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool rf_write_wake_prog_syn(struct vnt_private *priv, unsigned char rf_type,
- u16 channel)
-{
- void __iomem *iobase = priv->port_offset;
- int i;
- unsigned char init_count = 0;
- unsigned char sleep_count = 0;
- unsigned short idx = MISCFIFO_SYNDATA_IDX;
-
- iowrite16(0, iobase + MAC_REG_MISCFFNDEX);
- switch (rf_type) {
- case RF_AIROHA:
- case RF_AL2230S:
-
- if (channel > CB_MAX_CHANNEL_24G)
- return false;
-
- /* Init Reg + Channel Reg (2) */
- init_count = CB_AL2230_INIT_SEQ + 2;
- sleep_count = 0;
-
- for (i = 0; i < CB_AL2230_INIT_SEQ; i++)
- MACvSetMISCFifo(priv, idx++, al2230_init_table[i]);
-
- MACvSetMISCFifo(priv, idx++, al2230_channel_table0[channel - 1]);
- MACvSetMISCFifo(priv, idx++, al2230_channel_table1[channel - 1]);
- break;
-
- /* Need to check, PLLON need to be low for channel setting */
-
- case RF_NOTHING:
- return true;
-
- default:
- return false;
- }
-
- MACvSetMISCFifo(priv, MISCFIFO_SYNINFO_IDX, (unsigned long)MAKEWORD(sleep_count, init_count));
-
- return true;
-}
-
-/*
- * Description: Set Tx power
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * dwRFPowerTable - RF Tx Power Setting
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH)
-{
- bool ret;
- unsigned char byPwr = 0;
- unsigned char byDec = 0;
-
- if (priv->dwDiagRefCount != 0)
- return true;
-
- if ((uCH < 1) || (uCH > CB_MAX_CHANNEL))
- return false;
-
- switch (rate) {
- case RATE_1M:
- case RATE_2M:
- case RATE_5M:
- case RATE_11M:
- if (uCH > CB_MAX_CHANNEL_24G)
- return false;
-
- byPwr = priv->abyCCKPwrTbl[uCH];
- break;
- case RATE_6M:
- case RATE_9M:
- case RATE_12M:
- case RATE_18M:
- byPwr = priv->abyOFDMPwrTbl[uCH];
- byDec = byPwr + 10;
-
- if (byDec >= priv->max_pwr_level)
- byDec = priv->max_pwr_level - 1;
-
- byPwr = byDec;
- break;
- case RATE_24M:
- case RATE_36M:
- case RATE_48M:
- case RATE_54M:
- byPwr = priv->abyOFDMPwrTbl[uCH];
- break;
- }
-
- if (priv->cur_pwr == byPwr)
- return true;
-
- ret = RFbRawSetPower(priv, byPwr, rate);
- if (ret)
- priv->cur_pwr = byPwr;
-
- return ret;
-}
-
-/*
- * Description: Set Tx power
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * dwRFPowerTable - RF Tx Power Setting
- * Out:
- * none
- *
- * Return Value: true if succeeded; false if failed.
- *
- */
-
-bool RFbRawSetPower(struct vnt_private *priv, unsigned char byPwr,
- unsigned int rate)
-{
- bool ret = true;
-
- if (byPwr >= priv->max_pwr_level)
- return false;
-
- switch (priv->rf_type) {
- case RF_AIROHA:
- ret &= IFRFbWriteEmbedded(priv, al2230_power_table[byPwr]);
- if (rate <= RATE_11M)
- ret &= IFRFbWriteEmbedded(priv, 0x0001B400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
- else
- ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
-
- break;
-
- case RF_AL2230S:
- ret &= IFRFbWriteEmbedded(priv, al2230_power_table[byPwr]);
- if (rate <= RATE_11M) {
- ret &= IFRFbWriteEmbedded(priv, 0x040C1400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
- ret &= IFRFbWriteEmbedded(priv, 0x00299B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
- } else {
- ret &= IFRFbWriteEmbedded(priv, 0x0005A400 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
- ret &= IFRFbWriteEmbedded(priv, 0x00099B00 + (BY_AL2230_REG_LEN << 3) + IFREGCTL_REGW);
- }
-
- break;
-
- default:
- break;
- }
- return ret;
-}
-
-/*
- *
- * Routine Description:
- * Translate RSSI to dBm
- *
- * Parameters:
- * In:
- * priv - The adapter to be translated
- * byCurrRSSI - RSSI to be translated
- * Out:
- * pdwdbm - Translated dbm number
- *
- * Return Value: none
- *
- */
-void
-RFvRSSITodBm(struct vnt_private *priv, unsigned char byCurrRSSI, long *pldBm)
-{
- unsigned char byIdx = (((byCurrRSSI & 0xC0) >> 6) & 0x03);
- long b = (byCurrRSSI & 0x3F);
- long a = 0;
- unsigned char abyAIROHARF[4] = {0, 18, 0, 40};
-
- switch (priv->rf_type) {
- case RF_AIROHA:
- case RF_AL2230S:
- a = abyAIROHARF[byIdx];
- break;
- default:
- break;
- }
-
- *pldBm = -1 * (a + b * 2);
-}
-
diff --git a/drivers/staging/vt6655/rf.h b/drivers/staging/vt6655/rf.h
deleted file mode 100644
index 8eef100c7ef2..000000000000
--- a/drivers/staging/vt6655/rf.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Jerry Chen
- *
- * Date: Feb. 19, 2004
- *
- */
-
-#ifndef __RF_H__
-#define __RF_H__
-
-#include "device.h"
-
-/*--------------------- Export Definitions -------------------------*/
-/*
- * Baseband RF pair definition in eeprom (Bits 6..0)
- */
-#define RF_RFMD2959 0x01
-#define RF_MAXIMAG 0x02
-#define RF_AIROHA 0x03
-
-#define RF_UW2451 0x05
-#define RF_MAXIMG 0x06
-#define RF_MAXIM2829 0x07 /* RobertYu: 20041118 */
-#define RF_UW2452 0x08 /* RobertYu: 20041210 */
-#define RF_AIROHA7230 0x0a /* RobertYu: 20050104 */
-#define RF_UW2453 0x0b
-
-#define RF_VT3226 0x09
-#define RF_AL2230S 0x0e
-
-#define RF_NOTHING 0x7E
-#define RF_EMU 0x80
-#define RF_MASK 0x7F
-
-#define ZONE_FCC 0
-#define ZONE_MKK1 1
-#define ZONE_ETSI 2
-#define ZONE_IC 3
-#define ZONE_SPAIN 4
-#define ZONE_FRANCE 5
-#define ZONE_MKK 6
-#define ZONE_ISRAEL 7
-
-/* [20050104] CB_MAXIM2829_CHANNEL_5G_HIGH, CB_UW2452_CHANNEL_5G_HIGH: 40==>41 */
-#define CB_MAXIM2829_CHANNEL_5G_HIGH 41 /* Index41: channel = 100, Tf = 5500MHz, set the (A3:A0=0101) D6=1 */
-#define CB_UW2452_CHANNEL_5G_HIGH 41 /* [20041210] Index41: channel = 100, Tf = 5500MHz, change VCO2->VCO3 */
-
-/*--------------------- Export Classes ----------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-bool IFRFbWriteEmbedded(struct vnt_private *priv, unsigned long dwData);
-bool RFbSelectChannel(struct vnt_private *priv, unsigned char rf_type, u16 byChannel);
-bool RFbInit(struct vnt_private *priv);
-bool rf_write_wake_prog_syn(struct vnt_private *priv, unsigned char rf_type, u16 channel);
-bool RFbSetPower(struct vnt_private *priv, unsigned int rate, u16 uCH);
-bool RFbRawSetPower(struct vnt_private *priv, unsigned char byPwr,
- unsigned int rate);
-
-void RFvRSSITodBm(struct vnt_private *priv, unsigned char byCurrRSSI,
- long *pldBm);
-
-#endif /* __RF_H__ */
diff --git a/drivers/staging/vt6655/rxtx.c b/drivers/staging/vt6655/rxtx.c
deleted file mode 100644
index 3705cb1e87b6..000000000000
--- a/drivers/staging/vt6655/rxtx.c
+++ /dev/null
@@ -1,1462 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: handle WMAC/802.3/802.11 rx & tx functions
- *
- * Author: Lyndon Chen
- *
- * Date: May 20, 2003
- *
- * Functions:
- * s_vGenerateTxParameter - Generate tx dma required parameter.
- * vGenerateMACHeader - Translate 802.3 to 802.11 header
- * cbGetFragCount - Calculate fragment number count
- * csBeacon_xmit - beacon tx function
- * csMgmt_xmit - management tx function
- * s_cbFillTxBufHead - fulfill tx dma buffer header
- * s_uGetDataDuration - get tx data required duration
- * s_uFillDataHead- fulfill tx data duration header
- * s_uGetRTSCTSDuration- get rtx/cts required duration
- * get_rtscts_time- get rts/cts reserved time
- * s_uGetTxRsvTime- get frame reserved time
- * s_vFillCTSHead- fulfill CTS ctl header
- * s_vFillFragParameter- Set fragment ctl parameter.
- * s_vFillRTSHead- fulfill RTS ctl header
- * s_vFillTxKey- fulfill tx encrypt key
- * s_vSWencryption- Software encrypt header
- * vDMA0_tx_80211- tx 802.11 frame via dma0
- * vGenerateFIFOHeader- Generate tx FIFO ctl header
- *
- * Revision History:
- *
- */
-
-#include "device.h"
-#include "rxtx.h"
-#include "card.h"
-#include "mac.h"
-#include "baseband.h"
-#include "rf.h"
-
-/*--------------------- Static Definitions -------------------------*/
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Variables --------------------------*/
-
-/*--------------------- Static Functions --------------------------*/
-
-/*--------------------- Static Definitions -------------------------*/
-/* if packet size < 256 -> in-direct send
- * vpacket size >= 256 -> direct send
- */
-#define CRITICAL_PACKET_LEN 256
-
-static const unsigned short time_stamp_off[2][MAX_RATE] = {
- {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23}, /* Long Preamble */
- {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23}, /* Short Preamble */
-};
-
-static const unsigned short fb_opt0[2][5] = {
- {RATE_12M, RATE_18M, RATE_24M, RATE_36M, RATE_48M}, /* fallback_rate0 */
- {RATE_12M, RATE_12M, RATE_18M, RATE_24M, RATE_36M}, /* fallback_rate1 */
-};
-
-static const unsigned short fb_opt1[2][5] = {
- {RATE_12M, RATE_18M, RATE_24M, RATE_24M, RATE_36M}, /* fallback_rate0 */
- {RATE_6M, RATE_6M, RATE_12M, RATE_12M, RATE_18M}, /* fallback_rate1 */
-};
-
-#define RTSDUR_BB 0
-#define RTSDUR_BA 1
-#define RTSDUR_AA 2
-#define CTSDUR_BA 3
-#define RTSDUR_BA_F0 4
-#define RTSDUR_AA_F0 5
-#define RTSDUR_BA_F1 6
-#define RTSDUR_AA_F1 7
-#define CTSDUR_BA_F0 8
-#define CTSDUR_BA_F1 9
-#define DATADUR_B 10
-#define DATADUR_A 11
-#define DATADUR_A_F0 12
-#define DATADUR_A_F1 13
-
-/*--------------------- Static Functions --------------------------*/
-static
-void
-s_vFillRTSHead(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- void *pvRTS,
- unsigned int cbFrameLength,
- bool bNeedAck,
- bool bDisCRC,
- struct ieee80211_hdr *hdr,
- unsigned short wCurrentRate,
- unsigned char byFBOption
-);
-
-static
-void
-s_vGenerateTxParameter(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- struct vnt_tx_fifo_head *,
- void *pvRrvTime,
- void *pvRTS,
- void *pvCTS,
- unsigned int cbFrameSize,
- bool bNeedACK,
- unsigned int uDMAIdx,
- void *psEthHeader,
- unsigned short wCurrentRate
-);
-
-static unsigned int
-s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
- unsigned char *pbyTxBufferAddr,
- unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD,
- unsigned int uNodeIndex);
-
-static
-__le16
-s_uFillDataHead(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- void *pTxDataHead,
- unsigned int cbFrameLength,
- unsigned int uDMAIdx,
- bool bNeedAck,
- unsigned int uFragIdx,
- unsigned int cbLastFragmentSize,
- unsigned int uMACfragNum,
- unsigned char byFBOption,
- unsigned short wCurrentRate,
- bool is_pspoll
-);
-
-/*--------------------- Export Variables --------------------------*/
-
-static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate)
-{
- return cpu_to_le16(time_stamp_off[priv->preamble_type % 2]
- [rate % MAX_RATE]);
-}
-
-/* byPktType : PK_TYPE_11A 0
- * PK_TYPE_11B 1
- * PK_TYPE_11GB 2
- * PK_TYPE_11GA 3
- */
-static
-unsigned int
-s_uGetTxRsvTime(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- unsigned int cbFrameLength,
- unsigned short wRate,
- bool bNeedAck
-)
-{
- unsigned int uDataTime, uAckTime;
-
- uDataTime = bb_get_frame_time(pDevice->preamble_type, byPktType, cbFrameLength, wRate);
-
- if (!bNeedAck)
- return uDataTime;
-
- /*
- * CCK mode - 11b
- * OFDM mode - 11g 2.4G & 11a 5G
- */
- uAckTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14,
- byPktType == PK_TYPE_11B ?
- pDevice->byTopCCKBasicRate :
- pDevice->byTopOFDMBasicRate);
-
- return uDataTime + pDevice->uSIFS + uAckTime;
-}
-
-static __le16 vnt_rxtx_rsvtime_le16(struct vnt_private *priv, u8 pkt_type,
- u32 frame_length, u16 rate, bool need_ack)
-{
- return cpu_to_le16((u16)s_uGetTxRsvTime(priv, pkt_type,
- frame_length, rate, need_ack));
-}
-
-/* byFreqType: 0=>5GHZ 1=>2.4GHZ */
-static __le16 get_rtscts_time(struct vnt_private *priv,
- unsigned char rts_rsvtype,
- unsigned char pkt_type,
- unsigned int frame_length,
- unsigned short current_rate)
-{
- unsigned int rrv_time = 0;
- unsigned int rts_time = 0;
- unsigned int cts_time = 0;
- unsigned int ack_time = 0;
- unsigned int data_time = 0;
-
- data_time = bb_get_frame_time(priv->preamble_type, pkt_type, frame_length, current_rate);
- if (rts_rsvtype == 0) { /* RTSTxRrvTime_bb */
- rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopCCKBasicRate);
- ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate);
- cts_time = ack_time;
- } else if (rts_rsvtype == 1) { /* RTSTxRrvTime_ba, only in 2.4GHZ */
- rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopCCKBasicRate);
- cts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate);
- ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate);
- } else if (rts_rsvtype == 2) { /* RTSTxRrvTime_aa */
- rts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 20, priv->byTopOFDMBasicRate);
- ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate);
- cts_time = ack_time;
- } else if (rts_rsvtype == 3) { /* CTSTxRrvTime_ba, only in 2.4GHZ */
- cts_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopCCKBasicRate);
- ack_time = bb_get_frame_time(priv->preamble_type, pkt_type, 14, priv->byTopOFDMBasicRate);
- rrv_time = cts_time + ack_time + data_time + 2 * priv->uSIFS;
- return cpu_to_le16((u16)rrv_time);
- }
-
- /* RTSRrvTime */
- rrv_time = rts_time + cts_time + ack_time + data_time + 3 * priv->uSIFS;
- return cpu_to_le16((u16)rrv_time);
-}
-
-/* byFreqType 0: 5GHz, 1:2.4Ghz */
-static
-unsigned int
-s_uGetDataDuration(
- struct vnt_private *pDevice,
- unsigned char byDurType,
- unsigned int cbFrameLength,
- unsigned char byPktType,
- unsigned short wRate,
- bool bNeedAck,
- unsigned int uFragIdx,
- unsigned int cbLastFragmentSize,
- unsigned int uMACfragNum,
- unsigned char byFBOption
-)
-{
- bool bLastFrag = false;
- unsigned int uAckTime = 0, uNextPktTime = 0, len;
-
- if (uFragIdx == (uMACfragNum - 1))
- bLastFrag = true;
-
- if (uFragIdx == (uMACfragNum - 2))
- len = cbLastFragmentSize;
- else
- len = cbFrameLength;
-
- switch (byDurType) {
- case DATADUR_B: /* DATADUR_B */
- if (bNeedAck) {
- uAckTime = bb_get_frame_time(pDevice->preamble_type,
- byPktType, 14,
- pDevice->byTopCCKBasicRate);
- }
- /* Non Frag or Last Frag */
- if ((uMACfragNum == 1) || bLastFrag) {
- if (!bNeedAck)
- return 0;
- } else {
- /* First Frag or Mid Frag */
- uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType,
- len, wRate, bNeedAck);
- }
-
- return pDevice->uSIFS + uAckTime + uNextPktTime;
-
- case DATADUR_A: /* DATADUR_A */
- if (bNeedAck) {
- uAckTime = bb_get_frame_time(pDevice->preamble_type,
- byPktType, 14,
- pDevice->byTopOFDMBasicRate);
- }
- /* Non Frag or Last Frag */
- if ((uMACfragNum == 1) || bLastFrag) {
- if (!bNeedAck)
- return 0;
- } else {
- /* First Frag or Mid Frag */
- uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType,
- len, wRate, bNeedAck);
- }
-
- return pDevice->uSIFS + uAckTime + uNextPktTime;
-
- case DATADUR_A_F0: /* DATADUR_A_F0 */
- case DATADUR_A_F1: /* DATADUR_A_F1 */
- if (bNeedAck) {
- uAckTime = bb_get_frame_time(pDevice->preamble_type,
- byPktType, 14,
- pDevice->byTopOFDMBasicRate);
- }
- /* Non Frag or Last Frag */
- if ((uMACfragNum == 1) || bLastFrag) {
- if (!bNeedAck)
- return 0;
- } else {
- /* First Frag or Mid Frag */
- if (wRate < RATE_18M)
- wRate = RATE_18M;
- else if (wRate > RATE_54M)
- wRate = RATE_54M;
-
- wRate -= RATE_18M;
-
- if (byFBOption == AUTO_FB_0)
- wRate = fb_opt0[FB_RATE0][wRate];
- else
- wRate = fb_opt1[FB_RATE0][wRate];
-
- uNextPktTime = s_uGetTxRsvTime(pDevice, byPktType,
- len, wRate, bNeedAck);
- }
-
- return pDevice->uSIFS + uAckTime + uNextPktTime;
-
- default:
- break;
- }
-
- return 0;
-}
-
-/* byFreqType: 0=>5GHZ 1=>2.4GHZ */
-static
-__le16
-s_uGetRTSCTSDuration(
- struct vnt_private *pDevice,
- unsigned char byDurType,
- unsigned int cbFrameLength,
- unsigned char byPktType,
- unsigned short wRate,
- bool bNeedAck,
- unsigned char byFBOption
-)
-{
- unsigned int uCTSTime = 0, uDurTime = 0;
-
- switch (byDurType) {
- case RTSDUR_BB: /* RTSDuration_bb */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate);
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
- break;
-
- case RTSDUR_BA: /* RTSDuration_ba */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate);
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
- break;
-
- case RTSDUR_AA: /* RTSDuration_aa */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate);
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
- break;
-
- case CTSDUR_BA: /* CTSDuration_ba */
- uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, wRate, bNeedAck);
- break;
-
- case RTSDUR_BA_F0: /* RTSDuration_ba_f0 */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate);
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE0][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE0][wRate - RATE_18M], bNeedAck);
-
- break;
-
- case RTSDUR_AA_F0: /* RTSDuration_aa_f0 */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate);
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE0][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE0][wRate - RATE_18M], bNeedAck);
-
- break;
-
- case RTSDUR_BA_F1: /* RTSDuration_ba_f1 */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopCCKBasicRate);
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE1][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE1][wRate - RATE_18M], bNeedAck);
-
- break;
-
- case RTSDUR_AA_F1: /* RTSDuration_aa_f1 */
- uCTSTime = bb_get_frame_time(pDevice->preamble_type, byPktType, 14, pDevice->byTopOFDMBasicRate);
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE1][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = uCTSTime + 2 * pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE1][wRate - RATE_18M], bNeedAck);
-
- break;
-
- case CTSDUR_BA_F0: /* CTSDuration_ba_f0 */
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE0][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE0][wRate - RATE_18M], bNeedAck);
-
- break;
-
- case CTSDUR_BA_F1: /* CTSDuration_ba_f1 */
- if ((byFBOption == AUTO_FB_0) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt0[FB_RATE1][wRate - RATE_18M], bNeedAck);
- else if ((byFBOption == AUTO_FB_1) && (wRate >= RATE_18M) && (wRate <= RATE_54M))
- uDurTime = pDevice->uSIFS + s_uGetTxRsvTime(pDevice, byPktType, cbFrameLength, fb_opt1[FB_RATE1][wRate - RATE_18M], bNeedAck);
-
- break;
-
- default:
- break;
- }
-
- return cpu_to_le16((u16)uDurTime);
-}
-
-static
-__le16
-s_uFillDataHead(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- void *pTxDataHead,
- unsigned int cbFrameLength,
- unsigned int uDMAIdx,
- bool bNeedAck,
- unsigned int uFragIdx,
- unsigned int cbLastFragmentSize,
- unsigned int uMACfragNum,
- unsigned char byFBOption,
- unsigned short wCurrentRate,
- bool is_pspoll
-)
-{
- struct vnt_tx_datahead_ab *buf = pTxDataHead;
-
- if (!pTxDataHead)
- return 0;
-
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- /* Auto Fallback */
- struct vnt_tx_datahead_g_fb *buf = pTxDataHead;
-
- if (byFBOption == AUTO_FB_NONE) {
- struct vnt_tx_datahead_g *buf = pTxDataHead;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &buf->a);
-
- vnt_get_phy_field(pDevice, cbFrameLength,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
-
- if (is_pspoll) {
- __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15));
-
- buf->duration_a = dur;
- buf->duration_b = dur;
- } else {
- /* Get Duration and TimeStamp */
- buf->duration_a =
- cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength,
- byPktType, wCurrentRate, bNeedAck, uFragIdx,
- cbLastFragmentSize, uMACfragNum,
- byFBOption));
- buf->duration_b =
- cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength,
- PK_TYPE_11B, pDevice->byTopCCKBasicRate,
- bNeedAck, uFragIdx, cbLastFragmentSize,
- uMACfragNum, byFBOption));
- }
-
- buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate);
- buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate);
-
- return buf->duration_a;
- }
-
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &buf->a);
-
- vnt_get_phy_field(pDevice, cbFrameLength,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
- /* Get Duration and TimeStamp */
- buf->duration_a = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->duration_b = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, PK_TYPE_11B,
- pDevice->byTopCCKBasicRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->duration_a_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->duration_a_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
-
- buf->time_stamp_off_a = vnt_time_stamp_off(pDevice, wCurrentRate);
- buf->time_stamp_off_b = vnt_time_stamp_off(pDevice, pDevice->byTopCCKBasicRate);
-
- return buf->duration_a;
- /* if (byFBOption == AUTO_FB_NONE) */
- } else if (byPktType == PK_TYPE_11A) {
- struct vnt_tx_datahead_ab *buf = pTxDataHead;
-
- if (byFBOption != AUTO_FB_NONE) {
- /* Auto Fallback */
- struct vnt_tx_datahead_a_fb *buf = pTxDataHead;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &buf->a);
-
- /* Get Duration and TimeStampOff */
- buf->duration = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->duration_f0 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F0, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->duration_f1 = cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A_F1, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx, cbLastFragmentSize, uMACfragNum, byFBOption));
- buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
- return buf->duration;
- }
-
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &buf->ab);
-
- if (is_pspoll) {
- __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15));
-
- buf->duration = dur;
- } else {
- /* Get Duration and TimeStampOff */
- buf->duration =
- cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_A, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx,
- cbLastFragmentSize, uMACfragNum,
- byFBOption));
- }
-
- buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
- return buf->duration;
- }
-
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, cbFrameLength, wCurrentRate,
- byPktType, &buf->ab);
-
- if (is_pspoll) {
- __le16 dur = cpu_to_le16(pDevice->current_aid | BIT(14) | BIT(15));
-
- buf->duration = dur;
- } else {
- /* Get Duration and TimeStampOff */
- buf->duration =
- cpu_to_le16((u16)s_uGetDataDuration(pDevice, DATADUR_B, cbFrameLength, byPktType,
- wCurrentRate, bNeedAck, uFragIdx,
- cbLastFragmentSize, uMACfragNum,
- byFBOption));
- }
-
- buf->time_stamp_off = vnt_time_stamp_off(pDevice, wCurrentRate);
- return buf->duration;
-}
-
-static
-void
-s_vFillRTSHead(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- void *pvRTS,
- unsigned int cbFrameLength,
- bool bNeedAck,
- bool bDisCRC,
- struct ieee80211_hdr *hdr,
- unsigned short wCurrentRate,
- unsigned char byFBOption
-)
-{
- unsigned int uRTSFrameLen = 20;
-
- if (!pvRTS)
- return;
-
- if (bDisCRC) {
- /* When CRCDIS bit is on, H/W forgot to generate FCS for
- * RTS frame, in this case we need to decrease its length by 4.
- */
- uRTSFrameLen -= 4;
- }
-
- /* Note: So far RTSHead doesn't appear in ATIM & Beacom DMA,
- * so we don't need to take them into account.
- * Otherwise, we need to modify codes for them.
- */
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- if (byFBOption == AUTO_FB_NONE) {
- struct vnt_rts_g *buf = pvRTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
-
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopOFDMBasicRate,
- byPktType, &buf->a);
- /* Get Duration */
- buf->duration_bb =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
- cbFrameLength, PK_TYPE_11B,
- pDevice->byTopCCKBasicRate,
- bNeedAck, byFBOption);
- buf->duration_aa =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->duration_ba =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
-
- buf->data.duration = buf->duration_aa;
- /* Get RTS Frame body */
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_RTS);
-
- ether_addr_copy(buf->data.ra, hdr->addr1);
- ether_addr_copy(buf->data.ta, hdr->addr2);
- } else {
- struct vnt_rts_g_fb *buf = pvRTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
-
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopOFDMBasicRate,
- byPktType, &buf->a);
- /* Get Duration */
- buf->duration_bb =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BB,
- cbFrameLength, PK_TYPE_11B,
- pDevice->byTopCCKBasicRate,
- bNeedAck, byFBOption);
- buf->duration_aa =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->duration_ba =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_ba_f0 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F0,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_aa_f0 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_ba_f1 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BA_F1,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_aa_f1 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->data.duration = buf->duration_aa;
- /* Get RTS Frame body */
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_RTS);
-
- ether_addr_copy(buf->data.ra, hdr->addr1);
- ether_addr_copy(buf->data.ta, hdr->addr2);
- } /* if (byFBOption == AUTO_FB_NONE) */
- } else if (byPktType == PK_TYPE_11A) {
- if (byFBOption == AUTO_FB_NONE) {
- struct vnt_rts_ab *buf = pvRTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopOFDMBasicRate,
- byPktType, &buf->ab);
- /* Get Duration */
- buf->duration =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->data.duration = buf->duration;
- /* Get RTS Frame body */
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_RTS);
-
- ether_addr_copy(buf->data.ra, hdr->addr1);
- ether_addr_copy(buf->data.ta, hdr->addr2);
- } else {
- struct vnt_rts_a_fb *buf = pvRTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopOFDMBasicRate,
- byPktType, &buf->a);
- /* Get Duration */
- buf->duration =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_f0 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F0,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->rts_duration_f1 =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_AA_F1,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
- buf->data.duration = buf->duration;
- /* Get RTS Frame body */
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_RTS);
-
- ether_addr_copy(buf->data.ra, hdr->addr1);
- ether_addr_copy(buf->data.ta, hdr->addr2);
- }
- } else if (byPktType == PK_TYPE_11B) {
- struct vnt_rts_ab *buf = pvRTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uRTSFrameLen,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->ab);
- /* Get Duration */
- buf->duration =
- s_uGetRTSCTSDuration(pDevice, RTSDUR_BB, cbFrameLength,
- byPktType, wCurrentRate, bNeedAck,
- byFBOption);
-
- buf->data.duration = buf->duration;
- /* Get RTS Frame body */
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
-
- ether_addr_copy(buf->data.ra, hdr->addr1);
- ether_addr_copy(buf->data.ta, hdr->addr2);
- }
-}
-
-static
-void
-s_vFillCTSHead(
- struct vnt_private *pDevice,
- unsigned int uDMAIdx,
- unsigned char byPktType,
- void *pvCTS,
- unsigned int cbFrameLength,
- bool bNeedAck,
- bool bDisCRC,
- unsigned short wCurrentRate,
- unsigned char byFBOption
-)
-{
- unsigned int uCTSFrameLen = 14;
-
- if (!pvCTS)
- return;
-
- if (bDisCRC) {
- /* When CRCDIS bit is on, H/W forgot to generate FCS for
- * CTS frame, in this case we need to decrease its length by 4.
- */
- uCTSFrameLen -= 4;
- }
-
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) {
- /* Auto Fall back */
- struct vnt_cts_fb *buf = pvCTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uCTSFrameLen,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
-
- buf->duration_ba =
- s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
-
- /* Get CTSDuration_ba_f0 */
- buf->cts_duration_ba_f0 =
- s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F0,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
-
- /* Get CTSDuration_ba_f1 */
- buf->cts_duration_ba_f1 =
- s_uGetRTSCTSDuration(pDevice, CTSDUR_BA_F1,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
-
- /* Get CTS Frame body */
- buf->data.duration = buf->duration_ba;
-
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_CTS);
-
- buf->reserved2 = 0x0;
-
- ether_addr_copy(buf->data.ra,
- pDevice->abyCurrentNetAddr);
- } else { /* if (byFBOption != AUTO_FB_NONE && uDMAIdx != TYPE_ATIMDMA && uDMAIdx != TYPE_BEACONDMA) */
- struct vnt_cts *buf = pvCTS;
- /* Get SignalField, ServiceField & Length */
- vnt_get_phy_field(pDevice, uCTSFrameLen,
- pDevice->byTopCCKBasicRate,
- PK_TYPE_11B, &buf->b);
-
- /* Get CTSDuration_ba */
- buf->duration_ba =
- s_uGetRTSCTSDuration(pDevice, CTSDUR_BA,
- cbFrameLength, byPktType,
- wCurrentRate, bNeedAck,
- byFBOption);
-
- /* Get CTS Frame body */
- buf->data.duration = buf->duration_ba;
-
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL |
- IEEE80211_STYPE_CTS);
-
- buf->reserved2 = 0x0;
- ether_addr_copy(buf->data.ra,
- pDevice->abyCurrentNetAddr);
- }
- }
-}
-
-/*
- *
- * Description:
- * Generate FIFO control for MAC & Baseband controller
- *
- * Parameters:
- * In:
- * pDevice - Pointer to adapter
- * pTxDataHead - Transmit Data Buffer
- * pTxBufHead - pTxBufHead
- * pvRrvTime - pvRrvTime
- * pvRTS - RTS Buffer
- * pCTS - CTS Buffer
- * cbFrameSize - Transmit Data Length (Hdr+Payload+FCS)
- * bNeedACK - If need ACK
- * uDescIdx - Desc Index
- * Out:
- * none
- *
- * Return Value: none
- *
- -
- * unsigned int cbFrameSize, Hdr+Payload+FCS
- */
-static
-void
-s_vGenerateTxParameter(
- struct vnt_private *pDevice,
- unsigned char byPktType,
- struct vnt_tx_fifo_head *tx_buffer_head,
- void *pvRrvTime,
- void *pvRTS,
- void *pvCTS,
- unsigned int cbFrameSize,
- bool bNeedACK,
- unsigned int uDMAIdx,
- void *psEthHeader,
- unsigned short wCurrentRate
-)
-{
- u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl);
- bool bDisCRC = false;
- unsigned char byFBOption = AUTO_FB_NONE;
-
- tx_buffer_head->current_rate = cpu_to_le16(wCurrentRate);
-
- if (fifo_ctl & FIFOCTL_CRCDIS)
- bDisCRC = true;
-
- if (fifo_ctl & FIFOCTL_AUTO_FB_0)
- byFBOption = AUTO_FB_0;
- else if (fifo_ctl & FIFOCTL_AUTO_FB_1)
- byFBOption = AUTO_FB_1;
-
- if (!pvRrvTime)
- return;
-
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {
- if (pvRTS) { /* RTS_need */
- /* Fill RsvTime */
- struct vnt_rrv_time_rts *buf = pvRrvTime;
-
- buf->rts_rrv_time_aa = get_rtscts_time(pDevice, 2, byPktType, cbFrameSize, wCurrentRate);
- buf->rts_rrv_time_ba = get_rtscts_time(pDevice, 1, byPktType, cbFrameSize, wCurrentRate);
- buf->rts_rrv_time_bb = get_rtscts_time(pDevice, 0, byPktType, cbFrameSize, wCurrentRate);
- buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
- buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK);
-
- s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
- } else {/* RTS_needless, PCF mode */
- struct vnt_rrv_time_cts *buf = pvRrvTime;
-
- buf->rrv_time_a = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
- buf->rrv_time_b = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, pDevice->byTopCCKBasicRate, bNeedACK);
- buf->cts_rrv_time_ba = get_rtscts_time(pDevice, 3, byPktType, cbFrameSize, wCurrentRate);
-
- /* Fill CTS */
- s_vFillCTSHead(pDevice, uDMAIdx, byPktType, pvCTS, cbFrameSize, bNeedACK, bDisCRC, wCurrentRate, byFBOption);
- }
- } else if (byPktType == PK_TYPE_11A) {
- if (pvRTS) {/* RTS_need, non PCF mode */
- struct vnt_rrv_time_ab *buf = pvRrvTime;
-
- buf->rts_rrv_time = get_rtscts_time(pDevice, 2, byPktType, cbFrameSize, wCurrentRate);
- buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, byPktType, cbFrameSize, wCurrentRate, bNeedACK);
-
- /* Fill RTS */
- s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
- } else if (!pvRTS) {/* RTS_needless, non PCF mode */
- struct vnt_rrv_time_ab *buf = pvRrvTime;
-
- buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11A, cbFrameSize, wCurrentRate, bNeedACK);
- }
- } else if (byPktType == PK_TYPE_11B) {
- if (pvRTS) {/* RTS_need, non PCF mode */
- struct vnt_rrv_time_ab *buf = pvRrvTime;
-
- buf->rts_rrv_time = get_rtscts_time(pDevice, 0, byPktType, cbFrameSize, wCurrentRate);
- buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK);
-
- /* Fill RTS */
- s_vFillRTSHead(pDevice, byPktType, pvRTS, cbFrameSize, bNeedACK, bDisCRC, psEthHeader, wCurrentRate, byFBOption);
- } else { /* RTS_needless, non PCF mode */
- struct vnt_rrv_time_ab *buf = pvRrvTime;
-
- buf->rrv_time = vnt_rxtx_rsvtime_le16(pDevice, PK_TYPE_11B, cbFrameSize, wCurrentRate, bNeedACK);
- }
- }
-}
-
-static unsigned int
-s_cbFillTxBufHead(struct vnt_private *pDevice, unsigned char byPktType,
- unsigned char *pbyTxBufferAddr,
- unsigned int uDMAIdx, struct vnt_tx_desc *pHeadTD,
- unsigned int is_pspoll)
-{
- struct vnt_td_info *td_info = pHeadTD->td_info;
- struct sk_buff *skb = td_info->skb;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- struct vnt_tx_fifo_head *tx_buffer_head =
- (struct vnt_tx_fifo_head *)td_info->buf;
- u16 fifo_ctl = le16_to_cpu(tx_buffer_head->fifo_ctl);
- unsigned int cbFrameSize;
- __le16 uDuration;
- unsigned char *pbyBuffer;
- unsigned int uLength = 0;
- unsigned int cbMICHDR = 0;
- unsigned int uMACfragNum = 1;
- unsigned int uPadding = 0;
- unsigned int cbReqCount = 0;
- bool bNeedACK = (bool)(fifo_ctl & FIFOCTL_NEEDACK);
- bool bRTS = (bool)(fifo_ctl & FIFOCTL_RTS);
- struct vnt_tx_desc *ptdCurr;
- unsigned int cbHeaderLength = 0;
- void *pvRrvTime = NULL;
- struct vnt_mic_hdr *pMICHDR = NULL;
- void *pvRTS = NULL;
- void *pvCTS = NULL;
- void *pvTxDataHd = NULL;
- unsigned short wTxBufSize; /* FFinfo size */
- unsigned char byFBOption = AUTO_FB_NONE;
-
- cbFrameSize = skb->len + 4;
-
- if (info->control.hw_key) {
- switch (info->control.hw_key->cipher) {
- case WLAN_CIPHER_SUITE_CCMP:
- cbMICHDR = sizeof(struct vnt_mic_hdr);
- break;
- default:
- break;
- }
-
- cbFrameSize += info->control.hw_key->icv_len;
-
- if (pDevice->local_id > REV_ID_VT3253_A1) {
- /* MAC Header should be padding 0 to DW alignment. */
- uPadding = 4 - (ieee80211_get_hdrlen_from_skb(skb) % 4);
- uPadding %= 4;
- }
- }
-
- /*
- * Use for AUTO FALL BACK
- */
- if (fifo_ctl & FIFOCTL_AUTO_FB_0)
- byFBOption = AUTO_FB_0;
- else if (fifo_ctl & FIFOCTL_AUTO_FB_1)
- byFBOption = AUTO_FB_1;
-
- /* Set RrvTime/RTS/CTS Buffer */
- wTxBufSize = sizeof(struct vnt_tx_fifo_head);
- if (byPktType == PK_TYPE_11GB || byPktType == PK_TYPE_11GA) {/* 802.11g packet */
-
- if (byFBOption == AUTO_FB_NONE) {
- if (bRTS) {/* RTS_need */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts));
- pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g) +
- sizeof(struct vnt_tx_datahead_g);
- } else { /* RTS_needless */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts));
- pvRTS = NULL;
- pvCTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_cts) + cbMICHDR + sizeof(struct vnt_cts));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts) + sizeof(struct vnt_tx_datahead_g);
- }
- } else {
- /* Auto Fall Back */
- if (bRTS) {/* RTS_need */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts));
- pvRTS = (void *) (pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) + cbMICHDR);
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g_fb));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_rts) +
- cbMICHDR + sizeof(struct vnt_rts_g_fb) + sizeof(struct vnt_tx_datahead_g_fb);
- } else { /* RTS_needless */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts));
- pvRTS = NULL;
- pvCTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) + cbMICHDR);
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts_fb));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_cts) +
- cbMICHDR + sizeof(struct vnt_cts_fb) + sizeof(struct vnt_tx_datahead_g_fb);
- }
- } /* Auto Fall Back */
- } else {/* 802.11a/b packet */
-
- if (byFBOption == AUTO_FB_NONE) {
- if (bRTS) {
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
- pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_ab));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_rts_ab) + sizeof(struct vnt_tx_datahead_ab);
- } else { /* RTS_needless, need MICHDR */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
- pvRTS = NULL;
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_tx_datahead_ab);
- }
- } else {
- /* Auto Fall Back */
- if (bRTS) { /* RTS_need */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
- pvRTS = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize +
- sizeof(struct vnt_rrv_time_ab) + cbMICHDR + sizeof(struct vnt_rts_a_fb));
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_rts_a_fb) + sizeof(struct vnt_tx_datahead_a_fb);
- } else { /* RTS_needless */
- pvRrvTime = (void *)(pbyTxBufferAddr + wTxBufSize);
- pMICHDR = (struct vnt_mic_hdr *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab));
- pvRTS = NULL;
- pvCTS = NULL;
- pvTxDataHd = (void *)(pbyTxBufferAddr + wTxBufSize + sizeof(struct vnt_rrv_time_ab) + cbMICHDR);
- cbHeaderLength = wTxBufSize + sizeof(struct vnt_rrv_time_ab) +
- cbMICHDR + sizeof(struct vnt_tx_datahead_a_fb);
- }
- } /* Auto Fall Back */
- }
-
- td_info->mic_hdr = pMICHDR;
-
- memset((void *)(pbyTxBufferAddr + wTxBufSize), 0, (cbHeaderLength - wTxBufSize));
-
- /* Fill FIFO,RrvTime,RTS,and CTS */
- s_vGenerateTxParameter(pDevice, byPktType, tx_buffer_head, pvRrvTime, pvRTS, pvCTS,
- cbFrameSize, bNeedACK, uDMAIdx, hdr, pDevice->wCurrentRate);
- /* Fill DataHead */
- uDuration = s_uFillDataHead(pDevice, byPktType, pvTxDataHd, cbFrameSize, uDMAIdx, bNeedACK,
- 0, 0, uMACfragNum, byFBOption, pDevice->wCurrentRate, is_pspoll);
-
- hdr->duration_id = uDuration;
-
- cbReqCount = cbHeaderLength + uPadding + skb->len;
- pbyBuffer = (unsigned char *)pHeadTD->td_info->buf;
- uLength = cbHeaderLength + uPadding;
-
- /* Copy the Packet into a tx Buffer */
- memcpy((pbyBuffer + uLength), skb->data, skb->len);
-
- ptdCurr = pHeadTD;
-
- ptdCurr->td_info->req_count = (u16)cbReqCount;
-
- return cbHeaderLength;
-}
-
-static void vnt_fill_txkey(struct ieee80211_hdr *hdr, u8 *key_buffer,
- struct ieee80211_key_conf *tx_key,
- struct sk_buff *skb, u16 payload_len,
- struct vnt_mic_hdr *mic_hdr)
-{
- u64 pn64;
- u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb));
-
- /* strip header and icv len from payload */
- payload_len -= ieee80211_get_hdrlen_from_skb(skb);
- payload_len -= tx_key->icv_len;
-
- switch (tx_key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- memcpy(key_buffer, iv, 3);
- memcpy(key_buffer + 3, tx_key->key, tx_key->keylen);
-
- if (tx_key->keylen == WLAN_KEY_LEN_WEP40) {
- memcpy(key_buffer + 8, iv, 3);
- memcpy(key_buffer + 11,
- tx_key->key, WLAN_KEY_LEN_WEP40);
- }
-
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- ieee80211_get_tkip_p2k(tx_key, skb, key_buffer);
-
- break;
- case WLAN_CIPHER_SUITE_CCMP:
-
- if (!mic_hdr)
- return;
-
- mic_hdr->id = 0x59;
- mic_hdr->payload_len = cpu_to_be16(payload_len);
- ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2);
-
- pn64 = atomic64_read(&tx_key->tx_pn);
- mic_hdr->ccmp_pn[5] = pn64;
- mic_hdr->ccmp_pn[4] = pn64 >> 8;
- mic_hdr->ccmp_pn[3] = pn64 >> 16;
- mic_hdr->ccmp_pn[2] = pn64 >> 24;
- mic_hdr->ccmp_pn[1] = pn64 >> 32;
- mic_hdr->ccmp_pn[0] = pn64 >> 40;
-
- if (ieee80211_has_a4(hdr->frame_control))
- mic_hdr->hlen = cpu_to_be16(28);
- else
- mic_hdr->hlen = cpu_to_be16(22);
-
- ether_addr_copy(mic_hdr->addr1, hdr->addr1);
- ether_addr_copy(mic_hdr->addr2, hdr->addr2);
- ether_addr_copy(mic_hdr->addr3, hdr->addr3);
-
- mic_hdr->frame_control = cpu_to_le16(
- le16_to_cpu(hdr->frame_control) & 0xc78f);
- mic_hdr->seq_ctrl = cpu_to_le16(
- le16_to_cpu(hdr->seq_ctrl) & 0xf);
-
- if (ieee80211_has_a4(hdr->frame_control))
- ether_addr_copy(mic_hdr->addr4, hdr->addr4);
-
- memcpy(key_buffer, tx_key->key, WLAN_KEY_LEN_CCMP);
-
- break;
- default:
- break;
- }
-}
-
-int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
- struct vnt_tx_desc *head_td, struct sk_buff *skb)
-{
- struct vnt_td_info *td_info = head_td->td_info;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_tx_rate *tx_rate = &info->control.rates[0];
- struct ieee80211_rate *rate;
- struct ieee80211_key_conf *tx_key;
- struct ieee80211_hdr *hdr;
- struct vnt_tx_fifo_head *tx_buffer_head =
- (struct vnt_tx_fifo_head *)td_info->buf;
- u16 tx_body_size = skb->len, current_rate;
- u8 pkt_type;
- bool is_pspoll = false;
-
- memset(tx_buffer_head, 0, sizeof(*tx_buffer_head));
-
- hdr = (struct ieee80211_hdr *)(skb->data);
-
- rate = ieee80211_get_tx_rate(priv->hw, info);
-
- current_rate = rate->hw_value;
- if (priv->wCurrentRate != current_rate &&
- !(priv->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
- priv->wCurrentRate = current_rate;
-
- RFbSetPower(priv, priv->wCurrentRate,
- priv->hw->conf.chandef.chan->hw_value);
- }
-
- if (current_rate > RATE_11M) {
- if (info->band == NL80211_BAND_5GHZ) {
- pkt_type = PK_TYPE_11A;
- } else {
- if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
- pkt_type = PK_TYPE_11GB;
- else
- pkt_type = PK_TYPE_11GA;
- }
- } else {
- pkt_type = PK_TYPE_11B;
- }
-
- /*Set fifo controls */
- if (pkt_type == PK_TYPE_11A)
- tx_buffer_head->fifo_ctl = 0;
- else if (pkt_type == PK_TYPE_11B)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B);
- else if (pkt_type == PK_TYPE_11GB)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB);
- else if (pkt_type == PK_TYPE_11GA)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA);
-
- /* generate interrupt */
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT);
-
- if (!ieee80211_is_data(hdr->frame_control)) {
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN);
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_ISDMA0);
- tx_buffer_head->time_stamp =
- cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
- } else {
- tx_buffer_head->time_stamp =
- cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
- }
-
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK);
-
- if (ieee80211_has_retry(hdr->frame_control))
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY);
-
- if (tx_rate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
- priv->preamble_type = PREAMBLE_SHORT;
- else
- priv->preamble_type = PREAMBLE_LONG;
-
- if (tx_rate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS);
-
- if (ieee80211_has_a4(hdr->frame_control)) {
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD);
- priv->bLongHeader = true;
- }
-
- if (info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER)
- is_pspoll = true;
-
- tx_buffer_head->frag_ctl =
- cpu_to_le16(ieee80211_get_hdrlen_from_skb(skb) << 10);
-
- if (info->control.hw_key) {
- switch (info->control.hw_key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY);
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP);
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_AES);
- break;
- default:
- break;
- }
- }
-
- tx_buffer_head->current_rate = cpu_to_le16(current_rate);
-
- /* legacy rates TODO use ieee80211_tx_rate */
- if (current_rate >= RATE_18M && ieee80211_is_data(hdr->frame_control)) {
- if (priv->byAutoFBCtrl == AUTO_FB_0)
- tx_buffer_head->fifo_ctl |=
- cpu_to_le16(FIFOCTL_AUTO_FB_0);
- else if (priv->byAutoFBCtrl == AUTO_FB_1)
- tx_buffer_head->fifo_ctl |=
- cpu_to_le16(FIFOCTL_AUTO_FB_1);
- }
-
- tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG);
-
- s_cbFillTxBufHead(priv, pkt_type, (u8 *)tx_buffer_head,
- dma_idx, head_td, is_pspoll);
-
- if (info->control.hw_key) {
- tx_key = info->control.hw_key;
- if (tx_key->keylen > 0)
- vnt_fill_txkey(hdr, tx_buffer_head->tx_key,
- tx_key, skb, tx_body_size,
- td_info->mic_hdr);
- }
-
- return 0;
-}
-
-static int vnt_beacon_xmit(struct vnt_private *priv,
- struct sk_buff *skb)
-{
- struct vnt_tx_short_buf_head *short_head =
- (struct vnt_tx_short_buf_head *)priv->tx_beacon_bufs;
- struct ieee80211_mgmt *mgmt_hdr = (struct ieee80211_mgmt *)
- (priv->tx_beacon_bufs + sizeof(*short_head));
- struct ieee80211_tx_info *info;
- u32 frame_size = skb->len + 4;
- u16 current_rate;
-
- memset(priv->tx_beacon_bufs, 0, sizeof(*short_head));
-
- if (priv->byBBType == BB_TYPE_11A) {
- current_rate = RATE_6M;
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_size, current_rate,
- PK_TYPE_11A, &short_head->ab);
-
- /* Get Duration and TimeStampOff */
- short_head->duration =
- cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B,
- frame_size, PK_TYPE_11A, current_rate,
- false, 0, 0, 1, AUTO_FB_NONE));
-
- short_head->time_stamp_off =
- vnt_time_stamp_off(priv, current_rate);
- } else {
- current_rate = RATE_1M;
- short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B);
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_size, current_rate,
- PK_TYPE_11B, &short_head->ab);
-
- /* Get Duration and TimeStampOff */
- short_head->duration =
- cpu_to_le16((u16)s_uGetDataDuration(priv, DATADUR_B,
- frame_size, PK_TYPE_11B, current_rate,
- false, 0, 0, 1, AUTO_FB_NONE));
-
- short_head->time_stamp_off =
- vnt_time_stamp_off(priv, current_rate);
- }
-
- short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT);
-
- /* Copy Beacon */
- memcpy(mgmt_hdr, skb->data, skb->len);
-
- /* time stamp always 0 */
- mgmt_hdr->u.beacon.timestamp = 0;
-
- info = IEEE80211_SKB_CB(skb);
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr;
-
- hdr->duration_id = 0;
- hdr->seq_ctrl = cpu_to_le16(priv->wSeqCounter << 4);
- }
-
- priv->wSeqCounter++;
- if (priv->wSeqCounter > 0x0fff)
- priv->wSeqCounter = 0;
-
- priv->wBCNBufLen = sizeof(*short_head) + skb->len;
-
- iowrite32((u32)priv->tx_beacon_dma, priv->port_offset + MAC_REG_BCNDMAPTR);
-
- iowrite16(priv->wBCNBufLen, priv->port_offset + MAC_REG_BCNDMACTL + 2);
- /* Set auto Transmit on */
- vt6655_mac_reg_bits_on(priv->port_offset, MAC_REG_TCR, TCR_AUTOBCNTX);
- /* Poll Transmit the adapter */
- iowrite8(BEACON_READY, priv->port_offset + MAC_REG_BCNDMACTL);
-
- return 0;
-}
-
-int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif)
-{
- struct sk_buff *beacon;
-
- beacon = ieee80211_beacon_get(priv->hw, vif, 0);
- if (!beacon)
- return -ENOMEM;
-
- if (vnt_beacon_xmit(priv, beacon)) {
- ieee80211_free_txskb(priv->hw, beacon);
- return -ENODEV;
- }
-
- return 0;
-}
-
-int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf)
-{
- iowrite8(TFTCTL_TSFCNTRST, priv->port_offset + MAC_REG_TFTCTL);
-
- iowrite8(TFTCTL_TSFCNTREN, priv->port_offset + MAC_REG_TFTCTL);
-
- CARDvSetFirstNextTBTT(priv, conf->beacon_int);
-
- card_set_beacon_period(priv, conf->beacon_int);
-
- return vnt_beacon_make(priv, vif);
-}
diff --git a/drivers/staging/vt6655/rxtx.h b/drivers/staging/vt6655/rxtx.h
deleted file mode 100644
index be1e5180d57b..000000000000
--- a/drivers/staging/vt6655/rxtx.h
+++ /dev/null
@@ -1,184 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 27, 2002
- *
- */
-
-#ifndef __RXTX_H__
-#define __RXTX_H__
-
-#include "device.h"
-
-#define DEFAULT_MSDU_LIFETIME_RES_64us 8000 /* 64us */
-#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */
-
-/*--------------------- Export Definitions -------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-/* MIC HDR data header */
-struct vnt_mic_hdr {
- u8 id;
- u8 tx_priority;
- u8 mic_addr2[ETH_ALEN];
- u8 ccmp_pn[IEEE80211_CCMP_PN_LEN];
- __be16 payload_len;
- __be16 hlen;
- __le16 frame_control;
- u8 addr1[ETH_ALEN];
- u8 addr2[ETH_ALEN];
- u8 addr3[ETH_ALEN];
- __le16 seq_ctrl;
- u8 addr4[ETH_ALEN];
- u16 packing; /* packing to 48 bytes */
-} __packed;
-
-/* RsvTime buffer header */
-struct vnt_rrv_time_rts {
- __le16 rts_rrv_time_ba;
- __le16 rts_rrv_time_aa;
- __le16 rts_rrv_time_bb;
- u16 reserved;
- __le16 rrv_time_b;
- __le16 rrv_time_a;
-} __packed;
-
-struct vnt_rrv_time_cts {
- __le16 cts_rrv_time_ba;
- u16 reserved;
- __le16 rrv_time_b;
- __le16 rrv_time_a;
-} __packed;
-
-struct vnt_rrv_time_ab {
- __le16 rts_rrv_time;
- __le16 rrv_time;
-} __packed;
-
-/* TX data header */
-struct vnt_tx_datahead_g {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_b;
- __le16 duration_a;
- __le16 time_stamp_off_b;
- __le16 time_stamp_off_a;
-} __packed;
-
-struct vnt_tx_datahead_g_fb {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_b;
- __le16 duration_a;
- __le16 duration_a_f0;
- __le16 duration_a_f1;
- __le16 time_stamp_off_b;
- __le16 time_stamp_off_a;
-} __packed;
-
-struct vnt_tx_datahead_ab {
- struct vnt_phy_field ab;
- __le16 duration;
- __le16 time_stamp_off;
-} __packed;
-
-struct vnt_tx_datahead_a_fb {
- struct vnt_phy_field a;
- __le16 duration;
- __le16 time_stamp_off;
- __le16 duration_f0;
- __le16 duration_f1;
-} __packed;
-
-/* RTS buffer header */
-struct vnt_rts_g {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_ba;
- __le16 duration_aa;
- __le16 duration_bb;
- u16 reserved;
- struct ieee80211_rts data;
-} __packed __aligned(2);
-
-struct vnt_rts_g_fb {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_ba;
- __le16 duration_aa;
- __le16 duration_bb;
- u16 wReserved;
- __le16 rts_duration_ba_f0;
- __le16 rts_duration_aa_f0;
- __le16 rts_duration_ba_f1;
- __le16 rts_duration_aa_f1;
- struct ieee80211_rts data;
-} __packed __aligned(2);
-
-struct vnt_rts_ab {
- struct vnt_phy_field ab;
- __le16 duration;
- u16 reserved;
- struct ieee80211_rts data;
-} __packed __aligned(2);
-
-struct vnt_rts_a_fb {
- struct vnt_phy_field a;
- __le16 duration;
- u16 reserved;
- __le16 rts_duration_f0;
- __le16 rts_duration_f1;
- struct ieee80211_rts data;
-} __packed __aligned(2);
-
-/* CTS buffer header */
-struct vnt_cts {
- struct vnt_phy_field b;
- __le16 duration_ba;
- u16 reserved;
- struct ieee80211_cts data;
- u16 reserved2;
-} __packed __aligned(2);
-
-struct vnt_cts_fb {
- struct vnt_phy_field b;
- __le16 duration_ba;
- u16 reserved;
- __le16 cts_duration_ba_f0;
- __le16 cts_duration_ba_f1;
- struct ieee80211_cts data;
- u16 reserved2;
-} __packed __aligned(2);
-
-struct vnt_tx_fifo_head {
- u8 tx_key[WLAN_KEY_LEN_CCMP];
- __le16 fifo_ctl;
- __le16 time_stamp;
- __le16 frag_ctl;
- __le16 current_rate;
-} __packed;
-
-struct vnt_tx_short_buf_head {
- __le16 fifo_ctl;
- u16 time_stamp;
- struct vnt_phy_field ab;
- __le16 duration;
- __le16 time_stamp_off;
-} __packed;
-
-int vnt_generate_fifo_header(struct vnt_private *priv, u32 dma_idx,
- struct vnt_tx_desc *head_td, struct sk_buff *skb);
-int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif);
-int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf);
-
-#endif /* __RXTX_H__ */
diff --git a/drivers/staging/vt6655/srom.c b/drivers/staging/vt6655/srom.c
deleted file mode 100644
index e80556509c58..000000000000
--- a/drivers/staging/vt6655/srom.c
+++ /dev/null
@@ -1,139 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:Implement functions to access eeprom
- *
- * Author: Jerry Chen
- *
- * Date: Jan 29, 2003
- *
- * Functions:
- * SROMbyReadEmbedded - Embedded read eeprom via MAC
- * SROMbWriteEmbedded - Embedded write eeprom via MAC
- * SROMvRegBitsOn - Set Bits On in eeprom
- * SROMvRegBitsOff - Clear Bits Off in eeprom
- * SROMbIsRegBitsOn - Test if Bits On in eeprom
- * SROMbIsRegBitsOff - Test if Bits Off in eeprom
- * SROMvReadAllContents - Read all contents in eeprom
- * SROMvWriteAllContents - Write all contents in eeprom
- * SROMvReadEtherAddress - Read Ethernet Address in eeprom
- * SROMvWriteEtherAddress - Write Ethernet Address in eeprom
- * SROMvReadSubSysVenId - Read Sub_VID and Sub_SysId in eeprom
- * SROMbAutoLoad - Auto Load eeprom to MAC register
- *
- * Revision History:
- *
- */
-
-#include "device.h"
-#include "mac.h"
-#include "srom.h"
-
-/*--------------------- Static Definitions -------------------------*/
-
-/*--------------------- Static Classes ----------------------------*/
-
-/*--------------------- Static Variables --------------------------*/
-
-/*--------------------- Static Functions --------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-/*
- * Description: Read a byte from EEPROM, by MAC I2C
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * contnt_offset - address of EEPROM
- * Out:
- * none
- *
- * Return Value: data read
- *
- */
-unsigned char SROMbyReadEmbedded(void __iomem *iobase,
- unsigned char contnt_offset)
-{
- unsigned short wDelay, wNoACK;
- unsigned char byWait;
- unsigned char byData;
- unsigned char byOrg;
-
- byOrg = ioread8(iobase + MAC_REG_I2MCFG);
- /* turn off hardware retry for getting NACK */
- iowrite8(byOrg & (~I2MCFG_NORETRY), iobase + MAC_REG_I2MCFG);
- for (wNoACK = 0; wNoACK < W_MAX_I2CRETRY; wNoACK++) {
- iowrite8(EEP_I2C_DEV_ID, iobase + MAC_REG_I2MTGID);
- iowrite8(contnt_offset, iobase + MAC_REG_I2MTGAD);
-
- /* issue read command */
- iowrite8(I2MCSR_EEMR, iobase + MAC_REG_I2MCSR);
- /* wait DONE be set */
- for (wDelay = 0; wDelay < W_MAX_TIMEOUT; wDelay++) {
- byWait = ioread8(iobase + MAC_REG_I2MCSR);
- if (byWait & (I2MCSR_DONE | I2MCSR_NACK))
- break;
- udelay(CB_DELAY_LOOP_WAIT);
- }
- if ((wDelay < W_MAX_TIMEOUT) &&
- (!(byWait & I2MCSR_NACK))) {
- break;
- }
- }
- byData = ioread8(iobase + MAC_REG_I2MDIPT);
- iowrite8(byOrg, iobase + MAC_REG_I2MCFG);
- return byData;
-}
-
-/*
- * Description: Read all contents of eeprom to buffer
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * Out:
- * pbyEepromRegs - EEPROM content Buffer
- *
- * Return Value: none
- *
- */
-void SROMvReadAllContents(void __iomem *iobase, unsigned char *pbyEepromRegs)
-{
- int ii;
-
- /* ii = Rom Address */
- for (ii = 0; ii < EEP_MAX_CONTEXT_SIZE; ii++) {
- *pbyEepromRegs = SROMbyReadEmbedded(iobase,
- (unsigned char)ii);
- pbyEepromRegs++;
- }
-}
-
-/*
- * Description: Read Ethernet Address from eeprom to buffer
- *
- * Parameters:
- * In:
- * iobase - I/O base address
- * Out:
- * pbyEtherAddress - Ethernet Address buffer
- *
- * Return Value: none
- *
- */
-void SROMvReadEtherAddress(void __iomem *iobase,
- unsigned char *pbyEtherAddress)
-{
- unsigned char ii;
-
- /* ii = Rom Address */
- for (ii = 0; ii < ETH_ALEN; ii++) {
- *pbyEtherAddress = SROMbyReadEmbedded(iobase, ii);
- pbyEtherAddress++;
- }
-}
diff --git a/drivers/staging/vt6655/srom.h b/drivers/staging/vt6655/srom.h
deleted file mode 100644
index b03073ffa18a..000000000000
--- a/drivers/staging/vt6655/srom.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions to access eeprom
- *
- * Author: Jerry Chen
- *
- * Date: Jan 29, 2003
- */
-
-#ifndef __SROM_H__
-#define __SROM_H__
-
-/*--------------------- Export Definitions -------------------------*/
-
-#define EEP_MAX_CONTEXT_SIZE 256
-
-#define CB_EEPROM_READBYTE_WAIT 900 /* us */
-
-#define W_MAX_I2CRETRY 0x0fff
-
-/* Contents in the EEPROM */
-#define EEP_OFS_PAR 0x00 /* physical address */
-#define EEP_OFS_ANTENNA 0x16
-#define EEP_OFS_RADIOCTL 0x17
-#define EEP_OFS_RFTYPE 0x1B /* for select RF */
-#define EEP_OFS_MINCHANNEL 0x1C /* Min Channel # */
-#define EEP_OFS_MAXCHANNEL 0x1D /* Max Channel # */
-#define EEP_OFS_SIGNATURE 0x1E
-#define EEP_OFS_ZONETYPE 0x1F
-#define EEP_OFS_RFTABLE 0x20 /* RF POWER TABLE */
-#define EEP_OFS_PWR_CCK 0x20
-#define EEP_OFS_SETPT_CCK 0x21
-#define EEP_OFS_PWR_OFDMG 0x23
-#define EEP_OFS_SETPT_OFDMG 0x24
-#define EEP_OFS_PWR_FORMULA_OST 0x26
-#define EEP_OFS_MAJOR_VER 0x2E
-#define EEP_OFS_MINOR_VER 0x2F
-#define EEP_OFS_CCK_PWR_TBL 0x30
-#define EEP_OFS_CCK_PWR_dBm 0x3F
-#define EEP_OFS_OFDM_PWR_TBL 0x40
-#define EEP_OFS_OFDM_PWR_dBm 0x4F
-/*{{ RobertYu: 20041124 */
-#define EEP_OFS_SETPT_OFDMA 0x4E
-#define EEP_OFS_OFDMA_PWR_TBL 0x50
-/*}}*/
-#define EEP_OFS_OFDMA_PWR_dBm 0xD2
-
-/*----------need to remove --------------------*/
-#define EEP_OFS_BBTAB_LEN 0x70 /* BB Table Length */
-#define EEP_OFS_BBTAB_ADR 0x71 /* BB Table Offset */
-#define EEP_OFS_CHECKSUM 0xFF /* reserved area for baseband 28h~78h */
-
-#define EEP_I2C_DEV_ID 0x50 /* EEPROM device address on I2C bus */
-
-/* Bits in EEP_OFS_ANTENNA */
-#define EEP_ANTENNA_MAIN 0x01
-#define EEP_ANTENNA_AUX 0x02
-#define EEP_ANTINV 0x04
-
-/* Bits in EEP_OFS_RADIOCTL */
-#define EEP_RADIOCTL_ENABLE 0x80
-#define EEP_RADIOCTL_INV 0x01
-
-/*--------------------- Export Types ------------------------------*/
-
-/*--------------------- Export Macros ------------------------------*/
-
-/*--------------------- Export Classes ----------------------------*/
-
-/*--------------------- Export Variables --------------------------*/
-
-/*--------------------- Export Functions --------------------------*/
-
-unsigned char SROMbyReadEmbedded(void __iomem *iobase,
- unsigned char byContntOffset);
-
-void SROMvReadAllContents(void __iomem *iobase, unsigned char *pbyEepromRegs);
-
-void SROMvReadEtherAddress(void __iomem *iobase,
- unsigned char *pbyEtherAddress);
-
-#endif /* __EEPROM_H__*/
diff --git a/drivers/staging/vt6655/test b/drivers/staging/vt6655/test
deleted file mode 100644
index ba6dec774478..000000000000
--- a/drivers/staging/vt6655/test
+++ /dev/null
@@ -1,9 +0,0 @@
-KSP := /lib/modules/$(shell uname -r)/build \
- /usr/src/linux-$(shell uname -r) \
- /usr/src/linux-$(shell uname -r | sed 's/-.*//') \
-# /usr/src/kernel-headers-$(shell uname -r) \
-# /usr/src/kernel-source-$(shell uname -r) \
-# /usr/src/linux-$(shell uname -r | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
-# /usr/src/linux /home/plice
-test_dir = $(shell [ -e $(dir)/include/linux ] && echo $(dir))
-KSP := $(foreach dir, $(KSP), $(test_dir))
diff --git a/drivers/staging/vt6656/Kconfig b/drivers/staging/vt6656/Kconfig
deleted file mode 100644
index f52a3f1d9a2e..000000000000
--- a/drivers/staging/vt6656/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-config VT6656
- tristate "VIA Technologies VT6656 support"
- depends on MAC80211 && USB && WLAN && m
- select FW_LOADER
- help
- This is a vendor-written driver for VIA VT6656.
diff --git a/drivers/staging/vt6656/Makefile b/drivers/staging/vt6656/Makefile
deleted file mode 100644
index f696a9d7a143..000000000000
--- a/drivers/staging/vt6656/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# SPDX-License-Identifier: GPL-2.0
-
-vt6656_stage-y += main_usb.o \
- card.o \
- mac.o \
- baseband.o \
- wcmd.o\
- rxtx.o \
- power.o \
- key.o \
- rf.o \
- usbpipe.o \
- channel.o
-
-obj-$(CONFIG_VT6656) += vt6656_stage.o
diff --git a/drivers/staging/vt6656/TODO b/drivers/staging/vt6656/TODO
deleted file mode 100644
index cca78d2d3cfe..000000000000
--- a/drivers/staging/vt6656/TODO
+++ /dev/null
@@ -1,17 +0,0 @@
-TODO:
-- remove __cplusplus ifdefs -- done
-- remove kernel version compatibility wrappers
-- remove support for older wireless extensions
-- prepare for merge with vt6655 driver:
- - remove PRINT_K() macro
- - split rf.c
- - abstract VT3184 chipset specific code
-- add common vt665x infrastructure
-- kill ttype.h -- done
-- switch to use MAC80211
-- use kernel coding style
-- sparse fixes
-- integrate with drivers/net/wireless
-
-Please send any patches to Greg Kroah-Hartman <greg@kroah.com>
-and Forest Bond <forest@alittletooquiet.net>.
diff --git a/drivers/staging/vt6656/baseband.c b/drivers/staging/vt6656/baseband.c
deleted file mode 100644
index ad7b963f0d98..000000000000
--- a/drivers/staging/vt6656/baseband.c
+++ /dev/null
@@ -1,455 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions to access baseband
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 5, 2002
- *
- * Functions:
- * vnt_get_frame_time - Calculate data frame transmitting time
- * vnt_get_phy_field - Calculate PhyLength, PhyService and Phy
- * Signal parameter for baseband Tx
- * vnt_vt3184_init - VIA VT3184 baseband chip init code
- *
- * Revision History:
- *
- *
- */
-
-#include <linux/bits.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include "device.h"
-#include "mac.h"
-#include "baseband.h"
-#include "rf.h"
-#include "usbpipe.h"
-
-static const u8 vnt_vt3184_agc[] = {
- 0x00, 0x00, 0x02, 0x02, 0x04, 0x04, 0x06, 0x06,
- 0x08, 0x08, 0x0a, 0x0a, 0x0c, 0x0c, 0x0e, 0x0e, /* 0x0f */
- 0x10, 0x10, 0x12, 0x12, 0x14, 0x14, 0x16, 0x16,
- 0x18, 0x18, 0x1a, 0x1a, 0x1c, 0x1c, 0x1e, 0x1e, /* 0x1f */
- 0x20, 0x20, 0x22, 0x22, 0x24, 0x24, 0x26, 0x26,
- 0x28, 0x28, 0x2a, 0x2a, 0x2c, 0x2c, 0x2e, 0x2e, /* 0x2f */
- 0x30, 0x30, 0x32, 0x32, 0x34, 0x34, 0x36, 0x36,
- 0x38, 0x38, 0x3a, 0x3a, 0x3c, 0x3c, 0x3e, 0x3e /* 0x3f */
-};
-
-static u8 vnt_vt3184_al2230[] = {
- 0x31, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
- 0x70, 0x45, 0x2a, 0x76, 0x00, 0x00, 0x80, 0x00, /* 0x0f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x8e, 0x0a, 0x00, 0x00, 0x00, /* 0x1f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x0c, /* 0x2f */
- 0x26, 0x5b, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa,
- 0xff, 0xff, 0x79, 0x00, 0x00, 0x0b, 0x48, 0x04, /* 0x3f */
- 0x00, 0x08, 0x00, 0x08, 0x08, 0x14, 0x05, 0x09,
- 0x00, 0x00, 0x00, 0x00, 0x09, 0x73, 0x00, 0xc5, /* 0x4f */
- 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f */
- 0xe4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* 0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7f */
- 0x8c, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x1f, 0xb7, 0x88, 0x47, 0xaa, 0x00, /* 0x8f */
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x00, 0x15, 0x00, 0x18, /* 0xaf */
- 0x38, 0x30, 0x00, 0x00, 0xff, 0x0f, 0xe4, 0xe2,
- 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, /* 0xbf */
- 0x18, 0x20, 0x07, 0x18, 0xff, 0xff, 0x0e, 0x0a,
- 0x0e, 0x00, 0x82, 0xa7, 0x3c, 0x10, 0x30, 0x05, /* 0xcf */
- 0x40, 0x12, 0x00, 0x00, 0x10, 0x28, 0x80, 0x2a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf */
- 0x00, 0xf3, 0x00, 0x00, 0x00, 0x10, 0x00, 0x12,
- 0x00, 0xf4, 0x00, 0xff, 0x79, 0x20, 0x30, 0x05, /* 0xef */
- 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xff */
-};
-
-/* {{RobertYu:20060515, new BB setting for VT3226D0 */
-static const u8 vnt_vt3184_vt3226d0[] = {
- 0x31, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
- 0x70, 0x45, 0x2a, 0x76, 0x00, 0x00, 0x80, 0x00, /* 0x0f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x8e, 0x0a, 0x00, 0x00, 0x00, /* 0x1f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x4a, 0x00, 0x0c, /* 0x2f */
- 0x26, 0x5b, 0x00, 0x00, 0x00, 0x00, 0xaa, 0xaa,
- 0xff, 0xff, 0x79, 0x00, 0x00, 0x0b, 0x48, 0x04, /* 0x3f */
- 0x00, 0x08, 0x00, 0x08, 0x08, 0x14, 0x05, 0x09,
- 0x00, 0x00, 0x00, 0x00, 0x09, 0x73, 0x00, 0xc5, /* 0x4f */
- 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0xd0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x5f */
- 0xe4, 0x80, 0x00, 0x00, 0x00, 0x00, 0x98, 0x0a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, /* 0x6f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x7f */
- 0x8c, 0x01, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x08, 0x00, 0x1f, 0xb7, 0x88, 0x47, 0xaa, 0x00, /* 0x8f */
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xeb,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, /* 0x9f */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, /* 0xaf */
- 0x38, 0x30, 0x00, 0x00, 0xff, 0x0f, 0xe4, 0xe2,
- 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x00, /* 0xbf */
- 0x18, 0x20, 0x07, 0x18, 0xff, 0xff, 0x10, 0x0a,
- 0x0e, 0x00, 0x84, 0xa7, 0x3c, 0x10, 0x24, 0x05, /* 0xcf */
- 0x40, 0x12, 0x00, 0x00, 0x10, 0x28, 0x80, 0x2a,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xdf */
- 0x00, 0xf3, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10,
- 0x00, 0xf4, 0x00, 0xff, 0x79, 0x20, 0x30, 0x08, /* 0xef */
- 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /* 0xff */
-};
-
-struct vnt_threshold {
- u8 bb_pre_ed_rssi;
- u8 cr_201;
- u8 cr_206;
-};
-
-static const struct vnt_threshold al2230_vnt_threshold[] = {
- {0, 0x00, 0x30}, /* Max sensitivity */
- {68, 0x00, 0x36},
- {67, 0x00, 0x43},
- {66, 0x00, 0x51},
- {65, 0x00, 0x62},
- {64, 0x00, 0x79},
- {63, 0x00, 0x93},
- {62, 0x00, 0xb9},
- {61, 0x00, 0xe3},
- {60, 0x01, 0x18},
- {59, 0x01, 0x54},
- {58, 0x01, 0xa0},
- {57, 0x02, 0x20},
- {56, 0x02, 0xa0},
- {55, 0x03, 0x00},
- {53, 0x06, 0x00},
- {51, 0x09, 0x00},
- {49, 0x0e, 0x00},
- {47, 0x15, 0x00},
- {46, 0x1a, 0x00},
- {45, 0xff, 0x00}
-};
-
-static const struct vnt_threshold vt3226_vnt_threshold[] = {
- {0, 0x00, 0x24}, /* Max sensitivity */
- {68, 0x00, 0x2d},
- {67, 0x00, 0x36},
- {66, 0x00, 0x43},
- {65, 0x00, 0x52},
- {64, 0x00, 0x68},
- {63, 0x00, 0x80},
- {62, 0x00, 0x9c},
- {61, 0x00, 0xc0},
- {60, 0x00, 0xea},
- {59, 0x01, 0x30},
- {58, 0x01, 0x70},
- {57, 0x01, 0xb0},
- {56, 0x02, 0x30},
- {55, 0x02, 0xc0},
- {53, 0x04, 0x00},
- {51, 0x07, 0x00},
- {49, 0x0a, 0x00},
- {47, 0x11, 0x00},
- {45, 0x18, 0x00},
- {43, 0x26, 0x00},
- {42, 0x36, 0x00},
- {41, 0xff, 0x00}
-};
-
-/*
- * Description: Set Antenna mode
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * antenna_mode - Antenna Mode
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-int vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode)
-{
- switch (antenna_mode) {
- case ANT_TXA:
- case ANT_TXB:
- break;
- case ANT_RXA:
- priv->bb_rx_conf &= 0xFC;
- break;
- case ANT_RXB:
- priv->bb_rx_conf &= 0xFE;
- priv->bb_rx_conf |= 0x02;
- break;
- }
-
- return vnt_control_out(priv, MESSAGE_TYPE_SET_ANTMD,
- (u16)antenna_mode, 0, 0, NULL);
-}
-
-/*
- * Description: Set Antenna mode
- *
- * Parameters:
- * In:
- * pDevice - Device Structure
- * byAntennaMode - Antenna Mode
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-
-int vnt_vt3184_init(struct vnt_private *priv)
-{
- int ret;
- u16 length;
- u8 *addr = NULL;
- const u8 *c_addr;
- u8 data;
-
- ret = vnt_control_in(priv, MESSAGE_TYPE_READ, 0, MESSAGE_REQUEST_EEPROM,
- EEP_MAX_CONTEXT_SIZE, priv->eeprom);
- if (ret)
- goto end;
-
- priv->rf_type = priv->eeprom[EEP_OFS_RFTYPE];
-
- dev_dbg(&priv->usb->dev, "RF Type %d\n", priv->rf_type);
-
- if ((priv->rf_type == RF_AL2230) ||
- (priv->rf_type == RF_AL2230S)) {
- priv->bb_rx_conf = vnt_vt3184_al2230[10];
- length = sizeof(vnt_vt3184_al2230);
- addr = vnt_vt3184_al2230;
-
- priv->bb_vga[0] = 0x1c;
- priv->bb_vga[1] = 0x10;
- priv->bb_vga[2] = 0x0;
- priv->bb_vga[3] = 0x0;
-
- } else if ((priv->rf_type == RF_VT3226) ||
- (priv->rf_type == RF_VT3226D0)) {
- priv->bb_rx_conf = vnt_vt3184_vt3226d0[10];
- length = sizeof(vnt_vt3184_vt3226d0);
- c_addr = vnt_vt3184_vt3226d0;
-
- priv->bb_vga[0] = 0x20;
- priv->bb_vga[1] = 0x10;
- priv->bb_vga[2] = 0x0;
- priv->bb_vga[3] = 0x0;
-
- /* Fix VT3226 DFC system timing issue */
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL2,
- SOFTPWRCTL_RFLEOPT);
- if (ret)
- goto end;
- } else {
- goto end;
- }
-
- if (addr)
- c_addr = addr;
-
- ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
- MESSAGE_REQUEST_BBREG, length, c_addr);
- if (ret)
- goto end;
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
- MESSAGE_REQUEST_BBAGC,
- sizeof(vnt_vt3184_agc), vnt_vt3184_agc);
- if (ret)
- goto end;
-
- if ((priv->rf_type == RF_VT3226) ||
- (priv->rf_type == RF_VT3226D0)) {
- data = (priv->rf_type == RF_VT3226D0) ? 0x11 : 0x23;
-
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG,
- MAC_REG_ITRTMSET, data);
- if (ret)
- goto end;
-
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_PAPEDELAY, BIT(0));
- if (ret)
- goto end;
- }
-
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x04, 0x7f);
- if (ret)
- goto end;
-
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01);
- if (ret)
- goto end;
-
- ret = vnt_rf_table_download(priv);
- if (ret)
- goto end;
-
- /* Fix for TX USB resets from vendors driver */
- ret = vnt_control_in(priv, MESSAGE_TYPE_READ, USB_REG4,
- MESSAGE_REQUEST_MEM, sizeof(data), &data);
- if (ret)
- goto end;
-
- data |= 0x2;
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, USB_REG4,
- MESSAGE_REQUEST_MEM, sizeof(data), &data);
-
-end:
- return ret;
-}
-
-/*
- * Description: Set ShortSlotTime mode
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-int vnt_set_short_slot_time(struct vnt_private *priv)
-{
- int ret = 0;
- u8 bb_vga = 0;
-
- if (priv->short_slot_time)
- priv->bb_rx_conf &= 0xdf;
- else
- priv->bb_rx_conf |= 0x20;
-
- ret = vnt_control_in_u8(priv, MESSAGE_REQUEST_BBREG, 0xe7, &bb_vga);
- if (ret)
- return ret;
-
- if (bb_vga == priv->bb_vga[0])
- priv->bb_rx_conf |= 0x20;
-
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0a,
- priv->bb_rx_conf);
-}
-
-int vnt_set_vga_gain_offset(struct vnt_private *priv, u8 data)
-{
- int ret;
-
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xE7, data);
- if (ret)
- return ret;
-
- /* patch for 3253B0 Baseband with Cardbus module */
- if (priv->short_slot_time)
- priv->bb_rx_conf &= 0xdf; /* 1101 1111 */
- else
- priv->bb_rx_conf |= 0x20; /* 0010 0000 */
-
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0a,
- priv->bb_rx_conf);
-}
-
-/*
- * Description: vnt_set_deep_sleep
- *
- * Parameters:
- * In:
- * priv - Device Structure
- * Out:
- * none
- *
- * Return Value: none
- *
- */
-int vnt_set_deep_sleep(struct vnt_private *priv)
-{
- int ret = 0;
-
- /* CR12 */
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0c, 0x17);
- if (ret)
- return ret;
-
- /* CR13 */
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0xB9);
-}
-
-int vnt_exit_deep_sleep(struct vnt_private *priv)
-{
- int ret = 0;
-
- /* CR12 */
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0c, 0x00);
- if (ret)
- return ret;
-
- /* CR13 */
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0x0d, 0x01);
-}
-
-int vnt_update_pre_ed_threshold(struct vnt_private *priv, int scanning)
-{
- const struct vnt_threshold *threshold = NULL;
- u8 length;
- u8 cr_201, cr_206;
- u8 ed_inx;
- int ret;
-
- switch (priv->rf_type) {
- case RF_AL2230:
- case RF_AL2230S:
- threshold = al2230_vnt_threshold;
- length = ARRAY_SIZE(al2230_vnt_threshold);
- break;
-
- case RF_VT3226:
- case RF_VT3226D0:
- threshold = vt3226_vnt_threshold;
- length = ARRAY_SIZE(vt3226_vnt_threshold);
- break;
- }
-
- if (!threshold)
- return -EINVAL;
-
- for (ed_inx = scanning ? 0 : length - 1; ed_inx > 0; ed_inx--) {
- if (priv->bb_pre_ed_rssi <= threshold[ed_inx].bb_pre_ed_rssi)
- break;
- }
-
- cr_201 = threshold[ed_inx].cr_201;
- cr_206 = threshold[ed_inx].cr_206;
-
- if (ed_inx == priv->bb_pre_ed_index && !scanning)
- return 0;
-
- priv->bb_pre_ed_index = ed_inx;
-
- dev_dbg(&priv->usb->dev, "%s bb_pre_ed_rssi %d\n",
- __func__, priv->bb_pre_ed_rssi);
-
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xc9, cr_201);
- if (ret)
- return ret;
-
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG, 0xce, cr_206);
-}
-
diff --git a/drivers/staging/vt6656/baseband.h b/drivers/staging/vt6656/baseband.h
deleted file mode 100644
index dce50a311f24..000000000000
--- a/drivers/staging/vt6656/baseband.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions to access baseband
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 5, 2002
- *
- * Revision History:
- * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-26-2003 Kyle Hsu : Add defines of packet type and TX rate.
- */
-
-#ifndef __BASEBAND_H__
-#define __BASEBAND_H__
-
-#include "device.h"
-
-#define PREAMBLE_LONG 0
-#define PREAMBLE_SHORT 1
-
-/*
- * Registers in the BASEBAND
- */
-#define BB_MAX_CONTEXT_SIZE 256
-
-#define C_SIFS_A 16 /* usec */
-#define C_SIFS_BG 10
-
-#define C_EIFS 80 /* usec */
-
-#define C_SLOT_SHORT 9 /* usec */
-#define C_SLOT_LONG 20
-
-#define C_CWMIN_A 15 /* slot time */
-#define C_CWMIN_B 31
-
-#define C_CWMAX 1023 /* slot time */
-
-/* 0:11A 1:11B 2:11G */
-#define BB_TYPE_11A 0
-#define BB_TYPE_11B 1
-#define BB_TYPE_11G 2
-
-/* 0:11a, 1:11b, 2:11gb (only CCK in BasicRate), 3:11ga (OFDM in BasicRate) */
-#define PK_TYPE_11A 0
-#define PK_TYPE_11B 1
-#define PK_TYPE_11GB 2
-#define PK_TYPE_11GA 3
-
-#define TOP_RATE_54M 0x80000000
-#define TOP_RATE_48M 0x40000000
-#define TOP_RATE_36M 0x20000000
-#define TOP_RATE_24M 0x10000000
-#define TOP_RATE_18M 0x08000000
-#define TOP_RATE_12M 0x04000000
-#define TOP_RATE_11M 0x02000000
-#define TOP_RATE_9M 0x01000000
-#define TOP_RATE_6M 0x00800000
-#define TOP_RATE_55M 0x00400000
-#define TOP_RATE_2M 0x00200000
-#define TOP_RATE_1M 0x00100000
-
-int vnt_set_short_slot_time(struct vnt_private *priv);
-int vnt_set_vga_gain_offset(struct vnt_private *priv, u8 data);
-int vnt_set_antenna_mode(struct vnt_private *priv, u8 antenna_mode);
-int vnt_vt3184_init(struct vnt_private *priv);
-int vnt_set_deep_sleep(struct vnt_private *priv);
-int vnt_exit_deep_sleep(struct vnt_private *priv);
-int vnt_update_pre_ed_threshold(struct vnt_private *priv, int scanning);
-
-#endif /* __BASEBAND_H__ */
diff --git a/drivers/staging/vt6656/card.c b/drivers/staging/vt6656/card.c
deleted file mode 100644
index b9dc0d13c00c..000000000000
--- a/drivers/staging/vt6656/card.c
+++ /dev/null
@@ -1,456 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Provide functions to setup NIC operation mode
- * Functions:
- * vnt_set_rspinf - Set RSPINF
- * vnt_update_ifs - Update slotTime,SIFS,DIFS, and EIFS
- * vnt_update_top_rates - Update BasicTopRate
- * vnt_add_basic_rate - Add to BasicRateSet
- * vnt_ofdm_min_rate - Check if any OFDM rate is in BasicRateSet
- * vnt_get_tsf_offset - Calculate TSFOffset
- * vnt_get_next_tbtt - Calculate Next Beacon TSF counter
- * vnt_reset_next_tbtt - Set NIC Beacon time
- * vnt_update_next_tbtt - Sync. NIC Beacon time
- * vnt_radio_power_off - Turn Off NIC Radio Power
- * vnt_radio_power_on - Turn On NIC Radio Power
- *
- * Revision History:
- * 06-10-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-26-2003 Kyle Hsu: Modify the definition type of dwIoBase.
- * 09-01-2003 Bryan YC Fan: Add vnt_update_ifs().
- *
- */
-
-#include <linux/bitops.h>
-#include <linux/errno.h>
-#include "device.h"
-#include "card.h"
-#include "baseband.h"
-#include "mac.h"
-#include "desc.h"
-#include "rf.h"
-#include "power.h"
-#include "key.h"
-#include "usbpipe.h"
-
-/* const u16 cw_rxbcntsf_off[MAX_RATE] =
- * {17, 34, 96, 192, 34, 23, 17, 11, 8, 5, 4, 3};
- */
-
-static const u16 cw_rxbcntsf_off[MAX_RATE] = {
- 192, 96, 34, 17, 34, 23, 17, 11, 8, 5, 4, 3
-};
-
-int vnt_set_channel(struct vnt_private *priv, u32 connection_channel)
-{
- int ret;
-
- if (connection_channel > CB_MAX_CHANNEL || !connection_channel)
- return -EINVAL;
-
- /* clear NAV */
- vnt_mac_reg_bits_on(priv, MAC_REG_MACCR, MACCR_CLRNAV);
-
- /* Set Channel[7] = 0 to tell H/W channel is changing now. */
- vnt_mac_reg_bits_off(priv, MAC_REG_CHANNEL,
- (BIT(7) | BIT(5) | BIT(4)));
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_SELECT_CHANNEL,
- connection_channel, 0, 0, NULL);
- if (ret)
- return ret;
-
- return vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_CHANNEL,
- (u8)(connection_channel | 0x80));
-}
-
-static const u8 vnt_rspinf_b_short_table[] = {
- 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x09, 0x00,
- 0x15, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x0b, 0x80
-};
-
-static const u8 vnt_rspinf_b_long_table[] = {
- 0x70, 0x00, 0x00, 0x00, 0x38, 0x00, 0x01, 0x00,
- 0x15, 0x00, 0x02, 0x00, 0x0b, 0x00, 0x03, 0x80
-};
-
-static const u8 vnt_rspinf_a_table[] = {
- 0x9b, 0x18, 0x9f, 0x10, 0x9a, 0x0a, 0x9e, 0x08, 0x99,
- 0x08, 0x9d, 0x04, 0x98, 0x04, 0x9c, 0x04, 0x9c, 0x04
-};
-
-static const u8 vnt_rspinf_gb_table[] = {
- 0x8b, 0x1e, 0x8f, 0x16, 0x8a, 0x12, 0x8e, 0x0e, 0x89,
- 0x0e, 0x8d, 0x0a, 0x88, 0x0a, 0x8c, 0x0a, 0x8c, 0x0a
-};
-
-int vnt_set_rspinf(struct vnt_private *priv, u8 bb_type)
-{
- const u8 *data;
- u16 len;
- int ret;
-
- if (priv->preamble_type) {
- data = vnt_rspinf_b_short_table;
- len = ARRAY_SIZE(vnt_rspinf_b_short_table);
- } else {
- data = vnt_rspinf_b_long_table;
- len = ARRAY_SIZE(vnt_rspinf_b_long_table);
- }
-
- /* RSPINF_b_1 to RSPINF_b_11 */
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_B_1,
- MESSAGE_REQUEST_MACREG, len, data);
- if (ret)
- return ret;
-
- if (bb_type == BB_TYPE_11A) {
- data = vnt_rspinf_a_table;
- len = ARRAY_SIZE(vnt_rspinf_a_table);
- } else {
- data = vnt_rspinf_gb_table;
- len = ARRAY_SIZE(vnt_rspinf_gb_table);
- }
-
- /* RSPINF_a_6 to RSPINF_a_72 */
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_RSPINF_A_6,
- MESSAGE_REQUEST_MACREG, len, data);
-}
-
-int vnt_update_ifs(struct vnt_private *priv)
-{
- u8 max_min = 0;
- u8 data[4];
- int ret;
-
- if (priv->packet_type == PK_TYPE_11A) {
- priv->slot = C_SLOT_SHORT;
- priv->sifs = C_SIFS_A;
- priv->difs = C_SIFS_A + 2 * C_SLOT_SHORT;
- max_min = 4;
- } else {
- priv->sifs = C_SIFS_BG;
-
- if (priv->short_slot_time) {
- priv->slot = C_SLOT_SHORT;
- max_min = 4;
- } else {
- priv->slot = C_SLOT_LONG;
- max_min = 5;
- }
-
- priv->difs = C_SIFS_BG + 2 * priv->slot;
- }
-
- priv->eifs = C_EIFS;
-
- data[0] = (u8)priv->sifs;
- data[1] = (u8)priv->difs;
- data[2] = (u8)priv->eifs;
- data[3] = (u8)priv->slot;
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_SIFS,
- MESSAGE_REQUEST_MACREG, 4, &data[0]);
- if (ret)
- return ret;
-
- max_min |= 0xa0;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_CWMAXMIN0,
- MESSAGE_REQUEST_MACREG, 1, &max_min);
-}
-
-void vnt_update_top_rates(struct vnt_private *priv)
-{
- int pos;
-
- pos = fls(priv->basic_rates & GENMASK(RATE_54M, RATE_6M));
- priv->top_ofdm_basic_rate = pos ? (pos - 1) : RATE_24M;
-
- pos = fls(priv->basic_rates & GENMASK(RATE_11M, RATE_1M));
- priv->top_cck_basic_rate = pos ? (pos - 1) : RATE_1M;
-}
-
-bool vnt_ofdm_min_rate(struct vnt_private *priv)
-{
- return priv->basic_rates & GENMASK(RATE_54M, RATE_6M) ? true : false;
-}
-
-u8 vnt_get_pkt_type(struct vnt_private *priv)
-{
- if (priv->bb_type == BB_TYPE_11A || priv->bb_type == BB_TYPE_11B)
- return (u8)priv->bb_type;
- else if (vnt_ofdm_min_rate(priv))
- return PK_TYPE_11GA;
- return PK_TYPE_11GB;
-}
-
-/*
- * Description: Calculate TSF offset of two TSF input
- * Get TSF Offset from RxBCN's TSF and local TSF
- *
- * Parameters:
- * In:
- * rx_rate - rx rate.
- * tsf1 - Rx BCN's TSF
- * tsf2 - Local TSF
- * Out:
- * none
- *
- * Return Value: TSF Offset value
- *
- */
-u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2)
-{
- return tsf1 - tsf2 - (u64)cw_rxbcntsf_off[rx_rate % MAX_RATE];
-}
-
-int vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate,
- u64 time_stamp, u64 local_tsf)
-{
- u64 tsf_offset = 0;
- u8 data[8];
-
- tsf_offset = vnt_get_tsf_offset(rx_rate, time_stamp, local_tsf);
-
- data[0] = (u8)tsf_offset;
- data[1] = (u8)(tsf_offset >> 8);
- data[2] = (u8)(tsf_offset >> 16);
- data[3] = (u8)(tsf_offset >> 24);
- data[4] = (u8)(tsf_offset >> 32);
- data[5] = (u8)(tsf_offset >> 40);
- data[6] = (u8)(tsf_offset >> 48);
- data[7] = (u8)(tsf_offset >> 56);
-
- return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT,
- MESSAGE_REQUEST_TSF, 0, 8, data);
-}
-
-/*
- * Description: Clear NIC TSF counter
- * Clear local TSF counter
- *
- * Parameters:
- * In:
- * priv - The adapter to be read
- *
- * Return Value: true if success; otherwise false
- *
- */
-bool vnt_clear_current_tsf(struct vnt_private *priv)
-{
- vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTRST);
-
- priv->current_tsf = 0;
-
- return true;
-}
-
-/*
- * Description: Read NIC TSF counter
- * Get NEXTTBTT from adjusted TSF and Beacon Interval
- *
- * Parameters:
- * In:
- * tsf - Current TSF counter
- * beacon_interval - Beacon Interval
- * Out:
- * tsf - Current TSF counter
- *
- * Return Value: TSF value of next Beacon
- *
- */
-u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval)
-{
- u32 beacon_int;
-
- beacon_int = beacon_interval * 1024;
-
- /* Next TBTT =
- * ((local_current_TSF / beacon_interval) + 1) * beacon_interval
- */
- if (beacon_int) {
- do_div(tsf, beacon_int);
- tsf += 1;
- tsf *= beacon_int;
- }
-
- return tsf;
-}
-
-int vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval)
-{
- u64 next_tbtt = 0;
- u8 data[8];
-
- vnt_clear_current_tsf(priv);
-
- next_tbtt = vnt_get_next_tbtt(next_tbtt, beacon_interval);
-
- data[0] = (u8)next_tbtt;
- data[1] = (u8)(next_tbtt >> 8);
- data[2] = (u8)(next_tbtt >> 16);
- data[3] = (u8)(next_tbtt >> 24);
- data[4] = (u8)(next_tbtt >> 32);
- data[5] = (u8)(next_tbtt >> 40);
- data[6] = (u8)(next_tbtt >> 48);
- data[7] = (u8)(next_tbtt >> 56);
-
- return vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT,
- MESSAGE_REQUEST_TBTT, 0, 8, data);
-}
-
-int vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf,
- u16 beacon_interval)
-{
- u8 data[8];
- int ret;
-
- tsf = vnt_get_next_tbtt(tsf, beacon_interval);
-
- data[0] = (u8)tsf;
- data[1] = (u8)(tsf >> 8);
- data[2] = (u8)(tsf >> 16);
- data[3] = (u8)(tsf >> 24);
- data[4] = (u8)(tsf >> 32);
- data[5] = (u8)(tsf >> 40);
- data[6] = (u8)(tsf >> 48);
- data[7] = (u8)(tsf >> 56);
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_SET_TSFTBTT,
- MESSAGE_REQUEST_TBTT, 0, 8, data);
- if (ret)
- return ret;
-
- dev_dbg(&priv->usb->dev, "%s TBTT: %8llx\n", __func__, tsf);
- return 0;
-}
-
-/*
- * Description: Turn off Radio power
- *
- * Parameters:
- * In:
- * priv - The adapter to be turned off
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-int vnt_radio_power_off(struct vnt_private *priv)
-{
- int ret = 0;
-
- switch (priv->rf_type) {
- case RF_AL2230:
- case RF_AL2230S:
- case RF_VT3226:
- case RF_VT3226D0:
- ret = vnt_mac_reg_bits_off(priv, MAC_REG_SOFTPWRCTL,
- (SOFTPWRCTL_SWPE2 |
- SOFTPWRCTL_SWPE3));
- break;
- }
-
- if (ret)
- goto end;
-
- ret = vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_RXON);
- if (ret)
- goto end;
-
- ret = vnt_set_deep_sleep(priv);
- if (ret)
- goto end;
-
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD);
-
-end:
- return ret;
-}
-
-/*
- * Description: Turn on Radio power
- *
- * Parameters:
- * In:
- * priv - The adapter to be turned on
- * Out:
- * none
- *
- * Return Value: true if success; otherwise false
- *
- */
-int vnt_radio_power_on(struct vnt_private *priv)
-{
- int ret = 0;
-
- ret = vnt_exit_deep_sleep(priv);
- if (ret)
- return ret;
-
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_RXON);
- if (ret)
- return ret;
-
- switch (priv->rf_type) {
- case RF_AL2230:
- case RF_AL2230S:
- case RF_VT3226:
- case RF_VT3226D0:
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_SOFTPWRCTL,
- (SOFTPWRCTL_SWPE2 |
- SOFTPWRCTL_SWPE3));
- if (ret)
- return ret;
- }
-
- return vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1, GPIO3_INTMD);
-}
-
-int vnt_set_bss_mode(struct vnt_private *priv)
-{
- int ret;
- unsigned char type = priv->bb_type;
- unsigned char data = 0;
- unsigned char bb_vga_2_3 = 0x00;
-
- ret = vnt_mac_set_bb_type(priv, type);
- if (ret)
- return ret;
-
- priv->packet_type = vnt_get_pkt_type(priv);
-
- if (priv->bb_type == BB_TYPE_11A) {
- data = 0x03;
- bb_vga_2_3 = 0x10;
- } else if (priv->bb_type == BB_TYPE_11B) {
- data = 0x02;
- } else if (priv->bb_type == BB_TYPE_11G) {
- data = 0x08;
- }
-
- if (data) {
- ret = vnt_control_out_u8(priv, MESSAGE_REQUEST_BBREG,
- 0x88, data);
- if (ret)
- return ret;
- }
-
- ret = vnt_update_ifs(priv);
- if (ret)
- return ret;
-
- ret = vnt_set_rspinf(priv, priv->bb_type);
- if (ret)
- return ret;
-
- priv->bb_vga[2] = bb_vga_2_3;
- priv->bb_vga[3] = bb_vga_2_3;
-
- return vnt_set_vga_gain_offset(priv, priv->bb_vga[0]);
-}
diff --git a/drivers/staging/vt6656/card.h b/drivers/staging/vt6656/card.h
deleted file mode 100644
index eb01f7cc871f..000000000000
--- a/drivers/staging/vt6656/card.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Provide functions to setup NIC operation mode
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- */
-
-#ifndef __CARD_H__
-#define __CARD_H__
-#include "device.h"
-
-/* init card type */
-
-#define CB_MAX_CHANNEL_24G 14
-#define CB_MAX_CHANNEL_5G 42 /* add channel9(5045MHz), 41==>42 */
-#define CB_MAX_CHANNEL (CB_MAX_CHANNEL_24G + CB_MAX_CHANNEL_5G)
-
-struct vnt_private;
-
-int vnt_set_channel(struct vnt_private *priv, u32 connection_channel);
-int vnt_set_rspinf(struct vnt_private *priv, u8 bb_type);
-int vnt_update_ifs(struct vnt_private *priv);
-void vnt_update_top_rates(struct vnt_private *priv);
-bool vnt_ofdm_min_rate(struct vnt_private *priv);
-int vnt_adjust_tsf(struct vnt_private *priv, u8 rx_rate,
- u64 time_stamp, u64 local_tsf);
-bool vnt_clear_current_tsf(struct vnt_private *priv);
-int vnt_reset_next_tbtt(struct vnt_private *priv, u16 beacon_interval);
-int vnt_update_next_tbtt(struct vnt_private *priv, u64 tsf,
- u16 beacon_interval);
-u64 vnt_get_next_tbtt(u64 tsf, u16 beacon_interval);
-u64 vnt_get_tsf_offset(u8 rx_rate, u64 tsf1, u64 tsf2);
-int vnt_radio_power_off(struct vnt_private *priv);
-int vnt_radio_power_on(struct vnt_private *priv);
-u8 vnt_get_pkt_type(struct vnt_private *priv);
-int vnt_set_bss_mode(struct vnt_private *priv);
-
-#endif /* __CARD_H__ */
diff --git a/drivers/staging/vt6656/channel.c b/drivers/staging/vt6656/channel.c
deleted file mode 100644
index 413e2fc4a50d..000000000000
--- a/drivers/staging/vt6656/channel.c
+++ /dev/null
@@ -1,77 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Channel number mapping
- *
- * Author: Lucas Lin
- *
- * Date: Dec 24, 2004
- *
- *
- *
- * Revision History:
- * 01-18-2005 RobertYu: remove the for loop searching in
- * ChannelValid, change ChannelRuleTab
- * to lookup-type, reorder table items.
- *
- *
- */
-
-#include "device.h"
-#include "channel.h"
-#include "rf.h"
-
-static struct ieee80211_rate vnt_rates_bg[] = {
- { .bitrate = 10, .hw_value = RATE_1M },
- { .bitrate = 20, .hw_value = RATE_2M },
- { .bitrate = 55, .hw_value = RATE_5M },
- { .bitrate = 110, .hw_value = RATE_11M },
- { .bitrate = 60, .hw_value = RATE_6M },
- { .bitrate = 90, .hw_value = RATE_9M },
- { .bitrate = 120, .hw_value = RATE_12M },
- { .bitrate = 180, .hw_value = RATE_18M },
- { .bitrate = 240, .hw_value = RATE_24M },
- { .bitrate = 360, .hw_value = RATE_36M },
- { .bitrate = 480, .hw_value = RATE_48M },
- { .bitrate = 540, .hw_value = RATE_54M },
-};
-
-static struct ieee80211_channel vnt_channels_2ghz[] = {
- { .center_freq = 2412, .hw_value = 1 },
- { .center_freq = 2417, .hw_value = 2 },
- { .center_freq = 2422, .hw_value = 3 },
- { .center_freq = 2427, .hw_value = 4 },
- { .center_freq = 2432, .hw_value = 5 },
- { .center_freq = 2437, .hw_value = 6 },
- { .center_freq = 2442, .hw_value = 7 },
- { .center_freq = 2447, .hw_value = 8 },
- { .center_freq = 2452, .hw_value = 9 },
- { .center_freq = 2457, .hw_value = 10 },
- { .center_freq = 2462, .hw_value = 11 },
- { .center_freq = 2467, .hw_value = 12 },
- { .center_freq = 2472, .hw_value = 13 },
- { .center_freq = 2484, .hw_value = 14 }
-};
-
-static struct ieee80211_supported_band vnt_supported_2ghz_band = {
- .channels = vnt_channels_2ghz,
- .n_channels = ARRAY_SIZE(vnt_channels_2ghz),
- .bitrates = vnt_rates_bg,
- .n_bitrates = ARRAY_SIZE(vnt_rates_bg),
-};
-
-void vnt_init_bands(struct vnt_private *priv)
-{
- struct ieee80211_channel *ch;
- int i;
-
- ch = vnt_channels_2ghz;
- for (i = 0; i < ARRAY_SIZE(vnt_channels_2ghz); i++) {
- ch[i].max_power = VNT_RF_MAX_POWER;
- ch[i].flags = IEEE80211_CHAN_NO_HT40;
- }
- priv->hw->wiphy->bands[NL80211_BAND_2GHZ] =
- &vnt_supported_2ghz_band;
-}
diff --git a/drivers/staging/vt6656/channel.h b/drivers/staging/vt6656/channel.h
deleted file mode 100644
index 723660e40310..000000000000
--- a/drivers/staging/vt6656/channel.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Country Regulation Rules header file
- *
- * Author: Lucas Lin
- *
- * Date: Dec 23, 2004
- *
- */
-
-#ifndef _CHANNEL_H_
-#define _CHANNEL_H_
-
-#include "device.h"
-
-void vnt_init_bands(struct vnt_private *priv);
-
-#endif /* _CHANNEL_H_ */
diff --git a/drivers/staging/vt6656/desc.h b/drivers/staging/vt6656/desc.h
deleted file mode 100644
index c13561e528db..000000000000
--- a/drivers/staging/vt6656/desc.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:The header file of descriptor
- *
- * Revision History:
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- */
-
-#ifndef __DESC_H__
-#define __DESC_H__
-
-#include <linux/bits.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-
-/* max transmit or receive buffer size */
-#define CB_MAX_BUF_SIZE 2900U /* NOTE: must be multiple of 4 */
-
-#define MAX_TOTAL_SIZE_WITH_ALL_HEADERS CB_MAX_BUF_SIZE
-
-#define MAX_INTERRUPT_SIZE 32
-
-#define CB_MAX_RX_DESC 128 /* max # of descriptors */
-#define CB_MIN_RX_DESC 16 /* min # of RX descriptors */
-#define CB_MAX_TX_DESC 128 /* max # of descriptors */
-#define CB_MIN_TX_DESC 16 /* min # of TX descriptors */
-
-/*
- * bits in the RSR register
- */
-#define RSR_ADDRBROAD BIT(7)
-#define RSR_ADDRMULTI BIT(6)
-#define RSR_ADDRUNI 0x00
-#define RSR_IVLDTYP BIT(5) /* invalid packet type */
-#define RSR_IVLDLEN BIT(4) /* invalid len (> 2312 byte) */
-#define RSR_BSSIDOK BIT(3)
-#define RSR_CRCOK BIT(2)
-#define RSR_BCNSSIDOK BIT(1)
-#define RSR_ADDROK BIT(0)
-
-/*
- * bits in the new RSR register
- */
-#define NEWRSR_DECRYPTOK BIT(4)
-#define NEWRSR_CFPIND BIT(3)
-#define NEWRSR_HWUTSF BIT(2)
-#define NEWRSR_BCNHITAID BIT(1)
-#define NEWRSR_BCNHITAID0 BIT(0)
-
-/*
- * bits in the TSR register
- */
-#define TSR_RETRYTMO BIT(3)
-#define TSR_TMO BIT(2)
-#define TSR_ACKDATA BIT(1)
-#define TSR_VALID BIT(0)
-
-#define FIFOCTL_AUTO_FB_1 0x1000
-#define FIFOCTL_AUTO_FB_0 0x0800
-#define FIFOCTL_GRPACK 0x0400
-#define FIFOCTL_11GA 0x0300
-#define FIFOCTL_11GB 0x0200
-#define FIFOCTL_11B 0x0100
-#define FIFOCTL_11A 0x0000
-#define FIFOCTL_RTS 0x0080
-#define FIFOCTL_ISDMA0 0x0040
-#define FIFOCTL_GENINT 0x0020
-#define FIFOCTL_TMOEN 0x0010
-#define FIFOCTL_LRETRY 0x0008
-#define FIFOCTL_CRCDIS 0x0004
-#define FIFOCTL_NEEDACK 0x0002
-#define FIFOCTL_LHEAD 0x0001
-
-/* WMAC definition Frag Control */
-#define FRAGCTL_AES 0x0300
-#define FRAGCTL_TKIP 0x0200
-#define FRAGCTL_LEGACY 0x0100
-#define FRAGCTL_NONENCRYPT 0x0000
-#define FRAGCTL_ENDFRAG 0x0003
-#define FRAGCTL_MIDFRAG 0x0002
-#define FRAGCTL_STAFRAG 0x0001
-#define FRAGCTL_NONFRAG 0x0000
-
-#endif /* __DESC_H__ */
diff --git a/drivers/staging/vt6656/device.h b/drivers/staging/vt6656/device.h
deleted file mode 100644
index ca974d61d3f4..000000000000
--- a/drivers/staging/vt6656/device.h
+++ /dev/null
@@ -1,386 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC Data structure
- *
- * Author: Tevin Chen
- *
- * Date: Mar 17, 1997
- *
- */
-
-#ifndef __DEVICE_H__
-#define __DEVICE_H__
-
-#include <linux/bits.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/firmware.h>
-#include <linux/suspend.h>
-#include <linux/if_arp.h>
-#include <linux/wireless.h>
-#include <linux/timer.h>
-#include <linux/usb.h>
-#include <linux/crc32.h>
-#include <net/mac80211.h>
-
-#ifdef SIOCETHTOOL
-#define DEVICE_ETHTOOL_IOCTL_SUPPORT
-#include <linux/ethtool.h>
-#else
-#undef DEVICE_ETHTOOL_IOCTL_SUPPORT
-#endif
-
-#define RATE_1M 0
-#define RATE_2M 1
-#define RATE_5M 2
-#define RATE_11M 3
-#define RATE_6M 4
-#define RATE_9M 5
-#define RATE_12M 6
-#define RATE_18M 7
-#define RATE_24M 8
-#define RATE_36M 9
-#define RATE_48M 10
-#define RATE_54M 11
-#define RATE_AUTO 12
-
-#define MAX_RATE 12
-#define VNT_B_RATES (BIT(RATE_1M) | BIT(RATE_2M) |\
- BIT(RATE_5M) | BIT(RATE_11M))
-
-/*
- * device specific
- */
-
-#include "wcmd.h"
-#include "desc.h"
-#include "key.h"
-#include "card.h"
-
-#define VNT_USB_VENDOR_ID 0x160a
-#define VNT_USB_PRODUCT_ID 0x3184
-
-#define DEVICE_NAME "vt6656"
-#define DEVICE_FULL_DRV_NAM "VIA Networking Wireless LAN USB Driver"
-
-#define DEVICE_VERSION "mac80211"
-
-#define FIRMWARE_VERSION 0x133 /* version 1.51 */
-#define FIRMWARE_NAME "vntwusb.fw"
-#define FIRMWARE_CHUNK_SIZE 0x400
-
-#define MAX_UINTS 8
-#define OPTION_DEFAULT { [0 ... MAX_UINTS - 1] = -1}
-
-#define DUPLICATE_RX_CACHE_LENGTH 5
-
-#define AUTO_FB_NONE 0
-#define AUTO_FB_0 1
-#define AUTO_FB_1 2
-
-#define FB_RATE0 0
-#define FB_RATE1 1
-
-/* Antenna Mode */
-#define ANT_A 0
-#define ANT_B 1
-#define ANT_DIVERSITY 2
-#define ANT_RXD_TXA 3
-#define ANT_RXD_TXB 4
-#define ANT_UNKNOWN 0xFF
-#define ANT_TXA 0
-#define ANT_TXB 1
-#define ANT_RXA 2
-#define ANT_RXB 3
-
-#define BB_VGA_LEVEL 4
-#define BB_VGA_CHANGE_THRESHOLD 3
-
-#define EEP_MAX_CONTEXT_SIZE 256
-
-/* Contents in the EEPROM */
-#define EEP_OFS_PAR 0x0
-#define EEP_OFS_ANTENNA 0x17
-#define EEP_OFS_RADIOCTL 0x18
-#define EEP_OFS_RFTYPE 0x1b
-#define EEP_OFS_MINCHANNEL 0x1c
-#define EEP_OFS_MAXCHANNEL 0x1d
-#define EEP_OFS_SIGNATURE 0x1e
-#define EEP_OFS_ZONETYPE 0x1f
-#define EEP_OFS_RFTABLE 0x20
-#define EEP_OFS_PWR_CCK 0x20
-#define EEP_OFS_SETPT_CCK 0x21
-#define EEP_OFS_PWR_OFDMG 0x23
-
-#define EEP_OFS_CALIB_TX_IQ 0x24
-#define EEP_OFS_CALIB_TX_DC 0x25
-#define EEP_OFS_CALIB_RX_IQ 0x26
-
-#define EEP_OFS_MAJOR_VER 0x2e
-#define EEP_OFS_MINOR_VER 0x2f
-
-#define EEP_OFS_CCK_PWR_TBL 0x30
-#define EEP_OFS_OFDM_PWR_TBL 0x40
-#define EEP_OFS_OFDMA_PWR_TBL 0x50
-
-/* Bits in EEP_OFS_ANTENNA */
-#define EEP_ANTENNA_MAIN BIT(0)
-#define EEP_ANTENNA_AUX BIT(1)
-#define EEP_ANTINV BIT(2)
-
-/* Bits in EEP_OFS_RADIOCTL */
-#define EEP_RADIOCTL_ENABLE BIT(7)
-
-/* control commands */
-#define MESSAGE_TYPE_READ 0x1
-#define MESSAGE_TYPE_WRITE 0x0
-#define MESSAGE_TYPE_LOCK_OR 0x2
-#define MESSAGE_TYPE_LOCK_AND 0x3
-#define MESSAGE_TYPE_WRITE_MASK 0x4
-#define MESSAGE_TYPE_CARDINIT 0x5
-#define MESSAGE_TYPE_INIT_RSP 0x6
-#define MESSAGE_TYPE_MACSHUTDOWN 0x7
-#define MESSAGE_TYPE_SETKEY 0x8
-#define MESSAGE_TYPE_CLRKEYENTRY 0x9
-#define MESSAGE_TYPE_WRITE_MISCFF 0xa
-#define MESSAGE_TYPE_SET_ANTMD 0xb
-#define MESSAGE_TYPE_SELECT_CHANNEL 0xc
-#define MESSAGE_TYPE_SET_TSFTBTT 0xd
-#define MESSAGE_TYPE_SET_SSTIFS 0xe
-#define MESSAGE_TYPE_CHANGE_BBTYPE 0xf
-#define MESSAGE_TYPE_DISABLE_PS 0x10
-#define MESSAGE_TYPE_WRITE_IFRF 0x11
-
-/* command read/write(index) */
-#define MESSAGE_REQUEST_MEM 0x1
-#define MESSAGE_REQUEST_BBREG 0x2
-#define MESSAGE_REQUEST_MACREG 0x3
-#define MESSAGE_REQUEST_EEPROM 0x4
-#define MESSAGE_REQUEST_TSF 0x5
-#define MESSAGE_REQUEST_TBTT 0x6
-#define MESSAGE_REQUEST_BBAGC 0x7
-#define MESSAGE_REQUEST_VERSION 0x8
-#define MESSAGE_REQUEST_RF_INIT 0x9
-#define MESSAGE_REQUEST_RF_INIT2 0xa
-#define MESSAGE_REQUEST_RF_CH0 0xb
-#define MESSAGE_REQUEST_RF_CH1 0xc
-#define MESSAGE_REQUEST_RF_CH2 0xd
-
-/* USB registers */
-#define USB_REG4 0x604
-
-#define DEVICE_INIT_COLD 0x0 /* cold init */
-#define DEVICE_INIT_RESET 0x1 /* reset init or Dx to D0 power remain */
-#define DEVICE_INIT_DXPL 0x2 /* Dx to D0 power lost init */
-
-/* Device init */
-struct vnt_cmd_card_init {
- u8 init_class;
- u8 exist_sw_net_addr;
- u8 sw_net_addr[6];
- u8 short_retry_limit;
- u8 long_retry_limit;
-};
-
-struct vnt_rsp_card_init {
- u8 status;
- u8 net_addr[6];
- u8 rf_type;
- u8 min_channel;
- u8 max_channel;
-};
-
-/* USB */
-
-/*
- * Enum of context types for SendPacket
- */
-enum {
- CONTEXT_DATA_PACKET = 0,
- CONTEXT_BEACON_PACKET
-};
-
-struct vnt_rx_header {
- u32 wbk_status;
- u8 rx_sts;
- u8 rx_rate;
- u16 pay_load_len;
-} __packed;
-
-struct vnt_rx_tail {
- __le64 tsf_time;
- u8 sq;
- u8 new_rsr;
- u8 rssi;
- u8 rsr;
- u8 sq_3;
-} __packed;
-
-/* RCB (Receive Control Block) */
-struct vnt_rcb {
- void *priv;
- struct urb *urb;
- struct sk_buff *skb;
-};
-
-/* used to track bulk out irps */
-struct vnt_usb_send_context {
- void *priv;
- struct sk_buff *skb;
- void *tx_buffer;
- u32 frame_len;
- u16 tx_hdr_size;
- u16 tx_rate;
- u8 type;
- u8 pkt_no;
- u8 pkt_type;
- bool in_use;
-};
-
-/*
- * Structure to keep track of USB interrupt packets
- */
-struct vnt_interrupt_buffer {
- u8 *data_buf;
-};
-
-/* flags for options */
-#define DEVICE_FLAGS_UNPLUG 0
-#define DEVICE_FLAGS_DISCONNECTED 1
-
-struct vnt_private {
- /* mac80211 */
- struct ieee80211_hw *hw;
- struct ieee80211_vif *vif;
- u8 mac_hw;
- /* netdev */
- struct usb_device *usb;
- struct usb_interface *intf;
-
- u64 tsf_time;
-
- u32 rx_buf_sz;
- int mc_list_count;
-
- spinlock_t lock; /* prepare tx USB URB */
- struct mutex usb_lock; /* USB control messages */
-
- unsigned long flags;
-
- /* USB */
- struct urb *interrupt_urb;
- u32 int_interval;
-
- /* Variables to track resources for the BULK In Pipe */
- struct vnt_rcb *rcb[CB_MAX_RX_DESC];
- u32 num_rcb;
-
- /* Variables to track resources for the BULK Out Pipe */
- struct vnt_usb_send_context *tx_context[CB_MAX_TX_DESC];
- struct usb_anchor tx_submitted;
- u32 num_tx_context;
-
- /* Variables to track resources for the Interrupt In Pipe */
- struct vnt_interrupt_buffer int_buf;
-
- /* Version control */
- u16 firmware_version;
- u8 local_id;
- u8 rf_type;
- u8 bb_rx_conf;
-
- struct vnt_cmd_card_init init_command;
- struct vnt_rsp_card_init init_response;
- u8 current_net_addr[ETH_ALEN] __aligned(2);
- u8 permanent_net_addr[ETH_ALEN] __aligned(2);
-
- u8 exist_sw_net_addr;
-
- u64 current_tsf;
-
- /* 802.11 MAC specific */
- u32 current_rssi;
-
- /* Antenna Diversity */
- int tx_rx_ant_inv;
- u32 rx_antenna_sel;
- u8 rx_antenna_mode;
- u8 tx_antenna_mode;
- u8 radio_ctl;
-
- /* IFS & Cw */
- u32 sifs; /* Current SIFS */
- u32 difs; /* Current DIFS */
- u32 eifs; /* Current EIFS */
- u32 slot; /* Current SlotTime */
-
- /* Rate */
- u8 bb_type; /* 0: 11A, 1:11B, 2:11G */
- u8 packet_type; /* 0:11a 1:11b 2:11gb 3:11ga */
- u32 basic_rates;
- u8 top_ofdm_basic_rate;
- u8 top_cck_basic_rate;
-
- u8 eeprom[EEP_MAX_CONTEXT_SIZE]; /*u32 alignment */
-
- u8 preamble_type;
-
- /* For RF Power table */
- u8 cck_pwr;
- u8 ofdm_pwr_g;
- u8 ofdm_pwr_a;
- u8 power;
- u8 cck_pwr_tbl[14];
- u8 ofdm_pwr_tbl[14];
- u8 ofdm_a_pwr_tbl[42];
-
- u16 tx_rate_fb0;
- u16 tx_rate_fb1;
-
- enum nl80211_iftype op_mode;
-
- int short_slot_time;
-
- /* Power save */
- u16 current_aid;
-
- /* Beacon related */
- u16 seq_counter;
-
- enum vnt_cmd_state command_state;
-
- enum vnt_cmd command;
-
- /* 802.11 counter */
-
- enum vnt_cmd cmd_queue[CMD_Q_SIZE];
- u32 cmd_dequeue_idx;
- u32 cmd_enqueue_idx;
- u32 free_cmd_queue;
- int cmd_running;
-
- unsigned long key_entry_inuse;
-
- u8 auto_fb_ctrl;
-
- /* For Update BaseBand VGA Gain Offset */
- u8 bb_vga[BB_VGA_LEVEL];
-
- u8 bb_pre_ed_rssi;
- u8 bb_pre_ed_index;
-
- /* command timer */
- struct delayed_work run_command_work;
-
- struct ieee80211_low_level_stats low_stats;
-};
-
-int vnt_init(struct vnt_private *priv);
-
-#endif
diff --git a/drivers/staging/vt6656/key.c b/drivers/staging/vt6656/key.c
deleted file mode 100644
index bdc5f30c4f9d..000000000000
--- a/drivers/staging/vt6656/key.c
+++ /dev/null
@@ -1,142 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions for 802.11i Key management
- *
- * Author: Jerry Chen
- *
- * Date: May 29, 2003
- *
- * Functions:
- *
- * Revision History:
- *
- */
-
-#include "mac.h"
-#include "key.h"
-#include "usbpipe.h"
-
-int vnt_key_init_table(struct vnt_private *priv)
-{
- u8 i;
- u8 data[MAX_KEY_TABLE];
-
- for (i = 0; i < MAX_KEY_TABLE; i++)
- data[i] = i;
-
- return vnt_control_out(priv, MESSAGE_TYPE_CLRKEYENTRY,
- 0, 0, ARRAY_SIZE(data), data);
-}
-
-static int vnt_set_keymode(struct ieee80211_hw *hw, u8 *mac_addr,
- struct ieee80211_key_conf *key, u32 key_type,
- u32 mode)
-{
- struct vnt_private *priv = hw->priv;
- u8 broadcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
- u16 key_mode = 0;
- u32 entry = 0;
- u8 *bssid;
- u8 key_inx = key->keyidx;
- u8 i;
-
- if (mac_addr)
- bssid = mac_addr;
- else
- bssid = &broadcast[0];
-
- if (key_type != VNT_KEY_DEFAULTKEY) {
- for (i = 0; i < (MAX_KEY_TABLE - 1); i++) {
- if (!test_bit(i, &priv->key_entry_inuse)) {
- set_bit(i, &priv->key_entry_inuse);
-
- key->hw_key_idx = i;
- entry = key->hw_key_idx;
- break;
- }
- }
- }
-
- switch (key_type) {
- case VNT_KEY_DEFAULTKEY:
- /* default key last entry */
- entry = MAX_KEY_TABLE - 1;
- key->hw_key_idx = entry;
- fallthrough;
- case VNT_KEY_GROUP_ADDRESS:
- key_mode = mode | (mode << 4);
- break;
- case VNT_KEY_GROUP:
- key_mode = mode << 4;
- break;
- case VNT_KEY_PAIRWISE:
- key_mode |= mode;
- key_inx = 4;
- break;
- default:
- return -EINVAL;
- }
-
- key_mode |= key_type;
-
- if (mode == KEY_CTL_WEP) {
- if (key->keylen == WLAN_KEY_LEN_WEP40)
- key->key[15] &= 0x7f;
- if (key->keylen == WLAN_KEY_LEN_WEP104)
- key->key[15] |= 0x80;
- }
-
- return vnt_mac_set_keyentry(priv, key_mode, entry,
- key_inx, bssid, key->key);
-}
-
-int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- struct ieee80211_vif *vif, struct ieee80211_key_conf *key)
-{
- struct vnt_private *priv = hw->priv;
- u8 *mac_addr = NULL;
- u8 key_dec_mode = 0;
-
- if (sta)
- mac_addr = &sta->addr[0];
-
- switch (key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY,
- KEY_CTL_WEP);
-
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-
- return vnt_set_keymode(hw, mac_addr, key, VNT_KEY_DEFAULTKEY,
- KEY_CTL_WEP);
-
- case WLAN_CIPHER_SUITE_TKIP:
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-
- key_dec_mode = KEY_CTL_TKIP;
-
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- if (priv->local_id <= MAC_REVISION_A1)
- return -EOPNOTSUPP;
-
- key_dec_mode = KEY_CTL_CCMP;
-
- key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
- return vnt_set_keymode(hw, mac_addr, key, VNT_KEY_PAIRWISE,
- key_dec_mode);
-
- return vnt_set_keymode(hw, mac_addr, key,
- VNT_KEY_GROUP_ADDRESS, key_dec_mode);
-}
diff --git a/drivers/staging/vt6656/key.h b/drivers/staging/vt6656/key.h
deleted file mode 100644
index 6f1d5b4f6da7..000000000000
--- a/drivers/staging/vt6656/key.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Implement functions for 802.11i Key management
- *
- * Author: Jerry Chen
- *
- * Date: May 29, 2003
- *
- */
-
-#ifndef __KEY_H__
-#define __KEY_H__
-
-#include "device.h"
-
-#define MAX_KEY_TABLE 11
-
-#define KEY_CTL_WEP 0x00
-#define KEY_CTL_NONE 0x01
-#define KEY_CTL_TKIP 0x02
-#define KEY_CTL_CCMP 0x03
-
-#define VNT_KEY_ONFLY_ALL 0x4000
-#define VNT_KEY_ONFLY 0x8000
-#define VNT_KEY_ALLGROUP 0x04
-#define VNT_KEY_GROUP 0x40
-#define VNT_KEY_PAIRWISE VNT_KEY_ONFLY
-#define VNT_KEY_GROUP_ADDRESS (VNT_KEY_ALLGROUP | VNT_KEY_GROUP)
-#define VNT_KEY_DEFAULTKEY (VNT_KEY_GROUP_ADDRESS | VNT_KEY_ONFLY |\
- VNT_KEY_ONFLY_ALL)
-
-int vnt_key_init_table(struct vnt_private *priv);
-
-int vnt_set_keys(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
- struct ieee80211_vif *vif, struct ieee80211_key_conf *key);
-
-#endif /* __KEY_H__ */
diff --git a/drivers/staging/vt6656/mac.c b/drivers/staging/vt6656/mac.c
deleted file mode 100644
index 49430c0a99b8..000000000000
--- a/drivers/staging/vt6656/mac.c
+++ /dev/null
@@ -1,183 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC routines
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- * Functions:
- *
- * Revision History:
- */
-
-#include <linux/etherdevice.h>
-
-#include "desc.h"
-#include "mac.h"
-#include "usbpipe.h"
-
-int vnt_mac_set_filter(struct vnt_private *priv, u64 mc_filter)
-{
- __le64 le_mc = cpu_to_le64(mc_filter);
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_MAR0,
- MESSAGE_REQUEST_MACREG, sizeof(le_mc),
- (u8 *)&le_mc);
-}
-
-int vnt_mac_shutdown(struct vnt_private *priv)
-{
- return vnt_control_out(priv, MESSAGE_TYPE_MACSHUTDOWN, 0, 0, 0, NULL);
-}
-
-int vnt_mac_set_bb_type(struct vnt_private *priv, u8 type)
-{
- u8 data[2];
-
- data[0] = type;
- data[1] = EN_CFG_BB_TYPE_MASK;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG0,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data),
- data);
-}
-
-int vnt_mac_disable_keyentry(struct vnt_private *priv, u8 entry_idx)
-{
- return vnt_control_out(priv, MESSAGE_TYPE_CLRKEYENTRY, 0, 0,
- sizeof(entry_idx), &entry_idx);
-}
-
-int vnt_mac_set_keyentry(struct vnt_private *priv, u16 key_ctl, u32 entry_idx,
- u32 key_idx, u8 *addr, u8 *key)
-{
- struct vnt_mac_set_key set_key;
- u16 offset;
-
- offset = MISCFIFO_KEYETRY0;
- offset += entry_idx * MISCFIFO_KEYENTRYSIZE;
-
- set_key.u.write.key_ctl = cpu_to_le16(key_ctl);
- ether_addr_copy(set_key.u.write.addr, addr);
-
- /* swap over swap[0] and swap[1] to get correct write order */
- swap(set_key.u.swap[0], set_key.u.swap[1]);
-
- memcpy(set_key.key, key, WLAN_KEY_LEN_CCMP);
-
- dev_dbg(&priv->usb->dev, "offset %d key ctl %d set key %24ph\n",
- offset, key_ctl, (u8 *)&set_key);
-
- return vnt_control_out(priv, MESSAGE_TYPE_SETKEY, offset,
- (u16)key_idx, sizeof(struct vnt_mac_set_key),
- (u8 *)&set_key);
-}
-
-int vnt_mac_reg_bits_off(struct vnt_private *priv, u8 reg_ofs, u8 bits)
-{
- u8 data[2];
-
- data[0] = 0;
- data[1] = bits;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, reg_ofs,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_reg_bits_on(struct vnt_private *priv, u8 reg_ofs, u8 bits)
-{
- u8 data[2];
-
- data[0] = bits;
- data[1] = bits;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, reg_ofs,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_write_word(struct vnt_private *priv, u8 reg_ofs, u16 word)
-{
- u8 data[2];
-
- data[0] = (u8)(word & 0xff);
- data[1] = (u8)(word >> 8);
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, reg_ofs,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_set_bssid_addr(struct vnt_private *priv, u8 *addr)
-{
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_BSSID0,
- MESSAGE_REQUEST_MACREG, ETH_ALEN, addr);
-}
-
-int vnt_mac_enable_protect_mode(struct vnt_private *priv)
-{
- u8 data[2];
-
- data[0] = EN_CFG_PROTECT_MD;
- data[1] = EN_CFG_PROTECT_MD;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG0,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_disable_protect_mode(struct vnt_private *priv)
-{
- u8 data[2];
-
- data[0] = 0;
- data[1] = EN_CFG_PROTECT_MD;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG0,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_enable_barker_preamble_mode(struct vnt_private *priv)
-{
- u8 data[2];
-
- data[0] = EN_CFG_BARKER_PREAM;
- data[1] = EN_CFG_BARKER_PREAM;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG2,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_disable_barker_preamble_mode(struct vnt_private *priv)
-{
- u8 data[2];
-
- data[0] = 0;
- data[1] = EN_CFG_BARKER_PREAM;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_ENCFG2,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_set_beacon_interval(struct vnt_private *priv, u16 interval)
-{
- u8 data[2];
-
- data[0] = (u8)(interval & 0xff);
- data[1] = (u8)(interval >> 8);
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE, MAC_REG_BI,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
-
-int vnt_mac_set_led(struct vnt_private *priv, u8 state, u8 led)
-{
- u8 data[2];
-
- data[0] = led;
- data[1] = state;
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_MASK, MAC_REG_PAPEDELAY,
- MESSAGE_REQUEST_MACREG, ARRAY_SIZE(data), data);
-}
diff --git a/drivers/staging/vt6656/mac.h b/drivers/staging/vt6656/mac.h
deleted file mode 100644
index 0ac845bd3c5a..000000000000
--- a/drivers/staging/vt6656/mac.h
+++ /dev/null
@@ -1,373 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: MAC routines
- *
- * Author: Tevin Chen
- *
- * Date: May 21, 1996
- *
- * Revision History:
- * 07-01-2003 Bryan YC Fan: Re-write codes to support VT3253 spec.
- * 08-25-2003 Kyle Hsu: Porting MAC functions from sim53.
- * 09-03-2003 Bryan YC Fan: Add MACvDisableProtectMD & MACvEnableProtectMD
- */
-
-#ifndef __MAC_H__
-#define __MAC_H__
-
-#include <linux/bits.h>
-#include "device.h"
-
-#define REV_ID_VT3253_A0 0x00
-#define REV_ID_VT3253_A1 0x01
-#define REV_ID_VT3253_B0 0x08
-#define REV_ID_VT3253_B1 0x09
-
-/* Registers in the MAC */
-#define MAC_REG_BISTCMD 0x04
-#define MAC_REG_BISTSR0 0x05
-#define MAC_REG_BISTSR1 0x06
-#define MAC_REG_BISTSR2 0x07
-#define MAC_REG_I2MCSR 0x08
-#define MAC_REG_I2MTGID 0x09
-#define MAC_REG_I2MTGAD 0x0a
-#define MAC_REG_I2MCFG 0x0b
-#define MAC_REG_I2MDIPT 0x0c
-#define MAC_REG_I2MDOPT 0x0e
-#define MAC_REG_USBSUS 0x0f
-
-#define MAC_REG_LOCALID 0x14
-#define MAC_REG_TESTCFG 0x15
-#define MAC_REG_JUMPER0 0x16
-#define MAC_REG_JUMPER1 0x17
-#define MAC_REG_TMCTL 0x18
-#define MAC_REG_TMDATA0 0x1c
-#define MAC_REG_TMDATA1 0x1d
-#define MAC_REG_TMDATA2 0x1e
-#define MAC_REG_TMDATA3 0x1f
-
-/* MAC Parameter related */
-#define MAC_REG_LRT 0x20
-#define MAC_REG_SRT 0x21
-#define MAC_REG_SIFS 0x22
-#define MAC_REG_DIFS 0x23
-#define MAC_REG_EIFS 0x24
-#define MAC_REG_SLOT 0x25
-#define MAC_REG_BI 0x26
-#define MAC_REG_CWMAXMIN0 0x28
-#define MAC_REG_LINKOFFTOTM 0x2a
-#define MAC_REG_SWTMOT 0x2b
-#define MAC_REG_RTSOKCNT 0x2c
-#define MAC_REG_RTSFAILCNT 0x2d
-#define MAC_REG_ACKFAILCNT 0x2e
-#define MAC_REG_FCSERRCNT 0x2f
-
-/* TSF Related */
-#define MAC_REG_TSFCNTR 0x30
-#define MAC_REG_NEXTTBTT 0x38
-#define MAC_REG_TSFOFST 0x40
-#define MAC_REG_TFTCTL 0x48
-
-/* WMAC Control/Status Related */
-#define MAC_REG_ENCFG0 0x4c
-#define MAC_REG_ENCFG1 0x4d
-#define MAC_REG_ENCFG2 0x4e
-
-#define MAC_REG_CFG 0x50
-#define MAC_REG_TEST 0x52
-#define MAC_REG_HOSTCR 0x54
-#define MAC_REG_MACCR 0x55
-#define MAC_REG_RCR 0x56
-#define MAC_REG_TCR 0x57
-#define MAC_REG_IMR 0x58
-#define MAC_REG_ISR 0x5c
-#define MAC_REG_ISR1 0x5d
-
-/* Power Saving Related */
-#define MAC_REG_PSCFG 0x60
-#define MAC_REG_PSCTL 0x61
-#define MAC_REG_PSPWRSIG 0x62
-#define MAC_REG_BBCR13 0x63
-#define MAC_REG_AIDATIM 0x64
-#define MAC_REG_PWBT 0x66
-#define MAC_REG_WAKEOKTMR 0x68
-#define MAC_REG_CALTMR 0x69
-#define MAC_REG_SYNSPACCNT 0x6a
-#define MAC_REG_WAKSYNOPT 0x6b
-
-/* Baseband/IF Control Group */
-#define MAC_REG_BBREGCTL 0x6c
-#define MAC_REG_CHANNEL 0x6d
-#define MAC_REG_BBREGADR 0x6e
-#define MAC_REG_BBREGDATA 0x6f
-#define MAC_REG_IFREGCTL 0x70
-#define MAC_REG_IFDATA 0x71
-#define MAC_REG_ITRTMSET 0x74
-#define MAC_REG_PAPEDELAY 0x77
-#define MAC_REG_SOFTPWRCTL 0x78
-#define MAC_REG_SOFTPWRCTL2 0x79
-#define MAC_REG_GPIOCTL0 0x7a
-#define MAC_REG_GPIOCTL1 0x7b
-
-/* MiscFF PIO related */
-#define MAC_REG_MISCFFNDEX 0xbc
-#define MAC_REG_MISCFFCTL 0xbe
-#define MAC_REG_MISCFFDATA 0xc0
-
-/* MAC Configuration Group */
-#define MAC_REG_PAR0 0xc4
-#define MAC_REG_PAR4 0xc8
-#define MAC_REG_BSSID0 0xcc
-#define MAC_REG_BSSID4 0xd0
-#define MAC_REG_MAR0 0xd4
-#define MAC_REG_MAR4 0xd8
-
-/* MAC RSPPKT INFO Group */
-#define MAC_REG_RSPINF_B_1 0xdC
-#define MAC_REG_RSPINF_B_2 0xe0
-#define MAC_REG_RSPINF_B_5 0xe4
-#define MAC_REG_RSPINF_B_11 0xe8
-#define MAC_REG_RSPINF_A_6 0xec
-#define MAC_REG_RSPINF_A_9 0xee
-#define MAC_REG_RSPINF_A_12 0xf0
-#define MAC_REG_RSPINF_A_18 0xf2
-#define MAC_REG_RSPINF_A_24 0xf4
-#define MAC_REG_RSPINF_A_36 0xf6
-#define MAC_REG_RSPINF_A_48 0xf8
-#define MAC_REG_RSPINF_A_54 0xfa
-#define MAC_REG_RSPINF_A_72 0xfc
-
-/* Bits in the I2MCFG EEPROM register */
-#define I2MCFG_BOUNDCTL BIT(7)
-#define I2MCFG_WAITCTL BIT(5)
-#define I2MCFG_SCLOECTL BIT(4)
-#define I2MCFG_WBUSYCTL BIT(3)
-#define I2MCFG_NORETRY BIT(2)
-#define I2MCFG_I2MLDSEQ BIT(1)
-#define I2MCFG_I2CMFAST BIT(0)
-
-/* Bits in the I2MCSR EEPROM register */
-#define I2MCSR_EEMW BIT(7)
-#define I2MCSR_EEMR BIT(6)
-#define I2MCSR_AUTOLD BIT(3)
-#define I2MCSR_NACK BIT(1)
-#define I2MCSR_DONE BIT(0)
-
-/* Bits in the TMCTL register */
-#define TMCTL_TSUSP BIT(2)
-#define TMCTL_TMD BIT(1)
-#define TMCTL_TE BIT(0)
-
-/* Bits in the TFTCTL register */
-#define TFTCTL_HWUTSF BIT(7)
-#define TFTCTL_TBTTSYNC BIT(6)
-#define TFTCTL_HWUTSFEN BIT(5)
-#define TFTCTL_TSFCNTRRD BIT(4)
-#define TFTCTL_TBTTSYNCEN BIT(3)
-#define TFTCTL_TSFSYNCEN BIT(2)
-#define TFTCTL_TSFCNTRST BIT(1)
-#define TFTCTL_TSFCNTREN BIT(0)
-
-/* Bits in the EnhanceCFG_0 register */
-#define EN_CFG_BB_TYPE_A 0x00
-#define EN_CFG_BB_TYPE_B BIT(0)
-#define EN_CFG_BB_TYPE_G BIT(1)
-#define EN_CFG_BB_TYPE_MASK (EN_CFG_BB_TYPE_B | EN_CFG_BB_TYPE_G)
-#define EN_CFG_PROTECT_MD BIT(5)
-
-/* Bits in the EnhanceCFG_1 register */
-#define EN_CFG_BCN_SUS_IND BIT(0)
-#define EN_CFG_BCN_SUS_CLR BIT(1)
-
-/* Bits in the EnhanceCFG_2 register */
-#define EN_CFG_NXTBTTCFPSTR BIT(0)
-#define EN_CFG_BARKER_PREAM BIT(1)
-#define EN_CFG_PKT_BURST_MD BIT(2)
-
-/* Bits in the CFG register */
-#define CFG_TKIPOPT BIT(7)
-#define CFG_RXDMAOPT BIT(6)
-#define CFG_TMOT_SW BIT(5)
-#define CFG_TMOT_HWLONG BIT(4)
-#define CFG_TMOT_HW 0x00
-#define CFG_CFPENDOPT BIT(3)
-#define CFG_BCNSUSEN BIT(2)
-#define CFG_NOTXTIMEOUT BIT(1)
-#define CFG_NOBUFOPT BIT(0)
-
-/* Bits in the TEST register */
-#define TEST_LBEXT BIT(7)
-#define TEST_LBINT BIT(6)
-#define TEST_LBNONE 0x00
-#define TEST_SOFTINT BIT(5)
-#define TEST_CONTTX BIT(4)
-#define TEST_TXPE BIT(3)
-#define TEST_NAVDIS BIT(2)
-#define TEST_NOCTS BIT(1)
-#define TEST_NOACK BIT(0)
-
-/* Bits in the HOSTCR register */
-#define HOSTCR_TXONST BIT(7)
-#define HOSTCR_RXONST BIT(6)
-#define HOSTCR_ADHOC BIT(5)
-#define HOSTCR_AP BIT(4)
-#define HOSTCR_TXON BIT(3)
-#define HOSTCR_RXON BIT(2)
-#define HOSTCR_MACEN BIT(1)
-#define HOSTCR_SOFTRST BIT(0)
-
-/* Bits in the MACCR register */
-#define MACCR_SYNCFLUSHOK BIT(2)
-#define MACCR_SYNCFLUSH BIT(1)
-#define MACCR_CLRNAV BIT(0)
-
-/* Bits in the RCR register */
-#define RCR_SSID BIT(7)
-#define RCR_RXALLTYPE BIT(6)
-#define RCR_UNICAST BIT(5)
-#define RCR_BROADCAST BIT(4)
-#define RCR_MULTICAST BIT(3)
-#define RCR_WPAERR BIT(2)
-#define RCR_ERRCRC BIT(1)
-#define RCR_BSSID BIT(0)
-
-/* Bits in the TCR register */
-#define TCR_SYNCDCFOPT BIT(1)
-#define TCR_AUTOBCNTX BIT(0)
-
-/* ISR1 */
-#define ISR_GPIO3 BIT(6)
-#define ISR_RXNOBUF BIT(3)
-#define ISR_MIBNEARFULL BIT(2)
-#define ISR_SOFTINT BIT(1)
-#define ISR_FETALERR BIT(0)
-
-#define LEDSTS_STS 0x06
-#define LEDSTS_TMLEN 0x78
-#define LEDSTS_OFF 0x00
-#define LEDSTS_ON 0x02
-#define LEDSTS_SLOW 0x04
-#define LEDSTS_INTER 0x06
-
-/* ISR0 */
-#define ISR_WATCHDOG BIT(7)
-#define ISR_SOFTTIMER BIT(6)
-#define ISR_GPIO0 BIT(5)
-#define ISR_TBTT BIT(4)
-#define ISR_RXDMA0 BIT(3)
-#define ISR_BNTX BIT(2)
-#define ISR_ACTX BIT(0)
-
-/* Bits in the PSCFG register */
-#define PSCFG_PHILIPMD BIT(6)
-#define PSCFG_WAKECALEN BIT(5)
-#define PSCFG_WAKETMREN BIT(4)
-#define PSCFG_BBPSPROG BIT(3)
-#define PSCFG_WAKESYN BIT(2)
-#define PSCFG_SLEEPSYN BIT(1)
-#define PSCFG_AUTOSLEEP BIT(0)
-
-/* Bits in the PSCTL register */
-#define PSCTL_WAKEDONE BIT(5)
-#define PSCTL_PS BIT(4)
-#define PSCTL_GO2DOZE BIT(3)
-#define PSCTL_LNBCN BIT(2)
-#define PSCTL_ALBCN BIT(1)
-#define PSCTL_PSEN BIT(0)
-
-/* Bits in the PSPWSIG register */
-#define PSSIG_WPE3 BIT(7)
-#define PSSIG_WPE2 BIT(6)
-#define PSSIG_WPE1 BIT(5)
-#define PSSIG_WRADIOPE BIT(4)
-#define PSSIG_SPE3 BIT(3)
-#define PSSIG_SPE2 BIT(2)
-#define PSSIG_SPE1 BIT(1)
-#define PSSIG_SRADIOPE BIT(0)
-
-/* Bits in the BBREGCTL register */
-#define BBREGCTL_DONE BIT(2)
-#define BBREGCTL_REGR BIT(1)
-#define BBREGCTL_REGW BIT(0)
-
-/* Bits in the IFREGCTL register */
-#define IFREGCTL_DONE BIT(2)
-#define IFREGCTL_IFRF BIT(1)
-#define IFREGCTL_REGW BIT(0)
-
-/* Bits in the SOFTPWRCTL register */
-#define SOFTPWRCTL_RFLEOPT BIT(3)
-#define SOFTPWRCTL_TXPEINV BIT(1)
-#define SOFTPWRCTL_SWPECTI BIT(0)
-#define SOFTPWRCTL_SWPAPE BIT(5)
-#define SOFTPWRCTL_SWCALEN BIT(4)
-#define SOFTPWRCTL_SWRADIO_PE BIT(3)
-#define SOFTPWRCTL_SWPE2 BIT(2)
-#define SOFTPWRCTL_SWPE1 BIT(1)
-#define SOFTPWRCTL_SWPE3 BIT(0)
-
-/* Bits in the GPIOCTL1 register */
-#define GPIO3_MD BIT(5)
-#define GPIO3_DATA BIT(6)
-#define GPIO3_INTMD BIT(7)
-
-/* Bits in the MISCFFCTL register */
-#define MISCFFCTL_WRITE BIT(0)
-
-/* Loopback mode */
-#define MAC_LB_EXT BIT(1)
-#define MAC_LB_INTERNAL BIT(0)
-#define MAC_LB_NONE 0x00
-
-/* Ethernet address filter type */
-#define PKT_TYPE_NONE 0x00 /* turn off receiver */
-#define PKT_TYPE_ALL_MULTICAST BIT(7)
-#define PKT_TYPE_PROMISCUOUS BIT(6)
-#define PKT_TYPE_DIRECTED BIT(5) /* obselete */
-#define PKT_TYPE_BROADCAST BIT(4)
-#define PKT_TYPE_MULTICAST BIT(3)
-#define PKT_TYPE_ERROR_WPA BIT(2)
-#define PKT_TYPE_ERROR_CRC BIT(1)
-#define PKT_TYPE_BSSID BIT(0)
-
-#define DEFAULT_BI 0x200
-
-/* MiscFIFO Offset */
-#define MISCFIFO_KEYETRY0 32
-#define MISCFIFO_KEYENTRYSIZE 22
-
-#define MAC_REVISION_A0 0x00
-#define MAC_REVISION_A1 0x01
-
-struct vnt_mac_set_key {
- union {
- struct {
- u8 addr[ETH_ALEN];
- __le16 key_ctl;
- } write __packed;
- u32 swap[2];
- } u;
- u8 key[WLAN_KEY_LEN_CCMP];
-} __packed;
-
-int vnt_mac_set_filter(struct vnt_private *priv, u64 mc_filter);
-int vnt_mac_shutdown(struct vnt_private *priv);
-int vnt_mac_set_bb_type(struct vnt_private *priv, u8 type);
-int vnt_mac_disable_keyentry(struct vnt_private *priv, u8 entry_idx);
-int vnt_mac_set_keyentry(struct vnt_private *priv, u16 key_ctl, u32 entry_idx,
- u32 key_idx, u8 *addr, u8 *key);
-int vnt_mac_reg_bits_off(struct vnt_private *priv, u8 reg_ofs, u8 bits);
-int vnt_mac_reg_bits_on(struct vnt_private *priv, u8 reg_ofs, u8 bits);
-int vnt_mac_write_word(struct vnt_private *priv, u8 reg_ofs, u16 word);
-int vnt_mac_set_bssid_addr(struct vnt_private *priv, u8 *addr);
-int vnt_mac_enable_protect_mode(struct vnt_private *priv);
-int vnt_mac_disable_protect_mode(struct vnt_private *priv);
-int vnt_mac_enable_barker_preamble_mode(struct vnt_private *priv);
-int vnt_mac_disable_barker_preamble_mode(struct vnt_private *priv);
-int vnt_mac_set_beacon_interval(struct vnt_private *priv, u16 interval);
-int vnt_mac_set_led(struct vnt_private *privpriv, u8 state, u8 led);
-
-#endif /* __MAC_H__ */
diff --git a/drivers/staging/vt6656/main_usb.c b/drivers/staging/vt6656/main_usb.c
deleted file mode 100644
index 4f09e733e7a8..000000000000
--- a/drivers/staging/vt6656/main_usb.c
+++ /dev/null
@@ -1,1121 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: driver entry for initial, open, close, tx and rx.
- *
- * Author: Lyndon Chen
- *
- * Date: Dec 8, 2005
- *
- * Functions:
- *
- * vt6656_probe - module initial (insmod) driver entry
- * vnt_free_tx_bufs - free tx buffer function
- * vnt_init_registers- initial MAC & BBP & RF internal registers.
- *
- * Revision History:
- */
-#undef __NO_VERSION__
-
-#include <linux/bits.h>
-#include <linux/etherdevice.h>
-#include <linux/file.h>
-#include <linux/kernel.h>
-#include "device.h"
-#include "card.h"
-#include "baseband.h"
-#include "mac.h"
-#include "power.h"
-#include "wcmd.h"
-#include "rxtx.h"
-#include "rf.h"
-#include "usbpipe.h"
-#include "channel.h"
-
-/*
- * define module options
- */
-
-/* version information */
-#define DRIVER_AUTHOR \
- "VIA Networking Technologies, Inc., <lyndonchen@vntek.com.tw>"
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION(DEVICE_FULL_DRV_NAM);
-
-#define RX_DESC_DEF0 64
-static int vnt_rx_buffers = RX_DESC_DEF0;
-module_param_named(rx_buffers, vnt_rx_buffers, int, 0644);
-MODULE_PARM_DESC(rx_buffers, "Number of receive usb rx buffers");
-
-#define TX_DESC_DEF0 64
-static int vnt_tx_buffers = TX_DESC_DEF0;
-module_param_named(tx_buffers, vnt_tx_buffers, int, 0644);
-MODULE_PARM_DESC(tx_buffers, "Number of receive usb tx buffers");
-
-#define RTS_THRESH_DEF 2347
-#define FRAG_THRESH_DEF 2346
-
-/* BasebandType[] baseband type selected
- * 0: indicate 802.11a type
- * 1: indicate 802.11b type
- * 2: indicate 802.11g type
- */
-
-#define BBP_TYPE_DEF 2
-
-/*
- * Static vars definitions
- */
-
-static const struct usb_device_id vt6656_table[] = {
- {USB_DEVICE(VNT_USB_VENDOR_ID, VNT_USB_PRODUCT_ID)},
- {}
-};
-
-static void vnt_set_options(struct vnt_private *priv)
-{
- /* Set number of TX buffers */
- if (vnt_tx_buffers < CB_MIN_TX_DESC || vnt_tx_buffers > CB_MAX_TX_DESC)
- priv->num_tx_context = TX_DESC_DEF0;
- else
- priv->num_tx_context = vnt_tx_buffers;
-
- /* Set number of RX buffers */
- if (vnt_rx_buffers < CB_MIN_RX_DESC || vnt_rx_buffers > CB_MAX_RX_DESC)
- priv->num_rcb = RX_DESC_DEF0;
- else
- priv->num_rcb = vnt_rx_buffers;
-
- priv->op_mode = NL80211_IFTYPE_UNSPECIFIED;
- priv->bb_type = BBP_TYPE_DEF;
- priv->packet_type = priv->bb_type;
- priv->preamble_type = PREAMBLE_LONG;
- priv->exist_sw_net_addr = false;
-}
-
-static int vnt_download_firmware(struct vnt_private *priv)
-{
- struct device *dev = &priv->usb->dev;
- const struct firmware *fw;
- u16 length;
- int ii;
- int ret = 0;
-
- dev_dbg(dev, "---->Download firmware\n");
-
- ret = request_firmware(&fw, FIRMWARE_NAME, dev);
- if (ret) {
- dev_err(dev, "firmware file %s request failed (%d)\n",
- FIRMWARE_NAME, ret);
- goto end;
- }
-
- for (ii = 0; ii < fw->size; ii += FIRMWARE_CHUNK_SIZE) {
- length = min_t(int, fw->size - ii, FIRMWARE_CHUNK_SIZE);
-
- ret = vnt_control_out(priv, 0, 0x1200 + ii, 0x0000, length,
- fw->data + ii);
- if (ret)
- goto free_fw;
-
- dev_dbg(dev, "Download firmware...%d %zu\n", ii, fw->size);
- }
-
-free_fw:
- release_firmware(fw);
-end:
- return ret;
-}
-
-static int vnt_firmware_branch_to_sram(struct vnt_private *priv)
-{
- dev_dbg(&priv->usb->dev, "---->Branch to Sram\n");
-
- return vnt_control_out(priv, 1, 0x1200, 0x0000, 0, NULL);
-}
-
-static int vnt_check_firmware_version(struct vnt_private *priv)
-{
- int ret = 0;
-
- ret = vnt_control_in(priv, MESSAGE_TYPE_READ, 0,
- MESSAGE_REQUEST_VERSION, 2,
- (u8 *)&priv->firmware_version);
- if (ret) {
- dev_dbg(&priv->usb->dev,
- "Could not get firmware version: %d.\n", ret);
- goto end;
- }
-
- dev_dbg(&priv->usb->dev, "Firmware Version [%04x]\n",
- priv->firmware_version);
-
- if (priv->firmware_version == 0xFFFF) {
- dev_dbg(&priv->usb->dev, "In Loader.\n");
- ret = -EINVAL;
- goto end;
- }
-
- if (priv->firmware_version < FIRMWARE_VERSION) {
- /* branch to loader for download new firmware */
- ret = vnt_firmware_branch_to_sram(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev,
- "Could not branch to SRAM: %d.\n", ret);
- } else {
- ret = -EINVAL;
- }
- }
-
-end:
- return ret;
-}
-
-/*
- * initialization of MAC & BBP registers
- */
-static int vnt_init_registers(struct vnt_private *priv)
-{
- int ret;
- struct vnt_cmd_card_init *init_cmd = &priv->init_command;
- struct vnt_rsp_card_init *init_rsp = &priv->init_response;
- u8 antenna;
- int ii;
- u8 tmp;
- u8 calib_tx_iq = 0, calib_tx_dc = 0, calib_rx_iq = 0;
-
- dev_dbg(&priv->usb->dev, "---->INIbInitAdapter. [%d][%d]\n",
- DEVICE_INIT_COLD, priv->packet_type);
-
- ret = vnt_check_firmware_version(priv);
- if (ret) {
- ret = vnt_download_firmware(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev,
- "Could not download firmware: %d.\n", ret);
- goto end;
- }
-
- ret = vnt_firmware_branch_to_sram(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev,
- "Could not branch to SRAM: %d.\n", ret);
- goto end;
- }
- }
-
- ret = vnt_vt3184_init(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev, "vnt_vt3184_init fail\n");
- goto end;
- }
-
- init_cmd->init_class = DEVICE_INIT_COLD;
- init_cmd->exist_sw_net_addr = priv->exist_sw_net_addr;
- for (ii = 0; ii < ARRAY_SIZE(init_cmd->sw_net_addr); ii++)
- init_cmd->sw_net_addr[ii] = priv->current_net_addr[ii];
- init_cmd->short_retry_limit = priv->hw->wiphy->retry_short;
- init_cmd->long_retry_limit = priv->hw->wiphy->retry_long;
-
- /* issue card_init command to device */
- ret = vnt_control_out(priv, MESSAGE_TYPE_CARDINIT, 0, 0,
- sizeof(struct vnt_cmd_card_init),
- (u8 *)init_cmd);
- if (ret) {
- dev_dbg(&priv->usb->dev, "Issue Card init fail\n");
- goto end;
- }
-
- ret = vnt_control_in(priv, MESSAGE_TYPE_INIT_RSP, 0, 0,
- sizeof(struct vnt_rsp_card_init),
- (u8 *)init_rsp);
- if (ret) {
- dev_dbg(&priv->usb->dev, "Cardinit request in status fail!\n");
- goto end;
- }
-
- /* local ID for AES functions */
- ret = vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_LOCALID,
- MESSAGE_REQUEST_MACREG, 1, &priv->local_id);
- if (ret)
- goto end;
-
- /* do MACbSoftwareReset in MACvInitialize */
-
- priv->top_ofdm_basic_rate = RATE_24M;
- priv->top_cck_basic_rate = RATE_1M;
-
- /* target to IF pin while programming to RF chip */
- priv->power = 0xFF;
-
- priv->cck_pwr = priv->eeprom[EEP_OFS_PWR_CCK];
- priv->ofdm_pwr_g = priv->eeprom[EEP_OFS_PWR_OFDMG];
- /* load power table */
- for (ii = 0; ii < ARRAY_SIZE(priv->cck_pwr_tbl); ii++) {
- priv->cck_pwr_tbl[ii] =
- priv->eeprom[ii + EEP_OFS_CCK_PWR_TBL];
- if (priv->cck_pwr_tbl[ii] == 0)
- priv->cck_pwr_tbl[ii] = priv->cck_pwr;
-
- priv->ofdm_pwr_tbl[ii] =
- priv->eeprom[ii + EEP_OFS_OFDM_PWR_TBL];
- if (priv->ofdm_pwr_tbl[ii] == 0)
- priv->ofdm_pwr_tbl[ii] = priv->ofdm_pwr_g;
- }
-
- /*
- * original zonetype is USA, but custom zonetype is Europe,
- * then need to recover 12, 13, 14 channels with 11 channel
- */
- for (ii = 11; ii < ARRAY_SIZE(priv->cck_pwr_tbl); ii++) {
- priv->cck_pwr_tbl[ii] = priv->cck_pwr_tbl[10];
- priv->ofdm_pwr_tbl[ii] = priv->ofdm_pwr_tbl[10];
- }
-
- priv->ofdm_pwr_a = 0x34; /* same as RFbMA2829SelectChannel */
-
- /* load OFDM A power table */
- for (ii = 0; ii < CB_MAX_CHANNEL_5G; ii++) {
- priv->ofdm_a_pwr_tbl[ii] =
- priv->eeprom[ii + EEP_OFS_OFDMA_PWR_TBL];
-
- if (priv->ofdm_a_pwr_tbl[ii] == 0)
- priv->ofdm_a_pwr_tbl[ii] = priv->ofdm_pwr_a;
- }
-
- antenna = priv->eeprom[EEP_OFS_ANTENNA];
-
- if (antenna & EEP_ANTINV)
- priv->tx_rx_ant_inv = true;
- else
- priv->tx_rx_ant_inv = false;
-
- antenna &= (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
-
- if (antenna == 0) /* if not set default is both */
- antenna = (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN);
-
- if (antenna == (EEP_ANTENNA_AUX | EEP_ANTENNA_MAIN)) {
- priv->tx_antenna_mode = ANT_B;
- priv->rx_antenna_sel = 1;
-
- if (priv->tx_rx_ant_inv)
- priv->rx_antenna_mode = ANT_A;
- else
- priv->rx_antenna_mode = ANT_B;
- } else {
- priv->rx_antenna_sel = 0;
-
- if (antenna & EEP_ANTENNA_AUX) {
- priv->tx_antenna_mode = ANT_A;
-
- if (priv->tx_rx_ant_inv)
- priv->rx_antenna_mode = ANT_B;
- else
- priv->rx_antenna_mode = ANT_A;
- } else {
- priv->tx_antenna_mode = ANT_B;
-
- if (priv->tx_rx_ant_inv)
- priv->rx_antenna_mode = ANT_A;
- else
- priv->rx_antenna_mode = ANT_B;
- }
- }
-
- /* Set initial antenna mode */
- ret = vnt_set_antenna_mode(priv, priv->rx_antenna_mode);
- if (ret)
- goto end;
-
- /* default Auto Mode */
- priv->bb_type = BB_TYPE_11G;
-
- /* get RFType */
- priv->rf_type = init_rsp->rf_type;
-
- /* load vt3266 calibration parameters in EEPROM */
- if (priv->rf_type == RF_VT3226D0) {
- if ((priv->eeprom[EEP_OFS_MAJOR_VER] == 0x1) &&
- (priv->eeprom[EEP_OFS_MINOR_VER] >= 0x4)) {
- calib_tx_iq = priv->eeprom[EEP_OFS_CALIB_TX_IQ];
- calib_tx_dc = priv->eeprom[EEP_OFS_CALIB_TX_DC];
- calib_rx_iq = priv->eeprom[EEP_OFS_CALIB_RX_IQ];
- if (calib_tx_iq || calib_tx_dc || calib_rx_iq) {
- /* CR255, enable TX/RX IQ and
- * DC compensation mode
- */
- ret = vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xff, 0x03);
- if (ret)
- goto end;
-
- /* CR251, TX I/Q Imbalance Calibration */
- ret = vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xfb, calib_tx_iq);
- if (ret)
- goto end;
-
- /* CR252, TX DC-Offset Calibration */
- ret = vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xfC, calib_tx_dc);
- if (ret)
- goto end;
-
- /* CR253, RX I/Q Imbalance Calibration */
- ret = vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xfd, calib_rx_iq);
- if (ret)
- goto end;
- } else {
- /* CR255, turn off
- * BB Calibration compensation
- */
- ret = vnt_control_out_u8(priv,
- MESSAGE_REQUEST_BBREG,
- 0xff, 0x0);
- if (ret)
- goto end;
- }
- }
- }
-
- /* get permanent network address */
- memcpy(priv->permanent_net_addr, init_rsp->net_addr, 6);
- ether_addr_copy(priv->current_net_addr, priv->permanent_net_addr);
-
- /* if exist SW network address, use it */
- dev_dbg(&priv->usb->dev, "Network address = %pM\n",
- priv->current_net_addr);
-
- priv->radio_ctl = priv->eeprom[EEP_OFS_RADIOCTL];
-
- if ((priv->radio_ctl & EEP_RADIOCTL_ENABLE) != 0) {
- ret = vnt_control_in(priv, MESSAGE_TYPE_READ,
- MAC_REG_GPIOCTL1, MESSAGE_REQUEST_MACREG,
- 1, &tmp);
- if (ret)
- goto end;
-
- if ((tmp & GPIO3_DATA) == 0) {
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL1,
- GPIO3_INTMD);
- } else {
- ret = vnt_mac_reg_bits_off(priv, MAC_REG_GPIOCTL1,
- GPIO3_INTMD);
- }
-
- if (ret)
- goto end;
- }
-
- ret = vnt_mac_set_led(priv, LEDSTS_TMLEN, 0x38);
- if (ret)
- goto end;
-
- ret = vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_SLOW);
- if (ret)
- goto end;
-
- ret = vnt_mac_reg_bits_on(priv, MAC_REG_GPIOCTL0, BIT(0));
- if (ret)
- goto end;
-
- ret = vnt_radio_power_on(priv);
- if (ret)
- goto end;
-
- dev_dbg(&priv->usb->dev, "<----INIbInitAdapter Exit\n");
-
-end:
- return ret;
-}
-
-static void vnt_free_tx_bufs(struct vnt_private *priv)
-{
- struct vnt_usb_send_context *tx_context;
- int ii;
-
- usb_kill_anchored_urbs(&priv->tx_submitted);
-
- for (ii = 0; ii < priv->num_tx_context; ii++) {
- tx_context = priv->tx_context[ii];
- if (!tx_context)
- continue;
-
- kfree(tx_context);
- }
-}
-
-static void vnt_free_rx_bufs(struct vnt_private *priv)
-{
- struct vnt_rcb *rcb;
- int ii;
-
- for (ii = 0; ii < priv->num_rcb; ii++) {
- rcb = priv->rcb[ii];
- if (!rcb)
- continue;
-
- /* deallocate URBs */
- if (rcb->urb) {
- usb_kill_urb(rcb->urb);
- usb_free_urb(rcb->urb);
- }
-
- /* deallocate skb */
- if (rcb->skb)
- dev_kfree_skb(rcb->skb);
-
- kfree(rcb);
- }
-}
-
-static void vnt_free_int_bufs(struct vnt_private *priv)
-{
- kfree(priv->int_buf.data_buf);
-}
-
-static int vnt_alloc_bufs(struct vnt_private *priv)
-{
- int ret;
- struct vnt_usb_send_context *tx_context;
- struct vnt_rcb *rcb;
- int ii;
-
- init_usb_anchor(&priv->tx_submitted);
-
- for (ii = 0; ii < priv->num_tx_context; ii++) {
- tx_context = kmalloc(sizeof(*tx_context), GFP_KERNEL);
- if (!tx_context) {
- ret = -ENOMEM;
- goto free_tx;
- }
-
- priv->tx_context[ii] = tx_context;
- tx_context->priv = priv;
- tx_context->pkt_no = ii;
- tx_context->in_use = false;
- }
-
- for (ii = 0; ii < priv->num_rcb; ii++) {
- priv->rcb[ii] = kzalloc(sizeof(*priv->rcb[ii]), GFP_KERNEL);
- if (!priv->rcb[ii]) {
- ret = -ENOMEM;
- goto free_rx_tx;
- }
-
- rcb = priv->rcb[ii];
-
- rcb->priv = priv;
-
- /* allocate URBs */
- rcb->urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!rcb->urb) {
- ret = -ENOMEM;
- goto free_rx_tx;
- }
-
- rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
- if (!rcb->skb) {
- ret = -ENOMEM;
- goto free_rx_tx;
- }
- /* submit rx urb */
- ret = vnt_submit_rx_urb(priv, rcb);
- if (ret)
- goto free_rx_tx;
- }
-
- priv->interrupt_urb = usb_alloc_urb(0, GFP_KERNEL);
- if (!priv->interrupt_urb) {
- ret = -ENOMEM;
- goto free_rx_tx;
- }
-
- priv->int_buf.data_buf = kmalloc(MAX_INTERRUPT_SIZE, GFP_KERNEL);
- if (!priv->int_buf.data_buf) {
- ret = -ENOMEM;
- goto free_rx_tx_urb;
- }
-
- return 0;
-
-free_rx_tx_urb:
- usb_free_urb(priv->interrupt_urb);
-free_rx_tx:
- vnt_free_rx_bufs(priv);
-free_tx:
- vnt_free_tx_bufs(priv);
- return ret;
-}
-
-static void vnt_tx_80211(struct ieee80211_hw *hw,
- struct ieee80211_tx_control *control,
- struct sk_buff *skb)
-{
- struct vnt_private *priv = hw->priv;
-
- if (vnt_tx_packet(priv, skb))
- ieee80211_free_txskb(hw, skb);
-}
-
-static int vnt_start(struct ieee80211_hw *hw)
-{
- int ret;
- struct vnt_private *priv = hw->priv;
-
- priv->rx_buf_sz = MAX_TOTAL_SIZE_WITH_ALL_HEADERS;
-
- ret = vnt_alloc_bufs(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev, "vnt_alloc_bufs fail...\n");
- goto err;
- }
-
- clear_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags);
-
- ret = vnt_init_registers(priv);
- if (ret) {
- dev_dbg(&priv->usb->dev, " init register fail\n");
- goto free_all;
- }
-
- ret = vnt_key_init_table(priv);
- if (ret)
- goto free_all;
-
- priv->int_interval = 1; /* bInterval is set to 1 */
-
- ret = vnt_start_interrupt_urb(priv);
- if (ret)
- goto free_all;
-
- ieee80211_wake_queues(hw);
-
- return 0;
-
-free_all:
- vnt_free_rx_bufs(priv);
- vnt_free_tx_bufs(priv);
- vnt_free_int_bufs(priv);
-
- usb_kill_urb(priv->interrupt_urb);
- usb_free_urb(priv->interrupt_urb);
-err:
- return ret;
-}
-
-static void vnt_stop(struct ieee80211_hw *hw, bool suspend)
-{
- struct vnt_private *priv = hw->priv;
- int i;
-
- if (!priv)
- return;
-
- for (i = 0; i < MAX_KEY_TABLE; i++)
- vnt_mac_disable_keyentry(priv, i);
-
- /* clear all keys */
- priv->key_entry_inuse = 0;
-
- if (!test_bit(DEVICE_FLAGS_UNPLUG, &priv->flags))
- vnt_mac_shutdown(priv);
-
- ieee80211_stop_queues(hw);
-
- set_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags);
-
- cancel_delayed_work_sync(&priv->run_command_work);
-
- priv->cmd_running = false;
-
- vnt_free_tx_bufs(priv);
- vnt_free_rx_bufs(priv);
- vnt_free_int_bufs(priv);
-
- usb_kill_urb(priv->interrupt_urb);
- usb_free_urb(priv->interrupt_urb);
-}
-
-static int vnt_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- priv->vif = vif;
-
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- break;
- case NL80211_IFTYPE_ADHOC:
- vnt_mac_reg_bits_off(priv, MAC_REG_RCR, RCR_UNICAST);
-
- vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_ADHOC);
-
- break;
- case NL80211_IFTYPE_AP:
- vnt_mac_reg_bits_off(priv, MAC_REG_RCR, RCR_UNICAST);
-
- vnt_mac_reg_bits_on(priv, MAC_REG_HOSTCR, HOSTCR_AP);
-
- break;
- default:
- return -EOPNOTSUPP;
- }
-
- priv->op_mode = vif->type;
-
- /* LED blink on TX */
- vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_INTER);
-
- return 0;
-}
-
-static void vnt_remove_interface(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- switch (vif->type) {
- case NL80211_IFTYPE_STATION:
- break;
- case NL80211_IFTYPE_ADHOC:
- vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
- vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
- vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_ADHOC);
- break;
- case NL80211_IFTYPE_AP:
- vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
- vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
- vnt_mac_reg_bits_off(priv, MAC_REG_HOSTCR, HOSTCR_AP);
- break;
- default:
- break;
- }
-
- vnt_radio_power_off(priv);
-
- priv->op_mode = NL80211_IFTYPE_UNSPECIFIED;
-
- /* LED slow blink */
- vnt_mac_set_led(priv, LEDSTS_STS, LEDSTS_SLOW);
-}
-
-static int vnt_config(struct ieee80211_hw *hw, u32 changed)
-{
- struct vnt_private *priv = hw->priv;
- struct ieee80211_conf *conf = &hw->conf;
-
- if (changed & IEEE80211_CONF_CHANGE_PS) {
- if (conf->flags & IEEE80211_CONF_PS)
- vnt_enable_power_saving(priv, conf->listen_interval);
- else
- vnt_disable_power_saving(priv);
- }
-
- if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) ||
- (conf->flags & IEEE80211_CONF_OFFCHANNEL)) {
- vnt_set_channel(priv, conf->chandef.chan->hw_value);
-
- if (conf->chandef.chan->band == NL80211_BAND_5GHZ)
- priv->bb_type = BB_TYPE_11A;
- else
- priv->bb_type = BB_TYPE_11G;
- }
-
- if (changed & IEEE80211_CONF_CHANGE_POWER)
- vnt_rf_setpower(priv, conf->chandef.chan);
-
- if (conf->flags & (IEEE80211_CONF_OFFCHANNEL | IEEE80211_CONF_IDLE))
- /* Set max sensitivity*/
- vnt_update_pre_ed_threshold(priv, true);
- else
- vnt_update_pre_ed_threshold(priv, false);
-
- return 0;
-}
-
-static void vnt_bss_info_changed(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf, u64 changed)
-{
- struct vnt_private *priv = hw->priv;
-
- priv->current_aid = vif->cfg.aid;
-
- if (changed & BSS_CHANGED_BSSID && conf->bssid)
- vnt_mac_set_bssid_addr(priv, (u8 *)conf->bssid);
-
- if (changed & BSS_CHANGED_BASIC_RATES) {
- priv->basic_rates = conf->basic_rates;
-
- vnt_update_top_rates(priv);
-
- dev_dbg(&priv->usb->dev, "basic rates %x\n", conf->basic_rates);
- }
-
- if (changed & BSS_CHANGED_ERP_PREAMBLE) {
- if (conf->use_short_preamble) {
- vnt_mac_enable_barker_preamble_mode(priv);
- priv->preamble_type = PREAMBLE_SHORT;
- } else {
- vnt_mac_disable_barker_preamble_mode(priv);
- priv->preamble_type = PREAMBLE_LONG;
- }
- }
-
- if (changed & BSS_CHANGED_ERP_CTS_PROT) {
- if (conf->use_cts_prot)
- vnt_mac_enable_protect_mode(priv);
- else
- vnt_mac_disable_protect_mode(priv);
- }
-
- if (changed & BSS_CHANGED_ERP_SLOT) {
- if (conf->use_short_slot)
- priv->short_slot_time = true;
- else
- priv->short_slot_time = false;
-
- vnt_set_short_slot_time(priv);
- vnt_set_vga_gain_offset(priv, priv->bb_vga[0]);
- }
-
- if (changed & (BSS_CHANGED_BASIC_RATES | BSS_CHANGED_ERP_PREAMBLE |
- BSS_CHANGED_ERP_SLOT))
- vnt_set_bss_mode(priv);
-
- if (changed & (BSS_CHANGED_TXPOWER | BSS_CHANGED_BANDWIDTH))
- vnt_rf_setpower(priv, conf->chanreq.oper.chan);
-
- if (changed & BSS_CHANGED_BEACON_ENABLED) {
- dev_dbg(&priv->usb->dev,
- "Beacon enable %d\n", conf->enable_beacon);
-
- if (conf->enable_beacon) {
- vnt_beacon_enable(priv, vif, conf);
-
- vnt_mac_reg_bits_on(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
- } else {
- vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
- }
- }
-
- if (changed & (BSS_CHANGED_ASSOC | BSS_CHANGED_BEACON_INFO) &&
- priv->op_mode != NL80211_IFTYPE_AP) {
- if (vif->cfg.assoc && conf->beacon_rate) {
- u16 ps_beacon_int = conf->beacon_int;
-
- if (conf->dtim_period)
- ps_beacon_int *= conf->dtim_period;
- else if (hw->conf.listen_interval)
- ps_beacon_int *= hw->conf.listen_interval;
-
- vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL,
- TFTCTL_TSFCNTREN);
-
- vnt_mac_set_beacon_interval(priv, ps_beacon_int);
-
- vnt_reset_next_tbtt(priv, conf->beacon_int);
-
- vnt_adjust_tsf(priv, conf->beacon_rate->hw_value,
- conf->sync_tsf, priv->current_tsf);
-
- vnt_update_next_tbtt(priv,
- conf->sync_tsf, ps_beacon_int);
- } else {
- vnt_clear_current_tsf(priv);
-
- vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL,
- TFTCTL_TSFCNTREN);
- }
- }
-}
-
-static u64 vnt_prepare_multicast(struct ieee80211_hw *hw,
- struct netdev_hw_addr_list *mc_list)
-{
- struct vnt_private *priv = hw->priv;
- struct netdev_hw_addr *ha;
- u64 mc_filter = 0;
- u32 bit_nr;
-
- netdev_hw_addr_list_for_each(ha, mc_list) {
- bit_nr = ether_crc(ETH_ALEN, ha->addr) >> 26;
- mc_filter |= BIT_ULL(bit_nr);
- }
-
- priv->mc_list_count = mc_list->count;
-
- return mc_filter;
-}
-
-static void vnt_configure(struct ieee80211_hw *hw,
- unsigned int changed_flags,
- unsigned int *total_flags, u64 multicast)
-{
- struct vnt_private *priv = hw->priv;
- u8 rx_mode = 0;
-
- *total_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC;
-
- vnt_control_in(priv, MESSAGE_TYPE_READ, MAC_REG_RCR,
- MESSAGE_REQUEST_MACREG, sizeof(u8), &rx_mode);
-
- dev_dbg(&priv->usb->dev, "rx mode in = %x\n", rx_mode);
-
- if (changed_flags & FIF_ALLMULTI) {
- if (*total_flags & FIF_ALLMULTI) {
- if (priv->mc_list_count > 2)
- vnt_mac_set_filter(priv, ~0);
- else
- vnt_mac_set_filter(priv, multicast);
-
- rx_mode |= RCR_MULTICAST | RCR_BROADCAST;
- } else {
- rx_mode &= ~(RCR_MULTICAST | RCR_BROADCAST);
- }
- }
-
- if (changed_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC)) {
- if (*total_flags & (FIF_OTHER_BSS | FIF_BCN_PRBRESP_PROMISC))
- rx_mode &= ~RCR_BSSID;
- else
- rx_mode |= RCR_BSSID;
- }
-
- vnt_control_out_u8(priv, MESSAGE_REQUEST_MACREG, MAC_REG_RCR, rx_mode);
-
- dev_dbg(&priv->usb->dev, "rx mode out= %x\n", rx_mode);
-}
-
-static int vnt_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
- struct ieee80211_vif *vif, struct ieee80211_sta *sta,
- struct ieee80211_key_conf *key)
-{
- struct vnt_private *priv = hw->priv;
-
- switch (cmd) {
- case SET_KEY:
- return vnt_set_keys(hw, sta, vif, key);
- case DISABLE_KEY:
- if (test_bit(key->hw_key_idx, &priv->key_entry_inuse)) {
- clear_bit(key->hw_key_idx, &priv->key_entry_inuse);
-
- vnt_mac_disable_keyentry(priv, key->hw_key_idx);
- }
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-static int vnt_get_stats(struct ieee80211_hw *hw,
- struct ieee80211_low_level_stats *stats)
-{
- struct vnt_private *priv = hw->priv;
-
- memcpy(stats, &priv->low_stats, sizeof(*stats));
-
- return 0;
-}
-
-static u64 vnt_get_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- return priv->current_tsf;
-}
-
-static void vnt_set_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- u64 tsf)
-{
- struct vnt_private *priv = hw->priv;
-
- vnt_update_next_tbtt(priv, tsf, vif->bss_conf.beacon_int);
-}
-
-static void vnt_reset_tsf(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
- struct vnt_private *priv = hw->priv;
-
- vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
-
- vnt_clear_current_tsf(priv);
-}
-
-static const struct ieee80211_ops vnt_mac_ops = {
- .add_chanctx = ieee80211_emulate_add_chanctx,
- .remove_chanctx = ieee80211_emulate_remove_chanctx,
- .change_chanctx = ieee80211_emulate_change_chanctx,
- .switch_vif_chanctx = ieee80211_emulate_switch_vif_chanctx,
- .tx = vnt_tx_80211,
- .wake_tx_queue = ieee80211_handle_wake_tx_queue,
- .start = vnt_start,
- .stop = vnt_stop,
- .add_interface = vnt_add_interface,
- .remove_interface = vnt_remove_interface,
- .config = vnt_config,
- .bss_info_changed = vnt_bss_info_changed,
- .prepare_multicast = vnt_prepare_multicast,
- .configure_filter = vnt_configure,
- .set_key = vnt_set_key,
- .get_stats = vnt_get_stats,
- .get_tsf = vnt_get_tsf,
- .set_tsf = vnt_set_tsf,
- .reset_tsf = vnt_reset_tsf,
-};
-
-int vnt_init(struct vnt_private *priv)
-{
- if (vnt_init_registers(priv))
- return -EAGAIN;
-
- SET_IEEE80211_PERM_ADDR(priv->hw, priv->permanent_net_addr);
-
- vnt_init_bands(priv);
-
- if (ieee80211_register_hw(priv->hw))
- return -ENODEV;
-
- priv->mac_hw = true;
-
- vnt_radio_power_off(priv);
-
- return 0;
-}
-
-static int
-vt6656_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
- struct usb_device *udev;
- struct vnt_private *priv;
- struct ieee80211_hw *hw;
- struct wiphy *wiphy;
- int rc;
-
- udev = usb_get_dev(interface_to_usbdev(intf));
-
- dev_notice(&udev->dev, "%s Ver. %s\n",
- DEVICE_FULL_DRV_NAM, DEVICE_VERSION);
- dev_notice(&udev->dev,
- "Copyright (c) 2004 VIA Networking Technologies, Inc.\n");
-
- hw = ieee80211_alloc_hw(sizeof(struct vnt_private), &vnt_mac_ops);
- if (!hw) {
- dev_err(&udev->dev, "could not register ieee80211_hw\n");
- rc = -ENOMEM;
- goto err_nomem;
- }
-
- priv = hw->priv;
- priv->hw = hw;
- priv->usb = udev;
- priv->intf = intf;
-
- vnt_set_options(priv);
-
- spin_lock_init(&priv->lock);
- mutex_init(&priv->usb_lock);
-
- INIT_DELAYED_WORK(&priv->run_command_work, vnt_run_command);
-
- usb_set_intfdata(intf, priv);
-
- wiphy = priv->hw->wiphy;
-
- wiphy->frag_threshold = FRAG_THRESH_DEF;
- wiphy->rts_threshold = RTS_THRESH_DEF;
- wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
-
- ieee80211_hw_set(priv->hw, TIMING_BEACON_ONLY);
- ieee80211_hw_set(priv->hw, SIGNAL_DBM);
- ieee80211_hw_set(priv->hw, RX_INCLUDES_FCS);
- ieee80211_hw_set(priv->hw, REPORTS_TX_ACK_STATUS);
- ieee80211_hw_set(priv->hw, SUPPORTS_PS);
- ieee80211_hw_set(priv->hw, PS_NULLFUNC_STACK);
-
- priv->hw->extra_tx_headroom =
- sizeof(struct vnt_tx_buffer) + sizeof(struct vnt_tx_usb_header);
- priv->hw->max_signal = 100;
-
- SET_IEEE80211_DEV(priv->hw, &intf->dev);
-
- rc = usb_reset_device(priv->usb);
- if (rc)
- dev_warn(&priv->usb->dev,
- "%s reset fail status=%d\n", __func__, rc);
-
- clear_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags);
- vnt_reset_command_timer(priv);
-
- vnt_schedule_command(priv, WLAN_CMD_INIT_MAC80211);
-
- return 0;
-
-err_nomem:
- usb_put_dev(udev);
-
- return rc;
-}
-
-static void vt6656_disconnect(struct usb_interface *intf)
-{
- struct vnt_private *priv = usb_get_intfdata(intf);
-
- if (!priv)
- return;
-
- if (priv->mac_hw)
- ieee80211_unregister_hw(priv->hw);
-
- usb_set_intfdata(intf, NULL);
- usb_put_dev(interface_to_usbdev(intf));
-
- set_bit(DEVICE_FLAGS_UNPLUG, &priv->flags);
-
- ieee80211_free_hw(priv->hw);
-}
-
-#ifdef CONFIG_PM
-
-static int vt6656_suspend(struct usb_interface *intf, pm_message_t message)
-{
- return 0;
-}
-
-static int vt6656_resume(struct usb_interface *intf)
-{
- return 0;
-}
-
-#endif /* CONFIG_PM */
-
-MODULE_DEVICE_TABLE(usb, vt6656_table);
-
-static struct usb_driver vt6656_driver = {
- .name = DEVICE_NAME,
- .probe = vt6656_probe,
- .disconnect = vt6656_disconnect,
- .id_table = vt6656_table,
-#ifdef CONFIG_PM
- .suspend = vt6656_suspend,
- .resume = vt6656_resume,
-#endif /* CONFIG_PM */
-};
-
-module_usb_driver(vt6656_driver);
-
-MODULE_FIRMWARE(FIRMWARE_NAME);
diff --git a/drivers/staging/vt6656/power.c b/drivers/staging/vt6656/power.c
deleted file mode 100644
index e5411f6284c7..000000000000
--- a/drivers/staging/vt6656/power.c
+++ /dev/null
@@ -1,112 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles 802.11 power management functions
- *
- * Author: Lyndon Chen
- *
- * Date: July 17, 2002
- *
- * Functions:
- * vnt_enable_power_saving - Enable Power Saving Mode
- * PSvDiasblePowerSaving - Disable Power Saving Mode
- * vnt_next_tbtt_wakeup - Decide if we need to wake up at next Beacon
- *
- * Revision History:
- *
- */
-
-#include "mac.h"
-#include "device.h"
-#include "power.h"
-#include "wcmd.h"
-#include "rxtx.h"
-#include "card.h"
-#include "usbpipe.h"
-
-/*
- *
- * Routine Description:
- * Enable hw power saving functions
- *
- * Return Value:
- * None.
- *
- */
-
-void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval)
-{
- u16 aid = priv->current_aid | BIT(14) | BIT(15);
-
- /* set period of power up before TBTT */
- vnt_mac_write_word(priv, MAC_REG_PWBT, C_PWBT);
-
- if (priv->op_mode != NL80211_IFTYPE_ADHOC)
- /* set AID */
- vnt_mac_write_word(priv, MAC_REG_AIDATIM, aid);
-
- /* Warren:06-18-2004,the sequence must follow
- * PSEN->AUTOSLEEP->GO2DOZE
- */
- /* enable power saving hw function */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_PSEN);
-
- /* Set AutoSleep */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
-
- /* Warren:MUST turn on this once before turn on AUTOSLEEP ,or the
- * AUTOSLEEP doesn't work
- */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_GO2DOZE);
-
- /* always listen beacon */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_ALBCN);
-
- dev_dbg(&priv->usb->dev, "PS:Power Saving Mode Enable...\n");
-}
-
-int vnt_disable_power_saving(struct vnt_private *priv)
-{
- int ret;
-
- /* disable power saving hw function */
- ret = vnt_control_out(priv, MESSAGE_TYPE_DISABLE_PS, 0,
- 0, 0, NULL);
- if (ret)
- return ret;
-
- /* clear AutoSleep */
- vnt_mac_reg_bits_off(priv, MAC_REG_PSCFG, PSCFG_AUTOSLEEP);
-
- /* set always listen beacon */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_ALBCN);
-
- return 0;
-}
-
-/*
- *
- * Routine Description:
- * Check if Next TBTT must wake up
- *
- * Return Value:
- * None.
- *
- */
-
-int vnt_next_tbtt_wakeup(struct vnt_private *priv)
-{
- struct ieee80211_hw *hw = priv->hw;
- struct ieee80211_conf *conf = &hw->conf;
- int wake_up = false;
-
- if (conf->listen_interval > 1) {
- /* Turn on wake up to listen next beacon */
- vnt_mac_reg_bits_on(priv, MAC_REG_PSCTL, PSCTL_LNBCN);
- wake_up = true;
- }
-
- return wake_up;
-}
diff --git a/drivers/staging/vt6656/power.h b/drivers/staging/vt6656/power.h
deleted file mode 100644
index 9f9c70072933..000000000000
--- a/drivers/staging/vt6656/power.h
+++ /dev/null
@@ -1,23 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles 802.11 power management functions
- *
- * Author: Lyndon Chen
- *
- * Date: July 17, 2002
- *
- */
-
-#ifndef __POWER_H__
-#define __POWER_H__
-
-#define C_PWBT 1000 /* micro sec. power up before TBTT */
-
-int vnt_disable_power_saving(struct vnt_private *priv);
-void vnt_enable_power_saving(struct vnt_private *priv, u16 listen_interval);
-int vnt_next_tbtt_wakeup(struct vnt_private *priv);
-
-#endif /* __POWER_H__ */
diff --git a/drivers/staging/vt6656/rf.c b/drivers/staging/vt6656/rf.c
deleted file mode 100644
index 464602c74727..000000000000
--- a/drivers/staging/vt6656/rf.c
+++ /dev/null
@@ -1,443 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: rf function code
- *
- * Author: Jerry Chen
- *
- * Date: Feb. 19, 2004
- *
- * Functions:
- * vnt_rf_write_embedded - Embedded write RF register via MAC
- *
- * Revision History:
- * RF_VT3226: RobertYu:20051111, VT3226C0 and before
- * RF_VT3226D0: RobertYu:20051228
- * RF_VT3342A0: RobertYu:20060609
- *
- */
-
-#include <linux/errno.h>
-#include "mac.h"
-#include "rf.h"
-#include "baseband.h"
-#include "usbpipe.h"
-
-#define CB_AL2230_INIT_SEQ 15
-#define CB_AL7230_INIT_SEQ 16
-#define CB_VT3226_INIT_SEQ 11
-#define CB_VT3342_INIT_SEQ 13
-
-static u8 al2230_init_table[CB_AL2230_INIT_SEQ][3] = {
- {0x03, 0xf7, 0x90},
- {0x03, 0x33, 0x31},
- {0x01, 0xb8, 0x02},
- {0x00, 0xff, 0xf3},
- {0x00, 0x05, 0xa4},
- {0x0f, 0x4d, 0xc5},
- {0x08, 0x05, 0xb6},
- {0x01, 0x47, 0xc7},
- {0x00, 0x06, 0x88},
- {0x04, 0x03, 0xb9},
- {0x00, 0xdb, 0xba},
- {0x00, 0x09, 0x9b},
- {0x0b, 0xdf, 0xfc},
- {0x00, 0x00, 0x0d},
- {0x00, 0x58, 0x0f}
-};
-
-static u8 al2230_channel_table0[CB_MAX_CHANNEL_24G][3] = {
- {0x03, 0xf7, 0x90},
- {0x03, 0xf7, 0x90},
- {0x03, 0xe7, 0x90},
- {0x03, 0xe7, 0x90},
- {0x03, 0xf7, 0xa0},
- {0x03, 0xf7, 0xa0},
- {0x03, 0xe7, 0xa0},
- {0x03, 0xe7, 0xa0},
- {0x03, 0xf7, 0xb0},
- {0x03, 0xf7, 0xb0},
- {0x03, 0xe7, 0xb0},
- {0x03, 0xe7, 0xb0},
- {0x03, 0xf7, 0xc0},
- {0x03, 0xe7, 0xc0}
-};
-
-static u8 al2230_channel_table1[CB_MAX_CHANNEL_24G][3] = {
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x0b, 0x33, 0x31},
- {0x03, 0x33, 0x31},
- {0x06, 0x66, 0x61}
-};
-
-static u8 vt3226_init_table[CB_VT3226_INIT_SEQ][3] = {
- {0x03, 0xff, 0x80},
- {0x02, 0x82, 0xa1},
- {0x03, 0xc6, 0xa2},
- {0x01, 0x97, 0x93},
- {0x03, 0x66, 0x64},
- {0x00, 0x61, 0xa5},
- {0x01, 0x7b, 0xd6},
- {0x00, 0x80, 0x17},
- {0x03, 0xf8, 0x08},
- {0x00, 0x02, 0x39},
- {0x02, 0x00, 0x2a}
-};
-
-static u8 vt3226d0_init_table[CB_VT3226_INIT_SEQ][3] = {
- {0x03, 0xff, 0x80},
- {0x03, 0x02, 0x21},
- {0x03, 0xc6, 0xa2},
- {0x01, 0x97, 0x93},
- {0x03, 0x66, 0x64},
- {0x00, 0x71, 0xa5},
- {0x01, 0x15, 0xc6},
- {0x01, 0x2e, 0x07},
- {0x00, 0x58, 0x08},
- {0x00, 0x02, 0x79},
- {0x02, 0x01, 0xaa}
-};
-
-static u8 vt3226_channel_table0[CB_MAX_CHANNEL_24G][3] = {
- {0x01, 0x97, 0x83},
- {0x01, 0x97, 0x83},
- {0x01, 0x97, 0x93},
- {0x01, 0x97, 0x93},
- {0x01, 0x97, 0x93},
- {0x01, 0x97, 0x93},
- {0x01, 0x97, 0xa3},
- {0x01, 0x97, 0xa3},
- {0x01, 0x97, 0xa3},
- {0x01, 0x97, 0xa3},
- {0x01, 0x97, 0xb3},
- {0x01, 0x97, 0xb3},
- {0x01, 0x97, 0xb3},
- {0x03, 0x37, 0xc3}
-};
-
-static u8 vt3226_channel_table1[CB_MAX_CHANNEL_24G][3] = {
- {0x02, 0x66, 0x64},
- {0x03, 0x66, 0x64},
- {0x00, 0x66, 0x64},
- {0x01, 0x66, 0x64},
- {0x02, 0x66, 0x64},
- {0x03, 0x66, 0x64},
- {0x00, 0x66, 0x64},
- {0x01, 0x66, 0x64},
- {0x02, 0x66, 0x64},
- {0x03, 0x66, 0x64},
- {0x00, 0x66, 0x64},
- {0x01, 0x66, 0x64},
- {0x02, 0x66, 0x64},
- {0x00, 0xcc, 0xc4}
-};
-
-static const u32 vt3226d0_lo_current_table[CB_MAX_CHANNEL_24G] = {
- 0x0135c600,
- 0x0135c600,
- 0x0235c600,
- 0x0235c600,
- 0x0235c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0335c600,
- 0x0135c600
-};
-
-enum {
- VNT_TABLE_INIT = 0,
- VNT_TABLE_INIT_2 = 0,
- VNT_TABLE_0 = 1,
- VNT_TABLE_1 = 2,
- VNT_TABLE_2 = 1
-};
-
-struct vnt_table_info {
- u8 *addr;
- int length;
-};
-
-static const struct vnt_table_info vnt_table_seq[][3] = {
- { /* RF_AL2230, RF_AL2230S init table, channel table 0 and 1 */
- {&al2230_init_table[0][0], CB_AL2230_INIT_SEQ * 3},
- {&al2230_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
- {&al2230_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
- }, { /* RF_VT3226 init table, channel table 0 and 1 */
- {&vt3226_init_table[0][0], CB_VT3226_INIT_SEQ * 3},
- {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
- {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
- }, { /* RF_VT3226D0 init table, channel table 0 and 1 */
- {&vt3226d0_init_table[0][0], CB_VT3226_INIT_SEQ * 3},
- {&vt3226_channel_table0[0][0], CB_MAX_CHANNEL_24G * 3},
- {&vt3226_channel_table1[0][0], CB_MAX_CHANNEL_24G * 3}
- }
-};
-
-/*
- * Description: Write to IF/RF, by embedded programming
- */
-int vnt_rf_write_embedded(struct vnt_private *priv, u32 data)
-{
- u8 reg_data[4];
-
- data |= (VNT_RF_REG_LEN << 3) | IFREGCTL_REGW;
-
- reg_data[0] = (u8)data;
- reg_data[1] = (u8)(data >> 8);
- reg_data[2] = (u8)(data >> 16);
- reg_data[3] = (u8)(data >> 24);
-
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE_IFRF, 0, 0,
- ARRAY_SIZE(reg_data), reg_data);
-}
-
-static u8 vnt_rf_addpower(struct vnt_private *priv)
-{
- int base;
- s32 rssi = -priv->current_rssi;
-
- if (!rssi)
- return 7;
-
- if (priv->rf_type == RF_VT3226D0)
- base = -60;
- else
- base = -70;
-
- if (rssi < base)
- return ((rssi - base + 1) / -5) * 2 + 5;
-
- return 0;
-}
-
-/* Set Tx power by power level and rate */
-static int vnt_rf_set_txpower(struct vnt_private *priv, u8 power,
- struct ieee80211_channel *ch)
-{
- u32 power_setting = 0;
- int ret = 0;
-
- power += vnt_rf_addpower(priv);
- if (power > VNT_RF_MAX_POWER)
- power = VNT_RF_MAX_POWER;
-
- if (priv->power == power)
- return 0;
-
- priv->power = power;
-
- switch (priv->rf_type) {
- case RF_AL2230:
- power_setting = 0x0404090 | (power << 12);
-
- ret = vnt_rf_write_embedded(priv, power_setting);
- if (ret)
- return ret;
-
- if (ch->flags & IEEE80211_CHAN_NO_OFDM)
- ret = vnt_rf_write_embedded(priv, 0x0001b400);
- else
- ret = vnt_rf_write_embedded(priv, 0x0005a400);
-
- break;
- case RF_AL2230S:
- power_setting = 0x0404090 | (power << 12);
-
- ret = vnt_rf_write_embedded(priv, power_setting);
- if (ret)
- return ret;
-
- if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
- ret = vnt_rf_write_embedded(priv, 0x040c1400);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x00299b00);
- } else {
- ret = vnt_rf_write_embedded(priv, 0x0005a400);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x00099b00);
- }
-
- break;
-
- case RF_VT3226:
- power_setting = ((0x3f - power) << 20) | (0x17 << 8);
-
- ret = vnt_rf_write_embedded(priv, power_setting);
- break;
- case RF_VT3226D0:
- if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
- u16 hw_value = ch->hw_value;
-
- power_setting = ((0x3f - power) << 20) | (0xe07 << 8);
-
- ret = vnt_rf_write_embedded(priv, power_setting);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x03c6a200);
- if (ret)
- return ret;
-
- dev_dbg(&priv->usb->dev,
- "%s 11b channel [%d]\n", __func__, hw_value);
-
- hw_value--;
-
- if (hw_value < ARRAY_SIZE(vt3226d0_lo_current_table)) {
- ret = vnt_rf_write_embedded(priv,
- vt3226d0_lo_current_table[hw_value]);
- if (ret)
- return ret;
- }
-
- ret = vnt_rf_write_embedded(priv, 0x015C0800);
- } else {
- dev_dbg(&priv->usb->dev,
- "@@@@ %s> 11G mode\n", __func__);
-
- power_setting = ((0x3f - power) << 20) | (0x7 << 8);
-
- ret = vnt_rf_write_embedded(priv, power_setting);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x00C6A200);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x016BC600);
- if (ret)
- return ret;
-
- ret = vnt_rf_write_embedded(priv, 0x00900800);
- }
-
- break;
-
- default:
- break;
- }
- return ret;
-}
-
-/* Set Tx power by channel number type */
-int vnt_rf_setpower(struct vnt_private *priv,
- struct ieee80211_channel *ch)
-{
- u16 channel;
- u8 power = priv->cck_pwr;
-
- if (!ch)
- return -EINVAL;
-
- /* set channel number to array number */
- channel = ch->hw_value - 1;
-
- if (ch->flags & IEEE80211_CHAN_NO_OFDM) {
- if (channel < ARRAY_SIZE(priv->cck_pwr_tbl))
- power = priv->cck_pwr_tbl[channel];
- } else if (ch->band == NL80211_BAND_5GHZ) {
- /* remove 14 channels to array size */
- channel -= 14;
-
- if (channel < ARRAY_SIZE(priv->ofdm_a_pwr_tbl))
- power = priv->ofdm_a_pwr_tbl[channel];
- } else {
- if (channel < ARRAY_SIZE(priv->ofdm_pwr_tbl))
- power = priv->ofdm_pwr_tbl[channel];
- }
-
- return vnt_rf_set_txpower(priv, power, ch);
-}
-
-/* Convert rssi to dbm */
-void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm)
-{
- u8 idx = ((rssi & 0xc0) >> 6) & 0x03;
- long b = rssi & 0x3f;
- long a = 0;
- u8 airoharf[4] = {0, 18, 0, 40};
-
- switch (priv->rf_type) {
- case RF_AL2230:
- case RF_AL2230S:
- case RF_VT3226:
- case RF_VT3226D0:
- a = airoharf[idx];
- break;
- default:
- break;
- }
-
- *dbm = -1 * (a + b * 2);
-}
-
-int vnt_rf_table_download(struct vnt_private *priv)
-{
- int ret;
- int idx = -1;
- const struct vnt_table_info *table_seq;
-
- switch (priv->rf_type) {
- case RF_AL2230:
- case RF_AL2230S:
- idx = 0;
- break;
- case RF_VT3226:
- idx = 1;
- break;
- case RF_VT3226D0:
- idx = 2;
- break;
- }
-
- if (idx < 0)
- return 0;
-
- table_seq = &vnt_table_seq[idx][0];
-
- /* Init Table */
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE, 0,
- MESSAGE_REQUEST_RF_INIT,
- table_seq[VNT_TABLE_INIT].length,
- table_seq[VNT_TABLE_INIT].addr);
- if (ret)
- return ret;
-
- /* Channel Table 0 */
- ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
- MESSAGE_REQUEST_RF_CH0,
- table_seq[VNT_TABLE_0].length,
- table_seq[VNT_TABLE_0].addr);
- if (ret)
- return ret;
-
- /* Channel Table 1 */
- ret = vnt_control_out_blocks(priv, VNT_REG_BLOCK_SIZE,
- MESSAGE_REQUEST_RF_CH1,
- table_seq[VNT_TABLE_1].length,
- table_seq[VNT_TABLE_1].addr);
-
- return ret;
-}
diff --git a/drivers/staging/vt6656/rf.h b/drivers/staging/vt6656/rf.h
deleted file mode 100644
index b47e149875d1..000000000000
--- a/drivers/staging/vt6656/rf.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Jerry Chen
- *
- * Date: Feb. 19, 2004
- *
- */
-
-#ifndef __RF_H__
-#define __RF_H__
-
-#include "device.h"
-
-/* Baseband RF pair definition in eeprom (Bits 6..0) */
-#define RF_RFMD2959 0x01
-#define RF_MAXIMAG 0x02
-#define RF_AL2230 0x03
-#define RF_GCT5103 0x04
-#define RF_UW2451 0x05
-#define RF_MAXIMG 0x06
-#define RF_MAXIM2829 0x07
-#define RF_UW2452 0x08
-#define RF_VT3226 0x09
-#define RF_AIROHA7230 0x0a
-#define RF_UW2453 0x0b
-#define RF_VT3226D0 0x0c /* RobertYu:20051114 */
-#define RF_VT3342A0 0x0d /* RobertYu:20060609 */
-#define RF_AL2230S 0x0e
-
-#define RF_EMU 0x80
-#define RF_MASK 0x7F
-
-#define VNT_RF_MAX_POWER 0x3f
-#define VNT_RF_REG_LEN 0x17 /* 24 bit length */
-
-int vnt_rf_write_embedded(struct vnt_private *priv, u32 data);
-int vnt_rf_setpower(struct vnt_private *priv, struct ieee80211_channel *ch);
-void vnt_rf_rssi_to_dbm(struct vnt_private *priv, u8 rssi, long *dbm);
-int vnt_rf_table_download(struct vnt_private *priv);
-
-#endif /* __RF_H__ */
diff --git a/drivers/staging/vt6656/rxtx.c b/drivers/staging/vt6656/rxtx.c
deleted file mode 100644
index cd99091c6c28..000000000000
--- a/drivers/staging/vt6656/rxtx.c
+++ /dev/null
@@ -1,730 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: handle WMAC/802.3/802.11 rx & tx functions
- *
- * Author: Lyndon Chen
- *
- * Date: May 20, 2003
- *
- * Functions:
- * vnt_generate_tx_parameter - Generate tx dma required parameter.
- * vnt_get_rsvtime- get frame reserved time
- * vnt_fill_cts_head- fulfill CTS ctl header
- *
- * Revision History:
- *
- */
-
-#include <linux/etherdevice.h>
-#include "device.h"
-#include "rxtx.h"
-#include "card.h"
-#include "mac.h"
-#include "rf.h"
-#include "usbpipe.h"
-
-static const u16 vnt_time_stampoff[2][MAX_RATE] = {
- /* Long Preamble */
- {384, 288, 226, 209, 54, 43, 37, 31, 28, 25, 24, 23},
-
- /* Short Preamble */
- {384, 192, 130, 113, 54, 43, 37, 31, 28, 25, 24, 23},
-};
-
-#define DATADUR_B 10
-#define DATADUR_A 11
-
-static const u8 vnt_phy_signal[] = {
- 0x00, /* RATE_1M */
- 0x01, /* RATE_2M */
- 0x02, /* RATE_5M */
- 0x03, /* RATE_11M */
- 0x8b, /* RATE_6M */
- 0x8f, /* RATE_9M */
- 0x8a, /* RATE_12M */
- 0x8e, /* RATE_18M */
- 0x89, /* RATE_24M */
- 0x8d, /* RATE_36M */
- 0x88, /* RATE_48M */
- 0x8c /* RATE_54M */
-};
-
-static struct vnt_usb_send_context
- *vnt_get_free_context(struct vnt_private *priv)
-{
- struct vnt_usb_send_context *context = NULL;
- int ii;
-
- for (ii = 0; ii < priv->num_tx_context; ii++) {
- if (!priv->tx_context[ii])
- return NULL;
-
- context = priv->tx_context[ii];
- if (!context->in_use) {
- context->in_use = true;
- return context;
- }
- }
-
- if (ii == priv->num_tx_context) {
- dev_dbg(&priv->usb->dev, "%s No Free Tx Context\n", __func__);
-
- ieee80211_stop_queues(priv->hw);
- }
-
- return NULL;
-}
-
-/* Get Length, Service, and Signal fields of Phy for Tx */
-static void vnt_get_phy_field(struct vnt_private *priv, u32 frame_length,
- u16 tx_rate, u8 pkt_type,
- struct vnt_phy_field *phy)
-{
- u32 bit_count;
- u32 count = 0;
- u32 tmp;
- int ext_bit;
- int i;
- u8 mask = 0;
- u8 preamble_type = priv->preamble_type;
-
- bit_count = frame_length * 8;
- ext_bit = false;
-
- switch (tx_rate) {
- case RATE_1M:
- count = bit_count;
- break;
- case RATE_2M:
- count = bit_count / 2;
- break;
- case RATE_5M:
- count = DIV_ROUND_UP(bit_count * 10, 55);
- break;
- case RATE_11M:
- count = bit_count / 11;
- tmp = count * 11;
-
- if (tmp != bit_count) {
- count++;
-
- if ((bit_count - tmp) <= 3)
- ext_bit = true;
- }
-
- break;
- }
-
- if (tx_rate > RATE_11M) {
- if (pkt_type == PK_TYPE_11A)
- mask = BIT(4);
- } else if (tx_rate > RATE_1M) {
- if (preamble_type == PREAMBLE_SHORT)
- mask = BIT(3);
- }
-
- i = tx_rate > RATE_54M ? RATE_54M : tx_rate;
- phy->signal = vnt_phy_signal[i] | mask;
- phy->service = 0x00;
-
- if (pkt_type == PK_TYPE_11B) {
- if (ext_bit)
- phy->service |= 0x80;
- phy->len = cpu_to_le16((u16)count);
- } else {
- phy->len = cpu_to_le16((u16)frame_length);
- }
-}
-
-static __le16 vnt_time_stamp_off(struct vnt_private *priv, u16 rate)
-{
- return cpu_to_le16(vnt_time_stampoff[priv->preamble_type % 2]
- [rate % MAX_RATE]);
-}
-
-static __le16 vnt_rxtx_rsvtime_le16(struct vnt_usb_send_context *context)
-{
- struct vnt_private *priv = context->priv;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(context->skb);
- struct ieee80211_rate *rate = ieee80211_get_tx_rate(priv->hw, info);
-
- return ieee80211_generic_frame_duration(priv->hw,
- info->control.vif, info->band,
- context->frame_len,
- rate);
-}
-
-static __le16 vnt_get_rts_duration(struct vnt_usb_send_context *context)
-{
- struct vnt_private *priv = context->priv;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(context->skb);
-
- return ieee80211_rts_duration(priv->hw, priv->vif,
- context->frame_len, info);
-}
-
-static __le16 vnt_get_cts_duration(struct vnt_usb_send_context *context)
-{
- struct vnt_private *priv = context->priv;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(context->skb);
-
- return ieee80211_ctstoself_duration(priv->hw, priv->vif,
- context->frame_len, info);
-}
-
-static void vnt_rxtx_datahead_g(struct vnt_usb_send_context *tx_context,
- struct vnt_tx_datahead_g *buf)
-{
- struct vnt_private *priv = tx_context->priv;
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *)tx_context->skb->data;
- u32 frame_len = tx_context->frame_len;
- u16 rate = tx_context->tx_rate;
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_len, rate, tx_context->pkt_type, &buf->a);
- vnt_get_phy_field(priv, frame_len, priv->top_cck_basic_rate,
- PK_TYPE_11B, &buf->b);
-
- /* Get Duration and TimeStamp */
- buf->duration_a = hdr->duration_id;
- buf->duration_b = hdr->duration_id;
- buf->time_stamp_off_a = vnt_time_stamp_off(priv, rate);
- buf->time_stamp_off_b = vnt_time_stamp_off(priv,
- priv->top_cck_basic_rate);
-}
-
-static void vnt_rxtx_datahead_ab(struct vnt_usb_send_context *tx_context,
- struct vnt_tx_datahead_ab *buf)
-{
- struct vnt_private *priv = tx_context->priv;
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *)tx_context->skb->data;
- u32 frame_len = tx_context->frame_len;
- u16 rate = tx_context->tx_rate;
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_len, rate,
- tx_context->pkt_type, &buf->ab);
-
- /* Get Duration and TimeStampOff */
- buf->duration = hdr->duration_id;
- buf->time_stamp_off = vnt_time_stamp_off(priv, rate);
-}
-
-static void vnt_fill_ieee80211_rts(struct vnt_usb_send_context *tx_context,
- struct ieee80211_rts *rts, __le16 duration)
-{
- struct ieee80211_hdr *hdr =
- (struct ieee80211_hdr *)tx_context->skb->data;
-
- rts->duration = duration;
- rts->frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_RTS);
-
- ether_addr_copy(rts->ra, hdr->addr1);
- ether_addr_copy(rts->ta, hdr->addr2);
-}
-
-static void vnt_rxtx_rts_g_head(struct vnt_usb_send_context *tx_context,
- struct vnt_rts_g *buf)
-{
- struct vnt_private *priv = tx_context->priv;
- u16 rts_frame_len = 20;
-
- vnt_get_phy_field(priv, rts_frame_len, priv->top_cck_basic_rate,
- PK_TYPE_11B, &buf->b);
- vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate,
- tx_context->pkt_type, &buf->a);
-
- buf->duration_bb = vnt_get_rts_duration(tx_context);
- buf->duration_aa = buf->duration_bb;
- buf->duration_ba = buf->duration_bb;
-
- vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration_aa);
-
- vnt_rxtx_datahead_g(tx_context, &buf->data_head);
-}
-
-static void vnt_rxtx_rts_ab_head(struct vnt_usb_send_context *tx_context,
- struct vnt_rts_ab *buf)
-{
- struct vnt_private *priv = tx_context->priv;
- u16 rts_frame_len = 20;
-
- vnt_get_phy_field(priv, rts_frame_len, priv->top_ofdm_basic_rate,
- tx_context->pkt_type, &buf->ab);
-
- buf->duration = vnt_get_rts_duration(tx_context);
-
- vnt_fill_ieee80211_rts(tx_context, &buf->data, buf->duration);
-
- vnt_rxtx_datahead_ab(tx_context, &buf->data_head);
-}
-
-static void vnt_fill_cts_head(struct vnt_usb_send_context *tx_context,
- union vnt_tx_data_head *head)
-{
- struct vnt_private *priv = tx_context->priv;
- struct vnt_cts *buf = &head->cts_g;
- u32 cts_frame_len = 14;
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, cts_frame_len, priv->top_cck_basic_rate,
- PK_TYPE_11B, &buf->b);
- /* Get CTSDuration_ba */
- buf->duration_ba = vnt_get_cts_duration(tx_context);
- /*Get CTS Frame body*/
- buf->data.duration = buf->duration_ba;
- buf->data.frame_control =
- cpu_to_le16(IEEE80211_FTYPE_CTL | IEEE80211_STYPE_CTS);
-
- ether_addr_copy(buf->data.ra, priv->current_net_addr);
-
- vnt_rxtx_datahead_g(tx_context, &buf->data_head);
-}
-
-/* returns true if mic_hdr is needed */
-static bool vnt_fill_txkey(struct vnt_tx_buffer *tx_buffer, struct sk_buff *skb)
-{
- struct vnt_tx_fifo_head *fifo = &tx_buffer->fifo_head;
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_key_conf *tx_key = info->control.hw_key;
- struct vnt_mic_hdr *mic_hdr;
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
- u64 pn64;
- u16 payload_len = skb->len;
- u8 *iv = ((u8 *)hdr + ieee80211_get_hdrlen_from_skb(skb));
-
- /* strip header and icv len from payload */
- payload_len -= ieee80211_get_hdrlen_from_skb(skb);
- payload_len -= tx_key->icv_len;
-
- switch (tx_key->cipher) {
- case WLAN_CIPHER_SUITE_WEP40:
- case WLAN_CIPHER_SUITE_WEP104:
- memcpy(fifo->tx_key, iv, 3);
- memcpy(fifo->tx_key + 3, tx_key->key, tx_key->keylen);
-
- if (tx_key->keylen == WLAN_KEY_LEN_WEP40) {
- memcpy(fifo->tx_key + 8, iv, 3);
- memcpy(fifo->tx_key + 11,
- tx_key->key, WLAN_KEY_LEN_WEP40);
- }
-
- fifo->frag_ctl |= cpu_to_le16(FRAGCTL_LEGACY);
- break;
- case WLAN_CIPHER_SUITE_TKIP:
- ieee80211_get_tkip_p2k(tx_key, skb, fifo->tx_key);
-
- fifo->frag_ctl |= cpu_to_le16(FRAGCTL_TKIP);
- break;
- case WLAN_CIPHER_SUITE_CCMP:
- if (info->control.use_cts_prot) {
- if (info->control.use_rts)
- mic_hdr = &tx_buffer->tx_head.tx_rts.tx.mic.hdr;
- else
- mic_hdr = &tx_buffer->tx_head.tx_cts.tx.mic.hdr;
- } else {
- mic_hdr = &tx_buffer->tx_head.tx_ab.tx.mic.hdr;
- }
-
- mic_hdr->id = 0x59;
- mic_hdr->payload_len = cpu_to_be16(payload_len);
- ether_addr_copy(mic_hdr->mic_addr2, hdr->addr2);
-
- pn64 = atomic64_read(&tx_key->tx_pn);
- mic_hdr->ccmp_pn[5] = pn64;
- mic_hdr->ccmp_pn[4] = pn64 >> 8;
- mic_hdr->ccmp_pn[3] = pn64 >> 16;
- mic_hdr->ccmp_pn[2] = pn64 >> 24;
- mic_hdr->ccmp_pn[1] = pn64 >> 32;
- mic_hdr->ccmp_pn[0] = pn64 >> 40;
-
- if (ieee80211_has_a4(hdr->frame_control))
- mic_hdr->hlen = cpu_to_be16(28);
- else
- mic_hdr->hlen = cpu_to_be16(22);
-
- ether_addr_copy(mic_hdr->addr1, hdr->addr1);
- ether_addr_copy(mic_hdr->addr2, hdr->addr2);
- ether_addr_copy(mic_hdr->addr3, hdr->addr3);
-
- mic_hdr->frame_control = cpu_to_le16(le16_to_cpu(hdr->frame_control) & 0xc78f);
- mic_hdr->seq_ctrl = cpu_to_le16(le16_to_cpu(hdr->seq_ctrl) & 0xf);
-
- if (ieee80211_has_a4(hdr->frame_control))
- ether_addr_copy(mic_hdr->addr4, hdr->addr4);
-
- memcpy(fifo->tx_key, tx_key->key, WLAN_KEY_LEN_CCMP);
-
- fifo->frag_ctl |= cpu_to_le16(FRAGCTL_AES);
- return true;
- default:
- break;
- }
-
- return false;
-}
-
-static void vnt_rxtx_rts(struct vnt_usb_send_context *tx_context)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb);
- struct vnt_tx_buffer *tx_buffer = tx_context->tx_buffer;
- union vnt_tx_head *tx_head = &tx_buffer->tx_head;
- struct vnt_rrv_time_rts *buf = &tx_head->tx_rts.rts;
- union vnt_tx_data_head *head = &tx_head->tx_rts.tx.head;
-
- buf->rts_rrv_time_aa = vnt_get_rts_duration(tx_context);
- buf->rts_rrv_time_ba = buf->rts_rrv_time_aa;
- buf->rts_rrv_time_bb = buf->rts_rrv_time_aa;
-
- buf->rrv_time_a = vnt_rxtx_rsvtime_le16(tx_context);
- buf->rrv_time_b = buf->rrv_time_a;
-
- if (info->control.hw_key) {
- if (vnt_fill_txkey(tx_buffer, tx_context->skb))
- head = &tx_head->tx_rts.tx.mic.head;
- }
-
- vnt_rxtx_rts_g_head(tx_context, &head->rts_g);
-}
-
-static void vnt_rxtx_cts(struct vnt_usb_send_context *tx_context)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb);
- struct vnt_tx_buffer *tx_buffer = tx_context->tx_buffer;
- union vnt_tx_head *tx_head = &tx_buffer->tx_head;
- struct vnt_rrv_time_cts *buf = &tx_head->tx_cts.cts;
- union vnt_tx_data_head *head = &tx_head->tx_cts.tx.head;
-
- buf->rrv_time_a = vnt_rxtx_rsvtime_le16(tx_context);
- buf->rrv_time_b = buf->rrv_time_a;
-
- buf->cts_rrv_time_ba = vnt_get_cts_duration(tx_context);
-
- if (info->control.hw_key) {
- if (vnt_fill_txkey(tx_buffer, tx_context->skb))
- head = &tx_head->tx_cts.tx.mic.head;
- }
-
- vnt_fill_cts_head(tx_context, head);
-}
-
-static void vnt_rxtx_ab(struct vnt_usb_send_context *tx_context)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb);
- struct vnt_tx_buffer *tx_buffer = tx_context->tx_buffer;
- union vnt_tx_head *tx_head = &tx_buffer->tx_head;
- struct vnt_rrv_time_ab *buf = &tx_head->tx_ab.ab;
- union vnt_tx_data_head *head = &tx_head->tx_ab.tx.head;
-
- buf->rrv_time = vnt_rxtx_rsvtime_le16(tx_context);
-
- if (info->control.hw_key) {
- if (vnt_fill_txkey(tx_buffer, tx_context->skb))
- head = &tx_head->tx_ab.tx.mic.head;
- }
-
- if (info->control.use_rts) {
- buf->rts_rrv_time = vnt_get_rts_duration(tx_context);
-
- vnt_rxtx_rts_ab_head(tx_context, &head->rts_ab);
-
- return;
- }
-
- vnt_rxtx_datahead_ab(tx_context, &head->data_head_ab);
-}
-
-static void vnt_generate_tx_parameter(struct vnt_usb_send_context *tx_context)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(tx_context->skb);
-
- if (info->control.use_cts_prot) {
- if (info->control.use_rts) {
- vnt_rxtx_rts(tx_context);
-
- return;
- }
-
- vnt_rxtx_cts(tx_context);
-
- return;
- }
-
- vnt_rxtx_ab(tx_context);
-}
-
-static u16 vnt_get_hdr_size(struct ieee80211_tx_info *info)
-{
- u16 size = sizeof(struct vnt_tx_datahead_ab);
-
- if (info->control.use_cts_prot) {
- if (info->control.use_rts)
- size = sizeof(struct vnt_rts_g);
- else
- size = sizeof(struct vnt_cts);
- } else if (info->control.use_rts) {
- size = sizeof(struct vnt_rts_ab);
- }
-
- if (info->control.hw_key) {
- if (info->control.hw_key->cipher == WLAN_CIPHER_SUITE_CCMP)
- size += sizeof(struct vnt_mic_hdr);
- }
-
- /* Get rrv_time header */
- if (info->control.use_cts_prot) {
- if (info->control.use_rts)
- size += sizeof(struct vnt_rrv_time_rts);
- else
- size += sizeof(struct vnt_rrv_time_cts);
- } else {
- size += sizeof(struct vnt_rrv_time_ab);
- }
-
- size += sizeof(struct vnt_tx_fifo_head);
-
- return size;
-}
-
-int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb)
-{
- struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
- struct ieee80211_tx_rate *tx_rate = &info->control.rates[0];
- struct ieee80211_rate *rate;
- struct ieee80211_hdr *hdr;
- struct vnt_tx_buffer *tx_buffer;
- struct vnt_tx_fifo_head *tx_buffer_head;
- struct vnt_usb_send_context *tx_context;
- unsigned long flags;
- u8 pkt_type;
-
- hdr = (struct ieee80211_hdr *)(skb->data);
-
- rate = ieee80211_get_tx_rate(priv->hw, info);
-
- if (rate->hw_value > RATE_11M) {
- if (info->band == NL80211_BAND_5GHZ) {
- pkt_type = PK_TYPE_11A;
- } else {
- if (tx_rate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
- if (priv->basic_rates & VNT_B_RATES)
- pkt_type = PK_TYPE_11GB;
- else
- pkt_type = PK_TYPE_11GA;
- } else {
- pkt_type = PK_TYPE_11A;
- }
- }
- } else {
- pkt_type = PK_TYPE_11B;
- }
-
- spin_lock_irqsave(&priv->lock, flags);
-
- tx_context = vnt_get_free_context(priv);
- if (!tx_context) {
- dev_dbg(&priv->usb->dev, "%s No free context\n", __func__);
- spin_unlock_irqrestore(&priv->lock, flags);
- return -ENOMEM;
- }
-
- tx_context->pkt_type = pkt_type;
- tx_context->frame_len = skb->len + 4;
- tx_context->tx_rate = rate->hw_value;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- tx_context->skb = skb_clone(skb, GFP_ATOMIC);
- if (!tx_context->skb) {
- tx_context->in_use = false;
- return -ENOMEM;
- }
-
- tx_buffer = skb_push(skb, vnt_get_hdr_size(info));
- tx_context->tx_buffer = tx_buffer;
- tx_buffer_head = &tx_buffer->fifo_head;
-
- tx_context->type = CONTEXT_DATA_PACKET;
-
- /*Set fifo controls */
- if (pkt_type == PK_TYPE_11A)
- tx_buffer_head->fifo_ctl = 0;
- else if (pkt_type == PK_TYPE_11B)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11B);
- else if (pkt_type == PK_TYPE_11GB)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GB);
- else if (pkt_type == PK_TYPE_11GA)
- tx_buffer_head->fifo_ctl = cpu_to_le16(FIFOCTL_11GA);
-
- if (!ieee80211_is_data(hdr->frame_control)) {
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_GENINT |
- FIFOCTL_ISDMA0);
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_TMOEN);
-
- tx_buffer_head->time_stamp =
- cpu_to_le16(DEFAULT_MGN_LIFETIME_RES_64us);
- } else {
- tx_buffer_head->time_stamp =
- cpu_to_le16(DEFAULT_MSDU_LIFETIME_RES_64us);
- }
-
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_NEEDACK);
-
- if (ieee80211_has_retry(hdr->frame_control))
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LRETRY);
-
- if (info->control.use_rts)
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_RTS);
-
- if (ieee80211_has_a4(hdr->frame_control))
- tx_buffer_head->fifo_ctl |= cpu_to_le16(FIFOCTL_LHEAD);
-
- tx_buffer_head->frag_ctl =
- cpu_to_le16(ieee80211_hdrlen(hdr->frame_control) << 10);
-
- if (info->control.hw_key)
- tx_context->frame_len += info->control.hw_key->icv_len;
-
- tx_buffer_head->current_rate = cpu_to_le16(rate->hw_value);
-
- vnt_generate_tx_parameter(tx_context);
-
- tx_buffer_head->frag_ctl |= cpu_to_le16(FRAGCTL_NONFRAG);
-
- priv->seq_counter = (le16_to_cpu(hdr->seq_ctrl) &
- IEEE80211_SCTL_SEQ) >> 4;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- if (vnt_tx_context(priv, tx_context, skb)) {
- dev_kfree_skb(tx_context->skb);
- spin_unlock_irqrestore(&priv->lock, flags);
- return -EIO;
- }
-
- dev_kfree_skb(skb);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-static int vnt_beacon_xmit(struct vnt_private *priv, struct sk_buff *skb)
-{
- struct vnt_tx_short_buf_head *short_head;
- struct ieee80211_tx_info *info;
- struct vnt_usb_send_context *context;
- struct ieee80211_mgmt *mgmt_hdr;
- unsigned long flags;
- u32 frame_size = skb->len + 4;
- u16 current_rate;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- context = vnt_get_free_context(priv);
- if (!context) {
- dev_dbg(&priv->usb->dev, "%s No free context!\n", __func__);
- spin_unlock_irqrestore(&priv->lock, flags);
- return -ENOMEM;
- }
-
- context->skb = skb;
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- mgmt_hdr = (struct ieee80211_mgmt *)skb->data;
- short_head = skb_push(skb, sizeof(*short_head));
-
- if (priv->bb_type == BB_TYPE_11A) {
- current_rate = RATE_6M;
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_size, current_rate,
- PK_TYPE_11A, &short_head->ab);
-
- /* Get TimeStampOff */
- short_head->time_stamp_off =
- vnt_time_stamp_off(priv, current_rate);
- } else {
- current_rate = RATE_1M;
- short_head->fifo_ctl |= cpu_to_le16(FIFOCTL_11B);
-
- /* Get SignalField,ServiceField,Length */
- vnt_get_phy_field(priv, frame_size, current_rate,
- PK_TYPE_11B, &short_head->ab);
-
- /* Get TimeStampOff */
- short_head->time_stamp_off =
- vnt_time_stamp_off(priv, current_rate);
- }
-
- /* Get Duration */
- short_head->duration = mgmt_hdr->duration;
-
- /* time stamp always 0 */
- mgmt_hdr->u.beacon.timestamp = 0;
-
- info = IEEE80211_SKB_CB(skb);
- if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
- struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)mgmt_hdr;
-
- hdr->duration_id = 0;
- hdr->seq_ctrl = cpu_to_le16(priv->seq_counter << 4);
- }
-
- priv->seq_counter++;
- if (priv->seq_counter > 0x0fff)
- priv->seq_counter = 0;
-
- context->type = CONTEXT_BEACON_PACKET;
-
- spin_lock_irqsave(&priv->lock, flags);
-
- if (vnt_tx_context(priv, context, skb))
- ieee80211_free_txskb(priv->hw, context->skb);
-
- spin_unlock_irqrestore(&priv->lock, flags);
-
- return 0;
-}
-
-int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif)
-{
- struct sk_buff *beacon;
-
- beacon = ieee80211_beacon_get(priv->hw, vif, 0);
- if (!beacon)
- return -ENOMEM;
-
- if (vnt_beacon_xmit(priv, beacon)) {
- ieee80211_free_txskb(priv->hw, beacon);
- return -ENODEV;
- }
-
- return 0;
-}
-
-int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf)
-{
- vnt_mac_reg_bits_off(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
-
- vnt_mac_reg_bits_off(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
-
- vnt_mac_set_beacon_interval(priv, conf->beacon_int);
-
- vnt_clear_current_tsf(priv);
-
- vnt_mac_reg_bits_on(priv, MAC_REG_TFTCTL, TFTCTL_TSFCNTREN);
-
- vnt_reset_next_tbtt(priv, conf->beacon_int);
-
- return vnt_beacon_make(priv, vif);
-}
diff --git a/drivers/staging/vt6656/rxtx.h b/drivers/staging/vt6656/rxtx.h
deleted file mode 100644
index b9df0854b4b0..000000000000
--- a/drivers/staging/vt6656/rxtx.h
+++ /dev/null
@@ -1,178 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Jerry Chen
- *
- * Date: Jun. 27, 2002
- *
- */
-
-#ifndef __RXTX_H__
-#define __RXTX_H__
-
-#include "device.h"
-#include "wcmd.h"
-#include "baseband.h"
-
-#define DEFAULT_MGN_LIFETIME_RES_64us 125 /* 64us */
-#define DEFAULT_MSDU_LIFETIME_RES_64us 8000
-
-/* Length, Service, and Signal fields of Phy for Tx */
-struct vnt_phy_field {
- u8 signal;
- u8 service;
- __le16 len;
-} __packed;
-
-/* MIC HDR data header */
-struct vnt_mic_hdr {
- u8 id;
- u8 tx_priority;
- u8 mic_addr2[6];
- u8 ccmp_pn[IEEE80211_CCMP_PN_LEN];
- __be16 payload_len;
- __be16 hlen;
- __le16 frame_control;
- u8 addr1[6];
- u8 addr2[6];
- u8 addr3[6];
- __le16 seq_ctrl;
- u8 addr4[6];
- u16 packing; /* packing to 48 bytes */
-} __packed;
-
-/* RsvTime buffer header */
-struct vnt_rrv_time_rts {
- __le16 rts_rrv_time_ba;
- __le16 rts_rrv_time_aa;
- __le16 rts_rrv_time_bb;
- u16 wReserved;
- __le16 rrv_time_b;
- __le16 rrv_time_a;
-} __packed;
-
-struct vnt_rrv_time_cts {
- __le16 cts_rrv_time_ba;
- u16 wReserved;
- __le16 rrv_time_b;
- __le16 rrv_time_a;
-} __packed;
-
-struct vnt_rrv_time_ab {
- __le16 rts_rrv_time;
- __le16 rrv_time;
-} __packed;
-
-/* TX data header */
-struct vnt_tx_datahead_g {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_b;
- __le16 duration_a;
- __le16 time_stamp_off_b;
- __le16 time_stamp_off_a;
-} __packed;
-
-struct vnt_tx_datahead_ab {
- struct vnt_phy_field ab;
- __le16 duration;
- __le16 time_stamp_off;
-} __packed;
-
-/* RTS buffer header */
-struct vnt_rts_g {
- struct vnt_phy_field b;
- struct vnt_phy_field a;
- __le16 duration_ba;
- __le16 duration_aa;
- __le16 duration_bb;
- u16 wReserved;
- struct ieee80211_rts data;
- struct vnt_tx_datahead_g data_head;
-} __packed __aligned(2);
-
-struct vnt_rts_ab {
- struct vnt_phy_field ab;
- __le16 duration;
- u16 wReserved;
- struct ieee80211_rts data;
- struct vnt_tx_datahead_ab data_head;
-} __packed __aligned(2);
-
-/* CTS buffer header */
-struct vnt_cts {
- struct vnt_phy_field b;
- __le16 duration_ba;
- u16 wReserved;
- struct ieee80211_cts data;
- u16 reserved2;
- struct vnt_tx_datahead_g data_head;
-} __packed __aligned(2);
-
-union vnt_tx_data_head {
- /* rts g */
- struct vnt_rts_g rts_g;
- /* rts a/b */
- struct vnt_rts_ab rts_ab;
- /* cts g */
- struct vnt_cts cts_g;
- /* no rts/cts */
- struct vnt_tx_datahead_ab data_head_ab;
-};
-
-struct vnt_tx_mic_hdr {
- struct vnt_mic_hdr hdr;
- union vnt_tx_data_head head;
-} __packed;
-
-union vnt_tx {
- struct vnt_tx_mic_hdr mic;
- union vnt_tx_data_head head;
-};
-
-union vnt_tx_head {
- struct {
- struct vnt_rrv_time_rts rts;
- union vnt_tx tx;
- } __packed tx_rts;
- struct {
- struct vnt_rrv_time_cts cts;
- union vnt_tx tx;
- } __packed tx_cts;
- struct {
- struct vnt_rrv_time_ab ab;
- union vnt_tx tx;
- } __packed tx_ab;
-};
-
-struct vnt_tx_fifo_head {
- u8 tx_key[WLAN_KEY_LEN_CCMP];
- __le16 fifo_ctl;
- __le16 time_stamp;
- __le16 frag_ctl;
- __le16 current_rate;
-} __packed;
-
-struct vnt_tx_buffer {
- struct vnt_tx_fifo_head fifo_head;
- union vnt_tx_head tx_head;
-} __packed;
-
-struct vnt_tx_short_buf_head {
- __le16 fifo_ctl;
- u16 time_stamp;
- struct vnt_phy_field ab;
- __le16 duration;
- __le16 time_stamp_off;
-} __packed;
-
-int vnt_tx_packet(struct vnt_private *priv, struct sk_buff *skb);
-int vnt_beacon_make(struct vnt_private *priv, struct ieee80211_vif *vif);
-int vnt_beacon_enable(struct vnt_private *priv, struct ieee80211_vif *vif,
- struct ieee80211_bss_conf *conf);
-
-#endif /* __RXTX_H__ */
diff --git a/drivers/staging/vt6656/usbpipe.c b/drivers/staging/vt6656/usbpipe.c
deleted file mode 100644
index d505b4b69ba4..000000000000
--- a/drivers/staging/vt6656/usbpipe.c
+++ /dev/null
@@ -1,506 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handle USB control endpoint
- *
- * Author: Warren Hsu
- *
- * Date: Mar. 29, 2005
- *
- * Functions:
- * vnt_control_out - Write variable length bytes to MEM/BB/MAC/EEPROM
- * vnt_control_in - Read variable length bytes from MEM/BB/MAC/EEPROM
- * vnt_control_out_u8 - Write one byte to MEM/BB/MAC/EEPROM
- * vnt_control_in_u8 - Read one byte from MEM/BB/MAC/EEPROM
- *
- * Revision History:
- * 04-05-2004 Jerry Chen: Initial release
- * 11-24-2004 Warren Hsu: Add ControlvWriteByte,ControlvReadByte,
- * ControlvMaskByte
- *
- */
-
-#include "rxtx.h"
-#include "desc.h"
-#include "device.h"
-#include "usbpipe.h"
-#include "mac.h"
-#include "rf.h"
-
-#define USB_CTL_WAIT 500 /* ms */
-
-int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
- u16 index, u16 length, const u8 *buffer)
-{
- int ret = 0;
- u8 *usb_buffer;
-
- if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
- ret = -EINVAL;
- goto end;
- }
-
- mutex_lock(&priv->usb_lock);
-
- usb_buffer = kmemdup(buffer, length, GFP_KERNEL);
- if (!usb_buffer) {
- ret = -ENOMEM;
- goto end_unlock;
- }
-
- ret = usb_control_msg(priv->usb,
- usb_sndctrlpipe(priv->usb, 0),
- request, 0x40, value,
- index, usb_buffer, length, USB_CTL_WAIT);
-
- kfree(usb_buffer);
-
- if (ret == (int)length)
- ret = 0;
- else
- ret = -EIO;
-
-end_unlock:
- mutex_unlock(&priv->usb_lock);
-end:
- return ret;
-}
-
-int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 data)
-{
- return vnt_control_out(priv, MESSAGE_TYPE_WRITE,
- reg_off, reg, sizeof(u8), &data);
-}
-
-int vnt_control_out_blocks(struct vnt_private *priv,
- u16 block, u8 reg, u16 length, const u8 *data)
-{
- int ret = 0, i;
-
- for (i = 0; i < length; i += block) {
- u16 len = min_t(int, length - i, block);
-
- ret = vnt_control_out(priv, MESSAGE_TYPE_WRITE,
- i, reg, len, data + i);
- if (ret)
- goto end;
- }
-end:
- return ret;
-}
-
-int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
- u16 index, u16 length, u8 *buffer)
-{
- int ret = 0;
- u8 *usb_buffer;
-
- if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
- ret = -EINVAL;
- goto end;
- }
-
- mutex_lock(&priv->usb_lock);
-
- usb_buffer = kmalloc(length, GFP_KERNEL);
- if (!usb_buffer) {
- ret = -ENOMEM;
- goto end_unlock;
- }
-
- ret = usb_control_msg(priv->usb,
- usb_rcvctrlpipe(priv->usb, 0),
- request, 0xc0, value,
- index, usb_buffer, length, USB_CTL_WAIT);
-
- if (ret == length)
- memcpy(buffer, usb_buffer, length);
-
- kfree(usb_buffer);
-
- if (ret == (int)length)
- ret = 0;
- else
- ret = -EIO;
-
-end_unlock:
- mutex_unlock(&priv->usb_lock);
-end:
- return ret;
-}
-
-int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data)
-{
- return vnt_control_in(priv, MESSAGE_TYPE_READ,
- reg_off, reg, sizeof(u8), data);
-}
-
-static int vnt_int_report_rate(struct vnt_private *priv, u8 pkt_no, u8 tsr)
-{
- struct vnt_usb_send_context *context;
- struct ieee80211_tx_info *info;
- u8 tx_retry = (tsr & 0xf0) >> 4;
- s8 idx;
-
- if (pkt_no >= priv->num_tx_context)
- return -EINVAL;
-
- context = priv->tx_context[pkt_no];
-
- if (!context->skb)
- return -EINVAL;
-
- info = IEEE80211_SKB_CB(context->skb);
- idx = info->control.rates[0].idx;
-
- ieee80211_tx_info_clear_status(info);
-
- info->status.rates[0].count = tx_retry;
-
- if (!(tsr & TSR_TMO)) {
- info->status.rates[0].idx = idx;
-
- if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
- info->flags |= IEEE80211_TX_STAT_ACK;
- }
-
- ieee80211_tx_status_irqsafe(priv->hw, context->skb);
-
- context->in_use = false;
-
- return 0;
-}
-
-static void vnt_int_process_data(struct vnt_private *priv)
-{
- struct vnt_interrupt_data *int_data;
- struct ieee80211_low_level_stats *low_stats = &priv->low_stats;
-
- dev_dbg(&priv->usb->dev, "---->s_nsInterruptProcessData\n");
-
- int_data = (struct vnt_interrupt_data *)priv->int_buf.data_buf;
-
- if (int_data->tsr0 & TSR_VALID)
- vnt_int_report_rate(priv, int_data->pkt0, int_data->tsr0);
-
- if (int_data->tsr1 & TSR_VALID)
- vnt_int_report_rate(priv, int_data->pkt1, int_data->tsr1);
-
- if (int_data->tsr2 & TSR_VALID)
- vnt_int_report_rate(priv, int_data->pkt2, int_data->tsr2);
-
- if (int_data->tsr3 & TSR_VALID)
- vnt_int_report_rate(priv, int_data->pkt3, int_data->tsr3);
-
- if (!int_data->isr0)
- return;
-
- if (int_data->isr0 & ISR_BNTX && priv->op_mode == NL80211_IFTYPE_AP)
- vnt_schedule_command(priv, WLAN_CMD_BECON_SEND);
-
- priv->current_tsf = le64_to_cpu(int_data->tsf);
-
- low_stats->dot11RTSSuccessCount += int_data->rts_success;
- low_stats->dot11RTSFailureCount += int_data->rts_fail;
- low_stats->dot11ACKFailureCount += int_data->ack_fail;
- low_stats->dot11FCSErrorCount += int_data->fcs_err;
-}
-
-static void vnt_start_interrupt_urb_complete(struct urb *urb)
-{
- struct vnt_private *priv = urb->context;
- int status = urb->status;
-
- switch (status) {
- case 0:
- case -ETIMEDOUT:
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- return;
- default:
- break;
- }
-
- if (status)
- dev_dbg(&priv->usb->dev, "%s status = %d\n", __func__, status);
- else
- vnt_int_process_data(priv);
-
- if (!test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
- status = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
-
- if (status)
- dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", status);
-}
-
-int vnt_start_interrupt_urb(struct vnt_private *priv)
-{
- int ret = 0;
-
- dev_dbg(&priv->usb->dev, "---->Interrupt Polling Thread\n");
-
- usb_fill_int_urb(priv->interrupt_urb,
- priv->usb,
- usb_rcvintpipe(priv->usb, 1),
- priv->int_buf.data_buf,
- MAX_INTERRUPT_SIZE,
- vnt_start_interrupt_urb_complete,
- priv,
- priv->int_interval);
-
- ret = usb_submit_urb(priv->interrupt_urb, GFP_ATOMIC);
- if (ret)
- dev_dbg(&priv->usb->dev, "Submit int URB failed %d\n", ret);
-
- return ret;
-}
-
-static int vnt_rx_data(struct vnt_private *priv, struct vnt_rcb *ptr_rcb,
- unsigned long bytes_received)
-{
- struct ieee80211_hw *hw = priv->hw;
- struct ieee80211_supported_band *sband;
- struct sk_buff *skb;
- struct ieee80211_rx_status *rx_status;
- struct vnt_rx_header *head;
- struct vnt_rx_tail *tail;
- u32 frame_size;
- int ii;
- u16 rx_bitrate, pay_load_with_padding;
- u8 rate_idx = 0;
- long rx_dbm;
-
- skb = ptr_rcb->skb;
- rx_status = IEEE80211_SKB_RXCB(skb);
-
- /* [31:16]RcvByteCount ( not include 4-byte Status ) */
- head = (struct vnt_rx_header *)skb->data;
- frame_size = head->wbk_status >> 16;
- frame_size += 4;
-
- if (bytes_received != frame_size) {
- dev_dbg(&priv->usb->dev, "------- WRONG Length 1\n");
- return false;
- }
-
- if ((bytes_received > 2372) || (bytes_received <= 40)) {
- /* Frame Size error drop this packet.*/
- dev_dbg(&priv->usb->dev, "------ WRONG Length 2\n");
- return false;
- }
-
- /* real Frame Size = USBframe_size -4WbkStatus - 4RxStatus */
- /* -8TSF - 4RSR - 4SQ3 - ?Padding */
-
- /* if SQ3 the range is 24~27, if no SQ3 the range is 20~23 */
-
- /*Fix hardware bug => PLCP_Length error */
- if (((bytes_received - head->pay_load_len) > 27) ||
- ((bytes_received - head->pay_load_len) < 24) ||
- (bytes_received < head->pay_load_len)) {
- dev_dbg(&priv->usb->dev, "Wrong PLCP Length %x\n",
- head->pay_load_len);
- return false;
- }
-
- sband = hw->wiphy->bands[hw->conf.chandef.chan->band];
- rx_bitrate = head->rx_rate * 5; /* rx_rate * 5 */
-
- for (ii = 0; ii < sband->n_bitrates; ii++) {
- if (sband->bitrates[ii].bitrate == rx_bitrate) {
- rate_idx = ii;
- break;
- }
- }
-
- if (ii == sband->n_bitrates) {
- dev_dbg(&priv->usb->dev, "Wrong Rx Bit Rate %d\n", rx_bitrate);
- return false;
- }
-
- pay_load_with_padding = ((head->pay_load_len / 4) +
- ((head->pay_load_len % 4) ? 1 : 0)) * 4;
-
- tail = (struct vnt_rx_tail *)(skb->data +
- sizeof(*head) + pay_load_with_padding);
- priv->tsf_time = le64_to_cpu(tail->tsf_time);
-
- if (tail->rsr & (RSR_IVLDTYP | RSR_IVLDLEN))
- return false;
-
- vnt_rf_rssi_to_dbm(priv, tail->rssi, &rx_dbm);
-
- priv->bb_pre_ed_rssi = (u8)-rx_dbm + 1;
- priv->current_rssi = priv->bb_pre_ed_rssi;
-
- skb_pull(skb, sizeof(*head));
- skb_trim(skb, head->pay_load_len);
-
- rx_status->mactime = priv->tsf_time;
- rx_status->band = hw->conf.chandef.chan->band;
- rx_status->signal = rx_dbm;
- rx_status->flag = 0;
- rx_status->freq = hw->conf.chandef.chan->center_freq;
-
- if (!(tail->rsr & RSR_CRCOK))
- rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
-
- rx_status->rate_idx = rate_idx;
-
- if (tail->new_rsr & NEWRSR_DECRYPTOK)
- rx_status->flag |= RX_FLAG_DECRYPTED;
-
- ieee80211_rx_irqsafe(priv->hw, skb);
-
- return true;
-}
-
-static void vnt_submit_rx_urb_complete(struct urb *urb)
-{
- struct vnt_rcb *rcb = urb->context;
- struct vnt_private *priv = rcb->priv;
-
- switch (urb->status) {
- case 0:
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- return;
- case -ETIMEDOUT:
- default:
- dev_dbg(&priv->usb->dev, "BULK In failed %d\n", urb->status);
- break;
- }
-
- if (urb->actual_length) {
- if (vnt_rx_data(priv, rcb, urb->actual_length)) {
- rcb->skb = dev_alloc_skb(priv->rx_buf_sz);
- if (!rcb->skb)
- return;
- } else {
- skb_push(rcb->skb, skb_headroom(rcb->skb));
- skb_trim(rcb->skb, 0);
- }
-
- urb->transfer_buffer = skb_put(rcb->skb,
- skb_tailroom(rcb->skb));
- }
-
- if (usb_submit_urb(urb, GFP_ATOMIC))
- dev_dbg(&priv->usb->dev, "Failed to re submit rx skb\n");
-}
-
-int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb)
-{
- int ret = 0;
- struct urb *urb = rcb->urb;
-
- if (!rcb->skb) {
- dev_dbg(&priv->usb->dev, "rcb->skb is null\n");
- ret = -EINVAL;
- goto end;
- }
-
- usb_fill_bulk_urb(urb,
- priv->usb,
- usb_rcvbulkpipe(priv->usb, 2),
- skb_put(rcb->skb, skb_tailroom(rcb->skb)),
- MAX_TOTAL_SIZE_WITH_ALL_HEADERS,
- vnt_submit_rx_urb_complete,
- rcb);
-
- ret = usb_submit_urb(urb, GFP_ATOMIC);
- if (ret)
- dev_dbg(&priv->usb->dev, "Submit Rx URB failed %d\n", ret);
-end:
- return ret;
-}
-
-static void vnt_tx_context_complete(struct urb *urb)
-{
- struct vnt_usb_send_context *context = urb->context;
- struct vnt_private *priv = context->priv;
-
- switch (urb->status) {
- case 0:
- dev_dbg(&priv->usb->dev,
- "Write %d bytes\n", urb->actual_length);
- break;
- case -ECONNRESET:
- case -ENOENT:
- case -ESHUTDOWN:
- context->in_use = false;
- return;
- case -ETIMEDOUT:
- default:
- dev_dbg(&priv->usb->dev, "BULK Out failed %d\n", urb->status);
- break;
- }
-
- if (context->type == CONTEXT_DATA_PACKET)
- ieee80211_wake_queues(priv->hw);
-
- if (urb->status || context->type == CONTEXT_BEACON_PACKET) {
- if (context->skb)
- ieee80211_free_txskb(priv->hw, context->skb);
-
- context->in_use = false;
- }
-}
-
-int vnt_tx_context(struct vnt_private *priv,
- struct vnt_usb_send_context *context,
- struct sk_buff *skb)
-{
- struct vnt_tx_usb_header *usb;
- struct urb *urb;
- int status;
- u16 count = skb->len;
-
- usb = skb_push(skb, sizeof(*usb));
- usb->tx_byte_count = cpu_to_le16(count);
- usb->pkt_no = context->pkt_no;
- usb->type = context->type;
-
- if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags)) {
- context->in_use = false;
- return -ENODEV;
- }
-
- if (skb->len > MAX_TOTAL_SIZE_WITH_ALL_HEADERS) {
- context->in_use = false;
- return -E2BIG;
- }
-
- urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!urb) {
- context->in_use = false;
- return -ENOMEM;
- }
-
- usb_fill_bulk_urb(urb,
- priv->usb,
- usb_sndbulkpipe(priv->usb, 3),
- skb->data,
- skb->len,
- vnt_tx_context_complete,
- context);
-
- usb_anchor_urb(urb, &priv->tx_submitted);
-
- status = usb_submit_urb(urb, GFP_ATOMIC);
- if (status) {
- dev_dbg(&priv->usb->dev, "Submit Tx URB failed %d\n", status);
- usb_unanchor_urb(urb);
- context->in_use = false;
- }
-
- usb_free_urb(urb);
-
- return status;
-}
diff --git a/drivers/staging/vt6656/usbpipe.h b/drivers/staging/vt6656/usbpipe.h
deleted file mode 100644
index 922312e299bf..000000000000
--- a/drivers/staging/vt6656/usbpipe.h
+++ /dev/null
@@ -1,67 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose:
- *
- * Author: Warren Hsu
- *
- * Date: Mar. 30, 2005
- *
- */
-
-#ifndef __USBPIPE_H__
-#define __USBPIPE_H__
-
-#include "device.h"
-
-struct vnt_interrupt_data {
- u8 tsr0;
- u8 pkt0;
- u16 time0;
- u8 tsr1;
- u8 pkt1;
- u16 time1;
- u8 tsr2;
- u8 pkt2;
- u16 time2;
- u8 tsr3;
- u8 pkt3;
- u16 time3;
- __le64 tsf;
- u8 isr0;
- u8 isr1;
- u8 rts_success;
- u8 rts_fail;
- u8 ack_fail;
- u8 fcs_err;
- u8 sw[2];
-} __packed;
-
-struct vnt_tx_usb_header {
- u8 type;
- u8 pkt_no;
- __le16 tx_byte_count;
-} __packed;
-
-#define VNT_REG_BLOCK_SIZE 64
-
-int vnt_control_out(struct vnt_private *priv, u8 request, u16 value,
- u16 index, u16 length, const u8 *buffer);
-int vnt_control_in(struct vnt_private *priv, u8 request, u16 value,
- u16 index, u16 length, u8 *buffer);
-
-int vnt_control_out_u8(struct vnt_private *priv, u8 reg, u8 ref_off, u8 data);
-int vnt_control_in_u8(struct vnt_private *priv, u8 reg, u8 reg_off, u8 *data);
-
-int vnt_control_out_blocks(struct vnt_private *priv,
- u16 block, u8 reg, u16 len, const u8 *data);
-
-int vnt_start_interrupt_urb(struct vnt_private *priv);
-int vnt_submit_rx_urb(struct vnt_private *priv, struct vnt_rcb *rcb);
-int vnt_tx_context(struct vnt_private *priv,
- struct vnt_usb_send_context *context,
- struct sk_buff *skb);
-
-#endif /* __USBPIPE_H__ */
diff --git a/drivers/staging/vt6656/wcmd.c b/drivers/staging/vt6656/wcmd.c
deleted file mode 100644
index 14b8aa587119..000000000000
--- a/drivers/staging/vt6656/wcmd.c
+++ /dev/null
@@ -1,185 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles the management command interface functions
- *
- * Author: Lyndon Chen
- *
- * Date: May 8, 2003
- *
- * Functions:
- * vnt_cmd_complete - Command Complete function
- * vnt_schedule_command - Push Command and wait Command Scheduler to do
- * vnt_cmd_timer_wait- Call back timer
- *
- * Revision History:
- *
- */
-
-#include "device.h"
-#include "mac.h"
-#include "wcmd.h"
-#include "power.h"
-#include "usbpipe.h"
-#include "rxtx.h"
-#include "rf.h"
-
-static void vnt_cmd_timer_wait(struct vnt_private *priv, unsigned long msecs)
-{
- schedule_delayed_work(&priv->run_command_work, msecs_to_jiffies(msecs));
-}
-
-static u32 add_one_with_wrap_around(u32 var, u8 modulo)
-{
- if (var >= (modulo - 1))
- var = 0;
- else
- var++;
- return var;
-}
-
-static int vnt_cmd_complete(struct vnt_private *priv)
-{
- priv->command_state = WLAN_CMD_IDLE;
- if (priv->free_cmd_queue == CMD_Q_SIZE) {
- /* Command Queue Empty */
- priv->cmd_running = false;
- return true;
- }
-
- priv->command = priv->cmd_queue[priv->cmd_dequeue_idx];
-
- priv->cmd_dequeue_idx = add_one_with_wrap_around(priv->cmd_dequeue_idx, CMD_Q_SIZE);
- priv->free_cmd_queue++;
- priv->cmd_running = true;
-
- switch (priv->command) {
- case WLAN_CMD_INIT_MAC80211:
- priv->command_state = WLAN_CMD_INIT_MAC80211_START;
- break;
-
- case WLAN_CMD_TBTT_WAKEUP:
- priv->command_state = WLAN_CMD_TBTT_WAKEUP_START;
- break;
-
- case WLAN_CMD_BECON_SEND:
- priv->command_state = WLAN_CMD_BECON_SEND_START;
- break;
-
- case WLAN_CMD_SETPOWER:
- priv->command_state = WLAN_CMD_SETPOWER_START;
- break;
-
- case WLAN_CMD_CHANGE_ANTENNA:
- priv->command_state = WLAN_CMD_CHANGE_ANTENNA_START;
- break;
-
- default:
- break;
- }
-
- vnt_cmd_timer_wait(priv, 0);
-
- return true;
-}
-
-void vnt_run_command(struct work_struct *work)
-{
- struct vnt_private *priv =
- container_of(work, struct vnt_private, run_command_work.work);
-
- if (test_bit(DEVICE_FLAGS_DISCONNECTED, &priv->flags))
- return;
-
- if (!priv->cmd_running)
- return;
-
- switch (priv->command_state) {
- case WLAN_CMD_INIT_MAC80211_START:
- if (priv->mac_hw)
- break;
-
- dev_info(&priv->usb->dev, "Starting mac80211\n");
-
- if (vnt_init(priv)) {
- /* If fail all ends TODO retry */
- dev_err(&priv->usb->dev, "failed to start\n");
- usb_set_intfdata(priv->intf, NULL);
- ieee80211_free_hw(priv->hw);
- return;
- }
-
- break;
-
- case WLAN_CMD_TBTT_WAKEUP_START:
- vnt_next_tbtt_wakeup(priv);
- break;
-
- case WLAN_CMD_BECON_SEND_START:
- if (!priv->vif)
- break;
-
- vnt_beacon_make(priv, priv->vif);
-
- vnt_mac_reg_bits_on(priv, MAC_REG_TCR, TCR_AUTOBCNTX);
-
- break;
-
- case WLAN_CMD_SETPOWER_START:
-
- vnt_rf_setpower(priv, priv->hw->conf.chandef.chan);
-
- break;
-
- case WLAN_CMD_CHANGE_ANTENNA_START:
- dev_dbg(&priv->usb->dev, "Change from Antenna%d to",
- priv->rx_antenna_sel);
-
- if (priv->rx_antenna_sel == 0) {
- priv->rx_antenna_sel = 1;
- if (priv->tx_rx_ant_inv)
- vnt_set_antenna_mode(priv, ANT_RXA);
- else
- vnt_set_antenna_mode(priv, ANT_RXB);
- } else {
- priv->rx_antenna_sel = 0;
- if (priv->tx_rx_ant_inv)
- vnt_set_antenna_mode(priv, ANT_RXB);
- else
- vnt_set_antenna_mode(priv, ANT_RXA);
- }
- break;
-
- default:
- break;
- }
-
- vnt_cmd_complete(priv);
-}
-
-int vnt_schedule_command(struct vnt_private *priv, enum vnt_cmd command)
-{
- if (priv->free_cmd_queue == 0)
- return false;
-
- priv->cmd_queue[priv->cmd_enqueue_idx] = command;
-
- priv->cmd_enqueue_idx = add_one_with_wrap_around(priv->cmd_enqueue_idx, CMD_Q_SIZE);
- priv->free_cmd_queue--;
-
- if (!priv->cmd_running)
- vnt_cmd_complete(priv);
-
- return true;
-}
-
-void vnt_reset_command_timer(struct vnt_private *priv)
-{
- priv->free_cmd_queue = CMD_Q_SIZE;
- priv->cmd_dequeue_idx = 0;
- priv->cmd_enqueue_idx = 0;
- priv->command_state = WLAN_CMD_IDLE;
- priv->cmd_running = false;
-}
diff --git a/drivers/staging/vt6656/wcmd.h b/drivers/staging/vt6656/wcmd.h
deleted file mode 100644
index a62924671b17..000000000000
--- a/drivers/staging/vt6656/wcmd.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
-/*
- * Copyright (c) 1996, 2003 VIA Networking Technologies, Inc.
- * All rights reserved.
- *
- * Purpose: Handles the management command interface functions
- *
- * Author: Lyndon Chen
- *
- * Date: May 8, 2002
- *
- */
-
-#ifndef __WCMD_H__
-#define __WCMD_H__
-
-#include "device.h"
-
-/* Command code */
-enum vnt_cmd {
- WLAN_CMD_INIT_MAC80211,
- WLAN_CMD_SETPOWER,
- WLAN_CMD_TBTT_WAKEUP,
- WLAN_CMD_BECON_SEND,
- WLAN_CMD_CHANGE_ANTENNA
-};
-
-#define CMD_Q_SIZE 32
-
-/* Command state */
-enum vnt_cmd_state {
- WLAN_CMD_INIT_MAC80211_START,
- WLAN_CMD_SETPOWER_START,
- WLAN_CMD_TBTT_WAKEUP_START,
- WLAN_CMD_BECON_SEND_START,
- WLAN_CMD_CHANGE_ANTENNA_START,
- WLAN_CMD_IDLE
-};
-
-struct vnt_private;
-
-void vnt_reset_command_timer(struct vnt_private *priv);
-
-int vnt_schedule_command(struct vnt_private *priv, enum vnt_cmd);
-
-void vnt_run_command(struct work_struct *work);
-
-#endif /* __WCMD_H__ */
diff --git a/drivers/target/target_core_user.c b/drivers/target/target_core_user.c
index 717931267bda..0f5d820af119 100644
--- a/drivers/target/target_core_user.c
+++ b/drivers/target/target_core_user.c
@@ -361,7 +361,7 @@ static const struct genl_multicast_group tcmu_mcgrps[] = {
[TCMU_MCGRP_CONFIG] = { .name = "config", },
};
-static struct nla_policy tcmu_attr_policy[TCMU_ATTR_MAX+1] = {
+static const struct nla_policy tcmu_attr_policy[TCMU_ATTR_MAX + 1] = {
[TCMU_ATTR_DEVICE] = { .type = NLA_STRING },
[TCMU_ATTR_MINOR] = { .type = NLA_U32 },
[TCMU_ATTR_CMD_STATUS] = { .type = NLA_S32 },
@@ -2430,7 +2430,7 @@ enum {
Opt_cmd_ring_size_mb, Opt_err,
};
-static match_table_t tokens = {
+static const match_table_t tokens = {
{Opt_dev_config, "dev_config=%s"},
{Opt_dev_size, "dev_size=%s"},
{Opt_hw_block_size, "hw_block_size=%d"},
diff --git a/drivers/tee/optee/smc_abi.c b/drivers/tee/optee/smc_abi.c
index e9456e3e74cc..3e33cf2af73b 100644
--- a/drivers/tee/optee/smc_abi.c
+++ b/drivers/tee/optee/smc_abi.c
@@ -1817,7 +1817,7 @@ MODULE_DEVICE_TABLE(of, optee_dt_match);
static struct platform_driver optee_driver = {
.probe = optee_probe,
- .remove_new = optee_smc_remove,
+ .remove = optee_smc_remove,
.shutdown = optee_shutdown,
.driver = {
.name = "optee",
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
index 7c46dd6bee73..c868d8b7bd1c 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device.c
@@ -454,8 +454,8 @@ void proc_thermal_mmio_remove(struct pci_dev *pdev, struct proc_thermal_device *
}
EXPORT_SYMBOL_GPL(proc_thermal_mmio_remove);
-MODULE_IMPORT_NS(INTEL_TCC);
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INTEL_TCC");
+MODULE_IMPORT_NS("INT340X_THERMAL");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
index ba5d36d36fc4..145d471546d5 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_device_pci.c
@@ -510,7 +510,7 @@ static struct pci_driver proc_thermal_pci_driver = {
module_pci_driver(proc_thermal_pci_driver);
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INT340X_THERMAL");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_DESCRIPTION("Processor Thermal Reporting Device Driver");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c
index af2ec0beb7a1..b1d531ef440f 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_mbox.c
@@ -94,7 +94,7 @@ int processor_thermal_send_mbox_read_cmd(struct pci_dev *pdev, u16 id, u64 *resp
return ret;
}
-EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_read_cmd, "INT340X_THERMAL");
int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data)
{
@@ -106,7 +106,7 @@ int processor_thermal_send_mbox_write_cmd(struct pci_dev *pdev, u16 id, u32 data
return ret;
}
-EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(processor_thermal_send_mbox_write_cmd, "INT340X_THERMAL");
#define MBOX_CAMARILLO_RD_INTR_CONFIG 0x1E
#define MBOX_CAMARILLO_WR_INTR_CONFIG 0x1F
@@ -153,7 +153,7 @@ unlock:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(processor_thermal_mbox_interrupt_config, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(processor_thermal_mbox_interrupt_config, "INT340X_THERMAL");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Processor Thermal Mail Box Interface");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c
index d6b787ca2741..25cdbb6d91a6 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_power_floor.c
@@ -42,7 +42,7 @@ int proc_thermal_read_power_floor_status(struct proc_thermal_device *proc_priv)
status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
return (status & SOC_POWER_FLOOR_STATUS) >> SOC_POWER_FLOOR_SHIFT;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_read_power_floor_status, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_read_power_floor_status, "INT340X_THERMAL");
static bool enable_state;
static DEFINE_MUTEX(pf_lock);
@@ -69,13 +69,13 @@ pf_unlock:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_set_state, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_set_state, "INT340X_THERMAL");
bool proc_thermal_power_floor_get_state(struct proc_thermal_device *proc_priv)
{
return enable_state;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_get_state, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_get_state, "INT340X_THERMAL");
/**
* proc_thermal_check_power_floor_intr() - Check power floor interrupt.
@@ -94,7 +94,7 @@ bool proc_thermal_check_power_floor_intr(struct proc_thermal_device *proc_priv)
int_status = readq(proc_priv->mmio_base + SOC_WT_RES_INT_STATUS_OFFSET);
return !!(int_status & SOC_POWER_FLOOR_INT_ACTIVE);
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_check_power_floor_intr, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_check_power_floor_intr, "INT340X_THERMAL");
/**
* proc_thermal_power_floor_intr_callback() - Process power floor notification
@@ -120,8 +120,8 @@ void proc_thermal_power_floor_intr_callback(struct pci_dev *pdev,
sysfs_notify(&pdev->dev.kobj, "power_limits", "power_floor_status");
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_intr_callback, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_power_floor_intr_callback, "INT340X_THERMAL");
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INT340X_THERMAL");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Processor Thermal power floor notification Interface");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
index 0e2dc1426282..dad63f2d5f90 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_rfim.c
@@ -9,7 +9,7 @@
#include <linux/pci.h>
#include "processor_thermal_device.h"
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INT340X_THERMAL");
struct mmio_reg {
int read_only;
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c
index e947d84f4977..68e8391af8f4 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_hint.c
@@ -204,7 +204,7 @@ bool proc_thermal_check_wt_intr(struct proc_thermal_device *proc_priv)
return false;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_check_wt_intr, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_check_wt_intr, "INT340X_THERMAL");
/* Callback to notify user space */
void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_device *proc_priv)
@@ -217,7 +217,7 @@ void proc_thermal_wt_intr_callback(struct pci_dev *pdev, struct proc_thermal_dev
sysfs_notify(&pdev->dev.kobj, "workload_hint", "workload_type_index");
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_intr_callback, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_intr_callback, "INT340X_THERMAL");
static bool workload_hint_created;
@@ -233,7 +233,7 @@ int proc_thermal_wt_hint_add(struct pci_dev *pdev, struct proc_thermal_device *p
return 0;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_add, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_add, "INT340X_THERMAL");
void proc_thermal_wt_hint_remove(struct pci_dev *pdev)
{
@@ -249,8 +249,8 @@ void proc_thermal_wt_hint_remove(struct pci_dev *pdev)
workload_hint_created = false;
}
-EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_remove, INT340X_THERMAL);
+EXPORT_SYMBOL_NS_GPL(proc_thermal_wt_hint_remove, "INT340X_THERMAL");
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INT340X_THERMAL");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Processor Thermal Work Load type hint Interface");
diff --git a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c
index f298e7442662..b95810f4a011 100644
--- a/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c
+++ b/drivers/thermal/intel/int340x_thermal/processor_thermal_wt_req.c
@@ -132,6 +132,6 @@ void proc_thermal_wt_req_remove(struct pci_dev *pdev)
}
EXPORT_SYMBOL_GPL(proc_thermal_wt_req_remove);
-MODULE_IMPORT_NS(INT340X_THERMAL);
+MODULE_IMPORT_NS("INT340X_THERMAL");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Processor Thermal Work Load type request Interface");
diff --git a/drivers/thermal/intel/intel_powerclamp.c b/drivers/thermal/intel/intel_powerclamp.c
index 4ba649370aa1..96a24df79686 100644
--- a/drivers/thermal/intel/intel_powerclamp.c
+++ b/drivers/thermal/intel/intel_powerclamp.c
@@ -809,7 +809,7 @@ static void __exit powerclamp_exit(void)
}
module_exit(powerclamp_exit);
-MODULE_IMPORT_NS(IDLE_INJECT);
+MODULE_IMPORT_NS("IDLE_INJECT");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Arjan van de Ven <arjan@linux.intel.com>");
diff --git a/drivers/thermal/intel/intel_soc_dts_iosf.c b/drivers/thermal/intel/intel_soc_dts_iosf.c
index 43a29551ba17..ea87439fe7a9 100644
--- a/drivers/thermal/intel/intel_soc_dts_iosf.c
+++ b/drivers/thermal/intel/intel_soc_dts_iosf.c
@@ -388,6 +388,6 @@ void intel_soc_dts_iosf_exit(struct intel_soc_dts_sensors *sensors)
}
EXPORT_SYMBOL_GPL(intel_soc_dts_iosf_exit);
-MODULE_IMPORT_NS(INTEL_TCC);
+MODULE_IMPORT_NS("INTEL_TCC");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("SoC DTS driver using side band interface");
diff --git a/drivers/thermal/intel/intel_tcc.c b/drivers/thermal/intel/intel_tcc.c
index c86654f28aa5..817421508d5c 100644
--- a/drivers/thermal/intel/intel_tcc.c
+++ b/drivers/thermal/intel/intel_tcc.c
@@ -150,7 +150,7 @@ u32 intel_tcc_get_offset_mask(void)
{
return intel_tcc_temp_masks.tcc_offset;
}
-EXPORT_SYMBOL_NS(intel_tcc_get_offset_mask, INTEL_TCC);
+EXPORT_SYMBOL_NS(intel_tcc_get_offset_mask, "INTEL_TCC");
/**
* get_temp_mask() - Returns the model-specific bitmask for temperature
@@ -195,7 +195,7 @@ int intel_tcc_get_tjmax(int cpu)
return val ? val : -ENODATA;
}
-EXPORT_SYMBOL_NS_GPL(intel_tcc_get_tjmax, INTEL_TCC);
+EXPORT_SYMBOL_NS_GPL(intel_tcc_get_tjmax, "INTEL_TCC");
/**
* intel_tcc_get_offset() - returns the TCC Offset value to Tjmax
@@ -220,7 +220,7 @@ int intel_tcc_get_offset(int cpu)
return (low >> 24) & intel_tcc_temp_masks.tcc_offset;
}
-EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, INTEL_TCC);
+EXPORT_SYMBOL_NS_GPL(intel_tcc_get_offset, "INTEL_TCC");
/**
* intel_tcc_set_offset() - set the TCC offset value to Tjmax
@@ -263,7 +263,7 @@ int intel_tcc_set_offset(int cpu, int offset)
else
return wrmsr_safe_on_cpu(cpu, MSR_IA32_TEMPERATURE_TARGET, low, high);
}
-EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, INTEL_TCC);
+EXPORT_SYMBOL_NS_GPL(intel_tcc_set_offset, "INTEL_TCC");
/**
* intel_tcc_get_temp() - returns the current temperature
@@ -303,4 +303,4 @@ int intel_tcc_get_temp(int cpu, int *temp, bool pkg)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, INTEL_TCC);
+EXPORT_SYMBOL_NS_GPL(intel_tcc_get_temp, "INTEL_TCC");
diff --git a/drivers/thermal/intel/intel_tcc_cooling.c b/drivers/thermal/intel/intel_tcc_cooling.c
index 17110ffa80bb..9ff0ebdde0ef 100644
--- a/drivers/thermal/intel/intel_tcc_cooling.c
+++ b/drivers/thermal/intel/intel_tcc_cooling.c
@@ -118,7 +118,7 @@ static void __exit tcc_cooling_exit(void)
module_exit(tcc_cooling_exit)
-MODULE_IMPORT_NS(INTEL_TCC);
+MODULE_IMPORT_NS("INTEL_TCC");
MODULE_DESCRIPTION("TCC offset cooling device Driver");
MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/intel/x86_pkg_temp_thermal.c b/drivers/thermal/intel/x86_pkg_temp_thermal.c
index 65b33b56a9be..496abf8e55e0 100644
--- a/drivers/thermal/intel/x86_pkg_temp_thermal.c
+++ b/drivers/thermal/intel/x86_pkg_temp_thermal.c
@@ -524,7 +524,7 @@ static void __exit pkg_temp_thermal_exit(void)
}
module_exit(pkg_temp_thermal_exit)
-MODULE_IMPORT_NS(INTEL_TCC);
+MODULE_IMPORT_NS("INTEL_TCC");
MODULE_DESCRIPTION("X86 PKG TEMP Thermal Driver");
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/thermal/thermal_hwmon.c b/drivers/thermal/thermal_hwmon.c
index 37da7a8ea948..0ecccd4d8556 100644
--- a/drivers/thermal/thermal_hwmon.c
+++ b/drivers/thermal/thermal_hwmon.c
@@ -284,4 +284,4 @@ int devm_thermal_add_hwmon_sysfs(struct device *dev, struct thermal_zone_device
}
EXPORT_SYMBOL_GPL(devm_thermal_add_hwmon_sysfs);
-MODULE_IMPORT_NS(HWMON_THERMAL);
+MODULE_IMPORT_NS("HWMON_THERMAL");
diff --git a/drivers/thermal/thermal_thresholds.c b/drivers/thermal/thermal_thresholds.c
index d9b2a0bb44fc..38f5fd0e8930 100644
--- a/drivers/thermal/thermal_thresholds.c
+++ b/drivers/thermal/thermal_thresholds.c
@@ -69,58 +69,60 @@ static struct user_threshold *__thermal_thresholds_find(const struct list_head *
return NULL;
}
-static bool __thermal_threshold_is_crossed(struct user_threshold *threshold, int temperature,
- int last_temperature, int direction,
- int *low, int *high)
+static bool thermal_thresholds_handle_raising(struct list_head *thresholds, int temperature,
+ int last_temperature)
{
+ struct user_threshold *t;
- if (temperature >= threshold->temperature) {
- if (threshold->temperature > *low &&
- THERMAL_THRESHOLD_WAY_DOWN & threshold->direction)
- *low = threshold->temperature;
+ list_for_each_entry(t, thresholds, list_node) {
- if (last_temperature < threshold->temperature &&
- threshold->direction & direction)
- return true;
- } else {
- if (threshold->temperature < *high && THERMAL_THRESHOLD_WAY_UP
- & threshold->direction)
- *high = threshold->temperature;
+ if (!(t->direction & THERMAL_THRESHOLD_WAY_UP))
+ continue;
- if (last_temperature >= threshold->temperature &&
- threshold->direction & direction)
+ if (temperature >= t->temperature &&
+ last_temperature < t->temperature)
return true;
}
return false;
}
-static bool thermal_thresholds_handle_raising(struct list_head *thresholds, int temperature,
- int last_temperature, int *low, int *high)
+static bool thermal_thresholds_handle_dropping(struct list_head *thresholds, int temperature,
+ int last_temperature)
{
struct user_threshold *t;
- list_for_each_entry(t, thresholds, list_node) {
- if (__thermal_threshold_is_crossed(t, temperature, last_temperature,
- THERMAL_THRESHOLD_WAY_UP, low, high))
+ list_for_each_entry_reverse(t, thresholds, list_node) {
+
+ if (!(t->direction & THERMAL_THRESHOLD_WAY_DOWN))
+ continue;
+
+ if (temperature <= t->temperature &&
+ last_temperature > t->temperature)
return true;
}
return false;
}
-static bool thermal_thresholds_handle_dropping(struct list_head *thresholds, int temperature,
- int last_temperature, int *low, int *high)
+static void thermal_threshold_find_boundaries(struct list_head *thresholds, int temperature,
+ int *low, int *high)
{
struct user_threshold *t;
- list_for_each_entry_reverse(t, thresholds, list_node) {
- if (__thermal_threshold_is_crossed(t, temperature, last_temperature,
- THERMAL_THRESHOLD_WAY_DOWN, low, high))
- return true;
+ list_for_each_entry(t, thresholds, list_node) {
+ if (temperature < t->temperature &&
+ (t->direction & THERMAL_THRESHOLD_WAY_UP) &&
+ *high > t->temperature)
+ *high = t->temperature;
}
- return false;
+ list_for_each_entry_reverse(t, thresholds, list_node) {
+ if (temperature > t->temperature &&
+ (t->direction & THERMAL_THRESHOLD_WAY_DOWN) &&
+ *low < t->temperature)
+ *low = t->temperature;
+ }
}
void thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *high)
@@ -132,6 +134,8 @@ void thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *hi
lockdep_assert_held(&tz->lock);
+ thermal_threshold_find_boundaries(thresholds, temperature, low, high);
+
/*
* We need a second update in order to detect a threshold being crossed
*/
@@ -151,12 +155,12 @@ void thermal_thresholds_handle(struct thermal_zone_device *tz, int *low, int *hi
* - decreased : thresholds are crossed the way down
*/
if (temperature > last_temperature) {
- if (thermal_thresholds_handle_raising(thresholds, temperature,
- last_temperature, low, high))
+ if (thermal_thresholds_handle_raising(thresholds,
+ temperature, last_temperature))
thermal_notify_threshold_up(tz);
} else {
- if (thermal_thresholds_handle_dropping(thresholds, temperature,
- last_temperature, low, high))
+ if (thermal_thresholds_handle_dropping(thresholds,
+ temperature, last_temperature))
thermal_notify_threshold_down(tz);
}
}
diff --git a/drivers/thunderbolt/debugfs.c b/drivers/thunderbolt/debugfs.c
index 350310bd0fee..a1d0d8a33f20 100644
--- a/drivers/thunderbolt/debugfs.c
+++ b/drivers/thunderbolt/debugfs.c
@@ -7,6 +7,7 @@
* Mika Westerberg <mika.westerberg@linux.intel.com>
*/
+#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
@@ -43,6 +44,24 @@
#define MAX_DWELL_TIME 500 /* ms */
#define DWELL_SAMPLE_INTERVAL 10
+enum usb4_margin_cap_voltage_indp {
+ USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_MIN,
+ USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_HL,
+ USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_BOTH,
+ USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_MIN,
+ USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_BOTH,
+ USB4_MARGIN_CAP_VOLTAGE_INDP_UNKNOWN,
+};
+
+enum usb4_margin_cap_time_indp {
+ USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_MIN,
+ USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_LR,
+ USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_BOTH,
+ USB4_MARGIN_CAP_TIME_INDP_GEN_4_MIN,
+ USB4_MARGIN_CAP_TIME_INDP_GEN_4_BOTH,
+ USB4_MARGIN_CAP_TIME_INDP_UNKNOWN,
+};
+
/* Sideband registers and their sizes as defined in the USB4 spec */
struct sb_reg {
unsigned int reg;
@@ -395,6 +414,8 @@ out:
* @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @dev: Pointer to the device that is the target (USB4 port or retimer)
+ * @gen: Link generation
+ * @asym_rx: %true% if @port supports asymmetric link with 3 Rx
* @caps: Port lane margining capabilities
* @results: Last lane margining results
* @lanes: %0, %1 or %7 (all)
@@ -416,15 +437,19 @@ out:
* @time: %true if time margining is used instead of voltage
* @right_high: %false if left/low margin test is performed, %true if
* right/high
+ * @upper_eye: %false if the lower PAM3 eye is used, %true if the upper
+ * eye is used
*/
struct tb_margining {
struct tb_port *port;
enum usb4_sb_target target;
u8 index;
struct device *dev;
- u32 caps[2];
- u32 results[2];
- unsigned int lanes;
+ unsigned int gen;
+ bool asym_rx;
+ u32 caps[3];
+ u32 results[3];
+ enum usb4_margining_lane lanes;
unsigned int min_ber_level;
unsigned int max_ber_level;
unsigned int ber_level;
@@ -441,6 +466,7 @@ struct tb_margining {
bool software;
bool time;
bool right_high;
+ bool upper_eye;
};
static int margining_modify_error_counter(struct tb_margining *margining,
@@ -463,35 +489,75 @@ static int margining_modify_error_counter(struct tb_margining *margining,
static bool supports_software(const struct tb_margining *margining)
{
- return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_SW;
+ if (margining->gen < 4)
+ return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_SW;
+ return margining->caps[2] & USB4_MARGIN_CAP_2_MODES_SW;
}
static bool supports_hardware(const struct tb_margining *margining)
{
- return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_HW;
+ if (margining->gen < 4)
+ return margining->caps[0] & USB4_MARGIN_CAP_0_MODES_HW;
+ return margining->caps[2] & USB4_MARGIN_CAP_2_MODES_HW;
}
-static bool both_lanes(const struct tb_margining *margining)
+static bool all_lanes(const struct tb_margining *margining)
{
- return margining->caps[0] & USB4_MARGIN_CAP_0_2_LANES;
+ return margining->caps[0] & USB4_MARGIN_CAP_0_ALL_LANES;
}
-static unsigned int
+static enum usb4_margin_cap_voltage_indp
independent_voltage_margins(const struct tb_margining *margining)
{
- return FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK, margining->caps[0]);
+ if (margining->gen < 4) {
+ switch (FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK, margining->caps[0])) {
+ case USB4_MARGIN_CAP_0_VOLTAGE_MIN:
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_MIN;
+ case USB4_MARGIN_CAP_0_VOLTAGE_HL:
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_HL;
+ case USB4_MARGIN_CAP_1_TIME_BOTH:
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_BOTH;
+ }
+ } else {
+ switch (FIELD_GET(USB4_MARGIN_CAP_2_VOLTAGE_INDP_MASK, margining->caps[2])) {
+ case USB4_MARGIN_CAP_2_VOLTAGE_MIN:
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_MIN;
+ case USB4_MARGIN_CAP_2_VOLTAGE_BOTH:
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_BOTH;
+ }
+ }
+ return USB4_MARGIN_CAP_VOLTAGE_INDP_UNKNOWN;
}
static bool supports_time(const struct tb_margining *margining)
{
- return margining->caps[0] & USB4_MARGIN_CAP_0_TIME;
+ if (margining->gen < 4)
+ return margining->caps[0] & USB4_MARGIN_CAP_0_TIME;
+ return margining->caps[2] & USB4_MARGIN_CAP_2_TIME;
}
/* Only applicable if supports_time() returns true */
-static unsigned int
+static enum usb4_margin_cap_time_indp
independent_time_margins(const struct tb_margining *margining)
{
- return FIELD_GET(USB4_MARGIN_CAP_1_TIME_INDP_MASK, margining->caps[1]);
+ if (margining->gen < 4) {
+ switch (FIELD_GET(USB4_MARGIN_CAP_1_TIME_INDP_MASK, margining->caps[1])) {
+ case USB4_MARGIN_CAP_1_TIME_MIN:
+ return USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_MIN;
+ case USB4_MARGIN_CAP_1_TIME_LR:
+ return USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_LR;
+ case USB4_MARGIN_CAP_1_TIME_BOTH:
+ return USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_BOTH;
+ }
+ } else {
+ switch (FIELD_GET(USB4_MARGIN_CAP_2_TIME_INDP_MASK, margining->caps[2])) {
+ case USB4_MARGIN_CAP_2_TIME_MIN:
+ return USB4_MARGIN_CAP_TIME_INDP_GEN_4_MIN;
+ case USB4_MARGIN_CAP_2_TIME_BOTH:
+ return USB4_MARGIN_CAP_TIME_INDP_GEN_4_BOTH;
+ }
+ }
+ return USB4_MARGIN_CAP_TIME_INDP_UNKNOWN;
}
static bool
@@ -570,16 +636,14 @@ static int margining_caps_show(struct seq_file *s, void *not_used)
{
struct tb_margining *margining = s->private;
struct tb *tb = margining->port->sw->tb;
- u32 cap0, cap1;
+ int ret = 0;
if (mutex_lock_interruptible(&tb->lock))
return -ERESTARTSYS;
/* Dump the raw caps first */
- cap0 = margining->caps[0];
- seq_printf(s, "0x%08x\n", cap0);
- cap1 = margining->caps[1];
- seq_printf(s, "0x%08x\n", cap1);
+ for (int i = 0; i < ARRAY_SIZE(margining->caps); i++)
+ seq_printf(s, "0x%08x\n", margining->caps[i]);
seq_printf(s, "# software margining: %s\n",
supports_software(margining) ? "yes" : "no");
@@ -593,8 +657,8 @@ static int margining_caps_show(struct seq_file *s, void *not_used)
seq_puts(s, "# hardware margining: no\n");
}
- seq_printf(s, "# both lanes simultaneously: %s\n",
- both_lanes(margining) ? "yes" : "no");
+ seq_printf(s, "# all lanes simultaneously: %s\n",
+ str_yes_no(all_lanes(margining)));
seq_printf(s, "# voltage margin steps: %u\n",
margining->voltage_steps);
seq_printf(s, "# maximum voltage offset: %u mV\n",
@@ -609,32 +673,54 @@ static int margining_caps_show(struct seq_file *s, void *not_used)
}
switch (independent_voltage_margins(margining)) {
- case USB4_MARGIN_CAP_0_VOLTAGE_MIN:
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_MIN:
seq_puts(s, "# returns minimum between high and low voltage margins\n");
break;
- case USB4_MARGIN_CAP_0_VOLTAGE_HL:
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_HL:
seq_puts(s, "# returns high or low voltage margin\n");
break;
- case USB4_MARGIN_CAP_0_VOLTAGE_BOTH:
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_BOTH:
seq_puts(s, "# returns both high and low margins\n");
break;
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_MIN:
+ seq_puts(s, "# returns minimum between high and low voltage margins in both lower and upper eye\n");
+ break;
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_4_BOTH:
+ seq_puts(s, "# returns both high and low margins of both upper and lower eye\n");
+ break;
+ case USB4_MARGIN_CAP_VOLTAGE_INDP_UNKNOWN:
+ tb_port_warn(margining->port,
+ "failed to parse independent voltage margining capabilities\n");
+ ret = -EIO;
+ goto out;
}
if (supports_time(margining)) {
seq_puts(s, "# time margining: yes\n");
seq_printf(s, "# time margining is destructive: %s\n",
- cap1 & USB4_MARGIN_CAP_1_TIME_DESTR ? "yes" : "no");
+ str_yes_no(margining->caps[1] & USB4_MARGIN_CAP_1_TIME_DESTR));
switch (independent_time_margins(margining)) {
- case USB4_MARGIN_CAP_1_TIME_MIN:
+ case USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_MIN:
seq_puts(s, "# returns minimum between left and right time margins\n");
break;
- case USB4_MARGIN_CAP_1_TIME_LR:
+ case USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_LR:
seq_puts(s, "# returns left or right margin\n");
break;
- case USB4_MARGIN_CAP_1_TIME_BOTH:
+ case USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_BOTH:
seq_puts(s, "# returns both left and right margins\n");
break;
+ case USB4_MARGIN_CAP_TIME_INDP_GEN_4_MIN:
+ seq_puts(s, "# returns minimum between left and right time margins in both lower and upper eye\n");
+ break;
+ case USB4_MARGIN_CAP_TIME_INDP_GEN_4_BOTH:
+ seq_puts(s, "# returns both left and right margins of both upper and lower eye\n");
+ break;
+ case USB4_MARGIN_CAP_TIME_INDP_UNKNOWN:
+ tb_port_warn(margining->port,
+ "failed to parse independent time margining capabilities\n");
+ ret = -EIO;
+ goto out;
}
seq_printf(s, "# time margin steps: %u\n",
@@ -645,19 +731,43 @@ static int margining_caps_show(struct seq_file *s, void *not_used)
seq_puts(s, "# time margining: no\n");
}
+out:
mutex_unlock(&tb->lock);
- return 0;
+ return ret;
}
DEBUGFS_ATTR_RO(margining_caps);
+static const struct {
+ enum usb4_margining_lane lane;
+ const char *name;
+} lane_names[] = {
+ {
+ .lane = USB4_MARGINING_LANE_RX0,
+ .name = "0",
+ },
+ {
+ .lane = USB4_MARGINING_LANE_RX1,
+ .name = "1",
+ },
+ {
+ .lane = USB4_MARGINING_LANE_RX2,
+ .name = "2",
+ },
+ {
+ .lane = USB4_MARGINING_LANE_ALL,
+ .name = "all",
+ },
+};
+
static ssize_t
margining_lanes_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct seq_file *s = file->private_data;
struct tb_margining *margining = s->private;
- struct tb *tb = margining->port->sw->tb;
- int ret = 0;
+ struct tb_port *port = margining->port;
+ struct tb *tb = port->sw->tb;
+ int lane = -1;
char *buf;
buf = validate_and_copy_from_user(user_buf, &count);
@@ -666,57 +776,60 @@ margining_lanes_write(struct file *file, const char __user *user_buf,
buf[count - 1] = '\0';
- if (mutex_lock_interruptible(&tb->lock)) {
- ret = -ERESTARTSYS;
- goto out_free;
+ for (int i = 0; i < ARRAY_SIZE(lane_names); i++) {
+ if (!strcmp(buf, lane_names[i].name)) {
+ lane = lane_names[i].lane;
+ break;
+ }
}
- if (!strcmp(buf, "0")) {
- margining->lanes = 0;
- } else if (!strcmp(buf, "1")) {
- margining->lanes = 1;
- } else if (!strcmp(buf, "all")) {
- /* Needs to be supported */
- if (both_lanes(margining))
- margining->lanes = 7;
- else
- ret = -EINVAL;
- } else {
- ret = -EINVAL;
- }
+ free_page((unsigned long)buf);
- mutex_unlock(&tb->lock);
+ if (lane == -1)
+ return -EINVAL;
-out_free:
- free_page((unsigned long)buf);
- return ret < 0 ? ret : count;
+ scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
+ if (lane == USB4_MARGINING_LANE_ALL && !all_lanes(margining))
+ return -EINVAL;
+ /*
+ * Enabling on RX2 requires that it is supported by the
+ * USB4 port.
+ */
+ if (lane == USB4_MARGINING_LANE_RX2 && !margining->asym_rx)
+ return -EINVAL;
+
+ margining->lanes = lane;
+ }
+
+ return count;
}
static int margining_lanes_show(struct seq_file *s, void *not_used)
{
struct tb_margining *margining = s->private;
- struct tb *tb = margining->port->sw->tb;
- unsigned int lanes;
-
- if (mutex_lock_interruptible(&tb->lock))
- return -ERESTARTSYS;
+ struct tb_port *port = margining->port;
+ struct tb *tb = port->sw->tb;
- lanes = margining->lanes;
- if (both_lanes(margining)) {
- if (!lanes)
- seq_puts(s, "[0] 1 all\n");
- else if (lanes == 1)
- seq_puts(s, "0 [1] all\n");
- else
- seq_puts(s, "0 1 [all]\n");
- } else {
- if (!lanes)
- seq_puts(s, "[0] 1\n");
- else
- seq_puts(s, "0 [1]\n");
+ scoped_cond_guard(mutex_intr, return -ERESTARTSYS, &tb->lock) {
+ for (int i = 0; i < ARRAY_SIZE(lane_names); i++) {
+ if (lane_names[i].lane == USB4_MARGINING_LANE_ALL &&
+ !all_lanes(margining))
+ continue;
+ if (lane_names[i].lane == USB4_MARGINING_LANE_RX2 &&
+ !margining->asym_rx)
+ continue;
+
+ if (i != 0)
+ seq_putc(s, ' ');
+
+ if (lane_names[i].lane == margining->lanes)
+ seq_printf(s, "[%s]", lane_names[i].name);
+ else
+ seq_printf(s, "%s", lane_names[i].name);
+ }
+ seq_puts(s, "\n");
}
- mutex_unlock(&tb->lock);
return 0;
}
DEBUGFS_ATTR_RW(margining_lanes);
@@ -1004,13 +1117,16 @@ static int margining_run_sw(struct tb_margining *margining,
if (ret)
break;
- if (margining->lanes == USB4_MARGIN_SW_LANE_0)
+ if (margining->lanes == USB4_MARGINING_LANE_RX0)
errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_0_MASK,
margining->results[1]);
- else if (margining->lanes == USB4_MARGIN_SW_LANE_1)
+ else if (margining->lanes == USB4_MARGINING_LANE_RX1)
errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_1_MASK,
margining->results[1]);
- else if (margining->lanes == USB4_MARGIN_SW_ALL_LANES)
+ else if (margining->lanes == USB4_MARGINING_LANE_RX2)
+ errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_2_MASK,
+ margining->results[1]);
+ else if (margining->lanes == USB4_MARGINING_LANE_ALL)
errors = margining->results[1];
/* Any errors stop the test */
@@ -1030,6 +1146,31 @@ out_stop:
return ret;
}
+static int validate_margining(struct tb_margining *margining)
+{
+ /*
+ * For running on RX2 the link must be asymmetric with 3
+ * receivers. Because this is can change dynamically, check it
+ * here before we start the margining and report back error if
+ * expectations are not met.
+ */
+ if (margining->lanes == USB4_MARGINING_LANE_RX2) {
+ int ret;
+
+ ret = tb_port_get_link_width(margining->port);
+ if (ret < 0)
+ return ret;
+ if (ret != TB_LINK_WIDTH_ASYM_RX) {
+ tb_port_warn(margining->port, "link is %s expected %s",
+ tb_width_name(ret),
+ tb_width_name(TB_LINK_WIDTH_ASYM_RX));
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static int margining_run_write(void *data, u64 val)
{
struct tb_margining *margining = data;
@@ -1050,6 +1191,10 @@ static int margining_run_write(void *data, u64 val)
goto out_rpm_put;
}
+ ret = validate_margining(margining);
+ if (ret)
+ goto out_unlock;
+
if (tb_is_upstream_port(port))
down_sw = sw;
else if (port->remote)
@@ -1080,6 +1225,7 @@ static int margining_run_write(void *data, u64 val)
.time = margining->time,
.voltage_time_offset = margining->voltage_time_offset,
.right_high = margining->right_high,
+ .upper_eye = margining->upper_eye,
.optional_voltage_offset_range = margining->optional_voltage_offset_range,
};
@@ -1095,6 +1241,7 @@ static int margining_run_write(void *data, u64 val)
.lanes = margining->lanes,
.time = margining->time,
.right_high = margining->right_high,
+ .upper_eye = margining->upper_eye,
.optional_voltage_offset_range = margining->optional_voltage_offset_range,
};
@@ -1104,7 +1251,7 @@ static int margining_run_write(void *data, u64 val)
margining->lanes);
ret = usb4_port_hw_margin(port, margining->target, margining->index, &params,
- margining->results);
+ margining->results, ARRAY_SIZE(margining->results));
}
if (down_sw)
@@ -1132,13 +1279,12 @@ static ssize_t margining_results_write(struct file *file,
return -ERESTARTSYS;
/* Just clear the results */
- margining->results[0] = 0;
- margining->results[1] = 0;
+ memset(margining->results, 0, sizeof(margining->results));
if (margining->software) {
/* Clear the error counters */
margining_modify_error_counter(margining,
- USB4_MARGIN_SW_ALL_LANES,
+ USB4_MARGINING_LANE_ALL,
USB4_MARGIN_SW_ERROR_COUNTER_CLEAR);
}
@@ -1151,10 +1297,10 @@ static void voltage_margin_show(struct seq_file *s,
{
unsigned int tmp, voltage;
- tmp = FIELD_GET(USB4_MARGIN_HW_RES_1_MARGIN_MASK, val);
+ tmp = FIELD_GET(USB4_MARGIN_HW_RES_MARGIN_MASK, val);
voltage = tmp * margining->max_voltage_offset / margining->voltage_steps;
seq_printf(s, "%u mV (%u)", voltage, tmp);
- if (val & USB4_MARGIN_HW_RES_1_EXCEEDS)
+ if (val & USB4_MARGIN_HW_RES_EXCEEDS)
seq_puts(s, " exceeds maximum");
seq_puts(s, "\n");
if (margining->optional_voltage_offset_range)
@@ -1166,14 +1312,55 @@ static void time_margin_show(struct seq_file *s,
{
unsigned int tmp, interval;
- tmp = FIELD_GET(USB4_MARGIN_HW_RES_1_MARGIN_MASK, val);
+ tmp = FIELD_GET(USB4_MARGIN_HW_RES_MARGIN_MASK, val);
interval = tmp * margining->max_time_offset / margining->time_steps;
seq_printf(s, "%u mUI (%u)", interval, tmp);
- if (val & USB4_MARGIN_HW_RES_1_EXCEEDS)
+ if (val & USB4_MARGIN_HW_RES_EXCEEDS)
seq_puts(s, " exceeds maximum");
seq_puts(s, "\n");
}
+static u8 margining_hw_result_val(const u32 *results,
+ enum usb4_margining_lane lane,
+ bool right_high)
+{
+ u32 val;
+
+ if (lane == USB4_MARGINING_LANE_RX0)
+ val = results[1];
+ else if (lane == USB4_MARGINING_LANE_RX1)
+ val = results[1] >> USB4_MARGIN_HW_RES_LANE_SHIFT;
+ else if (lane == USB4_MARGINING_LANE_RX2)
+ val = results[2];
+ else
+ val = 0;
+
+ return right_high ? val : val >> USB4_MARGIN_HW_RES_LL_SHIFT;
+}
+
+static void margining_hw_result_format(struct seq_file *s,
+ const struct tb_margining *margining,
+ enum usb4_margining_lane lane)
+{
+ u8 val;
+
+ if (margining->time) {
+ val = margining_hw_result_val(margining->results, lane, true);
+ seq_printf(s, "# lane %u right time margin: ", lane);
+ time_margin_show(s, margining, val);
+ val = margining_hw_result_val(margining->results, lane, false);
+ seq_printf(s, "# lane %u left time margin: ", lane);
+ time_margin_show(s, margining, val);
+ } else {
+ val = margining_hw_result_val(margining->results, lane, true);
+ seq_printf(s, "# lane %u high voltage margin: ", lane);
+ voltage_margin_show(s, margining, val);
+ val = margining_hw_result_val(margining->results, lane, false);
+ seq_printf(s, "# lane %u low voltage margin: ", lane);
+ voltage_margin_show(s, margining, val);
+ }
+}
+
static int margining_results_show(struct seq_file *s, void *not_used)
{
struct tb_margining *margining = s->private;
@@ -1186,69 +1373,46 @@ static int margining_results_show(struct seq_file *s, void *not_used)
seq_printf(s, "0x%08x\n", margining->results[0]);
/* Only the hardware margining has two result dwords */
if (!margining->software) {
- unsigned int val;
-
- seq_printf(s, "0x%08x\n", margining->results[1]);
-
- if (margining->time) {
- if (!margining->lanes || margining->lanes == 7) {
- val = margining->results[1];
- seq_puts(s, "# lane 0 right time margin: ");
- time_margin_show(s, margining, val);
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L0_LL_MARGIN_SHIFT;
- seq_puts(s, "# lane 0 left time margin: ");
- time_margin_show(s, margining, val);
- }
- if (margining->lanes == 1 || margining->lanes == 7) {
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L1_RH_MARGIN_SHIFT;
- seq_puts(s, "# lane 1 right time margin: ");
- time_margin_show(s, margining, val);
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L1_LL_MARGIN_SHIFT;
- seq_puts(s, "# lane 1 left time margin: ");
- time_margin_show(s, margining, val);
- }
+ for (int i = 1; i < ARRAY_SIZE(margining->results); i++)
+ seq_printf(s, "0x%08x\n", margining->results[i]);
+
+ if (margining->lanes == USB4_MARGINING_LANE_ALL) {
+ margining_hw_result_format(s, margining,
+ USB4_MARGINING_LANE_RX0);
+ margining_hw_result_format(s, margining,
+ USB4_MARGINING_LANE_RX1);
+ if (margining->asym_rx)
+ margining_hw_result_format(s, margining,
+ USB4_MARGINING_LANE_RX2);
} else {
- if (!margining->lanes || margining->lanes == 7) {
- val = margining->results[1];
- seq_puts(s, "# lane 0 high voltage margin: ");
- voltage_margin_show(s, margining, val);
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L0_LL_MARGIN_SHIFT;
- seq_puts(s, "# lane 0 low voltage margin: ");
- voltage_margin_show(s, margining, val);
- }
- if (margining->lanes == 1 || margining->lanes == 7) {
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L1_RH_MARGIN_SHIFT;
- seq_puts(s, "# lane 1 high voltage margin: ");
- voltage_margin_show(s, margining, val);
- val = margining->results[1] >>
- USB4_MARGIN_HW_RES_1_L1_LL_MARGIN_SHIFT;
- seq_puts(s, "# lane 1 low voltage margin: ");
- voltage_margin_show(s, margining, val);
- }
+ margining_hw_result_format(s, margining,
+ margining->lanes);
}
} else {
u32 lane_errors, result;
seq_printf(s, "0x%08x\n", margining->results[1]);
- result = FIELD_GET(USB4_MARGIN_SW_LANES_MASK, margining->results[0]);
- if (result == USB4_MARGIN_SW_LANE_0 ||
- result == USB4_MARGIN_SW_ALL_LANES) {
+ result = FIELD_GET(USB4_MARGIN_SW_LANES_MASK, margining->results[0]);
+ if (result == USB4_MARGINING_LANE_RX0 ||
+ result == USB4_MARGINING_LANE_ALL) {
lane_errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_0_MASK,
margining->results[1]);
seq_printf(s, "# lane 0 errors: %u\n", lane_errors);
}
- if (result == USB4_MARGIN_SW_LANE_1 ||
- result == USB4_MARGIN_SW_ALL_LANES) {
+ if (result == USB4_MARGINING_LANE_RX1 ||
+ result == USB4_MARGINING_LANE_ALL) {
lane_errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_1_MASK,
margining->results[1]);
seq_printf(s, "# lane 1 errors: %u\n", lane_errors);
}
+ if (margining->asym_rx &&
+ (result == USB4_MARGINING_LANE_RX2 ||
+ result == USB4_MARGINING_LANE_ALL)) {
+ lane_errors = FIELD_GET(USB4_MARGIN_SW_ERR_COUNTER_LANE_2_MASK,
+ margining->results[1]);
+ seq_printf(s, "# lane 2 errors: %u\n", lane_errors);
+ }
}
mutex_unlock(&tb->lock);
@@ -1382,6 +1546,55 @@ static int margining_margin_show(struct seq_file *s, void *not_used)
}
DEBUGFS_ATTR_RW(margining_margin);
+static ssize_t margining_eye_write(struct file *file,
+ const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct seq_file *s = file->private_data;
+ struct tb_port *port = s->private;
+ struct usb4_port *usb4 = port->usb4;
+ struct tb *tb = port->sw->tb;
+ int ret = 0;
+ char *buf;
+
+ buf = validate_and_copy_from_user(user_buf, &count);
+ if (IS_ERR(buf))
+ return PTR_ERR(buf);
+
+ buf[count - 1] = '\0';
+
+ scoped_cond_guard(mutex_intr, ret = -ERESTARTSYS, &tb->lock) {
+ if (!strcmp(buf, "lower"))
+ usb4->margining->upper_eye = false;
+ else if (!strcmp(buf, "upper"))
+ usb4->margining->upper_eye = true;
+ else
+ ret = -EINVAL;
+ }
+
+ free_page((unsigned long)buf);
+ return ret ? ret : count;
+}
+
+static int margining_eye_show(struct seq_file *s, void *not_used)
+{
+ struct tb_port *port = s->private;
+ struct usb4_port *usb4 = port->usb4;
+ struct tb *tb = port->sw->tb;
+
+ scoped_guard(mutex_intr, &tb->lock) {
+ if (usb4->margining->upper_eye)
+ seq_puts(s, "lower [upper]\n");
+ else
+ seq_puts(s, "[lower] upper\n");
+
+ return 0;
+ }
+
+ return -ERESTARTSYS;
+}
+DEBUGFS_ATTR_RW(margining_eye);
+
static struct tb_margining *margining_alloc(struct tb_port *port,
struct device *dev,
enum usb4_sb_target target,
@@ -1392,6 +1605,12 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
unsigned int val;
int ret;
+ ret = tb_port_get_link_generation(port);
+ if (ret < 0) {
+ tb_port_warn(port, "failed to read link generation\n");
+ return NULL;
+ }
+
margining = kzalloc(sizeof(*margining), GFP_KERNEL);
if (!margining)
return NULL;
@@ -1400,8 +1619,11 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
margining->target = target;
margining->index = index;
margining->dev = dev;
+ margining->gen = ret;
+ margining->asym_rx = tb_port_width_supported(port, TB_LINK_WIDTH_ASYM_RX);
- ret = usb4_port_margining_caps(port, target, index, margining->caps);
+ ret = usb4_port_margining_caps(port, target, index, margining->caps,
+ ARRAY_SIZE(margining->caps));
if (ret) {
kfree(margining);
return NULL;
@@ -1411,10 +1633,17 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
if (supports_software(margining))
margining->software = true;
- val = FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK, margining->caps[0]);
- margining->voltage_steps = val;
- val = FIELD_GET(USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK, margining->caps[0]);
- margining->max_voltage_offset = 74 + val * 2;
+ if (margining->gen < 4) {
+ val = FIELD_GET(USB4_MARGIN_CAP_0_VOLTAGE_STEPS_MASK, margining->caps[0]);
+ margining->voltage_steps = val;
+ val = FIELD_GET(USB4_MARGIN_CAP_0_MAX_VOLTAGE_OFFSET_MASK, margining->caps[0]);
+ margining->max_voltage_offset = 74 + val * 2;
+ } else {
+ val = FIELD_GET(USB4_MARGIN_CAP_2_VOLTAGE_STEPS_MASK, margining->caps[2]);
+ margining->voltage_steps = val;
+ val = FIELD_GET(USB4_MARGIN_CAP_2_MAX_VOLTAGE_OFFSET_MASK, margining->caps[2]);
+ margining->max_voltage_offset = 74 + val * 2;
+ }
if (supports_optional_voltage_offset_range(margining)) {
val = FIELD_GET(USB4_MARGIN_CAP_0_VOLT_STEPS_OPT_MASK,
@@ -1456,11 +1685,10 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
debugfs_create_file("results", 0600, dir, margining,
&margining_results_fops);
debugfs_create_file("test", 0600, dir, margining, &margining_test_fops);
- if (independent_voltage_margins(margining) == USB4_MARGIN_CAP_0_VOLTAGE_HL ||
+ if (independent_voltage_margins(margining) == USB4_MARGIN_CAP_VOLTAGE_INDP_GEN_2_3_HL ||
(supports_time(margining) &&
- independent_time_margins(margining) == USB4_MARGIN_CAP_1_TIME_LR))
- debugfs_create_file("margin", 0600, dir, margining,
- &margining_margin_fops);
+ independent_time_margins(margining) == USB4_MARGIN_CAP_TIME_INDP_GEN_2_3_LR))
+ debugfs_create_file("margin", 0600, dir, margining, &margining_margin_fops);
margining->error_counter = USB4_MARGIN_SW_ERROR_COUNTER_CLEAR;
margining->dwell_time = MIN_DWELL_TIME;
@@ -1477,6 +1705,10 @@ static struct tb_margining *margining_alloc(struct tb_port *port,
debugfs_create_file("dwell_time", DEBUGFS_MODE, dir, margining,
&margining_dwell_time_fops);
}
+
+ if (margining->gen >= 4)
+ debugfs_create_file("eye", 0600, dir, port, &margining_eye_fops);
+
return margining;
}
diff --git a/drivers/thunderbolt/nhi.c b/drivers/thunderbolt/nhi.c
index 7af2642b97cb..f3a2264e012b 100644
--- a/drivers/thunderbolt/nhi.c
+++ b/drivers/thunderbolt/nhi.c
@@ -1340,18 +1340,18 @@ static int nhi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (res)
return dev_err_probe(dev, res, "cannot enable PCI device, aborting\n");
- res = pcim_iomap_regions(pdev, 1 << 0, "thunderbolt");
- if (res)
- return dev_err_probe(dev, res, "cannot obtain PCI resources, aborting\n");
-
nhi = devm_kzalloc(&pdev->dev, sizeof(*nhi), GFP_KERNEL);
if (!nhi)
return -ENOMEM;
nhi->pdev = pdev;
nhi->ops = (const struct tb_nhi_ops *)id->driver_data;
- /* cannot fail - table is allocated in pcim_iomap_regions */
- nhi->iobase = pcim_iomap_table(pdev)[0];
+
+ nhi->iobase = pcim_iomap_region(pdev, 0, "thunderbolt");
+ res = PTR_ERR_OR_ZERO(nhi->iobase);
+ if (res)
+ return dev_err_probe(dev, res, "cannot obtain PCI resources, aborting\n");
+
nhi->hop_count = ioread32(nhi->iobase + REG_CAPS) & 0x3ff;
dev_dbg(dev, "total paths: %d\n", nhi->hop_count);
@@ -1520,6 +1520,14 @@ static struct pci_device_id nhi_ids[] = {
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_LNL_NHI1),
.driver_data = (kernel_ulong_t)&icl_nhi_ops },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_M_NHI0),
+ .driver_data = (kernel_ulong_t)&icl_nhi_ops },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_M_NHI1),
+ .driver_data = (kernel_ulong_t)&icl_nhi_ops },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI0),
+ .driver_data = (kernel_ulong_t)&icl_nhi_ops },
+ { PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_PTL_P_NHI1),
+ .driver_data = (kernel_ulong_t)&icl_nhi_ops },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_80G_NHI) },
{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_INTEL_BARLOW_RIDGE_HOST_40G_NHI) },
diff --git a/drivers/thunderbolt/nhi.h b/drivers/thunderbolt/nhi.h
index 7a07c7c1a9c2..16744f25a9a0 100644
--- a/drivers/thunderbolt/nhi.h
+++ b/drivers/thunderbolt/nhi.h
@@ -92,6 +92,10 @@ extern const struct tb_nhi_ops icl_nhi_ops;
#define PCI_DEVICE_ID_INTEL_RPL_NHI1 0xa76d
#define PCI_DEVICE_ID_INTEL_LNL_NHI0 0xa833
#define PCI_DEVICE_ID_INTEL_LNL_NHI1 0xa834
+#define PCI_DEVICE_ID_INTEL_PTL_M_NHI0 0xe333
+#define PCI_DEVICE_ID_INTEL_PTL_M_NHI1 0xe334
+#define PCI_DEVICE_ID_INTEL_PTL_P_NHI0 0xe433
+#define PCI_DEVICE_ID_INTEL_PTL_P_NHI1 0xe434
#define PCI_CLASS_SERIAL_USB_USB4 0x0c0340
diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c
index 89d2919d0193..eeb64433ebbc 100644
--- a/drivers/thunderbolt/retimer.c
+++ b/drivers/thunderbolt/retimer.c
@@ -103,6 +103,7 @@ static int tb_retimer_nvm_add(struct tb_retimer *rt)
err_nvm:
dev_dbg(&rt->dev, "NVM upgrade disabled\n");
+ rt->no_nvm_upgrade = true;
if (!IS_ERR(nvm))
tb_nvm_free(nvm);
@@ -182,8 +183,6 @@ static ssize_t nvm_authenticate_show(struct device *dev,
if (!rt->nvm)
ret = -EAGAIN;
- else if (rt->no_nvm_upgrade)
- ret = -EOPNOTSUPP;
else
ret = sysfs_emit(buf, "%#x\n", rt->auth_status);
@@ -323,8 +322,6 @@ static ssize_t nvm_version_show(struct device *dev,
if (!rt->nvm)
ret = -EAGAIN;
- else if (rt->no_nvm_upgrade)
- ret = -EOPNOTSUPP;
else
ret = sysfs_emit(buf, "%x.%x\n", rt->nvm->major, rt->nvm->minor);
@@ -342,6 +339,19 @@ static ssize_t vendor_show(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RO(vendor);
+static umode_t retimer_is_visible(struct kobject *kobj, struct attribute *attr,
+ int n)
+{
+ struct device *dev = kobj_to_dev(kobj);
+ struct tb_retimer *rt = tb_to_retimer(dev);
+
+ if (attr == &dev_attr_nvm_authenticate.attr ||
+ attr == &dev_attr_nvm_version.attr)
+ return rt->no_nvm_upgrade ? 0 : attr->mode;
+
+ return attr->mode;
+}
+
static struct attribute *retimer_attrs[] = {
&dev_attr_device.attr,
&dev_attr_nvm_authenticate.attr,
@@ -351,6 +361,7 @@ static struct attribute *retimer_attrs[] = {
};
static const struct attribute_group retimer_group = {
+ .is_visible = retimer_is_visible,
.attrs = retimer_attrs,
};
diff --git a/drivers/thunderbolt/sb_regs.h b/drivers/thunderbolt/sb_regs.h
index dbcad25ead50..5391502a4b87 100644
--- a/drivers/thunderbolt/sb_regs.h
+++ b/drivers/thunderbolt/sb_regs.h
@@ -49,7 +49,7 @@ enum usb4_sb_opcode {
/* USB4_SB_OPCODE_READ_LANE_MARGINING_CAP */
#define USB4_MARGIN_CAP_0_MODES_HW BIT(0)
#define USB4_MARGIN_CAP_0_MODES_SW BIT(1)
-#define USB4_MARGIN_CAP_0_2_LANES BIT(2)
+#define USB4_MARGIN_CAP_0_ALL_LANES BIT(2)
#define USB4_MARGIN_CAP_0_VOLTAGE_INDP_MASK GENMASK(4, 3)
#define USB4_MARGIN_CAP_0_VOLTAGE_MIN 0x0
#define USB4_MARGIN_CAP_0_VOLTAGE_HL 0x1
@@ -69,34 +69,44 @@ enum usb4_sb_opcode {
#define USB4_MARGIN_CAP_1_TIME_OFFSET_MASK GENMASK(20, 16)
#define USB4_MARGIN_CAP_1_MIN_BER_MASK GENMASK(25, 21)
#define USB4_MARGIN_CAP_1_MAX_BER_MASK GENMASK(30, 26)
+#define USB4_MARGIN_CAP_2_MODES_HW BIT(0)
+#define USB4_MARGIN_CAP_2_MODES_SW BIT(1)
+#define USB4_MARGIN_CAP_2_TIME BIT(2)
+#define USB4_MARGIN_CAP_2_MAX_VOLTAGE_OFFSET_MASK GENMASK(8, 3)
+#define USB4_MARGIN_CAP_2_VOLTAGE_STEPS_MASK GENMASK(15, 9)
+#define USB4_MARGIN_CAP_2_VOLTAGE_INDP_MASK GENMASK(17, 16)
+#define USB4_MARGIN_CAP_2_VOLTAGE_MIN 0x0
+#define USB4_MARGIN_CAP_2_VOLTAGE_BOTH 0x1
+#define USB4_MARGIN_CAP_2_TIME_INDP_MASK GENMASK(19, 18)
+#define USB4_MARGIN_CAP_2_TIME_MIN 0x0
+#define USB4_MARGIN_CAP_2_TIME_BOTH 0x1
/* USB4_SB_OPCODE_RUN_HW_LANE_MARGINING */
#define USB4_MARGIN_HW_TIME BIT(3)
-#define USB4_MARGIN_HW_RH BIT(4)
+#define USB4_MARGIN_HW_RHU BIT(4)
#define USB4_MARGIN_HW_BER_MASK GENMASK(9, 5)
#define USB4_MARGIN_HW_BER_SHIFT 5
#define USB4_MARGIN_HW_OPT_VOLTAGE BIT(10)
/* Applicable to all margin values */
-#define USB4_MARGIN_HW_RES_1_MARGIN_MASK GENMASK(6, 0)
-#define USB4_MARGIN_HW_RES_1_EXCEEDS BIT(7)
-/* Different lane margin shifts */
-#define USB4_MARGIN_HW_RES_1_L0_LL_MARGIN_SHIFT 8
-#define USB4_MARGIN_HW_RES_1_L1_RH_MARGIN_SHIFT 16
-#define USB4_MARGIN_HW_RES_1_L1_LL_MARGIN_SHIFT 24
+#define USB4_MARGIN_HW_RES_MARGIN_MASK GENMASK(6, 0)
+#define USB4_MARGIN_HW_RES_EXCEEDS BIT(7)
+
+/* Shifts for parsing the lane results */
+#define USB4_MARGIN_HW_RES_LANE_SHIFT 16
+#define USB4_MARGIN_HW_RES_LL_SHIFT 8
/* USB4_SB_OPCODE_RUN_SW_LANE_MARGINING */
#define USB4_MARGIN_SW_LANES_MASK GENMASK(2, 0)
-#define USB4_MARGIN_SW_LANE_0 0x0
-#define USB4_MARGIN_SW_LANE_1 0x1
-#define USB4_MARGIN_SW_ALL_LANES 0x7
#define USB4_MARGIN_SW_TIME BIT(3)
#define USB4_MARGIN_SW_RH BIT(4)
#define USB4_MARGIN_SW_OPT_VOLTAGE BIT(5)
#define USB4_MARGIN_SW_VT_MASK GENMASK(12, 6)
#define USB4_MARGIN_SW_COUNTER_MASK GENMASK(14, 13)
+#define USB4_MARGIN_SW_UPPER_EYE BIT(15)
#define USB4_MARGIN_SW_ERR_COUNTER_LANE_0_MASK GENMASK(3, 0)
#define USB4_MARGIN_SW_ERR_COUNTER_LANE_1_MASK GENMASK(7, 4)
+#define USB4_MARGIN_SW_ERR_COUNTER_LANE_2_MASK GENMASK(11, 8)
#endif
diff --git a/drivers/thunderbolt/tb.c b/drivers/thunderbolt/tb.c
index 4f777788e917..a7c6919fbf97 100644
--- a/drivers/thunderbolt/tb.c
+++ b/drivers/thunderbolt/tb.c
@@ -2059,6 +2059,37 @@ static void tb_exit_redrive(struct tb_port *port)
}
}
+static void tb_switch_enter_redrive(struct tb_switch *sw)
+{
+ struct tb_port *port;
+
+ tb_switch_for_each_port(sw, port)
+ tb_enter_redrive(port);
+}
+
+/*
+ * Called during system and runtime suspend to forcefully exit redrive
+ * mode without querying whether the resource is available.
+ */
+static void tb_switch_exit_redrive(struct tb_switch *sw)
+{
+ struct tb_port *port;
+
+ if (!(sw->quirks & QUIRK_KEEP_POWER_IN_DP_REDRIVE))
+ return;
+
+ tb_switch_for_each_port(sw, port) {
+ if (!tb_port_is_dpin(port))
+ continue;
+
+ if (port->redrive) {
+ port->redrive = false;
+ pm_runtime_put(&sw->dev);
+ tb_port_dbg(port, "exit redrive mode\n");
+ }
+ }
+}
+
static void tb_dp_resource_unavailable(struct tb *tb, struct tb_port *port)
{
struct tb_port *in, *out;
@@ -2909,6 +2940,7 @@ static int tb_start(struct tb *tb, bool reset)
tb_create_usb3_tunnels(tb->root_switch);
/* Add DP IN resources for the root switch */
tb_add_dp_resources(tb->root_switch);
+ tb_switch_enter_redrive(tb->root_switch);
/* Make the discovered switches available to the userspace */
device_for_each_child(&tb->root_switch->dev, NULL,
tb_scan_finalize_switch);
@@ -2924,6 +2956,7 @@ static int tb_suspend_noirq(struct tb *tb)
tb_dbg(tb, "suspending...\n");
tb_disconnect_and_release_dp(tb);
+ tb_switch_exit_redrive(tb->root_switch);
tb_switch_suspend(tb->root_switch, false);
tcm->hotplug_active = false; /* signal tb_handle_hotplug to quit */
tb_dbg(tb, "suspend finished\n");
@@ -3016,6 +3049,7 @@ static int tb_resume_noirq(struct tb *tb)
tb_dbg(tb, "tunnels restarted, sleeping for 100ms\n");
msleep(100);
}
+ tb_switch_enter_redrive(tb->root_switch);
/* Allow tb_handle_hotplug to progress events */
tcm->hotplug_active = true;
tb_dbg(tb, "resume finished\n");
@@ -3079,6 +3113,12 @@ static int tb_runtime_suspend(struct tb *tb)
struct tb_cm *tcm = tb_priv(tb);
mutex_lock(&tb->lock);
+ /*
+ * The below call only releases DP resources to allow exiting and
+ * re-entering redrive mode.
+ */
+ tb_disconnect_and_release_dp(tb);
+ tb_switch_exit_redrive(tb->root_switch);
tb_switch_suspend(tb->root_switch, true);
tcm->hotplug_active = false;
mutex_unlock(&tb->lock);
@@ -3110,6 +3150,7 @@ static int tb_runtime_resume(struct tb *tb)
tb_restore_children(tb->root_switch);
list_for_each_entry_safe(tunnel, n, &tcm->tunnel_list, list)
tb_tunnel_restart(tunnel);
+ tb_switch_enter_redrive(tb->root_switch);
tcm->hotplug_active = true;
mutex_unlock(&tb->lock);
diff --git a/drivers/thunderbolt/tb.h b/drivers/thunderbolt/tb.h
index 6737188f2581..ddbf0cd78377 100644
--- a/drivers/thunderbolt/tb.h
+++ b/drivers/thunderbolt/tb.h
@@ -1367,11 +1367,18 @@ enum usb4_margin_sw_error_counter {
USB4_MARGIN_SW_ERROR_COUNTER_STOP,
};
+enum usb4_margining_lane {
+ USB4_MARGINING_LANE_RX0 = 0,
+ USB4_MARGINING_LANE_RX1 = 1,
+ USB4_MARGINING_LANE_RX2 = 2,
+ USB4_MARGINING_LANE_ALL = 7,
+};
+
/**
* struct usb4_port_margining_params - USB4 margining parameters
* @error_counter: Error counter operation for software margining
* @ber_level: Current BER level contour value
- * @lanes: %0, %1 or %7 (all)
+ * @lanes: Lanes to enable for the margining operation
* @voltage_time_offset: Offset for voltage / time for software margining
* @optional_voltage_offset_range: Enable optional extended voltage range
* @right_high: %false if left/low margin test is performed, %true if right/high
@@ -1380,18 +1387,19 @@ enum usb4_margin_sw_error_counter {
struct usb4_port_margining_params {
enum usb4_margin_sw_error_counter error_counter;
u32 ber_level;
- u32 lanes;
+ enum usb4_margining_lane lanes;
u32 voltage_time_offset;
bool optional_voltage_offset_range;
bool right_high;
+ bool upper_eye;
bool time;
};
int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
- u8 index, u32 *caps);
+ u8 index, u32 *caps, size_t ncaps);
int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, const struct usb4_port_margining_params *params,
- u32 *results);
+ u32 *results, size_t nresults);
int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, const struct usb4_port_margining_params *params,
u32 *results);
diff --git a/drivers/thunderbolt/usb4.c b/drivers/thunderbolt/usb4.c
index 402fdf8b1cde..e51d01671d8e 100644
--- a/drivers/thunderbolt/usb4.c
+++ b/drivers/thunderbolt/usb4.c
@@ -1631,11 +1631,12 @@ int usb4_port_asym_start(struct tb_port *port)
* @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @caps: Array with at least two elements to hold the results
+ * @ncaps: Number of elements in the caps array
*
* Reads the USB4 port lane margining capabilities into @caps.
*/
int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
- u8 index, u32 *caps)
+ u8 index, u32 *caps, size_t ncaps)
{
int ret;
@@ -1645,7 +1646,7 @@ int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
return ret;
return usb4_port_sb_read(port, target, index, USB4_SB_DATA, caps,
- sizeof(*caps) * 2);
+ sizeof(*caps) * ncaps);
}
/**
@@ -1654,14 +1655,15 @@ int usb4_port_margining_caps(struct tb_port *port, enum usb4_sb_target target,
* @target: Sideband target
* @index: Retimer index if taget is %USB4_SB_TARGET_RETIMER
* @params: Parameters for USB4 hardware margining
- * @results: Array with at least two elements to hold the results
+ * @results: Array to hold the results
+ * @nresults: Number of elements in the results array
*
* Runs hardware lane margining on USB4 port and returns the result in
* @results.
*/
int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
u8 index, const struct usb4_port_margining_params *params,
- u32 *results)
+ u32 *results, size_t nresults)
{
u32 val;
int ret;
@@ -1672,8 +1674,8 @@ int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
val = params->lanes;
if (params->time)
val |= USB4_MARGIN_HW_TIME;
- if (params->right_high)
- val |= USB4_MARGIN_HW_RH;
+ if (params->right_high || params->upper_eye)
+ val |= USB4_MARGIN_HW_RHU;
if (params->ber_level)
val |= FIELD_PREP(USB4_MARGIN_HW_BER_MASK, params->ber_level);
if (params->optional_voltage_offset_range)
@@ -1690,7 +1692,7 @@ int usb4_port_hw_margin(struct tb_port *port, enum usb4_sb_target target,
return ret;
return usb4_port_sb_read(port, target, index, USB4_SB_DATA, results,
- sizeof(*results) * 2);
+ sizeof(*results) * nresults);
}
/**
@@ -1722,6 +1724,8 @@ int usb4_port_sw_margin(struct tb_port *port, enum usb4_sb_target target,
val |= USB4_MARGIN_SW_OPT_VOLTAGE;
if (params->right_high)
val |= USB4_MARGIN_SW_RH;
+ if (params->upper_eye)
+ val |= USB4_MARGIN_SW_UPPER_EYE;
val |= FIELD_PREP(USB4_MARGIN_SW_COUNTER_MASK, params->error_counter);
val |= FIELD_PREP(USB4_MARGIN_SW_VT_MASK, params->voltage_time_offset);
diff --git a/drivers/tty/amiserial.c b/drivers/tty/amiserial.c
index 37164289277b..5af46442a792 100644
--- a/drivers/tty/amiserial.c
+++ b/drivers/tty/amiserial.c
@@ -1585,7 +1585,7 @@ static void __exit amiga_serial_remove(struct platform_device *pdev)
* triggering a section mismatch warning.
*/
static struct platform_driver amiga_serial_driver __refdata = {
- .remove_new = __exit_p(amiga_serial_remove),
+ .remove = __exit_p(amiga_serial_remove),
.driver = {
.name = "amiga-serial",
},
diff --git a/drivers/tty/goldfish.c b/drivers/tty/goldfish.c
index c60745f8e621..3a9582029005 100644
--- a/drivers/tty/goldfish.c
+++ b/drivers/tty/goldfish.c
@@ -461,7 +461,7 @@ MODULE_DEVICE_TABLE(of, goldfish_tty_of_match);
static struct platform_driver goldfish_tty_platform_driver = {
.probe = goldfish_tty_probe,
- .remove_new = goldfish_tty_remove,
+ .remove = goldfish_tty_remove,
.driver = {
.name = "goldfish_tty",
.of_match_table = goldfish_tty_of_match,
diff --git a/drivers/tty/hvc/hvc_opal.c b/drivers/tty/hvc/hvc_opal.c
index 095c33ad10f8..b2ec1f6efa0a 100644
--- a/drivers/tty/hvc/hvc_opal.c
+++ b/drivers/tty/hvc/hvc_opal.c
@@ -247,7 +247,7 @@ static void hvc_opal_remove(struct platform_device *dev)
static struct platform_driver hvc_opal_driver = {
.probe = hvc_opal_probe,
- .remove_new = hvc_opal_remove,
+ .remove = hvc_opal_remove,
.driver = {
.name = hvc_opal_name,
.of_match_table = hvc_opal_match,
diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
index 25c201cfb91e..e5da9ce26006 100644
--- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
+++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
@@ -569,7 +569,7 @@ static struct platform_driver aspeed_vuart_driver = {
.of_match_table = aspeed_vuart_table,
},
.probe = aspeed_vuart_probe,
- .remove_new = aspeed_vuart_remove,
+ .remove = aspeed_vuart_remove,
};
module_platform_driver(aspeed_vuart_driver);
diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c
index d7a0f271263a..fdb53b54e99e 100644
--- a/drivers/tty/serial/8250/8250_bcm2835aux.c
+++ b/drivers/tty/serial/8250/8250_bcm2835aux.c
@@ -267,7 +267,7 @@ static struct platform_driver bcm2835aux_serial_driver = {
.pm = pm_ptr(&bcm2835aux_dev_pm_ops),
},
.probe = bcm2835aux_serial_probe,
- .remove_new = bcm2835aux_serial_remove,
+ .remove = bcm2835aux_serial_remove,
};
module_platform_driver(bcm2835aux_serial_driver);
diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
index 2569ca69223f..d0b18358859e 100644
--- a/drivers/tty/serial/8250/8250_bcm7271.c
+++ b/drivers/tty/serial/8250/8250_bcm7271.c
@@ -812,7 +812,7 @@ static int brcmuart_handle_irq(struct uart_port *p)
/*
* if Receive Data Interrupt is enabled and
* we're uing hardware flow control, deassert
- * RTS and wait for any chars in the pipline to
+ * RTS and wait for any chars in the pipeline to
* arrive and then check for DR again.
*/
if ((ier & UART_IER_RDI) && (up->mcr & UART_MCR_AFE)) {
@@ -1204,7 +1204,7 @@ static struct platform_driver brcmuart_platform_driver = {
.of_match_table = brcmuart_dt_ids,
},
.probe = brcmuart_probe,
- .remove_new = brcmuart_remove,
+ .remove = brcmuart_remove,
};
static int __init brcmuart_init(void)
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index ab9e7f204260..6afcf27db3b8 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -750,7 +750,7 @@ static const struct dw8250_platform_data dw8250_renesas_rzn1_data = {
.quirks = DW_UART_QUIRK_CPR_VALUE | DW_UART_QUIRK_IS_DMA_FC,
};
-static const struct dw8250_platform_data dw8250_starfive_jh7100_data = {
+static const struct dw8250_platform_data dw8250_skip_set_rate_data = {
.usr_reg = DW_UART_USR,
.quirks = DW_UART_QUIRK_SKIP_SET_RATE,
};
@@ -760,7 +760,8 @@ static const struct of_device_id dw8250_of_match[] = {
{ .compatible = "cavium,octeon-3860-uart", .data = &dw8250_octeon_3860_data },
{ .compatible = "marvell,armada-38x-uart", .data = &dw8250_armada_38x_data },
{ .compatible = "renesas,rzn1-uart", .data = &dw8250_renesas_rzn1_data },
- { .compatible = "starfive,jh7100-uart", .data = &dw8250_starfive_jh7100_data },
+ { .compatible = "sophgo,sg2044-uart", .data = &dw8250_skip_set_rate_data },
+ { .compatible = "starfive,jh7100-uart", .data = &dw8250_skip_set_rate_data },
{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, dw8250_of_match);
@@ -796,7 +797,7 @@ static struct platform_driver dw8250_platform_driver = {
.acpi_match_table = dw8250_acpi_match,
},
.probe = dw8250_probe,
- .remove_new = dw8250_remove,
+ .remove = dw8250_remove,
};
module_platform_driver(dw8250_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
index a754755100ff..35094f884492 100644
--- a/drivers/tty/serial/8250/8250_em.c
+++ b/drivers/tty/serial/8250/8250_em.c
@@ -219,7 +219,7 @@ static struct platform_driver serial8250_em_platform_driver = {
.of_match_table = serial8250_em_dt_ids,
},
.probe = serial8250_em_probe,
- .remove_new = serial8250_em_remove,
+ .remove = serial8250_em_remove,
};
module_platform_driver(serial8250_em_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index b7a75db15249..04a0cbab02c2 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmi.h>
+#include <linux/eeprom_93cx6.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/math.h>
@@ -135,8 +136,6 @@
#define UART_EXAR_REGB_EECS BIT(5)
#define UART_EXAR_REGB_EEDI BIT(6)
#define UART_EXAR_REGB_EEDO BIT(7)
-#define UART_EXAR_REGB_EE_ADDR_SIZE 6
-#define UART_EXAR_REGB_EE_DATA_SIZE 16
#define UART_EXAR_XR17C15X_PORT_OFFSET 0x200
#define UART_EXAR_XR17V25X_PORT_OFFSET 0x200
@@ -179,18 +178,19 @@
/* CTI EEPROM offsets */
#define CTI_EE_OFF_XR17C15X_OSC_FREQ 0x04 /* 2 words */
-#define CTI_EE_OFF_XR17V25X_OSC_FREQ 0x08 /* 2 words */
#define CTI_EE_OFF_XR17C15X_PART_NUM 0x0A /* 4 words */
-#define CTI_EE_OFF_XR17V25X_PART_NUM 0x0E /* 4 words */
#define CTI_EE_OFF_XR17C15X_SERIAL_NUM 0x0E /* 1 word */
+
+#define CTI_EE_OFF_XR17V25X_OSC_FREQ 0x08 /* 2 words */
+#define CTI_EE_OFF_XR17V25X_PART_NUM 0x0E /* 4 words */
#define CTI_EE_OFF_XR17V25X_SERIAL_NUM 0x12 /* 1 word */
+
#define CTI_EE_OFF_XR17V35X_SERIAL_NUM 0x11 /* 2 word */
#define CTI_EE_OFF_XR17V35X_BRD_FLAGS 0x13 /* 1 word */
#define CTI_EE_OFF_XR17V35X_PORT_FLAGS 0x14 /* 1 word */
#define CTI_EE_MASK_PORT_FLAGS_TYPE GENMASK(7, 0)
-#define CTI_EE_MASK_OSC_FREQ_LOWER GENMASK(15, 0)
-#define CTI_EE_MASK_OSC_FREQ_UPPER GENMASK(31, 16)
+#define CTI_EE_MASK_OSC_FREQ GENMASK(31, 0)
#define CTI_FPGA_RS485_IO_REG 0x2008
#define CTI_FPGA_CFG_INT_EN_REG 0x48
@@ -252,6 +252,7 @@ struct exar8250 {
unsigned int nr;
unsigned int osc_freq;
struct exar8250_board *board;
+ struct eeprom_93cx6 eeprom;
void __iomem *virt;
int line[];
};
@@ -267,92 +268,37 @@ static inline u8 exar_read_reg(struct exar8250 *priv, unsigned int reg)
return readb(priv->virt + reg);
}
-static inline void exar_ee_select(struct exar8250 *priv)
-{
- // Set chip select pin high to enable EEPROM reads/writes
- exar_write_reg(priv, UART_EXAR_REGB, UART_EXAR_REGB_EECS);
- // Min ~500ns delay needed between CS assert and EEPROM access
- udelay(1);
-}
-
-static inline void exar_ee_deselect(struct exar8250 *priv)
-{
- exar_write_reg(priv, UART_EXAR_REGB, 0x00);
-}
-
-static inline void exar_ee_write_bit(struct exar8250 *priv, u8 bit)
+static void exar_eeprom_93cx6_reg_read(struct eeprom_93cx6 *eeprom)
{
- u8 value = UART_EXAR_REGB_EECS;
+ struct exar8250 *priv = eeprom->data;
+ u8 regb = exar_read_reg(priv, UART_EXAR_REGB);
- if (bit)
- value |= UART_EXAR_REGB_EEDI;
-
- // Clock out the bit on the EEPROM interface
- exar_write_reg(priv, UART_EXAR_REGB, value);
- // 2us delay = ~500khz clock speed
- udelay(2);
-
- value |= UART_EXAR_REGB_EECK;
-
- exar_write_reg(priv, UART_EXAR_REGB, value);
- udelay(2);
+ /* EECK and EECS always read 0 from REGB so only set EEDO */
+ eeprom->reg_data_out = regb & UART_EXAR_REGB_EEDO;
}
-static inline u8 exar_ee_read_bit(struct exar8250 *priv)
+static void exar_eeprom_93cx6_reg_write(struct eeprom_93cx6 *eeprom)
{
- u8 regb;
- u8 value = UART_EXAR_REGB_EECS;
-
- // Clock in the bit on the EEPROM interface
- exar_write_reg(priv, UART_EXAR_REGB, value);
- // 2us delay = ~500khz clock speed
- udelay(2);
+ struct exar8250 *priv = eeprom->data;
+ u8 regb = 0;
- value |= UART_EXAR_REGB_EECK;
+ if (eeprom->reg_data_in)
+ regb |= UART_EXAR_REGB_EEDI;
+ if (eeprom->reg_data_clock)
+ regb |= UART_EXAR_REGB_EECK;
+ if (eeprom->reg_chip_select)
+ regb |= UART_EXAR_REGB_EECS;
- exar_write_reg(priv, UART_EXAR_REGB, value);
- udelay(2);
-
- regb = exar_read_reg(priv, UART_EXAR_REGB);
-
- return (regb & UART_EXAR_REGB_EEDO ? 1 : 0);
+ exar_write_reg(priv, UART_EXAR_REGB, regb);
}
-/**
- * exar_ee_read() - Read a word from the EEPROM
- * @priv: Device's private structure
- * @ee_addr: Offset of EEPROM to read word from
- *
- * Read a single 16bit word from an Exar UART's EEPROM.
- * The type of the EEPROM is AT93C46D.
- *
- * Return: EEPROM word
- */
-static u16 exar_ee_read(struct exar8250 *priv, u8 ee_addr)
+static void exar_eeprom_init(struct exar8250 *priv)
{
- int i;
- u16 data = 0;
-
- exar_ee_select(priv);
-
- // Send read command (opcode 110)
- exar_ee_write_bit(priv, 1);
- exar_ee_write_bit(priv, 1);
- exar_ee_write_bit(priv, 0);
-
- // Send address to read from
- for (i = UART_EXAR_REGB_EE_ADDR_SIZE - 1; i >= 0; i--)
- exar_ee_write_bit(priv, ee_addr & BIT(i));
-
- // Read data 1 bit at a time starting with a dummy bit
- for (i = UART_EXAR_REGB_EE_DATA_SIZE; i >= 0; i--) {
- if (exar_ee_read_bit(priv))
- data |= BIT(i);
- }
-
- exar_ee_deselect(priv);
-
- return data;
+ priv->eeprom.data = priv;
+ priv->eeprom.register_read = exar_eeprom_93cx6_reg_read;
+ priv->eeprom.register_write = exar_eeprom_93cx6_reg_write;
+ priv->eeprom.width = PCI_EEPROM_WIDTH_93C46;
+ priv->eeprom.quirks |= PCI_EEPROM_QUIRK_EXTRA_READ_CYCLE;
}
/**
@@ -360,7 +306,7 @@ static u16 exar_ee_read(struct exar8250 *priv, u8 ee_addr)
* @priv: Device's private structure
* @mpio_num: MPIO number/offset to configure
*
- * Configure a single MPIO as an output and disable tristate. It is reccomended
+ * Configure a single MPIO as an output and disable tristate. It is recommended
* to set the level with exar_mpio_set_high()/exar_mpio_set_low() prior to
* calling this function to ensure default MPIO pin state.
*
@@ -516,7 +462,7 @@ static int xr17v35x_startup(struct uart_port *port)
serial_port_out(port, UART_XR_EFR, UART_EFR_ECB);
/*
- * Make sure all interrups are masked until initialization is
+ * Make sure all interrupts are masked until initialization is
* complete and the FIFOs are cleared
*
* Synchronize UART_IER access against the console.
@@ -696,20 +642,16 @@ static int cti_plx_int_enable(struct exar8250 *priv)
*/
static int cti_read_osc_freq(struct exar8250 *priv, u8 eeprom_offset)
{
- u16 lower_word;
- u16 upper_word;
+ __le16 ee_words[2];
+ u32 osc_freq;
- lower_word = exar_ee_read(priv, eeprom_offset);
- // Check if EEPROM word was blank
- if (lower_word == 0xFFFF)
- return -EIO;
+ eeprom_93cx6_multiread(&priv->eeprom, eeprom_offset, ee_words, ARRAY_SIZE(ee_words));
- upper_word = exar_ee_read(priv, (eeprom_offset + 1));
- if (upper_word == 0xFFFF)
+ osc_freq = le16_to_cpu(ee_words[0]) | (le16_to_cpu(ee_words[1]) << 16);
+ if (osc_freq == CTI_EE_MASK_OSC_FREQ)
return -EIO;
- return FIELD_PREP(CTI_EE_MASK_OSC_FREQ_LOWER, lower_word) |
- FIELD_PREP(CTI_EE_MASK_OSC_FREQ_UPPER, upper_word);
+ return osc_freq;
}
/**
@@ -833,7 +775,7 @@ static enum cti_port_type cti_get_port_type_xr17v35x(struct exar8250 *priv,
u8 offset;
offset = CTI_EE_OFF_XR17V35X_PORT_FLAGS + port_num;
- port_flags = exar_ee_read(priv, offset);
+ eeprom_93cx6_read(&priv->eeprom, offset, &port_flags);
port_type = FIELD_GET(CTI_EE_MASK_PORT_FLAGS_TYPE, port_flags);
if (CTI_PORT_TYPE_VALID(port_type))
@@ -1551,6 +1493,8 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
if (rc)
return rc;
+ exar_eeprom_init(priv);
+
for (i = 0; i < nr_ports && i < maxnr; i++) {
rc = board->setup(priv, pcidev, &uart, i);
if (rc) {
@@ -1786,7 +1730,7 @@ static struct pci_driver exar_pci_driver = {
};
module_pci_driver(exar_pci_driver);
-MODULE_IMPORT_NS(SERIAL_8250_PCI);
+MODULE_IMPORT_NS("SERIAL_8250_PCI");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Exar Serial Driver");
MODULE_AUTHOR("Sudip Mukherjee <sudip.mukherjee@codethink.co.uk>");
diff --git a/drivers/tty/serial/8250/8250_fintek.c b/drivers/tty/serial/8250/8250_fintek.c
index e2aa2a1a02dd..b4461a89b8d0 100644
--- a/drivers/tty/serial/8250/8250_fintek.c
+++ b/drivers/tty/serial/8250/8250_fintek.c
@@ -21,6 +21,7 @@
#define CHIP_ID_F81866 0x1010
#define CHIP_ID_F81966 0x0215
#define CHIP_ID_F81216AD 0x1602
+#define CHIP_ID_F81216E 0x1617
#define CHIP_ID_F81216H 0x0501
#define CHIP_ID_F81216 0x0802
#define VENDOR_ID1 0x23
@@ -125,7 +126,7 @@ static int fintek_8250_enter_key(u16 base_port, u8 key)
if (!request_muxed_region(base_port, 2, "8250_fintek"))
return -EBUSY;
- /* Force to deactive all SuperIO in this base_port */
+ /* Force to deactivate all SuperIO in this base_port */
outb(EXIT_KEY, base_port + ADDR_PORT);
outb(key, base_port + ADDR_PORT);
@@ -158,6 +159,7 @@ static int fintek_8250_check_id(struct fintek_8250 *pdata)
case CHIP_ID_F81866:
case CHIP_ID_F81966:
case CHIP_ID_F81216AD:
+ case CHIP_ID_F81216E:
case CHIP_ID_F81216H:
case CHIP_ID_F81216:
break;
@@ -181,6 +183,7 @@ static int fintek_8250_get_ldn_range(struct fintek_8250 *pdata, int *min,
return 0;
case CHIP_ID_F81216AD:
+ case CHIP_ID_F81216E:
case CHIP_ID_F81216H:
case CHIP_ID_F81216:
*min = F81216_LDN_LOW;
@@ -250,6 +253,7 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level)
break;
case CHIP_ID_F81216AD:
+ case CHIP_ID_F81216E:
case CHIP_ID_F81216H:
case CHIP_ID_F81216:
sio_write_mask_reg(pdata, FINTEK_IRQ_MODE, IRQ_SHARE,
@@ -263,7 +267,8 @@ static void fintek_8250_set_irq_mode(struct fintek_8250 *pdata, bool is_level)
static void fintek_8250_set_max_fifo(struct fintek_8250 *pdata)
{
switch (pdata->pid) {
- case CHIP_ID_F81216H: /* 128Bytes FIFO */
+ case CHIP_ID_F81216E: /* 128Bytes FIFO */
+ case CHIP_ID_F81216H:
case CHIP_ID_F81966:
case CHIP_ID_F81866:
sio_write_mask_reg(pdata, FIFO_CTRL,
@@ -297,6 +302,7 @@ static void fintek_8250_set_termios(struct uart_port *port,
goto exit;
switch (pdata->pid) {
+ case CHIP_ID_F81216E:
case CHIP_ID_F81216H:
reg = RS485;
break;
@@ -346,6 +352,7 @@ static void fintek_8250_set_termios_handler(struct uart_8250_port *uart)
struct fintek_8250 *pdata = uart->port.private_data;
switch (pdata->pid) {
+ case CHIP_ID_F81216E:
case CHIP_ID_F81216H:
case CHIP_ID_F81966:
case CHIP_ID_F81866:
@@ -438,6 +445,11 @@ static void fintek_8250_set_rs485_handler(struct uart_8250_port *uart)
uart->port.rs485_supported = fintek_8250_rs485_supported;
break;
+ case CHIP_ID_F81216E: /* F81216E does not support RS485 delays */
+ uart->port.rs485_config = fintek_8250_rs485_config;
+ uart->port.rs485_supported = fintek_8250_rs485_supported;
+ break;
+
default: /* No RS485 Auto direction functional */
break;
}
diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
index b4ed442082a8..1b7bd55619c6 100644
--- a/drivers/tty/serial/8250/8250_fsl.c
+++ b/drivers/tty/serial/8250/8250_fsl.c
@@ -179,7 +179,7 @@ static struct platform_driver fsl8250_platform_driver = {
.acpi_match_table = ACPI_PTR(fsl_8250_acpi_id),
},
.probe = fsl8250_acpi_probe,
- .remove_new = fsl8250_acpi_remove,
+ .remove = fsl8250_acpi_remove,
};
module_platform_driver(fsl8250_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
index a2783e38a2e3..a73dd3773640 100644
--- a/drivers/tty/serial/8250/8250_ingenic.c
+++ b/drivers/tty/serial/8250/8250_ingenic.c
@@ -361,7 +361,7 @@ static struct platform_driver ingenic_uart_platform_driver = {
.of_match_table = of_match,
},
.probe = ingenic_uart_probe,
- .remove_new = ingenic_uart_remove,
+ .remove = ingenic_uart_remove,
};
module_platform_driver(ingenic_uart_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_ioc3.c b/drivers/tty/serial/8250/8250_ioc3.c
index 50c77c3dacf2..499e80aa4cf9 100644
--- a/drivers/tty/serial/8250/8250_ioc3.c
+++ b/drivers/tty/serial/8250/8250_ioc3.c
@@ -84,7 +84,7 @@ static void serial8250_ioc3_remove(struct platform_device *pdev)
static struct platform_driver serial8250_ioc3_driver = {
.probe = serial8250_ioc3_probe,
- .remove_new = serial8250_ioc3_remove,
+ .remove = serial8250_ioc3_remove,
.driver = {
.name = "ioc3-serial8250",
}
diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c
index 47e1a056a60c..d52445948da0 100644
--- a/drivers/tty/serial/8250/8250_lpc18xx.c
+++ b/drivers/tty/serial/8250/8250_lpc18xx.c
@@ -195,7 +195,7 @@ MODULE_DEVICE_TABLE(of, lpc18xx_serial_match);
static struct platform_driver lpc18xx_serial_driver = {
.probe = lpc18xx_serial_probe,
- .remove_new = lpc18xx_serial_remove,
+ .remove = lpc18xx_serial_remove,
.driver = {
.name = "lpc18xx-uart",
.of_match_table = lpc18xx_serial_match,
diff --git a/drivers/tty/serial/8250/8250_men_mcb.c b/drivers/tty/serial/8250/8250_men_mcb.c
index dc9e093b1cb3..a78ef35c8187 100644
--- a/drivers/tty/serial/8250/8250_men_mcb.c
+++ b/drivers/tty/serial/8250/8250_men_mcb.c
@@ -271,4 +271,4 @@ MODULE_AUTHOR("Michael Moese <michael.moese@men.de");
MODULE_ALIAS("mcb:16z125");
MODULE_ALIAS("mcb:16z025");
MODULE_ALIAS("mcb:16z057");
-MODULE_IMPORT_NS(MCB);
+MODULE_IMPORT_NS("MCB");
diff --git a/drivers/tty/serial/8250/8250_mtk.c b/drivers/tty/serial/8250/8250_mtk.c
index b9cca210e171..b44de2ed7413 100644
--- a/drivers/tty/serial/8250/8250_mtk.c
+++ b/drivers/tty/serial/8250/8250_mtk.c
@@ -346,8 +346,8 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Mediatek UARTs use an extra highspeed register (MTK_UART_HIGHS)
*
- * We need to recalcualte the quot register, as the claculation depends
- * on the vaule in the highspeed register.
+ * We need to recalculate the quot register, as the calculation depends
+ * on the value in the highspeed register.
*
* Some baudrates are not supported by the chip, so we use the next
* lower rate supported and update termios c_flag.
@@ -654,7 +654,7 @@ static struct platform_driver mtk8250_platform_driver = {
.of_match_table = mtk8250_of_match,
},
.probe = mtk8250_probe,
- .remove_new = mtk8250_remove,
+ .remove = mtk8250_remove,
};
module_platform_driver(mtk8250_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_of.c b/drivers/tty/serial/8250/8250_of.c
index e14f47ef1172..64aed7efc569 100644
--- a/drivers/tty/serial/8250/8250_of.c
+++ b/drivers/tty/serial/8250/8250_of.c
@@ -352,7 +352,7 @@ static struct platform_driver of_platform_serial_driver = {
.pm = &of_serial_pm_ops,
},
.probe = of_platform_serial_probe,
- .remove_new = of_platform_serial_remove,
+ .remove = of_platform_serial_remove,
};
module_platform_driver(of_platform_serial_driver);
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index 88b58f44e4e9..9eb9aa766811 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -776,12 +776,12 @@ static void omap_8250_shutdown(struct uart_port *port)
struct uart_8250_port *up = up_to_u8250p(port);
struct omap8250_priv *priv = port->private_data;
+ pm_runtime_get_sync(port->dev);
+
flush_work(&priv->qos_work);
if (up->dma)
omap_8250_rx_dma_flush(up);
- pm_runtime_get_sync(port->dev);
-
serial_out(up, UART_OMAP_WER, 0);
if (priv->habit & UART_HAS_EFR2)
serial_out(up, UART_OMAP_EFR2, 0x0);
@@ -1304,7 +1304,7 @@ static void am654_8250_handle_rx_dma(struct uart_8250_port *up, u8 iir,
/*
* This is mostly serial8250_handle_irq(). We have a slightly different DMA
- * hoook for RX/TX and need different logic for them in the ISR. Therefore we
+ * hook for RX/TX and need different logic for them in the ISR. Therefore we
* use the default routine in the non-DMA case and this one for with DMA.
*/
static int omap_8250_dma_handle_irq(struct uart_port *port)
@@ -1338,7 +1338,7 @@ static int omap_8250_dma_handle_irq(struct uart_port *port)
serial8250_tx_chars(up);
} else {
/*
- * try again due to an earlier failer which
+ * try again due to an earlier failure which
* might have been resolved by now.
*/
if (omap_8250_tx_dma(up))
@@ -1867,7 +1867,7 @@ static struct platform_driver omap8250_platform_driver = {
.of_match_table = omap8250_dt_ids,
},
.probe = omap8250_probe,
- .remove_new = omap8250_remove,
+ .remove = omap8250_remove,
};
module_platform_driver(omap8250_platform_driver);
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 7d7a6d62c09c..3c3f7c926afb 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -6180,4 +6180,4 @@ module_pci_driver(serial_pci_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
MODULE_DEVICE_TABLE(pci, serial_pci_tbl);
-MODULE_IMPORT_NS(SERIAL_8250_PCI);
+MODULE_IMPORT_NS("SERIAL_8250_PCI");
diff --git a/drivers/tty/serial/8250/8250_pci1xxxx.c b/drivers/tty/serial/8250/8250_pci1xxxx.c
index d3930bf32fe4..838f181f929b 100644
--- a/drivers/tty/serial/8250/8250_pci1xxxx.c
+++ b/drivers/tty/serial/8250/8250_pci1xxxx.c
@@ -812,7 +812,7 @@ module_pci_driver(pci1xxxx_pci_driver);
static_assert((ARRAY_SIZE(logical_to_physical_port_idx) == PCI_SUBDEVICE_ID_EFAR_PCI1XXXX_1p3 + 1));
-MODULE_IMPORT_NS(SERIAL_8250_PCI);
+MODULE_IMPORT_NS("SERIAL_8250_PCI");
MODULE_DESCRIPTION("Microchip Technology Inc. PCIe to UART module");
MODULE_AUTHOR("Kumaravel Thiagarajan <kumaravel.thiagarajan@microchip.com>");
MODULE_AUTHOR("Tharun Kumar P <tharunkumar.pasumarthi@microchip.com>");
diff --git a/drivers/tty/serial/8250/8250_pcilib.c b/drivers/tty/serial/8250/8250_pcilib.c
index 3bdccf76f71d..d8d0ae0d7238 100644
--- a/drivers/tty/serial/8250/8250_pcilib.c
+++ b/drivers/tty/serial/8250/8250_pcilib.c
@@ -19,7 +19,7 @@ int serial_8250_warn_need_ioport(struct pci_dev *dev)
return -ENXIO;
}
-EXPORT_SYMBOL_NS_GPL(serial_8250_warn_need_ioport, SERIAL_8250_PCI);
+EXPORT_SYMBOL_NS_GPL(serial_8250_warn_need_ioport, "SERIAL_8250_PCI");
int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port,
u8 bar, unsigned int offset, int regshift)
@@ -47,6 +47,6 @@ int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port,
}
return 0;
}
-EXPORT_SYMBOL_NS_GPL(serial8250_pci_setup_port, SERIAL_8250_PCI);
+EXPORT_SYMBOL_NS_GPL(serial8250_pci_setup_port, "SERIAL_8250_PCI");
MODULE_DESCRIPTION("8250 PCI library");
MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c
index be7ff07cbdd0..8bdc1879d952 100644
--- a/drivers/tty/serial/8250/8250_platform.c
+++ b/drivers/tty/serial/8250/8250_platform.c
@@ -285,7 +285,7 @@ MODULE_DEVICE_TABLE(acpi, acpi_platform_serial_table);
static struct platform_driver serial8250_isa_driver = {
.probe = serial8250_probe,
- .remove_new = serial8250_remove,
+ .remove = serial8250_remove,
.suspend = serial8250_suspend,
.resume = serial8250_resume,
.driver = {
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 4d63d80e78a9..649e74e9b52f 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -467,7 +467,8 @@ static void set_io_from_upio(struct uart_port *p)
break;
#endif
default:
- WARN(1, "Unsupported UART type %x\n", p->iotype);
+ WARN(p->iotype != UPIO_PORT || p->iobase,
+ "Unsupported UART type %x\n", p->iotype);
p->serial_in = no_serial_in;
p->serial_out = no_serial_out;
}
diff --git a/drivers/tty/serial/8250/8250_pxa.c b/drivers/tty/serial/8250/8250_pxa.c
index 96dd6126296c..6dd0190b4843 100644
--- a/drivers/tty/serial/8250/8250_pxa.c
+++ b/drivers/tty/serial/8250/8250_pxa.c
@@ -154,7 +154,7 @@ static void serial_pxa_remove(struct platform_device *pdev)
static struct platform_driver serial_pxa_driver = {
.probe = serial_pxa_probe,
- .remove_new = serial_pxa_remove,
+ .remove = serial_pxa_remove,
.driver = {
.name = "pxa2xx-uart",
diff --git a/drivers/tty/serial/8250/8250_tegra.c b/drivers/tty/serial/8250/8250_tegra.c
index 60a80d00d251..2f3b0075763f 100644
--- a/drivers/tty/serial/8250/8250_tegra.c
+++ b/drivers/tty/serial/8250/8250_tegra.c
@@ -182,7 +182,7 @@ static struct platform_driver tegra_uart_driver = {
.acpi_match_table = ACPI_PTR(tegra_uart_acpi_match),
},
.probe = tegra_uart_probe,
- .remove_new = tegra_uart_remove,
+ .remove = tegra_uart_remove,
};
module_platform_driver(tegra_uart_driver);
diff --git a/drivers/tty/serial/8250/8250_uniphier.c b/drivers/tty/serial/8250/8250_uniphier.c
index 670d2ca0f757..4874a9632db3 100644
--- a/drivers/tty/serial/8250/8250_uniphier.c
+++ b/drivers/tty/serial/8250/8250_uniphier.c
@@ -282,7 +282,7 @@ MODULE_DEVICE_TABLE(of, uniphier_uart_match);
static struct platform_driver uniphier_uart_platform_driver = {
.probe = uniphier_uart_probe,
- .remove_new = uniphier_uart_remove,
+ .remove = uniphier_uart_remove,
.driver = {
.name = "uniphier-uart",
.of_match_table = uniphier_uart_match,
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 1eb20350fcf4..55d26d16df9b 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -150,6 +150,7 @@ config SERIAL_8250_EXAR
tristate "8250/16550 Exar/Commtech PCI/PCIe device support"
depends on SERIAL_8250 && PCI
select SERIAL_8250_PCILIB
+ select EEPROM_93CX6
default SERIAL_8250
help
This builds support for XR17C1xx, XR17V3xx and some Commtech
diff --git a/drivers/tty/serial/altera_jtaguart.c b/drivers/tty/serial/altera_jtaguart.c
index effcba71ea77..b9c3c3bed0c1 100644
--- a/drivers/tty/serial/altera_jtaguart.c
+++ b/drivers/tty/serial/altera_jtaguart.c
@@ -175,8 +175,8 @@ static int altera_jtaguart_startup(struct uart_port *port)
ret = request_irq(port->irq, altera_jtaguart_interrupt, 0,
DRV_NAME, port);
if (ret) {
- pr_err(DRV_NAME ": unable to attach Altera JTAG UART %d "
- "interrupt vector=%d\n", port->line, port->irq);
+ dev_err(port->dev, "unable to attach Altera JTAG UART %d interrupt vector=%d\n",
+ port->line, port->irq);
return ret;
}
@@ -449,7 +449,7 @@ MODULE_DEVICE_TABLE(of, altera_jtaguart_match);
static struct platform_driver altera_jtaguart_platform_driver = {
.probe = altera_jtaguart_probe,
- .remove_new = altera_jtaguart_remove,
+ .remove = altera_jtaguart_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(altera_jtaguart_match),
diff --git a/drivers/tty/serial/altera_uart.c b/drivers/tty/serial/altera_uart.c
index 897f0995b2fe..c94655453c33 100644
--- a/drivers/tty/serial/altera_uart.c
+++ b/drivers/tty/serial/altera_uart.c
@@ -307,8 +307,8 @@ static int altera_uart_startup(struct uart_port *port)
ret = request_irq(port->irq, altera_uart_interrupt, 0,
dev_name(port->dev), port);
if (ret) {
- pr_err(DRV_NAME ": unable to attach Altera UART %d "
- "interrupt vector=%d\n", port->line, port->irq);
+ dev_err(port->dev, "unable to attach Altera UART %d interrupt vector=%d\n",
+ port->line, port->irq);
return ret;
}
}
@@ -617,7 +617,7 @@ MODULE_DEVICE_TABLE(of, altera_uart_match);
static struct platform_driver altera_uart_platform_driver = {
.probe = altera_uart_probe,
- .remove_new = altera_uart_remove,
+ .remove = altera_uart_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(altera_uart_match),
diff --git a/drivers/tty/serial/amba-pl011.c b/drivers/tty/serial/amba-pl011.c
index 1c60850030b1..69b7a3e1e418 100644
--- a/drivers/tty/serial/amba-pl011.c
+++ b/drivers/tty/serial/amba-pl011.c
@@ -1819,6 +1819,13 @@ static void pl011_unthrottle_rx(struct uart_port *port)
pl011_write(uap->im, uap, REG_IMSC);
+#ifdef CONFIG_DMA_ENGINE
+ if (uap->using_rx_dma) {
+ uap->dmacr |= UART011_RXDMAE;
+ pl011_write(uap->dmacr, uap, REG_DMACR);
+ }
+#endif
+
uart_port_unlock_irqrestore(&uap->port, flags);
}
@@ -2937,7 +2944,7 @@ MODULE_DEVICE_TABLE(acpi, sbsa_uart_acpi_match);
static struct platform_driver arm_sbsa_uart_platform_driver = {
.probe = sbsa_uart_probe,
- .remove_new = sbsa_uart_remove,
+ .remove = sbsa_uart_remove,
.driver = {
.name = "sbsa-uart",
.pm = &pl011_dev_pm_ops,
diff --git a/drivers/tty/serial/ar933x_uart.c b/drivers/tty/serial/ar933x_uart.c
index 47889a557119..8bb33556b312 100644
--- a/drivers/tty/serial/ar933x_uart.c
+++ b/drivers/tty/serial/ar933x_uart.c
@@ -832,7 +832,7 @@ MODULE_DEVICE_TABLE(of, ar933x_uart_of_ids);
static struct platform_driver ar933x_uart_platform_driver = {
.probe = ar933x_uart_probe,
- .remove_new = ar933x_uart_remove,
+ .remove = ar933x_uart_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(ar933x_uart_of_ids),
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 09b246c9e389..0cf05ac18993 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -1166,7 +1166,7 @@ static void atmel_rx_from_dma(struct uart_port *port)
port->icount.rx += count;
}
- /* USART retreives ownership of RX DMA buffer */
+ /* USART retrieves ownership of RX DMA buffer */
dma_sync_single_for_device(port->dev, atmel_port->rx_phys,
ATMEL_SERIAL_RX_SIZE, DMA_FROM_DEVICE);
@@ -2419,17 +2419,11 @@ static void atmel_release_port(struct uart_port *port)
static int atmel_request_port(struct uart_port *port)
{
struct platform_device *mpdev = to_platform_device(port->dev->parent);
- int size = resource_size(mpdev->resource);
-
- if (!request_mem_region(port->mapbase, size, "atmel_serial"))
- return -EBUSY;
if (port->flags & UPF_IOREMAP) {
- port->membase = ioremap(port->mapbase, size);
- if (port->membase == NULL) {
- release_mem_region(port->mapbase, size);
- return -ENOMEM;
- }
+ port->membase = devm_platform_ioremap_resource(mpdev, 0);
+ if (IS_ERR(port->membase))
+ return PTR_ERR(port->membase);
}
return 0;
@@ -3017,7 +3011,7 @@ static SIMPLE_DEV_PM_OPS(atmel_serial_pm_ops, atmel_serial_suspend,
static struct platform_driver atmel_serial_driver = {
.probe = atmel_serial_probe,
- .remove_new = atmel_serial_remove,
+ .remove = atmel_serial_remove,
.driver = {
.name = "atmel_usart_serial",
.of_match_table = of_match_ptr(atmel_serial_dt_ids),
diff --git a/drivers/tty/serial/bcm63xx_uart.c b/drivers/tty/serial/bcm63xx_uart.c
index b88cc28c94e3..51df9d2d8bfc 100644
--- a/drivers/tty/serial/bcm63xx_uart.c
+++ b/drivers/tty/serial/bcm63xx_uart.c
@@ -884,7 +884,7 @@ MODULE_DEVICE_TABLE(of, bcm63xx_of_match);
*/
static struct platform_driver bcm_uart_platform_driver = {
.probe = bcm_uart_probe,
- .remove_new = bcm_uart_remove,
+ .remove = bcm_uart_remove,
.driver = {
.name = "bcm63xx_uart",
.of_match_table = bcm63xx_of_match,
diff --git a/drivers/tty/serial/clps711x.c b/drivers/tty/serial/clps711x.c
index 30425a3d19fb..83186bf50002 100644
--- a/drivers/tty/serial/clps711x.c
+++ b/drivers/tty/serial/clps711x.c
@@ -529,7 +529,7 @@ static struct platform_driver clps711x_uart_platform = {
.of_match_table = of_match_ptr(clps711x_uart_dt_ids),
},
.probe = uart_clps711x_probe,
- .remove_new = uart_clps711x_remove,
+ .remove = uart_clps711x_remove,
};
static int __init uart_clps711x_init(void)
diff --git a/drivers/tty/serial/cpm_uart.c b/drivers/tty/serial/cpm_uart.c
index 6eb8625de435..b778a20ec9b1 100644
--- a/drivers/tty/serial/cpm_uart.c
+++ b/drivers/tty/serial/cpm_uart.c
@@ -1573,7 +1573,7 @@ static struct platform_driver cpm_uart_driver = {
.of_match_table = cpm_uart_match,
},
.probe = cpm_uart_probe,
- .remove_new = cpm_uart_remove,
+ .remove = cpm_uart_remove,
};
static int __init cpm_uart_init(void)
diff --git a/drivers/tty/serial/digicolor-usart.c b/drivers/tty/serial/digicolor-usart.c
index 2ccd13cc0a89..d2482df5cb9b 100644
--- a/drivers/tty/serial/digicolor-usart.c
+++ b/drivers/tty/serial/digicolor-usart.c
@@ -522,7 +522,7 @@ static struct platform_driver digicolor_uart_platform = {
.of_match_table = of_match_ptr(digicolor_uart_dt_ids),
},
.probe = digicolor_uart_probe,
- .remove_new = digicolor_uart_remove,
+ .remove = digicolor_uart_remove,
};
static int __init digicolor_uart_init(void)
diff --git a/drivers/tty/serial/esp32_acm.c b/drivers/tty/serial/esp32_acm.c
index 85eb0392e379..bb7cc65427f0 100644
--- a/drivers/tty/serial/esp32_acm.c
+++ b/drivers/tty/serial/esp32_acm.c
@@ -423,7 +423,7 @@ static void esp32s3_acm_remove(struct platform_device *pdev)
static struct platform_driver esp32s3_acm_driver = {
.probe = esp32s3_acm_probe,
- .remove_new = esp32s3_acm_remove,
+ .remove = esp32s3_acm_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = esp32s3_acm_dt_ids,
diff --git a/drivers/tty/serial/esp32_uart.c b/drivers/tty/serial/esp32_uart.c
index 8c86cf9cb763..667c2198a03a 100644
--- a/drivers/tty/serial/esp32_uart.c
+++ b/drivers/tty/serial/esp32_uart.c
@@ -743,7 +743,7 @@ static void esp32_uart_remove(struct platform_device *pdev)
static struct platform_driver esp32_uart_driver = {
.probe = esp32_uart_probe,
- .remove_new = esp32_uart_remove,
+ .remove = esp32_uart_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = esp32_uart_dt_ids,
diff --git a/drivers/tty/serial/fsl_linflexuart.c b/drivers/tty/serial/fsl_linflexuart.c
index e972df4b188d..e70a56de1fce 100644
--- a/drivers/tty/serial/fsl_linflexuart.c
+++ b/drivers/tty/serial/fsl_linflexuart.c
@@ -882,7 +882,7 @@ static SIMPLE_DEV_PM_OPS(linflex_pm_ops, linflex_suspend, linflex_resume);
static struct platform_driver linflex_driver = {
.probe = linflex_probe,
- .remove_new = linflex_remove,
+ .remove = linflex_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = linflex_dt_ids,
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 77efa7ee6eda..57b0632a3db6 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -184,6 +184,7 @@
#define UARTCTRL_SBK 0x00010000
#define UARTCTRL_MA1IE 0x00008000
#define UARTCTRL_MA2IE 0x00004000
+#define UARTCTRL_M7 0x00000800
#define UARTCTRL_IDLECFG GENMASK(10, 8)
#define UARTCTRL_LOOPS 0x00000080
#define UARTCTRL_DOZEEN 0x00000040
@@ -2222,8 +2223,9 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
modem = lpuart32_read(&sport->port, UARTMODIR);
sport->is_cs7 = false;
/*
- * only support CS8 and CS7, and for CS7 must enable PE.
+ * only support CS8 and CS7
* supported mode:
+ * - (7,n,1) (imx only)
* - (7,e/o,1)
* - (8,n,1)
* - (8,m/s,1)
@@ -2238,7 +2240,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
if ((termios->c_cflag & CSIZE) == CS8 ||
(termios->c_cflag & CSIZE) == CS7)
- ctrl = old_ctrl & ~UARTCTRL_M;
+ ctrl = old_ctrl & ~(UARTCTRL_M | UARTCTRL_M7);
if (termios->c_cflag & CMSPAR) {
if ((termios->c_cflag & CSIZE) != CS8) {
@@ -2265,9 +2267,18 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
else
bd &= ~UARTBAUD_SBNS;
- /* parity must be enabled when CS7 to match 8-bits format */
- if ((termios->c_cflag & CSIZE) == CS7)
- termios->c_cflag |= PARENB;
+ /*
+ * imx support 7-bits format, no limitation on parity when CS7
+ * for layerscape, parity must be enabled when CS7 to match 8-bits format
+ */
+ if ((termios->c_cflag & CSIZE) == CS7 && !(termios->c_cflag & PARENB)) {
+ if (is_imx7ulp_lpuart(sport) ||
+ is_imx8ulp_lpuart(sport) ||
+ is_imx8qxp_lpuart(sport))
+ ctrl |= UARTCTRL_M7;
+ else
+ termios->c_cflag |= PARENB;
+ }
if ((termios->c_cflag & PARENB)) {
if (termios->c_cflag & CMSPAR) {
@@ -3206,7 +3217,7 @@ static const struct dev_pm_ops lpuart_pm_ops = {
static struct platform_driver lpuart_driver = {
.probe = lpuart_probe,
- .remove_new = lpuart_remove,
+ .remove = lpuart_remove,
.driver = {
.name = "fsl-lpuart",
.of_match_table = lpuart_dt_ids,
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 90974d338f3c..17f70e4bee43 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -230,6 +230,8 @@ struct imx_port {
unsigned int saved_reg[10];
bool context_saved;
+ bool last_putchar_was_newline;
+
enum imx_tx_state tx_state;
struct hrtimer trigger_start_tx;
struct hrtimer trigger_stop_tx;
@@ -370,6 +372,7 @@ static void imx_uart_soft_reset(struct imx_port *sport)
sport->idle_counter = 0;
}
+/* called with port.lock taken and irqs off */
static void imx_uart_disable_loopback_rs485(struct imx_port *sport)
{
unsigned int uts;
@@ -470,6 +473,7 @@ static void imx_uart_stop_tx(struct uart_port *port)
}
}
+/* called with port.lock taken and irqs off */
static void imx_uart_stop_rx_with_loopback_ctrl(struct uart_port *port, bool loopback)
{
struct imx_port *sport = to_imx_port(port);
@@ -818,6 +822,8 @@ static irqreturn_t imx_uart_txint(int irq, void *dev_id)
* issuing soft reset to the UART (just stop/start of RX does not help). Note
* that what we do here is sending isolated start bit about 2.4 times shorter
* than it is to be on UART configured baud rate.
+ *
+ * Called with port.lock taken and irqs off.
*/
static void imx_uart_check_flood(struct imx_port *sport, u32 usr2)
{
@@ -853,6 +859,7 @@ static void imx_uart_check_flood(struct imx_port *sport, u32 usr2)
}
}
+/* called with port.lock taken and irqs off */
static irqreturn_t __imx_uart_rxint(int irq, void *dev_id)
{
struct imx_port *sport = dev_id;
@@ -931,6 +938,7 @@ static void imx_uart_clear_rx_errors(struct imx_port *sport);
/*
* We have a modem side uart, so the meanings of RTS and CTS are inverted.
*/
+/* called with port.lock taken and irqs off */
static unsigned int imx_uart_get_hwmctrl(struct imx_port *sport)
{
unsigned int tmp = TIOCM_DSR;
@@ -953,6 +961,8 @@ static unsigned int imx_uart_get_hwmctrl(struct imx_port *sport)
/*
* Handle any change of modem status signal since we were last called.
+ *
+ * Called with port.lock taken and irqs off.
*/
static void imx_uart_mctrl_check(struct imx_port *sport)
{
@@ -1292,6 +1302,7 @@ static int imx_uart_start_rx_dma(struct imx_port *sport)
return 0;
}
+/* called with port.lock taken and irqs off */
static void imx_uart_clear_rx_errors(struct imx_port *sport)
{
struct tty_port *port = &sport->port.state->port;
@@ -1422,6 +1433,7 @@ err:
return ret;
}
+/* called with port.lock taken and irqs off */
static void imx_uart_enable_dma(struct imx_port *sport)
{
u32 ucr1;
@@ -2069,26 +2081,34 @@ static void imx_uart_console_putchar(struct uart_port *port, unsigned char ch)
barrier();
imx_uart_writel(sport, ch, URTX0);
+
+ sport->last_putchar_was_newline = (ch == '\n');
}
-/*
- * Interrupts are disabled on entering
- */
-static void
-imx_uart_console_write(struct console *co, const char *s, unsigned int count)
+static void imx_uart_console_device_lock(struct console *co, unsigned long *flags)
+{
+ struct uart_port *up = &imx_uart_ports[co->index]->port;
+
+ return __uart_port_lock_irqsave(up, flags);
+}
+
+static void imx_uart_console_device_unlock(struct console *co, unsigned long flags)
+{
+ struct uart_port *up = &imx_uart_ports[co->index]->port;
+
+ return __uart_port_unlock_irqrestore(up, flags);
+}
+
+static void imx_uart_console_write_atomic(struct console *co,
+ struct nbcon_write_context *wctxt)
{
struct imx_port *sport = imx_uart_ports[co->index];
+ struct uart_port *port = &sport->port;
struct imx_port_ucrs old_ucr;
- unsigned long flags;
unsigned int ucr1, usr2;
- int locked = 1;
- if (sport->port.sysrq)
- locked = 0;
- else if (oops_in_progress)
- locked = uart_port_trylock_irqsave(&sport->port, &flags);
- else
- uart_port_lock_irqsave(&sport->port, &flags);
+ if (!nbcon_enter_unsafe(wctxt))
+ return;
/*
* First, save UCR1/2/3 and then disable interrupts
@@ -2102,10 +2122,12 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN);
imx_uart_writel(sport, ucr1, UCR1);
-
imx_uart_writel(sport, old_ucr.ucr2 | UCR2_TXEN, UCR2);
- uart_console_write(&sport->port, s, count, imx_uart_console_putchar);
+ if (!sport->last_putchar_was_newline)
+ uart_console_write(port, "\n", 1, imx_uart_console_putchar);
+ uart_console_write(port, wctxt->outbuf, wctxt->len,
+ imx_uart_console_putchar);
/*
* Finally, wait for transmitter to become empty
@@ -2115,8 +2137,73 @@ imx_uart_console_write(struct console *co, const char *s, unsigned int count)
0, USEC_PER_SEC, false, sport, USR2);
imx_uart_ucrs_restore(sport, &old_ucr);
- if (locked)
- uart_port_unlock_irqrestore(&sport->port, flags);
+ nbcon_exit_unsafe(wctxt);
+}
+
+static void imx_uart_console_write_thread(struct console *co,
+ struct nbcon_write_context *wctxt)
+{
+ struct imx_port *sport = imx_uart_ports[co->index];
+ struct uart_port *port = &sport->port;
+ struct imx_port_ucrs old_ucr;
+ unsigned int ucr1, usr2;
+
+ if (!nbcon_enter_unsafe(wctxt))
+ return;
+
+ /*
+ * First, save UCR1/2/3 and then disable interrupts
+ */
+ imx_uart_ucrs_save(sport, &old_ucr);
+ ucr1 = old_ucr.ucr1;
+
+ if (imx_uart_is_imx1(sport))
+ ucr1 |= IMX1_UCR1_UARTCLKEN;
+ ucr1 |= UCR1_UARTEN;
+ ucr1 &= ~(UCR1_TRDYEN | UCR1_RRDYEN | UCR1_RTSDEN);
+
+ imx_uart_writel(sport, ucr1, UCR1);
+ imx_uart_writel(sport, old_ucr.ucr2 | UCR2_TXEN, UCR2);
+
+ if (nbcon_exit_unsafe(wctxt)) {
+ int len = READ_ONCE(wctxt->len);
+ int i;
+
+ /*
+ * Write out the message. Toggle unsafe for each byte in order
+ * to give another (higher priority) context the opportunity
+ * for a friendly takeover. If such a takeover occurs, this
+ * context must reacquire ownership in order to perform final
+ * actions (such as re-enabling the interrupts).
+ *
+ * IMPORTANT: wctxt->outbuf and wctxt->len are no longer valid
+ * after a reacquire so writing the message must be
+ * aborted.
+ */
+ for (i = 0; i < len; i++) {
+ if (!nbcon_enter_unsafe(wctxt))
+ break;
+
+ uart_console_write(port, wctxt->outbuf + i, 1,
+ imx_uart_console_putchar);
+
+ if (!nbcon_exit_unsafe(wctxt))
+ break;
+ }
+ }
+
+ while (!nbcon_enter_unsafe(wctxt))
+ nbcon_reacquire_nobuf(wctxt);
+
+ /*
+ * Finally, wait for transmitter to become empty
+ * and restore UCR1/2/3
+ */
+ read_poll_timeout(imx_uart_readl, usr2, usr2 & USR2_TXDC,
+ 0, USEC_PER_SEC, false, sport, USR2);
+ imx_uart_ucrs_restore(sport, &old_ucr);
+
+ nbcon_exit_unsafe(wctxt);
}
/*
@@ -2208,6 +2295,8 @@ imx_uart_console_setup(struct console *co, char *options)
if (retval)
goto error_console;
+ sport->last_putchar_was_newline = true;
+
if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);
else
@@ -2244,11 +2333,14 @@ imx_uart_console_exit(struct console *co)
static struct uart_driver imx_uart_uart_driver;
static struct console imx_uart_console = {
.name = DEV_NAME,
- .write = imx_uart_console_write,
+ .write_atomic = imx_uart_console_write_atomic,
+ .write_thread = imx_uart_console_write_thread,
+ .device_lock = imx_uart_console_device_lock,
+ .device_unlock = imx_uart_console_device_unlock,
+ .flags = CON_PRINTBUFFER | CON_NBCON,
.device = uart_console_device,
.setup = imx_uart_console_setup,
.exit = imx_uart_console_exit,
- .flags = CON_PRINTBUFFER,
.index = -1,
.data = &imx_uart_uart_driver,
};
@@ -2595,10 +2687,13 @@ static void imx_uart_save_context(struct imx_port *sport)
uart_port_unlock_irqrestore(&sport->port, flags);
}
+/* called with irq off */
static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
{
u32 ucr3;
+ uart_port_lock(&sport->port);
+
ucr3 = imx_uart_readl(sport, UCR3);
if (on) {
imx_uart_writel(sport, USR1_AWAKE, USR1);
@@ -2618,6 +2713,8 @@ static void imx_uart_enable_wakeup(struct imx_port *sport, bool on)
}
imx_uart_writel(sport, ucr1, UCR1);
}
+
+ uart_port_unlock(&sport->port);
}
static int imx_uart_suspend_noirq(struct device *dev)
@@ -2717,7 +2814,7 @@ static const struct dev_pm_ops imx_uart_pm_ops = {
static struct platform_driver imx_uart_platform_driver = {
.probe = imx_uart_probe,
- .remove_new = imx_uart_remove,
+ .remove = imx_uart_remove,
.driver = {
.name = "imx-uart",
diff --git a/drivers/tty/serial/lantiq.c b/drivers/tty/serial/lantiq.c
index a0731773ce75..58a3ab030d67 100644
--- a/drivers/tty/serial/lantiq.c
+++ b/drivers/tty/serial/lantiq.c
@@ -915,7 +915,7 @@ MODULE_DEVICE_TABLE(of, ltq_asc_match);
static struct platform_driver lqasc_driver = {
.probe = lqasc_probe,
- .remove_new = lqasc_remove,
+ .remove = lqasc_remove,
.driver = {
.name = DRVNAME,
.of_match_table = ltq_asc_match,
diff --git a/drivers/tty/serial/liteuart.c b/drivers/tty/serial/liteuart.c
index 3ce369f76349..6c13cf1ab646 100644
--- a/drivers/tty/serial/liteuart.c
+++ b/drivers/tty/serial/liteuart.c
@@ -353,7 +353,7 @@ MODULE_DEVICE_TABLE(of, liteuart_of_match);
static struct platform_driver liteuart_platform_driver = {
.probe = liteuart_probe,
- .remove_new = liteuart_remove,
+ .remove = liteuart_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = liteuart_of_match,
diff --git a/drivers/tty/serial/lpc32xx_hs.c b/drivers/tty/serial/lpc32xx_hs.c
index 3e4ac46de1bc..42c5f9bc18b7 100644
--- a/drivers/tty/serial/lpc32xx_hs.c
+++ b/drivers/tty/serial/lpc32xx_hs.c
@@ -695,7 +695,7 @@ MODULE_DEVICE_TABLE(of, serial_hs_lpc32xx_dt_ids);
static struct platform_driver serial_hs_lpc32xx_driver = {
.probe = serial_hs_lpc32xx_probe,
- .remove_new = serial_hs_lpc32xx_remove,
+ .remove = serial_hs_lpc32xx_remove,
.suspend = serial_hs_lpc32xx_suspend,
.resume = serial_hs_lpc32xx_resume,
.driver = {
diff --git a/drivers/tty/serial/ma35d1_serial.c b/drivers/tty/serial/ma35d1_serial.c
index 3b4206e815fe..8dcad52eedfd 100644
--- a/drivers/tty/serial/ma35d1_serial.c
+++ b/drivers/tty/serial/ma35d1_serial.c
@@ -794,7 +794,7 @@ static int ma35d1serial_resume(struct platform_device *dev)
static struct platform_driver ma35d1serial_driver = {
.probe = ma35d1serial_probe,
- .remove_new = ma35d1serial_remove,
+ .remove = ma35d1serial_remove,
.suspend = ma35d1serial_suspend,
.resume = ma35d1serial_resume,
.driver = {
diff --git a/drivers/tty/serial/mcf.c b/drivers/tty/serial/mcf.c
index 58858dd352c5..93e7dda4d39a 100644
--- a/drivers/tty/serial/mcf.c
+++ b/drivers/tty/serial/mcf.c
@@ -616,7 +616,7 @@ static void mcf_remove(struct platform_device *pdev)
static struct platform_driver mcf_platform_driver = {
.probe = mcf_probe,
- .remove_new = mcf_remove,
+ .remove = mcf_remove,
.driver = {
.name = "mcfuart",
},
diff --git a/drivers/tty/serial/men_z135_uart.c b/drivers/tty/serial/men_z135_uart.c
index 4bff422bb1bc..9cc15449b673 100644
--- a/drivers/tty/serial/men_z135_uart.c
+++ b/drivers/tty/serial/men_z135_uart.c
@@ -920,4 +920,4 @@ MODULE_AUTHOR("Johannes Thumshirn <johannes.thumshirn@men.de>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("MEN 16z135 High Speed UART");
MODULE_ALIAS("mcb:16z135");
-MODULE_IMPORT_NS(MCB);
+MODULE_IMPORT_NS("MCB");
diff --git a/drivers/tty/serial/meson_uart.c b/drivers/tty/serial/meson_uart.c
index 8eb586ac3b0d..a6cb2a535f9d 100644
--- a/drivers/tty/serial/meson_uart.c
+++ b/drivers/tty/serial/meson_uart.c
@@ -842,7 +842,7 @@ MODULE_DEVICE_TABLE(of, meson_uart_dt_match);
static struct platform_driver meson_uart_platform_driver = {
.probe = meson_uart_probe,
- .remove_new = meson_uart_remove,
+ .remove = meson_uart_remove,
.driver = {
.name = "meson_uart",
.of_match_table = meson_uart_dt_match,
diff --git a/drivers/tty/serial/milbeaut_usio.c b/drivers/tty/serial/milbeaut_usio.c
index fb082ee73d5b..059bea18dbab 100644
--- a/drivers/tty/serial/milbeaut_usio.c
+++ b/drivers/tty/serial/milbeaut_usio.c
@@ -570,7 +570,7 @@ MODULE_DEVICE_TABLE(of, mlb_usio_dt_ids);
static struct platform_driver mlb_usio_driver = {
.probe = mlb_usio_probe,
- .remove_new = mlb_usio_remove,
+ .remove = mlb_usio_remove,
.driver = {
.name = USIO_NAME,
.of_match_table = mlb_usio_dt_ids,
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 95dae5e27b28..f55aa353aed9 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1843,7 +1843,7 @@ MODULE_DEVICE_TABLE(of, mpc52xx_uart_of_match);
static struct platform_driver mpc52xx_uart_of_driver = {
.probe = mpc52xx_uart_of_probe,
- .remove_new = mpc52xx_uart_of_remove,
+ .remove = mpc52xx_uart_of_remove,
#ifdef CONFIG_PM
.suspend = mpc52xx_uart_of_suspend,
.resume = mpc52xx_uart_of_resume,
diff --git a/drivers/tty/serial/msm_serial.c b/drivers/tty/serial/msm_serial.c
index 0a9c5219df88..1b137e068444 100644
--- a/drivers/tty/serial/msm_serial.c
+++ b/drivers/tty/serial/msm_serial.c
@@ -1894,7 +1894,7 @@ static const struct dev_pm_ops msm_serial_dev_pm_ops = {
};
static struct platform_driver msm_platform_driver = {
- .remove_new = msm_serial_remove,
+ .remove = msm_serial_remove,
.probe = msm_serial_probe,
.driver = {
.name = "msm_serial",
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index a1c76565c399..cc65c9fb6446 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -1704,7 +1704,7 @@ static void mxs_auart_remove(struct platform_device *pdev)
static struct platform_driver mxs_auart_driver = {
.probe = mxs_auart_probe,
- .remove_new = mxs_auart_remove,
+ .remove = mxs_auart_remove,
.driver = {
.name = "mxs-auart",
.of_match_table = mxs_auart_dt_ids,
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index d7e172eeaab1..0b85f47ff19e 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1802,7 +1802,7 @@ MODULE_DEVICE_TABLE(of, omap_serial_of_match);
static struct platform_driver serial_omap_driver = {
.probe = serial_omap_probe,
- .remove_new = serial_omap_remove,
+ .remove = serial_omap_remove,
.driver = {
.name = OMAP_SERIAL_DRIVER_NAME,
.pm = &serial_omap_dev_pm_ops,
diff --git a/drivers/tty/serial/owl-uart.c b/drivers/tty/serial/owl-uart.c
index ecec483d4d59..0542882cfbbe 100644
--- a/drivers/tty/serial/owl-uart.c
+++ b/drivers/tty/serial/owl-uart.c
@@ -730,7 +730,7 @@ static void owl_uart_remove(struct platform_device *pdev)
static struct platform_driver owl_uart_platform_driver = {
.probe = owl_uart_probe,
- .remove_new = owl_uart_remove,
+ .remove = owl_uart_remove,
.driver = {
.name = "owl-uart",
.of_match_table = owl_uart_dt_matches,
diff --git a/drivers/tty/serial/pic32_uart.c b/drivers/tty/serial/pic32_uart.c
index 261c8115a700..14d50bd7f1bd 100644
--- a/drivers/tty/serial/pic32_uart.c
+++ b/drivers/tty/serial/pic32_uart.c
@@ -956,7 +956,7 @@ MODULE_DEVICE_TABLE(of, pic32_serial_dt_ids);
static struct platform_driver pic32_uart_platform_driver = {
.probe = pic32_uart_probe,
- .remove_new = pic32_uart_remove,
+ .remove = pic32_uart_remove,
.driver = {
.name = PIC32_DEV_NAME,
.of_match_table = of_match_ptr(pic32_serial_dt_ids),
diff --git a/drivers/tty/serial/pmac_zilog.c b/drivers/tty/serial/pmac_zilog.c
index 8969b11cc0a9..e3a919328695 100644
--- a/drivers/tty/serial/pmac_zilog.c
+++ b/drivers/tty/serial/pmac_zilog.c
@@ -1776,7 +1776,7 @@ static struct macio_driver pmz_driver = {
static struct platform_driver pmz_driver = {
.probe = pmz_attach,
- .remove_new = pmz_detach,
+ .remove = pmz_detach,
.driver = {
.name = "scc",
},
diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c
index 5dfe4e599ad6..a80ce7aaf309 100644
--- a/drivers/tty/serial/qcom_geni_serial.c
+++ b/drivers/tty/serial/qcom_geni_serial.c
@@ -1839,7 +1839,7 @@ static const struct of_device_id qcom_geni_serial_match_table[] = {
MODULE_DEVICE_TABLE(of, qcom_geni_serial_match_table);
static struct platform_driver qcom_geni_serial_platform_driver = {
- .remove_new = qcom_geni_serial_remove,
+ .remove = qcom_geni_serial_remove,
.probe = qcom_geni_serial_probe,
.driver = {
.name = "qcom_geni_serial",
diff --git a/drivers/tty/serial/rda-uart.c b/drivers/tty/serial/rda-uart.c
index 663e35e424bd..87fa30d68687 100644
--- a/drivers/tty/serial/rda-uart.c
+++ b/drivers/tty/serial/rda-uart.c
@@ -777,7 +777,7 @@ static void rda_uart_remove(struct platform_device *pdev)
static struct platform_driver rda_uart_platform_driver = {
.probe = rda_uart_probe,
- .remove_new = rda_uart_remove,
+ .remove = rda_uart_remove,
.driver = {
.name = "rda-uart",
.of_match_table = rda_uart_dt_matches,
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index 79c794fa6545..3c34027687d2 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -880,7 +880,7 @@ static void sa1100_serial_remove(struct platform_device *pdev)
static struct platform_driver sa11x0_serial_driver = {
.probe = sa1100_serial_probe,
- .remove_new = sa1100_serial_remove,
+ .remove = sa1100_serial_remove,
.suspend = sa1100_serial_suspend,
.resume = sa1100_serial_resume,
.driver = {
diff --git a/drivers/tty/serial/samsung_tty.c b/drivers/tty/serial/samsung_tty.c
index 0d184ee2f9ce..210fff7164c1 100644
--- a/drivers/tty/serial/samsung_tty.c
+++ b/drivers/tty/serial/samsung_tty.c
@@ -2498,6 +2498,12 @@ static const struct s3c24xx_serial_drv_data exynos850_serial_drv_data = {
.fifosize = { 256, 64, 64, 64 },
};
+static const struct s3c24xx_serial_drv_data exynos8895_serial_drv_data = {
+ EXYNOS_COMMON_SERIAL_DRV_DATA,
+ /* samsung,uart-fifosize must be specified in the device tree. */
+ .fifosize = { 0 },
+};
+
static const struct s3c24xx_serial_drv_data gs101_serial_drv_data = {
.info = {
.name = "Google GS101 UART",
@@ -2528,12 +2534,14 @@ static const struct s3c24xx_serial_drv_data gs101_serial_drv_data = {
#define EXYNOS4210_SERIAL_DRV_DATA (&exynos4210_serial_drv_data)
#define EXYNOS5433_SERIAL_DRV_DATA (&exynos5433_serial_drv_data)
#define EXYNOS850_SERIAL_DRV_DATA (&exynos850_serial_drv_data)
+#define EXYNOS8895_SERIAL_DRV_DATA (&exynos8895_serial_drv_data)
#define GS101_SERIAL_DRV_DATA (&gs101_serial_drv_data)
#else
#define EXYNOS4210_SERIAL_DRV_DATA NULL
#define EXYNOS5433_SERIAL_DRV_DATA NULL
#define EXYNOS850_SERIAL_DRV_DATA NULL
+#define EXYNOS8895_SERIAL_DRV_DATA NULL
#define GS101_SERIAL_DRV_DATA NULL
#endif
@@ -2623,6 +2631,9 @@ static const struct platform_device_id s3c24xx_serial_driver_ids[] = {
}, {
.name = "gs101-uart",
.driver_data = (kernel_ulong_t)GS101_SERIAL_DRV_DATA,
+ }, {
+ .name = "exynos8895-uart",
+ .driver_data = (kernel_ulong_t)EXYNOS8895_SERIAL_DRV_DATA,
},
{ },
};
@@ -2646,6 +2657,8 @@ static const struct of_device_id s3c24xx_uart_dt_match[] = {
.data = ARTPEC8_SERIAL_DRV_DATA },
{ .compatible = "google,gs101-uart",
.data = GS101_SERIAL_DRV_DATA },
+ { .compatible = "samsung,exynos8895-uart",
+ .data = EXYNOS8895_SERIAL_DRV_DATA },
{},
};
MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
@@ -2653,7 +2666,7 @@ MODULE_DEVICE_TABLE(of, s3c24xx_uart_dt_match);
static struct platform_driver samsung_serial_driver = {
.probe = s3c24xx_serial_probe,
- .remove_new = s3c24xx_serial_remove,
+ .remove = s3c24xx_serial_remove,
.id_table = s3c24xx_serial_driver_ids,
.driver = {
.name = "samsung-uart",
diff --git a/drivers/tty/serial/sc16is7xx.c b/drivers/tty/serial/sc16is7xx.c
index ad88a33a504f..a3093e09309f 100644
--- a/drivers/tty/serial/sc16is7xx.c
+++ b/drivers/tty/serial/sc16is7xx.c
@@ -8,7 +8,7 @@
*/
#undef DEFAULT_SYMBOL_NAMESPACE
-#define DEFAULT_SYMBOL_NAMESPACE SERIAL_NXP_SC16IS7XX
+#define DEFAULT_SYMBOL_NAMESPACE "SERIAL_NXP_SC16IS7XX"
#include <linux/bits.h>
#include <linux/clk.h>
@@ -1473,7 +1473,7 @@ static int sc16is7xx_setup_mctrl_ports(struct sc16is7xx_port *s,
}
static const struct serial_rs485 sc16is7xx_rs485_supported = {
- .flags = SER_RS485_ENABLED | SER_RS485_RTS_AFTER_SEND,
+ .flags = SER_RS485_ENABLED | SER_RS485_RTS_ON_SEND | SER_RS485_RTS_AFTER_SEND,
.delay_rts_before_send = 1,
.delay_rts_after_send = 1, /* Not supported but keep returning -EINVAL */
};
diff --git a/drivers/tty/serial/sc16is7xx_i2c.c b/drivers/tty/serial/sc16is7xx_i2c.c
index 3ed47c306d85..cd7de9e057b8 100644
--- a/drivers/tty/serial/sc16is7xx_i2c.c
+++ b/drivers/tty/serial/sc16is7xx_i2c.c
@@ -64,4 +64,4 @@ module_i2c_driver(sc16is7xx_i2c_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SC16IS7xx I2C interface driver");
-MODULE_IMPORT_NS(SERIAL_NXP_SC16IS7XX);
+MODULE_IMPORT_NS("SERIAL_NXP_SC16IS7XX");
diff --git a/drivers/tty/serial/sc16is7xx_spi.c b/drivers/tty/serial/sc16is7xx_spi.c
index 73df36f8a7fd..20d736b657b1 100644
--- a/drivers/tty/serial/sc16is7xx_spi.c
+++ b/drivers/tty/serial/sc16is7xx_spi.c
@@ -87,4 +87,4 @@ module_spi_driver(sc16is7xx_spi_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SC16IS7xx SPI interface driver");
-MODULE_IMPORT_NS(SERIAL_NXP_SC16IS7XX);
+MODULE_IMPORT_NS("SERIAL_NXP_SC16IS7XX");
diff --git a/drivers/tty/serial/sccnxp.c b/drivers/tty/serial/sccnxp.c
index 6d1d142fd216..4c851dae6624 100644
--- a/drivers/tty/serial/sccnxp.c
+++ b/drivers/tty/serial/sccnxp.c
@@ -1052,7 +1052,7 @@ static struct platform_driver sccnxp_uart_driver = {
.name = SCCNXP_NAME,
},
.probe = sccnxp_probe,
- .remove_new = sccnxp_remove,
+ .remove = sccnxp_remove,
.id_table = sccnxp_id_table,
};
module_platform_driver(sccnxp_uart_driver);
diff --git a/drivers/tty/serial/serial-tegra.c b/drivers/tty/serial/serial-tegra.c
index 1183ca54ab92..8004fc00fb9c 100644
--- a/drivers/tty/serial/serial-tegra.c
+++ b/drivers/tty/serial/serial-tegra.c
@@ -1648,7 +1648,7 @@ static const struct dev_pm_ops tegra_uart_pm_ops = {
static struct platform_driver tegra_uart_platform_driver = {
.probe = tegra_uart_probe,
- .remove_new = tegra_uart_remove,
+ .remove = tegra_uart_remove,
.driver = {
.name = "serial-tegra",
.of_match_table = tegra_uart_of_match,
diff --git a/drivers/tty/serial/serial_txx9.c b/drivers/tty/serial/serial_txx9.c
index abba39722958..436a559234df 100644
--- a/drivers/tty/serial/serial_txx9.c
+++ b/drivers/tty/serial/serial_txx9.c
@@ -1097,7 +1097,7 @@ static int serial_txx9_resume(struct platform_device *dev)
static struct platform_driver serial_txx9_plat_driver = {
.probe = serial_txx9_probe,
- .remove_new = serial_txx9_remove,
+ .remove = serial_txx9_remove,
#ifdef CONFIG_PM
.suspend = serial_txx9_suspend,
.resume = serial_txx9_resume,
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index b80e9a528e17..924b803af440 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -157,6 +157,7 @@ struct sci_port {
bool has_rtscts;
bool autorts;
+ bool tx_occurred;
};
#define SCI_NPORTS CONFIG_SERIAL_SH_SCI_NR_UARTS
@@ -850,6 +851,7 @@ static void sci_transmit_chars(struct uart_port *port)
{
struct tty_port *tport = &port->state->port;
unsigned int stopped = uart_tx_stopped(port);
+ struct sci_port *s = to_sci_port(port);
unsigned short status;
unsigned short ctrl;
int count;
@@ -885,6 +887,7 @@ static void sci_transmit_chars(struct uart_port *port)
}
sci_serial_out(port, SCxTDR, c);
+ s->tx_occurred = true;
port->icount.tx++;
} while (--count > 0);
@@ -1241,6 +1244,8 @@ static void sci_dma_tx_complete(void *arg)
if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS)
uart_write_wakeup(port);
+ s->tx_occurred = true;
+
if (!kfifo_is_empty(&tport->xmit_fifo)) {
s->cookie_tx = 0;
schedule_work(&s->work_tx);
@@ -1731,6 +1736,19 @@ static void sci_flush_buffer(struct uart_port *port)
s->cookie_tx = -EINVAL;
}
}
+
+static void sci_dma_check_tx_occurred(struct sci_port *s)
+{
+ struct dma_tx_state state;
+ enum dma_status status;
+
+ if (!s->chan_tx)
+ return;
+
+ status = dmaengine_tx_status(s->chan_tx, s->cookie_tx, &state);
+ if (status == DMA_COMPLETE || status == DMA_IN_PROGRESS)
+ s->tx_occurred = true;
+}
#else /* !CONFIG_SERIAL_SH_SCI_DMA */
static inline void sci_request_dma(struct uart_port *port)
{
@@ -1740,6 +1758,10 @@ static inline void sci_free_dma(struct uart_port *port)
{
}
+static void sci_dma_check_tx_occurred(struct sci_port *s)
+{
+}
+
#define sci_flush_buffer NULL
#endif /* !CONFIG_SERIAL_SH_SCI_DMA */
@@ -2076,6 +2098,12 @@ static unsigned int sci_tx_empty(struct uart_port *port)
{
unsigned short status = sci_serial_in(port, SCxSR);
unsigned short in_tx_fifo = sci_txfill(port);
+ struct sci_port *s = to_sci_port(port);
+
+ sci_dma_check_tx_occurred(s);
+
+ if (!s->tx_occurred)
+ return TIOCSER_TEMT;
return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
}
@@ -2247,6 +2275,7 @@ static int sci_startup(struct uart_port *port)
dev_dbg(port->dev, "%s(%d)\n", __func__, port->line);
+ s->tx_occurred = false;
sci_request_dma(port);
ret = sci_request_irq(s);
@@ -3505,7 +3534,7 @@ static SIMPLE_DEV_PM_OPS(sci_dev_pm_ops, sci_suspend, sci_resume);
static struct platform_driver sci_driver = {
.probe = sci_probe,
- .remove_new = sci_remove,
+ .remove = sci_remove,
.driver = {
.name = "sh-sci",
.pm = &sci_dev_pm_ops,
diff --git a/drivers/tty/serial/sifive.c b/drivers/tty/serial/sifive.c
index cbfce65c9d22..5904a2d4cefa 100644
--- a/drivers/tty/serial/sifive.c
+++ b/drivers/tty/serial/sifive.c
@@ -1040,7 +1040,7 @@ MODULE_DEVICE_TABLE(of, sifive_serial_of_match);
static struct platform_driver sifive_serial_platform_driver = {
.probe = sifive_serial_probe,
- .remove_new = sifive_serial_remove,
+ .remove = sifive_serial_remove,
.driver = {
.name = SIFIVE_SERIAL_NAME,
.pm = pm_sleep_ptr(&sifive_uart_pm_ops),
diff --git a/drivers/tty/serial/sprd_serial.c b/drivers/tty/serial/sprd_serial.c
index 3fc54cc02a1f..8c9366321f8e 100644
--- a/drivers/tty/serial/sprd_serial.c
+++ b/drivers/tty/serial/sprd_serial.c
@@ -53,10 +53,12 @@
#define SPRD_IEN_TX_EMPTY BIT(1)
#define SPRD_IEN_BREAK_DETECT BIT(7)
#define SPRD_IEN_TIMEOUT BIT(13)
+#define SPRD_IEN_DATA_TIMEOUT BIT(17)
/* interrupt clear register */
#define SPRD_ICLR 0x0014
#define SPRD_ICLR_TIMEOUT BIT(13)
+#define SPRD_ICLR_DATA_TIMEOUT BIT(17)
/* line control register */
#define SPRD_LCR 0x0018
@@ -102,6 +104,7 @@
#define SPRD_IMSR_TX_FIFO_EMPTY BIT(1)
#define SPRD_IMSR_BREAK_DETECT BIT(7)
#define SPRD_IMSR_TIMEOUT BIT(13)
+#define SPRD_IMSR_DATA_TIMEOUT BIT(17)
#define SPRD_DEFAULT_SOURCE_CLK 26000000
#define SPRD_RX_DMA_STEP 1
@@ -118,6 +121,12 @@ struct sprd_uart_dma {
bool enable;
};
+struct sprd_uart_data {
+ unsigned int timeout_ien;
+ unsigned int timeout_iclr;
+ unsigned int timeout_imsr;
+};
+
struct sprd_uart_port {
struct uart_port port;
char name[16];
@@ -126,6 +135,7 @@ struct sprd_uart_port {
struct sprd_uart_dma rx_dma;
dma_addr_t pos;
unsigned char *rx_buf_tail;
+ const struct sprd_uart_data *pdata;
};
static struct sprd_uart_port *sprd_port[UART_NR_MAX];
@@ -134,6 +144,18 @@ static int sprd_ports_num;
static int sprd_start_dma_rx(struct uart_port *port);
static int sprd_tx_dma_config(struct uart_port *port);
+static const struct sprd_uart_data sc9836_data = {
+ .timeout_ien = SPRD_IEN_TIMEOUT,
+ .timeout_iclr = SPRD_ICLR_TIMEOUT,
+ .timeout_imsr = SPRD_IMSR_TIMEOUT,
+};
+
+static const struct sprd_uart_data sc9632_data = {
+ .timeout_ien = SPRD_IEN_DATA_TIMEOUT,
+ .timeout_iclr = SPRD_ICLR_DATA_TIMEOUT,
+ .timeout_imsr = SPRD_IMSR_DATA_TIMEOUT,
+};
+
static inline unsigned int serial_in(struct uart_port *port,
unsigned int offset)
{
@@ -637,6 +659,8 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
unsigned int ims;
+ struct sprd_uart_port *sp =
+ container_of(port, struct sprd_uart_port, port);
uart_port_lock(port);
@@ -647,14 +671,14 @@ static irqreturn_t sprd_handle_irq(int irq, void *dev_id)
return IRQ_NONE;
}
- if (ims & SPRD_IMSR_TIMEOUT)
- serial_out(port, SPRD_ICLR, SPRD_ICLR_TIMEOUT);
+ if (ims & sp->pdata->timeout_imsr)
+ serial_out(port, SPRD_ICLR, sp->pdata->timeout_iclr);
if (ims & SPRD_IMSR_BREAK_DETECT)
serial_out(port, SPRD_ICLR, SPRD_IMSR_BREAK_DETECT);
if (ims & (SPRD_IMSR_RX_FIFO_FULL | SPRD_IMSR_BREAK_DETECT |
- SPRD_IMSR_TIMEOUT))
+ sp->pdata->timeout_imsr))
sprd_rx(port);
if (ims & SPRD_IMSR_TX_FIFO_EMPTY)
@@ -729,7 +753,7 @@ static int sprd_startup(struct uart_port *port)
/* enable interrupt */
uart_port_lock_irqsave(port, &flags);
ien = serial_in(port, SPRD_IEN);
- ien |= SPRD_IEN_BREAK_DETECT | SPRD_IEN_TIMEOUT;
+ ien |= SPRD_IEN_BREAK_DETECT | sp->pdata->timeout_ien;
if (!sp->rx_dma.enable)
ien |= SPRD_IEN_RX_FULL;
serial_out(port, SPRD_IEN, ien);
@@ -1184,6 +1208,12 @@ static int sprd_probe(struct platform_device *pdev)
up->mapbase = res->start;
+ sport->pdata = of_device_get_match_data(&pdev->dev);
+ if (!sport->pdata) {
+ dev_err(&pdev->dev, "get match data failed!\n");
+ return -EINVAL;
+ }
+
irq = platform_get_irq(pdev, 0);
if (irq < 0)
return irq;
@@ -1248,14 +1278,15 @@ static int sprd_resume(struct device *dev)
static SIMPLE_DEV_PM_OPS(sprd_pm_ops, sprd_suspend, sprd_resume);
static const struct of_device_id serial_ids[] = {
- {.compatible = "sprd,sc9836-uart",},
+ {.compatible = "sprd,sc9836-uart", .data = &sc9836_data},
+ {.compatible = "sprd,sc9632-uart", .data = &sc9632_data},
{}
};
MODULE_DEVICE_TABLE(of, serial_ids);
static struct platform_driver sprd_platform_driver = {
.probe = sprd_probe,
- .remove_new = sprd_remove,
+ .remove = sprd_remove,
.driver = {
.name = "sprd_serial",
.of_match_table = serial_ids,
diff --git a/drivers/tty/serial/st-asc.c b/drivers/tty/serial/st-asc.c
index 8aea59f8ca13..6ed9a327702b 100644
--- a/drivers/tty/serial/st-asc.c
+++ b/drivers/tty/serial/st-asc.c
@@ -934,7 +934,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(asc_serial_pm_ops, asc_serial_suspend,
static struct platform_driver asc_serial_driver = {
.probe = asc_serial_probe,
- .remove_new = asc_serial_remove,
+ .remove = asc_serial_remove,
.driver = {
.name = DRIVER_NAME,
.pm = pm_sleep_ptr(&asc_serial_pm_ops),
diff --git a/drivers/tty/serial/stm32-usart.c b/drivers/tty/serial/stm32-usart.c
index e1e7bc04c579..7dc254546075 100644
--- a/drivers/tty/serial/stm32-usart.c
+++ b/drivers/tty/serial/stm32-usart.c
@@ -2188,7 +2188,7 @@ static const struct dev_pm_ops stm32_serial_pm_ops = {
static struct platform_driver stm32_serial_driver = {
.probe = stm32_usart_serial_probe,
- .remove_new = stm32_usart_serial_remove,
+ .remove = stm32_usart_serial_remove,
.driver = {
.name = DRIVER_NAME,
.pm = &stm32_serial_pm_ops,
diff --git a/drivers/tty/serial/sunhv.c b/drivers/tty/serial/sunhv.c
index 7f60679fdde1..2b3ec65d595d 100644
--- a/drivers/tty/serial/sunhv.c
+++ b/drivers/tty/serial/sunhv.c
@@ -633,7 +633,7 @@ static struct platform_driver hv_driver = {
.of_match_table = hv_match,
},
.probe = hv_probe,
- .remove_new = hv_remove,
+ .remove = hv_remove,
};
static int __init sunhv_init(void)
diff --git a/drivers/tty/serial/sunplus-uart.c b/drivers/tty/serial/sunplus-uart.c
index abf7c449308d..38deee571b0d 100644
--- a/drivers/tty/serial/sunplus-uart.c
+++ b/drivers/tty/serial/sunplus-uart.c
@@ -697,7 +697,7 @@ MODULE_DEVICE_TABLE(of, sp_uart_of_match);
static struct platform_driver sunplus_uart_platform_driver = {
.probe = sunplus_uart_probe,
- .remove_new = sunplus_uart_remove,
+ .remove = sunplus_uart_remove,
.driver = {
.name = "sunplus_uart",
.of_match_table = sp_uart_of_match,
diff --git a/drivers/tty/serial/sunsab.c b/drivers/tty/serial/sunsab.c
index 1acbe2fba746..df906ccf2e8a 100644
--- a/drivers/tty/serial/sunsab.c
+++ b/drivers/tty/serial/sunsab.c
@@ -1100,7 +1100,7 @@ static struct platform_driver sab_driver = {
.of_match_table = sab_match,
},
.probe = sab_probe,
- .remove_new = sab_remove,
+ .remove = sab_remove,
};
static int __init sunsab_init(void)
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 0f463da5e7ce..7f0fef07e141 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -1549,7 +1549,7 @@ static struct platform_driver su_driver = {
.of_match_table = su_match,
},
.probe = su_probe,
- .remove_new = su_remove,
+ .remove = su_remove,
};
static int __init sunsu_init(void)
diff --git a/drivers/tty/serial/sunzilog.c b/drivers/tty/serial/sunzilog.c
index 71758ad4241c..0551c24c06f5 100644
--- a/drivers/tty/serial/sunzilog.c
+++ b/drivers/tty/serial/sunzilog.c
@@ -1538,7 +1538,7 @@ static struct platform_driver zs_driver = {
.of_match_table = zs_match,
},
.probe = zs_probe,
- .remove_new = zs_remove,
+ .remove = zs_remove,
};
static int __init sunzilog_init(void)
diff --git a/drivers/tty/serial/tegra-tcu.c b/drivers/tty/serial/tegra-tcu.c
index 21ca5fcadf49..7033dbfe8ba1 100644
--- a/drivers/tty/serial/tegra-tcu.c
+++ b/drivers/tty/serial/tegra-tcu.c
@@ -293,7 +293,7 @@ static struct platform_driver tegra_tcu_driver = {
.of_match_table = tegra_tcu_match,
},
.probe = tegra_tcu_probe,
- .remove_new = tegra_tcu_remove,
+ .remove = tegra_tcu_remove,
};
module_platform_driver(tegra_tcu_driver);
diff --git a/drivers/tty/serial/timbuart.c b/drivers/tty/serial/timbuart.c
index 43fa0938b5e3..6fa93c3872a7 100644
--- a/drivers/tty/serial/timbuart.c
+++ b/drivers/tty/serial/timbuart.c
@@ -485,7 +485,7 @@ static struct platform_driver timbuart_platform_driver = {
.name = "timb-uart",
},
.probe = timbuart_probe,
- .remove_new = timbuart_remove,
+ .remove = timbuart_remove,
};
module_platform_driver(timbuart_platform_driver);
diff --git a/drivers/tty/serial/uartlite.c b/drivers/tty/serial/uartlite.c
index 68357ac8ffe3..a41e7fc373b7 100644
--- a/drivers/tty/serial/uartlite.c
+++ b/drivers/tty/serial/uartlite.c
@@ -915,7 +915,7 @@ MODULE_ALIAS("platform:uartlite");
static struct platform_driver ulite_platform_driver = {
.probe = ulite_probe,
- .remove_new = ulite_remove,
+ .remove = ulite_remove,
.driver = {
.name = "uartlite",
.of_match_table = of_match_ptr(ulite_of_match),
diff --git a/drivers/tty/serial/ucc_uart.c b/drivers/tty/serial/ucc_uart.c
index 4eed909468ff..0613f8c11ab1 100644
--- a/drivers/tty/serial/ucc_uart.c
+++ b/drivers/tty/serial/ucc_uart.c
@@ -1484,7 +1484,7 @@ static struct platform_driver ucc_uart_of_driver = {
.of_match_table = ucc_uart_match,
},
.probe = ucc_uart_probe,
- .remove_new = ucc_uart_remove,
+ .remove = ucc_uart_remove,
};
static int __init ucc_uart_init(void)
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index 777392914819..beb151be4d32 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -1903,7 +1903,7 @@ static void cdns_uart_remove(struct platform_device *pdev)
static struct platform_driver cdns_uart_platform_driver = {
.probe = cdns_uart_probe,
- .remove_new = cdns_uart_remove,
+ .remove = cdns_uart_remove,
.driver = {
.name = CDNS_UART_NAME,
.of_match_table = cdns_uart_of_match,
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 9771072da177..dcb1769c3625 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3631,7 +3631,7 @@ static struct ctl_table tty_table[] = {
.data = &tty_ldisc_autoload,
.maxlen = sizeof(tty_ldisc_autoload),
.mode = 0644,
- .proc_handler = proc_dointvec,
+ .proc_handler = proc_dointvec_minmax,
.extra1 = SYSCTL_ZERO,
.extra2 = SYSCTL_ONE,
},
diff --git a/drivers/ufs/core/ufs-sysfs.c b/drivers/ufs/core/ufs-sysfs.c
index 265f21133b63..796e37a1d859 100644
--- a/drivers/ufs/core/ufs-sysfs.c
+++ b/drivers/ufs/core/ufs-sysfs.c
@@ -670,6 +670,9 @@ static ssize_t read_req_latency_avg_show(struct device *dev,
struct ufs_hba *hba = dev_get_drvdata(dev);
struct ufs_hba_monitor *m = &hba->monitor;
+ if (!m->nr_req[READ])
+ return sysfs_emit(buf, "0\n");
+
return sysfs_emit(buf, "%llu\n", div_u64(ktime_to_us(m->lat_sum[READ]),
m->nr_req[READ]));
}
@@ -737,6 +740,9 @@ static ssize_t write_req_latency_avg_show(struct device *dev,
struct ufs_hba *hba = dev_get_drvdata(dev);
struct ufs_hba_monitor *m = &hba->monitor;
+ if (!m->nr_req[WRITE])
+ return sysfs_emit(buf, "0\n");
+
return sysfs_emit(buf, "%llu\n", div_u64(ktime_to_us(m->lat_sum[WRITE]),
m->nr_req[WRITE]));
}
diff --git a/drivers/ufs/core/ufs_bsg.c b/drivers/ufs/core/ufs_bsg.c
index 433d0480391e..6c09d97ae006 100644
--- a/drivers/ufs/core/ufs_bsg.c
+++ b/drivers/ufs/core/ufs_bsg.c
@@ -170,7 +170,7 @@ static int ufs_bsg_request(struct bsg_job *job)
break;
case UPIU_TRANSACTION_UIC_CMD:
memcpy(&uc, &bsg_request->upiu_req.uc, UIC_CMD_SIZE);
- ret = ufshcd_send_uic_cmd(hba, &uc);
+ ret = ufshcd_send_bsg_uic_cmd(hba, &uc);
if (ret)
dev_err(hba->dev, "send uic cmd: error code %d\n", ret);
diff --git a/drivers/ufs/core/ufshcd-priv.h b/drivers/ufs/core/ufshcd-priv.h
index 7aea8fbaeee8..786f20ef2238 100644
--- a/drivers/ufs/core/ufshcd-priv.h
+++ b/drivers/ufs/core/ufshcd-priv.h
@@ -84,6 +84,7 @@ int ufshcd_read_string_desc(struct ufs_hba *hba, u8 desc_index,
u8 **buf, bool ascii);
int ufshcd_send_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
+int ufshcd_send_bsg_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd);
int ufshcd_exec_raw_upiu_cmd(struct ufs_hba *hba,
struct utp_upiu_req *req_upiu,
@@ -236,12 +237,6 @@ static inline void ufshcd_vops_config_scaling_param(struct ufs_hba *hba,
hba->vops->config_scaling_param(hba, p, data);
}
-static inline void ufshcd_vops_reinit_notify(struct ufs_hba *hba)
-{
- if (hba->vops && hba->vops->reinit_notify)
- hba->vops->reinit_notify(hba);
-}
-
static inline int ufshcd_vops_mcq_config_resource(struct ufs_hba *hba)
{
if (hba->vops && hba->vops->mcq_config_resource)
diff --git a/drivers/ufs/core/ufshcd.c b/drivers/ufs/core/ufshcd.c
index 6a2685333076..9c26e8767515 100644
--- a/drivers/ufs/core/ufshcd.c
+++ b/drivers/ufs/core/ufshcd.c
@@ -4320,6 +4320,42 @@ out_unlock:
}
/**
+ * ufshcd_send_bsg_uic_cmd - Send UIC commands requested via BSG layer and retrieve the result
+ * @hba: per adapter instance
+ * @uic_cmd: UIC command
+ *
+ * Return: 0 only if success.
+ */
+int ufshcd_send_bsg_uic_cmd(struct ufs_hba *hba, struct uic_command *uic_cmd)
+{
+ int ret;
+
+ if (hba->quirks & UFSHCD_QUIRK_BROKEN_UIC_CMD)
+ return 0;
+
+ ufshcd_hold(hba);
+
+ if (uic_cmd->argument1 == UIC_ARG_MIB(PA_PWRMODE) &&
+ uic_cmd->command == UIC_CMD_DME_SET) {
+ ret = ufshcd_uic_pwr_ctrl(hba, uic_cmd);
+ goto out;
+ }
+
+ mutex_lock(&hba->uic_cmd_mutex);
+ ufshcd_add_delay_before_dme_cmd(hba);
+
+ ret = __ufshcd_send_uic_cmd(hba, uic_cmd);
+ if (!ret)
+ ret = ufshcd_wait_for_uic_cmd(hba, uic_cmd);
+
+ mutex_unlock(&hba->uic_cmd_mutex);
+
+out:
+ ufshcd_release(hba);
+ return ret;
+}
+
+/**
* ufshcd_uic_change_pwr_mode - Perform the UIC power mode chage
* using DME_SET primitives.
* @hba: per adapter instance
@@ -4635,9 +4671,6 @@ static int ufshcd_change_power_mode(struct ufs_hba *hba,
dev_err(hba->dev,
"%s: power mode change failed %d\n", __func__, ret);
} else {
- ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL,
- pwr_mode);
-
memcpy(&hba->pwr_info, pwr_mode,
sizeof(struct ufs_pa_layer_attr));
}
@@ -4666,6 +4699,10 @@ int ufshcd_config_pwr_mode(struct ufs_hba *hba,
ret = ufshcd_change_power_mode(hba, &final_params);
+ if (!ret)
+ ufshcd_vops_pwr_change_notify(hba, POST_CHANGE, NULL,
+ &final_params);
+
return ret;
}
EXPORT_SYMBOL_GPL(ufshcd_config_pwr_mode);
@@ -5519,6 +5556,7 @@ void ufshcd_compl_one_cqe(struct ufs_hba *hba, int task_tag,
lrbp = &hba->lrb[task_tag];
lrbp->compl_time_stamp = ktime_get();
+ lrbp->compl_time_stamp_local_clock = local_clock();
cmd = lrbp->cmd;
if (cmd) {
if (unlikely(ufshcd_should_inform_monitor(hba, lrbp)))
@@ -8820,7 +8858,6 @@ static int ufshcd_probe_hba(struct ufs_hba *hba, bool init_dev_params)
ufshcd_device_reset(hba);
ufs_put_device_desc(hba);
ufshcd_hba_stop(hba);
- ufshcd_vops_reinit_notify(hba);
ret = ufshcd_hba_enable(hba);
if (ret) {
dev_err(hba->dev, "Host controller enable failed\n");
@@ -10195,6 +10232,7 @@ void ufshcd_remove(struct ufs_hba *hba)
ufs_hwmon_remove(hba);
ufs_bsg_remove(hba);
ufs_sysfs_remove_nodes(hba->dev);
+ cancel_delayed_work_sync(&hba->ufs_rtc_update_work);
blk_mq_destroy_queue(hba->tmf_queue);
blk_put_queue(hba->tmf_queue);
blk_mq_free_tag_set(&hba->tmf_tag_set);
@@ -10552,14 +10590,17 @@ int ufshcd_init(struct ufs_hba *hba, void __iomem *mmio_base, unsigned int irq)
}
/*
- * Set the default power management level for runtime and system PM.
+ * Set the default power management level for runtime and system PM if
+ * not set by the host controller drivers.
* Default power saving mode is to keep UFS link in Hibern8 state
* and UFS device in sleep state.
*/
- hba->rpm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state(
+ if (!hba->rpm_lvl)
+ hba->rpm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state(
UFS_SLEEP_PWR_MODE,
UIC_LINK_HIBERN8_STATE);
- hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state(
+ if (!hba->spm_lvl)
+ hba->spm_lvl = ufs_get_desired_pm_lvl_for_dev_link_state(
UFS_SLEEP_PWR_MODE,
UIC_LINK_HIBERN8_STATE);
diff --git a/drivers/ufs/host/cdns-pltfrm.c b/drivers/ufs/host/cdns-pltfrm.c
index 66811d8d1929..e793e3538c48 100644
--- a/drivers/ufs/host/cdns-pltfrm.c
+++ b/drivers/ufs/host/cdns-pltfrm.c
@@ -307,9 +307,7 @@ static int cdns_ufs_pltfrm_probe(struct platform_device *pdev)
*/
static void cdns_ufs_pltfrm_remove(struct platform_device *pdev)
{
- struct ufs_hba *hba = platform_get_drvdata(pdev);
-
- ufshcd_remove(hba);
+ ufshcd_pltfrm_remove(pdev);
}
static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
@@ -321,7 +319,7 @@ static const struct dev_pm_ops cdns_ufs_dev_pm_ops = {
static struct platform_driver cdns_ufs_pltfrm_driver = {
.probe = cdns_ufs_pltfrm_probe,
- .remove_new = cdns_ufs_pltfrm_remove,
+ .remove = cdns_ufs_pltfrm_remove,
.driver = {
.name = "cdns-ufshcd",
.pm = &cdns_ufs_dev_pm_ops,
diff --git a/drivers/ufs/host/tc-dwc-g210-pltfrm.c b/drivers/ufs/host/tc-dwc-g210-pltfrm.c
index a3877592604d..454ac88c357d 100644
--- a/drivers/ufs/host/tc-dwc-g210-pltfrm.c
+++ b/drivers/ufs/host/tc-dwc-g210-pltfrm.c
@@ -76,10 +76,7 @@ static int tc_dwc_g210_pltfm_probe(struct platform_device *pdev)
*/
static void tc_dwc_g210_pltfm_remove(struct platform_device *pdev)
{
- struct ufs_hba *hba = platform_get_drvdata(pdev);
-
- pm_runtime_get_sync(&(pdev)->dev);
- ufshcd_remove(hba);
+ ufshcd_pltfrm_remove(pdev);
}
static const struct dev_pm_ops tc_dwc_g210_pltfm_pm_ops = {
@@ -89,7 +86,7 @@ static const struct dev_pm_ops tc_dwc_g210_pltfm_pm_ops = {
static struct platform_driver tc_dwc_g210_pltfm_driver = {
.probe = tc_dwc_g210_pltfm_probe,
- .remove_new = tc_dwc_g210_pltfm_remove,
+ .remove = tc_dwc_g210_pltfm_remove,
.driver = {
.name = "tc-dwc-g210-pltfm",
.pm = &tc_dwc_g210_pltfm_pm_ops,
diff --git a/drivers/ufs/host/ti-j721e-ufs.c b/drivers/ufs/host/ti-j721e-ufs.c
index 250c22df000d..21214e5d5896 100644
--- a/drivers/ufs/host/ti-j721e-ufs.c
+++ b/drivers/ufs/host/ti-j721e-ufs.c
@@ -83,7 +83,7 @@ MODULE_DEVICE_TABLE(of, ti_j721e_ufs_of_match);
static struct platform_driver ti_j721e_ufs_driver = {
.probe = ti_j721e_ufs_probe,
- .remove_new = ti_j721e_ufs_remove,
+ .remove = ti_j721e_ufs_remove,
.driver = {
.name = "ti-j721e-ufs",
.of_match_table = ti_j721e_ufs_of_match,
diff --git a/drivers/ufs/host/ufs-exynos.c b/drivers/ufs/host/ufs-exynos.c
index 6548f7a8562f..13dd5dfc03eb 100644
--- a/drivers/ufs/host/ufs-exynos.c
+++ b/drivers/ufs/host/ufs-exynos.c
@@ -1992,8 +1992,7 @@ static void exynos_ufs_remove(struct platform_device *pdev)
struct ufs_hba *hba = platform_get_drvdata(pdev);
struct exynos_ufs *ufs = ufshcd_get_variant(hba);
- pm_runtime_get_sync(&(pdev)->dev);
- ufshcd_remove(hba);
+ ufshcd_pltfrm_remove(pdev);
phy_power_off(ufs->phy);
phy_exit(ufs->phy);
@@ -2166,7 +2165,7 @@ static const struct dev_pm_ops exynos_ufs_pm_ops = {
static struct platform_driver exynos_ufs_pltform = {
.probe = exynos_ufs_probe,
- .remove_new = exynos_ufs_remove,
+ .remove = exynos_ufs_remove,
.driver = {
.name = "exynos-ufshc",
.pm = &exynos_ufs_pm_ops,
diff --git a/drivers/ufs/host/ufs-hisi.c b/drivers/ufs/host/ufs-hisi.c
index 5ee73ff05251..6e6569de74d8 100644
--- a/drivers/ufs/host/ufs-hisi.c
+++ b/drivers/ufs/host/ufs-hisi.c
@@ -576,9 +576,7 @@ static int ufs_hisi_probe(struct platform_device *pdev)
static void ufs_hisi_remove(struct platform_device *pdev)
{
- struct ufs_hba *hba = platform_get_drvdata(pdev);
-
- ufshcd_remove(hba);
+ ufshcd_pltfrm_remove(pdev);
}
static const struct dev_pm_ops ufs_hisi_pm_ops = {
@@ -590,7 +588,7 @@ static const struct dev_pm_ops ufs_hisi_pm_ops = {
static struct platform_driver ufs_hisi_pltform = {
.probe = ufs_hisi_probe,
- .remove_new = ufs_hisi_remove,
+ .remove = ufs_hisi_remove,
.driver = {
.name = "ufshcd-hisi",
.pm = &ufs_hisi_pm_ops,
diff --git a/drivers/ufs/host/ufs-mediatek.c b/drivers/ufs/host/ufs-mediatek.c
index 06ab1e5e8b6f..135cd78109e2 100644
--- a/drivers/ufs/host/ufs-mediatek.c
+++ b/drivers/ufs/host/ufs-mediatek.c
@@ -1879,10 +1879,7 @@ out:
*/
static void ufs_mtk_remove(struct platform_device *pdev)
{
- struct ufs_hba *hba = platform_get_drvdata(pdev);
-
- pm_runtime_get_sync(&(pdev)->dev);
- ufshcd_remove(hba);
+ ufshcd_pltfrm_remove(pdev);
}
#ifdef CONFIG_PM_SLEEP
@@ -1962,7 +1959,7 @@ static const struct dev_pm_ops ufs_mtk_pm_ops = {
static struct platform_driver ufs_mtk_pltform = {
.probe = ufs_mtk_probe,
- .remove_new = ufs_mtk_remove,
+ .remove = ufs_mtk_remove,
.driver = {
.name = "ufshcd-mtk",
.pm = &ufs_mtk_pm_ops,
diff --git a/drivers/ufs/host/ufs-qcom.c b/drivers/ufs/host/ufs-qcom.c
index 3b592492e152..91e94fe990b4 100644
--- a/drivers/ufs/host/ufs-qcom.c
+++ b/drivers/ufs/host/ufs-qcom.c
@@ -368,6 +368,11 @@ static int ufs_qcom_power_up_sequence(struct ufs_hba *hba)
if (ret)
return ret;
+ if (phy->power_count) {
+ phy_power_off(phy);
+ phy_exit(phy);
+ }
+
/* phy initialization - calibrate the phy */
ret = phy_init(phy);
if (ret) {
@@ -866,6 +871,7 @@ static u32 ufs_qcom_get_ufs_hci_version(struct ufs_hba *hba)
*/
static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
{
+ const struct ufs_qcom_drvdata *drvdata = of_device_get_match_data(hba->dev);
struct ufs_qcom_host *host = ufshcd_get_variant(hba);
if (host->hw_ver.major == 0x2)
@@ -874,9 +880,8 @@ static void ufs_qcom_advertise_quirks(struct ufs_hba *hba)
if (host->hw_ver.major > 0x3)
hba->quirks |= UFSHCD_QUIRK_REINIT_AFTER_MAX_GEAR_SWITCH;
- if (of_device_is_compatible(hba->dev->of_node, "qcom,sm8550-ufshc") ||
- of_device_is_compatible(hba->dev->of_node, "qcom,sm8650-ufshc"))
- hba->quirks |= UFSHCD_QUIRK_BROKEN_LSDBS_CAP;
+ if (drvdata && drvdata->quirks)
+ hba->quirks |= drvdata->quirks;
}
static void ufs_qcom_set_phy_gear(struct ufs_qcom_host *host)
@@ -1064,6 +1069,7 @@ static int ufs_qcom_init(struct ufs_hba *hba)
struct device *dev = hba->dev;
struct ufs_qcom_host *host;
struct ufs_clk_info *clki;
+ const struct ufs_qcom_drvdata *drvdata = of_device_get_match_data(hba->dev);
host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
if (!host)
@@ -1143,6 +1149,9 @@ static int ufs_qcom_init(struct ufs_hba *hba)
dev_warn(dev, "%s: failed to configure the testbus %d\n",
__func__, err);
+ if (drvdata && drvdata->no_phy_retention)
+ hba->spm_lvl = UFS_PM_LVL_5;
+
return 0;
out_variant_clear:
@@ -1579,13 +1588,6 @@ static void ufs_qcom_config_scaling_param(struct ufs_hba *hba,
}
#endif
-static void ufs_qcom_reinit_notify(struct ufs_hba *hba)
-{
- struct ufs_qcom_host *host = ufshcd_get_variant(hba);
-
- phy_power_off(host->generic_phy);
-}
-
/* Resources */
static const struct ufshcd_res_info ufs_res_info[RES_MAX] = {
{.name = "ufs_mem",},
@@ -1825,7 +1827,6 @@ static const struct ufs_hba_variant_ops ufs_hba_qcom_vops = {
.device_reset = ufs_qcom_device_reset,
.config_scaling_param = ufs_qcom_config_scaling_param,
.program_key = ufs_qcom_ice_program_key,
- .reinit_notify = ufs_qcom_reinit_notify,
.mcq_config_resource = ufs_qcom_mcq_config_resource,
.get_hba_mac = ufs_qcom_get_hba_mac,
.op_runtime_config = ufs_qcom_op_runtime_config,
@@ -1861,15 +1862,22 @@ static int ufs_qcom_probe(struct platform_device *pdev)
static void ufs_qcom_remove(struct platform_device *pdev)
{
struct ufs_hba *hba = platform_get_drvdata(pdev);
+ struct ufs_qcom_host *host = ufshcd_get_variant(hba);
- pm_runtime_get_sync(&(pdev)->dev);
- ufshcd_remove(hba);
- platform_device_msi_free_irqs_all(hba->dev);
+ ufshcd_pltfrm_remove(pdev);
+ if (host->esi_enabled)
+ platform_device_msi_free_irqs_all(hba->dev);
}
+static const struct ufs_qcom_drvdata ufs_qcom_sm8550_drvdata = {
+ .quirks = UFSHCD_QUIRK_BROKEN_LSDBS_CAP,
+ .no_phy_retention = true,
+};
+
static const struct of_device_id ufs_qcom_of_match[] __maybe_unused = {
{ .compatible = "qcom,ufshc" },
- { .compatible = "qcom,sm8550-ufshc" },
+ { .compatible = "qcom,sm8550-ufshc", .data = &ufs_qcom_sm8550_drvdata },
+ { .compatible = "qcom,sm8650-ufshc", .data = &ufs_qcom_sm8550_drvdata },
{},
};
MODULE_DEVICE_TABLE(of, ufs_qcom_of_match);
@@ -1897,7 +1905,7 @@ static const struct dev_pm_ops ufs_qcom_pm_ops = {
static struct platform_driver ufs_qcom_pltform = {
.probe = ufs_qcom_probe,
- .remove_new = ufs_qcom_remove,
+ .remove = ufs_qcom_remove,
.driver = {
.name = "ufshcd-qcom",
.pm = &ufs_qcom_pm_ops,
diff --git a/drivers/ufs/host/ufs-qcom.h b/drivers/ufs/host/ufs-qcom.h
index b9de170983c9..919f53682beb 100644
--- a/drivers/ufs/host/ufs-qcom.h
+++ b/drivers/ufs/host/ufs-qcom.h
@@ -217,6 +217,11 @@ struct ufs_qcom_host {
bool esi_enabled;
};
+struct ufs_qcom_drvdata {
+ enum ufshcd_quirks quirks;
+ bool no_phy_retention;
+};
+
static inline u32
ufs_qcom_get_debug_reg_offset(struct ufs_qcom_host *host, u32 reg)
{
diff --git a/drivers/ufs/host/ufs-renesas.c b/drivers/ufs/host/ufs-renesas.c
index 3ff97112e1f6..03cd82db751b 100644
--- a/drivers/ufs/host/ufs-renesas.c
+++ b/drivers/ufs/host/ufs-renesas.c
@@ -397,14 +397,12 @@ static int ufs_renesas_probe(struct platform_device *pdev)
static void ufs_renesas_remove(struct platform_device *pdev)
{
- struct ufs_hba *hba = platform_get_drvdata(pdev);
-
- ufshcd_remove(hba);
+ ufshcd_pltfrm_remove(pdev);
}
static struct platform_driver ufs_renesas_platform = {
.probe = ufs_renesas_probe,
- .remove_new = ufs_renesas_remove,
+ .remove = ufs_renesas_remove,
.driver = {
.name = "ufshcd-renesas",
.of_match_table = of_match_ptr(ufs_renesas_of_match),
diff --git a/drivers/ufs/host/ufs-sprd.c b/drivers/ufs/host/ufs-sprd.c
index d8b165908809..b1d532363f9d 100644
--- a/drivers/ufs/host/ufs-sprd.c
+++ b/drivers/ufs/host/ufs-sprd.c
@@ -427,10 +427,7 @@ static int ufs_sprd_probe(struct platform_device *pdev)
static void ufs_sprd_remove(struct platform_device *pdev)
{
- struct ufs_hba *hba = platform_get_drvdata(pdev);
-
- pm_runtime_get_sync(&(pdev)->dev);
- ufshcd_remove(hba);
+ ufshcd_pltfrm_remove(pdev);
}
static const struct dev_pm_ops ufs_sprd_pm_ops = {
@@ -442,7 +439,7 @@ static const struct dev_pm_ops ufs_sprd_pm_ops = {
static struct platform_driver ufs_sprd_pltform = {
.probe = ufs_sprd_probe,
- .remove_new = ufs_sprd_remove,
+ .remove = ufs_sprd_remove,
.driver = {
.name = "ufshcd-sprd",
.pm = &ufs_sprd_pm_ops,
diff --git a/drivers/ufs/host/ufshcd-pltfrm.c b/drivers/ufs/host/ufshcd-pltfrm.c
index 1f4f30d6cb42..505572d4fa87 100644
--- a/drivers/ufs/host/ufshcd-pltfrm.c
+++ b/drivers/ufs/host/ufshcd-pltfrm.c
@@ -524,6 +524,22 @@ out:
}
EXPORT_SYMBOL_GPL(ufshcd_pltfrm_init);
+/**
+ * ufshcd_pltfrm_remove - Remove ufshcd platform
+ * @pdev: pointer to Platform device handle
+ */
+void ufshcd_pltfrm_remove(struct platform_device *pdev)
+{
+ struct ufs_hba *hba = platform_get_drvdata(pdev);
+
+ pm_runtime_get_sync(&pdev->dev);
+ ufshcd_remove(hba);
+ ufshcd_dealloc_host(hba);
+ pm_runtime_disable(&pdev->dev);
+ pm_runtime_put_noidle(&pdev->dev);
+}
+EXPORT_SYMBOL_GPL(ufshcd_pltfrm_remove);
+
MODULE_AUTHOR("Santosh Yaragnavi <santosh.sy@samsung.com>");
MODULE_AUTHOR("Vinayak Holikatti <h.vinayak@samsung.com>");
MODULE_DESCRIPTION("UFS host controller Platform bus based glue driver");
diff --git a/drivers/ufs/host/ufshcd-pltfrm.h b/drivers/ufs/host/ufshcd-pltfrm.h
index df387be5216b..3017f8e8f93c 100644
--- a/drivers/ufs/host/ufshcd-pltfrm.h
+++ b/drivers/ufs/host/ufshcd-pltfrm.h
@@ -31,6 +31,7 @@ int ufshcd_negotiate_pwr_params(const struct ufs_host_params *host_params,
void ufshcd_init_host_params(struct ufs_host_params *host_params);
int ufshcd_pltfrm_init(struct platform_device *pdev,
const struct ufs_hba_variant_ops *vops);
+void ufshcd_pltfrm_remove(struct platform_device *pdev);
int ufshcd_populate_vreg(struct device *dev, const char *name,
struct ufs_vreg **out_vreg, bool skip_current);
diff --git a/drivers/uio/uio_dmem_genirq.c b/drivers/uio/uio_dmem_genirq.c
index 13cc35ab5d29..c70dd81bfc61 100644
--- a/drivers/uio/uio_dmem_genirq.c
+++ b/drivers/uio/uio_dmem_genirq.c
@@ -210,8 +210,6 @@ static int uio_dmem_genirq_probe(struct platform_device *pdev)
}
if (uioinfo->irq) {
- struct irq_data *irq_data = irq_get_irq_data(uioinfo->irq);
-
/*
* If a level interrupt, dont do lazy disable. Otherwise the
* irq will fire again since clearing of the actual cause, on
@@ -219,8 +217,7 @@ static int uio_dmem_genirq_probe(struct platform_device *pdev)
* irqd_is_level_type() isn't used since isn't valid until
* irq is configured.
*/
- if (irq_data &&
- irqd_get_trigger_type(irq_data) & IRQ_TYPE_LEVEL_MASK) {
+ if (irq_get_trigger_type(uioinfo->irq) & IRQ_TYPE_LEVEL_MASK) {
dev_dbg(&pdev->dev, "disable lazy unmask\n");
irq_set_status_flags(uioinfo->irq, IRQ_DISABLE_UNLAZY);
}
diff --git a/drivers/uio/uio_fsl_elbc_gpcm.c b/drivers/uio/uio_fsl_elbc_gpcm.c
index 496caff66e7e..81454c3e2484 100644
--- a/drivers/uio/uio_fsl_elbc_gpcm.c
+++ b/drivers/uio/uio_fsl_elbc_gpcm.c
@@ -453,7 +453,7 @@ static struct platform_driver uio_fsl_elbc_gpcm_driver = {
.dev_groups = uio_fsl_elbc_gpcm_groups,
},
.probe = uio_fsl_elbc_gpcm_probe,
- .remove_new = uio_fsl_elbc_gpcm_remove,
+ .remove = uio_fsl_elbc_gpcm_remove,
};
module_platform_driver(uio_fsl_elbc_gpcm_driver);
diff --git a/drivers/uio/uio_hv_generic.c b/drivers/uio/uio_hv_generic.c
index 870409599411..3976360d0096 100644
--- a/drivers/uio/uio_hv_generic.c
+++ b/drivers/uio/uio_hv_generic.c
@@ -135,7 +135,7 @@ static void hv_uio_rescind(struct vmbus_channel *channel)
* The ring buffer is allocated as contiguous memory by vmbus_open
*/
static int hv_uio_ring_mmap(struct file *filp, struct kobject *kobj,
- struct bin_attribute *attr,
+ const struct bin_attribute *attr,
struct vm_area_struct *vma)
{
struct vmbus_channel *channel
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index 796f5be0a086..2ec7d25e8264 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -173,8 +173,6 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
}
if (uioinfo->irq) {
- struct irq_data *irq_data = irq_get_irq_data(uioinfo->irq);
-
/*
* If a level interrupt, dont do lazy disable. Otherwise the
* irq will fire again since clearing of the actual cause, on
@@ -182,8 +180,7 @@ static int uio_pdrv_genirq_probe(struct platform_device *pdev)
* irqd_is_level_type() isn't used since isn't valid until
* irq is configured.
*/
- if (irq_data &&
- irqd_get_trigger_type(irq_data) & IRQ_TYPE_LEVEL_MASK) {
+ if (irq_get_trigger_type(uioinfo->irq) & IRQ_TYPE_LEVEL_MASK) {
dev_dbg(&pdev->dev, "disable lazy unmask\n");
irq_set_status_flags(uioinfo->irq, IRQ_DISABLE_UNLAZY);
}
diff --git a/drivers/usb/atm/ueagle-atm.c b/drivers/usb/atm/ueagle-atm.c
index e8e43c38aa1b..cd0f7b4bd82a 100644
--- a/drivers/usb/atm/ueagle-atm.c
+++ b/drivers/usb/atm/ueagle-atm.c
@@ -808,7 +808,7 @@ static int check_dsp_e4(const u8 *dsp, int len)
if (l > len)
return 1;
- /* zero is zero regardless endianes */
+ /* zero is zero regardless endianness */
} while (blockidx->NotLastBlock);
}
@@ -1276,7 +1276,7 @@ static void uea_set_bulk_timeout(struct uea_softc *sc, u32 dsrate)
sc->stats.phy.dsrate == dsrate)
return;
- /* Original timming (1Mbit/s) from ADI (used in windows driver) */
+ /* Original timing (1Mbit/s) from ADI (used in windows driver) */
timeout = (dsrate <= 1024*1024) ? 0 : 1;
ret = uea_request(sc, UEA_SET_TIMEOUT, timeout, 0, NULL);
uea_info(INS_TO_USBDEV(sc), "setting new timeout %d%s\n",
@@ -1972,7 +1972,7 @@ static void uea_dispatch_cmv_e1(struct uea_softc *sc, struct intr_pkt *intr)
if (cmv->bDirection != E1_MODEMTOHOST)
goto bad1;
- /* FIXME : ADI930 reply wrong preambule (func = 2, sub = 2) to
+ /* FIXME : ADI930 reply wrong preamble (func = 2, sub = 2) to
* the first MEMACCESS cmv. Ignore it...
*/
if (cmv->bFunction != dsc->function) {
diff --git a/drivers/usb/atm/usbatm.c b/drivers/usb/atm/usbatm.c
index 2da6615fbb6f..d1e622bb1406 100644
--- a/drivers/usb/atm/usbatm.c
+++ b/drivers/usb/atm/usbatm.c
@@ -1158,7 +1158,7 @@ int usbatm_usb_probe(struct usb_interface *intf, const struct usb_device_id *id,
if (i >= num_rcv_urbs)
list_add_tail(&urb->urb_list, &channel->list);
- vdbg(&intf->dev, "%s: alloced buffer 0x%p buf size %u urb 0x%p",
+ vdbg(&intf->dev, "%s: allocated buffer 0x%p buf size %u urb 0x%p",
__func__, urb->transfer_buffer, urb->transfer_buffer_length, urb);
}
diff --git a/drivers/usb/c67x00/c67x00-drv.c b/drivers/usb/c67x00/c67x00-drv.c
index bb9d5d7ffefc..8f38e2c5369a 100644
--- a/drivers/usb/c67x00/c67x00-drv.c
+++ b/drivers/usb/c67x00/c67x00-drv.c
@@ -201,7 +201,7 @@ static void c67x00_drv_remove(struct platform_device *pdev)
static struct platform_driver c67x00_driver = {
.probe = c67x00_drv_probe,
- .remove_new = c67x00_drv_remove,
+ .remove = c67x00_drv_remove,
.driver = {
.name = "c67x00",
},
diff --git a/drivers/usb/cdns3/cdns3-imx.c b/drivers/usb/cdns3/cdns3-imx.c
index 281de47e2a3b..a2f041e1707c 100644
--- a/drivers/usb/cdns3/cdns3-imx.c
+++ b/drivers/usb/cdns3/cdns3-imx.c
@@ -422,7 +422,7 @@ MODULE_DEVICE_TABLE(of, cdns_imx_of_match);
static struct platform_driver cdns_imx_driver = {
.probe = cdns_imx_probe,
- .remove_new = cdns_imx_remove,
+ .remove = cdns_imx_remove,
.driver = {
.name = "cdns3-imx",
.of_match_table = cdns_imx_of_match,
diff --git a/drivers/usb/cdns3/cdns3-pci-wrap.c b/drivers/usb/cdns3/cdns3-pci-wrap.c
index 591d149de8f3..3b3b3dc75f35 100644
--- a/drivers/usb/cdns3/cdns3-pci-wrap.c
+++ b/drivers/usb/cdns3/cdns3-pci-wrap.c
@@ -37,8 +37,6 @@ struct cdns3_wrap {
#define PCI_DRIVER_NAME "cdns3-pci-usbss"
#define PLAT_DRIVER_NAME "cdns-usb3"
-#define PCI_DEVICE_ID_CDNS_USB3 0x0100
-
static struct pci_dev *cdns3_get_second_fun(struct pci_dev *pdev)
{
struct pci_dev *func;
@@ -189,7 +187,7 @@ static void cdns3_pci_remove(struct pci_dev *pdev)
}
static const struct pci_device_id cdns3_pci_ids[] = {
- { PCI_VDEVICE(CDNS, PCI_DEVICE_ID_CDNS_USB3) },
+ { PCI_VDEVICE(CDNS, PCI_DEVICE_ID_CDNS_USBSS) },
{ 0, }
};
diff --git a/drivers/usb/cdns3/cdns3-plat.c b/drivers/usb/cdns3/cdns3-plat.c
index 3ef8e3c872a3..59ec505e198a 100644
--- a/drivers/usb/cdns3/cdns3-plat.c
+++ b/drivers/usb/cdns3/cdns3-plat.c
@@ -327,7 +327,7 @@ MODULE_DEVICE_TABLE(of, of_cdns3_match);
static struct platform_driver cdns3_driver = {
.probe = cdns3_plat_probe,
- .remove_new = cdns3_plat_remove,
+ .remove = cdns3_plat_remove,
.driver = {
.name = "cdns-usb3",
.of_match_table = of_match_ptr(of_cdns3_match),
diff --git a/drivers/usb/cdns3/cdns3-starfive.c b/drivers/usb/cdns3/cdns3-starfive.c
index c04d196abd87..2ff7f2b48cc2 100644
--- a/drivers/usb/cdns3/cdns3-starfive.c
+++ b/drivers/usb/cdns3/cdns3-starfive.c
@@ -230,7 +230,7 @@ MODULE_DEVICE_TABLE(of, cdns_starfive_of_match);
static struct platform_driver cdns_starfive_driver = {
.probe = cdns_starfive_probe,
- .remove_new = cdns_starfive_remove,
+ .remove = cdns_starfive_remove,
.driver = {
.name = "cdns3-starfive",
.of_match_table = cdns_starfive_of_match,
diff --git a/drivers/usb/cdns3/cdns3-ti.c b/drivers/usb/cdns3/cdns3-ti.c
index cfabc12ee0e3..040bb91e9c01 100644
--- a/drivers/usb/cdns3/cdns3-ti.c
+++ b/drivers/usb/cdns3/cdns3-ti.c
@@ -233,7 +233,7 @@ MODULE_DEVICE_TABLE(of, cdns_ti_of_match);
static struct platform_driver cdns_ti_driver = {
.probe = cdns_ti_probe,
- .remove_new = cdns_ti_remove,
+ .remove = cdns_ti_remove,
.driver = {
.name = "cdns3-ti",
.of_match_table = cdns_ti_of_match,
diff --git a/drivers/usb/cdns3/cdnsp-pci.c b/drivers/usb/cdns3/cdnsp-pci.c
index 2d05368a6745..a51144504ff3 100644
--- a/drivers/usb/cdns3/cdnsp-pci.c
+++ b/drivers/usb/cdns3/cdnsp-pci.c
@@ -28,12 +28,6 @@
#define PCI_DRIVER_NAME "cdns-pci-usbssp"
#define PLAT_DRIVER_NAME "cdns-usbssp"
-#define PCI_DEVICE_ID_CDNS_USB3 0x0100
-#define PCI_DEVICE_ID_CDNS_UDC 0x0200
-
-#define PCI_CLASS_SERIAL_USB_CDNS_USB3 (PCI_CLASS_SERIAL_USB << 8 | 0x80)
-#define PCI_CLASS_SERIAL_USB_CDNS_UDC PCI_CLASS_SERIAL_USB_DEVICE
-
static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev)
{
/*
@@ -41,10 +35,10 @@ static struct pci_dev *cdnsp_get_second_fun(struct pci_dev *pdev)
* Platform has two function. The fist keeps resources for
* Host/Device while the secon keeps resources for DRD/OTG.
*/
- if (pdev->device == PCI_DEVICE_ID_CDNS_UDC)
- return pci_get_device(pdev->vendor, PCI_DEVICE_ID_CDNS_USB3, NULL);
- if (pdev->device == PCI_DEVICE_ID_CDNS_USB3)
- return pci_get_device(pdev->vendor, PCI_DEVICE_ID_CDNS_UDC, NULL);
+ if (pdev->device == PCI_DEVICE_ID_CDNS_USBSSP)
+ return pci_get_device(pdev->vendor, PCI_DEVICE_ID_CDNS_USBSS, NULL);
+ if (pdev->device == PCI_DEVICE_ID_CDNS_USBSS)
+ return pci_get_device(pdev->vendor, PCI_DEVICE_ID_CDNS_USBSSP, NULL);
return NULL;
}
@@ -221,12 +215,12 @@ static const struct dev_pm_ops cdnsp_pci_pm_ops = {
};
static const struct pci_device_id cdnsp_pci_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_UDC),
- .class = PCI_CLASS_SERIAL_USB_CDNS_UDC },
- { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_UDC),
- .class = PCI_CLASS_SERIAL_USB_CDNS_USB3 },
- { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USB3),
- .class = PCI_CLASS_SERIAL_USB_CDNS_USB3 },
+ { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USBSSP),
+ .class = PCI_CLASS_SERIAL_USB_DEVICE },
+ { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USBSSP),
+ .class = PCI_CLASS_SERIAL_USB_CDNS },
+ { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USBSS),
+ .class = PCI_CLASS_SERIAL_USB_CDNS },
{ 0, }
};
diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h
index 2a38e1eb6546..97437de52ef6 100644
--- a/drivers/usb/chipidea/ci.h
+++ b/drivers/usb/chipidea/ci.h
@@ -25,6 +25,7 @@
#define TD_PAGE_COUNT 5
#define CI_HDRC_PAGE_SIZE 4096ul /* page size for TD's */
#define ENDPT_MAX 32
+#define CI_MAX_REQ_SIZE (4 * CI_HDRC_PAGE_SIZE)
#define CI_MAX_BUF_SIZE (TD_PAGE_COUNT * CI_HDRC_PAGE_SIZE)
/******************************************************************************
@@ -260,6 +261,7 @@ struct ci_hdrc {
bool b_sess_valid_event;
bool imx28_write_fix;
bool has_portsc_pec_bug;
+ bool has_short_pkt_limit;
bool supports_runtime_pm;
bool in_lpm;
bool wakeup_int;
diff --git a/drivers/usb/chipidea/ci_hdrc_imx.c b/drivers/usb/chipidea/ci_hdrc_imx.c
index c64ab0e07ea0..f2801700be8e 100644
--- a/drivers/usb/chipidea/ci_hdrc_imx.c
+++ b/drivers/usb/chipidea/ci_hdrc_imx.c
@@ -342,6 +342,7 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
struct ci_hdrc_platform_data pdata = {
.name = dev_name(&pdev->dev),
.capoffset = DEF_CAPOFFSET,
+ .flags = CI_HDRC_HAS_SHORT_PKT_LIMIT,
.notify_event = ci_hdrc_imx_notify_event,
};
int ret;
@@ -675,7 +676,7 @@ static const struct dev_pm_ops ci_hdrc_imx_pm_ops = {
};
static struct platform_driver ci_hdrc_imx_driver = {
.probe = ci_hdrc_imx_probe,
- .remove_new = ci_hdrc_imx_remove,
+ .remove = ci_hdrc_imx_remove,
.shutdown = ci_hdrc_imx_shutdown,
.driver = {
.name = "imx_usb",
diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c
index 1661639cd2eb..3ab3daa78e34 100644
--- a/drivers/usb/chipidea/ci_hdrc_msm.c
+++ b/drivers/usb/chipidea/ci_hdrc_msm.c
@@ -292,7 +292,7 @@ MODULE_DEVICE_TABLE(of, msm_ci_dt_match);
static struct platform_driver ci_hdrc_msm_driver = {
.probe = ci_hdrc_msm_probe,
- .remove_new = ci_hdrc_msm_remove,
+ .remove = ci_hdrc_msm_remove,
.driver = {
.name = "msm_hsusb",
.of_match_table = msm_ci_dt_match,
diff --git a/drivers/usb/chipidea/ci_hdrc_npcm.c b/drivers/usb/chipidea/ci_hdrc_npcm.c
index 3e5e05dbda89..e52a2b05cbe2 100644
--- a/drivers/usb/chipidea/ci_hdrc_npcm.c
+++ b/drivers/usb/chipidea/ci_hdrc_npcm.c
@@ -98,7 +98,7 @@ MODULE_DEVICE_TABLE(of, npcm_udc_dt_match);
static struct platform_driver npcm_udc_driver = {
.probe = npcm_udc_probe,
- .remove_new = npcm_udc_remove,
+ .remove = npcm_udc_remove,
.driver = {
.name = "npcm_udc",
.of_match_table = npcm_udc_dt_match,
diff --git a/drivers/usb/chipidea/ci_hdrc_tegra.c b/drivers/usb/chipidea/ci_hdrc_tegra.c
index 9538d425f0a0..372788f0f970 100644
--- a/drivers/usb/chipidea/ci_hdrc_tegra.c
+++ b/drivers/usb/chipidea/ci_hdrc_tegra.c
@@ -406,7 +406,7 @@ static struct platform_driver tegra_usb_driver = {
.pm = pm_ptr(&tegra_usb_pm),
},
.probe = tegra_usb_probe,
- .remove_new = tegra_usb_remove,
+ .remove = tegra_usb_remove,
};
module_platform_driver(tegra_usb_driver);
diff --git a/drivers/usb/chipidea/ci_hdrc_usb2.c b/drivers/usb/chipidea/ci_hdrc_usb2.c
index 97379f653b06..8ffa1e95d8e8 100644
--- a/drivers/usb/chipidea/ci_hdrc_usb2.c
+++ b/drivers/usb/chipidea/ci_hdrc_usb2.c
@@ -116,7 +116,7 @@ static void ci_hdrc_usb2_remove(struct platform_device *pdev)
static struct platform_driver ci_hdrc_usb2_driver = {
.probe = ci_hdrc_usb2_probe,
- .remove_new = ci_hdrc_usb2_remove,
+ .remove = ci_hdrc_usb2_remove,
.driver = {
.name = "chipidea-usb2",
.of_match_table = ci_hdrc_usb2_of_match,
diff --git a/drivers/usb/chipidea/core.c b/drivers/usb/chipidea/core.c
index 835bf2428dc6..694b4a8e4e1d 100644
--- a/drivers/usb/chipidea/core.c
+++ b/drivers/usb/chipidea/core.c
@@ -765,7 +765,7 @@ static int ci_get_platdata(struct device *dev,
ext_id = ERR_PTR(-ENODEV);
ext_vbus = ERR_PTR(-ENODEV);
- if (of_property_read_bool(dev->of_node, "extcon")) {
+ if (of_property_present(dev->of_node, "extcon")) {
/* Each one of them is not mandatory */
ext_vbus = extcon_get_edev_by_phandle(dev, 0);
if (IS_ERR(ext_vbus) && PTR_ERR(ext_vbus) != -ENODEV)
@@ -1076,6 +1076,8 @@ static int ci_hdrc_probe(struct platform_device *pdev)
CI_HDRC_SUPPORTS_RUNTIME_PM);
ci->has_portsc_pec_bug = !!(ci->platdata->flags &
CI_HDRC_HAS_PORTSC_PEC_MISSED);
+ ci->has_short_pkt_limit = !!(ci->platdata->flags &
+ CI_HDRC_HAS_SHORT_PKT_LIMIT);
platform_set_drvdata(pdev, ci);
ret = hw_device_init(ci, base);
@@ -1495,7 +1497,7 @@ static const struct dev_pm_ops ci_pm_ops = {
static struct platform_driver ci_hdrc_driver = {
.probe = ci_hdrc_probe,
- .remove_new = ci_hdrc_remove,
+ .remove = ci_hdrc_remove,
.driver = {
.name = "ci_hdrc",
.pm = &ci_pm_ops,
diff --git a/drivers/usb/chipidea/udc.c b/drivers/usb/chipidea/udc.c
index 69ef3cd8d4f8..8a9b31fd5c89 100644
--- a/drivers/usb/chipidea/udc.c
+++ b/drivers/usb/chipidea/udc.c
@@ -10,6 +10,7 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/dmapool.h>
+#include <linux/dma-direct.h>
#include <linux/err.h>
#include <linux/irqreturn.h>
#include <linux/kernel.h>
@@ -540,6 +541,126 @@ static int prepare_td_for_sg(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
return ret;
}
+/*
+ * Verify if the scatterlist is valid by iterating each sg entry.
+ * Return invalid sg entry index which is less than num_sgs.
+ */
+static int sglist_get_invalid_entry(struct device *dma_dev, u8 dir,
+ struct usb_request *req)
+{
+ int i;
+ struct scatterlist *s = req->sg;
+
+ if (req->num_sgs == 1)
+ return 1;
+
+ dir = dir ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ for (i = 0; i < req->num_sgs; i++, s = sg_next(s)) {
+ /* Only small sg (generally last sg) may be bounced. If
+ * that happens. we can't ensure the addr is page-aligned
+ * after dma map.
+ */
+ if (dma_kmalloc_needs_bounce(dma_dev, s->length, dir))
+ break;
+
+ /* Make sure each sg start address (except first sg) is
+ * page-aligned and end address (except last sg) is also
+ * page-aligned.
+ */
+ if (i == 0) {
+ if (!IS_ALIGNED(s->offset + s->length,
+ CI_HDRC_PAGE_SIZE))
+ break;
+ } else {
+ if (s->offset)
+ break;
+ if (!sg_is_last(s) && !IS_ALIGNED(s->length,
+ CI_HDRC_PAGE_SIZE))
+ break;
+ }
+ }
+
+ return i;
+}
+
+static int sglist_do_bounce(struct ci_hw_req *hwreq, int index,
+ bool copy, unsigned int *bounced)
+{
+ void *buf;
+ int i, ret, nents, num_sgs;
+ unsigned int rest, rounded;
+ struct scatterlist *sg, *src, *dst;
+
+ nents = index + 1;
+ ret = sg_alloc_table(&hwreq->sgt, nents, GFP_KERNEL);
+ if (ret)
+ return ret;
+
+ sg = src = hwreq->req.sg;
+ num_sgs = hwreq->req.num_sgs;
+ rest = hwreq->req.length;
+ dst = hwreq->sgt.sgl;
+
+ for (i = 0; i < index; i++) {
+ memcpy(dst, src, sizeof(*src));
+ rest -= src->length;
+ src = sg_next(src);
+ dst = sg_next(dst);
+ }
+
+ /* create one bounce buffer */
+ rounded = round_up(rest, CI_HDRC_PAGE_SIZE);
+ buf = kmalloc(rounded, GFP_KERNEL);
+ if (!buf) {
+ sg_free_table(&hwreq->sgt);
+ return -ENOMEM;
+ }
+
+ sg_set_buf(dst, buf, rounded);
+
+ hwreq->req.sg = hwreq->sgt.sgl;
+ hwreq->req.num_sgs = nents;
+ hwreq->sgt.sgl = sg;
+ hwreq->sgt.nents = num_sgs;
+
+ if (copy)
+ sg_copy_to_buffer(src, num_sgs - index, buf, rest);
+
+ *bounced = rest;
+
+ return 0;
+}
+
+static void sglist_do_debounce(struct ci_hw_req *hwreq, bool copy)
+{
+ void *buf;
+ int i, nents, num_sgs;
+ struct scatterlist *sg, *src, *dst;
+
+ sg = hwreq->req.sg;
+ num_sgs = hwreq->req.num_sgs;
+ src = sg_last(sg, num_sgs);
+ buf = sg_virt(src);
+
+ if (copy) {
+ dst = hwreq->sgt.sgl;
+ for (i = 0; i < num_sgs - 1; i++)
+ dst = sg_next(dst);
+
+ nents = hwreq->sgt.nents - num_sgs + 1;
+ sg_copy_from_buffer(dst, nents, buf, sg_dma_len(src));
+ }
+
+ hwreq->req.sg = hwreq->sgt.sgl;
+ hwreq->req.num_sgs = hwreq->sgt.nents;
+ hwreq->sgt.sgl = sg;
+ hwreq->sgt.nents = num_sgs;
+
+ kfree(buf);
+ sg_free_table(&hwreq->sgt);
+}
+
/**
* _hardware_enqueue: configures a request at hardware level
* @hwep: endpoint
@@ -552,6 +673,8 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
struct ci_hdrc *ci = hwep->ci;
int ret = 0;
struct td_node *firstnode, *lastnode;
+ unsigned int bounced_size;
+ struct scatterlist *sg;
/* don't queue twice */
if (hwreq->req.status == -EALREADY)
@@ -559,11 +682,29 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
hwreq->req.status = -EALREADY;
+ if (hwreq->req.num_sgs && hwreq->req.length &&
+ ci->has_short_pkt_limit) {
+ ret = sglist_get_invalid_entry(ci->dev->parent, hwep->dir,
+ &hwreq->req);
+ if (ret < hwreq->req.num_sgs) {
+ ret = sglist_do_bounce(hwreq, ret, hwep->dir == TX,
+ &bounced_size);
+ if (ret)
+ return ret;
+ }
+ }
+
ret = usb_gadget_map_request_by_dev(ci->dev->parent,
&hwreq->req, hwep->dir);
if (ret)
return ret;
+ if (hwreq->sgt.sgl) {
+ /* We've mapped a bigger buffer, now recover the actual size */
+ sg = sg_last(hwreq->req.sg, hwreq->req.num_sgs);
+ sg_dma_len(sg) = min(sg_dma_len(sg), bounced_size);
+ }
+
if (hwreq->req.num_mapped_sgs)
ret = prepare_td_for_sg(hwep, hwreq);
else
@@ -612,10 +753,17 @@ static int _hardware_enqueue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
do {
hw_write(ci, OP_USBCMD, USBCMD_ATDTW, USBCMD_ATDTW);
tmp_stat = hw_read(ci, OP_ENDPTSTAT, BIT(n));
- } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW));
+ } while (!hw_read(ci, OP_USBCMD, USBCMD_ATDTW) && tmp_stat);
hw_write(ci, OP_USBCMD, USBCMD_ATDTW, 0);
if (tmp_stat)
goto done;
+
+ /* OP_ENDPTSTAT will be clear by HW when the endpoint met
+ * err. This dTD don't push to dQH if current dTD point is
+ * not the last one in previous request.
+ */
+ if (hwep->qh.ptr->curr != cpu_to_le32(prevlastnode->dma))
+ goto done;
}
/* QH configuration */
@@ -676,6 +824,7 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
unsigned remaining_length;
unsigned actual = hwreq->req.length;
struct ci_hdrc *ci = hwep->ci;
+ bool is_isoc = hwep->type == USB_ENDPOINT_XFER_ISOC;
if (hwreq->req.status != -EALREADY)
return -EINVAL;
@@ -689,7 +838,7 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
int n = hw_ep_bit(hwep->num, hwep->dir);
if (ci->rev == CI_REVISION_24 ||
- ci->rev == CI_REVISION_22)
+ ci->rev == CI_REVISION_22 || is_isoc)
if (!hw_read(ci, OP_ENDPTSTAT, BIT(n)))
reprime_dtd(ci, hwep, node);
hwreq->req.status = -EALREADY;
@@ -708,11 +857,15 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
hwreq->req.status = -EPROTO;
break;
} else if ((TD_STATUS_TR_ERR & hwreq->req.status)) {
- hwreq->req.status = -EILSEQ;
- break;
+ if (is_isoc) {
+ hwreq->req.status = 0;
+ } else {
+ hwreq->req.status = -EILSEQ;
+ break;
+ }
}
- if (remaining_length) {
+ if (remaining_length && !is_isoc) {
if (hwep->dir == TX) {
hwreq->req.status = -EPROTO;
break;
@@ -733,6 +886,10 @@ static int _hardware_dequeue(struct ci_hw_ep *hwep, struct ci_hw_req *hwreq)
usb_gadget_unmap_request_by_dev(hwep->ci->dev->parent,
&hwreq->req, hwep->dir);
+ /* sglist bounced */
+ if (hwreq->sgt.sgl)
+ sglist_do_debounce(hwreq, hwep->dir == RX);
+
hwreq->req.actual += actual;
if (hwreq->req.status)
@@ -960,6 +1117,12 @@ static int _ep_queue(struct usb_ep *ep, struct usb_request *req,
return -EMSGSIZE;
}
+ if (ci->has_short_pkt_limit &&
+ hwreq->req.length > CI_MAX_REQ_SIZE) {
+ dev_err(hwep->ci->dev, "request length too big (max 16KB)\n");
+ return -EMSGSIZE;
+ }
+
/* first nuke then test link, e.g. previous status has not sent */
if (!list_empty(&hwreq->queue)) {
dev_err(hwep->ci->dev, "request already in queue\n");
@@ -1574,6 +1737,9 @@ static int ep_dequeue(struct usb_ep *ep, struct usb_request *req)
usb_gadget_unmap_request(&hwep->ci->gadget, req, hwep->dir);
+ if (hwreq->sgt.sgl)
+ sglist_do_debounce(hwreq, false);
+
req->status = -ECONNRESET;
if (hwreq->req.complete != NULL) {
@@ -2063,7 +2229,7 @@ static irqreturn_t udc_irq(struct ci_hdrc *ci)
}
}
- if (USBi_UI & intr)
+ if ((USBi_UI | USBi_UEI) & intr)
isr_tr_complete_handler(ci);
if ((USBi_SLI & intr) && !(ci->suspended)) {
diff --git a/drivers/usb/chipidea/udc.h b/drivers/usb/chipidea/udc.h
index 5193df1e18c7..c8a47389a46b 100644
--- a/drivers/usb/chipidea/udc.h
+++ b/drivers/usb/chipidea/udc.h
@@ -69,11 +69,13 @@ struct td_node {
* @req: request structure for gadget drivers
* @queue: link to QH list
* @tds: link to TD list
+ * @sgt: hold original sglist when bounce sglist
*/
struct ci_hw_req {
struct usb_request req;
struct list_head queue;
struct list_head tds;
+ struct sg_table sgt;
};
#ifdef CONFIG_USB_CHIPIDEA_UDC
diff --git a/drivers/usb/chipidea/usbmisc_imx.c b/drivers/usb/chipidea/usbmisc_imx.c
index 173c78afd502..1394881fde5f 100644
--- a/drivers/usb/chipidea/usbmisc_imx.c
+++ b/drivers/usb/chipidea/usbmisc_imx.c
@@ -1285,6 +1285,10 @@ static const struct of_device_id usbmisc_imx_dt_ids[] = {
.compatible = "fsl,imx7ulp-usbmisc",
.data = &imx7ulp_usbmisc_ops,
},
+ {
+ .compatible = "fsl,imx8ulp-usbmisc",
+ .data = &imx7ulp_usbmisc_ops,
+ },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, usbmisc_imx_dt_ids);
diff --git a/drivers/usb/common/common.c b/drivers/usb/common/common.c
index b7bea1015d7c..871cf199b6bf 100644
--- a/drivers/usb/common/common.c
+++ b/drivers/usb/common/common.c
@@ -415,6 +415,9 @@ EXPORT_SYMBOL_GPL(usb_of_get_companion_dev);
struct dentry *usb_debug_root;
EXPORT_SYMBOL_GPL(usb_debug_root);
+DEFINE_MUTEX(usb_dynids_lock);
+EXPORT_SYMBOL_GPL(usb_dynids_lock);
+
static int __init usb_common_init(void)
{
usb_debug_root = debugfs_create_dir("usb", NULL);
diff --git a/drivers/usb/common/usb-conn-gpio.c b/drivers/usb/common/usb-conn-gpio.c
index 501e8bc9738e..c84b4a700084 100644
--- a/drivers/usb/common/usb-conn-gpio.c
+++ b/drivers/usb/common/usb-conn-gpio.c
@@ -340,7 +340,7 @@ MODULE_DEVICE_TABLE(of, usb_conn_dt_match);
static struct platform_driver usb_conn_driver = {
.probe = usb_conn_probe,
- .remove_new = usb_conn_remove,
+ .remove = usb_conn_remove,
.driver = {
.name = "usb-conn-gpio",
.pm = &usb_conn_pm_ops,
diff --git a/drivers/usb/core/config.c b/drivers/usb/core/config.c
index 880d52c0949d..25a00f974934 100644
--- a/drivers/usb/core/config.c
+++ b/drivers/usb/core/config.c
@@ -924,7 +924,7 @@ int usb_get_configuration(struct usb_device *dev)
result = -EINVAL;
goto err;
}
- length = max((int) le16_to_cpu(desc->wTotalLength),
+ length = max_t(int, le16_to_cpu(desc->wTotalLength),
USB_DT_CONFIG_SIZE);
/* Now that we know the length, get the whole thing */
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 3beb6a862e80..f6ce6e26e0d4 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -238,6 +238,9 @@ static int usbdev_mmap(struct file *file, struct vm_area_struct *vma)
dma_addr_t dma_handle = DMA_MAPPING_ERROR;
int ret;
+ if (!(file->f_mode & FMODE_WRITE))
+ return -EPERM;
+
ret = usbfs_increase_memory_usage(size + sizeof(struct usb_memory));
if (ret)
goto error;
@@ -1295,7 +1298,7 @@ static int do_proc_bulk(struct usb_dev_state *ps,
return ret;
len1 = bulk->len;
- if (len1 < 0 || len1 >= (INT_MAX - sizeof(struct urb)))
+ if (len1 >= (INT_MAX - sizeof(struct urb)))
return -EINVAL;
if (bulk->ep & USB_DIR_IN)
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 0c3f12daac79..f203fdbfb6f6 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -95,9 +95,9 @@ ssize_t usb_store_new_id(struct usb_dynids *dynids,
}
}
- spin_lock(&dynids->lock);
+ mutex_lock(&usb_dynids_lock);
list_add_tail(&dynid->node, &dynids->list);
- spin_unlock(&dynids->lock);
+ mutex_unlock(&usb_dynids_lock);
retval = driver_attach(driver);
@@ -116,6 +116,7 @@ ssize_t usb_show_dynids(struct usb_dynids *dynids, char *buf)
struct usb_dynid *dynid;
size_t count = 0;
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry(dynid, &dynids->list, node)
if (dynid->id.bInterfaceClass != 0)
count += scnprintf(&buf[count], PAGE_SIZE - count, "%04x %04x %02x\n",
@@ -160,7 +161,7 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
if (fields < 2)
return -EINVAL;
- spin_lock(&usb_driver->dynids.lock);
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry_safe(dynid, n, &usb_driver->dynids.list, node) {
struct usb_device_id *id = &dynid->id;
@@ -171,7 +172,6 @@ static ssize_t remove_id_store(struct device_driver *driver, const char *buf,
break;
}
}
- spin_unlock(&usb_driver->dynids.lock);
return count;
}
@@ -220,27 +220,24 @@ static void usb_free_dynids(struct usb_driver *usb_drv)
{
struct usb_dynid *dynid, *n;
- spin_lock(&usb_drv->dynids.lock);
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry_safe(dynid, n, &usb_drv->dynids.list, node) {
list_del(&dynid->node);
kfree(dynid);
}
- spin_unlock(&usb_drv->dynids.lock);
}
static const struct usb_device_id *usb_match_dynamic_id(struct usb_interface *intf,
- struct usb_driver *drv)
+ const struct usb_driver *drv)
{
struct usb_dynid *dynid;
- spin_lock(&drv->dynids.lock);
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
if (usb_match_one_id(intf, &dynid->id)) {
- spin_unlock(&drv->dynids.lock);
return &dynid->id;
}
}
- spin_unlock(&drv->dynids.lock);
return NULL;
}
@@ -853,7 +850,7 @@ const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
EXPORT_SYMBOL_GPL(usb_device_match_id);
bool usb_driver_applicable(struct usb_device *udev,
- struct usb_device_driver *udrv)
+ const struct usb_device_driver *udrv)
{
if (udrv->id_table && udrv->match)
return usb_device_match_id(udev, udrv->id_table) != NULL &&
@@ -873,7 +870,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv)
/* devices and interfaces are handled separately */
if (is_usb_device(dev)) {
struct usb_device *udev;
- struct usb_device_driver *udrv;
+ const struct usb_device_driver *udrv;
/* interface drivers never match devices */
if (!is_usb_device_driver(drv))
@@ -893,7 +890,7 @@ static int usb_device_match(struct device *dev, const struct device_driver *drv)
} else if (is_usb_interface(dev)) {
struct usb_interface *intf;
- struct usb_driver *usb_drv;
+ const struct usb_driver *usb_drv;
const struct usb_device_id *id;
/* device drivers never match interfaces */
@@ -1076,7 +1073,6 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner,
new_driver->driver.owner = owner;
new_driver->driver.mod_name = mod_name;
new_driver->driver.dev_groups = new_driver->dev_groups;
- spin_lock_init(&new_driver->dynids.lock);
INIT_LIST_HEAD(&new_driver->dynids.list);
retval = driver_register(&new_driver->driver);
diff --git a/drivers/usb/core/endpoint.c b/drivers/usb/core/endpoint.c
index 4b38b87a1343..e48399401608 100644
--- a/drivers/usb/core/endpoint.c
+++ b/drivers/usb/core/endpoint.c
@@ -14,6 +14,7 @@
#include <linux/kernel.h>
#include <linux/spinlock.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/usb.h>
#include "usb.h"
@@ -39,7 +40,7 @@ static ssize_t field##_show(struct device *dev, \
char *buf) \
{ \
struct ep_device *ep = to_ep_device(dev); \
- return sprintf(buf, format_string, ep->desc->field); \
+ return sysfs_emit(buf, format_string, ep->desc->field); \
} \
static DEVICE_ATTR_RO(field)
@@ -52,7 +53,7 @@ static ssize_t wMaxPacketSize_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
struct ep_device *ep = to_ep_device(dev);
- return sprintf(buf, "%04x\n", usb_endpoint_maxp(ep->desc));
+ return sysfs_emit(buf, "%04x\n", usb_endpoint_maxp(ep->desc));
}
static DEVICE_ATTR_RO(wMaxPacketSize);
@@ -76,7 +77,7 @@ static ssize_t type_show(struct device *dev, struct device_attribute *attr,
type = "Interrupt";
break;
}
- return sprintf(buf, "%s\n", type);
+ return sysfs_emit(buf, "%s\n", type);
}
static DEVICE_ATTR_RO(type);
@@ -95,7 +96,7 @@ static ssize_t interval_show(struct device *dev, struct device_attribute *attr,
interval /= 1000;
}
- return sprintf(buf, "%d%cs\n", interval, unit);
+ return sysfs_emit(buf, "%d%cs\n", interval, unit);
}
static DEVICE_ATTR_RO(interval);
@@ -111,7 +112,7 @@ static ssize_t direction_show(struct device *dev, struct device_attribute *attr,
direction = "in";
else
direction = "out";
- return sprintf(buf, "%s\n", direction);
+ return sysfs_emit(buf, "%s\n", direction);
}
static DEVICE_ATTR_RO(direction);
diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c
index 500dc35e6477..0b2490347b9f 100644
--- a/drivers/usb/core/hcd.c
+++ b/drivers/usb/core/hcd.c
@@ -2794,8 +2794,14 @@ int usb_add_hcd(struct usb_hcd *hcd,
int retval;
struct usb_device *rhdev;
struct usb_hcd *shared_hcd;
+ int skip_phy_initialization;
- if (!hcd->skip_phy_initialization) {
+ if (usb_hcd_is_primary_hcd(hcd))
+ skip_phy_initialization = hcd->skip_phy_initialization;
+ else
+ skip_phy_initialization = hcd->primary_hcd->skip_phy_initialization;
+
+ if (!skip_phy_initialization) {
if (usb_hcd_is_primary_hcd(hcd)) {
hcd->phy_roothub = usb_phy_roothub_alloc(hcd->self.sysdev);
if (IS_ERR(hcd->phy_roothub))
diff --git a/drivers/usb/core/ledtrig-usbport.c b/drivers/usb/core/ledtrig-usbport.c
index 85c999f71ad7..5e3c515991f3 100644
--- a/drivers/usb/core/ledtrig-usbport.c
+++ b/drivers/usb/core/ledtrig-usbport.c
@@ -10,6 +10,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/usb.h>
#include <linux/usb/of.h>
@@ -87,7 +88,7 @@ static ssize_t usbport_trig_port_show(struct device *dev,
struct usbport_trig_port,
attr);
- return sprintf(buf, "%d\n", port->observed) + 1;
+ return sysfs_emit(buf, "%d\n", port->observed) + 1;
}
static ssize_t usbport_trig_port_store(struct device *dev,
diff --git a/drivers/usb/core/port.c b/drivers/usb/core/port.c
index e7da2fca11a4..45d7af00f8d1 100644
--- a/drivers/usb/core/port.c
+++ b/drivers/usb/core/port.c
@@ -9,6 +9,7 @@
#include <linux/kstrtox.h>
#include <linux/slab.h>
+#include <linux/sysfs.h>
#include <linux/pm_qos.h>
#include <linux/component.h>
#include <linux/usb/of.h>
@@ -166,7 +167,7 @@ static ssize_t location_show(struct device *dev,
{
struct usb_port *port_dev = to_usb_port(dev);
- return sprintf(buf, "0x%08x\n", port_dev->location);
+ return sysfs_emit(buf, "0x%08x\n", port_dev->location);
}
static DEVICE_ATTR_RO(location);
@@ -191,7 +192,7 @@ static ssize_t connect_type_show(struct device *dev,
break;
}
- return sprintf(buf, "%s\n", result);
+ return sysfs_emit(buf, "%s\n", result);
}
static DEVICE_ATTR_RO(connect_type);
@@ -210,7 +211,7 @@ static ssize_t over_current_count_show(struct device *dev,
{
struct usb_port *port_dev = to_usb_port(dev);
- return sprintf(buf, "%u\n", port_dev->over_current_count);
+ return sysfs_emit(buf, "%u\n", port_dev->over_current_count);
}
static DEVICE_ATTR_RO(over_current_count);
@@ -219,7 +220,7 @@ static ssize_t quirks_show(struct device *dev,
{
struct usb_port *port_dev = to_usb_port(dev);
- return sprintf(buf, "%08x\n", port_dev->quirks);
+ return sysfs_emit(buf, "%08x\n", port_dev->quirks);
}
static ssize_t quirks_store(struct device *dev, struct device_attribute *attr,
@@ -254,7 +255,7 @@ static ssize_t usb3_lpm_permit_show(struct device *dev,
p = "0";
}
- return sprintf(buf, "%s\n", p);
+ return sysfs_emit(buf, "%s\n", p);
}
static ssize_t usb3_lpm_permit_store(struct device *dev,
diff --git a/drivers/usb/core/sysfs.c b/drivers/usb/core/sysfs.c
index 61b6d978892c..b4cba23831ac 100644
--- a/drivers/usb/core/sysfs.c
+++ b/drivers/usb/core/sysfs.c
@@ -925,7 +925,7 @@ static struct bin_attribute *dev_bin_attrs[] = {
};
static umode_t dev_bin_attrs_are_visible(struct kobject *kobj,
- struct bin_attribute *a, int n)
+ const struct bin_attribute *a, int n)
{
struct device *dev = kobj_to_dev(kobj);
struct usb_device *udev = to_usb_device(dev);
diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h
index b8324ea05b20..a9b37aeb515b 100644
--- a/drivers/usb/core/usb.h
+++ b/drivers/usb/core/usb.h
@@ -75,7 +75,7 @@ extern int usb_match_device(struct usb_device *dev,
extern const struct usb_device_id *usb_device_match_id(struct usb_device *udev,
const struct usb_device_id *id);
extern bool usb_driver_applicable(struct usb_device *udev,
- struct usb_device_driver *udrv);
+ const struct usb_device_driver *udrv);
extern void usb_forced_unbind_intf(struct usb_interface *intf);
extern void usb_unbind_and_rebind_marked_interfaces(struct usb_device *udev);
diff --git a/drivers/usb/dwc2/Kconfig b/drivers/usb/dwc2/Kconfig
index c131719367ec..d7af55a8eced 100644
--- a/drivers/usb/dwc2/Kconfig
+++ b/drivers/usb/dwc2/Kconfig
@@ -21,7 +21,7 @@ config USB_DWC2
if USB_DWC2
choice
- bool "DWC2 Mode Selection"
+ prompt "DWC2 Mode Selection"
default USB_DWC2_DUAL_ROLE if (USB && USB_GADGET)
default USB_DWC2_HOST if (USB && !USB_GADGET)
default USB_DWC2_PERIPHERAL if (!USB && USB_GADGET)
diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c
index cb54390e7de4..8c3941ecaaf5 100644
--- a/drivers/usb/dwc2/hcd.c
+++ b/drivers/usb/dwc2/hcd.c
@@ -3546,11 +3546,9 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
port_status |= USB_PORT_STAT_C_OVERCURRENT << 16;
}
- if (!hsotg->flags.b.port_connect_status) {
+ if (dwc2_is_device_mode(hsotg)) {
/*
- * The port is disconnected, which means the core is
- * either in device mode or it soon will be. Just
- * return 0's for the remainder of the port status
+ * Just return 0's for the remainder of the port status
* since the port register can't be read if the core
* is in device mode.
*/
@@ -3620,13 +3618,11 @@ static int dwc2_hcd_hub_control(struct dwc2_hsotg *hsotg, u16 typereq,
if (wvalue != USB_PORT_FEAT_TEST && (!windex || windex > 1))
goto error;
- if (!hsotg->flags.b.port_connect_status) {
+ if (dwc2_is_device_mode(hsotg)) {
/*
- * The port is disconnected, which means the core is
- * either in device mode or it soon will be. Just
- * return without doing anything since the port
- * register can't be written if the core is in device
- * mode.
+ * Just return 0's for the remainder of the port status
+ * since the port register can't be read if the core
+ * is in device mode.
*/
break;
}
@@ -4349,7 +4345,7 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd)
if (hsotg->bus_suspended)
goto skip_power_saving;
- if (hsotg->flags.b.port_connect_status == 0)
+ if (!(dwc2_read_hprt0(hsotg) & HPRT0_CONNSTS))
goto skip_power_saving;
switch (hsotg->params.power_down) {
@@ -4431,6 +4427,7 @@ static int _dwc2_hcd_resume(struct usb_hcd *hcd)
* Power Down mode.
*/
if (hprt0 & HPRT0_CONNSTS) {
+ set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
hsotg->lx_state = DWC2_L0;
goto unlock;
}
diff --git a/drivers/usb/dwc2/platform.c b/drivers/usb/dwc2/platform.c
index c1b7209b9483..91c80a92d9b8 100644
--- a/drivers/usb/dwc2/platform.c
+++ b/drivers/usb/dwc2/platform.c
@@ -756,7 +756,7 @@ static struct platform_driver dwc2_platform_driver = {
.pm = &dwc2_dev_pm_ops,
},
.probe = dwc2_driver_probe,
- .remove_new = dwc2_driver_remove,
+ .remove = dwc2_driver_remove,
.shutdown = dwc2_driver_shutdown,
};
diff --git a/drivers/usb/dwc3/Kconfig b/drivers/usb/dwc3/Kconfig
index 31078f3d41b8..310d182e10b5 100644
--- a/drivers/usb/dwc3/Kconfig
+++ b/drivers/usb/dwc3/Kconfig
@@ -23,7 +23,7 @@ config USB_DWC3_ULPI
controller.
choice
- bool "DWC3 Mode Selection"
+ prompt "DWC3 Mode Selection"
default USB_DWC3_DUAL_ROLE if (USB && USB_GADGET)
default USB_DWC3_HOST if (USB && !USB_GADGET)
default USB_DWC3_GADGET if (!USB && USB_GADGET)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index 98114c2827c0..f219c82e9619 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -1409,7 +1409,7 @@ static int dwc3_core_init(struct dwc3 *dwc)
/*
* When configured in HOST mode, after issuing U3/L2 exit controller
- * fails to send proper CRC checksum in CRC5 feild. Because of this
+ * fails to send proper CRC checksum in CRC5 field. Because of this
* behaviour Transaction Error is generated, resulting in reset and
* re-enumeration of usb device attached. All the termsel, xcvrsel,
* opmode becomes 0 during end of resume. Enabling bit 10 of GUCTL1
@@ -1470,9 +1470,13 @@ static int dwc3_core_init(struct dwc3 *dwc)
if (hw_mode != DWC3_GHWPARAMS0_MODE_GADGET &&
(DWC3_IP_IS(DWC31)) &&
dwc->maximum_speed == USB_SPEED_SUPER) {
- reg = dwc3_readl(dwc->regs, DWC3_LLUCTL);
- reg |= DWC3_LLUCTL_FORCE_GEN1;
- dwc3_writel(dwc->regs, DWC3_LLUCTL, reg);
+ int i;
+
+ for (i = 0; i < dwc->num_usb3_ports; i++) {
+ reg = dwc3_readl(dwc->regs, DWC3_LLUCTL(i));
+ reg |= DWC3_LLUCTL_FORCE_GEN1;
+ dwc3_writel(dwc->regs, DWC3_LLUCTL(i), reg);
+ }
}
return 0;
@@ -1941,7 +1945,7 @@ static struct extcon_dev *dwc3_get_extcon(struct dwc3 *dwc)
struct extcon_dev *edev = NULL;
const char *name;
- if (device_property_read_bool(dev, "extcon"))
+ if (device_property_present(dev, "extcon"))
return extcon_get_edev_by_phandle(dev, 0);
/*
@@ -2651,7 +2655,7 @@ MODULE_DEVICE_TABLE(acpi, dwc3_acpi_match);
static struct platform_driver dwc3_driver = {
.probe = dwc3_probe,
- .remove_new = dwc3_remove,
+ .remove = dwc3_remove,
.driver = {
.name = "dwc3",
.of_match_table = of_match_ptr(of_dwc3_match),
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index eab81dfdcc35..ee73789326bc 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -81,7 +81,7 @@
#define DWC3_GSNPSREV_MASK 0xffff
#define DWC3_GSNPS_ID(p) (((p) & DWC3_GSNPSID_MASK) >> 16)
-/* DWC3 registers memory space boundries */
+/* DWC3 registers memory space boundaries */
#define DWC3_XHCI_REGS_START 0x0
#define DWC3_XHCI_REGS_END 0x7fff
#define DWC3_GLOBALS_REGS_START 0xc100
@@ -179,7 +179,7 @@
#define DWC3_OEVTEN 0xcc0C
#define DWC3_OSTS 0xcc10
-#define DWC3_LLUCTL 0xd024
+#define DWC3_LLUCTL(n) (0xd024 + ((n) * 0x80))
/* Bit fields */
@@ -915,6 +915,7 @@ struct dwc3_hwparams {
#define DWC3_MODE(n) ((n) & 0x7)
/* HWPARAMS1 */
+#define DWC3_SPRAM_TYPE(n) (((n) >> 23) & 1)
#define DWC3_NUM_INT(n) (((n) & (0x3f << 15)) >> 15)
/* HWPARAMS3 */
@@ -925,6 +926,9 @@ struct dwc3_hwparams {
#define DWC3_NUM_IN_EPS(p) (((p)->hwparams3 & \
(DWC3_NUM_IN_EPS_MASK)) >> 18)
+/* HWPARAMS6 */
+#define DWC3_RAM0_DEPTH(n) (((n) & (0xffff0000)) >> 16)
+
/* HWPARAMS7 */
#define DWC3_RAM1_DEPTH(n) ((n) & 0xffff)
@@ -937,18 +941,14 @@ struct dwc3_hwparams {
* @request: struct usb_request to be transferred
* @list: a list_head used for request queueing
* @dep: struct dwc3_ep owning this request
- * @sg: pointer to first incomplete sg
* @start_sg: pointer to the sg which should be queued next
* @num_pending_sgs: counter to pending sgs
- * @num_queued_sgs: counter to the number of sgs which already got queued
* @remaining: amount of data remaining
* @status: internal dwc3 request status tracking
* @epnum: endpoint number to which this request refers
* @trb: pointer to struct dwc3_trb
* @trb_dma: DMA address of @trb
* @num_trbs: number of TRBs used by this request
- * @needs_extra_trb: true when request needs one extra TRB (either due to ZLP
- * or unaligned OUT)
* @direction: IN or OUT direction flag
* @mapped: true when request has been dma-mapped
*/
@@ -960,7 +960,6 @@ struct dwc3_request {
struct scatterlist *start_sg;
unsigned int num_pending_sgs;
- unsigned int num_queued_sgs;
unsigned int remaining;
unsigned int status;
@@ -978,7 +977,6 @@ struct dwc3_request {
unsigned int num_trbs;
- unsigned int needs_extra_trb:1;
unsigned int direction:1;
unsigned int mapped:1;
};
diff --git a/drivers/usb/dwc3/dwc3-am62.c b/drivers/usb/dwc3/dwc3-am62.c
index fad151e78fd6..5e3d1741701f 100644
--- a/drivers/usb/dwc3/dwc3-am62.c
+++ b/drivers/usb/dwc3/dwc3-am62.c
@@ -377,7 +377,7 @@ MODULE_DEVICE_TABLE(of, dwc3_ti_of_match);
static struct platform_driver dwc3_ti_driver = {
.probe = dwc3_ti_probe,
- .remove_new = dwc3_ti_remove,
+ .remove = dwc3_ti_remove,
.driver = {
.name = "dwc3-am62",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c
index 9a6e988d165a..f5d963fae9e0 100644
--- a/drivers/usb/dwc3/dwc3-exynos.c
+++ b/drivers/usb/dwc3/dwc3-exynos.c
@@ -243,7 +243,7 @@ static DEFINE_SIMPLE_DEV_PM_OPS(dwc3_exynos_dev_pm_ops,
static struct platform_driver dwc3_exynos_driver = {
.probe = dwc3_exynos_probe,
- .remove_new = dwc3_exynos_remove,
+ .remove = dwc3_exynos_remove,
.driver = {
.name = "exynos-dwc3",
.of_match_table = exynos_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-imx8mp.c b/drivers/usb/dwc3/dwc3-imx8mp.c
index 64c0cd1995aa..3edc5aca76f9 100644
--- a/drivers/usb/dwc3/dwc3-imx8mp.c
+++ b/drivers/usb/dwc3/dwc3-imx8mp.c
@@ -129,6 +129,16 @@ static void dwc3_imx8mp_wakeup_disable(struct dwc3_imx8mp *dwc3_imx)
writel(val, dwc3_imx->hsio_blk_base + USB_WAKEUP_CTRL);
}
+static const struct property_entry dwc3_imx8mp_properties[] = {
+ PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk"),
+ PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk"),
+ {},
+};
+
+static const struct software_node dwc3_imx8mp_swnode = {
+ .properties = dwc3_imx8mp_properties,
+};
+
static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
{
struct dwc3_imx8mp *dwc3_imx = _dwc3_imx;
@@ -148,17 +158,6 @@ static irqreturn_t dwc3_imx8mp_interrupt(int irq, void *_dwc3_imx)
return IRQ_HANDLED;
}
-static int dwc3_imx8mp_set_software_node(struct device *dev)
-{
- struct property_entry props[3] = { 0 };
- int prop_idx = 0;
-
- props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-missing-cas-quirk");
- props[prop_idx++] = PROPERTY_ENTRY_BOOL("xhci-skip-phy-init-quirk");
-
- return device_create_managed_software_node(dev, props, NULL);
-}
-
static int dwc3_imx8mp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -221,17 +220,17 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
if (err < 0)
goto disable_rpm;
- err = dwc3_imx8mp_set_software_node(dev);
+ err = device_add_software_node(dev, &dwc3_imx8mp_swnode);
if (err) {
err = -ENODEV;
- dev_err(dev, "failed to create software node\n");
+ dev_err(dev, "failed to add software node\n");
goto disable_rpm;
}
err = of_platform_populate(node, NULL, NULL, dev);
if (err) {
dev_err(&pdev->dev, "failed to create dwc3 core\n");
- goto disable_rpm;
+ goto remove_swnode;
}
dwc3_imx->dwc3 = of_find_device_by_node(dwc3_np);
@@ -255,6 +254,8 @@ static int dwc3_imx8mp_probe(struct platform_device *pdev)
depopulate:
of_platform_depopulate(dev);
+remove_swnode:
+ device_remove_software_node(dev);
disable_rpm:
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
@@ -268,6 +269,7 @@ static void dwc3_imx8mp_remove(struct platform_device *pdev)
pm_runtime_get_sync(dev);
of_platform_depopulate(dev);
+ device_remove_software_node(dev);
pm_runtime_disable(dev);
pm_runtime_put_noidle(dev);
@@ -400,7 +402,7 @@ MODULE_DEVICE_TABLE(of, dwc3_imx8mp_of_match);
static struct platform_driver dwc3_imx8mp_driver = {
.probe = dwc3_imx8mp_probe,
- .remove_new = dwc3_imx8mp_remove,
+ .remove = dwc3_imx8mp_remove,
.driver = {
.name = "imx8mp-dwc3",
.pm = pm_ptr(&dwc3_imx8mp_dev_pm_ops),
diff --git a/drivers/usb/dwc3/dwc3-keystone.c b/drivers/usb/dwc3/dwc3-keystone.c
index 8899348b6276..7ee1610162b9 100644
--- a/drivers/usb/dwc3/dwc3-keystone.c
+++ b/drivers/usb/dwc3/dwc3-keystone.c
@@ -208,7 +208,7 @@ MODULE_DEVICE_TABLE(of, kdwc3_of_match);
static struct platform_driver kdwc3_driver = {
.probe = kdwc3_probe,
- .remove_new = kdwc3_remove,
+ .remove = kdwc3_remove,
.driver = {
.name = "keystone-dwc3",
.of_match_table = kdwc3_of_match,
diff --git a/drivers/usb/dwc3/dwc3-meson-g12a.c b/drivers/usb/dwc3/dwc3-meson-g12a.c
index 2c07c038b584..7d80bf7b18b0 100644
--- a/drivers/usb/dwc3/dwc3-meson-g12a.c
+++ b/drivers/usb/dwc3/dwc3-meson-g12a.c
@@ -968,7 +968,7 @@ MODULE_DEVICE_TABLE(of, dwc3_meson_g12a_match);
static struct platform_driver dwc3_meson_g12a_driver = {
.probe = dwc3_meson_g12a_probe,
- .remove_new = dwc3_meson_g12a_remove,
+ .remove = dwc3_meson_g12a_remove,
.driver = {
.name = "dwc3-meson-g12a",
.of_match_table = dwc3_meson_g12a_match,
diff --git a/drivers/usb/dwc3/dwc3-octeon.c b/drivers/usb/dwc3/dwc3-octeon.c
index 1a3b205367fd..42bfc14ae0c4 100644
--- a/drivers/usb/dwc3/dwc3-octeon.c
+++ b/drivers/usb/dwc3/dwc3-octeon.c
@@ -520,7 +520,7 @@ MODULE_DEVICE_TABLE(of, dwc3_octeon_of_match);
static struct platform_driver dwc3_octeon_driver = {
.probe = dwc3_octeon_probe,
- .remove_new = dwc3_octeon_remove,
+ .remove = dwc3_octeon_remove,
.driver = {
.name = "dwc3-octeon",
.of_match_table = dwc3_octeon_of_match,
diff --git a/drivers/usb/dwc3/dwc3-of-simple.c b/drivers/usb/dwc3/dwc3-of-simple.c
index be7be00ecb34..a4954a21be93 100644
--- a/drivers/usb/dwc3/dwc3-of-simple.c
+++ b/drivers/usb/dwc3/dwc3-of-simple.c
@@ -180,7 +180,7 @@ MODULE_DEVICE_TABLE(of, of_dwc3_simple_match);
static struct platform_driver dwc3_of_simple_driver = {
.probe = dwc3_of_simple_probe,
- .remove_new = dwc3_of_simple_remove,
+ .remove = dwc3_of_simple_remove,
.shutdown = dwc3_of_simple_shutdown,
.driver = {
.name = "dwc3-of-simple",
diff --git a/drivers/usb/dwc3/dwc3-omap.c b/drivers/usb/dwc3/dwc3-omap.c
index 2a11fc0ee84f..b261c46124c6 100644
--- a/drivers/usb/dwc3/dwc3-omap.c
+++ b/drivers/usb/dwc3/dwc3-omap.c
@@ -416,7 +416,7 @@ static int dwc3_omap_extcon_register(struct dwc3_omap *omap)
struct device_node *node = omap->dev->of_node;
struct extcon_dev *edev;
- if (of_property_read_bool(node, "extcon")) {
+ if (of_property_present(node, "extcon")) {
edev = extcon_get_edev_by_phandle(omap->dev, 0);
if (IS_ERR(edev)) {
dev_vdbg(omap->dev, "couldn't get extcon device\n");
@@ -611,7 +611,7 @@ static const struct dev_pm_ops dwc3_omap_dev_pm_ops = {
static struct platform_driver dwc3_omap_driver = {
.probe = dwc3_omap_probe,
- .remove_new = dwc3_omap_remove,
+ .remove = dwc3_omap_remove,
.driver = {
.name = "omap-dwc3",
.of_match_table = of_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c
index c1d4b52f25b0..58683bb672e9 100644
--- a/drivers/usb/dwc3/dwc3-qcom.c
+++ b/drivers/usb/dwc3/dwc3-qcom.c
@@ -161,7 +161,7 @@ static int dwc3_qcom_register_extcon(struct dwc3_qcom *qcom)
struct extcon_dev *host_edev;
int ret;
- if (!of_property_read_bool(dev->of_node, "extcon"))
+ if (!of_property_present(dev->of_node, "extcon"))
return 0;
qcom->edev = extcon_get_edev_by_phandle(dev, 0);
@@ -921,7 +921,7 @@ MODULE_DEVICE_TABLE(of, dwc3_qcom_of_match);
static struct platform_driver dwc3_qcom_driver = {
.probe = dwc3_qcom_probe,
- .remove_new = dwc3_qcom_remove,
+ .remove = dwc3_qcom_remove,
.driver = {
.name = "dwc3-qcom",
.pm = &dwc3_qcom_dev_pm_ops,
diff --git a/drivers/usb/dwc3/dwc3-rtk.c b/drivers/usb/dwc3/dwc3-rtk.c
index e9c8b032c72c..56c53e0c0257 100644
--- a/drivers/usb/dwc3/dwc3-rtk.c
+++ b/drivers/usb/dwc3/dwc3-rtk.c
@@ -441,7 +441,7 @@ static const struct dev_pm_ops dwc3_rtk_dev_pm_ops = {
static struct platform_driver dwc3_rtk_driver = {
.probe = dwc3_rtk_probe,
- .remove_new = dwc3_rtk_remove,
+ .remove = dwc3_rtk_remove,
.driver = {
.name = "rtk-dwc3",
.of_match_table = rtk_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-st.c b/drivers/usb/dwc3/dwc3-st.c
index 2841021f3557..e16c3237180e 100644
--- a/drivers/usb/dwc3/dwc3-st.c
+++ b/drivers/usb/dwc3/dwc3-st.c
@@ -356,7 +356,7 @@ MODULE_DEVICE_TABLE(of, st_dwc3_match);
static struct platform_driver st_dwc3_driver = {
.probe = st_dwc3_probe,
- .remove_new = st_dwc3_remove,
+ .remove = st_dwc3_remove,
.driver = {
.name = "usb-st-dwc3",
.of_match_table = st_dwc3_match,
diff --git a/drivers/usb/dwc3/dwc3-xilinx.c b/drivers/usb/dwc3/dwc3-xilinx.c
index b5e5be424ce9..a33a42ba0249 100644
--- a/drivers/usb/dwc3/dwc3-xilinx.c
+++ b/drivers/usb/dwc3/dwc3-xilinx.c
@@ -121,8 +121,11 @@ static int dwc3_xlnx_init_zynqmp(struct dwc3_xlnx *priv_data)
* in use but the usb3-phy entry is missing from the device tree.
* Therefore, skip these operations in this case.
*/
- if (!priv_data->usb3_phy)
+ if (!priv_data->usb3_phy) {
+ /* Deselect the PIPE Clock Select bit in FPD PIPE Clock register */
+ writel(PIPE_CLK_DESELECT, priv_data->regs + XLNX_USB_FPD_PIPE_CLK);
goto skip_usb3_phy;
+ }
crst = devm_reset_control_get_exclusive(dev, "usb_crst");
if (IS_ERR(crst)) {
@@ -420,7 +423,7 @@ static const struct dev_pm_ops dwc3_xlnx_dev_pm_ops = {
static struct platform_driver dwc3_xlnx_driver = {
.probe = dwc3_xlnx_probe,
- .remove_new = dwc3_xlnx_remove,
+ .remove = dwc3_xlnx_remove,
.driver = {
.name = "dwc3-xilinx",
.of_match_table = dwc3_xlnx_of_match,
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index c9533a99e47c..666ac432f52d 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -145,7 +145,7 @@ static int __dwc3_gadget_ep0_queue(struct dwc3_ep *dep,
* Unfortunately we have uncovered a limitation wrt the Data Phase.
*
* Section 9.4 says we can wait for the XferNotReady(DATA) event to
- * come before issueing Start Transfer command, but if we do, we will
+ * come before issuing Start Transfer command, but if we do, we will
* miss situations where the host starts another SETUP phase instead of
* the DATA phase. Such cases happen at least on TD.7.6 of the Link
* Layer Compliance Suite.
@@ -232,7 +232,7 @@ void dwc3_ep0_stall_and_restart(struct dwc3 *dwc)
/* stall is always issued on EP0 */
dep = dwc->eps[0];
__dwc3_gadget_ep_set_halt(dep, 1, false);
- dep->flags &= DWC3_EP_RESOURCE_ALLOCATED;
+ dep->flags &= DWC3_EP_RESOURCE_ALLOCATED | DWC3_EP_TRANSFER_STARTED;
dep->flags |= DWC3_EP_ENABLED;
dwc->delayed_status = false;
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 4959c26d3b71..83dc7304d701 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -197,7 +197,6 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
list_del(&req->list);
req->remaining = 0;
- req->needs_extra_trb = false;
req->num_trbs = 0;
if (req->request.status == -EINPROGRESS)
@@ -688,6 +687,44 @@ static int dwc3_gadget_calc_tx_fifo_size(struct dwc3 *dwc, int mult)
}
/**
+ * dwc3_gadget_calc_ram_depth - calculates the ram depth for txfifo
+ * @dwc: pointer to the DWC3 context
+ */
+static int dwc3_gadget_calc_ram_depth(struct dwc3 *dwc)
+{
+ int ram_depth;
+ int fifo_0_start;
+ bool is_single_port_ram;
+
+ /* Check supporting RAM type by HW */
+ is_single_port_ram = DWC3_SPRAM_TYPE(dwc->hwparams.hwparams1);
+
+ /*
+ * If a single port RAM is utilized, then allocate TxFIFOs from
+ * RAM0. otherwise, allocate them from RAM1.
+ */
+ ram_depth = is_single_port_ram ? DWC3_RAM0_DEPTH(dwc->hwparams.hwparams6) :
+ DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
+
+ /*
+ * In a single port RAM configuration, the available RAM is shared
+ * between the RX and TX FIFOs. This means that the txfifo can begin
+ * at a non-zero address.
+ */
+ if (is_single_port_ram) {
+ u32 reg;
+
+ /* Check if TXFIFOs start at non-zero addr */
+ reg = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
+ fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(reg);
+
+ ram_depth -= (fifo_0_start >> 16);
+ }
+
+ return ram_depth;
+}
+
+/**
* dwc3_gadget_clear_tx_fifos - Clears txfifo allocation
* @dwc: pointer to the DWC3 context
*
@@ -753,7 +790,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
{
struct dwc3 *dwc = dep->dwc;
int fifo_0_start;
- int ram1_depth;
+ int ram_depth;
int fifo_size;
int min_depth;
int num_in_ep;
@@ -773,17 +810,32 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
if (dep->flags & DWC3_EP_TXFIFO_RESIZED)
return 0;
- ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
+ ram_depth = dwc3_gadget_calc_ram_depth(dwc);
- if ((dep->endpoint.maxburst > 1 &&
- usb_endpoint_xfer_bulk(dep->endpoint.desc)) ||
- usb_endpoint_xfer_isoc(dep->endpoint.desc))
- num_fifos = 3;
-
- if (dep->endpoint.maxburst > 6 &&
- (usb_endpoint_xfer_bulk(dep->endpoint.desc) ||
- usb_endpoint_xfer_isoc(dep->endpoint.desc)) && DWC3_IP_IS(DWC31))
- num_fifos = dwc->tx_fifo_resize_max_num;
+ switch (dwc->gadget->speed) {
+ case USB_SPEED_SUPER_PLUS:
+ case USB_SPEED_SUPER:
+ if (usb_endpoint_xfer_bulk(dep->endpoint.desc) ||
+ usb_endpoint_xfer_isoc(dep->endpoint.desc))
+ num_fifos = min_t(unsigned int,
+ dep->endpoint.maxburst,
+ dwc->tx_fifo_resize_max_num);
+ break;
+ case USB_SPEED_HIGH:
+ if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+ num_fifos = min_t(unsigned int,
+ usb_endpoint_maxp_mult(dep->endpoint.desc) + 1,
+ dwc->tx_fifo_resize_max_num);
+ break;
+ }
+ fallthrough;
+ case USB_SPEED_FULL:
+ if (usb_endpoint_xfer_bulk(dep->endpoint.desc))
+ num_fifos = 2;
+ break;
+ default:
+ break;
+ }
/* FIFO size for a single buffer */
fifo = dwc3_gadget_calc_tx_fifo_size(dwc, 1);
@@ -794,7 +846,7 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
/* Reserve at least one FIFO for the number of IN EPs */
min_depth = num_in_ep * (fifo + 1);
- remaining = ram1_depth - min_depth - dwc->last_fifo_depth;
+ remaining = ram_depth - min_depth - dwc->last_fifo_depth;
remaining = max_t(int, 0, remaining);
/*
* We've already reserved 1 FIFO per EP, so check what we can fit in
@@ -820,9 +872,9 @@ static int dwc3_gadget_resize_tx_fifos(struct dwc3_ep *dep)
dwc->last_fifo_depth += DWC31_GTXFIFOSIZ_TXFDEP(fifo_size);
/* Check fifo size allocation doesn't exceed available RAM size. */
- if (dwc->last_fifo_depth >= ram1_depth) {
+ if (dwc->last_fifo_depth >= ram_depth) {
dev_err(dwc->dev, "Fifosize(%d) > RAM size(%d) %s depth:%d\n",
- dwc->last_fifo_depth, ram1_depth,
+ dwc->last_fifo_depth, ram_depth,
dep->endpoint.name, fifo_size);
if (DWC3_IP_IS(DWC3))
fifo_size = DWC3_GTXFIFOSIZ_TXFDEP(fifo_size);
@@ -1177,11 +1229,14 @@ static u32 dwc3_calc_trbs_left(struct dwc3_ep *dep)
* pending to be processed by the driver.
*/
if (dep->trb_enqueue == dep->trb_dequeue) {
+ struct dwc3_request *req;
+
/*
- * If there is any request remained in the started_list at
- * this point, that means there is no TRB available.
+ * If there is any request remained in the started_list with
+ * active TRBs at this point, then there is no TRB available.
*/
- if (!list_empty(&dep->started_list))
+ req = next_request(&dep->started_list);
+ if (req && req->num_trbs)
return 0;
return DWC3_TRB_NUM - 1;
@@ -1384,6 +1439,7 @@ static int dwc3_prepare_last_sg(struct dwc3_ep *dep,
unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
unsigned int rem = req->request.length % maxp;
unsigned int num_trbs = 1;
+ bool needs_extra_trb;
if (dwc3_needs_extra_trb(dep, req))
num_trbs++;
@@ -1391,15 +1447,15 @@ static int dwc3_prepare_last_sg(struct dwc3_ep *dep,
if (dwc3_calc_trbs_left(dep) < num_trbs)
return 0;
- req->needs_extra_trb = num_trbs > 1;
+ needs_extra_trb = num_trbs > 1;
/* Prepare a normal TRB */
if (req->direction || req->request.length)
dwc3_prepare_one_trb(dep, req, entry_length,
- req->needs_extra_trb, node, false, false);
+ needs_extra_trb, node, false, false);
/* Prepare extra TRBs for ZLP and MPS OUT transfer alignment */
- if ((!req->direction && !req->request.length) || req->needs_extra_trb)
+ if ((!req->direction && !req->request.length) || needs_extra_trb)
dwc3_prepare_one_trb(dep, req,
req->direction ? 0 : maxp - rem,
false, 1, true, false);
@@ -1414,8 +1470,8 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
struct scatterlist *s;
int i;
unsigned int length = req->request.length;
- unsigned int remaining = req->request.num_mapped_sgs
- - req->num_queued_sgs;
+ unsigned int remaining = req->num_pending_sgs;
+ unsigned int num_queued_sgs = req->request.num_mapped_sgs - remaining;
unsigned int num_trbs = req->num_trbs;
bool needs_extra_trb = dwc3_needs_extra_trb(dep, req);
@@ -1423,7 +1479,7 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
* If we resume preparing the request, then get the remaining length of
* the request and resume where we left off.
*/
- for_each_sg(req->request.sg, s, req->num_queued_sgs, i)
+ for_each_sg(req->request.sg, s, num_queued_sgs, i)
length -= sg_dma_len(s);
for_each_sg(sg, s, remaining, i) {
@@ -1488,7 +1544,6 @@ static int dwc3_prepare_trbs_sg(struct dwc3_ep *dep,
if (!last_sg)
req->start_sg = sg_next(s);
- req->num_queued_sgs++;
req->num_pending_sgs--;
/*
@@ -1569,9 +1624,7 @@ static int dwc3_prepare_trbs(struct dwc3_ep *dep)
if (ret)
return ret;
- req->sg = req->request.sg;
- req->start_sg = req->sg;
- req->num_queued_sgs = 0;
+ req->start_sg = req->request.sg;
req->num_pending_sgs = req->request.num_mapped_sgs;
if (req->num_pending_sgs > 0) {
@@ -3075,7 +3128,7 @@ static int dwc3_gadget_check_config(struct usb_gadget *g)
struct dwc3 *dwc = gadget_to_dwc(g);
struct usb_ep *ep;
int fifo_size = 0;
- int ram1_depth;
+ int ram_depth;
int ep_num = 0;
if (!dwc->do_fifo_resize)
@@ -3098,8 +3151,8 @@ static int dwc3_gadget_check_config(struct usb_gadget *g)
fifo_size += dwc->max_cfg_eps;
/* Check if we can fit a single fifo per endpoint */
- ram1_depth = DWC3_RAM1_DEPTH(dwc->hwparams.hwparams7);
- if (fifo_size > ram1_depth)
+ ram_depth = dwc3_gadget_calc_ram_depth(dwc);
+ if (fifo_size > ram_depth)
return -ENOMEM;
return 0;
@@ -3416,20 +3469,16 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,
int status)
{
struct dwc3_trb *trb;
- struct scatterlist *sg = req->sg;
- struct scatterlist *s;
- unsigned int num_queued = req->num_queued_sgs;
+ unsigned int num_completed_trbs = req->num_trbs;
unsigned int i;
int ret = 0;
- for_each_sg(sg, s, num_queued, i) {
+ for (i = 0; i < num_completed_trbs; i++) {
trb = &dep->trb_pool[dep->trb_dequeue];
- req->sg = sg_next(s);
- req->num_queued_sgs--;
-
ret = dwc3_gadget_ep_reclaim_completed_trb(dep, req,
- trb, event, status, true);
+ trb, event, status,
+ !!(trb->ctrl & DWC3_TRB_CTRL_CHN));
if (ret)
break;
}
@@ -3437,19 +3486,9 @@ static int dwc3_gadget_ep_reclaim_trb_sg(struct dwc3_ep *dep,
return ret;
}
-static int dwc3_gadget_ep_reclaim_trb_linear(struct dwc3_ep *dep,
- struct dwc3_request *req, const struct dwc3_event_depevt *event,
- int status)
-{
- struct dwc3_trb *trb = &dep->trb_pool[dep->trb_dequeue];
-
- return dwc3_gadget_ep_reclaim_completed_trb(dep, req, trb,
- event, status, false);
-}
-
static bool dwc3_gadget_ep_request_completed(struct dwc3_request *req)
{
- return req->num_pending_sgs == 0 && req->num_queued_sgs == 0;
+ return req->num_pending_sgs == 0 && req->num_trbs == 0;
}
static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
@@ -3459,24 +3498,13 @@ static int dwc3_gadget_ep_cleanup_completed_request(struct dwc3_ep *dep,
int request_status;
int ret;
- if (req->request.num_mapped_sgs)
- ret = dwc3_gadget_ep_reclaim_trb_sg(dep, req, event,
- status);
- else
- ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
- status);
+ ret = dwc3_gadget_ep_reclaim_trb_sg(dep, req, event, status);
req->request.actual = req->request.length - req->remaining;
if (!dwc3_gadget_ep_request_completed(req))
goto out;
- if (req->needs_extra_trb) {
- ret = dwc3_gadget_ep_reclaim_trb_linear(dep, req, event,
- status);
- req->needs_extra_trb = false;
- }
-
/*
* The event status only reflects the status of the TRB with IOC set.
* For the requests that don't set interrupt on completion, the driver
diff --git a/drivers/usb/dwc3/host.c b/drivers/usb/dwc3/host.c
index e0533cee6870..b48e108fc8fe 100644
--- a/drivers/usb/dwc3/host.c
+++ b/drivers/usb/dwc3/host.c
@@ -35,7 +35,7 @@ static void dwc3_power_off_all_roothub_ports(struct dwc3 *dwc)
u32 reg;
int i;
- /* xhci regs is not mapped yet, do it temperary here */
+ /* xhci regs are not mapped yet, do it temporarily here */
if (dwc->xhci_resources[0].start) {
xhci_regs = ioremap(dwc->xhci_resources[0].start, DWC3_XHCI_REGS_END);
if (!xhci_regs) {
diff --git a/drivers/usb/fotg210/fotg210-core.c b/drivers/usb/fotg210/fotg210-core.c
index 0655afe7f977..49f25a70b32e 100644
--- a/drivers/usb/fotg210/fotg210-core.c
+++ b/drivers/usb/fotg210/fotg210-core.c
@@ -195,7 +195,7 @@ static struct platform_driver fotg210_driver = {
.of_match_table = of_match_ptr(fotg210_of_match),
},
.probe = fotg210_probe,
- .remove_new = fotg210_remove,
+ .remove = fotg210_remove,
};
static int __init fotg210_init(void)
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index f25dd2cb5d03..bdda8c74602d 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1844,7 +1844,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
cdev->desc.bcdUSB = cpu_to_le16(0x0200);
}
- value = min(w_length, (u16) sizeof cdev->desc);
+ value = min_t(u16, w_length, sizeof(cdev->desc));
memcpy(req->buf, &cdev->desc, value);
break;
case USB_DT_DEVICE_QUALIFIER:
@@ -1863,19 +1863,19 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
case USB_DT_CONFIG:
value = config_desc(cdev, w_value);
if (value >= 0)
- value = min(w_length, (u16) value);
+ value = min_t(u16, w_length, value);
break;
case USB_DT_STRING:
value = get_string(cdev, req->buf,
w_index, w_value & 0xff);
if (value >= 0)
- value = min(w_length, (u16) value);
+ value = min_t(u16, w_length, value);
break;
case USB_DT_BOS:
if (gadget_is_superspeed(gadget) ||
gadget->lpm_capable || cdev->use_webusb) {
value = bos_desc(cdev);
- value = min(w_length, (u16) value);
+ value = min_t(u16, w_length, value);
}
break;
case USB_DT_OTG:
@@ -1930,7 +1930,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
*(u8 *)req->buf = cdev->config->bConfigurationValue;
else
*(u8 *)req->buf = 0;
- value = min(w_length, (u16) 1);
+ value = min_t(u16, w_length, 1);
break;
/* function drivers must handle get/set altsetting */
@@ -1976,7 +1976,7 @@ composite_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
if (value < 0)
break;
*((u8 *)req->buf) = value;
- value = min(w_length, (u16) 1);
+ value = min_t(u16, w_length, 1);
break;
case USB_REQ_GET_STATUS:
if (gadget_is_otg(gadget) && gadget->hnp_polling_support &&
@@ -2111,8 +2111,20 @@ unknown:
memset(buf, 0, w_length);
buf[5] = 0x01;
switch (ctrl->bRequestType & USB_RECIP_MASK) {
+ /*
+ * The Microsoft CompatID OS Descriptor Spec(w_index = 0x4) and
+ * Extended Prop OS Desc Spec(w_index = 0x5) state that the
+ * HighByte of wValue is the InterfaceNumber and the LowByte is
+ * the PageNumber. This high/low byte ordering is incorrectly
+ * documented in the Spec. USB analyzer output on the below
+ * request packets show the high/low byte inverted i.e LowByte
+ * is the InterfaceNumber and the HighByte is the PageNumber.
+ * Since we dont support >64KB CompatID/ExtendedProp descriptors,
+ * PageNumber is set to 0. Hence verify that the HighByte is 0
+ * for below two cases.
+ */
case USB_RECIP_DEVICE:
- if (w_index != 0x4 || (w_value & 0xff))
+ if (w_index != 0x4 || (w_value >> 8))
break;
buf[6] = w_index;
/* Number of ext compat interfaces */
@@ -2128,9 +2140,9 @@ unknown:
}
break;
case USB_RECIP_INTERFACE:
- if (w_index != 0x5 || (w_value & 0xff))
+ if (w_index != 0x5 || (w_value >> 8))
break;
- interface = w_value >> 8;
+ interface = w_value & 0xFF;
if (interface >= MAX_CONFIG_INTERFACES ||
!os_desc_cfg->interface[interface])
break;
diff --git a/drivers/usb/gadget/config.c b/drivers/usb/gadget/config.c
index b1f625245713..95f144a54ed9 100644
--- a/drivers/usb/gadget/config.c
+++ b/drivers/usb/gadget/config.c
@@ -57,11 +57,11 @@ EXPORT_SYMBOL_GPL(usb_descriptor_fillbuf);
* usb_gadget_config_buf - builts a complete configuration descriptor
* @config: Header for the descriptor, including characteristics such
* as power requirements and number of interfaces.
- * @desc: Null-terminated vector of pointers to the descriptors (interface,
- * endpoint, etc) defining all functions in this device configuration.
* @buf: Buffer for the resulting configuration descriptor.
* @length: Length of buffer. If this is not big enough to hold the
* entire configuration descriptor, an error code will be returned.
+ * @desc: Null-terminated vector of pointers to the descriptors (interface,
+ * endpoint, etc) defining all functions in this device configuration.
*
* This copies descriptors into the response buffer, building a descriptor
* for that configuration. It returns the buffer length or a negative
diff --git a/drivers/usb/gadget/configfs.c b/drivers/usb/gadget/configfs.c
index c82a6a0fba93..6499a88d346c 100644
--- a/drivers/usb/gadget/configfs.c
+++ b/drivers/usb/gadget/configfs.c
@@ -1184,7 +1184,7 @@ static ssize_t os_desc_qw_sign_store(struct config_item *item, const char *page,
struct gadget_info *gi = os_desc_item_to_gadget_info(item);
int res, l;
- l = min((int)len, OS_STRING_QW_SIGN_LEN >> 1);
+ l = min_t(int, len, OS_STRING_QW_SIGN_LEN >> 1);
if (page[l - 1] == '\n')
--l;
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
index 87917a7d4a9b..7ce1637276f0 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -41,6 +41,10 @@ obj-$(CONFIG_USB_F_UAC1_LEGACY) += usb_f_uac1_legacy.o
usb_f_uac2-y := f_uac2.o
obj-$(CONFIG_USB_F_UAC2) += usb_f_uac2.o
usb_f_uvc-y := f_uvc.o uvc_queue.o uvc_v4l2.o uvc_video.o uvc_configfs.o
+ifneq ($(CONFIG_TRACING),)
+ CFLAGS_uvc_trace.o := -I$(src)
+ usb_f_uvc-y += uvc_trace.o
+endif
obj-$(CONFIG_USB_F_UVC) += usb_f_uvc.o
usb_f_midi-y := f_midi.o
obj-$(CONFIG_USB_F_MIDI) += usb_f_midi.o
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 2920f8000bbd..ad79eb0f729b 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -49,7 +49,7 @@
#define DMABUF_ENQUEUE_TIMEOUT_MS 5000
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
/* Reference counter handling */
static void ffs_data_get(struct ffs_data *ffs);
@@ -456,7 +456,7 @@ static ssize_t ffs_ep0_write(struct file *file, const char __user *buf,
}
/* FFS_SETUP_PENDING and not stall */
- len = min(len, (size_t)le16_to_cpu(ffs->ev.setup.wLength));
+ len = min_t(size_t, len, le16_to_cpu(ffs->ev.setup.wLength));
spin_unlock_irq(&ffs->ev.waitq.lock);
@@ -590,7 +590,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
/* unlocks spinlock */
return __ffs_ep0_read_events(ffs, buf,
- min(n, (size_t)ffs->ev.count));
+ min_t(size_t, n, ffs->ev.count));
case FFS_SETUP_PENDING:
if (ffs->ev.setup.bRequestType & USB_DIR_IN) {
@@ -599,7 +599,7 @@ static ssize_t ffs_ep0_read(struct file *file, char __user *buf,
goto done_mutex;
}
- len = min(len, (size_t)le16_to_cpu(ffs->ev.setup.wLength));
+ len = min_t(size_t, len, le16_to_cpu(ffs->ev.setup.wLength));
spin_unlock_irq(&ffs->ev.waitq.lock);
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 08e0d1c511e8..2eae8fc2e0db 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -500,7 +500,7 @@ static int fsg_setup(struct usb_function *f,
*(u8 *)req->buf = _fsg_common_get_max_lun(fsg->common);
/* Respond with data/status */
- req->length = min((u16)1, w_length);
+ req->length = min_t(u16, 1, w_length);
return ep0_queue(fsg->common);
}
@@ -655,7 +655,7 @@ static int do_read(struct fsg_common *common)
* And don't try to read past the end of the file.
*/
amount = min(amount_left, FSG_BUFLEN);
- amount = min((loff_t)amount,
+ amount = min_t(loff_t, amount,
curlun->file_length - file_offset);
/* Wait for the next buffer to become available */
@@ -1005,7 +1005,7 @@ static int do_verify(struct fsg_common *common)
* And don't try to read past the end of the file.
*/
amount = min(amount_left, FSG_BUFLEN);
- amount = min((loff_t)amount,
+ amount = min_t(loff_t, amount,
curlun->file_length - file_offset);
if (amount == 0) {
curlun->sense_data =
@@ -2167,7 +2167,7 @@ unknown_cmnd:
if (reply == -EINVAL)
reply = 0; /* Error reply length */
if (reply >= 0 && common->data_dir == DATA_DIR_TO_HOST) {
- reply = min((u32)reply, common->data_size_from_cmnd);
+ reply = min_t(u32, reply, common->data_size_from_cmnd);
bh->inreq->length = reply;
bh->state = BUF_STATE_FULL;
common->residue -= reply;
diff --git a/drivers/usb/gadget/function/f_midi.c b/drivers/usb/gadget/function/f_midi.c
index 1067847cc079..837fcdfa3840 100644
--- a/drivers/usb/gadget/function/f_midi.c
+++ b/drivers/usb/gadget/function/f_midi.c
@@ -819,9 +819,9 @@ static int f_midi_register_card(struct f_midi *midi)
goto fail;
}
- strcpy(card->driver, f_midi_longname);
- strcpy(card->longname, f_midi_longname);
- strcpy(card->shortname, f_midi_shortname);
+ strscpy(card->driver, f_midi_longname);
+ strscpy(card->longname, f_midi_longname);
+ strscpy(card->shortname, f_midi_shortname);
/* Set up rawmidi */
snd_component_add(card, "MIDI");
@@ -833,7 +833,7 @@ static int f_midi_register_card(struct f_midi *midi)
}
midi->rmidi = rmidi;
midi->in_last_port = 0;
- strcpy(rmidi->name, card->shortname);
+ strscpy(rmidi->name, card->shortname);
rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
SNDRV_RAWMIDI_INFO_INPUT |
SNDRV_RAWMIDI_INFO_DUPLEX;
diff --git a/drivers/usb/gadget/function/f_midi2.c b/drivers/usb/gadget/function/f_midi2.c
index 8285df9ed6fd..12e866fb311d 100644
--- a/drivers/usb/gadget/function/f_midi2.c
+++ b/drivers/usb/gadget/function/f_midi2.c
@@ -1285,10 +1285,8 @@ static int f_midi2_set_alt(struct usb_function *fn, unsigned int intf,
if (alt == 0)
op_mode = MIDI_OP_MODE_MIDI1;
- else if (alt == 1)
- op_mode = MIDI_OP_MODE_MIDI2;
else
- op_mode = MIDI_OP_MODE_UNSET;
+ op_mode = MIDI_OP_MODE_MIDI2;
if (midi2->operation_mode == op_mode)
return 0;
@@ -1593,7 +1591,11 @@ static int f_midi2_create_card(struct f_midi2 *midi2)
fb->info.midi_ci_version = b->midi_ci_version;
fb->info.ui_hint = reverse_dir(b->ui_hint);
fb->info.sysex8_streams = b->sysex8_streams;
- fb->info.flags |= b->is_midi1;
+ if (b->is_midi1 < 2)
+ fb->info.flags |= b->is_midi1;
+ else
+ fb->info.flags |= SNDRV_UMP_BLOCK_IS_MIDI1 |
+ SNDRV_UMP_BLOCK_IS_LOWSPEED;
strscpy(fb->info.name, ump_fb_name(b),
sizeof(fb->info.name));
}
diff --git a/drivers/usb/gadget/function/f_uvc.c b/drivers/usb/gadget/function/f_uvc.c
index 40187b7112e7..aa6ab666741a 100644
--- a/drivers/usb/gadget/function/f_uvc.c
+++ b/drivers/usb/gadget/function/f_uvc.c
@@ -465,7 +465,7 @@ uvc_register_video(struct uvc_device *uvc)
memcpy(mem, desc, (desc)->bLength); \
*(dst)++ = mem; \
mem += (desc)->bLength; \
- } while (0);
+ } while (0)
#define UVC_COPY_DESCRIPTORS(mem, dst, src) \
do { \
@@ -991,6 +991,8 @@ static void uvc_function_unbind(struct usb_configuration *c,
uvcg_info(f, "%s()\n", __func__);
+ kthread_cancel_work_sync(&video->hw_submit);
+
if (video->async_wq)
destroy_workqueue(video->async_wq);
diff --git a/drivers/usb/gadget/function/u_serial.c b/drivers/usb/gadget/function/u_serial.c
index 0a8c05b2746b..53d9fc41acc5 100644
--- a/drivers/usb/gadget/function/u_serial.c
+++ b/drivers/usb/gadget/function/u_serial.c
@@ -579,9 +579,12 @@ static int gs_start_io(struct gs_port *port)
* we didn't in gs_start_tx() */
tty_wakeup(port->port.tty);
} else {
- gs_free_requests(ep, head, &port->read_allocated);
- gs_free_requests(port->port_usb->in, &port->write_pool,
- &port->write_allocated);
+ /* Free reqs only if we are still connected */
+ if (port->port_usb) {
+ gs_free_requests(ep, head, &port->read_allocated);
+ gs_free_requests(port->port_usb->in, &port->write_pool,
+ &port->write_allocated);
+ }
status = -EIO;
}
diff --git a/drivers/usb/gadget/function/uvc.h b/drivers/usb/gadget/function/uvc.h
index cb35687b11e7..6f44dd732315 100644
--- a/drivers/usb/gadget/function/uvc.h
+++ b/drivers/usb/gadget/function/uvc.h
@@ -71,6 +71,11 @@ extern unsigned int uvc_gadget_trace_param;
#define UVCG_REQUEST_HEADER_LEN 12
+#define UVCG_REQ_MAX_INT_COUNT 16
+#define UVCG_REQ_MAX_ZERO_COUNT (2 * UVCG_REQ_MAX_INT_COUNT)
+
+#define UVCG_STREAMING_MIN_BUFFERS 2
+
/* ------------------------------------------------------------------------
* Structures
*/
@@ -91,16 +96,24 @@ struct uvc_video {
struct work_struct pump;
struct workqueue_struct *async_wq;
+ struct kthread_worker *kworker;
+ struct kthread_work hw_submit;
+
+ atomic_t queued;
+
/* Frame parameters */
u8 bpp;
u32 fcc;
unsigned int width;
unsigned int height;
unsigned int imagesize;
+ unsigned int interval;
struct mutex mutex; /* protects frame parameters */
unsigned int uvc_num_requests;
+ unsigned int reqs_per_frame;
+
/* Requests */
bool is_enabled; /* tracks whether video stream is enabled */
unsigned int req_size;
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 6fac696ea846..f131943254a4 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -1566,11 +1566,13 @@ static const struct uvcg_config_group_type uvcg_control_grp_type = {
/* -----------------------------------------------------------------------------
* streaming/uncompressed
* streaming/mjpeg
+ * streaming/framebased
*/
static const char * const uvcg_format_names[] = {
"uncompressed",
"mjpeg",
+ "framebased",
};
static struct uvcg_color_matching *
@@ -1777,6 +1779,9 @@ static int uvcg_streaming_header_allow_link(struct config_item *src,
target_fmt = container_of(to_config_group(target), struct uvcg_format,
group);
+ if (!target_fmt)
+ goto out;
+
uvcg_format_set_indices(to_config_group(target));
format_ptr = kzalloc(sizeof(*format_ptr), GFP_KERNEL);
@@ -1816,6 +1821,9 @@ static void uvcg_streaming_header_drop_link(struct config_item *src,
target_fmt = container_of(to_config_group(target), struct uvcg_format,
group);
+ if (!target_fmt)
+ goto out;
+
list_for_each_entry_safe(format_ptr, tmp, &src_hdr->formats, entry)
if (format_ptr->fmt == target_fmt) {
list_del(&format_ptr->entry);
@@ -1826,6 +1834,7 @@ static void uvcg_streaming_header_drop_link(struct config_item *src,
--target_fmt->linked;
+out:
mutex_unlock(&opts->lock);
mutex_unlock(su_mutex);
}
@@ -2022,6 +2031,7 @@ UVCG_FRAME_ATTR(dw_min_bit_rate, dwMinBitRate, 32);
UVCG_FRAME_ATTR(dw_max_bit_rate, dwMaxBitRate, 32);
UVCG_FRAME_ATTR(dw_max_video_frame_buffer_size, dwMaxVideoFrameBufferSize, 32);
UVCG_FRAME_ATTR(dw_default_frame_interval, dwDefaultFrameInterval, 32);
+UVCG_FRAME_ATTR(dw_bytes_perline, dwBytesPerLine, 32);
#undef UVCG_FRAME_ATTR
@@ -2035,7 +2045,7 @@ static ssize_t uvcg_frame_dw_frame_interval_show(struct config_item *item,
int result, i;
char *pg = page;
- mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
opts_item = frm->item.ci_parent->ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -2105,7 +2115,7 @@ end:
UVC_ATTR(uvcg_frame_, dw_frame_interval, dwFrameInterval);
-static struct configfs_attribute *uvcg_frame_attrs[] = {
+static struct configfs_attribute *uvcg_frame_attrs1[] = {
&uvcg_frame_attr_b_frame_index,
&uvcg_frame_attr_bm_capabilities,
&uvcg_frame_attr_w_width,
@@ -2118,12 +2128,31 @@ static struct configfs_attribute *uvcg_frame_attrs[] = {
NULL,
};
-static const struct config_item_type uvcg_frame_type = {
+static struct configfs_attribute *uvcg_frame_attrs2[] = {
+ &uvcg_frame_attr_b_frame_index,
+ &uvcg_frame_attr_bm_capabilities,
+ &uvcg_frame_attr_w_width,
+ &uvcg_frame_attr_w_height,
+ &uvcg_frame_attr_dw_min_bit_rate,
+ &uvcg_frame_attr_dw_max_bit_rate,
+ &uvcg_frame_attr_dw_default_frame_interval,
+ &uvcg_frame_attr_dw_frame_interval,
+ &uvcg_frame_attr_dw_bytes_perline,
+ NULL,
+};
+
+static const struct config_item_type uvcg_frame_type1 = {
.ct_item_ops = &uvcg_config_item_ops,
- .ct_attrs = uvcg_frame_attrs,
+ .ct_attrs = uvcg_frame_attrs1,
.ct_owner = THIS_MODULE,
};
+static const struct config_item_type uvcg_frame_type2 = {
+ .ct_item_ops = &uvcg_config_item_ops,
+ .ct_attrs = uvcg_frame_attrs2,
+ .ct_owner = THIS_MODULE,
+};
+
static struct config_item *uvcg_frame_make(struct config_group *group,
const char *name)
{
@@ -2145,6 +2174,7 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
h->frame.dw_max_bit_rate = 55296000;
h->frame.dw_max_video_frame_buffer_size = 460800;
h->frame.dw_default_frame_interval = 666666;
+ h->frame.dw_bytes_perline = 0;
opts_item = group->cg_item.ci_parent->ci_parent->ci_parent;
opts = to_f_uvc_opts(opts_item);
@@ -2157,6 +2187,9 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
} else if (fmt->type == UVCG_MJPEG) {
h->frame.b_descriptor_subtype = UVC_VS_FRAME_MJPEG;
h->fmt_type = UVCG_MJPEG;
+ } else if (fmt->type == UVCG_FRAMEBASED) {
+ h->frame.b_descriptor_subtype = UVC_VS_FRAME_FRAME_BASED;
+ h->fmt_type = UVCG_FRAMEBASED;
} else {
mutex_unlock(&opts->lock);
kfree(h);
@@ -2175,7 +2208,10 @@ static struct config_item *uvcg_frame_make(struct config_group *group,
++fmt->num_frames;
mutex_unlock(&opts->lock);
- config_item_init_type_name(&h->item, name, &uvcg_frame_type);
+ if (fmt->type == UVCG_FRAMEBASED)
+ config_item_init_type_name(&h->item, name, &uvcg_frame_type2);
+ else
+ config_item_init_type_name(&h->item, name, &uvcg_frame_type1);
return &h->item;
}
@@ -2215,9 +2251,6 @@ static void uvcg_format_set_indices(struct config_group *fmt)
list_for_each_entry(ci, &fmt->cg_children, ci_entry) {
struct uvcg_frame *frm;
- if (ci->ci_type != &uvcg_frame_type)
- continue;
-
frm = to_uvcg_frame(ci);
frm->frame.b_frame_index = i++;
}
@@ -2678,6 +2711,251 @@ static const struct uvcg_config_group_type uvcg_mjpeg_grp_type = {
};
/* -----------------------------------------------------------------------------
+ * streaming/framebased/<NAME>
+ */
+
+static struct configfs_group_operations uvcg_framebased_group_ops = {
+ .make_item = uvcg_frame_make,
+ .drop_item = uvcg_frame_drop,
+};
+
+#define UVCG_FRAMEBASED_ATTR_RO(cname, aname, bits) \
+static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \
+ char *page) \
+{ \
+ struct uvcg_framebased *u = to_uvcg_framebased(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
+ int result; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
+ opts = to_f_uvc_opts(opts_item); \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
+ mutex_unlock(&opts->lock); \
+ \
+ mutex_unlock(su_mutex); \
+ return result; \
+} \
+ \
+UVC_ATTR_RO(uvcg_framebased_, cname, aname)
+
+#define UVCG_FRAMEBASED_ATTR(cname, aname, bits) \
+static ssize_t uvcg_framebased_##cname##_show(struct config_item *item, \
+ char *page) \
+{ \
+ struct uvcg_framebased *u = to_uvcg_framebased(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
+ int result; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
+ opts = to_f_uvc_opts(opts_item); \
+ \
+ mutex_lock(&opts->lock); \
+ result = sprintf(page, "%u\n", le##bits##_to_cpu(u->desc.aname));\
+ mutex_unlock(&opts->lock); \
+ \
+ mutex_unlock(su_mutex); \
+ return result; \
+} \
+ \
+static ssize_t \
+uvcg_framebased_##cname##_store(struct config_item *item, \
+ const char *page, size_t len) \
+{ \
+ struct uvcg_framebased *u = to_uvcg_framebased(item); \
+ struct f_uvc_opts *opts; \
+ struct config_item *opts_item; \
+ struct mutex *su_mutex = &u->fmt.group.cg_subsys->su_mutex; \
+ int ret; \
+ u8 num; \
+ \
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */ \
+ \
+ opts_item = u->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;\
+ opts = to_f_uvc_opts(opts_item); \
+ \
+ mutex_lock(&opts->lock); \
+ if (u->fmt.linked || opts->refcnt) { \
+ ret = -EBUSY; \
+ goto end; \
+ } \
+ \
+ ret = kstrtou8(page, 0, &num); \
+ if (ret) \
+ goto end; \
+ \
+ if (num > 255) { \
+ ret = -EINVAL; \
+ goto end; \
+ } \
+ u->desc.aname = num; \
+ ret = len; \
+end: \
+ mutex_unlock(&opts->lock); \
+ mutex_unlock(su_mutex); \
+ return ret; \
+} \
+ \
+UVC_ATTR(uvcg_framebased_, cname, aname)
+
+UVCG_FRAMEBASED_ATTR_RO(b_format_index, bFormatIndex, 8);
+UVCG_FRAMEBASED_ATTR_RO(b_bits_per_pixel, bBitsPerPixel, 8);
+UVCG_FRAMEBASED_ATTR(b_default_frame_index, bDefaultFrameIndex, 8);
+UVCG_FRAMEBASED_ATTR_RO(b_aspect_ratio_x, bAspectRatioX, 8);
+UVCG_FRAMEBASED_ATTR_RO(b_aspect_ratio_y, bAspectRatioY, 8);
+UVCG_FRAMEBASED_ATTR_RO(bm_interface_flags, bmInterfaceFlags, 8);
+
+#undef UVCG_FRAMEBASED_ATTR
+#undef UVCG_FRAMEBASED_ATTR_RO
+
+static ssize_t uvcg_framebased_guid_format_show(struct config_item *item,
+ char *page)
+{
+ struct uvcg_framebased *ch = to_uvcg_framebased(item);
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+ struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
+
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+ opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
+ memcpy(page, ch->desc.guidFormat, sizeof(ch->desc.guidFormat));
+ mutex_unlock(&opts->lock);
+
+ mutex_unlock(su_mutex);
+
+ return sizeof(ch->desc.guidFormat);
+}
+
+static ssize_t uvcg_framebased_guid_format_store(struct config_item *item,
+ const char *page, size_t len)
+{
+ struct uvcg_framebased *ch = to_uvcg_framebased(item);
+ struct f_uvc_opts *opts;
+ struct config_item *opts_item;
+ struct mutex *su_mutex = &ch->fmt.group.cg_subsys->su_mutex;
+ int ret;
+
+ mutex_lock(su_mutex); /* for navigating configfs hierarchy */
+
+ opts_item = ch->fmt.group.cg_item.ci_parent->ci_parent->ci_parent;
+ opts = to_f_uvc_opts(opts_item);
+
+ mutex_lock(&opts->lock);
+ if (ch->fmt.linked || opts->refcnt) {
+ ret = -EBUSY;
+ goto end;
+ }
+
+ memcpy(ch->desc.guidFormat, page,
+ min(sizeof(ch->desc.guidFormat), len));
+ ret = sizeof(ch->desc.guidFormat);
+
+end:
+ mutex_unlock(&opts->lock);
+ mutex_unlock(su_mutex);
+ return ret;
+}
+
+UVC_ATTR(uvcg_framebased_, guid_format, guidFormat);
+
+static inline ssize_t
+uvcg_framebased_bma_controls_show(struct config_item *item, char *page)
+{
+ struct uvcg_framebased *u = to_uvcg_framebased(item);
+
+ return uvcg_format_bma_controls_show(&u->fmt, page);
+}
+
+static inline ssize_t
+uvcg_framebased_bma_controls_store(struct config_item *item,
+ const char *page, size_t len)
+{
+ struct uvcg_framebased *u = to_uvcg_framebased(item);
+
+ return uvcg_format_bma_controls_store(&u->fmt, page, len);
+}
+
+UVC_ATTR(uvcg_framebased_, bma_controls, bmaControls);
+
+static struct configfs_attribute *uvcg_framebased_attrs[] = {
+ &uvcg_framebased_attr_b_format_index,
+ &uvcg_framebased_attr_b_default_frame_index,
+ &uvcg_framebased_attr_b_bits_per_pixel,
+ &uvcg_framebased_attr_b_aspect_ratio_x,
+ &uvcg_framebased_attr_b_aspect_ratio_y,
+ &uvcg_framebased_attr_bm_interface_flags,
+ &uvcg_framebased_attr_bma_controls,
+ &uvcg_framebased_attr_guid_format,
+ NULL,
+};
+
+static const struct config_item_type uvcg_framebased_type = {
+ .ct_item_ops = &uvcg_config_item_ops,
+ .ct_group_ops = &uvcg_framebased_group_ops,
+ .ct_attrs = uvcg_framebased_attrs,
+ .ct_owner = THIS_MODULE,
+};
+
+static struct config_group *uvcg_framebased_make(struct config_group *group,
+ const char *name)
+{
+ static char guid[] = { /*Declear frame based as H264 format*/
+ 'H', '2', '6', '4', 0x00, 0x00, 0x10, 0x00,
+ 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71
+ };
+ struct uvcg_framebased *h;
+
+ h = kzalloc(sizeof(*h), GFP_KERNEL);
+ if (!h)
+ return ERR_PTR(-ENOMEM);
+
+ h->desc.bLength = UVC_DT_FORMAT_FRAMEBASED_SIZE;
+ h->desc.bDescriptorType = USB_DT_CS_INTERFACE;
+ h->desc.bDescriptorSubType = UVC_VS_FORMAT_FRAME_BASED;
+ memcpy(h->desc.guidFormat, guid, sizeof(guid));
+ h->desc.bBitsPerPixel = 0;
+ h->desc.bDefaultFrameIndex = 1;
+ h->desc.bAspectRatioX = 0;
+ h->desc.bAspectRatioY = 0;
+ h->desc.bmInterfaceFlags = 0;
+ h->desc.bCopyProtect = 0;
+ h->desc.bVariableSize = 1;
+
+ INIT_LIST_HEAD(&h->fmt.frames);
+ h->fmt.type = UVCG_FRAMEBASED;
+ config_group_init_type_name(&h->fmt.group, name,
+ &uvcg_framebased_type);
+
+ return &h->fmt.group;
+}
+
+static struct configfs_group_operations uvcg_framebased_grp_ops = {
+ .make_group = uvcg_framebased_make,
+};
+
+static const struct uvcg_config_group_type uvcg_framebased_grp_type = {
+ .type = {
+ .ct_item_ops = &uvcg_config_item_ops,
+ .ct_group_ops = &uvcg_framebased_grp_ops,
+ .ct_owner = THIS_MODULE,
+ },
+ .name = "framebased",
+};
+
+/* -----------------------------------------------------------------------------
* streaming/color_matching/default
*/
@@ -2912,6 +3190,7 @@ static int __uvcg_iter_strm_cls(struct uvcg_streaming_header *h,
if (ret)
return ret;
grp = &f->fmt->group;
+ j = 0;
list_for_each_entry(item, &grp->cg_children, ci_entry) {
frm = to_uvcg_frame(item);
ret = fun(frm, priv2, priv3, j++, UVCG_FRAME);
@@ -2965,6 +3244,11 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
container_of(fmt, struct uvcg_mjpeg, fmt);
*size += sizeof(m->desc);
+ } else if (fmt->type == UVCG_FRAMEBASED) {
+ struct uvcg_framebased *f =
+ container_of(fmt, struct uvcg_framebased, fmt);
+
+ *size += sizeof(f->desc);
} else {
return -EINVAL;
}
@@ -2975,6 +3259,11 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
int sz = sizeof(frm->dw_frame_interval);
*size += sizeof(frm->frame);
+ /*
+ * framebased has duplicate member with uncompressed and
+ * mjpeg, so minus it
+ */
+ *size -= sizeof(u32);
*size += frm->frame.b_frame_interval_type * sz;
}
break;
@@ -2991,6 +3280,27 @@ static int __uvcg_cnt_strm(void *priv1, void *priv2, void *priv3, int n,
return 0;
}
+static int __uvcg_copy_framebased_desc(void *dest, struct uvcg_frame *frm,
+ int sz)
+{
+ struct uvc_frame_framebased *desc = dest;
+
+ desc->bLength = frm->frame.b_length;
+ desc->bDescriptorType = frm->frame.b_descriptor_type;
+ desc->bDescriptorSubType = frm->frame.b_descriptor_subtype;
+ desc->bFrameIndex = frm->frame.b_frame_index;
+ desc->bmCapabilities = frm->frame.bm_capabilities;
+ desc->wWidth = frm->frame.w_width;
+ desc->wHeight = frm->frame.w_height;
+ desc->dwMinBitRate = frm->frame.dw_min_bit_rate;
+ desc->dwMaxBitRate = frm->frame.dw_max_bit_rate;
+ desc->dwDefaultFrameInterval = frm->frame.dw_default_frame_interval;
+ desc->bFrameIntervalType = frm->frame.b_frame_interval_type;
+ desc->dwBytesPerLine = frm->frame.dw_bytes_perline;
+
+ return 0;
+}
+
/*
* Fill an array of streaming descriptors.
*
@@ -3045,6 +3355,15 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
m->desc.bNumFrameDescriptors = fmt->num_frames;
memcpy(*dest, &m->desc, sizeof(m->desc));
*dest += sizeof(m->desc);
+ } else if (fmt->type == UVCG_FRAMEBASED) {
+ struct uvcg_framebased *f =
+ container_of(fmt, struct uvcg_framebased,
+ fmt);
+
+ f->desc.bFormatIndex = n + 1;
+ f->desc.bNumFrameDescriptors = fmt->num_frames;
+ memcpy(*dest, &f->desc, sizeof(f->desc));
+ *dest += sizeof(f->desc);
} else {
return -EINVAL;
}
@@ -3054,8 +3373,11 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
struct uvcg_frame *frm = priv1;
struct uvc_descriptor_header *h = *dest;
- sz = sizeof(frm->frame);
- memcpy(*dest, &frm->frame, sz);
+ sz = sizeof(frm->frame) - 4;
+ if (frm->fmt_type != UVCG_FRAMEBASED)
+ memcpy(*dest, &frm->frame, sz);
+ else
+ __uvcg_copy_framebased_desc(*dest, frm, sz);
*dest += sz;
sz = frm->frame.b_frame_interval_type *
sizeof(*frm->dw_frame_interval);
@@ -3066,7 +3388,10 @@ static int __uvcg_fill_strm(void *priv1, void *priv2, void *priv3, int n,
frm->frame.b_frame_interval_type);
else if (frm->fmt_type == UVCG_MJPEG)
h->bLength = UVC_DT_FRAME_MJPEG_SIZE(
- frm->frame.b_frame_interval_type);
+ frm->frame.b_frame_interval_type);
+ else if (frm->fmt_type == UVCG_FRAMEBASED)
+ h->bLength = UVC_DT_FRAME_FRAMEBASED_SIZE(
+ frm->frame.b_frame_interval_type);
}
break;
case UVCG_COLOR_MATCHING: {
@@ -3285,6 +3610,7 @@ static const struct uvcg_config_group_type uvcg_streaming_grp_type = {
&uvcg_streaming_header_grp_type,
&uvcg_uncompressed_grp_type,
&uvcg_mjpeg_grp_type,
+ &uvcg_framebased_grp_type,
&uvcg_color_matching_grp_type,
&uvcg_streaming_class_grp_type,
NULL,
diff --git a/drivers/usb/gadget/function/uvc_configfs.h b/drivers/usb/gadget/function/uvc_configfs.h
index c6a690158138..2f78cd4f396f 100644
--- a/drivers/usb/gadget/function/uvc_configfs.h
+++ b/drivers/usb/gadget/function/uvc_configfs.h
@@ -49,6 +49,7 @@ container_of(group_ptr, struct uvcg_color_matching, group)
enum uvcg_format_type {
UVCG_UNCOMPRESSED = 0,
UVCG_MJPEG,
+ UVCG_FRAMEBASED,
};
struct uvcg_format {
@@ -105,6 +106,7 @@ struct uvcg_frame {
u32 dw_max_video_frame_buffer_size;
u32 dw_default_frame_interval;
u8 b_frame_interval_type;
+ u32 dw_bytes_perline;
} __attribute__((packed)) frame;
u32 *dw_frame_interval;
};
@@ -143,6 +145,20 @@ static inline struct uvcg_mjpeg *to_uvcg_mjpeg(struct config_item *item)
}
/* -----------------------------------------------------------------------------
+ * streaming/framebased/<NAME>
+ */
+
+struct uvcg_framebased {
+ struct uvcg_format fmt;
+ struct uvc_format_framebased desc;
+};
+
+static inline struct uvcg_framebased *to_uvcg_framebased(struct config_item *item)
+{
+ return container_of(to_uvcg_format(item), struct uvcg_framebased, fmt);
+}
+
+/* -----------------------------------------------------------------------------
* control/extensions/<NAME>
*/
diff --git a/drivers/usb/gadget/function/uvc_queue.c b/drivers/usb/gadget/function/uvc_queue.c
index 0aa3d7e1f3cc..5eaeae3e2441 100644
--- a/drivers/usb/gadget/function/uvc_queue.c
+++ b/drivers/usb/gadget/function/uvc_queue.c
@@ -21,6 +21,7 @@
#include <media/videobuf2-vmalloc.h>
#include "uvc.h"
+#include "uvc_video.h"
/* ------------------------------------------------------------------------
* Video buffers queue management.
@@ -44,33 +45,23 @@ static int uvc_queue_setup(struct vb2_queue *vq,
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
struct uvc_video *video = container_of(queue, struct uvc_video, queue);
- unsigned int req_size;
- unsigned int nreq;
if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
*nbuffers = UVC_MAX_VIDEO_BUFFERS;
+ if (*nbuffers < UVCG_STREAMING_MIN_BUFFERS)
+ *nbuffers = UVCG_STREAMING_MIN_BUFFERS;
*nplanes = 1;
sizes[0] = video->imagesize;
- req_size = video->ep->maxpacket
- * max_t(unsigned int, video->ep->maxburst, 1)
- * (video->ep->mult);
-
- /* We divide by two, to increase the chance to run
- * into fewer requests for smaller framesizes.
- */
- nreq = DIV_ROUND_UP(DIV_ROUND_UP(sizes[0], 2), req_size);
- nreq = clamp(nreq, 4U, 64U);
- video->uvc_num_requests = nreq;
-
return 0;
}
static int uvc_buffer_prepare(struct vb2_buffer *vb)
{
struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
+ struct uvc_video *video = container_of(queue, struct uvc_video, queue);
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
@@ -91,10 +82,15 @@ static int uvc_buffer_prepare(struct vb2_buffer *vb)
buf->mem = vb2_plane_vaddr(vb, 0);
}
buf->length = vb2_plane_size(vb, 0);
- if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+ if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
buf->bytesused = 0;
- else
+ } else {
buf->bytesused = vb2_get_plane_payload(vb, 0);
+ buf->req_payload_size =
+ DIV_ROUND_UP(buf->bytesused +
+ (video->reqs_per_frame * UVCG_REQUEST_HEADER_LEN),
+ video->reqs_per_frame);
+ }
return 0;
}
diff --git a/drivers/usb/gadget/function/uvc_queue.h b/drivers/usb/gadget/function/uvc_queue.h
index 41f87b917f6b..b54becc570a3 100644
--- a/drivers/usb/gadget/function/uvc_queue.h
+++ b/drivers/usb/gadget/function/uvc_queue.h
@@ -39,6 +39,8 @@ struct uvc_buffer {
unsigned int offset;
unsigned int length;
unsigned int bytesused;
+ /* req_payload_size: only used with isoc */
+ unsigned int req_payload_size;
};
#define UVC_QUEUE_DISCONNECTED (1 << 0)
diff --git a/drivers/usb/gadget/function/uvc_trace.c b/drivers/usb/gadget/function/uvc_trace.c
new file mode 100644
index 000000000000..d384f6d8221a
--- /dev/null
+++ b/drivers/usb/gadget/function/uvc_trace.c
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * trace.c - USB UVC Gadget Trace Support
+ *
+ * Copyright (C) 2024 Pengutronix e.K.
+ *
+ * Author: Michael Grzeschik <m.grzeschik@pengutronix.de>
+ */
+
+#define CREATE_TRACE_POINTS
+#include "uvc_trace.h"
diff --git a/drivers/usb/gadget/function/uvc_trace.h b/drivers/usb/gadget/function/uvc_trace.h
new file mode 100644
index 000000000000..04c33cf43cc2
--- /dev/null
+++ b/drivers/usb/gadget/function/uvc_trace.h
@@ -0,0 +1,60 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * trace.h - USB UVC Gadget Trace Support
+ *
+ * Copyright (C) 2024 Pengutronix e.K.
+ *
+ * Author: Michael Grzeschik <m.grzeschik@pengutronix.de>
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM uvcg
+
+#if !defined(__UVCG_TRACE_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __UVCG_TRACE_H
+
+#include <linux/types.h>
+#include <linux/tracepoint.h>
+#include <linux/usb/gadget.h>
+#include <asm/byteorder.h>
+
+DECLARE_EVENT_CLASS(uvcg_video_req,
+ TP_PROTO(struct usb_request *req, u32 queued),
+ TP_ARGS(req, queued),
+ TP_STRUCT__entry(
+ __field(struct usb_request *, req)
+ __field(u32, length)
+ __field(u32, queued)
+ ),
+ TP_fast_assign(
+ __entry->req = req;
+ __entry->length = req->length;
+ __entry->queued = queued;
+ ),
+ TP_printk("req %p length %u queued %u",
+ __entry->req,
+ __entry->length,
+ __entry->queued)
+);
+
+DEFINE_EVENT(uvcg_video_req, uvcg_video_complete,
+ TP_PROTO(struct usb_request *req, u32 queued),
+ TP_ARGS(req, queued)
+);
+
+DEFINE_EVENT(uvcg_video_req, uvcg_video_queue,
+ TP_PROTO(struct usb_request *req, u32 queued),
+ TP_ARGS(req, queued)
+);
+
+#endif /* __UVCG_TRACE_H */
+
+/* this part has to be here */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE uvc_trace
+
+#include <trace/define_trace.h>
diff --git a/drivers/usb/gadget/function/uvc_v4l2.c b/drivers/usb/gadget/function/uvc_v4l2.c
index de1736f834e6..fc9a8d31a1e9 100644
--- a/drivers/usb/gadget/function/uvc_v4l2.c
+++ b/drivers/usb/gadget/function/uvc_v4l2.c
@@ -31,14 +31,23 @@ static const struct uvc_format_desc *to_uvc_format(struct uvcg_format *uformat)
{
char guid[16] = UVC_GUID_FORMAT_MJPEG;
const struct uvc_format_desc *format;
- struct uvcg_uncompressed *unc;
if (uformat->type == UVCG_UNCOMPRESSED) {
+ struct uvcg_uncompressed *unc;
+
unc = to_uvcg_uncompressed(&uformat->group.cg_item);
if (!unc)
return ERR_PTR(-EINVAL);
memcpy(guid, unc->desc.guidFormat, sizeof(guid));
+ } else if (uformat->type == UVCG_FRAMEBASED) {
+ struct uvcg_framebased *unc;
+
+ unc = to_uvcg_framebased(&uformat->group.cg_item);
+ if (!unc)
+ return ERR_PTR(-EINVAL);
+
+ memcpy(guid, unc->desc.guidFormat, sizeof(guid));
}
format = uvc_format_by_guid(guid);
@@ -314,6 +323,56 @@ uvc_v4l2_set_format(struct file *file, void *fh, struct v4l2_format *fmt)
return ret;
}
+static int uvc_v4l2_g_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *parm)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct uvc_device *uvc = video_get_drvdata(vdev);
+ struct uvc_video *video = &uvc->video;
+ struct v4l2_fract timeperframe;
+
+ if (!V4L2_TYPE_IS_OUTPUT(parm->type))
+ return -EINVAL;
+
+ /* Return the actual frame period. */
+ timeperframe.numerator = video->interval;
+ timeperframe.denominator = 10000000;
+ v4l2_simplify_fraction(&timeperframe.numerator,
+ &timeperframe.denominator, 8, 333);
+
+ uvcg_dbg(&uvc->func, "Getting frame interval of %u/%u (%u)\n",
+ timeperframe.numerator, timeperframe.denominator,
+ video->interval);
+
+ parm->parm.output.timeperframe = timeperframe;
+ parm->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+
+ return 0;
+}
+
+static int uvc_v4l2_s_parm(struct file *file, void *fh,
+ struct v4l2_streamparm *parm)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct uvc_device *uvc = video_get_drvdata(vdev);
+ struct uvc_video *video = &uvc->video;
+ struct v4l2_fract timeperframe;
+
+ if (!V4L2_TYPE_IS_OUTPUT(parm->type))
+ return -EINVAL;
+
+ timeperframe = parm->parm.output.timeperframe;
+
+ video->interval = v4l2_fraction_to_interval(timeperframe.numerator,
+ timeperframe.denominator);
+
+ uvcg_dbg(&uvc->func, "Setting frame interval to %u/%u (%u)\n",
+ timeperframe.numerator, timeperframe.denominator,
+ video->interval);
+
+ return 0;
+}
+
static int
uvc_v4l2_enum_frameintervals(struct file *file, void *fh,
struct v4l2_frmivalenum *fival)
@@ -496,6 +555,9 @@ uvc_v4l2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
if (ret < 0)
return ret;
+ if (uvc->state != UVC_STATE_STREAMING)
+ return 0;
+
uvc->state = UVC_STATE_CONNECTED;
uvc_function_setup_continue(uvc, 1);
return 0;
@@ -587,6 +649,8 @@ const struct v4l2_ioctl_ops uvc_v4l2_ioctl_ops = {
.vidioc_dqbuf = uvc_v4l2_dqbuf,
.vidioc_streamon = uvc_v4l2_streamon,
.vidioc_streamoff = uvc_v4l2_streamoff,
+ .vidioc_s_parm = uvc_v4l2_s_parm,
+ .vidioc_g_parm = uvc_v4l2_g_parm,
.vidioc_subscribe_event = uvc_v4l2_subscribe_event,
.vidioc_unsubscribe_event = uvc_v4l2_unsubscribe_event,
.vidioc_default = uvc_v4l2_ioctl_default,
diff --git a/drivers/usb/gadget/function/uvc_video.c b/drivers/usb/gadget/function/uvc_video.c
index 57a851151225..79e223713d8b 100644
--- a/drivers/usb/gadget/function/uvc_video.c
+++ b/drivers/usb/gadget/function/uvc_video.c
@@ -19,6 +19,7 @@
#include "uvc.h"
#include "uvc_queue.h"
#include "uvc_video.h"
+#include "uvc_trace.h"
/* --------------------------------------------------------------------------
* Video codecs
@@ -78,7 +79,7 @@ uvc_video_encode_data(struct uvc_video *video, struct uvc_buffer *buf,
/* Copy video data to the USB buffer. */
mem = buf->mem + queue->buf_used;
- nbytes = min((unsigned int)len, buf->bytesused - queue->buf_used);
+ nbytes = min_t(unsigned int, len, buf->bytesused - queue->buf_used);
memcpy(data, mem, nbytes);
queue->buf_used += nbytes;
@@ -104,7 +105,7 @@ uvc_video_encode_bulk(struct usb_request *req, struct uvc_video *video,
}
/* Process video data. */
- len = min((int)(video->max_payload_size - video->payload_size), len);
+ len = min_t(int, video->max_payload_size - video->payload_size, len);
ret = uvc_video_encode_data(video, buf, mem, len);
video->payload_size += ret;
@@ -136,7 +137,7 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
unsigned int pending = buf->bytesused - video->queue.buf_used;
struct uvc_request *ureq = req->context;
struct scatterlist *sg, *iter;
- unsigned int len = video->req_size;
+ unsigned int len = buf->req_payload_size;
unsigned int sg_left, part = 0;
unsigned int i;
int header_len;
@@ -146,15 +147,15 @@ uvc_video_encode_isoc_sg(struct usb_request *req, struct uvc_video *video,
/* Init the header. */
header_len = uvc_video_encode_header(video, buf, ureq->header,
- video->req_size);
+ buf->req_payload_size);
sg_set_buf(sg, ureq->header, header_len);
len -= header_len;
if (pending <= len)
len = pending;
- req->length = (len == pending) ?
- len + header_len : video->req_size;
+ req->length = (len == pending) ? len + header_len :
+ buf->req_payload_size;
/* Init the pending sgs with payload */
sg = sg_next(sg);
@@ -202,7 +203,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
{
void *mem = req->buf;
struct uvc_request *ureq = req->context;
- int len = video->req_size;
+ int len = buf->req_payload_size;
int ret;
/* Add the header. */
@@ -214,7 +215,7 @@ uvc_video_encode_isoc(struct usb_request *req, struct uvc_video *video,
ret = uvc_video_encode_data(video, buf, mem, len);
len -= ret;
- req->length = video->req_size - len;
+ req->length = buf->req_payload_size - len;
if (buf->bytesused == video->queue.buf_used ||
video->queue.flags & UVC_QUEUE_DROP_INCOMPLETE) {
@@ -269,6 +270,10 @@ static int uvcg_video_ep_queue(struct uvc_video *video, struct usb_request *req)
}
}
+ atomic_inc(&video->queued);
+
+ trace_uvcg_video_queue(req, atomic_read(&video->queued));
+
return ret;
}
@@ -304,7 +309,7 @@ static int uvcg_video_usb_req_queue(struct uvc_video *video,
*/
if (list_empty(&video->req_free) || ureq->last_buf ||
!(video->req_int_count %
- DIV_ROUND_UP(video->uvc_num_requests, 4))) {
+ min(DIV_ROUND_UP(video->uvc_num_requests, 4), UVCG_REQ_MAX_INT_COUNT))) {
video->req_int_count = 0;
req->no_interrupt = 0;
} else {
@@ -322,50 +327,6 @@ static int uvcg_video_usb_req_queue(struct uvc_video *video,
return 0;
}
-/*
- * Must only be called from uvcg_video_enable - since after that we only want to
- * queue requests to the endpoint from the uvc_video_complete complete handler.
- * This function is needed in order to 'kick start' the flow of requests from
- * gadget driver to the usb controller.
- */
-static void uvc_video_ep_queue_initial_requests(struct uvc_video *video)
-{
- struct usb_request *req = NULL;
- unsigned long flags = 0;
- unsigned int count = 0;
- int ret = 0;
-
- /*
- * We only queue half of the free list since we still want to have
- * some free usb_requests in the free list for the video_pump async_wq
- * thread to encode uvc buffers into. Otherwise we could get into a
- * situation where the free list does not have any usb requests to
- * encode into - we always end up queueing 0 length requests to the
- * end point.
- */
- unsigned int half_list_size = video->uvc_num_requests / 2;
-
- spin_lock_irqsave(&video->req_lock, flags);
- /*
- * Take these requests off the free list and queue them all to the
- * endpoint. Since we queue 0 length requests with the req_lock held,
- * there isn't any 'data' race involved here with the complete handler.
- */
- while (count < half_list_size) {
- req = list_first_entry(&video->req_free, struct usb_request,
- list);
- list_del(&req->list);
- req->length = 0;
- ret = uvcg_video_ep_queue(video, req);
- if (ret < 0) {
- uvcg_queue_cancel(&video->queue, 0);
- break;
- }
- count++;
- }
- spin_unlock_irqrestore(&video->req_lock, flags);
-}
-
static void
uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
{
@@ -373,12 +334,10 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
struct uvc_video *video = ureq->video;
struct uvc_video_queue *queue = &video->queue;
struct uvc_buffer *last_buf;
- struct usb_request *to_queue = req;
unsigned long flags;
- bool is_bulk = video->max_payload_size;
- int ret = 0;
spin_lock_irqsave(&video->req_lock, flags);
+ atomic_dec(&video->queued);
if (!video->is_enabled) {
/*
* When is_enabled is false, uvcg_video_disable() ensures
@@ -438,51 +397,87 @@ uvc_video_complete(struct usb_ep *ep, struct usb_request *req)
return;
}
+ list_add_tail(&req->list, &video->req_free);
/*
- * Here we check whether any request is available in the ready
- * list. If it is, queue it to the ep and add the current
- * usb_request to the req_free list - for video_pump to fill in.
- * Otherwise, just use the current usb_request to queue a 0
- * length request to the ep. Since we always add to the req_free
- * list if we dequeue from the ready list, there will never
- * be a situation where the req_free list is completely out of
- * requests and cannot recover.
+ * Queue work to the wq as well since it is possible that a
+ * buffer may not have been completely encoded with the set of
+ * in-flight usb requests for whih the complete callbacks are
+ * firing.
+ * In that case, if we do not queue work to the worker thread,
+ * the buffer will never be marked as complete - and therefore
+ * not be returned to userpsace. As a result,
+ * dequeue -> queue -> dequeue flow of uvc buffers will not
+ * happen. Since there are is a new free request wake up the pump.
*/
- to_queue->length = 0;
- if (!list_empty(&video->req_ready)) {
- to_queue = list_first_entry(&video->req_ready,
- struct usb_request, list);
- list_del(&to_queue->list);
- list_add_tail(&req->list, &video->req_free);
+ queue_work(video->async_wq, &video->pump);
+
+ trace_uvcg_video_complete(req, atomic_read(&video->queued));
+
+ spin_unlock_irqrestore(&video->req_lock, flags);
+
+ kthread_queue_work(video->kworker, &video->hw_submit);
+}
+
+static void uvcg_video_hw_submit(struct kthread_work *work)
+{
+ struct uvc_video *video = container_of(work, struct uvc_video, hw_submit);
+ bool is_bulk = video->max_payload_size;
+ unsigned long flags;
+ struct usb_request *req;
+ int ret = 0;
+
+ while (true) {
+ if (!video->ep->enabled)
+ return;
+ spin_lock_irqsave(&video->req_lock, flags);
/*
- * Queue work to the wq as well since it is possible that a
- * buffer may not have been completely encoded with the set of
- * in-flight usb requests for whih the complete callbacks are
- * firing.
- * In that case, if we do not queue work to the worker thread,
- * the buffer will never be marked as complete - and therefore
- * not be returned to userpsace. As a result,
- * dequeue -> queue -> dequeue flow of uvc buffers will not
- * happen.
+ * Here we check whether any request is available in the ready
+ * list. If it is, queue it to the ep and add the current
+ * usb_request to the req_free list - for video_pump to fill in.
+ * Otherwise, just use the current usb_request to queue a 0
+ * length request to the ep. Since we always add to the req_free
+ * list if we dequeue from the ready list, there will never
+ * be a situation where the req_free list is completely out of
+ * requests and cannot recover.
*/
- queue_work(video->async_wq, &video->pump);
- }
- /*
- * Queue to the endpoint. The actual queueing to ep will
- * only happen on one thread - the async_wq for bulk endpoints
- * and this thread for isoc endpoints.
- */
- ret = uvcg_video_usb_req_queue(video, to_queue, !is_bulk);
- if (ret < 0) {
+ if (!list_empty(&video->req_ready)) {
+ req = list_first_entry(&video->req_ready,
+ struct usb_request, list);
+ } else {
+ if (list_empty(&video->req_free) ||
+ (atomic_read(&video->queued) > UVCG_REQ_MAX_ZERO_COUNT)) {
+ spin_unlock_irqrestore(&video->req_lock, flags);
+
+ return;
+ }
+ req = list_first_entry(&video->req_free, struct usb_request,
+ list);
+ req->length = 0;
+ }
+ list_del(&req->list);
+
/*
- * Endpoint error, but the stream is still enabled.
- * Put request back in req_free for it to be cleaned
- * up later.
+ * Queue to the endpoint. The actual queueing to ep will
+ * only happen on one thread - the async_wq for bulk endpoints
+ * and this thread for isoc endpoints.
*/
- list_add_tail(&to_queue->list, &video->req_free);
- }
+ ret = uvcg_video_usb_req_queue(video, req, !is_bulk);
+ if (ret < 0) {
+ /*
+ * Endpoint error, but the stream is still enabled.
+ * Put request back in req_free for it to be cleaned
+ * up later.
+ */
+ list_add_tail(&req->list, &video->req_free);
+ /*
+ * There is a new free request - wake up the pump.
+ */
+ queue_work(video->async_wq, &video->pump);
- spin_unlock_irqrestore(&video->req_lock, flags);
+ }
+
+ spin_unlock_irqrestore(&video->req_lock, flags);
+ }
}
static int
@@ -496,23 +491,71 @@ uvc_video_free_requests(struct uvc_video *video)
INIT_LIST_HEAD(&video->ureqs);
INIT_LIST_HEAD(&video->req_free);
INIT_LIST_HEAD(&video->req_ready);
- video->req_size = 0;
return 0;
}
+static void
+uvc_video_prep_requests(struct uvc_video *video)
+{
+ struct uvc_device *uvc = container_of(video, struct uvc_device, video);
+ struct usb_composite_dev *cdev = uvc->func.config->cdev;
+ unsigned int interval_duration = video->ep->desc->bInterval * 1250;
+ unsigned int max_req_size, req_size, header_size;
+ unsigned int nreq;
+
+ max_req_size = video->ep->maxpacket
+ * max_t(unsigned int, video->ep->maxburst, 1)
+ * (video->ep->mult);
+
+ if (!usb_endpoint_xfer_isoc(video->ep->desc)) {
+ video->req_size = max_req_size;
+ video->reqs_per_frame = video->uvc_num_requests =
+ DIV_ROUND_UP(video->imagesize, max_req_size);
+
+ return;
+ }
+
+ if (cdev->gadget->speed < USB_SPEED_HIGH)
+ interval_duration = video->ep->desc->bInterval * 10000;
+
+ nreq = DIV_ROUND_UP(video->interval, interval_duration);
+
+ header_size = nreq * UVCG_REQUEST_HEADER_LEN;
+
+ req_size = DIV_ROUND_UP(video->imagesize + header_size, nreq);
+
+ if (req_size > max_req_size) {
+ /* The prepared interval length and expected buffer size
+ * is not possible to stream with the currently configured
+ * isoc bandwidth. Fallback to the maximum.
+ */
+ req_size = max_req_size;
+ }
+ video->req_size = req_size;
+
+ /* We need to compensate the amount of requests to be
+ * allocated with the maximum amount of zero length requests.
+ * Since it is possible that hw_submit will initially
+ * enqueue some zero length requests and we then will not be
+ * able to fully encode one frame.
+ */
+ video->uvc_num_requests = nreq + UVCG_REQ_MAX_ZERO_COUNT;
+ video->reqs_per_frame = nreq;
+}
+
static int
uvc_video_alloc_requests(struct uvc_video *video)
{
struct uvc_request *ureq;
- unsigned int req_size;
unsigned int i;
int ret = -ENOMEM;
- BUG_ON(video->req_size);
-
- req_size = video->ep->maxpacket
- * max_t(unsigned int, video->ep->maxburst, 1)
- * (video->ep->mult);
+ /*
+ * calculate in uvc_video_prep_requests
+ * - video->uvc_num_requests
+ * - video->req_size
+ */
+ uvc_video_prep_requests(video);
for (i = 0; i < video->uvc_num_requests; i++) {
ureq = kzalloc(sizeof(struct uvc_request), GFP_KERNEL);
@@ -523,7 +566,7 @@ uvc_video_alloc_requests(struct uvc_video *video)
list_add_tail(&ureq->list, &video->ureqs);
- ureq->req_buffer = kmalloc(req_size, GFP_KERNEL);
+ ureq->req_buffer = kmalloc(video->req_size, GFP_KERNEL);
if (ureq->req_buffer == NULL)
goto error;
@@ -541,12 +584,10 @@ uvc_video_alloc_requests(struct uvc_video *video)
list_add_tail(&ureq->req->list, &video->req_free);
/* req_size/PAGE_SIZE + 1 for overruns and + 1 for header */
sg_alloc_table(&ureq->sgt,
- DIV_ROUND_UP(req_size - UVCG_REQUEST_HEADER_LEN,
+ DIV_ROUND_UP(video->req_size - UVCG_REQUEST_HEADER_LEN,
PAGE_SIZE) + 2, GFP_KERNEL);
}
- video->req_size = req_size;
-
return 0;
error:
@@ -699,7 +740,6 @@ uvcg_video_disable(struct uvc_video *video)
INIT_LIST_HEAD(&video->ureqs);
INIT_LIST_HEAD(&video->req_free);
INIT_LIST_HEAD(&video->req_ready);
- video->req_size = 0;
spin_unlock_irqrestore(&video->req_lock, flags);
/*
@@ -752,7 +792,9 @@ int uvcg_video_enable(struct uvc_video *video)
video->req_int_count = 0;
- uvc_video_ep_queue_initial_requests(video);
+ atomic_set(&video->queued, 0);
+
+ kthread_queue_work(video->kworker, &video->hw_submit);
queue_work(video->async_wq, &video->pump);
return ret;
@@ -775,12 +817,24 @@ int uvcg_video_init(struct uvc_video *video, struct uvc_device *uvc)
if (!video->async_wq)
return -EINVAL;
+ /* Allocate a kthread for asynchronous hw submit handler. */
+ video->kworker = kthread_create_worker(0, "UVCG");
+ if (IS_ERR(video->kworker)) {
+ uvcg_err(&video->uvc->func, "failed to create UVCG kworker\n");
+ return PTR_ERR(video->kworker);
+ }
+
+ kthread_init_work(&video->hw_submit, uvcg_video_hw_submit);
+
+ sched_set_fifo(video->kworker->task);
+
video->uvc = uvc;
video->fcc = V4L2_PIX_FMT_YUYV;
video->bpp = 16;
video->width = 320;
video->height = 240;
video->imagesize = 320 * 240 * 2;
+ video->interval = 666666;
/* Initialize the video buffers queue. */
uvcg_queue_init(&video->queue, uvc->v4l2_dev.dev->parent,
diff --git a/drivers/usb/gadget/legacy/hid.c b/drivers/usb/gadget/legacy/hid.c
index 4ca67b2f8f24..3684546e8801 100644
--- a/drivers/usb/gadget/legacy/hid.c
+++ b/drivers/usb/gadget/legacy/hid.c
@@ -261,7 +261,7 @@ static struct usb_composite_driver hidg_driver = {
};
static struct platform_driver hidg_plat_driver = {
- .remove_new = hidg_plat_driver_remove,
+ .remove = hidg_plat_driver_remove,
.driver = {
.name = "hidg",
},
diff --git a/drivers/usb/gadget/legacy/raw_gadget.c b/drivers/usb/gadget/legacy/raw_gadget.c
index 112fd18d8c99..20165e1582d9 100644
--- a/drivers/usb/gadget/legacy/raw_gadget.c
+++ b/drivers/usb/gadget/legacy/raw_gadget.c
@@ -782,7 +782,7 @@ static int raw_ioctl_ep0_read(struct raw_dev *dev, unsigned long value)
if (ret < 0)
goto free;
- length = min(io.length, (unsigned int)ret);
+ length = min_t(unsigned int, io.length, ret);
if (copy_to_user((void __user *)(value + sizeof(io)), data, length))
ret = -EFAULT;
else
@@ -1168,7 +1168,7 @@ static int raw_ioctl_ep_read(struct raw_dev *dev, unsigned long value)
if (ret < 0)
goto free;
- length = min(io.length, (unsigned int)ret);
+ length = min_t(unsigned int, io.length, ret);
if (copy_to_user((void __user *)(value + sizeof(io)), data, length))
ret = -EFAULT;
else
diff --git a/drivers/usb/gadget/udc/aspeed-vhub/core.c b/drivers/usb/gadget/udc/aspeed-vhub/core.c
index f60a019bb173..f2685f89b3e5 100644
--- a/drivers/usb/gadget/udc/aspeed-vhub/core.c
+++ b/drivers/usb/gadget/udc/aspeed-vhub/core.c
@@ -428,7 +428,7 @@ MODULE_DEVICE_TABLE(of, ast_vhub_dt_ids);
static struct platform_driver ast_vhub_driver = {
.probe = ast_vhub_probe,
- .remove_new = ast_vhub_remove,
+ .remove = ast_vhub_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = ast_vhub_dt_ids,
diff --git a/drivers/usb/gadget/udc/aspeed_udc.c b/drivers/usb/gadget/udc/aspeed_udc.c
index f4781e611aaa..353bfb1ff0a1 100644
--- a/drivers/usb/gadget/udc/aspeed_udc.c
+++ b/drivers/usb/gadget/udc/aspeed_udc.c
@@ -156,7 +156,7 @@
#define AST_EP_DMA_DESC_PID_DATA1 (2 << 14)
#define AST_EP_DMA_DESC_PID_MDATA (3 << 14)
#define EP_DESC1_IN_LEN(x) ((x) & 0x1fff)
-#define AST_EP_DMA_DESC_MAX_LEN (7680) /* Max packet length for trasmit in 1 desc */
+#define AST_EP_DMA_DESC_MAX_LEN (7680) /* Max packet length for transmit in 1 desc */
struct ast_udc_request {
struct usb_request req;
@@ -1590,7 +1590,7 @@ MODULE_DEVICE_TABLE(of, ast_udc_of_dt_ids);
static struct platform_driver ast_udc_driver = {
.probe = ast_udc_probe,
- .remove_new = ast_udc_remove,
+ .remove = ast_udc_remove,
.driver = {
.name = KBUILD_MODNAME,
.of_match_table = ast_udc_of_dt_ids,
diff --git a/drivers/usb/gadget/udc/at91_udc.c b/drivers/usb/gadget/udc/at91_udc.c
index e3bf17a98b38..e3af4ec3794e 100644
--- a/drivers/usb/gadget/udc/at91_udc.c
+++ b/drivers/usb/gadget/udc/at91_udc.c
@@ -2002,7 +2002,7 @@ static int at91udc_resume(struct platform_device *pdev)
static struct platform_driver at91_udc_driver = {
.probe = at91udc_probe,
- .remove_new = at91udc_remove,
+ .remove = at91udc_remove,
.shutdown = at91udc_shutdown,
.suspend = at91udc_suspend,
.resume = at91udc_resume,
diff --git a/drivers/usb/gadget/udc/atmel_usba_udc.c b/drivers/usb/gadget/udc/atmel_usba_udc.c
index 4928eba19327..0c6f2ad81d37 100644
--- a/drivers/usb/gadget/udc/atmel_usba_udc.c
+++ b/drivers/usb/gadget/udc/atmel_usba_udc.c
@@ -2444,7 +2444,7 @@ static SIMPLE_DEV_PM_OPS(usba_udc_pm_ops, usba_udc_suspend, usba_udc_resume);
static struct platform_driver udc_driver = {
.probe = usba_udc_probe,
- .remove_new = usba_udc_remove,
+ .remove = usba_udc_remove,
.driver = {
.name = "atmel_usba_udc",
.pm = &usba_udc_pm_ops,
diff --git a/drivers/usb/gadget/udc/bcm63xx_udc.c b/drivers/usb/gadget/udc/bcm63xx_udc.c
index da7011d906e0..502612a5650e 100644
--- a/drivers/usb/gadget/udc/bcm63xx_udc.c
+++ b/drivers/usb/gadget/udc/bcm63xx_udc.c
@@ -2367,7 +2367,7 @@ static void bcm63xx_udc_remove(struct platform_device *pdev)
static struct platform_driver bcm63xx_udc_driver = {
.probe = bcm63xx_udc_probe,
- .remove_new = bcm63xx_udc_remove,
+ .remove = bcm63xx_udc_remove,
.driver = {
.name = DRV_MODULE_NAME,
},
diff --git a/drivers/usb/gadget/udc/bdc/bdc_core.c b/drivers/usb/gadget/udc/bdc/bdc_core.c
index 5149e2b7f050..5c3d8b64c0e7 100644
--- a/drivers/usb/gadget/udc/bdc/bdc_core.c
+++ b/drivers/usb/gadget/udc/bdc/bdc_core.c
@@ -648,7 +648,7 @@ static struct platform_driver bdc_driver = {
.of_match_table = bdc_of_match,
},
.probe = bdc_probe,
- .remove_new = bdc_remove,
+ .remove = bdc_remove,
};
module_platform_driver(bdc_driver);
diff --git a/drivers/usb/gadget/udc/cdns2/cdns2-pci.c b/drivers/usb/gadget/udc/cdns2/cdns2-pci.c
index b1a8f772467c..e589593b4cbf 100644
--- a/drivers/usb/gadget/udc/cdns2/cdns2-pci.c
+++ b/drivers/usb/gadget/udc/cdns2/cdns2-pci.c
@@ -15,7 +15,6 @@
#include "cdns2-gadget.h"
#define PCI_DRIVER_NAME "cdns-pci-usbhs"
-#define PCI_DEVICE_ID_CDNS_USB2 0x0120
#define PCI_BAR_DEV 0
#define PCI_DEV_FN_DEVICE 0
@@ -113,7 +112,7 @@ static const struct dev_pm_ops cdns2_pci_pm_ops = {
};
static const struct pci_device_id cdns2_pci_ids[] = {
- { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USB2),
+ { PCI_DEVICE(PCI_VENDOR_ID_CDNS, PCI_DEVICE_ID_CDNS_USB),
.class = PCI_CLASS_SERIAL_USB_DEVICE },
{ 0, }
};
diff --git a/drivers/usb/gadget/udc/dummy_hcd.c b/drivers/usb/gadget/udc/dummy_hcd.c
index 081ac7683c0b..a7e8fa45776b 100644
--- a/drivers/usb/gadget/udc/dummy_hcd.c
+++ b/drivers/usb/gadget/udc/dummy_hcd.c
@@ -80,7 +80,7 @@ module_param_named(num, mod_data.num, uint, S_IRUGO);
MODULE_PARM_DESC(num, "number of emulated controllers");
/*-------------------------------------------------------------------------*/
-/* gadget side driver data structres */
+/* gadget side driver data structures */
struct dummy_ep {
struct list_head queue;
unsigned long last_io; /* jiffies timestamp */
@@ -1152,7 +1152,7 @@ static int dummy_udc_resume(struct platform_device *pdev)
static struct platform_driver dummy_udc_driver = {
.probe = dummy_udc_probe,
- .remove_new = dummy_udc_remove,
+ .remove = dummy_udc_remove,
.suspend = dummy_udc_suspend,
.resume = dummy_udc_resume,
.driver = {
@@ -2769,7 +2769,7 @@ static int dummy_hcd_resume(struct platform_device *pdev)
static struct platform_driver dummy_hcd_driver = {
.probe = dummy_hcd_probe,
- .remove_new = dummy_hcd_remove,
+ .remove = dummy_hcd_remove,
.suspend = dummy_hcd_suspend,
.resume = dummy_hcd_resume,
.driver = {
diff --git a/drivers/usb/gadget/udc/fsl_qe_udc.c b/drivers/usb/gadget/udc/fsl_qe_udc.c
index 4e88681a79b6..aacfde06387c 100644
--- a/drivers/usb/gadget/udc/fsl_qe_udc.c
+++ b/drivers/usb/gadget/udc/fsl_qe_udc.c
@@ -511,7 +511,7 @@ static int qe_ep_register_init(struct qe_udc *udc, unsigned char pipe_num)
out_8(&epparam->tbmr, rtfcr);
tmp = (u16)(ep->ep.maxpacket + USB_CRC_SIZE);
- /* MRBLR must be divisble by 4 */
+ /* MRBLR must be divisible by 4 */
tmp = (u16)(((tmp >> 2) << 2) + 4);
out_be16(&epparam->mrblr, tmp);
@@ -1413,7 +1413,7 @@ static int ep_txframe_handle(struct qe_ep *ep)
return 0;
}
-/* confirm the already trainsmited bd */
+/* confirm the already transmitted bd */
static int qe_ep_txconf(struct qe_ep *ep)
{
struct qe_bd __iomem *bd;
@@ -2196,7 +2196,7 @@ static int tx_irq(struct qe_udc *udc)
}
-/* setup packect's rx is handle in the function too */
+/* setup packet's rx is handle in the function too */
static void rx_irq(struct qe_udc *udc)
{
struct qe_ep *ep;
@@ -2704,7 +2704,7 @@ static struct platform_driver udc_driver = {
.of_match_table = qe_udc_match,
},
.probe = qe_udc_probe,
- .remove_new = qe_udc_remove,
+ .remove = qe_udc_remove,
#ifdef CONFIG_PM
.suspend = qe_udc_suspend,
.resume = qe_udc_resume,
diff --git a/drivers/usb/gadget/udc/fsl_udc_core.c b/drivers/usb/gadget/udc/fsl_udc_core.c
index 0cabd4eee6ac..8b7f7f961774 100644
--- a/drivers/usb/gadget/udc/fsl_udc_core.c
+++ b/drivers/usb/gadget/udc/fsl_udc_core.c
@@ -2685,7 +2685,7 @@ MODULE_DEVICE_TABLE(of, fsl_udc_dt_ids);
static struct platform_driver udc_driver = {
.probe = fsl_udc_probe,
- .remove_new = fsl_udc_remove,
+ .remove = fsl_udc_remove,
.id_table = fsl_udc_devtype,
/* these suspend and resume are not usb suspend and resume */
.suspend = fsl_udc_suspend,
diff --git a/drivers/usb/gadget/udc/fusb300_udc.c b/drivers/usb/gadget/udc/fusb300_udc.c
index 873265634ccc..5e94a99b3e53 100644
--- a/drivers/usb/gadget/udc/fusb300_udc.c
+++ b/drivers/usb/gadget/udc/fusb300_udc.c
@@ -1297,7 +1297,7 @@ static void init_controller(struct fusb300 *fusb300)
reg |= val;
iowrite32(reg, fusb300->reg + FUSB300_OFFSET_HSCR);
- /*set u1 u2 timmer*/
+ /*set u1 u2 timer*/
fusb300_set_u2_timeout(fusb300, 0xff);
fusb300_set_u1_timeout(fusb300, 0xff);
@@ -1507,7 +1507,7 @@ clean_up:
static struct platform_driver fusb300_driver = {
.probe = fusb300_probe,
- .remove_new = fusb300_remove,
+ .remove = fusb300_remove,
.driver = {
.name = udc_name,
},
diff --git a/drivers/usb/gadget/udc/gr_udc.c b/drivers/usb/gadget/udc/gr_udc.c
index fb901be5dac1..bf5b3c964c18 100644
--- a/drivers/usb/gadget/udc/gr_udc.c
+++ b/drivers/usb/gadget/udc/gr_udc.c
@@ -2249,7 +2249,7 @@ static struct platform_driver gr_driver = {
.of_match_table = gr_match,
},
.probe = gr_probe,
- .remove_new = gr_remove,
+ .remove = gr_remove,
};
module_platform_driver(gr_driver);
diff --git a/drivers/usb/gadget/udc/lpc32xx_udc.c b/drivers/usb/gadget/udc/lpc32xx_udc.c
index 3bfd889ed56a..89d6daf2bda7 100644
--- a/drivers/usb/gadget/udc/lpc32xx_udc.c
+++ b/drivers/usb/gadget/udc/lpc32xx_udc.c
@@ -3249,7 +3249,7 @@ MODULE_DEVICE_TABLE(of, lpc32xx_udc_of_match);
static struct platform_driver lpc32xx_udc_driver = {
.probe = lpc32xx_udc_probe,
- .remove_new = lpc32xx_udc_remove,
+ .remove = lpc32xx_udc_remove,
.shutdown = lpc32xx_udc_shutdown,
.suspend = lpc32xx_udc_suspend,
.resume = lpc32xx_udc_resume,
diff --git a/drivers/usb/gadget/udc/m66592-udc.c b/drivers/usb/gadget/udc/m66592-udc.c
index bfaa5291e6c8..a938b2af0944 100644
--- a/drivers/usb/gadget/udc/m66592-udc.c
+++ b/drivers/usb/gadget/udc/m66592-udc.c
@@ -1688,7 +1688,7 @@ clean_up:
/*-------------------------------------------------------------------------*/
static struct platform_driver m66592_driver = {
.probe = m66592_probe,
- .remove_new = m66592_remove,
+ .remove = m66592_remove,
.driver = {
.name = udc_name,
},
diff --git a/drivers/usb/gadget/udc/mv_u3d_core.c b/drivers/usb/gadget/udc/mv_u3d_core.c
index e1dd5cf25d08..062f43e146aa 100644
--- a/drivers/usb/gadget/udc/mv_u3d_core.c
+++ b/drivers/usb/gadget/udc/mv_u3d_core.c
@@ -2047,7 +2047,7 @@ static void mv_u3d_shutdown(struct platform_device *dev)
static struct platform_driver mv_u3d_driver = {
.probe = mv_u3d_probe,
- .remove_new = mv_u3d_remove,
+ .remove = mv_u3d_remove,
.shutdown = mv_u3d_shutdown,
.driver = {
.name = "mv-u3d",
diff --git a/drivers/usb/gadget/udc/mv_udc_core.c b/drivers/usb/gadget/udc/mv_udc_core.c
index 71012b282891..ff103e6b3048 100644
--- a/drivers/usb/gadget/udc/mv_udc_core.c
+++ b/drivers/usb/gadget/udc/mv_udc_core.c
@@ -2409,7 +2409,7 @@ static void mv_udc_shutdown(struct platform_device *pdev)
static struct platform_driver udc_driver = {
.probe = mv_udc_probe,
- .remove_new = mv_udc_remove,
+ .remove = mv_udc_remove,
.shutdown = mv_udc_shutdown,
.driver = {
.name = "mv-udc",
diff --git a/drivers/usb/gadget/udc/net2272.c b/drivers/usb/gadget/udc/net2272.c
index 9230db57dab7..7ecddbf5c90d 100644
--- a/drivers/usb/gadget/udc/net2272.c
+++ b/drivers/usb/gadget/udc/net2272.c
@@ -2097,7 +2097,7 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
}
/* check dma interrupts */
#endif
- /* Platform/devcice interrupt handler */
+ /* Platform/device interrupt handler */
#if !defined(PLX_PCI_RDK)
net2272_handle_stat1_irqs(dev, net2272_read(dev, IRQSTAT1));
net2272_handle_stat0_irqs(dev, net2272_read(dev, IRQSTAT0));
@@ -2685,7 +2685,7 @@ net2272_plat_remove(struct platform_device *pdev)
static struct platform_driver net2272_plat_driver = {
.probe = net2272_plat_probe,
- .remove_new = net2272_plat_remove,
+ .remove = net2272_plat_remove,
.driver = {
.name = driver_name,
},
diff --git a/drivers/usb/gadget/udc/omap_udc.c b/drivers/usb/gadget/udc/omap_udc.c
index 61a45e4657d5..698463bf697b 100644
--- a/drivers/usb/gadget/udc/omap_udc.c
+++ b/drivers/usb/gadget/udc/omap_udc.c
@@ -576,13 +576,13 @@ static void finish_in_dma(struct omap_ep *ep, struct omap_req *req, int status)
static void next_out_dma(struct omap_ep *ep, struct omap_req *req)
{
- unsigned packets = req->req.length - req->req.actual;
+ unsigned int packets = req->req.length - req->req.actual;
int dma_trigger = 0;
u16 w;
/* set up this DMA transfer, enable the fifo, start */
packets /= ep->ep.maxpacket;
- packets = min(packets, (unsigned)UDC_RXN_TC + 1);
+ packets = min_t(unsigned int, packets, UDC_RXN_TC + 1);
req->dma_bytes = packets * ep->ep.maxpacket;
omap_set_dma_transfer_params(ep->lch, OMAP_DMA_DATA_TYPE_S16,
ep->ep.maxpacket >> 1, packets,
@@ -2980,7 +2980,7 @@ static int omap_udc_resume(struct platform_device *dev)
static struct platform_driver udc_driver = {
.probe = omap_udc_probe,
- .remove_new = omap_udc_remove,
+ .remove = omap_udc_remove,
.suspend = omap_udc_suspend,
.resume = omap_udc_resume,
.driver = {
diff --git a/drivers/usb/gadget/udc/pxa25x_udc.c b/drivers/usb/gadget/udc/pxa25x_udc.c
index 7c96fc9f680f..1e9998024aaa 100644
--- a/drivers/usb/gadget/udc/pxa25x_udc.c
+++ b/drivers/usb/gadget/udc/pxa25x_udc.c
@@ -2474,7 +2474,7 @@ static int pxa25x_udc_resume(struct platform_device *dev)
static struct platform_driver udc_driver = {
.shutdown = pxa25x_udc_shutdown,
.probe = pxa25x_udc_probe,
- .remove_new = pxa25x_udc_remove,
+ .remove = pxa25x_udc_remove,
.suspend = pxa25x_udc_suspend,
.resume = pxa25x_udc_resume,
.driver = {
diff --git a/drivers/usb/gadget/udc/pxa27x_udc.c b/drivers/usb/gadget/udc/pxa27x_udc.c
index ea79f85f8e0b..f9a55d4f189f 100644
--- a/drivers/usb/gadget/udc/pxa27x_udc.c
+++ b/drivers/usb/gadget/udc/pxa27x_udc.c
@@ -2539,7 +2539,7 @@ static struct platform_driver udc_driver = {
.of_match_table = of_match_ptr(udc_pxa_dt_ids),
},
.probe = pxa_udc_probe,
- .remove_new = pxa_udc_remove,
+ .remove = pxa_udc_remove,
.shutdown = pxa_udc_shutdown,
#ifdef CONFIG_PM
.suspend = pxa_udc_suspend,
diff --git a/drivers/usb/gadget/udc/r8a66597-udc.c b/drivers/usb/gadget/udc/r8a66597-udc.c
index db4a10a979f9..ff6f846b1d41 100644
--- a/drivers/usb/gadget/udc/r8a66597-udc.c
+++ b/drivers/usb/gadget/udc/r8a66597-udc.c
@@ -1965,7 +1965,7 @@ clean_up2:
/*-------------------------------------------------------------------------*/
static struct platform_driver r8a66597_driver = {
.probe = r8a66597_probe,
- .remove_new = r8a66597_remove,
+ .remove = r8a66597_remove,
.driver = {
.name = udc_name,
},
diff --git a/drivers/usb/gadget/udc/renesas_usb3.c b/drivers/usb/gadget/udc/renesas_usb3.c
index 3b01734ce1b7..fce5c41d9f29 100644
--- a/drivers/usb/gadget/udc/renesas_usb3.c
+++ b/drivers/usb/gadget/udc/renesas_usb3.c
@@ -3013,7 +3013,7 @@ static SIMPLE_DEV_PM_OPS(renesas_usb3_pm_ops, renesas_usb3_suspend,
static struct platform_driver renesas_usb3_driver = {
.probe = renesas_usb3_probe,
- .remove_new = renesas_usb3_remove,
+ .remove = renesas_usb3_remove,
.driver = {
.name = udc_name,
.pm = &renesas_usb3_pm_ops,
diff --git a/drivers/usb/gadget/udc/renesas_usbf.c b/drivers/usb/gadget/udc/renesas_usbf.c
index 657f265ac7cc..14f4b2cf05a4 100644
--- a/drivers/usb/gadget/udc/renesas_usbf.c
+++ b/drivers/usb/gadget/udc/renesas_usbf.c
@@ -2482,7 +2482,7 @@ static int usbf_handle_ep0_setup(struct usbf_ep *ep0)
ep0->delayed_status = 0;
if ((crq.ctrlreq.bRequestType & USB_TYPE_MASK) != USB_TYPE_STANDARD) {
- /* This is not a USB standard request -> delelate */
+ /* This is not a USB standard request -> delegate */
goto delegate;
}
@@ -3381,7 +3381,7 @@ static struct platform_driver udc_driver = {
.of_match_table = usbf_match,
},
.probe = usbf_probe,
- .remove_new = usbf_remove,
+ .remove = usbf_remove,
};
module_platform_driver(udc_driver);
diff --git a/drivers/usb/gadget/udc/rzv2m_usb3drd.c b/drivers/usb/gadget/udc/rzv2m_usb3drd.c
index 36f4ff00d22f..4692eae89f44 100644
--- a/drivers/usb/gadget/udc/rzv2m_usb3drd.c
+++ b/drivers/usb/gadget/udc/rzv2m_usb3drd.c
@@ -127,7 +127,7 @@ static struct platform_driver rzv2m_usb3drd_driver = {
.of_match_table = rzv2m_usb3drd_of_match,
},
.probe = rzv2m_usb3drd_probe,
- .remove_new = rzv2m_usb3drd_remove,
+ .remove = rzv2m_usb3drd_remove,
};
module_platform_driver(rzv2m_usb3drd_driver);
diff --git a/drivers/usb/gadget/udc/snps_udc_core.c b/drivers/usb/gadget/udc/snps_udc_core.c
index cd89532adec2..1f8a99d2a643 100644
--- a/drivers/usb/gadget/udc/snps_udc_core.c
+++ b/drivers/usb/gadget/udc/snps_udc_core.c
@@ -2707,7 +2707,7 @@ static irqreturn_t udc_control_in_isr(struct udc *dev)
/* write fifo */
udc_txfifo_write(ep, &req->req);
- /* lengh bytes transferred */
+ /* length bytes transferred */
len = req->req.length - req->req.actual;
if (len > ep->ep.maxpacket)
len = ep->ep.maxpacket;
diff --git a/drivers/usb/gadget/udc/snps_udc_plat.c b/drivers/usb/gadget/udc/snps_udc_plat.c
index ba5a06690507..db842a6de643 100644
--- a/drivers/usb/gadget/udc/snps_udc_plat.c
+++ b/drivers/usb/gadget/udc/snps_udc_plat.c
@@ -309,7 +309,7 @@ MODULE_DEVICE_TABLE(of, of_udc_match);
static struct platform_driver udc_plat_driver = {
.probe = udc_plat_probe,
- .remove_new = udc_plat_remove,
+ .remove = udc_plat_remove,
.driver = {
.name = "snps-udc-plat",
.of_match_table = of_udc_match,
diff --git a/drivers/usb/gadget/udc/tegra-xudc.c b/drivers/usb/gadget/udc/tegra-xudc.c
index 7aa46d426f31..c7fdbc55fb0b 100644
--- a/drivers/usb/gadget/udc/tegra-xudc.c
+++ b/drivers/usb/gadget/udc/tegra-xudc.c
@@ -4071,7 +4071,7 @@ static const struct dev_pm_ops tegra_xudc_pm_ops = {
static struct platform_driver tegra_xudc_driver = {
.probe = tegra_xudc_probe,
- .remove_new = tegra_xudc_remove,
+ .remove = tegra_xudc_remove,
.driver = {
.name = "tegra-xudc",
.pm = &tegra_xudc_pm_ops,
diff --git a/drivers/usb/gadget/udc/udc-xilinx.c b/drivers/usb/gadget/udc/udc-xilinx.c
index ebc45565c33e..ae2aeb271897 100644
--- a/drivers/usb/gadget/udc/udc-xilinx.c
+++ b/drivers/usb/gadget/udc/udc-xilinx.c
@@ -2258,7 +2258,7 @@ static struct platform_driver xudc_driver = {
.pm = &xudc_pm_ops,
},
.probe = xudc_probe,
- .remove_new = xudc_remove,
+ .remove = xudc_remove,
};
module_platform_driver(xudc_driver);
diff --git a/drivers/usb/gadget/usbstring.c b/drivers/usb/gadget/usbstring.c
index 75f6f99f8173..37a2f1b61cba 100644
--- a/drivers/usb/gadget/usbstring.c
+++ b/drivers/usb/gadget/usbstring.c
@@ -55,7 +55,7 @@ usb_gadget_get_string (const struct usb_gadget_strings *table, int id, u8 *buf)
return -EINVAL;
/* string descriptors have length, tag, then UTF16-LE text */
- len = min((size_t)USB_MAX_STRING_LEN, strlen(s->s));
+ len = min_t(size_t, USB_MAX_STRING_LEN, strlen(s->s));
len = utf8s_to_utf16s(s->s, len, UTF16_LITTLE_ENDIAN,
(wchar_t *) &buf[2], USB_MAX_STRING_LEN);
if (len < 0)
diff --git a/drivers/usb/host/bcma-hcd.c b/drivers/usb/host/bcma-hcd.c
index 7558cc4d90cc..519386255886 100644
--- a/drivers/usb/host/bcma-hcd.c
+++ b/drivers/usb/host/bcma-hcd.c
@@ -25,7 +25,6 @@
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/of.h>
-#include <linux/of_gpio.h>
#include <linux/of_platform.h>
#include <linux/usb/ehci_pdriver.h>
#include <linux/usb/ohci_pdriver.h>
diff --git a/drivers/usb/host/ehci-atmel.c b/drivers/usb/host/ehci-atmel.c
index 6a6e1c510b28..65747270fd88 100644
--- a/drivers/usb/host/ehci-atmel.c
+++ b/drivers/usb/host/ehci-atmel.c
@@ -220,7 +220,7 @@ static SIMPLE_DEV_PM_OPS(ehci_atmel_pm_ops, ehci_atmel_drv_suspend,
static struct platform_driver ehci_atmel_driver = {
.probe = ehci_atmel_drv_probe,
- .remove_new = ehci_atmel_drv_remove,
+ .remove = ehci_atmel_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "atmel-ehci",
diff --git a/drivers/usb/host/ehci-brcm.c b/drivers/usb/host/ehci-brcm.c
index 68cad0620f1a..888e8f6670d2 100644
--- a/drivers/usb/host/ehci-brcm.c
+++ b/drivers/usb/host/ehci-brcm.c
@@ -250,7 +250,7 @@ MODULE_DEVICE_TABLE(of, brcm_ehci_of_match);
static struct platform_driver ehci_brcm_driver = {
.probe = ehci_brcm_probe,
- .remove_new = ehci_brcm_remove,
+ .remove = ehci_brcm_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ehci-brcm",
diff --git a/drivers/usb/host/ehci-exynos.c b/drivers/usb/host/ehci-exynos.c
index e3a961d3f5fc..d2a5bedf736a 100644
--- a/drivers/usb/host/ehci-exynos.c
+++ b/drivers/usb/host/ehci-exynos.c
@@ -288,7 +288,7 @@ MODULE_DEVICE_TABLE(of, exynos_ehci_match);
static struct platform_driver exynos_ehci_driver = {
.probe = exynos_ehci_probe,
- .remove_new = exynos_ehci_remove,
+ .remove = exynos_ehci_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "exynos-ehci",
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 5b1ce394a417..26f13278d4d6 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -706,7 +706,7 @@ static void fsl_ehci_drv_remove(struct platform_device *pdev)
static struct platform_driver ehci_fsl_driver = {
.probe = fsl_ehci_drv_probe,
- .remove_new = fsl_ehci_drv_remove,
+ .remove = fsl_ehci_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/usb/host/ehci-grlib.c b/drivers/usb/host/ehci-grlib.c
index 14150e4d3382..bd9762eaa135 100644
--- a/drivers/usb/host/ehci-grlib.c
+++ b/drivers/usb/host/ehci-grlib.c
@@ -168,7 +168,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_grlib_of_match);
static struct platform_driver ehci_grlib_driver = {
.probe = ehci_hcd_grlib_probe,
- .remove_new = ehci_hcd_grlib_remove,
+ .remove = ehci_hcd_grlib_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "grlib-ehci",
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index cbc0b86fcc36..6de79ac5e6a4 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -547,7 +547,7 @@ static int ehci_init(struct usb_hcd *hcd)
* make problems: throughput reduction (!), data errors...
*/
if (park) {
- park = min(park, (unsigned) 3);
+ park = min_t(unsigned int, park, 3);
temp |= CMD_PARK;
temp |= park << 8;
}
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index 2f1fc7eb8b72..cbabbe107172 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -279,7 +279,7 @@ static const struct of_device_id ehci_mv_dt_ids[] = {
static struct platform_driver ehci_mv_driver = {
.probe = mv_ehci_probe,
- .remove_new = mv_ehci_remove,
+ .remove = mv_ehci_remove,
.shutdown = mv_ehci_shutdown,
.driver = {
.name = "mv-ehci",
diff --git a/drivers/usb/host/ehci-npcm7xx.c b/drivers/usb/host/ehci-npcm7xx.c
index 3d3317a1a0b3..f1c7034c1e80 100644
--- a/drivers/usb/host/ehci-npcm7xx.c
+++ b/drivers/usb/host/ehci-npcm7xx.c
@@ -122,7 +122,7 @@ MODULE_DEVICE_TABLE(of, npcm7xx_ehci_id_table);
static struct platform_driver npcm7xx_ehci_hcd_driver = {
.probe = npcm7xx_ehci_hcd_drv_probe,
- .remove_new = npcm7xx_ehci_hcd_drv_remove,
+ .remove = npcm7xx_ehci_hcd_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "npcm7xx-ehci",
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index b24f371a46f3..db4a1acb27da 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -264,7 +264,7 @@ MODULE_DEVICE_TABLE(of, omap_ehci_dt_ids);
static struct platform_driver ehci_hcd_omap_driver = {
.probe = ehci_hcd_omap_probe,
- .remove_new = ehci_hcd_omap_remove,
+ .remove = ehci_hcd_omap_remove,
.shutdown = usb_hcd_platform_shutdown,
/*.suspend = ehci_hcd_omap_suspend, */
/*.resume = ehci_hcd_omap_resume, */
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index ad145a54ca74..34abff8669f8 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -352,7 +352,7 @@ MODULE_DEVICE_TABLE(of, ehci_orion_dt_ids);
static struct platform_driver ehci_orion_driver = {
.probe = ehci_orion_drv_probe,
- .remove_new = ehci_orion_drv_remove,
+ .remove = ehci_orion_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "orion-ehci",
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index 98b073185e1c..cdf41886e8ca 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -508,7 +508,7 @@ static SIMPLE_DEV_PM_OPS(ehci_platform_pm_ops, ehci_platform_suspend,
static struct platform_driver ehci_platform_driver = {
.id_table = ehci_platform_table,
.probe = ehci_platform_probe,
- .remove_new = ehci_platform_remove,
+ .remove = ehci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ehci-platform",
diff --git a/drivers/usb/host/ehci-ppc-of.c b/drivers/usb/host/ehci-ppc-of.c
index 7fd83e806ae4..8063b9d3aebd 100644
--- a/drivers/usb/host/ehci-ppc-of.c
+++ b/drivers/usb/host/ehci-ppc-of.c
@@ -230,7 +230,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_ppc_of_match);
static struct platform_driver ehci_hcd_ppc_of_driver = {
.probe = ehci_hcd_ppc_of_probe,
- .remove_new = ehci_hcd_ppc_of_remove,
+ .remove = ehci_hcd_ppc_of_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ppc-of-ehci",
diff --git a/drivers/usb/host/ehci-sh.c b/drivers/usb/host/ehci-sh.c
index d31d9506e41a..2d23690d72c5 100644
--- a/drivers/usb/host/ehci-sh.c
+++ b/drivers/usb/host/ehci-sh.c
@@ -119,8 +119,12 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
if (IS_ERR(priv->iclk))
priv->iclk = NULL;
- clk_enable(priv->fclk);
- clk_enable(priv->iclk);
+ ret = clk_enable(priv->fclk);
+ if (ret)
+ goto fail_request_resource;
+ ret = clk_enable(priv->iclk);
+ if (ret)
+ goto fail_iclk;
ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (ret != 0) {
@@ -136,6 +140,7 @@ static int ehci_hcd_sh_probe(struct platform_device *pdev)
fail_add_hcd:
clk_disable(priv->iclk);
+fail_iclk:
clk_disable(priv->fclk);
fail_request_resource:
@@ -169,7 +174,7 @@ static void ehci_hcd_sh_shutdown(struct platform_device *pdev)
static struct platform_driver ehci_hcd_sh_driver = {
.probe = ehci_hcd_sh_probe,
- .remove_new = ehci_hcd_sh_remove,
+ .remove = ehci_hcd_sh_remove,
.shutdown = ehci_hcd_sh_shutdown,
.driver = {
.name = "sh_ehci",
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index d0e94e4c9fe2..e96710192d6b 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -105,7 +105,9 @@ static int spear_ehci_hcd_drv_probe(struct platform_device *pdev)
/* registers start at offset 0x0 */
hcd_to_ehci(hcd)->caps = hcd->regs;
- clk_prepare_enable(sehci->clk);
+ retval = clk_prepare_enable(sehci->clk);
+ if (retval)
+ goto err_put_hcd;
retval = usb_add_hcd(hcd, irq, IRQF_SHARED);
if (retval)
goto err_stop_ehci;
@@ -130,8 +132,7 @@ static void spear_ehci_hcd_drv_remove(struct platform_device *pdev)
usb_remove_hcd(hcd);
- if (sehci->clk)
- clk_disable_unprepare(sehci->clk);
+ clk_disable_unprepare(sehci->clk);
usb_put_hcd(hcd);
}
@@ -143,7 +144,7 @@ MODULE_DEVICE_TABLE(of, spear_ehci_id_table);
static struct platform_driver spear_ehci_hcd_driver = {
.probe = spear_ehci_hcd_drv_probe,
- .remove_new = spear_ehci_hcd_drv_remove,
+ .remove = spear_ehci_hcd_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "spear-ehci",
diff --git a/drivers/usb/host/ehci-st.c b/drivers/usb/host/ehci-st.c
index 2dbb0d86daaa..58867d816af7 100644
--- a/drivers/usb/host/ehci-st.c
+++ b/drivers/usb/host/ehci-st.c
@@ -320,7 +320,7 @@ MODULE_DEVICE_TABLE(of, st_ehci_ids);
static struct platform_driver ehci_platform_driver = {
.probe = st_ehci_platform_probe,
- .remove_new = st_ehci_platform_remove,
+ .remove = st_ehci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "st-ehci",
diff --git a/drivers/usb/host/ehci-xilinx-of.c b/drivers/usb/host/ehci-xilinx-of.c
index a2112c28f631..1d16cfefabd7 100644
--- a/drivers/usb/host/ehci-xilinx-of.c
+++ b/drivers/usb/host/ehci-xilinx-of.c
@@ -220,7 +220,7 @@ MODULE_DEVICE_TABLE(of, ehci_hcd_xilinx_of_match);
static struct platform_driver ehci_hcd_xilinx_of_driver = {
.probe = ehci_hcd_xilinx_of_probe,
- .remove_new = ehci_hcd_xilinx_of_remove,
+ .remove = ehci_hcd_xilinx_of_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "xilinx-of-ehci",
diff --git a/drivers/usb/host/fhci-hcd.c b/drivers/usb/host/fhci-hcd.c
index 9a1b5224f239..22a0942f0bce 100644
--- a/drivers/usb/host/fhci-hcd.c
+++ b/drivers/usb/host/fhci-hcd.c
@@ -791,7 +791,7 @@ static struct platform_driver of_fhci_driver = {
.of_match_table = of_fhci_match,
},
.probe = of_fhci_probe,
- .remove_new = of_fhci_remove,
+ .remove = of_fhci_remove,
};
module_platform_driver(of_fhci_driver);
diff --git a/drivers/usb/host/fhci-sched.c b/drivers/usb/host/fhci-sched.c
index a45ede80edfc..c3acd410ce94 100644
--- a/drivers/usb/host/fhci-sched.c
+++ b/drivers/usb/host/fhci-sched.c
@@ -158,7 +158,7 @@ static int add_packet(struct fhci_usb *usb, struct ed *ed, struct td *td)
struct packet *pkt;
u8 *data = NULL;
- /* calcalate data address,len and toggle and then add the transaction */
+ /* calculate data address,len and toggle and then add the transaction */
if (td->toggle == USB_TD_TOGGLE_CARRY)
td->toggle = ed->toggle_carry;
@@ -679,7 +679,7 @@ static void process_done_list(unsigned long data)
DECLARE_TASKLET_OLD(fhci_tasklet, process_done_list);
-/* transfer complted callback */
+/* transfer completed callback */
u32 fhci_transfer_confirm_callback(struct fhci_hcd *fhci)
{
if (!fhci->process_done_task->state)
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 6cdc3d805c32..4e67b9471986 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -362,7 +362,7 @@ static struct platform_driver fsl_usb2_mph_dr_driver = {
.of_match_table = fsl_usb2_mph_dr_of_match,
},
.probe = fsl_usb2_mph_dr_of_probe,
- .remove_new = fsl_usb2_mph_dr_of_remove,
+ .remove = fsl_usb2_mph_dr_of_remove,
};
module_platform_driver(fsl_usb2_mph_dr_driver);
diff --git a/drivers/usb/host/isp116x-hcd.c b/drivers/usb/host/isp116x-hcd.c
index a82d8926e922..71c22c4bd163 100644
--- a/drivers/usb/host/isp116x-hcd.c
+++ b/drivers/usb/host/isp116x-hcd.c
@@ -1684,7 +1684,7 @@ MODULE_ALIAS("platform:isp116x-hcd");
static struct platform_driver isp116x_driver = {
.probe = isp116x_probe,
- .remove_new = isp116x_remove,
+ .remove = isp116x_remove,
.suspend = isp116x_suspend,
.resume = isp116x_resume,
.driver = {
diff --git a/drivers/usb/host/isp1362-hcd.c b/drivers/usb/host/isp1362-hcd.c
index 31059c8f94e6..2d3a082cb52f 100644
--- a/drivers/usb/host/isp1362-hcd.c
+++ b/drivers/usb/host/isp1362-hcd.c
@@ -2757,7 +2757,7 @@ static int isp1362_resume(struct platform_device *pdev)
static struct platform_driver isp1362_driver = {
.probe = isp1362_probe,
- .remove_new = isp1362_remove,
+ .remove = isp1362_remove,
.suspend = isp1362_suspend,
.resume = isp1362_resume,
diff --git a/drivers/usb/host/max3421-hcd.c b/drivers/usb/host/max3421-hcd.c
index 9fe4f48b1898..0881fdd1823e 100644
--- a/drivers/usb/host/max3421-hcd.c
+++ b/drivers/usb/host/max3421-hcd.c
@@ -779,11 +779,17 @@ max3421_check_unlink(struct usb_hcd *hcd)
retval = 1;
dev_dbg(&spi->dev, "%s: URB %p unlinked=%d",
__func__, urb, urb->unlinked);
- usb_hcd_unlink_urb_from_ep(hcd, urb);
- spin_unlock_irqrestore(&max3421_hcd->lock,
- flags);
- usb_hcd_giveback_urb(hcd, urb, 0);
- spin_lock_irqsave(&max3421_hcd->lock, flags);
+ if (urb == max3421_hcd->curr_urb) {
+ max3421_hcd->urb_done = 1;
+ max3421_hcd->hien &= ~(BIT(MAX3421_HI_HXFRDN_BIT) |
+ BIT(MAX3421_HI_RCVDAV_BIT));
+ } else {
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+ spin_unlock_irqrestore(&max3421_hcd->lock,
+ flags);
+ usb_hcd_giveback_urb(hcd, urb, 0);
+ spin_lock_irqsave(&max3421_hcd->lock, flags);
+ }
}
}
}
diff --git a/drivers/usb/host/octeon-hcd.c b/drivers/usb/host/octeon-hcd.c
index 19d5777f5db2..361d33b0c4d2 100644
--- a/drivers/usb/host/octeon-hcd.c
+++ b/drivers/usb/host/octeon-hcd.c
@@ -3346,7 +3346,7 @@ static int octeon_usb_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
break;
case USB_PORT_FEAT_INDICATOR:
dev_dbg(dev, " INDICATOR\n");
- /* Port inidicator not supported */
+ /* Port indicator not supported */
break;
case USB_PORT_FEAT_C_CONNECTION:
dev_dbg(dev, " C_CONNECTION\n");
@@ -3711,8 +3711,8 @@ static struct platform_driver octeon_usb_driver = {
.name = "octeon-hcd",
.of_match_table = octeon_usb_match,
},
- .probe = octeon_usb_probe,
- .remove_new = octeon_usb_remove,
+ .probe = octeon_usb_probe,
+ .remove = octeon_usb_remove,
};
static int __init octeon_usb_driver_init(void)
diff --git a/drivers/usb/host/ohci-at91.c b/drivers/usb/host/ohci-at91.c
index f691cd98a574..5df793dcb25d 100644
--- a/drivers/usb/host/ohci-at91.c
+++ b/drivers/usb/host/ohci-at91.c
@@ -685,7 +685,7 @@ static SIMPLE_DEV_PM_OPS(ohci_hcd_at91_pm_ops, ohci_hcd_at91_drv_suspend,
static struct platform_driver ohci_hcd_at91_driver = {
.probe = ohci_hcd_at91_drv_probe,
- .remove_new = ohci_hcd_at91_drv_remove,
+ .remove = ohci_hcd_at91_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "at91_ohci",
diff --git a/drivers/usb/host/ohci-da8xx.c b/drivers/usb/host/ohci-da8xx.c
index d2b67da76762..3c5ca2d7c92e 100644
--- a/drivers/usb/host/ohci-da8xx.c
+++ b/drivers/usb/host/ohci-da8xx.c
@@ -531,7 +531,7 @@ static const struct ohci_driver_overrides da8xx_overrides __initconst = {
*/
static struct platform_driver ohci_hcd_da8xx_driver = {
.probe = ohci_da8xx_probe,
- .remove_new = ohci_da8xx_remove,
+ .remove = ohci_da8xx_remove,
.shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_da8xx_suspend,
diff --git a/drivers/usb/host/ohci-exynos.c b/drivers/usb/host/ohci-exynos.c
index 1379e03644b2..cc5cb0900988 100644
--- a/drivers/usb/host/ohci-exynos.c
+++ b/drivers/usb/host/ohci-exynos.c
@@ -262,7 +262,7 @@ MODULE_DEVICE_TABLE(of, exynos_ohci_match);
static struct platform_driver exynos_ohci_driver = {
.probe = exynos_ohci_probe,
- .remove_new = exynos_ohci_remove,
+ .remove = exynos_ohci_remove,
.shutdown = exynos_ohci_shutdown,
.driver = {
.name = "exynos-ohci",
diff --git a/drivers/usb/host/ohci-nxp.c b/drivers/usb/host/ohci-nxp.c
index 5b775e1ea527..24d5a1dc5056 100644
--- a/drivers/usb/host/ohci-nxp.c
+++ b/drivers/usb/host/ohci-nxp.c
@@ -254,7 +254,7 @@ static struct platform_driver ohci_hcd_nxp_driver = {
.of_match_table = of_match_ptr(ohci_hcd_nxp_match),
},
.probe = ohci_hcd_nxp_probe,
- .remove_new = ohci_hcd_nxp_remove,
+ .remove = ohci_hcd_nxp_remove,
};
static int __init ohci_nxp_init(void)
diff --git a/drivers/usb/host/ohci-omap.c b/drivers/usb/host/ohci-omap.c
index 21a6f6c55e07..f6e56c4b9914 100644
--- a/drivers/usb/host/ohci-omap.c
+++ b/drivers/usb/host/ohci-omap.c
@@ -152,7 +152,7 @@ static int ohci_omap_reset(struct usb_hcd *hcd)
rh &= ~RH_A_NOCP;
- /* gpio9 for overcurrent detction */
+ /* gpio9 for overcurrent detection */
omap_cfg_reg(W8_1610_GPIO9);
/* for paranoia's sake: disable USB.PUEN */
@@ -390,7 +390,7 @@ static int ohci_omap_resume(struct platform_device *dev)
*/
static struct platform_driver ohci_hcd_omap_driver = {
.probe = ohci_hcd_omap_probe,
- .remove_new = ohci_hcd_omap_remove,
+ .remove = ohci_hcd_omap_remove,
.shutdown = usb_hcd_platform_shutdown,
#ifdef CONFIG_PM
.suspend = ohci_omap_suspend,
diff --git a/drivers/usb/host/ohci-platform.c b/drivers/usb/host/ohci-platform.c
index 4a75507325dd..f47ae12cde6a 100644
--- a/drivers/usb/host/ohci-platform.c
+++ b/drivers/usb/host/ohci-platform.c
@@ -344,7 +344,7 @@ static const struct dev_pm_ops ohci_platform_pm_ops = {
static struct platform_driver ohci_platform_driver = {
.id_table = ohci_platform_table,
.probe = ohci_platform_probe,
- .remove_new = ohci_platform_remove,
+ .remove = ohci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ohci-platform",
diff --git a/drivers/usb/host/ohci-ppc-of.c b/drivers/usb/host/ohci-ppc-of.c
index a6be061f8653..acd0a0e398a4 100644
--- a/drivers/usb/host/ohci-ppc-of.c
+++ b/drivers/usb/host/ohci-ppc-of.c
@@ -219,7 +219,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_ppc_of_match);
static struct platform_driver ohci_hcd_ppc_of_driver = {
.probe = ohci_hcd_ppc_of_probe,
- .remove_new = ohci_hcd_ppc_of_remove,
+ .remove = ohci_hcd_ppc_of_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "ppc-of-ohci",
diff --git a/drivers/usb/host/ohci-pxa27x.c b/drivers/usb/host/ohci-pxa27x.c
index 3348c25ddb18..45d026e85168 100644
--- a/drivers/usb/host/ohci-pxa27x.c
+++ b/drivers/usb/host/ohci-pxa27x.c
@@ -569,7 +569,7 @@ static const struct dev_pm_ops ohci_hcd_pxa27x_pm_ops = {
static struct platform_driver ohci_hcd_pxa27x_driver = {
.probe = ohci_hcd_pxa27x_probe,
- .remove_new = ohci_hcd_pxa27x_remove,
+ .remove = ohci_hcd_pxa27x_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "pxa27x-ohci",
diff --git a/drivers/usb/host/ohci-s3c2410.c b/drivers/usb/host/ohci-s3c2410.c
index c5c9b4cbcb9a..66d970854357 100644
--- a/drivers/usb/host/ohci-s3c2410.c
+++ b/drivers/usb/host/ohci-s3c2410.c
@@ -457,7 +457,7 @@ MODULE_DEVICE_TABLE(of, ohci_hcd_s3c2410_dt_ids);
static struct platform_driver ohci_hcd_s3c2410_driver = {
.probe = ohci_hcd_s3c2410_probe,
- .remove_new = ohci_hcd_s3c2410_remove,
+ .remove = ohci_hcd_s3c2410_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "s3c2410-ohci",
diff --git a/drivers/usb/host/ohci-sm501.c b/drivers/usb/host/ohci-sm501.c
index 4b39e9d6f33a..843a5378764e 100644
--- a/drivers/usb/host/ohci-sm501.c
+++ b/drivers/usb/host/ohci-sm501.c
@@ -252,7 +252,7 @@ static int ohci_sm501_resume(struct platform_device *pdev)
*/
static struct platform_driver ohci_hcd_sm501_driver = {
.probe = ohci_hcd_sm501_drv_probe,
- .remove_new = ohci_hcd_sm501_drv_remove,
+ .remove = ohci_hcd_sm501_drv_remove,
.shutdown = usb_hcd_platform_shutdown,
.suspend = ohci_sm501_suspend,
.resume = ohci_sm501_resume,
diff --git a/drivers/usb/host/ohci-spear.c b/drivers/usb/host/ohci-spear.c
index 993f347c5c28..d7131e5a4477 100644
--- a/drivers/usb/host/ohci-spear.c
+++ b/drivers/usb/host/ohci-spear.c
@@ -157,7 +157,7 @@ MODULE_DEVICE_TABLE(of, spear_ohci_id_table);
/* Driver definition to register with the platform bus */
static struct platform_driver spear_ohci_hcd_driver = {
.probe = spear_ohci_hcd_drv_probe,
- .remove_new = spear_ohci_hcd_drv_remove,
+ .remove = spear_ohci_hcd_drv_remove,
#ifdef CONFIG_PM
.suspend = spear_ohci_hcd_drv_suspend,
.resume = spear_ohci_hcd_drv_resume,
diff --git a/drivers/usb/host/ohci-st.c b/drivers/usb/host/ohci-st.c
index 214342013f7e..d1656fce5400 100644
--- a/drivers/usb/host/ohci-st.c
+++ b/drivers/usb/host/ohci-st.c
@@ -298,7 +298,7 @@ MODULE_DEVICE_TABLE(of, st_ohci_platform_ids);
static struct platform_driver ohci_platform_driver = {
.probe = st_ohci_platform_probe,
- .remove_new = st_ohci_platform_remove,
+ .remove = st_ohci_platform_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "st-ohci",
diff --git a/drivers/usb/host/oxu210hp-hcd.c b/drivers/usb/host/oxu210hp-hcd.c
index ca3859463ba1..a6c20facf945 100644
--- a/drivers/usb/host/oxu210hp-hcd.c
+++ b/drivers/usb/host/oxu210hp-hcd.c
@@ -885,7 +885,7 @@ static int oxu_buf_alloc(struct oxu_hcd *oxu, struct ehci_qtd *qtd, int len)
int a_blocks; /* blocks allocated */
int i, j;
- /* Don't allocte bigger than supported */
+ /* Don't allocate bigger than supported */
if (len > BUFFER_SIZE * BUFFER_NUM) {
oxu_err(oxu, "buffer too big (%d)\n", len);
return -ENOMEM;
@@ -902,7 +902,7 @@ static int oxu_buf_alloc(struct oxu_hcd *oxu, struct ehci_qtd *qtd, int len)
/* Find a suitable available data buffer */
for (i = 0; i < BUFFER_NUM;
- i += max(a_blocks, (int)oxu->db_used[i])) {
+ i += max_t(int, a_blocks, oxu->db_used[i])) {
/* Check all the required blocks are available */
for (j = 0; j < a_blocks; j++)
@@ -3040,7 +3040,7 @@ static int oxu_hcd_init(struct usb_hcd *hcd)
* make problems: throughput reduction (!), data errors...
*/
if (park) {
- park = min(park, (unsigned) 3);
+ park = min_t(unsigned int, park, 3);
temp |= CMD_PARK;
temp |= park << 8;
}
@@ -4289,7 +4289,7 @@ static int oxu_drv_resume(struct device *dev)
static struct platform_driver oxu_driver = {
.probe = oxu_drv_probe,
- .remove_new = oxu_drv_remove,
+ .remove = oxu_drv_remove,
.shutdown = oxu_drv_shutdown,
.suspend = oxu_drv_suspend,
.resume = oxu_drv_resume,
diff --git a/drivers/usb/host/r8a66597-hcd.c b/drivers/usb/host/r8a66597-hcd.c
index 6576515a29cd..a44992e2561b 100644
--- a/drivers/usb/host/r8a66597-hcd.c
+++ b/drivers/usb/host/r8a66597-hcd.c
@@ -759,7 +759,7 @@ static void enable_r8a66597_pipe_dma(struct r8a66597 *r8a66597,
struct r8a66597_pipe_info *info = &pipe->info;
unsigned short mbw = mbw_value(r8a66597);
- /* pipe dma is only for external controlles */
+ /* pipe dma is only for external controllers */
if (r8a66597->pdata->on_chip)
return;
@@ -1336,7 +1336,7 @@ static void packet_read(struct r8a66597 *r8a66597, u16 pipenum)
buf = (void *)urb->transfer_buffer + urb->actual_length;
urb_len = urb->transfer_buffer_length - urb->actual_length;
}
- bufsize = min(urb_len, (int) td->maxpacket);
+ bufsize = min_t(int, urb_len, td->maxpacket);
if (rcv_len <= bufsize) {
size = rcv_len;
} else {
@@ -2510,7 +2510,7 @@ clean_up:
static struct platform_driver r8a66597_driver = {
.probe = r8a66597_probe,
- .remove_new = r8a66597_remove,
+ .remove = r8a66597_remove,
.driver = {
.name = hcd_name,
.pm = R8A66597_DEV_PM_OPS,
diff --git a/drivers/usb/host/sl811-hcd.c b/drivers/usb/host/sl811-hcd.c
index 92f2d1238448..036f5fd6d159 100644
--- a/drivers/usb/host/sl811-hcd.c
+++ b/drivers/usb/host/sl811-hcd.c
@@ -1784,7 +1784,7 @@ sl811h_resume(struct platform_device *dev)
/* this driver is exported so sl811_cs can depend on it */
struct platform_driver sl811h_driver = {
.probe = sl811h_probe,
- .remove_new = sl811h_remove,
+ .remove = sl811h_remove,
.suspend = sl811h_suspend,
.resume = sl811h_resume,
diff --git a/drivers/usb/host/uhci-grlib.c b/drivers/usb/host/uhci-grlib.c
index cfebb833668e..8a1f6d1b5b56 100644
--- a/drivers/usb/host/uhci-grlib.c
+++ b/drivers/usb/host/uhci-grlib.c
@@ -184,7 +184,7 @@ MODULE_DEVICE_TABLE(of, uhci_hcd_grlib_of_match);
static struct platform_driver uhci_grlib_driver = {
.probe = uhci_hcd_grlib_probe,
- .remove_new = uhci_hcd_grlib_remove,
+ .remove = uhci_hcd_grlib_remove,
.shutdown = uhci_hcd_grlib_shutdown,
.driver = {
.name = "grlib-uhci",
diff --git a/drivers/usb/host/uhci-platform.c b/drivers/usb/host/uhci-platform.c
index 3dec5dd3a0d5..a7c934404ebc 100644
--- a/drivers/usb/host/uhci-platform.c
+++ b/drivers/usb/host/uhci-platform.c
@@ -184,7 +184,7 @@ MODULE_DEVICE_TABLE(of, platform_uhci_ids);
static struct platform_driver uhci_platform_driver = {
.probe = uhci_hcd_platform_probe,
- .remove_new = uhci_hcd_platform_remove,
+ .remove = uhci_hcd_platform_remove,
.shutdown = uhci_hcd_platform_shutdown,
.driver = {
.name = "platform-uhci",
diff --git a/drivers/usb/host/xhci-dbgcap.c b/drivers/usb/host/xhci-dbgcap.c
index 241d7aa1fbc2..227e513867dd 100644
--- a/drivers/usb/host/xhci-dbgcap.c
+++ b/drivers/usb/host/xhci-dbgcap.c
@@ -248,8 +248,9 @@ xhci_dbc_queue_trb(struct xhci_ring *ring, u32 field1,
trb->generic.field[2] = cpu_to_le32(field3);
trb->generic.field[3] = cpu_to_le32(field4);
- trace_xhci_dbc_gadget_ep_queue(ring, &trb->generic);
-
+ trace_xhci_dbc_gadget_ep_queue(ring, &trb->generic,
+ xhci_trb_virt_to_dma(ring->enq_seg,
+ ring->enqueue));
ring->num_trbs_free--;
next = ++(ring->enqueue);
if (TRB_TYPE_LINK_LE32(next->link.control)) {
@@ -471,7 +472,7 @@ xhci_dbc_ring_alloc(struct device *dev, enum xhci_ring_type type, gfp_t flags)
trb->link.control = cpu_to_le32(LINK_TOGGLE | TRB_TYPE(TRB_LINK));
}
INIT_LIST_HEAD(&ring->td_list);
- xhci_initialize_ring_info(ring, 1);
+ xhci_initialize_ring_info(ring);
return ring;
dma_fail:
kfree(seg);
@@ -747,7 +748,7 @@ static void dbc_handle_xfer_event(struct xhci_dbc *dbc, union xhci_trb *event)
return;
}
- trace_xhci_dbc_handle_transfer(ring, &req->trb->generic);
+ trace_xhci_dbc_handle_transfer(ring, &req->trb->generic, req->trb_dma);
switch (comp_code) {
case COMP_SUCCESS:
@@ -898,7 +899,9 @@ static enum evtreturn xhci_dbc_do_handle_events(struct xhci_dbc *dbc)
*/
rmb();
- trace_xhci_dbc_handle_event(dbc->ring_evt, &evt->generic);
+ trace_xhci_dbc_handle_event(dbc->ring_evt, &evt->generic,
+ xhci_trb_virt_to_dma(dbc->ring_evt->deq_seg,
+ dbc->ring_evt->dequeue));
switch (le32_to_cpu(evt->event_cmd.flags) & TRB_TYPE_BITMASK) {
case TRB_TYPE(TRB_PORT_STATUS):
diff --git a/drivers/usb/host/xhci-debugfs.c b/drivers/usb/host/xhci-debugfs.c
index f8ba15e7c225..4f0c1b96e208 100644
--- a/drivers/usb/host/xhci-debugfs.c
+++ b/drivers/usb/host/xhci-debugfs.c
@@ -214,14 +214,11 @@ static void xhci_ring_dump_segment(struct seq_file *s,
static int xhci_ring_trb_show(struct seq_file *s, void *unused)
{
- int i;
struct xhci_ring *ring = *(struct xhci_ring **)s->private;
struct xhci_segment *seg = ring->first_seg;
- for (i = 0; i < ring->num_segs; i++) {
+ xhci_for_each_ring_seg(ring->first_seg, seg)
xhci_ring_dump_segment(s, seg);
- seg = seg->next;
- }
return 0;
}
@@ -291,12 +288,13 @@ static int xhci_endpoint_context_show(struct seq_file *s, void *unused)
for (ep_index = 0; ep_index < 31; ep_index++) {
ep_ctx = xhci_get_ep_ctx(xhci, dev->out_ctx, ep_index);
dma = dev->out_ctx->dma + (ep_index + 1) * CTX_SIZE(xhci->hcc_params);
- seq_printf(s, "%pad: %s\n", &dma,
+ seq_printf(s, "%pad: %s, virt_state:%#x\n", &dma,
xhci_decode_ep_context(str,
le32_to_cpu(ep_ctx->ep_info),
le32_to_cpu(ep_ctx->ep_info2),
le64_to_cpu(ep_ctx->deq),
- le32_to_cpu(ep_ctx->tx_info)));
+ le32_to_cpu(ep_ctx->tx_info)),
+ dev->eps[ep_index].ep_state);
}
return 0;
diff --git a/drivers/usb/host/xhci-histb.c b/drivers/usb/host/xhci-histb.c
index f9a4a4b0eb57..8a7d46dae62c 100644
--- a/drivers/usb/host/xhci-histb.c
+++ b/drivers/usb/host/xhci-histb.c
@@ -373,7 +373,7 @@ MODULE_DEVICE_TABLE(of, histb_xhci_of_match);
static struct platform_driver histb_xhci_driver = {
.probe = xhci_histb_probe,
- .remove_new = xhci_histb_remove,
+ .remove = xhci_histb_remove,
.driver = {
.name = "xhci-histb",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 8d774f19271e..9693464c0520 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -946,9 +946,9 @@ static int xhci_handle_usb2_port_link_resume(struct xhci_port *port,
}
/* did port event handler already start resume timing? */
if (!port->resume_timestamp) {
- /* If not, maybe we are in a host initated resume? */
+ /* If not, maybe we are in a host initiated resume? */
if (test_bit(wIndex, &bus_state->resuming_ports)) {
- /* Host initated resume doesn't time the resume
+ /* Host initiated resume doesn't time the resume
* signalling using resume_done[].
* It manually sets RESUME state, sleeps 20ms
* and sets U0 state. This should probably be
@@ -1924,7 +1924,7 @@ int xhci_bus_resume(struct usb_hcd *hcd)
/* resume already initiated */
break;
default:
- /* not in a resumeable state, ignore it */
+ /* not in a resumable state, ignore it */
clear_bit(port_index,
&bus_state->bus_suspended);
break;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index d2900197a49e..92703efda1f7 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -27,14 +27,12 @@
* "All components of all Command and Transfer TRBs shall be initialized to '0'"
*/
static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
- unsigned int cycle_state,
unsigned int max_packet,
unsigned int num,
gfp_t flags)
{
struct xhci_segment *seg;
dma_addr_t dma;
- int i;
struct device *dev = xhci_to_hcd(xhci)->self.sysdev;
seg = kzalloc_node(sizeof(*seg), flags, dev_to_node(dev));
@@ -56,11 +54,6 @@ static struct xhci_segment *xhci_segment_alloc(struct xhci_hcd *xhci,
return NULL;
}
}
- /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */
- if (cycle_state == 0) {
- for (i = 0; i < TRBS_PER_SEGMENT; i++)
- seg->trbs[i].link.control = cpu_to_le32(TRB_CYCLE);
- }
seg->num = num;
seg->dma = dma;
seg->next = NULL;
@@ -78,82 +71,104 @@ static void xhci_segment_free(struct xhci_hcd *xhci, struct xhci_segment *seg)
kfree(seg);
}
-static void xhci_free_segments_for_ring(struct xhci_hcd *xhci,
- struct xhci_segment *first)
+static void xhci_ring_segments_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
{
- struct xhci_segment *seg;
+ struct xhci_segment *seg, *next;
+
+ ring->last_seg->next = NULL;
+ seg = ring->first_seg;
- seg = first->next;
- while (seg && seg != first) {
- struct xhci_segment *next = seg->next;
+ while (seg) {
+ next = seg->next;
xhci_segment_free(xhci, seg);
seg = next;
}
- xhci_segment_free(xhci, first);
}
/*
- * Make the prev segment point to the next segment.
+ * Only for transfer and command rings where driver is the producer, not for
+ * event rings.
*
- * Change the last TRB in the prev segment to be a Link TRB which points to the
+ * Change the last TRB in the segment to be a Link TRB which points to the
* DMA address of the next segment. The caller needs to set any Link TRB
* related flags, such as End TRB, Toggle Cycle, and no snoop.
*/
-static void xhci_link_segments(struct xhci_segment *prev,
- struct xhci_segment *next,
- enum xhci_ring_type type, bool chain_links)
+static void xhci_set_link_trb(struct xhci_segment *seg, bool chain_links)
{
+ union xhci_trb *trb;
u32 val;
- if (!prev || !next)
+ if (!seg || !seg->next)
return;
- prev->next = next;
- if (type != TYPE_EVENT) {
- prev->trbs[TRBS_PER_SEGMENT-1].link.segment_ptr =
- cpu_to_le64(next->dma);
- /* Set the last TRB in the segment to have a TRB type ID of Link TRB */
- val = le32_to_cpu(prev->trbs[TRBS_PER_SEGMENT-1].link.control);
- val &= ~TRB_TYPE_BITMASK;
- val |= TRB_TYPE(TRB_LINK);
- if (chain_links)
- val |= TRB_CHAIN;
- prev->trbs[TRBS_PER_SEGMENT-1].link.control = cpu_to_le32(val);
- }
+ trb = &seg->trbs[TRBS_PER_SEGMENT - 1];
+
+ /* Set the last TRB in the segment to have a TRB type ID of Link TRB */
+ val = le32_to_cpu(trb->link.control);
+ val &= ~TRB_TYPE_BITMASK;
+ val |= TRB_TYPE(TRB_LINK);
+ if (chain_links)
+ val |= TRB_CHAIN;
+ trb->link.control = cpu_to_le32(val);
+ trb->link.segment_ptr = cpu_to_le64(seg->next->dma);
+}
+
+static void xhci_initialize_ring_segments(struct xhci_hcd *xhci, struct xhci_ring *ring)
+{
+ struct xhci_segment *seg;
+ bool chain_links;
+
+ if (ring->type == TYPE_EVENT)
+ return;
+
+ chain_links = xhci_link_chain_quirk(xhci, ring->type);
+ xhci_for_each_ring_seg(ring->first_seg, seg)
+ xhci_set_link_trb(seg, chain_links);
+
+ /* See section 4.9.2.1 and 6.4.4.1 */
+ ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |= cpu_to_le32(LINK_TOGGLE);
}
/*
- * Link the ring to the new segments.
+ * Link the src ring segments to the dst ring.
* Set Toggle Cycle for the new ring if needed.
*/
-static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *ring,
- struct xhci_segment *first, struct xhci_segment *last,
- unsigned int num_segs)
+static void xhci_link_rings(struct xhci_hcd *xhci, struct xhci_ring *src, struct xhci_ring *dst)
{
- struct xhci_segment *next, *seg;
+ struct xhci_segment *seg;
bool chain_links;
- if (!ring || !first || !last)
+ if (!src || !dst)
return;
- chain_links = xhci_link_chain_quirk(xhci, ring->type);
+ /* If the cycle state is 0, set the cycle bit to 1 for all the TRBs */
+ if (dst->cycle_state == 0) {
+ xhci_for_each_ring_seg(src->first_seg, seg) {
+ for (int i = 0; i < TRBS_PER_SEGMENT; i++)
+ seg->trbs[i].link.control |= cpu_to_le32(TRB_CYCLE);
+ }
+ }
- next = ring->enq_seg->next;
- xhci_link_segments(ring->enq_seg, first, ring->type, chain_links);
- xhci_link_segments(last, next, ring->type, chain_links);
- ring->num_segs += num_segs;
+ src->last_seg->next = dst->enq_seg->next;
+ dst->enq_seg->next = src->first_seg;
+ if (dst->type != TYPE_EVENT) {
+ chain_links = xhci_link_chain_quirk(xhci, dst->type);
+ xhci_set_link_trb(dst->enq_seg, chain_links);
+ xhci_set_link_trb(src->last_seg, chain_links);
+ }
+ dst->num_segs += src->num_segs;
- if (ring->enq_seg == ring->last_seg) {
- if (ring->type != TYPE_EVENT) {
- ring->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control
+ if (dst->enq_seg == dst->last_seg) {
+ if (dst->type != TYPE_EVENT)
+ dst->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control
&= ~cpu_to_le32(LINK_TOGGLE);
- last->trbs[TRBS_PER_SEGMENT-1].link.control
- |= cpu_to_le32(LINK_TOGGLE);
- }
- ring->last_seg = last;
+
+ dst->last_seg = src->last_seg;
+ } else if (dst->type != TYPE_EVENT) {
+ src->last_seg->trbs[TRBS_PER_SEGMENT-1].link.control &= ~cpu_to_le32(LINK_TOGGLE);
}
- for (seg = ring->enq_seg; seg != ring->last_seg; seg = seg->next)
+ for (seg = dst->enq_seg; seg != dst->last_seg; seg = seg->next)
seg->next->num = seg->num + 1;
}
@@ -224,7 +239,6 @@ static int xhci_update_stream_segment_mapping(
struct radix_tree_root *trb_address_map,
struct xhci_ring *ring,
struct xhci_segment *first_seg,
- struct xhci_segment *last_seg,
gfp_t mem_flags)
{
struct xhci_segment *seg;
@@ -234,28 +248,22 @@ static int xhci_update_stream_segment_mapping(
if (WARN_ON_ONCE(trb_address_map == NULL))
return 0;
- seg = first_seg;
- do {
+ xhci_for_each_ring_seg(first_seg, seg) {
ret = xhci_insert_segment_mapping(trb_address_map,
ring, seg, mem_flags);
if (ret)
goto remove_streams;
- if (seg == last_seg)
- return 0;
- seg = seg->next;
- } while (seg != first_seg);
+ }
return 0;
remove_streams:
failed_seg = seg;
- seg = first_seg;
- do {
+ xhci_for_each_ring_seg(first_seg, seg) {
xhci_remove_segment_mapping(trb_address_map, seg);
if (seg == failed_seg)
return ret;
- seg = seg->next;
- } while (seg != first_seg);
+ }
return ret;
}
@@ -267,17 +275,14 @@ static void xhci_remove_stream_mapping(struct xhci_ring *ring)
if (WARN_ON_ONCE(ring->trb_address_map == NULL))
return;
- seg = ring->first_seg;
- do {
+ xhci_for_each_ring_seg(ring->first_seg, seg)
xhci_remove_segment_mapping(ring->trb_address_map, seg);
- seg = seg->next;
- } while (seg != ring->first_seg);
}
static int xhci_update_stream_mapping(struct xhci_ring *ring, gfp_t mem_flags)
{
return xhci_update_stream_segment_mapping(ring->trb_address_map, ring,
- ring->first_seg, ring->last_seg, mem_flags);
+ ring->first_seg, mem_flags);
}
/* XXX: Do we need the hcd structure in all these functions? */
@@ -291,14 +296,13 @@ void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring)
if (ring->first_seg) {
if (ring->type == TYPE_STREAM)
xhci_remove_stream_mapping(ring);
- xhci_free_segments_for_ring(xhci, ring->first_seg);
+ xhci_ring_segments_free(xhci, ring);
}
kfree(ring);
}
-void xhci_initialize_ring_info(struct xhci_ring *ring,
- unsigned int cycle_state)
+void xhci_initialize_ring_info(struct xhci_ring *ring)
{
/* The ring is empty, so the enqueue pointer == dequeue pointer */
ring->enqueue = ring->first_seg->trbs;
@@ -312,7 +316,7 @@ void xhci_initialize_ring_info(struct xhci_ring *ring,
* New rings are initialized with cycle state equal to 1; if we are
* handling ring expansion, set the cycle state equal to the old ring.
*/
- ring->cycle_state = cycle_state;
+ ring->cycle_state = 1;
/*
* Each segment has a link TRB, and leave an extra TRB for SW
@@ -323,46 +327,36 @@ void xhci_initialize_ring_info(struct xhci_ring *ring,
EXPORT_SYMBOL_GPL(xhci_initialize_ring_info);
/* Allocate segments and link them for a ring */
-static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci,
- struct xhci_segment **first,
- struct xhci_segment **last,
- unsigned int num_segs,
- unsigned int cycle_state,
- enum xhci_ring_type type,
- unsigned int max_packet,
- gfp_t flags)
+static int xhci_alloc_segments_for_ring(struct xhci_hcd *xhci, struct xhci_ring *ring, gfp_t flags)
{
struct xhci_segment *prev;
unsigned int num = 0;
- bool chain_links;
-
- chain_links = xhci_link_chain_quirk(xhci, type);
- prev = xhci_segment_alloc(xhci, cycle_state, max_packet, num, flags);
+ prev = xhci_segment_alloc(xhci, ring->bounce_buf_len, num, flags);
if (!prev)
return -ENOMEM;
num++;
- *first = prev;
- while (num < num_segs) {
+ ring->first_seg = prev;
+ while (num < ring->num_segs) {
struct xhci_segment *next;
- next = xhci_segment_alloc(xhci, cycle_state, max_packet, num,
- flags);
+ next = xhci_segment_alloc(xhci, ring->bounce_buf_len, num, flags);
if (!next)
goto free_segments;
- xhci_link_segments(prev, next, type, chain_links);
+ prev->next = next;
prev = next;
num++;
}
- xhci_link_segments(prev, *first, type, chain_links);
- *last = prev;
+ ring->last_seg = prev;
+ ring->last_seg->next = ring->first_seg;
return 0;
free_segments:
- xhci_free_segments_for_ring(xhci, *first);
+ ring->last_seg = prev;
+ xhci_ring_segments_free(xhci, ring);
return -ENOMEM;
}
@@ -373,9 +367,8 @@ free_segments:
* Set the end flag and the cycle toggle bit on the last segment.
* See section 4.9.1 and figures 15 and 16.
*/
-struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
- unsigned int num_segs, unsigned int cycle_state,
- enum xhci_ring_type type, unsigned int max_packet, gfp_t flags)
+struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, unsigned int num_segs,
+ enum xhci_ring_type type, unsigned int max_packet, gfp_t flags)
{
struct xhci_ring *ring;
int ret;
@@ -392,18 +385,12 @@ struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
if (num_segs == 0)
return ring;
- ret = xhci_alloc_segments_for_ring(xhci, &ring->first_seg, &ring->last_seg, num_segs,
- cycle_state, type, max_packet, flags);
+ ret = xhci_alloc_segments_for_ring(xhci, ring, flags);
if (ret)
goto fail;
- /* Only event ring does not use link TRB */
- if (type != TYPE_EVENT) {
- /* See section 4.9.2.1 and 6.4.4.1 */
- ring->last_seg->trbs[TRBS_PER_SEGMENT - 1].link.control |=
- cpu_to_le32(LINK_TOGGLE);
- }
- xhci_initialize_ring_info(ring, cycle_state);
+ xhci_initialize_ring_segments(xhci, ring);
+ xhci_initialize_ring_info(ring);
trace_xhci_ring_alloc(ring);
return ring;
@@ -427,23 +414,29 @@ void xhci_free_endpoint_ring(struct xhci_hcd *xhci,
int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
unsigned int num_new_segs, gfp_t flags)
{
- struct xhci_segment *first;
- struct xhci_segment *last;
- int ret;
+ struct xhci_ring new_ring;
+ int ret;
+
+ if (num_new_segs == 0)
+ return 0;
- ret = xhci_alloc_segments_for_ring(xhci, &first, &last, num_new_segs, ring->cycle_state,
- ring->type, ring->bounce_buf_len, flags);
+ new_ring.num_segs = num_new_segs;
+ new_ring.bounce_buf_len = ring->bounce_buf_len;
+ new_ring.type = ring->type;
+ ret = xhci_alloc_segments_for_ring(xhci, &new_ring, flags);
if (ret)
return -ENOMEM;
+ xhci_initialize_ring_segments(xhci, &new_ring);
+
if (ring->type == TYPE_STREAM) {
- ret = xhci_update_stream_segment_mapping(ring->trb_address_map,
- ring, first, last, flags);
+ ret = xhci_update_stream_segment_mapping(ring->trb_address_map, ring,
+ new_ring.first_seg, flags);
if (ret)
goto free_segments;
}
- xhci_link_rings(xhci, ring, first, last, num_new_segs);
+ xhci_link_rings(xhci, &new_ring, ring);
trace_xhci_ring_expansion(ring);
xhci_dbg_trace(xhci, trace_xhci_dbg_ring_expansion,
"ring expansion succeed, now has %d segments",
@@ -452,7 +445,7 @@ int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
return 0;
free_segments:
- xhci_free_segments_for_ring(xhci, first);
+ xhci_ring_segments_free(xhci, &new_ring);
return ret;
}
@@ -642,8 +635,7 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
for (cur_stream = 1; cur_stream < num_streams; cur_stream++) {
stream_info->stream_rings[cur_stream] =
- xhci_ring_alloc(xhci, 2, 1, TYPE_STREAM, max_packet,
- mem_flags);
+ xhci_ring_alloc(xhci, 2, TYPE_STREAM, max_packet, mem_flags);
cur_ring = stream_info->stream_rings[cur_stream];
if (!cur_ring)
goto cleanup_rings;
@@ -658,6 +650,8 @@ struct xhci_stream_info *xhci_alloc_stream_info(struct xhci_hcd *xhci,
xhci_dbg(xhci, "Setting stream %d ring ptr to 0x%08llx\n", cur_stream, addr);
ret = xhci_update_stream_mapping(cur_ring, mem_flags);
+
+ trace_xhci_alloc_stream_info_ctx(stream_info, cur_stream);
if (ret) {
xhci_ring_free(xhci, cur_ring);
stream_info->stream_rings[cur_stream] = NULL;
@@ -984,7 +978,7 @@ int xhci_alloc_virt_device(struct xhci_hcd *xhci, int slot_id,
}
/* Allocate endpoint 0 ring */
- dev->eps[0].ring = xhci_ring_alloc(xhci, 2, 1, TYPE_CTRL, 0, flags);
+ dev->eps[0].ring = xhci_ring_alloc(xhci, 2, TYPE_CTRL, 0, flags);
if (!dev->eps[0].ring)
goto fail;
@@ -1461,7 +1455,7 @@ int xhci_endpoint_init(struct xhci_hcd *xhci,
/* Set up the endpoint ring */
virt_dev->eps[ep_index].new_ring =
- xhci_ring_alloc(xhci, 2, 1, ring_type, max_packet, mem_flags);
+ xhci_ring_alloc(xhci, 2, ring_type, max_packet, mem_flags);
if (!virt_dev->eps[ep_index].new_ring)
return -ENOMEM;
@@ -2271,7 +2265,7 @@ xhci_alloc_interrupter(struct xhci_hcd *xhci, unsigned int segs, gfp_t flags)
if (!ir)
return NULL;
- ir->event_ring = xhci_ring_alloc(xhci, segs, 1, TYPE_EVENT, 0, flags);
+ ir->event_ring = xhci_ring_alloc(xhci, segs, TYPE_EVENT, 0, flags);
if (!ir->event_ring) {
xhci_warn(xhci, "Failed to allocate interrupter event ring\n");
kfree(ir);
@@ -2473,7 +2467,7 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
goto fail;
/* Set up the command ring to have one segments for now. */
- xhci->cmd_ring = xhci_ring_alloc(xhci, 1, 1, TYPE_COMMAND, 0, flags);
+ xhci->cmd_ring = xhci_ring_alloc(xhci, 1, TYPE_COMMAND, 0, flags);
if (!xhci->cmd_ring)
goto fail;
xhci_dbg_trace(xhci, trace_xhci_dbg_init,
@@ -2518,11 +2512,6 @@ int xhci_mem_init(struct xhci_hcd *xhci, gfp_t flags)
ir->isoc_bei_interval = AVOID_BEI_INTERVAL_MAX;
- /*
- * XXX: Might need to set the Interrupter Moderation Register to
- * something other than the default (~1ms minimum between interrupts).
- * See section 5.5.1.2.
- */
for (i = 0; i < MAX_HC_SLOTS; i++)
xhci->devs[i] = NULL;
diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c
index 3252e3d2d79c..904831344440 100644
--- a/drivers/usb/host/xhci-mtk.c
+++ b/drivers/usb/host/xhci-mtk.c
@@ -853,7 +853,7 @@ MODULE_DEVICE_TABLE(of, mtk_xhci_of_match);
static struct platform_driver mtk_xhci_driver = {
.probe = xhci_mtk_probe,
- .remove_new = xhci_mtk_remove,
+ .remove = xhci_mtk_remove,
.driver = {
.name = "xhci-mtk",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/host/xhci-pci-renesas.c b/drivers/usb/host/xhci-pci-renesas.c
index 65fc9319d5e7..620f8f0febb8 100644
--- a/drivers/usb/host/xhci-pci-renesas.c
+++ b/drivers/usb/host/xhci-pci-renesas.c
@@ -661,5 +661,5 @@ module_pci_driver(xhci_renesas_pci_driver);
MODULE_DESCRIPTION("Renesas xHCI PCI Host Controller Driver");
MODULE_FIRMWARE(RENESAS_FW_NAME);
-MODULE_IMPORT_NS(xhci);
+MODULE_IMPORT_NS("xhci");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index cb07cee9ed0c..2d1e205c14c6 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -28,18 +28,18 @@
#define SPARSE_CNTL_ENABLE 0xC12C
/* Device for a quirk */
-#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
-#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
+#define PCI_VENDOR_ID_FRESCO_LOGIC 0x1b73
+#define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1009 0x1009
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1100 0x1100
#define PCI_DEVICE_ID_FRESCO_LOGIC_FL1400 0x1400
-#define PCI_VENDOR_ID_ETRON 0x1b6f
-#define PCI_DEVICE_ID_EJ168 0x7023
-#define PCI_DEVICE_ID_EJ188 0x7052
+#define PCI_VENDOR_ID_ETRON 0x1b6f
+#define PCI_DEVICE_ID_ETRON_EJ168 0x7023
+#define PCI_DEVICE_ID_ETRON_EJ188 0x7052
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
-#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
#define PCI_DEVICE_ID_INTEL_WILDCATPOINT_LP_XHCI 0x9cb1
#define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f
@@ -82,9 +82,6 @@
#define PCI_DEVICE_ID_ASMEDIA_3042_XHCI 0x3042
#define PCI_DEVICE_ID_ASMEDIA_3242_XHCI 0x3242
-#define PCI_DEVICE_ID_CADENCE 0x17CD
-#define PCI_DEVICE_ID_CADENCE_SSP 0x0200
-
static const char hcd_name[] = "xhci_hcd";
static struct hc_driver __read_mostly xhci_pci_hc_driver;
@@ -150,14 +147,11 @@ static int xhci_try_enable_msi(struct usb_hcd *hcd)
hcd->irq = 0;
/*
- * calculate number of MSI-X vectors supported.
- * - HCS_MAX_INTRS: the max number of interrupts the host can handle,
- * with max number of interrupters based on the xhci HCSPARAMS1.
- * - num_online_cpus: maximum MSI-X vectors per CPUs core.
- * Add additional 1 vector to ensure always available interrupt.
+ * Calculate number of MSI/MSI-X vectors supported.
+ * - max_interrupters: the max number of interrupts requested, capped to xhci HCSPARAMS1.
+ * - num_online_cpus: one vector per CPUs core, with at least one overall.
*/
- xhci->nvecs = min(num_online_cpus() + 1,
- HCS_MAX_INTRS(xhci->hcs_params1));
+ xhci->nvecs = min(num_online_cpus() + 1, xhci->max_interrupters);
/* TODO: Check with MSI Soc for sysdev */
xhci->nvecs = pci_alloc_irq_vectors(pdev, 1, xhci->nvecs,
@@ -395,14 +389,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_DEFAULT_PM_RUNTIME_ALLOW;
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
- pdev->device == PCI_DEVICE_ID_EJ168) {
- xhci->quirks |= XHCI_RESET_ON_RESUME;
- xhci->quirks |= XHCI_BROKEN_STREAMS;
- }
- if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
- pdev->device == PCI_DEVICE_ID_EJ188) {
+ (pdev->device == PCI_DEVICE_ID_ETRON_EJ168 ||
+ pdev->device == PCI_DEVICE_ID_ETRON_EJ188)) {
+ xhci->quirks |= XHCI_ETRON_HOST;
xhci->quirks |= XHCI_RESET_ON_RESUME;
xhci->quirks |= XHCI_BROKEN_STREAMS;
+ xhci->quirks |= XHCI_NO_SOFT_RETRY;
}
if (pdev->vendor == PCI_VENDOR_ID_RENESAS &&
@@ -482,8 +474,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
xhci->quirks |= XHCI_ZHAOXIN_TRB_FETCH;
}
- if (pdev->vendor == PCI_DEVICE_ID_CADENCE &&
- pdev->device == PCI_DEVICE_ID_CADENCE_SSP)
+ if (pdev->vendor == PCI_VENDOR_ID_CDNS &&
+ pdev->device == PCI_DEVICE_ID_CDNS_USBSSP)
xhci->quirks |= XHCI_CDNS_SCTX_QUIRK;
/* xHC spec requires PCI devices to support D3hot and D3cold */
@@ -646,6 +638,9 @@ int xhci_pci_common_probe(struct pci_dev *dev, const struct pci_device_id *id)
dma_set_max_seg_size(&dev->dev, UINT_MAX);
+ if (device_property_read_bool(&dev->dev, "ti,pwron-active-high"))
+ pci_clear_and_set_config_dword(dev, 0xE0, 0, 1 << 22);
+
return 0;
put_usb3_hcd:
@@ -656,7 +651,7 @@ put_runtime_pm:
pm_runtime_put_noidle(&dev->dev);
return retval;
}
-EXPORT_SYMBOL_NS_GPL(xhci_pci_common_probe, xhci);
+EXPORT_SYMBOL_NS_GPL(xhci_pci_common_probe, "xhci");
static const struct pci_device_id pci_ids_reject[] = {
/* handled by xhci-pci-renesas */
@@ -700,7 +695,7 @@ void xhci_pci_remove(struct pci_dev *dev)
if (set_power_d3)
pci_set_power_state(dev, PCI_D3hot);
}
-EXPORT_SYMBOL_NS_GPL(xhci_pci_remove, xhci);
+EXPORT_SYMBOL_NS_GPL(xhci_pci_remove, "xhci");
/*
* In some Intel xHCI controllers, in order to get D3 working,
diff --git a/drivers/usb/host/xhci-plat.c b/drivers/usb/host/xhci-plat.c
index ecaa75718e59..e6c9006bd568 100644
--- a/drivers/usb/host/xhci-plat.c
+++ b/drivers/usb/host/xhci-plat.c
@@ -573,7 +573,7 @@ MODULE_DEVICE_TABLE(acpi, usb_xhci_acpi_match);
static struct platform_driver usb_generic_xhci_driver = {
.probe = xhci_generic_plat_probe,
- .remove_new = xhci_plat_remove,
+ .remove = xhci_plat_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "xhci-hcd",
diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c
index 8b357647728c..1cc082a3b793 100644
--- a/drivers/usb/host/xhci-rcar.c
+++ b/drivers/usb/host/xhci-rcar.c
@@ -274,7 +274,7 @@ static int xhci_renesas_probe(struct platform_device *pdev)
static struct platform_driver usb_xhci_renesas_driver = {
.probe = xhci_renesas_probe,
- .remove_new = xhci_plat_remove,
+ .remove = xhci_plat_remove,
.shutdown = usb_hcd_platform_shutdown,
.driver = {
.name = "xhci-renesas-hcd",
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 928b93ad1ee8..09b05a62375e 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -52,6 +52,7 @@
* endpoint rings; it generates events on the event ring for these.
*/
+#include <linux/jiffies.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
@@ -145,10 +146,8 @@ static void trb_to_noop(union xhci_trb *trb, u32 noop_type)
* TRB is in a new segment. This does not skip over link TRBs, and it does not
* effect the ring dequeue or enqueue pointers.
*/
-static void next_trb(struct xhci_hcd *xhci,
- struct xhci_ring *ring,
- struct xhci_segment **seg,
- union xhci_trb **trb)
+static void next_trb(struct xhci_segment **seg,
+ union xhci_trb **trb)
{
if (trb_is_link(*trb) || last_trb_on_seg(*seg, *trb)) {
*seg = (*seg)->next;
@@ -169,13 +168,16 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
if (ring->type == TYPE_EVENT) {
if (!last_trb_on_seg(ring->deq_seg, ring->dequeue)) {
ring->dequeue++;
- goto out;
+ return;
}
if (last_trb_on_ring(ring, ring->deq_seg, ring->dequeue))
ring->cycle_state ^= 1;
ring->deq_seg = ring->deq_seg->next;
ring->dequeue = ring->deq_seg->trbs;
- goto out;
+
+ trace_xhci_inc_deq(ring);
+
+ return;
}
/* All other rings have link trbs */
@@ -190,14 +192,13 @@ void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring)
ring->deq_seg = ring->deq_seg->next;
ring->dequeue = ring->deq_seg->trbs;
+ trace_xhci_inc_deq(ring);
+
if (link_trb_count++ > ring->num_segs) {
xhci_warn(xhci, "Ring is an endless link TRB loop\n");
break;
}
}
-out:
- trace_xhci_inc_deq(ring);
-
return;
}
@@ -266,13 +267,13 @@ static void inc_enq(struct xhci_hcd *xhci, struct xhci_ring *ring,
ring->enqueue = ring->enq_seg->trbs;
next = ring->enqueue;
+ trace_xhci_inc_enq(ring);
+
if (link_trb_count++ > ring->num_segs) {
xhci_warn(xhci, "%s: Ring link TRB loop\n", __func__);
break;
}
}
-
- trace_xhci_inc_enq(ring);
}
/*
@@ -426,7 +427,7 @@ static void xhci_handle_stopped_cmd_ring(struct xhci_hcd *xhci,
}
}
-/* Must be called with xhci->lock held, releases and aquires lock back */
+/* Must be called with xhci->lock held, releases and acquires lock back */
static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
{
struct xhci_segment *new_seg = xhci->cmd_ring->deq_seg;
@@ -446,9 +447,9 @@ static int xhci_abort_cmd_ring(struct xhci_hcd *xhci, unsigned long flags)
* avoiding corrupting the command ring pointer in case the command ring
* is stopped by the time the upper dword is written.
*/
- next_trb(xhci, NULL, &new_seg, &new_deq);
+ next_trb(&new_seg, &new_deq);
if (trb_is_link(new_deq))
- next_trb(xhci, NULL, &new_seg, &new_deq);
+ next_trb(&new_seg, &new_deq);
crcr = xhci_trb_virt_to_dma(new_seg, new_deq);
xhci_write_64(xhci, crcr | CMD_RING_ABORT, &xhci->op_regs->cmd_ring);
@@ -660,8 +661,8 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
/*
* We want to find the pointer, segment and cycle state of the new trb
- * (the one after current TD's last_trb). We know the cycle state at
- * hw_dequeue, so walk the ring until both hw_dequeue and last_trb are
+ * (the one after current TD's end_trb). We know the cycle state at
+ * hw_dequeue, so walk the ring until both hw_dequeue and end_trb are
* found.
*/
do {
@@ -671,14 +672,14 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
if (td_last_trb_found)
break;
}
- if (new_deq == td->last_trb)
+ if (new_deq == td->end_trb)
td_last_trb_found = true;
if (cycle_found && trb_is_link(new_deq) &&
link_trb_toggles_cycle(new_deq))
new_cycle ^= 0x1;
- next_trb(xhci, ep_ring, &new_seg, &new_deq);
+ next_trb(&new_seg, &new_deq);
/* Search wrapped around, bail out */
if (new_deq == ep->ring->dequeue) {
@@ -740,23 +741,22 @@ static int xhci_move_dequeue_past_td(struct xhci_hcd *xhci,
* (The last TRB actually points to the ring enqueue pointer, which is not part
* of this TD.) This is used to remove partially enqueued isoc TDs from a ring.
*/
-static void td_to_noop(struct xhci_hcd *xhci, struct xhci_ring *ep_ring,
- struct xhci_td *td, bool flip_cycle)
+static void td_to_noop(struct xhci_td *td, bool flip_cycle)
{
struct xhci_segment *seg = td->start_seg;
- union xhci_trb *trb = td->first_trb;
+ union xhci_trb *trb = td->start_trb;
while (1) {
trb_to_noop(trb, TRB_TR_NOOP);
/* flip cycle if asked to */
- if (flip_cycle && trb != td->first_trb && trb != td->last_trb)
+ if (flip_cycle && trb != td->start_trb && trb != td->end_trb)
trb->generic.field[3] ^= cpu_to_le32(TRB_CYCLE);
- if (trb == td->last_trb)
+ if (trb == td->end_trb)
break;
- next_trb(xhci, ep_ring, &seg, &trb);
+ next_trb(&seg, &trb);
}
}
@@ -799,7 +799,7 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
dma_unmap_single(dev, seg->bounce_dma, ring->bounce_buf_len,
DMA_FROM_DEVICE);
- /* for in tranfers we need to copy the data from bounce to sg */
+ /* for in transfers we need to copy the data from bounce to sg */
if (urb->num_sgs) {
len = sg_pcopy_from_buffer(urb->sg, urb->num_sgs, seg->bounce_buf,
seg->bounce_len, seg->bounce_offs);
@@ -814,8 +814,8 @@ static void xhci_unmap_td_bounce_buffer(struct xhci_hcd *xhci,
seg->bounce_offs = 0;
}
-static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
- struct xhci_ring *ep_ring, int status)
+static void xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
+ struct xhci_ring *ep_ring, int status)
{
struct urb *urb = NULL;
@@ -858,10 +858,18 @@ static int xhci_td_cleanup(struct xhci_hcd *xhci, struct xhci_td *td,
status = 0;
xhci_giveback_urb_in_irq(xhci, td, status);
}
-
- return 0;
}
+/* Give back previous TD and move on to the next TD. */
+static void xhci_dequeue_td(struct xhci_hcd *xhci, struct xhci_td *td, struct xhci_ring *ring,
+ u32 status)
+{
+ ring->dequeue = td->end_trb;
+ ring->deq_seg = td->end_seg;
+ inc_deq(xhci, ring);
+
+ xhci_td_cleanup(xhci, td, ring, status);
+}
/* Complete the cancelled URBs we unlinked from td_list. */
static void xhci_giveback_invalidated_tds(struct xhci_virt_ep *ep)
@@ -972,13 +980,20 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
unsigned int slot_id = ep->vdev->slot_id;
int err;
+ /*
+ * This is not going to work if the hardware is changing its dequeue
+ * pointers as we look at them. Completion handler will call us later.
+ */
+ if (ep->ep_state & SET_DEQ_PENDING)
+ return 0;
+
xhci = ep->xhci;
list_for_each_entry_safe(td, tmp_td, &ep->cancelled_td_list, cancelled_td_list) {
xhci_dbg_trace(xhci, trace_xhci_dbg_cancel_urb,
"Removing canceled TD starting at 0x%llx (dma) in stream %u URB %p",
(unsigned long long)xhci_trb_virt_to_dma(
- td->start_seg, td->first_trb),
+ td->start_seg, td->start_trb),
td->urb->stream_id, td->urb);
list_del_init(&td->td_list);
ring = xhci_urb_to_transfer_ring(xhci, td->urb);
@@ -1020,16 +1035,16 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
"Found multiple active URBs %p and %p in stream %u?\n",
td->urb, cached_td->urb,
td->urb->stream_id);
- td_to_noop(xhci, ring, cached_td, false);
+ td_to_noop(cached_td, false);
cached_td->cancel_status = TD_CLEARED;
}
- td_to_noop(xhci, ring, td, false);
+ td_to_noop(td, false);
td->cancel_status = TD_CLEARING_CACHE;
cached_td = td;
break;
}
} else {
- td_to_noop(xhci, ring, td, false);
+ td_to_noop(td, false);
td->cancel_status = TD_CLEARED;
}
}
@@ -1054,7 +1069,7 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
continue;
xhci_warn(xhci, "Failed to clear cancelled cached URB %p, mark clear anyway\n",
td->urb);
- td_to_noop(xhci, ring, td, false);
+ td_to_noop(td, false);
td->cancel_status = TD_CLEARED;
}
}
@@ -1062,6 +1077,19 @@ static int xhci_invalidate_cancelled_tds(struct xhci_virt_ep *ep)
}
/*
+ * Erase queued TDs from transfer ring(s) and give back those the xHC didn't
+ * stop on. If necessary, queue commands to move the xHC off cancelled TDs it
+ * stopped on. Those will be given back later when the commands complete.
+ *
+ * Call under xhci->lock on a stopped endpoint.
+ */
+void xhci_process_cancelled_tds(struct xhci_virt_ep *ep)
+{
+ xhci_invalidate_cancelled_tds(ep);
+ xhci_giveback_invalidated_tds(ep);
+}
+
+/*
* Returns the TD the endpoint ring halted on.
* Only call for non-running rings without streams.
*/
@@ -1151,16 +1179,33 @@ static void xhci_handle_cmd_stop_ep(struct xhci_hcd *xhci, int slot_id,
return;
case EP_STATE_STOPPED:
/*
- * NEC uPD720200 sometimes sets this state and fails with
- * Context Error while continuing to process TRBs.
- * Be conservative and trust EP_CTX_STATE on other chips.
+ * Per xHCI 4.6.9, Stop Endpoint command on a Stopped
+ * EP is a Context State Error, and EP stays Stopped.
+ *
+ * But maybe it failed on Halted, and somebody ran Reset
+ * Endpoint later. EP state is now Stopped and EP_HALTED
+ * still set because Reset EP handler will run after us.
*/
- if (!(xhci->quirks & XHCI_NEC_HOST))
+ if (ep->ep_state & EP_HALTED)
+ break;
+ /*
+ * On some HCs EP state remains Stopped for some tens of
+ * us to a few ms or more after a doorbell ring, and any
+ * new Stop Endpoint fails without aborting the restart.
+ * This handler may run quickly enough to still see this
+ * Stopped state, but it will soon change to Running.
+ *
+ * Assume this bug on unexpected Stop Endpoint failures.
+ * Keep retrying until the EP starts and stops again, on
+ * chips where this is known to help. Wait for 100ms.
+ */
+ if (time_is_before_jiffies(ep->stop_time + msecs_to_jiffies(100)))
break;
fallthrough;
case EP_STATE_RUNNING:
/* Race, HW handled stop ep cmd before ep was running */
- xhci_dbg(xhci, "Stop ep completion ctx error, ep is running\n");
+ xhci_dbg(xhci, "Stop ep completion ctx error, ctx_state %d\n",
+ GET_EP_CTX_STATE(ep_ctx));
command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
if (!command) {
@@ -1338,8 +1383,8 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
struct xhci_virt_ep *ep;
struct xhci_ep_ctx *ep_ctx;
struct xhci_slot_ctx *slot_ctx;
+ struct xhci_stream_ctx *stream_ctx;
struct xhci_td *td, *tmp_td;
- bool deferred = false;
ep_index = TRB_TO_EP_INDEX(le32_to_cpu(trb->generic.field[3]));
stream_id = TRB_TO_STREAM_ID(le32_to_cpu(trb->generic.field[2]));
@@ -1360,6 +1405,11 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
trace_xhci_handle_cmd_set_deq(slot_ctx);
trace_xhci_handle_cmd_set_deq_ep(ep_ctx);
+ if (ep->ep_state & EP_HAS_STREAMS) {
+ stream_ctx = &ep->stream_info->stream_ctx_array[stream_id];
+ trace_xhci_handle_cmd_set_deq_stream(ep->stream_info, stream_id);
+ }
+
if (cmd_comp_code != COMP_SUCCESS) {
unsigned int ep_state;
unsigned int slot_state;
@@ -1396,9 +1446,7 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
u64 deq;
/* 4.6.10 deq ptr is written to the stream ctx for streams */
if (ep->ep_state & EP_HAS_STREAMS) {
- struct xhci_stream_ctx *ctx =
- &ep->stream_info->stream_ctx_array[stream_id];
- deq = le64_to_cpu(ctx->stream_ring) & SCTX_DEQ_MASK;
+ deq = le64_to_cpu(stream_ctx->stream_ring) & SCTX_DEQ_MASK;
/*
* Cadence xHCI controllers store some endpoint state
@@ -1410,8 +1458,8 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
* To fix this issue driver must clear Rsvd0 field.
*/
if (xhci->quirks & XHCI_CDNS_SCTX_QUIRK) {
- ctx->reserved[0] = 0;
- ctx->reserved[1] = 0;
+ stream_ctx->reserved[0] = 0;
+ stream_ctx->reserved[1] = 0;
}
} else {
deq = le64_to_cpu(ep_ctx->deq) & ~EP_CTX_CYCLE_MASK;
@@ -1440,8 +1488,6 @@ static void xhci_handle_cmd_set_deq(struct xhci_hcd *xhci, int slot_id,
xhci_dbg(ep->xhci, "%s: Giveback cancelled URB %p TD\n",
__func__, td->urb);
xhci_td_cleanup(ep->xhci, td, ep_ring, td->status);
- } else if (td->cancel_status == TD_CLEARING_CACHE_DEFERRED) {
- deferred = true;
} else {
xhci_dbg(ep->xhci, "%s: Keep cancelled URB %p TD as cancel_status is %d\n",
__func__, td->urb, td->cancel_status);
@@ -1452,11 +1498,15 @@ cleanup:
ep->queued_deq_seg = NULL;
ep->queued_deq_ptr = NULL;
- if (deferred) {
- /* We have more streams to clear */
+ /* Check for deferred or newly cancelled TDs */
+ if (!list_empty(&ep->cancelled_td_list)) {
xhci_dbg(ep->xhci, "%s: Pending TDs to clear, continuing with invalidation\n",
__func__);
xhci_invalidate_cancelled_tds(ep);
+ /* Try to restart the endpoint if all is done */
+ ring_doorbell_for_active_rings(xhci, slot_id, ep_index);
+ /* Start giving back any TDs invalidated above */
+ xhci_giveback_invalidated_tds(ep);
} else {
/* Restart any rings with pending URBs */
xhci_dbg(ep->xhci, "%s: All TDs cleared, ring doorbell\n", __func__);
@@ -1716,7 +1766,7 @@ static void handle_cmd_completion(struct xhci_hcd *xhci,
cmd_dma = le64_to_cpu(event->cmd_trb);
cmd_trb = xhci->cmd_ring->dequeue;
- trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic);
+ trace_xhci_handle_command(xhci->cmd_ring, &cmd_trb->generic, cmd_dma);
cmd_comp_code = GET_COMP_CODE(le32_to_cpu(event->status));
@@ -2074,7 +2124,7 @@ struct xhci_segment *trb_in_td(struct xhci_hcd *xhci, struct xhci_td *td, dma_ad
dma_addr_t end_trb_dma;
struct xhci_segment *cur_seg;
- start_dma = xhci_trb_virt_to_dma(td->start_seg, td->first_trb);
+ start_dma = xhci_trb_virt_to_dma(td->start_seg, td->start_trb);
cur_seg = td->start_seg;
do {
@@ -2084,7 +2134,7 @@ struct xhci_segment *trb_in_td(struct xhci_hcd *xhci, struct xhci_td *td, dma_ad
end_seg_dma = xhci_trb_virt_to_dma(cur_seg,
&cur_seg->trbs[TRBS_PER_SEGMENT - 1]);
/* If the end TRB isn't in this segment, this is set to 0 */
- end_trb_dma = xhci_trb_virt_to_dma(cur_seg, td->last_trb);
+ end_trb_dma = xhci_trb_virt_to_dma(cur_seg, td->end_trb);
if (debug)
xhci_warn(xhci,
@@ -2184,9 +2234,9 @@ int xhci_is_vendor_info_code(struct xhci_hcd *xhci, unsigned int trb_comp_code)
return 0;
}
-static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
- struct xhci_ring *ep_ring, struct xhci_td *td,
- u32 trb_comp_code)
+static void finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+ struct xhci_ring *ep_ring, struct xhci_td *td,
+ u32 trb_comp_code)
{
struct xhci_ep_ctx *ep_ctx;
@@ -2201,7 +2251,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
* stopped TDs. A stopped TD may be restarted, so don't update
* the ring dequeue pointer or take this TD off any lists yet.
*/
- return 0;
+ return;
case COMP_USB_TRANSACTION_ERROR:
case COMP_BABBLE_DETECTED_ERROR:
case COMP_SPLIT_TRANSACTION_ERROR:
@@ -2226,8 +2276,8 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
!list_empty(&td->cancelled_td_list)) {
xhci_dbg(xhci, "Already resolving halted ep for 0x%llx\n",
(unsigned long long)xhci_trb_virt_to_dma(
- td->start_seg, td->first_trb));
- return 0;
+ td->start_seg, td->start_trb));
+ return;
}
/* endpoint not halted, don't reset it */
break;
@@ -2235,7 +2285,7 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
/* Almost same procedure as for STALL_ERROR below */
xhci_clear_hub_tt_buffer(xhci, td, ep);
xhci_handle_halted_endpoint(xhci, ep, td, EP_HARD_RESET);
- return 0;
+ return;
case COMP_STALL_ERROR:
/*
* xhci internal endpoint state will go to a "halt" state for
@@ -2252,28 +2302,22 @@ static int finish_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
xhci_handle_halted_endpoint(xhci, ep, td, EP_HARD_RESET);
- return 0; /* xhci_handle_halted_endpoint marked td cancelled */
+ return; /* xhci_handle_halted_endpoint marked td cancelled */
default:
break;
}
- /* Update ring dequeue pointer */
- ep_ring->dequeue = td->last_trb;
- ep_ring->deq_seg = td->last_trb_seg;
- inc_deq(xhci, ep_ring);
-
- return xhci_td_cleanup(xhci, td, ep_ring, td->status);
+ xhci_dequeue_td(xhci, td, ep_ring, td->status);
}
-/* sum trb lengths from ring dequeue up to stop_trb, _excluding_ stop_trb */
-static int sum_trb_lengths(struct xhci_hcd *xhci, struct xhci_ring *ring,
- union xhci_trb *stop_trb)
+/* sum trb lengths from the first trb up to stop_trb, _excluding_ stop_trb */
+static u32 sum_trb_lengths(struct xhci_td *td, union xhci_trb *stop_trb)
{
u32 sum;
- union xhci_trb *trb = ring->dequeue;
- struct xhci_segment *seg = ring->deq_seg;
+ union xhci_trb *trb = td->start_trb;
+ struct xhci_segment *seg = td->start_seg;
- for (sum = 0; trb != stop_trb; next_trb(xhci, ring, &seg, &trb)) {
+ for (sum = 0; trb != stop_trb; next_trb(&seg, &trb)) {
if (!trb_is_noop(trb) && !trb_is_link(trb))
sum += TRB_LEN(le32_to_cpu(trb->generic.field[2]));
}
@@ -2283,9 +2327,9 @@ static int sum_trb_lengths(struct xhci_hcd *xhci, struct xhci_ring *ring,
/*
* Process control tds, update urb status and actual_length.
*/
-static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
- struct xhci_ring *ep_ring, struct xhci_td *td,
- union xhci_trb *ep_trb, struct xhci_transfer_event *event)
+static void process_ctrl_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+ struct xhci_ring *ep_ring, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event)
{
struct xhci_ep_ctx *ep_ctx;
u32 trb_comp_code;
@@ -2364,7 +2408,7 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
td->urb_length_set = true;
td->urb->actual_length = requested - remaining;
xhci_dbg(xhci, "Waiting for status stage event\n");
- return 0;
+ return;
}
/* at status stage */
@@ -2372,15 +2416,15 @@ static int process_ctrl_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
td->urb->actual_length = requested;
finish_td:
- return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
+ finish_td(xhci, ep, ep_ring, td, trb_comp_code);
}
/*
* Process isochronous tds, update urb packet status and actual_length.
*/
-static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
- struct xhci_ring *ep_ring, struct xhci_td *td,
- union xhci_trb *ep_trb, struct xhci_transfer_event *event)
+static void process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+ struct xhci_ring *ep_ring, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event)
{
struct urb_priv *urb_priv;
int idx;
@@ -2425,7 +2469,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
fallthrough;
case COMP_ISOCH_BUFFER_OVERRUN:
frame->status = -EOVERFLOW;
- if (ep_trb != td->last_trb)
+ if (ep_trb != td->end_trb)
td->error_mid_td = true;
break;
case COMP_INCOMPATIBLE_DEVICE_ERROR:
@@ -2435,14 +2479,14 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
case COMP_USB_TRANSACTION_ERROR:
frame->status = -EPROTO;
sum_trbs_for_length = true;
- if (ep_trb != td->last_trb)
+ if (ep_trb != td->end_trb)
td->error_mid_td = true;
break;
case COMP_STOPPED:
sum_trbs_for_length = true;
break;
case COMP_STOPPED_SHORT_PACKET:
- /* field normally containing residue now contains tranferred */
+ /* field normally containing residue now contains transferred */
frame->status = short_framestatus;
requested = remaining;
break;
@@ -2462,7 +2506,7 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
goto finish_td;
if (sum_trbs_for_length)
- frame->actual_length = sum_trb_lengths(xhci, ep->ring, ep_trb) +
+ frame->actual_length = sum_trb_lengths(td, ep_trb) +
ep_trb_len - remaining;
else
frame->actual_length = requested;
@@ -2471,17 +2515,16 @@ static int process_isoc_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
finish_td:
/* Don't give back TD yet if we encountered an error mid TD */
- if (td->error_mid_td && ep_trb != td->last_trb) {
+ if (td->error_mid_td && ep_trb != td->end_trb) {
xhci_dbg(xhci, "Error mid isoc TD, wait for final completion event\n");
td->urb_length_set = true;
- return 0;
+ return;
}
-
- return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
+ finish_td(xhci, ep, ep_ring, td, trb_comp_code);
}
-static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
- struct xhci_virt_ep *ep, int status)
+static void skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
+ struct xhci_virt_ep *ep, int status)
{
struct urb_priv *urb_priv;
struct usb_iso_packet_descriptor *frame;
@@ -2497,20 +2540,15 @@ static int skip_isoc_td(struct xhci_hcd *xhci, struct xhci_td *td,
/* calc actual length */
frame->actual_length = 0;
- /* Update ring dequeue pointer */
- ep->ring->dequeue = td->last_trb;
- ep->ring->deq_seg = td->last_trb_seg;
- inc_deq(xhci, ep->ring);
-
- return xhci_td_cleanup(xhci, td, ep->ring, status);
+ xhci_dequeue_td(xhci, td, ep->ring, status);
}
/*
* Process bulk and interrupt tds, update urb status and actual_length.
*/
-static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
- struct xhci_ring *ep_ring, struct xhci_td *td,
- union xhci_trb *ep_trb, struct xhci_transfer_event *event)
+static void process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+ struct xhci_ring *ep_ring, struct xhci_td *td,
+ union xhci_trb *ep_trb, struct xhci_transfer_event *event)
{
struct xhci_slot_ctx *slot_ctx;
u32 trb_comp_code;
@@ -2526,7 +2564,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
case COMP_SUCCESS:
ep->err_count = 0;
/* handle success with untransferred data as short packet */
- if (ep_trb != td->last_trb || remaining) {
+ if (ep_trb != td->end_trb || remaining) {
xhci_warn(xhci, "WARN Successful completion on short TX\n");
xhci_dbg(xhci, "ep %#x - asked for %d bytes, %d bytes untransferred\n",
td->urb->ep->desc.bEndpointAddress,
@@ -2542,7 +2580,7 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
goto finish_td;
case COMP_STOPPED_LENGTH_INVALID:
/* stopped on ep trb with invalid length, exclude it */
- td->urb->actual_length = sum_trb_lengths(xhci, ep_ring, ep_trb);
+ td->urb->actual_length = sum_trb_lengths(td, ep_trb);
goto finish_td;
case COMP_USB_TRANSACTION_ERROR:
if (xhci->quirks & XHCI_NO_SOFT_RETRY ||
@@ -2553,17 +2591,17 @@ static int process_bulk_intr_td(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
td->status = 0;
xhci_handle_halted_endpoint(xhci, ep, td, EP_SOFT_RESET);
- return 0;
+ return;
default:
/* do nothing */
break;
}
- if (ep_trb == td->last_trb)
+ if (ep_trb == td->end_trb)
td->urb->actual_length = requested - remaining;
else
td->urb->actual_length =
- sum_trb_lengths(xhci, ep_ring, ep_trb) +
+ sum_trb_lengths(td, ep_trb) +
ep_trb_len - remaining;
finish_td:
if (remaining > requested) {
@@ -2572,7 +2610,7 @@ finish_td:
td->urb->actual_length = 0;
}
- return finish_td(xhci, ep, ep_ring, td, trb_comp_code);
+ finish_td(xhci, ep, ep_ring, td, trb_comp_code);
}
/* Transfer events which don't point to a transfer TRB, see xhci 4.17.4 */
@@ -2792,10 +2830,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
if (td && td->error_mid_td && !trb_in_td(xhci, td, ep_trb_dma, false)) {
xhci_dbg(xhci, "Missing TD completion event after mid TD error\n");
- ep_ring->dequeue = td->last_trb;
- ep_ring->deq_seg = td->last_trb_seg;
- inc_deq(xhci, ep_ring);
- xhci_td_cleanup(xhci, td, ep_ring, td->status);
+ xhci_dequeue_td(xhci, td, ep_ring, td->status);
}
if (list_empty(&ep_ring->td_list)) {
@@ -2889,7 +2924,7 @@ static int handle_tx_event(struct xhci_hcd *xhci,
ep_ring->last_td_was_short = false;
ep_trb = &ep_seg->trbs[(ep_trb_dma - ep_seg->dma) / sizeof(*ep_trb)];
- trace_xhci_handle_transfer(ep_ring, (struct xhci_generic_trb *) ep_trb);
+ trace_xhci_handle_transfer(ep_ring, (struct xhci_generic_trb *) ep_trb, ep_trb_dma);
/*
* No-op TRB could trigger interrupts in a case where a URB was killed
@@ -2939,7 +2974,9 @@ static int xhci_handle_event_trb(struct xhci_hcd *xhci, struct xhci_interrupter
{
u32 trb_type;
- trace_xhci_handle_event(ir->event_ring, &event->generic);
+ trace_xhci_handle_event(ir->event_ring, &event->generic,
+ xhci_trb_virt_to_dma(ir->event_ring->deq_seg,
+ ir->event_ring->dequeue));
/*
* Barrier between reading the TRB_CYCLE (valid) flag before, and any
@@ -3162,7 +3199,8 @@ static void queue_trb(struct xhci_hcd *xhci, struct xhci_ring *ring,
wmb();
trb->field[3] = cpu_to_le32(field4);
- trace_xhci_queue_trb(ring, trb);
+ trace_xhci_queue_trb(ring, trb,
+ xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue));
inc_enq(xhci, ring, more_trbs_coming);
}
@@ -3302,7 +3340,7 @@ static int prepare_transfer(struct xhci_hcd *xhci,
/* Add this TD to the tail of the endpoint ring's TD list */
list_add_tail(&td->td_list, &ep_ring->td_list);
td->start_seg = ep_ring->enq_seg;
- td->first_trb = ep_ring->enqueue;
+ td->start_trb = ep_ring->enqueue;
return 0;
}
@@ -3641,8 +3679,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
field &= ~TRB_CHAIN;
field |= TRB_IOC;
more_trbs_coming = false;
- td->last_trb = ring->enqueue;
- td->last_trb_seg = ring->enq_seg;
+ td->end_trb = ring->enqueue;
+ td->end_seg = ring->enq_seg;
if (xhci_urb_suitable_for_idt(urb)) {
memcpy(&send_addr, urb->transfer_buffer,
trb_buff_len);
@@ -3690,8 +3728,8 @@ int xhci_queue_bulk_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
ret = prepare_transfer(xhci, xhci->devs[slot_id],
ep_index, urb->stream_id,
1, urb, 1, mem_flags);
- urb_priv->td[1].last_trb = ring->enqueue;
- urb_priv->td[1].last_trb_seg = ring->enq_seg;
+ urb_priv->td[1].end_trb = ring->enqueue;
+ urb_priv->td[1].end_seg = ring->enq_seg;
field = TRB_TYPE(TRB_NORMAL) | ring->cycle_state | TRB_IOC;
queue_trb(xhci, ring, 0, 0, 0, TRB_INTR_TARGET(0), field);
}
@@ -3727,6 +3765,20 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
if (!urb->setup_packet)
return -EINVAL;
+ if ((xhci->quirks & XHCI_ETRON_HOST) &&
+ urb->dev->speed >= USB_SPEED_SUPER) {
+ /*
+ * If next available TRB is the Link TRB in the ring segment then
+ * enqueue a No Op TRB, this can prevent the Setup and Data Stage
+ * TRB to be breaked by the Link TRB.
+ */
+ if (trb_is_link(ep_ring->enqueue + 1)) {
+ field = TRB_TYPE(TRB_TR_NOOP) | ep_ring->cycle_state;
+ queue_trb(xhci, ep_ring, false, 0, 0,
+ TRB_INTR_TARGET(0), field);
+ }
+ }
+
/* 1 TRB for setup, 1 for status */
num_trbs = 2;
/*
@@ -3815,8 +3867,8 @@ int xhci_queue_ctrl_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
}
/* Save the DMA address of the last TRB in the TD */
- td->last_trb = ep_ring->enqueue;
- td->last_trb_seg = ep_ring->enq_seg;
+ td->end_trb = ep_ring->enqueue;
+ td->end_seg = ep_ring->enq_seg;
/* Queue status TRB - see Table 7 and sections 4.11.2.2 and 6.4.1.2.3 */
/* If the device sent data, the status stage is an OUT transfer */
@@ -4101,8 +4153,8 @@ static int xhci_queue_isoc_tx(struct xhci_hcd *xhci, gfp_t mem_flags,
field |= TRB_CHAIN;
} else {
more_trbs_coming = false;
- td->last_trb = ep_ring->enqueue;
- td->last_trb_seg = ep_ring->enq_seg;
+ td->end_trb = ep_ring->enqueue;
+ td->end_seg = ep_ring->enq_seg;
field |= TRB_IOC;
if (trb_block_event_intr(xhci, num_tds, i, ir))
field |= TRB_BEI;
@@ -4168,14 +4220,14 @@ cleanup:
/* Use the first TD as a temporary variable to turn the TDs we've queued
* into No-ops with a software-owned cycle bit. That way the hardware
* won't accidentally start executing bogus TDs when we partially
- * overwrite them. td->first_trb and td->start_seg are already set.
+ * overwrite them. td->start_trb and td->start_seg are already set.
*/
- urb_priv->td[0].last_trb = ep_ring->enqueue;
+ urb_priv->td[0].end_trb = ep_ring->enqueue;
/* Every TRB except the first & last will have its cycle bit flipped. */
- td_to_noop(xhci, ep_ring, &urb_priv->td[0], true);
+ td_to_noop(&urb_priv->td[0], true);
/* Reset the ring enqueue back to the first TRB and its cycle bit. */
- ep_ring->enqueue = urb_priv->td[0].first_trb;
+ ep_ring->enqueue = urb_priv->td[0].start_trb;
ep_ring->enq_seg = urb_priv->td[0].start_seg;
ep_ring->cycle_state = start_cycle;
usb_hcd_unlink_urb_from_ep(bus_to_hcd(urb->dev->bus), urb);
diff --git a/drivers/usb/host/xhci-tegra.c b/drivers/usb/host/xhci-tegra.c
index 76f228e7443c..06ae193ec874 100644
--- a/drivers/usb/host/xhci-tegra.c
+++ b/drivers/usb/host/xhci-tegra.c
@@ -2664,7 +2664,7 @@ MODULE_DEVICE_TABLE(of, tegra_xusb_of_match);
static struct platform_driver tegra_xusb_driver = {
.probe = tegra_xusb_probe,
- .remove_new = tegra_xusb_remove,
+ .remove = tegra_xusb_remove,
.shutdown = tegra_xusb_shutdown,
.driver = {
.name = "tegra-xusb",
diff --git a/drivers/usb/host/xhci-trace.h b/drivers/usb/host/xhci-trace.h
index 24405315ffe6..bfb5c5c17012 100644
--- a/drivers/usb/host/xhci-trace.h
+++ b/drivers/usb/host/xhci-trace.h
@@ -108,9 +108,10 @@ DEFINE_EVENT(xhci_log_ctx, xhci_address_ctx,
);
DECLARE_EVENT_CLASS(xhci_log_trb,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb),
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma),
TP_STRUCT__entry(
+ __field(dma_addr_t, dma)
__field(u32, type)
__field(u32, field0)
__field(u32, field1)
@@ -118,51 +119,54 @@ DECLARE_EVENT_CLASS(xhci_log_trb,
__field(u32, field3)
),
TP_fast_assign(
+ __entry->dma = dma;
__entry->type = ring->type;
__entry->field0 = le32_to_cpu(trb->field[0]);
__entry->field1 = le32_to_cpu(trb->field[1]);
__entry->field2 = le32_to_cpu(trb->field[2]);
__entry->field3 = le32_to_cpu(trb->field[3]);
),
- TP_printk("%s: %s", xhci_ring_type_string(__entry->type),
+ TP_printk("%s: @%pad %s",
+ xhci_ring_type_string(__entry->type), &__entry->dma,
xhci_decode_trb(__get_buf(XHCI_MSG_MAX), XHCI_MSG_MAX, __entry->field0,
__entry->field1, __entry->field2, __entry->field3)
)
);
DEFINE_EVENT(xhci_log_trb, xhci_handle_event,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DEFINE_EVENT(xhci_log_trb, xhci_handle_command,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DEFINE_EVENT(xhci_log_trb, xhci_handle_transfer,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DEFINE_EVENT(xhci_log_trb, xhci_queue_trb,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
+
);
DEFINE_EVENT(xhci_log_trb, xhci_dbc_handle_event,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DEFINE_EVENT(xhci_log_trb, xhci_dbc_handle_transfer,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DEFINE_EVENT(xhci_log_trb, xhci_dbc_gadget_ep_queue,
- TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb),
- TP_ARGS(ring, trb)
+ TP_PROTO(struct xhci_ring *ring, struct xhci_generic_trb *trb, dma_addr_t dma),
+ TP_ARGS(ring, trb, dma)
);
DECLARE_EVENT_CLASS(xhci_log_free_virt_dev,
@@ -310,6 +314,37 @@ DEFINE_EVENT(xhci_log_urb, xhci_urb_dequeue,
TP_ARGS(urb)
);
+DECLARE_EVENT_CLASS(xhci_log_stream_ctx,
+ TP_PROTO(struct xhci_stream_info *info, unsigned int stream_id),
+ TP_ARGS(info, stream_id),
+ TP_STRUCT__entry(
+ __field(unsigned int, stream_id)
+ __field(u64, stream_ring)
+ __field(dma_addr_t, ctx_array_dma)
+
+ ),
+ TP_fast_assign(
+ __entry->stream_id = stream_id;
+ __entry->stream_ring = le64_to_cpu(info->stream_ctx_array[stream_id].stream_ring);
+ __entry->ctx_array_dma = info->ctx_array_dma + stream_id * 16;
+
+ ),
+ TP_printk("stream %u ctx @%pad: SCT %llu deq %llx", __entry->stream_id,
+ &__entry->ctx_array_dma, CTX_TO_SCT(__entry->stream_ring),
+ __entry->stream_ring
+ )
+);
+
+DEFINE_EVENT(xhci_log_stream_ctx, xhci_alloc_stream_info_ctx,
+ TP_PROTO(struct xhci_stream_info *info, unsigned int stream_id),
+ TP_ARGS(info, stream_id)
+);
+
+DEFINE_EVENT(xhci_log_stream_ctx, xhci_handle_cmd_set_deq_stream,
+ TP_PROTO(struct xhci_stream_info *info, unsigned int stream_id),
+ TP_ARGS(info, stream_id)
+);
+
DECLARE_EVENT_CLASS(xhci_log_ep_ctx,
TP_PROTO(struct xhci_ep_ctx *ctx),
TP_ARGS(ctx),
@@ -454,8 +489,6 @@ DECLARE_EVENT_CLASS(xhci_log_ring,
__field(void *, ring)
__field(dma_addr_t, enq)
__field(dma_addr_t, deq)
- __field(dma_addr_t, enq_seg)
- __field(dma_addr_t, deq_seg)
__field(unsigned int, num_segs)
__field(unsigned int, stream_id)
__field(unsigned int, cycle_state)
@@ -466,17 +499,15 @@ DECLARE_EVENT_CLASS(xhci_log_ring,
__entry->type = ring->type;
__entry->num_segs = ring->num_segs;
__entry->stream_id = ring->stream_id;
- __entry->enq_seg = ring->enq_seg->dma;
- __entry->deq_seg = ring->deq_seg->dma;
__entry->cycle_state = ring->cycle_state;
__entry->bounce_buf_len = ring->bounce_buf_len;
__entry->enq = xhci_trb_virt_to_dma(ring->enq_seg, ring->enqueue);
__entry->deq = xhci_trb_virt_to_dma(ring->deq_seg, ring->dequeue);
),
- TP_printk("%s %p: enq %pad(%pad) deq %pad(%pad) segs %d stream %d bounce %d cycle %d",
+ TP_printk("%s %p: enq %pad deq %pad segs %d stream %d bounce %d cycle %d",
xhci_ring_type_string(__entry->type), __entry->ring,
- &__entry->enq, &__entry->enq_seg,
- &__entry->deq, &__entry->deq_seg,
+ &__entry->enq,
+ &__entry->deq,
__entry->num_segs,
__entry->stream_id,
__entry->bounce_buf_len,
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 899c0effb5d3..5ebde8cae4fc 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -8,6 +8,7 @@
* Some code borrowed from the Linux EHCI driver.
*/
+#include <linux/jiffies.h>
#include <linux/pci.h>
#include <linux/iommu.h>
#include <linux/iopoll.h>
@@ -40,15 +41,15 @@ MODULE_PARM_DESC(quirks, "Bit flags for quirks to be enabled as default");
static bool td_on_ring(struct xhci_td *td, struct xhci_ring *ring)
{
- struct xhci_segment *seg = ring->first_seg;
+ struct xhci_segment *seg;
if (!td || !td->start_seg)
return false;
- do {
+
+ xhci_for_each_ring_seg(ring->first_seg, seg) {
if (seg == td->start_seg)
return true;
- seg = seg->next;
- } while (seg && seg != ring->first_seg);
+ }
return false;
}
@@ -473,14 +474,7 @@ static int xhci_init(struct usb_hcd *hcd)
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "xhci_init");
spin_lock_init(&xhci->lock);
- if (xhci->hci_version == 0x95 && link_quirk) {
- xhci_dbg_trace(xhci, trace_xhci_dbg_quirks,
- "QUIRK: Not clearing Link TRB chain bits.");
- xhci->quirks |= XHCI_LINK_TRB_QUIRK;
- } else {
- xhci_dbg_trace(xhci, trace_xhci_dbg_init,
- "xHCI doesn't need link TRB QUIRK");
- }
+
retval = xhci_mem_init(xhci, GFP_KERNEL);
xhci_dbg_trace(xhci, trace_xhci_dbg_init, "Finished xhci_init");
@@ -785,16 +779,10 @@ static void xhci_clear_command_ring(struct xhci_hcd *xhci)
struct xhci_segment *seg;
ring = xhci->cmd_ring;
- seg = ring->deq_seg;
- do {
- memset(seg->trbs, 0,
- sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1));
- seg->trbs[TRBS_PER_SEGMENT - 1].link.control &=
- cpu_to_le32(~TRB_CYCLE);
- seg = seg->next;
- } while (seg != ring->deq_seg);
-
- xhci_initialize_ring_info(ring, 1);
+ xhci_for_each_ring_seg(ring->first_seg, seg)
+ memset(seg->trbs, 0, sizeof(union xhci_trb) * (TRBS_PER_SEGMENT - 1));
+
+ xhci_initialize_ring_info(ring);
/*
* Reset the hardware dequeue pointer.
* Yes, this will need to be re-written after resume, but we're paranoid
@@ -1756,7 +1744,7 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
urb->ep->desc.bEndpointAddress,
(unsigned long long) xhci_trb_virt_to_dma(
urb_priv->td[i].start_seg,
- urb_priv->td[i].first_trb));
+ urb_priv->td[i].start_trb));
for (; i < urb_priv->num_tds; i++) {
td = &urb_priv->td[i];
@@ -1768,15 +1756,27 @@ static int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status)
}
}
- /* Queue a stop endpoint command, but only if this is
- * the first cancellation to be handled.
- */
- if (!(ep->ep_state & EP_STOP_CMD_PENDING)) {
+ /* These completion handlers will sort out cancelled TDs for us */
+ if (ep->ep_state & (EP_STOP_CMD_PENDING | EP_HALTED | SET_DEQ_PENDING)) {
+ xhci_dbg(xhci, "Not queuing Stop Endpoint on slot %d ep %d in state 0x%x\n",
+ urb->dev->slot_id, ep_index, ep->ep_state);
+ goto done;
+ }
+
+ /* In this case no commands are pending but the endpoint is stopped */
+ if (ep->ep_state & EP_CLEARING_TT) {
+ /* and cancelled TDs can be given back right away */
+ xhci_dbg(xhci, "Invalidating TDs instantly on slot %d ep %d in state 0x%x\n",
+ urb->dev->slot_id, ep_index, ep->ep_state);
+ xhci_process_cancelled_tds(ep);
+ } else {
+ /* Otherwise, queue a new Stop Endpoint command */
command = xhci_alloc_command(xhci, false, GFP_ATOMIC);
if (!command) {
ret = -ENOMEM;
goto done;
}
+ ep->stop_time = jiffies;
ep->ep_state |= EP_STOP_CMD_PENDING;
xhci_queue_stop_endpoint(xhci, command, urb->dev->slot_id,
ep_index, 0);
@@ -2794,6 +2794,51 @@ static int xhci_reserve_bandwidth(struct xhci_hcd *xhci,
return -ENOMEM;
}
+/*
+ * Synchronous XHCI stop endpoint helper. Issues the stop endpoint command and
+ * waits for the command completion before returning. This does not call
+ * xhci_handle_cmd_stop_ep(), which has additional handling for 'context error'
+ * cases, along with transfer ring cleanup.
+ *
+ * xhci_stop_endpoint_sync() is intended to be utilized by clients that manage
+ * their own transfer ring, such as offload situations.
+ */
+int xhci_stop_endpoint_sync(struct xhci_hcd *xhci, struct xhci_virt_ep *ep, int suspend,
+ gfp_t gfp_flags)
+{
+ struct xhci_command *command;
+ unsigned long flags;
+ int ret;
+
+ command = xhci_alloc_command(xhci, true, gfp_flags);
+ if (!command)
+ return -ENOMEM;
+
+ spin_lock_irqsave(&xhci->lock, flags);
+ ret = xhci_queue_stop_endpoint(xhci, command, ep->vdev->slot_id,
+ ep->ep_index, suspend);
+ if (ret < 0) {
+ spin_unlock_irqrestore(&xhci->lock, flags);
+ goto out;
+ }
+
+ xhci_ring_cmd_db(xhci);
+ spin_unlock_irqrestore(&xhci->lock, flags);
+
+ wait_for_completion(command->completion);
+
+ /* No handling for COMP_CONTEXT_STATE_ERROR done at command completion*/
+ if (command->status == COMP_COMMAND_ABORTED ||
+ command->status == COMP_COMMAND_RING_STOPPED) {
+ xhci_warn(xhci, "Timeout while waiting for stop endpoint command\n");
+ ret = -ETIME;
+ }
+out:
+ xhci_free_command(xhci, command);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(xhci_stop_endpoint_sync);
/* Issue a configure endpoint command or evaluate context command
* and wait for it to finish.
@@ -3692,6 +3737,8 @@ void xhci_free_device_endpoint_resources(struct xhci_hcd *xhci,
xhci->num_active_eps);
}
+static void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev);
+
/*
* This submits a Reset Device Command, which will set the device state to 0,
* set the device address to 0, and disable all the endpoints except the default
@@ -3762,6 +3809,23 @@ static int xhci_discover_or_reset_device(struct usb_hcd *hcd,
SLOT_STATE_DISABLED)
return 0;
+ if (xhci->quirks & XHCI_ETRON_HOST) {
+ /*
+ * Obtaining a new device slot to inform the xHCI host that
+ * the USB device has been reset.
+ */
+ ret = xhci_disable_slot(xhci, udev->slot_id);
+ xhci_free_virt_device(xhci, udev->slot_id);
+ if (!ret) {
+ ret = xhci_alloc_dev(hcd, udev);
+ if (ret == 1)
+ ret = 0;
+ else
+ ret = -EINVAL;
+ }
+ return ret;
+ }
+
trace_xhci_discover_or_reset_device(slot_ctx);
xhci_dbg(xhci, "Resetting device with slot ID %u\n", slot_id);
@@ -5251,6 +5315,11 @@ int xhci_gen_setup(struct usb_hcd *hcd, xhci_get_quirks_t get_quirks)
if (xhci->hci_version > 0x96)
xhci->quirks |= XHCI_SPURIOUS_SUCCESS;
+ if (xhci->hci_version == 0x95 && link_quirk) {
+ xhci_dbg(xhci, "QUIRK: Not clearing Link TRB chain bits");
+ xhci->quirks |= XHCI_LINK_TRB_QUIRK;
+ }
+
/* Make sure the HC is halted. */
retval = xhci_halt(xhci);
if (retval)
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index f0fb696d5619..4914f0a10cff 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -554,6 +554,7 @@ struct xhci_stream_ctx {
/* Stream Context Types (section 6.4.1) - bits 3:1 of stream ctx deq ptr */
#define SCT_FOR_CTX(p) (((p) & 0x7) << 1)
+#define CTX_TO_SCT(p) (((p) >> 1) & 0x7)
/* Secondary stream array type, dequeue pointer is to a transfer ring */
#define SCT_SEC_TR 0
/* Primary stream array type, dequeue pointer is to a transfer ring */
@@ -690,6 +691,7 @@ struct xhci_virt_ep {
/* Bandwidth checking storage */
struct xhci_bw_info bw_info;
struct list_head bw_endpoint_list;
+ unsigned long stop_time;
/* Isoch Frame ID checking storage */
int next_frame_id;
/* Use new Isoch TRB layout needed for extended TBC support */
@@ -1023,9 +1025,6 @@ enum xhci_setup_dev {
/* Interrupter Target - which MSI-X vector to target the completion event at */
#define TRB_INTR_TARGET(p) (((p) & 0x3ff) << 22)
#define GET_INTR_TARGET(p) (((p) >> 22) & 0x3ff)
-/* Total burst count field, Rsvdz on xhci 1.1 with Extended TBC enabled (ETE) */
-#define TRB_TBC(p) (((p) & 0x3) << 7)
-#define TRB_TLBPC(p) (((p) & 0xf) << 16)
/* Cycle bit - indicates TRB ownership by HC or HCD */
#define TRB_CYCLE (1<<0)
@@ -1059,6 +1058,12 @@ enum xhci_setup_dev {
/* Isochronous TRB specific fields */
#define TRB_SIA (1<<31)
#define TRB_FRAME_ID(p) (((p) & 0x7ff) << 20)
+#define GET_FRAME_ID(p) (((p) >> 20) & 0x7ff)
+/* Total burst count field, Rsvdz on xhci 1.1 with Extended TBC enabled (ETE) */
+#define TRB_TBC(p) (((p) & 0x3) << 7)
+#define GET_TBC(p) (((p) >> 7) & 0x3)
+#define TRB_TLBPC(p) (((p) & 0xf) << 16)
+#define GET_TLBPC(p) (((p) >> 16) & 0xf)
/* TRB cache size for xHC with TRB cache */
#define TRB_CACHE_SIZE_HS 8
@@ -1259,6 +1264,9 @@ static inline const char *xhci_trb_type_string(u8 type)
#define AVOID_BEI_INTERVAL_MIN 8
#define AVOID_BEI_INTERVAL_MAX 32
+#define xhci_for_each_ring_seg(head, seg) \
+ for (seg = head; seg != NULL; seg = (seg->next != head ? seg->next : NULL))
+
struct xhci_segment {
union xhci_trb *trbs;
/* private to HCD */
@@ -1287,9 +1295,9 @@ struct xhci_td {
enum xhci_cancelled_td_status cancel_status;
struct urb *urb;
struct xhci_segment *start_seg;
- union xhci_trb *first_trb;
- union xhci_trb *last_trb;
- struct xhci_segment *last_trb_seg;
+ union xhci_trb *start_trb;
+ struct xhci_segment *end_seg;
+ union xhci_trb *end_trb;
struct xhci_segment *bounce_seg;
/* actual_length of the URB has already been set */
bool urb_length_set;
@@ -1624,6 +1632,7 @@ struct xhci_hcd {
#define XHCI_ZHAOXIN_HOST BIT_ULL(46)
#define XHCI_WRITE_64_HI_LO BIT_ULL(47)
#define XHCI_CDNS_SCTX_QUIRK BIT_ULL(48)
+#define XHCI_ETRON_HOST BIT_ULL(49)
unsigned int num_active_eps;
unsigned int limit_active_eps;
@@ -1788,14 +1797,12 @@ void xhci_slot_copy(struct xhci_hcd *xhci,
int xhci_endpoint_init(struct xhci_hcd *xhci, struct xhci_virt_device *virt_dev,
struct usb_device *udev, struct usb_host_endpoint *ep,
gfp_t mem_flags);
-struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci,
- unsigned int num_segs, unsigned int cycle_state,
+struct xhci_ring *xhci_ring_alloc(struct xhci_hcd *xhci, unsigned int num_segs,
enum xhci_ring_type type, unsigned int max_packet, gfp_t flags);
void xhci_ring_free(struct xhci_hcd *xhci, struct xhci_ring *ring);
int xhci_ring_expansion(struct xhci_hcd *xhci, struct xhci_ring *ring,
unsigned int num_trbs, gfp_t flags);
-void xhci_initialize_ring_info(struct xhci_ring *ring,
- unsigned int cycle_state);
+void xhci_initialize_ring_info(struct xhci_ring *ring);
void xhci_free_endpoint_ring(struct xhci_hcd *xhci,
struct xhci_virt_device *virt_dev,
unsigned int ep_index);
@@ -1913,6 +1920,9 @@ void xhci_ring_doorbell_for_active_rings(struct xhci_hcd *xhci,
void xhci_cleanup_command_queue(struct xhci_hcd *xhci);
void inc_deq(struct xhci_hcd *xhci, struct xhci_ring *ring);
unsigned int count_trbs(u64 addr, u64 len);
+int xhci_stop_endpoint_sync(struct xhci_hcd *xhci, struct xhci_virt_ep *ep,
+ int suspend, gfp_t gfp_flags);
+void xhci_process_cancelled_tds(struct xhci_virt_ep *ep);
/* xHCI roothub code */
void xhci_set_link_state(struct xhci_hcd *xhci, struct xhci_port *port,
@@ -2070,7 +2080,6 @@ static inline const char *xhci_decode_trb(char *str, size_t size,
field3 & TRB_CYCLE ? 'C' : 'c');
break;
case TRB_NORMAL:
- case TRB_ISOC:
case TRB_EVENT_DATA:
case TRB_TR_NOOP:
snprintf(str, size,
@@ -2087,7 +2096,25 @@ static inline const char *xhci_decode_trb(char *str, size_t size,
field3 & TRB_ENT ? 'E' : 'e',
field3 & TRB_CYCLE ? 'C' : 'c');
break;
-
+ case TRB_ISOC:
+ snprintf(str, size,
+ "Buffer %08x%08x length %d TD size/TBC %d intr %d type '%s' TBC %u TLBPC %u frame_id %u flags %c:%c:%c:%c:%c:%c:%c:%c:%c",
+ field1, field0, TRB_LEN(field2), GET_TD_SIZE(field2),
+ GET_INTR_TARGET(field2),
+ xhci_trb_type_string(type),
+ GET_TBC(field3),
+ GET_TLBPC(field3),
+ GET_FRAME_ID(field3),
+ field3 & TRB_SIA ? 'S' : 's',
+ field3 & TRB_BEI ? 'B' : 'b',
+ field3 & TRB_IDT ? 'I' : 'i',
+ field3 & TRB_IOC ? 'I' : 'i',
+ field3 & TRB_CHAIN ? 'C' : 'c',
+ field3 & TRB_NO_SNOOP ? 'S' : 's',
+ field3 & TRB_ISP ? 'I' : 'i',
+ field3 & TRB_ENT ? 'E' : 'e',
+ field3 & TRB_CYCLE ? 'C' : 'c');
+ break;
case TRB_CMD_NOOP:
case TRB_ENABLE_SLOT:
snprintf(str, size,
diff --git a/drivers/usb/isp1760/Kconfig b/drivers/usb/isp1760/Kconfig
index 2ed2b73291d1..e19178f3cdd3 100644
--- a/drivers/usb/isp1760/Kconfig
+++ b/drivers/usb/isp1760/Kconfig
@@ -26,7 +26,7 @@ config USB_ISP1761_UDC
if USB_ISP1760
choice
- bool "ISP1760 Mode Selection"
+ prompt "ISP1760 Mode Selection"
default USB_ISP1760_DUAL_ROLE if (USB && USB_GADGET)
default USB_ISP1760_HOST_ROLE if (USB && !USB_GADGET)
default USB_ISP1760_GADGET_ROLE if (!USB && USB_GADGET)
diff --git a/drivers/usb/isp1760/isp1760-if.c b/drivers/usb/isp1760/isp1760-if.c
index fe1e3985419a..a64190addba6 100644
--- a/drivers/usb/isp1760/isp1760-if.c
+++ b/drivers/usb/isp1760/isp1760-if.c
@@ -263,7 +263,7 @@ MODULE_DEVICE_TABLE(of, isp1760_of_match);
static struct platform_driver isp1760_plat_driver = {
.probe = isp1760_plat_probe,
- .remove_new = isp1760_plat_remove,
+ .remove = isp1760_plat_remove,
.driver = {
.name = "isp1760",
.of_match_table = of_match_ptr(isp1760_of_match),
diff --git a/drivers/usb/misc/chaoskey.c b/drivers/usb/misc/chaoskey.c
index 6fb5140e29b9..225863321dc4 100644
--- a/drivers/usb/misc/chaoskey.c
+++ b/drivers/usb/misc/chaoskey.c
@@ -27,6 +27,8 @@ static struct usb_class_driver chaoskey_class;
static int chaoskey_rng_read(struct hwrng *rng, void *data,
size_t max, bool wait);
+static DEFINE_MUTEX(chaoskey_list_lock);
+
#define usb_dbg(usb_if, format, arg...) \
dev_dbg(&(usb_if)->dev, format, ## arg)
@@ -233,6 +235,7 @@ static void chaoskey_disconnect(struct usb_interface *interface)
usb_deregister_dev(interface, &chaoskey_class);
usb_set_intfdata(interface, NULL);
+ mutex_lock(&chaoskey_list_lock);
mutex_lock(&dev->lock);
dev->present = false;
@@ -244,6 +247,7 @@ static void chaoskey_disconnect(struct usb_interface *interface)
} else
mutex_unlock(&dev->lock);
+ mutex_unlock(&chaoskey_list_lock);
usb_dbg(interface, "disconnect done");
}
@@ -251,6 +255,7 @@ static int chaoskey_open(struct inode *inode, struct file *file)
{
struct chaoskey *dev;
struct usb_interface *interface;
+ int rv = 0;
/* get the interface from minor number and driver information */
interface = usb_find_interface(&chaoskey_driver, iminor(inode));
@@ -266,18 +271,23 @@ static int chaoskey_open(struct inode *inode, struct file *file)
}
file->private_data = dev;
+ mutex_lock(&chaoskey_list_lock);
mutex_lock(&dev->lock);
- ++dev->open;
+ if (dev->present)
+ ++dev->open;
+ else
+ rv = -ENODEV;
mutex_unlock(&dev->lock);
+ mutex_unlock(&chaoskey_list_lock);
- usb_dbg(interface, "open success");
- return 0;
+ return rv;
}
static int chaoskey_release(struct inode *inode, struct file *file)
{
struct chaoskey *dev = file->private_data;
struct usb_interface *interface;
+ int rv = 0;
if (dev == NULL)
return -ENODEV;
@@ -286,14 +296,15 @@ static int chaoskey_release(struct inode *inode, struct file *file)
usb_dbg(interface, "release");
+ mutex_lock(&chaoskey_list_lock);
mutex_lock(&dev->lock);
usb_dbg(interface, "open count at release is %d", dev->open);
if (dev->open <= 0) {
usb_dbg(interface, "invalid open count (%d)", dev->open);
- mutex_unlock(&dev->lock);
- return -ENODEV;
+ rv = -ENODEV;
+ goto bail;
}
--dev->open;
@@ -302,13 +313,15 @@ static int chaoskey_release(struct inode *inode, struct file *file)
if (dev->open == 0) {
mutex_unlock(&dev->lock);
chaoskey_free(dev);
- } else
- mutex_unlock(&dev->lock);
- } else
- mutex_unlock(&dev->lock);
-
+ goto destruction;
+ }
+ }
+bail:
+ mutex_unlock(&dev->lock);
+destruction:
+ mutex_unlock(&chaoskey_list_lock);
usb_dbg(interface, "release success");
- return 0;
+ return rv;
}
static void chaos_read_callback(struct urb *urb)
diff --git a/drivers/usb/misc/iowarrior.c b/drivers/usb/misc/iowarrior.c
index 6d28467ce352..365c10069345 100644
--- a/drivers/usb/misc/iowarrior.c
+++ b/drivers/usb/misc/iowarrior.c
@@ -277,28 +277,45 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer,
struct iowarrior *dev;
int read_idx;
int offset;
+ int retval;
dev = file->private_data;
+ if (file->f_flags & O_NONBLOCK) {
+ retval = mutex_trylock(&dev->mutex);
+ if (!retval)
+ return -EAGAIN;
+ } else {
+ retval = mutex_lock_interruptible(&dev->mutex);
+ if (retval)
+ return -ERESTARTSYS;
+ }
+
/* verify that the device wasn't unplugged */
- if (!dev || !dev->present)
- return -ENODEV;
+ if (!dev->present) {
+ retval = -ENODEV;
+ goto exit;
+ }
dev_dbg(&dev->interface->dev, "minor %d, count = %zd\n",
dev->minor, count);
/* read count must be packet size (+ time stamp) */
if ((count != dev->report_size)
- && (count != (dev->report_size + 1)))
- return -EINVAL;
+ && (count != (dev->report_size + 1))) {
+ retval = -EINVAL;
+ goto exit;
+ }
/* repeat until no buffer overrun in callback handler occur */
do {
atomic_set(&dev->overflow_flag, 0);
if ((read_idx = read_index(dev)) == -1) {
/* queue empty */
- if (file->f_flags & O_NONBLOCK)
- return -EAGAIN;
+ if (file->f_flags & O_NONBLOCK) {
+ retval = -EAGAIN;
+ goto exit;
+ }
else {
//next line will return when there is either new data, or the device is unplugged
int r = wait_event_interruptible(dev->read_wait,
@@ -309,28 +326,37 @@ static ssize_t iowarrior_read(struct file *file, char __user *buffer,
-1));
if (r) {
//we were interrupted by a signal
- return -ERESTART;
+ retval = -ERESTART;
+ goto exit;
}
if (!dev->present) {
//The device was unplugged
- return -ENODEV;
+ retval = -ENODEV;
+ goto exit;
}
if (read_idx == -1) {
// Can this happen ???
- return 0;
+ retval = 0;
+ goto exit;
}
}
}
offset = read_idx * (dev->report_size + 1);
if (copy_to_user(buffer, dev->read_queue + offset, count)) {
- return -EFAULT;
+ retval = -EFAULT;
+ goto exit;
}
} while (atomic_read(&dev->overflow_flag));
read_idx = ++read_idx == MAX_INTERRUPT_BUFFER ? 0 : read_idx;
atomic_set(&dev->read_idx, read_idx);
+ mutex_unlock(&dev->mutex);
return count;
+
+exit:
+ mutex_unlock(&dev->mutex);
+ return retval;
}
/*
@@ -885,7 +911,6 @@ error:
static void iowarrior_disconnect(struct usb_interface *interface)
{
struct iowarrior *dev = usb_get_intfdata(interface);
- int minor = dev->minor;
usb_deregister_dev(interface, &iowarrior_class);
@@ -909,9 +934,6 @@ static void iowarrior_disconnect(struct usb_interface *interface)
mutex_unlock(&dev->mutex);
iowarrior_delete(dev);
}
-
- dev_info(&interface->dev, "I/O-Warror #%d now disconnected\n",
- minor - IOWARRIOR_MINOR_BASE);
}
/* usb specific object needed to register this driver with the usb subsystem */
diff --git a/drivers/usb/misc/onboard_usb_dev.c b/drivers/usb/misc/onboard_usb_dev.c
index 75dfdca04ff1..75ac3c6aa92d 100644
--- a/drivers/usb/misc/onboard_usb_dev.c
+++ b/drivers/usb/misc/onboard_usb_dev.c
@@ -407,8 +407,10 @@ static int onboard_dev_probe(struct platform_device *pdev)
}
if (of_device_is_compatible(pdev->dev.of_node, "usb424,2744") ||
- of_device_is_compatible(pdev->dev.of_node, "usb424,5744"))
+ of_device_is_compatible(pdev->dev.of_node, "usb424,5744")) {
err = onboard_dev_5744_i2c_init(client);
+ onboard_dev->always_powered_in_suspend = true;
+ }
put_device(&client->dev);
if (err < 0)
@@ -473,7 +475,7 @@ static const struct dev_pm_ops __maybe_unused onboard_dev_pm_ops = {
static struct platform_driver onboard_dev_driver = {
.probe = onboard_dev_probe,
- .remove_new = onboard_dev_remove,
+ .remove = onboard_dev_remove,
.driver = {
.name = "onboard-usb-dev",
diff --git a/drivers/usb/misc/qcom_eud.c b/drivers/usb/misc/qcom_eud.c
index 19906301a4eb..83079c414b4f 100644
--- a/drivers/usb/misc/qcom_eud.c
+++ b/drivers/usb/misc/qcom_eud.c
@@ -239,7 +239,7 @@ MODULE_DEVICE_TABLE(of, eud_dt_match);
static struct platform_driver eud_driver = {
.probe = eud_probe,
- .remove_new = eud_remove,
+ .remove = eud_remove,
.driver = {
.name = "qcom_eud",
.dev_groups = eud_groups,
diff --git a/drivers/usb/misc/usb-ljca.c b/drivers/usb/misc/usb-ljca.c
index 01ceafc4ab78..c562630d862c 100644
--- a/drivers/usb/misc/usb-ljca.c
+++ b/drivers/usb/misc/usb-ljca.c
@@ -332,14 +332,11 @@ static int ljca_send(struct ljca_adapter *adap, u8 type, u8 cmd,
ret = usb_bulk_msg(adap->usb_dev, adap->tx_pipe, header,
msg_len, &transferred, LJCA_WRITE_TIMEOUT_MS);
-
- usb_autopm_put_interface(adap->intf);
-
if (ret < 0)
- goto out;
+ goto out_put;
if (transferred != msg_len) {
ret = -EIO;
- goto out;
+ goto out_put;
}
if (ack) {
@@ -347,11 +344,14 @@ static int ljca_send(struct ljca_adapter *adap, u8 type, u8 cmd,
timeout);
if (!ret) {
ret = -ETIMEDOUT;
- goto out;
+ goto out_put;
}
}
ret = adap->actual_length;
+out_put:
+ usb_autopm_put_interface(adap->intf);
+
out:
spin_lock_irqsave(&adap->lock, flags);
adap->ex_buf = NULL;
@@ -372,7 +372,7 @@ int ljca_transfer(struct ljca_client *client, u8 cmd, const u8 *obuf,
obuf, obuf_len, ibuf, ibuf_len, true,
LJCA_WRITE_ACK_TIMEOUT_MS);
}
-EXPORT_SYMBOL_NS_GPL(ljca_transfer, LJCA);
+EXPORT_SYMBOL_NS_GPL(ljca_transfer, "LJCA");
int ljca_transfer_noack(struct ljca_client *client, u8 cmd, const u8 *obuf,
u8 obuf_len)
@@ -380,7 +380,7 @@ int ljca_transfer_noack(struct ljca_client *client, u8 cmd, const u8 *obuf,
return ljca_send(client->adapter, client->type, cmd, obuf,
obuf_len, NULL, 0, false, LJCA_WRITE_ACK_TIMEOUT_MS);
}
-EXPORT_SYMBOL_NS_GPL(ljca_transfer_noack, LJCA);
+EXPORT_SYMBOL_NS_GPL(ljca_transfer_noack, "LJCA");
int ljca_register_event_cb(struct ljca_client *client, ljca_event_cb_t event_cb,
void *context)
@@ -404,7 +404,7 @@ int ljca_register_event_cb(struct ljca_client *client, ljca_event_cb_t event_cb,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(ljca_register_event_cb, LJCA);
+EXPORT_SYMBOL_NS_GPL(ljca_register_event_cb, "LJCA");
void ljca_unregister_event_cb(struct ljca_client *client)
{
@@ -417,7 +417,7 @@ void ljca_unregister_event_cb(struct ljca_client *client)
spin_unlock_irqrestore(&client->event_cb_lock, flags);
}
-EXPORT_SYMBOL_NS_GPL(ljca_unregister_event_cb, LJCA);
+EXPORT_SYMBOL_NS_GPL(ljca_unregister_event_cb, "LJCA");
static int ljca_match_device_ids(struct acpi_device *adev, void *data)
{
@@ -811,6 +811,14 @@ static int ljca_probe(struct usb_interface *interface,
if (ret)
goto err_free;
+ /*
+ * This works around problems with ov2740 initialization on some
+ * Lenovo platforms. The autosuspend delay, has to be smaller than
+ * the delay after setting the reset_gpio line in ov2740_resume().
+ * Otherwise the sensor randomly fails to initialize.
+ */
+ pm_runtime_set_autosuspend_delay(&usb_dev->dev, 10);
+
usb_enable_autosuspend(usb_dev);
return 0;
diff --git a/drivers/usb/misc/usb3503.c b/drivers/usb/misc/usb3503.c
index 3b33e4878c60..322e59381b78 100644
--- a/drivers/usb/misc/usb3503.c
+++ b/drivers/usb/misc/usb3503.c
@@ -423,7 +423,7 @@ static struct platform_driver usb3503_platform_driver = {
.pm = pm_ptr(&usb3503_platform_pm_ops),
},
.probe = usb3503_platform_probe,
- .remove_new = usb3503_platform_remove,
+ .remove = usb3503_platform_remove,
};
static int __init usb3503_init(void)
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index caf65f8294db..8d379ae835bc 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -2021,7 +2021,8 @@ static struct urb *iso_alloc_urb(
for (i = 0; i < packets; i++) {
/* here, only the last packet will be short */
- urb->iso_frame_desc[i].length = min((unsigned) bytes, maxp);
+ urb->iso_frame_desc[i].length = min_t(unsigned int,
+ bytes, maxp);
bytes -= urb->iso_frame_desc[i].length;
urb->iso_frame_desc[i].offset = maxp * i;
diff --git a/drivers/usb/misc/yurex.c b/drivers/usb/misc/yurex.c
index 6aebc736a80c..70dff0db5354 100644
--- a/drivers/usb/misc/yurex.c
+++ b/drivers/usb/misc/yurex.c
@@ -441,7 +441,10 @@ static ssize_t yurex_write(struct file *file, const char __user *user_buffer,
if (count == 0)
goto error;
- mutex_lock(&dev->io_mutex);
+ retval = mutex_lock_interruptible(&dev->io_mutex);
+ if (retval < 0)
+ return -EINTR;
+
if (dev->disconnected) { /* already disconnected */
mutex_unlock(&dev->io_mutex);
retval = -ENODEV;
diff --git a/drivers/usb/mon/mon_bin.c b/drivers/usb/mon/mon_bin.c
index afb71c18415d..c93b43f5bc46 100644
--- a/drivers/usb/mon/mon_bin.c
+++ b/drivers/usb/mon/mon_bin.c
@@ -823,7 +823,7 @@ static ssize_t mon_bin_read(struct file *file, char __user *buf,
ep = MON_OFF2HDR(rp, rp->b_out);
if (rp->b_read < hdrbytes) {
- step_len = min(nbytes, (size_t)(hdrbytes - rp->b_read));
+ step_len = min_t(size_t, nbytes, hdrbytes - rp->b_read);
ptr = ((char *)ep) + rp->b_read;
if (step_len && copy_to_user(buf, ptr, step_len)) {
mutex_unlock(&rp->fetch_lock);
diff --git a/drivers/usb/mtu3/Kconfig b/drivers/usb/mtu3/Kconfig
index bf98fd36341d..d281da1cdbcc 100644
--- a/drivers/usb/mtu3/Kconfig
+++ b/drivers/usb/mtu3/Kconfig
@@ -21,7 +21,7 @@ config USB_MTU3
if USB_MTU3
choice
- bool "MTU3 Mode Selection"
+ prompt "MTU3 Mode Selection"
default USB_MTU3_DUAL_ROLE if (USB && USB_GADGET)
default USB_MTU3_HOST if (USB && !USB_GADGET)
default USB_MTU3_GADGET if (!USB && USB_GADGET)
diff --git a/drivers/usb/mtu3/mtu3_plat.c b/drivers/usb/mtu3/mtu3_plat.c
index 6858ed9fc3b2..7b5a431acb56 100644
--- a/drivers/usb/mtu3/mtu3_plat.c
+++ b/drivers/usb/mtu3/mtu3_plat.c
@@ -307,7 +307,7 @@ static int get_ssusb_rscs(struct platform_device *pdev, struct ssusb_mtk *ssusb)
if (otg_sx->role_sw_used || otg_sx->manual_drd_enabled)
goto out;
- if (of_property_read_bool(node, "extcon")) {
+ if (of_property_present(node, "extcon")) {
otg_sx->edev = extcon_get_edev_by_phandle(ssusb->dev, 0);
if (IS_ERR(otg_sx->edev)) {
return dev_err_probe(dev, PTR_ERR(otg_sx->edev),
@@ -621,7 +621,7 @@ MODULE_DEVICE_TABLE(of, mtu3_of_match);
static struct platform_driver mtu3_driver = {
.probe = mtu3_probe,
- .remove_new = mtu3_remove,
+ .remove = mtu3_remove,
.driver = {
.name = MTU3_DRIVER_NAME,
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/musb/Kconfig b/drivers/usb/musb/Kconfig
index 9a8cf3de0617..9e45d12b81d3 100644
--- a/drivers/usb/musb/Kconfig
+++ b/drivers/usb/musb/Kconfig
@@ -29,7 +29,7 @@ config USB_MUSB_HDRC
if USB_MUSB_HDRC
choice
- bool "MUSB Mode Selection"
+ prompt "MUSB Mode Selection"
default USB_MUSB_DUAL_ROLE if (USB && USB_GADGET)
default USB_MUSB_HOST if (USB && !USB_GADGET)
default USB_MUSB_GADGET if (!USB && USB_GADGET)
diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c
index 953094c1930c..f772aa272bea 100644
--- a/drivers/usb/musb/da8xx.c
+++ b/drivers/usb/musb/da8xx.c
@@ -633,7 +633,7 @@ MODULE_DEVICE_TABLE(of, da8xx_id_table);
static struct platform_driver da8xx_driver = {
.probe = da8xx_probe,
- .remove_new = da8xx_remove,
+ .remove = da8xx_remove,
.driver = {
.name = "musb-da8xx",
.pm = &da8xx_pm_ops,
diff --git a/drivers/usb/musb/jz4740.c b/drivers/usb/musb/jz4740.c
index b38df9226278..acdeb1117cd3 100644
--- a/drivers/usb/musb/jz4740.c
+++ b/drivers/usb/musb/jz4740.c
@@ -325,7 +325,7 @@ MODULE_DEVICE_TABLE(of, jz4740_musb_of_match);
static struct platform_driver jz4740_driver = {
.probe = jz4740_probe,
- .remove_new = jz4740_remove,
+ .remove = jz4740_remove,
.driver = {
.name = "musb-jz4740",
.of_match_table = jz4740_musb_of_match,
diff --git a/drivers/usb/musb/mediatek.c b/drivers/usb/musb/mediatek.c
index 63c86c046b98..aa988d74b58d 100644
--- a/drivers/usb/musb/mediatek.c
+++ b/drivers/usb/musb/mediatek.c
@@ -523,7 +523,7 @@ MODULE_DEVICE_TABLE(of, mtk_musb_match);
static struct platform_driver mtk_musb_driver = {
.probe = mtk_musb_probe,
- .remove_new = mtk_musb_remove,
+ .remove = mtk_musb_remove,
.driver = {
.name = "musb-mtk",
.of_match_table = of_match_ptr(mtk_musb_match),
diff --git a/drivers/usb/musb/mpfs.c b/drivers/usb/musb/mpfs.c
index 00e13214aa76..7edc8429b274 100644
--- a/drivers/usb/musb/mpfs.c
+++ b/drivers/usb/musb/mpfs.c
@@ -369,7 +369,7 @@ MODULE_DEVICE_TABLE(of, mpfs_id_table);
static struct platform_driver mpfs_musb_driver = {
.probe = mpfs_probe,
- .remove_new = mpfs_remove,
+ .remove = mpfs_remove,
.driver = {
.name = "mpfs-musb",
.of_match_table = of_match_ptr(mpfs_id_table)
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index b24adb5b399f..03b1154a6014 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -1387,7 +1387,7 @@ fifo_setup(struct musb *musb, struct musb_hw_ep *hw_ep,
/* expect hw_ep has already been zero-initialized */
- size = ffs(max(maxpacket, (u16) 8)) - 1;
+ size = ffs(max_t(u16, maxpacket, 8)) - 1;
maxpacket = 1 << size;
c_size = size - 3;
@@ -2953,7 +2953,7 @@ static struct platform_driver musb_driver = {
.dev_groups = musb_groups,
},
.probe = musb_probe,
- .remove_new = musb_remove,
+ .remove = musb_remove,
};
module_platform_driver(musb_driver);
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 9c7a8bbc0542..2542239ec64e 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -1032,7 +1032,7 @@ static SIMPLE_DEV_PM_OPS(dsps_pm_ops, dsps_suspend, dsps_resume);
static struct platform_driver dsps_usbss_driver = {
.probe = dsps_probe,
- .remove_new = dsps_remove,
+ .remove = dsps_remove,
.driver = {
.name = "musb-dsps",
.pm = &dsps_pm_ops,
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
index bdf13911a1e5..c6076df0d50c 100644
--- a/drivers/usb/musb/musb_gadget.c
+++ b/drivers/usb/musb/musb_gadget.c
@@ -1161,12 +1161,19 @@ void musb_free_request(struct usb_ep *ep, struct usb_request *req)
*/
void musb_ep_restart(struct musb *musb, struct musb_request *req)
{
+ u16 csr;
+ void __iomem *epio = req->ep->hw_ep->regs;
+
trace_musb_req_start(req);
musb_ep_select(musb->mregs, req->epnum);
- if (req->tx)
+ if (req->tx) {
txstate(musb, req);
- else
- rxstate(musb, req);
+ } else {
+ csr = musb_readw(epio, MUSB_RXCSR);
+ csr |= MUSB_RXCSR_FLUSHFIFO | MUSB_RXCSR_P_WZC_BITS;
+ musb_writew(epio, MUSB_RXCSR, csr);
+ musb_writew(epio, MUSB_RXCSR, csr);
+ }
}
static int musb_ep_restart_resume_work(struct musb *musb, void *data)
diff --git a/drivers/usb/musb/musb_gadget_ep0.c b/drivers/usb/musb/musb_gadget_ep0.c
index 6d7336727388..f0786f8fbb25 100644
--- a/drivers/usb/musb/musb_gadget_ep0.c
+++ b/drivers/usb/musb/musb_gadget_ep0.c
@@ -533,7 +533,7 @@ static void ep0_txstate(struct musb *musb)
/* load the data */
fifo_src = (u8 *) request->buf + request->actual;
- fifo_count = min((unsigned) MUSB_EP0_FIFOSIZE,
+ fifo_count = min_t(unsigned, MUSB_EP0_FIFOSIZE,
request->length - request->actual);
musb_write_fifo(&musb->endpoints[0], fifo_count, fifo_src);
request->actual += fifo_count;
diff --git a/drivers/usb/musb/musb_host.c b/drivers/usb/musb/musb_host.c
index bc4507781167..732ba981e607 100644
--- a/drivers/usb/musb/musb_host.c
+++ b/drivers/usb/musb/musb_host.c
@@ -798,10 +798,9 @@ static void musb_ep_program(struct musb *musb, u8 epnum,
}
if (can_bulk_split(musb, qh->type))
- load_count = min((u32) hw_ep->max_packet_sz_tx,
- len);
+ load_count = min_t(u32, hw_ep->max_packet_sz_tx, len);
else
- load_count = min((u32) packet_sz, len);
+ load_count = min_t(u32, packet_sz, len);
if (dma_channel && musb_tx_dma_program(dma_controller,
hw_ep, qh, urb, offset, len))
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index b4a4c1df4e0d..2970967a4fd2 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -608,7 +608,7 @@ MODULE_DEVICE_TABLE(of, omap2430_id_table);
static struct platform_driver omap2430_driver = {
.probe = omap2430_probe,
- .remove_new = omap2430_remove,
+ .remove = omap2430_remove,
.driver = {
.name = "musb-omap2430",
.pm = DEV_PM_OPS,
diff --git a/drivers/usb/musb/sunxi.c b/drivers/usb/musb/sunxi.c
index 05b6e7e52e02..eac1cde86be3 100644
--- a/drivers/usb/musb/sunxi.c
+++ b/drivers/usb/musb/sunxi.c
@@ -857,7 +857,7 @@ MODULE_DEVICE_TABLE(of, sunxi_musb_match);
static struct platform_driver sunxi_musb_driver = {
.probe = sunxi_musb_probe,
- .remove_new = sunxi_musb_remove,
+ .remove = sunxi_musb_remove,
.driver = {
.name = "musb-sunxi",
.of_match_table = sunxi_musb_match,
diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c
index 461587629bf2..90b760a95e4e 100644
--- a/drivers/usb/musb/tusb6010.c
+++ b/drivers/usb/musb/tusb6010.c
@@ -1290,7 +1290,7 @@ static void tusb_remove(struct platform_device *pdev)
static struct platform_driver tusb_driver = {
.probe = tusb_probe,
- .remove_new = tusb_remove,
+ .remove = tusb_remove,
.driver = {
.name = "musb-tusb",
},
diff --git a/drivers/usb/musb/ux500.c b/drivers/usb/musb/ux500.c
index c8d9d2a1d2f0..8c2a43d992f5 100644
--- a/drivers/usb/musb/ux500.c
+++ b/drivers/usb/musb/ux500.c
@@ -355,7 +355,7 @@ MODULE_DEVICE_TABLE(of, ux500_match);
static struct platform_driver ux500_driver = {
.probe = ux500_probe,
- .remove_new = ux500_remove,
+ .remove = ux500_remove,
.driver = {
.name = "musb-ux500",
.pm = &ux500_pm_ops,
diff --git a/drivers/usb/phy/phy-ab8500-usb.c b/drivers/usb/phy/phy-ab8500-usb.c
index 408f47e39025..6a98aeeeae31 100644
--- a/drivers/usb/phy/phy-ab8500-usb.c
+++ b/drivers/usb/phy/phy-ab8500-usb.c
@@ -987,7 +987,7 @@ MODULE_DEVICE_TABLE(platform, ab8500_usb_devtype);
static struct platform_driver ab8500_usb_driver = {
.probe = ab8500_usb_probe,
- .remove_new = ab8500_usb_remove,
+ .remove = ab8500_usb_remove,
.id_table = ab8500_usb_devtype,
.driver = {
.name = "abx5x0-usb",
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index 6db88e00f127..ca9353dad71a 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -133,7 +133,7 @@ MODULE_DEVICE_TABLE(of, am335x_phy_ids);
static struct platform_driver am335x_phy_driver = {
.probe = am335x_phy_probe,
- .remove_new = am335x_phy_remove,
+ .remove = am335x_phy_remove,
.driver = {
.name = "am335x-phy-driver",
.pm = &am335x_pm_ops,
diff --git a/drivers/usb/phy/phy-fsl-usb.c b/drivers/usb/phy/phy-fsl-usb.c
index c5c6b818998e..42c42e193232 100644
--- a/drivers/usb/phy/phy-fsl-usb.c
+++ b/drivers/usb/phy/phy-fsl-usb.c
@@ -1002,7 +1002,7 @@ static void fsl_otg_remove(struct platform_device *pdev)
struct platform_driver fsl_otg_driver = {
.probe = fsl_otg_probe,
- .remove_new = fsl_otg_remove,
+ .remove = fsl_otg_remove,
.driver = {
.name = driver_name,
},
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index e7d50e0a1612..6c3ececf9137 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -345,7 +345,7 @@ MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids);
static struct platform_driver usb_phy_generic_driver = {
.probe = usb_phy_generic_probe,
- .remove_new = usb_phy_generic_remove,
+ .remove = usb_phy_generic_remove,
.driver = {
.name = "usb_phy_generic",
.of_match_table = nop_xceiv_dt_ids,
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index 5428b2b67de1..ce09e789afd8 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -385,7 +385,7 @@ static struct platform_driver gpio_vbus_driver = {
.of_match_table = gpio_vbus_of_match,
},
.probe = gpio_vbus_probe,
- .remove_new = gpio_vbus_remove,
+ .remove = gpio_vbus_remove,
};
module_platform_driver(gpio_vbus_driver);
diff --git a/drivers/usb/phy/phy-isp1301.c b/drivers/usb/phy/phy-isp1301.c
index 993d7525a102..f9b5c411aee4 100644
--- a/drivers/usb/phy/phy-isp1301.c
+++ b/drivers/usb/phy/phy-isp1301.c
@@ -25,7 +25,7 @@ struct isp1301 {
#define phy_to_isp(p) (container_of((p), struct isp1301, phy))
static const struct i2c_device_id isp1301_id[] = {
- { "isp1301", 0 },
+ { "isp1301" },
{ }
};
MODULE_DEVICE_TABLE(i2c, isp1301_id);
diff --git a/drivers/usb/phy/phy-keystone.c b/drivers/usb/phy/phy-keystone.c
index bd9a98ad1b30..51155c5513d3 100644
--- a/drivers/usb/phy/phy-keystone.c
+++ b/drivers/usb/phy/phy-keystone.c
@@ -103,7 +103,7 @@ MODULE_DEVICE_TABLE(of, keystone_usbphy_ids);
static struct platform_driver keystone_usbphy_driver = {
.probe = keystone_usbphy_probe,
- .remove_new = keystone_usbphy_remove,
+ .remove = keystone_usbphy_remove,
.driver = {
.name = "keystone-usbphy",
.of_match_table = keystone_usbphy_ids,
diff --git a/drivers/usb/phy/phy-mv-usb.c b/drivers/usb/phy/phy-mv-usb.c
index df7c27474a75..a7a102f2e163 100644
--- a/drivers/usb/phy/phy-mv-usb.c
+++ b/drivers/usb/phy/phy-mv-usb.c
@@ -867,7 +867,7 @@ static int mv_otg_resume(struct platform_device *pdev)
static struct platform_driver mv_otg_driver = {
.probe = mv_otg_probe,
- .remove_new = mv_otg_remove,
+ .remove = mv_otg_remove,
.driver = {
.name = driver_name,
.dev_groups = mv_otg_groups,
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index cc4156c1b148..7490f1798b46 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -952,7 +952,7 @@ static SIMPLE_DEV_PM_OPS(mxs_phy_pm, mxs_phy_system_suspend,
static struct platform_driver mxs_phy_driver = {
.probe = mxs_phy_probe,
- .remove_new = mxs_phy_remove,
+ .remove = mxs_phy_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = mxs_phy_dt_ids,
diff --git a/drivers/usb/phy/phy-tahvo.c b/drivers/usb/phy/phy-tahvo.c
index 5cac31c6029b..ae7bf3ff89ee 100644
--- a/drivers/usb/phy/phy-tahvo.c
+++ b/drivers/usb/phy/phy-tahvo.c
@@ -424,7 +424,7 @@ static void tahvo_usb_remove(struct platform_device *pdev)
static struct platform_driver tahvo_usb_driver = {
.probe = tahvo_usb_probe,
- .remove_new = tahvo_usb_remove,
+ .remove = tahvo_usb_remove,
.driver = {
.name = "tahvo-usb",
.dev_groups = tahvo_groups,
diff --git a/drivers/usb/phy/phy-tegra-usb.c b/drivers/usb/phy/phy-tegra-usb.c
index 4ea47e6f835b..bee222967f6b 100644
--- a/drivers/usb/phy/phy-tegra-usb.c
+++ b/drivers/usb/phy/phy-tegra-usb.c
@@ -1495,7 +1495,7 @@ static void tegra_usb_phy_remove(struct platform_device *pdev)
static struct platform_driver tegra_usb_phy_driver = {
.probe = tegra_usb_phy_probe,
- .remove_new = tegra_usb_phy_remove,
+ .remove = tegra_usb_phy_remove,
.driver = {
.name = "tegra-phy",
.of_match_table = tegra_usb_phy_id_table,
diff --git a/drivers/usb/phy/phy-twl6030-usb.c b/drivers/usb/phy/phy-twl6030-usb.c
index da09cff55abc..49d79c1257f3 100644
--- a/drivers/usb/phy/phy-twl6030-usb.c
+++ b/drivers/usb/phy/phy-twl6030-usb.c
@@ -432,7 +432,7 @@ MODULE_DEVICE_TABLE(of, twl6030_usb_id_table);
static struct platform_driver twl6030_usb_driver = {
.probe = twl6030_usb_probe,
- .remove_new = twl6030_usb_remove,
+ .remove = twl6030_usb_remove,
.driver = {
.name = "twl6030_usb",
.of_match_table = of_match_ptr(twl6030_usb_id_table),
diff --git a/drivers/usb/phy/phy.c b/drivers/usb/phy/phy.c
index 06f789097989..1ce134505cee 100644
--- a/drivers/usb/phy/phy.c
+++ b/drivers/usb/phy/phy.c
@@ -365,7 +365,7 @@ static int usb_add_extcon(struct usb_phy *x)
{
int ret;
- if (of_property_read_bool(x->dev->of_node, "extcon")) {
+ if (of_property_present(x->dev->of_node, "extcon")) {
x->edev = extcon_get_edev_by_phandle(x->dev, 0);
if (IS_ERR(x->edev))
return PTR_ERR(x->edev);
diff --git a/drivers/usb/renesas_usbhs/common.c b/drivers/usb/renesas_usbhs/common.c
index edc43f169d49..935fc496fe94 100644
--- a/drivers/usb/renesas_usbhs/common.c
+++ b/drivers/usb/renesas_usbhs/common.c
@@ -632,7 +632,7 @@ static int usbhs_probe(struct platform_device *pdev)
if (IS_ERR(priv->base))
return PTR_ERR(priv->base);
- if (of_property_read_bool(dev_of_node(dev), "extcon")) {
+ if (of_property_present(dev_of_node(dev), "extcon")) {
priv->edev = extcon_get_edev_by_phandle(dev, 0);
if (IS_ERR(priv->edev))
return PTR_ERR(priv->edev);
@@ -835,7 +835,7 @@ static struct platform_driver renesas_usbhs_driver = {
.of_match_table = usbhs_of_match,
},
.probe = usbhs_probe,
- .remove_new = usbhs_remove,
+ .remove = usbhs_remove,
};
module_platform_driver(renesas_usbhs_driver);
diff --git a/drivers/usb/roles/intel-xhci-usb-role-switch.c b/drivers/usb/roles/intel-xhci-usb-role-switch.c
index e5c6c413a075..cd2e026dcb22 100644
--- a/drivers/usb/roles/intel-xhci-usb-role-switch.c
+++ b/drivers/usb/roles/intel-xhci-usb-role-switch.c
@@ -217,7 +217,7 @@ static struct platform_driver intel_xhci_usb_driver = {
},
.id_table = intel_xhci_usb_table,
.probe = intel_xhci_usb_probe,
- .remove_new = intel_xhci_usb_remove,
+ .remove = intel_xhci_usb_remove,
};
module_platform_driver(intel_xhci_usb_driver);
diff --git a/drivers/usb/serial/bus.c b/drivers/usb/serial/bus.c
index d200e2c29a8f..2fea1b1db4a2 100644
--- a/drivers/usb/serial/bus.c
+++ b/drivers/usb/serial/bus.c
@@ -136,12 +136,11 @@ static void free_dynids(struct usb_serial_driver *drv)
{
struct usb_dynid *dynid, *n;
- spin_lock(&drv->dynids.lock);
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry_safe(dynid, n, &drv->dynids.list, node) {
list_del(&dynid->node);
kfree(dynid);
}
- spin_unlock(&drv->dynids.lock);
}
const struct bus_type usb_serial_bus_type = {
@@ -157,7 +156,6 @@ int usb_serial_bus_register(struct usb_serial_driver *driver)
int retval;
driver->driver.bus = &usb_serial_bus_type;
- spin_lock_init(&driver->dynids.lock);
INIT_LIST_HEAD(&driver->dynids.list);
retval = driver_register(&driver->driver);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index c6f17d732b95..e07c5e3eb18c 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -1443,9 +1443,11 @@ static void get_serial_info(struct tty_struct *tty, struct serial_struct *ss)
struct usb_serial_port *port = tty->driver_data;
struct ftdi_private *priv = usb_get_serial_port_data(port);
+ mutex_lock(&priv->cfg_lock);
ss->flags = priv->flags;
ss->baud_base = priv->baud_base;
ss->custom_divisor = priv->custom_divisor;
+ mutex_unlock(&priv->cfg_lock);
}
static int set_serial_info(struct tty_struct *tty, struct serial_struct *ss)
diff --git a/drivers/usb/serial/io_edgeport.c b/drivers/usb/serial/io_edgeport.c
index 28c71d99e857..1fffda7647f9 100644
--- a/drivers/usb/serial/io_edgeport.c
+++ b/drivers/usb/serial/io_edgeport.c
@@ -1129,7 +1129,7 @@ static int edge_write(struct tty_struct *tty, struct usb_serial_port *port,
spin_lock_irqsave(&edge_port->ep_lock, flags);
/* calculate number of bytes to put in fifo */
- copySize = min((unsigned int)count,
+ copySize = min_t(unsigned int, count,
(edge_port->txCredits - fifo->count));
dev_dbg(&port->dev, "%s of %d byte(s) Fifo room %d -- will copy %d bytes\n",
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index 9ba5584061c8..64317b390d22 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -625,6 +625,8 @@ static void option_instat_callback(struct urb *urb);
#define MEIGSMART_PRODUCT_SRM825L 0x4d22
/* MeiG Smart SLM320 based on UNISOC UIS8910 */
#define MEIGSMART_PRODUCT_SLM320 0x4d41
+/* MeiG Smart SLM770A based on ASR1803 */
+#define MEIGSMART_PRODUCT_SLM770A 0x4d57
/* Device flags */
@@ -1395,6 +1397,12 @@ static const struct usb_device_id option_ids[] = {
.driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
{ USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10aa, 0xff), /* Telit FN920C04 (MBIM) */
.driver_info = NCTRL(3) | RSVD(4) | RSVD(5) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c0, 0xff), /* Telit FE910C04 (rmnet) */
+ .driver_info = RSVD(0) | NCTRL(3) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c4, 0xff), /* Telit FE910C04 (rmnet) */
+ .driver_info = RSVD(0) | NCTRL(3) },
+ { USB_DEVICE_INTERFACE_CLASS(TELIT_VENDOR_ID, 0x10c8, 0xff), /* Telit FE910C04 (rmnet) */
+ .driver_info = RSVD(0) | NCTRL(2) | RSVD(3) | RSVD(4) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910),
.driver_info = NCTRL(0) | RSVD(1) | RSVD(3) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_ME910_DUAL_MODEM),
@@ -2247,6 +2255,8 @@ static const struct usb_device_id option_ids[] = {
.driver_info = NCTRL(2) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x7127, 0xff, 0x00, 0x00),
.driver_info = NCTRL(2) | NCTRL(3) | NCTRL(4) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, 0x7129, 0xff, 0x00, 0x00), /* MediaTek T7XX */
+ .driver_info = NCTRL(2) | NCTRL(3) | NCTRL(4) },
{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MPL200),
.driver_info = RSVD(1) | RSVD(4) },
@@ -2375,6 +2385,18 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for Golbal EDU */
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0x00, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x0116, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010a, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WRD for WWAN Ready */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010a, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010a, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010b, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for WWAN Ready */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010b, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010b, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010c, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WRD for WWAN Ready */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010c, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010c, 0xff, 0xff, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010d, 0xff, 0xff, 0x30) }, /* NetPrisma LCUK54-WWD for WWAN Ready */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010d, 0xff, 0x00, 0x40) },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x3731, 0x010d, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(OPPO_VENDOR_ID, OPPO_PRODUCT_R11, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(SIERRA_VENDOR_ID, SIERRA_PRODUCT_EM9191, 0xff, 0xff, 0x40) },
@@ -2382,9 +2404,14 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, TOZED_PRODUCT_LT70C, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(UNISOC_VENDOR_ID, LUAT_PRODUCT_AIR720U, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM320, 0xff, 0, 0) },
+ { USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SLM770A, 0xff, 0, 0) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x30) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x40) },
{ USB_DEVICE_AND_INTERFACE_INFO(MEIGSMART_VENDOR_ID, MEIGSMART_PRODUCT_SRM825L, 0xff, 0xff, 0x60) },
+ { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0530, 0xff), /* TCL IK512 MBIM */
+ .driver_info = NCTRL(1) },
+ { USB_DEVICE_INTERFACE_CLASS(0x1bbb, 0x0640, 0xff), /* TCL IK512 ECM */
+ .driver_info = NCTRL(3) },
{ } /* Terminating entry */
};
MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/usb/serial/pl2303.c b/drivers/usb/serial/pl2303.c
index ad41363e3cea..010688dd9e49 100644
--- a/drivers/usb/serial/pl2303.c
+++ b/drivers/usb/serial/pl2303.c
@@ -31,6 +31,7 @@
#define PL2303_QUIRK_UART_STATE_IDX0 BIT(0)
#define PL2303_QUIRK_LEGACY BIT(1)
#define PL2303_QUIRK_ENDPOINT_HACK BIT(2)
+#define PL2303_QUIRK_NO_BREAK_GETLINE BIT(3)
static const struct usb_device_id id_table[] = {
{ USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID),
@@ -467,6 +468,25 @@ static int pl2303_detect_type(struct usb_serial *serial)
return -ENODEV;
}
+static bool pl2303_is_hxd_clone(struct usb_serial *serial)
+{
+ struct usb_device *udev = serial->dev;
+ unsigned char *buf;
+ int ret;
+
+ buf = kmalloc(7, GFP_KERNEL);
+ if (!buf)
+ return false;
+
+ ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+ GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
+ 0, 0, buf, 7, 100);
+
+ kfree(buf);
+
+ return ret == -EPIPE;
+}
+
static int pl2303_startup(struct usb_serial *serial)
{
struct pl2303_serial_private *spriv;
@@ -489,6 +509,9 @@ static int pl2303_startup(struct usb_serial *serial)
spriv->quirks = (unsigned long)usb_get_serial_data(serial);
spriv->quirks |= spriv->type->quirks;
+ if (type == TYPE_HXD && pl2303_is_hxd_clone(serial))
+ spriv->quirks |= PL2303_QUIRK_NO_BREAK_GETLINE;
+
usb_set_serial_data(serial, spriv);
if (type != TYPE_HXN) {
@@ -725,9 +748,18 @@ static void pl2303_encode_baud_rate(struct tty_struct *tty,
static int pl2303_get_line_request(struct usb_serial_port *port,
unsigned char buf[7])
{
- struct usb_device *udev = port->serial->dev;
+ struct usb_serial *serial = port->serial;
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
+ struct usb_device *udev = serial->dev;
int ret;
+ if (spriv->quirks & PL2303_QUIRK_NO_BREAK_GETLINE) {
+ struct pl2303_private *priv = usb_get_serial_port_data(port);
+
+ memcpy(buf, priv->line_settings, 7);
+ return 0;
+ }
+
ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
GET_LINE_REQUEST, GET_LINE_REQUEST_TYPE,
0, 0, buf, 7, 100);
@@ -1064,9 +1096,13 @@ static int pl2303_carrier_raised(struct usb_serial_port *port)
static int pl2303_set_break(struct usb_serial_port *port, bool enable)
{
struct usb_serial *serial = port->serial;
+ struct pl2303_serial_private *spriv = usb_get_serial_data(serial);
u16 state;
int result;
+ if (spriv->quirks & PL2303_QUIRK_NO_BREAK_GETLINE)
+ return -ENOTTY;
+
if (enable)
state = BREAK_ON;
else
diff --git a/drivers/usb/serial/sierra.c b/drivers/usb/serial/sierra.c
index 64a2e0bb5723..741e68e46139 100644
--- a/drivers/usb/serial/sierra.c
+++ b/drivers/usb/serial/sierra.c
@@ -421,7 +421,7 @@ static int sierra_write(struct tty_struct *tty, struct usb_serial_port *port,
unsigned long flags;
unsigned char *buffer;
struct urb *urb;
- size_t writesize = min((size_t)count, (size_t)MAX_TRANSFER);
+ size_t writesize = min_t(size_t, count, MAX_TRANSFER);
int retval = 0;
/* verify that we actually have some data to write */
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index df6a2ae0bf42..7266558d823a 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -706,14 +706,12 @@ static const struct usb_device_id *match_dynamic_id(struct usb_interface *intf,
{
struct usb_dynid *dynid;
- spin_lock(&drv->dynids.lock);
+ guard(mutex)(&usb_dynids_lock);
list_for_each_entry(dynid, &drv->dynids.list, node) {
if (usb_match_one_id(intf, &dynid->id)) {
- spin_unlock(&drv->dynids.lock);
return &dynid->id;
}
}
- spin_unlock(&drv->dynids.lock);
return NULL;
}
diff --git a/drivers/usb/storage/Makefile b/drivers/usb/storage/Makefile
index 46635fa4a340..28db337f190b 100644
--- a/drivers/usb/storage/Makefile
+++ b/drivers/usb/storage/Makefile
@@ -8,7 +8,7 @@
ccflags-y := -I $(srctree)/drivers/scsi
-ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE=USB_STORAGE
+ccflags-y += -DDEFAULT_SYMBOL_NAMESPACE='"USB_STORAGE"'
obj-$(CONFIG_USB_UAS) += uas.o
obj-$(CONFIG_USB_STORAGE) += usb-storage.o
diff --git a/drivers/usb/storage/alauda.c b/drivers/usb/storage/alauda.c
index a9d3c58ce7d9..6263c4e61678 100644
--- a/drivers/usb/storage/alauda.c
+++ b/drivers/usb/storage/alauda.c
@@ -36,7 +36,7 @@
MODULE_DESCRIPTION("Driver for Alauda-based card readers");
MODULE_AUTHOR("Daniel Drake <dsd@gentoo.org>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
/*
* Status bytes
diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
index 30dfd0082474..2fce5f95be51 100644
--- a/drivers/usb/storage/cypress_atacb.c
+++ b/drivers/usb/storage/cypress_atacb.c
@@ -22,7 +22,7 @@
MODULE_DESCRIPTION("SAT support for Cypress USB/ATA bridges with ATACB");
MODULE_AUTHOR("Matthieu Castet <castet.matthieu@free.fr>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
/*
* The table of devices
diff --git a/drivers/usb/storage/datafab.c b/drivers/usb/storage/datafab.c
index 3ea5601d16b8..bbfa2398b170 100644
--- a/drivers/usb/storage/datafab.c
+++ b/drivers/usb/storage/datafab.c
@@ -54,7 +54,7 @@
MODULE_DESCRIPTION("Driver for Datafab USB Compact Flash reader");
MODULE_AUTHOR("Jimmie Mayfield <mayfield+datafab@sackheads.org>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
struct datafab_info {
unsigned long sectors; /* total sector count */
diff --git a/drivers/usb/storage/ene_ub6250.c b/drivers/usb/storage/ene_ub6250.c
index a4bfbecbf16c..ce91fb105975 100644
--- a/drivers/usb/storage/ene_ub6250.c
+++ b/drivers/usb/storage/ene_ub6250.c
@@ -26,7 +26,7 @@
MODULE_DESCRIPTION("Driver for ENE UB6250 reader");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
MODULE_FIRMWARE(SD_INIT1_FIRMWARE);
MODULE_FIRMWARE(SD_INIT2_FIRMWARE);
MODULE_FIRMWARE(SD_RW_FIRMWARE);
@@ -737,7 +737,7 @@ static int sd_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = blenByte;
- bcb->Flags = 0x00;
+ bcb->Flags = US_BULK_FLAG_OUT;
bcb->CDB[0] = 0xF0;
bcb->CDB[5] = (unsigned char)(bnByte);
bcb->CDB[4] = (unsigned char)(bnByte>>8);
@@ -1163,7 +1163,7 @@ static int ms_read_copyblock(struct us_data *us, u16 oldphy, u16 newphy,
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = 0x200*len;
- bcb->Flags = 0x00;
+ bcb->Flags = US_BULK_FLAG_OUT;
bcb->CDB[0] = 0xF0;
bcb->CDB[1] = 0x08;
bcb->CDB[4] = (unsigned char)(oldphy);
@@ -1759,7 +1759,7 @@ static int ms_scsi_write(struct us_data *us, struct scsi_cmnd *srb)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = blenByte;
- bcb->Flags = 0x00;
+ bcb->Flags = US_BULK_FLAG_OUT;
bcb->CDB[0] = 0xF0;
bcb->CDB[1] = 0x04;
bcb->CDB[5] = (unsigned char)(bn);
@@ -1931,7 +1931,7 @@ static int ene_load_bincode(struct us_data *us, unsigned char flag)
memset(bcb, 0, sizeof(struct bulk_cb_wrap));
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = sd_fw->size;
- bcb->Flags = 0x00;
+ bcb->Flags = US_BULK_FLAG_OUT;
bcb->CDB[0] = 0xEF;
result = ene_send_scsi_cmd(us, FDIR_WRITE, buf, 0);
diff --git a/drivers/usb/storage/freecom.c b/drivers/usb/storage/freecom.c
index cab27ba7a32a..a075620907b4 100644
--- a/drivers/usb/storage/freecom.c
+++ b/drivers/usb/storage/freecom.c
@@ -29,7 +29,7 @@
MODULE_DESCRIPTION("Driver for Freecom USB/IDE adaptor");
MODULE_AUTHOR("David Brown <usb-storage@davidb.org>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
#ifdef CONFIG_USB_STORAGE_DEBUG
static void pdump(struct us_data *us, void *ibuffer, int length);
diff --git a/drivers/usb/storage/isd200.c b/drivers/usb/storage/isd200.c
index f2254eb3c0d7..a1669c35bad5 100644
--- a/drivers/usb/storage/isd200.c
+++ b/drivers/usb/storage/isd200.c
@@ -53,7 +53,7 @@
MODULE_DESCRIPTION("Driver for In-System Design, Inc. ISD200 ASIC");
MODULE_AUTHOR("Björn Stenberg <bjorn@haxx.se>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
static int isd200_Initialization(struct us_data *us);
diff --git a/drivers/usb/storage/jumpshot.c b/drivers/usb/storage/jumpshot.c
index 0e71a8f33c2b..39ca84d68591 100644
--- a/drivers/usb/storage/jumpshot.c
+++ b/drivers/usb/storage/jumpshot.c
@@ -51,7 +51,7 @@
MODULE_DESCRIPTION("Driver for Lexar \"Jumpshot\" Compact Flash reader");
MODULE_AUTHOR("Jimmie Mayfield <mayfield+usb@sackheads.org>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
/*
* The table of devices
diff --git a/drivers/usb/storage/karma.c b/drivers/usb/storage/karma.c
index d6a5e54f2ca8..341d6839548a 100644
--- a/drivers/usb/storage/karma.c
+++ b/drivers/usb/storage/karma.c
@@ -23,7 +23,7 @@
MODULE_DESCRIPTION("Driver for Rio Karma");
MODULE_AUTHOR("Bob Copeland <me@bobcopeland.com>, Keith Bennett <keith@mcs.st-and.ac.uk>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
#define RIO_PREFIX "RIOP\x00"
#define RIO_PREFIX_LEN 5
diff --git a/drivers/usb/storage/onetouch.c b/drivers/usb/storage/onetouch.c
index f97cf6cadb8e..5a8a1ffda0ec 100644
--- a/drivers/usb/storage/onetouch.c
+++ b/drivers/usb/storage/onetouch.c
@@ -25,7 +25,7 @@
MODULE_DESCRIPTION("Maxtor USB OneTouch hard drive button driver");
MODULE_AUTHOR("Nick Sillik <n.sillik@temple.edu>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
#define ONETOUCH_PKT_LEN 0x02
#define ONETOUCH_BUTTON KEY_PROG1
diff --git a/drivers/usb/storage/realtek_cr.c b/drivers/usb/storage/realtek_cr.c
index 0c423916d7bf..2a82ed7b68ea 100644
--- a/drivers/usb/storage/realtek_cr.c
+++ b/drivers/usb/storage/realtek_cr.c
@@ -35,7 +35,7 @@
MODULE_DESCRIPTION("Driver for Realtek USB Card Reader");
MODULE_AUTHOR("wwang <wei_wang@realsil.com.cn>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
static int auto_delink_en = 1;
module_param(auto_delink_en, int, S_IRUGO | S_IWUSR);
@@ -212,7 +212,7 @@ static int rts51x_bulk_transport(struct us_data *us, u8 lun,
/* set up the command wrapper */
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(buf_len);
- bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0;
+ bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : US_BULK_FLAG_OUT;
bcb->Tag = ++us->tag;
bcb->Lun = lun;
bcb->Length = cmd_len;
@@ -301,7 +301,7 @@ static int rts51x_bulk_transport_special(struct us_data *us, u8 lun,
/* set up the command wrapper */
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(buf_len);
- bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : 0;
+ bcb->Flags = (dir == DMA_FROM_DEVICE) ? US_BULK_FLAG_IN : US_BULK_FLAG_OUT;
bcb->Tag = ++us->tag;
bcb->Lun = lun;
bcb->Length = cmd_len;
diff --git a/drivers/usb/storage/sddr09.c b/drivers/usb/storage/sddr09.c
index 03d1b9c69ea1..d21ce3466e25 100644
--- a/drivers/usb/storage/sddr09.c
+++ b/drivers/usb/storage/sddr09.c
@@ -47,7 +47,7 @@
MODULE_DESCRIPTION("Driver for SanDisk SDDR-09 SmartMedia reader");
MODULE_AUTHOR("Andries Brouwer <aeb@cwi.nl>, Robert Baruch <autophile@starband.net>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
static int usb_stor_sddr09_dpcm_init(struct us_data *us);
static int sddr09_transport(struct scsi_cmnd *srb, struct us_data *us);
@@ -752,7 +752,7 @@ sddr09_read_data(struct us_data *us,
// a bounce buffer and move the data a piece at a time between the
// bounce buffer and the actual transfer buffer.
- len = min(sectors, (unsigned int) info->blocksize) * info->pagesize;
+ len = min_t(unsigned int, sectors, info->blocksize) * info->pagesize;
buffer = kmalloc(len, GFP_NOIO);
if (!buffer)
return -ENOMEM;
@@ -997,7 +997,7 @@ sddr09_write_data(struct us_data *us,
* at a time between the bounce buffer and the actual transfer buffer.
*/
- len = min(sectors, (unsigned int) info->blocksize) * info->pagesize;
+ len = min_t(unsigned int, sectors, info->blocksize) * info->pagesize;
buffer = kmalloc(len, GFP_NOIO);
if (!buffer) {
kfree(blockbuffer);
diff --git a/drivers/usb/storage/sddr55.c b/drivers/usb/storage/sddr55.c
index b8227478a7ad..d5cdff30f6f3 100644
--- a/drivers/usb/storage/sddr55.c
+++ b/drivers/usb/storage/sddr55.c
@@ -29,7 +29,7 @@
MODULE_DESCRIPTION("Driver for SanDisk SDDR-55 SmartMedia reader");
MODULE_AUTHOR("Simon Munton");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
/*
* The table of devices
@@ -206,7 +206,7 @@ static int sddr55_read_data(struct us_data *us,
// a bounce buffer and move the data a piece at a time between the
// bounce buffer and the actual transfer buffer.
- len = min((unsigned int) sectors, (unsigned int) info->blocksize >>
+ len = min_t(unsigned int, sectors, info->blocksize >>
info->smallpageshift) * PAGESIZE;
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
@@ -224,7 +224,7 @@ static int sddr55_read_data(struct us_data *us,
// Read as many sectors as possible in this block
- pages = min((unsigned int) sectors << info->smallpageshift,
+ pages = min_t(unsigned int, sectors << info->smallpageshift,
info->blocksize - page);
len = pages << info->pageshift;
@@ -333,7 +333,7 @@ static int sddr55_write_data(struct us_data *us,
// a bounce buffer and move the data a piece at a time between the
// bounce buffer and the actual transfer buffer.
- len = min((unsigned int) sectors, (unsigned int) info->blocksize >>
+ len = min_t(unsigned int, sectors, info->blocksize >>
info->smallpageshift) * PAGESIZE;
buffer = kmalloc(len, GFP_NOIO);
if (buffer == NULL)
@@ -351,7 +351,7 @@ static int sddr55_write_data(struct us_data *us,
// Write as many sectors as possible in this block
- pages = min((unsigned int) sectors << info->smallpageshift,
+ pages = min_t(unsigned int, sectors << info->smallpageshift,
info->blocksize - page);
len = pages << info->pageshift;
diff --git a/drivers/usb/storage/shuttle_usbat.c b/drivers/usb/storage/shuttle_usbat.c
index e7c224b7c464..087c706bb315 100644
--- a/drivers/usb/storage/shuttle_usbat.c
+++ b/drivers/usb/storage/shuttle_usbat.c
@@ -48,7 +48,7 @@
MODULE_DESCRIPTION("Driver for SCM Microsystems (a.k.a. Shuttle) USB-ATAPI cable");
MODULE_AUTHOR("Daniel Drake <dsd@gentoo.org>, Robert Baruch <autophile@starband.net>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
/* Supported device types */
#define USBAT_DEV_HP8200 0x01
diff --git a/drivers/usb/storage/transport.c b/drivers/usb/storage/transport.c
index 7449e379077a..9d767f6bf722 100644
--- a/drivers/usb/storage/transport.c
+++ b/drivers/usb/storage/transport.c
@@ -1133,7 +1133,7 @@ int usb_stor_Bulk_transport(struct scsi_cmnd *srb, struct us_data *us)
bcb->Signature = cpu_to_le32(US_BULK_CB_SIGN);
bcb->DataTransferLength = cpu_to_le32(transfer_length);
bcb->Flags = srb->sc_data_direction == DMA_FROM_DEVICE ?
- US_BULK_FLAG_IN : 0;
+ US_BULK_FLAG_IN : US_BULK_FLAG_OUT;
bcb->Tag = ++us->tag;
bcb->Lun = srb->device->lun;
if (us->fflags & US_FL_SCM_MULT_TARG)
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 03043d567fa1..f9ad90ce7af4 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -1289,6 +1289,6 @@ module_exit(uas_exit);
MODULE_DESCRIPTION("USB Attached SCSI driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(USB_STORAGE);
+MODULE_IMPORT_NS("USB_STORAGE");
MODULE_AUTHOR(
"Hans de Goede <hdegoede@redhat.com>, Matthew Wilcox and Sarah Sharp");
diff --git a/drivers/usb/typec/altmodes/displayport.c b/drivers/usb/typec/altmodes/displayport.c
index 92cc1b136120..2f03190a9873 100644
--- a/drivers/usb/typec/altmodes/displayport.c
+++ b/drivers/usb/typec/altmodes/displayport.c
@@ -729,7 +729,7 @@ int dp_altmode_probe(struct typec_altmode *alt)
/* FIXME: Port can only be DFP_U. */
- /* Make sure we have compatiple pin configurations */
+ /* Make sure we have compatible pin configurations */
if (!(DP_CAP_PIN_ASSIGN_DFP_D(port->vdo) &
DP_CAP_PIN_ASSIGN_UFP_D(alt->vdo)) &&
!(DP_CAP_PIN_ASSIGN_UFP_D(port->vdo) &
diff --git a/drivers/usb/typec/anx7411.c b/drivers/usb/typec/anx7411.c
index d1e7c487ddfb..0ae0a5ee3fae 100644
--- a/drivers/usb/typec/anx7411.c
+++ b/drivers/usb/typec/anx7411.c
@@ -290,6 +290,8 @@ struct anx7411_data {
struct power_supply *psy;
struct power_supply_desc psy_desc;
struct device *dev;
+ struct fwnode_handle *switch_node;
+ struct fwnode_handle *mux_node;
};
static u8 snk_identity[] = {
@@ -1021,6 +1023,16 @@ static void anx7411_port_unregister_altmodes(struct typec_altmode **adev)
}
}
+static void anx7411_port_unregister(struct typec_params *typecp)
+{
+ fwnode_handle_put(typecp->caps.fwnode);
+ anx7411_port_unregister_altmodes(typecp->port_amode);
+ if (typecp->port)
+ typec_unregister_port(typecp->port);
+ if (typecp->role_sw)
+ usb_role_switch_put(typecp->role_sw);
+}
+
static int anx7411_usb_mux_set(struct typec_mux_dev *mux,
struct typec_mux_state *state)
{
@@ -1089,6 +1101,7 @@ static void anx7411_unregister_mux(struct anx7411_data *ctx)
if (ctx->typec.typec_mux) {
typec_mux_unregister(ctx->typec.typec_mux);
ctx->typec.typec_mux = NULL;
+ fwnode_handle_put(ctx->mux_node);
}
}
@@ -1097,6 +1110,7 @@ static void anx7411_unregister_switch(struct anx7411_data *ctx)
if (ctx->typec.typec_switch) {
typec_switch_unregister(ctx->typec.typec_switch);
ctx->typec.typec_switch = NULL;
+ fwnode_handle_put(ctx->switch_node);
}
}
@@ -1104,28 +1118,29 @@ static int anx7411_typec_switch_probe(struct anx7411_data *ctx,
struct device *dev)
{
int ret;
- struct device_node *node;
- node = of_get_child_by_name(dev->of_node, "orientation_switch");
- if (!node)
+ ctx->switch_node = device_get_named_child_node(dev, "orientation_switch");
+ if (!ctx->switch_node)
return 0;
- ret = anx7411_register_switch(ctx, dev, &node->fwnode);
+ ret = anx7411_register_switch(ctx, dev, ctx->switch_node);
if (ret) {
dev_err(dev, "failed register switch");
+ fwnode_handle_put(ctx->switch_node);
return ret;
}
- node = of_get_child_by_name(dev->of_node, "mode_switch");
- if (!node) {
+ ctx->mux_node = device_get_named_child_node(dev, "mode_switch");
+ if (!ctx->mux_node) {
dev_err(dev, "no typec mux exist");
ret = -ENODEV;
goto unregister_switch;
}
- ret = anx7411_register_mux(ctx, dev, &node->fwnode);
+ ret = anx7411_register_mux(ctx, dev, ctx->mux_node);
if (ret) {
dev_err(dev, "failed register mode switch");
+ fwnode_handle_put(ctx->mux_node);
ret = -ENODEV;
goto unregister_switch;
}
@@ -1154,34 +1169,34 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
ret = fwnode_property_read_string(fwnode, "power-role", &buf);
if (ret) {
dev_err(dev, "power-role not found: %d\n", ret);
- return ret;
+ goto put_fwnode;
}
ret = typec_find_port_power_role(buf);
if (ret < 0)
- return ret;
+ goto put_fwnode;
cap->type = ret;
ret = fwnode_property_read_string(fwnode, "data-role", &buf);
if (ret) {
dev_err(dev, "data-role not found: %d\n", ret);
- return ret;
+ goto put_fwnode;
}
ret = typec_find_port_data_role(buf);
if (ret < 0)
- return ret;
+ goto put_fwnode;
cap->data = ret;
ret = fwnode_property_read_string(fwnode, "try-power-role", &buf);
if (ret) {
dev_err(dev, "try-power-role not found: %d\n", ret);
- return ret;
+ goto put_fwnode;
}
ret = typec_find_power_role(buf);
if (ret < 0)
- return ret;
+ goto put_fwnode;
cap->prefer_role = ret;
/* Get source pdos */
@@ -1193,7 +1208,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
typecp->src_pdo_nr);
if (ret < 0) {
dev_err(dev, "source cap validate failed: %d\n", ret);
- return -EINVAL;
+ goto put_fwnode;
}
typecp->caps_flags |= HAS_SOURCE_CAP;
@@ -1207,7 +1222,7 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
typecp->sink_pdo_nr);
if (ret < 0) {
dev_err(dev, "sink cap validate failed: %d\n", ret);
- return -EINVAL;
+ goto put_fwnode;
}
for (i = 0; i < typecp->sink_pdo_nr; i++) {
@@ -1251,13 +1266,21 @@ static int anx7411_typec_port_probe(struct anx7411_data *ctx,
ret = PTR_ERR(ctx->typec.port);
ctx->typec.port = NULL;
dev_err(dev, "Failed to register type c port %d\n", ret);
- return ret;
+ goto put_usb_role_switch;
}
typec_port_register_altmodes(ctx->typec.port, NULL, ctx,
ctx->typec.port_amode,
MAX_ALTMODE);
return 0;
+
+put_usb_role_switch:
+ if (ctx->typec.role_sw)
+ usb_role_switch_put(ctx->typec.role_sw);
+put_fwnode:
+ fwnode_handle_put(fwnode);
+
+ return ret;
}
static int anx7411_typec_check_connection(struct anx7411_data *ctx)
@@ -1523,8 +1546,7 @@ free_wq:
destroy_workqueue(plat->workqueue);
free_typec_port:
- typec_unregister_port(plat->typec.port);
- anx7411_port_unregister_altmodes(plat->typec.port_amode);
+ anx7411_port_unregister(&plat->typec);
free_typec_switch:
anx7411_unregister_switch(plat);
@@ -1548,17 +1570,11 @@ static void anx7411_i2c_remove(struct i2c_client *client)
i2c_unregister_device(plat->spi_client);
- if (plat->typec.role_sw)
- usb_role_switch_put(plat->typec.role_sw);
-
anx7411_unregister_mux(plat);
anx7411_unregister_switch(plat);
- if (plat->typec.port)
- typec_unregister_port(plat->typec.port);
-
- anx7411_port_unregister_altmodes(plat->typec.port_amode);
+ anx7411_port_unregister(&plat->typec);
}
static const struct i2c_device_id anx7411_id[] = {
diff --git a/drivers/usb/typec/class.c b/drivers/usb/typec/class.c
index 58f40156de56..4b3047e055a3 100644
--- a/drivers/usb/typec/class.c
+++ b/drivers/usb/typec/class.c
@@ -219,6 +219,13 @@ static ssize_t usb_power_delivery_revision_show(struct device *dev,
char *buf);
static DEVICE_ATTR_RO(usb_power_delivery_revision);
+static const char * const usb_modes[] = {
+ [USB_MODE_NONE] = "none",
+ [USB_MODE_USB2] = "usb2",
+ [USB_MODE_USB3] = "usb3",
+ [USB_MODE_USB4] = "usb4"
+};
+
/* ------------------------------------------------------------------------- */
/* Alternate Modes */
@@ -614,6 +621,75 @@ EXPORT_SYMBOL_GPL(typec_unregister_altmode);
/* ------------------------------------------------------------------------- */
/* Type-C Partners */
+/**
+ * typec_partner_set_usb_mode - Assign active USB Mode for the partner
+ * @partner: USB Type-C partner
+ * @mode: USB Mode (USB2, USB3 or USB4)
+ *
+ * The port drivers can use this function to assign the active USB Mode to
+ * @partner. The USB Mode can change for example due to Data Reset.
+ */
+void typec_partner_set_usb_mode(struct typec_partner *partner, enum usb_mode mode)
+{
+ if (!partner || partner->usb_mode == mode)
+ return;
+
+ partner->usb_capability |= BIT(mode - 1);
+ partner->usb_mode = mode;
+ sysfs_notify(&partner->dev.kobj, NULL, "usb_mode");
+}
+EXPORT_SYMBOL_GPL(typec_partner_set_usb_mode);
+
+static ssize_t
+usb_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct typec_partner *partner = to_typec_partner(dev);
+ int len = 0;
+ int i;
+
+ for (i = USB_MODE_USB2; i < USB_MODE_USB4 + 1; i++) {
+ if (!(BIT(i - 1) & partner->usb_capability))
+ continue;
+
+ if (i == partner->usb_mode)
+ len += sysfs_emit_at(buf, len, "[%s] ", usb_modes[i]);
+ else
+ len += sysfs_emit_at(buf, len, "%s ", usb_modes[i]);
+ }
+
+ sysfs_emit_at(buf, len - 1, "\n");
+
+ return len;
+}
+
+static ssize_t usb_mode_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct typec_partner *partner = to_typec_partner(dev);
+ struct typec_port *port = to_typec_port(dev->parent);
+ int mode;
+ int ret;
+
+ if (!port->ops || !port->ops->enter_usb_mode)
+ return -EOPNOTSUPP;
+
+ mode = sysfs_match_string(usb_modes, buf);
+ if (mode < 0)
+ return mode;
+
+ if (mode == partner->usb_mode)
+ return size;
+
+ ret = port->ops->enter_usb_mode(port, mode);
+ if (ret)
+ return ret;
+
+ typec_partner_set_usb_mode(partner, mode);
+
+ return size;
+}
+static DEVICE_ATTR_RW(usb_mode);
+
static ssize_t accessory_mode_show(struct device *dev,
struct device_attribute *attr,
char *buf)
@@ -660,6 +736,7 @@ static struct attribute *typec_partner_attrs[] = {
&dev_attr_supports_usb_power_delivery.attr,
&dev_attr_number_of_alternate_modes.attr,
&dev_attr_type.attr,
+ &dev_attr_usb_mode.attr,
&dev_attr_usb_power_delivery_revision.attr,
NULL
};
@@ -667,6 +744,14 @@ static struct attribute *typec_partner_attrs[] = {
static umode_t typec_partner_attr_is_visible(struct kobject *kobj, struct attribute *attr, int n)
{
struct typec_partner *partner = to_typec_partner(kobj_to_dev(kobj));
+ struct typec_port *port = to_typec_port(partner->dev.parent);
+
+ if (attr == &dev_attr_usb_mode.attr) {
+ if (!partner->usb_capability)
+ return 0;
+ if (!port->ops || !port->ops->enter_usb_mode)
+ return 0444;
+ }
if (attr == &dev_attr_number_of_alternate_modes.attr) {
if (partner->num_altmodes < 0)
@@ -740,10 +825,33 @@ static void typec_partner_unlink_device(struct typec_partner *partner, struct de
*/
int typec_partner_set_identity(struct typec_partner *partner)
{
- if (!partner->identity)
+ u8 usb_capability = partner->usb_capability;
+ struct device *dev = &partner->dev;
+ struct usb_pd_identity *id;
+
+ id = get_pd_identity(dev);
+ if (!id)
return -EINVAL;
- typec_report_identity(&partner->dev);
+ if (to_typec_port(dev->parent)->data_role == TYPEC_HOST) {
+ u32 devcap = PD_VDO_UFP_DEVCAP(id->vdo[0]);
+
+ if (devcap & (DEV_USB2_CAPABLE | DEV_USB2_BILLBOARD))
+ usb_capability |= USB_CAPABILITY_USB2;
+ if (devcap & DEV_USB3_CAPABLE)
+ usb_capability |= USB_CAPABILITY_USB3;
+ if (devcap & DEV_USB4_CAPABLE)
+ usb_capability |= USB_CAPABILITY_USB4;
+ } else {
+ usb_capability = PD_VDO_DFP_HOSTCAP(id->vdo[0]);
+ }
+
+ if (partner->usb_capability != usb_capability) {
+ partner->usb_capability = usb_capability;
+ sysfs_notify(&dev->kobj, NULL, "usb_mode");
+ }
+
+ typec_report_identity(dev);
return 0;
}
EXPORT_SYMBOL_GPL(typec_partner_set_identity);
@@ -913,6 +1021,7 @@ struct typec_partner *typec_register_partner(struct typec_port *port,
partner->usb_pd = desc->usb_pd;
partner->accessory = desc->accessory;
partner->num_altmodes = -1;
+ partner->usb_capability = desc->usb_capability;
partner->pd_revision = desc->pd_revision;
partner->svdm_version = port->cap->svdm_version;
partner->attach = desc->attach;
@@ -932,6 +1041,15 @@ struct typec_partner *typec_register_partner(struct typec_port *port,
partner->dev.type = &typec_partner_dev_type;
dev_set_name(&partner->dev, "%s-partner", dev_name(&port->dev));
+ if (port->usb2_dev) {
+ partner->usb_capability |= USB_CAPABILITY_USB2;
+ partner->usb_mode = USB_MODE_USB2;
+ }
+ if (port->usb3_dev) {
+ partner->usb_capability |= USB_CAPABILITY_USB2 | USB_CAPABILITY_USB3;
+ partner->usb_mode = USB_MODE_USB3;
+ }
+
ret = device_register(&partner->dev);
if (ret) {
dev_err(&port->dev, "failed to register partner (%d)\n", ret);
@@ -1293,6 +1411,67 @@ EXPORT_SYMBOL_GPL(typec_unregister_cable);
/* USB Type-C ports */
/**
+ * typec_port_set_usb_mode - Set the operational USB mode for the port
+ * @port: USB Type-C port
+ * @mode: USB Mode (USB2, USB3 or USB4)
+ *
+ * @mode will be used with the next Enter_USB message. Existing connections are
+ * not affected.
+ */
+void typec_port_set_usb_mode(struct typec_port *port, enum usb_mode mode)
+{
+ port->usb_mode = mode;
+}
+EXPORT_SYMBOL_GPL(typec_port_set_usb_mode);
+
+static ssize_t
+usb_capability_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct typec_port *port = to_typec_port(dev);
+ int len = 0;
+ int i;
+
+ for (i = USB_MODE_USB2; i < USB_MODE_USB4 + 1; i++) {
+ if (!(BIT(i - 1) & port->cap->usb_capability))
+ continue;
+
+ if (i == port->usb_mode)
+ len += sysfs_emit_at(buf, len, "[%s] ", usb_modes[i]);
+ else
+ len += sysfs_emit_at(buf, len, "%s ", usb_modes[i]);
+ }
+
+ sysfs_emit_at(buf, len - 1, "\n");
+
+ return len;
+}
+
+static ssize_t
+usb_capability_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct typec_port *port = to_typec_port(dev);
+ int ret = 0;
+ int mode;
+
+ if (!port->ops || !port->ops->default_usb_mode_set)
+ return -EOPNOTSUPP;
+
+ mode = sysfs_match_string(usb_modes, buf);
+ if (mode < 0)
+ return mode;
+
+ ret = port->ops->default_usb_mode_set(port, mode);
+ if (ret)
+ return ret;
+
+ port->usb_mode = mode;
+
+ return size;
+}
+static DEVICE_ATTR_RW(usb_capability);
+
+/**
* typec_port_set_usb_power_delivery - Assign USB PD for port.
* @port: USB Type-C port.
* @pd: USB PD instance.
@@ -1760,6 +1939,7 @@ static struct attribute *typec_attrs[] = {
&dev_attr_vconn_source.attr,
&dev_attr_port_type.attr,
&dev_attr_orientation.attr,
+ &dev_attr_usb_capability.attr,
NULL,
};
@@ -1793,6 +1973,11 @@ static umode_t typec_attr_is_visible(struct kobject *kobj,
if (port->cap->orientation_aware)
return 0444;
return 0;
+ } else if (attr == &dev_attr_usb_capability.attr) {
+ if (!port->cap->usb_capability)
+ return 0;
+ if (!port->ops || !port->ops->default_usb_mode_set)
+ return 0444;
}
return attr->mode;
@@ -1864,13 +2049,18 @@ static void typec_partner_attach(struct typec_connector *con, struct device *dev
struct typec_port *port = container_of(con, struct typec_port, con);
struct typec_partner *partner = typec_get_partner(port);
struct usb_device *udev = to_usb_device(dev);
+ enum usb_mode usb_mode;
- if (udev->speed < USB_SPEED_SUPER)
+ if (udev->speed < USB_SPEED_SUPER) {
+ usb_mode = USB_MODE_USB2;
port->usb2_dev = dev;
- else
+ } else {
+ usb_mode = USB_MODE_USB3;
port->usb3_dev = dev;
+ }
if (partner) {
+ typec_partner_set_usb_mode(partner, usb_mode);
typec_partner_link_device(partner, dev);
put_device(&partner->dev);
}
@@ -2433,6 +2623,13 @@ struct typec_port *typec_register_port(struct device *parent,
port->con.attach = typec_partner_attach;
port->con.deattach = typec_partner_deattach;
+ if (cap->usb_capability & USB_CAPABILITY_USB4)
+ port->usb_mode = USB_MODE_USB4;
+ else if (cap->usb_capability & USB_CAPABILITY_USB3)
+ port->usb_mode = USB_MODE_USB3;
+ else if (cap->usb_capability & USB_CAPABILITY_USB2)
+ port->usb_mode = USB_MODE_USB2;
+
device_initialize(&port->dev);
port->dev.class = &typec_class;
port->dev.parent = parent;
diff --git a/drivers/usb/typec/class.h b/drivers/usb/typec/class.h
index 7485cdb9dd20..b3076a24ad2e 100644
--- a/drivers/usb/typec/class.h
+++ b/drivers/usb/typec/class.h
@@ -35,6 +35,8 @@ struct typec_partner {
int num_altmodes;
u16 pd_revision; /* 0300H = "3.0" */
enum usb_pd_svdm_ver svdm_version;
+ enum usb_mode usb_mode;
+ u8 usb_capability;
struct usb_power_delivery *pd;
@@ -55,6 +57,7 @@ struct typec_port {
enum typec_role vconn_role;
enum typec_pwr_opmode pwr_opmode;
enum typec_port_type port_type;
+ enum usb_mode usb_mode;
struct mutex port_type_lock;
enum typec_orientation orientation;
diff --git a/drivers/usb/typec/mux/Kconfig b/drivers/usb/typec/mux/Kconfig
index ce7db6ad3057..67381b4ef4f6 100644
--- a/drivers/usb/typec/mux/Kconfig
+++ b/drivers/usb/typec/mux/Kconfig
@@ -66,6 +66,15 @@ config TYPEC_MUX_PTN36502
Say Y or M if your system has a NXP PTN36502 Type-C redriver chip
found on some devices with a Type-C port.
+config TYPEC_MUX_TUSB1046
+ tristate "TI TUSB1046 Type-C crosspoint switch driver"
+ depends on I2C
+ help
+ Driver for the Texas Instruments TUSB1046-DCI crosspoint switch.
+ Supports flipping USB-C SuperSpeed lanes to adapt to orientation
+ changes, as well as muxing DisplayPort and sideband signals to a
+ common Type-C connector.
+
config TYPEC_MUX_WCD939X_USBSS
tristate "Qualcomm WCD939x USBSS Analog Audio Switch driver"
depends on I2C
diff --git a/drivers/usb/typec/mux/Makefile b/drivers/usb/typec/mux/Makefile
index bb96f30267af..60879446da93 100644
--- a/drivers/usb/typec/mux/Makefile
+++ b/drivers/usb/typec/mux/Makefile
@@ -7,4 +7,5 @@ obj-$(CONFIG_TYPEC_MUX_INTEL_PMC) += intel_pmc_mux.o
obj-$(CONFIG_TYPEC_MUX_IT5205) += it5205.o
obj-$(CONFIG_TYPEC_MUX_NB7VPQ904M) += nb7vpq904m.o
obj-$(CONFIG_TYPEC_MUX_PTN36502) += ptn36502.o
+obj-$(CONFIG_TYPEC_MUX_TUSB1046) += tusb1046.o
obj-$(CONFIG_TYPEC_MUX_WCD939X_USBSS) += wcd939x-usbss.o
diff --git a/drivers/usb/typec/mux/gpio-sbu-mux.c b/drivers/usb/typec/mux/gpio-sbu-mux.c
index 8902102c05a8..1834f1a2dd9d 100644
--- a/drivers/usb/typec/mux/gpio-sbu-mux.c
+++ b/drivers/usb/typec/mux/gpio-sbu-mux.c
@@ -159,7 +159,7 @@ MODULE_DEVICE_TABLE(of, gpio_sbu_mux_match);
static struct platform_driver gpio_sbu_mux_driver = {
.probe = gpio_sbu_mux_probe,
- .remove_new = gpio_sbu_mux_remove,
+ .remove = gpio_sbu_mux_remove,
.driver = {
.name = "gpio_sbu_mux",
.of_match_table = gpio_sbu_mux_match,
diff --git a/drivers/usb/typec/mux/intel_pmc_mux.c b/drivers/usb/typec/mux/intel_pmc_mux.c
index 46b4c5c3a6be..5dfe95754394 100644
--- a/drivers/usb/typec/mux/intel_pmc_mux.c
+++ b/drivers/usb/typec/mux/intel_pmc_mux.c
@@ -828,7 +828,7 @@ static struct platform_driver pmc_usb_driver = {
.acpi_match_table = ACPI_PTR(pmc_usb_acpi_ids),
},
.probe = pmc_usb_probe,
- .remove_new = pmc_usb_remove,
+ .remove = pmc_usb_remove,
};
static int __init pmc_usb_init(void)
diff --git a/drivers/usb/typec/mux/tusb1046.c b/drivers/usb/typec/mux/tusb1046.c
new file mode 100644
index 000000000000..b4f45c217b59
--- /dev/null
+++ b/drivers/usb/typec/mux/tusb1046.c
@@ -0,0 +1,196 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Driver for the TUSB1046-DCI USB Type-C crosspoint switch
+ *
+ * Copyright (C) 2024 Bootlin
+ */
+
+#include <linux/bits.h>
+#include <linux/i2c.h>
+#include <linux/usb/typec_mux.h>
+#include <linux/usb/typec_dp.h>
+#include <linux/usb/typec_altmode.h>
+#include <linux/module.h>
+#include <linux/mod_devicetable.h>
+#include <linux/err.h>
+#include <linux/of_device.h>
+#include <linux/device.h>
+#include <linux/mutex.h>
+
+#define TUSB1046_REG_GENERAL 0xa
+
+/* General register bits */
+#define TUSB1046_GENERAL_FLIPSEL BIT(2)
+#define TUSB1046_GENERAL_CTLSEL GENMASK(1, 0)
+
+/* Mux modes */
+#define TUSB1046_CTLSEL_DISABLED 0x0
+#define TUSB1046_CTLSEL_USB3 0x1
+#define TUSB1046_CTLSEL_4LANE_DP 0x2
+#define TUSB1046_CTLSEL_USB3_AND_2LANE_DP 0x3
+
+struct tusb1046_priv {
+ struct i2c_client *client;
+ struct typec_switch_dev *sw;
+ struct typec_mux_dev *mux;
+
+ /* Lock General register during accesses */
+ struct mutex general_reg_lock;
+};
+
+static int tusb1046_mux_set(struct typec_mux_dev *mux,
+ struct typec_mux_state *state)
+{
+ struct tusb1046_priv *priv = typec_mux_get_drvdata(mux);
+ struct i2c_client *client = priv->client;
+ struct device *dev = &client->dev;
+ int mode, val, ret = 0;
+
+ if (state->mode >= TYPEC_STATE_MODAL &&
+ state->alt->svid != USB_TYPEC_DP_SID)
+ return -EINVAL;
+
+ dev_dbg(dev, "mux mode requested: %lu\n", state->mode);
+
+ mutex_lock(&priv->general_reg_lock);
+
+ val = i2c_smbus_read_byte_data(client, TUSB1046_REG_GENERAL);
+ if (val < 0) {
+ dev_err(dev, "failed to read ctlsel status, err %d\n", val);
+ ret = val;
+ goto out_unlock;
+ }
+
+ switch (state->mode) {
+ case TYPEC_STATE_USB:
+ mode = TUSB1046_CTLSEL_USB3;
+ break;
+ case TYPEC_DP_STATE_C:
+ case TYPEC_DP_STATE_E:
+ mode = TUSB1046_CTLSEL_4LANE_DP;
+ break;
+ case TYPEC_DP_STATE_D:
+ mode = TUSB1046_CTLSEL_USB3_AND_2LANE_DP;
+ break;
+ case TYPEC_STATE_SAFE:
+ default:
+ mode = TUSB1046_CTLSEL_DISABLED;
+ break;
+ }
+
+ val &= ~TUSB1046_GENERAL_CTLSEL;
+ val |= mode;
+
+ ret = i2c_smbus_write_byte_data(client, TUSB1046_REG_GENERAL, val);
+
+out_unlock:
+ mutex_unlock(&priv->general_reg_lock);
+ return ret;
+}
+
+static int tusb1046_switch_set(struct typec_switch_dev *sw,
+ enum typec_orientation orientation)
+{
+ struct tusb1046_priv *priv = typec_switch_get_drvdata(sw);
+ struct i2c_client *client = priv->client;
+ struct device *dev = &client->dev;
+ int val, ret = 0;
+
+ dev_dbg(dev, "setting USB3.0 lane flip for orientation %d\n", orientation);
+
+ mutex_lock(&priv->general_reg_lock);
+
+ val = i2c_smbus_read_byte_data(client, TUSB1046_REG_GENERAL);
+ if (val < 0) {
+ dev_err(dev, "failed to read flipsel status, err %d\n", val);
+ ret = val;
+ goto out_unlock;
+ }
+
+ if (orientation == TYPEC_ORIENTATION_REVERSE)
+ val |= TUSB1046_GENERAL_FLIPSEL;
+ else
+ val &= ~TUSB1046_GENERAL_FLIPSEL;
+
+ ret = i2c_smbus_write_byte_data(client, TUSB1046_REG_GENERAL, val);
+
+out_unlock:
+ mutex_unlock(&priv->general_reg_lock);
+ return ret;
+}
+
+static int tusb1046_i2c_probe(struct i2c_client *client)
+{
+ struct typec_switch_desc sw_desc = { };
+ struct typec_mux_desc mux_desc = { };
+ struct device *dev = &client->dev;
+ struct tusb1046_priv *priv;
+ int ret = 0;
+
+ priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+ if (!priv)
+ return dev_err_probe(dev, -ENOMEM, "failed to allocate driver data\n");
+
+ priv->client = client;
+
+ mutex_init(&priv->general_reg_lock);
+
+ sw_desc.drvdata = priv;
+ sw_desc.fwnode = dev_fwnode(dev);
+ sw_desc.set = tusb1046_switch_set;
+
+ priv->sw = typec_switch_register(dev, &sw_desc);
+ if (IS_ERR(priv->sw)) {
+ ret = dev_err_probe(dev, PTR_ERR(priv->sw), "failed to register type-c switch\n");
+ goto err_destroy_mutex;
+ }
+
+ mux_desc.drvdata = priv;
+ mux_desc.fwnode = dev_fwnode(dev);
+ mux_desc.set = tusb1046_mux_set;
+
+ priv->mux = typec_mux_register(dev, &mux_desc);
+ if (IS_ERR(priv->mux)) {
+ ret = dev_err_probe(dev, PTR_ERR(priv->mux), "failed to register type-c mux\n");
+ goto err_unregister_switch;
+ }
+
+ i2c_set_clientdata(client, priv);
+
+ return 0;
+
+err_unregister_switch:
+ typec_switch_unregister(priv->sw);
+err_destroy_mutex:
+ mutex_destroy(&priv->general_reg_lock);
+ return ret;
+}
+
+static void tusb1046_i2c_remove(struct i2c_client *client)
+{
+ struct tusb1046_priv *priv = i2c_get_clientdata(client);
+
+ typec_switch_unregister(priv->sw);
+ typec_mux_unregister(priv->mux);
+ mutex_destroy(&priv->general_reg_lock);
+}
+
+static const struct of_device_id tusb1046_match_table[] = {
+ {.compatible = "ti,tusb1046"},
+ {},
+};
+
+static struct i2c_driver tusb1046_driver = {
+ .driver = {
+ .name = "tusb1046",
+ .of_match_table = tusb1046_match_table,
+ },
+ .probe = tusb1046_i2c_probe,
+ .remove = tusb1046_i2c_remove,
+};
+
+module_i2c_driver(tusb1046_driver);
+
+MODULE_DESCRIPTION("TUSB1046 USB Type-C switch driver");
+MODULE_AUTHOR("Romain Gantois <romain.gantois@bootlin.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/typec/stusb160x.c b/drivers/usb/typec/stusb160x.c
index f3140fc04c12..6d85b25b40bc 100644
--- a/drivers/usb/typec/stusb160x.c
+++ b/drivers/usb/typec/stusb160x.c
@@ -633,9 +633,8 @@ MODULE_DEVICE_TABLE(of, stusb160x_of_match);
static int stusb160x_probe(struct i2c_client *client)
{
+ const struct regmap_config *regmap_config;
struct stusb160x *chip;
- const struct of_device_id *match;
- struct regmap_config *regmap_config;
struct fwnode_handle *fwnode;
int ret;
@@ -645,8 +644,8 @@ static int stusb160x_probe(struct i2c_client *client)
i2c_set_clientdata(client, chip);
- match = i2c_of_match_device(stusb160x_of_match, client);
- regmap_config = (struct regmap_config *)match->data;
+ regmap_config = i2c_get_match_data(client);
+
chip->regmap = devm_regmap_init_i2c(client, regmap_config);
if (IS_ERR(chip->regmap)) {
ret = PTR_ERR(chip->regmap);
diff --git a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
index b80eb2d78d88..3766790c1548 100644
--- a/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
+++ b/drivers/usb/typec/tcpm/qcom/qcom_pmic_typec.c
@@ -163,7 +163,7 @@ static struct platform_driver qcom_pmic_typec_driver = {
.of_match_table = qcom_pmic_typec_table,
},
.probe = qcom_pmic_typec_probe,
- .remove_new = qcom_pmic_typec_remove,
+ .remove = qcom_pmic_typec_remove,
};
module_platform_driver(qcom_pmic_typec_driver);
diff --git a/drivers/usb/typec/tcpm/tcpci_mt6360.c b/drivers/usb/typec/tcpm/tcpci_mt6360.c
index 02b7fd302265..881ffacbfd77 100644
--- a/drivers/usb/typec/tcpm/tcpci_mt6360.c
+++ b/drivers/usb/typec/tcpm/tcpci_mt6360.c
@@ -221,7 +221,7 @@ static struct platform_driver mt6360_tcpc_driver = {
.of_match_table = mt6360_tcpc_of_id,
},
.probe = mt6360_tcpc_probe,
- .remove_new = mt6360_tcpc_remove,
+ .remove = mt6360_tcpc_remove,
};
module_platform_driver(mt6360_tcpc_driver);
diff --git a/drivers/usb/typec/tcpm/tcpci_mt6370.c b/drivers/usb/typec/tcpm/tcpci_mt6370.c
index 9cda1005ef01..1479f961772d 100644
--- a/drivers/usb/typec/tcpm/tcpci_mt6370.c
+++ b/drivers/usb/typec/tcpm/tcpci_mt6370.c
@@ -196,7 +196,7 @@ static struct platform_driver mt6370_tcpc_driver = {
.of_match_table = mt6370_tcpc_devid_table,
},
.probe = mt6370_tcpc_probe,
- .remove_new = mt6370_tcpc_remove,
+ .remove = mt6370_tcpc_remove,
};
module_platform_driver(mt6370_tcpc_driver);
diff --git a/drivers/usb/typec/tcpm/tcpm.c b/drivers/usb/typec/tcpm/tcpm.c
index 7ae341a40342..6021eeb903fe 100644
--- a/drivers/usb/typec/tcpm/tcpm.c
+++ b/drivers/usb/typec/tcpm/tcpm.c
@@ -310,6 +310,18 @@ struct pd_data {
unsigned int operating_snk_mw;
};
+/*
+ * @sink_wait_cap_time: Deadline (in ms) for tTypeCSinkWaitCap timer
+ * @ps_src_wait_off_time: Deadline (in ms) for tPSSourceOff timer
+ * @cc_debounce_time: Deadline (in ms) for tCCDebounce timer
+ */
+struct pd_timings {
+ u32 sink_wait_cap_time;
+ u32 ps_src_off_time;
+ u32 cc_debounce_time;
+ u32 snk_bc12_cmpletion_time;
+};
+
struct tcpm_port {
struct device *dev;
@@ -552,6 +564,9 @@ struct tcpm_port {
*/
unsigned int message_id_prime;
unsigned int rx_msgid_prime;
+
+ /* Timer deadline values configured at runtime */
+ struct pd_timings timings;
#ifdef CONFIG_DEBUG_FS
struct dentry *dentry;
struct mutex logbuffer_lock; /* log buffer access lock */
@@ -4640,15 +4655,15 @@ static void run_state_machine(struct tcpm_port *port)
case SRC_ATTACH_WAIT:
if (tcpm_port_is_debug(port))
tcpm_set_state(port, DEBUG_ACC_ATTACHED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
else if (tcpm_port_is_audio(port))
tcpm_set_state(port, AUDIO_ACC_ATTACHED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
else if (tcpm_port_is_source(port) && port->vbus_vsafe0v)
tcpm_set_state(port,
tcpm_try_snk(port) ? SNK_TRY
: SRC_ATTACHED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
break;
case SNK_TRY:
@@ -4699,7 +4714,7 @@ static void run_state_machine(struct tcpm_port *port)
}
break;
case SRC_TRYWAIT_DEBOUNCE:
- tcpm_set_state(port, SRC_ATTACHED, PD_T_CC_DEBOUNCE);
+ tcpm_set_state(port, SRC_ATTACHED, port->timings.cc_debounce_time);
break;
case SRC_TRYWAIT_UNATTACHED:
tcpm_set_state(port, SNK_UNATTACHED, 0);
@@ -4902,7 +4917,7 @@ static void run_state_machine(struct tcpm_port *port)
(port->cc1 != TYPEC_CC_OPEN &&
port->cc2 == TYPEC_CC_OPEN))
tcpm_set_state(port, SNK_DEBOUNCED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
else if (tcpm_port_is_disconnected(port))
tcpm_set_state(port, SNK_UNATTACHED,
PD_T_PD_DEBOUNCE);
@@ -4942,7 +4957,7 @@ static void run_state_machine(struct tcpm_port *port)
break;
case SNK_TRYWAIT:
tcpm_set_cc(port, TYPEC_CC_RD);
- tcpm_set_state(port, SNK_TRYWAIT_VBUS, PD_T_CC_DEBOUNCE);
+ tcpm_set_state(port, SNK_TRYWAIT_VBUS, port->timings.cc_debounce_time);
break;
case SNK_TRYWAIT_VBUS:
/*
@@ -4965,7 +4980,16 @@ static void run_state_machine(struct tcpm_port *port)
if (ret < 0)
tcpm_set_state(port, SNK_UNATTACHED, 0);
else
- tcpm_set_state(port, SNK_STARTUP, 0);
+ /*
+ * For Type C port controllers that use Battery Charging
+ * Detection (based on BCv1.2 spec) to detect USB
+ * charger type, add a delay of "snk_bc12_cmpletion_time"
+ * before transitioning to SNK_STARTUP to allow BC1.2
+ * detection to complete before PD is eventually enabled
+ * in later states.
+ */
+ tcpm_set_state(port, SNK_STARTUP,
+ port->timings.snk_bc12_cmpletion_time);
break;
case SNK_STARTUP:
opmode = tcpm_get_pwr_opmode(port->polarity ?
@@ -5015,7 +5039,7 @@ static void run_state_machine(struct tcpm_port *port)
break;
case SNK_DISCOVERY_DEBOUNCE:
tcpm_set_state(port, SNK_DISCOVERY_DEBOUNCE_DONE,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
break;
case SNK_DISCOVERY_DEBOUNCE_DONE:
if (!tcpm_port_is_disconnected(port) &&
@@ -5042,13 +5066,14 @@ static void run_state_machine(struct tcpm_port *port)
if (port->vbus_never_low) {
port->vbus_never_low = false;
tcpm_set_state(port, SNK_SOFT_RESET,
- PD_T_SINK_WAIT_CAP);
+ port->timings.sink_wait_cap_time);
} else {
if (!port->self_powered)
upcoming_state = SNK_WAIT_CAPABILITIES_TIMEOUT;
else
upcoming_state = hard_reset_state(port);
- tcpm_set_state(port, upcoming_state, PD_T_SINK_WAIT_CAP);
+ tcpm_set_state(port, SNK_WAIT_CAPABILITIES_TIMEOUT,
+ port->timings.sink_wait_cap_time);
}
break;
case SNK_WAIT_CAPABILITIES_TIMEOUT:
@@ -5070,7 +5095,8 @@ static void run_state_machine(struct tcpm_port *port)
if (tcpm_pd_send_control(port, PD_CTRL_GET_SOURCE_CAP, TCPC_TX_SOP))
tcpm_set_state_cond(port, hard_reset_state(port), 0);
else
- tcpm_set_state(port, hard_reset_state(port), PD_T_SINK_WAIT_CAP);
+ tcpm_set_state(port, hard_reset_state(port),
+ port->timings.sink_wait_cap_time);
break;
case SNK_NEGOTIATE_CAPABILITIES:
port->pd_capable = true;
@@ -5207,7 +5233,7 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, ACC_UNATTACHED, 0);
break;
case AUDIO_ACC_DEBOUNCE:
- tcpm_set_state(port, ACC_UNATTACHED, PD_T_CC_DEBOUNCE);
+ tcpm_set_state(port, ACC_UNATTACHED, port->timings.cc_debounce_time);
break;
/* Hard_Reset states */
@@ -5274,7 +5300,7 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, SRC_UNATTACHED, PD_T_PS_SOURCE_ON);
break;
case SNK_HARD_RESET_SINK_OFF:
- /* Do not discharge/disconnect during hard reseet */
+ /* Do not discharge/disconnect during hard reset */
tcpm_set_auto_vbus_discharge_threshold(port, TYPEC_PWR_MODE_USB, false, 0);
memset(&port->pps_data, 0, sizeof(port->pps_data));
tcpm_set_vconn(port, false);
@@ -5424,7 +5450,7 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_state(port, ERROR_RECOVERY, 0);
break;
case FR_SWAP_SNK_SRC_TRANSITION_TO_OFF:
- tcpm_set_state(port, ERROR_RECOVERY, PD_T_PS_SOURCE_OFF);
+ tcpm_set_state(port, ERROR_RECOVERY, port->timings.ps_src_off_time);
break;
case FR_SWAP_SNK_SRC_NEW_SINK_READY:
if (port->vbus_source)
@@ -5479,7 +5505,7 @@ static void run_state_machine(struct tcpm_port *port)
tcpm_set_cc(port, TYPEC_CC_RD);
/* allow CC debounce */
tcpm_set_state(port, PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
break;
case PR_SWAP_SRC_SNK_SOURCE_OFF_CC_DEBOUNCED:
/*
@@ -5514,7 +5540,7 @@ static void run_state_machine(struct tcpm_port *port)
port->pps_data.active, 0);
tcpm_set_charge(port, false);
tcpm_set_state(port, hard_reset_state(port),
- PD_T_PS_SOURCE_OFF);
+ port->timings.ps_src_off_time);
break;
case PR_SWAP_SNK_SRC_SOURCE_ON:
tcpm_enable_auto_vbus_discharge(port, true);
@@ -5670,7 +5696,7 @@ static void run_state_machine(struct tcpm_port *port)
case PORT_RESET_WAIT_OFF:
tcpm_set_state(port,
tcpm_default_state(port),
- port->vbus_present ? PD_T_PS_SOURCE_OFF : 0);
+ port->vbus_present ? port->timings.ps_src_off_time : 0);
break;
/* AMS intermediate state */
@@ -6070,7 +6096,7 @@ static void _tcpm_pd_vbus_off(struct tcpm_port *port)
break;
case SNK_ATTACH_WAIT:
case SNK_DEBOUNCED:
- /* Do nothing, as TCPM is still waiting for vbus to reaach VSAFE5V to connect */
+ /* Do nothing, as TCPM is still waiting for vbus to reach VSAFE5V to connect */
break;
case SNK_NEGOTIATE_CAPABILITIES:
@@ -6161,7 +6187,7 @@ static void _tcpm_pd_vbus_vsafe0v(struct tcpm_port *port)
case SRC_ATTACH_WAIT:
if (tcpm_port_is_source(port))
tcpm_set_state(port, tcpm_try_snk(port) ? SNK_TRY : SRC_ATTACHED,
- PD_T_CC_DEBOUNCE);
+ port->timings.cc_debounce_time);
break;
case SRC_STARTUP:
case SRC_SEND_CAPABILITIES:
@@ -7057,6 +7083,34 @@ err_unregister:
return ret;
}
+static void tcpm_fw_get_timings(struct tcpm_port *port, struct fwnode_handle *fwnode)
+{
+ int ret;
+ u32 val;
+
+ ret = fwnode_property_read_u32(fwnode, "sink-wait-cap-time-ms", &val);
+ if (!ret)
+ port->timings.sink_wait_cap_time = val;
+ else
+ port->timings.sink_wait_cap_time = PD_T_SINK_WAIT_CAP;
+
+ ret = fwnode_property_read_u32(fwnode, "ps-source-off-time-ms", &val);
+ if (!ret)
+ port->timings.ps_src_off_time = val;
+ else
+ port->timings.ps_src_off_time = PD_T_PS_SOURCE_OFF;
+
+ ret = fwnode_property_read_u32(fwnode, "cc-debounce-time-ms", &val);
+ if (!ret)
+ port->timings.cc_debounce_time = val;
+ else
+ port->timings.cc_debounce_time = PD_T_CC_DEBOUNCE;
+
+ ret = fwnode_property_read_u32(fwnode, "sink-bc12-completion-time-ms", &val);
+ if (!ret)
+ port->timings.snk_bc12_cmpletion_time = val;
+}
+
static int tcpm_fw_get_caps(struct tcpm_port *port, struct fwnode_handle *fwnode)
{
struct fwnode_handle *capabilities, *child, *caps = NULL;
@@ -7371,7 +7425,7 @@ static int tcpm_psy_get_input_power_limit(struct tcpm_port *port,
src_mv = pdo_fixed_voltage(pdo);
src_ma = pdo_max_current(pdo);
tmp = src_mv * src_ma;
- max_src_uw = tmp > max_src_uw ? tmp : max_src_uw;
+ max_src_uw = max(tmp, max_src_uw);
}
}
@@ -7614,6 +7668,8 @@ struct tcpm_port *tcpm_register_port(struct device *dev, struct tcpc_dev *tcpc)
if (err < 0)
goto out_destroy_wq;
+ tcpm_fw_get_timings(port, tcpc->fwnode);
+
port->try_role = port->typec_caps.prefer_role;
port->typec_caps.revision = 0x0120; /* Type-C spec release 1.2 */
diff --git a/drivers/usb/typec/tcpm/wcove.c b/drivers/usb/typec/tcpm/wcove.c
index 60b2766a69bf..759c982bb16a 100644
--- a/drivers/usb/typec/tcpm/wcove.c
+++ b/drivers/usb/typec/tcpm/wcove.c
@@ -687,7 +687,7 @@ static struct platform_driver wcove_typec_driver = {
.name = "bxt_wcove_usbc",
},
.probe = wcove_typec_probe,
- .remove_new = wcove_typec_remove,
+ .remove = wcove_typec_remove,
};
module_platform_driver(wcove_typec_driver);
diff --git a/drivers/usb/typec/ucsi/debugfs.c b/drivers/usb/typec/ucsi/debugfs.c
index f67733cecfdf..83ff23086d79 100644
--- a/drivers/usb/typec/ucsi/debugfs.c
+++ b/drivers/usb/typec/ucsi/debugfs.c
@@ -32,6 +32,7 @@ static int ucsi_cmd(void *data, u64 val)
case UCSI_SET_UOR:
case UCSI_SET_PDR:
case UCSI_CONNECTOR_RESET:
+ case UCSI_SET_SINK_PATH:
ret = ucsi_send_command(ucsi, val, NULL, 0);
break;
case UCSI_GET_CAPABILITY:
diff --git a/drivers/usb/typec/ucsi/psy.c b/drivers/usb/typec/ucsi/psy.c
index 1c631c7855a9..62ac69730405 100644
--- a/drivers/usb/typec/ucsi/psy.c
+++ b/drivers/usb/typec/ucsi/psy.c
@@ -55,8 +55,8 @@ static int ucsi_psy_get_online(struct ucsi_connector *con,
union power_supply_propval *val)
{
val->intval = UCSI_PSY_OFFLINE;
- if (con->status.flags & UCSI_CONSTAT_CONNECTED &&
- (con->status.flags & UCSI_CONSTAT_PWR_DIR) == TYPEC_SINK)
+ if (UCSI_CONSTAT(con, CONNECTED) &&
+ (UCSI_CONSTAT(con, PWR_DIR) == TYPEC_SINK))
val->intval = UCSI_PSY_FIXED_ONLINE;
return 0;
}
@@ -66,7 +66,7 @@ static int ucsi_psy_get_voltage_min(struct ucsi_connector *con,
{
u32 pdo;
- switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
pdo = con->src_pdos[0];
val->intval = pdo_fixed_voltage(pdo) * 1000;
@@ -89,7 +89,7 @@ static int ucsi_psy_get_voltage_max(struct ucsi_connector *con,
{
u32 pdo;
- switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
if (con->num_pdos > 0) {
pdo = con->src_pdos[con->num_pdos - 1];
@@ -117,7 +117,7 @@ static int ucsi_psy_get_voltage_now(struct ucsi_connector *con,
int index;
u32 pdo;
- switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
index = rdo_index(con->rdo);
if (index > 0) {
@@ -145,7 +145,7 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con,
{
u32 pdo;
- switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
if (con->num_pdos > 0) {
pdo = con->src_pdos[con->num_pdos - 1];
@@ -173,9 +173,7 @@ static int ucsi_psy_get_current_max(struct ucsi_connector *con,
static int ucsi_psy_get_current_now(struct ucsi_connector *con,
union power_supply_propval *val)
{
- u16 flags = con->status.flags;
-
- if (UCSI_CONSTAT_PWR_OPMODE(flags) == UCSI_CONSTAT_PWR_OPMODE_PD)
+ if (UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD)
val->intval = rdo_op_current(con->rdo) * 1000;
else
val->intval = 0;
@@ -185,11 +183,9 @@ static int ucsi_psy_get_current_now(struct ucsi_connector *con,
static int ucsi_psy_get_usb_type(struct ucsi_connector *con,
union power_supply_propval *val)
{
- u16 flags = con->status.flags;
-
val->intval = POWER_SUPPLY_USB_TYPE_C;
- if (flags & UCSI_CONSTAT_CONNECTED &&
- UCSI_CONSTAT_PWR_OPMODE(flags) == UCSI_CONSTAT_PWR_OPMODE_PD)
+ if (UCSI_CONSTAT(con, CONNECTED) &&
+ UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD)
val->intval = POWER_SUPPLY_USB_TYPE_PD;
return 0;
@@ -197,18 +193,18 @@ static int ucsi_psy_get_usb_type(struct ucsi_connector *con,
static int ucsi_psy_get_charge_type(struct ucsi_connector *con, union power_supply_propval *val)
{
- if (!(con->status.flags & UCSI_CONSTAT_CONNECTED)) {
+ if (!(UCSI_CONSTAT(con, CONNECTED))) {
val->intval = POWER_SUPPLY_CHARGE_TYPE_NONE;
return 0;
}
/* The Battery Charging Cabability Status field is only valid in sink role. */
- if ((con->status.flags & UCSI_CONSTAT_PWR_DIR) != TYPEC_SINK) {
+ if (UCSI_CONSTAT(con, PWR_DIR) != TYPEC_SINK) {
val->intval = POWER_SUPPLY_CHARGE_TYPE_UNKNOWN;
return 0;
}
- switch (UCSI_CONSTAT_BC_STATUS(con->status.pwr_status)) {
+ switch (UCSI_CONSTAT(con, BC_STATUS)) {
case UCSI_CONSTAT_BC_NOMINAL_CHARGING:
val->intval = POWER_SUPPLY_CHARGE_TYPE_STANDARD;
break;
diff --git a/drivers/usb/typec/ucsi/trace.h b/drivers/usb/typec/ucsi/trace.h
index a0d3a934d3d9..41701dee7056 100644
--- a/drivers/usb/typec/ucsi/trace.h
+++ b/drivers/usb/typec/ucsi/trace.h
@@ -40,8 +40,8 @@ DEFINE_EVENT(ucsi_log_command, ucsi_reset_ppm,
);
DECLARE_EVENT_CLASS(ucsi_log_connector_status,
- TP_PROTO(int port, struct ucsi_connector_status *status),
- TP_ARGS(port, status),
+ TP_PROTO(int port, struct ucsi_connector *con),
+ TP_ARGS(port, con),
TP_STRUCT__entry(
__field(int, port)
__field(u16, change)
@@ -55,14 +55,14 @@ DECLARE_EVENT_CLASS(ucsi_log_connector_status,
),
TP_fast_assign(
__entry->port = port - 1;
- __entry->change = status->change;
- __entry->opmode = UCSI_CONSTAT_PWR_OPMODE(status->flags);
- __entry->connected = !!(status->flags & UCSI_CONSTAT_CONNECTED);
- __entry->pwr_dir = !!(status->flags & UCSI_CONSTAT_PWR_DIR);
- __entry->partner_flags = UCSI_CONSTAT_PARTNER_FLAGS(status->flags);
- __entry->partner_type = UCSI_CONSTAT_PARTNER_TYPE(status->flags);
- __entry->request_data_obj = status->request_data_obj;
- __entry->bc_status = UCSI_CONSTAT_BC_STATUS(status->pwr_status);
+ __entry->change = UCSI_CONSTAT(con, CHANGE);
+ __entry->opmode = UCSI_CONSTAT(con, PWR_OPMODE);
+ __entry->connected = UCSI_CONSTAT(con, CONNECTED);
+ __entry->pwr_dir = UCSI_CONSTAT(con, PWR_DIR);
+ __entry->partner_flags = UCSI_CONSTAT(con, PARTNER_FLAGS);
+ __entry->partner_type = UCSI_CONSTAT(con, PARTNER_TYPE);
+ __entry->request_data_obj = UCSI_CONSTAT(con, RDO);
+ __entry->bc_status = UCSI_CONSTAT(con, BC_STATUS);
),
TP_printk("port%d status: change=%04x, opmode=%x, connected=%d, "
"sourcing=%d, partner_flags=%x, partner_type=%x, "
@@ -73,13 +73,13 @@ DECLARE_EVENT_CLASS(ucsi_log_connector_status,
);
DEFINE_EVENT(ucsi_log_connector_status, ucsi_connector_change,
- TP_PROTO(int port, struct ucsi_connector_status *status),
- TP_ARGS(port, status)
+ TP_PROTO(int port, struct ucsi_connector *con),
+ TP_ARGS(port, con)
);
DEFINE_EVENT(ucsi_log_connector_status, ucsi_register_port,
- TP_PROTO(int port, struct ucsi_connector_status *status),
- TP_ARGS(port, status)
+ TP_PROTO(int port, struct ucsi_connector *con),
+ TP_ARGS(port, con)
);
DECLARE_EVENT_CLASS(ucsi_log_register_altmode,
diff --git a/drivers/usb/typec/ucsi/ucsi.c b/drivers/usb/typec/ucsi/ucsi.c
index e0f3925e401b..fcf499cc9458 100644
--- a/drivers/usb/typec/ucsi/ucsi.c
+++ b/drivers/usb/typec/ucsi/ucsi.c
@@ -46,11 +46,11 @@ void ucsi_notify_common(struct ucsi *ucsi, u32 cci)
ucsi_connector_change(ucsi, UCSI_CCI_CONNECTOR(cci));
if (cci & UCSI_CCI_ACK_COMPLETE &&
- test_bit(ACK_PENDING, &ucsi->flags))
+ test_and_clear_bit(ACK_PENDING, &ucsi->flags))
complete(&ucsi->complete);
if (cci & UCSI_CCI_COMMAND_COMPLETE &&
- test_bit(COMMAND_PENDING, &ucsi->flags))
+ test_and_clear_bit(COMMAND_PENDING, &ucsi->flags))
complete(&ucsi->complete);
}
EXPORT_SYMBOL_GPL(ucsi_notify_common);
@@ -65,6 +65,8 @@ int ucsi_sync_control_common(struct ucsi *ucsi, u64 command)
else
set_bit(COMMAND_PENDING, &ucsi->flags);
+ reinit_completion(&ucsi->complete);
+
ret = ucsi->ops->async_control(ucsi, command);
if (ret)
goto out_clear_bit;
@@ -648,6 +650,18 @@ static void ucsi_unregister_altmodes(struct ucsi_connector *con, u8 recipient)
}
}
+static int ucsi_get_connector_status(struct ucsi_connector *con, bool conn_ack)
+{
+ u64 command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
+ size_t size = min(sizeof(con->status),
+ UCSI_MAX_DATA_LENGTH(con->ucsi));
+ int ret;
+
+ ret = ucsi_send_command_common(con->ucsi, command, &con->status, size, conn_ack);
+
+ return ret < 0 ? ret : 0;
+}
+
static int ucsi_read_pdos(struct ucsi_connector *con,
enum typec_role role, int is_partner,
u32 *pdos, int offset, int num_pdos)
@@ -658,8 +672,7 @@ static int ucsi_read_pdos(struct ucsi_connector *con,
if (is_partner &&
ucsi->quirks & UCSI_NO_PARTNER_PDOS &&
- ((con->status.flags & UCSI_CONSTAT_PWR_DIR) ||
- !is_source(role)))
+ (UCSI_CONSTAT(con, PWR_DIR) || !is_source(role)))
return 0;
command = UCSI_COMMAND(UCSI_GET_PDOS) | UCSI_CONNECTOR_NUMBER(con->num);
@@ -973,6 +986,7 @@ static void ucsi_unregister_cable(struct ucsi_connector *con)
static int ucsi_check_connector_capability(struct ucsi_connector *con)
{
+ u64 pd_revision;
u64 command;
int ret;
@@ -986,17 +1000,17 @@ static int ucsi_check_connector_capability(struct ucsi_connector *con)
return ret;
}
- typec_partner_set_pd_revision(con->partner,
- UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(con->cap.flags));
+ pd_revision = UCSI_CONCAP(con, PARTNER_PD_REVISION_V2_1);
+ typec_partner_set_pd_revision(con->partner, UCSI_SPEC_REVISION_TO_BCD(pd_revision));
return ret;
}
static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
{
- switch (UCSI_CONSTAT_PWR_OPMODE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PWR_OPMODE)) {
case UCSI_CONSTAT_PWR_OPMODE_PD:
- con->rdo = con->status.request_data_obj;
+ con->rdo = UCSI_CONSTAT(con, RDO);
typec_set_pwr_opmode(con->port, TYPEC_PWR_MODE_PD);
ucsi_partner_task(con, ucsi_get_src_pdos, 30, 0);
ucsi_partner_task(con, ucsi_check_altmodes, 30, HZ);
@@ -1020,7 +1034,7 @@ static void ucsi_pwr_opmode_change(struct ucsi_connector *con)
static int ucsi_register_partner(struct ucsi_connector *con)
{
- u8 pwr_opmode = UCSI_CONSTAT_PWR_OPMODE(con->status.flags);
+ u8 pwr_opmode = UCSI_CONSTAT(con, PWR_OPMODE);
struct typec_partner_desc desc;
struct typec_partner *partner;
@@ -1029,7 +1043,7 @@ static int ucsi_register_partner(struct ucsi_connector *con)
memset(&desc, 0, sizeof(desc));
- switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
desc.accessory = TYPEC_ACCESSORY_DEBUG;
break;
@@ -1047,6 +1061,11 @@ static int ucsi_register_partner(struct ucsi_connector *con)
desc.identity = &con->partner_identity;
desc.usb_pd = pwr_opmode == UCSI_CONSTAT_PWR_OPMODE_PD;
+ if (con->ucsi->version >= UCSI_VERSION_2_1) {
+ u64 pd_revision = UCSI_CONCAP(con, PARTNER_PD_REVISION_V2_1);
+ desc.pd_revision = UCSI_SPEC_REVISION_TO_BCD(pd_revision);
+ }
+
partner = typec_register_partner(con->port, &desc);
if (IS_ERR(partner)) {
dev_err(con->ucsi->dev,
@@ -1057,6 +1076,13 @@ static int ucsi_register_partner(struct ucsi_connector *con)
con->partner = partner;
+ if (con->ucsi->version >= UCSI_VERSION_3_0 &&
+ UCSI_CONSTAT(con, PARTNER_FLAG_USB4_GEN4))
+ typec_partner_set_usb_mode(partner, USB_MODE_USB4);
+ else if (con->ucsi->version >= UCSI_VERSION_2_0 &&
+ UCSI_CONSTAT(con, PARTNER_FLAG_USB4_GEN3))
+ typec_partner_set_usb_mode(partner, USB_MODE_USB4);
+
return 0;
}
@@ -1081,7 +1107,7 @@ static void ucsi_partner_change(struct ucsi_connector *con)
enum usb_role u_role = USB_ROLE_NONE;
int ret;
- switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
case UCSI_CONSTAT_PARTNER_TYPE_UFP:
case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
u_role = USB_ROLE_HOST;
@@ -1097,8 +1123,8 @@ static void ucsi_partner_change(struct ucsi_connector *con)
break;
}
- if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
- switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
+ if (UCSI_CONSTAT(con, CONNECTED)) {
+ switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
case UCSI_CONSTAT_PARTNER_TYPE_DEBUG:
typec_set_mode(con->port, TYPEC_MODE_DEBUG);
break;
@@ -1106,14 +1132,13 @@ static void ucsi_partner_change(struct ucsi_connector *con)
typec_set_mode(con->port, TYPEC_MODE_AUDIO);
break;
default:
- if (UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) ==
- UCSI_CONSTAT_PARTNER_FLAG_USB)
+ if (UCSI_CONSTAT(con, PARTNER_FLAG_USB))
typec_set_mode(con->port, TYPEC_STATE_USB);
}
}
/* Only notify USB controller if partner supports USB data */
- if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB))
+ if (!(UCSI_CONSTAT(con, PARTNER_FLAG_USB)))
u_role = USB_ROLE_NONE;
ret = usb_role_switch_set_role(con->usb_role_sw, u_role);
@@ -1124,21 +1149,18 @@ static void ucsi_partner_change(struct ucsi_connector *con)
static int ucsi_check_connection(struct ucsi_connector *con)
{
- u8 prev_flags = con->status.flags;
- u64 command;
+ u8 prev_state = UCSI_CONSTAT(con, CONNECTED);
int ret;
- command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
- ret = ucsi_send_command(con->ucsi, command, &con->status, sizeof(con->status));
- if (ret < 0) {
+ ret = ucsi_get_connector_status(con, false);
+ if (ret) {
dev_err(con->ucsi->dev, "GET_CONNECTOR_STATUS failed (%d)\n", ret);
return ret;
}
- if (con->status.flags == prev_flags)
- return 0;
-
- if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
+ if (UCSI_CONSTAT(con, CONNECTED)) {
+ if (prev_state)
+ return 0;
ucsi_register_partner(con);
ucsi_pwr_opmode_change(con);
ucsi_partner_change(con);
@@ -1194,7 +1216,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
work);
struct ucsi *ucsi = con->ucsi;
enum typec_role role;
- u64 command;
+ u16 change;
int ret;
mutex_lock(&con->lock);
@@ -1203,25 +1225,23 @@ static void ucsi_handle_connector_change(struct work_struct *work)
dev_err_once(ucsi->dev, "%s entered without EVENT_PENDING\n",
__func__);
- command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
-
- ret = ucsi_send_command_common(ucsi, command, &con->status,
- sizeof(con->status), true);
- if (ret < 0) {
+ ret = ucsi_get_connector_status(con, true);
+ if (ret) {
dev_err(ucsi->dev, "%s: GET_CONNECTOR_STATUS failed (%d)\n",
__func__, ret);
clear_bit(EVENT_PENDING, &con->ucsi->flags);
goto out_unlock;
}
- trace_ucsi_connector_change(con->num, &con->status);
+ trace_ucsi_connector_change(con->num, con);
if (ucsi->ops->connector_status)
ucsi->ops->connector_status(con);
- role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
+ change = UCSI_CONSTAT(con, CHANGE);
+ role = UCSI_CONSTAT(con, PWR_DIR);
- if (con->status.change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
+ if (change & UCSI_CONSTAT_POWER_DIR_CHANGE) {
typec_set_pwr_role(con->port, role);
/* Complete pending power role swap */
@@ -1229,12 +1249,12 @@ static void ucsi_handle_connector_change(struct work_struct *work)
complete(&con->complete);
}
- if (con->status.change & UCSI_CONSTAT_CONNECT_CHANGE) {
+ if (change & UCSI_CONSTAT_CONNECT_CHANGE) {
typec_set_pwr_role(con->port, role);
ucsi_port_psy_changed(con);
ucsi_partner_change(con);
- if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
+ if (UCSI_CONSTAT(con, CONNECTED)) {
ucsi_register_partner(con);
ucsi_partner_task(con, ucsi_check_connection, 1, HZ);
if (con->ucsi->cap.features & UCSI_CAP_GET_PD_MESSAGE)
@@ -1242,8 +1262,7 @@ static void ucsi_handle_connector_change(struct work_struct *work)
if (con->ucsi->cap.features & UCSI_CAP_CABLE_DETAILS)
ucsi_partner_task(con, ucsi_check_cable, 1, HZ);
- if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
- UCSI_CONSTAT_PWR_OPMODE_PD) {
+ if (UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD) {
ucsi_partner_task(con, ucsi_register_partner_pdos, 1, HZ);
ucsi_partner_task(con, ucsi_check_connector_capability, 1, HZ);
}
@@ -1252,11 +1271,10 @@ static void ucsi_handle_connector_change(struct work_struct *work)
}
}
- if (con->status.change & UCSI_CONSTAT_POWER_OPMODE_CHANGE ||
- con->status.change & UCSI_CONSTAT_POWER_LEVEL_CHANGE)
+ if (change & (UCSI_CONSTAT_POWER_OPMODE_CHANGE | UCSI_CONSTAT_POWER_LEVEL_CHANGE))
ucsi_pwr_opmode_change(con);
- if (con->partner && con->status.change & UCSI_CONSTAT_PARTNER_CHANGE) {
+ if (con->partner && (change & UCSI_CONSTAT_PARTNER_CHANGE)) {
ucsi_partner_change(con);
/* Complete pending data role swap */
@@ -1264,10 +1282,10 @@ static void ucsi_handle_connector_change(struct work_struct *work)
complete(&con->complete);
}
- if (con->status.change & UCSI_CONSTAT_CAM_CHANGE)
+ if (change & UCSI_CONSTAT_CAM_CHANGE)
ucsi_partner_task(con, ucsi_check_altmodes, 1, HZ);
- if (con->status.change & UCSI_CONSTAT_BC_CHANGE)
+ if (change & UCSI_CONSTAT_BC_CHANGE)
ucsi_port_psy_changed(con);
out_unlock:
@@ -1427,7 +1445,7 @@ static int ucsi_dr_swap(struct typec_port *port, enum typec_data_role role)
goto out_unlock;
}
- partner_type = UCSI_CONSTAT_PARTNER_TYPE(con->status.flags);
+ partner_type = UCSI_CONSTAT(con, PARTNER_TYPE);
if ((partner_type == UCSI_CONSTAT_PARTNER_TYPE_DFP &&
role == TYPEC_DEVICE) ||
(partner_type == UCSI_CONSTAT_PARTNER_TYPE_UFP &&
@@ -1471,7 +1489,7 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
goto out_unlock;
}
- cur_role = !!(con->status.flags & UCSI_CONSTAT_PWR_DIR);
+ cur_role = UCSI_CONSTAT(con, PWR_DIR);
if (cur_role == role)
goto out_unlock;
@@ -1494,8 +1512,7 @@ static int ucsi_pr_swap(struct typec_port *port, enum typec_role role)
mutex_lock(&con->lock);
/* Something has gone wrong while swapping the role */
- if (UCSI_CONSTAT_PWR_OPMODE(con->status.flags) !=
- UCSI_CONSTAT_PWR_OPMODE_PD) {
+ if (UCSI_CONSTAT(con, PWR_OPMODE) != UCSI_CONSTAT_PWR_OPMODE_PD) {
ucsi_reset_connector(con, true);
ret = -EPROTO;
}
@@ -1563,19 +1580,18 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
if (ret < 0)
goto out_unlock;
- if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DRP)
+ if (UCSI_CONCAP(con, OPMODE_DRP))
cap->data = TYPEC_PORT_DRD;
- else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DFP)
+ else if (UCSI_CONCAP(con, OPMODE_DFP))
cap->data = TYPEC_PORT_DFP;
- else if (con->cap.op_mode & UCSI_CONCAP_OPMODE_UFP)
+ else if (UCSI_CONCAP(con, OPMODE_UFP))
cap->data = TYPEC_PORT_UFP;
- if ((con->cap.flags & UCSI_CONCAP_FLAG_PROVIDER) &&
- (con->cap.flags & UCSI_CONCAP_FLAG_CONSUMER))
+ if (UCSI_CONCAP(con, PROVIDER) && UCSI_CONCAP(con, CONSUMER))
cap->type = TYPEC_PORT_DRP;
- else if (con->cap.flags & UCSI_CONCAP_FLAG_PROVIDER)
+ else if (UCSI_CONCAP(con, PROVIDER))
cap->type = TYPEC_PORT_SRC;
- else if (con->cap.flags & UCSI_CONCAP_FLAG_CONSUMER)
+ else if (UCSI_CONCAP(con, CONSUMER))
cap->type = TYPEC_PORT_SNK;
cap->revision = ucsi->cap.typec_version;
@@ -1583,11 +1599,18 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
cap->svdm_version = SVDM_VER_2_0;
cap->prefer_role = TYPEC_NO_PREFERRED_ROLE;
- if (con->cap.op_mode & UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY)
+ if (UCSI_CONCAP(con, OPMODE_AUDIO_ACCESSORY))
*accessory++ = TYPEC_ACCESSORY_AUDIO;
- if (con->cap.op_mode & UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY)
+ if (UCSI_CONCAP(con, OPMODE_DEBUG_ACCESSORY))
*accessory = TYPEC_ACCESSORY_DEBUG;
+ if (UCSI_CONCAP_USB2_SUPPORT(con))
+ cap->usb_capability |= USB_CAPABILITY_USB2;
+ if (UCSI_CONCAP_USB3_SUPPORT(con))
+ cap->usb_capability |= USB_CAPABILITY_USB3;
+ if (UCSI_CONCAP_USB4_SUPPORT(con))
+ cap->usb_capability |= USB_CAPABILITY_USB4;
+
cap->driver_data = con;
cap->ops = &ucsi_ops;
@@ -1617,19 +1640,16 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
}
/* Get the status */
- command = UCSI_GET_CONNECTOR_STATUS | UCSI_CONNECTOR_NUMBER(con->num);
- ret = ucsi_send_command(ucsi, command, &con->status, sizeof(con->status));
- if (ret < 0) {
+ ret = ucsi_get_connector_status(con, false);
+ if (ret) {
dev_err(ucsi->dev, "con%d: failed to get status\n", con->num);
- ret = 0;
goto out;
}
- ret = 0; /* ucsi_send_command() returns length on success */
if (ucsi->ops->connector_status)
ucsi->ops->connector_status(con);
- switch (UCSI_CONSTAT_PARTNER_TYPE(con->status.flags)) {
+ switch (UCSI_CONSTAT(con, PARTNER_TYPE)) {
case UCSI_CONSTAT_PARTNER_TYPE_UFP:
case UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP:
u_role = USB_ROLE_HOST;
@@ -1646,9 +1666,8 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
}
/* Check if there is already something connected */
- if (con->status.flags & UCSI_CONSTAT_CONNECTED) {
- typec_set_pwr_role(con->port,
- !!(con->status.flags & UCSI_CONSTAT_PWR_DIR));
+ if (UCSI_CONSTAT(con, CONNECTED)) {
+ typec_set_pwr_role(con->port, UCSI_CONSTAT(con, PWR_DIR));
ucsi_register_partner(con);
ucsi_pwr_opmode_change(con);
ucsi_port_psy_changed(con);
@@ -1659,7 +1678,7 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
}
/* Only notify USB controller if partner supports USB data */
- if (!(UCSI_CONSTAT_PARTNER_FLAGS(con->status.flags) & UCSI_CONSTAT_PARTNER_FLAG_USB))
+ if (!(UCSI_CONSTAT(con, PARTNER_FLAG_USB)))
u_role = USB_ROLE_NONE;
ret = usb_role_switch_set_role(con->usb_role_sw, u_role);
@@ -1669,16 +1688,14 @@ static int ucsi_register_port(struct ucsi *ucsi, struct ucsi_connector *con)
ret = 0;
}
- if (con->partner &&
- UCSI_CONSTAT_PWR_OPMODE(con->status.flags) ==
- UCSI_CONSTAT_PWR_OPMODE_PD) {
+ if (con->partner && UCSI_CONSTAT(con, PWR_OPMODE) == UCSI_CONSTAT_PWR_OPMODE_PD) {
ucsi_register_device_pdos(con);
ucsi_get_src_pdos(con);
ucsi_check_altmodes(con);
ucsi_check_connector_capability(con);
}
- trace_ucsi_register_port(con->num, &con->status);
+ trace_ucsi_register_port(con->num, con);
out:
fwnode_handle_put(cap->fwnode);
@@ -1761,7 +1778,8 @@ static int ucsi_init(struct ucsi *ucsi)
/* Get PPM capabilities */
command = UCSI_GET_CAPABILITY;
- ret = ucsi_send_command(ucsi, command, &ucsi->cap, sizeof(ucsi->cap));
+ ret = ucsi_send_command(ucsi, command, &ucsi->cap,
+ BITS_TO_BYTES(UCSI_GET_CAPABILITY_SIZE));
if (ret < 0)
goto err_reset;
diff --git a/drivers/usb/typec/ucsi/ucsi.h b/drivers/usb/typec/ucsi/ucsi.h
index 1cf5aad4c23a..5ff369c24a2f 100644
--- a/drivers/usb/typec/ucsi/ucsi.h
+++ b/drivers/usb/typec/ucsi/ucsi.h
@@ -4,6 +4,7 @@
#define __DRIVER_USB_TYPEC_UCSI_H
#include <linux/bitops.h>
+#include <linux/bitmap.h>
#include <linux/completion.h>
#include <linux/device.h>
#include <linux/power_supply.h>
@@ -95,26 +96,31 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
/* -------------------------------------------------------------------------- */
/* Commands */
-#define UCSI_PPM_RESET 0x01
-#define UCSI_CANCEL 0x02
-#define UCSI_CONNECTOR_RESET 0x03
-#define UCSI_ACK_CC_CI 0x04
-#define UCSI_SET_NOTIFICATION_ENABLE 0x05
-#define UCSI_GET_CAPABILITY 0x06
-#define UCSI_GET_CONNECTOR_CAPABILITY 0x07
-#define UCSI_SET_UOM 0x08
-#define UCSI_SET_UOR 0x09
-#define UCSI_SET_PDM 0x0a
-#define UCSI_SET_PDR 0x0b
-#define UCSI_GET_ALTERNATE_MODES 0x0c
-#define UCSI_GET_CAM_SUPPORTED 0x0d
-#define UCSI_GET_CURRENT_CAM 0x0e
-#define UCSI_SET_NEW_CAM 0x0f
-#define UCSI_GET_PDOS 0x10
-#define UCSI_GET_CABLE_PROPERTY 0x11
-#define UCSI_GET_CONNECTOR_STATUS 0x12
-#define UCSI_GET_ERROR_STATUS 0x13
-#define UCSI_GET_PD_MESSAGE 0x15
+#define UCSI_PPM_RESET 0x01
+#define UCSI_CANCEL 0x02
+#define UCSI_CONNECTOR_RESET 0x03
+#define UCSI_ACK_CC_CI 0x04
+#define UCSI_SET_NOTIFICATION_ENABLE 0x05
+#define UCSI_GET_CAPABILITY 0x06
+#define UCSI_GET_CAPABILITY_SIZE 128
+#define UCSI_GET_CONNECTOR_CAPABILITY 0x07
+#define UCSI_GET_CONNECTOR_CAPABILITY_SIZE 32
+#define UCSI_SET_UOM 0x08
+#define UCSI_SET_UOR 0x09
+#define UCSI_SET_PDM 0x0a
+#define UCSI_SET_PDR 0x0b
+#define UCSI_GET_ALTERNATE_MODES 0x0c
+#define UCSI_GET_CAM_SUPPORTED 0x0d
+#define UCSI_GET_CURRENT_CAM 0x0e
+#define UCSI_SET_NEW_CAM 0x0f
+#define UCSI_GET_PDOS 0x10
+#define UCSI_GET_CABLE_PROPERTY 0x11
+#define UCSI_GET_CABLE_PROPERTY_SIZE 64
+#define UCSI_GET_CONNECTOR_STATUS 0x12
+#define UCSI_GET_CONNECTOR_STATUS_SIZE 152
+#define UCSI_GET_ERROR_STATUS 0x13
+#define UCSI_GET_PD_MESSAGE 0x15
+#define UCSI_SET_SINK_PATH 0x1c
#define UCSI_CONNECTOR_NUMBER(_num_) ((u64)(_num_) << 16)
#define UCSI_COMMAND(_cmd_) ((_cmd_) & 0xff)
@@ -126,7 +132,6 @@ void ucsi_connector_change(struct ucsi *ucsi, u8 num);
#define UCSI_CONNECTOR_RESET_HARD_VER_1_0 BIT(23) /* Deprecated in v1.1 */
#define UCSI_CONNECTOR_RESET_DATA_VER_2_0 BIT(23) /* Redefined in v2.0 */
-
/* ACK_CC_CI bits */
#define UCSI_ACK_CONNECTOR_CHANGE BIT(16)
#define UCSI_ACK_COMMAND_COMPLETE BIT(17)
@@ -250,42 +255,6 @@ struct ucsi_capability {
u16 typec_version;
} __packed;
-/* Data structure filled by PPM in response to GET_CONNECTOR_CAPABILITY cmd. */
-struct ucsi_connector_capability {
- u8 op_mode;
-#define UCSI_CONCAP_OPMODE_DFP BIT(0)
-#define UCSI_CONCAP_OPMODE_UFP BIT(1)
-#define UCSI_CONCAP_OPMODE_DRP BIT(2)
-#define UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY BIT(3)
-#define UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY BIT(4)
-#define UCSI_CONCAP_OPMODE_USB2 BIT(5)
-#define UCSI_CONCAP_OPMODE_USB3 BIT(6)
-#define UCSI_CONCAP_OPMODE_ALT_MODE BIT(7)
- u32 flags;
-#define UCSI_CONCAP_FLAG_PROVIDER BIT(0)
-#define UCSI_CONCAP_FLAG_CONSUMER BIT(1)
-#define UCSI_CONCAP_FLAG_SWAP_TO_DFP BIT(2)
-#define UCSI_CONCAP_FLAG_SWAP_TO_UFP BIT(3)
-#define UCSI_CONCAP_FLAG_SWAP_TO_SRC BIT(4)
-#define UCSI_CONCAP_FLAG_SWAP_TO_SINK BIT(5)
-#define UCSI_CONCAP_FLAG_EX_OP_MODE(_f_) \
- (((_f_) & GENMASK(13, 6)) >> 6)
-#define UCSI_CONCAP_EX_OP_MODE_USB4_GEN2 BIT(0)
-#define UCSI_CONCAP_EX_OP_MODE_EPR_SRC BIT(1)
-#define UCSI_CONCAP_EX_OP_MODE_EPR_SINK BIT(2)
-#define UCSI_CONCAP_EX_OP_MODE_USB4_GEN3 BIT(3)
-#define UCSI_CONCAP_EX_OP_MODE_USB4_GEN4 BIT(4)
-#define UCSI_CONCAP_FLAG_MISC_CAPS(_f_) \
- (((_f_) & GENMASK(17, 14)) >> 14)
-#define UCSI_CONCAP_MISC_CAP_FW_UPDATE BIT(0)
-#define UCSI_CONCAP_MISC_CAP_SECURITY BIT(1)
-#define UCSI_CONCAP_FLAG_REV_CURR_PROT_SUPPORT BIT(18)
-#define UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV(_f_) \
- (((_f_) & GENMASK(20, 19)) >> 19)
-#define UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV_AS_BCD(_f_) \
- UCSI_SPEC_REVISION_TO_BCD(UCSI_CONCAP_FLAG_PARTNER_PD_MAJOR_REV(_f_))
-} __packed;
-
struct ucsi_altmode {
u16 svid;
u32 mid;
@@ -311,49 +280,143 @@ struct ucsi_cable_property {
u8 latency;
} __packed;
-/* Data structure filled by PPM in response to GET_CONNECTOR_STATUS command. */
-struct ucsi_connector_status {
- u16 change;
-#define UCSI_CONSTAT_EXT_SUPPLY_CHANGE BIT(1)
-#define UCSI_CONSTAT_POWER_OPMODE_CHANGE BIT(2)
-#define UCSI_CONSTAT_PDOS_CHANGE BIT(5)
-#define UCSI_CONSTAT_POWER_LEVEL_CHANGE BIT(6)
-#define UCSI_CONSTAT_PD_RESET_COMPLETE BIT(7)
-#define UCSI_CONSTAT_CAM_CHANGE BIT(8)
-#define UCSI_CONSTAT_BC_CHANGE BIT(9)
-#define UCSI_CONSTAT_PARTNER_CHANGE BIT(11)
-#define UCSI_CONSTAT_POWER_DIR_CHANGE BIT(12)
-#define UCSI_CONSTAT_CONNECT_CHANGE BIT(14)
-#define UCSI_CONSTAT_ERROR BIT(15)
- u16 flags;
-#define UCSI_CONSTAT_PWR_OPMODE(_f_) ((_f_) & GENMASK(2, 0))
+/* Get Connector Capability Fields. */
+#define UCSI_CONCAP_OPMODE UCSI_DECLARE_BITFIELD(0, 0, 8)
+#define UCSI_CONCAP_OPMODE_DFP UCSI_DECLARE_BITFIELD(0, 0, 1)
+#define UCSI_CONCAP_OPMODE_UFP UCSI_DECLARE_BITFIELD(0, 1, 1)
+#define UCSI_CONCAP_OPMODE_DRP UCSI_DECLARE_BITFIELD(0, 2, 1)
+#define UCSI_CONCAP_OPMODE_AUDIO_ACCESSORY UCSI_DECLARE_BITFIELD(0, 3, 1)
+#define UCSI_CONCAP_OPMODE_DEBUG_ACCESSORY UCSI_DECLARE_BITFIELD(0, 4, 1)
+#define UCSI_CONCAP_OPMODE_USB2 UCSI_DECLARE_BITFIELD(0, 5, 1)
+#define UCSI_CONCAP_OPMODE_USB3 UCSI_DECLARE_BITFIELD(0, 6, 1)
+#define UCSI_CONCAP_OPMODE_ALT_MODE UCSI_DECLARE_BITFIELD(0, 7, 1)
+#define UCSI_CONCAP_PROVIDER UCSI_DECLARE_BITFIELD(0, 8, 1)
+#define UCSI_CONCAP_CONSUMER UCSI_DECLARE_BITFIELD(0, 9, 1)
+#define UCSI_CONCAP_SWAP_TO_DFP_V1_1 UCSI_DECLARE_BITFIELD_V1_1(10, 1)
+#define UCSI_CONCAP_SWAP_TO_UFP_V1_1 UCSI_DECLARE_BITFIELD_V1_1(11, 1)
+#define UCSI_CONCAP_SWAP_TO_SRC_V1_1 UCSI_DECLARE_BITFIELD_V1_1(12, 1)
+#define UCSI_CONCAP_SWAP_TO_SNK_V1_1 UCSI_DECLARE_BITFIELD_V1_1(13, 1)
+#define UCSI_CONCAP_EXT_OPMODE_V2_0 UCSI_DECLARE_BITFIELD_V2_0(14, 8)
+#define UCSI_CONCAP_EXT_OPMODE_USB4_GEN2_V2_0 UCSI_DECLARE_BITFIELD_V2_0(14, 1)
+#define UCSI_CONCAP_EXT_OPMODE_EPR_SRC_V2_0 UCSI_DECLARE_BITFIELD_V2_0(15, 1)
+#define UCSI_CONCAP_EXT_OPMODE_EPR_SINK_V2_0 UCSI_DECLARE_BITFIELD_V2_0(16, 1)
+#define UCSI_CONCAP_EXT_OPMODE_USB4_GEN3_V2_0 UCSI_DECLARE_BITFIELD_V2_0(17, 1)
+#define UCSI_CONCAP_EXT_OPMODE_USB4_GEN4_V2_0 UCSI_DECLARE_BITFIELD_V2_0(18, 1)
+#define UCSI_CONCAP_MISC_V2_0 UCSI_DECLARE_BITFIELD_V2_0(22, 4)
+#define UCSI_CONCAP_MISC_FW_UPDATE_V2_0 UCSI_DECLARE_BITFIELD_V2_0(22, 1)
+#define UCSI_CONCAP_MISC_SECURITY_V2_0 UCSI_DECLARE_BITFIELD_V2_0(23, 1)
+#define UCSI_CONCAP_REV_CURR_PROT_SUPPORT_V2_0 UCSI_DECLARE_BITFIELD_V2_0(26, 1)
+#define UCSI_CONCAP_PARTNER_PD_REVISION_V2_1 UCSI_DECLARE_BITFIELD_V2_1(27, 2)
+
+/* Helpers for USB capability checks. */
+#define UCSI_CONCAP_USB2_SUPPORT(_con_) UCSI_CONCAP((_con_), OPMODE_USB2)
+#define UCSI_CONCAP_USB3_SUPPORT(_con_) UCSI_CONCAP((_con_), OPMODE_USB3)
+#define UCSI_CONCAP_USB4_SUPPORT(_con_) \
+ ((_con_)->ucsi->version >= UCSI_VERSION_2_0 && \
+ (UCSI_CONCAP((_con_), EXT_OPMODE_USB4_GEN2_V2_0) | \
+ UCSI_CONCAP((_con_), EXT_OPMODE_USB4_GEN3_V2_0) | \
+ UCSI_CONCAP((_con_), EXT_OPMODE_USB4_GEN4_V2_0)))
+
+/* Get Connector Status Fields. */
+#define UCSI_CONSTAT_CHANGE UCSI_DECLARE_BITFIELD(0, 0, 16)
+#define UCSI_CONSTAT_PWR_OPMODE UCSI_DECLARE_BITFIELD(0, 16, 3)
#define UCSI_CONSTAT_PWR_OPMODE_NONE 0
#define UCSI_CONSTAT_PWR_OPMODE_DEFAULT 1
#define UCSI_CONSTAT_PWR_OPMODE_BC 2
#define UCSI_CONSTAT_PWR_OPMODE_PD 3
#define UCSI_CONSTAT_PWR_OPMODE_TYPEC1_5 4
#define UCSI_CONSTAT_PWR_OPMODE_TYPEC3_0 5
-#define UCSI_CONSTAT_CONNECTED BIT(3)
-#define UCSI_CONSTAT_PWR_DIR BIT(4)
-#define UCSI_CONSTAT_PARTNER_FLAGS(_f_) (((_f_) & GENMASK(12, 5)) >> 5)
-#define UCSI_CONSTAT_PARTNER_FLAG_USB 1
-#define UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE 2
-#define UCSI_CONSTAT_PARTNER_TYPE(_f_) (((_f_) & GENMASK(15, 13)) >> 13)
+#define UCSI_CONSTAT_CONNECTED UCSI_DECLARE_BITFIELD(0, 19, 1)
+#define UCSI_CONSTAT_PWR_DIR UCSI_DECLARE_BITFIELD(0, 20, 1)
+#define UCSI_CONSTAT_PARTNER_FLAGS UCSI_DECLARE_BITFIELD(0, 21, 8)
+#define UCSI_CONSTAT_PARTNER_FLAG_USB UCSI_DECLARE_BITFIELD(0, 21, 1)
+#define UCSI_CONSTAT_PARTNER_FLAG_ALT_MODE UCSI_DECLARE_BITFIELD(0, 22, 1)
+#define UCSI_CONSTAT_PARTNER_FLAG_USB4_GEN3 UCSI_DECLARE_BITFIELD(0, 23, 1)
+#define UCSI_CONSTAT_PARTNER_FLAG_USB4_GEN4 UCSI_DECLARE_BITFIELD(0, 24, 1)
+#define UCSI_CONSTAT_PARTNER_TYPE UCSI_DECLARE_BITFIELD(0, 29, 3)
#define UCSI_CONSTAT_PARTNER_TYPE_DFP 1
#define UCSI_CONSTAT_PARTNER_TYPE_UFP 2
-#define UCSI_CONSTAT_PARTNER_TYPE_CABLE 3 /* Powered Cable */
-#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP 4 /* Powered Cable */
+#define UCSI_CONSTAT_PARTNER_TYPE_CABLE 3 /* Powered Cable */
+#define UCSI_CONSTAT_PARTNER_TYPE_CABLE_AND_UFP 4 /* Powered Cable */
#define UCSI_CONSTAT_PARTNER_TYPE_DEBUG 5
#define UCSI_CONSTAT_PARTNER_TYPE_AUDIO 6
- u32 request_data_obj;
-
- u8 pwr_status;
-#define UCSI_CONSTAT_BC_STATUS(_p_) ((_p_) & GENMASK(1, 0))
+#define UCSI_CONSTAT_RDO UCSI_DECLARE_BITFIELD(0, 32, 32)
+#define UCSI_CONSTAT_BC_STATUS UCSI_DECLARE_BITFIELD(0, 64, 2)
#define UCSI_CONSTAT_BC_NOT_CHARGING 0
#define UCSI_CONSTAT_BC_NOMINAL_CHARGING 1
#define UCSI_CONSTAT_BC_SLOW_CHARGING 2
#define UCSI_CONSTAT_BC_TRICKLE_CHARGING 3
-} __packed;
+#define UCSI_CONSTAT_PD_VERSION_V1_2 UCSI_DECLARE_BITFIELD_V1_2(70, 16)
+
+/* Connector Status Change Bits. */
+#define UCSI_CONSTAT_EXT_SUPPLY_CHANGE BIT(1)
+#define UCSI_CONSTAT_POWER_OPMODE_CHANGE BIT(2)
+#define UCSI_CONSTAT_PDOS_CHANGE BIT(5)
+#define UCSI_CONSTAT_POWER_LEVEL_CHANGE BIT(6)
+#define UCSI_CONSTAT_PD_RESET_COMPLETE BIT(7)
+#define UCSI_CONSTAT_CAM_CHANGE BIT(8)
+#define UCSI_CONSTAT_BC_CHANGE BIT(9)
+#define UCSI_CONSTAT_PARTNER_CHANGE BIT(11)
+#define UCSI_CONSTAT_POWER_DIR_CHANGE BIT(12)
+#define UCSI_CONSTAT_CONNECT_CHANGE BIT(14)
+#define UCSI_CONSTAT_ERROR BIT(15)
+
+#define UCSI_DECLARE_BITFIELD_V1_1(_offset_, _size_) \
+ UCSI_DECLARE_BITFIELD(UCSI_VERSION_1_1, (_offset_), (_size_))
+#define UCSI_DECLARE_BITFIELD_V1_2(_offset_, _size_) \
+ UCSI_DECLARE_BITFIELD(UCSI_VERSION_1_2, (_offset_), (_size_))
+#define UCSI_DECLARE_BITFIELD_V2_0(_offset_, _size_) \
+ UCSI_DECLARE_BITFIELD(UCSI_VERSION_2_0, (_offset_), (_size_))
+#define UCSI_DECLARE_BITFIELD_V2_1(_offset_, _size_) \
+ UCSI_DECLARE_BITFIELD(UCSI_VERSION_2_1, (_offset_), (_size_))
+#define UCSI_DECLARE_BITFIELD_V3_0(_offset_, _size_) \
+ UCSI_DECLARE_BITFIELD(UCSI_VERSION_3_0, (_offset_), (_size_))
+
+#define UCSI_DECLARE_BITFIELD(_ver_, _offset_, _size_) \
+(struct ucsi_bitfield) { \
+ .version = _ver_, \
+ .offset = _offset_, \
+ .size = _size_, \
+}
+
+struct ucsi_bitfield {
+ const u16 version;
+ const u8 offset;
+ const u8 size;
+};
+
+/**
+ * ucsi_bitfield_read - Read a field from UCSI command response
+ * @_map_: UCSI command response
+ * @_field_: The field offset in the response data structure
+ * @_ver_: UCSI version where the field was introduced
+ *
+ * Reads the fields in the command responses by first checking that the field is
+ * valid with the UCSI interface version that is used in the system.
+ * @_ver_ is the minimum UCSI version for the @_field_. If the UCSI interface is
+ * older than @_ver_, a warning is generated.
+ *
+ * Caveats:
+ * - Removed fields are not checked - @_ver_ is just the minimum UCSI version.
+ *
+ * Returns the value of @_field_, or 0 when the UCSI interface is older than
+ * @_ver_.
+ */
+#define ucsi_bitfield_read(_map_, _field_, _ver_) \
+({ \
+ struct ucsi_bitfield f = (_field_); \
+ WARN((_ver_) < f.version, \
+ "Access to unsupported field at offset 0x%x (need version %04x)", \
+ f.offset, f.version) ? 0 : \
+ bitmap_read((_map_), f.offset, f.size); \
+})
+
+/* Helpers to access cached command responses. */
+#define UCSI_CONCAP(_con_, _field_) \
+ ucsi_bitfield_read((_con_)->cap, UCSI_CONCAP_##_field_, (_con_)->ucsi->version)
+
+#define UCSI_CONSTAT(_con_, _field_) \
+ ucsi_bitfield_read((_con_)->status, UCSI_CONSTAT_##_field_, (_con_)->ucsi->version)
/* -------------------------------------------------------------------------- */
@@ -433,8 +496,10 @@ struct ucsi_connector {
struct typec_capability typec_cap;
- struct ucsi_connector_status status;
- struct ucsi_connector_capability cap;
+ /* Cached command responses. */
+ DECLARE_BITMAP(cap, UCSI_GET_CONNECTOR_CAPABILITY_SIZE);
+ DECLARE_BITMAP(status, UCSI_GET_CONNECTOR_STATUS_SIZE);
+
struct power_supply *psy;
struct power_supply_desc psy_desc;
u32 rdo;
diff --git a/drivers/usb/typec/ucsi/ucsi_acpi.c b/drivers/usb/typec/ucsi/ucsi_acpi.c
index 7a5dff8d9cc6..5c5515551963 100644
--- a/drivers/usb/typec/ucsi/ucsi_acpi.c
+++ b/drivers/usb/typec/ucsi/ucsi_acpi.c
@@ -61,9 +61,11 @@ static int ucsi_acpi_read_cci(struct ucsi *ucsi, u32 *cci)
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
int ret;
- ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
- if (ret)
- return ret;
+ if (UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) {
+ ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
+ if (ret)
+ return ret;
+ }
memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci));
@@ -73,11 +75,6 @@ static int ucsi_acpi_read_cci(struct ucsi *ucsi, u32 *cci)
static int ucsi_acpi_read_message_in(struct ucsi *ucsi, void *val, size_t val_len)
{
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
- int ret;
-
- ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
- if (ret)
- return ret;
memcpy(val, ua->base + UCSI_MESSAGE_IN, val_len);
@@ -102,48 +99,11 @@ static const struct ucsi_operations ucsi_acpi_ops = {
.async_control = ucsi_acpi_async_control
};
-static int
-ucsi_zenbook_read_cci(struct ucsi *ucsi, u32 *cci)
-{
- struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
- int ret;
-
- if (UCSI_COMMAND(ua->cmd) == UCSI_PPM_RESET) {
- ret = ucsi_acpi_dsm(ua, UCSI_DSM_FUNC_READ);
- if (ret)
- return ret;
- }
-
- memcpy(cci, ua->base + UCSI_CCI, sizeof(*cci));
-
- return 0;
-}
-
-static int
-ucsi_zenbook_read_message_in(struct ucsi *ucsi, void *val, size_t val_len)
-{
- struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
-
- /* UCSI_MESSAGE_IN is never read for PPM_RESET, return stored data */
- memcpy(val, ua->base + UCSI_MESSAGE_IN, val_len);
-
- return 0;
-}
-
-static const struct ucsi_operations ucsi_zenbook_ops = {
- .read_version = ucsi_acpi_read_version,
- .read_cci = ucsi_zenbook_read_cci,
- .read_message_in = ucsi_zenbook_read_message_in,
- .sync_control = ucsi_sync_control_common,
- .async_control = ucsi_acpi_async_control
-};
-
static int ucsi_gram_read_message_in(struct ucsi *ucsi, void *val, size_t val_len)
{
u16 bogus_change = UCSI_CONSTAT_POWER_LEVEL_CHANGE |
UCSI_CONSTAT_PDOS_CHANGE;
struct ucsi_acpi *ua = ucsi_get_drvdata(ucsi);
- struct ucsi_connector_status *status;
int ret;
ret = ucsi_acpi_read_message_in(ucsi, val, val_len);
@@ -152,11 +112,9 @@ static int ucsi_gram_read_message_in(struct ucsi *ucsi, void *val, size_t val_le
if (UCSI_COMMAND(ua->cmd) == UCSI_GET_CONNECTOR_STATUS &&
ua->check_bogus_event) {
- status = (struct ucsi_connector_status *)val;
-
/* Clear the bogus change */
- if (status->change == bogus_change)
- status->change = 0;
+ if (*(u16 *)val == bogus_change)
+ *(u16 *)val = 0;
ua->check_bogus_event = false;
}
@@ -192,13 +150,6 @@ static const struct ucsi_operations ucsi_gram_ops = {
static const struct dmi_system_id ucsi_acpi_quirks[] = {
{
.matches = {
- DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."),
- DMI_MATCH(DMI_PRODUCT_NAME, "ZenBook UX325UA_UM325UA"),
- },
- .driver_data = (void *)&ucsi_zenbook_ops,
- },
- {
- .matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"),
DMI_MATCH(DMI_PRODUCT_FAMILY, "LG gram PC"),
DMI_MATCH(DMI_PRODUCT_NAME, "90Q"),
@@ -320,7 +271,7 @@ static struct platform_driver ucsi_acpi_platform_driver = {
.acpi_match_table = ACPI_PTR(ucsi_acpi_match),
},
.probe = ucsi_acpi_probe,
- .remove_new = ucsi_acpi_remove,
+ .remove = ucsi_acpi_remove,
};
module_platform_driver(ucsi_acpi_platform_driver);
diff --git a/drivers/usb/typec/ucsi/ucsi_ccg.c b/drivers/usb/typec/ucsi/ucsi_ccg.c
index bccfc03b5986..fcb8e61136cf 100644
--- a/drivers/usb/typec/ucsi/ucsi_ccg.c
+++ b/drivers/usb/typec/ucsi/ucsi_ccg.c
@@ -644,6 +644,10 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command)
uc->has_multiple_dp) {
con_index = (uc->last_cmd_sent >> 16) &
UCSI_CMD_CONNECTOR_MASK;
+ if (con_index == 0) {
+ ret = -EINVAL;
+ goto unlock;
+ }
con = &uc->ucsi->connector[con_index - 1];
ucsi_ccg_update_set_new_cam_cmd(uc, con, &command);
}
@@ -651,6 +655,7 @@ static int ucsi_ccg_sync_control(struct ucsi *ucsi, u64 command)
ret = ucsi_sync_control_common(ucsi, command);
pm_runtime_put_sync(uc->dev);
+unlock:
mutex_unlock(&uc->lock);
return ret;
diff --git a/drivers/usb/typec/ucsi/ucsi_glink.c b/drivers/usb/typec/ucsi/ucsi_glink.c
index 03c0fa8edc8d..90948cd6d297 100644
--- a/drivers/usb/typec/ucsi/ucsi_glink.c
+++ b/drivers/usb/typec/ucsi/ucsi_glink.c
@@ -172,12 +172,12 @@ static int pmic_glink_ucsi_async_control(struct ucsi *__ucsi, u64 command)
static void pmic_glink_ucsi_update_connector(struct ucsi_connector *con)
{
struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi);
- int i;
- for (i = 0; i < PMIC_GLINK_MAX_PORTS; i++) {
- if (ucsi->port_orientation[i])
- con->typec_cap.orientation_aware = true;
- }
+ if (con->num > PMIC_GLINK_MAX_PORTS ||
+ !ucsi->port_orientation[con->num - 1])
+ return;
+
+ con->typec_cap.orientation_aware = true;
}
static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con)
@@ -185,7 +185,7 @@ static void pmic_glink_ucsi_connector_status(struct ucsi_connector *con)
struct pmic_glink_ucsi *ucsi = ucsi_get_drvdata(con->ucsi);
int orientation;
- if (con->num >= PMIC_GLINK_MAX_PORTS ||
+ if (con->num > PMIC_GLINK_MAX_PORTS ||
!ucsi->port_orientation[con->num - 1])
return;
@@ -322,7 +322,6 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
struct pmic_glink_ucsi *ucsi;
struct device *dev = &adev->dev;
const struct of_device_id *match;
- struct fwnode_handle *fwnode;
int ret;
ucsi = devm_kzalloc(dev, sizeof(*ucsi), GFP_KERNEL);
@@ -354,14 +353,13 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
ucsi_set_drvdata(ucsi->ucsi, ucsi);
- device_for_each_child_node(dev, fwnode) {
+ device_for_each_child_node_scoped(dev, fwnode) {
struct gpio_desc *desc;
u32 port;
ret = fwnode_property_read_u32(fwnode, "reg", &port);
if (ret < 0) {
dev_err(dev, "missing reg property of %pOFn\n", fwnode);
- fwnode_handle_put(fwnode);
return ret;
}
@@ -376,11 +374,10 @@ static int pmic_glink_ucsi_probe(struct auxiliary_device *adev,
if (!desc)
continue;
- if (IS_ERR(desc)) {
- fwnode_handle_put(fwnode);
+ if (IS_ERR(desc))
return dev_err_probe(dev, PTR_ERR(desc),
"unable to acquire orientation gpio\n");
- }
+
ucsi->port_orientation[port] = desc;
}
diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c
index 8dac1edc74d4..b03e5021c25b 100644
--- a/drivers/usb/usbip/vhci_hcd.c
+++ b/drivers/usb/usbip/vhci_hcd.c
@@ -1487,7 +1487,7 @@ static int vhci_hcd_resume(struct platform_device *pdev)
static struct platform_driver vhci_driver = {
.probe = vhci_hcd_probe,
- .remove_new = vhci_hcd_remove,
+ .remove = vhci_hcd_remove,
.suspend = vhci_hcd_suspend,
.resume = vhci_hcd_resume,
.driver = {
diff --git a/drivers/usb/usbip/vudc_main.c b/drivers/usb/usbip/vudc_main.c
index 8bee553e4894..993e721cb840 100644
--- a/drivers/usb/usbip/vudc_main.c
+++ b/drivers/usb/usbip/vudc_main.c
@@ -19,7 +19,7 @@ MODULE_PARM_DESC(num, "number of emulated controllers");
static struct platform_driver vudc_driver = {
.probe = vudc_probe,
- .remove_new = vudc_remove,
+ .remove = vudc_remove,
.driver = {
.name = GADGET_NAME,
.dev_groups = vudc_groups,
diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c
index 5f581e71e201..36099047560d 100644
--- a/drivers/vdpa/mlx5/net/mlx5_vnet.c
+++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c
@@ -1952,7 +1952,7 @@ static int mlx5_vdpa_add_mac_vlan_rules(struct mlx5_vdpa_net *ndev, u8 *mac,
goto out_free;
#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
- dests[1].counter_id = mlx5_fc_id(node->ucast_counter.counter);
+ dests[1].counter = node->ucast_counter.counter;
#endif
node->ucast_rule = mlx5_add_flow_rules(ndev->rxft, spec, &flow_act, dests, NUM_DESTS);
if (IS_ERR(node->ucast_rule)) {
@@ -1961,7 +1961,7 @@ static int mlx5_vdpa_add_mac_vlan_rules(struct mlx5_vdpa_net *ndev, u8 *mac,
}
#if defined(CONFIG_MLX5_VDPA_STEERING_DEBUG)
- dests[1].counter_id = mlx5_fc_id(node->mcast_counter.counter);
+ dests[1].counter = node->mcast_counter.counter;
#endif
memset(dmac_c, 0, ETH_ALEN);
diff --git a/drivers/vfio/cdx/main.c b/drivers/vfio/cdx/main.c
index 67465fad5b4b..5dd5f5ad7686 100644
--- a/drivers/vfio/cdx/main.c
+++ b/drivers/vfio/cdx/main.c
@@ -347,4 +347,4 @@ module_driver(vfio_cdx_driver, cdx_driver_register, cdx_driver_unregister);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("VFIO for CDX devices - User Level meta-driver");
-MODULE_IMPORT_NS(CDX_BUS);
+MODULE_IMPORT_NS("CDX_BUS");
diff --git a/drivers/vfio/iommufd.c b/drivers/vfio/iommufd.c
index 82eba6966fa5..516294fd901b 100644
--- a/drivers/vfio/iommufd.c
+++ b/drivers/vfio/iommufd.c
@@ -7,8 +7,8 @@
#include "vfio.h"
-MODULE_IMPORT_NS(IOMMUFD);
-MODULE_IMPORT_NS(IOMMUFD_VFIO);
+MODULE_IMPORT_NS("IOMMUFD");
+MODULE_IMPORT_NS("IOMMUFD_VFIO");
bool vfio_iommufd_device_has_compat_ioas(struct vfio_device *vdev,
struct iommufd_ctx *ictx)
diff --git a/drivers/vfio/pci/mlx5/cmd.c b/drivers/vfio/pci/mlx5/cmd.c
index 7527e277c898..eb7387ee6ebd 100644
--- a/drivers/vfio/pci/mlx5/cmd.c
+++ b/drivers/vfio/pci/mlx5/cmd.c
@@ -1517,7 +1517,8 @@ int mlx5vf_start_page_tracker(struct vfio_device *vdev,
struct mlx5_vhca_qp *host_qp;
struct mlx5_vhca_qp *fw_qp;
struct mlx5_core_dev *mdev;
- u32 max_msg_size = PAGE_SIZE;
+ u32 log_max_msg_size;
+ u32 max_msg_size;
u64 rq_size = SZ_2M;
u32 max_recv_wr;
int err;
@@ -1534,6 +1535,12 @@ int mlx5vf_start_page_tracker(struct vfio_device *vdev,
}
mdev = mvdev->mdev;
+ log_max_msg_size = MLX5_CAP_ADV_VIRTUALIZATION(mdev, pg_track_log_max_msg_size);
+ max_msg_size = (1ULL << log_max_msg_size);
+ /* The RQ must hold at least 4 WQEs/messages for successful QP creation */
+ if (rq_size < 4 * max_msg_size)
+ rq_size = 4 * max_msg_size;
+
memset(tracker, 0, sizeof(*tracker));
tracker->uar = mlx5_get_uars_page(mdev);
if (IS_ERR(tracker->uar)) {
@@ -1623,25 +1630,41 @@ set_report_output(u32 size, int index, struct mlx5_vhca_qp *qp,
{
u32 entry_size = MLX5_ST_SZ_BYTES(page_track_report_entry);
u32 nent = size / entry_size;
+ u32 nent_in_page;
+ u32 nent_to_set;
struct page *page;
+ u32 page_offset;
+ u32 page_index;
+ u32 buf_offset;
+ void *kaddr;
u64 addr;
u64 *buf;
int i;
- if (WARN_ON(index >= qp->recv_buf.npages ||
+ buf_offset = index * qp->max_msg_size;
+ if (WARN_ON(buf_offset + size >= qp->recv_buf.npages * PAGE_SIZE ||
(nent > qp->max_msg_size / entry_size)))
return;
- page = qp->recv_buf.page_list[index];
- buf = kmap_local_page(page);
- for (i = 0; i < nent; i++) {
- addr = MLX5_GET(page_track_report_entry, buf + i,
- dirty_address_low);
- addr |= (u64)MLX5_GET(page_track_report_entry, buf + i,
- dirty_address_high) << 32;
- iova_bitmap_set(dirty, addr, qp->tracked_page_size);
- }
- kunmap_local(buf);
+ do {
+ page_index = buf_offset / PAGE_SIZE;
+ page_offset = buf_offset % PAGE_SIZE;
+ nent_in_page = (PAGE_SIZE - page_offset) / entry_size;
+ page = qp->recv_buf.page_list[page_index];
+ kaddr = kmap_local_page(page);
+ buf = kaddr + page_offset;
+ nent_to_set = min(nent, nent_in_page);
+ for (i = 0; i < nent_to_set; i++) {
+ addr = MLX5_GET(page_track_report_entry, buf + i,
+ dirty_address_low);
+ addr |= (u64)MLX5_GET(page_track_report_entry, buf + i,
+ dirty_address_high) << 32;
+ iova_bitmap_set(dirty, addr, qp->tracked_page_size);
+ }
+ kunmap_local(kaddr);
+ buf_offset += (nent_to_set * entry_size);
+ nent -= nent_to_set;
+ } while (nent);
}
static void
diff --git a/drivers/vfio/pci/mlx5/main.c b/drivers/vfio/pci/mlx5/main.c
index 8833e60d42f5..709543e7eb04 100644
--- a/drivers/vfio/pci/mlx5/main.c
+++ b/drivers/vfio/pci/mlx5/main.c
@@ -1446,7 +1446,7 @@ static struct pci_driver mlx5vf_pci_driver = {
module_pci_driver(mlx5vf_pci_driver);
-MODULE_IMPORT_NS(IOMMUFD);
+MODULE_IMPORT_NS("IOMMUFD");
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Max Gurtovoy <mgurtovoy@nvidia.com>");
MODULE_AUTHOR("Yishai Hadas <yishaih@nvidia.com>");
diff --git a/drivers/vfio/pci/pds/pci_drv.c b/drivers/vfio/pci/pds/pci_drv.c
index 16e93b11ab1b..4923f1823126 100644
--- a/drivers/vfio/pci/pds/pci_drv.c
+++ b/drivers/vfio/pci/pds/pci_drv.c
@@ -187,7 +187,7 @@ static struct pci_driver pds_vfio_pci_driver = {
module_pci_driver(pds_vfio_pci_driver);
-MODULE_IMPORT_NS(IOMMUFD);
+MODULE_IMPORT_NS("IOMMUFD");
MODULE_DESCRIPTION(PDS_VFIO_DRV_DESCRIPTION);
MODULE_AUTHOR("Brett Creeley <brett.creeley@amd.com>");
MODULE_LICENSE("GPL");
diff --git a/drivers/vfio/pci/qat/main.c b/drivers/vfio/pci/qat/main.c
index c78cb6de9390..845ed15b6771 100644
--- a/drivers/vfio/pci/qat/main.c
+++ b/drivers/vfio/pci/qat/main.c
@@ -697,4 +697,4 @@ module_pci_driver(qat_vf_vfio_pci_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Xin Zeng <xin.zeng@intel.com>");
MODULE_DESCRIPTION("QAT VFIO PCI - VFIO PCI driver with live migration support for Intel(R) QAT GEN4 device family");
-MODULE_IMPORT_NS(CRYPTO_QAT);
+MODULE_IMPORT_NS("CRYPTO_QAT");
diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c
index 1ab58da9f38a..1a4ed5a357d3 100644
--- a/drivers/vfio/pci/vfio_pci_core.c
+++ b/drivers/vfio/pci/vfio_pci_core.c
@@ -1661,14 +1661,15 @@ static vm_fault_t vfio_pci_mmap_huge_fault(struct vm_fault *vmf,
unsigned long pfn, pgoff = vmf->pgoff - vma->vm_pgoff;
vm_fault_t ret = VM_FAULT_SIGBUS;
- if (order && (vmf->address & ((PAGE_SIZE << order) - 1) ||
+ pfn = vma_to_pfn(vma) + pgoff;
+
+ if (order && (pfn & ((1 << order) - 1) ||
+ vmf->address & ((PAGE_SIZE << order) - 1) ||
vmf->address + (PAGE_SIZE << order) > vma->vm_end)) {
ret = VM_FAULT_FALLBACK;
goto out;
}
- pfn = vma_to_pfn(vma);
-
down_read(&vdev->memory_lock);
if (vdev->pm_runtime_engaged || !__vfio_pci_memory_enabled(vdev))
@@ -1676,18 +1677,18 @@ static vm_fault_t vfio_pci_mmap_huge_fault(struct vm_fault *vmf,
switch (order) {
case 0:
- ret = vmf_insert_pfn(vma, vmf->address, pfn + pgoff);
+ ret = vmf_insert_pfn(vma, vmf->address, pfn);
break;
#ifdef CONFIG_ARCH_SUPPORTS_PMD_PFNMAP
case PMD_ORDER:
- ret = vmf_insert_pfn_pmd(vmf, __pfn_to_pfn_t(pfn + pgoff,
- PFN_DEV), false);
+ ret = vmf_insert_pfn_pmd(vmf,
+ __pfn_to_pfn_t(pfn, PFN_DEV), false);
break;
#endif
#ifdef CONFIG_ARCH_SUPPORTS_PUD_PFNMAP
case PUD_ORDER:
- ret = vmf_insert_pfn_pud(vmf, __pfn_to_pfn_t(pfn + pgoff,
- PFN_DEV), false);
+ ret = vmf_insert_pfn_pud(vmf,
+ __pfn_to_pfn_t(pfn, PFN_DEV), false);
break;
#endif
default:
diff --git a/drivers/vfio/platform/vfio_platform.c b/drivers/vfio/platform/vfio_platform.c
index 42d1462c5e19..512533501eb7 100644
--- a/drivers/vfio/platform/vfio_platform.c
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -112,7 +112,7 @@ static const struct vfio_device_ops vfio_platform_ops = {
static struct platform_driver vfio_platform_driver = {
.probe = vfio_platform_probe,
- .remove_new = vfio_platform_remove,
+ .remove = vfio_platform_remove,
.driver = {
.name = "vfio-platform",
},
diff --git a/drivers/vfio/vfio_main.c b/drivers/vfio/vfio_main.c
index a5a62d9d963f..1fd261efc582 100644
--- a/drivers/vfio/vfio_main.c
+++ b/drivers/vfio/vfio_main.c
@@ -1751,7 +1751,7 @@ static void __exit vfio_cleanup(void)
module_init(vfio_init);
module_exit(vfio_cleanup);
-MODULE_IMPORT_NS(IOMMUFD);
+MODULE_IMPORT_NS("IOMMUFD");
MODULE_VERSION(DRIVER_VERSION);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/video/backlight/aat2870_bl.c b/drivers/video/backlight/aat2870_bl.c
index 68d327ee4b2e..8b790df1e842 100644
--- a/drivers/video/backlight/aat2870_bl.c
+++ b/drivers/video/backlight/aat2870_bl.c
@@ -186,7 +186,7 @@ static struct platform_driver aat2870_bl_driver = {
.name = "aat2870-backlight",
},
.probe = aat2870_bl_probe,
- .remove_new = aat2870_bl_remove,
+ .remove = aat2870_bl_remove,
};
static int __init aat2870_bl_init(void)
diff --git a/drivers/video/backlight/adp5520_bl.c b/drivers/video/backlight/adp5520_bl.c
index 8e0e9cfe5fe9..aa5c15e8db86 100644
--- a/drivers/video/backlight/adp5520_bl.c
+++ b/drivers/video/backlight/adp5520_bl.c
@@ -375,7 +375,7 @@ static struct platform_driver adp5520_bl_driver = {
.pm = &adp5520_bl_pm_ops,
},
.probe = adp5520_bl_probe,
- .remove_new = adp5520_bl_remove,
+ .remove = adp5520_bl_remove,
};
module_platform_driver(adp5520_bl_driver);
diff --git a/drivers/video/backlight/da9052_bl.c b/drivers/video/backlight/da9052_bl.c
index b8ff7046510e..5e13ef96b717 100644
--- a/drivers/video/backlight/da9052_bl.c
+++ b/drivers/video/backlight/da9052_bl.c
@@ -165,7 +165,7 @@ MODULE_DEVICE_TABLE(platform, da9052_wled_ids);
static struct platform_driver da9052_wled_driver = {
.probe = da9052_backlight_probe,
- .remove_new = da9052_backlight_remove,
+ .remove = da9052_backlight_remove,
.id_table = da9052_wled_ids,
.driver = {
.name = "da9052-wled",
diff --git a/drivers/video/backlight/hp680_bl.c b/drivers/video/backlight/hp680_bl.c
index ddb7ab4df77e..fa9a983533b2 100644
--- a/drivers/video/backlight/hp680_bl.c
+++ b/drivers/video/backlight/hp680_bl.c
@@ -130,7 +130,7 @@ static void hp680bl_remove(struct platform_device *pdev)
static struct platform_driver hp680bl_driver = {
.probe = hp680bl_probe,
- .remove_new = hp680bl_remove,
+ .remove = hp680bl_remove,
.driver = {
.name = "hp680-bl",
.pm = &hp680bl_pm_ops,
diff --git a/drivers/video/backlight/ktd2801-backlight.c b/drivers/video/backlight/ktd2801-backlight.c
index d295c2766025..0489b0615ceb 100644
--- a/drivers/video/backlight/ktd2801-backlight.c
+++ b/drivers/video/backlight/ktd2801-backlight.c
@@ -122,7 +122,7 @@ static struct platform_driver ktd2801_backlight_driver = {
};
module_platform_driver(ktd2801_backlight_driver);
-MODULE_IMPORT_NS(EXPRESSWIRE);
+MODULE_IMPORT_NS("EXPRESSWIRE");
MODULE_AUTHOR("Duje Mihanović <duje.mihanovic@skole.hr>");
MODULE_DESCRIPTION("Kinetic KTD2801 Backlight Driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/led_bl.c b/drivers/video/backlight/led_bl.c
index c7aefcd6e4e3..ae34d1ecbfbe 100644
--- a/drivers/video/backlight/led_bl.c
+++ b/drivers/video/backlight/led_bl.c
@@ -246,7 +246,7 @@ static struct platform_driver led_bl_driver = {
.of_match_table = led_bl_of_match,
},
.probe = led_bl_probe,
- .remove_new = led_bl_remove,
+ .remove = led_bl_remove,
};
module_platform_driver(led_bl_driver);
diff --git a/drivers/video/backlight/lm3533_bl.c b/drivers/video/backlight/lm3533_bl.c
index 5d06f8ca976c..babfd3ceec86 100644
--- a/drivers/video/backlight/lm3533_bl.c
+++ b/drivers/video/backlight/lm3533_bl.c
@@ -387,7 +387,7 @@ static struct platform_driver lm3533_bl_driver = {
.pm = &lm3533_bl_pm_ops,
},
.probe = lm3533_bl_probe,
- .remove_new = lm3533_bl_remove,
+ .remove = lm3533_bl_remove,
.shutdown = lm3533_bl_shutdown,
};
module_platform_driver(lm3533_bl_driver);
diff --git a/drivers/video/backlight/lp8788_bl.c b/drivers/video/backlight/lp8788_bl.c
index 0b7663519fa5..f61a64905a02 100644
--- a/drivers/video/backlight/lp8788_bl.c
+++ b/drivers/video/backlight/lp8788_bl.c
@@ -177,7 +177,7 @@ static void lp8788_backlight_remove(struct platform_device *pdev)
static struct platform_driver lp8788_bl_driver = {
.probe = lp8788_backlight_probe,
- .remove_new = lp8788_backlight_remove,
+ .remove = lp8788_backlight_remove,
.driver = {
.name = LP8788_DEV_BACKLIGHT,
},
diff --git a/drivers/video/backlight/mt6370-backlight.c b/drivers/video/backlight/mt6370-backlight.c
index 94422c956453..e55f26888d0f 100644
--- a/drivers/video/backlight/mt6370-backlight.c
+++ b/drivers/video/backlight/mt6370-backlight.c
@@ -340,7 +340,7 @@ static struct platform_driver mt6370_bl_driver = {
.of_match_table = mt6370_bl_of_match,
},
.probe = mt6370_bl_probe,
- .remove_new = mt6370_bl_remove,
+ .remove = mt6370_bl_remove,
};
module_platform_driver(mt6370_bl_driver);
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index e942908d1275..237d3d3f3bb1 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -697,7 +697,7 @@ static struct platform_driver pwm_backlight_driver = {
.of_match_table = of_match_ptr(pwm_backlight_of_match),
},
.probe = pwm_backlight_probe,
- .remove_new = pwm_backlight_remove,
+ .remove = pwm_backlight_remove,
.shutdown = pwm_backlight_shutdown,
};
diff --git a/drivers/video/backlight/qcom-wled.c b/drivers/video/backlight/qcom-wled.c
index 10129095a4c1..9afe701b2a1b 100644
--- a/drivers/video/backlight/qcom-wled.c
+++ b/drivers/video/backlight/qcom-wled.c
@@ -1741,7 +1741,7 @@ MODULE_DEVICE_TABLE(of, wled_match_table);
static struct platform_driver wled_driver = {
.probe = wled_probe,
- .remove_new = wled_remove,
+ .remove = wled_remove,
.driver = {
.name = "qcom,wled",
.of_match_table = wled_match_table,
diff --git a/drivers/video/backlight/rt4831-backlight.c b/drivers/video/backlight/rt4831-backlight.c
index c2f6fb29e1d0..7ead75929a43 100644
--- a/drivers/video/backlight/rt4831-backlight.c
+++ b/drivers/video/backlight/rt4831-backlight.c
@@ -224,7 +224,7 @@ static struct platform_driver rt4831_bl_driver = {
.of_match_table = rt4831_bl_of_match,
},
.probe = rt4831_bl_probe,
- .remove_new = rt4831_bl_remove,
+ .remove = rt4831_bl_remove,
};
module_platform_driver(rt4831_bl_driver);
diff --git a/drivers/video/backlight/sky81452-backlight.c b/drivers/video/backlight/sky81452-backlight.c
index 935043b67786..2749231f0385 100644
--- a/drivers/video/backlight/sky81452-backlight.c
+++ b/drivers/video/backlight/sky81452-backlight.c
@@ -337,7 +337,7 @@ static struct platform_driver sky81452_bl_driver = {
.of_match_table = of_match_ptr(sky81452_bl_of_match),
},
.probe = sky81452_bl_probe,
- .remove_new = sky81452_bl_remove,
+ .remove = sky81452_bl_remove,
};
module_platform_driver(sky81452_bl_driver);
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index de035071fedb..55c6686f091e 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -649,6 +649,7 @@ config FB_S1D13XXX
config FB_ATMEL
tristate "AT91 LCD Controller support"
depends on FB && OF && HAVE_CLK && HAS_IOMEM
+ depends on BACKLIGHT_CLASS_DEVICE
depends on HAVE_FB_ATMEL || COMPILE_TEST
select FB_BACKLIGHT
select FB_IOMEM_HELPERS
@@ -660,7 +661,6 @@ config FB_ATMEL
config FB_NVIDIA
tristate "nVidia Framebuffer Support"
depends on FB && PCI
- select FB_BACKLIGHT if FB_NVIDIA_BACKLIGHT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -700,6 +700,8 @@ config FB_NVIDIA_DEBUG
config FB_NVIDIA_BACKLIGHT
bool "Support for backlight control"
depends on FB_NVIDIA
+ depends on BACKLIGHT_CLASS_DEVICE=y || BACKLIGHT_CLASS_DEVICE=FB_NVIDIA
+ select FB_BACKLIGHT
default y
help
Say Y here if you want to control the backlight of your display.
@@ -707,7 +709,6 @@ config FB_NVIDIA_BACKLIGHT
config FB_RIVA
tristate "nVidia Riva support"
depends on FB && PCI
- select FB_BACKLIGHT if FB_RIVA_BACKLIGHT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -747,6 +748,8 @@ config FB_RIVA_DEBUG
config FB_RIVA_BACKLIGHT
bool "Support for backlight control"
depends on FB_RIVA
+ depends on BACKLIGHT_CLASS_DEVICE=y || BACKLIGHT_CLASS_DEVICE=FB_RIVA
+ select FB_BACKLIGHT
default y
help
Say Y here if you want to control the backlight of your display.
@@ -934,7 +937,6 @@ config FB_MATROX_MAVEN
config FB_RADEON
tristate "ATI Radeon display support"
depends on FB && PCI
- select FB_BACKLIGHT if FB_RADEON_BACKLIGHT
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
@@ -960,6 +962,8 @@ config FB_RADEON_I2C
config FB_RADEON_BACKLIGHT
bool "Support for backlight control"
depends on FB_RADEON
+ depends on BACKLIGHT_CLASS_DEVICE=y || BACKLIGHT_CLASS_DEVICE=FB_RADEON
+ select FB_BACKLIGHT
default y
help
Say Y here if you want to control the backlight of your display.
@@ -975,7 +979,6 @@ config FB_RADEON_DEBUG
config FB_ATY128
tristate "ATI Rage128 display support"
depends on FB && PCI
- select FB_BACKLIGHT if FB_ATY128_BACKLIGHT
select FB_IOMEM_HELPERS
select FB_MACMODES if PPC_PMAC
help
@@ -989,6 +992,8 @@ config FB_ATY128
config FB_ATY128_BACKLIGHT
bool "Support for backlight control"
depends on FB_ATY128
+ depends on BACKLIGHT_CLASS_DEVICE=y || BACKLIGHT_CLASS_DEVICE=FB_ATY128
+ select FB_BACKLIGHT
default y
help
Say Y here if you want to control the backlight of your display.
@@ -999,7 +1004,6 @@ config FB_ATY
select FB_CFB_FILLRECT
select FB_CFB_COPYAREA
select FB_CFB_IMAGEBLIT
- select FB_BACKLIGHT if FB_ATY_BACKLIGHT
select FB_IOMEM_FOPS
select FB_MACMODES if PPC
select FB_ATY_CT if SPARC64 && PCI
@@ -1040,6 +1044,8 @@ config FB_ATY_GX
config FB_ATY_BACKLIGHT
bool "Support for backlight control"
depends on FB_ATY
+ depends on BACKLIGHT_CLASS_DEVICE=y || BACKLIGHT_CLASS_DEVICE=FB_ATY
+ select FB_BACKLIGHT
default y
help
Say Y here if you want to control the backlight of your display.
@@ -1528,6 +1534,7 @@ config FB_SH_MOBILE_LCDC
depends on FB && HAVE_CLK && HAS_IOMEM
depends on SUPERH || COMPILE_TEST
depends on FB_DEVICE
+ depends on BACKLIGHT_CLASS_DEVICE
select FB_BACKLIGHT
select FB_DEFERRED_IO
select FB_DMAMEM_HELPERS
@@ -1793,6 +1800,7 @@ config FB_SSD1307
tristate "Solomon SSD1307 framebuffer support"
depends on FB && I2C
depends on GPIOLIB || COMPILE_TEST
+ depends on BACKLIGHT_CLASS_DEVICE
select FB_BACKLIGHT
select FB_SYSMEM_HELPERS_DEFERRED
help
diff --git a/drivers/video/fbdev/core/Kconfig b/drivers/video/fbdev/core/Kconfig
index 0ab8848ba2f1..d554d8c543d4 100644
--- a/drivers/video/fbdev/core/Kconfig
+++ b/drivers/video/fbdev/core/Kconfig
@@ -183,9 +183,8 @@ config FB_SYSMEM_HELPERS_DEFERRED
select FB_SYSMEM_HELPERS
config FB_BACKLIGHT
- tristate
+ bool
depends on FB
- select BACKLIGHT_CLASS_DEVICE
config FB_MODE_HELPERS
bool "Enable Video Mode Handling Helpers"
diff --git a/drivers/virt/coco/arm-cca-guest/Kconfig b/drivers/virt/coco/arm-cca-guest/Kconfig
index 9dd27c3ee215..3f0f013f03f1 100644
--- a/drivers/virt/coco/arm-cca-guest/Kconfig
+++ b/drivers/virt/coco/arm-cca-guest/Kconfig
@@ -1,7 +1,6 @@
config ARM_CCA_GUEST
tristate "Arm CCA Guest driver"
depends on ARM64
- default m
select TSM_REPORTS
help
The driver provides userspace interface to request and
diff --git a/drivers/virt/coco/efi_secret/efi_secret.c b/drivers/virt/coco/efi_secret/efi_secret.c
index cd29e66b1543..1864f9f80617 100644
--- a/drivers/virt/coco/efi_secret/efi_secret.c
+++ b/drivers/virt/coco/efi_secret/efi_secret.c
@@ -334,7 +334,7 @@ static void efi_secret_remove(struct platform_device *dev)
static struct platform_driver efi_secret_driver = {
.probe = efi_secret_probe,
- .remove_new = efi_secret_remove,
+ .remove = efi_secret_remove,
.driver = {
.name = "efi_secret",
},
diff --git a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c
index 56a3859dda8a..4230b817a80b 100644
--- a/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c
+++ b/drivers/virt/coco/pkvm-guest/arm-pkvm-guest.c
@@ -87,12 +87,8 @@ static int mmio_guard_ioremap_hook(phys_addr_t phys, size_t size,
while (phys < end) {
const int func_id = ARM_SMCCC_VENDOR_HYP_KVM_MMIO_GUARD_FUNC_ID;
- int err;
-
- err = arm_smccc_do_one_page(func_id, phys);
- if (err)
- return err;
+ WARN_ON_ONCE(arm_smccc_do_one_page(func_id, phys));
phys += PAGE_SIZE;
}
diff --git a/drivers/virt/coco/sev-guest/sev-guest.c b/drivers/virt/coco/sev-guest/sev-guest.c
index fca5c45ed5cd..b699771be029 100644
--- a/drivers/virt/coco/sev-guest/sev-guest.c
+++ b/drivers/virt/coco/sev-guest/sev-guest.c
@@ -1116,7 +1116,7 @@ static void __exit sev_guest_remove(struct platform_device *pdev)
* triggering a section mismatch warning.
*/
static struct platform_driver sev_guest_driver __refdata = {
- .remove_new = __exit_p(sev_guest_remove),
+ .remove = __exit_p(sev_guest_remove),
.driver = {
.name = "sev-guest",
},
diff --git a/drivers/virt/coco/tdx-guest/tdx-guest.c b/drivers/virt/coco/tdx-guest/tdx-guest.c
index d7db6c824e13..224e7dde9cde 100644
--- a/drivers/virt/coco/tdx-guest/tdx-guest.c
+++ b/drivers/virt/coco/tdx-guest/tdx-guest.c
@@ -124,10 +124,8 @@ static void *alloc_quote_buf(void)
if (!addr)
return NULL;
- if (set_memory_decrypted((unsigned long)addr, count)) {
- free_pages_exact(addr, len);
+ if (set_memory_decrypted((unsigned long)addr, count))
return NULL;
- }
return addr;
}
diff --git a/drivers/virtio/virtio_dma_buf.c b/drivers/virtio/virtio_dma_buf.c
index 3034a2f605c8..3fe1d03b0645 100644
--- a/drivers/virtio/virtio_dma_buf.c
+++ b/drivers/virtio/virtio_dma_buf.c
@@ -87,4 +87,4 @@ EXPORT_SYMBOL(virtio_dma_buf_get_uuid);
MODULE_DESCRIPTION("dma-bufs for virtio exported objects");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c
index 90e784e7b721..5d78c2d572ab 100644
--- a/drivers/virtio/virtio_mmio.c
+++ b/drivers/virtio/virtio_mmio.c
@@ -845,7 +845,7 @@ MODULE_DEVICE_TABLE(acpi, virtio_mmio_acpi_match);
static struct platform_driver virtio_mmio_driver = {
.probe = virtio_mmio_probe,
- .remove_new = virtio_mmio_remove,
+ .remove = virtio_mmio_remove,
.driver = {
.name = "virtio-mmio",
.of_match_table = virtio_mmio_match,
diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 82a7d2cbc704..fdd2d2b07b5a 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -2772,6 +2772,7 @@ EXPORT_SYMBOL_GPL(vring_create_virtqueue_dma);
* @_vq: the struct virtqueue we're talking about.
* @num: new ring num
* @recycle: callback to recycle unused buffers
+ * @recycle_done: callback to be invoked when recycle for all unused buffers done
*
* When it is really necessary to create a new vring, it will set the current vq
* into the reset state. Then call the passed callback to recycle the buffer
@@ -2792,7 +2793,8 @@ EXPORT_SYMBOL_GPL(vring_create_virtqueue_dma);
*
*/
int virtqueue_resize(struct virtqueue *_vq, u32 num,
- void (*recycle)(struct virtqueue *vq, void *buf))
+ void (*recycle)(struct virtqueue *vq, void *buf),
+ void (*recycle_done)(struct virtqueue *vq))
{
struct vring_virtqueue *vq = to_vvq(_vq);
int err;
@@ -2809,6 +2811,8 @@ int virtqueue_resize(struct virtqueue *_vq, u32 num,
err = virtqueue_disable_and_recycle(_vq, recycle);
if (err)
return err;
+ if (recycle_done)
+ recycle_done(_vq);
if (vq->packed_ring)
err = virtqueue_resize_packed(_vq, num);
@@ -2823,6 +2827,7 @@ EXPORT_SYMBOL_GPL(virtqueue_resize);
* virtqueue_reset - detach and recycle all unused buffers
* @_vq: the struct virtqueue we're talking about.
* @recycle: callback to recycle unused buffers
+ * @recycle_done: callback to be invoked when recycle for all unused buffers done
*
* Caller must ensure we don't call this with other virtqueue operations
* at the same time (except where noted).
@@ -2834,7 +2839,8 @@ EXPORT_SYMBOL_GPL(virtqueue_resize);
* -EPERM: Operation not permitted
*/
int virtqueue_reset(struct virtqueue *_vq,
- void (*recycle)(struct virtqueue *vq, void *buf))
+ void (*recycle)(struct virtqueue *vq, void *buf),
+ void (*recycle_done)(struct virtqueue *vq))
{
struct vring_virtqueue *vq = to_vvq(_vq);
int err;
@@ -2842,6 +2848,8 @@ int virtqueue_reset(struct virtqueue *_vq,
err = virtqueue_disable_and_recycle(_vq, recycle);
if (err)
return err;
+ if (recycle_done)
+ recycle_done(_vq);
if (vq->packed_ring)
virtqueue_reinit_packed(vq);
diff --git a/drivers/w1/masters/amd_axi_w1.c b/drivers/w1/masters/amd_axi_w1.c
index 4d3a68ca9263..5da8b8d86811 100644
--- a/drivers/w1/masters/amd_axi_w1.c
+++ b/drivers/w1/masters/amd_axi_w1.c
@@ -383,7 +383,7 @@ MODULE_DEVICE_TABLE(of, amd_axi_w1_of_match);
static struct platform_driver amd_axi_w1_driver = {
.probe = amd_axi_w1_probe,
- .remove_new = amd_axi_w1_remove,
+ .remove = amd_axi_w1_remove,
.driver = {
.name = DRIVER_NAME,
.of_match_table = amd_axi_w1_of_match,
diff --git a/drivers/w1/masters/mxc_w1.c b/drivers/w1/masters/mxc_w1.c
index ba1d0866d1c4..30a190ce4298 100644
--- a/drivers/w1/masters/mxc_w1.c
+++ b/drivers/w1/masters/mxc_w1.c
@@ -172,7 +172,7 @@ static struct platform_driver mxc_w1_driver = {
.of_match_table = mxc_w1_dt_ids,
},
.probe = mxc_w1_probe,
- .remove_new = mxc_w1_remove,
+ .remove = mxc_w1_remove,
};
module_platform_driver(mxc_w1_driver);
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c
index d1cb5190445a..69b1d145657a 100644
--- a/drivers/w1/masters/omap_hdq.c
+++ b/drivers/w1/masters/omap_hdq.c
@@ -672,7 +672,7 @@ MODULE_DEVICE_TABLE(of, omap_hdq_dt_ids);
static struct platform_driver omap_hdq_driver = {
.probe = omap_hdq_probe,
- .remove_new = omap_hdq_remove,
+ .remove = omap_hdq_remove,
.driver = {
.name = "omap_hdq",
.of_match_table = omap_hdq_dt_ids,
diff --git a/drivers/w1/masters/sgi_w1.c b/drivers/w1/masters/sgi_w1.c
index 7bb7876aa70e..af6b1186b763 100644
--- a/drivers/w1/masters/sgi_w1.c
+++ b/drivers/w1/masters/sgi_w1.c
@@ -117,7 +117,7 @@ static struct platform_driver sgi_w1_driver = {
.name = "sgi_w1",
},
.probe = sgi_w1_probe,
- .remove_new = sgi_w1_remove,
+ .remove = sgi_w1_remove,
};
module_platform_driver(sgi_w1_driver);
diff --git a/drivers/w1/masters/w1-gpio.c b/drivers/w1/masters/w1-gpio.c
index a39fa8bf866a..a579f95be8f1 100644
--- a/drivers/w1/masters/w1-gpio.c
+++ b/drivers/w1/masters/w1-gpio.c
@@ -146,7 +146,7 @@ static struct platform_driver w1_gpio_driver = {
.of_match_table = w1_gpio_dt_ids,
},
.probe = w1_gpio_probe,
- .remove_new = w1_gpio_remove,
+ .remove = w1_gpio_remove,
};
module_platform_driver(w1_gpio_driver);
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index 2333476a42c0..f81705f8539a 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -408,6 +408,14 @@ config SL28CPLD_WATCHDOG
# ARM Architecture
+config AIROHA_WATCHDOG
+ tristate "Airoha EN7581 Watchdog"
+ depends on ARCH_AIROHA || COMPILE_TEST
+ select WATCHDOG_CORE
+ help
+ Watchdog timer embedded into Airoha SoC. This will reboot your
+ system when the timeout is reached.
+
config ARM_SP805_WATCHDOG
tristate "ARM SP805 Watchdog"
depends on (ARM || ARM64 || COMPILE_TEST) && ARM_AMBA
@@ -549,6 +557,7 @@ config S3C2410_WATCHDOG
tristate "S3C6410/S5Pv210/Exynos Watchdog"
depends on ARCH_S3C64XX || ARCH_S5PV210 || ARCH_EXYNOS || COMPILE_TEST
select WATCHDOG_CORE
+ select MFD_SYSCON if ARCH_EXYNOS
help
Watchdog timer block in the Samsung S3C64xx, S5Pv210 and Exynos
SoCs. This will reboot the system when the timer expires with
@@ -1543,14 +1552,6 @@ config SBC7240_WDT
To compile this driver as a module, choose M here: the
module will be called sbc7240_wdt.
-config CPU5_WDT
- tristate "SMA CPU5 Watchdog"
- depends on (X86 || COMPILE_TEST) && HAS_IOPORT
- help
- TBD.
- To compile this driver as a module, choose M here: the
- module will be called cpu5wdt.
-
config SMSC_SCH311X_WDT
tristate "SMSC SCH311X Watchdog Timer"
depends on (X86 || COMPILE_TEST) && HAS_IOPORT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 386d88d89fe5..8411626fa162 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -40,6 +40,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o
obj-$(CONFIG_ARM_SP805_WATCHDOG) += sp805_wdt.o
obj-$(CONFIG_ARM_SBSA_WATCHDOG) += sbsa_gwdt.o
obj-$(CONFIG_ARMADA_37XX_WATCHDOG) += armada_37xx_wdt.o
+obj-$(CONFIG_AIROHA_WATCHDOG) += airoha_wdt.o
obj-$(CONFIG_ASM9260_WATCHDOG) += asm9260_wdt.o
obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o
obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o
@@ -138,7 +139,6 @@ obj-$(CONFIG_RDC321X_WDT) += rdc321x_wdt.o
obj-$(CONFIG_60XX_WDT) += sbc60xxwdt.o
obj-$(CONFIG_SBC8360_WDT) += sbc8360.o
obj-$(CONFIG_SBC7240_WDT) += sbc7240_wdt.o
-obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o
obj-$(CONFIG_SMSC_SCH311X_WDT) += sch311x_wdt.o
obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o
obj-$(CONFIG_TQMX86_WDT) += tqmx86_wdt.o
diff --git a/drivers/watchdog/acquirewdt.c b/drivers/watchdog/acquirewdt.c
index 08ca18e91124..052f65c48a70 100644
--- a/drivers/watchdog/acquirewdt.c
+++ b/drivers/watchdog/acquirewdt.c
@@ -285,7 +285,7 @@ static void acq_shutdown(struct platform_device *dev)
}
static struct platform_driver acquirewdt_driver = {
- .remove_new = acq_remove,
+ .remove = acq_remove,
.shutdown = acq_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/watchdog/advantechwdt.c b/drivers/watchdog/advantechwdt.c
index e41cd3ba4e0e..42d3f3771781 100644
--- a/drivers/watchdog/advantechwdt.c
+++ b/drivers/watchdog/advantechwdt.c
@@ -293,7 +293,7 @@ static void advwdt_shutdown(struct platform_device *dev)
}
static struct platform_driver advwdt_driver = {
- .remove_new = advwdt_remove,
+ .remove = advwdt_remove,
.shutdown = advwdt_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/watchdog/airoha_wdt.c b/drivers/watchdog/airoha_wdt.c
new file mode 100644
index 000000000000..dc8ca11c14d8
--- /dev/null
+++ b/drivers/watchdog/airoha_wdt.c
@@ -0,0 +1,216 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Airoha Watchdog Driver
+ *
+ * Copyright (c) 2024, AIROHA All rights reserved.
+ *
+ * Mayur Kumar <mayur.kumar@airoha.com>
+ * Christian Marangi <ansuelsmth@gmail.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/types.h>
+#include <linux/bitfield.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/math.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/watchdog.h>
+
+/* Base address of timer and watchdog registers */
+#define TIMER_CTRL 0x0
+#define WDT_ENABLE BIT(25)
+#define WDT_TIMER_INTERRUPT BIT(21)
+/* Timer3 is used as Watchdog Timer */
+#define WDT_TIMER_ENABLE BIT(5)
+#define WDT_TIMER_LOAD_VALUE 0x2c
+#define WDT_TIMER_CUR_VALUE 0x30
+#define WDT_TIMER_VAL GENMASK(31, 0)
+#define WDT_RELOAD 0x38
+#define WDT_RLD BIT(0)
+
+/* Airoha watchdog structure description */
+struct airoha_wdt_desc {
+ struct watchdog_device wdog_dev;
+ unsigned int wdt_freq;
+ void __iomem *base;
+};
+
+#define WDT_HEARTBEAT 24
+static int heartbeat = WDT_HEARTBEAT;
+module_param(heartbeat, int, 0);
+MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. (default="
+ __MODULE_STRING(WDT_HEARTBEAT) ")");
+
+static bool nowayout = WATCHDOG_NOWAYOUT;
+module_param(nowayout, bool, 0);
+MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
+ __MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
+
+static int airoha_wdt_start(struct watchdog_device *wdog_dev)
+{
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
+ u32 val;
+
+ val = readl(airoha_wdt->base + TIMER_CTRL);
+ val |= (WDT_TIMER_ENABLE | WDT_ENABLE | WDT_TIMER_INTERRUPT);
+ writel(val, airoha_wdt->base + TIMER_CTRL);
+ val = wdog_dev->timeout * airoha_wdt->wdt_freq;
+ writel(val, airoha_wdt->base + WDT_TIMER_LOAD_VALUE);
+
+ return 0;
+}
+
+static int airoha_wdt_stop(struct watchdog_device *wdog_dev)
+{
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
+ u32 val;
+
+ val = readl(airoha_wdt->base + TIMER_CTRL);
+ val &= (~WDT_ENABLE & ~WDT_TIMER_ENABLE);
+ writel(val, airoha_wdt->base + TIMER_CTRL);
+
+ return 0;
+}
+
+static int airoha_wdt_ping(struct watchdog_device *wdog_dev)
+{
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
+ u32 val;
+
+ val = readl(airoha_wdt->base + WDT_RELOAD);
+ val |= WDT_RLD;
+ writel(val, airoha_wdt->base + WDT_RELOAD);
+
+ return 0;
+}
+
+static int airoha_wdt_set_timeout(struct watchdog_device *wdog_dev, unsigned int timeout)
+{
+ wdog_dev->timeout = timeout;
+
+ if (watchdog_active(wdog_dev)) {
+ airoha_wdt_stop(wdog_dev);
+ return airoha_wdt_start(wdog_dev);
+ }
+
+ return 0;
+}
+
+static unsigned int airoha_wdt_get_timeleft(struct watchdog_device *wdog_dev)
+{
+ struct airoha_wdt_desc *airoha_wdt = watchdog_get_drvdata(wdog_dev);
+ u32 val;
+
+ val = readl(airoha_wdt->base + WDT_TIMER_CUR_VALUE);
+ return DIV_ROUND_UP(val, airoha_wdt->wdt_freq);
+}
+
+static const struct watchdog_info airoha_wdt_info = {
+ .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
+ .identity = "Airoha Watchdog",
+};
+
+static const struct watchdog_ops airoha_wdt_ops = {
+ .owner = THIS_MODULE,
+ .start = airoha_wdt_start,
+ .stop = airoha_wdt_stop,
+ .ping = airoha_wdt_ping,
+ .set_timeout = airoha_wdt_set_timeout,
+ .get_timeleft = airoha_wdt_get_timeleft,
+};
+
+static int airoha_wdt_probe(struct platform_device *pdev)
+{
+ struct airoha_wdt_desc *airoha_wdt;
+ struct watchdog_device *wdog_dev;
+ struct device *dev = &pdev->dev;
+ struct clk *bus_clk;
+ int ret;
+
+ airoha_wdt = devm_kzalloc(dev, sizeof(*airoha_wdt), GFP_KERNEL);
+ if (!airoha_wdt)
+ return -ENOMEM;
+
+ airoha_wdt->base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(airoha_wdt->base))
+ return PTR_ERR(airoha_wdt->base);
+
+ bus_clk = devm_clk_get_enabled(dev, "bus");
+ if (IS_ERR(bus_clk))
+ return dev_err_probe(dev, PTR_ERR(bus_clk),
+ "failed to enable bus clock\n");
+
+ /* Watchdog ticks at half the bus rate */
+ airoha_wdt->wdt_freq = clk_get_rate(bus_clk) / 2;
+
+ /* Initialize struct watchdog device */
+ wdog_dev = &airoha_wdt->wdog_dev;
+ wdog_dev->timeout = heartbeat;
+ wdog_dev->info = &airoha_wdt_info;
+ wdog_dev->ops = &airoha_wdt_ops;
+ /* Bus 300MHz, watchdog 150MHz, 28 seconds */
+ wdog_dev->max_timeout = FIELD_MAX(WDT_TIMER_VAL) / airoha_wdt->wdt_freq;
+ wdog_dev->parent = dev;
+
+ watchdog_set_drvdata(wdog_dev, airoha_wdt);
+ watchdog_set_nowayout(wdog_dev, nowayout);
+ watchdog_stop_on_unregister(wdog_dev);
+
+ ret = devm_watchdog_register_device(dev, wdog_dev);
+ if (ret)
+ return ret;
+
+ platform_set_drvdata(pdev, airoha_wdt);
+ return 0;
+}
+
+static int airoha_wdt_suspend(struct device *dev)
+{
+ struct airoha_wdt_desc *airoha_wdt = dev_get_drvdata(dev);
+
+ if (watchdog_active(&airoha_wdt->wdog_dev))
+ airoha_wdt_stop(&airoha_wdt->wdog_dev);
+
+ return 0;
+}
+
+static int airoha_wdt_resume(struct device *dev)
+{
+ struct airoha_wdt_desc *airoha_wdt = dev_get_drvdata(dev);
+
+ if (watchdog_active(&airoha_wdt->wdog_dev)) {
+ airoha_wdt_start(&airoha_wdt->wdog_dev);
+ airoha_wdt_ping(&airoha_wdt->wdog_dev);
+ }
+ return 0;
+}
+
+static const struct of_device_id airoha_wdt_of_match[] = {
+ { .compatible = "airoha,en7581-wdt", },
+ { },
+};
+
+MODULE_DEVICE_TABLE(of, airoha_wdt_of_match);
+
+static DEFINE_SIMPLE_DEV_PM_OPS(airoha_wdt_pm_ops, airoha_wdt_suspend, airoha_wdt_resume);
+
+static struct platform_driver airoha_wdt_driver = {
+ .probe = airoha_wdt_probe,
+ .driver = {
+ .name = "airoha-wdt",
+ .pm = pm_sleep_ptr(&airoha_wdt_pm_ops),
+ .of_match_table = airoha_wdt_of_match,
+ },
+};
+
+module_platform_driver(airoha_wdt_driver);
+
+MODULE_AUTHOR("Mayur Kumar <mayur.kumar@airoha.com>");
+MODULE_AUTHOR("Christian Marangi <ansuelsmth@gmail.com>");
+MODULE_DESCRIPTION("Airoha EN7581 Watchdog Driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/apple_wdt.c b/drivers/watchdog/apple_wdt.c
index d4f739932f0b..95d9e37df41c 100644
--- a/drivers/watchdog/apple_wdt.c
+++ b/drivers/watchdog/apple_wdt.c
@@ -127,11 +127,11 @@ static int apple_wdt_restart(struct watchdog_device *wdd, unsigned long mode,
/*
* Flush writes and then wait for the SoC to reset. Even though the
* reset is queued almost immediately experiments have shown that it
- * can take up to ~20-25ms until the SoC is actually reset. Just wait
- * 50ms here to be safe.
+ * can take up to ~120-125ms until the SoC is actually reset. Just
+ * wait 150ms here to be safe.
*/
- (void)readl_relaxed(wdt->regs + APPLE_WDT_WD1_CUR_TIME);
- mdelay(50);
+ (void)readl(wdt->regs + APPLE_WDT_WD1_CUR_TIME);
+ mdelay(150);
return 0;
}
diff --git a/drivers/watchdog/armada_37xx_wdt.c b/drivers/watchdog/armada_37xx_wdt.c
index 8133a5d05647..a17a7911771a 100644
--- a/drivers/watchdog/armada_37xx_wdt.c
+++ b/drivers/watchdog/armada_37xx_wdt.c
@@ -248,7 +248,6 @@ static const struct watchdog_ops armada_37xx_wdt_ops = {
static int armada_37xx_wdt_probe(struct platform_device *pdev)
{
struct armada_37xx_watchdog *dev;
- struct resource *res;
struct regmap *regmap;
int ret;
@@ -266,12 +265,9 @@ static int armada_37xx_wdt_probe(struct platform_device *pdev)
return PTR_ERR(regmap);
dev->cpu_misc = regmap;
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!res)
- return -ENODEV;
- dev->reg = devm_ioremap(&pdev->dev, res->start, resource_size(res));
- if (!dev->reg)
- return -ENOMEM;
+ dev->reg = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(dev->reg))
+ return PTR_ERR(dev->reg);
/* init clock */
dev->clk = devm_clk_get_enabled(&pdev->dev, NULL);
diff --git a/drivers/watchdog/at91rm9200_wdt.c b/drivers/watchdog/at91rm9200_wdt.c
index 17382512a609..1795aaf1ec45 100644
--- a/drivers/watchdog/at91rm9200_wdt.c
+++ b/drivers/watchdog/at91rm9200_wdt.c
@@ -295,7 +295,7 @@ MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids);
static struct platform_driver at91wdt_driver = {
.probe = at91wdt_probe,
- .remove_new = at91wdt_remove,
+ .remove = at91wdt_remove,
.shutdown = at91wdt_shutdown,
.suspend = pm_ptr(at91wdt_suspend),
.resume = pm_ptr(at91wdt_resume),
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c
index 2c6474cb858b..7be70b98d091 100644
--- a/drivers/watchdog/at91sam9_wdt.c
+++ b/drivers/watchdog/at91sam9_wdt.c
@@ -392,7 +392,7 @@ MODULE_DEVICE_TABLE(of, at91_wdt_dt_ids);
static struct platform_driver at91wdt_driver = {
.probe = at91wdt_probe,
- .remove_new = at91wdt_remove,
+ .remove = at91wdt_remove,
.driver = {
.name = "at91_wdt",
.of_match_table = of_match_ptr(at91_wdt_dt_ids),
diff --git a/drivers/watchdog/ath79_wdt.c b/drivers/watchdog/ath79_wdt.c
index d16b2c583fa4..7df703e9852a 100644
--- a/drivers/watchdog/ath79_wdt.c
+++ b/drivers/watchdog/ath79_wdt.c
@@ -305,7 +305,7 @@ MODULE_DEVICE_TABLE(of, ath79_wdt_match);
static struct platform_driver ath79_wdt_driver = {
.probe = ath79_wdt_probe,
- .remove_new = ath79_wdt_remove,
+ .remove = ath79_wdt_remove,
.shutdown = ath79_wdt_shutdown,
.driver = {
.name = DRIVER_NAME,
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
index bb001c5d7f17..9fcfee63905b 100644
--- a/drivers/watchdog/bcm2835_wdt.c
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -227,7 +227,7 @@ static void bcm2835_wdt_remove(struct platform_device *pdev)
static struct platform_driver bcm2835_wdt_driver = {
.probe = bcm2835_wdt_probe,
- .remove_new = bcm2835_wdt_remove,
+ .remove = bcm2835_wdt_remove,
.driver = {
.name = "bcm2835-wdt",
},
diff --git a/drivers/watchdog/bcm_kona_wdt.c b/drivers/watchdog/bcm_kona_wdt.c
index 49e12d47b073..66bd0324fd68 100644
--- a/drivers/watchdog/bcm_kona_wdt.c
+++ b/drivers/watchdog/bcm_kona_wdt.c
@@ -328,7 +328,7 @@ static struct platform_driver bcm_kona_wdt_driver = {
.of_match_table = bcm_kona_wdt_of_match,
},
.probe = bcm_kona_wdt_probe,
- .remove_new = bcm_kona_wdt_remove,
+ .remove = bcm_kona_wdt_remove,
};
module_platform_driver(bcm_kona_wdt_driver);
diff --git a/drivers/watchdog/cpu5wdt.c b/drivers/watchdog/cpu5wdt.c
deleted file mode 100644
index f94b84048612..000000000000
--- a/drivers/watchdog/cpu5wdt.c
+++ /dev/null
@@ -1,284 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * sma cpu5 watchdog driver
- *
- * Copyright (C) 2003 Heiko Ronsdorf <hero@ihg.uni-duisburg.de>
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/miscdevice.h>
-#include <linux/fs.h>
-#include <linux/ioport.h>
-#include <linux/timer.h>
-#include <linux/completion.h>
-#include <linux/jiffies.h>
-#include <linux/io.h>
-#include <linux/uaccess.h>
-#include <linux/watchdog.h>
-
-/* adjustable parameters */
-
-static int verbose;
-static int port = 0x91;
-static int ticks = 10000;
-static DEFINE_SPINLOCK(cpu5wdt_lock);
-
-#define PFX "cpu5wdt: "
-
-#define CPU5WDT_EXTENT 0x0A
-
-#define CPU5WDT_STATUS_REG 0x00
-#define CPU5WDT_TIME_A_REG 0x02
-#define CPU5WDT_TIME_B_REG 0x03
-#define CPU5WDT_MODE_REG 0x04
-#define CPU5WDT_TRIGGER_REG 0x07
-#define CPU5WDT_ENABLE_REG 0x08
-#define CPU5WDT_RESET_REG 0x09
-
-#define CPU5WDT_INTERVAL (HZ/10+1)
-
-/* some device data */
-
-static struct {
- struct completion stop;
- int running;
- struct timer_list timer;
- int queue;
- int default_ticks;
- unsigned long inuse;
-} cpu5wdt_device;
-
-/* generic helper functions */
-
-static void cpu5wdt_trigger(struct timer_list *unused)
-{
- if (verbose > 2)
- pr_debug("trigger at %i ticks\n", ticks);
-
- if (cpu5wdt_device.running)
- ticks--;
-
- spin_lock(&cpu5wdt_lock);
- /* keep watchdog alive */
- outb(1, port + CPU5WDT_TRIGGER_REG);
-
- /* requeue?? */
- if (cpu5wdt_device.queue && ticks)
- mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
- else {
- /* ticks doesn't matter anyway */
- complete(&cpu5wdt_device.stop);
- }
- spin_unlock(&cpu5wdt_lock);
-
-}
-
-static void cpu5wdt_reset(void)
-{
- ticks = cpu5wdt_device.default_ticks;
-
- if (verbose)
- pr_debug("reset (%i ticks)\n", (int) ticks);
-
-}
-
-static void cpu5wdt_start(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cpu5wdt_lock, flags);
- if (!cpu5wdt_device.queue) {
- cpu5wdt_device.queue = 1;
- outb(0, port + CPU5WDT_TIME_A_REG);
- outb(0, port + CPU5WDT_TIME_B_REG);
- outb(1, port + CPU5WDT_MODE_REG);
- outb(0, port + CPU5WDT_RESET_REG);
- outb(0, port + CPU5WDT_ENABLE_REG);
- mod_timer(&cpu5wdt_device.timer, jiffies + CPU5WDT_INTERVAL);
- }
- /* if process dies, counter is not decremented */
- cpu5wdt_device.running++;
- spin_unlock_irqrestore(&cpu5wdt_lock, flags);
-}
-
-static int cpu5wdt_stop(void)
-{
- unsigned long flags;
-
- spin_lock_irqsave(&cpu5wdt_lock, flags);
- if (cpu5wdt_device.running)
- cpu5wdt_device.running = 0;
- ticks = cpu5wdt_device.default_ticks;
- spin_unlock_irqrestore(&cpu5wdt_lock, flags);
- if (verbose)
- pr_crit("stop not possible\n");
- return -EIO;
-}
-
-/* filesystem operations */
-
-static int cpu5wdt_open(struct inode *inode, struct file *file)
-{
- if (test_and_set_bit(0, &cpu5wdt_device.inuse))
- return -EBUSY;
- return stream_open(inode, file);
-}
-
-static int cpu5wdt_release(struct inode *inode, struct file *file)
-{
- clear_bit(0, &cpu5wdt_device.inuse);
- return 0;
-}
-
-static long cpu5wdt_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- void __user *argp = (void __user *)arg;
- int __user *p = argp;
- unsigned int value;
- static const struct watchdog_info ident = {
- .options = WDIOF_CARDRESET,
- .identity = "CPU5 WDT",
- };
-
- switch (cmd) {
- case WDIOC_GETSUPPORT:
- if (copy_to_user(argp, &ident, sizeof(ident)))
- return -EFAULT;
- break;
- case WDIOC_GETSTATUS:
- value = inb(port + CPU5WDT_STATUS_REG);
- value = (value >> 2) & 1;
- return put_user(value, p);
- case WDIOC_GETBOOTSTATUS:
- return put_user(0, p);
- case WDIOC_SETOPTIONS:
- if (get_user(value, p))
- return -EFAULT;
- if (value & WDIOS_ENABLECARD)
- cpu5wdt_start();
- if (value & WDIOS_DISABLECARD)
- cpu5wdt_stop();
- break;
- case WDIOC_KEEPALIVE:
- cpu5wdt_reset();
- break;
- default:
- return -ENOTTY;
- }
- return 0;
-}
-
-static ssize_t cpu5wdt_write(struct file *file, const char __user *buf,
- size_t count, loff_t *ppos)
-{
- if (!count)
- return -EIO;
- cpu5wdt_reset();
- return count;
-}
-
-static const struct file_operations cpu5wdt_fops = {
- .owner = THIS_MODULE,
- .unlocked_ioctl = cpu5wdt_ioctl,
- .compat_ioctl = compat_ptr_ioctl,
- .open = cpu5wdt_open,
- .write = cpu5wdt_write,
- .release = cpu5wdt_release,
-};
-
-static struct miscdevice cpu5wdt_misc = {
- .minor = WATCHDOG_MINOR,
- .name = "watchdog",
- .fops = &cpu5wdt_fops,
-};
-
-/* init/exit function */
-
-static int cpu5wdt_init(void)
-{
- unsigned int val;
- int err;
-
- if (verbose)
- pr_debug("port=0x%x, verbose=%i\n", port, verbose);
-
- init_completion(&cpu5wdt_device.stop);
- cpu5wdt_device.queue = 0;
- timer_setup(&cpu5wdt_device.timer, cpu5wdt_trigger, 0);
- cpu5wdt_device.default_ticks = ticks;
-
- if (!request_region(port, CPU5WDT_EXTENT, PFX)) {
- pr_err("request_region failed\n");
- err = -EBUSY;
- goto no_port;
- }
-
- /* watchdog reboot? */
- val = inb(port + CPU5WDT_STATUS_REG);
- val = (val >> 2) & 1;
- if (!val)
- pr_info("sorry, was my fault\n");
-
- err = misc_register(&cpu5wdt_misc);
- if (err < 0) {
- pr_err("misc_register failed\n");
- goto no_misc;
- }
-
-
- pr_info("init success\n");
- return 0;
-
-no_misc:
- release_region(port, CPU5WDT_EXTENT);
-no_port:
- return err;
-}
-
-static int cpu5wdt_init_module(void)
-{
- return cpu5wdt_init();
-}
-
-static void cpu5wdt_exit(void)
-{
- if (cpu5wdt_device.queue) {
- cpu5wdt_device.queue = 0;
- wait_for_completion(&cpu5wdt_device.stop);
- timer_shutdown_sync(&cpu5wdt_device.timer);
- }
-
- misc_deregister(&cpu5wdt_misc);
-
- release_region(port, CPU5WDT_EXTENT);
-
-}
-
-static void cpu5wdt_exit_module(void)
-{
- cpu5wdt_exit();
-}
-
-/* module entry points */
-
-module_init(cpu5wdt_init_module);
-module_exit(cpu5wdt_exit_module);
-
-MODULE_AUTHOR("Heiko Ronsdorf <hero@ihg.uni-duisburg.de>");
-MODULE_DESCRIPTION("sma cpu5 watchdog driver");
-MODULE_LICENSE("GPL");
-
-module_param_hw(port, int, ioport, 0);
-MODULE_PARM_DESC(port, "base address of watchdog card, default is 0x91");
-
-module_param(verbose, int, 0);
-MODULE_PARM_DESC(verbose, "be verbose, default is 0 (no)");
-
-module_param(ticks, int, 0);
-MODULE_PARM_DESC(ticks, "count down ticks, default is 10000");
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c
index 8ee81f018dda..4fb92c9e046a 100644
--- a/drivers/watchdog/cpwd.c
+++ b/drivers/watchdog/cpwd.c
@@ -653,7 +653,7 @@ static struct platform_driver cpwd_driver = {
.of_match_table = cpwd_match,
},
.probe = cpwd_probe,
- .remove_new = cpwd_remove,
+ .remove = cpwd_remove,
};
module_platform_driver(cpwd_driver);
diff --git a/drivers/watchdog/da9055_wdt.c b/drivers/watchdog/da9055_wdt.c
index 389a4bdd208c..9d5a2009466f 100644
--- a/drivers/watchdog/da9055_wdt.c
+++ b/drivers/watchdog/da9055_wdt.c
@@ -146,12 +146,7 @@ static int da9055_wdt_probe(struct platform_device *pdev)
return ret;
}
- ret = devm_watchdog_register_device(dev, &driver_data->wdt);
- if (ret != 0)
- dev_err(da9055->dev, "watchdog_register_device() failed: %d\n",
- ret);
-
- return ret;
+ return devm_watchdog_register_device(dev, &driver_data->wdt);
}
static struct platform_driver da9055_wdt_driver = {
diff --git a/drivers/watchdog/da9063_wdt.c b/drivers/watchdog/da9063_wdt.c
index 684667469b10..92e1b78ff481 100644
--- a/drivers/watchdog/da9063_wdt.c
+++ b/drivers/watchdog/da9063_wdt.c
@@ -27,7 +27,6 @@
* others: timeout = 2048 ms * 2^(TWDSCALE-1).
*/
static const unsigned int wdt_timeout[] = { 0, 2, 4, 8, 16, 32, 65, 131 };
-static bool use_sw_pm;
#define DA9063_TWDSCALE_DISABLE 0
#define DA9063_TWDSCALE_MIN 1
@@ -230,7 +229,7 @@ static int da9063_wdt_probe(struct platform_device *pdev)
if (!wdd)
return -ENOMEM;
- use_sw_pm = device_property_present(dev, "dlg,use-sw-pm");
+ da9063->use_sw_pm = device_property_present(dev, "dlg,use-sw-pm");
wdd->info = &da9063_watchdog_info;
wdd->ops = &da9063_watchdog_ops;
@@ -264,11 +263,12 @@ static int da9063_wdt_probe(struct platform_device *pdev)
return devm_watchdog_register_device(dev, wdd);
}
-static int __maybe_unused da9063_wdt_suspend(struct device *dev)
+static int da9063_wdt_suspend(struct device *dev)
{
struct watchdog_device *wdd = dev_get_drvdata(dev);
+ struct da9063 *da9063 = watchdog_get_drvdata(wdd);
- if (!use_sw_pm)
+ if (!da9063->use_sw_pm)
return 0;
if (watchdog_active(wdd))
@@ -277,11 +277,12 @@ static int __maybe_unused da9063_wdt_suspend(struct device *dev)
return 0;
}
-static int __maybe_unused da9063_wdt_resume(struct device *dev)
+static int da9063_wdt_resume(struct device *dev)
{
struct watchdog_device *wdd = dev_get_drvdata(dev);
+ struct da9063 *da9063 = watchdog_get_drvdata(wdd);
- if (!use_sw_pm)
+ if (!da9063->use_sw_pm)
return 0;
if (watchdog_active(wdd))
@@ -290,14 +291,14 @@ static int __maybe_unused da9063_wdt_resume(struct device *dev)
return 0;
}
-static SIMPLE_DEV_PM_OPS(da9063_wdt_pm_ops,
- da9063_wdt_suspend, da9063_wdt_resume);
+static DEFINE_SIMPLE_DEV_PM_OPS(da9063_wdt_pm_ops, da9063_wdt_suspend,
+ da9063_wdt_resume);
static struct platform_driver da9063_wdt_driver = {
.probe = da9063_wdt_probe,
.driver = {
.name = DA9063_DRVNAME_WATCHDOG,
- .pm = &da9063_wdt_pm_ops,
+ .pm = pm_sleep_ptr(&da9063_wdt_pm_ops),
},
};
module_platform_driver(da9063_wdt_driver);
diff --git a/drivers/watchdog/dw_wdt.c b/drivers/watchdog/dw_wdt.c
index 84dca3695f86..26efca9ae0e7 100644
--- a/drivers/watchdog/dw_wdt.c
+++ b/drivers/watchdog/dw_wdt.c
@@ -684,7 +684,7 @@ MODULE_DEVICE_TABLE(of, dw_wdt_of_match);
static struct platform_driver dw_wdt_driver = {
.probe = dw_wdt_drv_probe,
- .remove_new = dw_wdt_drv_remove,
+ .remove = dw_wdt_drv_remove,
.driver = {
.name = "dw_wdt",
.of_match_table = of_match_ptr(dw_wdt_of_match),
diff --git a/drivers/watchdog/gef_wdt.c b/drivers/watchdog/gef_wdt.c
index d854fcfbfa5b..bf6f733dfb5f 100644
--- a/drivers/watchdog/gef_wdt.c
+++ b/drivers/watchdog/gef_wdt.c
@@ -305,7 +305,7 @@ static struct platform_driver gef_wdt_driver = {
.of_match_table = gef_wdt_ids,
},
.probe = gef_wdt_probe,
- .remove_new = gef_wdt_remove,
+ .remove = gef_wdt_remove,
};
static int __init gef_wdt_init(void)
diff --git a/drivers/watchdog/geodewdt.c b/drivers/watchdog/geodewdt.c
index 4ed6d139320b..5b80ade1c681 100644
--- a/drivers/watchdog/geodewdt.c
+++ b/drivers/watchdog/geodewdt.c
@@ -248,7 +248,7 @@ static void geodewdt_shutdown(struct platform_device *dev)
}
static struct platform_driver geodewdt_driver = {
- .remove_new = geodewdt_remove,
+ .remove = geodewdt_remove,
.shutdown = geodewdt_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/watchdog/gxp-wdt.c b/drivers/watchdog/gxp-wdt.c
index 2fd85be88278..f2c236160266 100644
--- a/drivers/watchdog/gxp-wdt.c
+++ b/drivers/watchdog/gxp-wdt.c
@@ -151,10 +151,8 @@ static int gxp_wdt_probe(struct platform_device *pdev)
watchdog_stop_on_reboot(&drvdata->wdd);
err = devm_watchdog_register_device(dev, &drvdata->wdd);
- if (err) {
- dev_err(dev, "Failed to register watchdog device");
+ if (err)
return err;
- }
dev_info(dev, "HPE GXP watchdog timer");
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 35b358bcf94c..7672582fa407 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -82,6 +82,13 @@
#define TCO2_CNT(p) (TCOBASE(p) + 0x0a) /* TCO2 Control Register */
#define TCOv2_TMR(p) (TCOBASE(p) + 0x12) /* TCOv2 Timer Initial Value*/
+/*
+ * NMI_NOW is bit 8 of TCO1_CNT register
+ * Read/Write
+ * This bit is implemented as RW but has no effect on HW.
+ */
+#define NMI_NOW BIT(8)
+
/* internal variables */
struct iTCO_wdt_private {
struct watchdog_device wddev;
@@ -219,13 +226,23 @@ static int update_no_reboot_bit_cnt(void *priv, bool set)
struct iTCO_wdt_private *p = priv;
u16 val, newval;
- val = inw(TCO1_CNT(p));
+ /*
+ * writing back 1b1 to NMI_NOW of TCO1_CNT register
+ * causes NMI_NOW bit inversion what consequently does
+ * not allow to perform the register's value comparison
+ * properly.
+ *
+ * NMI_NOW bit masking for TCO1_CNT register values
+ * helps to avoid possible NMI_NOW bit inversions on
+ * following write operation.
+ */
+ val = inw(TCO1_CNT(p)) & ~NMI_NOW;
if (set)
val |= BIT(0);
else
val &= ~BIT(0);
outw(val, TCO1_CNT(p));
- newval = inw(TCO1_CNT(p));
+ newval = inw(TCO1_CNT(p)) & ~NMI_NOW;
/* make sure the update is successful */
return val != newval ? -EIO : 0;
@@ -592,10 +609,8 @@ static int iTCO_wdt_probe(struct platform_device *pdev)
watchdog_stop_on_reboot(&p->wddev);
watchdog_stop_on_unregister(&p->wddev);
ret = devm_watchdog_register_device(dev, &p->wddev);
- if (ret != 0) {
- dev_err(dev, "cannot register watchdog device (err=%d)\n", ret);
+ if (ret != 0)
return ret;
- }
dev_info(dev, "initialized. heartbeat=%d sec (nowayout=%d)\n",
heartbeat, nowayout);
diff --git a/drivers/watchdog/ib700wdt.c b/drivers/watchdog/ib700wdt.c
index b041ad90a62c..5ce6101d236d 100644
--- a/drivers/watchdog/ib700wdt.c
+++ b/drivers/watchdog/ib700wdt.c
@@ -331,7 +331,7 @@ static void ibwdt_shutdown(struct platform_device *dev)
}
static struct platform_driver ibwdt_driver = {
- .remove_new = ibwdt_remove,
+ .remove = ibwdt_remove,
.shutdown = ibwdt_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/watchdog/ie6xx_wdt.c b/drivers/watchdog/ie6xx_wdt.c
index e5cbb409df25..5a7bb7e84653 100644
--- a/drivers/watchdog/ie6xx_wdt.c
+++ b/drivers/watchdog/ie6xx_wdt.c
@@ -280,7 +280,7 @@ static void ie6xx_wdt_remove(struct platform_device *pdev)
static struct platform_driver ie6xx_wdt_driver = {
.probe = ie6xx_wdt_probe,
- .remove_new = ie6xx_wdt_remove,
+ .remove = ie6xx_wdt_remove,
.driver = {
.name = DRIVER_NAME,
},
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index 3e8c15138edd..a1e23dce8810 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -20,6 +20,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <linux/bits.h>
+#include <linux/dmi.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/kernel.h>
@@ -40,6 +42,7 @@
#define VAL 0x2f
/* Logical device Numbers LDN */
+#define EC 0x04
#define GPIO 0x07
/* Configuration Registers and Functions */
@@ -73,6 +76,12 @@
#define IT8784_ID 0x8784
#define IT8786_ID 0x8786
+/* Environment Controller Configuration Registers LDN=0x04 */
+#define SCR1 0xfa
+
+/* Environment Controller Bits SCR1 */
+#define WDT_PWRGD 0x20
+
/* GPIO Configuration Registers LDN=0x07 */
#define WDTCTRL 0x71
#define WDTCFG 0x72
@@ -240,6 +249,21 @@ static int wdt_set_timeout(struct watchdog_device *wdd, unsigned int t)
return ret;
}
+enum {
+ IT87_WDT_OUTPUT_THROUGH_PWRGD = BIT(0),
+};
+
+static const struct dmi_system_id it87_quirks[] = {
+ {
+ /* Qotom Q30900P (IT8786) */
+ .matches = {
+ DMI_EXACT_MATCH(DMI_BOARD_NAME, "QCML04"),
+ },
+ .driver_data = (void *)IT87_WDT_OUTPUT_THROUGH_PWRGD,
+ },
+ {}
+};
+
static const struct watchdog_info ident = {
.options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING,
.firmware_version = 1,
@@ -261,8 +285,10 @@ static struct watchdog_device wdt_dev = {
static int __init it87_wdt_init(void)
{
+ const struct dmi_system_id *dmi_id;
u8 chip_rev;
u8 ctrl;
+ int quirks = 0;
int rc;
rc = superio_enter();
@@ -273,6 +299,10 @@ static int __init it87_wdt_init(void)
chip_rev = superio_inb(CHIPREV) & 0x0f;
superio_exit();
+ dmi_id = dmi_first_match(it87_quirks);
+ if (dmi_id)
+ quirks = (long)dmi_id->driver_data;
+
switch (chip_type) {
case IT8702_ID:
max_units = 255;
@@ -333,6 +363,15 @@ static int __init it87_wdt_init(void)
superio_outb(0x00, WDTCTRL);
}
+ if (quirks & IT87_WDT_OUTPUT_THROUGH_PWRGD) {
+ superio_select(EC);
+ ctrl = superio_inb(SCR1);
+ if (!(ctrl & WDT_PWRGD)) {
+ ctrl |= WDT_PWRGD;
+ superio_outb(ctrl, SCR1);
+ }
+ }
+
superio_exit();
if (timeout < 1 || timeout > max_units * 60) {
@@ -349,10 +388,8 @@ static int __init it87_wdt_init(void)
watchdog_stop_on_reboot(&wdt_dev);
rc = watchdog_register_device(&wdt_dev);
- if (rc) {
- pr_err("Cannot register watchdog device (err=%d)\n", rc);
+ if (rc)
return rc;
- }
pr_info("Chip IT%04x revision %d initialized. timeout=%d sec (nowayout=%d testmode=%d)\n",
chip_type, chip_rev, timeout, nowayout, testmode);
diff --git a/drivers/watchdog/lpc18xx_wdt.c b/drivers/watchdog/lpc18xx_wdt.c
index 19535f4a2fd2..f19580e1b318 100644
--- a/drivers/watchdog/lpc18xx_wdt.c
+++ b/drivers/watchdog/lpc18xx_wdt.c
@@ -281,7 +281,7 @@ static struct platform_driver lpc18xx_wdt_driver = {
.of_match_table = lpc18xx_wdt_match,
},
.probe = lpc18xx_wdt_probe,
- .remove_new = lpc18xx_wdt_remove,
+ .remove = lpc18xx_wdt_remove,
};
module_platform_driver(lpc18xx_wdt_driver);
diff --git a/drivers/watchdog/menz69_wdt.c b/drivers/watchdog/menz69_wdt.c
index 0508a65acfa6..6e5e4e5c0b56 100644
--- a/drivers/watchdog/menz69_wdt.c
+++ b/drivers/watchdog/menz69_wdt.c
@@ -164,4 +164,4 @@ MODULE_AUTHOR("Johannes Thumshirn <jth@kernel.org>");
MODULE_DESCRIPTION("Watchdog driver for the MEN z069 IP-Core");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("mcb:16z069");
-MODULE_IMPORT_NS(MCB);
+MODULE_IMPORT_NS("MCB");
diff --git a/drivers/watchdog/mtk_wdt.c b/drivers/watchdog/mtk_wdt.c
index c35f85ce8d69..91d110646e16 100644
--- a/drivers/watchdog/mtk_wdt.c
+++ b/drivers/watchdog/mtk_wdt.c
@@ -10,6 +10,7 @@
*/
#include <dt-bindings/reset/mt2712-resets.h>
+#include <dt-bindings/reset/mediatek,mt6735-wdt.h>
#include <dt-bindings/reset/mediatek,mt6795-resets.h>
#include <dt-bindings/reset/mt7986-resets.h>
#include <dt-bindings/reset/mt8183-resets.h>
@@ -87,6 +88,10 @@ static const struct mtk_wdt_data mt2712_data = {
.toprgu_sw_rst_num = MT2712_TOPRGU_SW_RST_NUM,
};
+static const struct mtk_wdt_data mt6735_data = {
+ .toprgu_sw_rst_num = MT6735_TOPRGU_RST_NUM,
+};
+
static const struct mtk_wdt_data mt6795_data = {
.toprgu_sw_rst_num = MT6795_TOPRGU_SW_RST_NUM,
};
@@ -225,9 +230,15 @@ static int mtk_wdt_restart(struct watchdog_device *wdt_dev,
{
struct mtk_wdt_dev *mtk_wdt = watchdog_get_drvdata(wdt_dev);
void __iomem *wdt_base;
+ u32 reg;
wdt_base = mtk_wdt->wdt_base;
+ /* Enable reset in order to issue a system reset instead of an IRQ */
+ reg = readl(wdt_base + WDT_MODE);
+ reg &= ~WDT_MODE_IRQ_EN;
+ writel(reg | WDT_MODE_KEY, wdt_base + WDT_MODE);
+
while (1) {
writel(WDT_SWRST_KEY, wdt_base + WDT_SWRST);
mdelay(5);
@@ -483,6 +494,7 @@ static int mtk_wdt_resume(struct device *dev)
static const struct of_device_id mtk_wdt_dt_ids[] = {
{ .compatible = "mediatek,mt2712-wdt", .data = &mt2712_data },
{ .compatible = "mediatek,mt6589-wdt" },
+ { .compatible = "mediatek,mt6735-wdt", .data = &mt6735_data },
{ .compatible = "mediatek,mt6795-wdt", .data = &mt6795_data },
{ .compatible = "mediatek,mt7986-wdt", .data = &mt7986_data },
{ .compatible = "mediatek,mt7988-wdt", .data = &mt7988_data },
diff --git a/drivers/watchdog/mtx-1_wdt.c b/drivers/watchdog/mtx-1_wdt.c
index 11f05024a181..f75426cfa425 100644
--- a/drivers/watchdog/mtx-1_wdt.c
+++ b/drivers/watchdog/mtx-1_wdt.c
@@ -233,7 +233,7 @@ static void mtx1_wdt_remove(struct platform_device *pdev)
static struct platform_driver mtx1_wdt_driver = {
.probe = mtx1_wdt_probe,
- .remove_new = mtx1_wdt_remove,
+ .remove = mtx1_wdt_remove,
.driver.name = "mtx1-wdt",
};
diff --git a/drivers/watchdog/nic7018_wdt.c b/drivers/watchdog/nic7018_wdt.c
index c3f0a4926667..44982b37ba6f 100644
--- a/drivers/watchdog/nic7018_wdt.c
+++ b/drivers/watchdog/nic7018_wdt.c
@@ -236,7 +236,7 @@ MODULE_DEVICE_TABLE(acpi, nic7018_device_ids);
static struct platform_driver watchdog_driver = {
.probe = nic7018_probe,
- .remove_new = nic7018_remove,
+ .remove = nic7018_remove,
.driver = {
.name = KBUILD_MODNAME,
.acpi_match_table = ACPI_PTR(nic7018_device_ids),
diff --git a/drivers/watchdog/nv_tco.c b/drivers/watchdog/nv_tco.c
index f8eb1f65a59e..f16cee5173d5 100644
--- a/drivers/watchdog/nv_tco.c
+++ b/drivers/watchdog/nv_tco.c
@@ -466,7 +466,7 @@ static void nv_tco_shutdown(struct platform_device *dev)
static struct platform_driver nv_tco_driver = {
.probe = nv_tco_init,
- .remove_new = nv_tco_remove,
+ .remove = nv_tco_remove,
.shutdown = nv_tco_shutdown,
.driver = {
.name = TCO_MODULE_NAME,
diff --git a/drivers/watchdog/octeon-wdt-main.c b/drivers/watchdog/octeon-wdt-main.c
index 52d49e4e35a0..0615bb816082 100644
--- a/drivers/watchdog/octeon-wdt-main.c
+++ b/drivers/watchdog/octeon-wdt-main.c
@@ -559,10 +559,8 @@ static int __init octeon_wdt_init(void)
watchdog_set_nowayout(&octeon_wdt, nowayout);
ret = watchdog_register_device(&octeon_wdt);
- if (ret) {
- pr_err("watchdog_register_device() failed: %d\n", ret);
+ if (ret)
return ret;
- }
if (disable) {
pr_notice("disabled\n");
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index b6e0236509bb..d523428a8d22 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -357,7 +357,7 @@ MODULE_DEVICE_TABLE(of, omap_wdt_of_match);
static struct platform_driver omap_wdt_driver = {
.probe = omap_wdt_probe,
- .remove_new = omap_wdt_remove,
+ .remove = omap_wdt_remove,
.shutdown = omap_wdt_shutdown,
.suspend = pm_ptr(omap_wdt_suspend),
.resume = pm_ptr(omap_wdt_resume),
diff --git a/drivers/watchdog/orion_wdt.c b/drivers/watchdog/orion_wdt.c
index 1fe583e8a95b..0e145f762f6f 100644
--- a/drivers/watchdog/orion_wdt.c
+++ b/drivers/watchdog/orion_wdt.c
@@ -665,7 +665,7 @@ static void orion_wdt_shutdown(struct platform_device *pdev)
static struct platform_driver orion_wdt_driver = {
.probe = orion_wdt_probe,
- .remove_new = orion_wdt_remove,
+ .remove = orion_wdt_remove,
.shutdown = orion_wdt_shutdown,
.driver = {
.name = "orion_wdt",
diff --git a/drivers/watchdog/pcwd.c b/drivers/watchdog/pcwd.c
index 1a4282235aac..31d3dcbf815e 100644
--- a/drivers/watchdog/pcwd.c
+++ b/drivers/watchdog/pcwd.c
@@ -833,7 +833,7 @@ static int pcwd_isa_match(struct device *dev, unsigned int id)
port0 = inb_p(base_addr);
port1 = inb_p(base_addr + 1);
- /* Has either hearbeat bit changed? */
+ /* Has either heartbeat bit changed? */
if ((port0 ^ last_port0) & WD_HRTBT ||
(port1 ^ last_port1) & WD_REVC_HRBT) {
retval = 1;
diff --git a/drivers/watchdog/rc32434_wdt.c b/drivers/watchdog/rc32434_wdt.c
index efadbb9d7ce7..0e5c5c96af58 100644
--- a/drivers/watchdog/rc32434_wdt.c
+++ b/drivers/watchdog/rc32434_wdt.c
@@ -309,7 +309,7 @@ static void rc32434_wdt_shutdown(struct platform_device *pdev)
static struct platform_driver rc32434_wdt_driver = {
.probe = rc32434_wdt_probe,
- .remove_new = rc32434_wdt_remove,
+ .remove = rc32434_wdt_remove,
.shutdown = rc32434_wdt_shutdown,
.driver = {
.name = "rc32434_wdt",
diff --git a/drivers/watchdog/rdc321x_wdt.c b/drivers/watchdog/rdc321x_wdt.c
index 80490316a27f..8955177072fa 100644
--- a/drivers/watchdog/rdc321x_wdt.c
+++ b/drivers/watchdog/rdc321x_wdt.c
@@ -268,7 +268,7 @@ static void rdc321x_wdt_remove(struct platform_device *pdev)
static struct platform_driver rdc321x_wdt_driver = {
.probe = rdc321x_wdt_probe,
- .remove_new = rdc321x_wdt_remove,
+ .remove = rdc321x_wdt_remove,
.driver = {
.name = "rdc321x-wdt",
},
diff --git a/drivers/watchdog/renesas_wdt.c b/drivers/watchdog/renesas_wdt.c
index 12c41d6e5cd6..c0b2a9c5250d 100644
--- a/drivers/watchdog/renesas_wdt.c
+++ b/drivers/watchdog/renesas_wdt.c
@@ -337,7 +337,7 @@ static struct platform_driver rwdt_driver = {
.pm = &rwdt_pm_ops,
},
.probe = rwdt_probe,
- .remove_new = rwdt_remove,
+ .remove = rwdt_remove,
};
module_platform_driver(rwdt_driver);
diff --git a/drivers/watchdog/riowd.c b/drivers/watchdog/riowd.c
index f47d90d01c19..83806ccf06d1 100644
--- a/drivers/watchdog/riowd.c
+++ b/drivers/watchdog/riowd.c
@@ -238,7 +238,7 @@ static struct platform_driver riowd_driver = {
.of_match_table = riowd_match,
},
.probe = riowd_probe,
- .remove_new = riowd_remove,
+ .remove = riowd_remove,
};
module_platform_driver(riowd_driver);
diff --git a/drivers/watchdog/rti_wdt.c b/drivers/watchdog/rti_wdt.c
index 4895a69015a8..58c9445c0f88 100644
--- a/drivers/watchdog/rti_wdt.c
+++ b/drivers/watchdog/rti_wdt.c
@@ -61,7 +61,7 @@
#define MAX_HW_ERROR 250
-static int heartbeat = DEFAULT_HEARTBEAT;
+static int heartbeat;
/*
* struct to hold data for each WDT device
@@ -252,6 +252,7 @@ static int rti_wdt_probe(struct platform_device *pdev)
wdd->min_timeout = 1;
wdd->max_hw_heartbeat_ms = (WDT_PRELOAD_MAX << WDT_PRELOAD_SHIFT) /
wdt->freq * 1000;
+ wdd->timeout = DEFAULT_HEARTBEAT;
wdd->parent = dev;
watchdog_set_drvdata(wdd, wdt);
@@ -336,10 +337,8 @@ static int rti_wdt_probe(struct platform_device *pdev)
watchdog_init_timeout(wdd, heartbeat, dev);
ret = watchdog_register_device(wdd);
- if (ret) {
- dev_err(dev, "cannot register watchdog device\n");
+ if (ret)
goto err_iomap;
- }
if (last_ping)
watchdog_set_last_hw_keepalive(wdd, last_ping);
@@ -380,7 +379,7 @@ static struct platform_driver rti_wdt_driver = {
.of_match_table = rti_wdt_of_match,
},
.probe = rti_wdt_probe,
- .remove_new = rti_wdt_remove,
+ .remove = rti_wdt_remove,
};
module_platform_driver(rti_wdt_driver);
diff --git a/drivers/watchdog/rza_wdt.c b/drivers/watchdog/rza_wdt.c
index cb4901b3f777..9334255a37e9 100644
--- a/drivers/watchdog/rza_wdt.c
+++ b/drivers/watchdog/rza_wdt.c
@@ -169,7 +169,6 @@ static int rza_wdt_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct rza_wdt *priv;
unsigned long rate;
- int ret;
priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
if (!priv)
@@ -218,11 +217,7 @@ static int rza_wdt_probe(struct platform_device *pdev)
watchdog_init_timeout(&priv->wdev, 0, dev);
watchdog_set_drvdata(&priv->wdev, priv);
- ret = devm_watchdog_register_device(dev, &priv->wdev);
- if (ret)
- dev_err(dev, "Cannot register watchdog device\n");
-
- return ret;
+ return devm_watchdog_register_device(dev, &priv->wdev);
}
static const struct of_device_id rza_wdt_of_match[] = {
diff --git a/drivers/watchdog/rzg2l_wdt.c b/drivers/watchdog/rzg2l_wdt.c
index 2a35f890a288..11bbe48160ec 100644
--- a/drivers/watchdog/rzg2l_wdt.c
+++ b/drivers/watchdog/rzg2l_wdt.c
@@ -12,6 +12,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/pm_domain.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/units.h>
@@ -166,8 +167,22 @@ static int rzg2l_wdt_restart(struct watchdog_device *wdev,
struct rzg2l_wdt_priv *priv = watchdog_get_drvdata(wdev);
int ret;
- clk_prepare_enable(priv->pclk);
- clk_prepare_enable(priv->osc_clk);
+ /*
+ * In case of RZ/G3S the watchdog device may be part of an IRQ safe power
+ * domain that is currently powered off. In this case we need to power
+ * it on before accessing registers. Along with this the clocks will be
+ * enabled. We don't undo the pm_runtime_resume_and_get() as the device
+ * need to be on for the reboot to happen.
+ *
+ * For the rest of SoCs not registering a watchdog IRQ safe power
+ * domain it is safe to call pm_runtime_resume_and_get() as the
+ * irq_safe_dev_in_sleep_domain() call in genpd_runtime_resume()
+ * returns non zero value and the genpd_lock() is avoided, thus, there
+ * will be no invalid wait context reported by lockdep.
+ */
+ ret = pm_runtime_resume_and_get(wdev->parent);
+ if (ret)
+ return ret;
if (priv->devtype == WDT_RZG2L) {
ret = reset_control_deassert(priv->rstc);
@@ -275,6 +290,7 @@ static int rzg2l_wdt_probe(struct platform_device *pdev)
priv->devtype = (uintptr_t)of_device_get_match_data(dev);
+ pm_runtime_irq_safe(&pdev->dev);
pm_runtime_enable(&pdev->dev);
priv->wdev.info = &rzg2l_wdt_ident;
diff --git a/drivers/watchdog/rzn1_wdt.c b/drivers/watchdog/rzn1_wdt.c
index 7d3192d34afd..96fd04fbc2a2 100644
--- a/drivers/watchdog/rzn1_wdt.c
+++ b/drivers/watchdog/rzn1_wdt.c
@@ -52,7 +52,7 @@ static int rzn1_wdt_ping(struct watchdog_device *w)
{
struct rzn1_watchdog *wdt = watchdog_get_drvdata(w);
- /* Any value retrigggers the watchdog */
+ /* Any value retriggers the watchdog */
writel(0, wdt->base + RZN1_WDT_RETRIGGER);
return 0;
diff --git a/drivers/watchdog/s3c2410_wdt.c b/drivers/watchdog/s3c2410_wdt.c
index 686cf544d0ae..30450e99e5e9 100644
--- a/drivers/watchdog/s3c2410_wdt.c
+++ b/drivers/watchdog/s3c2410_wdt.c
@@ -24,9 +24,9 @@
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/of.h>
+#include <linux/mfd/syscon.h>
#include <linux/regmap.h>
#include <linux/delay.h>
-#include <linux/soc/samsung/exynos-pmu.h>
#define S3C2410_WTCON 0x00
#define S3C2410_WTDAT 0x04
@@ -63,6 +63,10 @@
#define EXYNOS850_CLUSTER1_NONCPU_INT_EN 0x1644
#define EXYNOSAUTOV9_CLUSTER1_NONCPU_OUT 0x1520
#define EXYNOSAUTOV9_CLUSTER1_NONCPU_INT_EN 0x1544
+#define EXYNOSAUTOV920_CLUSTER0_NONCPU_OUT 0x1420
+#define EXYNOSAUTOV920_CLUSTER0_NONCPU_INT_EN 0x1444
+#define EXYNOSAUTOV920_CLUSTER1_NONCPU_OUT 0x1720
+#define EXYNOSAUTOV920_CLUSTER1_NONCPU_INT_EN 0x1744
#define EXYNOS850_CLUSTER0_WDTRESET_BIT 24
#define EXYNOS850_CLUSTER1_WDTRESET_BIT 23
@@ -303,6 +307,32 @@ static const struct s3c2410_wdt_variant drv_data_gs101_cl1 = {
QUIRK_HAS_DBGACK_BIT,
};
+static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl0 = {
+ .mask_reset_reg = EXYNOSAUTOV920_CLUSTER0_NONCPU_INT_EN,
+ .mask_bit = 2,
+ .mask_reset_inv = true,
+ .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
+ .rst_stat_bit = EXYNOSAUTOV9_CLUSTER0_WDTRESET_BIT,
+ .cnt_en_reg = EXYNOSAUTOV920_CLUSTER0_NONCPU_OUT,
+ .cnt_en_bit = 7,
+ .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
+ QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
+ QUIRK_HAS_DBGACK_BIT,
+};
+
+static const struct s3c2410_wdt_variant drv_data_exynosautov920_cl1 = {
+ .mask_reset_reg = EXYNOSAUTOV920_CLUSTER1_NONCPU_INT_EN,
+ .mask_bit = 2,
+ .mask_reset_inv = true,
+ .rst_stat_reg = EXYNOS5_RST_STAT_REG_OFFSET,
+ .rst_stat_bit = EXYNOSAUTOV9_CLUSTER1_WDTRESET_BIT,
+ .cnt_en_reg = EXYNOSAUTOV920_CLUSTER1_NONCPU_OUT,
+ .cnt_en_bit = 7,
+ .quirks = QUIRK_HAS_WTCLRINT_REG | QUIRK_HAS_PMU_MASK_RESET |
+ QUIRK_HAS_PMU_RST_STAT | QUIRK_HAS_PMU_CNT_EN |
+ QUIRK_HAS_DBGACK_BIT,
+};
+
static const struct of_device_id s3c2410_wdt_match[] = {
{ .compatible = "google,gs101-wdt",
.data = &drv_data_gs101_cl0 },
@@ -320,6 +350,8 @@ static const struct of_device_id s3c2410_wdt_match[] = {
.data = &drv_data_exynos850_cl0 },
{ .compatible = "samsung,exynosautov9-wdt",
.data = &drv_data_exynosautov9_cl0 },
+ { .compatible = "samsung,exynosautov920-wdt",
+ .data = &drv_data_exynosautov920_cl0 },
{},
};
MODULE_DEVICE_TABLE(of, s3c2410_wdt_match);
@@ -643,7 +675,8 @@ s3c2410_get_wdt_drv_data(struct platform_device *pdev, struct s3c2410_wdt *wdt)
/* Choose Exynos850/ExynosAutov9 driver data w.r.t. cluster index */
if (variant == &drv_data_exynos850_cl0 ||
variant == &drv_data_exynosautov9_cl0 ||
- variant == &drv_data_gs101_cl0) {
+ variant == &drv_data_gs101_cl0 ||
+ variant == &drv_data_exynosautov920_cl0) {
u32 index;
int err;
@@ -662,6 +695,8 @@ s3c2410_get_wdt_drv_data(struct platform_device *pdev, struct s3c2410_wdt *wdt)
variant = &drv_data_exynosautov9_cl1;
else if (variant == &drv_data_gs101_cl0)
variant = &drv_data_gs101_cl1;
+ else if (variant == &drv_data_exynosautov920_cl0)
+ variant = &drv_data_exynosautov920_cl1;
break;
default:
return dev_err_probe(dev, -EINVAL, "wrong cluster index: %u\n", index);
@@ -699,11 +734,11 @@ static int s3c2410wdt_probe(struct platform_device *pdev)
return ret;
if (wdt->drv_data->quirks & QUIRKS_HAVE_PMUREG) {
- wdt->pmureg = exynos_get_pmu_regmap_by_phandle(dev->of_node,
- "samsung,syscon-phandle");
+ wdt->pmureg = syscon_regmap_lookup_by_phandle(dev->of_node,
+ "samsung,syscon-phandle");
if (IS_ERR(wdt->pmureg))
return dev_err_probe(dev, PTR_ERR(wdt->pmureg),
- "PMU regmap lookup failed.\n");
+ "syscon regmap lookup failed.\n");
}
wdt_irq = platform_get_irq(pdev, 0);
diff --git a/drivers/watchdog/sa1100_wdt.c b/drivers/watchdog/sa1100_wdt.c
index 6e91ee3fbfb5..729a8508b31d 100644
--- a/drivers/watchdog/sa1100_wdt.c
+++ b/drivers/watchdog/sa1100_wdt.c
@@ -236,8 +236,8 @@ static void sa1100dog_remove(struct platform_device *pdev)
static struct platform_driver sa1100dog_driver = {
.driver.name = "sa1100_wdt",
- .probe = sa1100dog_probe,
- .remove_new = sa1100dog_remove,
+ .probe = sa1100dog_probe,
+ .remove = sa1100dog_remove,
};
module_platform_driver(sa1100dog_driver);
diff --git a/drivers/watchdog/sch311x_wdt.c b/drivers/watchdog/sch311x_wdt.c
index 76053158d259..9670a1ea57cb 100644
--- a/drivers/watchdog/sch311x_wdt.c
+++ b/drivers/watchdog/sch311x_wdt.c
@@ -445,7 +445,7 @@ static void sch311x_wdt_shutdown(struct platform_device *dev)
static struct platform_driver sch311x_wdt_driver = {
.probe = sch311x_wdt_probe,
- .remove_new = sch311x_wdt_remove,
+ .remove = sch311x_wdt_remove,
.shutdown = sch311x_wdt_shutdown,
.driver = {
.name = DRV_NAME,
diff --git a/drivers/watchdog/shwdt.c b/drivers/watchdog/shwdt.c
index 10f1fba78ec2..7f0150c39421 100644
--- a/drivers/watchdog/shwdt.c
+++ b/drivers/watchdog/shwdt.c
@@ -297,7 +297,7 @@ static struct platform_driver sh_wdt_driver = {
},
.probe = sh_wdt_probe,
- .remove_new = sh_wdt_remove,
+ .remove = sh_wdt_remove,
.shutdown = sh_wdt_shutdown,
};
diff --git a/drivers/watchdog/sl28cpld_wdt.c b/drivers/watchdog/sl28cpld_wdt.c
index 9ce456f09f73..8630c29818f2 100644
--- a/drivers/watchdog/sl28cpld_wdt.c
+++ b/drivers/watchdog/sl28cpld_wdt.c
@@ -198,10 +198,8 @@ static int sl28cpld_wdt_probe(struct platform_device *pdev)
}
ret = devm_watchdog_register_device(&pdev->dev, wdd);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to register watchdog device\n");
+ if (ret < 0)
return ret;
- }
dev_info(&pdev->dev, "initial timeout %d sec%s\n",
wdd->timeout, nowayout ? ", nowayout" : "");
diff --git a/drivers/watchdog/smsc37b787_wdt.c b/drivers/watchdog/smsc37b787_wdt.c
index 97ca500ec8a8..3011e1af00f9 100644
--- a/drivers/watchdog/smsc37b787_wdt.c
+++ b/drivers/watchdog/smsc37b787_wdt.c
@@ -485,7 +485,7 @@ static long wb_smsc_wdt_ioctl(struct file *file,
}
}
-/* -- Notifier funtions -----------------------------------------*/
+/* -- Notifier functions -----------------------------------------*/
static int wb_smsc_wdt_notify_sys(struct notifier_block *this,
unsigned long code, void *unused)
diff --git a/drivers/watchdog/st_lpc_wdt.c b/drivers/watchdog/st_lpc_wdt.c
index 4c5b8d98a4f3..d206452072ae 100644
--- a/drivers/watchdog/st_lpc_wdt.c
+++ b/drivers/watchdog/st_lpc_wdt.c
@@ -286,7 +286,7 @@ static struct platform_driver st_wdog_driver = {
.of_match_table = st_wdog_match,
},
.probe = st_wdog_probe,
- .remove_new = st_wdog_remove,
+ .remove = st_wdog_remove,
};
module_platform_driver(st_wdog_driver);
diff --git a/drivers/watchdog/starfive-wdt.c b/drivers/watchdog/starfive-wdt.c
index 19a2620d3d38..355918d62f63 100644
--- a/drivers/watchdog/starfive-wdt.c
+++ b/drivers/watchdog/starfive-wdt.c
@@ -80,7 +80,7 @@ MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started (default="
__MODULE_STRING(WATCHDOG_NOWAYOUT) ")");
struct starfive_wdt_variant {
- unsigned int control; /* Watchdog Control Resgister for reset enable */
+ unsigned int control; /* Watchdog Control Register for reset enable */
unsigned int load; /* Watchdog Load register */
unsigned int reload; /* Watchdog Reload Control register */
unsigned int enable; /* Watchdog Enable Register */
@@ -597,7 +597,7 @@ MODULE_DEVICE_TABLE(of, starfive_wdt_match);
static struct platform_driver starfive_wdt_driver = {
.probe = starfive_wdt_probe,
- .remove_new = starfive_wdt_remove,
+ .remove = starfive_wdt_remove,
.shutdown = starfive_wdt_shutdown,
.driver = {
.name = "starfive-wdt",
diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index 5404e0387620..8ad06b54c5ad 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
+#include <linux/pm_wakeirq.h>
#include <linux/watchdog.h>
#define DEFAULT_TIMEOUT 10
@@ -28,6 +29,7 @@
#define IWDG_RLR 0x08 /* ReLoad Register */
#define IWDG_SR 0x0C /* Status Register */
#define IWDG_WINR 0x10 /* Windows Register */
+#define IWDG_EWCR 0x14 /* Early Wake-up Register */
/* IWDG_KR register bit mask */
#define KR_KEY_RELOAD 0xAAAA /* reload counter enable */
@@ -47,22 +49,29 @@
#define SR_PVU BIT(0) /* Watchdog prescaler value update */
#define SR_RVU BIT(1) /* Watchdog counter reload value update */
+#define EWCR_EWIT GENMASK(11, 0) /* Watchdog counter window value */
+#define EWCR_EWIC BIT(14) /* Watchdog early interrupt acknowledge */
+#define EWCR_EWIE BIT(15) /* Watchdog early interrupt enable */
+
/* set timeout to 100000 us */
#define TIMEOUT_US 100000
#define SLEEP_US 1000
struct stm32_iwdg_data {
bool has_pclk;
+ bool has_early_wakeup;
u32 max_prescaler;
};
static const struct stm32_iwdg_data stm32_iwdg_data = {
.has_pclk = false,
+ .has_early_wakeup = false,
.max_prescaler = 256,
};
static const struct stm32_iwdg_data stm32mp1_iwdg_data = {
.has_pclk = true,
+ .has_early_wakeup = true,
.max_prescaler = 1024,
};
@@ -88,13 +97,18 @@ static inline void reg_write(void __iomem *base, u32 reg, u32 val)
static int stm32_iwdg_start(struct watchdog_device *wdd)
{
struct stm32_iwdg *wdt = watchdog_get_drvdata(wdd);
- u32 tout, presc, iwdg_rlr, iwdg_pr, iwdg_sr;
+ u32 tout, ptot, presc, iwdg_rlr, iwdg_ewcr, iwdg_pr, iwdg_sr;
int ret;
dev_dbg(wdd->parent, "%s\n", __func__);
+ if (!wdd->pretimeout)
+ wdd->pretimeout = 3 * wdd->timeout / 4;
+
tout = clamp_t(unsigned int, wdd->timeout,
wdd->min_timeout, wdd->max_hw_heartbeat_ms / 1000);
+ ptot = clamp_t(unsigned int, tout - wdd->pretimeout,
+ wdd->min_timeout, tout);
presc = DIV_ROUND_UP(tout * wdt->rate, RLR_MAX + 1);
@@ -102,6 +116,7 @@ static int stm32_iwdg_start(struct watchdog_device *wdd)
presc = roundup_pow_of_two(presc);
iwdg_pr = presc <= 1 << PR_SHIFT ? 0 : ilog2(presc) - PR_SHIFT;
iwdg_rlr = ((tout * wdt->rate) / presc) - 1;
+ iwdg_ewcr = ((ptot * wdt->rate) / presc) - 1;
/* enable write access */
reg_write(wdt->regs, IWDG_KR, KR_KEY_EWA);
@@ -109,6 +124,8 @@ static int stm32_iwdg_start(struct watchdog_device *wdd)
/* set prescaler & reload registers */
reg_write(wdt->regs, IWDG_PR, iwdg_pr);
reg_write(wdt->regs, IWDG_RLR, iwdg_rlr);
+ if (wdt->data->has_early_wakeup)
+ reg_write(wdt->regs, IWDG_EWCR, iwdg_ewcr | EWCR_EWIE);
reg_write(wdt->regs, IWDG_KR, KR_KEY_ENABLE);
/* wait for the registers to be updated (max 100ms) */
@@ -151,6 +168,34 @@ static int stm32_iwdg_set_timeout(struct watchdog_device *wdd,
return 0;
}
+static int stm32_iwdg_set_pretimeout(struct watchdog_device *wdd,
+ unsigned int pretimeout)
+{
+ dev_dbg(wdd->parent, "%s pretimeout: %d sec\n", __func__, pretimeout);
+
+ wdd->pretimeout = pretimeout;
+
+ if (watchdog_active(wdd))
+ return stm32_iwdg_start(wdd);
+
+ return 0;
+}
+
+static irqreturn_t stm32_iwdg_isr(int irq, void *wdog_arg)
+{
+ struct watchdog_device *wdd = wdog_arg;
+ struct stm32_iwdg *wdt = watchdog_get_drvdata(wdd);
+ u32 reg;
+
+ reg = reg_read(wdt->regs, IWDG_EWCR);
+ reg |= EWCR_EWIC;
+ reg_write(wdt->regs, IWDG_EWCR, reg);
+
+ watchdog_notify_pretimeout(wdd);
+
+ return IRQ_HANDLED;
+}
+
static void stm32_clk_disable_unprepare(void *data)
{
clk_disable_unprepare(data);
@@ -207,11 +252,20 @@ static const struct watchdog_info stm32_iwdg_info = {
.identity = "STM32 Independent Watchdog",
};
+static const struct watchdog_info stm32_iwdg_preinfo = {
+ .options = WDIOF_SETTIMEOUT |
+ WDIOF_MAGICCLOSE |
+ WDIOF_KEEPALIVEPING |
+ WDIOF_PRETIMEOUT,
+ .identity = "STM32 Independent Watchdog",
+};
+
static const struct watchdog_ops stm32_iwdg_ops = {
.owner = THIS_MODULE,
.start = stm32_iwdg_start,
.ping = stm32_iwdg_ping,
.set_timeout = stm32_iwdg_set_timeout,
+ .set_pretimeout = stm32_iwdg_set_pretimeout,
};
static const struct of_device_id stm32_iwdg_of_match[] = {
@@ -221,6 +275,40 @@ static const struct of_device_id stm32_iwdg_of_match[] = {
};
MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
+static int stm32_iwdg_irq_init(struct platform_device *pdev,
+ struct stm32_iwdg *wdt)
+{
+ struct device_node *np = pdev->dev.of_node;
+ struct watchdog_device *wdd = &wdt->wdd;
+ struct device *dev = &pdev->dev;
+ int irq, ret;
+
+ if (!wdt->data->has_early_wakeup)
+ return 0;
+
+ irq = platform_get_irq_optional(pdev, 0);
+ if (irq <= 0)
+ return 0;
+
+ if (of_property_read_bool(np, "wakeup-source")) {
+ ret = device_init_wakeup(dev, true);
+ if (ret)
+ return ret;
+
+ ret = dev_pm_set_wake_irq(dev, irq);
+ if (ret)
+ return ret;
+ }
+
+ ret = devm_request_irq(dev, irq, stm32_iwdg_isr, 0,
+ dev_name(dev), wdd);
+ if (ret)
+ return ret;
+
+ wdd->info = &stm32_iwdg_preinfo;
+ return 0;
+}
+
static int stm32_iwdg_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
@@ -255,6 +343,11 @@ static int stm32_iwdg_probe(struct platform_device *pdev)
wdd->max_hw_heartbeat_ms = ((RLR_MAX + 1) * wdt->data->max_prescaler *
1000) / wdt->rate;
+ /* Initialize IRQ, this might override wdd->info, hence it is here. */
+ ret = stm32_iwdg_irq_init(pdev, wdt);
+ if (ret)
+ return ret;
+
watchdog_set_drvdata(wdd, wdt);
watchdog_set_nowayout(wdd, WATCHDOG_NOWAYOUT);
watchdog_init_timeout(wdd, 0, dev);
diff --git a/drivers/watchdog/stmp3xxx_rtc_wdt.c b/drivers/watchdog/stmp3xxx_rtc_wdt.c
index 4b2caa9807ac..060447101f48 100644
--- a/drivers/watchdog/stmp3xxx_rtc_wdt.c
+++ b/drivers/watchdog/stmp3xxx_rtc_wdt.c
@@ -143,7 +143,7 @@ static struct platform_driver stmp3xxx_wdt_driver = {
.pm = &stmp3xxx_wdt_pm_ops,
},
.probe = stmp3xxx_wdt_probe,
- .remove_new = stmp3xxx_wdt_remove,
+ .remove = stmp3xxx_wdt_remove,
};
module_platform_driver(stmp3xxx_wdt_driver);
diff --git a/drivers/watchdog/txx9wdt.c b/drivers/watchdog/txx9wdt.c
index 8d5f67acbff2..305349844b4f 100644
--- a/drivers/watchdog/txx9wdt.c
+++ b/drivers/watchdog/txx9wdt.c
@@ -159,7 +159,7 @@ static void txx9wdt_shutdown(struct platform_device *dev)
static struct platform_driver txx9wdt_driver = {
.probe = txx9wdt_probe,
- .remove_new = txx9wdt_remove,
+ .remove = txx9wdt_remove,
.shutdown = txx9wdt_shutdown,
.driver = {
.name = "txx9wdt",
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index aff2c3912ead..d46d8c8c01f2 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -237,7 +237,7 @@ void watchdog_set_restart_priority(struct watchdog_device *wdd, int priority)
}
EXPORT_SYMBOL_GPL(watchdog_set_restart_priority);
-static int __watchdog_register_device(struct watchdog_device *wdd)
+static int ___watchdog_register_device(struct watchdog_device *wdd)
{
int ret, id = -1;
@@ -337,6 +337,22 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
return 0;
}
+static int __watchdog_register_device(struct watchdog_device *wdd)
+{
+ const char *dev_str;
+ int ret;
+
+ ret = ___watchdog_register_device(wdd);
+ if (ret) {
+ dev_str = wdd->parent ? dev_name(wdd->parent) :
+ (const char *)wdd->info->identity;
+ pr_err("%s: failed to register watchdog device (err = %d)\n",
+ dev_str, ret);
+ }
+
+ return ret;
+}
+
/**
* watchdog_register_device() - register a watchdog device
* @wdd: watchdog device
@@ -350,7 +366,6 @@ static int __watchdog_register_device(struct watchdog_device *wdd)
int watchdog_register_device(struct watchdog_device *wdd)
{
- const char *dev_str;
int ret = 0;
mutex_lock(&wtd_deferred_reg_mutex);
@@ -360,13 +375,6 @@ int watchdog_register_device(struct watchdog_device *wdd)
watchdog_deferred_registration_add(wdd);
mutex_unlock(&wtd_deferred_reg_mutex);
- if (ret) {
- dev_str = wdd->parent ? dev_name(wdd->parent) :
- (const char *)wdd->info->identity;
- pr_err("%s: failed to register watchdog device (err = %d)\n",
- dev_str, ret);
- }
-
return ret;
}
EXPORT_SYMBOL_GPL(watchdog_register_device);
diff --git a/drivers/watchdog/xilinx_wwdt.c b/drivers/watchdog/xilinx_wwdt.c
index d271e2e8d6e2..3d2a156f7180 100644
--- a/drivers/watchdog/xilinx_wwdt.c
+++ b/drivers/watchdog/xilinx_wwdt.c
@@ -2,7 +2,7 @@
/*
* Window watchdog device driver for Xilinx Versal WWDT
*
- * Copyright (C) 2022 - 2023, Advanced Micro Devices, Inc.
+ * Copyright (C) 2022 - 2024, Advanced Micro Devices, Inc.
*/
#include <linux/clk.h>
@@ -36,6 +36,12 @@
#define XWWDT_CLOSE_WINDOW_PERCENT 50
+/* Maximum count value of each 32 bit window */
+#define XWWDT_MAX_COUNT_WINDOW GENMASK(31, 0)
+
+/* Maximum count value of closed and open window combined */
+#define XWWDT_MAX_COUNT_WINDOW_COMBINED GENMASK_ULL(32, 1)
+
static int wwdt_timeout;
static int closed_window_percent;
@@ -54,6 +60,8 @@ MODULE_PARM_DESC(closed_window_percent,
* @xilinx_wwdt_wdd: watchdog device structure
* @freq: source clock frequency of WWDT
* @close_percent: Closed window percent
+ * @closed_timeout: Closed window timeout in ticks
+ * @open_timeout: Open window timeout in ticks
*/
struct xwwdt_device {
void __iomem *base;
@@ -61,27 +69,22 @@ struct xwwdt_device {
struct watchdog_device xilinx_wwdt_wdd;
unsigned long freq;
u32 close_percent;
+ u64 closed_timeout;
+ u64 open_timeout;
};
static int xilinx_wwdt_start(struct watchdog_device *wdd)
{
struct xwwdt_device *xdev = watchdog_get_drvdata(wdd);
struct watchdog_device *xilinx_wwdt_wdd = &xdev->xilinx_wwdt_wdd;
- u64 time_out, closed_timeout, open_timeout;
u32 control_status_reg;
- /* Calculate timeout count */
- time_out = xdev->freq * wdd->timeout;
- closed_timeout = div_u64(time_out * xdev->close_percent, 100);
- open_timeout = time_out - closed_timeout;
- wdd->min_hw_heartbeat_ms = xdev->close_percent * 10 * wdd->timeout;
-
spin_lock(&xdev->spinlock);
iowrite32(XWWDT_MWR_MASK, xdev->base + XWWDT_MWR_OFFSET);
iowrite32(~(u32)XWWDT_ESR_WEN_MASK, xdev->base + XWWDT_ESR_OFFSET);
- iowrite32((u32)closed_timeout, xdev->base + XWWDT_FWR_OFFSET);
- iowrite32((u32)open_timeout, xdev->base + XWWDT_SWR_OFFSET);
+ iowrite32((u32)xdev->closed_timeout, xdev->base + XWWDT_FWR_OFFSET);
+ iowrite32((u32)xdev->open_timeout, xdev->base + XWWDT_SWR_OFFSET);
/* Enable the window watchdog timer */
control_status_reg = ioread32(xdev->base + XWWDT_ESR_OFFSET);
@@ -133,7 +136,12 @@ static int xwwdt_probe(struct platform_device *pdev)
struct watchdog_device *xilinx_wwdt_wdd;
struct device *dev = &pdev->dev;
struct xwwdt_device *xdev;
+ u64 max_per_window_ms;
+ u64 min_per_window_ms;
+ u64 timeout_count;
struct clk *clk;
+ u32 timeout_ms;
+ u64 ms_count;
int ret;
xdev = devm_kzalloc(dev, sizeof(*xdev), GFP_KERNEL);
@@ -154,12 +162,13 @@ static int xwwdt_probe(struct platform_device *pdev)
return PTR_ERR(clk);
xdev->freq = clk_get_rate(clk);
- if (!xdev->freq)
+ if (xdev->freq < 1000000)
return -EINVAL;
xilinx_wwdt_wdd->min_timeout = XWWDT_MIN_TIMEOUT;
xilinx_wwdt_wdd->timeout = XWWDT_DEFAULT_TIMEOUT;
- xilinx_wwdt_wdd->max_hw_heartbeat_ms = 1000 * xilinx_wwdt_wdd->timeout;
+ xilinx_wwdt_wdd->max_hw_heartbeat_ms =
+ div64_u64(XWWDT_MAX_COUNT_WINDOW_COMBINED, xdev->freq) * 1000;
if (closed_window_percent == 0 || closed_window_percent >= 100)
xdev->close_percent = XWWDT_CLOSE_WINDOW_PERCENT;
@@ -167,6 +176,48 @@ static int xwwdt_probe(struct platform_device *pdev)
xdev->close_percent = closed_window_percent;
watchdog_init_timeout(xilinx_wwdt_wdd, wwdt_timeout, &pdev->dev);
+
+ /* Calculate ticks for 1 milli-second */
+ ms_count = div_u64(xdev->freq, 1000);
+ timeout_ms = xilinx_wwdt_wdd->timeout * 1000;
+ timeout_count = timeout_ms * ms_count;
+
+ if (timeout_ms > xilinx_wwdt_wdd->max_hw_heartbeat_ms) {
+ /*
+ * To avoid ping restrictions until the minimum hardware heartbeat,
+ * we will solely rely on the open window and
+ * adjust the minimum hardware heartbeat to 0.
+ */
+ xdev->closed_timeout = 0;
+ xdev->open_timeout = XWWDT_MAX_COUNT_WINDOW;
+ xilinx_wwdt_wdd->min_hw_heartbeat_ms = 0;
+ xilinx_wwdt_wdd->max_hw_heartbeat_ms = xilinx_wwdt_wdd->max_hw_heartbeat_ms / 2;
+ } else {
+ xdev->closed_timeout = div64_u64(timeout_count * xdev->close_percent, 100);
+ xilinx_wwdt_wdd->min_hw_heartbeat_ms =
+ div64_u64(timeout_ms * xdev->close_percent, 100);
+
+ if (timeout_ms > xilinx_wwdt_wdd->max_hw_heartbeat_ms / 2) {
+ max_per_window_ms = xilinx_wwdt_wdd->max_hw_heartbeat_ms / 2;
+ min_per_window_ms = timeout_ms - max_per_window_ms;
+
+ if (xilinx_wwdt_wdd->min_hw_heartbeat_ms > max_per_window_ms) {
+ dev_info(xilinx_wwdt_wdd->parent,
+ "Closed window cannot be set to %d%%. Using maximum supported value.\n",
+ xdev->close_percent);
+ xdev->closed_timeout = max_per_window_ms * ms_count;
+ xilinx_wwdt_wdd->min_hw_heartbeat_ms = max_per_window_ms;
+ } else if (xilinx_wwdt_wdd->min_hw_heartbeat_ms < min_per_window_ms) {
+ dev_info(xilinx_wwdt_wdd->parent,
+ "Closed window cannot be set to %d%%. Using minimum supported value.\n",
+ xdev->close_percent);
+ xdev->closed_timeout = min_per_window_ms * ms_count;
+ xilinx_wwdt_wdd->min_hw_heartbeat_ms = min_per_window_ms;
+ }
+ }
+ xdev->open_timeout = timeout_count - xdev->closed_timeout;
+ }
+
spin_lock_init(&xdev->spinlock);
watchdog_set_drvdata(xilinx_wwdt_wdd, xdev);
watchdog_set_nowayout(xilinx_wwdt_wdd, 1);
diff --git a/drivers/watchdog/ziirave_wdt.c b/drivers/watchdog/ziirave_wdt.c
index 775838346bb5..fcc1ba02e75b 100644
--- a/drivers/watchdog/ziirave_wdt.c
+++ b/drivers/watchdog/ziirave_wdt.c
@@ -715,7 +715,7 @@ static void ziirave_wdt_remove(struct i2c_client *client)
}
static const struct i2c_device_id ziirave_wdt_id[] = {
- { "rave-wdt", 0 },
+ { "rave-wdt" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ziirave_wdt_id);
diff --git a/drivers/xen/gntdev-dmabuf.c b/drivers/xen/gntdev-dmabuf.c
index 42adc2c1e06b..5453d86324f6 100644
--- a/drivers/xen/gntdev-dmabuf.c
+++ b/drivers/xen/gntdev-dmabuf.c
@@ -23,7 +23,7 @@
#include "gntdev-common.h"
#include "gntdev-dmabuf.h"
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
struct gntdev_dmabuf {
struct gntdev_dmabuf_priv *priv;
diff --git a/drivers/xen/grant-dma-iommu.c b/drivers/xen/grant-dma-iommu.c
index 2ee750a03c2f..0965e2dd4edf 100644
--- a/drivers/xen/grant-dma-iommu.c
+++ b/drivers/xen/grant-dma-iommu.c
@@ -65,7 +65,7 @@ static struct platform_driver grant_dma_iommu_driver = {
.of_match_table = grant_dma_iommu_of_match,
},
.probe = grant_dma_iommu_probe,
- .remove_new = grant_dma_iommu_remove,
+ .remove = grant_dma_iommu_remove,
};
static int __init grant_dma_iommu_init(void)
diff --git a/fs/9p/v9fs.c b/fs/9p/v9fs.c
index 281a1ed03a04..77e9c4387c1d 100644
--- a/fs/9p/v9fs.c
+++ b/fs/9p/v9fs.c
@@ -659,21 +659,6 @@ static void v9fs_destroy_inode_cache(void)
kmem_cache_destroy(v9fs_inode_cache);
}
-static int v9fs_cache_register(void)
-{
- int ret;
-
- ret = v9fs_init_inode_cache();
- if (ret < 0)
- return ret;
- return ret;
-}
-
-static void v9fs_cache_unregister(void)
-{
- v9fs_destroy_inode_cache();
-}
-
/**
* init_v9fs - Initialize module
*
@@ -686,7 +671,7 @@ static int __init init_v9fs(void)
pr_info("Installing v9fs 9p2000 file system support\n");
/* TODO: Setup list of registered trasnport modules */
- err = v9fs_cache_register();
+ err = v9fs_init_inode_cache();
if (err < 0) {
pr_err("Failed to register v9fs for caching\n");
return err;
@@ -709,7 +694,7 @@ out_sysfs_cleanup:
v9fs_sysfs_cleanup();
out_cache:
- v9fs_cache_unregister();
+ v9fs_destroy_inode_cache();
return err;
}
@@ -722,7 +707,7 @@ out_cache:
static void __exit exit_v9fs(void)
{
v9fs_sysfs_cleanup();
- v9fs_cache_unregister();
+ v9fs_destroy_inode_cache();
unregister_filesystem(&v9fs_fs_type);
}
diff --git a/fs/9p/vfs_addr.c b/fs/9p/vfs_addr.c
index 819c75233235..3bc9ce6c575e 100644
--- a/fs/9p/vfs_addr.c
+++ b/fs/9p/vfs_addr.c
@@ -57,6 +57,8 @@ static void v9fs_issue_write(struct netfs_io_subrequest *subreq)
int err, len;
len = p9_client_write(fid, subreq->start, &subreq->io_iter, &err);
+ if (len > 0)
+ __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
netfs_write_subrequest_terminated(subreq, len ?: err, false);
}
@@ -80,8 +82,10 @@ static void v9fs_issue_read(struct netfs_io_subrequest *subreq)
if (pos + total >= i_size_read(rreq->inode))
__set_bit(NETFS_SREQ_HIT_EOF, &subreq->flags);
- if (!err)
+ if (!err) {
subreq->transferred += total;
+ __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
+ }
netfs_read_subreq_terminated(subreq, err, false);
}
diff --git a/fs/afs/write.c b/fs/afs/write.c
index 34107b55f834..ccb6aa8027c5 100644
--- a/fs/afs/write.c
+++ b/fs/afs/write.c
@@ -122,7 +122,7 @@ static void afs_issue_write_worker(struct work_struct *work)
if (subreq->debug_index == 3)
return netfs_write_subrequest_terminated(subreq, -ENOANO, false);
- if (!test_bit(NETFS_SREQ_RETRYING, &subreq->flags)) {
+ if (!subreq->retry_count) {
set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
return netfs_write_subrequest_terminated(subreq, -EAGAIN, false);
}
@@ -149,6 +149,9 @@ static void afs_issue_write_worker(struct work_struct *work)
afs_wait_for_operation(op);
ret = afs_put_operation(op);
switch (ret) {
+ case 0:
+ __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
+ break;
case -EACCES:
case -EPERM:
case -ENOKEY:
diff --git a/fs/btrfs/bio.c b/fs/btrfs/bio.c
index 1f216d07eff6..7ea6f0b43b95 100644
--- a/fs/btrfs/bio.c
+++ b/fs/btrfs/bio.c
@@ -81,6 +81,9 @@ static struct btrfs_bio *btrfs_split_bio(struct btrfs_fs_info *fs_info,
bio = bio_split(&orig_bbio->bio, map_length >> SECTOR_SHIFT, GFP_NOFS,
&btrfs_clone_bioset);
+ if (IS_ERR(bio))
+ return ERR_CAST(bio);
+
bbio = btrfs_bio(bio);
btrfs_bio_init(bbio, fs_info, NULL, orig_bbio);
bbio->inode = orig_bbio->inode;
@@ -355,7 +358,7 @@ static void btrfs_simple_end_io(struct bio *bio)
INIT_WORK(&bbio->end_io_work, btrfs_end_bio_work);
queue_work(btrfs_end_io_wq(fs_info, bio), &bbio->end_io_work);
} else {
- if (bio_op(bio) == REQ_OP_ZONE_APPEND && !bio->bi_status)
+ if (bio_is_zone_append(bio) && !bio->bi_status)
btrfs_record_physical_zoned(bbio);
btrfs_bio_end_io(bbio, bbio->bio.bi_status);
}
@@ -398,7 +401,7 @@ static void btrfs_orig_write_end_io(struct bio *bio)
else
bio->bi_status = BLK_STS_OK;
- if (bio_op(bio) == REQ_OP_ZONE_APPEND && !bio->bi_status)
+ if (bio_is_zone_append(bio) && !bio->bi_status)
stripe->physical = bio->bi_iter.bi_sector << SECTOR_SHIFT;
btrfs_bio_end_io(bbio, bbio->bio.bi_status);
@@ -412,7 +415,7 @@ static void btrfs_clone_write_end_io(struct bio *bio)
if (bio->bi_status) {
atomic_inc(&stripe->bioc->error);
btrfs_log_dev_io_error(bio, stripe->dev);
- } else if (bio_op(bio) == REQ_OP_ZONE_APPEND) {
+ } else if (bio_is_zone_append(bio)) {
stripe->physical = bio->bi_iter.bi_sector << SECTOR_SHIFT;
}
@@ -649,8 +652,14 @@ static u64 btrfs_append_map_length(struct btrfs_bio *bbio, u64 map_length)
map_length = min(map_length, bbio->fs_info->max_zone_append_size);
sector_offset = bio_split_rw_at(&bbio->bio, &bbio->fs_info->limits,
&nr_segs, map_length);
- if (sector_offset)
- return sector_offset << SECTOR_SHIFT;
+ if (sector_offset) {
+ /*
+ * bio_split_rw_at() could split at a size smaller than our
+ * sectorsize and thus cause unaligned I/Os. Fix that by
+ * always rounding down to the nearest boundary.
+ */
+ return ALIGN_DOWN(sector_offset << SECTOR_SHIFT, bbio->fs_info->sectorsize);
+ }
return map_length;
}
@@ -678,7 +687,8 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
&bioc, &smap, &mirror_num);
if (error) {
ret = errno_to_blk_status(error);
- goto fail;
+ btrfs_bio_counter_dec(fs_info);
+ goto end_bbio;
}
map_length = min(map_length, length);
@@ -686,7 +696,15 @@ static bool btrfs_submit_chunk(struct btrfs_bio *bbio, int mirror_num)
map_length = btrfs_append_map_length(bbio, map_length);
if (map_length < length) {
- bbio = btrfs_split_bio(fs_info, bbio, map_length);
+ struct btrfs_bio *split;
+
+ split = btrfs_split_bio(fs_info, bbio, map_length);
+ if (IS_ERR(split)) {
+ ret = errno_to_blk_status(PTR_ERR(split));
+ btrfs_bio_counter_dec(fs_info);
+ goto end_bbio;
+ }
+ bbio = split;
bio = &bbio->bio;
}
@@ -760,6 +778,7 @@ fail:
btrfs_bio_end_io(remaining, ret);
}
+end_bbio:
btrfs_bio_end_io(bbio, ret);
/* Do not submit another chunk */
return true;
diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c
index 148648ea1c8b..185985a337b3 100644
--- a/fs/btrfs/ctree.c
+++ b/fs/btrfs/ctree.c
@@ -654,6 +654,8 @@ int btrfs_force_cow_block(struct btrfs_trans_handle *trans,
goto error_unlock_cow;
}
}
+
+ trace_btrfs_cow_block(root, buf, cow);
if (unlock_orig)
btrfs_tree_unlock(buf);
free_extent_buffer_stale(buf);
@@ -710,7 +712,6 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
{
struct btrfs_fs_info *fs_info = root->fs_info;
u64 search_start;
- int ret;
if (unlikely(test_bit(BTRFS_ROOT_DELETING, &root->state))) {
btrfs_abort_transaction(trans, -EUCLEAN);
@@ -751,12 +752,8 @@ int btrfs_cow_block(struct btrfs_trans_handle *trans,
* Also We don't care about the error, as it's handled internally.
*/
btrfs_qgroup_trace_subtree_after_cow(trans, root, buf);
- ret = btrfs_force_cow_block(trans, root, buf, parent, parent_slot,
- cow_ret, search_start, 0, nest);
-
- trace_btrfs_cow_block(root, buf, *cow_ret);
-
- return ret;
+ return btrfs_force_cow_block(trans, root, buf, parent, parent_slot,
+ cow_ret, search_start, 0, nest);
}
ALLOW_ERROR_INJECTION(btrfs_cow_block, ERRNO);
@@ -2046,7 +2043,7 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
const struct btrfs_key *key, struct btrfs_path *p,
int ins_len, int cow)
{
- struct btrfs_fs_info *fs_info = root->fs_info;
+ struct btrfs_fs_info *fs_info;
struct extent_buffer *b;
int slot;
int ret;
@@ -2059,6 +2056,10 @@ int btrfs_search_slot(struct btrfs_trans_handle *trans, struct btrfs_root *root,
int min_write_lock_level;
int prev_cmp;
+ if (!root)
+ return -EINVAL;
+
+ fs_info = root->fs_info;
might_sleep();
lowest_level = p->lowest_level;
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 307dedf95c70..2c341956a01c 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -371,6 +371,25 @@ static inline void btrfs_set_root_last_trans(struct btrfs_root *root, u64 transi
}
/*
+ * Return the generation this root started with.
+ *
+ * Every normal root that is created with root->root_key.offset set to it's
+ * originating generation. If it is a snapshot it is the generation when the
+ * snapshot was created.
+ *
+ * However for TREE_RELOC roots root_key.offset is the objectid of the owning
+ * tree root. Thankfully we copy the root item of the owning tree root, which
+ * has it's last_snapshot set to what we would have root_key.offset set to, so
+ * return that if this is a TREE_RELOC root.
+ */
+static inline u64 btrfs_root_origin_generation(const struct btrfs_root *root)
+{
+ if (btrfs_root_id(root) == BTRFS_TREE_RELOC_OBJECTID)
+ return btrfs_root_last_snapshot(&root->root_item);
+ return root->root_key.offset;
+}
+
+/*
* Structure that conveys information about an extent that is going to replace
* all the extents in a file range.
*/
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 814320948645..eff0dd1ae62f 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -4262,6 +4262,15 @@ void __cold close_ctree(struct btrfs_fs_info *fs_info)
* already the cleaner, but below we run all pending delayed iputs.
*/
btrfs_flush_workqueue(fs_info->fixup_workers);
+ /*
+ * Similar case here, we have to wait for delalloc workers before we
+ * proceed below and stop the cleaner kthread, otherwise we trigger a
+ * use-after-tree on the cleaner kthread task_struct when a delalloc
+ * worker running submit_compressed_extents() adds a delayed iput, which
+ * does a wake up on the cleaner kthread, which was already freed below
+ * when we call kthread_stop().
+ */
+ btrfs_flush_workqueue(fs_info->delalloc_workers);
/*
* After we parked the cleaner kthread, ordered extents may have
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 412e318e4a22..3c6f7fecbb9a 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -2422,7 +2422,7 @@ int btrfs_cross_ref_exist(struct btrfs_root *root, u64 objectid, u64 offset,
goto out;
ret = check_delayed_ref(root, path, objectid, offset, bytenr);
- } while (ret == -EAGAIN);
+ } while (ret == -EAGAIN && !path->nowait);
out:
btrfs_release_path(path);
@@ -5285,7 +5285,7 @@ static bool visit_node_for_delete(struct btrfs_root *root, struct walk_control *
* reference to it.
*/
generation = btrfs_node_ptr_generation(eb, slot);
- if (!wc->update_ref || generation <= root->root_key.offset)
+ if (!wc->update_ref || generation <= btrfs_root_origin_generation(root))
return false;
/*
@@ -5340,7 +5340,7 @@ static noinline void reada_walk_down(struct btrfs_trans_handle *trans,
goto reada;
if (wc->stage == UPDATE_BACKREF &&
- generation <= root->root_key.offset)
+ generation <= btrfs_root_origin_generation(root))
continue;
/* We don't lock the tree block, it's OK to be racy here */
@@ -5683,7 +5683,7 @@ static noinline int do_walk_down(struct btrfs_trans_handle *trans,
* for the subtree
*/
if (wc->stage == UPDATE_BACKREF &&
- generation <= root->root_key.offset) {
+ generation <= btrfs_root_origin_generation(root)) {
wc->lookup_info = 1;
return 1;
}
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 588c353d2969..14e27473c5bc 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -911,6 +911,7 @@ again:
ret = PTR_ERR(folio);
return ret;
}
+ folio_wait_writeback(folio);
/* Only support page sized folio yet. */
ASSERT(folio_order(folio) == 0);
ret = set_folio_extent_mapped(folio);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 03fe0de2cd0d..27b2fe7f735d 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3063,6 +3063,19 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
goto out;
}
+ /*
+ * If it's a COW write we need to lock the extent range as we will be
+ * inserting/replacing file extent items and unpinning an extent map.
+ * This must be taken before joining a transaction, as it's a higher
+ * level lock (like the inode's VFS lock), otherwise we can run into an
+ * ABBA deadlock with other tasks (transactions work like a lock,
+ * depending on their current state).
+ */
+ if (!test_bit(BTRFS_ORDERED_NOCOW, &ordered_extent->flags)) {
+ clear_bits |= EXTENT_LOCKED;
+ lock_extent(io_tree, start, end, &cached_state);
+ }
+
if (freespace_inode)
trans = btrfs_join_transaction_spacecache(root);
else
@@ -3099,9 +3112,6 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
goto out;
}
- clear_bits |= EXTENT_LOCKED;
- lock_extent(io_tree, start, end, &cached_state);
-
if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
compress_type = ordered_extent->compress_type;
if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
@@ -9068,9 +9078,9 @@ out:
}
struct btrfs_encoded_read_private {
- wait_queue_head_t wait;
+ struct completion done;
void *uring_ctx;
- atomic_t pending;
+ refcount_t pending_refs;
blk_status_t status;
};
@@ -9089,14 +9099,14 @@ static void btrfs_encoded_read_endio(struct btrfs_bio *bbio)
*/
WRITE_ONCE(priv->status, bbio->bio.bi_status);
}
- if (atomic_dec_return(&priv->pending) == 0) {
+ if (refcount_dec_and_test(&priv->pending_refs)) {
int err = blk_status_to_errno(READ_ONCE(priv->status));
if (priv->uring_ctx) {
btrfs_uring_read_extent_endio(priv->uring_ctx, err);
kfree(priv);
} else {
- wake_up(&priv->wait);
+ complete(&priv->done);
}
}
bio_put(&bbio->bio);
@@ -9116,8 +9126,8 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
if (!priv)
return -ENOMEM;
- init_waitqueue_head(&priv->wait);
- atomic_set(&priv->pending, 1);
+ init_completion(&priv->done);
+ refcount_set(&priv->pending_refs, 1);
priv->status = 0;
priv->uring_ctx = uring_ctx;
@@ -9130,7 +9140,7 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
size_t bytes = min_t(u64, disk_io_size, PAGE_SIZE);
if (bio_add_page(&bbio->bio, pages[i], bytes, 0) < bytes) {
- atomic_inc(&priv->pending);
+ refcount_inc(&priv->pending_refs);
btrfs_submit_bbio(bbio, 0);
bbio = btrfs_bio_alloc(BIO_MAX_VECS, REQ_OP_READ, fs_info,
@@ -9145,11 +9155,11 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
disk_io_size -= bytes;
} while (disk_io_size);
- atomic_inc(&priv->pending);
+ refcount_inc(&priv->pending_refs);
btrfs_submit_bbio(bbio, 0);
if (uring_ctx) {
- if (atomic_dec_return(&priv->pending) == 0) {
+ if (refcount_dec_and_test(&priv->pending_refs)) {
ret = blk_status_to_errno(READ_ONCE(priv->status));
btrfs_uring_read_extent_endio(uring_ctx, ret);
kfree(priv);
@@ -9158,8 +9168,8 @@ int btrfs_encoded_read_regular_fill_pages(struct btrfs_inode *inode,
return -EIOCBQUEUED;
} else {
- if (atomic_dec_return(&priv->pending) != 0)
- io_wait_event(priv->wait, !atomic_read(&priv->pending));
+ if (!refcount_dec_and_test(&priv->pending_refs))
+ wait_for_completion_io(&priv->done);
/* See btrfs_encoded_read_endio() for ordering. */
ret = blk_status_to_errno(READ_ONCE(priv->status));
kfree(priv);
@@ -9789,15 +9799,25 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
struct btrfs_fs_info *fs_info = root->fs_info;
struct extent_io_tree *io_tree = &BTRFS_I(inode)->io_tree;
struct extent_state *cached_state = NULL;
- struct extent_map *em = NULL;
struct btrfs_chunk_map *map = NULL;
struct btrfs_device *device = NULL;
struct btrfs_swap_info bsi = {
.lowest_ppage = (sector_t)-1ULL,
};
+ struct btrfs_backref_share_check_ctx *backref_ctx = NULL;
+ struct btrfs_path *path = NULL;
int ret = 0;
u64 isize;
- u64 start;
+ u64 prev_extent_end = 0;
+
+ /*
+ * Acquire the inode's mmap lock to prevent races with memory mapped
+ * writes, as they could happen after we flush delalloc below and before
+ * we lock the extent range further below. The inode was already locked
+ * up in the call chain.
+ */
+ btrfs_assert_inode_locked(BTRFS_I(inode));
+ down_write(&BTRFS_I(inode)->i_mmap_lock);
/*
* If the swap file was just created, make sure delalloc is done. If the
@@ -9806,22 +9826,32 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
*/
ret = btrfs_wait_ordered_range(BTRFS_I(inode), 0, (u64)-1);
if (ret)
- return ret;
+ goto out_unlock_mmap;
/*
* The inode is locked, so these flags won't change after we check them.
*/
if (BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS) {
btrfs_warn(fs_info, "swapfile must not be compressed");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_unlock_mmap;
}
if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATACOW)) {
btrfs_warn(fs_info, "swapfile must not be copy-on-write");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_unlock_mmap;
}
if (!(BTRFS_I(inode)->flags & BTRFS_INODE_NODATASUM)) {
btrfs_warn(fs_info, "swapfile must not be checksummed");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_unlock_mmap;
+ }
+
+ path = btrfs_alloc_path();
+ backref_ctx = btrfs_alloc_backref_share_check_ctx();
+ if (!path || !backref_ctx) {
+ ret = -ENOMEM;
+ goto out_unlock_mmap;
}
/*
@@ -9836,7 +9866,8 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
if (!btrfs_exclop_start(fs_info, BTRFS_EXCLOP_SWAP_ACTIVATE)) {
btrfs_warn(fs_info,
"cannot activate swapfile while exclusive operation is running");
- return -EBUSY;
+ ret = -EBUSY;
+ goto out_unlock_mmap;
}
/*
@@ -9850,7 +9881,8 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
btrfs_exclop_finish(fs_info);
btrfs_warn(fs_info,
"cannot activate swapfile because snapshot creation is in progress");
- return -EINVAL;
+ ret = -EINVAL;
+ goto out_unlock_mmap;
}
/*
* Snapshots can create extents which require COW even if NODATACOW is
@@ -9866,11 +9898,13 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
if (btrfs_root_dead(root)) {
spin_unlock(&root->root_item_lock);
+ btrfs_drew_write_unlock(&root->snapshot_lock);
btrfs_exclop_finish(fs_info);
btrfs_warn(fs_info,
"cannot activate swapfile because subvolume %llu is being deleted",
btrfs_root_id(root));
- return -EPERM;
+ ret = -EPERM;
+ goto out_unlock_mmap;
}
atomic_inc(&root->nr_swapfiles);
spin_unlock(&root->root_item_lock);
@@ -9878,24 +9912,39 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
isize = ALIGN_DOWN(inode->i_size, fs_info->sectorsize);
lock_extent(io_tree, 0, isize - 1, &cached_state);
- start = 0;
- while (start < isize) {
- u64 logical_block_start, physical_block_start;
+ while (prev_extent_end < isize) {
+ struct btrfs_key key;
+ struct extent_buffer *leaf;
+ struct btrfs_file_extent_item *ei;
struct btrfs_block_group *bg;
- u64 len = isize - start;
+ u64 logical_block_start;
+ u64 physical_block_start;
+ u64 extent_gen;
+ u64 disk_bytenr;
+ u64 len;
- em = btrfs_get_extent(BTRFS_I(inode), NULL, start, len);
- if (IS_ERR(em)) {
- ret = PTR_ERR(em);
+ key.objectid = btrfs_ino(BTRFS_I(inode));
+ key.type = BTRFS_EXTENT_DATA_KEY;
+ key.offset = prev_extent_end;
+
+ ret = btrfs_search_slot(NULL, root, &key, path, 0, 0);
+ if (ret < 0)
goto out;
- }
- if (em->disk_bytenr == EXTENT_MAP_HOLE) {
+ /*
+ * If key not found it means we have an implicit hole (NO_HOLES
+ * is enabled).
+ */
+ if (ret > 0) {
btrfs_warn(fs_info, "swapfile must not have holes");
ret = -EINVAL;
goto out;
}
- if (em->disk_bytenr == EXTENT_MAP_INLINE) {
+
+ leaf = path->nodes[0];
+ ei = btrfs_item_ptr(leaf, path->slots[0], struct btrfs_file_extent_item);
+
+ if (btrfs_file_extent_type(leaf, ei) == BTRFS_FILE_EXTENT_INLINE) {
/*
* It's unlikely we'll ever actually find ourselves
* here, as a file small enough to fit inline won't be
@@ -9907,23 +9956,45 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
ret = -EINVAL;
goto out;
}
- if (extent_map_is_compressed(em)) {
+
+ if (btrfs_file_extent_compression(leaf, ei) != BTRFS_COMPRESS_NONE) {
btrfs_warn(fs_info, "swapfile must not be compressed");
ret = -EINVAL;
goto out;
}
- logical_block_start = extent_map_block_start(em) + (start - em->start);
- len = min(len, em->len - (start - em->start));
- free_extent_map(em);
- em = NULL;
+ disk_bytenr = btrfs_file_extent_disk_bytenr(leaf, ei);
+ if (disk_bytenr == 0) {
+ btrfs_warn(fs_info, "swapfile must not have holes");
+ ret = -EINVAL;
+ goto out;
+ }
- ret = can_nocow_extent(inode, start, &len, NULL, false, true);
+ logical_block_start = disk_bytenr + btrfs_file_extent_offset(leaf, ei);
+ extent_gen = btrfs_file_extent_generation(leaf, ei);
+ prev_extent_end = btrfs_file_extent_end(path);
+
+ if (prev_extent_end > isize)
+ len = isize - key.offset;
+ else
+ len = btrfs_file_extent_num_bytes(leaf, ei);
+
+ backref_ctx->curr_leaf_bytenr = leaf->start;
+
+ /*
+ * Don't need the path anymore, release to avoid deadlocks when
+ * calling btrfs_is_data_extent_shared() because when joining a
+ * transaction it can block waiting for the current one's commit
+ * which in turn may be trying to lock the same leaf to flush
+ * delayed items for example.
+ */
+ btrfs_release_path(path);
+
+ ret = btrfs_is_data_extent_shared(BTRFS_I(inode), disk_bytenr,
+ extent_gen, backref_ctx);
if (ret < 0) {
goto out;
- } else if (ret) {
- ret = 0;
- } else {
+ } else if (ret > 0) {
btrfs_warn(fs_info,
"swapfile must not be copy-on-write");
ret = -EINVAL;
@@ -9958,7 +10029,6 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
physical_block_start = (map->stripes[0].physical +
(logical_block_start - map->start));
- len = min(len, map->chunk_len - (logical_block_start - map->start));
btrfs_free_chunk_map(map);
map = NULL;
@@ -9999,20 +10069,23 @@ static int btrfs_swap_activate(struct swap_info_struct *sis, struct file *file,
if (ret)
goto out;
}
- bsi.start = start;
+ bsi.start = key.offset;
bsi.block_start = physical_block_start;
bsi.block_len = len;
}
- start += len;
+ if (fatal_signal_pending(current)) {
+ ret = -EINTR;
+ goto out;
+ }
+
+ cond_resched();
}
if (bsi.block_len)
ret = btrfs_add_swap_extent(sis, &bsi);
out:
- if (!IS_ERR_OR_NULL(em))
- free_extent_map(em);
if (!IS_ERR_OR_NULL(map))
btrfs_free_chunk_map(map);
@@ -10025,6 +10098,10 @@ out:
btrfs_exclop_finish(fs_info);
+out_unlock_mmap:
+ up_write(&BTRFS_I(inode)->i_mmap_lock);
+ btrfs_free_backref_share_ctx(backref_ctx);
+ btrfs_free_path(path);
if (ret)
return ret;
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index c9302d193187..4d9305fa37a8 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -4751,6 +4751,9 @@ static void btrfs_uring_read_finished(struct io_uring_cmd *cmd, unsigned int iss
size_t page_offset;
ssize_t ret;
+ /* The inode lock has already been acquired in btrfs_uring_read_extent. */
+ btrfs_lockdep_inode_acquire(inode, i_rwsem);
+
if (priv->err) {
ret = priv->err;
goto out;
@@ -4859,6 +4862,13 @@ static int btrfs_uring_read_extent(struct kiocb *iocb, struct iov_iter *iter,
* and inode and freeing the allocations.
*/
+ /*
+ * We're returning to userspace with the inode lock held, and that's
+ * okay - it'll get unlocked in a worker thread. Call
+ * btrfs_lockdep_inode_release() to avoid confusing lockdep.
+ */
+ btrfs_lockdep_inode_release(inode, i_rwsem);
+
return -EIOCBQUEUED;
out_fail:
@@ -4868,25 +4878,29 @@ out_fail:
return ret;
}
+struct btrfs_uring_encoded_data {
+ struct btrfs_ioctl_encoded_io_args args;
+ struct iovec iovstack[UIO_FASTIOV];
+ struct iovec *iov;
+ struct iov_iter iter;
+};
+
static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue_flags)
{
size_t copy_end_kernel = offsetofend(struct btrfs_ioctl_encoded_io_args, flags);
size_t copy_end;
- struct btrfs_ioctl_encoded_io_args args = { 0 };
int ret;
u64 disk_bytenr, disk_io_size;
struct file *file;
struct btrfs_inode *inode;
struct btrfs_fs_info *fs_info;
struct extent_io_tree *io_tree;
- struct iovec iovstack[UIO_FASTIOV];
- struct iovec *iov = iovstack;
- struct iov_iter iter;
loff_t pos;
struct kiocb kiocb;
struct extent_state *cached_state = NULL;
u64 start, lockend;
void __user *sqe_addr;
+ struct btrfs_uring_encoded_data *data = io_uring_cmd_get_async_data(cmd)->op_data;
if (!capable(CAP_SYS_ADMIN)) {
ret = -EPERM;
@@ -4900,43 +4914,64 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
if (issue_flags & IO_URING_F_COMPAT) {
#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
- struct btrfs_ioctl_encoded_io_args_32 args32;
-
copy_end = offsetofend(struct btrfs_ioctl_encoded_io_args_32, flags);
- if (copy_from_user(&args32, sqe_addr, copy_end)) {
- ret = -EFAULT;
- goto out_acct;
- }
- args.iov = compat_ptr(args32.iov);
- args.iovcnt = args32.iovcnt;
- args.offset = args32.offset;
- args.flags = args32.flags;
#else
return -ENOTTY;
#endif
} else {
copy_end = copy_end_kernel;
- if (copy_from_user(&args, sqe_addr, copy_end)) {
- ret = -EFAULT;
+ }
+
+ if (!data) {
+ data = kzalloc(sizeof(*data), GFP_NOFS);
+ if (!data) {
+ ret = -ENOMEM;
goto out_acct;
}
- }
- if (args.flags != 0)
- return -EINVAL;
+ io_uring_cmd_get_async_data(cmd)->op_data = data;
- ret = import_iovec(ITER_DEST, args.iov, args.iovcnt, ARRAY_SIZE(iovstack),
- &iov, &iter);
- if (ret < 0)
- goto out_acct;
+ if (issue_flags & IO_URING_F_COMPAT) {
+#if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
+ struct btrfs_ioctl_encoded_io_args_32 args32;
- if (iov_iter_count(&iter) == 0) {
- ret = 0;
- goto out_free;
+ if (copy_from_user(&args32, sqe_addr, copy_end)) {
+ ret = -EFAULT;
+ goto out_acct;
+ }
+
+ data->args.iov = compat_ptr(args32.iov);
+ data->args.iovcnt = args32.iovcnt;
+ data->args.offset = args32.offset;
+ data->args.flags = args32.flags;
+#endif
+ } else {
+ if (copy_from_user(&data->args, sqe_addr, copy_end)) {
+ ret = -EFAULT;
+ goto out_acct;
+ }
+ }
+
+ if (data->args.flags != 0) {
+ ret = -EINVAL;
+ goto out_acct;
+ }
+
+ data->iov = data->iovstack;
+ ret = import_iovec(ITER_DEST, data->args.iov, data->args.iovcnt,
+ ARRAY_SIZE(data->iovstack), &data->iov,
+ &data->iter);
+ if (ret < 0)
+ goto out_acct;
+
+ if (iov_iter_count(&data->iter) == 0) {
+ ret = 0;
+ goto out_free;
+ }
}
- pos = args.offset;
- ret = rw_verify_area(READ, file, &pos, args.len);
+ pos = data->args.offset;
+ ret = rw_verify_area(READ, file, &pos, data->args.len);
if (ret < 0)
goto out_free;
@@ -4949,15 +4984,16 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
start = ALIGN_DOWN(pos, fs_info->sectorsize);
lockend = start + BTRFS_MAX_UNCOMPRESSED - 1;
- ret = btrfs_encoded_read(&kiocb, &iter, &args, &cached_state,
+ ret = btrfs_encoded_read(&kiocb, &data->iter, &data->args, &cached_state,
&disk_bytenr, &disk_io_size);
if (ret < 0 && ret != -EIOCBQUEUED)
goto out_free;
file_accessed(file);
- if (copy_to_user(sqe_addr + copy_end, (const char *)&args + copy_end_kernel,
- sizeof(args) - copy_end_kernel)) {
+ if (copy_to_user(sqe_addr + copy_end,
+ (const char *)&data->args + copy_end_kernel,
+ sizeof(data->args) - copy_end_kernel)) {
if (ret == -EIOCBQUEUED) {
unlock_extent(io_tree, start, lockend, &cached_state);
btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
@@ -4967,40 +5003,22 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
}
if (ret == -EIOCBQUEUED) {
- u64 count;
-
- /*
- * If we've optimized things by storing the iovecs on the stack,
- * undo this.
- */
- if (!iov) {
- iov = kmalloc(sizeof(struct iovec) * args.iovcnt, GFP_NOFS);
- if (!iov) {
- unlock_extent(io_tree, start, lockend, &cached_state);
- btrfs_inode_unlock(inode, BTRFS_ILOCK_SHARED);
- ret = -ENOMEM;
- goto out_acct;
- }
-
- memcpy(iov, iovstack, sizeof(struct iovec) * args.iovcnt);
- }
-
- count = min_t(u64, iov_iter_count(&iter), disk_io_size);
+ u64 count = min_t(u64, iov_iter_count(&data->iter), disk_io_size);
/* Match ioctl by not returning past EOF if uncompressed. */
- if (!args.compression)
- count = min_t(u64, count, args.len);
+ if (!data->args.compression)
+ count = min_t(u64, count, data->args.len);
- ret = btrfs_uring_read_extent(&kiocb, &iter, start, lockend,
- cached_state, disk_bytenr,
- disk_io_size, count,
- args.compression, iov, cmd);
+ ret = btrfs_uring_read_extent(&kiocb, &data->iter, start, lockend,
+ cached_state, disk_bytenr, disk_io_size,
+ count, data->args.compression,
+ data->iov, cmd);
goto out_acct;
}
out_free:
- kfree(iov);
+ kfree(data->iov);
out_acct:
if (ret > 0)
diff --git a/fs/btrfs/locking.h b/fs/btrfs/locking.h
index 46c8be2afab1..35036b151bf5 100644
--- a/fs/btrfs/locking.h
+++ b/fs/btrfs/locking.h
@@ -129,6 +129,16 @@ enum btrfs_lockdep_trans_states {
rwsem_release(&owner->lock##_map, _THIS_IP_)
/*
+ * Used to account for the fact that when doing io_uring encoded I/O, we can
+ * return to userspace with the inode lock still held.
+ */
+#define btrfs_lockdep_inode_acquire(owner, lock) \
+ rwsem_acquire_read(&owner->vfs_inode.lock.dep_map, 0, 0, _THIS_IP_)
+
+#define btrfs_lockdep_inode_release(owner, lock) \
+ rwsem_release(&owner->vfs_inode.lock.dep_map, _THIS_IP_)
+
+/*
* Macros for the transaction states wait events, similar to the generic wait
* event macros.
*/
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index a6f92836c9b1..f9b214992212 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -1121,6 +1121,7 @@ int btrfs_quota_enable(struct btrfs_fs_info *fs_info,
fs_info->qgroup_flags = BTRFS_QGROUP_STATUS_FLAG_ON;
if (simple) {
fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_SIMPLE_MODE;
+ btrfs_set_fs_incompat(fs_info, SIMPLE_QUOTA);
btrfs_set_qgroup_status_enable_gen(leaf, ptr, trans->transid);
} else {
fs_info->qgroup_flags |= BTRFS_QGROUP_STATUS_FLAG_INCONSISTENT;
@@ -1254,8 +1255,6 @@ out_add_root:
spin_lock(&fs_info->qgroup_lock);
fs_info->quota_root = quota_root;
set_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags);
- if (simple)
- btrfs_set_fs_incompat(fs_info, SIMPLE_QUOTA);
spin_unlock(&fs_info->qgroup_lock);
/* Skip rescan for simple qgroups. */
diff --git a/fs/btrfs/ref-verify.c b/fs/btrfs/ref-verify.c
index 9522a8b79d22..2928abf7eb82 100644
--- a/fs/btrfs/ref-verify.c
+++ b/fs/btrfs/ref-verify.c
@@ -857,6 +857,7 @@ int btrfs_ref_tree_mod(struct btrfs_fs_info *fs_info,
"dropping a ref for a root that doesn't have a ref on the block");
dump_block_entry(fs_info, be);
dump_ref_action(fs_info, ra);
+ rb_erase(&ref->node, &be->refs);
kfree(ref);
kfree(ra);
goto out_unlock;
diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c
index bf267bdfa8f8..db8b42f674b7 100644
--- a/fs/btrfs/relocation.c
+++ b/fs/btrfs/relocation.c
@@ -2902,6 +2902,7 @@ static int relocate_one_folio(struct reloc_control *rc,
const bool use_rst = btrfs_need_stripe_tree_update(fs_info, rc->block_group->flags);
ASSERT(index <= last_index);
+again:
folio = filemap_lock_folio(inode->i_mapping, index);
if (IS_ERR(folio)) {
@@ -2937,6 +2938,11 @@ static int relocate_one_folio(struct reloc_control *rc,
ret = -EIO;
goto release_folio;
}
+ if (folio->mapping != inode->i_mapping) {
+ folio_unlock(folio);
+ folio_put(folio);
+ goto again;
+ }
}
/*
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index 204c928beaf9..531312efee8d 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -1541,6 +1541,10 @@ static int scrub_find_fill_first_stripe(struct btrfs_block_group *bg,
u64 extent_gen;
int ret;
+ if (unlikely(!extent_root)) {
+ btrfs_err(fs_info, "no valid extent root for scrub");
+ return -EUCLEAN;
+ }
memset(stripe->sectors, 0, sizeof(struct scrub_sector_verification) *
stripe->nr_sectors);
scrub_stripe_reset_bitmaps(stripe);
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 7254279c3cc9..498c84323253 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -5280,6 +5280,7 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
unsigned cur_len = min_t(unsigned, len,
PAGE_SIZE - pg_offset);
+again:
folio = filemap_lock_folio(mapping, index);
if (IS_ERR(folio)) {
page_cache_sync_readahead(mapping,
@@ -5312,6 +5313,11 @@ static int put_file_data(struct send_ctx *sctx, u64 offset, u32 len)
ret = -EIO;
break;
}
+ if (folio->mapping != mapping) {
+ folio_unlock(folio);
+ folio_put(folio);
+ goto again;
+ }
}
memcpy_from_folio(sctx->send_buf + sctx->send_size, folio,
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 97a85d180b61..7dfe5005129a 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -1885,18 +1885,21 @@ static int btrfs_get_tree_super(struct fs_context *fc)
if (sb->s_root) {
btrfs_close_devices(fs_devices);
- if ((fc->sb_flags ^ sb->s_flags) & SB_RDONLY)
- ret = -EBUSY;
+ /*
+ * At this stage we may have RO flag mismatch between
+ * fc->sb_flags and sb->s_flags. Caller should detect such
+ * mismatch and reconfigure with sb->s_umount rwsem held if
+ * needed.
+ */
} else {
snprintf(sb->s_id, sizeof(sb->s_id), "%pg", bdev);
shrinker_debugfs_rename(sb->s_shrink, "sb-btrfs:%s", sb->s_id);
btrfs_sb(sb)->bdev_holder = &btrfs_fs_type;
ret = btrfs_fill_super(sb, fs_devices);
- }
-
- if (ret) {
- deactivate_locked_super(sb);
- return ret;
+ if (ret) {
+ deactivate_locked_super(sb);
+ return ret;
+ }
}
btrfs_clear_oneshot_options(fs_info);
@@ -1982,39 +1985,18 @@ error:
* btrfs or not, setting the whole super block RO. To make per-subvolume mounting
* work with different options work we need to keep backward compatibility.
*/
-static struct vfsmount *btrfs_reconfigure_for_mount(struct fs_context *fc)
+static int btrfs_reconfigure_for_mount(struct fs_context *fc, struct vfsmount *mnt)
{
- struct vfsmount *mnt;
- int ret;
- const bool ro2rw = !(fc->sb_flags & SB_RDONLY);
-
- /*
- * We got an EBUSY because our SB_RDONLY flag didn't match the existing
- * super block, so invert our setting here and retry the mount so we
- * can get our vfsmount.
- */
- if (ro2rw)
- fc->sb_flags |= SB_RDONLY;
- else
- fc->sb_flags &= ~SB_RDONLY;
-
- mnt = fc_mount(fc);
- if (IS_ERR(mnt))
- return mnt;
+ int ret = 0;
- if (!ro2rw)
- return mnt;
+ if (fc->sb_flags & SB_RDONLY)
+ return ret;
- /* We need to convert to rw, call reconfigure. */
- fc->sb_flags &= ~SB_RDONLY;
down_write(&mnt->mnt_sb->s_umount);
- ret = btrfs_reconfigure(fc);
+ if (!(fc->sb_flags & SB_RDONLY) && (mnt->mnt_sb->s_flags & SB_RDONLY))
+ ret = btrfs_reconfigure(fc);
up_write(&mnt->mnt_sb->s_umount);
- if (ret) {
- mntput(mnt);
- return ERR_PTR(ret);
- }
- return mnt;
+ return ret;
}
static int btrfs_get_tree_subvol(struct fs_context *fc)
@@ -2024,6 +2006,7 @@ static int btrfs_get_tree_subvol(struct fs_context *fc)
struct fs_context *dup_fc;
struct dentry *dentry;
struct vfsmount *mnt;
+ int ret = 0;
/*
* Setup a dummy root and fs_info for test/set super. This is because
@@ -2066,11 +2049,16 @@ static int btrfs_get_tree_subvol(struct fs_context *fc)
fc->security = NULL;
mnt = fc_mount(dup_fc);
- if (PTR_ERR_OR_ZERO(mnt) == -EBUSY)
- mnt = btrfs_reconfigure_for_mount(dup_fc);
- put_fs_context(dup_fc);
- if (IS_ERR(mnt))
+ if (IS_ERR(mnt)) {
+ put_fs_context(dup_fc);
return PTR_ERR(mnt);
+ }
+ ret = btrfs_reconfigure_for_mount(dup_fc, mnt);
+ put_fs_context(dup_fc);
+ if (ret) {
+ mntput(mnt);
+ return ret;
+ }
/*
* This free's ->subvol_name, because if it isn't set we have to
diff --git a/fs/btrfs/sysfs.c b/fs/btrfs/sysfs.c
index b843308e2bc6..7f09b6c9cc2d 100644
--- a/fs/btrfs/sysfs.c
+++ b/fs/btrfs/sysfs.c
@@ -295,7 +295,7 @@ BTRFS_FEAT_ATTR_INCOMPAT(simple_quota, SIMPLE_QUOTA);
#ifdef CONFIG_BLK_DEV_ZONED
BTRFS_FEAT_ATTR_INCOMPAT(zoned, ZONED);
#endif
-#ifdef CONFIG_BTRFS_DEBUG
+#ifdef CONFIG_BTRFS_EXPERIMENTAL
/* Remove once support for extent tree v2 is feature complete */
BTRFS_FEAT_ATTR_INCOMPAT(extent_tree_v2, EXTENT_TREE_V2);
/* Remove once support for raid stripe tree is feature complete. */
@@ -329,7 +329,7 @@ static struct attribute *btrfs_supported_feature_attrs[] = {
#ifdef CONFIG_BLK_DEV_ZONED
BTRFS_FEAT_ATTR_PTR(zoned),
#endif
-#ifdef CONFIG_BTRFS_DEBUG
+#ifdef CONFIG_BTRFS_EXPERIMENTAL
BTRFS_FEAT_ATTR_PTR(extent_tree_v2),
BTRFS_FEAT_ATTR_PTR(raid_stripe_tree),
#endif
@@ -1118,7 +1118,7 @@ static ssize_t btrfs_nodesize_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
- return sysfs_emit(buf, "%u\n", fs_info->super_copy->nodesize);
+ return sysfs_emit(buf, "%u\n", fs_info->nodesize);
}
BTRFS_ATTR(, nodesize, btrfs_nodesize_show);
@@ -1128,7 +1128,7 @@ static ssize_t btrfs_sectorsize_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
- return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize);
+ return sysfs_emit(buf, "%u\n", fs_info->sectorsize);
}
BTRFS_ATTR(, sectorsize, btrfs_sectorsize_show);
@@ -1180,7 +1180,7 @@ static ssize_t btrfs_clone_alignment_show(struct kobject *kobj,
{
struct btrfs_fs_info *fs_info = to_fs_info(kobj);
- return sysfs_emit(buf, "%u\n", fs_info->super_copy->sectorsize);
+ return sysfs_emit(buf, "%u\n", fs_info->sectorsize);
}
BTRFS_ATTR(, clone_alignment, btrfs_clone_alignment_show);
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c
index 148d8cefa40e..dfeee033f31f 100644
--- a/fs/btrfs/tree-checker.c
+++ b/fs/btrfs/tree-checker.c
@@ -1527,6 +1527,11 @@ static int check_extent_item(struct extent_buffer *leaf,
dref_offset, fs_info->sectorsize);
return -EUCLEAN;
}
+ if (unlikely(btrfs_extent_data_ref_count(leaf, dref) == 0)) {
+ extent_err(leaf, slot,
+ "invalid data ref count, should have non-zero value");
+ return -EUCLEAN;
+ }
inline_refs += btrfs_extent_data_ref_count(leaf, dref);
break;
/* Contains parent bytenr and ref count */
@@ -1539,6 +1544,11 @@ static int check_extent_item(struct extent_buffer *leaf,
inline_offset, fs_info->sectorsize);
return -EUCLEAN;
}
+ if (unlikely(btrfs_shared_data_ref_count(leaf, sref) == 0)) {
+ extent_err(leaf, slot,
+ "invalid shared data ref count, should have non-zero value");
+ return -EUCLEAN;
+ }
inline_refs += btrfs_shared_data_ref_count(leaf, sref);
break;
case BTRFS_EXTENT_OWNER_REF_KEY:
@@ -1611,8 +1621,18 @@ static int check_simple_keyed_refs(struct extent_buffer *leaf,
{
u32 expect_item_size = 0;
- if (key->type == BTRFS_SHARED_DATA_REF_KEY)
+ if (key->type == BTRFS_SHARED_DATA_REF_KEY) {
+ struct btrfs_shared_data_ref *sref;
+
+ sref = btrfs_item_ptr(leaf, slot, struct btrfs_shared_data_ref);
+ if (unlikely(btrfs_shared_data_ref_count(leaf, sref) == 0)) {
+ extent_err(leaf, slot,
+ "invalid shared data backref count, should have non-zero value");
+ return -EUCLEAN;
+ }
+
expect_item_size = sizeof(struct btrfs_shared_data_ref);
+ }
if (unlikely(btrfs_item_size(leaf, slot) != expect_item_size)) {
generic_err(leaf, slot,
@@ -1689,6 +1709,11 @@ static int check_extent_data_ref(struct extent_buffer *leaf,
offset, leaf->fs_info->sectorsize);
return -EUCLEAN;
}
+ if (unlikely(btrfs_extent_data_ref_count(leaf, dref) == 0)) {
+ extent_err(leaf, slot,
+ "invalid extent data backref count, should have non-zero value");
+ return -EUCLEAN;
+ }
}
return 0;
}
diff --git a/fs/btrfs/zlib.c b/fs/btrfs/zlib.c
index ddf0d5a448a7..c9e92c6941ec 100644
--- a/fs/btrfs/zlib.c
+++ b/fs/btrfs/zlib.c
@@ -174,10 +174,10 @@ int zlib_compress_folios(struct list_head *ws, struct address_space *mapping,
copy_page(workspace->buf + i * PAGE_SIZE,
data_in);
start += PAGE_SIZE;
- workspace->strm.avail_in =
- (in_buf_folios << PAGE_SHIFT);
}
workspace->strm.next_in = workspace->buf;
+ workspace->strm.avail_in = min(bytes_left,
+ in_buf_folios << PAGE_SHIFT);
} else {
unsigned int pg_off;
unsigned int cur_len;
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index 11ed523e528e..df905ae82929 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -748,8 +748,9 @@ int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info)
(u64)lim->max_segments << PAGE_SHIFT),
fs_info->sectorsize);
fs_info->fs_devices->chunk_alloc_policy = BTRFS_CHUNK_ALLOC_ZONED;
- if (fs_info->max_zone_append_size < fs_info->max_extent_size)
- fs_info->max_extent_size = fs_info->max_zone_append_size;
+
+ fs_info->max_extent_size = min_not_zero(fs_info->max_extent_size,
+ fs_info->max_zone_append_size);
/*
* Check mount options here, because we might change fs_info->zoned
diff --git a/fs/cachefiles/daemon.c b/fs/cachefiles/daemon.c
index 89b11336a836..1806bff8e59b 100644
--- a/fs/cachefiles/daemon.c
+++ b/fs/cachefiles/daemon.c
@@ -15,6 +15,7 @@
#include <linux/namei.h>
#include <linux/poll.h>
#include <linux/mount.h>
+#include <linux/security.h>
#include <linux/statfs.h>
#include <linux/ctype.h>
#include <linux/string.h>
@@ -576,7 +577,7 @@ static int cachefiles_daemon_dir(struct cachefiles_cache *cache, char *args)
*/
static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args)
{
- char *secctx;
+ int err;
_enter(",%s", args);
@@ -585,16 +586,16 @@ static int cachefiles_daemon_secctx(struct cachefiles_cache *cache, char *args)
return -EINVAL;
}
- if (cache->secctx) {
+ if (cache->have_secid) {
pr_err("Second security context specified\n");
return -EINVAL;
}
- secctx = kstrdup(args, GFP_KERNEL);
- if (!secctx)
- return -ENOMEM;
+ err = security_secctx_to_secid(args, strlen(args), &cache->secid);
+ if (err)
+ return err;
- cache->secctx = secctx;
+ cache->have_secid = true;
return 0;
}
@@ -820,7 +821,6 @@ static void cachefiles_daemon_unbind(struct cachefiles_cache *cache)
put_cred(cache->cache_cred);
kfree(cache->rootdirname);
- kfree(cache->secctx);
kfree(cache->tag);
_leave("");
diff --git a/fs/cachefiles/internal.h b/fs/cachefiles/internal.h
index 7b99bd98de75..38c236e38cef 100644
--- a/fs/cachefiles/internal.h
+++ b/fs/cachefiles/internal.h
@@ -122,7 +122,6 @@ struct cachefiles_cache {
#define CACHEFILES_STATE_CHANGED 3 /* T if state changed (poll trigger) */
#define CACHEFILES_ONDEMAND_MODE 4 /* T if in on-demand read mode */
char *rootdirname; /* name of cache root directory */
- char *secctx; /* LSM security context */
char *tag; /* cache binding tag */
refcount_t unbind_pincount;/* refcount to do daemon unbind */
struct xarray reqs; /* xarray of pending on-demand requests */
@@ -130,6 +129,8 @@ struct cachefiles_cache {
struct xarray ondemand_ids; /* xarray for ondemand_id allocation */
u32 ondemand_id_next;
u32 msg_id_next;
+ u32 secid; /* LSM security id */
+ bool have_secid; /* whether "secid" was set */
};
static inline bool cachefiles_in_ondemand_mode(struct cachefiles_cache *cache)
diff --git a/fs/cachefiles/security.c b/fs/cachefiles/security.c
index fe777164f1d8..fc6611886b3b 100644
--- a/fs/cachefiles/security.c
+++ b/fs/cachefiles/security.c
@@ -18,7 +18,7 @@ int cachefiles_get_security_ID(struct cachefiles_cache *cache)
struct cred *new;
int ret;
- _enter("{%s}", cache->secctx);
+ _enter("{%u}", cache->have_secid ? cache->secid : 0);
new = prepare_kernel_cred(current);
if (!new) {
@@ -26,8 +26,8 @@ int cachefiles_get_security_ID(struct cachefiles_cache *cache)
goto error;
}
- if (cache->secctx) {
- ret = set_security_override_from_ctx(new, cache->secctx);
+ if (cache->have_secid) {
+ ret = set_security_override(new, cache->secid);
if (ret < 0) {
put_cred(new);
pr_err("Security denies permission to nominate security context: error %d\n",
diff --git a/fs/ceph/addr.c b/fs/ceph/addr.c
index 4c82348fe1e6..85936f6d2bf7 100644
--- a/fs/ceph/addr.c
+++ b/fs/ceph/addr.c
@@ -2195,7 +2195,7 @@ int ceph_pool_perm_check(struct inode *inode, int need)
if (ci->i_vino.snap != CEPH_NOSNAP) {
/*
* Pool permission check needs to write to the first object.
- * But for snapshot, head of the first object may have alread
+ * But for snapshot, head of the first object may have already
* been deleted. Skip check to avoid creating orphan object.
*/
return 0;
diff --git a/fs/ceph/caps.c b/fs/ceph/caps.c
index bed34fc11c91..a8d8b56cf9d2 100644
--- a/fs/ceph/caps.c
+++ b/fs/ceph/caps.c
@@ -978,20 +978,6 @@ int __ceph_caps_revoking_other(struct ceph_inode_info *ci,
return 0;
}
-int ceph_caps_revoking(struct ceph_inode_info *ci, int mask)
-{
- struct inode *inode = &ci->netfs.inode;
- struct ceph_client *cl = ceph_inode_to_client(inode);
- int ret;
-
- spin_lock(&ci->i_ceph_lock);
- ret = __ceph_caps_revoking_other(ci, NULL, mask);
- spin_unlock(&ci->i_ceph_lock);
- doutc(cl, "%p %llx.%llx %s = %d\n", inode, ceph_vinop(inode),
- ceph_cap_string(mask), ret);
- return ret;
-}
-
int __ceph_caps_used(struct ceph_inode_info *ci)
{
int used = 0;
@@ -2813,7 +2799,7 @@ void ceph_take_cap_refs(struct ceph_inode_info *ci, int got,
* requested from the MDS.
*
* Returns 0 if caps were not able to be acquired (yet), 1 if succeed,
- * or a negative error code. There are 3 speical error codes:
+ * or a negative error code. There are 3 special error codes:
* -EAGAIN: need to sleep but non-blocking is specified
* -EFBIG: ask caller to call check_max_size() and try again.
* -EUCLEAN: ask caller to call ceph_renew_caps() and try again.
@@ -4085,23 +4071,22 @@ static void handle_cap_export(struct inode *inode, struct ceph_mds_caps *ex,
struct ceph_cap *cap, *tcap, *new_cap = NULL;
struct ceph_inode_info *ci = ceph_inode(inode);
u64 t_cap_id;
- unsigned mseq = le32_to_cpu(ex->migrate_seq);
- unsigned t_seq, t_mseq;
+ u32 t_issue_seq, t_mseq;
int target, issued;
int mds = session->s_mds;
if (ph) {
t_cap_id = le64_to_cpu(ph->cap_id);
- t_seq = le32_to_cpu(ph->seq);
+ t_issue_seq = le32_to_cpu(ph->issue_seq);
t_mseq = le32_to_cpu(ph->mseq);
target = le32_to_cpu(ph->mds);
} else {
- t_cap_id = t_seq = t_mseq = 0;
+ t_cap_id = t_issue_seq = t_mseq = 0;
target = -1;
}
- doutc(cl, "%p %llx.%llx ci %p mds%d mseq %d target %d\n",
- inode, ceph_vinop(inode), ci, mds, mseq, target);
+ doutc(cl, " cap %llx.%llx export to peer %d piseq %u pmseq %u\n",
+ ceph_vinop(inode), target, t_issue_seq, t_mseq);
retry:
down_read(&mdsc->snap_rwsem);
spin_lock(&ci->i_ceph_lock);
@@ -4134,12 +4119,12 @@ retry:
if (tcap) {
/* already have caps from the target */
if (tcap->cap_id == t_cap_id &&
- ceph_seq_cmp(tcap->seq, t_seq) < 0) {
+ ceph_seq_cmp(tcap->seq, t_issue_seq) < 0) {
doutc(cl, " updating import cap %p mds%d\n", tcap,
target);
tcap->cap_id = t_cap_id;
- tcap->seq = t_seq - 1;
- tcap->issue_seq = t_seq - 1;
+ tcap->seq = t_issue_seq - 1;
+ tcap->issue_seq = t_issue_seq - 1;
tcap->issued |= issued;
tcap->implemented |= issued;
if (cap == ci->i_auth_cap) {
@@ -4154,7 +4139,7 @@ retry:
int flag = (cap == ci->i_auth_cap) ? CEPH_CAP_FLAG_AUTH : 0;
tcap = new_cap;
ceph_add_cap(inode, tsession, t_cap_id, issued, 0,
- t_seq - 1, t_mseq, (u64)-1, flag, &new_cap);
+ t_issue_seq - 1, t_mseq, (u64)-1, flag, &new_cap);
if (!list_empty(&ci->i_cap_flush_list) &&
ci->i_auth_cap == tcap) {
@@ -4228,18 +4213,22 @@ static void handle_cap_import(struct ceph_mds_client *mdsc,
u64 realmino = le64_to_cpu(im->realm);
u64 cap_id = le64_to_cpu(im->cap_id);
u64 p_cap_id;
+ u32 piseq = 0;
+ u32 pmseq = 0;
int peer;
if (ph) {
p_cap_id = le64_to_cpu(ph->cap_id);
peer = le32_to_cpu(ph->mds);
+ piseq = le32_to_cpu(ph->issue_seq);
+ pmseq = le32_to_cpu(ph->mseq);
} else {
p_cap_id = 0;
peer = -1;
}
- doutc(cl, "%p %llx.%llx ci %p mds%d mseq %d peer %d\n",
- inode, ceph_vinop(inode), ci, mds, mseq, peer);
+ doutc(cl, " cap %llx.%llx import from peer %d piseq %u pmseq %u\n",
+ ceph_vinop(inode), peer, piseq, pmseq);
retry:
cap = __get_cap_for_mds(ci, mds);
if (!cap) {
@@ -4268,15 +4257,13 @@ retry:
doutc(cl, " remove export cap %p mds%d flags %d\n",
ocap, peer, ph->flags);
if ((ph->flags & CEPH_CAP_FLAG_AUTH) &&
- (ocap->seq != le32_to_cpu(ph->seq) ||
- ocap->mseq != le32_to_cpu(ph->mseq))) {
+ (ocap->seq != piseq ||
+ ocap->mseq != pmseq)) {
pr_err_ratelimited_client(cl, "mismatched seq/mseq: "
"%p %llx.%llx mds%d seq %d mseq %d"
" importer mds%d has peer seq %d mseq %d\n",
inode, ceph_vinop(inode), peer,
- ocap->seq, ocap->mseq, mds,
- le32_to_cpu(ph->seq),
- le32_to_cpu(ph->mseq));
+ ocap->seq, ocap->mseq, mds, piseq, pmseq);
}
ceph_remove_cap(mdsc, ocap, (ph->flags & CEPH_CAP_FLAG_RELEASE));
}
@@ -4350,7 +4337,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
struct ceph_snap_realm *realm = NULL;
int op;
int msg_version = le16_to_cpu(msg->hdr.version);
- u32 seq, mseq;
+ u32 seq, mseq, issue_seq;
struct ceph_vino vino;
void *snaptrace;
size_t snaptrace_len;
@@ -4360,8 +4347,6 @@ void ceph_handle_caps(struct ceph_mds_session *session,
bool close_sessions = false;
bool do_cap_release = false;
- doutc(cl, "from mds%d\n", session->s_mds);
-
if (!ceph_inc_mds_stopping_blocker(mdsc, session))
return;
@@ -4375,6 +4360,7 @@ void ceph_handle_caps(struct ceph_mds_session *session,
vino.snap = CEPH_NOSNAP;
seq = le32_to_cpu(h->seq);
mseq = le32_to_cpu(h->migrate_seq);
+ issue_seq = le32_to_cpu(h->issue_seq);
snaptrace = h + 1;
snaptrace_len = le32_to_cpu(h->snap_trace_len);
@@ -4462,12 +4448,11 @@ void ceph_handle_caps(struct ceph_mds_session *session,
/* lookup ino */
inode = ceph_find_inode(mdsc->fsc->sb, vino);
- doutc(cl, " op %s ino %llx.%llx inode %p\n", ceph_cap_op_name(op),
- vino.ino, vino.snap, inode);
+ doutc(cl, " caps mds%d op %s ino %llx.%llx inode %p seq %u iseq %u mseq %u\n",
+ session->s_mds, ceph_cap_op_name(op), vino.ino, vino.snap, inode,
+ seq, issue_seq, mseq);
mutex_lock(&session->s_mutex);
- doutc(cl, " mds%d seq %lld cap seq %u\n", session->s_mds,
- session->s_seq, (unsigned)seq);
if (!inode) {
doutc(cl, " i don't have ino %llx\n", vino.ino);
diff --git a/fs/ceph/crypto.h b/fs/ceph/crypto.h
index 47e0c319fc68..d0768239a1c9 100644
--- a/fs/ceph/crypto.h
+++ b/fs/ceph/crypto.h
@@ -27,7 +27,7 @@ struct ceph_fname {
};
/*
- * Header for the crypted file when truncating the size, this
+ * Header for the encrypted file when truncating the size, this
* will be sent to MDS, and the MDS will update the encrypted
* last block and then truncate the size.
*/
diff --git a/fs/ceph/debugfs.c b/fs/ceph/debugfs.c
index 24c08078f5aa..fdf9dc15eafa 100644
--- a/fs/ceph/debugfs.c
+++ b/fs/ceph/debugfs.c
@@ -357,7 +357,7 @@ static int status_show(struct seq_file *s, void *p)
seq_printf(s, "instance: %s.%lld %s/%u\n", ENTITY_NAME(inst->name),
ceph_pr_addr(client_addr), le32_to_cpu(client_addr->nonce));
- seq_printf(s, "blocklisted: %s\n", fsc->blocklisted ? "true" : "false");
+ seq_printf(s, "blocklisted: %s\n", str_true_false(fsc->blocklisted));
return 0;
}
diff --git a/fs/ceph/dir.c b/fs/ceph/dir.c
index 952109292d69..0bf388e07a02 100644
--- a/fs/ceph/dir.c
+++ b/fs/ceph/dir.c
@@ -207,7 +207,7 @@ static int __dcache_readdir(struct file *file, struct dir_context *ctx,
dentry = __dcache_find_get_entry(parent, idx + step,
&cache_ctl);
if (!dentry) {
- /* use linar search */
+ /* use linear search */
idx = 0;
break;
}
@@ -659,7 +659,7 @@ static bool need_reset_readdir(struct ceph_dir_file_info *dfi, loff_t new_pos)
return true;
if (is_hash_order(new_pos)) {
/* no need to reset last_name for a forward seek when
- * dentries are sotred in hash order */
+ * dentries are sorted in hash order */
} else if (dfi->frag != fpos_frag(new_pos)) {
return true;
}
diff --git a/fs/ceph/export.c b/fs/ceph/export.c
index 44451749c544..150076ced937 100644
--- a/fs/ceph/export.c
+++ b/fs/ceph/export.c
@@ -393,9 +393,9 @@ static struct dentry *ceph_get_parent(struct dentry *child)
}
dir = snapdir;
}
- /* If directory has already been deleted, futher get_parent
+ /* If directory has already been deleted, further get_parent
* will fail. Do not mark snapdir dentry as disconnected,
- * this prevent exportfs from doing futher get_parent. */
+ * this prevents exportfs from doing further get_parent. */
if (unlinked)
dn = d_obtain_root(dir);
else
@@ -452,7 +452,13 @@ static int __get_snap_name(struct dentry *parent, char *name,
goto out;
if (ceph_snap(inode) == CEPH_SNAPDIR) {
if (ceph_snap(dir) == CEPH_NOSNAP) {
- strcpy(name, fsc->mount_options->snapdir_name);
+ /*
+ * .get_name() from struct export_operations
+ * assumes that its 'name' parameter is pointing
+ * to a NAME_MAX+1 sized buffer
+ */
+ strscpy(name, fsc->mount_options->snapdir_name,
+ NAME_MAX + 1);
err = 0;
}
goto out;
diff --git a/fs/ceph/file.c b/fs/ceph/file.c
index 4b8d59ebda00..851d70200c6b 100644
--- a/fs/ceph/file.c
+++ b/fs/ceph/file.c
@@ -1066,7 +1066,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
if (ceph_inode_is_shutdown(inode))
return -EIO;
- if (!len)
+ if (!len || !i_size)
return 0;
/*
* flush any page cache pages in this range. this
@@ -1086,7 +1086,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
int num_pages;
size_t page_off;
bool more;
- int idx;
+ int idx = 0;
size_t left;
struct ceph_osd_req_op *op;
u64 read_off = off;
@@ -1116,6 +1116,16 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
len = read_off + read_len - off;
more = len < iov_iter_count(to);
+ op = &req->r_ops[0];
+ if (sparse) {
+ extent_cnt = __ceph_sparse_read_ext_count(inode, read_len);
+ ret = ceph_alloc_sparse_ext_map(op, extent_cnt);
+ if (ret) {
+ ceph_osdc_put_request(req);
+ break;
+ }
+ }
+
num_pages = calc_pages_for(read_off, read_len);
page_off = offset_in_page(off);
pages = ceph_alloc_page_vector(num_pages, GFP_KERNEL);
@@ -1127,17 +1137,7 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
osd_req_op_extent_osd_data_pages(req, 0, pages, read_len,
offset_in_page(read_off),
- false, false);
-
- op = &req->r_ops[0];
- if (sparse) {
- extent_cnt = __ceph_sparse_read_ext_count(inode, read_len);
- ret = ceph_alloc_sparse_ext_map(op, extent_cnt);
- if (ret) {
- ceph_osdc_put_request(req);
- break;
- }
- }
+ false, true);
ceph_osdc_start_request(osdc, req);
ret = ceph_osdc_wait_request(osdc, req);
@@ -1160,7 +1160,14 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
else if (ret == -ENOENT)
ret = 0;
- if (ret > 0 && IS_ENCRYPTED(inode)) {
+ if (ret < 0) {
+ ceph_osdc_put_request(req);
+ if (ret == -EBLOCKLISTED)
+ fsc->blocklisted = true;
+ break;
+ }
+
+ if (IS_ENCRYPTED(inode)) {
int fret;
fret = ceph_fscrypt_decrypt_extents(inode, pages,
@@ -1186,10 +1193,8 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
ret = min_t(ssize_t, fret, len);
}
- ceph_osdc_put_request(req);
-
/* Short read but not EOF? Zero out the remainder. */
- if (ret >= 0 && ret < len && (off + ret < i_size)) {
+ if (ret < len && (off + ret < i_size)) {
int zlen = min(len - ret, i_size - off - ret);
int zoff = page_off + ret;
@@ -1199,13 +1204,11 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
ret += zlen;
}
- idx = 0;
- if (ret <= 0)
- left = 0;
- else if (off + ret > i_size)
- left = i_size - off;
+ if (off + ret > i_size)
+ left = (i_size > off) ? i_size - off : 0;
else
left = ret;
+
while (left > 0) {
size_t plen, copied;
@@ -1221,13 +1224,8 @@ ssize_t __ceph_sync_read(struct inode *inode, loff_t *ki_pos,
break;
}
}
- ceph_release_page_vector(pages, num_pages);
- if (ret < 0) {
- if (ret == -EBLOCKLISTED)
- fsc->blocklisted = true;
- break;
- }
+ ceph_osdc_put_request(req);
if (off >= i_size || !more)
break;
@@ -1553,6 +1551,16 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
break;
}
+ op = &req->r_ops[0];
+ if (!write && sparse) {
+ extent_cnt = __ceph_sparse_read_ext_count(inode, size);
+ ret = ceph_alloc_sparse_ext_map(op, extent_cnt);
+ if (ret) {
+ ceph_osdc_put_request(req);
+ break;
+ }
+ }
+
len = iter_get_bvecs_alloc(iter, size, &bvecs, &num_pages);
if (len < 0) {
ceph_osdc_put_request(req);
@@ -1562,6 +1570,8 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
if (len != size)
osd_req_op_extent_update(req, 0, len);
+ osd_req_op_extent_osd_data_bvecs(req, 0, bvecs, num_pages, len);
+
/*
* To simplify error handling, allow AIO when IO within i_size
* or IO can be satisfied by single OSD request.
@@ -1593,17 +1603,6 @@ ceph_direct_read_write(struct kiocb *iocb, struct iov_iter *iter,
req->r_mtime = mtime;
}
- osd_req_op_extent_osd_data_bvecs(req, 0, bvecs, num_pages, len);
- op = &req->r_ops[0];
- if (sparse) {
- extent_cnt = __ceph_sparse_read_ext_count(inode, size);
- ret = ceph_alloc_sparse_ext_map(op, extent_cnt);
- if (ret) {
- ceph_osdc_put_request(req);
- break;
- }
- }
-
if (aio_req) {
aio_req->total_len += len;
aio_req->num_reqs++;
diff --git a/fs/ceph/inode.c b/fs/ceph/inode.c
index 315ef02f9a3f..7dd6c2275085 100644
--- a/fs/ceph/inode.c
+++ b/fs/ceph/inode.c
@@ -160,7 +160,7 @@ struct inode *ceph_get_inode(struct super_block *sb, struct ceph_vino vino,
}
/*
- * get/constuct snapdir inode for a given directory
+ * get/construct snapdir inode for a given directory
*/
struct inode *ceph_get_snapdir(struct inode *parent)
{
diff --git a/fs/ceph/mds_client.c b/fs/ceph/mds_client.c
index c4a5fd94bbbb..785fe489ef4b 100644
--- a/fs/ceph/mds_client.c
+++ b/fs/ceph/mds_client.c
@@ -827,7 +827,7 @@ static void destroy_reply_info(struct ceph_mds_reply_info_parsed *info)
* And the worst case is that for the none async openc request it will
* successfully open the file if the CDentry hasn't been unlinked yet,
* but later the previous delayed async unlink request will remove the
- * CDenty. That means the just created file is possiblly deleted later
+ * CDentry. That means the just created file is possibly deleted later
* by accident.
*
* We need to wait for the inflight async unlink requests to finish
@@ -1747,14 +1747,6 @@ static void __open_export_target_sessions(struct ceph_mds_client *mdsc,
}
}
-void ceph_mdsc_open_export_target_sessions(struct ceph_mds_client *mdsc,
- struct ceph_mds_session *session)
-{
- mutex_lock(&mdsc->mutex);
- __open_export_target_sessions(mdsc, session);
- mutex_unlock(&mdsc->mutex);
-}
-
/*
* session caps
*/
@@ -2362,7 +2354,7 @@ again:
item->ino = cpu_to_le64(cap->cap_ino);
item->cap_id = cpu_to_le64(cap->cap_id);
item->migrate_seq = cpu_to_le32(cap->mseq);
- item->seq = cpu_to_le32(cap->issue_seq);
+ item->issue_seq = cpu_to_le32(cap->issue_seq);
msg->front.iov_len += sizeof(*item);
ceph_put_cap(mdsc, cap);
@@ -2808,12 +2800,11 @@ retry:
if (pos < 0) {
/*
- * A rename didn't occur, but somehow we didn't end up where
- * we thought we would. Throw a warning and try again.
+ * The path is longer than PATH_MAX and this function
+ * cannot ever succeed. Creating paths that long is
+ * possible with Ceph, but Linux cannot use them.
*/
- pr_warn_client(cl, "did not end path lookup where expected (pos = %d)\n",
- pos);
- goto retry;
+ return ERR_PTR(-ENAMETOOLONG);
}
*pbase = base;
@@ -3269,7 +3260,7 @@ static int __prepare_send_request(struct ceph_mds_session *session,
&session->s_features);
/*
- * Avoid inifinite retrying after overflow. The client will
+ * Avoid infinite retrying after overflow. The client will
* increase the retry count and if the MDS is old version,
* so we limit to retry at most 256 times.
*/
@@ -3522,7 +3513,7 @@ static void __do_request(struct ceph_mds_client *mdsc,
/*
* For async create we will choose the auth MDS of frag in parent
- * directory to send the request and ususally this works fine, but
+ * directory to send the request and usually this works fine, but
* if the migrated the dirtory to another MDS before it could handle
* it the request will be forwarded.
*
@@ -4033,7 +4024,7 @@ static void handle_forward(struct ceph_mds_client *mdsc,
__unregister_request(mdsc, req);
} else if (fwd_seq <= req->r_num_fwd || (uint32_t)fwd_seq >= U32_MAX) {
/*
- * Avoid inifinite retrying after overflow.
+ * Avoid infinite retrying after overflow.
*
* The MDS will increase the fwd count and in client side
* if the num_fwd is less than the one saved in request
@@ -5609,9 +5600,9 @@ void send_flush_mdlog(struct ceph_mds_session *s)
static int ceph_mds_auth_match(struct ceph_mds_client *mdsc,
struct ceph_mds_cap_auth *auth,
+ const struct cred *cred,
char *tpath)
{
- const struct cred *cred = get_current_cred();
u32 caller_uid = from_kuid(&init_user_ns, cred->fsuid);
u32 caller_gid = from_kgid(&init_user_ns, cred->fsgid);
struct ceph_client *cl = mdsc->fsc->client;
@@ -5734,11 +5725,12 @@ int ceph_mds_check_access(struct ceph_mds_client *mdsc, char *tpath, int mask)
for (i = 0; i < mdsc->s_cap_auths_num; i++) {
struct ceph_mds_cap_auth *s = &mdsc->s_cap_auths[i];
- err = ceph_mds_auth_match(mdsc, s, tpath);
+ err = ceph_mds_auth_match(mdsc, s, cred, tpath);
if (err < 0) {
+ put_cred(cred);
return err;
} else if (err > 0) {
- /* always follow the last auth caps' permision */
+ /* always follow the last auth caps' permission */
root_squash_perms = true;
rw_perms_s = NULL;
if ((mask & MAY_WRITE) && s->writeable &&
@@ -5751,6 +5743,8 @@ int ceph_mds_check_access(struct ceph_mds_client *mdsc, char *tpath, int mask)
}
}
+ put_cred(cred);
+
doutc(cl, "root_squash_perms %d, rw_perms_s %p\n", root_squash_perms,
rw_perms_s);
if (root_squash_perms && rw_perms_s == NULL) {
diff --git a/fs/ceph/mds_client.h b/fs/ceph/mds_client.h
index 3dd54587944a..38bb7e0d2d79 100644
--- a/fs/ceph/mds_client.h
+++ b/fs/ceph/mds_client.h
@@ -634,8 +634,6 @@ extern void ceph_mdsc_handle_fsmap(struct ceph_mds_client *mdsc,
extern struct ceph_mds_session *
ceph_mdsc_open_export_target_session(struct ceph_mds_client *mdsc, int target);
-extern void ceph_mdsc_open_export_target_sessions(struct ceph_mds_client *mdsc,
- struct ceph_mds_session *session);
extern int ceph_trim_caps(struct ceph_mds_client *mdsc,
struct ceph_mds_session *session,
diff --git a/fs/ceph/super.c b/fs/ceph/super.c
index 73f321b52895..4344e1f11806 100644
--- a/fs/ceph/super.c
+++ b/fs/ceph/super.c
@@ -285,8 +285,10 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
size_t len;
struct ceph_fsid fsid;
struct ceph_parse_opts_ctx *pctx = fc->fs_private;
+ struct ceph_options *opts = pctx->copts;
struct ceph_mount_options *fsopt = pctx->opts;
- char *fsid_start, *fs_name_start;
+ const char *name_start = dev_name;
+ const char *fsid_start, *fs_name_start;
if (*dev_name_end != '=') {
dout("separator '=' missing in source");
@@ -296,8 +298,14 @@ static int ceph_parse_new_source(const char *dev_name, const char *dev_name_end,
fsid_start = strchr(dev_name, '@');
if (!fsid_start)
return invalfc(fc, "missing cluster fsid");
- ++fsid_start; /* start of cluster fsid */
+ len = fsid_start - name_start;
+ kfree(opts->name);
+ opts->name = kstrndup(name_start, len, GFP_KERNEL);
+ if (!opts->name)
+ return -ENOMEM;
+ dout("using %s entity name", opts->name);
+ ++fsid_start; /* start of cluster fsid */
fs_name_start = strchr(fsid_start, '.');
if (!fs_name_start)
return invalfc(fc, "missing file system name");
@@ -423,6 +431,8 @@ static int ceph_parse_mount_param(struct fs_context *fc,
switch (token) {
case Opt_snapdirname:
+ if (strlen(param->string) > NAME_MAX)
+ return invalfc(fc, "snapdirname too long");
kfree(fsopt->snapdir_name);
fsopt->snapdir_name = param->string;
param->string = NULL;
diff --git a/fs/ceph/super.h b/fs/ceph/super.h
index 037eac35a9e0..af14ec382246 100644
--- a/fs/ceph/super.h
+++ b/fs/ceph/super.h
@@ -60,7 +60,7 @@
/* max size of osd read request, limited by libceph */
#define CEPH_MAX_READ_SIZE CEPH_MSG_MAX_DATA_LEN
-/* osd has a configurable limitaion of max write size.
+/* osd has a configurable limitation of max write size.
* CEPH_MSG_MAX_DATA_LEN should be small enough. */
#define CEPH_MAX_WRITE_SIZE CEPH_MSG_MAX_DATA_LEN
#define CEPH_RASIZE_DEFAULT (8192*1024) /* max readahead */
@@ -796,7 +796,6 @@ extern int __ceph_mark_dirty_caps(struct ceph_inode_info *ci, int mask,
extern int __ceph_caps_revoking_other(struct ceph_inode_info *ci,
struct ceph_cap *ocap, int mask);
-extern int ceph_caps_revoking(struct ceph_inode_info *ci, int mask);
extern int __ceph_caps_used(struct ceph_inode_info *ci);
static inline bool __ceph_is_file_opened(struct ceph_inode_info *ci)
diff --git a/fs/ceph/xattr.c b/fs/ceph/xattr.c
index e066a556eccb..1a9f12204666 100644
--- a/fs/ceph/xattr.c
+++ b/fs/ceph/xattr.c
@@ -899,7 +899,7 @@ static int __get_required_blob_size(struct ceph_inode_info *ci, int name_size,
}
/*
- * If there are dirty xattrs, reencode xattrs into the prealloc_blob
+ * If there are dirty xattrs, re-encode xattrs into the prealloc_blob
* and swap into place. It returns the old i_xattrs.blob (or NULL) so
* that it can be freed by the caller as the i_ceph_lock is likely to be
* held.
diff --git a/fs/efivarfs/inode.c b/fs/efivarfs/inode.c
index 586446e02ef7..ec23da8405ff 100644
--- a/fs/efivarfs/inode.c
+++ b/fs/efivarfs/inode.c
@@ -51,7 +51,7 @@ struct inode *efivarfs_get_inode(struct super_block *sb,
*
* VariableName-12345678-1234-1234-1234-1234567891bc
*/
-bool efivarfs_valid_name(const char *str, int len)
+static bool efivarfs_valid_name(const char *str, int len)
{
const char *s = str + len - EFI_VARIABLE_GUID_LEN;
diff --git a/fs/efivarfs/internal.h b/fs/efivarfs/internal.h
index d71d2e08422f..74f0602a9e01 100644
--- a/fs/efivarfs/internal.h
+++ b/fs/efivarfs/internal.h
@@ -60,7 +60,6 @@ bool efivar_variable_is_removable(efi_guid_t vendor, const char *name,
extern const struct file_operations efivarfs_file_operations;
extern const struct inode_operations efivarfs_dir_inode_operations;
-extern bool efivarfs_valid_name(const char *str, int len);
extern struct inode *efivarfs_get_inode(struct super_block *sb,
const struct inode *dir, int mode, dev_t dev,
bool is_removable);
diff --git a/fs/efivarfs/super.c b/fs/efivarfs/super.c
index a929f1b613be..beba15673be8 100644
--- a/fs/efivarfs/super.c
+++ b/fs/efivarfs/super.c
@@ -144,9 +144,6 @@ static int efivarfs_d_hash(const struct dentry *dentry, struct qstr *qstr)
const unsigned char *s = qstr->name;
unsigned int len = qstr->len;
- if (!efivarfs_valid_name(s, len))
- return -EINVAL;
-
while (len-- > EFI_VARIABLE_GUID_LEN)
hash = partial_name_hash(*s++, hash);
diff --git a/fs/efivarfs/vars.c b/fs/efivarfs/vars.c
index 3cc89bb624f0..f7d43c847ee9 100644
--- a/fs/efivarfs/vars.c
+++ b/fs/efivarfs/vars.c
@@ -22,7 +22,7 @@
#include "internal.h"
-MODULE_IMPORT_NS(EFIVAR);
+MODULE_IMPORT_NS("EFIVAR");
static bool
validate_device_path(efi_char16_t *var_name, int match, u8 *buffer,
diff --git a/fs/erofs/data.c b/fs/erofs/data.c
index 1c49f8962021..0cd6b5c4df98 100644
--- a/fs/erofs/data.c
+++ b/fs/erofs/data.c
@@ -56,10 +56,10 @@ void erofs_init_metabuf(struct erofs_buf *buf, struct super_block *sb)
buf->file = NULL;
if (erofs_is_fileio_mode(sbi)) {
- buf->file = sbi->fdev; /* some fs like FUSE needs it */
+ buf->file = sbi->dif0.file; /* some fs like FUSE needs it */
buf->mapping = buf->file->f_mapping;
} else if (erofs_is_fscache_mode(sb))
- buf->mapping = sbi->s_fscache->inode->i_mapping;
+ buf->mapping = sbi->dif0.fscache->inode->i_mapping;
else
buf->mapping = sb->s_bdev->bd_mapping;
}
@@ -179,19 +179,13 @@ out:
}
static void erofs_fill_from_devinfo(struct erofs_map_dev *map,
- struct erofs_device_info *dif)
+ struct super_block *sb, struct erofs_device_info *dif)
{
+ map->m_sb = sb;
+ map->m_dif = dif;
map->m_bdev = NULL;
- map->m_fp = NULL;
- if (dif->file) {
- if (S_ISBLK(file_inode(dif->file)->i_mode))
- map->m_bdev = file_bdev(dif->file);
- else
- map->m_fp = dif->file;
- }
- map->m_daxdev = dif->dax_dev;
- map->m_dax_part_off = dif->dax_part_off;
- map->m_fscache = dif->fscache;
+ if (dif->file && S_ISBLK(file_inode(dif->file)->i_mode))
+ map->m_bdev = file_bdev(dif->file);
}
int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
@@ -201,12 +195,8 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
erofs_off_t startoff, length;
int id;
- map->m_bdev = sb->s_bdev;
- map->m_daxdev = EROFS_SB(sb)->dax_dev;
- map->m_dax_part_off = EROFS_SB(sb)->dax_part_off;
- map->m_fscache = EROFS_SB(sb)->s_fscache;
- map->m_fp = EROFS_SB(sb)->fdev;
-
+ erofs_fill_from_devinfo(map, sb, &EROFS_SB(sb)->dif0);
+ map->m_bdev = sb->s_bdev; /* use s_bdev for the primary device */
if (map->m_deviceid) {
down_read(&devs->rwsem);
dif = idr_find(&devs->tree, map->m_deviceid - 1);
@@ -219,7 +209,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
up_read(&devs->rwsem);
return 0;
}
- erofs_fill_from_devinfo(map, dif);
+ erofs_fill_from_devinfo(map, sb, dif);
up_read(&devs->rwsem);
} else if (devs->extra_devices && !devs->flatdev) {
down_read(&devs->rwsem);
@@ -232,7 +222,7 @@ int erofs_map_dev(struct super_block *sb, struct erofs_map_dev *map)
if (map->m_pa >= startoff &&
map->m_pa < startoff + length) {
map->m_pa -= startoff;
- erofs_fill_from_devinfo(map, dif);
+ erofs_fill_from_devinfo(map, sb, dif);
break;
}
}
@@ -302,7 +292,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
iomap->offset = map.m_la;
if (flags & IOMAP_DAX)
- iomap->dax_dev = mdev.m_daxdev;
+ iomap->dax_dev = mdev.m_dif->dax_dev;
else
iomap->bdev = mdev.m_bdev;
iomap->length = map.m_llen;
@@ -331,7 +321,7 @@ static int erofs_iomap_begin(struct inode *inode, loff_t offset, loff_t length,
iomap->type = IOMAP_MAPPED;
iomap->addr = mdev.m_pa;
if (flags & IOMAP_DAX)
- iomap->addr += mdev.m_dax_part_off;
+ iomap->addr += mdev.m_dif->dax_part_off;
}
return 0;
}
diff --git a/fs/erofs/fileio.c b/fs/erofs/fileio.c
index 3af96b1e2c2a..33f8539dda4a 100644
--- a/fs/erofs/fileio.c
+++ b/fs/erofs/fileio.c
@@ -9,6 +9,7 @@ struct erofs_fileio_rq {
struct bio_vec bvecs[BIO_MAX_VECS];
struct bio bio;
struct kiocb iocb;
+ struct super_block *sb;
};
struct erofs_fileio {
@@ -52,8 +53,9 @@ static void erofs_fileio_rq_submit(struct erofs_fileio_rq *rq)
rq->iocb.ki_pos = rq->bio.bi_iter.bi_sector << SECTOR_SHIFT;
rq->iocb.ki_ioprio = get_current_ioprio();
rq->iocb.ki_complete = erofs_fileio_ki_complete;
- rq->iocb.ki_flags = (rq->iocb.ki_filp->f_mode & FMODE_CAN_ODIRECT) ?
- IOCB_DIRECT : 0;
+ if (test_opt(&EROFS_SB(rq->sb)->opt, DIRECT_IO) &&
+ rq->iocb.ki_filp->f_mode & FMODE_CAN_ODIRECT)
+ rq->iocb.ki_flags = IOCB_DIRECT;
iov_iter_bvec(&iter, ITER_DEST, rq->bvecs, rq->bio.bi_vcnt,
rq->bio.bi_iter.bi_size);
ret = vfs_iocb_iter_read(rq->iocb.ki_filp, &rq->iocb, &iter);
@@ -67,7 +69,8 @@ static struct erofs_fileio_rq *erofs_fileio_rq_alloc(struct erofs_map_dev *mdev)
GFP_KERNEL | __GFP_NOFAIL);
bio_init(&rq->bio, NULL, rq->bvecs, BIO_MAX_VECS, REQ_OP_READ);
- rq->iocb.ki_filp = mdev->m_fp;
+ rq->iocb.ki_filp = mdev->m_dif->file;
+ rq->sb = mdev->m_sb;
return rq;
}
diff --git a/fs/erofs/fscache.c b/fs/erofs/fscache.c
index fda16eedafb5..ce3d8737df85 100644
--- a/fs/erofs/fscache.c
+++ b/fs/erofs/fscache.c
@@ -198,7 +198,7 @@ struct bio *erofs_fscache_bio_alloc(struct erofs_map_dev *mdev)
io = kmalloc(sizeof(*io), GFP_KERNEL | __GFP_NOFAIL);
bio_init(&io->bio, NULL, io->bvecs, BIO_MAX_VECS, REQ_OP_READ);
- io->io.private = mdev->m_fscache->cookie;
+ io->io.private = mdev->m_dif->fscache->cookie;
io->io.end_io = erofs_fscache_bio_endio;
refcount_set(&io->io.ref, 1);
return &io->bio;
@@ -316,7 +316,7 @@ static int erofs_fscache_data_read_slice(struct erofs_fscache_rq *req)
if (!io)
return -ENOMEM;
iov_iter_xarray(&io->iter, ITER_DEST, &mapping->i_pages, pos, count);
- ret = erofs_fscache_read_io_async(mdev.m_fscache->cookie,
+ ret = erofs_fscache_read_io_async(mdev.m_dif->fscache->cookie,
mdev.m_pa + (pos - map.m_la), io);
erofs_fscache_req_io_put(io);
@@ -657,7 +657,7 @@ int erofs_fscache_register_fs(struct super_block *sb)
if (IS_ERR(fscache))
return PTR_ERR(fscache);
- sbi->s_fscache = fscache;
+ sbi->dif0.fscache = fscache;
return 0;
}
@@ -665,14 +665,14 @@ void erofs_fscache_unregister_fs(struct super_block *sb)
{
struct erofs_sb_info *sbi = EROFS_SB(sb);
- erofs_fscache_unregister_cookie(sbi->s_fscache);
+ erofs_fscache_unregister_cookie(sbi->dif0.fscache);
if (sbi->domain)
erofs_fscache_domain_put(sbi->domain);
else
fscache_relinquish_volume(sbi->volume, NULL, false);
- sbi->s_fscache = NULL;
+ sbi->dif0.fscache = NULL;
sbi->volume = NULL;
sbi->domain = NULL;
}
diff --git a/fs/erofs/internal.h b/fs/erofs/internal.h
index 1c847c30a918..686d835eb533 100644
--- a/fs/erofs/internal.h
+++ b/fs/erofs/internal.h
@@ -107,6 +107,7 @@ struct erofs_xattr_prefix_item {
};
struct erofs_sb_info {
+ struct erofs_device_info dif0;
struct erofs_mount_opts opt; /* options */
#ifdef CONFIG_EROFS_FS_ZIP
/* list for all registered superblocks, mainly for shrinker */
@@ -124,13 +125,9 @@ struct erofs_sb_info {
struct erofs_sb_lz4_info lz4;
#endif /* CONFIG_EROFS_FS_ZIP */
- struct file *fdev;
struct inode *packed_inode;
struct erofs_dev_context *devs;
- struct dax_device *dax_dev;
- u64 dax_part_off;
u64 total_blocks;
- u32 primarydevice_blocks;
u32 meta_blkaddr;
#ifdef CONFIG_EROFS_FS_XATTR
@@ -166,7 +163,6 @@ struct erofs_sb_info {
/* fscache support */
struct fscache_volume *volume;
- struct erofs_fscache *s_fscache;
struct erofs_domain *domain;
char *fsid;
char *domain_id;
@@ -180,6 +176,7 @@ struct erofs_sb_info {
#define EROFS_MOUNT_POSIX_ACL 0x00000020
#define EROFS_MOUNT_DAX_ALWAYS 0x00000040
#define EROFS_MOUNT_DAX_NEVER 0x00000080
+#define EROFS_MOUNT_DIRECT_IO 0x00000100
#define clear_opt(opt, option) ((opt)->mount_opt &= ~EROFS_MOUNT_##option)
#define set_opt(opt, option) ((opt)->mount_opt |= EROFS_MOUNT_##option)
@@ -187,7 +184,7 @@ struct erofs_sb_info {
static inline bool erofs_is_fileio_mode(struct erofs_sb_info *sbi)
{
- return IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && sbi->fdev;
+ return IS_ENABLED(CONFIG_EROFS_FS_BACKED_BY_FILE) && sbi->dif0.file;
}
static inline bool erofs_is_fscache_mode(struct super_block *sb)
@@ -357,11 +354,9 @@ enum {
};
struct erofs_map_dev {
- struct erofs_fscache *m_fscache;
+ struct super_block *m_sb;
+ struct erofs_device_info *m_dif;
struct block_device *m_bdev;
- struct dax_device *m_daxdev;
- struct file *m_fp;
- u64 m_dax_part_off;
erofs_off_t m_pa;
unsigned int m_deviceid;
diff --git a/fs/erofs/super.c b/fs/erofs/super.c
index c235a8e4315e..f5956474bfde 100644
--- a/fs/erofs/super.c
+++ b/fs/erofs/super.c
@@ -203,7 +203,7 @@ static int erofs_scan_devices(struct super_block *sb,
struct erofs_device_info *dif;
int id, err = 0;
- sbi->total_blocks = sbi->primarydevice_blocks;
+ sbi->total_blocks = sbi->dif0.blocks;
if (!erofs_sb_has_device_table(sbi))
ondisk_extradevs = 0;
else
@@ -307,7 +307,7 @@ static int erofs_read_superblock(struct super_block *sb)
sbi->sb_size);
goto out;
}
- sbi->primarydevice_blocks = le32_to_cpu(dsb->blocks);
+ sbi->dif0.blocks = le32_to_cpu(dsb->blocks);
sbi->meta_blkaddr = le32_to_cpu(dsb->meta_blkaddr);
#ifdef CONFIG_EROFS_FS_XATTR
sbi->xattr_blkaddr = le32_to_cpu(dsb->xattr_blkaddr);
@@ -364,14 +364,8 @@ static void erofs_default_options(struct erofs_sb_info *sbi)
}
enum {
- Opt_user_xattr,
- Opt_acl,
- Opt_cache_strategy,
- Opt_dax,
- Opt_dax_enum,
- Opt_device,
- Opt_fsid,
- Opt_domain_id,
+ Opt_user_xattr, Opt_acl, Opt_cache_strategy, Opt_dax, Opt_dax_enum,
+ Opt_device, Opt_fsid, Opt_domain_id, Opt_directio,
Opt_err
};
@@ -398,6 +392,7 @@ static const struct fs_parameter_spec erofs_fs_parameters[] = {
fsparam_string("device", Opt_device),
fsparam_string("fsid", Opt_fsid),
fsparam_string("domain_id", Opt_domain_id),
+ fsparam_flag_no("directio", Opt_directio),
{}
};
@@ -511,6 +506,16 @@ static int erofs_fc_parse_param(struct fs_context *fc,
errorfc(fc, "%s option not supported", erofs_fs_parameters[opt].name);
break;
#endif
+ case Opt_directio:
+#ifdef CONFIG_EROFS_FS_BACKED_BY_FILE
+ if (result.boolean)
+ set_opt(&sbi->opt, DIRECT_IO);
+ else
+ clear_opt(&sbi->opt, DIRECT_IO);
+#else
+ errorfc(fc, "%s option not supported", erofs_fs_parameters[opt].name);
+#endif
+ break;
default:
return -ENOPARAM;
}
@@ -602,9 +607,8 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
return -EINVAL;
}
- sbi->dax_dev = fs_dax_get_by_bdev(sb->s_bdev,
- &sbi->dax_part_off,
- NULL, NULL);
+ sbi->dif0.dax_dev = fs_dax_get_by_bdev(sb->s_bdev,
+ &sbi->dif0.dax_part_off, NULL, NULL);
}
err = erofs_read_superblock(sb);
@@ -627,7 +631,7 @@ static int erofs_fc_fill_super(struct super_block *sb, struct fs_context *fc)
}
if (test_opt(&sbi->opt, DAX_ALWAYS)) {
- if (!sbi->dax_dev) {
+ if (!sbi->dif0.dax_dev) {
errorfc(fc, "DAX unsupported by block device. Turning off DAX.");
clear_opt(&sbi->opt, DAX_ALWAYS);
} else if (sbi->blkszbits != PAGE_SHIFT) {
@@ -703,16 +707,18 @@ static int erofs_fc_get_tree(struct fs_context *fc)
GET_TREE_BDEV_QUIET_LOOKUP : 0);
#ifdef CONFIG_EROFS_FS_BACKED_BY_FILE
if (ret == -ENOTBLK) {
+ struct file *file;
+
if (!fc->source)
return invalf(fc, "No source specified");
- sbi->fdev = filp_open(fc->source, O_RDONLY | O_LARGEFILE, 0);
- if (IS_ERR(sbi->fdev))
- return PTR_ERR(sbi->fdev);
+ file = filp_open(fc->source, O_RDONLY | O_LARGEFILE, 0);
+ if (IS_ERR(file))
+ return PTR_ERR(file);
+ sbi->dif0.file = file;
- if (S_ISREG(file_inode(sbi->fdev)->i_mode) &&
- sbi->fdev->f_mapping->a_ops->read_folio)
+ if (S_ISREG(file_inode(sbi->dif0.file)->i_mode) &&
+ sbi->dif0.file->f_mapping->a_ops->read_folio)
return get_tree_nodev(fc, erofs_fc_fill_super);
- fput(sbi->fdev);
}
#endif
return ret;
@@ -763,19 +769,24 @@ static void erofs_free_dev_context(struct erofs_dev_context *devs)
kfree(devs);
}
-static void erofs_fc_free(struct fs_context *fc)
+static void erofs_sb_free(struct erofs_sb_info *sbi)
{
- struct erofs_sb_info *sbi = fc->s_fs_info;
-
- if (!sbi)
- return;
-
erofs_free_dev_context(sbi->devs);
kfree(sbi->fsid);
kfree(sbi->domain_id);
+ if (sbi->dif0.file)
+ fput(sbi->dif0.file);
kfree(sbi);
}
+static void erofs_fc_free(struct fs_context *fc)
+{
+ struct erofs_sb_info *sbi = fc->s_fs_info;
+
+ if (sbi) /* free here if an error occurs before transferring to sb */
+ erofs_sb_free(sbi);
+}
+
static const struct fs_context_operations erofs_context_ops = {
.parse_param = erofs_fc_parse_param,
.get_tree = erofs_fc_get_tree,
@@ -809,19 +820,14 @@ static void erofs_kill_sb(struct super_block *sb)
{
struct erofs_sb_info *sbi = EROFS_SB(sb);
- if ((IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid) || sbi->fdev)
+ if ((IS_ENABLED(CONFIG_EROFS_FS_ONDEMAND) && sbi->fsid) ||
+ sbi->dif0.file)
kill_anon_super(sb);
else
kill_block_super(sb);
-
- erofs_free_dev_context(sbi->devs);
- fs_put_dax(sbi->dax_dev, NULL);
+ fs_put_dax(sbi->dif0.dax_dev, NULL);
erofs_fscache_unregister_fs(sb);
- kfree(sbi->fsid);
- kfree(sbi->domain_id);
- if (sbi->fdev)
- fput(sbi->fdev);
- kfree(sbi);
+ erofs_sb_free(sbi);
sb->s_fs_info = NULL;
}
@@ -947,6 +953,8 @@ static int erofs_show_options(struct seq_file *seq, struct dentry *root)
seq_puts(seq, ",dax=always");
if (test_opt(opt, DAX_NEVER))
seq_puts(seq, ",dax=never");
+ if (erofs_is_fileio_mode(sbi) && test_opt(opt, DIRECT_IO))
+ seq_puts(seq, ",directio");
#ifdef CONFIG_EROFS_FS_ONDEMAND
if (sbi->fsid)
seq_printf(seq, ",fsid=%s", sbi->fsid);
diff --git a/fs/erofs/zdata.c b/fs/erofs/zdata.c
index 01f147505487..19ef4ff2a134 100644
--- a/fs/erofs/zdata.c
+++ b/fs/erofs/zdata.c
@@ -1792,9 +1792,9 @@ drain_io:
erofs_fscache_submit_bio(bio);
else
submit_bio(bio);
- if (memstall)
- psi_memstall_leave(&pflags);
}
+ if (memstall)
+ psi_memstall_leave(&pflags);
/*
* although background is preferred, no one is pending for submission.
diff --git a/fs/erofs/zutil.c b/fs/erofs/zutil.c
index 75704f58ecfa..0dd65cefce33 100644
--- a/fs/erofs/zutil.c
+++ b/fs/erofs/zutil.c
@@ -230,9 +230,10 @@ void erofs_shrinker_unregister(struct super_block *sb)
struct erofs_sb_info *const sbi = EROFS_SB(sb);
mutex_lock(&sbi->umount_mutex);
- /* clean up all remaining pclusters in memory */
- z_erofs_shrink_scan(sbi, ~0UL);
-
+ while (!xa_empty(&sbi->managed_pslots)) {
+ z_erofs_shrink_scan(sbi, ~0UL);
+ cond_resched();
+ }
spin_lock(&erofs_sb_list_lock);
list_del(&sbi->list);
spin_unlock(&erofs_sb_list_lock);
diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c
index fe0a9b8a0cd0..3103b932b674 100644
--- a/fs/exfat/dir.c
+++ b/fs/exfat/dir.c
@@ -122,7 +122,7 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
type = exfat_get_entry_type(ep);
if (type == TYPE_UNUSED) {
brelse(bh);
- break;
+ goto out;
}
if (type != TYPE_FILE && type != TYPE_DIR) {
@@ -170,6 +170,7 @@ static int exfat_readdir(struct inode *inode, loff_t *cpos, struct exfat_dir_ent
}
}
+out:
dir_entry->namebuf.lfn[0] = '\0';
*cpos = EXFAT_DEN_TO_B(dentry);
return 0;
diff --git a/fs/exfat/fatent.c b/fs/exfat/fatent.c
index 773c320d68f3..9e5492ac409b 100644
--- a/fs/exfat/fatent.c
+++ b/fs/exfat/fatent.c
@@ -216,6 +216,16 @@ static int __exfat_free_cluster(struct inode *inode, struct exfat_chain *p_chain
if (err)
goto dec_used_clus;
+
+ if (num_clusters >= sbi->num_clusters - EXFAT_FIRST_CLUSTER) {
+ /*
+ * The cluster chain includes a loop, scan the
+ * bitmap to get the number of used clusters.
+ */
+ exfat_count_used_clusters(sb, &sbi->used_clusters);
+
+ return 0;
+ }
} while (clu != EXFAT_EOF_CLUSTER);
}
diff --git a/fs/exfat/file.c b/fs/exfat/file.c
index fb38769c3e39..05b51e721783 100644
--- a/fs/exfat/file.c
+++ b/fs/exfat/file.c
@@ -545,6 +545,7 @@ static int exfat_extend_valid_size(struct file *file, loff_t new_valid_size)
while (pos < new_valid_size) {
u32 len;
struct folio *folio;
+ unsigned long off;
len = PAGE_SIZE - (pos & (PAGE_SIZE - 1));
if (pos + len > new_valid_size)
@@ -554,6 +555,9 @@ static int exfat_extend_valid_size(struct file *file, loff_t new_valid_size)
if (err)
goto out;
+ off = offset_in_folio(folio, pos);
+ folio_zero_new_buffers(folio, off, off + len);
+
err = ops->write_end(file, mapping, pos, len, len, folio, NULL);
if (err < 0)
goto out;
@@ -563,6 +567,8 @@ static int exfat_extend_valid_size(struct file *file, loff_t new_valid_size)
cond_resched();
}
+ return 0;
+
out:
return err;
}
diff --git a/fs/exfat/namei.c b/fs/exfat/namei.c
index 97d2774760fe..099f80645072 100644
--- a/fs/exfat/namei.c
+++ b/fs/exfat/namei.c
@@ -330,8 +330,8 @@ static int exfat_find_empty_entry(struct inode *inode,
while ((dentry = exfat_search_empty_slot(sb, &hint_femp, p_dir,
num_entries, es)) < 0) {
- if (dentry == -EIO)
- break;
+ if (dentry != -ENOSPC)
+ return dentry;
if (exfat_check_max_dentries(inode))
return -ENOSPC;
diff --git a/fs/file.c b/fs/file.c
index fb1011cf6b4a..25c6e53b03f8 100644
--- a/fs/file.c
+++ b/fs/file.c
@@ -22,6 +22,7 @@
#include <linux/close_range.h>
#include <linux/file_ref.h>
#include <net/sock.h>
+#include <linux/init_task.h>
#include "internal.h"
diff --git a/fs/fuse/dir.c b/fs/fuse/dir.c
index 494ac372ace0..e540d05549ff 100644
--- a/fs/fuse/dir.c
+++ b/fs/fuse/dir.c
@@ -1681,6 +1681,8 @@ static int fuse_dir_open(struct inode *inode, struct file *file)
*/
if (ff->open_flags & (FOPEN_STREAM | FOPEN_NONSEEKABLE))
nonseekable_open(inode, file);
+ if (!(ff->open_flags & FOPEN_KEEP_CACHE))
+ invalidate_inode_pages2(inode->i_mapping);
}
return err;
diff --git a/fs/hfs/super.c b/fs/hfs/super.c
index 3bee9b5dba5e..fe09c2093a93 100644
--- a/fs/hfs/super.c
+++ b/fs/hfs/super.c
@@ -349,11 +349,13 @@ static int hfs_fill_super(struct super_block *sb, struct fs_context *fc)
goto bail_no_root;
res = hfs_cat_find_brec(sb, HFS_ROOT_CNID, &fd);
if (!res) {
- if (fd.entrylength > sizeof(rec) || fd.entrylength < 0) {
+ if (fd.entrylength != sizeof(rec.dir)) {
res = -EIO;
goto bail_hfs_find;
}
hfs_bnode_read(fd.bnode, &rec, fd.entryoffset, fd.entrylength);
+ if (rec.type != HFS_CDR_DIR)
+ res = -EIO;
}
if (res)
goto bail_hfs_find;
diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c
index 6d1cf2436ead..7e51d2cec64b 100644
--- a/fs/hostfs/hostfs_kern.c
+++ b/fs/hostfs/hostfs_kern.c
@@ -57,6 +57,7 @@ static int __init hostfs_args(char *options, int *add)
{
char *ptr;
+ *add = 0;
ptr = strchr(options, ',');
if (ptr != NULL)
*ptr++ = '\0';
@@ -471,8 +472,8 @@ static int hostfs_write_begin(struct file *file, struct address_space *mapping,
*foliop = __filemap_get_folio(mapping, index, FGP_WRITEBEGIN,
mapping_gfp_mask(mapping));
- if (!*foliop)
- return -ENOMEM;
+ if (IS_ERR(*foliop))
+ return PTR_ERR(*foliop);
return 0;
}
diff --git a/fs/hugetlbfs/inode.c b/fs/hugetlbfs/inode.c
index a4441fb77f7c..fc1ae5132127 100644
--- a/fs/hugetlbfs/inode.c
+++ b/fs/hugetlbfs/inode.c
@@ -113,7 +113,7 @@ static int hugetlbfs_file_mmap(struct file *file, struct vm_area_struct *vma)
* way when do_mmap unwinds (may be important on powerpc
* and ia64).
*/
- vm_flags_set(vma, VM_HUGETLB | VM_DONTEXPAND | VM_MTE_ALLOWED);
+ vm_flags_set(vma, VM_HUGETLB | VM_DONTEXPAND);
vma->vm_ops = &hugetlb_vm_ops;
ret = seal_check_write(info->seals, vma);
@@ -825,7 +825,7 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
error = PTR_ERR(folio);
goto out;
}
- folio_zero_user(folio, ALIGN_DOWN(addr, hpage_size));
+ folio_zero_user(folio, addr);
__folio_mark_uptodate(folio);
error = hugetlb_add_to_page_cache(folio, mapping, index);
if (unlikely(error)) {
diff --git a/fs/iomap/buffered-io.c b/fs/iomap/buffered-io.c
index 955f19e27e47..54dc27d92781 100644
--- a/fs/iomap/buffered-io.c
+++ b/fs/iomap/buffered-io.c
@@ -1774,7 +1774,8 @@ static bool iomap_can_add_to_ioend(struct iomap_writepage_ctx *wpc, loff_t pos)
*/
static int iomap_add_to_ioend(struct iomap_writepage_ctx *wpc,
struct writeback_control *wbc, struct folio *folio,
- struct inode *inode, loff_t pos, unsigned len)
+ struct inode *inode, loff_t pos, loff_t end_pos,
+ unsigned len)
{
struct iomap_folio_state *ifs = folio->private;
size_t poff = offset_in_folio(folio, pos);
@@ -1793,15 +1794,60 @@ new_ioend:
if (ifs)
atomic_add(len, &ifs->write_bytes_pending);
+
+ /*
+ * Clamp io_offset and io_size to the incore EOF so that ondisk
+ * file size updates in the ioend completion are byte-accurate.
+ * This avoids recovering files with zeroed tail regions when
+ * writeback races with appending writes:
+ *
+ * Thread 1: Thread 2:
+ * ------------ -----------
+ * write [A, A+B]
+ * update inode size to A+B
+ * submit I/O [A, A+BS]
+ * write [A+B, A+B+C]
+ * update inode size to A+B+C
+ * <I/O completes, updates disk size to min(A+B+C, A+BS)>
+ * <power failure>
+ *
+ * After reboot:
+ * 1) with A+B+C < A+BS, the file has zero padding in range
+ * [A+B, A+B+C]
+ *
+ * |< Block Size (BS) >|
+ * |DDDDDDDDDDDD0000000000000|
+ * ^ ^ ^
+ * A A+B A+B+C
+ * (EOF)
+ *
+ * 2) with A+B+C > A+BS, the file has zero padding in range
+ * [A+B, A+BS]
+ *
+ * |< Block Size (BS) >|< Block Size (BS) >|
+ * |DDDDDDDDDDDD0000000000000|00000000000000000000000000|
+ * ^ ^ ^ ^
+ * A A+B A+BS A+B+C
+ * (EOF)
+ *
+ * D = Valid Data
+ * 0 = Zero Padding
+ *
+ * Note that this defeats the ability to chain the ioends of
+ * appending writes.
+ */
wpc->ioend->io_size += len;
+ if (wpc->ioend->io_offset + wpc->ioend->io_size > end_pos)
+ wpc->ioend->io_size = end_pos - wpc->ioend->io_offset;
+
wbc_account_cgroup_owner(wbc, folio, len);
return 0;
}
static int iomap_writepage_map_blocks(struct iomap_writepage_ctx *wpc,
struct writeback_control *wbc, struct folio *folio,
- struct inode *inode, u64 pos, unsigned dirty_len,
- unsigned *count)
+ struct inode *inode, u64 pos, u64 end_pos,
+ unsigned dirty_len, unsigned *count)
{
int error;
@@ -1826,7 +1872,7 @@ static int iomap_writepage_map_blocks(struct iomap_writepage_ctx *wpc,
break;
default:
error = iomap_add_to_ioend(wpc, wbc, folio, inode, pos,
- map_len);
+ end_pos, map_len);
if (!error)
(*count)++;
break;
@@ -1897,11 +1943,11 @@ static bool iomap_writepage_handle_eof(struct folio *folio, struct inode *inode,
* remaining memory is zeroed when mapped, and writes to that
* region are not written out to the file.
*
- * Also adjust the writeback range to skip all blocks entirely
- * beyond i_size.
+ * Also adjust the end_pos to the end of file and skip writeback
+ * for all blocks entirely beyond i_size.
*/
folio_zero_segment(folio, poff, folio_size(folio));
- *end_pos = round_up(isize, i_blocksize(inode));
+ *end_pos = isize;
}
return true;
@@ -1914,6 +1960,7 @@ static int iomap_writepage_map(struct iomap_writepage_ctx *wpc,
struct inode *inode = folio->mapping->host;
u64 pos = folio_pos(folio);
u64 end_pos = pos + folio_size(folio);
+ u64 end_aligned = 0;
unsigned count = 0;
int error = 0;
u32 rlen;
@@ -1955,9 +2002,10 @@ static int iomap_writepage_map(struct iomap_writepage_ctx *wpc,
/*
* Walk through the folio to find dirty areas to write back.
*/
- while ((rlen = iomap_find_dirty_range(folio, &pos, end_pos))) {
+ end_aligned = round_up(end_pos, i_blocksize(inode));
+ while ((rlen = iomap_find_dirty_range(folio, &pos, end_aligned))) {
error = iomap_writepage_map_blocks(wpc, wbc, folio, inode,
- pos, rlen, &count);
+ pos, end_pos, rlen, &count);
if (error)
break;
pos += rlen;
diff --git a/fs/jbd2/commit.c b/fs/jbd2/commit.c
index 9153ff3a08e7..e8e80761ac73 100644
--- a/fs/jbd2/commit.c
+++ b/fs/jbd2/commit.c
@@ -772,9 +772,9 @@ start_journal_io:
/*
* If the journal is not located on the file system device,
* then we must flush the file system device before we issue
- * the commit record
+ * the commit record and update the journal tail sequence.
*/
- if (commit_transaction->t_need_data_flush &&
+ if ((commit_transaction->t_need_data_flush || update_tail) &&
(journal->j_fs_dev != journal->j_dev) &&
(journal->j_flags & JBD2_BARRIER))
blkdev_issue_flush(journal->j_fs_dev);
diff --git a/fs/jbd2/revoke.c b/fs/jbd2/revoke.c
index 4556e4689024..ce63d5fde9c3 100644
--- a/fs/jbd2/revoke.c
+++ b/fs/jbd2/revoke.c
@@ -654,7 +654,7 @@ static void flush_descriptor(journal_t *journal,
set_buffer_jwrite(descriptor);
BUFFER_TRACE(descriptor, "write");
set_buffer_dirty(descriptor);
- write_dirty_buffer(descriptor, REQ_SYNC);
+ write_dirty_buffer(descriptor, JBD2_JOURNAL_REQ_FLAGS);
}
#endif
diff --git a/fs/jffs2/compr_rtime.c b/fs/jffs2/compr_rtime.c
index 79e771ab624f..3bd9d2f3bece 100644
--- a/fs/jffs2/compr_rtime.c
+++ b/fs/jffs2/compr_rtime.c
@@ -95,6 +95,9 @@ static int jffs2_rtime_decompress(unsigned char *data_in,
positions[value]=outpos;
if (repeat) {
+ if ((outpos + repeat) > destlen) {
+ return 1;
+ }
if (backoffs + repeat >= outpos) {
while(repeat) {
cpage_out[outpos++] = cpage_out[backoffs++];
diff --git a/fs/jffs2/compr_rubin.c b/fs/jffs2/compr_rubin.c
index 556de100ebd5..9854253d0108 100644
--- a/fs/jffs2/compr_rubin.c
+++ b/fs/jffs2/compr_rubin.c
@@ -276,11 +276,6 @@ static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in,
end_rubin(&rs);
- if (outpos > pos) {
- /* We failed */
- return -1;
- }
-
/* Tell the caller how much we managed to compress,
* and how much space it took */
diff --git a/fs/jffs2/erase.c b/fs/jffs2/erase.c
index acd32f05b519..ef3a1e1b6cb0 100644
--- a/fs/jffs2/erase.c
+++ b/fs/jffs2/erase.c
@@ -338,10 +338,9 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
} while(--retlen);
mtd_unpoint(c->mtd, jeb->offset, c->sector_size);
if (retlen) {
- pr_warn("Newly-erased block contained word 0x%lx at offset 0x%08tx\n",
- *wordebuf,
- jeb->offset +
- c->sector_size-retlen * sizeof(*wordebuf));
+ *bad_offset = jeb->offset + c->sector_size - retlen * sizeof(*wordebuf);
+ pr_warn("Newly-erased block contained word 0x%lx at offset 0x%08x\n",
+ *wordebuf, *bad_offset);
return -EIO;
}
return 0;
diff --git a/fs/jffs2/gc.c b/fs/jffs2/gc.c
index 822949d0eb00..1b833bbffcf5 100644
--- a/fs/jffs2/gc.c
+++ b/fs/jffs2/gc.c
@@ -82,7 +82,7 @@ again:
nextlist = &c->erasable_list;
} else if (!list_empty(&c->erasable_pending_wbuf_list)) {
- /* There are blocks are wating for the wbuf sync */
+ /* There are blocks are waiting for the wbuf sync */
jffs2_dbg(1, "Synching wbuf in order to reuse erasable_pending_wbuf_list blocks\n");
spin_unlock(&c->erase_completion_lock);
jffs2_flush_wbuf_pad(c);
diff --git a/fs/jffs2/nodemgmt.c b/fs/jffs2/nodemgmt.c
index bbab2bdc71b6..3fb9f9807b66 100644
--- a/fs/jffs2/nodemgmt.c
+++ b/fs/jffs2/nodemgmt.c
@@ -15,6 +15,7 @@
#include <linux/mtd/mtd.h>
#include <linux/compiler.h>
#include <linux/sched/signal.h>
+#include <linux/string_choices.h>
#include "nodelist.h"
#include "debug.h"
@@ -317,9 +318,9 @@ static int jffs2_find_nextblock(struct jffs2_sb_info *c)
And there's no space left. At all. */
pr_crit("Argh. No free space left for GC. nr_erasing_blocks is %d. nr_free_blocks is %d. (erasableempty: %s, erasingempty: %s, erasependingempty: %s)\n",
c->nr_erasing_blocks, c->nr_free_blocks,
- list_empty(&c->erasable_list) ? "yes" : "no",
- list_empty(&c->erasing_list) ? "yes" : "no",
- list_empty(&c->erase_pending_list) ? "yes" : "no");
+ str_yes_no(list_empty(&c->erasable_list)),
+ str_yes_no(list_empty(&c->erasing_list)),
+ str_yes_no(list_empty(&c->erase_pending_list)));
return -ENOSPC;
}
@@ -630,8 +631,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
ref->flash_offset, jeb->used_size);
BUG();
})
- jffs2_dbg(1, "Obsoleting previously unchecked node at 0x%08x of len %x\n",
- ref_offset(ref), freed_len);
+ jffs2_dbg(1, "Obsoleting previously unchecked node at 0x%08x of len %x\n",
+ ref_offset(ref), freed_len);
jeb->unchecked_size -= freed_len;
c->unchecked_size -= freed_len;
} else {
@@ -641,8 +642,8 @@ void jffs2_mark_node_obsolete(struct jffs2_sb_info *c, struct jffs2_raw_node_ref
ref->flash_offset, jeb->used_size);
BUG();
})
- jffs2_dbg(1, "Obsoleting node at 0x%08x of len %#x: ",
- ref_offset(ref), freed_len);
+ jffs2_dbg(1, "Obsoleting node at 0x%08x of len %#x: ",
+ ref_offset(ref), freed_len);
jeb->used_size -= freed_len;
c->used_size -= freed_len;
}
@@ -883,7 +884,7 @@ int jffs2_thread_should_wake(struct jffs2_sb_info *c)
jffs2_dbg(1, "%s(): nr_free_blocks %d, nr_erasing_blocks %d, dirty_size 0x%x, vdirty_blocks %d: %s\n",
__func__, c->nr_free_blocks, c->nr_erasing_blocks,
- c->dirty_size, nr_very_dirty, ret ? "yes" : "no");
+ c->dirty_size, nr_very_dirty, str_yes_no(ret));
return ret;
}
diff --git a/fs/jffs2/readinode.c b/fs/jffs2/readinode.c
index 03b4f99614be..f987f78a894e 100644
--- a/fs/jffs2/readinode.c
+++ b/fs/jffs2/readinode.c
@@ -72,7 +72,7 @@ static int check_node_data(struct jffs2_sb_info *c, struct jffs2_tmp_dnode_info
if (err != -EOPNOTSUPP)
JFFS2_WARNING("MTD point failed: error code %d.\n", err);
} else
- pointed = 1; /* succefully pointed to device */
+ pointed = 1; /* successfully pointed to device */
#endif
if (!pointed) {
diff --git a/fs/namespace.c b/fs/namespace.c
index 23e81c2a1e3f..6eec7794f707 100644
--- a/fs/namespace.c
+++ b/fs/namespace.c
@@ -2055,9 +2055,15 @@ SYSCALL_DEFINE1(oldumount, char __user *, name)
static bool is_mnt_ns_file(struct dentry *dentry)
{
+ struct ns_common *ns;
+
/* Is this a proxy for a mount namespace? */
- return dentry->d_op == &ns_dentry_operations &&
- dentry->d_fsdata == &mntns_operations;
+ if (dentry->d_op != &ns_dentry_operations)
+ return false;
+
+ ns = d_inode(dentry)->i_private;
+
+ return ns->ops == &mntns_operations;
}
struct ns_common *from_mnt_ns(struct mnt_namespace *mnt)
diff --git a/fs/netfs/buffered_read.c b/fs/netfs/buffered_read.c
index 7ac34550c403..4dc9b8286355 100644
--- a/fs/netfs/buffered_read.c
+++ b/fs/netfs/buffered_read.c
@@ -275,22 +275,14 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
netfs_stat(&netfs_n_rh_download);
if (rreq->netfs_ops->prepare_read) {
ret = rreq->netfs_ops->prepare_read(subreq);
- if (ret < 0) {
- atomic_dec(&rreq->nr_outstanding);
- netfs_put_subrequest(subreq, false,
- netfs_sreq_trace_put_cancel);
- break;
- }
+ if (ret < 0)
+ goto prep_failed;
trace_netfs_sreq(subreq, netfs_sreq_trace_prepare);
}
slice = netfs_prepare_read_iterator(subreq);
- if (slice < 0) {
- atomic_dec(&rreq->nr_outstanding);
- netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_cancel);
- ret = slice;
- break;
- }
+ if (slice < 0)
+ goto prep_iter_failed;
rreq->netfs_ops->issue_read(subreq);
goto done;
@@ -302,6 +294,8 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
trace_netfs_sreq(subreq, netfs_sreq_trace_submit);
netfs_stat(&netfs_n_rh_zero);
slice = netfs_prepare_read_iterator(subreq);
+ if (slice < 0)
+ goto prep_iter_failed;
__set_bit(NETFS_SREQ_CLEAR_TAIL, &subreq->flags);
netfs_read_subreq_terminated(subreq, 0, false);
goto done;
@@ -310,6 +304,8 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
if (source == NETFS_READ_FROM_CACHE) {
trace_netfs_sreq(subreq, netfs_sreq_trace_submit);
slice = netfs_prepare_read_iterator(subreq);
+ if (slice < 0)
+ goto prep_iter_failed;
netfs_read_cache_to_pagecache(rreq, subreq);
goto done;
}
@@ -318,6 +314,14 @@ static void netfs_read_to_pagecache(struct netfs_io_request *rreq)
WARN_ON_ONCE(1);
break;
+ prep_iter_failed:
+ ret = slice;
+ prep_failed:
+ subreq->error = ret;
+ atomic_dec(&rreq->nr_outstanding);
+ netfs_put_subrequest(subreq, false, netfs_sreq_trace_put_cancel);
+ break;
+
done:
size -= slice;
start += slice;
diff --git a/fs/netfs/direct_write.c b/fs/netfs/direct_write.c
index 88f2adfab75e..173e8b5e6a93 100644
--- a/fs/netfs/direct_write.c
+++ b/fs/netfs/direct_write.c
@@ -104,7 +104,6 @@ ssize_t netfs_unbuffered_write_iter_locked(struct kiocb *iocb, struct iov_iter *
trace_netfs_rreq(wreq, netfs_rreq_trace_wait_ip);
wait_on_bit(&wreq->flags, NETFS_RREQ_IN_PROGRESS,
TASK_UNINTERRUPTIBLE);
- smp_rmb(); /* Read error/transferred after RIP flag */
ret = wreq->error;
if (ret == 0) {
ret = wreq->transferred;
diff --git a/fs/netfs/read_collect.c b/fs/netfs/read_collect.c
index 3cbb289535a8..e8624f5c7fcc 100644
--- a/fs/netfs/read_collect.c
+++ b/fs/netfs/read_collect.c
@@ -62,10 +62,14 @@ static void netfs_unlock_read_folio(struct netfs_io_subrequest *subreq,
} else {
trace_netfs_folio(folio, netfs_folio_trace_read_done);
}
+
+ folioq_clear(folioq, slot);
} else {
// TODO: Use of PG_private_2 is deprecated.
if (test_bit(NETFS_SREQ_COPY_TO_CACHE, &subreq->flags))
netfs_pgpriv2_mark_copy_to_cache(subreq, rreq, folioq, slot);
+ else
+ folioq_clear(folioq, slot);
}
if (!test_bit(NETFS_RREQ_DONT_UNLOCK_FOLIOS, &rreq->flags)) {
@@ -77,8 +81,6 @@ static void netfs_unlock_read_folio(struct netfs_io_subrequest *subreq,
folio_unlock(folio);
}
}
-
- folioq_clear(folioq, slot);
}
/*
@@ -247,16 +249,17 @@ donation_changed:
/* Deal with the trickiest case: that this subreq is in the middle of a
* folio, not touching either edge, but finishes first. In such a
- * case, we donate to the previous subreq, if there is one, so that the
- * donation is only handled when that completes - and remove this
- * subreq from the list.
+ * case, we donate to the previous subreq, if there is one and if it is
+ * contiguous, so that the donation is only handled when that completes
+ * - and remove this subreq from the list.
*
* If the previous subreq finished first, we will have acquired their
* donation and should be able to unlock folios and/or donate nextwards.
*/
if (!subreq->consumed &&
!prev_donated &&
- !list_is_first(&subreq->rreq_link, &rreq->subrequests)) {
+ !list_is_first(&subreq->rreq_link, &rreq->subrequests) &&
+ subreq->start == prev->start + prev->len) {
prev = list_prev_entry(subreq, rreq_link);
WRITE_ONCE(prev->next_donated, prev->next_donated + subreq->len);
subreq->start += subreq->len;
@@ -378,8 +381,7 @@ static void netfs_rreq_assess(struct netfs_io_request *rreq)
task_io_account_read(rreq->transferred);
trace_netfs_rreq(rreq, netfs_rreq_trace_wake_ip);
- clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &rreq->flags);
- wake_up_bit(&rreq->flags, NETFS_RREQ_IN_PROGRESS);
+ clear_and_wake_up_bit(NETFS_RREQ_IN_PROGRESS, &rreq->flags);
trace_netfs_rreq(rreq, netfs_rreq_trace_done);
netfs_clear_subrequests(rreq, false);
@@ -438,7 +440,7 @@ void netfs_read_subreq_progress(struct netfs_io_subrequest *subreq,
rreq->origin == NETFS_READPAGE ||
rreq->origin == NETFS_READ_FOR_WRITE)) {
netfs_consume_read_data(subreq, was_async);
- __clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags);
+ __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
}
}
EXPORT_SYMBOL(netfs_read_subreq_progress);
@@ -497,7 +499,7 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq,
rreq->origin == NETFS_READPAGE ||
rreq->origin == NETFS_READ_FOR_WRITE)) {
netfs_consume_read_data(subreq, was_async);
- __clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags);
+ __set_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
}
rreq->transferred += subreq->transferred;
}
@@ -511,10 +513,13 @@ void netfs_read_subreq_terminated(struct netfs_io_subrequest *subreq,
} else {
trace_netfs_sreq(subreq, netfs_sreq_trace_short);
if (subreq->transferred > subreq->consumed) {
- __set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
- __clear_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags);
- set_bit(NETFS_RREQ_NEED_RETRY, &rreq->flags);
- } else if (!__test_and_set_bit(NETFS_SREQ_NO_PROGRESS, &subreq->flags)) {
+ /* If we didn't read new data, abandon retry. */
+ if (subreq->retry_count &&
+ test_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags)) {
+ __set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
+ set_bit(NETFS_RREQ_NEED_RETRY, &rreq->flags);
+ }
+ } else if (test_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags)) {
__set_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
set_bit(NETFS_RREQ_NEED_RETRY, &rreq->flags);
} else {
diff --git a/fs/netfs/read_pgpriv2.c b/fs/netfs/read_pgpriv2.c
index ba5af89d37fa..54d5004fec18 100644
--- a/fs/netfs/read_pgpriv2.c
+++ b/fs/netfs/read_pgpriv2.c
@@ -170,6 +170,10 @@ void netfs_pgpriv2_write_to_the_cache(struct netfs_io_request *rreq)
trace_netfs_write(wreq, netfs_write_trace_copy_to_cache);
netfs_stat(&netfs_n_wh_copy_to_cache);
+ if (!wreq->io_streams[1].avail) {
+ netfs_put_request(wreq, false, netfs_rreq_trace_put_return);
+ goto couldnt_start;
+ }
for (;;) {
error = netfs_pgpriv2_copy_folio(wreq, folio);
diff --git a/fs/netfs/read_retry.c b/fs/netfs/read_retry.c
index 0350592ea804..21b4a54e545e 100644
--- a/fs/netfs/read_retry.c
+++ b/fs/netfs/read_retry.c
@@ -49,13 +49,15 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
* up to the first permanently failed one.
*/
if (!rreq->netfs_ops->prepare_read &&
- !test_bit(NETFS_RREQ_COPY_TO_CACHE, &rreq->flags)) {
+ !rreq->cache_resources.ops) {
struct netfs_io_subrequest *subreq;
list_for_each_entry(subreq, &rreq->subrequests, rreq_link) {
if (test_bit(NETFS_SREQ_FAILED, &subreq->flags))
break;
if (__test_and_clear_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags)) {
+ __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
+ subreq->retry_count++;
netfs_reset_iter(subreq);
netfs_reissue_read(rreq, subreq);
}
@@ -137,7 +139,8 @@ static void netfs_retry_read_subrequests(struct netfs_io_request *rreq)
stream0->sreq_max_len = subreq->len;
__clear_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
- __set_bit(NETFS_SREQ_RETRYING, &subreq->flags);
+ __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
+ subreq->retry_count++;
spin_lock_bh(&rreq->lock);
list_add_tail(&subreq->rreq_link, &rreq->subrequests);
@@ -213,7 +216,6 @@ abandon:
subreq->error = -ENOMEM;
__clear_bit(NETFS_SREQ_FAILED, &subreq->flags);
__clear_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
- __clear_bit(NETFS_SREQ_RETRYING, &subreq->flags);
}
spin_lock_bh(&rreq->lock);
list_splice_tail_init(&queue, &rreq->subrequests);
diff --git a/fs/netfs/write_collect.c b/fs/netfs/write_collect.c
index 1d438be2e1b4..ca3a11ed9b54 100644
--- a/fs/netfs/write_collect.c
+++ b/fs/netfs/write_collect.c
@@ -179,7 +179,6 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
struct iov_iter source = subreq->io_iter;
iov_iter_revert(&source, subreq->len - source.count);
- __set_bit(NETFS_SREQ_RETRYING, &subreq->flags);
netfs_get_subrequest(subreq, netfs_sreq_trace_get_resubmit);
netfs_reissue_write(stream, subreq, &source);
}
@@ -234,7 +233,7 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
/* Renegotiate max_len (wsize) */
trace_netfs_sreq(subreq, netfs_sreq_trace_retry);
__clear_bit(NETFS_SREQ_NEED_RETRY, &subreq->flags);
- __set_bit(NETFS_SREQ_RETRYING, &subreq->flags);
+ subreq->retry_count++;
stream->prepare_write(subreq);
part = min(len, stream->sreq_max_len);
@@ -279,7 +278,7 @@ static void netfs_retry_write_stream(struct netfs_io_request *wreq,
subreq->start = start;
subreq->debug_index = atomic_inc_return(&wreq->subreq_counter);
subreq->stream_nr = to->stream_nr;
- __set_bit(NETFS_SREQ_RETRYING, &subreq->flags);
+ subreq->retry_count = 1;
trace_netfs_sreq_ref(wreq->debug_id, subreq->debug_index,
refcount_read(&subreq->ref),
@@ -501,8 +500,7 @@ reassess_streams:
goto need_retry;
if ((notes & MADE_PROGRESS) && test_bit(NETFS_RREQ_PAUSE, &wreq->flags)) {
trace_netfs_rreq(wreq, netfs_rreq_trace_unpause);
- clear_bit_unlock(NETFS_RREQ_PAUSE, &wreq->flags);
- wake_up_bit(&wreq->flags, NETFS_RREQ_PAUSE);
+ clear_and_wake_up_bit(NETFS_RREQ_PAUSE, &wreq->flags);
}
if (notes & NEED_REASSESS) {
@@ -605,8 +603,7 @@ void netfs_write_collection_worker(struct work_struct *work)
_debug("finished");
trace_netfs_rreq(wreq, netfs_rreq_trace_wake_ip);
- clear_bit_unlock(NETFS_RREQ_IN_PROGRESS, &wreq->flags);
- wake_up_bit(&wreq->flags, NETFS_RREQ_IN_PROGRESS);
+ clear_and_wake_up_bit(NETFS_RREQ_IN_PROGRESS, &wreq->flags);
if (wreq->iocb) {
size_t written = min(wreq->transferred, wreq->len);
@@ -714,8 +711,7 @@ void netfs_write_subrequest_terminated(void *_op, ssize_t transferred_or_error,
trace_netfs_sreq(subreq, netfs_sreq_trace_terminated);
- clear_bit_unlock(NETFS_SREQ_IN_PROGRESS, &subreq->flags);
- wake_up_bit(&subreq->flags, NETFS_SREQ_IN_PROGRESS);
+ clear_and_wake_up_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags);
/* If we are at the head of the queue, wake up the collector,
* transferring a ref to it if we were the ones to do so.
diff --git a/fs/netfs/write_issue.c b/fs/netfs/write_issue.c
index bf6d507578e5..ff0e82505a0b 100644
--- a/fs/netfs/write_issue.c
+++ b/fs/netfs/write_issue.c
@@ -244,6 +244,8 @@ void netfs_reissue_write(struct netfs_io_stream *stream,
iov_iter_advance(source, size);
iov_iter_truncate(&subreq->io_iter, size);
+ subreq->retry_count++;
+ __clear_bit(NETFS_SREQ_MADE_PROGRESS, &subreq->flags);
__set_bit(NETFS_SREQ_IN_PROGRESS, &subreq->flags);
netfs_do_issue_write(stream, subreq);
}
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index 0becdec12970..47189476b553 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -571,19 +571,32 @@ retry:
if (!node)
return ERR_PTR(-ENODEV);
+ /*
+ * Devices that are marked unavailable are left in the cache with a
+ * timeout to avoid sending GETDEVINFO after every LAYOUTGET, or
+ * constantly attempting to register the device. Once marked as
+ * unavailable they must be deleted and never reused.
+ */
if (test_bit(NFS_DEVICEID_UNAVAILABLE, &node->flags)) {
unsigned long end = jiffies;
unsigned long start = end - PNFS_DEVICE_RETRY_TIMEOUT;
if (!time_in_range(node->timestamp_unavailable, start, end)) {
+ /* Uncork subsequent GETDEVINFO operations for this device */
nfs4_delete_deviceid(node->ld, node->nfs_client, id);
goto retry;
}
goto out_put;
}
- if (!bl_register_dev(container_of(node, struct pnfs_block_dev, node)))
+ if (!bl_register_dev(container_of(node, struct pnfs_block_dev, node))) {
+ /*
+ * If we cannot register, treat this device as transient:
+ * Make a negative cache entry for the device
+ */
+ nfs4_mark_deviceid_unavailable(node);
goto out_put;
+ }
return node;
diff --git a/fs/nfs/blocklayout/dev.c b/fs/nfs/blocklayout/dev.c
index 6252f4447945..cab8809f0e0f 100644
--- a/fs/nfs/blocklayout/dev.c
+++ b/fs/nfs/blocklayout/dev.c
@@ -20,9 +20,6 @@ static void bl_unregister_scsi(struct pnfs_block_dev *dev)
const struct pr_ops *ops = bdev->bd_disk->fops->pr_ops;
int status;
- if (!test_and_clear_bit(PNFS_BDEV_REGISTERED, &dev->flags))
- return;
-
status = ops->pr_register(bdev, dev->pr_key, 0, false);
if (status)
trace_bl_pr_key_unreg_err(bdev, dev->pr_key, status);
@@ -58,7 +55,8 @@ static void bl_unregister_dev(struct pnfs_block_dev *dev)
return;
}
- if (dev->type == PNFS_BLOCK_VOLUME_SCSI)
+ if (dev->type == PNFS_BLOCK_VOLUME_SCSI &&
+ test_and_clear_bit(PNFS_BDEV_REGISTERED, &dev->flags))
bl_unregister_scsi(dev);
}
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 03ecc7765615..550ca934c9cf 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -55,9 +55,13 @@
#define NFSDBG_FACILITY NFSDBG_CLIENT
static DECLARE_WAIT_QUEUE_HEAD(nfs_client_active_wq);
-static DEFINE_SPINLOCK(nfs_version_lock);
-static DEFINE_MUTEX(nfs_version_mutex);
-static LIST_HEAD(nfs_versions);
+static DEFINE_RWLOCK(nfs_version_lock);
+
+static struct nfs_subversion *nfs_version_mods[5] = {
+ [2] = NULL,
+ [3] = NULL,
+ [4] = NULL,
+};
/*
* RPC cruft for NFS
@@ -76,38 +80,38 @@ const struct rpc_program nfs_program = {
.pipe_dir_name = NFS_PIPE_DIRNAME,
};
-static struct nfs_subversion *find_nfs_version(unsigned int version)
+static struct nfs_subversion *__find_nfs_version(unsigned int version)
{
struct nfs_subversion *nfs;
- spin_lock(&nfs_version_lock);
-
- list_for_each_entry(nfs, &nfs_versions, list) {
- if (nfs->rpc_ops->version == version) {
- spin_unlock(&nfs_version_lock);
- return nfs;
- }
- }
- spin_unlock(&nfs_version_lock);
- return ERR_PTR(-EPROTONOSUPPORT);
+ read_lock(&nfs_version_lock);
+ nfs = nfs_version_mods[version];
+ read_unlock(&nfs_version_lock);
+ return nfs;
}
-struct nfs_subversion *get_nfs_version(unsigned int version)
+struct nfs_subversion *find_nfs_version(unsigned int version)
{
- struct nfs_subversion *nfs = find_nfs_version(version);
+ struct nfs_subversion *nfs = __find_nfs_version(version);
- if (IS_ERR(nfs)) {
- mutex_lock(&nfs_version_mutex);
- request_module("nfsv%d", version);
- nfs = find_nfs_version(version);
- mutex_unlock(&nfs_version_mutex);
- }
+ if (!nfs && request_module("nfsv%d", version) == 0)
+ nfs = __find_nfs_version(version);
- if (!IS_ERR(nfs) && !try_module_get(nfs->owner))
+ if (!nfs)
+ return ERR_PTR(-EPROTONOSUPPORT);
+
+ if (!get_nfs_version(nfs))
return ERR_PTR(-EAGAIN);
+
return nfs;
}
+int get_nfs_version(struct nfs_subversion *nfs)
+{
+ return try_module_get(nfs->owner);
+}
+EXPORT_SYMBOL_GPL(get_nfs_version);
+
void put_nfs_version(struct nfs_subversion *nfs)
{
module_put(nfs->owner);
@@ -115,23 +119,23 @@ void put_nfs_version(struct nfs_subversion *nfs)
void register_nfs_version(struct nfs_subversion *nfs)
{
- spin_lock(&nfs_version_lock);
+ write_lock(&nfs_version_lock);
- list_add(&nfs->list, &nfs_versions);
+ nfs_version_mods[nfs->rpc_ops->version] = nfs;
nfs_version[nfs->rpc_ops->version] = nfs->rpc_vers;
- spin_unlock(&nfs_version_lock);
+ write_unlock(&nfs_version_lock);
}
EXPORT_SYMBOL_GPL(register_nfs_version);
void unregister_nfs_version(struct nfs_subversion *nfs)
{
- spin_lock(&nfs_version_lock);
+ write_lock(&nfs_version_lock);
nfs_version[nfs->rpc_ops->version] = NULL;
- list_del(&nfs->list);
+ nfs_version_mods[nfs->rpc_ops->version] = NULL;
- spin_unlock(&nfs_version_lock);
+ write_unlock(&nfs_version_lock);
}
EXPORT_SYMBOL_GPL(unregister_nfs_version);
@@ -151,7 +155,7 @@ struct nfs_client *nfs_alloc_client(const struct nfs_client_initdata *cl_init)
clp->cl_minorversion = cl_init->minorversion;
clp->cl_nfs_mod = cl_init->nfs_mod;
- if (!try_module_get(clp->cl_nfs_mod->owner))
+ if (!get_nfs_version(clp->cl_nfs_mod))
goto error_dealloc;
clp->rpc_ops = clp->cl_nfs_mod->rpc_ops;
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 90079ca134dd..b08dbe96bc57 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -454,8 +454,16 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
if (user_backed_iter(iter))
dreq->flags = NFS_ODIRECT_SHOULD_DIRTY;
- if (!swap)
- nfs_start_io_direct(inode);
+ if (!swap) {
+ result = nfs_start_io_direct(inode);
+ if (result) {
+ /* release the reference that would usually be
+ * consumed by nfs_direct_read_schedule_iovec()
+ */
+ nfs_direct_req_release(dreq);
+ goto out_release;
+ }
+ }
NFS_I(inode)->read_io += count;
requested = nfs_direct_read_schedule_iovec(dreq, iter, iocb->ki_pos);
@@ -1007,7 +1015,14 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
requested = nfs_direct_write_schedule_iovec(dreq, iter, pos,
FLUSH_STABLE);
} else {
- nfs_start_io_direct(inode);
+ result = nfs_start_io_direct(inode);
+ if (result) {
+ /* release the reference that would usually be
+ * consumed by nfs_direct_write_schedule_iovec()
+ */
+ nfs_direct_req_release(dreq);
+ goto out_release;
+ }
requested = nfs_direct_write_schedule_iovec(dreq, iter, pos,
FLUSH_COND_STABLE);
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 6800ee92d742..1bb646752e46 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -166,7 +166,10 @@ nfs_file_read(struct kiocb *iocb, struct iov_iter *to)
iocb->ki_filp,
iov_iter_count(to), (unsigned long) iocb->ki_pos);
- nfs_start_io_read(inode);
+ result = nfs_start_io_read(inode);
+ if (result)
+ return result;
+
result = nfs_revalidate_mapping(inode, iocb->ki_filp->f_mapping);
if (!result) {
result = generic_file_read_iter(iocb, to);
@@ -187,7 +190,10 @@ nfs_file_splice_read(struct file *in, loff_t *ppos, struct pipe_inode_info *pipe
dprintk("NFS: splice_read(%pD2, %zu@%llu)\n", in, len, *ppos);
- nfs_start_io_read(inode);
+ result = nfs_start_io_read(inode);
+ if (result)
+ return result;
+
result = nfs_revalidate_mapping(inode, in->f_mapping);
if (!result) {
result = filemap_splice_read(in, ppos, pipe, len, flags);
@@ -668,7 +674,9 @@ ssize_t nfs_file_write(struct kiocb *iocb, struct iov_iter *from)
nfs_clear_invalid_mapping(file->f_mapping);
since = filemap_sample_wb_err(file->f_mapping);
- nfs_start_io_write(inode);
+ error = nfs_start_io_write(inode);
+ if (error)
+ return error;
result = generic_write_checks(iocb, from);
if (result > 0)
result = generic_perform_write(iocb, from);
diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c
index 7e000d782e28..b069385eea17 100644
--- a/fs/nfs/fs_context.c
+++ b/fs/nfs/fs_context.c
@@ -1467,7 +1467,7 @@ static int nfs_fs_context_validate(struct fs_context *fc)
/* Load the NFS protocol module if we haven't done so yet */
if (!ctx->nfs_mod) {
- nfs_mod = get_nfs_version(ctx->version);
+ nfs_mod = find_nfs_version(ctx->version);
if (IS_ERR(nfs_mod)) {
ret = PTR_ERR(nfs_mod);
goto out_version_unavailable;
@@ -1541,7 +1541,7 @@ static int nfs_fs_context_dup(struct fs_context *fc, struct fs_context *src_fc)
}
nfs_copy_fh(ctx->mntfh, src->mntfh);
- __module_get(ctx->nfs_mod->owner);
+ get_nfs_version(ctx->nfs_mod);
ctx->client_address = NULL;
ctx->mount_server.hostname = NULL;
ctx->nfs_server.export_path = NULL;
@@ -1633,7 +1633,7 @@ static int nfs_init_fs_context(struct fs_context *fc)
}
ctx->nfs_mod = nfss->nfs_client->cl_nfs_mod;
- __module_get(ctx->nfs_mod->owner);
+ get_nfs_version(ctx->nfs_mod);
} else {
/* defaults */
ctx->timeo = NFS_UNSPEC_TIMEO;
diff --git a/fs/nfs/fscache.c b/fs/nfs/fscache.c
index 810269ee0a50..d49e4ce27999 100644
--- a/fs/nfs/fscache.c
+++ b/fs/nfs/fscache.c
@@ -263,6 +263,12 @@ int nfs_netfs_readahead(struct readahead_control *ractl)
static atomic_t nfs_netfs_debug_id;
static int nfs_netfs_init_request(struct netfs_io_request *rreq, struct file *file)
{
+ if (!file) {
+ if (WARN_ON_ONCE(rreq->origin != NETFS_PGPRIV2_COPY_TO_CACHE))
+ return -EIO;
+ return 0;
+ }
+
rreq->netfs_priv = get_nfs_open_context(nfs_file_open_context(file));
rreq->debug_id = atomic_inc_return(&nfs_netfs_debug_id);
/* [DEPRECATED] Use PG_private_2 to mark folio being written to the cache. */
@@ -274,7 +280,8 @@ static int nfs_netfs_init_request(struct netfs_io_request *rreq, struct file *fi
static void nfs_netfs_free_request(struct netfs_io_request *rreq)
{
- put_nfs_open_context(rreq->netfs_priv);
+ if (rreq->netfs_priv)
+ put_nfs_open_context(rreq->netfs_priv);
}
static struct nfs_netfs_io_data *nfs_netfs_alloc(struct netfs_io_subrequest *sreq)
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h
index 430733e3eff2..e564bd11ba60 100644
--- a/fs/nfs/internal.h
+++ b/fs/nfs/internal.h
@@ -6,13 +6,14 @@
#include "nfs4_fs.h"
#include <linux/fs_context.h>
#include <linux/security.h>
+#include <linux/compiler_attributes.h>
#include <linux/crc32.h>
#include <linux/sunrpc/addr.h>
#include <linux/nfs_page.h>
#include <linux/nfslocalio.h>
#include <linux/wait_bit.h>
-#define NFS_SB_MASK (SB_RDONLY|SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS)
+#define NFS_SB_MASK (SB_NOSUID|SB_NODEV|SB_NOEXEC|SB_SYNCHRONOUS)
extern const struct export_operations nfs_export_ops;
@@ -516,11 +517,11 @@ extern const struct netfs_request_ops nfs_netfs_ops;
#endif
/* io.c */
-extern void nfs_start_io_read(struct inode *inode);
+extern __must_check int nfs_start_io_read(struct inode *inode);
extern void nfs_end_io_read(struct inode *inode);
-extern void nfs_start_io_write(struct inode *inode);
+extern __must_check int nfs_start_io_write(struct inode *inode);
extern void nfs_end_io_write(struct inode *inode);
-extern void nfs_start_io_direct(struct inode *inode);
+extern __must_check int nfs_start_io_direct(struct inode *inode);
extern void nfs_end_io_direct(struct inode *inode);
static inline bool nfs_file_io_is_buffered(struct nfs_inode *nfsi)
diff --git a/fs/nfs/io.c b/fs/nfs/io.c
index b5551ed8f648..3388faf2acb9 100644
--- a/fs/nfs/io.c
+++ b/fs/nfs/io.c
@@ -39,19 +39,28 @@ static void nfs_block_o_direct(struct nfs_inode *nfsi, struct inode *inode)
* Note that buffered writes and truncates both take a write lock on
* inode->i_rwsem, meaning that those are serialised w.r.t. the reads.
*/
-void
+int
nfs_start_io_read(struct inode *inode)
{
struct nfs_inode *nfsi = NFS_I(inode);
+ int err;
+
/* Be an optimist! */
- down_read(&inode->i_rwsem);
+ err = down_read_killable(&inode->i_rwsem);
+ if (err)
+ return err;
if (test_bit(NFS_INO_ODIRECT, &nfsi->flags) == 0)
- return;
+ return 0;
up_read(&inode->i_rwsem);
+
/* Slow path.... */
- down_write(&inode->i_rwsem);
+ err = down_write_killable(&inode->i_rwsem);
+ if (err)
+ return err;
nfs_block_o_direct(nfsi, inode);
downgrade_write(&inode->i_rwsem);
+
+ return 0;
}
/**
@@ -74,11 +83,15 @@ nfs_end_io_read(struct inode *inode)
* Declare that a buffered read operation is about to start, and ensure
* that we block all direct I/O.
*/
-void
+int
nfs_start_io_write(struct inode *inode)
{
- down_write(&inode->i_rwsem);
- nfs_block_o_direct(NFS_I(inode), inode);
+ int err;
+
+ err = down_write_killable(&inode->i_rwsem);
+ if (!err)
+ nfs_block_o_direct(NFS_I(inode), inode);
+ return err;
}
/**
@@ -119,19 +132,28 @@ static void nfs_block_buffered(struct nfs_inode *nfsi, struct inode *inode)
* Note that buffered writes and truncates both take a write lock on
* inode->i_rwsem, meaning that those are serialised w.r.t. O_DIRECT.
*/
-void
+int
nfs_start_io_direct(struct inode *inode)
{
struct nfs_inode *nfsi = NFS_I(inode);
+ int err;
+
/* Be an optimist! */
- down_read(&inode->i_rwsem);
+ err = down_read_killable(&inode->i_rwsem);
+ if (err)
+ return err;
if (test_bit(NFS_INO_ODIRECT, &nfsi->flags) != 0)
- return;
+ return 0;
up_read(&inode->i_rwsem);
+
/* Slow path.... */
- down_write(&inode->i_rwsem);
+ err = down_write_killable(&inode->i_rwsem);
+ if (err)
+ return err;
nfs_block_buffered(nfsi, inode);
downgrade_write(&inode->i_rwsem);
+
+ return 0;
}
/**
diff --git a/fs/nfs/localio.c b/fs/nfs/localio.c
index 8f0ce82a677e..4b8618cf114c 100644
--- a/fs/nfs/localio.c
+++ b/fs/nfs/localio.c
@@ -42,10 +42,8 @@ struct nfs_local_fsync_ctx {
struct nfsd_file *localio;
struct nfs_commit_data *data;
struct work_struct work;
- struct kref kref;
struct completion *done;
};
-static void nfs_local_fsync_work(struct work_struct *work);
static bool localio_enabled __read_mostly = true;
module_param(localio_enabled, bool, 0644);
@@ -274,7 +272,7 @@ nfs_local_iocb_free(struct nfs_local_kiocb *iocb)
static struct nfs_local_kiocb *
nfs_local_iocb_alloc(struct nfs_pgio_header *hdr,
- struct nfsd_file *localio, gfp_t flags)
+ struct file *file, gfp_t flags)
{
struct nfs_local_kiocb *iocb;
@@ -287,9 +285,8 @@ nfs_local_iocb_alloc(struct nfs_pgio_header *hdr,
kfree(iocb);
return NULL;
}
- init_sync_kiocb(&iocb->kiocb, nfs_to->nfsd_file_file(localio));
+ init_sync_kiocb(&iocb->kiocb, file);
iocb->kiocb.ki_pos = hdr->args.offset;
- iocb->localio = localio;
iocb->hdr = hdr;
iocb->kiocb.ki_flags &= ~IOCB_APPEND;
return iocb;
@@ -354,6 +351,12 @@ nfs_local_read_done(struct nfs_local_kiocb *iocb, long status)
nfs_local_pgio_done(hdr, status);
+ /*
+ * Must clear replen otherwise NFSv3 data corruption will occur
+ * if/when switching from LOCALIO back to using normal RPC.
+ */
+ hdr->res.replen = 0;
+
if (hdr->res.count != hdr->args.count ||
hdr->args.offset + hdr->res.count >= i_size_read(file_inode(filp)))
hdr->res.eof = true;
@@ -390,13 +393,19 @@ nfs_do_local_read(struct nfs_pgio_header *hdr,
const struct rpc_call_ops *call_ops)
{
struct nfs_local_kiocb *iocb;
+ struct file *file = nfs_to->nfsd_file_file(localio);
+
+ /* Don't support filesystems without read_iter */
+ if (!file->f_op->read_iter)
+ return -EAGAIN;
dprintk("%s: vfs_read count=%u pos=%llu\n",
__func__, hdr->args.count, hdr->args.offset);
- iocb = nfs_local_iocb_alloc(hdr, localio, GFP_KERNEL);
+ iocb = nfs_local_iocb_alloc(hdr, file, GFP_KERNEL);
if (iocb == NULL)
return -ENOMEM;
+ iocb->localio = localio;
nfs_local_pgio_init(hdr, call_ops);
hdr->res.eof = false;
@@ -521,12 +530,7 @@ nfs_local_write_done(struct nfs_local_kiocb *iocb, long status)
}
if (status < 0)
nfs_reset_boot_verifier(inode);
- else if (nfs_should_remove_suid(inode)) {
- /* Deal with the suid/sgid bit corner case */
- spin_lock(&inode->i_lock);
- nfs_set_cache_invalid(inode, NFS_INO_INVALID_MODE);
- spin_unlock(&inode->i_lock);
- }
+
nfs_local_pgio_done(hdr, status);
}
@@ -564,14 +568,20 @@ nfs_do_local_write(struct nfs_pgio_header *hdr,
const struct rpc_call_ops *call_ops)
{
struct nfs_local_kiocb *iocb;
+ struct file *file = nfs_to->nfsd_file_file(localio);
+
+ /* Don't support filesystems without write_iter */
+ if (!file->f_op->write_iter)
+ return -EAGAIN;
dprintk("%s: vfs_write count=%u pos=%llu %s\n",
__func__, hdr->args.count, hdr->args.offset,
(hdr->args.stable == NFS_UNSTABLE) ? "unstable" : "stable");
- iocb = nfs_local_iocb_alloc(hdr, localio, GFP_NOIO);
+ iocb = nfs_local_iocb_alloc(hdr, file, GFP_NOIO);
if (iocb == NULL)
return -ENOMEM;
+ iocb->localio = localio;
switch (hdr->args.stable) {
default:
@@ -597,16 +607,9 @@ int nfs_local_doio(struct nfs_client *clp, struct nfsd_file *localio,
const struct rpc_call_ops *call_ops)
{
int status = 0;
- struct file *filp = nfs_to->nfsd_file_file(localio);
if (!hdr->args.count)
return 0;
- /* Don't support filesystems without read_iter/write_iter */
- if (!filp->f_op->read_iter || !filp->f_op->write_iter) {
- nfs_local_disable(clp);
- status = -EAGAIN;
- goto out;
- }
switch (hdr->rw_mode) {
case FMODE_READ:
@@ -620,8 +623,10 @@ int nfs_local_doio(struct nfs_client *clp, struct nfsd_file *localio,
hdr->rw_mode);
status = -EINVAL;
}
-out:
+
if (status != 0) {
+ if (status == -EAGAIN)
+ nfs_local_disable(clp);
nfs_to_nfsd_file_put_local(localio);
hdr->task.tk_status = status;
nfs_local_hdr_release(hdr, call_ops);
@@ -678,40 +683,12 @@ nfs_local_release_commit_data(struct nfsd_file *localio,
call_ops->rpc_release(data);
}
-static struct nfs_local_fsync_ctx *
-nfs_local_fsync_ctx_alloc(struct nfs_commit_data *data,
- struct nfsd_file *localio, gfp_t flags)
-{
- struct nfs_local_fsync_ctx *ctx = kmalloc(sizeof(*ctx), flags);
-
- if (ctx != NULL) {
- ctx->localio = localio;
- ctx->data = data;
- INIT_WORK(&ctx->work, nfs_local_fsync_work);
- kref_init(&ctx->kref);
- ctx->done = NULL;
- }
- return ctx;
-}
-
-static void
-nfs_local_fsync_ctx_kref_free(struct kref *kref)
-{
- kfree(container_of(kref, struct nfs_local_fsync_ctx, kref));
-}
-
-static void
-nfs_local_fsync_ctx_put(struct nfs_local_fsync_ctx *ctx)
-{
- kref_put(&ctx->kref, nfs_local_fsync_ctx_kref_free);
-}
-
static void
nfs_local_fsync_ctx_free(struct nfs_local_fsync_ctx *ctx)
{
nfs_local_release_commit_data(ctx->localio, ctx->data,
ctx->data->task.tk_ops);
- nfs_local_fsync_ctx_put(ctx);
+ kfree(ctx);
}
static void
@@ -730,6 +707,21 @@ nfs_local_fsync_work(struct work_struct *work)
nfs_local_fsync_ctx_free(ctx);
}
+static struct nfs_local_fsync_ctx *
+nfs_local_fsync_ctx_alloc(struct nfs_commit_data *data,
+ struct nfsd_file *localio, gfp_t flags)
+{
+ struct nfs_local_fsync_ctx *ctx = kmalloc(sizeof(*ctx), flags);
+
+ if (ctx != NULL) {
+ ctx->localio = localio;
+ ctx->data = data;
+ INIT_WORK(&ctx->work, nfs_local_fsync_work);
+ ctx->done = NULL;
+ }
+ return ctx;
+}
+
int nfs_local_commit(struct nfsd_file *localio,
struct nfs_commit_data *data,
const struct rpc_call_ops *call_ops, int how)
@@ -744,7 +736,7 @@ int nfs_local_commit(struct nfsd_file *localio,
}
nfs_local_init_commit(data, call_ops);
- kref_get(&ctx->kref);
+
if (how & FLUSH_SYNC) {
DECLARE_COMPLETION_ONSTACK(done);
ctx->done = &done;
@@ -752,6 +744,6 @@ int nfs_local_commit(struct nfsd_file *localio,
wait_for_completion(&done);
} else
queue_work(nfsiod_workqueue, &ctx->work);
- nfs_local_fsync_ctx_put(ctx);
+
return 0;
}
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index e7494cdd957e..2d53574da605 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -182,7 +182,7 @@ struct vfsmount *nfs_d_automount(struct path *path)
ctx->version = client->rpc_ops->version;
ctx->minorversion = client->cl_minorversion;
ctx->nfs_mod = client->cl_nfs_mod;
- __module_get(ctx->nfs_mod->owner);
+ get_nfs_version(ctx->nfs_mod);
ret = client->rpc_ops->submount(fc, server);
if (ret < 0) {
diff --git a/fs/nfs/nfs.h b/fs/nfs/nfs.h
index 0d3ce0460e35..8a5f51be013a 100644
--- a/fs/nfs/nfs.h
+++ b/fs/nfs/nfs.h
@@ -19,10 +19,10 @@ struct nfs_subversion {
const struct nfs_rpc_ops *rpc_ops; /* NFS operations */
const struct super_operations *sops; /* NFS Super operations */
const struct xattr_handler * const *xattr; /* NFS xattr handlers */
- struct list_head list; /* List of NFS versions */
};
-struct nfs_subversion *get_nfs_version(unsigned int);
+struct nfs_subversion *find_nfs_version(unsigned int);
+int get_nfs_version(struct nfs_subversion *);
void put_nfs_version(struct nfs_subversion *);
void register_nfs_version(struct nfs_subversion *);
void unregister_nfs_version(struct nfs_subversion *);
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 9d40319e063d..405f17e6e0b4 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -2603,12 +2603,14 @@ static void nfs4_open_release(void *calldata)
struct nfs4_opendata *data = calldata;
struct nfs4_state *state = NULL;
+ /* In case of error, no cleanup! */
+ if (data->rpc_status != 0 || !data->rpc_done) {
+ nfs_release_seqid(data->o_arg.seqid);
+ goto out_free;
+ }
/* If this request hasn't been cancelled, do nothing */
if (!data->cancelled)
goto out_free;
- /* In case of error, no cleanup! */
- if (data->rpc_status != 0 || !data->rpc_done)
- goto out_free;
/* In case we need an open_confirm, no cleanup! */
if (data->o_res.rflags & NFS4_OPEN_RESULT_CONFIRM)
goto out_free;
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index dafd61186557..9a9f60a2291b 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -1083,14 +1083,12 @@ void nfs_release_seqid(struct nfs_seqid *seqid)
return;
sequence = seqid->sequence;
spin_lock(&sequence->lock);
- list_del_init(&seqid->list);
- if (!list_empty(&sequence->list)) {
- struct nfs_seqid *next;
-
- next = list_first_entry(&sequence->list,
- struct nfs_seqid, list);
+ if (list_is_first(&seqid->list, &sequence->list) &&
+ !list_is_singular(&sequence->list)) {
+ struct nfs_seqid *next = list_next_entry(seqid, list);
rpc_wake_up_queued_task(&sequence->wait, next->task);
}
+ list_del_init(&seqid->list);
spin_unlock(&sequence->lock);
}
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index 0d16b383a452..5f582713bf05 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -1308,7 +1308,7 @@ pnfs_prepare_layoutreturn(struct pnfs_layout_hdr *lo,
enum pnfs_iomode *iomode)
{
/* Serialise LAYOUTGET/LAYOUTRETURN */
- if (atomic_read(&lo->plh_outstanding) != 0)
+ if (atomic_read(&lo->plh_outstanding) != 0 && lo->plh_return_seq == 0)
return false;
if (test_and_set_bit(NFS_LAYOUT_RETURN_LOCK, &lo->plh_flags))
return false;
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ae5c5e39afa0..aeb715b4a690 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -73,6 +73,7 @@
#include "nfs.h"
#include "netns.h"
#include "sysfs.h"
+#include "nfs4idmap.h"
#define NFSDBG_FACILITY NFSDBG_VFS
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index ead2dc55952d..50fa539611f5 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -144,6 +144,31 @@ static void nfs_io_completion_put(struct nfs_io_completion *ioc)
kref_put(&ioc->refcount, nfs_io_completion_release);
}
+static void
+nfs_page_set_inode_ref(struct nfs_page *req, struct inode *inode)
+{
+ if (!test_and_set_bit(PG_INODE_REF, &req->wb_flags)) {
+ kref_get(&req->wb_kref);
+ atomic_long_inc(&NFS_I(inode)->nrequests);
+ }
+}
+
+static int
+nfs_cancel_remove_inode(struct nfs_page *req, struct inode *inode)
+{
+ int ret;
+
+ if (!test_bit(PG_REMOVE, &req->wb_flags))
+ return 0;
+ ret = nfs_page_group_lock(req);
+ if (ret)
+ return ret;
+ if (test_and_clear_bit(PG_REMOVE, &req->wb_flags))
+ nfs_page_set_inode_ref(req, inode);
+ nfs_page_group_unlock(req);
+ return 0;
+}
+
/**
* nfs_folio_find_head_request - find head request associated with a folio
* @folio: pointer to folio
@@ -540,7 +565,6 @@ static struct nfs_page *nfs_lock_and_join_requests(struct folio *folio)
struct inode *inode = folio->mapping->host;
struct nfs_page *head, *subreq;
struct nfs_commit_info cinfo;
- bool removed;
int ret;
/*
@@ -565,18 +589,18 @@ retry:
goto retry;
}
- ret = nfs_page_group_lock(head);
+ ret = nfs_cancel_remove_inode(head, inode);
if (ret < 0)
goto out_unlock;
- removed = test_bit(PG_REMOVE, &head->wb_flags);
+ ret = nfs_page_group_lock(head);
+ if (ret < 0)
+ goto out_unlock;
/* lock each request in the page group */
for (subreq = head->wb_this_page;
subreq != head;
subreq = subreq->wb_this_page) {
- if (test_bit(PG_REMOVE, &subreq->wb_flags))
- removed = true;
ret = nfs_page_group_lock_subreq(head, subreq);
if (ret < 0)
goto out_unlock;
@@ -584,21 +608,6 @@ retry:
nfs_page_group_unlock(head);
- /*
- * If PG_REMOVE is set on any request, I/O on that request has
- * completed, but some requests were still under I/O at the time
- * we locked the head request.
- *
- * In that case the above wait for all requests means that all I/O
- * has now finished, and we can restart from a clean slate. Let the
- * old requests go away and start from scratch instead.
- */
- if (removed) {
- nfs_unroll_locks(head, head);
- nfs_unlock_and_release_request(head);
- goto retry;
- }
-
nfs_init_cinfo_from_inode(&cinfo, inode);
nfs_join_page_group(head, &cinfo, inode);
return head;
@@ -772,7 +781,8 @@ static void nfs_inode_add_request(struct nfs_page *req)
nfs_lock_request(req);
spin_lock(&mapping->i_private_lock);
set_bit(PG_MAPPED, &req->wb_flags);
- folio_attach_private(folio, req);
+ folio_set_private(folio);
+ folio->private = req;
spin_unlock(&mapping->i_private_lock);
atomic_long_inc(&nfsi->nrequests);
/* this a head request for a page group - mark it as having an
@@ -796,7 +806,8 @@ static void nfs_inode_remove_request(struct nfs_page *req)
spin_lock(&mapping->i_private_lock);
if (likely(folio)) {
- folio_detach_private(folio);
+ folio->private = NULL;
+ folio_clear_private(folio);
clear_bit(PG_MAPPED, &req->wb_head->wb_flags);
}
spin_unlock(&mapping->i_private_lock);
diff --git a/fs/nfsd/export.c b/fs/nfsd/export.c
index eacafe46e3b6..aa4712362b3b 100644
--- a/fs/nfsd/export.c
+++ b/fs/nfsd/export.c
@@ -40,24 +40,15 @@
#define EXPKEY_HASHMAX (1 << EXPKEY_HASHBITS)
#define EXPKEY_HASHMASK (EXPKEY_HASHMAX -1)
-static void expkey_put_work(struct work_struct *work)
+static void expkey_put(struct kref *ref)
{
- struct svc_expkey *key =
- container_of(to_rcu_work(work), struct svc_expkey, ek_rcu_work);
+ struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
if (test_bit(CACHE_VALID, &key->h.flags) &&
!test_bit(CACHE_NEGATIVE, &key->h.flags))
path_put(&key->ek_path);
auth_domain_put(key->ek_client);
- kfree(key);
-}
-
-static void expkey_put(struct kref *ref)
-{
- struct svc_expkey *key = container_of(ref, struct svc_expkey, h.ref);
-
- INIT_RCU_WORK(&key->ek_rcu_work, expkey_put_work);
- queue_rcu_work(system_wq, &key->ek_rcu_work);
+ kfree_rcu(key, ek_rcu);
}
static int expkey_upcall(struct cache_detail *cd, struct cache_head *h)
@@ -364,26 +355,16 @@ static void export_stats_destroy(struct export_stats *stats)
EXP_STATS_COUNTERS_NUM);
}
-static void svc_export_put_work(struct work_struct *work)
+static void svc_export_put(struct kref *ref)
{
- struct svc_export *exp =
- container_of(to_rcu_work(work), struct svc_export, ex_rcu_work);
-
+ struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
path_put(&exp->ex_path);
auth_domain_put(exp->ex_client);
nfsd4_fslocs_free(&exp->ex_fslocs);
export_stats_destroy(exp->ex_stats);
kfree(exp->ex_stats);
kfree(exp->ex_uuid);
- kfree(exp);
-}
-
-static void svc_export_put(struct kref *ref)
-{
- struct svc_export *exp = container_of(ref, struct svc_export, h.ref);
-
- INIT_RCU_WORK(&exp->ex_rcu_work, svc_export_put_work);
- queue_rcu_work(system_wq, &exp->ex_rcu_work);
+ kfree_rcu(exp, ex_rcu);
}
static int svc_export_upcall(struct cache_detail *cd, struct cache_head *h)
diff --git a/fs/nfsd/export.h b/fs/nfsd/export.h
index 6f2fbaae01fa..4d92b99c1ffd 100644
--- a/fs/nfsd/export.h
+++ b/fs/nfsd/export.h
@@ -75,7 +75,7 @@ struct svc_export {
u32 ex_layout_types;
struct nfsd4_deviceid_map *ex_devid_map;
struct cache_detail *cd;
- struct rcu_work ex_rcu_work;
+ struct rcu_head ex_rcu;
unsigned long ex_xprtsec_modes;
struct export_stats *ex_stats;
};
@@ -92,7 +92,7 @@ struct svc_expkey {
u32 ek_fsid[6];
struct path ek_path;
- struct rcu_work ek_rcu_work;
+ struct rcu_head ek_rcu;
};
#define EX_ISSYNC(exp) (!((exp)->ex_flags & NFSEXP_ASYNC))
diff --git a/fs/nfsd/nfs4callback.c b/fs/nfsd/nfs4callback.c
index 3877b53e429f..c083e539e898 100644
--- a/fs/nfsd/nfs4callback.c
+++ b/fs/nfsd/nfs4callback.c
@@ -1100,7 +1100,7 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
args.authflavor = clp->cl_cred.cr_flavor;
clp->cl_cb_ident = conn->cb_ident;
} else {
- if (!conn->cb_xprt)
+ if (!conn->cb_xprt || !ses)
return -EINVAL;
clp->cl_cb_session = ses;
args.bc_xprt = conn->cb_xprt;
@@ -1522,8 +1522,6 @@ static void nfsd4_process_cb_update(struct nfsd4_callback *cb)
ses = c->cn_session;
}
spin_unlock(&clp->cl_lock);
- if (!c)
- return;
err = setup_callback_client(clp, &conn, ses);
if (err) {
diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index f8a10f90bc7a..ad44ad49274f 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -1347,7 +1347,6 @@ static void nfs4_put_copy(struct nfsd4_copy *copy)
{
if (!refcount_dec_and_test(&copy->refcount))
return;
- atomic_dec(&copy->cp_nn->pending_async_copies);
kfree(copy->cp_src);
kfree(copy);
}
@@ -1870,6 +1869,7 @@ do_callback:
set_bit(NFSD4_COPY_F_COMPLETED, &copy->cp_flags);
trace_nfsd_copy_async_done(copy);
nfsd4_send_cb_offload(copy);
+ atomic_dec(&copy->cp_nn->pending_async_copies);
return 0;
}
@@ -1927,19 +1927,19 @@ nfsd4_copy(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
/* Arbitrary cap on number of pending async copy operations */
if (atomic_inc_return(&nn->pending_async_copies) >
(int)rqstp->rq_pool->sp_nrthreads)
- goto out_err;
+ goto out_dec_async_copy_err;
async_copy->cp_src = kmalloc(sizeof(*async_copy->cp_src), GFP_KERNEL);
if (!async_copy->cp_src)
- goto out_err;
+ goto out_dec_async_copy_err;
if (!nfs4_init_copy_state(nn, copy))
- goto out_err;
+ goto out_dec_async_copy_err;
memcpy(&result->cb_stateid, &copy->cp_stateid.cs_stid,
sizeof(result->cb_stateid));
dup_copy_fields(copy, async_copy);
async_copy->copy_task = kthread_create(nfsd4_do_async_copy,
async_copy, "%s", "copy thread");
if (IS_ERR(async_copy->copy_task))
- goto out_err;
+ goto out_dec_async_copy_err;
spin_lock(&async_copy->cp_clp->async_lock);
list_add(&async_copy->copies,
&async_copy->cp_clp->async_copies);
@@ -1954,6 +1954,9 @@ out:
trace_nfsd_copy_done(copy, status);
release_copy_files(copy);
return status;
+out_dec_async_copy_err:
+ if (async_copy)
+ atomic_dec(&nn->pending_async_copies);
out_err:
if (nfsd4_ssc_is_inter(copy)) {
/*
diff --git a/fs/nilfs2/btnode.c b/fs/nilfs2/btnode.c
index 501ad7be5174..54a3fa0cf67e 100644
--- a/fs/nilfs2/btnode.c
+++ b/fs/nilfs2/btnode.c
@@ -35,6 +35,7 @@ void nilfs_init_btnc_inode(struct inode *btnc_inode)
ii->i_flags = 0;
memset(&ii->i_bmap_data, 0, sizeof(struct nilfs_bmap));
mapping_set_gfp_mask(btnc_inode->i_mapping, GFP_NOFS);
+ btnc_inode->i_mapping->a_ops = &nilfs_buffer_cache_aops;
}
void nilfs_btnode_cache_clear(struct address_space *btnc)
diff --git a/fs/nilfs2/dir.c b/fs/nilfs2/dir.c
index 14e8d82f8629..0a3aea6c416b 100644
--- a/fs/nilfs2/dir.c
+++ b/fs/nilfs2/dir.c
@@ -70,7 +70,7 @@ static inline unsigned int nilfs_chunk_size(struct inode *inode)
*/
static unsigned int nilfs_last_byte(struct inode *inode, unsigned long page_nr)
{
- unsigned int last_byte = inode->i_size;
+ u64 last_byte = inode->i_size;
last_byte -= page_nr << PAGE_SHIFT;
if (last_byte > PAGE_SIZE)
diff --git a/fs/nilfs2/gcinode.c b/fs/nilfs2/gcinode.c
index ace22253fed0..2dbb15767df1 100644
--- a/fs/nilfs2/gcinode.c
+++ b/fs/nilfs2/gcinode.c
@@ -163,7 +163,7 @@ int nilfs_init_gcinode(struct inode *inode)
inode->i_mode = S_IFREG;
mapping_set_gfp_mask(inode->i_mapping, GFP_NOFS);
- inode->i_mapping->a_ops = &empty_aops;
+ inode->i_mapping->a_ops = &nilfs_buffer_cache_aops;
ii->i_flags = 0;
nilfs_bmap_init_gc(ii->i_bmap);
diff --git a/fs/nilfs2/inode.c b/fs/nilfs2/inode.c
index cf9ba481ae37..23f3a75edd50 100644
--- a/fs/nilfs2/inode.c
+++ b/fs/nilfs2/inode.c
@@ -276,6 +276,10 @@ const struct address_space_operations nilfs_aops = {
.is_partially_uptodate = block_is_partially_uptodate,
};
+const struct address_space_operations nilfs_buffer_cache_aops = {
+ .invalidate_folio = block_invalidate_folio,
+};
+
static int nilfs_insert_inode_locked(struct inode *inode,
struct nilfs_root *root,
unsigned long ino)
@@ -544,8 +548,14 @@ struct inode *nilfs_iget(struct super_block *sb, struct nilfs_root *root,
inode = nilfs_iget_locked(sb, root, ino);
if (unlikely(!inode))
return ERR_PTR(-ENOMEM);
- if (!(inode->i_state & I_NEW))
+
+ if (!(inode->i_state & I_NEW)) {
+ if (!inode->i_nlink) {
+ iput(inode);
+ return ERR_PTR(-ESTALE);
+ }
return inode;
+ }
err = __nilfs_read_inode(sb, root, ino, inode);
if (unlikely(err)) {
@@ -675,6 +685,7 @@ struct inode *nilfs_iget_for_shadow(struct inode *inode)
NILFS_I(s_inode)->i_flags = 0;
memset(NILFS_I(s_inode)->i_bmap, 0, sizeof(struct nilfs_bmap));
mapping_set_gfp_mask(s_inode->i_mapping, GFP_NOFS);
+ s_inode->i_mapping->a_ops = &nilfs_buffer_cache_aops;
err = nilfs_attach_btree_node_cache(s_inode);
if (unlikely(err)) {
diff --git a/fs/nilfs2/namei.c b/fs/nilfs2/namei.c
index 9b108052d9f7..1d836a5540f3 100644
--- a/fs/nilfs2/namei.c
+++ b/fs/nilfs2/namei.c
@@ -67,6 +67,11 @@ nilfs_lookup(struct inode *dir, struct dentry *dentry, unsigned int flags)
inode = NULL;
} else {
inode = nilfs_iget(dir->i_sb, NILFS_I(dir)->i_root, ino);
+ if (inode == ERR_PTR(-ESTALE)) {
+ nilfs_error(dir->i_sb,
+ "deleted inode referenced: %lu", ino);
+ return ERR_PTR(-EIO);
+ }
}
return d_splice_alias(inode, dentry);
diff --git a/fs/nilfs2/nilfs.h b/fs/nilfs2/nilfs.h
index 45d03826eaf1..dff241c53fc5 100644
--- a/fs/nilfs2/nilfs.h
+++ b/fs/nilfs2/nilfs.h
@@ -401,6 +401,7 @@ extern const struct file_operations nilfs_dir_operations;
extern const struct inode_operations nilfs_file_inode_operations;
extern const struct file_operations nilfs_file_operations;
extern const struct address_space_operations nilfs_aops;
+extern const struct address_space_operations nilfs_buffer_cache_aops;
extern const struct inode_operations nilfs_dir_inode_operations;
extern const struct inode_operations nilfs_special_inode_operations;
extern const struct inode_operations nilfs_symlink_inode_operations;
diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c
index dec553034027..e933f9c65d90 100644
--- a/fs/notify/fdinfo.c
+++ b/fs/notify/fdinfo.c
@@ -47,10 +47,8 @@ static void show_mark_fhandle(struct seq_file *m, struct inode *inode)
size = f->handle_bytes >> 2;
ret = exportfs_encode_fid(inode, (struct fid *)f->f_handle, &size);
- if ((ret == FILEID_INVALID) || (ret < 0)) {
- WARN_ONCE(1, "Can't encode file handler for inotify: %d\n", ret);
+ if ((ret == FILEID_INVALID) || (ret < 0))
return;
- }
f->handle_type = ret;
f->handle_bytes = size * sizeof(u32);
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 60df52e4c1f8..764ecbd5ad41 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -3110,6 +3110,7 @@ static void *ocfs2_dlm_seq_next(struct seq_file *m, void *v, loff_t *pos)
struct ocfs2_lock_res *iter = v;
struct ocfs2_lock_res *dummy = &priv->p_iter_res;
+ (*pos)++;
spin_lock(&ocfs2_dlm_tracking_lock);
iter = ocfs2_dlm_next_res(iter, priv);
list_del_init(&dummy->l_debug_list);
diff --git a/fs/ocfs2/localalloc.c b/fs/ocfs2/localalloc.c
index 8ac42ea81a17..d1aa04a5af1b 100644
--- a/fs/ocfs2/localalloc.c
+++ b/fs/ocfs2/localalloc.c
@@ -971,9 +971,9 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
start = count = 0;
left = le32_to_cpu(alloc->id1.bitmap1.i_total);
- while ((bit_off = ocfs2_find_next_zero_bit(bitmap, left, start)) <
- left) {
- if (bit_off == start) {
+ while (1) {
+ bit_off = ocfs2_find_next_zero_bit(bitmap, left, start);
+ if ((bit_off < left) && (bit_off == start)) {
count++;
start++;
continue;
@@ -998,29 +998,12 @@ static int ocfs2_sync_local_to_main(struct ocfs2_super *osb,
}
}
+ if (bit_off >= left)
+ break;
count = 1;
start = bit_off + 1;
}
- /* clear the contiguous bits until the end boundary */
- if (count) {
- blkno = la_start_blk +
- ocfs2_clusters_to_blocks(osb->sb,
- start - count);
-
- trace_ocfs2_sync_local_to_main_free(
- count, start - count,
- (unsigned long long)la_start_blk,
- (unsigned long long)blkno);
-
- status = ocfs2_release_clusters(handle,
- main_bm_inode,
- main_bm_bh, blkno,
- count);
- if (status < 0)
- mlog_errno(status);
- }
-
bail:
if (status)
mlog_errno(status);
diff --git a/fs/ocfs2/namei.c b/fs/ocfs2/namei.c
index 59c92353151a..5550f8afa438 100644
--- a/fs/ocfs2/namei.c
+++ b/fs/ocfs2/namei.c
@@ -200,8 +200,10 @@ static struct inode *ocfs2_get_init_inode(struct inode *dir, umode_t mode)
mode = mode_strip_sgid(&nop_mnt_idmap, dir, mode);
inode_init_owner(&nop_mnt_idmap, inode, dir, mode);
status = dquot_initialize(inode);
- if (status)
+ if (status) {
+ iput(inode);
return ERR_PTR(status);
+ }
return inode;
}
diff --git a/fs/ocfs2/quota_global.c b/fs/ocfs2/quota_global.c
index 2b0daced98eb..3404e7a30c33 100644
--- a/fs/ocfs2/quota_global.c
+++ b/fs/ocfs2/quota_global.c
@@ -893,7 +893,7 @@ static int ocfs2_get_next_id(struct super_block *sb, struct kqid *qid)
int status = 0;
trace_ocfs2_get_next_id(from_kqid(&init_user_ns, *qid), type);
- if (!sb_has_quota_loaded(sb, type)) {
+ if (!sb_has_quota_active(sb, type)) {
status = -ESRCH;
goto out;
}
diff --git a/fs/ocfs2/quota_local.c b/fs/ocfs2/quota_local.c
index 73d3367c533b..2956d888c131 100644
--- a/fs/ocfs2/quota_local.c
+++ b/fs/ocfs2/quota_local.c
@@ -867,6 +867,7 @@ out:
brelse(oinfo->dqi_libh);
brelse(oinfo->dqi_lqi_bh);
kfree(oinfo);
+ info->dqi_priv = NULL;
return status;
}
diff --git a/fs/overlayfs/copy_up.c b/fs/overlayfs/copy_up.c
index 3601ddfeddc2..0c28e5fa3407 100644
--- a/fs/overlayfs/copy_up.c
+++ b/fs/overlayfs/copy_up.c
@@ -415,13 +415,13 @@ int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upperdentry,
return err;
}
-struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
+struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode,
bool is_upper)
{
struct ovl_fh *fh;
int fh_type, dwords;
int buflen = MAX_HANDLE_SZ;
- uuid_t *uuid = &real->d_sb->s_uuid;
+ uuid_t *uuid = &realinode->i_sb->s_uuid;
int err;
/* Make sure the real fid stays 32bit aligned */
@@ -438,13 +438,13 @@ struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
* the price or reconnecting the dentry.
*/
dwords = buflen >> 2;
- fh_type = exportfs_encode_fh(real, (void *)fh->fb.fid, &dwords, 0);
+ fh_type = exportfs_encode_inode_fh(realinode, (void *)fh->fb.fid,
+ &dwords, NULL, 0);
buflen = (dwords << 2);
err = -EIO;
- if (WARN_ON(fh_type < 0) ||
- WARN_ON(buflen > MAX_HANDLE_SZ) ||
- WARN_ON(fh_type == FILEID_INVALID))
+ if (fh_type < 0 || fh_type == FILEID_INVALID ||
+ WARN_ON(buflen > MAX_HANDLE_SZ))
goto out_err;
fh->fb.version = OVL_FH_VERSION;
@@ -480,7 +480,7 @@ struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin)
if (!ovl_can_decode_fh(origin->d_sb))
return NULL;
- return ovl_encode_real_fh(ofs, origin, false);
+ return ovl_encode_real_fh(ofs, d_inode(origin), false);
}
int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh,
@@ -505,7 +505,7 @@ static int ovl_set_upper_fh(struct ovl_fs *ofs, struct dentry *upper,
const struct ovl_fh *fh;
int err;
- fh = ovl_encode_real_fh(ofs, upper, true);
+ fh = ovl_encode_real_fh(ofs, d_inode(upper), true);
if (IS_ERR(fh))
return PTR_ERR(fh);
diff --git a/fs/overlayfs/export.c b/fs/overlayfs/export.c
index 5868cb222955..444aeeccb6da 100644
--- a/fs/overlayfs/export.c
+++ b/fs/overlayfs/export.c
@@ -176,35 +176,37 @@ static int ovl_connect_layer(struct dentry *dentry)
*
* Return 0 for upper file handle, > 0 for lower file handle or < 0 on error.
*/
-static int ovl_check_encode_origin(struct dentry *dentry)
+static int ovl_check_encode_origin(struct inode *inode)
{
- struct ovl_fs *ofs = OVL_FS(dentry->d_sb);
+ struct ovl_fs *ofs = OVL_FS(inode->i_sb);
bool decodable = ofs->config.nfs_export;
+ struct dentry *dentry;
+ int err;
/* No upper layer? */
if (!ovl_upper_mnt(ofs))
return 1;
/* Lower file handle for non-upper non-decodable */
- if (!ovl_dentry_upper(dentry) && !decodable)
+ if (!ovl_inode_upper(inode) && !decodable)
return 1;
/* Upper file handle for pure upper */
- if (!ovl_dentry_lower(dentry))
+ if (!ovl_inode_lower(inode))
return 0;
/*
* Root is never indexed, so if there's an upper layer, encode upper for
* root.
*/
- if (dentry == dentry->d_sb->s_root)
+ if (inode == d_inode(inode->i_sb->s_root))
return 0;
/*
* Upper decodable file handle for non-indexed upper.
*/
- if (ovl_dentry_upper(dentry) && decodable &&
- !ovl_test_flag(OVL_INDEX, d_inode(dentry)))
+ if (ovl_inode_upper(inode) && decodable &&
+ !ovl_test_flag(OVL_INDEX, inode))
return 0;
/*
@@ -213,14 +215,23 @@ static int ovl_check_encode_origin(struct dentry *dentry)
* ovl_connect_layer() will try to make origin's layer "connected" by
* copying up a "connectable" ancestor.
*/
- if (d_is_dir(dentry) && decodable)
- return ovl_connect_layer(dentry);
+ if (!decodable || !S_ISDIR(inode->i_mode))
+ return 1;
+
+ dentry = d_find_any_alias(inode);
+ if (!dentry)
+ return -ENOENT;
+
+ err = ovl_connect_layer(dentry);
+ dput(dentry);
+ if (err < 0)
+ return err;
/* Lower file handle for indexed and non-upper dir/non-dir */
return 1;
}
-static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry,
+static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct inode *inode,
u32 *fid, int buflen)
{
struct ovl_fh *fh = NULL;
@@ -231,13 +242,13 @@ static int ovl_dentry_to_fid(struct ovl_fs *ofs, struct dentry *dentry,
* Check if we should encode a lower or upper file handle and maybe
* copy up an ancestor to make lower file handle connectable.
*/
- err = enc_lower = ovl_check_encode_origin(dentry);
+ err = enc_lower = ovl_check_encode_origin(inode);
if (enc_lower < 0)
goto fail;
/* Encode an upper or lower file handle */
- fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_dentry_lower(dentry) :
- ovl_dentry_upper(dentry), !enc_lower);
+ fh = ovl_encode_real_fh(ofs, enc_lower ? ovl_inode_lower(inode) :
+ ovl_inode_upper(inode), !enc_lower);
if (IS_ERR(fh))
return PTR_ERR(fh);
@@ -251,8 +262,8 @@ out:
return err;
fail:
- pr_warn_ratelimited("failed to encode file handle (%pd2, err=%i)\n",
- dentry, err);
+ pr_warn_ratelimited("failed to encode file handle (ino=%lu, err=%i)\n",
+ inode->i_ino, err);
goto out;
}
@@ -260,19 +271,13 @@ static int ovl_encode_fh(struct inode *inode, u32 *fid, int *max_len,
struct inode *parent)
{
struct ovl_fs *ofs = OVL_FS(inode->i_sb);
- struct dentry *dentry;
int bytes, buflen = *max_len << 2;
/* TODO: encode connectable file handles */
if (parent)
return FILEID_INVALID;
- dentry = d_find_any_alias(inode);
- if (!dentry)
- return FILEID_INVALID;
-
- bytes = ovl_dentry_to_fid(ofs, dentry, fid, buflen);
- dput(dentry);
+ bytes = ovl_dentry_to_fid(ofs, inode, fid, buflen);
if (bytes <= 0)
return FILEID_INVALID;
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c
index 7e27b7d4adee..cea820cb3b55 100644
--- a/fs/overlayfs/namei.c
+++ b/fs/overlayfs/namei.c
@@ -542,7 +542,7 @@ int ovl_verify_origin_xattr(struct ovl_fs *ofs, struct dentry *dentry,
struct ovl_fh *fh;
int err;
- fh = ovl_encode_real_fh(ofs, real, is_upper);
+ fh = ovl_encode_real_fh(ofs, d_inode(real), is_upper);
err = PTR_ERR(fh);
if (IS_ERR(fh)) {
fh = NULL;
@@ -738,7 +738,7 @@ int ovl_get_index_name(struct ovl_fs *ofs, struct dentry *origin,
struct ovl_fh *fh;
int err;
- fh = ovl_encode_real_fh(ofs, origin, false);
+ fh = ovl_encode_real_fh(ofs, d_inode(origin), false);
if (IS_ERR(fh))
return PTR_ERR(fh);
diff --git a/fs/overlayfs/overlayfs.h b/fs/overlayfs/overlayfs.h
index b361f35762be..0021e2025020 100644
--- a/fs/overlayfs/overlayfs.h
+++ b/fs/overlayfs/overlayfs.h
@@ -865,7 +865,7 @@ int ovl_copy_up_with_data(struct dentry *dentry);
int ovl_maybe_copy_up(struct dentry *dentry, int flags);
int ovl_copy_xattr(struct super_block *sb, const struct path *path, struct dentry *new);
int ovl_set_attr(struct ovl_fs *ofs, struct dentry *upper, struct kstat *stat);
-struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct dentry *real,
+struct ovl_fh *ovl_encode_real_fh(struct ovl_fs *ofs, struct inode *realinode,
bool is_upper);
struct ovl_fh *ovl_get_origin_fh(struct ovl_fs *ofs, struct dentry *origin);
int ovl_set_origin_fh(struct ovl_fs *ofs, const struct ovl_fh *fh,
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index 38a5a3e9cba2..f02cd362309a 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -1810,7 +1810,7 @@ static int pagemap_pmd_range(pmd_t *pmdp, unsigned long addr, unsigned long end,
}
for (; addr != end; addr += PAGE_SIZE, idx++) {
- unsigned long cur_flags = flags;
+ u64 cur_flags = flags;
pagemap_entry_t pme;
if (folio && (flags & PM_PRESENT) &&
diff --git a/fs/proc/vmcore.c b/fs/proc/vmcore.c
index b4521b096058..3d8a82cee63e 100644
--- a/fs/proc/vmcore.c
+++ b/fs/proc/vmcore.c
@@ -414,6 +414,34 @@ static ssize_t read_vmcore(struct kiocb *iocb, struct iov_iter *iter)
return __read_vmcore(iter, &iocb->ki_pos);
}
+/**
+ * vmcore_alloc_buf - allocate buffer in vmalloc memory
+ * @size: size of buffer
+ *
+ * If CONFIG_MMU is defined, use vmalloc_user() to allow users to mmap
+ * the buffer to user-space by means of remap_vmalloc_range().
+ *
+ * If CONFIG_MMU is not defined, use vzalloc() since mmap_vmcore() is
+ * disabled and there's no need to allow users to mmap the buffer.
+ */
+static inline char *vmcore_alloc_buf(size_t size)
+{
+#ifdef CONFIG_MMU
+ return vmalloc_user(size);
+#else
+ return vzalloc(size);
+#endif
+}
+
+/*
+ * Disable mmap_vmcore() if CONFIG_MMU is not defined. MMU is
+ * essential for mmap_vmcore() in order to map physically
+ * non-contiguous objects (ELF header, ELF note segment and memory
+ * regions in the 1st kernel pointed to by PT_LOAD entries) into
+ * virtually contiguous user-space in ELF layout.
+ */
+#ifdef CONFIG_MMU
+
/*
* The vmcore fault handler uses the page cache and fills data using the
* standard __read_vmcore() function.
@@ -457,34 +485,6 @@ static vm_fault_t mmap_vmcore_fault(struct vm_fault *vmf)
#endif
}
-/**
- * vmcore_alloc_buf - allocate buffer in vmalloc memory
- * @size: size of buffer
- *
- * If CONFIG_MMU is defined, use vmalloc_user() to allow users to mmap
- * the buffer to user-space by means of remap_vmalloc_range().
- *
- * If CONFIG_MMU is not defined, use vzalloc() since mmap_vmcore() is
- * disabled and there's no need to allow users to mmap the buffer.
- */
-static inline char *vmcore_alloc_buf(size_t size)
-{
-#ifdef CONFIG_MMU
- return vmalloc_user(size);
-#else
- return vzalloc(size);
-#endif
-}
-
-/*
- * Disable mmap_vmcore() if CONFIG_MMU is not defined. MMU is
- * essential for mmap_vmcore() in order to map physically
- * non-contiguous objects (ELF header, ELF note segment and memory
- * regions in the 1st kernel pointed to by PT_LOAD entries) into
- * virtually contiguous user-space in ELF layout.
- */
-#ifdef CONFIG_MMU
-
static const struct vm_operations_struct vmcore_mmap_ops = {
.fault = mmap_vmcore_fault,
};
diff --git a/fs/pstore/ram.c b/fs/pstore/ram.c
index 4311fcbc84f2..bc68b4de5287 100644
--- a/fs/pstore/ram.c
+++ b/fs/pstore/ram.c
@@ -901,7 +901,7 @@ MODULE_DEVICE_TABLE(of, dt_match);
static struct platform_driver ramoops_driver = {
.probe = ramoops_probe,
- .remove_new = ramoops_remove,
+ .remove = ramoops_remove,
.driver = {
.name = "ramoops",
.of_match_table = dt_match,
diff --git a/fs/qnx6/inode.c b/fs/qnx6/inode.c
index 85925ec0051a..3310d1ad4d0e 100644
--- a/fs/qnx6/inode.c
+++ b/fs/qnx6/inode.c
@@ -179,8 +179,7 @@ static int qnx6_statfs(struct dentry *dentry, struct kstatfs *buf)
*/
static const char *qnx6_checkroot(struct super_block *s)
{
- static char match_root[2][3] = {".\0\0", "..\0"};
- int i, error = 0;
+ int error = 0;
struct qnx6_dir_entry *dir_entry;
struct inode *root = d_inode(s->s_root);
struct address_space *mapping = root->i_mapping;
@@ -189,11 +188,9 @@ static const char *qnx6_checkroot(struct super_block *s)
if (IS_ERR(folio))
return "error reading root directory";
dir_entry = kmap_local_folio(folio, 0);
- for (i = 0; i < 2; i++) {
- /* maximum 3 bytes - due to match_root limitation */
- if (strncmp(dir_entry[i].de_fname, match_root[i], 3))
- error = 1;
- }
+ if (memcmp(dir_entry[0].de_fname, ".", 2) ||
+ memcmp(dir_entry[1].de_fname, "..", 3))
+ error = 1;
folio_release_kmap(folio, dir_entry);
if (error)
return "error reading root directory.";
diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c
index 3dd8d6f27725..f9578918cfb2 100644
--- a/fs/quota/dquot.c
+++ b/fs/quota/dquot.c
@@ -688,6 +688,8 @@ int dquot_writeback_dquots(struct super_block *sb, int type)
WARN_ON_ONCE(!rwsem_is_locked(&sb->s_umount));
+ flush_delayed_work(&quota_release_work);
+
for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
if (type != -1 && cnt != type)
continue;
diff --git a/fs/smb/client/Kconfig b/fs/smb/client/Kconfig
index 2aff6d1395ce..9f05f94e265a 100644
--- a/fs/smb/client/Kconfig
+++ b/fs/smb/client/Kconfig
@@ -2,7 +2,6 @@
config CIFS
tristate "SMB3 and CIFS support (advanced network filesystem)"
depends on INET
- select NETFS_SUPPORT
select NLS
select NLS_UCS2_UTILS
select CRYPTO
diff --git a/fs/smb/client/cached_dir.c b/fs/smb/client/cached_dir.c
index 06eb19dabb0e..fe738623cf1b 100644
--- a/fs/smb/client/cached_dir.c
+++ b/fs/smb/client/cached_dir.c
@@ -17,6 +17,11 @@ static void free_cached_dir(struct cached_fid *cfid);
static void smb2_close_cached_fid(struct kref *ref);
static void cfids_laundromat_worker(struct work_struct *work);
+struct cached_dir_dentry {
+ struct list_head entry;
+ struct dentry *dentry;
+};
+
static struct cached_fid *find_or_create_cached_dir(struct cached_fids *cfids,
const char *path,
bool lookup_only,
@@ -157,15 +162,17 @@ int open_cached_dir(unsigned int xid, struct cifs_tcon *tcon,
const char *npath;
int retries = 0, cur_sleep = 1;
- if (tcon == NULL || tcon->cfids == NULL || tcon->nohandlecache ||
- is_smb1_server(tcon->ses->server) || (dir_cache_timeout == 0))
+ if (cifs_sb->root == NULL)
+ return -ENOENT;
+
+ if (tcon == NULL)
return -EOPNOTSUPP;
ses = tcon->ses;
cfids = tcon->cfids;
- if (cifs_sb->root == NULL)
- return -ENOENT;
+ if (cfids == NULL)
+ return -EOPNOTSUPP;
replay_again:
/* reinitialize for possible replay */
@@ -222,6 +229,7 @@ replay_again:
}
}
cfid->dentry = dentry;
+ cfid->tcon = tcon;
/*
* We do not hold the lock for the open because in case
@@ -293,7 +301,6 @@ replay_again:
}
goto oshr_free;
}
- cfid->tcon = tcon;
cfid->is_open = true;
spin_lock(&cfids->cfid_list_lock);
@@ -389,7 +396,7 @@ int open_cached_dir_by_dentry(struct cifs_tcon *tcon,
struct cached_fids *cfids = tcon->cfids;
if (cfids == NULL)
- return -ENOENT;
+ return -EOPNOTSUPP;
spin_lock(&cfids->cfid_list_lock);
list_for_each_entry(cfid, &cfids->entries, entry) {
@@ -470,7 +477,10 @@ void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
struct cifs_tcon *tcon;
struct tcon_link *tlink;
struct cached_fids *cfids;
+ struct cached_dir_dentry *tmp_list, *q;
+ LIST_HEAD(entry);
+ spin_lock(&cifs_sb->tlink_tree_lock);
for (node = rb_first(root); node; node = rb_next(node)) {
tlink = rb_entry(node, struct tcon_link, tl_rbnode);
tcon = tlink_tcon(tlink);
@@ -479,11 +489,30 @@ void close_all_cached_dirs(struct cifs_sb_info *cifs_sb)
cfids = tcon->cfids;
if (cfids == NULL)
continue;
+ spin_lock(&cfids->cfid_list_lock);
list_for_each_entry(cfid, &cfids->entries, entry) {
- dput(cfid->dentry);
+ tmp_list = kmalloc(sizeof(*tmp_list), GFP_ATOMIC);
+ if (tmp_list == NULL)
+ break;
+ spin_lock(&cfid->fid_lock);
+ tmp_list->dentry = cfid->dentry;
cfid->dentry = NULL;
+ spin_unlock(&cfid->fid_lock);
+
+ list_add_tail(&tmp_list->entry, &entry);
}
+ spin_unlock(&cfids->cfid_list_lock);
}
+ spin_unlock(&cifs_sb->tlink_tree_lock);
+
+ list_for_each_entry_safe(tmp_list, q, &entry, entry) {
+ list_del(&tmp_list->entry);
+ dput(tmp_list->dentry);
+ kfree(tmp_list);
+ }
+
+ /* Flush any pending work that will drop dentries */
+ flush_workqueue(cfid_put_wq);
}
/*
@@ -494,14 +523,18 @@ void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
{
struct cached_fids *cfids = tcon->cfids;
struct cached_fid *cfid, *q;
- LIST_HEAD(entry);
if (cfids == NULL)
return;
+ /*
+ * Mark all the cfids as closed, and move them to the cfids->dying list.
+ * They'll be cleaned up later by cfids_invalidation_worker. Take
+ * a reference to each cfid during this process.
+ */
spin_lock(&cfids->cfid_list_lock);
list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
- list_move(&cfid->entry, &entry);
+ list_move(&cfid->entry, &cfids->dying);
cfids->num_entries--;
cfid->is_open = false;
cfid->on_list = false;
@@ -514,26 +547,47 @@ void invalidate_all_cached_dirs(struct cifs_tcon *tcon)
} else
kref_get(&cfid->refcount);
}
+ /*
+ * Queue dropping of the dentries once locks have been dropped
+ */
+ if (!list_empty(&cfids->dying))
+ queue_work(cfid_put_wq, &cfids->invalidation_work);
spin_unlock(&cfids->cfid_list_lock);
-
- list_for_each_entry_safe(cfid, q, &entry, entry) {
- list_del(&cfid->entry);
- cancel_work_sync(&cfid->lease_break);
- /*
- * Drop the ref-count from above, either the lease-ref (if there
- * was one) or the extra one acquired.
- */
- kref_put(&cfid->refcount, smb2_close_cached_fid);
- }
}
static void
-smb2_cached_lease_break(struct work_struct *work)
+cached_dir_offload_close(struct work_struct *work)
{
struct cached_fid *cfid = container_of(work,
- struct cached_fid, lease_break);
+ struct cached_fid, close_work);
+ struct cifs_tcon *tcon = cfid->tcon;
+
+ WARN_ON(cfid->on_list);
kref_put(&cfid->refcount, smb2_close_cached_fid);
+ cifs_put_tcon(tcon, netfs_trace_tcon_ref_put_cached_close);
+}
+
+/*
+ * Release the cached directory's dentry, and then queue work to drop cached
+ * directory itself (closing on server if needed).
+ *
+ * Must be called with a reference to the cached_fid and a reference to the
+ * tcon.
+ */
+static void cached_dir_put_work(struct work_struct *work)
+{
+ struct cached_fid *cfid = container_of(work, struct cached_fid,
+ put_work);
+ struct dentry *dentry;
+
+ spin_lock(&cfid->fid_lock);
+ dentry = cfid->dentry;
+ cfid->dentry = NULL;
+ spin_unlock(&cfid->fid_lock);
+
+ dput(dentry);
+ queue_work(serverclose_wq, &cfid->close_work);
}
int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16])
@@ -560,8 +614,10 @@ int cached_dir_lease_break(struct cifs_tcon *tcon, __u8 lease_key[16])
cfid->on_list = false;
cfids->num_entries--;
- queue_work(cifsiod_wq,
- &cfid->lease_break);
+ ++tcon->tc_count;
+ trace_smb3_tcon_ref(tcon->debug_id, tcon->tc_count,
+ netfs_trace_tcon_ref_get_cached_lease_break);
+ queue_work(cfid_put_wq, &cfid->put_work);
spin_unlock(&cfids->cfid_list_lock);
return true;
}
@@ -583,7 +639,8 @@ static struct cached_fid *init_cached_dir(const char *path)
return NULL;
}
- INIT_WORK(&cfid->lease_break, smb2_cached_lease_break);
+ INIT_WORK(&cfid->close_work, cached_dir_offload_close);
+ INIT_WORK(&cfid->put_work, cached_dir_put_work);
INIT_LIST_HEAD(&cfid->entry);
INIT_LIST_HEAD(&cfid->dirents.entries);
mutex_init(&cfid->dirents.de_mutex);
@@ -596,6 +653,9 @@ static void free_cached_dir(struct cached_fid *cfid)
{
struct cached_dirent *dirent, *q;
+ WARN_ON(work_pending(&cfid->close_work));
+ WARN_ON(work_pending(&cfid->put_work));
+
dput(cfid->dentry);
cfid->dentry = NULL;
@@ -613,10 +673,30 @@ static void free_cached_dir(struct cached_fid *cfid)
kfree(cfid);
}
+static void cfids_invalidation_worker(struct work_struct *work)
+{
+ struct cached_fids *cfids = container_of(work, struct cached_fids,
+ invalidation_work);
+ struct cached_fid *cfid, *q;
+ LIST_HEAD(entry);
+
+ spin_lock(&cfids->cfid_list_lock);
+ /* move cfids->dying to the local list */
+ list_cut_before(&entry, &cfids->dying, &cfids->dying);
+ spin_unlock(&cfids->cfid_list_lock);
+
+ list_for_each_entry_safe(cfid, q, &entry, entry) {
+ list_del(&cfid->entry);
+ /* Drop the ref-count acquired in invalidate_all_cached_dirs */
+ kref_put(&cfid->refcount, smb2_close_cached_fid);
+ }
+}
+
static void cfids_laundromat_worker(struct work_struct *work)
{
struct cached_fids *cfids;
struct cached_fid *cfid, *q;
+ struct dentry *dentry;
LIST_HEAD(entry);
cfids = container_of(work, struct cached_fids, laundromat_work.work);
@@ -642,18 +722,28 @@ static void cfids_laundromat_worker(struct work_struct *work)
list_for_each_entry_safe(cfid, q, &entry, entry) {
list_del(&cfid->entry);
- /*
- * Cancel and wait for the work to finish in case we are racing
- * with it.
- */
- cancel_work_sync(&cfid->lease_break);
- /*
- * Drop the ref-count from above, either the lease-ref (if there
- * was one) or the extra one acquired.
- */
- kref_put(&cfid->refcount, smb2_close_cached_fid);
+
+ spin_lock(&cfid->fid_lock);
+ dentry = cfid->dentry;
+ cfid->dentry = NULL;
+ spin_unlock(&cfid->fid_lock);
+
+ dput(dentry);
+ if (cfid->is_open) {
+ spin_lock(&cifs_tcp_ses_lock);
+ ++cfid->tcon->tc_count;
+ trace_smb3_tcon_ref(cfid->tcon->debug_id, cfid->tcon->tc_count,
+ netfs_trace_tcon_ref_get_cached_laundromat);
+ spin_unlock(&cifs_tcp_ses_lock);
+ queue_work(serverclose_wq, &cfid->close_work);
+ } else
+ /*
+ * Drop the ref-count from above, either the lease-ref (if there
+ * was one) or the extra one acquired.
+ */
+ kref_put(&cfid->refcount, smb2_close_cached_fid);
}
- queue_delayed_work(cifsiod_wq, &cfids->laundromat_work,
+ queue_delayed_work(cfid_put_wq, &cfids->laundromat_work,
dir_cache_timeout * HZ);
}
@@ -666,9 +756,11 @@ struct cached_fids *init_cached_dirs(void)
return NULL;
spin_lock_init(&cfids->cfid_list_lock);
INIT_LIST_HEAD(&cfids->entries);
+ INIT_LIST_HEAD(&cfids->dying);
+ INIT_WORK(&cfids->invalidation_work, cfids_invalidation_worker);
INIT_DELAYED_WORK(&cfids->laundromat_work, cfids_laundromat_worker);
- queue_delayed_work(cifsiod_wq, &cfids->laundromat_work,
+ queue_delayed_work(cfid_put_wq, &cfids->laundromat_work,
dir_cache_timeout * HZ);
return cfids;
@@ -687,6 +779,7 @@ void free_cached_dirs(struct cached_fids *cfids)
return;
cancel_delayed_work_sync(&cfids->laundromat_work);
+ cancel_work_sync(&cfids->invalidation_work);
spin_lock(&cfids->cfid_list_lock);
list_for_each_entry_safe(cfid, q, &cfids->entries, entry) {
@@ -694,6 +787,11 @@ void free_cached_dirs(struct cached_fids *cfids)
cfid->is_open = false;
list_move(&cfid->entry, &entry);
}
+ list_for_each_entry_safe(cfid, q, &cfids->dying, entry) {
+ cfid->on_list = false;
+ cfid->is_open = false;
+ list_move(&cfid->entry, &entry);
+ }
spin_unlock(&cfids->cfid_list_lock);
list_for_each_entry_safe(cfid, q, &entry, entry) {
diff --git a/fs/smb/client/cached_dir.h b/fs/smb/client/cached_dir.h
index 81ba0fd5cc16..1dfe79d947a6 100644
--- a/fs/smb/client/cached_dir.h
+++ b/fs/smb/client/cached_dir.h
@@ -44,7 +44,8 @@ struct cached_fid {
spinlock_t fid_lock;
struct cifs_tcon *tcon;
struct dentry *dentry;
- struct work_struct lease_break;
+ struct work_struct put_work;
+ struct work_struct close_work;
struct smb2_file_all_info file_all_info;
struct cached_dirents dirents;
};
@@ -53,10 +54,13 @@ struct cached_fid {
struct cached_fids {
/* Must be held when:
* - accessing the cfids->entries list
+ * - accessing the cfids->dying list
*/
spinlock_t cfid_list_lock;
int num_entries;
struct list_head entries;
+ struct list_head dying;
+ struct work_struct invalidation_work;
struct delayed_work laundromat_work;
};
diff --git a/fs/smb/client/cifsfs.c b/fs/smb/client/cifsfs.c
index 979853471027..b800c9f585d8 100644
--- a/fs/smb/client/cifsfs.c
+++ b/fs/smb/client/cifsfs.c
@@ -157,6 +157,7 @@ struct workqueue_struct *fileinfo_put_wq;
struct workqueue_struct *cifsoplockd_wq;
struct workqueue_struct *deferredclose_wq;
struct workqueue_struct *serverclose_wq;
+struct workqueue_struct *cfid_put_wq;
__u32 cifs_lock_secret;
/*
@@ -397,7 +398,7 @@ cifs_alloc_inode(struct super_block *sb)
cifs_inode = alloc_inode_sb(sb, cifs_inode_cachep, GFP_KERNEL);
if (!cifs_inode)
return NULL;
- cifs_inode->cifsAttrs = 0x20; /* default */
+ cifs_inode->cifsAttrs = ATTR_ARCHIVE; /* default */
cifs_inode->time = 0;
/*
* Until the file is open and we have gotten oplock info back from the
@@ -1920,9 +1921,16 @@ init_cifs(void)
goto out_destroy_deferredclose_wq;
}
+ cfid_put_wq = alloc_workqueue("cfid_put_wq",
+ WQ_FREEZABLE|WQ_MEM_RECLAIM, 0);
+ if (!cfid_put_wq) {
+ rc = -ENOMEM;
+ goto out_destroy_serverclose_wq;
+ }
+
rc = cifs_init_inodecache();
if (rc)
- goto out_destroy_serverclose_wq;
+ goto out_destroy_cfid_put_wq;
rc = cifs_init_netfs();
if (rc)
@@ -1990,6 +1998,8 @@ out_destroy_netfs:
cifs_destroy_netfs();
out_destroy_inodecache:
cifs_destroy_inodecache();
+out_destroy_cfid_put_wq:
+ destroy_workqueue(cfid_put_wq);
out_destroy_serverclose_wq:
destroy_workqueue(serverclose_wq);
out_destroy_deferredclose_wq:
@@ -2033,6 +2043,7 @@ exit_cifs(void)
destroy_workqueue(decrypt_wq);
destroy_workqueue(fileinfo_put_wq);
destroy_workqueue(serverclose_wq);
+ destroy_workqueue(cfid_put_wq);
destroy_workqueue(cifsiod_wq);
cifs_proc_clean();
}
diff --git a/fs/smb/client/cifsfs.h b/fs/smb/client/cifsfs.h
index 71b720dbb2ce..a762dbbbd959 100644
--- a/fs/smb/client/cifsfs.h
+++ b/fs/smb/client/cifsfs.h
@@ -146,6 +146,6 @@ extern const struct export_operations cifs_export_ops;
#endif /* CONFIG_CIFS_NFSD_EXPORT */
/* when changing internal version - update following two lines at same time */
-#define SMB3_PRODUCT_BUILD 51
-#define CIFS_VERSION "2.51"
+#define SMB3_PRODUCT_BUILD 52
+#define CIFS_VERSION "2.52"
#endif /* _CIFSFS_H */
diff --git a/fs/smb/client/cifsglob.h b/fs/smb/client/cifsglob.h
index fc33dfe7e925..6e63abe461fd 100644
--- a/fs/smb/client/cifsglob.h
+++ b/fs/smb/client/cifsglob.h
@@ -594,6 +594,7 @@ struct smb_version_operations {
/* Check for STATUS_NETWORK_NAME_DELETED */
bool (*is_network_name_deleted)(char *buf, struct TCP_Server_Info *srv);
int (*parse_reparse_point)(struct cifs_sb_info *cifs_sb,
+ const char *full_path,
struct kvec *rsp_iov,
struct cifs_open_info_data *data);
int (*create_reparse_symlink)(const unsigned int xid,
@@ -1990,7 +1991,7 @@ require use of the stronger protocol */
* cifsInodeInfo->lock_sem cifsInodeInfo->llist cifs_init_once
* ->can_cache_brlcks
* cifsInodeInfo->deferred_lock cifsInodeInfo->deferred_closes cifsInodeInfo_alloc
- * cached_fid->fid_mutex cifs_tcon->crfid tcon_info_alloc
+ * cached_fids->cfid_list_lock cifs_tcon->cfids->entries init_cached_dirs
* cifsFileInfo->fh_mutex cifsFileInfo cifs_new_fileinfo
* cifsFileInfo->file_info_lock cifsFileInfo->count cifs_new_fileinfo
* ->invalidHandle initiate_cifs_search
@@ -2078,6 +2079,7 @@ extern struct workqueue_struct *fileinfo_put_wq;
extern struct workqueue_struct *cifsoplockd_wq;
extern struct workqueue_struct *deferredclose_wq;
extern struct workqueue_struct *serverclose_wq;
+extern struct workqueue_struct *cfid_put_wq;
extern __u32 cifs_lock_secret;
extern mempool_t *cifs_sm_req_poolp;
diff --git a/fs/smb/client/cifsproto.h b/fs/smb/client/cifsproto.h
index 075985bfb13a..d26f9bbb5382 100644
--- a/fs/smb/client/cifsproto.h
+++ b/fs/smb/client/cifsproto.h
@@ -314,8 +314,7 @@ extern void cifs_move_llist(struct list_head *source, struct list_head *dest);
extern void cifs_free_llist(struct list_head *llist);
extern void cifs_del_lock_waiters(struct cifsLockInfo *lock);
-extern int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon,
- const struct nls_table *nlsc);
+int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon);
extern int cifs_negotiate_protocol(const unsigned int xid,
struct cifs_ses *ses,
@@ -615,8 +614,6 @@ int cifs_alloc_hash(const char *name, struct shash_desc **sdesc);
void cifs_free_hash(struct shash_desc **sdesc);
int cifs_try_adding_channels(struct cifs_ses *ses);
-bool is_server_using_iface(struct TCP_Server_Info *server,
- struct cifs_server_iface *iface);
bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface);
void cifs_ses_mark_for_reconnect(struct cifs_ses *ses);
@@ -661,6 +658,7 @@ char *extract_hostname(const char *unc);
char *extract_sharename(const char *unc);
int parse_reparse_point(struct reparse_data_buffer *buf,
u32 plen, struct cifs_sb_info *cifs_sb,
+ const char *full_path,
bool unicode, struct cifs_open_info_data *data);
int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
@@ -669,6 +667,7 @@ int __cifs_sfu_make_node(unsigned int xid, struct inode *inode,
int cifs_sfu_make_node(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev);
+umode_t wire_mode_to_posix(u32 wire, bool is_dir);
#ifdef CONFIG_CIFS_DFS_UPCALL
static inline int get_dfs_path(const unsigned int xid, struct cifs_ses *ses,
diff --git a/fs/smb/client/cifssmb.c b/fs/smb/client/cifssmb.c
index 4858331ee918..6cb1e81993f8 100644
--- a/fs/smb/client/cifssmb.c
+++ b/fs/smb/client/cifssmb.c
@@ -70,10 +70,9 @@ static struct {
static int
cifs_reconnect_tcon(struct cifs_tcon *tcon, int smb_command)
{
- int rc;
- struct cifs_ses *ses;
struct TCP_Server_Info *server;
- struct nls_table *nls_codepage = NULL;
+ struct cifs_ses *ses;
+ int rc;
/*
* SMBs NegProt, SessSetup, uLogoff do not have tcon yet so check for
@@ -131,8 +130,6 @@ again:
}
spin_unlock(&server->srv_lock);
- nls_codepage = ses->local_nls;
-
/*
* need to prevent multiple threads trying to simultaneously
* reconnect the same SMB session
@@ -156,7 +153,7 @@ again:
rc = cifs_negotiate_protocol(0, ses, server);
if (!rc)
- rc = cifs_setup_session(0, ses, server, nls_codepage);
+ rc = cifs_setup_session(0, ses, server, ses->local_nls);
/* do we need to reconnect tcon? */
if (rc || !tcon->need_reconnect) {
@@ -166,7 +163,7 @@ again:
skip_sess_setup:
cifs_mark_open_files_invalid(tcon);
- rc = cifs_tree_connect(0, tcon, nls_codepage);
+ rc = cifs_tree_connect(0, tcon);
mutex_unlock(&ses->session_mutex);
cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
@@ -1322,14 +1319,16 @@ cifs_readv_callback(struct mid_q_entry *mid)
}
if (rdata->result == -ENODATA) {
- __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
rdata->result = 0;
+ __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
} else {
size_t trans = rdata->subreq.transferred + rdata->got_bytes;
if (trans < rdata->subreq.len &&
rdata->subreq.start + trans == ictx->remote_i_size) {
- __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
rdata->result = 0;
+ __set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
+ } else if (rdata->got_bytes > 0) {
+ __set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags);
}
}
@@ -1673,10 +1672,13 @@ cifs_writev_callback(struct mid_q_entry *mid)
if (written > wdata->subreq.len)
written &= 0xFFFF;
- if (written < wdata->subreq.len)
+ if (written < wdata->subreq.len) {
result = -ENOSPC;
- else
+ } else {
result = written;
+ if (written > 0)
+ __set_bit(NETFS_SREQ_MADE_PROGRESS, &wdata->subreq.flags);
+ }
break;
case MID_REQUEST_SUBMITTED:
case MID_RETRY_NEEDED:
@@ -4320,8 +4322,8 @@ getDFSRetry:
* CIFSGetDFSRefer() may be called from cifs_reconnect_tcon() and thus
* causing an infinite recursion.
*/
- rc = smb_init_no_reconnect(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
- (void **)&pSMB, (void **)&pSMBr);
+ rc = smb_init(SMB_COM_TRANSACTION2, 15, ses->tcon_ipc,
+ (void **)&pSMB, (void **)&pSMBr);
if (rc)
return rc;
diff --git a/fs/smb/client/connect.c b/fs/smb/client/connect.c
index 0a97228c06b1..ddcc9e514a0e 100644
--- a/fs/smb/client/connect.c
+++ b/fs/smb/client/connect.c
@@ -987,9 +987,13 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
msleep(125);
if (cifs_rdma_enabled(server))
smbd_destroy(server);
+
if (server->ssocket) {
sock_release(server->ssocket);
server->ssocket = NULL;
+
+ /* Release netns reference for the socket. */
+ put_net(cifs_net_ns(server));
}
if (!list_empty(&server->pending_mid_q)) {
@@ -1037,6 +1041,7 @@ clean_demultiplex_info(struct TCP_Server_Info *server)
*/
}
+ /* Release netns reference for this server. */
put_net(cifs_net_ns(server));
kfree(server->leaf_fullpath);
kfree(server);
@@ -1713,6 +1718,8 @@ cifs_get_tcp_session(struct smb3_fs_context *ctx,
tcp_ses->ops = ctx->ops;
tcp_ses->vals = ctx->vals;
+
+ /* Grab netns reference for this server. */
cifs_set_net_ns(tcp_ses, get_net(current->nsproxy->net_ns));
tcp_ses->conn_id = atomic_inc_return(&tcpSesNextId);
@@ -1844,6 +1851,7 @@ smbd_connected:
out_err_crypto_release:
cifs_crypto_secmech_release(tcp_ses);
+ /* Release netns reference for this server. */
put_net(cifs_net_ns(tcp_ses));
out_err:
@@ -1852,8 +1860,10 @@ out_err:
cifs_put_tcp_session(tcp_ses->primary_server, false);
kfree(tcp_ses->hostname);
kfree(tcp_ses->leaf_fullpath);
- if (tcp_ses->ssocket)
+ if (tcp_ses->ssocket) {
sock_release(tcp_ses->ssocket);
+ put_net(cifs_net_ns(tcp_ses));
+ }
kfree(tcp_ses);
}
return ERR_PTR(rc);
@@ -1897,11 +1907,35 @@ static int match_session(struct cifs_ses *ses,
CIFS_MAX_USERNAME_LEN))
return 0;
if ((ctx->username && strlen(ctx->username) != 0) &&
- ses->password != NULL &&
- strncmp(ses->password,
- ctx->password ? ctx->password : "",
- CIFS_MAX_PASSWORD_LEN))
- return 0;
+ ses->password != NULL) {
+
+ /* New mount can only share sessions with an existing mount if:
+ * 1. Both password and password2 match, or
+ * 2. password2 of the old mount matches password of the new mount
+ * and password of the old mount matches password2 of the new
+ * mount
+ */
+ if (ses->password2 != NULL && ctx->password2 != NULL) {
+ if (!((strncmp(ses->password, ctx->password ?
+ ctx->password : "", CIFS_MAX_PASSWORD_LEN) == 0 &&
+ strncmp(ses->password2, ctx->password2,
+ CIFS_MAX_PASSWORD_LEN) == 0) ||
+ (strncmp(ses->password, ctx->password2,
+ CIFS_MAX_PASSWORD_LEN) == 0 &&
+ strncmp(ses->password2, ctx->password ?
+ ctx->password : "", CIFS_MAX_PASSWORD_LEN) == 0)))
+ return 0;
+
+ } else if ((ses->password2 == NULL && ctx->password2 != NULL) ||
+ (ses->password2 != NULL && ctx->password2 == NULL)) {
+ return 0;
+
+ } else {
+ if (strncmp(ses->password, ctx->password ?
+ ctx->password : "", CIFS_MAX_PASSWORD_LEN))
+ return 0;
+ }
+ }
}
if (strcmp(ctx->local_nls->charset, ses->local_nls->charset))
@@ -2244,6 +2278,7 @@ struct cifs_ses *
cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
{
int rc = 0;
+ int retries = 0;
unsigned int xid;
struct cifs_ses *ses;
struct sockaddr_in *addr = (struct sockaddr_in *)&server->dstaddr;
@@ -2262,6 +2297,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
cifs_dbg(FYI, "Session needs reconnect\n");
mutex_lock(&ses->session_mutex);
+
+retry_old_session:
rc = cifs_negotiate_protocol(xid, ses, server);
if (rc) {
mutex_unlock(&ses->session_mutex);
@@ -2274,6 +2311,13 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
rc = cifs_setup_session(xid, ses, server,
ctx->local_nls);
if (rc) {
+ if (((rc == -EACCES) || (rc == -EKEYEXPIRED) ||
+ (rc == -EKEYREVOKED)) && !retries && ses->password2) {
+ retries++;
+ cifs_dbg(FYI, "Session reconnect failed, retrying with alternate password\n");
+ swap(ses->password, ses->password2);
+ goto retry_old_session;
+ }
mutex_unlock(&ses->session_mutex);
/* problem -- put our reference */
cifs_put_smb_ses(ses);
@@ -2369,6 +2413,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
ses->chans_need_reconnect = 1;
spin_unlock(&ses->chan_lock);
+retry_new_session:
mutex_lock(&ses->session_mutex);
rc = cifs_negotiate_protocol(xid, ses, server);
if (!rc)
@@ -2381,8 +2426,16 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb3_fs_context *ctx)
sizeof(ses->smb3signingkey));
spin_unlock(&ses->chan_lock);
- if (rc)
- goto get_ses_fail;
+ if (rc) {
+ if (((rc == -EACCES) || (rc == -EKEYEXPIRED) ||
+ (rc == -EKEYREVOKED)) && !retries && ses->password2) {
+ retries++;
+ cifs_dbg(FYI, "Session setup failed, retrying with alternate password\n");
+ swap(ses->password, ses->password2);
+ goto retry_new_session;
+ } else
+ goto get_ses_fail;
+ }
/*
* success, put it on the list and add it as first channel
@@ -2489,9 +2542,6 @@ cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
list_del_init(&tcon->tcon_list);
tcon->status = TID_EXITING;
-#ifdef CONFIG_CIFS_DFS_UPCALL
- list_replace_init(&tcon->dfs_ses_list, &ses_list);
-#endif
spin_unlock(&tcon->tc_lock);
spin_unlock(&cifs_tcp_ses_lock);
@@ -2499,6 +2549,7 @@ cifs_put_tcon(struct cifs_tcon *tcon, enum smb3_tcon_ref_trace trace)
cancel_delayed_work_sync(&tcon->query_interfaces);
#ifdef CONFIG_CIFS_DFS_UPCALL
cancel_delayed_work_sync(&tcon->dfs_cache_work);
+ list_replace_init(&tcon->dfs_ses_list, &ses_list);
#endif
if (tcon->use_witness) {
@@ -2571,7 +2622,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb3_fs_context *ctx)
if (ses->server->dialect >= SMB20_PROT_ID &&
(ses->server->capabilities & SMB2_GLOBAL_CAP_DIRECTORY_LEASING))
- nohandlecache = ctx->nohandlecache;
+ nohandlecache = ctx->nohandlecache || !dir_cache_timeout;
else
nohandlecache = true;
tcon = tcon_info_alloc(!nohandlecache, netfs_trace_tcon_ref_new);
@@ -3090,20 +3141,20 @@ generic_ip_connect(struct TCP_Server_Info *server)
socket = server->ssocket;
} else {
struct net *net = cifs_net_ns(server);
- struct sock *sk;
- rc = __sock_create(net, sfamily, SOCK_STREAM,
- IPPROTO_TCP, &server->ssocket, 1);
+ rc = sock_create_kern(net, sfamily, SOCK_STREAM, IPPROTO_TCP, &server->ssocket);
if (rc < 0) {
cifs_server_dbg(VFS, "Error %d creating socket\n", rc);
return rc;
}
- sk = server->ssocket->sk;
- __netns_tracker_free(net, &sk->ns_tracker, false);
- sk->sk_net_refcnt = 1;
- get_net_track(net, &sk->ns_tracker, GFP_KERNEL);
- sock_inuse_add(net, 1);
+ /*
+ * Grab netns reference for the socket.
+ *
+ * It'll be released here, on error, or in clean_demultiplex_info() upon server
+ * teardown.
+ */
+ get_net(net);
/* BB other socket options to set KEEPALIVE, NODELAY? */
cifs_dbg(FYI, "Socket created\n");
@@ -3117,8 +3168,10 @@ generic_ip_connect(struct TCP_Server_Info *server)
}
rc = bind_socket(server);
- if (rc < 0)
+ if (rc < 0) {
+ put_net(cifs_net_ns(server));
return rc;
+ }
/*
* Eventually check for other socket options to change from
@@ -3155,6 +3208,7 @@ generic_ip_connect(struct TCP_Server_Info *server)
if (rc < 0) {
cifs_dbg(FYI, "Error %d connecting to server\n", rc);
trace_smb3_connect_err(server->hostname, server->conn_id, &server->dstaddr, rc);
+ put_net(cifs_net_ns(server));
sock_release(socket);
server->ssocket = NULL;
return rc;
@@ -3163,6 +3217,9 @@ generic_ip_connect(struct TCP_Server_Info *server)
if (sport == htons(RFC1001_PORT))
rc = ip_rfc1001_connect(server);
+ if (rc < 0)
+ put_net(cifs_net_ns(server));
+
return rc;
}
@@ -4344,10 +4401,10 @@ cifs_prune_tlinks(struct work_struct *work)
}
#ifndef CONFIG_CIFS_DFS_UPCALL
-int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
+int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon)
{
- int rc;
const struct smb_version_operations *ops = tcon->ses->server->ops;
+ int rc;
/* only send once per connect */
spin_lock(&tcon->tc_lock);
@@ -4370,7 +4427,8 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
tcon->status = TID_IN_TCON;
spin_unlock(&tcon->tc_lock);
- rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon, nlsc);
+ rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name,
+ tcon, tcon->ses->local_nls);
if (rc) {
spin_lock(&tcon->tc_lock);
if (tcon->status == TID_IN_TCON)
diff --git a/fs/smb/client/dfs.c b/fs/smb/client/dfs.c
index 3f6077c68d68..4647df9e1e3b 100644
--- a/fs/smb/client/dfs.c
+++ b/fs/smb/client/dfs.c
@@ -321,49 +321,6 @@ int dfs_mount_share(struct cifs_mount_ctx *mnt_ctx)
return rc;
}
-/* Update dfs referral path of superblock */
-static int update_server_fullpath(struct TCP_Server_Info *server, struct cifs_sb_info *cifs_sb,
- const char *target)
-{
- int rc = 0;
- size_t len = strlen(target);
- char *refpath, *npath;
-
- if (unlikely(len < 2 || *target != '\\'))
- return -EINVAL;
-
- if (target[1] == '\\') {
- len += 1;
- refpath = kmalloc(len, GFP_KERNEL);
- if (!refpath)
- return -ENOMEM;
-
- scnprintf(refpath, len, "%s", target);
- } else {
- len += sizeof("\\");
- refpath = kmalloc(len, GFP_KERNEL);
- if (!refpath)
- return -ENOMEM;
-
- scnprintf(refpath, len, "\\%s", target);
- }
-
- npath = dfs_cache_canonical_path(refpath, cifs_sb->local_nls, cifs_remap(cifs_sb));
- kfree(refpath);
-
- if (IS_ERR(npath)) {
- rc = PTR_ERR(npath);
- } else {
- mutex_lock(&server->refpath_lock);
- spin_lock(&server->srv_lock);
- kfree(server->leaf_fullpath);
- server->leaf_fullpath = npath;
- spin_unlock(&server->srv_lock);
- mutex_unlock(&server->refpath_lock);
- }
- return rc;
-}
-
static int target_share_matches_server(struct TCP_Server_Info *server, char *share,
bool *target_match)
{
@@ -388,77 +345,22 @@ static int target_share_matches_server(struct TCP_Server_Info *server, char *sha
return rc;
}
-static void __tree_connect_ipc(const unsigned int xid, char *tree,
- struct cifs_sb_info *cifs_sb,
- struct cifs_ses *ses)
-{
- struct TCP_Server_Info *server = ses->server;
- struct cifs_tcon *tcon = ses->tcon_ipc;
- int rc;
-
- spin_lock(&ses->ses_lock);
- spin_lock(&ses->chan_lock);
- if (cifs_chan_needs_reconnect(ses, server) ||
- ses->ses_status != SES_GOOD) {
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
- cifs_server_dbg(FYI, "%s: skipping ipc reconnect due to disconnected ses\n",
- __func__);
- return;
- }
- spin_unlock(&ses->chan_lock);
- spin_unlock(&ses->ses_lock);
-
- cifs_server_lock(server);
- scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
- cifs_server_unlock(server);
-
- rc = server->ops->tree_connect(xid, ses, tree, tcon,
- cifs_sb->local_nls);
- cifs_server_dbg(FYI, "%s: tree_reconnect %s: %d\n", __func__, tree, rc);
- spin_lock(&tcon->tc_lock);
- if (rc) {
- tcon->status = TID_NEED_TCON;
- } else {
- tcon->status = TID_GOOD;
- tcon->need_reconnect = false;
- }
- spin_unlock(&tcon->tc_lock);
-}
-
-static void tree_connect_ipc(const unsigned int xid, char *tree,
- struct cifs_sb_info *cifs_sb,
- struct cifs_tcon *tcon)
-{
- struct cifs_ses *ses = tcon->ses;
-
- __tree_connect_ipc(xid, tree, cifs_sb, ses);
- __tree_connect_ipc(xid, tree, cifs_sb, CIFS_DFS_ROOT_SES(ses));
-}
-
-static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, char *tree, bool islink,
- struct dfs_cache_tgt_list *tl)
+static int tree_connect_dfs_target(const unsigned int xid,
+ struct cifs_tcon *tcon,
+ struct cifs_sb_info *cifs_sb,
+ char *tree, bool islink,
+ struct dfs_cache_tgt_list *tl)
{
- int rc;
+ const struct smb_version_operations *ops = tcon->ses->server->ops;
struct TCP_Server_Info *server = tcon->ses->server;
- const struct smb_version_operations *ops = server->ops;
- struct cifs_ses *root_ses = CIFS_DFS_ROOT_SES(tcon->ses);
- char *share = NULL, *prefix = NULL;
struct dfs_cache_tgt_iterator *tit;
+ char *share = NULL, *prefix = NULL;
bool target_match;
-
- tit = dfs_cache_get_tgt_iterator(tl);
- if (!tit) {
- rc = -ENOENT;
- goto out;
- }
+ int rc = -ENOENT;
/* Try to tree connect to all dfs targets */
- for (; tit; tit = dfs_cache_get_next_tgt(tl, tit)) {
- const char *target = dfs_cache_get_tgt_name(tit);
- DFS_CACHE_TGT_LIST(ntl);
-
+ for (tit = dfs_cache_get_tgt_iterator(tl);
+ tit; tit = dfs_cache_get_next_tgt(tl, tit)) {
kfree(share);
kfree(prefix);
share = prefix = NULL;
@@ -479,74 +381,21 @@ static int __tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *t
}
dfs_cache_noreq_update_tgthint(server->leaf_fullpath + 1, tit);
- tree_connect_ipc(xid, tree, cifs_sb, tcon);
-
scnprintf(tree, MAX_TREE_SIZE, "\\%s", share);
- if (!islink) {
- rc = ops->tree_connect(xid, tcon->ses, tree, tcon, cifs_sb->local_nls);
- break;
- }
-
- /*
- * If no dfs referrals were returned from link target, then just do a TREE_CONNECT
- * to it. Otherwise, cache the dfs referral and then mark current tcp ses for
- * reconnect so either the demultiplex thread or the echo worker will reconnect to
- * newly resolved target.
- */
- if (dfs_cache_find(xid, root_ses, cifs_sb->local_nls, cifs_remap(cifs_sb), target,
- NULL, &ntl)) {
- rc = ops->tree_connect(xid, tcon->ses, tree, tcon, cifs_sb->local_nls);
- if (rc)
- continue;
-
+ rc = ops->tree_connect(xid, tcon->ses, tree,
+ tcon, tcon->ses->local_nls);
+ if (islink && !rc && cifs_sb)
rc = cifs_update_super_prepath(cifs_sb, prefix);
- } else {
- /* Target is another dfs share */
- rc = update_server_fullpath(server, cifs_sb, target);
- dfs_cache_free_tgts(tl);
-
- if (!rc) {
- rc = -EREMOTE;
- list_replace_init(&ntl.tl_list, &tl->tl_list);
- } else
- dfs_cache_free_tgts(&ntl);
- }
break;
}
-out:
kfree(share);
kfree(prefix);
-
- return rc;
-}
-
-static int tree_connect_dfs_target(const unsigned int xid, struct cifs_tcon *tcon,
- struct cifs_sb_info *cifs_sb, char *tree, bool islink,
- struct dfs_cache_tgt_list *tl)
-{
- int rc;
- int num_links = 0;
- struct TCP_Server_Info *server = tcon->ses->server;
- char *old_fullpath = server->leaf_fullpath;
-
- do {
- rc = __tree_connect_dfs_target(xid, tcon, cifs_sb, tree, islink, tl);
- if (!rc || rc != -EREMOTE)
- break;
- } while (rc = -ELOOP, ++num_links < MAX_NESTED_LINKS);
- /*
- * If we couldn't tree connect to any targets from last referral path, then
- * retry it from newly resolved dfs referral.
- */
- if (rc && server->leaf_fullpath != old_fullpath)
- cifs_signal_cifsd_for_reconnect(server, true);
-
dfs_cache_free_tgts(tl);
return rc;
}
-int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const struct nls_table *nlsc)
+int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon)
{
int rc;
struct TCP_Server_Info *server = tcon->ses->server;
@@ -588,7 +437,8 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
cifs_server_lock(server);
scnprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$", server->hostname);
cifs_server_unlock(server);
- rc = ops->tree_connect(xid, tcon->ses, tree, tcon, nlsc);
+ rc = ops->tree_connect(xid, tcon->ses, tree,
+ tcon, tcon->ses->local_nls);
goto out;
}
@@ -596,14 +446,11 @@ int cifs_tree_connect(const unsigned int xid, struct cifs_tcon *tcon, const stru
if (!IS_ERR(sb))
cifs_sb = CIFS_SB(sb);
- /*
- * Tree connect to last share in @tcon->tree_name whether dfs super or
- * cached dfs referral was not found.
- */
- if (!cifs_sb || !server->leaf_fullpath ||
+ /* Tree connect to last share in @tcon->tree_name if no DFS referral */
+ if (!server->leaf_fullpath ||
dfs_cache_noreq_find(server->leaf_fullpath + 1, &ref, &tl)) {
- rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name, tcon,
- cifs_sb ? cifs_sb->local_nls : nlsc);
+ rc = ops->tree_connect(xid, tcon->ses, tcon->tree_name,
+ tcon, tcon->ses->local_nls);
goto out;
}
diff --git a/fs/smb/client/dfs_cache.c b/fs/smb/client/dfs_cache.c
index 00820f57b434..541608b0267e 100644
--- a/fs/smb/client/dfs_cache.c
+++ b/fs/smb/client/dfs_cache.c
@@ -24,8 +24,8 @@
#include "dfs_cache.h"
-#define CACHE_HTABLE_SIZE 32
-#define CACHE_MAX_ENTRIES 64
+#define CACHE_HTABLE_SIZE 512
+#define CACHE_MAX_ENTRIES 1024
#define CACHE_MIN_TTL 120 /* 2 minutes */
#define CACHE_DEFAULT_TTL 300 /* 5 minutes */
diff --git a/fs/smb/client/file.c b/fs/smb/client/file.c
index a58a3333ecc3..3b2d33291a7e 100644
--- a/fs/smb/client/file.c
+++ b/fs/smb/client/file.c
@@ -990,7 +990,11 @@ int cifs_open(struct inode *inode, struct file *file)
}
/* Get the cached handle as SMB2 close is deferred */
- rc = cifs_get_readable_path(tcon, full_path, &cfile);
+ if (OPEN_FMODE(file->f_flags) & FMODE_WRITE) {
+ rc = cifs_get_writable_path(tcon, full_path, FIND_WR_FSUID_ONLY, &cfile);
+ } else {
+ rc = cifs_get_readable_path(tcon, full_path, &cfile);
+ }
if (rc == 0) {
if (file->f_flags == cfile->f_flags) {
file->private_data = cfile;
diff --git a/fs/smb/client/fs_context.c b/fs/smb/client/fs_context.c
index c87879e4739b..49123f458d0c 100644
--- a/fs/smb/client/fs_context.c
+++ b/fs/smb/client/fs_context.c
@@ -920,12 +920,37 @@ do { \
cifs_sb->ctx->field = NULL; \
} while (0)
+int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses)
+{
+ if (ses->password &&
+ cifs_sb->ctx->password &&
+ strcmp(ses->password, cifs_sb->ctx->password)) {
+ kfree_sensitive(cifs_sb->ctx->password);
+ cifs_sb->ctx->password = kstrdup(ses->password, GFP_KERNEL);
+ if (!cifs_sb->ctx->password)
+ return -ENOMEM;
+ }
+ if (ses->password2 &&
+ cifs_sb->ctx->password2 &&
+ strcmp(ses->password2, cifs_sb->ctx->password2)) {
+ kfree_sensitive(cifs_sb->ctx->password2);
+ cifs_sb->ctx->password2 = kstrdup(ses->password2, GFP_KERNEL);
+ if (!cifs_sb->ctx->password2) {
+ kfree_sensitive(cifs_sb->ctx->password);
+ cifs_sb->ctx->password = NULL;
+ return -ENOMEM;
+ }
+ }
+ return 0;
+}
+
static int smb3_reconfigure(struct fs_context *fc)
{
struct smb3_fs_context *ctx = smb3_fc2context(fc);
struct dentry *root = fc->root;
struct cifs_sb_info *cifs_sb = CIFS_SB(root->d_sb);
struct cifs_ses *ses = cifs_sb_master_tcon(cifs_sb)->ses;
+ char *new_password = NULL, *new_password2 = NULL;
bool need_recon = false;
int rc;
@@ -945,21 +970,63 @@ static int smb3_reconfigure(struct fs_context *fc)
STEAL_STRING(cifs_sb, ctx, UNC);
STEAL_STRING(cifs_sb, ctx, source);
STEAL_STRING(cifs_sb, ctx, username);
+
if (need_recon == false)
STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
else {
- kfree_sensitive(ses->password);
- ses->password = kstrdup(ctx->password, GFP_KERNEL);
- if (!ses->password)
- return -ENOMEM;
- kfree_sensitive(ses->password2);
- ses->password2 = kstrdup(ctx->password2, GFP_KERNEL);
- if (!ses->password2) {
- kfree_sensitive(ses->password);
- ses->password = NULL;
+ if (ctx->password) {
+ new_password = kstrdup(ctx->password, GFP_KERNEL);
+ if (!new_password)
+ return -ENOMEM;
+ } else
+ STEAL_STRING_SENSITIVE(cifs_sb, ctx, password);
+ }
+
+ /*
+ * if a new password2 has been specified, then reset it's value
+ * inside the ses struct
+ */
+ if (ctx->password2) {
+ new_password2 = kstrdup(ctx->password2, GFP_KERNEL);
+ if (!new_password2) {
+ kfree_sensitive(new_password);
return -ENOMEM;
}
+ } else
+ STEAL_STRING_SENSITIVE(cifs_sb, ctx, password2);
+
+ /*
+ * we may update the passwords in the ses struct below. Make sure we do
+ * not race with smb2_reconnect
+ */
+ mutex_lock(&ses->session_mutex);
+
+ /*
+ * smb2_reconnect may swap password and password2 in case session setup
+ * failed. First get ctx passwords in sync with ses passwords. It should
+ * be okay to do this even if this function were to return an error at a
+ * later stage
+ */
+ rc = smb3_sync_session_ctx_passwords(cifs_sb, ses);
+ if (rc) {
+ mutex_unlock(&ses->session_mutex);
+ return rc;
}
+
+ /*
+ * now that allocations for passwords are done, commit them
+ */
+ if (new_password) {
+ kfree_sensitive(ses->password);
+ ses->password = new_password;
+ }
+ if (new_password2) {
+ kfree_sensitive(ses->password2);
+ ses->password2 = new_password2;
+ }
+
+ mutex_unlock(&ses->session_mutex);
+
STEAL_STRING(cifs_sb, ctx, domainname);
STEAL_STRING(cifs_sb, ctx, nodename);
STEAL_STRING(cifs_sb, ctx, iocharset);
diff --git a/fs/smb/client/fs_context.h b/fs/smb/client/fs_context.h
index 67b7fc48ac58..ac6baa774ad3 100644
--- a/fs/smb/client/fs_context.h
+++ b/fs/smb/client/fs_context.h
@@ -309,6 +309,7 @@ static inline struct smb3_fs_context *smb3_fc2context(const struct fs_context *f
}
extern int smb3_fs_context_dup(struct smb3_fs_context *new_ctx, struct smb3_fs_context *ctx);
+extern int smb3_sync_session_ctx_passwords(struct cifs_sb_info *cifs_sb, struct cifs_ses *ses);
extern void smb3_update_mnt_flags(struct cifs_sb_info *cifs_sb);
/*
diff --git a/fs/smb/client/inode.c b/fs/smb/client/inode.c
index de8063b44072..f146e06c97eb 100644
--- a/fs/smb/client/inode.c
+++ b/fs/smb/client/inode.c
@@ -746,6 +746,88 @@ static int cifs_sfu_mode(struct cifs_fattr *fattr, const unsigned char *path,
#endif
}
+#define POSIX_TYPE_FILE 0
+#define POSIX_TYPE_DIR 1
+#define POSIX_TYPE_SYMLINK 2
+#define POSIX_TYPE_CHARDEV 3
+#define POSIX_TYPE_BLKDEV 4
+#define POSIX_TYPE_FIFO 5
+#define POSIX_TYPE_SOCKET 6
+
+#define POSIX_X_OTH 0000001
+#define POSIX_W_OTH 0000002
+#define POSIX_R_OTH 0000004
+#define POSIX_X_GRP 0000010
+#define POSIX_W_GRP 0000020
+#define POSIX_R_GRP 0000040
+#define POSIX_X_USR 0000100
+#define POSIX_W_USR 0000200
+#define POSIX_R_USR 0000400
+#define POSIX_STICKY 0001000
+#define POSIX_SET_GID 0002000
+#define POSIX_SET_UID 0004000
+
+#define POSIX_OTH_MASK 0000007
+#define POSIX_GRP_MASK 0000070
+#define POSIX_USR_MASK 0000700
+#define POSIX_PERM_MASK 0000777
+#define POSIX_FILETYPE_MASK 0070000
+
+#define POSIX_FILETYPE_SHIFT 12
+
+static u32 wire_perms_to_posix(u32 wire)
+{
+ u32 mode = 0;
+
+ mode |= (wire & POSIX_X_OTH) ? S_IXOTH : 0;
+ mode |= (wire & POSIX_W_OTH) ? S_IWOTH : 0;
+ mode |= (wire & POSIX_R_OTH) ? S_IROTH : 0;
+ mode |= (wire & POSIX_X_GRP) ? S_IXGRP : 0;
+ mode |= (wire & POSIX_W_GRP) ? S_IWGRP : 0;
+ mode |= (wire & POSIX_R_GRP) ? S_IRGRP : 0;
+ mode |= (wire & POSIX_X_USR) ? S_IXUSR : 0;
+ mode |= (wire & POSIX_W_USR) ? S_IWUSR : 0;
+ mode |= (wire & POSIX_R_USR) ? S_IRUSR : 0;
+ mode |= (wire & POSIX_STICKY) ? S_ISVTX : 0;
+ mode |= (wire & POSIX_SET_GID) ? S_ISGID : 0;
+ mode |= (wire & POSIX_SET_UID) ? S_ISUID : 0;
+
+ return mode;
+}
+
+static u32 posix_filetypes[] = {
+ S_IFREG,
+ S_IFDIR,
+ S_IFLNK,
+ S_IFCHR,
+ S_IFBLK,
+ S_IFIFO,
+ S_IFSOCK
+};
+
+static u32 wire_filetype_to_posix(u32 wire_type)
+{
+ if (wire_type >= ARRAY_SIZE(posix_filetypes)) {
+ pr_warn("Unexpected type %u", wire_type);
+ return 0;
+ }
+ return posix_filetypes[wire_type];
+}
+
+umode_t wire_mode_to_posix(u32 wire, bool is_dir)
+{
+ u32 wire_type;
+ u32 mode;
+
+ wire_type = (wire & POSIX_FILETYPE_MASK) >> POSIX_FILETYPE_SHIFT;
+ /* older servers do not set POSIX file type in the mode field in the response */
+ if ((wire_type == 0) && is_dir)
+ mode = wire_perms_to_posix(wire) | S_IFDIR;
+ else
+ mode = (wire_perms_to_posix(wire) | wire_filetype_to_posix(wire_type));
+ return (umode_t)mode;
+}
+
/* Fill a cifs_fattr struct with info from POSIX info struct */
static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr,
struct cifs_open_info_data *data,
@@ -782,20 +864,14 @@ static void smb311_posix_info_to_fattr(struct cifs_fattr *fattr,
fattr->cf_bytes = le64_to_cpu(info->AllocationSize);
fattr->cf_createtime = le64_to_cpu(info->CreationTime);
fattr->cf_nlink = le32_to_cpu(info->HardLinks);
- fattr->cf_mode = (umode_t) le32_to_cpu(info->Mode);
+ fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode),
+ fattr->cf_cifsattrs & ATTR_DIRECTORY);
if (cifs_open_data_reparse(data) &&
cifs_reparse_point_to_fattr(cifs_sb, fattr, data))
goto out_reparse;
- fattr->cf_mode &= ~S_IFMT;
- if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
- fattr->cf_mode |= S_IFDIR;
- fattr->cf_dtype = DT_DIR;
- } else { /* file */
- fattr->cf_mode |= S_IFREG;
- fattr->cf_dtype = DT_REG;
- }
+ fattr->cf_dtype = S_DT(fattr->cf_mode);
out_reparse:
if (S_ISLNK(fattr->cf_mode)) {
@@ -1137,6 +1213,7 @@ static int reparse_info_to_fattr(struct cifs_open_info_data *data,
rc = 0;
} else if (iov && server->ops->parse_reparse_point) {
rc = server->ops->parse_reparse_point(cifs_sb,
+ full_path,
iov, data);
}
break;
@@ -1870,6 +1947,7 @@ int cifs_unlink(struct inode *dir, struct dentry *dentry)
goto unlink_out;
}
+ netfs_wait_for_outstanding_io(inode);
cifs_close_deferred_file_under_dentry(tcon, full_path);
#ifdef CONFIG_CIFS_ALLOW_INSECURE_LEGACY
if (cap_unix(tcon->ses) && (CIFS_UNIX_POSIX_PATH_OPS_CAP &
@@ -2387,8 +2465,10 @@ cifs_rename2(struct mnt_idmap *idmap, struct inode *source_dir,
}
cifs_close_deferred_file_under_dentry(tcon, from_name);
- if (d_inode(target_dentry) != NULL)
+ if (d_inode(target_dentry) != NULL) {
+ netfs_wait_for_outstanding_io(d_inode(target_dentry));
cifs_close_deferred_file_under_dentry(tcon, to_name);
+ }
rc = cifs_do_rename(xid, source_dentry, from_name, target_dentry,
to_name);
@@ -2495,13 +2575,10 @@ cifs_dentry_needs_reval(struct dentry *dentry)
return true;
if (!open_cached_dir_by_dentry(tcon, dentry->d_parent, &cfid)) {
- spin_lock(&cfid->fid_lock);
if (cfid->time && cifs_i->time > cfid->time) {
- spin_unlock(&cfid->fid_lock);
close_cached_dir(cfid);
return false;
}
- spin_unlock(&cfid->fid_lock);
close_cached_dir(cfid);
}
/*
diff --git a/fs/smb/client/readdir.c b/fs/smb/client/readdir.c
index b3a8f9c6fcff..273358d20a46 100644
--- a/fs/smb/client/readdir.c
+++ b/fs/smb/client/readdir.c
@@ -71,6 +71,8 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
struct inode *inode;
struct super_block *sb = parent->d_sb;
struct cifs_sb_info *cifs_sb = CIFS_SB(sb);
+ bool posix = cifs_sb_master_tcon(cifs_sb)->posix_extensions;
+ bool reparse_need_reval = false;
DECLARE_WAIT_QUEUE_HEAD_ONSTACK(wq);
int rc;
@@ -85,7 +87,21 @@ cifs_prime_dcache(struct dentry *parent, struct qstr *name,
* this spares us an invalidation.
*/
retry:
- if ((fattr->cf_cifsattrs & ATTR_REPARSE) ||
+ if (posix) {
+ switch (fattr->cf_mode & S_IFMT) {
+ case S_IFLNK:
+ case S_IFBLK:
+ case S_IFCHR:
+ reparse_need_reval = true;
+ break;
+ default:
+ break;
+ }
+ } else if (fattr->cf_cifsattrs & ATTR_REPARSE) {
+ reparse_need_reval = true;
+ }
+
+ if (reparse_need_reval ||
(fattr->cf_flags & CIFS_FATTR_NEED_REVAL))
return;
@@ -241,31 +257,29 @@ cifs_posix_to_fattr(struct cifs_fattr *fattr, struct smb2_posix_info *info,
fattr->cf_nlink = le32_to_cpu(info->HardLinks);
fattr->cf_cifsattrs = le32_to_cpu(info->DosAttributes);
- /*
- * Since we set the inode type below we need to mask off
- * to avoid strange results if bits set above.
- * XXX: why not make server&client use the type bits?
- */
- fattr->cf_mode = le32_to_cpu(info->Mode) & ~S_IFMT;
+ if (fattr->cf_cifsattrs & ATTR_REPARSE)
+ fattr->cf_cifstag = le32_to_cpu(info->ReparseTag);
+
+ /* The Mode field in the response can now include the file type as well */
+ fattr->cf_mode = wire_mode_to_posix(le32_to_cpu(info->Mode),
+ fattr->cf_cifsattrs & ATTR_DIRECTORY);
+ fattr->cf_dtype = S_DT(le32_to_cpu(info->Mode));
+
+ switch (fattr->cf_mode & S_IFMT) {
+ case S_IFLNK:
+ case S_IFBLK:
+ case S_IFCHR:
+ fattr->cf_flags |= CIFS_FATTR_NEED_REVAL;
+ break;
+ default:
+ break;
+ }
cifs_dbg(FYI, "posix fattr: dev %d, reparse %d, mode %o\n",
le32_to_cpu(info->DeviceId),
le32_to_cpu(info->ReparseTag),
le32_to_cpu(info->Mode));
- if (fattr->cf_cifsattrs & ATTR_DIRECTORY) {
- fattr->cf_mode |= S_IFDIR;
- fattr->cf_dtype = DT_DIR;
- } else {
- /*
- * mark anything that is not a dir as regular
- * file. special files should have the REPARSE
- * attribute and will be marked as needing revaluation
- */
- fattr->cf_mode |= S_IFREG;
- fattr->cf_dtype = DT_REG;
- }
-
sid_to_id(cifs_sb, &parsed.owner, fattr, SIDOWNER);
sid_to_id(cifs_sb, &parsed.group, fattr, SIDGROUP);
}
diff --git a/fs/smb/client/reparse.c b/fs/smb/client/reparse.c
index 90da1e2b6217..d88b41133e00 100644
--- a/fs/smb/client/reparse.c
+++ b/fs/smb/client/reparse.c
@@ -378,8 +378,8 @@ static int wsl_set_xattrs(struct inode *inode, umode_t _mode,
memset(iov, 0, sizeof(*iov));
- /* Exclude $LXDEV xattr for sockets and fifos */
- if (S_ISSOCK(_mode) || S_ISFIFO(_mode))
+ /* Exclude $LXDEV xattr for non-device files */
+ if (!S_ISBLK(_mode) && !S_ISCHR(_mode))
num_xattrs = ARRAY_SIZE(xattrs) - 1;
else
num_xattrs = ARRAY_SIZE(xattrs);
@@ -535,9 +535,95 @@ static int parse_reparse_posix(struct reparse_posix_data *buf,
return 0;
}
+int smb2_parse_native_symlink(char **target, const char *buf, unsigned int len,
+ bool unicode, bool relative,
+ const char *full_path,
+ struct cifs_sb_info *cifs_sb)
+{
+ char sep = CIFS_DIR_SEP(cifs_sb);
+ char *linux_target = NULL;
+ char *smb_target = NULL;
+ int levels;
+ int rc;
+ int i;
+
+ /* Check that length it valid for unicode/non-unicode mode */
+ if (!len || (unicode && (len % 2))) {
+ cifs_dbg(VFS, "srv returned malformed symlink buffer\n");
+ rc = -EIO;
+ goto out;
+ }
+
+ /*
+ * Check that buffer does not contain UTF-16 null codepoint in unicode
+ * mode or null byte in non-unicode mode because Linux cannot process
+ * symlink with null byte.
+ */
+ if ((unicode && UniStrnlen((wchar_t *)buf, len/2) != len/2) ||
+ (!unicode && strnlen(buf, len) != len)) {
+ cifs_dbg(VFS, "srv returned null byte in native symlink target location\n");
+ rc = -EIO;
+ goto out;
+ }
+
+ smb_target = cifs_strndup_from_utf16(buf, len, unicode, cifs_sb->local_nls);
+ if (!smb_target) {
+ rc = -ENOMEM;
+ goto out;
+ }
+
+ if (smb_target[0] == sep && relative) {
+ /*
+ * This is a relative SMB symlink from the top of the share,
+ * which is the top level directory of the Linux mount point.
+ * Linux does not support such relative symlinks, so convert
+ * it to the relative symlink from the current directory.
+ * full_path is the SMB path to the symlink (from which is
+ * extracted current directory) and smb_target is the SMB path
+ * where symlink points, therefore full_path must always be on
+ * the SMB share.
+ */
+ int smb_target_len = strlen(smb_target)+1;
+ levels = 0;
+ for (i = 1; full_path[i]; i++) { /* i=1 to skip leading sep */
+ if (full_path[i] == sep)
+ levels++;
+ }
+ linux_target = kmalloc(levels*3 + smb_target_len, GFP_KERNEL);
+ if (!linux_target) {
+ rc = -ENOMEM;
+ goto out;
+ }
+ for (i = 0; i < levels; i++) {
+ linux_target[i*3 + 0] = '.';
+ linux_target[i*3 + 1] = '.';
+ linux_target[i*3 + 2] = sep;
+ }
+ memcpy(linux_target + levels*3, smb_target+1, smb_target_len); /* +1 to skip leading sep */
+ } else {
+ linux_target = smb_target;
+ smb_target = NULL;
+ }
+
+ if (sep == '\\')
+ convert_delimiter(linux_target, '/');
+
+ rc = 0;
+ *target = linux_target;
+
+ cifs_dbg(FYI, "%s: symlink target: %s\n", __func__, *target);
+
+out:
+ if (rc != 0)
+ kfree(linux_target);
+ kfree(smb_target);
+ return rc;
+}
+
static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym,
u32 plen, bool unicode,
struct cifs_sb_info *cifs_sb,
+ const char *full_path,
struct cifs_open_info_data *data)
{
unsigned int len;
@@ -552,20 +638,64 @@ static int parse_reparse_symlink(struct reparse_symlink_data_buffer *sym,
return -EIO;
}
- data->symlink_target = cifs_strndup_from_utf16(sym->PathBuffer + offs,
- len, unicode,
+ return smb2_parse_native_symlink(&data->symlink_target,
+ sym->PathBuffer + offs,
+ len,
+ unicode,
+ le32_to_cpu(sym->Flags) & SYMLINK_FLAG_RELATIVE,
+ full_path,
+ cifs_sb);
+}
+
+static int parse_reparse_wsl_symlink(struct reparse_wsl_symlink_data_buffer *buf,
+ struct cifs_sb_info *cifs_sb,
+ struct cifs_open_info_data *data)
+{
+ int len = le16_to_cpu(buf->ReparseDataLength);
+ int symname_utf8_len;
+ __le16 *symname_utf16;
+ int symname_utf16_len;
+
+ if (len <= sizeof(buf->Flags)) {
+ cifs_dbg(VFS, "srv returned malformed wsl symlink buffer\n");
+ return -EIO;
+ }
+
+ /* PathBuffer is in UTF-8 but without trailing null-term byte */
+ symname_utf8_len = len - sizeof(buf->Flags);
+ /*
+ * Check that buffer does not contain null byte
+ * because Linux cannot process symlink with null byte.
+ */
+ if (strnlen(buf->PathBuffer, symname_utf8_len) != symname_utf8_len) {
+ cifs_dbg(VFS, "srv returned null byte in wsl symlink target location\n");
+ return -EIO;
+ }
+ symname_utf16 = kzalloc(symname_utf8_len * 2, GFP_KERNEL);
+ if (!symname_utf16)
+ return -ENOMEM;
+ symname_utf16_len = utf8s_to_utf16s(buf->PathBuffer, symname_utf8_len,
+ UTF16_LITTLE_ENDIAN,
+ (wchar_t *) symname_utf16, symname_utf8_len * 2);
+ if (symname_utf16_len < 0) {
+ kfree(symname_utf16);
+ return symname_utf16_len;
+ }
+ symname_utf16_len *= 2; /* utf8s_to_utf16s() returns number of u16 items, not byte length */
+
+ data->symlink_target = cifs_strndup_from_utf16((u8 *)symname_utf16,
+ symname_utf16_len, true,
cifs_sb->local_nls);
+ kfree(symname_utf16);
if (!data->symlink_target)
return -ENOMEM;
- convert_delimiter(data->symlink_target, '/');
- cifs_dbg(FYI, "%s: target path: %s\n", __func__, data->symlink_target);
-
return 0;
}
int parse_reparse_point(struct reparse_data_buffer *buf,
u32 plen, struct cifs_sb_info *cifs_sb,
+ const char *full_path,
bool unicode, struct cifs_open_info_data *data)
{
struct cifs_tcon *tcon = cifs_sb_master_tcon(cifs_sb);
@@ -580,12 +710,20 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
case IO_REPARSE_TAG_SYMLINK:
return parse_reparse_symlink(
(struct reparse_symlink_data_buffer *)buf,
- plen, unicode, cifs_sb, data);
+ plen, unicode, cifs_sb, full_path, data);
case IO_REPARSE_TAG_LX_SYMLINK:
+ return parse_reparse_wsl_symlink(
+ (struct reparse_wsl_symlink_data_buffer *)buf,
+ cifs_sb, data);
case IO_REPARSE_TAG_AF_UNIX:
case IO_REPARSE_TAG_LX_FIFO:
case IO_REPARSE_TAG_LX_CHR:
case IO_REPARSE_TAG_LX_BLK:
+ if (le16_to_cpu(buf->ReparseDataLength) != 0) {
+ cifs_dbg(VFS, "srv returned malformed buffer for reparse point: 0x%08x\n",
+ le32_to_cpu(buf->ReparseTag));
+ return -EIO;
+ }
break;
default:
cifs_tcon_dbg(VFS | ONCE, "unhandled reparse tag: 0x%08x\n",
@@ -596,6 +734,7 @@ int parse_reparse_point(struct reparse_data_buffer *buf,
}
int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
+ const char *full_path,
struct kvec *rsp_iov,
struct cifs_open_info_data *data)
{
@@ -605,7 +744,7 @@ int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
buf = (struct reparse_data_buffer *)((u8 *)io +
le32_to_cpu(io->OutputOffset));
- return parse_reparse_point(buf, plen, cifs_sb, true, data);
+ return parse_reparse_point(buf, plen, cifs_sb, full_path, true, data);
}
static void wsl_to_fattr(struct cifs_open_info_data *data,
@@ -664,44 +803,60 @@ out:
fattr->cf_dtype = S_DT(fattr->cf_mode);
}
-bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
- struct cifs_fattr *fattr,
- struct cifs_open_info_data *data)
+static bool posix_reparse_to_fattr(struct cifs_sb_info *cifs_sb,
+ struct cifs_fattr *fattr,
+ struct cifs_open_info_data *data)
{
struct reparse_posix_data *buf = data->reparse.posix;
- u32 tag = data->reparse.tag;
- if (tag == IO_REPARSE_TAG_NFS && buf) {
- if (le16_to_cpu(buf->ReparseDataLength) < sizeof(buf->InodeType))
+
+ if (buf == NULL)
+ return true;
+
+ if (le16_to_cpu(buf->ReparseDataLength) < sizeof(buf->InodeType)) {
+ WARN_ON_ONCE(1);
+ return false;
+ }
+
+ switch (le64_to_cpu(buf->InodeType)) {
+ case NFS_SPECFILE_CHR:
+ if (le16_to_cpu(buf->ReparseDataLength) != sizeof(buf->InodeType) + 8) {
+ WARN_ON_ONCE(1);
return false;
- switch (le64_to_cpu(buf->InodeType)) {
- case NFS_SPECFILE_CHR:
- if (le16_to_cpu(buf->ReparseDataLength) != sizeof(buf->InodeType) + 8)
- return false;
- fattr->cf_mode |= S_IFCHR;
- fattr->cf_rdev = reparse_mkdev(buf->DataBuffer);
- break;
- case NFS_SPECFILE_BLK:
- if (le16_to_cpu(buf->ReparseDataLength) != sizeof(buf->InodeType) + 8)
- return false;
- fattr->cf_mode |= S_IFBLK;
- fattr->cf_rdev = reparse_mkdev(buf->DataBuffer);
- break;
- case NFS_SPECFILE_FIFO:
- fattr->cf_mode |= S_IFIFO;
- break;
- case NFS_SPECFILE_SOCK:
- fattr->cf_mode |= S_IFSOCK;
- break;
- case NFS_SPECFILE_LNK:
- fattr->cf_mode |= S_IFLNK;
- break;
- default:
+ }
+ fattr->cf_mode |= S_IFCHR;
+ fattr->cf_rdev = reparse_mkdev(buf->DataBuffer);
+ break;
+ case NFS_SPECFILE_BLK:
+ if (le16_to_cpu(buf->ReparseDataLength) != sizeof(buf->InodeType) + 8) {
WARN_ON_ONCE(1);
return false;
}
- goto out;
+ fattr->cf_mode |= S_IFBLK;
+ fattr->cf_rdev = reparse_mkdev(buf->DataBuffer);
+ break;
+ case NFS_SPECFILE_FIFO:
+ fattr->cf_mode |= S_IFIFO;
+ break;
+ case NFS_SPECFILE_SOCK:
+ fattr->cf_mode |= S_IFSOCK;
+ break;
+ case NFS_SPECFILE_LNK:
+ fattr->cf_mode |= S_IFLNK;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ return false;
}
+ return true;
+}
+
+bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
+ struct cifs_fattr *fattr,
+ struct cifs_open_info_data *data)
+{
+ u32 tag = data->reparse.tag;
+ bool ok;
switch (tag) {
case IO_REPARSE_TAG_INTERNAL:
@@ -721,15 +876,19 @@ bool cifs_reparse_point_to_fattr(struct cifs_sb_info *cifs_sb,
case IO_REPARSE_TAG_LX_BLK:
wsl_to_fattr(data, cifs_sb, tag, fattr);
break;
+ case IO_REPARSE_TAG_NFS:
+ ok = posix_reparse_to_fattr(cifs_sb, fattr, data);
+ if (!ok)
+ return false;
+ break;
case 0: /* SMB1 symlink */
case IO_REPARSE_TAG_SYMLINK:
- case IO_REPARSE_TAG_NFS:
fattr->cf_mode |= S_IFLNK;
break;
default:
return false;
}
-out:
+
fattr->cf_dtype = S_DT(fattr->cf_mode);
return true;
}
diff --git a/fs/smb/client/reparse.h b/fs/smb/client/reparse.h
index 2a9f4f9f79de..ff05b0e75c92 100644
--- a/fs/smb/client/reparse.h
+++ b/fs/smb/client/reparse.h
@@ -117,7 +117,9 @@ int smb2_create_reparse_symlink(const unsigned int xid, struct inode *inode,
int smb2_mknod_reparse(unsigned int xid, struct inode *inode,
struct dentry *dentry, struct cifs_tcon *tcon,
const char *full_path, umode_t mode, dev_t dev);
-int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb, struct kvec *rsp_iov,
+int smb2_parse_reparse_point(struct cifs_sb_info *cifs_sb,
+ const char *full_path,
+ struct kvec *rsp_iov,
struct cifs_open_info_data *data);
#endif /* _CIFS_REPARSE_H */
diff --git a/fs/smb/client/sess.c b/fs/smb/client/sess.c
index c88e9657f47a..91d4d409cb1d 100644
--- a/fs/smb/client/sess.c
+++ b/fs/smb/client/sess.c
@@ -27,31 +27,6 @@ static int
cifs_ses_add_channel(struct cifs_ses *ses,
struct cifs_server_iface *iface);
-bool
-is_server_using_iface(struct TCP_Server_Info *server,
- struct cifs_server_iface *iface)
-{
- struct sockaddr_in *i4 = (struct sockaddr_in *)&iface->sockaddr;
- struct sockaddr_in6 *i6 = (struct sockaddr_in6 *)&iface->sockaddr;
- struct sockaddr_in *s4 = (struct sockaddr_in *)&server->dstaddr;
- struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)&server->dstaddr;
-
- if (server->dstaddr.ss_family != iface->sockaddr.ss_family)
- return false;
- if (server->dstaddr.ss_family == AF_INET) {
- if (s4->sin_addr.s_addr != i4->sin_addr.s_addr)
- return false;
- } else if (server->dstaddr.ss_family == AF_INET6) {
- if (memcmp(&s6->sin6_addr, &i6->sin6_addr,
- sizeof(i6->sin6_addr)) != 0)
- return false;
- } else {
- /* unknown family.. */
- return false;
- }
- return true;
-}
-
bool is_ses_using_iface(struct cifs_ses *ses, struct cifs_server_iface *iface)
{
int i;
@@ -347,10 +322,7 @@ done:
spin_unlock(&ses->chan_lock);
}
-/*
- * update the iface for the channel if necessary.
- * Must be called with chan_lock held.
- */
+/* update the iface for the channel if necessary. */
void
cifs_chan_update_iface(struct cifs_ses *ses, struct TCP_Server_Info *server)
{
@@ -491,11 +463,11 @@ cifs_ses_add_channel(struct cifs_ses *ses,
if (iface->sockaddr.ss_family == AF_INET)
cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI4)\n",
- ses, iface->speed, iface->rdma_capable ? "yes" : "no",
+ ses, iface->speed, str_yes_no(iface->rdma_capable),
&ipv4->sin_addr);
else
cifs_dbg(FYI, "adding channel to ses %p (speed:%zu bps rdma:%s ip:%pI6)\n",
- ses, iface->speed, iface->rdma_capable ? "yes" : "no",
+ ses, iface->speed, str_yes_no(iface->rdma_capable),
&ipv6->sin6_addr);
/*
diff --git a/fs/smb/client/smb1ops.c b/fs/smb/client/smb1ops.c
index 9a6ece66c4d3..db3695eddcf9 100644
--- a/fs/smb/client/smb1ops.c
+++ b/fs/smb/client/smb1ops.c
@@ -994,17 +994,17 @@ static int cifs_query_symlink(const unsigned int xid,
}
static int cifs_parse_reparse_point(struct cifs_sb_info *cifs_sb,
+ const char *full_path,
struct kvec *rsp_iov,
struct cifs_open_info_data *data)
{
struct reparse_data_buffer *buf;
TRANSACT_IOCTL_RSP *io = rsp_iov->iov_base;
- bool unicode = !!(io->hdr.Flags2 & SMBFLG2_UNICODE);
u32 plen = le16_to_cpu(io->ByteCount);
buf = (struct reparse_data_buffer *)((__u8 *)&io->hdr.Protocol +
le32_to_cpu(io->DataOffset));
- return parse_reparse_point(buf, plen, cifs_sb, unicode, data);
+ return parse_reparse_point(buf, plen, cifs_sb, full_path, true, data);
}
static bool
diff --git a/fs/smb/client/smb2file.c b/fs/smb/client/smb2file.c
index e301349b0078..e836bc2193dd 100644
--- a/fs/smb/client/smb2file.c
+++ b/fs/smb/client/smb2file.c
@@ -63,12 +63,12 @@ static struct smb2_symlink_err_rsp *symlink_data(const struct kvec *iov)
return sym;
}
-int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov, char **path)
+int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov,
+ const char *full_path, char **path)
{
struct smb2_symlink_err_rsp *sym;
unsigned int sub_offs, sub_len;
unsigned int print_offs, print_len;
- char *s;
if (!cifs_sb || !iov || !iov->iov_base || !iov->iov_len || !path)
return -EINVAL;
@@ -86,15 +86,13 @@ int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec
iov->iov_len < SMB2_SYMLINK_STRUCT_SIZE + print_offs + print_len)
return -EINVAL;
- s = cifs_strndup_from_utf16((char *)sym->PathBuffer + sub_offs, sub_len, true,
- cifs_sb->local_nls);
- if (!s)
- return -ENOMEM;
- convert_delimiter(s, '/');
- cifs_dbg(FYI, "%s: symlink target: %s\n", __func__, s);
-
- *path = s;
- return 0;
+ return smb2_parse_native_symlink(path,
+ (char *)sym->PathBuffer + sub_offs,
+ sub_len,
+ true,
+ le32_to_cpu(sym->Flags) & SYMLINK_FLAG_RELATIVE,
+ full_path,
+ cifs_sb);
}
int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock, void *buf)
@@ -126,6 +124,7 @@ int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32
goto out;
if (hdr->Status == STATUS_STOPPED_ON_SYMLINK) {
rc = smb2_parse_symlink_response(oparms->cifs_sb, &err_iov,
+ oparms->path,
&data->symlink_target);
if (!rc) {
memset(smb2_data, 0, sizeof(*smb2_data));
diff --git a/fs/smb/client/smb2inode.c b/fs/smb/client/smb2inode.c
index e49d0c25eb03..a55f0044d30b 100644
--- a/fs/smb/client/smb2inode.c
+++ b/fs/smb/client/smb2inode.c
@@ -828,6 +828,7 @@ finished:
static int parse_create_response(struct cifs_open_info_data *data,
struct cifs_sb_info *cifs_sb,
+ const char *full_path,
const struct kvec *iov)
{
struct smb2_create_rsp *rsp = iov->iov_base;
@@ -841,6 +842,7 @@ static int parse_create_response(struct cifs_open_info_data *data,
break;
case STATUS_STOPPED_ON_SYMLINK:
rc = smb2_parse_symlink_response(cifs_sb, iov,
+ full_path,
&data->symlink_target);
if (rc)
return rc;
@@ -930,18 +932,19 @@ int smb2_query_path_info(const unsigned int xid,
switch (rc) {
case 0:
- rc = parse_create_response(data, cifs_sb, &out_iov[0]);
+ rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
break;
case -EOPNOTSUPP:
/*
* BB TODO: When support for special files added to Samba
* re-verify this path.
*/
- rc = parse_create_response(data, cifs_sb, &out_iov[0]);
+ rc = parse_create_response(data, cifs_sb, full_path, &out_iov[0]);
if (rc || !data->reparse_point)
goto out;
- cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA;
+ if (!tcon->posix_extensions)
+ cmds[num_cmds++] = SMB2_OP_QUERY_WSL_EA;
/*
* Skip SMB2_OP_GET_REPARSE if symlink already parsed in create
* response.
diff --git a/fs/smb/client/smb2ops.c b/fs/smb/client/smb2ops.c
index fa96ebed8310..87cb1872db28 100644
--- a/fs/smb/client/smb2ops.c
+++ b/fs/smb/client/smb2ops.c
@@ -2932,7 +2932,7 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
struct fsctl_get_dfs_referral_req *dfs_req = NULL;
struct get_dfs_referral_rsp *dfs_rsp = NULL;
u32 dfs_req_size = 0, dfs_rsp_size = 0;
- int retry_count = 0;
+ int retry_once = 0;
cifs_dbg(FYI, "%s: path: %s\n", __func__, search_name);
@@ -2981,21 +2981,25 @@ smb2_get_dfs_refer(const unsigned int xid, struct cifs_ses *ses,
/* Path to resolve in an UTF-16 null-terminated string */
memcpy(dfs_req->RequestFileName, utf16_path, utf16_path_len);
- do {
+ for (;;) {
rc = SMB2_ioctl(xid, tcon, NO_FILE_ID, NO_FILE_ID,
FSCTL_DFS_GET_REFERRALS,
(char *)dfs_req, dfs_req_size, CIFSMaxBufSize,
(char **)&dfs_rsp, &dfs_rsp_size);
- if (!is_retryable_error(rc))
+ if (fatal_signal_pending(current)) {
+ rc = -EINTR;
+ break;
+ }
+ if (!is_retryable_error(rc) || retry_once++)
break;
usleep_range(512, 2048);
- } while (++retry_count < 5);
+ }
if (!rc && !dfs_rsp)
rc = -EIO;
if (rc) {
if (!is_retryable_error(rc) && rc != -ENOENT && rc != -EOPNOTSUPP)
- cifs_tcon_dbg(VFS, "%s: ioctl error: rc=%d\n", __func__, rc);
+ cifs_tcon_dbg(FYI, "%s: ioctl error: rc=%d\n", __func__, rc);
goto out;
}
diff --git a/fs/smb/client/smb2pdu.c b/fs/smb/client/smb2pdu.c
index 055236835537..0577556f0a41 100644
--- a/fs/smb/client/smb2pdu.c
+++ b/fs/smb/client/smb2pdu.c
@@ -216,10 +216,9 @@ static int
smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
struct TCP_Server_Info *server, bool from_reconnect)
{
- int rc = 0;
- struct nls_table *nls_codepage = NULL;
struct cifs_ses *ses;
int xid;
+ int rc = 0;
/*
* SMB2s NegProt, SessSetup, Logoff do not have tcon yet so
@@ -229,11 +228,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon,
if (tcon == NULL)
return 0;
- /*
- * Need to also skip SMB2_IOCTL because it is used for checking nested dfs links in
- * cifs_tree_connect().
- */
- if (smb2_command == SMB2_TREE_CONNECT || smb2_command == SMB2_IOCTL)
+ if (smb2_command == SMB2_TREE_CONNECT)
return 0;
spin_lock(&tcon->tc_lock);
@@ -334,8 +329,6 @@ again:
}
spin_unlock(&server->srv_lock);
- nls_codepage = ses->local_nls;
-
/*
* need to prevent multiple threads trying to simultaneously
* reconnect the same SMB session
@@ -372,7 +365,7 @@ again:
}
}
- rc = cifs_setup_session(0, ses, server, nls_codepage);
+ rc = cifs_setup_session(0, ses, server, ses->local_nls);
if ((rc == -EACCES) || (rc == -EKEYEXPIRED) || (rc == -EKEYREVOKED)) {
/*
* Try alternate password for next reconnect (key rotation
@@ -406,7 +399,7 @@ skip_sess_setup:
if (tcon->use_persistent)
tcon->need_reopen_files = true;
- rc = cifs_tree_connect(0, tcon, nls_codepage);
+ rc = cifs_tree_connect(0, tcon);
cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
if (rc) {
@@ -494,6 +487,7 @@ out:
case SMB2_CHANGE_NOTIFY:
case SMB2_QUERY_INFO:
case SMB2_SET_INFO:
+ case SMB2_IOCTL:
rc = -EAGAIN;
}
failed:
@@ -1231,7 +1225,9 @@ SMB2_negotiate(const unsigned int xid,
* SMB3.0 supports only 1 cipher and doesn't have a encryption neg context
* Set the cipher type manually.
*/
- if (server->dialect == SMB30_PROT_ID && (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
+ if ((server->dialect == SMB30_PROT_ID ||
+ server->dialect == SMB302_PROT_ID) &&
+ (server->capabilities & SMB2_GLOBAL_CAP_ENCRYPTION))
server->cipher_type = SMB2_ENCRYPTION_AES128_CCM;
security_blob = smb2_get_data_area_len(&blob_offset, &blob_length,
@@ -4619,6 +4615,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
__set_bit(NETFS_SREQ_HIT_EOF, &rdata->subreq.flags);
rdata->result = 0;
}
+ __set_bit(NETFS_SREQ_MADE_PROGRESS, &rdata->subreq.flags);
}
trace_smb3_rw_credits(rreq_debug_id, subreq_debug_index, rdata->credits.value,
server->credits, server->in_flight,
@@ -4844,10 +4841,14 @@ smb2_writev_callback(struct mid_q_entry *mid)
if (written > wdata->subreq.len)
written &= 0xFFFF;
- if (written < wdata->subreq.len)
+ cifs_stats_bytes_written(tcon, written);
+
+ if (written < wdata->subreq.len) {
wdata->result = -ENOSPC;
- else
+ } else if (written > 0) {
wdata->subreq.len = written;
+ __set_bit(NETFS_SREQ_MADE_PROGRESS, &wdata->subreq.flags);
+ }
break;
case MID_REQUEST_SUBMITTED:
case MID_RETRY_NEEDED:
@@ -5016,7 +5017,7 @@ smb2_async_writev(struct cifs_io_subrequest *wdata)
}
#endif
- if (test_bit(NETFS_SREQ_RETRYING, &wdata->subreq.flags))
+ if (wdata->subreq.retry_count > 0)
smb2_set_replay(server, &rqst);
cifs_dbg(FYI, "async write at %llu %u bytes iter=%zx\n",
@@ -5160,6 +5161,7 @@ replay_again:
cifs_dbg(VFS, "Send error in write = %d\n", rc);
} else {
*nbytes = le32_to_cpu(rsp->DataLength);
+ cifs_stats_bytes_written(io_parms->tcon, *nbytes);
trace_smb3_write_done(0, 0, xid,
req->PersistentFileId,
io_parms->tcon->tid,
@@ -6208,7 +6210,7 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
req->StructureSize = cpu_to_le16(36);
total_len += 12;
- memcpy(req->LeaseKey, lease_key, 16);
+ memcpy(req->LeaseKey, lease_key, SMB2_LEASE_KEY_SIZE);
req->LeaseState = lease_state;
flags |= CIFS_NO_RSP_BUF;
diff --git a/fs/smb/client/smb2proto.h b/fs/smb/client/smb2proto.h
index 71504b30909e..09349fa8da03 100644
--- a/fs/smb/client/smb2proto.h
+++ b/fs/smb/client/smb2proto.h
@@ -111,7 +111,14 @@ extern int smb3_query_mf_symlink(unsigned int xid, struct cifs_tcon *tcon,
struct cifs_sb_info *cifs_sb,
const unsigned char *path, char *pbuf,
unsigned int *pbytes_read);
-int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb, const struct kvec *iov, char **path);
+int smb2_parse_native_symlink(char **target, const char *buf, unsigned int len,
+ bool unicode, bool relative,
+ const char *full_path,
+ struct cifs_sb_info *cifs_sb);
+int smb2_parse_symlink_response(struct cifs_sb_info *cifs_sb,
+ const struct kvec *iov,
+ const char *full_path,
+ char **path);
int smb2_open_file(const unsigned int xid, struct cifs_open_parms *oparms, __u32 *oplock,
void *buf);
extern int smb2_unlock_range(struct cifsFileInfo *cfile,
diff --git a/fs/smb/client/trace.h b/fs/smb/client/trace.h
index 0b52d22a91a0..12cbd3428a6d 100644
--- a/fs/smb/client/trace.h
+++ b/fs/smb/client/trace.h
@@ -44,6 +44,8 @@
EM(netfs_trace_tcon_ref_free_ipc, "FRE Ipc ") \
EM(netfs_trace_tcon_ref_free_ipc_fail, "FRE Ipc-F ") \
EM(netfs_trace_tcon_ref_free_reconnect_server, "FRE Reconn") \
+ EM(netfs_trace_tcon_ref_get_cached_laundromat, "GET Ch-Lau") \
+ EM(netfs_trace_tcon_ref_get_cached_lease_break, "GET Ch-Lea") \
EM(netfs_trace_tcon_ref_get_cancelled_close, "GET Cn-Cls") \
EM(netfs_trace_tcon_ref_get_dfs_refer, "GET DfsRef") \
EM(netfs_trace_tcon_ref_get_find, "GET Find ") \
@@ -52,6 +54,7 @@
EM(netfs_trace_tcon_ref_new, "NEW ") \
EM(netfs_trace_tcon_ref_new_ipc, "NEW Ipc ") \
EM(netfs_trace_tcon_ref_new_reconnect_server, "NEW Reconn") \
+ EM(netfs_trace_tcon_ref_put_cached_close, "PUT Ch-Cls") \
EM(netfs_trace_tcon_ref_put_cancelled_close, "PUT Cn-Cls") \
EM(netfs_trace_tcon_ref_put_cancelled_close_fid, "PUT Cn-Fid") \
EM(netfs_trace_tcon_ref_put_cancelled_mid, "PUT Cn-Mid") \
diff --git a/fs/smb/common/smb2pdu.h b/fs/smb/common/smb2pdu.h
index 9f272cc8f566..3c7c706c797d 100644
--- a/fs/smb/common/smb2pdu.h
+++ b/fs/smb/common/smb2pdu.h
@@ -1552,6 +1552,15 @@ struct reparse_symlink_data_buffer {
/* See MS-FSCC 2.1.2.6 and cifspdu.h for struct reparse_posix_data */
+/* For IO_REPARSE_TAG_LX_SYMLINK */
+struct reparse_wsl_symlink_data_buffer {
+ __le32 ReparseTag;
+ __le16 ReparseDataLength;
+ __u16 Reserved;
+ __le32 Flags;
+ __u8 PathBuffer[]; /* Variable Length UTF-8 string without nul-term */
+} __packed;
+
struct validate_negotiate_info_req {
__le32 Capabilities;
__u8 Guid[SMB2_CLIENT_GUID_SIZE];
diff --git a/fs/smb/server/asn1.c b/fs/smb/server/asn1.c
index b931a99ab9c8..5c4c5121fece 100644
--- a/fs/smb/server/asn1.c
+++ b/fs/smb/server/asn1.c
@@ -104,7 +104,7 @@ int build_spnego_ntlmssp_neg_blob(unsigned char **pbuffer, u16 *buflen,
oid_len + ntlmssp_len) * 2 +
neg_result_len + oid_len + ntlmssp_len;
- buf = kmalloc(total_len, GFP_KERNEL);
+ buf = kmalloc(total_len, KSMBD_DEFAULT_GFP);
if (!buf)
return -ENOMEM;
@@ -140,7 +140,7 @@ int build_spnego_ntlmssp_auth_blob(unsigned char **pbuffer, u16 *buflen,
int total_len = 4 + compute_asn_hdr_len_bytes(neg_result_len) * 2 +
neg_result_len;
- buf = kmalloc(total_len, GFP_KERNEL);
+ buf = kmalloc(total_len, KSMBD_DEFAULT_GFP);
if (!buf)
return -ENOMEM;
@@ -217,7 +217,7 @@ static int ksmbd_neg_token_alloc(void *context, size_t hdrlen,
if (!vlen)
return -EINVAL;
- conn->mechToken = kmemdup_nul(value, vlen, GFP_KERNEL);
+ conn->mechToken = kmemdup_nul(value, vlen, KSMBD_DEFAULT_GFP);
if (!conn->mechToken)
return -ENOMEM;
diff --git a/fs/smb/server/auth.c b/fs/smb/server/auth.c
index 611716bc8f27..2a5b4a96bf99 100644
--- a/fs/smb/server/auth.c
+++ b/fs/smb/server/auth.c
@@ -151,7 +151,7 @@ static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
/* convert user_name to unicode */
len = strlen(user_name(sess->user));
- uniname = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
+ uniname = kzalloc(2 + UNICODE_LEN(len), KSMBD_DEFAULT_GFP);
if (!uniname) {
ret = -ENOMEM;
goto out;
@@ -175,7 +175,7 @@ static int calc_ntlmv2_hash(struct ksmbd_conn *conn, struct ksmbd_session *sess,
/* Convert domain name or conn name to unicode and uppercase */
len = strlen(dname);
- domain = kzalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
+ domain = kzalloc(2 + UNICODE_LEN(len), KSMBD_DEFAULT_GFP);
if (!domain) {
ret = -ENOMEM;
goto out;
@@ -254,7 +254,7 @@ int ksmbd_auth_ntlmv2(struct ksmbd_conn *conn, struct ksmbd_session *sess,
}
len = CIFS_CRYPTO_KEY_SIZE + blen;
- construct = kzalloc(len, GFP_KERNEL);
+ construct = kzalloc(len, KSMBD_DEFAULT_GFP);
if (!construct) {
rc = -ENOMEM;
goto out;
@@ -361,7 +361,7 @@ int ksmbd_decode_ntlmssp_auth_blob(struct authenticate_message *authblob,
if (sess_key_len > CIFS_KEY_SIZE)
return -EINVAL;
- ctx_arc4 = kmalloc(sizeof(*ctx_arc4), GFP_KERNEL);
+ ctx_arc4 = kmalloc(sizeof(*ctx_arc4), KSMBD_DEFAULT_GFP);
if (!ctx_arc4)
return -ENOMEM;
@@ -451,7 +451,7 @@ ksmbd_build_ntlmssp_challenge_blob(struct challenge_message *chgblob,
chgblob->NegotiateFlags = cpu_to_le32(flags);
len = strlen(ksmbd_netbios_name());
- name = kmalloc(2 + UNICODE_LEN(len), GFP_KERNEL);
+ name = kmalloc(2 + UNICODE_LEN(len), KSMBD_DEFAULT_GFP);
if (!name)
return -ENOMEM;
@@ -1016,6 +1016,8 @@ static int ksmbd_get_encryption_key(struct ksmbd_work *work, __u64 ses_id,
ses_enc_key = enc ? sess->smb3encryptionkey :
sess->smb3decryptionkey;
+ if (enc)
+ ksmbd_user_session_get(sess);
memcpy(key, ses_enc_key, SMB3_ENC_DEC_KEY_SIZE);
return 0;
@@ -1043,7 +1045,7 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
if (!nvec)
return NULL;
- nr_entries = kcalloc(nvec, sizeof(int), GFP_KERNEL);
+ nr_entries = kcalloc(nvec, sizeof(int), KSMBD_DEFAULT_GFP);
if (!nr_entries)
return NULL;
@@ -1063,7 +1065,8 @@ static struct scatterlist *ksmbd_init_sg(struct kvec *iov, unsigned int nvec,
/* Add two entries for transform header and signature */
total_entries += 2;
- sg = kmalloc_array(total_entries, sizeof(struct scatterlist), GFP_KERNEL);
+ sg = kmalloc_array(total_entries, sizeof(struct scatterlist),
+ KSMBD_DEFAULT_GFP);
if (!sg) {
kfree(nr_entries);
return NULL;
@@ -1163,7 +1166,7 @@ int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
goto free_ctx;
}
- req = aead_request_alloc(tfm, GFP_KERNEL);
+ req = aead_request_alloc(tfm, KSMBD_DEFAULT_GFP);
if (!req) {
rc = -ENOMEM;
goto free_ctx;
@@ -1182,7 +1185,7 @@ int ksmbd_crypt_message(struct ksmbd_work *work, struct kvec *iov,
}
iv_len = crypto_aead_ivsize(tfm);
- iv = kzalloc(iv_len, GFP_KERNEL);
+ iv = kzalloc(iv_len, KSMBD_DEFAULT_GFP);
if (!iv) {
rc = -ENOMEM;
goto free_sg;
diff --git a/fs/smb/server/connection.c b/fs/smb/server/connection.c
index e6a72f75ab94..f8a40f65db6a 100644
--- a/fs/smb/server/connection.c
+++ b/fs/smb/server/connection.c
@@ -52,7 +52,7 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
{
struct ksmbd_conn *conn;
- conn = kzalloc(sizeof(struct ksmbd_conn), GFP_KERNEL);
+ conn = kzalloc(sizeof(struct ksmbd_conn), KSMBD_DEFAULT_GFP);
if (!conn)
return NULL;
@@ -70,7 +70,6 @@ struct ksmbd_conn *ksmbd_conn_alloc(void)
atomic_set(&conn->req_running, 0);
atomic_set(&conn->r_count, 0);
atomic_set(&conn->refcnt, 1);
- atomic_set(&conn->mux_smb_requests, 0);
conn->total_credits = 1;
conn->outstanding_credits = 0;
@@ -120,8 +119,8 @@ void ksmbd_conn_enqueue_request(struct ksmbd_work *work)
if (conn->ops->get_cmd_val(work) != SMB2_CANCEL_HE)
requests_queue = &conn->requests;
+ atomic_inc(&conn->req_running);
if (requests_queue) {
- atomic_inc(&conn->req_running);
spin_lock(&conn->request_lock);
list_add_tail(&work->request_entry, requests_queue);
spin_unlock(&conn->request_lock);
@@ -132,11 +131,14 @@ void ksmbd_conn_try_dequeue_request(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
+ atomic_dec(&conn->req_running);
+ if (waitqueue_active(&conn->req_running_q))
+ wake_up(&conn->req_running_q);
+
if (list_empty(&work->request_entry) &&
list_empty(&work->async_request_entry))
return;
- atomic_dec(&conn->req_running);
spin_lock(&conn->request_lock);
list_del_init(&work->request_entry);
spin_unlock(&conn->request_lock);
@@ -308,7 +310,7 @@ int ksmbd_conn_handler_loop(void *p)
{
struct ksmbd_conn *conn = (struct ksmbd_conn *)p;
struct ksmbd_transport *t = conn->transport;
- unsigned int pdu_size, max_allowed_pdu_size;
+ unsigned int pdu_size, max_allowed_pdu_size, max_req;
char hdr_buf[4] = {0,};
int size;
@@ -318,6 +320,7 @@ int ksmbd_conn_handler_loop(void *p)
if (t->ops->prepare && t->ops->prepare(t))
goto out;
+ max_req = server_conf.max_inflight_req;
conn->last_active = jiffies;
set_freezable();
while (ksmbd_conn_alive(conn)) {
@@ -327,6 +330,13 @@ int ksmbd_conn_handler_loop(void *p)
kvfree(conn->request_buf);
conn->request_buf = NULL;
+recheck:
+ if (atomic_read(&conn->req_running) + 1 > max_req) {
+ wait_event_interruptible(conn->req_running_q,
+ atomic_read(&conn->req_running) < max_req);
+ goto recheck;
+ }
+
size = t->ops->read(t, hdr_buf, sizeof(hdr_buf), -1);
if (size != sizeof(hdr_buf))
break;
@@ -359,7 +369,7 @@ int ksmbd_conn_handler_loop(void *p)
/* 4 for rfc1002 length field */
/* 1 for implied bcc[0] */
size = pdu_size + 4 + 1;
- conn->request_buf = kvmalloc(size, GFP_KERNEL);
+ conn->request_buf = kvmalloc(size, KSMBD_DEFAULT_GFP);
if (!conn->request_buf)
break;
@@ -404,6 +414,7 @@ int ksmbd_conn_handler_loop(void *p)
out:
ksmbd_conn_set_releasing(conn);
/* Wait till all reference dropped to the Server object*/
+ ksmbd_debug(CONN, "Wait for all pending requests(%d)\n", atomic_read(&conn->r_count));
wait_event(conn->r_count_q, atomic_read(&conn->r_count) == 0);
if (IS_ENABLED(CONFIG_UNICODE))
@@ -462,7 +473,7 @@ again:
up_read(&conn_list_lock);
if (!list_empty(&conn_list)) {
- schedule_timeout_interruptible(HZ / 10); /* 100ms */
+ msleep(100);
goto again;
}
}
diff --git a/fs/smb/server/connection.h b/fs/smb/server/connection.h
index 8ddd5a3c7baf..b379ae4fdcdf 100644
--- a/fs/smb/server/connection.h
+++ b/fs/smb/server/connection.h
@@ -107,7 +107,6 @@ struct ksmbd_conn {
__le16 signing_algorithm;
bool binding;
atomic_t refcnt;
- atomic_t mux_smb_requests;
};
struct ksmbd_conn_ops {
diff --git a/fs/smb/server/crypto_ctx.c b/fs/smb/server/crypto_ctx.c
index 81488d04199d..ce733dc9a4a3 100644
--- a/fs/smb/server/crypto_ctx.c
+++ b/fs/smb/server/crypto_ctx.c
@@ -89,7 +89,7 @@ static struct shash_desc *alloc_shash_desc(int id)
return NULL;
shash = kzalloc(sizeof(*shash) + crypto_shash_descsize(tfm),
- GFP_KERNEL);
+ KSMBD_DEFAULT_GFP);
if (!shash)
crypto_free_shash(tfm);
else
@@ -133,7 +133,7 @@ static struct ksmbd_crypto_ctx *ksmbd_find_crypto_ctx(void)
ctx_list.avail_ctx++;
spin_unlock(&ctx_list.ctx_lock);
- ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
+ ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), KSMBD_DEFAULT_GFP);
if (!ctx) {
spin_lock(&ctx_list.ctx_lock);
ctx_list.avail_ctx--;
@@ -258,7 +258,7 @@ int ksmbd_crypto_create(void)
init_waitqueue_head(&ctx_list.ctx_wait);
ctx_list.avail_ctx = 1;
- ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), GFP_KERNEL);
+ ctx = kzalloc(sizeof(struct ksmbd_crypto_ctx), KSMBD_DEFAULT_GFP);
if (!ctx)
return -ENOMEM;
list_add(&ctx->list, &ctx_list.idle_ctx);
diff --git a/fs/smb/server/glob.h b/fs/smb/server/glob.h
index d528b20b37a8..4ea187af2348 100644
--- a/fs/smb/server/glob.h
+++ b/fs/smb/server/glob.h
@@ -44,4 +44,6 @@ extern int ksmbd_debug_types;
#define UNICODE_LEN(x) ((x) * 2)
+#define KSMBD_DEFAULT_GFP (GFP_KERNEL | __GFP_RETRY_MAYFAIL)
+
#endif /* __KSMBD_GLOB_H */
diff --git a/fs/smb/server/ksmbd_work.c b/fs/smb/server/ksmbd_work.c
index d7c676c151e2..4af2e6007c29 100644
--- a/fs/smb/server/ksmbd_work.c
+++ b/fs/smb/server/ksmbd_work.c
@@ -18,7 +18,7 @@ static struct workqueue_struct *ksmbd_wq;
struct ksmbd_work *ksmbd_alloc_work_struct(void)
{
- struct ksmbd_work *work = kmem_cache_zalloc(work_cache, GFP_KERNEL);
+ struct ksmbd_work *work = kmem_cache_zalloc(work_cache, KSMBD_DEFAULT_GFP);
if (work) {
work->compound_fid = KSMBD_NO_FID;
@@ -30,7 +30,7 @@ struct ksmbd_work *ksmbd_alloc_work_struct(void)
INIT_LIST_HEAD(&work->aux_read_list);
work->iov_alloc_cnt = 4;
work->iov = kcalloc(work->iov_alloc_cnt, sizeof(struct kvec),
- GFP_KERNEL);
+ KSMBD_DEFAULT_GFP);
if (!work->iov) {
kmem_cache_free(work_cache, work);
work = NULL;
@@ -114,7 +114,7 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
if (aux_size) {
need_iov_cnt++;
- ar = kmalloc(sizeof(struct aux_read), GFP_KERNEL);
+ ar = kmalloc(sizeof(struct aux_read), KSMBD_DEFAULT_GFP);
if (!ar)
return -ENOMEM;
}
@@ -125,7 +125,7 @@ static int __ksmbd_iov_pin_rsp(struct ksmbd_work *work, void *ib, int len,
work->iov_alloc_cnt += 4;
new = krealloc(work->iov,
sizeof(struct kvec) * work->iov_alloc_cnt,
- GFP_KERNEL | __GFP_ZERO);
+ KSMBD_DEFAULT_GFP | __GFP_ZERO);
if (!new) {
kfree(ar);
work->iov_alloc_cnt -= 4;
@@ -169,7 +169,7 @@ int ksmbd_iov_pin_rsp_read(struct ksmbd_work *work, void *ib, int len,
int allocate_interim_rsp_buf(struct ksmbd_work *work)
{
- work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE, GFP_KERNEL);
+ work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE, KSMBD_DEFAULT_GFP);
if (!work->response_buf)
return -ENOMEM;
work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
diff --git a/fs/smb/server/mgmt/ksmbd_ida.c b/fs/smb/server/mgmt/ksmbd_ida.c
index a18e27e9e0cd..0e2ae994ab52 100644
--- a/fs/smb/server/mgmt/ksmbd_ida.c
+++ b/fs/smb/server/mgmt/ksmbd_ida.c
@@ -4,31 +4,32 @@
*/
#include "ksmbd_ida.h"
+#include "../glob.h"
int ksmbd_acquire_smb2_tid(struct ida *ida)
{
- return ida_alloc_range(ida, 1, 0xFFFFFFFE, GFP_KERNEL);
+ return ida_alloc_range(ida, 1, 0xFFFFFFFE, KSMBD_DEFAULT_GFP);
}
int ksmbd_acquire_smb2_uid(struct ida *ida)
{
int id;
- id = ida_alloc_min(ida, 1, GFP_KERNEL);
+ id = ida_alloc_min(ida, 1, KSMBD_DEFAULT_GFP);
if (id == 0xFFFE)
- id = ida_alloc_min(ida, 1, GFP_KERNEL);
+ id = ida_alloc_min(ida, 1, KSMBD_DEFAULT_GFP);
return id;
}
int ksmbd_acquire_async_msg_id(struct ida *ida)
{
- return ida_alloc_min(ida, 1, GFP_KERNEL);
+ return ida_alloc_min(ida, 1, KSMBD_DEFAULT_GFP);
}
int ksmbd_acquire_id(struct ida *ida)
{
- return ida_alloc(ida, GFP_KERNEL);
+ return ida_alloc(ida, KSMBD_DEFAULT_GFP);
}
void ksmbd_release_id(struct ida *ida, int id)
diff --git a/fs/smb/server/mgmt/share_config.c b/fs/smb/server/mgmt/share_config.c
index d8d03070ae44..d3d5f99bdd34 100644
--- a/fs/smb/server/mgmt/share_config.c
+++ b/fs/smb/server/mgmt/share_config.c
@@ -102,11 +102,11 @@ static int parse_veto_list(struct ksmbd_share_config *share,
if (!sz)
break;
- p = kzalloc(sizeof(struct ksmbd_veto_pattern), GFP_KERNEL);
+ p = kzalloc(sizeof(struct ksmbd_veto_pattern), KSMBD_DEFAULT_GFP);
if (!p)
return -ENOMEM;
- p->pattern = kstrdup(veto_list, GFP_KERNEL);
+ p->pattern = kstrdup(veto_list, KSMBD_DEFAULT_GFP);
if (!p->pattern) {
kfree(p);
return -ENOMEM;
@@ -150,14 +150,14 @@ static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work,
goto out;
}
- share = kzalloc(sizeof(struct ksmbd_share_config), GFP_KERNEL);
+ share = kzalloc(sizeof(struct ksmbd_share_config), KSMBD_DEFAULT_GFP);
if (!share)
goto out;
share->flags = resp->flags;
atomic_set(&share->refcount, 1);
INIT_LIST_HEAD(&share->veto_list);
- share->name = kstrdup(name, GFP_KERNEL);
+ share->name = kstrdup(name, KSMBD_DEFAULT_GFP);
if (!test_share_config_flag(share, KSMBD_SHARE_FLAG_PIPE)) {
int path_len = PATH_MAX;
@@ -166,7 +166,7 @@ static struct ksmbd_share_config *share_config_request(struct ksmbd_work *work,
path_len = resp->payload_sz - resp->veto_list_sz;
share->path = kstrndup(ksmbd_share_config_path(resp), path_len,
- GFP_KERNEL);
+ KSMBD_DEFAULT_GFP);
if (share->path) {
share->path_sz = strlen(share->path);
while (share->path_sz > 1 &&
diff --git a/fs/smb/server/mgmt/tree_connect.c b/fs/smb/server/mgmt/tree_connect.c
index 94a52a75014a..ecfc57508671 100644
--- a/fs/smb/server/mgmt/tree_connect.c
+++ b/fs/smb/server/mgmt/tree_connect.c
@@ -31,7 +31,8 @@ ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name)
if (!sc)
return status;
- tree_conn = kzalloc(sizeof(struct ksmbd_tree_connect), GFP_KERNEL);
+ tree_conn = kzalloc(sizeof(struct ksmbd_tree_connect),
+ KSMBD_DEFAULT_GFP);
if (!tree_conn) {
status.ret = -ENOMEM;
goto out_error;
@@ -80,7 +81,7 @@ ksmbd_tree_conn_connect(struct ksmbd_work *work, const char *share_name)
init_waitqueue_head(&tree_conn->refcount_q);
ret = xa_err(xa_store(&sess->tree_conns, tree_conn->id, tree_conn,
- GFP_KERNEL));
+ KSMBD_DEFAULT_GFP));
if (ret) {
status.ret = -ENOMEM;
goto out_error;
diff --git a/fs/smb/server/mgmt/user_config.c b/fs/smb/server/mgmt/user_config.c
index 421a4a95e216..56c9a38ca878 100644
--- a/fs/smb/server/mgmt/user_config.c
+++ b/fs/smb/server/mgmt/user_config.c
@@ -36,16 +36,16 @@ struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp,
{
struct ksmbd_user *user;
- user = kmalloc(sizeof(struct ksmbd_user), GFP_KERNEL);
+ user = kmalloc(sizeof(struct ksmbd_user), KSMBD_DEFAULT_GFP);
if (!user)
return NULL;
- user->name = kstrdup(resp->account, GFP_KERNEL);
+ user->name = kstrdup(resp->account, KSMBD_DEFAULT_GFP);
user->flags = resp->status;
user->gid = resp->gid;
user->uid = resp->uid;
user->passkey_sz = resp->hash_sz;
- user->passkey = kmalloc(resp->hash_sz, GFP_KERNEL);
+ user->passkey = kmalloc(resp->hash_sz, KSMBD_DEFAULT_GFP);
if (user->passkey)
memcpy(user->passkey, resp->hash, resp->hash_sz);
@@ -64,7 +64,7 @@ struct ksmbd_user *ksmbd_alloc_user(struct ksmbd_login_response *resp,
user->sgid = kmemdup(resp_ext->____payload,
resp_ext->ngroups * sizeof(gid_t),
- GFP_KERNEL);
+ KSMBD_DEFAULT_GFP);
if (!user->sgid)
goto err_free;
diff --git a/fs/smb/server/mgmt/user_session.c b/fs/smb/server/mgmt/user_session.c
index ad02fe555fda..71c6939dfbf1 100644
--- a/fs/smb/server/mgmt/user_session.c
+++ b/fs/smb/server/mgmt/user_session.c
@@ -98,7 +98,7 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
if (!method)
return -EINVAL;
- entry = kzalloc(sizeof(struct ksmbd_session_rpc), GFP_KERNEL);
+ entry = kzalloc(sizeof(struct ksmbd_session_rpc), KSMBD_DEFAULT_GFP);
if (!entry)
return -ENOMEM;
@@ -106,7 +106,7 @@ int ksmbd_session_rpc_open(struct ksmbd_session *sess, char *rpc_name)
entry->id = ksmbd_ipc_id_alloc();
if (entry->id < 0)
goto free_entry;
- old = xa_store(&sess->rpc_handle_list, entry->id, entry, GFP_KERNEL);
+ old = xa_store(&sess->rpc_handle_list, entry->id, entry, KSMBD_DEFAULT_GFP);
if (xa_is_err(old))
goto free_id;
@@ -201,7 +201,7 @@ int ksmbd_session_register(struct ksmbd_conn *conn,
sess->dialect = conn->dialect;
memcpy(sess->ClientGUID, conn->ClientGUID, SMB2_CLIENT_GUID_SIZE);
ksmbd_expire_session(conn);
- return xa_err(xa_store(&conn->sessions, sess->id, sess, GFP_KERNEL));
+ return xa_err(xa_store(&conn->sessions, sess->id, sess, KSMBD_DEFAULT_GFP));
}
static int ksmbd_chann_del(struct ksmbd_conn *conn, struct ksmbd_session *sess)
@@ -263,8 +263,10 @@ struct ksmbd_session *ksmbd_session_lookup(struct ksmbd_conn *conn,
down_read(&conn->session_lock);
sess = xa_load(&conn->sessions, id);
- if (sess)
+ if (sess) {
sess->last_active = jiffies;
+ ksmbd_user_session_get(sess);
+ }
up_read(&conn->session_lock);
return sess;
}
@@ -275,6 +277,8 @@ struct ksmbd_session *ksmbd_session_lookup_slowpath(unsigned long long id)
down_read(&sessions_table_lock);
sess = __session_lookup(id);
+ if (sess)
+ ksmbd_user_session_get(sess);
up_read(&sessions_table_lock);
return sess;
@@ -314,7 +318,7 @@ struct preauth_session *ksmbd_preauth_session_alloc(struct ksmbd_conn *conn,
{
struct preauth_session *sess;
- sess = kmalloc(sizeof(struct preauth_session), GFP_KERNEL);
+ sess = kmalloc(sizeof(struct preauth_session), KSMBD_DEFAULT_GFP);
if (!sess)
return NULL;
@@ -398,7 +402,7 @@ static struct ksmbd_session *__session_create(int protocol)
if (protocol != CIFDS_SESSION_FLAG_SMB2)
return NULL;
- sess = kzalloc(sizeof(struct ksmbd_session), GFP_KERNEL);
+ sess = kzalloc(sizeof(struct ksmbd_session), KSMBD_DEFAULT_GFP);
if (!sess)
return NULL;
diff --git a/fs/smb/server/misc.c b/fs/smb/server/misc.c
index 1a5faa6f6e7b..cb2a11ffb23f 100644
--- a/fs/smb/server/misc.c
+++ b/fs/smb/server/misc.c
@@ -165,7 +165,7 @@ char *convert_to_nt_pathname(struct ksmbd_share_config *share,
char *pathname, *ab_pathname, *nt_pathname;
int share_path_len = share->path_sz;
- pathname = kmalloc(PATH_MAX, GFP_KERNEL);
+ pathname = kmalloc(PATH_MAX, KSMBD_DEFAULT_GFP);
if (!pathname)
return ERR_PTR(-EACCES);
@@ -180,7 +180,8 @@ char *convert_to_nt_pathname(struct ksmbd_share_config *share,
goto free_pathname;
}
- nt_pathname = kzalloc(strlen(&ab_pathname[share_path_len]) + 2, GFP_KERNEL);
+ nt_pathname = kzalloc(strlen(&ab_pathname[share_path_len]) + 2,
+ KSMBD_DEFAULT_GFP);
if (!nt_pathname) {
nt_pathname = ERR_PTR(-ENOMEM);
goto free_pathname;
@@ -232,7 +233,7 @@ char *ksmbd_casefold_sharename(struct unicode_map *um, const char *name)
char *cf_name;
int cf_len;
- cf_name = kzalloc(KSMBD_REQ_MAX_SHARE_NAME, GFP_KERNEL);
+ cf_name = kzalloc(KSMBD_REQ_MAX_SHARE_NAME, KSMBD_DEFAULT_GFP);
if (!cf_name)
return ERR_PTR(-ENOMEM);
@@ -294,7 +295,7 @@ char *convert_to_unix_name(struct ksmbd_share_config *share, const char *name)
path_len = share->path_sz;
name_len = strlen(name);
- new_name = kmalloc(path_len + name_len + 2, GFP_KERNEL);
+ new_name = kmalloc(path_len + name_len + 2, KSMBD_DEFAULT_GFP);
if (!new_name)
return new_name;
@@ -320,7 +321,7 @@ char *ksmbd_convert_dir_info_name(struct ksmbd_dir_info *d_info,
if (!sz)
return NULL;
- conv = kmalloc(sz, GFP_KERNEL);
+ conv = kmalloc(sz, KSMBD_DEFAULT_GFP);
if (!conv)
return NULL;
diff --git a/fs/smb/server/ndr.c b/fs/smb/server/ndr.c
index 3507d8f89074..58d71560f626 100644
--- a/fs/smb/server/ndr.c
+++ b/fs/smb/server/ndr.c
@@ -18,7 +18,7 @@ static int try_to_realloc_ndr_blob(struct ndr *n, size_t sz)
{
char *data;
- data = krealloc(n->data, n->offset + sz + 1024, GFP_KERNEL);
+ data = krealloc(n->data, n->offset + sz + 1024, KSMBD_DEFAULT_GFP);
if (!data)
return -ENOMEM;
@@ -174,7 +174,7 @@ int ndr_encode_dos_attr(struct ndr *n, struct xattr_dos_attrib *da)
n->offset = 0;
n->length = 1024;
- n->data = kzalloc(n->length, GFP_KERNEL);
+ n->data = kzalloc(n->length, KSMBD_DEFAULT_GFP);
if (!n->data)
return -ENOMEM;
@@ -350,7 +350,7 @@ int ndr_encode_posix_acl(struct ndr *n,
n->offset = 0;
n->length = 1024;
- n->data = kzalloc(n->length, GFP_KERNEL);
+ n->data = kzalloc(n->length, KSMBD_DEFAULT_GFP);
if (!n->data)
return -ENOMEM;
@@ -401,7 +401,7 @@ int ndr_encode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
n->offset = 0;
n->length = 2048;
- n->data = kzalloc(n->length, GFP_KERNEL);
+ n->data = kzalloc(n->length, KSMBD_DEFAULT_GFP);
if (!n->data)
return -ENOMEM;
@@ -505,7 +505,7 @@ int ndr_decode_v4_ntacl(struct ndr *n, struct xattr_ntacl *acl)
return ret;
acl->sd_size = n->length - n->offset;
- acl->sd_buf = kzalloc(acl->sd_size, GFP_KERNEL);
+ acl->sd_buf = kzalloc(acl->sd_size, KSMBD_DEFAULT_GFP);
if (!acl->sd_buf)
return -ENOMEM;
diff --git a/fs/smb/server/oplock.c b/fs/smb/server/oplock.c
index 4142c7ad5fa9..3a3fe4afbdf0 100644
--- a/fs/smb/server/oplock.c
+++ b/fs/smb/server/oplock.c
@@ -34,7 +34,7 @@ static struct oplock_info *alloc_opinfo(struct ksmbd_work *work,
struct ksmbd_session *sess = work->sess;
struct oplock_info *opinfo;
- opinfo = kzalloc(sizeof(struct oplock_info), GFP_KERNEL);
+ opinfo = kzalloc(sizeof(struct oplock_info), KSMBD_DEFAULT_GFP);
if (!opinfo)
return NULL;
@@ -94,7 +94,7 @@ static int alloc_lease(struct oplock_info *opinfo, struct lease_ctx_info *lctx)
{
struct lease *lease;
- lease = kmalloc(sizeof(struct lease), GFP_KERNEL);
+ lease = kmalloc(sizeof(struct lease), KSMBD_DEFAULT_GFP);
if (!lease)
return -ENOMEM;
@@ -709,7 +709,7 @@ static int smb2_oplock_break_noti(struct oplock_info *opinfo)
if (!work)
return -ENOMEM;
- br_info = kmalloc(sizeof(struct oplock_break_info), GFP_KERNEL);
+ br_info = kmalloc(sizeof(struct oplock_break_info), KSMBD_DEFAULT_GFP);
if (!br_info) {
ksmbd_free_work_struct(work);
return -ENOMEM;
@@ -812,7 +812,7 @@ static int smb2_lease_break_noti(struct oplock_info *opinfo)
if (!work)
return -ENOMEM;
- br_info = kmalloc(sizeof(struct lease_break_info), GFP_KERNEL);
+ br_info = kmalloc(sizeof(struct lease_break_info), KSMBD_DEFAULT_GFP);
if (!br_info) {
ksmbd_free_work_struct(work);
return -ENOMEM;
@@ -1057,7 +1057,7 @@ static int add_lease_global_list(struct oplock_info *opinfo)
}
read_unlock(&lease_list_lock);
- lb = kmalloc(sizeof(struct lease_table), GFP_KERNEL);
+ lb = kmalloc(sizeof(struct lease_table), KSMBD_DEFAULT_GFP);
if (!lb)
return -ENOMEM;
@@ -1499,7 +1499,7 @@ struct lease_ctx_info *parse_lease_state(void *open_req)
if (IS_ERR_OR_NULL(cc))
return NULL;
- lreq = kzalloc(sizeof(struct lease_ctx_info), GFP_KERNEL);
+ lreq = kzalloc(sizeof(struct lease_ctx_info), KSMBD_DEFAULT_GFP);
if (!lreq)
return NULL;
diff --git a/fs/smb/server/server.c b/fs/smb/server/server.c
index e6cfedba9992..601e7fcbcf1e 100644
--- a/fs/smb/server/server.c
+++ b/fs/smb/server/server.c
@@ -47,7 +47,7 @@ static int ___server_conf_set(int idx, char *val)
return -EINVAL;
kfree(server_conf.conf[idx]);
- server_conf.conf[idx] = kstrdup(val, GFP_KERNEL);
+ server_conf.conf[idx] = kstrdup(val, KSMBD_DEFAULT_GFP);
if (!server_conf.conf[idx])
return -ENOMEM;
return 0;
@@ -241,14 +241,14 @@ send:
if (work->tcon)
ksmbd_tree_connect_put(work->tcon);
smb3_preauth_hash_rsp(work);
- if (work->sess)
- ksmbd_user_session_put(work->sess);
if (work->sess && work->sess->enc && work->encrypted &&
conn->ops->encrypt_resp) {
rc = conn->ops->encrypt_resp(work);
if (rc < 0)
conn->ops->set_rsp_status(work, STATUS_DATA_ERROR);
}
+ if (work->sess)
+ ksmbd_user_session_put(work->sess);
ksmbd_conn_write(work);
}
@@ -270,14 +270,17 @@ static void handle_ksmbd_work(struct work_struct *wk)
ksmbd_conn_try_dequeue_request(work);
ksmbd_free_work_struct(work);
- atomic_dec(&conn->mux_smb_requests);
/*
* Checking waitqueue to dropping pending requests on
* disconnection. waitqueue_active is safe because it
* uses atomic operation for condition.
*/
+ atomic_inc(&conn->refcnt);
if (!atomic_dec_return(&conn->r_count) && waitqueue_active(&conn->r_count_q))
wake_up(&conn->r_count_q);
+
+ if (atomic_dec_and_test(&conn->refcnt))
+ kfree(conn);
}
/**
@@ -296,11 +299,6 @@ static int queue_ksmbd_work(struct ksmbd_conn *conn)
if (err)
return 0;
- if (atomic_inc_return(&conn->mux_smb_requests) >= conn->vals->max_credits) {
- atomic_dec_return(&conn->mux_smb_requests);
- return -ENOSPC;
- }
-
work = ksmbd_alloc_work_struct();
if (!work) {
pr_err("allocation for work failed\n");
@@ -363,6 +361,7 @@ static int server_conf_init(void)
server_conf.auth_mechs |= KSMBD_AUTH_KRB5 |
KSMBD_AUTH_MSKRB5;
#endif
+ server_conf.max_inflight_req = SMB2_MAX_CREDITS;
return 0;
}
@@ -415,7 +414,7 @@ static int __queue_ctrl_work(int type)
{
struct server_ctrl_struct *ctrl;
- ctrl = kmalloc(sizeof(struct server_ctrl_struct), GFP_KERNEL);
+ ctrl = kmalloc(sizeof(struct server_ctrl_struct), KSMBD_DEFAULT_GFP);
if (!ctrl)
return -ENOMEM;
diff --git a/fs/smb/server/server.h b/fs/smb/server/server.h
index 4fc529335271..94187628ff08 100644
--- a/fs/smb/server/server.h
+++ b/fs/smb/server/server.h
@@ -42,6 +42,7 @@ struct ksmbd_server_config {
struct smb_sid domain_sid;
unsigned int auth_mechs;
unsigned int max_connections;
+ unsigned int max_inflight_req;
char *conf[SERVER_CONF_WORK_GROUP + 1];
struct task_struct *dh_task;
diff --git a/fs/smb/server/smb2pdu.c b/fs/smb/server/smb2pdu.c
index 599118aed205..23e21845f928 100644
--- a/fs/smb/server/smb2pdu.c
+++ b/fs/smb/server/smb2pdu.c
@@ -67,8 +67,10 @@ static inline bool check_session_id(struct ksmbd_conn *conn, u64 id)
return false;
sess = ksmbd_session_lookup_all(conn, id);
- if (sess)
+ if (sess) {
+ ksmbd_user_session_put(sess);
return true;
+ }
pr_err("Invalid user session id: %llu\n", id);
return false;
}
@@ -551,7 +553,7 @@ int smb2_allocate_rsp_buf(struct ksmbd_work *work)
if (le32_to_cpu(hdr->NextCommand) > 0)
sz = large_sz;
- work->response_buf = kvzalloc(sz, GFP_KERNEL);
+ work->response_buf = kvzalloc(sz, KSMBD_DEFAULT_GFP);
if (!work->response_buf)
return -ENOMEM;
@@ -605,10 +607,8 @@ int smb2_check_user_session(struct ksmbd_work *work)
/* Check for validity of user session */
work->sess = ksmbd_session_lookup_all(conn, sess_id);
- if (work->sess) {
- ksmbd_user_session_get(work->sess);
+ if (work->sess)
return 1;
- }
ksmbd_debug(SMB, "Invalid user session, Uid %llu\n", sess_id);
return -ENOENT;
}
@@ -1097,6 +1097,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
return rc;
}
+ ksmbd_conn_lock(conn);
smb2_buf_len = get_rfc1002_len(work->request_buf);
smb2_neg_size = offsetof(struct smb2_negotiate_req, Dialects);
if (smb2_neg_size > smb2_buf_len) {
@@ -1147,7 +1148,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
case SMB311_PROT_ID:
conn->preauth_info =
kzalloc(sizeof(struct preauth_integrity_info),
- GFP_KERNEL);
+ KSMBD_DEFAULT_GFP);
if (!conn->preauth_info) {
rc = -ENOMEM;
rsp->hdr.Status = STATUS_INVALID_PARAMETER;
@@ -1247,6 +1248,7 @@ int smb2_handle_negotiate(struct ksmbd_work *work)
ksmbd_conn_set_need_negotiate(conn);
err_out:
+ ksmbd_conn_unlock(conn);
if (rc)
rsp->hdr.Status = STATUS_INSUFFICIENT_RESOURCES;
@@ -1266,7 +1268,7 @@ static int alloc_preauth_hash(struct ksmbd_session *sess,
return 0;
sess->Preauth_HashValue = kmemdup(conn->preauth_info->Preauth_HashValue,
- PREAUTH_HASHVALUE_SIZE, GFP_KERNEL);
+ PREAUTH_HASHVALUE_SIZE, KSMBD_DEFAULT_GFP);
if (!sess->Preauth_HashValue)
return -ENOMEM;
@@ -1352,7 +1354,7 @@ static int ntlm_negotiate(struct ksmbd_work *work,
sz = sizeof(struct challenge_message);
sz += (strlen(ksmbd_netbios_name()) * 2 + 1 + 4) * 6;
- neg_blob = kzalloc(sz, GFP_KERNEL);
+ neg_blob = kzalloc(sz, KSMBD_DEFAULT_GFP);
if (!neg_blob)
return -ENOMEM;
@@ -1543,12 +1545,12 @@ binding_session:
if (conn->dialect >= SMB30_PROT_ID) {
chann = lookup_chann_list(sess, conn);
if (!chann) {
- chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
+ chann = kmalloc(sizeof(struct channel), KSMBD_DEFAULT_GFP);
if (!chann)
return -ENOMEM;
chann->conn = conn;
- xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL);
+ xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP);
}
}
@@ -1624,12 +1626,12 @@ static int krb5_authenticate(struct ksmbd_work *work,
if (conn->dialect >= SMB30_PROT_ID) {
chann = lookup_chann_list(sess, conn);
if (!chann) {
- chann = kmalloc(sizeof(struct channel), GFP_KERNEL);
+ chann = kmalloc(sizeof(struct channel), KSMBD_DEFAULT_GFP);
if (!chann)
return -ENOMEM;
chann->conn = conn;
- xa_store(&sess->ksmbd_chann_list, (long)conn, chann, GFP_KERNEL);
+ xa_store(&sess->ksmbd_chann_list, (long)conn, chann, KSMBD_DEFAULT_GFP);
}
}
@@ -1666,7 +1668,7 @@ int smb2_sess_setup(struct ksmbd_work *work)
unsigned int negblob_len, negblob_off;
int rc = 0;
- ksmbd_debug(SMB, "Received request for session setup\n");
+ ksmbd_debug(SMB, "Received smb2 session setup request\n");
WORK_BUFFERS(work, req, rsp);
@@ -1701,29 +1703,35 @@ int smb2_sess_setup(struct ksmbd_work *work)
if (conn->dialect != sess->dialect) {
rc = -EINVAL;
+ ksmbd_user_session_put(sess);
goto out_err;
}
if (!(req->hdr.Flags & SMB2_FLAGS_SIGNED)) {
rc = -EINVAL;
+ ksmbd_user_session_put(sess);
goto out_err;
}
if (strncmp(conn->ClientGUID, sess->ClientGUID,
SMB2_CLIENT_GUID_SIZE)) {
rc = -ENOENT;
+ ksmbd_user_session_put(sess);
goto out_err;
}
if (sess->state == SMB2_SESSION_IN_PROGRESS) {
rc = -EACCES;
+ ksmbd_user_session_put(sess);
goto out_err;
}
if (sess->state == SMB2_SESSION_EXPIRED) {
rc = -EFAULT;
+ ksmbd_user_session_put(sess);
goto out_err;
}
+ ksmbd_user_session_put(sess);
if (ksmbd_conn_need_reconnect(conn)) {
rc = -EFAULT;
@@ -1731,7 +1739,8 @@ int smb2_sess_setup(struct ksmbd_work *work)
goto out_err;
}
- if (ksmbd_session_lookup(conn, sess_id)) {
+ sess = ksmbd_session_lookup(conn, sess_id);
+ if (!sess) {
rc = -EACCES;
goto out_err;
}
@@ -1742,7 +1751,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
}
conn->binding = true;
- ksmbd_user_session_get(sess);
} else if ((conn->dialect < SMB30_PROT_ID ||
server_conf.flags & KSMBD_GLOBAL_FLAG_SMB3_MULTICHANNEL) &&
(req->Flags & SMB2_SESSION_REQ_FLAG_BINDING)) {
@@ -1769,7 +1777,6 @@ int smb2_sess_setup(struct ksmbd_work *work)
}
conn->binding = false;
- ksmbd_user_session_get(sess);
}
work->sess = sess;
@@ -1940,6 +1947,8 @@ int smb2_tree_connect(struct ksmbd_work *work)
struct ksmbd_share_config *share = NULL;
int rc = -EINVAL;
+ ksmbd_debug(SMB, "Received smb2 tree connect request\n");
+
WORK_BUFFERS(work, req, rsp);
treename = smb_strndup_from_utf16((char *)req + le16_to_cpu(req->PathOffset),
@@ -2136,9 +2145,9 @@ int smb2_tree_disconnect(struct ksmbd_work *work)
struct ksmbd_tree_connect *tcon = work->tcon;
int err;
- WORK_BUFFERS(work, req, rsp);
+ ksmbd_debug(SMB, "Received smb2 tree disconnect request\n");
- ksmbd_debug(SMB, "request\n");
+ WORK_BUFFERS(work, req, rsp);
if (!tcon) {
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
@@ -2195,15 +2204,15 @@ err_out:
int smb2_session_logoff(struct ksmbd_work *work)
{
struct ksmbd_conn *conn = work->conn;
+ struct ksmbd_session *sess = work->sess;
struct smb2_logoff_req *req;
struct smb2_logoff_rsp *rsp;
- struct ksmbd_session *sess;
u64 sess_id;
int err;
WORK_BUFFERS(work, req, rsp);
- ksmbd_debug(SMB, "request\n");
+ ksmbd_debug(SMB, "Received smb2 session logoff request\n");
ksmbd_conn_lock(conn);
if (!ksmbd_conn_good(conn)) {
@@ -2219,11 +2228,6 @@ int smb2_session_logoff(struct ksmbd_work *work)
ksmbd_close_session_fds(work);
ksmbd_conn_wait_idle(conn);
- /*
- * Re-lookup session to validate if session is deleted
- * while waiting request complete
- */
- sess = ksmbd_session_lookup_all(conn, sess_id);
if (ksmbd_tree_conn_session_logoff(sess)) {
ksmbd_debug(SMB, "Invalid tid %d\n", req->hdr.Id.SyncId.TreeId);
rsp->hdr.Status = STATUS_NETWORK_NAME_DELETED;
@@ -2346,7 +2350,7 @@ static int smb2_set_ea(struct smb2_ea_info *eabuf, unsigned int buf_len,
le16_to_cpu(eabuf->EaValueLength))
return -EINVAL;
- attr_name = kmalloc(XATTR_NAME_MAX + 1, GFP_KERNEL);
+ attr_name = kmalloc(XATTR_NAME_MAX + 1, KSMBD_DEFAULT_GFP);
if (!attr_name)
return -ENOMEM;
@@ -2849,6 +2853,8 @@ int smb2_open(struct ksmbd_work *work)
__le32 daccess, maximal_access = 0;
int iov_len = 0;
+ ksmbd_debug(SMB, "Received smb2 create request\n");
+
WORK_BUFFERS(work, req, rsp);
if (req->hdr.NextCommand && !work->next_smb2_rcv_hdr_off &&
@@ -2897,7 +2903,7 @@ int smb2_open(struct ksmbd_work *work)
goto err_out2;
}
} else {
- name = kstrdup("", GFP_KERNEL);
+ name = kstrdup("", KSMBD_DEFAULT_GFP);
if (!name) {
rc = -ENOMEM;
goto err_out2;
@@ -3338,7 +3344,7 @@ int smb2_open(struct ksmbd_work *work)
sizeof(struct smb_sid) * 3 +
sizeof(struct smb_acl) +
sizeof(struct smb_ace) * ace_num * 2,
- GFP_KERNEL);
+ KSMBD_DEFAULT_GFP);
if (!pntsd) {
posix_acl_release(fattr.cf_acls);
posix_acl_release(fattr.cf_dacls);
@@ -4224,6 +4230,7 @@ static bool __query_dir(struct dir_context *ctx, const char *name, int namlen,
/* dot and dotdot entries are already reserved */
if (!strcmp(".", name) || !strcmp("..", name))
return true;
+ d_info->num_scan++;
if (ksmbd_share_veto_filename(priv->work->tcon->share_conf, name))
return true;
if (!match_pattern(name, namlen, priv->search_pattern))
@@ -4296,6 +4303,8 @@ int smb2_query_dir(struct ksmbd_work *work)
int buffer_sz;
struct smb2_query_dir_private query_dir_private = {NULL, };
+ ksmbd_debug(SMB, "Received smb2 query directory request\n");
+
WORK_BUFFERS(work, req, rsp);
if (ksmbd_override_fsids(work)) {
@@ -4384,9 +4393,18 @@ int smb2_query_dir(struct ksmbd_work *work)
query_dir_private.info_level = req->FileInformationClass;
dir_fp->readdir_data.private = &query_dir_private;
set_ctx_actor(&dir_fp->readdir_data.ctx, __query_dir);
-
+again:
+ d_info.num_scan = 0;
rc = iterate_dir(dir_fp->filp, &dir_fp->readdir_data.ctx);
/*
+ * num_entry can be 0 if the directory iteration stops before reaching
+ * the end of the directory and no file is matched with the search
+ * pattern.
+ */
+ if (rc >= 0 && !d_info.num_entry && d_info.num_scan &&
+ d_info.out_buf_len > 0)
+ goto again;
+ /*
* req->OutputBufferLength is too small to contain even one entry.
* In this case, it immediately returns OutputBufferLength 0 to client.
*/
@@ -4946,7 +4964,7 @@ static int get_file_stream_info(struct ksmbd_work *work,
/* plus : size */
streamlen += 1;
- stream_buf = kmalloc(streamlen + 1, GFP_KERNEL);
+ stream_buf = kmalloc(streamlen + 1, KSMBD_DEFAULT_GFP);
if (!stream_buf)
break;
@@ -5602,9 +5620,9 @@ int smb2_query_info(struct ksmbd_work *work)
struct smb2_query_info_rsp *rsp;
int rc = 0;
- WORK_BUFFERS(work, req, rsp);
+ ksmbd_debug(SMB, "Received request smb2 query info request\n");
- ksmbd_debug(SMB, "GOT query info request\n");
+ WORK_BUFFERS(work, req, rsp);
if (ksmbd_override_fsids(work)) {
rc = -ENOMEM;
@@ -5709,6 +5727,8 @@ int smb2_close(struct ksmbd_work *work)
u64 time;
int err = 0;
+ ksmbd_debug(SMB, "Received smb2 close request\n");
+
WORK_BUFFERS(work, req, rsp);
if (test_share_config_flag(work->tcon->share_conf,
@@ -5825,6 +5845,8 @@ int smb2_echo(struct ksmbd_work *work)
{
struct smb2_echo_rsp *rsp = smb2_get_msg(work->response_buf);
+ ksmbd_debug(SMB, "Received smb2 echo request\n");
+
if (work->next_smb2_rcv_hdr_off)
rsp = ksmbd_resp_buf_next(work);
@@ -5921,7 +5943,7 @@ static int smb2_create_link(struct ksmbd_work *work,
return -EINVAL;
ksmbd_debug(SMB, "setting FILE_LINK_INFORMATION\n");
- pathname = kmalloc(PATH_MAX, GFP_KERNEL);
+ pathname = kmalloc(PATH_MAX, KSMBD_DEFAULT_GFP);
if (!pathname)
return -ENOMEM;
@@ -6006,15 +6028,13 @@ static int set_file_basic_info(struct ksmbd_file *fp,
attrs.ia_valid |= (ATTR_ATIME | ATTR_ATIME_SET);
}
- attrs.ia_valid |= ATTR_CTIME;
if (file_info->ChangeTime)
- attrs.ia_ctime = ksmbd_NTtimeToUnix(file_info->ChangeTime);
- else
- attrs.ia_ctime = inode_get_ctime(inode);
+ inode_set_ctime_to_ts(inode,
+ ksmbd_NTtimeToUnix(file_info->ChangeTime));
if (file_info->LastWriteTime) {
attrs.ia_mtime = ksmbd_NTtimeToUnix(file_info->LastWriteTime);
- attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET);
+ attrs.ia_valid |= (ATTR_MTIME | ATTR_MTIME_SET | ATTR_CTIME);
}
if (file_info->Attributes) {
@@ -6056,8 +6076,6 @@ static int set_file_basic_info(struct ksmbd_file *fp,
return -EACCES;
inode_lock(inode);
- inode_set_ctime_to_ts(inode, attrs.ia_ctime);
- attrs.ia_valid &= ~ATTR_CTIME;
rc = notify_change(idmap, dentry, &attrs, NULL);
inode_unlock(inode);
}
@@ -6365,7 +6383,7 @@ int smb2_set_info(struct ksmbd_work *work)
int rc = 0;
unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
- ksmbd_debug(SMB, "Received set info request\n");
+ ksmbd_debug(SMB, "Received smb2 set info request\n");
if (work->next_smb2_rcv_hdr_off) {
req = ksmbd_req_buf_next(work);
@@ -6485,7 +6503,7 @@ static noinline int smb2_read_pipe(struct ksmbd_work *work)
}
aux_payload_buf =
- kvmalloc(rpc_resp->payload_sz, GFP_KERNEL);
+ kvmalloc(rpc_resp->payload_sz, KSMBD_DEFAULT_GFP);
if (!aux_payload_buf) {
err = -ENOMEM;
goto out;
@@ -6591,6 +6609,8 @@ int smb2_read(struct ksmbd_work *work)
unsigned int id = KSMBD_NO_FID, pid = KSMBD_NO_FID;
void *aux_payload_buf;
+ ksmbd_debug(SMB, "Received smb2 read request\n");
+
if (test_share_config_flag(work->tcon->share_conf,
KSMBD_SHARE_FLAG_PIPE)) {
ksmbd_debug(SMB, "IPC pipe read request\n");
@@ -6651,6 +6671,10 @@ int smb2_read(struct ksmbd_work *work)
}
offset = le64_to_cpu(req->Offset);
+ if (offset < 0) {
+ err = -EINVAL;
+ goto out;
+ }
length = le32_to_cpu(req->Length);
mincount = le32_to_cpu(req->MinimumCount);
@@ -6664,7 +6688,7 @@ int smb2_read(struct ksmbd_work *work)
ksmbd_debug(SMB, "filename %pD, offset %lld, len %zu\n",
fp->filp, offset, length);
- aux_payload_buf = kvzalloc(length, GFP_KERNEL);
+ aux_payload_buf = kvzalloc(ALIGN(length, 8), KSMBD_DEFAULT_GFP);
if (!aux_payload_buf) {
err = -ENOMEM;
goto out;
@@ -6816,7 +6840,7 @@ static ssize_t smb2_write_rdma_channel(struct ksmbd_work *work,
int ret;
ssize_t nbytes;
- data_buf = kvzalloc(length, GFP_KERNEL);
+ data_buf = kvzalloc(length, KSMBD_DEFAULT_GFP);
if (!data_buf)
return -ENOMEM;
@@ -6856,6 +6880,8 @@ int smb2_write(struct ksmbd_work *work)
int err = 0;
unsigned int max_write_size = work->conn->vals->max_write_size;
+ ksmbd_debug(SMB, "Received smb2 write request\n");
+
WORK_BUFFERS(work, req, rsp);
if (test_share_config_flag(work->tcon->share_conf, KSMBD_SHARE_FLAG_PIPE)) {
@@ -6864,6 +6890,8 @@ int smb2_write(struct ksmbd_work *work)
}
offset = le64_to_cpu(req->Offset);
+ if (offset < 0)
+ return -EINVAL;
length = le32_to_cpu(req->Length);
if (req->Channel == SMB2_CHANNEL_RDMA_V1 ||
@@ -6994,7 +7022,7 @@ int smb2_flush(struct ksmbd_work *work)
WORK_BUFFERS(work, req, rsp);
- ksmbd_debug(SMB, "SMB2_FLUSH called for fid %llu\n", req->VolatileFileId);
+ ksmbd_debug(SMB, "Received smb2 flush request(fid : %llu)\n", req->VolatileFileId);
err = ksmbd_vfs_fsync(work, req->VolatileFileId, req->PersistentFileId);
if (err)
@@ -7145,7 +7173,7 @@ static struct ksmbd_lock *smb2_lock_init(struct file_lock *flock,
{
struct ksmbd_lock *lock;
- lock = kzalloc(sizeof(struct ksmbd_lock), GFP_KERNEL);
+ lock = kzalloc(sizeof(struct ksmbd_lock), KSMBD_DEFAULT_GFP);
if (!lock)
return NULL;
@@ -7206,7 +7234,7 @@ int smb2_lock(struct ksmbd_work *work)
WORK_BUFFERS(work, req, rsp);
- ksmbd_debug(SMB, "Received lock request\n");
+ ksmbd_debug(SMB, "Received smb2 lock request\n");
fp = ksmbd_lookup_fd_slow(work, req->VolatileFileId, req->PersistentFileId);
if (!fp) {
ksmbd_debug(SMB, "Invalid file id for lock : %llu\n", req->VolatileFileId);
@@ -7413,7 +7441,7 @@ skip:
"would have to wait for getting lock\n");
list_add(&smb_lock->llist, &rollback_list);
- argv = kmalloc(sizeof(void *), GFP_KERNEL);
+ argv = kmalloc(sizeof(void *), KSMBD_DEFAULT_GFP);
if (!argv) {
err = -ENOMEM;
goto out;
@@ -7973,6 +8001,8 @@ int smb2_ioctl(struct ksmbd_work *work)
int ret = 0;
char *buffer;
+ ksmbd_debug(SMB, "Received smb2 ioctl request\n");
+
if (work->next_smb2_rcv_hdr_off) {
req = ksmbd_req_buf_next(work);
rsp = ksmbd_resp_buf_next(work);
@@ -8599,6 +8629,8 @@ int smb2_oplock_break(struct ksmbd_work *work)
struct smb2_oplock_break *req;
struct smb2_oplock_break *rsp;
+ ksmbd_debug(SMB, "Received smb2 oplock break acknowledgment request\n");
+
WORK_BUFFERS(work, req, rsp);
switch (le16_to_cpu(req->StructureSize)) {
@@ -8629,6 +8661,8 @@ int smb2_notify(struct ksmbd_work *work)
struct smb2_change_notify_req *req;
struct smb2_change_notify_rsp *rsp;
+ ksmbd_debug(SMB, "Received smb2 notify\n");
+
WORK_BUFFERS(work, req, rsp);
if (work->next_smb2_rcv_hdr_off && req->hdr.NextCommand) {
@@ -8907,7 +8941,7 @@ int smb3_encrypt_resp(struct ksmbd_work *work)
int rc = -ENOMEM;
void *tr_buf;
- tr_buf = kzalloc(sizeof(struct smb2_transform_hdr) + 4, GFP_KERNEL);
+ tr_buf = kzalloc(sizeof(struct smb2_transform_hdr) + 4, KSMBD_DEFAULT_GFP);
if (!tr_buf)
return rc;
@@ -8956,6 +8990,7 @@ int smb3_decrypt_req(struct ksmbd_work *work)
le64_to_cpu(tr_hdr->SessionId));
return -ECONNABORTED;
}
+ ksmbd_user_session_put(sess);
iov[0].iov_base = buf;
iov[0].iov_len = sizeof(struct smb2_transform_hdr) + 4;
diff --git a/fs/smb/server/smb_common.c b/fs/smb/server/smb_common.c
index 75b4eb856d32..f51cd0816b1a 100644
--- a/fs/smb/server/smb_common.c
+++ b/fs/smb/server/smb_common.c
@@ -18,8 +18,8 @@
#include "mgmt/share_config.h"
/*for shortname implementation */
-static const char basechars[43] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
-#define MANGLE_BASE (sizeof(basechars) / sizeof(char) - 1)
+static const char *basechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ_-!@#$%";
+#define MANGLE_BASE (strlen(basechars) - 1)
#define MAGIC_CHAR '~'
#define PERIOD '.'
#define mangle(V) ((char)(basechars[(V) % MANGLE_BASE]))
@@ -358,7 +358,7 @@ static int smb1_check_user_session(struct ksmbd_work *work)
static int smb1_allocate_rsp_buf(struct ksmbd_work *work)
{
work->response_buf = kzalloc(MAX_CIFS_SMALL_BUFFER_SIZE,
- GFP_KERNEL);
+ KSMBD_DEFAULT_GFP);
work->response_sz = MAX_CIFS_SMALL_BUFFER_SIZE;
if (!work->response_buf) {
@@ -576,7 +576,7 @@ static int smb_handle_negotiate(struct ksmbd_work *work)
ksmbd_debug(SMB, "Unsupported SMB1 protocol\n");
- if (ksmbd_iov_pin_rsp(work, (void *)neg_rsp,
+ if (ksmbd_iov_pin_rsp(work, (void *)neg_rsp + 4,
sizeof(struct smb_negotiate_rsp) - 4))
return -ENOMEM;
diff --git a/fs/smb/server/smbacl.c b/fs/smb/server/smbacl.c
index 1c9775f1efa5..d39d3e553366 100644
--- a/fs/smb/server/smbacl.c
+++ b/fs/smb/server/smbacl.c
@@ -345,10 +345,10 @@ int init_acl_state(struct posix_acl_state *state, int cnt)
*/
alloc = sizeof(struct posix_ace_state_array)
+ cnt * sizeof(struct posix_user_ace_state);
- state->users = kzalloc(alloc, GFP_KERNEL);
+ state->users = kzalloc(alloc, KSMBD_DEFAULT_GFP);
if (!state->users)
return -ENOMEM;
- state->groups = kzalloc(alloc, GFP_KERNEL);
+ state->groups = kzalloc(alloc, KSMBD_DEFAULT_GFP);
if (!state->groups) {
kfree(state->users);
return -ENOMEM;
@@ -410,7 +410,7 @@ static void parse_dacl(struct mnt_idmap *idmap,
return;
}
- ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), GFP_KERNEL);
+ ppace = kmalloc_array(num_aces, sizeof(struct smb_ace *), KSMBD_DEFAULT_GFP);
if (!ppace) {
free_acl_state(&default_acl_state);
free_acl_state(&acl_state);
@@ -553,7 +553,7 @@ static void parse_dacl(struct mnt_idmap *idmap,
if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
fattr->cf_acls =
posix_acl_alloc(acl_state.users->n +
- acl_state.groups->n + 4, GFP_KERNEL);
+ acl_state.groups->n + 4, KSMBD_DEFAULT_GFP);
if (fattr->cf_acls) {
cf_pace = fattr->cf_acls->a_entries;
posix_state_to_acl(&acl_state, cf_pace);
@@ -567,7 +567,7 @@ static void parse_dacl(struct mnt_idmap *idmap,
if (IS_ENABLED(CONFIG_FS_POSIX_ACL)) {
fattr->cf_dacls =
posix_acl_alloc(default_acl_state.users->n +
- default_acl_state.groups->n + 4, GFP_KERNEL);
+ default_acl_state.groups->n + 4, KSMBD_DEFAULT_GFP);
if (fattr->cf_dacls) {
cf_pdace = fattr->cf_dacls->a_entries;
posix_state_to_acl(&default_acl_state, cf_pdace);
@@ -595,7 +595,7 @@ static void set_posix_acl_entries_dacl(struct mnt_idmap *idmap,
for (i = 0; i < fattr->cf_acls->a_count; i++, pace++) {
int flags = 0;
- sid = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
+ sid = kmalloc(sizeof(struct smb_sid), KSMBD_DEFAULT_GFP);
if (!sid)
break;
@@ -662,7 +662,7 @@ posix_default_acl:
pace = fattr->cf_dacls->a_entries;
for (i = 0; i < fattr->cf_dacls->a_count; i++, pace++) {
- sid = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
+ sid = kmalloc(sizeof(struct smb_sid), KSMBD_DEFAULT_GFP);
if (!sid)
break;
@@ -906,7 +906,7 @@ int build_sec_desc(struct mnt_idmap *idmap,
gid_t gid;
unsigned int sid_type = SIDOWNER;
- nowner_sid_ptr = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
+ nowner_sid_ptr = kmalloc(sizeof(struct smb_sid), KSMBD_DEFAULT_GFP);
if (!nowner_sid_ptr)
return -ENOMEM;
@@ -915,7 +915,7 @@ int build_sec_desc(struct mnt_idmap *idmap,
sid_type = SIDUNIX_USER;
id_to_sid(uid, sid_type, nowner_sid_ptr);
- ngroup_sid_ptr = kmalloc(sizeof(struct smb_sid), GFP_KERNEL);
+ ngroup_sid_ptr = kmalloc(sizeof(struct smb_sid), KSMBD_DEFAULT_GFP);
if (!ngroup_sid_ptr) {
kfree(nowner_sid_ptr);
return -ENOMEM;
@@ -1032,7 +1032,8 @@ int smb_inherit_dacl(struct ksmbd_conn *conn,
goto free_parent_pntsd;
}
- aces_base = kmalloc(sizeof(struct smb_ace) * num_aces * 2, GFP_KERNEL);
+ aces_base = kmalloc(sizeof(struct smb_ace) * num_aces * 2,
+ KSMBD_DEFAULT_GFP);
if (!aces_base) {
rc = -ENOMEM;
goto free_parent_pntsd;
@@ -1126,7 +1127,7 @@ pass:
pntsd_alloc_size = sizeof(struct smb_ntsd) + powner_sid_size +
pgroup_sid_size + sizeof(struct smb_acl) + nt_size;
- pntsd = kzalloc(pntsd_alloc_size, GFP_KERNEL);
+ pntsd = kzalloc(pntsd_alloc_size, KSMBD_DEFAULT_GFP);
if (!pntsd) {
rc = -ENOMEM;
goto free_aces_base;
diff --git a/fs/smb/server/transport_ipc.c b/fs/smb/server/transport_ipc.c
index 2f27afb695f6..befaf42b84cc 100644
--- a/fs/smb/server/transport_ipc.c
+++ b/fs/smb/server/transport_ipc.c
@@ -244,7 +244,7 @@ static struct ksmbd_ipc_msg *ipc_msg_alloc(size_t sz)
struct ksmbd_ipc_msg *msg;
size_t msg_sz = sz + sizeof(struct ksmbd_ipc_msg);
- msg = kvzalloc(msg_sz, GFP_KERNEL);
+ msg = kvzalloc(msg_sz, KSMBD_DEFAULT_GFP);
if (msg)
msg->sz = sz;
return msg;
@@ -283,7 +283,7 @@ static int handle_response(int type, void *payload, size_t sz)
entry->type + 1, type);
}
- entry->response = kvzalloc(sz, GFP_KERNEL);
+ entry->response = kvzalloc(sz, KSMBD_DEFAULT_GFP);
if (!entry->response) {
ret = -ENOMEM;
break;
@@ -319,8 +319,11 @@ static int ipc_server_config_on_startup(struct ksmbd_startup_request *req)
init_smb2_max_write_size(req->smb2_max_write);
if (req->smb2_max_trans)
init_smb2_max_trans_size(req->smb2_max_trans);
- if (req->smb2_max_credits)
+ if (req->smb2_max_credits) {
init_smb2_max_credits(req->smb2_max_credits);
+ server_conf.max_inflight_req =
+ req->smb2_max_credits;
+ }
if (req->smbd_max_io_size)
init_smbd_max_io_size(req->smbd_max_io_size);
@@ -444,7 +447,7 @@ static int ipc_msg_send(struct ksmbd_ipc_msg *msg)
if (!ksmbd_tools_pid)
return ret;
- skb = genlmsg_new(msg->sz, GFP_KERNEL);
+ skb = genlmsg_new(msg->sz, KSMBD_DEFAULT_GFP);
if (!skb)
return -ENOMEM;
diff --git a/fs/smb/server/transport_rdma.c b/fs/smb/server/transport_rdma.c
index 17c76713c6d0..0ef3c9f0bfeb 100644
--- a/fs/smb/server/transport_rdma.c
+++ b/fs/smb/server/transport_rdma.c
@@ -362,7 +362,7 @@ static struct smb_direct_transport *alloc_transport(struct rdma_cm_id *cm_id)
struct smb_direct_transport *t;
struct ksmbd_conn *conn;
- t = kzalloc(sizeof(*t), GFP_KERNEL);
+ t = kzalloc(sizeof(*t), KSMBD_DEFAULT_GFP);
if (!t)
return NULL;
@@ -462,7 +462,7 @@ static struct smb_direct_sendmsg
{
struct smb_direct_sendmsg *msg;
- msg = mempool_alloc(t->sendmsg_mempool, GFP_KERNEL);
+ msg = mempool_alloc(t->sendmsg_mempool, KSMBD_DEFAULT_GFP);
if (!msg)
return ERR_PTR(-ENOMEM);
msg->transport = t;
@@ -1406,7 +1406,7 @@ static int smb_direct_rdma_xmit(struct smb_direct_transport *t,
desc_buf = buf;
for (i = 0; i < desc_num; i++) {
msg = kzalloc(struct_size(msg, sg_list, SG_CHUNK_SIZE),
- GFP_KERNEL);
+ KSMBD_DEFAULT_GFP);
if (!msg) {
ret = -ENOMEM;
goto out;
@@ -1852,7 +1852,7 @@ static int smb_direct_create_pools(struct smb_direct_transport *t)
INIT_LIST_HEAD(&t->recvmsg_queue);
for (i = 0; i < t->recv_credit_max; i++) {
- recvmsg = mempool_alloc(t->recvmsg_mempool, GFP_KERNEL);
+ recvmsg = mempool_alloc(t->recvmsg_mempool, KSMBD_DEFAULT_GFP);
if (!recvmsg)
goto err;
recvmsg->transport = t;
@@ -2144,7 +2144,7 @@ static int smb_direct_ib_client_add(struct ib_device *ib_dev)
if (!rdma_frwr_is_supported(&ib_dev->attrs))
return 0;
- smb_dev = kzalloc(sizeof(*smb_dev), GFP_KERNEL);
+ smb_dev = kzalloc(sizeof(*smb_dev), KSMBD_DEFAULT_GFP);
if (!smb_dev)
return -ENOMEM;
smb_dev->ib_dev = ib_dev;
@@ -2289,6 +2289,9 @@ out:
}
}
+ ksmbd_debug(RDMA, "netdev(%s) rdma capable : %s\n",
+ netdev->name, rdma_capable ? "true" : "false");
+
return rdma_capable;
}
diff --git a/fs/smb/server/transport_tcp.c b/fs/smb/server/transport_tcp.c
index aaed9e293b2e..0d9007285e30 100644
--- a/fs/smb/server/transport_tcp.c
+++ b/fs/smb/server/transport_tcp.c
@@ -76,7 +76,7 @@ static struct tcp_transport *alloc_transport(struct socket *client_sk)
struct tcp_transport *t;
struct ksmbd_conn *conn;
- t = kzalloc(sizeof(*t), GFP_KERNEL);
+ t = kzalloc(sizeof(*t), KSMBD_DEFAULT_GFP);
if (!t)
return NULL;
t->sock = client_sk;
@@ -151,7 +151,7 @@ static struct kvec *get_conn_iovec(struct tcp_transport *t, unsigned int nr_segs
return t->iov;
/* not big enough -- allocate a new one and release the old */
- new_iov = kmalloc_array(nr_segs, sizeof(*new_iov), GFP_KERNEL);
+ new_iov = kmalloc_array(nr_segs, sizeof(*new_iov), KSMBD_DEFAULT_GFP);
if (new_iov) {
kfree(t->iov);
t->iov = new_iov;
@@ -521,6 +521,8 @@ static int ksmbd_netdev_event(struct notifier_block *nb, unsigned long event,
found = 1;
if (iface->state != IFACE_STATE_DOWN)
break;
+ ksmbd_debug(CONN, "netdev-up event: netdev(%s) is going up\n",
+ iface->name);
ret = create_socket(iface);
if (ret)
return NOTIFY_OK;
@@ -528,9 +530,11 @@ static int ksmbd_netdev_event(struct notifier_block *nb, unsigned long event,
}
}
if (!found && bind_additional_ifaces) {
- iface = alloc_iface(kstrdup(netdev->name, GFP_KERNEL));
+ iface = alloc_iface(kstrdup(netdev->name, KSMBD_DEFAULT_GFP));
if (!iface)
return NOTIFY_OK;
+ ksmbd_debug(CONN, "netdev-up event: netdev(%s) is going up\n",
+ iface->name);
ret = create_socket(iface);
if (ret)
break;
@@ -540,6 +544,8 @@ static int ksmbd_netdev_event(struct notifier_block *nb, unsigned long event,
list_for_each_entry(iface, &iface_list, entry) {
if (!strcmp(iface->name, netdev->name) &&
iface->state == IFACE_STATE_CONFIGURED) {
+ ksmbd_debug(CONN, "netdev-down event: netdev(%s) is going down\n",
+ iface->name);
tcp_stop_kthread(iface->ksmbd_kthread);
iface->ksmbd_kthread = NULL;
mutex_lock(&iface->sock_release_lock);
@@ -600,7 +606,7 @@ static struct interface *alloc_iface(char *ifname)
if (!ifname)
return NULL;
- iface = kzalloc(sizeof(struct interface), GFP_KERNEL);
+ iface = kzalloc(sizeof(struct interface), KSMBD_DEFAULT_GFP);
if (!iface) {
kfree(ifname);
return NULL;
@@ -624,7 +630,7 @@ int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz)
for_each_netdev(&init_net, netdev) {
if (netif_is_bridge_port(netdev))
continue;
- if (!alloc_iface(kstrdup(netdev->name, GFP_KERNEL))) {
+ if (!alloc_iface(kstrdup(netdev->name, KSMBD_DEFAULT_GFP))) {
rtnl_unlock();
return -ENOMEM;
}
@@ -635,7 +641,7 @@ int ksmbd_tcp_set_interfaces(char *ifc_list, int ifc_list_sz)
}
while (ifc_list_sz > 0) {
- if (!alloc_iface(kstrdup(ifc_list, GFP_KERNEL)))
+ if (!alloc_iface(kstrdup(ifc_list, KSMBD_DEFAULT_GFP)))
return -ENOMEM;
sz = strlen(ifc_list);
diff --git a/fs/smb/server/unicode.c b/fs/smb/server/unicode.c
index 217106ff7b82..85e6791745ec 100644
--- a/fs/smb/server/unicode.c
+++ b/fs/smb/server/unicode.c
@@ -297,7 +297,7 @@ char *smb_strndup_from_utf16(const char *src, const int maxlen,
if (is_unicode) {
len = smb_utf16_bytes((__le16 *)src, maxlen, codepage);
len += nls_nullsize(codepage);
- dst = kmalloc(len, GFP_KERNEL);
+ dst = kmalloc(len, KSMBD_DEFAULT_GFP);
if (!dst)
return ERR_PTR(-ENOMEM);
ret = smb_from_utf16(dst, (__le16 *)src, len, maxlen, codepage,
@@ -309,7 +309,7 @@ char *smb_strndup_from_utf16(const char *src, const int maxlen,
} else {
len = strnlen(src, maxlen);
len++;
- dst = kmalloc(len, GFP_KERNEL);
+ dst = kmalloc(len, KSMBD_DEFAULT_GFP);
if (!dst)
return ERR_PTR(-ENOMEM);
strscpy(dst, src, len);
diff --git a/fs/smb/server/vfs.c b/fs/smb/server/vfs.c
index 7cbd580120d1..88d167a5f8b7 100644
--- a/fs/smb/server/vfs.c
+++ b/fs/smb/server/vfs.c
@@ -444,7 +444,7 @@ static int ksmbd_vfs_stream_write(struct ksmbd_file *fp, char *buf, loff_t *pos,
}
if (v_len < size) {
- wbuf = kvzalloc(size, GFP_KERNEL);
+ wbuf = kvzalloc(size, KSMBD_DEFAULT_GFP);
if (!wbuf) {
err = -ENOMEM;
goto out;
@@ -865,7 +865,7 @@ ssize_t ksmbd_vfs_listxattr(struct dentry *dentry, char **list)
if (size <= 0)
return size;
- vlist = kvzalloc(size, GFP_KERNEL);
+ vlist = kvzalloc(size, KSMBD_DEFAULT_GFP);
if (!vlist)
return -ENOMEM;
@@ -907,7 +907,7 @@ ssize_t ksmbd_vfs_getxattr(struct mnt_idmap *idmap,
if (xattr_len < 0)
return xattr_len;
- buf = kmalloc(xattr_len + 1, GFP_KERNEL);
+ buf = kmalloc(xattr_len + 1, KSMBD_DEFAULT_GFP);
if (!buf)
return -ENOMEM;
@@ -1411,7 +1411,7 @@ static struct xattr_smb_acl *ksmbd_vfs_make_xattr_posix_acl(struct mnt_idmap *id
smb_acl = kzalloc(sizeof(struct xattr_smb_acl) +
sizeof(struct xattr_acl_entry) * posix_acls->a_count,
- GFP_KERNEL);
+ KSMBD_DEFAULT_GFP);
if (!smb_acl)
goto out;
@@ -1767,7 +1767,7 @@ int ksmbd_vfs_xattr_stream_name(char *stream_name, char **xattr_stream_name,
else
type = ":$DATA";
- buf = kasprintf(GFP_KERNEL, "%s%s%s",
+ buf = kasprintf(KSMBD_DEFAULT_GFP, "%s%s%s",
XATTR_NAME_STREAM, stream_name, type);
if (!buf)
return -ENOMEM;
@@ -1896,7 +1896,7 @@ int ksmbd_vfs_set_init_posix_acl(struct mnt_idmap *idmap,
acl_state.group.allow;
acl_state.mask.allow = 0x07;
- acls = posix_acl_alloc(6, GFP_KERNEL);
+ acls = posix_acl_alloc(6, KSMBD_DEFAULT_GFP);
if (!acls) {
free_acl_state(&acl_state);
return -ENOMEM;
diff --git a/fs/smb/server/vfs.h b/fs/smb/server/vfs.h
index cb76f4b5bafe..06903024a2d8 100644
--- a/fs/smb/server/vfs.h
+++ b/fs/smb/server/vfs.h
@@ -43,6 +43,7 @@ struct ksmbd_dir_info {
char *rptr;
int name_len;
int out_buf_len;
+ int num_scan;
int num_entry;
int data_count;
int last_entry_offset;
diff --git a/fs/smb/server/vfs_cache.c b/fs/smb/server/vfs_cache.c
index a19f4e563c7e..8d1f30dcba7e 100644
--- a/fs/smb/server/vfs_cache.c
+++ b/fs/smb/server/vfs_cache.c
@@ -188,7 +188,7 @@ static struct ksmbd_inode *ksmbd_inode_get(struct ksmbd_file *fp)
if (ci)
return ci;
- ci = kmalloc(sizeof(struct ksmbd_inode), GFP_KERNEL);
+ ci = kmalloc(sizeof(struct ksmbd_inode), KSMBD_DEFAULT_GFP);
if (!ci)
return NULL;
@@ -577,7 +577,7 @@ static int __open_id(struct ksmbd_file_table *ft, struct ksmbd_file *fp,
return -EMFILE;
}
- idr_preload(GFP_KERNEL);
+ idr_preload(KSMBD_DEFAULT_GFP);
write_lock(&ft->lock);
ret = idr_alloc_cyclic(ft->idr, fp, 0, INT_MAX - 1, GFP_NOWAIT);
if (ret >= 0) {
@@ -605,7 +605,7 @@ struct ksmbd_file *ksmbd_open_fd(struct ksmbd_work *work, struct file *filp)
struct ksmbd_file *fp;
int ret;
- fp = kmem_cache_zalloc(filp_cache, GFP_KERNEL);
+ fp = kmem_cache_zalloc(filp_cache, KSMBD_DEFAULT_GFP);
if (!fp) {
pr_err("Failed to allocate memory\n");
return ERR_PTR(-ENOMEM);
@@ -923,7 +923,7 @@ int ksmbd_validate_name_reconnect(struct ksmbd_share_config *share,
char *pathname, *ab_pathname;
int ret = 0;
- pathname = kmalloc(PATH_MAX, GFP_KERNEL);
+ pathname = kmalloc(PATH_MAX, KSMBD_DEFAULT_GFP);
if (!pathname)
return -EACCES;
@@ -983,7 +983,7 @@ int ksmbd_reopen_durable_fd(struct ksmbd_work *work, struct ksmbd_file *fp)
int ksmbd_init_file_table(struct ksmbd_file_table *ft)
{
- ft->idr = kzalloc(sizeof(struct idr), GFP_KERNEL);
+ ft->idr = kzalloc(sizeof(struct idr), KSMBD_DEFAULT_GFP);
if (!ft->idr)
return -ENOMEM;
diff --git a/fs/sysfs/file.c b/fs/sysfs/file.c
index d1995e2d6c94..785408861c01 100644
--- a/fs/sysfs/file.c
+++ b/fs/sysfs/file.c
@@ -91,9 +91,12 @@ static ssize_t sysfs_kf_bin_read(struct kernfs_open_file *of, char *buf,
count = size - pos;
}
- if (!battr->read)
+ if (!battr->read && !battr->read_new)
return -EIO;
+ if (battr->read_new)
+ return battr->read_new(of->file, kobj, battr, buf, pos, count);
+
return battr->read(of->file, kobj, battr, buf, pos, count);
}
@@ -152,9 +155,12 @@ static ssize_t sysfs_kf_bin_write(struct kernfs_open_file *of, char *buf,
if (!count)
return 0;
- if (!battr->write)
+ if (!battr->write && !battr->write_new)
return -EIO;
+ if (battr->write_new)
+ return battr->write_new(of->file, kobj, battr, buf, pos, count);
+
return battr->write(of->file, kobj, battr, buf, pos, count);
}
@@ -315,7 +321,7 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent,
}
int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
- const struct bin_attribute *battr, umode_t mode,
+ const struct bin_attribute *battr, umode_t mode, size_t size,
kuid_t uid, kgid_t gid, const void *ns)
{
const struct attribute *attr = &battr->attr;
@@ -323,13 +329,19 @@ int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
const struct kernfs_ops *ops;
struct kernfs_node *kn;
+ if (battr->read && battr->read_new)
+ return -EINVAL;
+
+ if (battr->write && battr->write_new)
+ return -EINVAL;
+
if (battr->mmap)
ops = &sysfs_bin_kfops_mmap;
- else if (battr->read && battr->write)
+ else if ((battr->read || battr->read_new) && (battr->write || battr->write_new))
ops = &sysfs_bin_kfops_rw;
- else if (battr->read)
+ else if (battr->read || battr->read_new)
ops = &sysfs_bin_kfops_ro;
- else if (battr->write)
+ else if (battr->write || battr->write_new)
ops = &sysfs_bin_kfops_wo;
else
ops = &sysfs_file_kfops_empty;
@@ -340,7 +352,7 @@ int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
#endif
kn = __kernfs_create_file(parent, attr->name, mode & 0777, uid, gid,
- battr->size, ops, (void *)attr, ns, key);
+ size, ops, (void *)attr, ns, key);
if (IS_ERR(kn)) {
if (PTR_ERR(kn) == -EEXIST)
sysfs_warn_dup(parent, attr->name);
@@ -580,8 +592,8 @@ int sysfs_create_bin_file(struct kobject *kobj,
return -EINVAL;
kobject_get_ownership(kobj, &uid, &gid);
- return sysfs_add_bin_file_mode_ns(kobj->sd, attr, attr->attr.mode, uid,
- gid, NULL);
+ return sysfs_add_bin_file_mode_ns(kobj->sd, attr, attr->attr.mode,
+ attr->size, uid, gid, NULL);
}
EXPORT_SYMBOL_GPL(sysfs_create_bin_file);
diff --git a/fs/sysfs/group.c b/fs/sysfs/group.c
index d22ad67a0f32..8b01a7eda5fb 100644
--- a/fs/sysfs/group.c
+++ b/fs/sysfs/group.c
@@ -87,6 +87,7 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
if (grp->bin_attrs) {
for (i = 0, bin_attr = grp->bin_attrs; *bin_attr; i++, bin_attr++) {
umode_t mode = (*bin_attr)->attr.mode;
+ size_t size = (*bin_attr)->size;
if (update)
kernfs_remove_by_name(parent,
@@ -97,6 +98,8 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
if (!mode)
continue;
}
+ if (grp->bin_size)
+ size = grp->bin_size(kobj, *bin_attr, i);
WARN(mode & ~(SYSFS_PREALLOC | 0664),
"Attribute %s: Invalid permissions 0%o\n",
@@ -104,7 +107,7 @@ static int create_files(struct kernfs_node *parent, struct kobject *kobj,
mode &= SYSFS_PREALLOC | 0664;
error = sysfs_add_bin_file_mode_ns(parent, *bin_attr,
- mode, uid, gid,
+ mode, size, uid, gid,
NULL);
if (error)
break;
diff --git a/fs/sysfs/sysfs.h b/fs/sysfs/sysfs.h
index 3f28c9af5756..8e012f25e1c0 100644
--- a/fs/sysfs/sysfs.h
+++ b/fs/sysfs/sysfs.h
@@ -31,7 +31,7 @@ int sysfs_add_file_mode_ns(struct kernfs_node *parent,
const struct attribute *attr, umode_t amode, kuid_t uid,
kgid_t gid, const void *ns);
int sysfs_add_bin_file_mode_ns(struct kernfs_node *parent,
- const struct bin_attribute *battr, umode_t mode,
+ const struct bin_attribute *battr, umode_t mode, size_t size,
kuid_t uid, kgid_t gid, const void *ns);
/*
diff --git a/fs/ubifs/ioctl.c b/fs/ubifs/ioctl.c
index d79cabe193c3..2c99349cf537 100644
--- a/fs/ubifs/ioctl.c
+++ b/fs/ubifs/ioctl.c
@@ -213,12 +213,6 @@ long ubifs_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
long ubifs_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
switch (cmd) {
- case FS_IOC32_GETFLAGS:
- cmd = FS_IOC_GETFLAGS;
- break;
- case FS_IOC32_SETFLAGS:
- cmd = FS_IOC_SETFLAGS;
- break;
case FS_IOC_SET_ENCRYPTION_POLICY:
case FS_IOC_GET_ENCRYPTION_POLICY:
case FS_IOC_GET_ENCRYPTION_POLICY_EX:
diff --git a/fs/ubifs/journal.c b/fs/ubifs/journal.c
index 4a35f9e8f668..36ba79fbd2ff 100644
--- a/fs/ubifs/journal.c
+++ b/fs/ubifs/journal.c
@@ -981,6 +981,13 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
dbg_jnl("ino %lu, nlink %u", inode->i_ino, inode->i_nlink);
+ if (kill_xattrs && ui->xattr_cnt > ubifs_xattr_max_cnt(c)) {
+ ubifs_err(c, "Cannot delete inode, it has too much xattrs!");
+ err = -EPERM;
+ ubifs_ro_mode(c, err);
+ return err;
+ }
+
/*
* If the inode is being deleted, do not write the attached data. No
* need to synchronize the write-buffer either.
@@ -1012,12 +1019,6 @@ int ubifs_jnl_write_inode(struct ubifs_info *c, const struct inode *inode)
struct inode *xino;
struct ubifs_dent_node *xent, *pxent = NULL;
- if (ui->xattr_cnt > ubifs_xattr_max_cnt(c)) {
- err = -EPERM;
- ubifs_err(c, "Cannot delete inode, it has too much xattrs!");
- goto out_release;
- }
-
lowest_xent_key(c, &key, inode->i_ino);
while (1) {
xent = ubifs_tnc_next_ent(c, &key, &nm);
diff --git a/fs/ubifs/lpt_commit.c b/fs/ubifs/lpt_commit.c
index 07351fdce722..aa8837e6247c 100644
--- a/fs/ubifs/lpt_commit.c
+++ b/fs/ubifs/lpt_commit.c
@@ -577,7 +577,7 @@ static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c,
/* Go right */
nnode = ubifs_get_nnode(c, nnode, iip);
if (IS_ERR(nnode))
- return (void *)nnode;
+ return ERR_CAST(nnode);
/* Go down to level 1 */
while (nnode->level > 1) {
@@ -594,7 +594,7 @@ static struct ubifs_pnode *next_pnode_to_dirty(struct ubifs_info *c,
}
nnode = ubifs_get_nnode(c, nnode, iip);
if (IS_ERR(nnode))
- return (void *)nnode;
+ return ERR_CAST(nnode);
}
for (iip = 0; iip < UBIFS_LPT_FANOUT; iip++)
diff --git a/fs/ubifs/orphan.c b/fs/ubifs/orphan.c
index fb957d963ba6..5555dd740889 100644
--- a/fs/ubifs/orphan.c
+++ b/fs/ubifs/orphan.c
@@ -76,7 +76,7 @@ int ubifs_add_orphan(struct ubifs_info *c, ino_t inum)
else if (inum > o->inum)
p = &(*p)->rb_right;
else {
- ubifs_err(c, "orphaned twice");
+ ubifs_err(c, "ino %lu orphaned twice", (unsigned long)inum);
spin_unlock(&c->orphan_lock);
kfree(orphan);
return -EINVAL;
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 3fb308b6e167..f3e3b2068608 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -773,10 +773,10 @@ static void init_constants_master(struct ubifs_info *c)
* necessary to report something for the 'statfs()' call.
*
* Subtract the LEB reserved for GC, the LEB which is reserved for
- * deletions, minimum LEBs for the index, and assume only one journal
- * head is available.
+ * deletions, minimum LEBs for the index, the LEBs which are reserved
+ * for each journal head.
*/
- tmp64 = c->main_lebs - 1 - 1 - MIN_INDEX_LEBS - c->jhead_cnt + 1;
+ tmp64 = c->main_lebs - 1 - 1 - MIN_INDEX_LEBS - c->jhead_cnt;
tmp64 *= (long long)c->leb_size - c->leb_overhead;
tmp64 = ubifs_reported_space(c, tmp64);
c->block_cnt = tmp64 >> UBIFS_BLOCK_SHIFT;
@@ -2206,6 +2206,8 @@ static int ubifs_fill_super(struct super_block *sb, struct fs_context *fc)
}
super_set_uuid(sb, c->uuid, sizeof(c->uuid));
+ super_set_sysfs_name_generic(sb, UBIFS_DFS_DIR_NAME,
+ c->vi.ubi_num, c->vi.vol_id);
mutex_unlock(&c->umount_mutex);
return 0;
diff --git a/fs/ubifs/tnc.c b/fs/ubifs/tnc.c
index 45cacdcd4746..33946b518148 100644
--- a/fs/ubifs/tnc.c
+++ b/fs/ubifs/tnc.c
@@ -2930,8 +2930,6 @@ int ubifs_tnc_remove_ino(struct ubifs_info *c, ino_t inum)
dbg_tnc("xent '%s', ino %lu", xent->name,
(unsigned long)xattr_inum);
- ubifs_evict_xattr_inode(c, xattr_inum);
-
fname_name(&nm) = xent->name;
fname_len(&nm) = le16_to_cpu(xent->nlen);
err = ubifs_tnc_remove_nm(c, &key1, &nm);
diff --git a/fs/ubifs/tnc_commit.c b/fs/ubifs/tnc_commit.c
index a55e04822d16..7c43e0ccf6d4 100644
--- a/fs/ubifs/tnc_commit.c
+++ b/fs/ubifs/tnc_commit.c
@@ -657,6 +657,8 @@ static int get_znodes_to_commit(struct ubifs_info *c)
znode->alt = 0;
cnext = find_next_dirty(znode);
if (!cnext) {
+ ubifs_assert(c, !znode->parent);
+ znode->cparent = NULL;
znode->cnext = c->cnext;
break;
}
diff --git a/fs/ubifs/ubifs.h b/fs/ubifs/ubifs.h
index d69a5a42d693..3375bbe0508c 100644
--- a/fs/ubifs/ubifs.h
+++ b/fs/ubifs/ubifs.h
@@ -2040,13 +2040,10 @@ ssize_t ubifs_xattr_get(struct inode *host, const char *name, void *buf,
#ifdef CONFIG_UBIFS_FS_XATTR
extern const struct xattr_handler * const ubifs_xattr_handlers[];
ssize_t ubifs_listxattr(struct dentry *dentry, char *buffer, size_t size);
-void ubifs_evict_xattr_inode(struct ubifs_info *c, ino_t xattr_inum);
int ubifs_purge_xattrs(struct inode *host);
#else
#define ubifs_listxattr NULL
#define ubifs_xattr_handlers NULL
-static inline void ubifs_evict_xattr_inode(struct ubifs_info *c,
- ino_t xattr_inum) { }
static inline int ubifs_purge_xattrs(struct inode *host)
{
return 0;
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index f734588b224a..c21a0c2b3e90 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -48,19 +48,6 @@
#include <linux/slab.h>
#include <linux/xattr.h>
-/*
- * Extended attribute type constants.
- *
- * USER_XATTR: user extended attribute ("user.*")
- * TRUSTED_XATTR: trusted extended attribute ("trusted.*)
- * SECURITY_XATTR: security extended attribute ("security.*")
- */
-enum {
- USER_XATTR,
- TRUSTED_XATTR,
- SECURITY_XATTR,
-};
-
static const struct inode_operations empty_iops;
static const struct file_operations empty_fops;
@@ -532,8 +519,6 @@ int ubifs_purge_xattrs(struct inode *host)
ubifs_err(c, "dead directory entry '%s', error %d",
xent->name, err);
ubifs_ro_mode(c, err);
- kfree(pxent);
- kfree(xent);
goto out_err;
}
@@ -541,16 +526,12 @@ int ubifs_purge_xattrs(struct inode *host)
clear_nlink(xino);
err = remove_xattr(c, host, xino, &nm);
+ iput(xino);
if (err) {
- kfree(pxent);
- kfree(xent);
- iput(xino);
ubifs_err(c, "cannot remove xattr, error %d", err);
goto out_err;
}
- iput(xino);
-
kfree(pxent);
pxent = xent;
key_read(c, &xent->key, &key);
@@ -566,32 +547,12 @@ int ubifs_purge_xattrs(struct inode *host)
return 0;
out_err:
+ kfree(pxent);
+ kfree(xent);
up_write(&ubifs_inode(host)->xattr_sem);
return err;
}
-/**
- * ubifs_evict_xattr_inode - Evict an xattr inode.
- * @c: UBIFS file-system description object
- * @xattr_inum: xattr inode number
- *
- * When an inode that hosts xattrs is being removed we have to make sure
- * that cached inodes of the xattrs also get removed from the inode cache
- * otherwise we'd waste memory. This function looks up an inode from the
- * inode cache and clears the link counter such that iput() will evict
- * the inode.
- */
-void ubifs_evict_xattr_inode(struct ubifs_info *c, ino_t xattr_inum)
-{
- struct inode *inode;
-
- inode = ilookup(c->vfs_sb, xattr_inum);
- if (inode) {
- clear_nlink(inode);
- iput(inode);
- }
-}
-
static int ubifs_xattr_remove(struct inode *host, const char *name)
{
struct inode *inode;
diff --git a/fs/udf/namei.c b/fs/udf/namei.c
index 78a603129dd5..2cb49b6b0716 100644
--- a/fs/udf/namei.c
+++ b/fs/udf/namei.c
@@ -517,7 +517,11 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry)
inode->i_nlink);
clear_nlink(inode);
inode->i_size = 0;
- inode_dec_link_count(dir);
+ if (dir->i_nlink >= 3)
+ inode_dec_link_count(dir);
+ else
+ udf_warn(inode->i_sb, "parent dir link count too low (%u)\n",
+ dir->i_nlink);
udf_add_fid_counter(dir->i_sb, true, -1);
inode_set_mtime_to_ts(dir,
inode_set_ctime_to_ts(dir, inode_set_ctime_current(inode)));
@@ -787,8 +791,18 @@ static int udf_rename(struct mnt_idmap *idmap, struct inode *old_dir,
retval = -ENOTEMPTY;
if (!empty_dir(new_inode))
goto out_oiter;
+ retval = -EFSCORRUPTED;
+ if (new_inode->i_nlink != 2)
+ goto out_oiter;
}
+ retval = -EFSCORRUPTED;
+ if (old_dir->i_nlink < 3)
+ goto out_oiter;
is_dir = true;
+ } else if (new_inode) {
+ retval = -EFSCORRUPTED;
+ if (new_inode->i_nlink < 1)
+ goto out_oiter;
}
if (is_dir && old_dir != new_dir) {
retval = udf_fiiter_find_entry(old_inode, &dotdot_name,
diff --git a/fs/unicode/mkutf8data.c b/fs/unicode/mkutf8data.c
index 6b095dd32e0f..401f5d3aeb0c 100644
--- a/fs/unicode/mkutf8data.c
+++ b/fs/unicode/mkutf8data.c
@@ -2230,6 +2230,75 @@ static void nfdicf_init(void)
file_fail(fold_name);
}
+static void ignore_init(void)
+{
+ FILE *file;
+ unsigned int unichar;
+ unsigned int first;
+ unsigned int last;
+ unsigned int *um;
+ int count;
+ int ret;
+
+ if (verbose > 0)
+ printf("Parsing %s\n", prop_name);
+ file = fopen(prop_name, "r");
+ if (!file)
+ open_fail(prop_name, errno);
+ assert(file);
+ count = 0;
+ while (fgets(line, LINESIZE, file)) {
+ ret = sscanf(line, "%X..%X ; %s # ", &first, &last, buf0);
+ if (ret == 3) {
+ if (strcmp(buf0, "Default_Ignorable_Code_Point"))
+ continue;
+ if (!utf32valid(first) || !utf32valid(last))
+ line_fail(prop_name, line);
+ for (unichar = first; unichar <= last; unichar++) {
+ free(unicode_data[unichar].utf32nfdi);
+ um = malloc(sizeof(unsigned int));
+ *um = 0;
+ unicode_data[unichar].utf32nfdi = um;
+ free(unicode_data[unichar].utf32nfdicf);
+ um = malloc(sizeof(unsigned int));
+ *um = 0;
+ unicode_data[unichar].utf32nfdicf = um;
+ count++;
+ }
+ if (verbose > 1)
+ printf(" %X..%X Default_Ignorable_Code_Point\n",
+ first, last);
+ continue;
+ }
+ ret = sscanf(line, "%X ; %s # ", &unichar, buf0);
+ if (ret == 2) {
+ if (strcmp(buf0, "Default_Ignorable_Code_Point"))
+ continue;
+ if (!utf32valid(unichar))
+ line_fail(prop_name, line);
+ free(unicode_data[unichar].utf32nfdi);
+ um = malloc(sizeof(unsigned int));
+ *um = 0;
+ unicode_data[unichar].utf32nfdi = um;
+ free(unicode_data[unichar].utf32nfdicf);
+ um = malloc(sizeof(unsigned int));
+ *um = 0;
+ unicode_data[unichar].utf32nfdicf = um;
+ if (verbose > 1)
+ printf(" %X Default_Ignorable_Code_Point\n",
+ unichar);
+ count++;
+ continue;
+ }
+ }
+ fclose(file);
+
+ if (verbose > 0)
+ printf("Found %d entries\n", count);
+ if (count == 0)
+ file_fail(prop_name);
+}
+
static void corrections_init(void)
{
FILE *file;
@@ -3342,6 +3411,7 @@ int main(int argc, char *argv[])
ccc_init();
nfdi_init();
nfdicf_init();
+ ignore_init();
corrections_init();
hangul_decompose();
nfdi_decompose();
diff --git a/fs/unicode/utf8data.c_shipped b/fs/unicode/utf8data.c_shipped
index ef15d52900d0..73a93d49b3ba 100644
--- a/fs/unicode/utf8data.c_shipped
+++ b/fs/unicode/utf8data.c_shipped
@@ -82,58 +82,58 @@ static const struct utf8data utf8nfdidata[] = {
{ 0xc0100, 20736 }
};
-static const unsigned char utf8data[64080] = {
+static const unsigned char utf8data[64256] = {
/* nfdicf_30100 */
- 0xd7,0x07,0x66,0x84,0x0c,0x01,0x00,0xc6,0xd5,0x16,0xe4,0x96,0x1a,0xe3,0x60,0x15,
- 0xe2,0x49,0x0e,0xc1,0xe0,0x4b,0x0d,0xcf,0x86,0x65,0x2d,0x0d,0x01,0x00,0xd4,0xb8,
- 0xd3,0x27,0xe2,0x03,0xa3,0xe1,0xcb,0x35,0xe0,0x29,0x22,0xcf,0x86,0xc5,0xe4,0xfa,
- 0x6c,0xe3,0x45,0x68,0xe2,0xdb,0x65,0xe1,0x0e,0x65,0xe0,0xd3,0x64,0xcf,0x86,0xe5,
- 0x98,0x64,0x64,0x7b,0x64,0x0b,0x00,0xd2,0x0e,0xe1,0xb3,0x3c,0xe0,0x34,0xa3,0xcf,
- 0x86,0xcf,0x06,0x01,0x00,0xd1,0x0c,0xe0,0x98,0xa8,0xcf,0x86,0xcf,0x06,0x02,0xff,
+ 0xd7,0x07,0x66,0x84,0x0c,0x01,0x00,0xc6,0xd5,0x16,0xe4,0x99,0x1a,0xe3,0x63,0x15,
+ 0xe2,0x4c,0x0e,0xc1,0xe0,0x4e,0x0d,0xcf,0x86,0x65,0x2d,0x0d,0x01,0x00,0xd4,0xb8,
+ 0xd3,0x27,0xe2,0x89,0xa3,0xe1,0xce,0x35,0xe0,0x2c,0x22,0xcf,0x86,0xc5,0xe4,0x15,
+ 0x6d,0xe3,0x60,0x68,0xe2,0xf6,0x65,0xe1,0x29,0x65,0xe0,0xee,0x64,0xcf,0x86,0xe5,
+ 0xb3,0x64,0x64,0x96,0x64,0x0b,0x00,0xd2,0x0e,0xe1,0xb5,0x3c,0xe0,0xba,0xa3,0xcf,
+ 0x86,0xcf,0x06,0x01,0x00,0xd1,0x0c,0xe0,0x1e,0xa9,0xcf,0x86,0xcf,0x06,0x02,0xff,
0xff,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01,
- 0x00,0xe4,0xdf,0x45,0xe3,0x39,0x45,0xd2,0x06,0xcf,0x06,0x01,0x00,0xe1,0x01,0xad,
- 0xd0,0x21,0xcf,0x86,0xe5,0xfb,0xa9,0xe4,0x7a,0xa9,0xe3,0x39,0xa9,0xe2,0x18,0xa9,
- 0xe1,0x07,0xa9,0x10,0x08,0x01,0xff,0xe8,0xb1,0x88,0x00,0x01,0xff,0xe6,0x9b,0xb4,
- 0x00,0xcf,0x86,0xe5,0xdd,0xab,0xd4,0x19,0xe3,0x1c,0xab,0xe2,0xfb,0xaa,0xe1,0xea,
- 0xaa,0x10,0x08,0x01,0xff,0xe9,0xb9,0xbf,0x00,0x01,0xff,0xe8,0xab,0x96,0x00,0xe3,
- 0x83,0xab,0xe2,0x62,0xab,0xe1,0x51,0xab,0x10,0x08,0x01,0xff,0xe7,0xb8,0xb7,0x00,
- 0x01,0xff,0xe9,0x9b,0xbb,0x00,0x83,0xe2,0x68,0xf9,0xe1,0x52,0xf6,0xe0,0xcf,0xf4,
- 0xcf,0x86,0xd5,0x31,0xc4,0xe3,0x51,0x4e,0xe2,0xf2,0x4c,0xe1,0x09,0xcc,0xe0,0x99,
- 0x4b,0xcf,0x86,0xe5,0x8b,0x49,0xe4,0xac,0x46,0xe3,0x76,0xbc,0xe2,0xcd,0xbb,0xe1,
- 0xa8,0xbb,0xe0,0x81,0xbb,0xcf,0x86,0xe5,0x4e,0xbb,0x94,0x07,0x63,0x39,0xbb,0x07,
- 0x00,0x07,0x00,0xe4,0x3b,0xf4,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd2,0x0b,
- 0xe1,0x4a,0xe1,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0x39,0xe2,0xcf,0x86,
- 0xe5,0xfe,0xe1,0xcf,0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0x39,0xe2,0xcf,0x06,
- 0x13,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0xd4,0xf3,0xe3,0xbd,0xf2,
- 0xd2,0xa0,0xe1,0x73,0xe6,0xd0,0x21,0xcf,0x86,0xe5,0x74,0xe3,0xe4,0xf0,0xe2,0xe3,
- 0xae,0xe2,0xe2,0x8d,0xe2,0xe1,0x7b,0xe2,0x10,0x08,0x05,0xff,0xe4,0xb8,0xbd,0x00,
- 0x05,0xff,0xe4,0xb8,0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0xd0,0xe4,0xe3,0x8f,0xe4,
- 0xe2,0x6e,0xe4,0xe1,0x5d,0xe4,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,0x05,0xff,
- 0xe5,0x93,0xb6,0x00,0xd4,0x34,0xd3,0x18,0xe2,0x57,0xe5,0xe1,0x46,0xe5,0x10,0x09,
- 0x05,0xff,0xf0,0xa1,0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00,0xe2,0x77,
- 0xe5,0x91,0x11,0x10,0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,0xe5,0xac,
- 0x88,0x00,0x05,0xff,0xe5,0xac,0xbe,0x00,0xe3,0xbd,0xe5,0xd2,0x14,0xe1,0x8c,0xe5,
+ 0x00,0xe4,0xe1,0x45,0xe3,0x3b,0x45,0xd2,0x06,0xcf,0x06,0x01,0x00,0xe1,0x87,0xad,
+ 0xd0,0x21,0xcf,0x86,0xe5,0x81,0xaa,0xe4,0x00,0xaa,0xe3,0xbf,0xa9,0xe2,0x9e,0xa9,
+ 0xe1,0x8d,0xa9,0x10,0x08,0x01,0xff,0xe8,0xb1,0x88,0x00,0x01,0xff,0xe6,0x9b,0xb4,
+ 0x00,0xcf,0x86,0xe5,0x63,0xac,0xd4,0x19,0xe3,0xa2,0xab,0xe2,0x81,0xab,0xe1,0x70,
+ 0xab,0x10,0x08,0x01,0xff,0xe9,0xb9,0xbf,0x00,0x01,0xff,0xe8,0xab,0x96,0x00,0xe3,
+ 0x09,0xac,0xe2,0xe8,0xab,0xe1,0xd7,0xab,0x10,0x08,0x01,0xff,0xe7,0xb8,0xb7,0x00,
+ 0x01,0xff,0xe9,0x9b,0xbb,0x00,0x83,0xe2,0x19,0xfa,0xe1,0xf2,0xf6,0xe0,0x6f,0xf5,
+ 0xcf,0x86,0xd5,0x31,0xc4,0xe3,0x54,0x4e,0xe2,0xf5,0x4c,0xe1,0xa4,0xcc,0xe0,0x9c,
+ 0x4b,0xcf,0x86,0xe5,0x8e,0x49,0xe4,0xaf,0x46,0xe3,0x11,0xbd,0xe2,0x68,0xbc,0xe1,
+ 0x43,0xbc,0xe0,0x1c,0xbc,0xcf,0x86,0xe5,0xe9,0xbb,0x94,0x07,0x63,0xd4,0xbb,0x07,
+ 0x00,0x07,0x00,0xe4,0xdb,0xf4,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd2,0x0b,
+ 0xe1,0xea,0xe1,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0xd9,0xe2,0xcf,0x86,
+ 0xe5,0x9e,0xe2,0xcf,0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0xd9,0xe2,0xcf,0x06,
+ 0x13,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0x74,0xf4,0xe3,0x5d,0xf3,
+ 0xd2,0xa0,0xe1,0x13,0xe7,0xd0,0x21,0xcf,0x86,0xe5,0x14,0xe4,0xe4,0x90,0xe3,0xe3,
+ 0x4e,0xe3,0xe2,0x2d,0xe3,0xe1,0x1b,0xe3,0x10,0x08,0x05,0xff,0xe4,0xb8,0xbd,0x00,
+ 0x05,0xff,0xe4,0xb8,0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0x70,0xe5,0xe3,0x2f,0xe5,
+ 0xe2,0x0e,0xe5,0xe1,0xfd,0xe4,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,0x05,0xff,
+ 0xe5,0x93,0xb6,0x00,0xd4,0x34,0xd3,0x18,0xe2,0xf7,0xe5,0xe1,0xe6,0xe5,0x10,0x09,
+ 0x05,0xff,0xf0,0xa1,0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00,0xe2,0x17,
+ 0xe6,0x91,0x11,0x10,0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,0xe5,0xac,
+ 0x88,0x00,0x05,0xff,0xe5,0xac,0xbe,0x00,0xe3,0x5d,0xe6,0xd2,0x14,0xe1,0x2c,0xe6,
0x10,0x08,0x05,0xff,0xe5,0xaf,0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,0x00,0xe1,
- 0x98,0xe5,0x10,0x08,0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,0xa2,0x00,
- 0xd1,0xd5,0xd0,0x6a,0xcf,0x86,0xe5,0xed,0xea,0xd4,0x19,0xe3,0x26,0xea,0xe2,0x04,
- 0xea,0xe1,0xf3,0xe9,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,0xe6,0xb5,
- 0xb7,0x00,0xd3,0x18,0xe2,0x70,0xea,0xe1,0x5f,0xea,0x10,0x09,0x05,0xff,0xf0,0xa3,
- 0xbd,0x9e,0x00,0x05,0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0x88,0xea,0x10,
+ 0x38,0xe6,0x10,0x08,0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,0xa2,0x00,
+ 0xd1,0xd5,0xd0,0x6a,0xcf,0x86,0xe5,0x8d,0xeb,0xd4,0x19,0xe3,0xc6,0xea,0xe2,0xa4,
+ 0xea,0xe1,0x93,0xea,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,0xe6,0xb5,
+ 0xb7,0x00,0xd3,0x18,0xe2,0x10,0xeb,0xe1,0xff,0xea,0x10,0x09,0x05,0xff,0xf0,0xa3,
+ 0xbd,0x9e,0x00,0x05,0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0x28,0xeb,0x10,
0x08,0x05,0xff,0xe7,0x81,0xbd,0x00,0x05,0xff,0xe7,0x81,0xb7,0x00,0xd1,0x11,0x10,
0x08,0x05,0xff,0xe7,0x85,0x85,0x00,0x05,0xff,0xf0,0xa4,0x89,0xa3,0x00,0x10,0x08,
- 0x05,0xff,0xe7,0x86,0x9c,0x00,0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86,0xe5,0x8a,
- 0xec,0xd4,0x1a,0xe3,0xc2,0xeb,0xe2,0xa8,0xeb,0xe1,0x95,0xeb,0x10,0x08,0x05,0xff,
- 0xe7,0x9b,0xb4,0x00,0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2,0x0a,0xec,
- 0xe1,0xf8,0xeb,0x10,0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,0x83,0xa3,
- 0x00,0xd2,0x13,0xe1,0x26,0xec,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,0x05,0xff,
+ 0x05,0xff,0xe7,0x86,0x9c,0x00,0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86,0xe5,0x2a,
+ 0xed,0xd4,0x1a,0xe3,0x62,0xec,0xe2,0x48,0xec,0xe1,0x35,0xec,0x10,0x08,0x05,0xff,
+ 0xe7,0x9b,0xb4,0x00,0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2,0xaa,0xec,
+ 0xe1,0x98,0xec,0x10,0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,0x83,0xa3,
+ 0x00,0xd2,0x13,0xe1,0xc6,0xec,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,0x05,0xff,
0xe7,0xa9,0x80,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5,0xbc,0x00,0x05,
0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x05,
- 0xff,0xe7,0xaa,0xae,0x00,0xe0,0x3c,0xef,0xcf,0x86,0xd5,0x1d,0xe4,0xb1,0xed,0xe3,
- 0x6d,0xed,0xe2,0x4b,0xed,0xe1,0x3a,0xed,0x10,0x09,0x05,0xff,0xf0,0xa3,0x8d,0x9f,
- 0x00,0x05,0xff,0xe4,0x8f,0x95,0x00,0xd4,0x19,0xe3,0x58,0xee,0xe2,0x34,0xee,0xe1,
- 0x23,0xee,0x10,0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,0x8a,0x00,
- 0xd3,0x18,0xe2,0xa3,0xee,0xe1,0x92,0xee,0x10,0x09,0x05,0xff,0xf0,0xa6,0xbe,0xb1,
- 0x00,0x05,0xff,0xf0,0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0xbb,0xee,0x10,0x08,0x05,
+ 0xff,0xe7,0xaa,0xae,0x00,0xe0,0xdc,0xef,0xcf,0x86,0xd5,0x1d,0xe4,0x51,0xee,0xe3,
+ 0x0d,0xee,0xe2,0xeb,0xed,0xe1,0xda,0xed,0x10,0x09,0x05,0xff,0xf0,0xa3,0x8d,0x9f,
+ 0x00,0x05,0xff,0xe4,0x8f,0x95,0x00,0xd4,0x19,0xe3,0xf8,0xee,0xe2,0xd4,0xee,0xe1,
+ 0xc3,0xee,0x10,0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,0x8a,0x00,
+ 0xd3,0x18,0xe2,0x43,0xef,0xe1,0x32,0xef,0x10,0x09,0x05,0xff,0xf0,0xa6,0xbe,0xb1,
+ 0x00,0x05,0xff,0xf0,0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0x5b,0xef,0x10,0x08,0x05,
0xff,0xe8,0x9a,0x88,0x00,0x05,0xff,0xe8,0x9c,0x8e,0x00,0xd1,0x10,0x10,0x08,0x05,
0xff,0xe8,0x9c,0xa8,0x00,0x05,0xff,0xe8,0x9d,0xab,0x00,0x10,0x08,0x05,0xff,0xe8,
0x9e,0x86,0x00,0x05,0xff,0xe4,0xb5,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
@@ -141,152 +141,152 @@ static const unsigned char utf8data[64080] = {
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* nfdi_30100 */
- 0x57,0x04,0x01,0x00,0xc6,0xd5,0x13,0xe4,0xa8,0x59,0xe3,0xe2,0x54,0xe2,0x5b,0x4f,
- 0xc1,0xe0,0x87,0x4d,0xcf,0x06,0x01,0x00,0xd4,0xb8,0xd3,0x27,0xe2,0x89,0x9f,0xe1,
- 0x91,0x8d,0xe0,0x21,0x71,0xcf,0x86,0xc5,0xe4,0x80,0x69,0xe3,0xcb,0x64,0xe2,0x61,
- 0x62,0xe1,0x94,0x61,0xe0,0x59,0x61,0xcf,0x86,0xe5,0x1e,0x61,0x64,0x01,0x61,0x0b,
- 0x00,0xd2,0x0e,0xe1,0x3f,0xa0,0xe0,0xba,0x9f,0xcf,0x86,0xcf,0x06,0x01,0x00,0xd1,
- 0x0c,0xe0,0x1e,0xa5,0xcf,0x86,0xcf,0x06,0x02,0xff,0xff,0xd0,0x08,0xcf,0x86,0xcf,
- 0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01,0x00,0xe4,0x1b,0xb6,0xe3,0x95,
- 0xad,0xd2,0x06,0xcf,0x06,0x01,0x00,0xe1,0x87,0xa9,0xd0,0x21,0xcf,0x86,0xe5,0x81,
- 0xa6,0xe4,0x00,0xa6,0xe3,0xbf,0xa5,0xe2,0x9e,0xa5,0xe1,0x8d,0xa5,0x10,0x08,0x01,
- 0xff,0xe8,0xb1,0x88,0x00,0x01,0xff,0xe6,0x9b,0xb4,0x00,0xcf,0x86,0xe5,0x63,0xa8,
- 0xd4,0x19,0xe3,0xa2,0xa7,0xe2,0x81,0xa7,0xe1,0x70,0xa7,0x10,0x08,0x01,0xff,0xe9,
- 0xb9,0xbf,0x00,0x01,0xff,0xe8,0xab,0x96,0x00,0xe3,0x09,0xa8,0xe2,0xe8,0xa7,0xe1,
- 0xd7,0xa7,0x10,0x08,0x01,0xff,0xe7,0xb8,0xb7,0x00,0x01,0xff,0xe9,0x9b,0xbb,0x00,
- 0x83,0xe2,0xee,0xf5,0xe1,0xd8,0xf2,0xe0,0x55,0xf1,0xcf,0x86,0xd5,0x31,0xc4,0xe3,
- 0xd5,0xcb,0xe2,0xae,0xc9,0xe1,0x8f,0xc8,0xe0,0x1f,0xbf,0xcf,0x86,0xe5,0x12,0xbb,
- 0xe4,0x0b,0xba,0xe3,0xfc,0xb8,0xe2,0x53,0xb8,0xe1,0x2e,0xb8,0xe0,0x07,0xb8,0xcf,
- 0x86,0xe5,0xd4,0xb7,0x94,0x07,0x63,0xbf,0xb7,0x07,0x00,0x07,0x00,0xe4,0xc1,0xf0,
- 0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd2,0x0b,0xe1,0xd0,0xdd,0xcf,0x86,0xcf,
- 0x06,0x05,0x00,0xd1,0x0e,0xe0,0xbf,0xde,0xcf,0x86,0xe5,0x84,0xde,0xcf,0x06,0x11,
- 0x00,0xd0,0x0b,0xcf,0x86,0xe5,0xbf,0xde,0xcf,0x06,0x13,0x00,0xcf,0x86,0xd5,0x06,
- 0xcf,0x06,0x00,0x00,0xe4,0x5a,0xf0,0xe3,0x43,0xef,0xd2,0xa0,0xe1,0xf9,0xe2,0xd0,
- 0x21,0xcf,0x86,0xe5,0xfa,0xdf,0xe4,0x76,0xdf,0xe3,0x34,0xdf,0xe2,0x13,0xdf,0xe1,
- 0x01,0xdf,0x10,0x08,0x05,0xff,0xe4,0xb8,0xbd,0x00,0x05,0xff,0xe4,0xb8,0xb8,0x00,
- 0xcf,0x86,0xd5,0x1c,0xe4,0x56,0xe1,0xe3,0x15,0xe1,0xe2,0xf4,0xe0,0xe1,0xe3,0xe0,
- 0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,0x05,0xff,0xe5,0x93,0xb6,0x00,0xd4,0x34,
- 0xd3,0x18,0xe2,0xdd,0xe1,0xe1,0xcc,0xe1,0x10,0x09,0x05,0xff,0xf0,0xa1,0x9a,0xa8,
- 0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00,0xe2,0xfd,0xe1,0x91,0x11,0x10,0x09,0x05,
- 0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,0xe5,0xac,0x88,0x00,0x05,0xff,0xe5,0xac,
- 0xbe,0x00,0xe3,0x43,0xe2,0xd2,0x14,0xe1,0x12,0xe2,0x10,0x08,0x05,0xff,0xe5,0xaf,
- 0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,0x00,0xe1,0x1e,0xe2,0x10,0x08,0x05,0xff,
- 0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,0xa2,0x00,0xd1,0xd5,0xd0,0x6a,0xcf,0x86,
- 0xe5,0x73,0xe7,0xd4,0x19,0xe3,0xac,0xe6,0xe2,0x8a,0xe6,0xe1,0x79,0xe6,0x10,0x08,
- 0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,0xe6,0xb5,0xb7,0x00,0xd3,0x18,0xe2,0xf6,
- 0xe6,0xe1,0xe5,0xe6,0x10,0x09,0x05,0xff,0xf0,0xa3,0xbd,0x9e,0x00,0x05,0xff,0xf0,
- 0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0x0e,0xe7,0x10,0x08,0x05,0xff,0xe7,0x81,0xbd,
- 0x00,0x05,0xff,0xe7,0x81,0xb7,0x00,0xd1,0x11,0x10,0x08,0x05,0xff,0xe7,0x85,0x85,
- 0x00,0x05,0xff,0xf0,0xa4,0x89,0xa3,0x00,0x10,0x08,0x05,0xff,0xe7,0x86,0x9c,0x00,
- 0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86,0xe5,0x10,0xe9,0xd4,0x1a,0xe3,0x48,0xe8,
- 0xe2,0x2e,0xe8,0xe1,0x1b,0xe8,0x10,0x08,0x05,0xff,0xe7,0x9b,0xb4,0x00,0x05,0xff,
- 0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2,0x90,0xe8,0xe1,0x7e,0xe8,0x10,0x08,0x05,
- 0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,0x83,0xa3,0x00,0xd2,0x13,0xe1,0xac,0xe8,
- 0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,0x05,0xff,0xe7,0xa9,0x80,0x00,0xd1,0x12,
- 0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5,0xbc,0x00,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,
- 0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x05,0xff,0xe7,0xaa,0xae,0x00,0xe0,
- 0xc2,0xeb,0xcf,0x86,0xd5,0x1d,0xe4,0x37,0xea,0xe3,0xf3,0xe9,0xe2,0xd1,0xe9,0xe1,
- 0xc0,0xe9,0x10,0x09,0x05,0xff,0xf0,0xa3,0x8d,0x9f,0x00,0x05,0xff,0xe4,0x8f,0x95,
- 0x00,0xd4,0x19,0xe3,0xde,0xea,0xe2,0xba,0xea,0xe1,0xa9,0xea,0x10,0x08,0x05,0xff,
- 0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,0x8a,0x00,0xd3,0x18,0xe2,0x29,0xeb,0xe1,
- 0x18,0xeb,0x10,0x09,0x05,0xff,0xf0,0xa6,0xbe,0xb1,0x00,0x05,0xff,0xf0,0xa7,0x83,
- 0x92,0x00,0xd2,0x13,0xe1,0x41,0xeb,0x10,0x08,0x05,0xff,0xe8,0x9a,0x88,0x00,0x05,
- 0xff,0xe8,0x9c,0x8e,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x9c,0xa8,0x00,0x05,
- 0xff,0xe8,0x9d,0xab,0x00,0x10,0x08,0x05,0xff,0xe8,0x9e,0x86,0x00,0x05,0xff,0xe4,
- 0xb5,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x57,0x04,0x01,0x00,0xc6,0xd5,0x16,0xe4,0xc2,0x59,0xe3,0xfb,0x54,0xe2,0x74,0x4f,
+ 0xc1,0xe0,0xa0,0x4d,0xcf,0x86,0x65,0x84,0x4d,0x01,0x00,0xd4,0xb8,0xd3,0x27,0xe2,
+ 0x0c,0xa0,0xe1,0xdf,0x8d,0xe0,0x39,0x71,0xcf,0x86,0xc5,0xe4,0x98,0x69,0xe3,0xe3,
+ 0x64,0xe2,0x79,0x62,0xe1,0xac,0x61,0xe0,0x71,0x61,0xcf,0x86,0xe5,0x36,0x61,0x64,
+ 0x19,0x61,0x0b,0x00,0xd2,0x0e,0xe1,0xc2,0xa0,0xe0,0x3d,0xa0,0xcf,0x86,0xcf,0x06,
+ 0x01,0x00,0xd1,0x0c,0xe0,0xa1,0xa5,0xcf,0x86,0xcf,0x06,0x02,0xff,0xff,0xd0,0x08,
+ 0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01,0x00,0xe4,0x9e,
+ 0xb6,0xe3,0x18,0xae,0xd2,0x06,0xcf,0x06,0x01,0x00,0xe1,0x0a,0xaa,0xd0,0x21,0xcf,
+ 0x86,0xe5,0x04,0xa7,0xe4,0x83,0xa6,0xe3,0x42,0xa6,0xe2,0x21,0xa6,0xe1,0x10,0xa6,
+ 0x10,0x08,0x01,0xff,0xe8,0xb1,0x88,0x00,0x01,0xff,0xe6,0x9b,0xb4,0x00,0xcf,0x86,
+ 0xe5,0xe6,0xa8,0xd4,0x19,0xe3,0x25,0xa8,0xe2,0x04,0xa8,0xe1,0xf3,0xa7,0x10,0x08,
+ 0x01,0xff,0xe9,0xb9,0xbf,0x00,0x01,0xff,0xe8,0xab,0x96,0x00,0xe3,0x8c,0xa8,0xe2,
+ 0x6b,0xa8,0xe1,0x5a,0xa8,0x10,0x08,0x01,0xff,0xe7,0xb8,0xb7,0x00,0x01,0xff,0xe9,
+ 0x9b,0xbb,0x00,0x83,0xe2,0x9c,0xf6,0xe1,0x75,0xf3,0xe0,0xf2,0xf1,0xcf,0x86,0xd5,
+ 0x31,0xc4,0xe3,0x6d,0xcc,0xe2,0x46,0xca,0xe1,0x27,0xc9,0xe0,0xb7,0xbf,0xcf,0x86,
+ 0xe5,0xaa,0xbb,0xe4,0xa3,0xba,0xe3,0x94,0xb9,0xe2,0xeb,0xb8,0xe1,0xc6,0xb8,0xe0,
+ 0x9f,0xb8,0xcf,0x86,0xe5,0x6c,0xb8,0x94,0x07,0x63,0x57,0xb8,0x07,0x00,0x07,0x00,
+ 0xe4,0x5e,0xf1,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd2,0x0b,0xe1,0x6d,0xde,
+ 0xcf,0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0x5c,0xdf,0xcf,0x86,0xe5,0x21,0xdf,
+ 0xcf,0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0x5c,0xdf,0xcf,0x06,0x13,0x00,0xcf,
+ 0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0xf7,0xf0,0xe3,0xe0,0xef,0xd2,0xa0,0xe1,
+ 0x96,0xe3,0xd0,0x21,0xcf,0x86,0xe5,0x97,0xe0,0xe4,0x13,0xe0,0xe3,0xd1,0xdf,0xe2,
+ 0xb0,0xdf,0xe1,0x9e,0xdf,0x10,0x08,0x05,0xff,0xe4,0xb8,0xbd,0x00,0x05,0xff,0xe4,
+ 0xb8,0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0xf3,0xe1,0xe3,0xb2,0xe1,0xe2,0x91,0xe1,
+ 0xe1,0x80,0xe1,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,0x05,0xff,0xe5,0x93,0xb6,
+ 0x00,0xd4,0x34,0xd3,0x18,0xe2,0x7a,0xe2,0xe1,0x69,0xe2,0x10,0x09,0x05,0xff,0xf0,
+ 0xa1,0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00,0xe2,0x9a,0xe2,0x91,0x11,
+ 0x10,0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,0xe5,0xac,0x88,0x00,0x05,
+ 0xff,0xe5,0xac,0xbe,0x00,0xe3,0xe0,0xe2,0xd2,0x14,0xe1,0xaf,0xe2,0x10,0x08,0x05,
+ 0xff,0xe5,0xaf,0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,0x00,0xe1,0xbb,0xe2,0x10,
+ 0x08,0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,0xa2,0x00,0xd1,0xd5,0xd0,
+ 0x6a,0xcf,0x86,0xe5,0x10,0xe8,0xd4,0x19,0xe3,0x49,0xe7,0xe2,0x27,0xe7,0xe1,0x16,
+ 0xe7,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,0xe6,0xb5,0xb7,0x00,0xd3,
+ 0x18,0xe2,0x93,0xe7,0xe1,0x82,0xe7,0x10,0x09,0x05,0xff,0xf0,0xa3,0xbd,0x9e,0x00,
+ 0x05,0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0xab,0xe7,0x10,0x08,0x05,0xff,
+ 0xe7,0x81,0xbd,0x00,0x05,0xff,0xe7,0x81,0xb7,0x00,0xd1,0x11,0x10,0x08,0x05,0xff,
+ 0xe7,0x85,0x85,0x00,0x05,0xff,0xf0,0xa4,0x89,0xa3,0x00,0x10,0x08,0x05,0xff,0xe7,
+ 0x86,0x9c,0x00,0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86,0xe5,0xad,0xe9,0xd4,0x1a,
+ 0xe3,0xe5,0xe8,0xe2,0xcb,0xe8,0xe1,0xb8,0xe8,0x10,0x08,0x05,0xff,0xe7,0x9b,0xb4,
+ 0x00,0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2,0x2d,0xe9,0xe1,0x1b,0xe9,
+ 0x10,0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,0x83,0xa3,0x00,0xd2,0x13,
+ 0xe1,0x49,0xe9,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,0x05,0xff,0xe7,0xa9,0x80,
+ 0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5,0xbc,0x00,0x05,0xff,0xf0,0xa5,
+ 0xaa,0xa7,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x05,0xff,0xe7,0xaa,
+ 0xae,0x00,0xe0,0x5f,0xec,0xcf,0x86,0xd5,0x1d,0xe4,0xd4,0xea,0xe3,0x90,0xea,0xe2,
+ 0x6e,0xea,0xe1,0x5d,0xea,0x10,0x09,0x05,0xff,0xf0,0xa3,0x8d,0x9f,0x00,0x05,0xff,
+ 0xe4,0x8f,0x95,0x00,0xd4,0x19,0xe3,0x7b,0xeb,0xe2,0x57,0xeb,0xe1,0x46,0xeb,0x10,
+ 0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,0x8a,0x00,0xd3,0x18,0xe2,
+ 0xc6,0xeb,0xe1,0xb5,0xeb,0x10,0x09,0x05,0xff,0xf0,0xa6,0xbe,0xb1,0x00,0x05,0xff,
+ 0xf0,0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0xde,0xeb,0x10,0x08,0x05,0xff,0xe8,0x9a,
+ 0x88,0x00,0x05,0xff,0xe8,0x9c,0x8e,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x9c,
+ 0xa8,0x00,0x05,0xff,0xe8,0x9d,0xab,0x00,0x10,0x08,0x05,0xff,0xe8,0x9e,0x86,0x00,
+ 0x05,0xff,0xe4,0xb5,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* nfdicf_30200 */
- 0xd7,0x07,0x66,0x84,0x05,0x01,0x00,0xc6,0xd5,0x16,0xe4,0x96,0x13,0xe3,0x60,0x0e,
- 0xe2,0x49,0x07,0xc1,0xe0,0x4b,0x06,0xcf,0x86,0x65,0x2d,0x06,0x01,0x00,0xd4,0x2a,
- 0xe3,0xce,0x35,0xe2,0x02,0x9c,0xe1,0xca,0x2e,0xe0,0x28,0x1b,0xcf,0x86,0xc5,0xe4,
- 0xf9,0x65,0xe3,0x44,0x61,0xe2,0xda,0x5e,0xe1,0x0d,0x5e,0xe0,0xd2,0x5d,0xcf,0x86,
- 0xe5,0x97,0x5d,0x64,0x7a,0x5d,0x0b,0x00,0x83,0xe2,0xf6,0xf2,0xe1,0xe0,0xef,0xe0,
- 0x5d,0xee,0xcf,0x86,0xd5,0x31,0xc4,0xe3,0xdf,0x47,0xe2,0x80,0x46,0xe1,0x97,0xc5,
- 0xe0,0x27,0x45,0xcf,0x86,0xe5,0x19,0x43,0xe4,0x3a,0x40,0xe3,0x04,0xb6,0xe2,0x5b,
- 0xb5,0xe1,0x36,0xb5,0xe0,0x0f,0xb5,0xcf,0x86,0xe5,0xdc,0xb4,0x94,0x07,0x63,0xc7,
- 0xb4,0x07,0x00,0x07,0x00,0xe4,0xc9,0xed,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,
- 0xd2,0x0b,0xe1,0xd8,0xda,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0xc7,0xdb,
- 0xcf,0x86,0xe5,0x8c,0xdb,0xcf,0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0xc7,0xdb,
- 0xcf,0x06,0x13,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0x62,0xed,0xe3,
- 0x4b,0xec,0xd2,0xa0,0xe1,0x01,0xe0,0xd0,0x21,0xcf,0x86,0xe5,0x02,0xdd,0xe4,0x7e,
- 0xdc,0xe3,0x3c,0xdc,0xe2,0x1b,0xdc,0xe1,0x09,0xdc,0x10,0x08,0x05,0xff,0xe4,0xb8,
- 0xbd,0x00,0x05,0xff,0xe4,0xb8,0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0x5e,0xde,0xe3,
- 0x1d,0xde,0xe2,0xfc,0xdd,0xe1,0xeb,0xdd,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,
- 0x05,0xff,0xe5,0x93,0xb6,0x00,0xd4,0x34,0xd3,0x18,0xe2,0xe5,0xde,0xe1,0xd4,0xde,
+ 0xd7,0x07,0x66,0x84,0x05,0x01,0x00,0xc6,0xd5,0x16,0xe4,0x99,0x13,0xe3,0x63,0x0e,
+ 0xe2,0x4c,0x07,0xc1,0xe0,0x4e,0x06,0xcf,0x86,0x65,0x2d,0x06,0x01,0x00,0xd4,0x2a,
+ 0xe3,0xd0,0x35,0xe2,0x88,0x9c,0xe1,0xcd,0x2e,0xe0,0x2b,0x1b,0xcf,0x86,0xc5,0xe4,
+ 0x14,0x66,0xe3,0x5f,0x61,0xe2,0xf5,0x5e,0xe1,0x28,0x5e,0xe0,0xed,0x5d,0xcf,0x86,
+ 0xe5,0xb2,0x5d,0x64,0x95,0x5d,0x0b,0x00,0x83,0xe2,0xa7,0xf3,0xe1,0x80,0xf0,0xe0,
+ 0xfd,0xee,0xcf,0x86,0xd5,0x31,0xc4,0xe3,0xe2,0x47,0xe2,0x83,0x46,0xe1,0x32,0xc6,
+ 0xe0,0x2a,0x45,0xcf,0x86,0xe5,0x1c,0x43,0xe4,0x3d,0x40,0xe3,0x9f,0xb6,0xe2,0xf6,
+ 0xb5,0xe1,0xd1,0xb5,0xe0,0xaa,0xb5,0xcf,0x86,0xe5,0x77,0xb5,0x94,0x07,0x63,0x62,
+ 0xb5,0x07,0x00,0x07,0x00,0xe4,0x69,0xee,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,
+ 0xd2,0x0b,0xe1,0x78,0xdb,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0x67,0xdc,
+ 0xcf,0x86,0xe5,0x2c,0xdc,0xcf,0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0x67,0xdc,
+ 0xcf,0x06,0x13,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0x02,0xee,0xe3,
+ 0xeb,0xec,0xd2,0xa0,0xe1,0xa1,0xe0,0xd0,0x21,0xcf,0x86,0xe5,0xa2,0xdd,0xe4,0x1e,
+ 0xdd,0xe3,0xdc,0xdc,0xe2,0xbb,0xdc,0xe1,0xa9,0xdc,0x10,0x08,0x05,0xff,0xe4,0xb8,
+ 0xbd,0x00,0x05,0xff,0xe4,0xb8,0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0xfe,0xde,0xe3,
+ 0xbd,0xde,0xe2,0x9c,0xde,0xe1,0x8b,0xde,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,
+ 0x05,0xff,0xe5,0x93,0xb6,0x00,0xd4,0x34,0xd3,0x18,0xe2,0x85,0xdf,0xe1,0x74,0xdf,
0x10,0x09,0x05,0xff,0xf0,0xa1,0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00,
- 0xe2,0x05,0xdf,0x91,0x11,0x10,0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,
- 0xe5,0xac,0x88,0x00,0x05,0xff,0xe5,0xac,0xbe,0x00,0xe3,0x4b,0xdf,0xd2,0x14,0xe1,
- 0x1a,0xdf,0x10,0x08,0x05,0xff,0xe5,0xaf,0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,
- 0x00,0xe1,0x26,0xdf,0x10,0x08,0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,
- 0xa2,0x00,0xd1,0xd5,0xd0,0x6a,0xcf,0x86,0xe5,0x7b,0xe4,0xd4,0x19,0xe3,0xb4,0xe3,
- 0xe2,0x92,0xe3,0xe1,0x81,0xe3,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,
- 0xe6,0xb5,0xb7,0x00,0xd3,0x18,0xe2,0xfe,0xe3,0xe1,0xed,0xe3,0x10,0x09,0x05,0xff,
- 0xf0,0xa3,0xbd,0x9e,0x00,0x05,0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0x16,
+ 0xe2,0xa5,0xdf,0x91,0x11,0x10,0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,
+ 0xe5,0xac,0x88,0x00,0x05,0xff,0xe5,0xac,0xbe,0x00,0xe3,0xeb,0xdf,0xd2,0x14,0xe1,
+ 0xba,0xdf,0x10,0x08,0x05,0xff,0xe5,0xaf,0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,
+ 0x00,0xe1,0xc6,0xdf,0x10,0x08,0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,
+ 0xa2,0x00,0xd1,0xd5,0xd0,0x6a,0xcf,0x86,0xe5,0x1b,0xe5,0xd4,0x19,0xe3,0x54,0xe4,
+ 0xe2,0x32,0xe4,0xe1,0x21,0xe4,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,
+ 0xe6,0xb5,0xb7,0x00,0xd3,0x18,0xe2,0x9e,0xe4,0xe1,0x8d,0xe4,0x10,0x09,0x05,0xff,
+ 0xf0,0xa3,0xbd,0x9e,0x00,0x05,0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0xb6,
0xe4,0x10,0x08,0x05,0xff,0xe7,0x81,0xbd,0x00,0x05,0xff,0xe7,0x81,0xb7,0x00,0xd1,
0x11,0x10,0x08,0x05,0xff,0xe7,0x85,0x85,0x00,0x05,0xff,0xf0,0xa4,0x89,0xa3,0x00,
0x10,0x08,0x05,0xff,0xe7,0x86,0x9c,0x00,0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86,
- 0xe5,0x18,0xe6,0xd4,0x1a,0xe3,0x50,0xe5,0xe2,0x36,0xe5,0xe1,0x23,0xe5,0x10,0x08,
+ 0xe5,0xb8,0xe6,0xd4,0x1a,0xe3,0xf0,0xe5,0xe2,0xd6,0xe5,0xe1,0xc3,0xe5,0x10,0x08,
0x05,0xff,0xe7,0x9b,0xb4,0x00,0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2,
- 0x98,0xe5,0xe1,0x86,0xe5,0x10,0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,
- 0x83,0xa3,0x00,0xd2,0x13,0xe1,0xb4,0xe5,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,
+ 0x38,0xe6,0xe1,0x26,0xe6,0x10,0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,
+ 0x83,0xa3,0x00,0xd2,0x13,0xe1,0x54,0xe6,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,
0x05,0xff,0xe7,0xa9,0x80,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5,0xbc,
0x00,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa,0xa7,
- 0x00,0x05,0xff,0xe7,0xaa,0xae,0x00,0xe0,0xca,0xe8,0xcf,0x86,0xd5,0x1d,0xe4,0x3f,
- 0xe7,0xe3,0xfb,0xe6,0xe2,0xd9,0xe6,0xe1,0xc8,0xe6,0x10,0x09,0x05,0xff,0xf0,0xa3,
- 0x8d,0x9f,0x00,0x05,0xff,0xe4,0x8f,0x95,0x00,0xd4,0x19,0xe3,0xe6,0xe7,0xe2,0xc2,
- 0xe7,0xe1,0xb1,0xe7,0x10,0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,
- 0x8a,0x00,0xd3,0x18,0xe2,0x31,0xe8,0xe1,0x20,0xe8,0x10,0x09,0x05,0xff,0xf0,0xa6,
- 0xbe,0xb1,0x00,0x05,0xff,0xf0,0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0x49,0xe8,0x10,
+ 0x00,0x05,0xff,0xe7,0xaa,0xae,0x00,0xe0,0x6a,0xe9,0xcf,0x86,0xd5,0x1d,0xe4,0xdf,
+ 0xe7,0xe3,0x9b,0xe7,0xe2,0x79,0xe7,0xe1,0x68,0xe7,0x10,0x09,0x05,0xff,0xf0,0xa3,
+ 0x8d,0x9f,0x00,0x05,0xff,0xe4,0x8f,0x95,0x00,0xd4,0x19,0xe3,0x86,0xe8,0xe2,0x62,
+ 0xe8,0xe1,0x51,0xe8,0x10,0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,
+ 0x8a,0x00,0xd3,0x18,0xe2,0xd1,0xe8,0xe1,0xc0,0xe8,0x10,0x09,0x05,0xff,0xf0,0xa6,
+ 0xbe,0xb1,0x00,0x05,0xff,0xf0,0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0xe9,0xe8,0x10,
0x08,0x05,0xff,0xe8,0x9a,0x88,0x00,0x05,0xff,0xe8,0x9c,0x8e,0x00,0xd1,0x10,0x10,
0x08,0x05,0xff,0xe8,0x9c,0xa8,0x00,0x05,0xff,0xe8,0x9d,0xab,0x00,0x10,0x08,0x05,
0xff,0xe8,0x9e,0x86,0x00,0x05,0xff,0xe4,0xb5,0x97,0x00,0x00,0x00,0x00,0x00,0x00,
/* nfdi_30200 */
- 0x57,0x04,0x01,0x00,0xc6,0xd5,0x13,0xe4,0x68,0x53,0xe3,0xa2,0x4e,0xe2,0x1b,0x49,
- 0xc1,0xe0,0x47,0x47,0xcf,0x06,0x01,0x00,0xd4,0x2a,0xe3,0x99,0x99,0xe2,0x48,0x99,
- 0xe1,0x50,0x87,0xe0,0xe0,0x6a,0xcf,0x86,0xc5,0xe4,0x3f,0x63,0xe3,0x8a,0x5e,0xe2,
- 0x20,0x5c,0xe1,0x53,0x5b,0xe0,0x18,0x5b,0xcf,0x86,0xe5,0xdd,0x5a,0x64,0xc0,0x5a,
- 0x0b,0x00,0x83,0xe2,0x3c,0xf0,0xe1,0x26,0xed,0xe0,0xa3,0xeb,0xcf,0x86,0xd5,0x31,
- 0xc4,0xe3,0x23,0xc6,0xe2,0xfc,0xc3,0xe1,0xdd,0xc2,0xe0,0x6d,0xb9,0xcf,0x86,0xe5,
- 0x60,0xb5,0xe4,0x59,0xb4,0xe3,0x4a,0xb3,0xe2,0xa1,0xb2,0xe1,0x7c,0xb2,0xe0,0x55,
- 0xb2,0xcf,0x86,0xe5,0x22,0xb2,0x94,0x07,0x63,0x0d,0xb2,0x07,0x00,0x07,0x00,0xe4,
- 0x0f,0xeb,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd2,0x0b,0xe1,0x1e,0xd8,0xcf,
- 0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0x0d,0xd9,0xcf,0x86,0xe5,0xd2,0xd8,0xcf,
- 0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0x0d,0xd9,0xcf,0x06,0x13,0x00,0xcf,0x86,
- 0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0xa8,0xea,0xe3,0x91,0xe9,0xd2,0xa0,0xe1,0x47,
- 0xdd,0xd0,0x21,0xcf,0x86,0xe5,0x48,0xda,0xe4,0xc4,0xd9,0xe3,0x82,0xd9,0xe2,0x61,
- 0xd9,0xe1,0x4f,0xd9,0x10,0x08,0x05,0xff,0xe4,0xb8,0xbd,0x00,0x05,0xff,0xe4,0xb8,
- 0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0xa4,0xdb,0xe3,0x63,0xdb,0xe2,0x42,0xdb,0xe1,
- 0x31,0xdb,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,0x05,0xff,0xe5,0x93,0xb6,0x00,
- 0xd4,0x34,0xd3,0x18,0xe2,0x2b,0xdc,0xe1,0x1a,0xdc,0x10,0x09,0x05,0xff,0xf0,0xa1,
- 0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00,0xe2,0x4b,0xdc,0x91,0x11,0x10,
- 0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,0xe5,0xac,0x88,0x00,0x05,0xff,
- 0xe5,0xac,0xbe,0x00,0xe3,0x91,0xdc,0xd2,0x14,0xe1,0x60,0xdc,0x10,0x08,0x05,0xff,
- 0xe5,0xaf,0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,0x00,0xe1,0x6c,0xdc,0x10,0x08,
- 0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,0xa2,0x00,0xd1,0xd5,0xd0,0x6a,
- 0xcf,0x86,0xe5,0xc1,0xe1,0xd4,0x19,0xe3,0xfa,0xe0,0xe2,0xd8,0xe0,0xe1,0xc7,0xe0,
- 0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,0xe6,0xb5,0xb7,0x00,0xd3,0x18,
- 0xe2,0x44,0xe1,0xe1,0x33,0xe1,0x10,0x09,0x05,0xff,0xf0,0xa3,0xbd,0x9e,0x00,0x05,
- 0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0x5c,0xe1,0x10,0x08,0x05,0xff,0xe7,
- 0x81,0xbd,0x00,0x05,0xff,0xe7,0x81,0xb7,0x00,0xd1,0x11,0x10,0x08,0x05,0xff,0xe7,
- 0x85,0x85,0x00,0x05,0xff,0xf0,0xa4,0x89,0xa3,0x00,0x10,0x08,0x05,0xff,0xe7,0x86,
- 0x9c,0x00,0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86,0xe5,0x5e,0xe3,0xd4,0x1a,0xe3,
- 0x96,0xe2,0xe2,0x7c,0xe2,0xe1,0x69,0xe2,0x10,0x08,0x05,0xff,0xe7,0x9b,0xb4,0x00,
- 0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2,0xde,0xe2,0xe1,0xcc,0xe2,0x10,
- 0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,0x83,0xa3,0x00,0xd2,0x13,0xe1,
- 0xfa,0xe2,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,0x05,0xff,0xe7,0xa9,0x80,0x00,
- 0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5,0xbc,0x00,0x05,0xff,0xf0,0xa5,0xaa,
- 0xa7,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x05,0xff,0xe7,0xaa,0xae,
- 0x00,0xe0,0x10,0xe6,0xcf,0x86,0xd5,0x1d,0xe4,0x85,0xe4,0xe3,0x41,0xe4,0xe2,0x1f,
- 0xe4,0xe1,0x0e,0xe4,0x10,0x09,0x05,0xff,0xf0,0xa3,0x8d,0x9f,0x00,0x05,0xff,0xe4,
- 0x8f,0x95,0x00,0xd4,0x19,0xe3,0x2c,0xe5,0xe2,0x08,0xe5,0xe1,0xf7,0xe4,0x10,0x08,
- 0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,0x8a,0x00,0xd3,0x18,0xe2,0x77,
- 0xe5,0xe1,0x66,0xe5,0x10,0x09,0x05,0xff,0xf0,0xa6,0xbe,0xb1,0x00,0x05,0xff,0xf0,
- 0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0x8f,0xe5,0x10,0x08,0x05,0xff,0xe8,0x9a,0x88,
- 0x00,0x05,0xff,0xe8,0x9c,0x8e,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,0xe8,0x9c,0xa8,
- 0x00,0x05,0xff,0xe8,0x9d,0xab,0x00,0x10,0x08,0x05,0xff,0xe8,0x9e,0x86,0x00,0x05,
- 0xff,0xe4,0xb5,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x57,0x04,0x01,0x00,0xc6,0xd5,0x16,0xe4,0x82,0x53,0xe3,0xbb,0x4e,0xe2,0x34,0x49,
+ 0xc1,0xe0,0x60,0x47,0xcf,0x86,0x65,0x44,0x47,0x01,0x00,0xd4,0x2a,0xe3,0x1c,0x9a,
+ 0xe2,0xcb,0x99,0xe1,0x9e,0x87,0xe0,0xf8,0x6a,0xcf,0x86,0xc5,0xe4,0x57,0x63,0xe3,
+ 0xa2,0x5e,0xe2,0x38,0x5c,0xe1,0x6b,0x5b,0xe0,0x30,0x5b,0xcf,0x86,0xe5,0xf5,0x5a,
+ 0x64,0xd8,0x5a,0x0b,0x00,0x83,0xe2,0xea,0xf0,0xe1,0xc3,0xed,0xe0,0x40,0xec,0xcf,
+ 0x86,0xd5,0x31,0xc4,0xe3,0xbb,0xc6,0xe2,0x94,0xc4,0xe1,0x75,0xc3,0xe0,0x05,0xba,
+ 0xcf,0x86,0xe5,0xf8,0xb5,0xe4,0xf1,0xb4,0xe3,0xe2,0xb3,0xe2,0x39,0xb3,0xe1,0x14,
+ 0xb3,0xe0,0xed,0xb2,0xcf,0x86,0xe5,0xba,0xb2,0x94,0x07,0x63,0xa5,0xb2,0x07,0x00,
+ 0x07,0x00,0xe4,0xac,0xeb,0xd3,0x08,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd2,0x0b,0xe1,
+ 0xbb,0xd8,0xcf,0x86,0xcf,0x06,0x05,0x00,0xd1,0x0e,0xe0,0xaa,0xd9,0xcf,0x86,0xe5,
+ 0x6f,0xd9,0xcf,0x06,0x11,0x00,0xd0,0x0b,0xcf,0x86,0xe5,0xaa,0xd9,0xcf,0x06,0x13,
+ 0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0x45,0xeb,0xe3,0x2e,0xea,0xd2,
+ 0xa0,0xe1,0xe4,0xdd,0xd0,0x21,0xcf,0x86,0xe5,0xe5,0xda,0xe4,0x61,0xda,0xe3,0x1f,
+ 0xda,0xe2,0xfe,0xd9,0xe1,0xec,0xd9,0x10,0x08,0x05,0xff,0xe4,0xb8,0xbd,0x00,0x05,
+ 0xff,0xe4,0xb8,0xb8,0x00,0xcf,0x86,0xd5,0x1c,0xe4,0x41,0xdc,0xe3,0x00,0xdc,0xe2,
+ 0xdf,0xdb,0xe1,0xce,0xdb,0x10,0x08,0x05,0xff,0xe5,0x92,0xa2,0x00,0x05,0xff,0xe5,
+ 0x93,0xb6,0x00,0xd4,0x34,0xd3,0x18,0xe2,0xc8,0xdc,0xe1,0xb7,0xdc,0x10,0x09,0x05,
+ 0xff,0xf0,0xa1,0x9a,0xa8,0x00,0x05,0xff,0xf0,0xa1,0x9b,0xaa,0x00,0xe2,0xe8,0xdc,
+ 0x91,0x11,0x10,0x09,0x05,0xff,0xf0,0xa1,0x8d,0xaa,0x00,0x05,0xff,0xe5,0xac,0x88,
+ 0x00,0x05,0xff,0xe5,0xac,0xbe,0x00,0xe3,0x2e,0xdd,0xd2,0x14,0xe1,0xfd,0xdc,0x10,
+ 0x08,0x05,0xff,0xe5,0xaf,0xb3,0x00,0x05,0xff,0xf0,0xa1,0xac,0x98,0x00,0xe1,0x09,
+ 0xdd,0x10,0x08,0x05,0xff,0xe5,0xbc,0xb3,0x00,0x05,0xff,0xe5,0xb0,0xa2,0x00,0xd1,
+ 0xd5,0xd0,0x6a,0xcf,0x86,0xe5,0x5e,0xe2,0xd4,0x19,0xe3,0x97,0xe1,0xe2,0x75,0xe1,
+ 0xe1,0x64,0xe1,0x10,0x08,0x05,0xff,0xe6,0xb4,0xbe,0x00,0x05,0xff,0xe6,0xb5,0xb7,
+ 0x00,0xd3,0x18,0xe2,0xe1,0xe1,0xe1,0xd0,0xe1,0x10,0x09,0x05,0xff,0xf0,0xa3,0xbd,
+ 0x9e,0x00,0x05,0xff,0xf0,0xa3,0xbe,0x8e,0x00,0xd2,0x13,0xe1,0xf9,0xe1,0x10,0x08,
+ 0x05,0xff,0xe7,0x81,0xbd,0x00,0x05,0xff,0xe7,0x81,0xb7,0x00,0xd1,0x11,0x10,0x08,
+ 0x05,0xff,0xe7,0x85,0x85,0x00,0x05,0xff,0xf0,0xa4,0x89,0xa3,0x00,0x10,0x08,0x05,
+ 0xff,0xe7,0x86,0x9c,0x00,0x05,0xff,0xe4,0x8e,0xab,0x00,0xcf,0x86,0xe5,0xfb,0xe3,
+ 0xd4,0x1a,0xe3,0x33,0xe3,0xe2,0x19,0xe3,0xe1,0x06,0xe3,0x10,0x08,0x05,0xff,0xe7,
+ 0x9b,0xb4,0x00,0x05,0xff,0xf0,0xa5,0x83,0xb3,0x00,0xd3,0x16,0xe2,0x7b,0xe3,0xe1,
+ 0x69,0xe3,0x10,0x08,0x05,0xff,0xe7,0xa3,0x8c,0x00,0x05,0xff,0xe4,0x83,0xa3,0x00,
+ 0xd2,0x13,0xe1,0x97,0xe3,0x10,0x08,0x05,0xff,0xe4,0x84,0xaf,0x00,0x05,0xff,0xe7,
+ 0xa9,0x80,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0xa5,0xa5,0xbc,0x00,0x05,0xff,
+ 0xf0,0xa5,0xaa,0xa7,0x00,0x10,0x09,0x05,0xff,0xf0,0xa5,0xaa,0xa7,0x00,0x05,0xff,
+ 0xe7,0xaa,0xae,0x00,0xe0,0xad,0xe6,0xcf,0x86,0xd5,0x1d,0xe4,0x22,0xe5,0xe3,0xde,
+ 0xe4,0xe2,0xbc,0xe4,0xe1,0xab,0xe4,0x10,0x09,0x05,0xff,0xf0,0xa3,0x8d,0x9f,0x00,
+ 0x05,0xff,0xe4,0x8f,0x95,0x00,0xd4,0x19,0xe3,0xc9,0xe5,0xe2,0xa5,0xe5,0xe1,0x94,
+ 0xe5,0x10,0x08,0x05,0xff,0xe8,0x8d,0x93,0x00,0x05,0xff,0xe8,0x8f,0x8a,0x00,0xd3,
+ 0x18,0xe2,0x14,0xe6,0xe1,0x03,0xe6,0x10,0x09,0x05,0xff,0xf0,0xa6,0xbe,0xb1,0x00,
+ 0x05,0xff,0xf0,0xa7,0x83,0x92,0x00,0xd2,0x13,0xe1,0x2c,0xe6,0x10,0x08,0x05,0xff,
+ 0xe8,0x9a,0x88,0x00,0x05,0xff,0xe8,0x9c,0x8e,0x00,0xd1,0x10,0x10,0x08,0x05,0xff,
+ 0xe8,0x9c,0xa8,0x00,0x05,0xff,0xe8,0x9d,0xab,0x00,0x10,0x08,0x05,0xff,0xe8,0x9e,
+ 0x86,0x00,0x05,0xff,0xe4,0xb5,0x97,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
/* nfdicf_c0100 */
0xd7,0xb0,0x56,0x04,0x01,0x00,0x95,0xa8,0xd4,0x5e,0xd3,0x2e,0xd2,0x16,0xd1,0x0a,
0x10,0x04,0x01,0x00,0x01,0xff,0x61,0x00,0x10,0x06,0x01,0xff,0x62,0x00,0x01,0xff,
@@ -299,3174 +299,3184 @@ static const unsigned char utf8data[64080] = {
0xd1,0x0c,0x10,0x06,0x01,0xff,0x74,0x00,0x01,0xff,0x75,0x00,0x10,0x06,0x01,0xff,
0x76,0x00,0x01,0xff,0x77,0x00,0x92,0x16,0xd1,0x0c,0x10,0x06,0x01,0xff,0x78,0x00,
0x01,0xff,0x79,0x00,0x10,0x06,0x01,0xff,0x7a,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
- 0xc6,0xe5,0xf6,0x14,0xe4,0x6c,0x0d,0xe3,0x36,0x08,0xe2,0x1f,0x01,0xc1,0xd0,0x21,
- 0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x93,0x13,0x52,0x04,0x01,0x00,
- 0x91,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xce,0xbc,0x00,0x01,0x00,0x01,0x00,0xcf,
- 0x86,0xe5,0x9d,0x44,0xd4,0x7f,0xd3,0x3f,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x61,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x61,0xcc,
- 0x82,0x00,0x01,0xff,0x61,0xcc,0x83,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,
- 0x88,0x00,0x01,0xff,0x61,0xcc,0x8a,0x00,0x10,0x07,0x01,0xff,0xc3,0xa6,0x00,0x01,
- 0xff,0x63,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0x80,
- 0x00,0x01,0xff,0x65,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x82,0x00,0x01,
- 0xff,0x65,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x80,0x00,0x01,
- 0xff,0x69,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x69,0xcc,0x82,0x00,0x01,0xff,0x69,
- 0xcc,0x88,0x00,0xd3,0x3b,0xd2,0x1f,0xd1,0x0f,0x10,0x07,0x01,0xff,0xc3,0xb0,0x00,
- 0x01,0xff,0x6e,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x80,0x00,0x01,0xff,
- 0x6f,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x82,0x00,0x01,0xff,
- 0x6f,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x88,0x00,0x01,0x00,0xd2,0x1f,
- 0xd1,0x0f,0x10,0x07,0x01,0xff,0xc3,0xb8,0x00,0x01,0xff,0x75,0xcc,0x80,0x00,0x10,
- 0x08,0x01,0xff,0x75,0xcc,0x81,0x00,0x01,0xff,0x75,0xcc,0x82,0x00,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0x75,0xcc,0x88,0x00,0x01,0xff,0x79,0xcc,0x81,0x00,0x10,0x07,0x01,
- 0xff,0xc3,0xbe,0x00,0x01,0xff,0x73,0x73,0x00,0xe1,0xd4,0x03,0xe0,0xeb,0x01,0xcf,
- 0x86,0xd5,0xfb,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,
- 0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x61,0xcc,0x86,
- 0x00,0x01,0xff,0x61,0xcc,0x86,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0xa8,
- 0x00,0x01,0xff,0x61,0xcc,0xa8,0x00,0x10,0x08,0x01,0xff,0x63,0xcc,0x81,0x00,0x01,
- 0xff,0x63,0xcc,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x63,0xcc,0x82,
- 0x00,0x01,0xff,0x63,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x63,0xcc,0x87,0x00,0x01,
- 0xff,0x63,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x63,0xcc,0x8c,0x00,0x01,
- 0xff,0x63,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0x8c,0x00,0x01,0xff,0x64,
- 0xcc,0x8c,0x00,0xd3,0x3b,0xd2,0x1b,0xd1,0x0b,0x10,0x07,0x01,0xff,0xc4,0x91,0x00,
- 0x01,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x84,0x00,0x01,0xff,0x65,0xcc,0x84,0x00,
- 0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0x86,0x00,0x01,0xff,0x65,0xcc,0x86,0x00,
- 0x10,0x08,0x01,0xff,0x65,0xcc,0x87,0x00,0x01,0xff,0x65,0xcc,0x87,0x00,0xd2,0x20,
- 0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0xa8,0x00,0x01,0xff,0x65,0xcc,0xa8,0x00,
- 0x10,0x08,0x01,0xff,0x65,0xcc,0x8c,0x00,0x01,0xff,0x65,0xcc,0x8c,0x00,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0x67,0xcc,0x82,0x00,0x01,0xff,0x67,0xcc,0x82,0x00,0x10,0x08,
- 0x01,0xff,0x67,0xcc,0x86,0x00,0x01,0xff,0x67,0xcc,0x86,0x00,0xd4,0x7b,0xd3,0x3b,
- 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x67,0xcc,0x87,0x00,0x01,0xff,0x67,0xcc,
- 0x87,0x00,0x10,0x08,0x01,0xff,0x67,0xcc,0xa7,0x00,0x01,0xff,0x67,0xcc,0xa7,0x00,
- 0xd1,0x10,0x10,0x08,0x01,0xff,0x68,0xcc,0x82,0x00,0x01,0xff,0x68,0xcc,0x82,0x00,
- 0x10,0x07,0x01,0xff,0xc4,0xa7,0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0x69,0xcc,0x83,0x00,0x01,0xff,0x69,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x69,
- 0xcc,0x84,0x00,0x01,0xff,0x69,0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,
- 0xcc,0x86,0x00,0x01,0xff,0x69,0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x69,0xcc,0xa8,
- 0x00,0x01,0xff,0x69,0xcc,0xa8,0x00,0xd3,0x37,0xd2,0x17,0xd1,0x0c,0x10,0x08,0x01,
- 0xff,0x69,0xcc,0x87,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xc4,0xb3,0x00,0x01,0x00,
- 0xd1,0x10,0x10,0x08,0x01,0xff,0x6a,0xcc,0x82,0x00,0x01,0xff,0x6a,0xcc,0x82,0x00,
- 0x10,0x08,0x01,0xff,0x6b,0xcc,0xa7,0x00,0x01,0xff,0x6b,0xcc,0xa7,0x00,0xd2,0x1c,
- 0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x6c,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,
- 0x6c,0xcc,0x81,0x00,0x01,0xff,0x6c,0xcc,0xa7,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x6c,0xcc,0xa7,0x00,0x01,0xff,0x6c,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x6c,0xcc,
- 0x8c,0x00,0x01,0xff,0xc5,0x80,0x00,0xcf,0x86,0xd5,0xed,0xd4,0x72,0xd3,0x37,0xd2,
- 0x17,0xd1,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xc5,0x82,0x00,0x10,0x04,0x01,0x00,
- 0x01,0xff,0x6e,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e,0xcc,0x81,0x00,
- 0x01,0xff,0x6e,0xcc,0xa7,0x00,0x10,0x08,0x01,0xff,0x6e,0xcc,0xa7,0x00,0x01,0xff,
- 0x6e,0xcc,0x8c,0x00,0xd2,0x1b,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e,0xcc,0x8c,0x00,
- 0x01,0xff,0xca,0xbc,0x6e,0x00,0x10,0x07,0x01,0xff,0xc5,0x8b,0x00,0x01,0x00,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc,0x84,0x00,0x10,
- 0x08,0x01,0xff,0x6f,0xcc,0x86,0x00,0x01,0xff,0x6f,0xcc,0x86,0x00,0xd3,0x3b,0xd2,
- 0x1b,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x8b,0x00,0x01,0xff,0x6f,0xcc,0x8b,
- 0x00,0x10,0x07,0x01,0xff,0xc5,0x93,0x00,0x01,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x72,0xcc,0x81,0x00,0x01,0xff,0x72,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x72,0xcc,
- 0xa7,0x00,0x01,0xff,0x72,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x72,0xcc,0x8c,0x00,0x01,0xff,0x72,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x73,0xcc,
- 0x81,0x00,0x01,0xff,0x73,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x73,0xcc,
- 0x82,0x00,0x01,0xff,0x73,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x73,0xcc,0xa7,0x00,
- 0x01,0xff,0x73,0xcc,0xa7,0x00,0xd4,0x7b,0xd3,0x3b,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x73,0xcc,0x8c,0x00,0x01,0xff,0x73,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,
- 0x74,0xcc,0xa7,0x00,0x01,0xff,0x74,0xcc,0xa7,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x74,0xcc,0x8c,0x00,0x01,0xff,0x74,0xcc,0x8c,0x00,0x10,0x07,0x01,0xff,0xc5,0xa7,
- 0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x83,0x00,0x01,
- 0xff,0x75,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x84,0x00,0x01,0xff,0x75,
- 0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x86,0x00,0x01,0xff,0x75,
- 0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x8a,0x00,0x01,0xff,0x75,0xcc,0x8a,
- 0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x8b,0x00,0x01,
- 0xff,0x75,0xcc,0x8b,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0xa8,0x00,0x01,0xff,0x75,
- 0xcc,0xa8,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x82,0x00,0x01,0xff,0x77,
- 0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x79,0xcc,0x82,0x00,0x01,0xff,0x79,0xcc,0x82,
- 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x79,0xcc,0x88,0x00,0x01,0xff,0x7a,
- 0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x81,0x00,0x01,0xff,0x7a,0xcc,0x87,
- 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x7a,0xcc,0x87,0x00,0x01,0xff,0x7a,0xcc,0x8c,
- 0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x8c,0x00,0x01,0xff,0x73,0x00,0xe0,0x65,0x01,
- 0xcf,0x86,0xd5,0xb4,0xd4,0x5a,0xd3,0x2f,0xd2,0x16,0xd1,0x0b,0x10,0x04,0x01,0x00,
- 0x01,0xff,0xc9,0x93,0x00,0x10,0x07,0x01,0xff,0xc6,0x83,0x00,0x01,0x00,0xd1,0x0b,
- 0x10,0x07,0x01,0xff,0xc6,0x85,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xc9,0x94,0x00,
- 0x01,0xff,0xc6,0x88,0x00,0xd2,0x19,0xd1,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xc9,
- 0x96,0x00,0x10,0x07,0x01,0xff,0xc9,0x97,0x00,0x01,0xff,0xc6,0x8c,0x00,0x51,0x04,
- 0x01,0x00,0x10,0x07,0x01,0xff,0xc7,0x9d,0x00,0x01,0xff,0xc9,0x99,0x00,0xd3,0x32,
- 0xd2,0x19,0xd1,0x0e,0x10,0x07,0x01,0xff,0xc9,0x9b,0x00,0x01,0xff,0xc6,0x92,0x00,
- 0x10,0x04,0x01,0x00,0x01,0xff,0xc9,0xa0,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xc9,
- 0xa3,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xc9,0xa9,0x00,0x01,0xff,0xc9,0xa8,0x00,
- 0xd2,0x0f,0x91,0x0b,0x10,0x07,0x01,0xff,0xc6,0x99,0x00,0x01,0x00,0x01,0x00,0xd1,
- 0x0e,0x10,0x07,0x01,0xff,0xc9,0xaf,0x00,0x01,0xff,0xc9,0xb2,0x00,0x10,0x04,0x01,
- 0x00,0x01,0xff,0xc9,0xb5,0x00,0xd4,0x5d,0xd3,0x34,0xd2,0x1b,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x6f,0xcc,0x9b,0x00,0x01,0xff,0x6f,0xcc,0x9b,0x00,0x10,0x07,0x01,0xff,
- 0xc6,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xc6,0xa5,0x00,0x01,0x00,
- 0x10,0x07,0x01,0xff,0xca,0x80,0x00,0x01,0xff,0xc6,0xa8,0x00,0xd2,0x0f,0x91,0x0b,
- 0x10,0x04,0x01,0x00,0x01,0xff,0xca,0x83,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,
- 0xff,0xc6,0xad,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xca,0x88,0x00,0x01,0xff,0x75,
- 0xcc,0x9b,0x00,0xd3,0x33,0xd2,0x1d,0xd1,0x0f,0x10,0x08,0x01,0xff,0x75,0xcc,0x9b,
- 0x00,0x01,0xff,0xca,0x8a,0x00,0x10,0x07,0x01,0xff,0xca,0x8b,0x00,0x01,0xff,0xc6,
- 0xb4,0x00,0xd1,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xc6,0xb6,0x00,0x10,0x04,0x01,
- 0x00,0x01,0xff,0xca,0x92,0x00,0xd2,0x0f,0x91,0x0b,0x10,0x07,0x01,0xff,0xc6,0xb9,
- 0x00,0x01,0x00,0x01,0x00,0x91,0x0b,0x10,0x07,0x01,0xff,0xc6,0xbd,0x00,0x01,0x00,
- 0x01,0x00,0xcf,0x86,0xd5,0xd4,0xd4,0x44,0xd3,0x16,0x52,0x04,0x01,0x00,0x51,0x07,
- 0x01,0xff,0xc7,0x86,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xc7,0x89,0x00,0xd2,0x12,
- 0x91,0x0b,0x10,0x07,0x01,0xff,0xc7,0x89,0x00,0x01,0x00,0x01,0xff,0xc7,0x8c,0x00,
- 0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x61,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,
- 0x61,0xcc,0x8c,0x00,0x01,0xff,0x69,0xcc,0x8c,0x00,0xd3,0x46,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0x69,0xcc,0x8c,0x00,0x01,0xff,0x6f,0xcc,0x8c,0x00,0x10,0x08,
- 0x01,0xff,0x6f,0xcc,0x8c,0x00,0x01,0xff,0x75,0xcc,0x8c,0x00,0xd1,0x12,0x10,0x08,
- 0x01,0xff,0x75,0xcc,0x8c,0x00,0x01,0xff,0x75,0xcc,0x88,0xcc,0x84,0x00,0x10,0x0a,
- 0x01,0xff,0x75,0xcc,0x88,0xcc,0x84,0x00,0x01,0xff,0x75,0xcc,0x88,0xcc,0x81,0x00,
- 0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x81,0x00,0x01,0xff,
- 0x75,0xcc,0x88,0xcc,0x8c,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x8c,0x00,
- 0x01,0xff,0x75,0xcc,0x88,0xcc,0x80,0x00,0xd1,0x0e,0x10,0x0a,0x01,0xff,0x75,0xcc,
- 0x88,0xcc,0x80,0x00,0x01,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0x88,0xcc,0x84,0x00,
- 0x01,0xff,0x61,0xcc,0x88,0xcc,0x84,0x00,0xd4,0x87,0xd3,0x41,0xd2,0x26,0xd1,0x14,
- 0x10,0x0a,0x01,0xff,0x61,0xcc,0x87,0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x87,0xcc,
- 0x84,0x00,0x10,0x09,0x01,0xff,0xc3,0xa6,0xcc,0x84,0x00,0x01,0xff,0xc3,0xa6,0xcc,
- 0x84,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xc7,0xa5,0x00,0x01,0x00,0x10,0x08,0x01,
- 0xff,0x67,0xcc,0x8c,0x00,0x01,0xff,0x67,0xcc,0x8c,0x00,0xd2,0x20,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0x6b,0xcc,0x8c,0x00,0x01,0xff,0x6b,0xcc,0x8c,0x00,0x10,0x08,0x01,
- 0xff,0x6f,0xcc,0xa8,0x00,0x01,0xff,0x6f,0xcc,0xa8,0x00,0xd1,0x14,0x10,0x0a,0x01,
- 0xff,0x6f,0xcc,0xa8,0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc,0xa8,0xcc,0x84,0x00,0x10,
- 0x09,0x01,0xff,0xca,0x92,0xcc,0x8c,0x00,0x01,0xff,0xca,0x92,0xcc,0x8c,0x00,0xd3,
- 0x38,0xd2,0x1a,0xd1,0x0f,0x10,0x08,0x01,0xff,0x6a,0xcc,0x8c,0x00,0x01,0xff,0xc7,
- 0xb3,0x00,0x10,0x07,0x01,0xff,0xc7,0xb3,0x00,0x01,0x00,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0x67,0xcc,0x81,0x00,0x01,0xff,0x67,0xcc,0x81,0x00,0x10,0x07,0x04,0xff,0xc6,
- 0x95,0x00,0x04,0xff,0xc6,0xbf,0x00,0xd2,0x24,0xd1,0x10,0x10,0x08,0x04,0xff,0x6e,
- 0xcc,0x80,0x00,0x04,0xff,0x6e,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0x8a,
- 0xcc,0x81,0x00,0x01,0xff,0x61,0xcc,0x8a,0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,0x01,
- 0xff,0xc3,0xa6,0xcc,0x81,0x00,0x01,0xff,0xc3,0xa6,0xcc,0x81,0x00,0x10,0x09,0x01,
- 0xff,0xc3,0xb8,0xcc,0x81,0x00,0x01,0xff,0xc3,0xb8,0xcc,0x81,0x00,0xe2,0x31,0x02,
- 0xe1,0xad,0x44,0xe0,0xc8,0x01,0xcf,0x86,0xd5,0xfb,0xd4,0x80,0xd3,0x40,0xd2,0x20,
- 0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0x8f,0x00,0x01,0xff,0x61,0xcc,0x8f,0x00,
- 0x10,0x08,0x01,0xff,0x61,0xcc,0x91,0x00,0x01,0xff,0x61,0xcc,0x91,0x00,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0x65,0xcc,0x8f,0x00,0x01,0xff,0x65,0xcc,0x8f,0x00,0x10,0x08,
- 0x01,0xff,0x65,0xcc,0x91,0x00,0x01,0xff,0x65,0xcc,0x91,0x00,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0x69,0xcc,0x8f,0x00,0x01,0xff,0x69,0xcc,0x8f,0x00,0x10,0x08,
- 0x01,0xff,0x69,0xcc,0x91,0x00,0x01,0xff,0x69,0xcc,0x91,0x00,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x6f,0xcc,0x8f,0x00,0x01,0xff,0x6f,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,
- 0x6f,0xcc,0x91,0x00,0x01,0xff,0x6f,0xcc,0x91,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0x72,0xcc,0x8f,0x00,0x01,0xff,0x72,0xcc,0x8f,0x00,0x10,0x08,
- 0x01,0xff,0x72,0xcc,0x91,0x00,0x01,0xff,0x72,0xcc,0x91,0x00,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x75,0xcc,0x8f,0x00,0x01,0xff,0x75,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,
- 0x75,0xcc,0x91,0x00,0x01,0xff,0x75,0xcc,0x91,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x04,0xff,0x73,0xcc,0xa6,0x00,0x04,0xff,0x73,0xcc,0xa6,0x00,0x10,0x08,0x04,0xff,
- 0x74,0xcc,0xa6,0x00,0x04,0xff,0x74,0xcc,0xa6,0x00,0xd1,0x0b,0x10,0x07,0x04,0xff,
- 0xc8,0x9d,0x00,0x04,0x00,0x10,0x08,0x04,0xff,0x68,0xcc,0x8c,0x00,0x04,0xff,0x68,
- 0xcc,0x8c,0x00,0xd4,0x79,0xd3,0x31,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x06,0xff,0xc6,
- 0x9e,0x00,0x07,0x00,0x10,0x07,0x04,0xff,0xc8,0xa3,0x00,0x04,0x00,0xd1,0x0b,0x10,
- 0x07,0x04,0xff,0xc8,0xa5,0x00,0x04,0x00,0x10,0x08,0x04,0xff,0x61,0xcc,0x87,0x00,
- 0x04,0xff,0x61,0xcc,0x87,0x00,0xd2,0x24,0xd1,0x10,0x10,0x08,0x04,0xff,0x65,0xcc,
- 0xa7,0x00,0x04,0xff,0x65,0xcc,0xa7,0x00,0x10,0x0a,0x04,0xff,0x6f,0xcc,0x88,0xcc,
- 0x84,0x00,0x04,0xff,0x6f,0xcc,0x88,0xcc,0x84,0x00,0xd1,0x14,0x10,0x0a,0x04,0xff,
- 0x6f,0xcc,0x83,0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc,0x83,0xcc,0x84,0x00,0x10,0x08,
- 0x04,0xff,0x6f,0xcc,0x87,0x00,0x04,0xff,0x6f,0xcc,0x87,0x00,0xd3,0x27,0xe2,0x0b,
- 0x43,0xd1,0x14,0x10,0x0a,0x04,0xff,0x6f,0xcc,0x87,0xcc,0x84,0x00,0x04,0xff,0x6f,
- 0xcc,0x87,0xcc,0x84,0x00,0x10,0x08,0x04,0xff,0x79,0xcc,0x84,0x00,0x04,0xff,0x79,
- 0xcc,0x84,0x00,0xd2,0x13,0x51,0x04,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0xa5,
- 0x00,0x08,0xff,0xc8,0xbc,0x00,0xd1,0x0b,0x10,0x04,0x08,0x00,0x08,0xff,0xc6,0x9a,
- 0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0xa6,0x00,0x08,0x00,0xcf,0x86,0x95,0x5f,0x94,
- 0x5b,0xd3,0x2f,0xd2,0x16,0xd1,0x0b,0x10,0x04,0x08,0x00,0x08,0xff,0xc9,0x82,0x00,
- 0x10,0x04,0x09,0x00,0x09,0xff,0xc6,0x80,0x00,0xd1,0x0e,0x10,0x07,0x09,0xff,0xca,
- 0x89,0x00,0x09,0xff,0xca,0x8c,0x00,0x10,0x07,0x09,0xff,0xc9,0x87,0x00,0x09,0x00,
- 0xd2,0x16,0xd1,0x0b,0x10,0x07,0x09,0xff,0xc9,0x89,0x00,0x09,0x00,0x10,0x07,0x09,
- 0xff,0xc9,0x8b,0x00,0x09,0x00,0xd1,0x0b,0x10,0x07,0x09,0xff,0xc9,0x8d,0x00,0x09,
- 0x00,0x10,0x07,0x09,0xff,0xc9,0x8f,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0xd1,0x8b,
- 0xd0,0x0c,0xcf,0x86,0xe5,0xfa,0x42,0x64,0xd9,0x42,0x01,0xe6,0xcf,0x86,0xd5,0x2a,
- 0xe4,0x82,0x43,0xe3,0x69,0x43,0xd2,0x11,0xe1,0x48,0x43,0x10,0x07,0x01,0xff,0xcc,
- 0x80,0x00,0x01,0xff,0xcc,0x81,0x00,0xe1,0x4f,0x43,0x10,0x09,0x01,0xff,0xcc,0x88,
- 0xcc,0x81,0x00,0x01,0xff,0xce,0xb9,0x00,0xd4,0x0f,0x93,0x0b,0x92,0x07,0x61,0x94,
- 0x43,0x01,0xea,0x06,0xe6,0x06,0xe6,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x0a,
- 0xff,0xcd,0xb1,0x00,0x0a,0x00,0x10,0x07,0x0a,0xff,0xcd,0xb3,0x00,0x0a,0x00,0xd1,
- 0x0b,0x10,0x07,0x01,0xff,0xca,0xb9,0x00,0x01,0x00,0x10,0x07,0x0a,0xff,0xcd,0xb7,
- 0x00,0x0a,0x00,0xd2,0x07,0x61,0x80,0x43,0x00,0x00,0x51,0x04,0x09,0x00,0x10,0x06,
- 0x01,0xff,0x3b,0x00,0x10,0xff,0xcf,0xb3,0x00,0xe0,0x31,0x01,0xcf,0x86,0xd5,0xd3,
- 0xd4,0x5f,0xd3,0x21,0x52,0x04,0x00,0x00,0xd1,0x0d,0x10,0x04,0x01,0x00,0x01,0xff,
- 0xc2,0xa8,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x81,0x00,0x01,0xff,
- 0xc2,0xb7,0x00,0xd2,0x1f,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc,0x81,0x00,
- 0x01,0xff,0xce,0xb7,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x81,0x00,
- 0x00,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00,0x00,0x00,0x10,
- 0x09,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0x01,0xff,0xcf,0x89,0xcc,0x81,0x00,0xd3,
- 0x3c,0xd2,0x20,0xd1,0x12,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x88,0xcc,0x81,0x00,
- 0x01,0xff,0xce,0xb1,0x00,0x10,0x07,0x01,0xff,0xce,0xb2,0x00,0x01,0xff,0xce,0xb3,
- 0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xce,0xb4,0x00,0x01,0xff,0xce,0xb5,0x00,0x10,
- 0x07,0x01,0xff,0xce,0xb6,0x00,0x01,0xff,0xce,0xb7,0x00,0xd2,0x1c,0xd1,0x0e,0x10,
- 0x07,0x01,0xff,0xce,0xb8,0x00,0x01,0xff,0xce,0xb9,0x00,0x10,0x07,0x01,0xff,0xce,
- 0xba,0x00,0x01,0xff,0xce,0xbb,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xce,0xbc,0x00,
- 0x01,0xff,0xce,0xbd,0x00,0x10,0x07,0x01,0xff,0xce,0xbe,0x00,0x01,0xff,0xce,0xbf,
- 0x00,0xe4,0x6e,0x43,0xd3,0x35,0xd2,0x19,0xd1,0x0e,0x10,0x07,0x01,0xff,0xcf,0x80,
- 0x00,0x01,0xff,0xcf,0x81,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xcf,0x83,0x00,0xd1,
- 0x0e,0x10,0x07,0x01,0xff,0xcf,0x84,0x00,0x01,0xff,0xcf,0x85,0x00,0x10,0x07,0x01,
- 0xff,0xcf,0x86,0x00,0x01,0xff,0xcf,0x87,0x00,0xe2,0x14,0x43,0xd1,0x0e,0x10,0x07,
- 0x01,0xff,0xcf,0x88,0x00,0x01,0xff,0xcf,0x89,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,
- 0xcc,0x88,0x00,0x01,0xff,0xcf,0x85,0xcc,0x88,0x00,0xcf,0x86,0xd5,0x94,0xd4,0x3c,
- 0xd3,0x13,0x92,0x0f,0x51,0x04,0x01,0x00,0x10,0x07,0x01,0xff,0xcf,0x83,0x00,0x01,
- 0x00,0x01,0x00,0xd2,0x07,0x61,0x23,0x43,0x01,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,
- 0xce,0xbf,0xcc,0x81,0x00,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,
- 0xcf,0x89,0xcc,0x81,0x00,0x0a,0xff,0xcf,0x97,0x00,0xd3,0x2c,0xd2,0x11,0xe1,0x2f,
- 0x43,0x10,0x07,0x01,0xff,0xce,0xb2,0x00,0x01,0xff,0xce,0xb8,0x00,0xd1,0x10,0x10,
- 0x09,0x01,0xff,0xcf,0x92,0xcc,0x88,0x00,0x01,0xff,0xcf,0x86,0x00,0x10,0x07,0x01,
- 0xff,0xcf,0x80,0x00,0x04,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x06,0xff,0xcf,0x99,
- 0x00,0x06,0x00,0x10,0x07,0x01,0xff,0xcf,0x9b,0x00,0x04,0x00,0xd1,0x0b,0x10,0x07,
- 0x01,0xff,0xcf,0x9d,0x00,0x04,0x00,0x10,0x07,0x01,0xff,0xcf,0x9f,0x00,0x04,0x00,
- 0xd4,0x58,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xcf,0xa1,0x00,0x04,
- 0x00,0x10,0x07,0x01,0xff,0xcf,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,
- 0xcf,0xa5,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xcf,0xa7,0x00,0x01,0x00,0xd2,0x16,
- 0xd1,0x0b,0x10,0x07,0x01,0xff,0xcf,0xa9,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xcf,
- 0xab,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xcf,0xad,0x00,0x01,0x00,0x10,
- 0x07,0x01,0xff,0xcf,0xaf,0x00,0x01,0x00,0xd3,0x2b,0xd2,0x12,0x91,0x0e,0x10,0x07,
- 0x01,0xff,0xce,0xba,0x00,0x01,0xff,0xcf,0x81,0x00,0x01,0x00,0xd1,0x0e,0x10,0x07,
- 0x05,0xff,0xce,0xb8,0x00,0x05,0xff,0xce,0xb5,0x00,0x10,0x04,0x06,0x00,0x07,0xff,
- 0xcf,0xb8,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x04,0x07,0x00,0x07,0xff,0xcf,0xb2,0x00,
- 0x10,0x07,0x07,0xff,0xcf,0xbb,0x00,0x07,0x00,0xd1,0x0b,0x10,0x04,0x08,0x00,0x08,
- 0xff,0xcd,0xbb,0x00,0x10,0x07,0x08,0xff,0xcd,0xbc,0x00,0x08,0xff,0xcd,0xbd,0x00,
- 0xe3,0xd6,0x46,0xe2,0x3d,0x05,0xe1,0x27,0x02,0xe0,0x66,0x01,0xcf,0x86,0xd5,0xf0,
- 0xd4,0x7e,0xd3,0x40,0xd2,0x22,0xd1,0x12,0x10,0x09,0x04,0xff,0xd0,0xb5,0xcc,0x80,
- 0x00,0x01,0xff,0xd0,0xb5,0xcc,0x88,0x00,0x10,0x07,0x01,0xff,0xd1,0x92,0x00,0x01,
- 0xff,0xd0,0xb3,0xcc,0x81,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x94,0x00,0x01,
- 0xff,0xd1,0x95,0x00,0x10,0x07,0x01,0xff,0xd1,0x96,0x00,0x01,0xff,0xd1,0x96,0xcc,
- 0x88,0x00,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x98,0x00,0x01,0xff,0xd1,
- 0x99,0x00,0x10,0x07,0x01,0xff,0xd1,0x9a,0x00,0x01,0xff,0xd1,0x9b,0x00,0xd1,0x12,
- 0x10,0x09,0x01,0xff,0xd0,0xba,0xcc,0x81,0x00,0x04,0xff,0xd0,0xb8,0xcc,0x80,0x00,
- 0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x86,0x00,0x01,0xff,0xd1,0x9f,0x00,0xd3,0x38,
- 0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd0,0xb0,0x00,0x01,0xff,0xd0,0xb1,0x00,
- 0x10,0x07,0x01,0xff,0xd0,0xb2,0x00,0x01,0xff,0xd0,0xb3,0x00,0xd1,0x0e,0x10,0x07,
- 0x01,0xff,0xd0,0xb4,0x00,0x01,0xff,0xd0,0xb5,0x00,0x10,0x07,0x01,0xff,0xd0,0xb6,
- 0x00,0x01,0xff,0xd0,0xb7,0x00,0xd2,0x1e,0xd1,0x10,0x10,0x07,0x01,0xff,0xd0,0xb8,
- 0x00,0x01,0xff,0xd0,0xb8,0xcc,0x86,0x00,0x10,0x07,0x01,0xff,0xd0,0xba,0x00,0x01,
- 0xff,0xd0,0xbb,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd0,0xbc,0x00,0x01,0xff,0xd0,
- 0xbd,0x00,0x10,0x07,0x01,0xff,0xd0,0xbe,0x00,0x01,0xff,0xd0,0xbf,0x00,0xe4,0x0e,
- 0x42,0xd3,0x38,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x80,0x00,0x01,0xff,
- 0xd1,0x81,0x00,0x10,0x07,0x01,0xff,0xd1,0x82,0x00,0x01,0xff,0xd1,0x83,0x00,0xd1,
- 0x0e,0x10,0x07,0x01,0xff,0xd1,0x84,0x00,0x01,0xff,0xd1,0x85,0x00,0x10,0x07,0x01,
- 0xff,0xd1,0x86,0x00,0x01,0xff,0xd1,0x87,0x00,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,
- 0xff,0xd1,0x88,0x00,0x01,0xff,0xd1,0x89,0x00,0x10,0x07,0x01,0xff,0xd1,0x8a,0x00,
- 0x01,0xff,0xd1,0x8b,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x8c,0x00,0x01,0xff,
- 0xd1,0x8d,0x00,0x10,0x07,0x01,0xff,0xd1,0x8e,0x00,0x01,0xff,0xd1,0x8f,0x00,0xcf,
- 0x86,0xd5,0x07,0x64,0xb8,0x41,0x01,0x00,0xd4,0x58,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,
- 0x10,0x07,0x01,0xff,0xd1,0xa1,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xa3,0x00,
- 0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xa5,0x00,0x01,0x00,0x10,0x07,0x01,
- 0xff,0xd1,0xa7,0x00,0x01,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xa9,
- 0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xab,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,
- 0x01,0xff,0xd1,0xad,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xaf,0x00,0x01,0x00,
- 0xd3,0x33,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xb1,0x00,0x01,0x00,0x10,
- 0x07,0x01,0xff,0xd1,0xb3,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xb5,
- 0x00,0x01,0x00,0x10,0x09,0x01,0xff,0xd1,0xb5,0xcc,0x8f,0x00,0x01,0xff,0xd1,0xb5,
- 0xcc,0x8f,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xb9,0x00,0x01,0x00,
- 0x10,0x07,0x01,0xff,0xd1,0xbb,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,
- 0xbd,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xbf,0x00,0x01,0x00,0xe0,0x41,0x01,
- 0xcf,0x86,0xd5,0x8e,0xd4,0x36,0xd3,0x11,0xe2,0x7a,0x41,0xe1,0x71,0x41,0x10,0x07,
- 0x01,0xff,0xd2,0x81,0x00,0x01,0x00,0xd2,0x0f,0x51,0x04,0x04,0x00,0x10,0x07,0x06,
- 0xff,0xd2,0x8b,0x00,0x06,0x00,0xd1,0x0b,0x10,0x07,0x04,0xff,0xd2,0x8d,0x00,0x04,
- 0x00,0x10,0x07,0x04,0xff,0xd2,0x8f,0x00,0x04,0x00,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,
- 0x10,0x07,0x01,0xff,0xd2,0x91,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0x93,0x00,
- 0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0x95,0x00,0x01,0x00,0x10,0x07,0x01,
- 0xff,0xd2,0x97,0x00,0x01,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0x99,
- 0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0x9b,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,
- 0x01,0xff,0xd2,0x9d,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0x9f,0x00,0x01,0x00,
- 0xd4,0x58,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xa1,0x00,0x01,
- 0x00,0x10,0x07,0x01,0xff,0xd2,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,
- 0xd2,0xa5,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xa7,0x00,0x01,0x00,0xd2,0x16,
- 0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xa9,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,
- 0xab,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xad,0x00,0x01,0x00,0x10,
- 0x07,0x01,0xff,0xd2,0xaf,0x00,0x01,0x00,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,
- 0x01,0xff,0xd2,0xb1,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xb3,0x00,0x01,0x00,
- 0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xb5,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,
- 0xb7,0x00,0x01,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xb9,0x00,0x01,
- 0x00,0x10,0x07,0x01,0xff,0xd2,0xbb,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,
- 0xd2,0xbd,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xbf,0x00,0x01,0x00,0xcf,0x86,
- 0xd5,0xdc,0xd4,0x5a,0xd3,0x36,0xd2,0x20,0xd1,0x10,0x10,0x07,0x01,0xff,0xd3,0x8f,
- 0x00,0x01,0xff,0xd0,0xb6,0xcc,0x86,0x00,0x10,0x09,0x01,0xff,0xd0,0xb6,0xcc,0x86,
- 0x00,0x01,0xff,0xd3,0x84,0x00,0xd1,0x0b,0x10,0x04,0x01,0x00,0x06,0xff,0xd3,0x86,
- 0x00,0x10,0x04,0x06,0x00,0x01,0xff,0xd3,0x88,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x04,
- 0x01,0x00,0x06,0xff,0xd3,0x8a,0x00,0x10,0x04,0x06,0x00,0x01,0xff,0xd3,0x8c,0x00,
- 0xe1,0x52,0x40,0x10,0x04,0x01,0x00,0x06,0xff,0xd3,0x8e,0x00,0xd3,0x41,0xd2,0x24,
- 0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0xb0,0xcc,0x86,0x00,0x01,0xff,0xd0,0xb0,0xcc,
- 0x86,0x00,0x10,0x09,0x01,0xff,0xd0,0xb0,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb0,0xcc,
- 0x88,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0x95,0x00,0x01,0x00,0x10,0x09,0x01,
- 0xff,0xd0,0xb5,0xcc,0x86,0x00,0x01,0xff,0xd0,0xb5,0xcc,0x86,0x00,0xd2,0x1d,0xd1,
- 0x0b,0x10,0x07,0x01,0xff,0xd3,0x99,0x00,0x01,0x00,0x10,0x09,0x01,0xff,0xd3,0x99,
- 0xcc,0x88,0x00,0x01,0xff,0xd3,0x99,0xcc,0x88,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,
- 0xd0,0xb6,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb6,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,
- 0xd0,0xb7,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb7,0xcc,0x88,0x00,0xd4,0x82,0xd3,0x41,
- 0xd2,0x1d,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0xa1,0x00,0x01,0x00,0x10,0x09,0x01,
- 0xff,0xd0,0xb8,0xcc,0x84,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x84,0x00,0xd1,0x12,0x10,
- 0x09,0x01,0xff,0xd0,0xb8,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x88,0x00,0x10,
- 0x09,0x01,0xff,0xd0,0xbe,0xcc,0x88,0x00,0x01,0xff,0xd0,0xbe,0xcc,0x88,0x00,0xd2,
- 0x1d,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0xa9,0x00,0x01,0x00,0x10,0x09,0x01,0xff,
- 0xd3,0xa9,0xcc,0x88,0x00,0x01,0xff,0xd3,0xa9,0xcc,0x88,0x00,0xd1,0x12,0x10,0x09,
- 0x04,0xff,0xd1,0x8d,0xcc,0x88,0x00,0x04,0xff,0xd1,0x8d,0xcc,0x88,0x00,0x10,0x09,
- 0x01,0xff,0xd1,0x83,0xcc,0x84,0x00,0x01,0xff,0xd1,0x83,0xcc,0x84,0x00,0xd3,0x41,
- 0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x88,0x00,0x01,0xff,0xd1,
- 0x83,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x8b,0x00,0x01,0xff,0xd1,
- 0x83,0xcc,0x8b,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd1,0x87,0xcc,0x88,0x00,0x01,
- 0xff,0xd1,0x87,0xcc,0x88,0x00,0x10,0x07,0x08,0xff,0xd3,0xb7,0x00,0x08,0x00,0xd2,
- 0x1d,0xd1,0x12,0x10,0x09,0x01,0xff,0xd1,0x8b,0xcc,0x88,0x00,0x01,0xff,0xd1,0x8b,
- 0xcc,0x88,0x00,0x10,0x07,0x09,0xff,0xd3,0xbb,0x00,0x09,0x00,0xd1,0x0b,0x10,0x07,
- 0x09,0xff,0xd3,0xbd,0x00,0x09,0x00,0x10,0x07,0x09,0xff,0xd3,0xbf,0x00,0x09,0x00,
- 0xe1,0x26,0x02,0xe0,0x78,0x01,0xcf,0x86,0xd5,0xb0,0xd4,0x58,0xd3,0x2c,0xd2,0x16,
- 0xd1,0x0b,0x10,0x07,0x06,0xff,0xd4,0x81,0x00,0x06,0x00,0x10,0x07,0x06,0xff,0xd4,
- 0x83,0x00,0x06,0x00,0xd1,0x0b,0x10,0x07,0x06,0xff,0xd4,0x85,0x00,0x06,0x00,0x10,
- 0x07,0x06,0xff,0xd4,0x87,0x00,0x06,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x06,0xff,
- 0xd4,0x89,0x00,0x06,0x00,0x10,0x07,0x06,0xff,0xd4,0x8b,0x00,0x06,0x00,0xd1,0x0b,
- 0x10,0x07,0x06,0xff,0xd4,0x8d,0x00,0x06,0x00,0x10,0x07,0x06,0xff,0xd4,0x8f,0x00,
- 0x06,0x00,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x09,0xff,0xd4,0x91,0x00,0x09,
- 0x00,0x10,0x07,0x09,0xff,0xd4,0x93,0x00,0x09,0x00,0xd1,0x0b,0x10,0x07,0x0a,0xff,
- 0xd4,0x95,0x00,0x0a,0x00,0x10,0x07,0x0a,0xff,0xd4,0x97,0x00,0x0a,0x00,0xd2,0x16,
- 0xd1,0x0b,0x10,0x07,0x0a,0xff,0xd4,0x99,0x00,0x0a,0x00,0x10,0x07,0x0a,0xff,0xd4,
- 0x9b,0x00,0x0a,0x00,0xd1,0x0b,0x10,0x07,0x0a,0xff,0xd4,0x9d,0x00,0x0a,0x00,0x10,
- 0x07,0x0a,0xff,0xd4,0x9f,0x00,0x0a,0x00,0xd4,0x58,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,
- 0x10,0x07,0x0a,0xff,0xd4,0xa1,0x00,0x0a,0x00,0x10,0x07,0x0a,0xff,0xd4,0xa3,0x00,
- 0x0a,0x00,0xd1,0x0b,0x10,0x07,0x0b,0xff,0xd4,0xa5,0x00,0x0b,0x00,0x10,0x07,0x0c,
- 0xff,0xd4,0xa7,0x00,0x0c,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x10,0xff,0xd4,0xa9,
- 0x00,0x10,0x00,0x10,0x07,0x10,0xff,0xd4,0xab,0x00,0x10,0x00,0xd1,0x0b,0x10,0x07,
- 0x10,0xff,0xd4,0xad,0x00,0x10,0x00,0x10,0x07,0x10,0xff,0xd4,0xaf,0x00,0x10,0x00,
- 0xd3,0x35,0xd2,0x19,0xd1,0x0b,0x10,0x04,0x00,0x00,0x01,0xff,0xd5,0xa1,0x00,0x10,
- 0x07,0x01,0xff,0xd5,0xa2,0x00,0x01,0xff,0xd5,0xa3,0x00,0xd1,0x0e,0x10,0x07,0x01,
- 0xff,0xd5,0xa4,0x00,0x01,0xff,0xd5,0xa5,0x00,0x10,0x07,0x01,0xff,0xd5,0xa6,0x00,
- 0x01,0xff,0xd5,0xa7,0x00,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,0xa8,0x00,
- 0x01,0xff,0xd5,0xa9,0x00,0x10,0x07,0x01,0xff,0xd5,0xaa,0x00,0x01,0xff,0xd5,0xab,
- 0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,0xac,0x00,0x01,0xff,0xd5,0xad,0x00,0x10,
- 0x07,0x01,0xff,0xd5,0xae,0x00,0x01,0xff,0xd5,0xaf,0x00,0xcf,0x86,0xe5,0xf1,0x3e,
- 0xd4,0x70,0xd3,0x38,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,0xb0,0x00,0x01,
- 0xff,0xd5,0xb1,0x00,0x10,0x07,0x01,0xff,0xd5,0xb2,0x00,0x01,0xff,0xd5,0xb3,0x00,
- 0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,0xb4,0x00,0x01,0xff,0xd5,0xb5,0x00,0x10,0x07,
- 0x01,0xff,0xd5,0xb6,0x00,0x01,0xff,0xd5,0xb7,0x00,0xd2,0x1c,0xd1,0x0e,0x10,0x07,
- 0x01,0xff,0xd5,0xb8,0x00,0x01,0xff,0xd5,0xb9,0x00,0x10,0x07,0x01,0xff,0xd5,0xba,
- 0x00,0x01,0xff,0xd5,0xbb,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,0xbc,0x00,0x01,
- 0xff,0xd5,0xbd,0x00,0x10,0x07,0x01,0xff,0xd5,0xbe,0x00,0x01,0xff,0xd5,0xbf,0x00,
- 0xe3,0x70,0x3e,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd6,0x80,0x00,0x01,0xff,
- 0xd6,0x81,0x00,0x10,0x07,0x01,0xff,0xd6,0x82,0x00,0x01,0xff,0xd6,0x83,0x00,0xd1,
- 0x0e,0x10,0x07,0x01,0xff,0xd6,0x84,0x00,0x01,0xff,0xd6,0x85,0x00,0x10,0x07,0x01,
- 0xff,0xd6,0x86,0x00,0x00,0x00,0xe0,0x18,0x3f,0xcf,0x86,0xe5,0xa9,0x3e,0xe4,0x80,
- 0x3e,0xe3,0x5f,0x3e,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,
- 0x01,0xff,0xd5,0xa5,0xd6,0x82,0x00,0xe4,0x3e,0x25,0xe3,0xc4,0x1a,0xe2,0xf8,0x80,
- 0xe1,0xc0,0x13,0xd0,0x1e,0xcf,0x86,0xc5,0xe4,0xf0,0x4a,0xe3,0x3b,0x46,0xe2,0xd1,
- 0x43,0xe1,0x04,0x43,0xe0,0xc9,0x42,0xcf,0x86,0xe5,0x8e,0x42,0x64,0x71,0x42,0x0b,
- 0x00,0xcf,0x86,0xe5,0xfa,0x01,0xe4,0xd5,0x55,0xe3,0x76,0x01,0xe2,0x76,0x53,0xd1,
- 0x0c,0xe0,0xd7,0x52,0xcf,0x86,0x65,0x75,0x52,0x04,0x00,0xe0,0x0d,0x01,0xcf,0x86,
- 0xd5,0x0a,0xe4,0xf8,0x52,0x63,0xe7,0x52,0x0a,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,
- 0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x80,0x00,0x01,0xff,0xe2,0xb4,0x81,0x00,
- 0x10,0x08,0x01,0xff,0xe2,0xb4,0x82,0x00,0x01,0xff,0xe2,0xb4,0x83,0x00,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0xe2,0xb4,0x84,0x00,0x01,0xff,0xe2,0xb4,0x85,0x00,0x10,0x08,
- 0x01,0xff,0xe2,0xb4,0x86,0x00,0x01,0xff,0xe2,0xb4,0x87,0x00,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0xe2,0xb4,0x88,0x00,0x01,0xff,0xe2,0xb4,0x89,0x00,0x10,0x08,
- 0x01,0xff,0xe2,0xb4,0x8a,0x00,0x01,0xff,0xe2,0xb4,0x8b,0x00,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0xe2,0xb4,0x8c,0x00,0x01,0xff,0xe2,0xb4,0x8d,0x00,0x10,0x08,0x01,0xff,
- 0xe2,0xb4,0x8e,0x00,0x01,0xff,0xe2,0xb4,0x8f,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0xe2,0xb4,0x90,0x00,0x01,0xff,0xe2,0xb4,0x91,0x00,0x10,0x08,
- 0x01,0xff,0xe2,0xb4,0x92,0x00,0x01,0xff,0xe2,0xb4,0x93,0x00,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0xe2,0xb4,0x94,0x00,0x01,0xff,0xe2,0xb4,0x95,0x00,0x10,0x08,0x01,0xff,
- 0xe2,0xb4,0x96,0x00,0x01,0xff,0xe2,0xb4,0x97,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0xe2,0xb4,0x98,0x00,0x01,0xff,0xe2,0xb4,0x99,0x00,0x10,0x08,0x01,0xff,
- 0xe2,0xb4,0x9a,0x00,0x01,0xff,0xe2,0xb4,0x9b,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0xe2,0xb4,0x9c,0x00,0x01,0xff,0xe2,0xb4,0x9d,0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,
- 0x9e,0x00,0x01,0xff,0xe2,0xb4,0x9f,0x00,0xcf,0x86,0xe5,0x2a,0x52,0x94,0x50,0xd3,
- 0x3c,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0xa0,0x00,0x01,0xff,0xe2,
- 0xb4,0xa1,0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0xa2,0x00,0x01,0xff,0xe2,0xb4,0xa3,
- 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0xa4,0x00,0x01,0xff,0xe2,0xb4,0xa5,
- 0x00,0x10,0x04,0x00,0x00,0x0d,0xff,0xe2,0xb4,0xa7,0x00,0x52,0x04,0x00,0x00,0x91,
- 0x0c,0x10,0x04,0x00,0x00,0x0d,0xff,0xe2,0xb4,0xad,0x00,0x00,0x00,0x01,0x00,0xd2,
- 0x1b,0xe1,0xce,0x52,0xe0,0x7f,0x52,0xcf,0x86,0x95,0x0f,0x94,0x0b,0x93,0x07,0x62,
- 0x64,0x52,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xd1,0x13,0xe0,0xa5,0x53,0xcf,
- 0x86,0x95,0x0a,0xe4,0x7a,0x53,0x63,0x69,0x53,0x04,0x00,0x04,0x00,0xd0,0x0d,0xcf,
- 0x86,0x95,0x07,0x64,0xf4,0x53,0x08,0x00,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,0x00,
- 0x54,0x04,0x04,0x00,0xd3,0x07,0x62,0x01,0x54,0x04,0x00,0xd2,0x20,0xd1,0x10,0x10,
- 0x08,0x11,0xff,0xe1,0x8f,0xb0,0x00,0x11,0xff,0xe1,0x8f,0xb1,0x00,0x10,0x08,0x11,
- 0xff,0xe1,0x8f,0xb2,0x00,0x11,0xff,0xe1,0x8f,0xb3,0x00,0x91,0x10,0x10,0x08,0x11,
- 0xff,0xe1,0x8f,0xb4,0x00,0x11,0xff,0xe1,0x8f,0xb5,0x00,0x00,0x00,0xd4,0x1c,0xe3,
- 0x92,0x56,0xe2,0xc9,0x55,0xe1,0x8c,0x55,0xe0,0x6d,0x55,0xcf,0x86,0x95,0x0a,0xe4,
- 0x56,0x55,0x63,0x45,0x55,0x04,0x00,0x04,0x00,0xe3,0xd2,0x01,0xe2,0xdd,0x59,0xd1,
- 0x0c,0xe0,0xfe,0x58,0xcf,0x86,0x65,0xd7,0x58,0x0a,0x00,0xe0,0x4e,0x59,0xcf,0x86,
- 0xd5,0xc5,0xd4,0x45,0xd3,0x31,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x12,0xff,0xd0,0xb2,
- 0x00,0x12,0xff,0xd0,0xb4,0x00,0x10,0x07,0x12,0xff,0xd0,0xbe,0x00,0x12,0xff,0xd1,
- 0x81,0x00,0x51,0x07,0x12,0xff,0xd1,0x82,0x00,0x10,0x07,0x12,0xff,0xd1,0x8a,0x00,
- 0x12,0xff,0xd1,0xa3,0x00,0x92,0x10,0x91,0x0c,0x10,0x08,0x12,0xff,0xea,0x99,0x8b,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x14,
- 0xff,0xe1,0x83,0x90,0x00,0x14,0xff,0xe1,0x83,0x91,0x00,0x10,0x08,0x14,0xff,0xe1,
- 0x83,0x92,0x00,0x14,0xff,0xe1,0x83,0x93,0x00,0xd1,0x10,0x10,0x08,0x14,0xff,0xe1,
- 0x83,0x94,0x00,0x14,0xff,0xe1,0x83,0x95,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,0x96,
- 0x00,0x14,0xff,0xe1,0x83,0x97,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x14,0xff,0xe1,
- 0x83,0x98,0x00,0x14,0xff,0xe1,0x83,0x99,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,0x9a,
- 0x00,0x14,0xff,0xe1,0x83,0x9b,0x00,0xd1,0x10,0x10,0x08,0x14,0xff,0xe1,0x83,0x9c,
- 0x00,0x14,0xff,0xe1,0x83,0x9d,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,0x9e,0x00,0x14,
- 0xff,0xe1,0x83,0x9f,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x14,
- 0xff,0xe1,0x83,0xa0,0x00,0x14,0xff,0xe1,0x83,0xa1,0x00,0x10,0x08,0x14,0xff,0xe1,
- 0x83,0xa2,0x00,0x14,0xff,0xe1,0x83,0xa3,0x00,0xd1,0x10,0x10,0x08,0x14,0xff,0xe1,
- 0x83,0xa4,0x00,0x14,0xff,0xe1,0x83,0xa5,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,0xa6,
- 0x00,0x14,0xff,0xe1,0x83,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x14,0xff,0xe1,
- 0x83,0xa8,0x00,0x14,0xff,0xe1,0x83,0xa9,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,0xaa,
- 0x00,0x14,0xff,0xe1,0x83,0xab,0x00,0xd1,0x10,0x10,0x08,0x14,0xff,0xe1,0x83,0xac,
- 0x00,0x14,0xff,0xe1,0x83,0xad,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,0xae,0x00,0x14,
- 0xff,0xe1,0x83,0xaf,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x14,0xff,0xe1,
- 0x83,0xb0,0x00,0x14,0xff,0xe1,0x83,0xb1,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,0xb2,
- 0x00,0x14,0xff,0xe1,0x83,0xb3,0x00,0xd1,0x10,0x10,0x08,0x14,0xff,0xe1,0x83,0xb4,
- 0x00,0x14,0xff,0xe1,0x83,0xb5,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,0xb6,0x00,0x14,
- 0xff,0xe1,0x83,0xb7,0x00,0xd2,0x1c,0xd1,0x10,0x10,0x08,0x14,0xff,0xe1,0x83,0xb8,
- 0x00,0x14,0xff,0xe1,0x83,0xb9,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,0xba,0x00,0x00,
- 0x00,0xd1,0x0c,0x10,0x04,0x00,0x00,0x14,0xff,0xe1,0x83,0xbd,0x00,0x10,0x08,0x14,
- 0xff,0xe1,0x83,0xbe,0x00,0x14,0xff,0xe1,0x83,0xbf,0x00,0xe2,0x9d,0x08,0xe1,0x48,
- 0x04,0xe0,0x1c,0x02,0xcf,0x86,0xe5,0x11,0x01,0xd4,0x84,0xd3,0x40,0xd2,0x20,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0xa5,0x00,0x01,0xff,0x61,0xcc,0xa5,0x00,0x10,
- 0x08,0x01,0xff,0x62,0xcc,0x87,0x00,0x01,0xff,0x62,0xcc,0x87,0x00,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0x62,0xcc,0xa3,0x00,0x01,0xff,0x62,0xcc,0xa3,0x00,0x10,0x08,0x01,
- 0xff,0x62,0xcc,0xb1,0x00,0x01,0xff,0x62,0xcc,0xb1,0x00,0xd2,0x24,0xd1,0x14,0x10,
- 0x0a,0x01,0xff,0x63,0xcc,0xa7,0xcc,0x81,0x00,0x01,0xff,0x63,0xcc,0xa7,0xcc,0x81,
- 0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0x87,0x00,0x01,0xff,0x64,0xcc,0x87,0x00,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0x64,0xcc,0xa3,0x00,0x01,0xff,0x64,0xcc,0xa3,0x00,0x10,
- 0x08,0x01,0xff,0x64,0xcc,0xb1,0x00,0x01,0xff,0x64,0xcc,0xb1,0x00,0xd3,0x48,0xd2,
- 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x64,0xcc,0xa7,0x00,0x01,0xff,0x64,0xcc,0xa7,
- 0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0xad,0x00,0x01,0xff,0x64,0xcc,0xad,0x00,0xd1,
- 0x14,0x10,0x0a,0x01,0xff,0x65,0xcc,0x84,0xcc,0x80,0x00,0x01,0xff,0x65,0xcc,0x84,
- 0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x65,0xcc,0x84,0xcc,0x81,0x00,0x01,0xff,0x65,
- 0xcc,0x84,0xcc,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0xad,
- 0x00,0x01,0xff,0x65,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0xb0,0x00,0x01,
- 0xff,0x65,0xcc,0xb0,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x65,0xcc,0xa7,0xcc,0x86,
- 0x00,0x01,0xff,0x65,0xcc,0xa7,0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x66,0xcc,0x87,
- 0x00,0x01,0xff,0x66,0xcc,0x87,0x00,0xd4,0x84,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0x67,0xcc,0x84,0x00,0x01,0xff,0x67,0xcc,0x84,0x00,0x10,0x08,0x01,
- 0xff,0x68,0xcc,0x87,0x00,0x01,0xff,0x68,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0x68,0xcc,0xa3,0x00,0x01,0xff,0x68,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x68,
- 0xcc,0x88,0x00,0x01,0xff,0x68,0xcc,0x88,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0x68,0xcc,0xa7,0x00,0x01,0xff,0x68,0xcc,0xa7,0x00,0x10,0x08,0x01,0xff,0x68,
- 0xcc,0xae,0x00,0x01,0xff,0x68,0xcc,0xae,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,
- 0xcc,0xb0,0x00,0x01,0xff,0x69,0xcc,0xb0,0x00,0x10,0x0a,0x01,0xff,0x69,0xcc,0x88,
- 0xcc,0x81,0x00,0x01,0xff,0x69,0xcc,0x88,0xcc,0x81,0x00,0xd3,0x40,0xd2,0x20,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0x6b,0xcc,0x81,0x00,0x01,0xff,0x6b,0xcc,0x81,0x00,0x10,
- 0x08,0x01,0xff,0x6b,0xcc,0xa3,0x00,0x01,0xff,0x6b,0xcc,0xa3,0x00,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0x6b,0xcc,0xb1,0x00,0x01,0xff,0x6b,0xcc,0xb1,0x00,0x10,0x08,0x01,
- 0xff,0x6c,0xcc,0xa3,0x00,0x01,0xff,0x6c,0xcc,0xa3,0x00,0xd2,0x24,0xd1,0x14,0x10,
- 0x0a,0x01,0xff,0x6c,0xcc,0xa3,0xcc,0x84,0x00,0x01,0xff,0x6c,0xcc,0xa3,0xcc,0x84,
- 0x00,0x10,0x08,0x01,0xff,0x6c,0xcc,0xb1,0x00,0x01,0xff,0x6c,0xcc,0xb1,0x00,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0x6c,0xcc,0xad,0x00,0x01,0xff,0x6c,0xcc,0xad,0x00,0x10,
- 0x08,0x01,0xff,0x6d,0xcc,0x81,0x00,0x01,0xff,0x6d,0xcc,0x81,0x00,0xcf,0x86,0xe5,
- 0x15,0x01,0xd4,0x88,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x6d,0xcc,
- 0x87,0x00,0x01,0xff,0x6d,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x6d,0xcc,0xa3,0x00,
- 0x01,0xff,0x6d,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e,0xcc,0x87,0x00,
- 0x01,0xff,0x6e,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x6e,0xcc,0xa3,0x00,0x01,0xff,
- 0x6e,0xcc,0xa3,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e,0xcc,0xb1,0x00,
- 0x01,0xff,0x6e,0xcc,0xb1,0x00,0x10,0x08,0x01,0xff,0x6e,0xcc,0xad,0x00,0x01,0xff,
- 0x6e,0xcc,0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x81,0x00,
- 0x01,0xff,0x6f,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x83,0xcc,
- 0x88,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x88,0x00,0xd3,0x48,0xd2,0x28,0xd1,0x14,
- 0x10,0x0a,0x01,0xff,0x6f,0xcc,0x84,0xcc,0x80,0x00,0x01,0xff,0x6f,0xcc,0x84,0xcc,
- 0x80,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x84,0xcc,0x81,0x00,0x01,0xff,0x6f,0xcc,
- 0x84,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x70,0xcc,0x81,0x00,0x01,0xff,
- 0x70,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x70,0xcc,0x87,0x00,0x01,0xff,0x70,0xcc,
- 0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x72,0xcc,0x87,0x00,0x01,0xff,
- 0x72,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x72,0xcc,0xa3,0x00,0x01,0xff,0x72,0xcc,
- 0xa3,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x72,0xcc,0xa3,0xcc,0x84,0x00,0x01,0xff,
- 0x72,0xcc,0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x72,0xcc,0xb1,0x00,0x01,0xff,
- 0x72,0xcc,0xb1,0x00,0xd4,0x8c,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x73,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x73,0xcc,
- 0xa3,0x00,0x01,0xff,0x73,0xcc,0xa3,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x73,0xcc,
- 0x81,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x81,0xcc,0x87,0x00,0x10,0x0a,0x01,0xff,
- 0x73,0xcc,0x8c,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x8c,0xcc,0x87,0x00,0xd2,0x24,
- 0xd1,0x14,0x10,0x0a,0x01,0xff,0x73,0xcc,0xa3,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,
- 0xa3,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x74,0xcc,0x87,0x00,0x01,0xff,0x74,0xcc,
- 0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x74,0xcc,0xa3,0x00,0x01,0xff,0x74,0xcc,
- 0xa3,0x00,0x10,0x08,0x01,0xff,0x74,0xcc,0xb1,0x00,0x01,0xff,0x74,0xcc,0xb1,0x00,
- 0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x74,0xcc,0xad,0x00,0x01,0xff,
- 0x74,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0xa4,0x00,0x01,0xff,0x75,0xcc,
- 0xa4,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0xb0,0x00,0x01,0xff,0x75,0xcc,
- 0xb0,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0xad,0x00,0x01,0xff,0x75,0xcc,0xad,0x00,
- 0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x83,0xcc,0x81,0x00,0x01,0xff,
- 0x75,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x84,0xcc,0x88,0x00,
- 0x01,0xff,0x75,0xcc,0x84,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x76,0xcc,
- 0x83,0x00,0x01,0xff,0x76,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x76,0xcc,0xa3,0x00,
- 0x01,0xff,0x76,0xcc,0xa3,0x00,0xe0,0x11,0x02,0xcf,0x86,0xd5,0xe2,0xd4,0x80,0xd3,
- 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x80,0x00,0x01,0xff,0x77,
- 0xcc,0x80,0x00,0x10,0x08,0x01,0xff,0x77,0xcc,0x81,0x00,0x01,0xff,0x77,0xcc,0x81,
- 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x88,0x00,0x01,0xff,0x77,0xcc,0x88,
- 0x00,0x10,0x08,0x01,0xff,0x77,0xcc,0x87,0x00,0x01,0xff,0x77,0xcc,0x87,0x00,0xd2,
- 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0xa3,0x00,0x01,0xff,0x77,0xcc,0xa3,
- 0x00,0x10,0x08,0x01,0xff,0x78,0xcc,0x87,0x00,0x01,0xff,0x78,0xcc,0x87,0x00,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0x78,0xcc,0x88,0x00,0x01,0xff,0x78,0xcc,0x88,0x00,0x10,
- 0x08,0x01,0xff,0x79,0xcc,0x87,0x00,0x01,0xff,0x79,0xcc,0x87,0x00,0xd3,0x33,0xd2,
- 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x7a,0xcc,0x82,0x00,0x01,0xff,0x7a,0xcc,0x82,
- 0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0xa3,0x00,0x01,0xff,0x7a,0xcc,0xa3,0x00,0xe1,
- 0xc4,0x58,0x10,0x08,0x01,0xff,0x7a,0xcc,0xb1,0x00,0x01,0xff,0x7a,0xcc,0xb1,0x00,
- 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x8a,0x00,0x01,0xff,0x79,0xcc,
- 0x8a,0x00,0x10,0x08,0x01,0xff,0x61,0xca,0xbe,0x00,0x02,0xff,0x73,0xcc,0x87,0x00,
- 0x51,0x04,0x0a,0x00,0x10,0x07,0x0a,0xff,0x73,0x73,0x00,0x0a,0x00,0xd4,0x98,0xd3,
- 0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0xa3,0x00,0x01,0xff,0x61,
- 0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x61,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x89,
- 0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0x82,0xcc,0x81,0x00,0x01,0xff,0x61,
- 0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0x82,0xcc,0x80,0x00,0x01,
- 0xff,0x61,0xcc,0x82,0xcc,0x80,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,
- 0xcc,0x82,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x89,0x00,0x10,0x0a,0x01,
- 0xff,0x61,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x83,0x00,0xd1,
- 0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x61,0xcc,0xa3,
- 0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0x86,0xcc,0x81,0x00,0x01,0xff,0x61,
- 0xcc,0x86,0xcc,0x81,0x00,0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,
- 0xcc,0x86,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,0x80,0x00,0x10,0x0a,0x01,
- 0xff,0x61,0xcc,0x86,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,0x89,0x00,0xd1,
- 0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0x86,0xcc,0x83,0x00,0x01,0xff,0x61,0xcc,0x86,
- 0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0xa3,0xcc,0x86,0x00,0x01,0xff,0x61,
- 0xcc,0xa3,0xcc,0x86,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0xa3,
- 0x00,0x01,0xff,0x65,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x89,0x00,0x01,
- 0xff,0x65,0xcc,0x89,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0x83,0x00,0x01,
- 0xff,0x65,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x65,0xcc,0x82,0xcc,0x81,0x00,0x01,
- 0xff,0x65,0xcc,0x82,0xcc,0x81,0x00,0xcf,0x86,0xe5,0x31,0x01,0xd4,0x90,0xd3,0x50,
- 0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x65,0xcc,0x82,0xcc,0x80,0x00,0x01,0xff,
- 0x65,0xcc,0x82,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x65,0xcc,0x82,0xcc,0x89,0x00,
- 0x01,0xff,0x65,0xcc,0x82,0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x65,0xcc,
- 0x82,0xcc,0x83,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,
- 0x65,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x65,0xcc,0xa3,0xcc,0x82,0x00,0xd2,0x20,
- 0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x89,0x00,0x01,0xff,0x69,0xcc,0x89,0x00,
- 0x10,0x08,0x01,0xff,0x69,0xcc,0xa3,0x00,0x01,0xff,0x69,0xcc,0xa3,0x00,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0x6f,0xcc,0xa3,0x00,0x01,0xff,0x6f,0xcc,0xa3,0x00,0x10,0x08,
- 0x01,0xff,0x6f,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x89,0x00,0xd3,0x50,0xd2,0x28,
- 0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x81,0x00,0x01,0xff,0x6f,0xcc,
- 0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x80,0x00,0x01,0xff,
- 0x6f,0xcc,0x82,0xcc,0x80,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x82,0xcc,
- 0x89,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x89,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,
- 0x82,0xcc,0x83,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x83,0x00,0xd2,0x28,0xd1,0x14,
- 0x10,0x0a,0x01,0xff,0x6f,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x6f,0xcc,0xa3,0xcc,
- 0x82,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x81,0x00,0x01,0xff,0x6f,0xcc,
- 0x9b,0xcc,0x81,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x80,0x00,
- 0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,
- 0x89,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x89,0x00,0xd4,0x98,0xd3,0x48,0xd2,0x28,
- 0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x83,0x00,0x01,0xff,0x6f,0xcc,
- 0x9b,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0xa3,0x00,0x01,0xff,
- 0x6f,0xcc,0x9b,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0xa3,0x00,
- 0x01,0xff,0x75,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x89,0x00,0x01,0xff,
- 0x75,0xcc,0x89,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x9b,0xcc,
- 0x81,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,
- 0x9b,0xcc,0x80,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x80,0x00,0xd1,0x14,0x10,0x0a,
- 0x01,0xff,0x75,0xcc,0x9b,0xcc,0x89,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x89,0x00,
- 0x10,0x0a,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x83,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,
- 0x83,0x00,0xd3,0x44,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x9b,0xcc,
- 0xa3,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x79,0xcc,
- 0x80,0x00,0x01,0xff,0x79,0xcc,0x80,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x79,0xcc,
- 0xa3,0x00,0x01,0xff,0x79,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x79,0xcc,0x89,0x00,
- 0x01,0xff,0x79,0xcc,0x89,0x00,0xd2,0x1c,0xd1,0x10,0x10,0x08,0x01,0xff,0x79,0xcc,
- 0x83,0x00,0x01,0xff,0x79,0xcc,0x83,0x00,0x10,0x08,0x0a,0xff,0xe1,0xbb,0xbb,0x00,
- 0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xe1,0xbb,0xbd,0x00,0x0a,0x00,0x10,0x08,
- 0x0a,0xff,0xe1,0xbb,0xbf,0x00,0x0a,0x00,0xe1,0xbf,0x02,0xe0,0xa1,0x01,0xcf,0x86,
- 0xd5,0xc6,0xd4,0x6c,0xd3,0x18,0xe2,0xc0,0x58,0xe1,0xa9,0x58,0x10,0x09,0x01,0xff,
- 0xce,0xb1,0xcc,0x93,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,
- 0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x93,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0x00,
- 0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb1,0xcc,
- 0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x81,
- 0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce,0xb1,
- 0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82,0x00,0xd3,0x18,
- 0xe2,0xfc,0x58,0xe1,0xe5,0x58,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc,0x93,0x00,0x01,
- 0xff,0xce,0xb5,0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb5,
- 0xcc,0x93,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb5,
- 0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0xcc,0x80,0x00,0x91,0x16,
- 0x10,0x0b,0x01,0xff,0xce,0xb5,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb5,0xcc,
- 0x94,0xcc,0x81,0x00,0x00,0x00,0xd4,0x6c,0xd3,0x18,0xe2,0x26,0x59,0xe1,0x0f,0x59,
- 0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x93,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0x00,
- 0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x93,0x00,0x01,0xff,0xce,
- 0xb7,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x80,0x00,0x01,
- 0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb7,
- 0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,
- 0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,
- 0x82,0x00,0xd3,0x18,0xe2,0x62,0x59,0xe1,0x4b,0x59,0x10,0x09,0x01,0xff,0xce,0xb9,
- 0xcc,0x93,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,
- 0x01,0xff,0xce,0xb9,0xcc,0x93,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0x00,0x10,0x0b,
- 0x01,0xff,0xce,0xb9,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcc,
- 0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x93,0xcc,0x81,0x00,0x01,
- 0xff,0xce,0xb9,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x93,
- 0xcd,0x82,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcd,0x82,0x00,0xcf,0x86,0xd5,0xac,
- 0xd4,0x5a,0xd3,0x18,0xe2,0x9f,0x59,0xe1,0x88,0x59,0x10,0x09,0x01,0xff,0xce,0xbf,
- 0xcc,0x93,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,
- 0x01,0xff,0xce,0xbf,0xcc,0x93,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0x00,0x10,0x0b,
- 0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0xcc,
- 0x80,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,0x81,0x00,0x01,
- 0xff,0xce,0xbf,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd3,0x18,0xe2,0xc9,0x59,0xe1,
- 0xb2,0x59,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x93,0x00,0x01,0xff,0xcf,0x85,0xcc,
- 0x94,0x00,0xd2,0x1c,0xd1,0x0d,0x10,0x04,0x00,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,
- 0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x0f,
- 0x10,0x04,0x00,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcc,0x81,0x00,0x10,0x04,0x00,
- 0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcd,0x82,0x00,0xe4,0x85,0x5a,0xd3,0x18,0xe2,
- 0x04,0x5a,0xe1,0xed,0x59,0x10,0x09,0x01,0xff,0xcf,0x89,0xcc,0x93,0x00,0x01,0xff,
- 0xcf,0x89,0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xcf,0x89,0xcc,
- 0x93,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,
- 0x93,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,
- 0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,
- 0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,
- 0xcf,0x89,0xcc,0x94,0xcd,0x82,0x00,0xe0,0xd9,0x02,0xcf,0x86,0xe5,0x91,0x01,0xd4,
- 0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xce,
- 0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,
- 0xb1,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x80,
- 0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x81,0xce,
- 0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00,0x10,0x0d,0x01,
- 0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,
- 0xcd,0x82,0xce,0xb9,0x00,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,
- 0x93,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d,0x01,
- 0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,
- 0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,
- 0x81,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00,0x10,
- 0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,
- 0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,
- 0xff,0xce,0xb7,0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xce,0xb9,
- 0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,
- 0xce,0xb7,0xcc,0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,
- 0xb7,0xcc,0x93,0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x81,
- 0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,
- 0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x30,0xd1,0x16,0x10,
- 0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,
- 0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,
- 0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,
- 0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,
- 0xcc,0x81,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x82,0xce,
- 0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd4,0xc8,0xd3,
- 0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xce,0xb9,0x00,
- 0x01,0xff,0xcf,0x89,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,
- 0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x80,0xce,0xb9,
- 0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x81,0xce,0xb9,0x00,
- 0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xcf,
- 0x89,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,0x82,
- 0xce,0xb9,0x00,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xce,
- 0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xcf,
- 0x89,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x80,
- 0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x81,0xce,
- 0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00,0x10,0x0d,0x01,
- 0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,
- 0xcd,0x82,0xce,0xb9,0x00,0xd3,0x49,0xd2,0x26,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,
- 0xb1,0xcc,0x86,0x00,0x01,0xff,0xce,0xb1,0xcc,0x84,0x00,0x10,0x0b,0x01,0xff,0xce,
- 0xb1,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xce,0xb9,0x00,0xd1,0x0f,0x10,
- 0x0b,0x01,0xff,0xce,0xb1,0xcc,0x81,0xce,0xb9,0x00,0x00,0x00,0x10,0x09,0x01,0xff,
- 0xce,0xb1,0xcd,0x82,0x00,0x01,0xff,0xce,0xb1,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x24,
- 0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x86,0x00,0x01,0xff,0xce,0xb1,0xcc,
- 0x84,0x00,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x80,0x00,0x01,0xff,0xce,0xb1,0xcc,
- 0x81,0x00,0xe1,0xa5,0x5a,0x10,0x09,0x01,0xff,0xce,0xb1,0xce,0xb9,0x00,0x01,0x00,
- 0xcf,0x86,0xd5,0xbd,0xd4,0x7e,0xd3,0x44,0xd2,0x21,0xd1,0x0d,0x10,0x04,0x01,0x00,
- 0x01,0xff,0xc2,0xa8,0xcd,0x82,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x80,0xce,
- 0xb9,0x00,0x01,0xff,0xce,0xb7,0xce,0xb9,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xce,
- 0xb7,0xcc,0x81,0xce,0xb9,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xb7,0xcd,0x82,
- 0x00,0x01,0xff,0xce,0xb7,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,
- 0x01,0xff,0xce,0xb5,0xcc,0x80,0x00,0x01,0xff,0xce,0xb5,0xcc,0x81,0x00,0x10,0x09,
- 0x01,0xff,0xce,0xb7,0xcc,0x80,0x00,0x01,0xff,0xce,0xb7,0xcc,0x81,0x00,0xe1,0xb4,
- 0x5a,0x10,0x09,0x01,0xff,0xce,0xb7,0xce,0xb9,0x00,0x01,0xff,0xe1,0xbe,0xbf,0xcc,
- 0x80,0x00,0xd3,0x18,0xe2,0xda,0x5a,0xe1,0xc3,0x5a,0x10,0x09,0x01,0xff,0xce,0xb9,
- 0xcc,0x86,0x00,0x01,0xff,0xce,0xb9,0xcc,0x84,0x00,0xe2,0xfe,0x5a,0xd1,0x12,0x10,
- 0x09,0x01,0xff,0xce,0xb9,0xcc,0x86,0x00,0x01,0xff,0xce,0xb9,0xcc,0x84,0x00,0x10,
- 0x09,0x01,0xff,0xce,0xb9,0xcc,0x80,0x00,0x01,0xff,0xce,0xb9,0xcc,0x81,0x00,0xd4,
- 0x51,0xd3,0x18,0xe2,0x21,0x5b,0xe1,0x0a,0x5b,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,
- 0x86,0x00,0x01,0xff,0xcf,0x85,0xcc,0x84,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,
- 0xff,0xcf,0x85,0xcc,0x86,0x00,0x01,0xff,0xcf,0x85,0xcc,0x84,0x00,0x10,0x09,0x01,
- 0xff,0xcf,0x85,0xcc,0x80,0x00,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0xe1,0x41,0x5b,
- 0x10,0x09,0x01,0xff,0xcf,0x81,0xcc,0x94,0x00,0x01,0xff,0xc2,0xa8,0xcc,0x80,0x00,
- 0xd3,0x3b,0xd2,0x18,0x51,0x04,0x00,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x80,
- 0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xce,0xb9,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,
- 0xcf,0x89,0xcc,0x81,0xce,0xb9,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xcf,0x89,0xcd,
- 0x82,0x00,0x01,0xff,0xcf,0x89,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x24,0xd1,0x12,0x10,
- 0x09,0x01,0xff,0xce,0xbf,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00,0x10,
- 0x09,0x01,0xff,0xcf,0x89,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc,0x81,0x00,0xe1,
- 0x4b,0x5b,0x10,0x09,0x01,0xff,0xcf,0x89,0xce,0xb9,0x00,0x01,0xff,0xc2,0xb4,0x00,
- 0xe0,0xa2,0x67,0xcf,0x86,0xe5,0x24,0x02,0xe4,0x26,0x01,0xe3,0x1b,0x5e,0xd2,0x2b,
- 0xe1,0xf5,0x5b,0xe0,0x7a,0x5b,0xcf,0x86,0xe5,0x5f,0x5b,0x94,0x1c,0x93,0x18,0x92,
- 0x14,0x91,0x10,0x10,0x08,0x01,0xff,0xe2,0x80,0x82,0x00,0x01,0xff,0xe2,0x80,0x83,
- 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd1,0xd6,0xd0,0x46,0xcf,0x86,0x55,
- 0x04,0x01,0x00,0xd4,0x29,0xd3,0x13,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,
- 0x07,0x01,0xff,0xcf,0x89,0x00,0x01,0x00,0x92,0x12,0x51,0x04,0x01,0x00,0x10,0x06,
- 0x01,0xff,0x6b,0x00,0x01,0xff,0x61,0xcc,0x8a,0x00,0x01,0x00,0xe3,0xba,0x5c,0x92,
- 0x10,0x51,0x04,0x01,0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0x8e,0x00,0x01,0x00,0x01,
- 0x00,0xcf,0x86,0xd5,0x0a,0xe4,0xd7,0x5c,0x63,0xc2,0x5c,0x06,0x00,0x94,0x80,0xd3,
- 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xb0,0x00,0x01,0xff,0xe2,
- 0x85,0xb1,0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xb2,0x00,0x01,0xff,0xe2,0x85,0xb3,
- 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xb4,0x00,0x01,0xff,0xe2,0x85,0xb5,
- 0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xb6,0x00,0x01,0xff,0xe2,0x85,0xb7,0x00,0xd2,
- 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xb8,0x00,0x01,0xff,0xe2,0x85,0xb9,
- 0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xba,0x00,0x01,0xff,0xe2,0x85,0xbb,0x00,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xbc,0x00,0x01,0xff,0xe2,0x85,0xbd,0x00,0x10,
- 0x08,0x01,0xff,0xe2,0x85,0xbe,0x00,0x01,0xff,0xe2,0x85,0xbf,0x00,0x01,0x00,0xe0,
- 0xc9,0x5c,0xcf,0x86,0xe5,0xa8,0x5c,0xe4,0x87,0x5c,0xe3,0x76,0x5c,0xe2,0x69,0x5c,
- 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x04,0xff,0xe2,0x86,0x84,0x00,0xe3,0xb8,
- 0x60,0xe2,0x85,0x60,0xd1,0x0c,0xe0,0x32,0x60,0xcf,0x86,0x65,0x13,0x60,0x01,0x00,
- 0xd0,0x62,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x18,0x52,0x04,
- 0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x08,0x01,0xff,0xe2,0x93,0x90,0x00,0x01,0xff,
- 0xe2,0x93,0x91,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x93,0x92,0x00,
- 0x01,0xff,0xe2,0x93,0x93,0x00,0x10,0x08,0x01,0xff,0xe2,0x93,0x94,0x00,0x01,0xff,
- 0xe2,0x93,0x95,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x93,0x96,0x00,0x01,0xff,
- 0xe2,0x93,0x97,0x00,0x10,0x08,0x01,0xff,0xe2,0x93,0x98,0x00,0x01,0xff,0xe2,0x93,
- 0x99,0x00,0xcf,0x86,0xe5,0xec,0x5f,0x94,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0xe2,0x93,0x9a,0x00,0x01,0xff,0xe2,0x93,0x9b,0x00,0x10,0x08,0x01,
- 0xff,0xe2,0x93,0x9c,0x00,0x01,0xff,0xe2,0x93,0x9d,0x00,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0xe2,0x93,0x9e,0x00,0x01,0xff,0xe2,0x93,0x9f,0x00,0x10,0x08,0x01,0xff,0xe2,
- 0x93,0xa0,0x00,0x01,0xff,0xe2,0x93,0xa1,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0xe2,0x93,0xa2,0x00,0x01,0xff,0xe2,0x93,0xa3,0x00,0x10,0x08,0x01,0xff,0xe2,
- 0x93,0xa4,0x00,0x01,0xff,0xe2,0x93,0xa5,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,
- 0x93,0xa6,0x00,0x01,0xff,0xe2,0x93,0xa7,0x00,0x10,0x08,0x01,0xff,0xe2,0x93,0xa8,
- 0x00,0x01,0xff,0xe2,0x93,0xa9,0x00,0x01,0x00,0xd4,0x0c,0xe3,0xc8,0x61,0xe2,0xc1,
- 0x61,0xcf,0x06,0x04,0x00,0xe3,0xa1,0x64,0xe2,0x94,0x63,0xe1,0x2e,0x02,0xe0,0x84,
- 0x01,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x08,0xff,0xe2,0xb0,0xb0,0x00,0x08,0xff,0xe2,0xb0,0xb1,0x00,0x10,0x08,0x08,0xff,
- 0xe2,0xb0,0xb2,0x00,0x08,0xff,0xe2,0xb0,0xb3,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,
- 0xe2,0xb0,0xb4,0x00,0x08,0xff,0xe2,0xb0,0xb5,0x00,0x10,0x08,0x08,0xff,0xe2,0xb0,
- 0xb6,0x00,0x08,0xff,0xe2,0xb0,0xb7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,
- 0xe2,0xb0,0xb8,0x00,0x08,0xff,0xe2,0xb0,0xb9,0x00,0x10,0x08,0x08,0xff,0xe2,0xb0,
- 0xba,0x00,0x08,0xff,0xe2,0xb0,0xbb,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb0,
- 0xbc,0x00,0x08,0xff,0xe2,0xb0,0xbd,0x00,0x10,0x08,0x08,0xff,0xe2,0xb0,0xbe,0x00,
- 0x08,0xff,0xe2,0xb0,0xbf,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,
- 0xe2,0xb1,0x80,0x00,0x08,0xff,0xe2,0xb1,0x81,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,
- 0x82,0x00,0x08,0xff,0xe2,0xb1,0x83,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb1,
- 0x84,0x00,0x08,0xff,0xe2,0xb1,0x85,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0x86,0x00,
- 0x08,0xff,0xe2,0xb1,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb1,
- 0x88,0x00,0x08,0xff,0xe2,0xb1,0x89,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0x8a,0x00,
- 0x08,0xff,0xe2,0xb1,0x8b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb1,0x8c,0x00,
- 0x08,0xff,0xe2,0xb1,0x8d,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0x8e,0x00,0x08,0xff,
- 0xe2,0xb1,0x8f,0x00,0x94,0x7c,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,
- 0xe2,0xb1,0x90,0x00,0x08,0xff,0xe2,0xb1,0x91,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,
- 0x92,0x00,0x08,0xff,0xe2,0xb1,0x93,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb1,
- 0x94,0x00,0x08,0xff,0xe2,0xb1,0x95,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0x96,0x00,
- 0x08,0xff,0xe2,0xb1,0x97,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb1,
- 0x98,0x00,0x08,0xff,0xe2,0xb1,0x99,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0x9a,0x00,
- 0x08,0xff,0xe2,0xb1,0x9b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb1,0x9c,0x00,
- 0x08,0xff,0xe2,0xb1,0x9d,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0x9e,0x00,0x00,0x00,
- 0x08,0x00,0xcf,0x86,0xd5,0x07,0x64,0x84,0x61,0x08,0x00,0xd4,0x63,0xd3,0x32,0xd2,
- 0x1b,0xd1,0x0c,0x10,0x08,0x09,0xff,0xe2,0xb1,0xa1,0x00,0x09,0x00,0x10,0x07,0x09,
- 0xff,0xc9,0xab,0x00,0x09,0xff,0xe1,0xb5,0xbd,0x00,0xd1,0x0b,0x10,0x07,0x09,0xff,
- 0xc9,0xbd,0x00,0x09,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xe2,0xb1,0xa8,0x00,0xd2,
- 0x18,0xd1,0x0c,0x10,0x04,0x09,0x00,0x09,0xff,0xe2,0xb1,0xaa,0x00,0x10,0x04,0x09,
- 0x00,0x09,0xff,0xe2,0xb1,0xac,0x00,0xd1,0x0b,0x10,0x04,0x09,0x00,0x0a,0xff,0xc9,
- 0x91,0x00,0x10,0x07,0x0a,0xff,0xc9,0xb1,0x00,0x0a,0xff,0xc9,0x90,0x00,0xd3,0x27,
- 0xd2,0x17,0xd1,0x0b,0x10,0x07,0x0b,0xff,0xc9,0x92,0x00,0x0a,0x00,0x10,0x08,0x0a,
- 0xff,0xe2,0xb1,0xb3,0x00,0x0a,0x00,0x91,0x0c,0x10,0x04,0x09,0x00,0x09,0xff,0xe2,
- 0xb1,0xb6,0x00,0x09,0x00,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,0x07,0x0b,
- 0xff,0xc8,0xbf,0x00,0x0b,0xff,0xc9,0x80,0x00,0xe0,0x83,0x01,0xcf,0x86,0xd5,0xc0,
- 0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0x81,0x00,
- 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x83,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,
- 0x08,0xff,0xe2,0xb2,0x85,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x87,0x00,
- 0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0x89,0x00,0x08,0x00,
- 0x10,0x08,0x08,0xff,0xe2,0xb2,0x8b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,
- 0xe2,0xb2,0x8d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x8f,0x00,0x08,0x00,
- 0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0x91,0x00,0x08,0x00,
- 0x10,0x08,0x08,0xff,0xe2,0xb2,0x93,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,
- 0xe2,0xb2,0x95,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x97,0x00,0x08,0x00,
- 0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0x99,0x00,0x08,0x00,0x10,0x08,
- 0x08,0xff,0xe2,0xb2,0x9b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,
- 0x9d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x9f,0x00,0x08,0x00,0xd4,0x60,
- 0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa1,0x00,0x08,0x00,
- 0x10,0x08,0x08,0xff,0xe2,0xb2,0xa3,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,
- 0xe2,0xb2,0xa5,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa7,0x00,0x08,0x00,
- 0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa9,0x00,0x08,0x00,0x10,0x08,
- 0x08,0xff,0xe2,0xb2,0xab,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,
- 0xad,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xaf,0x00,0x08,0x00,0xd3,0x30,
- 0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xb1,0x00,0x08,0x00,0x10,0x08,
- 0x08,0xff,0xe2,0xb2,0xb3,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,
- 0xb5,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xb7,0x00,0x08,0x00,0xd2,0x18,
- 0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xb9,0x00,0x08,0x00,0x10,0x08,0x08,0xff,
- 0xe2,0xb2,0xbb,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xbd,0x00,
- 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xbf,0x00,0x08,0x00,0xcf,0x86,0xd5,0xc0,
- 0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0x81,0x00,
- 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x83,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,
- 0x08,0xff,0xe2,0xb3,0x85,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x87,0x00,
- 0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0x89,0x00,0x08,0x00,
- 0x10,0x08,0x08,0xff,0xe2,0xb3,0x8b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,
- 0xe2,0xb3,0x8d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x8f,0x00,0x08,0x00,
- 0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0x91,0x00,0x08,0x00,
- 0x10,0x08,0x08,0xff,0xe2,0xb3,0x93,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,
- 0xe2,0xb3,0x95,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x97,0x00,0x08,0x00,
- 0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0x99,0x00,0x08,0x00,0x10,0x08,
- 0x08,0xff,0xe2,0xb3,0x9b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,
- 0x9d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x9f,0x00,0x08,0x00,0xd4,0x3b,
- 0xd3,0x1c,0x92,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0xa1,0x00,0x08,0x00,
- 0x10,0x08,0x08,0xff,0xe2,0xb3,0xa3,0x00,0x08,0x00,0x08,0x00,0xd2,0x10,0x51,0x04,
- 0x08,0x00,0x10,0x04,0x08,0x00,0x0b,0xff,0xe2,0xb3,0xac,0x00,0xe1,0xd0,0x5e,0x10,
- 0x04,0x0b,0x00,0x0b,0xff,0xe2,0xb3,0xae,0x00,0xe3,0xd5,0x5e,0x92,0x10,0x51,0x04,
- 0x0b,0xe6,0x10,0x08,0x0d,0xff,0xe2,0xb3,0xb3,0x00,0x0d,0x00,0x00,0x00,0xe2,0x98,
- 0x08,0xd1,0x0b,0xe0,0x8d,0x66,0xcf,0x86,0xcf,0x06,0x01,0x00,0xe0,0xe1,0x6b,0xcf,
- 0x86,0xe5,0xa7,0x05,0xd4,0x06,0xcf,0x06,0x04,0x00,0xd3,0x0c,0xe2,0x74,0x67,0xe1,
- 0x0b,0x67,0xcf,0x06,0x04,0x00,0xe2,0xdb,0x01,0xe1,0x26,0x01,0xd0,0x09,0xcf,0x86,
- 0x65,0x70,0x67,0x0a,0x00,0xcf,0x86,0xd5,0xc0,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,
- 0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,
- 0x99,0x83,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x85,0x00,0x0a,
- 0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x87,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,
- 0x08,0x0a,0xff,0xea,0x99,0x89,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x8b,
- 0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x8d,0x00,0x0a,0x00,0x10,
- 0x08,0x0a,0xff,0xea,0x99,0x8f,0x00,0x0a,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,
- 0x08,0x0a,0xff,0xea,0x99,0x91,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x93,
- 0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x95,0x00,0x0a,0x00,0x10,
- 0x08,0x0a,0xff,0xea,0x99,0x97,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,
- 0xff,0xea,0x99,0x99,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x9b,0x00,0x0a,
- 0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x9d,0x00,0x0a,0x00,0x10,0x08,0x0a,
- 0xff,0xea,0x99,0x9f,0x00,0x0a,0x00,0xe4,0xd9,0x66,0xd3,0x30,0xd2,0x18,0xd1,0x0c,
- 0x10,0x08,0x0c,0xff,0xea,0x99,0xa1,0x00,0x0c,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,
- 0xa3,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0xa5,0x00,0x0a,0x00,
- 0x10,0x08,0x0a,0xff,0xea,0x99,0xa7,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,
- 0x0a,0xff,0xea,0x99,0xa9,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0xab,0x00,
- 0x0a,0x00,0xe1,0x88,0x66,0x10,0x08,0x0a,0xff,0xea,0x99,0xad,0x00,0x0a,0x00,0xe0,
- 0xb1,0x66,0xcf,0x86,0x95,0xab,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,
- 0x0a,0xff,0xea,0x9a,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9a,0x83,0x00,
- 0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9a,0x85,0x00,0x0a,0x00,0x10,0x08,
- 0x0a,0xff,0xea,0x9a,0x87,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,
- 0xea,0x9a,0x89,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9a,0x8b,0x00,0x0a,0x00,
- 0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9a,0x8d,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,
- 0xea,0x9a,0x8f,0x00,0x0a,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,
- 0xea,0x9a,0x91,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9a,0x93,0x00,0x0a,0x00,
- 0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9a,0x95,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,
- 0xea,0x9a,0x97,0x00,0x0a,0x00,0xe2,0x0e,0x66,0xd1,0x0c,0x10,0x08,0x10,0xff,0xea,
- 0x9a,0x99,0x00,0x10,0x00,0x10,0x08,0x10,0xff,0xea,0x9a,0x9b,0x00,0x10,0x00,0x0b,
- 0x00,0xe1,0x10,0x02,0xd0,0xb9,0xcf,0x86,0xd5,0x07,0x64,0x1a,0x66,0x08,0x00,0xd4,
- 0x58,0xd3,0x28,0xd2,0x10,0x51,0x04,0x09,0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xa3,
- 0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9c,0xa5,0x00,0x0a,0x00,0x10,
- 0x08,0x0a,0xff,0xea,0x9c,0xa7,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,
- 0xff,0xea,0x9c,0xa9,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xab,0x00,0x0a,
- 0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9c,0xad,0x00,0x0a,0x00,0x10,0x08,0x0a,
- 0xff,0xea,0x9c,0xaf,0x00,0x0a,0x00,0xd3,0x28,0xd2,0x10,0x51,0x04,0x0a,0x00,0x10,
- 0x08,0x0a,0xff,0xea,0x9c,0xb3,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,
- 0x9c,0xb5,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xb7,0x00,0x0a,0x00,0xd2,
- 0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9c,0xb9,0x00,0x0a,0x00,0x10,0x08,0x0a,
- 0xff,0xea,0x9c,0xbb,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9c,0xbd,
- 0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xbf,0x00,0x0a,0x00,0xcf,0x86,0xd5,
- 0xc0,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x81,
- 0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x83,0x00,0x0a,0x00,0xd1,0x0c,0x10,
- 0x08,0x0a,0xff,0xea,0x9d,0x85,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x87,
- 0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x89,0x00,0x0a,
- 0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x8b,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,
- 0xff,0xea,0x9d,0x8d,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x8f,0x00,0x0a,
- 0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x91,0x00,0x0a,
- 0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x93,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,
- 0xff,0xea,0x9d,0x95,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x97,0x00,0x0a,
- 0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x99,0x00,0x0a,0x00,0x10,
- 0x08,0x0a,0xff,0xea,0x9d,0x9b,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,
- 0x9d,0x9d,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x9f,0x00,0x0a,0x00,0xd4,
- 0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa1,0x00,0x0a,
- 0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa3,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,
- 0xff,0xea,0x9d,0xa5,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa7,0x00,0x0a,
- 0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa9,0x00,0x0a,0x00,0x10,
- 0x08,0x0a,0xff,0xea,0x9d,0xab,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,
- 0x9d,0xad,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xaf,0x00,0x0a,0x00,0x53,
- 0x04,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x04,0x0a,0x00,0x0a,0xff,0xea,0x9d,0xba,
- 0x00,0x10,0x04,0x0a,0x00,0x0a,0xff,0xea,0x9d,0xbc,0x00,0xd1,0x0c,0x10,0x04,0x0a,
- 0x00,0x0a,0xff,0xe1,0xb5,0xb9,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xbf,0x00,0x0a,
- 0x00,0xe0,0x71,0x01,0xcf,0x86,0xd5,0xa6,0xd4,0x4e,0xd3,0x30,0xd2,0x18,0xd1,0x0c,
- 0x10,0x08,0x0a,0xff,0xea,0x9e,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9e,
- 0x83,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9e,0x85,0x00,0x0a,0x00,
- 0x10,0x08,0x0a,0xff,0xea,0x9e,0x87,0x00,0x0a,0x00,0xd2,0x10,0x51,0x04,0x0a,0x00,
- 0x10,0x04,0x0a,0x00,0x0a,0xff,0xea,0x9e,0x8c,0x00,0xe1,0x16,0x64,0x10,0x04,0x0a,
- 0x00,0x0c,0xff,0xc9,0xa5,0x00,0xd3,0x28,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0c,0xff,
- 0xea,0x9e,0x91,0x00,0x0c,0x00,0x10,0x08,0x0d,0xff,0xea,0x9e,0x93,0x00,0x0d,0x00,
- 0x51,0x04,0x10,0x00,0x10,0x08,0x10,0xff,0xea,0x9e,0x97,0x00,0x10,0x00,0xd2,0x18,
- 0xd1,0x0c,0x10,0x08,0x10,0xff,0xea,0x9e,0x99,0x00,0x10,0x00,0x10,0x08,0x10,0xff,
- 0xea,0x9e,0x9b,0x00,0x10,0x00,0xd1,0x0c,0x10,0x08,0x10,0xff,0xea,0x9e,0x9d,0x00,
- 0x10,0x00,0x10,0x08,0x10,0xff,0xea,0x9e,0x9f,0x00,0x10,0x00,0xd4,0x63,0xd3,0x30,
- 0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0c,0xff,0xea,0x9e,0xa1,0x00,0x0c,0x00,0x10,0x08,
- 0x0c,0xff,0xea,0x9e,0xa3,0x00,0x0c,0x00,0xd1,0x0c,0x10,0x08,0x0c,0xff,0xea,0x9e,
- 0xa5,0x00,0x0c,0x00,0x10,0x08,0x0c,0xff,0xea,0x9e,0xa7,0x00,0x0c,0x00,0xd2,0x1a,
- 0xd1,0x0c,0x10,0x08,0x0c,0xff,0xea,0x9e,0xa9,0x00,0x0c,0x00,0x10,0x07,0x0d,0xff,
- 0xc9,0xa6,0x00,0x10,0xff,0xc9,0x9c,0x00,0xd1,0x0e,0x10,0x07,0x10,0xff,0xc9,0xa1,
- 0x00,0x10,0xff,0xc9,0xac,0x00,0x10,0x07,0x12,0xff,0xc9,0xaa,0x00,0x14,0x00,0xd3,
- 0x35,0xd2,0x1d,0xd1,0x0e,0x10,0x07,0x10,0xff,0xca,0x9e,0x00,0x10,0xff,0xca,0x87,
- 0x00,0x10,0x07,0x11,0xff,0xca,0x9d,0x00,0x11,0xff,0xea,0xad,0x93,0x00,0xd1,0x0c,
- 0x10,0x08,0x11,0xff,0xea,0x9e,0xb5,0x00,0x11,0x00,0x10,0x08,0x11,0xff,0xea,0x9e,
- 0xb7,0x00,0x11,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x14,0xff,0xea,0x9e,0xb9,0x00,
- 0x14,0x00,0x10,0x08,0x15,0xff,0xea,0x9e,0xbb,0x00,0x15,0x00,0xd1,0x0c,0x10,0x08,
- 0x15,0xff,0xea,0x9e,0xbd,0x00,0x15,0x00,0x10,0x08,0x15,0xff,0xea,0x9e,0xbf,0x00,
- 0x15,0x00,0xcf,0x86,0xe5,0x50,0x63,0x94,0x2f,0x93,0x2b,0xd2,0x10,0x51,0x04,0x00,
- 0x00,0x10,0x08,0x15,0xff,0xea,0x9f,0x83,0x00,0x15,0x00,0xd1,0x0f,0x10,0x08,0x15,
- 0xff,0xea,0x9e,0x94,0x00,0x15,0xff,0xca,0x82,0x00,0x10,0x08,0x15,0xff,0xe1,0xb6,
- 0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0x30,0x66,0xd3,0x1d,0xe2,0xd7,0x63,
- 0xe1,0x86,0x63,0xe0,0x73,0x63,0xcf,0x86,0xe5,0x54,0x63,0x94,0x0b,0x93,0x07,0x62,
- 0x3f,0x63,0x08,0x00,0x08,0x00,0x08,0x00,0xd2,0x0f,0xe1,0xd6,0x64,0xe0,0xa3,0x64,
- 0xcf,0x86,0x65,0x88,0x64,0x0a,0x00,0xd1,0xab,0xd0,0x1a,0xcf,0x86,0xe5,0x93,0x65,
- 0xe4,0x76,0x65,0xe3,0x5d,0x65,0xe2,0x50,0x65,0x91,0x08,0x10,0x04,0x00,0x00,0x0c,
- 0x00,0x0c,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0xd4,0x0b,0x93,0x07,0x62,0xa3,0x65,
- 0x11,0x00,0x00,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,
- 0xa0,0x00,0x11,0xff,0xe1,0x8e,0xa1,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xa2,0x00,
- 0x11,0xff,0xe1,0x8e,0xa3,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xa4,0x00,
- 0x11,0xff,0xe1,0x8e,0xa5,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xa6,0x00,0x11,0xff,
- 0xe1,0x8e,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xa8,0x00,
- 0x11,0xff,0xe1,0x8e,0xa9,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xaa,0x00,0x11,0xff,
- 0xe1,0x8e,0xab,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xac,0x00,0x11,0xff,
- 0xe1,0x8e,0xad,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xae,0x00,0x11,0xff,0xe1,0x8e,
- 0xaf,0x00,0xe0,0x2e,0x65,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,
- 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xb0,0x00,0x11,0xff,0xe1,0x8e,0xb1,0x00,
- 0x10,0x08,0x11,0xff,0xe1,0x8e,0xb2,0x00,0x11,0xff,0xe1,0x8e,0xb3,0x00,0xd1,0x10,
- 0x10,0x08,0x11,0xff,0xe1,0x8e,0xb4,0x00,0x11,0xff,0xe1,0x8e,0xb5,0x00,0x10,0x08,
- 0x11,0xff,0xe1,0x8e,0xb6,0x00,0x11,0xff,0xe1,0x8e,0xb7,0x00,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x11,0xff,0xe1,0x8e,0xb8,0x00,0x11,0xff,0xe1,0x8e,0xb9,0x00,0x10,0x08,
- 0x11,0xff,0xe1,0x8e,0xba,0x00,0x11,0xff,0xe1,0x8e,0xbb,0x00,0xd1,0x10,0x10,0x08,
- 0x11,0xff,0xe1,0x8e,0xbc,0x00,0x11,0xff,0xe1,0x8e,0xbd,0x00,0x10,0x08,0x11,0xff,
- 0xe1,0x8e,0xbe,0x00,0x11,0xff,0xe1,0x8e,0xbf,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x11,0xff,0xe1,0x8f,0x80,0x00,0x11,0xff,0xe1,0x8f,0x81,0x00,0x10,0x08,
- 0x11,0xff,0xe1,0x8f,0x82,0x00,0x11,0xff,0xe1,0x8f,0x83,0x00,0xd1,0x10,0x10,0x08,
- 0x11,0xff,0xe1,0x8f,0x84,0x00,0x11,0xff,0xe1,0x8f,0x85,0x00,0x10,0x08,0x11,0xff,
- 0xe1,0x8f,0x86,0x00,0x11,0xff,0xe1,0x8f,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x11,0xff,0xe1,0x8f,0x88,0x00,0x11,0xff,0xe1,0x8f,0x89,0x00,0x10,0x08,0x11,0xff,
- 0xe1,0x8f,0x8a,0x00,0x11,0xff,0xe1,0x8f,0x8b,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,
- 0xe1,0x8f,0x8c,0x00,0x11,0xff,0xe1,0x8f,0x8d,0x00,0x10,0x08,0x11,0xff,0xe1,0x8f,
- 0x8e,0x00,0x11,0xff,0xe1,0x8f,0x8f,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x11,0xff,0xe1,0x8f,0x90,0x00,0x11,0xff,0xe1,0x8f,0x91,0x00,0x10,0x08,
- 0x11,0xff,0xe1,0x8f,0x92,0x00,0x11,0xff,0xe1,0x8f,0x93,0x00,0xd1,0x10,0x10,0x08,
- 0x11,0xff,0xe1,0x8f,0x94,0x00,0x11,0xff,0xe1,0x8f,0x95,0x00,0x10,0x08,0x11,0xff,
- 0xe1,0x8f,0x96,0x00,0x11,0xff,0xe1,0x8f,0x97,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x11,0xff,0xe1,0x8f,0x98,0x00,0x11,0xff,0xe1,0x8f,0x99,0x00,0x10,0x08,0x11,0xff,
- 0xe1,0x8f,0x9a,0x00,0x11,0xff,0xe1,0x8f,0x9b,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,
- 0xe1,0x8f,0x9c,0x00,0x11,0xff,0xe1,0x8f,0x9d,0x00,0x10,0x08,0x11,0xff,0xe1,0x8f,
- 0x9e,0x00,0x11,0xff,0xe1,0x8f,0x9f,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x11,0xff,0xe1,0x8f,0xa0,0x00,0x11,0xff,0xe1,0x8f,0xa1,0x00,0x10,0x08,0x11,0xff,
- 0xe1,0x8f,0xa2,0x00,0x11,0xff,0xe1,0x8f,0xa3,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,
- 0xe1,0x8f,0xa4,0x00,0x11,0xff,0xe1,0x8f,0xa5,0x00,0x10,0x08,0x11,0xff,0xe1,0x8f,
- 0xa6,0x00,0x11,0xff,0xe1,0x8f,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x11,0xff,
- 0xe1,0x8f,0xa8,0x00,0x11,0xff,0xe1,0x8f,0xa9,0x00,0x10,0x08,0x11,0xff,0xe1,0x8f,
- 0xaa,0x00,0x11,0xff,0xe1,0x8f,0xab,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8f,
- 0xac,0x00,0x11,0xff,0xe1,0x8f,0xad,0x00,0x10,0x08,0x11,0xff,0xe1,0x8f,0xae,0x00,
- 0x11,0xff,0xe1,0x8f,0xaf,0x00,0xd1,0x0c,0xe0,0x67,0x63,0xcf,0x86,0xcf,0x06,0x02,
- 0xff,0xff,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,
- 0x01,0x00,0xd4,0xae,0xd3,0x09,0xe2,0xd0,0x63,0xcf,0x06,0x01,0x00,0xd2,0x27,0xe1,
- 0x9b,0x6f,0xe0,0xa2,0x6d,0xcf,0x86,0xe5,0xbb,0x6c,0xe4,0x4a,0x6c,0xe3,0x15,0x6c,
- 0xe2,0xf4,0x6b,0xe1,0xe3,0x6b,0x10,0x08,0x01,0xff,0xe5,0x88,0x87,0x00,0x01,0xff,
- 0xe5,0xba,0xa6,0x00,0xe1,0xf0,0x73,0xe0,0x64,0x73,0xcf,0x86,0xe5,0x9e,0x72,0xd4,
- 0x3b,0x93,0x37,0xd2,0x1d,0xd1,0x0e,0x10,0x07,0x01,0xff,0x66,0x66,0x00,0x01,0xff,
- 0x66,0x69,0x00,0x10,0x07,0x01,0xff,0x66,0x6c,0x00,0x01,0xff,0x66,0x66,0x69,0x00,
- 0xd1,0x0f,0x10,0x08,0x01,0xff,0x66,0x66,0x6c,0x00,0x01,0xff,0x73,0x74,0x00,0x10,
- 0x07,0x01,0xff,0x73,0x74,0x00,0x00,0x00,0x00,0x00,0xe3,0x44,0x72,0xd2,0x11,0x51,
- 0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xd5,0xb4,0xd5,0xb6,0x00,0xd1,0x12,
- 0x10,0x09,0x01,0xff,0xd5,0xb4,0xd5,0xa5,0x00,0x01,0xff,0xd5,0xb4,0xd5,0xab,0x00,
- 0x10,0x09,0x01,0xff,0xd5,0xbe,0xd5,0xb6,0x00,0x01,0xff,0xd5,0xb4,0xd5,0xad,0x00,
- 0xd3,0x09,0xe2,0xbc,0x73,0xcf,0x06,0x01,0x00,0xd2,0x12,0xe1,0xab,0x74,0xe0,0x3c,
- 0x74,0xcf,0x86,0xe5,0x19,0x74,0x64,0x08,0x74,0x06,0x00,0xe1,0x11,0x75,0xe0,0xde,
- 0x74,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,
- 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x7c,0xd3,0x3c,0xd2,
- 0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0xef,0xbd,0x81,0x00,0x10,0x08,0x01,
- 0xff,0xef,0xbd,0x82,0x00,0x01,0xff,0xef,0xbd,0x83,0x00,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0xef,0xbd,0x84,0x00,0x01,0xff,0xef,0xbd,0x85,0x00,0x10,0x08,0x01,0xff,0xef,
- 0xbd,0x86,0x00,0x01,0xff,0xef,0xbd,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0xef,0xbd,0x88,0x00,0x01,0xff,0xef,0xbd,0x89,0x00,0x10,0x08,0x01,0xff,0xef,
- 0xbd,0x8a,0x00,0x01,0xff,0xef,0xbd,0x8b,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xef,
- 0xbd,0x8c,0x00,0x01,0xff,0xef,0xbd,0x8d,0x00,0x10,0x08,0x01,0xff,0xef,0xbd,0x8e,
- 0x00,0x01,0xff,0xef,0xbd,0x8f,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0xef,0xbd,0x90,0x00,0x01,0xff,0xef,0xbd,0x91,0x00,0x10,0x08,0x01,0xff,0xef,
- 0xbd,0x92,0x00,0x01,0xff,0xef,0xbd,0x93,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xef,
- 0xbd,0x94,0x00,0x01,0xff,0xef,0xbd,0x95,0x00,0x10,0x08,0x01,0xff,0xef,0xbd,0x96,
- 0x00,0x01,0xff,0xef,0xbd,0x97,0x00,0x92,0x1c,0xd1,0x10,0x10,0x08,0x01,0xff,0xef,
- 0xbd,0x98,0x00,0x01,0xff,0xef,0xbd,0x99,0x00,0x10,0x08,0x01,0xff,0xef,0xbd,0x9a,
- 0x00,0x01,0x00,0x01,0x00,0x83,0xe2,0xd9,0xb2,0xe1,0xc3,0xaf,0xe0,0x40,0xae,0xcf,
- 0x86,0xe5,0xe4,0x9a,0xc4,0xe3,0xc1,0x07,0xe2,0x62,0x06,0xe1,0x79,0x85,0xe0,0x09,
- 0x05,0xcf,0x86,0xe5,0xfb,0x02,0xd4,0x1c,0xe3,0xe7,0x75,0xe2,0x3e,0x75,0xe1,0x19,
- 0x75,0xe0,0xf2,0x74,0xcf,0x86,0xe5,0xbf,0x74,0x94,0x07,0x63,0xaa,0x74,0x07,0x00,
- 0x07,0x00,0xe3,0x93,0x77,0xe2,0x58,0x77,0xe1,0x77,0x01,0xe0,0xf0,0x76,0xcf,0x86,
- 0xe5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,
- 0x90,0x90,0xa8,0x00,0x05,0xff,0xf0,0x90,0x90,0xa9,0x00,0x10,0x09,0x05,0xff,0xf0,
- 0x90,0x90,0xaa,0x00,0x05,0xff,0xf0,0x90,0x90,0xab,0x00,0xd1,0x12,0x10,0x09,0x05,
- 0xff,0xf0,0x90,0x90,0xac,0x00,0x05,0xff,0xf0,0x90,0x90,0xad,0x00,0x10,0x09,0x05,
- 0xff,0xf0,0x90,0x90,0xae,0x00,0x05,0xff,0xf0,0x90,0x90,0xaf,0x00,0xd2,0x24,0xd1,
- 0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb0,0x00,0x05,0xff,0xf0,0x90,0x90,0xb1,
- 0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb2,0x00,0x05,0xff,0xf0,0x90,0x90,0xb3,
- 0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb4,0x00,0x05,0xff,0xf0,0x90,
- 0x90,0xb5,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb6,0x00,0x05,0xff,0xf0,0x90,
- 0x90,0xb7,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,
- 0xb8,0x00,0x05,0xff,0xf0,0x90,0x90,0xb9,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,
- 0xba,0x00,0x05,0xff,0xf0,0x90,0x90,0xbb,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,
- 0x90,0x90,0xbc,0x00,0x05,0xff,0xf0,0x90,0x90,0xbd,0x00,0x10,0x09,0x05,0xff,0xf0,
- 0x90,0x90,0xbe,0x00,0x05,0xff,0xf0,0x90,0x90,0xbf,0x00,0xd2,0x24,0xd1,0x12,0x10,
- 0x09,0x05,0xff,0xf0,0x90,0x91,0x80,0x00,0x05,0xff,0xf0,0x90,0x91,0x81,0x00,0x10,
- 0x09,0x05,0xff,0xf0,0x90,0x91,0x82,0x00,0x05,0xff,0xf0,0x90,0x91,0x83,0x00,0xd1,
- 0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,0x84,0x00,0x05,0xff,0xf0,0x90,0x91,0x85,
- 0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,0x86,0x00,0x05,0xff,0xf0,0x90,0x91,0x87,
- 0x00,0x94,0x4c,0x93,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,
- 0x88,0x00,0x05,0xff,0xf0,0x90,0x91,0x89,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,
- 0x8a,0x00,0x05,0xff,0xf0,0x90,0x91,0x8b,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,
- 0x90,0x91,0x8c,0x00,0x05,0xff,0xf0,0x90,0x91,0x8d,0x00,0x10,0x09,0x07,0xff,0xf0,
- 0x90,0x91,0x8e,0x00,0x07,0xff,0xf0,0x90,0x91,0x8f,0x00,0x05,0x00,0x05,0x00,0xd0,
- 0xa0,0xcf,0x86,0xd5,0x07,0x64,0x98,0x75,0x07,0x00,0xd4,0x07,0x63,0xa5,0x75,0x07,
- 0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0x98,0x00,
- 0x12,0xff,0xf0,0x90,0x93,0x99,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0x9a,0x00,
- 0x12,0xff,0xf0,0x90,0x93,0x9b,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,
- 0x9c,0x00,0x12,0xff,0xf0,0x90,0x93,0x9d,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,
- 0x9e,0x00,0x12,0xff,0xf0,0x90,0x93,0x9f,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,
- 0xff,0xf0,0x90,0x93,0xa0,0x00,0x12,0xff,0xf0,0x90,0x93,0xa1,0x00,0x10,0x09,0x12,
- 0xff,0xf0,0x90,0x93,0xa2,0x00,0x12,0xff,0xf0,0x90,0x93,0xa3,0x00,0xd1,0x12,0x10,
- 0x09,0x12,0xff,0xf0,0x90,0x93,0xa4,0x00,0x12,0xff,0xf0,0x90,0x93,0xa5,0x00,0x10,
- 0x09,0x12,0xff,0xf0,0x90,0x93,0xa6,0x00,0x12,0xff,0xf0,0x90,0x93,0xa7,0x00,0xcf,
- 0x86,0xe5,0x2e,0x75,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,
- 0xf0,0x90,0x93,0xa8,0x00,0x12,0xff,0xf0,0x90,0x93,0xa9,0x00,0x10,0x09,0x12,0xff,
- 0xf0,0x90,0x93,0xaa,0x00,0x12,0xff,0xf0,0x90,0x93,0xab,0x00,0xd1,0x12,0x10,0x09,
- 0x12,0xff,0xf0,0x90,0x93,0xac,0x00,0x12,0xff,0xf0,0x90,0x93,0xad,0x00,0x10,0x09,
- 0x12,0xff,0xf0,0x90,0x93,0xae,0x00,0x12,0xff,0xf0,0x90,0x93,0xaf,0x00,0xd2,0x24,
- 0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb0,0x00,0x12,0xff,0xf0,0x90,0x93,
- 0xb1,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb2,0x00,0x12,0xff,0xf0,0x90,0x93,
- 0xb3,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb4,0x00,0x12,0xff,0xf0,
- 0x90,0x93,0xb5,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb6,0x00,0x12,0xff,0xf0,
- 0x90,0x93,0xb7,0x00,0x93,0x28,0x92,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,
- 0x93,0xb8,0x00,0x12,0xff,0xf0,0x90,0x93,0xb9,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,
- 0x93,0xba,0x00,0x12,0xff,0xf0,0x90,0x93,0xbb,0x00,0x00,0x00,0x12,0x00,0xd4,0x1f,
- 0xe3,0x47,0x76,0xe2,0xd2,0x75,0xe1,0x71,0x75,0xe0,0x52,0x75,0xcf,0x86,0xe5,0x1f,
- 0x75,0x94,0x0a,0xe3,0x0a,0x75,0x62,0x01,0x75,0x07,0x00,0x07,0x00,0xe3,0x46,0x78,
- 0xe2,0x17,0x78,0xd1,0x09,0xe0,0xb4,0x77,0xcf,0x06,0x0b,0x00,0xe0,0xe7,0x77,0xcf,
- 0x86,0xe5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x11,0xff,
- 0xf0,0x90,0xb3,0x80,0x00,0x11,0xff,0xf0,0x90,0xb3,0x81,0x00,0x10,0x09,0x11,0xff,
- 0xf0,0x90,0xb3,0x82,0x00,0x11,0xff,0xf0,0x90,0xb3,0x83,0x00,0xd1,0x12,0x10,0x09,
- 0x11,0xff,0xf0,0x90,0xb3,0x84,0x00,0x11,0xff,0xf0,0x90,0xb3,0x85,0x00,0x10,0x09,
- 0x11,0xff,0xf0,0x90,0xb3,0x86,0x00,0x11,0xff,0xf0,0x90,0xb3,0x87,0x00,0xd2,0x24,
- 0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x88,0x00,0x11,0xff,0xf0,0x90,0xb3,
- 0x89,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x8a,0x00,0x11,0xff,0xf0,0x90,0xb3,
- 0x8b,0x00,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x8c,0x00,0x11,0xff,0xf0,
- 0x90,0xb3,0x8d,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x8e,0x00,0x11,0xff,0xf0,
- 0x90,0xb3,0x8f,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,
- 0xb3,0x90,0x00,0x11,0xff,0xf0,0x90,0xb3,0x91,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,
- 0xb3,0x92,0x00,0x11,0xff,0xf0,0x90,0xb3,0x93,0x00,0xd1,0x12,0x10,0x09,0x11,0xff,
- 0xf0,0x90,0xb3,0x94,0x00,0x11,0xff,0xf0,0x90,0xb3,0x95,0x00,0x10,0x09,0x11,0xff,
- 0xf0,0x90,0xb3,0x96,0x00,0x11,0xff,0xf0,0x90,0xb3,0x97,0x00,0xd2,0x24,0xd1,0x12,
- 0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x98,0x00,0x11,0xff,0xf0,0x90,0xb3,0x99,0x00,
- 0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x9a,0x00,0x11,0xff,0xf0,0x90,0xb3,0x9b,0x00,
- 0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x9c,0x00,0x11,0xff,0xf0,0x90,0xb3,
- 0x9d,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x9e,0x00,0x11,0xff,0xf0,0x90,0xb3,
- 0x9f,0x00,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,
- 0xb3,0xa0,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa1,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,
- 0xb3,0xa2,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa3,0x00,0xd1,0x12,0x10,0x09,0x11,0xff,
- 0xf0,0x90,0xb3,0xa4,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa5,0x00,0x10,0x09,0x11,0xff,
- 0xf0,0x90,0xb3,0xa6,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa7,0x00,0xd2,0x24,0xd1,0x12,
- 0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xa8,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa9,0x00,
- 0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xaa,0x00,0x11,0xff,0xf0,0x90,0xb3,0xab,0x00,
- 0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xac,0x00,0x11,0xff,0xf0,0x90,0xb3,
- 0xad,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xae,0x00,0x11,0xff,0xf0,0x90,0xb3,
- 0xaf,0x00,0x93,0x23,0x92,0x1f,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xb0,
- 0x00,0x11,0xff,0xf0,0x90,0xb3,0xb1,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xb2,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x15,0xe4,0xf9,0x7a,0xe3,0x03,
- 0x79,0xe2,0xfc,0x77,0xe1,0x4c,0x77,0xe0,0x05,0x77,0xcf,0x06,0x0c,0x00,0xe4,0x53,
- 0x7e,0xe3,0xac,0x7d,0xe2,0x55,0x7d,0xd1,0x0c,0xe0,0x1a,0x7d,0xcf,0x86,0x65,0xfb,
- 0x7c,0x14,0x00,0xe0,0x1e,0x7d,0xcf,0x86,0x55,0x04,0x00,0x00,0xd4,0x90,0xd3,0x48,
- 0xd2,0x24,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x80,0x00,0x10,0xff,0xf0,
- 0x91,0xa3,0x81,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x82,0x00,0x10,0xff,0xf0,
- 0x91,0xa3,0x83,0x00,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x84,0x00,0x10,
- 0xff,0xf0,0x91,0xa3,0x85,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x86,0x00,0x10,
- 0xff,0xf0,0x91,0xa3,0x87,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,
- 0xa3,0x88,0x00,0x10,0xff,0xf0,0x91,0xa3,0x89,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,
- 0xa3,0x8a,0x00,0x10,0xff,0xf0,0x91,0xa3,0x8b,0x00,0xd1,0x12,0x10,0x09,0x10,0xff,
- 0xf0,0x91,0xa3,0x8c,0x00,0x10,0xff,0xf0,0x91,0xa3,0x8d,0x00,0x10,0x09,0x10,0xff,
- 0xf0,0x91,0xa3,0x8e,0x00,0x10,0xff,0xf0,0x91,0xa3,0x8f,0x00,0xd3,0x48,0xd2,0x24,
- 0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x90,0x00,0x10,0xff,0xf0,0x91,0xa3,
- 0x91,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x92,0x00,0x10,0xff,0xf0,0x91,0xa3,
- 0x93,0x00,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x94,0x00,0x10,0xff,0xf0,
- 0x91,0xa3,0x95,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x96,0x00,0x10,0xff,0xf0,
- 0x91,0xa3,0x97,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x98,
- 0x00,0x10,0xff,0xf0,0x91,0xa3,0x99,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x9a,
- 0x00,0x10,0xff,0xf0,0x91,0xa3,0x9b,0x00,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,
- 0xa3,0x9c,0x00,0x10,0xff,0xf0,0x91,0xa3,0x9d,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,
- 0xa3,0x9e,0x00,0x10,0xff,0xf0,0x91,0xa3,0x9f,0x00,0xd1,0x11,0xe0,0x7a,0x80,0xcf,
- 0x86,0xe5,0x71,0x80,0xe4,0x3a,0x80,0xcf,0x06,0x00,0x00,0xe0,0x43,0x82,0xcf,0x86,
- 0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x09,0xe3,0x78,0x80,0xcf,0x06,0x0c,0x00,0xd3,
- 0x06,0xcf,0x06,0x00,0x00,0xe2,0xa3,0x81,0xe1,0x7e,0x81,0xd0,0x06,0xcf,0x06,0x00,
- 0x00,0xcf,0x86,0xa5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,
- 0x14,0xff,0xf0,0x96,0xb9,0xa0,0x00,0x14,0xff,0xf0,0x96,0xb9,0xa1,0x00,0x10,0x09,
- 0x14,0xff,0xf0,0x96,0xb9,0xa2,0x00,0x14,0xff,0xf0,0x96,0xb9,0xa3,0x00,0xd1,0x12,
- 0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa4,0x00,0x14,0xff,0xf0,0x96,0xb9,0xa5,0x00,
- 0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa6,0x00,0x14,0xff,0xf0,0x96,0xb9,0xa7,0x00,
- 0xd2,0x24,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa8,0x00,0x14,0xff,0xf0,
- 0x96,0xb9,0xa9,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xaa,0x00,0x14,0xff,0xf0,
- 0x96,0xb9,0xab,0x00,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xac,0x00,0x14,
- 0xff,0xf0,0x96,0xb9,0xad,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xae,0x00,0x14,
- 0xff,0xf0,0x96,0xb9,0xaf,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x14,0xff,
- 0xf0,0x96,0xb9,0xb0,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb1,0x00,0x10,0x09,0x14,0xff,
- 0xf0,0x96,0xb9,0xb2,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb3,0x00,0xd1,0x12,0x10,0x09,
- 0x14,0xff,0xf0,0x96,0xb9,0xb4,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb5,0x00,0x10,0x09,
- 0x14,0xff,0xf0,0x96,0xb9,0xb6,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb7,0x00,0xd2,0x24,
- 0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xb8,0x00,0x14,0xff,0xf0,0x96,0xb9,
- 0xb9,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xba,0x00,0x14,0xff,0xf0,0x96,0xb9,
- 0xbb,0x00,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xbc,0x00,0x14,0xff,0xf0,
- 0x96,0xb9,0xbd,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xbe,0x00,0x14,0xff,0xf0,
- 0x96,0xb9,0xbf,0x00,0x14,0x00,0xd2,0x14,0xe1,0x8d,0x81,0xe0,0x84,0x81,0xcf,0x86,
- 0xe5,0x45,0x81,0xe4,0x02,0x81,0xcf,0x06,0x12,0x00,0xd1,0x0b,0xe0,0xb8,0x82,0xcf,
- 0x86,0xcf,0x06,0x00,0x00,0xe0,0xf8,0x8a,0xcf,0x86,0xd5,0x22,0xe4,0x33,0x88,0xe3,
- 0xf6,0x87,0xe2,0x9b,0x87,0xe1,0x94,0x87,0xe0,0x8d,0x87,0xcf,0x86,0xe5,0x5e,0x87,
- 0xe4,0x45,0x87,0x93,0x07,0x62,0x34,0x87,0x12,0xe6,0x12,0xe6,0xe4,0x99,0x88,0xe3,
- 0x92,0x88,0xd2,0x09,0xe1,0x1b,0x88,0xcf,0x06,0x10,0x00,0xe1,0x82,0x88,0xe0,0x4f,
- 0x88,0xcf,0x86,0xe5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,
- 0x12,0xff,0xf0,0x9e,0xa4,0xa2,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xa3,0x00,0x10,0x09,
- 0x12,0xff,0xf0,0x9e,0xa4,0xa4,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xa5,0x00,0xd1,0x12,
- 0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xa6,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xa7,0x00,
- 0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xa8,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xa9,0x00,
- 0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xaa,0x00,0x12,0xff,0xf0,
- 0x9e,0xa4,0xab,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xac,0x00,0x12,0xff,0xf0,
- 0x9e,0xa4,0xad,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xae,0x00,0x12,
- 0xff,0xf0,0x9e,0xa4,0xaf,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xb0,0x00,0x12,
- 0xff,0xf0,0x9e,0xa4,0xb1,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,
- 0xf0,0x9e,0xa4,0xb2,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb3,0x00,0x10,0x09,0x12,0xff,
- 0xf0,0x9e,0xa4,0xb4,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb5,0x00,0xd1,0x12,0x10,0x09,
- 0x12,0xff,0xf0,0x9e,0xa4,0xb6,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb7,0x00,0x10,0x09,
- 0x12,0xff,0xf0,0x9e,0xa4,0xb8,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb9,0x00,0xd2,0x24,
- 0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xba,0x00,0x12,0xff,0xf0,0x9e,0xa4,
- 0xbb,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xbc,0x00,0x12,0xff,0xf0,0x9e,0xa4,
- 0xbd,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xbe,0x00,0x12,0xff,0xf0,
- 0x9e,0xa4,0xbf,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa5,0x80,0x00,0x12,0xff,0xf0,
- 0x9e,0xa5,0x81,0x00,0x94,0x1e,0x93,0x1a,0x92,0x16,0x91,0x12,0x10,0x09,0x12,0xff,
- 0xf0,0x9e,0xa5,0x82,0x00,0x12,0xff,0xf0,0x9e,0xa5,0x83,0x00,0x12,0x00,0x12,0x00,
- 0x12,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- /* nfdi_c0100 */
- 0x57,0x04,0x01,0x00,0xc6,0xe5,0x91,0x13,0xe4,0x27,0x0c,0xe3,0x61,0x07,0xe2,0xda,
- 0x01,0xc1,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0xe4,0xd4,0x7c,0xd3,0x3c,
- 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0x80,0x00,0x01,0xff,0x41,0xcc,
- 0x81,0x00,0x10,0x08,0x01,0xff,0x41,0xcc,0x82,0x00,0x01,0xff,0x41,0xcc,0x83,0x00,
- 0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0x88,0x00,0x01,0xff,0x41,0xcc,0x8a,0x00,
- 0x10,0x04,0x01,0x00,0x01,0xff,0x43,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x45,0xcc,0x80,0x00,0x01,0xff,0x45,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,
- 0x45,0xcc,0x82,0x00,0x01,0xff,0x45,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x49,0xcc,0x80,0x00,0x01,0xff,0x49,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,
- 0x82,0x00,0x01,0xff,0x49,0xcc,0x88,0x00,0xd3,0x38,0xd2,0x1c,0xd1,0x0c,0x10,0x04,
- 0x01,0x00,0x01,0xff,0x4e,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0x80,0x00,
- 0x01,0xff,0x4f,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0x82,0x00,
- 0x01,0xff,0x4f,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0x88,0x00,0x01,0x00,
- 0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x55,0xcc,0x80,0x00,0x10,0x08,
- 0x01,0xff,0x55,0xcc,0x81,0x00,0x01,0xff,0x55,0xcc,0x82,0x00,0x91,0x10,0x10,0x08,
- 0x01,0xff,0x55,0xcc,0x88,0x00,0x01,0xff,0x59,0xcc,0x81,0x00,0x01,0x00,0xd4,0x7c,
- 0xd3,0x3c,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0x80,0x00,0x01,0xff,
- 0x61,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x61,0xcc,0x82,0x00,0x01,0xff,0x61,0xcc,
- 0x83,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0x88,0x00,0x01,0xff,0x61,0xcc,
- 0x8a,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0x63,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0x65,0xcc,0x80,0x00,0x01,0xff,0x65,0xcc,0x81,0x00,0x10,0x08,
- 0x01,0xff,0x65,0xcc,0x82,0x00,0x01,0xff,0x65,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x69,0xcc,0x80,0x00,0x01,0xff,0x69,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,
- 0x69,0xcc,0x82,0x00,0x01,0xff,0x69,0xcc,0x88,0x00,0xd3,0x38,0xd2,0x1c,0xd1,0x0c,
- 0x10,0x04,0x01,0x00,0x01,0xff,0x6e,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,
- 0x80,0x00,0x01,0xff,0x6f,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,
- 0x82,0x00,0x01,0xff,0x6f,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x88,0x00,
- 0x01,0x00,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x75,0xcc,0x80,0x00,
- 0x10,0x08,0x01,0xff,0x75,0xcc,0x81,0x00,0x01,0xff,0x75,0xcc,0x82,0x00,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0x75,0xcc,0x88,0x00,0x01,0xff,0x79,0xcc,0x81,0x00,0x10,0x04,
- 0x01,0x00,0x01,0xff,0x79,0xcc,0x88,0x00,0xe1,0x9a,0x03,0xe0,0xd3,0x01,0xcf,0x86,
- 0xd5,0xf4,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,
- 0x84,0x00,0x01,0xff,0x61,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x41,0xcc,0x86,0x00,
- 0x01,0xff,0x61,0xcc,0x86,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0xa8,0x00,
- 0x01,0xff,0x61,0xcc,0xa8,0x00,0x10,0x08,0x01,0xff,0x43,0xcc,0x81,0x00,0x01,0xff,
- 0x63,0xcc,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x43,0xcc,0x82,0x00,
- 0x01,0xff,0x63,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x43,0xcc,0x87,0x00,0x01,0xff,
- 0x63,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x43,0xcc,0x8c,0x00,0x01,0xff,
- 0x63,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x44,0xcc,0x8c,0x00,0x01,0xff,0x64,0xcc,
- 0x8c,0x00,0xd3,0x34,0xd2,0x14,0x51,0x04,0x01,0x00,0x10,0x08,0x01,0xff,0x45,0xcc,
- 0x84,0x00,0x01,0xff,0x65,0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,
- 0x86,0x00,0x01,0xff,0x65,0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x87,0x00,
- 0x01,0xff,0x65,0xcc,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,
- 0xa8,0x00,0x01,0xff,0x65,0xcc,0xa8,0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x8c,0x00,
- 0x01,0xff,0x65,0xcc,0x8c,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x47,0xcc,0x82,0x00,
- 0x01,0xff,0x67,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x47,0xcc,0x86,0x00,0x01,0xff,
- 0x67,0xcc,0x86,0x00,0xd4,0x74,0xd3,0x34,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x47,0xcc,0x87,0x00,0x01,0xff,0x67,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x47,0xcc,
- 0xa7,0x00,0x01,0xff,0x67,0xcc,0xa7,0x00,0x91,0x10,0x10,0x08,0x01,0xff,0x48,0xcc,
- 0x82,0x00,0x01,0xff,0x68,0xcc,0x82,0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x49,0xcc,0x83,0x00,0x01,0xff,0x69,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,
- 0x49,0xcc,0x84,0x00,0x01,0xff,0x69,0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x49,0xcc,0x86,0x00,0x01,0xff,0x69,0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,
- 0xa8,0x00,0x01,0xff,0x69,0xcc,0xa8,0x00,0xd3,0x30,0xd2,0x10,0x91,0x0c,0x10,0x08,
- 0x01,0xff,0x49,0xcc,0x87,0x00,0x01,0x00,0x01,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x4a,0xcc,0x82,0x00,0x01,0xff,0x6a,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x4b,0xcc,
- 0xa7,0x00,0x01,0xff,0x6b,0xcc,0xa7,0x00,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,
- 0x01,0xff,0x4c,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x6c,0xcc,0x81,0x00,0x01,0xff,
- 0x4c,0xcc,0xa7,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6c,0xcc,0xa7,0x00,0x01,0xff,
- 0x4c,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x6c,0xcc,0x8c,0x00,0x01,0x00,0xcf,0x86,
- 0xd5,0xd4,0xd4,0x60,0xd3,0x30,0xd2,0x10,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,
- 0x01,0xff,0x4e,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e,0xcc,0x81,0x00,
- 0x01,0xff,0x4e,0xcc,0xa7,0x00,0x10,0x08,0x01,0xff,0x6e,0xcc,0xa7,0x00,0x01,0xff,
- 0x4e,0xcc,0x8c,0x00,0xd2,0x10,0x91,0x0c,0x10,0x08,0x01,0xff,0x6e,0xcc,0x8c,0x00,
- 0x01,0x00,0x01,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0x84,0x00,0x01,0xff,
- 0x6f,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0x86,0x00,0x01,0xff,0x6f,0xcc,
- 0x86,0x00,0xd3,0x34,0xd2,0x14,0x91,0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0x8b,0x00,
- 0x01,0xff,0x6f,0xcc,0x8b,0x00,0x01,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x52,0xcc,
- 0x81,0x00,0x01,0xff,0x72,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x52,0xcc,0xa7,0x00,
- 0x01,0xff,0x72,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x52,0xcc,
- 0x8c,0x00,0x01,0xff,0x72,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x53,0xcc,0x81,0x00,
- 0x01,0xff,0x73,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x53,0xcc,0x82,0x00,
- 0x01,0xff,0x73,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x53,0xcc,0xa7,0x00,0x01,0xff,
- 0x73,0xcc,0xa7,0x00,0xd4,0x74,0xd3,0x34,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x53,0xcc,0x8c,0x00,0x01,0xff,0x73,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x54,0xcc,
- 0xa7,0x00,0x01,0xff,0x74,0xcc,0xa7,0x00,0x91,0x10,0x10,0x08,0x01,0xff,0x54,0xcc,
- 0x8c,0x00,0x01,0xff,0x74,0xcc,0x8c,0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x55,0xcc,0x83,0x00,0x01,0xff,0x75,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,
- 0x55,0xcc,0x84,0x00,0x01,0xff,0x75,0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x55,0xcc,0x86,0x00,0x01,0xff,0x75,0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,
- 0x8a,0x00,0x01,0xff,0x75,0xcc,0x8a,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x55,0xcc,0x8b,0x00,0x01,0xff,0x75,0xcc,0x8b,0x00,0x10,0x08,0x01,0xff,
- 0x55,0xcc,0xa8,0x00,0x01,0xff,0x75,0xcc,0xa8,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x57,0xcc,0x82,0x00,0x01,0xff,0x77,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x59,0xcc,
- 0x82,0x00,0x01,0xff,0x79,0xcc,0x82,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x59,0xcc,0x88,0x00,0x01,0xff,0x5a,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,
- 0x81,0x00,0x01,0xff,0x5a,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x7a,0xcc,
- 0x87,0x00,0x01,0xff,0x5a,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x8c,0x00,
- 0x01,0x00,0xd0,0x4a,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x2c,0xd3,0x18,0x92,0x14,
- 0x91,0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0x9b,0x00,0x01,0xff,0x6f,0xcc,0x9b,0x00,
- 0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,
- 0x01,0xff,0x55,0xcc,0x9b,0x00,0x93,0x14,0x92,0x10,0x91,0x0c,0x10,0x08,0x01,0xff,
- 0x75,0xcc,0x9b,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0xb4,
- 0xd4,0x24,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x0c,0x10,0x04,0x01,0x00,
- 0x01,0xff,0x41,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x61,0xcc,0x8c,0x00,0x01,0xff,
- 0x49,0xcc,0x8c,0x00,0xd3,0x46,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,
- 0x8c,0x00,0x01,0xff,0x4f,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x8c,0x00,
- 0x01,0xff,0x55,0xcc,0x8c,0x00,0xd1,0x12,0x10,0x08,0x01,0xff,0x75,0xcc,0x8c,0x00,
- 0x01,0xff,0x55,0xcc,0x88,0xcc,0x84,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,
- 0x84,0x00,0x01,0xff,0x55,0xcc,0x88,0xcc,0x81,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,
- 0x01,0xff,0x75,0xcc,0x88,0xcc,0x81,0x00,0x01,0xff,0x55,0xcc,0x88,0xcc,0x8c,0x00,
- 0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x8c,0x00,0x01,0xff,0x55,0xcc,0x88,0xcc,
- 0x80,0x00,0xd1,0x0e,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x80,0x00,0x01,0x00,
- 0x10,0x0a,0x01,0xff,0x41,0xcc,0x88,0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x88,0xcc,
- 0x84,0x00,0xd4,0x80,0xd3,0x3a,0xd2,0x26,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,
- 0x87,0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x87,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,
- 0xc3,0x86,0xcc,0x84,0x00,0x01,0xff,0xc3,0xa6,0xcc,0x84,0x00,0x51,0x04,0x01,0x00,
- 0x10,0x08,0x01,0xff,0x47,0xcc,0x8c,0x00,0x01,0xff,0x67,0xcc,0x8c,0x00,0xd2,0x20,
- 0xd1,0x10,0x10,0x08,0x01,0xff,0x4b,0xcc,0x8c,0x00,0x01,0xff,0x6b,0xcc,0x8c,0x00,
- 0x10,0x08,0x01,0xff,0x4f,0xcc,0xa8,0x00,0x01,0xff,0x6f,0xcc,0xa8,0x00,0xd1,0x14,
- 0x10,0x0a,0x01,0xff,0x4f,0xcc,0xa8,0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc,0xa8,0xcc,
- 0x84,0x00,0x10,0x09,0x01,0xff,0xc6,0xb7,0xcc,0x8c,0x00,0x01,0xff,0xca,0x92,0xcc,
- 0x8c,0x00,0xd3,0x24,0xd2,0x10,0x91,0x0c,0x10,0x08,0x01,0xff,0x6a,0xcc,0x8c,0x00,
- 0x01,0x00,0x01,0x00,0x91,0x10,0x10,0x08,0x01,0xff,0x47,0xcc,0x81,0x00,0x01,0xff,
- 0x67,0xcc,0x81,0x00,0x04,0x00,0xd2,0x24,0xd1,0x10,0x10,0x08,0x04,0xff,0x4e,0xcc,
- 0x80,0x00,0x04,0xff,0x6e,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x8a,0xcc,
- 0x81,0x00,0x01,0xff,0x61,0xcc,0x8a,0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,
- 0xc3,0x86,0xcc,0x81,0x00,0x01,0xff,0xc3,0xa6,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,
- 0xc3,0x98,0xcc,0x81,0x00,0x01,0xff,0xc3,0xb8,0xcc,0x81,0x00,0xe2,0x07,0x02,0xe1,
- 0xae,0x01,0xe0,0x93,0x01,0xcf,0x86,0xd5,0xf4,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0x8f,0x00,0x01,0xff,0x61,0xcc,0x8f,0x00,0x10,
- 0x08,0x01,0xff,0x41,0xcc,0x91,0x00,0x01,0xff,0x61,0xcc,0x91,0x00,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0x45,0xcc,0x8f,0x00,0x01,0xff,0x65,0xcc,0x8f,0x00,0x10,0x08,0x01,
- 0xff,0x45,0xcc,0x91,0x00,0x01,0xff,0x65,0xcc,0x91,0x00,0xd2,0x20,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0x49,0xcc,0x8f,0x00,0x01,0xff,0x69,0xcc,0x8f,0x00,0x10,0x08,0x01,
- 0xff,0x49,0xcc,0x91,0x00,0x01,0xff,0x69,0xcc,0x91,0x00,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0x4f,0xcc,0x8f,0x00,0x01,0xff,0x6f,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x4f,
- 0xcc,0x91,0x00,0x01,0xff,0x6f,0xcc,0x91,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0x52,0xcc,0x8f,0x00,0x01,0xff,0x72,0xcc,0x8f,0x00,0x10,0x08,0x01,
- 0xff,0x52,0xcc,0x91,0x00,0x01,0xff,0x72,0xcc,0x91,0x00,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0x55,0xcc,0x8f,0x00,0x01,0xff,0x75,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x55,
- 0xcc,0x91,0x00,0x01,0xff,0x75,0xcc,0x91,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x04,
- 0xff,0x53,0xcc,0xa6,0x00,0x04,0xff,0x73,0xcc,0xa6,0x00,0x10,0x08,0x04,0xff,0x54,
- 0xcc,0xa6,0x00,0x04,0xff,0x74,0xcc,0xa6,0x00,0x51,0x04,0x04,0x00,0x10,0x08,0x04,
- 0xff,0x48,0xcc,0x8c,0x00,0x04,0xff,0x68,0xcc,0x8c,0x00,0xd4,0x68,0xd3,0x20,0xd2,
- 0x0c,0x91,0x08,0x10,0x04,0x06,0x00,0x07,0x00,0x04,0x00,0x51,0x04,0x04,0x00,0x10,
- 0x08,0x04,0xff,0x41,0xcc,0x87,0x00,0x04,0xff,0x61,0xcc,0x87,0x00,0xd2,0x24,0xd1,
- 0x10,0x10,0x08,0x04,0xff,0x45,0xcc,0xa7,0x00,0x04,0xff,0x65,0xcc,0xa7,0x00,0x10,
- 0x0a,0x04,0xff,0x4f,0xcc,0x88,0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc,0x88,0xcc,0x84,
- 0x00,0xd1,0x14,0x10,0x0a,0x04,0xff,0x4f,0xcc,0x83,0xcc,0x84,0x00,0x04,0xff,0x6f,
- 0xcc,0x83,0xcc,0x84,0x00,0x10,0x08,0x04,0xff,0x4f,0xcc,0x87,0x00,0x04,0xff,0x6f,
- 0xcc,0x87,0x00,0x93,0x30,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x04,0xff,0x4f,0xcc,0x87,
- 0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc,0x87,0xcc,0x84,0x00,0x10,0x08,0x04,0xff,0x59,
- 0xcc,0x84,0x00,0x04,0xff,0x79,0xcc,0x84,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x07,
- 0x00,0x08,0x00,0x08,0x00,0xcf,0x86,0x95,0x14,0x94,0x10,0x93,0x0c,0x92,0x08,0x11,
- 0x04,0x08,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x01,0x00,0x01,0x00,0xd0,0x22,0xcf,
- 0x86,0x55,0x04,0x01,0x00,0x94,0x18,0x53,0x04,0x01,0x00,0xd2,0x0c,0x91,0x08,0x10,
- 0x04,0x01,0x00,0x04,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x07,0x00,0x01,0x00,0xcf,
- 0x86,0xd5,0x18,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,
- 0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x04,0x00,0x94,0x18,0x53,0x04,0x01,0x00,0xd2,
- 0x08,0x11,0x04,0x01,0x00,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x07,
- 0x00,0x07,0x00,0xe1,0x34,0x01,0xd0,0x72,0xcf,0x86,0xd5,0x24,0x54,0x04,0x01,0xe6,
- 0xd3,0x10,0x52,0x04,0x01,0xe6,0x91,0x08,0x10,0x04,0x01,0xe6,0x01,0xe8,0x01,0xdc,
- 0x92,0x0c,0x51,0x04,0x01,0xdc,0x10,0x04,0x01,0xe8,0x01,0xd8,0x01,0xdc,0xd4,0x2c,
- 0xd3,0x1c,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0xdc,0x01,0xca,0x10,0x04,0x01,0xca,
- 0x01,0xdc,0x51,0x04,0x01,0xdc,0x10,0x04,0x01,0xdc,0x01,0xca,0x92,0x0c,0x91,0x08,
- 0x10,0x04,0x01,0xca,0x01,0xdc,0x01,0xdc,0x01,0xdc,0xd3,0x08,0x12,0x04,0x01,0xdc,
- 0x01,0x01,0xd2,0x0c,0x91,0x08,0x10,0x04,0x01,0x01,0x01,0xdc,0x01,0xdc,0x91,0x08,
- 0x10,0x04,0x01,0xdc,0x01,0xe6,0x01,0xe6,0xcf,0x86,0xd5,0x7e,0xd4,0x46,0xd3,0x2e,
- 0xd2,0x19,0xd1,0x0e,0x10,0x07,0x01,0xff,0xcc,0x80,0x00,0x01,0xff,0xcc,0x81,0x00,
- 0x10,0x04,0x01,0xe6,0x01,0xff,0xcc,0x93,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xcc,
- 0x88,0xcc,0x81,0x00,0x01,0xf0,0x10,0x04,0x04,0xe6,0x04,0xdc,0xd2,0x08,0x11,0x04,
- 0x04,0xdc,0x04,0xe6,0xd1,0x08,0x10,0x04,0x04,0xe6,0x04,0xdc,0x10,0x04,0x04,0xdc,
- 0x06,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x07,0xe6,0x10,0x04,0x07,0xe6,0x07,0xdc,
- 0x51,0x04,0x07,0xdc,0x10,0x04,0x07,0xdc,0x07,0xe6,0xd2,0x10,0xd1,0x08,0x10,0x04,
- 0x08,0xe8,0x08,0xdc,0x10,0x04,0x08,0xdc,0x08,0xe6,0xd1,0x08,0x10,0x04,0x08,0xe9,
- 0x07,0xea,0x10,0x04,0x07,0xea,0x07,0xe9,0xd4,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,
- 0x01,0xea,0x10,0x04,0x04,0xe9,0x06,0xe6,0x06,0xe6,0x06,0xe6,0xd3,0x13,0x52,0x04,
- 0x0a,0x00,0x91,0x0b,0x10,0x07,0x01,0xff,0xca,0xb9,0x00,0x01,0x00,0x0a,0x00,0xd2,
- 0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x01,0x00,0x09,0x00,0x51,0x04,0x09,0x00,0x10,
- 0x06,0x01,0xff,0x3b,0x00,0x10,0x00,0xd0,0xe1,0xcf,0x86,0xd5,0x7a,0xd4,0x5f,0xd3,
- 0x21,0x52,0x04,0x00,0x00,0xd1,0x0d,0x10,0x04,0x01,0x00,0x01,0xff,0xc2,0xa8,0xcc,
- 0x81,0x00,0x10,0x09,0x01,0xff,0xce,0x91,0xcc,0x81,0x00,0x01,0xff,0xc2,0xb7,0x00,
- 0xd2,0x1f,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x95,0xcc,0x81,0x00,0x01,0xff,0xce,
- 0x97,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0x99,0xcc,0x81,0x00,0x00,0x00,0xd1,
- 0x0d,0x10,0x09,0x01,0xff,0xce,0x9f,0xcc,0x81,0x00,0x00,0x00,0x10,0x09,0x01,0xff,
- 0xce,0xa5,0xcc,0x81,0x00,0x01,0xff,0xce,0xa9,0xcc,0x81,0x00,0x93,0x17,0x92,0x13,
- 0x91,0x0f,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x88,0xcc,0x81,0x00,0x01,0x00,0x01,
- 0x00,0x01,0x00,0x01,0x00,0xd4,0x4a,0xd3,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,
- 0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,
- 0xff,0xce,0x99,0xcc,0x88,0x00,0x01,0xff,0xce,0xa5,0xcc,0x88,0x00,0xd1,0x12,0x10,
- 0x09,0x01,0xff,0xce,0xb1,0xcc,0x81,0x00,0x01,0xff,0xce,0xb5,0xcc,0x81,0x00,0x10,
- 0x09,0x01,0xff,0xce,0xb7,0xcc,0x81,0x00,0x01,0xff,0xce,0xb9,0xcc,0x81,0x00,0x93,
- 0x17,0x92,0x13,0x91,0x0f,0x10,0x0b,0x01,0xff,0xcf,0x85,0xcc,0x88,0xcc,0x81,0x00,
- 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x7b,0xd4,0x39,0x53,0x04,
- 0x01,0x00,0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x88,
- 0x00,0x01,0xff,0xcf,0x85,0xcc,0x88,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xbf,
- 0xcc,0x81,0x00,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xcf,0x89,
- 0xcc,0x81,0x00,0x0a,0x00,0xd3,0x26,0xd2,0x11,0x51,0x04,0x01,0x00,0x10,0x04,0x01,
- 0x00,0x01,0xff,0xcf,0x92,0xcc,0x81,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xcf,0x92,
- 0xcc,0x88,0x00,0x01,0x00,0x10,0x04,0x01,0x00,0x04,0x00,0xd2,0x0c,0x51,0x04,0x06,
- 0x00,0x10,0x04,0x01,0x00,0x04,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x10,
- 0x04,0x01,0x00,0x04,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,
- 0x00,0x04,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,
- 0x04,0x05,0x00,0x10,0x04,0x06,0x00,0x07,0x00,0x12,0x04,0x07,0x00,0x08,0x00,0xe3,
- 0x47,0x04,0xe2,0xbe,0x02,0xe1,0x07,0x01,0xd0,0x8b,0xcf,0x86,0xd5,0x6c,0xd4,0x53,
- 0xd3,0x30,0xd2,0x1f,0xd1,0x12,0x10,0x09,0x04,0xff,0xd0,0x95,0xcc,0x80,0x00,0x01,
- 0xff,0xd0,0x95,0xcc,0x88,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0x93,0xcc,0x81,
- 0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0x86,0xcc,0x88,0x00,
- 0x52,0x04,0x01,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0x9a,0xcc,0x81,0x00,0x04,
- 0xff,0xd0,0x98,0xcc,0x80,0x00,0x10,0x09,0x01,0xff,0xd0,0xa3,0xcc,0x86,0x00,0x01,
- 0x00,0x53,0x04,0x01,0x00,0x92,0x11,0x91,0x0d,0x10,0x04,0x01,0x00,0x01,0xff,0xd0,
- 0x98,0xcc,0x86,0x00,0x01,0x00,0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,
- 0x92,0x11,0x91,0x0d,0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x86,0x00,0x01,
- 0x00,0x01,0x00,0xcf,0x86,0xd5,0x57,0x54,0x04,0x01,0x00,0xd3,0x30,0xd2,0x1f,0xd1,
- 0x12,0x10,0x09,0x04,0xff,0xd0,0xb5,0xcc,0x80,0x00,0x01,0xff,0xd0,0xb5,0xcc,0x88,
- 0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0xb3,0xcc,0x81,0x00,0x51,0x04,0x01,0x00,
- 0x10,0x04,0x01,0x00,0x01,0xff,0xd1,0x96,0xcc,0x88,0x00,0x52,0x04,0x01,0x00,0xd1,
- 0x12,0x10,0x09,0x01,0xff,0xd0,0xba,0xcc,0x81,0x00,0x04,0xff,0xd0,0xb8,0xcc,0x80,
- 0x00,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x86,0x00,0x01,0x00,0x54,0x04,0x01,0x00,
- 0x93,0x1a,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xd1,0xb4,
- 0xcc,0x8f,0x00,0x01,0xff,0xd1,0xb5,0xcc,0x8f,0x00,0x01,0x00,0xd0,0x2e,0xcf,0x86,
- 0x95,0x28,0x94,0x24,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,
- 0x01,0xe6,0x51,0x04,0x01,0xe6,0x10,0x04,0x01,0xe6,0x0a,0xe6,0x92,0x08,0x11,0x04,
- 0x04,0x00,0x06,0x00,0x04,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0xbe,0xd4,0x4a,
- 0xd3,0x2a,0xd2,0x1a,0xd1,0x0d,0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0x96,0xcc,0x86,
- 0x00,0x10,0x09,0x01,0xff,0xd0,0xb6,0xcc,0x86,0x00,0x01,0x00,0xd1,0x08,0x10,0x04,
- 0x01,0x00,0x06,0x00,0x10,0x04,0x06,0x00,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,
- 0x01,0x00,0x06,0x00,0x10,0x04,0x06,0x00,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,
- 0x06,0x00,0x10,0x04,0x06,0x00,0x09,0x00,0xd3,0x3a,0xd2,0x24,0xd1,0x12,0x10,0x09,
- 0x01,0xff,0xd0,0x90,0xcc,0x86,0x00,0x01,0xff,0xd0,0xb0,0xcc,0x86,0x00,0x10,0x09,
- 0x01,0xff,0xd0,0x90,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb0,0xcc,0x88,0x00,0x51,0x04,
- 0x01,0x00,0x10,0x09,0x01,0xff,0xd0,0x95,0xcc,0x86,0x00,0x01,0xff,0xd0,0xb5,0xcc,
- 0x86,0x00,0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xd3,0x98,0xcc,0x88,
- 0x00,0x01,0xff,0xd3,0x99,0xcc,0x88,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0x96,
- 0xcc,0x88,0x00,0x01,0xff,0xd0,0xb6,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,0xd0,0x97,
- 0xcc,0x88,0x00,0x01,0xff,0xd0,0xb7,0xcc,0x88,0x00,0xd4,0x74,0xd3,0x3a,0xd2,0x16,
- 0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xd0,0x98,0xcc,0x84,0x00,0x01,0xff,0xd0,
- 0xb8,0xcc,0x84,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0x98,0xcc,0x88,0x00,0x01,
- 0xff,0xd0,0xb8,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,0xd0,0x9e,0xcc,0x88,0x00,0x01,
- 0xff,0xd0,0xbe,0xcc,0x88,0x00,0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,
- 0xd3,0xa8,0xcc,0x88,0x00,0x01,0xff,0xd3,0xa9,0xcc,0x88,0x00,0xd1,0x12,0x10,0x09,
- 0x04,0xff,0xd0,0xad,0xcc,0x88,0x00,0x04,0xff,0xd1,0x8d,0xcc,0x88,0x00,0x10,0x09,
- 0x01,0xff,0xd0,0xa3,0xcc,0x84,0x00,0x01,0xff,0xd1,0x83,0xcc,0x84,0x00,0xd3,0x3a,
- 0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0xa3,0xcc,0x88,0x00,0x01,0xff,0xd1,
- 0x83,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,0xd0,0xa3,0xcc,0x8b,0x00,0x01,0xff,0xd1,
- 0x83,0xcc,0x8b,0x00,0x91,0x12,0x10,0x09,0x01,0xff,0xd0,0xa7,0xcc,0x88,0x00,0x01,
- 0xff,0xd1,0x87,0xcc,0x88,0x00,0x08,0x00,0x92,0x16,0x91,0x12,0x10,0x09,0x01,0xff,
- 0xd0,0xab,0xcc,0x88,0x00,0x01,0xff,0xd1,0x8b,0xcc,0x88,0x00,0x09,0x00,0x09,0x00,
- 0xd1,0x74,0xd0,0x36,0xcf,0x86,0xd5,0x10,0x54,0x04,0x06,0x00,0x93,0x08,0x12,0x04,
- 0x09,0x00,0x0a,0x00,0x0a,0x00,0xd4,0x10,0x93,0x0c,0x52,0x04,0x0a,0x00,0x11,0x04,
- 0x0b,0x00,0x0c,0x00,0x10,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,
- 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x24,0x54,0x04,0x01,0x00,
- 0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,
- 0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x14,
- 0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
- 0x01,0x00,0x01,0x00,0xd0,0xba,0xcf,0x86,0xd5,0x4c,0xd4,0x24,0x53,0x04,0x01,0x00,
- 0xd2,0x10,0xd1,0x08,0x10,0x04,0x14,0x00,0x01,0x00,0x10,0x04,0x04,0x00,0x00,0x00,
- 0xd1,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x04,0x10,0x00,0x0d,0x00,0xd3,0x18,
- 0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x02,0xdc,0x02,0xe6,0x51,0x04,0x02,0xe6,
- 0x10,0x04,0x02,0xdc,0x02,0xe6,0x92,0x0c,0x51,0x04,0x02,0xe6,0x10,0x04,0x02,0xde,
- 0x02,0xdc,0x02,0xe6,0xd4,0x2c,0xd3,0x10,0x92,0x0c,0x51,0x04,0x02,0xe6,0x10,0x04,
- 0x08,0xdc,0x02,0xdc,0x02,0xdc,0xd2,0x0c,0x51,0x04,0x02,0xe6,0x10,0x04,0x02,0xdc,
- 0x02,0xe6,0xd1,0x08,0x10,0x04,0x02,0xe6,0x02,0xde,0x10,0x04,0x02,0xe4,0x02,0xe6,
- 0xd3,0x20,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x0a,0x01,0x0b,0x10,0x04,0x01,0x0c,
- 0x01,0x0d,0xd1,0x08,0x10,0x04,0x01,0x0e,0x01,0x0f,0x10,0x04,0x01,0x10,0x01,0x11,
- 0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x12,0x01,0x13,0x10,0x04,0x09,0x13,0x01,0x14,
- 0xd1,0x08,0x10,0x04,0x01,0x15,0x01,0x16,0x10,0x04,0x01,0x00,0x01,0x17,0xcf,0x86,
- 0xd5,0x28,0x94,0x24,0x93,0x20,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x01,0x18,
- 0x10,0x04,0x01,0x19,0x01,0x00,0xd1,0x08,0x10,0x04,0x02,0xe6,0x08,0xdc,0x10,0x04,
- 0x08,0x00,0x08,0x12,0x00,0x00,0x01,0x00,0xd4,0x1c,0x53,0x04,0x01,0x00,0xd2,0x0c,
- 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,
- 0x00,0x00,0x14,0x00,0x93,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0xe2,0xfa,0x01,0xe1,0x2a,0x01,0xd0,0xa7,0xcf,0x86,
- 0xd5,0x54,0xd4,0x28,0xd3,0x10,0x52,0x04,0x07,0x00,0x91,0x08,0x10,0x04,0x0d,0x00,
- 0x10,0x00,0x0a,0x00,0xd2,0x0c,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x00,0x08,0x00,
- 0x91,0x08,0x10,0x04,0x01,0x00,0x07,0x00,0x07,0x00,0xd3,0x0c,0x52,0x04,0x07,0xe6,
- 0x11,0x04,0x07,0xe6,0x0a,0xe6,0xd2,0x10,0xd1,0x08,0x10,0x04,0x0a,0x1e,0x0a,0x1f,
- 0x10,0x04,0x0a,0x20,0x01,0x00,0xd1,0x08,0x10,0x04,0x0f,0x00,0x00,0x00,0x10,0x04,
- 0x08,0x00,0x01,0x00,0xd4,0x3d,0x93,0x39,0xd2,0x1a,0xd1,0x08,0x10,0x04,0x0c,0x00,
- 0x01,0x00,0x10,0x09,0x01,0xff,0xd8,0xa7,0xd9,0x93,0x00,0x01,0xff,0xd8,0xa7,0xd9,
- 0x94,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd9,0x88,0xd9,0x94,0x00,0x01,0xff,0xd8,
- 0xa7,0xd9,0x95,0x00,0x10,0x09,0x01,0xff,0xd9,0x8a,0xd9,0x94,0x00,0x01,0x00,0x01,
- 0x00,0x53,0x04,0x01,0x00,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x0a,
- 0x00,0x0a,0x00,0xcf,0x86,0xd5,0x5c,0xd4,0x20,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,
- 0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0x1b,0xd1,0x08,0x10,0x04,0x01,0x1c,0x01,
- 0x1d,0x10,0x04,0x01,0x1e,0x01,0x1f,0xd3,0x20,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,
- 0x20,0x01,0x21,0x10,0x04,0x01,0x22,0x04,0xe6,0xd1,0x08,0x10,0x04,0x04,0xe6,0x04,
- 0xdc,0x10,0x04,0x07,0xdc,0x07,0xe6,0xd2,0x0c,0x91,0x08,0x10,0x04,0x07,0xe6,0x08,
- 0xe6,0x08,0xe6,0xd1,0x08,0x10,0x04,0x08,0xdc,0x08,0xe6,0x10,0x04,0x08,0xe6,0x0c,
- 0xdc,0xd4,0x10,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x11,0x04,0x01,0x00,0x06,
- 0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x23,0x01,0x00,0x01,0x00,0x01,
- 0x00,0x01,0x00,0xd0,0x22,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x53,
- 0x04,0x01,0x00,0xd2,0x08,0x11,0x04,0x04,0x00,0x01,0x00,0x51,0x04,0x01,0x00,0x10,
- 0x04,0x01,0x00,0x04,0x00,0xcf,0x86,0xd5,0x5b,0xd4,0x2e,0xd3,0x1e,0x92,0x1a,0xd1,
- 0x0d,0x10,0x09,0x01,0xff,0xdb,0x95,0xd9,0x94,0x00,0x01,0x00,0x10,0x09,0x01,0xff,
- 0xdb,0x81,0xd9,0x94,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,
- 0x00,0x10,0x04,0x01,0x00,0x04,0x00,0xd3,0x19,0xd2,0x11,0x51,0x04,0x01,0x00,0x10,
- 0x04,0x01,0x00,0x01,0xff,0xdb,0x92,0xd9,0x94,0x00,0x11,0x04,0x01,0x00,0x01,0xe6,
- 0x52,0x04,0x01,0xe6,0xd1,0x08,0x10,0x04,0x01,0xe6,0x01,0x00,0x10,0x04,0x01,0x00,
- 0x01,0xe6,0xd4,0x38,0xd3,0x1c,0xd2,0x0c,0x51,0x04,0x01,0xe6,0x10,0x04,0x01,0xe6,
- 0x01,0xdc,0xd1,0x08,0x10,0x04,0x01,0xe6,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xe6,
- 0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0xe6,0x01,0x00,0x10,0x04,0x01,0xdc,0x01,0xe6,
- 0x91,0x08,0x10,0x04,0x01,0xe6,0x01,0xdc,0x07,0x00,0x53,0x04,0x01,0x00,0xd2,0x08,
- 0x11,0x04,0x01,0x00,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x07,0x00,
- 0xd1,0xc8,0xd0,0x76,0xcf,0x86,0xd5,0x28,0xd4,0x14,0x53,0x04,0x04,0x00,0x52,0x04,
- 0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x00,0x00,0x04,0x00,0x93,0x10,0x92,0x0c,
- 0x91,0x08,0x10,0x04,0x04,0x00,0x04,0x24,0x04,0x00,0x04,0x00,0x04,0x00,0xd4,0x14,
- 0x53,0x04,0x04,0x00,0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x07,0x00,
- 0x07,0x00,0xd3,0x1c,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0xe6,0x04,0xdc,0x04,0xe6,
- 0xd1,0x08,0x10,0x04,0x04,0xdc,0x04,0xe6,0x10,0x04,0x04,0xe6,0x04,0xdc,0xd2,0x0c,
- 0x51,0x04,0x04,0xdc,0x10,0x04,0x04,0xe6,0x04,0xdc,0xd1,0x08,0x10,0x04,0x04,0xdc,
- 0x04,0xe6,0x10,0x04,0x04,0xdc,0x04,0xe6,0xcf,0x86,0xd5,0x3c,0x94,0x38,0xd3,0x1c,
- 0xd2,0x0c,0x51,0x04,0x04,0xe6,0x10,0x04,0x04,0xdc,0x04,0xe6,0xd1,0x08,0x10,0x04,
- 0x04,0xdc,0x04,0xe6,0x10,0x04,0x04,0xdc,0x04,0xe6,0xd2,0x10,0xd1,0x08,0x10,0x04,
- 0x04,0xdc,0x04,0xe6,0x10,0x04,0x04,0xe6,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,
- 0x07,0x00,0x07,0x00,0x08,0x00,0x94,0x10,0x53,0x04,0x08,0x00,0x52,0x04,0x08,0x00,
- 0x11,0x04,0x08,0x00,0x0a,0x00,0x0a,0x00,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x04,0x00,
- 0x54,0x04,0x04,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x06,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,0x09,0x00,0xd4,0x14,0x53,0x04,
- 0x09,0x00,0x92,0x0c,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x09,0xe6,0x09,0xe6,
- 0xd3,0x10,0x92,0x0c,0x51,0x04,0x09,0xe6,0x10,0x04,0x09,0xdc,0x09,0xe6,0x09,0x00,
- 0xd2,0x0c,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x00,0x00,0x91,0x08,0x10,0x04,
- 0x00,0x00,0x14,0xdc,0x14,0x00,0xe4,0x78,0x57,0xe3,0xda,0x3e,0xe2,0x89,0x3e,0xe1,
- 0x91,0x2c,0xe0,0x21,0x10,0xcf,0x86,0xc5,0xe4,0x80,0x08,0xe3,0xcb,0x03,0xe2,0x61,
- 0x01,0xd1,0x94,0xd0,0x5a,0xcf,0x86,0xd5,0x20,0x54,0x04,0x0b,0x00,0xd3,0x0c,0x52,
- 0x04,0x0b,0x00,0x11,0x04,0x0b,0x00,0x0b,0xe6,0x92,0x0c,0x51,0x04,0x0b,0xe6,0x10,
- 0x04,0x0b,0x00,0x0b,0xe6,0x0b,0xe6,0xd4,0x24,0xd3,0x10,0x52,0x04,0x0b,0xe6,0x91,
- 0x08,0x10,0x04,0x0b,0x00,0x0b,0xe6,0x0b,0xe6,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0b,
- 0x00,0x0b,0xe6,0x0b,0xe6,0x11,0x04,0x0b,0xe6,0x00,0x00,0x53,0x04,0x0b,0x00,0x52,
- 0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0xcf,0x86,0xd5,
- 0x20,0x54,0x04,0x0c,0x00,0x53,0x04,0x0c,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0c,
- 0x00,0x0c,0xdc,0x0c,0xdc,0x51,0x04,0x00,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x94,
- 0x14,0x53,0x04,0x13,0x00,0x92,0x0c,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xd0,0x4a,0xcf,0x86,0x55,0x04,0x00,0x00,0xd4,0x20,0xd3,
- 0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0d,0x00,0x10,0x00,0x0d,0x00,0x0d,0x00,0x52,
- 0x04,0x0d,0x00,0x91,0x08,0x10,0x04,0x0d,0x00,0x10,0x00,0x10,0x00,0xd3,0x18,0xd2,
- 0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x11,0x00,0x91,0x08,0x10,0x04,0x11,
- 0x00,0x00,0x00,0x12,0x00,0x52,0x04,0x12,0x00,0x11,0x04,0x12,0x00,0x00,0x00,0xcf,
- 0x86,0xd5,0x18,0x54,0x04,0x00,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,
- 0x04,0x00,0x00,0x14,0xdc,0x12,0xe6,0x12,0xe6,0xd4,0x30,0xd3,0x18,0xd2,0x0c,0x51,
- 0x04,0x12,0xe6,0x10,0x04,0x12,0x00,0x11,0xdc,0x51,0x04,0x0d,0xe6,0x10,0x04,0x0d,
- 0xdc,0x0d,0xe6,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0d,0xe6,0x0d,0xdc,0x0d,0xe6,0x91,
- 0x08,0x10,0x04,0x0d,0xe6,0x0d,0xdc,0x0d,0xdc,0xd3,0x1c,0xd2,0x10,0xd1,0x08,0x10,
- 0x04,0x0d,0x1b,0x0d,0x1c,0x10,0x04,0x0d,0x1d,0x0d,0xe6,0x51,0x04,0x0d,0xe6,0x10,
- 0x04,0x0d,0xdc,0x0d,0xe6,0xd2,0x10,0xd1,0x08,0x10,0x04,0x0d,0xe6,0x0d,0xdc,0x10,
- 0x04,0x0d,0xdc,0x0d,0xe6,0x51,0x04,0x0d,0xe6,0x10,0x04,0x0d,0xe6,0x10,0xe6,0xe1,
- 0x3a,0x01,0xd0,0x77,0xcf,0x86,0xd5,0x20,0x94,0x1c,0x93,0x18,0xd2,0x0c,0x91,0x08,
- 0x10,0x04,0x0b,0x00,0x01,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x07,0x00,0x01,0x00,
- 0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x1b,0x53,0x04,0x01,0x00,0x92,0x13,0x91,0x0f,
- 0x10,0x04,0x01,0x00,0x01,0xff,0xe0,0xa4,0xa8,0xe0,0xa4,0xbc,0x00,0x01,0x00,0x01,
- 0x00,0xd3,0x26,0xd2,0x13,0x91,0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe0,0xa4,0xb0,
- 0xe0,0xa4,0xbc,0x00,0x01,0x00,0x91,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xa4,0xb3,0xe0,
- 0xa4,0xbc,0x00,0x01,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x0c,0x00,0x91,
- 0x08,0x10,0x04,0x01,0x07,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x8c,0xd4,0x18,0x53,
- 0x04,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x01,0x09,0x10,
- 0x04,0x0b,0x00,0x0c,0x00,0xd3,0x1c,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x01,
- 0xe6,0x10,0x04,0x01,0xdc,0x01,0xe6,0x91,0x08,0x10,0x04,0x01,0xe6,0x0b,0x00,0x0c,
- 0x00,0xd2,0x2c,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe0,0xa4,0x95,0xe0,0xa4,0xbc,0x00,
- 0x01,0xff,0xe0,0xa4,0x96,0xe0,0xa4,0xbc,0x00,0x10,0x0b,0x01,0xff,0xe0,0xa4,0x97,
- 0xe0,0xa4,0xbc,0x00,0x01,0xff,0xe0,0xa4,0x9c,0xe0,0xa4,0xbc,0x00,0xd1,0x16,0x10,
- 0x0b,0x01,0xff,0xe0,0xa4,0xa1,0xe0,0xa4,0xbc,0x00,0x01,0xff,0xe0,0xa4,0xa2,0xe0,
- 0xa4,0xbc,0x00,0x10,0x0b,0x01,0xff,0xe0,0xa4,0xab,0xe0,0xa4,0xbc,0x00,0x01,0xff,
- 0xe0,0xa4,0xaf,0xe0,0xa4,0xbc,0x00,0x54,0x04,0x01,0x00,0xd3,0x14,0x92,0x10,0xd1,
- 0x08,0x10,0x04,0x01,0x00,0x0a,0x00,0x10,0x04,0x0a,0x00,0x0c,0x00,0x0c,0x00,0xd2,
- 0x10,0xd1,0x08,0x10,0x04,0x10,0x00,0x0b,0x00,0x10,0x04,0x0b,0x00,0x09,0x00,0x91,
- 0x08,0x10,0x04,0x09,0x00,0x08,0x00,0x09,0x00,0xd0,0x86,0xcf,0x86,0xd5,0x44,0xd4,
- 0x2c,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x01,0x00,0x01,0x00,0x91,
- 0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,
- 0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x93,0x14,0x92,0x10,0xd1,
- 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,
- 0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,
- 0x00,0x01,0x00,0x01,0x00,0xd3,0x18,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,
- 0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0xd2,0x08,0x11,
- 0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x01,0x07,0x07,0x00,0x01,0x00,0xcf,
- 0x86,0xd5,0x7b,0xd4,0x42,0xd3,0x14,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,
- 0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd2,0x17,0xd1,0x08,0x10,0x04,0x01,
- 0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xe0,0xa7,0x87,0xe0,0xa6,0xbe,0x00,
- 0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xa7,0x87,0xe0,0xa7,0x97,0x00,0x01,0x09,0x10,
- 0x04,0x08,0x00,0x00,0x00,0xd3,0x10,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,
- 0x04,0x00,0x00,0x01,0x00,0x52,0x04,0x00,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe0,
- 0xa6,0xa1,0xe0,0xa6,0xbc,0x00,0x01,0xff,0xe0,0xa6,0xa2,0xe0,0xa6,0xbc,0x00,0x10,
- 0x04,0x00,0x00,0x01,0xff,0xe0,0xa6,0xaf,0xe0,0xa6,0xbc,0x00,0xd4,0x10,0x93,0x0c,
- 0x52,0x04,0x01,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x53,0x04,0x01,0x00,
- 0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x0b,0x00,0x51,0x04,0x13,0x00,
- 0x10,0x04,0x14,0xe6,0x00,0x00,0xe2,0x48,0x02,0xe1,0x4f,0x01,0xd0,0xa4,0xcf,0x86,
- 0xd5,0x4c,0xd4,0x34,0xd3,0x1c,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x07,0x00,
- 0x10,0x04,0x01,0x00,0x07,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,
- 0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x51,0x04,0x00,0x00,
- 0x10,0x04,0x00,0x00,0x01,0x00,0x93,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,
- 0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,
- 0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
- 0xd3,0x2e,0xd2,0x17,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x01,0x00,
- 0x01,0xff,0xe0,0xa8,0xb2,0xe0,0xa8,0xbc,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,
- 0x00,0x10,0x0b,0x01,0xff,0xe0,0xa8,0xb8,0xe0,0xa8,0xbc,0x00,0x00,0x00,0xd2,0x08,
- 0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x01,0x07,0x00,0x00,0x01,0x00,
- 0xcf,0x86,0xd5,0x80,0xd4,0x34,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,
- 0x01,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd2,0x10,
- 0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x91,0x08,
- 0x10,0x04,0x01,0x00,0x01,0x09,0x00,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,
- 0x00,0x00,0x0a,0x00,0x00,0x00,0x00,0x00,0xd2,0x25,0xd1,0x0f,0x10,0x04,0x00,0x00,
- 0x01,0xff,0xe0,0xa8,0x96,0xe0,0xa8,0xbc,0x00,0x10,0x0b,0x01,0xff,0xe0,0xa8,0x97,
- 0xe0,0xa8,0xbc,0x00,0x01,0xff,0xe0,0xa8,0x9c,0xe0,0xa8,0xbc,0x00,0xd1,0x08,0x10,
- 0x04,0x01,0x00,0x00,0x00,0x10,0x0b,0x01,0xff,0xe0,0xa8,0xab,0xe0,0xa8,0xbc,0x00,
- 0x00,0x00,0xd4,0x10,0x93,0x0c,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,
- 0x01,0x00,0x93,0x14,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x0a,0x00,
- 0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0xd0,0x82,0xcf,0x86,0xd5,0x40,0xd4,0x2c,
- 0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x91,0x08,
- 0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,
- 0x07,0x00,0x01,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,
- 0x01,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,
- 0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
- 0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x91,0x08,
- 0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,
- 0x91,0x08,0x10,0x04,0x01,0x07,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x3c,0xd4,0x28,
- 0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x00,0x00,0x01,0x00,
- 0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,
- 0x01,0x00,0x01,0x09,0x00,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x18,0x93,0x14,0xd2,0x0c,0x91,0x08,
- 0x10,0x04,0x01,0x00,0x07,0x00,0x07,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,
- 0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0d,0x00,0x07,0x00,0x00,0x00,0x00,0x00,
- 0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x11,0x00,0x13,0x00,0x13,0x00,0xe1,0x24,
- 0x01,0xd0,0x86,0xcf,0x86,0xd5,0x44,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,
- 0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,
- 0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,
- 0x00,0x01,0x00,0x93,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,
- 0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,
- 0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x18,0xd2,
- 0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,
- 0x00,0x07,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,
- 0x04,0x01,0x07,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x73,0xd4,0x45,0xd3,0x14,0x52,
- 0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x0a,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,
- 0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xad,0x87,0xe0,0xad,0x96,0x00,
- 0x00,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xe0,0xad,0x87,0xe0,0xac,0xbe,0x00,0x91,
- 0x0f,0x10,0x0b,0x01,0xff,0xe0,0xad,0x87,0xe0,0xad,0x97,0x00,0x01,0x09,0x00,0x00,
- 0xd3,0x0c,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x52,0x04,0x00,0x00,
- 0xd1,0x16,0x10,0x0b,0x01,0xff,0xe0,0xac,0xa1,0xe0,0xac,0xbc,0x00,0x01,0xff,0xe0,
- 0xac,0xa2,0xe0,0xac,0xbc,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd4,0x14,0x93,0x10,
- 0xd2,0x08,0x11,0x04,0x01,0x00,0x0a,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,
- 0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x07,0x00,0x0c,0x00,0x0c,0x00,
- 0x00,0x00,0xd0,0xb1,0xcf,0x86,0xd5,0x63,0xd4,0x28,0xd3,0x14,0xd2,0x08,0x11,0x04,
- 0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd2,0x0c,
- 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,
- 0xd3,0x1f,0xd2,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x91,0x0f,
- 0x10,0x0b,0x01,0xff,0xe0,0xae,0x92,0xe0,0xaf,0x97,0x00,0x01,0x00,0x00,0x00,0xd2,
- 0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x91,
- 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,0x51,
- 0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,
- 0x00,0x00,0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x11,
- 0x04,0x00,0x00,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,
- 0x04,0x08,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x00,
- 0x00,0x01,0x00,0xcf,0x86,0xd5,0x61,0xd4,0x45,0xd3,0x14,0xd2,0x0c,0x51,0x04,0x01,
- 0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0xd2,0x1e,0xd1,
- 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x0b,0x01,0xff,0xe0,0xaf,0x86,0xe0,0xae,
- 0xbe,0x00,0x01,0xff,0xe0,0xaf,0x87,0xe0,0xae,0xbe,0x00,0x91,0x0f,0x10,0x0b,0x01,
- 0xff,0xe0,0xaf,0x86,0xe0,0xaf,0x97,0x00,0x01,0x09,0x00,0x00,0x93,0x18,0xd2,0x0c,
- 0x91,0x08,0x10,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,
- 0x00,0x00,0x01,0x00,0x00,0x00,0xd4,0x14,0x93,0x10,0x52,0x04,0x00,0x00,0x51,0x04,
- 0x00,0x00,0x10,0x04,0x08,0x00,0x01,0x00,0x01,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,
- 0x01,0x00,0x10,0x04,0x01,0x00,0x07,0x00,0x07,0x00,0x92,0x0c,0x51,0x04,0x07,0x00,
- 0x10,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0xe3,0x1c,0x04,0xe2,0x1a,0x02,0xd1,0xf3,
- 0xd0,0x76,0xcf,0x86,0xd5,0x3c,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,
- 0x10,0x00,0x01,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x14,0x00,0x01,0x00,0x01,0x00,
- 0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x93,0x10,
- 0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
- 0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,
- 0x01,0x00,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x10,0x00,
- 0x01,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,
- 0x00,0x00,0x0a,0x00,0x01,0x00,0xcf,0x86,0xd5,0x53,0xd4,0x2f,0xd3,0x10,0x52,0x04,
- 0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0xd2,0x13,0x91,0x0f,
- 0x10,0x0b,0x01,0xff,0xe0,0xb1,0x86,0xe0,0xb1,0x96,0x00,0x00,0x00,0x01,0x00,0x91,
- 0x08,0x10,0x04,0x01,0x00,0x01,0x09,0x00,0x00,0xd3,0x14,0x52,0x04,0x00,0x00,0xd1,
- 0x08,0x10,0x04,0x00,0x00,0x01,0x54,0x10,0x04,0x01,0x5b,0x00,0x00,0x92,0x0c,0x51,
- 0x04,0x0a,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0xd4,0x14,0x93,0x10,0xd2,
- 0x08,0x11,0x04,0x01,0x00,0x0a,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x93,
- 0x10,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x15,0x00,0x0a,
- 0x00,0xd0,0x76,0xcf,0x86,0xd5,0x3c,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,
- 0x04,0x12,0x00,0x10,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x14,0x00,0x01,0x00,0x01,
- 0x00,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x93,
- 0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,
- 0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,
- 0x00,0x01,0x00,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x00,
- 0x00,0x01,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,
- 0x04,0x07,0x07,0x07,0x00,0x01,0x00,0xcf,0x86,0xd5,0x82,0xd4,0x5e,0xd3,0x2a,0xd2,
- 0x13,0x91,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xb2,0xbf,0xe0,0xb3,0x95,0x00,0x01,0x00,
- 0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x01,0x00,0x01,0xff,
- 0xe0,0xb3,0x86,0xe0,0xb3,0x95,0x00,0xd2,0x28,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe0,
- 0xb3,0x86,0xe0,0xb3,0x96,0x00,0x00,0x00,0x10,0x0b,0x01,0xff,0xe0,0xb3,0x86,0xe0,
- 0xb3,0x82,0x00,0x01,0xff,0xe0,0xb3,0x86,0xe0,0xb3,0x82,0xe0,0xb3,0x95,0x00,0x91,
- 0x08,0x10,0x04,0x01,0x00,0x01,0x09,0x00,0x00,0xd3,0x14,0x52,0x04,0x00,0x00,0xd1,
- 0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x52,0x04,0x00,
- 0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0xd4,0x14,0x93,0x10,0xd2,
- 0x08,0x11,0x04,0x01,0x00,0x09,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x93,
- 0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x09,0x00,0x10,0x04,0x09,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xe1,0x06,0x01,0xd0,0x6e,0xcf,0x86,0xd5,0x3c,0xd4,0x28,
- 0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x13,0x00,0x10,0x00,0x01,0x00,0x91,0x08,
- 0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,
- 0x01,0x00,0x00,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,
- 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,
- 0x91,0x08,0x10,0x04,0x01,0x00,0x0c,0x00,0x01,0x00,0x01,0x00,0x53,0x04,0x01,0x00,
- 0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x0c,0x00,0x13,0x09,0x91,0x08,0x10,0x04,
- 0x13,0x09,0x0a,0x00,0x01,0x00,0xcf,0x86,0xd5,0x65,0xd4,0x45,0xd3,0x10,0x52,0x04,
- 0x01,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x00,0x00,0x01,0x00,0xd2,0x1e,0xd1,0x08,
- 0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x0b,0x01,0xff,0xe0,0xb5,0x86,0xe0,0xb4,0xbe,
- 0x00,0x01,0xff,0xe0,0xb5,0x87,0xe0,0xb4,0xbe,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,
- 0xe0,0xb5,0x86,0xe0,0xb5,0x97,0x00,0x01,0x09,0x10,0x04,0x0c,0x00,0x12,0x00,0xd3,
- 0x10,0x52,0x04,0x00,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x01,0x00,0x52,
- 0x04,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x11,0x00,0xd4,0x14,0x93,
- 0x10,0xd2,0x08,0x11,0x04,0x01,0x00,0x0a,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,
- 0x00,0xd3,0x0c,0x52,0x04,0x0a,0x00,0x11,0x04,0x0a,0x00,0x12,0x00,0x92,0x0c,0x91,
- 0x08,0x10,0x04,0x12,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0xd0,0x5a,0xcf,0x86,0xd5,
- 0x34,0xd4,0x18,0x93,0x14,0xd2,0x08,0x11,0x04,0x00,0x00,0x04,0x00,0x91,0x08,0x10,
- 0x04,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,
- 0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x04,
- 0x00,0x04,0x00,0x54,0x04,0x04,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x04,0x00,0x10,
- 0x04,0x00,0x00,0x04,0x00,0x04,0x00,0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x00,
- 0x00,0x04,0x00,0x00,0x00,0xcf,0x86,0xd5,0x77,0xd4,0x28,0xd3,0x10,0x52,0x04,0x04,
- 0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0xd2,0x0c,0x51,0x04,0x00,
- 0x00,0x10,0x04,0x04,0x09,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x04,
- 0x00,0xd3,0x14,0x52,0x04,0x04,0x00,0xd1,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x10,
- 0x04,0x04,0x00,0x00,0x00,0xd2,0x13,0x51,0x04,0x04,0x00,0x10,0x0b,0x04,0xff,0xe0,
- 0xb7,0x99,0xe0,0xb7,0x8a,0x00,0x04,0x00,0xd1,0x19,0x10,0x0b,0x04,0xff,0xe0,0xb7,
- 0x99,0xe0,0xb7,0x8f,0x00,0x04,0xff,0xe0,0xb7,0x99,0xe0,0xb7,0x8f,0xe0,0xb7,0x8a,
- 0x00,0x10,0x0b,0x04,0xff,0xe0,0xb7,0x99,0xe0,0xb7,0x9f,0x00,0x04,0x00,0xd4,0x10,
- 0x93,0x0c,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x93,0x14,
- 0xd2,0x08,0x11,0x04,0x00,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0xe2,0x31,0x01,0xd1,0x58,0xd0,0x3a,0xcf,0x86,0xd5,0x18,0x94,
- 0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,
- 0x00,0x01,0x00,0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,
- 0x04,0x01,0x67,0x10,0x04,0x01,0x09,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,
- 0x00,0x01,0x00,0xcf,0x86,0x95,0x18,0xd4,0x0c,0x53,0x04,0x01,0x00,0x12,0x04,0x01,
- 0x6b,0x01,0x00,0x53,0x04,0x01,0x00,0x12,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0xd0,
- 0x9e,0xcf,0x86,0xd5,0x54,0xd4,0x3c,0xd3,0x20,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,
- 0x00,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,
- 0x00,0x10,0x04,0x15,0x00,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x15,
- 0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x15,0x00,0x01,0x00,0x15,
- 0x00,0xd3,0x08,0x12,0x04,0x15,0x00,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x15,
- 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x30,0xd3,0x1c,0xd2,0x0c,0x91,0x08,0x10,
- 0x04,0x15,0x00,0x01,0x00,0x01,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x10,
- 0x04,0x00,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x15,0x00,0x01,0x00,0x91,0x08,0x10,
- 0x04,0x15,0x00,0x01,0x00,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,
- 0x76,0x10,0x04,0x15,0x09,0x01,0x00,0x11,0x04,0x01,0x00,0x00,0x00,0xcf,0x86,0x95,
- 0x34,0xd4,0x20,0xd3,0x14,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,
- 0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x52,0x04,0x01,0x7a,0x11,0x04,0x01,0x00,0x00,
- 0x00,0x53,0x04,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x01,
- 0x00,0x0d,0x00,0x00,0x00,0xe1,0x2b,0x01,0xd0,0x3e,0xcf,0x86,0xd5,0x14,0x54,0x04,
- 0x02,0x00,0x53,0x04,0x02,0x00,0x92,0x08,0x11,0x04,0x02,0xdc,0x02,0x00,0x02,0x00,
- 0x54,0x04,0x02,0x00,0xd3,0x14,0x52,0x04,0x02,0x00,0xd1,0x08,0x10,0x04,0x02,0x00,
- 0x02,0xdc,0x10,0x04,0x02,0x00,0x02,0xdc,0x92,0x0c,0x91,0x08,0x10,0x04,0x02,0x00,
- 0x02,0xd8,0x02,0x00,0x02,0x00,0xcf,0x86,0xd5,0x73,0xd4,0x36,0xd3,0x17,0x92,0x13,
- 0x51,0x04,0x02,0x00,0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbd,0x82,0xe0,0xbe,0xb7,
- 0x00,0x02,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x02,0x00,0x02,0x00,0x91,
- 0x0f,0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbd,0x8c,0xe0,0xbe,0xb7,0x00,0x02,0x00,
- 0xd3,0x26,0xd2,0x13,0x51,0x04,0x02,0x00,0x10,0x0b,0x02,0xff,0xe0,0xbd,0x91,0xe0,
- 0xbe,0xb7,0x00,0x02,0x00,0x51,0x04,0x02,0x00,0x10,0x04,0x02,0x00,0x02,0xff,0xe0,
- 0xbd,0x96,0xe0,0xbe,0xb7,0x00,0x52,0x04,0x02,0x00,0x91,0x0f,0x10,0x0b,0x02,0xff,
- 0xe0,0xbd,0x9b,0xe0,0xbe,0xb7,0x00,0x02,0x00,0x02,0x00,0xd4,0x27,0x53,0x04,0x02,
- 0x00,0xd2,0x17,0xd1,0x0f,0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbd,0x80,0xe0,0xbe,
- 0xb5,0x00,0x10,0x04,0x04,0x00,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x00,0x00,
- 0x00,0x00,0xd3,0x35,0xd2,0x17,0xd1,0x08,0x10,0x04,0x00,0x00,0x02,0x81,0x10,0x04,
- 0x02,0x82,0x02,0xff,0xe0,0xbd,0xb1,0xe0,0xbd,0xb2,0x00,0xd1,0x0f,0x10,0x04,0x02,
- 0x84,0x02,0xff,0xe0,0xbd,0xb1,0xe0,0xbd,0xb4,0x00,0x10,0x0b,0x02,0xff,0xe0,0xbe,
- 0xb2,0xe0,0xbe,0x80,0x00,0x02,0x00,0xd2,0x13,0x91,0x0f,0x10,0x0b,0x02,0xff,0xe0,
- 0xbe,0xb3,0xe0,0xbe,0x80,0x00,0x02,0x00,0x02,0x82,0x11,0x04,0x02,0x82,0x02,0x00,
- 0xd0,0xd3,0xcf,0x86,0xd5,0x65,0xd4,0x27,0xd3,0x1f,0xd2,0x13,0x91,0x0f,0x10,0x04,
- 0x02,0x82,0x02,0xff,0xe0,0xbd,0xb1,0xe0,0xbe,0x80,0x00,0x02,0xe6,0x91,0x08,0x10,
- 0x04,0x02,0x09,0x02,0x00,0x02,0xe6,0x12,0x04,0x02,0x00,0x0c,0x00,0xd3,0x1f,0xd2,
- 0x13,0x51,0x04,0x02,0x00,0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbe,0x92,0xe0,0xbe,
- 0xb7,0x00,0x51,0x04,0x02,0x00,0x10,0x04,0x04,0x00,0x02,0x00,0xd2,0x0c,0x91,0x08,
- 0x10,0x04,0x00,0x00,0x02,0x00,0x02,0x00,0x91,0x0f,0x10,0x04,0x02,0x00,0x02,0xff,
- 0xe0,0xbe,0x9c,0xe0,0xbe,0xb7,0x00,0x02,0x00,0xd4,0x3d,0xd3,0x26,0xd2,0x13,0x51,
- 0x04,0x02,0x00,0x10,0x0b,0x02,0xff,0xe0,0xbe,0xa1,0xe0,0xbe,0xb7,0x00,0x02,0x00,
- 0x51,0x04,0x02,0x00,0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbe,0xa6,0xe0,0xbe,0xb7,
- 0x00,0x52,0x04,0x02,0x00,0x91,0x0f,0x10,0x0b,0x02,0xff,0xe0,0xbe,0xab,0xe0,0xbe,
- 0xb7,0x00,0x02,0x00,0x04,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,
- 0x02,0x00,0x02,0x00,0x02,0x00,0xd2,0x13,0x91,0x0f,0x10,0x04,0x04,0x00,0x02,0xff,
- 0xe0,0xbe,0x90,0xe0,0xbe,0xb5,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,
- 0x00,0x04,0x00,0xcf,0x86,0x95,0x4c,0xd4,0x24,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,
- 0x04,0x04,0x00,0x10,0x04,0x04,0xdc,0x04,0x00,0x52,0x04,0x04,0x00,0xd1,0x08,0x10,
- 0x04,0x04,0x00,0x00,0x00,0x10,0x04,0x0a,0x00,0x04,0x00,0xd3,0x14,0xd2,0x08,0x11,
- 0x04,0x08,0x00,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x0b,0x00,0x92,
- 0x10,0xd1,0x08,0x10,0x04,0x0b,0x00,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0xcf,0x86,0xe5,0xcc,0x04,0xe4,0x63,0x03,0xe3,0x65,0x01,0xe2,0x04,
- 0x01,0xd1,0x7f,0xd0,0x65,0xcf,0x86,0x55,0x04,0x04,0x00,0xd4,0x33,0xd3,0x1f,0xd2,
- 0x0c,0x51,0x04,0x04,0x00,0x10,0x04,0x0a,0x00,0x04,0x00,0x51,0x04,0x04,0x00,0x10,
- 0x0b,0x04,0xff,0xe1,0x80,0xa5,0xe1,0x80,0xae,0x00,0x04,0x00,0x92,0x10,0xd1,0x08,
- 0x10,0x04,0x0a,0x00,0x04,0x00,0x10,0x04,0x04,0x00,0x0a,0x00,0x04,0x00,0xd3,0x18,
- 0xd2,0x0c,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x0a,0x00,0x51,0x04,0x0a,0x00,
- 0x10,0x04,0x04,0x00,0x04,0x07,0x92,0x10,0xd1,0x08,0x10,0x04,0x04,0x00,0x04,0x09,
- 0x10,0x04,0x0a,0x09,0x0a,0x00,0x0a,0x00,0xcf,0x86,0x95,0x14,0x54,0x04,0x04,0x00,
- 0x53,0x04,0x04,0x00,0x92,0x08,0x11,0x04,0x04,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,
- 0xd0,0x2e,0xcf,0x86,0x95,0x28,0xd4,0x14,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,
- 0x91,0x08,0x10,0x04,0x0a,0x00,0x0a,0xdc,0x0a,0x00,0x53,0x04,0x0a,0x00,0xd2,0x08,
- 0x11,0x04,0x0a,0x00,0x0b,0x00,0x11,0x04,0x0b,0x00,0x0a,0x00,0x01,0x00,0xcf,0x86,
- 0xd5,0x24,0x94,0x20,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,
- 0x00,0x00,0x0d,0x00,0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0d,0x00,
- 0x00,0x00,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,
- 0x01,0x00,0x10,0x04,0x01,0x00,0x06,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x06,0x00,
- 0x08,0x00,0x10,0x04,0x08,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x0d,0x00,
- 0x0d,0x00,0xd1,0x28,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0x95,0x1c,0x54,0x04,
- 0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x0b,0x00,0x51,0x04,
- 0x0b,0x00,0x10,0x04,0x0b,0x00,0x01,0x00,0x01,0x00,0xd0,0x1e,0xcf,0x86,0x55,0x04,
- 0x01,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,
- 0x0b,0x00,0x0b,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,
- 0x01,0x00,0x53,0x04,0x01,0x00,0x92,0x08,0x11,0x04,0x01,0x00,0x0b,0x00,0x0b,0x00,
- 0xe2,0x21,0x01,0xd1,0x6c,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x93,0x10,0x52,
- 0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x04,0x00,0x04,
- 0x00,0x04,0x00,0xcf,0x86,0x95,0x48,0xd4,0x24,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,
- 0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,
- 0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0xd3,0x10,0x52,0x04,0x04,
- 0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0xd2,0x0c,0x91,0x08,0x10,
- 0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0xd0,
- 0x62,0xcf,0x86,0xd5,0x28,0x94,0x24,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,
- 0x00,0x10,0x04,0x04,0x00,0x08,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x00,
- 0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0xd4,0x14,0x53,0x04,0x04,
- 0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0xd3,
- 0x14,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,
- 0x00,0x00,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,
- 0x00,0xcf,0x86,0xd5,0x38,0xd4,0x24,0xd3,0x14,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,
- 0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x52,0x04,0x04,0x00,0x51,
- 0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x93,0x10,0x52,0x04,0x04,0x00,0x51,
- 0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x94,0x14,0x53,0x04,0x04,
- 0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x04,
- 0x00,0xd1,0x9c,0xd0,0x3e,0xcf,0x86,0x95,0x38,0xd4,0x14,0x53,0x04,0x04,0x00,0x52,
- 0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0xd3,0x14,0xd2,
- 0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,
- 0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x04,
- 0x00,0xcf,0x86,0xd5,0x34,0xd4,0x14,0x93,0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,
- 0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x04,0x00,0x53,0x04,0x04,0x00,0xd2,0x0c,0x51,
- 0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x0c,
- 0xe6,0x10,0x04,0x0c,0xe6,0x08,0xe6,0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,
- 0x04,0x08,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x53,0x04,0x04,0x00,0x52,
- 0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0xd0,0x1a,0xcf,
- 0x86,0x95,0x14,0x54,0x04,0x08,0x00,0x53,0x04,0x08,0x00,0x92,0x08,0x11,0x04,0x08,
- 0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,
- 0x00,0xd3,0x10,0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x11,0x00,0x00,
- 0x00,0x52,0x04,0x11,0x00,0x11,0x04,0x11,0x00,0x00,0x00,0xd3,0x30,0xd2,0x2a,0xd1,
- 0x24,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,
- 0x04,0x0b,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xcf,
- 0x06,0x04,0x00,0xcf,0x06,0x04,0x00,0xcf,0x06,0x04,0x00,0xd2,0x6c,0xd1,0x24,0xd0,
- 0x06,0xcf,0x06,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00,0x93,
- 0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x0b,0x00,0x0b,
- 0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00,0x52,
- 0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xcf,
- 0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,
- 0x04,0x04,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x80,0xd0,0x46,0xcf,0x86,0xd5,0x28,0xd4,
- 0x14,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x91,0x08,0x10,0x04,0x06,0x00,0x00,
- 0x00,0x06,0x00,0x93,0x10,0x52,0x04,0x06,0x00,0x91,0x08,0x10,0x04,0x06,0x09,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x54,0x04,0x06,0x00,0x93,0x14,0x52,0x04,0x06,0x00,0xd1,
- 0x08,0x10,0x04,0x06,0x09,0x06,0x00,0x10,0x04,0x06,0x00,0x00,0x00,0x00,0x00,0xcf,
- 0x86,0xd5,0x10,0x54,0x04,0x06,0x00,0x93,0x08,0x12,0x04,0x06,0x00,0x00,0x00,0x00,
- 0x00,0xd4,0x14,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x91,0x08,0x10,0x04,0x06,
- 0x00,0x00,0x00,0x06,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x06,0x00,0x00,
- 0x00,0x06,0x00,0x00,0x00,0x00,0x00,0xd0,0x06,0xcf,0x06,0x04,0x00,0xcf,0x86,0xd5,
- 0x24,0x54,0x04,0x04,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x04,0x00,0x10,0x04,0x04,
- 0x09,0x04,0x00,0x04,0x00,0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x07,
- 0xe6,0x00,0x00,0xd4,0x10,0x53,0x04,0x04,0x00,0x92,0x08,0x11,0x04,0x04,0x00,0x00,
- 0x00,0x00,0x00,0x53,0x04,0x07,0x00,0x92,0x08,0x11,0x04,0x07,0x00,0x00,0x00,0x00,
- 0x00,0xe4,0xac,0x03,0xe3,0x4d,0x01,0xd2,0x84,0xd1,0x48,0xd0,0x2a,0xcf,0x86,0x95,
- 0x24,0xd4,0x14,0x53,0x04,0x04,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,
- 0x04,0x04,0x00,0x00,0x00,0x53,0x04,0x04,0x00,0x92,0x08,0x11,0x04,0x04,0x00,0x00,
- 0x00,0x00,0x00,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00,0x53,
- 0x04,0x04,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0xd0,0x22,0xcf,0x86,0x55,0x04,0x04,0x00,0x94,0x18,0x53,0x04,0x04,0x00,0x92,
- 0x10,0xd1,0x08,0x10,0x04,0x04,0x00,0x04,0xe4,0x10,0x04,0x0a,0x00,0x00,0x00,0x00,
- 0x00,0x0b,0x00,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,0x00,0x93,0x0c,0x52,
- 0x04,0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xd1,0x80,0xd0,0x42,0xcf,
- 0x86,0xd5,0x1c,0x54,0x04,0x07,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,0xd1,
- 0x08,0x10,0x04,0x07,0x00,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0xd4,0x0c,0x53,
- 0x04,0x07,0x00,0x12,0x04,0x07,0x00,0x00,0x00,0x53,0x04,0x07,0x00,0x92,0x10,0xd1,
- 0x08,0x10,0x04,0x07,0x00,0x07,0xde,0x10,0x04,0x07,0xe6,0x07,0xdc,0x00,0x00,0xcf,
- 0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x07,0x00,0x00,
- 0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0xd4,0x10,0x53,0x04,0x07,0x00,0x52,
- 0x04,0x07,0x00,0x11,0x04,0x07,0x00,0x00,0x00,0x93,0x10,0x52,0x04,0x07,0x00,0x91,
- 0x08,0x10,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x1a,0xcf,0x86,0x55,
- 0x04,0x08,0x00,0x94,0x10,0x53,0x04,0x08,0x00,0x92,0x08,0x11,0x04,0x08,0x00,0x0b,
- 0x00,0x00,0x00,0x08,0x00,0xcf,0x86,0x95,0x28,0xd4,0x10,0x53,0x04,0x08,0x00,0x92,
- 0x08,0x11,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x08,0x00,0xd2,0x0c,0x51,
- 0x04,0x08,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x08,0x00,0x07,
- 0x00,0xd2,0xe4,0xd1,0x80,0xd0,0x2e,0xcf,0x86,0x95,0x28,0x54,0x04,0x08,0x00,0xd3,
- 0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x08,0xe6,0xd2,
- 0x0c,0x91,0x08,0x10,0x04,0x08,0xdc,0x08,0x00,0x08,0x00,0x11,0x04,0x00,0x00,0x08,
- 0x00,0x0b,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,0x52,
- 0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0xd4,0x14,0x93,
- 0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x09,0x0b,0x00,0x0b,0x00,0x0b,0x00,0x0b,
- 0x00,0xd3,0x10,0x52,0x04,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0xe6,0x0b,
- 0xe6,0x52,0x04,0x0b,0xe6,0xd1,0x08,0x10,0x04,0x0b,0xe6,0x00,0x00,0x10,0x04,0x00,
- 0x00,0x0b,0xdc,0xd0,0x5e,0xcf,0x86,0xd5,0x20,0xd4,0x10,0x53,0x04,0x0b,0x00,0x92,
- 0x08,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x0b,0x00,0x92,0x08,0x11,
- 0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xd4,0x10,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,
- 0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0xd3,0x10,0x52,0x04,0x10,0xe6,0x91,0x08,0x10,
- 0x04,0x10,0xe6,0x10,0xdc,0x10,0xdc,0xd2,0x0c,0x51,0x04,0x10,0xdc,0x10,0x04,0x10,
- 0xdc,0x10,0xe6,0xd1,0x08,0x10,0x04,0x10,0xe6,0x10,0xdc,0x10,0x04,0x10,0x00,0x00,
- 0x00,0xcf,0x06,0x00,0x00,0xe1,0x1e,0x01,0xd0,0xaa,0xcf,0x86,0xd5,0x6e,0xd4,0x53,
- 0xd3,0x17,0x52,0x04,0x09,0x00,0x51,0x04,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,0xac,
- 0x85,0xe1,0xac,0xb5,0x00,0x09,0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x09,0xff,0xe1,
- 0xac,0x87,0xe1,0xac,0xb5,0x00,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,0xac,0x89,0xe1,
- 0xac,0xb5,0x00,0x09,0x00,0xd1,0x0f,0x10,0x0b,0x09,0xff,0xe1,0xac,0x8b,0xe1,0xac,
- 0xb5,0x00,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,0xac,0x8d,0xe1,0xac,0xb5,0x00,0x09,
- 0x00,0x93,0x17,0x92,0x13,0x51,0x04,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,0xac,0x91,
- 0xe1,0xac,0xb5,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x54,0x04,0x09,0x00,0xd3,0x10,
- 0x52,0x04,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x07,0x09,0x00,0x09,0x00,0xd2,0x13,
- 0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xe1,0xac,0xba,0xe1,0xac,0xb5,
- 0x00,0x91,0x0f,0x10,0x04,0x09,0x00,0x09,0xff,0xe1,0xac,0xbc,0xe1,0xac,0xb5,0x00,
- 0x09,0x00,0xcf,0x86,0xd5,0x3d,0x94,0x39,0xd3,0x31,0xd2,0x25,0xd1,0x16,0x10,0x0b,
- 0x09,0xff,0xe1,0xac,0xbe,0xe1,0xac,0xb5,0x00,0x09,0xff,0xe1,0xac,0xbf,0xe1,0xac,
- 0xb5,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xe1,0xad,0x82,0xe1,0xac,0xb5,0x00,0x91,
- 0x08,0x10,0x04,0x09,0x09,0x09,0x00,0x09,0x00,0x12,0x04,0x09,0x00,0x00,0x00,0x09,
- 0x00,0xd4,0x1c,0x53,0x04,0x09,0x00,0xd2,0x0c,0x51,0x04,0x09,0x00,0x10,0x04,0x09,
- 0x00,0x09,0xe6,0x91,0x08,0x10,0x04,0x09,0xdc,0x09,0xe6,0x09,0xe6,0xd3,0x08,0x12,
- 0x04,0x09,0xe6,0x09,0x00,0x52,0x04,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x00,0x00,
- 0x00,0x00,0x00,0xd0,0x2e,0xcf,0x86,0x55,0x04,0x0a,0x00,0xd4,0x18,0x53,0x04,0x0a,
- 0x00,0xd2,0x0c,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x09,0x0d,0x09,0x11,0x04,0x0d,
- 0x00,0x0a,0x00,0x53,0x04,0x0a,0x00,0x92,0x08,0x11,0x04,0x0a,0x00,0x0d,0x00,0x0d,
- 0x00,0xcf,0x86,0x55,0x04,0x0c,0x00,0xd4,0x14,0x93,0x10,0x52,0x04,0x0c,0x00,0x51,
- 0x04,0x0c,0x00,0x10,0x04,0x0c,0x07,0x0c,0x00,0x0c,0x00,0xd3,0x0c,0x92,0x08,0x11,
- 0x04,0x0c,0x00,0x0c,0x09,0x00,0x00,0x12,0x04,0x00,0x00,0x0c,0x00,0xe3,0xb2,0x01,
- 0xe2,0x09,0x01,0xd1,0x4c,0xd0,0x2a,0xcf,0x86,0x55,0x04,0x0a,0x00,0x54,0x04,0x0a,
- 0x00,0xd3,0x10,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x00,0x0a,
- 0x07,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0a,0x00,0x0a,0x00,0xcf,
- 0x86,0x95,0x1c,0x94,0x18,0x53,0x04,0x0a,0x00,0xd2,0x08,0x11,0x04,0x0a,0x00,0x00,
- 0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0xd0,
- 0x3a,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x12,0x00,0x92,0x0c,0x91,0x08,0x10,
- 0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x54,0x04,0x14,0x00,0x53,
- 0x04,0x14,0x00,0xd2,0x0c,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0x91,
- 0x08,0x10,0x04,0x00,0x00,0x14,0x00,0x14,0x00,0xcf,0x86,0xd5,0x2c,0xd4,0x08,0x13,
- 0x04,0x0d,0x00,0x00,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x0b,0xe6,0x10,0x04,0x0b,
- 0xe6,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x01,0x0b,0xdc,0x0b,0xdc,0x92,0x08,0x11,
- 0x04,0x0b,0xdc,0x0b,0xe6,0x0b,0xdc,0xd4,0x28,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,
- 0x04,0x0b,0xe6,0x0b,0x00,0x0b,0x01,0x0b,0x01,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0b,
- 0x01,0x0b,0x00,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0xdc,0x0b,0x00,0xd3,
- 0x1c,0xd2,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x0d,0x00,0xd1,0x08,0x10,
- 0x04,0x0d,0xe6,0x0d,0x00,0x10,0x04,0x0d,0x00,0x13,0x00,0x92,0x0c,0x51,0x04,0x10,
- 0xe6,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0xd1,0x1c,0xd0,0x06,0xcf,0x06,0x07,
- 0x00,0xcf,0x86,0x55,0x04,0x07,0x00,0x94,0x0c,0x53,0x04,0x07,0x00,0x12,0x04,0x07,
- 0x00,0x08,0x00,0x08,0x00,0xd0,0x06,0xcf,0x06,0x08,0x00,0xcf,0x86,0xd5,0x40,0xd4,
- 0x2c,0xd3,0x10,0x92,0x0c,0x51,0x04,0x08,0xe6,0x10,0x04,0x08,0xdc,0x08,0xe6,0x09,
- 0xe6,0xd2,0x0c,0x51,0x04,0x09,0xe6,0x10,0x04,0x09,0xdc,0x0a,0xe6,0xd1,0x08,0x10,
- 0x04,0x0a,0xe6,0x0a,0xea,0x10,0x04,0x0a,0xd6,0x0a,0xdc,0x93,0x10,0x92,0x0c,0x91,
- 0x08,0x10,0x04,0x0a,0xca,0x0a,0xe6,0x0a,0xe6,0x0a,0xe6,0x0a,0xe6,0xd4,0x14,0x93,
- 0x10,0x52,0x04,0x0a,0xe6,0x51,0x04,0x0a,0xe6,0x10,0x04,0x0a,0xe6,0x10,0xe6,0x10,
- 0xe6,0xd3,0x10,0x52,0x04,0x10,0xe6,0x51,0x04,0x10,0xe6,0x10,0x04,0x13,0xe8,0x13,
- 0xe4,0xd2,0x10,0xd1,0x08,0x10,0x04,0x13,0xe4,0x13,0xdc,0x10,0x04,0x00,0x00,0x12,
- 0xe6,0xd1,0x08,0x10,0x04,0x0c,0xe9,0x0b,0xdc,0x10,0x04,0x09,0xe6,0x09,0xdc,0xe2,
- 0x80,0x08,0xe1,0x48,0x04,0xe0,0x1c,0x02,0xcf,0x86,0xe5,0x11,0x01,0xd4,0x84,0xd3,
- 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0xa5,0x00,0x01,0xff,0x61,
- 0xcc,0xa5,0x00,0x10,0x08,0x01,0xff,0x42,0xcc,0x87,0x00,0x01,0xff,0x62,0xcc,0x87,
- 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x42,0xcc,0xa3,0x00,0x01,0xff,0x62,0xcc,0xa3,
- 0x00,0x10,0x08,0x01,0xff,0x42,0xcc,0xb1,0x00,0x01,0xff,0x62,0xcc,0xb1,0x00,0xd2,
- 0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x43,0xcc,0xa7,0xcc,0x81,0x00,0x01,0xff,0x63,
- 0xcc,0xa7,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x44,0xcc,0x87,0x00,0x01,0xff,0x64,
- 0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x44,0xcc,0xa3,0x00,0x01,0xff,0x64,
- 0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x44,0xcc,0xb1,0x00,0x01,0xff,0x64,0xcc,0xb1,
- 0x00,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x44,0xcc,0xa7,0x00,0x01,
- 0xff,0x64,0xcc,0xa7,0x00,0x10,0x08,0x01,0xff,0x44,0xcc,0xad,0x00,0x01,0xff,0x64,
- 0xcc,0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x45,0xcc,0x84,0xcc,0x80,0x00,0x01,
- 0xff,0x65,0xcc,0x84,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x45,0xcc,0x84,0xcc,0x81,
- 0x00,0x01,0xff,0x65,0xcc,0x84,0xcc,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0x45,0xcc,0xad,0x00,0x01,0xff,0x65,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x45,
- 0xcc,0xb0,0x00,0x01,0xff,0x65,0xcc,0xb0,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x45,
- 0xcc,0xa7,0xcc,0x86,0x00,0x01,0xff,0x65,0xcc,0xa7,0xcc,0x86,0x00,0x10,0x08,0x01,
- 0xff,0x46,0xcc,0x87,0x00,0x01,0xff,0x66,0xcc,0x87,0x00,0xd4,0x84,0xd3,0x40,0xd2,
- 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x47,0xcc,0x84,0x00,0x01,0xff,0x67,0xcc,0x84,
- 0x00,0x10,0x08,0x01,0xff,0x48,0xcc,0x87,0x00,0x01,0xff,0x68,0xcc,0x87,0x00,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0x48,0xcc,0xa3,0x00,0x01,0xff,0x68,0xcc,0xa3,0x00,0x10,
- 0x08,0x01,0xff,0x48,0xcc,0x88,0x00,0x01,0xff,0x68,0xcc,0x88,0x00,0xd2,0x20,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0x48,0xcc,0xa7,0x00,0x01,0xff,0x68,0xcc,0xa7,0x00,0x10,
- 0x08,0x01,0xff,0x48,0xcc,0xae,0x00,0x01,0xff,0x68,0xcc,0xae,0x00,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0x49,0xcc,0xb0,0x00,0x01,0xff,0x69,0xcc,0xb0,0x00,0x10,0x0a,0x01,
- 0xff,0x49,0xcc,0x88,0xcc,0x81,0x00,0x01,0xff,0x69,0xcc,0x88,0xcc,0x81,0x00,0xd3,
- 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x4b,0xcc,0x81,0x00,0x01,0xff,0x6b,
- 0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x4b,0xcc,0xa3,0x00,0x01,0xff,0x6b,0xcc,0xa3,
- 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4b,0xcc,0xb1,0x00,0x01,0xff,0x6b,0xcc,0xb1,
- 0x00,0x10,0x08,0x01,0xff,0x4c,0xcc,0xa3,0x00,0x01,0xff,0x6c,0xcc,0xa3,0x00,0xd2,
- 0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4c,0xcc,0xa3,0xcc,0x84,0x00,0x01,0xff,0x6c,
- 0xcc,0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x4c,0xcc,0xb1,0x00,0x01,0xff,0x6c,
- 0xcc,0xb1,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4c,0xcc,0xad,0x00,0x01,0xff,0x6c,
- 0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x4d,0xcc,0x81,0x00,0x01,0xff,0x6d,0xcc,0x81,
- 0x00,0xcf,0x86,0xe5,0x15,0x01,0xd4,0x88,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x4d,0xcc,0x87,0x00,0x01,0xff,0x6d,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,
- 0x4d,0xcc,0xa3,0x00,0x01,0xff,0x6d,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x4e,0xcc,0x87,0x00,0x01,0xff,0x6e,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x4e,0xcc,
- 0xa3,0x00,0x01,0xff,0x6e,0xcc,0xa3,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x4e,0xcc,0xb1,0x00,0x01,0xff,0x6e,0xcc,0xb1,0x00,0x10,0x08,0x01,0xff,0x4e,0xcc,
- 0xad,0x00,0x01,0xff,0x6e,0xcc,0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,
- 0x83,0xcc,0x81,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,
- 0x4f,0xcc,0x83,0xcc,0x88,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x88,0x00,0xd3,0x48,
- 0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x84,0xcc,0x80,0x00,0x01,0xff,
- 0x6f,0xcc,0x84,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x84,0xcc,0x81,0x00,
- 0x01,0xff,0x6f,0xcc,0x84,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x50,0xcc,
- 0x81,0x00,0x01,0xff,0x70,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x50,0xcc,0x87,0x00,
- 0x01,0xff,0x70,0xcc,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x52,0xcc,
- 0x87,0x00,0x01,0xff,0x72,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x52,0xcc,0xa3,0x00,
- 0x01,0xff,0x72,0xcc,0xa3,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x52,0xcc,0xa3,0xcc,
- 0x84,0x00,0x01,0xff,0x72,0xcc,0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x52,0xcc,
- 0xb1,0x00,0x01,0xff,0x72,0xcc,0xb1,0x00,0xd4,0x8c,0xd3,0x48,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x01,0xff,0x53,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x87,0x00,0x10,0x08,
- 0x01,0xff,0x53,0xcc,0xa3,0x00,0x01,0xff,0x73,0xcc,0xa3,0x00,0xd1,0x14,0x10,0x0a,
- 0x01,0xff,0x53,0xcc,0x81,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x81,0xcc,0x87,0x00,
- 0x10,0x0a,0x01,0xff,0x53,0xcc,0x8c,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x8c,0xcc,
- 0x87,0x00,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x53,0xcc,0xa3,0xcc,0x87,0x00,
- 0x01,0xff,0x73,0xcc,0xa3,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x54,0xcc,0x87,0x00,
- 0x01,0xff,0x74,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x54,0xcc,0xa3,0x00,
- 0x01,0xff,0x74,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x54,0xcc,0xb1,0x00,0x01,0xff,
- 0x74,0xcc,0xb1,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x54,0xcc,
- 0xad,0x00,0x01,0xff,0x74,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0xa4,0x00,
- 0x01,0xff,0x75,0xcc,0xa4,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0xb0,0x00,
- 0x01,0xff,0x75,0xcc,0xb0,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0xad,0x00,0x01,0xff,
- 0x75,0xcc,0xad,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x55,0xcc,0x83,0xcc,
- 0x81,0x00,0x01,0xff,0x75,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x55,0xcc,
- 0x84,0xcc,0x88,0x00,0x01,0xff,0x75,0xcc,0x84,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0x56,0xcc,0x83,0x00,0x01,0xff,0x76,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,
- 0x56,0xcc,0xa3,0x00,0x01,0xff,0x76,0xcc,0xa3,0x00,0xe0,0x10,0x02,0xcf,0x86,0xd5,
- 0xe1,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc,0x80,
- 0x00,0x01,0xff,0x77,0xcc,0x80,0x00,0x10,0x08,0x01,0xff,0x57,0xcc,0x81,0x00,0x01,
- 0xff,0x77,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc,0x88,0x00,0x01,
- 0xff,0x77,0xcc,0x88,0x00,0x10,0x08,0x01,0xff,0x57,0xcc,0x87,0x00,0x01,0xff,0x77,
- 0xcc,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc,0xa3,0x00,0x01,
- 0xff,0x77,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x58,0xcc,0x87,0x00,0x01,0xff,0x78,
- 0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x58,0xcc,0x88,0x00,0x01,0xff,0x78,
- 0xcc,0x88,0x00,0x10,0x08,0x01,0xff,0x59,0xcc,0x87,0x00,0x01,0xff,0x79,0xcc,0x87,
- 0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x5a,0xcc,0x82,0x00,0x01,
- 0xff,0x7a,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x5a,0xcc,0xa3,0x00,0x01,0xff,0x7a,
- 0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x5a,0xcc,0xb1,0x00,0x01,0xff,0x7a,
- 0xcc,0xb1,0x00,0x10,0x08,0x01,0xff,0x68,0xcc,0xb1,0x00,0x01,0xff,0x74,0xcc,0x88,
- 0x00,0x92,0x1d,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x8a,0x00,0x01,0xff,0x79,
- 0xcc,0x8a,0x00,0x10,0x04,0x01,0x00,0x02,0xff,0xc5,0xbf,0xcc,0x87,0x00,0x0a,0x00,
- 0xd4,0x98,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0xa3,0x00,
- 0x01,0xff,0x61,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x41,0xcc,0x89,0x00,0x01,0xff,
- 0x61,0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0x82,0xcc,0x81,0x00,
- 0x01,0xff,0x61,0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x82,0xcc,
+ 0xc6,0xe5,0xf9,0x14,0xe4,0x6f,0x0d,0xe3,0x39,0x08,0xe2,0x22,0x01,0xc1,0xd0,0x24,
+ 0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x07,0x63,0xd8,0x43,0x01,0x00,0x93,0x13,0x52,
+ 0x04,0x01,0x00,0x91,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xce,0xbc,0x00,0x01,0x00,
+ 0x01,0x00,0xcf,0x86,0xe5,0xb3,0x44,0xd4,0x7f,0xd3,0x3f,0xd2,0x20,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x61,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x81,0x00,0x10,0x08,0x01,
+ 0xff,0x61,0xcc,0x82,0x00,0x01,0xff,0x61,0xcc,0x83,0x00,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x61,0xcc,0x88,0x00,0x01,0xff,0x61,0xcc,0x8a,0x00,0x10,0x07,0x01,0xff,0xc3,
+ 0xa6,0x00,0x01,0xff,0x63,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0x65,0xcc,0x80,0x00,0x01,0xff,0x65,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,
+ 0x82,0x00,0x01,0xff,0x65,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,
+ 0x80,0x00,0x01,0xff,0x69,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x69,0xcc,0x82,0x00,
+ 0x01,0xff,0x69,0xcc,0x88,0x00,0xd3,0x3b,0xd2,0x1f,0xd1,0x0f,0x10,0x07,0x01,0xff,
+ 0xc3,0xb0,0x00,0x01,0xff,0x6e,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x80,
+ 0x00,0x01,0xff,0x6f,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x82,
+ 0x00,0x01,0xff,0x6f,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x88,0x00,0x01,
+ 0x00,0xd2,0x1f,0xd1,0x0f,0x10,0x07,0x01,0xff,0xc3,0xb8,0x00,0x01,0xff,0x75,0xcc,
+ 0x80,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x81,0x00,0x01,0xff,0x75,0xcc,0x82,0x00,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x88,0x00,0x01,0xff,0x79,0xcc,0x81,0x00,
+ 0x10,0x07,0x01,0xff,0xc3,0xbe,0x00,0x01,0xff,0x73,0x73,0x00,0xe1,0xd4,0x03,0xe0,
+ 0xeb,0x01,0xcf,0x86,0xd5,0xfb,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0x61,0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,
+ 0x61,0xcc,0x86,0x00,0x01,0xff,0x61,0xcc,0x86,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0x61,0xcc,0xa8,0x00,0x01,0xff,0x61,0xcc,0xa8,0x00,0x10,0x08,0x01,0xff,0x63,0xcc,
+ 0x81,0x00,0x01,0xff,0x63,0xcc,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0x63,0xcc,0x82,0x00,0x01,0xff,0x63,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x63,0xcc,
+ 0x87,0x00,0x01,0xff,0x63,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x63,0xcc,
+ 0x8c,0x00,0x01,0xff,0x63,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0x8c,0x00,
+ 0x01,0xff,0x64,0xcc,0x8c,0x00,0xd3,0x3b,0xd2,0x1b,0xd1,0x0b,0x10,0x07,0x01,0xff,
+ 0xc4,0x91,0x00,0x01,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x84,0x00,0x01,0xff,0x65,
+ 0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0x86,0x00,0x01,0xff,0x65,
+ 0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x87,0x00,0x01,0xff,0x65,0xcc,0x87,
+ 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0xa8,0x00,0x01,0xff,0x65,
+ 0xcc,0xa8,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x8c,0x00,0x01,0xff,0x65,0xcc,0x8c,
+ 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x67,0xcc,0x82,0x00,0x01,0xff,0x67,0xcc,0x82,
+ 0x00,0x10,0x08,0x01,0xff,0x67,0xcc,0x86,0x00,0x01,0xff,0x67,0xcc,0x86,0x00,0xd4,
+ 0x7b,0xd3,0x3b,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x67,0xcc,0x87,0x00,0x01,
+ 0xff,0x67,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x67,0xcc,0xa7,0x00,0x01,0xff,0x67,
+ 0xcc,0xa7,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x68,0xcc,0x82,0x00,0x01,0xff,0x68,
+ 0xcc,0x82,0x00,0x10,0x07,0x01,0xff,0xc4,0xa7,0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0x69,0xcc,0x83,0x00,0x01,0xff,0x69,0xcc,0x83,0x00,0x10,0x08,
+ 0x01,0xff,0x69,0xcc,0x84,0x00,0x01,0xff,0x69,0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0x69,0xcc,0x86,0x00,0x01,0xff,0x69,0xcc,0x86,0x00,0x10,0x08,0x01,0xff,
+ 0x69,0xcc,0xa8,0x00,0x01,0xff,0x69,0xcc,0xa8,0x00,0xd3,0x37,0xd2,0x17,0xd1,0x0c,
+ 0x10,0x08,0x01,0xff,0x69,0xcc,0x87,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xc4,0xb3,
+ 0x00,0x01,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6a,0xcc,0x82,0x00,0x01,0xff,0x6a,
+ 0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x6b,0xcc,0xa7,0x00,0x01,0xff,0x6b,0xcc,0xa7,
+ 0x00,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x6c,0xcc,0x81,0x00,0x10,
+ 0x08,0x01,0xff,0x6c,0xcc,0x81,0x00,0x01,0xff,0x6c,0xcc,0xa7,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x6c,0xcc,0xa7,0x00,0x01,0xff,0x6c,0xcc,0x8c,0x00,0x10,0x08,0x01,
+ 0xff,0x6c,0xcc,0x8c,0x00,0x01,0xff,0xc5,0x80,0x00,0xcf,0x86,0xd5,0xed,0xd4,0x72,
+ 0xd3,0x37,0xd2,0x17,0xd1,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xc5,0x82,0x00,0x10,
+ 0x04,0x01,0x00,0x01,0xff,0x6e,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e,
+ 0xcc,0x81,0x00,0x01,0xff,0x6e,0xcc,0xa7,0x00,0x10,0x08,0x01,0xff,0x6e,0xcc,0xa7,
+ 0x00,0x01,0xff,0x6e,0xcc,0x8c,0x00,0xd2,0x1b,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e,
+ 0xcc,0x8c,0x00,0x01,0xff,0xca,0xbc,0x6e,0x00,0x10,0x07,0x01,0xff,0xc5,0x8b,0x00,
+ 0x01,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc,
+ 0x84,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x86,0x00,0x01,0xff,0x6f,0xcc,0x86,0x00,
+ 0xd3,0x3b,0xd2,0x1b,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x8b,0x00,0x01,0xff,
+ 0x6f,0xcc,0x8b,0x00,0x10,0x07,0x01,0xff,0xc5,0x93,0x00,0x01,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x72,0xcc,0x81,0x00,0x01,0xff,0x72,0xcc,0x81,0x00,0x10,0x08,0x01,
+ 0xff,0x72,0xcc,0xa7,0x00,0x01,0xff,0x72,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x72,0xcc,0x8c,0x00,0x01,0xff,0x72,0xcc,0x8c,0x00,0x10,0x08,0x01,
+ 0xff,0x73,0xcc,0x81,0x00,0x01,0xff,0x73,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x73,0xcc,0x82,0x00,0x01,0xff,0x73,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x73,
+ 0xcc,0xa7,0x00,0x01,0xff,0x73,0xcc,0xa7,0x00,0xd4,0x7b,0xd3,0x3b,0xd2,0x20,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x73,0xcc,0x8c,0x00,0x01,0xff,0x73,0xcc,0x8c,0x00,0x10,
+ 0x08,0x01,0xff,0x74,0xcc,0xa7,0x00,0x01,0xff,0x74,0xcc,0xa7,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x74,0xcc,0x8c,0x00,0x01,0xff,0x74,0xcc,0x8c,0x00,0x10,0x07,0x01,
+ 0xff,0xc5,0xa7,0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,
+ 0x83,0x00,0x01,0xff,0x75,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x84,0x00,
+ 0x01,0xff,0x75,0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x86,0x00,
+ 0x01,0xff,0x75,0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x8a,0x00,0x01,0xff,
+ 0x75,0xcc,0x8a,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,
+ 0x8b,0x00,0x01,0xff,0x75,0xcc,0x8b,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0xa8,0x00,
+ 0x01,0xff,0x75,0xcc,0xa8,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x82,0x00,
+ 0x01,0xff,0x77,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x79,0xcc,0x82,0x00,0x01,0xff,
+ 0x79,0xcc,0x82,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x79,0xcc,0x88,0x00,
+ 0x01,0xff,0x7a,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x81,0x00,0x01,0xff,
+ 0x7a,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x7a,0xcc,0x87,0x00,0x01,0xff,
+ 0x7a,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x8c,0x00,0x01,0xff,0x73,0x00,
+ 0xe0,0x65,0x01,0xcf,0x86,0xd5,0xb4,0xd4,0x5a,0xd3,0x2f,0xd2,0x16,0xd1,0x0b,0x10,
+ 0x04,0x01,0x00,0x01,0xff,0xc9,0x93,0x00,0x10,0x07,0x01,0xff,0xc6,0x83,0x00,0x01,
+ 0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xc6,0x85,0x00,0x01,0x00,0x10,0x07,0x01,0xff,
+ 0xc9,0x94,0x00,0x01,0xff,0xc6,0x88,0x00,0xd2,0x19,0xd1,0x0b,0x10,0x04,0x01,0x00,
+ 0x01,0xff,0xc9,0x96,0x00,0x10,0x07,0x01,0xff,0xc9,0x97,0x00,0x01,0xff,0xc6,0x8c,
+ 0x00,0x51,0x04,0x01,0x00,0x10,0x07,0x01,0xff,0xc7,0x9d,0x00,0x01,0xff,0xc9,0x99,
+ 0x00,0xd3,0x32,0xd2,0x19,0xd1,0x0e,0x10,0x07,0x01,0xff,0xc9,0x9b,0x00,0x01,0xff,
+ 0xc6,0x92,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xc9,0xa0,0x00,0xd1,0x0b,0x10,0x07,
+ 0x01,0xff,0xc9,0xa3,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xc9,0xa9,0x00,0x01,0xff,
+ 0xc9,0xa8,0x00,0xd2,0x0f,0x91,0x0b,0x10,0x07,0x01,0xff,0xc6,0x99,0x00,0x01,0x00,
+ 0x01,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xc9,0xaf,0x00,0x01,0xff,0xc9,0xb2,0x00,
+ 0x10,0x04,0x01,0x00,0x01,0xff,0xc9,0xb5,0x00,0xd4,0x5d,0xd3,0x34,0xd2,0x1b,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x9b,0x00,0x01,0xff,0x6f,0xcc,0x9b,0x00,0x10,
+ 0x07,0x01,0xff,0xc6,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xc6,0xa5,
+ 0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xca,0x80,0x00,0x01,0xff,0xc6,0xa8,0x00,0xd2,
+ 0x0f,0x91,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xca,0x83,0x00,0x01,0x00,0xd1,0x0b,
+ 0x10,0x07,0x01,0xff,0xc6,0xad,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xca,0x88,0x00,
+ 0x01,0xff,0x75,0xcc,0x9b,0x00,0xd3,0x33,0xd2,0x1d,0xd1,0x0f,0x10,0x08,0x01,0xff,
+ 0x75,0xcc,0x9b,0x00,0x01,0xff,0xca,0x8a,0x00,0x10,0x07,0x01,0xff,0xca,0x8b,0x00,
+ 0x01,0xff,0xc6,0xb4,0x00,0xd1,0x0b,0x10,0x04,0x01,0x00,0x01,0xff,0xc6,0xb6,0x00,
+ 0x10,0x04,0x01,0x00,0x01,0xff,0xca,0x92,0x00,0xd2,0x0f,0x91,0x0b,0x10,0x07,0x01,
+ 0xff,0xc6,0xb9,0x00,0x01,0x00,0x01,0x00,0x91,0x0b,0x10,0x07,0x01,0xff,0xc6,0xbd,
+ 0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0xd4,0xd4,0x44,0xd3,0x16,0x52,0x04,0x01,
+ 0x00,0x51,0x07,0x01,0xff,0xc7,0x86,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xc7,0x89,
+ 0x00,0xd2,0x12,0x91,0x0b,0x10,0x07,0x01,0xff,0xc7,0x89,0x00,0x01,0x00,0x01,0xff,
+ 0xc7,0x8c,0x00,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x61,0xcc,0x8c,0x00,0x10,
+ 0x08,0x01,0xff,0x61,0xcc,0x8c,0x00,0x01,0xff,0x69,0xcc,0x8c,0x00,0xd3,0x46,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x8c,0x00,0x01,0xff,0x6f,0xcc,0x8c,
+ 0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x8c,0x00,0x01,0xff,0x75,0xcc,0x8c,0x00,0xd1,
+ 0x12,0x10,0x08,0x01,0xff,0x75,0xcc,0x8c,0x00,0x01,0xff,0x75,0xcc,0x88,0xcc,0x84,
+ 0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x84,0x00,0x01,0xff,0x75,0xcc,0x88,
+ 0xcc,0x81,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x81,
+ 0x00,0x01,0xff,0x75,0xcc,0x88,0xcc,0x8c,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,
+ 0xcc,0x8c,0x00,0x01,0xff,0x75,0xcc,0x88,0xcc,0x80,0x00,0xd1,0x0e,0x10,0x0a,0x01,
+ 0xff,0x75,0xcc,0x88,0xcc,0x80,0x00,0x01,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0x88,
+ 0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x88,0xcc,0x84,0x00,0xd4,0x87,0xd3,0x41,0xd2,
+ 0x26,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0x87,0xcc,0x84,0x00,0x01,0xff,0x61,
+ 0xcc,0x87,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xc3,0xa6,0xcc,0x84,0x00,0x01,0xff,
+ 0xc3,0xa6,0xcc,0x84,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xc7,0xa5,0x00,0x01,0x00,
+ 0x10,0x08,0x01,0xff,0x67,0xcc,0x8c,0x00,0x01,0xff,0x67,0xcc,0x8c,0x00,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0x6b,0xcc,0x8c,0x00,0x01,0xff,0x6b,0xcc,0x8c,0x00,
+ 0x10,0x08,0x01,0xff,0x6f,0xcc,0xa8,0x00,0x01,0xff,0x6f,0xcc,0xa8,0x00,0xd1,0x14,
+ 0x10,0x0a,0x01,0xff,0x6f,0xcc,0xa8,0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc,0xa8,0xcc,
+ 0x84,0x00,0x10,0x09,0x01,0xff,0xca,0x92,0xcc,0x8c,0x00,0x01,0xff,0xca,0x92,0xcc,
+ 0x8c,0x00,0xd3,0x38,0xd2,0x1a,0xd1,0x0f,0x10,0x08,0x01,0xff,0x6a,0xcc,0x8c,0x00,
+ 0x01,0xff,0xc7,0xb3,0x00,0x10,0x07,0x01,0xff,0xc7,0xb3,0x00,0x01,0x00,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0x67,0xcc,0x81,0x00,0x01,0xff,0x67,0xcc,0x81,0x00,0x10,0x07,
+ 0x04,0xff,0xc6,0x95,0x00,0x04,0xff,0xc6,0xbf,0x00,0xd2,0x24,0xd1,0x10,0x10,0x08,
+ 0x04,0xff,0x6e,0xcc,0x80,0x00,0x04,0xff,0x6e,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,
+ 0x61,0xcc,0x8a,0xcc,0x81,0x00,0x01,0xff,0x61,0xcc,0x8a,0xcc,0x81,0x00,0xd1,0x12,
+ 0x10,0x09,0x01,0xff,0xc3,0xa6,0xcc,0x81,0x00,0x01,0xff,0xc3,0xa6,0xcc,0x81,0x00,
+ 0x10,0x09,0x01,0xff,0xc3,0xb8,0xcc,0x81,0x00,0x01,0xff,0xc3,0xb8,0xcc,0x81,0x00,
+ 0xe2,0x31,0x02,0xe1,0xc3,0x44,0xe0,0xc8,0x01,0xcf,0x86,0xd5,0xfb,0xd4,0x80,0xd3,
+ 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0x8f,0x00,0x01,0xff,0x61,
+ 0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x61,0xcc,0x91,0x00,0x01,0xff,0x61,0xcc,0x91,
+ 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0x8f,0x00,0x01,0xff,0x65,0xcc,0x8f,
+ 0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x91,0x00,0x01,0xff,0x65,0xcc,0x91,0x00,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x8f,0x00,0x01,0xff,0x69,0xcc,0x8f,
+ 0x00,0x10,0x08,0x01,0xff,0x69,0xcc,0x91,0x00,0x01,0xff,0x69,0xcc,0x91,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x8f,0x00,0x01,0xff,0x6f,0xcc,0x8f,0x00,0x10,
+ 0x08,0x01,0xff,0x6f,0xcc,0x91,0x00,0x01,0xff,0x6f,0xcc,0x91,0x00,0xd3,0x40,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x72,0xcc,0x8f,0x00,0x01,0xff,0x72,0xcc,0x8f,
+ 0x00,0x10,0x08,0x01,0xff,0x72,0xcc,0x91,0x00,0x01,0xff,0x72,0xcc,0x91,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x8f,0x00,0x01,0xff,0x75,0xcc,0x8f,0x00,0x10,
+ 0x08,0x01,0xff,0x75,0xcc,0x91,0x00,0x01,0xff,0x75,0xcc,0x91,0x00,0xd2,0x20,0xd1,
+ 0x10,0x10,0x08,0x04,0xff,0x73,0xcc,0xa6,0x00,0x04,0xff,0x73,0xcc,0xa6,0x00,0x10,
+ 0x08,0x04,0xff,0x74,0xcc,0xa6,0x00,0x04,0xff,0x74,0xcc,0xa6,0x00,0xd1,0x0b,0x10,
+ 0x07,0x04,0xff,0xc8,0x9d,0x00,0x04,0x00,0x10,0x08,0x04,0xff,0x68,0xcc,0x8c,0x00,
+ 0x04,0xff,0x68,0xcc,0x8c,0x00,0xd4,0x79,0xd3,0x31,0xd2,0x16,0xd1,0x0b,0x10,0x07,
+ 0x06,0xff,0xc6,0x9e,0x00,0x07,0x00,0x10,0x07,0x04,0xff,0xc8,0xa3,0x00,0x04,0x00,
+ 0xd1,0x0b,0x10,0x07,0x04,0xff,0xc8,0xa5,0x00,0x04,0x00,0x10,0x08,0x04,0xff,0x61,
+ 0xcc,0x87,0x00,0x04,0xff,0x61,0xcc,0x87,0x00,0xd2,0x24,0xd1,0x10,0x10,0x08,0x04,
+ 0xff,0x65,0xcc,0xa7,0x00,0x04,0xff,0x65,0xcc,0xa7,0x00,0x10,0x0a,0x04,0xff,0x6f,
+ 0xcc,0x88,0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc,0x88,0xcc,0x84,0x00,0xd1,0x14,0x10,
+ 0x0a,0x04,0xff,0x6f,0xcc,0x83,0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc,0x83,0xcc,0x84,
+ 0x00,0x10,0x08,0x04,0xff,0x6f,0xcc,0x87,0x00,0x04,0xff,0x6f,0xcc,0x87,0x00,0xd3,
+ 0x27,0xe2,0x21,0x43,0xd1,0x14,0x10,0x0a,0x04,0xff,0x6f,0xcc,0x87,0xcc,0x84,0x00,
+ 0x04,0xff,0x6f,0xcc,0x87,0xcc,0x84,0x00,0x10,0x08,0x04,0xff,0x79,0xcc,0x84,0x00,
+ 0x04,0xff,0x79,0xcc,0x84,0x00,0xd2,0x13,0x51,0x04,0x08,0x00,0x10,0x08,0x08,0xff,
+ 0xe2,0xb1,0xa5,0x00,0x08,0xff,0xc8,0xbc,0x00,0xd1,0x0b,0x10,0x04,0x08,0x00,0x08,
+ 0xff,0xc6,0x9a,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0xa6,0x00,0x08,0x00,0xcf,0x86,
+ 0x95,0x5f,0x94,0x5b,0xd3,0x2f,0xd2,0x16,0xd1,0x0b,0x10,0x04,0x08,0x00,0x08,0xff,
+ 0xc9,0x82,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xc6,0x80,0x00,0xd1,0x0e,0x10,0x07,
+ 0x09,0xff,0xca,0x89,0x00,0x09,0xff,0xca,0x8c,0x00,0x10,0x07,0x09,0xff,0xc9,0x87,
+ 0x00,0x09,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x09,0xff,0xc9,0x89,0x00,0x09,0x00,
+ 0x10,0x07,0x09,0xff,0xc9,0x8b,0x00,0x09,0x00,0xd1,0x0b,0x10,0x07,0x09,0xff,0xc9,
+ 0x8d,0x00,0x09,0x00,0x10,0x07,0x09,0xff,0xc9,0x8f,0x00,0x09,0x00,0x01,0x00,0x01,
+ 0x00,0xd1,0x8b,0xd0,0x0c,0xcf,0x86,0xe5,0x10,0x43,0x64,0xef,0x42,0x01,0xe6,0xcf,
+ 0x86,0xd5,0x2a,0xe4,0x99,0x43,0xe3,0x7f,0x43,0xd2,0x11,0xe1,0x5e,0x43,0x10,0x07,
+ 0x01,0xff,0xcc,0x80,0x00,0x01,0xff,0xcc,0x81,0x00,0xe1,0x65,0x43,0x10,0x09,0x01,
+ 0xff,0xcc,0x88,0xcc,0x81,0x00,0x01,0xff,0xce,0xb9,0x00,0xd4,0x0f,0x93,0x0b,0x92,
+ 0x07,0x61,0xab,0x43,0x01,0xea,0x06,0xe6,0x06,0xe6,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,
+ 0x10,0x07,0x0a,0xff,0xcd,0xb1,0x00,0x0a,0x00,0x10,0x07,0x0a,0xff,0xcd,0xb3,0x00,
+ 0x0a,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xca,0xb9,0x00,0x01,0x00,0x10,0x07,0x0a,
+ 0xff,0xcd,0xb7,0x00,0x0a,0x00,0xd2,0x07,0x61,0x97,0x43,0x00,0x00,0x51,0x04,0x09,
+ 0x00,0x10,0x06,0x01,0xff,0x3b,0x00,0x10,0xff,0xcf,0xb3,0x00,0xe0,0x31,0x01,0xcf,
+ 0x86,0xd5,0xd3,0xd4,0x5f,0xd3,0x21,0x52,0x04,0x00,0x00,0xd1,0x0d,0x10,0x04,0x01,
+ 0x00,0x01,0xff,0xc2,0xa8,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x81,
+ 0x00,0x01,0xff,0xc2,0xb7,0x00,0xd2,0x1f,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb5,
+ 0xcc,0x81,0x00,0x01,0xff,0xce,0xb7,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,
+ 0xcc,0x81,0x00,0x00,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00,
+ 0x00,0x00,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0x01,0xff,0xcf,0x89,0xcc,
+ 0x81,0x00,0xd3,0x3c,0xd2,0x20,0xd1,0x12,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x88,
+ 0xcc,0x81,0x00,0x01,0xff,0xce,0xb1,0x00,0x10,0x07,0x01,0xff,0xce,0xb2,0x00,0x01,
+ 0xff,0xce,0xb3,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xce,0xb4,0x00,0x01,0xff,0xce,
+ 0xb5,0x00,0x10,0x07,0x01,0xff,0xce,0xb6,0x00,0x01,0xff,0xce,0xb7,0x00,0xd2,0x1c,
+ 0xd1,0x0e,0x10,0x07,0x01,0xff,0xce,0xb8,0x00,0x01,0xff,0xce,0xb9,0x00,0x10,0x07,
+ 0x01,0xff,0xce,0xba,0x00,0x01,0xff,0xce,0xbb,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,
+ 0xce,0xbc,0x00,0x01,0xff,0xce,0xbd,0x00,0x10,0x07,0x01,0xff,0xce,0xbe,0x00,0x01,
+ 0xff,0xce,0xbf,0x00,0xe4,0x85,0x43,0xd3,0x35,0xd2,0x19,0xd1,0x0e,0x10,0x07,0x01,
+ 0xff,0xcf,0x80,0x00,0x01,0xff,0xcf,0x81,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xcf,
+ 0x83,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xcf,0x84,0x00,0x01,0xff,0xcf,0x85,0x00,
+ 0x10,0x07,0x01,0xff,0xcf,0x86,0x00,0x01,0xff,0xcf,0x87,0x00,0xe2,0x2b,0x43,0xd1,
+ 0x0e,0x10,0x07,0x01,0xff,0xcf,0x88,0x00,0x01,0xff,0xcf,0x89,0x00,0x10,0x09,0x01,
+ 0xff,0xce,0xb9,0xcc,0x88,0x00,0x01,0xff,0xcf,0x85,0xcc,0x88,0x00,0xcf,0x86,0xd5,
+ 0x94,0xd4,0x3c,0xd3,0x13,0x92,0x0f,0x51,0x04,0x01,0x00,0x10,0x07,0x01,0xff,0xcf,
+ 0x83,0x00,0x01,0x00,0x01,0x00,0xd2,0x07,0x61,0x3a,0x43,0x01,0x00,0xd1,0x12,0x10,
+ 0x09,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0x10,
+ 0x09,0x01,0xff,0xcf,0x89,0xcc,0x81,0x00,0x0a,0xff,0xcf,0x97,0x00,0xd3,0x2c,0xd2,
+ 0x11,0xe1,0x46,0x43,0x10,0x07,0x01,0xff,0xce,0xb2,0x00,0x01,0xff,0xce,0xb8,0x00,
+ 0xd1,0x10,0x10,0x09,0x01,0xff,0xcf,0x92,0xcc,0x88,0x00,0x01,0xff,0xcf,0x86,0x00,
+ 0x10,0x07,0x01,0xff,0xcf,0x80,0x00,0x04,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x06,
+ 0xff,0xcf,0x99,0x00,0x06,0x00,0x10,0x07,0x01,0xff,0xcf,0x9b,0x00,0x04,0x00,0xd1,
+ 0x0b,0x10,0x07,0x01,0xff,0xcf,0x9d,0x00,0x04,0x00,0x10,0x07,0x01,0xff,0xcf,0x9f,
+ 0x00,0x04,0x00,0xd4,0x58,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xcf,
+ 0xa1,0x00,0x04,0x00,0x10,0x07,0x01,0xff,0xcf,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10,
+ 0x07,0x01,0xff,0xcf,0xa5,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xcf,0xa7,0x00,0x01,
+ 0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xcf,0xa9,0x00,0x01,0x00,0x10,0x07,
+ 0x01,0xff,0xcf,0xab,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xcf,0xad,0x00,
+ 0x01,0x00,0x10,0x07,0x01,0xff,0xcf,0xaf,0x00,0x01,0x00,0xd3,0x2b,0xd2,0x12,0x91,
+ 0x0e,0x10,0x07,0x01,0xff,0xce,0xba,0x00,0x01,0xff,0xcf,0x81,0x00,0x01,0x00,0xd1,
+ 0x0e,0x10,0x07,0x05,0xff,0xce,0xb8,0x00,0x05,0xff,0xce,0xb5,0x00,0x10,0x04,0x06,
+ 0x00,0x07,0xff,0xcf,0xb8,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x04,0x07,0x00,0x07,0xff,
+ 0xcf,0xb2,0x00,0x10,0x07,0x07,0xff,0xcf,0xbb,0x00,0x07,0x00,0xd1,0x0b,0x10,0x04,
+ 0x08,0x00,0x08,0xff,0xcd,0xbb,0x00,0x10,0x07,0x08,0xff,0xcd,0xbc,0x00,0x08,0xff,
+ 0xcd,0xbd,0x00,0xe3,0xed,0x46,0xe2,0x3d,0x05,0xe1,0x27,0x02,0xe0,0x66,0x01,0xcf,
+ 0x86,0xd5,0xf0,0xd4,0x7e,0xd3,0x40,0xd2,0x22,0xd1,0x12,0x10,0x09,0x04,0xff,0xd0,
+ 0xb5,0xcc,0x80,0x00,0x01,0xff,0xd0,0xb5,0xcc,0x88,0x00,0x10,0x07,0x01,0xff,0xd1,
+ 0x92,0x00,0x01,0xff,0xd0,0xb3,0xcc,0x81,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,
+ 0x94,0x00,0x01,0xff,0xd1,0x95,0x00,0x10,0x07,0x01,0xff,0xd1,0x96,0x00,0x01,0xff,
+ 0xd1,0x96,0xcc,0x88,0x00,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x98,0x00,
+ 0x01,0xff,0xd1,0x99,0x00,0x10,0x07,0x01,0xff,0xd1,0x9a,0x00,0x01,0xff,0xd1,0x9b,
+ 0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0xba,0xcc,0x81,0x00,0x04,0xff,0xd0,0xb8,
+ 0xcc,0x80,0x00,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x86,0x00,0x01,0xff,0xd1,0x9f,
+ 0x00,0xd3,0x38,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd0,0xb0,0x00,0x01,0xff,
+ 0xd0,0xb1,0x00,0x10,0x07,0x01,0xff,0xd0,0xb2,0x00,0x01,0xff,0xd0,0xb3,0x00,0xd1,
+ 0x0e,0x10,0x07,0x01,0xff,0xd0,0xb4,0x00,0x01,0xff,0xd0,0xb5,0x00,0x10,0x07,0x01,
+ 0xff,0xd0,0xb6,0x00,0x01,0xff,0xd0,0xb7,0x00,0xd2,0x1e,0xd1,0x10,0x10,0x07,0x01,
+ 0xff,0xd0,0xb8,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x86,0x00,0x10,0x07,0x01,0xff,0xd0,
+ 0xba,0x00,0x01,0xff,0xd0,0xbb,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd0,0xbc,0x00,
+ 0x01,0xff,0xd0,0xbd,0x00,0x10,0x07,0x01,0xff,0xd0,0xbe,0x00,0x01,0xff,0xd0,0xbf,
+ 0x00,0xe4,0x25,0x42,0xd3,0x38,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x80,
+ 0x00,0x01,0xff,0xd1,0x81,0x00,0x10,0x07,0x01,0xff,0xd1,0x82,0x00,0x01,0xff,0xd1,
+ 0x83,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x84,0x00,0x01,0xff,0xd1,0x85,0x00,
+ 0x10,0x07,0x01,0xff,0xd1,0x86,0x00,0x01,0xff,0xd1,0x87,0x00,0xd2,0x1c,0xd1,0x0e,
+ 0x10,0x07,0x01,0xff,0xd1,0x88,0x00,0x01,0xff,0xd1,0x89,0x00,0x10,0x07,0x01,0xff,
+ 0xd1,0x8a,0x00,0x01,0xff,0xd1,0x8b,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd1,0x8c,
+ 0x00,0x01,0xff,0xd1,0x8d,0x00,0x10,0x07,0x01,0xff,0xd1,0x8e,0x00,0x01,0xff,0xd1,
+ 0x8f,0x00,0xcf,0x86,0xd5,0x07,0x64,0xcf,0x41,0x01,0x00,0xd4,0x58,0xd3,0x2c,0xd2,
+ 0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xa1,0x00,0x01,0x00,0x10,0x07,0x01,0xff,
+ 0xd1,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xa5,0x00,0x01,0x00,
+ 0x10,0x07,0x01,0xff,0xd1,0xa7,0x00,0x01,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,
+ 0xff,0xd1,0xa9,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xab,0x00,0x01,0x00,0xd1,
+ 0x0b,0x10,0x07,0x01,0xff,0xd1,0xad,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xaf,
+ 0x00,0x01,0x00,0xd3,0x33,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xb1,0x00,
+ 0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xb3,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,
+ 0xff,0xd1,0xb5,0x00,0x01,0x00,0x10,0x09,0x01,0xff,0xd1,0xb5,0xcc,0x8f,0x00,0x01,
+ 0xff,0xd1,0xb5,0xcc,0x8f,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd1,0xb9,
+ 0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xbb,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,
+ 0x01,0xff,0xd1,0xbd,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd1,0xbf,0x00,0x01,0x00,
+ 0xe0,0x41,0x01,0xcf,0x86,0xd5,0x8e,0xd4,0x36,0xd3,0x11,0xe2,0x91,0x41,0xe1,0x88,
+ 0x41,0x10,0x07,0x01,0xff,0xd2,0x81,0x00,0x01,0x00,0xd2,0x0f,0x51,0x04,0x04,0x00,
+ 0x10,0x07,0x06,0xff,0xd2,0x8b,0x00,0x06,0x00,0xd1,0x0b,0x10,0x07,0x04,0xff,0xd2,
+ 0x8d,0x00,0x04,0x00,0x10,0x07,0x04,0xff,0xd2,0x8f,0x00,0x04,0x00,0xd3,0x2c,0xd2,
+ 0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0x91,0x00,0x01,0x00,0x10,0x07,0x01,0xff,
+ 0xd2,0x93,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0x95,0x00,0x01,0x00,
+ 0x10,0x07,0x01,0xff,0xd2,0x97,0x00,0x01,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,
+ 0xff,0xd2,0x99,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0x9b,0x00,0x01,0x00,0xd1,
+ 0x0b,0x10,0x07,0x01,0xff,0xd2,0x9d,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0x9f,
+ 0x00,0x01,0x00,0xd4,0x58,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,
+ 0xa1,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xa3,0x00,0x01,0x00,0xd1,0x0b,0x10,
+ 0x07,0x01,0xff,0xd2,0xa5,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xa7,0x00,0x01,
+ 0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xa9,0x00,0x01,0x00,0x10,0x07,
+ 0x01,0xff,0xd2,0xab,0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xad,0x00,
+ 0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xaf,0x00,0x01,0x00,0xd3,0x2c,0xd2,0x16,0xd1,
+ 0x0b,0x10,0x07,0x01,0xff,0xd2,0xb1,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xb3,
+ 0x00,0x01,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,0xb5,0x00,0x01,0x00,0x10,0x07,
+ 0x01,0xff,0xd2,0xb7,0x00,0x01,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd2,
+ 0xb9,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xbb,0x00,0x01,0x00,0xd1,0x0b,0x10,
+ 0x07,0x01,0xff,0xd2,0xbd,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xd2,0xbf,0x00,0x01,
+ 0x00,0xcf,0x86,0xd5,0xdc,0xd4,0x5a,0xd3,0x36,0xd2,0x20,0xd1,0x10,0x10,0x07,0x01,
+ 0xff,0xd3,0x8f,0x00,0x01,0xff,0xd0,0xb6,0xcc,0x86,0x00,0x10,0x09,0x01,0xff,0xd0,
+ 0xb6,0xcc,0x86,0x00,0x01,0xff,0xd3,0x84,0x00,0xd1,0x0b,0x10,0x04,0x01,0x00,0x06,
+ 0xff,0xd3,0x86,0x00,0x10,0x04,0x06,0x00,0x01,0xff,0xd3,0x88,0x00,0xd2,0x16,0xd1,
+ 0x0b,0x10,0x04,0x01,0x00,0x06,0xff,0xd3,0x8a,0x00,0x10,0x04,0x06,0x00,0x01,0xff,
+ 0xd3,0x8c,0x00,0xe1,0x69,0x40,0x10,0x04,0x01,0x00,0x06,0xff,0xd3,0x8e,0x00,0xd3,
+ 0x41,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0xb0,0xcc,0x86,0x00,0x01,0xff,
+ 0xd0,0xb0,0xcc,0x86,0x00,0x10,0x09,0x01,0xff,0xd0,0xb0,0xcc,0x88,0x00,0x01,0xff,
+ 0xd0,0xb0,0xcc,0x88,0x00,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0x95,0x00,0x01,0x00,
+ 0x10,0x09,0x01,0xff,0xd0,0xb5,0xcc,0x86,0x00,0x01,0xff,0xd0,0xb5,0xcc,0x86,0x00,
+ 0xd2,0x1d,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0x99,0x00,0x01,0x00,0x10,0x09,0x01,
+ 0xff,0xd3,0x99,0xcc,0x88,0x00,0x01,0xff,0xd3,0x99,0xcc,0x88,0x00,0xd1,0x12,0x10,
+ 0x09,0x01,0xff,0xd0,0xb6,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb6,0xcc,0x88,0x00,0x10,
+ 0x09,0x01,0xff,0xd0,0xb7,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb7,0xcc,0x88,0x00,0xd4,
+ 0x82,0xd3,0x41,0xd2,0x1d,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0xa1,0x00,0x01,0x00,
+ 0x10,0x09,0x01,0xff,0xd0,0xb8,0xcc,0x84,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x84,0x00,
+ 0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0xb8,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb8,0xcc,
+ 0x88,0x00,0x10,0x09,0x01,0xff,0xd0,0xbe,0xcc,0x88,0x00,0x01,0xff,0xd0,0xbe,0xcc,
+ 0x88,0x00,0xd2,0x1d,0xd1,0x0b,0x10,0x07,0x01,0xff,0xd3,0xa9,0x00,0x01,0x00,0x10,
+ 0x09,0x01,0xff,0xd3,0xa9,0xcc,0x88,0x00,0x01,0xff,0xd3,0xa9,0xcc,0x88,0x00,0xd1,
+ 0x12,0x10,0x09,0x04,0xff,0xd1,0x8d,0xcc,0x88,0x00,0x04,0xff,0xd1,0x8d,0xcc,0x88,
+ 0x00,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x84,0x00,0x01,0xff,0xd1,0x83,0xcc,0x84,
+ 0x00,0xd3,0x41,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x88,0x00,
+ 0x01,0xff,0xd1,0x83,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,0xd1,0x83,0xcc,0x8b,0x00,
+ 0x01,0xff,0xd1,0x83,0xcc,0x8b,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd1,0x87,0xcc,
+ 0x88,0x00,0x01,0xff,0xd1,0x87,0xcc,0x88,0x00,0x10,0x07,0x08,0xff,0xd3,0xb7,0x00,
+ 0x08,0x00,0xd2,0x1d,0xd1,0x12,0x10,0x09,0x01,0xff,0xd1,0x8b,0xcc,0x88,0x00,0x01,
+ 0xff,0xd1,0x8b,0xcc,0x88,0x00,0x10,0x07,0x09,0xff,0xd3,0xbb,0x00,0x09,0x00,0xd1,
+ 0x0b,0x10,0x07,0x09,0xff,0xd3,0xbd,0x00,0x09,0x00,0x10,0x07,0x09,0xff,0xd3,0xbf,
+ 0x00,0x09,0x00,0xe1,0x26,0x02,0xe0,0x78,0x01,0xcf,0x86,0xd5,0xb0,0xd4,0x58,0xd3,
+ 0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x06,0xff,0xd4,0x81,0x00,0x06,0x00,0x10,0x07,
+ 0x06,0xff,0xd4,0x83,0x00,0x06,0x00,0xd1,0x0b,0x10,0x07,0x06,0xff,0xd4,0x85,0x00,
+ 0x06,0x00,0x10,0x07,0x06,0xff,0xd4,0x87,0x00,0x06,0x00,0xd2,0x16,0xd1,0x0b,0x10,
+ 0x07,0x06,0xff,0xd4,0x89,0x00,0x06,0x00,0x10,0x07,0x06,0xff,0xd4,0x8b,0x00,0x06,
+ 0x00,0xd1,0x0b,0x10,0x07,0x06,0xff,0xd4,0x8d,0x00,0x06,0x00,0x10,0x07,0x06,0xff,
+ 0xd4,0x8f,0x00,0x06,0x00,0xd3,0x2c,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x09,0xff,0xd4,
+ 0x91,0x00,0x09,0x00,0x10,0x07,0x09,0xff,0xd4,0x93,0x00,0x09,0x00,0xd1,0x0b,0x10,
+ 0x07,0x0a,0xff,0xd4,0x95,0x00,0x0a,0x00,0x10,0x07,0x0a,0xff,0xd4,0x97,0x00,0x0a,
+ 0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x0a,0xff,0xd4,0x99,0x00,0x0a,0x00,0x10,0x07,
+ 0x0a,0xff,0xd4,0x9b,0x00,0x0a,0x00,0xd1,0x0b,0x10,0x07,0x0a,0xff,0xd4,0x9d,0x00,
+ 0x0a,0x00,0x10,0x07,0x0a,0xff,0xd4,0x9f,0x00,0x0a,0x00,0xd4,0x58,0xd3,0x2c,0xd2,
+ 0x16,0xd1,0x0b,0x10,0x07,0x0a,0xff,0xd4,0xa1,0x00,0x0a,0x00,0x10,0x07,0x0a,0xff,
+ 0xd4,0xa3,0x00,0x0a,0x00,0xd1,0x0b,0x10,0x07,0x0b,0xff,0xd4,0xa5,0x00,0x0b,0x00,
+ 0x10,0x07,0x0c,0xff,0xd4,0xa7,0x00,0x0c,0x00,0xd2,0x16,0xd1,0x0b,0x10,0x07,0x10,
+ 0xff,0xd4,0xa9,0x00,0x10,0x00,0x10,0x07,0x10,0xff,0xd4,0xab,0x00,0x10,0x00,0xd1,
+ 0x0b,0x10,0x07,0x10,0xff,0xd4,0xad,0x00,0x10,0x00,0x10,0x07,0x10,0xff,0xd4,0xaf,
+ 0x00,0x10,0x00,0xd3,0x35,0xd2,0x19,0xd1,0x0b,0x10,0x04,0x00,0x00,0x01,0xff,0xd5,
+ 0xa1,0x00,0x10,0x07,0x01,0xff,0xd5,0xa2,0x00,0x01,0xff,0xd5,0xa3,0x00,0xd1,0x0e,
+ 0x10,0x07,0x01,0xff,0xd5,0xa4,0x00,0x01,0xff,0xd5,0xa5,0x00,0x10,0x07,0x01,0xff,
+ 0xd5,0xa6,0x00,0x01,0xff,0xd5,0xa7,0x00,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,
+ 0xd5,0xa8,0x00,0x01,0xff,0xd5,0xa9,0x00,0x10,0x07,0x01,0xff,0xd5,0xaa,0x00,0x01,
+ 0xff,0xd5,0xab,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,0xac,0x00,0x01,0xff,0xd5,
+ 0xad,0x00,0x10,0x07,0x01,0xff,0xd5,0xae,0x00,0x01,0xff,0xd5,0xaf,0x00,0xcf,0x86,
+ 0xe5,0x08,0x3f,0xd4,0x70,0xd3,0x38,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,
+ 0xb0,0x00,0x01,0xff,0xd5,0xb1,0x00,0x10,0x07,0x01,0xff,0xd5,0xb2,0x00,0x01,0xff,
+ 0xd5,0xb3,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,0xb4,0x00,0x01,0xff,0xd5,0xb5,
+ 0x00,0x10,0x07,0x01,0xff,0xd5,0xb6,0x00,0x01,0xff,0xd5,0xb7,0x00,0xd2,0x1c,0xd1,
+ 0x0e,0x10,0x07,0x01,0xff,0xd5,0xb8,0x00,0x01,0xff,0xd5,0xb9,0x00,0x10,0x07,0x01,
+ 0xff,0xd5,0xba,0x00,0x01,0xff,0xd5,0xbb,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd5,
+ 0xbc,0x00,0x01,0xff,0xd5,0xbd,0x00,0x10,0x07,0x01,0xff,0xd5,0xbe,0x00,0x01,0xff,
+ 0xd5,0xbf,0x00,0xe3,0x87,0x3e,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd6,0x80,
+ 0x00,0x01,0xff,0xd6,0x81,0x00,0x10,0x07,0x01,0xff,0xd6,0x82,0x00,0x01,0xff,0xd6,
+ 0x83,0x00,0xd1,0x0e,0x10,0x07,0x01,0xff,0xd6,0x84,0x00,0x01,0xff,0xd6,0x85,0x00,
+ 0x10,0x07,0x01,0xff,0xd6,0x86,0x00,0x00,0x00,0xe0,0x2f,0x3f,0xcf,0x86,0xe5,0xc0,
+ 0x3e,0xe4,0x97,0x3e,0xe3,0x76,0x3e,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,
+ 0x04,0x01,0x00,0x01,0xff,0xd5,0xa5,0xd6,0x82,0x00,0xe4,0x3e,0x25,0xe3,0xc3,0x1a,
+ 0xe2,0x7b,0x81,0xe1,0xc0,0x13,0xd0,0x1e,0xcf,0x86,0xc5,0xe4,0x08,0x4b,0xe3,0x53,
+ 0x46,0xe2,0xe9,0x43,0xe1,0x1c,0x43,0xe0,0xe1,0x42,0xcf,0x86,0xe5,0xa6,0x42,0x64,
+ 0x89,0x42,0x0b,0x00,0xcf,0x86,0xe5,0xfa,0x01,0xe4,0x03,0x56,0xe3,0x76,0x01,0xe2,
+ 0x8e,0x53,0xd1,0x0c,0xe0,0xef,0x52,0xcf,0x86,0x65,0x8d,0x52,0x04,0x00,0xe0,0x0d,
+ 0x01,0xcf,0x86,0xd5,0x0a,0xe4,0x10,0x53,0x63,0xff,0x52,0x0a,0x00,0xd4,0x80,0xd3,
+ 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x80,0x00,0x01,0xff,0xe2,
+ 0xb4,0x81,0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0x82,0x00,0x01,0xff,0xe2,0xb4,0x83,
+ 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x84,0x00,0x01,0xff,0xe2,0xb4,0x85,
+ 0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0x86,0x00,0x01,0xff,0xe2,0xb4,0x87,0x00,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x88,0x00,0x01,0xff,0xe2,0xb4,0x89,
+ 0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0x8a,0x00,0x01,0xff,0xe2,0xb4,0x8b,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x8c,0x00,0x01,0xff,0xe2,0xb4,0x8d,0x00,0x10,
+ 0x08,0x01,0xff,0xe2,0xb4,0x8e,0x00,0x01,0xff,0xe2,0xb4,0x8f,0x00,0xd3,0x40,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x90,0x00,0x01,0xff,0xe2,0xb4,0x91,
+ 0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0x92,0x00,0x01,0xff,0xe2,0xb4,0x93,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x94,0x00,0x01,0xff,0xe2,0xb4,0x95,0x00,0x10,
+ 0x08,0x01,0xff,0xe2,0xb4,0x96,0x00,0x01,0xff,0xe2,0xb4,0x97,0x00,0xd2,0x20,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0x98,0x00,0x01,0xff,0xe2,0xb4,0x99,0x00,0x10,
+ 0x08,0x01,0xff,0xe2,0xb4,0x9a,0x00,0x01,0xff,0xe2,0xb4,0x9b,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0xe2,0xb4,0x9c,0x00,0x01,0xff,0xe2,0xb4,0x9d,0x00,0x10,0x08,0x01,
+ 0xff,0xe2,0xb4,0x9e,0x00,0x01,0xff,0xe2,0xb4,0x9f,0x00,0xcf,0x86,0xe5,0x42,0x52,
+ 0x94,0x50,0xd3,0x3c,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0xa0,0x00,
+ 0x01,0xff,0xe2,0xb4,0xa1,0x00,0x10,0x08,0x01,0xff,0xe2,0xb4,0xa2,0x00,0x01,0xff,
+ 0xe2,0xb4,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0xb4,0xa4,0x00,0x01,0xff,
+ 0xe2,0xb4,0xa5,0x00,0x10,0x04,0x00,0x00,0x0d,0xff,0xe2,0xb4,0xa7,0x00,0x52,0x04,
+ 0x00,0x00,0x91,0x0c,0x10,0x04,0x00,0x00,0x0d,0xff,0xe2,0xb4,0xad,0x00,0x00,0x00,
+ 0x01,0x00,0xd2,0x1b,0xe1,0xfc,0x52,0xe0,0xad,0x52,0xcf,0x86,0x95,0x0f,0x94,0x0b,
+ 0x93,0x07,0x62,0x92,0x52,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xd1,0x13,0xe0,
+ 0xd3,0x53,0xcf,0x86,0x95,0x0a,0xe4,0xa8,0x53,0x63,0x97,0x53,0x04,0x00,0x04,0x00,
+ 0xd0,0x0d,0xcf,0x86,0x95,0x07,0x64,0x22,0x54,0x08,0x00,0x04,0x00,0xcf,0x86,0x55,
+ 0x04,0x04,0x00,0x54,0x04,0x04,0x00,0xd3,0x07,0x62,0x2f,0x54,0x04,0x00,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8f,0xb0,0x00,0x11,0xff,0xe1,0x8f,0xb1,0x00,
+ 0x10,0x08,0x11,0xff,0xe1,0x8f,0xb2,0x00,0x11,0xff,0xe1,0x8f,0xb3,0x00,0x91,0x10,
+ 0x10,0x08,0x11,0xff,0xe1,0x8f,0xb4,0x00,0x11,0xff,0xe1,0x8f,0xb5,0x00,0x00,0x00,
+ 0xd4,0x1c,0xe3,0xe0,0x56,0xe2,0x17,0x56,0xe1,0xda,0x55,0xe0,0xbb,0x55,0xcf,0x86,
+ 0x95,0x0a,0xe4,0xa4,0x55,0x63,0x88,0x55,0x04,0x00,0x04,0x00,0xe3,0xd2,0x01,0xe2,
+ 0x2b,0x5a,0xd1,0x0c,0xe0,0x4c,0x59,0xcf,0x86,0x65,0x25,0x59,0x0a,0x00,0xe0,0x9c,
+ 0x59,0xcf,0x86,0xd5,0xc5,0xd4,0x45,0xd3,0x31,0xd2,0x1c,0xd1,0x0e,0x10,0x07,0x12,
+ 0xff,0xd0,0xb2,0x00,0x12,0xff,0xd0,0xb4,0x00,0x10,0x07,0x12,0xff,0xd0,0xbe,0x00,
+ 0x12,0xff,0xd1,0x81,0x00,0x51,0x07,0x12,0xff,0xd1,0x82,0x00,0x10,0x07,0x12,0xff,
+ 0xd1,0x8a,0x00,0x12,0xff,0xd1,0xa3,0x00,0x92,0x10,0x91,0x0c,0x10,0x08,0x12,0xff,
+ 0xea,0x99,0x8b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x14,0xff,0xe1,0x83,0x90,0x00,0x14,0xff,0xe1,0x83,0x91,0x00,0x10,0x08,
+ 0x14,0xff,0xe1,0x83,0x92,0x00,0x14,0xff,0xe1,0x83,0x93,0x00,0xd1,0x10,0x10,0x08,
+ 0x14,0xff,0xe1,0x83,0x94,0x00,0x14,0xff,0xe1,0x83,0x95,0x00,0x10,0x08,0x14,0xff,
+ 0xe1,0x83,0x96,0x00,0x14,0xff,0xe1,0x83,0x97,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x14,0xff,0xe1,0x83,0x98,0x00,0x14,0xff,0xe1,0x83,0x99,0x00,0x10,0x08,0x14,0xff,
+ 0xe1,0x83,0x9a,0x00,0x14,0xff,0xe1,0x83,0x9b,0x00,0xd1,0x10,0x10,0x08,0x14,0xff,
+ 0xe1,0x83,0x9c,0x00,0x14,0xff,0xe1,0x83,0x9d,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,
+ 0x9e,0x00,0x14,0xff,0xe1,0x83,0x9f,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x14,0xff,0xe1,0x83,0xa0,0x00,0x14,0xff,0xe1,0x83,0xa1,0x00,0x10,0x08,
+ 0x14,0xff,0xe1,0x83,0xa2,0x00,0x14,0xff,0xe1,0x83,0xa3,0x00,0xd1,0x10,0x10,0x08,
+ 0x14,0xff,0xe1,0x83,0xa4,0x00,0x14,0xff,0xe1,0x83,0xa5,0x00,0x10,0x08,0x14,0xff,
+ 0xe1,0x83,0xa6,0x00,0x14,0xff,0xe1,0x83,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x14,0xff,0xe1,0x83,0xa8,0x00,0x14,0xff,0xe1,0x83,0xa9,0x00,0x10,0x08,0x14,0xff,
+ 0xe1,0x83,0xaa,0x00,0x14,0xff,0xe1,0x83,0xab,0x00,0xd1,0x10,0x10,0x08,0x14,0xff,
+ 0xe1,0x83,0xac,0x00,0x14,0xff,0xe1,0x83,0xad,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,
+ 0xae,0x00,0x14,0xff,0xe1,0x83,0xaf,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x14,0xff,0xe1,0x83,0xb0,0x00,0x14,0xff,0xe1,0x83,0xb1,0x00,0x10,0x08,0x14,0xff,
+ 0xe1,0x83,0xb2,0x00,0x14,0xff,0xe1,0x83,0xb3,0x00,0xd1,0x10,0x10,0x08,0x14,0xff,
+ 0xe1,0x83,0xb4,0x00,0x14,0xff,0xe1,0x83,0xb5,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,
+ 0xb6,0x00,0x14,0xff,0xe1,0x83,0xb7,0x00,0xd2,0x1c,0xd1,0x10,0x10,0x08,0x14,0xff,
+ 0xe1,0x83,0xb8,0x00,0x14,0xff,0xe1,0x83,0xb9,0x00,0x10,0x08,0x14,0xff,0xe1,0x83,
+ 0xba,0x00,0x00,0x00,0xd1,0x0c,0x10,0x04,0x00,0x00,0x14,0xff,0xe1,0x83,0xbd,0x00,
+ 0x10,0x08,0x14,0xff,0xe1,0x83,0xbe,0x00,0x14,0xff,0xe1,0x83,0xbf,0x00,0xe2,0x9d,
+ 0x08,0xe1,0x48,0x04,0xe0,0x1c,0x02,0xcf,0x86,0xe5,0x11,0x01,0xd4,0x84,0xd3,0x40,
+ 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0xa5,0x00,0x01,0xff,0x61,0xcc,
+ 0xa5,0x00,0x10,0x08,0x01,0xff,0x62,0xcc,0x87,0x00,0x01,0xff,0x62,0xcc,0x87,0x00,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0x62,0xcc,0xa3,0x00,0x01,0xff,0x62,0xcc,0xa3,0x00,
+ 0x10,0x08,0x01,0xff,0x62,0xcc,0xb1,0x00,0x01,0xff,0x62,0xcc,0xb1,0x00,0xd2,0x24,
+ 0xd1,0x14,0x10,0x0a,0x01,0xff,0x63,0xcc,0xa7,0xcc,0x81,0x00,0x01,0xff,0x63,0xcc,
+ 0xa7,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0x87,0x00,0x01,0xff,0x64,0xcc,
+ 0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x64,0xcc,0xa3,0x00,0x01,0xff,0x64,0xcc,
+ 0xa3,0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0xb1,0x00,0x01,0xff,0x64,0xcc,0xb1,0x00,
+ 0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x64,0xcc,0xa7,0x00,0x01,0xff,
+ 0x64,0xcc,0xa7,0x00,0x10,0x08,0x01,0xff,0x64,0xcc,0xad,0x00,0x01,0xff,0x64,0xcc,
+ 0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x65,0xcc,0x84,0xcc,0x80,0x00,0x01,0xff,
+ 0x65,0xcc,0x84,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x65,0xcc,0x84,0xcc,0x81,0x00,
+ 0x01,0xff,0x65,0xcc,0x84,0xcc,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0x65,0xcc,0xad,0x00,0x01,0xff,0x65,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,
+ 0xb0,0x00,0x01,0xff,0x65,0xcc,0xb0,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x65,0xcc,
+ 0xa7,0xcc,0x86,0x00,0x01,0xff,0x65,0xcc,0xa7,0xcc,0x86,0x00,0x10,0x08,0x01,0xff,
+ 0x66,0xcc,0x87,0x00,0x01,0xff,0x66,0xcc,0x87,0x00,0xd4,0x84,0xd3,0x40,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0x67,0xcc,0x84,0x00,0x01,0xff,0x67,0xcc,0x84,0x00,
+ 0x10,0x08,0x01,0xff,0x68,0xcc,0x87,0x00,0x01,0xff,0x68,0xcc,0x87,0x00,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0x68,0xcc,0xa3,0x00,0x01,0xff,0x68,0xcc,0xa3,0x00,0x10,0x08,
+ 0x01,0xff,0x68,0xcc,0x88,0x00,0x01,0xff,0x68,0xcc,0x88,0x00,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0x68,0xcc,0xa7,0x00,0x01,0xff,0x68,0xcc,0xa7,0x00,0x10,0x08,
+ 0x01,0xff,0x68,0xcc,0xae,0x00,0x01,0xff,0x68,0xcc,0xae,0x00,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0x69,0xcc,0xb0,0x00,0x01,0xff,0x69,0xcc,0xb0,0x00,0x10,0x0a,0x01,0xff,
+ 0x69,0xcc,0x88,0xcc,0x81,0x00,0x01,0xff,0x69,0xcc,0x88,0xcc,0x81,0x00,0xd3,0x40,
+ 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x6b,0xcc,0x81,0x00,0x01,0xff,0x6b,0xcc,
+ 0x81,0x00,0x10,0x08,0x01,0xff,0x6b,0xcc,0xa3,0x00,0x01,0xff,0x6b,0xcc,0xa3,0x00,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0x6b,0xcc,0xb1,0x00,0x01,0xff,0x6b,0xcc,0xb1,0x00,
+ 0x10,0x08,0x01,0xff,0x6c,0xcc,0xa3,0x00,0x01,0xff,0x6c,0xcc,0xa3,0x00,0xd2,0x24,
+ 0xd1,0x14,0x10,0x0a,0x01,0xff,0x6c,0xcc,0xa3,0xcc,0x84,0x00,0x01,0xff,0x6c,0xcc,
+ 0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x6c,0xcc,0xb1,0x00,0x01,0xff,0x6c,0xcc,
+ 0xb1,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6c,0xcc,0xad,0x00,0x01,0xff,0x6c,0xcc,
+ 0xad,0x00,0x10,0x08,0x01,0xff,0x6d,0xcc,0x81,0x00,0x01,0xff,0x6d,0xcc,0x81,0x00,
+ 0xcf,0x86,0xe5,0x15,0x01,0xd4,0x88,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x6d,0xcc,0x87,0x00,0x01,0xff,0x6d,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x6d,
+ 0xcc,0xa3,0x00,0x01,0xff,0x6d,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e,
+ 0xcc,0x87,0x00,0x01,0xff,0x6e,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x6e,0xcc,0xa3,
+ 0x00,0x01,0xff,0x6e,0xcc,0xa3,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x6e,
+ 0xcc,0xb1,0x00,0x01,0xff,0x6e,0xcc,0xb1,0x00,0x10,0x08,0x01,0xff,0x6e,0xcc,0xad,
+ 0x00,0x01,0xff,0x6e,0xcc,0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x83,
+ 0xcc,0x81,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x6f,
+ 0xcc,0x83,0xcc,0x88,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x88,0x00,0xd3,0x48,0xd2,
+ 0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x84,0xcc,0x80,0x00,0x01,0xff,0x6f,
+ 0xcc,0x84,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x84,0xcc,0x81,0x00,0x01,
+ 0xff,0x6f,0xcc,0x84,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x70,0xcc,0x81,
+ 0x00,0x01,0xff,0x70,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x70,0xcc,0x87,0x00,0x01,
+ 0xff,0x70,0xcc,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x72,0xcc,0x87,
+ 0x00,0x01,0xff,0x72,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x72,0xcc,0xa3,0x00,0x01,
+ 0xff,0x72,0xcc,0xa3,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x72,0xcc,0xa3,0xcc,0x84,
+ 0x00,0x01,0xff,0x72,0xcc,0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x72,0xcc,0xb1,
+ 0x00,0x01,0xff,0x72,0xcc,0xb1,0x00,0xd4,0x8c,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x73,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x87,0x00,0x10,0x08,0x01,
+ 0xff,0x73,0xcc,0xa3,0x00,0x01,0xff,0x73,0xcc,0xa3,0x00,0xd1,0x14,0x10,0x0a,0x01,
+ 0xff,0x73,0xcc,0x81,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x81,0xcc,0x87,0x00,0x10,
+ 0x0a,0x01,0xff,0x73,0xcc,0x8c,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x8c,0xcc,0x87,
+ 0x00,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x73,0xcc,0xa3,0xcc,0x87,0x00,0x01,
+ 0xff,0x73,0xcc,0xa3,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x74,0xcc,0x87,0x00,0x01,
+ 0xff,0x74,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x74,0xcc,0xa3,0x00,0x01,
+ 0xff,0x74,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x74,0xcc,0xb1,0x00,0x01,0xff,0x74,
+ 0xcc,0xb1,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x74,0xcc,0xad,
+ 0x00,0x01,0xff,0x74,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0xa4,0x00,0x01,
+ 0xff,0x75,0xcc,0xa4,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0xb0,0x00,0x01,
+ 0xff,0x75,0xcc,0xb0,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0xad,0x00,0x01,0xff,0x75,
+ 0xcc,0xad,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x83,0xcc,0x81,
+ 0x00,0x01,0xff,0x75,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x84,
+ 0xcc,0x88,0x00,0x01,0xff,0x75,0xcc,0x84,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x76,0xcc,0x83,0x00,0x01,0xff,0x76,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x76,
+ 0xcc,0xa3,0x00,0x01,0xff,0x76,0xcc,0xa3,0x00,0xe0,0x11,0x02,0xcf,0x86,0xd5,0xe2,
+ 0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x80,0x00,
+ 0x01,0xff,0x77,0xcc,0x80,0x00,0x10,0x08,0x01,0xff,0x77,0xcc,0x81,0x00,0x01,0xff,
+ 0x77,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x88,0x00,0x01,0xff,
+ 0x77,0xcc,0x88,0x00,0x10,0x08,0x01,0xff,0x77,0xcc,0x87,0x00,0x01,0xff,0x77,0xcc,
+ 0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0xa3,0x00,0x01,0xff,
+ 0x77,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x78,0xcc,0x87,0x00,0x01,0xff,0x78,0xcc,
+ 0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x78,0xcc,0x88,0x00,0x01,0xff,0x78,0xcc,
+ 0x88,0x00,0x10,0x08,0x01,0xff,0x79,0xcc,0x87,0x00,0x01,0xff,0x79,0xcc,0x87,0x00,
+ 0xd3,0x33,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x7a,0xcc,0x82,0x00,0x01,0xff,
+ 0x7a,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0xa3,0x00,0x01,0xff,0x7a,0xcc,
+ 0xa3,0x00,0xe1,0x12,0x59,0x10,0x08,0x01,0xff,0x7a,0xcc,0xb1,0x00,0x01,0xff,0x7a,
+ 0xcc,0xb1,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x8a,0x00,0x01,
+ 0xff,0x79,0xcc,0x8a,0x00,0x10,0x08,0x01,0xff,0x61,0xca,0xbe,0x00,0x02,0xff,0x73,
+ 0xcc,0x87,0x00,0x51,0x04,0x0a,0x00,0x10,0x07,0x0a,0xff,0x73,0x73,0x00,0x0a,0x00,
+ 0xd4,0x98,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x61,0xcc,0xa3,0x00,
+ 0x01,0xff,0x61,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x61,0xcc,0x89,0x00,0x01,0xff,
+ 0x61,0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0x82,0xcc,0x81,0x00,
+ 0x01,0xff,0x61,0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0x82,0xcc,
0x80,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x80,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,
- 0x01,0xff,0x41,0xcc,0x82,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x89,0x00,
- 0x10,0x0a,0x01,0xff,0x41,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,
- 0x83,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,
- 0x61,0xcc,0xa3,0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x81,0x00,
+ 0x01,0xff,0x61,0xcc,0x82,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x89,0x00,
+ 0x10,0x0a,0x01,0xff,0x61,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,
+ 0x83,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,
+ 0x61,0xcc,0xa3,0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0x86,0xcc,0x81,0x00,
0x01,0xff,0x61,0xcc,0x86,0xcc,0x81,0x00,0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,
- 0x01,0xff,0x41,0xcc,0x86,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,0x80,0x00,
- 0x10,0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,
- 0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x83,0x00,0x01,0xff,
- 0x61,0xcc,0x86,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0xa3,0xcc,0x86,0x00,
+ 0x01,0xff,0x61,0xcc,0x86,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,0x80,0x00,
+ 0x10,0x0a,0x01,0xff,0x61,0xcc,0x86,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,
+ 0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x61,0xcc,0x86,0xcc,0x83,0x00,0x01,0xff,
+ 0x61,0xcc,0x86,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x61,0xcc,0xa3,0xcc,0x86,0x00,
0x01,0xff,0x61,0xcc,0xa3,0xcc,0x86,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0x45,0xcc,0xa3,0x00,0x01,0xff,0x65,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x45,0xcc,
- 0x89,0x00,0x01,0xff,0x65,0xcc,0x89,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,
- 0x83,0x00,0x01,0xff,0x65,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x45,0xcc,0x82,0xcc,
+ 0x65,0xcc,0xa3,0x00,0x01,0xff,0x65,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,
+ 0x89,0x00,0x01,0xff,0x65,0xcc,0x89,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,
+ 0x83,0x00,0x01,0xff,0x65,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x65,0xcc,0x82,0xcc,
0x81,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x81,0x00,0xcf,0x86,0xe5,0x31,0x01,0xd4,
- 0x90,0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x45,0xcc,0x82,0xcc,0x80,
- 0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x45,0xcc,0x82,
+ 0x90,0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x65,0xcc,0x82,0xcc,0x80,
+ 0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x65,0xcc,0x82,
0xcc,0x89,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,
- 0xff,0x45,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x83,0x00,0x10,
- 0x0a,0x01,0xff,0x45,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x65,0xcc,0xa3,0xcc,0x82,
- 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x89,0x00,0x01,0xff,0x69,
- 0xcc,0x89,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0xa3,0x00,0x01,0xff,0x69,0xcc,0xa3,
- 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0xa3,0x00,0x01,0xff,0x6f,0xcc,0xa3,
- 0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x89,0x00,0xd3,
- 0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x82,0xcc,0x81,0x00,0x01,
- 0xff,0x6f,0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x82,0xcc,0x80,
- 0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x80,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,
+ 0xff,0x65,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x83,0x00,0x10,
+ 0x0a,0x01,0xff,0x65,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x65,0xcc,0xa3,0xcc,0x82,
+ 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x89,0x00,0x01,0xff,0x69,
+ 0xcc,0x89,0x00,0x10,0x08,0x01,0xff,0x69,0xcc,0xa3,0x00,0x01,0xff,0x69,0xcc,0xa3,
+ 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0xa3,0x00,0x01,0xff,0x6f,0xcc,0xa3,
+ 0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x89,0x00,0xd3,
+ 0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x81,0x00,0x01,
+ 0xff,0x6f,0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x80,
+ 0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x80,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,
0xcc,0x82,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x89,0x00,0x10,0x0a,0x01,
- 0xff,0x4f,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x83,0x00,0xd2,
- 0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x6f,
- 0xcc,0xa3,0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x9b,0xcc,0x81,0x00,0x01,
- 0xff,0x6f,0xcc,0x9b,0xcc,0x81,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x9b,
- 0xcc,0x80,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x4f,
+ 0xff,0x6f,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x83,0x00,0xd2,
+ 0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x6f,
+ 0xcc,0xa3,0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x81,0x00,0x01,
+ 0xff,0x6f,0xcc,0x9b,0xcc,0x81,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,
+ 0xcc,0x80,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x6f,
0xcc,0x9b,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x89,0x00,0xd4,0x98,0xd3,
- 0x48,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x9b,0xcc,0x83,0x00,0x01,
- 0xff,0x6f,0xcc,0x9b,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x9b,0xcc,0xa3,
- 0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,
- 0xcc,0xa3,0x00,0x01,0xff,0x75,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0x89,
- 0x00,0x01,0xff,0x75,0xcc,0x89,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x55,
+ 0x48,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x83,0x00,0x01,
+ 0xff,0x6f,0xcc,0x9b,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0xa3,
+ 0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,
+ 0xcc,0xa3,0x00,0x01,0xff,0x75,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x89,
+ 0x00,0x01,0xff,0x75,0xcc,0x89,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,
0xcc,0x9b,0xcc,0x81,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x81,0x00,0x10,0x0a,0x01,
- 0xff,0x55,0xcc,0x9b,0xcc,0x80,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x80,0x00,0xd1,
- 0x14,0x10,0x0a,0x01,0xff,0x55,0xcc,0x9b,0xcc,0x89,0x00,0x01,0xff,0x75,0xcc,0x9b,
- 0xcc,0x89,0x00,0x10,0x0a,0x01,0xff,0x55,0xcc,0x9b,0xcc,0x83,0x00,0x01,0xff,0x75,
- 0xcc,0x9b,0xcc,0x83,0x00,0xd3,0x44,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x55,
+ 0xff,0x75,0xcc,0x9b,0xcc,0x80,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x80,0x00,0xd1,
+ 0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x89,0x00,0x01,0xff,0x75,0xcc,0x9b,
+ 0xcc,0x89,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x83,0x00,0x01,0xff,0x75,
+ 0xcc,0x9b,0xcc,0x83,0x00,0xd3,0x44,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,
0xcc,0x9b,0xcc,0xa3,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0xa3,0x00,0x10,0x08,0x01,
- 0xff,0x59,0xcc,0x80,0x00,0x01,0xff,0x79,0xcc,0x80,0x00,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0x59,0xcc,0xa3,0x00,0x01,0xff,0x79,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x59,
- 0xcc,0x89,0x00,0x01,0xff,0x79,0xcc,0x89,0x00,0x92,0x14,0x91,0x10,0x10,0x08,0x01,
- 0xff,0x59,0xcc,0x83,0x00,0x01,0xff,0x79,0xcc,0x83,0x00,0x0a,0x00,0x0a,0x00,0xe1,
- 0xc0,0x04,0xe0,0x80,0x02,0xcf,0x86,0xe5,0x2d,0x01,0xd4,0xa8,0xd3,0x54,0xd2,0x28,
- 0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x93,0x00,0x01,0xff,0xce,0xb1,0xcc,
- 0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,
- 0xb1,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,
- 0xcc,0x81,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,
- 0xce,0xb1,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82,0x00,
- 0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x91,0xcc,0x93,0x00,0x01,0xff,0xce,
- 0x91,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0x91,0xcc,0x93,0xcc,0x80,0x00,0x01,
- 0xff,0xce,0x91,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0x91,
- 0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,
- 0x01,0xff,0xce,0x91,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,0xcd,
- 0x82,0x00,0xd3,0x42,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc,0x93,
- 0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb5,0xcc,0x93,
- 0xcc,0x80,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0xcc,0x80,0x00,0x91,0x16,0x10,0x0b,
- 0x01,0xff,0xce,0xb5,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0xcc,
- 0x81,0x00,0x00,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x95,0xcc,0x93,
- 0x00,0x01,0xff,0xce,0x95,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0x95,0xcc,0x93,
- 0xcc,0x80,0x00,0x01,0xff,0xce,0x95,0xcc,0x94,0xcc,0x80,0x00,0x91,0x16,0x10,0x0b,
- 0x01,0xff,0xce,0x95,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0x95,0xcc,0x94,0xcc,
- 0x81,0x00,0x00,0x00,0xd4,0xa8,0xd3,0x54,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,
- 0xce,0xb7,0xcc,0x93,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,
- 0xce,0xb7,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0x00,
- 0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,
- 0xb7,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x82,
- 0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x82,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,
- 0x01,0xff,0xce,0x97,0xcc,0x93,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0x00,0x10,0x0b,
- 0x01,0xff,0xce,0x97,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcc,
- 0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0x97,0xcc,0x93,0xcc,0x81,0x00,0x01,
- 0xff,0xce,0x97,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce,0x97,0xcc,0x93,
- 0xcd,0x82,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcd,0x82,0x00,0xd3,0x54,0xd2,0x28,
- 0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x93,0x00,0x01,0xff,0xce,0xb9,0xcc,
- 0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,
- 0xb9,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x93,
- 0xcc,0x81,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,
- 0xce,0xb9,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcd,0x82,0x00,
- 0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x99,0xcc,0x93,0x00,0x01,0xff,0xce,
- 0x99,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0x99,0xcc,0x93,0xcc,0x80,0x00,0x01,
- 0xff,0xce,0x99,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0x99,
- 0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0x99,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,
- 0x01,0xff,0xce,0x99,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0x99,0xcc,0x94,0xcd,
- 0x82,0x00,0xcf,0x86,0xe5,0x13,0x01,0xd4,0x84,0xd3,0x42,0xd2,0x28,0xd1,0x12,0x10,
- 0x09,0x01,0xff,0xce,0xbf,0xcc,0x93,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0x00,0x10,
- 0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,
- 0xcc,0x80,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,0x81,0x00,
- 0x01,0xff,0xce,0xbf,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd2,0x28,0xd1,0x12,0x10,
- 0x09,0x01,0xff,0xce,0x9f,0xcc,0x93,0x00,0x01,0xff,0xce,0x9f,0xcc,0x94,0x00,0x10,
- 0x0b,0x01,0xff,0xce,0x9f,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0x9f,0xcc,0x94,
- 0xcc,0x80,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0x9f,0xcc,0x93,0xcc,0x81,0x00,
- 0x01,0xff,0xce,0x9f,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd3,0x54,0xd2,0x28,0xd1,
- 0x12,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x93,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,
- 0x00,0x10,0x0b,0x01,0xff,0xcf,0x85,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xcf,0x85,
- 0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x85,0xcc,0x93,0xcc,
- 0x81,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xcf,
- 0x85,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcd,0x82,0x00,0xd2,
- 0x1c,0xd1,0x0d,0x10,0x04,0x00,0x00,0x01,0xff,0xce,0xa5,0xcc,0x94,0x00,0x10,0x04,
- 0x00,0x00,0x01,0xff,0xce,0xa5,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x0f,0x10,0x04,0x00,
- 0x00,0x01,0xff,0xce,0xa5,0xcc,0x94,0xcc,0x81,0x00,0x10,0x04,0x00,0x00,0x01,0xff,
- 0xce,0xa5,0xcc,0x94,0xcd,0x82,0x00,0xd4,0xa8,0xd3,0x54,0xd2,0x28,0xd1,0x12,0x10,
- 0x09,0x01,0xff,0xcf,0x89,0xcc,0x93,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0x00,0x10,
- 0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,
- 0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x81,0x00,
- 0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,
- 0x93,0xcd,0x82,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,0x82,0x00,0xd2,0x28,0xd1,
- 0x12,0x10,0x09,0x01,0xff,0xce,0xa9,0xcc,0x93,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,
- 0x00,0x10,0x0b,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xa9,
- 0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcc,
- 0x81,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce,
- 0xa9,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcd,0x82,0x00,0xd3,
- 0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x80,0x00,0x01,0xff,
- 0xce,0xb1,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc,0x80,0x00,0x01,0xff,
- 0xce,0xb5,0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x80,0x00,
- 0x01,0xff,0xce,0xb7,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x80,0x00,
- 0x01,0xff,0xce,0xb9,0xcc,0x81,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,
- 0xbf,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xcf,
- 0x85,0xcc,0x80,0x00,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0x91,0x12,0x10,0x09,0x01,
- 0xff,0xcf,0x89,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc,0x81,0x00,0x00,0x00,0xe0,
- 0xe1,0x02,0xcf,0x86,0xe5,0x91,0x01,0xd4,0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,
- 0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,
- 0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0xcd,0x85,0x00,
- 0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d,0x01,
- 0xff,0xce,0xb1,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,
- 0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0xcd,
- 0x85,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x30,0xd1,
- 0x16,0x10,0x0b,0x01,0xff,0xce,0x91,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xce,0x91,
- 0xcc,0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0x91,0xcc,0x93,0xcc,0x80,0xcd,
- 0x85,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,
- 0x0d,0x01,0xff,0xce,0x91,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xce,0x91,
- 0xcc,0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0x91,0xcc,0x93,0xcd,
- 0x82,0xcd,0x85,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,0xd3,
- 0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x85,0x00,
- 0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,
- 0x93,0xcc,0x80,0xcd,0x85,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0xcd,0x85,
- 0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,
- 0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,
- 0xb7,0xcc,0x93,0xcd,0x82,0xcd,0x85,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x82,
- 0xcd,0x85,0x00,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0x97,0xcc,0x93,0xcd,
- 0x85,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,
- 0x97,0xcc,0x93,0xcc,0x80,0xcd,0x85,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcc,0x80,
- 0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0x97,0xcc,0x93,0xcc,0x81,0xcd,
- 0x85,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,
- 0xff,0xce,0x97,0xcc,0x93,0xcd,0x82,0xcd,0x85,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,
- 0xcd,0x82,0xcd,0x85,0x00,0xd4,0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,
- 0xff,0xcf,0x89,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,0x85,
- 0x00,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x80,0xcd,0x85,0x00,0x01,0xff,
- 0xcf,0x89,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xcf,
- 0x89,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x81,
- 0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82,0xcd,0x85,0x00,
- 0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x30,0xd1,0x16,0x10,
- 0x0b,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,
- 0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcc,0x80,0xcd,0x85,0x00,
- 0x01,0xff,0xce,0xa9,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d,0x01,
- 0xff,0xce,0xa9,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,
- 0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcd,0x82,0xcd,
- 0x85,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,0xd3,0x49,0xd2,
- 0x26,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x86,0x00,0x01,0xff,0xce,0xb1,
- 0xcc,0x84,0x00,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x80,0xcd,0x85,0x00,0x01,0xff,
- 0xce,0xb1,0xcd,0x85,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x81,0xcd,
- 0x85,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xb1,0xcd,0x82,0x00,0x01,0xff,0xce,
- 0xb1,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x91,
- 0xcc,0x86,0x00,0x01,0xff,0xce,0x91,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xce,0x91,
- 0xcc,0x80,0x00,0x01,0xff,0xce,0x91,0xcc,0x81,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,
- 0xce,0x91,0xcd,0x85,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xce,0xb9,0x00,0x01,0x00,
- 0xcf,0x86,0xe5,0x16,0x01,0xd4,0x8f,0xd3,0x44,0xd2,0x21,0xd1,0x0d,0x10,0x04,0x01,
- 0x00,0x01,0xff,0xc2,0xa8,0xcd,0x82,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x80,
- 0xcd,0x85,0x00,0x01,0xff,0xce,0xb7,0xcd,0x85,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,
- 0xce,0xb7,0xcc,0x81,0xcd,0x85,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xb7,0xcd,
- 0x82,0x00,0x01,0xff,0xce,0xb7,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x24,0xd1,0x12,0x10,
- 0x09,0x01,0xff,0xce,0x95,0xcc,0x80,0x00,0x01,0xff,0xce,0x95,0xcc,0x81,0x00,0x10,
- 0x09,0x01,0xff,0xce,0x97,0xcc,0x80,0x00,0x01,0xff,0xce,0x97,0xcc,0x81,0x00,0xd1,
- 0x13,0x10,0x09,0x01,0xff,0xce,0x97,0xcd,0x85,0x00,0x01,0xff,0xe1,0xbe,0xbf,0xcc,
- 0x80,0x00,0x10,0x0a,0x01,0xff,0xe1,0xbe,0xbf,0xcc,0x81,0x00,0x01,0xff,0xe1,0xbe,
- 0xbf,0xcd,0x82,0x00,0xd3,0x40,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb9,
- 0xcc,0x86,0x00,0x01,0xff,0xce,0xb9,0xcc,0x84,0x00,0x10,0x0b,0x01,0xff,0xce,0xb9,
- 0xcc,0x88,0xcc,0x80,0x00,0x01,0xff,0xce,0xb9,0xcc,0x88,0xcc,0x81,0x00,0x51,0x04,
- 0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcd,0x82,0x00,0x01,0xff,0xce,0xb9,0xcc,
- 0x88,0xcd,0x82,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x99,0xcc,0x86,
- 0x00,0x01,0xff,0xce,0x99,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xce,0x99,0xcc,0x80,
- 0x00,0x01,0xff,0xce,0x99,0xcc,0x81,0x00,0xd1,0x0e,0x10,0x04,0x00,0x00,0x01,0xff,
- 0xe1,0xbf,0xbe,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0xe1,0xbf,0xbe,0xcc,0x81,0x00,
- 0x01,0xff,0xe1,0xbf,0xbe,0xcd,0x82,0x00,0xd4,0x93,0xd3,0x4e,0xd2,0x28,0xd1,0x12,
+ 0xff,0x79,0xcc,0x80,0x00,0x01,0xff,0x79,0xcc,0x80,0x00,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x79,0xcc,0xa3,0x00,0x01,0xff,0x79,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x79,
+ 0xcc,0x89,0x00,0x01,0xff,0x79,0xcc,0x89,0x00,0xd2,0x1c,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x79,0xcc,0x83,0x00,0x01,0xff,0x79,0xcc,0x83,0x00,0x10,0x08,0x0a,0xff,0xe1,
+ 0xbb,0xbb,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xe1,0xbb,0xbd,0x00,0x0a,
+ 0x00,0x10,0x08,0x0a,0xff,0xe1,0xbb,0xbf,0x00,0x0a,0x00,0xe1,0xbf,0x02,0xe0,0xa1,
+ 0x01,0xcf,0x86,0xd5,0xc6,0xd4,0x6c,0xd3,0x18,0xe2,0x0e,0x59,0xe1,0xf7,0x58,0x10,
+ 0x09,0x01,0xff,0xce,0xb1,0xcc,0x93,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0x00,0xd2,
+ 0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x93,0x00,0x01,0xff,0xce,0xb1,
+ 0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,
+ 0xce,0xb1,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,
+ 0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,
+ 0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82,
+ 0x00,0xd3,0x18,0xe2,0x4a,0x59,0xe1,0x33,0x59,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc,
+ 0x93,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,
+ 0xff,0xce,0xb5,0xcc,0x93,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0x00,0x10,0x0b,0x01,
+ 0xff,0xce,0xb5,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0xcc,0x80,
+ 0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0xb5,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,
+ 0xce,0xb5,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd4,0x6c,0xd3,0x18,0xe2,0x74,0x59,
+ 0xe1,0x5d,0x59,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x93,0x00,0x01,0xff,0xce,0xb7,
+ 0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x93,0x00,
+ 0x01,0xff,0xce,0xb7,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,
+ 0x80,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,
+ 0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x81,
+ 0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb7,
+ 0xcc,0x94,0xcd,0x82,0x00,0xd3,0x18,0xe2,0xb0,0x59,0xe1,0x99,0x59,0x10,0x09,0x01,
+ 0xff,0xce,0xb9,0xcc,0x93,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0x00,0xd2,0x28,0xd1,
+ 0x12,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x93,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,
+ 0x00,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb9,
+ 0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x93,0xcc,
+ 0x81,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce,
+ 0xb9,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcd,0x82,0x00,0xcf,
+ 0x86,0xd5,0xac,0xd4,0x5a,0xd3,0x18,0xe2,0xed,0x59,0xe1,0xd6,0x59,0x10,0x09,0x01,
+ 0xff,0xce,0xbf,0xcc,0x93,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0x00,0xd2,0x28,0xd1,
+ 0x12,0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x93,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,
+ 0x00,0x10,0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,
+ 0xcc,0x94,0xcc,0x80,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,
+ 0x81,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd3,0x18,0xe2,
+ 0x17,0x5a,0xe1,0x00,0x5a,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x93,0x00,0x01,0xff,
+ 0xcf,0x85,0xcc,0x94,0x00,0xd2,0x1c,0xd1,0x0d,0x10,0x04,0x00,0x00,0x01,0xff,0xcf,
+ 0x85,0xcc,0x94,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcc,0x80,
+ 0x00,0xd1,0x0f,0x10,0x04,0x00,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcc,0x81,0x00,
+ 0x10,0x04,0x00,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcd,0x82,0x00,0xe4,0xd3,0x5a,
+ 0xd3,0x18,0xe2,0x52,0x5a,0xe1,0x3b,0x5a,0x10,0x09,0x01,0xff,0xcf,0x89,0xcc,0x93,
+ 0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,
+ 0xcf,0x89,0xcc,0x93,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,
+ 0xcf,0x89,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x80,0x00,
+ 0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xcf,
+ 0x89,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82,
+ 0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,0x82,0x00,0xe0,0xd9,0x02,0xcf,0x86,0xe5,
+ 0x91,0x01,0xd4,0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb1,
+ 0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d,
+ 0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,
+ 0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,
+ 0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00,
+ 0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xce,
+ 0xb1,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,
+ 0xce,0xb1,0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xce,0xb9,0x00,
+ 0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce,
+ 0xb1,0xcc,0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0xb1,
+ 0xcc,0x93,0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0xce,
+ 0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,
+ 0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd3,0x64,0xd2,0x30,0xd1,0x16,
+ 0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,
+ 0x94,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x80,0xce,0xb9,
+ 0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,
+ 0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,
+ 0x94,0xcc,0x81,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x82,
+ 0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x30,
+ 0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xce,
+ 0xb7,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x80,
+ 0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,
+ 0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xce,
+ 0xb7,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,
+ 0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,
+ 0xd4,0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,
+ 0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d,0x01,0xff,
+ 0xcf,0x89,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,
+ 0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x81,
+ 0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00,0x10,0x0d,
+ 0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,
+ 0x94,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89,
+ 0xcc,0x93,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xce,0xb9,0x00,0x10,0x0d,
+ 0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,
+ 0x94,0xcc,0x80,0xce,0xb9,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,
+ 0xcc,0x81,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x81,0xce,0xb9,0x00,
+ 0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82,0xce,0xb9,0x00,0x01,0xff,0xcf,
+ 0x89,0xcc,0x94,0xcd,0x82,0xce,0xb9,0x00,0xd3,0x49,0xd2,0x26,0xd1,0x12,0x10,0x09,
+ 0x01,0xff,0xce,0xb1,0xcc,0x86,0x00,0x01,0xff,0xce,0xb1,0xcc,0x84,0x00,0x10,0x0b,
+ 0x01,0xff,0xce,0xb1,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce,0xb1,0xce,0xb9,0x00,
+ 0xd1,0x0f,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x81,0xce,0xb9,0x00,0x00,0x00,0x10,
+ 0x09,0x01,0xff,0xce,0xb1,0xcd,0x82,0x00,0x01,0xff,0xce,0xb1,0xcd,0x82,0xce,0xb9,
+ 0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x86,0x00,0x01,0xff,
+ 0xce,0xb1,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x80,0x00,0x01,0xff,
+ 0xce,0xb1,0xcc,0x81,0x00,0xe1,0xf3,0x5a,0x10,0x09,0x01,0xff,0xce,0xb1,0xce,0xb9,
+ 0x00,0x01,0x00,0xcf,0x86,0xd5,0xbd,0xd4,0x7e,0xd3,0x44,0xd2,0x21,0xd1,0x0d,0x10,
+ 0x04,0x01,0x00,0x01,0xff,0xc2,0xa8,0xcd,0x82,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,
+ 0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xce,0xb7,0xce,0xb9,0x00,0xd1,0x0f,0x10,0x0b,
+ 0x01,0xff,0xce,0xb7,0xcc,0x81,0xce,0xb9,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce,
+ 0xb7,0xcd,0x82,0x00,0x01,0xff,0xce,0xb7,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x24,0xd1,
+ 0x12,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc,0x80,0x00,0x01,0xff,0xce,0xb5,0xcc,0x81,
+ 0x00,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x80,0x00,0x01,0xff,0xce,0xb7,0xcc,0x81,
+ 0x00,0xe1,0x02,0x5b,0x10,0x09,0x01,0xff,0xce,0xb7,0xce,0xb9,0x00,0x01,0xff,0xe1,
+ 0xbe,0xbf,0xcc,0x80,0x00,0xd3,0x18,0xe2,0x28,0x5b,0xe1,0x11,0x5b,0x10,0x09,0x01,
+ 0xff,0xce,0xb9,0xcc,0x86,0x00,0x01,0xff,0xce,0xb9,0xcc,0x84,0x00,0xe2,0x4c,0x5b,
+ 0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x86,0x00,0x01,0xff,0xce,0xb9,0xcc,
+ 0x84,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x80,0x00,0x01,0xff,0xce,0xb9,0xcc,
+ 0x81,0x00,0xd4,0x51,0xd3,0x18,0xe2,0x6f,0x5b,0xe1,0x58,0x5b,0x10,0x09,0x01,0xff,
+ 0xcf,0x85,0xcc,0x86,0x00,0x01,0xff,0xcf,0x85,0xcc,0x84,0x00,0xd2,0x24,0xd1,0x12,
0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x86,0x00,0x01,0xff,0xcf,0x85,0xcc,0x84,0x00,
- 0x10,0x0b,0x01,0xff,0xcf,0x85,0xcc,0x88,0xcc,0x80,0x00,0x01,0xff,0xcf,0x85,0xcc,
- 0x88,0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xcf,0x81,0xcc,0x93,0x00,0x01,
- 0xff,0xcf,0x81,0xcc,0x94,0x00,0x10,0x09,0x01,0xff,0xcf,0x85,0xcd,0x82,0x00,0x01,
- 0xff,0xcf,0x85,0xcc,0x88,0xcd,0x82,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,
- 0xce,0xa5,0xcc,0x86,0x00,0x01,0xff,0xce,0xa5,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,
- 0xce,0xa5,0xcc,0x80,0x00,0x01,0xff,0xce,0xa5,0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,
- 0x01,0xff,0xce,0xa1,0xcc,0x94,0x00,0x01,0xff,0xc2,0xa8,0xcc,0x80,0x00,0x10,0x09,
- 0x01,0xff,0xc2,0xa8,0xcc,0x81,0x00,0x01,0xff,0x60,0x00,0xd3,0x3b,0xd2,0x18,0x51,
- 0x04,0x00,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x80,0xcd,0x85,0x00,0x01,0xff,
- 0xcf,0x89,0xcd,0x85,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x81,0xcd,
- 0x85,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xcf,0x89,0xcd,0x82,0x00,0x01,0xff,0xcf,
- 0x89,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x9f,
- 0xcc,0x80,0x00,0x01,0xff,0xce,0x9f,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xa9,
- 0xcc,0x80,0x00,0x01,0xff,0xce,0xa9,0xcc,0x81,0x00,0xd1,0x10,0x10,0x09,0x01,0xff,
- 0xce,0xa9,0xcd,0x85,0x00,0x01,0xff,0xc2,0xb4,0x00,0x10,0x04,0x01,0x00,0x00,0x00,
- 0xe0,0x62,0x0c,0xcf,0x86,0xe5,0x9f,0x08,0xe4,0xf8,0x05,0xe3,0xdb,0x02,0xe2,0xa1,
- 0x01,0xd1,0xb4,0xd0,0x3a,0xcf,0x86,0xd5,0x20,0x94,0x1c,0x93,0x18,0x92,0x14,0x91,
- 0x10,0x10,0x08,0x01,0xff,0xe2,0x80,0x82,0x00,0x01,0xff,0xe2,0x80,0x83,0x00,0x01,
- 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x14,0x53,0x04,0x01,0x00,0x52,0x04,0x01,
- 0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x04,0x00,0x01,0x00,0xcf,0x86,0xd5,
- 0x48,0xd4,0x1c,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,
- 0x00,0x06,0x00,0x52,0x04,0x04,0x00,0x11,0x04,0x04,0x00,0x06,0x00,0xd3,0x1c,0xd2,
- 0x0c,0x51,0x04,0x06,0x00,0x10,0x04,0x06,0x00,0x07,0x00,0xd1,0x08,0x10,0x04,0x07,
- 0x00,0x08,0x00,0x10,0x04,0x08,0x00,0x06,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,
- 0x00,0x10,0x04,0x08,0x00,0x06,0x00,0xd4,0x1c,0xd3,0x10,0x52,0x04,0x06,0x00,0x91,
- 0x08,0x10,0x04,0x0a,0x00,0x00,0x00,0x0f,0x00,0x92,0x08,0x11,0x04,0x0f,0x00,0x01,
- 0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x00,
- 0x00,0x01,0x00,0x01,0x00,0xd0,0x7e,0xcf,0x86,0xd5,0x34,0xd4,0x14,0x53,0x04,0x01,
- 0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0xd3,
- 0x10,0x52,0x04,0x08,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x0c,0x00,0x0c,0x00,0x52,
- 0x04,0x0c,0x00,0x91,0x08,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0xd4,0x1c,0x53,
- 0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x02,0x00,0x91,
- 0x08,0x10,0x04,0x03,0x00,0x04,0x00,0x04,0x00,0xd3,0x10,0xd2,0x08,0x11,0x04,0x06,
- 0x00,0x08,0x00,0x11,0x04,0x08,0x00,0x0b,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x0b,
- 0x00,0x0c,0x00,0x10,0x04,0x0e,0x00,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x11,
- 0x00,0x13,0x00,0xcf,0x86,0xd5,0x28,0x54,0x04,0x00,0x00,0xd3,0x0c,0x92,0x08,0x11,
- 0x04,0x01,0xe6,0x01,0x01,0x01,0xe6,0xd2,0x0c,0x51,0x04,0x01,0x01,0x10,0x04,0x01,
- 0x01,0x01,0xe6,0x91,0x08,0x10,0x04,0x01,0xe6,0x01,0x00,0x01,0x00,0xd4,0x30,0xd3,
- 0x1c,0xd2,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x01,0xe6,0x04,0x00,0xd1,0x08,0x10,
- 0x04,0x06,0x00,0x06,0x01,0x10,0x04,0x06,0x01,0x06,0xe6,0x92,0x10,0xd1,0x08,0x10,
- 0x04,0x06,0xdc,0x06,0xe6,0x10,0x04,0x06,0x01,0x08,0x01,0x09,0xdc,0x93,0x10,0x92,
- 0x0c,0x91,0x08,0x10,0x04,0x0a,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,
- 0x81,0xd0,0x4f,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x29,0xd3,0x13,0x52,0x04,0x01,
- 0x00,0x51,0x04,0x01,0x00,0x10,0x07,0x01,0xff,0xce,0xa9,0x00,0x01,0x00,0x92,0x12,
- 0x51,0x04,0x01,0x00,0x10,0x06,0x01,0xff,0x4b,0x00,0x01,0xff,0x41,0xcc,0x8a,0x00,
- 0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x04,0x00,
- 0x10,0x04,0x04,0x00,0x07,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x06,0x00,0x06,0x00,
- 0xcf,0x86,0x95,0x2c,0xd4,0x18,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0xd1,0x08,
- 0x10,0x04,0x08,0x00,0x09,0x00,0x10,0x04,0x09,0x00,0x0a,0x00,0x93,0x10,0x92,0x0c,
- 0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
- 0xd0,0x68,0xcf,0x86,0xd5,0x48,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,
- 0x10,0x04,0x01,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,
- 0x92,0x0c,0x91,0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x11,0x00,0x00,0x00,0x53,0x04,
- 0x01,0x00,0x92,0x18,0x51,0x04,0x01,0x00,0x10,0x0a,0x01,0xff,0xe2,0x86,0x90,0xcc,
- 0xb8,0x00,0x01,0xff,0xe2,0x86,0x92,0xcc,0xb8,0x00,0x01,0x00,0x94,0x1a,0x53,0x04,
- 0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x0a,0x01,0xff,0xe2,0x86,
- 0x94,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x2e,0x94,0x2a,0x53,0x04,
- 0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x0e,0x10,0x04,0x01,0x00,0x01,0xff,0xe2,0x87,
- 0x90,0xcc,0xb8,0x00,0x10,0x0a,0x01,0xff,0xe2,0x87,0x94,0xcc,0xb8,0x00,0x01,0xff,
- 0xe2,0x87,0x92,0xcc,0xb8,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,
- 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x04,0x00,0x04,0x00,0x93,0x08,0x12,0x04,
- 0x04,0x00,0x06,0x00,0x06,0x00,0xe2,0x38,0x02,0xe1,0x3f,0x01,0xd0,0x68,0xcf,0x86,
- 0xd5,0x3e,0x94,0x3a,0xd3,0x16,0x52,0x04,0x01,0x00,0x91,0x0e,0x10,0x0a,0x01,0xff,
- 0xe2,0x88,0x83,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0xd2,0x12,0x91,0x0e,0x10,0x04,
- 0x01,0x00,0x01,0xff,0xe2,0x88,0x88,0xcc,0xb8,0x00,0x01,0x00,0x91,0x0e,0x10,0x0a,
- 0x01,0xff,0xe2,0x88,0x8b,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x24,
- 0x93,0x20,0x52,0x04,0x01,0x00,0xd1,0x0e,0x10,0x0a,0x01,0xff,0xe2,0x88,0xa3,0xcc,
- 0xb8,0x00,0x01,0x00,0x10,0x0a,0x01,0xff,0xe2,0x88,0xa5,0xcc,0xb8,0x00,0x01,0x00,
- 0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x48,0x94,0x44,0xd3,0x2e,0xd2,0x12,0x91,0x0e,
- 0x10,0x04,0x01,0x00,0x01,0xff,0xe2,0x88,0xbc,0xcc,0xb8,0x00,0x01,0x00,0xd1,0x0e,
- 0x10,0x0a,0x01,0xff,0xe2,0x89,0x83,0xcc,0xb8,0x00,0x01,0x00,0x10,0x04,0x01,0x00,
- 0x01,0xff,0xe2,0x89,0x85,0xcc,0xb8,0x00,0x92,0x12,0x91,0x0e,0x10,0x04,0x01,0x00,
- 0x01,0xff,0xe2,0x89,0x88,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x40,
- 0xd3,0x1e,0x92,0x1a,0xd1,0x0c,0x10,0x08,0x01,0xff,0x3d,0xcc,0xb8,0x00,0x01,0x00,
- 0x10,0x0a,0x01,0xff,0xe2,0x89,0xa1,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x52,0x04,
- 0x01,0x00,0xd1,0x0e,0x10,0x04,0x01,0x00,0x01,0xff,0xe2,0x89,0x8d,0xcc,0xb8,0x00,
- 0x10,0x08,0x01,0xff,0x3c,0xcc,0xb8,0x00,0x01,0xff,0x3e,0xcc,0xb8,0x00,0xd3,0x30,
- 0xd2,0x18,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xa4,0xcc,0xb8,0x00,0x01,0xff,
- 0xe2,0x89,0xa5,0xcc,0xb8,0x00,0x01,0x00,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,
- 0xb2,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x89,0xb3,0xcc,0xb8,0x00,0x01,0x00,0x92,0x18,
- 0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xb6,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x89,
- 0xb7,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0xd0,0x86,0xcf,0x86,0xd5,0x50,0x94,0x4c,
- 0xd3,0x30,0xd2,0x18,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xba,0xcc,0xb8,0x00,
- 0x01,0xff,0xe2,0x89,0xbb,0xcc,0xb8,0x00,0x01,0x00,0x91,0x14,0x10,0x0a,0x01,0xff,
- 0xe2,0x8a,0x82,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0x83,0xcc,0xb8,0x00,0x01,0x00,
- 0x92,0x18,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x8a,0x86,0xcc,0xb8,0x00,0x01,0xff,
- 0xe2,0x8a,0x87,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x30,0x53,0x04,
- 0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0xe2,0x8a,0xa2,0xcc,
- 0xb8,0x00,0x01,0xff,0xe2,0x8a,0xa8,0xcc,0xb8,0x00,0x10,0x0a,0x01,0xff,0xe2,0x8a,
- 0xa9,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0xab,0xcc,0xb8,0x00,0x01,0x00,0xcf,0x86,
- 0x55,0x04,0x01,0x00,0xd4,0x5c,0xd3,0x2c,0x92,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,
- 0xe2,0x89,0xbc,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x89,0xbd,0xcc,0xb8,0x00,0x10,0x0a,
- 0x01,0xff,0xe2,0x8a,0x91,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0x92,0xcc,0xb8,0x00,
- 0x01,0x00,0xd2,0x18,0x51,0x04,0x01,0x00,0x10,0x0a,0x01,0xff,0xe2,0x8a,0xb2,0xcc,
- 0xb8,0x00,0x01,0xff,0xe2,0x8a,0xb3,0xcc,0xb8,0x00,0x91,0x14,0x10,0x0a,0x01,0xff,
- 0xe2,0x8a,0xb4,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0xb5,0xcc,0xb8,0x00,0x01,0x00,
- 0x93,0x0c,0x92,0x08,0x11,0x04,0x01,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0xd1,0x64,
- 0xd0,0x3e,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,
- 0x01,0x00,0x04,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x20,0x53,0x04,
- 0x01,0x00,0x92,0x18,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x80,0x88,0x00,
- 0x10,0x08,0x01,0xff,0xe3,0x80,0x89,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,
- 0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,
- 0x01,0x00,0x10,0x04,0x01,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x06,0x00,0x04,0x00,
- 0x04,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00,
- 0x92,0x0c,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x06,0x00,0x06,0x00,0x06,0x00,
- 0xcf,0x86,0xd5,0x2c,0xd4,0x14,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x51,0x04,
- 0x06,0x00,0x10,0x04,0x06,0x00,0x07,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,
- 0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x12,0x04,0x08,0x00,0x09,0x00,0xd4,0x14,
- 0x53,0x04,0x09,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x0c,0x00,0x0c,0x00,
- 0x0c,0x00,0xd3,0x08,0x12,0x04,0x0c,0x00,0x10,0x00,0xd2,0x0c,0x51,0x04,0x10,0x00,
- 0x10,0x04,0x10,0x00,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x13,0x00,
- 0xd3,0xa6,0xd2,0x74,0xd1,0x40,0xd0,0x22,0xcf,0x86,0x55,0x04,0x01,0x00,0x94,0x18,
- 0x93,0x14,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x10,0x04,
- 0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,0x53,0x04,
- 0x01,0x00,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x01,0x00,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,
- 0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,
- 0x06,0x00,0x06,0x00,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x51,0x04,0x06,0x00,
- 0x10,0x04,0x06,0x00,0x07,0x00,0xd1,0x06,0xcf,0x06,0x01,0x00,0xd0,0x1a,0xcf,0x86,
- 0x95,0x14,0x54,0x04,0x01,0x00,0x93,0x0c,0x52,0x04,0x01,0x00,0x11,0x04,0x01,0x00,
- 0x06,0x00,0x06,0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,
- 0x13,0x04,0x04,0x00,0x06,0x00,0xd2,0xdc,0xd1,0x48,0xd0,0x26,0xcf,0x86,0x95,0x20,
- 0x54,0x04,0x01,0x00,0xd3,0x0c,0x52,0x04,0x01,0x00,0x11,0x04,0x07,0x00,0x06,0x00,
- 0x92,0x0c,0x91,0x08,0x10,0x04,0x08,0x00,0x04,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
- 0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,
- 0x04,0x00,0x06,0x00,0x06,0x00,0x52,0x04,0x06,0x00,0x11,0x04,0x06,0x00,0x08,0x00,
- 0xd0,0x5e,0xcf,0x86,0xd5,0x2c,0xd4,0x10,0x53,0x04,0x06,0x00,0x92,0x08,0x11,0x04,
- 0x06,0x00,0x07,0x00,0x07,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x07,0x00,0x08,0x00,
- 0x08,0x00,0x52,0x04,0x08,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x0a,0x00,0x0b,0x00,
- 0xd4,0x10,0x93,0x0c,0x92,0x08,0x11,0x04,0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,
- 0xd3,0x10,0x92,0x0c,0x51,0x04,0x08,0x00,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,
- 0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x0b,0x00,0xcf,0x86,
- 0xd5,0x1c,0x94,0x18,0xd3,0x08,0x12,0x04,0x0a,0x00,0x0b,0x00,0x52,0x04,0x0b,0x00,
- 0x51,0x04,0x0b,0x00,0x10,0x04,0x0c,0x00,0x0b,0x00,0x0b,0x00,0x94,0x14,0x93,0x10,
- 0x92,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04,0x0c,0x00,0x0b,0x00,0x0c,0x00,0x0b,0x00,
- 0x0b,0x00,0xd1,0xa8,0xd0,0x42,0xcf,0x86,0xd5,0x28,0x94,0x24,0xd3,0x18,0xd2,0x0c,
- 0x91,0x08,0x10,0x04,0x10,0x00,0x01,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,
- 0x0c,0x00,0x01,0x00,0x92,0x08,0x11,0x04,0x01,0x00,0x0c,0x00,0x01,0x00,0x01,0x00,
- 0x94,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x01,0x00,
- 0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x40,0xd4,0x18,0x53,0x04,0x01,0x00,
- 0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x0c,0x00,0x01,0x00,0x10,0x04,0x0c,0x00,
- 0x01,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x0c,0x00,
- 0x51,0x04,0x0c,0x00,0x10,0x04,0x01,0x00,0x0b,0x00,0x52,0x04,0x01,0x00,0x51,0x04,
- 0x01,0x00,0x10,0x04,0x01,0x00,0x0c,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,
- 0x10,0x04,0x0c,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x06,0x00,0x93,0x0c,0x52,0x04,
- 0x06,0x00,0x11,0x04,0x06,0x00,0x01,0x00,0x01,0x00,0xd0,0x3e,0xcf,0x86,0xd5,0x18,
- 0x54,0x04,0x01,0x00,0x93,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,
- 0x0c,0x00,0x0c,0x00,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,
- 0x10,0x04,0x0c,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,
- 0x01,0x00,0x10,0x04,0x01,0x00,0x0c,0x00,0xcf,0x86,0xd5,0x2c,0x94,0x28,0xd3,0x10,
- 0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x09,0x00,0xd2,0x0c,
- 0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x0d,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,
- 0x0d,0x00,0x0c,0x00,0x06,0x00,0x94,0x0c,0x53,0x04,0x06,0x00,0x12,0x04,0x06,0x00,
- 0x0a,0x00,0x06,0x00,0xe4,0x39,0x01,0xd3,0x0c,0xd2,0x06,0xcf,0x06,0x04,0x00,0xcf,
- 0x06,0x06,0x00,0xd2,0x30,0xd1,0x06,0xcf,0x06,0x06,0x00,0xd0,0x06,0xcf,0x06,0x06,
- 0x00,0xcf,0x86,0x95,0x1e,0x54,0x04,0x06,0x00,0x53,0x04,0x06,0x00,0x52,0x04,0x06,
- 0x00,0x91,0x0e,0x10,0x0a,0x06,0xff,0xe2,0xab,0x9d,0xcc,0xb8,0x00,0x06,0x00,0x06,
- 0x00,0x06,0x00,0xd1,0x80,0xd0,0x3a,0xcf,0x86,0xd5,0x28,0xd4,0x10,0x53,0x04,0x07,
- 0x00,0x52,0x04,0x07,0x00,0x11,0x04,0x07,0x00,0x08,0x00,0xd3,0x08,0x12,0x04,0x08,
- 0x00,0x09,0x00,0x92,0x0c,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,
- 0x00,0x94,0x0c,0x93,0x08,0x12,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0xcf,
- 0x86,0xd5,0x30,0xd4,0x14,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,
- 0x04,0x0a,0x00,0x10,0x00,0x10,0x00,0xd3,0x10,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,
- 0x04,0x0a,0x00,0x0b,0x00,0x0b,0x00,0x92,0x08,0x11,0x04,0x0b,0x00,0x10,0x00,0x10,
- 0x00,0x54,0x04,0x10,0x00,0x93,0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x00,0x00,0x10,
- 0x00,0x10,0x00,0xd0,0x32,0xcf,0x86,0xd5,0x14,0x54,0x04,0x10,0x00,0x93,0x0c,0x52,
- 0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x00,0x00,0x10,0x00,0x54,0x04,0x10,0x00,0x53,
- 0x04,0x10,0x00,0xd2,0x08,0x11,0x04,0x10,0x00,0x14,0x00,0x91,0x08,0x10,0x04,0x14,
- 0x00,0x10,0x00,0x10,0x00,0xcf,0x86,0xd5,0x28,0xd4,0x14,0x53,0x04,0x10,0x00,0x92,
- 0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x15,0x00,0x10,0x00,0x10,0x00,0x93,0x10,0x92,
- 0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x13,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0xd4,
- 0x0c,0x53,0x04,0x14,0x00,0x12,0x04,0x14,0x00,0x11,0x00,0x53,0x04,0x14,0x00,0x52,
- 0x04,0x14,0x00,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x15,0x00,0xe3,0xb9,0x01,
- 0xd2,0xac,0xd1,0x68,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x08,0x00,0x94,0x14,0x53,0x04,
- 0x08,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,
- 0x08,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x08,0x00,0x53,0x04,0x08,0x00,0x52,0x04,
- 0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,0xd4,0x14,0x53,0x04,
- 0x09,0x00,0x52,0x04,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,
- 0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x0a,0x00,0x0a,0x00,0x09,0x00,
- 0x52,0x04,0x0a,0x00,0x11,0x04,0x0a,0x00,0x0b,0x00,0xd0,0x06,0xcf,0x06,0x08,0x00,
- 0xcf,0x86,0x55,0x04,0x08,0x00,0xd4,0x1c,0x53,0x04,0x08,0x00,0xd2,0x0c,0x51,0x04,
- 0x08,0x00,0x10,0x04,0x08,0x00,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,
- 0x0b,0xe6,0xd3,0x0c,0x92,0x08,0x11,0x04,0x0b,0xe6,0x0d,0x00,0x00,0x00,0x92,0x0c,
- 0x91,0x08,0x10,0x04,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xd1,0x6c,0xd0,0x2a,
- 0xcf,0x86,0x55,0x04,0x08,0x00,0x94,0x20,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,
- 0x08,0x00,0x10,0x04,0x00,0x00,0x0d,0x00,0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,
- 0x00,0x00,0x0d,0x00,0x00,0x00,0x08,0x00,0xcf,0x86,0x55,0x04,0x08,0x00,0xd4,0x1c,
- 0xd3,0x0c,0x52,0x04,0x08,0x00,0x11,0x04,0x08,0x00,0x0d,0x00,0x52,0x04,0x00,0x00,
- 0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x08,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,
- 0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,
- 0x00,0x00,0x10,0x04,0x00,0x00,0x0c,0x09,0xd0,0x5a,0xcf,0x86,0xd5,0x18,0x54,0x04,
- 0x08,0x00,0x93,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,
- 0x00,0x00,0x00,0x00,0xd4,0x20,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,
- 0x10,0x04,0x08,0x00,0x00,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,
- 0x08,0x00,0x00,0x00,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,
- 0x08,0x00,0x00,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,
- 0x00,0x00,0xcf,0x86,0x95,0x40,0xd4,0x20,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,
- 0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,
- 0x10,0x04,0x08,0x00,0x00,0x00,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,
- 0x10,0x04,0x08,0x00,0x00,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,
- 0x08,0x00,0x00,0x00,0x0a,0xe6,0xd2,0x9c,0xd1,0x68,0xd0,0x32,0xcf,0x86,0xd5,0x14,
- 0x54,0x04,0x08,0x00,0x53,0x04,0x08,0x00,0x52,0x04,0x0a,0x00,0x11,0x04,0x08,0x00,
- 0x0a,0x00,0x54,0x04,0x0a,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0a,0x00,
- 0x0b,0x00,0x0d,0x00,0x0d,0x00,0x12,0x04,0x0d,0x00,0x10,0x00,0xcf,0x86,0x95,0x30,
- 0x94,0x2c,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x12,0x00,
- 0x91,0x08,0x10,0x04,0x12,0x00,0x13,0x00,0x13,0x00,0xd2,0x08,0x11,0x04,0x13,0x00,
- 0x14,0x00,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x15,0x00,0x00,0x00,0x00,0x00,
- 0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00,0x92,0x0c,
- 0x51,0x04,0x04,0x00,0x10,0x04,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xcf,0x86,
- 0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00,0x93,0x08,0x12,0x04,0x04,0x00,0x00,0x00,
- 0x00,0x00,0xd1,0x06,0xcf,0x06,0x04,0x00,0xd0,0x06,0xcf,0x06,0x04,0x00,0xcf,0x86,
- 0xd5,0x14,0x54,0x04,0x04,0x00,0x93,0x0c,0x52,0x04,0x04,0x00,0x11,0x04,0x04,0x00,
- 0x00,0x00,0x00,0x00,0x54,0x04,0x00,0x00,0x53,0x04,0x04,0x00,0x12,0x04,0x04,0x00,
- 0x00,0x00,0xcf,0x86,0xe5,0x8d,0x05,0xe4,0x86,0x05,0xe3,0x7d,0x04,0xe2,0xe4,0x03,
- 0xe1,0xc0,0x01,0xd0,0x3e,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x1c,0x53,0x04,0x01,
- 0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0xda,0x01,0xe4,0x91,0x08,0x10,
- 0x04,0x01,0xe8,0x01,0xde,0x01,0xe0,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x04,
- 0x00,0x10,0x04,0x04,0x00,0x06,0x00,0x51,0x04,0x06,0x00,0x10,0x04,0x04,0x00,0x01,
- 0x00,0xcf,0x86,0xd5,0xaa,0xd4,0x32,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,
- 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,
- 0xff,0xe3,0x81,0x8b,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,
- 0x8d,0xe3,0x82,0x99,0x00,0x01,0x00,0xd3,0x3c,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,
- 0xff,0xe3,0x81,0x8f,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,
- 0x91,0xe3,0x82,0x99,0x00,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x93,
- 0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0x95,0xe3,0x82,0x99,
- 0x00,0x01,0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x97,0xe3,0x82,
- 0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0x99,0xe3,0x82,0x99,0x00,0x01,
- 0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x9b,0xe3,0x82,0x99,0x00,0x01,0x00,
- 0x10,0x0b,0x01,0xff,0xe3,0x81,0x9d,0xe3,0x82,0x99,0x00,0x01,0x00,0xd4,0x53,0xd3,
- 0x3c,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x9f,0xe3,0x82,0x99,0x00,
- 0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0xa1,0xe3,0x82,0x99,0x00,0x01,0x00,0xd1,
- 0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x81,0xa4,0xe3,0x82,0x99,0x00,0x10,0x04,
- 0x01,0x00,0x01,0xff,0xe3,0x81,0xa6,0xe3,0x82,0x99,0x00,0x92,0x13,0x91,0x0f,0x10,
- 0x04,0x01,0x00,0x01,0xff,0xe3,0x81,0xa8,0xe3,0x82,0x99,0x00,0x01,0x00,0x01,0x00,
- 0xd3,0x4a,0xd2,0x25,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe3,0x81,0xaf,0xe3,0x82,0x99,
- 0x00,0x01,0xff,0xe3,0x81,0xaf,0xe3,0x82,0x9a,0x00,0x10,0x04,0x01,0x00,0x01,0xff,
- 0xe3,0x81,0xb2,0xe3,0x82,0x99,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0xb2,
- 0xe3,0x82,0x9a,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0xb5,0xe3,0x82,0x99,
- 0x00,0x01,0xff,0xe3,0x81,0xb5,0xe3,0x82,0x9a,0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x04,
- 0x01,0x00,0x01,0xff,0xe3,0x81,0xb8,0xe3,0x82,0x99,0x00,0x10,0x0b,0x01,0xff,0xe3,
- 0x81,0xb8,0xe3,0x82,0x9a,0x00,0x01,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xe3,0x81,
- 0xbb,0xe3,0x82,0x99,0x00,0x01,0xff,0xe3,0x81,0xbb,0xe3,0x82,0x9a,0x00,0x01,0x00,
- 0xd0,0xee,0xcf,0x86,0xd5,0x42,0x54,0x04,0x01,0x00,0xd3,0x1b,0x52,0x04,0x01,0x00,
- 0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x86,0xe3,0x82,0x99,0x00,0x06,0x00,0x10,
- 0x04,0x06,0x00,0x00,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x08,0x10,
- 0x04,0x01,0x08,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0x9d,
- 0xe3,0x82,0x99,0x00,0x06,0x00,0xd4,0x32,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,
- 0x06,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x0f,0x10,0x0b,
- 0x01,0xff,0xe3,0x82,0xab,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,
- 0x82,0xad,0xe3,0x82,0x99,0x00,0x01,0x00,0xd3,0x3c,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,
- 0x01,0xff,0xe3,0x82,0xaf,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,
- 0x82,0xb1,0xe3,0x82,0x99,0x00,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,
- 0xb3,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb5,0xe3,0x82,
- 0x99,0x00,0x01,0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb7,0xe3,
- 0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb9,0xe3,0x82,0x99,0x00,
- 0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xbb,0xe3,0x82,0x99,0x00,0x01,
- 0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xbd,0xe3,0x82,0x99,0x00,0x01,0x00,0xcf,0x86,
- 0xd5,0xd5,0xd4,0x53,0xd3,0x3c,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,
- 0xbf,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x83,0x81,0xe3,0x82,
- 0x99,0x00,0x01,0x00,0xd1,0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x84,0xe3,
- 0x82,0x99,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x86,0xe3,0x82,0x99,0x00,
- 0x92,0x13,0x91,0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x88,0xe3,0x82,0x99,
- 0x00,0x01,0x00,0x01,0x00,0xd3,0x4a,0xd2,0x25,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe3,
- 0x83,0x8f,0xe3,0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0x8f,0xe3,0x82,0x9a,0x00,0x10,
- 0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x92,0xe3,0x82,0x99,0x00,0xd1,0x0f,0x10,0x0b,
- 0x01,0xff,0xe3,0x83,0x92,0xe3,0x82,0x9a,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,
- 0x83,0x95,0xe3,0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0x95,0xe3,0x82,0x9a,0x00,0xd2,
- 0x1e,0xd1,0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x98,0xe3,0x82,0x99,0x00,
- 0x10,0x0b,0x01,0xff,0xe3,0x83,0x98,0xe3,0x82,0x9a,0x00,0x01,0x00,0x91,0x16,0x10,
- 0x0b,0x01,0xff,0xe3,0x83,0x9b,0xe3,0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0x9b,0xe3,
- 0x82,0x9a,0x00,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x22,0x52,0x04,0x01,0x00,0xd1,
- 0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xa6,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x04,
- 0x01,0x00,0x01,0xff,0xe3,0x83,0xaf,0xe3,0x82,0x99,0x00,0xd2,0x25,0xd1,0x16,0x10,
- 0x0b,0x01,0xff,0xe3,0x83,0xb0,0xe3,0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0xb1,0xe3,
- 0x82,0x99,0x00,0x10,0x0b,0x01,0xff,0xe3,0x83,0xb2,0xe3,0x82,0x99,0x00,0x01,0x00,
- 0x51,0x04,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x83,0xbd,0xe3,0x82,0x99,0x00,0x06,
- 0x00,0xd1,0x4c,0xd0,0x46,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x52,0x04,0x00,
- 0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,
- 0x18,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x0a,
- 0x00,0x10,0x04,0x13,0x00,0x14,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,
- 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x06,0x01,0x00,0xd0,0x32,0xcf,
- 0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,
- 0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x54,0x04,0x04,0x00,0x53,0x04,0x04,
- 0x00,0x92,0x0c,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0xcf,
- 0x86,0xd5,0x08,0x14,0x04,0x08,0x00,0x0a,0x00,0x94,0x0c,0x93,0x08,0x12,0x04,0x0a,
- 0x00,0x00,0x00,0x00,0x00,0x06,0x00,0xd2,0xa4,0xd1,0x5c,0xd0,0x22,0xcf,0x86,0x95,
- 0x1c,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,
- 0x04,0x01,0x00,0x07,0x00,0x10,0x04,0x07,0x00,0x00,0x00,0x01,0x00,0xcf,0x86,0xd5,
- 0x20,0xd4,0x0c,0x93,0x08,0x12,0x04,0x01,0x00,0x0b,0x00,0x0b,0x00,0x93,0x10,0x92,
- 0x0c,0x91,0x08,0x10,0x04,0x07,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x54,
- 0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x07,0x00,0x10,
- 0x04,0x08,0x00,0x01,0x00,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,
- 0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x06,0x00,0x06,
- 0x00,0x06,0x00,0xcf,0x86,0xd5,0x10,0x94,0x0c,0x53,0x04,0x01,0x00,0x12,0x04,0x01,
- 0x00,0x07,0x00,0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,
- 0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x16,0x00,0xd1,0x30,0xd0,0x06,0xcf,
- 0x06,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x10,0x52,
- 0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x07,0x00,0x92,0x0c,0x51,
- 0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x01,0x00,0x01,0x00,0xd0,0x06,0xcf,0x06,0x01,
- 0x00,0xcf,0x86,0xd5,0x14,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,
- 0x00,0x11,0x04,0x01,0x00,0x07,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,
- 0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x07,0x00,0xcf,0x06,0x04,
- 0x00,0xcf,0x06,0x04,0x00,0xd1,0x48,0xd0,0x40,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x04,
- 0x00,0xd4,0x06,0xcf,0x06,0x04,0x00,0xd3,0x2c,0xd2,0x06,0xcf,0x06,0x04,0x00,0xd1,
- 0x06,0xcf,0x06,0x04,0x00,0xd0,0x1a,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,
- 0x00,0x93,0x0c,0x52,0x04,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0xcf,
- 0x06,0x07,0x00,0xcf,0x06,0x01,0x00,0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xcf,
- 0x06,0x01,0x00,0xe2,0x71,0x05,0xd1,0x8c,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x01,0x00,
- 0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01,0x00,0xd4,0x06,0xcf,0x06,0x01,0x00,0xd3,0x06,
- 0xcf,0x06,0x01,0x00,0xd2,0x06,0xcf,0x06,0x01,0x00,0xd1,0x06,0xcf,0x06,0x01,0x00,
- 0xd0,0x22,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x10,0x93,0x0c,0x52,0x04,0x01,0x00,
- 0x11,0x04,0x01,0x00,0x08,0x00,0x08,0x00,0x53,0x04,0x08,0x00,0x12,0x04,0x08,0x00,
- 0x0a,0x00,0xcf,0x86,0xd5,0x28,0xd4,0x18,0xd3,0x08,0x12,0x04,0x0a,0x00,0x0b,0x00,
- 0x52,0x04,0x0b,0x00,0x91,0x08,0x10,0x04,0x0d,0x00,0x11,0x00,0x11,0x00,0x93,0x0c,
- 0x52,0x04,0x11,0x00,0x11,0x04,0x11,0x00,0x13,0x00,0x13,0x00,0x94,0x14,0x53,0x04,
- 0x13,0x00,0x92,0x0c,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x14,0x00,0x14,0x00,
- 0x00,0x00,0xe0,0xdb,0x04,0xcf,0x86,0xe5,0xdf,0x01,0xd4,0x06,0xcf,0x06,0x04,0x00,
- 0xd3,0x74,0xd2,0x6e,0xd1,0x06,0xcf,0x06,0x04,0x00,0xd0,0x3e,0xcf,0x86,0xd5,0x18,
- 0x94,0x14,0x53,0x04,0x04,0x00,0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,
- 0x00,0x00,0x00,0x00,0x04,0x00,0xd4,0x10,0x93,0x0c,0x92,0x08,0x11,0x04,0x04,0x00,
- 0x06,0x00,0x04,0x00,0x04,0x00,0x93,0x10,0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,
- 0x06,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xcf,0x86,0x95,0x24,0x94,0x20,0x93,0x1c,
- 0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x06,0x00,0x04,0x00,0xd1,0x08,0x10,0x04,
- 0x04,0x00,0x06,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0x0b,0x00,
- 0xcf,0x06,0x0a,0x00,0xd2,0x84,0xd1,0x4c,0xd0,0x16,0xcf,0x86,0x55,0x04,0x0a,0x00,
- 0x94,0x0c,0x53,0x04,0x0a,0x00,0x12,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,
- 0x55,0x04,0x0a,0x00,0xd4,0x1c,0xd3,0x0c,0x92,0x08,0x11,0x04,0x0c,0x00,0x0a,0x00,
- 0x0a,0x00,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x00,0x0a,0xe6,
- 0xd3,0x08,0x12,0x04,0x0a,0x00,0x0d,0xe6,0x52,0x04,0x0d,0xe6,0x11,0x04,0x0a,0xe6,
- 0x0a,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x0a,0x00,0x53,0x04,0x0a,0x00,
- 0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x11,0xe6,0x0d,0xe6,0x0b,0x00,
- 0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,
- 0x0b,0xe6,0x0b,0x00,0x0b,0x00,0x00,0x00,0xd1,0x40,0xd0,0x3a,0xcf,0x86,0xd5,0x24,
- 0x54,0x04,0x08,0x00,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,
- 0x08,0x00,0x09,0x00,0x92,0x0c,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x0a,0x00,
- 0x0a,0x00,0x94,0x10,0x93,0x0c,0x92,0x08,0x11,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,
- 0x0a,0x00,0x0a,0x00,0xcf,0x06,0x0a,0x00,0xd0,0x5e,0xcf,0x86,0xd5,0x28,0xd4,0x18,
- 0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,0xd1,0x08,0x10,0x04,0x0a,0x00,0x0c,0x00,
- 0x10,0x04,0x0c,0x00,0x11,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x0c,0x00,0x0d,0x00,
- 0x10,0x00,0x10,0x00,0xd4,0x1c,0x53,0x04,0x0c,0x00,0xd2,0x0c,0x51,0x04,0x0c,0x00,
- 0x10,0x04,0x0d,0x00,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x12,0x00,0x14,0x00,
- 0xd3,0x0c,0x92,0x08,0x11,0x04,0x10,0x00,0x11,0x00,0x11,0x00,0x92,0x08,0x11,0x04,
- 0x14,0x00,0x15,0x00,0x15,0x00,0xcf,0x86,0xd5,0x1c,0x94,0x18,0x93,0x14,0xd2,0x08,
- 0x11,0x04,0x00,0x00,0x15,0x00,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x54,0x04,0x00,0x00,0xd3,0x10,0x52,0x04,0x00,0x00,0x51,0x04,
- 0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x92,0x0c,0x51,0x04,0x0d,0x00,0x10,0x04,
- 0x0c,0x00,0x0a,0x00,0x0a,0x00,0xe4,0xf2,0x02,0xe3,0x65,0x01,0xd2,0x98,0xd1,0x48,
- 0xd0,0x36,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x52,0x04,0x08,0x00,0x51,0x04,
- 0x08,0x00,0x10,0x04,0x08,0x09,0x08,0x00,0x08,0x00,0x08,0x00,0xd4,0x0c,0x53,0x04,
- 0x08,0x00,0x12,0x04,0x08,0x00,0x00,0x00,0x53,0x04,0x0b,0x00,0x92,0x08,0x11,0x04,
- 0x0b,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,0x09,0x00,0x54,0x04,0x09,0x00,
- 0x13,0x04,0x09,0x00,0x00,0x00,0xd0,0x06,0xcf,0x06,0x0a,0x00,0xcf,0x86,0xd5,0x2c,
- 0xd4,0x1c,0xd3,0x10,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x09,0x12,0x00,
- 0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x0a,0x00,0x53,0x04,0x0a,0x00,
- 0x92,0x08,0x11,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0x54,0x04,0x0b,0xe6,0xd3,0x0c,
- 0x92,0x08,0x11,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0x00,0x52,0x04,0x0b,0x00,0x11,0x04,
- 0x11,0x00,0x14,0x00,0xd1,0x60,0xd0,0x22,0xcf,0x86,0x55,0x04,0x0a,0x00,0x94,0x18,
- 0x53,0x04,0x0a,0x00,0xd2,0x0c,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x00,0x0a,0xdc,
- 0x11,0x04,0x0a,0xdc,0x0a,0x00,0x0a,0x00,0xcf,0x86,0xd5,0x24,0x54,0x04,0x0a,0x00,
- 0xd3,0x10,0x92,0x0c,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x00,0x0a,0x09,0x00,0x00,
- 0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0a,0x00,0x54,0x04,
- 0x0b,0x00,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x00,
- 0x00,0x00,0x00,0x00,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,0x00,
- 0x93,0x10,0x92,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x0b,0x07,0x0b,0x00,
- 0x0b,0x00,0xcf,0x86,0xd5,0x34,0xd4,0x20,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,
- 0x0b,0x09,0x0b,0x00,0x0b,0x00,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,
- 0x10,0x04,0x00,0x00,0x0b,0x00,0x53,0x04,0x0b,0x00,0xd2,0x08,0x11,0x04,0x0b,0x00,
- 0x00,0x00,0x11,0x04,0x00,0x00,0x0b,0x00,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,
- 0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0xd2,0xd0,
- 0xd1,0x50,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x0a,0x00,0x54,0x04,0x0a,0x00,0x93,0x10,
- 0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,
- 0xcf,0x86,0xd5,0x20,0xd4,0x10,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,0x11,0x04,
- 0x0a,0x00,0x00,0x00,0x53,0x04,0x0a,0x00,0x92,0x08,0x11,0x04,0x0a,0x00,0x00,0x00,
- 0x0a,0x00,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,0x12,0x04,0x0b,0x00,0x10,0x00,
- 0xd0,0x3a,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,0x00,0xd3,0x1c,0xd2,0x0c,
- 0x91,0x08,0x10,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0xe6,0xd1,0x08,0x10,0x04,0x0b,0xdc,
- 0x0b,0x00,0x10,0x04,0x0b,0x00,0x0b,0xe6,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0b,0xe6,
- 0x0b,0x00,0x0b,0x00,0x11,0x04,0x0b,0x00,0x0b,0xe6,0xcf,0x86,0xd5,0x2c,0xd4,0x18,
- 0x93,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x0b,0x00,0x0b,0xe6,0x10,0x04,0x0b,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x00,0x00,0x92,0x0c,0x51,0x04,0x00,0x00,
- 0x10,0x04,0x00,0x00,0x0b,0x00,0x0b,0x00,0x54,0x04,0x0d,0x00,0x93,0x10,0x52,0x04,
- 0x0d,0x00,0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x09,0x00,0x00,0x00,0x00,0xd1,0x8c,
- 0xd0,0x72,0xcf,0x86,0xd5,0x4c,0xd4,0x30,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,
- 0x00,0x00,0x0c,0x00,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,
+ 0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x80,0x00,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,
+ 0xe1,0x8f,0x5b,0x10,0x09,0x01,0xff,0xcf,0x81,0xcc,0x94,0x00,0x01,0xff,0xc2,0xa8,
+ 0xcc,0x80,0x00,0xd3,0x3b,0xd2,0x18,0x51,0x04,0x00,0x00,0x10,0x0b,0x01,0xff,0xcf,
+ 0x89,0xcc,0x80,0xce,0xb9,0x00,0x01,0xff,0xcf,0x89,0xce,0xb9,0x00,0xd1,0x0f,0x10,
+ 0x0b,0x01,0xff,0xcf,0x89,0xcc,0x81,0xce,0xb9,0x00,0x00,0x00,0x10,0x09,0x01,0xff,
+ 0xcf,0x89,0xcd,0x82,0x00,0x01,0xff,0xcf,0x89,0xcd,0x82,0xce,0xb9,0x00,0xd2,0x24,
+ 0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,0xcc,
+ 0x81,0x00,0x10,0x09,0x01,0xff,0xcf,0x89,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc,
+ 0x81,0x00,0xe1,0x99,0x5b,0x10,0x09,0x01,0xff,0xcf,0x89,0xce,0xb9,0x00,0x01,0xff,
+ 0xc2,0xb4,0x00,0xe0,0x0c,0x68,0xcf,0x86,0xe5,0x23,0x02,0xe4,0x25,0x01,0xe3,0x85,
+ 0x5e,0xd2,0x2a,0xe1,0x5f,0x5c,0xe0,0xdd,0x5b,0xcf,0x86,0xe5,0xbb,0x5b,0x94,0x1b,
+ 0xe3,0xa4,0x5b,0x92,0x14,0x91,0x10,0x10,0x08,0x01,0xff,0xe2,0x80,0x82,0x00,0x01,
+ 0xff,0xe2,0x80,0x83,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd1,0xd6,0xd0,0x46,0xcf,
+ 0x86,0x55,0x04,0x01,0x00,0xd4,0x29,0xd3,0x13,0x52,0x04,0x01,0x00,0x51,0x04,0x01,
+ 0x00,0x10,0x07,0x01,0xff,0xcf,0x89,0x00,0x01,0x00,0x92,0x12,0x51,0x04,0x01,0x00,
+ 0x10,0x06,0x01,0xff,0x6b,0x00,0x01,0xff,0x61,0xcc,0x8a,0x00,0x01,0x00,0xe3,0x25,
+ 0x5d,0x92,0x10,0x51,0x04,0x01,0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0x8e,0x00,0x01,
+ 0x00,0x01,0x00,0xcf,0x86,0xd5,0x0a,0xe4,0x42,0x5d,0x63,0x2d,0x5d,0x06,0x00,0x94,
+ 0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xb0,0x00,0x01,
+ 0xff,0xe2,0x85,0xb1,0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xb2,0x00,0x01,0xff,0xe2,
+ 0x85,0xb3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xb4,0x00,0x01,0xff,0xe2,
+ 0x85,0xb5,0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xb6,0x00,0x01,0xff,0xe2,0x85,0xb7,
+ 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xb8,0x00,0x01,0xff,0xe2,
+ 0x85,0xb9,0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xba,0x00,0x01,0xff,0xe2,0x85,0xbb,
+ 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x85,0xbc,0x00,0x01,0xff,0xe2,0x85,0xbd,
+ 0x00,0x10,0x08,0x01,0xff,0xe2,0x85,0xbe,0x00,0x01,0xff,0xe2,0x85,0xbf,0x00,0x01,
+ 0x00,0xe0,0x34,0x5d,0xcf,0x86,0xe5,0x13,0x5d,0xe4,0xf2,0x5c,0xe3,0xe1,0x5c,0xe2,
+ 0xd4,0x5c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x04,0xff,0xe2,0x86,0x84,0x00,
+ 0xe3,0x23,0x61,0xe2,0xf0,0x60,0xd1,0x0c,0xe0,0x9d,0x60,0xcf,0x86,0x65,0x7e,0x60,
+ 0x01,0x00,0xd0,0x62,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x18,
+ 0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x08,0x01,0xff,0xe2,0x93,0x90,0x00,
+ 0x01,0xff,0xe2,0x93,0x91,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x93,
+ 0x92,0x00,0x01,0xff,0xe2,0x93,0x93,0x00,0x10,0x08,0x01,0xff,0xe2,0x93,0x94,0x00,
+ 0x01,0xff,0xe2,0x93,0x95,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe2,0x93,0x96,0x00,
+ 0x01,0xff,0xe2,0x93,0x97,0x00,0x10,0x08,0x01,0xff,0xe2,0x93,0x98,0x00,0x01,0xff,
+ 0xe2,0x93,0x99,0x00,0xcf,0x86,0xe5,0x57,0x60,0x94,0x80,0xd3,0x40,0xd2,0x20,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0xe2,0x93,0x9a,0x00,0x01,0xff,0xe2,0x93,0x9b,0x00,0x10,
+ 0x08,0x01,0xff,0xe2,0x93,0x9c,0x00,0x01,0xff,0xe2,0x93,0x9d,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0xe2,0x93,0x9e,0x00,0x01,0xff,0xe2,0x93,0x9f,0x00,0x10,0x08,0x01,
+ 0xff,0xe2,0x93,0xa0,0x00,0x01,0xff,0xe2,0x93,0xa1,0x00,0xd2,0x20,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0xe2,0x93,0xa2,0x00,0x01,0xff,0xe2,0x93,0xa3,0x00,0x10,0x08,0x01,
+ 0xff,0xe2,0x93,0xa4,0x00,0x01,0xff,0xe2,0x93,0xa5,0x00,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0xe2,0x93,0xa6,0x00,0x01,0xff,0xe2,0x93,0xa7,0x00,0x10,0x08,0x01,0xff,0xe2,
+ 0x93,0xa8,0x00,0x01,0xff,0xe2,0x93,0xa9,0x00,0x01,0x00,0xd4,0x0c,0xe3,0x33,0x62,
+ 0xe2,0x2c,0x62,0xcf,0x06,0x04,0x00,0xe3,0x0c,0x65,0xe2,0xff,0x63,0xe1,0x2e,0x02,
+ 0xe0,0x84,0x01,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x08,0xff,0xe2,0xb0,0xb0,0x00,0x08,0xff,0xe2,0xb0,0xb1,0x00,0x10,0x08,
+ 0x08,0xff,0xe2,0xb0,0xb2,0x00,0x08,0xff,0xe2,0xb0,0xb3,0x00,0xd1,0x10,0x10,0x08,
+ 0x08,0xff,0xe2,0xb0,0xb4,0x00,0x08,0xff,0xe2,0xb0,0xb5,0x00,0x10,0x08,0x08,0xff,
+ 0xe2,0xb0,0xb6,0x00,0x08,0xff,0xe2,0xb0,0xb7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x08,0xff,0xe2,0xb0,0xb8,0x00,0x08,0xff,0xe2,0xb0,0xb9,0x00,0x10,0x08,0x08,0xff,
+ 0xe2,0xb0,0xba,0x00,0x08,0xff,0xe2,0xb0,0xbb,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe2,0xb0,0xbc,0x00,0x08,0xff,0xe2,0xb0,0xbd,0x00,0x10,0x08,0x08,0xff,0xe2,0xb0,
+ 0xbe,0x00,0x08,0xff,0xe2,0xb0,0xbf,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x08,0xff,0xe2,0xb1,0x80,0x00,0x08,0xff,0xe2,0xb1,0x81,0x00,0x10,0x08,0x08,0xff,
+ 0xe2,0xb1,0x82,0x00,0x08,0xff,0xe2,0xb1,0x83,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe2,0xb1,0x84,0x00,0x08,0xff,0xe2,0xb1,0x85,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,
+ 0x86,0x00,0x08,0xff,0xe2,0xb1,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe2,0xb1,0x88,0x00,0x08,0xff,0xe2,0xb1,0x89,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,
+ 0x8a,0x00,0x08,0xff,0xe2,0xb1,0x8b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb1,
+ 0x8c,0x00,0x08,0xff,0xe2,0xb1,0x8d,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0x8e,0x00,
+ 0x08,0xff,0xe2,0xb1,0x8f,0x00,0x94,0x7c,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x08,0xff,0xe2,0xb1,0x90,0x00,0x08,0xff,0xe2,0xb1,0x91,0x00,0x10,0x08,0x08,0xff,
+ 0xe2,0xb1,0x92,0x00,0x08,0xff,0xe2,0xb1,0x93,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe2,0xb1,0x94,0x00,0x08,0xff,0xe2,0xb1,0x95,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,
+ 0x96,0x00,0x08,0xff,0xe2,0xb1,0x97,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe2,0xb1,0x98,0x00,0x08,0xff,0xe2,0xb1,0x99,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,
+ 0x9a,0x00,0x08,0xff,0xe2,0xb1,0x9b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe2,0xb1,
+ 0x9c,0x00,0x08,0xff,0xe2,0xb1,0x9d,0x00,0x10,0x08,0x08,0xff,0xe2,0xb1,0x9e,0x00,
+ 0x00,0x00,0x08,0x00,0xcf,0x86,0xd5,0x07,0x64,0xef,0x61,0x08,0x00,0xd4,0x63,0xd3,
+ 0x32,0xd2,0x1b,0xd1,0x0c,0x10,0x08,0x09,0xff,0xe2,0xb1,0xa1,0x00,0x09,0x00,0x10,
+ 0x07,0x09,0xff,0xc9,0xab,0x00,0x09,0xff,0xe1,0xb5,0xbd,0x00,0xd1,0x0b,0x10,0x07,
+ 0x09,0xff,0xc9,0xbd,0x00,0x09,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xe2,0xb1,0xa8,
+ 0x00,0xd2,0x18,0xd1,0x0c,0x10,0x04,0x09,0x00,0x09,0xff,0xe2,0xb1,0xaa,0x00,0x10,
+ 0x04,0x09,0x00,0x09,0xff,0xe2,0xb1,0xac,0x00,0xd1,0x0b,0x10,0x04,0x09,0x00,0x0a,
+ 0xff,0xc9,0x91,0x00,0x10,0x07,0x0a,0xff,0xc9,0xb1,0x00,0x0a,0xff,0xc9,0x90,0x00,
+ 0xd3,0x27,0xd2,0x17,0xd1,0x0b,0x10,0x07,0x0b,0xff,0xc9,0x92,0x00,0x0a,0x00,0x10,
+ 0x08,0x0a,0xff,0xe2,0xb1,0xb3,0x00,0x0a,0x00,0x91,0x0c,0x10,0x04,0x09,0x00,0x09,
+ 0xff,0xe2,0xb1,0xb6,0x00,0x09,0x00,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,
+ 0x07,0x0b,0xff,0xc8,0xbf,0x00,0x0b,0xff,0xc9,0x80,0x00,0xe0,0x83,0x01,0xcf,0x86,
+ 0xd5,0xc0,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,
+ 0x81,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x83,0x00,0x08,0x00,0xd1,0x0c,
+ 0x10,0x08,0x08,0xff,0xe2,0xb2,0x85,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,
+ 0x87,0x00,0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0x89,0x00,
+ 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x8b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,
+ 0x08,0xff,0xe2,0xb2,0x8d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x8f,0x00,
+ 0x08,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0x91,0x00,
+ 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x93,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,
+ 0x08,0xff,0xe2,0xb2,0x95,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x97,0x00,
+ 0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0x99,0x00,0x08,0x00,
+ 0x10,0x08,0x08,0xff,0xe2,0xb2,0x9b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,
+ 0xe2,0xb2,0x9d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0x9f,0x00,0x08,0x00,
+ 0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa1,0x00,
+ 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa3,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,
+ 0x08,0xff,0xe2,0xb2,0xa5,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa7,0x00,
+ 0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xa9,0x00,0x08,0x00,
+ 0x10,0x08,0x08,0xff,0xe2,0xb2,0xab,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,
+ 0xe2,0xb2,0xad,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xaf,0x00,0x08,0x00,
+ 0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xb1,0x00,0x08,0x00,
+ 0x10,0x08,0x08,0xff,0xe2,0xb2,0xb3,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,
+ 0xe2,0xb2,0xb5,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xb7,0x00,0x08,0x00,
+ 0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,0xb9,0x00,0x08,0x00,0x10,0x08,
+ 0x08,0xff,0xe2,0xb2,0xbb,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb2,
+ 0xbd,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb2,0xbf,0x00,0x08,0x00,0xcf,0x86,
+ 0xd5,0xc0,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,
+ 0x81,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x83,0x00,0x08,0x00,0xd1,0x0c,
+ 0x10,0x08,0x08,0xff,0xe2,0xb3,0x85,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,
+ 0x87,0x00,0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0x89,0x00,
+ 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x8b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,
+ 0x08,0xff,0xe2,0xb3,0x8d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x8f,0x00,
+ 0x08,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0x91,0x00,
+ 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x93,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,
+ 0x08,0xff,0xe2,0xb3,0x95,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x97,0x00,
+ 0x08,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0x99,0x00,0x08,0x00,
+ 0x10,0x08,0x08,0xff,0xe2,0xb3,0x9b,0x00,0x08,0x00,0xd1,0x0c,0x10,0x08,0x08,0xff,
+ 0xe2,0xb3,0x9d,0x00,0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0x9f,0x00,0x08,0x00,
+ 0xd4,0x3b,0xd3,0x1c,0x92,0x18,0xd1,0x0c,0x10,0x08,0x08,0xff,0xe2,0xb3,0xa1,0x00,
+ 0x08,0x00,0x10,0x08,0x08,0xff,0xe2,0xb3,0xa3,0x00,0x08,0x00,0x08,0x00,0xd2,0x10,
+ 0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x0b,0xff,0xe2,0xb3,0xac,0x00,0xe1,0x3b,
+ 0x5f,0x10,0x04,0x0b,0x00,0x0b,0xff,0xe2,0xb3,0xae,0x00,0xe3,0x40,0x5f,0x92,0x10,
+ 0x51,0x04,0x0b,0xe6,0x10,0x08,0x0d,0xff,0xe2,0xb3,0xb3,0x00,0x0d,0x00,0x00,0x00,
+ 0xe2,0x98,0x08,0xd1,0x0b,0xe0,0x11,0x67,0xcf,0x86,0xcf,0x06,0x01,0x00,0xe0,0x65,
+ 0x6c,0xcf,0x86,0xe5,0xa7,0x05,0xd4,0x06,0xcf,0x06,0x04,0x00,0xd3,0x0c,0xe2,0xf8,
+ 0x67,0xe1,0x8f,0x67,0xcf,0x06,0x04,0x00,0xe2,0xdb,0x01,0xe1,0x26,0x01,0xd0,0x09,
+ 0xcf,0x86,0x65,0xf4,0x67,0x0a,0x00,0xcf,0x86,0xd5,0xc0,0xd4,0x60,0xd3,0x30,0xd2,
+ 0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a,
+ 0xff,0xea,0x99,0x83,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x85,
+ 0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x87,0x00,0x0a,0x00,0xd2,0x18,0xd1,
+ 0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x89,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,
+ 0x99,0x8b,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x8d,0x00,0x0a,
+ 0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x8f,0x00,0x0a,0x00,0xd3,0x30,0xd2,0x18,0xd1,
+ 0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x91,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,
+ 0x99,0x93,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x95,0x00,0x0a,
+ 0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x97,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,
+ 0x08,0x0a,0xff,0xea,0x99,0x99,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0x9b,
+ 0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0x9d,0x00,0x0a,0x00,0x10,
+ 0x08,0x0a,0xff,0xea,0x99,0x9f,0x00,0x0a,0x00,0xe4,0x5d,0x67,0xd3,0x30,0xd2,0x18,
+ 0xd1,0x0c,0x10,0x08,0x0c,0xff,0xea,0x99,0xa1,0x00,0x0c,0x00,0x10,0x08,0x0a,0xff,
+ 0xea,0x99,0xa3,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x99,0xa5,0x00,
+ 0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,0xa7,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,
+ 0x10,0x08,0x0a,0xff,0xea,0x99,0xa9,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x99,
+ 0xab,0x00,0x0a,0x00,0xe1,0x0c,0x67,0x10,0x08,0x0a,0xff,0xea,0x99,0xad,0x00,0x0a,
+ 0x00,0xe0,0x35,0x67,0xcf,0x86,0x95,0xab,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,
+ 0x10,0x08,0x0a,0xff,0xea,0x9a,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9a,
+ 0x83,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9a,0x85,0x00,0x0a,0x00,
+ 0x10,0x08,0x0a,0xff,0xea,0x9a,0x87,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,
+ 0x0a,0xff,0xea,0x9a,0x89,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9a,0x8b,0x00,
+ 0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9a,0x8d,0x00,0x0a,0x00,0x10,0x08,
+ 0x0a,0xff,0xea,0x9a,0x8f,0x00,0x0a,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,
+ 0x0a,0xff,0xea,0x9a,0x91,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9a,0x93,0x00,
+ 0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9a,0x95,0x00,0x0a,0x00,0x10,0x08,
+ 0x0a,0xff,0xea,0x9a,0x97,0x00,0x0a,0x00,0xe2,0x92,0x66,0xd1,0x0c,0x10,0x08,0x10,
+ 0xff,0xea,0x9a,0x99,0x00,0x10,0x00,0x10,0x08,0x10,0xff,0xea,0x9a,0x9b,0x00,0x10,
+ 0x00,0x0b,0x00,0xe1,0x10,0x02,0xd0,0xb9,0xcf,0x86,0xd5,0x07,0x64,0x9e,0x66,0x08,
+ 0x00,0xd4,0x58,0xd3,0x28,0xd2,0x10,0x51,0x04,0x09,0x00,0x10,0x08,0x0a,0xff,0xea,
+ 0x9c,0xa3,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9c,0xa5,0x00,0x0a,
+ 0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xa7,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,
+ 0x08,0x0a,0xff,0xea,0x9c,0xa9,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xab,
+ 0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9c,0xad,0x00,0x0a,0x00,0x10,
+ 0x08,0x0a,0xff,0xea,0x9c,0xaf,0x00,0x0a,0x00,0xd3,0x28,0xd2,0x10,0x51,0x04,0x0a,
+ 0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xb3,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,
+ 0xff,0xea,0x9c,0xb5,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xb7,0x00,0x0a,
+ 0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9c,0xb9,0x00,0x0a,0x00,0x10,
+ 0x08,0x0a,0xff,0xea,0x9c,0xbb,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,
+ 0x9c,0xbd,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9c,0xbf,0x00,0x0a,0x00,0xcf,
+ 0x86,0xd5,0xc0,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,
+ 0x9d,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x83,0x00,0x0a,0x00,0xd1,
+ 0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x85,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,
+ 0x9d,0x87,0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x89,
+ 0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x8b,0x00,0x0a,0x00,0xd1,0x0c,0x10,
+ 0x08,0x0a,0xff,0xea,0x9d,0x8d,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x8f,
+ 0x00,0x0a,0x00,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x91,
+ 0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x93,0x00,0x0a,0x00,0xd1,0x0c,0x10,
+ 0x08,0x0a,0xff,0xea,0x9d,0x95,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x97,
+ 0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0x99,0x00,0x0a,
+ 0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x9b,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,
+ 0xff,0xea,0x9d,0x9d,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0x9f,0x00,0x0a,
+ 0x00,0xd4,0x60,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa1,
+ 0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa3,0x00,0x0a,0x00,0xd1,0x0c,0x10,
+ 0x08,0x0a,0xff,0xea,0x9d,0xa5,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa7,
+ 0x00,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9d,0xa9,0x00,0x0a,
+ 0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xab,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,
+ 0xff,0xea,0x9d,0xad,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xaf,0x00,0x0a,
+ 0x00,0x53,0x04,0x0a,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x04,0x0a,0x00,0x0a,0xff,0xea,
+ 0x9d,0xba,0x00,0x10,0x04,0x0a,0x00,0x0a,0xff,0xea,0x9d,0xbc,0x00,0xd1,0x0c,0x10,
+ 0x04,0x0a,0x00,0x0a,0xff,0xe1,0xb5,0xb9,0x00,0x10,0x08,0x0a,0xff,0xea,0x9d,0xbf,
+ 0x00,0x0a,0x00,0xe0,0x71,0x01,0xcf,0x86,0xd5,0xa6,0xd4,0x4e,0xd3,0x30,0xd2,0x18,
+ 0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9e,0x81,0x00,0x0a,0x00,0x10,0x08,0x0a,0xff,
+ 0xea,0x9e,0x83,0x00,0x0a,0x00,0xd1,0x0c,0x10,0x08,0x0a,0xff,0xea,0x9e,0x85,0x00,
+ 0x0a,0x00,0x10,0x08,0x0a,0xff,0xea,0x9e,0x87,0x00,0x0a,0x00,0xd2,0x10,0x51,0x04,
+ 0x0a,0x00,0x10,0x04,0x0a,0x00,0x0a,0xff,0xea,0x9e,0x8c,0x00,0xe1,0x9a,0x64,0x10,
+ 0x04,0x0a,0x00,0x0c,0xff,0xc9,0xa5,0x00,0xd3,0x28,0xd2,0x18,0xd1,0x0c,0x10,0x08,
+ 0x0c,0xff,0xea,0x9e,0x91,0x00,0x0c,0x00,0x10,0x08,0x0d,0xff,0xea,0x9e,0x93,0x00,
+ 0x0d,0x00,0x51,0x04,0x10,0x00,0x10,0x08,0x10,0xff,0xea,0x9e,0x97,0x00,0x10,0x00,
+ 0xd2,0x18,0xd1,0x0c,0x10,0x08,0x10,0xff,0xea,0x9e,0x99,0x00,0x10,0x00,0x10,0x08,
+ 0x10,0xff,0xea,0x9e,0x9b,0x00,0x10,0x00,0xd1,0x0c,0x10,0x08,0x10,0xff,0xea,0x9e,
+ 0x9d,0x00,0x10,0x00,0x10,0x08,0x10,0xff,0xea,0x9e,0x9f,0x00,0x10,0x00,0xd4,0x63,
+ 0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x0c,0xff,0xea,0x9e,0xa1,0x00,0x0c,0x00,
+ 0x10,0x08,0x0c,0xff,0xea,0x9e,0xa3,0x00,0x0c,0x00,0xd1,0x0c,0x10,0x08,0x0c,0xff,
+ 0xea,0x9e,0xa5,0x00,0x0c,0x00,0x10,0x08,0x0c,0xff,0xea,0x9e,0xa7,0x00,0x0c,0x00,
+ 0xd2,0x1a,0xd1,0x0c,0x10,0x08,0x0c,0xff,0xea,0x9e,0xa9,0x00,0x0c,0x00,0x10,0x07,
+ 0x0d,0xff,0xc9,0xa6,0x00,0x10,0xff,0xc9,0x9c,0x00,0xd1,0x0e,0x10,0x07,0x10,0xff,
+ 0xc9,0xa1,0x00,0x10,0xff,0xc9,0xac,0x00,0x10,0x07,0x12,0xff,0xc9,0xaa,0x00,0x14,
+ 0x00,0xd3,0x35,0xd2,0x1d,0xd1,0x0e,0x10,0x07,0x10,0xff,0xca,0x9e,0x00,0x10,0xff,
+ 0xca,0x87,0x00,0x10,0x07,0x11,0xff,0xca,0x9d,0x00,0x11,0xff,0xea,0xad,0x93,0x00,
+ 0xd1,0x0c,0x10,0x08,0x11,0xff,0xea,0x9e,0xb5,0x00,0x11,0x00,0x10,0x08,0x11,0xff,
+ 0xea,0x9e,0xb7,0x00,0x11,0x00,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x14,0xff,0xea,0x9e,
+ 0xb9,0x00,0x14,0x00,0x10,0x08,0x15,0xff,0xea,0x9e,0xbb,0x00,0x15,0x00,0xd1,0x0c,
+ 0x10,0x08,0x15,0xff,0xea,0x9e,0xbd,0x00,0x15,0x00,0x10,0x08,0x15,0xff,0xea,0x9e,
+ 0xbf,0x00,0x15,0x00,0xcf,0x86,0xe5,0xd4,0x63,0x94,0x2f,0x93,0x2b,0xd2,0x10,0x51,
+ 0x04,0x00,0x00,0x10,0x08,0x15,0xff,0xea,0x9f,0x83,0x00,0x15,0x00,0xd1,0x0f,0x10,
+ 0x08,0x15,0xff,0xea,0x9e,0x94,0x00,0x15,0xff,0xca,0x82,0x00,0x10,0x08,0x15,0xff,
+ 0xe1,0xb6,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe4,0xb4,0x66,0xd3,0x1d,0xe2,
+ 0x5b,0x64,0xe1,0x0a,0x64,0xe0,0xf7,0x63,0xcf,0x86,0xe5,0xd8,0x63,0x94,0x0b,0x93,
+ 0x07,0x62,0xc3,0x63,0x08,0x00,0x08,0x00,0x08,0x00,0xd2,0x0f,0xe1,0x5a,0x65,0xe0,
+ 0x27,0x65,0xcf,0x86,0x65,0x0c,0x65,0x0a,0x00,0xd1,0xab,0xd0,0x1a,0xcf,0x86,0xe5,
+ 0x17,0x66,0xe4,0xfa,0x65,0xe3,0xe1,0x65,0xe2,0xd4,0x65,0x91,0x08,0x10,0x04,0x00,
+ 0x00,0x0c,0x00,0x0c,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0xd4,0x0b,0x93,0x07,0x62,
+ 0x27,0x66,0x11,0x00,0x00,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x11,0xff,
+ 0xe1,0x8e,0xa0,0x00,0x11,0xff,0xe1,0x8e,0xa1,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,
+ 0xa2,0x00,0x11,0xff,0xe1,0x8e,0xa3,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,
+ 0xa4,0x00,0x11,0xff,0xe1,0x8e,0xa5,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xa6,0x00,
+ 0x11,0xff,0xe1,0x8e,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,
+ 0xa8,0x00,0x11,0xff,0xe1,0x8e,0xa9,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xaa,0x00,
+ 0x11,0xff,0xe1,0x8e,0xab,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xac,0x00,
+ 0x11,0xff,0xe1,0x8e,0xad,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xae,0x00,0x11,0xff,
+ 0xe1,0x8e,0xaf,0x00,0xe0,0xb2,0x65,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,
+ 0xd2,0x20,0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xb0,0x00,0x11,0xff,0xe1,0x8e,
+ 0xb1,0x00,0x10,0x08,0x11,0xff,0xe1,0x8e,0xb2,0x00,0x11,0xff,0xe1,0x8e,0xb3,0x00,
+ 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xb4,0x00,0x11,0xff,0xe1,0x8e,0xb5,0x00,
+ 0x10,0x08,0x11,0xff,0xe1,0x8e,0xb6,0x00,0x11,0xff,0xe1,0x8e,0xb7,0x00,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8e,0xb8,0x00,0x11,0xff,0xe1,0x8e,0xb9,0x00,
+ 0x10,0x08,0x11,0xff,0xe1,0x8e,0xba,0x00,0x11,0xff,0xe1,0x8e,0xbb,0x00,0xd1,0x10,
+ 0x10,0x08,0x11,0xff,0xe1,0x8e,0xbc,0x00,0x11,0xff,0xe1,0x8e,0xbd,0x00,0x10,0x08,
+ 0x11,0xff,0xe1,0x8e,0xbe,0x00,0x11,0xff,0xe1,0x8e,0xbf,0x00,0xd3,0x40,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8f,0x80,0x00,0x11,0xff,0xe1,0x8f,0x81,0x00,
+ 0x10,0x08,0x11,0xff,0xe1,0x8f,0x82,0x00,0x11,0xff,0xe1,0x8f,0x83,0x00,0xd1,0x10,
+ 0x10,0x08,0x11,0xff,0xe1,0x8f,0x84,0x00,0x11,0xff,0xe1,0x8f,0x85,0x00,0x10,0x08,
+ 0x11,0xff,0xe1,0x8f,0x86,0x00,0x11,0xff,0xe1,0x8f,0x87,0x00,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x11,0xff,0xe1,0x8f,0x88,0x00,0x11,0xff,0xe1,0x8f,0x89,0x00,0x10,0x08,
+ 0x11,0xff,0xe1,0x8f,0x8a,0x00,0x11,0xff,0xe1,0x8f,0x8b,0x00,0xd1,0x10,0x10,0x08,
+ 0x11,0xff,0xe1,0x8f,0x8c,0x00,0x11,0xff,0xe1,0x8f,0x8d,0x00,0x10,0x08,0x11,0xff,
+ 0xe1,0x8f,0x8e,0x00,0x11,0xff,0xe1,0x8f,0x8f,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x11,0xff,0xe1,0x8f,0x90,0x00,0x11,0xff,0xe1,0x8f,0x91,0x00,
+ 0x10,0x08,0x11,0xff,0xe1,0x8f,0x92,0x00,0x11,0xff,0xe1,0x8f,0x93,0x00,0xd1,0x10,
+ 0x10,0x08,0x11,0xff,0xe1,0x8f,0x94,0x00,0x11,0xff,0xe1,0x8f,0x95,0x00,0x10,0x08,
+ 0x11,0xff,0xe1,0x8f,0x96,0x00,0x11,0xff,0xe1,0x8f,0x97,0x00,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x11,0xff,0xe1,0x8f,0x98,0x00,0x11,0xff,0xe1,0x8f,0x99,0x00,0x10,0x08,
+ 0x11,0xff,0xe1,0x8f,0x9a,0x00,0x11,0xff,0xe1,0x8f,0x9b,0x00,0xd1,0x10,0x10,0x08,
+ 0x11,0xff,0xe1,0x8f,0x9c,0x00,0x11,0xff,0xe1,0x8f,0x9d,0x00,0x10,0x08,0x11,0xff,
+ 0xe1,0x8f,0x9e,0x00,0x11,0xff,0xe1,0x8f,0x9f,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x11,0xff,0xe1,0x8f,0xa0,0x00,0x11,0xff,0xe1,0x8f,0xa1,0x00,0x10,0x08,
+ 0x11,0xff,0xe1,0x8f,0xa2,0x00,0x11,0xff,0xe1,0x8f,0xa3,0x00,0xd1,0x10,0x10,0x08,
+ 0x11,0xff,0xe1,0x8f,0xa4,0x00,0x11,0xff,0xe1,0x8f,0xa5,0x00,0x10,0x08,0x11,0xff,
+ 0xe1,0x8f,0xa6,0x00,0x11,0xff,0xe1,0x8f,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x11,0xff,0xe1,0x8f,0xa8,0x00,0x11,0xff,0xe1,0x8f,0xa9,0x00,0x10,0x08,0x11,0xff,
+ 0xe1,0x8f,0xaa,0x00,0x11,0xff,0xe1,0x8f,0xab,0x00,0xd1,0x10,0x10,0x08,0x11,0xff,
+ 0xe1,0x8f,0xac,0x00,0x11,0xff,0xe1,0x8f,0xad,0x00,0x10,0x08,0x11,0xff,0xe1,0x8f,
+ 0xae,0x00,0x11,0xff,0xe1,0x8f,0xaf,0x00,0xd1,0x0c,0xe0,0xeb,0x63,0xcf,0x86,0xcf,
+ 0x06,0x02,0xff,0xff,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,
+ 0xcf,0x06,0x01,0x00,0xd4,0xae,0xd3,0x09,0xe2,0x54,0x64,0xcf,0x06,0x01,0x00,0xd2,
+ 0x27,0xe1,0x1f,0x70,0xe0,0x26,0x6e,0xcf,0x86,0xe5,0x3f,0x6d,0xe4,0xce,0x6c,0xe3,
+ 0x99,0x6c,0xe2,0x78,0x6c,0xe1,0x67,0x6c,0x10,0x08,0x01,0xff,0xe5,0x88,0x87,0x00,
+ 0x01,0xff,0xe5,0xba,0xa6,0x00,0xe1,0x74,0x74,0xe0,0xe8,0x73,0xcf,0x86,0xe5,0x22,
+ 0x73,0xd4,0x3b,0x93,0x37,0xd2,0x1d,0xd1,0x0e,0x10,0x07,0x01,0xff,0x66,0x66,0x00,
+ 0x01,0xff,0x66,0x69,0x00,0x10,0x07,0x01,0xff,0x66,0x6c,0x00,0x01,0xff,0x66,0x66,
+ 0x69,0x00,0xd1,0x0f,0x10,0x08,0x01,0xff,0x66,0x66,0x6c,0x00,0x01,0xff,0x73,0x74,
+ 0x00,0x10,0x07,0x01,0xff,0x73,0x74,0x00,0x00,0x00,0x00,0x00,0xe3,0xc8,0x72,0xd2,
+ 0x11,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xd5,0xb4,0xd5,0xb6,0x00,
+ 0xd1,0x12,0x10,0x09,0x01,0xff,0xd5,0xb4,0xd5,0xa5,0x00,0x01,0xff,0xd5,0xb4,0xd5,
+ 0xab,0x00,0x10,0x09,0x01,0xff,0xd5,0xbe,0xd5,0xb6,0x00,0x01,0xff,0xd5,0xb4,0xd5,
+ 0xad,0x00,0xd3,0x09,0xe2,0x40,0x74,0xcf,0x06,0x01,0x00,0xd2,0x13,0xe1,0x30,0x75,
+ 0xe0,0xc1,0x74,0xcf,0x86,0xe5,0x9e,0x74,0x64,0x8d,0x74,0x06,0xff,0x00,0xe1,0x96,
+ 0x75,0xe0,0x63,0x75,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x7c,
+ 0xd3,0x3c,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0xef,0xbd,0x81,0x00,
+ 0x10,0x08,0x01,0xff,0xef,0xbd,0x82,0x00,0x01,0xff,0xef,0xbd,0x83,0x00,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xef,0xbd,0x84,0x00,0x01,0xff,0xef,0xbd,0x85,0x00,0x10,0x08,
+ 0x01,0xff,0xef,0xbd,0x86,0x00,0x01,0xff,0xef,0xbd,0x87,0x00,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xef,0xbd,0x88,0x00,0x01,0xff,0xef,0xbd,0x89,0x00,0x10,0x08,
+ 0x01,0xff,0xef,0xbd,0x8a,0x00,0x01,0xff,0xef,0xbd,0x8b,0x00,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xef,0xbd,0x8c,0x00,0x01,0xff,0xef,0xbd,0x8d,0x00,0x10,0x08,0x01,0xff,
+ 0xef,0xbd,0x8e,0x00,0x01,0xff,0xef,0xbd,0x8f,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xef,0xbd,0x90,0x00,0x01,0xff,0xef,0xbd,0x91,0x00,0x10,0x08,
+ 0x01,0xff,0xef,0xbd,0x92,0x00,0x01,0xff,0xef,0xbd,0x93,0x00,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xef,0xbd,0x94,0x00,0x01,0xff,0xef,0xbd,0x95,0x00,0x10,0x08,0x01,0xff,
+ 0xef,0xbd,0x96,0x00,0x01,0xff,0xef,0xbd,0x97,0x00,0x92,0x1c,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xef,0xbd,0x98,0x00,0x01,0xff,0xef,0xbd,0x99,0x00,0x10,0x08,0x01,0xff,
+ 0xef,0xbd,0x9a,0x00,0x01,0x00,0x01,0x00,0x83,0xe2,0x87,0xb3,0xe1,0x60,0xb0,0xe0,
+ 0xdd,0xae,0xcf,0x86,0xe5,0x81,0x9b,0xc4,0xe3,0xc1,0x07,0xe2,0x62,0x06,0xe1,0x11,
+ 0x86,0xe0,0x09,0x05,0xcf,0x86,0xe5,0xfb,0x02,0xd4,0x1c,0xe3,0x7f,0x76,0xe2,0xd6,
+ 0x75,0xe1,0xb1,0x75,0xe0,0x8a,0x75,0xcf,0x86,0xe5,0x57,0x75,0x94,0x07,0x63,0x42,
+ 0x75,0x07,0x00,0x07,0x00,0xe3,0x2b,0x78,0xe2,0xf0,0x77,0xe1,0x77,0x01,0xe0,0x88,
+ 0x77,0xcf,0x86,0xe5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,
+ 0x05,0xff,0xf0,0x90,0x90,0xa8,0x00,0x05,0xff,0xf0,0x90,0x90,0xa9,0x00,0x10,0x09,
+ 0x05,0xff,0xf0,0x90,0x90,0xaa,0x00,0x05,0xff,0xf0,0x90,0x90,0xab,0x00,0xd1,0x12,
+ 0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xac,0x00,0x05,0xff,0xf0,0x90,0x90,0xad,0x00,
+ 0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xae,0x00,0x05,0xff,0xf0,0x90,0x90,0xaf,0x00,
+ 0xd2,0x24,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb0,0x00,0x05,0xff,0xf0,
+ 0x90,0x90,0xb1,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb2,0x00,0x05,0xff,0xf0,
+ 0x90,0x90,0xb3,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb4,0x00,0x05,
+ 0xff,0xf0,0x90,0x90,0xb5,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x90,0xb6,0x00,0x05,
+ 0xff,0xf0,0x90,0x90,0xb7,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x05,0xff,
+ 0xf0,0x90,0x90,0xb8,0x00,0x05,0xff,0xf0,0x90,0x90,0xb9,0x00,0x10,0x09,0x05,0xff,
+ 0xf0,0x90,0x90,0xba,0x00,0x05,0xff,0xf0,0x90,0x90,0xbb,0x00,0xd1,0x12,0x10,0x09,
+ 0x05,0xff,0xf0,0x90,0x90,0xbc,0x00,0x05,0xff,0xf0,0x90,0x90,0xbd,0x00,0x10,0x09,
+ 0x05,0xff,0xf0,0x90,0x90,0xbe,0x00,0x05,0xff,0xf0,0x90,0x90,0xbf,0x00,0xd2,0x24,
+ 0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,0x80,0x00,0x05,0xff,0xf0,0x90,0x91,
+ 0x81,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,0x82,0x00,0x05,0xff,0xf0,0x90,0x91,
+ 0x83,0x00,0xd1,0x12,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,0x84,0x00,0x05,0xff,0xf0,
+ 0x90,0x91,0x85,0x00,0x10,0x09,0x05,0xff,0xf0,0x90,0x91,0x86,0x00,0x05,0xff,0xf0,
+ 0x90,0x91,0x87,0x00,0x94,0x4c,0x93,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x05,0xff,
+ 0xf0,0x90,0x91,0x88,0x00,0x05,0xff,0xf0,0x90,0x91,0x89,0x00,0x10,0x09,0x05,0xff,
+ 0xf0,0x90,0x91,0x8a,0x00,0x05,0xff,0xf0,0x90,0x91,0x8b,0x00,0xd1,0x12,0x10,0x09,
+ 0x05,0xff,0xf0,0x90,0x91,0x8c,0x00,0x05,0xff,0xf0,0x90,0x91,0x8d,0x00,0x10,0x09,
+ 0x07,0xff,0xf0,0x90,0x91,0x8e,0x00,0x07,0xff,0xf0,0x90,0x91,0x8f,0x00,0x05,0x00,
+ 0x05,0x00,0xd0,0xa0,0xcf,0x86,0xd5,0x07,0x64,0x30,0x76,0x07,0x00,0xd4,0x07,0x63,
+ 0x3d,0x76,0x07,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,
+ 0x93,0x98,0x00,0x12,0xff,0xf0,0x90,0x93,0x99,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,
+ 0x93,0x9a,0x00,0x12,0xff,0xf0,0x90,0x93,0x9b,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,
+ 0xf0,0x90,0x93,0x9c,0x00,0x12,0xff,0xf0,0x90,0x93,0x9d,0x00,0x10,0x09,0x12,0xff,
+ 0xf0,0x90,0x93,0x9e,0x00,0x12,0xff,0xf0,0x90,0x93,0x9f,0x00,0xd2,0x24,0xd1,0x12,
+ 0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xa0,0x00,0x12,0xff,0xf0,0x90,0x93,0xa1,0x00,
+ 0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xa2,0x00,0x12,0xff,0xf0,0x90,0x93,0xa3,0x00,
+ 0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xa4,0x00,0x12,0xff,0xf0,0x90,0x93,
+ 0xa5,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xa6,0x00,0x12,0xff,0xf0,0x90,0x93,
+ 0xa7,0x00,0xcf,0x86,0xe5,0xc6,0x75,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,
+ 0x09,0x12,0xff,0xf0,0x90,0x93,0xa8,0x00,0x12,0xff,0xf0,0x90,0x93,0xa9,0x00,0x10,
+ 0x09,0x12,0xff,0xf0,0x90,0x93,0xaa,0x00,0x12,0xff,0xf0,0x90,0x93,0xab,0x00,0xd1,
+ 0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xac,0x00,0x12,0xff,0xf0,0x90,0x93,0xad,
+ 0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xae,0x00,0x12,0xff,0xf0,0x90,0x93,0xaf,
+ 0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb0,0x00,0x12,0xff,
+ 0xf0,0x90,0x93,0xb1,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb2,0x00,0x12,0xff,
+ 0xf0,0x90,0x93,0xb3,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb4,0x00,
+ 0x12,0xff,0xf0,0x90,0x93,0xb5,0x00,0x10,0x09,0x12,0xff,0xf0,0x90,0x93,0xb6,0x00,
+ 0x12,0xff,0xf0,0x90,0x93,0xb7,0x00,0x93,0x28,0x92,0x24,0xd1,0x12,0x10,0x09,0x12,
+ 0xff,0xf0,0x90,0x93,0xb8,0x00,0x12,0xff,0xf0,0x90,0x93,0xb9,0x00,0x10,0x09,0x12,
+ 0xff,0xf0,0x90,0x93,0xba,0x00,0x12,0xff,0xf0,0x90,0x93,0xbb,0x00,0x00,0x00,0x12,
+ 0x00,0xd4,0x1f,0xe3,0xdf,0x76,0xe2,0x6a,0x76,0xe1,0x09,0x76,0xe0,0xea,0x75,0xcf,
+ 0x86,0xe5,0xb7,0x75,0x94,0x0a,0xe3,0xa2,0x75,0x62,0x99,0x75,0x07,0x00,0x07,0x00,
+ 0xe3,0xde,0x78,0xe2,0xaf,0x78,0xd1,0x09,0xe0,0x4c,0x78,0xcf,0x06,0x0b,0x00,0xe0,
+ 0x7f,0x78,0xcf,0x86,0xe5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,
+ 0x09,0x11,0xff,0xf0,0x90,0xb3,0x80,0x00,0x11,0xff,0xf0,0x90,0xb3,0x81,0x00,0x10,
+ 0x09,0x11,0xff,0xf0,0x90,0xb3,0x82,0x00,0x11,0xff,0xf0,0x90,0xb3,0x83,0x00,0xd1,
+ 0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x84,0x00,0x11,0xff,0xf0,0x90,0xb3,0x85,
+ 0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x86,0x00,0x11,0xff,0xf0,0x90,0xb3,0x87,
+ 0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x88,0x00,0x11,0xff,
+ 0xf0,0x90,0xb3,0x89,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x8a,0x00,0x11,0xff,
+ 0xf0,0x90,0xb3,0x8b,0x00,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x8c,0x00,
+ 0x11,0xff,0xf0,0x90,0xb3,0x8d,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x8e,0x00,
+ 0x11,0xff,0xf0,0x90,0xb3,0x8f,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x11,
+ 0xff,0xf0,0x90,0xb3,0x90,0x00,0x11,0xff,0xf0,0x90,0xb3,0x91,0x00,0x10,0x09,0x11,
+ 0xff,0xf0,0x90,0xb3,0x92,0x00,0x11,0xff,0xf0,0x90,0xb3,0x93,0x00,0xd1,0x12,0x10,
+ 0x09,0x11,0xff,0xf0,0x90,0xb3,0x94,0x00,0x11,0xff,0xf0,0x90,0xb3,0x95,0x00,0x10,
+ 0x09,0x11,0xff,0xf0,0x90,0xb3,0x96,0x00,0x11,0xff,0xf0,0x90,0xb3,0x97,0x00,0xd2,
+ 0x24,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x98,0x00,0x11,0xff,0xf0,0x90,
+ 0xb3,0x99,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x9a,0x00,0x11,0xff,0xf0,0x90,
+ 0xb3,0x9b,0x00,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x9c,0x00,0x11,0xff,
+ 0xf0,0x90,0xb3,0x9d,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0x9e,0x00,0x11,0xff,
+ 0xf0,0x90,0xb3,0x9f,0x00,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x11,
+ 0xff,0xf0,0x90,0xb3,0xa0,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa1,0x00,0x10,0x09,0x11,
+ 0xff,0xf0,0x90,0xb3,0xa2,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa3,0x00,0xd1,0x12,0x10,
+ 0x09,0x11,0xff,0xf0,0x90,0xb3,0xa4,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa5,0x00,0x10,
+ 0x09,0x11,0xff,0xf0,0x90,0xb3,0xa6,0x00,0x11,0xff,0xf0,0x90,0xb3,0xa7,0x00,0xd2,
+ 0x24,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xa8,0x00,0x11,0xff,0xf0,0x90,
+ 0xb3,0xa9,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xaa,0x00,0x11,0xff,0xf0,0x90,
+ 0xb3,0xab,0x00,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xac,0x00,0x11,0xff,
+ 0xf0,0x90,0xb3,0xad,0x00,0x10,0x09,0x11,0xff,0xf0,0x90,0xb3,0xae,0x00,0x11,0xff,
+ 0xf0,0x90,0xb3,0xaf,0x00,0x93,0x23,0x92,0x1f,0xd1,0x12,0x10,0x09,0x11,0xff,0xf0,
+ 0x90,0xb3,0xb0,0x00,0x11,0xff,0xf0,0x90,0xb3,0xb1,0x00,0x10,0x09,0x11,0xff,0xf0,
+ 0x90,0xb3,0xb2,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x15,0xe4,0x91,
+ 0x7b,0xe3,0x9b,0x79,0xe2,0x94,0x78,0xe1,0xe4,0x77,0xe0,0x9d,0x77,0xcf,0x06,0x0c,
+ 0x00,0xe4,0xeb,0x7e,0xe3,0x44,0x7e,0xe2,0xed,0x7d,0xd1,0x0c,0xe0,0xb2,0x7d,0xcf,
+ 0x86,0x65,0x93,0x7d,0x14,0x00,0xe0,0xb6,0x7d,0xcf,0x86,0x55,0x04,0x00,0x00,0xd4,
+ 0x90,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x80,0x00,
+ 0x10,0xff,0xf0,0x91,0xa3,0x81,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x82,0x00,
+ 0x10,0xff,0xf0,0x91,0xa3,0x83,0x00,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,
+ 0x84,0x00,0x10,0xff,0xf0,0x91,0xa3,0x85,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,
+ 0x86,0x00,0x10,0xff,0xf0,0x91,0xa3,0x87,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x10,
+ 0xff,0xf0,0x91,0xa3,0x88,0x00,0x10,0xff,0xf0,0x91,0xa3,0x89,0x00,0x10,0x09,0x10,
+ 0xff,0xf0,0x91,0xa3,0x8a,0x00,0x10,0xff,0xf0,0x91,0xa3,0x8b,0x00,0xd1,0x12,0x10,
+ 0x09,0x10,0xff,0xf0,0x91,0xa3,0x8c,0x00,0x10,0xff,0xf0,0x91,0xa3,0x8d,0x00,0x10,
+ 0x09,0x10,0xff,0xf0,0x91,0xa3,0x8e,0x00,0x10,0xff,0xf0,0x91,0xa3,0x8f,0x00,0xd3,
+ 0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x90,0x00,0x10,0xff,
+ 0xf0,0x91,0xa3,0x91,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x92,0x00,0x10,0xff,
+ 0xf0,0x91,0xa3,0x93,0x00,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x94,0x00,
+ 0x10,0xff,0xf0,0x91,0xa3,0x95,0x00,0x10,0x09,0x10,0xff,0xf0,0x91,0xa3,0x96,0x00,
+ 0x10,0xff,0xf0,0x91,0xa3,0x97,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x10,0xff,0xf0,
+ 0x91,0xa3,0x98,0x00,0x10,0xff,0xf0,0x91,0xa3,0x99,0x00,0x10,0x09,0x10,0xff,0xf0,
+ 0x91,0xa3,0x9a,0x00,0x10,0xff,0xf0,0x91,0xa3,0x9b,0x00,0xd1,0x12,0x10,0x09,0x10,
+ 0xff,0xf0,0x91,0xa3,0x9c,0x00,0x10,0xff,0xf0,0x91,0xa3,0x9d,0x00,0x10,0x09,0x10,
+ 0xff,0xf0,0x91,0xa3,0x9e,0x00,0x10,0xff,0xf0,0x91,0xa3,0x9f,0x00,0xd1,0x11,0xe0,
+ 0x12,0x81,0xcf,0x86,0xe5,0x09,0x81,0xe4,0xd2,0x80,0xcf,0x06,0x00,0x00,0xe0,0xdb,
+ 0x82,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xd4,0x09,0xe3,0x10,0x81,0xcf,0x06,
+ 0x0c,0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xe2,0x3b,0x82,0xe1,0x16,0x82,0xd0,0x06,
+ 0xcf,0x06,0x00,0x00,0xcf,0x86,0xa5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,
+ 0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa0,0x00,0x14,0xff,0xf0,0x96,0xb9,0xa1,
+ 0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa2,0x00,0x14,0xff,0xf0,0x96,0xb9,0xa3,
+ 0x00,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa4,0x00,0x14,0xff,0xf0,0x96,
+ 0xb9,0xa5,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa6,0x00,0x14,0xff,0xf0,0x96,
+ 0xb9,0xa7,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xa8,0x00,
+ 0x14,0xff,0xf0,0x96,0xb9,0xa9,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xaa,0x00,
+ 0x14,0xff,0xf0,0x96,0xb9,0xab,0x00,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,
+ 0xac,0x00,0x14,0xff,0xf0,0x96,0xb9,0xad,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,
+ 0xae,0x00,0x14,0xff,0xf0,0x96,0xb9,0xaf,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,
+ 0x09,0x14,0xff,0xf0,0x96,0xb9,0xb0,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb1,0x00,0x10,
+ 0x09,0x14,0xff,0xf0,0x96,0xb9,0xb2,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb3,0x00,0xd1,
+ 0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xb4,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb5,
+ 0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xb6,0x00,0x14,0xff,0xf0,0x96,0xb9,0xb7,
+ 0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xb8,0x00,0x14,0xff,
+ 0xf0,0x96,0xb9,0xb9,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xba,0x00,0x14,0xff,
+ 0xf0,0x96,0xb9,0xbb,0x00,0xd1,0x12,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xbc,0x00,
+ 0x14,0xff,0xf0,0x96,0xb9,0xbd,0x00,0x10,0x09,0x14,0xff,0xf0,0x96,0xb9,0xbe,0x00,
+ 0x14,0xff,0xf0,0x96,0xb9,0xbf,0x00,0x14,0x00,0xd2,0x14,0xe1,0x25,0x82,0xe0,0x1c,
+ 0x82,0xcf,0x86,0xe5,0xdd,0x81,0xe4,0x9a,0x81,0xcf,0x06,0x12,0x00,0xd1,0x0b,0xe0,
+ 0x51,0x83,0xcf,0x86,0xcf,0x06,0x00,0x00,0xe0,0x95,0x8b,0xcf,0x86,0xd5,0x22,0xe4,
+ 0xd0,0x88,0xe3,0x93,0x88,0xe2,0x38,0x88,0xe1,0x31,0x88,0xe0,0x2a,0x88,0xcf,0x86,
+ 0xe5,0xfb,0x87,0xe4,0xe2,0x87,0x93,0x07,0x62,0xd1,0x87,0x12,0xe6,0x12,0xe6,0xe4,
+ 0x36,0x89,0xe3,0x2f,0x89,0xd2,0x09,0xe1,0xb8,0x88,0xcf,0x06,0x10,0x00,0xe1,0x1f,
+ 0x89,0xe0,0xec,0x88,0xcf,0x86,0xe5,0x21,0x01,0xd4,0x90,0xd3,0x48,0xd2,0x24,0xd1,
+ 0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xa2,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xa3,
+ 0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xa4,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xa5,
+ 0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xa6,0x00,0x12,0xff,0xf0,0x9e,
+ 0xa4,0xa7,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xa8,0x00,0x12,0xff,0xf0,0x9e,
+ 0xa4,0xa9,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xaa,0x00,
+ 0x12,0xff,0xf0,0x9e,0xa4,0xab,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xac,0x00,
+ 0x12,0xff,0xf0,0x9e,0xa4,0xad,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,
+ 0xae,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xaf,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,
+ 0xb0,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb1,0x00,0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,
+ 0x09,0x12,0xff,0xf0,0x9e,0xa4,0xb2,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb3,0x00,0x10,
+ 0x09,0x12,0xff,0xf0,0x9e,0xa4,0xb4,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb5,0x00,0xd1,
+ 0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xb6,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb7,
+ 0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xb8,0x00,0x12,0xff,0xf0,0x9e,0xa4,0xb9,
+ 0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xba,0x00,0x12,0xff,
+ 0xf0,0x9e,0xa4,0xbb,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xbc,0x00,0x12,0xff,
+ 0xf0,0x9e,0xa4,0xbd,0x00,0xd1,0x12,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa4,0xbe,0x00,
+ 0x12,0xff,0xf0,0x9e,0xa4,0xbf,0x00,0x10,0x09,0x12,0xff,0xf0,0x9e,0xa5,0x80,0x00,
+ 0x12,0xff,0xf0,0x9e,0xa5,0x81,0x00,0x94,0x1e,0x93,0x1a,0x92,0x16,0x91,0x12,0x10,
+ 0x09,0x12,0xff,0xf0,0x9e,0xa5,0x82,0x00,0x12,0xff,0xf0,0x9e,0xa5,0x83,0x00,0x12,
+ 0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ /* nfdi_c0100 */
+ 0x57,0x04,0x01,0x00,0xc6,0xe5,0xac,0x13,0xe4,0x41,0x0c,0xe3,0x7a,0x07,0xe2,0xf3,
+ 0x01,0xc1,0xd0,0x1f,0xcf,0x86,0x55,0x04,0x01,0x00,0x94,0x15,0x53,0x04,0x01,0x00,
+ 0x52,0x04,0x01,0x00,0x91,0x09,0x10,0x04,0x01,0x00,0x01,0xff,0x00,0x01,0x00,0x01,
+ 0x00,0xcf,0x86,0xd5,0xe4,0xd4,0x7c,0xd3,0x3c,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x41,0xcc,0x80,0x00,0x01,0xff,0x41,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x41,
+ 0xcc,0x82,0x00,0x01,0xff,0x41,0xcc,0x83,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,
+ 0xcc,0x88,0x00,0x01,0xff,0x41,0xcc,0x8a,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0x43,
+ 0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,0x80,0x00,0x01,
+ 0xff,0x45,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x82,0x00,0x01,0xff,0x45,
+ 0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x80,0x00,0x01,0xff,0x49,
+ 0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0x82,0x00,0x01,0xff,0x49,0xcc,0x88,
+ 0x00,0xd3,0x38,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x4e,0xcc,0x83,
+ 0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0x80,0x00,0x01,0xff,0x4f,0xcc,0x81,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0x82,0x00,0x01,0xff,0x4f,0xcc,0x83,0x00,0x10,
+ 0x08,0x01,0xff,0x4f,0xcc,0x88,0x00,0x01,0x00,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,
+ 0x00,0x01,0xff,0x55,0xcc,0x80,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0x81,0x00,0x01,
+ 0xff,0x55,0xcc,0x82,0x00,0x91,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0x88,0x00,0x01,
+ 0xff,0x59,0xcc,0x81,0x00,0x01,0x00,0xd4,0x7c,0xd3,0x3c,0xd2,0x20,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x61,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x81,0x00,0x10,0x08,0x01,
+ 0xff,0x61,0xcc,0x82,0x00,0x01,0xff,0x61,0xcc,0x83,0x00,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x61,0xcc,0x88,0x00,0x01,0xff,0x61,0xcc,0x8a,0x00,0x10,0x04,0x01,0x00,0x01,
+ 0xff,0x63,0xcc,0xa7,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x65,0xcc,0x80,
+ 0x00,0x01,0xff,0x65,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x65,0xcc,0x82,0x00,0x01,
+ 0xff,0x65,0xcc,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x80,0x00,0x01,
+ 0xff,0x69,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x69,0xcc,0x82,0x00,0x01,0xff,0x69,
+ 0xcc,0x88,0x00,0xd3,0x38,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x6e,
+ 0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x80,0x00,0x01,0xff,0x6f,0xcc,0x81,
+ 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x6f,0xcc,0x82,0x00,0x01,0xff,0x6f,0xcc,0x83,
+ 0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x88,0x00,0x01,0x00,0xd2,0x1c,0xd1,0x0c,0x10,
+ 0x04,0x01,0x00,0x01,0xff,0x75,0xcc,0x80,0x00,0x10,0x08,0x01,0xff,0x75,0xcc,0x81,
+ 0x00,0x01,0xff,0x75,0xcc,0x82,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x75,0xcc,0x88,
+ 0x00,0x01,0xff,0x79,0xcc,0x81,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0x79,0xcc,0x88,
+ 0x00,0xe1,0x9a,0x03,0xe0,0xd3,0x01,0xcf,0x86,0xd5,0xf4,0xd4,0x80,0xd3,0x40,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x84,
+ 0x00,0x10,0x08,0x01,0xff,0x41,0xcc,0x86,0x00,0x01,0xff,0x61,0xcc,0x86,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0xa8,0x00,0x01,0xff,0x61,0xcc,0xa8,0x00,0x10,
+ 0x08,0x01,0xff,0x43,0xcc,0x81,0x00,0x01,0xff,0x63,0xcc,0x81,0x00,0xd2,0x20,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x43,0xcc,0x82,0x00,0x01,0xff,0x63,0xcc,0x82,0x00,0x10,
+ 0x08,0x01,0xff,0x43,0xcc,0x87,0x00,0x01,0xff,0x63,0xcc,0x87,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x43,0xcc,0x8c,0x00,0x01,0xff,0x63,0xcc,0x8c,0x00,0x10,0x08,0x01,
+ 0xff,0x44,0xcc,0x8c,0x00,0x01,0xff,0x64,0xcc,0x8c,0x00,0xd3,0x34,0xd2,0x14,0x51,
+ 0x04,0x01,0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x84,0x00,0x01,0xff,0x65,0xcc,0x84,
+ 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,0x86,0x00,0x01,0xff,0x65,0xcc,0x86,
+ 0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x87,0x00,0x01,0xff,0x65,0xcc,0x87,0x00,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,0xa8,0x00,0x01,0xff,0x65,0xcc,0xa8,
+ 0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x8c,0x00,0x01,0xff,0x65,0xcc,0x8c,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x47,0xcc,0x82,0x00,0x01,0xff,0x67,0xcc,0x82,0x00,0x10,
+ 0x08,0x01,0xff,0x47,0xcc,0x86,0x00,0x01,0xff,0x67,0xcc,0x86,0x00,0xd4,0x74,0xd3,
+ 0x34,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x47,0xcc,0x87,0x00,0x01,0xff,0x67,
+ 0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x47,0xcc,0xa7,0x00,0x01,0xff,0x67,0xcc,0xa7,
+ 0x00,0x91,0x10,0x10,0x08,0x01,0xff,0x48,0xcc,0x82,0x00,0x01,0xff,0x68,0xcc,0x82,
+ 0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x83,0x00,0x01,
+ 0xff,0x69,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0x84,0x00,0x01,0xff,0x69,
+ 0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x86,0x00,0x01,0xff,0x69,
+ 0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0xa8,0x00,0x01,0xff,0x69,0xcc,0xa8,
+ 0x00,0xd3,0x30,0xd2,0x10,0x91,0x0c,0x10,0x08,0x01,0xff,0x49,0xcc,0x87,0x00,0x01,
+ 0x00,0x01,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4a,0xcc,0x82,0x00,0x01,0xff,0x6a,
+ 0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x4b,0xcc,0xa7,0x00,0x01,0xff,0x6b,0xcc,0xa7,
+ 0x00,0xd2,0x1c,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x4c,0xcc,0x81,0x00,0x10,
+ 0x08,0x01,0xff,0x6c,0xcc,0x81,0x00,0x01,0xff,0x4c,0xcc,0xa7,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x6c,0xcc,0xa7,0x00,0x01,0xff,0x4c,0xcc,0x8c,0x00,0x10,0x08,0x01,
+ 0xff,0x6c,0xcc,0x8c,0x00,0x01,0x00,0xcf,0x86,0xd5,0xd4,0xd4,0x60,0xd3,0x30,0xd2,
+ 0x10,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0x4e,0xcc,0x81,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x6e,0xcc,0x81,0x00,0x01,0xff,0x4e,0xcc,0xa7,0x00,0x10,
+ 0x08,0x01,0xff,0x6e,0xcc,0xa7,0x00,0x01,0xff,0x4e,0xcc,0x8c,0x00,0xd2,0x10,0x91,
+ 0x0c,0x10,0x08,0x01,0xff,0x6e,0xcc,0x8c,0x00,0x01,0x00,0x01,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x4f,0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc,0x84,0x00,0x10,0x08,0x01,
+ 0xff,0x4f,0xcc,0x86,0x00,0x01,0xff,0x6f,0xcc,0x86,0x00,0xd3,0x34,0xd2,0x14,0x91,
+ 0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0x8b,0x00,0x01,0xff,0x6f,0xcc,0x8b,0x00,0x01,
+ 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x52,0xcc,0x81,0x00,0x01,0xff,0x72,0xcc,0x81,
+ 0x00,0x10,0x08,0x01,0xff,0x52,0xcc,0xa7,0x00,0x01,0xff,0x72,0xcc,0xa7,0x00,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x52,0xcc,0x8c,0x00,0x01,0xff,0x72,0xcc,0x8c,
+ 0x00,0x10,0x08,0x01,0xff,0x53,0xcc,0x81,0x00,0x01,0xff,0x73,0xcc,0x81,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x53,0xcc,0x82,0x00,0x01,0xff,0x73,0xcc,0x82,0x00,0x10,
+ 0x08,0x01,0xff,0x53,0xcc,0xa7,0x00,0x01,0xff,0x73,0xcc,0xa7,0x00,0xd4,0x74,0xd3,
+ 0x34,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x53,0xcc,0x8c,0x00,0x01,0xff,0x73,
+ 0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x54,0xcc,0xa7,0x00,0x01,0xff,0x74,0xcc,0xa7,
+ 0x00,0x91,0x10,0x10,0x08,0x01,0xff,0x54,0xcc,0x8c,0x00,0x01,0xff,0x74,0xcc,0x8c,
+ 0x00,0x01,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0x83,0x00,0x01,
+ 0xff,0x75,0xcc,0x83,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0x84,0x00,0x01,0xff,0x75,
+ 0xcc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0x86,0x00,0x01,0xff,0x75,
+ 0xcc,0x86,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0x8a,0x00,0x01,0xff,0x75,0xcc,0x8a,
+ 0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0x8b,0x00,0x01,
+ 0xff,0x75,0xcc,0x8b,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0xa8,0x00,0x01,0xff,0x75,
+ 0xcc,0xa8,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc,0x82,0x00,0x01,0xff,0x77,
+ 0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x59,0xcc,0x82,0x00,0x01,0xff,0x79,0xcc,0x82,
+ 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x59,0xcc,0x88,0x00,0x01,0xff,0x5a,
+ 0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x81,0x00,0x01,0xff,0x5a,0xcc,0x87,
+ 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x7a,0xcc,0x87,0x00,0x01,0xff,0x5a,0xcc,0x8c,
+ 0x00,0x10,0x08,0x01,0xff,0x7a,0xcc,0x8c,0x00,0x01,0x00,0xd0,0x4a,0xcf,0x86,0x55,
+ 0x04,0x01,0x00,0xd4,0x2c,0xd3,0x18,0x92,0x14,0x91,0x10,0x10,0x08,0x01,0xff,0x4f,
+ 0xcc,0x9b,0x00,0x01,0xff,0x6f,0xcc,0x9b,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,
+ 0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0x55,0xcc,0x9b,0x00,0x93,
+ 0x14,0x92,0x10,0x91,0x0c,0x10,0x08,0x01,0xff,0x75,0xcc,0x9b,0x00,0x01,0x00,0x01,
+ 0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0xb4,0xd4,0x24,0x53,0x04,0x01,0x00,0x52,
+ 0x04,0x01,0x00,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0x41,0xcc,0x8c,0x00,0x10,
+ 0x08,0x01,0xff,0x61,0xcc,0x8c,0x00,0x01,0xff,0x49,0xcc,0x8c,0x00,0xd3,0x46,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x69,0xcc,0x8c,0x00,0x01,0xff,0x4f,0xcc,0x8c,
+ 0x00,0x10,0x08,0x01,0xff,0x6f,0xcc,0x8c,0x00,0x01,0xff,0x55,0xcc,0x8c,0x00,0xd1,
+ 0x12,0x10,0x08,0x01,0xff,0x75,0xcc,0x8c,0x00,0x01,0xff,0x55,0xcc,0x88,0xcc,0x84,
+ 0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x84,0x00,0x01,0xff,0x55,0xcc,0x88,
+ 0xcc,0x81,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,0xcc,0x81,
+ 0x00,0x01,0xff,0x55,0xcc,0x88,0xcc,0x8c,0x00,0x10,0x0a,0x01,0xff,0x75,0xcc,0x88,
+ 0xcc,0x8c,0x00,0x01,0xff,0x55,0xcc,0x88,0xcc,0x80,0x00,0xd1,0x0e,0x10,0x0a,0x01,
+ 0xff,0x75,0xcc,0x88,0xcc,0x80,0x00,0x01,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x88,
+ 0xcc,0x84,0x00,0x01,0xff,0x61,0xcc,0x88,0xcc,0x84,0x00,0xd4,0x80,0xd3,0x3a,0xd2,
+ 0x26,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0x87,0xcc,0x84,0x00,0x01,0xff,0x61,
+ 0xcc,0x87,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xc3,0x86,0xcc,0x84,0x00,0x01,0xff,
+ 0xc3,0xa6,0xcc,0x84,0x00,0x51,0x04,0x01,0x00,0x10,0x08,0x01,0xff,0x47,0xcc,0x8c,
+ 0x00,0x01,0xff,0x67,0xcc,0x8c,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x4b,
+ 0xcc,0x8c,0x00,0x01,0xff,0x6b,0xcc,0x8c,0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0xa8,
+ 0x00,0x01,0xff,0x6f,0xcc,0xa8,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0xa8,
+ 0xcc,0x84,0x00,0x01,0xff,0x6f,0xcc,0xa8,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xc6,
+ 0xb7,0xcc,0x8c,0x00,0x01,0xff,0xca,0x92,0xcc,0x8c,0x00,0xd3,0x24,0xd2,0x10,0x91,
+ 0x0c,0x10,0x08,0x01,0xff,0x6a,0xcc,0x8c,0x00,0x01,0x00,0x01,0x00,0x91,0x10,0x10,
+ 0x08,0x01,0xff,0x47,0xcc,0x81,0x00,0x01,0xff,0x67,0xcc,0x81,0x00,0x04,0x00,0xd2,
+ 0x24,0xd1,0x10,0x10,0x08,0x04,0xff,0x4e,0xcc,0x80,0x00,0x04,0xff,0x6e,0xcc,0x80,
+ 0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x8a,0xcc,0x81,0x00,0x01,0xff,0x61,0xcc,0x8a,
+ 0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xc3,0x86,0xcc,0x81,0x00,0x01,0xff,
+ 0xc3,0xa6,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xc3,0x98,0xcc,0x81,0x00,0x01,0xff,
+ 0xc3,0xb8,0xcc,0x81,0x00,0xe2,0x07,0x02,0xe1,0xae,0x01,0xe0,0x93,0x01,0xcf,0x86,
+ 0xd5,0xf4,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,
+ 0x8f,0x00,0x01,0xff,0x61,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x41,0xcc,0x91,0x00,
+ 0x01,0xff,0x61,0xcc,0x91,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,0xcc,0x8f,0x00,
+ 0x01,0xff,0x65,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x45,0xcc,0x91,0x00,0x01,0xff,
+ 0x65,0xcc,0x91,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x8f,0x00,
+ 0x01,0xff,0x69,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0x91,0x00,0x01,0xff,
+ 0x69,0xcc,0x91,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0x8f,0x00,0x01,0xff,
+ 0x6f,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0x91,0x00,0x01,0xff,0x6f,0xcc,
+ 0x91,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x52,0xcc,0x8f,0x00,
+ 0x01,0xff,0x72,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x52,0xcc,0x91,0x00,0x01,0xff,
+ 0x72,0xcc,0x91,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0x8f,0x00,0x01,0xff,
+ 0x75,0xcc,0x8f,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0x91,0x00,0x01,0xff,0x75,0xcc,
+ 0x91,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x04,0xff,0x53,0xcc,0xa6,0x00,0x04,0xff,
+ 0x73,0xcc,0xa6,0x00,0x10,0x08,0x04,0xff,0x54,0xcc,0xa6,0x00,0x04,0xff,0x74,0xcc,
+ 0xa6,0x00,0x51,0x04,0x04,0x00,0x10,0x08,0x04,0xff,0x48,0xcc,0x8c,0x00,0x04,0xff,
+ 0x68,0xcc,0x8c,0x00,0xd4,0x68,0xd3,0x20,0xd2,0x0c,0x91,0x08,0x10,0x04,0x06,0x00,
+ 0x07,0x00,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x08,0x04,0xff,0x41,0xcc,0x87,0x00,
+ 0x04,0xff,0x61,0xcc,0x87,0x00,0xd2,0x24,0xd1,0x10,0x10,0x08,0x04,0xff,0x45,0xcc,
+ 0xa7,0x00,0x04,0xff,0x65,0xcc,0xa7,0x00,0x10,0x0a,0x04,0xff,0x4f,0xcc,0x88,0xcc,
+ 0x84,0x00,0x04,0xff,0x6f,0xcc,0x88,0xcc,0x84,0x00,0xd1,0x14,0x10,0x0a,0x04,0xff,
+ 0x4f,0xcc,0x83,0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc,0x83,0xcc,0x84,0x00,0x10,0x08,
+ 0x04,0xff,0x4f,0xcc,0x87,0x00,0x04,0xff,0x6f,0xcc,0x87,0x00,0x93,0x30,0xd2,0x24,
+ 0xd1,0x14,0x10,0x0a,0x04,0xff,0x4f,0xcc,0x87,0xcc,0x84,0x00,0x04,0xff,0x6f,0xcc,
+ 0x87,0xcc,0x84,0x00,0x10,0x08,0x04,0xff,0x59,0xcc,0x84,0x00,0x04,0xff,0x79,0xcc,
+ 0x84,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x08,0x00,0x08,0x00,0xcf,0x86,
+ 0x95,0x14,0x94,0x10,0x93,0x0c,0x92,0x08,0x11,0x04,0x08,0x00,0x09,0x00,0x09,0x00,
+ 0x09,0x00,0x01,0x00,0x01,0x00,0xd0,0x22,0xcf,0x86,0x55,0x04,0x01,0x00,0x94,0x18,
+ 0x53,0x04,0x01,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x04,0x00,
+ 0x11,0x04,0x04,0x00,0x07,0x00,0x01,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x01,0x00,
+ 0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,
+ 0x04,0x00,0x94,0x18,0x53,0x04,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x04,0x00,
+ 0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x07,0x00,0x07,0x00,0xe1,0x35,0x01,0xd0,
+ 0x72,0xcf,0x86,0xd5,0x24,0x54,0x04,0x01,0xe6,0xd3,0x10,0x52,0x04,0x01,0xe6,0x91,
+ 0x08,0x10,0x04,0x01,0xe6,0x01,0xe8,0x01,0xdc,0x92,0x0c,0x51,0x04,0x01,0xdc,0x10,
+ 0x04,0x01,0xe8,0x01,0xd8,0x01,0xdc,0xd4,0x2c,0xd3,0x1c,0xd2,0x10,0xd1,0x08,0x10,
+ 0x04,0x01,0xdc,0x01,0xca,0x10,0x04,0x01,0xca,0x01,0xdc,0x51,0x04,0x01,0xdc,0x10,
+ 0x04,0x01,0xdc,0x01,0xca,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0xca,0x01,0xdc,0x01,
+ 0xdc,0x01,0xdc,0xd3,0x08,0x12,0x04,0x01,0xdc,0x01,0x01,0xd2,0x0c,0x91,0x08,0x10,
+ 0x04,0x01,0x01,0x01,0xdc,0x01,0xdc,0x91,0x08,0x10,0x04,0x01,0xdc,0x01,0xe6,0x01,
+ 0xe6,0xcf,0x86,0xd5,0x7f,0xd4,0x47,0xd3,0x2e,0xd2,0x19,0xd1,0x0e,0x10,0x07,0x01,
+ 0xff,0xcc,0x80,0x00,0x01,0xff,0xcc,0x81,0x00,0x10,0x04,0x01,0xe6,0x01,0xff,0xcc,
+ 0x93,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xcc,0x88,0xcc,0x81,0x00,0x01,0xf0,0x10,
+ 0x04,0x04,0xe6,0x04,0xdc,0xd2,0x08,0x11,0x04,0x04,0xdc,0x04,0xe6,0xd1,0x08,0x10,
+ 0x04,0x04,0xe6,0x04,0xdc,0x10,0x04,0x04,0xdc,0x06,0xff,0x00,0xd3,0x18,0xd2,0x0c,
+ 0x51,0x04,0x07,0xe6,0x10,0x04,0x07,0xe6,0x07,0xdc,0x51,0x04,0x07,0xdc,0x10,0x04,
+ 0x07,0xdc,0x07,0xe6,0xd2,0x10,0xd1,0x08,0x10,0x04,0x08,0xe8,0x08,0xdc,0x10,0x04,
+ 0x08,0xdc,0x08,0xe6,0xd1,0x08,0x10,0x04,0x08,0xe9,0x07,0xea,0x10,0x04,0x07,0xea,
+ 0x07,0xe9,0xd4,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x01,0xea,0x10,0x04,0x04,0xe9,
+ 0x06,0xe6,0x06,0xe6,0x06,0xe6,0xd3,0x13,0x52,0x04,0x0a,0x00,0x91,0x0b,0x10,0x07,
+ 0x01,0xff,0xca,0xb9,0x00,0x01,0x00,0x0a,0x00,0xd2,0x0c,0x51,0x04,0x00,0x00,0x10,
+ 0x04,0x01,0x00,0x09,0x00,0x51,0x04,0x09,0x00,0x10,0x06,0x01,0xff,0x3b,0x00,0x10,
+ 0x00,0xd0,0xe1,0xcf,0x86,0xd5,0x7a,0xd4,0x5f,0xd3,0x21,0x52,0x04,0x00,0x00,0xd1,
+ 0x0d,0x10,0x04,0x01,0x00,0x01,0xff,0xc2,0xa8,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,
+ 0xce,0x91,0xcc,0x81,0x00,0x01,0xff,0xc2,0xb7,0x00,0xd2,0x1f,0xd1,0x12,0x10,0x09,
+ 0x01,0xff,0xce,0x95,0xcc,0x81,0x00,0x01,0xff,0xce,0x97,0xcc,0x81,0x00,0x10,0x09,
+ 0x01,0xff,0xce,0x99,0xcc,0x81,0x00,0x00,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xce,
+ 0x9f,0xcc,0x81,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xa5,0xcc,0x81,0x00,0x01,
+ 0xff,0xce,0xa9,0xcc,0x81,0x00,0x93,0x17,0x92,0x13,0x91,0x0f,0x10,0x0b,0x01,0xff,
+ 0xce,0xb9,0xcc,0x88,0xcc,0x81,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,
+ 0x4a,0xd3,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x01,
+ 0x00,0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xce,0x99,0xcc,0x88,0x00,
+ 0x01,0xff,0xce,0xa5,0xcc,0x88,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,
+ 0x81,0x00,0x01,0xff,0xce,0xb5,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,
+ 0x81,0x00,0x01,0xff,0xce,0xb9,0xcc,0x81,0x00,0x93,0x17,0x92,0x13,0x91,0x0f,0x10,
+ 0x0b,0x01,0xff,0xcf,0x85,0xcc,0x88,0xcc,0x81,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
+ 0x01,0x00,0xcf,0x86,0xd5,0x7b,0xd4,0x39,0x53,0x04,0x01,0x00,0xd2,0x16,0x51,0x04,
+ 0x01,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x88,0x00,0x01,0xff,0xcf,0x85,0xcc,
+ 0x88,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00,0x01,0xff,0xcf,
+ 0x85,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xcf,0x89,0xcc,0x81,0x00,0x0a,0x00,0xd3,
+ 0x26,0xd2,0x11,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xcf,0x92,0xcc,
+ 0x81,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xcf,0x92,0xcc,0x88,0x00,0x01,0x00,0x10,
+ 0x04,0x01,0x00,0x04,0x00,0xd2,0x0c,0x51,0x04,0x06,0x00,0x10,0x04,0x01,0x00,0x04,
+ 0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x10,0x04,0x01,0x00,0x04,0x00,0xd4,
+ 0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x01,0x00,0x01,
+ 0x00,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x05,0x00,0x10,0x04,0x06,
+ 0x00,0x07,0x00,0x12,0x04,0x07,0x00,0x08,0x00,0xe3,0x47,0x04,0xe2,0xbe,0x02,0xe1,
+ 0x07,0x01,0xd0,0x8b,0xcf,0x86,0xd5,0x6c,0xd4,0x53,0xd3,0x30,0xd2,0x1f,0xd1,0x12,
+ 0x10,0x09,0x04,0xff,0xd0,0x95,0xcc,0x80,0x00,0x01,0xff,0xd0,0x95,0xcc,0x88,0x00,
+ 0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0x93,0xcc,0x81,0x00,0x51,0x04,0x01,0x00,0x10,
+ 0x04,0x01,0x00,0x01,0xff,0xd0,0x86,0xcc,0x88,0x00,0x52,0x04,0x01,0x00,0xd1,0x12,
+ 0x10,0x09,0x01,0xff,0xd0,0x9a,0xcc,0x81,0x00,0x04,0xff,0xd0,0x98,0xcc,0x80,0x00,
+ 0x10,0x09,0x01,0xff,0xd0,0xa3,0xcc,0x86,0x00,0x01,0x00,0x53,0x04,0x01,0x00,0x92,
+ 0x11,0x91,0x0d,0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0x98,0xcc,0x86,0x00,0x01,0x00,
+ 0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x92,0x11,0x91,0x0d,0x10,0x04,
+ 0x01,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x86,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,
+ 0x57,0x54,0x04,0x01,0x00,0xd3,0x30,0xd2,0x1f,0xd1,0x12,0x10,0x09,0x04,0xff,0xd0,
+ 0xb5,0xcc,0x80,0x00,0x01,0xff,0xd0,0xb5,0xcc,0x88,0x00,0x10,0x04,0x01,0x00,0x01,
+ 0xff,0xd0,0xb3,0xcc,0x81,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,
+ 0xd1,0x96,0xcc,0x88,0x00,0x52,0x04,0x01,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,
+ 0xba,0xcc,0x81,0x00,0x04,0xff,0xd0,0xb8,0xcc,0x80,0x00,0x10,0x09,0x01,0xff,0xd1,
+ 0x83,0xcc,0x86,0x00,0x01,0x00,0x54,0x04,0x01,0x00,0x93,0x1a,0x52,0x04,0x01,0x00,
+ 0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xd1,0xb4,0xcc,0x8f,0x00,0x01,0xff,0xd1,
+ 0xb5,0xcc,0x8f,0x00,0x01,0x00,0xd0,0x2e,0xcf,0x86,0x95,0x28,0x94,0x24,0xd3,0x18,
+ 0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xe6,0x51,0x04,0x01,0xe6,
+ 0x10,0x04,0x01,0xe6,0x0a,0xe6,0x92,0x08,0x11,0x04,0x04,0x00,0x06,0x00,0x04,0x00,
+ 0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0xbe,0xd4,0x4a,0xd3,0x2a,0xd2,0x1a,0xd1,0x0d,
+ 0x10,0x04,0x01,0x00,0x01,0xff,0xd0,0x96,0xcc,0x86,0x00,0x10,0x09,0x01,0xff,0xd0,
+ 0xb6,0xcc,0x86,0x00,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x10,0x04,
+ 0x06,0x00,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x10,0x04,
+ 0x06,0x00,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x10,0x04,0x06,0x00,
+ 0x09,0x00,0xd3,0x3a,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0x90,0xcc,0x86,
+ 0x00,0x01,0xff,0xd0,0xb0,0xcc,0x86,0x00,0x10,0x09,0x01,0xff,0xd0,0x90,0xcc,0x88,
+ 0x00,0x01,0xff,0xd0,0xb0,0xcc,0x88,0x00,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,
+ 0xd0,0x95,0xcc,0x86,0x00,0x01,0xff,0xd0,0xb5,0xcc,0x86,0x00,0xd2,0x16,0x51,0x04,
+ 0x01,0x00,0x10,0x09,0x01,0xff,0xd3,0x98,0xcc,0x88,0x00,0x01,0xff,0xd3,0x99,0xcc,
+ 0x88,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd0,0x96,0xcc,0x88,0x00,0x01,0xff,0xd0,
+ 0xb6,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,0xd0,0x97,0xcc,0x88,0x00,0x01,0xff,0xd0,
+ 0xb7,0xcc,0x88,0x00,0xd4,0x74,0xd3,0x3a,0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,
+ 0x01,0xff,0xd0,0x98,0xcc,0x84,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x84,0x00,0xd1,0x12,
+ 0x10,0x09,0x01,0xff,0xd0,0x98,0xcc,0x88,0x00,0x01,0xff,0xd0,0xb8,0xcc,0x88,0x00,
+ 0x10,0x09,0x01,0xff,0xd0,0x9e,0xcc,0x88,0x00,0x01,0xff,0xd0,0xbe,0xcc,0x88,0x00,
+ 0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xd3,0xa8,0xcc,0x88,0x00,0x01,
+ 0xff,0xd3,0xa9,0xcc,0x88,0x00,0xd1,0x12,0x10,0x09,0x04,0xff,0xd0,0xad,0xcc,0x88,
+ 0x00,0x04,0xff,0xd1,0x8d,0xcc,0x88,0x00,0x10,0x09,0x01,0xff,0xd0,0xa3,0xcc,0x84,
+ 0x00,0x01,0xff,0xd1,0x83,0xcc,0x84,0x00,0xd3,0x3a,0xd2,0x24,0xd1,0x12,0x10,0x09,
+ 0x01,0xff,0xd0,0xa3,0xcc,0x88,0x00,0x01,0xff,0xd1,0x83,0xcc,0x88,0x00,0x10,0x09,
+ 0x01,0xff,0xd0,0xa3,0xcc,0x8b,0x00,0x01,0xff,0xd1,0x83,0xcc,0x8b,0x00,0x91,0x12,
+ 0x10,0x09,0x01,0xff,0xd0,0xa7,0xcc,0x88,0x00,0x01,0xff,0xd1,0x87,0xcc,0x88,0x00,
+ 0x08,0x00,0x92,0x16,0x91,0x12,0x10,0x09,0x01,0xff,0xd0,0xab,0xcc,0x88,0x00,0x01,
+ 0xff,0xd1,0x8b,0xcc,0x88,0x00,0x09,0x00,0x09,0x00,0xd1,0x74,0xd0,0x36,0xcf,0x86,
+ 0xd5,0x10,0x54,0x04,0x06,0x00,0x93,0x08,0x12,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,
+ 0xd4,0x10,0x93,0x0c,0x52,0x04,0x0a,0x00,0x11,0x04,0x0b,0x00,0x0c,0x00,0x10,0x00,
+ 0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
+ 0x01,0x00,0xcf,0x86,0xd5,0x24,0x54,0x04,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,
+ 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,
+ 0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x14,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0xba,
+ 0xcf,0x86,0xd5,0x4c,0xd4,0x24,0x53,0x04,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,
+ 0x14,0x00,0x01,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,
+ 0x10,0x00,0x10,0x04,0x10,0x00,0x0d,0x00,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,
+ 0x00,0x00,0x02,0xdc,0x02,0xe6,0x51,0x04,0x02,0xe6,0x10,0x04,0x02,0xdc,0x02,0xe6,
+ 0x92,0x0c,0x51,0x04,0x02,0xe6,0x10,0x04,0x02,0xde,0x02,0xdc,0x02,0xe6,0xd4,0x2c,
+ 0xd3,0x10,0x92,0x0c,0x51,0x04,0x02,0xe6,0x10,0x04,0x08,0xdc,0x02,0xdc,0x02,0xdc,
+ 0xd2,0x0c,0x51,0x04,0x02,0xe6,0x10,0x04,0x02,0xdc,0x02,0xe6,0xd1,0x08,0x10,0x04,
+ 0x02,0xe6,0x02,0xde,0x10,0x04,0x02,0xe4,0x02,0xe6,0xd3,0x20,0xd2,0x10,0xd1,0x08,
+ 0x10,0x04,0x01,0x0a,0x01,0x0b,0x10,0x04,0x01,0x0c,0x01,0x0d,0xd1,0x08,0x10,0x04,
+ 0x01,0x0e,0x01,0x0f,0x10,0x04,0x01,0x10,0x01,0x11,0xd2,0x10,0xd1,0x08,0x10,0x04,
+ 0x01,0x12,0x01,0x13,0x10,0x04,0x09,0x13,0x01,0x14,0xd1,0x08,0x10,0x04,0x01,0x15,
+ 0x01,0x16,0x10,0x04,0x01,0x00,0x01,0x17,0xcf,0x86,0xd5,0x28,0x94,0x24,0x93,0x20,
+ 0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x01,0x18,0x10,0x04,0x01,0x19,0x01,0x00,
+ 0xd1,0x08,0x10,0x04,0x02,0xe6,0x08,0xdc,0x10,0x04,0x08,0x00,0x08,0x12,0x00,0x00,
+ 0x01,0x00,0xd4,0x1c,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,
+ 0x01,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x14,0x00,0x93,0x10,
+ 0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe2,0xfb,0x01,0xe1,0x2b,0x01,0xd0,0xa8,0xcf,0x86,0xd5,0x55,0xd4,0x28,0xd3,0x10,
+ 0x52,0x04,0x07,0x00,0x91,0x08,0x10,0x04,0x0d,0x00,0x10,0x00,0x0a,0x00,0xd2,0x0c,
+ 0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x00,0x08,0x00,0x91,0x08,0x10,0x04,0x01,0x00,
+ 0x07,0x00,0x07,0x00,0xd3,0x0c,0x52,0x04,0x07,0xe6,0x11,0x04,0x07,0xe6,0x0a,0xe6,
+ 0xd2,0x10,0xd1,0x08,0x10,0x04,0x0a,0x1e,0x0a,0x1f,0x10,0x04,0x0a,0x20,0x01,0x00,
+ 0xd1,0x09,0x10,0x05,0x0f,0xff,0x00,0x00,0x00,0x10,0x04,0x08,0x00,0x01,0x00,0xd4,
+ 0x3d,0x93,0x39,0xd2,0x1a,0xd1,0x08,0x10,0x04,0x0c,0x00,0x01,0x00,0x10,0x09,0x01,
+ 0xff,0xd8,0xa7,0xd9,0x93,0x00,0x01,0xff,0xd8,0xa7,0xd9,0x94,0x00,0xd1,0x12,0x10,
+ 0x09,0x01,0xff,0xd9,0x88,0xd9,0x94,0x00,0x01,0xff,0xd8,0xa7,0xd9,0x95,0x00,0x10,
+ 0x09,0x01,0xff,0xd9,0x8a,0xd9,0x94,0x00,0x01,0x00,0x01,0x00,0x53,0x04,0x01,0x00,
+ 0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x0a,0x00,0x0a,0x00,0xcf,0x86,
+ 0xd5,0x5c,0xd4,0x20,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,
+ 0x01,0x00,0x01,0x1b,0xd1,0x08,0x10,0x04,0x01,0x1c,0x01,0x1d,0x10,0x04,0x01,0x1e,
+ 0x01,0x1f,0xd3,0x20,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x20,0x01,0x21,0x10,0x04,
+ 0x01,0x22,0x04,0xe6,0xd1,0x08,0x10,0x04,0x04,0xe6,0x04,0xdc,0x10,0x04,0x07,0xdc,
+ 0x07,0xe6,0xd2,0x0c,0x91,0x08,0x10,0x04,0x07,0xe6,0x08,0xe6,0x08,0xe6,0xd1,0x08,
+ 0x10,0x04,0x08,0xdc,0x08,0xe6,0x10,0x04,0x08,0xe6,0x0c,0xdc,0xd4,0x10,0x53,0x04,
+ 0x01,0x00,0x52,0x04,0x01,0x00,0x11,0x04,0x01,0x00,0x06,0x00,0x93,0x10,0x92,0x0c,
+ 0x91,0x08,0x10,0x04,0x01,0x23,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0x22,
+ 0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x08,
+ 0x11,0x04,0x04,0x00,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x04,0x00,
+ 0xcf,0x86,0xd5,0x5b,0xd4,0x2e,0xd3,0x1e,0x92,0x1a,0xd1,0x0d,0x10,0x09,0x01,0xff,
+ 0xdb,0x95,0xd9,0x94,0x00,0x01,0x00,0x10,0x09,0x01,0xff,0xdb,0x81,0xd9,0x94,0x00,
+ 0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,
+ 0x04,0x00,0xd3,0x19,0xd2,0x11,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,
+ 0xdb,0x92,0xd9,0x94,0x00,0x11,0x04,0x01,0x00,0x01,0xe6,0x52,0x04,0x01,0xe6,0xd1,
+ 0x08,0x10,0x04,0x01,0xe6,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xe6,0xd4,0x38,0xd3,
+ 0x1c,0xd2,0x0c,0x51,0x04,0x01,0xe6,0x10,0x04,0x01,0xe6,0x01,0xdc,0xd1,0x08,0x10,
+ 0x04,0x01,0xe6,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xe6,0xd2,0x10,0xd1,0x08,0x10,
+ 0x04,0x01,0xe6,0x01,0x00,0x10,0x04,0x01,0xdc,0x01,0xe6,0x91,0x08,0x10,0x04,0x01,
+ 0xe6,0x01,0xdc,0x07,0x00,0x53,0x04,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x04,
+ 0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x07,0x00,0xd1,0xc8,0xd0,0x76,0xcf,
+ 0x86,0xd5,0x28,0xd4,0x14,0x53,0x04,0x04,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,
+ 0x00,0x10,0x04,0x00,0x00,0x04,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x04,
+ 0x00,0x04,0x24,0x04,0x00,0x04,0x00,0x04,0x00,0xd4,0x14,0x53,0x04,0x04,0x00,0x52,
+ 0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x07,0x00,0x07,0x00,0xd3,0x1c,0xd2,
+ 0x0c,0x91,0x08,0x10,0x04,0x04,0xe6,0x04,0xdc,0x04,0xe6,0xd1,0x08,0x10,0x04,0x04,
+ 0xdc,0x04,0xe6,0x10,0x04,0x04,0xe6,0x04,0xdc,0xd2,0x0c,0x51,0x04,0x04,0xdc,0x10,
+ 0x04,0x04,0xe6,0x04,0xdc,0xd1,0x08,0x10,0x04,0x04,0xdc,0x04,0xe6,0x10,0x04,0x04,
+ 0xdc,0x04,0xe6,0xcf,0x86,0xd5,0x3c,0x94,0x38,0xd3,0x1c,0xd2,0x0c,0x51,0x04,0x04,
+ 0xe6,0x10,0x04,0x04,0xdc,0x04,0xe6,0xd1,0x08,0x10,0x04,0x04,0xdc,0x04,0xe6,0x10,
+ 0x04,0x04,0xdc,0x04,0xe6,0xd2,0x10,0xd1,0x08,0x10,0x04,0x04,0xdc,0x04,0xe6,0x10,
+ 0x04,0x04,0xe6,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x07,0x00,0x07,0x00,0x08,
+ 0x00,0x94,0x10,0x53,0x04,0x08,0x00,0x52,0x04,0x08,0x00,0x11,0x04,0x08,0x00,0x0a,
+ 0x00,0x0a,0x00,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00,0x93,
+ 0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xcf,0x86,0x55,0x04,0x09,0x00,0xd4,0x14,0x53,0x04,0x09,0x00,0x92,0x0c,0x51,
+ 0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x09,0xe6,0x09,0xe6,0xd3,0x10,0x92,0x0c,0x51,
+ 0x04,0x09,0xe6,0x10,0x04,0x09,0xdc,0x09,0xe6,0x09,0x00,0xd2,0x0c,0x51,0x04,0x09,
+ 0x00,0x10,0x04,0x09,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x14,0xdc,0x14,
+ 0x00,0xe4,0xf8,0x57,0xe3,0x45,0x3f,0xe2,0xf4,0x3e,0xe1,0xc7,0x2c,0xe0,0x21,0x10,
+ 0xcf,0x86,0xc5,0xe4,0x80,0x08,0xe3,0xcb,0x03,0xe2,0x61,0x01,0xd1,0x94,0xd0,0x5a,
+ 0xcf,0x86,0xd5,0x20,0x54,0x04,0x0b,0x00,0xd3,0x0c,0x52,0x04,0x0b,0x00,0x11,0x04,
+ 0x0b,0x00,0x0b,0xe6,0x92,0x0c,0x51,0x04,0x0b,0xe6,0x10,0x04,0x0b,0x00,0x0b,0xe6,
+ 0x0b,0xe6,0xd4,0x24,0xd3,0x10,0x52,0x04,0x0b,0xe6,0x91,0x08,0x10,0x04,0x0b,0x00,
+ 0x0b,0xe6,0x0b,0xe6,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0xe6,0x0b,0xe6,
+ 0x11,0x04,0x0b,0xe6,0x00,0x00,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,0x04,
+ 0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0xcf,0x86,0xd5,0x20,0x54,0x04,0x0c,0x00,
+ 0x53,0x04,0x0c,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x0c,0xdc,0x0c,0xdc,
+ 0x51,0x04,0x00,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x94,0x14,0x53,0x04,0x13,0x00,
+ 0x92,0x0c,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xd0,0x4a,0xcf,0x86,0x55,0x04,0x00,0x00,0xd4,0x20,0xd3,0x10,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x0d,0x00,0x10,0x00,0x0d,0x00,0x0d,0x00,0x52,0x04,0x0d,0x00,0x91,0x08,
+ 0x10,0x04,0x0d,0x00,0x10,0x00,0x10,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x10,0x00,
+ 0x10,0x04,0x10,0x00,0x11,0x00,0x91,0x08,0x10,0x04,0x11,0x00,0x00,0x00,0x12,0x00,
+ 0x52,0x04,0x12,0x00,0x11,0x04,0x12,0x00,0x00,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,
+ 0x00,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x14,0xdc,
+ 0x12,0xe6,0x12,0xe6,0xd4,0x30,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x12,0xe6,0x10,0x04,
+ 0x12,0x00,0x11,0xdc,0x51,0x04,0x0d,0xe6,0x10,0x04,0x0d,0xdc,0x0d,0xe6,0xd2,0x0c,
+ 0x91,0x08,0x10,0x04,0x0d,0xe6,0x0d,0xdc,0x0d,0xe6,0x91,0x08,0x10,0x04,0x0d,0xe6,
+ 0x0d,0xdc,0x0d,0xdc,0xd3,0x1c,0xd2,0x10,0xd1,0x08,0x10,0x04,0x0d,0x1b,0x0d,0x1c,
+ 0x10,0x04,0x0d,0x1d,0x0d,0xe6,0x51,0x04,0x0d,0xe6,0x10,0x04,0x0d,0xdc,0x0d,0xe6,
+ 0xd2,0x10,0xd1,0x08,0x10,0x04,0x0d,0xe6,0x0d,0xdc,0x10,0x04,0x0d,0xdc,0x0d,0xe6,
+ 0x51,0x04,0x0d,0xe6,0x10,0x04,0x0d,0xe6,0x10,0xe6,0xe1,0x3a,0x01,0xd0,0x77,0xcf,
+ 0x86,0xd5,0x20,0x94,0x1c,0x93,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x01,
+ 0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x07,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
+ 0x00,0xd4,0x1b,0x53,0x04,0x01,0x00,0x92,0x13,0x91,0x0f,0x10,0x04,0x01,0x00,0x01,
+ 0xff,0xe0,0xa4,0xa8,0xe0,0xa4,0xbc,0x00,0x01,0x00,0x01,0x00,0xd3,0x26,0xd2,0x13,
+ 0x91,0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe0,0xa4,0xb0,0xe0,0xa4,0xbc,0x00,0x01,
+ 0x00,0x91,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xa4,0xb3,0xe0,0xa4,0xbc,0x00,0x01,0x00,
+ 0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x0c,0x00,0x91,0x08,0x10,0x04,0x01,0x07,
+ 0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x8c,0xd4,0x18,0x53,0x04,0x01,0x00,0x52,0x04,
+ 0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x01,0x09,0x10,0x04,0x0b,0x00,0x0c,0x00,
+ 0xd3,0x1c,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x01,0xe6,0x10,0x04,0x01,0xdc,
+ 0x01,0xe6,0x91,0x08,0x10,0x04,0x01,0xe6,0x0b,0x00,0x0c,0x00,0xd2,0x2c,0xd1,0x16,
+ 0x10,0x0b,0x01,0xff,0xe0,0xa4,0x95,0xe0,0xa4,0xbc,0x00,0x01,0xff,0xe0,0xa4,0x96,
+ 0xe0,0xa4,0xbc,0x00,0x10,0x0b,0x01,0xff,0xe0,0xa4,0x97,0xe0,0xa4,0xbc,0x00,0x01,
+ 0xff,0xe0,0xa4,0x9c,0xe0,0xa4,0xbc,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe0,0xa4,
+ 0xa1,0xe0,0xa4,0xbc,0x00,0x01,0xff,0xe0,0xa4,0xa2,0xe0,0xa4,0xbc,0x00,0x10,0x0b,
+ 0x01,0xff,0xe0,0xa4,0xab,0xe0,0xa4,0xbc,0x00,0x01,0xff,0xe0,0xa4,0xaf,0xe0,0xa4,
+ 0xbc,0x00,0x54,0x04,0x01,0x00,0xd3,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,
+ 0x0a,0x00,0x10,0x04,0x0a,0x00,0x0c,0x00,0x0c,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,
+ 0x10,0x00,0x0b,0x00,0x10,0x04,0x0b,0x00,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x00,
+ 0x08,0x00,0x09,0x00,0xd0,0x86,0xcf,0x86,0xd5,0x44,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,
+ 0x91,0x08,0x10,0x04,0x10,0x00,0x01,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,
+ 0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,
+ 0x10,0x04,0x00,0x00,0x01,0x00,0x93,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,
+ 0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,
+ 0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
+ 0xd3,0x18,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x01,0x00,
+ 0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,
+ 0x91,0x08,0x10,0x04,0x01,0x07,0x07,0x00,0x01,0x00,0xcf,0x86,0xd5,0x7b,0xd4,0x42,
+ 0xd3,0x14,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,
+ 0x00,0x00,0x01,0x00,0xd2,0x17,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,
+ 0x00,0x00,0x01,0xff,0xe0,0xa7,0x87,0xe0,0xa6,0xbe,0x00,0xd1,0x0f,0x10,0x0b,0x01,
+ 0xff,0xe0,0xa7,0x87,0xe0,0xa7,0x97,0x00,0x01,0x09,0x10,0x04,0x08,0x00,0x00,0x00,
+ 0xd3,0x10,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,
+ 0x52,0x04,0x00,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe0,0xa6,0xa1,0xe0,0xa6,0xbc,
+ 0x00,0x01,0xff,0xe0,0xa6,0xa2,0xe0,0xa6,0xbc,0x00,0x10,0x04,0x00,0x00,0x01,0xff,
+ 0xe0,0xa6,0xaf,0xe0,0xa6,0xbc,0x00,0xd4,0x10,0x93,0x0c,0x52,0x04,0x01,0x00,0x11,
+ 0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,
+ 0x00,0x10,0x04,0x01,0x00,0x0b,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x14,0xe6,0x00,
+ 0x00,0xe2,0x48,0x02,0xe1,0x4f,0x01,0xd0,0xa4,0xcf,0x86,0xd5,0x4c,0xd4,0x34,0xd3,
+ 0x1c,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x07,0x00,0x10,0x04,0x01,0x00,0x07,
+ 0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,
+ 0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,
+ 0x00,0x93,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,
+ 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91,
+ 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x2e,0xd2,0x17,0xd1,
+ 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xe0,0xa8,0xb2,
+ 0xe0,0xa8,0xbc,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,
+ 0xe0,0xa8,0xb8,0xe0,0xa8,0xbc,0x00,0x00,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,
+ 0x00,0x91,0x08,0x10,0x04,0x01,0x07,0x00,0x00,0x01,0x00,0xcf,0x86,0xd5,0x80,0xd4,
+ 0x34,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x51,
+ 0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,
+ 0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x01,
+ 0x09,0x00,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0a,0x00,0x00,
+ 0x00,0x00,0x00,0xd2,0x25,0xd1,0x0f,0x10,0x04,0x00,0x00,0x01,0xff,0xe0,0xa8,0x96,
+ 0xe0,0xa8,0xbc,0x00,0x10,0x0b,0x01,0xff,0xe0,0xa8,0x97,0xe0,0xa8,0xbc,0x00,0x01,
+ 0xff,0xe0,0xa8,0x9c,0xe0,0xa8,0xbc,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,
+ 0x10,0x0b,0x01,0xff,0xe0,0xa8,0xab,0xe0,0xa8,0xbc,0x00,0x00,0x00,0xd4,0x10,0x93,
+ 0x0c,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x93,0x14,0x52,
+ 0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x0a,0x00,0x10,0x04,0x14,0x00,0x00,
+ 0x00,0x00,0x00,0xd0,0x82,0xcf,0x86,0xd5,0x40,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,0x91,
+ 0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,
+ 0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x07,0x00,0x01,0x00,0x10,
+ 0x04,0x00,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x00,
+ 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91,
+ 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x18,0xd2,0x0c,0x91,
+ 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,
+ 0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x01,
+ 0x07,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x3c,0xd4,0x28,0xd3,0x10,0x52,0x04,0x01,
+ 0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,
+ 0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x01,0x09,0x00,
+ 0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0xd4,0x18,0x93,0x14,0xd2,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x07,
+ 0x00,0x07,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x10,0x92,0x0c,0x91,
+ 0x08,0x10,0x04,0x0d,0x00,0x07,0x00,0x00,0x00,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,
+ 0x04,0x00,0x00,0x11,0x00,0x13,0x00,0x13,0x00,0xe1,0x24,0x01,0xd0,0x86,0xcf,0x86,
+ 0xd5,0x44,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,
+ 0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,
+ 0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x93,0x14,
+ 0x92,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,
+ 0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,
+ 0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,
+ 0x01,0x00,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x07,0x00,0x01,0x00,
+ 0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x01,0x07,0x01,0x00,
+ 0x01,0x00,0xcf,0x86,0xd5,0x73,0xd4,0x45,0xd3,0x14,0x52,0x04,0x01,0x00,0xd1,0x08,
+ 0x10,0x04,0x0a,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd2,0x1e,0xd1,0x0f,
+ 0x10,0x0b,0x01,0xff,0xe0,0xad,0x87,0xe0,0xad,0x96,0x00,0x00,0x00,0x10,0x04,0x00,
+ 0x00,0x01,0xff,0xe0,0xad,0x87,0xe0,0xac,0xbe,0x00,0x91,0x0f,0x10,0x0b,0x01,0xff,
+ 0xe0,0xad,0x87,0xe0,0xad,0x97,0x00,0x01,0x09,0x00,0x00,0xd3,0x0c,0x52,0x04,0x00,
+ 0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x52,0x04,0x00,0x00,0xd1,0x16,0x10,0x0b,0x01,
+ 0xff,0xe0,0xac,0xa1,0xe0,0xac,0xbc,0x00,0x01,0xff,0xe0,0xac,0xa2,0xe0,0xac,0xbc,
+ 0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd4,0x14,0x93,0x10,0xd2,0x08,0x11,0x04,0x01,
+ 0x00,0x0a,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x91,
+ 0x08,0x10,0x04,0x01,0x00,0x07,0x00,0x0c,0x00,0x0c,0x00,0x00,0x00,0xd0,0xb1,0xcf,
+ 0x86,0xd5,0x63,0xd4,0x28,0xd3,0x14,0xd2,0x08,0x11,0x04,0x00,0x00,0x01,0x00,0x91,
+ 0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,
+ 0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0xd3,0x1f,0xd2,0x0c,0x91,
+ 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x91,0x0f,0x10,0x0b,0x01,0xff,0xe0,
+ 0xae,0x92,0xe0,0xaf,0x97,0x00,0x01,0x00,0x00,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,
+ 0x00,0x00,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x01,0x00,
+ 0x00,0x00,0x01,0x00,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,
+ 0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0xd2,0x0c,
+ 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,
+ 0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x08,0x00,0x01,0x00,
+ 0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0xcf,0x86,
+ 0xd5,0x61,0xd4,0x45,0xd3,0x14,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,
+ 0x00,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0xd2,0x1e,0xd1,0x08,0x10,0x04,0x01,0x00,
+ 0x00,0x00,0x10,0x0b,0x01,0xff,0xe0,0xaf,0x86,0xe0,0xae,0xbe,0x00,0x01,0xff,0xe0,
+ 0xaf,0x87,0xe0,0xae,0xbe,0x00,0x91,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xaf,0x86,0xe0,
+ 0xaf,0x97,0x00,0x01,0x09,0x00,0x00,0x93,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0a,
+ 0x00,0x00,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x00,
+ 0x00,0xd4,0x14,0x93,0x10,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x08,
+ 0x00,0x01,0x00,0x01,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,
+ 0x00,0x07,0x00,0x07,0x00,0x92,0x0c,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x00,
+ 0x00,0x00,0x00,0xe3,0x1c,0x04,0xe2,0x1a,0x02,0xd1,0xf3,0xd0,0x76,0xcf,0x86,0xd5,
+ 0x3c,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x01,0x00,0x01,
+ 0x00,0x91,0x08,0x10,0x04,0x14,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x91,
+ 0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,
+ 0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,
+ 0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,
+ 0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x01,0x00,0x01,0x00,0xd2,
+ 0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0a,0x00,0x01,
+ 0x00,0xcf,0x86,0xd5,0x53,0xd4,0x2f,0xd3,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,
+ 0x04,0x01,0x00,0x00,0x00,0x01,0x00,0xd2,0x13,0x91,0x0f,0x10,0x0b,0x01,0xff,0xe0,
+ 0xb1,0x86,0xe0,0xb1,0x96,0x00,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,
+ 0x01,0x09,0x00,0x00,0xd3,0x14,0x52,0x04,0x00,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,
+ 0x01,0x54,0x10,0x04,0x01,0x5b,0x00,0x00,0x92,0x0c,0x51,0x04,0x0a,0x00,0x10,0x04,
+ 0x11,0x00,0x00,0x00,0x00,0x00,0xd4,0x14,0x93,0x10,0xd2,0x08,0x11,0x04,0x01,0x00,
+ 0x0a,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x93,0x10,0x52,0x04,0x00,0x00,
+ 0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x15,0x00,0x0a,0x00,0xd0,0x76,0xcf,0x86,
+ 0xd5,0x3c,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x12,0x00,0x10,0x00,
+ 0x01,0x00,0x91,0x08,0x10,0x04,0x14,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,
+ 0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,
+ 0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,
+ 0xd3,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,
+ 0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x07,0x07,0x07,0x00,
+ 0x01,0x00,0xcf,0x86,0xd5,0x82,0xd4,0x5e,0xd3,0x2a,0xd2,0x13,0x91,0x0f,0x10,0x0b,
+ 0x01,0xff,0xe0,0xb2,0xbf,0xe0,0xb3,0x95,0x00,0x01,0x00,0x01,0x00,0xd1,0x08,0x10,
+ 0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xe0,0xb3,0x86,0xe0,0xb3,
+ 0x95,0x00,0xd2,0x28,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xb3,0x86,0xe0,0xb3,0x96,
+ 0x00,0x00,0x00,0x10,0x0b,0x01,0xff,0xe0,0xb3,0x86,0xe0,0xb3,0x82,0x00,0x01,0xff,
+ 0xe0,0xb3,0x86,0xe0,0xb3,0x82,0xe0,0xb3,0x95,0x00,0x91,0x08,0x10,0x04,0x01,0x00,
+ 0x01,0x09,0x00,0x00,0xd3,0x14,0x52,0x04,0x00,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,
+ 0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,
+ 0x10,0x04,0x01,0x00,0x00,0x00,0xd4,0x14,0x93,0x10,0xd2,0x08,0x11,0x04,0x01,0x00,
+ 0x09,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x93,0x14,0x92,0x10,0xd1,0x08,
+ 0x10,0x04,0x00,0x00,0x09,0x00,0x10,0x04,0x09,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xe1,0x06,0x01,0xd0,0x6e,0xcf,0x86,0xd5,0x3c,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x91,
+ 0x08,0x10,0x04,0x13,0x00,0x10,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x01,
+ 0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,
+ 0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,
+ 0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,
+ 0x00,0x0c,0x00,0x01,0x00,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,
+ 0x00,0x10,0x04,0x0c,0x00,0x13,0x09,0x91,0x08,0x10,0x04,0x13,0x09,0x0a,0x00,0x01,
+ 0x00,0xcf,0x86,0xd5,0x65,0xd4,0x45,0xd3,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,
+ 0x04,0x0a,0x00,0x00,0x00,0x01,0x00,0xd2,0x1e,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,
+ 0x00,0x10,0x0b,0x01,0xff,0xe0,0xb5,0x86,0xe0,0xb4,0xbe,0x00,0x01,0xff,0xe0,0xb5,
+ 0x87,0xe0,0xb4,0xbe,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe0,0xb5,0x86,0xe0,0xb5,
+ 0x97,0x00,0x01,0x09,0x10,0x04,0x0c,0x00,0x12,0x00,0xd3,0x10,0x52,0x04,0x00,0x00,
+ 0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x01,0x00,0x52,0x04,0x12,0x00,0x51,0x04,
+ 0x12,0x00,0x10,0x04,0x12,0x00,0x11,0x00,0xd4,0x14,0x93,0x10,0xd2,0x08,0x11,0x04,
+ 0x01,0x00,0x0a,0x00,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x0c,0x52,0x04,
+ 0x0a,0x00,0x11,0x04,0x0a,0x00,0x12,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x12,0x00,
+ 0x0a,0x00,0x0a,0x00,0x0a,0x00,0xd0,0x5a,0xcf,0x86,0xd5,0x34,0xd4,0x18,0x93,0x14,
+ 0xd2,0x08,0x11,0x04,0x00,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x04,0x00,
+ 0x04,0x00,0x04,0x00,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,
+ 0x04,0x00,0x00,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x04,0x00,0x04,0x00,0x54,0x04,
+ 0x04,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x04,0x00,0x10,0x04,0x00,0x00,0x04,0x00,
+ 0x04,0x00,0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x04,0x00,0x00,0x00,
+ 0xcf,0x86,0xd5,0x77,0xd4,0x28,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,
+ 0x10,0x04,0x04,0x00,0x00,0x00,0xd2,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x04,0x09,
+ 0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x04,0x00,0xd3,0x14,0x52,0x04,
+ 0x04,0x00,0xd1,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x10,0x04,0x04,0x00,0x00,0x00,
+ 0xd2,0x13,0x51,0x04,0x04,0x00,0x10,0x0b,0x04,0xff,0xe0,0xb7,0x99,0xe0,0xb7,0x8a,
+ 0x00,0x04,0x00,0xd1,0x19,0x10,0x0b,0x04,0xff,0xe0,0xb7,0x99,0xe0,0xb7,0x8f,0x00,
+ 0x04,0xff,0xe0,0xb7,0x99,0xe0,0xb7,0x8f,0xe0,0xb7,0x8a,0x00,0x10,0x0b,0x04,0xff,
+ 0xe0,0xb7,0x99,0xe0,0xb7,0x9f,0x00,0x04,0x00,0xd4,0x10,0x93,0x0c,0x52,0x04,0x00,
+ 0x00,0x11,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x93,0x14,0xd2,0x08,0x11,0x04,0x00,
+ 0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xe2,
+ 0x31,0x01,0xd1,0x58,0xd0,0x3a,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,
+ 0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
+ 0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x67,0x10,0x04,
+ 0x01,0x09,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xcf,0x86,
+ 0x95,0x18,0xd4,0x0c,0x53,0x04,0x01,0x00,0x12,0x04,0x01,0x6b,0x01,0x00,0x53,0x04,
+ 0x01,0x00,0x12,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0xd0,0x9e,0xcf,0x86,0xd5,0x54,
+ 0xd4,0x3c,0xd3,0x20,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x10,0x04,
+ 0x01,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x15,0x00,
+ 0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x15,0x00,0x10,0x04,0x01,0x00,
+ 0x00,0x00,0x91,0x08,0x10,0x04,0x15,0x00,0x01,0x00,0x15,0x00,0xd3,0x08,0x12,0x04,
+ 0x15,0x00,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x15,0x00,0x01,0x00,0x01,0x00,
+ 0x01,0x00,0xd4,0x30,0xd3,0x1c,0xd2,0x0c,0x91,0x08,0x10,0x04,0x15,0x00,0x01,0x00,
+ 0x01,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x10,0x04,0x00,0x00,0x01,0x00,
+ 0xd2,0x08,0x11,0x04,0x15,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x15,0x00,0x01,0x00,
+ 0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x76,0x10,0x04,0x15,0x09,
+ 0x01,0x00,0x11,0x04,0x01,0x00,0x00,0x00,0xcf,0x86,0x95,0x34,0xd4,0x20,0xd3,0x14,
+ 0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x01,0x00,
+ 0x00,0x00,0x52,0x04,0x01,0x7a,0x11,0x04,0x01,0x00,0x00,0x00,0x53,0x04,0x01,0x00,
+ 0xd2,0x08,0x11,0x04,0x01,0x00,0x00,0x00,0x11,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,
+ 0xe1,0x2b,0x01,0xd0,0x3e,0xcf,0x86,0xd5,0x14,0x54,0x04,0x02,0x00,0x53,0x04,0x02,
+ 0x00,0x92,0x08,0x11,0x04,0x02,0xdc,0x02,0x00,0x02,0x00,0x54,0x04,0x02,0x00,0xd3,
+ 0x14,0x52,0x04,0x02,0x00,0xd1,0x08,0x10,0x04,0x02,0x00,0x02,0xdc,0x10,0x04,0x02,
+ 0x00,0x02,0xdc,0x92,0x0c,0x91,0x08,0x10,0x04,0x02,0x00,0x02,0xd8,0x02,0x00,0x02,
+ 0x00,0xcf,0x86,0xd5,0x73,0xd4,0x36,0xd3,0x17,0x92,0x13,0x51,0x04,0x02,0x00,0x10,
+ 0x04,0x02,0x00,0x02,0xff,0xe0,0xbd,0x82,0xe0,0xbe,0xb7,0x00,0x02,0x00,0xd2,0x0c,
+ 0x91,0x08,0x10,0x04,0x00,0x00,0x02,0x00,0x02,0x00,0x91,0x0f,0x10,0x04,0x02,0x00,
+ 0x02,0xff,0xe0,0xbd,0x8c,0xe0,0xbe,0xb7,0x00,0x02,0x00,0xd3,0x26,0xd2,0x13,0x51,
+ 0x04,0x02,0x00,0x10,0x0b,0x02,0xff,0xe0,0xbd,0x91,0xe0,0xbe,0xb7,0x00,0x02,0x00,
+ 0x51,0x04,0x02,0x00,0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbd,0x96,0xe0,0xbe,0xb7,
+ 0x00,0x52,0x04,0x02,0x00,0x91,0x0f,0x10,0x0b,0x02,0xff,0xe0,0xbd,0x9b,0xe0,0xbe,
+ 0xb7,0x00,0x02,0x00,0x02,0x00,0xd4,0x27,0x53,0x04,0x02,0x00,0xd2,0x17,0xd1,0x0f,
+ 0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbd,0x80,0xe0,0xbe,0xb5,0x00,0x10,0x04,0x04,
+ 0x00,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0xd3,0x35,0xd2,
+ 0x17,0xd1,0x08,0x10,0x04,0x00,0x00,0x02,0x81,0x10,0x04,0x02,0x82,0x02,0xff,0xe0,
+ 0xbd,0xb1,0xe0,0xbd,0xb2,0x00,0xd1,0x0f,0x10,0x04,0x02,0x84,0x02,0xff,0xe0,0xbd,
+ 0xb1,0xe0,0xbd,0xb4,0x00,0x10,0x0b,0x02,0xff,0xe0,0xbe,0xb2,0xe0,0xbe,0x80,0x00,
+ 0x02,0x00,0xd2,0x13,0x91,0x0f,0x10,0x0b,0x02,0xff,0xe0,0xbe,0xb3,0xe0,0xbe,0x80,
+ 0x00,0x02,0x00,0x02,0x82,0x11,0x04,0x02,0x82,0x02,0x00,0xd0,0xd3,0xcf,0x86,0xd5,
+ 0x65,0xd4,0x27,0xd3,0x1f,0xd2,0x13,0x91,0x0f,0x10,0x04,0x02,0x82,0x02,0xff,0xe0,
+ 0xbd,0xb1,0xe0,0xbe,0x80,0x00,0x02,0xe6,0x91,0x08,0x10,0x04,0x02,0x09,0x02,0x00,
+ 0x02,0xe6,0x12,0x04,0x02,0x00,0x0c,0x00,0xd3,0x1f,0xd2,0x13,0x51,0x04,0x02,0x00,
+ 0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbe,0x92,0xe0,0xbe,0xb7,0x00,0x51,0x04,0x02,
+ 0x00,0x10,0x04,0x04,0x00,0x02,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x02,
+ 0x00,0x02,0x00,0x91,0x0f,0x10,0x04,0x02,0x00,0x02,0xff,0xe0,0xbe,0x9c,0xe0,0xbe,
+ 0xb7,0x00,0x02,0x00,0xd4,0x3d,0xd3,0x26,0xd2,0x13,0x51,0x04,0x02,0x00,0x10,0x0b,
+ 0x02,0xff,0xe0,0xbe,0xa1,0xe0,0xbe,0xb7,0x00,0x02,0x00,0x51,0x04,0x02,0x00,0x10,
+ 0x04,0x02,0x00,0x02,0xff,0xe0,0xbe,0xa6,0xe0,0xbe,0xb7,0x00,0x52,0x04,0x02,0x00,
+ 0x91,0x0f,0x10,0x0b,0x02,0xff,0xe0,0xbe,0xab,0xe0,0xbe,0xb7,0x00,0x02,0x00,0x04,
+ 0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x02,0x00,0x02,0x00,0x02,
+ 0x00,0xd2,0x13,0x91,0x0f,0x10,0x04,0x04,0x00,0x02,0xff,0xe0,0xbe,0x90,0xe0,0xbe,
+ 0xb5,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0xcf,0x86,
+ 0x95,0x4c,0xd4,0x24,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,
+ 0x04,0xdc,0x04,0x00,0x52,0x04,0x04,0x00,0xd1,0x08,0x10,0x04,0x04,0x00,0x00,0x00,
+ 0x10,0x04,0x0a,0x00,0x04,0x00,0xd3,0x14,0xd2,0x08,0x11,0x04,0x08,0x00,0x0a,0x00,
+ 0x91,0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x0b,0x00,0x92,0x10,0xd1,0x08,0x10,0x04,
+ 0x0b,0x00,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,
+ 0xe5,0xf7,0x04,0xe4,0x79,0x03,0xe3,0x7b,0x01,0xe2,0x04,0x01,0xd1,0x7f,0xd0,0x65,
+ 0xcf,0x86,0x55,0x04,0x04,0x00,0xd4,0x33,0xd3,0x1f,0xd2,0x0c,0x51,0x04,0x04,0x00,
+ 0x10,0x04,0x0a,0x00,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x0b,0x04,0xff,0xe1,0x80,
+ 0xa5,0xe1,0x80,0xae,0x00,0x04,0x00,0x92,0x10,0xd1,0x08,0x10,0x04,0x0a,0x00,0x04,
+ 0x00,0x10,0x04,0x04,0x00,0x0a,0x00,0x04,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x04,
+ 0x00,0x10,0x04,0x04,0x00,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,0x04,0x04,0x00,0x04,
+ 0x07,0x92,0x10,0xd1,0x08,0x10,0x04,0x04,0x00,0x04,0x09,0x10,0x04,0x0a,0x09,0x0a,
+ 0x00,0x0a,0x00,0xcf,0x86,0x95,0x14,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00,0x92,
+ 0x08,0x11,0x04,0x04,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0xd0,0x2e,0xcf,0x86,0x95,
+ 0x28,0xd4,0x14,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,
+ 0x00,0x0a,0xdc,0x0a,0x00,0x53,0x04,0x0a,0x00,0xd2,0x08,0x11,0x04,0x0a,0x00,0x0b,
+ 0x00,0x11,0x04,0x0b,0x00,0x0a,0x00,0x01,0x00,0xcf,0x86,0xd5,0x24,0x94,0x20,0xd3,
+ 0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x00,0x00,0x0d,0x00,0x52,
+ 0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0d,0x00,0x00,0x00,0x01,0x00,0x54,
+ 0x04,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,
+ 0x00,0x06,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x06,0x00,0x08,0x00,0x10,0x04,0x08,
+ 0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x0d,0x00,0x0d,0x00,0xd1,0x3e,0xd0,
+ 0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x1d,0x54,0x04,0x01,0x00,0x53,0x04,0x01,
+ 0x00,0xd2,0x08,0x11,0x04,0x01,0x00,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,
+ 0x00,0x01,0xff,0x00,0x94,0x15,0x93,0x11,0x92,0x0d,0x91,0x09,0x10,0x05,0x01,0xff,
+ 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0x1e,0xcf,0x86,0x55,
+ 0x04,0x01,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,
+ 0x00,0x0b,0x00,0x0b,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,
+ 0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x92,0x08,0x11,0x04,0x01,0x00,0x0b,0x00,0x0b,
+ 0x00,0xe2,0x21,0x01,0xd1,0x6c,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x93,0x10,
+ 0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x04,0x00,
+ 0x04,0x00,0x04,0x00,0xcf,0x86,0x95,0x48,0xd4,0x24,0xd3,0x10,0x52,0x04,0x04,0x00,
+ 0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,
+ 0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0xd3,0x10,0x52,0x04,
+ 0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0xd2,0x0c,0x91,0x08,
+ 0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x04,0x00,
+ 0xd0,0x62,0xcf,0x86,0xd5,0x28,0x94,0x24,0xd3,0x10,0x52,0x04,0x04,0x00,0x51,0x04,
+ 0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,
+ 0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0xd4,0x14,0x53,0x04,
+ 0x04,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,
+ 0xd3,0x14,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,
+ 0x04,0x00,0x00,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,
+ 0x00,0x00,0xcf,0x86,0xd5,0x38,0xd4,0x24,0xd3,0x14,0xd2,0x0c,0x91,0x08,0x10,0x04,
+ 0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x52,0x04,0x04,0x00,
+ 0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x93,0x10,0x52,0x04,0x04,0x00,
+ 0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x94,0x14,0x53,0x04,
+ 0x04,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,
+ 0x04,0x00,0xd1,0x9c,0xd0,0x3e,0xcf,0x86,0x95,0x38,0xd4,0x14,0x53,0x04,0x04,0x00,
+ 0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0xd3,0x14,
+ 0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x04,0x00,0x11,0x04,0x04,0x00,
+ 0x00,0x00,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,
+ 0x04,0x00,0xcf,0x86,0xd5,0x34,0xd4,0x14,0x93,0x10,0x52,0x04,0x04,0x00,0x51,0x04,
+ 0x04,0x00,0x10,0x04,0x04,0x00,0x08,0x00,0x04,0x00,0x53,0x04,0x04,0x00,0xd2,0x0c,
+ 0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,
+ 0x0c,0xe6,0x10,0x04,0x0c,0xe6,0x08,0xe6,0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x08,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x53,0x04,0x04,0x00,
+ 0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0xd0,0x1a,
+ 0xcf,0x86,0x95,0x14,0x54,0x04,0x08,0x00,0x53,0x04,0x08,0x00,0x92,0x08,0x11,0x04,
+ 0x08,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,
+ 0x04,0x00,0xd3,0x10,0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x11,0x00,
+ 0x00,0x00,0x52,0x04,0x11,0x00,0x11,0x04,0x11,0x00,0x00,0x00,0xd3,0x30,0xd2,0x2a,
+ 0xd1,0x24,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x0b,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0x04,0x00,
+ 0xcf,0x06,0x04,0x00,0xcf,0x06,0x04,0x00,0xcf,0x06,0x04,0x00,0xd2,0x6c,0xd1,0x24,
+ 0xd0,0x06,0xcf,0x06,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00,
+ 0x93,0x10,0x52,0x04,0x04,0x00,0x51,0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x0b,0x00,
+ 0x0b,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00,
+ 0x52,0x04,0x04,0x00,0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x00,
+ 0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x04,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,
+ 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x80,0xd0,0x46,0xcf,0x86,0xd5,0x28,
+ 0xd4,0x14,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x91,0x08,0x10,0x04,0x06,0x00,
+ 0x00,0x00,0x06,0x00,0x93,0x10,0x52,0x04,0x06,0x00,0x91,0x08,0x10,0x04,0x06,0x09,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x04,0x06,0x00,0x93,0x14,0x52,0x04,0x06,0x00,
+ 0xd1,0x08,0x10,0x04,0x06,0x09,0x06,0x00,0x10,0x04,0x06,0x00,0x00,0x00,0x00,0x00,
+ 0xcf,0x86,0xd5,0x10,0x54,0x04,0x06,0x00,0x93,0x08,0x12,0x04,0x06,0x00,0x00,0x00,
+ 0x00,0x00,0xd4,0x14,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x91,0x08,0x10,0x04,
+ 0x06,0x00,0x00,0x00,0x06,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x06,0x00,
+ 0x00,0x00,0x06,0x00,0x00,0x00,0x00,0x00,0xd0,0x1b,0xcf,0x86,0x55,0x04,0x04,0x00,
+ 0x54,0x04,0x04,0x00,0x93,0x0d,0x52,0x04,0x04,0x00,0x11,0x05,0x04,0xff,0x00,0x04,
+ 0x00,0x04,0x00,0xcf,0x86,0xd5,0x24,0x54,0x04,0x04,0x00,0xd3,0x10,0x92,0x0c,0x51,
+ 0x04,0x04,0x00,0x10,0x04,0x04,0x09,0x04,0x00,0x04,0x00,0x52,0x04,0x04,0x00,0x91,
+ 0x08,0x10,0x04,0x04,0x00,0x07,0xe6,0x00,0x00,0xd4,0x10,0x53,0x04,0x04,0x00,0x92,
+ 0x08,0x11,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x07,0x00,0x92,0x08,0x11,
+ 0x04,0x07,0x00,0x00,0x00,0x00,0x00,0xe4,0xb7,0x03,0xe3,0x58,0x01,0xd2,0x8f,0xd1,
+ 0x53,0xd0,0x35,0xcf,0x86,0x95,0x2f,0xd4,0x1f,0x53,0x04,0x04,0x00,0xd2,0x0d,0x51,
+ 0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x04,0xff,0x00,0x51,0x05,0x04,0xff,0x00,0x10,
+ 0x05,0x04,0xff,0x00,0x00,0x00,0x53,0x04,0x04,0x00,0x92,0x08,0x11,0x04,0x04,0x00,
+ 0x00,0x00,0x00,0x00,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,0x00,0x54,0x04,0x04,0x00,
+ 0x53,0x04,0x04,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xd0,0x22,0xcf,0x86,0x55,0x04,0x04,0x00,0x94,0x18,0x53,0x04,0x04,0x00,
+ 0x92,0x10,0xd1,0x08,0x10,0x04,0x04,0x00,0x04,0xe4,0x10,0x04,0x0a,0x00,0x00,0x00,
+ 0x00,0x00,0x0b,0x00,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,0x00,0x93,0x0c,
+ 0x52,0x04,0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xd1,0x80,0xd0,0x42,
+ 0xcf,0x86,0xd5,0x1c,0x54,0x04,0x07,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,
+ 0xd1,0x08,0x10,0x04,0x07,0x00,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0xd4,0x0c,
+ 0x53,0x04,0x07,0x00,0x12,0x04,0x07,0x00,0x00,0x00,0x53,0x04,0x07,0x00,0x92,0x10,
+ 0xd1,0x08,0x10,0x04,0x07,0x00,0x07,0xde,0x10,0x04,0x07,0xe6,0x07,0xdc,0x00,0x00,
+ 0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x07,0x00,
+ 0x00,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0xd4,0x10,0x53,0x04,0x07,0x00,
+ 0x52,0x04,0x07,0x00,0x11,0x04,0x07,0x00,0x00,0x00,0x93,0x10,0x52,0x04,0x07,0x00,
+ 0x91,0x08,0x10,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x1a,0xcf,0x86,
+ 0x55,0x04,0x08,0x00,0x94,0x10,0x53,0x04,0x08,0x00,0x92,0x08,0x11,0x04,0x08,0x00,
+ 0x0b,0x00,0x00,0x00,0x08,0x00,0xcf,0x86,0x95,0x28,0xd4,0x10,0x53,0x04,0x08,0x00,
+ 0x92,0x08,0x11,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x08,0x00,0xd2,0x0c,
+ 0x51,0x04,0x08,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x08,0x00,
+ 0x07,0x00,0xd2,0xe4,0xd1,0x80,0xd0,0x2e,0xcf,0x86,0x95,0x28,0x54,0x04,0x08,0x00,
+ 0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x08,0xe6,
+ 0xd2,0x0c,0x91,0x08,0x10,0x04,0x08,0xdc,0x08,0x00,0x08,0x00,0x11,0x04,0x00,0x00,
+ 0x08,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,
+ 0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0xd4,0x14,
+ 0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x09,0x0b,0x00,0x0b,0x00,0x0b,0x00,
+ 0x0b,0x00,0xd3,0x10,0x52,0x04,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0xe6,
+ 0x0b,0xe6,0x52,0x04,0x0b,0xe6,0xd1,0x08,0x10,0x04,0x0b,0xe6,0x00,0x00,0x10,0x04,
+ 0x00,0x00,0x0b,0xdc,0xd0,0x5e,0xcf,0x86,0xd5,0x20,0xd4,0x10,0x53,0x04,0x0b,0x00,
+ 0x92,0x08,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x0b,0x00,0x92,0x08,
+ 0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xd4,0x10,0x53,0x04,0x0b,0x00,0x52,0x04,
+ 0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0xd3,0x10,0x52,0x04,0x10,0xe6,0x91,0x08,
+ 0x10,0x04,0x10,0xe6,0x10,0xdc,0x10,0xdc,0xd2,0x0c,0x51,0x04,0x10,0xdc,0x10,0x04,
+ 0x10,0xdc,0x10,0xe6,0xd1,0x08,0x10,0x04,0x10,0xe6,0x10,0xdc,0x10,0x04,0x10,0x00,
+ 0x00,0x00,0xcf,0x06,0x00,0x00,0xe1,0x1e,0x01,0xd0,0xaa,0xcf,0x86,0xd5,0x6e,0xd4,
+ 0x53,0xd3,0x17,0x52,0x04,0x09,0x00,0x51,0x04,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,
+ 0xac,0x85,0xe1,0xac,0xb5,0x00,0x09,0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x09,0xff,
+ 0xe1,0xac,0x87,0xe1,0xac,0xb5,0x00,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,0xac,0x89,
+ 0xe1,0xac,0xb5,0x00,0x09,0x00,0xd1,0x0f,0x10,0x0b,0x09,0xff,0xe1,0xac,0x8b,0xe1,
+ 0xac,0xb5,0x00,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,0xac,0x8d,0xe1,0xac,0xb5,0x00,
+ 0x09,0x00,0x93,0x17,0x92,0x13,0x51,0x04,0x09,0x00,0x10,0x0b,0x09,0xff,0xe1,0xac,
+ 0x91,0xe1,0xac,0xb5,0x00,0x09,0x00,0x09,0x00,0x09,0x00,0x54,0x04,0x09,0x00,0xd3,
+ 0x10,0x52,0x04,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x07,0x09,0x00,0x09,0x00,0xd2,
+ 0x13,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xe1,0xac,0xba,0xe1,0xac,
+ 0xb5,0x00,0x91,0x0f,0x10,0x04,0x09,0x00,0x09,0xff,0xe1,0xac,0xbc,0xe1,0xac,0xb5,
+ 0x00,0x09,0x00,0xcf,0x86,0xd5,0x3d,0x94,0x39,0xd3,0x31,0xd2,0x25,0xd1,0x16,0x10,
+ 0x0b,0x09,0xff,0xe1,0xac,0xbe,0xe1,0xac,0xb5,0x00,0x09,0xff,0xe1,0xac,0xbf,0xe1,
+ 0xac,0xb5,0x00,0x10,0x04,0x09,0x00,0x09,0xff,0xe1,0xad,0x82,0xe1,0xac,0xb5,0x00,
+ 0x91,0x08,0x10,0x04,0x09,0x09,0x09,0x00,0x09,0x00,0x12,0x04,0x09,0x00,0x00,0x00,
+ 0x09,0x00,0xd4,0x1c,0x53,0x04,0x09,0x00,0xd2,0x0c,0x51,0x04,0x09,0x00,0x10,0x04,
+ 0x09,0x00,0x09,0xe6,0x91,0x08,0x10,0x04,0x09,0xdc,0x09,0xe6,0x09,0xe6,0xd3,0x08,
+ 0x12,0x04,0x09,0xe6,0x09,0x00,0x52,0x04,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x00,
+ 0x00,0x00,0x00,0x00,0xd0,0x2e,0xcf,0x86,0x55,0x04,0x0a,0x00,0xd4,0x18,0x53,0x04,
+ 0x0a,0x00,0xd2,0x0c,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x09,0x0d,0x09,0x11,0x04,
+ 0x0d,0x00,0x0a,0x00,0x53,0x04,0x0a,0x00,0x92,0x08,0x11,0x04,0x0a,0x00,0x0d,0x00,
+ 0x0d,0x00,0xcf,0x86,0x55,0x04,0x0c,0x00,0xd4,0x14,0x93,0x10,0x52,0x04,0x0c,0x00,
+ 0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x07,0x0c,0x00,0x0c,0x00,0xd3,0x0c,0x92,0x08,
+ 0x11,0x04,0x0c,0x00,0x0c,0x09,0x00,0x00,0x12,0x04,0x00,0x00,0x0c,0x00,0xe3,0xb2,
+ 0x01,0xe2,0x09,0x01,0xd1,0x4c,0xd0,0x2a,0xcf,0x86,0x55,0x04,0x0a,0x00,0x54,0x04,
+ 0x0a,0x00,0xd3,0x10,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,0x04,0x0a,0x00,
+ 0x0a,0x07,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0a,0x00,0x0a,0x00,
+ 0xcf,0x86,0x95,0x1c,0x94,0x18,0x53,0x04,0x0a,0x00,0xd2,0x08,0x11,0x04,0x0a,0x00,
+ 0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,
+ 0xd0,0x3a,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x12,0x00,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x14,0x00,0x54,0x04,0x14,0x00,
+ 0x53,0x04,0x14,0x00,0xd2,0x0c,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,
+ 0x91,0x08,0x10,0x04,0x00,0x00,0x14,0x00,0x14,0x00,0xcf,0x86,0xd5,0x2c,0xd4,0x08,
+ 0x13,0x04,0x0d,0x00,0x00,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x0b,0xe6,0x10,0x04,
+ 0x0b,0xe6,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x01,0x0b,0xdc,0x0b,0xdc,0x92,0x08,
+ 0x11,0x04,0x0b,0xdc,0x0b,0xe6,0x0b,0xdc,0xd4,0x28,0xd3,0x10,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0x01,0x0b,0x01,0xd2,0x0c,0x91,0x08,0x10,0x04,
+ 0x0b,0x01,0x0b,0x00,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0xdc,0x0b,0x00,
+ 0xd3,0x1c,0xd2,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x0d,0x00,0xd1,0x08,
+ 0x10,0x04,0x0d,0xe6,0x0d,0x00,0x10,0x04,0x0d,0x00,0x13,0x00,0x92,0x0c,0x51,0x04,
+ 0x10,0xe6,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0xd1,0x1c,0xd0,0x06,0xcf,0x06,
+ 0x07,0x00,0xcf,0x86,0x55,0x04,0x07,0x00,0x94,0x0c,0x53,0x04,0x07,0x00,0x12,0x04,
+ 0x07,0x00,0x08,0x00,0x08,0x00,0xd0,0x06,0xcf,0x06,0x08,0x00,0xcf,0x86,0xd5,0x40,
+ 0xd4,0x2c,0xd3,0x10,0x92,0x0c,0x51,0x04,0x08,0xe6,0x10,0x04,0x08,0xdc,0x08,0xe6,
+ 0x09,0xe6,0xd2,0x0c,0x51,0x04,0x09,0xe6,0x10,0x04,0x09,0xdc,0x0a,0xe6,0xd1,0x08,
+ 0x10,0x04,0x0a,0xe6,0x0a,0xea,0x10,0x04,0x0a,0xd6,0x0a,0xdc,0x93,0x10,0x92,0x0c,
+ 0x91,0x08,0x10,0x04,0x0a,0xca,0x0a,0xe6,0x0a,0xe6,0x0a,0xe6,0x0a,0xe6,0xd4,0x14,
+ 0x93,0x10,0x52,0x04,0x0a,0xe6,0x51,0x04,0x0a,0xe6,0x10,0x04,0x0a,0xe6,0x10,0xe6,
+ 0x10,0xe6,0xd3,0x10,0x52,0x04,0x10,0xe6,0x51,0x04,0x10,0xe6,0x10,0x04,0x13,0xe8,
+ 0x13,0xe4,0xd2,0x10,0xd1,0x08,0x10,0x04,0x13,0xe4,0x13,0xdc,0x10,0x04,0x00,0x00,
+ 0x12,0xe6,0xd1,0x08,0x10,0x04,0x0c,0xe9,0x0b,0xdc,0x10,0x04,0x09,0xe6,0x09,0xdc,
+ 0xe2,0x80,0x08,0xe1,0x48,0x04,0xe0,0x1c,0x02,0xcf,0x86,0xe5,0x11,0x01,0xd4,0x84,
+ 0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0xa5,0x00,0x01,0xff,
+ 0x61,0xcc,0xa5,0x00,0x10,0x08,0x01,0xff,0x42,0xcc,0x87,0x00,0x01,0xff,0x62,0xcc,
+ 0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x42,0xcc,0xa3,0x00,0x01,0xff,0x62,0xcc,
+ 0xa3,0x00,0x10,0x08,0x01,0xff,0x42,0xcc,0xb1,0x00,0x01,0xff,0x62,0xcc,0xb1,0x00,
+ 0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x43,0xcc,0xa7,0xcc,0x81,0x00,0x01,0xff,
+ 0x63,0xcc,0xa7,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x44,0xcc,0x87,0x00,0x01,0xff,
+ 0x64,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x44,0xcc,0xa3,0x00,0x01,0xff,
+ 0x64,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x44,0xcc,0xb1,0x00,0x01,0xff,0x64,0xcc,
+ 0xb1,0x00,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x44,0xcc,0xa7,0x00,
+ 0x01,0xff,0x64,0xcc,0xa7,0x00,0x10,0x08,0x01,0xff,0x44,0xcc,0xad,0x00,0x01,0xff,
+ 0x64,0xcc,0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x45,0xcc,0x84,0xcc,0x80,0x00,
+ 0x01,0xff,0x65,0xcc,0x84,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x45,0xcc,0x84,0xcc,
+ 0x81,0x00,0x01,0xff,0x65,0xcc,0x84,0xcc,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0x45,0xcc,0xad,0x00,0x01,0xff,0x65,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,
+ 0x45,0xcc,0xb0,0x00,0x01,0xff,0x65,0xcc,0xb0,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,
+ 0x45,0xcc,0xa7,0xcc,0x86,0x00,0x01,0xff,0x65,0xcc,0xa7,0xcc,0x86,0x00,0x10,0x08,
+ 0x01,0xff,0x46,0xcc,0x87,0x00,0x01,0xff,0x66,0xcc,0x87,0x00,0xd4,0x84,0xd3,0x40,
+ 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x47,0xcc,0x84,0x00,0x01,0xff,0x67,0xcc,
+ 0x84,0x00,0x10,0x08,0x01,0xff,0x48,0xcc,0x87,0x00,0x01,0xff,0x68,0xcc,0x87,0x00,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0x48,0xcc,0xa3,0x00,0x01,0xff,0x68,0xcc,0xa3,0x00,
+ 0x10,0x08,0x01,0xff,0x48,0xcc,0x88,0x00,0x01,0xff,0x68,0xcc,0x88,0x00,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0x48,0xcc,0xa7,0x00,0x01,0xff,0x68,0xcc,0xa7,0x00,
+ 0x10,0x08,0x01,0xff,0x48,0xcc,0xae,0x00,0x01,0xff,0x68,0xcc,0xae,0x00,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0x49,0xcc,0xb0,0x00,0x01,0xff,0x69,0xcc,0xb0,0x00,0x10,0x0a,
+ 0x01,0xff,0x49,0xcc,0x88,0xcc,0x81,0x00,0x01,0xff,0x69,0xcc,0x88,0xcc,0x81,0x00,
+ 0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x4b,0xcc,0x81,0x00,0x01,0xff,
+ 0x6b,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x4b,0xcc,0xa3,0x00,0x01,0xff,0x6b,0xcc,
+ 0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4b,0xcc,0xb1,0x00,0x01,0xff,0x6b,0xcc,
+ 0xb1,0x00,0x10,0x08,0x01,0xff,0x4c,0xcc,0xa3,0x00,0x01,0xff,0x6c,0xcc,0xa3,0x00,
+ 0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4c,0xcc,0xa3,0xcc,0x84,0x00,0x01,0xff,
+ 0x6c,0xcc,0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x4c,0xcc,0xb1,0x00,0x01,0xff,
+ 0x6c,0xcc,0xb1,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4c,0xcc,0xad,0x00,0x01,0xff,
+ 0x6c,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x4d,0xcc,0x81,0x00,0x01,0xff,0x6d,0xcc,
+ 0x81,0x00,0xcf,0x86,0xe5,0x15,0x01,0xd4,0x88,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x4d,0xcc,0x87,0x00,0x01,0xff,0x6d,0xcc,0x87,0x00,0x10,0x08,0x01,
+ 0xff,0x4d,0xcc,0xa3,0x00,0x01,0xff,0x6d,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x4e,0xcc,0x87,0x00,0x01,0xff,0x6e,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x4e,
+ 0xcc,0xa3,0x00,0x01,0xff,0x6e,0xcc,0xa3,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x4e,0xcc,0xb1,0x00,0x01,0xff,0x6e,0xcc,0xb1,0x00,0x10,0x08,0x01,0xff,0x4e,
+ 0xcc,0xad,0x00,0x01,0xff,0x6e,0xcc,0xad,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,
+ 0xcc,0x83,0xcc,0x81,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,
+ 0xff,0x4f,0xcc,0x83,0xcc,0x88,0x00,0x01,0xff,0x6f,0xcc,0x83,0xcc,0x88,0x00,0xd3,
+ 0x48,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x84,0xcc,0x80,0x00,0x01,
+ 0xff,0x6f,0xcc,0x84,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x84,0xcc,0x81,
+ 0x00,0x01,0xff,0x6f,0xcc,0x84,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x50,
+ 0xcc,0x81,0x00,0x01,0xff,0x70,0xcc,0x81,0x00,0x10,0x08,0x01,0xff,0x50,0xcc,0x87,
+ 0x00,0x01,0xff,0x70,0xcc,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x52,
+ 0xcc,0x87,0x00,0x01,0xff,0x72,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x52,0xcc,0xa3,
+ 0x00,0x01,0xff,0x72,0xcc,0xa3,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x52,0xcc,0xa3,
+ 0xcc,0x84,0x00,0x01,0xff,0x72,0xcc,0xa3,0xcc,0x84,0x00,0x10,0x08,0x01,0xff,0x52,
+ 0xcc,0xb1,0x00,0x01,0xff,0x72,0xcc,0xb1,0x00,0xd4,0x8c,0xd3,0x48,0xd2,0x20,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0x53,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x87,0x00,0x10,
+ 0x08,0x01,0xff,0x53,0xcc,0xa3,0x00,0x01,0xff,0x73,0xcc,0xa3,0x00,0xd1,0x14,0x10,
+ 0x0a,0x01,0xff,0x53,0xcc,0x81,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x81,0xcc,0x87,
+ 0x00,0x10,0x0a,0x01,0xff,0x53,0xcc,0x8c,0xcc,0x87,0x00,0x01,0xff,0x73,0xcc,0x8c,
+ 0xcc,0x87,0x00,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,0x53,0xcc,0xa3,0xcc,0x87,
+ 0x00,0x01,0xff,0x73,0xcc,0xa3,0xcc,0x87,0x00,0x10,0x08,0x01,0xff,0x54,0xcc,0x87,
+ 0x00,0x01,0xff,0x74,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x54,0xcc,0xa3,
+ 0x00,0x01,0xff,0x74,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x54,0xcc,0xb1,0x00,0x01,
+ 0xff,0x74,0xcc,0xb1,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x54,
+ 0xcc,0xad,0x00,0x01,0xff,0x74,0xcc,0xad,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0xa4,
+ 0x00,0x01,0xff,0x75,0xcc,0xa4,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x55,0xcc,0xb0,
+ 0x00,0x01,0xff,0x75,0xcc,0xb0,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,0xad,0x00,0x01,
+ 0xff,0x75,0xcc,0xad,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x55,0xcc,0x83,
+ 0xcc,0x81,0x00,0x01,0xff,0x75,0xcc,0x83,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x55,
+ 0xcc,0x84,0xcc,0x88,0x00,0x01,0xff,0x75,0xcc,0x84,0xcc,0x88,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0x56,0xcc,0x83,0x00,0x01,0xff,0x76,0xcc,0x83,0x00,0x10,0x08,0x01,
+ 0xff,0x56,0xcc,0xa3,0x00,0x01,0xff,0x76,0xcc,0xa3,0x00,0xe0,0x10,0x02,0xcf,0x86,
+ 0xd5,0xe1,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc,
+ 0x80,0x00,0x01,0xff,0x77,0xcc,0x80,0x00,0x10,0x08,0x01,0xff,0x57,0xcc,0x81,0x00,
+ 0x01,0xff,0x77,0xcc,0x81,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc,0x88,0x00,
+ 0x01,0xff,0x77,0xcc,0x88,0x00,0x10,0x08,0x01,0xff,0x57,0xcc,0x87,0x00,0x01,0xff,
+ 0x77,0xcc,0x87,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x57,0xcc,0xa3,0x00,
+ 0x01,0xff,0x77,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x58,0xcc,0x87,0x00,0x01,0xff,
+ 0x78,0xcc,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x58,0xcc,0x88,0x00,0x01,0xff,
+ 0x78,0xcc,0x88,0x00,0x10,0x08,0x01,0xff,0x59,0xcc,0x87,0x00,0x01,0xff,0x79,0xcc,
+ 0x87,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x5a,0xcc,0x82,0x00,
+ 0x01,0xff,0x7a,0xcc,0x82,0x00,0x10,0x08,0x01,0xff,0x5a,0xcc,0xa3,0x00,0x01,0xff,
+ 0x7a,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x5a,0xcc,0xb1,0x00,0x01,0xff,
+ 0x7a,0xcc,0xb1,0x00,0x10,0x08,0x01,0xff,0x68,0xcc,0xb1,0x00,0x01,0xff,0x74,0xcc,
+ 0x88,0x00,0x92,0x1d,0xd1,0x10,0x10,0x08,0x01,0xff,0x77,0xcc,0x8a,0x00,0x01,0xff,
+ 0x79,0xcc,0x8a,0x00,0x10,0x04,0x01,0x00,0x02,0xff,0xc5,0xbf,0xcc,0x87,0x00,0x0a,
+ 0x00,0xd4,0x98,0xd3,0x48,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x41,0xcc,0xa3,
+ 0x00,0x01,0xff,0x61,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x41,0xcc,0x89,0x00,0x01,
+ 0xff,0x61,0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0x82,0xcc,0x81,
+ 0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x82,
+ 0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x80,0x00,0xd2,0x28,0xd1,0x14,0x10,
+ 0x0a,0x01,0xff,0x41,0xcc,0x82,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x82,0xcc,0x89,
+ 0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x61,0xcc,0x82,
+ 0xcc,0x83,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0xa3,0xcc,0x82,0x00,0x01,
+ 0xff,0x61,0xcc,0xa3,0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x81,
+ 0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,0x81,0x00,0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,
+ 0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x80,0x00,0x01,0xff,0x61,0xcc,0x86,0xcc,0x80,
+ 0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x89,0x00,0x01,0xff,0x61,0xcc,0x86,
+ 0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x41,0xcc,0x86,0xcc,0x83,0x00,0x01,
+ 0xff,0x61,0xcc,0x86,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x41,0xcc,0xa3,0xcc,0x86,
+ 0x00,0x01,0xff,0x61,0xcc,0xa3,0xcc,0x86,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0x45,0xcc,0xa3,0x00,0x01,0xff,0x65,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x45,
+ 0xcc,0x89,0x00,0x01,0xff,0x65,0xcc,0x89,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x45,
+ 0xcc,0x83,0x00,0x01,0xff,0x65,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x45,0xcc,0x82,
+ 0xcc,0x81,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x81,0x00,0xcf,0x86,0xe5,0x31,0x01,
+ 0xd4,0x90,0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x45,0xcc,0x82,0xcc,
+ 0x80,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0x45,0xcc,
+ 0x82,0xcc,0x89,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x89,0x00,0xd1,0x14,0x10,0x0a,
+ 0x01,0xff,0x45,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x65,0xcc,0x82,0xcc,0x83,0x00,
+ 0x10,0x0a,0x01,0xff,0x45,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,0x65,0xcc,0xa3,0xcc,
+ 0x82,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0x49,0xcc,0x89,0x00,0x01,0xff,
+ 0x69,0xcc,0x89,0x00,0x10,0x08,0x01,0xff,0x49,0xcc,0xa3,0x00,0x01,0xff,0x69,0xcc,
+ 0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0x4f,0xcc,0xa3,0x00,0x01,0xff,0x6f,0xcc,
+ 0xa3,0x00,0x10,0x08,0x01,0xff,0x4f,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x89,0x00,
+ 0xd3,0x50,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x82,0xcc,0x81,0x00,
+ 0x01,0xff,0x6f,0xcc,0x82,0xcc,0x81,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x82,0xcc,
+ 0x80,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x80,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,
+ 0x4f,0xcc,0x82,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x89,0x00,0x10,0x0a,
+ 0x01,0xff,0x4f,0xcc,0x82,0xcc,0x83,0x00,0x01,0xff,0x6f,0xcc,0x82,0xcc,0x83,0x00,
+ 0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0xa3,0xcc,0x82,0x00,0x01,0xff,
+ 0x6f,0xcc,0xa3,0xcc,0x82,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x9b,0xcc,0x81,0x00,
+ 0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x81,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,
+ 0x9b,0xcc,0x80,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,
+ 0x4f,0xcc,0x9b,0xcc,0x89,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x89,0x00,0xd4,0x98,
+ 0xd3,0x48,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x9b,0xcc,0x83,0x00,
+ 0x01,0xff,0x6f,0xcc,0x9b,0xcc,0x83,0x00,0x10,0x0a,0x01,0xff,0x4f,0xcc,0x9b,0xcc,
+ 0xa3,0x00,0x01,0xff,0x6f,0xcc,0x9b,0xcc,0xa3,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0x55,0xcc,0xa3,0x00,0x01,0xff,0x75,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,0x55,0xcc,
+ 0x89,0x00,0x01,0xff,0x75,0xcc,0x89,0x00,0xd2,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,
+ 0x55,0xcc,0x9b,0xcc,0x81,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x81,0x00,0x10,0x0a,
+ 0x01,0xff,0x55,0xcc,0x9b,0xcc,0x80,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0x80,0x00,
+ 0xd1,0x14,0x10,0x0a,0x01,0xff,0x55,0xcc,0x9b,0xcc,0x89,0x00,0x01,0xff,0x75,0xcc,
+ 0x9b,0xcc,0x89,0x00,0x10,0x0a,0x01,0xff,0x55,0xcc,0x9b,0xcc,0x83,0x00,0x01,0xff,
+ 0x75,0xcc,0x9b,0xcc,0x83,0x00,0xd3,0x44,0xd2,0x24,0xd1,0x14,0x10,0x0a,0x01,0xff,
+ 0x55,0xcc,0x9b,0xcc,0xa3,0x00,0x01,0xff,0x75,0xcc,0x9b,0xcc,0xa3,0x00,0x10,0x08,
+ 0x01,0xff,0x59,0xcc,0x80,0x00,0x01,0xff,0x79,0xcc,0x80,0x00,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0x59,0xcc,0xa3,0x00,0x01,0xff,0x79,0xcc,0xa3,0x00,0x10,0x08,0x01,0xff,
+ 0x59,0xcc,0x89,0x00,0x01,0xff,0x79,0xcc,0x89,0x00,0x92,0x14,0x91,0x10,0x10,0x08,
+ 0x01,0xff,0x59,0xcc,0x83,0x00,0x01,0xff,0x79,0xcc,0x83,0x00,0x0a,0x00,0x0a,0x00,
+ 0xe1,0xc0,0x04,0xe0,0x80,0x02,0xcf,0x86,0xe5,0x2d,0x01,0xd4,0xa8,0xd3,0x54,0xd2,
+ 0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x93,0x00,0x01,0xff,0xce,0xb1,
+ 0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,
+ 0xce,0xb1,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,
+ 0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,
+ 0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82,
+ 0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x91,0xcc,0x93,0x00,0x01,0xff,
+ 0xce,0x91,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0x91,0xcc,0x93,0xcc,0x80,0x00,
+ 0x01,0xff,0xce,0x91,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,
+ 0x91,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,0xcc,0x81,0x00,0x10,
+ 0x0b,0x01,0xff,0xce,0x91,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,
+ 0xcd,0x82,0x00,0xd3,0x42,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc,
+ 0x93,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb5,0xcc,
+ 0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,0xcc,0x80,0x00,0x91,0x16,0x10,
+ 0x0b,0x01,0xff,0xce,0xb5,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb5,0xcc,0x94,
+ 0xcc,0x81,0x00,0x00,0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x95,0xcc,
+ 0x93,0x00,0x01,0xff,0xce,0x95,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0x95,0xcc,
+ 0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0x95,0xcc,0x94,0xcc,0x80,0x00,0x91,0x16,0x10,
+ 0x0b,0x01,0xff,0xce,0x95,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0x95,0xcc,0x94,
+ 0xcc,0x81,0x00,0x00,0x00,0xd4,0xa8,0xd3,0x54,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,
+ 0xff,0xce,0xb7,0xcc,0x93,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0x00,0x10,0x0b,0x01,
+ 0xff,0xce,0xb7,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,
+ 0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,
+ 0xce,0xb7,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,
+ 0x82,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x82,0x00,0xd2,0x28,0xd1,0x12,0x10,
+ 0x09,0x01,0xff,0xce,0x97,0xcc,0x93,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0x00,0x10,
+ 0x0b,0x01,0xff,0xce,0x97,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,
+ 0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0x97,0xcc,0x93,0xcc,0x81,0x00,
+ 0x01,0xff,0xce,0x97,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xce,0x97,0xcc,
+ 0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcd,0x82,0x00,0xd3,0x54,0xd2,
+ 0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x93,0x00,0x01,0xff,0xce,0xb9,
+ 0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,
+ 0xce,0xb9,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb9,0xcc,
+ 0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,
+ 0xff,0xce,0xb9,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xb9,0xcc,0x94,0xcd,0x82,
+ 0x00,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x99,0xcc,0x93,0x00,0x01,0xff,
+ 0xce,0x99,0xcc,0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0x99,0xcc,0x93,0xcc,0x80,0x00,
+ 0x01,0xff,0xce,0x99,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,
+ 0x99,0xcc,0x93,0xcc,0x81,0x00,0x01,0xff,0xce,0x99,0xcc,0x94,0xcc,0x81,0x00,0x10,
+ 0x0b,0x01,0xff,0xce,0x99,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0x99,0xcc,0x94,
+ 0xcd,0x82,0x00,0xcf,0x86,0xe5,0x13,0x01,0xd4,0x84,0xd3,0x42,0xd2,0x28,0xd1,0x12,
+ 0x10,0x09,0x01,0xff,0xce,0xbf,0xcc,0x93,0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0x00,
+ 0x10,0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,0xcc,
+ 0x94,0xcc,0x80,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0xbf,0xcc,0x93,0xcc,0x81,
+ 0x00,0x01,0xff,0xce,0xbf,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd2,0x28,0xd1,0x12,
+ 0x10,0x09,0x01,0xff,0xce,0x9f,0xcc,0x93,0x00,0x01,0xff,0xce,0x9f,0xcc,0x94,0x00,
+ 0x10,0x0b,0x01,0xff,0xce,0x9f,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,0x9f,0xcc,
+ 0x94,0xcc,0x80,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xce,0x9f,0xcc,0x93,0xcc,0x81,
+ 0x00,0x01,0xff,0xce,0x9f,0xcc,0x94,0xcc,0x81,0x00,0x00,0x00,0xd3,0x54,0xd2,0x28,
+ 0xd1,0x12,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x93,0x00,0x01,0xff,0xcf,0x85,0xcc,
+ 0x94,0x00,0x10,0x0b,0x01,0xff,0xcf,0x85,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xcf,
+ 0x85,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x85,0xcc,0x93,
+ 0xcc,0x81,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,
+ 0xcf,0x85,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xcf,0x85,0xcc,0x94,0xcd,0x82,0x00,
+ 0xd2,0x1c,0xd1,0x0d,0x10,0x04,0x00,0x00,0x01,0xff,0xce,0xa5,0xcc,0x94,0x00,0x10,
+ 0x04,0x00,0x00,0x01,0xff,0xce,0xa5,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x0f,0x10,0x04,
+ 0x00,0x00,0x01,0xff,0xce,0xa5,0xcc,0x94,0xcc,0x81,0x00,0x10,0x04,0x00,0x00,0x01,
+ 0xff,0xce,0xa5,0xcc,0x94,0xcd,0x82,0x00,0xd4,0xa8,0xd3,0x54,0xd2,0x28,0xd1,0x12,
+ 0x10,0x09,0x01,0xff,0xcf,0x89,0xcc,0x93,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0x00,
+ 0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc,
+ 0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x81,
+ 0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89,
+ 0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,0x82,0x00,0xd2,0x28,
+ 0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xa9,0xcc,0x93,0x00,0x01,0xff,0xce,0xa9,0xcc,
+ 0x94,0x00,0x10,0x0b,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcc,0x80,0x00,0x01,0xff,0xce,
+ 0xa9,0xcc,0x94,0xcc,0x80,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xa9,0xcc,0x93,
+ 0xcc,0x81,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcc,0x81,0x00,0x10,0x0b,0x01,0xff,
+ 0xce,0xa9,0xcc,0x93,0xcd,0x82,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcd,0x82,0x00,
+ 0xd3,0x48,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x80,0x00,0x01,
+ 0xff,0xce,0xb1,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb5,0xcc,0x80,0x00,0x01,
+ 0xff,0xce,0xb5,0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb7,0xcc,0x80,
+ 0x00,0x01,0xff,0xce,0xb7,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcc,0x80,
+ 0x00,0x01,0xff,0xce,0xb9,0xcc,0x81,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,
+ 0xce,0xbf,0xcc,0x80,0x00,0x01,0xff,0xce,0xbf,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,
+ 0xcf,0x85,0xcc,0x80,0x00,0x01,0xff,0xcf,0x85,0xcc,0x81,0x00,0x91,0x12,0x10,0x09,
+ 0x01,0xff,0xcf,0x89,0xcc,0x80,0x00,0x01,0xff,0xcf,0x89,0xcc,0x81,0x00,0x00,0x00,
+ 0xe0,0xe1,0x02,0xcf,0x86,0xe5,0x91,0x01,0xd4,0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16,
+ 0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xce,0xb1,0xcc,
+ 0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x80,0xcd,0x85,
+ 0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d,
+ 0x01,0xff,0xce,0xb1,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xce,0xb1,0xcc,
+ 0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xb1,0xcc,0x93,0xcd,0x82,
+ 0xcd,0x85,0x00,0x01,0xff,0xce,0xb1,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x30,
+ 0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0x91,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xce,
+ 0x91,0xcc,0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0x91,0xcc,0x93,0xcc,0x80,
+ 0xcd,0x85,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,
+ 0x10,0x0d,0x01,0xff,0xce,0x91,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xce,
+ 0x91,0xcc,0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0x91,0xcc,0x93,
+ 0xcd,0x82,0xcd,0x85,0x00,0x01,0xff,0xce,0x91,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,
+ 0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcd,0x85,
+ 0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xb7,
+ 0xcc,0x93,0xcc,0x80,0xcd,0x85,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x80,0xcd,
+ 0x85,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0xb7,0xcc,0x93,0xcc,0x81,0xcd,0x85,
+ 0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,
+ 0xce,0xb7,0xcc,0x93,0xcd,0x82,0xcd,0x85,0x00,0x01,0xff,0xce,0xb7,0xcc,0x94,0xcd,
+ 0x82,0xcd,0x85,0x00,0xd2,0x30,0xd1,0x16,0x10,0x0b,0x01,0xff,0xce,0x97,0xcc,0x93,
+ 0xcd,0x85,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,
+ 0xce,0x97,0xcc,0x93,0xcc,0x80,0xcd,0x85,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcc,
+ 0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,0xce,0x97,0xcc,0x93,0xcc,0x81,
+ 0xcd,0x85,0x00,0x01,0xff,0xce,0x97,0xcc,0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,
+ 0x01,0xff,0xce,0x97,0xcc,0x93,0xcd,0x82,0xcd,0x85,0x00,0x01,0xff,0xce,0x97,0xcc,
+ 0x94,0xcd,0x82,0xcd,0x85,0x00,0xd4,0xc8,0xd3,0x64,0xd2,0x30,0xd1,0x16,0x10,0x0b,
+ 0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,
+ 0x85,0x00,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcc,0x80,0xcd,0x85,0x00,0x01,
+ 0xff,0xcf,0x89,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d,0x01,0xff,
+ 0xcf,0x89,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcc,
+ 0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xcf,0x89,0xcc,0x93,0xcd,0x82,0xcd,0x85,
+ 0x00,0x01,0xff,0xcf,0x89,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x30,0xd1,0x16,
+ 0x10,0x0b,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcd,0x85,0x00,0x01,0xff,0xce,0xa9,0xcc,
+ 0x94,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcc,0x80,0xcd,0x85,
+ 0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcc,0x80,0xcd,0x85,0x00,0xd1,0x1a,0x10,0x0d,
+ 0x01,0xff,0xce,0xa9,0xcc,0x93,0xcc,0x81,0xcd,0x85,0x00,0x01,0xff,0xce,0xa9,0xcc,
+ 0x94,0xcc,0x81,0xcd,0x85,0x00,0x10,0x0d,0x01,0xff,0xce,0xa9,0xcc,0x93,0xcd,0x82,
+ 0xcd,0x85,0x00,0x01,0xff,0xce,0xa9,0xcc,0x94,0xcd,0x82,0xcd,0x85,0x00,0xd3,0x49,
+ 0xd2,0x26,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0xb1,0xcc,0x86,0x00,0x01,0xff,0xce,
+ 0xb1,0xcc,0x84,0x00,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x80,0xcd,0x85,0x00,0x01,
+ 0xff,0xce,0xb1,0xcd,0x85,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xce,0xb1,0xcc,0x81,
+ 0xcd,0x85,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xb1,0xcd,0x82,0x00,0x01,0xff,
+ 0xce,0xb1,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,
+ 0x91,0xcc,0x86,0x00,0x01,0xff,0xce,0x91,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xce,
+ 0x91,0xcc,0x80,0x00,0x01,0xff,0xce,0x91,0xcc,0x81,0x00,0xd1,0x0d,0x10,0x09,0x01,
+ 0xff,0xce,0x91,0xcd,0x85,0x00,0x01,0x00,0x10,0x07,0x01,0xff,0xce,0xb9,0x00,0x01,
+ 0x00,0xcf,0x86,0xe5,0x16,0x01,0xd4,0x8f,0xd3,0x44,0xd2,0x21,0xd1,0x0d,0x10,0x04,
+ 0x01,0x00,0x01,0xff,0xc2,0xa8,0xcd,0x82,0x00,0x10,0x0b,0x01,0xff,0xce,0xb7,0xcc,
+ 0x80,0xcd,0x85,0x00,0x01,0xff,0xce,0xb7,0xcd,0x85,0x00,0xd1,0x0f,0x10,0x0b,0x01,
+ 0xff,0xce,0xb7,0xcc,0x81,0xcd,0x85,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xb7,
+ 0xcd,0x82,0x00,0x01,0xff,0xce,0xb7,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x24,0xd1,0x12,
+ 0x10,0x09,0x01,0xff,0xce,0x95,0xcc,0x80,0x00,0x01,0xff,0xce,0x95,0xcc,0x81,0x00,
+ 0x10,0x09,0x01,0xff,0xce,0x97,0xcc,0x80,0x00,0x01,0xff,0xce,0x97,0xcc,0x81,0x00,
+ 0xd1,0x13,0x10,0x09,0x01,0xff,0xce,0x97,0xcd,0x85,0x00,0x01,0xff,0xe1,0xbe,0xbf,
+ 0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0xe1,0xbe,0xbf,0xcc,0x81,0x00,0x01,0xff,0xe1,
+ 0xbe,0xbf,0xcd,0x82,0x00,0xd3,0x40,0xd2,0x28,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,
+ 0xb9,0xcc,0x86,0x00,0x01,0xff,0xce,0xb9,0xcc,0x84,0x00,0x10,0x0b,0x01,0xff,0xce,
+ 0xb9,0xcc,0x88,0xcc,0x80,0x00,0x01,0xff,0xce,0xb9,0xcc,0x88,0xcc,0x81,0x00,0x51,
+ 0x04,0x00,0x00,0x10,0x09,0x01,0xff,0xce,0xb9,0xcd,0x82,0x00,0x01,0xff,0xce,0xb9,
+ 0xcc,0x88,0xcd,0x82,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,0x99,0xcc,
+ 0x86,0x00,0x01,0xff,0xce,0x99,0xcc,0x84,0x00,0x10,0x09,0x01,0xff,0xce,0x99,0xcc,
+ 0x80,0x00,0x01,0xff,0xce,0x99,0xcc,0x81,0x00,0xd1,0x0e,0x10,0x04,0x00,0x00,0x01,
+ 0xff,0xe1,0xbf,0xbe,0xcc,0x80,0x00,0x10,0x0a,0x01,0xff,0xe1,0xbf,0xbe,0xcc,0x81,
+ 0x00,0x01,0xff,0xe1,0xbf,0xbe,0xcd,0x82,0x00,0xd4,0x93,0xd3,0x4e,0xd2,0x28,0xd1,
+ 0x12,0x10,0x09,0x01,0xff,0xcf,0x85,0xcc,0x86,0x00,0x01,0xff,0xcf,0x85,0xcc,0x84,
+ 0x00,0x10,0x0b,0x01,0xff,0xcf,0x85,0xcc,0x88,0xcc,0x80,0x00,0x01,0xff,0xcf,0x85,
+ 0xcc,0x88,0xcc,0x81,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xcf,0x81,0xcc,0x93,0x00,
+ 0x01,0xff,0xcf,0x81,0xcc,0x94,0x00,0x10,0x09,0x01,0xff,0xcf,0x85,0xcd,0x82,0x00,
+ 0x01,0xff,0xcf,0x85,0xcc,0x88,0xcd,0x82,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,
+ 0xff,0xce,0xa5,0xcc,0x86,0x00,0x01,0xff,0xce,0xa5,0xcc,0x84,0x00,0x10,0x09,0x01,
+ 0xff,0xce,0xa5,0xcc,0x80,0x00,0x01,0xff,0xce,0xa5,0xcc,0x81,0x00,0xd1,0x12,0x10,
+ 0x09,0x01,0xff,0xce,0xa1,0xcc,0x94,0x00,0x01,0xff,0xc2,0xa8,0xcc,0x80,0x00,0x10,
+ 0x09,0x01,0xff,0xc2,0xa8,0xcc,0x81,0x00,0x01,0xff,0x60,0x00,0xd3,0x3b,0xd2,0x18,
+ 0x51,0x04,0x00,0x00,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x80,0xcd,0x85,0x00,0x01,
+ 0xff,0xcf,0x89,0xcd,0x85,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xcf,0x89,0xcc,0x81,
+ 0xcd,0x85,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xcf,0x89,0xcd,0x82,0x00,0x01,0xff,
+ 0xcf,0x89,0xcd,0x82,0xcd,0x85,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xce,
+ 0x9f,0xcc,0x80,0x00,0x01,0xff,0xce,0x9f,0xcc,0x81,0x00,0x10,0x09,0x01,0xff,0xce,
+ 0xa9,0xcc,0x80,0x00,0x01,0xff,0xce,0xa9,0xcc,0x81,0x00,0xd1,0x10,0x10,0x09,0x01,
+ 0xff,0xce,0xa9,0xcd,0x85,0x00,0x01,0xff,0xc2,0xb4,0x00,0x10,0x04,0x01,0x00,0x00,
+ 0x00,0xe0,0x7e,0x0c,0xcf,0x86,0xe5,0xbb,0x08,0xe4,0x14,0x06,0xe3,0xf7,0x02,0xe2,
+ 0xbd,0x01,0xd1,0xd0,0xd0,0x4f,0xcf,0x86,0xd5,0x2e,0x94,0x2a,0xd3,0x18,0x92,0x14,
+ 0x91,0x10,0x10,0x08,0x01,0xff,0xe2,0x80,0x82,0x00,0x01,0xff,0xe2,0x80,0x83,0x00,
+ 0x01,0x00,0x01,0x00,0x92,0x0d,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,
+ 0x00,0x01,0xff,0x00,0x01,0x00,0x94,0x1b,0x53,0x04,0x01,0x00,0xd2,0x09,0x11,0x04,
+ 0x01,0x00,0x01,0xff,0x00,0x51,0x05,0x01,0xff,0x00,0x10,0x05,0x01,0xff,0x00,0x04,
+ 0x00,0x01,0x00,0xcf,0x86,0xd5,0x48,0xd4,0x1c,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,
+ 0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x06,0x00,0x52,0x04,0x04,0x00,0x11,0x04,0x04,
+ 0x00,0x06,0x00,0xd3,0x1c,0xd2,0x0c,0x51,0x04,0x06,0x00,0x10,0x04,0x06,0x00,0x07,
+ 0x00,0xd1,0x08,0x10,0x04,0x07,0x00,0x08,0x00,0x10,0x04,0x08,0x00,0x06,0x00,0x52,
+ 0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x06,0x00,0xd4,0x23,0xd3,
+ 0x14,0x52,0x05,0x06,0xff,0x00,0x91,0x0a,0x10,0x05,0x0a,0xff,0x00,0x00,0xff,0x00,
+ 0x0f,0xff,0x00,0x92,0x0a,0x11,0x05,0x0f,0xff,0x00,0x01,0xff,0x00,0x01,0xff,0x00,
+ 0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x00,0x00,0x01,0x00,
+ 0x01,0x00,0xd0,0x7e,0xcf,0x86,0xd5,0x34,0xd4,0x14,0x53,0x04,0x01,0x00,0x52,0x04,
+ 0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0xd3,0x10,0x52,0x04,
+ 0x08,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x0c,0x00,0x0c,0x00,0x52,0x04,0x0c,0x00,
+ 0x91,0x08,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0xd4,0x1c,0x53,0x04,0x01,0x00,
+ 0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x02,0x00,0x91,0x08,0x10,0x04,
+ 0x03,0x00,0x04,0x00,0x04,0x00,0xd3,0x10,0xd2,0x08,0x11,0x04,0x06,0x00,0x08,0x00,
+ 0x11,0x04,0x08,0x00,0x0b,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x0b,0x00,0x0c,0x00,
+ 0x10,0x04,0x0e,0x00,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x11,0x00,0x13,0x00,
+ 0xcf,0x86,0xd5,0x28,0x54,0x04,0x00,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x01,0xe6,
+ 0x01,0x01,0x01,0xe6,0xd2,0x0c,0x51,0x04,0x01,0x01,0x10,0x04,0x01,0x01,0x01,0xe6,
+ 0x91,0x08,0x10,0x04,0x01,0xe6,0x01,0x00,0x01,0x00,0xd4,0x30,0xd3,0x1c,0xd2,0x0c,
+ 0x91,0x08,0x10,0x04,0x01,0x00,0x01,0xe6,0x04,0x00,0xd1,0x08,0x10,0x04,0x06,0x00,
+ 0x06,0x01,0x10,0x04,0x06,0x01,0x06,0xe6,0x92,0x10,0xd1,0x08,0x10,0x04,0x06,0xdc,
+ 0x06,0xe6,0x10,0x04,0x06,0x01,0x08,0x01,0x09,0xdc,0x93,0x10,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x0a,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x81,0xd0,0x4f,
+ 0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x29,0xd3,0x13,0x52,0x04,0x01,0x00,0x51,0x04,
+ 0x01,0x00,0x10,0x07,0x01,0xff,0xce,0xa9,0x00,0x01,0x00,0x92,0x12,0x51,0x04,0x01,
+ 0x00,0x10,0x06,0x01,0xff,0x4b,0x00,0x01,0xff,0x41,0xcc,0x8a,0x00,0x01,0x00,0x53,
+ 0x04,0x01,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x10,0x04,0x04,
+ 0x00,0x07,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x06,0x00,0x06,0x00,0xcf,0x86,0x95,
+ 0x2c,0xd4,0x18,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0xd1,0x08,0x10,0x04,0x08,
+ 0x00,0x09,0x00,0x10,0x04,0x09,0x00,0x0a,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x0b,
+ 0x00,0x10,0x04,0x0b,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0x68,0xcf,
+ 0x86,0xd5,0x48,0xd4,0x28,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,
+ 0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x92,0x0c,0x91,
+ 0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x11,0x00,0x00,0x00,0x53,0x04,0x01,0x00,0x92,
+ 0x18,0x51,0x04,0x01,0x00,0x10,0x0a,0x01,0xff,0xe2,0x86,0x90,0xcc,0xb8,0x00,0x01,
+ 0xff,0xe2,0x86,0x92,0xcc,0xb8,0x00,0x01,0x00,0x94,0x1a,0x53,0x04,0x01,0x00,0x52,
+ 0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x0a,0x01,0xff,0xe2,0x86,0x94,0xcc,0xb8,
+ 0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x2e,0x94,0x2a,0x53,0x04,0x01,0x00,0x52,
+ 0x04,0x01,0x00,0xd1,0x0e,0x10,0x04,0x01,0x00,0x01,0xff,0xe2,0x87,0x90,0xcc,0xb8,
+ 0x00,0x10,0x0a,0x01,0xff,0xe2,0x87,0x94,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x87,0x92,
+ 0xcc,0xb8,0x00,0x01,0x00,0xd4,0x14,0x53,0x04,0x01,0x00,0x92,0x0c,0x51,0x04,0x01,
+ 0x00,0x10,0x04,0x01,0x00,0x04,0x00,0x04,0x00,0x93,0x08,0x12,0x04,0x04,0x00,0x06,
+ 0x00,0x06,0x00,0xe2,0x38,0x02,0xe1,0x3f,0x01,0xd0,0x68,0xcf,0x86,0xd5,0x3e,0x94,
+ 0x3a,0xd3,0x16,0x52,0x04,0x01,0x00,0x91,0x0e,0x10,0x0a,0x01,0xff,0xe2,0x88,0x83,
+ 0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0xd2,0x12,0x91,0x0e,0x10,0x04,0x01,0x00,0x01,
+ 0xff,0xe2,0x88,0x88,0xcc,0xb8,0x00,0x01,0x00,0x91,0x0e,0x10,0x0a,0x01,0xff,0xe2,
+ 0x88,0x8b,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x24,0x93,0x20,0x52,
+ 0x04,0x01,0x00,0xd1,0x0e,0x10,0x0a,0x01,0xff,0xe2,0x88,0xa3,0xcc,0xb8,0x00,0x01,
+ 0x00,0x10,0x0a,0x01,0xff,0xe2,0x88,0xa5,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01,
+ 0x00,0xcf,0x86,0xd5,0x48,0x94,0x44,0xd3,0x2e,0xd2,0x12,0x91,0x0e,0x10,0x04,0x01,
+ 0x00,0x01,0xff,0xe2,0x88,0xbc,0xcc,0xb8,0x00,0x01,0x00,0xd1,0x0e,0x10,0x0a,0x01,
+ 0xff,0xe2,0x89,0x83,0xcc,0xb8,0x00,0x01,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xe2,
+ 0x89,0x85,0xcc,0xb8,0x00,0x92,0x12,0x91,0x0e,0x10,0x04,0x01,0x00,0x01,0xff,0xe2,
+ 0x89,0x88,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x40,0xd3,0x1e,0x92,
+ 0x1a,0xd1,0x0c,0x10,0x08,0x01,0xff,0x3d,0xcc,0xb8,0x00,0x01,0x00,0x10,0x0a,0x01,
+ 0xff,0xe2,0x89,0xa1,0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,
+ 0x0e,0x10,0x04,0x01,0x00,0x01,0xff,0xe2,0x89,0x8d,0xcc,0xb8,0x00,0x10,0x08,0x01,
+ 0xff,0x3c,0xcc,0xb8,0x00,0x01,0xff,0x3e,0xcc,0xb8,0x00,0xd3,0x30,0xd2,0x18,0x91,
+ 0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xa4,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x89,0xa5,
+ 0xcc,0xb8,0x00,0x01,0x00,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xb2,0xcc,0xb8,
+ 0x00,0x01,0xff,0xe2,0x89,0xb3,0xcc,0xb8,0x00,0x01,0x00,0x92,0x18,0x91,0x14,0x10,
+ 0x0a,0x01,0xff,0xe2,0x89,0xb6,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x89,0xb7,0xcc,0xb8,
+ 0x00,0x01,0x00,0x01,0x00,0xd0,0x86,0xcf,0x86,0xd5,0x50,0x94,0x4c,0xd3,0x30,0xd2,
+ 0x18,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xba,0xcc,0xb8,0x00,0x01,0xff,0xe2,
+ 0x89,0xbb,0xcc,0xb8,0x00,0x01,0x00,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x8a,0x82,
+ 0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0x83,0xcc,0xb8,0x00,0x01,0x00,0x92,0x18,0x91,
+ 0x14,0x10,0x0a,0x01,0xff,0xe2,0x8a,0x86,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0x87,
+ 0xcc,0xb8,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x30,0x53,0x04,0x01,0x00,0x52,
+ 0x04,0x01,0x00,0xd1,0x14,0x10,0x0a,0x01,0xff,0xe2,0x8a,0xa2,0xcc,0xb8,0x00,0x01,
+ 0xff,0xe2,0x8a,0xa8,0xcc,0xb8,0x00,0x10,0x0a,0x01,0xff,0xe2,0x8a,0xa9,0xcc,0xb8,
+ 0x00,0x01,0xff,0xe2,0x8a,0xab,0xcc,0xb8,0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,
+ 0x00,0xd4,0x5c,0xd3,0x2c,0x92,0x28,0xd1,0x14,0x10,0x0a,0x01,0xff,0xe2,0x89,0xbc,
+ 0xcc,0xb8,0x00,0x01,0xff,0xe2,0x89,0xbd,0xcc,0xb8,0x00,0x10,0x0a,0x01,0xff,0xe2,
+ 0x8a,0x91,0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0x92,0xcc,0xb8,0x00,0x01,0x00,0xd2,
+ 0x18,0x51,0x04,0x01,0x00,0x10,0x0a,0x01,0xff,0xe2,0x8a,0xb2,0xcc,0xb8,0x00,0x01,
+ 0xff,0xe2,0x8a,0xb3,0xcc,0xb8,0x00,0x91,0x14,0x10,0x0a,0x01,0xff,0xe2,0x8a,0xb4,
+ 0xcc,0xb8,0x00,0x01,0xff,0xe2,0x8a,0xb5,0xcc,0xb8,0x00,0x01,0x00,0x93,0x0c,0x92,
+ 0x08,0x11,0x04,0x01,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0xd1,0x64,0xd0,0x3e,0xcf,
+ 0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,0x00,0x04,
+ 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x94,0x20,0x53,0x04,0x01,0x00,0x92,
+ 0x18,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x80,0x88,0x00,0x10,0x08,0x01,
+ 0xff,0xe3,0x80,0x89,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,
+ 0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,
+ 0x04,0x01,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x06,0x00,0x04,0x00,0x04,0x00,0xd0,
+ 0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00,0x92,0x0c,0x51,
+ 0x04,0x04,0x00,0x10,0x04,0x04,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0xcf,0x86,0xd5,
+ 0x2c,0xd4,0x14,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x51,0x04,0x06,0x00,0x10,
+ 0x04,0x06,0x00,0x07,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x07,0x00,0x08,
+ 0x00,0x08,0x00,0x08,0x00,0x12,0x04,0x08,0x00,0x09,0x00,0xd4,0x14,0x53,0x04,0x09,
+ 0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0xd3,
+ 0x08,0x12,0x04,0x0c,0x00,0x10,0x00,0xd2,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x10,
+ 0x00,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x13,0x00,0xd3,0xa6,0xd2,
+ 0x74,0xd1,0x40,0xd0,0x22,0xcf,0x86,0x55,0x04,0x01,0x00,0x94,0x18,0x93,0x14,0x52,
+ 0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x04,0x00,0x10,0x04,0x04,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,0x53,0x04,0x01,0x00,0x92,
+ 0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,
+ 0x00,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x14,0x53,
+ 0x04,0x01,0x00,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x06,0x00,0x06,
+ 0x00,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x51,0x04,0x06,0x00,0x10,0x04,0x06,
+ 0x00,0x07,0x00,0xd1,0x06,0xcf,0x06,0x01,0x00,0xd0,0x1a,0xcf,0x86,0x95,0x14,0x54,
+ 0x04,0x01,0x00,0x93,0x0c,0x52,0x04,0x01,0x00,0x11,0x04,0x01,0x00,0x06,0x00,0x06,
+ 0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x13,0x04,0x04,
+ 0x00,0x06,0x00,0xd2,0xdc,0xd1,0x48,0xd0,0x26,0xcf,0x86,0x95,0x20,0x54,0x04,0x01,
+ 0x00,0xd3,0x0c,0x52,0x04,0x01,0x00,0x11,0x04,0x07,0x00,0x06,0x00,0x92,0x0c,0x91,
+ 0x08,0x10,0x04,0x08,0x00,0x04,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0x55,
+ 0x04,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x04,0x00,0x06,
+ 0x00,0x06,0x00,0x52,0x04,0x06,0x00,0x11,0x04,0x06,0x00,0x08,0x00,0xd0,0x5e,0xcf,
+ 0x86,0xd5,0x2c,0xd4,0x10,0x53,0x04,0x06,0x00,0x92,0x08,0x11,0x04,0x06,0x00,0x07,
+ 0x00,0x07,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x07,0x00,0x08,0x00,0x08,0x00,0x52,
+ 0x04,0x08,0x00,0x91,0x08,0x10,0x04,0x08,0x00,0x0a,0x00,0x0b,0x00,0xd4,0x10,0x93,
+ 0x0c,0x92,0x08,0x11,0x04,0x07,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xd3,0x10,0x92,
+ 0x0c,0x51,0x04,0x08,0x00,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x52,0x04,0x0a,
+ 0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x1c,0x94,
+ 0x18,0xd3,0x08,0x12,0x04,0x0a,0x00,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,
+ 0x00,0x10,0x04,0x0c,0x00,0x0b,0x00,0x0b,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x51,
+ 0x04,0x0b,0x00,0x10,0x04,0x0c,0x00,0x0b,0x00,0x0c,0x00,0x0b,0x00,0x0b,0x00,0xd1,
+ 0xa8,0xd0,0x42,0xcf,0x86,0xd5,0x28,0x94,0x24,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,
+ 0x04,0x10,0x00,0x01,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x0c,0x00,0x01,
+ 0x00,0x92,0x08,0x11,0x04,0x01,0x00,0x0c,0x00,0x01,0x00,0x01,0x00,0x94,0x14,0x53,
+ 0x04,0x01,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x01,0x00,0x01,0x00,0x01,
+ 0x00,0x01,0x00,0xcf,0x86,0xd5,0x40,0xd4,0x18,0x53,0x04,0x01,0x00,0x52,0x04,0x01,
+ 0x00,0xd1,0x08,0x10,0x04,0x0c,0x00,0x01,0x00,0x10,0x04,0x0c,0x00,0x01,0x00,0xd3,
+ 0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x0c,0x00,0x51,0x04,0x0c,
+ 0x00,0x10,0x04,0x01,0x00,0x0b,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,
+ 0x04,0x01,0x00,0x0c,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c,
+ 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x06,0x00,0x93,0x0c,0x52,0x04,0x06,0x00,0x11,
+ 0x04,0x06,0x00,0x01,0x00,0x01,0x00,0xd0,0x3e,0xcf,0x86,0xd5,0x18,0x54,0x04,0x01,
+ 0x00,0x93,0x10,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x0c,0x00,0x0c,
+ 0x00,0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c,
+ 0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,
+ 0x04,0x01,0x00,0x0c,0x00,0xcf,0x86,0xd5,0x2c,0x94,0x28,0xd3,0x10,0x52,0x04,0x08,
+ 0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x09,0x00,0xd2,0x0c,0x51,0x04,0x09,
+ 0x00,0x10,0x04,0x09,0x00,0x0d,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x0d,0x00,0x0c,
+ 0x00,0x06,0x00,0x94,0x0c,0x53,0x04,0x06,0x00,0x12,0x04,0x06,0x00,0x0a,0x00,0x06,
+ 0x00,0xe4,0x39,0x01,0xd3,0x0c,0xd2,0x06,0xcf,0x06,0x04,0x00,0xcf,0x06,0x06,0x00,
+ 0xd2,0x30,0xd1,0x06,0xcf,0x06,0x06,0x00,0xd0,0x06,0xcf,0x06,0x06,0x00,0xcf,0x86,
+ 0x95,0x1e,0x54,0x04,0x06,0x00,0x53,0x04,0x06,0x00,0x52,0x04,0x06,0x00,0x91,0x0e,
+ 0x10,0x0a,0x06,0xff,0xe2,0xab,0x9d,0xcc,0xb8,0x00,0x06,0x00,0x06,0x00,0x06,0x00,
+ 0xd1,0x80,0xd0,0x3a,0xcf,0x86,0xd5,0x28,0xd4,0x10,0x53,0x04,0x07,0x00,0x52,0x04,
+ 0x07,0x00,0x11,0x04,0x07,0x00,0x08,0x00,0xd3,0x08,0x12,0x04,0x08,0x00,0x09,0x00,
+ 0x92,0x0c,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x94,0x0c,
+ 0x93,0x08,0x12,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0xcf,0x86,0xd5,0x30,
+ 0xd4,0x14,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,
+ 0x10,0x00,0x10,0x00,0xd3,0x10,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,
+ 0x0b,0x00,0x0b,0x00,0x92,0x08,0x11,0x04,0x0b,0x00,0x10,0x00,0x10,0x00,0x54,0x04,
+ 0x10,0x00,0x93,0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x00,0x00,0x10,0x00,0x10,0x00,
+ 0xd0,0x32,0xcf,0x86,0xd5,0x14,0x54,0x04,0x10,0x00,0x93,0x0c,0x52,0x04,0x10,0x00,
+ 0x11,0x04,0x10,0x00,0x00,0x00,0x10,0x00,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,
+ 0xd2,0x08,0x11,0x04,0x10,0x00,0x14,0x00,0x91,0x08,0x10,0x04,0x14,0x00,0x10,0x00,
+ 0x10,0x00,0xcf,0x86,0xd5,0x28,0xd4,0x14,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x10,0x00,0x15,0x00,0x10,0x00,0x10,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,
+ 0x10,0x00,0x10,0x04,0x13,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0xd4,0x0c,0x53,0x04,
+ 0x14,0x00,0x12,0x04,0x14,0x00,0x11,0x00,0x53,0x04,0x14,0x00,0x52,0x04,0x14,0x00,
+ 0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x15,0x00,0xe3,0xb9,0x01,0xd2,0xac,0xd1,
+ 0x68,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x08,0x00,0x94,0x14,0x53,0x04,0x08,0x00,0x52,
+ 0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,0x08,0x00,0xcf,
+ 0x86,0xd5,0x18,0x54,0x04,0x08,0x00,0x53,0x04,0x08,0x00,0x52,0x04,0x08,0x00,0x51,
+ 0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,0xd4,0x14,0x53,0x04,0x09,0x00,0x52,
+ 0x04,0x09,0x00,0x91,0x08,0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0xd3,0x10,0x92,
+ 0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x0a,0x00,0x0a,0x00,0x09,0x00,0x52,0x04,0x0a,
+ 0x00,0x11,0x04,0x0a,0x00,0x0b,0x00,0xd0,0x06,0xcf,0x06,0x08,0x00,0xcf,0x86,0x55,
+ 0x04,0x08,0x00,0xd4,0x1c,0x53,0x04,0x08,0x00,0xd2,0x0c,0x51,0x04,0x08,0x00,0x10,
+ 0x04,0x08,0x00,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x0b,0xe6,0xd3,
+ 0x0c,0x92,0x08,0x11,0x04,0x0b,0xe6,0x0d,0x00,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,
+ 0x04,0x00,0x00,0x08,0x00,0x08,0x00,0x08,0x00,0xd1,0x6c,0xd0,0x2a,0xcf,0x86,0x55,
+ 0x04,0x08,0x00,0x94,0x20,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,
+ 0x04,0x00,0x00,0x0d,0x00,0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x0d,
+ 0x00,0x00,0x00,0x08,0x00,0xcf,0x86,0x55,0x04,0x08,0x00,0xd4,0x1c,0xd3,0x0c,0x52,
+ 0x04,0x08,0x00,0x11,0x04,0x08,0x00,0x0d,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,
+ 0x00,0x10,0x04,0x00,0x00,0x08,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,
+ 0x04,0x00,0x00,0x0c,0x09,0xd0,0x5a,0xcf,0x86,0xd5,0x18,0x54,0x04,0x08,0x00,0x93,
+ 0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,0x00,
+ 0x00,0xd4,0x20,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,
+ 0x00,0x00,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,
+ 0x00,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,
+ 0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,0x00,0xcf,
+ 0x86,0x95,0x40,0xd4,0x20,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,
+ 0x04,0x08,0x00,0x00,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,
+ 0x00,0x00,0x00,0xd3,0x10,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,
+ 0x00,0x00,0x00,0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x00,
+ 0x00,0x0a,0xe6,0xd2,0x9c,0xd1,0x68,0xd0,0x32,0xcf,0x86,0xd5,0x14,0x54,0x04,0x08,
+ 0x00,0x53,0x04,0x08,0x00,0x52,0x04,0x0a,0x00,0x11,0x04,0x08,0x00,0x0a,0x00,0x54,
+ 0x04,0x0a,0x00,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0a,0x00,0x0b,0x00,0x0d,
+ 0x00,0x0d,0x00,0x12,0x04,0x0d,0x00,0x10,0x00,0xcf,0x86,0x95,0x30,0x94,0x2c,0xd3,
+ 0x18,0xd2,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x12,0x00,0x91,0x08,0x10,
+ 0x04,0x12,0x00,0x13,0x00,0x13,0x00,0xd2,0x08,0x11,0x04,0x13,0x00,0x14,0x00,0x51,
+ 0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0xd0,0x1e,0xcf,
+ 0x86,0x95,0x18,0x54,0x04,0x04,0x00,0x53,0x04,0x04,0x00,0x92,0x0c,0x51,0x04,0x04,
+ 0x00,0x10,0x04,0x00,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xcf,0x86,0x55,0x04,0x04,
+ 0x00,0x54,0x04,0x04,0x00,0x93,0x08,0x12,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0xd1,
+ 0x06,0xcf,0x06,0x04,0x00,0xd0,0x06,0xcf,0x06,0x04,0x00,0xcf,0x86,0xd5,0x14,0x54,
+ 0x04,0x04,0x00,0x93,0x0c,0x52,0x04,0x04,0x00,0x11,0x04,0x04,0x00,0x00,0x00,0x00,
+ 0x00,0x54,0x04,0x00,0x00,0x53,0x04,0x04,0x00,0x12,0x04,0x04,0x00,0x00,0x00,0xcf,
+ 0x86,0xe5,0xa6,0x05,0xe4,0x9f,0x05,0xe3,0x96,0x04,0xe2,0xe4,0x03,0xe1,0xc0,0x01,
+ 0xd0,0x3e,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x1c,0x53,0x04,0x01,0x00,0xd2,0x0c,
+ 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0xda,0x01,0xe4,0x91,0x08,0x10,0x04,0x01,0xe8,
+ 0x01,0xde,0x01,0xe0,0x53,0x04,0x01,0x00,0xd2,0x0c,0x51,0x04,0x04,0x00,0x10,0x04,
+ 0x04,0x00,0x06,0x00,0x51,0x04,0x06,0x00,0x10,0x04,0x04,0x00,0x01,0x00,0xcf,0x86,
+ 0xd5,0xaa,0xd4,0x32,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,
+ 0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,
+ 0x8b,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0x8d,0xe3,0x82,
+ 0x99,0x00,0x01,0x00,0xd3,0x3c,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,
+ 0x8f,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0x91,0xe3,0x82,
+ 0x99,0x00,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x93,0xe3,0x82,0x99,
+ 0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0x95,0xe3,0x82,0x99,0x00,0x01,0x00,
+ 0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x97,0xe3,0x82,0x99,0x00,0x01,
+ 0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0x99,0xe3,0x82,0x99,0x00,0x01,0x00,0xd1,0x0f,
+ 0x10,0x0b,0x01,0xff,0xe3,0x81,0x9b,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,
+ 0xff,0xe3,0x81,0x9d,0xe3,0x82,0x99,0x00,0x01,0x00,0xd4,0x53,0xd3,0x3c,0xd2,0x1e,
+ 0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0x9f,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,
+ 0x0b,0x01,0xff,0xe3,0x81,0xa1,0xe3,0x82,0x99,0x00,0x01,0x00,0xd1,0x0f,0x10,0x04,
+ 0x01,0x00,0x01,0xff,0xe3,0x81,0xa4,0xe3,0x82,0x99,0x00,0x10,0x04,0x01,0x00,0x01,
+ 0xff,0xe3,0x81,0xa6,0xe3,0x82,0x99,0x00,0x92,0x13,0x91,0x0f,0x10,0x04,0x01,0x00,
+ 0x01,0xff,0xe3,0x81,0xa8,0xe3,0x82,0x99,0x00,0x01,0x00,0x01,0x00,0xd3,0x4a,0xd2,
+ 0x25,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe3,0x81,0xaf,0xe3,0x82,0x99,0x00,0x01,0xff,
+ 0xe3,0x81,0xaf,0xe3,0x82,0x9a,0x00,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x81,0xb2,
+ 0xe3,0x82,0x99,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x81,0xb2,0xe3,0x82,0x9a,
+ 0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0xb5,0xe3,0x82,0x99,0x00,0x01,0xff,
+ 0xe3,0x81,0xb5,0xe3,0x82,0x9a,0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x04,0x01,0x00,0x01,
+ 0xff,0xe3,0x81,0xb8,0xe3,0x82,0x99,0x00,0x10,0x0b,0x01,0xff,0xe3,0x81,0xb8,0xe3,
+ 0x82,0x9a,0x00,0x01,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,0xe3,0x81,0xbb,0xe3,0x82,
+ 0x99,0x00,0x01,0xff,0xe3,0x81,0xbb,0xe3,0x82,0x9a,0x00,0x01,0x00,0xd0,0xee,0xcf,
+ 0x86,0xd5,0x42,0x54,0x04,0x01,0x00,0xd3,0x1b,0x52,0x04,0x01,0x00,0xd1,0x0f,0x10,
+ 0x0b,0x01,0xff,0xe3,0x81,0x86,0xe3,0x82,0x99,0x00,0x06,0x00,0x10,0x04,0x06,0x00,
+ 0x00,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x00,0x00,0x01,0x08,0x10,0x04,0x01,0x08,
+ 0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0x9d,0xe3,0x82,0x99,
+ 0x00,0x06,0x00,0xd4,0x32,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x06,0x00,0x01,
+ 0x00,0x01,0x00,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,
+ 0x82,0xab,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xad,0xe3,
+ 0x82,0x99,0x00,0x01,0x00,0xd3,0x3c,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,
+ 0x82,0xaf,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb1,0xe3,
+ 0x82,0x99,0x00,0x01,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb3,0xe3,0x82,
+ 0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb5,0xe3,0x82,0x99,0x00,0x01,
+ 0x00,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb7,0xe3,0x82,0x99,0x00,
+ 0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x82,0xb9,0xe3,0x82,0x99,0x00,0x01,0x00,0xd1,
+ 0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xbb,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x0b,
+ 0x01,0xff,0xe3,0x82,0xbd,0xe3,0x82,0x99,0x00,0x01,0x00,0xcf,0x86,0xd5,0xd5,0xd4,
+ 0x53,0xd3,0x3c,0xd2,0x1e,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,0x82,0xbf,0xe3,0x82,
+ 0x99,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x83,0x81,0xe3,0x82,0x99,0x00,0x01,
+ 0x00,0xd1,0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x84,0xe3,0x82,0x99,0x00,
+ 0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x86,0xe3,0x82,0x99,0x00,0x92,0x13,0x91,
+ 0x0f,0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x88,0xe3,0x82,0x99,0x00,0x01,0x00,
+ 0x01,0x00,0xd3,0x4a,0xd2,0x25,0xd1,0x16,0x10,0x0b,0x01,0xff,0xe3,0x83,0x8f,0xe3,
+ 0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0x8f,0xe3,0x82,0x9a,0x00,0x10,0x04,0x01,0x00,
+ 0x01,0xff,0xe3,0x83,0x92,0xe3,0x82,0x99,0x00,0xd1,0x0f,0x10,0x0b,0x01,0xff,0xe3,
+ 0x83,0x92,0xe3,0x82,0x9a,0x00,0x01,0x00,0x10,0x0b,0x01,0xff,0xe3,0x83,0x95,0xe3,
+ 0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0x95,0xe3,0x82,0x9a,0x00,0xd2,0x1e,0xd1,0x0f,
+ 0x10,0x04,0x01,0x00,0x01,0xff,0xe3,0x83,0x98,0xe3,0x82,0x99,0x00,0x10,0x0b,0x01,
+ 0xff,0xe3,0x83,0x98,0xe3,0x82,0x9a,0x00,0x01,0x00,0x91,0x16,0x10,0x0b,0x01,0xff,
+ 0xe3,0x83,0x9b,0xe3,0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0x9b,0xe3,0x82,0x9a,0x00,
+ 0x01,0x00,0x54,0x04,0x01,0x00,0xd3,0x22,0x52,0x04,0x01,0x00,0xd1,0x0f,0x10,0x0b,
+ 0x01,0xff,0xe3,0x82,0xa6,0xe3,0x82,0x99,0x00,0x01,0x00,0x10,0x04,0x01,0x00,0x01,
+ 0xff,0xe3,0x83,0xaf,0xe3,0x82,0x99,0x00,0xd2,0x25,0xd1,0x16,0x10,0x0b,0x01,0xff,
+ 0xe3,0x83,0xb0,0xe3,0x82,0x99,0x00,0x01,0xff,0xe3,0x83,0xb1,0xe3,0x82,0x99,0x00,
+ 0x10,0x0b,0x01,0xff,0xe3,0x83,0xb2,0xe3,0x82,0x99,0x00,0x01,0x00,0x51,0x04,0x01,
+ 0x00,0x10,0x0b,0x01,0xff,0xe3,0x83,0xbd,0xe3,0x82,0x99,0x00,0x06,0x00,0xd1,0x65,
+ 0xd0,0x46,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x52,0x04,0x00,0x00,0x91,0x08,
+ 0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd4,0x18,0x53,0x04,
+ 0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x0a,0x00,0x10,0x04,
+ 0x13,0x00,0x14,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,
+ 0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x94,0x15,0x93,0x11,
+ 0x52,0x04,0x01,0x00,0x91,0x09,0x10,0x05,0x01,0xff,0x00,0x01,0x00,0x01,0x00,0x01,
+ 0x00,0x01,0x00,0xd0,0x32,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x01,0x00,0x52,
+ 0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x54,
+ 0x04,0x04,0x00,0x53,0x04,0x04,0x00,0x92,0x0c,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,
+ 0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x08,0x14,0x04,0x08,0x00,0x0a,0x00,0x94,
+ 0x0c,0x93,0x08,0x12,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0x06,0x00,0xd2,0xa4,0xd1,
+ 0x5c,0xd0,0x22,0xcf,0x86,0x95,0x1c,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,
+ 0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x07,0x00,0x10,0x04,0x07,0x00,0x00,
+ 0x00,0x01,0x00,0xcf,0x86,0xd5,0x20,0xd4,0x0c,0x93,0x08,0x12,0x04,0x01,0x00,0x0b,
+ 0x00,0x0b,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x07,0x00,0x06,0x00,0x06,
+ 0x00,0x06,0x00,0x06,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,
+ 0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x08,0x00,0x01,0x00,0xd0,0x1e,0xcf,0x86,0x55,
+ 0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x01,
+ 0x00,0x06,0x00,0x06,0x00,0x06,0x00,0x06,0x00,0xcf,0x86,0xd5,0x10,0x94,0x0c,0x53,
+ 0x04,0x01,0x00,0x12,0x04,0x01,0x00,0x07,0x00,0x01,0x00,0x54,0x04,0x01,0x00,0x53,
+ 0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x16,
+ 0x00,0xd1,0x30,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,
+ 0x04,0x01,0x00,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,
+ 0x00,0x07,0x00,0x92,0x0c,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x01,0x00,0x01,
+ 0x00,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x14,0x54,0x04,0x01,0x00,0x53,
+ 0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x11,0x04,0x01,0x00,0x07,0x00,0x54,0x04,0x01,
+ 0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,
+ 0x00,0x07,0x00,0xcf,0x06,0x04,0x00,0xcf,0x06,0x04,0x00,0xd1,0x48,0xd0,0x40,0xcf,
+ 0x86,0xd5,0x06,0xcf,0x06,0x04,0x00,0xd4,0x06,0xcf,0x06,0x04,0x00,0xd3,0x2c,0xd2,
+ 0x06,0xcf,0x06,0x04,0x00,0xd1,0x06,0xcf,0x06,0x04,0x00,0xd0,0x1a,0xcf,0x86,0x55,
+ 0x04,0x04,0x00,0x54,0x04,0x04,0x00,0x93,0x0c,0x52,0x04,0x04,0x00,0x11,0x04,0x04,
+ 0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x07,0x00,0xcf,0x06,0x01,0x00,0xcf,0x86,0xcf,
+ 0x06,0x01,0x00,0xcf,0x86,0xcf,0x06,0x01,0x00,0xe2,0x71,0x05,0xd1,0x8c,0xd0,0x08,
+ 0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01,0x00,0xd4,0x06,
+ 0xcf,0x06,0x01,0x00,0xd3,0x06,0xcf,0x06,0x01,0x00,0xd2,0x06,0xcf,0x06,0x01,0x00,
+ 0xd1,0x06,0xcf,0x06,0x01,0x00,0xd0,0x22,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x10,
+ 0x93,0x0c,0x52,0x04,0x01,0x00,0x11,0x04,0x01,0x00,0x08,0x00,0x08,0x00,0x53,0x04,
+ 0x08,0x00,0x12,0x04,0x08,0x00,0x0a,0x00,0xcf,0x86,0xd5,0x28,0xd4,0x18,0xd3,0x08,
+ 0x12,0x04,0x0a,0x00,0x0b,0x00,0x52,0x04,0x0b,0x00,0x91,0x08,0x10,0x04,0x0d,0x00,
+ 0x11,0x00,0x11,0x00,0x93,0x0c,0x52,0x04,0x11,0x00,0x11,0x04,0x11,0x00,0x13,0x00,
+ 0x13,0x00,0x94,0x14,0x53,0x04,0x13,0x00,0x92,0x0c,0x51,0x04,0x13,0x00,0x10,0x04,
+ 0x13,0x00,0x14,0x00,0x14,0x00,0x00,0x00,0xe0,0xdb,0x04,0xcf,0x86,0xe5,0xdf,0x01,
+ 0xd4,0x06,0xcf,0x06,0x04,0x00,0xd3,0x74,0xd2,0x6e,0xd1,0x06,0xcf,0x06,0x04,0x00,
+ 0xd0,0x3e,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x04,0x00,0x52,0x04,0x04,0x00,
+ 0x91,0x08,0x10,0x04,0x04,0x00,0x00,0x00,0x00,0x00,0x04,0x00,0xd4,0x10,0x93,0x0c,
+ 0x92,0x08,0x11,0x04,0x04,0x00,0x06,0x00,0x04,0x00,0x04,0x00,0x93,0x10,0x52,0x04,
+ 0x04,0x00,0x91,0x08,0x10,0x04,0x06,0x00,0x04,0x00,0x04,0x00,0x04,0x00,0xcf,0x86,
+ 0x95,0x24,0x94,0x20,0x93,0x1c,0xd2,0x0c,0x91,0x08,0x10,0x04,0x04,0x00,0x06,0x00,
+ 0x04,0x00,0xd1,0x08,0x10,0x04,0x04,0x00,0x06,0x00,0x10,0x04,0x04,0x00,0x00,0x00,
+ 0x00,0x00,0x0b,0x00,0x0b,0x00,0xcf,0x06,0x0a,0x00,0xd2,0x84,0xd1,0x4c,0xd0,0x16,
+ 0xcf,0x86,0x55,0x04,0x0a,0x00,0x94,0x0c,0x53,0x04,0x0a,0x00,0x12,0x04,0x0a,0x00,
+ 0x00,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,0x0a,0x00,0xd4,0x1c,0xd3,0x0c,0x92,0x08,
+ 0x11,0x04,0x0c,0x00,0x0a,0x00,0x0a,0x00,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,
+ 0x10,0x04,0x0a,0x00,0x0a,0xe6,0xd3,0x08,0x12,0x04,0x0a,0x00,0x0d,0xe6,0x52,0x04,
+ 0x0d,0xe6,0x11,0x04,0x0a,0xe6,0x0a,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,
+ 0x0a,0x00,0x53,0x04,0x0a,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,
+ 0x11,0xe6,0x0d,0xe6,0x0b,0x00,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,0x00,
+ 0x93,0x0c,0x92,0x08,0x11,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0x00,0x00,0x00,0xd1,0x40,
+ 0xd0,0x3a,0xcf,0x86,0xd5,0x24,0x54,0x04,0x08,0x00,0xd3,0x10,0x52,0x04,0x08,0x00,
+ 0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x09,0x00,0x92,0x0c,0x51,0x04,0x09,0x00,
+ 0x10,0x04,0x09,0x00,0x0a,0x00,0x0a,0x00,0x94,0x10,0x93,0x0c,0x92,0x08,0x11,0x04,
+ 0x09,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0x0a,0x00,0xcf,0x06,0x0a,0x00,0xd0,0x5e,
+ 0xcf,0x86,0xd5,0x28,0xd4,0x18,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,0xd1,0x08,
+ 0x10,0x04,0x0a,0x00,0x0c,0x00,0x10,0x04,0x0c,0x00,0x11,0x00,0x93,0x0c,0x92,0x08,
+ 0x11,0x04,0x0c,0x00,0x0d,0x00,0x10,0x00,0x10,0x00,0xd4,0x1c,0x53,0x04,0x0c,0x00,
+ 0xd2,0x0c,0x51,0x04,0x0c,0x00,0x10,0x04,0x0d,0x00,0x10,0x00,0x51,0x04,0x10,0x00,
+ 0x10,0x04,0x12,0x00,0x14,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x10,0x00,0x11,0x00,
+ 0x11,0x00,0x92,0x08,0x11,0x04,0x14,0x00,0x15,0x00,0x15,0x00,0xcf,0x86,0xd5,0x1c,
+ 0x94,0x18,0x93,0x14,0xd2,0x08,0x11,0x04,0x00,0x00,0x15,0x00,0x51,0x04,0x15,0x00,
+ 0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x54,0x04,0x00,0x00,0xd3,0x10,
+ 0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x92,0x0c,
+ 0x51,0x04,0x0d,0x00,0x10,0x04,0x0c,0x00,0x0a,0x00,0x0a,0x00,0xe4,0xf2,0x02,0xe3,
+ 0x65,0x01,0xd2,0x98,0xd1,0x48,0xd0,0x36,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,
+ 0x52,0x04,0x08,0x00,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x09,0x08,0x00,0x08,0x00,
+ 0x08,0x00,0xd4,0x0c,0x53,0x04,0x08,0x00,0x12,0x04,0x08,0x00,0x00,0x00,0x53,0x04,
+ 0x0b,0x00,0x92,0x08,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,
+ 0x09,0x00,0x54,0x04,0x09,0x00,0x13,0x04,0x09,0x00,0x00,0x00,0xd0,0x06,0xcf,0x06,
+ 0x0a,0x00,0xcf,0x86,0xd5,0x2c,0xd4,0x1c,0xd3,0x10,0x52,0x04,0x0a,0x00,0x91,0x08,
+ 0x10,0x04,0x0a,0x09,0x12,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,
+ 0x0a,0x00,0x53,0x04,0x0a,0x00,0x92,0x08,0x11,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,
+ 0x54,0x04,0x0b,0xe6,0xd3,0x0c,0x92,0x08,0x11,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0x00,
+ 0x52,0x04,0x0b,0x00,0x11,0x04,0x11,0x00,0x14,0x00,0xd1,0x60,0xd0,0x22,0xcf,0x86,
+ 0x55,0x04,0x0a,0x00,0x94,0x18,0x53,0x04,0x0a,0x00,0xd2,0x0c,0x51,0x04,0x0a,0x00,
+ 0x10,0x04,0x0a,0x00,0x0a,0xdc,0x11,0x04,0x0a,0xdc,0x0a,0x00,0x0a,0x00,0xcf,0x86,
+ 0xd5,0x24,0x54,0x04,0x0a,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x0a,0x00,0x10,0x04,
+ 0x0a,0x00,0x0a,0x09,0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,
+ 0x00,0x00,0x0a,0x00,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,
+ 0x91,0x08,0x10,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xd0,0x1e,0xcf,0x86,0x55,0x04,
+ 0x0b,0x00,0x54,0x04,0x0b,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04,
+ 0x0b,0x00,0x0b,0x07,0x0b,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x34,0xd4,0x20,0xd3,0x10,
+ 0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x09,0x0b,0x00,0x0b,0x00,0x0b,0x00,0x52,0x04,
+ 0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x00,0x00,0x0b,0x00,0x53,0x04,0x0b,0x00,
+ 0xd2,0x08,0x11,0x04,0x0b,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x0b,0x00,0x54,0x04,
+ 0x10,0x00,0x53,0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,
+ 0x10,0x00,0x00,0x00,0xd2,0xd0,0xd1,0x50,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x0a,0x00,
+ 0x54,0x04,0x0a,0x00,0x93,0x10,0x52,0x04,0x0a,0x00,0x51,0x04,0x0a,0x00,0x10,0x04,
+ 0x0a,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x20,0xd4,0x10,0x53,0x04,0x0a,0x00,
+ 0x52,0x04,0x0a,0x00,0x11,0x04,0x0a,0x00,0x00,0x00,0x53,0x04,0x0a,0x00,0x92,0x08,
+ 0x11,0x04,0x0a,0x00,0x00,0x00,0x0a,0x00,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,
+ 0x12,0x04,0x0b,0x00,0x10,0x00,0xd0,0x3a,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,
+ 0x0b,0x00,0xd3,0x1c,0xd2,0x0c,0x91,0x08,0x10,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0xe6,
+ 0xd1,0x08,0x10,0x04,0x0b,0xdc,0x0b,0x00,0x10,0x04,0x0b,0x00,0x0b,0xe6,0xd2,0x0c,
+ 0x91,0x08,0x10,0x04,0x0b,0xe6,0x0b,0x00,0x0b,0x00,0x11,0x04,0x0b,0x00,0x0b,0xe6,
+ 0xcf,0x86,0xd5,0x2c,0xd4,0x18,0x93,0x14,0x92,0x10,0xd1,0x08,0x10,0x04,0x0b,0x00,
+ 0x0b,0xe6,0x10,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x00,0x00,
+ 0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0b,0x00,0x0b,0x00,0x54,0x04,
+ 0x0d,0x00,0x93,0x10,0x52,0x04,0x0d,0x00,0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x09,
+ 0x00,0x00,0x00,0x00,0xd1,0x8c,0xd0,0x72,0xcf,0x86,0xd5,0x4c,0xd4,0x30,0xd3,0x18,
0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0c,0x00,0x0c,0x00,0x51,0x04,0x0c,0x00,
- 0x10,0x04,0x0c,0x00,0x00,0x00,0x93,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,
- 0x0c,0x00,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,
- 0x94,0x20,0xd3,0x10,0x52,0x04,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,
- 0x00,0x00,0x52,0x04,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,
- 0x10,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0x94,0x10,0x93,0x0c,0x52,0x04,0x11,0x00,
- 0x11,0x04,0x10,0x00,0x15,0x00,0x00,0x00,0x11,0x00,0xd0,0x06,0xcf,0x06,0x11,0x00,
- 0xcf,0x86,0x55,0x04,0x0b,0x00,0xd4,0x14,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,
- 0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0x09,0x00,0x00,0x53,0x04,0x0b,0x00,0x92,0x08,
- 0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x02,0xff,0xff,0xcf,0x86,0xcf,
- 0x06,0x02,0xff,0xff,0xd1,0x76,0xd0,0x09,0xcf,0x86,0xcf,0x06,0x02,0xff,0xff,0xcf,
- 0x86,0x85,0xd4,0x07,0xcf,0x06,0x02,0xff,0xff,0xd3,0x07,0xcf,0x06,0x02,0xff,0xff,
- 0xd2,0x07,0xcf,0x06,0x02,0xff,0xff,0xd1,0x07,0xcf,0x06,0x02,0xff,0xff,0xd0,0x18,
- 0xcf,0x86,0x55,0x05,0x02,0xff,0xff,0x94,0x0d,0x93,0x09,0x12,0x05,0x02,0xff,0xff,
- 0x00,0x00,0x00,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x24,0x94,0x20,0xd3,0x10,0x52,0x04,
- 0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0x92,0x0c,0x51,0x04,
- 0x00,0x00,0x10,0x04,0x00,0x00,0x0b,0x00,0x0b,0x00,0x0b,0x00,0x54,0x04,0x0b,0x00,
- 0x53,0x04,0x0b,0x00,0x12,0x04,0x0b,0x00,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06,
- 0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01,0x00,0xe4,0x9c,0x10,0xe3,0x16,0x08,
- 0xd2,0x06,0xcf,0x06,0x01,0x00,0xe1,0x08,0x04,0xe0,0x04,0x02,0xcf,0x86,0xe5,0x01,
- 0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0xb1,0x88,
- 0x00,0x01,0xff,0xe6,0x9b,0xb4,0x00,0x10,0x08,0x01,0xff,0xe8,0xbb,0x8a,0x00,0x01,
- 0xff,0xe8,0xb3,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xbb,0x91,0x00,0x01,
- 0xff,0xe4,0xb8,0xb2,0x00,0x10,0x08,0x01,0xff,0xe5,0x8f,0xa5,0x00,0x01,0xff,0xe9,
- 0xbe,0x9c,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xbe,0x9c,0x00,0x01,
- 0xff,0xe5,0xa5,0x91,0x00,0x10,0x08,0x01,0xff,0xe9,0x87,0x91,0x00,0x01,0xff,0xe5,
- 0x96,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0xa5,0x88,0x00,0x01,0xff,0xe6,
- 0x87,0xb6,0x00,0x10,0x08,0x01,0xff,0xe7,0x99,0xa9,0x00,0x01,0xff,0xe7,0xbe,0x85,
- 0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x98,0xbf,0x00,0x01,
- 0xff,0xe8,0x9e,0xba,0x00,0x10,0x08,0x01,0xff,0xe8,0xa3,0xb8,0x00,0x01,0xff,0xe9,
- 0x82,0x8f,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xa8,0x82,0x00,0x01,0xff,0xe6,
- 0xb4,0x9b,0x00,0x10,0x08,0x01,0xff,0xe7,0x83,0x99,0x00,0x01,0xff,0xe7,0x8f,0x9e,
- 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x90,0xbd,0x00,0x01,0xff,0xe9,
- 0x85,0xaa,0x00,0x10,0x08,0x01,0xff,0xe9,0xa7,0xb1,0x00,0x01,0xff,0xe4,0xba,0x82,
- 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x8d,0xb5,0x00,0x01,0xff,0xe6,0xac,0x84,
- 0x00,0x10,0x08,0x01,0xff,0xe7,0x88,0x9b,0x00,0x01,0xff,0xe8,0x98,0xad,0x00,0xd4,
- 0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xb8,0x9e,0x00,0x01,
- 0xff,0xe5,0xb5,0x90,0x00,0x10,0x08,0x01,0xff,0xe6,0xbf,0xab,0x00,0x01,0xff,0xe8,
- 0x97,0x8d,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0xa5,0xa4,0x00,0x01,0xff,0xe6,
- 0x8b,0x89,0x00,0x10,0x08,0x01,0xff,0xe8,0x87,0x98,0x00,0x01,0xff,0xe8,0xa0,0x9f,
- 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0xbb,0x8a,0x00,0x01,0xff,0xe6,
- 0x9c,0x97,0x00,0x10,0x08,0x01,0xff,0xe6,0xb5,0xaa,0x00,0x01,0xff,0xe7,0x8b,0xbc,
- 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0x83,0x8e,0x00,0x01,0xff,0xe4,0xbe,0x86,
- 0x00,0x10,0x08,0x01,0xff,0xe5,0x86,0xb7,0x00,0x01,0xff,0xe5,0x8b,0x9e,0x00,0xd3,
- 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x93,0x84,0x00,0x01,0xff,0xe6,
- 0xab,0x93,0x00,0x10,0x08,0x01,0xff,0xe7,0x88,0x90,0x00,0x01,0xff,0xe7,0x9b,0xa7,
- 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x80,0x81,0x00,0x01,0xff,0xe8,0x98,0x86,
- 0x00,0x10,0x08,0x01,0xff,0xe8,0x99,0x9c,0x00,0x01,0xff,0xe8,0xb7,0xaf,0x00,0xd2,
- 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0x9c,0xb2,0x00,0x01,0xff,0xe9,0xad,0xaf,
- 0x00,0x10,0x08,0x01,0xff,0xe9,0xb7,0xba,0x00,0x01,0xff,0xe7,0xa2,0x8c,0x00,0xd1,
- 0x10,0x10,0x08,0x01,0xff,0xe7,0xa5,0xbf,0x00,0x01,0xff,0xe7,0xb6,0xa0,0x00,0x10,
- 0x08,0x01,0xff,0xe8,0x8f,0x89,0x00,0x01,0xff,0xe9,0x8c,0x84,0x00,0xcf,0x86,0xe5,
- 0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xb9,
- 0xbf,0x00,0x01,0xff,0xe8,0xab,0x96,0x00,0x10,0x08,0x01,0xff,0xe5,0xa3,0x9f,0x00,
- 0x01,0xff,0xe5,0xbc,0x84,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0xb1,0xa0,0x00,
- 0x01,0xff,0xe8,0x81,0xbe,0x00,0x10,0x08,0x01,0xff,0xe7,0x89,0xa2,0x00,0x01,0xff,
- 0xe7,0xa3,0x8a,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0xb3,0x82,0x00,
- 0x01,0xff,0xe9,0x9b,0xb7,0x00,0x10,0x08,0x01,0xff,0xe5,0xa3,0x98,0x00,0x01,0xff,
- 0xe5,0xb1,0xa2,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xa8,0x93,0x00,0x01,0xff,
- 0xe6,0xb7,0x9a,0x00,0x10,0x08,0x01,0xff,0xe6,0xbc,0x8f,0x00,0x01,0xff,0xe7,0xb4,
- 0xaf,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0xb8,0xb7,0x00,
- 0x01,0xff,0xe9,0x99,0x8b,0x00,0x10,0x08,0x01,0xff,0xe5,0x8b,0x92,0x00,0x01,0xff,
- 0xe8,0x82,0x8b,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x87,0x9c,0x00,0x01,0xff,
- 0xe5,0x87,0x8c,0x00,0x10,0x08,0x01,0xff,0xe7,0xa8,0x9c,0x00,0x01,0xff,0xe7,0xb6,
- 0xbe,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x8f,0xb1,0x00,0x01,0xff,
- 0xe9,0x99,0xb5,0x00,0x10,0x08,0x01,0xff,0xe8,0xae,0x80,0x00,0x01,0xff,0xe6,0x8b,
- 0x8f,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xa8,0x82,0x00,0x01,0xff,0xe8,0xab,
- 0xbe,0x00,0x10,0x08,0x01,0xff,0xe4,0xb8,0xb9,0x00,0x01,0xff,0xe5,0xaf,0xa7,0x00,
- 0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x80,0x92,0x00,
- 0x01,0xff,0xe7,0x8e,0x87,0x00,0x10,0x08,0x01,0xff,0xe7,0x95,0xb0,0x00,0x01,0xff,
- 0xe5,0x8c,0x97,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0xa3,0xbb,0x00,0x01,0xff,
- 0xe4,0xbe,0xbf,0x00,0x10,0x08,0x01,0xff,0xe5,0xbe,0xa9,0x00,0x01,0xff,0xe4,0xb8,
- 0x8d,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xb3,0x8c,0x00,0x01,0xff,
- 0xe6,0x95,0xb8,0x00,0x10,0x08,0x01,0xff,0xe7,0xb4,0xa2,0x00,0x01,0xff,0xe5,0x8f,
- 0x83,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0xa1,0x9e,0x00,0x01,0xff,0xe7,0x9c,
- 0x81,0x00,0x10,0x08,0x01,0xff,0xe8,0x91,0x89,0x00,0x01,0xff,0xe8,0xaa,0xaa,0x00,
- 0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xae,0xba,0x00,0x01,0xff,
- 0xe8,0xbe,0xb0,0x00,0x10,0x08,0x01,0xff,0xe6,0xb2,0x88,0x00,0x01,0xff,0xe6,0x8b,
- 0xbe,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x8b,0xa5,0x00,0x01,0xff,0xe6,0x8e,
- 0xa0,0x00,0x10,0x08,0x01,0xff,0xe7,0x95,0xa5,0x00,0x01,0xff,0xe4,0xba,0xae,0x00,
- 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x85,0xa9,0x00,0x01,0xff,0xe5,0x87,
- 0x89,0x00,0x10,0x08,0x01,0xff,0xe6,0xa2,0x81,0x00,0x01,0xff,0xe7,0xb3,0xa7,0x00,
- 0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x89,0xaf,0x00,0x01,0xff,0xe8,0xab,0x92,0x00,
- 0x10,0x08,0x01,0xff,0xe9,0x87,0x8f,0x00,0x01,0xff,0xe5,0x8b,0xb5,0x00,0xe0,0x04,
- 0x02,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
- 0x01,0xff,0xe5,0x91,0x82,0x00,0x01,0xff,0xe5,0xa5,0xb3,0x00,0x10,0x08,0x01,0xff,
- 0xe5,0xbb,0xac,0x00,0x01,0xff,0xe6,0x97,0x85,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0xe6,0xbf,0xbe,0x00,0x01,0xff,0xe7,0xa4,0xaa,0x00,0x10,0x08,0x01,0xff,0xe9,0x96,
- 0xad,0x00,0x01,0xff,0xe9,0xa9,0xaa,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0xe9,0xba,0x97,0x00,0x01,0xff,0xe9,0xbb,0x8e,0x00,0x10,0x08,0x01,0xff,0xe5,0x8a,
- 0x9b,0x00,0x01,0xff,0xe6,0x9b,0x86,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xad,
- 0xb7,0x00,0x01,0xff,0xe8,0xbd,0xa2,0x00,0x10,0x08,0x01,0xff,0xe5,0xb9,0xb4,0x00,
- 0x01,0xff,0xe6,0x86,0x90,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0xe6,0x88,0x80,0x00,0x01,0xff,0xe6,0x92,0x9a,0x00,0x10,0x08,0x01,0xff,0xe6,0xbc,
- 0xa3,0x00,0x01,0xff,0xe7,0x85,0x89,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0x92,
- 0x89,0x00,0x01,0xff,0xe7,0xa7,0x8a,0x00,0x10,0x08,0x01,0xff,0xe7,0xb7,0xb4,0x00,
- 0x01,0xff,0xe8,0x81,0xaf,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0xbc,
- 0xa6,0x00,0x01,0xff,0xe8,0x93,0xae,0x00,0x10,0x08,0x01,0xff,0xe9,0x80,0xa3,0x00,
- 0x01,0xff,0xe9,0x8d,0x8a,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x88,0x97,0x00,
- 0x01,0xff,0xe5,0x8a,0xa3,0x00,0x10,0x08,0x01,0xff,0xe5,0x92,0xbd,0x00,0x01,0xff,
- 0xe7,0x83,0x88,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0xe8,0xa3,0x82,0x00,0x01,0xff,0xe8,0xaa,0xaa,0x00,0x10,0x08,0x01,0xff,0xe5,0xbb,
- 0x89,0x00,0x01,0xff,0xe5,0xbf,0xb5,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x8d,
- 0xbb,0x00,0x01,0xff,0xe6,0xae,0xae,0x00,0x10,0x08,0x01,0xff,0xe7,0xb0,0xbe,0x00,
- 0x01,0xff,0xe7,0x8d,0xb5,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe4,0xbb,
- 0xa4,0x00,0x01,0xff,0xe5,0x9b,0xb9,0x00,0x10,0x08,0x01,0xff,0xe5,0xaf,0xa7,0x00,
- 0x01,0xff,0xe5,0xb6,0xba,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x80,0x9c,0x00,
- 0x01,0xff,0xe7,0x8e,0xb2,0x00,0x10,0x08,0x01,0xff,0xe7,0x91,0xa9,0x00,0x01,0xff,
- 0xe7,0xbe,0x9a,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x81,
- 0x86,0x00,0x01,0xff,0xe9,0x88,0xb4,0x00,0x10,0x08,0x01,0xff,0xe9,0x9b,0xb6,0x00,
- 0x01,0xff,0xe9,0x9d,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xa0,0x98,0x00,
- 0x01,0xff,0xe4,0xbe,0x8b,0x00,0x10,0x08,0x01,0xff,0xe7,0xa6,0xae,0x00,0x01,0xff,
- 0xe9,0x86,0xb4,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0x9a,0xb8,0x00,
- 0x01,0xff,0xe6,0x83,0xa1,0x00,0x10,0x08,0x01,0xff,0xe4,0xba,0x86,0x00,0x01,0xff,
- 0xe5,0x83,0x9a,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0xaf,0xae,0x00,0x01,0xff,
- 0xe5,0xb0,0xbf,0x00,0x10,0x08,0x01,0xff,0xe6,0x96,0x99,0x00,0x01,0xff,0xe6,0xa8,
- 0x82,0x00,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,
- 0x08,0x01,0xff,0xe7,0x87,0x8e,0x00,0x01,0xff,0xe7,0x99,0x82,0x00,0x10,0x08,0x01,
- 0xff,0xe8,0x93,0xbc,0x00,0x01,0xff,0xe9,0x81,0xbc,0x00,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0xe9,0xbe,0x8d,0x00,0x01,0xff,0xe6,0x9a,0x88,0x00,0x10,0x08,0x01,0xff,0xe9,
- 0x98,0xae,0x00,0x01,0xff,0xe5,0x8a,0x89,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0xe6,0x9d,0xbb,0x00,0x01,0xff,0xe6,0x9f,0xb3,0x00,0x10,0x08,0x01,0xff,0xe6,
- 0xb5,0x81,0x00,0x01,0xff,0xe6,0xba,0x9c,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,
- 0x90,0x89,0x00,0x01,0xff,0xe7,0x95,0x99,0x00,0x10,0x08,0x01,0xff,0xe7,0xa1,0xab,
- 0x00,0x01,0xff,0xe7,0xb4,0x90,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0xe9,0xa1,0x9e,0x00,0x01,0xff,0xe5,0x85,0xad,0x00,0x10,0x08,0x01,0xff,0xe6,
- 0x88,0xae,0x00,0x01,0xff,0xe9,0x99,0xb8,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,
- 0x80,0xab,0x00,0x01,0xff,0xe5,0xb4,0x99,0x00,0x10,0x08,0x01,0xff,0xe6,0xb7,0xaa,
- 0x00,0x01,0xff,0xe8,0xbc,0xaa,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,
- 0xbe,0x8b,0x00,0x01,0xff,0xe6,0x85,0x84,0x00,0x10,0x08,0x01,0xff,0xe6,0xa0,0x97,
- 0x00,0x01,0xff,0xe7,0x8e,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0x9a,0x86,
- 0x00,0x01,0xff,0xe5,0x88,0xa9,0x00,0x10,0x08,0x01,0xff,0xe5,0x90,0x8f,0x00,0x01,
- 0xff,0xe5,0xb1,0xa5,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
- 0xff,0xe6,0x98,0x93,0x00,0x01,0xff,0xe6,0x9d,0x8e,0x00,0x10,0x08,0x01,0xff,0xe6,
- 0xa2,0xa8,0x00,0x01,0xff,0xe6,0xb3,0xa5,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,
- 0x90,0x86,0x00,0x01,0xff,0xe7,0x97,0xa2,0x00,0x10,0x08,0x01,0xff,0xe7,0xbd,0xb9,
- 0x00,0x01,0xff,0xe8,0xa3,0x8f,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,
- 0xa3,0xa1,0x00,0x01,0xff,0xe9,0x87,0x8c,0x00,0x10,0x08,0x01,0xff,0xe9,0x9b,0xa2,
- 0x00,0x01,0xff,0xe5,0x8c,0xbf,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xba,0xba,
- 0x00,0x01,0xff,0xe5,0x90,0x9d,0x00,0x10,0x08,0x01,0xff,0xe7,0x87,0x90,0x00,0x01,
- 0xff,0xe7,0x92,0x98,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,
- 0x97,0xba,0x00,0x01,0xff,0xe9,0x9a,0xa3,0x00,0x10,0x08,0x01,0xff,0xe9,0xb1,0x97,
- 0x00,0x01,0xff,0xe9,0xba,0x9f,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x9e,0x97,
- 0x00,0x01,0xff,0xe6,0xb7,0x8b,0x00,0x10,0x08,0x01,0xff,0xe8,0x87,0xa8,0x00,0x01,
- 0xff,0xe7,0xab,0x8b,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0xac,0xa0,
- 0x00,0x01,0xff,0xe7,0xb2,0x92,0x00,0x10,0x08,0x01,0xff,0xe7,0x8b,0x80,0x00,0x01,
- 0xff,0xe7,0x82,0x99,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0xad,0x98,0x00,0x01,
- 0xff,0xe4,0xbb,0x80,0x00,0x10,0x08,0x01,0xff,0xe8,0x8c,0xb6,0x00,0x01,0xff,0xe5,
- 0x88,0xba,0x00,0xe2,0xad,0x06,0xe1,0xc4,0x03,0xe0,0xcb,0x01,0xcf,0x86,0xd5,0xe4,
- 0xd4,0x74,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x88,0x87,0x00,
- 0x01,0xff,0xe5,0xba,0xa6,0x00,0x10,0x08,0x01,0xff,0xe6,0x8b,0x93,0x00,0x01,0xff,
- 0xe7,0xb3,0x96,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0xae,0x85,0x00,0x01,0xff,
- 0xe6,0xb4,0x9e,0x00,0x10,0x08,0x01,0xff,0xe6,0x9a,0xb4,0x00,0x01,0xff,0xe8,0xbc,
- 0xbb,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0xa1,0x8c,0x00,0x01,0xff,
- 0xe9,0x99,0x8d,0x00,0x10,0x08,0x01,0xff,0xe8,0xa6,0x8b,0x00,0x01,0xff,0xe5,0xbb,
- 0x93,0x00,0x91,0x10,0x10,0x08,0x01,0xff,0xe5,0x85,0x80,0x00,0x01,0xff,0xe5,0x97,
- 0x80,0x00,0x01,0x00,0xd3,0x34,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x01,0xff,0xe5,0xa1,
- 0x9a,0x00,0x01,0x00,0x10,0x08,0x01,0xff,0xe6,0x99,0xb4,0x00,0x01,0x00,0xd1,0x0c,
- 0x10,0x04,0x01,0x00,0x01,0xff,0xe5,0x87,0x9e,0x00,0x10,0x08,0x01,0xff,0xe7,0x8c,
- 0xaa,0x00,0x01,0xff,0xe7,0x9b,0x8a,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
- 0xe7,0xa4,0xbc,0x00,0x01,0xff,0xe7,0xa5,0x9e,0x00,0x10,0x08,0x01,0xff,0xe7,0xa5,
- 0xa5,0x00,0x01,0xff,0xe7,0xa6,0x8f,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0x9d,
- 0x96,0x00,0x01,0xff,0xe7,0xb2,0xbe,0x00,0x10,0x08,0x01,0xff,0xe7,0xbe,0xbd,0x00,
- 0x01,0x00,0xd4,0x64,0xd3,0x30,0xd2,0x18,0xd1,0x0c,0x10,0x08,0x01,0xff,0xe8,0x98,
- 0x92,0x00,0x01,0x00,0x10,0x08,0x01,0xff,0xe8,0xab,0xb8,0x00,0x01,0x00,0xd1,0x0c,
- 0x10,0x04,0x01,0x00,0x01,0xff,0xe9,0x80,0xb8,0x00,0x10,0x08,0x01,0xff,0xe9,0x83,
- 0xbd,0x00,0x01,0x00,0xd2,0x14,0x51,0x04,0x01,0x00,0x10,0x08,0x01,0xff,0xe9,0xa3,
- 0xaf,0x00,0x01,0xff,0xe9,0xa3,0xbc,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xa4,
- 0xa8,0x00,0x01,0xff,0xe9,0xb6,0xb4,0x00,0x10,0x08,0x0d,0xff,0xe9,0x83,0x9e,0x00,
- 0x0d,0xff,0xe9,0x9a,0xb7,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,0xff,
- 0xe4,0xbe,0xae,0x00,0x06,0xff,0xe5,0x83,0xa7,0x00,0x10,0x08,0x06,0xff,0xe5,0x85,
- 0x8d,0x00,0x06,0xff,0xe5,0x8b,0x89,0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe5,0x8b,
- 0xa4,0x00,0x06,0xff,0xe5,0x8d,0x91,0x00,0x10,0x08,0x06,0xff,0xe5,0x96,0x9d,0x00,
- 0x06,0xff,0xe5,0x98,0x86,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe5,0x99,
- 0xa8,0x00,0x06,0xff,0xe5,0xa1,0x80,0x00,0x10,0x08,0x06,0xff,0xe5,0xa2,0xa8,0x00,
- 0x06,0xff,0xe5,0xb1,0xa4,0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe5,0xb1,0xae,0x00,
- 0x06,0xff,0xe6,0x82,0x94,0x00,0x10,0x08,0x06,0xff,0xe6,0x85,0xa8,0x00,0x06,0xff,
- 0xe6,0x86,0x8e,0x00,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,
- 0x10,0x10,0x08,0x06,0xff,0xe6,0x87,0xb2,0x00,0x06,0xff,0xe6,0x95,0x8f,0x00,0x10,
- 0x08,0x06,0xff,0xe6,0x97,0xa2,0x00,0x06,0xff,0xe6,0x9a,0x91,0x00,0xd1,0x10,0x10,
- 0x08,0x06,0xff,0xe6,0xa2,0x85,0x00,0x06,0xff,0xe6,0xb5,0xb7,0x00,0x10,0x08,0x06,
- 0xff,0xe6,0xb8,0x9a,0x00,0x06,0xff,0xe6,0xbc,0xa2,0x00,0xd2,0x20,0xd1,0x10,0x10,
- 0x08,0x06,0xff,0xe7,0x85,0xae,0x00,0x06,0xff,0xe7,0x88,0xab,0x00,0x10,0x08,0x06,
- 0xff,0xe7,0x90,0xa2,0x00,0x06,0xff,0xe7,0xa2,0x91,0x00,0xd1,0x10,0x10,0x08,0x06,
- 0xff,0xe7,0xa4,0xbe,0x00,0x06,0xff,0xe7,0xa5,0x89,0x00,0x10,0x08,0x06,0xff,0xe7,
- 0xa5,0x88,0x00,0x06,0xff,0xe7,0xa5,0x90,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,
- 0x08,0x06,0xff,0xe7,0xa5,0x96,0x00,0x06,0xff,0xe7,0xa5,0x9d,0x00,0x10,0x08,0x06,
- 0xff,0xe7,0xa6,0x8d,0x00,0x06,0xff,0xe7,0xa6,0x8e,0x00,0xd1,0x10,0x10,0x08,0x06,
- 0xff,0xe7,0xa9,0x80,0x00,0x06,0xff,0xe7,0xaa,0x81,0x00,0x10,0x08,0x06,0xff,0xe7,
- 0xaf,0x80,0x00,0x06,0xff,0xe7,0xb7,0xb4,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,
- 0xff,0xe7,0xb8,0x89,0x00,0x06,0xff,0xe7,0xb9,0x81,0x00,0x10,0x08,0x06,0xff,0xe7,
- 0xbd,0xb2,0x00,0x06,0xff,0xe8,0x80,0x85,0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe8,
- 0x87,0xad,0x00,0x06,0xff,0xe8,0x89,0xb9,0x00,0x10,0x08,0x06,0xff,0xe8,0x89,0xb9,
- 0x00,0x06,0xff,0xe8,0x91,0x97,0x00,0xd4,0x75,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,
- 0x08,0x06,0xff,0xe8,0xa4,0x90,0x00,0x06,0xff,0xe8,0xa6,0x96,0x00,0x10,0x08,0x06,
- 0xff,0xe8,0xac,0x81,0x00,0x06,0xff,0xe8,0xac,0xb9,0x00,0xd1,0x10,0x10,0x08,0x06,
- 0xff,0xe8,0xb3,0x93,0x00,0x06,0xff,0xe8,0xb4,0x88,0x00,0x10,0x08,0x06,0xff,0xe8,
- 0xbe,0xb6,0x00,0x06,0xff,0xe9,0x80,0xb8,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,
- 0xff,0xe9,0x9b,0xa3,0x00,0x06,0xff,0xe9,0x9f,0xbf,0x00,0x10,0x08,0x06,0xff,0xe9,
- 0xa0,0xbb,0x00,0x0b,0xff,0xe6,0x81,0xb5,0x00,0x91,0x11,0x10,0x09,0x0b,0xff,0xf0,
- 0xa4,0x8b,0xae,0x00,0x0b,0xff,0xe8,0x88,0x98,0x00,0x00,0x00,0xd3,0x40,0xd2,0x20,
- 0xd1,0x10,0x10,0x08,0x08,0xff,0xe4,0xb8,0xa6,0x00,0x08,0xff,0xe5,0x86,0xb5,0x00,
- 0x10,0x08,0x08,0xff,0xe5,0x85,0xa8,0x00,0x08,0xff,0xe4,0xbe,0x80,0x00,0xd1,0x10,
- 0x10,0x08,0x08,0xff,0xe5,0x85,0x85,0x00,0x08,0xff,0xe5,0x86,0x80,0x00,0x10,0x08,
- 0x08,0xff,0xe5,0x8b,0x87,0x00,0x08,0xff,0xe5,0x8b,0xba,0x00,0xd2,0x20,0xd1,0x10,
- 0x10,0x08,0x08,0xff,0xe5,0x96,0x9d,0x00,0x08,0xff,0xe5,0x95,0x95,0x00,0x10,0x08,
- 0x08,0xff,0xe5,0x96,0x99,0x00,0x08,0xff,0xe5,0x97,0xa2,0x00,0xd1,0x10,0x10,0x08,
- 0x08,0xff,0xe5,0xa1,0x9a,0x00,0x08,0xff,0xe5,0xa2,0xb3,0x00,0x10,0x08,0x08,0xff,
- 0xe5,0xa5,0x84,0x00,0x08,0xff,0xe5,0xa5,0x94,0x00,0xe0,0x04,0x02,0xcf,0x86,0xe5,
- 0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe5,0xa9,
- 0xa2,0x00,0x08,0xff,0xe5,0xac,0xa8,0x00,0x10,0x08,0x08,0xff,0xe5,0xbb,0x92,0x00,
- 0x08,0xff,0xe5,0xbb,0x99,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe5,0xbd,0xa9,0x00,
- 0x08,0xff,0xe5,0xbe,0xad,0x00,0x10,0x08,0x08,0xff,0xe6,0x83,0x98,0x00,0x08,0xff,
- 0xe6,0x85,0x8e,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe6,0x84,0x88,0x00,
- 0x08,0xff,0xe6,0x86,0x8e,0x00,0x10,0x08,0x08,0xff,0xe6,0x85,0xa0,0x00,0x08,0xff,
- 0xe6,0x87,0xb2,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe6,0x88,0xb4,0x00,0x08,0xff,
- 0xe6,0x8f,0x84,0x00,0x10,0x08,0x08,0xff,0xe6,0x90,0x9c,0x00,0x08,0xff,0xe6,0x91,
- 0x92,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe6,0x95,0x96,0x00,
- 0x08,0xff,0xe6,0x99,0xb4,0x00,0x10,0x08,0x08,0xff,0xe6,0x9c,0x97,0x00,0x08,0xff,
- 0xe6,0x9c,0x9b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe6,0x9d,0x96,0x00,0x08,0xff,
- 0xe6,0xad,0xb9,0x00,0x10,0x08,0x08,0xff,0xe6,0xae,0xba,0x00,0x08,0xff,0xe6,0xb5,
- 0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe6,0xbb,0x9b,0x00,0x08,0xff,
- 0xe6,0xbb,0x8b,0x00,0x10,0x08,0x08,0xff,0xe6,0xbc,0xa2,0x00,0x08,0xff,0xe7,0x80,
- 0x9e,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe7,0x85,0xae,0x00,0x08,0xff,0xe7,0x9e,
- 0xa7,0x00,0x10,0x08,0x08,0xff,0xe7,0x88,0xb5,0x00,0x08,0xff,0xe7,0x8a,0xaf,0x00,
- 0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe7,0x8c,0xaa,0x00,
- 0x08,0xff,0xe7,0x91,0xb1,0x00,0x10,0x08,0x08,0xff,0xe7,0x94,0x86,0x00,0x08,0xff,
- 0xe7,0x94,0xbb,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe7,0x98,0x9d,0x00,0x08,0xff,
- 0xe7,0x98,0x9f,0x00,0x10,0x08,0x08,0xff,0xe7,0x9b,0x8a,0x00,0x08,0xff,0xe7,0x9b,
- 0x9b,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe7,0x9b,0xb4,0x00,0x08,0xff,
- 0xe7,0x9d,0x8a,0x00,0x10,0x08,0x08,0xff,0xe7,0x9d,0x80,0x00,0x08,0xff,0xe7,0xa3,
- 0x8c,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe7,0xaa,0xb1,0x00,0x08,0xff,0xe7,0xaf,
- 0x80,0x00,0x10,0x08,0x08,0xff,0xe7,0xb1,0xbb,0x00,0x08,0xff,0xe7,0xb5,0x9b,0x00,
- 0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe7,0xb7,0xb4,0x00,0x08,0xff,
- 0xe7,0xbc,0xbe,0x00,0x10,0x08,0x08,0xff,0xe8,0x80,0x85,0x00,0x08,0xff,0xe8,0x8d,
- 0x92,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe8,0x8f,0xaf,0x00,0x08,0xff,0xe8,0x9d,
- 0xb9,0x00,0x10,0x08,0x08,0xff,0xe8,0xa5,0x81,0x00,0x08,0xff,0xe8,0xa6,0x86,0x00,
- 0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe8,0xa6,0x96,0x00,0x08,0xff,0xe8,0xaa,
- 0xbf,0x00,0x10,0x08,0x08,0xff,0xe8,0xab,0xb8,0x00,0x08,0xff,0xe8,0xab,0x8b,0x00,
- 0xd1,0x10,0x10,0x08,0x08,0xff,0xe8,0xac,0x81,0x00,0x08,0xff,0xe8,0xab,0xbe,0x00,
- 0x10,0x08,0x08,0xff,0xe8,0xab,0xad,0x00,0x08,0xff,0xe8,0xac,0xb9,0x00,0xcf,0x86,
- 0x95,0xde,0xd4,0x81,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe8,0xae,
- 0x8a,0x00,0x08,0xff,0xe8,0xb4,0x88,0x00,0x10,0x08,0x08,0xff,0xe8,0xbc,0xb8,0x00,
- 0x08,0xff,0xe9,0x81,0xb2,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe9,0x86,0x99,0x00,
- 0x08,0xff,0xe9,0x89,0xb6,0x00,0x10,0x08,0x08,0xff,0xe9,0x99,0xbc,0x00,0x08,0xff,
- 0xe9,0x9b,0xa3,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe9,0x9d,0x96,0x00,
- 0x08,0xff,0xe9,0x9f,0x9b,0x00,0x10,0x08,0x08,0xff,0xe9,0x9f,0xbf,0x00,0x08,0xff,
- 0xe9,0xa0,0x8b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe9,0xa0,0xbb,0x00,0x08,0xff,
- 0xe9,0xac,0x92,0x00,0x10,0x08,0x08,0xff,0xe9,0xbe,0x9c,0x00,0x08,0xff,0xf0,0xa2,
- 0xa1,0x8a,0x00,0xd3,0x45,0xd2,0x22,0xd1,0x12,0x10,0x09,0x08,0xff,0xf0,0xa2,0xa1,
- 0x84,0x00,0x08,0xff,0xf0,0xa3,0x8f,0x95,0x00,0x10,0x08,0x08,0xff,0xe3,0xae,0x9d,
- 0x00,0x08,0xff,0xe4,0x80,0x98,0x00,0xd1,0x11,0x10,0x08,0x08,0xff,0xe4,0x80,0xb9,
- 0x00,0x08,0xff,0xf0,0xa5,0x89,0x89,0x00,0x10,0x09,0x08,0xff,0xf0,0xa5,0xb3,0x90,
- 0x00,0x08,0xff,0xf0,0xa7,0xbb,0x93,0x00,0x92,0x14,0x91,0x10,0x10,0x08,0x08,0xff,
- 0xe9,0xbd,0x83,0x00,0x08,0xff,0xe9,0xbe,0x8e,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0xe1,0x94,0x01,0xe0,0x08,0x01,0xcf,0x86,0xd5,0x42,0xd4,0x14,0x93,0x10,0x52,0x04,
- 0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0xd3,0x10,
- 0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x52,0x04,
- 0x00,0x00,0xd1,0x0d,0x10,0x04,0x00,0x00,0x04,0xff,0xd7,0x99,0xd6,0xb4,0x00,0x10,
- 0x04,0x01,0x1a,0x01,0xff,0xd7,0xb2,0xd6,0xb7,0x00,0xd4,0x42,0x53,0x04,0x01,0x00,
- 0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,0xd7,0xa9,0xd7,0x81,0x00,0x01,
- 0xff,0xd7,0xa9,0xd7,0x82,0x00,0xd1,0x16,0x10,0x0b,0x01,0xff,0xd7,0xa9,0xd6,0xbc,
- 0xd7,0x81,0x00,0x01,0xff,0xd7,0xa9,0xd6,0xbc,0xd7,0x82,0x00,0x10,0x09,0x01,0xff,
- 0xd7,0x90,0xd6,0xb7,0x00,0x01,0xff,0xd7,0x90,0xd6,0xb8,0x00,0xd3,0x43,0xd2,0x24,
- 0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0x90,0xd6,0xbc,0x00,0x01,0xff,0xd7,0x91,0xd6,
- 0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0x92,0xd6,0xbc,0x00,0x01,0xff,0xd7,0x93,0xd6,
- 0xbc,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0x94,0xd6,0xbc,0x00,0x01,0xff,0xd7,
- 0x95,0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0x96,0xd6,0xbc,0x00,0x00,0x00,0xd2,
- 0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0x98,0xd6,0xbc,0x00,0x01,0xff,0xd7,0x99,
- 0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0x9a,0xd6,0xbc,0x00,0x01,0xff,0xd7,0x9b,
- 0xd6,0xbc,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xd7,0x9c,0xd6,0xbc,0x00,0x00,0x00,
- 0x10,0x09,0x01,0xff,0xd7,0x9e,0xd6,0xbc,0x00,0x00,0x00,0xcf,0x86,0x95,0x85,0x94,
- 0x81,0xd3,0x3e,0xd2,0x1f,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0xa0,0xd6,0xbc,0x00,
- 0x01,0xff,0xd7,0xa1,0xd6,0xbc,0x00,0x10,0x04,0x00,0x00,0x01,0xff,0xd7,0xa3,0xd6,
- 0xbc,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xd7,0xa4,0xd6,0xbc,0x00,0x00,0x00,0x10,
- 0x09,0x01,0xff,0xd7,0xa6,0xd6,0xbc,0x00,0x01,0xff,0xd7,0xa7,0xd6,0xbc,0x00,0xd2,
- 0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0xa8,0xd6,0xbc,0x00,0x01,0xff,0xd7,0xa9,
- 0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0xaa,0xd6,0xbc,0x00,0x01,0xff,0xd7,0x95,
- 0xd6,0xb9,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0x91,0xd6,0xbf,0x00,0x01,0xff,
- 0xd7,0x9b,0xd6,0xbf,0x00,0x10,0x09,0x01,0xff,0xd7,0xa4,0xd6,0xbf,0x00,0x01,0x00,
- 0x01,0x00,0x01,0x00,0xd0,0x1a,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,
- 0x93,0x0c,0x92,0x08,0x11,0x04,0x01,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0xcf,0x86,
- 0x95,0x24,0xd4,0x10,0x93,0x0c,0x92,0x08,0x11,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,
- 0x01,0x00,0x01,0x00,0x01,0x00,0xd3,0x5a,0xd2,0x06,0xcf,0x06,0x01,0x00,0xd1,0x14,
- 0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0x95,0x08,0x14,0x04,0x00,0x00,0x01,0x00,
- 0x01,0x00,0xd0,0x1a,0xcf,0x86,0x95,0x14,0x54,0x04,0x01,0x00,0x93,0x0c,0x92,0x08,
- 0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x0c,
- 0x94,0x08,0x13,0x04,0x01,0x00,0x00,0x00,0x05,0x00,0x54,0x04,0x05,0x00,0x53,0x04,
- 0x01,0x00,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,0x06,0x00,0x07,0x00,0x00,0x00,
- 0xd2,0xcc,0xd1,0xa4,0xd0,0x36,0xcf,0x86,0xd5,0x14,0x54,0x04,0x06,0x00,0x53,0x04,
- 0x08,0x00,0x92,0x08,0x11,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x94,0x1c,0xd3,0x10,
- 0x52,0x04,0x01,0xe6,0x51,0x04,0x0a,0xe6,0x10,0x04,0x0a,0xe6,0x10,0xdc,0x52,0x04,
- 0x10,0xdc,0x11,0x04,0x10,0xdc,0x11,0xe6,0x01,0x00,0xcf,0x86,0xd5,0x38,0xd4,0x24,
- 0xd3,0x14,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x06,0x00,0x10,0x04,
- 0x06,0x00,0x07,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x07,0x00,0x01,0x00,0x01,0x00,
- 0x01,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,
- 0x01,0x00,0x01,0x00,0xd4,0x18,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,
- 0x10,0x04,0x01,0x00,0x00,0x00,0x12,0x04,0x01,0x00,0x00,0x00,0x93,0x18,0xd2,0x0c,
- 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x06,0x00,0x91,0x08,0x10,0x04,0x01,0x00,
- 0x00,0x00,0x01,0x00,0x01,0x00,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0x55,0x04,
- 0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0xd1,0x08,
- 0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x01,0x00,0xd1,0x50,0xd0,0x1e,
- 0xcf,0x86,0x95,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,
- 0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x18,
- 0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,
- 0x10,0x04,0x01,0x00,0x06,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,
- 0x06,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0x1e,0xcf,0x86,
- 0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,
- 0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0xcf,0x86,0xd5,0x38,0xd4,0x18,
- 0xd3,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x92,0x08,0x11,0x04,
- 0x00,0x00,0x01,0x00,0x01,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x01,0x00,
- 0x01,0x00,0xd2,0x08,0x11,0x04,0x00,0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,
- 0x00,0x00,0x00,0x00,0xd4,0x20,0xd3,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,
- 0x10,0x04,0x01,0x00,0x00,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,
- 0x01,0x00,0x00,0x00,0x53,0x04,0x00,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,
- 0x04,0x00,0x04,0x00,0x91,0x08,0x10,0x04,0x03,0x00,0x01,0x00,0x01,0x00,0x83,0xe2,
- 0x30,0x3e,0xe1,0x1a,0x3b,0xe0,0x97,0x39,0xcf,0x86,0xe5,0x3b,0x26,0xc4,0xe3,0x16,
- 0x14,0xe2,0xef,0x11,0xe1,0xd0,0x10,0xe0,0x60,0x07,0xcf,0x86,0xe5,0x53,0x03,0xe4,
- 0x4c,0x02,0xe3,0x3d,0x01,0xd2,0x94,0xd1,0x70,0xd0,0x4a,0xcf,0x86,0xd5,0x18,0x94,
- 0x14,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x07,
- 0x00,0x07,0x00,0x07,0x00,0xd4,0x14,0x93,0x10,0x52,0x04,0x07,0x00,0x51,0x04,0x07,
- 0x00,0x10,0x04,0x07,0x00,0x00,0x00,0x07,0x00,0x53,0x04,0x07,0x00,0xd2,0x0c,0x51,
- 0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x00,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x00,
- 0x00,0x07,0x00,0xcf,0x86,0x95,0x20,0xd4,0x10,0x53,0x04,0x07,0x00,0x52,0x04,0x07,
- 0x00,0x11,0x04,0x07,0x00,0x00,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,0x11,
- 0x04,0x07,0x00,0x00,0x00,0x00,0x00,0xd0,0x06,0xcf,0x06,0x07,0x00,0xcf,0x86,0x55,
- 0x04,0x07,0x00,0x54,0x04,0x07,0x00,0x53,0x04,0x07,0x00,0x92,0x0c,0x51,0x04,0x07,
- 0x00,0x10,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0xd1,0x40,0xd0,0x3a,0xcf,0x86,0xd5,
- 0x20,0x94,0x1c,0x93,0x18,0xd2,0x0c,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x00,
- 0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x54,
- 0x04,0x07,0x00,0x93,0x10,0x52,0x04,0x07,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,
- 0x00,0x07,0x00,0x07,0x00,0xcf,0x06,0x08,0x00,0xd0,0x46,0xcf,0x86,0xd5,0x2c,0xd4,
- 0x20,0x53,0x04,0x08,0x00,0xd2,0x0c,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x10,
- 0x00,0xd1,0x08,0x10,0x04,0x10,0x00,0x12,0x00,0x10,0x04,0x12,0x00,0x00,0x00,0x53,
- 0x04,0x0a,0x00,0x12,0x04,0x0a,0x00,0x00,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,
- 0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,
- 0x86,0xd5,0x08,0x14,0x04,0x00,0x00,0x0a,0x00,0x54,0x04,0x0a,0x00,0x53,0x04,0x0a,
- 0x00,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x0a,0xdc,0x00,0x00,0xd2,
- 0x5e,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x0a,
- 0x00,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x00,
- 0x00,0x00,0x00,0x0a,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x0a,0x00,0x93,0x10,0x92,
- 0x0c,0x91,0x08,0x10,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,
- 0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0xdc,0x10,0x00,0x10,0x00,0x10,
- 0x00,0x10,0x00,0x53,0x04,0x10,0x00,0x12,0x04,0x10,0x00,0x00,0x00,0xd1,0x70,0xd0,
- 0x36,0xcf,0x86,0xd5,0x18,0x54,0x04,0x05,0x00,0x53,0x04,0x05,0x00,0x52,0x04,0x05,
- 0x00,0x51,0x04,0x05,0x00,0x10,0x04,0x05,0x00,0x10,0x00,0x94,0x18,0xd3,0x08,0x12,
- 0x04,0x05,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x13,
- 0x00,0x13,0x00,0x05,0x00,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x05,0x00,0x92,
- 0x0c,0x51,0x04,0x05,0x00,0x10,0x04,0x05,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x54,
- 0x04,0x10,0x00,0xd3,0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x10,0xe6,0x92,
- 0x0c,0x51,0x04,0x10,0xe6,0x10,0x04,0x10,0xe6,0x00,0x00,0x00,0x00,0xd0,0x1e,0xcf,
- 0x86,0x95,0x18,0x54,0x04,0x07,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,0x51,
- 0x04,0x07,0x00,0x10,0x04,0x00,0x00,0x07,0x00,0x08,0x00,0xcf,0x86,0x95,0x1c,0xd4,
- 0x0c,0x93,0x08,0x12,0x04,0x08,0x00,0x00,0x00,0x08,0x00,0x93,0x0c,0x52,0x04,0x08,
- 0x00,0x11,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd3,0xba,0xd2,0x80,0xd1,
- 0x34,0xd0,0x1a,0xcf,0x86,0x55,0x04,0x05,0x00,0x94,0x10,0x93,0x0c,0x52,0x04,0x05,
- 0x00,0x11,0x04,0x05,0x00,0x07,0x00,0x05,0x00,0x05,0x00,0xcf,0x86,0x95,0x14,0x94,
- 0x10,0x53,0x04,0x05,0x00,0x52,0x04,0x05,0x00,0x11,0x04,0x05,0x00,0x07,0x00,0x07,
- 0x00,0x07,0x00,0xd0,0x2a,0xcf,0x86,0xd5,0x14,0x54,0x04,0x07,0x00,0x53,0x04,0x07,
- 0x00,0x52,0x04,0x07,0x00,0x11,0x04,0x07,0x00,0x00,0x00,0x94,0x10,0x53,0x04,0x07,
- 0x00,0x92,0x08,0x11,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0xcf,0x86,0xd5,
- 0x10,0x54,0x04,0x12,0x00,0x93,0x08,0x12,0x04,0x12,0x00,0x00,0x00,0x12,0x00,0x54,
- 0x04,0x12,0x00,0x53,0x04,0x12,0x00,0x12,0x04,0x12,0x00,0x00,0x00,0xd1,0x34,0xd0,
- 0x12,0xcf,0x86,0x55,0x04,0x10,0x00,0x94,0x08,0x13,0x04,0x10,0x00,0x00,0x00,0x10,
- 0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0x94,0x18,0xd3,0x08,0x12,0x04,0x10,0x00,0x00,
- 0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x00,
- 0x00,0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x10,0x00,0xd1,0x40,0xd0,0x1e,0xcf,
- 0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0x93,0x10,0x52,0x04,0x10,0x00,0x51,
- 0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x14,0x54,
- 0x04,0x10,0x00,0x93,0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x00,0x00,0x00,
- 0x00,0x94,0x08,0x13,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xe4,
- 0xce,0x02,0xe3,0x45,0x01,0xd2,0xd0,0xd1,0x70,0xd0,0x52,0xcf,0x86,0xd5,0x20,0x94,
- 0x1c,0xd3,0x0c,0x52,0x04,0x07,0x00,0x11,0x04,0x07,0x00,0x00,0x00,0x92,0x0c,0x91,
- 0x08,0x10,0x04,0x07,0x00,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x54,0x04,0x07,
- 0x00,0xd3,0x10,0x52,0x04,0x07,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x00,0x00,0x07,
- 0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0xd1,0x08,0x10,
- 0x04,0x07,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x07,0x00,0xcf,0x86,0x95,0x18,0x54,
- 0x04,0x0b,0x00,0x93,0x10,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x00,
- 0x00,0x0b,0x00,0x0b,0x00,0x10,0x00,0xd0,0x32,0xcf,0x86,0xd5,0x18,0x54,0x04,0x10,
- 0x00,0x53,0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,
- 0x00,0x00,0x00,0x94,0x14,0x93,0x10,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,
- 0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,
- 0x04,0x11,0x00,0xd3,0x14,0xd2,0x0c,0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,
- 0x00,0x11,0x04,0x11,0x00,0x00,0x00,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,
- 0x00,0x11,0x00,0x11,0x00,0xd1,0x40,0xd0,0x3a,0xcf,0x86,0xd5,0x1c,0x54,0x04,0x09,
- 0x00,0x53,0x04,0x09,0x00,0xd2,0x08,0x11,0x04,0x09,0x00,0x0b,0x00,0x51,0x04,0x00,
- 0x00,0x10,0x04,0x00,0x00,0x09,0x00,0x54,0x04,0x0a,0x00,0x53,0x04,0x0a,0x00,0xd2,
- 0x08,0x11,0x04,0x0a,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0a,
- 0x00,0xcf,0x06,0x00,0x00,0xd0,0x1a,0xcf,0x86,0x55,0x04,0x0d,0x00,0x54,0x04,0x0d,
- 0x00,0x53,0x04,0x0d,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x11,0x00,0x0d,0x00,0xcf,
- 0x86,0x95,0x14,0x54,0x04,0x11,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x11,
- 0x00,0x11,0x00,0x11,0x00,0x11,0x00,0xd2,0xec,0xd1,0xa4,0xd0,0x76,0xcf,0x86,0xd5,
- 0x48,0xd4,0x28,0xd3,0x14,0x52,0x04,0x08,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x08,
- 0x00,0x10,0x04,0x08,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0xd1,0x08,0x10,0x04,0x08,
- 0x00,0x08,0xdc,0x10,0x04,0x08,0x00,0x08,0xe6,0xd3,0x10,0x52,0x04,0x08,0x00,0x91,
- 0x08,0x10,0x04,0x00,0x00,0x08,0x00,0x08,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,
- 0x00,0x08,0x00,0x08,0x00,0x08,0x00,0x54,0x04,0x08,0x00,0xd3,0x0c,0x52,0x04,0x08,
- 0x00,0x11,0x04,0x14,0x00,0x00,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x08,0xe6,0x08,
- 0x01,0x10,0x04,0x08,0xdc,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x08,
- 0x09,0xcf,0x86,0x95,0x28,0xd4,0x14,0x53,0x04,0x08,0x00,0x92,0x0c,0x91,0x08,0x10,
- 0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x08,0x00,0x92,0x0c,0x91,
- 0x08,0x10,0x04,0x08,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0xd0,0x0a,0xcf,
- 0x86,0x15,0x04,0x10,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0xd4,0x24,0xd3,
- 0x14,0x52,0x04,0x10,0x00,0xd1,0x08,0x10,0x04,0x10,0x00,0x10,0xe6,0x10,0x04,0x10,
- 0xdc,0x00,0x00,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10,
- 0x00,0x93,0x10,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,
- 0x00,0x00,0x00,0xd1,0x54,0xd0,0x26,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,
- 0x00,0xd3,0x0c,0x52,0x04,0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0x92,0x0c,0x91,
- 0x08,0x10,0x04,0x00,0x00,0x0b,0x00,0x0b,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x14,0x54,
- 0x04,0x0b,0x00,0x93,0x0c,0x52,0x04,0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0x0b,
- 0x00,0x54,0x04,0x0b,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,
- 0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0xd0,0x42,0xcf,0x86,0xd5,0x28,0x54,0x04,0x10,
- 0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd2,0x0c,0x91,
- 0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,
- 0x00,0x00,0x00,0x94,0x14,0x53,0x04,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,
- 0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd3,0x96,0xd2,
- 0x68,0xd1,0x24,0xd0,0x06,0xcf,0x06,0x0b,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,0x53,
- 0x04,0x0b,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x11,0x00,0x54,0x04,0x11,
- 0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0xcf,0x86,0x55,0x04,0x11,0x00,0x54,0x04,0x11,0x00,0xd3,0x10,0x92,
- 0x0c,0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x92,0x08,0x11,
- 0x04,0x00,0x00,0x11,0x00,0x11,0x00,0xd1,0x28,0xd0,0x22,0xcf,0x86,0x55,0x04,0x14,
- 0x00,0xd4,0x0c,0x93,0x08,0x12,0x04,0x14,0x00,0x14,0xe6,0x00,0x00,0x53,0x04,0x14,
- 0x00,0x92,0x08,0x11,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,
- 0x06,0x00,0x00,0xd2,0x2a,0xd1,0x24,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,
- 0x04,0x00,0x00,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,
- 0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1,0x58,0xd0,
- 0x12,0xcf,0x86,0x55,0x04,0x14,0x00,0x94,0x08,0x13,0x04,0x14,0x00,0x00,0x00,0x14,
- 0x00,0xcf,0x86,0x95,0x40,0xd4,0x24,0xd3,0x0c,0x52,0x04,0x14,0x00,0x11,0x04,0x14,
- 0x00,0x14,0xdc,0xd2,0x0c,0x51,0x04,0x14,0xe6,0x10,0x04,0x14,0xe6,0x14,0xdc,0x91,
- 0x08,0x10,0x04,0x14,0xe6,0x14,0xdc,0x14,0xdc,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,
- 0x04,0x14,0xdc,0x14,0x00,0x14,0x00,0x14,0x00,0x92,0x08,0x11,0x04,0x14,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,
- 0x00,0x54,0x04,0x15,0x00,0x93,0x10,0x52,0x04,0x15,0x00,0x51,0x04,0x15,0x00,0x10,
- 0x04,0x15,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xe5,0x0f,0x06,0xe4,0xf8,0x03,0xe3,
- 0x02,0x02,0xd2,0xfb,0xd1,0x4c,0xd0,0x06,0xcf,0x06,0x0c,0x00,0xcf,0x86,0xd5,0x2c,
- 0xd4,0x1c,0xd3,0x10,0x52,0x04,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x09,
- 0x0c,0x00,0x52,0x04,0x0c,0x00,0x11,0x04,0x0c,0x00,0x00,0x00,0x93,0x0c,0x92,0x08,
- 0x11,0x04,0x00,0x00,0x0c,0x00,0x0c,0x00,0x0c,0x00,0x54,0x04,0x0c,0x00,0x53,0x04,
- 0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x09,
- 0xd0,0x69,0xcf,0x86,0xd5,0x32,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,0xd2,0x15,
- 0x51,0x04,0x0b,0x00,0x10,0x0d,0x0b,0xff,0xf0,0x91,0x82,0x99,0xf0,0x91,0x82,0xba,
- 0x00,0x0b,0x00,0x91,0x11,0x10,0x0d,0x0b,0xff,0xf0,0x91,0x82,0x9b,0xf0,0x91,0x82,
- 0xba,0x00,0x0b,0x00,0x0b,0x00,0xd4,0x1d,0x53,0x04,0x0b,0x00,0x92,0x15,0x51,0x04,
- 0x0b,0x00,0x10,0x04,0x0b,0x00,0x0b,0xff,0xf0,0x91,0x82,0xa5,0xf0,0x91,0x82,0xba,
- 0x00,0x0b,0x00,0x53,0x04,0x0b,0x00,0x92,0x10,0xd1,0x08,0x10,0x04,0x0b,0x00,0x0b,
- 0x09,0x10,0x04,0x0b,0x07,0x0b,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x20,0x94,0x1c,0xd3,
- 0x0c,0x92,0x08,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x91,
- 0x08,0x10,0x04,0x00,0x00,0x14,0x00,0x00,0x00,0x0d,0x00,0xd4,0x14,0x53,0x04,0x0d,
- 0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,
- 0x04,0x0d,0x00,0x92,0x08,0x11,0x04,0x0d,0x00,0x00,0x00,0x00,0x00,0xd1,0x96,0xd0,
- 0x5c,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x0d,0xe6,0x10,
- 0x04,0x0d,0xe6,0x0d,0x00,0x0d,0x00,0x0d,0x00,0x0d,0x00,0xd4,0x26,0x53,0x04,0x0d,
- 0x00,0x52,0x04,0x0d,0x00,0x51,0x04,0x0d,0x00,0x10,0x0d,0x0d,0xff,0xf0,0x91,0x84,
- 0xb1,0xf0,0x91,0x84,0xa7,0x00,0x0d,0xff,0xf0,0x91,0x84,0xb2,0xf0,0x91,0x84,0xa7,
- 0x00,0x93,0x18,0xd2,0x0c,0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x00,0x0d,0x09,0x91,
- 0x08,0x10,0x04,0x0d,0x09,0x00,0x00,0x0d,0x00,0x0d,0x00,0xcf,0x86,0xd5,0x18,0x94,
- 0x14,0x93,0x10,0x52,0x04,0x0d,0x00,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,
- 0x00,0x00,0x00,0x10,0x00,0x54,0x04,0x10,0x00,0x93,0x18,0xd2,0x0c,0x51,0x04,0x10,
- 0x00,0x10,0x04,0x10,0x00,0x10,0x07,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,
- 0x00,0x00,0x00,0xd0,0x06,0xcf,0x06,0x0d,0x00,0xcf,0x86,0xd5,0x40,0xd4,0x2c,0xd3,
- 0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x0d,0x09,0x0d,0x00,0x0d,0x00,0x0d,0x00,0xd2,
- 0x10,0xd1,0x08,0x10,0x04,0x0d,0x00,0x11,0x00,0x10,0x04,0x11,0x07,0x11,0x00,0x91,
- 0x08,0x10,0x04,0x11,0x00,0x10,0x00,0x00,0x00,0x53,0x04,0x0d,0x00,0x92,0x0c,0x51,
- 0x04,0x0d,0x00,0x10,0x04,0x10,0x00,0x11,0x00,0x11,0x00,0xd4,0x14,0x93,0x10,0x92,
- 0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x93,
- 0x10,0x52,0x04,0x10,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0xd2,0xc8,0xd1,0x48,0xd0,0x42,0xcf,0x86,0xd5,0x18,0x54,0x04,0x10,0x00,0x93,
- 0x10,0x92,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x10,
- 0x00,0x54,0x04,0x10,0x00,0xd3,0x14,0x52,0x04,0x10,0x00,0xd1,0x08,0x10,0x04,0x10,
- 0x00,0x10,0x09,0x10,0x04,0x10,0x07,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,
- 0x00,0x10,0x04,0x12,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd0,0x52,0xcf,0x86,0xd5,
- 0x3c,0xd4,0x28,0xd3,0x10,0x52,0x04,0x11,0x00,0x51,0x04,0x11,0x00,0x10,0x04,0x11,
- 0x00,0x00,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x11,0x00,0x00,0x00,0x11,0x00,0x51,
- 0x04,0x11,0x00,0x10,0x04,0x00,0x00,0x11,0x00,0x53,0x04,0x11,0x00,0x52,0x04,0x11,
- 0x00,0x51,0x04,0x11,0x00,0x10,0x04,0x00,0x00,0x11,0x00,0x94,0x10,0x53,0x04,0x11,
- 0x00,0x92,0x08,0x11,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xcf,0x86,0x55,
- 0x04,0x10,0x00,0xd4,0x18,0x53,0x04,0x10,0x00,0x92,0x10,0xd1,0x08,0x10,0x04,0x10,
- 0x00,0x10,0x07,0x10,0x04,0x10,0x09,0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x92,
- 0x08,0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xe1,0x27,0x01,0xd0,0x8a,0xcf,0x86,
- 0xd5,0x44,0xd4,0x2c,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x11,0x00,0x10,0x00,
- 0x10,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x52,0x04,0x10,0x00,
- 0xd1,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x93,0x14,
- 0x92,0x10,0xd1,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,
- 0x10,0x00,0x10,0x00,0xd4,0x14,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,
- 0x10,0x00,0x00,0x00,0x10,0x00,0x10,0x00,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,
- 0x10,0x00,0x00,0x00,0x10,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,
- 0xd2,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x00,0x00,0x14,0x07,0x91,0x08,0x10,0x04,
- 0x10,0x07,0x10,0x00,0x10,0x00,0xcf,0x86,0xd5,0x6a,0xd4,0x42,0xd3,0x14,0x52,0x04,
- 0x10,0x00,0xd1,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,
- 0xd2,0x19,0xd1,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0xff,
- 0xf0,0x91,0x8d,0x87,0xf0,0x91,0x8c,0xbe,0x00,0x91,0x11,0x10,0x0d,0x10,0xff,0xf0,
- 0x91,0x8d,0x87,0xf0,0x91,0x8d,0x97,0x00,0x10,0x09,0x00,0x00,0xd3,0x18,0xd2,0x0c,
- 0x91,0x08,0x10,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,
- 0x00,0x00,0x10,0x00,0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,
- 0x10,0x00,0xd4,0x1c,0xd3,0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x00,0x00,0x10,0xe6,
- 0x52,0x04,0x10,0xe6,0x91,0x08,0x10,0x04,0x10,0xe6,0x00,0x00,0x00,0x00,0x93,0x10,
- 0x52,0x04,0x10,0xe6,0x91,0x08,0x10,0x04,0x10,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,
- 0xcf,0x06,0x00,0x00,0xe3,0x30,0x01,0xd2,0xb7,0xd1,0x48,0xd0,0x06,0xcf,0x06,0x12,
- 0x00,0xcf,0x86,0x95,0x3c,0xd4,0x1c,0x93,0x18,0xd2,0x0c,0x51,0x04,0x12,0x00,0x10,
- 0x04,0x12,0x09,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x07,0x12,0x00,0x12,
- 0x00,0x53,0x04,0x12,0x00,0xd2,0x0c,0x51,0x04,0x12,0x00,0x10,0x04,0x00,0x00,0x12,
- 0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x12,0x00,0x10,0x04,0x14,0xe6,0x15,0x00,0x00,
- 0x00,0xd0,0x45,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0x53,0x04,0x10,
- 0x00,0xd2,0x15,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x10,0xff,0xf0,0x91,0x92,
- 0xb9,0xf0,0x91,0x92,0xba,0x00,0xd1,0x11,0x10,0x0d,0x10,0xff,0xf0,0x91,0x92,0xb9,
- 0xf0,0x91,0x92,0xb0,0x00,0x10,0x00,0x10,0x0d,0x10,0xff,0xf0,0x91,0x92,0xb9,0xf0,
- 0x91,0x92,0xbd,0x00,0x10,0x00,0xcf,0x86,0x95,0x24,0xd4,0x14,0x93,0x10,0x92,0x0c,
- 0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x09,0x10,0x07,0x10,0x00,0x00,0x00,0x53,0x04,
- 0x10,0x00,0x92,0x08,0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x06,
- 0xcf,0x06,0x00,0x00,0xd0,0x40,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,
- 0xd3,0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x00,0x00,0xd2,0x1e,0x51,0x04,
- 0x10,0x00,0x10,0x0d,0x10,0xff,0xf0,0x91,0x96,0xb8,0xf0,0x91,0x96,0xaf,0x00,0x10,
- 0xff,0xf0,0x91,0x96,0xb9,0xf0,0x91,0x96,0xaf,0x00,0x51,0x04,0x10,0x00,0x10,0x04,
- 0x10,0x00,0x10,0x09,0xcf,0x86,0x95,0x2c,0xd4,0x1c,0xd3,0x10,0x92,0x0c,0x91,0x08,
- 0x10,0x04,0x10,0x07,0x10,0x00,0x10,0x00,0x10,0x00,0x92,0x08,0x11,0x04,0x10,0x00,
- 0x11,0x00,0x11,0x00,0x53,0x04,0x11,0x00,0x52,0x04,0x11,0x00,0x11,0x04,0x11,0x00,
- 0x00,0x00,0x00,0x00,0xd2,0xa0,0xd1,0x5c,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x10,0x00,
- 0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,
- 0x10,0x04,0x10,0x00,0x10,0x09,0xcf,0x86,0xd5,0x24,0xd4,0x14,0x93,0x10,0x52,0x04,
- 0x10,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x04,
- 0x10,0x00,0x92,0x08,0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x94,0x14,0x53,0x04,
- 0x12,0x00,0x52,0x04,0x12,0x00,0x91,0x08,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0xd0,0x2a,0xcf,0x86,0x55,0x04,0x0d,0x00,0x54,0x04,0x0d,0x00,0xd3,0x10,
- 0x52,0x04,0x0d,0x00,0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x09,0x0d,0x07,0x92,0x0c,
- 0x91,0x08,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x95,0x14,
- 0x94,0x10,0x53,0x04,0x0d,0x00,0x92,0x08,0x11,0x04,0x0d,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0xd1,0x40,0xd0,0x3a,0xcf,0x86,0xd5,0x20,0x54,0x04,0x11,0x00,
- 0x53,0x04,0x11,0x00,0xd2,0x0c,0x51,0x04,0x11,0x00,0x10,0x04,0x14,0x00,0x00,0x00,
- 0x91,0x08,0x10,0x04,0x00,0x00,0x11,0x00,0x11,0x00,0x94,0x14,0x53,0x04,0x11,0x00,
- 0x92,0x0c,0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x11,0x09,0x00,0x00,0x11,0x00,
- 0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xe4,0x59,0x01,0xd3,0xb2,0xd2,0x5c,0xd1,
- 0x28,0xd0,0x22,0xcf,0x86,0x55,0x04,0x14,0x00,0x54,0x04,0x14,0x00,0x53,0x04,0x14,
- 0x00,0x92,0x10,0xd1,0x08,0x10,0x04,0x14,0x00,0x14,0x09,0x10,0x04,0x14,0x07,0x14,
- 0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd0,0x0a,0xcf,0x86,0x15,0x04,0x00,0x00,0x10,
- 0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0xd3,0x10,0x92,0x0c,0x51,
- 0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x51,
- 0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,
- 0x1a,0xcf,0x86,0x55,0x04,0x00,0x00,0x94,0x10,0x53,0x04,0x15,0x00,0x92,0x08,0x11,
- 0x04,0x00,0x00,0x15,0x00,0x15,0x00,0x15,0x00,0xcf,0x86,0xd5,0x14,0x54,0x04,0x15,
- 0x00,0x53,0x04,0x15,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x15,0x00,0x15,0x00,0x94,
- 0x1c,0x93,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x15,0x09,0x15,0x00,0x15,0x00,0x91,
- 0x08,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd2,0xa0,0xd1,
- 0x3c,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x13,0x00,0x54,0x04,0x13,0x00,0x93,0x10,0x52,
- 0x04,0x13,0x00,0x91,0x08,0x10,0x04,0x13,0x09,0x13,0x00,0x13,0x00,0x13,0x00,0xcf,
- 0x86,0x95,0x18,0x94,0x14,0x93,0x10,0x52,0x04,0x13,0x00,0x51,0x04,0x13,0x00,0x10,
- 0x04,0x13,0x00,0x13,0x09,0x00,0x00,0x13,0x00,0x13,0x00,0xd0,0x46,0xcf,0x86,0xd5,
- 0x2c,0xd4,0x10,0x93,0x0c,0x52,0x04,0x13,0x00,0x11,0x04,0x15,0x00,0x13,0x00,0x13,
- 0x00,0x53,0x04,0x13,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x13,0x00,0x13,0x09,0x13,
- 0x00,0x91,0x08,0x10,0x04,0x13,0x00,0x14,0x00,0x13,0x00,0x94,0x14,0x93,0x10,0x92,
- 0x0c,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0x92,
- 0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,
- 0x00,0xe3,0xa9,0x01,0xd2,0xb0,0xd1,0x6c,0xd0,0x3e,0xcf,0x86,0xd5,0x18,0x94,0x14,
- 0x53,0x04,0x12,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x12,0x00,0x00,0x00,0x12,0x00,
- 0x12,0x00,0x12,0x00,0x54,0x04,0x12,0x00,0xd3,0x10,0x52,0x04,0x12,0x00,0x51,0x04,
- 0x12,0x00,0x10,0x04,0x12,0x00,0x00,0x00,0x52,0x04,0x12,0x00,0x51,0x04,0x12,0x00,
- 0x10,0x04,0x12,0x00,0x12,0x09,0xcf,0x86,0xd5,0x14,0x94,0x10,0x93,0x0c,0x52,0x04,
- 0x12,0x00,0x11,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x94,0x14,0x53,0x04,
- 0x12,0x00,0x52,0x04,0x12,0x00,0x91,0x08,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,
- 0x12,0x00,0xd0,0x3e,0xcf,0x86,0xd5,0x14,0x54,0x04,0x12,0x00,0x93,0x0c,0x92,0x08,
- 0x11,0x04,0x00,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0xd4,0x14,0x53,0x04,0x12,0x00,
- 0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x93,0x10,
- 0x52,0x04,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,
- 0xcf,0x06,0x00,0x00,0xd1,0xa0,0xd0,0x52,0xcf,0x86,0xd5,0x24,0x94,0x20,0xd3,0x10,
- 0x52,0x04,0x13,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0x92,0x0c,
- 0x51,0x04,0x13,0x00,0x10,0x04,0x00,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x54,0x04,
- 0x13,0x00,0xd3,0x10,0x52,0x04,0x13,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,
- 0x00,0x00,0xd2,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0x51,0x04,
- 0x13,0x00,0x10,0x04,0x00,0x00,0x13,0x00,0xcf,0x86,0xd5,0x28,0xd4,0x18,0x93,0x14,
- 0xd2,0x0c,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x07,0x13,0x00,0x11,0x04,0x13,0x09,
- 0x13,0x00,0x00,0x00,0x53,0x04,0x13,0x00,0x92,0x08,0x11,0x04,0x13,0x00,0x00,0x00,
- 0x00,0x00,0x94,0x20,0xd3,0x10,0x52,0x04,0x14,0x00,0x51,0x04,0x14,0x00,0x10,0x04,
- 0x00,0x00,0x14,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x14,0x00,
- 0x14,0x00,0x14,0x00,0xd0,0x52,0xcf,0x86,0xd5,0x3c,0xd4,0x14,0x53,0x04,0x14,0x00,
- 0x52,0x04,0x14,0x00,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0xd3,0x18,
- 0xd2,0x0c,0x51,0x04,0x14,0x00,0x10,0x04,0x00,0x00,0x14,0x00,0x51,0x04,0x14,0x00,
- 0x10,0x04,0x14,0x00,0x14,0x09,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x94,0x10,0x53,0x04,0x14,0x00,0x92,0x08,0x11,0x04,0x14,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd2,0x2a,0xd1,0x06,0xcf,0x06,
- 0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,
- 0x14,0x00,0x53,0x04,0x14,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,
- 0xcf,0x86,0x55,0x04,0x15,0x00,0x54,0x04,0x15,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,
- 0x15,0x00,0x00,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,
- 0x00,0x00,0x15,0x00,0xd0,0xca,0xcf,0x86,0xd5,0xc2,0xd4,0x54,0xd3,0x06,0xcf,0x06,
- 0x09,0x00,0xd2,0x06,0xcf,0x06,0x09,0x00,0xd1,0x24,0xd0,0x06,0xcf,0x06,0x09,0x00,
- 0xcf,0x86,0x55,0x04,0x09,0x00,0x94,0x14,0x53,0x04,0x09,0x00,0x52,0x04,0x09,0x00,
- 0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x10,0x00,0x10,0x00,0xd0,0x1e,0xcf,0x86,
- 0x95,0x18,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,
- 0x10,0x00,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd3,0x68,
- 0xd2,0x46,0xd1,0x40,0xd0,0x06,0xcf,0x06,0x09,0x00,0xcf,0x86,0x55,0x04,0x09,0x00,
- 0xd4,0x20,0xd3,0x10,0x92,0x0c,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x10,0x00,
- 0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,
- 0x93,0x10,0x52,0x04,0x09,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0xcf,0x06,0x11,0x00,0xd1,0x1c,0xd0,0x06,0xcf,0x06,0x11,0x00,0xcf,0x86,
- 0x95,0x10,0x94,0x0c,0x93,0x08,0x12,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x86,
- 0xd5,0x4c,0xd4,0x06,0xcf,0x06,0x0b,0x00,0xd3,0x40,0xd2,0x3a,0xd1,0x34,0xd0,0x2e,
- 0xcf,0x86,0x55,0x04,0x0b,0x00,0xd4,0x14,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,
- 0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0x53,0x04,0x15,0x00,0x92,0x0c,
- 0x91,0x08,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,
- 0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,
- 0xd1,0x4c,0xd0,0x44,0xcf,0x86,0xd5,0x3c,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x06,
- 0xcf,0x06,0x11,0x00,0xd2,0x2a,0xd1,0x24,0xd0,0x06,0xcf,0x06,0x11,0x00,0xcf,0x86,
- 0x95,0x18,0x94,0x14,0x93,0x10,0x52,0x04,0x11,0x00,0x51,0x04,0x11,0x00,0x10,0x04,
- 0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,
- 0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x86,0xcf,0x06,0x00,0x00,0xe0,0xd2,0x01,0xcf,
- 0x86,0xd5,0x06,0xcf,0x06,0x00,0x00,0xe4,0x0b,0x01,0xd3,0x06,0xcf,0x06,0x0c,0x00,
- 0xd2,0x84,0xd1,0x50,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x0c,0x00,0x54,0x04,0x0c,0x00,
- 0x53,0x04,0x0c,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0x52,0x04,
- 0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x94,0x14,0x53,0x04,
- 0x10,0x00,0xd2,0x08,0x11,0x04,0x10,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x10,0x00,
- 0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,0x08,0x14,0x04,0x00,0x00,
- 0x10,0x00,0xd4,0x10,0x53,0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,
- 0x00,0x00,0x93,0x10,0x52,0x04,0x10,0x01,0x91,0x08,0x10,0x04,0x10,0x01,0x10,0x00,
- 0x00,0x00,0x00,0x00,0xd1,0x6c,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,
- 0x10,0x00,0x93,0x10,0x52,0x04,0x10,0xe6,0x51,0x04,0x10,0xe6,0x10,0x04,0x10,0xe6,
- 0x10,0x00,0x10,0x00,0xcf,0x86,0xd5,0x24,0xd4,0x10,0x93,0x0c,0x52,0x04,0x10,0x00,
- 0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x92,0x0c,0x51,0x04,
- 0x10,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c,
- 0x51,0x04,0x10,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x53,0x04,
- 0x10,0x00,0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,
- 0xd0,0x0e,0xcf,0x86,0x95,0x08,0x14,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,
- 0x00,0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xd2,0x30,0xd1,0x0c,0xd0,0x06,0xcf,0x06,
- 0x00,0x00,0xcf,0x06,0x14,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x14,0x00,
- 0x53,0x04,0x14,0x00,0x92,0x0c,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1,0x4c,0xd0,0x06,0xcf,0x06,0x0d,0x00,
- 0xcf,0x86,0xd5,0x2c,0x94,0x28,0xd3,0x10,0x52,0x04,0x0d,0x00,0x91,0x08,0x10,0x04,
- 0x0d,0x00,0x15,0x00,0x15,0x00,0xd2,0x0c,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,
- 0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x15,0x00,0x0d,0x00,0x54,0x04,
- 0x0d,0x00,0x53,0x04,0x0d,0x00,0x52,0x04,0x0d,0x00,0x51,0x04,0x0d,0x00,0x10,0x04,
- 0x0d,0x00,0x15,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x53,0x04,0x15,0x00,
- 0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0d,0x00,0x0d,0x00,
- 0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,
- 0x10,0x04,0x12,0x00,0x13,0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,
- 0xcf,0x06,0x12,0x00,0xe2,0xc5,0x01,0xd1,0x8e,0xd0,0x86,0xcf,0x86,0xd5,0x48,0xd4,
- 0x06,0xcf,0x06,0x12,0x00,0xd3,0x06,0xcf,0x06,0x12,0x00,0xd2,0x06,0xcf,0x06,0x12,
- 0x00,0xd1,0x06,0xcf,0x06,0x12,0x00,0xd0,0x06,0xcf,0x06,0x12,0x00,0xcf,0x86,0x55,
- 0x04,0x12,0x00,0xd4,0x14,0x53,0x04,0x12,0x00,0x52,0x04,0x12,0x00,0x91,0x08,0x10,
- 0x04,0x12,0x00,0x14,0x00,0x14,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x14,0x00,0x15,
- 0x00,0x15,0x00,0x00,0x00,0xd4,0x36,0xd3,0x06,0xcf,0x06,0x12,0x00,0xd2,0x2a,0xd1,
- 0x06,0xcf,0x06,0x12,0x00,0xd0,0x06,0xcf,0x06,0x12,0x00,0xcf,0x86,0x55,0x04,0x12,
- 0x00,0x54,0x04,0x12,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x12,0x00,0x10,0x04,0x12,
+ 0x10,0x04,0x0c,0x00,0x00,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0c,0x00,
+ 0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x93,0x18,0xd2,0x0c,
+ 0x91,0x08,0x10,0x04,0x00,0x00,0x0c,0x00,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,
+ 0x0c,0x00,0x00,0x00,0x00,0x00,0x94,0x20,0xd3,0x10,0x52,0x04,0x0c,0x00,0x51,0x04,
+ 0x0c,0x00,0x10,0x04,0x0c,0x00,0x00,0x00,0x52,0x04,0x0c,0x00,0x51,0x04,0x0c,0x00,
+ 0x10,0x04,0x0c,0x00,0x00,0x00,0x10,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0x94,0x10,
+ 0x93,0x0c,0x52,0x04,0x11,0x00,0x11,0x04,0x10,0x00,0x15,0x00,0x00,0x00,0x11,0x00,
+ 0xd0,0x06,0xcf,0x06,0x11,0x00,0xcf,0x86,0x55,0x04,0x0b,0x00,0xd4,0x14,0x53,0x04,
+ 0x0b,0x00,0x52,0x04,0x0b,0x00,0x91,0x08,0x10,0x04,0x0b,0x00,0x0b,0x09,0x00,0x00,
+ 0x53,0x04,0x0b,0x00,0x92,0x08,0x11,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,
+ 0x02,0xff,0xff,0xcf,0x86,0xcf,0x06,0x02,0xff,0xff,0xd1,0x76,0xd0,0x09,0xcf,0x86,
+ 0xcf,0x06,0x02,0xff,0xff,0xcf,0x86,0x85,0xd4,0x07,0xcf,0x06,0x02,0xff,0xff,0xd3,
+ 0x07,0xcf,0x06,0x02,0xff,0xff,0xd2,0x07,0xcf,0x06,0x02,0xff,0xff,0xd1,0x07,0xcf,
+ 0x06,0x02,0xff,0xff,0xd0,0x18,0xcf,0x86,0x55,0x05,0x02,0xff,0xff,0x94,0x0d,0x93,
+ 0x09,0x12,0x05,0x02,0xff,0xff,0x00,0x00,0x00,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x24,
+ 0x94,0x20,0xd3,0x10,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,
+ 0x00,0x00,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0b,0x00,0x0b,0x00,
+ 0x0b,0x00,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,0x12,0x04,0x0b,0x00,0x00,0x00,
+ 0xd0,0x08,0xcf,0x86,0xcf,0x06,0x01,0x00,0xcf,0x86,0xd5,0x06,0xcf,0x06,0x01,0x00,
+ 0xe4,0x9c,0x10,0xe3,0x16,0x08,0xd2,0x06,0xcf,0x06,0x01,0x00,0xe1,0x08,0x04,0xe0,
+ 0x04,0x02,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0xe8,0xb1,0x88,0x00,0x01,0xff,0xe6,0x9b,0xb4,0x00,0x10,0x08,0x01,
+ 0xff,0xe8,0xbb,0x8a,0x00,0x01,0xff,0xe8,0xb3,0x88,0x00,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0xe6,0xbb,0x91,0x00,0x01,0xff,0xe4,0xb8,0xb2,0x00,0x10,0x08,0x01,0xff,0xe5,
+ 0x8f,0xa5,0x00,0x01,0xff,0xe9,0xbe,0x9c,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0xe9,0xbe,0x9c,0x00,0x01,0xff,0xe5,0xa5,0x91,0x00,0x10,0x08,0x01,0xff,0xe9,
+ 0x87,0x91,0x00,0x01,0xff,0xe5,0x96,0x87,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,
+ 0xa5,0x88,0x00,0x01,0xff,0xe6,0x87,0xb6,0x00,0x10,0x08,0x01,0xff,0xe7,0x99,0xa9,
+ 0x00,0x01,0xff,0xe7,0xbe,0x85,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0xe8,0x98,0xbf,0x00,0x01,0xff,0xe8,0x9e,0xba,0x00,0x10,0x08,0x01,0xff,0xe8,
+ 0xa3,0xb8,0x00,0x01,0xff,0xe9,0x82,0x8f,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,
+ 0xa8,0x82,0x00,0x01,0xff,0xe6,0xb4,0x9b,0x00,0x10,0x08,0x01,0xff,0xe7,0x83,0x99,
+ 0x00,0x01,0xff,0xe7,0x8f,0x9e,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,
+ 0x90,0xbd,0x00,0x01,0xff,0xe9,0x85,0xaa,0x00,0x10,0x08,0x01,0xff,0xe9,0xa7,0xb1,
+ 0x00,0x01,0xff,0xe4,0xba,0x82,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x8d,0xb5,
+ 0x00,0x01,0xff,0xe6,0xac,0x84,0x00,0x10,0x08,0x01,0xff,0xe7,0x88,0x9b,0x00,0x01,
+ 0xff,0xe8,0x98,0xad,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0xe9,0xb8,0x9e,0x00,0x01,0xff,0xe5,0xb5,0x90,0x00,0x10,0x08,0x01,0xff,0xe6,
+ 0xbf,0xab,0x00,0x01,0xff,0xe8,0x97,0x8d,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,
+ 0xa5,0xa4,0x00,0x01,0xff,0xe6,0x8b,0x89,0x00,0x10,0x08,0x01,0xff,0xe8,0x87,0x98,
+ 0x00,0x01,0xff,0xe8,0xa0,0x9f,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,
+ 0xbb,0x8a,0x00,0x01,0xff,0xe6,0x9c,0x97,0x00,0x10,0x08,0x01,0xff,0xe6,0xb5,0xaa,
+ 0x00,0x01,0xff,0xe7,0x8b,0xbc,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0x83,0x8e,
+ 0x00,0x01,0xff,0xe4,0xbe,0x86,0x00,0x10,0x08,0x01,0xff,0xe5,0x86,0xb7,0x00,0x01,
+ 0xff,0xe5,0x8b,0x9e,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,
+ 0x93,0x84,0x00,0x01,0xff,0xe6,0xab,0x93,0x00,0x10,0x08,0x01,0xff,0xe7,0x88,0x90,
+ 0x00,0x01,0xff,0xe7,0x9b,0xa7,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x80,0x81,
+ 0x00,0x01,0xff,0xe8,0x98,0x86,0x00,0x10,0x08,0x01,0xff,0xe8,0x99,0x9c,0x00,0x01,
+ 0xff,0xe8,0xb7,0xaf,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0x9c,0xb2,
+ 0x00,0x01,0xff,0xe9,0xad,0xaf,0x00,0x10,0x08,0x01,0xff,0xe9,0xb7,0xba,0x00,0x01,
+ 0xff,0xe7,0xa2,0x8c,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0xa5,0xbf,0x00,0x01,
+ 0xff,0xe7,0xb6,0xa0,0x00,0x10,0x08,0x01,0xff,0xe8,0x8f,0x89,0x00,0x01,0xff,0xe9,
+ 0x8c,0x84,0x00,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xe9,0xb9,0xbf,0x00,0x01,0xff,0xe8,0xab,0x96,0x00,0x10,0x08,
+ 0x01,0xff,0xe5,0xa3,0x9f,0x00,0x01,0xff,0xe5,0xbc,0x84,0x00,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xe7,0xb1,0xa0,0x00,0x01,0xff,0xe8,0x81,0xbe,0x00,0x10,0x08,0x01,0xff,
+ 0xe7,0x89,0xa2,0x00,0x01,0xff,0xe7,0xa3,0x8a,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xe8,0xb3,0x82,0x00,0x01,0xff,0xe9,0x9b,0xb7,0x00,0x10,0x08,0x01,0xff,
+ 0xe5,0xa3,0x98,0x00,0x01,0xff,0xe5,0xb1,0xa2,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0xe6,0xa8,0x93,0x00,0x01,0xff,0xe6,0xb7,0x9a,0x00,0x10,0x08,0x01,0xff,0xe6,0xbc,
+ 0x8f,0x00,0x01,0xff,0xe7,0xb4,0xaf,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xe7,0xb8,0xb7,0x00,0x01,0xff,0xe9,0x99,0x8b,0x00,0x10,0x08,0x01,0xff,
+ 0xe5,0x8b,0x92,0x00,0x01,0xff,0xe8,0x82,0x8b,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0xe5,0x87,0x9c,0x00,0x01,0xff,0xe5,0x87,0x8c,0x00,0x10,0x08,0x01,0xff,0xe7,0xa8,
+ 0x9c,0x00,0x01,0xff,0xe7,0xb6,0xbe,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0xe8,0x8f,0xb1,0x00,0x01,0xff,0xe9,0x99,0xb5,0x00,0x10,0x08,0x01,0xff,0xe8,0xae,
+ 0x80,0x00,0x01,0xff,0xe6,0x8b,0x8f,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xa8,
+ 0x82,0x00,0x01,0xff,0xe8,0xab,0xbe,0x00,0x10,0x08,0x01,0xff,0xe4,0xb8,0xb9,0x00,
+ 0x01,0xff,0xe5,0xaf,0xa7,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xe6,0x80,0x92,0x00,0x01,0xff,0xe7,0x8e,0x87,0x00,0x10,0x08,0x01,0xff,
+ 0xe7,0x95,0xb0,0x00,0x01,0xff,0xe5,0x8c,0x97,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0xe7,0xa3,0xbb,0x00,0x01,0xff,0xe4,0xbe,0xbf,0x00,0x10,0x08,0x01,0xff,0xe5,0xbe,
+ 0xa9,0x00,0x01,0xff,0xe4,0xb8,0x8d,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0xe6,0xb3,0x8c,0x00,0x01,0xff,0xe6,0x95,0xb8,0x00,0x10,0x08,0x01,0xff,0xe7,0xb4,
+ 0xa2,0x00,0x01,0xff,0xe5,0x8f,0x83,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0xa1,
+ 0x9e,0x00,0x01,0xff,0xe7,0x9c,0x81,0x00,0x10,0x08,0x01,0xff,0xe8,0x91,0x89,0x00,
+ 0x01,0xff,0xe8,0xaa,0xaa,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0xe6,0xae,0xba,0x00,0x01,0xff,0xe8,0xbe,0xb0,0x00,0x10,0x08,0x01,0xff,0xe6,0xb2,
+ 0x88,0x00,0x01,0xff,0xe6,0x8b,0xbe,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x8b,
+ 0xa5,0x00,0x01,0xff,0xe6,0x8e,0xa0,0x00,0x10,0x08,0x01,0xff,0xe7,0x95,0xa5,0x00,
+ 0x01,0xff,0xe4,0xba,0xae,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x85,
+ 0xa9,0x00,0x01,0xff,0xe5,0x87,0x89,0x00,0x10,0x08,0x01,0xff,0xe6,0xa2,0x81,0x00,
+ 0x01,0xff,0xe7,0xb3,0xa7,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0x89,0xaf,0x00,
+ 0x01,0xff,0xe8,0xab,0x92,0x00,0x10,0x08,0x01,0xff,0xe9,0x87,0x8f,0x00,0x01,0xff,
+ 0xe5,0x8b,0xb5,0x00,0xe0,0x04,0x02,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,
+ 0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe5,0x91,0x82,0x00,0x01,0xff,0xe5,0xa5,
+ 0xb3,0x00,0x10,0x08,0x01,0xff,0xe5,0xbb,0xac,0x00,0x01,0xff,0xe6,0x97,0x85,0x00,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0xbf,0xbe,0x00,0x01,0xff,0xe7,0xa4,0xaa,0x00,
+ 0x10,0x08,0x01,0xff,0xe9,0x96,0xad,0x00,0x01,0xff,0xe9,0xa9,0xaa,0x00,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xba,0x97,0x00,0x01,0xff,0xe9,0xbb,0x8e,0x00,
+ 0x10,0x08,0x01,0xff,0xe5,0x8a,0x9b,0x00,0x01,0xff,0xe6,0x9b,0x86,0x00,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xe6,0xad,0xb7,0x00,0x01,0xff,0xe8,0xbd,0xa2,0x00,0x10,0x08,
+ 0x01,0xff,0xe5,0xb9,0xb4,0x00,0x01,0xff,0xe6,0x86,0x90,0x00,0xd3,0x40,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x88,0x80,0x00,0x01,0xff,0xe6,0x92,0x9a,0x00,
+ 0x10,0x08,0x01,0xff,0xe6,0xbc,0xa3,0x00,0x01,0xff,0xe7,0x85,0x89,0x00,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xe7,0x92,0x89,0x00,0x01,0xff,0xe7,0xa7,0x8a,0x00,0x10,0x08,
+ 0x01,0xff,0xe7,0xb7,0xb4,0x00,0x01,0xff,0xe8,0x81,0xaf,0x00,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xe8,0xbc,0xa6,0x00,0x01,0xff,0xe8,0x93,0xae,0x00,0x10,0x08,
+ 0x01,0xff,0xe9,0x80,0xa3,0x00,0x01,0xff,0xe9,0x8d,0x8a,0x00,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xe5,0x88,0x97,0x00,0x01,0xff,0xe5,0x8a,0xa3,0x00,0x10,0x08,0x01,0xff,
+ 0xe5,0x92,0xbd,0x00,0x01,0xff,0xe7,0x83,0x88,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0xe8,0xa3,0x82,0x00,0x01,0xff,0xe8,0xaa,0xaa,0x00,
+ 0x10,0x08,0x01,0xff,0xe5,0xbb,0x89,0x00,0x01,0xff,0xe5,0xbf,0xb5,0x00,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xe6,0x8d,0xbb,0x00,0x01,0xff,0xe6,0xae,0xae,0x00,0x10,0x08,
+ 0x01,0xff,0xe7,0xb0,0xbe,0x00,0x01,0xff,0xe7,0x8d,0xb5,0x00,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xe4,0xbb,0xa4,0x00,0x01,0xff,0xe5,0x9b,0xb9,0x00,0x10,0x08,
+ 0x01,0xff,0xe5,0xaf,0xa7,0x00,0x01,0xff,0xe5,0xb6,0xba,0x00,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xe6,0x80,0x9c,0x00,0x01,0xff,0xe7,0x8e,0xb2,0x00,0x10,0x08,0x01,0xff,
+ 0xe7,0x91,0xa9,0x00,0x01,0xff,0xe7,0xbe,0x9a,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xe8,0x81,0x86,0x00,0x01,0xff,0xe9,0x88,0xb4,0x00,0x10,0x08,
+ 0x01,0xff,0xe9,0x9b,0xb6,0x00,0x01,0xff,0xe9,0x9d,0x88,0x00,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xe9,0xa0,0x98,0x00,0x01,0xff,0xe4,0xbe,0x8b,0x00,0x10,0x08,0x01,0xff,
+ 0xe7,0xa6,0xae,0x00,0x01,0xff,0xe9,0x86,0xb4,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xe9,0x9a,0xb8,0x00,0x01,0xff,0xe6,0x83,0xa1,0x00,0x10,0x08,0x01,0xff,
+ 0xe4,0xba,0x86,0x00,0x01,0xff,0xe5,0x83,0x9a,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0xe5,0xaf,0xae,0x00,0x01,0xff,0xe5,0xb0,0xbf,0x00,0x10,0x08,0x01,0xff,0xe6,0x96,
+ 0x99,0x00,0x01,0xff,0xe6,0xa8,0x82,0x00,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,
+ 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0x87,0x8e,0x00,0x01,0xff,0xe7,
+ 0x99,0x82,0x00,0x10,0x08,0x01,0xff,0xe8,0x93,0xbc,0x00,0x01,0xff,0xe9,0x81,0xbc,
+ 0x00,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xbe,0x8d,0x00,0x01,0xff,0xe6,0x9a,0x88,
+ 0x00,0x10,0x08,0x01,0xff,0xe9,0x98,0xae,0x00,0x01,0xff,0xe5,0x8a,0x89,0x00,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x9d,0xbb,0x00,0x01,0xff,0xe6,0x9f,0xb3,
+ 0x00,0x10,0x08,0x01,0xff,0xe6,0xb5,0x81,0x00,0x01,0xff,0xe6,0xba,0x9c,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0xe7,0x90,0x89,0x00,0x01,0xff,0xe7,0x95,0x99,0x00,0x10,
+ 0x08,0x01,0xff,0xe7,0xa1,0xab,0x00,0x01,0xff,0xe7,0xb4,0x90,0x00,0xd3,0x40,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe9,0xa1,0x9e,0x00,0x01,0xff,0xe5,0x85,0xad,
+ 0x00,0x10,0x08,0x01,0xff,0xe6,0x88,0xae,0x00,0x01,0xff,0xe9,0x99,0xb8,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0xe5,0x80,0xab,0x00,0x01,0xff,0xe5,0xb4,0x99,0x00,0x10,
+ 0x08,0x01,0xff,0xe6,0xb7,0xaa,0x00,0x01,0xff,0xe8,0xbc,0xaa,0x00,0xd2,0x20,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0xe5,0xbe,0x8b,0x00,0x01,0xff,0xe6,0x85,0x84,0x00,0x10,
+ 0x08,0x01,0xff,0xe6,0xa0,0x97,0x00,0x01,0xff,0xe7,0x8e,0x87,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0xe9,0x9a,0x86,0x00,0x01,0xff,0xe5,0x88,0xa9,0x00,0x10,0x08,0x01,
+ 0xff,0xe5,0x90,0x8f,0x00,0x01,0xff,0xe5,0xb1,0xa5,0x00,0xd4,0x80,0xd3,0x40,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x01,0xff,0xe6,0x98,0x93,0x00,0x01,0xff,0xe6,0x9d,0x8e,
+ 0x00,0x10,0x08,0x01,0xff,0xe6,0xa2,0xa8,0x00,0x01,0xff,0xe6,0xb3,0xa5,0x00,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0xe7,0x90,0x86,0x00,0x01,0xff,0xe7,0x97,0xa2,0x00,0x10,
+ 0x08,0x01,0xff,0xe7,0xbd,0xb9,0x00,0x01,0xff,0xe8,0xa3,0x8f,0x00,0xd2,0x20,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0xe8,0xa3,0xa1,0x00,0x01,0xff,0xe9,0x87,0x8c,0x00,0x10,
+ 0x08,0x01,0xff,0xe9,0x9b,0xa2,0x00,0x01,0xff,0xe5,0x8c,0xbf,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0xe6,0xba,0xba,0x00,0x01,0xff,0xe5,0x90,0x9d,0x00,0x10,0x08,0x01,
+ 0xff,0xe7,0x87,0x90,0x00,0x01,0xff,0xe7,0x92,0x98,0x00,0xd3,0x40,0xd2,0x20,0xd1,
+ 0x10,0x10,0x08,0x01,0xff,0xe8,0x97,0xba,0x00,0x01,0xff,0xe9,0x9a,0xa3,0x00,0x10,
+ 0x08,0x01,0xff,0xe9,0xb1,0x97,0x00,0x01,0xff,0xe9,0xba,0x9f,0x00,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0xe6,0x9e,0x97,0x00,0x01,0xff,0xe6,0xb7,0x8b,0x00,0x10,0x08,0x01,
+ 0xff,0xe8,0x87,0xa8,0x00,0x01,0xff,0xe7,0xab,0x8b,0x00,0xd2,0x20,0xd1,0x10,0x10,
+ 0x08,0x01,0xff,0xe7,0xac,0xa0,0x00,0x01,0xff,0xe7,0xb2,0x92,0x00,0x10,0x08,0x01,
+ 0xff,0xe7,0x8b,0x80,0x00,0x01,0xff,0xe7,0x82,0x99,0x00,0xd1,0x10,0x10,0x08,0x01,
+ 0xff,0xe8,0xad,0x98,0x00,0x01,0xff,0xe4,0xbb,0x80,0x00,0x10,0x08,0x01,0xff,0xe8,
+ 0x8c,0xb6,0x00,0x01,0xff,0xe5,0x88,0xba,0x00,0xe2,0xad,0x06,0xe1,0xc4,0x03,0xe0,
+ 0xcb,0x01,0xcf,0x86,0xd5,0xe4,0xd4,0x74,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x01,0xff,0xe5,0x88,0x87,0x00,0x01,0xff,0xe5,0xba,0xa6,0x00,0x10,0x08,0x01,0xff,
+ 0xe6,0x8b,0x93,0x00,0x01,0xff,0xe7,0xb3,0x96,0x00,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0xe5,0xae,0x85,0x00,0x01,0xff,0xe6,0xb4,0x9e,0x00,0x10,0x08,0x01,0xff,0xe6,0x9a,
+ 0xb4,0x00,0x01,0xff,0xe8,0xbc,0xbb,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x01,0xff,
+ 0xe8,0xa1,0x8c,0x00,0x01,0xff,0xe9,0x99,0x8d,0x00,0x10,0x08,0x01,0xff,0xe8,0xa6,
+ 0x8b,0x00,0x01,0xff,0xe5,0xbb,0x93,0x00,0x91,0x10,0x10,0x08,0x01,0xff,0xe5,0x85,
+ 0x80,0x00,0x01,0xff,0xe5,0x97,0x80,0x00,0x01,0x00,0xd3,0x34,0xd2,0x18,0xd1,0x0c,
+ 0x10,0x08,0x01,0xff,0xe5,0xa1,0x9a,0x00,0x01,0x00,0x10,0x08,0x01,0xff,0xe6,0x99,
+ 0xb4,0x00,0x01,0x00,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0xe5,0x87,0x9e,0x00,
+ 0x10,0x08,0x01,0xff,0xe7,0x8c,0xaa,0x00,0x01,0xff,0xe7,0x9b,0x8a,0x00,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x01,0xff,0xe7,0xa4,0xbc,0x00,0x01,0xff,0xe7,0xa5,0x9e,0x00,
+ 0x10,0x08,0x01,0xff,0xe7,0xa5,0xa5,0x00,0x01,0xff,0xe7,0xa6,0x8f,0x00,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xe9,0x9d,0x96,0x00,0x01,0xff,0xe7,0xb2,0xbe,0x00,0x10,0x08,
+ 0x01,0xff,0xe7,0xbe,0xbd,0x00,0x01,0x00,0xd4,0x64,0xd3,0x30,0xd2,0x18,0xd1,0x0c,
+ 0x10,0x08,0x01,0xff,0xe8,0x98,0x92,0x00,0x01,0x00,0x10,0x08,0x01,0xff,0xe8,0xab,
+ 0xb8,0x00,0x01,0x00,0xd1,0x0c,0x10,0x04,0x01,0x00,0x01,0xff,0xe9,0x80,0xb8,0x00,
+ 0x10,0x08,0x01,0xff,0xe9,0x83,0xbd,0x00,0x01,0x00,0xd2,0x14,0x51,0x04,0x01,0x00,
+ 0x10,0x08,0x01,0xff,0xe9,0xa3,0xaf,0x00,0x01,0xff,0xe9,0xa3,0xbc,0x00,0xd1,0x10,
+ 0x10,0x08,0x01,0xff,0xe9,0xa4,0xa8,0x00,0x01,0xff,0xe9,0xb6,0xb4,0x00,0x10,0x08,
+ 0x0d,0xff,0xe9,0x83,0x9e,0x00,0x0d,0xff,0xe9,0x9a,0xb7,0x00,0xd3,0x40,0xd2,0x20,
+ 0xd1,0x10,0x10,0x08,0x06,0xff,0xe4,0xbe,0xae,0x00,0x06,0xff,0xe5,0x83,0xa7,0x00,
+ 0x10,0x08,0x06,0xff,0xe5,0x85,0x8d,0x00,0x06,0xff,0xe5,0x8b,0x89,0x00,0xd1,0x10,
+ 0x10,0x08,0x06,0xff,0xe5,0x8b,0xa4,0x00,0x06,0xff,0xe5,0x8d,0x91,0x00,0x10,0x08,
+ 0x06,0xff,0xe5,0x96,0x9d,0x00,0x06,0xff,0xe5,0x98,0x86,0x00,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x06,0xff,0xe5,0x99,0xa8,0x00,0x06,0xff,0xe5,0xa1,0x80,0x00,0x10,0x08,
+ 0x06,0xff,0xe5,0xa2,0xa8,0x00,0x06,0xff,0xe5,0xb1,0xa4,0x00,0xd1,0x10,0x10,0x08,
+ 0x06,0xff,0xe5,0xb1,0xae,0x00,0x06,0xff,0xe6,0x82,0x94,0x00,0x10,0x08,0x06,0xff,
+ 0xe6,0x85,0xa8,0x00,0x06,0xff,0xe6,0x86,0x8e,0x00,0xcf,0x86,0xe5,0x01,0x01,0xd4,
+ 0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe6,0x87,0xb2,0x00,0x06,
+ 0xff,0xe6,0x95,0x8f,0x00,0x10,0x08,0x06,0xff,0xe6,0x97,0xa2,0x00,0x06,0xff,0xe6,
+ 0x9a,0x91,0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe6,0xa2,0x85,0x00,0x06,0xff,0xe6,
+ 0xb5,0xb7,0x00,0x10,0x08,0x06,0xff,0xe6,0xb8,0x9a,0x00,0x06,0xff,0xe6,0xbc,0xa2,
+ 0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe7,0x85,0xae,0x00,0x06,0xff,0xe7,
+ 0x88,0xab,0x00,0x10,0x08,0x06,0xff,0xe7,0x90,0xa2,0x00,0x06,0xff,0xe7,0xa2,0x91,
+ 0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe7,0xa4,0xbe,0x00,0x06,0xff,0xe7,0xa5,0x89,
+ 0x00,0x10,0x08,0x06,0xff,0xe7,0xa5,0x88,0x00,0x06,0xff,0xe7,0xa5,0x90,0x00,0xd3,
+ 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe7,0xa5,0x96,0x00,0x06,0xff,0xe7,
+ 0xa5,0x9d,0x00,0x10,0x08,0x06,0xff,0xe7,0xa6,0x8d,0x00,0x06,0xff,0xe7,0xa6,0x8e,
+ 0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe7,0xa9,0x80,0x00,0x06,0xff,0xe7,0xaa,0x81,
+ 0x00,0x10,0x08,0x06,0xff,0xe7,0xaf,0x80,0x00,0x06,0xff,0xe7,0xb7,0xb4,0x00,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe7,0xb8,0x89,0x00,0x06,0xff,0xe7,0xb9,0x81,
+ 0x00,0x10,0x08,0x06,0xff,0xe7,0xbd,0xb2,0x00,0x06,0xff,0xe8,0x80,0x85,0x00,0xd1,
+ 0x10,0x10,0x08,0x06,0xff,0xe8,0x87,0xad,0x00,0x06,0xff,0xe8,0x89,0xb9,0x00,0x10,
+ 0x08,0x06,0xff,0xe8,0x89,0xb9,0x00,0x06,0xff,0xe8,0x91,0x97,0x00,0xd4,0x75,0xd3,
+ 0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe8,0xa4,0x90,0x00,0x06,0xff,0xe8,
+ 0xa6,0x96,0x00,0x10,0x08,0x06,0xff,0xe8,0xac,0x81,0x00,0x06,0xff,0xe8,0xac,0xb9,
+ 0x00,0xd1,0x10,0x10,0x08,0x06,0xff,0xe8,0xb3,0x93,0x00,0x06,0xff,0xe8,0xb4,0x88,
+ 0x00,0x10,0x08,0x06,0xff,0xe8,0xbe,0xb6,0x00,0x06,0xff,0xe9,0x80,0xb8,0x00,0xd2,
+ 0x20,0xd1,0x10,0x10,0x08,0x06,0xff,0xe9,0x9b,0xa3,0x00,0x06,0xff,0xe9,0x9f,0xbf,
+ 0x00,0x10,0x08,0x06,0xff,0xe9,0xa0,0xbb,0x00,0x0b,0xff,0xe6,0x81,0xb5,0x00,0x91,
+ 0x11,0x10,0x09,0x0b,0xff,0xf0,0xa4,0x8b,0xae,0x00,0x0b,0xff,0xe8,0x88,0x98,0x00,
+ 0x00,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe4,0xb8,0xa6,0x00,
+ 0x08,0xff,0xe5,0x86,0xb5,0x00,0x10,0x08,0x08,0xff,0xe5,0x85,0xa8,0x00,0x08,0xff,
+ 0xe4,0xbe,0x80,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe5,0x85,0x85,0x00,0x08,0xff,
+ 0xe5,0x86,0x80,0x00,0x10,0x08,0x08,0xff,0xe5,0x8b,0x87,0x00,0x08,0xff,0xe5,0x8b,
+ 0xba,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe5,0x96,0x9d,0x00,0x08,0xff,
+ 0xe5,0x95,0x95,0x00,0x10,0x08,0x08,0xff,0xe5,0x96,0x99,0x00,0x08,0xff,0xe5,0x97,
+ 0xa2,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe5,0xa1,0x9a,0x00,0x08,0xff,0xe5,0xa2,
+ 0xb3,0x00,0x10,0x08,0x08,0xff,0xe5,0xa5,0x84,0x00,0x08,0xff,0xe5,0xa5,0x94,0x00,
+ 0xe0,0x04,0x02,0xcf,0x86,0xe5,0x01,0x01,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x08,0xff,0xe5,0xa9,0xa2,0x00,0x08,0xff,0xe5,0xac,0xa8,0x00,0x10,0x08,
+ 0x08,0xff,0xe5,0xbb,0x92,0x00,0x08,0xff,0xe5,0xbb,0x99,0x00,0xd1,0x10,0x10,0x08,
+ 0x08,0xff,0xe5,0xbd,0xa9,0x00,0x08,0xff,0xe5,0xbe,0xad,0x00,0x10,0x08,0x08,0xff,
+ 0xe6,0x83,0x98,0x00,0x08,0xff,0xe6,0x85,0x8e,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x08,0xff,0xe6,0x84,0x88,0x00,0x08,0xff,0xe6,0x86,0x8e,0x00,0x10,0x08,0x08,0xff,
+ 0xe6,0x85,0xa0,0x00,0x08,0xff,0xe6,0x87,0xb2,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe6,0x88,0xb4,0x00,0x08,0xff,0xe6,0x8f,0x84,0x00,0x10,0x08,0x08,0xff,0xe6,0x90,
+ 0x9c,0x00,0x08,0xff,0xe6,0x91,0x92,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x08,0xff,0xe6,0x95,0x96,0x00,0x08,0xff,0xe6,0x99,0xb4,0x00,0x10,0x08,0x08,0xff,
+ 0xe6,0x9c,0x97,0x00,0x08,0xff,0xe6,0x9c,0x9b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe6,0x9d,0x96,0x00,0x08,0xff,0xe6,0xad,0xb9,0x00,0x10,0x08,0x08,0xff,0xe6,0xae,
+ 0xba,0x00,0x08,0xff,0xe6,0xb5,0x81,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe6,0xbb,0x9b,0x00,0x08,0xff,0xe6,0xbb,0x8b,0x00,0x10,0x08,0x08,0xff,0xe6,0xbc,
+ 0xa2,0x00,0x08,0xff,0xe7,0x80,0x9e,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe7,0x85,
+ 0xae,0x00,0x08,0xff,0xe7,0x9e,0xa7,0x00,0x10,0x08,0x08,0xff,0xe7,0x88,0xb5,0x00,
+ 0x08,0xff,0xe7,0x8a,0xaf,0x00,0xd4,0x80,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x08,0xff,0xe7,0x8c,0xaa,0x00,0x08,0xff,0xe7,0x91,0xb1,0x00,0x10,0x08,0x08,0xff,
+ 0xe7,0x94,0x86,0x00,0x08,0xff,0xe7,0x94,0xbb,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe7,0x98,0x9d,0x00,0x08,0xff,0xe7,0x98,0x9f,0x00,0x10,0x08,0x08,0xff,0xe7,0x9b,
+ 0x8a,0x00,0x08,0xff,0xe7,0x9b,0x9b,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe7,0x9b,0xb4,0x00,0x08,0xff,0xe7,0x9d,0x8a,0x00,0x10,0x08,0x08,0xff,0xe7,0x9d,
+ 0x80,0x00,0x08,0xff,0xe7,0xa3,0x8c,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe7,0xaa,
+ 0xb1,0x00,0x08,0xff,0xe7,0xaf,0x80,0x00,0x10,0x08,0x08,0xff,0xe7,0xb1,0xbb,0x00,
+ 0x08,0xff,0xe7,0xb5,0x9b,0x00,0xd3,0x40,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe7,0xb7,0xb4,0x00,0x08,0xff,0xe7,0xbc,0xbe,0x00,0x10,0x08,0x08,0xff,0xe8,0x80,
+ 0x85,0x00,0x08,0xff,0xe8,0x8d,0x92,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe8,0x8f,
+ 0xaf,0x00,0x08,0xff,0xe8,0x9d,0xb9,0x00,0x10,0x08,0x08,0xff,0xe8,0xa5,0x81,0x00,
+ 0x08,0xff,0xe8,0xa6,0x86,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,0x08,0xff,0xe8,0xa6,
+ 0x96,0x00,0x08,0xff,0xe8,0xaa,0xbf,0x00,0x10,0x08,0x08,0xff,0xe8,0xab,0xb8,0x00,
+ 0x08,0xff,0xe8,0xab,0x8b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,0xe8,0xac,0x81,0x00,
+ 0x08,0xff,0xe8,0xab,0xbe,0x00,0x10,0x08,0x08,0xff,0xe8,0xab,0xad,0x00,0x08,0xff,
+ 0xe8,0xac,0xb9,0x00,0xcf,0x86,0x95,0xde,0xd4,0x81,0xd3,0x40,0xd2,0x20,0xd1,0x10,
+ 0x10,0x08,0x08,0xff,0xe8,0xae,0x8a,0x00,0x08,0xff,0xe8,0xb4,0x88,0x00,0x10,0x08,
+ 0x08,0xff,0xe8,0xbc,0xb8,0x00,0x08,0xff,0xe9,0x81,0xb2,0x00,0xd1,0x10,0x10,0x08,
+ 0x08,0xff,0xe9,0x86,0x99,0x00,0x08,0xff,0xe9,0x89,0xb6,0x00,0x10,0x08,0x08,0xff,
+ 0xe9,0x99,0xbc,0x00,0x08,0xff,0xe9,0x9b,0xa3,0x00,0xd2,0x20,0xd1,0x10,0x10,0x08,
+ 0x08,0xff,0xe9,0x9d,0x96,0x00,0x08,0xff,0xe9,0x9f,0x9b,0x00,0x10,0x08,0x08,0xff,
+ 0xe9,0x9f,0xbf,0x00,0x08,0xff,0xe9,0xa0,0x8b,0x00,0xd1,0x10,0x10,0x08,0x08,0xff,
+ 0xe9,0xa0,0xbb,0x00,0x08,0xff,0xe9,0xac,0x92,0x00,0x10,0x08,0x08,0xff,0xe9,0xbe,
+ 0x9c,0x00,0x08,0xff,0xf0,0xa2,0xa1,0x8a,0x00,0xd3,0x45,0xd2,0x22,0xd1,0x12,0x10,
+ 0x09,0x08,0xff,0xf0,0xa2,0xa1,0x84,0x00,0x08,0xff,0xf0,0xa3,0x8f,0x95,0x00,0x10,
+ 0x08,0x08,0xff,0xe3,0xae,0x9d,0x00,0x08,0xff,0xe4,0x80,0x98,0x00,0xd1,0x11,0x10,
+ 0x08,0x08,0xff,0xe4,0x80,0xb9,0x00,0x08,0xff,0xf0,0xa5,0x89,0x89,0x00,0x10,0x09,
+ 0x08,0xff,0xf0,0xa5,0xb3,0x90,0x00,0x08,0xff,0xf0,0xa7,0xbb,0x93,0x00,0x92,0x14,
+ 0x91,0x10,0x10,0x08,0x08,0xff,0xe9,0xbd,0x83,0x00,0x08,0xff,0xe9,0xbe,0x8e,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xe1,0x94,0x01,0xe0,0x08,0x01,0xcf,0x86,0xd5,0x42,
+ 0xd4,0x14,0x93,0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,
+ 0x00,0x00,0x00,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,
+ 0x01,0x00,0x01,0x00,0x52,0x04,0x00,0x00,0xd1,0x0d,0x10,0x04,0x00,0x00,0x04,0xff,
+ 0xd7,0x99,0xd6,0xb4,0x00,0x10,0x04,0x01,0x1a,0x01,0xff,0xd7,0xb2,0xd6,0xb7,0x00,
+ 0xd4,0x42,0x53,0x04,0x01,0x00,0xd2,0x16,0x51,0x04,0x01,0x00,0x10,0x09,0x01,0xff,
+ 0xd7,0xa9,0xd7,0x81,0x00,0x01,0xff,0xd7,0xa9,0xd7,0x82,0x00,0xd1,0x16,0x10,0x0b,
+ 0x01,0xff,0xd7,0xa9,0xd6,0xbc,0xd7,0x81,0x00,0x01,0xff,0xd7,0xa9,0xd6,0xbc,0xd7,
+ 0x82,0x00,0x10,0x09,0x01,0xff,0xd7,0x90,0xd6,0xb7,0x00,0x01,0xff,0xd7,0x90,0xd6,
+ 0xb8,0x00,0xd3,0x43,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0x90,0xd6,0xbc,
+ 0x00,0x01,0xff,0xd7,0x91,0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0x92,0xd6,0xbc,
+ 0x00,0x01,0xff,0xd7,0x93,0xd6,0xbc,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0x94,
+ 0xd6,0xbc,0x00,0x01,0xff,0xd7,0x95,0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0x96,
+ 0xd6,0xbc,0x00,0x00,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0x98,0xd6,
+ 0xbc,0x00,0x01,0xff,0xd7,0x99,0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0x9a,0xd6,
+ 0xbc,0x00,0x01,0xff,0xd7,0x9b,0xd6,0xbc,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xd7,
+ 0x9c,0xd6,0xbc,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xd7,0x9e,0xd6,0xbc,0x00,0x00,
+ 0x00,0xcf,0x86,0x95,0x85,0x94,0x81,0xd3,0x3e,0xd2,0x1f,0xd1,0x12,0x10,0x09,0x01,
+ 0xff,0xd7,0xa0,0xd6,0xbc,0x00,0x01,0xff,0xd7,0xa1,0xd6,0xbc,0x00,0x10,0x04,0x00,
+ 0x00,0x01,0xff,0xd7,0xa3,0xd6,0xbc,0x00,0xd1,0x0d,0x10,0x09,0x01,0xff,0xd7,0xa4,
+ 0xd6,0xbc,0x00,0x00,0x00,0x10,0x09,0x01,0xff,0xd7,0xa6,0xd6,0xbc,0x00,0x01,0xff,
+ 0xd7,0xa7,0xd6,0xbc,0x00,0xd2,0x24,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,0xa8,0xd6,
+ 0xbc,0x00,0x01,0xff,0xd7,0xa9,0xd6,0xbc,0x00,0x10,0x09,0x01,0xff,0xd7,0xaa,0xd6,
+ 0xbc,0x00,0x01,0xff,0xd7,0x95,0xd6,0xb9,0x00,0xd1,0x12,0x10,0x09,0x01,0xff,0xd7,
+ 0x91,0xd6,0xbf,0x00,0x01,0xff,0xd7,0x9b,0xd6,0xbf,0x00,0x10,0x09,0x01,0xff,0xd7,
+ 0xa4,0xd6,0xbf,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd0,0x1a,0xcf,0x86,0x55,0x04,
+ 0x01,0x00,0x54,0x04,0x01,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x01,0x00,0x0c,0x00,
+ 0x0c,0x00,0x0c,0x00,0xcf,0x86,0x95,0x24,0xd4,0x10,0x93,0x0c,0x92,0x08,0x11,0x04,
+ 0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x00,0x00,
+ 0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0xd3,0x5a,0xd2,0x06,
+ 0xcf,0x06,0x01,0x00,0xd1,0x14,0xd0,0x06,0xcf,0x06,0x01,0x00,0xcf,0x86,0x95,0x08,
+ 0x14,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd0,0x1a,0xcf,0x86,0x95,0x14,0x54,0x04,
+ 0x01,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
+ 0x01,0x00,0xcf,0x86,0xd5,0x0c,0x94,0x08,0x13,0x04,0x01,0x00,0x00,0x00,0x05,0x00,
+ 0x54,0x04,0x05,0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x91,0x08,0x10,0x04,
+ 0x06,0x00,0x07,0x00,0x00,0x00,0xd2,0xce,0xd1,0xa5,0xd0,0x37,0xcf,0x86,0xd5,0x15,
+ 0x54,0x05,0x06,0xff,0x00,0x53,0x04,0x08,0x00,0x92,0x08,0x11,0x04,0x08,0x00,0x00,
+ 0x00,0x00,0x00,0x94,0x1c,0xd3,0x10,0x52,0x04,0x01,0xe6,0x51,0x04,0x0a,0xe6,0x10,
+ 0x04,0x0a,0xe6,0x10,0xdc,0x52,0x04,0x10,0xdc,0x11,0x04,0x10,0xdc,0x11,0xe6,0x01,
+ 0x00,0xcf,0x86,0xd5,0x38,0xd4,0x24,0xd3,0x14,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,
+ 0x04,0x01,0x00,0x06,0x00,0x10,0x04,0x06,0x00,0x07,0x00,0x92,0x0c,0x91,0x08,0x10,
+ 0x04,0x07,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x01,
+ 0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd4,0x18,0xd3,0x10,0x52,
+ 0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x12,0x04,0x01,
+ 0x00,0x00,0x00,0x93,0x18,0xd2,0x0c,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x06,
+ 0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0xd0,0x06,0xcf,
+ 0x06,0x01,0x00,0xcf,0x86,0x55,0x04,0x01,0x00,0x54,0x04,0x01,0x00,0x53,0x04,0x01,
+ 0x00,0x52,0x04,0x01,0x00,0xd1,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x10,0x04,0x00,
+ 0x00,0x01,0xff,0x00,0xd1,0x50,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x93,0x10,
+ 0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
+ 0x01,0x00,0x01,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x01,0x00,0x53,0x04,0x01,0x00,
+ 0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x06,0x00,0x94,0x14,
+ 0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x06,0x00,0x01,0x00,0x01,0x00,0x01,0x00,
+ 0x01,0x00,0x01,0x00,0xd0,0x2f,0xcf,0x86,0x55,0x04,0x01,0x00,0xd4,0x15,0x93,0x11,
+ 0x92,0x0d,0x91,0x09,0x10,0x05,0x01,0xff,0x00,0x01,0x00,0x01,0x00,0x01,0x00,0x01,
+ 0x00,0x53,0x04,0x01,0x00,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,
+ 0x00,0x00,0x00,0xcf,0x86,0xd5,0x38,0xd4,0x18,0xd3,0x0c,0x92,0x08,0x11,0x04,0x00,
+ 0x00,0x01,0x00,0x01,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd3,
+ 0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x01,0x00,0x01,0x00,0xd2,0x08,0x11,0x04,0x00,
+ 0x00,0x01,0x00,0x91,0x08,0x10,0x04,0x01,0x00,0x00,0x00,0x00,0x00,0xd4,0x20,0xd3,
+ 0x10,0x52,0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x52,
+ 0x04,0x01,0x00,0x51,0x04,0x01,0x00,0x10,0x04,0x01,0x00,0x00,0x00,0x53,0x05,0x00,
+ 0xff,0x00,0xd2,0x0d,0x91,0x09,0x10,0x05,0x00,0xff,0x00,0x04,0x00,0x04,0x00,0x91,
+ 0x08,0x10,0x04,0x03,0x00,0x01,0x00,0x01,0x00,0x83,0xe2,0x46,0x3e,0xe1,0x1f,0x3b,
+ 0xe0,0x9c,0x39,0xcf,0x86,0xe5,0x40,0x26,0xc4,0xe3,0x16,0x14,0xe2,0xef,0x11,0xe1,
+ 0xd0,0x10,0xe0,0x60,0x07,0xcf,0x86,0xe5,0x53,0x03,0xe4,0x4c,0x02,0xe3,0x3d,0x01,
+ 0xd2,0x94,0xd1,0x70,0xd0,0x4a,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x07,0x00,
+ 0x52,0x04,0x07,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,
+ 0xd4,0x14,0x93,0x10,0x52,0x04,0x07,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,
+ 0x00,0x00,0x07,0x00,0x53,0x04,0x07,0x00,0xd2,0x0c,0x51,0x04,0x07,0x00,0x10,0x04,
+ 0x07,0x00,0x00,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x00,0x00,0x07,0x00,0xcf,0x86,
+ 0x95,0x20,0xd4,0x10,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,0x11,0x04,0x07,0x00,
+ 0x00,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,0x11,0x04,0x07,0x00,0x00,0x00,
+ 0x00,0x00,0xd0,0x06,0xcf,0x06,0x07,0x00,0xcf,0x86,0x55,0x04,0x07,0x00,0x54,0x04,
+ 0x07,0x00,0x53,0x04,0x07,0x00,0x92,0x0c,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,
+ 0x00,0x00,0x00,0x00,0xd1,0x40,0xd0,0x3a,0xcf,0x86,0xd5,0x20,0x94,0x1c,0x93,0x18,
+ 0xd2,0x0c,0x51,0x04,0x07,0x00,0x10,0x04,0x07,0x00,0x00,0x00,0x51,0x04,0x00,0x00,
+ 0x10,0x04,0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x54,0x04,0x07,0x00,0x93,0x10,
+ 0x52,0x04,0x07,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x07,0x00,0x07,0x00,
+ 0xcf,0x06,0x08,0x00,0xd0,0x46,0xcf,0x86,0xd5,0x2c,0xd4,0x20,0x53,0x04,0x08,0x00,
+ 0xd2,0x0c,0x51,0x04,0x08,0x00,0x10,0x04,0x08,0x00,0x10,0x00,0xd1,0x08,0x10,0x04,
+ 0x10,0x00,0x12,0x00,0x10,0x04,0x12,0x00,0x00,0x00,0x53,0x04,0x0a,0x00,0x12,0x04,
+ 0x0a,0x00,0x00,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x08,0x14,0x04,
+ 0x00,0x00,0x0a,0x00,0x54,0x04,0x0a,0x00,0x53,0x04,0x0a,0x00,0x52,0x04,0x0a,0x00,
+ 0x91,0x08,0x10,0x04,0x0a,0x00,0x0a,0xdc,0x00,0x00,0xd2,0x5e,0xd1,0x06,0xcf,0x06,
+ 0x00,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x0a,0x00,0x53,0x04,0x0a,0x00,
+ 0x52,0x04,0x0a,0x00,0x91,0x08,0x10,0x04,0x0a,0x00,0x00,0x00,0x00,0x00,0x0a,0x00,
+ 0xcf,0x86,0xd5,0x18,0x54,0x04,0x0a,0x00,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,
+ 0x0a,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c,
+ 0x91,0x08,0x10,0x04,0x10,0xdc,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x53,0x04,
+ 0x10,0x00,0x12,0x04,0x10,0x00,0x00,0x00,0xd1,0x70,0xd0,0x36,0xcf,0x86,0xd5,0x18,
+ 0x54,0x04,0x05,0x00,0x53,0x04,0x05,0x00,0x52,0x04,0x05,0x00,0x51,0x04,0x05,0x00,
+ 0x10,0x04,0x05,0x00,0x10,0x00,0x94,0x18,0xd3,0x08,0x12,0x04,0x05,0x00,0x00,0x00,
+ 0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x13,0x00,0x13,0x00,0x05,0x00,
+ 0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x05,0x00,0x92,0x0c,0x51,0x04,0x05,0x00,
+ 0x10,0x04,0x05,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0x54,0x04,0x10,0x00,0xd3,0x0c,
+ 0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x10,0xe6,0x92,0x0c,0x51,0x04,0x10,0xe6,
+ 0x10,0x04,0x10,0xe6,0x00,0x00,0x00,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,
+ 0x07,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,0x51,0x04,0x07,0x00,0x10,0x04,
+ 0x00,0x00,0x07,0x00,0x08,0x00,0xcf,0x86,0x95,0x1c,0xd4,0x0c,0x93,0x08,0x12,0x04,
+ 0x08,0x00,0x00,0x00,0x08,0x00,0x93,0x0c,0x52,0x04,0x08,0x00,0x11,0x04,0x08,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0xd3,0xba,0xd2,0x80,0xd1,0x34,0xd0,0x1a,0xcf,0x86,
+ 0x55,0x04,0x05,0x00,0x94,0x10,0x93,0x0c,0x52,0x04,0x05,0x00,0x11,0x04,0x05,0x00,
+ 0x07,0x00,0x05,0x00,0x05,0x00,0xcf,0x86,0x95,0x14,0x94,0x10,0x53,0x04,0x05,0x00,
+ 0x52,0x04,0x05,0x00,0x11,0x04,0x05,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0xd0,0x2a,
+ 0xcf,0x86,0xd5,0x14,0x54,0x04,0x07,0x00,0x53,0x04,0x07,0x00,0x52,0x04,0x07,0x00,
+ 0x11,0x04,0x07,0x00,0x00,0x00,0x94,0x10,0x53,0x04,0x07,0x00,0x92,0x08,0x11,0x04,
+ 0x07,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0xcf,0x86,0xd5,0x10,0x54,0x04,0x12,0x00,
+ 0x93,0x08,0x12,0x04,0x12,0x00,0x00,0x00,0x12,0x00,0x54,0x04,0x12,0x00,0x53,0x04,
+ 0x12,0x00,0x12,0x04,0x12,0x00,0x00,0x00,0xd1,0x34,0xd0,0x12,0xcf,0x86,0x55,0x04,
+ 0x10,0x00,0x94,0x08,0x13,0x04,0x10,0x00,0x00,0x00,0x10,0x00,0xcf,0x86,0x55,0x04,
+ 0x10,0x00,0x94,0x18,0xd3,0x08,0x12,0x04,0x10,0x00,0x00,0x00,0x52,0x04,0x00,0x00,
+ 0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,
+ 0xd2,0x06,0xcf,0x06,0x10,0x00,0xd1,0x40,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x10,0x00,
+ 0x54,0x04,0x10,0x00,0x93,0x10,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,
+ 0x10,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x14,0x54,0x04,0x10,0x00,0x93,0x0c,
+ 0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x94,0x08,0x13,0x04,
+ 0x10,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xe4,0xce,0x02,0xe3,0x45,0x01,
+ 0xd2,0xd0,0xd1,0x70,0xd0,0x52,0xcf,0x86,0xd5,0x20,0x94,0x1c,0xd3,0x0c,0x52,0x04,
+ 0x07,0x00,0x11,0x04,0x07,0x00,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x07,0x00,
+ 0x00,0x00,0x07,0x00,0x07,0x00,0x07,0x00,0x54,0x04,0x07,0x00,0xd3,0x10,0x52,0x04,
+ 0x07,0x00,0x51,0x04,0x07,0x00,0x10,0x04,0x00,0x00,0x07,0x00,0xd2,0x0c,0x91,0x08,
+ 0x10,0x04,0x07,0x00,0x00,0x00,0x00,0x00,0xd1,0x08,0x10,0x04,0x07,0x00,0x00,0x00,
+ 0x10,0x04,0x00,0x00,0x07,0x00,0xcf,0x86,0x95,0x18,0x54,0x04,0x0b,0x00,0x93,0x10,
+ 0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,0x00,0x00,0x0b,0x00,0x0b,0x00,
+ 0x10,0x00,0xd0,0x32,0xcf,0x86,0xd5,0x18,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,
+ 0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x94,0x14,
+ 0x93,0x10,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,
+ 0x10,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x11,0x00,0xd3,0x14,
+ 0xd2,0x0c,0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0x11,0x04,0x11,0x00,
+ 0x00,0x00,0x92,0x0c,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x11,0x00,0x11,0x00,
+ 0xd1,0x40,0xd0,0x3a,0xcf,0x86,0xd5,0x1c,0x54,0x04,0x09,0x00,0x53,0x04,0x09,0x00,
+ 0xd2,0x08,0x11,0x04,0x09,0x00,0x0b,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,
+ 0x09,0x00,0x54,0x04,0x0a,0x00,0x53,0x04,0x0a,0x00,0xd2,0x08,0x11,0x04,0x0a,0x00,
+ 0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0a,0x00,0xcf,0x06,0x00,0x00,
+ 0xd0,0x1a,0xcf,0x86,0x55,0x04,0x0d,0x00,0x54,0x04,0x0d,0x00,0x53,0x04,0x0d,0x00,
+ 0x52,0x04,0x00,0x00,0x11,0x04,0x11,0x00,0x0d,0x00,0xcf,0x86,0x95,0x14,0x54,0x04,
+ 0x11,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x11,0x00,0x11,0x00,0x11,0x00,
+ 0x11,0x00,0xd2,0xec,0xd1,0xa4,0xd0,0x76,0xcf,0x86,0xd5,0x48,0xd4,0x28,0xd3,0x14,
+ 0x52,0x04,0x08,0x00,0xd1,0x08,0x10,0x04,0x00,0x00,0x08,0x00,0x10,0x04,0x08,0x00,
+ 0x00,0x00,0x52,0x04,0x00,0x00,0xd1,0x08,0x10,0x04,0x08,0x00,0x08,0xdc,0x10,0x04,
+ 0x08,0x00,0x08,0xe6,0xd3,0x10,0x52,0x04,0x08,0x00,0x91,0x08,0x10,0x04,0x00,0x00,
+ 0x08,0x00,0x08,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x08,0x00,0x08,0x00,
+ 0x08,0x00,0x54,0x04,0x08,0x00,0xd3,0x0c,0x52,0x04,0x08,0x00,0x11,0x04,0x14,0x00,
+ 0x00,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,0x08,0xe6,0x08,0x01,0x10,0x04,0x08,0xdc,
+ 0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x08,0x09,0xcf,0x86,0x95,0x28,
+ 0xd4,0x14,0x53,0x04,0x08,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x53,0x04,0x08,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x08,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x0b,0x00,0xd0,0x0a,0xcf,0x86,0x15,0x04,0x10,0x00,
+ 0x00,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0xd4,0x24,0xd3,0x14,0x52,0x04,0x10,0x00,
+ 0xd1,0x08,0x10,0x04,0x10,0x00,0x10,0xe6,0x10,0x04,0x10,0xdc,0x00,0x00,0x92,0x0c,
+ 0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x93,0x10,0x52,0x04,
+ 0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd1,0x54,
+ 0xd0,0x26,0xcf,0x86,0x55,0x04,0x0b,0x00,0x54,0x04,0x0b,0x00,0xd3,0x0c,0x52,0x04,
+ 0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,
+ 0x0b,0x00,0x0b,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x14,0x54,0x04,0x0b,0x00,0x93,0x0c,
+ 0x52,0x04,0x0b,0x00,0x11,0x04,0x0b,0x00,0x00,0x00,0x0b,0x00,0x54,0x04,0x0b,0x00,
+ 0x93,0x10,0x92,0x0c,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,
+ 0x0b,0x00,0xd0,0x42,0xcf,0x86,0xd5,0x28,0x54,0x04,0x10,0x00,0xd3,0x0c,0x92,0x08,
+ 0x11,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd2,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,
+ 0x10,0x00,0x10,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x94,0x14,
+ 0x53,0x04,0x00,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,
+ 0x10,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd3,0x96,0xd2,0x68,0xd1,0x24,0xd0,0x06,
+ 0xcf,0x06,0x0b,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,0x53,0x04,0x0b,0x00,0x92,0x0c,
+ 0x91,0x08,0x10,0x04,0x0b,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xd0,0x1e,0xcf,0x86,0x55,0x04,0x11,0x00,0x54,0x04,0x11,0x00,0x93,0x10,0x92,0x0c,
+ 0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,
+ 0x55,0x04,0x11,0x00,0x54,0x04,0x11,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x11,0x00,
+ 0x10,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x11,0x00,
+ 0x11,0x00,0xd1,0x28,0xd0,0x22,0xcf,0x86,0x55,0x04,0x14,0x00,0xd4,0x0c,0x93,0x08,
+ 0x12,0x04,0x14,0x00,0x14,0xe6,0x00,0x00,0x53,0x04,0x14,0x00,0x92,0x08,0x11,0x04,
+ 0x14,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xd2,0x2a,
+ 0xd1,0x24,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,
+ 0x0b,0x00,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,0x04,
+ 0x0b,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1,0x58,0xd0,0x12,0xcf,0x86,0x55,0x04,
+ 0x14,0x00,0x94,0x08,0x13,0x04,0x14,0x00,0x00,0x00,0x14,0x00,0xcf,0x86,0x95,0x40,
+ 0xd4,0x24,0xd3,0x0c,0x52,0x04,0x14,0x00,0x11,0x04,0x14,0x00,0x14,0xdc,0xd2,0x0c,
+ 0x51,0x04,0x14,0xe6,0x10,0x04,0x14,0xe6,0x14,0xdc,0x91,0x08,0x10,0x04,0x14,0xe6,
+ 0x14,0xdc,0x14,0xdc,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0xdc,0x14,0x00,
+ 0x14,0x00,0x14,0x00,0x92,0x08,0x11,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x15,0x00,
+ 0x93,0x10,0x52,0x04,0x15,0x00,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00,0x00,
+ 0x00,0x00,0xcf,0x86,0xe5,0x0f,0x06,0xe4,0xf8,0x03,0xe3,0x02,0x02,0xd2,0xfb,0xd1,
+ 0x4c,0xd0,0x06,0xcf,0x06,0x0c,0x00,0xcf,0x86,0xd5,0x2c,0xd4,0x1c,0xd3,0x10,0x52,
+ 0x04,0x0c,0x00,0x51,0x04,0x0c,0x00,0x10,0x04,0x0c,0x09,0x0c,0x00,0x52,0x04,0x0c,
+ 0x00,0x11,0x04,0x0c,0x00,0x00,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x0c,
+ 0x00,0x0c,0x00,0x0c,0x00,0x54,0x04,0x0c,0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00,
+ 0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x09,0xd0,0x69,0xcf,0x86,0xd5,
+ 0x32,0x54,0x04,0x0b,0x00,0x53,0x04,0x0b,0x00,0xd2,0x15,0x51,0x04,0x0b,0x00,0x10,
+ 0x0d,0x0b,0xff,0xf0,0x91,0x82,0x99,0xf0,0x91,0x82,0xba,0x00,0x0b,0x00,0x91,0x11,
+ 0x10,0x0d,0x0b,0xff,0xf0,0x91,0x82,0x9b,0xf0,0x91,0x82,0xba,0x00,0x0b,0x00,0x0b,
+ 0x00,0xd4,0x1d,0x53,0x04,0x0b,0x00,0x92,0x15,0x51,0x04,0x0b,0x00,0x10,0x04,0x0b,
+ 0x00,0x0b,0xff,0xf0,0x91,0x82,0xa5,0xf0,0x91,0x82,0xba,0x00,0x0b,0x00,0x53,0x04,
+ 0x0b,0x00,0x92,0x10,0xd1,0x08,0x10,0x04,0x0b,0x00,0x0b,0x09,0x10,0x04,0x0b,0x07,
+ 0x0b,0x00,0x0b,0x00,0xcf,0x86,0xd5,0x20,0x94,0x1c,0xd3,0x0c,0x92,0x08,0x11,0x04,
+ 0x0b,0x00,0x00,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,
+ 0x14,0x00,0x00,0x00,0x0d,0x00,0xd4,0x14,0x53,0x04,0x0d,0x00,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x0d,0x00,0x92,0x08,
+ 0x11,0x04,0x0d,0x00,0x00,0x00,0x00,0x00,0xd1,0x96,0xd0,0x5c,0xcf,0x86,0xd5,0x18,
+ 0x94,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x0d,0xe6,0x10,0x04,0x0d,0xe6,0x0d,0x00,
+ 0x0d,0x00,0x0d,0x00,0x0d,0x00,0xd4,0x26,0x53,0x04,0x0d,0x00,0x52,0x04,0x0d,0x00,
+ 0x51,0x04,0x0d,0x00,0x10,0x0d,0x0d,0xff,0xf0,0x91,0x84,0xb1,0xf0,0x91,0x84,0xa7,
+ 0x00,0x0d,0xff,0xf0,0x91,0x84,0xb2,0xf0,0x91,0x84,0xa7,0x00,0x93,0x18,0xd2,0x0c,
+ 0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x00,0x0d,0x09,0x91,0x08,0x10,0x04,0x0d,0x09,
+ 0x00,0x00,0x0d,0x00,0x0d,0x00,0xcf,0x86,0xd5,0x18,0x94,0x14,0x93,0x10,0x52,0x04,
+ 0x0d,0x00,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x10,0x00,
+ 0x54,0x04,0x10,0x00,0x93,0x18,0xd2,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,
+ 0x10,0x07,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd0,0x06,
+ 0xcf,0x06,0x0d,0x00,0xcf,0x86,0xd5,0x40,0xd4,0x2c,0xd3,0x10,0x92,0x0c,0x91,0x08,
+ 0x10,0x04,0x0d,0x09,0x0d,0x00,0x0d,0x00,0x0d,0x00,0xd2,0x10,0xd1,0x08,0x10,0x04,
+ 0x0d,0x00,0x11,0x00,0x10,0x04,0x11,0x07,0x11,0x00,0x91,0x08,0x10,0x04,0x11,0x00,
+ 0x10,0x00,0x00,0x00,0x53,0x04,0x0d,0x00,0x92,0x0c,0x51,0x04,0x0d,0x00,0x10,0x04,
+ 0x10,0x00,0x11,0x00,0x11,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,
+ 0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x93,0x10,0x52,0x04,0x10,0x00,
+ 0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd2,0xc8,0xd1,0x48,
+ 0xd0,0x42,0xcf,0x86,0xd5,0x18,0x54,0x04,0x10,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,
+ 0x10,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x54,0x04,0x10,0x00,
+ 0xd3,0x14,0x52,0x04,0x10,0x00,0xd1,0x08,0x10,0x04,0x10,0x00,0x10,0x09,0x10,0x04,
+ 0x10,0x07,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x12,0x00,
+ 0x00,0x00,0xcf,0x06,0x00,0x00,0xd0,0x52,0xcf,0x86,0xd5,0x3c,0xd4,0x28,0xd3,0x10,
+ 0x52,0x04,0x11,0x00,0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0xd2,0x0c,
+ 0x91,0x08,0x10,0x04,0x11,0x00,0x00,0x00,0x11,0x00,0x51,0x04,0x11,0x00,0x10,0x04,
+ 0x00,0x00,0x11,0x00,0x53,0x04,0x11,0x00,0x52,0x04,0x11,0x00,0x51,0x04,0x11,0x00,
+ 0x10,0x04,0x00,0x00,0x11,0x00,0x94,0x10,0x53,0x04,0x11,0x00,0x92,0x08,0x11,0x04,
+ 0x11,0x00,0x00,0x00,0x00,0x00,0x10,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0xd4,0x18,
+ 0x53,0x04,0x10,0x00,0x92,0x10,0xd1,0x08,0x10,0x04,0x10,0x00,0x10,0x07,0x10,0x04,
+ 0x10,0x09,0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x92,0x08,0x11,0x04,0x10,0x00,
+ 0x00,0x00,0x00,0x00,0xe1,0x27,0x01,0xd0,0x8a,0xcf,0x86,0xd5,0x44,0xd4,0x2c,0xd3,
+ 0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x11,0x00,0x10,0x00,0x10,0x00,0x91,0x08,0x10,
+ 0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x52,0x04,0x10,0x00,0xd1,0x08,0x10,0x04,0x10,
+ 0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x93,0x14,0x92,0x10,0xd1,0x08,0x10,
+ 0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0xd4,
+ 0x14,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x10,
+ 0x00,0x10,0x00,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x10,
+ 0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0xd2,0x0c,0x51,0x04,0x10,
+ 0x00,0x10,0x04,0x00,0x00,0x14,0x07,0x91,0x08,0x10,0x04,0x10,0x07,0x10,0x00,0x10,
+ 0x00,0xcf,0x86,0xd5,0x6a,0xd4,0x42,0xd3,0x14,0x52,0x04,0x10,0x00,0xd1,0x08,0x10,
+ 0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0xd2,0x19,0xd1,0x08,0x10,
+ 0x04,0x10,0x00,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0xff,0xf0,0x91,0x8d,0x87,0xf0,
+ 0x91,0x8c,0xbe,0x00,0x91,0x11,0x10,0x0d,0x10,0xff,0xf0,0x91,0x8d,0x87,0xf0,0x91,
+ 0x8d,0x97,0x00,0x10,0x09,0x00,0x00,0xd3,0x18,0xd2,0x0c,0x91,0x08,0x10,0x04,0x11,
+ 0x00,0x00,0x00,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x10,0x00,0x52,
+ 0x04,0x00,0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0xd4,0x1c,0xd3,
+ 0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x00,0x00,0x10,0xe6,0x52,0x04,0x10,0xe6,0x91,
+ 0x08,0x10,0x04,0x10,0xe6,0x00,0x00,0x00,0x00,0x93,0x10,0x52,0x04,0x10,0xe6,0x91,
+ 0x08,0x10,0x04,0x10,0xe6,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xe3,
+ 0x30,0x01,0xd2,0xb7,0xd1,0x48,0xd0,0x06,0xcf,0x06,0x12,0x00,0xcf,0x86,0x95,0x3c,
+ 0xd4,0x1c,0x93,0x18,0xd2,0x0c,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x09,0x12,0x00,
+ 0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x07,0x12,0x00,0x12,0x00,0x53,0x04,0x12,0x00,
+ 0xd2,0x0c,0x51,0x04,0x12,0x00,0x10,0x04,0x00,0x00,0x12,0x00,0xd1,0x08,0x10,0x04,
+ 0x00,0x00,0x12,0x00,0x10,0x04,0x14,0xe6,0x15,0x00,0x00,0x00,0xd0,0x45,0xcf,0x86,
+ 0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0xd2,0x15,0x51,0x04,
+ 0x10,0x00,0x10,0x04,0x10,0x00,0x10,0xff,0xf0,0x91,0x92,0xb9,0xf0,0x91,0x92,0xba,
+ 0x00,0xd1,0x11,0x10,0x0d,0x10,0xff,0xf0,0x91,0x92,0xb9,0xf0,0x91,0x92,0xb0,0x00,
+ 0x10,0x00,0x10,0x0d,0x10,0xff,0xf0,0x91,0x92,0xb9,0xf0,0x91,0x92,0xbd,0x00,0x10,
+ 0x00,0xcf,0x86,0x95,0x24,0xd4,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x10,0x00,0x10,
+ 0x04,0x10,0x09,0x10,0x07,0x10,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x92,0x08,0x11,
+ 0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,
+ 0x40,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0xd3,0x0c,0x52,0x04,0x10,
+ 0x00,0x11,0x04,0x10,0x00,0x00,0x00,0xd2,0x1e,0x51,0x04,0x10,0x00,0x10,0x0d,0x10,
+ 0xff,0xf0,0x91,0x96,0xb8,0xf0,0x91,0x96,0xaf,0x00,0x10,0xff,0xf0,0x91,0x96,0xb9,
+ 0xf0,0x91,0x96,0xaf,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x10,0x09,0xcf,
+ 0x86,0x95,0x2c,0xd4,0x1c,0xd3,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0x07,0x10,
+ 0x00,0x10,0x00,0x10,0x00,0x92,0x08,0x11,0x04,0x10,0x00,0x11,0x00,0x11,0x00,0x53,
+ 0x04,0x11,0x00,0x52,0x04,0x11,0x00,0x11,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0xd2,
+ 0xa0,0xd1,0x5c,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0x53,
+ 0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x10,
+ 0x09,0xcf,0x86,0xd5,0x24,0xd4,0x14,0x93,0x10,0x52,0x04,0x10,0x00,0x91,0x08,0x10,
+ 0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x92,0x08,0x11,
+ 0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x94,0x14,0x53,0x04,0x12,0x00,0x52,0x04,0x12,
+ 0x00,0x91,0x08,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd0,0x2a,0xcf,
+ 0x86,0x55,0x04,0x0d,0x00,0x54,0x04,0x0d,0x00,0xd3,0x10,0x52,0x04,0x0d,0x00,0x51,
+ 0x04,0x0d,0x00,0x10,0x04,0x0d,0x09,0x0d,0x07,0x92,0x0c,0x91,0x08,0x10,0x04,0x15,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x95,0x14,0x94,0x10,0x53,0x04,0x0d,
+ 0x00,0x92,0x08,0x11,0x04,0x0d,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,
+ 0x40,0xd0,0x3a,0xcf,0x86,0xd5,0x20,0x54,0x04,0x11,0x00,0x53,0x04,0x11,0x00,0xd2,
+ 0x0c,0x51,0x04,0x11,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0x91,0x08,0x10,0x04,0x00,
+ 0x00,0x11,0x00,0x11,0x00,0x94,0x14,0x53,0x04,0x11,0x00,0x92,0x0c,0x51,0x04,0x11,
+ 0x00,0x10,0x04,0x11,0x00,0x11,0x09,0x00,0x00,0x11,0x00,0xcf,0x06,0x00,0x00,0xcf,
+ 0x06,0x00,0x00,0xe4,0x59,0x01,0xd3,0xb2,0xd2,0x5c,0xd1,0x28,0xd0,0x22,0xcf,0x86,
+ 0x55,0x04,0x14,0x00,0x54,0x04,0x14,0x00,0x53,0x04,0x14,0x00,0x92,0x10,0xd1,0x08,
+ 0x10,0x04,0x14,0x00,0x14,0x09,0x10,0x04,0x14,0x07,0x14,0x00,0x00,0x00,0xcf,0x06,
+ 0x00,0x00,0xd0,0x0a,0xcf,0x86,0x15,0x04,0x00,0x00,0x10,0x00,0xcf,0x86,0x55,0x04,
+ 0x10,0x00,0x54,0x04,0x10,0x00,0xd3,0x10,0x92,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,
+ 0x10,0x00,0x00,0x00,0x00,0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,
+ 0x00,0x00,0x10,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x1a,0xcf,0x86,0x55,0x04,
+ 0x00,0x00,0x94,0x10,0x53,0x04,0x15,0x00,0x92,0x08,0x11,0x04,0x00,0x00,0x15,0x00,
+ 0x15,0x00,0x15,0x00,0xcf,0x86,0xd5,0x14,0x54,0x04,0x15,0x00,0x53,0x04,0x15,0x00,
+ 0x92,0x08,0x11,0x04,0x00,0x00,0x15,0x00,0x15,0x00,0x94,0x1c,0x93,0x18,0xd2,0x0c,
+ 0x91,0x08,0x10,0x04,0x15,0x09,0x15,0x00,0x15,0x00,0x91,0x08,0x10,0x04,0x15,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd2,0xa0,0xd1,0x3c,0xd0,0x1e,0xcf,0x86,
+ 0x55,0x04,0x13,0x00,0x54,0x04,0x13,0x00,0x93,0x10,0x52,0x04,0x13,0x00,0x91,0x08,
+ 0x10,0x04,0x13,0x09,0x13,0x00,0x13,0x00,0x13,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,
+ 0x93,0x10,0x52,0x04,0x13,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x13,0x09,
+ 0x00,0x00,0x13,0x00,0x13,0x00,0xd0,0x46,0xcf,0x86,0xd5,0x2c,0xd4,0x10,0x93,0x0c,
+ 0x52,0x04,0x13,0x00,0x11,0x04,0x15,0x00,0x13,0x00,0x13,0x00,0x53,0x04,0x13,0x00,
+ 0xd2,0x0c,0x91,0x08,0x10,0x04,0x13,0x00,0x13,0x09,0x13,0x00,0x91,0x08,0x10,0x04,
+ 0x13,0x00,0x14,0x00,0x13,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x13,0x00,
+ 0x10,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0x55,0x04,
+ 0x10,0x00,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,
+ 0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xe3,0xa9,0x01,0xd2,
+ 0xb0,0xd1,0x6c,0xd0,0x3e,0xcf,0x86,0xd5,0x18,0x94,0x14,0x53,0x04,0x12,0x00,0x92,
+ 0x0c,0x91,0x08,0x10,0x04,0x12,0x00,0x00,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x54,
+ 0x04,0x12,0x00,0xd3,0x10,0x52,0x04,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,
+ 0x00,0x00,0x00,0x52,0x04,0x12,0x00,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x12,
+ 0x09,0xcf,0x86,0xd5,0x14,0x94,0x10,0x93,0x0c,0x52,0x04,0x12,0x00,0x11,0x04,0x12,
+ 0x00,0x00,0x00,0x00,0x00,0x12,0x00,0x94,0x14,0x53,0x04,0x12,0x00,0x52,0x04,0x12,
+ 0x00,0x91,0x08,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0x12,0x00,0xd0,0x3e,0xcf,
+ 0x86,0xd5,0x14,0x54,0x04,0x12,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x00,0x00,0x12,
+ 0x00,0x12,0x00,0x12,0x00,0xd4,0x14,0x53,0x04,0x12,0x00,0x92,0x0c,0x91,0x08,0x10,
+ 0x04,0x00,0x00,0x12,0x00,0x12,0x00,0x12,0x00,0x93,0x10,0x52,0x04,0x12,0x00,0x51,
+ 0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1,
+ 0xa0,0xd0,0x52,0xcf,0x86,0xd5,0x24,0x94,0x20,0xd3,0x10,0x52,0x04,0x13,0x00,0x51,
+ 0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0x92,0x0c,0x51,0x04,0x13,0x00,0x10,
+ 0x04,0x00,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x54,0x04,0x13,0x00,0xd3,0x10,0x52,
+ 0x04,0x13,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0xd2,0x0c,0x51,
+ 0x04,0x00,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0x51,0x04,0x13,0x00,0x10,0x04,0x00,
+ 0x00,0x13,0x00,0xcf,0x86,0xd5,0x28,0xd4,0x18,0x93,0x14,0xd2,0x0c,0x51,0x04,0x13,
+ 0x00,0x10,0x04,0x13,0x07,0x13,0x00,0x11,0x04,0x13,0x09,0x13,0x00,0x00,0x00,0x53,
+ 0x04,0x13,0x00,0x92,0x08,0x11,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0x94,0x20,0xd3,
+ 0x10,0x52,0x04,0x14,0x00,0x51,0x04,0x14,0x00,0x10,0x04,0x00,0x00,0x14,0x00,0x92,
+ 0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x14,0x00,0x14,0x00,0x14,0x00,0xd0,
+ 0x52,0xcf,0x86,0xd5,0x3c,0xd4,0x14,0x53,0x04,0x14,0x00,0x52,0x04,0x14,0x00,0x51,
+ 0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x14,
+ 0x00,0x10,0x04,0x00,0x00,0x14,0x00,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x14,
+ 0x09,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x94,
+ 0x10,0x53,0x04,0x14,0x00,0x92,0x08,0x11,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0xcf,0x06,0x00,0x00,0xd2,0x2a,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf,
+ 0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x14,0x00,0x53,0x04,0x14,
+ 0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xd1,
+ 0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x15,
+ 0x00,0x54,0x04,0x15,0x00,0xd3,0x0c,0x92,0x08,0x11,0x04,0x15,0x00,0x00,0x00,0x00,
+ 0x00,0x52,0x04,0x00,0x00,0x51,0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x15,0x00,0xd0,
+ 0xca,0xcf,0x86,0xd5,0xc2,0xd4,0x54,0xd3,0x06,0xcf,0x06,0x09,0x00,0xd2,0x06,0xcf,
+ 0x06,0x09,0x00,0xd1,0x24,0xd0,0x06,0xcf,0x06,0x09,0x00,0xcf,0x86,0x55,0x04,0x09,
+ 0x00,0x94,0x14,0x53,0x04,0x09,0x00,0x52,0x04,0x09,0x00,0x51,0x04,0x09,0x00,0x10,
+ 0x04,0x09,0x00,0x10,0x00,0x10,0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x10,
+ 0x00,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x11,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd3,0x68,0xd2,0x46,0xd1,0x40,0xd0,
+ 0x06,0xcf,0x06,0x09,0x00,0xcf,0x86,0x55,0x04,0x09,0x00,0xd4,0x20,0xd3,0x10,0x92,
+ 0x0c,0x51,0x04,0x09,0x00,0x10,0x04,0x09,0x00,0x10,0x00,0x10,0x00,0x52,0x04,0x10,
+ 0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x93,0x10,0x52,0x04,0x09,
+ 0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x11,
+ 0x00,0xd1,0x1c,0xd0,0x06,0xcf,0x06,0x11,0x00,0xcf,0x86,0x95,0x10,0x94,0x0c,0x93,
+ 0x08,0x12,0x04,0x11,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,
+ 0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,0x4c,0xd4,0x06,0xcf,
+ 0x06,0x0b,0x00,0xd3,0x40,0xd2,0x3a,0xd1,0x34,0xd0,0x2e,0xcf,0x86,0x55,0x04,0x0b,
+ 0x00,0xd4,0x14,0x53,0x04,0x0b,0x00,0x52,0x04,0x0b,0x00,0x51,0x04,0x0b,0x00,0x10,
+ 0x04,0x0b,0x00,0x00,0x00,0x53,0x04,0x15,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x15,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,
- 0x86,0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,
- 0xa2,0xd4,0x9c,0xd3,0x74,0xd2,0x26,0xd1,0x20,0xd0,0x1a,0xcf,0x86,0x95,0x14,0x94,
- 0x10,0x93,0x0c,0x92,0x08,0x11,0x04,0x0c,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,
- 0x00,0x13,0x00,0xcf,0x06,0x13,0x00,0xcf,0x06,0x13,0x00,0xd1,0x48,0xd0,0x1e,0xcf,
- 0x86,0x95,0x18,0x54,0x04,0x13,0x00,0x53,0x04,0x13,0x00,0x52,0x04,0x13,0x00,0x51,
- 0x04,0x13,0x00,0x10,0x04,0x13,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x18,0x54,
- 0x04,0x00,0x00,0x93,0x10,0x92,0x0c,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00,
- 0x00,0x00,0x00,0x00,0x00,0x94,0x0c,0x93,0x08,0x12,0x04,0x00,0x00,0x15,0x00,0x00,
- 0x00,0x13,0x00,0xcf,0x06,0x13,0x00,0xd2,0x22,0xd1,0x06,0xcf,0x06,0x13,0x00,0xd0,
- 0x06,0xcf,0x06,0x13,0x00,0xcf,0x86,0x55,0x04,0x13,0x00,0x54,0x04,0x13,0x00,0x53,
- 0x04,0x13,0x00,0x12,0x04,0x13,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,
- 0x00,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x7e,0xd2,0x78,0xd1,0x34,0xd0,0x06,0xcf,
- 0x06,0x10,0x00,0xcf,0x86,0x55,0x04,0x10,0x00,0xd4,0x14,0x53,0x04,0x10,0x00,0x92,
- 0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x10,
- 0x00,0x52,0x04,0x10,0x00,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd0,
- 0x3e,0xcf,0x86,0xd5,0x2c,0xd4,0x14,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,
- 0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0xd2,0x08,0x11,
- 0x04,0x10,0x00,0x00,0x00,0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x01,0x10,0x00,0x94,
- 0x0c,0x93,0x08,0x12,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,
- 0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xe1,0x92,0x04,0xd0,0x08,0xcf,0x86,
- 0xcf,0x06,0x00,0x00,0xcf,0x86,0xe5,0x2f,0x04,0xe4,0x7f,0x02,0xe3,0xf4,0x01,0xd2,
- 0x26,0xd1,0x06,0xcf,0x06,0x05,0x00,0xd0,0x06,0xcf,0x06,0x05,0x00,0xcf,0x86,0x55,
- 0x04,0x05,0x00,0x54,0x04,0x05,0x00,0x93,0x0c,0x52,0x04,0x05,0x00,0x11,0x04,0x05,
- 0x00,0x00,0x00,0x00,0x00,0xd1,0xeb,0xd0,0x2a,0xcf,0x86,0x55,0x04,0x05,0x00,0x94,
- 0x20,0xd3,0x10,0x52,0x04,0x05,0x00,0x51,0x04,0x05,0x00,0x10,0x04,0x05,0x00,0x00,
- 0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x0a,0x00,0x05,0x00,0x05,0x00,0x05,
- 0x00,0xcf,0x86,0xd5,0x2a,0x54,0x04,0x05,0x00,0x53,0x04,0x05,0x00,0x52,0x04,0x05,
- 0x00,0x51,0x04,0x05,0x00,0x10,0x0d,0x05,0xff,0xf0,0x9d,0x85,0x97,0xf0,0x9d,0x85,
- 0xa5,0x00,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0x00,0xd4,0x75,0xd3,
- 0x61,0xd2,0x44,0xd1,0x22,0x10,0x11,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,
- 0xa5,0xf0,0x9d,0x85,0xae,0x00,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,
- 0xf0,0x9d,0x85,0xaf,0x00,0x10,0x11,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,
- 0xa5,0xf0,0x9d,0x85,0xb0,0x00,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,
- 0xf0,0x9d,0x85,0xb1,0x00,0xd1,0x15,0x10,0x11,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,
- 0x9d,0x85,0xa5,0xf0,0x9d,0x85,0xb2,0x00,0x05,0xd8,0x10,0x04,0x05,0xd8,0x05,0x01,
- 0xd2,0x08,0x11,0x04,0x05,0x01,0x05,0x00,0x91,0x08,0x10,0x04,0x05,0x00,0x05,0xe2,
- 0x05,0xd8,0xd3,0x10,0x92,0x0c,0x51,0x04,0x05,0xd8,0x10,0x04,0x05,0xd8,0x05,0x00,
- 0x05,0x00,0x92,0x0c,0x51,0x04,0x05,0x00,0x10,0x04,0x05,0x00,0x05,0xdc,0x05,0xdc,
+ 0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xd1,0x4c,0xd0,0x44,0xcf,
+ 0x86,0xd5,0x3c,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x06,0xcf,0x06,0x11,0x00,0xd2,
+ 0x2a,0xd1,0x24,0xd0,0x06,0xcf,0x06,0x11,0x00,0xcf,0x86,0x95,0x18,0x94,0x14,0x93,
+ 0x10,0x52,0x04,0x11,0x00,0x51,0x04,0x11,0x00,0x10,0x04,0x11,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,
+ 0x00,0xcf,0x86,0xcf,0x06,0x00,0x00,0xe0,0xd2,0x01,0xcf,0x86,0xd5,0x06,0xcf,0x06,
+ 0x00,0x00,0xe4,0x0b,0x01,0xd3,0x06,0xcf,0x06,0x0c,0x00,0xd2,0x84,0xd1,0x50,0xd0,
+ 0x1e,0xcf,0x86,0x55,0x04,0x0c,0x00,0x54,0x04,0x0c,0x00,0x53,0x04,0x0c,0x00,0x92,
+ 0x0c,0x91,0x08,0x10,0x04,0x0c,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,
+ 0x18,0x54,0x04,0x10,0x00,0x53,0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x51,0x04,0x10,
+ 0x00,0x10,0x04,0x10,0x00,0x00,0x00,0x94,0x14,0x53,0x04,0x10,0x00,0xd2,0x08,0x11,
+ 0x04,0x10,0x00,0x00,0x00,0x11,0x04,0x00,0x00,0x10,0x00,0x00,0x00,0xd0,0x06,0xcf,
+ 0x06,0x00,0x00,0xcf,0x86,0xd5,0x08,0x14,0x04,0x00,0x00,0x10,0x00,0xd4,0x10,0x53,
+ 0x04,0x10,0x00,0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x00,0x00,0x93,0x10,0x52,
+ 0x04,0x10,0x01,0x91,0x08,0x10,0x04,0x10,0x01,0x10,0x00,0x00,0x00,0x00,0x00,0xd1,
+ 0x6c,0xd0,0x1e,0xcf,0x86,0x55,0x04,0x10,0x00,0x54,0x04,0x10,0x00,0x93,0x10,0x52,
+ 0x04,0x10,0xe6,0x51,0x04,0x10,0xe6,0x10,0x04,0x10,0xe6,0x10,0x00,0x10,0x00,0xcf,
+ 0x86,0xd5,0x24,0xd4,0x10,0x93,0x0c,0x52,0x04,0x10,0x00,0x11,0x04,0x10,0x00,0x00,
+ 0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x92,0x0c,0x51,0x04,0x10,0x00,0x10,0x04,0x00,
+ 0x00,0x10,0x00,0x10,0x00,0xd4,0x14,0x93,0x10,0x92,0x0c,0x51,0x04,0x10,0x00,0x10,
+ 0x04,0x00,0x00,0x10,0x00,0x10,0x00,0x10,0x00,0x53,0x04,0x10,0x00,0x52,0x04,0x00,
+ 0x00,0x91,0x08,0x10,0x04,0x00,0x00,0x10,0x00,0x10,0x00,0xd0,0x0e,0xcf,0x86,0x95,
+ 0x08,0x14,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xd3,0x06,0xcf,
+ 0x06,0x00,0x00,0xd2,0x30,0xd1,0x0c,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x06,0x14,
+ 0x00,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,0x14,0x00,0x53,0x04,0x14,0x00,0x92,
+ 0x0c,0x51,0x04,0x14,0x00,0x10,0x04,0x14,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,
+ 0x06,0x00,0x00,0xd1,0x4c,0xd0,0x06,0xcf,0x06,0x0d,0x00,0xcf,0x86,0xd5,0x2c,0x94,
+ 0x28,0xd3,0x10,0x52,0x04,0x0d,0x00,0x91,0x08,0x10,0x04,0x0d,0x00,0x15,0x00,0x15,
+ 0x00,0xd2,0x0c,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00,0x00,0x51,0x04,0x00,
+ 0x00,0x10,0x04,0x00,0x00,0x15,0x00,0x0d,0x00,0x54,0x04,0x0d,0x00,0x53,0x04,0x0d,
+ 0x00,0x52,0x04,0x0d,0x00,0x51,0x04,0x0d,0x00,0x10,0x04,0x0d,0x00,0x15,0x00,0xd0,
+ 0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x53,0x04,0x15,0x00,0x52,0x04,0x00,0x00,0x51,
+ 0x04,0x00,0x00,0x10,0x04,0x00,0x00,0x0d,0x00,0x0d,0x00,0x00,0x00,0xcf,0x86,0x55,
+ 0x04,0x00,0x00,0x94,0x14,0x93,0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x12,0x00,0x13,
+ 0x00,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xcf,0x06,0x12,0x00,0xe2,
+ 0xc6,0x01,0xd1,0x8e,0xd0,0x86,0xcf,0x86,0xd5,0x48,0xd4,0x06,0xcf,0x06,0x12,0x00,
+ 0xd3,0x06,0xcf,0x06,0x12,0x00,0xd2,0x06,0xcf,0x06,0x12,0x00,0xd1,0x06,0xcf,0x06,
+ 0x12,0x00,0xd0,0x06,0xcf,0x06,0x12,0x00,0xcf,0x86,0x55,0x04,0x12,0x00,0xd4,0x14,
+ 0x53,0x04,0x12,0x00,0x52,0x04,0x12,0x00,0x91,0x08,0x10,0x04,0x12,0x00,0x14,0x00,
+ 0x14,0x00,0x93,0x0c,0x92,0x08,0x11,0x04,0x14,0x00,0x15,0x00,0x15,0x00,0x00,0x00,
+ 0xd4,0x36,0xd3,0x06,0xcf,0x06,0x12,0x00,0xd2,0x2a,0xd1,0x06,0xcf,0x06,0x12,0x00,
+ 0xd0,0x06,0xcf,0x06,0x12,0x00,0xcf,0x86,0x55,0x04,0x12,0x00,0x54,0x04,0x12,0x00,
+ 0x93,0x10,0x92,0x0c,0x51,0x04,0x12,0x00,0x10,0x04,0x12,0x00,0x00,0x00,0x00,0x00,
+ 0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x86,0xcf,0x06,0x00,0x00,
+ 0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,0xa2,0xd4,0x9c,0xd3,0x74,
+ 0xd2,0x26,0xd1,0x20,0xd0,0x1a,0xcf,0x86,0x95,0x14,0x94,0x10,0x93,0x0c,0x92,0x08,
+ 0x11,0x04,0x0c,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0x13,0x00,0xcf,0x06,
+ 0x13,0x00,0xcf,0x06,0x13,0x00,0xd1,0x48,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x54,0x04,
+ 0x13,0x00,0x53,0x04,0x13,0x00,0x52,0x04,0x13,0x00,0x51,0x04,0x13,0x00,0x10,0x04,
+ 0x13,0x00,0x00,0x00,0x00,0x00,0xcf,0x86,0xd5,0x18,0x54,0x04,0x00,0x00,0x93,0x10,
+ 0x92,0x0c,0x51,0x04,0x15,0x00,0x10,0x04,0x15,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
+ 0x94,0x0c,0x93,0x08,0x12,0x04,0x00,0x00,0x15,0x00,0x00,0x00,0x13,0x00,0xcf,0x06,
+ 0x13,0x00,0xd2,0x22,0xd1,0x06,0xcf,0x06,0x13,0x00,0xd0,0x06,0xcf,0x06,0x13,0x00,
+ 0xcf,0x86,0x55,0x04,0x13,0x00,0x54,0x04,0x13,0x00,0x53,0x04,0x13,0x00,0x12,0x04,
+ 0x13,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,
+ 0x00,0x00,0xd3,0x7f,0xd2,0x79,0xd1,0x34,0xd0,0x06,0xcf,0x06,0x10,0x00,0xcf,0x86,
+ 0x55,0x04,0x10,0x00,0xd4,0x14,0x53,0x04,0x10,0x00,0x92,0x0c,0x51,0x04,0x10,0x00,
+ 0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0x52,0x04,0x10,0x00,
+ 0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,0x00,0x00,0xd0,0x3f,0xcf,0x86,0xd5,0x2c,
+ 0xd4,0x14,0x53,0x04,0x10,0x00,0x92,0x0c,0x91,0x08,0x10,0x04,0x10,0x00,0x00,0x00,
+ 0x00,0x00,0x00,0x00,0x53,0x04,0x10,0x00,0xd2,0x08,0x11,0x04,0x10,0x00,0x00,0x00,
+ 0x51,0x04,0x10,0x00,0x10,0x04,0x10,0x01,0x10,0x00,0x94,0x0d,0x93,0x09,0x12,0x05,
+ 0x10,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,
+ 0x00,0xcf,0x06,0x00,0x00,0xe1,0x96,0x04,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,
+ 0xcf,0x86,0xe5,0x33,0x04,0xe4,0x83,0x02,0xe3,0xf8,0x01,0xd2,0x26,0xd1,0x06,0xcf,
+ 0x06,0x05,0x00,0xd0,0x06,0xcf,0x06,0x05,0x00,0xcf,0x86,0x55,0x04,0x05,0x00,0x54,
+ 0x04,0x05,0x00,0x93,0x0c,0x52,0x04,0x05,0x00,0x11,0x04,0x05,0x00,0x00,0x00,0x00,
+ 0x00,0xd1,0xef,0xd0,0x2a,0xcf,0x86,0x55,0x04,0x05,0x00,0x94,0x20,0xd3,0x10,0x52,
+ 0x04,0x05,0x00,0x51,0x04,0x05,0x00,0x10,0x04,0x05,0x00,0x00,0x00,0x92,0x0c,0x91,
+ 0x08,0x10,0x04,0x00,0x00,0x0a,0x00,0x05,0x00,0x05,0x00,0x05,0x00,0xcf,0x86,0xd5,
+ 0x2a,0x54,0x04,0x05,0x00,0x53,0x04,0x05,0x00,0x52,0x04,0x05,0x00,0x51,0x04,0x05,
+ 0x00,0x10,0x0d,0x05,0xff,0xf0,0x9d,0x85,0x97,0xf0,0x9d,0x85,0xa5,0x00,0x05,0xff,
+ 0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0x00,0xd4,0x75,0xd3,0x61,0xd2,0x44,0xd1,
+ 0x22,0x10,0x11,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0xf0,0x9d,0x85,
+ 0xae,0x00,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0xf0,0x9d,0x85,0xaf,
+ 0x00,0x10,0x11,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0xf0,0x9d,0x85,
+ 0xb0,0x00,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0xf0,0x9d,0x85,0xb1,
+ 0x00,0xd1,0x15,0x10,0x11,0x05,0xff,0xf0,0x9d,0x85,0x98,0xf0,0x9d,0x85,0xa5,0xf0,
+ 0x9d,0x85,0xb2,0x00,0x05,0xd8,0x10,0x04,0x05,0xd8,0x05,0x01,0xd2,0x08,0x11,0x04,
+ 0x05,0x01,0x05,0x00,0x91,0x08,0x10,0x04,0x05,0x00,0x05,0xe2,0x05,0xd8,0xd3,0x12,
+ 0x92,0x0d,0x51,0x04,0x05,0xd8,0x10,0x04,0x05,0xd8,0x05,0xff,0x00,0x05,0xff,0x00,
+ 0x92,0x0e,0x51,0x05,0x05,0xff,0x00,0x10,0x05,0x05,0xff,0x00,0x05,0xdc,0x05,0xdc,
0xd0,0x97,0xcf,0x86,0xd5,0x28,0x94,0x24,0xd3,0x18,0xd2,0x0c,0x51,0x04,0x05,0xdc,
0x10,0x04,0x05,0xdc,0x05,0x00,0x91,0x08,0x10,0x04,0x05,0x00,0x05,0xe6,0x05,0xe6,
0x92,0x08,0x11,0x04,0x05,0xe6,0x05,0xdc,0x05,0x00,0x05,0x00,0xd4,0x14,0x53,0x04,
@@ -4080,20 +4090,21 @@ static const unsigned char utf8data[64080] = {
0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,
0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,
0x04,0x00,0x00,0x53,0x04,0x00,0x00,0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,
- 0x00,0xd4,0xc8,0xd3,0x70,0xd2,0x68,0xd1,0x60,0xd0,0x58,0xcf,0x86,0xd5,0x50,0xd4,
- 0x4a,0xd3,0x44,0xd2,0x2a,0xd1,0x24,0xd0,0x1e,0xcf,0x86,0x95,0x18,0x94,0x14,0x93,
- 0x10,0x92,0x0c,0x91,0x08,0x10,0x04,0x00,0x00,0x05,0x00,0x00,0x00,0x00,0x00,0x00,
- 0x00,0x00,0x00,0x05,0x00,0xcf,0x06,0x05,0x00,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,
- 0x06,0x07,0x00,0xd0,0x06,0xcf,0x06,0x07,0x00,0xcf,0x86,0x55,0x04,0x07,0x00,0x14,
- 0x04,0x07,0x00,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,0x00,0xcf,0x06,0x00,
- 0x00,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xcf,
- 0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd1,0x08,0xcf,0x86,0xcf,
- 0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,0x06,0xcf,
- 0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,0xd2,
- 0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,0x00,
- 0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00,0x00,0x53,0x04,0x00,0x00,0x52,
- 0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,0x00,0xcf,0x86,0xcf,0x06,0x02,0x00,0x81,
- 0x80,0xcf,0x86,0x85,0x84,0xcf,0x86,0xcf,0x06,0x02,0x00,0x00,0x00,0x00,0x00,0x00
+ 0x00,0xd4,0xd9,0xd3,0x81,0xd2,0x79,0xd1,0x71,0xd0,0x69,0xcf,0x86,0xd5,0x60,0xd4,
+ 0x59,0xd3,0x52,0xd2,0x33,0xd1,0x2c,0xd0,0x25,0xcf,0x86,0x95,0x1e,0x94,0x19,0x93,
+ 0x14,0x92,0x0f,0x91,0x0a,0x10,0x05,0x00,0xff,0x00,0x05,0xff,0x00,0x00,0xff,0x00,
+ 0x00,0xff,0x00,0x00,0xff,0x00,0x00,0xff,0x00,0x05,0xff,0x00,0xcf,0x06,0x05,0xff,
+ 0x00,0xcf,0x06,0x00,0xff,0x00,0xd1,0x07,0xcf,0x06,0x07,0xff,0x00,0xd0,0x07,0xcf,
+ 0x06,0x07,0xff,0x00,0xcf,0x86,0x55,0x05,0x07,0xff,0x00,0x14,0x05,0x07,0xff,0x00,
+ 0x00,0xff,0x00,0xcf,0x06,0x00,0xff,0x00,0xcf,0x06,0x00,0xff,0x00,0xcf,0x06,0x00,
+ 0xff,0x00,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,
+ 0xcf,0x06,0x00,0x00,0xd2,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xd1,0x08,0xcf,0x86,
+ 0xcf,0x06,0x00,0x00,0xd0,0x08,0xcf,0x86,0xcf,0x06,0x00,0x00,0xcf,0x86,0xd5,0x06,
+ 0xcf,0x06,0x00,0x00,0xd4,0x06,0xcf,0x06,0x00,0x00,0xd3,0x06,0xcf,0x06,0x00,0x00,
+ 0xd2,0x06,0xcf,0x06,0x00,0x00,0xd1,0x06,0xcf,0x06,0x00,0x00,0xd0,0x06,0xcf,0x06,
+ 0x00,0x00,0xcf,0x86,0x55,0x04,0x00,0x00,0x54,0x04,0x00,0x00,0x53,0x04,0x00,0x00,
+ 0x52,0x04,0x00,0x00,0x11,0x04,0x00,0x00,0x02,0x00,0xcf,0x86,0xcf,0x06,0x02,0x00,
+ 0x81,0x80,0xcf,0x86,0x85,0x84,0xcf,0x86,0xcf,0x06,0x02,0x00,0x00,0x00,0x00,0x00
};
const struct utf8data_table utf8_data_table = {
diff --git a/fs/xfs/libxfs/xfs_bmap.c b/fs/xfs/libxfs/xfs_bmap.c
index 9052839305e2..5255f93bae31 100644
--- a/fs/xfs/libxfs/xfs_bmap.c
+++ b/fs/xfs/libxfs/xfs_bmap.c
@@ -2620,8 +2620,7 @@ xfs_bmap_add_extent_hole_delay(
*/
if ((state & BMAP_LEFT_VALID) && (state & BMAP_LEFT_DELAY) &&
left.br_startoff + left.br_blockcount == new->br_startoff &&
- left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
- xfs_bmap_same_rtgroup(ip, whichfork, &left, new))
+ left.br_blockcount + new->br_blockcount <= XFS_MAX_BMBT_EXTLEN)
state |= BMAP_LEFT_CONTIG;
if ((state & BMAP_RIGHT_VALID) && (state & BMAP_RIGHT_DELAY) &&
@@ -2629,8 +2628,7 @@ xfs_bmap_add_extent_hole_delay(
new->br_blockcount + right.br_blockcount <= XFS_MAX_BMBT_EXTLEN &&
(!(state & BMAP_LEFT_CONTIG) ||
(left.br_blockcount + new->br_blockcount +
- right.br_blockcount <= XFS_MAX_BMBT_EXTLEN)) &&
- xfs_bmap_same_rtgroup(ip, whichfork, new, &right))
+ right.br_blockcount <= XFS_MAX_BMBT_EXTLEN)))
state |= BMAP_RIGHT_CONTIG;
/*
diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 2b5fc5fd1643..68ee1c299c25 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -3557,14 +3557,31 @@ xfs_btree_insrec(
xfs_btree_log_block(cur, bp, XFS_BB_NUMRECS);
/*
- * If we just inserted into a new tree block, we have to
- * recalculate nkey here because nkey is out of date.
+ * Update btree keys to reflect the newly added record or keyptr.
+ * There are three cases here to be aware of. Normally, all we have to
+ * do is walk towards the root, updating keys as necessary.
*
- * Otherwise we're just updating an existing block (having shoved
- * some records into the new tree block), so use the regular key
- * update mechanism.
+ * If the caller had us target a full block for the insertion, we dealt
+ * with that by calling the _make_block_unfull function. If the
+ * "make unfull" function splits the block, it'll hand us back the key
+ * and pointer of the new block. We haven't yet added the new block to
+ * the next level up, so if we decide to add the new record to the new
+ * block (bp->b_bn != old_bn), we have to update the caller's pointer
+ * so that the caller adds the new block with the correct key.
+ *
+ * However, there is a third possibility-- if the selected block is the
+ * root block of an inode-rooted btree and cannot be expanded further,
+ * the "make unfull" function moves the root block contents to a new
+ * block and updates the root block to point to the new block. In this
+ * case, no block pointer is passed back because the block has already
+ * been added to the btree. In this case, we need to use the regular
+ * key update function, just like the first case. This is critical for
+ * overlapping btrees, because the high key must be updated to reflect
+ * the entire tree, not just the subtree accessible through the first
+ * child of the root (which is now two levels down from the root).
*/
- if (bp && xfs_buf_daddr(bp) != old_bn) {
+ if (!xfs_btree_ptr_is_null(cur, &nptr) &&
+ bp && xfs_buf_daddr(bp) != old_bn) {
xfs_btree_get_keys(cur, block, lkey);
} else if (xfs_btree_needs_key_update(cur, optr)) {
error = xfs_btree_update_keys(cur, level);
@@ -5144,7 +5161,7 @@ xfs_btree_count_blocks_helper(
int level,
void *data)
{
- xfs_extlen_t *blocks = data;
+ xfs_filblks_t *blocks = data;
(*blocks)++;
return 0;
@@ -5154,7 +5171,7 @@ xfs_btree_count_blocks_helper(
int
xfs_btree_count_blocks(
struct xfs_btree_cur *cur,
- xfs_extlen_t *blocks)
+ xfs_filblks_t *blocks)
{
*blocks = 0;
return xfs_btree_visit_blocks(cur, xfs_btree_count_blocks_helper,
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index 3b739459ebb0..c5bff273cae2 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -484,7 +484,7 @@ typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level,
int xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
xfs_btree_visit_blocks_fn fn, unsigned int flags, void *data);
-int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_extlen_t *blocks);
+int xfs_btree_count_blocks(struct xfs_btree_cur *cur, xfs_filblks_t *blocks);
union xfs_btree_rec *xfs_btree_rec_addr(struct xfs_btree_cur *cur, int n,
struct xfs_btree_block *block);
diff --git a/fs/xfs/libxfs/xfs_ialloc.c b/fs/xfs/libxfs/xfs_ialloc.c
index 8b84e2cf711b..f3a840a425f5 100644
--- a/fs/xfs/libxfs/xfs_ialloc.c
+++ b/fs/xfs/libxfs/xfs_ialloc.c
@@ -853,7 +853,8 @@ sparse_alloc:
* the end of the AG.
*/
args.min_agbno = args.mp->m_sb.sb_inoalignmt;
- args.max_agbno = round_down(args.mp->m_sb.sb_agblocks,
+ args.max_agbno = round_down(xfs_ag_block_count(args.mp,
+ pag_agno(pag)),
args.mp->m_sb.sb_inoalignmt) -
igeo->ialloc_blks;
@@ -2349,9 +2350,9 @@ xfs_difree(
return -EINVAL;
}
agbno = XFS_AGINO_TO_AGBNO(mp, agino);
- if (agbno >= mp->m_sb.sb_agblocks) {
- xfs_warn(mp, "%s: agbno >= mp->m_sb.sb_agblocks (%d >= %d).",
- __func__, agbno, mp->m_sb.sb_agblocks);
+ if (agbno >= xfs_ag_block_count(mp, pag_agno(pag))) {
+ xfs_warn(mp, "%s: agbno >= xfs_ag_block_count (%d >= %d).",
+ __func__, agbno, xfs_ag_block_count(mp, pag_agno(pag)));
ASSERT(0);
return -EINVAL;
}
@@ -2474,7 +2475,7 @@ xfs_imap(
*/
agino = XFS_INO_TO_AGINO(mp, ino);
agbno = XFS_AGINO_TO_AGBNO(mp, agino);
- if (agbno >= mp->m_sb.sb_agblocks ||
+ if (agbno >= xfs_ag_block_count(mp, pag_agno(pag)) ||
ino != xfs_agino_to_ino(pag, agino)) {
error = -EINVAL;
#ifdef DEBUG
@@ -2484,11 +2485,12 @@ xfs_imap(
*/
if (flags & XFS_IGET_UNTRUSTED)
return error;
- if (agbno >= mp->m_sb.sb_agblocks) {
+ if (agbno >= xfs_ag_block_count(mp, pag_agno(pag))) {
xfs_alert(mp,
"%s: agbno (0x%llx) >= mp->m_sb.sb_agblocks (0x%lx)",
__func__, (unsigned long long)agbno,
- (unsigned long)mp->m_sb.sb_agblocks);
+ (unsigned long)xfs_ag_block_count(mp,
+ pag_agno(pag)));
}
if (ino != xfs_agino_to_ino(pag, agino)) {
xfs_alert(mp,
diff --git a/fs/xfs/libxfs/xfs_ialloc_btree.c b/fs/xfs/libxfs/xfs_ialloc_btree.c
index 9b34896dd1a3..6f270d8f4270 100644
--- a/fs/xfs/libxfs/xfs_ialloc_btree.c
+++ b/fs/xfs/libxfs/xfs_ialloc_btree.c
@@ -744,6 +744,7 @@ xfs_finobt_count_blocks(
{
struct xfs_buf *agbp = NULL;
struct xfs_btree_cur *cur;
+ xfs_filblks_t blocks;
int error;
error = xfs_ialloc_read_agi(pag, tp, 0, &agbp);
@@ -751,9 +752,10 @@ xfs_finobt_count_blocks(
return error;
cur = xfs_finobt_init_cursor(pag, tp, agbp);
- error = xfs_btree_count_blocks(cur, tree_blocks);
+ error = xfs_btree_count_blocks(cur, &blocks);
xfs_btree_del_cursor(cur, error);
xfs_trans_brelse(tp, agbp);
+ *tree_blocks = blocks;
return error;
}
diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c
index e74bb059f24f..4f3bfc884aff 100644
--- a/fs/xfs/libxfs/xfs_rtgroup.c
+++ b/fs/xfs/libxfs/xfs_rtgroup.c
@@ -496,7 +496,7 @@ xfs_rtginode_create(
error = xfs_metadir_create(&upd, S_IFREG);
if (error)
- return error;
+ goto out_cancel;
xfs_rtginode_lockdep_setup(upd.ip, rtg_rgno(rtg), type);
diff --git a/fs/xfs/libxfs/xfs_sb.c b/fs/xfs/libxfs/xfs_sb.c
index e81b240b7158..3b5623611eba 100644
--- a/fs/xfs/libxfs/xfs_sb.c
+++ b/fs/xfs/libxfs/xfs_sb.c
@@ -326,13 +326,6 @@ xfs_validate_sb_write(
* the kernel cannot support since we checked for unsupported bits in
* the read verifier, which means that memory is corrupt.
*/
- if (xfs_sb_has_compat_feature(sbp, XFS_SB_FEAT_COMPAT_UNKNOWN)) {
- xfs_warn(mp,
-"Corruption detected in superblock compatible features (0x%x)!",
- (sbp->sb_features_compat & XFS_SB_FEAT_COMPAT_UNKNOWN));
- return -EFSCORRUPTED;
- }
-
if (!xfs_is_readonly(mp) &&
xfs_sb_has_ro_compat_feature(sbp, XFS_SB_FEAT_RO_COMPAT_UNKNOWN)) {
xfs_alert(mp,
@@ -501,12 +494,13 @@ xfs_validate_sb_common(
return -EINVAL;
}
- if (!sbp->sb_spino_align ||
- sbp->sb_spino_align > sbp->sb_inoalignmt ||
- (sbp->sb_inoalignmt % sbp->sb_spino_align) != 0) {
+ if (sbp->sb_spino_align &&
+ (sbp->sb_spino_align > sbp->sb_inoalignmt ||
+ (sbp->sb_inoalignmt % sbp->sb_spino_align) != 0)) {
xfs_warn(mp,
- "Sparse inode alignment (%u) is invalid.",
- sbp->sb_spino_align);
+"Sparse inode alignment (%u) is invalid, must be integer factor of (%u).",
+ sbp->sb_spino_align,
+ sbp->sb_inoalignmt);
return -EINVAL;
}
} else if (sbp->sb_spino_align) {
diff --git a/fs/xfs/libxfs/xfs_symlink_remote.c b/fs/xfs/libxfs/xfs_symlink_remote.c
index f228127a88ff..fb47a76ead18 100644
--- a/fs/xfs/libxfs/xfs_symlink_remote.c
+++ b/fs/xfs/libxfs/xfs_symlink_remote.c
@@ -92,8 +92,10 @@ xfs_symlink_verify(
struct xfs_mount *mp = bp->b_mount;
struct xfs_dsymlink_hdr *dsl = bp->b_addr;
+ /* no verification of non-crc buffers */
if (!xfs_has_crc(mp))
- return __this_address;
+ return NULL;
+
if (!xfs_verify_magic(bp, dsl->sl_magic))
return __this_address;
if (!uuid_equal(&dsl->sl_uuid, &mp->m_sb.sb_meta_uuid))
diff --git a/fs/xfs/scrub/agheader.c b/fs/xfs/scrub/agheader.c
index 61f80a6410c7..9f8c312dfd3c 100644
--- a/fs/xfs/scrub/agheader.c
+++ b/fs/xfs/scrub/agheader.c
@@ -60,6 +60,32 @@ xchk_superblock_xref(
}
/*
+ * Calculate the ondisk superblock size in bytes given the feature set of the
+ * mounted filesystem (aka the primary sb). This is subtlely different from
+ * the logic in xfs_repair, which computes the size of a secondary sb given the
+ * featureset listed in the secondary sb.
+ */
+STATIC size_t
+xchk_superblock_ondisk_size(
+ struct xfs_mount *mp)
+{
+ if (xfs_has_metadir(mp))
+ return offsetofend(struct xfs_dsb, sb_pad);
+ if (xfs_has_metauuid(mp))
+ return offsetofend(struct xfs_dsb, sb_meta_uuid);
+ if (xfs_has_crc(mp))
+ return offsetofend(struct xfs_dsb, sb_lsn);
+ if (xfs_sb_version_hasmorebits(&mp->m_sb))
+ return offsetofend(struct xfs_dsb, sb_bad_features2);
+ if (xfs_has_logv2(mp))
+ return offsetofend(struct xfs_dsb, sb_logsunit);
+ if (xfs_has_sector(mp))
+ return offsetofend(struct xfs_dsb, sb_logsectsize);
+ /* only support dirv2 or more recent */
+ return offsetofend(struct xfs_dsb, sb_dirblklog);
+}
+
+/*
* Scrub the filesystem superblock.
*
* Note: We do /not/ attempt to check AG 0's superblock. Mount is
@@ -75,6 +101,7 @@ xchk_superblock(
struct xfs_buf *bp;
struct xfs_dsb *sb;
struct xfs_perag *pag;
+ size_t sblen;
xfs_agnumber_t agno;
uint32_t v2_ok;
__be32 features_mask;
@@ -145,8 +172,11 @@ xchk_superblock(
xchk_block_set_preen(sc, bp);
if (xfs_has_metadir(sc->mp)) {
- if (sb->sb_metadirino != cpu_to_be64(mp->m_sb.sb_metadirino))
- xchk_block_set_preen(sc, bp);
+ if (sb->sb_rbmino != cpu_to_be64(0))
+ xchk_block_set_corrupt(sc, bp);
+
+ if (sb->sb_rsumino != cpu_to_be64(0))
+ xchk_block_set_corrupt(sc, bp);
} else {
if (sb->sb_rbmino != cpu_to_be64(mp->m_sb.sb_rbmino))
xchk_block_set_preen(sc, bp);
@@ -229,7 +259,13 @@ xchk_superblock(
* sb_icount, sb_ifree, sb_fdblocks, sb_frexents
*/
- if (!xfs_has_metadir(mp)) {
+ if (xfs_has_metadir(mp)) {
+ if (sb->sb_uquotino != cpu_to_be64(0))
+ xchk_block_set_corrupt(sc, bp);
+
+ if (sb->sb_gquotino != cpu_to_be64(0))
+ xchk_block_set_preen(sc, bp);
+ } else {
if (sb->sb_uquotino != cpu_to_be64(mp->m_sb.sb_uquotino))
xchk_block_set_preen(sc, bp);
@@ -281,15 +317,8 @@ xchk_superblock(
if (!!(sb->sb_features2 & cpu_to_be32(~v2_ok)))
xchk_block_set_corrupt(sc, bp);
- if (xfs_has_metadir(mp)) {
- if (sb->sb_rgblklog != mp->m_sb.sb_rgblklog)
- xchk_block_set_corrupt(sc, bp);
- if (memchr_inv(sb->sb_pad, 0, sizeof(sb->sb_pad)))
- xchk_block_set_preen(sc, bp);
- } else {
- if (sb->sb_features2 != sb->sb_bad_features2)
- xchk_block_set_preen(sc, bp);
- }
+ if (sb->sb_features2 != sb->sb_bad_features2)
+ xchk_block_set_preen(sc, bp);
}
/* Check sb_features2 flags that are set at mkfs time. */
@@ -351,7 +380,10 @@ xchk_superblock(
if (sb->sb_spino_align != cpu_to_be32(mp->m_sb.sb_spino_align))
xchk_block_set_corrupt(sc, bp);
- if (!xfs_has_metadir(mp)) {
+ if (xfs_has_metadir(mp)) {
+ if (sb->sb_pquotino != cpu_to_be64(0))
+ xchk_block_set_corrupt(sc, bp);
+ } else {
if (sb->sb_pquotino != cpu_to_be64(mp->m_sb.sb_pquotino))
xchk_block_set_preen(sc, bp);
}
@@ -366,16 +398,25 @@ xchk_superblock(
}
if (xfs_has_metadir(mp)) {
+ if (sb->sb_metadirino != cpu_to_be64(mp->m_sb.sb_metadirino))
+ xchk_block_set_preen(sc, bp);
+
if (sb->sb_rgcount != cpu_to_be32(mp->m_sb.sb_rgcount))
xchk_block_set_corrupt(sc, bp);
if (sb->sb_rgextents != cpu_to_be32(mp->m_sb.sb_rgextents))
xchk_block_set_corrupt(sc, bp);
+
+ if (sb->sb_rgblklog != mp->m_sb.sb_rgblklog)
+ xchk_block_set_corrupt(sc, bp);
+
+ if (memchr_inv(sb->sb_pad, 0, sizeof(sb->sb_pad)))
+ xchk_block_set_corrupt(sc, bp);
}
/* Everything else must be zero. */
- if (memchr_inv(sb + 1, 0,
- BBTOB(bp->b_length) - sizeof(struct xfs_dsb)))
+ sblen = xchk_superblock_ondisk_size(mp);
+ if (memchr_inv((char *)sb + sblen, 0, BBTOB(bp->b_length) - sblen))
xchk_block_set_corrupt(sc, bp);
xchk_superblock_xref(sc, bp);
@@ -458,7 +499,7 @@ xchk_agf_xref_btreeblks(
{
struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
struct xfs_mount *mp = sc->mp;
- xfs_agblock_t blocks;
+ xfs_filblks_t blocks;
xfs_agblock_t btreeblks;
int error;
@@ -507,7 +548,7 @@ xchk_agf_xref_refcblks(
struct xfs_scrub *sc)
{
struct xfs_agf *agf = sc->sa.agf_bp->b_addr;
- xfs_agblock_t blocks;
+ xfs_filblks_t blocks;
int error;
if (!sc->sa.refc_cur)
@@ -840,7 +881,7 @@ xchk_agi_xref_fiblocks(
struct xfs_scrub *sc)
{
struct xfs_agi *agi = sc->sa.agi_bp->b_addr;
- xfs_agblock_t blocks;
+ xfs_filblks_t blocks;
int error = 0;
if (!xfs_has_inobtcounts(sc->mp))
diff --git a/fs/xfs/scrub/agheader_repair.c b/fs/xfs/scrub/agheader_repair.c
index 0fad0baaba2f..b45d2b32051a 100644
--- a/fs/xfs/scrub/agheader_repair.c
+++ b/fs/xfs/scrub/agheader_repair.c
@@ -256,7 +256,7 @@ xrep_agf_calc_from_btrees(
struct xfs_agf *agf = agf_bp->b_addr;
struct xfs_mount *mp = sc->mp;
xfs_agblock_t btreeblks;
- xfs_agblock_t blocks;
+ xfs_filblks_t blocks;
int error;
/* Update the AGF counters from the bnobt. */
@@ -946,7 +946,7 @@ xrep_agi_calc_from_btrees(
if (error)
goto err;
if (xfs_has_inobtcounts(mp)) {
- xfs_agblock_t blocks;
+ xfs_filblks_t blocks;
error = xfs_btree_count_blocks(cur, &blocks);
if (error)
@@ -959,7 +959,7 @@ xrep_agi_calc_from_btrees(
agi->agi_freecount = cpu_to_be32(freecount);
if (xfs_has_finobt(mp) && xfs_has_inobtcounts(mp)) {
- xfs_agblock_t blocks;
+ xfs_filblks_t blocks;
cur = xfs_finobt_init_cursor(sc->sa.pag, sc->tp, agi_bp);
error = xfs_btree_count_blocks(cur, &blocks);
diff --git a/fs/xfs/scrub/fscounters.c b/fs/xfs/scrub/fscounters.c
index 4a50f8e00040..ca23cf4db6c5 100644
--- a/fs/xfs/scrub/fscounters.c
+++ b/fs/xfs/scrub/fscounters.c
@@ -261,7 +261,7 @@ xchk_fscount_btreeblks(
struct xchk_fscounters *fsc,
xfs_agnumber_t agno)
{
- xfs_extlen_t blocks;
+ xfs_filblks_t blocks;
int error;
error = xchk_ag_init_existing(sc, agno, &sc->sa);
diff --git a/fs/xfs/scrub/health.c b/fs/xfs/scrub/health.c
index ce86bdad37fa..ccc6ca5934ca 100644
--- a/fs/xfs/scrub/health.c
+++ b/fs/xfs/scrub/health.c
@@ -71,7 +71,8 @@
/* Map our scrub type to a sick mask and a set of health update functions. */
enum xchk_health_group {
- XHG_FS = 1,
+ XHG_NONE = 1,
+ XHG_FS,
XHG_AG,
XHG_INO,
XHG_RTGROUP,
@@ -83,6 +84,7 @@ struct xchk_health_map {
};
static const struct xchk_health_map type_to_health_flag[XFS_SCRUB_TYPE_NR] = {
+ [XFS_SCRUB_TYPE_PROBE] = { XHG_NONE, 0 },
[XFS_SCRUB_TYPE_SB] = { XHG_AG, XFS_SICK_AG_SB },
[XFS_SCRUB_TYPE_AGF] = { XHG_AG, XFS_SICK_AG_AGF },
[XFS_SCRUB_TYPE_AGFL] = { XHG_AG, XFS_SICK_AG_AGFL },
@@ -133,7 +135,7 @@ xchk_mark_healthy_if_clean(
{
if (!(sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
XFS_SCRUB_OFLAG_XCORRUPT)))
- sc->sick_mask |= mask;
+ sc->healthy_mask |= mask;
}
/*
@@ -189,6 +191,7 @@ xchk_update_health(
{
struct xfs_perag *pag;
struct xfs_rtgroup *rtg;
+ unsigned int mask = sc->sick_mask;
bool bad;
/*
@@ -203,50 +206,56 @@ xchk_update_health(
return;
}
- if (!sc->sick_mask)
- return;
-
bad = (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
XFS_SCRUB_OFLAG_XCORRUPT));
+ if (!bad)
+ mask |= sc->healthy_mask;
switch (type_to_health_flag[sc->sm->sm_type].group) {
+ case XHG_NONE:
+ break;
case XHG_AG:
+ if (!mask)
+ return;
pag = xfs_perag_get(sc->mp, sc->sm->sm_agno);
if (bad)
- xfs_group_mark_corrupt(pag_group(pag), sc->sick_mask);
+ xfs_group_mark_corrupt(pag_group(pag), mask);
else
- xfs_group_mark_healthy(pag_group(pag), sc->sick_mask);
+ xfs_group_mark_healthy(pag_group(pag), mask);
xfs_perag_put(pag);
break;
case XHG_INO:
if (!sc->ip)
return;
- if (bad) {
- unsigned int mask = sc->sick_mask;
-
- /*
- * If we're coming in for repairs then we don't want
- * sickness flags to propagate to the incore health
- * status if the inode gets inactivated before we can
- * fix it.
- */
- if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)
- mask |= XFS_SICK_INO_FORGET;
+ /*
+ * If we're coming in for repairs then we don't want sickness
+ * flags to propagate to the incore health status if the inode
+ * gets inactivated before we can fix it.
+ */
+ if (sc->sm->sm_flags & XFS_SCRUB_IFLAG_REPAIR)
+ mask |= XFS_SICK_INO_FORGET;
+ if (!mask)
+ return;
+ if (bad)
xfs_inode_mark_corrupt(sc->ip, mask);
- } else
- xfs_inode_mark_healthy(sc->ip, sc->sick_mask);
+ else
+ xfs_inode_mark_healthy(sc->ip, mask);
break;
case XHG_FS:
+ if (!mask)
+ return;
if (bad)
- xfs_fs_mark_corrupt(sc->mp, sc->sick_mask);
+ xfs_fs_mark_corrupt(sc->mp, mask);
else
- xfs_fs_mark_healthy(sc->mp, sc->sick_mask);
+ xfs_fs_mark_healthy(sc->mp, mask);
break;
case XHG_RTGROUP:
+ if (!mask)
+ return;
rtg = xfs_rtgroup_get(sc->mp, sc->sm->sm_agno);
if (bad)
- xfs_group_mark_corrupt(rtg_group(rtg), sc->sick_mask);
+ xfs_group_mark_corrupt(rtg_group(rtg), mask);
else
- xfs_group_mark_healthy(rtg_group(rtg), sc->sick_mask);
+ xfs_group_mark_healthy(rtg_group(rtg), mask);
xfs_rtgroup_put(rtg);
break;
default:
diff --git a/fs/xfs/scrub/ialloc.c b/fs/xfs/scrub/ialloc.c
index abad54c3621d..4dc7c83dc08a 100644
--- a/fs/xfs/scrub/ialloc.c
+++ b/fs/xfs/scrub/ialloc.c
@@ -650,8 +650,8 @@ xchk_iallocbt_xref_rmap_btreeblks(
struct xfs_scrub *sc)
{
xfs_filblks_t blocks;
- xfs_extlen_t inobt_blocks = 0;
- xfs_extlen_t finobt_blocks = 0;
+ xfs_filblks_t inobt_blocks = 0;
+ xfs_filblks_t finobt_blocks = 0;
int error;
if (!sc->sa.ino_cur || !sc->sa.rmap_cur ||
diff --git a/fs/xfs/scrub/metapath.c b/fs/xfs/scrub/metapath.c
index b78db6513465..c678cba1ffc3 100644
--- a/fs/xfs/scrub/metapath.c
+++ b/fs/xfs/scrub/metapath.c
@@ -171,23 +171,13 @@ static int
xchk_setup_metapath_quotadir(
struct xfs_scrub *sc)
{
- struct xfs_trans *tp;
- struct xfs_inode *dp = NULL;
- int error;
-
- error = xfs_trans_alloc_empty(sc->mp, &tp);
- if (error)
- return error;
+ struct xfs_quotainfo *qi = sc->mp->m_quotainfo;
- error = xfs_dqinode_load_parent(tp, &dp);
- xfs_trans_cancel(tp);
- if (error)
- return error;
+ if (!qi || !qi->qi_dirip)
+ return -ENOENT;
- error = xchk_setup_metapath_scan(sc, sc->mp->m_metadirip,
- kasprintf(GFP_KERNEL, "quota"), dp);
- xfs_irele(dp);
- return error;
+ return xchk_setup_metapath_scan(sc, sc->mp->m_metadirip,
+ kstrdup("quota", GFP_KERNEL), qi->qi_dirip);
}
/* Scan a quota inode under the /quota directory. */
@@ -196,37 +186,31 @@ xchk_setup_metapath_dqinode(
struct xfs_scrub *sc,
xfs_dqtype_t type)
{
- struct xfs_trans *tp = NULL;
- struct xfs_inode *dp = NULL;
+ struct xfs_quotainfo *qi = sc->mp->m_quotainfo;
struct xfs_inode *ip = NULL;
- const char *path;
- int error;
-
- error = xfs_trans_alloc_empty(sc->mp, &tp);
- if (error)
- return error;
- error = xfs_dqinode_load_parent(tp, &dp);
- if (error)
- goto out_cancel;
-
- error = xfs_dqinode_load(tp, dp, type, &ip);
- if (error)
- goto out_dp;
-
- xfs_trans_cancel(tp);
- tp = NULL;
+ if (!qi)
+ return -ENOENT;
- path = kasprintf(GFP_KERNEL, "%s", xfs_dqinode_path(type));
- error = xchk_setup_metapath_scan(sc, dp, path, ip);
+ switch (type) {
+ case XFS_DQTYPE_USER:
+ ip = qi->qi_uquotaip;
+ break;
+ case XFS_DQTYPE_GROUP:
+ ip = qi->qi_gquotaip;
+ break;
+ case XFS_DQTYPE_PROJ:
+ ip = qi->qi_pquotaip;
+ break;
+ default:
+ ASSERT(0);
+ return -EINVAL;
+ }
+ if (!ip)
+ return -ENOENT;
- xfs_irele(ip);
-out_dp:
- xfs_irele(dp);
-out_cancel:
- if (tp)
- xfs_trans_cancel(tp);
- return error;
+ return xchk_setup_metapath_scan(sc, qi->qi_dirip,
+ kstrdup(xfs_dqinode_path(type), GFP_KERNEL), ip);
}
#else
# define xchk_setup_metapath_quotadir(...) (-ENOENT)
diff --git a/fs/xfs/scrub/refcount.c b/fs/xfs/scrub/refcount.c
index 2b6be75e9424..1c5e45cc6419 100644
--- a/fs/xfs/scrub/refcount.c
+++ b/fs/xfs/scrub/refcount.c
@@ -491,7 +491,7 @@ xchk_refcount_xref_rmap(
struct xfs_scrub *sc,
xfs_filblks_t cow_blocks)
{
- xfs_extlen_t refcbt_blocks = 0;
+ xfs_filblks_t refcbt_blocks = 0;
xfs_filblks_t blocks;
int error;
diff --git a/fs/xfs/scrub/scrub.h b/fs/xfs/scrub/scrub.h
index a7fda3e2b013..5dbbe93cb49b 100644
--- a/fs/xfs/scrub/scrub.h
+++ b/fs/xfs/scrub/scrub.h
@@ -184,6 +184,12 @@ struct xfs_scrub {
*/
unsigned int sick_mask;
+ /*
+ * Clear these XFS_SICK_* flags but only if the scan is ok. Useful for
+ * removing ZAPPED flags after a repair.
+ */
+ unsigned int healthy_mask;
+
/* next time we want to cond_resched() */
struct xchk_relax relax;
diff --git a/fs/xfs/scrub/symlink_repair.c b/fs/xfs/scrub/symlink_repair.c
index d015a86ef460..953ce7be78dc 100644
--- a/fs/xfs/scrub/symlink_repair.c
+++ b/fs/xfs/scrub/symlink_repair.c
@@ -36,6 +36,7 @@
#include "scrub/tempfile.h"
#include "scrub/tempexch.h"
#include "scrub/reap.h"
+#include "scrub/health.h"
/*
* Symbolic Link Repair
@@ -233,7 +234,7 @@ xrep_symlink_salvage(
* target zapped flag.
*/
if (buflen == 0) {
- sc->sick_mask |= XFS_SICK_INO_SYMLINK_ZAPPED;
+ xchk_mark_healthy_if_clean(sc, XFS_SICK_INO_SYMLINK_ZAPPED);
sprintf(target_buf, DUMMY_TARGET);
}
diff --git a/fs/xfs/scrub/tempfile.c b/fs/xfs/scrub/tempfile.c
index 4b7f7860e37e..2d7ca7e1bbca 100644
--- a/fs/xfs/scrub/tempfile.c
+++ b/fs/xfs/scrub/tempfile.c
@@ -184,11 +184,18 @@ out_release_dquots:
}
/*
+ * Move sc->tempip from the regular directory tree to the metadata directory
+ * tree if sc->ip is part of the metadata directory tree and tempip has an
+ * eligible file mode.
+ *
* Temporary files have to be created before we even know which inode we're
* going to scrub, so we assume that they will be part of the regular directory
* tree. If it turns out that we're actually scrubbing a file from the
* metadata directory tree, we have to subtract the temp file from the root
- * dquots and detach the dquots.
+ * dquots and detach the dquots prior to setting the METADATA iflag. However,
+ * the scrub setup functions grab sc->ip and create sc->tempip before we
+ * actually get around to checking if the file mode is the right type for the
+ * scrubber.
*/
int
xrep_tempfile_adjust_directory_tree(
@@ -204,6 +211,9 @@ xrep_tempfile_adjust_directory_tree(
if (!sc->ip || !xfs_is_metadir_inode(sc->ip))
return 0;
+ if (!S_ISDIR(VFS_I(sc->tempip)->i_mode) &&
+ !S_ISREG(VFS_I(sc->tempip)->i_mode))
+ return 0;
xfs_ilock(sc->tempip, XFS_IOLOCK_EXCL);
sc->temp_ilock_flags |= XFS_IOLOCK_EXCL;
@@ -223,6 +233,7 @@ xrep_tempfile_adjust_directory_tree(
if (error)
goto out_ilock;
+ xfs_iflags_set(sc->tempip, XFS_IRECOVERY);
xfs_qm_dqdetach(sc->tempip);
out_ilock:
xrep_tempfile_iunlock(sc);
@@ -246,6 +257,8 @@ xrep_tempfile_remove_metadir(
ASSERT(sc->tp == NULL);
+ xfs_iflags_clear(sc->tempip, XFS_IRECOVERY);
+
xfs_ilock(sc->tempip, XFS_IOLOCK_EXCL);
sc->temp_ilock_flags |= XFS_IOLOCK_EXCL;
@@ -945,10 +958,13 @@ xrep_is_tempfile(
/*
* Files in the metadata directory tree also have S_PRIVATE set and
- * IOP_XATTR unset, so we must distinguish them separately.
+ * IOP_XATTR unset, so we must distinguish them separately. We (ab)use
+ * the IRECOVERY flag to mark temporary metadir inodes knowing that the
+ * end of log recovery clears IRECOVERY, so the only ones that can
+ * exist during online repair are the ones we create.
*/
if (xfs_has_metadir(mp) && (ip->i_diflags2 & XFS_DIFLAG2_METADATA))
- return false;
+ return __xfs_iflags_test(ip, XFS_IRECOVERY);
if (IS_PRIVATE(inode) && !(inode->i_opflags & IOP_XATTR))
return true;
diff --git a/fs/xfs/scrub/trace.h b/fs/xfs/scrub/trace.h
index 9b38f5ad1eaf..d2ae7e93acb0 100644
--- a/fs/xfs/scrub/trace.h
+++ b/fs/xfs/scrub/trace.h
@@ -605,7 +605,7 @@ TRACE_EVENT(xchk_ifork_btree_op_error,
TP_fast_assign(
xfs_fsblock_t fsbno = xchk_btree_cur_fsbno(cur, level);
__entry->dev = sc->mp->m_super->s_dev;
- __entry->ino = sc->ip->i_ino;
+ __entry->ino = cur->bc_ino.ip->i_ino;
__entry->whichfork = cur->bc_ino.whichfork;
__entry->type = sc->sm->sm_type;
__assign_str(name);
diff --git a/fs/xfs/xfs_attr_list.c b/fs/xfs/xfs_attr_list.c
index 7db386304875..379b48d015d2 100644
--- a/fs/xfs/xfs_attr_list.c
+++ b/fs/xfs/xfs_attr_list.c
@@ -114,7 +114,8 @@ xfs_attr_shortform_list(
* It didn't all fit, so we have to sort everything on hashval.
*/
sbsize = sf->count * sizeof(*sbuf);
- sbp = sbuf = kmalloc(sbsize, GFP_KERNEL | __GFP_NOFAIL);
+ sbp = sbuf = kmalloc(sbsize,
+ GFP_KERNEL | __GFP_NOLOCKDEP | __GFP_NOFAIL);
/*
* Scan the attribute list for the rest of the entries, storing
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index a59bbe767a7d..0836fea2d6d8 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -103,7 +103,7 @@ xfs_bmap_count_blocks(
struct xfs_mount *mp = ip->i_mount;
struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork);
struct xfs_btree_cur *cur;
- xfs_extlen_t btblocks = 0;
+ xfs_filblks_t btblocks = 0;
int error;
*nextents = 0;
diff --git a/fs/xfs/xfs_dquot.c b/fs/xfs/xfs_dquot.c
index ff982d983989..f11d475898f2 100644
--- a/fs/xfs/xfs_dquot.c
+++ b/fs/xfs/xfs_dquot.c
@@ -69,6 +69,30 @@ xfs_dquot_mark_sick(
}
/*
+ * Detach the dquot buffer if it's still attached, because we can get called
+ * through dqpurge after a log shutdown. Caller must hold the dqflock or have
+ * otherwise isolated the dquot.
+ */
+void
+xfs_dquot_detach_buf(
+ struct xfs_dquot *dqp)
+{
+ struct xfs_dq_logitem *qlip = &dqp->q_logitem;
+ struct xfs_buf *bp = NULL;
+
+ spin_lock(&qlip->qli_lock);
+ if (qlip->qli_item.li_buf) {
+ bp = qlip->qli_item.li_buf;
+ qlip->qli_item.li_buf = NULL;
+ }
+ spin_unlock(&qlip->qli_lock);
+ if (bp) {
+ list_del_init(&qlip->qli_item.li_bio_list);
+ xfs_buf_rele(bp);
+ }
+}
+
+/*
* This is called to free all the memory associated with a dquot
*/
void
@@ -76,6 +100,7 @@ xfs_qm_dqdestroy(
struct xfs_dquot *dqp)
{
ASSERT(list_empty(&dqp->q_lru));
+ ASSERT(dqp->q_logitem.qli_item.li_buf == NULL);
kvfree(dqp->q_logitem.qli_item.li_lv_shadow);
mutex_destroy(&dqp->q_qlock);
@@ -1142,9 +1167,11 @@ static void
xfs_qm_dqflush_done(
struct xfs_log_item *lip)
{
- struct xfs_dq_logitem *qip = (struct xfs_dq_logitem *)lip;
- struct xfs_dquot *dqp = qip->qli_dquot;
+ struct xfs_dq_logitem *qlip =
+ container_of(lip, struct xfs_dq_logitem, qli_item);
+ struct xfs_dquot *dqp = qlip->qli_dquot;
struct xfs_ail *ailp = lip->li_ailp;
+ struct xfs_buf *bp = NULL;
xfs_lsn_t tail_lsn;
/*
@@ -1156,12 +1183,12 @@ xfs_qm_dqflush_done(
* holding the lock before removing the dquot from the AIL.
*/
if (test_bit(XFS_LI_IN_AIL, &lip->li_flags) &&
- ((lip->li_lsn == qip->qli_flush_lsn) ||
+ (lip->li_lsn == qlip->qli_flush_lsn ||
test_bit(XFS_LI_FAILED, &lip->li_flags))) {
spin_lock(&ailp->ail_lock);
xfs_clear_li_failed(lip);
- if (lip->li_lsn == qip->qli_flush_lsn) {
+ if (lip->li_lsn == qlip->qli_flush_lsn) {
/* xfs_ail_update_finish() drops the AIL lock */
tail_lsn = xfs_ail_delete_one(ailp, lip);
xfs_ail_update_finish(ailp, tail_lsn);
@@ -1171,6 +1198,20 @@ xfs_qm_dqflush_done(
}
/*
+ * If this dquot hasn't been dirtied since initiating the last dqflush,
+ * release the buffer reference. We already unlinked this dquot item
+ * from the buffer.
+ */
+ spin_lock(&qlip->qli_lock);
+ if (!qlip->qli_dirty) {
+ bp = lip->li_buf;
+ lip->li_buf = NULL;
+ }
+ spin_unlock(&qlip->qli_lock);
+ if (bp)
+ xfs_buf_rele(bp);
+
+ /*
* Release the dq's flush lock since we're done with it.
*/
xfs_dqfunlock(dqp);
@@ -1196,7 +1237,7 @@ xfs_buf_dquot_io_fail(
spin_lock(&bp->b_mount->m_ail->ail_lock);
list_for_each_entry(lip, &bp->b_li_list, li_bio_list)
- xfs_set_li_failed(lip, bp);
+ set_bit(XFS_LI_FAILED, &lip->li_flags);
spin_unlock(&bp->b_mount->m_ail->ail_lock);
}
@@ -1239,6 +1280,111 @@ xfs_qm_dqflush_check(
}
/*
+ * Get the buffer containing the on-disk dquot.
+ *
+ * Requires dquot flush lock, will clear the dirty flag, delete the quota log
+ * item from the AIL, and shut down the system if something goes wrong.
+ */
+static int
+xfs_dquot_read_buf(
+ struct xfs_trans *tp,
+ struct xfs_dquot *dqp,
+ struct xfs_buf **bpp)
+{
+ struct xfs_mount *mp = dqp->q_mount;
+ struct xfs_buf *bp = NULL;
+ int error;
+
+ error = xfs_trans_read_buf(mp, tp, mp->m_ddev_targp, dqp->q_blkno,
+ mp->m_quotainfo->qi_dqchunklen, 0,
+ &bp, &xfs_dquot_buf_ops);
+ if (xfs_metadata_is_sick(error))
+ xfs_dquot_mark_sick(dqp);
+ if (error)
+ goto out_abort;
+
+ *bpp = bp;
+ return 0;
+
+out_abort:
+ dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
+ xfs_trans_ail_delete(&dqp->q_logitem.qli_item, 0);
+ xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
+ return error;
+}
+
+/*
+ * Attach a dquot buffer to this dquot to avoid allocating a buffer during a
+ * dqflush, since dqflush can be called from reclaim context.
+ */
+int
+xfs_dquot_attach_buf(
+ struct xfs_trans *tp,
+ struct xfs_dquot *dqp)
+{
+ struct xfs_dq_logitem *qlip = &dqp->q_logitem;
+ struct xfs_log_item *lip = &qlip->qli_item;
+ int error;
+
+ spin_lock(&qlip->qli_lock);
+ if (!lip->li_buf) {
+ struct xfs_buf *bp = NULL;
+
+ spin_unlock(&qlip->qli_lock);
+ error = xfs_dquot_read_buf(tp, dqp, &bp);
+ if (error)
+ return error;
+
+ /*
+ * Attach the dquot to the buffer so that the AIL does not have
+ * to read the dquot buffer to push this item.
+ */
+ xfs_buf_hold(bp);
+ spin_lock(&qlip->qli_lock);
+ lip->li_buf = bp;
+ xfs_trans_brelse(tp, bp);
+ }
+ qlip->qli_dirty = true;
+ spin_unlock(&qlip->qli_lock);
+
+ return 0;
+}
+
+/*
+ * Get a new reference the dquot buffer attached to this dquot for a dqflush
+ * operation.
+ *
+ * Returns 0 and a NULL bp if none was attached to the dquot; 0 and a locked
+ * bp; or -EAGAIN if the buffer could not be locked.
+ */
+int
+xfs_dquot_use_attached_buf(
+ struct xfs_dquot *dqp,
+ struct xfs_buf **bpp)
+{
+ struct xfs_buf *bp = dqp->q_logitem.qli_item.li_buf;
+
+ /*
+ * A NULL buffer can happen if the dquot dirty flag was set but the
+ * filesystem shut down before transaction commit happened. In that
+ * case we're not going to flush anyway.
+ */
+ if (!bp) {
+ ASSERT(xfs_is_shutdown(dqp->q_mount));
+
+ *bpp = NULL;
+ return 0;
+ }
+
+ if (!xfs_buf_trylock(bp))
+ return -EAGAIN;
+
+ xfs_buf_hold(bp);
+ *bpp = bp;
+ return 0;
+}
+
+/*
* Write a modified dquot to disk.
* The dquot must be locked and the flush lock too taken by caller.
* The flush lock will not be unlocked until the dquot reaches the disk,
@@ -1249,11 +1395,11 @@ xfs_qm_dqflush_check(
int
xfs_qm_dqflush(
struct xfs_dquot *dqp,
- struct xfs_buf **bpp)
+ struct xfs_buf *bp)
{
struct xfs_mount *mp = dqp->q_mount;
- struct xfs_log_item *lip = &dqp->q_logitem.qli_item;
- struct xfs_buf *bp;
+ struct xfs_dq_logitem *qlip = &dqp->q_logitem;
+ struct xfs_log_item *lip = &qlip->qli_item;
struct xfs_dqblk *dqblk;
xfs_failaddr_t fa;
int error;
@@ -1263,28 +1409,12 @@ xfs_qm_dqflush(
trace_xfs_dqflush(dqp);
- *bpp = NULL;
-
xfs_qm_dqunpin_wait(dqp);
- /*
- * Get the buffer containing the on-disk dquot
- */
- error = xfs_trans_read_buf(mp, NULL, mp->m_ddev_targp, dqp->q_blkno,
- mp->m_quotainfo->qi_dqchunklen, XBF_TRYLOCK,
- &bp, &xfs_dquot_buf_ops);
- if (error == -EAGAIN)
- goto out_unlock;
- if (xfs_metadata_is_sick(error))
- xfs_dquot_mark_sick(dqp);
- if (error)
- goto out_abort;
-
fa = xfs_qm_dqflush_check(dqp);
if (fa) {
xfs_alert(mp, "corrupt dquot ID 0x%x in memory at %pS",
dqp->q_id, fa);
- xfs_buf_relse(bp);
xfs_dquot_mark_sick(dqp);
error = -EFSCORRUPTED;
goto out_abort;
@@ -1299,8 +1429,15 @@ xfs_qm_dqflush(
*/
dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
- xfs_trans_ail_copy_lsn(mp->m_ail, &dqp->q_logitem.qli_flush_lsn,
- &dqp->q_logitem.qli_item.li_lsn);
+ /*
+ * We hold the dquot lock, so nobody can dirty it while we're
+ * scheduling the write out. Clear the dirty-since-flush flag.
+ */
+ spin_lock(&qlip->qli_lock);
+ qlip->qli_dirty = false;
+ spin_unlock(&qlip->qli_lock);
+
+ xfs_trans_ail_copy_lsn(mp->m_ail, &qlip->qli_flush_lsn, &lip->li_lsn);
/*
* copy the lsn into the on-disk dquot now while we have the in memory
@@ -1312,7 +1449,7 @@ xfs_qm_dqflush(
* of a dquot without an up-to-date CRC getting to disk.
*/
if (xfs_has_crc(mp)) {
- dqblk->dd_lsn = cpu_to_be64(dqp->q_logitem.qli_item.li_lsn);
+ dqblk->dd_lsn = cpu_to_be64(lip->li_lsn);
xfs_update_cksum((char *)dqblk, sizeof(struct xfs_dqblk),
XFS_DQUOT_CRC_OFF);
}
@@ -1322,7 +1459,7 @@ xfs_qm_dqflush(
* the AIL and release the flush lock once the dquot is synced to disk.
*/
bp->b_flags |= _XBF_DQUOTS;
- list_add_tail(&dqp->q_logitem.qli_item.li_bio_list, &bp->b_li_list);
+ list_add_tail(&lip->li_bio_list, &bp->b_li_list);
/*
* If the buffer is pinned then push on the log so we won't
@@ -1334,14 +1471,12 @@ xfs_qm_dqflush(
}
trace_xfs_dqflush_done(dqp);
- *bpp = bp;
return 0;
out_abort:
dqp->q_flags &= ~XFS_DQFLAG_DIRTY;
xfs_trans_ail_delete(lip, 0);
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
-out_unlock:
xfs_dqfunlock(dqp);
return error;
}
diff --git a/fs/xfs/xfs_dquot.h b/fs/xfs/xfs_dquot.h
index d73d179df009..c617bac75361 100644
--- a/fs/xfs/xfs_dquot.h
+++ b/fs/xfs/xfs_dquot.h
@@ -214,7 +214,7 @@ void xfs_dquot_to_disk(struct xfs_disk_dquot *ddqp, struct xfs_dquot *dqp);
#define XFS_DQ_IS_DIRTY(dqp) ((dqp)->q_flags & XFS_DQFLAG_DIRTY)
void xfs_qm_dqdestroy(struct xfs_dquot *dqp);
-int xfs_qm_dqflush(struct xfs_dquot *dqp, struct xfs_buf **bpp);
+int xfs_qm_dqflush(struct xfs_dquot *dqp, struct xfs_buf *bp);
void xfs_qm_dqunpin_wait(struct xfs_dquot *dqp);
void xfs_qm_adjust_dqtimers(struct xfs_dquot *d);
void xfs_qm_adjust_dqlimits(struct xfs_dquot *d);
@@ -237,6 +237,10 @@ void xfs_dqlockn(struct xfs_dqtrx *q);
void xfs_dquot_set_prealloc_limits(struct xfs_dquot *);
+int xfs_dquot_attach_buf(struct xfs_trans *tp, struct xfs_dquot *dqp);
+int xfs_dquot_use_attached_buf(struct xfs_dquot *dqp, struct xfs_buf **bpp);
+void xfs_dquot_detach_buf(struct xfs_dquot *dqp);
+
static inline struct xfs_dquot *xfs_qm_dqhold(struct xfs_dquot *dqp)
{
xfs_dqlock(dqp);
diff --git a/fs/xfs/xfs_dquot_item.c b/fs/xfs/xfs_dquot_item.c
index 7d19091215b0..271b195ebb93 100644
--- a/fs/xfs/xfs_dquot_item.c
+++ b/fs/xfs/xfs_dquot_item.c
@@ -123,8 +123,9 @@ xfs_qm_dquot_logitem_push(
__releases(&lip->li_ailp->ail_lock)
__acquires(&lip->li_ailp->ail_lock)
{
- struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot;
- struct xfs_buf *bp = lip->li_buf;
+ struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip);
+ struct xfs_dquot *dqp = qlip->qli_dquot;
+ struct xfs_buf *bp;
uint rval = XFS_ITEM_SUCCESS;
int error;
@@ -155,14 +156,25 @@ xfs_qm_dquot_logitem_push(
spin_unlock(&lip->li_ailp->ail_lock);
- error = xfs_qm_dqflush(dqp, &bp);
+ error = xfs_dquot_use_attached_buf(dqp, &bp);
+ if (error == -EAGAIN) {
+ xfs_dqfunlock(dqp);
+ rval = XFS_ITEM_LOCKED;
+ goto out_relock_ail;
+ }
+
+ /*
+ * dqflush completes dqflock on error, and the delwri ioend does it on
+ * success.
+ */
+ error = xfs_qm_dqflush(dqp, bp);
if (!error) {
if (!xfs_buf_delwri_queue(bp, buffer_list))
rval = XFS_ITEM_FLUSHING;
- xfs_buf_relse(bp);
- } else if (error == -EAGAIN)
- rval = XFS_ITEM_LOCKED;
+ }
+ xfs_buf_relse(bp);
+out_relock_ail:
spin_lock(&lip->li_ailp->ail_lock);
out_unlock:
xfs_dqunlock(dqp);
@@ -195,12 +207,10 @@ xfs_qm_dquot_logitem_committing(
}
#ifdef DEBUG_EXPENSIVE
-static int
-xfs_qm_dquot_logitem_precommit(
- struct xfs_trans *tp,
- struct xfs_log_item *lip)
+static void
+xfs_qm_dquot_logitem_precommit_check(
+ struct xfs_dquot *dqp)
{
- struct xfs_dquot *dqp = DQUOT_ITEM(lip)->qli_dquot;
struct xfs_mount *mp = dqp->q_mount;
struct xfs_disk_dquot ddq = { };
xfs_failaddr_t fa;
@@ -216,13 +226,24 @@ xfs_qm_dquot_logitem_precommit(
xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE);
ASSERT(fa == NULL);
}
-
- return 0;
}
#else
-# define xfs_qm_dquot_logitem_precommit NULL
+# define xfs_qm_dquot_logitem_precommit_check(...) ((void)0)
#endif
+static int
+xfs_qm_dquot_logitem_precommit(
+ struct xfs_trans *tp,
+ struct xfs_log_item *lip)
+{
+ struct xfs_dq_logitem *qlip = DQUOT_ITEM(lip);
+ struct xfs_dquot *dqp = qlip->qli_dquot;
+
+ xfs_qm_dquot_logitem_precommit_check(dqp);
+
+ return xfs_dquot_attach_buf(tp, dqp);
+}
+
static const struct xfs_item_ops xfs_dquot_item_ops = {
.iop_size = xfs_qm_dquot_logitem_size,
.iop_precommit = xfs_qm_dquot_logitem_precommit,
@@ -247,5 +268,7 @@ xfs_qm_dquot_logitem_init(
xfs_log_item_init(dqp->q_mount, &lp->qli_item, XFS_LI_DQUOT,
&xfs_dquot_item_ops);
+ spin_lock_init(&lp->qli_lock);
lp->qli_dquot = dqp;
+ lp->qli_dirty = false;
}
diff --git a/fs/xfs/xfs_dquot_item.h b/fs/xfs/xfs_dquot_item.h
index 794710c24474..d66e52807d76 100644
--- a/fs/xfs/xfs_dquot_item.h
+++ b/fs/xfs/xfs_dquot_item.h
@@ -14,6 +14,13 @@ struct xfs_dq_logitem {
struct xfs_log_item qli_item; /* common portion */
struct xfs_dquot *qli_dquot; /* dquot ptr */
xfs_lsn_t qli_flush_lsn; /* lsn at last flush */
+
+ /*
+ * We use this spinlock to coordinate access to the li_buf pointer in
+ * the log item and the qli_dirty flag.
+ */
+ spinlock_t qli_lock;
+ bool qli_dirty; /* dirtied since last flush? */
};
void xfs_qm_dquot_logitem_init(struct xfs_dquot *dqp);
diff --git a/fs/xfs/xfs_exchrange.c b/fs/xfs/xfs_exchrange.c
index 9ab05ad224d1..265c42449893 100644
--- a/fs/xfs/xfs_exchrange.c
+++ b/fs/xfs/xfs_exchrange.c
@@ -854,7 +854,7 @@ xfs_ioc_start_commit(
struct xfs_commit_range __user *argp)
{
struct xfs_commit_range args = { };
- struct timespec64 ts;
+ struct kstat kstat = { };
struct xfs_commit_range_fresh *kern_f;
struct xfs_commit_range_fresh __user *user_f;
struct inode *inode2 = file_inode(file);
@@ -871,12 +871,12 @@ xfs_ioc_start_commit(
memcpy(&kern_f->fsid, ip2->i_mount->m_fixedfsid, sizeof(xfs_fsid_t));
xfs_ilock(ip2, lockflags);
- ts = inode_get_ctime(inode2);
- kern_f->file2_ctime = ts.tv_sec;
- kern_f->file2_ctime_nsec = ts.tv_nsec;
- ts = inode_get_mtime(inode2);
- kern_f->file2_mtime = ts.tv_sec;
- kern_f->file2_mtime_nsec = ts.tv_nsec;
+ /* Force writing of a distinct ctime if any writes happen. */
+ fill_mg_cmtime(&kstat, STATX_CTIME | STATX_MTIME, inode2);
+ kern_f->file2_ctime = kstat.ctime.tv_sec;
+ kern_f->file2_ctime_nsec = kstat.ctime.tv_nsec;
+ kern_f->file2_mtime = kstat.mtime.tv_sec;
+ kern_f->file2_mtime_nsec = kstat.mtime.tv_nsec;
kern_f->file2_ino = ip2->i_ino;
kern_f->file2_gen = inode2->i_generation;
kern_f->magic = XCR_FRESH_MAGIC;
diff --git a/fs/xfs/xfs_file.c b/fs/xfs/xfs_file.c
index 4a0b7de4f7ae..9a435b1ff264 100644
--- a/fs/xfs/xfs_file.c
+++ b/fs/xfs/xfs_file.c
@@ -1242,6 +1242,14 @@ out_unlock:
xfs_iunlock2_remapping(src, dest);
if (ret)
trace_xfs_reflink_remap_range_error(dest, ret, _RET_IP_);
+ /*
+ * If the caller did not set CAN_SHORTEN, then it is not prepared to
+ * handle partial results -- either the whole remap succeeds, or we
+ * must say why it did not. In this case, any error should be returned
+ * to the caller.
+ */
+ if (ret && remapped < len && !(remap_flags & REMAP_FILE_CAN_SHORTEN))
+ return ret;
return remapped > 0 ? remapped : ret;
}
diff --git a/fs/xfs/xfs_fsmap.c b/fs/xfs/xfs_fsmap.c
index 82f2e0dd2249..3290dd8524a6 100644
--- a/fs/xfs/xfs_fsmap.c
+++ b/fs/xfs/xfs_fsmap.c
@@ -163,7 +163,8 @@ struct xfs_getfsmap_info {
xfs_daddr_t next_daddr; /* next daddr we expect */
/* daddr of low fsmap key when we're using the rtbitmap */
xfs_daddr_t low_daddr;
- xfs_daddr_t end_daddr; /* daddr of high fsmap key */
+ /* daddr of high fsmap key, or the last daddr on the device */
+ xfs_daddr_t end_daddr;
u64 missing_owner; /* owner of holes */
u32 dev; /* device id */
/*
@@ -387,8 +388,8 @@ xfs_getfsmap_group_helper(
* we calculated from userspace's high key to synthesize the record.
* Note that if the btree query found a mapping, there won't be a gap.
*/
- if (info->last && info->end_daddr != XFS_BUF_DADDR_NULL)
- frec->start_daddr = info->end_daddr;
+ if (info->last)
+ frec->start_daddr = info->end_daddr + 1;
else
frec->start_daddr = xfs_gbno_to_daddr(xg, startblock);
@@ -736,11 +737,10 @@ xfs_getfsmap_rtdev_rtbitmap_helper(
* we calculated from userspace's high key to synthesize the record.
* Note that if the btree query found a mapping, there won't be a gap.
*/
- if (info->last && info->end_daddr != XFS_BUF_DADDR_NULL) {
- frec.start_daddr = info->end_daddr;
- } else {
+ if (info->last)
+ frec.start_daddr = info->end_daddr + 1;
+ else
frec.start_daddr = xfs_rtb_to_daddr(mp, start_rtb);
- }
frec.len_daddr = XFS_FSB_TO_BB(mp, rtbcount);
return xfs_getfsmap_helper(tp, info, &frec);
@@ -933,7 +933,10 @@ xfs_getfsmap(
struct xfs_trans *tp = NULL;
struct xfs_fsmap dkeys[2]; /* per-dev keys */
struct xfs_getfsmap_dev handlers[XFS_GETFSMAP_DEVS];
- struct xfs_getfsmap_info info = { NULL };
+ struct xfs_getfsmap_info info = {
+ .fsmap_recs = fsmap_recs,
+ .head = head,
+ };
bool use_rmap;
int i;
int error = 0;
@@ -998,9 +1001,6 @@ xfs_getfsmap(
info.next_daddr = head->fmh_keys[0].fmr_physical +
head->fmh_keys[0].fmr_length;
- info.end_daddr = XFS_BUF_DADDR_NULL;
- info.fsmap_recs = fsmap_recs;
- info.head = head;
/* For each device we support... */
for (i = 0; i < XFS_GETFSMAP_DEVS; i++) {
@@ -1013,17 +1013,23 @@ xfs_getfsmap(
break;
/*
- * If this device number matches the high key, we have
- * to pass the high key to the handler to limit the
- * query results. If the device number exceeds the
- * low key, zero out the low key so that we get
- * everything from the beginning.
+ * If this device number matches the high key, we have to pass
+ * the high key to the handler to limit the query results, and
+ * set the end_daddr so that we can synthesize records at the
+ * end of the query range or device.
*/
if (handlers[i].dev == head->fmh_keys[1].fmr_device) {
dkeys[1] = head->fmh_keys[1];
info.end_daddr = min(handlers[i].nr_sectors - 1,
dkeys[1].fmr_physical);
+ } else {
+ info.end_daddr = handlers[i].nr_sectors - 1;
}
+
+ /*
+ * If the device number exceeds the low key, zero out the low
+ * key so that we get everything from the beginning.
+ */
if (handlers[i].dev > head->fmh_keys[0].fmr_device)
memset(&dkeys[0], 0, sizeof(struct xfs_fsmap));
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h
index b0de3d924d4c..1648dc5a8068 100644
--- a/fs/xfs/xfs_inode.h
+++ b/fs/xfs/xfs_inode.h
@@ -231,7 +231,7 @@ xfs_iflags_clear(xfs_inode_t *ip, unsigned long flags)
}
static inline int
-__xfs_iflags_test(xfs_inode_t *ip, unsigned long flags)
+__xfs_iflags_test(const struct xfs_inode *ip, unsigned long flags)
{
return (ip->i_flags & flags);
}
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c
index 26b2f5887b88..05daad8a8d34 100644
--- a/fs/xfs/xfs_log.c
+++ b/fs/xfs/xfs_log.c
@@ -3456,6 +3456,16 @@ xlog_force_shutdown(
return false;
/*
+ * Ensure that there is only ever one log shutdown being processed.
+ * If we allow the log force below on a second pass after shutting
+ * down the log, we risk deadlocking the CIL push as it may require
+ * locks on objects the current shutdown context holds (e.g. taking
+ * buffer locks to abort buffers on last unpin of buf log items).
+ */
+ if (test_and_set_bit(XLOG_SHUTDOWN_STARTED, &log->l_opstate))
+ return false;
+
+ /*
* Flush all the completed transactions to disk before marking the log
* being shut down. We need to do this first as shutting down the log
* before the force will prevent the log force from flushing the iclogs
@@ -3487,6 +3497,7 @@ xlog_force_shutdown(
spin_lock(&log->l_icloglock);
if (test_and_set_bit(XLOG_IO_ERROR, &log->l_opstate)) {
spin_unlock(&log->l_icloglock);
+ ASSERT(0);
return false;
}
spin_unlock(&log->l_icloglock);
diff --git a/fs/xfs/xfs_log_cil.c b/fs/xfs/xfs_log_cil.c
index 2e9157b650e6..1ca406ec1b40 100644
--- a/fs/xfs/xfs_log_cil.c
+++ b/fs/xfs/xfs_log_cil.c
@@ -171,11 +171,8 @@ xlog_cil_insert_pcp_aggregate(
*/
for_each_cpu(cpu, &ctx->cil_pcpmask) {
struct xlog_cil_pcp *cilpcp = per_cpu_ptr(cil->xc_pcp, cpu);
- int old = READ_ONCE(cilpcp->space_used);
- while (!try_cmpxchg(&cilpcp->space_used, &old, 0))
- ;
- count += old;
+ count += xchg(&cilpcp->space_used, 0);
}
atomic_add(count, &ctx->space_used);
}
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h
index b8778a4fd6b6..f3d78869e5e5 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -458,6 +458,7 @@ struct xlog {
#define XLOG_IO_ERROR 2 /* log hit an I/O error, and being
shutdown */
#define XLOG_TAIL_WARN 3 /* log tail verify warning issued */
+#define XLOG_SHUTDOWN_STARTED 4 /* xlog_force_shutdown() exclusion */
static inline bool
xlog_recovery_needed(struct xlog *log)
diff --git a/fs/xfs/xfs_qm.c b/fs/xfs/xfs_qm.c
index 61ee110b47d7..dc8b1010d4d3 100644
--- a/fs/xfs/xfs_qm.c
+++ b/fs/xfs/xfs_qm.c
@@ -148,17 +148,29 @@ xfs_qm_dqpurge(
* We don't care about getting disk errors here. We need
* to purge this dquot anyway, so we go ahead regardless.
*/
- error = xfs_qm_dqflush(dqp, &bp);
+ error = xfs_dquot_use_attached_buf(dqp, &bp);
+ if (error == -EAGAIN) {
+ xfs_dqfunlock(dqp);
+ dqp->q_flags &= ~XFS_DQFLAG_FREEING;
+ goto out_unlock;
+ }
+ if (!bp)
+ goto out_funlock;
+
+ /*
+ * dqflush completes dqflock on error, and the bwrite ioend
+ * does it on success.
+ */
+ error = xfs_qm_dqflush(dqp, bp);
if (!error) {
error = xfs_bwrite(bp);
xfs_buf_relse(bp);
- } else if (error == -EAGAIN) {
- dqp->q_flags &= ~XFS_DQFLAG_FREEING;
- goto out_unlock;
}
xfs_dqflock(dqp);
}
+ xfs_dquot_detach_buf(dqp);
+out_funlock:
ASSERT(atomic_read(&dqp->q_pincount) == 0);
ASSERT(xlog_is_shutdown(dqp->q_logitem.qli_item.li_log) ||
!test_bit(XFS_LI_IN_AIL, &dqp->q_logitem.qli_item.li_flags));
@@ -241,6 +253,10 @@ xfs_qm_destroy_quotainos(
xfs_irele(qi->qi_pquotaip);
qi->qi_pquotaip = NULL;
}
+ if (qi->qi_dirip) {
+ xfs_irele(qi->qi_dirip);
+ qi->qi_dirip = NULL;
+ }
}
/*
@@ -490,7 +506,17 @@ xfs_qm_dquot_isolate(
/* we have to drop the LRU lock to flush the dquot */
spin_unlock(&lru->lock);
- error = xfs_qm_dqflush(dqp, &bp);
+ error = xfs_dquot_use_attached_buf(dqp, &bp);
+ if (!bp || error == -EAGAIN) {
+ xfs_dqfunlock(dqp);
+ goto out_unlock_dirty;
+ }
+
+ /*
+ * dqflush completes dqflock on error, and the delwri ioend
+ * does it on success.
+ */
+ error = xfs_qm_dqflush(dqp, bp);
if (error)
goto out_unlock_dirty;
@@ -498,6 +524,8 @@ xfs_qm_dquot_isolate(
xfs_buf_relse(bp);
goto out_unlock_dirty;
}
+
+ xfs_dquot_detach_buf(dqp);
xfs_dqfunlock(dqp);
/*
@@ -646,8 +674,7 @@ xfs_qm_init_timelimits(
static int
xfs_qm_load_metadir_qinos(
struct xfs_mount *mp,
- struct xfs_quotainfo *qi,
- struct xfs_inode **dpp)
+ struct xfs_quotainfo *qi)
{
struct xfs_trans *tp;
int error;
@@ -656,7 +683,7 @@ xfs_qm_load_metadir_qinos(
if (error)
return error;
- error = xfs_dqinode_load_parent(tp, dpp);
+ error = xfs_dqinode_load_parent(tp, &qi->qi_dirip);
if (error == -ENOENT) {
/* no quota dir directory, but we'll create one later */
error = 0;
@@ -666,21 +693,21 @@ xfs_qm_load_metadir_qinos(
goto out_trans;
if (XFS_IS_UQUOTA_ON(mp)) {
- error = xfs_dqinode_load(tp, *dpp, XFS_DQTYPE_USER,
+ error = xfs_dqinode_load(tp, qi->qi_dirip, XFS_DQTYPE_USER,
&qi->qi_uquotaip);
if (error && error != -ENOENT)
goto out_trans;
}
if (XFS_IS_GQUOTA_ON(mp)) {
- error = xfs_dqinode_load(tp, *dpp, XFS_DQTYPE_GROUP,
+ error = xfs_dqinode_load(tp, qi->qi_dirip, XFS_DQTYPE_GROUP,
&qi->qi_gquotaip);
if (error && error != -ENOENT)
goto out_trans;
}
if (XFS_IS_PQUOTA_ON(mp)) {
- error = xfs_dqinode_load(tp, *dpp, XFS_DQTYPE_PROJ,
+ error = xfs_dqinode_load(tp, qi->qi_dirip, XFS_DQTYPE_PROJ,
&qi->qi_pquotaip);
if (error && error != -ENOENT)
goto out_trans;
@@ -696,34 +723,40 @@ out_trans:
STATIC int
xfs_qm_create_metadir_qinos(
struct xfs_mount *mp,
- struct xfs_quotainfo *qi,
- struct xfs_inode **dpp)
+ struct xfs_quotainfo *qi)
{
int error;
- if (!*dpp) {
- error = xfs_dqinode_mkdir_parent(mp, dpp);
+ if (!qi->qi_dirip) {
+ error = xfs_dqinode_mkdir_parent(mp, &qi->qi_dirip);
if (error && error != -EEXIST)
return error;
+ /*
+ * If the /quotas dirent points to an inode that isn't
+ * loadable, qi_dirip will be NULL but mkdir_parent will return
+ * -EEXIST. In this case the metadir is corrupt, so bail out.
+ */
+ if (XFS_IS_CORRUPT(mp, qi->qi_dirip == NULL))
+ return -EFSCORRUPTED;
}
if (XFS_IS_UQUOTA_ON(mp) && !qi->qi_uquotaip) {
- error = xfs_dqinode_metadir_create(*dpp, XFS_DQTYPE_USER,
- &qi->qi_uquotaip);
+ error = xfs_dqinode_metadir_create(qi->qi_dirip,
+ XFS_DQTYPE_USER, &qi->qi_uquotaip);
if (error)
return error;
}
if (XFS_IS_GQUOTA_ON(mp) && !qi->qi_gquotaip) {
- error = xfs_dqinode_metadir_create(*dpp, XFS_DQTYPE_GROUP,
- &qi->qi_gquotaip);
+ error = xfs_dqinode_metadir_create(qi->qi_dirip,
+ XFS_DQTYPE_GROUP, &qi->qi_gquotaip);
if (error)
return error;
}
if (XFS_IS_PQUOTA_ON(mp) && !qi->qi_pquotaip) {
- error = xfs_dqinode_metadir_create(*dpp, XFS_DQTYPE_PROJ,
- &qi->qi_pquotaip);
+ error = xfs_dqinode_metadir_create(qi->qi_dirip,
+ XFS_DQTYPE_PROJ, &qi->qi_pquotaip);
if (error)
return error;
}
@@ -768,7 +801,6 @@ xfs_qm_init_metadir_qinos(
struct xfs_mount *mp)
{
struct xfs_quotainfo *qi = mp->m_quotainfo;
- struct xfs_inode *dp = NULL;
int error;
if (!xfs_has_quota(mp)) {
@@ -777,20 +809,22 @@ xfs_qm_init_metadir_qinos(
return error;
}
- error = xfs_qm_load_metadir_qinos(mp, qi, &dp);
+ error = xfs_qm_load_metadir_qinos(mp, qi);
if (error)
goto out_err;
- error = xfs_qm_create_metadir_qinos(mp, qi, &dp);
+ error = xfs_qm_create_metadir_qinos(mp, qi);
if (error)
goto out_err;
- xfs_irele(dp);
+ /* The only user of the quota dir inode is online fsck */
+#if !IS_ENABLED(CONFIG_XFS_ONLINE_SCRUB)
+ xfs_irele(qi->qi_dirip);
+ qi->qi_dirip = NULL;
+#endif
return 0;
out_err:
xfs_qm_destroy_quotainos(mp->m_quotainfo);
- if (dp)
- xfs_irele(dp);
return error;
}
@@ -1304,6 +1338,10 @@ xfs_qm_quotacheck_dqadjust(
return error;
}
+ error = xfs_dquot_attach_buf(NULL, dqp);
+ if (error)
+ return error;
+
trace_xfs_dqadjust(dqp);
/*
@@ -1486,11 +1524,17 @@ xfs_qm_flush_one(
goto out_unlock;
}
- error = xfs_qm_dqflush(dqp, &bp);
+ error = xfs_dquot_use_attached_buf(dqp, &bp);
if (error)
goto out_unlock;
+ if (!bp) {
+ error = -EFSCORRUPTED;
+ goto out_unlock;
+ }
- xfs_buf_delwri_queue(bp, buffer_list);
+ error = xfs_qm_dqflush(dqp, bp);
+ if (!error)
+ xfs_buf_delwri_queue(bp, buffer_list);
xfs_buf_relse(bp);
out_unlock:
xfs_dqunlock(dqp);
diff --git a/fs/xfs/xfs_qm.h b/fs/xfs/xfs_qm.h
index e919c7f62f57..35b64bc3a7a8 100644
--- a/fs/xfs/xfs_qm.h
+++ b/fs/xfs/xfs_qm.h
@@ -55,6 +55,7 @@ struct xfs_quotainfo {
struct xfs_inode *qi_uquotaip; /* user quota inode */
struct xfs_inode *qi_gquotaip; /* group quota inode */
struct xfs_inode *qi_pquotaip; /* project quota inode */
+ struct xfs_inode *qi_dirip; /* quota metadir */
struct list_lru qi_lru;
int qi_dquots;
struct mutex qi_quotaofflock;/* to serialize quotaoff */
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 4eda50ae2d1c..0c78f30fa4a3 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -427,19 +427,6 @@ xfs_qm_scall_getquota_fill_qc(
dst->d_ino_timer = 0;
dst->d_rt_spc_timer = 0;
}
-
-#ifdef DEBUG
- if (xfs_dquot_is_enforced(dqp) && dqp->q_id != 0) {
- if ((dst->d_space > dst->d_spc_softlimit) &&
- (dst->d_spc_softlimit > 0)) {
- ASSERT(dst->d_spc_timer != 0);
- }
- if ((dst->d_ino_count > dqp->q_ino.softlimit) &&
- (dqp->q_ino.softlimit > 0)) {
- ASSERT(dst->d_ino_timer != 0);
- }
- }
-#endif
}
/* Return the quota information for the dquot matching id. */
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h
index fa1317cc396c..d7565462af3d 100644
--- a/fs/xfs/xfs_quota.h
+++ b/fs/xfs/xfs_quota.h
@@ -101,7 +101,8 @@ extern void xfs_trans_free_dqinfo(struct xfs_trans *);
extern void xfs_trans_mod_dquot_byino(struct xfs_trans *, struct xfs_inode *,
uint, int64_t);
extern void xfs_trans_apply_dquot_deltas(struct xfs_trans *);
-extern void xfs_trans_unreserve_and_mod_dquots(struct xfs_trans *);
+void xfs_trans_unreserve_and_mod_dquots(struct xfs_trans *tp,
+ bool already_locked);
int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp, struct xfs_inode *ip,
int64_t dblocks, int64_t rblocks, bool force);
extern int xfs_trans_reserve_quota_bydquots(struct xfs_trans *,
@@ -173,7 +174,7 @@ static inline void xfs_trans_mod_dquot_byino(struct xfs_trans *tp,
{
}
#define xfs_trans_apply_dquot_deltas(tp)
-#define xfs_trans_unreserve_and_mod_dquots(tp)
+#define xfs_trans_unreserve_and_mod_dquots(tp, a)
static inline int xfs_trans_reserve_quota_nblks(struct xfs_trans *tp,
struct xfs_inode *ip, int64_t dblocks, int64_t rblocks,
bool force)
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index 0cb534d71119..fcfa6e0eb3ad 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1827,7 +1827,7 @@ xfs_rtallocate_rtg(
* For an allocation to an empty file at offset 0, pick an extent that
* will space things out in the rt area.
*/
- if (bno_hint)
+ if (bno_hint != NULLFSBLOCK)
start = xfs_rtb_to_rtx(args.mp, bno_hint);
else if (!xfs_has_rtgroups(args.mp) && initial_user_data)
start = xfs_rtpick_extent(args.rtg, tp, maxlen);
diff --git a/fs/xfs/xfs_trans.c b/fs/xfs/xfs_trans.c
index 30fbed27cf05..4cd25717c9d1 100644
--- a/fs/xfs/xfs_trans.c
+++ b/fs/xfs/xfs_trans.c
@@ -860,29 +860,17 @@ __xfs_trans_commit(
trace_xfs_trans_commit(tp, _RET_IP_);
- error = xfs_trans_run_precommits(tp);
- if (error) {
- if (tp->t_flags & XFS_TRANS_PERM_LOG_RES)
- xfs_defer_cancel(tp);
- goto out_unreserve;
- }
-
/*
- * Finish deferred items on final commit. Only permanent transactions
- * should ever have deferred ops.
+ * Commit per-transaction changes that are not already tracked through
+ * log items. This can add dirty log items to the transaction.
*/
- WARN_ON_ONCE(!list_empty(&tp->t_dfops) &&
- !(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
- if (!regrant && (tp->t_flags & XFS_TRANS_PERM_LOG_RES)) {
- error = xfs_defer_finish_noroll(&tp);
- if (error)
- goto out_unreserve;
+ if (tp->t_flags & XFS_TRANS_SB_DIRTY)
+ xfs_trans_apply_sb_deltas(tp);
+ xfs_trans_apply_dquot_deltas(tp);
- /* Run precommits from final tx in defer chain. */
- error = xfs_trans_run_precommits(tp);
- if (error)
- goto out_unreserve;
- }
+ error = xfs_trans_run_precommits(tp);
+ if (error)
+ goto out_unreserve;
/*
* If there is nothing to be logged by the transaction,
@@ -907,13 +895,6 @@ __xfs_trans_commit(
ASSERT(tp->t_ticket != NULL);
- /*
- * If we need to update the superblock, then do it now.
- */
- if (tp->t_flags & XFS_TRANS_SB_DIRTY)
- xfs_trans_apply_sb_deltas(tp);
- xfs_trans_apply_dquot_deltas(tp);
-
xlog_cil_commit(log, tp, &commit_seq, regrant);
xfs_trans_free(tp);
@@ -939,7 +920,7 @@ out_unreserve:
* the dqinfo portion to be. All that means is that we have some
* (non-persistent) quota reservations that need to be unreserved.
*/
- xfs_trans_unreserve_and_mod_dquots(tp);
+ xfs_trans_unreserve_and_mod_dquots(tp, true);
if (tp->t_ticket) {
if (regrant && !xlog_is_shutdown(log))
xfs_log_ticket_regrant(log, tp->t_ticket);
@@ -958,6 +939,20 @@ int
xfs_trans_commit(
struct xfs_trans *tp)
{
+ /*
+ * Finish deferred items on final commit. Only permanent transactions
+ * should ever have deferred ops.
+ */
+ WARN_ON_ONCE(!list_empty(&tp->t_dfops) &&
+ !(tp->t_flags & XFS_TRANS_PERM_LOG_RES));
+ if (tp->t_flags & XFS_TRANS_PERM_LOG_RES) {
+ int error = xfs_defer_finish_noroll(&tp);
+ if (error) {
+ xfs_trans_cancel(tp);
+ return error;
+ }
+ }
+
return __xfs_trans_commit(tp, false);
}
@@ -1019,7 +1014,7 @@ xfs_trans_cancel(
}
#endif
xfs_trans_unreserve_and_mod_sb(tp);
- xfs_trans_unreserve_and_mod_dquots(tp);
+ xfs_trans_unreserve_and_mod_dquots(tp, false);
if (tp->t_ticket) {
xfs_log_ticket_ungrant(log, tp->t_ticket);
@@ -1435,5 +1430,8 @@ done:
out_cancel:
xfs_trans_cancel(tp);
+ xfs_iunlock(dp, XFS_ILOCK_EXCL);
+ if (dp != ip)
+ xfs_iunlock(ip, XFS_ILOCK_EXCL);
return error;
}
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c
index 8ede9d099d1f..f56d62dced97 100644
--- a/fs/xfs/xfs_trans_ail.c
+++ b/fs/xfs/xfs_trans_ail.c
@@ -360,7 +360,7 @@ xfsaild_resubmit_item(
/* protected by ail_lock */
list_for_each_entry(lip, &bp->b_li_list, li_bio_list) {
- if (bp->b_flags & _XBF_INODES)
+ if (bp->b_flags & (_XBF_INODES | _XBF_DQUOTS))
clear_bit(XFS_LI_FAILED, &lip->li_flags);
else
xfs_clear_li_failed(lip);
diff --git a/fs/xfs/xfs_trans_dquot.c b/fs/xfs/xfs_trans_dquot.c
index 481ba3dc9f19..713b6d243e56 100644
--- a/fs/xfs/xfs_trans_dquot.c
+++ b/fs/xfs/xfs_trans_dquot.c
@@ -606,6 +606,24 @@ xfs_trans_apply_dquot_deltas(
ASSERT(dqp->q_blk.reserved >= dqp->q_blk.count);
ASSERT(dqp->q_ino.reserved >= dqp->q_ino.count);
ASSERT(dqp->q_rtb.reserved >= dqp->q_rtb.count);
+
+ /*
+ * We've applied the count changes and given back
+ * whatever reservation we didn't use. Zero out the
+ * dqtrx fields.
+ */
+ qtrx->qt_blk_res = 0;
+ qtrx->qt_bcount_delta = 0;
+ qtrx->qt_delbcnt_delta = 0;
+
+ qtrx->qt_rtblk_res = 0;
+ qtrx->qt_rtblk_res_used = 0;
+ qtrx->qt_rtbcount_delta = 0;
+ qtrx->qt_delrtb_delta = 0;
+
+ qtrx->qt_ino_res = 0;
+ qtrx->qt_ino_res_used = 0;
+ qtrx->qt_icount_delta = 0;
}
}
}
@@ -642,7 +660,8 @@ xfs_trans_unreserve_and_mod_dquots_hook(
*/
void
xfs_trans_unreserve_and_mod_dquots(
- struct xfs_trans *tp)
+ struct xfs_trans *tp,
+ bool already_locked)
{
int i, j;
struct xfs_dquot *dqp;
@@ -671,10 +690,12 @@ xfs_trans_unreserve_and_mod_dquots(
* about the number of blocks used field, or deltas.
* Also we don't bother to zero the fields.
*/
- locked = false;
+ locked = already_locked;
if (qtrx->qt_blk_res) {
- xfs_dqlock(dqp);
- locked = true;
+ if (!locked) {
+ xfs_dqlock(dqp);
+ locked = true;
+ }
dqp->q_blk.reserved -=
(xfs_qcnt_t)qtrx->qt_blk_res;
}
@@ -695,7 +716,7 @@ xfs_trans_unreserve_and_mod_dquots(
dqp->q_rtb.reserved -=
(xfs_qcnt_t)qtrx->qt_rtblk_res;
}
- if (locked)
+ if (locked && !already_locked)
xfs_dqunlock(dqp);
}
diff --git a/include/asm-generic/delay.h b/include/asm-generic/delay.h
index 76cf237b6e4c..03b0ec7afca6 100644
--- a/include/asm-generic/delay.h
+++ b/include/asm-generic/delay.h
@@ -75,11 +75,11 @@ static __always_inline void ndelay(unsigned long nsec)
{
if (__builtin_constant_p(nsec)) {
if (nsec >= DELAY_CONST_MAX)
- __bad_udelay();
+ __bad_ndelay();
else
__const_udelay(nsec * NDELAY_CONST_MULT);
} else {
- __udelay(nsec);
+ __ndelay(nsec);
}
}
#define ndelay(x) ndelay(x)
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index eeadbaeccf88..54504013c749 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -95,18 +95,25 @@
* With LTO_CLANG, the linker also splits sections by default, so we need
* these macros to combine the sections during the final link.
*
+ * With AUTOFDO_CLANG and PROPELLER_CLANG, by default, the linker splits
+ * text sections and regroups functions into subsections.
+ *
* RODATA_MAIN is not used because existing code already defines .rodata.x
* sections to be brought in with rodata.
*/
-#if defined(CONFIG_LD_DEAD_CODE_DATA_ELIMINATION) || defined(CONFIG_LTO_CLANG)
+#if defined(CONFIG_LD_DEAD_CODE_DATA_ELIMINATION) || defined(CONFIG_LTO_CLANG) || \
+defined(CONFIG_AUTOFDO_CLANG) || defined(CONFIG_PROPELLER_CLANG)
#define TEXT_MAIN .text .text.[0-9a-zA-Z_]*
+#else
+#define TEXT_MAIN .text
+#endif
+#if defined(CONFIG_LD_DEAD_CODE_DATA_ELIMINATION) || defined(CONFIG_LTO_CLANG)
#define DATA_MAIN .data .data.[0-9a-zA-Z_]* .data..L* .data..compoundliteral* .data.$__unnamed_* .data.$L*
#define SDATA_MAIN .sdata .sdata.[0-9a-zA-Z_]*
#define RODATA_MAIN .rodata .rodata.[0-9a-zA-Z_]* .rodata..L*
#define BSS_MAIN .bss .bss.[0-9a-zA-Z_]* .bss..L* .bss..compoundliteral*
#define SBSS_MAIN .sbss .sbss.[0-9a-zA-Z_]*
#else
-#define TEXT_MAIN .text
#define DATA_MAIN .data
#define SDATA_MAIN .sdata
#define RODATA_MAIN .rodata
@@ -350,9 +357,9 @@
*(.data..decrypted) \
*(.ref.data) \
*(.data..shared_aligned) /* percpu related */ \
- *(.data.unlikely) \
+ *(.data..unlikely) \
__start_once = .; \
- *(.data.once) \
+ *(.data..once) \
__end_once = .; \
STRUCT_ALIGN(); \
*(__tracepoints) \
@@ -549,24 +556,44 @@
__cpuidle_text_end = .; \
__noinstr_text_end = .;
+#define TEXT_SPLIT \
+ __split_text_start = .; \
+ *(.text.split .text.split.[0-9a-zA-Z_]*) \
+ __split_text_end = .;
+
+#define TEXT_UNLIKELY \
+ __unlikely_text_start = .; \
+ *(.text.unlikely .text.unlikely.*) \
+ __unlikely_text_end = .;
+
+#define TEXT_HOT \
+ __hot_text_start = .; \
+ *(.text.hot .text.hot.*) \
+ __hot_text_end = .;
+
/*
* .text section. Map to function alignment to avoid address changes
* during second ld run in second ld pass when generating System.map
*
- * TEXT_MAIN here will match .text.fixup and .text.unlikely if dead
- * code elimination is enabled, so these sections should be converted
- * to use ".." first.
+ * TEXT_MAIN here will match symbols with a fixed pattern (for example,
+ * .text.hot or .text.unlikely) if dead code elimination or
+ * function-section is enabled. Match these symbols first before
+ * TEXT_MAIN to ensure they are grouped together.
+ *
+ * Also placing .text.hot section at the beginning of a page, this
+ * would help the TLB performance.
*/
#define TEXT_TEXT \
ALIGN_FUNCTION(); \
- *(.text.hot .text.hot.*) \
- *(TEXT_MAIN .text.fixup) \
- *(.text.unlikely .text.unlikely.*) \
+ *(.text.asan.* .text.tsan.*) \
*(.text.unknown .text.unknown.*) \
+ TEXT_SPLIT \
+ TEXT_UNLIKELY \
+ . = ALIGN(PAGE_SIZE); \
+ TEXT_HOT \
+ *(TEXT_MAIN .text.fixup) \
NOINSTR_TEXT \
- *(.ref.text) \
- *(.text.asan.* .text.tsan.*)
-
+ *(.ref.text)
/* sched.text is aling to function alignment to secure we have same
* address even at second ld pass when generating System.map */
diff --git a/include/clocksource/hyperv_timer.h b/include/clocksource/hyperv_timer.h
index 6cdc873ac907..aa5233b1eba9 100644
--- a/include/clocksource/hyperv_timer.h
+++ b/include/clocksource/hyperv_timer.h
@@ -38,6 +38,8 @@ extern void hv_remap_tsc_clocksource(void);
extern unsigned long hv_get_tsc_pfn(void);
extern struct ms_hyperv_tsc_page *hv_get_tsc_page(void);
+extern void hv_adj_sched_clock_offset(u64 offset);
+
static __always_inline bool
hv_read_tsc_page_tsc(const struct ms_hyperv_tsc_page *tsc_pg,
u64 *cur_tsc, u64 *time)
diff --git a/include/drm/display/drm_dp_mst_helper.h b/include/drm/display/drm_dp_mst_helper.h
index f6a1cbb0f600..a80ba457a858 100644
--- a/include/drm/display/drm_dp_mst_helper.h
+++ b/include/drm/display/drm_dp_mst_helper.h
@@ -700,6 +700,13 @@ struct drm_dp_mst_topology_mgr {
bool payload_id_table_cleared : 1;
/**
+ * @reset_rx_state: The down request's reply and up request message
+ * receiver state must be reset, after the topology manager got
+ * removed. Protected by @lock.
+ */
+ bool reset_rx_state : 1;
+
+ /**
* @payload_count: The number of currently active payloads in hardware. This value is only
* intended to be used internally by MST helpers for payload tracking, and is only safe to
* read/write from the atomic commit (not check) context.
diff --git a/include/dt-bindings/iio/adc/gehc,pmc-adc.h b/include/dt-bindings/iio/adc/gehc,pmc-adc.h
new file mode 100644
index 000000000000..2f291e3c76ae
--- /dev/null
+++ b/include/dt-bindings/iio/adc/gehc,pmc-adc.h
@@ -0,0 +1,10 @@
+/* SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause */
+
+#ifndef _DT_BINDINGS_IIO_ADC_GEHC_PMC_ADC_H
+#define _DT_BINDINGS_IIO_ADC_GEHC_PMC_ADC_H
+
+/* ADC channel type */
+#define GEHC_PMC_ADC_VOLTAGE 0
+#define GEHC_PMC_ADC_CURRENT 1
+
+#endif
diff --git a/include/dt-bindings/interconnect/qcom,qcs615-rpmh.h b/include/dt-bindings/interconnect/qcom,qcs615-rpmh.h
new file mode 100644
index 000000000000..84ae0d39e73c
--- /dev/null
+++ b/include/dt-bindings/interconnect/qcom,qcs615-rpmh.h
@@ -0,0 +1,136 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_QCS615_H
+#define __DT_BINDINGS_INTERCONNECT_QCOM_QCS615_H
+
+#define MASTER_A1NOC_CFG 1
+#define MASTER_QDSS_BAM 2
+#define MASTER_QSPI 3
+#define MASTER_QUP_0 4
+#define MASTER_BLSP_1 5
+#define MASTER_CNOC_A2NOC 6
+#define MASTER_CRYPTO 7
+#define MASTER_IPA 8
+#define MASTER_EMAC_EVB 9
+#define MASTER_PCIE 10
+#define MASTER_QDSS_ETR 11
+#define MASTER_SDCC_1 12
+#define MASTER_SDCC_2 13
+#define MASTER_UFS_MEM 14
+#define MASTER_USB2 15
+#define MASTER_USB3_0 16
+#define SLAVE_A1NOC_SNOC 17
+#define SLAVE_LPASS_SNOC 18
+#define SLAVE_ANOC_PCIE_SNOC 19
+#define SLAVE_SERVICE_A2NOC 20
+
+#define MASTER_CAMNOC_HF0_UNCOMP 1
+#define MASTER_CAMNOC_HF1_UNCOMP 2
+#define MASTER_CAMNOC_SF_UNCOMP 3
+#define SLAVE_CAMNOC_UNCOMP 4
+
+#define MASTER_SPDM 1
+#define MASTER_SNOC_CNOC 2
+#define MASTER_QDSS_DAP 3
+#define SLAVE_A1NOC_CFG 4
+#define SLAVE_AHB2PHY_EAST 5
+#define SLAVE_AHB2PHY_WEST 6
+#define SLAVE_AOP 7
+#define SLAVE_AOSS 8
+#define SLAVE_CAMERA_CFG 9
+#define SLAVE_CLK_CTL 10
+#define SLAVE_RBCPR_CX_CFG 11
+#define SLAVE_RBCPR_MX_CFG 12
+#define SLAVE_CRYPTO_0_CFG 13
+#define SLAVE_CNOC_DDRSS 14
+#define SLAVE_DISPLAY_CFG 15
+#define SLAVE_EMAC_AVB_CFG 16
+#define SLAVE_GLM 17
+#define SLAVE_GFX3D_CFG 18
+#define SLAVE_IMEM_CFG 19
+#define SLAVE_IPA_CFG 20
+#define SLAVE_CNOC_MNOC_CFG 21
+#define SLAVE_PCIE_CFG 22
+#define SLAVE_PIMEM_CFG 23
+#define SLAVE_PRNG 24
+#define SLAVE_QDSS_CFG 25
+#define SLAVE_QSPI 26
+#define SLAVE_QUP_0 27
+#define SLAVE_QUP_1 28
+#define SLAVE_SDCC_1 29
+#define SLAVE_SDCC_2 30
+#define SLAVE_SNOC_CFG 31
+#define SLAVE_SPDM_WRAPPER 32
+#define SLAVE_TCSR 33
+#define SLAVE_TLMM_EAST 34
+#define SLAVE_TLMM_SOUTH 35
+#define SLAVE_TLMM_WEST 36
+#define SLAVE_UFS_MEM_CFG 37
+#define SLAVE_USB2 38
+#define SLAVE_USB3 39
+#define SLAVE_VENUS_CFG 40
+#define SLAVE_VSENSE_CTRL_CFG 41
+#define SLAVE_CNOC_A2NOC 42
+#define SLAVE_SERVICE_CNOC 43
+
+#define MASTER_CNOC_DC_NOC 1
+#define SLAVE_DC_NOC_GEMNOC 2
+#define SLAVE_LLCC_CFG 3
+
+#define MASTER_APPSS_PROC 1
+#define MASTER_GPU_TCU 2
+#define MASTER_SYS_TCU 3
+#define MASTER_GEM_NOC_CFG 4
+#define MASTER_GFX3D 5
+#define MASTER_MNOC_HF_MEM_NOC 6
+#define MASTER_MNOC_SF_MEM_NOC 7
+#define MASTER_SNOC_GC_MEM_NOC 8
+#define MASTER_SNOC_SF_MEM_NOC 9
+#define SLAVE_MSS_PROC_MS_MPU_CFG 10
+#define SLAVE_GEM_NOC_SNOC 11
+#define SLAVE_LLCC 12
+#define SLAVE_MEM_NOC_PCIE_SNOC 13
+#define SLAVE_SERVICE_GEM_NOC 14
+
+#define MASTER_IPA_CORE 1
+#define SLAVE_IPA_CORE 2
+
+#define MASTER_LLCC 1
+#define SLAVE_EBI1 2
+
+#define MASTER_CNOC_MNOC_CFG 1
+#define MASTER_CAMNOC_HF0 2
+#define MASTER_CAMNOC_HF1 3
+#define MASTER_CAMNOC_SF 4
+#define MASTER_MDP0 5
+#define MASTER_ROTATOR 6
+#define MASTER_VIDEO_P0 7
+#define MASTER_VIDEO_PROC 8
+#define SLAVE_MNOC_SF_MEM_NOC 9
+#define SLAVE_MNOC_HF_MEM_NOC 10
+#define SLAVE_SERVICE_MNOC 11
+
+#define MASTER_SNOC_CFG 1
+#define MASTER_A1NOC_SNOC 2
+#define MASTER_GEM_NOC_SNOC 3
+#define MASTER_GEM_NOC_PCIE_SNOC 4
+#define MASTER_LPASS_ANOC 5
+#define MASTER_ANOC_PCIE_SNOC 6
+#define MASTER_PIMEM 7
+#define MASTER_GIC 8
+#define SLAVE_APPSS 9
+#define SLAVE_SNOC_CNOC 10
+#define SLAVE_SNOC_GEM_NOC_SF 11
+#define SLAVE_SNOC_MEM_NOC_GC 12
+#define SLAVE_IMEM 13
+#define SLAVE_PIMEM 14
+#define SLAVE_SERVICE_SNOC 15
+#define SLAVE_PCIE_0 16
+#define SLAVE_QDSS_STM 17
+#define SLAVE_TCU 18
+
+#endif
+
diff --git a/include/dt-bindings/interconnect/qcom,qcs8300-rpmh.h b/include/dt-bindings/interconnect/qcom,qcs8300-rpmh.h
new file mode 100644
index 000000000000..c5eeafa1b1dd
--- /dev/null
+++ b/include/dt-bindings/interconnect/qcom,qcs8300-rpmh.h
@@ -0,0 +1,189 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_QCS8300_H
+#define __DT_BINDINGS_INTERCONNECT_QCOM_QCS8300_H
+
+#define MASTER_QUP_3 0
+#define MASTER_EMAC 1
+#define MASTER_SDC 2
+#define MASTER_UFS_MEM 3
+#define MASTER_USB2 4
+#define MASTER_USB3_0 5
+#define SLAVE_A1NOC_SNOC 6
+
+#define MASTER_QDSS_BAM 0
+#define MASTER_QUP_0 1
+#define MASTER_QUP_1 2
+#define MASTER_CNOC_A2NOC 3
+#define MASTER_CRYPTO_CORE0 4
+#define MASTER_CRYPTO_CORE1 5
+#define MASTER_IPA 6
+#define MASTER_QDSS_ETR_0 7
+#define MASTER_QDSS_ETR_1 8
+#define SLAVE_A2NOC_SNOC 9
+
+#define MASTER_QUP_CORE_0 0
+#define MASTER_QUP_CORE_1 1
+#define MASTER_QUP_CORE_3 2
+#define SLAVE_QUP_CORE_0 3
+#define SLAVE_QUP_CORE_1 4
+#define SLAVE_QUP_CORE_3 5
+
+#define MASTER_GEM_NOC_CNOC 0
+#define MASTER_GEM_NOC_PCIE_SNOC 1
+#define SLAVE_AHB2PHY_2 2
+#define SLAVE_AHB2PHY_3 3
+#define SLAVE_ANOC_THROTTLE_CFG 4
+#define SLAVE_AOSS 5
+#define SLAVE_APPSS 6
+#define SLAVE_BOOT_ROM 7
+#define SLAVE_CAMERA_CFG 8
+#define SLAVE_CAMERA_NRT_THROTTLE_CFG 9
+#define SLAVE_CAMERA_RT_THROTTLE_CFG 10
+#define SLAVE_CLK_CTL 11
+#define SLAVE_CDSP_CFG 12
+#define SLAVE_RBCPR_CX_CFG 13
+#define SLAVE_RBCPR_MMCX_CFG 14
+#define SLAVE_RBCPR_MX_CFG 15
+#define SLAVE_CPR_NSPCX 16
+#define SLAVE_CPR_NSPHMX 17
+#define SLAVE_CRYPTO_0_CFG 18
+#define SLAVE_CX_RDPM 19
+#define SLAVE_DISPLAY_CFG 20
+#define SLAVE_DISPLAY_RT_THROTTLE_CFG 21
+#define SLAVE_EMAC_CFG 22
+#define SLAVE_GP_DSP0_CFG 23
+#define SLAVE_GPDSP0_THROTTLE_CFG 24
+#define SLAVE_GPU_TCU_THROTTLE_CFG 25
+#define SLAVE_GFX3D_CFG 26
+#define SLAVE_HWKM 27
+#define SLAVE_IMEM_CFG 28
+#define SLAVE_IPA_CFG 29
+#define SLAVE_IPC_ROUTER_CFG 30
+#define SLAVE_LPASS 31
+#define SLAVE_LPASS_THROTTLE_CFG 32
+#define SLAVE_MX_RDPM 33
+#define SLAVE_MXC_RDPM 34
+#define SLAVE_PCIE_0_CFG 35
+#define SLAVE_PCIE_1_CFG 36
+#define SLAVE_PCIE_TCU_THROTTLE_CFG 37
+#define SLAVE_PCIE_THROTTLE_CFG 38
+#define SLAVE_PDM 39
+#define SLAVE_PIMEM_CFG 40
+#define SLAVE_PKA_WRAPPER_CFG 41
+#define SLAVE_QDSS_CFG 42
+#define SLAVE_QM_CFG 43
+#define SLAVE_QM_MPU_CFG 44
+#define SLAVE_QUP_0 45
+#define SLAVE_QUP_1 46
+#define SLAVE_QUP_3 47
+#define SLAVE_SAIL_THROTTLE_CFG 48
+#define SLAVE_SDC1 49
+#define SLAVE_SECURITY 50
+#define SLAVE_SNOC_THROTTLE_CFG 51
+#define SLAVE_TCSR 52
+#define SLAVE_TLMM 53
+#define SLAVE_TSC_CFG 54
+#define SLAVE_UFS_MEM_CFG 55
+#define SLAVE_USB2 56
+#define SLAVE_USB3_0 57
+#define SLAVE_VENUS_CFG 58
+#define SLAVE_VENUS_CVP_THROTTLE_CFG 59
+#define SLAVE_VENUS_V_CPU_THROTTLE_CFG 60
+#define SLAVE_VENUS_VCODEC_THROTTLE_CFG 61
+#define SLAVE_DDRSS_CFG 62
+#define SLAVE_GPDSP_NOC_CFG 63
+#define SLAVE_CNOC_MNOC_HF_CFG 64
+#define SLAVE_CNOC_MNOC_SF_CFG 65
+#define SLAVE_PCIE_ANOC_CFG 66
+#define SLAVE_SNOC_CFG 67
+#define SLAVE_BOOT_IMEM 68
+#define SLAVE_IMEM 69
+#define SLAVE_PIMEM 70
+#define SLAVE_PCIE_0 71
+#define SLAVE_PCIE_1 72
+#define SLAVE_QDSS_STM 73
+#define SLAVE_TCU 74
+
+#define MASTER_CNOC_DC_NOC 0
+#define SLAVE_LLCC_CFG 1
+#define SLAVE_GEM_NOC_CFG 2
+
+#define MASTER_GPU_TCU 0
+#define MASTER_PCIE_TCU 1
+#define MASTER_SYS_TCU 2
+#define MASTER_APPSS_PROC 3
+#define MASTER_COMPUTE_NOC 4
+#define MASTER_GEM_NOC_CFG 5
+#define MASTER_GPDSP_SAIL 6
+#define MASTER_GFX3D 7
+#define MASTER_MNOC_HF_MEM_NOC 8
+#define MASTER_MNOC_SF_MEM_NOC 9
+#define MASTER_ANOC_PCIE_GEM_NOC 10
+#define MASTER_SNOC_GC_MEM_NOC 11
+#define MASTER_SNOC_SF_MEM_NOC 12
+#define SLAVE_GEM_NOC_CNOC 13
+#define SLAVE_LLCC 14
+#define SLAVE_GEM_NOC_PCIE_CNOC 15
+#define SLAVE_SERVICE_GEM_NOC_1 16
+#define SLAVE_SERVICE_GEM_NOC_2 17
+#define SLAVE_SERVICE_GEM_NOC 18
+#define SLAVE_SERVICE_GEM_NOC2 19
+
+#define MASTER_SAILSS_MD0 0
+#define MASTER_DSP0 1
+#define SLAVE_GP_DSP_SAIL_NOC 2
+
+#define MASTER_CNOC_LPASS_AG_NOC 0
+#define MASTER_LPASS_PROC 1
+#define SLAVE_LPASS_CORE_CFG 2
+#define SLAVE_LPASS_LPI_CFG 3
+#define SLAVE_LPASS_MPU_CFG 4
+#define SLAVE_LPASS_TOP_CFG 5
+#define SLAVE_LPASS_SNOC 6
+#define SLAVE_SERVICES_LPASS_AML_NOC 7
+#define SLAVE_SERVICE_LPASS_AG_NOC 8
+
+#define MASTER_LLCC 0
+#define SLAVE_EBI1 1
+
+#define MASTER_CAMNOC_HF 0
+#define MASTER_CAMNOC_ICP 1
+#define MASTER_CAMNOC_SF 2
+#define MASTER_MDP0 3
+#define MASTER_MDP1 4
+#define MASTER_CNOC_MNOC_HF_CFG 5
+#define MASTER_CNOC_MNOC_SF_CFG 6
+#define MASTER_VIDEO_P0 7
+#define MASTER_VIDEO_PROC 8
+#define MASTER_VIDEO_V_PROC 9
+#define SLAVE_MNOC_HF_MEM_NOC 10
+#define SLAVE_MNOC_SF_MEM_NOC 11
+#define SLAVE_SERVICE_MNOC_HF 12
+#define SLAVE_SERVICE_MNOC_SF 13
+
+#define MASTER_CDSP_NOC_CFG 0
+#define MASTER_CDSP_PROC 1
+#define SLAVE_HCP_A 2
+#define SLAVE_CDSP_MEM_NOC 3
+#define SLAVE_SERVICE_NSP_NOC 4
+
+#define MASTER_PCIE_0 0
+#define MASTER_PCIE_1 1
+#define SLAVE_ANOC_PCIE_GEM_NOC 2
+
+#define MASTER_GIC_AHB 0
+#define MASTER_A1NOC_SNOC 1
+#define MASTER_A2NOC_SNOC 2
+#define MASTER_LPASS_ANOC 3
+#define MASTER_SNOC_CFG 4
+#define MASTER_PIMEM 5
+#define MASTER_GIC 6
+#define SLAVE_SNOC_GEM_NOC_GC 7
+#define SLAVE_SNOC_GEM_NOC_SF 8
+#define SLAVE_SERVICE_SNOC 9
+
+#endif
diff --git a/include/dt-bindings/interconnect/qcom,sar2130p-rpmh.h b/include/dt-bindings/interconnect/qcom,sar2130p-rpmh.h
new file mode 100644
index 000000000000..aec7cbb7cd70
--- /dev/null
+++ b/include/dt-bindings/interconnect/qcom,sar2130p-rpmh.h
@@ -0,0 +1,137 @@
+/* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */
+/*
+ * Copyright (c) 2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2024, Linaro Ltd.
+ */
+
+#ifndef __DT_BINDINGS_INTERCONNECT_QCOM_SAR2130P_H
+#define __DT_BINDINGS_INTERCONNECT_QCOM_SAR2130P_H
+
+#define MASTER_QUP_CORE_0 0
+#define MASTER_QUP_CORE_1 1
+#define SLAVE_QUP_CORE_0 2
+#define SLAVE_QUP_CORE_1 3
+
+#define MASTER_GEM_NOC_CNOC 0
+#define MASTER_GEM_NOC_PCIE_SNOC 1
+#define MASTER_QDSS_DAP 2
+#define SLAVE_AHB2PHY_SOUTH 3
+#define SLAVE_AOSS 4
+#define SLAVE_CAMERA_CFG 5
+#define SLAVE_CLK_CTL 6
+#define SLAVE_CDSP_CFG 7
+#define SLAVE_RBCPR_CX_CFG 8
+#define SLAVE_RBCPR_MMCX_CFG 9
+#define SLAVE_RBCPR_MXA_CFG 10
+#define SLAVE_RBCPR_MXC_CFG 11
+#define SLAVE_CPR_NSPCX 12
+#define SLAVE_CRYPTO_0_CFG 13
+#define SLAVE_CX_RDPM 14
+#define SLAVE_DISPLAY_CFG 15
+#define SLAVE_GFX3D_CFG 16
+#define SLAVE_IMEM_CFG 17
+#define SLAVE_IPC_ROUTER_CFG 18
+#define SLAVE_LPASS 19
+#define SLAVE_MX_RDPM 20
+#define SLAVE_PCIE_0_CFG 21
+#define SLAVE_PCIE_1_CFG 22
+#define SLAVE_PDM 23
+#define SLAVE_PIMEM_CFG 24
+#define SLAVE_PRNG 25
+#define SLAVE_QDSS_CFG 26
+#define SLAVE_QSPI_0 27
+#define SLAVE_QUP_0 28
+#define SLAVE_QUP_1 29
+#define SLAVE_SDCC_1 30
+#define SLAVE_TCSR 31
+#define SLAVE_TLMM 32
+#define SLAVE_TME_CFG 33
+#define SLAVE_USB3_0 34
+#define SLAVE_VENUS_CFG 35
+#define SLAVE_VSENSE_CTRL_CFG 36
+#define SLAVE_WLAN_Q6_CFG 37
+#define SLAVE_DDRSS_CFG 38
+#define SLAVE_CNOC_MNOC_CFG 39
+#define SLAVE_SNOC_CFG 40
+#define SLAVE_IMEM 41
+#define SLAVE_PIMEM 42
+#define SLAVE_SERVICE_CNOC 43
+#define SLAVE_PCIE_0 44
+#define SLAVE_PCIE_1 45
+#define SLAVE_QDSS_STM 46
+#define SLAVE_TCU 47
+
+#define MASTER_GPU_TCU 0
+#define MASTER_SYS_TCU 1
+#define MASTER_APPSS_PROC 2
+#define MASTER_GFX3D 3
+#define MASTER_MNOC_HF_MEM_NOC 4
+#define MASTER_MNOC_SF_MEM_NOC 5
+#define MASTER_COMPUTE_NOC 6
+#define MASTER_ANOC_PCIE_GEM_NOC 7
+#define MASTER_SNOC_GC_MEM_NOC 8
+#define MASTER_SNOC_SF_MEM_NOC 9
+#define MASTER_WLAN_Q6 10
+#define SLAVE_GEM_NOC_CNOC 11
+#define SLAVE_LLCC 12
+#define SLAVE_MEM_NOC_PCIE_SNOC 13
+
+#define MASTER_CNOC_LPASS_AG_NOC 0
+#define MASTER_LPASS_PROC 1
+#define SLAVE_LPASS_CORE_CFG 2
+#define SLAVE_LPASS_LPI_CFG 3
+#define SLAVE_LPASS_MPU_CFG 4
+#define SLAVE_LPASS_TOP_CFG 5
+#define SLAVE_LPASS_SNOC 6
+#define SLAVE_SERVICES_LPASS_AML_NOC 7
+#define SLAVE_SERVICE_LPASS_AG_NOC 8
+
+#define MASTER_LLCC 0
+#define SLAVE_EBI1 1
+
+#define MASTER_CAMNOC_HF 0
+#define MASTER_CAMNOC_ICP 1
+#define MASTER_CAMNOC_SF 2
+#define MASTER_LSR 3
+#define MASTER_MDP 4
+#define MASTER_CNOC_MNOC_CFG 5
+#define MASTER_VIDEO 6
+#define MASTER_VIDEO_CV_PROC 7
+#define MASTER_VIDEO_PROC 8
+#define MASTER_VIDEO_V_PROC 9
+#define SLAVE_MNOC_HF_MEM_NOC 10
+#define SLAVE_MNOC_SF_MEM_NOC 11
+#define SLAVE_SERVICE_MNOC 12
+
+#define MASTER_CDSP_NOC_CFG 0
+#define MASTER_CDSP_PROC 1
+#define SLAVE_CDSP_MEM_NOC 2
+#define SLAVE_SERVICE_NSP_NOC 3
+
+#define MASTER_PCIE_0 0
+#define MASTER_PCIE_1 1
+#define SLAVE_ANOC_PCIE_GEM_NOC 2
+
+#define MASTER_GIC_AHB 0
+#define MASTER_QDSS_BAM 1
+#define MASTER_QSPI_0 2
+#define MASTER_QUP_0 3
+#define MASTER_QUP_1 4
+#define MASTER_A2NOC_SNOC 5
+#define MASTER_CNOC_DATAPATH 6
+#define MASTER_LPASS_ANOC 7
+#define MASTER_SNOC_CFG 8
+#define MASTER_CRYPTO 9
+#define MASTER_PIMEM 10
+#define MASTER_GIC 11
+#define MASTER_QDSS_ETR 12
+#define MASTER_QDSS_ETR_1 13
+#define MASTER_SDCC_1 14
+#define MASTER_USB3_0 15
+#define SLAVE_A2NOC_SNOC 16
+#define SLAVE_SNOC_GEM_NOC_GC 17
+#define SLAVE_SNOC_GEM_NOC_SF 18
+#define SLAVE_SERVICE_SNOC 19
+
+#endif
diff --git a/include/kunit/visibility.h b/include/kunit/visibility.h
index efff77b58dd6..7c34c8ffcf3b 100644
--- a/include/kunit/visibility.h
+++ b/include/kunit/visibility.h
@@ -20,12 +20,11 @@
/**
* EXPORT_SYMBOL_IF_KUNIT(symbol) - Exports symbol into
* EXPORTED_FOR_KUNIT_TESTING namespace only if CONFIG_KUNIT is
- * enabled. Must use MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING)
+ * enabled. Must use MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING")
* in test file in order to use symbols.
* @symbol: the symbol identifier to export
*/
- #define EXPORT_SYMBOL_IF_KUNIT(symbol) EXPORT_SYMBOL_NS(symbol, \
- EXPORTED_FOR_KUNIT_TESTING)
+ #define EXPORT_SYMBOL_IF_KUNIT(symbol) EXPORT_SYMBOL_NS(symbol, "EXPORTED_FOR_KUNIT_TESTING")
#else
#define VISIBLE_IF_KUNIT static
#define EXPORT_SYMBOL_IF_KUNIT(symbol)
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index f5172549f9ba..3a8ccfda34d2 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -26,7 +26,6 @@
#define VGIC_NR_SGIS 16
#define VGIC_NR_PPIS 16
#define VGIC_NR_PRIVATE_IRQS (VGIC_NR_SGIS + VGIC_NR_PPIS)
-#define VGIC_MAX_PRIVATE (VGIC_NR_PRIVATE_IRQS - 1)
#define VGIC_MAX_SPI 1019
#define VGIC_MAX_RESERVED 1023
#define VGIC_MIN_LPI 8192
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 05f39fbfa485..6adcd1b92b20 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -40,7 +40,7 @@ struct irq_domain_ops;
#include <asm/acpi.h>
#ifdef CONFIG_ACPI_TABLE_LIB
-#define EXPORT_SYMBOL_ACPI_LIB(x) EXPORT_SYMBOL_NS_GPL(x, ACPI)
+#define EXPORT_SYMBOL_ACPI_LIB(x) EXPORT_SYMBOL_NS_GPL(x, "ACPI")
#define __init_or_acpilib
#define __initdata_or_acpilib
#else
diff --git a/include/linux/alcor_pci.h b/include/linux/alcor_pci.h
index c4a0b23846d8..dcb1d37dabc2 100644
--- a/include/linux/alcor_pci.h
+++ b/include/linux/alcor_pci.h
@@ -11,6 +11,7 @@
#define ALCOR_SD_CARD 0
#define ALCOR_MS_CARD 1
+#define DRV_NAME_ALCOR_PCI "alcor_pci"
#define DRV_NAME_ALCOR_PCI_SDMMC "alcor_sdmmc"
#define DRV_NAME_ALCOR_PCI_MS "alcor_ms"
diff --git a/include/linux/alloc_tag.h b/include/linux/alloc_tag.h
index 7c0786bdf9af..0bbbe537c5f9 100644
--- a/include/linux/alloc_tag.h
+++ b/include/linux/alloc_tag.h
@@ -63,7 +63,12 @@ static inline void set_codetag_empty(union codetag_ref *ref)
#else /* CONFIG_MEM_ALLOC_PROFILING_DEBUG */
static inline bool is_codetag_empty(union codetag_ref *ref) { return false; }
-static inline void set_codetag_empty(union codetag_ref *ref) {}
+
+static inline void set_codetag_empty(union codetag_ref *ref)
+{
+ if (ref)
+ ref->ct = NULL;
+}
#endif /* CONFIG_MEM_ALLOC_PROFILING_DEBUG */
@@ -135,7 +140,7 @@ static inline struct alloc_tag_counters alloc_tag_read(struct alloc_tag *tag)
#ifdef CONFIG_MEM_ALLOC_PROFILING_DEBUG
static inline void alloc_tag_add_check(union codetag_ref *ref, struct alloc_tag *tag)
{
- WARN_ONCE(ref && ref->ct,
+ WARN_ONCE(ref && ref->ct && !is_codetag_empty(ref),
"alloc_tag was not cleared (got tag for %s:%u)\n",
ref->ct->filename, ref->ct->lineno);
diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
index dda2f3ea89cb..9946276aff73 100644
--- a/include/linux/amba/bus.h
+++ b/include/linux/amba/bus.h
@@ -121,6 +121,7 @@ extern const struct bus_type amba_bustype;
#ifdef CONFIG_ARM_AMBA
int __amba_driver_register(struct amba_driver *, struct module *);
void amba_driver_unregister(struct amba_driver *);
+bool dev_is_amba(const struct device *dev);
#else
static inline int __amba_driver_register(struct amba_driver *drv,
struct module *owner)
@@ -130,6 +131,10 @@ static inline int __amba_driver_register(struct amba_driver *drv,
static inline void amba_driver_unregister(struct amba_driver *drv)
{
}
+static inline bool dev_is_amba(const struct device *dev)
+{
+ return false;
+}
#endif
struct amba_device *amba_device_alloc(const char *, resource_size_t, size_t);
diff --git a/include/linux/arm_ffa.h b/include/linux/arm_ffa.h
index a28e2a6a13d0..74169dd0f659 100644
--- a/include/linux/arm_ffa.h
+++ b/include/linux/arm_ffa.h
@@ -166,9 +166,12 @@ static inline void *ffa_dev_get_drvdata(struct ffa_device *fdev)
return dev_get_drvdata(&fdev->dev);
}
+struct ffa_partition_info;
+
#if IS_REACHABLE(CONFIG_ARM_FFA_TRANSPORT)
-struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
- const struct ffa_ops *ops);
+struct ffa_device *
+ffa_device_register(const struct ffa_partition_info *part_info,
+ const struct ffa_ops *ops);
void ffa_device_unregister(struct ffa_device *ffa_dev);
int ffa_driver_register(struct ffa_driver *driver, struct module *owner,
const char *mod_name);
@@ -176,9 +179,9 @@ void ffa_driver_unregister(struct ffa_driver *driver);
bool ffa_device_is_valid(struct ffa_device *ffa_dev);
#else
-static inline
-struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
- const struct ffa_ops *ops)
+static inline struct ffa_device *
+ffa_device_register(const struct ffa_partition_info *part_info,
+ const struct ffa_ops *ops)
{
return NULL;
}
diff --git a/include/linux/auxiliary_bus.h b/include/linux/auxiliary_bus.h
index 31762324bcc9..65dd7f154374 100644
--- a/include/linux/auxiliary_bus.h
+++ b/include/linux/auxiliary_bus.h
@@ -269,8 +269,4 @@ void auxiliary_driver_unregister(struct auxiliary_driver *auxdrv);
#define module_auxiliary_driver(__auxiliary_driver) \
module_driver(__auxiliary_driver, auxiliary_driver_register, auxiliary_driver_unregister)
-struct auxiliary_device *auxiliary_find_device(struct device *start,
- const void *data,
- device_match_t match);
-
#endif /* _AUXILIARY_BUS_H_ */
diff --git a/include/linux/bio.h b/include/linux/bio.h
index 60830a6a5939..7a1b3b1a8fed 100644
--- a/include/linux/bio.h
+++ b/include/linux/bio.h
@@ -423,7 +423,7 @@ void __bio_add_page(struct bio *bio, struct page *page,
void bio_add_folio_nofail(struct bio *bio, struct folio *folio, size_t len,
size_t off);
int bio_iov_iter_get_pages(struct bio *bio, struct iov_iter *iter);
-void bio_iov_bvec_set(struct bio *bio, struct iov_iter *iter);
+void bio_iov_bvec_set(struct bio *bio, const struct iov_iter *iter);
void __bio_release_pages(struct bio *bio, bool mark_dirty);
extern void bio_set_pages_dirty(struct bio *bio);
extern void bio_check_pages_dirty(struct bio *bio);
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index a1fd0ddce5cf..378d3a1a22fc 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -200,8 +200,6 @@ struct gendisk {
spinlock_t zone_wplugs_lock;
struct mempool_s *zone_wplugs_pool;
struct hlist_head *zone_wplugs_hash;
- struct list_head zone_wplugs_err_list;
- struct work_struct zone_wplugs_work;
struct workqueue_struct *zone_wplugs_wq;
#endif /* CONFIG_BLK_DEV_ZONED */
@@ -333,6 +331,10 @@ typedef unsigned int __bitwise blk_features_t;
#define BLK_FEAT_RAID_PARTIAL_STRIPES_EXPENSIVE \
((__force blk_features_t)(1u << 15))
+/* stacked device can/does support atomic writes */
+#define BLK_FEAT_ATOMIC_WRITES_STACKED \
+ ((__force blk_features_t)(1u << 16))
+
/*
* Flags automatically inherited when stacking limits.
*/
@@ -775,13 +777,13 @@ static inline void bdev_clear_flag(struct block_device *bdev, unsigned flag)
atomic_andnot(flag, &bdev->__bd_flags);
}
-static inline int get_disk_ro(struct gendisk *disk)
+static inline bool get_disk_ro(struct gendisk *disk)
{
return bdev_test_flag(disk->part0, BD_READ_ONLY) ||
test_bit(GD_READ_ONLY, &disk->state);
}
-static inline int bdev_read_only(struct block_device *bdev)
+static inline bool bdev_read_only(struct block_device *bdev)
{
return bdev_test_flag(bdev, BD_READ_ONLY) || get_disk_ro(bdev->bd_disk);
}
@@ -1261,7 +1263,7 @@ static inline unsigned int queue_io_min(const struct request_queue *q)
return q->limits.io_min;
}
-static inline int bdev_io_min(struct block_device *bdev)
+static inline unsigned int bdev_io_min(struct block_device *bdev)
{
return queue_io_min(bdev_get_queue(bdev));
}
@@ -1271,7 +1273,7 @@ static inline unsigned int queue_io_opt(const struct request_queue *q)
return q->limits.io_opt;
}
-static inline int bdev_io_opt(struct block_device *bdev)
+static inline unsigned int bdev_io_opt(struct block_device *bdev)
{
return queue_io_opt(bdev_get_queue(bdev));
}
@@ -1417,7 +1419,10 @@ static inline bool bdev_zone_is_seq(struct block_device *bdev, sector_t sector)
return is_seq;
}
-static inline int queue_dma_alignment(const struct request_queue *q)
+int blk_zone_issue_zeroout(struct block_device *bdev, sector_t sector,
+ sector_t nr_sects, gfp_t gfp_mask);
+
+static inline unsigned int queue_dma_alignment(const struct request_queue *q)
{
return q->limits.dma_alignment;
}
@@ -1458,12 +1463,13 @@ static inline bool bdev_iter_is_aligned(struct block_device *bdev,
bdev_logical_block_size(bdev) - 1);
}
-static inline int blk_lim_dma_alignment_and_pad(struct queue_limits *lim)
+static inline unsigned int
+blk_lim_dma_alignment_and_pad(struct queue_limits *lim)
{
return lim->dma_alignment | lim->dma_pad_mask;
}
-static inline int blk_rq_aligned(struct request_queue *q, unsigned long addr,
+static inline bool blk_rq_aligned(struct request_queue *q, unsigned long addr,
unsigned int len)
{
unsigned int alignment = blk_lim_dma_alignment_and_pad(&q->limits);
@@ -1581,7 +1587,6 @@ static inline void bio_end_io_acct(struct bio *bio, unsigned long start_time)
return bio_end_io_acct_remapped(bio, start_time, bio->bi_bdev);
}
-int bdev_read_only(struct block_device *bdev);
int set_blocksize(struct file *file, int size);
int lookup_bdev(const char *pathname, dev_t *dev);
diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index eaee2a819f4c..9ef57f6f584a 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -1527,6 +1527,7 @@ struct bpf_prog_aux {
bool is_extended; /* true if extended by freplace program */
bool jits_use_priv_stack;
bool priv_stack_requested;
+ bool changes_pkt_data;
u64 prog_array_member_cnt; /* counts how many times as member of prog_array */
struct mutex ext_mutex; /* mutex for is_extended and prog_array_member_cnt */
struct bpf_arena *arena;
@@ -2193,26 +2194,25 @@ bpf_prog_run_array(const struct bpf_prog_array *array,
* rcu-protected dynamically sized maps.
*/
static __always_inline u32
-bpf_prog_run_array_uprobe(const struct bpf_prog_array __rcu *array_rcu,
+bpf_prog_run_array_uprobe(const struct bpf_prog_array *array,
const void *ctx, bpf_prog_run_fn run_prog)
{
const struct bpf_prog_array_item *item;
const struct bpf_prog *prog;
- const struct bpf_prog_array *array;
struct bpf_run_ctx *old_run_ctx;
struct bpf_trace_run_ctx run_ctx;
u32 ret = 1;
might_fault();
+ RCU_LOCKDEP_WARN(!rcu_read_lock_trace_held(), "no rcu lock held");
+
+ if (unlikely(!array))
+ return ret;
- rcu_read_lock_trace();
migrate_disable();
run_ctx.is_uprobe = true;
- array = rcu_dereference_check(array_rcu, rcu_read_lock_trace_held());
- if (unlikely(!array))
- goto out;
old_run_ctx = bpf_set_run_ctx(&run_ctx.run_ctx);
item = &array->items[0];
while ((prog = READ_ONCE(item->prog))) {
@@ -2227,9 +2227,7 @@ bpf_prog_run_array_uprobe(const struct bpf_prog_array __rcu *array_rcu,
rcu_read_unlock();
}
bpf_reset_run_ctx(old_run_ctx);
-out:
migrate_enable();
- rcu_read_unlock_trace();
return ret;
}
@@ -2591,10 +2589,10 @@ int dev_map_enqueue(struct bpf_dtab_netdev *dst, struct xdp_frame *xdpf,
int dev_map_enqueue_multi(struct xdp_frame *xdpf, struct net_device *dev_rx,
struct bpf_map *map, bool exclude_ingress);
int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
- struct bpf_prog *xdp_prog);
+ const struct bpf_prog *xdp_prog);
int dev_map_redirect_multi(struct net_device *dev, struct sk_buff *skb,
- struct bpf_prog *xdp_prog, struct bpf_map *map,
- bool exclude_ingress);
+ const struct bpf_prog *xdp_prog,
+ struct bpf_map *map, bool exclude_ingress);
void __cpu_map_flush(struct list_head *flush_list);
int cpu_map_enqueue(struct bpf_cpu_map_entry *rcpu, struct xdp_frame *xdpf,
@@ -2864,15 +2862,15 @@ struct sk_buff;
static inline int dev_map_generic_redirect(struct bpf_dtab_netdev *dst,
struct sk_buff *skb,
- struct bpf_prog *xdp_prog)
+ const struct bpf_prog *xdp_prog)
{
return 0;
}
static inline
int dev_map_redirect_multi(struct net_device *dev, struct sk_buff *skb,
- struct bpf_prog *xdp_prog, struct bpf_map *map,
- bool exclude_ingress)
+ const struct bpf_prog *xdp_prog,
+ struct bpf_map *map, bool exclude_ingress)
{
return 0;
}
@@ -3516,10 +3514,4 @@ static inline bool bpf_is_subprog(const struct bpf_prog *prog)
return prog->aux->func_idx != 0;
}
-static inline bool bpf_prog_is_raw_tp(const struct bpf_prog *prog)
-{
- return prog->type == BPF_PROG_TYPE_TRACING &&
- prog->expected_attach_type == BPF_TRACE_RAW_TP;
-}
-
#endif /* _LINUX_BPF_H */
diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h
index f4290c179bee..48b7b2eeb7e2 100644
--- a/include/linux/bpf_verifier.h
+++ b/include/linux/bpf_verifier.h
@@ -659,6 +659,7 @@ struct bpf_subprog_info {
bool args_cached: 1;
/* true if bpf_fastcall stack region is used by functions that can't be inlined */
bool keep_fastcall_stack: 1;
+ bool changes_pkt_data: 1;
enum priv_stack_mode priv_stack_mode;
u8 arg_cnt;
diff --git a/include/linux/cacheinfo.h b/include/linux/cacheinfo.h
index 108060612bb8..7ad736538649 100644
--- a/include/linux/cacheinfo.h
+++ b/include/linux/cacheinfo.h
@@ -155,8 +155,14 @@ static inline int get_cpu_cacheinfo_id(int cpu, int level)
#ifndef CONFIG_ARCH_HAS_CPU_CACHE_ALIASING
#define cpu_dcache_is_aliasing() false
+#define cpu_icache_is_aliasing() cpu_dcache_is_aliasing()
#else
#include <asm/cachetype.h>
+
+#ifndef cpu_icache_is_aliasing
+#define cpu_icache_is_aliasing() cpu_dcache_is_aliasing()
+#endif
+
#endif
#endif /* _LINUX_CACHEINFO_H */
diff --git a/include/linux/ceph/ceph_fs.h b/include/linux/ceph/ceph_fs.h
index ee1d0e5f9789..2d7d86f0290d 100644
--- a/include/linux/ceph/ceph_fs.h
+++ b/include/linux/ceph/ceph_fs.h
@@ -808,7 +808,7 @@ struct ceph_mds_caps {
struct ceph_mds_cap_peer {
__le64 cap_id;
- __le32 seq;
+ __le32 issue_seq;
__le32 mseq;
__le32 mds;
__u8 flags;
@@ -822,7 +822,7 @@ struct ceph_mds_cap_release {
struct ceph_mds_cap_item {
__le64 ino;
__le64 cap_id;
- __le32 migrate_seq, seq;
+ __le32 migrate_seq, issue_seq;
} __attribute__ ((packed));
#define CEPH_MDS_LEASE_REVOKE 1 /* mds -> client */
diff --git a/include/linux/ceph/libceph.h b/include/linux/ceph/libceph.h
index 15fb566d3f46..733e7f93db66 100644
--- a/include/linux/ceph/libceph.h
+++ b/include/linux/ceph/libceph.h
@@ -317,12 +317,6 @@ extern void ceph_release_page_vector(struct page **pages, int num_pages);
extern void ceph_put_page_vector(struct page **pages, int num_pages,
bool dirty);
extern struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags);
-extern int ceph_copy_user_to_page_vector(struct page **pages,
- const void __user *data,
- loff_t off, size_t len);
-extern void ceph_copy_to_page_vector(struct page **pages,
- const void *data,
- loff_t off, size_t len);
extern void ceph_copy_from_page_vector(struct page **pages,
void *data,
loff_t off, size_t len);
diff --git a/include/linux/ceph/osd_client.h b/include/linux/ceph/osd_client.h
index d7941478158c..d55b30057a45 100644
--- a/include/linux/ceph/osd_client.h
+++ b/include/linux/ceph/osd_client.h
@@ -626,8 +626,6 @@ int ceph_osdc_notify(struct ceph_osd_client *osdc,
u32 timeout,
struct page ***preply_pages,
size_t *preply_len);
-int ceph_osdc_watch_check(struct ceph_osd_client *osdc,
- struct ceph_osd_linger_request *lreq);
int ceph_osdc_list_watchers(struct ceph_osd_client *osdc,
struct ceph_object_id *oid,
struct ceph_object_locator *oloc,
diff --git a/include/linux/ceph/pagelist.h b/include/linux/ceph/pagelist.h
index 5dead8486fd8..879bec0863aa 100644
--- a/include/linux/ceph/pagelist.h
+++ b/include/linux/ceph/pagelist.h
@@ -17,12 +17,6 @@ struct ceph_pagelist {
refcount_t refcnt;
};
-struct ceph_pagelist_cursor {
- struct ceph_pagelist *pl; /* pagelist, for error checking */
- struct list_head *page_lru; /* page in list */
- size_t room; /* room remaining to reset to */
-};
-
struct ceph_pagelist *ceph_pagelist_alloc(gfp_t gfp_flags);
extern void ceph_pagelist_release(struct ceph_pagelist *pl);
@@ -33,12 +27,6 @@ extern int ceph_pagelist_reserve(struct ceph_pagelist *pl, size_t space);
extern int ceph_pagelist_free_reserve(struct ceph_pagelist *pl);
-extern void ceph_pagelist_set_cursor(struct ceph_pagelist *pl,
- struct ceph_pagelist_cursor *c);
-
-extern int ceph_pagelist_truncate(struct ceph_pagelist *pl,
- struct ceph_pagelist_cursor *c);
-
static inline int ceph_pagelist_encode_64(struct ceph_pagelist *pl, u64 v)
{
__le64 ev = cpu_to_le64(v);
diff --git a/include/linux/cleanup.h b/include/linux/cleanup.h
index 966fcc5ff8ef..ec00e3f7af2b 100644
--- a/include/linux/cleanup.h
+++ b/include/linux/cleanup.h
@@ -273,12 +273,6 @@ static inline class_##_name##_t class_##_name##ext##_constructor(_init_args) \
* an anonymous instance of the (guard) class, not recommended for
* conditional locks.
*
- * if_not_guard(name, args...) { <error handling> }:
- * convenience macro for conditional guards that calls the statement that
- * follows only if the lock was not acquired (typically an error return).
- *
- * Only for conditional locks.
- *
* scoped_guard (name, args...) { }:
* similar to CLASS(name, scope)(args), except the variable (with the
* explicit name 'scope') is declard in a for-loop such that its scope is
@@ -350,14 +344,6 @@ _label: \
#define scoped_cond_guard(_name, _fail, args...) \
__scoped_cond_guard(_name, _fail, __UNIQUE_ID(label), args)
-#define __if_not_guard(_name, _id, args...) \
- BUILD_BUG_ON(!__is_cond_ptr(_name)); \
- CLASS(_name, _id)(args); \
- if (!__guard_ptr(_name)(&_id))
-
-#define if_not_guard(_name, args...) \
- __if_not_guard(_name, __UNIQUE_ID(guard), args)
-
/*
* Additional helper macros for generating lock guards with types, either for
* locks that don't have a native type (eg. RCU, preempt) or those that need a
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index ef1b16da6ad5..65b7c41471c3 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -49,6 +49,7 @@ struct module;
* @archdata: Optional arch-specific data
* @max_cycles: Maximum safe cycle value which won't overflow on
* multiplication
+ * @max_raw_delta: Maximum safe delta value for negative motion detection
* @name: Pointer to clocksource name
* @list: List head for registration (internal)
* @freq_khz: Clocksource frequency in khz.
@@ -109,6 +110,7 @@ struct clocksource {
struct arch_clocksource_data archdata;
#endif
u64 max_cycles;
+ u64 max_raw_delta;
const char *name;
struct list_head list;
u32 freq_khz;
diff --git a/include/linux/compiler.h b/include/linux/compiler.h
index 469a64dd6495..240c632c5b95 100644
--- a/include/linux/compiler.h
+++ b/include/linux/compiler.h
@@ -216,28 +216,43 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
#endif /* __KERNEL__ */
+/**
+ * offset_to_ptr - convert a relative memory offset to an absolute pointer
+ * @off: the address of the 32-bit offset value
+ */
+static inline void *offset_to_ptr(const int *off)
+{
+ return (void *)((unsigned long)off + *off);
+}
+
+#endif /* __ASSEMBLY__ */
+
+#ifdef CONFIG_64BIT
+#define ARCH_SEL(a,b) a
+#else
+#define ARCH_SEL(a,b) b
+#endif
+
/*
* Force the compiler to emit 'sym' as a symbol, so that we can reference
* it from inline assembler. Necessary in case 'sym' could be inlined
* otherwise, or eliminated entirely due to lack of references that are
* visible to the compiler.
*/
-#define ___ADDRESSABLE(sym, __attrs) \
- static void * __used __attrs \
+#define ___ADDRESSABLE(sym, __attrs) \
+ static void * __used __attrs \
__UNIQUE_ID(__PASTE(__addressable_,sym)) = (void *)(uintptr_t)&sym;
+
#define __ADDRESSABLE(sym) \
___ADDRESSABLE(sym, __section(".discard.addressable"))
-/**
- * offset_to_ptr - convert a relative memory offset to an absolute pointer
- * @off: the address of the 32-bit offset value
- */
-static inline void *offset_to_ptr(const int *off)
-{
- return (void *)((unsigned long)off + *off);
-}
+#define __ADDRESSABLE_ASM(sym) \
+ .pushsection .discard.addressable,"aw"; \
+ .align ARCH_SEL(8,4); \
+ ARCH_SEL(.quad, .long) __stringify(sym); \
+ .popsection;
-#endif /* __ASSEMBLY__ */
+#define __ADDRESSABLE_ASM_STR(sym) __stringify(__ADDRESSABLE_ASM(sym))
#ifdef __CHECKER__
#define __BUILD_BUG_ON_ZERO_MSG(e, msg) (0)
diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h
index b137fdb56093..346251bf1026 100644
--- a/include/linux/dmaengine.h
+++ b/include/linux/dmaengine.h
@@ -84,7 +84,7 @@ enum dma_transfer_direction {
DMA_TRANS_NONE,
};
-/**
+/*
* Interleaved Transfer Request
* ----------------------------
* A chunk is collection of contiguous bytes to be transferred.
@@ -223,7 +223,7 @@ enum sum_check_bits {
};
/**
- * enum pq_check_flags - result of async_{xor,pq}_zero_sum operations
+ * enum sum_check_flags - result of async_{xor,pq}_zero_sum operations
* @SUM_CHECK_P_RESULT - 1 if xor zero sum error, 0 otherwise
* @SUM_CHECK_Q_RESULT - 1 if reed-solomon zero sum error, 0 otherwise
*/
@@ -286,7 +286,7 @@ typedef struct { DECLARE_BITMAP(bits, DMA_TX_TYPE_END); } dma_cap_mask_t;
* pointer to the engine's metadata area
* 4. Read out the metadata from the pointer
*
- * Note: the two mode is not compatible and clients must use one mode for a
+ * Warning: the two modes are not compatible and clients must use one mode for a
* descriptor.
*/
enum dma_desc_metadata_mode {
@@ -594,9 +594,13 @@ struct dma_descriptor_metadata_ops {
* @phys: physical address of the descriptor
* @chan: target channel for this operation
* @tx_submit: accept the descriptor, assign ordered cookie and mark the
+ * @desc_free: driver's callback function to free a resusable descriptor
+ * after completion
* descriptor pending. To be pushed on .issue_pending() call
* @callback: routine to call after this operation is complete
+ * @callback_result: error result from a DMA transaction
* @callback_param: general parameter to pass to the callback routine
+ * @unmap: hook for generic DMA unmap data
* @desc_metadata_mode: core managed metadata mode to protect mixed use of
* DESC_METADATA_CLIENT or DESC_METADATA_ENGINE. Otherwise
* DESC_METADATA_NONE
@@ -827,6 +831,9 @@ struct dma_filter {
* @device_prep_dma_memset: prepares a memset operation
* @device_prep_dma_memset_sg: prepares a memset operation over a scatter list
* @device_prep_dma_interrupt: prepares an end of chain interrupt operation
+ * @device_prep_peripheral_dma_vec: prepares a scatter-gather DMA transfer,
+ * where the address and size of each segment is located in one entry of
+ * the dma_vec array.
* @device_prep_slave_sg: prepares a slave dma operation
* @device_prep_dma_cyclic: prepare a cyclic dma operation suitable for audio.
* The function takes a buffer of size buf_len. The callback function will
diff --git a/include/linux/dsa/ocelot.h b/include/linux/dsa/ocelot.h
index 6fbfbde68a37..620a3260fc08 100644
--- a/include/linux/dsa/ocelot.h
+++ b/include/linux/dsa/ocelot.h
@@ -15,6 +15,7 @@
struct ocelot_skb_cb {
struct sk_buff *clone;
unsigned int ptp_class; /* valid only for clones */
+ unsigned long ptp_tx_time; /* valid only for clones */
u32 tstamp_lo;
u8 ptp_cmd;
u8 ts_id;
diff --git a/include/linux/eeprom_93cx6.h b/include/linux/eeprom_93cx6.h
index c860c72a921d..3a485cc0e0fa 100644
--- a/include/linux/eeprom_93cx6.h
+++ b/include/linux/eeprom_93cx6.h
@@ -11,6 +11,8 @@
Supported chipsets: 93c46, 93c56 and 93c66.
*/
+#include <linux/bits.h>
+
/*
* EEPROM operation defines.
*/
@@ -34,6 +36,7 @@
* @register_write(struct eeprom_93cx6 *eeprom): handler to
* write to the eeprom register by using all reg_* fields.
* @width: eeprom width, should be one of the PCI_EEPROM_WIDTH_* defines
+ * @quirks: eeprom or controller quirks
* @drive_data: Set if we're driving the data line.
* @reg_data_in: register field to indicate data input
* @reg_data_out: register field to indicate data output
@@ -50,6 +53,9 @@ struct eeprom_93cx6 {
void (*register_write)(struct eeprom_93cx6 *eeprom);
int width;
+ unsigned int quirks;
+/* Some EEPROMs require an extra clock cycle before reading */
+#define PCI_EEPROM_QUIRK_EXTRA_READ_CYCLE BIT(0)
char drive_data;
char reg_data_in;
@@ -71,3 +77,8 @@ extern void eeprom_93cx6_wren(struct eeprom_93cx6 *eeprom, bool enable);
extern void eeprom_93cx6_write(struct eeprom_93cx6 *eeprom,
u8 addr, u16 data);
+
+static inline bool has_quirk_extra_read_cycle(struct eeprom_93cx6 *eeprom)
+{
+ return eeprom->quirks & PCI_EEPROM_QUIRK_EXTRA_READ_CYCLE;
+}
diff --git a/include/linux/etherdevice.h b/include/linux/etherdevice.h
index ecf203f01034..9a1eacf35d37 100644
--- a/include/linux/etherdevice.h
+++ b/include/linux/etherdevice.h
@@ -81,7 +81,7 @@ static const u8 eth_ipv6_mcast_addr_base[ETH_ALEN] __aligned(2) =
* is_link_local_ether_addr - Determine if given Ethernet address is link-local
* @addr: Pointer to a six-byte array containing the Ethernet address
*
- * Return true if address is link local reserved addr (01:80:c2:00:00:0X) per
+ * Return: true if address is link local reserved addr (01:80:c2:00:00:0X) per
* IEEE 802.1Q 8.6.3 Frame filtering.
*
* Please note: addr must be aligned to u16.
@@ -104,7 +104,7 @@ static inline bool is_link_local_ether_addr(const u8 *addr)
* is_zero_ether_addr - Determine if give Ethernet address is all zeros.
* @addr: Pointer to a six-byte array containing the Ethernet address
*
- * Return true if the address is all zeroes.
+ * Return: true if the address is all zeroes.
*
* Please note: addr must be aligned to u16.
*/
@@ -123,7 +123,7 @@ static inline bool is_zero_ether_addr(const u8 *addr)
* is_multicast_ether_addr - Determine if the Ethernet address is a multicast.
* @addr: Pointer to a six-byte array containing the Ethernet address
*
- * Return true if the address is a multicast address.
+ * Return: true if the address is a multicast address.
* By definition the broadcast address is also a multicast address.
*/
static inline bool is_multicast_ether_addr(const u8 *addr)
@@ -157,7 +157,7 @@ static inline bool is_multicast_ether_addr_64bits(const u8 *addr)
* is_local_ether_addr - Determine if the Ethernet address is locally-assigned one (IEEE 802).
* @addr: Pointer to a six-byte array containing the Ethernet address
*
- * Return true if the address is a local address.
+ * Return: true if the address is a local address.
*/
static inline bool is_local_ether_addr(const u8 *addr)
{
@@ -168,7 +168,7 @@ static inline bool is_local_ether_addr(const u8 *addr)
* is_broadcast_ether_addr - Determine if the Ethernet address is broadcast
* @addr: Pointer to a six-byte array containing the Ethernet address
*
- * Return true if the address is the broadcast address.
+ * Return: true if the address is the broadcast address.
*
* Please note: addr must be aligned to u16.
*/
@@ -183,7 +183,7 @@ static inline bool is_broadcast_ether_addr(const u8 *addr)
* is_unicast_ether_addr - Determine if the Ethernet address is unicast
* @addr: Pointer to a six-byte array containing the Ethernet address
*
- * Return true if the address is a unicast address.
+ * Return: true if the address is a unicast address.
*/
static inline bool is_unicast_ether_addr(const u8 *addr)
{
@@ -197,7 +197,7 @@ static inline bool is_unicast_ether_addr(const u8 *addr)
* Check that the Ethernet address (MAC) is not 00:00:00:00:00:00, is not
* a multicast address, and is not FF:FF:FF:FF:FF:FF.
*
- * Return true if the address is valid.
+ * Return: true if the address is valid.
*
* Please note: addr must be aligned to u16.
*/
@@ -214,7 +214,7 @@ static inline bool is_valid_ether_addr(const u8 *addr)
*
* Check that the value from the Ethertype/length field is a valid Ethertype.
*
- * Return true if the valid is an 802.3 supported Ethertype.
+ * Return: true if the valid is an 802.3 supported Ethertype.
*/
static inline bool eth_proto_is_802_3(__be16 proto)
{
@@ -458,7 +458,7 @@ static inline bool ether_addr_is_ip_mcast(const u8 *addr)
* ether_addr_to_u64 - Convert an Ethernet address into a u64 value.
* @addr: Pointer to a six-byte array containing the Ethernet address
*
- * Return a u64 value of the address
+ * Return: a u64 value of the address
*/
static inline u64 ether_addr_to_u64(const u8 *addr)
{
diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h
index b8b935b52603..f711bfd75c4d 100644
--- a/include/linux/ethtool.h
+++ b/include/linux/ethtool.h
@@ -257,7 +257,7 @@ struct ethtool_link_ksettings {
* @mode : one of the ETHTOOL_LINK_MODE_*_BIT
* (not atomic, no bound checking)
*
- * Returns true/false.
+ * Returns: true/false.
*/
#define ethtool_link_ksettings_test_link_mode(ptr, name, mode) \
test_bit(ETHTOOL_LINK_MODE_ ## mode ## _BIT, (ptr)->link_modes.name)
@@ -711,6 +711,7 @@ struct ethtool_rxfh_param {
* @cmd: command number = %ETHTOOL_GET_TS_INFO
* @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags
* @phc_index: device index of the associated PHC, or -1 if there is none
+ * @phc_qualifier: qualifier of the associated PHC
* @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values
* @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values
*/
@@ -718,6 +719,7 @@ struct kernel_ethtool_ts_info {
u32 cmd;
u32 so_timestamping;
int phc_index;
+ enum hwtstamp_provider_qualifier phc_qualifier;
enum hwtstamp_tx_types tx_types;
enum hwtstamp_rx_filters rx_filters;
};
@@ -749,6 +751,7 @@ struct kernel_ethtool_ts_info {
* @rss_context argument to @create_rxfh_context and friends.
* @supported_coalesce_params: supported types of interrupt coalescing.
* @supported_ring_params: supported ring params.
+ * @supported_hwtstamp_qualifiers: bitfield of supported hwtstamp qualifier.
* @get_drvinfo: Report driver/device information. Modern drivers no
* longer have to implement this callback. Most fields are
* correctly filled in by the core using system information, or
@@ -966,6 +969,7 @@ struct ethtool_ops {
u32 rxfh_max_num_contexts;
u32 supported_coalesce_params;
u32 supported_ring_params;
+ u32 supported_hwtstamp_qualifiers;
void (*get_drvinfo)(struct net_device *, struct ethtool_drvinfo *);
int (*get_regs_len)(struct net_device *);
void (*get_regs)(struct net_device *, struct ethtool_regs *, void *);
@@ -1199,7 +1203,7 @@ ethtool_params_from_link_mode(struct ethtool_link_ksettings *link_ksettings,
* @dev: pointer to net_device structure
* @vclock_index: pointer to pointer of vclock index
*
- * Return number of phc vclocks
+ * Return: number of phc vclocks
*/
int ethtool_get_phc_vclocks(struct net_device *dev, int **vclock_index);
@@ -1253,7 +1257,7 @@ static inline int ethtool_mm_frag_size_min_to_add(u32 val_min, u32 *val_add,
* ethtool_get_ts_info_by_layer - Obtains time stamping capabilities from the MAC or PHY layer.
* @dev: pointer to net_device structure
* @info: buffer to hold the result
- * Returns zero on success, non-zero otherwise.
+ * Returns: zero on success, non-zero otherwise.
*/
int ethtool_get_ts_info_by_layer(struct net_device *dev,
struct kernel_ethtool_ts_info *info);
diff --git a/include/linux/export.h b/include/linux/export.h
index 0bbd02fd351d..2633df4d31e6 100644
--- a/include/linux/export.h
+++ b/include/linux/export.h
@@ -60,14 +60,14 @@
#endif
#ifdef DEFAULT_SYMBOL_NAMESPACE
-#define _EXPORT_SYMBOL(sym, license) __EXPORT_SYMBOL(sym, license, __stringify(DEFAULT_SYMBOL_NAMESPACE))
+#define _EXPORT_SYMBOL(sym, license) __EXPORT_SYMBOL(sym, license, DEFAULT_SYMBOL_NAMESPACE)
#else
#define _EXPORT_SYMBOL(sym, license) __EXPORT_SYMBOL(sym, license, "")
#endif
#define EXPORT_SYMBOL(sym) _EXPORT_SYMBOL(sym, "")
#define EXPORT_SYMBOL_GPL(sym) _EXPORT_SYMBOL(sym, "GPL")
-#define EXPORT_SYMBOL_NS(sym, ns) __EXPORT_SYMBOL(sym, "", __stringify(ns))
-#define EXPORT_SYMBOL_NS_GPL(sym, ns) __EXPORT_SYMBOL(sym, "GPL", __stringify(ns))
+#define EXPORT_SYMBOL_NS(sym, ns) __EXPORT_SYMBOL(sym, "", ns)
+#define EXPORT_SYMBOL_NS_GPL(sym, ns) __EXPORT_SYMBOL(sym, "GPL", ns)
#endif /* _LINUX_EXPORT_H */
diff --git a/include/linux/filter.h b/include/linux/filter.h
index 3a21947f2fd4..a3ea46281595 100644
--- a/include/linux/filter.h
+++ b/include/linux/filter.h
@@ -1122,7 +1122,7 @@ bool bpf_jit_supports_insn(struct bpf_insn *insn, bool in_arena);
bool bpf_jit_supports_private_stack(void);
u64 bpf_arch_uaddress_limit(void);
void arch_bpf_stack_walk(bool (*consume_fn)(void *cookie, u64 ip, u64 sp, u64 bp), void *cookie);
-bool bpf_helper_changes_pkt_data(void *func);
+bool bpf_helper_changes_pkt_data(enum bpf_func_id func_id);
static inline bool bpf_dump_raw_ok(const struct cred *cred)
{
@@ -1179,17 +1179,18 @@ static inline int xdp_ok_fwd_dev(const struct net_device *fwd,
* This does not appear to be a real limitation for existing software.
*/
int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
- struct xdp_buff *xdp, struct bpf_prog *prog);
+ struct xdp_buff *xdp, const struct bpf_prog *prog);
int xdp_do_redirect(struct net_device *dev,
struct xdp_buff *xdp,
- struct bpf_prog *prog);
+ const struct bpf_prog *prog);
int xdp_do_redirect_frame(struct net_device *dev,
struct xdp_buff *xdp,
struct xdp_frame *xdpf,
- struct bpf_prog *prog);
+ const struct bpf_prog *prog);
void xdp_do_flush(void);
-void bpf_warn_invalid_xdp_action(struct net_device *dev, struct bpf_prog *prog, u32 act);
+void bpf_warn_invalid_xdp_action(const struct net_device *dev,
+ const struct bpf_prog *prog, u32 act);
#ifdef CONFIG_INET
struct sock *bpf_run_sk_reuseport(struct sock_reuseport *reuse, struct sock *sk,
diff --git a/include/linux/fortify-string.h b/include/linux/fortify-string.h
index 0d99bf11d260..e4ce1cae03bf 100644
--- a/include/linux/fortify-string.h
+++ b/include/linux/fortify-string.h
@@ -616,6 +616,12 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size,
return false;
}
+/*
+ * To work around what seems to be an optimizer bug, the macro arguments
+ * need to have const copies or the values end up changed by the time they
+ * reach fortify_warn_once(). See commit 6f7630b1b5bc ("fortify: Capture
+ * __bos() results in const temp vars") for more details.
+ */
#define __fortify_memcpy_chk(p, q, size, p_size, q_size, \
p_size_field, q_size_field, op) ({ \
const size_t __fortify_size = (size_t)(size); \
@@ -623,6 +629,8 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size,
const size_t __q_size = (q_size); \
const size_t __p_size_field = (p_size_field); \
const size_t __q_size_field = (q_size_field); \
+ /* Keep a mutable version of the size for the final copy. */ \
+ size_t __copy_size = __fortify_size; \
fortify_warn_once(fortify_memcpy_chk(__fortify_size, __p_size, \
__q_size, __p_size_field, \
__q_size_field, FORTIFY_FUNC_ ##op), \
@@ -630,7 +638,11 @@ __FORTIFY_INLINE bool fortify_memcpy_chk(__kernel_size_t size,
__fortify_size, \
"field \"" #p "\" at " FILE_LINE, \
__p_size_field); \
- __underlying_##op(p, q, __fortify_size); \
+ /* Hide only the run-time size from value range tracking to */ \
+ /* silence compile-time false positive bounds warnings. */ \
+ if (!__builtin_constant_p(__copy_size)) \
+ OPTIMIZER_HIDE_VAR(__copy_size); \
+ __underlying_##op(p, q, __copy_size); \
})
/*
diff --git a/include/linux/fw_table.h b/include/linux/fw_table.h
index 3ff4c277296f..9bd605b87c4c 100644
--- a/include/linux/fw_table.h
+++ b/include/linux/fw_table.h
@@ -54,7 +54,7 @@ int cdat_table_parse(enum acpi_cdat_type type,
#define EXPORT_SYMBOL_FWTBL_LIB(x) EXPORT_SYMBOL_ACPI_LIB(x)
#define __init_or_fwtbl_lib __init_or_acpilib
#else
-#define EXPORT_SYMBOL_FWTBL_LIB(x) EXPORT_SYMBOL_NS_GPL(x, CXL)
+#define EXPORT_SYMBOL_FWTBL_LIB(x) EXPORT_SYMBOL_NS_GPL(x, "CXL")
#define __init_or_fwtbl_lib
#endif
diff --git a/include/linux/hid-sensor-ids.h b/include/linux/hid-sensor-ids.h
index 6730ee900ee1..8a03d9696b1c 100644
--- a/include/linux/hid-sensor-ids.h
+++ b/include/linux/hid-sensor-ids.h
@@ -30,6 +30,8 @@
#define HID_USAGE_SENSOR_PROX 0x200011
#define HID_USAGE_SENSOR_DATA_PRESENCE 0x2004b0
#define HID_USAGE_SENSOR_HUMAN_PRESENCE 0x2004b1
+#define HID_USAGE_SENSOR_HUMAN_PROXIMITY 0x2004b2
+#define HID_USAGE_SENSOR_HUMAN_ATTENTION 0x2004bd
/* Pressure (200031) */
#define HID_USAGE_SENSOR_PRESSURE 0x200031
diff --git a/include/linux/hid_bpf.h b/include/linux/hid_bpf.h
index a6876ab29004..a2e47dbcf82c 100644
--- a/include/linux/hid_bpf.h
+++ b/include/linux/hid_bpf.h
@@ -78,7 +78,7 @@ struct hid_ops {
const struct bus_type *bus_type;
};
-extern struct hid_ops *hid_ops;
+extern const struct hid_ops *hid_ops;
/**
* struct hid_bpf_ops - A BPF struct_ops of callbacks allowing to attach HID-BPF
diff --git a/include/linux/highmem.h b/include/linux/highmem.h
index 6e452bd8e7e3..5c6bea81a90e 100644
--- a/include/linux/highmem.h
+++ b/include/linux/highmem.h
@@ -224,7 +224,13 @@ static inline
struct folio *vma_alloc_zeroed_movable_folio(struct vm_area_struct *vma,
unsigned long vaddr)
{
- return vma_alloc_folio(GFP_HIGHUSER_MOVABLE | __GFP_ZERO, 0, vma, vaddr);
+ struct folio *folio;
+
+ folio = vma_alloc_folio(GFP_HIGHUSER_MOVABLE, 0, vma, vaddr);
+ if (folio && user_alloc_needs_zeroing())
+ clear_user_highpage(&folio->page, vaddr);
+
+ return folio;
}
#endif
diff --git a/include/linux/hyperv.h b/include/linux/hyperv.h
index 22c22fb91042..02a226bcf0ed 100644
--- a/include/linux/hyperv.h
+++ b/include/linux/hyperv.h
@@ -1559,6 +1559,7 @@ struct hv_util_service {
void *channel;
void (*util_cb)(void *);
int (*util_init)(struct hv_util_service *);
+ int (*util_init_transport)(void);
void (*util_deinit)(void);
int (*util_pre_suspend)(void);
int (*util_pre_resume)(void);
diff --git a/include/linux/i2c-of-prober.h b/include/linux/i2c-of-prober.h
new file mode 100644
index 000000000000..bb6d47f50ee5
--- /dev/null
+++ b/include/linux/i2c-of-prober.h
@@ -0,0 +1,140 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Definitions for the Linux I2C OF component prober
+ *
+ * Copyright (C) 2024 Google LLC
+ */
+
+#ifndef _LINUX_I2C_OF_PROBER_H
+#define _LINUX_I2C_OF_PROBER_H
+
+#include <linux/kconfig.h>
+#include <linux/types.h>
+
+struct device;
+struct device_node;
+
+/**
+ * struct i2c_of_probe_ops - I2C OF component prober callbacks
+ *
+ * A set of callbacks to be used by i2c_of_probe_component().
+ *
+ * All callbacks are optional. Callbacks are called only once per run, and are
+ * used in the order they are defined in this structure.
+ *
+ * All callbacks that have return values shall return %0 on success,
+ * or a negative error number on failure.
+ *
+ * The @dev parameter passed to the callbacks is the same as @dev passed to
+ * i2c_of_probe_component(). It should only be used for dev_printk() calls
+ * and nothing else, especially not managed device resource (devres) APIs.
+ */
+struct i2c_of_probe_ops {
+ /**
+ * @enable: Retrieve and enable resources so that the components respond to probes.
+ *
+ * It is OK for this callback to return -EPROBE_DEFER since the intended use includes
+ * retrieving resources and enables them. Resources should be reverted to their initial
+ * state and released before returning if this fails.
+ */
+ int (*enable)(struct device *dev, struct device_node *bus_node, void *data);
+
+ /**
+ * @cleanup_early: Release exclusive resources prior to calling probe() on a
+ * detected component.
+ *
+ * Only called if a matching component is actually found. If none are found,
+ * resources that would have been released in this callback should be released in
+ * @free_resourcs_late instead.
+ */
+ void (*cleanup_early)(struct device *dev, void *data);
+
+ /**
+ * @cleanup: Opposite of @enable to balance refcounts and free resources after probing.
+ *
+ * Should check if resources were already freed by @cleanup_early.
+ */
+ void (*cleanup)(struct device *dev, void *data);
+};
+
+/**
+ * struct i2c_of_probe_cfg - I2C OF component prober configuration
+ * @ops: Callbacks for the prober to use.
+ * @type: A string to match the device node name prefix to probe for.
+ */
+struct i2c_of_probe_cfg {
+ const struct i2c_of_probe_ops *ops;
+ const char *type;
+};
+
+#if IS_ENABLED(CONFIG_OF_DYNAMIC)
+
+int i2c_of_probe_component(struct device *dev, const struct i2c_of_probe_cfg *cfg, void *ctx);
+
+/**
+ * DOC: I2C OF component prober simple helpers
+ *
+ * Components such as trackpads are commonly connected to a devices baseboard
+ * with a 6-pin ribbon cable. That gives at most one voltage supply and one
+ * GPIO (commonly a "enable" or "reset" line) besides the I2C bus, interrupt
+ * pin, and common ground. Touchscreens, while integrated into the display
+ * panel's connection, typically have the same set of connections.
+ *
+ * A simple set of helpers are provided here for use with the I2C OF component
+ * prober. This implementation targets such components, allowing for at most
+ * one regulator supply.
+ *
+ * The following helpers are provided:
+ * * i2c_of_probe_simple_enable()
+ * * i2c_of_probe_simple_cleanup_early()
+ * * i2c_of_probe_simple_cleanup()
+ */
+
+/**
+ * struct i2c_of_probe_simple_opts - Options for simple I2C component prober callbacks
+ * @res_node_compatible: Compatible string of device node to retrieve resources from.
+ * @supply_name: Name of regulator supply.
+ * @gpio_name: Name of GPIO. NULL if no GPIO line is used. Empty string ("") if GPIO
+ * line is unnamed.
+ * @post_power_on_delay_ms: Delay after regulators are powered on. Passed to msleep().
+ * @post_gpio_config_delay_ms: Delay after GPIO is configured. Passed to msleep().
+ * @gpio_assert_to_enable: %true if GPIO should be asserted, i.e. set to logical high,
+ * to enable the component.
+ *
+ * This describes power sequences common for the class of components supported by the
+ * simple component prober:
+ * * @gpio_name is configured to the non-active setting according to @gpio_assert_to_enable.
+ * * @supply_name regulator supply is enabled.
+ * * Wait for @post_power_on_delay_ms to pass.
+ * * @gpio_name is configured to the active setting according to @gpio_assert_to_enable.
+ * * Wait for @post_gpio_config_delay_ms to pass.
+ */
+struct i2c_of_probe_simple_opts {
+ const char *res_node_compatible;
+ const char *supply_name;
+ const char *gpio_name;
+ unsigned int post_power_on_delay_ms;
+ unsigned int post_gpio_config_delay_ms;
+ bool gpio_assert_to_enable;
+};
+
+struct gpio_desc;
+struct regulator;
+
+struct i2c_of_probe_simple_ctx {
+ /* public: provided by user before helpers are used. */
+ const struct i2c_of_probe_simple_opts *opts;
+ /* private: internal fields for helpers. */
+ struct regulator *supply;
+ struct gpio_desc *gpiod;
+};
+
+int i2c_of_probe_simple_enable(struct device *dev, struct device_node *bus_node, void *data);
+void i2c_of_probe_simple_cleanup_early(struct device *dev, void *data);
+void i2c_of_probe_simple_cleanup(struct device *dev, void *data);
+
+extern struct i2c_of_probe_ops i2c_of_probe_simple_ops;
+
+#endif /* IS_ENABLED(CONFIG_OF_DYNAMIC) */
+
+#endif /* _LINUX_I2C_OF_PROBER_H */
diff --git a/include/linux/if_vlan.h b/include/linux/if_vlan.h
index c1645c86eed9..38456b42cdb5 100644
--- a/include/linux/if_vlan.h
+++ b/include/linux/if_vlan.h
@@ -176,6 +176,7 @@ struct netpoll;
* @real_dev_addr: address of underlying netdevice
* @dent: proc dir entry
* @vlan_pcpu_stats: ptr to percpu rx stats
+ * @netpoll: netpoll instance "propagated" down to @real_dev
*/
struct vlan_dev_priv {
unsigned int nr_ingress_mappings;
@@ -310,7 +311,7 @@ static inline bool vlan_uses_dev(const struct net_device *dev)
* eth_type_vlan - check for valid vlan ether type.
* @ethertype: ether type to check
*
- * Returns true if the ether type is a vlan ether type.
+ * Returns: true if the ether type is a vlan ether type.
*/
static inline bool eth_type_vlan(__be16 ethertype)
{
@@ -341,9 +342,9 @@ static inline bool vlan_hw_offload_capable(netdev_features_t features,
* @mac_len: MAC header length including outer vlan headers
*
* Inserts the VLAN tag into @skb as part of the payload at offset mac_len
- * Returns error if skb_cow_head fails.
- *
* Does not change skb->protocol so this function can be used during receive.
+ *
+ * Returns: error if skb_cow_head fails.
*/
static inline int __vlan_insert_inner_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci,
@@ -390,9 +391,9 @@ static inline int __vlan_insert_inner_tag(struct sk_buff *skb,
* @vlan_tci: VLAN TCI to insert
*
* Inserts the VLAN tag into @skb as part of the payload
- * Returns error if skb_cow_head fails.
- *
* Does not change skb->protocol so this function can be used during receive.
+ *
+ * Returns: error if skb_cow_head fails.
*/
static inline int __vlan_insert_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
@@ -414,6 +415,8 @@ static inline int __vlan_insert_tag(struct sk_buff *skb,
* doesn't have to worry about freeing the original skb.
*
* Does not change skb->protocol so this function can be used during receive.
+ *
+ * Return: modified @skb on success, NULL on error (@skb is freed).
*/
static inline struct sk_buff *vlan_insert_inner_tag(struct sk_buff *skb,
__be16 vlan_proto,
@@ -443,6 +446,8 @@ static inline struct sk_buff *vlan_insert_inner_tag(struct sk_buff *skb,
* doesn't have to worry about freeing the original skb.
*
* Does not change skb->protocol so this function can be used during receive.
+ *
+ * Return: modified @skb on success, NULL on error (@skb is freed).
*/
static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
__be16 vlan_proto, u16 vlan_tci)
@@ -461,6 +466,8 @@ static inline struct sk_buff *vlan_insert_tag(struct sk_buff *skb,
*
* Following the skb_unshare() example, in case of error, the calling function
* doesn't have to worry about freeing the original skb.
+ *
+ * Return: modified @skb on success, NULL on error (@skb is freed).
*/
static inline struct sk_buff *vlan_insert_tag_set_proto(struct sk_buff *skb,
__be16 vlan_proto,
@@ -533,7 +540,7 @@ static inline void __vlan_hwaccel_put_tag(struct sk_buff *skb,
* @skb: skbuff to query
* @vlan_tci: buffer to store value
*
- * Returns error if the skb is not of VLAN type
+ * Returns: error if the skb is not of VLAN type
*/
static inline int __vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
{
@@ -551,7 +558,7 @@ static inline int __vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
* @skb: skbuff to query
* @vlan_tci: buffer to store value
*
- * Returns error if @skb->vlan_tci is not set correctly
+ * Returns: error if @skb->vlan_tci is not set correctly
*/
static inline int __vlan_hwaccel_get_tag(const struct sk_buff *skb,
u16 *vlan_tci)
@@ -570,7 +577,7 @@ static inline int __vlan_hwaccel_get_tag(const struct sk_buff *skb,
* @skb: skbuff to query
* @vlan_tci: buffer to store value
*
- * Returns error if the skb is not VLAN tagged
+ * Returns: error if the skb is not VLAN tagged
*/
static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
{
@@ -582,16 +589,19 @@ static inline int vlan_get_tag(const struct sk_buff *skb, u16 *vlan_tci)
}
/**
- * vlan_get_protocol - get protocol EtherType.
+ * __vlan_get_protocol_offset() - get protocol EtherType.
* @skb: skbuff to query
* @type: first vlan protocol
+ * @mac_offset: MAC offset
* @depth: buffer to store length of eth and vlan tags in bytes
*
- * Returns the EtherType of the packet, regardless of whether it is
+ * Returns: the EtherType of the packet, regardless of whether it is
* vlan encapsulated (normal or hardware accelerated) or not.
*/
-static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
- int *depth)
+static inline __be16 __vlan_get_protocol_offset(const struct sk_buff *skb,
+ __be16 type,
+ int mac_offset,
+ int *depth)
{
unsigned int vlan_depth = skb->mac_len, parse_depth = VLAN_MAX_DEPTH;
@@ -610,7 +620,8 @@ static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
do {
struct vlan_hdr vhdr, *vh;
- vh = skb_header_pointer(skb, vlan_depth, sizeof(vhdr), &vhdr);
+ vh = skb_header_pointer(skb, mac_offset + vlan_depth,
+ sizeof(vhdr), &vhdr);
if (unlikely(!vh || !--parse_depth))
return 0;
@@ -625,11 +636,17 @@ static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
return type;
}
+static inline __be16 __vlan_get_protocol(const struct sk_buff *skb, __be16 type,
+ int *depth)
+{
+ return __vlan_get_protocol_offset(skb, type, 0, depth);
+}
+
/**
* vlan_get_protocol - get protocol EtherType.
* @skb: skbuff to query
*
- * Returns the EtherType of the packet, regardless of whether it is
+ * Returns: the EtherType of the packet, regardless of whether it is
* vlan encapsulated (normal or hardware accelerated) or not.
*/
static inline __be16 vlan_get_protocol(const struct sk_buff *skb)
@@ -710,7 +727,7 @@ static inline void vlan_set_encap_proto(struct sk_buff *skb,
* Expects the skb to contain a VLAN tag in the payload, and to have skb->data
* pointing at the MAC header.
*
- * Returns a new pointer to skb->data, or NULL on failure to pull.
+ * Returns: a new pointer to skb->data, or NULL on failure to pull.
*/
static inline void *vlan_remove_tag(struct sk_buff *skb, u16 *vlan_tci)
{
@@ -727,7 +744,7 @@ static inline void *vlan_remove_tag(struct sk_buff *skb, u16 *vlan_tci)
* skb_vlan_tagged - check if skb is vlan tagged.
* @skb: skbuff to query
*
- * Returns true if the skb is tagged, regardless of whether it is hardware
+ * Returns: true if the skb is tagged, regardless of whether it is hardware
* accelerated or not.
*/
static inline bool skb_vlan_tagged(const struct sk_buff *skb)
@@ -743,7 +760,7 @@ static inline bool skb_vlan_tagged(const struct sk_buff *skb)
* skb_vlan_tagged_multi - check if skb is vlan tagged with multiple headers.
* @skb: skbuff to query
*
- * Returns true if the skb is tagged with multiple vlan headers, regardless
+ * Returns: true if the skb is tagged with multiple vlan headers, regardless
* of whether it is hardware accelerated or not.
*/
static inline bool skb_vlan_tagged_multi(struct sk_buff *skb)
@@ -774,7 +791,7 @@ static inline bool skb_vlan_tagged_multi(struct sk_buff *skb)
* @skb: skbuff to query
* @features: features to be checked
*
- * Returns features without unsafe ones if the skb has multiple tags.
+ * Returns: features without unsafe ones if the skb has multiple tags.
*/
static inline netdev_features_t vlan_features_check(struct sk_buff *skb,
netdev_features_t features)
@@ -798,9 +815,11 @@ static inline netdev_features_t vlan_features_check(struct sk_buff *skb,
* @h1: Pointer to vlan header
* @h2: Pointer to vlan header
*
- * Compare two vlan headers, returns 0 if equal.
+ * Compare two vlan headers.
*
* Please note that alignment of h1 & h2 are only guaranteed to be 16 bits.
+ *
+ * Return: 0 if equal, arbitrary non-zero value if not equal.
*/
static inline unsigned long compare_vlan_header(const struct vlan_hdr *h1,
const struct vlan_hdr *h2)
diff --git a/include/linux/igmp.h b/include/linux/igmp.h
index 5171231f70a8..073b30a9b850 100644
--- a/include/linux/igmp.h
+++ b/include/linux/igmp.h
@@ -87,6 +87,8 @@ struct ip_mc_list {
char loaded;
unsigned char gsquery; /* check source marks? */
unsigned char crcount;
+ unsigned long mca_cstamp;
+ unsigned long mca_tstamp;
struct rcu_head rcu;
};
diff --git a/include/linux/iio/backend.h b/include/linux/iio/backend.h
index 37d56914d485..10be00f3b120 100644
--- a/include/linux/iio/backend.h
+++ b/include/linux/iio/backend.h
@@ -14,12 +14,14 @@ struct iio_dev;
enum iio_backend_data_type {
IIO_BACKEND_TWOS_COMPLEMENT,
IIO_BACKEND_OFFSET_BINARY,
+ IIO_BACKEND_DATA_UNSIGNED,
IIO_BACKEND_DATA_TYPE_MAX
};
enum iio_backend_data_source {
IIO_BACKEND_INTERNAL_CONTINUOUS_WAVE,
IIO_BACKEND_EXTERNAL,
+ IIO_BACKEND_INTERNAL_RAMP_16BIT,
IIO_BACKEND_DATA_SOURCE_MAX
};
@@ -89,6 +91,11 @@ enum iio_backend_sample_trigger {
* @read_raw: Read a channel attribute from a backend device
* @debugfs_print_chan_status: Print channel status into a buffer.
* @debugfs_reg_access: Read or write register value of backend.
+ * @ddr_enable: Enable interface DDR (Double Data Rate) mode.
+ * @ddr_disable: Disable interface DDR (Double Data Rate) mode.
+ * @data_stream_enable: Enable data stream.
+ * @data_stream_disable: Disable data stream.
+ * @data_transfer_addr: Set data address.
**/
struct iio_backend_ops {
int (*enable)(struct iio_backend *back);
@@ -129,6 +136,11 @@ struct iio_backend_ops {
size_t len);
int (*debugfs_reg_access)(struct iio_backend *back, unsigned int reg,
unsigned int writeval, unsigned int *readval);
+ int (*ddr_enable)(struct iio_backend *back);
+ int (*ddr_disable)(struct iio_backend *back);
+ int (*data_stream_enable)(struct iio_backend *back);
+ int (*data_stream_disable)(struct iio_backend *back);
+ int (*data_transfer_addr)(struct iio_backend *back, u32 address);
};
/**
@@ -164,6 +176,11 @@ int iio_backend_data_sample_trigger(struct iio_backend *back,
int devm_iio_backend_request_buffer(struct device *dev,
struct iio_backend *back,
struct iio_dev *indio_dev);
+int iio_backend_ddr_enable(struct iio_backend *back);
+int iio_backend_ddr_disable(struct iio_backend *back);
+int iio_backend_data_stream_enable(struct iio_backend *back);
+int iio_backend_data_stream_disable(struct iio_backend *back);
+int iio_backend_data_transfer_addr(struct iio_backend *back, u32 address);
ssize_t iio_backend_ext_info_set(struct iio_dev *indio_dev, uintptr_t private,
const struct iio_chan_spec *chan,
const char *buf, size_t len);
diff --git a/include/linux/iio/driver.h b/include/linux/iio/driver.h
index 7a157ed218f6..7f8b55551ed0 100644
--- a/include/linux/iio/driver.h
+++ b/include/linux/iio/driver.h
@@ -18,7 +18,7 @@ struct iio_map;
* @map: array of mappings specifying association of channel with client
*/
int iio_map_array_register(struct iio_dev *indio_dev,
- struct iio_map *map);
+ const struct iio_map *map);
/**
* iio_map_array_unregister() - tell the core to remove consumer mappings for
@@ -38,6 +38,7 @@ int iio_map_array_unregister(struct iio_dev *indio_dev);
* handle de-registration of the IIO map object when the device's refcount goes to
* zero.
*/
-int devm_iio_map_array_register(struct device *dev, struct iio_dev *indio_dev, struct iio_map *maps);
+int devm_iio_map_array_register(struct device *dev, struct iio_dev *indio_dev,
+ const struct iio_map *maps);
#endif
diff --git a/include/linux/iio/events.h b/include/linux/iio/events.h
index a4558c45a548..72062a0c7c87 100644
--- a/include/linux/iio/events.h
+++ b/include/linux/iio/events.h
@@ -10,7 +10,7 @@
#include <uapi/linux/iio/events.h>
/**
- * IIO_EVENT_CODE() - create event identifier
+ * _IIO_EVENT_CODE() - create event identifier
* @chan_type: Type of the channel. Should be one of enum iio_chan_type.
* @diff: Whether the event is for an differential channel or not.
* @modifier: Modifier for the channel. Should be one of enum iio_modifier.
@@ -19,10 +19,13 @@
* @chan: Channel number for non-differential channels.
* @chan1: First channel number for differential channels.
* @chan2: Second channel number for differential channels.
+ *
+ * Drivers should use the specialized macros below instead of using this one
+ * directly.
*/
-#define IIO_EVENT_CODE(chan_type, diff, modifier, direction, \
- type, chan, chan1, chan2) \
+#define _IIO_EVENT_CODE(chan_type, diff, modifier, direction, \
+ type, chan, chan1, chan2) \
(((u64)type << 56) | ((u64)diff << 55) | \
((u64)direction << 48) | ((u64)modifier << 40) | \
((u64)chan_type << 32) | (((u16)chan2) << 16) | ((u16)chan1) | \
@@ -30,7 +33,8 @@
/**
- * IIO_MOD_EVENT_CODE() - create event identifier for modified channels
+ * IIO_MOD_EVENT_CODE() - create event identifier for modified (non
+ * differential) channels
* @chan_type: Type of the channel. Should be one of enum iio_chan_type.
* @number: Channel number.
* @modifier: Modifier for the channel. Should be one of enum iio_modifier.
@@ -40,10 +44,11 @@
#define IIO_MOD_EVENT_CODE(chan_type, number, modifier, \
type, direction) \
- IIO_EVENT_CODE(chan_type, 0, modifier, direction, type, number, 0, 0)
+ _IIO_EVENT_CODE(chan_type, 0, modifier, direction, type, number, 0, 0)
/**
- * IIO_UNMOD_EVENT_CODE() - create event identifier for unmodified channels
+ * IIO_UNMOD_EVENT_CODE() - create event identifier for unmodified (non
+ * differential) channels
* @chan_type: Type of the channel. Should be one of enum iio_chan_type.
* @number: Channel number.
* @type: Type of the event. Should be one of enum iio_event_type.
@@ -51,6 +56,18 @@
*/
#define IIO_UNMOD_EVENT_CODE(chan_type, number, type, direction) \
- IIO_EVENT_CODE(chan_type, 0, 0, direction, type, number, 0, 0)
+ _IIO_EVENT_CODE(chan_type, 0, 0, direction, type, number, 0, 0)
+
+/**
+ * IIO_DIFF_EVENT_CODE() - create event identifier for differential channels
+ * @chan_type: Type of the channel. Should be one of enum iio_chan_type.
+ * @chan1: First channel number for differential channels.
+ * @chan2: Second channel number for differential channels.
+ * @type: Type of the event. Should be one of enum iio_event_type.
+ * @direction: Direction of the event. One of enum iio_event_direction.
+ */
+
+#define IIO_DIFF_EVENT_CODE(chan_type, chan1, chan2, type, direction) \
+ _IIO_EVENT_CODE(chan_type, 1, 0, direction, type, 0, chan1, chan2)
#endif
diff --git a/include/linux/iio/iio-opaque.h b/include/linux/iio/iio-opaque.h
index 5aec3945555b..a89e7e43e441 100644
--- a/include/linux/iio/iio-opaque.h
+++ b/include/linux/iio/iio-opaque.h
@@ -70,7 +70,7 @@ struct iio_dev_opaque {
#if defined(CONFIG_DEBUG_FS)
struct dentry *debugfs_dentry;
- unsigned cached_reg_addr;
+ unsigned int cached_reg_addr;
char read_buf[20];
unsigned int read_buf_len;
#endif
diff --git a/include/linux/iio/iio.h b/include/linux/iio/iio.h
index 18779b631e90..ae65890d4567 100644
--- a/include/linux/iio/iio.h
+++ b/include/linux/iio/iio.h
@@ -282,11 +282,11 @@ struct iio_chan_spec {
const struct iio_chan_spec_ext_info *ext_info;
const char *extend_name;
const char *datasheet_name;
- unsigned modified:1;
- unsigned indexed:1;
- unsigned output:1;
- unsigned differential:1;
- unsigned has_ext_scan_type:1;
+ unsigned int modified:1;
+ unsigned int indexed:1;
+ unsigned int output:1;
+ unsigned int differential:1;
+ unsigned int has_ext_scan_type:1;
};
@@ -514,7 +514,7 @@ struct iio_info {
const struct iio_chan_spec *chan,
enum iio_event_type type,
enum iio_event_direction dir,
- int state);
+ bool state);
int (*read_event_value)(struct iio_dev *indio_dev,
const struct iio_chan_spec *chan,
@@ -541,13 +541,13 @@ struct iio_info {
int (*update_scan_mode)(struct iio_dev *indio_dev,
const unsigned long *scan_mask);
int (*debugfs_reg_access)(struct iio_dev *indio_dev,
- unsigned reg, unsigned writeval,
- unsigned *readval);
+ unsigned int reg, unsigned int writeval,
+ unsigned int *readval);
int (*fwnode_xlate)(struct iio_dev *indio_dev,
const struct fwnode_reference_args *iiospec);
- int (*hwfifo_set_watermark)(struct iio_dev *indio_dev, unsigned val);
+ int (*hwfifo_set_watermark)(struct iio_dev *indio_dev, unsigned int val);
int (*hwfifo_flush_to_buffer)(struct iio_dev *indio_dev,
- unsigned count);
+ unsigned int count);
};
/**
@@ -609,7 +609,7 @@ struct iio_dev {
int scan_bytes;
const unsigned long *available_scan_masks;
- unsigned __private masklength;
+ unsigned int __private masklength;
const unsigned long *active_scan_mask;
bool scan_timestamp;
struct iio_trigger *trig;
@@ -624,7 +624,7 @@ struct iio_dev {
const struct iio_info *info;
const struct iio_buffer_setup_ops *setup_ops;
- void *priv;
+ void *__private priv;
};
int iio_device_id(struct iio_dev *indio_dev);
@@ -785,7 +785,7 @@ struct iio_dev *iio_device_alloc(struct device *parent, int sizeof_priv);
/* The information at the returned address is guaranteed to be cacheline aligned */
static inline void *iio_priv(const struct iio_dev *indio_dev)
{
- return indio_dev->priv;
+ return ACCESS_PRIVATE(indio_dev, priv);
}
void iio_device_free(struct iio_dev *indio_dev);
@@ -831,6 +831,7 @@ int iio_device_resume_triggering(struct iio_dev *indio_dev);
bool iio_read_acpi_mount_matrix(struct device *dev,
struct iio_mount_matrix *orientation,
char *acpi_method);
+const char *iio_get_acpi_device_name_and_data(struct device *dev, const void **data);
#else
static inline bool iio_read_acpi_mount_matrix(struct device *dev,
struct iio_mount_matrix *orientation,
@@ -838,7 +839,16 @@ static inline bool iio_read_acpi_mount_matrix(struct device *dev,
{
return false;
}
+static inline const char *
+iio_get_acpi_device_name_and_data(struct device *dev, const void **data)
+{
+ return NULL;
+}
#endif
+static inline const char *iio_get_acpi_device_name(struct device *dev)
+{
+ return iio_get_acpi_device_name_and_data(dev, NULL);
+}
/**
* iio_get_current_scan_type - Get the current scan type for a channel
diff --git a/include/linux/io_uring.h b/include/linux/io_uring.h
index e123d5e17b52..85fe4e6b275c 100644
--- a/include/linux/io_uring.h
+++ b/include/linux/io_uring.h
@@ -15,10 +15,8 @@ bool io_is_uring_fops(struct file *file);
static inline void io_uring_files_cancel(void)
{
- if (current->io_uring) {
- io_uring_unreg_ringfd();
+ if (current->io_uring)
__io_uring_cancel(false);
- }
}
static inline void io_uring_task_cancel(void)
{
diff --git a/include/linux/io_uring/cmd.h b/include/linux/io_uring/cmd.h
index 578a3fdf5c71..a3ce553413de 100644
--- a/include/linux/io_uring/cmd.h
+++ b/include/linux/io_uring/cmd.h
@@ -18,6 +18,11 @@ struct io_uring_cmd {
u8 pdu[32]; /* available inline for free use */
};
+struct io_uring_cmd_data {
+ struct io_uring_sqe sqes[2];
+ void *op_data;
+};
+
static inline const void *io_uring_sqe_cmd(const struct io_uring_sqe *sqe)
{
return sqe->cmd;
@@ -43,7 +48,7 @@ int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
* Note: the caller should never hard code @issue_flags and is only allowed
* to pass the mask provided by the core io_uring code.
*/
-void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret, ssize_t res2,
+void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret, u64 res2,
unsigned issue_flags);
void __io_uring_cmd_do_in_task(struct io_uring_cmd *ioucmd,
@@ -67,7 +72,7 @@ static inline int io_uring_cmd_import_fixed(u64 ubuf, unsigned long len, int rw,
return -EOPNOTSUPP;
}
static inline void io_uring_cmd_done(struct io_uring_cmd *cmd, ssize_t ret,
- ssize_t ret2, unsigned issue_flags)
+ u64 ret2, unsigned issue_flags)
{
}
static inline void __io_uring_cmd_do_in_task(struct io_uring_cmd *ioucmd,
@@ -113,4 +118,9 @@ static inline struct task_struct *io_uring_cmd_get_task(struct io_uring_cmd *cmd
return cmd_to_io_kiocb(cmd)->tctx->task;
}
+static inline struct io_uring_cmd_data *io_uring_cmd_get_async_data(struct io_uring_cmd *cmd)
+{
+ return cmd_to_io_kiocb(cmd)->async_data;
+}
+
#endif /* _LINUX_IO_URING_CMD_H */
diff --git a/include/linux/io_uring_types.h b/include/linux/io_uring_types.h
index 593c10a02144..fd4cdb0860a2 100644
--- a/include/linux/io_uring_types.h
+++ b/include/linux/io_uring_types.h
@@ -336,6 +336,7 @@ struct io_ring_ctx {
*/
struct {
struct llist_head work_llist;
+ struct llist_head retry_llist;
unsigned long check_cq;
atomic_t cq_wait_nr;
atomic_t cq_timeouts;
@@ -344,7 +345,7 @@ struct io_ring_ctx {
/* timeouts */
struct {
- spinlock_t timeout_lock;
+ raw_spinlock_t timeout_lock;
struct list_head timeout_list;
struct list_head ltimeout_list;
unsigned cq_last_tm_flush;
diff --git a/include/linux/iomap.h b/include/linux/iomap.h
index 5675af6b740c..75bf54e76f3b 100644
--- a/include/linux/iomap.h
+++ b/include/linux/iomap.h
@@ -335,7 +335,7 @@ struct iomap_ioend {
u16 io_type;
u16 io_flags; /* IOMAP_F_* */
struct inode *io_inode; /* file being written to */
- size_t io_size; /* size of the extent */
+ size_t io_size; /* size of data within eof */
loff_t io_offset; /* offset in the file */
sector_t io_sector; /* start sector of ioend */
struct bio io_bio; /* MUST BE LAST! */
diff --git a/include/linux/kfifo.h b/include/linux/kfifo.h
index 564868bdce89..fd743d4c4b4b 100644
--- a/include/linux/kfifo.h
+++ b/include/linux/kfifo.h
@@ -37,7 +37,6 @@
*/
#include <linux/array_size.h>
-#include <linux/dma-mapping.h>
#include <linux/spinlock.h>
#include <linux/stddef.h>
#include <linux/types.h>
diff --git a/include/linux/ktime.h b/include/linux/ktime.h
index 3a4e723eae0f..383ed9985802 100644
--- a/include/linux/ktime.h
+++ b/include/linux/ktime.h
@@ -222,6 +222,11 @@ static inline ktime_t ns_to_ktime(u64 ns)
return ns;
}
+static inline ktime_t us_to_ktime(u64 us)
+{
+ return us * NSEC_PER_USEC;
+}
+
static inline ktime_t ms_to_ktime(u64 ms)
{
return ms * NSEC_PER_MSEC;
diff --git a/include/linux/list.h b/include/linux/list.h
index 5f4b0a39cf46..29a375889fb8 100644
--- a/include/linux/list.h
+++ b/include/linux/list.h
@@ -687,14 +687,6 @@ static inline void list_splice_tail_init(struct list_head *list,
for (pos = (head)->next; !list_is_head(pos, (head)); pos = pos->next)
/**
- * list_for_each_reverse - iterate backwards over a list
- * @pos: the &struct list_head to use as a loop cursor.
- * @head: the head for your list.
- */
-#define list_for_each_reverse(pos, head) \
- for (pos = (head)->prev; pos != (head); pos = pos->prev)
-
-/**
* list_for_each_rcu - Iterate over a list in an RCU-safe fashion
* @pos: the &struct list_head to use as a loop cursor.
* @head: the head for your list.
diff --git a/include/linux/memfd.h b/include/linux/memfd.h
index 3f2cf339ceaf..d437e3070850 100644
--- a/include/linux/memfd.h
+++ b/include/linux/memfd.h
@@ -7,6 +7,7 @@
#ifdef CONFIG_MEMFD_CREATE
extern long memfd_fcntl(struct file *file, unsigned int cmd, unsigned int arg);
struct folio *memfd_alloc_folio(struct file *memfd, pgoff_t idx);
+unsigned int *memfd_file_seals_ptr(struct file *file);
#else
static inline long memfd_fcntl(struct file *f, unsigned int c, unsigned int a)
{
@@ -16,6 +17,19 @@ static inline struct folio *memfd_alloc_folio(struct file *memfd, pgoff_t idx)
{
return ERR_PTR(-EINVAL);
}
+
+static inline unsigned int *memfd_file_seals_ptr(struct file *file)
+{
+ return NULL;
+}
#endif
+/* Retrieve memfd seals associated with the file, if any. */
+static inline unsigned int memfd_file_seals(struct file *file)
+{
+ unsigned int *sealsp = memfd_file_seals_ptr(file);
+
+ return sealsp ? *sealsp : 0;
+}
+
#endif /* __LINUX_MEMFD_H */
diff --git a/include/linux/mfd/88pm886.h b/include/linux/mfd/88pm886.h
index 133aa302e492..85eca44f39ab 100644
--- a/include/linux/mfd/88pm886.h
+++ b/include/linux/mfd/88pm886.h
@@ -31,6 +31,15 @@
#define PM886_INT_WC BIT(1)
#define PM886_INT_MASK_MODE BIT(2)
+#define PM886_REG_RTC_CNT1 0xd1
+#define PM886_REG_RTC_CNT2 0xd2
+#define PM886_REG_RTC_CNT3 0xd3
+#define PM886_REG_RTC_CNT4 0xd4
+#define PM886_REG_RTC_SPARE1 0xea
+#define PM886_REG_RTC_SPARE2 0xeb
+#define PM886_REG_RTC_SPARE3 0xec
+#define PM886_REG_RTC_SPARE4 0xed
+#define PM886_REG_RTC_SPARE5 0xee
#define PM886_REG_RTC_SPARE6 0xef
#define PM886_REG_BUCK_EN 0x08
diff --git a/include/linux/mfd/da9063/core.h b/include/linux/mfd/da9063/core.h
index 8db52324f416..eae82f421414 100644
--- a/include/linux/mfd/da9063/core.h
+++ b/include/linux/mfd/da9063/core.h
@@ -78,6 +78,7 @@ struct da9063 {
enum da9063_type type;
unsigned char variant_code;
unsigned int flags;
+ bool use_sw_pm;
/* Control interface */
struct regmap *regmap;
diff --git a/include/linux/misc/keba.h b/include/linux/misc/keba.h
index 323b31a847c5..a81d6fa70851 100644
--- a/include/linux/misc/keba.h
+++ b/include/linux/misc/keba.h
@@ -7,6 +7,7 @@
#include <linux/auxiliary_bus.h>
struct i2c_board_info;
+struct spi_board_info;
/**
* struct keba_i2c_auxdev - KEBA I2C auxiliary device
@@ -22,4 +23,50 @@ struct keba_i2c_auxdev {
struct i2c_board_info *info;
};
+/**
+ * struct keba_spi_auxdev - KEBA SPI auxiliary device
+ * @auxdev: auxiliary device object
+ * @io: address range of SPI controller IO memory
+ * @info_size: number of SPI devices to be probed
+ * @info: SPI devices to be probed
+ */
+struct keba_spi_auxdev {
+ struct auxiliary_device auxdev;
+ struct resource io;
+ int info_size;
+ struct spi_board_info *info;
+};
+
+/**
+ * struct keba_fan_auxdev - KEBA fan auxiliary device
+ * @auxdev: auxiliary device object
+ * @io: address range of fan controller IO memory
+ */
+struct keba_fan_auxdev {
+ struct auxiliary_device auxdev;
+ struct resource io;
+};
+
+/**
+ * struct keba_batt_auxdev - KEBA battery auxiliary device
+ * @auxdev: auxiliary device object
+ * @io: address range of battery controller IO memory
+ */
+struct keba_batt_auxdev {
+ struct auxiliary_device auxdev;
+ struct resource io;
+};
+
+/**
+ * struct keba_uart_auxdev - KEBA UART auxiliary device
+ * @auxdev: auxiliary device object
+ * @io: address range of UART controller IO memory
+ * @irq: number of UART controller interrupt
+ */
+struct keba_uart_auxdev {
+ struct auxiliary_device auxdev;
+ struct resource io;
+ unsigned int irq;
+};
+
#endif /* _LINUX_MISC_KEBA_H */
diff --git a/include/linux/mlx5/driver.h b/include/linux/mlx5/driver.h
index fc7e6153b73d..fed666c5bd16 100644
--- a/include/linux/mlx5/driver.h
+++ b/include/linux/mlx5/driver.h
@@ -524,6 +524,7 @@ enum {
* creation/deletion on drivers rescan. Unset during device attach.
*/
MLX5_PRIV_FLAGS_DETACH = 1 << 2,
+ MLX5_PRIV_FLAGS_SWITCH_LEGACY = 1 << 3,
};
struct mlx5_adev {
@@ -690,7 +691,6 @@ struct mlx5_timer {
struct timecounter tc;
u32 nominal_c_mult;
unsigned long overflow_period;
- struct delayed_work overflow_work;
};
struct mlx5_clock {
@@ -1202,6 +1202,12 @@ static inline bool mlx5_core_is_vf(const struct mlx5_core_dev *dev)
return dev->coredev_type == MLX5_COREDEV_VF;
}
+static inline bool mlx5_core_same_coredev_type(const struct mlx5_core_dev *dev1,
+ const struct mlx5_core_dev *dev2)
+{
+ return dev1->coredev_type == dev2->coredev_type;
+}
+
static inline bool mlx5_core_is_ecpf(const struct mlx5_core_dev *dev)
{
return dev->caps.embedded_cpu;
diff --git a/include/linux/mlx5/fs.h b/include/linux/mlx5/fs.h
index 438db888bde0..2a69d9d71276 100644
--- a/include/linux/mlx5/fs.h
+++ b/include/linux/mlx5/fs.h
@@ -163,7 +163,7 @@ struct mlx5_flow_destination {
u32 tir_num;
u32 ft_num;
struct mlx5_flow_table *ft;
- u32 counter_id;
+ struct mlx5_fc *counter;
struct {
u16 num;
u16 vhca_id;
@@ -299,6 +299,8 @@ int mlx5_modify_rule_destination(struct mlx5_flow_handle *handler,
struct mlx5_fc *mlx5_fc_create(struct mlx5_core_dev *dev, bool aging);
void mlx5_fc_destroy(struct mlx5_core_dev *dev, struct mlx5_fc *counter);
+struct mlx5_fc *mlx5_fc_local_create(u32 counter_id, u32 offset, u32 bulk_size);
+void mlx5_fc_local_destroy(struct mlx5_fc *counter);
u64 mlx5_fc_query_lastuse(struct mlx5_fc *counter);
void mlx5_fc_query_cached(struct mlx5_fc *counter,
u64 *bytes, u64 *packets, u64 *lastuse);
diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h
index 4fbbcf35498b..370f533da107 100644
--- a/include/linux/mlx5/mlx5_ifc.h
+++ b/include/linux/mlx5/mlx5_ifc.h
@@ -1095,7 +1095,9 @@ struct mlx5_ifc_qos_cap_bits {
u8 log_esw_max_sched_depth[0x4];
u8 reserved_at_10[0x10];
- u8 reserved_at_20[0xb];
+ u8 reserved_at_20[0x9];
+ u8 esw_cross_esw_sched[0x1];
+ u8 reserved_at_2a[0x1];
u8 log_max_qos_nic_queue_group[0x5];
u8 reserved_at_30[0x10];
@@ -1103,7 +1105,8 @@ struct mlx5_ifc_qos_cap_bits {
u8 packet_pacing_min_rate[0x20];
- u8 reserved_at_80[0x10];
+ u8 reserved_at_80[0xb];
+ u8 log_esw_max_rate_limit[0x5];
u8 packet_pacing_rate_table_size[0x10];
u8 esw_element_type[0x10];
@@ -1590,12 +1593,14 @@ enum {
MLX5_STEERING_FORMAT_CONNECTX_5 = 0,
MLX5_STEERING_FORMAT_CONNECTX_6DX = 1,
MLX5_STEERING_FORMAT_CONNECTX_7 = 2,
+ MLX5_STEERING_FORMAT_CONNECTX_8 = 3,
};
struct mlx5_ifc_cmd_hca_cap_bits {
u8 reserved_at_0[0x6];
u8 page_request_disable[0x1];
- u8 reserved_at_7[0x9];
+ u8 abs_native_port_num[0x1];
+ u8 reserved_at_8[0x8];
u8 shared_object_to_user_object_allowed[0x1];
u8 reserved_at_13[0xe];
u8 vhca_resource_manager[0x1];
@@ -2119,7 +2124,9 @@ struct mlx5_ifc_cmd_hca_cap_2_bits {
u8 migration_in_chunks[0x1];
u8 reserved_at_d1[0x1];
u8 sf_eq_usage[0x1];
- u8 reserved_at_d3[0xd];
+ u8 reserved_at_d3[0x5];
+ u8 multiplane[0x1];
+ u8 reserved_at_d9[0x7];
u8 cross_vhca_object_to_object_supported[0x20];
@@ -4103,6 +4110,7 @@ enum {
SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC = 0x2,
SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC = 0x3,
SCHEDULING_CONTEXT_ELEMENT_TYPE_QUEUE_GROUP = 0x4,
+ SCHEDULING_CONTEXT_ELEMENT_TYPE_RATE_LIMIT = 0x5,
};
enum {
@@ -4111,34 +4119,41 @@ enum {
ELEMENT_TYPE_CAP_MASK_VPORT_TC = 1 << 2,
ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC = 1 << 3,
ELEMENT_TYPE_CAP_MASK_QUEUE_GROUP = 1 << 4,
+ ELEMENT_TYPE_CAP_MASK_RATE_LIMIT = 1 << 5,
};
enum {
TSAR_ELEMENT_TSAR_TYPE_DWRR = 0x0,
TSAR_ELEMENT_TSAR_TYPE_ROUND_ROBIN = 0x1,
TSAR_ELEMENT_TSAR_TYPE_ETS = 0x2,
+ TSAR_ELEMENT_TSAR_TYPE_TC_ARB = 0x3,
};
enum {
TSAR_TYPE_CAP_MASK_DWRR = 1 << 0,
TSAR_TYPE_CAP_MASK_ROUND_ROBIN = 1 << 1,
TSAR_TYPE_CAP_MASK_ETS = 1 << 2,
+ TSAR_TYPE_CAP_MASK_TC_ARB = 1 << 3,
};
struct mlx5_ifc_tsar_element_bits {
- u8 reserved_at_0[0x8];
+ u8 traffic_class[0x4];
+ u8 reserved_at_4[0x4];
u8 tsar_type[0x8];
u8 reserved_at_10[0x10];
};
struct mlx5_ifc_vport_element_bits {
- u8 reserved_at_0[0x10];
+ u8 reserved_at_0[0x4];
+ u8 eswitch_owner_vhca_id_valid[0x1];
+ u8 eswitch_owner_vhca_id[0xb];
u8 vport_number[0x10];
};
struct mlx5_ifc_vport_tc_element_bits {
u8 traffic_class[0x4];
- u8 reserved_at_4[0xc];
+ u8 eswitch_owner_vhca_id_valid[0x1];
+ u8 eswitch_owner_vhca_id[0xb];
u8 vport_number[0x10];
};
@@ -4163,7 +4178,9 @@ struct mlx5_ifc_scheduling_context_bits {
u8 max_average_bw[0x20];
- u8 reserved_at_e0[0x120];
+ u8 max_bw_obj_id[0x20];
+
+ u8 reserved_at_100[0x100];
};
struct mlx5_ifc_rqtc_bits {
@@ -6324,6 +6341,20 @@ struct mlx5_ifc_modify_other_hca_cap_in_bits {
struct mlx5_ifc_other_hca_cap_bits other_capability;
};
+struct mlx5_ifc_sw_owner_icm_root_params_bits {
+ u8 sw_owner_icm_root_1[0x40];
+
+ u8 sw_owner_icm_root_0[0x40];
+};
+
+struct mlx5_ifc_rtc_params_bits {
+ u8 rtc_id_0[0x20];
+
+ u8 rtc_id_1[0x20];
+
+ u8 reserved_at_40[0x40];
+};
+
struct mlx5_ifc_flow_table_context_bits {
u8 reformat_en[0x1];
u8 decap_en[0x1];
@@ -6342,20 +6373,10 @@ struct mlx5_ifc_flow_table_context_bits {
u8 lag_master_next_table_id[0x18];
u8 reserved_at_60[0x60];
- union {
- struct {
- u8 sw_owner_icm_root_1[0x40];
-
- u8 sw_owner_icm_root_0[0x40];
- } sws;
- struct {
- u8 rtc_id_0[0x20];
- u8 rtc_id_1[0x20];
-
- u8 reserved_at_100[0x40];
-
- } hws;
+ union {
+ struct mlx5_ifc_sw_owner_icm_root_params_bits sws;
+ struct mlx5_ifc_rtc_params_bits hws;
};
};
diff --git a/include/linux/mm.h b/include/linux/mm.h
index c39c4945946c..b1c3db9cf355 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -31,6 +31,7 @@
#include <linux/kasan.h>
#include <linux/memremap.h>
#include <linux/slab.h>
+#include <linux/cacheinfo.h>
struct mempolicy;
struct anon_vma;
@@ -3010,7 +3011,15 @@ static inline void pagetable_pte_dtor(struct ptdesc *ptdesc)
lruvec_stat_sub_folio(folio, NR_PAGETABLE);
}
-pte_t *__pte_offset_map(pmd_t *pmd, unsigned long addr, pmd_t *pmdvalp);
+pte_t *___pte_offset_map(pmd_t *pmd, unsigned long addr, pmd_t *pmdvalp);
+static inline pte_t *__pte_offset_map(pmd_t *pmd, unsigned long addr,
+ pmd_t *pmdvalp)
+{
+ pte_t *pte;
+
+ __cond_lock(RCU, pte = ___pte_offset_map(pmd, addr, pmdvalp));
+ return pte;
+}
static inline pte_t *pte_offset_map(pmd_t *pmd, unsigned long addr)
{
return __pte_offset_map(pmd, addr, NULL);
@@ -3023,7 +3032,8 @@ static inline pte_t *pte_offset_map_lock(struct mm_struct *mm, pmd_t *pmd,
{
pte_t *pte;
- __cond_lock(*ptlp, pte = __pte_offset_map_lock(mm, pmd, addr, ptlp));
+ __cond_lock(RCU, __cond_lock(*ptlp,
+ pte = __pte_offset_map_lock(mm, pmd, addr, ptlp)));
return pte;
}
@@ -3115,6 +3125,7 @@ static inline bool pagetable_pmd_ctor(struct ptdesc *ptdesc)
if (!pmd_ptlock_init(ptdesc))
return false;
__folio_set_pgtable(folio);
+ ptdesc_pmd_pts_init(ptdesc);
lruvec_stat_add_folio(folio, NR_PAGETABLE);
return true;
}
@@ -4091,6 +4102,37 @@ void mem_dump_obj(void *object);
static inline void mem_dump_obj(void *object) {}
#endif
+static inline bool is_write_sealed(int seals)
+{
+ return seals & (F_SEAL_WRITE | F_SEAL_FUTURE_WRITE);
+}
+
+/**
+ * is_readonly_sealed - Checks whether write-sealed but mapped read-only,
+ * in which case writes should be disallowing moving
+ * forwards.
+ * @seals: the seals to check
+ * @vm_flags: the VMA flags to check
+ *
+ * Returns whether readonly sealed, in which case writess should be disallowed
+ * going forward.
+ */
+static inline bool is_readonly_sealed(int seals, vm_flags_t vm_flags)
+{
+ /*
+ * Since an F_SEAL_[FUTURE_]WRITE sealed memfd can be mapped as
+ * MAP_SHARED and read-only, take care to not allow mprotect to
+ * revert protections on such mappings. Do this only for shared
+ * mappings. For private mappings, don't need to mask
+ * VM_MAYWRITE as we still want them to be COW-writable.
+ */
+ if (is_write_sealed(seals) &&
+ ((vm_flags & (VM_SHARED | VM_WRITE)) == VM_SHARED))
+ return true;
+
+ return false;
+}
+
/**
* seal_check_write - Check for F_SEAL_WRITE or F_SEAL_FUTURE_WRITE flags and
* handle them.
@@ -4102,24 +4144,15 @@ static inline void mem_dump_obj(void *object) {}
*/
static inline int seal_check_write(int seals, struct vm_area_struct *vma)
{
- if (seals & (F_SEAL_WRITE | F_SEAL_FUTURE_WRITE)) {
- /*
- * New PROT_WRITE and MAP_SHARED mmaps are not allowed when
- * write seals are active.
- */
- if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE))
- return -EPERM;
-
- /*
- * Since an F_SEAL_[FUTURE_]WRITE sealed memfd can be mapped as
- * MAP_SHARED and read-only, take care to not allow mprotect to
- * revert protections on such mappings. Do this only for shared
- * mappings. For private mappings, don't need to mask
- * VM_MAYWRITE as we still want them to be COW-writable.
- */
- if (vma->vm_flags & VM_SHARED)
- vm_flags_clear(vma, VM_MAYWRITE);
- }
+ if (!is_write_sealed(seals))
+ return 0;
+
+ /*
+ * New PROT_WRITE and MAP_SHARED mmaps are not allowed when
+ * write seals are active.
+ */
+ if ((vma->vm_flags & VM_SHARED) && (vma->vm_flags & VM_WRITE))
+ return -EPERM;
return 0;
}
@@ -4175,6 +4208,23 @@ static inline int do_mseal(unsigned long start, size_t len_in, unsigned long fla
}
#endif
+/*
+ * user_alloc_needs_zeroing checks if a user folio from page allocator needs to
+ * be zeroed or not.
+ */
+static inline bool user_alloc_needs_zeroing(void)
+{
+ /*
+ * for user folios, arch with cache aliasing requires cache flush and
+ * arc changes folio->flags to make icache coherent with dcache, so
+ * always return false to make caller use
+ * clear_user_page()/clear_user_highpage().
+ */
+ return cpu_dcache_is_aliasing() || cpu_icache_is_aliasing() ||
+ !static_branch_maybe(CONFIG_INIT_ON_ALLOC_DEFAULT_ON,
+ &init_on_alloc);
+}
+
int arch_get_shadow_stack_status(struct task_struct *t, unsigned long __user *status);
int arch_set_shadow_stack_status(struct task_struct *t, unsigned long status);
int arch_lock_shadow_stack_status(struct task_struct *t, unsigned long status);
diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 7361a8f3ab68..332cee285662 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -445,6 +445,7 @@ FOLIO_MATCH(compound_head, _head_2a);
* @pt_index: Used for s390 gmap.
* @pt_mm: Used for x86 pgds.
* @pt_frag_refcount: For fragmented page table tracking. Powerpc only.
+ * @pt_share_count: Used for HugeTLB PMD page table share count.
* @_pt_pad_2: Padding to ensure proper alignment.
* @ptl: Lock for the page table.
* @__page_type: Same as page->page_type. Unused for page tables.
@@ -471,6 +472,9 @@ struct ptdesc {
pgoff_t pt_index;
struct mm_struct *pt_mm;
atomic_t pt_frag_refcount;
+#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING
+ atomic_t pt_share_count;
+#endif
};
union {
@@ -516,6 +520,32 @@ static_assert(sizeof(struct ptdesc) <= sizeof(struct page));
const struct page *: (const struct ptdesc *)(p), \
struct page *: (struct ptdesc *)(p)))
+#ifdef CONFIG_HUGETLB_PMD_PAGE_TABLE_SHARING
+static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc)
+{
+ atomic_set(&ptdesc->pt_share_count, 0);
+}
+
+static inline void ptdesc_pmd_pts_inc(struct ptdesc *ptdesc)
+{
+ atomic_inc(&ptdesc->pt_share_count);
+}
+
+static inline void ptdesc_pmd_pts_dec(struct ptdesc *ptdesc)
+{
+ atomic_dec(&ptdesc->pt_share_count);
+}
+
+static inline int ptdesc_pmd_pts_count(struct ptdesc *ptdesc)
+{
+ return atomic_read(&ptdesc->pt_share_count);
+}
+#else
+static inline void ptdesc_pmd_pts_init(struct ptdesc *ptdesc)
+{
+}
+#endif
+
/*
* Used for sizing the vmemmap region on some architectures
*/
diff --git a/include/linux/mmdebug.h b/include/linux/mmdebug.h
index 39a7714605a7..d7cb1e5ecbda 100644
--- a/include/linux/mmdebug.h
+++ b/include/linux/mmdebug.h
@@ -46,7 +46,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
} \
} while (0)
#define VM_WARN_ON_ONCE_PAGE(cond, page) ({ \
- static bool __section(".data.once") __warned; \
+ static bool __section(".data..once") __warned; \
int __ret_warn_once = !!(cond); \
\
if (unlikely(__ret_warn_once && !__warned)) { \
@@ -66,7 +66,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
unlikely(__ret_warn); \
})
#define VM_WARN_ON_ONCE_FOLIO(cond, folio) ({ \
- static bool __section(".data.once") __warned; \
+ static bool __section(".data..once") __warned; \
int __ret_warn_once = !!(cond); \
\
if (unlikely(__ret_warn_once && !__warned)) { \
@@ -77,7 +77,7 @@ void vma_iter_dump_tree(const struct vma_iterator *vmi);
unlikely(__ret_warn_once); \
})
#define VM_WARN_ON_ONCE_MM(cond, mm) ({ \
- static bool __section(".data.once") __warned; \
+ static bool __section(".data..once") __warned; \
int __ret_warn_once = !!(cond); \
\
if (unlikely(__ret_warn_once && !__warned)) { \
diff --git a/include/linux/module.h b/include/linux/module.h
index 2a9386cbdf85..94acbacdcdf1 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -247,7 +247,7 @@ extern void cleanup_module(void);
#ifdef MODULE
/* Creates an alias so file2alias.c can find device table. */
#define MODULE_DEVICE_TABLE(type, name) \
-extern typeof(name) __mod_##type##__##name##_device_table \
+extern typeof(name) __mod_device_table__##type##__##name \
__attribute__ ((unused, alias(__stringify(name))))
#else /* !MODULE */
#define MODULE_DEVICE_TABLE(type, name)
@@ -296,7 +296,7 @@ extern typeof(name) __mod_##type##__##name##_device_table \
* files require multiple MODULE_FIRMWARE() specifiers */
#define MODULE_FIRMWARE(_firmware) MODULE_INFO(firmware, _firmware)
-#define MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, __stringify(ns))
+#define MODULE_IMPORT_NS(ns) MODULE_INFO(import_ns, ns)
struct notifier_block;
diff --git a/include/linux/net_tstamp.h b/include/linux/net_tstamp.h
index 662074b08c94..ff0758e88ea1 100644
--- a/include/linux/net_tstamp.h
+++ b/include/linux/net_tstamp.h
@@ -20,6 +20,33 @@ enum hwtstamp_source {
};
/**
+ * struct hwtstamp_provider_desc - hwtstamp provider description
+ *
+ * @index: index of the hwtstamp provider.
+ * @qualifier: hwtstamp provider qualifier.
+ */
+struct hwtstamp_provider_desc {
+ int index;
+ enum hwtstamp_provider_qualifier qualifier;
+};
+
+/**
+ * struct hwtstamp_provider - hwtstamp provider object
+ *
+ * @rcu_head: RCU callback used to free the struct.
+ * @source: source of the hwtstamp provider.
+ * @phydev: pointer of the phydev source in case a PTP coming from phylib
+ * @desc: hwtstamp provider description.
+ */
+
+struct hwtstamp_provider {
+ struct rcu_head rcu_head;
+ enum hwtstamp_source source;
+ struct phy_device *phydev;
+ struct hwtstamp_provider_desc desc;
+};
+
+/**
* struct kernel_hwtstamp_config - Kernel copy of struct hwtstamp_config
*
* @flags: see struct hwtstamp_config
@@ -31,6 +58,7 @@ enum hwtstamp_source {
* copied the ioctl request back to user space
* @source: indication whether timestamps should come from the netdev or from
* an attached phylib PHY
+ * @qualifier: qualifier of the hwtstamp provider
*
* Prefer using this structure for in-kernel processing of hardware
* timestamping configuration, over the inextensible struct hwtstamp_config
@@ -43,6 +71,7 @@ struct kernel_hwtstamp_config {
struct ifreq *ifr;
bool copied_to_user;
enum hwtstamp_source source;
+ enum hwtstamp_provider_qualifier qualifier;
};
static inline void hwtstamp_config_to_kernel(struct kernel_hwtstamp_config *kernel_cfg,
diff --git a/include/linux/netdev_features.h b/include/linux/netdev_features.h
index 66e7d26b70a4..11be70a7929f 100644
--- a/include/linux/netdev_features.h
+++ b/include/linux/netdev_features.h
@@ -253,4 +253,11 @@ static inline int find_next_netdev_feature(u64 feature, unsigned long start)
NETIF_F_GSO_UDP_TUNNEL | \
NETIF_F_GSO_UDP_TUNNEL_CSUM)
+static inline netdev_features_t netdev_base_features(netdev_features_t features)
+{
+ features &= ~NETIF_F_ONE_FOR_ALL;
+ features |= NETIF_F_ALL_FOR_ALL;
+ return features;
+}
+
#endif /* _LINUX_NETDEV_FEATURES_H */
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index ecc686409161..1812564b5204 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -82,6 +82,7 @@ struct xdp_metadata_ops;
struct xdp_md;
struct ethtool_netdev_state;
struct phy_link_topology;
+struct hwtstamp_provider;
typedef u32 xdp_features_t;
@@ -509,7 +510,7 @@ static inline bool napi_prefer_busy_poll(struct napi_struct *n)
* is scheduled for example in the context of delayed timer
* that can be skipped if a NAPI is already scheduled.
*
- * Return True if NAPI is scheduled, False otherwise.
+ * Return: True if NAPI is scheduled, False otherwise.
*/
static inline bool napi_is_scheduled(struct napi_struct *n)
{
@@ -524,7 +525,7 @@ bool napi_schedule_prep(struct napi_struct *n);
*
* Schedule NAPI poll routine to be called if it is not already
* running.
- * Return true if we schedule a NAPI or false if not.
+ * Return: true if we schedule a NAPI or false if not.
* Refer to napi_schedule_prep() for additional reason on why
* a NAPI might not be scheduled.
*/
@@ -558,7 +559,7 @@ static inline void napi_schedule_irqoff(struct napi_struct *n)
* Mark NAPI processing as complete. Should only be called if poll budget
* has not been completely consumed.
* Prefer over napi_complete().
- * Return false if device should avoid rearming interrupts.
+ * Return: false if device should avoid rearming interrupts.
*/
bool napi_complete_done(struct napi_struct *n, int work_done);
@@ -2045,6 +2046,7 @@ enum netdev_reg_state {
*
* @neighbours: List heads pointing to this device's neighbours'
* dev_list, one per address-family.
+ * @hwprov: Tracks which PTP performs hardware packet time stamping.
*
* FIXME: cleanup struct net_device such that network protocol info
* moves out.
@@ -2259,7 +2261,7 @@ struct net_device {
void *atalk_ptr;
#endif
#if IS_ENABLED(CONFIG_AX25)
- void *ax25_ptr;
+ struct ax25_dev __rcu *ax25_ptr;
#endif
#if IS_ENABLED(CONFIG_CFG80211)
struct wireless_dev *ieee80211_ptr;
@@ -2457,6 +2459,8 @@ struct net_device {
struct hlist_head neighbours[NEIGH_NR_TABLES];
+ struct hwtstamp_provider __rcu *hwprov;
+
u8 priv[] ____cacheline_aligned
__counted_by(priv_len);
} ____cacheline_aligned;
@@ -2854,6 +2858,46 @@ static inline void dev_lstats_add(struct net_device *dev, unsigned int len)
u64_stats_update_end(&lstats->syncp);
}
+static inline void dev_dstats_rx_add(struct net_device *dev,
+ unsigned int len)
+{
+ struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
+
+ u64_stats_update_begin(&dstats->syncp);
+ u64_stats_inc(&dstats->rx_packets);
+ u64_stats_add(&dstats->rx_bytes, len);
+ u64_stats_update_end(&dstats->syncp);
+}
+
+static inline void dev_dstats_rx_dropped(struct net_device *dev)
+{
+ struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
+
+ u64_stats_update_begin(&dstats->syncp);
+ u64_stats_inc(&dstats->rx_drops);
+ u64_stats_update_end(&dstats->syncp);
+}
+
+static inline void dev_dstats_tx_add(struct net_device *dev,
+ unsigned int len)
+{
+ struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
+
+ u64_stats_update_begin(&dstats->syncp);
+ u64_stats_inc(&dstats->tx_packets);
+ u64_stats_add(&dstats->tx_bytes, len);
+ u64_stats_update_end(&dstats->syncp);
+}
+
+static inline void dev_dstats_tx_dropped(struct net_device *dev)
+{
+ struct pcpu_dstats *dstats = this_cpu_ptr(dev->dstats);
+
+ u64_stats_update_begin(&dstats->syncp);
+ u64_stats_inc(&dstats->tx_drops);
+ u64_stats_update_end(&dstats->syncp);
+}
+
#define __netdev_alloc_pcpu_stats(type, gfp) \
({ \
typeof(type) __percpu *pcpu_stats = alloc_percpu_gfp(type, gfp);\
@@ -3322,6 +3366,7 @@ struct softnet_data {
};
DECLARE_PER_CPU_ALIGNED(struct softnet_data, softnet_data);
+DECLARE_PER_CPU(struct page_pool *, system_page_pool);
#ifndef CONFIG_PREEMPT_RT
static inline int dev_recursion_level(void)
@@ -3810,7 +3855,7 @@ static inline bool netif_attr_test_mask(unsigned long j,
* @online_mask: bitmask for CPUs/Rx queues that are online
* @nr_bits: number of bits in the bitmask
*
- * Returns true if a CPU/Rx queue is online.
+ * Returns: true if a CPU/Rx queue is online.
*/
static inline bool netif_attr_test_online(unsigned long j,
const unsigned long *online_mask,
@@ -3830,7 +3875,8 @@ static inline bool netif_attr_test_online(unsigned long j,
* @srcp: the cpumask/Rx queue mask pointer
* @nr_bits: number of bits in the bitmask
*
- * Returns >= nr_bits if no further CPUs/Rx queues set.
+ * Returns: next (after n) CPU/Rx queue index in the mask;
+ * >= nr_bits if no further CPUs/Rx queues set.
*/
static inline unsigned int netif_attrmask_next(int n, const unsigned long *srcp,
unsigned int nr_bits)
@@ -3852,7 +3898,8 @@ static inline unsigned int netif_attrmask_next(int n, const unsigned long *srcp,
* @src2p: the second CPUs/Rx queues mask pointer
* @nr_bits: number of bits in the bitmask
*
- * Returns >= nr_bits if no further CPUs/Rx queues set in both.
+ * Returns: next (after n) CPU/Rx queue index set in both masks;
+ * >= nr_bits if no further CPUs/Rx queues set in both.
*/
static inline int netif_attrmask_next_and(int n, const unsigned long *src1p,
const unsigned long *src2p,
@@ -3958,9 +4005,9 @@ static inline void dev_consume_skb_any(struct sk_buff *skb)
}
u32 bpf_prog_run_generic_xdp(struct sk_buff *skb, struct xdp_buff *xdp,
- struct bpf_prog *xdp_prog);
-void generic_xdp_tx(struct sk_buff *skb, struct bpf_prog *xdp_prog);
-int do_xdp_generic(struct bpf_prog *xdp_prog, struct sk_buff **pskb);
+ const struct bpf_prog *xdp_prog);
+void generic_xdp_tx(struct sk_buff *skb, const struct bpf_prog *xdp_prog);
+int do_xdp_generic(const struct bpf_prog *xdp_prog, struct sk_buff **pskb);
int netif_rx(struct sk_buff *skb);
int __netif_rx(struct sk_buff *skb);
@@ -4248,7 +4295,7 @@ static inline bool netif_carrier_ok(const struct net_device *dev)
unsigned long dev_trans_start(struct net_device *dev);
-void __netdev_watchdog_up(struct net_device *dev);
+void netdev_watchdog_up(struct net_device *dev);
void netif_carrier_on(struct net_device *dev);
void netif_carrier_off(struct net_device *dev);
diff --git a/include/linux/netfilter/x_tables.h b/include/linux/netfilter/x_tables.h
index 5897f3dbaf7c..f39f688d7285 100644
--- a/include/linux/netfilter/x_tables.h
+++ b/include/linux/netfilter/x_tables.h
@@ -357,7 +357,7 @@ extern struct static_key xt_tee_enabled;
* Begin packet processing : all readers must wait the end
* 1) Must be called with preemption disabled
* 2) softirqs must be disabled too (or we should use this_cpu_add())
- * Returns :
+ * Returns:
* 1 if no recursion on this cpu
* 0 if recursion detected
*/
diff --git a/include/linux/netfilter_netdev.h b/include/linux/netfilter_netdev.h
index 8676316547cc..3175073a66ba 100644
--- a/include/linux/netfilter_netdev.h
+++ b/include/linux/netfilter_netdev.h
@@ -66,7 +66,6 @@ static inline bool nf_hook_egress_active(void)
* @rc: result code which shall be returned by __dev_queue_xmit() on failure
* @dev: netdev whose egress hooks shall be applied to @skb
*
- * Returns @skb on success or %NULL if the packet was consumed or filtered.
* Caller must hold rcu_read_lock.
*
* On ingress, packets are classified first by tc, then by netfilter.
@@ -81,6 +80,8 @@ static inline bool nf_hook_egress_active(void)
* called recursively by tunnel drivers such as vxlan, the flag is reverted to
* false after sch_handle_egress(). This ensures that netfilter is applied
* both on the overlay and underlying network.
+ *
+ * Returns: @skb on success or %NULL if the packet was consumed or filtered.
*/
static inline struct sk_buff *nf_hook_egress(struct sk_buff *skb, int *rc,
struct net_device *dev)
diff --git a/include/linux/netfs.h b/include/linux/netfs.h
index 5eaceef41e6c..ecdd5ced16a8 100644
--- a/include/linux/netfs.h
+++ b/include/linux/netfs.h
@@ -185,6 +185,7 @@ struct netfs_io_subrequest {
short error; /* 0 or error that occurred */
unsigned short debug_index; /* Index in list (for debugging output) */
unsigned int nr_segs; /* Number of segs in io_iter */
+ u8 retry_count; /* The number of retries (0 on initial pass) */
enum netfs_io_source source; /* Where to read from/write to */
unsigned char stream_nr; /* I/O stream this belongs to */
unsigned char curr_folioq_slot; /* Folio currently being read */
@@ -194,14 +195,13 @@ struct netfs_io_subrequest {
#define NETFS_SREQ_COPY_TO_CACHE 0 /* Set if should copy the data to the cache */
#define NETFS_SREQ_CLEAR_TAIL 1 /* Set if the rest of the read should be cleared */
#define NETFS_SREQ_SEEK_DATA_READ 3 /* Set if ->read() should SEEK_DATA first */
-#define NETFS_SREQ_NO_PROGRESS 4 /* Set if we didn't manage to read any data */
+#define NETFS_SREQ_MADE_PROGRESS 4 /* Set if we transferred at least some data */
#define NETFS_SREQ_ONDEMAND 5 /* Set if it's from on-demand read mode */
#define NETFS_SREQ_BOUNDARY 6 /* Set if ends on hard boundary (eg. ceph object) */
#define NETFS_SREQ_HIT_EOF 7 /* Set if short due to EOF */
#define NETFS_SREQ_IN_PROGRESS 8 /* Unlocked when the subrequest completes */
#define NETFS_SREQ_NEED_RETRY 9 /* Set if the filesystem requests a retry */
-#define NETFS_SREQ_RETRYING 10 /* Set if we're retrying */
-#define NETFS_SREQ_FAILED 11 /* Set if the subreq failed unretryably */
+#define NETFS_SREQ_FAILED 10 /* Set if the subreq failed unretryably */
};
enum netfs_io_origin {
@@ -269,7 +269,6 @@ struct netfs_io_request {
size_t prev_donated; /* Fallback for subreq->prev_donated */
refcount_t ref;
unsigned long flags;
-#define NETFS_RREQ_COPY_TO_CACHE 1 /* Need to write to the cache */
#define NETFS_RREQ_NO_UNLOCK_FOLIO 2 /* Don't unlock no_unlock_folio on completion */
#define NETFS_RREQ_DONT_UNLOCK_FOLIOS 3 /* Don't unlock the folios on completion */
#define NETFS_RREQ_FAILED 4 /* The request failed */
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 12d8e47bc5a3..559273a0f16d 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -1336,7 +1336,7 @@ struct pnfs_commit_array {
struct rcu_head rcu;
refcount_t refcount;
unsigned int nbuckets;
- struct pnfs_commit_bucket buckets[];
+ struct pnfs_commit_bucket buckets[] __counted_by(nbuckets);
};
struct pnfs_ds_commit_info {
diff --git a/include/linux/nvme.h b/include/linux/nvme.h
index 0a6e22038ce3..13377dde4527 100644
--- a/include/linux/nvme.h
+++ b/include/linux/nvme.h
@@ -389,6 +389,11 @@ enum {
NVME_CTRL_CTRATT_PREDICTABLE_LAT = 1 << 5,
NVME_CTRL_CTRATT_NAMESPACE_GRANULARITY = 1 << 7,
NVME_CTRL_CTRATT_UUID_LIST = 1 << 9,
+ NVME_CTRL_SGLS_BYTE_ALIGNED = 1,
+ NVME_CTRL_SGLS_DWORD_ALIGNED = 2,
+ NVME_CTRL_SGLS_KSDBDS = 1 << 2,
+ NVME_CTRL_SGLS_MSDS = 1 << 19,
+ NVME_CTRL_SGLS_SAOS = 1 << 20,
};
struct nvme_lbaf {
@@ -2166,4 +2171,13 @@ enum nvme_pr_release_action {
NVME_PR_RELEASE_ACT_CLEAR = 1,
};
+enum nvme_pr_change_ptpl {
+ NVME_PR_CPTPL_NO_CHANGE = 0,
+ NVME_PR_CPTPL_RESV = 1 << 30,
+ NVME_PR_CPTPL_CLEARED = 2 << 30,
+ NVME_PR_CPTPL_PERSIST = 3 << 30,
+};
+
+#define NVME_PR_IGNORE_KEY (1 << 3)
+
#endif /* _LINUX_NVME_H */
diff --git a/include/linux/of.h b/include/linux/of.h
index 086a60f3b8a6..f921786cb8ac 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -289,6 +289,9 @@ extern struct device_node *of_get_parent(const struct device_node *node);
extern struct device_node *of_get_next_parent(struct device_node *node);
extern struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev);
+extern struct device_node *of_get_next_child_with_prefix(const struct device_node *node,
+ struct device_node *prev,
+ const char *prefix);
extern struct device_node *of_get_next_available_child(
const struct device_node *node, struct device_node *prev);
extern struct device_node *of_get_next_reserved_child(
@@ -1468,6 +1471,12 @@ static inline int of_property_read_s32(const struct device_node *np,
child != NULL; \
child = of_get_next_child(parent, child))
+#define for_each_child_of_node_with_prefix(parent, child, prefix) \
+ for (struct device_node *child __free(device_node) = \
+ of_get_next_child_with_prefix(parent, NULL, prefix); \
+ child != NULL; \
+ child = of_get_next_child_with_prefix(parent, child, prefix))
+
#define for_each_available_child_of_node(parent, child) \
for (child = of_get_next_available_child(parent, NULL); child != NULL; \
child = of_get_next_available_child(parent, child))
@@ -1651,6 +1660,10 @@ static inline int of_changeset_add_prop_u32(struct of_changeset *ocs,
return of_changeset_add_prop_u32_array(ocs, np, prop_name, &val, 1);
}
+int of_changeset_update_prop_string(struct of_changeset *ocs,
+ struct device_node *np,
+ const char *prop_name, const char *str);
+
int of_changeset_add_prop_bool(struct of_changeset *ocs, struct device_node *np,
const char *prop_name);
diff --git a/include/linux/once.h b/include/linux/once.h
index bc714d414448..30346fcdc799 100644
--- a/include/linux/once.h
+++ b/include/linux/once.h
@@ -46,7 +46,7 @@ void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,
#define DO_ONCE(func, ...) \
({ \
bool ___ret = false; \
- static bool __section(".data.once") ___done = false; \
+ static bool __section(".data..once") ___done = false; \
static DEFINE_STATIC_KEY_TRUE(___once_key); \
if (static_branch_unlikely(&___once_key)) { \
unsigned long ___flags; \
@@ -64,7 +64,7 @@ void __do_once_sleepable_done(bool *done, struct static_key_true *once_key,
#define DO_ONCE_SLEEPABLE(func, ...) \
({ \
bool ___ret = false; \
- static bool __section(".data.once") ___done = false; \
+ static bool __section(".data..once") ___done = false; \
static DEFINE_STATIC_KEY_TRUE(___once_key); \
if (static_branch_unlikely(&___once_key)) { \
___ret = __do_once_sleepable_start(&___done); \
diff --git a/include/linux/once_lite.h b/include/linux/once_lite.h
index b7bce4983638..27de7bc32a06 100644
--- a/include/linux/once_lite.h
+++ b/include/linux/once_lite.h
@@ -12,7 +12,7 @@
#define __ONCE_LITE_IF(condition) \
({ \
- static bool __section(".data.once") __already_done; \
+ static bool __section(".data..once") __already_done; \
bool __ret_cond = !!(condition); \
bool __ret_once = false; \
\
diff --git a/include/linux/packing.h b/include/linux/packing.h
index 5d36dcd06f60..0589d70bbe04 100644
--- a/include/linux/packing.h
+++ b/include/linux/packing.h
@@ -8,6 +8,83 @@
#include <linux/types.h>
#include <linux/bitops.h>
+#define GEN_PACKED_FIELD_STRUCT(__type) \
+ struct packed_field_ ## __type { \
+ __type startbit; \
+ __type endbit; \
+ __type offset; \
+ __type size; \
+ }
+
+/* struct packed_field_u8. Use with bit offsets < 256, buffers < 32B and
+ * unpacked structures < 256B.
+ */
+GEN_PACKED_FIELD_STRUCT(u8);
+
+/* struct packed_field_u16. Use with bit offsets < 65536, buffers < 8KB and
+ * unpacked structures < 64KB.
+ */
+GEN_PACKED_FIELD_STRUCT(u16);
+
+#define PACKED_FIELD(start, end, struct_name, struct_field) \
+{ \
+ (start), \
+ (end), \
+ offsetof(struct_name, struct_field), \
+ sizeof_field(struct_name, struct_field), \
+}
+
+#define CHECK_PACKED_FIELD_OVERLAP(fields, index1, index2) ({ \
+ typeof(&(fields)[0]) __f = (fields); \
+ typeof(__f[0]) _f1 = __f[index1]; typeof(__f[0]) _f2 = __f[index2]; \
+ const bool _ascending = __f[0].startbit < __f[1].startbit; \
+ BUILD_BUG_ON_MSG(_ascending && _f1.startbit >= _f2.startbit, \
+ __stringify(fields) " field " __stringify(index2) \
+ " breaks ascending order"); \
+ BUILD_BUG_ON_MSG(!_ascending && _f1.startbit <= _f2.startbit, \
+ __stringify(fields) " field " __stringify(index2) \
+ " breaks descending order"); \
+ BUILD_BUG_ON_MSG(max(_f1.endbit, _f2.endbit) <= \
+ min(_f1.startbit, _f2.startbit), \
+ __stringify(fields) " field " __stringify(index2) \
+ " overlaps with previous field"); \
+})
+
+#define CHECK_PACKED_FIELD(fields, index) ({ \
+ typeof(&(fields)[0]) _f = (fields); \
+ typeof(_f[0]) __f = _f[index]; \
+ BUILD_BUG_ON_MSG(__f.startbit < __f.endbit, \
+ __stringify(fields) " field " __stringify(index) \
+ " start bit must not be smaller than end bit"); \
+ BUILD_BUG_ON_MSG(__f.size != 1 && __f.size != 2 && \
+ __f.size != 4 && __f.size != 8, \
+ __stringify(fields) " field " __stringify(index) \
+ " has unsupported unpacked storage size"); \
+ BUILD_BUG_ON_MSG(__f.startbit - __f.endbit >= BITS_PER_BYTE * __f.size, \
+ __stringify(fields) " field " __stringify(index) \
+ " exceeds unpacked storage size"); \
+ __builtin_choose_expr(index != 0, \
+ CHECK_PACKED_FIELD_OVERLAP(fields, index - 1, index), \
+ 1); \
+})
+
+/* Note that the packed fields may be either in ascending or descending order.
+ * Thus, we must check that both the first and last field wit within the
+ * packed buffer size.
+ */
+#define CHECK_PACKED_FIELDS_SIZE(fields, pbuflen) ({ \
+ typeof(&(fields)[0]) _f = (fields); \
+ typeof(pbuflen) _len = (pbuflen); \
+ const size_t num_fields = ARRAY_SIZE(fields); \
+ BUILD_BUG_ON_MSG(!__builtin_constant_p(_len), \
+ __stringify(fields) " pbuflen " __stringify(pbuflen) \
+ " must be a compile time constant"); \
+ BUILD_BUG_ON_MSG(_f[0].startbit >= BITS_PER_BYTE * _len, \
+ __stringify(fields) " first field exceeds packed buffer size"); \
+ BUILD_BUG_ON_MSG(_f[num_fields - 1].startbit >= BITS_PER_BYTE * _len, \
+ __stringify(fields) " last field exceeds packed buffer size"); \
+})
+
#define QUIRK_MSB_ON_THE_RIGHT BIT(0)
#define QUIRK_LITTLE_ENDIAN BIT(1)
#define QUIRK_LSW32_IS_FIRST BIT(2)
@@ -26,4 +103,352 @@ int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen,
int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
size_t pbuflen, u8 quirks);
+void pack_fields_u8(void *pbuf, size_t pbuflen, const void *ustruct,
+ const struct packed_field_u8 *fields, size_t num_fields,
+ u8 quirks);
+
+void pack_fields_u16(void *pbuf, size_t pbuflen, const void *ustruct,
+ const struct packed_field_u16 *fields, size_t num_fields,
+ u8 quirks);
+
+void unpack_fields_u8(const void *pbuf, size_t pbuflen, void *ustruct,
+ const struct packed_field_u8 *fields, size_t num_fields,
+ u8 quirks);
+
+void unpack_fields_u16(const void *pbuf, size_t pbuflen, void *ustruct,
+ const struct packed_field_u16 *fields, size_t num_fields,
+ u8 quirks);
+
+/* Do not hand-edit the following packed field check macros!
+ *
+ * They are generated using scripts/gen_packed_field_checks.c, which may be
+ * built via "make scripts_gen_packed_field_checks". If larger macro sizes are
+ * needed in the future, please use this program to re-generate the macros and
+ * insert them here.
+ */
+
+#define CHECK_PACKED_FIELDS_1(fields) \
+ CHECK_PACKED_FIELD(fields, 0)
+
+#define CHECK_PACKED_FIELDS_2(fields) do { \
+ CHECK_PACKED_FIELDS_1(fields); \
+ CHECK_PACKED_FIELD(fields, 1); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_3(fields) do { \
+ CHECK_PACKED_FIELDS_2(fields); \
+ CHECK_PACKED_FIELD(fields, 2); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_4(fields) do { \
+ CHECK_PACKED_FIELDS_3(fields); \
+ CHECK_PACKED_FIELD(fields, 3); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_5(fields) do { \
+ CHECK_PACKED_FIELDS_4(fields); \
+ CHECK_PACKED_FIELD(fields, 4); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_6(fields) do { \
+ CHECK_PACKED_FIELDS_5(fields); \
+ CHECK_PACKED_FIELD(fields, 5); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_7(fields) do { \
+ CHECK_PACKED_FIELDS_6(fields); \
+ CHECK_PACKED_FIELD(fields, 6); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_8(fields) do { \
+ CHECK_PACKED_FIELDS_7(fields); \
+ CHECK_PACKED_FIELD(fields, 7); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_9(fields) do { \
+ CHECK_PACKED_FIELDS_8(fields); \
+ CHECK_PACKED_FIELD(fields, 8); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_10(fields) do { \
+ CHECK_PACKED_FIELDS_9(fields); \
+ CHECK_PACKED_FIELD(fields, 9); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_11(fields) do { \
+ CHECK_PACKED_FIELDS_10(fields); \
+ CHECK_PACKED_FIELD(fields, 10); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_12(fields) do { \
+ CHECK_PACKED_FIELDS_11(fields); \
+ CHECK_PACKED_FIELD(fields, 11); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_13(fields) do { \
+ CHECK_PACKED_FIELDS_12(fields); \
+ CHECK_PACKED_FIELD(fields, 12); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_14(fields) do { \
+ CHECK_PACKED_FIELDS_13(fields); \
+ CHECK_PACKED_FIELD(fields, 13); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_15(fields) do { \
+ CHECK_PACKED_FIELDS_14(fields); \
+ CHECK_PACKED_FIELD(fields, 14); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_16(fields) do { \
+ CHECK_PACKED_FIELDS_15(fields); \
+ CHECK_PACKED_FIELD(fields, 15); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_17(fields) do { \
+ CHECK_PACKED_FIELDS_16(fields); \
+ CHECK_PACKED_FIELD(fields, 16); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_18(fields) do { \
+ CHECK_PACKED_FIELDS_17(fields); \
+ CHECK_PACKED_FIELD(fields, 17); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_19(fields) do { \
+ CHECK_PACKED_FIELDS_18(fields); \
+ CHECK_PACKED_FIELD(fields, 18); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_20(fields) do { \
+ CHECK_PACKED_FIELDS_19(fields); \
+ CHECK_PACKED_FIELD(fields, 19); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_21(fields) do { \
+ CHECK_PACKED_FIELDS_20(fields); \
+ CHECK_PACKED_FIELD(fields, 20); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_22(fields) do { \
+ CHECK_PACKED_FIELDS_21(fields); \
+ CHECK_PACKED_FIELD(fields, 21); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_23(fields) do { \
+ CHECK_PACKED_FIELDS_22(fields); \
+ CHECK_PACKED_FIELD(fields, 22); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_24(fields) do { \
+ CHECK_PACKED_FIELDS_23(fields); \
+ CHECK_PACKED_FIELD(fields, 23); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_25(fields) do { \
+ CHECK_PACKED_FIELDS_24(fields); \
+ CHECK_PACKED_FIELD(fields, 24); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_26(fields) do { \
+ CHECK_PACKED_FIELDS_25(fields); \
+ CHECK_PACKED_FIELD(fields, 25); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_27(fields) do { \
+ CHECK_PACKED_FIELDS_26(fields); \
+ CHECK_PACKED_FIELD(fields, 26); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_28(fields) do { \
+ CHECK_PACKED_FIELDS_27(fields); \
+ CHECK_PACKED_FIELD(fields, 27); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_29(fields) do { \
+ CHECK_PACKED_FIELDS_28(fields); \
+ CHECK_PACKED_FIELD(fields, 28); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_30(fields) do { \
+ CHECK_PACKED_FIELDS_29(fields); \
+ CHECK_PACKED_FIELD(fields, 29); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_31(fields) do { \
+ CHECK_PACKED_FIELDS_30(fields); \
+ CHECK_PACKED_FIELD(fields, 30); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_32(fields) do { \
+ CHECK_PACKED_FIELDS_31(fields); \
+ CHECK_PACKED_FIELD(fields, 31); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_33(fields) do { \
+ CHECK_PACKED_FIELDS_32(fields); \
+ CHECK_PACKED_FIELD(fields, 32); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_34(fields) do { \
+ CHECK_PACKED_FIELDS_33(fields); \
+ CHECK_PACKED_FIELD(fields, 33); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_35(fields) do { \
+ CHECK_PACKED_FIELDS_34(fields); \
+ CHECK_PACKED_FIELD(fields, 34); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_36(fields) do { \
+ CHECK_PACKED_FIELDS_35(fields); \
+ CHECK_PACKED_FIELD(fields, 35); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_37(fields) do { \
+ CHECK_PACKED_FIELDS_36(fields); \
+ CHECK_PACKED_FIELD(fields, 36); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_38(fields) do { \
+ CHECK_PACKED_FIELDS_37(fields); \
+ CHECK_PACKED_FIELD(fields, 37); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_39(fields) do { \
+ CHECK_PACKED_FIELDS_38(fields); \
+ CHECK_PACKED_FIELD(fields, 38); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_40(fields) do { \
+ CHECK_PACKED_FIELDS_39(fields); \
+ CHECK_PACKED_FIELD(fields, 39); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_41(fields) do { \
+ CHECK_PACKED_FIELDS_40(fields); \
+ CHECK_PACKED_FIELD(fields, 40); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_42(fields) do { \
+ CHECK_PACKED_FIELDS_41(fields); \
+ CHECK_PACKED_FIELD(fields, 41); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_43(fields) do { \
+ CHECK_PACKED_FIELDS_42(fields); \
+ CHECK_PACKED_FIELD(fields, 42); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_44(fields) do { \
+ CHECK_PACKED_FIELDS_43(fields); \
+ CHECK_PACKED_FIELD(fields, 43); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_45(fields) do { \
+ CHECK_PACKED_FIELDS_44(fields); \
+ CHECK_PACKED_FIELD(fields, 44); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_46(fields) do { \
+ CHECK_PACKED_FIELDS_45(fields); \
+ CHECK_PACKED_FIELD(fields, 45); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_47(fields) do { \
+ CHECK_PACKED_FIELDS_46(fields); \
+ CHECK_PACKED_FIELD(fields, 46); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_48(fields) do { \
+ CHECK_PACKED_FIELDS_47(fields); \
+ CHECK_PACKED_FIELD(fields, 47); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_49(fields) do { \
+ CHECK_PACKED_FIELDS_48(fields); \
+ CHECK_PACKED_FIELD(fields, 48); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS_50(fields) do { \
+ CHECK_PACKED_FIELDS_49(fields); \
+ CHECK_PACKED_FIELD(fields, 49); \
+} while (0)
+
+#define CHECK_PACKED_FIELDS(fields) \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 1, ({ CHECK_PACKED_FIELDS_1(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 2, ({ CHECK_PACKED_FIELDS_2(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 3, ({ CHECK_PACKED_FIELDS_3(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 4, ({ CHECK_PACKED_FIELDS_4(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 5, ({ CHECK_PACKED_FIELDS_5(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 6, ({ CHECK_PACKED_FIELDS_6(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 7, ({ CHECK_PACKED_FIELDS_7(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 8, ({ CHECK_PACKED_FIELDS_8(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 9, ({ CHECK_PACKED_FIELDS_9(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 10, ({ CHECK_PACKED_FIELDS_10(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 11, ({ CHECK_PACKED_FIELDS_11(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 12, ({ CHECK_PACKED_FIELDS_12(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 13, ({ CHECK_PACKED_FIELDS_13(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 14, ({ CHECK_PACKED_FIELDS_14(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 15, ({ CHECK_PACKED_FIELDS_15(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 16, ({ CHECK_PACKED_FIELDS_16(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 17, ({ CHECK_PACKED_FIELDS_17(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 18, ({ CHECK_PACKED_FIELDS_18(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 19, ({ CHECK_PACKED_FIELDS_19(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 20, ({ CHECK_PACKED_FIELDS_20(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 21, ({ CHECK_PACKED_FIELDS_21(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 22, ({ CHECK_PACKED_FIELDS_22(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 23, ({ CHECK_PACKED_FIELDS_23(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 24, ({ CHECK_PACKED_FIELDS_24(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 25, ({ CHECK_PACKED_FIELDS_25(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 26, ({ CHECK_PACKED_FIELDS_26(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 27, ({ CHECK_PACKED_FIELDS_27(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 28, ({ CHECK_PACKED_FIELDS_28(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 29, ({ CHECK_PACKED_FIELDS_29(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 30, ({ CHECK_PACKED_FIELDS_30(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 31, ({ CHECK_PACKED_FIELDS_31(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 32, ({ CHECK_PACKED_FIELDS_32(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 33, ({ CHECK_PACKED_FIELDS_33(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 34, ({ CHECK_PACKED_FIELDS_34(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 35, ({ CHECK_PACKED_FIELDS_35(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 36, ({ CHECK_PACKED_FIELDS_36(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 37, ({ CHECK_PACKED_FIELDS_37(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 38, ({ CHECK_PACKED_FIELDS_38(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 39, ({ CHECK_PACKED_FIELDS_39(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 40, ({ CHECK_PACKED_FIELDS_40(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 41, ({ CHECK_PACKED_FIELDS_41(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 42, ({ CHECK_PACKED_FIELDS_42(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 43, ({ CHECK_PACKED_FIELDS_43(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 44, ({ CHECK_PACKED_FIELDS_44(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 45, ({ CHECK_PACKED_FIELDS_45(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 46, ({ CHECK_PACKED_FIELDS_46(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 47, ({ CHECK_PACKED_FIELDS_47(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 48, ({ CHECK_PACKED_FIELDS_48(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 49, ({ CHECK_PACKED_FIELDS_49(fields); }), \
+ __builtin_choose_expr(ARRAY_SIZE(fields) == 50, ({ CHECK_PACKED_FIELDS_50(fields); }), \
+ ({ BUILD_BUG_ON_MSG(1, "CHECK_PACKED_FIELDS() must be regenerated to support array sizes larger than 50."); }) \
+))))))))))))))))))))))))))))))))))))))))))))))))))
+
+/* End of generated content */
+
+#define pack_fields(pbuf, pbuflen, ustruct, fields, quirks) \
+ ({ \
+ CHECK_PACKED_FIELDS(fields); \
+ CHECK_PACKED_FIELDS_SIZE((fields), (pbuflen)); \
+ _Generic((fields), \
+ const struct packed_field_u8 * : pack_fields_u8, \
+ const struct packed_field_u16 * : pack_fields_u16 \
+ )((pbuf), (pbuflen), (ustruct), (fields), ARRAY_SIZE(fields), (quirks)); \
+ })
+
+#define unpack_fields(pbuf, pbuflen, ustruct, fields, quirks) \
+ ({ \
+ CHECK_PACKED_FIELDS(fields); \
+ CHECK_PACKED_FIELDS_SIZE((fields), (pbuflen)); \
+ _Generic((fields), \
+ const struct packed_field_u8 * : unpack_fields_u8, \
+ const struct packed_field_u16 * : unpack_fields_u16 \
+ )((pbuf), (pbuflen), (ustruct), (fields), ARRAY_SIZE(fields), (quirks)); \
+ })
+
#endif
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h
index 2220bfec278e..691506bdf2c5 100644
--- a/include/linux/page-flags.h
+++ b/include/linux/page-flags.h
@@ -306,7 +306,7 @@ static const unsigned long *const_folio_flags(const struct folio *folio,
{
const struct page *page = &folio->page;
- VM_BUG_ON_PGFLAGS(PageTail(page), page);
+ VM_BUG_ON_PGFLAGS(page->compound_head & 1, page);
VM_BUG_ON_PGFLAGS(n > 0 && !test_bit(PG_head, &page->flags), page);
return &page[n].flags;
}
@@ -315,7 +315,7 @@ static unsigned long *folio_flags(struct folio *folio, unsigned n)
{
struct page *page = &folio->page;
- VM_BUG_ON_PGFLAGS(PageTail(page), page);
+ VM_BUG_ON_PGFLAGS(page->compound_head & 1, page);
VM_BUG_ON_PGFLAGS(n > 0 && !test_bit(PG_head, &page->flags), page);
return &page[n].flags;
}
@@ -862,18 +862,10 @@ static inline void ClearPageCompound(struct page *page)
ClearPageHead(page);
}
FOLIO_FLAG(large_rmappable, FOLIO_SECOND_PAGE)
-FOLIO_TEST_FLAG(partially_mapped, FOLIO_SECOND_PAGE)
-/*
- * PG_partially_mapped is protected by deferred_split split_queue_lock,
- * so its safe to use non-atomic set/clear.
- */
-__FOLIO_SET_FLAG(partially_mapped, FOLIO_SECOND_PAGE)
-__FOLIO_CLEAR_FLAG(partially_mapped, FOLIO_SECOND_PAGE)
+FOLIO_FLAG(partially_mapped, FOLIO_SECOND_PAGE)
#else
FOLIO_FLAG_FALSE(large_rmappable)
-FOLIO_TEST_FLAG_FALSE(partially_mapped)
-__FOLIO_SET_FLAG_NOOP(partially_mapped)
-__FOLIO_CLEAR_FLAG_NOOP(partially_mapped)
+FOLIO_FLAG_FALSE(partially_mapped)
#endif
#define PG_head_mask ((1UL << PG_head))
diff --git a/include/linux/pci.h b/include/linux/pci.h
index db9b47ce3eef..414ee5fff66b 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1047,6 +1047,20 @@ struct pci_driver {
.subvendor = PCI_ANY_ID, .subdevice = PCI_ANY_ID, 0, 0
/**
+ * PCI_VDEVICE_SUB - describe a specific PCI device/subdevice in a short form
+ * @vend: the vendor name
+ * @dev: the 16 bit PCI Device ID
+ * @subvend: the 16 bit PCI Subvendor ID
+ * @subdev: the 16 bit PCI Subdevice ID
+ *
+ * Generate the pci_device_id struct layout for the specific PCI
+ * device/subdevice. Private data may follow the output.
+ */
+#define PCI_VDEVICE_SUB(vend, dev, subvend, subdev) \
+ .vendor = PCI_VENDOR_ID_##vend, .device = (dev), \
+ .subvendor = (subvend), .subdevice = (subdev), 0, 0
+
+/**
* PCI_DEVICE_DATA - macro used to describe a specific PCI device in very short form
* @vend: the vendor name (without PCI_VENDOR_ID_ prefix)
* @dev: the device name (without PCI_DEVICE_ID_<vend>_ prefix)
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index e4bddb927795..d2402bf4aea2 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -121,6 +121,7 @@
#define PCI_CLASS_SERIAL_USB_OHCI 0x0c0310
#define PCI_CLASS_SERIAL_USB_EHCI 0x0c0320
#define PCI_CLASS_SERIAL_USB_XHCI 0x0c0330
+#define PCI_CLASS_SERIAL_USB_CDNS 0x0c0380
#define PCI_CLASS_SERIAL_USB_DEVICE 0x0c03fe
#define PCI_CLASS_SERIAL_FIBER 0x0c04
#define PCI_CLASS_SERIAL_SMBUS 0x0c05
@@ -2421,6 +2422,9 @@
#define PCI_VENDOR_ID_QCOM 0x17cb
#define PCI_VENDOR_ID_CDNS 0x17cd
+#define PCI_DEVICE_ID_CDNS_USBSS 0x0100
+#define PCI_DEVICE_ID_CDNS_USB 0x0120
+#define PCI_DEVICE_ID_CDNS_USBSSP 0x0200
#define PCI_VENDOR_ID_ARECA 0x17d3
#define PCI_DEVICE_ID_ARECA_1110 0x1110
diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h
index b5b5d17998b8..733f4ddd2ef1 100644
--- a/include/linux/pcs/pcs-xpcs.h
+++ b/include/linux/pcs/pcs-xpcs.h
@@ -50,7 +50,6 @@ struct dw_xpcs;
struct phylink_pcs *xpcs_to_phylink_pcs(struct dw_xpcs *xpcs);
int xpcs_get_an_mode(struct dw_xpcs *xpcs, phy_interface_t interface);
-void xpcs_get_interfaces(struct dw_xpcs *xpcs, unsigned long *interfaces);
int xpcs_config_eee(struct dw_xpcs *xpcs, int mult_fact_100ns,
int enable);
struct dw_xpcs *xpcs_create_mdiodev(struct mii_bus *bus, int addr);
diff --git a/include/linux/percpu-defs.h b/include/linux/percpu-defs.h
index 35842d1e3879..5b520fe86b60 100644
--- a/include/linux/percpu-defs.h
+++ b/include/linux/percpu-defs.h
@@ -221,10 +221,7 @@ do { \
} while (0)
#define PERCPU_PTR(__p) \
-({ \
- unsigned long __pcpu_ptr = (__force unsigned long)(__p); \
- (typeof(*(__p)) __force __kernel *)(__pcpu_ptr); \
-})
+ (typeof(*(__p)) __force __kernel *)((__force unsigned long)(__p))
#ifdef CONFIG_SMP
diff --git a/include/linux/pgalloc_tag.h b/include/linux/pgalloc_tag.h
index 0e43ab653ab6..3469c4b20105 100644
--- a/include/linux/pgalloc_tag.h
+++ b/include/linux/pgalloc_tag.h
@@ -231,7 +231,7 @@ static inline void pgalloc_tag_sub_pages(struct alloc_tag *tag, unsigned int nr)
}
void pgalloc_tag_split(struct folio *folio, int old_order, int new_order);
-void pgalloc_tag_copy(struct folio *new, struct folio *old);
+void pgalloc_tag_swap(struct folio *new, struct folio *old);
void __init alloc_tag_sec_init(void);
@@ -245,7 +245,7 @@ static inline struct alloc_tag *pgalloc_tag_get(struct page *page) { return NULL
static inline void pgalloc_tag_sub_pages(struct alloc_tag *tag, unsigned int nr) {}
static inline void alloc_tag_sec_init(void) {}
static inline void pgalloc_tag_split(struct folio *folio, int old_order, int new_order) {}
-static inline void pgalloc_tag_copy(struct folio *new, struct folio *old) {}
+static inline void pgalloc_tag_swap(struct folio *new, struct folio *old) {}
#endif /* CONFIG_MEM_ALLOC_PROFILING */
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 61a1bc81f597..5bc71d59910c 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -298,6 +298,29 @@ static inline const char *phy_modes(phy_interface_t interface)
}
}
+/**
+ * rgmii_clock - map link speed to the clock rate
+ * @speed: link speed value
+ *
+ * Description: maps RGMII supported link speeds
+ * into the clock rates.
+ *
+ * Returns: clock rate or negative errno
+ */
+static inline long rgmii_clock(int speed)
+{
+ switch (speed) {
+ case SPEED_10:
+ return 2500000;
+ case SPEED_100:
+ return 25000000;
+ case SPEED_1000:
+ return 125000000;
+ default:
+ return -EINVAL;
+ }
+}
+
#define PHY_INIT_TIMEOUT 100000
#define PHY_FORCE_TIMEOUT 10
@@ -1991,7 +2014,7 @@ int genphy_c45_plca_set_cfg(struct phy_device *phydev,
int genphy_c45_plca_get_status(struct phy_device *phydev,
struct phy_plca_status *plca_st);
int genphy_c45_eee_is_active(struct phy_device *phydev, unsigned long *adv,
- unsigned long *lp, bool *is_enabled);
+ unsigned long *lp);
int genphy_c45_ethtool_get_eee(struct phy_device *phydev,
struct ethtool_keee *data);
int genphy_c45_ethtool_set_eee(struct phy_device *phydev,
@@ -2048,6 +2071,7 @@ void phy_advertise_eee_all(struct phy_device *phydev);
void phy_support_sym_pause(struct phy_device *phydev);
void phy_support_asym_pause(struct phy_device *phydev);
void phy_support_eee(struct phy_device *phydev);
+void phy_disable_eee(struct phy_device *phydev);
void phy_set_sym_pause(struct phy_device *phydev, bool rx, bool tx,
bool autoneg);
void phy_set_asym_pause(struct phy_device *phydev, bool rx, bool tx);
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 5462cc6a37dc..4b7a20620b49 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -393,6 +393,8 @@ struct phylink_pcs_ops;
/**
* struct phylink_pcs - PHYLINK PCS instance
+ * @supported_interfaces: describing which PHY_INTERFACE_MODE_xxx
+ * are supported by this PCS.
* @ops: a pointer to the &struct phylink_pcs_ops structure
* @phylink: pointer to &struct phylink_config
* @neg_mode: provide PCS neg mode via "mode" argument
@@ -409,6 +411,7 @@ struct phylink_pcs_ops;
* the PCS driver.
*/
struct phylink_pcs {
+ DECLARE_PHY_INTERFACE_MASK(supported_interfaces);
const struct phylink_pcs_ops *ops;
struct phylink *phylink;
bool neg_mode;
diff --git a/include/linux/platform_data/amd_qdma.h b/include/linux/platform_data/amd_qdma.h
index 576d952f97ed..967a6ef31cf9 100644
--- a/include/linux/platform_data/amd_qdma.h
+++ b/include/linux/platform_data/amd_qdma.h
@@ -26,11 +26,13 @@ struct dma_slave_map;
* @max_mm_channels: Maximum number of MM DMA channels in each direction
* @device_map: DMA slave map
* @irq_index: The index of first IRQ
+ * @dma_dev: The device pointer for dma operations
*/
struct qdma_platdata {
u32 max_mm_channels;
u32 irq_index;
struct dma_slave_map *device_map;
+ struct device *dma_dev;
};
#endif /* _PLATDATA_AMD_QDMA_H */
diff --git a/include/linux/platform_data/sa11x0-serial.h b/include/linux/platform_data/sa11x0-serial.h
index 8b79ab08af45..a88096bc74e4 100644
--- a/include/linux/platform_data/sa11x0-serial.h
+++ b/include/linux/platform_data/sa11x0-serial.h
@@ -10,7 +10,6 @@
#define SA11X0_SERIAL_H
struct uart_port;
-struct uart_info;
/*
* This is a temporary structure for registering these
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index 7132623e4658..074754c23d33 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -235,17 +235,7 @@ extern void platform_device_put(struct platform_device *pdev);
struct platform_driver {
int (*probe)(struct platform_device *);
-
- /*
- * .remove_new() is a relic from a prototype conversion of .remove().
- * New drivers are supposed to implement .remove(). Once all drivers are
- * converted to not use .remove_new any more, it will be dropped.
- */
- union {
- void (*remove)(struct platform_device *);
- void (*remove_new)(struct platform_device *);
- };
-
+ void (*remove)(struct platform_device *);
void (*shutdown)(struct platform_device *);
int (*suspend)(struct platform_device *, pm_message_t state);
int (*resume)(struct platform_device *);
diff --git a/include/linux/pm.h b/include/linux/pm.h
index 97b0e23363c8..e7f0260f15ad 100644
--- a/include/linux/pm.h
+++ b/include/linux/pm.h
@@ -385,7 +385,7 @@ const struct dev_pm_ops name = { \
#ifdef CONFIG_PM
#define _EXPORT_DEV_PM_OPS(name, license, ns) _EXPORT_PM_OPS(name, license, ns)
#define EXPORT_PM_FN_GPL(name) EXPORT_SYMBOL_GPL(name)
-#define EXPORT_PM_FN_NS_GPL(name, ns) EXPORT_SYMBOL_NS_GPL(name, ns)
+#define EXPORT_PM_FN_NS_GPL(name, ns) EXPORT_SYMBOL_NS_GPL(name, "ns")
#else
#define _EXPORT_DEV_PM_OPS(name, license, ns) _DISCARD_PM_OPS(name, license, ns)
#define EXPORT_PM_FN_GPL(name)
diff --git a/include/linux/ptp_clock_kernel.h b/include/linux/ptp_clock_kernel.h
index c892d22ce0a7..0d68d09bedd1 100644
--- a/include/linux/ptp_clock_kernel.h
+++ b/include/linux/ptp_clock_kernel.h
@@ -307,7 +307,7 @@ static inline u64 adjust_by_scaled_ppm(u64 base, long scaled_ppm)
* @info: Structure describing the new clock.
* @parent: Pointer to the parent device of the new clock.
*
- * Returns a valid pointer on success or PTR_ERR on failure. If PHC
+ * Returns: a valid pointer on success or PTR_ERR on failure. If PHC
* support is missing at the configuration level, this function
* returns NULL, and drivers are expected to gracefully handle that
* case separately.
@@ -445,7 +445,7 @@ int ptp_get_vclocks_index(int pclock_index, int **vclock_index);
* @hwtstamp: timestamp
* @vclock_index: phc index of ptp vclock.
*
- * Returns converted timestamp, or 0 on error.
+ * Returns: converted timestamp, or 0 on error.
*/
ktime_t ptp_convert_timestamp(const ktime_t *hwtstamp, int vclock_index);
#else
diff --git a/include/linux/ptr_ring.h b/include/linux/ptr_ring.h
index fd037c127bb0..551329220e4f 100644
--- a/include/linux/ptr_ring.h
+++ b/include/linux/ptr_ring.h
@@ -615,15 +615,14 @@ static inline int ptr_ring_resize_noprof(struct ptr_ring *r, int size, gfp_t gfp
/*
* Note: producer lock is nested within consumer lock, so if you
* resize you must make sure all uses nest correctly.
- * In particular if you consume ring in interrupt or BH context, you must
- * disable interrupts/BH when doing so.
+ * In particular if you consume ring in BH context, you must
+ * disable BH when doing so.
*/
-static inline int ptr_ring_resize_multiple_noprof(struct ptr_ring **rings,
- unsigned int nrings,
- int size,
- gfp_t gfp, void (*destroy)(void *))
+static inline int ptr_ring_resize_multiple_bh_noprof(struct ptr_ring **rings,
+ unsigned int nrings,
+ int size, gfp_t gfp,
+ void (*destroy)(void *))
{
- unsigned long flags;
void ***queues;
int i;
@@ -638,12 +637,12 @@ static inline int ptr_ring_resize_multiple_noprof(struct ptr_ring **rings,
}
for (i = 0; i < nrings; ++i) {
- spin_lock_irqsave(&(rings[i])->consumer_lock, flags);
+ spin_lock_bh(&(rings[i])->consumer_lock);
spin_lock(&(rings[i])->producer_lock);
queues[i] = __ptr_ring_swap_queue(rings[i], queues[i],
size, gfp, destroy);
spin_unlock(&(rings[i])->producer_lock);
- spin_unlock_irqrestore(&(rings[i])->consumer_lock, flags);
+ spin_unlock_bh(&(rings[i])->consumer_lock);
}
for (i = 0; i < nrings; ++i)
@@ -662,8 +661,8 @@ nomem:
noqueues:
return -ENOMEM;
}
-#define ptr_ring_resize_multiple(...) \
- alloc_hooks(ptr_ring_resize_multiple_noprof(__VA_ARGS__))
+#define ptr_ring_resize_multiple_bh(...) \
+ alloc_hooks(ptr_ring_resize_multiple_bh_noprof(__VA_ARGS__))
static inline void ptr_ring_cleanup(struct ptr_ring *r, void (*destroy)(void *))
{
diff --git a/include/linux/pwm.h b/include/linux/pwm.h
index 78827f312407..6853e29d9674 100644
--- a/include/linux/pwm.h
+++ b/include/linux/pwm.h
@@ -8,7 +8,7 @@
#include <linux/mutex.h>
#include <linux/of.h>
-MODULE_IMPORT_NS(PWM);
+MODULE_IMPORT_NS("PWM");
struct pwm_chip;
diff --git a/include/linux/rcupdate.h b/include/linux/rcupdate.h
index 58d84c59f3dd..48e5c03df1dd 100644
--- a/include/linux/rcupdate.h
+++ b/include/linux/rcupdate.h
@@ -401,7 +401,7 @@ static inline int debug_lockdep_rcu_enabled(void)
*/
#define RCU_LOCKDEP_WARN(c, s) \
do { \
- static bool __section(".data.unlikely") __warned; \
+ static bool __section(".data..unlikely") __warned; \
if (debug_lockdep_rcu_enabled() && (c) && \
debug_lockdep_rcu_enabled() && !__warned) { \
__warned = true; \
diff --git a/include/linux/rcupdate_trace.h b/include/linux/rcupdate_trace.h
index eda493200663..e6c44eb428ab 100644
--- a/include/linux/rcupdate_trace.h
+++ b/include/linux/rcupdate_trace.h
@@ -10,6 +10,7 @@
#include <linux/sched.h>
#include <linux/rcupdate.h>
+#include <linux/cleanup.h>
extern struct lockdep_map rcu_trace_lock_map;
@@ -98,4 +99,8 @@ static inline void rcu_read_lock_trace(void) { BUG(); }
static inline void rcu_read_unlock_trace(void) { BUG(); }
#endif /* #ifdef CONFIG_TASKS_TRACE_RCU */
+DEFINE_LOCK_GUARD_0(rcu_tasks_trace,
+ rcu_read_lock_trace(),
+ rcu_read_unlock_trace())
+
#endif /* __LINUX_RCUPDATE_TRACE_H */
diff --git a/include/linux/rfkill.h b/include/linux/rfkill.h
index 997b34197385..6816e4c5f3f0 100644
--- a/include/linux/rfkill.h
+++ b/include/linux/rfkill.h
@@ -241,7 +241,7 @@ bool rfkill_soft_blocked(struct rfkill *rfkill);
* rfkill_find_type - Helper for finding rfkill type by name
* @name: the name of the type
*
- * Returns enum rfkill_type that corresponds to the name.
+ * Returns: enum rfkill_type that corresponds to the name.
*/
enum rfkill_type rfkill_find_type(const char *name);
diff --git a/include/linux/rtc/m48t59.h b/include/linux/rtc/m48t59.h
index 9465d5405fe2..373ba77071c6 100644
--- a/include/linux/rtc/m48t59.h
+++ b/include/linux/rtc/m48t59.h
@@ -56,6 +56,9 @@ struct m48t59_plat_data {
void __iomem *ioaddr;
/* offset to RTC registers, automatically set according to the type */
unsigned int offset;
+
+ /* YY digits (in RTC) are offset, i.e. year is 1900 + yy_offset + YY */
+ int yy_offset;
};
#endif /* _LINUX_RTC_M48T59_H_ */
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index 14b88f551920..4bc2ee0b10b0 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -78,7 +78,7 @@ static inline bool lockdep_rtnl_is_held(void)
* rtnl_dereference - fetch RCU pointer when updates are prevented by RTNL
* @p: The pointer to read, prior to dereferencing
*
- * Return the value of the specified RCU-protected pointer, but omit
+ * Return: the value of the specified RCU-protected pointer, but omit
* the READ_ONCE(), because caller holds RTNL.
*/
#define rtnl_dereference(p) \
@@ -102,6 +102,7 @@ void __rtnl_net_unlock(struct net *net);
void rtnl_net_lock(struct net *net);
void rtnl_net_unlock(struct net *net);
int rtnl_net_trylock(struct net *net);
+int rtnl_net_lock_killable(struct net *net);
int rtnl_net_lock_cmp_fn(const struct lockdep_map *a, const struct lockdep_map *b);
bool rtnl_net_is_locked(struct net *net);
@@ -138,6 +139,11 @@ static inline int rtnl_net_trylock(struct net *net)
return rtnl_trylock();
}
+static inline int rtnl_net_lock_killable(struct net *net)
+{
+ return rtnl_lock_killable();
+}
+
static inline void ASSERT_RTNL_NET(struct net *net)
{
ASSERT_RTNL();
@@ -178,6 +184,12 @@ void rtnetlink_init(void);
void __rtnl_unlock(void);
void rtnl_kfree_skbs(struct sk_buff *head, struct sk_buff *tail);
+/* Shared by rtnl_fdb_dump() and various ndo_fdb_dump() helpers. */
+struct ndo_fdb_dump_context {
+ unsigned long ifindex;
+ unsigned long fdb_idx;
+};
+
extern int ndo_dflt_fdb_dump(struct sk_buff *skb,
struct netlink_callback *cb,
struct net_device *dev,
diff --git a/include/linux/rtsx_common.h b/include/linux/rtsx_common.h
index bf290ad14c57..da9c8c6b5d50 100644
--- a/include/linux/rtsx_common.h
+++ b/include/linux/rtsx_common.h
@@ -12,7 +12,6 @@
#define DRV_NAME_RTSX_PCI "rtsx_pci"
#define DRV_NAME_RTSX_PCI_SDMMC "rtsx_pci_sdmmc"
-#define DRV_NAME_RTSX_PCI_MS "rtsx_pci_ms"
#define RTSX_REG_PAIR(addr, val) (((u32)(addr) << 16) | (u8)(val))
diff --git a/include/linux/rtsx_usb.h b/include/linux/rtsx_usb.h
index 3247ed8e9ff0..f267a06c6b1e 100644
--- a/include/linux/rtsx_usb.h
+++ b/include/linux/rtsx_usb.h
@@ -12,6 +12,10 @@
#include <linux/usb.h>
+#define DRV_NAME_RTSX_USB "rtsx_usb"
+#define DRV_NAME_RTSX_USB_SDMMC "rtsx_usb_sdmmc"
+#define DRV_NAME_RTSX_USB_MS "rtsx_usb_ms"
+
/* related module names */
#define RTSX_USB_SD_CARD 0
#define RTSX_USB_MS_CARD 1
diff --git a/include/linux/scatterlist.h b/include/linux/scatterlist.h
index c5e2239b550e..d836e7440ee8 100644
--- a/include/linux/scatterlist.h
+++ b/include/linux/scatterlist.h
@@ -313,7 +313,7 @@ static inline void sg_dma_mark_bus_address(struct scatterlist *sg)
}
/**
- * sg_unmark_bus_address - Unmark the scatterlist entry as a bus address
+ * sg_dma_unmark_bus_address - Unmark the scatterlist entry as a bus address
* @sg: SG entry
*
* Description:
diff --git a/include/linux/sched.h b/include/linux/sched.h
index d380bffee2ef..64934e0830af 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -656,6 +656,12 @@ struct sched_dl_entity {
* @dl_defer_armed tells if the deferrable server is waiting
* for the replenishment timer to activate it.
*
+ * @dl_server_active tells if the dlserver is active(started).
+ * dlserver is started on first cfs enqueue on an idle runqueue
+ * and is stopped when a dequeue results in 0 cfs tasks on the
+ * runqueue. In other words, dlserver is active only when cpu's
+ * runqueue has atleast one cfs task.
+ *
* @dl_defer_running tells if the deferrable server is actually
* running, skipping the defer phase.
*/
@@ -664,6 +670,7 @@ struct sched_dl_entity {
unsigned int dl_non_contending : 1;
unsigned int dl_overrun : 1;
unsigned int dl_server : 1;
+ unsigned int dl_server_active : 1;
unsigned int dl_defer : 1;
unsigned int dl_defer_armed : 1;
unsigned int dl_defer_running : 1;
@@ -1630,8 +1637,9 @@ static inline unsigned int __task_state_index(unsigned int tsk_state,
* We're lying here, but rather than expose a completely new task state
* to userspace, we can make this appear as if the task has gone through
* a regular rt_mutex_lock() call.
+ * Report frozen tasks as uninterruptible.
*/
- if (tsk_state & TASK_RTLOCK_WAIT)
+ if ((tsk_state & TASK_RTLOCK_WAIT) || (tsk_state & TASK_FROZEN))
state = TASK_UNINTERRUPTIBLE;
return fls(state);
diff --git a/include/linux/skb_array.h b/include/linux/skb_array.h
index 926496c9cc9c..bf178238a308 100644
--- a/include/linux/skb_array.h
+++ b/include/linux/skb_array.h
@@ -199,17 +199,18 @@ static inline int skb_array_resize(struct skb_array *a, int size, gfp_t gfp)
return ptr_ring_resize(&a->ring, size, gfp, __skb_array_destroy_skb);
}
-static inline int skb_array_resize_multiple_noprof(struct skb_array **rings,
- int nrings, unsigned int size,
- gfp_t gfp)
+static inline int skb_array_resize_multiple_bh_noprof(struct skb_array **rings,
+ int nrings,
+ unsigned int size,
+ gfp_t gfp)
{
BUILD_BUG_ON(offsetof(struct skb_array, ring));
- return ptr_ring_resize_multiple_noprof((struct ptr_ring **)rings,
- nrings, size, gfp,
- __skb_array_destroy_skb);
+ return ptr_ring_resize_multiple_bh_noprof((struct ptr_ring **)rings,
+ nrings, size, gfp,
+ __skb_array_destroy_skb);
}
-#define skb_array_resize_multiple(...) \
- alloc_hooks(skb_array_resize_multiple_noprof(__VA_ARGS__))
+#define skb_array_resize_multiple_bh(...) \
+ alloc_hooks(skb_array_resize_multiple_bh_noprof(__VA_ARGS__))
static inline void skb_array_cleanup(struct skb_array *a)
{
diff --git a/include/linux/skbuff.h b/include/linux/skbuff.h
index 58009fa66102..bb2b751d274a 100644
--- a/include/linux/skbuff.h
+++ b/include/linux/skbuff.h
@@ -608,11 +608,19 @@ struct skb_shared_info {
* Warning : all fields before dataref are cleared in __alloc_skb()
*/
atomic_t dataref;
- unsigned int xdp_frags_size;
- /* Intermediate layers must ensure that destructor_arg
- * remains valid until skb destructor */
- void * destructor_arg;
+ union {
+ struct {
+ u32 xdp_frags_size;
+ u32 xdp_frags_truesize;
+ };
+
+ /*
+ * Intermediate layers must ensure that destructor_arg
+ * remains valid until skb destructor.
+ */
+ void *destructor_arg;
+ };
/* must be last field, see pskb_expand_head() */
skb_frag_t frags[MAX_SKB_FRAGS];
@@ -1134,7 +1142,7 @@ static inline bool skb_pfmemalloc(const struct sk_buff *skb)
* skb_dst - returns skb dst_entry
* @skb: buffer
*
- * Returns skb dst_entry, regardless of reference taken or not.
+ * Returns: skb dst_entry, regardless of reference taken or not.
*/
static inline struct dst_entry *skb_dst(const struct sk_buff *skb)
{
@@ -1222,7 +1230,7 @@ static inline bool skb_wifi_acked_valid(const struct sk_buff *skb)
* skb_unref - decrement the skb's reference count
* @skb: buffer
*
- * Returns true if we can free the skb.
+ * Returns: true if we can free the skb.
*/
static inline bool skb_unref(struct sk_buff *skb)
{
@@ -1344,7 +1352,7 @@ struct sk_buff_fclones {
* @sk: socket
* @skb: buffer
*
- * Returns true if skb is a fast clone, and its clone is not freed.
+ * Returns: true if skb is a fast clone, and its clone is not freed.
* Some drivers call skb_orphan() in their ndo_start_xmit(),
* so we also check that didn't happen.
*/
@@ -3516,7 +3524,7 @@ static inline struct page *__dev_alloc_page_noprof(gfp_t gfp_mask)
* A page shouldn't be considered for reusing/recycling if it was allocated
* under memory pressure or at a distant memory node.
*
- * Returns false if this page should be returned to page allocator, true
+ * Returns: false if this page should be returned to page allocator, true
* otherwise.
*/
static inline bool dev_page_is_reusable(const struct page *page)
@@ -3627,13 +3635,13 @@ static inline netmem_ref skb_frag_netmem(const skb_frag_t *frag)
int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
unsigned int headroom);
int skb_cow_data_for_xdp(struct page_pool *pool, struct sk_buff **pskb,
- struct bpf_prog *prog);
+ const struct bpf_prog *prog);
/**
* skb_frag_address - gets the address of the data contained in a paged fragment
* @frag: the paged fragment buffer
*
- * Returns the address of the data within @frag. The page must already
+ * Returns: the address of the data within @frag. The page must already
* be mapped.
*/
static inline void *skb_frag_address(const skb_frag_t *frag)
@@ -3648,7 +3656,7 @@ static inline void *skb_frag_address(const skb_frag_t *frag)
* skb_frag_address_safe - gets the address of the data contained in a paged fragment
* @frag: the paged fragment buffer
*
- * Returns the address of the data within @frag. Checks that the page
+ * Returns: the address of the data within @frag. Checks that the page
* is mapped and returns %NULL otherwise.
*/
static inline void *skb_frag_address_safe(const skb_frag_t *frag)
@@ -3674,7 +3682,7 @@ static inline void skb_frag_page_copy(skb_frag_t *fragto,
bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio);
/**
- * skb_frag_dma_map - maps a paged fragment via the DMA API
+ * __skb_frag_dma_map - maps a paged fragment via the DMA API
* @dev: the device to map the fragment to
* @frag: the paged fragment to map
* @offset: the offset within the fragment (starting at the
@@ -3684,15 +3692,36 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio);
*
* Maps the page associated with @frag to @device.
*/
-static inline dma_addr_t skb_frag_dma_map(struct device *dev,
- const skb_frag_t *frag,
- size_t offset, size_t size,
- enum dma_data_direction dir)
+static inline dma_addr_t __skb_frag_dma_map(struct device *dev,
+ const skb_frag_t *frag,
+ size_t offset, size_t size,
+ enum dma_data_direction dir)
{
return dma_map_page(dev, skb_frag_page(frag),
skb_frag_off(frag) + offset, size, dir);
}
+#define skb_frag_dma_map(dev, frag, ...) \
+ CONCATENATE(_skb_frag_dma_map, \
+ COUNT_ARGS(__VA_ARGS__))(dev, frag, ##__VA_ARGS__)
+
+#define __skb_frag_dma_map1(dev, frag, offset, uf, uo) ({ \
+ const skb_frag_t *uf = (frag); \
+ size_t uo = (offset); \
+ \
+ __skb_frag_dma_map(dev, uf, uo, skb_frag_size(uf) - uo, \
+ DMA_TO_DEVICE); \
+})
+#define _skb_frag_dma_map1(dev, frag, offset) \
+ __skb_frag_dma_map1(dev, frag, offset, __UNIQUE_ID(frag_), \
+ __UNIQUE_ID(offset_))
+#define _skb_frag_dma_map0(dev, frag) \
+ _skb_frag_dma_map1(dev, frag, 0)
+#define _skb_frag_dma_map2(dev, frag, offset, size) \
+ __skb_frag_dma_map(dev, frag, offset, size, DMA_TO_DEVICE)
+#define _skb_frag_dma_map3(dev, frag, offset, size, dir) \
+ __skb_frag_dma_map(dev, frag, offset, size, dir)
+
static inline struct sk_buff *pskb_copy(struct sk_buff *skb,
gfp_t gfp_mask)
{
@@ -3890,7 +3919,7 @@ static inline int skb_linearize(struct sk_buff *skb)
* skb_has_shared_frag - can any frag be overwritten
* @skb: buffer to test
*
- * Return true if the skb has at least one frag that might be modified
+ * Return: true if the skb has at least one frag that might be modified
* by an external entity (as in vmsplice()/sendfile())
*/
static inline bool skb_has_shared_frag(const struct sk_buff *skb)
@@ -4612,7 +4641,7 @@ static inline void __skb_reset_checksum_unnecessary(struct sk_buff *skb)
/* Check if we need to perform checksum complete validation.
*
- * Returns true if checksum complete is needed, false otherwise
+ * Returns: true if checksum complete is needed, false otherwise
* (either checksum is unnecessary or zero checksum is allowed).
*/
static inline bool __skb_checksum_validate_needed(struct sk_buff *skb,
diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h
index d9b03e0746e7..2cbe0c22a32f 100644
--- a/include/linux/skmsg.h
+++ b/include/linux/skmsg.h
@@ -317,17 +317,22 @@ static inline void sock_drop(struct sock *sk, struct sk_buff *skb)
kfree_skb(skb);
}
-static inline void sk_psock_queue_msg(struct sk_psock *psock,
+static inline bool sk_psock_queue_msg(struct sk_psock *psock,
struct sk_msg *msg)
{
+ bool ret;
+
spin_lock_bh(&psock->ingress_lock);
- if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED))
+ if (sk_psock_test_state(psock, SK_PSOCK_TX_ENABLED)) {
list_add_tail(&msg->list, &psock->ingress_msg);
- else {
+ ret = true;
+ } else {
sk_msg_free(psock->sk, msg);
kfree(msg);
+ ret = false;
}
spin_unlock_bh(&psock->ingress_lock);
+ return ret;
}
static inline struct sk_msg *sk_psock_dequeue_msg(struct sk_psock *psock)
diff --git a/include/linux/stackdepot.h b/include/linux/stackdepot.h
index e9ec32fb97d4..2cc21ffcdaf9 100644
--- a/include/linux/stackdepot.h
+++ b/include/linux/stackdepot.h
@@ -147,7 +147,7 @@ static inline int stack_depot_early_init(void) { return 0; }
* If the provided stack trace comes from the interrupt context, only the part
* up to the interrupt entry is saved.
*
- * Context: Any context, but setting STACK_DEPOT_FLAG_CAN_ALLOC is required if
+ * Context: Any context, but unsetting STACK_DEPOT_FLAG_CAN_ALLOC is required if
* alloc_pages() cannot be used from the current context. Currently
* this is the case for contexts where neither %GFP_ATOMIC nor
* %GFP_NOWAIT can be used (NMI, raw_spin_lock).
@@ -156,7 +156,7 @@ static inline int stack_depot_early_init(void) { return 0; }
*/
depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
unsigned int nr_entries,
- gfp_t gfp_flags,
+ gfp_t alloc_flags,
depot_flags_t depot_flags);
/**
@@ -175,7 +175,7 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
* Return: Handle of the stack trace stored in depot, 0 on failure
*/
depot_stack_handle_t stack_depot_save(unsigned long *entries,
- unsigned int nr_entries, gfp_t gfp_flags);
+ unsigned int nr_entries, gfp_t alloc_flags);
/**
* __stack_depot_get_stack_record - Get a pointer to a stack_record struct
diff --git a/include/linux/static_call.h b/include/linux/static_call.h
index 141e6b176a1b..78a77a4ae0ea 100644
--- a/include/linux/static_call.h
+++ b/include/linux/static_call.h
@@ -160,6 +160,8 @@ extern void arch_static_call_transform(void *site, void *tramp, void *func, bool
#ifdef CONFIG_HAVE_STATIC_CALL_INLINE
+extern int static_call_initialized;
+
extern int __init static_call_init(void);
extern void static_call_force_reinit(void);
@@ -225,6 +227,8 @@ extern long __static_call_return0(void);
#elif defined(CONFIG_HAVE_STATIC_CALL)
+#define static_call_initialized 0
+
static inline int static_call_init(void) { return 0; }
#define DEFINE_STATIC_CALL(name, _func) \
@@ -281,6 +285,8 @@ extern long __static_call_return0(void);
#else /* Generic implementation */
+#define static_call_initialized 0
+
static inline int static_call_init(void) { return 0; }
static inline long __static_call_return0(void)
diff --git a/include/linux/stmmac.h b/include/linux/stmmac.h
index d79ff252cfdc..c9878a612e53 100644
--- a/include/linux/stmmac.h
+++ b/include/linux/stmmac.h
@@ -33,7 +33,9 @@
#define STMMAC_CSR_20_35M 0x2 /* MDC = clk_scr_i/16 */
#define STMMAC_CSR_35_60M 0x3 /* MDC = clk_scr_i/26 */
#define STMMAC_CSR_150_250M 0x4 /* MDC = clk_scr_i/102 */
-#define STMMAC_CSR_250_300M 0x5 /* MDC = clk_scr_i/122 */
+#define STMMAC_CSR_250_300M 0x5 /* MDC = clk_scr_i/124 */
+#define STMMAC_CSR_300_500M 0x6 /* MDC = clk_scr_i/204 */
+#define STMMAC_CSR_500_800M 0x7 /* MDC = clk_scr_i/324 */
/* MTL algorithms identifiers */
#define MTL_TX_ALGORITHM_WRR 0x0
@@ -250,8 +252,8 @@ struct plat_stmmacenet_data {
struct clk *stmmac_clk;
struct clk *pclk;
struct clk *clk_ptp_ref;
- unsigned int clk_ptp_rate;
- unsigned int clk_ref_rate;
+ unsigned long clk_ptp_rate;
+ unsigned long clk_ref_rate;
unsigned int mult_fact_100ns;
s32 ptp_max_adj;
u32 cdc_error_adj;
@@ -263,7 +265,7 @@ struct plat_stmmacenet_data {
int mac_port_sel_speed;
int has_xgmac;
u8 vlan_fail_q;
- unsigned int eee_usecs_rate;
+ unsigned long eee_usecs_rate;
struct pci_dev *pdev;
int int_snapshot_num;
int msi_mac_vec;
diff --git a/include/linux/string.h b/include/linux/string.h
index 0dd27afcfaf7..493ac4862c77 100644
--- a/include/linux/string.h
+++ b/include/linux/string.h
@@ -335,7 +335,6 @@ int __sysfs_match_string(const char * const *array, size_t n, const char *s);
#ifdef CONFIG_BINARY_PRINTF
int vbin_printf(u32 *bin_buf, size_t size, const char *fmt, va_list args);
int bstr_printf(char *buf, size_t size, const char *fmt, const u32 *bin_buf);
-int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...) __printf(3, 4);
#endif
extern ssize_t memory_read_from_buffer(void *to, size_t count, loff_t *ppos,
diff --git a/include/linux/sysfs.h b/include/linux/sysfs.h
index c4e64dc11206..0f2fcd244523 100644
--- a/include/linux/sysfs.h
+++ b/include/linux/sysfs.h
@@ -87,6 +87,11 @@ do { \
* SYSFS_GROUP_VISIBLE() when assigning this callback to
* specify separate _group_visible() and _attr_visible()
* handlers.
+ * @bin_size:
+ * Optional: Function to return the size of a binary attribute
+ * of the group. Will be called repeatedly for each binary
+ * attribute in the group. Overwrites the size field embedded
+ * inside the attribute itself.
* @attrs: Pointer to NULL terminated list of attributes.
* @bin_attrs: Pointer to NULL terminated list of binary attributes.
* Either attrs or bin_attrs or both must be provided.
@@ -96,9 +101,15 @@ struct attribute_group {
umode_t (*is_visible)(struct kobject *,
struct attribute *, int);
umode_t (*is_bin_visible)(struct kobject *,
- struct bin_attribute *, int);
+ const struct bin_attribute *, int);
+ size_t (*bin_size)(struct kobject *,
+ const struct bin_attribute *,
+ int);
struct attribute **attrs;
- struct bin_attribute **bin_attrs;
+ union {
+ struct bin_attribute **bin_attrs;
+ const struct bin_attribute *const *bin_attrs_new;
+ };
};
#define SYSFS_PREALLOC 010000
@@ -191,22 +202,22 @@ struct attribute_group {
* attributes, the group visibility is determined by the function
* specified to is_visible() not is_bin_visible()
*/
-#define DEFINE_SYSFS_BIN_GROUP_VISIBLE(name) \
- static inline umode_t sysfs_group_visible_##name( \
- struct kobject *kobj, struct bin_attribute *attr, int n) \
- { \
- if (n == 0 && !name##_group_visible(kobj)) \
- return SYSFS_GROUP_INVISIBLE; \
- return name##_attr_visible(kobj, attr, n); \
+#define DEFINE_SYSFS_BIN_GROUP_VISIBLE(name) \
+ static inline umode_t sysfs_group_visible_##name( \
+ struct kobject *kobj, const struct bin_attribute *attr, int n) \
+ { \
+ if (n == 0 && !name##_group_visible(kobj)) \
+ return SYSFS_GROUP_INVISIBLE; \
+ return name##_attr_visible(kobj, attr, n); \
}
-#define DEFINE_SIMPLE_SYSFS_BIN_GROUP_VISIBLE(name) \
- static inline umode_t sysfs_group_visible_##name( \
- struct kobject *kobj, struct bin_attribute *a, int n) \
- { \
- if (n == 0 && !name##_group_visible(kobj)) \
- return SYSFS_GROUP_INVISIBLE; \
- return a->mode; \
+#define DEFINE_SIMPLE_SYSFS_BIN_GROUP_VISIBLE(name) \
+ static inline umode_t sysfs_group_visible_##name( \
+ struct kobject *kobj, const struct bin_attribute *a, int n) \
+ { \
+ if (n == 0 && !name##_group_visible(kobj)) \
+ return SYSFS_GROUP_INVISIBLE; \
+ return a->mode; \
}
#define SYSFS_GROUP_VISIBLE(fn) sysfs_group_visible_##fn
@@ -297,11 +308,15 @@ struct bin_attribute {
struct address_space *(*f_mapping)(void);
ssize_t (*read)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
+ ssize_t (*read_new)(struct file *, struct kobject *, const struct bin_attribute *,
+ char *, loff_t, size_t);
ssize_t (*write)(struct file *, struct kobject *, struct bin_attribute *,
char *, loff_t, size_t);
- loff_t (*llseek)(struct file *, struct kobject *, struct bin_attribute *,
+ ssize_t (*write_new)(struct file *, struct kobject *,
+ const struct bin_attribute *, char *, loff_t, size_t);
+ loff_t (*llseek)(struct file *, struct kobject *, const struct bin_attribute *,
loff_t, int);
- int (*mmap)(struct file *, struct kobject *, struct bin_attribute *attr,
+ int (*mmap)(struct file *, struct kobject *, const struct bin_attribute *attr,
struct vm_area_struct *vma);
};
@@ -317,25 +332,36 @@ struct bin_attribute {
*/
#define sysfs_bin_attr_init(bin_attr) sysfs_attr_init(&(bin_attr)->attr)
+typedef ssize_t __sysfs_bin_rw_handler_new(struct file *, struct kobject *,
+ const struct bin_attribute *, char *, loff_t, size_t);
+
/* macros to create static binary attributes easier */
#define __BIN_ATTR(_name, _mode, _read, _write, _size) { \
.attr = { .name = __stringify(_name), .mode = _mode }, \
- .read = _read, \
- .write = _write, \
+ .read = _Generic(_read, \
+ __sysfs_bin_rw_handler_new * : NULL, \
+ default : _read \
+ ), \
+ .read_new = _Generic(_read, \
+ __sysfs_bin_rw_handler_new * : _read, \
+ default : NULL \
+ ), \
+ .write = _Generic(_write, \
+ __sysfs_bin_rw_handler_new * : NULL, \
+ default : _write \
+ ), \
+ .write_new = _Generic(_write, \
+ __sysfs_bin_rw_handler_new * : _write, \
+ default : NULL \
+ ), \
.size = _size, \
}
-#define __BIN_ATTR_RO(_name, _size) { \
- .attr = { .name = __stringify(_name), .mode = 0444 }, \
- .read = _name##_read, \
- .size = _size, \
-}
+#define __BIN_ATTR_RO(_name, _size) \
+ __BIN_ATTR(_name, 0444, _name##_read, NULL, _size)
-#define __BIN_ATTR_WO(_name, _size) { \
- .attr = { .name = __stringify(_name), .mode = 0200 }, \
- .write = _name##_write, \
- .size = _size, \
-}
+#define __BIN_ATTR_WO(_name, _size) \
+ __BIN_ATTR(_name, 0200, NULL, _name##_write, _size)
#define __BIN_ATTR_RW(_name, _size) \
__BIN_ATTR(_name, 0644, _name##_read, _name##_write, _size)
@@ -356,11 +382,8 @@ struct bin_attribute bin_attr_##_name = __BIN_ATTR_WO(_name, _size)
struct bin_attribute bin_attr_##_name = __BIN_ATTR_RW(_name, _size)
-#define __BIN_ATTR_ADMIN_RO(_name, _size) { \
- .attr = { .name = __stringify(_name), .mode = 0400 }, \
- .read = _name##_read, \
- .size = _size, \
-}
+#define __BIN_ATTR_ADMIN_RO(_name, _size) \
+ __BIN_ATTR(_name, 0400, _name##_read, NULL, _size)
#define __BIN_ATTR_ADMIN_RW(_name, _size) \
__BIN_ATTR(_name, 0600, _name##_read, _name##_write, _size)
@@ -371,10 +394,8 @@ struct bin_attribute bin_attr_##_name = __BIN_ATTR_ADMIN_RO(_name, _size)
#define BIN_ATTR_ADMIN_RW(_name, _size) \
struct bin_attribute bin_attr_##_name = __BIN_ATTR_ADMIN_RW(_name, _size)
-#define __BIN_ATTR_SIMPLE_RO(_name, _mode) { \
- .attr = { .name = __stringify(_name), .mode = _mode }, \
- .read = sysfs_bin_attr_simple_read, \
-}
+#define __BIN_ATTR_SIMPLE_RO(_name, _mode) \
+ __BIN_ATTR(_name, _mode, sysfs_bin_attr_simple_read, NULL, 0)
#define BIN_ATTR_SIMPLE_RO(_name) \
struct bin_attribute bin_attr_##_name = __BIN_ATTR_SIMPLE_RO(_name, 0444)
diff --git a/include/linux/trace_events.h b/include/linux/trace_events.h
index 016b29a56c87..58ad4ead33fc 100644
--- a/include/linux/trace_events.h
+++ b/include/linux/trace_events.h
@@ -184,6 +184,7 @@ unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status);
enum trace_flag_type {
TRACE_FLAG_IRQS_OFF = 0x01,
+ TRACE_FLAG_NEED_RESCHED_LAZY = 0x02,
TRACE_FLAG_NEED_RESCHED = 0x04,
TRACE_FLAG_HARDIRQ = 0x08,
TRACE_FLAG_SOFTIRQ = 0x10,
@@ -272,7 +273,8 @@ struct trace_event_fields {
const char *name;
const int size;
const int align;
- const int is_signed;
+ const unsigned int is_signed:1;
+ unsigned int needs_test:1;
const int filter_type;
const int len;
};
@@ -323,6 +325,7 @@ enum {
TRACE_EVENT_FL_EPROBE_BIT,
TRACE_EVENT_FL_FPROBE_BIT,
TRACE_EVENT_FL_CUSTOM_BIT,
+ TRACE_EVENT_FL_TEST_STR_BIT,
};
/*
@@ -339,6 +342,7 @@ enum {
* CUSTOM - Event is a custom event (to be attached to an exsiting tracepoint)
* This is set when the custom event has not been attached
* to a tracepoint yet, then it is cleared when it is.
+ * TEST_STR - The event has a "%s" that points to a string outside the event
*/
enum {
TRACE_EVENT_FL_CAP_ANY = (1 << TRACE_EVENT_FL_CAP_ANY_BIT),
@@ -351,6 +355,7 @@ enum {
TRACE_EVENT_FL_EPROBE = (1 << TRACE_EVENT_FL_EPROBE_BIT),
TRACE_EVENT_FL_FPROBE = (1 << TRACE_EVENT_FL_FPROBE_BIT),
TRACE_EVENT_FL_CUSTOM = (1 << TRACE_EVENT_FL_CUSTOM_BIT),
+ TRACE_EVENT_FL_TEST_STR = (1 << TRACE_EVENT_FL_TEST_STR_BIT),
};
#define TRACE_EVENT_FL_UKPROBE (TRACE_EVENT_FL_KPROBE | TRACE_EVENT_FL_UPROBE)
@@ -359,7 +364,7 @@ struct trace_event_call {
struct list_head list;
struct trace_event_class *class;
union {
- char *name;
+ const char *name;
/* Set TRACE_EVENT_FL_TRACEPOINT flag when using "tp" */
struct tracepoint *tp;
};
diff --git a/include/linux/tracepoint.h b/include/linux/tracepoint.h
index 6073a8c7e38c..76d9055b2cff 100644
--- a/include/linux/tracepoint.h
+++ b/include/linux/tracepoint.h
@@ -210,36 +210,6 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
#endif /* CONFIG_HAVE_STATIC_CALL */
/*
- * it_func[0] is never NULL because there is at least one element in the array
- * when the array itself is non NULL.
- *
- * With @syscall=0, the tracepoint callback array dereference is
- * protected by disabling preemption.
- * With @syscall=1, the tracepoint callback array dereference is
- * protected by Tasks Trace RCU, which allows probes to handle page
- * faults.
- */
-#define __DO_TRACE(name, args, cond, syscall) \
- do { \
- int __maybe_unused __idx = 0; \
- \
- if (!(cond)) \
- return; \
- \
- if (syscall) \
- rcu_read_lock_trace(); \
- else \
- preempt_disable_notrace(); \
- \
- __DO_TRACE_CALL(name, TP_ARGS(args)); \
- \
- if (syscall) \
- rcu_read_unlock_trace(); \
- else \
- preempt_enable_notrace(); \
- } while (0)
-
-/*
* Declare an exported function that Rust code can call to trigger this
* tracepoint. This function does not include the static branch; that is done
* in Rust to avoid a function call when the tracepoint is disabled.
@@ -262,7 +232,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
* site if it is not watching, as it will need to be active when the
* tracepoint is enabled.
*/
-#define __DECLARE_TRACE_COMMON(name, proto, args, cond, data_proto) \
+#define __DECLARE_TRACE_COMMON(name, proto, args, data_proto) \
extern int __traceiter_##name(data_proto); \
DECLARE_STATIC_CALL(tp_func_##name, __traceiter_##name); \
extern struct tracepoint __tracepoint_##name; \
@@ -297,41 +267,43 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
}
#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
- __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \
+ __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto)) \
static inline void __rust_do_trace_##name(proto) \
{ \
- __DO_TRACE(name, \
- TP_ARGS(args), \
- TP_CONDITION(cond), 0); \
+ if (cond) { \
+ guard(preempt_notrace)(); \
+ __DO_TRACE_CALL(name, TP_ARGS(args)); \
+ } \
} \
static inline void trace_##name(proto) \
{ \
- if (static_branch_unlikely(&__tracepoint_##name.key)) \
- __DO_TRACE(name, \
- TP_ARGS(args), \
- TP_CONDITION(cond), 0); \
+ if (static_branch_unlikely(&__tracepoint_##name.key)) { \
+ if (cond) { \
+ guard(preempt_notrace)(); \
+ __DO_TRACE_CALL(name, TP_ARGS(args)); \
+ } \
+ } \
if (IS_ENABLED(CONFIG_LOCKDEP) && (cond)) { \
WARN_ONCE(!rcu_is_watching(), \
"RCU not watching for tracepoint"); \
} \
}
-#define __DECLARE_TRACE_SYSCALL(name, proto, args, cond, data_proto) \
- __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), cond, PARAMS(data_proto)) \
+#define __DECLARE_TRACE_SYSCALL(name, proto, args, data_proto) \
+ __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto)) \
static inline void __rust_do_trace_##name(proto) \
{ \
- __DO_TRACE(name, \
- TP_ARGS(args), \
- TP_CONDITION(cond), 1); \
+ guard(rcu_tasks_trace)(); \
+ __DO_TRACE_CALL(name, TP_ARGS(args)); \
} \
static inline void trace_##name(proto) \
{ \
might_fault(); \
- if (static_branch_unlikely(&__tracepoint_##name.key)) \
- __DO_TRACE(name, \
- TP_ARGS(args), \
- TP_CONDITION(cond), 1); \
- if (IS_ENABLED(CONFIG_LOCKDEP) && (cond)) { \
+ if (static_branch_unlikely(&__tracepoint_##name.key)) { \
+ guard(rcu_tasks_trace)(); \
+ __DO_TRACE_CALL(name, TP_ARGS(args)); \
+ } \
+ if (IS_ENABLED(CONFIG_LOCKDEP)) { \
WARN_ONCE(!rcu_is_watching(), \
"RCU not watching for tracepoint"); \
} \
@@ -341,6 +313,9 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
* We have no guarantee that gcc and the linker won't up-align the tracepoint
* structures, so we create an array of pointers that will be used for iteration
* on the tracepoints.
+ *
+ * it_func[0] is never NULL because there is at least one element in the array
+ * when the array itself is non NULL.
*/
#define __DEFINE_TRACE_EXT(_name, _ext, proto, args) \
static const char __tpstrtab_##_name[] \
@@ -412,7 +387,7 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
#else /* !TRACEPOINTS_ENABLED */
-#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
+#define __DECLARE_TRACE_COMMON(name, proto, args, data_proto) \
static inline void trace_##name(proto) \
{ } \
static inline int \
@@ -436,7 +411,11 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
return false; \
}
-#define __DECLARE_TRACE_SYSCALL __DECLARE_TRACE
+#define __DECLARE_TRACE(name, proto, args, cond, data_proto) \
+ __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto))
+
+#define __DECLARE_TRACE_SYSCALL(name, proto, args, data_proto) \
+ __DECLARE_TRACE_COMMON(name, PARAMS(proto), PARAMS(args), PARAMS(data_proto))
#define DEFINE_TRACE_FN(name, reg, unreg, proto, args)
#define DEFINE_TRACE_SYSCALL(name, reg, unreg, proto, args)
@@ -502,7 +481,6 @@ static inline struct tracepoint *tracepoint_ptr_deref(tracepoint_ptr_t *p)
#define DECLARE_TRACE_SYSCALL(name, proto, args) \
__DECLARE_TRACE_SYSCALL(name, PARAMS(proto), PARAMS(args), \
- cpu_online(raw_smp_processor_id()), \
PARAMS(void *__data, proto))
#define TRACE_EVENT_FLAGS(event, flag)
diff --git a/include/linux/types.h b/include/linux/types.h
index 2bc8766ba20c..2d7b9ae8714c 100644
--- a/include/linux/types.h
+++ b/include/linux/types.h
@@ -115,8 +115,9 @@ typedef u64 u_int64_t;
typedef s64 int64_t;
#endif
-/* this is a special 64bit data type that is 8-byte aligned */
+/* These are the special 64-bit data types that are 8-byte aligned */
#define aligned_u64 __aligned_u64
+#define aligned_s64 __aligned_s64
#define aligned_be64 __aligned_be64
#define aligned_le64 __aligned_le64
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 672d8fc2abdb..cfa8005e24f9 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1129,8 +1129,8 @@ static inline int usb_make_path(struct usb_device *dev, char *buf, size_t size)
/* ----------------------------------------------------------------------- */
/* Stuff for dynamic usb ids */
+extern struct mutex usb_dynids_lock;
struct usb_dynids {
- spinlock_t lock;
struct list_head list;
};
@@ -1243,7 +1243,7 @@ struct usb_driver {
unsigned int disable_hub_initiated_lpm:1;
unsigned int soft_unbind:1;
};
-#define to_usb_driver(d) container_of(d, struct usb_driver, driver)
+#define to_usb_driver(d) container_of_const(d, struct usb_driver, driver)
/**
* struct usb_device_driver - identifies USB device driver to usbcore
@@ -1294,8 +1294,7 @@ struct usb_device_driver {
unsigned int supports_autosuspend:1;
unsigned int generic_subclass:1;
};
-#define to_usb_device_driver(d) container_of(d, struct usb_device_driver, \
- driver)
+#define to_usb_device_driver(d) container_of_const(d, struct usb_device_driver, driver)
/**
* struct usb_class_driver - identifies a USB driver that wants to use the USB major number
diff --git a/include/linux/usb/chipidea.h b/include/linux/usb/chipidea.h
index 5a7f96684ea2..ebdfef124b2b 100644
--- a/include/linux/usb/chipidea.h
+++ b/include/linux/usb/chipidea.h
@@ -65,6 +65,7 @@ struct ci_hdrc_platform_data {
#define CI_HDRC_PHY_VBUS_CONTROL BIT(16)
#define CI_HDRC_HAS_PORTSC_PEC_MISSED BIT(17)
#define CI_HDRC_FORCE_VBUS_ACTIVE_ALWAYS BIT(18)
+#define CI_HDRC_HAS_SHORT_PKT_LIMIT BIT(19)
enum usb_dr_mode dr_mode;
#define CI_HDRC_CONTROLLER_RESET_EVENT 0
#define CI_HDRC_CONTROLLER_STOPPED_EVENT 1
diff --git a/include/linux/usb/storage.h b/include/linux/usb/storage.h
index 2827ce72e502..8539956bc2be 100644
--- a/include/linux/usb/storage.h
+++ b/include/linux/usb/storage.h
@@ -53,7 +53,7 @@ struct bulk_cb_wrap {
__le32 Signature; /* contains 'USBC' */
__u32 Tag; /* unique per command id */
__le32 DataTransferLength; /* size of data */
- __u8 Flags; /* direction in bit 0 */
+ __u8 Flags; /* direction in bit 7 */
__u8 Lun; /* LUN normally 0 */
__u8 Length; /* length of the CDB */
__u8 CDB[16]; /* max command */
diff --git a/include/linux/usb/typec.h b/include/linux/usb/typec.h
index 549275f8ac1b..d616b8807000 100644
--- a/include/linux/usb/typec.h
+++ b/include/linux/usb/typec.h
@@ -87,6 +87,17 @@ enum typec_orientation {
TYPEC_ORIENTATION_REVERSE,
};
+enum usb_mode {
+ USB_MODE_NONE,
+ USB_MODE_USB2,
+ USB_MODE_USB3,
+ USB_MODE_USB4
+};
+
+#define USB_CAPABILITY_USB2 BIT(0)
+#define USB_CAPABILITY_USB3 BIT(1)
+#define USB_CAPABILITY_USB4 BIT(2)
+
/*
* struct enter_usb_data - Enter_USB Message details
* @eudo: Enter_USB Data Object
@@ -209,6 +220,7 @@ struct typec_cable_desc {
* @accessory: Audio, Debug or none.
* @identity: Discover Identity command data
* @pd_revision: USB Power Delivery Specification Revision if supported
+ * @usb_capability: Supported USB Modes
* @attach: Notification about attached USB device
* @deattach: Notification about removed USB device
*
@@ -226,6 +238,7 @@ struct typec_partner_desc {
enum typec_accessory accessory;
struct usb_pd_identity *identity;
u16 pd_revision; /* 0300H = "3.0" */
+ u8 usb_capability;
void (*attach)(struct typec_partner *partner, struct device *dev);
void (*deattach)(struct typec_partner *partner, struct device *dev);
@@ -240,6 +253,8 @@ struct typec_partner_desc {
* @port_type_set: Set port type
* @pd_get: Get available USB Power Delivery Capabilities.
* @pd_set: Set USB Power Delivery Capabilities.
+ * @default_usb_mode_set: USB Mode to be used by default with Enter_USB Message
+ * @enter_usb_mode: Change the active USB Mode
*/
struct typec_operations {
int (*try_role)(struct typec_port *port, int role);
@@ -250,6 +265,8 @@ struct typec_operations {
enum typec_port_type type);
struct usb_power_delivery **(*pd_get)(struct typec_port *port);
int (*pd_set)(struct typec_port *port, struct usb_power_delivery *pd);
+ int (*default_usb_mode_set)(struct typec_port *port, enum usb_mode mode);
+ int (*enter_usb_mode)(struct typec_port *port, enum usb_mode mode);
};
enum usb_pd_svdm_ver {
@@ -267,6 +284,7 @@ enum usb_pd_svdm_ver {
* @svdm_version: USB PD Structured VDM version if supported
* @prefer_role: Initial role preference (DRP ports).
* @accessory: Supported Accessory Modes
+ * @usb_capability: Supported USB Modes
* @fwnode: Optional fwnode of the port
* @driver_data: Private pointer for driver specific info
* @pd: Optional USB Power Delivery Support
@@ -283,6 +301,7 @@ struct typec_capability {
int prefer_role;
enum typec_accessory accessory[TYPEC_MAX_ACCESSORY];
unsigned int orientation_aware:1;
+ u8 usb_capability;
struct fwnode_handle *fwnode;
void *driver_data;
@@ -350,6 +369,9 @@ int typec_port_set_usb_power_delivery(struct typec_port *port, struct usb_power_
int typec_partner_set_usb_power_delivery(struct typec_partner *partner,
struct usb_power_delivery *pd);
+void typec_partner_set_usb_mode(struct typec_partner *partner, enum usb_mode usb_mode);
+void typec_port_set_usb_mode(struct typec_port *port, enum usb_mode mode);
+
/**
* struct typec_connector - Representation of Type-C port for external drivers
* @attach: notification about device removal
diff --git a/include/linux/vermagic.h b/include/linux/vermagic.h
index a54046bf37e5..939ceabcaf06 100644
--- a/include/linux/vermagic.h
+++ b/include/linux/vermagic.h
@@ -15,10 +15,10 @@
#else
#define MODULE_VERMAGIC_SMP ""
#endif
-#ifdef CONFIG_PREEMPT_BUILD
-#define MODULE_VERMAGIC_PREEMPT "preempt "
-#elif defined(CONFIG_PREEMPT_RT)
+#ifdef CONFIG_PREEMPT_RT
#define MODULE_VERMAGIC_PREEMPT "preempt_rt "
+#elif defined(CONFIG_PREEMPT_BUILD)
+#define MODULE_VERMAGIC_PREEMPT "preempt "
#else
#define MODULE_VERMAGIC_PREEMPT ""
#endif
diff --git a/include/linux/virtio.h b/include/linux/virtio.h
index 57cc4b07fd17..dd88682e27e3 100644
--- a/include/linux/virtio.h
+++ b/include/linux/virtio.h
@@ -109,9 +109,11 @@ dma_addr_t virtqueue_get_avail_addr(const struct virtqueue *vq);
dma_addr_t virtqueue_get_used_addr(const struct virtqueue *vq);
int virtqueue_resize(struct virtqueue *vq, u32 num,
- void (*recycle)(struct virtqueue *vq, void *buf));
+ void (*recycle)(struct virtqueue *vq, void *buf),
+ void (*recycle_done)(struct virtqueue *vq));
int virtqueue_reset(struct virtqueue *vq,
- void (*recycle)(struct virtqueue *vq, void *buf));
+ void (*recycle)(struct virtqueue *vq, void *buf),
+ void (*recycle_done)(struct virtqueue *vq));
struct virtio_admin_cmd {
__le16 opcode;
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
index d2761bf8ff32..9f3a04345b86 100644
--- a/include/linux/vmstat.h
+++ b/include/linux/vmstat.h
@@ -515,7 +515,7 @@ static inline const char *node_stat_name(enum node_stat_item item)
static inline const char *lru_list_name(enum lru_list lru)
{
- return node_stat_name(NR_LRU_BASE + lru) + 3; // skip "nr_"
+ return node_stat_name(NR_LRU_BASE + (enum node_stat_item)lru) + 3; // skip "nr_"
}
#if defined(CONFIG_VM_EVENT_COUNTERS) || defined(CONFIG_MEMCG)
diff --git a/include/linux/ww_mutex.h b/include/linux/ww_mutex.h
index a401a2f31a77..45ff6f7a872b 100644
--- a/include/linux/ww_mutex.h
+++ b/include/linux/ww_mutex.h
@@ -156,8 +156,8 @@ static inline void ww_acquire_init(struct ww_acquire_ctx *ctx,
debug_check_no_locks_freed((void *)ctx, sizeof(*ctx));
lockdep_init_map(&ctx->dep_map, ww_class->acquire_name,
&ww_class->acquire_key, 0);
- lockdep_init_map(&ctx->first_lock_dep_map, ww_class->mutex_name,
- &ww_class->mutex_key, 0);
+ lockdep_init_map_wait(&ctx->first_lock_dep_map, ww_class->mutex_name,
+ &ww_class->mutex_key, 0, LD_WAIT_SLEEP);
mutex_acquire(&ctx->dep_map, 0, 0, _RET_IP_);
mutex_acquire_nest(&ctx->first_lock_dep_map, 0, 0, &ctx->dep_map, _RET_IP_);
#endif
diff --git a/include/linux/wwan.h b/include/linux/wwan.h
index 79c781875c09..a4d6cc0c9f68 100644
--- a/include/linux/wwan.h
+++ b/include/linux/wwan.h
@@ -97,7 +97,7 @@ struct wwan_port_caps {
*
* This function must be balanced with a call to wwan_remove_port().
*
- * Returns a valid pointer to wwan_port on success or PTR_ERR on failure
+ * Returns: a valid pointer to wwan_port on success or PTR_ERR on failure
*/
struct wwan_port *wwan_create_port(struct device *parent,
enum wwan_port_type type,
diff --git a/include/net/addrconf.h b/include/net/addrconf.h
index 363dd63babe7..f8f91b2038ea 100644
--- a/include/net/addrconf.h
+++ b/include/net/addrconf.h
@@ -88,6 +88,23 @@ struct ifa6_config {
u16 scope;
};
+enum addr_type_t {
+ UNICAST_ADDR,
+ MULTICAST_ADDR,
+ ANYCAST_ADDR,
+};
+
+struct inet6_fill_args {
+ u32 portid;
+ u32 seq;
+ int event;
+ unsigned int flags;
+ int netnsid;
+ int ifindex;
+ enum addr_type_t type;
+ bool force_rt_scope_universe;
+};
+
int addrconf_init(void);
void addrconf_cleanup(void);
@@ -525,4 +542,11 @@ int if6_proc_init(void);
void if6_proc_exit(void);
#endif
+int inet6_fill_ifmcaddr(struct sk_buff *skb,
+ const struct ifmcaddr6 *ifmca,
+ struct inet6_fill_args *args);
+
+int inet6_fill_ifacaddr(struct sk_buff *skb,
+ const struct ifacaddr6 *ifaca,
+ struct inet6_fill_args *args);
#endif
diff --git a/include/net/ax25.h b/include/net/ax25.h
index cb622d84cd0c..4ee141aae0a2 100644
--- a/include/net/ax25.h
+++ b/include/net/ax25.h
@@ -231,6 +231,7 @@ typedef struct ax25_dev {
#endif
refcount_t refcount;
bool device_up;
+ struct rcu_head rcu;
} ax25_dev;
typedef struct ax25_cb {
@@ -290,9 +291,8 @@ static inline void ax25_dev_hold(ax25_dev *ax25_dev)
static inline void ax25_dev_put(ax25_dev *ax25_dev)
{
- if (refcount_dec_and_test(&ax25_dev->refcount)) {
- kfree(ax25_dev);
- }
+ if (refcount_dec_and_test(&ax25_dev->refcount))
+ kfree_rcu(ax25_dev, rcu);
}
static inline __be16 ax25_type_trans(struct sk_buff *skb, struct net_device *dev)
{
@@ -335,9 +335,9 @@ void ax25_digi_invert(const ax25_digi *, ax25_digi *);
extern spinlock_t ax25_dev_lock;
#if IS_ENABLED(CONFIG_AX25)
-static inline ax25_dev *ax25_dev_ax25dev(struct net_device *dev)
+static inline ax25_dev *ax25_dev_ax25dev(const struct net_device *dev)
{
- return dev->ax25_ptr;
+ return rcu_dereference_rtnl(dev->ax25_ptr);
}
#endif
diff --git a/include/net/bluetooth/bluetooth.h b/include/net/bluetooth/bluetooth.h
index f66bc85c6411..435250c72d56 100644
--- a/include/net/bluetooth/bluetooth.h
+++ b/include/net/bluetooth/bluetooth.h
@@ -123,6 +123,7 @@ struct bt_voice {
#define BT_VOICE_TRANSPARENT 0x0003
#define BT_VOICE_CVSD_16BIT 0x0060
+#define BT_VOICE_TRANSPARENT_16BIT 0x0063
#define BT_SNDMTU 12
#define BT_RCVMTU 13
@@ -590,15 +591,6 @@ static inline struct sk_buff *bt_skb_sendmmsg(struct sock *sk,
return skb;
}
-static inline int bt_copy_from_sockptr(void *dst, size_t dst_size,
- sockptr_t src, size_t src_size)
-{
- if (dst_size > src_size)
- return -EINVAL;
-
- return copy_from_sockptr(dst, src, dst_size);
-}
-
int bt_to_errno(u16 code);
__u8 bt_status(int err);
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index ea798f07c5a2..ca22ead85dbe 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -804,7 +804,6 @@ struct hci_conn_params {
extern struct list_head hci_dev_list;
extern struct list_head hci_cb_list;
extern rwlock_t hci_dev_list_lock;
-extern struct mutex hci_cb_list_lock;
#define hci_dev_set_flag(hdev, nr) set_bit((nr), (hdev)->dev_flags)
#define hci_dev_clear_flag(hdev, nr) clear_bit((nr), (hdev)->dev_flags)
@@ -2017,24 +2016,47 @@ struct hci_cb {
char *name;
+ bool (*match) (struct hci_conn *conn);
void (*connect_cfm) (struct hci_conn *conn, __u8 status);
void (*disconn_cfm) (struct hci_conn *conn, __u8 status);
void (*security_cfm) (struct hci_conn *conn, __u8 status,
- __u8 encrypt);
+ __u8 encrypt);
void (*key_change_cfm) (struct hci_conn *conn, __u8 status);
void (*role_switch_cfm) (struct hci_conn *conn, __u8 status, __u8 role);
};
+static inline void hci_cb_lookup(struct hci_conn *conn, struct list_head *list)
+{
+ struct hci_cb *cb, *cpy;
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(cb, &hci_cb_list, list) {
+ if (cb->match && cb->match(conn)) {
+ cpy = kmalloc(sizeof(*cpy), GFP_ATOMIC);
+ if (!cpy)
+ break;
+
+ *cpy = *cb;
+ INIT_LIST_HEAD(&cpy->list);
+ list_add_rcu(&cpy->list, list);
+ }
+ }
+ rcu_read_unlock();
+}
+
static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
{
- struct hci_cb *cb;
+ struct list_head list;
+ struct hci_cb *cb, *tmp;
+
+ INIT_LIST_HEAD(&list);
+ hci_cb_lookup(conn, &list);
- mutex_lock(&hci_cb_list_lock);
- list_for_each_entry(cb, &hci_cb_list, list) {
+ list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->connect_cfm)
cb->connect_cfm(conn, status);
+ kfree(cb);
}
- mutex_unlock(&hci_cb_list_lock);
if (conn->connect_cfm_cb)
conn->connect_cfm_cb(conn, status);
@@ -2042,43 +2064,55 @@ static inline void hci_connect_cfm(struct hci_conn *conn, __u8 status)
static inline void hci_disconn_cfm(struct hci_conn *conn, __u8 reason)
{
- struct hci_cb *cb;
+ struct list_head list;
+ struct hci_cb *cb, *tmp;
+
+ INIT_LIST_HEAD(&list);
+ hci_cb_lookup(conn, &list);
- mutex_lock(&hci_cb_list_lock);
- list_for_each_entry(cb, &hci_cb_list, list) {
+ list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->disconn_cfm)
cb->disconn_cfm(conn, reason);
+ kfree(cb);
}
- mutex_unlock(&hci_cb_list_lock);
if (conn->disconn_cfm_cb)
conn->disconn_cfm_cb(conn, reason);
}
-static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
+static inline void hci_security_cfm(struct hci_conn *conn, __u8 status,
+ __u8 encrypt)
{
- struct hci_cb *cb;
- __u8 encrypt;
-
- if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
- return;
+ struct list_head list;
+ struct hci_cb *cb, *tmp;
- encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00;
+ INIT_LIST_HEAD(&list);
+ hci_cb_lookup(conn, &list);
- mutex_lock(&hci_cb_list_lock);
- list_for_each_entry(cb, &hci_cb_list, list) {
+ list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->security_cfm)
cb->security_cfm(conn, status, encrypt);
+ kfree(cb);
}
- mutex_unlock(&hci_cb_list_lock);
if (conn->security_cfm_cb)
conn->security_cfm_cb(conn, status);
}
+static inline void hci_auth_cfm(struct hci_conn *conn, __u8 status)
+{
+ __u8 encrypt;
+
+ if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags))
+ return;
+
+ encrypt = test_bit(HCI_CONN_ENCRYPT, &conn->flags) ? 0x01 : 0x00;
+
+ hci_security_cfm(conn, status, encrypt);
+}
+
static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
{
- struct hci_cb *cb;
__u8 encrypt;
if (conn->state == BT_CONFIG) {
@@ -2105,40 +2139,38 @@ static inline void hci_encrypt_cfm(struct hci_conn *conn, __u8 status)
conn->sec_level = conn->pending_sec_level;
}
- mutex_lock(&hci_cb_list_lock);
- list_for_each_entry(cb, &hci_cb_list, list) {
- if (cb->security_cfm)
- cb->security_cfm(conn, status, encrypt);
- }
- mutex_unlock(&hci_cb_list_lock);
-
- if (conn->security_cfm_cb)
- conn->security_cfm_cb(conn, status);
+ hci_security_cfm(conn, status, encrypt);
}
static inline void hci_key_change_cfm(struct hci_conn *conn, __u8 status)
{
- struct hci_cb *cb;
+ struct list_head list;
+ struct hci_cb *cb, *tmp;
+
+ INIT_LIST_HEAD(&list);
+ hci_cb_lookup(conn, &list);
- mutex_lock(&hci_cb_list_lock);
- list_for_each_entry(cb, &hci_cb_list, list) {
+ list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->key_change_cfm)
cb->key_change_cfm(conn, status);
+ kfree(cb);
}
- mutex_unlock(&hci_cb_list_lock);
}
static inline void hci_role_switch_cfm(struct hci_conn *conn, __u8 status,
__u8 role)
{
- struct hci_cb *cb;
+ struct list_head list;
+ struct hci_cb *cb, *tmp;
+
+ INIT_LIST_HEAD(&list);
+ hci_cb_lookup(conn, &list);
- mutex_lock(&hci_cb_list_lock);
- list_for_each_entry(cb, &hci_cb_list, list) {
+ list_for_each_entry_safe(cb, tmp, &list, list) {
if (cb->role_switch_cfm)
cb->role_switch_cfm(conn, status, role);
+ kfree(cb);
}
- mutex_unlock(&hci_cb_list_lock);
}
static inline bool hci_bdaddr_is_rpa(bdaddr_t *bdaddr, u8 addr_type)
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 27acf1292a5c..7790af534b7f 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -4733,7 +4733,7 @@ struct cfg80211_ops {
int (*set_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
enum nl80211_tx_power_setting type, int mbm);
int (*get_tx_power)(struct wiphy *wiphy, struct wireless_dev *wdev,
- int *dbm);
+ unsigned int link_id, int *dbm);
void (*rfkill_poll)(struct wiphy *wiphy);
@@ -5957,7 +5957,7 @@ int wiphy_register(struct wiphy *wiphy);
* @wiphy: the wiphy to check the locking on
* @p: The pointer to read, prior to dereferencing
*
- * Return the value of the specified RCU-protected pointer, but omit the
+ * Return: the value of the specified RCU-protected pointer, but omit the
* READ_ONCE(), because caller holds the wiphy mutex used for updates.
*/
#define wiphy_dereference(wiphy, p) \
@@ -6031,6 +6031,10 @@ static inline void wiphy_unlock(struct wiphy *wiphy)
mutex_unlock(&wiphy->mtx);
}
+DEFINE_GUARD(wiphy, struct wiphy *,
+ mutex_lock(&_T->mtx),
+ mutex_unlock(&_T->mtx))
+
struct wiphy_work;
typedef void (*wiphy_work_func_t)(struct wiphy *, struct wiphy_work *);
diff --git a/include/net/devlink.h b/include/net/devlink.h
index fbb9a2668e24..fc79fe2297a1 100644
--- a/include/net/devlink.h
+++ b/include/net/devlink.h
@@ -35,7 +35,7 @@ struct devlink_port_phys_attrs {
/**
* struct devlink_port_pci_pf_attrs - devlink port's PCI PF attributes
* @controller: Associated controller number
- * @pf: Associated PCI PF number for this port.
+ * @pf: associated PCI function number for the devlink port instance
* @external: when set, indicates if a port is for an external controller
*/
struct devlink_port_pci_pf_attrs {
@@ -47,8 +47,9 @@ struct devlink_port_pci_pf_attrs {
/**
* struct devlink_port_pci_vf_attrs - devlink port's PCI VF attributes
* @controller: Associated controller number
- * @pf: Associated PCI PF number for this port.
- * @vf: Associated PCI VF for of the PCI PF for this port.
+ * @pf: associated PCI function number for the devlink port instance
+ * @vf: associated PCI VF number of a PF for the devlink port instance;
+ * VF number starts from 0 for the first PCI virtual function
* @external: when set, indicates if a port is for an external controller
*/
struct devlink_port_pci_vf_attrs {
@@ -61,8 +62,8 @@ struct devlink_port_pci_vf_attrs {
/**
* struct devlink_port_pci_sf_attrs - devlink port's PCI SF attributes
* @controller: Associated controller number
- * @sf: Associated PCI SF for of the PCI PF for this port.
- * @pf: Associated PCI PF number for this port.
+ * @sf: associated SF number of a PF for the devlink port instance
+ * @pf: associated PCI function number for the devlink port instance
* @external: when set, indicates if a port is for an external controller
*/
struct devlink_port_pci_sf_attrs {
@@ -1261,6 +1262,18 @@ enum devlink_trap_group_generic_id {
.min_burst = _min_burst, \
}
+#define devlink_fmsg_put(fmsg, name, value) ( \
+ _Generic((value), \
+ bool : devlink_fmsg_bool_pair_put, \
+ u8 : devlink_fmsg_u8_pair_put, \
+ u16 : devlink_fmsg_u32_pair_put, \
+ u32 : devlink_fmsg_u32_pair_put, \
+ u64 : devlink_fmsg_u64_pair_put, \
+ int : devlink_fmsg_u32_pair_put, \
+ char * : devlink_fmsg_string_pair_put, \
+ const char * : devlink_fmsg_string_pair_put) \
+ (fmsg, name, (value)))
+
enum {
/* device supports reload operations */
DEVLINK_F_RELOAD = 1UL << 0,
@@ -1994,6 +2007,7 @@ int devlink_compat_switch_id_get(struct net_device *dev,
int devlink_nl_port_handle_fill(struct sk_buff *msg, struct devlink_port *devlink_port);
size_t devlink_nl_port_handle_size(struct devlink_port *devlink_port);
+void devlink_fmsg_dump_skb(struct devlink_fmsg *fmsg, const struct sk_buff *skb);
#else
diff --git a/include/net/dropreason-core.h b/include/net/dropreason-core.h
index 6c5a1ea209a2..3a6602f37978 100644
--- a/include/net/dropreason-core.h
+++ b/include/net/dropreason-core.h
@@ -58,6 +58,12 @@
FN(TC_EGRESS) \
FN(SECURITY_HOOK) \
FN(QDISC_DROP) \
+ FN(QDISC_OVERLIMIT) \
+ FN(QDISC_CONGESTED) \
+ FN(CAKE_FLOOD) \
+ FN(FQ_BAND_LIMIT) \
+ FN(FQ_HORIZON_LIMIT) \
+ FN(FQ_FLOW_LIMIT) \
FN(CPU_BACKLOG) \
FN(XDP) \
FN(TC_INGRESS) \
@@ -100,11 +106,13 @@
FN(VXLAN_VNI_NOT_FOUND) \
FN(MAC_INVALID_SOURCE) \
FN(VXLAN_ENTRY_EXISTS) \
- FN(VXLAN_NO_REMOTE) \
+ FN(NO_TX_TARGET) \
FN(IP_TUNNEL_ECN) \
FN(TUNNEL_TXINFO) \
FN(LOCAL_MAC) \
FN(ARP_PVLAN_DISABLE) \
+ FN(MAC_IEEE_MAC_CONTROL) \
+ FN(BRIDGE_INGRESS_STP_STATE) \
FNe(MAX)
/**
@@ -312,6 +320,36 @@ enum skb_drop_reason {
*/
SKB_DROP_REASON_QDISC_DROP,
/**
+ * @SKB_DROP_REASON_QDISC_OVERLIMIT: dropped by qdisc when a qdisc
+ * instance exceeds its total buffer size limit.
+ */
+ SKB_DROP_REASON_QDISC_OVERLIMIT,
+ /**
+ * @SKB_DROP_REASON_QDISC_CONGESTED: dropped by a qdisc AQM algorithm
+ * due to congestion.
+ */
+ SKB_DROP_REASON_QDISC_CONGESTED,
+ /**
+ * @SKB_DROP_REASON_CAKE_FLOOD: dropped by the flood protection part of
+ * CAKE qdisc AQM algorithm (BLUE).
+ */
+ SKB_DROP_REASON_CAKE_FLOOD,
+ /**
+ * @SKB_DROP_REASON_FQ_BAND_LIMIT: dropped by fq qdisc when per band
+ * limit is reached.
+ */
+ SKB_DROP_REASON_FQ_BAND_LIMIT,
+ /**
+ * @SKB_DROP_REASON_FQ_HORIZON_LIMIT: dropped by fq qdisc when packet
+ * timestamp is too far in the future.
+ */
+ SKB_DROP_REASON_FQ_HORIZON_LIMIT,
+ /**
+ * @SKB_DROP_REASON_FQ_FLOW_LIMIT: dropped by fq qdisc when a flow
+ * exceeds its limits.
+ */
+ SKB_DROP_REASON_FQ_FLOW_LIMIT,
+ /**
* @SKB_DROP_REASON_CPU_BACKLOG: failed to enqueue the skb to the per CPU
* backlog queue. This can be caused by backlog queue full (see
* netdev_max_backlog in net.rst) or RPS flow limit
@@ -461,8 +499,8 @@ enum skb_drop_reason {
* entry or an entry pointing to a nexthop.
*/
SKB_DROP_REASON_VXLAN_ENTRY_EXISTS,
- /** @SKB_DROP_REASON_VXLAN_NO_REMOTE: no remote found for xmit */
- SKB_DROP_REASON_VXLAN_NO_REMOTE,
+ /** @SKB_DROP_REASON_NO_TX_TARGET: no target found for xmit */
+ SKB_DROP_REASON_NO_TX_TARGET,
/**
* @SKB_DROP_REASON_IP_TUNNEL_ECN: skb is dropped according to
* RFC 6040 4.2, see __INET_ECN_decapsulate() for detail.
@@ -485,6 +523,16 @@ enum skb_drop_reason {
*/
SKB_DROP_REASON_ARP_PVLAN_DISABLE,
/**
+ * @SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL: the destination MAC address
+ * is an IEEE MAC Control address.
+ */
+ SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL,
+ /**
+ * @SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE: the STP state of the
+ * ingress bridge port does not allow frames to be forwarded.
+ */
+ SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE,
+ /**
* @SKB_DROP_REASON_MAX: the maximum of core drop reasons, which
* shouldn't be used as a real 'reason' - only for tracing code gen
*/
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 72ae65e7246a..9640d5c67f56 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -988,10 +988,9 @@ struct dsa_switch_ops {
/*
* Port's MAC EEE settings
*/
+ bool (*support_eee)(struct dsa_switch *ds, int port);
int (*set_mac_eee)(struct dsa_switch *ds, int port,
struct ethtool_keee *e);
- int (*get_mac_eee)(struct dsa_switch *ds, int port,
- struct ethtool_keee *e);
/* EEPROM access */
int (*get_eeprom_len)(struct dsa_switch *ds);
@@ -1383,5 +1382,6 @@ static inline bool dsa_user_dev_check(const struct net_device *dev)
netdev_tx_t dsa_enqueue_skb(struct sk_buff *skb, struct net_device *dev);
void dsa_port_phylink_mac_change(struct dsa_switch *ds, int port, bool up);
+bool dsa_supports_eee(struct dsa_switch *ds, int port);
#endif
diff --git a/include/net/dst.h b/include/net/dst.h
index 0f303cc60252..78c78cdce0e9 100644
--- a/include/net/dst.h
+++ b/include/net/dst.h
@@ -307,7 +307,7 @@ static inline bool dst_hold_safe(struct dst_entry *dst)
* @skb: buffer
*
* If dst is not yet refcounted and not destroyed, grab a ref on it.
- * Returns true if dst is refcounted.
+ * Returns: true if dst is refcounted.
*/
static inline bool skb_dst_force(struct sk_buff *skb)
{
@@ -440,6 +440,15 @@ static inline void dst_set_expires(struct dst_entry *dst, int timeout)
dst->expires = expires;
}
+static inline unsigned int dst_dev_overhead(struct dst_entry *dst,
+ struct sk_buff *skb)
+{
+ if (likely(dst))
+ return LL_RESERVED_SPACE(dst->dev);
+
+ return skb->mac_len;
+}
+
INDIRECT_CALLABLE_DECLARE(int ip6_output(struct net *, struct sock *,
struct sk_buff *));
INDIRECT_CALLABLE_DECLARE(int ip_output(struct net *, struct sock *,
diff --git a/include/net/genetlink.h b/include/net/genetlink.h
index d096cc6352de..a03d56765832 100644
--- a/include/net/genetlink.h
+++ b/include/net/genetlink.h
@@ -354,7 +354,7 @@ __genlmsg_iput(struct sk_buff *skb, const struct genl_info *info, int flags)
* such requests) or a struct initialized by genl_info_init_ntf()
* when constructing notifications.
*
- * Returns pointer to new genetlink header.
+ * Returns: pointer to new genetlink header.
*/
static inline void *
genlmsg_iput(struct sk_buff *skb, const struct genl_info *info)
@@ -366,7 +366,7 @@ genlmsg_iput(struct sk_buff *skb, const struct genl_info *info)
* genlmsg_nlhdr - Obtain netlink header from user specified header
* @user_hdr: user header as returned from genlmsg_put()
*
- * Returns pointer to netlink header.
+ * Returns: pointer to netlink header.
*/
static inline struct nlmsghdr *genlmsg_nlhdr(void *user_hdr)
{
@@ -435,7 +435,7 @@ static inline void genl_dump_check_consistent(struct netlink_callback *cb,
* @flags: netlink message flags
* @cmd: generic netlink command
*
- * Returns pointer to user specific header
+ * Returns: pointer to user specific header
*/
static inline void *genlmsg_put_reply(struct sk_buff *skb,
struct genl_info *info,
diff --git a/include/net/inet_connection_sock.h b/include/net/inet_connection_sock.h
index 3c82fad904d4..c7f42844c79a 100644
--- a/include/net/inet_connection_sock.h
+++ b/include/net/inet_connection_sock.h
@@ -282,7 +282,7 @@ static inline int inet_csk_reqsk_queue_len(const struct sock *sk)
static inline int inet_csk_reqsk_queue_is_full(const struct sock *sk)
{
- return inet_csk_reqsk_queue_len(sk) >= READ_ONCE(sk->sk_max_ack_backlog);
+ return inet_csk_reqsk_queue_len(sk) > READ_ONCE(sk->sk_max_ack_backlog);
}
bool inet_csk_reqsk_queue_drop(struct sock *sk, struct request_sock *req);
diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
index 56d8bc5593d3..1086256549fa 100644
--- a/include/net/inet_sock.h
+++ b/include/net/inet_sock.h
@@ -19,6 +19,7 @@
#include <linux/netdevice.h>
#include <net/flow.h>
+#include <net/inet_dscp.h>
#include <net/sock.h>
#include <net/request_sock.h>
#include <net/netns/hash.h>
@@ -172,7 +173,7 @@ struct inet_cork {
u8 tx_flags;
__u8 ttl;
__s16 tos;
- char priority;
+ u32 priority;
__u16 gso_size;
u32 ts_opt_id;
u64 transmit_time;
@@ -302,6 +303,11 @@ static inline unsigned long inet_cmsg_flags(const struct inet_sock *inet)
return READ_ONCE(inet->inet_flags) & IP_CMSG_ALL;
}
+static inline dscp_t inet_sk_dscp(const struct inet_sock *inet)
+{
+ return inet_dsfield_to_dscp(READ_ONCE(inet->tos));
+}
+
#define inet_test_bit(nr, sk) \
test_bit(INET_FLAGS_##nr, &inet_sk(sk)->inet_flags)
#define inet_set_bit(nr, sk) \
diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
index beb533a0e880..67a313575780 100644
--- a/include/net/inet_timewait_sock.h
+++ b/include/net/inet_timewait_sock.h
@@ -45,6 +45,8 @@ struct inet_timewait_sock {
#define tw_node __tw_common.skc_nulls_node
#define tw_bind_node __tw_common.skc_bind_node
#define tw_refcnt __tw_common.skc_refcnt
+#define tw_tx_queue_mapping __tw_common.skc_tx_queue_mapping
+#define tw_rx_queue_mapping __tw_common.skc_rx_queue_mapping
#define tw_hash __tw_common.skc_hash
#define tw_prot __tw_common.skc_prot
#define tw_net __tw_common.skc_net
@@ -72,6 +74,10 @@ struct inet_timewait_sock {
tw_tos : 8;
u32 tw_txhash;
u32 tw_priority;
+ /**
+ * @tw_reuse_stamp: Time of entry into %TCP_TIME_WAIT state in msec.
+ */
+ u32 tw_entry_stamp;
struct timer_list tw_timer;
struct inet_bind_bucket *tw_tb;
struct inet_bind2_bucket *tw_tb2;
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 74ff688568a0..f475757daafb 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -96,30 +96,28 @@ static inline struct in6_addr *inetpeer_get_addr_v6(struct inetpeer_addr *iaddr)
/* can be called with or without local BH being disabled */
struct inet_peer *inet_getpeer(struct inet_peer_base *base,
- const struct inetpeer_addr *daddr,
- int create);
+ const struct inetpeer_addr *daddr);
static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base,
__be32 v4daddr,
- int vif, int create)
+ int vif)
{
struct inetpeer_addr daddr;
daddr.a4.addr = v4daddr;
daddr.a4.vif = vif;
daddr.family = AF_INET;
- return inet_getpeer(base, &daddr, create);
+ return inet_getpeer(base, &daddr);
}
static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base,
- const struct in6_addr *v6daddr,
- int create)
+ const struct in6_addr *v6daddr)
{
struct inetpeer_addr daddr;
daddr.a6 = *v6daddr;
daddr.family = AF_INET6;
- return inet_getpeer(base, &daddr, create);
+ return inet_getpeer(base, &daddr);
}
static inline int inetpeer_addr_cmp(const struct inetpeer_addr *a,
diff --git a/include/net/ip.h b/include/net/ip.h
index 0e548c1f2a0e..9f5e33e371fc 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -81,7 +81,6 @@ struct ipcm_cookie {
__u8 protocol;
__u8 ttl;
__s16 tos;
- char priority;
__u16 gso_size;
};
@@ -96,6 +95,7 @@ static inline void ipcm_init_sk(struct ipcm_cookie *ipcm,
ipcm_init(ipcm);
ipcm->sockc.mark = READ_ONCE(inet->sk.sk_mark);
+ ipcm->sockc.priority = READ_ONCE(inet->sk.sk_priority);
ipcm->sockc.tsflags = READ_ONCE(inet->sk.sk_tsflags);
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 248bfb26e2af..f5c43ad1565e 100644
--- a/include/net/ipv6.h
+++ b/include/net/ipv6.h
@@ -471,7 +471,7 @@ struct ipv6_txoptions *ipv6_update_options(struct sock *sk,
/* 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.
+ * Returns: 0, or IPPROTO_TCP if a BIG TCP packet is there.
*/
static inline int ipv6_has_hopopt_jumbo(const struct sk_buff *skb)
{
diff --git a/include/net/iucv/iucv.h b/include/net/iucv/iucv.h
index dd9e93c12260..9804fa5d9c67 100644
--- a/include/net/iucv/iucv.h
+++ b/include/net/iucv/iucv.h
@@ -202,7 +202,7 @@ struct iucv_handler {
*
* Registers a driver with IUCV.
*
- * Returns 0 on success, -ENOMEM if the memory allocation for the pathid
+ * Returns: 0 on success, -ENOMEM if the memory allocation for the pathid
* table failed, or -EIO if IUCV_DECLARE_BUFFER failed on all cpus.
*/
int iucv_register(struct iucv_handler *handler, int smp);
@@ -224,7 +224,7 @@ void iucv_unregister(struct iucv_handler *handle, int smp);
*
* Allocate a new path structure for use with iucv_connect.
*
- * Returns NULL if the memory allocation failed or a pointer to the
+ * Returns: NULL if the memory allocation failed or a pointer to the
* path structure.
*/
static inline struct iucv_path *iucv_path_alloc(u16 msglim, u8 flags, gfp_t gfp)
@@ -260,7 +260,7 @@ static inline void iucv_path_free(struct iucv_path *path)
* This function is issued after the user received a connection pending
* external interrupt and now wishes to complete the IUCV communication path.
*
- * Returns the result of the CP IUCV call.
+ * Returns: the result of the CP IUCV call.
*/
int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
u8 *userdata, void *private);
@@ -278,7 +278,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler,
* successfully, you are not able to use the path until you receive an IUCV
* Connection Complete external interrupt.
*
- * Returns the result of the CP IUCV call.
+ * Returns: the result of the CP IUCV call.
*/
int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
u8 *userid, u8 *system, u8 *userdata,
@@ -292,7 +292,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler,
* This function temporarily suspends incoming messages on an IUCV path.
* You can later reactivate the path by invoking the iucv_resume function.
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int iucv_path_quiesce(struct iucv_path *path, u8 *userdata);
@@ -304,7 +304,7 @@ int iucv_path_quiesce(struct iucv_path *path, u8 *userdata);
* This function resumes incoming messages on an IUCV path that has
* been stopped with iucv_path_quiesce.
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int iucv_path_resume(struct iucv_path *path, u8 *userdata);
@@ -315,7 +315,7 @@ int iucv_path_resume(struct iucv_path *path, u8 *userdata);
*
* This function terminates an IUCV path.
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int iucv_path_sever(struct iucv_path *path, u8 *userdata);
@@ -327,7 +327,7 @@ int iucv_path_sever(struct iucv_path *path, u8 *userdata);
*
* Cancels a message you have sent.
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
u32 srccls);
@@ -347,7 +347,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg,
*
* Locking: local_bh_enable/local_bh_disable
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
u8 flags, void *buffer, size_t size, size_t *residual);
@@ -367,7 +367,7 @@ int iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
*
* Locking: no locking.
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
u8 flags, void *buffer, size_t size,
@@ -382,7 +382,7 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg,
* are notified of a message and the time that you complete the message,
* the message may be rejected.
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg);
@@ -399,7 +399,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg);
* pathid, msgid, and trgcls. Prmmsg signifies the data is moved into
* the parameter list.
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
u8 flags, void *reply, size_t size);
@@ -419,7 +419,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg,
*
* Locking: local_bh_enable/local_bh_disable
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
u8 flags, u32 srccls, void *buffer, size_t size);
@@ -439,7 +439,7 @@ int iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
*
* Locking: no locking.
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
u8 flags, u32 srccls, void *buffer, size_t size);
@@ -461,7 +461,7 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg,
* reply to the message and a buffer is provided into which IUCV moves
* the reply to this message.
*
- * Returns the result from the CP IUCV call.
+ * Returns: the result from the CP IUCV call.
*/
int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg,
u8 flags, u32 srccls, void *buffer, size_t size,
diff --git a/include/net/lapb.h b/include/net/lapb.h
index 124ee122f2c8..6c07420644e4 100644
--- a/include/net/lapb.h
+++ b/include/net/lapb.h
@@ -4,7 +4,7 @@
#include <linux/lapb.h>
#include <linux/refcount.h>
-#define LAPB_HEADER_LEN 20 /* LAPB over Ethernet + a bit more */
+#define LAPB_HEADER_LEN MAX_HEADER /* LAPB over Ethernet + a bit more */
#define LAPB_ACK_PENDING_CONDITION 0x01
#define LAPB_REJECT_CONDITION 0x02
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index a97c9f85ae9a..9320d4bc22ee 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1987,6 +1987,8 @@ enum ieee80211_neg_ttlm_res {
* @neg_ttlm: negotiated TID to link mapping info.
* see &struct ieee80211_neg_ttlm.
* @addr: address of this interface
+ * @addr_valid: indicates if the address is actively used. Set to false for
+ * passive monitor interfaces, true in all other cases.
* @p2p: indicates whether this AP or STA interface is a p2p
* interface, i.e. a GO or p2p-sta respectively
* @netdev_features: tx netdev features supported by the hardware for this
@@ -2026,6 +2028,7 @@ struct ieee80211_vif {
u16 valid_links, active_links, dormant_links, suspended_links;
struct ieee80211_neg_ttlm neg_ttlm;
u8 addr[ETH_ALEN] __aligned(2);
+ bool addr_valid;
bool p2p;
u8 cab_queue;
@@ -4759,7 +4762,7 @@ struct ieee80211_ops {
u32 (*get_expected_throughput)(struct ieee80211_hw *hw,
struct ieee80211_sta *sta);
int (*get_txpower)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
- int *dbm);
+ unsigned int link_id, int *dbm);
int (*tdls_channel_switch)(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
@@ -6795,14 +6798,12 @@ void ieee80211_chswitch_done(struct ieee80211_vif *vif, bool success,
/**
* ieee80211_channel_switch_disconnect - disconnect due to channel switch error
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
- * @block_tx: if %true, do not send deauth frame.
*
* Instruct mac80211 to disconnect due to a channel switch error. The channel
* switch can request to block the tx and so, we need to make sure we do not send
* a deauth frame in this case.
*/
-void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif,
- bool block_tx);
+void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif);
/**
* ieee80211_request_smps - request SM PS transition
diff --git a/include/net/net_debug.h b/include/net/net_debug.h
index 9fecb1496be3..47f7a4a878b9 100644
--- a/include/net/net_debug.h
+++ b/include/net/net_debug.h
@@ -27,7 +27,7 @@ void netdev_info(const struct net_device *dev, const char *format, ...);
#define netdev_level_once(level, dev, fmt, ...) \
do { \
- static bool __section(".data.once") __print_once; \
+ static bool __section(".data..once") __print_once; \
\
if (!__print_once) { \
__print_once = true; \
diff --git a/include/net/net_namespace.h b/include/net/net_namespace.h
index 873c0f9fdac6..5a2a0df8ad91 100644
--- a/include/net/net_namespace.h
+++ b/include/net/net_namespace.h
@@ -80,6 +80,7 @@ struct net {
* or to unregister pernet ops
* (pernet_ops_rwsem write locked).
*/
+ struct llist_node defer_free_list;
struct llist_node cleanup_list; /* namespaces on death row */
#ifdef CONFIG_KEYS
@@ -325,6 +326,11 @@ static inline int check_net(const struct net *net)
#define net_drop_ns NULL
#endif
+/* Returns true if the netns initialization is completed successfully */
+static inline bool net_initialized(const struct net *net)
+{
+ return READ_ONCE(net->list.next);
+}
static inline void __netns_tracker_alloc(struct net *net,
netns_tracker *tracker,
diff --git a/include/net/netfilter/nf_tables.h b/include/net/netfilter/nf_tables.h
index 80a537ac26cd..0027beca5cd5 100644
--- a/include/net/netfilter/nf_tables.h
+++ b/include/net/netfilter/nf_tables.h
@@ -733,15 +733,18 @@ struct nft_set_ext_tmpl {
/**
* struct nft_set_ext - set extensions
*
- * @genmask: generation mask
+ * @genmask: generation mask, but also flags (see NFT_SET_ELEM_DEAD_BIT)
* @offset: offsets of individual extension types
* @data: beginning of extension data
+ *
+ * This structure must be aligned to word size, otherwise atomic bitops
+ * on genmask field can cause alignment failure on some archs.
*/
struct nft_set_ext {
u8 genmask;
u8 offset[NFT_SET_EXT_NUM];
char data[];
-};
+} __aligned(BITS_PER_LONG / 8);
static inline void nft_set_ext_prepare(struct nft_set_ext_tmpl *tmpl)
{
@@ -1103,7 +1106,6 @@ struct nft_rule_blob {
* @name: name of the chain
* @udlen: user data length
* @udata: user data in the chain
- * @rcu_head: rcu head for deferred release
* @blob_next: rule blob pointer to the next in the chain
*/
struct nft_chain {
@@ -1121,7 +1123,6 @@ struct nft_chain {
char *name;
u16 udlen;
u8 *udata;
- struct rcu_head rcu_head;
/* Only used during control plane commit phase: */
struct nft_rule_blob *blob_next;
@@ -1265,7 +1266,6 @@ static inline void nft_use_inc_restore(u32 *use)
* @sets: sets in the table
* @objects: stateful objects in the table
* @flowtables: flow tables in the table
- * @net: netnamespace this table belongs to
* @hgenerator: handle generator state
* @handle: table handle
* @use: number of chain references to this table
@@ -1285,7 +1285,6 @@ struct nft_table {
struct list_head sets;
struct list_head objects;
struct list_head flowtables;
- possible_net_t net;
u64 hgenerator;
u64 handle;
u32 use;
diff --git a/include/net/netfilter/nf_tables_core.h b/include/net/netfilter/nf_tables_core.h
index ff27cb2e1662..03b6165756fc 100644
--- a/include/net/netfilter/nf_tables_core.h
+++ b/include/net/netfilter/nf_tables_core.h
@@ -161,6 +161,7 @@ enum {
};
struct nft_inner_tun_ctx {
+ unsigned long cookie;
u16 type;
u16 inner_tunoff;
u16 inner_lloff;
diff --git a/include/net/netfilter/nf_tproxy.h b/include/net/netfilter/nf_tproxy.h
index 5adf6fda11e8..06985530517b 100644
--- a/include/net/netfilter/nf_tproxy.h
+++ b/include/net/netfilter/nf_tproxy.h
@@ -49,7 +49,7 @@ __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr);
*
* nf_tproxy_handle_time_wait4() consumes the socket reference passed in.
*
- * Returns the listener socket if there's one, the TIME_WAIT socket if
+ * Returns: the listener socket if there's one, the TIME_WAIT socket if
* no such listener is found, or NULL if the TCP header is incomplete.
*/
struct sock *
@@ -108,7 +108,7 @@ nf_tproxy_laddr6(struct sk_buff *skb, const struct in6_addr *user_laddr,
*
* nf_tproxy_handle_time_wait6() consumes the socket reference passed in.
*
- * Returns the listener socket if there's one, the TIME_WAIT socket if
+ * Returns: the listener socket if there's one, the TIME_WAIT socket if
* no such listener is found, or NULL if the TCP header is incomplete.
*/
struct sock *
diff --git a/include/net/netlink.h b/include/net/netlink.h
index 39eaa6be6ca8..e015ffbed819 100644
--- a/include/net/netlink.h
+++ b/include/net/netlink.h
@@ -649,7 +649,7 @@ static inline int nlmsg_ok(const struct nlmsghdr *nlh, int remaining)
* @nlh: netlink message header
* @remaining: number of bytes remaining in message stream
*
- * Returns the next netlink message in the message stream and
+ * Returns: the next netlink message in the message stream and
* decrements remaining by the size of the current message.
*/
static inline struct nlmsghdr *
@@ -676,7 +676,7 @@ nlmsg_next(const struct nlmsghdr *nlh, int *remaining)
* exceeding maxtype will be rejected, policy must be specified, attributes
* will be validated in the strictest way possible.
*
- * Returns 0 on success or a negative error code.
+ * Returns: 0 on success or a negative error code.
*/
static inline int nla_parse(struct nlattr **tb, int maxtype,
const struct nlattr *head, int len,
@@ -701,7 +701,7 @@ static inline int nla_parse(struct nlattr **tb, int maxtype,
* exceeding maxtype will be ignored and attributes from the policy are not
* always strictly validated (only for new attributes).
*
- * Returns 0 on success or a negative error code.
+ * Returns: 0 on success or a negative error code.
*/
static inline int nla_parse_deprecated(struct nlattr **tb, int maxtype,
const struct nlattr *head, int len,
@@ -726,7 +726,7 @@ static inline int nla_parse_deprecated(struct nlattr **tb, int maxtype,
* exceeding maxtype will be rejected as well as trailing data, but the
* policy is not completely strictly validated (only for new attributes).
*
- * Returns 0 on success or a negative error code.
+ * Returns: 0 on success or a negative error code.
*/
static inline int nla_parse_deprecated_strict(struct nlattr **tb, int maxtype,
const struct nlattr *head,
@@ -833,7 +833,7 @@ nlmsg_parse_deprecated_strict(const struct nlmsghdr *nlh, int hdrlen,
* @hdrlen: length of family specific header
* @attrtype: type of attribute to look for
*
- * Returns the first attribute which matches the specified type.
+ * Returns: the first attribute which matches the specified type.
*/
static inline struct nlattr *nlmsg_find_attr(const struct nlmsghdr *nlh,
int hdrlen, int attrtype)
@@ -854,7 +854,7 @@ static inline struct nlattr *nlmsg_find_attr(const struct nlmsghdr *nlh,
* specified policy. Validation is done in liberal mode.
* See documentation of struct nla_policy for more details.
*
- * Returns 0 on success or a negative error code.
+ * Returns: 0 on success or a negative error code.
*/
static inline int nla_validate_deprecated(const struct nlattr *head, int len,
int maxtype,
@@ -877,7 +877,7 @@ static inline int nla_validate_deprecated(const struct nlattr *head, int len,
* specified policy. Validation is done in strict mode.
* See documentation of struct nla_policy for more details.
*
- * Returns 0 on success or a negative error code.
+ * Returns: 0 on success or a negative error code.
*/
static inline int nla_validate(const struct nlattr *head, int len, int maxtype,
const struct nla_policy *policy,
@@ -914,7 +914,7 @@ static inline int nlmsg_validate_deprecated(const struct nlmsghdr *nlh,
* nlmsg_report - need to report back to application?
* @nlh: netlink message header
*
- * Returns 1 if a report back to the application is requested.
+ * Returns: 1 if a report back to the application is requested.
*/
static inline int nlmsg_report(const struct nlmsghdr *nlh)
{
@@ -925,7 +925,7 @@ static inline int nlmsg_report(const struct nlmsghdr *nlh)
* nlmsg_seq - return the seq number of netlink message
* @nlh: netlink message header
*
- * Returns 0 if netlink message is NULL
+ * Returns: 0 if netlink message is NULL
*/
static inline u32 nlmsg_seq(const struct nlmsghdr *nlh)
{
@@ -952,7 +952,7 @@ static inline u32 nlmsg_seq(const struct nlmsghdr *nlh)
* @payload: length of message payload
* @flags: message flags
*
- * Returns NULL if the tailroom of the skb is insufficient to store
+ * Returns: NULL if the tailroom of the skb is insufficient to store
* the message header and payload.
*/
static inline struct nlmsghdr *nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq,
@@ -971,7 +971,7 @@ static inline struct nlmsghdr *nlmsg_put(struct sk_buff *skb, u32 portid, u32 se
*
* Append data to an existing nlmsg, used when constructing a message
* with multiple fixed-format headers (which is rare).
- * Returns NULL if the tailroom of the skb is insufficient to store
+ * Returns: NULL if the tailroom of the skb is insufficient to store
* the extra payload.
*/
static inline void *nlmsg_append(struct sk_buff *skb, u32 size)
@@ -993,7 +993,7 @@ static inline void *nlmsg_append(struct sk_buff *skb, u32 size)
* @payload: length of message payload
* @flags: message flags
*
- * Returns NULL if the tailroom of the skb is insufficient to store
+ * Returns: NULL if the tailroom of the skb is insufficient to store
* the message header and payload.
*/
static inline struct nlmsghdr *nlmsg_put_answer(struct sk_buff *skb,
@@ -1050,7 +1050,7 @@ static inline void nlmsg_end(struct sk_buff *skb, struct nlmsghdr *nlh)
* nlmsg_get_pos - return current position in netlink message
* @skb: socket buffer the message is stored in
*
- * Returns a pointer to the current tail of the message.
+ * Returns: a pointer to the current tail of the message.
*/
static inline void *nlmsg_get_pos(struct sk_buff *skb)
{
@@ -1276,7 +1276,7 @@ static inline int nla_ok(const struct nlattr *nla, int remaining)
* @nla: netlink attribute
* @remaining: number of bytes remaining in attribute stream
*
- * Returns the next netlink attribute in the attribute stream and
+ * Returns: the next netlink attribute in the attribute stream and
* decrements remaining by the size of the current attribute.
*/
static inline struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
@@ -1292,7 +1292,7 @@ static inline struct nlattr *nla_next(const struct nlattr *nla, int *remaining)
* @nla: attribute containing the nested attributes
* @attrtype: type of attribute to look for
*
- * Returns the first attribute which matches the specified type.
+ * Returns: the first attribute which matches the specified type.
*/
static inline struct nlattr *
nla_find_nested(const struct nlattr *nla, int attrtype)
@@ -2091,7 +2091,7 @@ static inline int nla_get_flag(const struct nlattr *nla)
* nla_get_msecs - return payload of msecs attribute
* @nla: msecs netlink attribute
*
- * Returns the number of milliseconds in jiffies.
+ * Returns: the number of milliseconds in jiffies.
*/
static inline unsigned long nla_get_msecs(const struct nlattr *nla)
{
@@ -2183,7 +2183,7 @@ static inline void *nla_memdup_noprof(const struct nlattr *src, gfp_t gfp)
* marked their nest attributes with NLA_F_NESTED flag. New APIs should use
* nla_nest_start() which sets the flag.
*
- * Returns the container attribute or NULL on error
+ * Returns: the container attribute or NULL on error
*/
static inline struct nlattr *nla_nest_start_noflag(struct sk_buff *skb,
int attrtype)
@@ -2204,7 +2204,7 @@ static inline struct nlattr *nla_nest_start_noflag(struct sk_buff *skb,
* Unlike nla_nest_start_noflag(), mark the nest attribute with NLA_F_NESTED
* flag. This is the preferred function to use in new code.
*
- * Returns the container attribute or NULL on error
+ * Returns: the container attribute or NULL on error
*/
static inline struct nlattr *nla_nest_start(struct sk_buff *skb, int attrtype)
{
@@ -2219,7 +2219,7 @@ static inline struct nlattr *nla_nest_start(struct sk_buff *skb, int attrtype)
* Corrects the container attribute header to include the all
* appended attributes.
*
- * Returns the total data length of the skb.
+ * Returns: the total data length of the skb.
*/
static inline int nla_nest_end(struct sk_buff *skb, struct nlattr *start)
{
@@ -2252,7 +2252,7 @@ static inline void nla_nest_cancel(struct sk_buff *skb, struct nlattr *start)
* specified policy. Attributes with a type exceeding maxtype will be
* ignored. See documentation of struct nla_policy for more details.
*
- * Returns 0 on success or a negative error code.
+ * Returns: 0 on success or a negative error code.
*/
static inline int __nla_validate_nested(const struct nlattr *start, int maxtype,
const struct nla_policy *policy,
@@ -2285,7 +2285,7 @@ nla_validate_nested_deprecated(const struct nlattr *start, int maxtype,
* nla_need_padding_for_64bit - test 64-bit alignment of the next attribute
* @skb: socket buffer the message is stored in
*
- * Return true if padding is needed to align the next attribute (nla_data()) to
+ * Return: true if padding is needed to align the next attribute (nla_data()) to
* a 64-bit aligned area.
*/
static inline bool nla_need_padding_for_64bit(struct sk_buff *skb)
@@ -2312,7 +2312,7 @@ static inline bool nla_need_padding_for_64bit(struct sk_buff *skb)
* This will only be done in architectures which do not have
* CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS defined.
*
- * Returns zero on success or a negative error code.
+ * Returns: zero on success or a negative error code.
*/
static inline int nla_align_64bit(struct sk_buff *skb, int padattr)
{
diff --git a/include/net/netmem.h b/include/net/netmem.h
index 8a6e20be4b9d..1b58faa4f20f 100644
--- a/include/net/netmem.h
+++ b/include/net/netmem.h
@@ -72,6 +72,22 @@ static inline bool netmem_is_net_iov(const netmem_ref netmem)
return (__force unsigned long)netmem & NET_IOV;
}
+/**
+ * __netmem_to_page - unsafely get pointer to the &page backing @netmem
+ * @netmem: netmem reference to convert
+ *
+ * Unsafe version of netmem_to_page(). When @netmem is always page-backed,
+ * e.g. when it's a header buffer, performs faster and generates smaller
+ * object code (no check for the LSB, no WARN). When @netmem points to IOV,
+ * provokes undefined behaviour.
+ *
+ * Return: pointer to the &page (garbage if @netmem is not page-backed).
+ */
+static inline struct page *__netmem_to_page(netmem_ref netmem)
+{
+ return (__force struct page *)netmem;
+}
+
/* This conversion fails (returns NULL) if the netmem_ref is not struct page
* backed.
*/
@@ -80,7 +96,7 @@ static inline struct page *netmem_to_page(netmem_ref netmem)
if (WARN_ON_ONCE(netmem_is_net_iov(netmem)))
return NULL;
- return (__force struct page *)netmem;
+ return __netmem_to_page(netmem);
}
static inline struct net_iov *netmem_to_net_iov(netmem_ref netmem)
@@ -103,6 +119,17 @@ static inline netmem_ref page_to_netmem(struct page *page)
return (__force netmem_ref)page;
}
+/**
+ * virt_to_netmem - convert virtual memory pointer to a netmem reference
+ * @data: host memory pointer to convert
+ *
+ * Return: netmem reference to the &page backing this virtual address.
+ */
+static inline netmem_ref virt_to_netmem(const void *data)
+{
+ return page_to_netmem(virt_to_page(data));
+}
+
static inline int netmem_ref_count(netmem_ref netmem)
{
/* The non-pp refcount of net_iov is always 1. On net_iov, we only
@@ -127,6 +154,22 @@ static inline struct net_iov *__netmem_clear_lsb(netmem_ref netmem)
return (struct net_iov *)((__force unsigned long)netmem & ~NET_IOV);
}
+/**
+ * __netmem_get_pp - unsafely get pointer to the &page_pool backing @netmem
+ * @netmem: netmem reference to get the pointer from
+ *
+ * Unsafe version of netmem_get_pp(). When @netmem is always page-backed,
+ * e.g. when it's a header buffer, performs faster and generates smaller
+ * object code (avoids clearing the LSB). When @netmem points to IOV,
+ * provokes invalid memory access.
+ *
+ * Return: pointer to the &page_pool (garbage if @netmem is not page-backed).
+ */
+static inline struct page_pool *__netmem_get_pp(netmem_ref netmem)
+{
+ return __netmem_to_page(netmem)->pp;
+}
+
static inline struct page_pool *netmem_get_pp(netmem_ref netmem)
{
return __netmem_clear_lsb(netmem)->pp;
@@ -158,12 +201,43 @@ static inline netmem_ref netmem_compound_head(netmem_ref netmem)
return page_to_netmem(compound_head(netmem_to_page(netmem)));
}
+/**
+ * __netmem_address - unsafely get pointer to the memory backing @netmem
+ * @netmem: netmem reference to get the pointer for
+ *
+ * Unsafe version of netmem_address(). When @netmem is always page-backed,
+ * e.g. when it's a header buffer, performs faster and generates smaller
+ * object code (no check for the LSB). When @netmem points to IOV, provokes
+ * undefined behaviour.
+ *
+ * Return: pointer to the memory (garbage if @netmem is not page-backed).
+ */
+static inline void *__netmem_address(netmem_ref netmem)
+{
+ return page_address(__netmem_to_page(netmem));
+}
+
static inline void *netmem_address(netmem_ref netmem)
{
if (netmem_is_net_iov(netmem))
return NULL;
- return page_address(netmem_to_page(netmem));
+ return __netmem_address(netmem);
+}
+
+/**
+ * netmem_is_pfmemalloc - check if @netmem was allocated under memory pressure
+ * @netmem: netmem reference to check
+ *
+ * Return: true if @netmem is page-backed and the page was allocated under
+ * memory pressure, false otherwise.
+ */
+static inline bool netmem_is_pfmemalloc(netmem_ref netmem)
+{
+ if (netmem_is_net_iov(netmem))
+ return false;
+
+ return page_is_pfmemalloc(netmem_to_page(netmem));
}
static inline unsigned long netmem_get_dma_addr(netmem_ref netmem)
diff --git a/include/net/netns/ipv4.h b/include/net/netns/ipv4.h
index 3c014170e001..46452da35206 100644
--- a/include/net/netns/ipv4.h
+++ b/include/net/netns/ipv4.h
@@ -175,6 +175,7 @@ struct netns_ipv4 {
u8 sysctl_tcp_retries2;
u8 sysctl_tcp_orphan_retries;
u8 sysctl_tcp_tw_reuse;
+ unsigned int sysctl_tcp_tw_reuse_delay;
int sysctl_tcp_fin_timeout;
u8 sysctl_tcp_sack;
u8 sysctl_tcp_window_scaling;
diff --git a/include/net/page_pool/helpers.h b/include/net/page_pool/helpers.h
index 793e6fd78bc5..543f54fa3020 100644
--- a/include/net/page_pool/helpers.h
+++ b/include/net/page_pool/helpers.h
@@ -104,8 +104,7 @@ static inline struct page *page_pool_dev_alloc_pages(struct page_pool *pool)
*
* Get a page fragment from the page allocator or page_pool caches.
*
- * Return:
- * Return allocated page fragment, otherwise return NULL.
+ * Return: allocated page fragment, otherwise return NULL.
*/
static inline struct page *page_pool_dev_alloc_frag(struct page_pool *pool,
unsigned int *offset,
@@ -116,22 +115,22 @@ static inline struct page *page_pool_dev_alloc_frag(struct page_pool *pool,
return page_pool_alloc_frag(pool, offset, size, gfp);
}
-static inline struct page *page_pool_alloc(struct page_pool *pool,
- unsigned int *offset,
- unsigned int *size, gfp_t gfp)
+static inline netmem_ref page_pool_alloc_netmem(struct page_pool *pool,
+ unsigned int *offset,
+ unsigned int *size, gfp_t gfp)
{
unsigned int max_size = PAGE_SIZE << pool->p.order;
- struct page *page;
+ netmem_ref netmem;
if ((*size << 1) > max_size) {
*size = max_size;
*offset = 0;
- return page_pool_alloc_pages(pool, gfp);
+ return page_pool_alloc_netmems(pool, gfp);
}
- page = page_pool_alloc_frag(pool, offset, *size, gfp);
- if (unlikely(!page))
- return NULL;
+ netmem = page_pool_alloc_frag_netmem(pool, offset, *size, gfp);
+ if (unlikely(!netmem))
+ return 0;
/* There is very likely not enough space for another fragment, so append
* the remaining size to the current fragment to avoid truesize
@@ -142,7 +141,23 @@ static inline struct page *page_pool_alloc(struct page_pool *pool,
pool->frag_offset = max_size;
}
- return page;
+ return netmem;
+}
+
+static inline netmem_ref page_pool_dev_alloc_netmem(struct page_pool *pool,
+ unsigned int *offset,
+ unsigned int *size)
+{
+ gfp_t gfp = GFP_ATOMIC | __GFP_NOWARN;
+
+ return page_pool_alloc_netmem(pool, offset, size, gfp);
+}
+
+static inline struct page *page_pool_alloc(struct page_pool *pool,
+ unsigned int *offset,
+ unsigned int *size, gfp_t gfp)
+{
+ return netmem_to_page(page_pool_alloc_netmem(pool, offset, size, gfp));
}
/**
@@ -155,8 +170,7 @@ static inline struct page *page_pool_alloc(struct page_pool *pool,
* depending on the requested size in order to allocate memory with least memory
* utilization and performance penalty.
*
- * Return:
- * Return allocated page or page fragment, otherwise return NULL.
+ * Return: allocated page or page fragment, otherwise return NULL.
*/
static inline struct page *page_pool_dev_alloc(struct page_pool *pool,
unsigned int *offset,
@@ -190,8 +204,7 @@ static inline void *page_pool_alloc_va(struct page_pool *pool,
* This is just a thin wrapper around the page_pool_alloc() API, and
* it returns va of the allocated page or page fragment.
*
- * Return:
- * Return the va for the allocated page or page fragment, otherwise return NULL.
+ * Return: the va for the allocated page or page fragment, otherwise return NULL.
*/
static inline void *page_pool_dev_alloc_va(struct page_pool *pool,
unsigned int *size)
@@ -302,7 +315,7 @@ static inline void page_pool_ref_page(struct page *page)
page_pool_ref_netmem(page_to_netmem(page));
}
-static inline bool page_pool_is_last_ref(netmem_ref netmem)
+static inline bool page_pool_unref_and_test(netmem_ref netmem)
{
/* If page_pool_unref_page() returns 0, we were the last user */
return page_pool_unref_netmem(netmem, 1) == 0;
@@ -317,7 +330,7 @@ static inline void page_pool_put_netmem(struct page_pool *pool,
* allow registering MEM_TYPE_PAGE_POOL, but shield linker.
*/
#ifdef CONFIG_PAGE_POOL
- if (!page_pool_is_last_ref(netmem))
+ if (!page_pool_unref_and_test(netmem))
return;
page_pool_put_unrefed_netmem(pool, netmem, dma_sync_size, allow_direct);
@@ -418,7 +431,21 @@ static inline dma_addr_t page_pool_get_dma_addr_netmem(netmem_ref netmem)
*/
static inline dma_addr_t page_pool_get_dma_addr(const struct page *page)
{
- return page_pool_get_dma_addr_netmem(page_to_netmem((struct page *)page));
+ dma_addr_t ret = page->dma_addr;
+
+ if (PAGE_POOL_32BIT_ARCH_WITH_64BIT_DMA)
+ ret <<= PAGE_SHIFT;
+
+ return ret;
+}
+
+static inline void __page_pool_dma_sync_for_cpu(const struct page_pool *pool,
+ const dma_addr_t dma_addr,
+ u32 offset, u32 dma_sync_size)
+{
+ dma_sync_single_range_for_cpu(pool->p.dev, dma_addr,
+ offset + pool->p.offset, dma_sync_size,
+ page_pool_get_dma_dir(pool));
}
/**
@@ -437,10 +464,21 @@ static inline void page_pool_dma_sync_for_cpu(const struct page_pool *pool,
const struct page *page,
u32 offset, u32 dma_sync_size)
{
- dma_sync_single_range_for_cpu(pool->p.dev,
- page_pool_get_dma_addr(page),
- offset + pool->p.offset, dma_sync_size,
- page_pool_get_dma_dir(pool));
+ __page_pool_dma_sync_for_cpu(pool, page_pool_get_dma_addr(page), offset,
+ dma_sync_size);
+}
+
+static inline void
+page_pool_dma_sync_netmem_for_cpu(const struct page_pool *pool,
+ const netmem_ref netmem, u32 offset,
+ u32 dma_sync_size)
+{
+ if (!pool->dma_sync_for_cpu)
+ return;
+
+ __page_pool_dma_sync_for_cpu(pool,
+ page_pool_get_dma_addr_netmem(netmem),
+ offset, dma_sync_size);
}
static inline bool page_pool_put(struct page_pool *pool)
diff --git a/include/net/page_pool/types.h b/include/net/page_pool/types.h
index c022c410abe3..ed4cd114180a 100644
--- a/include/net/page_pool/types.h
+++ b/include/net/page_pool/types.h
@@ -164,7 +164,8 @@ struct page_pool {
bool has_init_callback:1; /* slow::init_callback is set */
bool dma_map:1; /* Perform DMA mapping */
- bool dma_sync:1; /* Perform DMA sync */
+ bool dma_sync:1; /* Perform DMA sync for device */
+ bool dma_sync_for_cpu:1; /* Perform DMA sync for cpu */
#ifdef CONFIG_PAGE_POOL_STATS
bool system:1; /* This is a global percpu pool */
#endif
@@ -242,7 +243,7 @@ struct page_pool {
};
struct page *page_pool_alloc_pages(struct page_pool *pool, gfp_t gfp);
-netmem_ref page_pool_alloc_netmem(struct page_pool *pool, gfp_t gfp);
+netmem_ref page_pool_alloc_netmems(struct page_pool *pool, gfp_t gfp);
struct page *page_pool_alloc_frag(struct page_pool *pool, unsigned int *offset,
unsigned int size, gfp_t gfp);
netmem_ref page_pool_alloc_frag_netmem(struct page_pool *pool,
@@ -259,8 +260,7 @@ void page_pool_disable_direct_recycling(struct page_pool *pool);
void page_pool_destroy(struct page_pool *pool);
void page_pool_use_xdp_mem(struct page_pool *pool, void (*disconnect)(void *),
const struct xdp_mem_info *mem);
-void page_pool_put_page_bulk(struct page_pool *pool, void **data,
- int count);
+void page_pool_put_netmem_bulk(netmem_ref *data, u32 count);
#else
static inline void page_pool_destroy(struct page_pool *pool)
{
@@ -272,8 +272,7 @@ static inline void page_pool_use_xdp_mem(struct page_pool *pool,
{
}
-static inline void page_pool_put_page_bulk(struct page_pool *pool, void **data,
- int count)
+static inline void page_pool_put_netmem_bulk(netmem_ref *data, u32 count)
{
}
#endif
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index cf199af85c52..22c5ab4269d7 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -319,7 +319,7 @@ tcf_exts_hw_stats_update(const struct tcf_exts *exts,
* tcf_exts_has_actions - check if at least one action is present
* @exts: tc filter extensions handle
*
- * Returns true if at least one action is present.
+ * Returns: true if at least one action is present.
*/
static inline bool tcf_exts_has_actions(struct tcf_exts *exts)
{
@@ -501,7 +501,7 @@ int __tcf_em_tree_match(struct sk_buff *, struct tcf_ematch_tree *,
* through all ematches respecting their logic relations returning
* as soon as the result is obvious.
*
- * Returns 1 if the ematch tree as-one matches, no ematches are configured
+ * Returns: 1 if the ematch tree as-one matches, no ematches are configured
* or ematch is not enabled in the kernel, otherwise 0 is returned.
*/
static inline int tcf_em_tree_match(struct sk_buff *skb,
diff --git a/include/net/route.h b/include/net/route.h
index 84cb1e04f5cd..f86775be3e29 100644
--- a/include/net/route.h
+++ b/include/net/route.h
@@ -28,6 +28,7 @@
#include <net/arp.h>
#include <net/ndisc.h>
#include <net/inet_dscp.h>
+#include <net/sock.h>
#include <linux/in_route.h>
#include <linux/rtnetlink.h>
#include <linux/rcupdate.h>
@@ -129,6 +130,33 @@ struct in_device;
int ip_rt_init(void);
void rt_cache_flush(struct net *net);
void rt_flush_dev(struct net_device *dev);
+
+static inline void inet_sk_init_flowi4(const struct inet_sock *inet,
+ struct flowi4 *fl4)
+{
+ const struct ip_options_rcu *ip4_opt;
+ const struct sock *sk;
+ __be32 daddr;
+
+ rcu_read_lock();
+ ip4_opt = rcu_dereference(inet->inet_opt);
+
+ /* Source routing option overrides the socket destination address */
+ if (ip4_opt && ip4_opt->opt.srr)
+ daddr = ip4_opt->opt.faddr;
+ else
+ daddr = inet->inet_daddr;
+ rcu_read_unlock();
+
+ sk = &inet->sk;
+ flowi4_init_output(fl4, sk->sk_bound_dev_if, READ_ONCE(sk->sk_mark),
+ ip_sock_rt_tos(sk), ip_sock_rt_scope(sk),
+ sk->sk_protocol, inet_sk_flowi_flags(sk), daddr,
+ inet->inet_saddr, inet->inet_dport,
+ inet->inet_sport, sk->sk_uid);
+ security_sk_classify_flow(sk, flowi4_to_flowi_common(fl4));
+}
+
struct rtable *ip_route_output_key_hash(struct net *net, struct flowi4 *flp,
const struct sk_buff *skb);
struct rtable *ip_route_output_key_hash_rcu(struct net *net, struct flowi4 *flp,
@@ -185,20 +213,6 @@ static inline struct rtable *ip_route_output_ports(struct net *net, struct flowi
return ip_route_output_flow(net, fl4, sk);
}
-static inline struct rtable *ip_route_output_gre(struct net *net, struct flowi4 *fl4,
- __be32 daddr, __be32 saddr,
- __be32 gre_key, __u8 tos, int oif)
-{
- memset(fl4, 0, sizeof(*fl4));
- fl4->flowi4_oif = oif;
- fl4->daddr = daddr;
- fl4->saddr = saddr;
- fl4->flowi4_tos = tos;
- fl4->flowi4_proto = IPPROTO_GRE;
- fl4->fl4_gre_key = gre_key;
- return ip_route_output_key(net, fl4);
-}
-
enum skb_drop_reason
ip_mc_validate_source(struct sk_buff *skb, __be32 daddr, __be32 saddr,
dscp_t dscp, struct net_device *dev,
diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h
index 5d74fa7e694c..8074322dd636 100644
--- a/include/net/sch_generic.h
+++ b/include/net/sch_generic.h
@@ -1245,6 +1245,14 @@ static inline int qdisc_drop(struct sk_buff *skb, struct Qdisc *sch,
return NET_XMIT_DROP;
}
+static inline int qdisc_drop_reason(struct sk_buff *skb, struct Qdisc *sch,
+ struct sk_buff **to_free,
+ enum skb_drop_reason reason)
+{
+ tcf_set_drop_reason(skb, reason);
+ return qdisc_drop(skb, sch, to_free);
+}
+
static inline int qdisc_drop_all(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
diff --git a/include/net/sock.h b/include/net/sock.h
index 7464e9f9f47c..ccf86c8a7a8a 100644
--- a/include/net/sock.h
+++ b/include/net/sock.h
@@ -953,6 +953,7 @@ enum sock_flags {
SOCK_XDP, /* XDP is attached */
SOCK_TSTAMP_NEW, /* Indicates 64 bit timestamps always */
SOCK_RCVMARK, /* Receive SO_MARK ancillary data with packet */
+ SOCK_RCVPRIORITY, /* Receive SO_PRIORITY ancillary data with packet */
};
#define SK_FLAGS_TIMESTAMP ((1UL << SOCK_TIMESTAMP) | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE))
@@ -1527,7 +1528,7 @@ static inline bool sk_wmem_schedule(struct sock *sk, int size)
}
static inline bool
-sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size)
+__sk_rmem_schedule(struct sock *sk, int size, bool pfmemalloc)
{
int delta;
@@ -1535,7 +1536,13 @@ sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size)
return true;
delta = size - sk->sk_forward_alloc;
return delta <= 0 || __sk_mem_schedule(sk, delta, SK_MEM_RECV) ||
- skb_pfmemalloc(skb);
+ pfmemalloc;
+}
+
+static inline bool
+sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size)
+{
+ return __sk_rmem_schedule(sk, size, skb_pfmemalloc(skb));
}
static inline int sk_unused_reserved_mem(const struct sock *sk)
@@ -1814,13 +1821,15 @@ struct sockcm_cookie {
u32 mark;
u32 tsflags;
u32 ts_opt_id;
+ u32 priority;
};
static inline void sockcm_init(struct sockcm_cookie *sockc,
const struct sock *sk)
{
*sockc = (struct sockcm_cookie) {
- .tsflags = READ_ONCE(sk->sk_tsflags)
+ .tsflags = READ_ONCE(sk->sk_tsflags),
+ .priority = READ_ONCE(sk->sk_priority),
};
}
@@ -2658,7 +2667,8 @@ static inline void sock_recv_cmsgs(struct msghdr *msg, struct sock *sk,
{
#define FLAGS_RECV_CMSGS ((1UL << SOCK_RXQ_OVFL) | \
(1UL << SOCK_RCVTSTAMP) | \
- (1UL << SOCK_RCVMARK))
+ (1UL << SOCK_RCVMARK) |\
+ (1UL << SOCK_RCVPRIORITY))
#define TSFLAGS_ANY (SOF_TIMESTAMPING_SOFTWARE | \
SOF_TIMESTAMPING_RAW_HARDWARE)
diff --git a/include/net/tcp.h b/include/net/tcp.h
index e9b37b76e894..5b2b04835688 100644
--- a/include/net/tcp.h
+++ b/include/net/tcp.h
@@ -1817,7 +1817,7 @@ int tcp_sigpool_hash_skb_data(struct tcp_sigpool *hp,
* @id: tcp_sigpool that was previously allocated by tcp_sigpool_alloc_ahash()
* @c: returned tcp_sigpool for usage (uninitialized on failure)
*
- * Returns 0 on success, error otherwise.
+ * Returns: 0 on success, error otherwise.
*/
int tcp_sigpool_start(unsigned int id, struct tcp_sigpool *c);
/**
diff --git a/include/net/tls.h b/include/net/tls.h
index 61fef2880114..857340338b69 100644
--- a/include/net/tls.h
+++ b/include/net/tls.h
@@ -59,6 +59,8 @@ struct tls_rec;
#define TLS_CRYPTO_INFO_READY(info) ((info)->cipher_type)
+#define TLS_HANDSHAKE_KEYUPDATE 24 /* rfc8446 B.3: Key update */
+
#define TLS_AAD_SPACE_SIZE 13
#define TLS_MAX_IV_SIZE 16
@@ -130,6 +132,7 @@ struct tls_sw_context_rx {
u8 async_capable:1;
u8 zc_capable:1;
u8 reader_contended:1;
+ bool key_update_pending;
struct tls_strparser strp;
diff --git a/include/net/vxlan.h b/include/net/vxlan.h
index 33ba6fc151cf..2dd23ee2bacd 100644
--- a/include/net/vxlan.h
+++ b/include/net/vxlan.h
@@ -227,6 +227,7 @@ struct vxlan_config {
unsigned int addrmax;
bool no_share;
enum ifla_vxlan_df df;
+ struct vxlanhdr reserved_bits;
};
enum {
diff --git a/include/net/xdp.h b/include/net/xdp.h
index e6770dd40c91..6da0e746cf75 100644
--- a/include/net/xdp.h
+++ b/include/net/xdp.h
@@ -11,6 +11,8 @@
#include <linux/netdevice.h>
#include <linux/skbuff.h> /* skb_shared_info */
+#include <net/page_pool/types.h>
+
/**
* DOC: XDP RX-queue information
*
@@ -88,7 +90,7 @@ struct xdp_buff {
u32 flags; /* supported values defined in xdp_buff_flags */
};
-static __always_inline bool xdp_buff_has_frags(struct xdp_buff *xdp)
+static __always_inline bool xdp_buff_has_frags(const struct xdp_buff *xdp)
{
return !!(xdp->flags & XDP_FLAGS_HAS_FRAGS);
}
@@ -103,7 +105,8 @@ static __always_inline void xdp_buff_clear_frags_flag(struct xdp_buff *xdp)
xdp->flags &= ~XDP_FLAGS_HAS_FRAGS;
}
-static __always_inline bool xdp_buff_is_frag_pfmemalloc(struct xdp_buff *xdp)
+static __always_inline bool
+xdp_buff_is_frag_pfmemalloc(const struct xdp_buff *xdp)
{
return !!(xdp->flags & XDP_FLAGS_FRAGS_PF_MEMALLOC);
}
@@ -144,15 +147,16 @@ xdp_prepare_buff(struct xdp_buff *xdp, unsigned char *hard_start,
SKB_DATA_ALIGN(sizeof(struct skb_shared_info)))
static inline struct skb_shared_info *
-xdp_get_shared_info_from_buff(struct xdp_buff *xdp)
+xdp_get_shared_info_from_buff(const struct xdp_buff *xdp)
{
return (struct skb_shared_info *)xdp_data_hard_end(xdp);
}
-static __always_inline unsigned int xdp_get_buff_len(struct xdp_buff *xdp)
+static __always_inline unsigned int
+xdp_get_buff_len(const struct xdp_buff *xdp)
{
unsigned int len = xdp->data_end - xdp->data;
- struct skb_shared_info *sinfo;
+ const struct skb_shared_info *sinfo;
if (likely(!xdp_buff_has_frags(xdp)))
goto out;
@@ -163,26 +167,114 @@ out:
return len;
}
+void xdp_return_frag(netmem_ref netmem, const struct xdp_buff *xdp);
+
+/**
+ * __xdp_buff_add_frag - attach frag to &xdp_buff
+ * @xdp: XDP buffer to attach the frag to
+ * @netmem: network memory containing the frag
+ * @offset: offset at which the frag starts
+ * @size: size of the frag
+ * @truesize: total memory size occupied by the frag
+ * @try_coalesce: whether to try coalescing the frags (not valid for XSk)
+ *
+ * Attach frag to the XDP buffer. If it currently has no frags attached,
+ * initialize the related fields, otherwise check that the frag number
+ * didn't reach the limit of ``MAX_SKB_FRAGS``. If possible, try coalescing
+ * the frag with the previous one.
+ * The function doesn't check/update the pfmemalloc bit. Please use the
+ * non-underscored wrapper in drivers.
+ *
+ * Return: true on success, false if there's no space for the frag in
+ * the shared info struct.
+ */
+static inline bool __xdp_buff_add_frag(struct xdp_buff *xdp, netmem_ref netmem,
+ u32 offset, u32 size, u32 truesize,
+ bool try_coalesce)
+{
+ struct skb_shared_info *sinfo = xdp_get_shared_info_from_buff(xdp);
+ skb_frag_t *prev;
+ u32 nr_frags;
+
+ if (!xdp_buff_has_frags(xdp)) {
+ xdp_buff_set_frags_flag(xdp);
+
+ nr_frags = 0;
+ sinfo->xdp_frags_size = 0;
+ sinfo->xdp_frags_truesize = 0;
+
+ goto fill;
+ }
+
+ nr_frags = sinfo->nr_frags;
+ prev = &sinfo->frags[nr_frags - 1];
+
+ if (try_coalesce && netmem == skb_frag_netmem(prev) &&
+ offset == skb_frag_off(prev) + skb_frag_size(prev)) {
+ skb_frag_size_add(prev, size);
+ /* Guaranteed to only decrement the refcount */
+ xdp_return_frag(netmem, xdp);
+ } else if (unlikely(nr_frags == MAX_SKB_FRAGS)) {
+ return false;
+ } else {
+fill:
+ __skb_fill_netmem_desc_noacc(sinfo, nr_frags++, netmem,
+ offset, size);
+ }
+
+ sinfo->nr_frags = nr_frags;
+ sinfo->xdp_frags_size += size;
+ sinfo->xdp_frags_truesize += truesize;
+
+ return true;
+}
+
+/**
+ * xdp_buff_add_frag - attach frag to &xdp_buff
+ * @xdp: XDP buffer to attach the frag to
+ * @netmem: network memory containing the frag
+ * @offset: offset at which the frag starts
+ * @size: size of the frag
+ * @truesize: total memory size occupied by the frag
+ *
+ * Version of __xdp_buff_add_frag() which takes care of the pfmemalloc bit.
+ *
+ * Return: true on success, false if there's no space for the frag in
+ * the shared info struct.
+ */
+static inline bool xdp_buff_add_frag(struct xdp_buff *xdp, netmem_ref netmem,
+ u32 offset, u32 size, u32 truesize)
+{
+ if (!__xdp_buff_add_frag(xdp, netmem, offset, size, truesize, true))
+ return false;
+
+ if (unlikely(netmem_is_pfmemalloc(netmem)))
+ xdp_buff_set_frag_pfmemalloc(xdp);
+
+ return true;
+}
+
struct xdp_frame {
void *data;
- u16 len;
- u16 headroom;
+ u32 len;
+ u32 headroom;
u32 metasize; /* uses lower 8-bits */
/* Lifetime of xdp_rxq_info is limited to NAPI/enqueue time,
- * while mem info is valid on remote CPU.
+ * while mem_type is valid on remote CPU.
*/
- struct xdp_mem_info mem;
+ enum xdp_mem_type mem_type:32;
struct net_device *dev_rx; /* used by cpumap */
u32 frame_sz;
u32 flags; /* supported values defined in xdp_buff_flags */
};
-static __always_inline bool xdp_frame_has_frags(struct xdp_frame *frame)
+static __always_inline bool xdp_frame_has_frags(const struct xdp_frame *frame)
{
return !!(frame->flags & XDP_FLAGS_HAS_FRAGS);
}
-static __always_inline bool xdp_frame_is_frag_pfmemalloc(struct xdp_frame *frame)
+static __always_inline bool
+xdp_frame_is_frag_pfmemalloc(const struct xdp_frame *frame)
{
return !!(frame->flags & XDP_FLAGS_FRAGS_PF_MEMALLOC);
}
@@ -190,18 +282,16 @@ static __always_inline bool xdp_frame_is_frag_pfmemalloc(struct xdp_frame *frame
#define XDP_BULK_QUEUE_SIZE 16
struct xdp_frame_bulk {
int count;
- void *xa;
- void *q[XDP_BULK_QUEUE_SIZE];
+ netmem_ref q[XDP_BULK_QUEUE_SIZE];
};
static __always_inline void xdp_frame_bulk_init(struct xdp_frame_bulk *bq)
{
- /* bq->count will be zero'ed when bq->xa gets updated */
- bq->xa = NULL;
+ bq->count = 0;
}
static inline struct skb_shared_info *
-xdp_get_shared_info_from_frame(struct xdp_frame *frame)
+xdp_get_shared_info_from_frame(const struct xdp_frame *frame)
{
void *data_hard_start = frame->data - frame->headroom - sizeof(*frame);
@@ -227,7 +317,14 @@ xdp_update_skb_shared_info(struct sk_buff *skb, u8 nr_frags,
unsigned int size, unsigned int truesize,
bool pfmemalloc)
{
- skb_shinfo(skb)->nr_frags = nr_frags;
+ struct skb_shared_info *sinfo = skb_shinfo(skb);
+
+ sinfo->nr_frags = nr_frags;
+ /*
+ * ``destructor_arg`` is unionized with ``xdp_frags_{,true}size``,
+ * reset it after that these fields aren't used anymore.
+ */
+ sinfo->destructor_arg = NULL;
skb->len += size;
skb->data_len += size;
@@ -239,6 +336,8 @@ xdp_update_skb_shared_info(struct sk_buff *skb, u8 nr_frags,
void xdp_warn(const char *msg, const char *func, const int line);
#define XDP_WARN(msg) xdp_warn(msg, __func__, __LINE__)
+struct sk_buff *xdp_build_skb_from_buff(const struct xdp_buff *xdp);
+struct sk_buff *xdp_build_skb_from_zc(struct xdp_buff *xdp);
struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp);
struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
struct sk_buff *skb,
@@ -249,7 +348,8 @@ int xdp_alloc_skb_bulk(void **skbs, int n_skb, gfp_t gfp);
struct xdp_frame *xdpf_clone(struct xdp_frame *xdpf);
static inline
-void xdp_convert_frame_to_buff(struct xdp_frame *frame, struct xdp_buff *xdp)
+void xdp_convert_frame_to_buff(const struct xdp_frame *frame,
+ struct xdp_buff *xdp)
{
xdp->data_hard_start = frame->data - frame->headroom - sizeof(*frame);
xdp->data = frame->data;
@@ -260,7 +360,7 @@ void xdp_convert_frame_to_buff(struct xdp_frame *frame, struct xdp_buff *xdp)
}
static inline
-int xdp_update_frame_from_buff(struct xdp_buff *xdp,
+int xdp_update_frame_from_buff(const struct xdp_buff *xdp,
struct xdp_frame *xdp_frame)
{
int metasize, headroom;
@@ -302,24 +402,33 @@ struct xdp_frame *xdp_convert_buff_to_frame(struct xdp_buff *xdp)
if (unlikely(xdp_update_frame_from_buff(xdp, xdp_frame) < 0))
return NULL;
- /* rxq only valid until napi_schedule ends, convert to xdp_mem_info */
- xdp_frame->mem = xdp->rxq->mem;
+ /* rxq only valid until napi_schedule ends, convert to xdp_mem_type */
+ xdp_frame->mem_type = xdp->rxq->mem.type;
return xdp_frame;
}
-void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
- struct xdp_buff *xdp);
+void __xdp_return(netmem_ref netmem, enum xdp_mem_type mem_type,
+ bool napi_direct, struct xdp_buff *xdp);
void xdp_return_frame(struct xdp_frame *xdpf);
void xdp_return_frame_rx_napi(struct xdp_frame *xdpf);
void xdp_return_buff(struct xdp_buff *xdp);
-void xdp_flush_frame_bulk(struct xdp_frame_bulk *bq);
void xdp_return_frame_bulk(struct xdp_frame *xdpf,
struct xdp_frame_bulk *bq);
-static __always_inline unsigned int xdp_get_frame_len(struct xdp_frame *xdpf)
+static inline void xdp_flush_frame_bulk(struct xdp_frame_bulk *bq)
+{
+ if (unlikely(!bq->count))
+ return;
+
+ page_pool_put_netmem_bulk(bq->q, bq->count);
+ bq->count = 0;
+}
+
+static __always_inline unsigned int
+xdp_get_frame_len(const struct xdp_frame *xdpf)
{
- struct skb_shared_info *sinfo;
+ const struct skb_shared_info *sinfo;
unsigned int len = xdpf->len;
if (likely(!xdp_frame_has_frags(xdpf)))
@@ -351,6 +460,38 @@ void xdp_rxq_info_unreg_mem_model(struct xdp_rxq_info *xdp_rxq);
int xdp_reg_mem_model(struct xdp_mem_info *mem,
enum xdp_mem_type type, void *allocator);
void xdp_unreg_mem_model(struct xdp_mem_info *mem);
+int xdp_reg_page_pool(struct page_pool *pool);
+void xdp_unreg_page_pool(const struct page_pool *pool);
+void xdp_rxq_info_attach_page_pool(struct xdp_rxq_info *xdp_rxq,
+ const struct page_pool *pool);
+
+/**
+ * xdp_rxq_info_attach_mem_model - attach registered mem info to RxQ info
+ * @xdp_rxq: XDP RxQ info to attach the memory info to
+ * @mem: already registered memory info
+ *
+ * If the driver registers its memory providers manually, it must use this
+ * function instead of xdp_rxq_info_reg_mem_model().
+ */
+static inline void
+xdp_rxq_info_attach_mem_model(struct xdp_rxq_info *xdp_rxq,
+ const struct xdp_mem_info *mem)
+{
+ xdp_rxq->mem = *mem;
+}
+
+/**
+ * xdp_rxq_info_detach_mem_model - detach registered mem info from RxQ info
+ * @xdp_rxq: XDP RxQ info to detach the memory info from
+ *
+ * If the driver registers its memory providers manually and then attaches it
+ * via xdp_rxq_info_attach_mem_model(), it must call this function before
+ * xdp_rxq_info_unreg().
+ */
+static inline void xdp_rxq_info_detach_mem_model(struct xdp_rxq_info *xdp_rxq)
+{
+ xdp_rxq->mem = (struct xdp_mem_info){ };
+}
/* Drivers not supporting XDP metadata can use this helper, which
* rejects any room expansion for metadata as a result.
diff --git a/include/net/xdp_sock_drv.h b/include/net/xdp_sock_drv.h
index 40085afd9160..86620c818965 100644
--- a/include/net/xdp_sock_drv.h
+++ b/include/net/xdp_sock_drv.h
@@ -101,7 +101,7 @@ static inline struct xdp_buff *xsk_buff_alloc(struct xsk_buff_pool *pool)
return xp_alloc(pool);
}
-static inline bool xsk_is_eop_desc(struct xdp_desc *desc)
+static inline bool xsk_is_eop_desc(const struct xdp_desc *desc)
{
return !xp_mb_desc(desc);
}
@@ -136,14 +136,24 @@ out:
xp_free(xskb);
}
-static inline void xsk_buff_add_frag(struct xdp_buff *xdp)
+static inline bool xsk_buff_add_frag(struct xdp_buff *head,
+ struct xdp_buff *xdp)
{
- struct xdp_buff_xsk *frag = container_of(xdp, struct xdp_buff_xsk, xdp);
+ const void *data = xdp->data;
+ struct xdp_buff_xsk *frag;
+
+ if (!__xdp_buff_add_frag(head, virt_to_netmem(data),
+ offset_in_page(data), xdp->data_end - data,
+ xdp->frame_sz, false))
+ return false;
+ frag = container_of(xdp, struct xdp_buff_xsk, xdp);
list_add_tail(&frag->list_node, &frag->pool->xskb_list);
+
+ return true;
}
-static inline struct xdp_buff *xsk_buff_get_frag(struct xdp_buff *first)
+static inline struct xdp_buff *xsk_buff_get_frag(const struct xdp_buff *first)
{
struct xdp_buff_xsk *xskb = container_of(first, struct xdp_buff_xsk, xdp);
struct xdp_buff *ret = NULL;
@@ -200,7 +210,8 @@ static inline void *xsk_buff_raw_get_data(struct xsk_buff_pool *pool, u64 addr)
XDP_TXMD_FLAGS_CHECKSUM | \
0)
-static inline bool xsk_buff_valid_tx_metadata(struct xsk_tx_metadata *meta)
+static inline bool
+xsk_buff_valid_tx_metadata(const struct xsk_tx_metadata *meta)
{
return !(meta->flags & ~XDP_TXMD_FLAGS_VALID);
}
@@ -337,7 +348,7 @@ static inline struct xdp_buff *xsk_buff_alloc(struct xsk_buff_pool *pool)
return NULL;
}
-static inline bool xsk_is_eop_desc(struct xdp_desc *desc)
+static inline bool xsk_is_eop_desc(const struct xdp_desc *desc)
{
return false;
}
@@ -356,11 +367,13 @@ static inline void xsk_buff_free(struct xdp_buff *xdp)
{
}
-static inline void xsk_buff_add_frag(struct xdp_buff *xdp)
+static inline bool xsk_buff_add_frag(struct xdp_buff *head,
+ struct xdp_buff *xdp)
{
+ return false;
}
-static inline struct xdp_buff *xsk_buff_get_frag(struct xdp_buff *first)
+static inline struct xdp_buff *xsk_buff_get_frag(const struct xdp_buff *first)
{
return NULL;
}
diff --git a/include/net/xsk_buff_pool.h b/include/net/xsk_buff_pool.h
index bb03cee716b3..50779406bc2d 100644
--- a/include/net/xsk_buff_pool.h
+++ b/include/net/xsk_buff_pool.h
@@ -29,7 +29,7 @@ struct xdp_buff_xsk {
dma_addr_t frame_dma;
struct xsk_buff_pool *pool;
struct list_head list_node;
-};
+} __aligned_largest;
#define XSK_CHECK_PRIV_TYPE(t) BUILD_BUG_ON(sizeof(t) > offsetofend(struct xdp_buff_xsk, cb))
#define XSK_TX_COMPL_FITS(t) BUILD_BUG_ON(sizeof(struct xsk_tx_metadata_compl) > sizeof(t))
@@ -183,7 +183,7 @@ static inline bool xp_desc_crosses_non_contig_pg(struct xsk_buff_pool *pool,
!(pool->dma_pages[addr >> PAGE_SHIFT] & XSK_NEXT_PG_CONTIG_MASK);
}
-static inline bool xp_mb_desc(struct xdp_desc *desc)
+static inline bool xp_mb_desc(const struct xdp_desc *desc)
{
return desc->options & XDP_PKT_CONTD;
}
diff --git a/include/soc/arc/aux.h b/include/soc/arc/arc_aux.h
index 9c2eff6140b6..9c2eff6140b6 100644
--- a/include/soc/arc/aux.h
+++ b/include/soc/arc/arc_aux.h
diff --git a/include/soc/arc/mcip.h b/include/soc/arc/mcip.h
index d1a93c73f006..a78dacd149f1 100644
--- a/include/soc/arc/mcip.h
+++ b/include/soc/arc/mcip.h
@@ -8,7 +8,7 @@
#ifndef __SOC_ARC_MCIP_H
#define __SOC_ARC_MCIP_H
-#include <soc/arc/aux.h>
+#include <soc/arc/arc_aux.h>
#define ARC_REG_MCIP_BCR 0x0d0
#define ARC_REG_MCIP_IDU_BCR 0x0D5
diff --git a/include/soc/arc/timers.h b/include/soc/arc/timers.h
index ae99d3e855f1..51a74166296c 100644
--- a/include/soc/arc/timers.h
+++ b/include/soc/arc/timers.h
@@ -6,7 +6,7 @@
#ifndef __SOC_ARC_TIMERS_H
#define __SOC_ARC_TIMERS_H
-#include <soc/arc/aux.h>
+#include <soc/arc/arc_aux.h>
/* Timer related Aux registers */
#define ARC_REG_TIMER0_LIMIT 0x23 /* timer 0 limit */
diff --git a/include/soc/mscc/ocelot.h b/include/soc/mscc/ocelot.h
index 462c653e1017..2db9ae0575b6 100644
--- a/include/soc/mscc/ocelot.h
+++ b/include/soc/mscc/ocelot.h
@@ -778,7 +778,6 @@ struct ocelot_port {
phy_interface_t phy_mode;
- unsigned int ptp_skbs_in_flight;
struct sk_buff_head tx_skbs;
unsigned int trap_proto;
@@ -786,7 +785,6 @@ struct ocelot_port {
u16 mrp_ring_id;
u8 ptp_cmd;
- u8 ts_id;
u8 index;
diff --git a/include/sound/cs35l56.h b/include/sound/cs35l56.h
index 94e8185c4795..3dc7a1551ac3 100644
--- a/include/sound/cs35l56.h
+++ b/include/sound/cs35l56.h
@@ -271,12 +271,6 @@ struct cs35l56_base {
struct gpio_desc *reset_gpio;
};
-/* Temporary to avoid a build break with the HDA driver */
-static inline int cs35l56_force_sync_asp1_registers_from_cache(struct cs35l56_base *cs35l56_base)
-{
- return 0;
-}
-
static inline bool cs35l56_is_otp_register(unsigned int reg)
{
return (reg >> 16) == 3;
diff --git a/include/sound/tas2781.h b/include/sound/tas2781.h
index 8cd6da0480b7..72d2060904f6 100644
--- a/include/sound/tas2781.h
+++ b/include/sound/tas2781.h
@@ -156,6 +156,7 @@ struct tasdevice_priv {
struct tasdevice_rca rcabin;
struct calidata cali_data;
struct tasdevice_fw *fmw;
+ struct gpio_desc *speaker_id;
struct gpio_desc *reset;
struct mutex codec_lock;
struct regmap *regmap;
diff --git a/include/trace/events/damon.h b/include/trace/events/damon.h
index 23200aabccac..da4bd9fd1162 100644
--- a/include/trace/events/damon.h
+++ b/include/trace/events/damon.h
@@ -15,7 +15,7 @@ TRACE_EVENT_CONDITION(damos_before_apply,
unsigned int target_idx, struct damon_region *r,
unsigned int nr_regions, bool do_trace),
- TP_ARGS(context_idx, target_idx, scheme_idx, r, nr_regions, do_trace),
+ TP_ARGS(context_idx, scheme_idx, target_idx, r, nr_regions, do_trace),
TP_CONDITION(do_trace),
diff --git a/include/trace/events/fib6.h b/include/trace/events/fib6.h
index 5d7ee2610728..8d22b2e98d48 100644
--- a/include/trace/events/fib6.h
+++ b/include/trace/events/fib6.h
@@ -22,6 +22,7 @@ TRACE_EVENT(fib6_table_lookup,
__field( int, err )
__field( int, oif )
__field( int, iif )
+ __field( u32, flowlabel )
__field( __u8, tos )
__field( __u8, scope )
__field( __u8, flags )
@@ -42,6 +43,7 @@ TRACE_EVENT(fib6_table_lookup,
__entry->err = ip6_rt_type_to_error(res->fib6_type);
__entry->oif = flp->flowi6_oif;
__entry->iif = flp->flowi6_iif;
+ __entry->flowlabel = ntohl(flowi6_get_flowlabel(flp));
__entry->tos = ip6_tclass(flp->flowlabel);
__entry->scope = flp->flowi6_scope;
__entry->flags = flp->flowi6_flags;
@@ -76,11 +78,11 @@ TRACE_EVENT(fib6_table_lookup,
}
),
- TP_printk("table %3u oif %d iif %d proto %u %pI6c/%u -> %pI6c/%u tos %d scope %d flags %x ==> dev %s gw %pI6c err %d",
+ TP_printk("table %3u oif %d iif %d proto %u %pI6c/%u -> %pI6c/%u flowlabel %#x tos %d scope %d flags %x ==> dev %s gw %pI6c err %d",
__entry->tb_id, __entry->oif, __entry->iif, __entry->proto,
__entry->src, __entry->sport, __entry->dst, __entry->dport,
- __entry->tos, __entry->scope, __entry->flags,
- __entry->name, __entry->gw, __entry->err)
+ __entry->flowlabel, __entry->tos, __entry->scope,
+ __entry->flags, __entry->name, __entry->gw, __entry->err)
);
#endif /* _TRACE_FIB6_H */
diff --git a/include/trace/events/rxrpc.h b/include/trace/events/rxrpc.h
index d03e0bd8c028..2f119d18a061 100644
--- a/include/trace/events/rxrpc.h
+++ b/include/trace/events/rxrpc.h
@@ -117,8 +117,10 @@
#define rxrpc_call_poke_traces \
EM(rxrpc_call_poke_abort, "Abort") \
EM(rxrpc_call_poke_complete, "Compl") \
+ EM(rxrpc_call_poke_conn_abort, "Conn-abort") \
EM(rxrpc_call_poke_error, "Error") \
EM(rxrpc_call_poke_idle, "Idle") \
+ EM(rxrpc_call_poke_rx_packet, "Rx-packet") \
EM(rxrpc_call_poke_set_timeout, "Set-timo") \
EM(rxrpc_call_poke_start, "Start") \
EM(rxrpc_call_poke_timer, "Timer") \
@@ -127,9 +129,9 @@
#define rxrpc_skb_traces \
EM(rxrpc_skb_eaten_by_unshare, "ETN unshare ") \
EM(rxrpc_skb_eaten_by_unshare_nomem, "ETN unshar-nm") \
+ EM(rxrpc_skb_get_call_rx, "GET call-rx ") \
EM(rxrpc_skb_get_conn_secured, "GET conn-secd") \
EM(rxrpc_skb_get_conn_work, "GET conn-work") \
- EM(rxrpc_skb_get_last_nack, "GET last-nack") \
EM(rxrpc_skb_get_local_work, "GET locl-work") \
EM(rxrpc_skb_get_reject_work, "GET rej-work ") \
EM(rxrpc_skb_get_to_recvmsg, "GET to-recv ") \
@@ -138,12 +140,12 @@
EM(rxrpc_skb_new_error_report, "NEW error-rpt") \
EM(rxrpc_skb_new_jumbo_subpacket, "NEW jumbo-sub") \
EM(rxrpc_skb_new_unshared, "NEW unshared ") \
+ EM(rxrpc_skb_put_call_rx, "PUT call-rx ") \
EM(rxrpc_skb_put_conn_secured, "PUT conn-secd") \
EM(rxrpc_skb_put_conn_work, "PUT conn-work") \
EM(rxrpc_skb_put_error_report, "PUT error-rep") \
EM(rxrpc_skb_put_input, "PUT input ") \
EM(rxrpc_skb_put_jumbo_subpacket, "PUT jumbo-sub") \
- EM(rxrpc_skb_put_last_nack, "PUT last-nack") \
EM(rxrpc_skb_put_purge, "PUT purge ") \
EM(rxrpc_skb_put_rotate, "PUT rotate ") \
EM(rxrpc_skb_put_unknown, "PUT unknown ") \
@@ -282,6 +284,7 @@
EM(rxrpc_call_see_activate_client, "SEE act-clnt") \
EM(rxrpc_call_see_connect_failed, "SEE con-fail") \
EM(rxrpc_call_see_connected, "SEE connect ") \
+ EM(rxrpc_call_see_conn_abort, "SEE conn-abt") \
EM(rxrpc_call_see_disconnected, "SEE disconn ") \
EM(rxrpc_call_see_distribute_error, "SEE dist-err") \
EM(rxrpc_call_see_input, "SEE input ") \
@@ -292,7 +295,6 @@
#define rxrpc_txqueue_traces \
EM(rxrpc_txqueue_await_reply, "AWR") \
- EM(rxrpc_txqueue_dequeue, "DEQ") \
EM(rxrpc_txqueue_end, "END") \
EM(rxrpc_txqueue_queue, "QUE") \
EM(rxrpc_txqueue_queue_last, "QLS") \
@@ -300,6 +302,13 @@
EM(rxrpc_txqueue_rotate_last, "RLS") \
E_(rxrpc_txqueue_wait, "WAI")
+#define rxrpc_txdata_traces \
+ EM(rxrpc_txdata_inject_loss, " *INJ-LOSS*") \
+ EM(rxrpc_txdata_new_data, " ") \
+ EM(rxrpc_txdata_retransmit, " *RETRANS*") \
+ EM(rxrpc_txdata_tlp_new_data, " *TLP-NEW*") \
+ E_(rxrpc_txdata_tlp_retransmit, " *TLP-RETRANS*")
+
#define rxrpc_receive_traces \
EM(rxrpc_receive_end, "END") \
EM(rxrpc_receive_front, "FRN") \
@@ -335,11 +344,10 @@
E_(rxrpc_rtt_tx_ping, "PING")
#define rxrpc_rtt_rx_traces \
- EM(rxrpc_rtt_rx_other_ack, "OACK") \
+ EM(rxrpc_rtt_rx_data_ack, "DACK") \
EM(rxrpc_rtt_rx_obsolete, "OBSL") \
EM(rxrpc_rtt_rx_lost, "LOST") \
- EM(rxrpc_rtt_rx_ping_response, "PONG") \
- E_(rxrpc_rtt_rx_requested_ack, "RACK")
+ E_(rxrpc_rtt_rx_ping_response, "PONG")
#define rxrpc_timer_traces \
EM(rxrpc_timer_trace_delayed_ack, "DelayAck ") \
@@ -347,11 +355,12 @@
EM(rxrpc_timer_trace_hard, "HardLimit") \
EM(rxrpc_timer_trace_idle, "IdleLimit") \
EM(rxrpc_timer_trace_keepalive, "KeepAlive") \
- EM(rxrpc_timer_trace_lost_ack, "LostAck ") \
EM(rxrpc_timer_trace_ping, "DelayPing") \
- EM(rxrpc_timer_trace_resend, "Resend ") \
- EM(rxrpc_timer_trace_resend_reset, "ResendRst") \
- E_(rxrpc_timer_trace_resend_tx, "ResendTx ")
+ EM(rxrpc_timer_trace_rack_off, "RACK-OFF ") \
+ EM(rxrpc_timer_trace_rack_zwp, "RACK-ZWP ") \
+ EM(rxrpc_timer_trace_rack_reo, "RACK-Reo ") \
+ EM(rxrpc_timer_trace_rack_tlp_pto, "TLP-PTO ") \
+ E_(rxrpc_timer_trace_rack_rto, "RTO ")
#define rxrpc_propose_ack_traces \
EM(rxrpc_propose_ack_client_tx_end, "ClTxEnd") \
@@ -362,22 +371,24 @@
EM(rxrpc_propose_ack_ping_for_lost_ack, "LostAck") \
EM(rxrpc_propose_ack_ping_for_lost_reply, "LostRpl") \
EM(rxrpc_propose_ack_ping_for_0_retrans, "0-Retrn") \
+ EM(rxrpc_propose_ack_ping_for_mtu_probe, "MTUProb") \
EM(rxrpc_propose_ack_ping_for_old_rtt, "OldRtt ") \
EM(rxrpc_propose_ack_ping_for_params, "Params ") \
EM(rxrpc_propose_ack_ping_for_rtt, "Rtt ") \
EM(rxrpc_propose_ack_processing_op, "ProcOp ") \
EM(rxrpc_propose_ack_respond_to_ack, "Rsp2Ack") \
EM(rxrpc_propose_ack_respond_to_ping, "Rsp2Png") \
+ EM(rxrpc_propose_ack_retransmit, "Retrans") \
EM(rxrpc_propose_ack_retry_tx, "RetryTx") \
EM(rxrpc_propose_ack_rotate_rx, "RxAck ") \
EM(rxrpc_propose_ack_rx_idle, "RxIdle ") \
E_(rxrpc_propose_ack_terminal_ack, "ClTerm ")
-#define rxrpc_congest_modes \
- EM(RXRPC_CALL_CONGEST_AVOIDANCE, "CongAvoid") \
- EM(RXRPC_CALL_FAST_RETRANSMIT, "FastReTx ") \
- EM(RXRPC_CALL_PACKET_LOSS, "PktLoss ") \
- E_(RXRPC_CALL_SLOW_START, "SlowStart")
+#define rxrpc_ca_states \
+ EM(RXRPC_CA_CONGEST_AVOIDANCE, "CongAvoid") \
+ EM(RXRPC_CA_FAST_RETRANSMIT, "FastReTx ") \
+ EM(RXRPC_CA_PACKET_LOSS, "PktLoss ") \
+ E_(RXRPC_CA_SLOW_START, "SlowStart")
#define rxrpc_congest_changes \
EM(rxrpc_cong_begin_retransmission, " Retrans") \
@@ -450,7 +461,7 @@
#define rxrpc_req_ack_traces \
EM(rxrpc_reqack_ack_lost, "ACK-LOST ") \
- EM(rxrpc_reqack_already_on, "ALREADY-ON") \
+ EM(rxrpc_reqack_app_stall, "APP-STALL ") \
EM(rxrpc_reqack_more_rtt, "MORE-RTT ") \
EM(rxrpc_reqack_no_srv_last, "NO-SRVLAST") \
EM(rxrpc_reqack_old_rtt, "OLD-RTT ") \
@@ -460,21 +471,60 @@
/* ---- Must update size of stat_why_req_ack[] if more are added! */
#define rxrpc_txbuf_traces \
- EM(rxrpc_txbuf_alloc_ack, "ALLOC ACK ") \
EM(rxrpc_txbuf_alloc_data, "ALLOC DATA ") \
EM(rxrpc_txbuf_free, "FREE ") \
EM(rxrpc_txbuf_get_buffer, "GET BUFFER ") \
EM(rxrpc_txbuf_get_trans, "GET TRANS ") \
EM(rxrpc_txbuf_get_retrans, "GET RETRANS") \
- EM(rxrpc_txbuf_put_ack_tx, "PUT ACK TX ") \
EM(rxrpc_txbuf_put_cleaned, "PUT CLEANED") \
EM(rxrpc_txbuf_put_nomem, "PUT NOMEM ") \
EM(rxrpc_txbuf_put_rotated, "PUT ROTATED") \
EM(rxrpc_txbuf_put_send_aborted, "PUT SEND-X ") \
EM(rxrpc_txbuf_put_trans, "PUT TRANS ") \
+ EM(rxrpc_txbuf_see_lost, "SEE LOST ") \
EM(rxrpc_txbuf_see_out_of_step, "OUT-OF-STEP") \
- EM(rxrpc_txbuf_see_send_more, "SEE SEND+ ") \
- E_(rxrpc_txbuf_see_unacked, "SEE UNACKED")
+ E_(rxrpc_txbuf_see_send_more, "SEE SEND+ ")
+
+#define rxrpc_tq_traces \
+ EM(rxrpc_tq_alloc, "ALLOC") \
+ EM(rxrpc_tq_cleaned, "CLEAN") \
+ EM(rxrpc_tq_decant, "DCNT ") \
+ EM(rxrpc_tq_decant_advance, "DCNT>") \
+ EM(rxrpc_tq_queue, "QUEUE") \
+ EM(rxrpc_tq_queue_dup, "QUE!!") \
+ EM(rxrpc_tq_rotate, "ROT ") \
+ EM(rxrpc_tq_rotate_and_free, "ROT-F") \
+ EM(rxrpc_tq_rotate_and_keep, "ROT-K") \
+ EM(rxrpc_tq_transmit, "XMIT ") \
+ E_(rxrpc_tq_transmit_advance, "XMIT>")
+
+#define rxrpc_pmtud_reduce_traces \
+ EM(rxrpc_pmtud_reduce_ack, "Ack ") \
+ EM(rxrpc_pmtud_reduce_icmp, "Icmp ") \
+ E_(rxrpc_pmtud_reduce_route, "Route")
+
+#define rxrpc_rotate_traces \
+ EM(rxrpc_rotate_trace_hack, "hard-ack") \
+ EM(rxrpc_rotate_trace_sack, "soft-ack") \
+ E_(rxrpc_rotate_trace_snak, "soft-nack")
+
+#define rxrpc_rack_timer_modes \
+ EM(RXRPC_CALL_RACKTIMER_OFF, "---") \
+ EM(RXRPC_CALL_RACKTIMER_RACK_REORDER, "REO") \
+ EM(RXRPC_CALL_RACKTIMER_TLP_PTO, "TLP") \
+ E_(RXRPC_CALL_RACKTIMER_RTO, "RTO")
+
+#define rxrpc_tlp_probe_traces \
+ EM(rxrpc_tlp_probe_trace_busy, "busy") \
+ EM(rxrpc_tlp_probe_trace_transmit_new, "transmit-new") \
+ E_(rxrpc_tlp_probe_trace_retransmit, "retransmit")
+
+#define rxrpc_tlp_ack_traces \
+ EM(rxrpc_tlp_ack_trace_acked, "acked") \
+ EM(rxrpc_tlp_ack_trace_dup_acked, "dup-acked") \
+ EM(rxrpc_tlp_ack_trace_hard_beyond, "hard-beyond") \
+ EM(rxrpc_tlp_ack_trace_incomplete, "incomplete") \
+ E_(rxrpc_tlp_ack_trace_new_data, "new-data")
/*
* Generate enums for tracing information.
@@ -496,18 +546,24 @@ enum rxrpc_congest_change { rxrpc_congest_changes } __mode(byte);
enum rxrpc_conn_trace { rxrpc_conn_traces } __mode(byte);
enum rxrpc_local_trace { rxrpc_local_traces } __mode(byte);
enum rxrpc_peer_trace { rxrpc_peer_traces } __mode(byte);
+enum rxrpc_pmtud_reduce_trace { rxrpc_pmtud_reduce_traces } __mode(byte);
enum rxrpc_propose_ack_outcome { rxrpc_propose_ack_outcomes } __mode(byte);
enum rxrpc_propose_ack_trace { rxrpc_propose_ack_traces } __mode(byte);
enum rxrpc_receive_trace { rxrpc_receive_traces } __mode(byte);
enum rxrpc_recvmsg_trace { rxrpc_recvmsg_traces } __mode(byte);
enum rxrpc_req_ack_trace { rxrpc_req_ack_traces } __mode(byte);
+enum rxrpc_rotate_trace { rxrpc_rotate_traces } __mode(byte);
enum rxrpc_rtt_rx_trace { rxrpc_rtt_rx_traces } __mode(byte);
enum rxrpc_rtt_tx_trace { rxrpc_rtt_tx_traces } __mode(byte);
enum rxrpc_sack_trace { rxrpc_sack_traces } __mode(byte);
enum rxrpc_skb_trace { rxrpc_skb_traces } __mode(byte);
enum rxrpc_timer_trace { rxrpc_timer_traces } __mode(byte);
+enum rxrpc_tlp_ack_trace { rxrpc_tlp_ack_traces } __mode(byte);
+enum rxrpc_tlp_probe_trace { rxrpc_tlp_probe_traces } __mode(byte);
+enum rxrpc_tq_trace { rxrpc_tq_traces } __mode(byte);
enum rxrpc_tx_point { rxrpc_tx_points } __mode(byte);
enum rxrpc_txbuf_trace { rxrpc_txbuf_traces } __mode(byte);
+enum rxrpc_txdata_trace { rxrpc_txdata_traces } __mode(byte);
enum rxrpc_txqueue_trace { rxrpc_txqueue_traces } __mode(byte);
#endif /* end __RXRPC_DECLARE_TRACE_ENUMS_ONCE_ONLY */
@@ -525,24 +581,31 @@ enum rxrpc_txqueue_trace { rxrpc_txqueue_traces } __mode(byte);
rxrpc_abort_reasons;
rxrpc_bundle_traces;
+rxrpc_ca_states;
rxrpc_call_poke_traces;
rxrpc_call_traces;
rxrpc_client_traces;
rxrpc_congest_changes;
-rxrpc_congest_modes;
rxrpc_conn_traces;
rxrpc_local_traces;
+rxrpc_pmtud_reduce_traces;
rxrpc_propose_ack_traces;
+rxrpc_rack_timer_modes;
rxrpc_receive_traces;
rxrpc_recvmsg_traces;
rxrpc_req_ack_traces;
+rxrpc_rotate_traces;
rxrpc_rtt_rx_traces;
rxrpc_rtt_tx_traces;
rxrpc_sack_traces;
rxrpc_skb_traces;
rxrpc_timer_traces;
+rxrpc_tlp_ack_traces;
+rxrpc_tlp_probe_traces;
+rxrpc_tq_traces;
rxrpc_tx_points;
rxrpc_txbuf_traces;
+rxrpc_txdata_traces;
rxrpc_txqueue_traces;
/*
@@ -581,6 +644,20 @@ TRACE_EVENT(rxrpc_local,
__entry->usage)
);
+TRACE_EVENT(rxrpc_iothread_rx,
+ TP_PROTO(struct rxrpc_local *local, unsigned int nr_rx),
+ TP_ARGS(local, nr_rx),
+ TP_STRUCT__entry(
+ __field(unsigned int, local)
+ __field(unsigned int, nr_rx)
+ ),
+ TP_fast_assign(
+ __entry->local = local->debug_id;
+ __entry->nr_rx = nr_rx;
+ ),
+ TP_printk("L=%08x nrx=%u", __entry->local, __entry->nr_rx)
+ );
+
TRACE_EVENT(rxrpc_peer,
TP_PROTO(unsigned int peer_debug_id, int ref, enum rxrpc_peer_trace why),
@@ -865,34 +942,101 @@ TRACE_EVENT(rxrpc_txqueue,
TP_STRUCT__entry(
__field(unsigned int, call)
__field(enum rxrpc_txqueue_trace, why)
- __field(rxrpc_seq_t, acks_hard_ack)
__field(rxrpc_seq_t, tx_bottom)
+ __field(rxrpc_seq_t, acks_hard_ack)
__field(rxrpc_seq_t, tx_top)
- __field(rxrpc_seq_t, tx_prepared)
+ __field(rxrpc_seq_t, send_top)
__field(int, tx_winsize)
),
TP_fast_assign(
__entry->call = call->debug_id;
__entry->why = why;
- __entry->acks_hard_ack = call->acks_hard_ack;
__entry->tx_bottom = call->tx_bottom;
+ __entry->acks_hard_ack = call->acks_hard_ack;
__entry->tx_top = call->tx_top;
- __entry->tx_prepared = call->tx_prepared;
+ __entry->send_top = call->send_top;
__entry->tx_winsize = call->tx_winsize;
),
- TP_printk("c=%08x %s f=%08x h=%08x n=%u/%u/%u/%u",
+ TP_printk("c=%08x %s b=%08x h=%08x n=%u/%u/%u/%u",
__entry->call,
__print_symbolic(__entry->why, rxrpc_txqueue_traces),
__entry->tx_bottom,
__entry->acks_hard_ack,
- __entry->tx_top - __entry->tx_bottom,
+ __entry->acks_hard_ack - __entry->tx_bottom,
__entry->tx_top - __entry->acks_hard_ack,
- __entry->tx_prepared - __entry->tx_bottom,
+ __entry->send_top - __entry->tx_top,
__entry->tx_winsize)
);
+TRACE_EVENT(rxrpc_transmit,
+ TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t send_top, int space),
+
+ TP_ARGS(call, send_top, space),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_seq_t, seq)
+ __field(u16, space)
+ __field(u16, tx_winsize)
+ __field(u16, cong_cwnd)
+ __field(u16, cong_extra)
+ __field(u16, in_flight)
+ __field(u16, prepared)
+ __field(u16, pmtud_jumbo)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->seq = call->tx_top + 1;
+ __entry->space = space;
+ __entry->tx_winsize = call->tx_winsize;
+ __entry->cong_cwnd = call->cong_cwnd;
+ __entry->cong_extra = call->cong_extra;
+ __entry->prepared = send_top - call->tx_bottom;
+ __entry->in_flight = call->tx_top - call->tx_bottom;
+ __entry->pmtud_jumbo = call->peer->pmtud_jumbo;
+ ),
+
+ TP_printk("c=%08x q=%08x sp=%u tw=%u cw=%u+%u pr=%u if=%u pj=%u",
+ __entry->call,
+ __entry->seq,
+ __entry->space,
+ __entry->tx_winsize,
+ __entry->cong_cwnd,
+ __entry->cong_extra,
+ __entry->prepared,
+ __entry->in_flight,
+ __entry->pmtud_jumbo)
+ );
+
+TRACE_EVENT(rxrpc_tx_rotate,
+ TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t seq, rxrpc_seq_t to),
+
+ TP_ARGS(call, seq, to),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_seq_t, seq)
+ __field(rxrpc_seq_t, to)
+ __field(rxrpc_seq_t, top)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->seq = seq;
+ __entry->to = to;
+ __entry->top = call->tx_top;
+ ),
+
+ TP_printk("c=%08x q=%08x-%08x-%08x",
+ __entry->call,
+ __entry->seq,
+ __entry->to,
+ __entry->top)
+ );
+
TRACE_EVENT(rxrpc_rx_data,
TP_PROTO(unsigned int call, rxrpc_seq_t seq,
rxrpc_serial_t serial, u8 flags),
@@ -921,11 +1065,9 @@ TRACE_EVENT(rxrpc_rx_data,
);
TRACE_EVENT(rxrpc_rx_ack,
- TP_PROTO(struct rxrpc_call *call,
- rxrpc_serial_t serial, rxrpc_serial_t ack_serial,
- rxrpc_seq_t first, rxrpc_seq_t prev, u8 reason, u8 n_acks),
+ TP_PROTO(struct rxrpc_call *call, struct rxrpc_skb_priv *sp),
- TP_ARGS(call, serial, ack_serial, first, prev, reason, n_acks),
+ TP_ARGS(call, sp),
TP_STRUCT__entry(
__field(unsigned int, call)
@@ -935,23 +1077,26 @@ TRACE_EVENT(rxrpc_rx_ack,
__field(rxrpc_seq_t, prev)
__field(u8, reason)
__field(u8, n_acks)
+ __field(u8, user_status)
),
TP_fast_assign(
- __entry->call = call->debug_id;
- __entry->serial = serial;
- __entry->ack_serial = ack_serial;
- __entry->first = first;
- __entry->prev = prev;
- __entry->reason = reason;
- __entry->n_acks = n_acks;
+ __entry->call = call->debug_id;
+ __entry->serial = sp->hdr.serial;
+ __entry->user_status = sp->hdr.userStatus;
+ __entry->ack_serial = sp->ack.acked_serial;
+ __entry->first = sp->ack.first_ack;
+ __entry->prev = sp->ack.prev_ack;
+ __entry->reason = sp->ack.reason;
+ __entry->n_acks = sp->ack.nr_acks;
),
- TP_printk("c=%08x %08x %s r=%08x f=%08x p=%08x n=%u",
+ TP_printk("c=%08x %08x %s r=%08x us=%02x f=%08x p=%08x n=%u",
__entry->call,
__entry->serial,
__print_symbolic(__entry->reason, rxrpc_ack_names),
__entry->ack_serial,
+ __entry->user_status,
__entry->first,
__entry->prev,
__entry->n_acks)
@@ -981,6 +1126,29 @@ TRACE_EVENT(rxrpc_rx_abort,
__entry->abort_code)
);
+TRACE_EVENT(rxrpc_rx_conn_abort,
+ TP_PROTO(const struct rxrpc_connection *conn, const struct sk_buff *skb),
+
+ TP_ARGS(conn, skb),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, conn)
+ __field(rxrpc_serial_t, serial)
+ __field(u32, abort_code)
+ ),
+
+ TP_fast_assign(
+ __entry->conn = conn->debug_id;
+ __entry->serial = rxrpc_skb(skb)->hdr.serial;
+ __entry->abort_code = skb->priority;
+ ),
+
+ TP_printk("C=%08x ABORT %08x ac=%d",
+ __entry->conn,
+ __entry->serial,
+ __entry->abort_code)
+ );
+
TRACE_EVENT(rxrpc_rx_challenge,
TP_PROTO(struct rxrpc_connection *conn, rxrpc_serial_t serial,
u32 version, u32 nonce, u32 min_level),
@@ -1102,9 +1270,10 @@ TRACE_EVENT(rxrpc_tx_packet,
TRACE_EVENT(rxrpc_tx_data,
TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t seq,
- rxrpc_serial_t serial, unsigned int flags, bool lose),
+ rxrpc_serial_t serial, unsigned int flags,
+ enum rxrpc_txdata_trace trace),
- TP_ARGS(call, seq, serial, flags, lose),
+ TP_ARGS(call, seq, serial, flags, trace),
TP_STRUCT__entry(
__field(unsigned int, call)
@@ -1113,7 +1282,7 @@ TRACE_EVENT(rxrpc_tx_data,
__field(u32, cid)
__field(u32, call_id)
__field(u16, flags)
- __field(bool, lose)
+ __field(enum rxrpc_txdata_trace, trace)
),
TP_fast_assign(
@@ -1123,26 +1292,26 @@ TRACE_EVENT(rxrpc_tx_data,
__entry->seq = seq;
__entry->serial = serial;
__entry->flags = flags;
- __entry->lose = lose;
+ __entry->trace = trace;
),
- TP_printk("c=%08x DATA %08x:%08x %08x q=%08x fl=%02x%s%s",
+ TP_printk("c=%08x DATA %08x:%08x %08x q=%08x fl=%02x%s",
__entry->call,
__entry->cid,
__entry->call_id,
__entry->serial,
__entry->seq,
__entry->flags & RXRPC_TXBUF_WIRE_FLAGS,
- __entry->flags & RXRPC_TXBUF_RESENT ? " *RETRANS*" : "",
- __entry->lose ? " *LOSE*" : "")
+ __print_symbolic(__entry->trace, rxrpc_txdata_traces))
);
TRACE_EVENT(rxrpc_tx_ack,
TP_PROTO(unsigned int call, rxrpc_serial_t serial,
rxrpc_seq_t ack_first, rxrpc_serial_t ack_serial,
- u8 reason, u8 n_acks, u16 rwind),
+ u8 reason, u8 n_acks, u16 rwind,
+ enum rxrpc_propose_ack_trace trace),
- TP_ARGS(call, serial, ack_first, ack_serial, reason, n_acks, rwind),
+ TP_ARGS(call, serial, ack_first, ack_serial, reason, n_acks, rwind, trace),
TP_STRUCT__entry(
__field(unsigned int, call)
@@ -1152,6 +1321,7 @@ TRACE_EVENT(rxrpc_tx_ack,
__field(u8, reason)
__field(u8, n_acks)
__field(u16, rwind)
+ __field(enum rxrpc_propose_ack_trace, trace)
),
TP_fast_assign(
@@ -1162,16 +1332,18 @@ TRACE_EVENT(rxrpc_tx_ack,
__entry->reason = reason;
__entry->n_acks = n_acks;
__entry->rwind = rwind;
+ __entry->trace = trace;
),
- TP_printk(" c=%08x ACK %08x %s f=%08x r=%08x n=%u rw=%u",
+ TP_printk(" c=%08x ACK %08x %s f=%08x r=%08x n=%u rw=%u %s",
__entry->call,
__entry->serial,
__print_symbolic(__entry->reason, rxrpc_ack_names),
__entry->ack_first,
__entry->ack_serial,
__entry->n_acks,
- __entry->rwind)
+ __entry->rwind,
+ __print_symbolic(__entry->trace, rxrpc_propose_ack_traces))
);
TRACE_EVENT(rxrpc_receive,
@@ -1296,9 +1468,9 @@ TRACE_EVENT(rxrpc_rtt_rx,
TP_PROTO(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why,
int slot,
rxrpc_serial_t send_serial, rxrpc_serial_t resp_serial,
- u32 rtt, u32 rto),
+ u32 rtt, u32 srtt, u32 rto),
- TP_ARGS(call, why, slot, send_serial, resp_serial, rtt, rto),
+ TP_ARGS(call, why, slot, send_serial, resp_serial, rtt, srtt, rto),
TP_STRUCT__entry(
__field(unsigned int, call)
@@ -1307,7 +1479,9 @@ TRACE_EVENT(rxrpc_rtt_rx,
__field(rxrpc_serial_t, send_serial)
__field(rxrpc_serial_t, resp_serial)
__field(u32, rtt)
+ __field(u32, srtt)
__field(u32, rto)
+ __field(u32, min_rtt)
),
TP_fast_assign(
@@ -1317,17 +1491,21 @@ TRACE_EVENT(rxrpc_rtt_rx,
__entry->send_serial = send_serial;
__entry->resp_serial = resp_serial;
__entry->rtt = rtt;
+ __entry->srtt = srtt;
__entry->rto = rto;
+ __entry->min_rtt = minmax_get(&call->min_rtt)
),
- TP_printk("c=%08x [%d] %s sr=%08x rr=%08x rtt=%u rto=%u",
+ TP_printk("c=%08x [%d] %s sr=%08x rr=%08x rtt=%u srtt=%u rto=%u min=%u",
__entry->call,
__entry->slot,
__print_symbolic(__entry->why, rxrpc_rtt_rx_traces),
__entry->send_serial,
__entry->resp_serial,
__entry->rtt,
- __entry->rto)
+ __entry->srtt / 8,
+ __entry->rto,
+ __entry->min_rtt)
);
TRACE_EVENT(rxrpc_timer_set,
@@ -1544,112 +1722,125 @@ TRACE_EVENT(rxrpc_drop_ack,
);
TRACE_EVENT(rxrpc_retransmit,
- TP_PROTO(struct rxrpc_call *call, rxrpc_seq_t seq,
- rxrpc_serial_t serial, ktime_t expiry),
+ TP_PROTO(struct rxrpc_call *call,
+ struct rxrpc_send_data_req *req,
+ struct rxrpc_txbuf *txb),
- TP_ARGS(call, seq, serial, expiry),
+ TP_ARGS(call, req, txb),
TP_STRUCT__entry(
__field(unsigned int, call)
+ __field(unsigned int, qbase)
__field(rxrpc_seq_t, seq)
__field(rxrpc_serial_t, serial)
- __field(ktime_t, expiry)
),
TP_fast_assign(
__entry->call = call->debug_id;
- __entry->seq = seq;
- __entry->serial = serial;
- __entry->expiry = expiry;
+ __entry->qbase = req->tq->qbase;
+ __entry->seq = req->seq;
+ __entry->serial = txb->serial;
),
- TP_printk("c=%08x q=%x r=%x xp=%lld",
+ TP_printk("c=%08x tq=%x q=%x r=%x",
__entry->call,
+ __entry->qbase,
__entry->seq,
- __entry->serial,
- ktime_to_us(__entry->expiry))
+ __entry->serial)
);
TRACE_EVENT(rxrpc_congest,
- TP_PROTO(struct rxrpc_call *call, struct rxrpc_ack_summary *summary,
- rxrpc_serial_t ack_serial, enum rxrpc_congest_change change),
+ TP_PROTO(struct rxrpc_call *call, struct rxrpc_ack_summary *summary),
- TP_ARGS(call, summary, ack_serial, change),
+ TP_ARGS(call, summary),
TP_STRUCT__entry(
__field(unsigned int, call)
- __field(enum rxrpc_congest_change, change)
+ __field(enum rxrpc_ca_state, ca_state)
__field(rxrpc_seq_t, hard_ack)
__field(rxrpc_seq_t, top)
__field(rxrpc_seq_t, lowest_nak)
- __field(rxrpc_serial_t, ack_serial)
+ __field(u16, nr_sacks)
+ __field(u16, nr_snacks)
+ __field(u16, cwnd)
+ __field(u16, ssthresh)
+ __field(u16, cumul_acks)
+ __field(u16, dup_acks)
__field_struct(struct rxrpc_ack_summary, sum)
),
TP_fast_assign(
__entry->call = call->debug_id;
- __entry->change = change;
+ __entry->ca_state = call->cong_ca_state;
__entry->hard_ack = call->acks_hard_ack;
__entry->top = call->tx_top;
__entry->lowest_nak = call->acks_lowest_nak;
- __entry->ack_serial = ack_serial;
+ __entry->nr_sacks = call->acks_nr_sacks;
+ __entry->nr_snacks = call->acks_nr_snacks;
+ __entry->cwnd = call->cong_cwnd;
+ __entry->ssthresh = call->cong_ssthresh;
+ __entry->cumul_acks = call->cong_cumul_acks;
+ __entry->dup_acks = call->cong_dup_acks;
memcpy(&__entry->sum, summary, sizeof(__entry->sum));
),
- TP_printk("c=%08x r=%08x %s q=%08x %s cw=%u ss=%u nA=%u,%u+%u,%u b=%u u=%u d=%u l=%x%s%s%s",
+ TP_printk("c=%08x r=%08x %s q=%08x %s cw=%u ss=%u A=%u+%u/%u+%u r=%u b=%u u=%u d=%u l=%x%s%s%s",
__entry->call,
- __entry->ack_serial,
+ __entry->sum.acked_serial,
__print_symbolic(__entry->sum.ack_reason, rxrpc_ack_names),
__entry->hard_ack,
- __print_symbolic(__entry->sum.mode, rxrpc_congest_modes),
- __entry->sum.cwnd,
- __entry->sum.ssthresh,
- __entry->sum.nr_acks, __entry->sum.nr_retained_nacks,
- __entry->sum.nr_new_acks,
- __entry->sum.nr_new_nacks,
+ __print_symbolic(__entry->ca_state, rxrpc_ca_states),
+ __entry->cwnd,
+ __entry->ssthresh,
+ __entry->nr_sacks, __entry->sum.nr_new_sacks,
+ __entry->nr_snacks, __entry->sum.nr_new_snacks,
+ __entry->sum.nr_new_hacks,
__entry->top - __entry->hard_ack,
- __entry->sum.cumulative_acks,
- __entry->sum.dup_acks,
- __entry->lowest_nak, __entry->sum.new_low_nack ? "!" : "",
- __print_symbolic(__entry->change, rxrpc_congest_changes),
+ __entry->cumul_acks,
+ __entry->dup_acks,
+ __entry->lowest_nak, __entry->sum.new_low_snack ? "!" : "",
+ __print_symbolic(__entry->sum.change, rxrpc_congest_changes),
__entry->sum.retrans_timeo ? " rTxTo" : "")
);
TRACE_EVENT(rxrpc_reset_cwnd,
- TP_PROTO(struct rxrpc_call *call, ktime_t now),
+ TP_PROTO(struct rxrpc_call *call, ktime_t since_last_tx, ktime_t rtt),
- TP_ARGS(call, now),
+ TP_ARGS(call, since_last_tx, rtt),
TP_STRUCT__entry(
__field(unsigned int, call)
- __field(enum rxrpc_congest_mode, mode)
+ __field(enum rxrpc_ca_state, ca_state)
__field(unsigned short, cwnd)
__field(unsigned short, extra)
__field(rxrpc_seq_t, hard_ack)
__field(rxrpc_seq_t, prepared)
__field(ktime_t, since_last_tx)
+ __field(ktime_t, rtt)
__field(bool, has_data)
),
TP_fast_assign(
__entry->call = call->debug_id;
- __entry->mode = call->cong_mode;
+ __entry->ca_state = call->cong_ca_state;
__entry->cwnd = call->cong_cwnd;
__entry->extra = call->cong_extra;
__entry->hard_ack = call->acks_hard_ack;
- __entry->prepared = call->tx_prepared - call->tx_bottom;
- __entry->since_last_tx = ktime_sub(now, call->tx_last_sent);
- __entry->has_data = !list_empty(&call->tx_sendmsg);
+ __entry->prepared = call->send_top - call->tx_bottom;
+ __entry->since_last_tx = since_last_tx;
+ __entry->rtt = rtt;
+ __entry->has_data = call->tx_bottom != call->tx_top;
),
- TP_printk("c=%08x q=%08x %s cw=%u+%u pr=%u tm=%llu d=%u",
+ TP_printk("c=%08x q=%08x %s cw=%u+%u pr=%u tm=%llu/%llu d=%u",
__entry->call,
__entry->hard_ack,
- __print_symbolic(__entry->mode, rxrpc_congest_modes),
+ __print_symbolic(__entry->ca_state, rxrpc_ca_states),
__entry->cwnd,
__entry->extra,
__entry->prepared,
- ktime_to_ns(__entry->since_last_tx),
+ ktime_to_us(__entry->since_last_tx),
+ ktime_to_us(__entry->rtt),
__entry->has_data)
);
@@ -1722,10 +1913,36 @@ TRACE_EVENT(rxrpc_connect_call,
&__entry->srx.transport)
);
+TRACE_EVENT(rxrpc_apply_acks,
+ TP_PROTO(struct rxrpc_call *call, struct rxrpc_txqueue *tq),
+
+ TP_ARGS(call, tq),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(unsigned int, nr_rep)
+ __field(rxrpc_seq_t, qbase)
+ __field(unsigned long, acks)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->qbase = tq->qbase;
+ __entry->acks = tq->segment_acked;
+ __entry->nr_rep = tq->nr_reported_acks;
+ ),
+
+ TP_printk("c=%08x tq=%x acks=%016lx rep=%u",
+ __entry->call,
+ __entry->qbase,
+ __entry->acks,
+ __entry->nr_rep)
+ );
+
TRACE_EVENT(rxrpc_resend,
- TP_PROTO(struct rxrpc_call *call, struct sk_buff *ack),
+ TP_PROTO(struct rxrpc_call *call, rxrpc_serial_t ack_serial),
- TP_ARGS(call, ack),
+ TP_ARGS(call, ack_serial),
TP_STRUCT__entry(
__field(unsigned int, call)
@@ -1735,11 +1952,10 @@ TRACE_EVENT(rxrpc_resend,
),
TP_fast_assign(
- struct rxrpc_skb_priv *sp = ack ? rxrpc_skb(ack) : NULL;
__entry->call = call->debug_id;
__entry->seq = call->acks_hard_ack;
__entry->transmitted = call->tx_transmitted;
- __entry->ack_serial = sp ? sp->hdr.serial : 0;
+ __entry->ack_serial = ack_serial;
),
TP_printk("c=%08x r=%x q=%x tq=%x",
@@ -1749,6 +1965,63 @@ TRACE_EVENT(rxrpc_resend,
__entry->transmitted)
);
+TRACE_EVENT(rxrpc_resend_lost,
+ TP_PROTO(struct rxrpc_call *call, struct rxrpc_txqueue *tq, unsigned long lost),
+
+ TP_ARGS(call, tq, lost),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_seq_t, qbase)
+ __field(u8, nr_rep)
+ __field(unsigned long, lost)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->qbase = tq->qbase;
+ __entry->nr_rep = tq->nr_reported_acks;
+ __entry->lost = lost;
+ ),
+
+ TP_printk("c=%08x tq=%x lost=%016lx nr=%u",
+ __entry->call,
+ __entry->qbase,
+ __entry->lost,
+ __entry->nr_rep)
+ );
+
+TRACE_EVENT(rxrpc_rotate,
+ TP_PROTO(struct rxrpc_call *call, struct rxrpc_txqueue *tq,
+ struct rxrpc_ack_summary *summary, rxrpc_seq_t seq,
+ enum rxrpc_rotate_trace trace),
+
+ TP_ARGS(call, tq, summary, seq, trace),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_seq_t, qbase)
+ __field(rxrpc_seq_t, seq)
+ __field(unsigned int, nr_rep)
+ __field(enum rxrpc_rotate_trace, trace)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->qbase = tq->qbase;
+ __entry->seq = seq;
+ __entry->nr_rep = tq->nr_reported_acks;
+ __entry->trace = trace;
+ ),
+
+ TP_printk("c=%08x tq=%x q=%x nr=%x %s",
+ __entry->call,
+ __entry->qbase,
+ __entry->seq,
+ __entry->nr_rep,
+ __print_symbolic(__entry->trace, rxrpc_rotate_traces))
+ );
+
TRACE_EVENT(rxrpc_rx_icmp,
TP_PROTO(struct rxrpc_peer *peer, struct sock_extended_err *ee,
struct sockaddr_rxrpc *srx),
@@ -1858,38 +2131,36 @@ TRACE_EVENT(rxrpc_notify_socket,
);
TRACE_EVENT(rxrpc_rx_discard_ack,
- TP_PROTO(unsigned int debug_id, rxrpc_serial_t serial,
- rxrpc_seq_t first_soft_ack, rxrpc_seq_t call_ackr_first,
- rxrpc_seq_t prev_pkt, rxrpc_seq_t call_ackr_prev),
+ TP_PROTO(struct rxrpc_call *call, rxrpc_serial_t serial,
+ rxrpc_seq_t hard_ack, rxrpc_seq_t prev_pkt),
- TP_ARGS(debug_id, serial, first_soft_ack, call_ackr_first,
- prev_pkt, call_ackr_prev),
+ TP_ARGS(call, serial, hard_ack, prev_pkt),
TP_STRUCT__entry(
__field(unsigned int, debug_id)
__field(rxrpc_serial_t, serial)
- __field(rxrpc_seq_t, first_soft_ack)
- __field(rxrpc_seq_t, call_ackr_first)
+ __field(rxrpc_seq_t, hard_ack)
__field(rxrpc_seq_t, prev_pkt)
- __field(rxrpc_seq_t, call_ackr_prev)
+ __field(rxrpc_seq_t, acks_hard_ack)
+ __field(rxrpc_seq_t, acks_prev_seq)
),
TP_fast_assign(
- __entry->debug_id = debug_id;
+ __entry->debug_id = call->debug_id;
__entry->serial = serial;
- __entry->first_soft_ack = first_soft_ack;
- __entry->call_ackr_first = call_ackr_first;
+ __entry->hard_ack = hard_ack;
__entry->prev_pkt = prev_pkt;
- __entry->call_ackr_prev = call_ackr_prev;
+ __entry->acks_hard_ack = call->acks_hard_ack;
+ __entry->acks_prev_seq = call->acks_prev_seq;
),
TP_printk("c=%08x r=%08x %08x<%08x %08x<%08x",
__entry->debug_id,
__entry->serial,
- __entry->first_soft_ack,
- __entry->call_ackr_first,
+ __entry->hard_ack,
+ __entry->acks_hard_ack,
__entry->prev_pkt,
- __entry->call_ackr_prev)
+ __entry->acks_prev_seq)
);
TRACE_EVENT(rxrpc_req_ack,
@@ -1947,6 +2218,33 @@ TRACE_EVENT(rxrpc_txbuf,
__entry->ref)
);
+TRACE_EVENT(rxrpc_tq,
+ TP_PROTO(struct rxrpc_call *call, struct rxrpc_txqueue *tq,
+ rxrpc_seq_t seq, enum rxrpc_tq_trace trace),
+
+ TP_ARGS(call, tq, seq, trace),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call_debug_id)
+ __field(rxrpc_seq_t, qbase)
+ __field(rxrpc_seq_t, seq)
+ __field(enum rxrpc_tq_trace, trace)
+ ),
+
+ TP_fast_assign(
+ __entry->call_debug_id = call->debug_id;
+ __entry->qbase = tq ? tq->qbase : call->tx_qbase;
+ __entry->seq = seq;
+ __entry->trace = trace;
+ ),
+
+ TP_printk("c=%08x bq=%08x q=%08x %s",
+ __entry->call_debug_id,
+ __entry->qbase,
+ __entry->seq,
+ __print_symbolic(__entry->trace, rxrpc_tq_traces))
+ );
+
TRACE_EVENT(rxrpc_poke_call,
TP_PROTO(struct rxrpc_call *call, bool busy,
enum rxrpc_call_poke_trace what),
@@ -2015,6 +2313,360 @@ TRACE_EVENT(rxrpc_sack,
__entry->sack)
);
+TRACE_EVENT(rxrpc_pmtud_tx,
+ TP_PROTO(struct rxrpc_call *call),
+
+ TP_ARGS(call),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, peer_debug_id)
+ __field(unsigned int, call_debug_id)
+ __field(rxrpc_serial_t, ping_serial)
+ __field(unsigned short, pmtud_trial)
+ __field(unsigned short, pmtud_good)
+ __field(unsigned short, pmtud_bad)
+ ),
+
+ TP_fast_assign(
+ __entry->peer_debug_id = call->peer->debug_id;
+ __entry->call_debug_id = call->debug_id;
+ __entry->ping_serial = call->conn->pmtud_probe;
+ __entry->pmtud_trial = call->peer->pmtud_trial;
+ __entry->pmtud_good = call->peer->pmtud_good;
+ __entry->pmtud_bad = call->peer->pmtud_bad;
+ ),
+
+ TP_printk("P=%08x c=%08x pr=%08x %u-%u-%u",
+ __entry->peer_debug_id,
+ __entry->call_debug_id,
+ __entry->ping_serial,
+ __entry->pmtud_good,
+ __entry->pmtud_trial,
+ __entry->pmtud_bad)
+ );
+
+TRACE_EVENT(rxrpc_pmtud_rx,
+ TP_PROTO(struct rxrpc_connection *conn, rxrpc_serial_t resp_serial),
+
+ TP_ARGS(conn, resp_serial),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, peer_debug_id)
+ __field(unsigned int, call_debug_id)
+ __field(rxrpc_serial_t, ping_serial)
+ __field(rxrpc_serial_t, resp_serial)
+ __field(unsigned short, max_data)
+ __field(u8, jumbo_max)
+ ),
+
+ TP_fast_assign(
+ __entry->peer_debug_id = conn->peer->debug_id;
+ __entry->call_debug_id = conn->pmtud_call;
+ __entry->ping_serial = conn->pmtud_probe;
+ __entry->resp_serial = resp_serial;
+ __entry->max_data = conn->peer->max_data;
+ __entry->jumbo_max = conn->peer->pmtud_jumbo;
+ ),
+
+ TP_printk("P=%08x c=%08x pr=%08x rr=%08x max=%u jm=%u",
+ __entry->peer_debug_id,
+ __entry->call_debug_id,
+ __entry->ping_serial,
+ __entry->resp_serial,
+ __entry->max_data,
+ __entry->jumbo_max)
+ );
+
+TRACE_EVENT(rxrpc_pmtud_lost,
+ TP_PROTO(struct rxrpc_connection *conn, rxrpc_serial_t resp_serial),
+
+ TP_ARGS(conn, resp_serial),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, peer_debug_id)
+ __field(unsigned int, call_debug_id)
+ __field(rxrpc_serial_t, ping_serial)
+ __field(rxrpc_serial_t, resp_serial)
+ ),
+
+ TP_fast_assign(
+ __entry->peer_debug_id = conn->peer->debug_id;
+ __entry->call_debug_id = conn->pmtud_call;
+ __entry->ping_serial = conn->pmtud_probe;
+ __entry->resp_serial = resp_serial;
+ ),
+
+ TP_printk("P=%08x c=%08x pr=%08x rr=%08x",
+ __entry->peer_debug_id,
+ __entry->call_debug_id,
+ __entry->ping_serial,
+ __entry->resp_serial)
+ );
+
+TRACE_EVENT(rxrpc_pmtud_reduce,
+ TP_PROTO(struct rxrpc_peer *peer, rxrpc_serial_t serial,
+ unsigned int max_data, enum rxrpc_pmtud_reduce_trace reason),
+
+ TP_ARGS(peer, serial, max_data, reason),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, peer_debug_id)
+ __field(rxrpc_serial_t, serial)
+ __field(unsigned int, max_data)
+ __field(enum rxrpc_pmtud_reduce_trace, reason)
+ ),
+
+ TP_fast_assign(
+ __entry->peer_debug_id = peer->debug_id;
+ __entry->serial = serial;
+ __entry->max_data = max_data;
+ __entry->reason = reason;
+ ),
+
+ TP_printk("P=%08x %s r=%08x m=%u",
+ __entry->peer_debug_id,
+ __print_symbolic(__entry->reason, rxrpc_pmtud_reduce_traces),
+ __entry->serial, __entry->max_data)
+ );
+
+TRACE_EVENT(rxrpc_rack,
+ TP_PROTO(struct rxrpc_call *call, ktime_t timo),
+
+ TP_ARGS(call, timo),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_serial_t, ack_serial)
+ __field(rxrpc_seq_t, seq)
+ __field(enum rxrpc_rack_timer_mode, mode)
+ __field(unsigned short, nr_sent)
+ __field(unsigned short, nr_lost)
+ __field(unsigned short, nr_resent)
+ __field(unsigned short, nr_sacked)
+ __field(ktime_t, timo)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->ack_serial = call->rx_serial;
+ __entry->seq = call->rack_end_seq;
+ __entry->mode = call->rack_timer_mode;
+ __entry->nr_sent = call->tx_nr_sent;
+ __entry->nr_lost = call->tx_nr_lost;
+ __entry->nr_resent = call->tx_nr_resent;
+ __entry->nr_sacked = call->acks_nr_sacks;
+ __entry->timo = timo;
+ ),
+
+ TP_printk("c=%08x r=%08x q=%08x %s slrs=%u,%u,%u,%u t=%lld",
+ __entry->call, __entry->ack_serial, __entry->seq,
+ __print_symbolic(__entry->mode, rxrpc_rack_timer_modes),
+ __entry->nr_sent, __entry->nr_lost,
+ __entry->nr_resent, __entry->nr_sacked,
+ ktime_to_us(__entry->timo))
+ );
+
+TRACE_EVENT(rxrpc_rack_update,
+ TP_PROTO(struct rxrpc_call *call, struct rxrpc_ack_summary *summary),
+
+ TP_ARGS(call, summary),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_serial_t, ack_serial)
+ __field(rxrpc_seq_t, seq)
+ __field(int, xmit_ts)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->ack_serial = call->rx_serial;
+ __entry->seq = call->rack_end_seq;
+ __entry->xmit_ts = ktime_sub(call->acks_latest_ts, call->rack_xmit_ts);
+ ),
+
+ TP_printk("c=%08x r=%08x q=%08x xt=%lld",
+ __entry->call, __entry->ack_serial, __entry->seq,
+ ktime_to_us(__entry->xmit_ts))
+ );
+
+TRACE_EVENT(rxrpc_rack_scan_loss,
+ TP_PROTO(struct rxrpc_call *call),
+
+ TP_ARGS(call),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(ktime_t, rack_rtt)
+ __field(ktime_t, rack_reo_wnd)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->rack_rtt = call->rack_rtt;
+ __entry->rack_reo_wnd = call->rack_reo_wnd;
+ ),
+
+ TP_printk("c=%08x rtt=%lld reow=%lld",
+ __entry->call, ktime_to_us(__entry->rack_rtt),
+ ktime_to_us(__entry->rack_reo_wnd))
+ );
+
+TRACE_EVENT(rxrpc_rack_scan_loss_tq,
+ TP_PROTO(struct rxrpc_call *call, const struct rxrpc_txqueue *tq,
+ unsigned long nacks),
+
+ TP_ARGS(call, tq, nacks),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_seq_t, qbase)
+ __field(unsigned long, nacks)
+ __field(unsigned long, lost)
+ __field(unsigned long, retrans)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->qbase = tq->qbase;
+ __entry->nacks = nacks;
+ __entry->lost = tq->segment_lost;
+ __entry->retrans = tq->segment_retransmitted;
+ ),
+
+ TP_printk("c=%08x q=%08x n=%lx l=%lx r=%lx",
+ __entry->call, __entry->qbase,
+ __entry->nacks, __entry->lost, __entry->retrans)
+ );
+
+TRACE_EVENT(rxrpc_rack_detect_loss,
+ TP_PROTO(struct rxrpc_call *call, struct rxrpc_ack_summary *summary,
+ rxrpc_seq_t seq),
+
+ TP_ARGS(call, summary, seq),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_serial_t, ack_serial)
+ __field(rxrpc_seq_t, seq)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->ack_serial = call->rx_serial;
+ __entry->seq = seq;
+ ),
+
+ TP_printk("c=%08x r=%08x q=%08x",
+ __entry->call, __entry->ack_serial, __entry->seq)
+ );
+
+TRACE_EVENT(rxrpc_rack_mark_loss_tq,
+ TP_PROTO(struct rxrpc_call *call, const struct rxrpc_txqueue *tq),
+
+ TP_ARGS(call, tq),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_seq_t, qbase)
+ __field(rxrpc_seq_t, trans)
+ __field(unsigned long, acked)
+ __field(unsigned long, lost)
+ __field(unsigned long, retrans)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->qbase = tq->qbase;
+ __entry->trans = call->tx_transmitted;
+ __entry->acked = tq->segment_acked;
+ __entry->lost = tq->segment_lost;
+ __entry->retrans = tq->segment_retransmitted;
+ ),
+
+ TP_printk("c=%08x tq=%08x txq=%08x a=%lx l=%lx r=%lx",
+ __entry->call, __entry->qbase, __entry->trans,
+ __entry->acked, __entry->lost, __entry->retrans)
+ );
+
+TRACE_EVENT(rxrpc_tlp_probe,
+ TP_PROTO(struct rxrpc_call *call, enum rxrpc_tlp_probe_trace trace),
+
+ TP_ARGS(call, trace),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_serial_t, serial)
+ __field(rxrpc_seq_t, seq)
+ __field(enum rxrpc_tlp_probe_trace, trace)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->serial = call->tlp_serial;
+ __entry->seq = call->tlp_seq;
+ __entry->trace = trace;
+ ),
+
+ TP_printk("c=%08x r=%08x pq=%08x %s",
+ __entry->call, __entry->serial, __entry->seq,
+ __print_symbolic(__entry->trace, rxrpc_tlp_probe_traces))
+ );
+
+TRACE_EVENT(rxrpc_tlp_ack,
+ TP_PROTO(struct rxrpc_call *call, struct rxrpc_ack_summary *summary,
+ enum rxrpc_tlp_ack_trace trace),
+
+ TP_ARGS(call, summary, trace),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(rxrpc_serial_t, serial)
+ __field(rxrpc_seq_t, tlp_seq)
+ __field(rxrpc_seq_t, hard_ack)
+ __field(enum rxrpc_tlp_ack_trace, trace)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->serial = call->tlp_serial;
+ __entry->tlp_seq = call->tlp_seq;
+ __entry->hard_ack = call->acks_hard_ack;
+ __entry->trace = trace;
+ ),
+
+ TP_printk("c=%08x r=%08x pq=%08x hq=%08x %s",
+ __entry->call, __entry->serial,
+ __entry->tlp_seq, __entry->hard_ack,
+ __print_symbolic(__entry->trace, rxrpc_tlp_ack_traces))
+ );
+
+TRACE_EVENT(rxrpc_rack_timer,
+ TP_PROTO(struct rxrpc_call *call, ktime_t delay, bool exp),
+
+ TP_ARGS(call, delay, exp),
+
+ TP_STRUCT__entry(
+ __field(unsigned int, call)
+ __field(bool, exp)
+ __field(enum rxrpc_rack_timer_mode, mode)
+ __field(ktime_t, delay)
+ ),
+
+ TP_fast_assign(
+ __entry->call = call->debug_id;
+ __entry->exp = exp;
+ __entry->mode = call->rack_timer_mode;
+ __entry->delay = delay;
+ ),
+
+ TP_printk("c=%08x %s %s to=%lld",
+ __entry->call,
+ __entry->exp ? "Exp" : "Set",
+ __print_symbolic(__entry->mode, rxrpc_rack_timer_modes),
+ ktime_to_us(__entry->delay))
+ );
+
#undef EM
#undef E_
diff --git a/include/trace/events/sunrpc.h b/include/trace/events/sunrpc.h
index 5e8495216689..b13dc275ef4a 100644
--- a/include/trace/events/sunrpc.h
+++ b/include/trace/events/sunrpc.h
@@ -719,7 +719,7 @@ TRACE_EVENT(rpc_xdr_overflow,
),
TP_printk(SUNRPC_TRACE_TASK_SPECIFIER
- " %sv%d %s requested=%zu p=%p end=%p xdr=[%p,%zu]/%u/[%p,%zu]/%u\n",
+ " %sv%d %s requested=%zu p=%p end=%p xdr=[%p,%zu]/%u/[%p,%zu]/%u",
__entry->task_id, __entry->client_id,
__get_str(progname), __entry->version, __get_str(procedure),
__entry->requested, __entry->p, __entry->end,
@@ -777,7 +777,7 @@ TRACE_EVENT(rpc_xdr_alignment,
),
TP_printk(SUNRPC_TRACE_TASK_SPECIFIER
- " %sv%d %s offset=%zu copied=%u xdr=[%p,%zu]/%u/[%p,%zu]/%u\n",
+ " %sv%d %s offset=%zu copied=%u xdr=[%p,%zu]/%u/[%p,%zu]/%u",
__entry->task_id, __entry->client_id,
__get_str(progname), __entry->version, __get_str(procedure),
__entry->offset, __entry->copied,
diff --git a/include/uapi/asm-generic/socket.h b/include/uapi/asm-generic/socket.h
index deacfd6dd197..aa5016ff3d91 100644
--- a/include/uapi/asm-generic/socket.h
+++ b/include/uapi/asm-generic/socket.h
@@ -143,6 +143,8 @@
#define SCM_TS_OPT_ID 81
+#define SO_RCVPRIORITY 82
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
diff --git a/include/uapi/linux/ethtool_netlink.h b/include/uapi/linux/ethtool_netlink.h
index 283305f6b063..9c909ce733a5 100644
--- a/include/uapi/linux/ethtool_netlink.h
+++ b/include/uapi/linux/ethtool_netlink.h
@@ -10,545 +10,12 @@
#define _UAPI_LINUX_ETHTOOL_NETLINK_H_
#include <linux/ethtool.h>
-
-/* message types - userspace to kernel */
-enum {
- ETHTOOL_MSG_USER_NONE,
- ETHTOOL_MSG_STRSET_GET,
- ETHTOOL_MSG_LINKINFO_GET,
- ETHTOOL_MSG_LINKINFO_SET,
- ETHTOOL_MSG_LINKMODES_GET,
- ETHTOOL_MSG_LINKMODES_SET,
- ETHTOOL_MSG_LINKSTATE_GET,
- ETHTOOL_MSG_DEBUG_GET,
- ETHTOOL_MSG_DEBUG_SET,
- ETHTOOL_MSG_WOL_GET,
- ETHTOOL_MSG_WOL_SET,
- ETHTOOL_MSG_FEATURES_GET,
- ETHTOOL_MSG_FEATURES_SET,
- ETHTOOL_MSG_PRIVFLAGS_GET,
- ETHTOOL_MSG_PRIVFLAGS_SET,
- ETHTOOL_MSG_RINGS_GET,
- ETHTOOL_MSG_RINGS_SET,
- ETHTOOL_MSG_CHANNELS_GET,
- ETHTOOL_MSG_CHANNELS_SET,
- ETHTOOL_MSG_COALESCE_GET,
- ETHTOOL_MSG_COALESCE_SET,
- ETHTOOL_MSG_PAUSE_GET,
- ETHTOOL_MSG_PAUSE_SET,
- ETHTOOL_MSG_EEE_GET,
- ETHTOOL_MSG_EEE_SET,
- ETHTOOL_MSG_TSINFO_GET,
- ETHTOOL_MSG_CABLE_TEST_ACT,
- ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
- ETHTOOL_MSG_TUNNEL_INFO_GET,
- ETHTOOL_MSG_FEC_GET,
- ETHTOOL_MSG_FEC_SET,
- ETHTOOL_MSG_MODULE_EEPROM_GET,
- ETHTOOL_MSG_STATS_GET,
- ETHTOOL_MSG_PHC_VCLOCKS_GET,
- ETHTOOL_MSG_MODULE_GET,
- ETHTOOL_MSG_MODULE_SET,
- ETHTOOL_MSG_PSE_GET,
- ETHTOOL_MSG_PSE_SET,
- ETHTOOL_MSG_RSS_GET,
- ETHTOOL_MSG_PLCA_GET_CFG,
- ETHTOOL_MSG_PLCA_SET_CFG,
- ETHTOOL_MSG_PLCA_GET_STATUS,
- ETHTOOL_MSG_MM_GET,
- ETHTOOL_MSG_MM_SET,
- ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
- ETHTOOL_MSG_PHY_GET,
-
- /* add new constants above here */
- __ETHTOOL_MSG_USER_CNT,
- ETHTOOL_MSG_USER_MAX = __ETHTOOL_MSG_USER_CNT - 1
-};
-
-/* message types - kernel to userspace */
-enum {
- ETHTOOL_MSG_KERNEL_NONE,
- ETHTOOL_MSG_STRSET_GET_REPLY,
- ETHTOOL_MSG_LINKINFO_GET_REPLY,
- ETHTOOL_MSG_LINKINFO_NTF,
- ETHTOOL_MSG_LINKMODES_GET_REPLY,
- ETHTOOL_MSG_LINKMODES_NTF,
- ETHTOOL_MSG_LINKSTATE_GET_REPLY,
- ETHTOOL_MSG_DEBUG_GET_REPLY,
- ETHTOOL_MSG_DEBUG_NTF,
- ETHTOOL_MSG_WOL_GET_REPLY,
- ETHTOOL_MSG_WOL_NTF,
- ETHTOOL_MSG_FEATURES_GET_REPLY,
- ETHTOOL_MSG_FEATURES_SET_REPLY,
- ETHTOOL_MSG_FEATURES_NTF,
- ETHTOOL_MSG_PRIVFLAGS_GET_REPLY,
- ETHTOOL_MSG_PRIVFLAGS_NTF,
- ETHTOOL_MSG_RINGS_GET_REPLY,
- ETHTOOL_MSG_RINGS_NTF,
- ETHTOOL_MSG_CHANNELS_GET_REPLY,
- ETHTOOL_MSG_CHANNELS_NTF,
- ETHTOOL_MSG_COALESCE_GET_REPLY,
- ETHTOOL_MSG_COALESCE_NTF,
- ETHTOOL_MSG_PAUSE_GET_REPLY,
- ETHTOOL_MSG_PAUSE_NTF,
- ETHTOOL_MSG_EEE_GET_REPLY,
- ETHTOOL_MSG_EEE_NTF,
- ETHTOOL_MSG_TSINFO_GET_REPLY,
- ETHTOOL_MSG_CABLE_TEST_NTF,
- ETHTOOL_MSG_CABLE_TEST_TDR_NTF,
- ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY,
- ETHTOOL_MSG_FEC_GET_REPLY,
- ETHTOOL_MSG_FEC_NTF,
- ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY,
- ETHTOOL_MSG_STATS_GET_REPLY,
- ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY,
- ETHTOOL_MSG_MODULE_GET_REPLY,
- ETHTOOL_MSG_MODULE_NTF,
- ETHTOOL_MSG_PSE_GET_REPLY,
- ETHTOOL_MSG_RSS_GET_REPLY,
- ETHTOOL_MSG_PLCA_GET_CFG_REPLY,
- ETHTOOL_MSG_PLCA_GET_STATUS_REPLY,
- ETHTOOL_MSG_PLCA_NTF,
- ETHTOOL_MSG_MM_GET_REPLY,
- ETHTOOL_MSG_MM_NTF,
- ETHTOOL_MSG_MODULE_FW_FLASH_NTF,
- ETHTOOL_MSG_PHY_GET_REPLY,
- ETHTOOL_MSG_PHY_NTF,
-
- /* add new constants above here */
- __ETHTOOL_MSG_KERNEL_CNT,
- ETHTOOL_MSG_KERNEL_MAX = __ETHTOOL_MSG_KERNEL_CNT - 1
-};
-
-/* request header */
-
-enum ethtool_header_flags {
- ETHTOOL_FLAG_COMPACT_BITSETS = 1 << 0, /* use compact bitsets in reply */
- ETHTOOL_FLAG_OMIT_REPLY = 1 << 1, /* provide optional reply for SET or ACT requests */
- ETHTOOL_FLAG_STATS = 1 << 2, /* request statistics, if supported by the driver */
-};
+#include <linux/ethtool_netlink_generated.h>
#define ETHTOOL_FLAG_ALL (ETHTOOL_FLAG_COMPACT_BITSETS | \
ETHTOOL_FLAG_OMIT_REPLY | \
ETHTOOL_FLAG_STATS)
-enum {
- ETHTOOL_A_HEADER_UNSPEC,
- ETHTOOL_A_HEADER_DEV_INDEX, /* u32 */
- ETHTOOL_A_HEADER_DEV_NAME, /* string */
- ETHTOOL_A_HEADER_FLAGS, /* u32 - ETHTOOL_FLAG_* */
- ETHTOOL_A_HEADER_PHY_INDEX, /* u32 */
-
- /* add new constants above here */
- __ETHTOOL_A_HEADER_CNT,
- ETHTOOL_A_HEADER_MAX = __ETHTOOL_A_HEADER_CNT - 1
-};
-
-/* bit sets */
-
-enum {
- ETHTOOL_A_BITSET_BIT_UNSPEC,
- ETHTOOL_A_BITSET_BIT_INDEX, /* u32 */
- ETHTOOL_A_BITSET_BIT_NAME, /* string */
- ETHTOOL_A_BITSET_BIT_VALUE, /* flag */
-
- /* add new constants above here */
- __ETHTOOL_A_BITSET_BIT_CNT,
- ETHTOOL_A_BITSET_BIT_MAX = __ETHTOOL_A_BITSET_BIT_CNT - 1
-};
-
-enum {
- ETHTOOL_A_BITSET_BITS_UNSPEC,
- ETHTOOL_A_BITSET_BITS_BIT, /* nest - _A_BITSET_BIT_* */
-
- /* add new constants above here */
- __ETHTOOL_A_BITSET_BITS_CNT,
- ETHTOOL_A_BITSET_BITS_MAX = __ETHTOOL_A_BITSET_BITS_CNT - 1
-};
-
-enum {
- ETHTOOL_A_BITSET_UNSPEC,
- ETHTOOL_A_BITSET_NOMASK, /* flag */
- ETHTOOL_A_BITSET_SIZE, /* u32 */
- ETHTOOL_A_BITSET_BITS, /* nest - _A_BITSET_BITS_* */
- ETHTOOL_A_BITSET_VALUE, /* binary */
- ETHTOOL_A_BITSET_MASK, /* binary */
-
- /* add new constants above here */
- __ETHTOOL_A_BITSET_CNT,
- ETHTOOL_A_BITSET_MAX = __ETHTOOL_A_BITSET_CNT - 1
-};
-
-/* string sets */
-
-enum {
- ETHTOOL_A_STRING_UNSPEC,
- ETHTOOL_A_STRING_INDEX, /* u32 */
- ETHTOOL_A_STRING_VALUE, /* string */
-
- /* add new constants above here */
- __ETHTOOL_A_STRING_CNT,
- ETHTOOL_A_STRING_MAX = __ETHTOOL_A_STRING_CNT - 1
-};
-
-enum {
- ETHTOOL_A_STRINGS_UNSPEC,
- ETHTOOL_A_STRINGS_STRING, /* nest - _A_STRINGS_* */
-
- /* add new constants above here */
- __ETHTOOL_A_STRINGS_CNT,
- ETHTOOL_A_STRINGS_MAX = __ETHTOOL_A_STRINGS_CNT - 1
-};
-
-enum {
- ETHTOOL_A_STRINGSET_UNSPEC,
- ETHTOOL_A_STRINGSET_ID, /* u32 */
- ETHTOOL_A_STRINGSET_COUNT, /* u32 */
- ETHTOOL_A_STRINGSET_STRINGS, /* nest - _A_STRINGS_* */
-
- /* add new constants above here */
- __ETHTOOL_A_STRINGSET_CNT,
- ETHTOOL_A_STRINGSET_MAX = __ETHTOOL_A_STRINGSET_CNT - 1
-};
-
-enum {
- ETHTOOL_A_STRINGSETS_UNSPEC,
- ETHTOOL_A_STRINGSETS_STRINGSET, /* nest - _A_STRINGSET_* */
-
- /* add new constants above here */
- __ETHTOOL_A_STRINGSETS_CNT,
- ETHTOOL_A_STRINGSETS_MAX = __ETHTOOL_A_STRINGSETS_CNT - 1
-};
-
-/* STRSET */
-
-enum {
- ETHTOOL_A_STRSET_UNSPEC,
- ETHTOOL_A_STRSET_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_STRSET_STRINGSETS, /* nest - _A_STRINGSETS_* */
- ETHTOOL_A_STRSET_COUNTS_ONLY, /* flag */
-
- /* add new constants above here */
- __ETHTOOL_A_STRSET_CNT,
- ETHTOOL_A_STRSET_MAX = __ETHTOOL_A_STRSET_CNT - 1
-};
-
-/* LINKINFO */
-
-enum {
- ETHTOOL_A_LINKINFO_UNSPEC,
- ETHTOOL_A_LINKINFO_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_LINKINFO_PORT, /* u8 */
- ETHTOOL_A_LINKINFO_PHYADDR, /* u8 */
- ETHTOOL_A_LINKINFO_TP_MDIX, /* u8 */
- ETHTOOL_A_LINKINFO_TP_MDIX_CTRL, /* u8 */
- ETHTOOL_A_LINKINFO_TRANSCEIVER, /* u8 */
-
- /* add new constants above here */
- __ETHTOOL_A_LINKINFO_CNT,
- ETHTOOL_A_LINKINFO_MAX = __ETHTOOL_A_LINKINFO_CNT - 1
-};
-
-/* LINKMODES */
-
-enum {
- ETHTOOL_A_LINKMODES_UNSPEC,
- ETHTOOL_A_LINKMODES_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_LINKMODES_AUTONEG, /* u8 */
- ETHTOOL_A_LINKMODES_OURS, /* bitset */
- ETHTOOL_A_LINKMODES_PEER, /* bitset */
- ETHTOOL_A_LINKMODES_SPEED, /* u32 */
- ETHTOOL_A_LINKMODES_DUPLEX, /* u8 */
- ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, /* u8 */
- ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, /* u8 */
- ETHTOOL_A_LINKMODES_LANES, /* u32 */
- ETHTOOL_A_LINKMODES_RATE_MATCHING, /* u8 */
-
- /* add new constants above here */
- __ETHTOOL_A_LINKMODES_CNT,
- ETHTOOL_A_LINKMODES_MAX = __ETHTOOL_A_LINKMODES_CNT - 1
-};
-
-/* LINKSTATE */
-
-enum {
- ETHTOOL_A_LINKSTATE_UNSPEC,
- ETHTOOL_A_LINKSTATE_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_LINKSTATE_LINK, /* u8 */
- ETHTOOL_A_LINKSTATE_SQI, /* u32 */
- ETHTOOL_A_LINKSTATE_SQI_MAX, /* u32 */
- ETHTOOL_A_LINKSTATE_EXT_STATE, /* u8 */
- ETHTOOL_A_LINKSTATE_EXT_SUBSTATE, /* u8 */
- ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT, /* u32 */
-
- /* add new constants above here */
- __ETHTOOL_A_LINKSTATE_CNT,
- ETHTOOL_A_LINKSTATE_MAX = __ETHTOOL_A_LINKSTATE_CNT - 1
-};
-
-/* DEBUG */
-
-enum {
- ETHTOOL_A_DEBUG_UNSPEC,
- ETHTOOL_A_DEBUG_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_DEBUG_MSGMASK, /* bitset */
-
- /* add new constants above here */
- __ETHTOOL_A_DEBUG_CNT,
- ETHTOOL_A_DEBUG_MAX = __ETHTOOL_A_DEBUG_CNT - 1
-};
-
-/* WOL */
-
-enum {
- ETHTOOL_A_WOL_UNSPEC,
- ETHTOOL_A_WOL_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_WOL_MODES, /* bitset */
- ETHTOOL_A_WOL_SOPASS, /* binary */
-
- /* add new constants above here */
- __ETHTOOL_A_WOL_CNT,
- ETHTOOL_A_WOL_MAX = __ETHTOOL_A_WOL_CNT - 1
-};
-
-/* FEATURES */
-
-enum {
- ETHTOOL_A_FEATURES_UNSPEC,
- ETHTOOL_A_FEATURES_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_FEATURES_HW, /* bitset */
- ETHTOOL_A_FEATURES_WANTED, /* bitset */
- ETHTOOL_A_FEATURES_ACTIVE, /* bitset */
- ETHTOOL_A_FEATURES_NOCHANGE, /* bitset */
-
- /* add new constants above here */
- __ETHTOOL_A_FEATURES_CNT,
- ETHTOOL_A_FEATURES_MAX = __ETHTOOL_A_FEATURES_CNT - 1
-};
-
-/* PRIVFLAGS */
-
-enum {
- ETHTOOL_A_PRIVFLAGS_UNSPEC,
- ETHTOOL_A_PRIVFLAGS_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_PRIVFLAGS_FLAGS, /* bitset */
-
- /* add new constants above here */
- __ETHTOOL_A_PRIVFLAGS_CNT,
- ETHTOOL_A_PRIVFLAGS_MAX = __ETHTOOL_A_PRIVFLAGS_CNT - 1
-};
-
-/* RINGS */
-
-enum {
- ETHTOOL_TCP_DATA_SPLIT_UNKNOWN = 0,
- ETHTOOL_TCP_DATA_SPLIT_DISABLED,
- ETHTOOL_TCP_DATA_SPLIT_ENABLED,
-};
-
-enum {
- ETHTOOL_A_RINGS_UNSPEC,
- ETHTOOL_A_RINGS_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_RINGS_RX_MAX, /* u32 */
- ETHTOOL_A_RINGS_RX_MINI_MAX, /* u32 */
- ETHTOOL_A_RINGS_RX_JUMBO_MAX, /* u32 */
- ETHTOOL_A_RINGS_TX_MAX, /* u32 */
- ETHTOOL_A_RINGS_RX, /* u32 */
- ETHTOOL_A_RINGS_RX_MINI, /* u32 */
- ETHTOOL_A_RINGS_RX_JUMBO, /* u32 */
- ETHTOOL_A_RINGS_TX, /* u32 */
- ETHTOOL_A_RINGS_RX_BUF_LEN, /* u32 */
- ETHTOOL_A_RINGS_TCP_DATA_SPLIT, /* u8 */
- ETHTOOL_A_RINGS_CQE_SIZE, /* u32 */
- ETHTOOL_A_RINGS_TX_PUSH, /* u8 */
- ETHTOOL_A_RINGS_RX_PUSH, /* u8 */
- ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN, /* u32 */
- ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX, /* u32 */
-
- /* add new constants above here */
- __ETHTOOL_A_RINGS_CNT,
- ETHTOOL_A_RINGS_MAX = (__ETHTOOL_A_RINGS_CNT - 1)
-};
-
-/* CHANNELS */
-
-enum {
- ETHTOOL_A_CHANNELS_UNSPEC,
- ETHTOOL_A_CHANNELS_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_CHANNELS_RX_MAX, /* u32 */
- ETHTOOL_A_CHANNELS_TX_MAX, /* u32 */
- ETHTOOL_A_CHANNELS_OTHER_MAX, /* u32 */
- ETHTOOL_A_CHANNELS_COMBINED_MAX, /* u32 */
- ETHTOOL_A_CHANNELS_RX_COUNT, /* u32 */
- ETHTOOL_A_CHANNELS_TX_COUNT, /* u32 */
- ETHTOOL_A_CHANNELS_OTHER_COUNT, /* u32 */
- ETHTOOL_A_CHANNELS_COMBINED_COUNT, /* u32 */
-
- /* add new constants above here */
- __ETHTOOL_A_CHANNELS_CNT,
- ETHTOOL_A_CHANNELS_MAX = (__ETHTOOL_A_CHANNELS_CNT - 1)
-};
-
-/* COALESCE */
-
-enum {
- ETHTOOL_A_COALESCE_UNSPEC,
- ETHTOOL_A_COALESCE_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_COALESCE_RX_USECS, /* u32 */
- ETHTOOL_A_COALESCE_RX_MAX_FRAMES, /* u32 */
- ETHTOOL_A_COALESCE_RX_USECS_IRQ, /* u32 */
- ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ, /* u32 */
- ETHTOOL_A_COALESCE_TX_USECS, /* u32 */
- ETHTOOL_A_COALESCE_TX_MAX_FRAMES, /* u32 */
- ETHTOOL_A_COALESCE_TX_USECS_IRQ, /* u32 */
- ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ, /* u32 */
- ETHTOOL_A_COALESCE_STATS_BLOCK_USECS, /* u32 */
- ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX, /* u8 */
- ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX, /* u8 */
- ETHTOOL_A_COALESCE_PKT_RATE_LOW, /* u32 */
- ETHTOOL_A_COALESCE_RX_USECS_LOW, /* u32 */
- ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW, /* u32 */
- ETHTOOL_A_COALESCE_TX_USECS_LOW, /* u32 */
- ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW, /* u32 */
- ETHTOOL_A_COALESCE_PKT_RATE_HIGH, /* u32 */
- ETHTOOL_A_COALESCE_RX_USECS_HIGH, /* u32 */
- ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH, /* u32 */
- ETHTOOL_A_COALESCE_TX_USECS_HIGH, /* u32 */
- ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH, /* u32 */
- ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL, /* u32 */
- ETHTOOL_A_COALESCE_USE_CQE_MODE_TX, /* u8 */
- ETHTOOL_A_COALESCE_USE_CQE_MODE_RX, /* u8 */
- ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES, /* u32 */
- ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES, /* u32 */
- ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS, /* u32 */
- /* nest - _A_PROFILE_IRQ_MODERATION */
- ETHTOOL_A_COALESCE_RX_PROFILE,
- /* nest - _A_PROFILE_IRQ_MODERATION */
- ETHTOOL_A_COALESCE_TX_PROFILE,
-
- /* add new constants above here */
- __ETHTOOL_A_COALESCE_CNT,
- ETHTOOL_A_COALESCE_MAX = (__ETHTOOL_A_COALESCE_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_PROFILE_UNSPEC,
- /* nest, _A_IRQ_MODERATION_* */
- ETHTOOL_A_PROFILE_IRQ_MODERATION,
- __ETHTOOL_A_PROFILE_CNT,
- ETHTOOL_A_PROFILE_MAX = (__ETHTOOL_A_PROFILE_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_IRQ_MODERATION_UNSPEC,
- ETHTOOL_A_IRQ_MODERATION_USEC, /* u32 */
- ETHTOOL_A_IRQ_MODERATION_PKTS, /* u32 */
- ETHTOOL_A_IRQ_MODERATION_COMPS, /* u32 */
-
- __ETHTOOL_A_IRQ_MODERATION_CNT,
- ETHTOOL_A_IRQ_MODERATION_MAX = (__ETHTOOL_A_IRQ_MODERATION_CNT - 1)
-};
-
-/* PAUSE */
-
-enum {
- ETHTOOL_A_PAUSE_UNSPEC,
- ETHTOOL_A_PAUSE_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_PAUSE_AUTONEG, /* u8 */
- ETHTOOL_A_PAUSE_RX, /* u8 */
- ETHTOOL_A_PAUSE_TX, /* u8 */
- ETHTOOL_A_PAUSE_STATS, /* nest - _PAUSE_STAT_* */
- ETHTOOL_A_PAUSE_STATS_SRC, /* u32 */
-
- /* add new constants above here */
- __ETHTOOL_A_PAUSE_CNT,
- ETHTOOL_A_PAUSE_MAX = (__ETHTOOL_A_PAUSE_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_PAUSE_STAT_UNSPEC,
- ETHTOOL_A_PAUSE_STAT_PAD,
-
- ETHTOOL_A_PAUSE_STAT_TX_FRAMES,
- ETHTOOL_A_PAUSE_STAT_RX_FRAMES,
-
- /* add new constants above here
- * adjust ETHTOOL_PAUSE_STAT_CNT if adding non-stats!
- */
- __ETHTOOL_A_PAUSE_STAT_CNT,
- ETHTOOL_A_PAUSE_STAT_MAX = (__ETHTOOL_A_PAUSE_STAT_CNT - 1)
-};
-
-/* EEE */
-
-enum {
- ETHTOOL_A_EEE_UNSPEC,
- ETHTOOL_A_EEE_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_EEE_MODES_OURS, /* bitset */
- ETHTOOL_A_EEE_MODES_PEER, /* bitset */
- ETHTOOL_A_EEE_ACTIVE, /* u8 */
- ETHTOOL_A_EEE_ENABLED, /* u8 */
- ETHTOOL_A_EEE_TX_LPI_ENABLED, /* u8 */
- ETHTOOL_A_EEE_TX_LPI_TIMER, /* u32 */
-
- /* add new constants above here */
- __ETHTOOL_A_EEE_CNT,
- ETHTOOL_A_EEE_MAX = (__ETHTOOL_A_EEE_CNT - 1)
-};
-
-/* TSINFO */
-
-enum {
- ETHTOOL_A_TSINFO_UNSPEC,
- ETHTOOL_A_TSINFO_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_TSINFO_TIMESTAMPING, /* bitset */
- ETHTOOL_A_TSINFO_TX_TYPES, /* bitset */
- ETHTOOL_A_TSINFO_RX_FILTERS, /* bitset */
- ETHTOOL_A_TSINFO_PHC_INDEX, /* u32 */
- ETHTOOL_A_TSINFO_STATS, /* nest - _A_TSINFO_STAT */
-
- /* add new constants above here */
- __ETHTOOL_A_TSINFO_CNT,
- ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_TS_STAT_UNSPEC,
-
- ETHTOOL_A_TS_STAT_TX_PKTS, /* uint */
- ETHTOOL_A_TS_STAT_TX_LOST, /* uint */
- ETHTOOL_A_TS_STAT_TX_ERR, /* uint */
-
- /* add new constants above here */
- __ETHTOOL_A_TS_STAT_CNT,
- ETHTOOL_A_TS_STAT_MAX = (__ETHTOOL_A_TS_STAT_CNT - 1)
-
-};
-
-/* PHC VCLOCKS */
-
-enum {
- ETHTOOL_A_PHC_VCLOCKS_UNSPEC,
- ETHTOOL_A_PHC_VCLOCKS_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_PHC_VCLOCKS_NUM, /* u32 */
- ETHTOOL_A_PHC_VCLOCKS_INDEX, /* array, s32 */
-
- /* add new constants above here */
- __ETHTOOL_A_PHC_VCLOCKS_CNT,
- ETHTOOL_A_PHC_VCLOCKS_MAX = (__ETHTOOL_A_PHC_VCLOCKS_CNT - 1)
-};
-
-/* CABLE TEST */
-
-enum {
- ETHTOOL_A_CABLE_TEST_UNSPEC,
- ETHTOOL_A_CABLE_TEST_HEADER, /* nest - _A_HEADER_* */
-
- /* add new constants above here */
- __ETHTOOL_A_CABLE_TEST_CNT,
- ETHTOOL_A_CABLE_TEST_MAX = __ETHTOOL_A_CABLE_TEST_CNT - 1
-};
-
/* CABLE TEST NOTIFY */
enum {
ETHTOOL_A_CABLE_RESULT_CODE_UNSPEC,
@@ -583,73 +50,11 @@ enum {
};
enum {
- ETHTOOL_A_CABLE_RESULT_UNSPEC,
- ETHTOOL_A_CABLE_RESULT_PAIR, /* u8 ETHTOOL_A_CABLE_PAIR_ */
- ETHTOOL_A_CABLE_RESULT_CODE, /* u8 ETHTOOL_A_CABLE_RESULT_CODE_ */
- ETHTOOL_A_CABLE_RESULT_SRC, /* u32 ETHTOOL_A_CABLE_INF_SRC_ */
-
- __ETHTOOL_A_CABLE_RESULT_CNT,
- ETHTOOL_A_CABLE_RESULT_MAX = (__ETHTOOL_A_CABLE_RESULT_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_CABLE_FAULT_LENGTH_UNSPEC,
- ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR, /* u8 ETHTOOL_A_CABLE_PAIR_ */
- ETHTOOL_A_CABLE_FAULT_LENGTH_CM, /* u32 */
- ETHTOOL_A_CABLE_FAULT_LENGTH_SRC, /* u32 ETHTOOL_A_CABLE_INF_SRC_ */
-
- __ETHTOOL_A_CABLE_FAULT_LENGTH_CNT,
- ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = (__ETHTOOL_A_CABLE_FAULT_LENGTH_CNT - 1)
-};
-
-enum {
ETHTOOL_A_CABLE_TEST_NTF_STATUS_UNSPEC,
ETHTOOL_A_CABLE_TEST_NTF_STATUS_STARTED,
ETHTOOL_A_CABLE_TEST_NTF_STATUS_COMPLETED
};
-enum {
- ETHTOOL_A_CABLE_NEST_UNSPEC,
- ETHTOOL_A_CABLE_NEST_RESULT, /* nest - ETHTOOL_A_CABLE_RESULT_ */
- ETHTOOL_A_CABLE_NEST_FAULT_LENGTH, /* nest - ETHTOOL_A_CABLE_FAULT_LENGTH_ */
- __ETHTOOL_A_CABLE_NEST_CNT,
- ETHTOOL_A_CABLE_NEST_MAX = (__ETHTOOL_A_CABLE_NEST_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_CABLE_TEST_NTF_UNSPEC,
- ETHTOOL_A_CABLE_TEST_NTF_HEADER, /* nest - ETHTOOL_A_HEADER_* */
- ETHTOOL_A_CABLE_TEST_NTF_STATUS, /* u8 - _STARTED/_COMPLETE */
- ETHTOOL_A_CABLE_TEST_NTF_NEST, /* nest - of results: */
-
- __ETHTOOL_A_CABLE_TEST_NTF_CNT,
- ETHTOOL_A_CABLE_TEST_NTF_MAX = (__ETHTOOL_A_CABLE_TEST_NTF_CNT - 1)
-};
-
-/* CABLE TEST TDR */
-
-enum {
- ETHTOOL_A_CABLE_TEST_TDR_CFG_UNSPEC,
- ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST, /* u32 */
- ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST, /* u32 */
- ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP, /* u32 */
- ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR, /* u8 */
-
- /* add new constants above here */
- __ETHTOOL_A_CABLE_TEST_TDR_CFG_CNT,
- ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX = __ETHTOOL_A_CABLE_TEST_TDR_CFG_CNT - 1
-};
-
-enum {
- ETHTOOL_A_CABLE_TEST_TDR_UNSPEC,
- ETHTOOL_A_CABLE_TEST_TDR_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_CABLE_TEST_TDR_CFG, /* nest - *_TDR_CFG_* */
-
- /* add new constants above here */
- __ETHTOOL_A_CABLE_TEST_TDR_CNT,
- ETHTOOL_A_CABLE_TEST_TDR_MAX = __ETHTOOL_A_CABLE_TEST_TDR_CNT - 1
-};
-
/* CABLE TEST TDR NOTIFY */
enum {
@@ -690,132 +95,6 @@ enum {
};
enum {
- ETHTOOL_A_CABLE_TEST_TDR_NTF_UNSPEC,
- ETHTOOL_A_CABLE_TEST_TDR_NTF_HEADER, /* nest - ETHTOOL_A_HEADER_* */
- ETHTOOL_A_CABLE_TEST_TDR_NTF_STATUS, /* u8 - _STARTED/_COMPLETE */
- ETHTOOL_A_CABLE_TEST_TDR_NTF_NEST, /* nest - of results: */
-
- /* add new constants above here */
- __ETHTOOL_A_CABLE_TEST_TDR_NTF_CNT,
- ETHTOOL_A_CABLE_TEST_TDR_NTF_MAX = __ETHTOOL_A_CABLE_TEST_TDR_NTF_CNT - 1
-};
-
-/* TUNNEL INFO */
-
-enum {
- ETHTOOL_UDP_TUNNEL_TYPE_VXLAN,
- ETHTOOL_UDP_TUNNEL_TYPE_GENEVE,
- ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE,
-
- __ETHTOOL_UDP_TUNNEL_TYPE_CNT
-};
-
-enum {
- ETHTOOL_A_TUNNEL_UDP_ENTRY_UNSPEC,
-
- ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT, /* be16 */
- ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE, /* u32 */
-
- /* add new constants above here */
- __ETHTOOL_A_TUNNEL_UDP_ENTRY_CNT,
- ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX = (__ETHTOOL_A_TUNNEL_UDP_ENTRY_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_TUNNEL_UDP_TABLE_UNSPEC,
-
- ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE, /* u32 */
- ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES, /* bitset */
- ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY, /* nest - _UDP_ENTRY_* */
-
- /* add new constants above here */
- __ETHTOOL_A_TUNNEL_UDP_TABLE_CNT,
- ETHTOOL_A_TUNNEL_UDP_TABLE_MAX = (__ETHTOOL_A_TUNNEL_UDP_TABLE_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_TUNNEL_UDP_UNSPEC,
-
- ETHTOOL_A_TUNNEL_UDP_TABLE, /* nest - _UDP_TABLE_* */
-
- /* add new constants above here */
- __ETHTOOL_A_TUNNEL_UDP_CNT,
- ETHTOOL_A_TUNNEL_UDP_MAX = (__ETHTOOL_A_TUNNEL_UDP_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_TUNNEL_INFO_UNSPEC,
- ETHTOOL_A_TUNNEL_INFO_HEADER, /* nest - _A_HEADER_* */
-
- ETHTOOL_A_TUNNEL_INFO_UDP_PORTS, /* nest - _UDP_TABLE */
-
- /* add new constants above here */
- __ETHTOOL_A_TUNNEL_INFO_CNT,
- ETHTOOL_A_TUNNEL_INFO_MAX = (__ETHTOOL_A_TUNNEL_INFO_CNT - 1)
-};
-
-/* FEC */
-
-enum {
- ETHTOOL_A_FEC_UNSPEC,
- ETHTOOL_A_FEC_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_FEC_MODES, /* bitset */
- ETHTOOL_A_FEC_AUTO, /* u8 */
- ETHTOOL_A_FEC_ACTIVE, /* u32 */
- ETHTOOL_A_FEC_STATS, /* nest - _A_FEC_STAT */
-
- __ETHTOOL_A_FEC_CNT,
- ETHTOOL_A_FEC_MAX = (__ETHTOOL_A_FEC_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_FEC_STAT_UNSPEC,
- ETHTOOL_A_FEC_STAT_PAD,
-
- ETHTOOL_A_FEC_STAT_CORRECTED, /* array, u64 */
- ETHTOOL_A_FEC_STAT_UNCORR, /* array, u64 */
- ETHTOOL_A_FEC_STAT_CORR_BITS, /* array, u64 */
-
- /* add new constants above here */
- __ETHTOOL_A_FEC_STAT_CNT,
- ETHTOOL_A_FEC_STAT_MAX = (__ETHTOOL_A_FEC_STAT_CNT - 1)
-};
-
-/* MODULE EEPROM */
-
-enum {
- ETHTOOL_A_MODULE_EEPROM_UNSPEC,
- ETHTOOL_A_MODULE_EEPROM_HEADER, /* nest - _A_HEADER_* */
-
- ETHTOOL_A_MODULE_EEPROM_OFFSET, /* u32 */
- ETHTOOL_A_MODULE_EEPROM_LENGTH, /* u32 */
- ETHTOOL_A_MODULE_EEPROM_PAGE, /* u8 */
- ETHTOOL_A_MODULE_EEPROM_BANK, /* u8 */
- ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS, /* u8 */
- ETHTOOL_A_MODULE_EEPROM_DATA, /* binary */
-
- __ETHTOOL_A_MODULE_EEPROM_CNT,
- ETHTOOL_A_MODULE_EEPROM_MAX = (__ETHTOOL_A_MODULE_EEPROM_CNT - 1)
-};
-
-/* STATS */
-
-enum {
- ETHTOOL_A_STATS_UNSPEC,
- ETHTOOL_A_STATS_PAD,
- ETHTOOL_A_STATS_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_STATS_GROUPS, /* bitset */
-
- ETHTOOL_A_STATS_GRP, /* nest - _A_STATS_GRP_* */
-
- ETHTOOL_A_STATS_SRC, /* u32 */
-
- /* add new constants above here */
- __ETHTOOL_A_STATS_CNT,
- ETHTOOL_A_STATS_MAX = (__ETHTOOL_A_STATS_CNT - 1)
-};
-
-enum {
ETHTOOL_STATS_ETH_PHY,
ETHTOOL_STATS_ETH_MAC,
ETHTOOL_STATS_ETH_CTRL,
@@ -826,27 +105,6 @@ enum {
};
enum {
- ETHTOOL_A_STATS_GRP_UNSPEC,
- ETHTOOL_A_STATS_GRP_PAD,
-
- ETHTOOL_A_STATS_GRP_ID, /* u32 */
- ETHTOOL_A_STATS_GRP_SS_ID, /* u32 */
-
- ETHTOOL_A_STATS_GRP_STAT, /* nest */
-
- ETHTOOL_A_STATS_GRP_HIST_RX, /* nest */
- ETHTOOL_A_STATS_GRP_HIST_TX, /* nest */
-
- ETHTOOL_A_STATS_GRP_HIST_BKT_LOW, /* u32 */
- ETHTOOL_A_STATS_GRP_HIST_BKT_HI, /* u32 */
- ETHTOOL_A_STATS_GRP_HIST_VAL, /* u64 */
-
- /* add new constants above here */
- __ETHTOOL_A_STATS_GRP_CNT,
- ETHTOOL_A_STATS_GRP_MAX = (__ETHTOOL_A_STATS_GRP_CNT - 1)
-};
-
-enum {
/* 30.3.2.1.5 aSymbolErrorDuringCarrier */
ETHTOOL_A_STATS_ETH_PHY_5_SYM_ERR,
@@ -935,155 +193,6 @@ enum {
ETHTOOL_A_STATS_RMON_MAX = (__ETHTOOL_A_STATS_RMON_CNT - 1)
};
-/* MODULE */
-
-enum {
- ETHTOOL_A_MODULE_UNSPEC,
- ETHTOOL_A_MODULE_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_MODULE_POWER_MODE_POLICY, /* u8 */
- ETHTOOL_A_MODULE_POWER_MODE, /* u8 */
-
- /* add new constants above here */
- __ETHTOOL_A_MODULE_CNT,
- ETHTOOL_A_MODULE_MAX = (__ETHTOOL_A_MODULE_CNT - 1)
-};
-
-/* Power Sourcing Equipment */
-enum {
- ETHTOOL_A_C33_PSE_PW_LIMIT_UNSPEC,
- ETHTOOL_A_C33_PSE_PW_LIMIT_MIN, /* u32 */
- ETHTOOL_A_C33_PSE_PW_LIMIT_MAX, /* u32 */
-};
-
-enum {
- ETHTOOL_A_PSE_UNSPEC,
- ETHTOOL_A_PSE_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_PODL_PSE_ADMIN_STATE, /* u32 */
- ETHTOOL_A_PODL_PSE_ADMIN_CONTROL, /* u32 */
- ETHTOOL_A_PODL_PSE_PW_D_STATUS, /* u32 */
- ETHTOOL_A_C33_PSE_ADMIN_STATE, /* u32 */
- ETHTOOL_A_C33_PSE_ADMIN_CONTROL, /* u32 */
- ETHTOOL_A_C33_PSE_PW_D_STATUS, /* u32 */
- ETHTOOL_A_C33_PSE_PW_CLASS, /* u32 */
- ETHTOOL_A_C33_PSE_ACTUAL_PW, /* u32 */
- ETHTOOL_A_C33_PSE_EXT_STATE, /* u32 */
- ETHTOOL_A_C33_PSE_EXT_SUBSTATE, /* u32 */
- ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT, /* u32 */
- ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES, /* nest - _C33_PSE_PW_LIMIT_* */
-
- /* add new constants above here */
- __ETHTOOL_A_PSE_CNT,
- ETHTOOL_A_PSE_MAX = (__ETHTOOL_A_PSE_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_RSS_UNSPEC,
- ETHTOOL_A_RSS_HEADER,
- ETHTOOL_A_RSS_CONTEXT, /* u32 */
- ETHTOOL_A_RSS_HFUNC, /* u32 */
- ETHTOOL_A_RSS_INDIR, /* binary */
- ETHTOOL_A_RSS_HKEY, /* binary */
- ETHTOOL_A_RSS_INPUT_XFRM, /* u32 */
- ETHTOOL_A_RSS_START_CONTEXT, /* u32 */
-
- __ETHTOOL_A_RSS_CNT,
- ETHTOOL_A_RSS_MAX = (__ETHTOOL_A_RSS_CNT - 1),
-};
-
-/* PLCA */
-
-enum {
- ETHTOOL_A_PLCA_UNSPEC,
- ETHTOOL_A_PLCA_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_PLCA_VERSION, /* u16 */
- ETHTOOL_A_PLCA_ENABLED, /* u8 */
- ETHTOOL_A_PLCA_STATUS, /* u8 */
- ETHTOOL_A_PLCA_NODE_CNT, /* u32 */
- ETHTOOL_A_PLCA_NODE_ID, /* u32 */
- ETHTOOL_A_PLCA_TO_TMR, /* u32 */
- ETHTOOL_A_PLCA_BURST_CNT, /* u32 */
- ETHTOOL_A_PLCA_BURST_TMR, /* u32 */
-
- /* add new constants above here */
- __ETHTOOL_A_PLCA_CNT,
- ETHTOOL_A_PLCA_MAX = (__ETHTOOL_A_PLCA_CNT - 1)
-};
-
-/* MAC Merge (802.3) */
-
-enum {
- ETHTOOL_A_MM_STAT_UNSPEC,
- ETHTOOL_A_MM_STAT_PAD,
-
- /* aMACMergeFrameAssErrorCount */
- ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS, /* u64 */
- /* aMACMergeFrameSmdErrorCount */
- ETHTOOL_A_MM_STAT_SMD_ERRORS, /* u64 */
- /* aMACMergeFrameAssOkCount */
- ETHTOOL_A_MM_STAT_REASSEMBLY_OK, /* u64 */
- /* aMACMergeFragCountRx */
- ETHTOOL_A_MM_STAT_RX_FRAG_COUNT, /* u64 */
- /* aMACMergeFragCountTx */
- ETHTOOL_A_MM_STAT_TX_FRAG_COUNT, /* u64 */
- /* aMACMergeHoldCount */
- ETHTOOL_A_MM_STAT_HOLD_COUNT, /* u64 */
-
- /* add new constants above here */
- __ETHTOOL_A_MM_STAT_CNT,
- ETHTOOL_A_MM_STAT_MAX = (__ETHTOOL_A_MM_STAT_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_MM_UNSPEC,
- ETHTOOL_A_MM_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_MM_PMAC_ENABLED, /* u8 */
- ETHTOOL_A_MM_TX_ENABLED, /* u8 */
- ETHTOOL_A_MM_TX_ACTIVE, /* u8 */
- ETHTOOL_A_MM_TX_MIN_FRAG_SIZE, /* u32 */
- ETHTOOL_A_MM_RX_MIN_FRAG_SIZE, /* u32 */
- ETHTOOL_A_MM_VERIFY_ENABLED, /* u8 */
- ETHTOOL_A_MM_VERIFY_STATUS, /* u8 */
- ETHTOOL_A_MM_VERIFY_TIME, /* u32 */
- ETHTOOL_A_MM_MAX_VERIFY_TIME, /* u32 */
- ETHTOOL_A_MM_STATS, /* nest - _A_MM_STAT_* */
-
- /* add new constants above here */
- __ETHTOOL_A_MM_CNT,
- ETHTOOL_A_MM_MAX = (__ETHTOOL_A_MM_CNT - 1)
-};
-
-/* MODULE_FW_FLASH */
-
-enum {
- ETHTOOL_A_MODULE_FW_FLASH_UNSPEC,
- ETHTOOL_A_MODULE_FW_FLASH_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME, /* string */
- ETHTOOL_A_MODULE_FW_FLASH_PASSWORD, /* u32 */
- ETHTOOL_A_MODULE_FW_FLASH_STATUS, /* u32 */
- ETHTOOL_A_MODULE_FW_FLASH_STATUS_MSG, /* string */
- ETHTOOL_A_MODULE_FW_FLASH_DONE, /* uint */
- ETHTOOL_A_MODULE_FW_FLASH_TOTAL, /* uint */
-
- /* add new constants above here */
- __ETHTOOL_A_MODULE_FW_FLASH_CNT,
- ETHTOOL_A_MODULE_FW_FLASH_MAX = (__ETHTOOL_A_MODULE_FW_FLASH_CNT - 1)
-};
-
-enum {
- ETHTOOL_A_PHY_UNSPEC,
- ETHTOOL_A_PHY_HEADER, /* nest - _A_HEADER_* */
- ETHTOOL_A_PHY_INDEX, /* u32 */
- ETHTOOL_A_PHY_DRVNAME, /* string */
- ETHTOOL_A_PHY_NAME, /* string */
- ETHTOOL_A_PHY_UPSTREAM_TYPE, /* u32 */
- ETHTOOL_A_PHY_UPSTREAM_INDEX, /* u32 */
- ETHTOOL_A_PHY_UPSTREAM_SFP_NAME, /* string */
- ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME, /* string */
-
- /* add new constants above here */
- __ETHTOOL_A_PHY_CNT,
- ETHTOOL_A_PHY_MAX = (__ETHTOOL_A_PHY_CNT - 1)
-};
/* generic netlink info */
#define ETHTOOL_GENL_NAME "ethtool"
diff --git a/include/uapi/linux/ethtool_netlink_generated.h b/include/uapi/linux/ethtool_netlink_generated.h
new file mode 100644
index 000000000000..43993a2d68e5
--- /dev/null
+++ b/include/uapi/linux/ethtool_netlink_generated.h
@@ -0,0 +1,818 @@
+/* SPDX-License-Identifier: ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause) */
+/* Do not edit directly, auto-generated from: */
+/* Documentation/netlink/specs/ethtool.yaml */
+/* YNL-GEN uapi header */
+
+#ifndef _UAPI_LINUX_ETHTOOL_NETLINK_GENERATED_H
+#define _UAPI_LINUX_ETHTOOL_NETLINK_GENERATED_H
+
+#define ETHTOOL_FAMILY_NAME "ethtool"
+#define ETHTOOL_FAMILY_VERSION 1
+
+enum {
+ ETHTOOL_UDP_TUNNEL_TYPE_VXLAN,
+ ETHTOOL_UDP_TUNNEL_TYPE_GENEVE,
+ ETHTOOL_UDP_TUNNEL_TYPE_VXLAN_GPE,
+
+ /* private: */
+ __ETHTOOL_UDP_TUNNEL_TYPE_CNT,
+ ETHTOOL_UDP_TUNNEL_TYPE_MAX = (__ETHTOOL_UDP_TUNNEL_TYPE_CNT - 1)
+};
+
+/**
+ * enum ethtool_header_flags - common ethtool header flags
+ * @ETHTOOL_FLAG_COMPACT_BITSETS: use compact bitsets in reply
+ * @ETHTOOL_FLAG_OMIT_REPLY: provide optional reply for SET or ACT requests
+ * @ETHTOOL_FLAG_STATS: request statistics, if supported by the driver
+ */
+enum ethtool_header_flags {
+ ETHTOOL_FLAG_COMPACT_BITSETS = 1,
+ ETHTOOL_FLAG_OMIT_REPLY = 2,
+ ETHTOOL_FLAG_STATS = 4,
+};
+
+enum {
+ ETHTOOL_PHY_UPSTREAM_TYPE_MAC,
+ ETHTOOL_PHY_UPSTREAM_TYPE_PHY,
+};
+
+enum ethtool_tcp_data_split {
+ ETHTOOL_TCP_DATA_SPLIT_UNKNOWN,
+ ETHTOOL_TCP_DATA_SPLIT_DISABLED,
+ ETHTOOL_TCP_DATA_SPLIT_ENABLED,
+};
+
+enum {
+ ETHTOOL_A_HEADER_UNSPEC,
+ ETHTOOL_A_HEADER_DEV_INDEX,
+ ETHTOOL_A_HEADER_DEV_NAME,
+ ETHTOOL_A_HEADER_FLAGS,
+ ETHTOOL_A_HEADER_PHY_INDEX,
+
+ __ETHTOOL_A_HEADER_CNT,
+ ETHTOOL_A_HEADER_MAX = (__ETHTOOL_A_HEADER_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_BITSET_BIT_UNSPEC,
+ ETHTOOL_A_BITSET_BIT_INDEX,
+ ETHTOOL_A_BITSET_BIT_NAME,
+ ETHTOOL_A_BITSET_BIT_VALUE,
+
+ __ETHTOOL_A_BITSET_BIT_CNT,
+ ETHTOOL_A_BITSET_BIT_MAX = (__ETHTOOL_A_BITSET_BIT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_BITSET_BITS_UNSPEC,
+ ETHTOOL_A_BITSET_BITS_BIT,
+
+ __ETHTOOL_A_BITSET_BITS_CNT,
+ ETHTOOL_A_BITSET_BITS_MAX = (__ETHTOOL_A_BITSET_BITS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_BITSET_UNSPEC,
+ ETHTOOL_A_BITSET_NOMASK,
+ ETHTOOL_A_BITSET_SIZE,
+ ETHTOOL_A_BITSET_BITS,
+ ETHTOOL_A_BITSET_VALUE,
+ ETHTOOL_A_BITSET_MASK,
+
+ __ETHTOOL_A_BITSET_CNT,
+ ETHTOOL_A_BITSET_MAX = (__ETHTOOL_A_BITSET_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STRING_UNSPEC,
+ ETHTOOL_A_STRING_INDEX,
+ ETHTOOL_A_STRING_VALUE,
+
+ __ETHTOOL_A_STRING_CNT,
+ ETHTOOL_A_STRING_MAX = (__ETHTOOL_A_STRING_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STRINGS_UNSPEC,
+ ETHTOOL_A_STRINGS_STRING,
+
+ __ETHTOOL_A_STRINGS_CNT,
+ ETHTOOL_A_STRINGS_MAX = (__ETHTOOL_A_STRINGS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STRINGSET_UNSPEC,
+ ETHTOOL_A_STRINGSET_ID,
+ ETHTOOL_A_STRINGSET_COUNT,
+ ETHTOOL_A_STRINGSET_STRINGS,
+
+ __ETHTOOL_A_STRINGSET_CNT,
+ ETHTOOL_A_STRINGSET_MAX = (__ETHTOOL_A_STRINGSET_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STRINGSETS_UNSPEC,
+ ETHTOOL_A_STRINGSETS_STRINGSET,
+
+ __ETHTOOL_A_STRINGSETS_CNT,
+ ETHTOOL_A_STRINGSETS_MAX = (__ETHTOOL_A_STRINGSETS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STRSET_UNSPEC,
+ ETHTOOL_A_STRSET_HEADER,
+ ETHTOOL_A_STRSET_STRINGSETS,
+ ETHTOOL_A_STRSET_COUNTS_ONLY,
+
+ __ETHTOOL_A_STRSET_CNT,
+ ETHTOOL_A_STRSET_MAX = (__ETHTOOL_A_STRSET_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PRIVFLAGS_UNSPEC,
+ ETHTOOL_A_PRIVFLAGS_HEADER,
+ ETHTOOL_A_PRIVFLAGS_FLAGS,
+
+ __ETHTOOL_A_PRIVFLAGS_CNT,
+ ETHTOOL_A_PRIVFLAGS_MAX = (__ETHTOOL_A_PRIVFLAGS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_RINGS_UNSPEC,
+ ETHTOOL_A_RINGS_HEADER,
+ ETHTOOL_A_RINGS_RX_MAX,
+ ETHTOOL_A_RINGS_RX_MINI_MAX,
+ ETHTOOL_A_RINGS_RX_JUMBO_MAX,
+ ETHTOOL_A_RINGS_TX_MAX,
+ ETHTOOL_A_RINGS_RX,
+ ETHTOOL_A_RINGS_RX_MINI,
+ ETHTOOL_A_RINGS_RX_JUMBO,
+ ETHTOOL_A_RINGS_TX,
+ ETHTOOL_A_RINGS_RX_BUF_LEN,
+ ETHTOOL_A_RINGS_TCP_DATA_SPLIT,
+ ETHTOOL_A_RINGS_CQE_SIZE,
+ ETHTOOL_A_RINGS_TX_PUSH,
+ ETHTOOL_A_RINGS_RX_PUSH,
+ ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN,
+ ETHTOOL_A_RINGS_TX_PUSH_BUF_LEN_MAX,
+
+ __ETHTOOL_A_RINGS_CNT,
+ ETHTOOL_A_RINGS_MAX = (__ETHTOOL_A_RINGS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MM_STAT_UNSPEC,
+ ETHTOOL_A_MM_STAT_PAD,
+ ETHTOOL_A_MM_STAT_REASSEMBLY_ERRORS,
+ ETHTOOL_A_MM_STAT_SMD_ERRORS,
+ ETHTOOL_A_MM_STAT_REASSEMBLY_OK,
+ ETHTOOL_A_MM_STAT_RX_FRAG_COUNT,
+ ETHTOOL_A_MM_STAT_TX_FRAG_COUNT,
+ ETHTOOL_A_MM_STAT_HOLD_COUNT,
+
+ __ETHTOOL_A_MM_STAT_CNT,
+ ETHTOOL_A_MM_STAT_MAX = (__ETHTOOL_A_MM_STAT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MM_UNSPEC,
+ ETHTOOL_A_MM_HEADER,
+ ETHTOOL_A_MM_PMAC_ENABLED,
+ ETHTOOL_A_MM_TX_ENABLED,
+ ETHTOOL_A_MM_TX_ACTIVE,
+ ETHTOOL_A_MM_TX_MIN_FRAG_SIZE,
+ ETHTOOL_A_MM_RX_MIN_FRAG_SIZE,
+ ETHTOOL_A_MM_VERIFY_ENABLED,
+ ETHTOOL_A_MM_VERIFY_STATUS,
+ ETHTOOL_A_MM_VERIFY_TIME,
+ ETHTOOL_A_MM_MAX_VERIFY_TIME,
+ ETHTOOL_A_MM_STATS,
+
+ __ETHTOOL_A_MM_CNT,
+ ETHTOOL_A_MM_MAX = (__ETHTOOL_A_MM_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_LINKINFO_UNSPEC,
+ ETHTOOL_A_LINKINFO_HEADER,
+ ETHTOOL_A_LINKINFO_PORT,
+ ETHTOOL_A_LINKINFO_PHYADDR,
+ ETHTOOL_A_LINKINFO_TP_MDIX,
+ ETHTOOL_A_LINKINFO_TP_MDIX_CTRL,
+ ETHTOOL_A_LINKINFO_TRANSCEIVER,
+
+ __ETHTOOL_A_LINKINFO_CNT,
+ ETHTOOL_A_LINKINFO_MAX = (__ETHTOOL_A_LINKINFO_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_LINKMODES_UNSPEC,
+ ETHTOOL_A_LINKMODES_HEADER,
+ ETHTOOL_A_LINKMODES_AUTONEG,
+ ETHTOOL_A_LINKMODES_OURS,
+ ETHTOOL_A_LINKMODES_PEER,
+ ETHTOOL_A_LINKMODES_SPEED,
+ ETHTOOL_A_LINKMODES_DUPLEX,
+ ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG,
+ ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE,
+ ETHTOOL_A_LINKMODES_LANES,
+ ETHTOOL_A_LINKMODES_RATE_MATCHING,
+
+ __ETHTOOL_A_LINKMODES_CNT,
+ ETHTOOL_A_LINKMODES_MAX = (__ETHTOOL_A_LINKMODES_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_LINKSTATE_UNSPEC,
+ ETHTOOL_A_LINKSTATE_HEADER,
+ ETHTOOL_A_LINKSTATE_LINK,
+ ETHTOOL_A_LINKSTATE_SQI,
+ ETHTOOL_A_LINKSTATE_SQI_MAX,
+ ETHTOOL_A_LINKSTATE_EXT_STATE,
+ ETHTOOL_A_LINKSTATE_EXT_SUBSTATE,
+ ETHTOOL_A_LINKSTATE_EXT_DOWN_CNT,
+
+ __ETHTOOL_A_LINKSTATE_CNT,
+ ETHTOOL_A_LINKSTATE_MAX = (__ETHTOOL_A_LINKSTATE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_DEBUG_UNSPEC,
+ ETHTOOL_A_DEBUG_HEADER,
+ ETHTOOL_A_DEBUG_MSGMASK,
+
+ __ETHTOOL_A_DEBUG_CNT,
+ ETHTOOL_A_DEBUG_MAX = (__ETHTOOL_A_DEBUG_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_WOL_UNSPEC,
+ ETHTOOL_A_WOL_HEADER,
+ ETHTOOL_A_WOL_MODES,
+ ETHTOOL_A_WOL_SOPASS,
+
+ __ETHTOOL_A_WOL_CNT,
+ ETHTOOL_A_WOL_MAX = (__ETHTOOL_A_WOL_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_FEATURES_UNSPEC,
+ ETHTOOL_A_FEATURES_HEADER,
+ ETHTOOL_A_FEATURES_HW,
+ ETHTOOL_A_FEATURES_WANTED,
+ ETHTOOL_A_FEATURES_ACTIVE,
+ ETHTOOL_A_FEATURES_NOCHANGE,
+
+ __ETHTOOL_A_FEATURES_CNT,
+ ETHTOOL_A_FEATURES_MAX = (__ETHTOOL_A_FEATURES_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CHANNELS_UNSPEC,
+ ETHTOOL_A_CHANNELS_HEADER,
+ ETHTOOL_A_CHANNELS_RX_MAX,
+ ETHTOOL_A_CHANNELS_TX_MAX,
+ ETHTOOL_A_CHANNELS_OTHER_MAX,
+ ETHTOOL_A_CHANNELS_COMBINED_MAX,
+ ETHTOOL_A_CHANNELS_RX_COUNT,
+ ETHTOOL_A_CHANNELS_TX_COUNT,
+ ETHTOOL_A_CHANNELS_OTHER_COUNT,
+ ETHTOOL_A_CHANNELS_COMBINED_COUNT,
+
+ __ETHTOOL_A_CHANNELS_CNT,
+ ETHTOOL_A_CHANNELS_MAX = (__ETHTOOL_A_CHANNELS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_IRQ_MODERATION_UNSPEC,
+ ETHTOOL_A_IRQ_MODERATION_USEC,
+ ETHTOOL_A_IRQ_MODERATION_PKTS,
+ ETHTOOL_A_IRQ_MODERATION_COMPS,
+
+ __ETHTOOL_A_IRQ_MODERATION_CNT,
+ ETHTOOL_A_IRQ_MODERATION_MAX = (__ETHTOOL_A_IRQ_MODERATION_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PROFILE_UNSPEC,
+ ETHTOOL_A_PROFILE_IRQ_MODERATION,
+
+ __ETHTOOL_A_PROFILE_CNT,
+ ETHTOOL_A_PROFILE_MAX = (__ETHTOOL_A_PROFILE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_COALESCE_UNSPEC,
+ ETHTOOL_A_COALESCE_HEADER,
+ ETHTOOL_A_COALESCE_RX_USECS,
+ ETHTOOL_A_COALESCE_RX_MAX_FRAMES,
+ ETHTOOL_A_COALESCE_RX_USECS_IRQ,
+ ETHTOOL_A_COALESCE_RX_MAX_FRAMES_IRQ,
+ ETHTOOL_A_COALESCE_TX_USECS,
+ ETHTOOL_A_COALESCE_TX_MAX_FRAMES,
+ ETHTOOL_A_COALESCE_TX_USECS_IRQ,
+ ETHTOOL_A_COALESCE_TX_MAX_FRAMES_IRQ,
+ ETHTOOL_A_COALESCE_STATS_BLOCK_USECS,
+ ETHTOOL_A_COALESCE_USE_ADAPTIVE_RX,
+ ETHTOOL_A_COALESCE_USE_ADAPTIVE_TX,
+ ETHTOOL_A_COALESCE_PKT_RATE_LOW,
+ ETHTOOL_A_COALESCE_RX_USECS_LOW,
+ ETHTOOL_A_COALESCE_RX_MAX_FRAMES_LOW,
+ ETHTOOL_A_COALESCE_TX_USECS_LOW,
+ ETHTOOL_A_COALESCE_TX_MAX_FRAMES_LOW,
+ ETHTOOL_A_COALESCE_PKT_RATE_HIGH,
+ ETHTOOL_A_COALESCE_RX_USECS_HIGH,
+ ETHTOOL_A_COALESCE_RX_MAX_FRAMES_HIGH,
+ ETHTOOL_A_COALESCE_TX_USECS_HIGH,
+ ETHTOOL_A_COALESCE_TX_MAX_FRAMES_HIGH,
+ ETHTOOL_A_COALESCE_RATE_SAMPLE_INTERVAL,
+ ETHTOOL_A_COALESCE_USE_CQE_MODE_TX,
+ ETHTOOL_A_COALESCE_USE_CQE_MODE_RX,
+ ETHTOOL_A_COALESCE_TX_AGGR_MAX_BYTES,
+ ETHTOOL_A_COALESCE_TX_AGGR_MAX_FRAMES,
+ ETHTOOL_A_COALESCE_TX_AGGR_TIME_USECS,
+ ETHTOOL_A_COALESCE_RX_PROFILE,
+ ETHTOOL_A_COALESCE_TX_PROFILE,
+
+ __ETHTOOL_A_COALESCE_CNT,
+ ETHTOOL_A_COALESCE_MAX = (__ETHTOOL_A_COALESCE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PAUSE_STAT_UNSPEC,
+ ETHTOOL_A_PAUSE_STAT_PAD,
+ ETHTOOL_A_PAUSE_STAT_TX_FRAMES,
+ ETHTOOL_A_PAUSE_STAT_RX_FRAMES,
+
+ __ETHTOOL_A_PAUSE_STAT_CNT,
+ ETHTOOL_A_PAUSE_STAT_MAX = (__ETHTOOL_A_PAUSE_STAT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PAUSE_UNSPEC,
+ ETHTOOL_A_PAUSE_HEADER,
+ ETHTOOL_A_PAUSE_AUTONEG,
+ ETHTOOL_A_PAUSE_RX,
+ ETHTOOL_A_PAUSE_TX,
+ ETHTOOL_A_PAUSE_STATS,
+ ETHTOOL_A_PAUSE_STATS_SRC,
+
+ __ETHTOOL_A_PAUSE_CNT,
+ ETHTOOL_A_PAUSE_MAX = (__ETHTOOL_A_PAUSE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_EEE_UNSPEC,
+ ETHTOOL_A_EEE_HEADER,
+ ETHTOOL_A_EEE_MODES_OURS,
+ ETHTOOL_A_EEE_MODES_PEER,
+ ETHTOOL_A_EEE_ACTIVE,
+ ETHTOOL_A_EEE_ENABLED,
+ ETHTOOL_A_EEE_TX_LPI_ENABLED,
+ ETHTOOL_A_EEE_TX_LPI_TIMER,
+
+ __ETHTOOL_A_EEE_CNT,
+ ETHTOOL_A_EEE_MAX = (__ETHTOOL_A_EEE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TS_STAT_UNSPEC,
+ ETHTOOL_A_TS_STAT_TX_PKTS,
+ ETHTOOL_A_TS_STAT_TX_LOST,
+ ETHTOOL_A_TS_STAT_TX_ERR,
+
+ __ETHTOOL_A_TS_STAT_CNT,
+ ETHTOOL_A_TS_STAT_MAX = (__ETHTOOL_A_TS_STAT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_UNSPEC,
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX,
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER,
+
+ __ETHTOOL_A_TS_HWTSTAMP_PROVIDER_CNT,
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_MAX = (__ETHTOOL_A_TS_HWTSTAMP_PROVIDER_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TSINFO_UNSPEC,
+ ETHTOOL_A_TSINFO_HEADER,
+ ETHTOOL_A_TSINFO_TIMESTAMPING,
+ ETHTOOL_A_TSINFO_TX_TYPES,
+ ETHTOOL_A_TSINFO_RX_FILTERS,
+ ETHTOOL_A_TSINFO_PHC_INDEX,
+ ETHTOOL_A_TSINFO_STATS,
+ ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER,
+
+ __ETHTOOL_A_TSINFO_CNT,
+ ETHTOOL_A_TSINFO_MAX = (__ETHTOOL_A_TSINFO_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_RESULT_UNSPEC,
+ ETHTOOL_A_CABLE_RESULT_PAIR,
+ ETHTOOL_A_CABLE_RESULT_CODE,
+ ETHTOOL_A_CABLE_RESULT_SRC,
+
+ __ETHTOOL_A_CABLE_RESULT_CNT,
+ ETHTOOL_A_CABLE_RESULT_MAX = (__ETHTOOL_A_CABLE_RESULT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_FAULT_LENGTH_UNSPEC,
+ ETHTOOL_A_CABLE_FAULT_LENGTH_PAIR,
+ ETHTOOL_A_CABLE_FAULT_LENGTH_CM,
+ ETHTOOL_A_CABLE_FAULT_LENGTH_SRC,
+
+ __ETHTOOL_A_CABLE_FAULT_LENGTH_CNT,
+ ETHTOOL_A_CABLE_FAULT_LENGTH_MAX = (__ETHTOOL_A_CABLE_FAULT_LENGTH_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_NEST_UNSPEC,
+ ETHTOOL_A_CABLE_NEST_RESULT,
+ ETHTOOL_A_CABLE_NEST_FAULT_LENGTH,
+
+ __ETHTOOL_A_CABLE_NEST_CNT,
+ ETHTOOL_A_CABLE_NEST_MAX = (__ETHTOOL_A_CABLE_NEST_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_TEST_UNSPEC,
+ ETHTOOL_A_CABLE_TEST_HEADER,
+
+ __ETHTOOL_A_CABLE_TEST_CNT,
+ ETHTOOL_A_CABLE_TEST_MAX = (__ETHTOOL_A_CABLE_TEST_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_TEST_NTF_UNSPEC,
+ ETHTOOL_A_CABLE_TEST_NTF_HEADER,
+ ETHTOOL_A_CABLE_TEST_NTF_STATUS,
+ ETHTOOL_A_CABLE_TEST_NTF_NEST,
+
+ __ETHTOOL_A_CABLE_TEST_NTF_CNT,
+ ETHTOOL_A_CABLE_TEST_NTF_MAX = (__ETHTOOL_A_CABLE_TEST_NTF_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_UNSPEC,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_FIRST,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_LAST,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_STEP,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_PAIR,
+
+ __ETHTOOL_A_CABLE_TEST_TDR_CFG_CNT,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG_MAX = (__ETHTOOL_A_CABLE_TEST_TDR_CFG_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_TEST_TDR_NTF_UNSPEC,
+ ETHTOOL_A_CABLE_TEST_TDR_NTF_HEADER,
+ ETHTOOL_A_CABLE_TEST_TDR_NTF_STATUS,
+ ETHTOOL_A_CABLE_TEST_TDR_NTF_NEST,
+
+ __ETHTOOL_A_CABLE_TEST_TDR_NTF_CNT,
+ ETHTOOL_A_CABLE_TEST_TDR_NTF_MAX = (__ETHTOOL_A_CABLE_TEST_TDR_NTF_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_CABLE_TEST_TDR_UNSPEC,
+ ETHTOOL_A_CABLE_TEST_TDR_HEADER,
+ ETHTOOL_A_CABLE_TEST_TDR_CFG,
+
+ __ETHTOOL_A_CABLE_TEST_TDR_CNT,
+ ETHTOOL_A_CABLE_TEST_TDR_MAX = (__ETHTOOL_A_CABLE_TEST_TDR_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TUNNEL_UDP_ENTRY_UNSPEC,
+ ETHTOOL_A_TUNNEL_UDP_ENTRY_PORT,
+ ETHTOOL_A_TUNNEL_UDP_ENTRY_TYPE,
+
+ __ETHTOOL_A_TUNNEL_UDP_ENTRY_CNT,
+ ETHTOOL_A_TUNNEL_UDP_ENTRY_MAX = (__ETHTOOL_A_TUNNEL_UDP_ENTRY_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TUNNEL_UDP_TABLE_UNSPEC,
+ ETHTOOL_A_TUNNEL_UDP_TABLE_SIZE,
+ ETHTOOL_A_TUNNEL_UDP_TABLE_TYPES,
+ ETHTOOL_A_TUNNEL_UDP_TABLE_ENTRY,
+
+ __ETHTOOL_A_TUNNEL_UDP_TABLE_CNT,
+ ETHTOOL_A_TUNNEL_UDP_TABLE_MAX = (__ETHTOOL_A_TUNNEL_UDP_TABLE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TUNNEL_UDP_UNSPEC,
+ ETHTOOL_A_TUNNEL_UDP_TABLE,
+
+ __ETHTOOL_A_TUNNEL_UDP_CNT,
+ ETHTOOL_A_TUNNEL_UDP_MAX = (__ETHTOOL_A_TUNNEL_UDP_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TUNNEL_INFO_UNSPEC,
+ ETHTOOL_A_TUNNEL_INFO_HEADER,
+ ETHTOOL_A_TUNNEL_INFO_UDP_PORTS,
+
+ __ETHTOOL_A_TUNNEL_INFO_CNT,
+ ETHTOOL_A_TUNNEL_INFO_MAX = (__ETHTOOL_A_TUNNEL_INFO_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_FEC_STAT_UNSPEC,
+ ETHTOOL_A_FEC_STAT_PAD,
+ ETHTOOL_A_FEC_STAT_CORRECTED,
+ ETHTOOL_A_FEC_STAT_UNCORR,
+ ETHTOOL_A_FEC_STAT_CORR_BITS,
+
+ __ETHTOOL_A_FEC_STAT_CNT,
+ ETHTOOL_A_FEC_STAT_MAX = (__ETHTOOL_A_FEC_STAT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_FEC_UNSPEC,
+ ETHTOOL_A_FEC_HEADER,
+ ETHTOOL_A_FEC_MODES,
+ ETHTOOL_A_FEC_AUTO,
+ ETHTOOL_A_FEC_ACTIVE,
+ ETHTOOL_A_FEC_STATS,
+
+ __ETHTOOL_A_FEC_CNT,
+ ETHTOOL_A_FEC_MAX = (__ETHTOOL_A_FEC_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MODULE_EEPROM_UNSPEC,
+ ETHTOOL_A_MODULE_EEPROM_HEADER,
+ ETHTOOL_A_MODULE_EEPROM_OFFSET,
+ ETHTOOL_A_MODULE_EEPROM_LENGTH,
+ ETHTOOL_A_MODULE_EEPROM_PAGE,
+ ETHTOOL_A_MODULE_EEPROM_BANK,
+ ETHTOOL_A_MODULE_EEPROM_I2C_ADDRESS,
+ ETHTOOL_A_MODULE_EEPROM_DATA,
+
+ __ETHTOOL_A_MODULE_EEPROM_CNT,
+ ETHTOOL_A_MODULE_EEPROM_MAX = (__ETHTOOL_A_MODULE_EEPROM_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STATS_GRP_UNSPEC,
+ ETHTOOL_A_STATS_GRP_PAD,
+ ETHTOOL_A_STATS_GRP_ID,
+ ETHTOOL_A_STATS_GRP_SS_ID,
+ ETHTOOL_A_STATS_GRP_STAT,
+ ETHTOOL_A_STATS_GRP_HIST_RX,
+ ETHTOOL_A_STATS_GRP_HIST_TX,
+ ETHTOOL_A_STATS_GRP_HIST_BKT_LOW,
+ ETHTOOL_A_STATS_GRP_HIST_BKT_HI,
+ ETHTOOL_A_STATS_GRP_HIST_VAL,
+
+ __ETHTOOL_A_STATS_GRP_CNT,
+ ETHTOOL_A_STATS_GRP_MAX = (__ETHTOOL_A_STATS_GRP_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_STATS_UNSPEC,
+ ETHTOOL_A_STATS_PAD,
+ ETHTOOL_A_STATS_HEADER,
+ ETHTOOL_A_STATS_GROUPS,
+ ETHTOOL_A_STATS_GRP,
+ ETHTOOL_A_STATS_SRC,
+
+ __ETHTOOL_A_STATS_CNT,
+ ETHTOOL_A_STATS_MAX = (__ETHTOOL_A_STATS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PHC_VCLOCKS_UNSPEC,
+ ETHTOOL_A_PHC_VCLOCKS_HEADER,
+ ETHTOOL_A_PHC_VCLOCKS_NUM,
+ ETHTOOL_A_PHC_VCLOCKS_INDEX,
+
+ __ETHTOOL_A_PHC_VCLOCKS_CNT,
+ ETHTOOL_A_PHC_VCLOCKS_MAX = (__ETHTOOL_A_PHC_VCLOCKS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MODULE_UNSPEC,
+ ETHTOOL_A_MODULE_HEADER,
+ ETHTOOL_A_MODULE_POWER_MODE_POLICY,
+ ETHTOOL_A_MODULE_POWER_MODE,
+
+ __ETHTOOL_A_MODULE_CNT,
+ ETHTOOL_A_MODULE_MAX = (__ETHTOOL_A_MODULE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_C33_PSE_PW_LIMIT_UNSPEC,
+ ETHTOOL_A_C33_PSE_PW_LIMIT_MIN,
+ ETHTOOL_A_C33_PSE_PW_LIMIT_MAX,
+
+ __ETHTOOL_A_C33_PSE_PW_LIMIT_CNT,
+ __ETHTOOL_A_C33_PSE_PW_LIMIT_MAX = (__ETHTOOL_A_C33_PSE_PW_LIMIT_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PSE_UNSPEC,
+ ETHTOOL_A_PSE_HEADER,
+ ETHTOOL_A_PODL_PSE_ADMIN_STATE,
+ ETHTOOL_A_PODL_PSE_ADMIN_CONTROL,
+ ETHTOOL_A_PODL_PSE_PW_D_STATUS,
+ ETHTOOL_A_C33_PSE_ADMIN_STATE,
+ ETHTOOL_A_C33_PSE_ADMIN_CONTROL,
+ ETHTOOL_A_C33_PSE_PW_D_STATUS,
+ ETHTOOL_A_C33_PSE_PW_CLASS,
+ ETHTOOL_A_C33_PSE_ACTUAL_PW,
+ ETHTOOL_A_C33_PSE_EXT_STATE,
+ ETHTOOL_A_C33_PSE_EXT_SUBSTATE,
+ ETHTOOL_A_C33_PSE_AVAIL_PW_LIMIT,
+ ETHTOOL_A_C33_PSE_PW_LIMIT_RANGES,
+
+ __ETHTOOL_A_PSE_CNT,
+ ETHTOOL_A_PSE_MAX = (__ETHTOOL_A_PSE_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_RSS_UNSPEC,
+ ETHTOOL_A_RSS_HEADER,
+ ETHTOOL_A_RSS_CONTEXT,
+ ETHTOOL_A_RSS_HFUNC,
+ ETHTOOL_A_RSS_INDIR,
+ ETHTOOL_A_RSS_HKEY,
+ ETHTOOL_A_RSS_INPUT_XFRM,
+ ETHTOOL_A_RSS_START_CONTEXT,
+
+ __ETHTOOL_A_RSS_CNT,
+ ETHTOOL_A_RSS_MAX = (__ETHTOOL_A_RSS_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PLCA_UNSPEC,
+ ETHTOOL_A_PLCA_HEADER,
+ ETHTOOL_A_PLCA_VERSION,
+ ETHTOOL_A_PLCA_ENABLED,
+ ETHTOOL_A_PLCA_STATUS,
+ ETHTOOL_A_PLCA_NODE_CNT,
+ ETHTOOL_A_PLCA_NODE_ID,
+ ETHTOOL_A_PLCA_TO_TMR,
+ ETHTOOL_A_PLCA_BURST_CNT,
+ ETHTOOL_A_PLCA_BURST_TMR,
+
+ __ETHTOOL_A_PLCA_CNT,
+ ETHTOOL_A_PLCA_MAX = (__ETHTOOL_A_PLCA_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_MODULE_FW_FLASH_UNSPEC,
+ ETHTOOL_A_MODULE_FW_FLASH_HEADER,
+ ETHTOOL_A_MODULE_FW_FLASH_FILE_NAME,
+ ETHTOOL_A_MODULE_FW_FLASH_PASSWORD,
+ ETHTOOL_A_MODULE_FW_FLASH_STATUS,
+ ETHTOOL_A_MODULE_FW_FLASH_STATUS_MSG,
+ ETHTOOL_A_MODULE_FW_FLASH_DONE,
+ ETHTOOL_A_MODULE_FW_FLASH_TOTAL,
+
+ __ETHTOOL_A_MODULE_FW_FLASH_CNT,
+ ETHTOOL_A_MODULE_FW_FLASH_MAX = (__ETHTOOL_A_MODULE_FW_FLASH_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_PHY_UNSPEC,
+ ETHTOOL_A_PHY_HEADER,
+ ETHTOOL_A_PHY_INDEX,
+ ETHTOOL_A_PHY_DRVNAME,
+ ETHTOOL_A_PHY_NAME,
+ ETHTOOL_A_PHY_UPSTREAM_TYPE,
+ ETHTOOL_A_PHY_UPSTREAM_INDEX,
+ ETHTOOL_A_PHY_UPSTREAM_SFP_NAME,
+ ETHTOOL_A_PHY_DOWNSTREAM_SFP_NAME,
+
+ __ETHTOOL_A_PHY_CNT,
+ ETHTOOL_A_PHY_MAX = (__ETHTOOL_A_PHY_CNT - 1)
+};
+
+enum {
+ ETHTOOL_A_TSCONFIG_UNSPEC,
+ ETHTOOL_A_TSCONFIG_HEADER,
+ ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER,
+ ETHTOOL_A_TSCONFIG_TX_TYPES,
+ ETHTOOL_A_TSCONFIG_RX_FILTERS,
+ ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS,
+
+ __ETHTOOL_A_TSCONFIG_CNT,
+ ETHTOOL_A_TSCONFIG_MAX = (__ETHTOOL_A_TSCONFIG_CNT - 1)
+};
+
+enum {
+ ETHTOOL_MSG_USER_NONE = 0,
+ ETHTOOL_MSG_STRSET_GET = 1,
+ ETHTOOL_MSG_LINKINFO_GET,
+ ETHTOOL_MSG_LINKINFO_SET,
+ ETHTOOL_MSG_LINKMODES_GET,
+ ETHTOOL_MSG_LINKMODES_SET,
+ ETHTOOL_MSG_LINKSTATE_GET,
+ ETHTOOL_MSG_DEBUG_GET,
+ ETHTOOL_MSG_DEBUG_SET,
+ ETHTOOL_MSG_WOL_GET,
+ ETHTOOL_MSG_WOL_SET,
+ ETHTOOL_MSG_FEATURES_GET,
+ ETHTOOL_MSG_FEATURES_SET,
+ ETHTOOL_MSG_PRIVFLAGS_GET,
+ ETHTOOL_MSG_PRIVFLAGS_SET,
+ ETHTOOL_MSG_RINGS_GET,
+ ETHTOOL_MSG_RINGS_SET,
+ ETHTOOL_MSG_CHANNELS_GET,
+ ETHTOOL_MSG_CHANNELS_SET,
+ ETHTOOL_MSG_COALESCE_GET,
+ ETHTOOL_MSG_COALESCE_SET,
+ ETHTOOL_MSG_PAUSE_GET,
+ ETHTOOL_MSG_PAUSE_SET,
+ ETHTOOL_MSG_EEE_GET,
+ ETHTOOL_MSG_EEE_SET,
+ ETHTOOL_MSG_TSINFO_GET,
+ ETHTOOL_MSG_CABLE_TEST_ACT,
+ ETHTOOL_MSG_CABLE_TEST_TDR_ACT,
+ ETHTOOL_MSG_TUNNEL_INFO_GET,
+ ETHTOOL_MSG_FEC_GET,
+ ETHTOOL_MSG_FEC_SET,
+ ETHTOOL_MSG_MODULE_EEPROM_GET,
+ ETHTOOL_MSG_STATS_GET,
+ ETHTOOL_MSG_PHC_VCLOCKS_GET,
+ ETHTOOL_MSG_MODULE_GET,
+ ETHTOOL_MSG_MODULE_SET,
+ ETHTOOL_MSG_PSE_GET,
+ ETHTOOL_MSG_PSE_SET,
+ ETHTOOL_MSG_RSS_GET,
+ ETHTOOL_MSG_PLCA_GET_CFG,
+ ETHTOOL_MSG_PLCA_SET_CFG,
+ ETHTOOL_MSG_PLCA_GET_STATUS,
+ ETHTOOL_MSG_MM_GET,
+ ETHTOOL_MSG_MM_SET,
+ ETHTOOL_MSG_MODULE_FW_FLASH_ACT,
+ ETHTOOL_MSG_PHY_GET,
+ ETHTOOL_MSG_TSCONFIG_GET,
+ ETHTOOL_MSG_TSCONFIG_SET,
+
+ __ETHTOOL_MSG_USER_CNT,
+ ETHTOOL_MSG_USER_MAX = (__ETHTOOL_MSG_USER_CNT - 1)
+};
+
+enum {
+ ETHTOOL_MSG_KERNEL_NONE = 0,
+ ETHTOOL_MSG_STRSET_GET_REPLY = 1,
+ ETHTOOL_MSG_LINKINFO_GET_REPLY,
+ ETHTOOL_MSG_LINKINFO_NTF,
+ ETHTOOL_MSG_LINKMODES_GET_REPLY,
+ ETHTOOL_MSG_LINKMODES_NTF,
+ ETHTOOL_MSG_LINKSTATE_GET_REPLY,
+ ETHTOOL_MSG_DEBUG_GET_REPLY,
+ ETHTOOL_MSG_DEBUG_NTF,
+ ETHTOOL_MSG_WOL_GET_REPLY,
+ ETHTOOL_MSG_WOL_NTF,
+ ETHTOOL_MSG_FEATURES_GET_REPLY,
+ ETHTOOL_MSG_FEATURES_SET_REPLY,
+ ETHTOOL_MSG_FEATURES_NTF,
+ ETHTOOL_MSG_PRIVFLAGS_GET_REPLY,
+ ETHTOOL_MSG_PRIVFLAGS_NTF,
+ ETHTOOL_MSG_RINGS_GET_REPLY,
+ ETHTOOL_MSG_RINGS_NTF,
+ ETHTOOL_MSG_CHANNELS_GET_REPLY,
+ ETHTOOL_MSG_CHANNELS_NTF,
+ ETHTOOL_MSG_COALESCE_GET_REPLY,
+ ETHTOOL_MSG_COALESCE_NTF,
+ ETHTOOL_MSG_PAUSE_GET_REPLY,
+ ETHTOOL_MSG_PAUSE_NTF,
+ ETHTOOL_MSG_EEE_GET_REPLY,
+ ETHTOOL_MSG_EEE_NTF,
+ ETHTOOL_MSG_TSINFO_GET_REPLY,
+ ETHTOOL_MSG_CABLE_TEST_NTF,
+ ETHTOOL_MSG_CABLE_TEST_TDR_NTF,
+ ETHTOOL_MSG_TUNNEL_INFO_GET_REPLY,
+ ETHTOOL_MSG_FEC_GET_REPLY,
+ ETHTOOL_MSG_FEC_NTF,
+ ETHTOOL_MSG_MODULE_EEPROM_GET_REPLY,
+ ETHTOOL_MSG_STATS_GET_REPLY,
+ ETHTOOL_MSG_PHC_VCLOCKS_GET_REPLY,
+ ETHTOOL_MSG_MODULE_GET_REPLY,
+ ETHTOOL_MSG_MODULE_NTF,
+ ETHTOOL_MSG_PSE_GET_REPLY,
+ ETHTOOL_MSG_RSS_GET_REPLY,
+ ETHTOOL_MSG_PLCA_GET_CFG_REPLY,
+ ETHTOOL_MSG_PLCA_GET_STATUS_REPLY,
+ ETHTOOL_MSG_PLCA_NTF,
+ ETHTOOL_MSG_MM_GET_REPLY,
+ ETHTOOL_MSG_MM_NTF,
+ ETHTOOL_MSG_MODULE_FW_FLASH_NTF,
+ ETHTOOL_MSG_PHY_GET_REPLY,
+ ETHTOOL_MSG_PHY_NTF,
+ ETHTOOL_MSG_TSCONFIG_GET_REPLY,
+ ETHTOOL_MSG_TSCONFIG_SET_REPLY,
+
+ __ETHTOOL_MSG_KERNEL_CNT,
+ ETHTOOL_MSG_KERNEL_MAX = (__ETHTOOL_MSG_KERNEL_CNT - 1)
+};
+
+#endif /* _UAPI_LINUX_ETHTOOL_NETLINK_GENERATED_H */
diff --git a/include/uapi/linux/fib_rules.h b/include/uapi/linux/fib_rules.h
index a6924dd3aff1..00e9890ca3c0 100644
--- a/include/uapi/linux/fib_rules.h
+++ b/include/uapi/linux/fib_rules.h
@@ -68,6 +68,8 @@ enum {
FRA_SPORT_RANGE, /* sport */
FRA_DPORT_RANGE, /* dport */
FRA_DSCP, /* dscp */
+ FRA_FLOWLABEL, /* flowlabel */
+ FRA_FLOWLABEL_MASK, /* flowlabel mask */
__FRA_MAX
};
diff --git a/include/uapi/linux/if_link.h b/include/uapi/linux/if_link.h
index 2575e0cd9b48..bfe880fbbb24 100644
--- a/include/uapi/linux/if_link.h
+++ b/include/uapi/linux/if_link.h
@@ -1315,6 +1315,8 @@ enum {
IFLA_NETKIT_MODE,
IFLA_NETKIT_SCRUB,
IFLA_NETKIT_PEER_SCRUB,
+ IFLA_NETKIT_HEADROOM,
+ IFLA_NETKIT_TAILROOM,
__IFLA_NETKIT_MAX,
};
#define IFLA_NETKIT_MAX (__IFLA_NETKIT_MAX - 1)
@@ -1394,6 +1396,7 @@ enum {
IFLA_VXLAN_VNIFILTER, /* only applicable with COLLECT_METADATA mode */
IFLA_VXLAN_LOCALBYPASS,
IFLA_VXLAN_LABEL_POLICY, /* IPv6 flow label policy; ifla_vxlan_label_policy */
+ IFLA_VXLAN_RESERVED_BITS,
__IFLA_VXLAN_MAX
};
#define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
diff --git a/include/uapi/linux/iio/types.h b/include/uapi/linux/iio/types.h
index f2e0b2d50e6b..12886d4465e4 100644
--- a/include/uapi/linux/iio/types.h
+++ b/include/uapi/linux/iio/types.h
@@ -51,6 +51,7 @@ enum iio_chan_type {
IIO_DELTA_VELOCITY,
IIO_COLORTEMP,
IIO_CHROMATICITY,
+ IIO_ATTENTION,
};
enum iio_modifier {
diff --git a/include/uapi/linux/io_uring.h b/include/uapi/linux/io_uring.h
index 4418d0192959..aac9a4f8fa9a 100644
--- a/include/uapi/linux/io_uring.h
+++ b/include/uapi/linux/io_uring.h
@@ -874,20 +874,6 @@ enum {
};
/*
- * Argument for IORING_REGISTER_CQWAIT_REG, registering a region of
- * struct io_uring_reg_wait that can be indexed when io_uring_enter(2) is
- * called rather than pass in a wait argument structure separately.
- */
-struct io_uring_cqwait_reg_arg {
- __u32 flags;
- __u32 struct_size;
- __u32 nr_entries;
- __u32 pad;
- __u64 user_addr;
- __u64 pad2[3];
-};
-
-/*
* Argument for io_uring_enter(2) with
* IORING_GETEVENTS | IORING_ENTER_EXT_ARG_REG set, where the actual argument
* is an index into a previously registered fixed wait region described by
diff --git a/include/uapi/linux/iommufd.h b/include/uapi/linux/iommufd.h
index 059b6537f2b7..34810f6ae2b5 100644
--- a/include/uapi/linux/iommufd.h
+++ b/include/uapi/linux/iommufd.h
@@ -297,7 +297,7 @@ struct iommu_ioas_unmap {
* ioctl(IOMMU_OPTION_HUGE_PAGES)
* @IOMMU_OPTION_RLIMIT_MODE:
* Change how RLIMIT_MEMLOCK accounting works. The caller must have privilege
- * to invoke this. Value 0 (default) is user based accouting, 1 uses process
+ * to invoke this. Value 0 (default) is user based accounting, 1 uses process
* based accounting. Global option, object_id must be 0
* @IOMMU_OPTION_HUGE_PAGES:
* Value 1 (default) allows contiguous pages to be combined when generating
@@ -390,7 +390,7 @@ struct iommu_vfio_ioas {
* @IOMMU_HWPT_ALLOC_PASID: Requests a domain that can be used with PASID. The
* domain can be attached to any PASID on the device.
* Any domain attached to the non-PASID part of the
- * device must also be flaged, otherwise attaching a
+ * device must also be flagged, otherwise attaching a
* PASID will blocked.
* If IOMMU does not support PASID it will return
* error (-EOPNOTSUPP).
@@ -558,16 +558,25 @@ struct iommu_hw_info_vtd {
* For the details of @idr, @iidr and @aidr, please refer to the chapters
* from 6.3.1 to 6.3.6 in the SMMUv3 Spec.
*
- * User space should read the underlying ARM SMMUv3 hardware information for
- * the list of supported features.
+ * This reports the raw HW capability, and not all bits are meaningful to be
+ * read by userspace. Only the following fields should be used:
*
- * Note that these values reflect the raw HW capability, without any insight if
- * any required kernel driver support is present. Bits may be set indicating the
- * HW has functionality that is lacking kernel software support, such as BTM. If
- * a VMM is using this information to construct emulated copies of these
- * registers it should only forward bits that it knows it can support.
+ * idr[0]: ST_LEVEL, TERM_MODEL, STALL_MODEL, TTENDIAN , CD2L, ASID16, TTF
+ * idr[1]: SIDSIZE, SSIDSIZE
+ * idr[3]: BBML, RIL
+ * idr[5]: VAX, GRAN64K, GRAN16K, GRAN4K
*
- * In future, presence of required kernel support will be indicated in flags.
+ * - S1P should be assumed to be true if a NESTED HWPT can be created
+ * - VFIO/iommufd only support platforms with COHACC, it should be assumed to be
+ * true.
+ * - ATS is a per-device property. If the VMM describes any devices as ATS
+ * capable in ACPI/DT it should set the corresponding idr.
+ *
+ * This list may expand in future (eg E0PD, AIE, PBHA, D128, DS etc). It is
+ * important that VMMs do not read bits outside the list to allow for
+ * compatibility with future kernels. Several features in the SMMUv3
+ * architecture are not currently supported by the kernel for nesting: HTTU,
+ * BTM, MPAM and others.
*/
struct iommu_hw_info_arm_smmuv3 {
__u32 flags;
@@ -766,7 +775,7 @@ struct iommu_hwpt_vtd_s1_invalidate {
};
/**
- * struct iommu_viommu_arm_smmuv3_invalidate - ARM SMMUv3 cahce invalidation
+ * struct iommu_viommu_arm_smmuv3_invalidate - ARM SMMUv3 cache invalidation
* (IOMMU_VIOMMU_INVALIDATE_DATA_ARM_SMMUV3)
* @cmd: 128-bit cache invalidation command that runs in SMMU CMDQ.
* Must be little-endian.
diff --git a/include/uapi/linux/mptcp_pm.h b/include/uapi/linux/mptcp_pm.h
index 50589e5dd6a3..84fa8a21dfd0 100644
--- a/include/uapi/linux/mptcp_pm.h
+++ b/include/uapi/linux/mptcp_pm.h
@@ -12,31 +12,33 @@
/**
* enum mptcp_event_type
* @MPTCP_EVENT_UNSPEC: unused event
- * @MPTCP_EVENT_CREATED: token, family, saddr4 | saddr6, daddr4 | daddr6,
- * sport, dport A new MPTCP connection has been created. It is the good time
- * to allocate memory and send ADD_ADDR if needed. Depending on the
+ * @MPTCP_EVENT_CREATED: A new MPTCP connection has been created. It is the
+ * good time to allocate memory and send ADD_ADDR if needed. Depending on the
* traffic-patterns it can take a long time until the MPTCP_EVENT_ESTABLISHED
- * is sent.
- * @MPTCP_EVENT_ESTABLISHED: token, family, saddr4 | saddr6, daddr4 | daddr6,
- * sport, dport A MPTCP connection is established (can start new subflows).
- * @MPTCP_EVENT_CLOSED: token A MPTCP connection has stopped.
- * @MPTCP_EVENT_ANNOUNCED: token, rem_id, family, daddr4 | daddr6 [, dport] A
- * new address has been announced by the peer.
- * @MPTCP_EVENT_REMOVED: token, rem_id An address has been lost by the peer.
- * @MPTCP_EVENT_SUB_ESTABLISHED: token, family, loc_id, rem_id, saddr4 |
- * saddr6, daddr4 | daddr6, sport, dport, backup, if_idx [, error] A new
- * subflow has been established. 'error' should not be set.
- * @MPTCP_EVENT_SUB_CLOSED: token, family, loc_id, rem_id, saddr4 | saddr6,
- * daddr4 | daddr6, sport, dport, backup, if_idx [, error] A subflow has been
- * closed. An error (copy of sk_err) could be set if an error has been
- * detected for this subflow.
- * @MPTCP_EVENT_SUB_PRIORITY: token, family, loc_id, rem_id, saddr4 | saddr6,
- * daddr4 | daddr6, sport, dport, backup, if_idx [, error] The priority of a
- * subflow has changed. 'error' should not be set.
- * @MPTCP_EVENT_LISTENER_CREATED: family, sport, saddr4 | saddr6 A new PM
- * listener is created.
- * @MPTCP_EVENT_LISTENER_CLOSED: family, sport, saddr4 | saddr6 A PM listener
- * is closed.
+ * is sent. Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6,
+ * sport, dport, server-side.
+ * @MPTCP_EVENT_ESTABLISHED: A MPTCP connection is established (can start new
+ * subflows). Attributes: token, family, saddr4 | saddr6, daddr4 | daddr6,
+ * sport, dport, server-side.
+ * @MPTCP_EVENT_CLOSED: A MPTCP connection has stopped. Attribute: token.
+ * @MPTCP_EVENT_ANNOUNCED: A new address has been announced by the peer.
+ * Attributes: token, rem_id, family, daddr4 | daddr6 [, dport].
+ * @MPTCP_EVENT_REMOVED: An address has been lost by the peer. Attributes:
+ * token, rem_id.
+ * @MPTCP_EVENT_SUB_ESTABLISHED: A new subflow has been established. 'error'
+ * should not be set. Attributes: token, family, loc_id, rem_id, saddr4 |
+ * saddr6, daddr4 | daddr6, sport, dport, backup, if_idx [, error].
+ * @MPTCP_EVENT_SUB_CLOSED: A subflow has been closed. An error (copy of
+ * sk_err) could be set if an error has been detected for this subflow.
+ * Attributes: token, family, loc_id, rem_id, saddr4 | saddr6, daddr4 |
+ * daddr6, sport, dport, backup, if_idx [, error].
+ * @MPTCP_EVENT_SUB_PRIORITY: The priority of a subflow has changed. 'error'
+ * should not be set. Attributes: token, family, loc_id, rem_id, saddr4 |
+ * saddr6, daddr4 | daddr6, sport, dport, backup, if_idx [, error].
+ * @MPTCP_EVENT_LISTENER_CREATED: A new PM listener is created. Attributes:
+ * family, sport, saddr4 | saddr6.
+ * @MPTCP_EVENT_LISTENER_CLOSED: A PM listener is closed. Attributes: family,
+ * sport, saddr4 | saddr6.
*/
enum mptcp_event_type {
MPTCP_EVENT_UNSPEC,
diff --git a/include/uapi/linux/net_tstamp.h b/include/uapi/linux/net_tstamp.h
index 858339d1c1c4..55b0ab51096c 100644
--- a/include/uapi/linux/net_tstamp.h
+++ b/include/uapi/linux/net_tstamp.h
@@ -13,6 +13,17 @@
#include <linux/types.h>
#include <linux/socket.h> /* for SO_TIMESTAMPING */
+/*
+ * Possible type of hwtstamp provider. Mainly "precise" the default one
+ * is for IEEE 1588 quality and "approx" is for NICs DMA point.
+ */
+enum hwtstamp_provider_qualifier {
+ HWTSTAMP_PROVIDER_QUALIFIER_PRECISE,
+ HWTSTAMP_PROVIDER_QUALIFIER_APPROX,
+
+ HWTSTAMP_PROVIDER_QUALIFIER_CNT,
+};
+
/* SO_TIMESTAMPING flags */
enum {
SOF_TIMESTAMPING_TX_HARDWARE = (1<<0),
diff --git a/include/uapi/linux/rtnetlink.h b/include/uapi/linux/rtnetlink.h
index db7254d52d93..66c3903d29cf 100644
--- a/include/uapi/linux/rtnetlink.h
+++ b/include/uapi/linux/rtnetlink.h
@@ -93,10 +93,18 @@ enum {
RTM_NEWPREFIX = 52,
#define RTM_NEWPREFIX RTM_NEWPREFIX
- RTM_GETMULTICAST = 58,
+ RTM_NEWMULTICAST = 56,
+#define RTM_NEWMULTICAST RTM_NEWMULTICAST
+ RTM_DELMULTICAST,
+#define RTM_DELMULTICAST RTM_DELMULTICAST
+ RTM_GETMULTICAST,
#define RTM_GETMULTICAST RTM_GETMULTICAST
- RTM_GETANYCAST = 62,
+ RTM_NEWANYCAST = 60,
+#define RTM_NEWANYCAST RTM_NEWANYCAST
+ RTM_DELANYCAST,
+#define RTM_DELANYCAST RTM_DELANYCAST
+ RTM_GETANYCAST,
#define RTM_GETANYCAST RTM_GETANYCAST
RTM_NEWNEIGHTBL = 64,
@@ -389,6 +397,7 @@ enum rtattr_type_t {
RTA_SPORT,
RTA_DPORT,
RTA_NH_ID,
+ RTA_FLOWLABEL,
__RTA_MAX
};
@@ -774,6 +783,12 @@ enum rtnetlink_groups {
#define RTNLGRP_TUNNEL RTNLGRP_TUNNEL
RTNLGRP_STATS,
#define RTNLGRP_STATS RTNLGRP_STATS
+ RTNLGRP_IPV4_MCADDR,
+#define RTNLGRP_IPV4_MCADDR RTNLGRP_IPV4_MCADDR
+ RTNLGRP_IPV6_MCADDR,
+#define RTNLGRP_IPV6_MCADDR RTNLGRP_IPV6_MCADDR
+ RTNLGRP_IPV6_ACADDR,
+#define RTNLGRP_IPV6_ACADDR RTNLGRP_IPV6_ACADDR
__RTNLGRP_MAX
};
#define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
diff --git a/include/uapi/linux/snmp.h b/include/uapi/linux/snmp.h
index 5a2553511190..2e75674e7d4f 100644
--- a/include/uapi/linux/snmp.h
+++ b/include/uapi/linux/snmp.h
@@ -360,6 +360,11 @@ enum
LINUX_MIB_TLSRXDEVICERESYNC, /* TlsRxDeviceResync */
LINUX_MIB_TLSDECRYPTRETRY, /* TlsDecryptRetry */
LINUX_MIB_TLSRXNOPADVIOL, /* TlsRxNoPadViolation */
+ LINUX_MIB_TLSRXREKEYOK, /* TlsRxRekeyOk */
+ LINUX_MIB_TLSRXREKEYERROR, /* TlsRxRekeyError */
+ LINUX_MIB_TLSTXREKEYOK, /* TlsTxRekeyOk */
+ LINUX_MIB_TLSTXREKEYERROR, /* TlsTxRekeyError */
+ LINUX_MIB_TLSRXREKEYRECEIVED, /* TlsRxRekeyReceived */
__LINUX_MIB_TLSMAX
};
diff --git a/include/uapi/linux/stddef.h b/include/uapi/linux/stddef.h
index 58154117d9b0..a6fce46aeb37 100644
--- a/include/uapi/linux/stddef.h
+++ b/include/uapi/linux/stddef.h
@@ -8,6 +8,13 @@
#define __always_inline inline
#endif
+/* Not all C++ standards support type declarations inside an anonymous union */
+#ifndef __cplusplus
+#define __struct_group_tag(TAG) TAG
+#else
+#define __struct_group_tag(TAG)
+#endif
+
/**
* __struct_group() - Create a mirrored named and anonyomous struct
*
@@ -20,13 +27,13 @@
* and size: one anonymous and one named. The former's members can be used
* normally without sub-struct naming, and the latter can be used to
* reason about the start, end, and size of the group of struct members.
- * The named struct can also be explicitly tagged for layer reuse, as well
- * as both having struct attributes appended.
+ * The named struct can also be explicitly tagged for layer reuse (C only),
+ * as well as both having struct attributes appended.
*/
#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \
union { \
struct { MEMBERS } ATTRS; \
- struct TAG { MEMBERS } ATTRS NAME; \
+ struct __struct_group_tag(TAG) { MEMBERS } ATTRS NAME; \
} ATTRS
#ifdef __cplusplus
diff --git a/include/uapi/linux/thermal.h b/include/uapi/linux/thermal.h
index ba8604bdf206..349718c271eb 100644
--- a/include/uapi/linux/thermal.h
+++ b/include/uapi/linux/thermal.h
@@ -3,8 +3,8 @@
#define _UAPI_LINUX_THERMAL_H
#define THERMAL_NAME_LENGTH 20
-#define THERMAL_THRESHOLD_WAY_UP BIT(0)
-#define THERMAL_THRESHOLD_WAY_DOWN BIT(1)
+#define THERMAL_THRESHOLD_WAY_UP 0x1
+#define THERMAL_THRESHOLD_WAY_DOWN 0x2
enum thermal_device_mode {
THERMAL_DEVICE_DISABLED = 0,
diff --git a/include/uapi/linux/types.h b/include/uapi/linux/types.h
index 6375a0684052..48b933938877 100644
--- a/include/uapi/linux/types.h
+++ b/include/uapi/linux/types.h
@@ -53,6 +53,7 @@ typedef __u32 __bitwise __wsum;
* No conversions are necessary between 32-bit user-space and a 64-bit kernel.
*/
#define __aligned_u64 __u64 __attribute__((aligned(8)))
+#define __aligned_s64 __s64 __attribute__((aligned(8)))
#define __aligned_be64 __be64 __attribute__((aligned(8)))
#define __aligned_le64 __le64 __attribute__((aligned(8)))
diff --git a/include/uapi/linux/usb/video.h b/include/uapi/linux/usb/video.h
index 2ff0e8a3a683..526b5155e23c 100644
--- a/include/uapi/linux/usb/video.h
+++ b/include/uapi/linux/usb/video.h
@@ -597,5 +597,63 @@ struct UVC_FRAME_MJPEG(n) { \
__le32 dwFrameInterval[n]; \
} __attribute__ ((packed))
+/* Frame Based Payload - 3.1.1. Frame Based Video Format Descriptor */
+struct uvc_format_framebased {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+ __u8 bFormatIndex;
+ __u8 bNumFrameDescriptors;
+ __u8 guidFormat[16];
+ __u8 bBitsPerPixel;
+ __u8 bDefaultFrameIndex;
+ __u8 bAspectRatioX;
+ __u8 bAspectRatioY;
+ __u8 bmInterfaceFlags;
+ __u8 bCopyProtect;
+ __u8 bVariableSize;
+} __attribute__((__packed__));
+
+#define UVC_DT_FORMAT_FRAMEBASED_SIZE 28
+
+/* Frame Based Payload - 3.1.2. Frame Based Video Frame Descriptor */
+struct uvc_frame_framebased {
+ __u8 bLength;
+ __u8 bDescriptorType;
+ __u8 bDescriptorSubType;
+ __u8 bFrameIndex;
+ __u8 bmCapabilities;
+ __u16 wWidth;
+ __u16 wHeight;
+ __u32 dwMinBitRate;
+ __u32 dwMaxBitRate;
+ __u32 dwDefaultFrameInterval;
+ __u8 bFrameIntervalType;
+ __u32 dwBytesPerLine;
+ __u32 dwFrameInterval[];
+} __attribute__((__packed__));
+
+#define UVC_DT_FRAME_FRAMEBASED_SIZE(n) (26+4*(n))
+
+#define UVC_FRAME_FRAMEBASED(n) \
+ uvc_frame_framebased_##n
+
+#define DECLARE_UVC_FRAME_FRAMEBASED(n) \
+struct UVC_FRAME_FRAMEBASED(n) { \
+ __u8 bLength; \
+ __u8 bDescriptorType; \
+ __u8 bDescriptorSubType; \
+ __u8 bFrameIndex; \
+ __u8 bmCapabilities; \
+ __u16 wWidth; \
+ __u16 wHeight; \
+ __u32 dwMinBitRate; \
+ __u32 dwMaxBitRate; \
+ __u32 dwDefaultFrameInterval; \
+ __u8 bFrameIntervalType; \
+ __u32 dwBytesPerLine; \
+ __u32 dwFrameInterval[n]; \
+} __attribute__ ((packed))
+
#endif /* __LINUX_USB_VIDEO_H */
diff --git a/include/ufs/ufshcd.h b/include/ufs/ufshcd.h
index d7aca9e61684..74e5b9960c54 100644
--- a/include/ufs/ufshcd.h
+++ b/include/ufs/ufshcd.h
@@ -310,7 +310,9 @@ struct ufs_pwr_mode_info {
* to allow variant specific Uni-Pro initialization.
* @pwr_change_notify: called before and after a power mode change
* is carried out to allow vendor spesific capabilities
- * to be set.
+ * to be set. PRE_CHANGE can modify final_params based
+ * on desired_pwr_mode, but POST_CHANGE must not alter
+ * the final_params parameter
* @setup_xfer_req: called before any transfer request is issued
* to set some things
* @setup_task_mgmt: called before any task management request is issued
@@ -327,7 +329,6 @@ struct ufs_pwr_mode_info {
* @program_key: program or evict an inline encryption key
* @fill_crypto_prdt: initialize crypto-related fields in the PRDT
* @event_notify: called to notify important events
- * @reinit_notify: called to notify reinit of UFSHCD during max gear switch
* @mcq_config_resource: called to configure MCQ platform resources
* @get_hba_mac: reports maximum number of outstanding commands supported by
* the controller. Should be implemented for UFSHCI 4.0 or later
@@ -353,9 +354,9 @@ struct ufs_hba_variant_ops {
int (*link_startup_notify)(struct ufs_hba *,
enum ufs_notify_change_status);
int (*pwr_change_notify)(struct ufs_hba *,
- enum ufs_notify_change_status status,
- struct ufs_pa_layer_attr *,
- struct ufs_pa_layer_attr *);
+ enum ufs_notify_change_status status,
+ struct ufs_pa_layer_attr *desired_pwr_mode,
+ struct ufs_pa_layer_attr *final_params);
void (*setup_xfer_req)(struct ufs_hba *hba, int tag,
bool is_scsi_cmd);
void (*setup_task_mgmt)(struct ufs_hba *, int, u8);
@@ -379,7 +380,6 @@ struct ufs_hba_variant_ops {
void *prdt, unsigned int num_segments);
void (*event_notify)(struct ufs_hba *hba,
enum ufs_event_type evt, void *data);
- void (*reinit_notify)(struct ufs_hba *);
int (*mcq_config_resource)(struct ufs_hba *hba);
int (*get_hba_mac)(struct ufs_hba *hba);
int (*op_runtime_config)(struct ufs_hba *hba);
diff --git a/io_uring/io_uring.c b/io_uring/io_uring.c
index 801293399883..ff691f37462c 100644
--- a/io_uring/io_uring.c
+++ b/io_uring/io_uring.c
@@ -121,6 +121,7 @@
#define IO_COMPL_BATCH 32
#define IO_REQ_ALLOC_BATCH 8
+#define IO_LOCAL_TW_DEFAULT_MAX 20
struct io_defer_entry {
struct list_head list;
@@ -214,9 +215,9 @@ bool io_match_task_safe(struct io_kiocb *head, struct io_uring_task *tctx,
struct io_ring_ctx *ctx = head->ctx;
/* protect against races with linked timeouts */
- spin_lock_irq(&ctx->timeout_lock);
+ raw_spin_lock_irq(&ctx->timeout_lock);
matched = io_match_linked(head);
- spin_unlock_irq(&ctx->timeout_lock);
+ raw_spin_unlock_irq(&ctx->timeout_lock);
} else {
matched = io_match_linked(head);
}
@@ -319,7 +320,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
ret |= io_alloc_cache_init(&ctx->rw_cache, IO_ALLOC_CACHE_MAX,
sizeof(struct io_async_rw));
ret |= io_alloc_cache_init(&ctx->uring_cache, IO_ALLOC_CACHE_MAX,
- sizeof(struct uring_cache));
+ sizeof(struct io_uring_cmd_data));
spin_lock_init(&ctx->msg_lock);
ret |= io_alloc_cache_init(&ctx->msg_cache, IO_ALLOC_CACHE_MAX,
sizeof(struct io_kiocb));
@@ -332,7 +333,7 @@ static __cold struct io_ring_ctx *io_ring_ctx_alloc(struct io_uring_params *p)
init_waitqueue_head(&ctx->cq_wait);
init_waitqueue_head(&ctx->poll_wq);
spin_lock_init(&ctx->completion_lock);
- spin_lock_init(&ctx->timeout_lock);
+ raw_spin_lock_init(&ctx->timeout_lock);
INIT_WQ_LIST(&ctx->iopoll_list);
INIT_LIST_HEAD(&ctx->io_buffers_comp);
INIT_LIST_HEAD(&ctx->defer_list);
@@ -497,10 +498,10 @@ static void io_prep_async_link(struct io_kiocb *req)
if (req->flags & REQ_F_LINK_TIMEOUT) {
struct io_ring_ctx *ctx = req->ctx;
- spin_lock_irq(&ctx->timeout_lock);
+ raw_spin_lock_irq(&ctx->timeout_lock);
io_for_each_link(cur, req)
io_prep_async_work(cur);
- spin_unlock_irq(&ctx->timeout_lock);
+ raw_spin_unlock_irq(&ctx->timeout_lock);
} else {
io_for_each_link(cur, req)
io_prep_async_work(cur);
@@ -513,7 +514,11 @@ static void io_queue_iowq(struct io_kiocb *req)
struct io_uring_task *tctx = req->tctx;
BUG_ON(!tctx);
- BUG_ON(!tctx->io_wq);
+
+ if ((current->flags & PF_KTHREAD) || !tctx->io_wq) {
+ io_req_task_queue_fail(req, -ECANCELED);
+ return;
+ }
/* init ->work of the whole link before punting */
io_prep_async_link(req);
@@ -1255,12 +1260,14 @@ static void __cold io_move_task_work_from_local(struct io_ring_ctx *ctx)
struct llist_node *node = llist_del_all(&ctx->work_llist);
__io_fallback_tw(node, false);
+ node = llist_del_all(&ctx->retry_llist);
+ __io_fallback_tw(node, false);
}
static bool io_run_local_work_continue(struct io_ring_ctx *ctx, int events,
int min_events)
{
- if (llist_empty(&ctx->work_llist))
+ if (!io_local_work_pending(ctx))
return false;
if (events < min_events)
return true;
@@ -1269,8 +1276,29 @@ static bool io_run_local_work_continue(struct io_ring_ctx *ctx, int events,
return false;
}
+static int __io_run_local_work_loop(struct llist_node **node,
+ struct io_tw_state *ts,
+ int events)
+{
+ int ret = 0;
+
+ while (*node) {
+ struct llist_node *next = (*node)->next;
+ struct io_kiocb *req = container_of(*node, struct io_kiocb,
+ io_task_work.node);
+ INDIRECT_CALL_2(req->io_task_work.func,
+ io_poll_task_func, io_req_rw_complete,
+ req, ts);
+ *node = next;
+ if (++ret >= events)
+ break;
+ }
+
+ return ret;
+}
+
static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts,
- int min_events)
+ int min_events, int max_events)
{
struct llist_node *node;
unsigned int loops = 0;
@@ -1281,25 +1309,23 @@ static int __io_run_local_work(struct io_ring_ctx *ctx, struct io_tw_state *ts,
if (ctx->flags & IORING_SETUP_TASKRUN_FLAG)
atomic_andnot(IORING_SQ_TASKRUN, &ctx->rings->sq_flags);
again:
+ min_events -= ret;
+ ret = __io_run_local_work_loop(&ctx->retry_llist.first, ts, max_events);
+ if (ctx->retry_llist.first)
+ goto retry_done;
+
/*
* llists are in reverse order, flip it back the right way before
* running the pending items.
*/
node = llist_reverse_order(llist_del_all(&ctx->work_llist));
- while (node) {
- struct llist_node *next = node->next;
- struct io_kiocb *req = container_of(node, struct io_kiocb,
- io_task_work.node);
- INDIRECT_CALL_2(req->io_task_work.func,
- io_poll_task_func, io_req_rw_complete,
- req, ts);
- ret++;
- node = next;
- }
+ ret += __io_run_local_work_loop(&node, ts, max_events - ret);
+ ctx->retry_llist.first = node;
loops++;
if (io_run_local_work_continue(ctx, ret, min_events))
goto again;
+retry_done:
io_submit_flush_completions(ctx);
if (io_run_local_work_continue(ctx, ret, min_events))
goto again;
@@ -1313,18 +1339,20 @@ static inline int io_run_local_work_locked(struct io_ring_ctx *ctx,
{
struct io_tw_state ts = {};
- if (llist_empty(&ctx->work_llist))
+ if (!io_local_work_pending(ctx))
return 0;
- return __io_run_local_work(ctx, &ts, min_events);
+ return __io_run_local_work(ctx, &ts, min_events,
+ max(IO_LOCAL_TW_DEFAULT_MAX, min_events));
}
-static int io_run_local_work(struct io_ring_ctx *ctx, int min_events)
+static int io_run_local_work(struct io_ring_ctx *ctx, int min_events,
+ int max_events)
{
struct io_tw_state ts = {};
int ret;
mutex_lock(&ctx->uring_lock);
- ret = __io_run_local_work(ctx, &ts, min_events);
+ ret = __io_run_local_work(ctx, &ts, min_events, max_events);
mutex_unlock(&ctx->uring_lock);
return ret;
}
@@ -2328,9 +2356,9 @@ static int io_wake_function(struct wait_queue_entry *curr, unsigned int mode,
int io_run_task_work_sig(struct io_ring_ctx *ctx)
{
- if (!llist_empty(&ctx->work_llist)) {
+ if (io_local_work_pending(ctx)) {
__set_current_state(TASK_RUNNING);
- if (io_run_local_work(ctx, INT_MAX) > 0)
+ if (io_run_local_work(ctx, INT_MAX, IO_LOCAL_TW_DEFAULT_MAX) > 0)
return 0;
}
if (io_run_task_work() > 0)
@@ -2459,7 +2487,7 @@ static inline int io_cqring_wait_schedule(struct io_ring_ctx *ctx,
{
if (unlikely(READ_ONCE(ctx->check_cq)))
return 1;
- if (unlikely(!llist_empty(&ctx->work_llist)))
+ if (unlikely(io_local_work_pending(ctx)))
return 1;
if (unlikely(task_work_pending(current)))
return 1;
@@ -2493,8 +2521,9 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, u32 flags,
if (!io_allowed_run_tw(ctx))
return -EEXIST;
- if (!llist_empty(&ctx->work_llist))
- io_run_local_work(ctx, min_events);
+ if (io_local_work_pending(ctx))
+ io_run_local_work(ctx, min_events,
+ max(IO_LOCAL_TW_DEFAULT_MAX, min_events));
io_run_task_work();
if (unlikely(test_bit(IO_CHECK_CQ_OVERFLOW_BIT, &ctx->check_cq)))
@@ -2564,8 +2593,8 @@ static int io_cqring_wait(struct io_ring_ctx *ctx, int min_events, u32 flags,
* If we got woken because of task_work being processed, run it
* now rather than let the caller do another wait loop.
*/
- if (!llist_empty(&ctx->work_llist))
- io_run_local_work(ctx, nr_wait);
+ if (io_local_work_pending(ctx))
+ io_run_local_work(ctx, nr_wait, nr_wait);
io_run_task_work();
/*
@@ -3077,7 +3106,7 @@ static __cold bool io_uring_try_cancel_requests(struct io_ring_ctx *ctx,
if ((ctx->flags & IORING_SETUP_DEFER_TASKRUN) &&
io_allowed_defer_tw_run(ctx))
- ret |= io_run_local_work(ctx, INT_MAX) > 0;
+ ret |= io_run_local_work(ctx, INT_MAX, INT_MAX) > 0;
ret |= io_cancel_defer_files(ctx, tctx, cancel_all);
mutex_lock(&ctx->uring_lock);
ret |= io_poll_remove_all(ctx, tctx, cancel_all);
@@ -3158,7 +3187,7 @@ __cold void io_uring_cancel_generic(bool cancel_all, struct io_sq_data *sqd)
io_run_task_work();
io_uring_drop_tctx_refs(current);
xa_for_each(&tctx->xa, index, node) {
- if (!llist_empty(&node->ctx->work_llist)) {
+ if (io_local_work_pending(node->ctx)) {
WARN_ON_ONCE(node->ctx->submitter_task &&
node->ctx->submitter_task != current);
goto end_wait;
@@ -3189,6 +3218,7 @@ end_wait:
void __io_uring_cancel(bool cancel_all)
{
+ io_uring_unreg_ringfd();
io_uring_cancel_generic(cancel_all, NULL);
}
diff --git a/io_uring/io_uring.h b/io_uring/io_uring.h
index 4070d4c8ef97..12abee607e4a 100644
--- a/io_uring/io_uring.h
+++ b/io_uring/io_uring.h
@@ -347,9 +347,14 @@ static inline int io_run_task_work(void)
return ret;
}
+static inline bool io_local_work_pending(struct io_ring_ctx *ctx)
+{
+ return !llist_empty(&ctx->work_llist) || !llist_empty(&ctx->retry_llist);
+}
+
static inline bool io_task_work_pending(struct io_ring_ctx *ctx)
{
- return task_work_pending(current) || !llist_empty(&ctx->work_llist);
+ return task_work_pending(current) || io_local_work_pending(ctx);
}
static inline void io_tw_lock(struct io_ring_ctx *ctx, struct io_tw_state *ts)
@@ -484,6 +489,6 @@ enum {
static inline bool io_has_work(struct io_ring_ctx *ctx)
{
return test_bit(IO_CHECK_CQ_OVERFLOW_BIT, &ctx->check_cq) ||
- !llist_empty(&ctx->work_llist);
+ io_local_work_pending(ctx);
}
#endif
diff --git a/io_uring/kbuf.c b/io_uring/kbuf.c
index d407576ddfb7..eec5eb7de843 100644
--- a/io_uring/kbuf.c
+++ b/io_uring/kbuf.c
@@ -139,6 +139,7 @@ static void __user *io_ring_buffer_select(struct io_kiocb *req, size_t *len,
struct io_uring_buf_ring *br = bl->buf_ring;
__u16 tail, head = bl->head;
struct io_uring_buf *buf;
+ void __user *ret;
tail = smp_load_acquire(&br->tail);
if (unlikely(tail == head))
@@ -153,6 +154,7 @@ static void __user *io_ring_buffer_select(struct io_kiocb *req, size_t *len,
req->flags |= REQ_F_BUFFER_RING | REQ_F_BUFFERS_COMMIT;
req->buf_list = bl;
req->buf_index = buf->bid;
+ ret = u64_to_user_ptr(buf->addr);
if (issue_flags & IO_URING_F_UNLOCKED || !io_file_can_poll(req)) {
/*
@@ -168,7 +170,7 @@ static void __user *io_ring_buffer_select(struct io_kiocb *req, size_t *len,
io_kbuf_commit(req, bl, *len, 1);
req->buf_list = NULL;
}
- return u64_to_user_ptr(buf->addr);
+ return ret;
}
void __user *io_buffer_select(struct io_kiocb *req, size_t *len,
diff --git a/io_uring/memmap.c b/io_uring/memmap.c
index 6e6ee79ba94f..57de9bccbf50 100644
--- a/io_uring/memmap.c
+++ b/io_uring/memmap.c
@@ -73,6 +73,8 @@ void *io_pages_map(struct page ***out_pages, unsigned short *npages,
ret = io_mem_alloc_compound(pages, nr_pages, size, gfp);
if (!IS_ERR(ret))
goto done;
+ if (nr_pages == 1)
+ goto fail;
ret = io_mem_alloc_single(pages, nr_pages, size, gfp);
if (!IS_ERR(ret)) {
@@ -81,7 +83,7 @@ done:
*npages = nr_pages;
return ret;
}
-
+fail:
kvfree(pages);
*out_pages = NULL;
*npages = 0;
@@ -136,7 +138,12 @@ struct page **io_pin_pages(unsigned long uaddr, unsigned long len, int *npages)
struct page **pages;
int ret;
- end = (uaddr + len + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ if (check_add_overflow(uaddr, len, &end))
+ return ERR_PTR(-EOVERFLOW);
+ if (check_add_overflow(end, PAGE_SIZE - 1, &end))
+ return ERR_PTR(-EOVERFLOW);
+
+ end = end >> PAGE_SHIFT;
start = uaddr >> PAGE_SHIFT;
nr_pages = end - start;
if (WARN_ON_ONCE(!nr_pages))
@@ -229,7 +236,7 @@ int io_create_region(struct io_ring_ctx *ctx, struct io_mapped_region *mr,
if (!reg->size || reg->mmap_offset || reg->id)
return -EINVAL;
if ((reg->size >> PAGE_SHIFT) > INT_MAX)
- return E2BIG;
+ return -E2BIG;
if ((reg->user_addr | reg->size) & ~PAGE_MASK)
return -EINVAL;
if (check_add_overflow(reg->user_addr, reg->size, &end))
diff --git a/io_uring/net.c b/io_uring/net.c
index df1f7dc6f1c8..c6cd38cc5dc4 100644
--- a/io_uring/net.c
+++ b/io_uring/net.c
@@ -754,6 +754,7 @@ static int io_recvmsg_prep_setup(struct io_kiocb *req)
if (req->opcode == IORING_OP_RECV) {
kmsg->msg.msg_name = NULL;
kmsg->msg.msg_namelen = 0;
+ kmsg->msg.msg_inq = 0;
kmsg->msg.msg_control = NULL;
kmsg->msg.msg_get_inq = 1;
kmsg->msg.msg_controllen = 0;
diff --git a/io_uring/nop.c b/io_uring/nop.c
index 6d470d4251ee..5e5196df650a 100644
--- a/io_uring/nop.c
+++ b/io_uring/nop.c
@@ -35,10 +35,14 @@ int io_nop_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe)
nop->result = READ_ONCE(sqe->len);
else
nop->result = 0;
- if (nop->flags & IORING_NOP_FIXED_FILE)
+ if (nop->flags & IORING_NOP_FILE)
nop->fd = READ_ONCE(sqe->fd);
+ else
+ nop->fd = -1;
if (nop->flags & IORING_NOP_FIXED_BUFFER)
nop->buffer = READ_ONCE(sqe->buf_index);
+ else
+ nop->buffer = -1;
return 0;
}
diff --git a/io_uring/opdef.c b/io_uring/opdef.c
index 3de75eca1c92..e8baef4e5146 100644
--- a/io_uring/opdef.c
+++ b/io_uring/opdef.c
@@ -7,6 +7,7 @@
#include <linux/fs.h>
#include <linux/file.h>
#include <linux/io_uring.h>
+#include <linux/io_uring/cmd.h>
#include "io_uring.h"
#include "opdef.h"
@@ -414,7 +415,7 @@ const struct io_issue_def io_issue_defs[] = {
.plug = 1,
.iopoll = 1,
.iopoll_queue = 1,
- .async_size = 2 * sizeof(struct io_uring_sqe),
+ .async_size = sizeof(struct io_uring_cmd_data),
.prep = io_uring_cmd_prep,
.issue = io_uring_cmd,
},
diff --git a/io_uring/register.c b/io_uring/register.c
index 1a60f4916649..fdd44914c39c 100644
--- a/io_uring/register.c
+++ b/io_uring/register.c
@@ -414,6 +414,9 @@ static int io_register_resize_rings(struct io_ring_ctx *ctx, void __user *arg)
if (ctx->flags & IORING_SETUP_SINGLE_ISSUER &&
current != ctx->submitter_task)
return -EEXIST;
+ /* limited to DEFER_TASKRUN for now */
+ if (!(ctx->flags & IORING_SETUP_DEFER_TASKRUN))
+ return -EINVAL;
if (copy_from_user(&p, arg, sizeof(p)))
return -EFAULT;
if (p.flags & ~RESIZE_FLAGS)
@@ -905,9 +908,10 @@ SYSCALL_DEFINE4(io_uring_register, unsigned int, fd, unsigned int, opcode,
mutex_lock(&ctx->uring_lock);
ret = __io_uring_register(ctx, opcode, arg, nr_args);
- mutex_unlock(&ctx->uring_lock);
+
trace_io_uring_register(ctx, opcode, ctx->file_table.data.nr,
ctx->buf_table.nr, ret);
+ mutex_unlock(&ctx->uring_lock);
if (!use_registered_ring)
fput(file);
return ret;
diff --git a/io_uring/rsrc.c b/io_uring/rsrc.c
index adaae8630932..077f84684c18 100644
--- a/io_uring/rsrc.c
+++ b/io_uring/rsrc.c
@@ -1036,8 +1036,10 @@ static int io_clone_buffers(struct io_ring_ctx *ctx, struct io_ring_ctx *src_ctx
out_put_free:
i = data.nr;
while (i--) {
- io_buffer_unmap(src_ctx, data.nodes[i]);
- kfree(data.nodes[i]);
+ if (data.nodes[i]) {
+ io_buffer_unmap(src_ctx, data.nodes[i]);
+ kfree(data.nodes[i]);
+ }
}
out_unlock:
io_rsrc_data_free(ctx, &data);
diff --git a/io_uring/rw.c b/io_uring/rw.c
index 0bcb83e4ce3c..29bb3010f9c0 100644
--- a/io_uring/rw.c
+++ b/io_uring/rw.c
@@ -983,6 +983,8 @@ int io_read_mshot(struct io_kiocb *req, unsigned int issue_flags)
io_kbuf_recycle(req, issue_flags);
if (ret < 0)
req_set_fail(req);
+ } else if (!(req->flags & REQ_F_APOLL_MULTISHOT)) {
+ cflags = io_put_kbuf(req, ret, issue_flags);
} else {
/*
* Any successful return value will keep the multishot read
diff --git a/io_uring/sqpoll.c b/io_uring/sqpoll.c
index 6df5e649c413..9e5bd79fd2b5 100644
--- a/io_uring/sqpoll.c
+++ b/io_uring/sqpoll.c
@@ -405,6 +405,7 @@ void io_sqpoll_wait_sq(struct io_ring_ctx *ctx)
__cold int io_sq_offload_create(struct io_ring_ctx *ctx,
struct io_uring_params *p)
{
+ struct task_struct *task_to_put = NULL;
int ret;
/* Retain compatibility with failing for an invalid attach attempt */
@@ -480,6 +481,7 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx,
}
sqd->thread = tsk;
+ task_to_put = get_task_struct(tsk);
ret = io_uring_alloc_task_context(tsk, ctx);
wake_up_new_task(tsk);
if (ret)
@@ -490,11 +492,15 @@ __cold int io_sq_offload_create(struct io_ring_ctx *ctx,
goto err;
}
+ if (task_to_put)
+ put_task_struct(task_to_put);
return 0;
err_sqpoll:
complete(&ctx->sq_data->exited);
err:
io_sq_thread_finish(ctx);
+ if (task_to_put)
+ put_task_struct(task_to_put);
return ret;
}
diff --git a/io_uring/tctx.c b/io_uring/tctx.c
index 503f3ff8bc4f..adc6e42c14df 100644
--- a/io_uring/tctx.c
+++ b/io_uring/tctx.c
@@ -47,8 +47,19 @@ static struct io_wq *io_init_wq_offload(struct io_ring_ctx *ctx,
void __io_uring_free(struct task_struct *tsk)
{
struct io_uring_task *tctx = tsk->io_uring;
+ struct io_tctx_node *node;
+ unsigned long index;
- WARN_ON_ONCE(!xa_empty(&tctx->xa));
+ /*
+ * Fault injection forcing allocation errors in the xa_store() path
+ * can lead to xa_empty() returning false, even though no actual
+ * node is stored in the xarray. Until that gets sorted out, attempt
+ * an iteration here and warn if any entries are found.
+ */
+ xa_for_each(&tctx->xa, index, node) {
+ WARN_ON_ONCE(1);
+ break;
+ }
WARN_ON_ONCE(tctx->io_wq);
WARN_ON_ONCE(tctx->cached_refs);
diff --git a/io_uring/timeout.c b/io_uring/timeout.c
index f3d502717aeb..362689b17ccc 100644
--- a/io_uring/timeout.c
+++ b/io_uring/timeout.c
@@ -74,10 +74,10 @@ static void io_timeout_complete(struct io_kiocb *req, struct io_tw_state *ts)
if (!io_timeout_finish(timeout, data)) {
if (io_req_post_cqe(req, -ETIME, IORING_CQE_F_MORE)) {
/* re-arm timer */
- spin_lock_irq(&ctx->timeout_lock);
+ raw_spin_lock_irq(&ctx->timeout_lock);
list_add(&timeout->list, ctx->timeout_list.prev);
hrtimer_start(&data->timer, timespec64_to_ktime(data->ts), data->mode);
- spin_unlock_irq(&ctx->timeout_lock);
+ raw_spin_unlock_irq(&ctx->timeout_lock);
return;
}
}
@@ -85,7 +85,27 @@ static void io_timeout_complete(struct io_kiocb *req, struct io_tw_state *ts)
io_req_task_complete(req, ts);
}
-static bool io_kill_timeout(struct io_kiocb *req, int status)
+static __cold bool io_flush_killed_timeouts(struct list_head *list, int err)
+{
+ if (list_empty(list))
+ return false;
+
+ while (!list_empty(list)) {
+ struct io_timeout *timeout;
+ struct io_kiocb *req;
+
+ timeout = list_first_entry(list, struct io_timeout, list);
+ list_del_init(&timeout->list);
+ req = cmd_to_io_kiocb(timeout);
+ if (err)
+ req_set_fail(req);
+ io_req_queue_tw_complete(req, err);
+ }
+
+ return true;
+}
+
+static void io_kill_timeout(struct io_kiocb *req, struct list_head *list)
__must_hold(&req->ctx->timeout_lock)
{
struct io_timeout_data *io = req->async_data;
@@ -93,23 +113,19 @@ static bool io_kill_timeout(struct io_kiocb *req, int status)
if (hrtimer_try_to_cancel(&io->timer) != -1) {
struct io_timeout *timeout = io_kiocb_to_cmd(req, struct io_timeout);
- if (status)
- req_set_fail(req);
atomic_set(&req->ctx->cq_timeouts,
atomic_read(&req->ctx->cq_timeouts) + 1);
- list_del_init(&timeout->list);
- io_req_queue_tw_complete(req, status);
- return true;
+ list_move_tail(&timeout->list, list);
}
- return false;
}
__cold void io_flush_timeouts(struct io_ring_ctx *ctx)
{
- u32 seq;
struct io_timeout *timeout, *tmp;
+ LIST_HEAD(list);
+ u32 seq;
- spin_lock_irq(&ctx->timeout_lock);
+ raw_spin_lock_irq(&ctx->timeout_lock);
seq = ctx->cached_cq_tail - atomic_read(&ctx->cq_timeouts);
list_for_each_entry_safe(timeout, tmp, &ctx->timeout_list, list) {
@@ -131,10 +147,11 @@ __cold void io_flush_timeouts(struct io_ring_ctx *ctx)
if (events_got < events_needed)
break;
- io_kill_timeout(req, 0);
+ io_kill_timeout(req, &list);
}
ctx->cq_last_tm_flush = seq;
- spin_unlock_irq(&ctx->timeout_lock);
+ raw_spin_unlock_irq(&ctx->timeout_lock);
+ io_flush_killed_timeouts(&list, 0);
}
static void io_req_tw_fail_links(struct io_kiocb *link, struct io_tw_state *ts)
@@ -200,9 +217,9 @@ void io_disarm_next(struct io_kiocb *req)
} else if (req->flags & REQ_F_LINK_TIMEOUT) {
struct io_ring_ctx *ctx = req->ctx;
- spin_lock_irq(&ctx->timeout_lock);
+ raw_spin_lock_irq(&ctx->timeout_lock);
link = io_disarm_linked_timeout(req);
- spin_unlock_irq(&ctx->timeout_lock);
+ raw_spin_unlock_irq(&ctx->timeout_lock);
if (link)
io_req_queue_tw_complete(link, -ECANCELED);
}
@@ -238,11 +255,11 @@ static enum hrtimer_restart io_timeout_fn(struct hrtimer *timer)
struct io_ring_ctx *ctx = req->ctx;
unsigned long flags;
- spin_lock_irqsave(&ctx->timeout_lock, flags);
+ raw_spin_lock_irqsave(&ctx->timeout_lock, flags);
list_del_init(&timeout->list);
atomic_set(&req->ctx->cq_timeouts,
atomic_read(&req->ctx->cq_timeouts) + 1);
- spin_unlock_irqrestore(&ctx->timeout_lock, flags);
+ raw_spin_unlock_irqrestore(&ctx->timeout_lock, flags);
if (!(data->flags & IORING_TIMEOUT_ETIME_SUCCESS))
req_set_fail(req);
@@ -285,9 +302,9 @@ int io_timeout_cancel(struct io_ring_ctx *ctx, struct io_cancel_data *cd)
{
struct io_kiocb *req;
- spin_lock_irq(&ctx->timeout_lock);
+ raw_spin_lock_irq(&ctx->timeout_lock);
req = io_timeout_extract(ctx, cd);
- spin_unlock_irq(&ctx->timeout_lock);
+ raw_spin_unlock_irq(&ctx->timeout_lock);
if (IS_ERR(req))
return PTR_ERR(req);
@@ -330,7 +347,7 @@ static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer)
struct io_ring_ctx *ctx = req->ctx;
unsigned long flags;
- spin_lock_irqsave(&ctx->timeout_lock, flags);
+ raw_spin_lock_irqsave(&ctx->timeout_lock, flags);
prev = timeout->head;
timeout->head = NULL;
@@ -345,7 +362,7 @@ static enum hrtimer_restart io_link_timeout_fn(struct hrtimer *timer)
}
list_del(&timeout->list);
timeout->prev = prev;
- spin_unlock_irqrestore(&ctx->timeout_lock, flags);
+ raw_spin_unlock_irqrestore(&ctx->timeout_lock, flags);
req->io_task_work.func = io_req_task_link_timeout;
io_req_task_work_add(req);
@@ -472,12 +489,12 @@ int io_timeout_remove(struct io_kiocb *req, unsigned int issue_flags)
} else {
enum hrtimer_mode mode = io_translate_timeout_mode(tr->flags);
- spin_lock_irq(&ctx->timeout_lock);
+ raw_spin_lock_irq(&ctx->timeout_lock);
if (tr->ltimeout)
ret = io_linked_timeout_update(ctx, tr->addr, &tr->ts, mode);
else
ret = io_timeout_update(ctx, tr->addr, &tr->ts, mode);
- spin_unlock_irq(&ctx->timeout_lock);
+ raw_spin_unlock_irq(&ctx->timeout_lock);
}
if (ret < 0)
@@ -572,7 +589,7 @@ int io_timeout(struct io_kiocb *req, unsigned int issue_flags)
struct list_head *entry;
u32 tail, off = timeout->off;
- spin_lock_irq(&ctx->timeout_lock);
+ raw_spin_lock_irq(&ctx->timeout_lock);
/*
* sqe->off holds how many events that need to occur for this
@@ -611,7 +628,7 @@ add:
list_add(&timeout->list, entry);
data->timer.function = io_timeout_fn;
hrtimer_start(&data->timer, timespec64_to_ktime(data->ts), data->mode);
- spin_unlock_irq(&ctx->timeout_lock);
+ raw_spin_unlock_irq(&ctx->timeout_lock);
return IOU_ISSUE_SKIP_COMPLETE;
}
@@ -620,7 +637,7 @@ void io_queue_linked_timeout(struct io_kiocb *req)
struct io_timeout *timeout = io_kiocb_to_cmd(req, struct io_timeout);
struct io_ring_ctx *ctx = req->ctx;
- spin_lock_irq(&ctx->timeout_lock);
+ raw_spin_lock_irq(&ctx->timeout_lock);
/*
* If the back reference is NULL, then our linked request finished
* before we got a chance to setup the timer
@@ -633,7 +650,7 @@ void io_queue_linked_timeout(struct io_kiocb *req)
data->mode);
list_add_tail(&timeout->list, &ctx->ltimeout_list);
}
- spin_unlock_irq(&ctx->timeout_lock);
+ raw_spin_unlock_irq(&ctx->timeout_lock);
/* drop submission reference */
io_put_req(req);
}
@@ -661,22 +678,22 @@ __cold bool io_kill_timeouts(struct io_ring_ctx *ctx, struct io_uring_task *tctx
bool cancel_all)
{
struct io_timeout *timeout, *tmp;
- int canceled = 0;
+ LIST_HEAD(list);
/*
* completion_lock is needed for io_match_task(). Take it before
* timeout_lockfirst to keep locking ordering.
*/
spin_lock(&ctx->completion_lock);
- spin_lock_irq(&ctx->timeout_lock);
+ raw_spin_lock_irq(&ctx->timeout_lock);
list_for_each_entry_safe(timeout, tmp, &ctx->timeout_list, list) {
struct io_kiocb *req = cmd_to_io_kiocb(timeout);
- if (io_match_task(req, tctx, cancel_all) &&
- io_kill_timeout(req, -ECANCELED))
- canceled++;
+ if (io_match_task(req, tctx, cancel_all))
+ io_kill_timeout(req, &list);
}
- spin_unlock_irq(&ctx->timeout_lock);
+ raw_spin_unlock_irq(&ctx->timeout_lock);
spin_unlock(&ctx->completion_lock);
- return canceled != 0;
+
+ return io_flush_killed_timeouts(&list, -ECANCELED);
}
diff --git a/io_uring/uring_cmd.c b/io_uring/uring_cmd.c
index d9fb2143f56f..ce7726a04883 100644
--- a/io_uring/uring_cmd.c
+++ b/io_uring/uring_cmd.c
@@ -16,26 +16,35 @@
#include "rsrc.h"
#include "uring_cmd.h"
-static struct uring_cache *io_uring_async_get(struct io_kiocb *req)
+static struct io_uring_cmd_data *io_uring_async_get(struct io_kiocb *req)
{
struct io_ring_ctx *ctx = req->ctx;
- struct uring_cache *cache;
+ struct io_uring_cmd_data *cache;
cache = io_alloc_cache_get(&ctx->uring_cache);
if (cache) {
+ cache->op_data = NULL;
req->flags |= REQ_F_ASYNC_DATA;
req->async_data = cache;
return cache;
}
- if (!io_alloc_async_data(req))
- return req->async_data;
+ if (!io_alloc_async_data(req)) {
+ cache = req->async_data;
+ cache->op_data = NULL;
+ return cache;
+ }
return NULL;
}
static void io_req_uring_cleanup(struct io_kiocb *req, unsigned int issue_flags)
{
struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
- struct uring_cache *cache = req->async_data;
+ struct io_uring_cmd_data *cache = req->async_data;
+
+ if (cache->op_data) {
+ kfree(cache->op_data);
+ cache->op_data = NULL;
+ }
if (issue_flags & IO_URING_F_UNLOCKED)
return;
@@ -151,7 +160,7 @@ static inline void io_req_set_cqe32_extra(struct io_kiocb *req,
* Called by consumers of io_uring_cmd, if they originally returned
* -EIOCBQUEUED upon receiving the command.
*/
-void io_uring_cmd_done(struct io_uring_cmd *ioucmd, ssize_t ret, ssize_t res2,
+void io_uring_cmd_done(struct io_uring_cmd *ioucmd, ssize_t ret, u64 res2,
unsigned issue_flags)
{
struct io_kiocb *req = cmd_to_io_kiocb(ioucmd);
@@ -183,7 +192,7 @@ static int io_uring_cmd_prep_setup(struct io_kiocb *req,
const struct io_uring_sqe *sqe)
{
struct io_uring_cmd *ioucmd = io_kiocb_to_cmd(req, struct io_uring_cmd);
- struct uring_cache *cache;
+ struct io_uring_cmd_data *cache;
cache = io_uring_async_get(req);
if (unlikely(!cache))
@@ -260,7 +269,7 @@ int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags)
ret = file->f_op->uring_cmd(ioucmd, issue_flags);
if (ret == -EAGAIN) {
- struct uring_cache *cache = req->async_data;
+ struct io_uring_cmd_data *cache = req->async_data;
if (ioucmd->sqe != (void *) cache)
memcpy(cache, ioucmd->sqe, uring_sqe_size(req->ctx));
diff --git a/io_uring/uring_cmd.h b/io_uring/uring_cmd.h
index 7dba0f1efc58..f6837ee0955b 100644
--- a/io_uring/uring_cmd.h
+++ b/io_uring/uring_cmd.h
@@ -1,9 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
-struct uring_cache {
- struct io_uring_sqe sqes[2];
-};
-
int io_uring_cmd(struct io_kiocb *req, unsigned int issue_flags);
int io_uring_cmd_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe);
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 279ba5c420a4..561d96affe9f 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -2728,8 +2728,8 @@ void __audit_ptrace(struct task_struct *t)
context->target_auid = audit_get_loginuid(t);
context->target_uid = task_uid(t);
context->target_sessionid = audit_get_sessionid(t);
- security_task_getlsmprop_obj(t, &context->target_ref);
strscpy(context->target_comm, t->comm);
+ security_task_getlsmprop_obj(t, &context->target_ref);
}
/**
@@ -2755,8 +2755,8 @@ int audit_signal_info_syscall(struct task_struct *t)
ctx->target_auid = audit_get_loginuid(t);
ctx->target_uid = t_uid;
ctx->target_sessionid = audit_get_sessionid(t);
- security_task_getlsmprop_obj(t, &ctx->target_ref);
strscpy(ctx->target_comm, t->comm);
+ security_task_getlsmprop_obj(t, &ctx->target_ref);
return 0;
}
diff --git a/kernel/bpf/Makefile b/kernel/bpf/Makefile
index 9762bdddf1de..410028633621 100644
--- a/kernel/bpf/Makefile
+++ b/kernel/bpf/Makefile
@@ -53,3 +53,9 @@ obj-$(CONFIG_BPF_SYSCALL) += relo_core.o
obj-$(CONFIG_BPF_SYSCALL) += btf_iter.o
obj-$(CONFIG_BPF_SYSCALL) += btf_relocate.o
obj-$(CONFIG_BPF_SYSCALL) += kmem_cache_iter.o
+
+CFLAGS_REMOVE_percpu_freelist.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_bpf_lru_list.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_queue_stack_maps.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_lpm_trie.o = $(CC_FLAGS_FTRACE)
+CFLAGS_REMOVE_ringbuf.o = $(CC_FLAGS_FTRACE)
diff --git a/kernel/bpf/bpf_lsm.c b/kernel/bpf/bpf_lsm.c
index 3bc61628ab25..967492b65185 100644
--- a/kernel/bpf/bpf_lsm.c
+++ b/kernel/bpf/bpf_lsm.c
@@ -375,8 +375,6 @@ BTF_ID(func, bpf_lsm_socket_socketpair)
BTF_ID(func, bpf_lsm_syslog)
BTF_ID(func, bpf_lsm_task_alloc)
-BTF_ID(func, bpf_lsm_current_getsecid_subj)
-BTF_ID(func, bpf_lsm_task_getsecid_obj)
BTF_ID(func, bpf_lsm_task_prctl)
BTF_ID(func, bpf_lsm_task_setscheduler)
BTF_ID(func, bpf_lsm_task_to_inode)
diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
index e7a59e6462a9..e5a5f023cedd 100644
--- a/kernel/bpf/btf.c
+++ b/kernel/bpf/btf.c
@@ -6439,6 +6439,101 @@ int btf_ctx_arg_offset(const struct btf *btf, const struct btf_type *func_proto,
return off;
}
+struct bpf_raw_tp_null_args {
+ const char *func;
+ u64 mask;
+};
+
+static const struct bpf_raw_tp_null_args raw_tp_null_args[] = {
+ /* sched */
+ { "sched_pi_setprio", 0x10 },
+ /* ... from sched_numa_pair_template event class */
+ { "sched_stick_numa", 0x100 },
+ { "sched_swap_numa", 0x100 },
+ /* afs */
+ { "afs_make_fs_call", 0x10 },
+ { "afs_make_fs_calli", 0x10 },
+ { "afs_make_fs_call1", 0x10 },
+ { "afs_make_fs_call2", 0x10 },
+ { "afs_protocol_error", 0x1 },
+ { "afs_flock_ev", 0x10 },
+ /* cachefiles */
+ { "cachefiles_lookup", 0x1 | 0x200 },
+ { "cachefiles_unlink", 0x1 },
+ { "cachefiles_rename", 0x1 },
+ { "cachefiles_prep_read", 0x1 },
+ { "cachefiles_mark_active", 0x1 },
+ { "cachefiles_mark_failed", 0x1 },
+ { "cachefiles_mark_inactive", 0x1 },
+ { "cachefiles_vfs_error", 0x1 },
+ { "cachefiles_io_error", 0x1 },
+ { "cachefiles_ondemand_open", 0x1 },
+ { "cachefiles_ondemand_copen", 0x1 },
+ { "cachefiles_ondemand_close", 0x1 },
+ { "cachefiles_ondemand_read", 0x1 },
+ { "cachefiles_ondemand_cread", 0x1 },
+ { "cachefiles_ondemand_fd_write", 0x1 },
+ { "cachefiles_ondemand_fd_release", 0x1 },
+ /* ext4, from ext4__mballoc event class */
+ { "ext4_mballoc_discard", 0x10 },
+ { "ext4_mballoc_free", 0x10 },
+ /* fib */
+ { "fib_table_lookup", 0x100 },
+ /* filelock */
+ /* ... from filelock_lock event class */
+ { "posix_lock_inode", 0x10 },
+ { "fcntl_setlk", 0x10 },
+ { "locks_remove_posix", 0x10 },
+ { "flock_lock_inode", 0x10 },
+ /* ... from filelock_lease event class */
+ { "break_lease_noblock", 0x10 },
+ { "break_lease_block", 0x10 },
+ { "break_lease_unblock", 0x10 },
+ { "generic_delete_lease", 0x10 },
+ { "time_out_leases", 0x10 },
+ /* host1x */
+ { "host1x_cdma_push_gather", 0x10000 },
+ /* huge_memory */
+ { "mm_khugepaged_scan_pmd", 0x10 },
+ { "mm_collapse_huge_page_isolate", 0x1 },
+ { "mm_khugepaged_scan_file", 0x10 },
+ { "mm_khugepaged_collapse_file", 0x10 },
+ /* kmem */
+ { "mm_page_alloc", 0x1 },
+ { "mm_page_pcpu_drain", 0x1 },
+ /* .. from mm_page event class */
+ { "mm_page_alloc_zone_locked", 0x1 },
+ /* netfs */
+ { "netfs_failure", 0x10 },
+ /* power */
+ { "device_pm_callback_start", 0x10 },
+ /* qdisc */
+ { "qdisc_dequeue", 0x1000 },
+ /* rxrpc */
+ { "rxrpc_recvdata", 0x1 },
+ { "rxrpc_resend", 0x10 },
+ /* sunrpc */
+ { "xs_stream_read_data", 0x1 },
+ /* ... from xprt_cong_event event class */
+ { "xprt_reserve_cong", 0x10 },
+ { "xprt_release_cong", 0x10 },
+ { "xprt_get_cong", 0x10 },
+ { "xprt_put_cong", 0x10 },
+ /* tcp */
+ { "tcp_send_reset", 0x11 },
+ /* tegra_apb_dma */
+ { "tegra_dma_tx_status", 0x100 },
+ /* timer_migration */
+ { "tmigr_update_events", 0x1 },
+ /* writeback, from writeback_folio_template event class */
+ { "writeback_dirty_folio", 0x10 },
+ { "folio_wait_writeback", 0x10 },
+ /* rdma */
+ { "mr_integ_alloc", 0x2000 },
+ /* bpf_testmod */
+ { "bpf_testmod_test_read", 0x0 },
+};
+
bool btf_ctx_access(int off, int size, enum bpf_access_type type,
const struct bpf_prog *prog,
struct bpf_insn_access_aux *info)
@@ -6449,6 +6544,7 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
const char *tname = prog->aux->attach_func_name;
struct bpf_verifier_log *log = info->log;
const struct btf_param *args;
+ bool ptr_err_raw_tp = false;
const char *tag_value;
u32 nr_args, arg;
int i, ret;
@@ -6543,6 +6639,12 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
return false;
}
+ if (size != sizeof(u64)) {
+ bpf_log(log, "func '%s' size %d must be 8\n",
+ tname, size);
+ return false;
+ }
+
/* check for PTR_TO_RDONLY_BUF_OR_NULL or PTR_TO_RDWR_BUF_OR_NULL */
for (i = 0; i < prog->aux->ctx_arg_info_size; i++) {
const struct bpf_ctx_arg_aux *ctx_arg_info = &prog->aux->ctx_arg_info[i];
@@ -6588,12 +6690,42 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
if (prog_args_trusted(prog))
info->reg_type |= PTR_TRUSTED;
- /* Raw tracepoint arguments always get marked as maybe NULL */
- if (bpf_prog_is_raw_tp(prog))
- info->reg_type |= PTR_MAYBE_NULL;
- else if (btf_param_match_suffix(btf, &args[arg], "__nullable"))
+ if (btf_param_match_suffix(btf, &args[arg], "__nullable"))
info->reg_type |= PTR_MAYBE_NULL;
+ if (prog->expected_attach_type == BPF_TRACE_RAW_TP) {
+ struct btf *btf = prog->aux->attach_btf;
+ const struct btf_type *t;
+ const char *tname;
+
+ /* BTF lookups cannot fail, return false on error */
+ t = btf_type_by_id(btf, prog->aux->attach_btf_id);
+ if (!t)
+ return false;
+ tname = btf_name_by_offset(btf, t->name_off);
+ if (!tname)
+ return false;
+ /* Checked by bpf_check_attach_target */
+ tname += sizeof("btf_trace_") - 1;
+ for (i = 0; i < ARRAY_SIZE(raw_tp_null_args); i++) {
+ /* Is this a func with potential NULL args? */
+ if (strcmp(tname, raw_tp_null_args[i].func))
+ continue;
+ if (raw_tp_null_args[i].mask & (0x1 << (arg * 4)))
+ info->reg_type |= PTR_MAYBE_NULL;
+ /* Is the current arg IS_ERR? */
+ if (raw_tp_null_args[i].mask & (0x2 << (arg * 4)))
+ ptr_err_raw_tp = true;
+ break;
+ }
+ /* If we don't know NULL-ness specification and the tracepoint
+ * is coming from a loadable module, be conservative and mark
+ * argument as PTR_MAYBE_NULL.
+ */
+ if (i == ARRAY_SIZE(raw_tp_null_args) && btf_is_module(btf))
+ info->reg_type |= PTR_MAYBE_NULL;
+ }
+
if (tgt_prog) {
enum bpf_prog_type tgt_type;
@@ -6638,6 +6770,15 @@ bool btf_ctx_access(int off, int size, enum bpf_access_type type,
bpf_log(log, "func '%s' arg%d has btf_id %d type %s '%s'\n",
tname, arg, info->btf_id, btf_type_str(t),
__btf_name_by_offset(btf, t->name_off));
+
+ /* Perform all checks on the validity of type for this argument, but if
+ * we know it can be IS_ERR at runtime, scrub pointer type and mark as
+ * scalar.
+ */
+ if (ptr_err_raw_tp) {
+ bpf_log(log, "marking pointer arg%d as scalar as it may encode error", arg);
+ info->reg_type = SCALAR_VALUE;
+ }
return true;
}
EXPORT_SYMBOL_GPL(btf_ctx_access);
diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c
index a2327c4fdc8b..da729cbbaeb9 100644
--- a/kernel/bpf/core.c
+++ b/kernel/bpf/core.c
@@ -539,6 +539,8 @@ struct bpf_prog *bpf_patch_insn_single(struct bpf_prog *prog, u32 off,
int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt)
{
+ int err;
+
/* Branch offsets can't overflow when program is shrinking, no need
* to call bpf_adj_branches(..., true) here
*/
@@ -546,7 +548,9 @@ int bpf_remove_insns(struct bpf_prog *prog, u32 off, u32 cnt)
sizeof(struct bpf_insn) * (prog->len - off - cnt));
prog->len -= cnt;
- return WARN_ON_ONCE(bpf_adj_branches(prog, off, off + cnt, off, false));
+ err = bpf_adj_branches(prog, off, off + cnt, off, false);
+ WARN_ON_ONCE(err);
+ return err;
}
static void bpf_prog_kallsyms_del_subprogs(struct bpf_prog *fp)
@@ -2936,7 +2940,7 @@ void __weak bpf_jit_compile(struct bpf_prog *prog)
{
}
-bool __weak bpf_helper_changes_pkt_data(void *func)
+bool __weak bpf_helper_changes_pkt_data(enum bpf_func_id func_id)
{
return false;
}
diff --git a/kernel/bpf/cpumap.c b/kernel/bpf/cpumap.c
index a2f46785ac3b..774accbd4a22 100644
--- a/kernel/bpf/cpumap.c
+++ b/kernel/bpf/cpumap.c
@@ -190,7 +190,7 @@ static int cpu_map_bpf_prog_run_xdp(struct bpf_cpu_map_entry *rcpu,
int err;
rxq.dev = xdpf->dev_rx;
- rxq.mem = xdpf->mem;
+ rxq.mem.type = xdpf->mem_type;
/* TODO: report queue_index to xdp_rxq_info */
xdp_convert_frame_to_buff(xdpf, &xdp);
diff --git a/kernel/bpf/devmap.c b/kernel/bpf/devmap.c
index 7878be18e9d2..482d284a1553 100644
--- a/kernel/bpf/devmap.c
+++ b/kernel/bpf/devmap.c
@@ -184,7 +184,7 @@ static struct bpf_map *dev_map_alloc(union bpf_attr *attr)
static void dev_map_free(struct bpf_map *map)
{
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
- int i;
+ u32 i;
/* At this point bpf_prog->aux->refcnt == 0 and this map->refcnt == 0,
* so the programs (can be more than one that used this map) were
@@ -678,7 +678,7 @@ int dev_map_enqueue_multi(struct xdp_frame *xdpf, struct net_device *dev_rx,
}
int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
- struct bpf_prog *xdp_prog)
+ const struct bpf_prog *xdp_prog)
{
int err;
@@ -701,7 +701,7 @@ int dev_map_generic_redirect(struct bpf_dtab_netdev *dst, struct sk_buff *skb,
static int dev_map_redirect_clone(struct bpf_dtab_netdev *dst,
struct sk_buff *skb,
- struct bpf_prog *xdp_prog)
+ const struct bpf_prog *xdp_prog)
{
struct sk_buff *nskb;
int err;
@@ -720,8 +720,8 @@ static int dev_map_redirect_clone(struct bpf_dtab_netdev *dst,
}
int dev_map_redirect_multi(struct net_device *dev, struct sk_buff *skb,
- struct bpf_prog *xdp_prog, struct bpf_map *map,
- bool exclude_ingress)
+ const struct bpf_prog *xdp_prog,
+ struct bpf_map *map, bool exclude_ingress)
{
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
struct bpf_dtab_netdev *dst, *last_dst = NULL;
@@ -821,7 +821,7 @@ static long dev_map_delete_elem(struct bpf_map *map, void *key)
{
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
struct bpf_dtab_netdev *old_dev;
- int k = *(u32 *)key;
+ u32 k = *(u32 *)key;
if (k >= map->max_entries)
return -EINVAL;
@@ -838,7 +838,7 @@ static long dev_map_hash_delete_elem(struct bpf_map *map, void *key)
{
struct bpf_dtab *dtab = container_of(map, struct bpf_dtab, map);
struct bpf_dtab_netdev *old_dev;
- int k = *(u32 *)key;
+ u32 k = *(u32 *)key;
unsigned long flags;
int ret = -ENOENT;
diff --git a/kernel/bpf/lpm_trie.c b/kernel/bpf/lpm_trie.c
index 9b60eda0f727..f8bc1e096182 100644
--- a/kernel/bpf/lpm_trie.c
+++ b/kernel/bpf/lpm_trie.c
@@ -15,6 +15,7 @@
#include <net/ipv6.h>
#include <uapi/linux/btf.h>
#include <linux/btf_ids.h>
+#include <linux/bpf_mem_alloc.h>
/* Intermediate node */
#define LPM_TREE_NODE_FLAG_IM BIT(0)
@@ -22,7 +23,6 @@
struct lpm_trie_node;
struct lpm_trie_node {
- struct rcu_head rcu;
struct lpm_trie_node __rcu *child[2];
u32 prefixlen;
u32 flags;
@@ -32,10 +32,11 @@ struct lpm_trie_node {
struct lpm_trie {
struct bpf_map map;
struct lpm_trie_node __rcu *root;
+ struct bpf_mem_alloc ma;
size_t n_entries;
size_t max_prefixlen;
size_t data_size;
- spinlock_t lock;
+ raw_spinlock_t lock;
};
/* This trie implements a longest prefix match algorithm that can be used to
@@ -287,17 +288,18 @@ static void *trie_lookup_elem(struct bpf_map *map, void *_key)
return found->data + trie->data_size;
}
-static struct lpm_trie_node *lpm_trie_node_alloc(const struct lpm_trie *trie,
- const void *value)
+static struct lpm_trie_node *lpm_trie_node_alloc(struct lpm_trie *trie,
+ const void *value,
+ bool disable_migration)
{
struct lpm_trie_node *node;
- size_t size = sizeof(struct lpm_trie_node) + trie->data_size;
- if (value)
- size += trie->map.value_size;
+ if (disable_migration)
+ migrate_disable();
+ node = bpf_mem_cache_alloc(&trie->ma);
+ if (disable_migration)
+ migrate_enable();
- node = bpf_map_kmalloc_node(&trie->map, size, GFP_NOWAIT | __GFP_NOWARN,
- trie->map.numa_node);
if (!node)
return NULL;
@@ -310,12 +312,22 @@ static struct lpm_trie_node *lpm_trie_node_alloc(const struct lpm_trie *trie,
return node;
}
+static int trie_check_add_elem(struct lpm_trie *trie, u64 flags)
+{
+ if (flags == BPF_EXIST)
+ return -ENOENT;
+ if (trie->n_entries == trie->map.max_entries)
+ return -ENOSPC;
+ trie->n_entries++;
+ return 0;
+}
+
/* Called from syscall or from eBPF program */
static long trie_update_elem(struct bpf_map *map,
void *_key, void *value, u64 flags)
{
struct lpm_trie *trie = container_of(map, struct lpm_trie, map);
- struct lpm_trie_node *node, *im_node = NULL, *new_node = NULL;
+ struct lpm_trie_node *node, *im_node, *new_node;
struct lpm_trie_node *free_node = NULL;
struct lpm_trie_node __rcu **slot;
struct bpf_lpm_trie_key_u8 *key = _key;
@@ -330,22 +342,14 @@ static long trie_update_elem(struct bpf_map *map,
if (key->prefixlen > trie->max_prefixlen)
return -EINVAL;
- spin_lock_irqsave(&trie->lock, irq_flags);
-
- /* Allocate and fill a new node */
-
- if (trie->n_entries == trie->map.max_entries) {
- ret = -ENOSPC;
- goto out;
- }
-
- new_node = lpm_trie_node_alloc(trie, value);
- if (!new_node) {
- ret = -ENOMEM;
- goto out;
- }
+ /* Allocate and fill a new node. Need to disable migration before
+ * invoking bpf_mem_cache_alloc().
+ */
+ new_node = lpm_trie_node_alloc(trie, value, true);
+ if (!new_node)
+ return -ENOMEM;
- trie->n_entries++;
+ raw_spin_lock_irqsave(&trie->lock, irq_flags);
new_node->prefixlen = key->prefixlen;
RCU_INIT_POINTER(new_node->child[0], NULL);
@@ -364,8 +368,7 @@ static long trie_update_elem(struct bpf_map *map,
matchlen = longest_prefix_match(trie, node, key);
if (node->prefixlen != matchlen ||
- node->prefixlen == key->prefixlen ||
- node->prefixlen == trie->max_prefixlen)
+ node->prefixlen == key->prefixlen)
break;
next_bit = extract_bit(key->data, node->prefixlen);
@@ -376,6 +379,10 @@ static long trie_update_elem(struct bpf_map *map,
* simply assign the @new_node to that slot and be done.
*/
if (!node) {
+ ret = trie_check_add_elem(trie, flags);
+ if (ret)
+ goto out;
+
rcu_assign_pointer(*slot, new_node);
goto out;
}
@@ -384,18 +391,30 @@ static long trie_update_elem(struct bpf_map *map,
* which already has the correct data array set.
*/
if (node->prefixlen == matchlen) {
+ if (!(node->flags & LPM_TREE_NODE_FLAG_IM)) {
+ if (flags == BPF_NOEXIST) {
+ ret = -EEXIST;
+ goto out;
+ }
+ } else {
+ ret = trie_check_add_elem(trie, flags);
+ if (ret)
+ goto out;
+ }
+
new_node->child[0] = node->child[0];
new_node->child[1] = node->child[1];
- if (!(node->flags & LPM_TREE_NODE_FLAG_IM))
- trie->n_entries--;
-
rcu_assign_pointer(*slot, new_node);
free_node = node;
goto out;
}
+ ret = trie_check_add_elem(trie, flags);
+ if (ret)
+ goto out;
+
/* If the new node matches the prefix completely, it must be inserted
* as an ancestor. Simply insert it between @node and *@slot.
*/
@@ -406,8 +425,10 @@ static long trie_update_elem(struct bpf_map *map,
goto out;
}
- im_node = lpm_trie_node_alloc(trie, NULL);
+ /* migration is disabled within the locked scope */
+ im_node = lpm_trie_node_alloc(trie, NULL, false);
if (!im_node) {
+ trie->n_entries--;
ret = -ENOMEM;
goto out;
}
@@ -429,16 +450,13 @@ static long trie_update_elem(struct bpf_map *map,
rcu_assign_pointer(*slot, im_node);
out:
- if (ret) {
- if (new_node)
- trie->n_entries--;
+ raw_spin_unlock_irqrestore(&trie->lock, irq_flags);
- kfree(new_node);
- kfree(im_node);
- }
-
- spin_unlock_irqrestore(&trie->lock, irq_flags);
- kfree_rcu(free_node, rcu);
+ migrate_disable();
+ if (ret)
+ bpf_mem_cache_free(&trie->ma, new_node);
+ bpf_mem_cache_free_rcu(&trie->ma, free_node);
+ migrate_enable();
return ret;
}
@@ -459,7 +477,7 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)
if (key->prefixlen > trie->max_prefixlen)
return -EINVAL;
- spin_lock_irqsave(&trie->lock, irq_flags);
+ raw_spin_lock_irqsave(&trie->lock, irq_flags);
/* Walk the tree looking for an exact key/length match and keeping
* track of the path we traverse. We will need to know the node
@@ -535,9 +553,12 @@ static long trie_delete_elem(struct bpf_map *map, void *_key)
free_node = node;
out:
- spin_unlock_irqrestore(&trie->lock, irq_flags);
- kfree_rcu(free_parent, rcu);
- kfree_rcu(free_node, rcu);
+ raw_spin_unlock_irqrestore(&trie->lock, irq_flags);
+
+ migrate_disable();
+ bpf_mem_cache_free_rcu(&trie->ma, free_parent);
+ bpf_mem_cache_free_rcu(&trie->ma, free_node);
+ migrate_enable();
return ret;
}
@@ -559,6 +580,8 @@ out:
static struct bpf_map *trie_alloc(union bpf_attr *attr)
{
struct lpm_trie *trie;
+ size_t leaf_size;
+ int err;
/* check sanity of attributes */
if (attr->max_entries == 0 ||
@@ -581,9 +604,19 @@ static struct bpf_map *trie_alloc(union bpf_attr *attr)
offsetof(struct bpf_lpm_trie_key_u8, data);
trie->max_prefixlen = trie->data_size * 8;
- spin_lock_init(&trie->lock);
+ raw_spin_lock_init(&trie->lock);
+ /* Allocate intermediate and leaf nodes from the same allocator */
+ leaf_size = sizeof(struct lpm_trie_node) + trie->data_size +
+ trie->map.value_size;
+ err = bpf_mem_alloc_init(&trie->ma, leaf_size, false);
+ if (err)
+ goto free_out;
return &trie->map;
+
+free_out:
+ bpf_map_area_free(trie);
+ return ERR_PTR(err);
}
static void trie_free(struct bpf_map *map)
@@ -615,13 +648,17 @@ static void trie_free(struct bpf_map *map)
continue;
}
- kfree(node);
+ /* No bpf program may access the map, so freeing the
+ * node without waiting for the extra RCU GP.
+ */
+ bpf_mem_cache_raw_free(node);
RCU_INIT_POINTER(*slot, NULL);
break;
}
}
out:
+ bpf_mem_alloc_destroy(&trie->ma);
bpf_map_area_free(trie);
}
@@ -633,7 +670,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key)
struct lpm_trie_node **node_stack = NULL;
int err = 0, stack_ptr = -1;
unsigned int next_bit;
- size_t matchlen;
+ size_t matchlen = 0;
/* The get_next_key follows postorder. For the 4 node example in
* the top of this file, the trie_get_next_key() returns the following
@@ -672,7 +709,7 @@ static int trie_get_next_key(struct bpf_map *map, void *_key, void *_next_key)
next_bit = extract_bit(key->data, node->prefixlen);
node = rcu_dereference(node->child[next_bit]);
}
- if (!node || node->prefixlen != key->prefixlen ||
+ if (!node || node->prefixlen != matchlen ||
(node->flags & LPM_TREE_NODE_FLAG_IM))
goto find_leftmost;
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 1c4ebb326785..77f56674aaa9 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -420,25 +420,6 @@ static struct btf_record *reg_btf_record(const struct bpf_reg_state *reg)
return rec;
}
-static bool mask_raw_tp_reg_cond(const struct bpf_verifier_env *env, struct bpf_reg_state *reg) {
- return reg->type == (PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL) &&
- bpf_prog_is_raw_tp(env->prog) && !reg->ref_obj_id;
-}
-
-static bool mask_raw_tp_reg(const struct bpf_verifier_env *env, struct bpf_reg_state *reg)
-{
- if (!mask_raw_tp_reg_cond(env, reg))
- return false;
- reg->type &= ~PTR_MAYBE_NULL;
- return true;
-}
-
-static void unmask_raw_tp_reg(struct bpf_reg_state *reg, bool result)
-{
- if (result)
- reg->type |= PTR_MAYBE_NULL;
-}
-
static bool subprog_is_global(const struct bpf_verifier_env *env, int subprog)
{
struct bpf_func_info_aux *aux = env->prog->aux->func_info_aux;
@@ -1202,14 +1183,17 @@ static bool is_spilled_scalar_reg64(const struct bpf_stack_state *stack)
/* Mark stack slot as STACK_MISC, unless it is already STACK_INVALID, in which
* case they are equivalent, or it's STACK_ZERO, in which case we preserve
* more precise STACK_ZERO.
- * Note, in uprivileged mode leaving STACK_INVALID is wrong, so we take
- * env->allow_ptr_leaks into account and force STACK_MISC, if necessary.
+ * Regardless of allow_ptr_leaks setting (i.e., privileged or unprivileged
+ * mode), we won't promote STACK_INVALID to STACK_MISC. In privileged case it is
+ * unnecessary as both are considered equivalent when loading data and pruning,
+ * in case of unprivileged mode it will be incorrect to allow reads of invalid
+ * slots.
*/
static void mark_stack_slot_misc(struct bpf_verifier_env *env, u8 *stype)
{
if (*stype == STACK_ZERO)
return;
- if (env->allow_ptr_leaks && *stype == STACK_INVALID)
+ if (*stype == STACK_INVALID)
return;
*stype = STACK_MISC;
}
@@ -2594,16 +2578,36 @@ static int cmp_subprogs(const void *a, const void *b)
((struct bpf_subprog_info *)b)->start;
}
+/* Find subprogram that contains instruction at 'off' */
+static struct bpf_subprog_info *find_containing_subprog(struct bpf_verifier_env *env, int off)
+{
+ struct bpf_subprog_info *vals = env->subprog_info;
+ int l, r, m;
+
+ if (off >= env->prog->len || off < 0 || env->subprog_cnt == 0)
+ return NULL;
+
+ l = 0;
+ r = env->subprog_cnt - 1;
+ while (l < r) {
+ m = l + (r - l + 1) / 2;
+ if (vals[m].start <= off)
+ l = m;
+ else
+ r = m - 1;
+ }
+ return &vals[l];
+}
+
+/* Find subprogram that starts exactly at 'off' */
static int find_subprog(struct bpf_verifier_env *env, int off)
{
struct bpf_subprog_info *p;
- p = bsearch(&off, env->subprog_info, env->subprog_cnt,
- sizeof(env->subprog_info[0]), cmp_subprogs);
- if (!p)
+ p = find_containing_subprog(env, off);
+ if (!p || p->start != off)
return -ENOENT;
return p - env->subprog_info;
-
}
static int add_subprog(struct bpf_verifier_env *env, int off)
@@ -4700,6 +4704,7 @@ static int check_stack_write_fixed_off(struct bpf_verifier_env *env,
*/
if (!env->allow_ptr_leaks &&
is_spilled_reg(&state->stack[spi]) &&
+ !is_spilled_scalar_reg(&state->stack[spi]) &&
size != BPF_REG_SIZE) {
verbose(env, "attempt to corrupt spilled pointer on stack\n");
return -EACCES;
@@ -6777,7 +6782,6 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
const char *field_name = NULL;
enum bpf_type_flag flag = 0;
u32 btf_id = 0;
- bool mask;
int ret;
if (!env->allow_ptr_leaks) {
@@ -6849,21 +6853,7 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
if (ret < 0)
return ret;
- /* For raw_tp progs, we allow dereference of PTR_MAYBE_NULL
- * trusted PTR_TO_BTF_ID, these are the ones that are possibly
- * arguments to the raw_tp. Since internal checks in for trusted
- * reg in check_ptr_to_btf_access would consider PTR_MAYBE_NULL
- * modifier as problematic, mask it out temporarily for the
- * check. Don't apply this to pointers with ref_obj_id > 0, as
- * those won't be raw_tp args.
- *
- * We may end up applying this relaxation to other trusted
- * PTR_TO_BTF_ID with maybe null flag, since we cannot
- * distinguish PTR_MAYBE_NULL tagged for arguments vs normal
- * tagging, but that should expand allowed behavior, and not
- * cause regression for existing behavior.
- */
- mask = mask_raw_tp_reg(env, reg);
+
if (ret != PTR_TO_BTF_ID) {
/* just mark; */
@@ -6924,13 +6914,8 @@ static int check_ptr_to_btf_access(struct bpf_verifier_env *env,
clear_trusted_flags(&flag);
}
- if (atype == BPF_READ && value_regno >= 0) {
+ if (atype == BPF_READ && value_regno >= 0)
mark_btf_ld_reg(env, regs, value_regno, ret, reg->btf, btf_id, flag);
- /* We've assigned a new type to regno, so don't undo masking. */
- if (regno == value_regno)
- mask = false;
- }
- unmask_raw_tp_reg(reg, mask);
return 0;
}
@@ -7305,7 +7290,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
if (!err && t == BPF_READ && value_regno >= 0)
mark_reg_unknown(env, regs, value_regno);
} else if (base_type(reg->type) == PTR_TO_BTF_ID &&
- (mask_raw_tp_reg_cond(env, reg) || !type_may_be_null(reg->type))) {
+ !type_may_be_null(reg->type)) {
err = check_ptr_to_btf_access(env, regs, regno, off, size, t,
value_regno);
} else if (reg->type == CONST_PTR_TO_MAP) {
@@ -8071,7 +8056,7 @@ static int process_dynptr_func(struct bpf_verifier_env *env, int regno, int insn
if (reg->type != PTR_TO_STACK && reg->type != CONST_PTR_TO_DYNPTR) {
verbose(env,
"arg#%d expected pointer to stack or const struct bpf_dynptr\n",
- regno);
+ regno - 1);
return -EINVAL;
}
@@ -8125,7 +8110,7 @@ static int process_dynptr_func(struct bpf_verifier_env *env, int regno, int insn
if (!is_dynptr_reg_valid_init(env, reg)) {
verbose(env,
"Expected an initialized dynptr as arg #%d\n",
- regno);
+ regno - 1);
return -EINVAL;
}
@@ -8133,7 +8118,7 @@ static int process_dynptr_func(struct bpf_verifier_env *env, int regno, int insn
if (!is_dynptr_type_expected(env, reg, arg_type & ~MEM_RDONLY)) {
verbose(env,
"Expected a dynptr of type %s as arg #%d\n",
- dynptr_type_str(arg_to_dynptr_type(arg_type)), regno);
+ dynptr_type_str(arg_to_dynptr_type(arg_type)), regno - 1);
return -EINVAL;
}
@@ -8189,6 +8174,11 @@ static int process_iter_arg(struct bpf_verifier_env *env, int regno, int insn_id
const struct btf_type *t;
int spi, err, i, nr_slots, btf_id;
+ if (reg->type != PTR_TO_STACK) {
+ verbose(env, "arg#%d expected pointer to an iterator on stack\n", regno - 1);
+ return -EINVAL;
+ }
+
/* For iter_{new,next,destroy} functions, btf_check_iter_kfuncs()
* ensures struct convention, so we wouldn't need to do any BTF
* validation here. But given iter state can be passed as a parameter
@@ -8197,7 +8187,7 @@ static int process_iter_arg(struct bpf_verifier_env *env, int regno, int insn_id
*/
btf_id = btf_check_iter_arg(meta->btf, meta->func_proto, regno - 1);
if (btf_id < 0) {
- verbose(env, "expected valid iter pointer as arg #%d\n", regno);
+ verbose(env, "expected valid iter pointer as arg #%d\n", regno - 1);
return -EINVAL;
}
t = btf_type_by_id(meta->btf, btf_id);
@@ -8207,7 +8197,7 @@ static int process_iter_arg(struct bpf_verifier_env *env, int regno, int insn_id
/* bpf_iter_<type>_new() expects pointer to uninit iter state */
if (!is_iter_reg_valid_uninit(env, reg, nr_slots)) {
verbose(env, "expected uninitialized iter_%s as arg #%d\n",
- iter_type_str(meta->btf, btf_id), regno);
+ iter_type_str(meta->btf, btf_id), regno - 1);
return -EINVAL;
}
@@ -8231,7 +8221,7 @@ static int process_iter_arg(struct bpf_verifier_env *env, int regno, int insn_id
break;
case -EINVAL:
verbose(env, "expected an initialized iter_%s as arg #%d\n",
- iter_type_str(meta->btf, btf_id), regno);
+ iter_type_str(meta->btf, btf_id), regno - 1);
return err;
case -EPROTO:
verbose(env, "expected an RCU CS when using %s\n", meta->func_name);
@@ -9003,7 +8993,6 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
enum bpf_reg_type type = reg->type;
u32 *arg_btf_id = NULL;
int err = 0;
- bool mask;
if (arg_type == ARG_DONTCARE)
return 0;
@@ -9044,11 +9033,11 @@ static int check_func_arg(struct bpf_verifier_env *env, u32 arg,
base_type(arg_type) == ARG_PTR_TO_SPIN_LOCK)
arg_btf_id = fn->arg_btf_id[arg];
- mask = mask_raw_tp_reg(env, reg);
err = check_reg_type(env, regno, arg_type, arg_btf_id, meta);
+ if (err)
+ return err;
- err = err ?: check_func_arg_reg_off(env, reg, regno, arg_type);
- unmask_raw_tp_reg(reg, mask);
+ err = check_func_arg_reg_off(env, reg, regno, arg_type);
if (err)
return err;
@@ -9843,17 +9832,14 @@ static int btf_check_func_arg_match(struct bpf_verifier_env *env, int subprog,
return ret;
} else if (base_type(arg->arg_type) == ARG_PTR_TO_BTF_ID) {
struct bpf_call_arg_meta meta;
- bool mask;
int err;
if (register_is_null(reg) && type_may_be_null(arg->arg_type))
continue;
memset(&meta, 0, sizeof(meta)); /* leave func_id as zero */
- mask = mask_raw_tp_reg(env, reg);
err = check_reg_type(env, regno, arg->arg_type, &arg->btf_id, &meta);
err = err ?: check_func_arg_reg_off(env, reg, regno, arg->arg_type);
- unmask_raw_tp_reg(reg, mask);
if (err)
return err;
} else {
@@ -10013,6 +9999,8 @@ static int check_func_call(struct bpf_verifier_env *env, struct bpf_insn *insn,
verbose(env, "Func#%d ('%s') is global and assumed valid.\n",
subprog, sub_name);
+ if (env->subprog_info[subprog].changes_pkt_data)
+ clear_all_pkt_pointers(env);
/* mark global subprog for verifying after main prog */
subprog_aux(env, subprog)->called = true;
clear_caller_saved_regs(env, caller->regs);
@@ -10699,7 +10687,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
}
/* With LD_ABS/IND some JITs save/restore skb from r1. */
- changes_data = bpf_helper_changes_pkt_data(fn->func);
+ changes_data = bpf_helper_changes_pkt_data(func_id);
if (changes_data && fn->arg1_type != ARG_PTR_TO_CTX) {
verbose(env, "kernel subsystem misconfigured func %s#%d: r1 != ctx\n",
func_id_name(func_id), func_id);
@@ -12174,7 +12162,6 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
enum bpf_arg_type arg_type = ARG_DONTCARE;
u32 regno = i + 1, ref_id, type_size;
bool is_ret_buf_sz = false;
- bool mask = false;
int kf_arg_type;
t = btf_type_skip_modifiers(btf, args[i].type, NULL);
@@ -12233,15 +12220,12 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
return -EINVAL;
}
- mask = mask_raw_tp_reg(env, reg);
if ((is_kfunc_trusted_args(meta) || is_kfunc_rcu(meta)) &&
(register_is_null(reg) || type_may_be_null(reg->type)) &&
!is_kfunc_arg_nullable(meta->btf, &args[i])) {
verbose(env, "Possibly NULL pointer passed to trusted arg%d\n", i);
- unmask_raw_tp_reg(reg, mask);
return -EACCES;
}
- unmask_raw_tp_reg(reg, mask);
if (reg->ref_obj_id) {
if (is_kfunc_release(meta) && meta->ref_obj_id) {
@@ -12299,24 +12283,16 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
if (!is_kfunc_trusted_args(meta) && !is_kfunc_rcu(meta))
break;
- /* Allow passing maybe NULL raw_tp arguments to
- * kfuncs for compatibility. Don't apply this to
- * arguments with ref_obj_id > 0.
- */
- mask = mask_raw_tp_reg(env, reg);
if (!is_trusted_reg(reg)) {
if (!is_kfunc_rcu(meta)) {
verbose(env, "R%d must be referenced or trusted\n", regno);
- unmask_raw_tp_reg(reg, mask);
return -EINVAL;
}
if (!is_rcu_reg(reg)) {
verbose(env, "R%d must be a rcu pointer\n", regno);
- unmask_raw_tp_reg(reg, mask);
return -EINVAL;
}
}
- unmask_raw_tp_reg(reg, mask);
fallthrough;
case KF_ARG_PTR_TO_CTX:
case KF_ARG_PTR_TO_DYNPTR:
@@ -12339,9 +12315,7 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
if (is_kfunc_release(meta) && reg->ref_obj_id)
arg_type |= OBJ_RELEASE;
- mask = mask_raw_tp_reg(env, reg);
ret = check_func_arg_reg_off(env, reg, regno, arg_type);
- unmask_raw_tp_reg(reg, mask);
if (ret < 0)
return ret;
@@ -12518,7 +12492,6 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
ref_tname = btf_name_by_offset(btf, ref_t->name_off);
fallthrough;
case KF_ARG_PTR_TO_BTF_ID:
- mask = mask_raw_tp_reg(env, reg);
/* Only base_type is checked, further checks are done here */
if ((base_type(reg->type) != PTR_TO_BTF_ID ||
(bpf_type_has_unsafe_modifiers(reg->type) && !is_rcu_reg(reg))) &&
@@ -12527,11 +12500,9 @@ static int check_kfunc_args(struct bpf_verifier_env *env, struct bpf_kfunc_call_
verbose(env, "expected %s or socket\n",
reg_type_str(env, base_type(reg->type) |
(type_flag(reg->type) & BPF_REG_TRUSTED_MODIFIERS)));
- unmask_raw_tp_reg(reg, mask);
return -EINVAL;
}
ret = process_kf_arg_ptr_to_btf_id(env, reg, ref_t, ref_tname, ref_id, meta, i);
- unmask_raw_tp_reg(reg, mask);
if (ret < 0)
return ret;
break;
@@ -13504,7 +13475,7 @@ static int sanitize_check_bounds(struct bpf_verifier_env *env,
*/
static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
struct bpf_insn *insn,
- struct bpf_reg_state *ptr_reg,
+ const struct bpf_reg_state *ptr_reg,
const struct bpf_reg_state *off_reg)
{
struct bpf_verifier_state *vstate = env->cur_state;
@@ -13518,7 +13489,6 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
struct bpf_sanitize_info info = {};
u8 opcode = BPF_OP(insn->code);
u32 dst = insn->dst_reg;
- bool mask;
int ret;
dst_reg = &regs[dst];
@@ -13545,14 +13515,11 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env,
return -EACCES;
}
- mask = mask_raw_tp_reg(env, ptr_reg);
if (ptr_reg->type & PTR_MAYBE_NULL) {
verbose(env, "R%d pointer arithmetic on %s prohibited, null-check it first\n",
dst, reg_type_str(env, ptr_reg->type));
- unmask_raw_tp_reg(ptr_reg, mask);
return -EACCES;
}
- unmask_raw_tp_reg(ptr_reg, mask);
switch (base_type(ptr_reg->type)) {
case PTR_TO_CTX:
@@ -16217,6 +16184,29 @@ enforce_retval:
return 0;
}
+static void mark_subprog_changes_pkt_data(struct bpf_verifier_env *env, int off)
+{
+ struct bpf_subprog_info *subprog;
+
+ subprog = find_containing_subprog(env, off);
+ subprog->changes_pkt_data = true;
+}
+
+/* 't' is an index of a call-site.
+ * 'w' is a callee entry point.
+ * Eventually this function would be called when env->cfg.insn_state[w] == EXPLORED.
+ * Rely on DFS traversal order and absence of recursive calls to guarantee that
+ * callee's change_pkt_data marks would be correct at that moment.
+ */
+static void merge_callee_effects(struct bpf_verifier_env *env, int t, int w)
+{
+ struct bpf_subprog_info *caller, *callee;
+
+ caller = find_containing_subprog(env, t);
+ callee = find_containing_subprog(env, w);
+ caller->changes_pkt_data |= callee->changes_pkt_data;
+}
+
/* non-recursive DFS pseudo code
* 1 procedure DFS-iterative(G,v):
* 2 label v as discovered
@@ -16350,6 +16340,7 @@ static int visit_func_call_insn(int t, struct bpf_insn *insns,
bool visit_callee)
{
int ret, insn_sz;
+ int w;
insn_sz = bpf_is_ldimm64(&insns[t]) ? 2 : 1;
ret = push_insn(t, t + insn_sz, FALLTHROUGH, env);
@@ -16361,8 +16352,10 @@ static int visit_func_call_insn(int t, struct bpf_insn *insns,
mark_jmp_point(env, t + insn_sz);
if (visit_callee) {
+ w = t + insns[t].imm + 1;
mark_prune_point(env, t);
- ret = push_insn(t, t + insns[t].imm + 1, BRANCH, env);
+ merge_callee_effects(env, t, w);
+ ret = push_insn(t, w, BRANCH, env);
}
return ret;
}
@@ -16679,6 +16672,8 @@ static int visit_insn(int t, struct bpf_verifier_env *env)
mark_prune_point(env, t);
mark_jmp_point(env, t);
}
+ if (bpf_helper_call(insn) && bpf_helper_changes_pkt_data(insn->imm))
+ mark_subprog_changes_pkt_data(env, t);
if (insn->src_reg == BPF_PSEUDO_KFUNC_CALL) {
struct bpf_kfunc_call_arg_meta meta;
@@ -16813,6 +16808,7 @@ walk_cfg:
}
}
ret = 0; /* cfg looks good */
+ env->prog->aux->changes_pkt_data = env->subprog_info[0].changes_pkt_data;
err_free:
kvfree(insn_state);
@@ -20066,7 +20062,6 @@ static int convert_ctx_accesses(struct bpf_verifier_env *env)
* for this case.
*/
case PTR_TO_BTF_ID | MEM_ALLOC | PTR_UNTRUSTED:
- case PTR_TO_BTF_ID | PTR_TRUSTED | PTR_MAYBE_NULL:
if (type == BPF_READ) {
if (BPF_MODE(insn->code) == BPF_MEM)
insn->code = BPF_LDX | BPF_PROBE_MEM |
@@ -20302,6 +20297,7 @@ static int jit_subprogs(struct bpf_verifier_env *env)
func[i]->aux->num_exentries = num_exentries;
func[i]->aux->tail_call_reachable = env->subprog_info[i].tail_call_reachable;
func[i]->aux->exception_cb = env->subprog_info[i].is_exception_cb;
+ func[i]->aux->changes_pkt_data = env->subprog_info[i].changes_pkt_data;
if (!i)
func[i]->aux->exception_boundary = env->seen_exception;
func[i] = bpf_int_jit_compile(func[i]);
@@ -21285,11 +21281,15 @@ patch_map_ops_generic:
* changed in some incompatible and hard to support
* way, it's fine to back out this inlining logic
*/
+#ifdef CONFIG_SMP
insn_buf[0] = BPF_MOV32_IMM(BPF_REG_0, (u32)(unsigned long)&pcpu_hot.cpu_number);
insn_buf[1] = BPF_MOV64_PERCPU_REG(BPF_REG_0, BPF_REG_0);
insn_buf[2] = BPF_LDX_MEM(BPF_W, BPF_REG_0, BPF_REG_0, 0);
cnt = 3;
-
+#else
+ insn_buf[0] = BPF_ALU32_REG(BPF_XOR, BPF_REG_0, BPF_REG_0);
+ cnt = 1;
+#endif
new_prog = bpf_patch_insn_data(env, i + delta, insn_buf, cnt);
if (!new_prog)
return -ENOMEM;
@@ -22132,6 +22132,7 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
}
if (tgt_prog) {
struct bpf_prog_aux *aux = tgt_prog->aux;
+ bool tgt_changes_pkt_data;
if (bpf_prog_is_dev_bound(prog->aux) &&
!bpf_prog_dev_bound_match(prog, tgt_prog)) {
@@ -22166,6 +22167,14 @@ int bpf_check_attach_target(struct bpf_verifier_log *log,
"Extension programs should be JITed\n");
return -EINVAL;
}
+ tgt_changes_pkt_data = aux->func
+ ? aux->func[subprog]->aux->changes_pkt_data
+ : aux->changes_pkt_data;
+ if (prog->aux->changes_pkt_data && !tgt_changes_pkt_data) {
+ bpf_log(log,
+ "Extension program changes packet data, while original does not\n");
+ return -EINVAL;
+ }
}
if (!tgt_prog->jited) {
bpf_log(log, "Can attach to only JITed progs\n");
@@ -22631,10 +22640,6 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
if (ret < 0)
goto skip_full_check;
- ret = check_attach_btf_id(env);
- if (ret)
- goto skip_full_check;
-
ret = resolve_pseudo_ldimm64(env);
if (ret < 0)
goto skip_full_check;
@@ -22649,6 +22654,10 @@ int bpf_check(struct bpf_prog **prog, union bpf_attr *attr, bpfptr_t uattr, __u3
if (ret < 0)
goto skip_full_check;
+ ret = check_attach_btf_id(env);
+ if (ret)
+ goto skip_full_check;
+
ret = mark_fastcall_patterns(env);
if (ret < 0)
goto skip_full_check;
diff --git a/kernel/cpu.c b/kernel/cpu.c
index 6e34b52cb5ce..b605334f8ee6 100644
--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -2866,7 +2866,6 @@ static struct attribute *cpuhp_cpu_attrs[] = {
static const struct attribute_group cpuhp_cpu_attr_group = {
.attrs = cpuhp_cpu_attrs,
.name = "hotplug",
- NULL
};
static ssize_t states_show(struct device *dev,
@@ -2898,7 +2897,6 @@ static struct attribute *cpuhp_cpu_root_attrs[] = {
static const struct attribute_group cpuhp_cpu_root_attr_group = {
.attrs = cpuhp_cpu_root_attrs,
.name = "hotplug",
- NULL
};
#ifdef CONFIG_HOTPLUG_SMT
@@ -3020,7 +3018,6 @@ static struct attribute *cpuhp_smt_attrs[] = {
static const struct attribute_group cpuhp_smt_attr_group = {
.attrs = cpuhp_smt_attrs,
.name = "smt",
- NULL
};
static int __init cpu_smt_sysfs_init(void)
diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
index 295396226f31..e43c6de2bce4 100644
--- a/kernel/dma/debug.c
+++ b/kernel/dma/debug.c
@@ -1219,7 +1219,7 @@ void debug_dma_map_page(struct device *dev, struct page *page, size_t offset,
entry->dev = dev;
entry->type = dma_debug_single;
- entry->paddr = page_to_phys(page);
+ entry->paddr = page_to_phys(page) + offset;
entry->dev_addr = dma_addr;
entry->size = size;
entry->direction = direction;
@@ -1377,6 +1377,18 @@ void debug_dma_unmap_sg(struct device *dev, struct scatterlist *sglist,
}
}
+static phys_addr_t virt_to_paddr(void *virt)
+{
+ struct page *page;
+
+ if (is_vmalloc_addr(virt))
+ page = vmalloc_to_page(virt);
+ else
+ page = virt_to_page(virt);
+
+ return page_to_phys(page) + offset_in_page(virt);
+}
+
void debug_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t dma_addr, void *virt,
unsigned long attrs)
@@ -1399,8 +1411,7 @@ void debug_dma_alloc_coherent(struct device *dev, size_t size,
entry->type = dma_debug_coherent;
entry->dev = dev;
- entry->paddr = page_to_phys((is_vmalloc_addr(virt) ?
- vmalloc_to_page(virt) : virt_to_page(virt)));
+ entry->paddr = virt_to_paddr(virt);
entry->size = size;
entry->dev_addr = dma_addr;
entry->direction = DMA_BIDIRECTIONAL;
@@ -1423,8 +1434,7 @@ void debug_dma_free_coherent(struct device *dev, size_t size,
if (!is_vmalloc_addr(virt) && !virt_addr_valid(virt))
return;
- ref.paddr = page_to_phys((is_vmalloc_addr(virt) ?
- vmalloc_to_page(virt) : virt_to_page(virt)));
+ ref.paddr = virt_to_paddr(virt);
if (unlikely(dma_debug_disabled()))
return;
diff --git a/kernel/fork.c b/kernel/fork.c
index 1450b461d196..9b301180fd41 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -639,11 +639,8 @@ static __latent_entropy int dup_mmap(struct mm_struct *mm,
LIST_HEAD(uf);
VMA_ITERATOR(vmi, mm, 0);
- uprobe_start_dup_mmap();
- if (mmap_write_lock_killable(oldmm)) {
- retval = -EINTR;
- goto fail_uprobe_end;
- }
+ if (mmap_write_lock_killable(oldmm))
+ return -EINTR;
flush_cache_dup_mm(oldmm);
uprobe_dup_mmap(oldmm, mm);
/*
@@ -782,8 +779,6 @@ out:
dup_userfaultfd_complete(&uf);
else
dup_userfaultfd_fail(&uf);
-fail_uprobe_end:
- uprobe_end_dup_mmap();
return retval;
fail_nomem_anon_vma_fork:
@@ -1692,9 +1687,11 @@ static struct mm_struct *dup_mm(struct task_struct *tsk,
if (!mm_init(mm, tsk, mm->user_ns))
goto fail_nomem;
+ uprobe_start_dup_mmap();
err = dup_mmap(mm, oldmm);
if (err)
goto free_pt;
+ uprobe_end_dup_mmap();
mm->hiwater_rss = get_mm_rss(mm);
mm->hiwater_vm = mm->total_vm;
@@ -1709,6 +1706,8 @@ free_pt:
mm->binfmt = NULL;
mm_init_owner(mm, NULL);
mmput(mm);
+ if (err)
+ uprobe_end_dup_mmap();
fail_nomem:
return NULL;
diff --git a/kernel/futex/futex.h b/kernel/futex/futex.h
index 618ce1fe870e..99b32e728c4a 100644
--- a/kernel/futex/futex.h
+++ b/kernel/futex/futex.h
@@ -265,11 +265,11 @@ static __always_inline int futex_read_inatomic(u32 *dest, u32 __user *from)
else if (!user_read_access_begin(from, sizeof(*from)))
return -EFAULT;
unsafe_get_user(val, from, Efault);
- user_access_end();
+ user_read_access_end();
*dest = val;
return 0;
Efault:
- user_access_end();
+ user_read_access_end();
return -EFAULT;
}
diff --git a/kernel/gen_kheaders.sh b/kernel/gen_kheaders.sh
index 383fd43ac612..7e1340da5aca 100755
--- a/kernel/gen_kheaders.sh
+++ b/kernel/gen_kheaders.sh
@@ -89,6 +89,7 @@ find $cpio_dir -type f -print0 |
# Create archive and try to normalize metadata for reproducibility.
tar "${KBUILD_BUILD_TIMESTAMP:+--mtime=$KBUILD_BUILD_TIMESTAMP}" \
+ --exclude=".__afs*" --exclude=".nfs*" \
--owner=0 --group=0 --sort=name --numeric-owner --mode=u=rw,go=r,a+X \
-I $XZ -cf $tarfile -C $cpio_dir/ . > /dev/null
diff --git a/kernel/irq/proc.c b/kernel/irq/proc.c
index f36c33bd2da4..8e29809de38d 100644
--- a/kernel/irq/proc.c
+++ b/kernel/irq/proc.c
@@ -501,17 +501,18 @@ int show_interrupts(struct seq_file *p, void *v)
seq_put_decimal_ull_width(p, " ", cnt, 10);
}
+ seq_putc(p, ' ');
raw_spin_lock_irqsave(&desc->lock, flags);
if (desc->irq_data.chip) {
if (desc->irq_data.chip->irq_print_chip)
desc->irq_data.chip->irq_print_chip(&desc->irq_data, p);
else if (desc->irq_data.chip->name)
- seq_printf(p, " %8s", desc->irq_data.chip->name);
+ seq_printf(p, "%8s", desc->irq_data.chip->name);
else
- seq_printf(p, " %8s", "-");
+ seq_printf(p, "%8s", "-");
} else {
- seq_printf(p, " %8s", "None");
+ seq_printf(p, "%8s", "None");
}
if (desc->irq_data.domain)
seq_printf(p, " %*lu", prec, desc->irq_data.hwirq);
diff --git a/kernel/kcov.c b/kernel/kcov.c
index 28a6be6e64fd..187ba1b80bda 100644
--- a/kernel/kcov.c
+++ b/kernel/kcov.c
@@ -166,7 +166,7 @@ static void kcov_remote_area_put(struct kcov_remote_area *area,
* Unlike in_serving_softirq(), this function returns false when called during
* a hardirq or an NMI that happened in the softirq context.
*/
-static inline bool in_softirq_really(void)
+static __always_inline bool in_softirq_really(void)
{
return in_serving_softirq() && !in_hardirq() && !in_nmi();
}
diff --git a/kernel/locking/rtmutex.c b/kernel/locking/rtmutex.c
index ac1365afcc4a..697a56d3d949 100644
--- a/kernel/locking/rtmutex.c
+++ b/kernel/locking/rtmutex.c
@@ -1248,10 +1248,7 @@ static int __sched task_blocks_on_rt_mutex(struct rt_mutex_base *lock,
/* Check whether the waiter should back out immediately */
rtm = container_of(lock, struct rt_mutex, rtmutex);
- preempt_disable();
res = __ww_mutex_add_waiter(waiter, rtm, ww_ctx, wake_q);
- wake_up_q(wake_q);
- preempt_enable();
if (res) {
raw_spin_lock(&task->pi_lock);
rt_mutex_dequeue(lock, waiter);
@@ -1295,7 +1292,13 @@ static int __sched task_blocks_on_rt_mutex(struct rt_mutex_base *lock,
*/
get_task_struct(owner);
+ preempt_disable();
raw_spin_unlock_irq(&lock->wait_lock);
+ /* wake up any tasks on the wake_q before calling rt_mutex_adjust_prio_chain */
+ wake_up_q(wake_q);
+ wake_q_init(wake_q);
+ preempt_enable();
+
res = rt_mutex_adjust_prio_chain(owner, chwalk, lock,
next_lock, waiter, task);
@@ -1599,6 +1602,7 @@ static void __sched remove_waiter(struct rt_mutex_base *lock,
* or TASK_UNINTERRUPTIBLE)
* @timeout: the pre-initialized and started timer, or NULL for none
* @waiter: the pre-initialized rt_mutex_waiter
+ * @wake_q: wake_q of tasks to wake when we drop the lock->wait_lock
*
* Must be called with lock->wait_lock held and interrupts disabled
*/
@@ -1606,7 +1610,8 @@ static int __sched rt_mutex_slowlock_block(struct rt_mutex_base *lock,
struct ww_acquire_ctx *ww_ctx,
unsigned int state,
struct hrtimer_sleeper *timeout,
- struct rt_mutex_waiter *waiter)
+ struct rt_mutex_waiter *waiter,
+ struct wake_q_head *wake_q)
__releases(&lock->wait_lock) __acquires(&lock->wait_lock)
{
struct rt_mutex *rtm = container_of(lock, struct rt_mutex, rtmutex);
@@ -1637,7 +1642,13 @@ static int __sched rt_mutex_slowlock_block(struct rt_mutex_base *lock,
owner = rt_mutex_owner(lock);
else
owner = NULL;
+ preempt_disable();
raw_spin_unlock_irq(&lock->wait_lock);
+ if (wake_q) {
+ wake_up_q(wake_q);
+ wake_q_init(wake_q);
+ }
+ preempt_enable();
if (!owner || !rtmutex_spin_on_owner(lock, waiter, owner))
rt_mutex_schedule();
@@ -1711,7 +1722,7 @@ static int __sched __rt_mutex_slowlock(struct rt_mutex_base *lock,
ret = task_blocks_on_rt_mutex(lock, waiter, current, ww_ctx, chwalk, wake_q);
if (likely(!ret))
- ret = rt_mutex_slowlock_block(lock, ww_ctx, state, NULL, waiter);
+ ret = rt_mutex_slowlock_block(lock, ww_ctx, state, NULL, waiter, wake_q);
if (likely(!ret)) {
/* acquired the lock */
diff --git a/kernel/locking/rtmutex_api.c b/kernel/locking/rtmutex_api.c
index 33ea31d6a7b3..191e4720e546 100644
--- a/kernel/locking/rtmutex_api.c
+++ b/kernel/locking/rtmutex_api.c
@@ -383,7 +383,7 @@ int __sched rt_mutex_wait_proxy_lock(struct rt_mutex_base *lock,
raw_spin_lock_irq(&lock->wait_lock);
/* sleep on the mutex */
set_current_state(TASK_INTERRUPTIBLE);
- ret = rt_mutex_slowlock_block(lock, NULL, TASK_INTERRUPTIBLE, to, waiter);
+ ret = rt_mutex_slowlock_block(lock, NULL, TASK_INTERRUPTIBLE, to, waiter, NULL);
/*
* try_to_take_rt_mutex() sets the waiter bit unconditionally. We might
* have to fix that up.
diff --git a/kernel/module/Kconfig b/kernel/module/Kconfig
index 7c6588148d42..7b329057997a 100644
--- a/kernel/module/Kconfig
+++ b/kernel/module/Kconfig
@@ -349,7 +349,7 @@ config MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS
help
Symbols exported with EXPORT_SYMBOL_NS*() are considered exported in
a namespace. A module that makes use of a symbol exported with such a
- namespace is required to import the namespace via MODULE_IMPORT_NS().
+ namespace is required to import the namespace via MODULE_IMPORT_NS("").
There is no technical reason to enforce correct namespace imports,
but it creates consistency between symbols defining namespaces and
users importing namespaces they make use of. This option relaxes this
diff --git a/kernel/resource.c b/kernel/resource.c
index c9fd26c06345..b7c0e24d9398 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -998,7 +998,7 @@ void insert_resource_expand_to_fit(struct resource *root, struct resource *new)
* to use this interface. The former are built-in and only the latter,
* CXL, is a module.
*/
-EXPORT_SYMBOL_NS_GPL(insert_resource_expand_to_fit, CXL);
+EXPORT_SYMBOL_NS_GPL(insert_resource_expand_to_fit, "CXL");
/**
* remove_resource - Remove a resource in the resource tree
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 95e40895a519..3e5a6bf587f9 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1283,9 +1283,9 @@ static void nohz_csd_func(void *info)
WARN_ON(!(flags & NOHZ_KICK_MASK));
rq->idle_balance = idle_cpu(cpu);
- if (rq->idle_balance && !need_resched()) {
+ if (rq->idle_balance) {
rq->nohz_idle_balance = flags;
- raise_softirq_irqoff(SCHED_SOFTIRQ);
+ __raise_softirq_irqoff(SCHED_SOFTIRQ);
}
}
@@ -1341,7 +1341,7 @@ bool sched_can_stop_tick(struct rq *rq)
if (scx_enabled() && !scx_can_stop_tick(rq))
return false;
- if (rq->cfs.nr_running > 1)
+ if (rq->cfs.h_nr_running > 1)
return false;
/*
diff --git a/kernel/sched/deadline.c b/kernel/sched/deadline.c
index d9d5a702f1a6..d94f2ed6d1f4 100644
--- a/kernel/sched/deadline.c
+++ b/kernel/sched/deadline.c
@@ -781,7 +781,7 @@ static inline void replenish_dl_new_period(struct sched_dl_entity *dl_se,
* If it is a deferred reservation, and the server
* is not handling an starvation case, defer it.
*/
- if (dl_se->dl_defer & !dl_se->dl_defer_running) {
+ if (dl_se->dl_defer && !dl_se->dl_defer_running) {
dl_se->dl_throttled = 1;
dl_se->dl_defer_armed = 1;
}
@@ -1647,6 +1647,7 @@ void dl_server_start(struct sched_dl_entity *dl_se)
if (!dl_se->dl_runtime)
return;
+ dl_se->dl_server_active = 1;
enqueue_dl_entity(dl_se, ENQUEUE_WAKEUP);
if (!dl_task(dl_se->rq->curr) || dl_entity_preempt(dl_se, &rq->curr->dl))
resched_curr(dl_se->rq);
@@ -1661,6 +1662,7 @@ void dl_server_stop(struct sched_dl_entity *dl_se)
hrtimer_try_to_cancel(&dl_se->dl_timer);
dl_se->dl_defer_armed = 0;
dl_se->dl_throttled = 0;
+ dl_se->dl_server_active = 0;
}
void dl_server_init(struct sched_dl_entity *dl_se, struct rq *rq,
@@ -2042,6 +2044,7 @@ enqueue_dl_entity(struct sched_dl_entity *dl_se, int flags)
} else if (flags & ENQUEUE_REPLENISH) {
replenish_dl_entity(dl_se);
} else if ((flags & ENQUEUE_RESTORE) &&
+ !is_dl_boosted(dl_se) &&
dl_time_before(dl_se->deadline, rq_clock(rq_of_dl_se(dl_se)))) {
setup_new_dl_entity(dl_se);
}
@@ -2420,8 +2423,10 @@ again:
if (dl_server(dl_se)) {
p = dl_se->server_pick_task(dl_se);
if (!p) {
- dl_se->dl_yielded = 1;
- update_curr_dl_se(rq, dl_se, 0);
+ if (dl_server_active(dl_se)) {
+ dl_se->dl_yielded = 1;
+ update_curr_dl_se(rq, dl_se, 0);
+ }
goto again;
}
rq->dl_server = dl_se;
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index a48b2a701ec2..a1be00a988bf 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -845,6 +845,7 @@ void print_cfs_rq(struct seq_file *m, int cpu, struct cfs_rq *cfs_rq)
SEQ_printf(m, " .%-30s: %Ld.%06ld\n", "spread", SPLIT_NS(spread));
SEQ_printf(m, " .%-30s: %d\n", "nr_running", cfs_rq->nr_running);
SEQ_printf(m, " .%-30s: %d\n", "h_nr_running", cfs_rq->h_nr_running);
+ SEQ_printf(m, " .%-30s: %d\n", "h_nr_delayed", cfs_rq->h_nr_delayed);
SEQ_printf(m, " .%-30s: %d\n", "idle_nr_running",
cfs_rq->idle_nr_running);
SEQ_printf(m, " .%-30s: %d\n", "idle_h_nr_running",
diff --git a/kernel/sched/ext.c b/kernel/sched/ext.c
index 7fff1d045477..19d2699cf638 100644
--- a/kernel/sched/ext.c
+++ b/kernel/sched/ext.c
@@ -4763,7 +4763,7 @@ static void scx_ops_bypass(bool bypass)
* sees scx_rq_bypassing() before moving tasks to SCX.
*/
if (!scx_enabled()) {
- rq_unlock_irqrestore(rq, &rf);
+ rq_unlock(rq, &rf);
continue;
}
@@ -7013,7 +7013,7 @@ __bpf_kfunc int bpf_iter_scx_dsq_new(struct bpf_iter_scx_dsq *it, u64 dsq_id,
return -ENOENT;
INIT_LIST_HEAD(&kit->cursor.node);
- kit->cursor.flags |= SCX_DSQ_LNODE_ITER_CURSOR | flags;
+ kit->cursor.flags = SCX_DSQ_LNODE_ITER_CURSOR | flags;
kit->cursor.priv = READ_ONCE(kit->dsq->seq);
return 0;
diff --git a/kernel/sched/fair.c b/kernel/sched/fair.c
index fbdca89c677f..3e9ca38512de 100644
--- a/kernel/sched/fair.c
+++ b/kernel/sched/fair.c
@@ -1159,8 +1159,6 @@ static inline void update_curr_task(struct task_struct *p, s64 delta_exec)
trace_sched_stat_runtime(p, delta_exec);
account_group_exec_runtime(p, delta_exec);
cgroup_account_cputime(p, delta_exec);
- if (p->dl_server)
- dl_server_update(p->dl_server, delta_exec);
}
static inline bool did_preempt_short(struct cfs_rq *cfs_rq, struct sched_entity *curr)
@@ -1237,11 +1235,16 @@ static void update_curr(struct cfs_rq *cfs_rq)
update_curr_task(p, delta_exec);
/*
- * Any fair task that runs outside of fair_server should
- * account against fair_server such that it can account for
- * this time and possibly avoid running this period.
+ * If the fair_server is active, we need to account for the
+ * fair_server time whether or not the task is running on
+ * behalf of fair_server or not:
+ * - If the task is running on behalf of fair_server, we need
+ * to limit its time based on the assigned runtime.
+ * - Fair task that runs outside of fair_server should account
+ * against fair_server such that it can account for this time
+ * and possibly avoid running this period.
*/
- if (p->dl_server != &rq->fair_server)
+ if (dl_server_active(&rq->fair_server))
dl_server_update(&rq->fair_server, delta_exec);
}
@@ -3399,10 +3402,16 @@ retry_pids:
/* Initialise new per-VMA NUMAB state. */
if (!vma->numab_state) {
- vma->numab_state = kzalloc(sizeof(struct vma_numab_state),
- GFP_KERNEL);
- if (!vma->numab_state)
+ struct vma_numab_state *ptr;
+
+ ptr = kzalloc(sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ continue;
+
+ if (cmpxchg(&vma->numab_state, NULL, ptr)) {
+ kfree(ptr);
continue;
+ }
vma->numab_state->start_scan_seq = mm->numa_scan_seq;
@@ -5465,9 +5474,33 @@ static void clear_buddies(struct cfs_rq *cfs_rq, struct sched_entity *se)
static __always_inline void return_cfs_rq_runtime(struct cfs_rq *cfs_rq);
-static inline void finish_delayed_dequeue_entity(struct sched_entity *se)
+static void set_delayed(struct sched_entity *se)
+{
+ se->sched_delayed = 1;
+ for_each_sched_entity(se) {
+ struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+ cfs_rq->h_nr_delayed++;
+ if (cfs_rq_throttled(cfs_rq))
+ break;
+ }
+}
+
+static void clear_delayed(struct sched_entity *se)
{
se->sched_delayed = 0;
+ for_each_sched_entity(se) {
+ struct cfs_rq *cfs_rq = cfs_rq_of(se);
+
+ cfs_rq->h_nr_delayed--;
+ if (cfs_rq_throttled(cfs_rq))
+ break;
+ }
+}
+
+static inline void finish_delayed_dequeue_entity(struct sched_entity *se)
+{
+ clear_delayed(se);
if (sched_feat(DELAY_ZERO) && se->vlag > 0)
se->vlag = 0;
}
@@ -5478,6 +5511,7 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
bool sleep = flags & DEQUEUE_SLEEP;
update_curr(cfs_rq);
+ clear_buddies(cfs_rq, se);
if (flags & DEQUEUE_DELAYED) {
SCHED_WARN_ON(!se->sched_delayed);
@@ -5494,10 +5528,8 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
if (sched_feat(DELAY_DEQUEUE) && delay &&
!entity_eligible(cfs_rq, se)) {
- if (cfs_rq->next == se)
- cfs_rq->next = NULL;
update_load_avg(cfs_rq, se, 0);
- se->sched_delayed = 1;
+ set_delayed(se);
return false;
}
}
@@ -5520,8 +5552,6 @@ dequeue_entity(struct cfs_rq *cfs_rq, struct sched_entity *se, int flags)
update_stats_dequeue_fair(cfs_rq, se, flags);
- clear_buddies(cfs_rq, se);
-
update_entity_lag(cfs_rq, se);
if (sched_feat(PLACE_REL_DEADLINE) && !sleep) {
se->deadline -= se->vruntime;
@@ -5911,7 +5941,7 @@ static bool throttle_cfs_rq(struct cfs_rq *cfs_rq)
struct rq *rq = rq_of(cfs_rq);
struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg);
struct sched_entity *se;
- long task_delta, idle_task_delta, dequeue = 1;
+ long task_delta, idle_task_delta, delayed_delta, dequeue = 1;
long rq_h_nr_running = rq->cfs.h_nr_running;
raw_spin_lock(&cfs_b->lock);
@@ -5944,6 +5974,7 @@ static bool throttle_cfs_rq(struct cfs_rq *cfs_rq)
task_delta = cfs_rq->h_nr_running;
idle_task_delta = cfs_rq->idle_h_nr_running;
+ delayed_delta = cfs_rq->h_nr_delayed;
for_each_sched_entity(se) {
struct cfs_rq *qcfs_rq = cfs_rq_of(se);
int flags;
@@ -5967,6 +5998,7 @@ static bool throttle_cfs_rq(struct cfs_rq *cfs_rq)
qcfs_rq->h_nr_running -= task_delta;
qcfs_rq->idle_h_nr_running -= idle_task_delta;
+ qcfs_rq->h_nr_delayed -= delayed_delta;
if (qcfs_rq->load.weight) {
/* Avoid re-evaluating load for this entity: */
@@ -5989,6 +6021,7 @@ static bool throttle_cfs_rq(struct cfs_rq *cfs_rq)
qcfs_rq->h_nr_running -= task_delta;
qcfs_rq->idle_h_nr_running -= idle_task_delta;
+ qcfs_rq->h_nr_delayed -= delayed_delta;
}
/* At this point se is NULL and we are at root level*/
@@ -6014,7 +6047,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
struct rq *rq = rq_of(cfs_rq);
struct cfs_bandwidth *cfs_b = tg_cfs_bandwidth(cfs_rq->tg);
struct sched_entity *se;
- long task_delta, idle_task_delta;
+ long task_delta, idle_task_delta, delayed_delta;
long rq_h_nr_running = rq->cfs.h_nr_running;
se = cfs_rq->tg->se[cpu_of(rq)];
@@ -6050,6 +6083,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
task_delta = cfs_rq->h_nr_running;
idle_task_delta = cfs_rq->idle_h_nr_running;
+ delayed_delta = cfs_rq->h_nr_delayed;
for_each_sched_entity(se) {
struct cfs_rq *qcfs_rq = cfs_rq_of(se);
@@ -6067,6 +6101,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
qcfs_rq->h_nr_running += task_delta;
qcfs_rq->idle_h_nr_running += idle_task_delta;
+ qcfs_rq->h_nr_delayed += delayed_delta;
/* end evaluation on encountering a throttled cfs_rq */
if (cfs_rq_throttled(qcfs_rq))
@@ -6084,6 +6119,7 @@ void unthrottle_cfs_rq(struct cfs_rq *cfs_rq)
qcfs_rq->h_nr_running += task_delta;
qcfs_rq->idle_h_nr_running += idle_task_delta;
+ qcfs_rq->h_nr_delayed += delayed_delta;
/* end evaluation on encountering a throttled cfs_rq */
if (cfs_rq_throttled(qcfs_rq))
@@ -6937,7 +6973,7 @@ requeue_delayed_entity(struct sched_entity *se)
}
update_load_avg(cfs_rq, se, 0);
- se->sched_delayed = 0;
+ clear_delayed(se);
}
/*
@@ -6951,6 +6987,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
struct cfs_rq *cfs_rq;
struct sched_entity *se = &p->se;
int idle_h_nr_running = task_has_idle_policy(p);
+ int h_nr_delayed = 0;
int task_new = !(flags & ENQUEUE_WAKEUP);
int rq_h_nr_running = rq->cfs.h_nr_running;
u64 slice = 0;
@@ -6977,6 +7014,9 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
if (p->in_iowait)
cpufreq_update_util(rq, SCHED_CPUFREQ_IOWAIT);
+ if (task_new)
+ h_nr_delayed = !!se->sched_delayed;
+
for_each_sched_entity(se) {
if (se->on_rq) {
if (se->sched_delayed)
@@ -6999,6 +7039,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
cfs_rq->h_nr_running++;
cfs_rq->idle_h_nr_running += idle_h_nr_running;
+ cfs_rq->h_nr_delayed += h_nr_delayed;
if (cfs_rq_is_idle(cfs_rq))
idle_h_nr_running = 1;
@@ -7022,6 +7063,7 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
cfs_rq->h_nr_running++;
cfs_rq->idle_h_nr_running += idle_h_nr_running;
+ cfs_rq->h_nr_delayed += h_nr_delayed;
if (cfs_rq_is_idle(cfs_rq))
idle_h_nr_running = 1;
@@ -7084,6 +7126,7 @@ static int dequeue_entities(struct rq *rq, struct sched_entity *se, int flags)
struct task_struct *p = NULL;
int idle_h_nr_running = 0;
int h_nr_running = 0;
+ int h_nr_delayed = 0;
struct cfs_rq *cfs_rq;
u64 slice = 0;
@@ -7091,6 +7134,8 @@ static int dequeue_entities(struct rq *rq, struct sched_entity *se, int flags)
p = task_of(se);
h_nr_running = 1;
idle_h_nr_running = task_has_idle_policy(p);
+ if (!task_sleep && !task_delayed)
+ h_nr_delayed = !!se->sched_delayed;
} else {
cfs_rq = group_cfs_rq(se);
slice = cfs_rq_min_slice(cfs_rq);
@@ -7108,6 +7153,7 @@ static int dequeue_entities(struct rq *rq, struct sched_entity *se, int flags)
cfs_rq->h_nr_running -= h_nr_running;
cfs_rq->idle_h_nr_running -= idle_h_nr_running;
+ cfs_rq->h_nr_delayed -= h_nr_delayed;
if (cfs_rq_is_idle(cfs_rq))
idle_h_nr_running = h_nr_running;
@@ -7146,6 +7192,7 @@ static int dequeue_entities(struct rq *rq, struct sched_entity *se, int flags)
cfs_rq->h_nr_running -= h_nr_running;
cfs_rq->idle_h_nr_running -= idle_h_nr_running;
+ cfs_rq->h_nr_delayed -= h_nr_delayed;
if (cfs_rq_is_idle(cfs_rq))
idle_h_nr_running = h_nr_running;
@@ -8774,7 +8821,7 @@ static void check_preempt_wakeup_fair(struct rq *rq, struct task_struct *p, int
if (unlikely(throttled_hierarchy(cfs_rq_of(pse))))
return;
- if (sched_feat(NEXT_BUDDY) && !(wake_flags & WF_FORK)) {
+ if (sched_feat(NEXT_BUDDY) && !(wake_flags & WF_FORK) && !pse->sched_delayed) {
set_next_buddy(pse);
}
@@ -12568,7 +12615,7 @@ static void _nohz_idle_balance(struct rq *this_rq, unsigned int flags)
* work being done for other CPUs. Next load
* balancing owner will pick it up.
*/
- if (need_resched()) {
+ if (!idle_cpu(this_cpu) && need_resched()) {
if (flags & NOHZ_STATS_KICK)
has_blocked_load = true;
if (flags & NOHZ_NEXT_KICK)
diff --git a/kernel/sched/pelt.c b/kernel/sched/pelt.c
index fc07382361a8..fee75cc2c47b 100644
--- a/kernel/sched/pelt.c
+++ b/kernel/sched/pelt.c
@@ -321,7 +321,7 @@ int __update_load_avg_cfs_rq(u64 now, struct cfs_rq *cfs_rq)
{
if (___update_load_sum(now, &cfs_rq->avg,
scale_load_down(cfs_rq->load.weight),
- cfs_rq->h_nr_running,
+ cfs_rq->h_nr_running - cfs_rq->h_nr_delayed,
cfs_rq->curr != NULL)) {
___update_load_avg(&cfs_rq->avg, 1);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index 76f5f53a645f..c5d67a43fe52 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -398,6 +398,11 @@ extern void __dl_server_attach_root(struct sched_dl_entity *dl_se, struct rq *rq
extern int dl_server_apply_params(struct sched_dl_entity *dl_se,
u64 runtime, u64 period, bool init);
+static inline bool dl_server_active(struct sched_dl_entity *dl_se)
+{
+ return dl_se->dl_server_active;
+}
+
#ifdef CONFIG_CGROUP_SCHED
extern struct list_head task_groups;
@@ -649,6 +654,7 @@ struct cfs_rq {
unsigned int h_nr_running; /* SCHED_{NORMAL,BATCH,IDLE} */
unsigned int idle_nr_running; /* SCHED_IDLE */
unsigned int idle_h_nr_running; /* SCHED_IDLE */
+ unsigned int h_nr_delayed;
s64 avg_vruntime;
u64 avg_load;
@@ -898,8 +904,11 @@ struct dl_rq {
static inline void se_update_runnable(struct sched_entity *se)
{
- if (!entity_is_task(se))
- se->runnable_weight = se->my_q->h_nr_running;
+ if (!entity_is_task(se)) {
+ struct cfs_rq *cfs_rq = se->my_q;
+
+ se->runnable_weight = cfs_rq->h_nr_running - cfs_rq->h_nr_delayed;
+ }
}
static inline long se_runnable(struct sched_entity *se)
diff --git a/kernel/sched/syscalls.c b/kernel/sched/syscalls.c
index 0d71fcbaf1e3..ff0e5ab4e37c 100644
--- a/kernel/sched/syscalls.c
+++ b/kernel/sched/syscalls.c
@@ -1200,7 +1200,7 @@ int __sched_setaffinity(struct task_struct *p, struct affinity_context *ctx)
bool empty = !cpumask_and(new_mask, new_mask,
ctx->user_mask);
- if (WARN_ON_ONCE(empty))
+ if (empty)
cpumask_copy(new_mask, cpus_allowed);
}
__set_cpus_allowed_ptr(p, ctx);
diff --git a/kernel/signal.c b/kernel/signal.c
index 98b65cb35830..989b1cc9116a 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1959,14 +1959,15 @@ static void posixtimer_queue_sigqueue(struct sigqueue *q, struct task_struct *t,
*
* Where type is not PIDTYPE_PID, signals must be delivered to the
* process. In this case, prefer to deliver to current if it is in
- * the same thread group as the target process, which avoids
- * unnecessarily waking up a potentially idle task.
+ * the same thread group as the target process and its sighand is
+ * stable, which avoids unnecessarily waking up a potentially idle task.
*/
static inline struct task_struct *posixtimer_get_target(struct k_itimer *tmr)
{
struct task_struct *t = pid_task(tmr->it_pid, tmr->it_pid_type);
- if (t && tmr->it_pid_type != PIDTYPE_PID && same_thread_group(t, current))
+ if (t && tmr->it_pid_type != PIDTYPE_PID &&
+ same_thread_group(t, current) && !current->exit_state)
t = current;
return t;
}
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 8b41bd13cc3d..4dae6ac2e83f 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -280,17 +280,24 @@ static inline void invoke_softirq(void)
wakeup_softirqd();
}
+#define SCHED_SOFTIRQ_MASK BIT(SCHED_SOFTIRQ)
+
/*
* flush_smp_call_function_queue() can raise a soft interrupt in a function
- * call. On RT kernels this is undesired and the only known functionality
- * in the block layer which does this is disabled on RT. If soft interrupts
- * get raised which haven't been raised before the flush, warn so it can be
+ * call. On RT kernels this is undesired and the only known functionalities
+ * are in the block layer which is disabled on RT, and in the scheduler for
+ * idle load balancing. If soft interrupts get raised which haven't been
+ * raised before the flush, warn if it is not a SCHED_SOFTIRQ so it can be
* investigated.
*/
void do_softirq_post_smp_call_flush(unsigned int was_pending)
{
- if (WARN_ON_ONCE(was_pending != local_softirq_pending()))
+ unsigned int is_pending = local_softirq_pending();
+
+ if (unlikely(was_pending != is_pending)) {
+ WARN_ON_ONCE(was_pending != (is_pending & ~SCHED_SOFTIRQ_MASK));
invoke_softirq();
+ }
}
#else /* CONFIG_PREEMPT_RT */
diff --git a/kernel/static_call_inline.c b/kernel/static_call_inline.c
index 5259cda486d0..bb7d066a7c39 100644
--- a/kernel/static_call_inline.c
+++ b/kernel/static_call_inline.c
@@ -15,7 +15,7 @@ extern struct static_call_site __start_static_call_sites[],
extern struct static_call_tramp_key __start_static_call_tramp_key[],
__stop_static_call_tramp_key[];
-static int static_call_initialized;
+int static_call_initialized;
/*
* Must be called before early_initcall() to be effective.
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index aab6472853fa..7304d7cf47f2 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -24,7 +24,7 @@ static void clocksource_enqueue(struct clocksource *cs);
static noinline u64 cycles_to_nsec_safe(struct clocksource *cs, u64 start, u64 end)
{
- u64 delta = clocksource_delta(end, start, cs->mask);
+ u64 delta = clocksource_delta(end, start, cs->mask, cs->max_raw_delta);
if (likely(delta < cs->max_cycles))
return clocksource_cyc2ns(delta, cs->mult, cs->shift);
@@ -993,6 +993,15 @@ static inline void clocksource_update_max_deferment(struct clocksource *cs)
cs->max_idle_ns = clocks_calc_max_nsecs(cs->mult, cs->shift,
cs->maxadj, cs->mask,
&cs->max_cycles);
+
+ /*
+ * Threshold for detecting negative motion in clocksource_delta().
+ *
+ * Allow for 0.875 of the counter width so that overly long idle
+ * sleeps, which go slightly over mask/2, do not trigger the
+ * negative motion detection.
+ */
+ cs->max_raw_delta = (cs->mask >> 1) + (cs->mask >> 2) + (cs->mask >> 3);
}
static struct clocksource *clocksource_find_best(bool oneshot, bool skipcur)
diff --git a/kernel/time/ntp.c b/kernel/time/ntp.c
index b550ebe0f03b..163e7a2033b6 100644
--- a/kernel/time/ntp.c
+++ b/kernel/time/ntp.c
@@ -798,7 +798,7 @@ int __do_adjtimex(struct __kernel_timex *txc, const struct timespec64 *ts,
txc->offset = shift_right(ntpdata->time_offset * NTP_INTERVAL_FREQ, NTP_SCALE_SHIFT);
if (!(ntpdata->time_status & STA_NANO))
- txc->offset = (u32)txc->offset / NSEC_PER_USEC;
+ txc->offset = div_s64(txc->offset, NSEC_PER_USEC);
}
result = ntpdata->time_state;
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index 0ca85ff4fbb4..3d128825d343 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -755,7 +755,8 @@ static void timekeeping_forward_now(struct timekeeper *tk)
u64 cycle_now, delta;
cycle_now = tk_clock_read(&tk->tkr_mono);
- delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask);
+ delta = clocksource_delta(cycle_now, tk->tkr_mono.cycle_last, tk->tkr_mono.mask,
+ tk->tkr_mono.clock->max_raw_delta);
tk->tkr_mono.cycle_last = cycle_now;
tk->tkr_raw.cycle_last = cycle_now;
@@ -2230,7 +2231,8 @@ static bool timekeeping_advance(enum timekeeping_adv_mode mode)
return false;
offset = clocksource_delta(tk_clock_read(&tk->tkr_mono),
- tk->tkr_mono.cycle_last, tk->tkr_mono.mask);
+ tk->tkr_mono.cycle_last, tk->tkr_mono.mask,
+ tk->tkr_mono.clock->max_raw_delta);
/* Check if there's really nothing to do */
if (offset < real_tk->cycle_interval && mode == TK_ADV_TICK)
diff --git a/kernel/time/timekeeping_internal.h b/kernel/time/timekeeping_internal.h
index 63e600e943a7..8c9079108ffb 100644
--- a/kernel/time/timekeeping_internal.h
+++ b/kernel/time/timekeeping_internal.h
@@ -30,15 +30,15 @@ static inline void timekeeping_inc_mg_floor_swaps(void)
#endif
-static inline u64 clocksource_delta(u64 now, u64 last, u64 mask)
+static inline u64 clocksource_delta(u64 now, u64 last, u64 mask, u64 max_delta)
{
u64 ret = (now - last) & mask;
/*
- * Prevent time going backwards by checking the MSB of mask in
- * the result. If set, return 0.
+ * Prevent time going backwards by checking the result against
+ * @max_delta. If greater, return 0.
*/
- return ret & ~(mask >> 1) ? 0 : ret;
+ return ret > max_delta ? 0 : ret;
}
/* Semi public for serialization of non timekeeper VDSO updates. */
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index 949a3870946c..1b8db5aee9d3 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -2250,6 +2250,9 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
goto unlock;
old_array = bpf_event_rcu_dereference(event->tp_event->prog_array);
+ if (!old_array)
+ goto put;
+
ret = bpf_prog_array_copy(old_array, event->prog, NULL, 0, &new_array);
if (ret < 0) {
bpf_prog_array_delete_safe(old_array, event->prog);
@@ -2258,6 +2261,14 @@ void perf_event_detach_bpf_prog(struct perf_event *event)
bpf_prog_array_free_sleepable(old_array);
}
+put:
+ /*
+ * It could be that the bpf_prog is not sleepable (and will be freed
+ * via normal RCU), but is called from a point that supports sleepable
+ * programs and uses tasks-trace-RCU.
+ */
+ synchronize_rcu_tasks_trace();
+
bpf_prog_put(event->prog);
event->prog = NULL;
diff --git a/kernel/trace/fgraph.c b/kernel/trace/fgraph.c
index 0bf78517b5d4..30e3ddc8a8a8 100644
--- a/kernel/trace/fgraph.c
+++ b/kernel/trace/fgraph.c
@@ -833,7 +833,7 @@ static unsigned long __ftrace_return_to_handler(struct fgraph_ret_regs *ret_regs
#endif
{
for_each_set_bit(i, &bitmap, sizeof(bitmap) * BITS_PER_BYTE) {
- struct fgraph_ops *gops = fgraph_array[i];
+ struct fgraph_ops *gops = READ_ONCE(fgraph_array[i]);
if (gops == &fgraph_stub)
continue;
@@ -1215,7 +1215,7 @@ void fgraph_update_pid_func(void)
static int start_graph_tracing(void)
{
unsigned long **ret_stack_list;
- int ret;
+ int ret, cpu;
ret_stack_list = kcalloc(FTRACE_RETSTACK_ALLOC_SIZE,
sizeof(*ret_stack_list), GFP_KERNEL);
@@ -1223,6 +1223,12 @@ static int start_graph_tracing(void)
if (!ret_stack_list)
return -ENOMEM;
+ /* The cpu_boot init_task->ret_stack will never be freed */
+ for_each_online_cpu(cpu) {
+ if (!idle_task(cpu)->ret_stack)
+ ftrace_graph_init_idle_task(idle_task(cpu), cpu);
+ }
+
do {
ret = alloc_retstack_tasklist(ret_stack_list);
} while (ret == -EAGAIN);
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 9b17efb1a87d..2e113f8b13a2 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -902,16 +902,13 @@ static void profile_graph_return(struct ftrace_graph_ret *trace,
}
static struct fgraph_ops fprofiler_ops = {
- .ops = {
- .flags = FTRACE_OPS_FL_INITIALIZED,
- INIT_OPS_HASH(fprofiler_ops.ops)
- },
.entryfunc = &profile_graph_entry,
.retfunc = &profile_graph_return,
};
static int register_ftrace_profiler(void)
{
+ ftrace_ops_set_global_filter(&fprofiler_ops.ops);
return register_ftrace_graph(&fprofiler_ops);
}
@@ -922,12 +919,11 @@ static void unregister_ftrace_profiler(void)
#else
static struct ftrace_ops ftrace_profile_ops __read_mostly = {
.func = function_profile_call,
- .flags = FTRACE_OPS_FL_INITIALIZED,
- INIT_OPS_HASH(ftrace_profile_ops)
};
static int register_ftrace_profiler(void)
{
+ ftrace_ops_set_global_filter(&ftrace_profile_ops);
return register_ftrace_function(&ftrace_profile_ops);
}
diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
index 7e257e855dd1..60210fb5b211 100644
--- a/kernel/trace/ring_buffer.c
+++ b/kernel/trace/ring_buffer.c
@@ -7019,7 +7019,11 @@ static int __rb_map_vma(struct ring_buffer_per_cpu *cpu_buffer,
lockdep_assert_held(&cpu_buffer->mapping_lock);
nr_subbufs = cpu_buffer->nr_pages + 1; /* + reader-subbuf */
- nr_pages = ((nr_subbufs + 1) << subbuf_order) - pgoff; /* + meta-page */
+ nr_pages = ((nr_subbufs + 1) << subbuf_order); /* + meta-page */
+ if (nr_pages <= pgoff)
+ return -EINVAL;
+
+ nr_pages -= pgoff;
nr_vma_pages = vma_pages(vma);
if (!nr_vma_pages || nr_vma_pages > nr_pages)
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 3ef047ed9705..f8aebcb01e62 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2552,6 +2552,8 @@ unsigned int tracing_gen_ctx_irq_test(unsigned int irqs_status)
trace_flags |= TRACE_FLAG_NEED_RESCHED;
if (test_preempt_need_resched())
trace_flags |= TRACE_FLAG_PREEMPT_RESCHED;
+ if (IS_ENABLED(CONFIG_ARCH_HAS_PREEMPT_LAZY) && tif_test_bit(TIF_NEED_RESCHED_LAZY))
+ trace_flags |= TRACE_FLAG_NEED_RESCHED_LAZY;
return (trace_flags << 16) | (min_t(unsigned int, pc & 0xff, 0xf)) |
(min_t(unsigned int, migration_disable_value(), 0xf)) << 4;
}
@@ -3609,17 +3611,12 @@ char *trace_iter_expand_format(struct trace_iterator *iter)
}
/* Returns true if the string is safe to dereference from an event */
-static bool trace_safe_str(struct trace_iterator *iter, const char *str,
- bool star, int len)
+static bool trace_safe_str(struct trace_iterator *iter, const char *str)
{
unsigned long addr = (unsigned long)str;
struct trace_event *trace_event;
struct trace_event_call *event;
- /* Ignore strings with no length */
- if (star && !len)
- return true;
-
/* OK if part of the event data */
if ((addr >= (unsigned long)iter->ent) &&
(addr < (unsigned long)iter->ent + iter->ent_size))
@@ -3659,181 +3656,69 @@ static bool trace_safe_str(struct trace_iterator *iter, const char *str,
return false;
}
-static DEFINE_STATIC_KEY_FALSE(trace_no_verify);
-
-static int test_can_verify_check(const char *fmt, ...)
-{
- char buf[16];
- va_list ap;
- int ret;
-
- /*
- * The verifier is dependent on vsnprintf() modifies the va_list
- * passed to it, where it is sent as a reference. Some architectures
- * (like x86_32) passes it by value, which means that vsnprintf()
- * does not modify the va_list passed to it, and the verifier
- * would then need to be able to understand all the values that
- * vsnprintf can use. If it is passed by value, then the verifier
- * is disabled.
- */
- va_start(ap, fmt);
- vsnprintf(buf, 16, "%d", ap);
- ret = va_arg(ap, int);
- va_end(ap);
-
- return ret;
-}
-
-static void test_can_verify(void)
-{
- if (!test_can_verify_check("%d %d", 0, 1)) {
- pr_info("trace event string verifier disabled\n");
- static_branch_inc(&trace_no_verify);
- }
-}
-
/**
- * trace_check_vprintf - Check dereferenced strings while writing to the seq buffer
+ * ignore_event - Check dereferenced fields while writing to the seq buffer
* @iter: The iterator that holds the seq buffer and the event being printed
- * @fmt: The format used to print the event
- * @ap: The va_list holding the data to print from @fmt.
*
- * This writes the data into the @iter->seq buffer using the data from
- * @fmt and @ap. If the format has a %s, then the source of the string
- * is examined to make sure it is safe to print, otherwise it will
- * warn and print "[UNSAFE MEMORY]" in place of the dereferenced string
- * pointer.
+ * At boot up, test_event_printk() will flag any event that dereferences
+ * a string with "%s" that does exist in the ring buffer. It may still
+ * be valid, as the string may point to a static string in the kernel
+ * rodata that never gets freed. But if the string pointer is pointing
+ * to something that was allocated, there's a chance that it can be freed
+ * by the time the user reads the trace. This would cause a bad memory
+ * access by the kernel and possibly crash the system.
+ *
+ * This function will check if the event has any fields flagged as needing
+ * to be checked at runtime and perform those checks.
+ *
+ * If it is found that a field is unsafe, it will write into the @iter->seq
+ * a message stating what was found to be unsafe.
+ *
+ * @return: true if the event is unsafe and should be ignored,
+ * false otherwise.
*/
-void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
- va_list ap)
+bool ignore_event(struct trace_iterator *iter)
{
- long text_delta = 0;
- long data_delta = 0;
- const char *p = fmt;
- const char *str;
- bool good;
- int i, j;
+ struct ftrace_event_field *field;
+ struct trace_event *trace_event;
+ struct trace_event_call *event;
+ struct list_head *head;
+ struct trace_seq *seq;
+ const void *ptr;
- if (WARN_ON_ONCE(!fmt))
- return;
+ trace_event = ftrace_find_event(iter->ent->type);
- if (static_branch_unlikely(&trace_no_verify))
- goto print;
+ seq = &iter->seq;
- /*
- * When the kernel is booted with the tp_printk command line
- * parameter, trace events go directly through to printk().
- * It also is checked by this function, but it does not
- * have an associated trace_array (tr) for it.
- */
- if (iter->tr) {
- text_delta = iter->tr->text_delta;
- data_delta = iter->tr->data_delta;
+ if (!trace_event) {
+ trace_seq_printf(seq, "EVENT ID %d NOT FOUND?\n", iter->ent->type);
+ return true;
}
- /* Don't bother checking when doing a ftrace_dump() */
- if (iter->fmt == static_fmt_buf)
- goto print;
-
- while (*p) {
- bool star = false;
- int len = 0;
-
- j = 0;
-
- /*
- * We only care about %s and variants
- * as well as %p[sS] if delta is non-zero
- */
- for (i = 0; p[i]; i++) {
- if (i + 1 >= iter->fmt_size) {
- /*
- * If we can't expand the copy buffer,
- * just print it.
- */
- if (!trace_iter_expand_format(iter))
- goto print;
- }
-
- if (p[i] == '\\' && p[i+1]) {
- i++;
- continue;
- }
- if (p[i] == '%') {
- /* Need to test cases like %08.*s */
- for (j = 1; p[i+j]; j++) {
- if (isdigit(p[i+j]) ||
- p[i+j] == '.')
- continue;
- if (p[i+j] == '*') {
- star = true;
- continue;
- }
- break;
- }
- if (p[i+j] == 's')
- break;
-
- if (text_delta && p[i+1] == 'p' &&
- ((p[i+2] == 's' || p[i+2] == 'S')))
- break;
-
- star = false;
- }
- j = 0;
- }
- /* If no %s found then just print normally */
- if (!p[i])
- break;
-
- /* Copy up to the %s, and print that */
- strncpy(iter->fmt, p, i);
- iter->fmt[i] = '\0';
- trace_seq_vprintf(&iter->seq, iter->fmt, ap);
+ event = container_of(trace_event, struct trace_event_call, event);
+ if (!(event->flags & TRACE_EVENT_FL_TEST_STR))
+ return false;
- /* Add delta to %pS pointers */
- if (p[i+1] == 'p') {
- unsigned long addr;
- char fmt[4];
+ head = trace_get_fields(event);
+ if (!head) {
+ trace_seq_printf(seq, "FIELDS FOR EVENT '%s' NOT FOUND?\n",
+ trace_event_name(event));
+ return true;
+ }
- fmt[0] = '%';
- fmt[1] = 'p';
- fmt[2] = p[i+2]; /* Either %ps or %pS */
- fmt[3] = '\0';
+ /* Offsets are from the iter->ent that points to the raw event */
+ ptr = iter->ent;
- addr = va_arg(ap, unsigned long);
- addr += text_delta;
- trace_seq_printf(&iter->seq, fmt, (void *)addr);
+ list_for_each_entry(field, head, link) {
+ const char *str;
+ bool good;
- p += i + 3;
+ if (!field->needs_test)
continue;
- }
-
- /*
- * If iter->seq is full, the above call no longer guarantees
- * that ap is in sync with fmt processing, and further calls
- * to va_arg() can return wrong positional arguments.
- *
- * Ensure that ap is no longer used in this case.
- */
- if (iter->seq.full) {
- p = "";
- break;
- }
- if (star)
- len = va_arg(ap, int);
+ str = *(const char **)(ptr + field->offset);
- /* The ap now points to the string data of the %s */
- str = va_arg(ap, const char *);
-
- good = trace_safe_str(iter, str, star, len);
-
- /* Could be from the last boot */
- if (data_delta && !good) {
- str += data_delta;
- good = trace_safe_str(iter, str, star, len);
- }
+ good = trace_safe_str(iter, str);
/*
* If you hit this warning, it is likely that the
@@ -3844,44 +3729,14 @@ void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
* instead. See samples/trace_events/trace-events-sample.h
* for reference.
*/
- if (WARN_ONCE(!good, "fmt: '%s' current_buffer: '%s'",
- fmt, seq_buf_str(&iter->seq.seq))) {
- int ret;
-
- /* Try to safely read the string */
- if (star) {
- if (len + 1 > iter->fmt_size)
- len = iter->fmt_size - 1;
- if (len < 0)
- len = 0;
- ret = copy_from_kernel_nofault(iter->fmt, str, len);
- iter->fmt[len] = 0;
- star = false;
- } else {
- ret = strncpy_from_kernel_nofault(iter->fmt, str,
- iter->fmt_size);
- }
- if (ret < 0)
- trace_seq_printf(&iter->seq, "(0x%px)", str);
- else
- trace_seq_printf(&iter->seq, "(0x%px:%s)",
- str, iter->fmt);
- str = "[UNSAFE-MEMORY]";
- strcpy(iter->fmt, "%s");
- } else {
- strncpy(iter->fmt, p + i, j + 1);
- iter->fmt[j+1] = '\0';
+ if (WARN_ONCE(!good, "event '%s' has unsafe pointer field '%s'",
+ trace_event_name(event), field->name)) {
+ trace_seq_printf(seq, "EVENT %s: HAS UNSAFE POINTER FIELD '%s'\n",
+ trace_event_name(event), field->name);
+ return true;
}
- if (star)
- trace_seq_printf(&iter->seq, iter->fmt, len, str);
- else
- trace_seq_printf(&iter->seq, iter->fmt, str);
-
- p += i + j + 1;
}
- print:
- if (*p)
- trace_seq_vprintf(&iter->seq, p, ap);
+ return false;
}
const char *trace_event_format(struct trace_iterator *iter, const char *fmt)
@@ -4351,6 +4206,15 @@ static enum print_line_t print_trace_fmt(struct trace_iterator *iter)
if (event) {
if (tr->trace_flags & TRACE_ITER_FIELDS)
return print_event_fields(iter, event);
+ /*
+ * For TRACE_EVENT() events, the print_fmt is not
+ * safe to use if the array has delta offsets
+ * Force printing via the fields.
+ */
+ if ((tr->text_delta || tr->data_delta) &&
+ event->type > __TRACE_LAST_TYPE)
+ return print_event_fields(iter, event);
+
return event->funcs->trace(iter, sym_flags, event);
}
@@ -5223,6 +5087,9 @@ tracing_cpumask_write(struct file *filp, const char __user *ubuf,
cpumask_var_t tracing_cpumask_new;
int err;
+ if (count == 0 || count > KMALLOC_MAX_SIZE)
+ return -EINVAL;
+
if (!zalloc_cpumask_var(&tracing_cpumask_new, GFP_KERNEL))
return -ENOMEM;
@@ -10775,8 +10642,6 @@ __init static int tracer_alloc_buffers(void)
register_snapshot_cmd();
- test_can_verify();
-
return 0;
out_free_pipe_cpumask:
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 266740b4e121..9691b47b5f3d 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -667,9 +667,8 @@ void trace_buffer_unlock_commit_nostack(struct trace_buffer *buffer,
bool trace_is_tracepoint_string(const char *str);
const char *trace_event_format(struct trace_iterator *iter, const char *fmt);
-void trace_check_vprintf(struct trace_iterator *iter, const char *fmt,
- va_list ap) __printf(2, 0);
char *trace_iter_expand_format(struct trace_iterator *iter);
+bool ignore_event(struct trace_iterator *iter);
int trace_empty(struct trace_iterator *iter);
@@ -1413,7 +1412,8 @@ struct ftrace_event_field {
int filter_type;
int offset;
int size;
- int is_signed;
+ unsigned int is_signed:1;
+ unsigned int needs_test:1;
int len;
};
diff --git a/kernel/trace/trace_eprobe.c b/kernel/trace/trace_eprobe.c
index ebda68ee9abf..be8be0c1aaf0 100644
--- a/kernel/trace/trace_eprobe.c
+++ b/kernel/trace/trace_eprobe.c
@@ -963,6 +963,11 @@ static int __trace_eprobe_create(int argc, const char *argv[])
goto error;
}
ret = dyn_event_add(&ep->devent, &ep->tp.event->call);
+ if (ret < 0) {
+ trace_probe_unregister_event_call(&ep->tp);
+ mutex_unlock(&event_mutex);
+ goto error;
+ }
mutex_unlock(&event_mutex);
return ret;
parse_error:
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 77e68efbd43e..770e7ed91716 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -82,7 +82,7 @@ static int system_refcount_dec(struct event_subsystem *system)
}
static struct ftrace_event_field *
-__find_event_field(struct list_head *head, char *name)
+__find_event_field(struct list_head *head, const char *name)
{
struct ftrace_event_field *field;
@@ -114,7 +114,8 @@ trace_find_event_field(struct trace_event_call *call, char *name)
static int __trace_define_field(struct list_head *head, const char *type,
const char *name, int offset, int size,
- int is_signed, int filter_type, int len)
+ int is_signed, int filter_type, int len,
+ int need_test)
{
struct ftrace_event_field *field;
@@ -133,6 +134,7 @@ static int __trace_define_field(struct list_head *head, const char *type,
field->offset = offset;
field->size = size;
field->is_signed = is_signed;
+ field->needs_test = need_test;
field->len = len;
list_add(&field->link, head);
@@ -151,13 +153,13 @@ int trace_define_field(struct trace_event_call *call, const char *type,
head = trace_get_fields(call);
return __trace_define_field(head, type, name, offset, size,
- is_signed, filter_type, 0);
+ is_signed, filter_type, 0, 0);
}
EXPORT_SYMBOL_GPL(trace_define_field);
static int trace_define_field_ext(struct trace_event_call *call, const char *type,
const char *name, int offset, int size, int is_signed,
- int filter_type, int len)
+ int filter_type, int len, int need_test)
{
struct list_head *head;
@@ -166,13 +168,13 @@ static int trace_define_field_ext(struct trace_event_call *call, const char *typ
head = trace_get_fields(call);
return __trace_define_field(head, type, name, offset, size,
- is_signed, filter_type, len);
+ is_signed, filter_type, len, need_test);
}
#define __generic_field(type, item, filter_type) \
ret = __trace_define_field(&ftrace_generic_fields, #type, \
#item, 0, 0, is_signed_type(type), \
- filter_type, 0); \
+ filter_type, 0, 0); \
if (ret) \
return ret;
@@ -181,7 +183,8 @@ static int trace_define_field_ext(struct trace_event_call *call, const char *typ
"common_" #item, \
offsetof(typeof(ent), item), \
sizeof(ent.item), \
- is_signed_type(type), FILTER_OTHER, 0); \
+ is_signed_type(type), FILTER_OTHER, \
+ 0, 0); \
if (ret) \
return ret;
@@ -244,19 +247,16 @@ int trace_event_get_offsets(struct trace_event_call *call)
return tail->offset + tail->size;
}
-/*
- * Check if the referenced field is an array and return true,
- * as arrays are OK to dereference.
- */
-static bool test_field(const char *fmt, struct trace_event_call *call)
+
+static struct trace_event_fields *find_event_field(const char *fmt,
+ struct trace_event_call *call)
{
struct trace_event_fields *field = call->class->fields_array;
- const char *array_descriptor;
const char *p = fmt;
int len;
if (!(len = str_has_prefix(fmt, "REC->")))
- return false;
+ return NULL;
fmt += len;
for (p = fmt; *p; p++) {
if (!isalnum(*p) && *p != '_')
@@ -265,16 +265,141 @@ static bool test_field(const char *fmt, struct trace_event_call *call)
len = p - fmt;
for (; field->type; field++) {
- if (strncmp(field->name, fmt, len) ||
- field->name[len])
+ if (strncmp(field->name, fmt, len) || field->name[len])
continue;
- array_descriptor = strchr(field->type, '[');
- /* This is an array and is OK to dereference. */
- return array_descriptor != NULL;
+
+ return field;
+ }
+ return NULL;
+}
+
+/*
+ * Check if the referenced field is an array and return true,
+ * as arrays are OK to dereference.
+ */
+static bool test_field(const char *fmt, struct trace_event_call *call)
+{
+ struct trace_event_fields *field;
+
+ field = find_event_field(fmt, call);
+ if (!field)
+ return false;
+
+ /* This is an array and is OK to dereference. */
+ return strchr(field->type, '[') != NULL;
+}
+
+/* Look for a string within an argument */
+static bool find_print_string(const char *arg, const char *str, const char *end)
+{
+ const char *r;
+
+ r = strstr(arg, str);
+ return r && r < end;
+}
+
+/* Return true if the argument pointer is safe */
+static bool process_pointer(const char *fmt, int len, struct trace_event_call *call)
+{
+ const char *r, *e, *a;
+
+ e = fmt + len;
+
+ /* Find the REC-> in the argument */
+ r = strstr(fmt, "REC->");
+ if (r && r < e) {
+ /*
+ * Addresses of events on the buffer, or an array on the buffer is
+ * OK to dereference. There's ways to fool this, but
+ * this is to catch common mistakes, not malicious code.
+ */
+ a = strchr(fmt, '&');
+ if ((a && (a < r)) || test_field(r, call))
+ return true;
+ } else if (find_print_string(fmt, "__get_dynamic_array(", e)) {
+ return true;
+ } else if (find_print_string(fmt, "__get_rel_dynamic_array(", e)) {
+ return true;
+ } else if (find_print_string(fmt, "__get_dynamic_array_len(", e)) {
+ return true;
+ } else if (find_print_string(fmt, "__get_rel_dynamic_array_len(", e)) {
+ return true;
+ } else if (find_print_string(fmt, "__get_sockaddr(", e)) {
+ return true;
+ } else if (find_print_string(fmt, "__get_rel_sockaddr(", e)) {
+ return true;
}
return false;
}
+/* Return true if the string is safe */
+static bool process_string(const char *fmt, int len, struct trace_event_call *call)
+{
+ struct trace_event_fields *field;
+ const char *r, *e, *s;
+
+ e = fmt + len;
+
+ /*
+ * There are several helper functions that return strings.
+ * If the argument contains a function, then assume its field is valid.
+ * It is considered that the argument has a function if it has:
+ * alphanumeric or '_' before a parenthesis.
+ */
+ s = fmt;
+ do {
+ r = strstr(s, "(");
+ if (!r || r >= e)
+ break;
+ for (int i = 1; r - i >= s; i++) {
+ char ch = *(r - i);
+ if (isspace(ch))
+ continue;
+ if (isalnum(ch) || ch == '_')
+ return true;
+ /* Anything else, this isn't a function */
+ break;
+ }
+ /* A function could be wrapped in parethesis, try the next one */
+ s = r + 1;
+ } while (s < e);
+
+ /*
+ * Check for arrays. If the argument has: foo[REC->val]
+ * then it is very likely that foo is an array of strings
+ * that are safe to use.
+ */
+ r = strstr(s, "[");
+ if (r && r < e) {
+ r = strstr(r, "REC->");
+ if (r && r < e)
+ return true;
+ }
+
+ /*
+ * If there's any strings in the argument consider this arg OK as it
+ * could be: REC->field ? "foo" : "bar" and we don't want to get into
+ * verifying that logic here.
+ */
+ if (find_print_string(fmt, "\"", e))
+ return true;
+
+ /* Dereferenced strings are also valid like any other pointer */
+ if (process_pointer(fmt, len, call))
+ return true;
+
+ /* Make sure the field is found */
+ field = find_event_field(fmt, call);
+ if (!field)
+ return false;
+
+ /* Test this field's string before printing the event */
+ call->flags |= TRACE_EVENT_FL_TEST_STR;
+ field->needs_test = 1;
+
+ return true;
+}
+
/*
* Examine the print fmt of the event looking for unsafe dereference
* pointers using %p* that could be recorded in the trace event and
@@ -284,13 +409,14 @@ static bool test_field(const char *fmt, struct trace_event_call *call)
static void test_event_printk(struct trace_event_call *call)
{
u64 dereference_flags = 0;
+ u64 string_flags = 0;
bool first = true;
- const char *fmt, *c, *r, *a;
+ const char *fmt;
int parens = 0;
char in_quote = 0;
int start_arg = 0;
int arg = 0;
- int i;
+ int i, e;
fmt = call->print_fmt;
@@ -374,8 +500,16 @@ static void test_event_printk(struct trace_event_call *call)
star = true;
continue;
}
- if ((fmt[i + j] == 's') && star)
- arg++;
+ if ((fmt[i + j] == 's')) {
+ if (star)
+ arg++;
+ if (WARN_ONCE(arg == 63,
+ "Too many args for event: %s",
+ trace_event_name(call)))
+ return;
+ dereference_flags |= 1ULL << arg;
+ string_flags |= 1ULL << arg;
+ }
break;
}
break;
@@ -403,42 +537,47 @@ static void test_event_printk(struct trace_event_call *call)
case ',':
if (in_quote || parens)
continue;
+ e = i;
i++;
while (isspace(fmt[i]))
i++;
- start_arg = i;
- if (!(dereference_flags & (1ULL << arg)))
- goto next_arg;
- /* Find the REC-> in the argument */
- c = strchr(fmt + i, ',');
- r = strstr(fmt + i, "REC->");
- if (r && (!c || r < c)) {
- /*
- * Addresses of events on the buffer,
- * or an array on the buffer is
- * OK to dereference.
- * There's ways to fool this, but
- * this is to catch common mistakes,
- * not malicious code.
- */
- a = strchr(fmt + i, '&');
- if ((a && (a < r)) || test_field(r, call))
+ /*
+ * If start_arg is zero, then this is the start of the
+ * first argument. The processing of the argument happens
+ * when the end of the argument is found, as it needs to
+ * handle paranthesis and such.
+ */
+ if (!start_arg) {
+ start_arg = i;
+ /* Balance out the i++ in the for loop */
+ i--;
+ continue;
+ }
+
+ if (dereference_flags & (1ULL << arg)) {
+ if (string_flags & (1ULL << arg)) {
+ if (process_string(fmt + start_arg, e - start_arg, call))
+ dereference_flags &= ~(1ULL << arg);
+ } else if (process_pointer(fmt + start_arg, e - start_arg, call))
dereference_flags &= ~(1ULL << arg);
- } else if ((r = strstr(fmt + i, "__get_dynamic_array(")) &&
- (!c || r < c)) {
- dereference_flags &= ~(1ULL << arg);
- } else if ((r = strstr(fmt + i, "__get_sockaddr(")) &&
- (!c || r < c)) {
- dereference_flags &= ~(1ULL << arg);
}
- next_arg:
- i--;
+ start_arg = i;
arg++;
+ /* Balance out the i++ in the for loop */
+ i--;
}
}
+ if (dereference_flags & (1ULL << arg)) {
+ if (string_flags & (1ULL << arg)) {
+ if (process_string(fmt + start_arg, i - start_arg, call))
+ dereference_flags &= ~(1ULL << arg);
+ } else if (process_pointer(fmt + start_arg, i - start_arg, call))
+ dereference_flags &= ~(1ULL << arg);
+ }
+
/*
* If you triggered the below warning, the trace event reported
* uses an unsafe dereference pointer %p*. As the data stored
@@ -2471,7 +2610,7 @@ event_define_fields(struct trace_event_call *call)
ret = trace_define_field_ext(call, field->type, field->name,
offset, field->size,
field->is_signed, field->filter_type,
- field->len);
+ field->len, field->needs_test);
if (WARN_ON_ONCE(ret)) {
pr_err("error code is %d\n", ret);
break;
diff --git a/kernel/trace/trace_functions.c b/kernel/trace/trace_functions.c
index 74c353164ca1..d358c9935164 100644
--- a/kernel/trace/trace_functions.c
+++ b/kernel/trace/trace_functions.c
@@ -176,7 +176,8 @@ static void function_trace_start(struct trace_array *tr)
tracing_reset_online_cpus(&tr->array_buffer);
}
-#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+/* fregs are guaranteed not to be NULL if HAVE_DYNAMIC_FTRACE_WITH_ARGS is set */
+#if defined(CONFIG_FUNCTION_GRAPH_TRACER) && defined(CONFIG_HAVE_DYNAMIC_FTRACE_WITH_ARGS)
static __always_inline unsigned long
function_get_true_parent_ip(unsigned long parent_ip, struct ftrace_regs *fregs)
{
diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c
index 263fac44d3ca..935a886af40c 100644
--- a/kernel/trace/trace_kprobe.c
+++ b/kernel/trace/trace_kprobe.c
@@ -725,7 +725,7 @@ static int trace_kprobe_module_callback(struct notifier_block *nb,
static struct notifier_block trace_kprobe_module_nb = {
.notifier_call = trace_kprobe_module_callback,
- .priority = 1 /* Invoked after kprobe module callback */
+ .priority = 2 /* Invoked after kprobe and jump_label module callback */
};
static int trace_kprobe_register_module_notifier(void)
{
diff --git a/kernel/trace/trace_output.c b/kernel/trace/trace_output.c
index e08aee34ef63..03d56f711ad1 100644
--- a/kernel/trace/trace_output.c
+++ b/kernel/trace/trace_output.c
@@ -317,10 +317,14 @@ EXPORT_SYMBOL(trace_raw_output_prep);
void trace_event_printf(struct trace_iterator *iter, const char *fmt, ...)
{
+ struct trace_seq *s = &iter->seq;
va_list ap;
+ if (ignore_event(iter))
+ return;
+
va_start(ap, fmt);
- trace_check_vprintf(iter, trace_event_format(iter, fmt), ap);
+ trace_seq_vprintf(s, trace_event_format(iter, fmt), ap);
va_end(ap);
}
EXPORT_SYMBOL(trace_event_printf);
@@ -462,17 +466,29 @@ int trace_print_lat_fmt(struct trace_seq *s, struct trace_entry *entry)
bh_off ? 'b' :
'.';
- switch (entry->flags & (TRACE_FLAG_NEED_RESCHED |
+ switch (entry->flags & (TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY |
TRACE_FLAG_PREEMPT_RESCHED)) {
+ case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED:
+ need_resched = 'B';
+ break;
case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_PREEMPT_RESCHED:
need_resched = 'N';
break;
+ case TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED:
+ need_resched = 'L';
+ break;
+ case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY:
+ need_resched = 'b';
+ break;
case TRACE_FLAG_NEED_RESCHED:
need_resched = 'n';
break;
case TRACE_FLAG_PREEMPT_RESCHED:
need_resched = 'p';
break;
+ case TRACE_FLAG_NEED_RESCHED_LAZY:
+ need_resched = 'l';
+ break;
default:
need_resched = '.';
break;
diff --git a/kernel/trace/trace_preemptirq.c b/kernel/trace/trace_preemptirq.c
index 5c03633316a6..0c42b15c3800 100644
--- a/kernel/trace/trace_preemptirq.c
+++ b/kernel/trace/trace_preemptirq.c
@@ -10,11 +10,42 @@
#include <linux/module.h>
#include <linux/ftrace.h>
#include <linux/kprobes.h>
+#include <linux/hardirq.h>
#include "trace.h"
#define CREATE_TRACE_POINTS
#include <trace/events/preemptirq.h>
+/*
+ * Use regular trace points on architectures that implement noinstr
+ * tooling: these calls will only happen with RCU enabled, which can
+ * use a regular tracepoint.
+ *
+ * On older architectures, RCU may not be watching in idle. In that
+ * case, wake up RCU to watch while calling the tracepoint. These
+ * aren't NMI-safe - so exclude NMI contexts:
+ */
+#ifdef CONFIG_ARCH_WANTS_NO_INSTR
+#define trace(point, args) trace_##point(args)
+#else
+#define trace(point, args) \
+ do { \
+ if (trace_##point##_enabled()) { \
+ bool exit_rcu = false; \
+ if (in_nmi()) \
+ break; \
+ if (!IS_ENABLED(CONFIG_TINY_RCU) && \
+ is_idle_task(current)) { \
+ ct_irq_enter(); \
+ exit_rcu = true; \
+ } \
+ trace_##point(args); \
+ if (exit_rcu) \
+ ct_irq_exit(); \
+ } \
+ } while (0)
+#endif
+
#ifdef CONFIG_TRACE_IRQFLAGS
/* Per-cpu variable to prevent redundant calls when IRQs already off */
static DEFINE_PER_CPU(int, tracing_irq_cpu);
@@ -28,7 +59,7 @@ static DEFINE_PER_CPU(int, tracing_irq_cpu);
void trace_hardirqs_on_prepare(void)
{
if (this_cpu_read(tracing_irq_cpu)) {
- trace_irq_enable(CALLER_ADDR0, CALLER_ADDR1);
+ trace(irq_enable, TP_ARGS(CALLER_ADDR0, CALLER_ADDR1));
tracer_hardirqs_on(CALLER_ADDR0, CALLER_ADDR1);
this_cpu_write(tracing_irq_cpu, 0);
}
@@ -39,7 +70,7 @@ NOKPROBE_SYMBOL(trace_hardirqs_on_prepare);
void trace_hardirqs_on(void)
{
if (this_cpu_read(tracing_irq_cpu)) {
- trace_irq_enable(CALLER_ADDR0, CALLER_ADDR1);
+ trace(irq_enable, TP_ARGS(CALLER_ADDR0, CALLER_ADDR1));
tracer_hardirqs_on(CALLER_ADDR0, CALLER_ADDR1);
this_cpu_write(tracing_irq_cpu, 0);
}
@@ -61,7 +92,7 @@ void trace_hardirqs_off_finish(void)
if (!this_cpu_read(tracing_irq_cpu)) {
this_cpu_write(tracing_irq_cpu, 1);
tracer_hardirqs_off(CALLER_ADDR0, CALLER_ADDR1);
- trace_irq_disable(CALLER_ADDR0, CALLER_ADDR1);
+ trace(irq_disable, TP_ARGS(CALLER_ADDR0, CALLER_ADDR1));
}
}
@@ -75,7 +106,7 @@ void trace_hardirqs_off(void)
if (!this_cpu_read(tracing_irq_cpu)) {
this_cpu_write(tracing_irq_cpu, 1);
tracer_hardirqs_off(CALLER_ADDR0, CALLER_ADDR1);
- trace_irq_disable(CALLER_ADDR0, CALLER_ADDR1);
+ trace(irq_disable, TP_ARGS(CALLER_ADDR0, CALLER_ADDR1));
}
}
EXPORT_SYMBOL(trace_hardirqs_off);
@@ -86,13 +117,13 @@ NOKPROBE_SYMBOL(trace_hardirqs_off);
void trace_preempt_on(unsigned long a0, unsigned long a1)
{
- trace_preempt_enable(a0, a1);
+ trace(preempt_enable, TP_ARGS(a0, a1));
tracer_preempt_on(a0, a1);
}
void trace_preempt_off(unsigned long a0, unsigned long a1)
{
- trace_preempt_disable(a0, a1);
+ trace(preempt_disable, TP_ARGS(a0, a1));
tracer_preempt_off(a0, a1);
}
#endif
diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index fed382b7881b..4875e7f5de3d 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -1402,9 +1402,13 @@ static void __uprobe_perf_func(struct trace_uprobe *tu,
#ifdef CONFIG_BPF_EVENTS
if (bpf_prog_array_valid(call)) {
+ const struct bpf_prog_array *array;
u32 ret;
- ret = bpf_prog_run_array_uprobe(call->prog_array, regs, bpf_prog_run);
+ rcu_read_lock_trace();
+ array = rcu_dereference_check(call->prog_array, rcu_read_lock_trace_held());
+ ret = bpf_prog_run_array_uprobe(array, regs, bpf_prog_run);
+ rcu_read_unlock_trace();
if (!ret)
return;
}
diff --git a/kernel/trace/tracing_map.c b/kernel/trace/tracing_map.c
index 3a56e7c8aa4f..1921ade45be3 100644
--- a/kernel/trace/tracing_map.c
+++ b/kernel/trace/tracing_map.c
@@ -845,15 +845,11 @@ int tracing_map_init(struct tracing_map *map)
static int cmp_entries_dup(const void *A, const void *B)
{
const struct tracing_map_sort_entry *a, *b;
- int ret = 0;
a = *(const struct tracing_map_sort_entry **)A;
b = *(const struct tracing_map_sort_entry **)B;
- if (memcmp(a->key, b->key, a->elt->map->key_size))
- ret = 1;
-
- return ret;
+ return memcmp(a->key, b->key, a->elt->map->key_size);
}
static int cmp_entries_sum(const void *A, const void *B)
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index 8b07576814a5..f7d8fc204579 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -3680,23 +3680,27 @@ void workqueue_softirq_dead(unsigned int cpu)
* check_flush_dependency - check for flush dependency sanity
* @target_wq: workqueue being flushed
* @target_work: work item being flushed (NULL for workqueue flushes)
+ * @from_cancel: are we called from the work cancel path
*
* %current is trying to flush the whole @target_wq or @target_work on it.
- * If @target_wq doesn't have %WQ_MEM_RECLAIM, verify that %current is not
- * reclaiming memory or running on a workqueue which doesn't have
- * %WQ_MEM_RECLAIM as that can break forward-progress guarantee leading to
- * a deadlock.
+ * If this is not the cancel path (which implies work being flushed is either
+ * already running, or will not be at all), check if @target_wq doesn't have
+ * %WQ_MEM_RECLAIM and verify that %current is not reclaiming memory or running
+ * on a workqueue which doesn't have %WQ_MEM_RECLAIM as that can break forward-
+ * progress guarantee leading to a deadlock.
*/
static void check_flush_dependency(struct workqueue_struct *target_wq,
- struct work_struct *target_work)
+ struct work_struct *target_work,
+ bool from_cancel)
{
- work_func_t target_func = target_work ? target_work->func : NULL;
+ work_func_t target_func;
struct worker *worker;
- if (target_wq->flags & WQ_MEM_RECLAIM)
+ if (from_cancel || target_wq->flags & WQ_MEM_RECLAIM)
return;
worker = current_wq_worker();
+ target_func = target_work ? target_work->func : NULL;
WARN_ONCE(current->flags & PF_MEMALLOC,
"workqueue: PF_MEMALLOC task %d(%s) is flushing !WQ_MEM_RECLAIM %s:%ps",
@@ -3980,7 +3984,7 @@ void __flush_workqueue(struct workqueue_struct *wq)
list_add_tail(&this_flusher.list, &wq->flusher_overflow);
}
- check_flush_dependency(wq, NULL);
+ check_flush_dependency(wq, NULL, false);
mutex_unlock(&wq->mutex);
@@ -4155,7 +4159,7 @@ static bool start_flush_work(struct work_struct *work, struct wq_barrier *barr,
}
wq = pwq->wq;
- check_flush_dependency(wq, work);
+ check_flush_dependency(wq, work, from_cancel);
insert_wq_barrier(pwq, barr, work, worker);
raw_spin_unlock_irq(&pool->lock);
@@ -5641,6 +5645,7 @@ static void wq_adjust_max_active(struct workqueue_struct *wq)
} while (activated);
}
+__printf(1, 0)
static struct workqueue_struct *__alloc_workqueue(const char *fmt,
unsigned int flags,
int max_active, va_list args)
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index f340017585c5..f3d723705879 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -3003,9 +3003,39 @@ config TEST_KALLSYMS_D
tristate
depends on m
+choice
+ prompt "Kallsym test range"
+ default TEST_KALLSYMS_LARGE
+ help
+ Selecting something other than "Fast" will enable tests which slow
+ down the build and may crash your build.
+
+config TEST_KALLSYMS_FAST
+ bool "Fast builds"
+ help
+ You won't really be testing kallsysms, so this just helps fast builds
+ when allmodconfig is used..
+
+config TEST_KALLSYMS_LARGE
+ bool "Enable testing kallsyms with large exports"
+ help
+ This will enable larger number of symbols. This will slow down
+ your build considerably.
+
+config TEST_KALLSYMS_MAX
+ bool "Known kallsysms limits"
+ help
+ This will enable exports to the point we know we'll start crashing
+ builds.
+
+endchoice
+
config TEST_KALLSYMS_NUMSYMS
int "test kallsyms number of symbols"
- default 100
+ range 2 10000
+ default 2 if TEST_KALLSYMS_FAST
+ default 100 if TEST_KALLSYMS_LARGE
+ default 10000 if TEST_KALLSYMS_MAX
help
The number of symbols to create on TEST_KALLSYMS_A, only one of which
module TEST_KALLSYMS_B will use. This also will be used
diff --git a/lib/alloc_tag.c b/lib/alloc_tag.c
index 2414a7ee7ec7..7dcebf118a3e 100644
--- a/lib/alloc_tag.c
+++ b/lib/alloc_tag.c
@@ -189,26 +189,41 @@ void pgalloc_tag_split(struct folio *folio, int old_order, int new_order)
}
}
-void pgalloc_tag_copy(struct folio *new, struct folio *old)
+void pgalloc_tag_swap(struct folio *new, struct folio *old)
{
- union pgtag_ref_handle handle;
- union codetag_ref ref;
- struct alloc_tag *tag;
+ union pgtag_ref_handle handle_old, handle_new;
+ union codetag_ref ref_old, ref_new;
+ struct alloc_tag *tag_old, *tag_new;
- tag = pgalloc_tag_get(&old->page);
- if (!tag)
+ tag_old = pgalloc_tag_get(&old->page);
+ if (!tag_old)
+ return;
+ tag_new = pgalloc_tag_get(&new->page);
+ if (!tag_new)
return;
- if (!get_page_tag_ref(&new->page, &ref, &handle))
+ if (!get_page_tag_ref(&old->page, &ref_old, &handle_old))
+ return;
+ if (!get_page_tag_ref(&new->page, &ref_new, &handle_new)) {
+ put_page_tag_ref(handle_old);
return;
+ }
+
+ /*
+ * Clear tag references to avoid debug warning when using
+ * __alloc_tag_ref_set() with non-empty reference.
+ */
+ set_codetag_empty(&ref_old);
+ set_codetag_empty(&ref_new);
+
+ /* swap tags */
+ __alloc_tag_ref_set(&ref_old, tag_new);
+ update_page_tag_ref(handle_old, &ref_old);
+ __alloc_tag_ref_set(&ref_new, tag_old);
+ update_page_tag_ref(handle_new, &ref_new);
- /* Clear the old ref to the original allocation tag. */
- clear_page_tag_ref(&old->page);
- /* Decrement the counters of the tag on get_new_folio. */
- alloc_tag_sub(&ref, folio_size(new));
- __alloc_tag_ref_set(&ref, tag);
- update_page_tag_ref(handle, &ref);
- put_page_tag_ref(handle);
+ put_page_tag_ref(handle_old);
+ put_page_tag_ref(handle_new);
}
static void shutdown_mem_profiling(bool remove_file)
@@ -393,28 +408,52 @@ repeat:
static int vm_module_tags_populate(void)
{
- unsigned long phys_size = vm_module_tags->nr_pages << PAGE_SHIFT;
+ unsigned long phys_end = ALIGN_DOWN(module_tags.start_addr, PAGE_SIZE) +
+ (vm_module_tags->nr_pages << PAGE_SHIFT);
+ unsigned long new_end = module_tags.start_addr + module_tags.size;
- if (phys_size < module_tags.size) {
+ if (phys_end < new_end) {
struct page **next_page = vm_module_tags->pages + vm_module_tags->nr_pages;
- unsigned long addr = module_tags.start_addr + phys_size;
+ unsigned long old_shadow_end = ALIGN(phys_end, MODULE_ALIGN);
+ unsigned long new_shadow_end = ALIGN(new_end, MODULE_ALIGN);
unsigned long more_pages;
unsigned long nr;
- more_pages = ALIGN(module_tags.size - phys_size, PAGE_SIZE) >> PAGE_SHIFT;
+ more_pages = ALIGN(new_end - phys_end, PAGE_SIZE) >> PAGE_SHIFT;
nr = alloc_pages_bulk_array_node(GFP_KERNEL | __GFP_NOWARN,
NUMA_NO_NODE, more_pages, next_page);
if (nr < more_pages ||
- vmap_pages_range(addr, addr + (nr << PAGE_SHIFT), PAGE_KERNEL,
+ vmap_pages_range(phys_end, phys_end + (nr << PAGE_SHIFT), PAGE_KERNEL,
next_page, PAGE_SHIFT) < 0) {
/* Clean up and error out */
for (int i = 0; i < nr; i++)
__free_page(next_page[i]);
return -ENOMEM;
}
+
vm_module_tags->nr_pages += nr;
+
+ /*
+ * Kasan allocates 1 byte of shadow for every 8 bytes of data.
+ * When kasan_alloc_module_shadow allocates shadow memory,
+ * its unit of allocation is a page.
+ * Therefore, here we need to align to MODULE_ALIGN.
+ */
+ if (old_shadow_end < new_shadow_end)
+ kasan_alloc_module_shadow((void *)old_shadow_end,
+ new_shadow_end - old_shadow_end,
+ GFP_KERNEL);
}
+ /*
+ * Mark the pages as accessible, now that they are mapped.
+ * With hardware tag-based KASAN, marking is skipped for
+ * non-VM_ALLOC mappings, see __kasan_unpoison_vmalloc().
+ */
+ kasan_unpoison_vmalloc((void *)module_tags.start_addr,
+ new_end - module_tags.start_addr,
+ KASAN_VMALLOC_PROT_NORMAL);
+
return 0;
}
diff --git a/lib/devres.c b/lib/devres.c
index 4fc152de6d8b..73901160197e 100644
--- a/lib/devres.c
+++ b/lib/devres.c
@@ -115,9 +115,8 @@ EXPORT_SYMBOL(devm_ioremap_wc);
*/
void devm_iounmap(struct device *dev, void __iomem *addr)
{
- WARN_ON(devres_destroy(dev, devm_ioremap_release, devm_ioremap_match,
+ WARN_ON(devres_release(dev, devm_ioremap_release, devm_ioremap_match,
(__force void *)addr));
- iounmap(addr);
}
EXPORT_SYMBOL(devm_iounmap);
@@ -308,8 +307,7 @@ EXPORT_SYMBOL(devm_ioport_map);
*/
void devm_ioport_unmap(struct device *dev, void __iomem *addr)
{
- ioport_unmap(addr);
- WARN_ON(devres_destroy(dev, devm_ioport_map_release,
+ WARN_ON(devres_release(dev, devm_ioport_map_release,
devm_ioport_map_match, (__force void *)addr));
}
EXPORT_SYMBOL(devm_ioport_unmap);
diff --git a/lib/kunit/user_alloc.c b/lib/kunit/user_alloc.c
index ae935df09a5e..46951be018be 100644
--- a/lib/kunit/user_alloc.c
+++ b/lib/kunit/user_alloc.c
@@ -114,4 +114,4 @@ unsigned long kunit_vm_mmap(struct kunit *test, struct file *file,
}
EXPORT_SYMBOL_GPL(kunit_vm_mmap);
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
diff --git a/lib/locking-selftest.c b/lib/locking-selftest.c
index 6e0c019f71b6..ed99344317f5 100644
--- a/lib/locking-selftest.c
+++ b/lib/locking-selftest.c
@@ -1720,8 +1720,6 @@ static void ww_test_normal(void)
{
int ret;
- WWAI(&t);
-
/*
* None of the ww_mutex codepaths should be taken in the 'normal'
* mutex calls. The easiest way to verify this is by using the
@@ -1770,6 +1768,8 @@ static void ww_test_normal(void)
ww_mutex_base_unlock(&o.base);
WARN_ON(o.ctx != (void *)~0UL);
+ WWAI(&t);
+
/* nest_lock */
o.ctx = (void *)~0UL;
ww_mutex_base_lock_nest_lock(&o.base, &t);
diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index d0ae808f3a14..047397136f15 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -4354,6 +4354,7 @@ int mas_alloc_cyclic(struct ma_state *mas, unsigned long *startp,
ret = 1;
}
if (ret < 0 && range_lo > min) {
+ mas_reset(mas);
ret = mas_empty_area(mas, min, range_hi, 1);
if (ret == 0)
ret = 1;
diff --git a/lib/packing.c b/lib/packing.c
index 793942745e34..bb1643d9e64d 100644
--- a/lib/packing.c
+++ b/lib/packing.c
@@ -5,10 +5,37 @@
#include <linux/packing.h>
#include <linux/module.h>
#include <linux/bitops.h>
+#include <linux/bits.h>
#include <linux/errno.h>
#include <linux/types.h>
#include <linux/bitrev.h>
+#define __pack_fields(pbuf, pbuflen, ustruct, fields, num_fields, quirks) \
+ ({ \
+ for (size_t i = 0; i < (num_fields); i++) { \
+ typeof(&(fields)[0]) field = &(fields)[i]; \
+ u64 uval; \
+ \
+ uval = ustruct_field_to_u64(ustruct, field->offset, field->size); \
+ \
+ __pack(pbuf, uval, field->startbit, field->endbit, \
+ pbuflen, quirks); \
+ } \
+ })
+
+#define __unpack_fields(pbuf, pbuflen, ustruct, fields, num_fields, quirks) \
+ ({ \
+ for (size_t i = 0; i < (num_fields); i++) { \
+ typeof(&(fields)[0]) field = &fields[i]; \
+ u64 uval; \
+ \
+ __unpack(pbuf, &uval, field->startbit, field->endbit, \
+ pbuflen, quirks); \
+ \
+ u64_to_ustruct_field(ustruct, field->offset, field->size, uval); \
+ } \
+ })
+
/**
* calculate_box_addr - Determine physical location of byte in buffer
* @box: Index of byte within buffer seen as a logical big-endian big number
@@ -51,64 +78,29 @@ static size_t calculate_box_addr(size_t box, size_t len, u8 quirks)
return offset_of_group + offset_in_group;
}
-/**
- * pack - Pack u64 number into bitfield of buffer.
- *
- * @pbuf: Pointer to a buffer holding the packed value.
- * @uval: CPU-readable unpacked value to pack.
- * @startbit: The index (in logical notation, compensated for quirks) where
- * the packed value starts within pbuf. Must be larger than, or
- * equal to, endbit.
- * @endbit: The index (in logical notation, compensated for quirks) where
- * the packed value ends within pbuf. Must be smaller than, or equal
- * to, startbit.
- * @pbuflen: The length in bytes of the packed buffer pointed to by @pbuf.
- * @quirks: A bit mask of QUIRK_LITTLE_ENDIAN, QUIRK_LSW32_IS_FIRST and
- * QUIRK_MSB_ON_THE_RIGHT.
- *
- * Return: 0 on success, EINVAL or ERANGE if called incorrectly. Assuming
- * correct usage, return code may be discarded. The @pbuf memory will
- * be modified on success.
- */
-int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen,
- u8 quirks)
+static void __pack(void *pbuf, u64 uval, size_t startbit, size_t endbit,
+ size_t pbuflen, u8 quirks)
{
/* Logical byte indices corresponding to the
* start and end of the field.
*/
- int plogical_first_u8, plogical_last_u8, box;
- /* width of the field to access in the pbuf */
- u64 value_width;
-
- /* startbit is expected to be larger than endbit, and both are
- * expected to be within the logically addressable range of the buffer.
- */
- if (unlikely(startbit < endbit || startbit >= BITS_PER_BYTE * pbuflen))
- /* Invalid function call */
- return -EINVAL;
-
- value_width = startbit - endbit + 1;
- if (unlikely(value_width > 64))
- return -ERANGE;
+ int plogical_first_u8 = startbit / BITS_PER_BYTE;
+ int plogical_last_u8 = endbit / BITS_PER_BYTE;
+ int value_width = startbit - endbit + 1;
+ int box;
/* Check if "uval" fits in "value_width" bits.
- * If value_width is 64, the check will fail, but any
- * 64-bit uval will surely fit.
+ * The test only works for value_width < 64, but in the latter case,
+ * any 64-bit uval will surely fit.
*/
- if (unlikely(value_width < 64 && uval >= (1ull << value_width)))
- /* Cannot store "uval" inside "value_width" bits.
- * Truncating "uval" is most certainly not desirable,
- * so simply erroring out is appropriate.
- */
- return -ERANGE;
+ WARN(value_width < 64 && uval >= (1ull << value_width),
+ "Cannot store 0x%llx inside bits %zu-%zu - will truncate\n",
+ uval, startbit, endbit);
/* Iterate through an idealistic view of the pbuf as an u64 with
* no quirks, u8 by u8 (aligned at u8 boundaries), from high to low
* logical bit significance. "box" denotes the current logical u8.
*/
- plogical_first_u8 = startbit / BITS_PER_BYTE;
- plogical_last_u8 = endbit / BITS_PER_BYTE;
-
for (box = plogical_first_u8; box >= plogical_last_u8; box--) {
/* Bit indices into the currently accessed 8-bit box */
size_t box_start_bit, box_end_bit, box_addr;
@@ -163,15 +155,13 @@ int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen,
((u8 *)pbuf)[box_addr] &= ~box_mask;
((u8 *)pbuf)[box_addr] |= pval;
}
- return 0;
}
-EXPORT_SYMBOL(pack);
/**
- * unpack - Unpack u64 number from packed buffer.
+ * pack - Pack u64 number into bitfield of buffer.
*
* @pbuf: Pointer to a buffer holding the packed value.
- * @uval: Pointer to an u64 holding the unpacked value.
+ * @uval: CPU-readable unpacked value to pack.
* @startbit: The index (in logical notation, compensated for quirks) where
* the packed value starts within pbuf. Must be larger than, or
* equal to, endbit.
@@ -183,19 +173,12 @@ EXPORT_SYMBOL(pack);
* QUIRK_MSB_ON_THE_RIGHT.
*
* Return: 0 on success, EINVAL or ERANGE if called incorrectly. Assuming
- * correct usage, return code may be discarded. The @uval will be
- * modified on success.
+ * correct usage, return code may be discarded. The @pbuf memory will
+ * be modified on success.
*/
-int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
- size_t pbuflen, u8 quirks)
+int pack(void *pbuf, u64 uval, size_t startbit, size_t endbit, size_t pbuflen,
+ u8 quirks)
{
- /* Logical byte indices corresponding to the
- * start and end of the field.
- */
- int plogical_first_u8, plogical_last_u8, box;
- /* width of the field to access in the pbuf */
- u64 value_width;
-
/* startbit is expected to be larger than endbit, and both are
* expected to be within the logically addressable range of the buffer.
*/
@@ -203,10 +186,25 @@ int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
/* Invalid function call */
return -EINVAL;
- value_width = startbit - endbit + 1;
- if (unlikely(value_width > 64))
+ if (unlikely(startbit - endbit >= 64))
return -ERANGE;
+ __pack(pbuf, uval, startbit, endbit, pbuflen, quirks);
+
+ return 0;
+}
+EXPORT_SYMBOL(pack);
+
+static void __unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
+ size_t pbuflen, u8 quirks)
+{
+ /* Logical byte indices corresponding to the
+ * start and end of the field.
+ */
+ int plogical_first_u8 = startbit / BITS_PER_BYTE;
+ int plogical_last_u8 = endbit / BITS_PER_BYTE;
+ int box;
+
/* Initialize parameter */
*uval = 0;
@@ -214,9 +212,6 @@ int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
* no quirks, u8 by u8 (aligned at u8 boundaries), from high to low
* logical bit significance. "box" denotes the current logical u8.
*/
- plogical_first_u8 = startbit / BITS_PER_BYTE;
- plogical_last_u8 = endbit / BITS_PER_BYTE;
-
for (box = plogical_first_u8; box >= plogical_last_u8; box--) {
/* Bit indices into the currently accessed 8-bit box */
size_t box_start_bit, box_end_bit, box_addr;
@@ -271,6 +266,46 @@ int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
*uval &= ~proj_mask;
*uval |= pval;
}
+}
+
+/**
+ * unpack - Unpack u64 number from packed buffer.
+ *
+ * @pbuf: Pointer to a buffer holding the packed value.
+ * @uval: Pointer to an u64 holding the unpacked value.
+ * @startbit: The index (in logical notation, compensated for quirks) where
+ * the packed value starts within pbuf. Must be larger than, or
+ * equal to, endbit.
+ * @endbit: The index (in logical notation, compensated for quirks) where
+ * the packed value ends within pbuf. Must be smaller than, or equal
+ * to, startbit.
+ * @pbuflen: The length in bytes of the packed buffer pointed to by @pbuf.
+ * @quirks: A bit mask of QUIRK_LITTLE_ENDIAN, QUIRK_LSW32_IS_FIRST and
+ * QUIRK_MSB_ON_THE_RIGHT.
+ *
+ * Return: 0 on success, EINVAL or ERANGE if called incorrectly. Assuming
+ * correct usage, return code may be discarded. The @uval will be
+ * modified on success.
+ */
+int unpack(const void *pbuf, u64 *uval, size_t startbit, size_t endbit,
+ size_t pbuflen, u8 quirks)
+{
+ /* width of the field to access in the pbuf */
+ u64 value_width;
+
+ /* startbit is expected to be larger than endbit, and both are
+ * expected to be within the logically addressable range of the buffer.
+ */
+ if (startbit < endbit || startbit >= BITS_PER_BYTE * pbuflen)
+ /* Invalid function call */
+ return -EINVAL;
+
+ value_width = startbit - endbit + 1;
+ if (value_width > 64)
+ return -ERANGE;
+
+ __unpack(pbuf, uval, startbit, endbit, pbuflen, quirks);
+
return 0;
}
EXPORT_SYMBOL(unpack);
@@ -314,4 +349,130 @@ int packing(void *pbuf, u64 *uval, int startbit, int endbit, size_t pbuflen,
}
EXPORT_SYMBOL(packing);
+static u64 ustruct_field_to_u64(const void *ustruct, size_t field_offset,
+ size_t field_size)
+{
+ switch (field_size) {
+ case 1:
+ return *((u8 *)(ustruct + field_offset));
+ case 2:
+ return *((u16 *)(ustruct + field_offset));
+ case 4:
+ return *((u32 *)(ustruct + field_offset));
+ default:
+ return *((u64 *)(ustruct + field_offset));
+ }
+}
+
+static void u64_to_ustruct_field(void *ustruct, size_t field_offset,
+ size_t field_size, u64 uval)
+{
+ switch (field_size) {
+ case 1:
+ *((u8 *)(ustruct + field_offset)) = uval;
+ break;
+ case 2:
+ *((u16 *)(ustruct + field_offset)) = uval;
+ break;
+ case 4:
+ *((u32 *)(ustruct + field_offset)) = uval;
+ break;
+ default:
+ *((u64 *)(ustruct + field_offset)) = uval;
+ break;
+ }
+}
+
+/**
+ * pack_fields_u8 - Pack array of fields
+ *
+ * @pbuf: Pointer to a buffer holding the packed value.
+ * @pbuflen: The length in bytes of the packed buffer pointed to by @pbuf.
+ * @ustruct: Pointer to CPU-readable structure holding the unpacked value.
+ * It is expected (but not checked) that this has the same data type
+ * as all struct packed_field_u8 definitions.
+ * @fields: Array of packed_field_u8 field definition. They must not overlap.
+ * @num_fields: Length of @fields array.
+ * @quirks: A bit mask of QUIRK_LITTLE_ENDIAN, QUIRK_LSW32_IS_FIRST and
+ * QUIRK_MSB_ON_THE_RIGHT.
+ *
+ * Use the pack_fields() macro instead of calling this directly.
+ */
+void pack_fields_u8(void *pbuf, size_t pbuflen, const void *ustruct,
+ const struct packed_field_u8 *fields, size_t num_fields,
+ u8 quirks)
+{
+ __pack_fields(pbuf, pbuflen, ustruct, fields, num_fields, quirks);
+}
+EXPORT_SYMBOL(pack_fields_u8);
+
+/**
+ * pack_fields_u16 - Pack array of fields
+ *
+ * @pbuf: Pointer to a buffer holding the packed value.
+ * @pbuflen: The length in bytes of the packed buffer pointed to by @pbuf.
+ * @ustruct: Pointer to CPU-readable structure holding the unpacked value.
+ * It is expected (but not checked) that this has the same data type
+ * as all struct packed_field_u16 definitions.
+ * @fields: Array of packed_field_u16 field definitions. They must not overlap.
+ * @num_fields: Length of @fields array.
+ * @quirks: A bit mask of QUIRK_LITTLE_ENDIAN, QUIRK_LSW32_IS_FIRST and
+ * QUIRK_MSB_ON_THE_RIGHT.
+ *
+ * Use the pack_fields() macro instead of calling this directly.
+ */
+void pack_fields_u16(void *pbuf, size_t pbuflen, const void *ustruct,
+ const struct packed_field_u16 *fields, size_t num_fields,
+ u8 quirks)
+{
+ __pack_fields(pbuf, pbuflen, ustruct, fields, num_fields, quirks);
+}
+EXPORT_SYMBOL(pack_fields_u16);
+
+/**
+ * unpack_fields_u8 - Unpack array of fields
+ *
+ * @pbuf: Pointer to a buffer holding the packed value.
+ * @pbuflen: The length in bytes of the packed buffer pointed to by @pbuf.
+ * @ustruct: Pointer to CPU-readable structure holding the unpacked value.
+ * It is expected (but not checked) that this has the same data type
+ * as all struct packed_field_u8 definitions.
+ * @fields: Array of packed_field_u8 field definitions. They must not overlap.
+ * @num_fields: Length of @fields array.
+ * @quirks: A bit mask of QUIRK_LITTLE_ENDIAN, QUIRK_LSW32_IS_FIRST and
+ * QUIRK_MSB_ON_THE_RIGHT.
+ *
+ * Use the unpack_fields() macro instead of calling this directly.
+ */
+void unpack_fields_u8(const void *pbuf, size_t pbuflen, void *ustruct,
+ const struct packed_field_u8 *fields, size_t num_fields,
+ u8 quirks)
+{
+ __unpack_fields(pbuf, pbuflen, ustruct, fields, num_fields, quirks);
+}
+EXPORT_SYMBOL(unpack_fields_u8);
+
+/**
+ * unpack_fields_u16 - Unpack array of fields
+ *
+ * @pbuf: Pointer to a buffer holding the packed value.
+ * @pbuflen: The length in bytes of the packed buffer pointed to by @pbuf.
+ * @ustruct: Pointer to CPU-readable structure holding the unpacked value.
+ * It is expected (but not checked) that this has the same data type
+ * as all struct packed_field_u16 definitions.
+ * @fields: Array of packed_field_u16 field definitions. They must not overlap.
+ * @num_fields: Length of @fields array.
+ * @quirks: A bit mask of QUIRK_LITTLE_ENDIAN, QUIRK_LSW32_IS_FIRST and
+ * QUIRK_MSB_ON_THE_RIGHT.
+ *
+ * Use the unpack_fields() macro instead of calling this directly.
+ */
+void unpack_fields_u16(const void *pbuf, size_t pbuflen, void *ustruct,
+ const struct packed_field_u16 *fields, size_t num_fields,
+ u8 quirks)
+{
+ __unpack_fields(pbuf, pbuflen, ustruct, fields, num_fields, quirks);
+}
+EXPORT_SYMBOL(unpack_fields_u16);
+
MODULE_DESCRIPTION("Generic bitfield packing and unpacking");
diff --git a/lib/packing_test.c b/lib/packing_test.c
index b38ea43c03fd..ce3b83d33b04 100644
--- a/lib/packing_test.c
+++ b/lib/packing_test.c
@@ -396,9 +396,70 @@ static void packing_test_unpack(struct kunit *test)
KUNIT_EXPECT_EQ(test, uval, params->uval);
}
+#define PACKED_BUF_SIZE 8
+
+typedef struct __packed { u8 buf[PACKED_BUF_SIZE]; } packed_buf_t;
+
+struct test_data {
+ u32 field3;
+ u16 field2;
+ u16 field4;
+ u16 field6;
+ u8 field1;
+ u8 field5;
+};
+
+static const struct packed_field_u8 test_fields[] = {
+ PACKED_FIELD(63, 61, struct test_data, field1),
+ PACKED_FIELD(60, 52, struct test_data, field2),
+ PACKED_FIELD(51, 28, struct test_data, field3),
+ PACKED_FIELD(27, 14, struct test_data, field4),
+ PACKED_FIELD(13, 9, struct test_data, field5),
+ PACKED_FIELD(8, 0, struct test_data, field6),
+};
+
+static void packing_test_pack_fields(struct kunit *test)
+{
+ const struct test_data data = {
+ .field1 = 0x2,
+ .field2 = 0x100,
+ .field3 = 0xF00050,
+ .field4 = 0x7D3,
+ .field5 = 0x9,
+ .field6 = 0x10B,
+ };
+ packed_buf_t expect = {
+ .buf = { 0x50, 0x0F, 0x00, 0x05, 0x01, 0xF4, 0xD3, 0x0B },
+ };
+ packed_buf_t buf = {};
+
+ pack_fields(&buf, sizeof(buf), &data, test_fields, 0);
+
+ KUNIT_EXPECT_MEMEQ(test, &expect, &buf, sizeof(buf));
+}
+
+static void packing_test_unpack_fields(struct kunit *test)
+{
+ const packed_buf_t buf = {
+ .buf = { 0x17, 0x28, 0x10, 0x19, 0x3D, 0xA9, 0x07, 0x9C },
+ };
+ struct test_data data = {};
+
+ unpack_fields(&buf, sizeof(buf), &data, test_fields, 0);
+
+ KUNIT_EXPECT_EQ(test, 0, data.field1);
+ KUNIT_EXPECT_EQ(test, 0x172, data.field2);
+ KUNIT_EXPECT_EQ(test, 0x810193, data.field3);
+ KUNIT_EXPECT_EQ(test, 0x36A4, data.field4);
+ KUNIT_EXPECT_EQ(test, 0x3, data.field5);
+ KUNIT_EXPECT_EQ(test, 0x19C, data.field6);
+}
+
static struct kunit_case packing_test_cases[] = {
KUNIT_CASE_PARAM(packing_test_pack, packing_gen_params),
KUNIT_CASE_PARAM(packing_test_unpack, packing_gen_params),
+ KUNIT_CASE(packing_test_pack_fields),
+ KUNIT_CASE(packing_test_unpack_fields),
{},
};
diff --git a/lib/stackdepot.c b/lib/stackdepot.c
index 5ed34cc963fc..245d5b416699 100644
--- a/lib/stackdepot.c
+++ b/lib/stackdepot.c
@@ -630,7 +630,15 @@ depot_stack_handle_t stack_depot_save_flags(unsigned long *entries,
prealloc = page_address(page);
}
- raw_spin_lock_irqsave(&pool_lock, flags);
+ if (in_nmi()) {
+ /* We can never allocate in NMI context. */
+ WARN_ON_ONCE(can_alloc);
+ /* Best effort; bail if we fail to take the lock. */
+ if (!raw_spin_trylock_irqsave(&pool_lock, flags))
+ goto exit;
+ } else {
+ raw_spin_lock_irqsave(&pool_lock, flags);
+ }
printk_deferred_enter();
/* Try to find again, to avoid concurrently inserting duplicates. */
diff --git a/lib/stackinit_kunit.c b/lib/stackinit_kunit.c
index c14c6f8e6308..c40818ec9c18 100644
--- a/lib/stackinit_kunit.c
+++ b/lib/stackinit_kunit.c
@@ -212,6 +212,7 @@ static noinline void test_ ## name (struct kunit *test) \
static noinline DO_NOTHING_TYPE_ ## which(var_type) \
do_nothing_ ## name(var_type *ptr) \
{ \
+ OPTIMIZER_HIDE_VAR(ptr); \
/* Will always be true, but compiler doesn't know. */ \
if ((unsigned long)ptr > 0x2) \
return DO_NOTHING_RETURN_ ## which(ptr); \
diff --git a/lib/string.c b/lib/string.c
index 76327b51e36f..eb4486ed40d2 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -104,6 +104,12 @@ char *strncpy(char *dest, const char *src, size_t count)
EXPORT_SYMBOL(strncpy);
#endif
+#ifdef __BIG_ENDIAN
+# define ALLBUTLAST_BYTE_MASK (~255ul)
+#else
+# define ALLBUTLAST_BYTE_MASK (~0ul >> 8)
+#endif
+
ssize_t sized_strscpy(char *dest, const char *src, size_t count)
{
const struct word_at_a_time constants = WORD_AT_A_TIME_CONSTANTS;
@@ -147,13 +153,18 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
*(unsigned long *)(dest+res) = c & zero_bytemask(data);
return res + find_zero(data);
}
+ count -= sizeof(unsigned long);
+ if (unlikely(!count)) {
+ c &= ALLBUTLAST_BYTE_MASK;
+ *(unsigned long *)(dest+res) = c;
+ return -E2BIG;
+ }
*(unsigned long *)(dest+res) = c;
res += sizeof(unsigned long);
- count -= sizeof(unsigned long);
max -= sizeof(unsigned long);
}
- while (count) {
+ while (count > 1) {
char c;
c = src[res];
@@ -164,11 +175,11 @@ ssize_t sized_strscpy(char *dest, const char *src, size_t count)
count--;
}
- /* Hit buffer length without finding a NUL; force NUL-termination. */
- if (res)
- dest[res-1] = '\0';
+ /* Force NUL-termination. */
+ dest[res] = '\0';
- return -E2BIG;
+ /* Return E2BIG if the source didn't stop */
+ return src[res] ? -E2BIG : res;
}
EXPORT_SYMBOL(sized_strscpy);
diff --git a/lib/test_firmware.c b/lib/test_firmware.c
index bcb32cbff188..211222e63328 100644
--- a/lib/test_firmware.c
+++ b/lib/test_firmware.c
@@ -27,7 +27,7 @@
#include <linux/vmalloc.h>
#include <linux/efi_embedded_fw.h>
-MODULE_IMPORT_NS(TEST_FIRMWARE);
+MODULE_IMPORT_NS("TEST_FIRMWARE");
#define TEST_FIRMWARE_NAME "test-firmware.bin"
#define TEST_FIRMWARE_NUM_REQS 4
diff --git a/lib/tests/module/Makefile b/lib/tests/module/Makefile
index af5c27b996cb..2f3e1a772c2c 100644
--- a/lib/tests/module/Makefile
+++ b/lib/tests/module/Makefile
@@ -3,13 +3,12 @@ obj-$(CONFIG_TEST_KALLSYMS_B) += test_kallsyms_b.o
obj-$(CONFIG_TEST_KALLSYMS_C) += test_kallsyms_c.o
obj-$(CONFIG_TEST_KALLSYMS_D) += test_kallsyms_d.o
-$(obj)/%.c: FORCE
- @$(kecho) " GEN $@"
- $(Q)$(srctree)/lib/tests/module/gen_test_kallsyms.sh $@\
- $(CONFIG_TEST_KALLSYMS_NUMSYMS) \
- $(CONFIG_TEST_KALLSYMS_SCALE_FACTOR)
+quiet_cmd_gen_test_kallsyms = GEN $@
+ cmd_gen_test_kallsyms = $< $@ \
+ $(CONFIG_TEST_KALLSYMS_NUMSYMS) \
+ $(CONFIG_TEST_KALLSYMS_SCALE_FACTOR)
-clean-files += test_kallsyms_a.c
-clean-files += test_kallsyms_b.c
-clean-files += test_kallsyms_c.c
-clean-files += test_kallsyms_d.c
+$(obj)/%.c: $(src)/gen_test_kallsyms.sh FORCE
+ $(call if_changed,gen_test_kallsyms)
+
+targets += $(foreach x, a b c d, test_kallsyms_$(x).c)
diff --git a/lib/tests/module/gen_test_kallsyms.sh b/lib/tests/module/gen_test_kallsyms.sh
index 3f2c626350ad..561dcac0f359 100755
--- a/lib/tests/module/gen_test_kallsyms.sh
+++ b/lib/tests/module/gen_test_kallsyms.sh
@@ -7,6 +7,11 @@ NUM_SYMS=$2
SCALE_FACTOR=$3
TEST_TYPE=$(echo $TARGET | sed -e 's|lib/tests/module/test_kallsyms_||g')
TEST_TYPE=$(echo $TEST_TYPE | sed -e 's|.c||g')
+FIRST_B_LOOKUP=1
+
+if [[ $NUM_SYMS -gt 2 ]]; then
+ FIRST_B_LOOKUP=$((NUM_SYMS/2))
+fi
gen_template_module_header()
{
@@ -52,10 +57,10 @@ ____END_MODULE
gen_template_module_data_b()
{
- printf "\nextern int auto_test_a_%010d;\n\n" 28
+ printf "\nextern int auto_test_a_%010d;\n\n" $FIRST_B_LOOKUP
echo "static int auto_runtime_test(void)"
echo "{"
- printf "\nreturn auto_test_a_%010d;\n" 28
+ printf "\nreturn auto_test_a_%010d;\n" $FIRST_B_LOOKUP
echo "}"
}
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 6ac02bbb7df1..9d3dac38a3f4 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -3428,29 +3428,6 @@ out:
}
EXPORT_SYMBOL_GPL(bstr_printf);
-/**
- * bprintf - Parse a format string and place args' binary value in a buffer
- * @bin_buf: The buffer to place args' binary value
- * @size: The size of the buffer(by words(32bits), not characters)
- * @fmt: The format string to use
- * @...: Arguments for the format string
- *
- * The function returns the number of words(u32) written
- * into @bin_buf.
- */
-int bprintf(u32 *bin_buf, size_t size, const char *fmt, ...)
-{
- va_list args;
- int ret;
-
- va_start(args, fmt);
- ret = vbin_printf(bin_buf, size, fmt, args);
- va_end(args);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(bprintf);
-
#endif /* CONFIG_BINARY_PRINTF */
/**
diff --git a/lib/win_minmax.c b/lib/win_minmax.c
index ec10506834b6..1682e614309c 100644
--- a/lib/win_minmax.c
+++ b/lib/win_minmax.c
@@ -97,3 +97,4 @@ u32 minmax_running_min(struct minmax *m, u32 win, u32 t, u32 meas)
return minmax_subwin_update(m, win, &val);
}
+EXPORT_SYMBOL(minmax_running_min);
diff --git a/mm/damon/core.c b/mm/damon/core.c
index 8b8e2933dcd4..0776452a1abb 100644
--- a/mm/damon/core.c
+++ b/mm/damon/core.c
@@ -868,6 +868,11 @@ static int damon_commit_schemes(struct damon_ctx *dst, struct damon_ctx *src)
NUMA_NO_NODE);
if (!new_scheme)
return -ENOMEM;
+ err = damos_commit(new_scheme, src_scheme);
+ if (err) {
+ damon_destroy_scheme(new_scheme);
+ return err;
+ }
damon_add_scheme(dst, new_scheme);
}
return 0;
@@ -961,8 +966,11 @@ static int damon_commit_targets(
return -ENOMEM;
err = damon_commit_target(new_target, false,
src_target, damon_target_has_pid(src));
- if (err)
+ if (err) {
+ damon_destroy_target(new_target);
return err;
+ }
+ damon_add_target(dst, new_target);
}
return 0;
}
diff --git a/mm/debug.c b/mm/debug.c
index aa57d3ffd4ed..95b6ab809c0e 100644
--- a/mm/debug.c
+++ b/mm/debug.c
@@ -124,19 +124,22 @@ static void __dump_page(const struct page *page)
{
struct folio *foliop, folio;
struct page precise;
+ unsigned long head;
unsigned long pfn = page_to_pfn(page);
unsigned long idx, nr_pages = 1;
int loops = 5;
again:
memcpy(&precise, page, sizeof(*page));
- foliop = page_folio(&precise);
- if (foliop == (struct folio *)&precise) {
+ head = precise.compound_head;
+ if ((head & 1) == 0) {
+ foliop = (struct folio *)&precise;
idx = 0;
if (!folio_test_large(foliop))
goto dump;
foliop = (struct folio *)page;
} else {
+ foliop = (struct folio *)(head - 1);
idx = folio_page_idx(foliop, page);
}
diff --git a/mm/filemap.c b/mm/filemap.c
index 7c76a123ba18..33b60d448fca 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -124,15 +124,6 @@
* ->private_lock (zap_pte_range->block_dirty_folio)
*/
-static void mapping_set_update(struct xa_state *xas,
- struct address_space *mapping)
-{
- if (dax_mapping(mapping) || shmem_mapping(mapping))
- return;
- xas_set_update(xas, workingset_update_node);
- xas_set_lru(xas, &shadow_nodes);
-}
-
static void page_cache_delete(struct address_space *mapping,
struct folio *folio, void *shadow)
{
@@ -3501,10 +3492,10 @@ static struct folio *next_uptodate_folio(struct xa_state *xas,
continue;
if (xa_is_value(folio))
continue;
- if (folio_test_locked(folio))
- continue;
if (!folio_try_get(folio))
continue;
+ if (folio_test_locked(folio))
+ goto skip;
/* Has the page moved or been split? */
if (unlikely(folio != xas_reload(xas)))
goto skip;
diff --git a/mm/gup.c b/mm/gup.c
index 746070a1d8bf..3b75e631f369 100644
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -52,7 +52,12 @@ static inline void sanity_check_pinned_pages(struct page **pages,
*/
for (; npages; npages--, pages++) {
struct page *page = *pages;
- struct folio *folio = page_folio(page);
+ struct folio *folio;
+
+ if (!page)
+ continue;
+
+ folio = page_folio(page);
if (is_zero_page(page) ||
!folio_test_anon(folio))
@@ -409,6 +414,10 @@ void unpin_user_pages(struct page **pages, unsigned long npages)
sanity_check_pinned_pages(pages, npages);
for (i = 0; i < npages; i += nr) {
+ if (!pages[i]) {
+ nr = 1;
+ continue;
+ }
folio = gup_folio_next(pages, npages, i, &nr);
gup_put_folio(folio, nr, FOLL_PIN);
}
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index ee335d96fc39..e53d83b3e5cf 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1176,11 +1176,12 @@ static struct folio *vma_alloc_anon_folio_pmd(struct vm_area_struct *vma,
folio_throttle_swaprate(folio, gfp);
/*
- * When a folio is not zeroed during allocation (__GFP_ZERO not used),
- * folio_zero_user() is used to make sure that the page corresponding
- * to the faulting address will be hot in the cache after zeroing.
+ * When a folio is not zeroed during allocation (__GFP_ZERO not used)
+ * or user folios require special handling, folio_zero_user() is used to
+ * make sure that the page corresponding to the faulting address will be
+ * hot in the cache after zeroing.
*/
- if (!alloc_zeroed())
+ if (user_alloc_needs_zeroing())
folio_zero_user(folio, addr);
/*
* The memory barrier inside __folio_mark_uptodate makes sure that
@@ -3576,7 +3577,7 @@ int split_huge_page_to_list_to_order(struct page *page, struct list_head *list,
!list_empty(&folio->_deferred_list)) {
ds_queue->split_queue_len--;
if (folio_test_partially_mapped(folio)) {
- __folio_clear_partially_mapped(folio);
+ folio_clear_partially_mapped(folio);
mod_mthp_stat(folio_order(folio),
MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1);
}
@@ -3688,7 +3689,7 @@ bool __folio_unqueue_deferred_split(struct folio *folio)
if (!list_empty(&folio->_deferred_list)) {
ds_queue->split_queue_len--;
if (folio_test_partially_mapped(folio)) {
- __folio_clear_partially_mapped(folio);
+ folio_clear_partially_mapped(folio);
mod_mthp_stat(folio_order(folio),
MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1);
}
@@ -3732,7 +3733,7 @@ void deferred_split_folio(struct folio *folio, bool partially_mapped)
spin_lock_irqsave(&ds_queue->split_queue_lock, flags);
if (partially_mapped) {
if (!folio_test_partially_mapped(folio)) {
- __folio_set_partially_mapped(folio);
+ folio_set_partially_mapped(folio);
if (folio_test_pmd_mappable(folio))
count_vm_event(THP_DEFERRED_SPLIT_PAGE);
count_mthp_stat(folio_order(folio), MTHP_STAT_SPLIT_DEFERRED);
@@ -3825,7 +3826,7 @@ static unsigned long deferred_split_scan(struct shrinker *shrink,
} else {
/* We lost race with folio_put() */
if (folio_test_partially_mapped(folio)) {
- __folio_clear_partially_mapped(folio);
+ folio_clear_partially_mapped(folio);
mod_mthp_stat(folio_order(folio),
MTHP_STAT_NR_ANON_PARTIALLY_MAPPED, -1);
}
@@ -4168,7 +4169,7 @@ static ssize_t split_huge_pages_write(struct file *file, const char __user *buf,
size_t input_len = strlen(input_buf);
tok = strsep(&buf, ",");
- if (tok) {
+ if (tok && buf) {
strscpy(file_path, tok);
} else {
ret = -EINVAL;
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index ea2ed8e301ef..c498874a7170 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -5340,7 +5340,7 @@ again:
break;
}
ret = copy_user_large_folio(new_folio, pte_folio,
- ALIGN_DOWN(addr, sz), dst_vma);
+ addr, dst_vma);
folio_put(pte_folio);
if (ret) {
folio_put(new_folio);
@@ -6643,8 +6643,7 @@ int hugetlb_mfill_atomic_pte(pte_t *dst_pte,
*foliop = NULL;
goto out;
}
- ret = copy_user_large_folio(folio, *foliop,
- ALIGN_DOWN(dst_addr, size), dst_vma);
+ ret = copy_user_large_folio(folio, *foliop, dst_addr, dst_vma);
folio_put(*foliop);
*foliop = NULL;
if (ret) {
@@ -7212,7 +7211,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma,
spte = hugetlb_walk(svma, saddr,
vma_mmu_pagesize(svma));
if (spte) {
- get_page(virt_to_page(spte));
+ ptdesc_pmd_pts_inc(virt_to_ptdesc(spte));
break;
}
}
@@ -7227,7 +7226,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, struct vm_area_struct *vma,
(pmd_t *)((unsigned long)spte & PAGE_MASK));
mm_inc_nr_pmds(mm);
} else {
- put_page(virt_to_page(spte));
+ ptdesc_pmd_pts_dec(virt_to_ptdesc(spte));
}
spin_unlock(&mm->page_table_lock);
out:
@@ -7239,10 +7238,6 @@ out:
/*
* unmap huge page backed by shared pte.
*
- * Hugetlb pte page is ref counted at the time of mapping. If pte is shared
- * indicated by page_count > 1, unmap is achieved by clearing pud and
- * decrementing the ref count. If count == 1, the pte page is not shared.
- *
* Called with page table lock held.
*
* returns: 1 successfully unmapped a shared pte page
@@ -7251,18 +7246,20 @@ out:
int huge_pmd_unshare(struct mm_struct *mm, struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep)
{
+ unsigned long sz = huge_page_size(hstate_vma(vma));
pgd_t *pgd = pgd_offset(mm, addr);
p4d_t *p4d = p4d_offset(pgd, addr);
pud_t *pud = pud_offset(p4d, addr);
i_mmap_assert_write_locked(vma->vm_file->f_mapping);
hugetlb_vma_assert_locked(vma);
- BUG_ON(page_count(virt_to_page(ptep)) == 0);
- if (page_count(virt_to_page(ptep)) == 1)
+ if (sz != PMD_SIZE)
+ return 0;
+ if (!ptdesc_pmd_pts_count(virt_to_ptdesc(ptep)))
return 0;
pud_clear(pud);
- put_page(virt_to_page(ptep));
+ ptdesc_pmd_pts_dec(virt_to_ptdesc(ptep));
mm_dec_nr_pmds(mm);
return 1;
}
diff --git a/mm/internal.h b/mm/internal.h
index 5a7302baeed7..9826f7dce607 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -49,7 +49,7 @@ struct folio_batch;
* when we specify __GFP_NOWARN.
*/
#define WARN_ON_ONCE_GFP(cond, gfp) ({ \
- static bool __section(".data.once") __warned; \
+ static bool __section(".data..once") __warned; \
int __ret_warn_once = !!(cond); \
\
if (unlikely(!(gfp & __GFP_NOWARN) && __ret_warn_once && !__warned)) { \
@@ -1285,12 +1285,6 @@ void touch_pud(struct vm_area_struct *vma, unsigned long addr,
void touch_pmd(struct vm_area_struct *vma, unsigned long addr,
pmd_t *pmd, bool write);
-static inline bool alloc_zeroed(void)
-{
- return static_branch_maybe(CONFIG_INIT_ON_ALLOC_DEFAULT_ON,
- &init_on_alloc);
-}
-
/*
* Parses a string with mem suffixes into its order. Useful to parse kernel
* parameters.
@@ -1510,6 +1504,12 @@ static inline void shrinker_debugfs_remove(struct dentry *debugfs_entry,
/* Only track the nodes of mappings with shadow entries */
void workingset_update_node(struct xa_node *node);
extern struct list_lru shadow_nodes;
+#define mapping_set_update(xas, mapping) do { \
+ if (!dax_mapping(mapping) && !shmem_mapping(mapping)) { \
+ xas_set_update(xas, workingset_update_node); \
+ xas_set_lru(xas, &shadow_nodes); \
+ } \
+} while (0)
/* mremap.c */
unsigned long move_page_tables(struct vm_area_struct *vma,
diff --git a/mm/kasan/kasan_test_c.c b/mm/kasan/kasan_test_c.c
index e0ec5a6d15be..99d4ff0ed57a 100644
--- a/mm/kasan/kasan_test_c.c
+++ b/mm/kasan/kasan_test_c.c
@@ -33,7 +33,7 @@
#define OOB_TAG_OFF (IS_ENABLED(CONFIG_KASAN_GENERIC) ? 0 : KASAN_GRANULE_SIZE)
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static bool multishot;
diff --git a/mm/kasan/report.c b/mm/kasan/report.c
index 50fb19ad4388..3fe77a360f1c 100644
--- a/mm/kasan/report.c
+++ b/mm/kasan/report.c
@@ -201,7 +201,7 @@ static inline void fail_non_kasan_kunit_test(void) { }
#endif /* CONFIG_KUNIT */
-static DEFINE_SPINLOCK(report_lock);
+static DEFINE_RAW_SPINLOCK(report_lock);
static void start_report(unsigned long *flags, bool sync)
{
@@ -212,7 +212,7 @@ static void start_report(unsigned long *flags, bool sync)
lockdep_off();
/* Make sure we don't end up in loop. */
report_suppress_start();
- spin_lock_irqsave(&report_lock, *flags);
+ raw_spin_lock_irqsave(&report_lock, *flags);
pr_err("==================================================================\n");
}
@@ -222,7 +222,7 @@ static void end_report(unsigned long *flags, const void *addr, bool is_write)
trace_error_report_end(ERROR_DETECTOR_KASAN,
(unsigned long)addr);
pr_err("==================================================================\n");
- spin_unlock_irqrestore(&report_lock, *flags);
+ raw_spin_unlock_irqrestore(&report_lock, *flags);
if (!test_bit(KASAN_BIT_MULTI_SHOT, &kasan_flags))
check_panic_on_warn("KASAN");
switch (kasan_arg_fault) {
diff --git a/mm/khugepaged.c b/mm/khugepaged.c
index 6f8d46d107b4..653dbb1ff05c 100644
--- a/mm/khugepaged.c
+++ b/mm/khugepaged.c
@@ -19,6 +19,7 @@
#include <linux/rcupdate_wait.h>
#include <linux/swapops.h>
#include <linux/shmem_fs.h>
+#include <linux/dax.h>
#include <linux/ksm.h>
#include <asm/tlb.h>
@@ -1837,6 +1838,8 @@ static int collapse_file(struct mm_struct *mm, unsigned long addr,
if (result != SCAN_SUCCEED)
goto out;
+ mapping_set_update(&xas, mapping);
+
__folio_set_locked(new_folio);
if (is_shmem)
__folio_set_swapbacked(new_folio);
diff --git a/mm/kmemleak.c b/mm/kmemleak.c
index 2a945c07ae99..737af23f4f4e 100644
--- a/mm/kmemleak.c
+++ b/mm/kmemleak.c
@@ -373,7 +373,7 @@ static void print_unreferenced(struct seq_file *seq,
for (i = 0; i < nr_entries; i++) {
void *ptr = (void *)entries[i];
- warn_or_seq_printf(seq, " [<%pK>] %pS\n", ptr, ptr);
+ warn_or_seq_printf(seq, " %pS\n", ptr);
}
}
diff --git a/mm/list_lru.c b/mm/list_lru.c
index f93ada6a207b..7d69434c70e0 100644
--- a/mm/list_lru.c
+++ b/mm/list_lru.c
@@ -77,7 +77,6 @@ again:
spin_lock(&l->lock);
nr_items = READ_ONCE(l->nr_items);
if (likely(nr_items != LONG_MIN)) {
- WARN_ON(nr_items < 0);
rcu_read_unlock();
return l;
}
@@ -450,6 +449,7 @@ static void memcg_reparent_list_lru_one(struct list_lru *lru, int nid,
list_splice_init(&src->list, &dst->list);
if (src->nr_items) {
+ WARN_ON(src->nr_items < 0);
dst->nr_items += src->nr_items;
set_shrinker_bit(dst_memcg, nid, lru_shrinker_id(lru));
}
diff --git a/mm/memblock.c b/mm/memblock.c
index 0389ce5cd281..095c18b5c430 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -735,7 +735,7 @@ int __init_memblock memblock_add(phys_addr_t base, phys_addr_t size)
/**
* memblock_validate_numa_coverage - check if amount of memory with
* no node ID assigned is less than a threshold
- * @threshold_bytes: maximal number of pages that can have unassigned node
+ * @threshold_bytes: maximal memory size that can have unassigned node
* ID (in bytes).
*
* A buggy firmware may report memory that does not belong to any node.
@@ -755,7 +755,7 @@ bool __init_memblock memblock_validate_numa_coverage(unsigned long threshold_byt
nr_pages += end_pfn - start_pfn;
}
- if ((nr_pages << PAGE_SHIFT) >= threshold_bytes) {
+ if ((nr_pages << PAGE_SHIFT) > threshold_bytes) {
mem_size_mb = memblock_phys_mem_size() >> 20;
pr_err("NUMA: no nodes coverage for %luMB of %luMB RAM\n",
(nr_pages << PAGE_SHIFT) >> 20, mem_size_mb);
diff --git a/mm/memcontrol-v1.h b/mm/memcontrol-v1.h
index 0e3b82951d91..144d71b65907 100644
--- a/mm/memcontrol-v1.h
+++ b/mm/memcontrol-v1.h
@@ -38,7 +38,7 @@ void mem_cgroup_id_put_many(struct mem_cgroup *memcg, unsigned int n);
iter = mem_cgroup_iter(NULL, iter, NULL))
/* Whether legacy memory+swap accounting is active */
-static bool do_memsw_account(void)
+static inline bool do_memsw_account(void)
{
return !cgroup_subsys_on_dfl(memory_cgrp_subsys);
}
diff --git a/mm/memfd.c b/mm/memfd.c
index c17c3ea701a1..35a370d75c9a 100644
--- a/mm/memfd.c
+++ b/mm/memfd.c
@@ -170,7 +170,7 @@ static int memfd_wait_for_pins(struct address_space *mapping)
return error;
}
-static unsigned int *memfd_file_seals_ptr(struct file *file)
+unsigned int *memfd_file_seals_ptr(struct file *file)
{
if (shmem_file(file))
return &SHMEM_I(file_inode(file))->seals;
diff --git a/mm/memory.c b/mm/memory.c
index 75c2dfd04f72..398c031be9ba 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4733,12 +4733,12 @@ static struct folio *alloc_anon_folio(struct vm_fault *vmf)
folio_throttle_swaprate(folio, gfp);
/*
* When a folio is not zeroed during allocation
- * (__GFP_ZERO not used), folio_zero_user() is used
- * to make sure that the page corresponding to the
- * faulting address will be hot in the cache after
- * zeroing.
+ * (__GFP_ZERO not used) or user folios require special
+ * handling, folio_zero_user() is used to make sure
+ * that the page corresponding to the faulting address
+ * will be hot in the cache after zeroing.
*/
- if (!alloc_zeroed())
+ if (user_alloc_needs_zeroing())
folio_zero_user(folio, vmf->address);
return folio;
}
@@ -6815,9 +6815,10 @@ static inline int process_huge_page(
return 0;
}
-static void clear_gigantic_page(struct folio *folio, unsigned long addr,
+static void clear_gigantic_page(struct folio *folio, unsigned long addr_hint,
unsigned int nr_pages)
{
+ unsigned long addr = ALIGN_DOWN(addr_hint, folio_size(folio));
int i;
might_sleep();
@@ -6851,13 +6852,14 @@ void folio_zero_user(struct folio *folio, unsigned long addr_hint)
}
static int copy_user_gigantic_page(struct folio *dst, struct folio *src,
- unsigned long addr,
+ unsigned long addr_hint,
struct vm_area_struct *vma,
unsigned int nr_pages)
{
- int i;
+ unsigned long addr = ALIGN_DOWN(addr_hint, folio_size(dst));
struct page *dst_page;
struct page *src_page;
+ int i;
for (i = 0; i < nr_pages; i++) {
dst_page = folio_page(dst, i);
diff --git a/mm/mempolicy.c b/mm/mempolicy.c
index bb37cd1a51d8..04f35659717a 100644
--- a/mm/mempolicy.c
+++ b/mm/mempolicy.c
@@ -1080,6 +1080,10 @@ static long migrate_to_node(struct mm_struct *mm, int source, int dest,
mmap_read_lock(mm);
vma = find_vma(mm, 0);
+ if (unlikely(!vma)) {
+ mmap_read_unlock(mm);
+ return 0;
+ }
/*
* This does not migrate the range, but isolates all pages that
diff --git a/mm/migrate.c b/mm/migrate.c
index 2ce6b4b814df..cc68583c86f9 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -745,7 +745,7 @@ void folio_migrate_flags(struct folio *newfolio, struct folio *folio)
folio_set_readahead(newfolio);
folio_copy_owner(newfolio, folio);
- pgalloc_tag_copy(newfolio, folio);
+ pgalloc_tag_swap(newfolio, folio);
mem_cgroup_migrate(folio, newfolio);
}
diff --git a/mm/mmap.c b/mm/mmap.c
index 386429f7db5a..aec208f90337 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -47,6 +47,7 @@
#include <linux/oom.h>
#include <linux/sched/mm.h>
#include <linux/ksm.h>
+#include <linux/memfd.h>
#include <linux/uaccess.h>
#include <asm/cacheflush.h>
@@ -368,6 +369,7 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
if (file) {
struct inode *inode = file_inode(file);
+ unsigned int seals = memfd_file_seals(file);
unsigned long flags_mask;
if (!file_mmap_ok(file, inode, pgoff, len))
@@ -408,6 +410,8 @@ unsigned long do_mmap(struct file *file, unsigned long addr,
vm_flags |= VM_SHARED | VM_MAYSHARE;
if (!(file->f_mode & FMODE_WRITE))
vm_flags &= ~(VM_MAYWRITE | VM_SHARED);
+ else if (is_readonly_sealed(seals, vm_flags))
+ vm_flags &= ~VM_MAYWRITE;
fallthrough;
case MAP_PRIVATE:
if (!(file->f_mode & FMODE_READ))
@@ -888,7 +892,8 @@ __get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
if (get_area) {
addr = get_area(file, addr, len, pgoff, flags);
- } else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)
+ } else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) && !file
+ && !addr /* no hint */
&& IS_ALIGNED(len, PMD_SIZE)) {
/* Ensures that larger anonymous mappings are THP aligned. */
addr = thp_get_unmapped_area_vmflags(file, addr, len,
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index 1cb4b8c8886d..cae7b93864c2 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1238,13 +1238,15 @@ static void split_large_buddy(struct zone *zone, struct page *page,
if (order > pageblock_order)
order = pageblock_order;
- while (pfn != end) {
+ do {
int mt = get_pfnblock_migratetype(page, pfn);
__free_one_page(page, pfn, zone, order, mt, fpi);
pfn += 1 << order;
+ if (pfn == end)
+ break;
page = pfn_to_page(pfn);
- }
+ } while (1);
}
static void free_one_page(struct zone *zone, struct page *page,
diff --git a/mm/pgtable-generic.c b/mm/pgtable-generic.c
index 5297dcc38c37..5a882f2b10f9 100644
--- a/mm/pgtable-generic.c
+++ b/mm/pgtable-generic.c
@@ -279,7 +279,7 @@ static unsigned long pmdp_get_lockless_start(void) { return 0; }
static void pmdp_get_lockless_end(unsigned long irqflags) { }
#endif
-pte_t *__pte_offset_map(pmd_t *pmd, unsigned long addr, pmd_t *pmdvalp)
+pte_t *___pte_offset_map(pmd_t *pmd, unsigned long addr, pmd_t *pmdvalp)
{
unsigned long irqflags;
pmd_t pmdval;
diff --git a/mm/readahead.c b/mm/readahead.c
index 8f1cf599b572..e151f4b13ca4 100644
--- a/mm/readahead.c
+++ b/mm/readahead.c
@@ -458,8 +458,7 @@ void page_cache_ra_order(struct readahead_control *ractl,
struct file_ra_state *ra, unsigned int new_order)
{
struct address_space *mapping = ractl->mapping;
- pgoff_t start = readahead_index(ractl);
- pgoff_t index = start;
+ pgoff_t index = readahead_index(ractl);
unsigned int min_order = mapping_min_folio_order(mapping);
pgoff_t limit = (i_size_read(mapping->host) - 1) >> PAGE_SHIFT;
pgoff_t mark = index + ra->size - ra->async_size;
@@ -522,7 +521,7 @@ void page_cache_ra_order(struct readahead_control *ractl,
if (!err)
return;
fallback:
- do_page_cache_ra(ractl, ra->size - (index - start), ra->async_size);
+ do_page_cache_ra(ractl, ra->size, ra->async_size);
}
static unsigned long ractl_max_pages(struct readahead_control *ractl,
@@ -647,7 +646,11 @@ void page_cache_async_ra(struct readahead_control *ractl,
1UL << order);
if (index == expected) {
ra->start += ra->size;
- ra->size = get_next_ra_size(ra, max_pages);
+ /*
+ * In the case of MADV_HUGEPAGE, the actual size might exceed
+ * the readahead window.
+ */
+ ra->size = max(ra->size, get_next_ra_size(ra, max_pages));
ra->async_size = ra->size;
goto readit;
}
diff --git a/mm/shmem.c b/mm/shmem.c
index ccb9629a0f70..ac58d4fb2e6f 100644
--- a/mm/shmem.c
+++ b/mm/shmem.c
@@ -787,6 +787,14 @@ static bool shmem_huge_global_enabled(struct inode *inode, pgoff_t index,
}
#endif /* CONFIG_TRANSPARENT_HUGEPAGE */
+static void shmem_update_stats(struct folio *folio, int nr_pages)
+{
+ if (folio_test_pmd_mappable(folio))
+ __lruvec_stat_mod_folio(folio, NR_SHMEM_THPS, nr_pages);
+ __lruvec_stat_mod_folio(folio, NR_FILE_PAGES, nr_pages);
+ __lruvec_stat_mod_folio(folio, NR_SHMEM, nr_pages);
+}
+
/*
* Somewhat like filemap_add_folio, but error if expected item has gone.
*/
@@ -821,10 +829,7 @@ static int shmem_add_to_page_cache(struct folio *folio,
xas_store(&xas, folio);
if (xas_error(&xas))
goto unlock;
- if (folio_test_pmd_mappable(folio))
- __lruvec_stat_mod_folio(folio, NR_SHMEM_THPS, nr);
- __lruvec_stat_mod_folio(folio, NR_FILE_PAGES, nr);
- __lruvec_stat_mod_folio(folio, NR_SHMEM, nr);
+ shmem_update_stats(folio, nr);
mapping->nrpages += nr;
unlock:
xas_unlock_irq(&xas);
@@ -852,8 +857,7 @@ static void shmem_delete_from_page_cache(struct folio *folio, void *radswap)
error = shmem_replace_entry(mapping, folio->index, folio, radswap);
folio->mapping = NULL;
mapping->nrpages -= nr;
- __lruvec_stat_mod_folio(folio, NR_FILE_PAGES, -nr);
- __lruvec_stat_mod_folio(folio, NR_SHMEM, -nr);
+ shmem_update_stats(folio, -nr);
xa_unlock_irq(&mapping->i_pages);
folio_put_refs(folio, nr);
BUG_ON(error);
@@ -1531,7 +1535,7 @@ try_split:
!shmem_falloc->waitq &&
index >= shmem_falloc->start &&
index < shmem_falloc->next)
- shmem_falloc->nr_unswapped++;
+ shmem_falloc->nr_unswapped += nr_pages;
else
shmem_falloc = NULL;
spin_unlock(&inode->i_lock);
@@ -1685,6 +1689,7 @@ unsigned long shmem_allowable_huge_orders(struct inode *inode,
unsigned long mask = READ_ONCE(huge_shmem_orders_always);
unsigned long within_size_orders = READ_ONCE(huge_shmem_orders_within_size);
unsigned long vm_flags = vma ? vma->vm_flags : 0;
+ pgoff_t aligned_index;
bool global_huge;
loff_t i_size;
int order;
@@ -1719,9 +1724,9 @@ unsigned long shmem_allowable_huge_orders(struct inode *inode,
/* Allow mTHP that will be fully within i_size. */
order = highest_order(within_size_orders);
while (within_size_orders) {
- index = round_up(index + 1, order);
+ aligned_index = round_up(index + 1, 1 << order);
i_size = round_up(i_size_read(inode), PAGE_SIZE);
- if (i_size >> PAGE_SHIFT >= index) {
+ if (i_size >> PAGE_SHIFT >= aligned_index) {
mask |= within_size_orders;
break;
}
@@ -1969,10 +1974,8 @@ static int shmem_replace_folio(struct folio **foliop, gfp_t gfp,
}
if (!error) {
mem_cgroup_replace_folio(old, new);
- __lruvec_stat_mod_folio(new, NR_FILE_PAGES, nr_pages);
- __lruvec_stat_mod_folio(new, NR_SHMEM, nr_pages);
- __lruvec_stat_mod_folio(old, NR_FILE_PAGES, -nr_pages);
- __lruvec_stat_mod_folio(old, NR_SHMEM, -nr_pages);
+ shmem_update_stats(new, nr_pages);
+ shmem_update_stats(old, -nr_pages);
}
xa_unlock_irq(&swap_mapping->i_pages);
diff --git a/mm/slub.c b/mm/slub.c
index 19980419b176..c2151c9fee22 100644
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -2189,9 +2189,24 @@ bool memcg_slab_post_charge(void *p, gfp_t flags)
folio = virt_to_folio(p);
if (!folio_test_slab(folio)) {
- return folio_memcg_kmem(folio) ||
- (__memcg_kmem_charge_page(folio_page(folio, 0), flags,
- folio_order(folio)) == 0);
+ int size;
+
+ if (folio_memcg_kmem(folio))
+ return true;
+
+ if (__memcg_kmem_charge_page(folio_page(folio, 0), flags,
+ folio_order(folio)))
+ return false;
+
+ /*
+ * This folio has already been accounted in the global stats but
+ * not in the memcg stats. So, subtract from the global and use
+ * the interface which adds to both global and memcg stats.
+ */
+ size = folio_size(folio);
+ node_stat_mod_folio(folio, NR_SLAB_UNRECLAIMABLE_B, -size);
+ lruvec_stat_mod_folio(folio, NR_SLAB_UNRECLAIMABLE_B, size);
+ return true;
}
slab = folio_slab(folio);
diff --git a/mm/util.c b/mm/util.c
index c1c3b06ab4f9..60aa40f612b8 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -297,12 +297,7 @@ void *memdup_user_nul(const void __user *src, size_t len)
{
char *p;
- /*
- * Always use GFP_KERNEL, since copy_from_user() can sleep and
- * cause pagefault, which makes it pointless to use GFP_NOFS
- * or GFP_ATOMIC.
- */
- p = kmalloc_track_caller(len + 1, GFP_KERNEL);
+ p = kmem_buckets_alloc_track_caller(user_buckets, len + 1, GFP_USER | __GFP_NOWARN);
if (!p)
return ERR_PTR(-ENOMEM);
diff --git a/mm/vma.c b/mm/vma.c
index 8a454a7bbc80..bb2119e5a0d0 100644
--- a/mm/vma.c
+++ b/mm/vma.c
@@ -35,7 +35,7 @@ struct mmap_state {
.mm = mm_, \
.vmi = vmi_, \
.addr = addr_, \
- .end = (addr_) + len, \
+ .end = (addr_) + (len_), \
.pgoff = pgoff_, \
.pglen = PHYS_PFN(len_), \
.flags = flags_, \
@@ -2460,10 +2460,13 @@ unsigned long __mmap_region(struct file *file, unsigned long addr,
/* If flags changed, we might be able to merge, so try again. */
if (map.retry_merge) {
+ struct vm_area_struct *merged;
VMG_MMAP_STATE(vmg, &map, vma);
vma_iter_config(map.vmi, map.addr, map.end);
- vma_merge_existing_range(&vmg);
+ merged = vma_merge_existing_range(&vmg);
+ if (merged)
+ vma = merged;
}
__mmap_complete(&map, vma);
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 7ed39d104201..5c88d0e90c20 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -3374,7 +3374,8 @@ void vfree(const void *addr)
struct page *page = vm->pages[i];
BUG_ON(!page);
- mod_memcg_page_state(page, MEMCG_VMALLOC, -1);
+ if (!(vm->flags & VM_MAP_PUT_PAGES))
+ mod_memcg_page_state(page, MEMCG_VMALLOC, -1);
/*
* High-order allocs for huge vmallocs are split, so
* can be freed as an array of order-0 allocations
@@ -3382,7 +3383,8 @@ void vfree(const void *addr)
__free_page(page);
cond_resched();
}
- atomic_long_sub(vm->nr_pages, &nr_vmalloc_pages);
+ if (!(vm->flags & VM_MAP_PUT_PAGES))
+ atomic_long_sub(vm->nr_pages, &nr_vmalloc_pages);
kvfree(vm->pages);
kfree(vm);
}
@@ -4093,7 +4095,8 @@ void *vrealloc_noprof(const void *p, size_t size, gfp_t flags)
/* Zero out spare memory. */
if (want_init_on_alloc(flags))
memset((void *)p + size, 0, old_size - size);
-
+ kasan_poison_vmalloc(p + size, old_size - size);
+ kasan_unpoison_vmalloc(p, size, KASAN_VMALLOC_PROT_NORMAL);
return (void *)p;
}
diff --git a/mm/vmscan.c b/mm/vmscan.c
index 76378bc257e3..9a859b7d18d7 100644
--- a/mm/vmscan.c
+++ b/mm/vmscan.c
@@ -374,7 +374,14 @@ unsigned long zone_reclaimable_pages(struct zone *zone)
if (can_reclaim_anon_pages(NULL, zone_to_nid(zone), NULL))
nr += zone_page_state_snapshot(zone, NR_ZONE_INACTIVE_ANON) +
zone_page_state_snapshot(zone, NR_ZONE_ACTIVE_ANON);
-
+ /*
+ * If there are no reclaimable file-backed or anonymous pages,
+ * ensure zones with sufficient free pages are not skipped.
+ * This prevents zones like DMA32 from being ignored in reclaim
+ * scenarios where they can still help alleviate memory pressure.
+ */
+ if (nr == 0)
+ nr = zone_page_state_snapshot(zone, NR_FREE_PAGES);
return nr;
}
diff --git a/mm/zswap.c b/mm/zswap.c
index f6316b66fb23..5a27af8d86ea 100644
--- a/mm/zswap.c
+++ b/mm/zswap.c
@@ -880,6 +880,18 @@ static int zswap_cpu_comp_dead(unsigned int cpu, struct hlist_node *node)
return 0;
}
+/* Prevent CPU hotplug from freeing up the per-CPU acomp_ctx resources */
+static struct crypto_acomp_ctx *acomp_ctx_get_cpu(struct crypto_acomp_ctx __percpu *acomp_ctx)
+{
+ cpus_read_lock();
+ return raw_cpu_ptr(acomp_ctx);
+}
+
+static void acomp_ctx_put_cpu(void)
+{
+ cpus_read_unlock();
+}
+
static bool zswap_compress(struct page *page, struct zswap_entry *entry,
struct zswap_pool *pool)
{
@@ -893,8 +905,7 @@ static bool zswap_compress(struct page *page, struct zswap_entry *entry,
gfp_t gfp;
u8 *dst;
- acomp_ctx = raw_cpu_ptr(pool->acomp_ctx);
-
+ acomp_ctx = acomp_ctx_get_cpu(pool->acomp_ctx);
mutex_lock(&acomp_ctx->mutex);
dst = acomp_ctx->buffer;
@@ -950,6 +961,7 @@ unlock:
zswap_reject_alloc_fail++;
mutex_unlock(&acomp_ctx->mutex);
+ acomp_ctx_put_cpu();
return comp_ret == 0 && alloc_ret == 0;
}
@@ -960,7 +972,7 @@ static void zswap_decompress(struct zswap_entry *entry, struct folio *folio)
struct crypto_acomp_ctx *acomp_ctx;
u8 *src;
- acomp_ctx = raw_cpu_ptr(entry->pool->acomp_ctx);
+ acomp_ctx = acomp_ctx_get_cpu(entry->pool->acomp_ctx);
mutex_lock(&acomp_ctx->mutex);
src = zpool_map_handle(zpool, entry->handle, ZPOOL_MM_RO);
@@ -990,6 +1002,7 @@ static void zswap_decompress(struct zswap_entry *entry, struct folio *folio)
if (src != acomp_ctx->buffer)
zpool_unmap_handle(zpool, entry->handle);
+ acomp_ctx_put_cpu();
}
/*********************************
diff --git a/net/802/psnap.c b/net/802/psnap.c
index fca9d454905f..389df460c8c4 100644
--- a/net/802/psnap.c
+++ b/net/802/psnap.c
@@ -55,11 +55,11 @@ static int snap_rcv(struct sk_buff *skb, struct net_device *dev,
goto drop;
rcu_read_lock();
- proto = find_snap_client(skb_transport_header(skb));
+ proto = find_snap_client(skb->data);
if (proto) {
/* Pass the frame on. */
- skb->transport_header += 5;
skb_pull_rcsum(skb, 5);
+ skb_reset_transport_header(skb);
rc = proto->rcvfunc(skb, dev, &snap_packet_type, orig_dev);
}
rcu_read_unlock();
diff --git a/net/9p/Kconfig b/net/9p/Kconfig
index ee967fd25312..22f8c167845d 100644
--- a/net/9p/Kconfig
+++ b/net/9p/Kconfig
@@ -41,8 +41,8 @@ config NET_9P_XEN
two Xen domains.
config NET_9P_USBG
- bool "9P USB Gadget Transport"
- depends on USB_GADGET=y || USB_GADGET=NET_9P
+ tristate "9P USB Gadget Transport"
+ depends on USB_GADGET
select CONFIGFS_FS
select USB_LIBCOMPOSITE
help
diff --git a/net/9p/trans_usbg.c b/net/9p/trans_usbg.c
index 975b76839dca..6b694f117aef 100644
--- a/net/9p/trans_usbg.c
+++ b/net/9p/trans_usbg.c
@@ -909,9 +909,9 @@ static struct usb_function_instance *usb9pfs_alloc_instance(void)
usb9pfs_opts->buflen = DEFAULT_BUFLEN;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (IS_ERR(dev)) {
+ if (!dev) {
kfree(usb9pfs_opts);
- return ERR_CAST(dev);
+ return ERR_PTR(-ENOMEM);
}
usb9pfs_opts->dev = dev;
diff --git a/net/9p/trans_xen.c b/net/9p/trans_xen.c
index dfdbe1ca5338..b9ff69c7522a 100644
--- a/net/9p/trans_xen.c
+++ b/net/9p/trans_xen.c
@@ -286,7 +286,7 @@ static void xen_9pfs_front_free(struct xen_9pfs_front_priv *priv)
if (!priv->rings[i].intf)
break;
if (priv->rings[i].irq > 0)
- unbind_from_irqhandler(priv->rings[i].irq, priv->dev);
+ unbind_from_irqhandler(priv->rings[i].irq, ring);
if (priv->rings[i].data.in) {
for (j = 0;
j < (1 << priv->rings[i].intf->ring_order);
@@ -465,6 +465,7 @@ static int xen_9pfs_front_init(struct xenbus_device *dev)
goto error;
}
+ xenbus_switch_state(dev, XenbusStateInitialised);
return 0;
error_xenbus:
@@ -512,8 +513,10 @@ static void xen_9pfs_front_changed(struct xenbus_device *dev,
break;
case XenbusStateInitWait:
- if (!xen_9pfs_front_init(dev))
- xenbus_switch_state(dev, XenbusStateInitialised);
+ if (dev->state != XenbusStateInitialising)
+ break;
+
+ xen_9pfs_front_init(dev);
break;
case XenbusStateConnected:
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c
index d6f9fae06a9d..aa6c714892ec 100644
--- a/net/ax25/af_ax25.c
+++ b/net/ax25/af_ax25.c
@@ -467,7 +467,7 @@ einval_put:
goto out_put;
}
-static void ax25_fillin_cb_from_dev(ax25_cb *ax25, ax25_dev *ax25_dev)
+static void ax25_fillin_cb_from_dev(ax25_cb *ax25, const ax25_dev *ax25_dev)
{
ax25->rtt = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]) / 2;
ax25->t1 = msecs_to_jiffies(ax25_dev->values[AX25_VALUES_T1]);
@@ -677,22 +677,22 @@ static int ax25_setsockopt(struct socket *sock, int level, int optname,
break;
}
- rtnl_lock();
- dev = __dev_get_by_name(&init_net, devname);
+ rcu_read_lock();
+ dev = dev_get_by_name_rcu(&init_net, devname);
if (!dev) {
- rtnl_unlock();
+ rcu_read_unlock();
res = -ENODEV;
break;
}
ax25->ax25_dev = ax25_dev_ax25dev(dev);
if (!ax25->ax25_dev) {
- rtnl_unlock();
+ rcu_read_unlock();
res = -ENODEV;
break;
}
ax25_fillin_cb(ax25, ax25->ax25_dev);
- rtnl_unlock();
+ rcu_read_unlock();
break;
default:
diff --git a/net/ax25/ax25_dev.c b/net/ax25/ax25_dev.c
index 9efd6690b344..3733c0254a50 100644
--- a/net/ax25/ax25_dev.c
+++ b/net/ax25/ax25_dev.c
@@ -90,7 +90,7 @@ void ax25_dev_device_up(struct net_device *dev)
spin_lock_bh(&ax25_dev_lock);
list_add(&ax25_dev->list, &ax25_dev_list);
- dev->ax25_ptr = ax25_dev;
+ rcu_assign_pointer(dev->ax25_ptr, ax25_dev);
spin_unlock_bh(&ax25_dev_lock);
ax25_register_dev_sysctl(ax25_dev);
@@ -125,7 +125,7 @@ void ax25_dev_device_down(struct net_device *dev)
}
}
- dev->ax25_ptr = NULL;
+ RCU_INIT_POINTER(dev->ax25_ptr, NULL);
spin_unlock_bh(&ax25_dev_lock);
netdev_put(dev, &ax25_dev->dev_tracker);
ax25_dev_put(ax25_dev);
diff --git a/net/ax25/ax25_ip.c b/net/ax25/ax25_ip.c
index 36249776c021..215d4ccf12b9 100644
--- a/net/ax25/ax25_ip.c
+++ b/net/ax25/ax25_ip.c
@@ -122,6 +122,7 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
if (dev == NULL)
dev = skb->dev;
+ rcu_read_lock();
if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL) {
kfree_skb(skb);
goto put;
@@ -202,7 +203,7 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
ax25_queue_xmit(skb, dev);
put:
-
+ rcu_read_unlock();
ax25_route_lock_unuse();
return NETDEV_TX_OK;
}
diff --git a/net/ax25/ax25_out.c b/net/ax25/ax25_out.c
index 3db76d2470e9..8bca2ace98e5 100644
--- a/net/ax25/ax25_out.c
+++ b/net/ax25/ax25_out.c
@@ -39,10 +39,14 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *sr
* specified.
*/
if (paclen == 0) {
- if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
+ rcu_read_lock();
+ ax25_dev = ax25_dev_ax25dev(dev);
+ if (!ax25_dev) {
+ rcu_read_unlock();
return NULL;
-
+ }
paclen = ax25_dev->values[AX25_VALUES_PACLEN];
+ rcu_read_unlock();
}
/*
@@ -53,13 +57,19 @@ ax25_cb *ax25_send_frame(struct sk_buff *skb, int paclen, const ax25_address *sr
return ax25; /* It already existed */
}
- if ((ax25_dev = ax25_dev_ax25dev(dev)) == NULL)
+ rcu_read_lock();
+ ax25_dev = ax25_dev_ax25dev(dev);
+ if (!ax25_dev) {
+ rcu_read_unlock();
return NULL;
+ }
- if ((ax25 = ax25_create_cb()) == NULL)
+ if ((ax25 = ax25_create_cb()) == NULL) {
+ rcu_read_unlock();
return NULL;
-
+ }
ax25_fillin_cb(ax25, ax25_dev);
+ rcu_read_unlock();
ax25->source_addr = *src;
ax25->dest_addr = *dest;
@@ -358,7 +368,9 @@ void ax25_queue_xmit(struct sk_buff *skb, struct net_device *dev)
{
unsigned char *ptr;
+ rcu_read_lock();
skb->protocol = ax25_type_trans(skb, ax25_fwd_dev(dev));
+ rcu_read_unlock();
ptr = skb_push(skb, 1);
*ptr = 0x00; /* KISS */
diff --git a/net/ax25/ax25_route.c b/net/ax25/ax25_route.c
index b7c4d656a94b..69de75db0c9c 100644
--- a/net/ax25/ax25_route.c
+++ b/net/ax25/ax25_route.c
@@ -406,6 +406,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
ax25_route_lock_unuse();
return -EHOSTUNREACH;
}
+ rcu_read_lock();
if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) {
err = -EHOSTUNREACH;
goto put;
@@ -442,6 +443,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
}
put:
+ rcu_read_unlock();
ax25_route_lock_unuse();
return err;
}
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c
index b44c382226a1..760d51fdbdf6 100644
--- a/net/batman-adv/translation-table.c
+++ b/net/batman-adv/translation-table.c
@@ -948,16 +948,25 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
int tt_diff_len, tt_change_len = 0;
int tt_diff_entries_num = 0;
int tt_diff_entries_count = 0;
+ bool drop_changes = false;
+ size_t tt_extra_len = 0;
u16 tvlv_len;
tt_diff_entries_num = atomic_read(&bat_priv->tt.local_changes);
tt_diff_len = batadv_tt_len(tt_diff_entries_num);
/* if we have too many changes for one packet don't send any
- * and wait for the tt table request which will be fragmented
+ * and wait for the tt table request so we can reply with the full
+ * (fragmented) table.
+ *
+ * The local change history should still be cleaned up so the next
+ * TT round can start again with a clean state.
*/
- if (tt_diff_len > bat_priv->soft_iface->mtu)
+ if (tt_diff_len > bat_priv->soft_iface->mtu) {
tt_diff_len = 0;
+ tt_diff_entries_num = 0;
+ drop_changes = true;
+ }
tvlv_len = batadv_tt_prepare_tvlv_local_data(bat_priv, &tt_data,
&tt_change, &tt_diff_len);
@@ -966,7 +975,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
tt_data->flags = BATADV_TT_OGM_DIFF;
- if (tt_diff_len == 0)
+ if (!drop_changes && tt_diff_len == 0)
goto container_register;
spin_lock_bh(&bat_priv->tt.changes_list_lock);
@@ -985,6 +994,9 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
}
spin_unlock_bh(&bat_priv->tt.changes_list_lock);
+ tt_extra_len = batadv_tt_len(tt_diff_entries_num -
+ tt_diff_entries_count);
+
/* Keep the buffer for possible tt_request */
spin_lock_bh(&bat_priv->tt.last_changeset_lock);
kfree(bat_priv->tt.last_changeset);
@@ -993,6 +1005,7 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
tt_change_len = batadv_tt_len(tt_diff_entries_count);
/* check whether this new OGM has no changes due to size problems */
if (tt_diff_entries_count > 0) {
+ tt_diff_len -= tt_extra_len;
/* if kmalloc() fails we will reply with the full table
* instead of providing the diff
*/
@@ -1005,6 +1018,8 @@ static void batadv_tt_tvlv_container_update(struct batadv_priv *bat_priv)
}
spin_unlock_bh(&bat_priv->tt.last_changeset_lock);
+ /* Remove extra packet space for OGM */
+ tvlv_len -= tt_extra_len;
container_register:
batadv_tvlv_container_register(bat_priv, BATADV_TVLV_TT, 1, tt_data,
tvlv_len);
@@ -2705,14 +2720,16 @@ static bool batadv_tt_global_valid(const void *entry_ptr,
*
* Fills the tvlv buff with the tt entries from the specified hash. If valid_cb
* is not provided then this becomes a no-op.
+ *
+ * Return: Remaining unused length in tvlv_buff.
*/
-static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
- struct batadv_hashtable *hash,
- void *tvlv_buff, u16 tt_len,
- bool (*valid_cb)(const void *,
- const void *,
- u8 *flags),
- void *cb_data)
+static u16 batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
+ struct batadv_hashtable *hash,
+ void *tvlv_buff, u16 tt_len,
+ bool (*valid_cb)(const void *,
+ const void *,
+ u8 *flags),
+ void *cb_data)
{
struct batadv_tt_common_entry *tt_common_entry;
struct batadv_tvlv_tt_change *tt_change;
@@ -2726,7 +2743,7 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
tt_change = tvlv_buff;
if (!valid_cb)
- return;
+ return tt_len;
rcu_read_lock();
for (i = 0; i < hash->size; i++) {
@@ -2752,6 +2769,8 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv,
}
}
rcu_read_unlock();
+
+ return batadv_tt_len(tt_tot - tt_num_entries);
}
/**
@@ -3022,10 +3041,11 @@ static bool batadv_send_other_tt_response(struct batadv_priv *bat_priv,
goto out;
/* fill the rest of the tvlv with the real TT entries */
- batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.global_hash,
- tt_change, tt_len,
- batadv_tt_global_valid,
- req_dst_orig_node);
+ tvlv_len -= batadv_tt_tvlv_generate(bat_priv,
+ bat_priv->tt.global_hash,
+ tt_change, tt_len,
+ batadv_tt_global_valid,
+ req_dst_orig_node);
}
/* Don't send the response, if larger than fragmented packet. */
@@ -3149,9 +3169,11 @@ static bool batadv_send_my_tt_response(struct batadv_priv *bat_priv,
goto out;
/* fill the rest of the tvlv with the real TT entries */
- batadv_tt_tvlv_generate(bat_priv, bat_priv->tt.local_hash,
- tt_change, tt_len,
- batadv_tt_local_valid, NULL);
+ tvlv_len -= batadv_tt_tvlv_generate(bat_priv,
+ bat_priv->tt.local_hash,
+ tt_change, tt_len,
+ batadv_tt_local_valid,
+ NULL);
}
tvlv_tt_data->flags = BATADV_TT_RESPONSE;
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index f9e19f9cb5a3..18ab5628f85a 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -57,7 +57,6 @@ DEFINE_RWLOCK(hci_dev_list_lock);
/* HCI callback list */
LIST_HEAD(hci_cb_list);
-DEFINE_MUTEX(hci_cb_list_lock);
/* HCI ID Numbering */
static DEFINE_IDA(hci_index_ida);
@@ -2993,9 +2992,7 @@ int hci_register_cb(struct hci_cb *cb)
{
BT_DBG("%p name %s", cb, cb->name);
- mutex_lock(&hci_cb_list_lock);
- list_add_tail(&cb->list, &hci_cb_list);
- mutex_unlock(&hci_cb_list_lock);
+ list_add_tail_rcu(&cb->list, &hci_cb_list);
return 0;
}
@@ -3005,9 +3002,8 @@ int hci_unregister_cb(struct hci_cb *cb)
{
BT_DBG("%p name %s", cb, cb->name);
- mutex_lock(&hci_cb_list_lock);
- list_del(&cb->list);
- mutex_unlock(&hci_cb_list_lock);
+ list_del_rcu(&cb->list);
+ synchronize_rcu();
return 0;
}
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 1427d6e2f3c9..2cc7a9306350 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -6870,38 +6870,27 @@ static void hci_le_create_big_complete_evt(struct hci_dev *hdev, void *data,
return;
hci_dev_lock(hdev);
- rcu_read_lock();
/* Connect all BISes that are bound to the BIG */
- list_for_each_entry_rcu(conn, &hdev->conn_hash.list, list) {
- if (bacmp(&conn->dst, BDADDR_ANY) ||
- conn->type != ISO_LINK ||
- conn->iso_qos.bcast.big != ev->handle)
+ while ((conn = hci_conn_hash_lookup_big_state(hdev, ev->handle,
+ BT_BOUND))) {
+ if (ev->status) {
+ hci_connect_cfm(conn, ev->status);
+ hci_conn_del(conn);
continue;
+ }
if (hci_conn_set_handle(conn,
__le16_to_cpu(ev->bis_handle[i++])))
continue;
- if (!ev->status) {
- conn->state = BT_CONNECTED;
- set_bit(HCI_CONN_BIG_CREATED, &conn->flags);
- rcu_read_unlock();
- hci_debugfs_create_conn(conn);
- hci_conn_add_sysfs(conn);
- hci_iso_setup_path(conn);
- rcu_read_lock();
- continue;
- }
-
- hci_connect_cfm(conn, ev->status);
- rcu_read_unlock();
- hci_conn_del(conn);
- rcu_read_lock();
+ conn->state = BT_CONNECTED;
+ set_bit(HCI_CONN_BIG_CREATED, &conn->flags);
+ hci_debugfs_create_conn(conn);
+ hci_conn_add_sysfs(conn);
+ hci_iso_setup_path(conn);
}
- rcu_read_unlock();
-
if (!ev->status && !i)
/* If no BISes have been connected for the BIG,
* terminate. This is in case all bound connections
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c
index 2272e1849ebd..022b86797acd 100644
--- a/net/bluetooth/hci_sock.c
+++ b/net/bluetooth/hci_sock.c
@@ -1926,7 +1926,7 @@ drop:
}
static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
- sockptr_t optval, unsigned int len)
+ sockptr_t optval, unsigned int optlen)
{
struct hci_ufilter uf = { .opcode = 0 };
struct sock *sk = sock->sk;
@@ -1943,7 +1943,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
switch (optname) {
case HCI_DATA_DIR:
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
@@ -1954,7 +1954,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
break;
case HCI_TIME_STAMP:
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
@@ -1974,7 +1974,7 @@ static int hci_sock_setsockopt_old(struct socket *sock, int level, int optname,
uf.event_mask[1] = *((u32 *) f->event_mask + 1);
}
- err = bt_copy_from_sockptr(&uf, sizeof(uf), optval, len);
+ err = copy_safe_from_sockptr(&uf, sizeof(uf), optval, optlen);
if (err)
break;
@@ -2005,7 +2005,7 @@ done:
}
static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
- sockptr_t optval, unsigned int len)
+ sockptr_t optval, unsigned int optlen)
{
struct sock *sk = sock->sk;
int err = 0;
@@ -2015,7 +2015,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
if (level == SOL_HCI)
return hci_sock_setsockopt_old(sock, level, optname, optval,
- len);
+ optlen);
if (level != SOL_BLUETOOTH)
return -ENOPROTOOPT;
@@ -2035,7 +2035,7 @@ static int hci_sock_setsockopt(struct socket *sock, int level, int optname,
goto done;
}
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, len);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index c86f4e42e69c..7b2b04d6b856 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -1031,9 +1031,9 @@ static bool adv_use_rpa(struct hci_dev *hdev, uint32_t flags)
static int hci_set_random_addr_sync(struct hci_dev *hdev, bdaddr_t *rpa)
{
- /* If we're advertising or initiating an LE connection we can't
- * go ahead and change the random address at this time. This is
- * because the eventual initiator address used for the
+ /* If a random_addr has been set we're advertising or initiating an LE
+ * connection we can't go ahead and change the random address at this
+ * time. This is because the eventual initiator address used for the
* subsequently created connection will be undefined (some
* controllers use the new address and others the one we had
* when the operation started).
@@ -1041,8 +1041,9 @@ static int hci_set_random_addr_sync(struct hci_dev *hdev, bdaddr_t *rpa)
* In this kind of scenario skip the update and let the random
* address be updated at the next cycle.
*/
- if (hci_dev_test_flag(hdev, HCI_LE_ADV) ||
- hci_lookup_le_connect(hdev)) {
+ if (bacmp(&hdev->random_addr, BDADDR_ANY) &&
+ (hci_dev_test_flag(hdev, HCI_LE_ADV) ||
+ hci_lookup_le_connect(hdev))) {
bt_dev_dbg(hdev, "Deferring random address update");
hci_dev_set_flag(hdev, HCI_RPA_EXPIRED);
return 0;
diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index 1b40fd2b2f02..43d0ebe11100 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -1129,6 +1129,7 @@ static int iso_listen_bis(struct sock *sk)
return -EHOSTUNREACH;
hci_dev_lock(hdev);
+ lock_sock(sk);
/* Fail if user set invalid QoS */
if (iso_pi(sk)->qos_user_set && !check_bcast_qos(&iso_pi(sk)->qos)) {
@@ -1158,10 +1159,10 @@ static int iso_listen_bis(struct sock *sk)
goto unlock;
}
- hci_dev_put(hdev);
-
unlock:
+ release_sock(sk);
hci_dev_unlock(hdev);
+ hci_dev_put(hdev);
return err;
}
@@ -1188,6 +1189,7 @@ static int iso_sock_listen(struct socket *sock, int backlog)
BT_DBG("sk %p backlog %d", sk, backlog);
+ sock_hold(sk);
lock_sock(sk);
if (sk->sk_state != BT_BOUND) {
@@ -1200,10 +1202,16 @@ static int iso_sock_listen(struct socket *sock, int backlog)
goto done;
}
- if (!bacmp(&iso_pi(sk)->dst, BDADDR_ANY))
+ if (!bacmp(&iso_pi(sk)->dst, BDADDR_ANY)) {
err = iso_listen_cis(sk);
- else
+ } else {
+ /* Drop sock lock to avoid potential
+ * deadlock with the hdev lock.
+ */
+ release_sock(sk);
err = iso_listen_bis(sk);
+ lock_sock(sk);
+ }
if (err)
goto done;
@@ -1215,6 +1223,7 @@ static int iso_sock_listen(struct socket *sock, int backlog)
done:
release_sock(sk);
+ sock_put(sk);
return err;
}
@@ -1226,7 +1235,11 @@ static int iso_sock_accept(struct socket *sock, struct socket *newsock,
long timeo;
int err = 0;
- lock_sock(sk);
+ /* Use explicit nested locking to avoid lockdep warnings generated
+ * because the parent socket and the child socket are locked on the
+ * same thread.
+ */
+ lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
timeo = sock_rcvtimeo(sk, arg->flags & O_NONBLOCK);
@@ -1257,7 +1270,7 @@ static int iso_sock_accept(struct socket *sock, struct socket *newsock,
release_sock(sk);
timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
- lock_sock(sk);
+ lock_sock_nested(sk, SINGLE_DEPTH_NESTING);
}
remove_wait_queue(sk_sleep(sk), &wait);
@@ -1398,6 +1411,7 @@ static void iso_conn_big_sync(struct sock *sk)
* change.
*/
hci_dev_lock(hdev);
+ lock_sock(sk);
if (!test_and_set_bit(BT_SK_BIG_SYNC, &iso_pi(sk)->flags)) {
err = hci_le_big_create_sync(hdev, iso_pi(sk)->conn->hcon,
@@ -1410,6 +1424,7 @@ static void iso_conn_big_sync(struct sock *sk)
err);
}
+ release_sock(sk);
hci_dev_unlock(hdev);
}
@@ -1418,39 +1433,57 @@ static int iso_sock_recvmsg(struct socket *sock, struct msghdr *msg,
{
struct sock *sk = sock->sk;
struct iso_pinfo *pi = iso_pi(sk);
+ bool early_ret = false;
+ int err = 0;
BT_DBG("sk %p", sk);
if (test_and_clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) {
+ sock_hold(sk);
lock_sock(sk);
+
switch (sk->sk_state) {
case BT_CONNECT2:
if (test_bit(BT_SK_PA_SYNC, &pi->flags)) {
+ release_sock(sk);
iso_conn_big_sync(sk);
+ lock_sock(sk);
+
sk->sk_state = BT_LISTEN;
} else {
iso_conn_defer_accept(pi->conn->hcon);
sk->sk_state = BT_CONFIG;
}
- release_sock(sk);
- return 0;
+
+ early_ret = true;
+ break;
case BT_CONNECTED:
if (test_bit(BT_SK_PA_SYNC, &iso_pi(sk)->flags)) {
+ release_sock(sk);
iso_conn_big_sync(sk);
+ lock_sock(sk);
+
sk->sk_state = BT_LISTEN;
- release_sock(sk);
- return 0;
+ early_ret = true;
}
- release_sock(sk);
break;
case BT_CONNECT:
release_sock(sk);
- return iso_connect_cis(sk);
+ err = iso_connect_cis(sk);
+ lock_sock(sk);
+
+ early_ret = true;
+ break;
default:
- release_sock(sk);
break;
}
+
+ release_sock(sk);
+ sock_put(sk);
+
+ if (early_ret)
+ return err;
}
return bt_sock_recvmsg(sock, msg, len, flags);
@@ -1566,7 +1599,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
@@ -1577,7 +1610,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
break;
case BT_PKT_STATUS:
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
@@ -1596,7 +1629,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- err = bt_copy_from_sockptr(&qos, sizeof(qos), optval, optlen);
+ err = copy_safe_from_sockptr(&qos, sizeof(qos), optval, optlen);
if (err)
break;
@@ -1617,8 +1650,8 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- err = bt_copy_from_sockptr(iso_pi(sk)->base, optlen, optval,
- optlen);
+ err = copy_safe_from_sockptr(iso_pi(sk)->base, optlen, optval,
+ optlen);
if (err)
break;
@@ -2118,6 +2151,11 @@ done:
return HCI_LM_ACCEPT;
}
+static bool iso_match(struct hci_conn *hcon)
+{
+ return hcon->type == ISO_LINK || hcon->type == LE_LINK;
+}
+
static void iso_connect_cfm(struct hci_conn *hcon, __u8 status)
{
if (hcon->type != ISO_LINK) {
@@ -2299,6 +2337,7 @@ drop:
static struct hci_cb iso_cb = {
.name = "ISO",
+ .match = iso_match,
.connect_cfm = iso_connect_cfm,
.disconn_cfm = iso_disconn_cfm,
};
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 6544c1ed7143..27b4c4a2ba1f 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -7217,6 +7217,11 @@ static struct l2cap_chan *l2cap_global_fixed_chan(struct l2cap_chan *c,
return NULL;
}
+static bool l2cap_match(struct hci_conn *hcon)
+{
+ return hcon->type == ACL_LINK || hcon->type == LE_LINK;
+}
+
static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
{
struct hci_dev *hdev = hcon->hdev;
@@ -7224,9 +7229,6 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
struct l2cap_chan *pchan;
u8 dst_type;
- if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
- return;
-
BT_DBG("hcon %p bdaddr %pMR status %d", hcon, &hcon->dst, status);
if (status) {
@@ -7291,9 +7293,6 @@ int l2cap_disconn_ind(struct hci_conn *hcon)
static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason)
{
- if (hcon->type != ACL_LINK && hcon->type != LE_LINK)
- return;
-
BT_DBG("hcon %p reason %d", hcon, reason);
l2cap_conn_del(hcon, bt_to_errno(reason));
@@ -7572,6 +7571,7 @@ drop:
static struct hci_cb l2cap_cb = {
.name = "L2CAP",
+ .match = l2cap_match,
.connect_cfm = l2cap_connect_cfm,
.disconn_cfm = l2cap_disconn_cfm,
.security_cfm = l2cap_security_cfm,
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 18e89e764f3b..3d2553dcdb1b 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -755,7 +755,8 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
opts.max_tx = chan->max_tx;
opts.txwin_size = chan->tx_win;
- err = bt_copy_from_sockptr(&opts, sizeof(opts), optval, optlen);
+ err = copy_safe_from_sockptr(&opts, sizeof(opts), optval,
+ optlen);
if (err)
break;
@@ -800,7 +801,7 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname,
break;
case L2CAP_LM:
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
@@ -909,7 +910,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
sec.level = BT_SECURITY_LOW;
- err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
+ err = copy_safe_from_sockptr(&sec, sizeof(sec), optval, optlen);
if (err)
break;
@@ -956,7 +957,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
@@ -970,7 +971,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
case BT_FLUSHABLE:
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
@@ -1004,7 +1005,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
pwr.force_active = BT_POWER_FORCE_ACTIVE_ON;
- err = bt_copy_from_sockptr(&pwr, sizeof(pwr), optval, optlen);
+ err = copy_safe_from_sockptr(&pwr, sizeof(pwr), optval, optlen);
if (err)
break;
@@ -1015,7 +1016,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
case BT_CHANNEL_POLICY:
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
@@ -1046,7 +1047,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- err = bt_copy_from_sockptr(&mtu, sizeof(mtu), optval, optlen);
+ err = copy_safe_from_sockptr(&mtu, sizeof(mtu), optval, optlen);
if (err)
break;
@@ -1076,7 +1077,8 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- err = bt_copy_from_sockptr(&mode, sizeof(mode), optval, optlen);
+ err = copy_safe_from_sockptr(&mode, sizeof(mode), optval,
+ optlen);
if (err)
break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index b31192d473d0..de47ad999d7b 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -7655,6 +7655,24 @@ static void device_added(struct sock *sk, struct hci_dev *hdev,
mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk);
}
+static void add_device_complete(struct hci_dev *hdev, void *data, int err)
+{
+ struct mgmt_pending_cmd *cmd = data;
+ struct mgmt_cp_add_device *cp = cmd->param;
+
+ if (!err) {
+ device_added(cmd->sk, hdev, &cp->addr.bdaddr, cp->addr.type,
+ cp->action);
+ device_flags_changed(NULL, hdev, &cp->addr.bdaddr,
+ cp->addr.type, hdev->conn_flags,
+ PTR_UINT(cmd->user_data));
+ }
+
+ mgmt_cmd_complete(cmd->sk, hdev->id, MGMT_OP_ADD_DEVICE,
+ mgmt_status(err), &cp->addr, sizeof(cp->addr));
+ mgmt_pending_free(cmd);
+}
+
static int add_device_sync(struct hci_dev *hdev, void *data)
{
return hci_update_passive_scan_sync(hdev);
@@ -7663,6 +7681,7 @@ static int add_device_sync(struct hci_dev *hdev, void *data)
static int add_device(struct sock *sk, struct hci_dev *hdev,
void *data, u16 len)
{
+ struct mgmt_pending_cmd *cmd;
struct mgmt_cp_add_device *cp = data;
u8 auto_conn, addr_type;
struct hci_conn_params *params;
@@ -7743,9 +7762,24 @@ static int add_device(struct sock *sk, struct hci_dev *hdev,
current_flags = params->flags;
}
- err = hci_cmd_sync_queue(hdev, add_device_sync, NULL, NULL);
- if (err < 0)
+ cmd = mgmt_pending_new(sk, MGMT_OP_ADD_DEVICE, hdev, data, len);
+ if (!cmd) {
+ err = -ENOMEM;
goto unlock;
+ }
+
+ cmd->user_data = UINT_PTR(current_flags);
+
+ err = hci_cmd_sync_queue(hdev, add_device_sync, cmd,
+ add_device_complete);
+ if (err < 0) {
+ err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE,
+ MGMT_STATUS_FAILED, &cp->addr,
+ sizeof(cp->addr));
+ mgmt_pending_free(cmd);
+ }
+
+ goto unlock;
added:
device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action);
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index ad5177e3a69b..4c56ca5a216c 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -2134,6 +2134,11 @@ static int rfcomm_run(void *unused)
return 0;
}
+static bool rfcomm_match(struct hci_conn *hcon)
+{
+ return hcon->type == ACL_LINK;
+}
+
static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
{
struct rfcomm_session *s;
@@ -2180,6 +2185,7 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt)
static struct hci_cb rfcomm_cb = {
.name = "RFCOMM",
+ .match = rfcomm_match,
.security_cfm = rfcomm_security_cfm
};
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 40766f8119ed..913402806fa0 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -629,10 +629,9 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname,
switch (optname) {
case RFCOMM_LM:
- if (bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen)) {
- err = -EFAULT;
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ if (err)
break;
- }
if (opt & RFCOMM_LM_FIPS) {
err = -EINVAL;
@@ -685,7 +684,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
sec.level = BT_SECURITY_LOW;
- err = bt_copy_from_sockptr(&sec, sizeof(sec), optval, optlen);
+ err = copy_safe_from_sockptr(&sec, sizeof(sec), optval, optlen);
if (err)
break;
@@ -703,7 +702,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index af80d599c337..21a5b5535ebc 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -201,14 +201,14 @@ static ssize_t address_show(struct device *tty_dev,
struct device_attribute *attr, char *buf)
{
struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
- return sprintf(buf, "%pMR\n", &dev->dst);
+ return sysfs_emit(buf, "%pMR\n", &dev->dst);
}
static ssize_t channel_show(struct device *tty_dev,
struct device_attribute *attr, char *buf)
{
struct rfcomm_dev *dev = dev_get_drvdata(tty_dev);
- return sprintf(buf, "%d\n", dev->channel);
+ return sysfs_emit(buf, "%d\n", dev->channel);
}
static DEVICE_ATTR_RO(address);
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 78f7bca24487..aa7bfe26cb40 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -319,10 +319,13 @@ static int sco_connect(struct sock *sk)
else
type = SCO_LINK;
- if (sco_pi(sk)->setting == BT_VOICE_TRANSPARENT &&
- (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev))) {
- err = -EOPNOTSUPP;
- goto unlock;
+ switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
+ case SCO_AIRMODE_TRANSP:
+ if (!lmp_transp_capable(hdev) || !lmp_esco_capable(hdev)) {
+ err = -EOPNOTSUPP;
+ goto unlock;
+ }
+ break;
}
hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
@@ -896,7 +899,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
@@ -915,18 +918,11 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
voice.setting = sco_pi(sk)->setting;
- err = bt_copy_from_sockptr(&voice, sizeof(voice), optval,
- optlen);
+ err = copy_safe_from_sockptr(&voice, sizeof(voice), optval,
+ optlen);
if (err)
break;
- /* Explicitly check for these values */
- if (voice.setting != BT_VOICE_TRANSPARENT &&
- voice.setting != BT_VOICE_CVSD_16BIT) {
- err = -EINVAL;
- break;
- }
-
sco_pi(sk)->setting = voice.setting;
hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src,
BDADDR_BREDR);
@@ -934,14 +930,19 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
err = -EBADFD;
break;
}
- if (enhanced_sync_conn_capable(hdev) &&
- voice.setting == BT_VOICE_TRANSPARENT)
- sco_pi(sk)->codec.id = BT_CODEC_TRANSPARENT;
+
+ switch (sco_pi(sk)->setting & SCO_AIRMODE_MASK) {
+ case SCO_AIRMODE_TRANSP:
+ if (enhanced_sync_conn_capable(hdev))
+ sco_pi(sk)->codec.id = BT_CODEC_TRANSPARENT;
+ break;
+ }
+
hci_dev_put(hdev);
break;
case BT_PKT_STATUS:
- err = bt_copy_from_sockptr(&opt, sizeof(opt), optval, optlen);
+ err = copy_safe_from_sockptr(&opt, sizeof(opt), optval, optlen);
if (err)
break;
@@ -984,7 +985,8 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname,
break;
}
- err = bt_copy_from_sockptr(buffer, optlen, optval, optlen);
+ err = copy_struct_from_sockptr(buffer, sizeof(buffer), optval,
+ optlen);
if (err) {
hci_dev_put(hdev);
break;
@@ -1396,11 +1398,13 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr, __u8 *flags)
return lm;
}
-static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
+static bool sco_match(struct hci_conn *hcon)
{
- if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
- return;
+ return hcon->type == SCO_LINK || hcon->type == ESCO_LINK;
+}
+static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
+{
BT_DBG("hcon %p bdaddr %pMR status %u", hcon, &hcon->dst, status);
if (!status) {
@@ -1415,9 +1419,6 @@ static void sco_connect_cfm(struct hci_conn *hcon, __u8 status)
static void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason)
{
- if (hcon->type != SCO_LINK && hcon->type != ESCO_LINK)
- return;
-
BT_DBG("hcon %p reason %d", hcon, reason);
sco_conn_del(hcon, bt_to_errno(reason));
@@ -1443,6 +1444,7 @@ drop:
static struct hci_cb sco_cb = {
.name = "SCO",
+ .match = sco_match,
.connect_cfm = sco_connect_cfm,
.disconn_cfm = sco_disconn_cfm,
};
diff --git a/net/bpf/test_run.c b/net/bpf/test_run.c
index 501ec4249fed..9ae2a7f1738b 100644
--- a/net/bpf/test_run.c
+++ b/net/bpf/test_run.c
@@ -153,7 +153,7 @@ static void xdp_test_run_init_page(netmem_ref netmem, void *arg)
new_ctx->data = new_ctx->data_meta + meta_len;
xdp_update_frame_from_buff(new_ctx, frm);
- frm->mem = new_ctx->rxq->mem;
+ frm->mem_type = new_ctx->rxq->mem.type;
memcpy(&head->orig_ctx, new_ctx, sizeof(head->orig_ctx));
}
@@ -246,7 +246,7 @@ static void reset_ctx(struct xdp_page_head *head)
head->ctx.data_meta = head->orig_ctx.data_meta;
head->ctx.data_end = head->orig_ctx.data_end;
xdp_update_frame_from_buff(&head->ctx, head->frame);
- head->frame->mem = head->orig_ctx.rxq->mem;
+ head->frame->mem_type = head->orig_ctx.rxq->mem.type;
}
static int xdp_recv_frames(struct xdp_frame **frames, int nframes,
diff --git a/net/bridge/br.c b/net/bridge/br.c
index 2cab878e0a39..183fcb362f9e 100644
--- a/net/bridge/br.c
+++ b/net/bridge/br.c
@@ -51,6 +51,13 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v
}
}
+ if (is_vlan_dev(dev)) {
+ struct net_device *real_dev = vlan_dev_real_dev(dev);
+
+ if (netif_is_bridge_master(real_dev))
+ br_vlan_vlan_upper_event(real_dev, dev, event);
+ }
+
/* not a port of a bridge */
p = br_port_get_rtnl(dev);
if (!p)
diff --git a/net/bridge/br_arp_nd_proxy.c b/net/bridge/br_arp_nd_proxy.c
index c7869a286df4..115a23054a58 100644
--- a/net/bridge/br_arp_nd_proxy.c
+++ b/net/bridge/br_arp_nd_proxy.c
@@ -229,7 +229,7 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
#endif
#if IS_ENABLED(CONFIG_IPV6)
-struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *msg)
+struct nd_msg *br_is_nd_neigh_msg(const struct sk_buff *skb, struct nd_msg *msg)
{
struct nd_msg *m;
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c
index 82bac2426631..902694c0ce64 100644
--- a/net/bridge/br_fdb.c
+++ b/net/bridge/br_fdb.c
@@ -955,6 +955,7 @@ int br_fdb_dump(struct sk_buff *skb,
struct net_device *filter_dev,
int *idx)
{
+ struct ndo_fdb_dump_context *ctx = (void *)cb->ctx;
struct net_bridge *br = netdev_priv(dev);
struct net_bridge_fdb_entry *f;
int err = 0;
@@ -970,7 +971,7 @@ int br_fdb_dump(struct sk_buff *skb,
rcu_read_lock();
hlist_for_each_entry_rcu(f, &br->fdb_list, fdb_node) {
- if (*idx < cb->args[2])
+ if (*idx < ctx->fdb_idx)
goto skip;
if (filter_dev && (!f->dst || f->dst->dev != filter_dev)) {
if (filter_dev != dev)
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c
index e19b583ff2c6..29097e984b4f 100644
--- a/net/bridge/br_forward.c
+++ b/net/bridge/br_forward.c
@@ -201,6 +201,7 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
enum br_pkt_type pkt_type, bool local_rcv, bool local_orig,
u16 vid)
{
+ enum skb_drop_reason reason = SKB_DROP_REASON_NO_TX_TARGET;
struct net_bridge_port *prev = NULL;
struct net_bridge_port *p;
@@ -234,8 +235,11 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
continue;
prev = maybe_deliver(prev, p, skb, local_orig);
- if (IS_ERR(prev))
+ if (IS_ERR(prev)) {
+ reason = PTR_ERR(prev) == -ENOMEM ? SKB_DROP_REASON_NOMEM :
+ SKB_DROP_REASON_NOT_SPECIFIED;
goto out;
+ }
}
if (!prev)
@@ -249,7 +253,7 @@ void br_flood(struct net_bridge *br, struct sk_buff *skb,
out:
if (!local_rcv)
- kfree_skb(skb);
+ kfree_skb_reason(skb, reason);
}
#ifdef CONFIG_BRIDGE_IGMP_SNOOPING
@@ -289,6 +293,7 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
struct net_bridge_mcast *brmctx,
bool local_rcv, bool local_orig)
{
+ enum skb_drop_reason reason = SKB_DROP_REASON_NO_TX_TARGET;
struct net_bridge_port *prev = NULL;
struct net_bridge_port_group *p;
bool allow_mode_include = true;
@@ -329,8 +334,11 @@ void br_multicast_flood(struct net_bridge_mdb_entry *mdst,
}
prev = maybe_deliver(prev, port, skb, local_orig);
- if (IS_ERR(prev))
+ if (IS_ERR(prev)) {
+ reason = PTR_ERR(prev) == -ENOMEM ? SKB_DROP_REASON_NOMEM :
+ SKB_DROP_REASON_NOT_SPECIFIED;
goto out;
+ }
delivered:
if ((unsigned long)lport >= (unsigned long)port)
p = rcu_dereference(p->next);
@@ -349,6 +357,6 @@ delivered:
out:
if (!local_rcv)
- kfree_skb(skb);
+ kfree_skb_reason(skb, reason);
}
#endif
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c
index ceaa5a89b947..232133a0fd21 100644
--- a/net/bridge/br_input.c
+++ b/net/bridge/br_input.c
@@ -75,6 +75,7 @@ static int br_pass_frame_up(struct sk_buff *skb, bool promisc)
/* note: already called with rcu_read_lock */
int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
{
+ enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
struct net_bridge_port *p = br_port_get_rcu(skb->dev);
enum br_pkt_type pkt_type = BR_PKT_UNICAST;
struct net_bridge_fdb_entry *dst = NULL;
@@ -96,8 +97,10 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
if (br_mst_is_enabled(br)) {
state = BR_STATE_FORWARDING;
} else {
- if (p->state == BR_STATE_DISABLED)
+ if (p->state == BR_STATE_DISABLED) {
+ reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;
goto drop;
+ }
state = p->state;
}
@@ -155,8 +158,10 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
}
}
- if (state == BR_STATE_LEARNING)
+ if (state == BR_STATE_LEARNING) {
+ reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;
goto drop;
+ }
BR_INPUT_SKB_CB(skb)->brdev = br->dev;
BR_INPUT_SKB_CB(skb)->src_port_isolated = !!(p->flags & BR_ISOLATED);
@@ -223,7 +228,7 @@ int br_handle_frame_finish(struct net *net, struct sock *sk, struct sk_buff *skb
out:
return 0;
drop:
- kfree_skb(skb);
+ kfree_skb_reason(skb, reason);
goto out;
}
EXPORT_SYMBOL_GPL(br_handle_frame_finish);
@@ -324,6 +329,7 @@ static int br_process_frame_type(struct net_bridge_port *p,
*/
static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
{
+ enum skb_drop_reason reason = SKB_DROP_REASON_NOT_SPECIFIED;
struct net_bridge_port *p;
struct sk_buff *skb = *pskb;
const unsigned char *dest = eth_hdr(skb)->h_dest;
@@ -331,8 +337,10 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
if (unlikely(skb->pkt_type == PACKET_LOOPBACK))
return RX_HANDLER_PASS;
- if (!is_valid_ether_addr(eth_hdr(skb)->h_source))
+ if (!is_valid_ether_addr(eth_hdr(skb)->h_source)) {
+ reason = SKB_DROP_REASON_MAC_INVALID_SOURCE;
goto drop;
+ }
skb = skb_share_check(skb, GFP_ATOMIC);
if (!skb)
@@ -374,6 +382,7 @@ static rx_handler_result_t br_handle_frame(struct sk_buff **pskb)
return RX_HANDLER_PASS;
case 0x01: /* IEEE MAC (Pause) */
+ reason = SKB_DROP_REASON_MAC_IEEE_MAC_CONTROL;
goto drop;
case 0x0E: /* 802.1AB LLDP */
@@ -423,8 +432,9 @@ defer_stp_filtering:
return nf_hook_bridge_pre(skb, pskb);
default:
+ reason = SKB_DROP_REASON_BRIDGE_INGRESS_STP_STATE;
drop:
- kfree_skb(skb);
+ kfree_skb_reason(skb, reason);
}
return RX_HANDLER_CONSUMED;
}
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index 9853cfbb9d14..1054b8a88edc 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -1571,6 +1571,9 @@ void br_vlan_get_stats(const struct net_bridge_vlan *v,
void br_vlan_port_event(struct net_bridge_port *p, unsigned long event);
int br_vlan_bridge_event(struct net_device *dev, unsigned long event,
void *ptr);
+void br_vlan_vlan_upper_event(struct net_device *br_dev,
+ struct net_device *vlan_dev,
+ unsigned long event);
int br_vlan_rtnl_init(void);
void br_vlan_rtnl_uninit(void);
void br_vlan_notify(const struct net_bridge *br,
@@ -1802,6 +1805,12 @@ static inline int br_vlan_bridge_event(struct net_device *dev,
return 0;
}
+static inline void br_vlan_vlan_upper_event(struct net_device *br_dev,
+ struct net_device *vlan_dev,
+ unsigned long event)
+{
+}
+
static inline int br_vlan_rtnl_init(void)
{
return 0;
@@ -2290,6 +2299,6 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
u16 vid, struct net_bridge_port *p);
void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
u16 vid, struct net_bridge_port *p, struct nd_msg *msg);
-struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *m);
+struct nd_msg *br_is_nd_neigh_msg(const struct sk_buff *skb, struct nd_msg *m);
bool br_is_neigh_suppress_enabled(const struct net_bridge_port *p, u16 vid);
#endif
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c
index ea733542244c..c1176a5e02c4 100644
--- a/net/bridge/br_sysfs_br.c
+++ b/net/bridge/br_sysfs_br.c
@@ -1002,7 +1002,7 @@ static const struct attribute_group bridge_group = {
* Returns the number of bytes read.
*/
static ssize_t brforward_read(struct file *filp, struct kobject *kobj,
- struct bin_attribute *bin_attr,
+ const struct bin_attribute *bin_attr,
char *buf, loff_t off, size_t count)
{
struct device *dev = kobj_to_dev(kobj);
@@ -1023,10 +1023,10 @@ static ssize_t brforward_read(struct file *filp, struct kobject *kobj,
return n;
}
-static struct bin_attribute bridge_forward = {
+static const struct bin_attribute bridge_forward = {
.attr = { .name = SYSFS_BRIDGE_FDB,
.mode = 0444, },
- .read = brforward_read,
+ .read_new = brforward_read,
};
/*
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c
index 89f51ea4cabe..d9a69ec9affe 100644
--- a/net/bridge/br_vlan.c
+++ b/net/bridge/br_vlan.c
@@ -1664,6 +1664,18 @@ static void br_vlan_set_all_vlan_dev_state(struct net_bridge_port *p)
}
}
+static void br_vlan_toggle_bridge_binding(struct net_device *br_dev,
+ bool enable)
+{
+ struct net_bridge *br = netdev_priv(br_dev);
+
+ if (enable)
+ br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING, true);
+ else
+ br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING,
+ br_vlan_has_upper_bind_vlan_dev(br_dev));
+}
+
static void br_vlan_upper_change(struct net_device *dev,
struct net_device *upper_dev,
bool linking)
@@ -1673,13 +1685,9 @@ static void br_vlan_upper_change(struct net_device *dev,
if (!br_vlan_is_bind_vlan_dev(upper_dev))
return;
- if (linking) {
+ br_vlan_toggle_bridge_binding(dev, linking);
+ if (linking)
br_vlan_set_vlan_dev_state(br, upper_dev);
- br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING, true);
- } else {
- br_opt_toggle(br, BROPT_VLAN_BRIDGE_BINDING,
- br_vlan_has_upper_bind_vlan_dev(dev));
- }
}
struct br_vlan_link_state_walk_data {
@@ -1764,6 +1772,30 @@ int br_vlan_bridge_event(struct net_device *dev, unsigned long event, void *ptr)
return ret;
}
+void br_vlan_vlan_upper_event(struct net_device *br_dev,
+ struct net_device *vlan_dev,
+ unsigned long event)
+{
+ struct vlan_dev_priv *vlan = vlan_dev_priv(vlan_dev);
+ struct net_bridge *br = netdev_priv(br_dev);
+ bool bridge_binding;
+
+ switch (event) {
+ case NETDEV_CHANGE:
+ case NETDEV_UP:
+ break;
+ default:
+ return;
+ }
+
+ bridge_binding = vlan->flags & VLAN_FLAG_BRIDGE_BINDING;
+ br_vlan_toggle_bridge_binding(br_dev, bridge_binding);
+ if (bridge_binding)
+ br_vlan_set_vlan_dev_state(br, vlan_dev);
+ else if (!bridge_binding && netif_carrier_ok(br_dev))
+ netif_carrier_on(vlan_dev);
+}
+
/* Must be protected by RTNL. */
void br_vlan_port_event(struct net_bridge_port *p, unsigned long event)
{
diff --git a/net/can/j1939/transport.c b/net/can/j1939/transport.c
index 319f47df3330..95f7a7e65a73 100644
--- a/net/can/j1939/transport.c
+++ b/net/can/j1939/transport.c
@@ -1505,7 +1505,7 @@ static struct j1939_session *j1939_session_new(struct j1939_priv *priv,
session->state = J1939_SESSION_NEW;
skb_queue_head_init(&session->skb_queue);
- skb_queue_tail(&session->skb_queue, skb);
+ skb_queue_tail(&session->skb_queue, skb_get(skb));
skcb = j1939_skb_to_cb(skb);
memcpy(&session->skcb, skcb, sizeof(session->skcb));
diff --git a/net/can/raw.c b/net/can/raw.c
index 255c0a8f39d6..46e8ed9d64da 100644
--- a/net/can/raw.c
+++ b/net/can/raw.c
@@ -962,7 +962,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size)
}
skb->dev = dev;
- skb->priority = READ_ONCE(sk->sk_priority);
+ skb->priority = sockc.priority;
skb->mark = READ_ONCE(sk->sk_mark);
skb->tstamp = sockc.transmit_time;
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c
index 051d22c0e4ad..01b2ce1e8fc0 100644
--- a/net/ceph/crypto.c
+++ b/net/ceph/crypto.c
@@ -74,18 +74,6 @@ int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
return set_secret(dst, src->key);
}
-int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end)
-{
- if (*p + sizeof(u16) + sizeof(key->created) +
- sizeof(u16) + key->len > end)
- return -ERANGE;
- ceph_encode_16(p, key->type);
- ceph_encode_copy(p, &key->created, sizeof(key->created));
- ceph_encode_16(p, key->len);
- ceph_encode_copy(p, key->key, key->len);
- return 0;
-}
-
int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end)
{
int ret;
diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h
index 13bd526349fa..23de29fc613c 100644
--- a/net/ceph/crypto.h
+++ b/net/ceph/crypto.h
@@ -21,7 +21,6 @@ struct ceph_crypto_key {
int ceph_crypto_key_clone(struct ceph_crypto_key *dst,
const struct ceph_crypto_key *src);
-int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end);
int ceph_crypto_key_decode(struct ceph_crypto_key *key, void **p, void *end);
int ceph_crypto_key_unarmor(struct ceph_crypto_key *key, const char *in);
void ceph_crypto_key_destroy(struct ceph_crypto_key *key);
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c
index 9d078b37fe0b..b24afec24138 100644
--- a/net/ceph/osd_client.c
+++ b/net/ceph/osd_client.c
@@ -1173,6 +1173,8 @@ EXPORT_SYMBOL(ceph_osdc_new_request);
int __ceph_alloc_sparse_ext_map(struct ceph_osd_req_op *op, int cnt)
{
+ WARN_ON(op->op != CEPH_OSD_OP_SPARSE_READ);
+
op->extent.sparse_ext_cnt = cnt;
op->extent.sparse_ext = kmalloc_array(cnt,
sizeof(*op->extent.sparse_ext),
@@ -4999,40 +5001,6 @@ out_put_lreq:
}
EXPORT_SYMBOL(ceph_osdc_notify);
-/*
- * Return the number of milliseconds since the watch was last
- * confirmed, or an error. If there is an error, the watch is no
- * longer valid, and should be destroyed with ceph_osdc_unwatch().
- */
-int ceph_osdc_watch_check(struct ceph_osd_client *osdc,
- struct ceph_osd_linger_request *lreq)
-{
- unsigned long stamp, age;
- int ret;
-
- down_read(&osdc->lock);
- mutex_lock(&lreq->lock);
- stamp = lreq->watch_valid_thru;
- if (!list_empty(&lreq->pending_lworks)) {
- struct linger_work *lwork =
- list_first_entry(&lreq->pending_lworks,
- struct linger_work,
- pending_item);
-
- if (time_before(lwork->queued_stamp, stamp))
- stamp = lwork->queued_stamp;
- }
- age = jiffies - stamp;
- dout("%s lreq %p linger_id %llu age %lu last_error %d\n", __func__,
- lreq, lreq->linger_id, age, lreq->last_error);
- /* we are truncating to msecs, so return a safe upper bound */
- ret = lreq->last_error ?: 1 + jiffies_to_msecs(age);
-
- mutex_unlock(&lreq->lock);
- up_read(&osdc->lock);
- return ret;
-}
-
static int decode_watcher(void **p, void *end, struct ceph_watch_item *item)
{
u8 struct_v;
diff --git a/net/ceph/pagelist.c b/net/ceph/pagelist.c
index 74622b278d57..5a9c4be5f222 100644
--- a/net/ceph/pagelist.c
+++ b/net/ceph/pagelist.c
@@ -131,41 +131,3 @@ int ceph_pagelist_free_reserve(struct ceph_pagelist *pl)
return 0;
}
EXPORT_SYMBOL(ceph_pagelist_free_reserve);
-
-/* Create a truncation point. */
-void ceph_pagelist_set_cursor(struct ceph_pagelist *pl,
- struct ceph_pagelist_cursor *c)
-{
- c->pl = pl;
- c->page_lru = pl->head.prev;
- c->room = pl->room;
-}
-EXPORT_SYMBOL(ceph_pagelist_set_cursor);
-
-/* Truncate a pagelist to the given point. Move extra pages to reserve.
- * This won't sleep.
- * Returns: 0 on success,
- * -EINVAL if the pagelist doesn't match the trunc point pagelist
- */
-int ceph_pagelist_truncate(struct ceph_pagelist *pl,
- struct ceph_pagelist_cursor *c)
-{
- struct page *page;
-
- if (pl != c->pl)
- return -EINVAL;
- ceph_pagelist_unmap_tail(pl);
- while (pl->head.prev != c->page_lru) {
- page = list_entry(pl->head.prev, struct page, lru);
- /* move from pagelist to reserve */
- list_move_tail(&page->lru, &pl->free_list);
- ++pl->num_pages_free;
- }
- pl->room = c->room;
- if (!list_empty(&pl->head)) {
- page = list_entry(pl->head.prev, struct page, lru);
- pl->mapped_tail = kmap(page);
- }
- return 0;
-}
-EXPORT_SYMBOL(ceph_pagelist_truncate);
diff --git a/net/ceph/pagevec.c b/net/ceph/pagevec.c
index 64305e7056a1..4509757d8b3b 100644
--- a/net/ceph/pagevec.c
+++ b/net/ceph/pagevec.c
@@ -55,58 +55,6 @@ struct page **ceph_alloc_page_vector(int num_pages, gfp_t flags)
}
EXPORT_SYMBOL(ceph_alloc_page_vector);
-/*
- * copy user data into a page vector
- */
-int ceph_copy_user_to_page_vector(struct page **pages,
- const void __user *data,
- loff_t off, size_t len)
-{
- int i = 0;
- int po = off & ~PAGE_MASK;
- int left = len;
- int l, bad;
-
- while (left > 0) {
- l = min_t(int, PAGE_SIZE-po, left);
- bad = copy_from_user(page_address(pages[i]) + po, data, l);
- if (bad == l)
- return -EFAULT;
- data += l - bad;
- left -= l - bad;
- po += l - bad;
- if (po == PAGE_SIZE) {
- po = 0;
- i++;
- }
- }
- return len;
-}
-EXPORT_SYMBOL(ceph_copy_user_to_page_vector);
-
-void ceph_copy_to_page_vector(struct page **pages,
- const void *data,
- loff_t off, size_t len)
-{
- int i = 0;
- size_t po = off & ~PAGE_MASK;
- size_t left = len;
-
- while (left > 0) {
- size_t l = min_t(size_t, PAGE_SIZE-po, left);
-
- memcpy(page_address(pages[i]) + po, data, l);
- data += l;
- left -= l;
- po += l;
- if (po == PAGE_SIZE) {
- po = 0;
- i++;
- }
- }
-}
-EXPORT_SYMBOL(ceph_copy_to_page_vector);
-
void ceph_copy_from_page_vector(struct page **pages,
void *data,
loff_t off, size_t len)
diff --git a/net/core/dev.c b/net/core/dev.c
index 13d00fc10f55..4452ca2c91ea 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -460,7 +460,7 @@ EXPORT_PER_CPU_SYMBOL(softnet_data);
* PP consumers must pay attention to run APIs in the appropriate context
* (e.g. NAPI context).
*/
-static DEFINE_PER_CPU(struct page_pool *, system_page_pool);
+DEFINE_PER_CPU(struct page_pool *, system_page_pool);
#ifdef CONFIG_LOCKDEP
/*
@@ -753,6 +753,36 @@ int dev_fill_forward_path(const struct net_device *dev, const u8 *daddr,
}
EXPORT_SYMBOL_GPL(dev_fill_forward_path);
+/* must be called under rcu_read_lock(), as we dont take a reference */
+static struct napi_struct *napi_by_id(unsigned int napi_id)
+{
+ unsigned int hash = napi_id % HASH_SIZE(napi_hash);
+ struct napi_struct *napi;
+
+ hlist_for_each_entry_rcu(napi, &napi_hash[hash], napi_hash_node)
+ if (napi->napi_id == napi_id)
+ return napi;
+
+ return NULL;
+}
+
+/* must be called under rcu_read_lock(), as we dont take a reference */
+struct napi_struct *netdev_napi_by_id(struct net *net, unsigned int napi_id)
+{
+ struct napi_struct *napi;
+
+ napi = napi_by_id(napi_id);
+ if (!napi)
+ return NULL;
+
+ if (WARN_ON_ONCE(!napi->dev))
+ return NULL;
+ if (!net_eq(net, dev_net(napi->dev)))
+ return NULL;
+
+ return napi;
+}
+
/**
* __dev_get_by_name - find a device by its name
* @net: the applicable net namespace
@@ -1769,14 +1799,19 @@ int register_netdevice_notifier(struct notifier_block *nb)
/* Close race with setup_net() and cleanup_net() */
down_write(&pernet_ops_rwsem);
+
+ /* When RTNL is removed, we need protection for netdev_chain. */
rtnl_lock();
+
err = raw_notifier_chain_register(&netdev_chain, nb);
if (err)
goto unlock;
if (dev_boot_phase)
goto unlock;
for_each_net(net) {
+ __rtnl_net_lock(net);
err = call_netdevice_register_net_notifiers(nb, net);
+ __rtnl_net_unlock(net);
if (err)
goto rollback;
}
@@ -1787,8 +1822,11 @@ unlock:
return err;
rollback:
- for_each_net_continue_reverse(net)
+ for_each_net_continue_reverse(net) {
+ __rtnl_net_lock(net);
call_netdevice_unregister_net_notifiers(nb, net);
+ __rtnl_net_unlock(net);
+ }
raw_notifier_chain_unregister(&netdev_chain, nb);
goto unlock;
@@ -1821,8 +1859,11 @@ int unregister_netdevice_notifier(struct notifier_block *nb)
if (err)
goto unlock;
- for_each_net(net)
+ for_each_net(net) {
+ __rtnl_net_lock(net);
call_netdevice_unregister_net_notifiers(nb, net);
+ __rtnl_net_unlock(net);
+ }
unlock:
rtnl_unlock();
@@ -1886,9 +1927,10 @@ int register_netdevice_notifier_net(struct net *net, struct notifier_block *nb)
{
int err;
- rtnl_lock();
+ rtnl_net_lock(net);
err = __register_netdevice_notifier_net(net, nb, false);
- rtnl_unlock();
+ rtnl_net_unlock(net);
+
return err;
}
EXPORT_SYMBOL(register_netdevice_notifier_net);
@@ -1914,9 +1956,10 @@ int unregister_netdevice_notifier_net(struct net *net,
{
int err;
- rtnl_lock();
+ rtnl_net_lock(net);
err = __unregister_netdevice_notifier_net(net, nb);
- rtnl_unlock();
+ rtnl_net_unlock(net);
+
return err;
}
EXPORT_SYMBOL(unregister_netdevice_notifier_net);
@@ -1933,15 +1976,17 @@ int register_netdevice_notifier_dev_net(struct net_device *dev,
struct notifier_block *nb,
struct netdev_net_notifier *nn)
{
+ struct net *net = dev_net(dev);
int err;
- rtnl_lock();
- err = __register_netdevice_notifier_net(dev_net(dev), nb, false);
+ rtnl_net_lock(net);
+ err = __register_netdevice_notifier_net(net, nb, false);
if (!err) {
nn->nb = nb;
list_add(&nn->list, &dev->net_notifier_list);
}
- rtnl_unlock();
+ rtnl_net_unlock(net);
+
return err;
}
EXPORT_SYMBOL(register_netdevice_notifier_dev_net);
@@ -1950,12 +1995,14 @@ int unregister_netdevice_notifier_dev_net(struct net_device *dev,
struct notifier_block *nb,
struct netdev_net_notifier *nn)
{
+ struct net *net = dev_net(dev);
int err;
- rtnl_lock();
+ rtnl_net_lock(net);
list_del(&nn->list);
- err = __unregister_netdevice_notifier_net(dev_net(dev), nb);
- rtnl_unlock();
+ err = __unregister_netdevice_notifier_net(net, nb);
+ rtnl_net_unlock(net);
+
return err;
}
EXPORT_SYMBOL(unregister_netdevice_notifier_dev_net);
@@ -3233,7 +3280,7 @@ void netif_device_attach(struct net_device *dev)
if (!test_and_set_bit(__LINK_STATE_PRESENT, &dev->state) &&
netif_running(dev)) {
netif_tx_wake_all_queues(dev);
- __netdev_watchdog_up(dev);
+ netdev_watchdog_up(dev);
}
}
EXPORT_SYMBOL(netif_device_attach);
@@ -3642,8 +3689,10 @@ int skb_csum_hwoffload_help(struct sk_buff *skb,
if (features & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM)) {
if (vlan_get_protocol(skb) == htons(ETH_P_IPV6) &&
- skb_network_header_len(skb) != sizeof(struct ipv6hdr))
+ skb_network_header_len(skb) != sizeof(struct ipv6hdr) &&
+ !ipv6_has_hopopt_jumbo(skb))
goto sw_checksum;
+
switch (skb->csum_offset) {
case offsetof(struct tcphdr, check):
case offsetof(struct udphdr, check):
@@ -4931,7 +4980,7 @@ static struct netdev_rx_queue *netif_get_rxqueue(struct sk_buff *skb)
}
u32 bpf_prog_run_generic_xdp(struct sk_buff *skb, struct xdp_buff *xdp,
- struct bpf_prog *xdp_prog)
+ const struct bpf_prog *xdp_prog)
{
void *orig_data, *orig_data_end, *hard_start;
struct netdev_rx_queue *rxqueue;
@@ -5033,7 +5082,7 @@ u32 bpf_prog_run_generic_xdp(struct sk_buff *skb, struct xdp_buff *xdp,
}
static int
-netif_skb_check_for_xdp(struct sk_buff **pskb, struct bpf_prog *prog)
+netif_skb_check_for_xdp(struct sk_buff **pskb, const struct bpf_prog *prog)
{
struct sk_buff *skb = *pskb;
int err, hroom, troom;
@@ -5057,7 +5106,7 @@ netif_skb_check_for_xdp(struct sk_buff **pskb, struct bpf_prog *prog)
static u32 netif_receive_generic_xdp(struct sk_buff **pskb,
struct xdp_buff *xdp,
- struct bpf_prog *xdp_prog)
+ const struct bpf_prog *xdp_prog)
{
struct sk_buff *skb = *pskb;
u32 mac_len, act = XDP_DROP;
@@ -5110,7 +5159,7 @@ static u32 netif_receive_generic_xdp(struct sk_buff **pskb,
* and DDOS attacks will be more effective. In-driver-XDP use dedicated TX
* queues, so they do not have this starvation issue.
*/
-void generic_xdp_tx(struct sk_buff *skb, struct bpf_prog *xdp_prog)
+void generic_xdp_tx(struct sk_buff *skb, const struct bpf_prog *xdp_prog)
{
struct net_device *dev = skb->dev;
struct netdev_queue *txq;
@@ -5135,7 +5184,7 @@ void generic_xdp_tx(struct sk_buff *skb, struct bpf_prog *xdp_prog)
static DEFINE_STATIC_KEY_FALSE(generic_xdp_needed_key);
-int do_xdp_generic(struct bpf_prog *xdp_prog, struct sk_buff **pskb)
+int do_xdp_generic(const struct bpf_prog *xdp_prog, struct sk_buff **pskb)
{
struct bpf_net_context __bpf_net_ctx, *bpf_net_ctx;
@@ -5474,8 +5523,14 @@ static int __netif_receive_skb_core(struct sk_buff **pskb, bool pfmemalloc,
orig_dev = skb->dev;
skb_reset_network_header(skb);
+#if !defined(CONFIG_DEBUG_NET)
+ /* We plan to no longer reset the transport header here.
+ * Give some time to fuzzers and dev build to catch bugs
+ * in network stacks.
+ */
if (!skb_transport_header_was_set(skb))
skb_reset_transport_header(skb);
+#endif
skb_reset_mac_len(skb);
pt_prev = NULL;
@@ -6291,19 +6346,6 @@ bool napi_complete_done(struct napi_struct *n, int work_done)
}
EXPORT_SYMBOL(napi_complete_done);
-/* must be called under rcu_read_lock(), as we dont take a reference */
-struct napi_struct *napi_by_id(unsigned int napi_id)
-{
- unsigned int hash = napi_id % HASH_SIZE(napi_hash);
- struct napi_struct *napi;
-
- hlist_for_each_entry_rcu(napi, &napi_hash[hash], napi_hash_node)
- if (napi->napi_id == napi_id)
- return napi;
-
- return NULL;
-}
-
static void skb_defer_free_flush(struct softnet_data *sd)
{
struct sk_buff *skb, *next;
@@ -6557,18 +6599,22 @@ static void __napi_hash_add_with_id(struct napi_struct *napi,
static void napi_hash_add_with_id(struct napi_struct *napi,
unsigned int napi_id)
{
- spin_lock(&napi_hash_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&napi_hash_lock, flags);
WARN_ON_ONCE(napi_by_id(napi_id));
__napi_hash_add_with_id(napi, napi_id);
- spin_unlock(&napi_hash_lock);
+ spin_unlock_irqrestore(&napi_hash_lock, flags);
}
static void napi_hash_add(struct napi_struct *napi)
{
+ unsigned long flags;
+
if (test_bit(NAPI_STATE_NO_BUSY_POLL, &napi->state))
return;
- spin_lock(&napi_hash_lock);
+ spin_lock_irqsave(&napi_hash_lock, flags);
/* 0..NR_CPUS range is reserved for sender_cpu use */
do {
@@ -6578,7 +6624,7 @@ static void napi_hash_add(struct napi_struct *napi)
__napi_hash_add_with_id(napi, napi_gen_id);
- spin_unlock(&napi_hash_lock);
+ spin_unlock_irqrestore(&napi_hash_lock, flags);
}
/* Warning : caller is responsible to make sure rcu grace period
@@ -6586,11 +6632,13 @@ static void napi_hash_add(struct napi_struct *napi)
*/
static void napi_hash_del(struct napi_struct *napi)
{
- spin_lock(&napi_hash_lock);
+ unsigned long flags;
+
+ spin_lock_irqsave(&napi_hash_lock, flags);
hlist_del_init_rcu(&napi->napi_hash_node);
- spin_unlock(&napi_hash_lock);
+ spin_unlock_irqrestore(&napi_hash_lock, flags);
}
static enum hrtimer_restart napi_watchdog(struct hrtimer *timer)
@@ -6705,13 +6753,14 @@ static void napi_restore_config(struct napi_struct *n)
n->gro_flush_timeout = n->config->gro_flush_timeout;
n->irq_suspend_timeout = n->config->irq_suspend_timeout;
/* a NAPI ID might be stored in the config, if so use it. if not, use
- * napi_hash_add to generate one for us. It will be saved to the config
- * in napi_disable.
+ * napi_hash_add to generate one for us.
*/
- if (n->config->napi_id)
+ if (n->config->napi_id) {
napi_hash_add_with_id(n, n->config->napi_id);
- else
+ } else {
napi_hash_add(n);
+ n->config->napi_id = n->napi_id;
+ }
}
static void napi_save_config(struct napi_struct *n)
@@ -6719,10 +6768,39 @@ static void napi_save_config(struct napi_struct *n)
n->config->defer_hard_irqs = n->defer_hard_irqs;
n->config->gro_flush_timeout = n->gro_flush_timeout;
n->config->irq_suspend_timeout = n->irq_suspend_timeout;
- n->config->napi_id = n->napi_id;
napi_hash_del(n);
}
+/* Netlink wants the NAPI list to be sorted by ID, if adding a NAPI which will
+ * inherit an existing ID try to insert it at the right position.
+ */
+static void
+netif_napi_dev_list_add(struct net_device *dev, struct napi_struct *napi)
+{
+ unsigned int new_id, pos_id;
+ struct list_head *higher;
+ struct napi_struct *pos;
+
+ new_id = UINT_MAX;
+ if (napi->config && napi->config->napi_id)
+ new_id = napi->config->napi_id;
+
+ higher = &dev->napi_list;
+ list_for_each_entry(pos, &dev->napi_list, dev_list) {
+ if (pos->napi_id >= MIN_NAPI_ID)
+ pos_id = pos->napi_id;
+ else if (pos->config)
+ pos_id = pos->config->napi_id;
+ else
+ pos_id = UINT_MAX;
+
+ if (pos_id <= new_id)
+ break;
+ higher = &pos->dev_list;
+ }
+ list_add_rcu(&napi->dev_list, higher); /* adds after higher */
+}
+
void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
int (*poll)(struct napi_struct *, int), int weight)
{
@@ -6749,7 +6827,7 @@ void netif_napi_add_weight(struct net_device *dev, struct napi_struct *napi,
napi->list_owner = -1;
set_bit(NAPI_STATE_SCHED, &napi->state);
set_bit(NAPI_STATE_NPSVC, &napi->state);
- list_add_rcu(&napi->dev_list, &dev->napi_list);
+ netif_napi_dev_list_add(dev, napi);
/* default settings from sysfs are applied to all NAPIs. any per-NAPI
* configuration will be loaded in napi_enable
@@ -10723,12 +10801,16 @@ EXPORT_SYMBOL_GPL(init_dummy_netdev);
*/
int register_netdev(struct net_device *dev)
{
+ struct net *net = dev_net(dev);
int err;
- if (rtnl_lock_killable())
+ if (rtnl_net_lock_killable(net))
return -EINTR;
+
err = register_netdevice(dev);
- rtnl_unlock();
+
+ rtnl_net_unlock(net);
+
return err;
}
EXPORT_SYMBOL(register_netdev);
@@ -11598,9 +11680,11 @@ EXPORT_SYMBOL(unregister_netdevice_many);
*/
void unregister_netdev(struct net_device *dev)
{
- rtnl_lock();
+ struct net *net = dev_net(dev);
+
+ rtnl_net_lock(net);
unregister_netdevice(dev);
- rtnl_unlock();
+ rtnl_net_unlock(net);
}
EXPORT_SYMBOL(unregister_netdev);
@@ -12146,11 +12230,18 @@ static int net_page_pool_create(int cpuid)
.nid = cpu_to_mem(cpuid),
};
struct page_pool *pp_ptr;
+ int err;
pp_ptr = page_pool_create_percpu(&page_pool_params, cpuid);
if (IS_ERR(pp_ptr))
return -ENOMEM;
+ err = xdp_reg_page_pool(pp_ptr);
+ if (err) {
+ page_pool_destroy(pp_ptr);
+ return err;
+ }
+
per_cpu(system_page_pool, cpuid) = pp_ptr;
#endif
return 0;
@@ -12284,6 +12375,7 @@ out:
if (!pp_ptr)
continue;
+ xdp_unreg_page_pool(pp_ptr);
page_pool_destroy(pp_ptr);
per_cpu(system_page_pool, i) = NULL;
}
diff --git a/net/core/dev.h b/net/core/dev.h
index d043dee25a68..08812a025a9b 100644
--- a/net/core/dev.h
+++ b/net/core/dev.h
@@ -22,6 +22,8 @@ struct sd_flow_limit {
extern int netdev_flow_limit_table_len;
+struct napi_struct *netdev_napi_by_id(struct net *net, unsigned int napi_id);
+
#ifdef CONFIG_PROC_FS
int __init dev_proc_init(void);
#else
@@ -269,7 +271,6 @@ void xdp_do_check_flushed(struct napi_struct *napi);
static inline void xdp_do_check_flushed(struct napi_struct *napi) { }
#endif
-struct napi_struct *napi_by_id(unsigned int napi_id);
void kick_defer_list_purge(struct softnet_data *sd, unsigned int cpu);
#define XMIT_RECURSION_LIMIT 8
@@ -310,5 +311,8 @@ static inline void dev_xmit_recursion_dec(void)
int dev_set_hwtstamp_phylib(struct net_device *dev,
struct kernel_hwtstamp_config *cfg,
struct netlink_ext_ack *extack);
+int dev_get_hwtstamp_phylib(struct net_device *dev,
+ struct kernel_hwtstamp_config *cfg);
+int net_hwtstamp_validate(const struct kernel_hwtstamp_config *cfg);
#endif
diff --git a/net/core/dev_ioctl.c b/net/core/dev_ioctl.c
index 46d43b950471..087a57b7e4fa 100644
--- a/net/core/dev_ioctl.c
+++ b/net/core/dev_ioctl.c
@@ -6,6 +6,7 @@
#include <linux/rtnetlink.h>
#include <linux/net_tstamp.h>
#include <linux/phylib_stubs.h>
+#include <linux/ptp_clock_kernel.h>
#include <linux/wireless.h>
#include <linux/if_bridge.h>
#include <net/dsa_stubs.h>
@@ -184,7 +185,7 @@ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cm
return err;
}
-static int net_hwtstamp_validate(const struct kernel_hwtstamp_config *cfg)
+int net_hwtstamp_validate(const struct kernel_hwtstamp_config *cfg)
{
enum hwtstamp_tx_types tx_type;
enum hwtstamp_rx_filters rx_filter;
@@ -266,9 +267,24 @@ static int dev_eth_ioctl(struct net_device *dev,
* -EOPNOTSUPP for phylib for now, which is still more accurate than letting
* the netdev handle the GET request.
*/
-static int dev_get_hwtstamp_phylib(struct net_device *dev,
- struct kernel_hwtstamp_config *cfg)
+int dev_get_hwtstamp_phylib(struct net_device *dev,
+ struct kernel_hwtstamp_config *cfg)
{
+ struct hwtstamp_provider *hwprov;
+
+ hwprov = rtnl_dereference(dev->hwprov);
+ if (hwprov) {
+ cfg->qualifier = hwprov->desc.qualifier;
+ if (hwprov->source == HWTSTAMP_SOURCE_PHYLIB &&
+ hwprov->phydev)
+ return phy_hwtstamp_get(hwprov->phydev, cfg);
+
+ if (hwprov->source == HWTSTAMP_SOURCE_NETDEV)
+ return dev->netdev_ops->ndo_hwtstamp_get(dev, cfg);
+
+ return -EOPNOTSUPP;
+ }
+
if (phy_is_default_hwtstamp(dev->phydev))
return phy_hwtstamp_get(dev->phydev, cfg);
@@ -324,11 +340,32 @@ int dev_set_hwtstamp_phylib(struct net_device *dev,
struct netlink_ext_ack *extack)
{
const struct net_device_ops *ops = dev->netdev_ops;
- bool phy_ts = phy_is_default_hwtstamp(dev->phydev);
struct kernel_hwtstamp_config old_cfg = {};
+ struct hwtstamp_provider *hwprov;
+ struct phy_device *phydev;
bool changed = false;
+ bool phy_ts;
int err;
+ hwprov = rtnl_dereference(dev->hwprov);
+ if (hwprov) {
+ if (hwprov->source == HWTSTAMP_SOURCE_PHYLIB &&
+ hwprov->phydev) {
+ phy_ts = true;
+ phydev = hwprov->phydev;
+ } else if (hwprov->source == HWTSTAMP_SOURCE_NETDEV) {
+ phy_ts = false;
+ } else {
+ return -EOPNOTSUPP;
+ }
+
+ cfg->qualifier = hwprov->desc.qualifier;
+ } else {
+ phy_ts = phy_is_default_hwtstamp(dev->phydev);
+ if (phy_ts)
+ phydev = dev->phydev;
+ }
+
cfg->source = phy_ts ? HWTSTAMP_SOURCE_PHYLIB : HWTSTAMP_SOURCE_NETDEV;
if (phy_ts && dev->see_all_hwtstamp_requests) {
@@ -350,7 +387,7 @@ int dev_set_hwtstamp_phylib(struct net_device *dev,
changed = kernel_hwtstamp_config_changed(&old_cfg, cfg);
if (phy_ts) {
- err = phy_hwtstamp_set(dev->phydev, cfg, extack);
+ err = phy_hwtstamp_set(phydev, cfg, extack);
if (err) {
if (changed)
ops->ndo_hwtstamp_set(dev, &old_cfg, NULL);
diff --git a/net/core/devmem.c b/net/core/devmem.c
index 11b91c12ee11..0b6ed7525b22 100644
--- a/net/core/devmem.c
+++ b/net/core/devmem.c
@@ -331,11 +331,11 @@ int mp_dmabuf_devmem_init(struct page_pool *pool)
if (!binding)
return -EINVAL;
- if (!pool->dma_map)
- return -EOPNOTSUPP;
-
- if (pool->dma_sync)
- return -EOPNOTSUPP;
+ /* dma-buf dma addresses do not need and should not be used with
+ * dma_sync_for_cpu/device. Force disable dma_sync.
+ */
+ pool->dma_sync = false;
+ pool->dma_sync_for_cpu = false;
if (pool->p.order != 0)
return -E2BIG;
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 34185d138c95..e684ba3ebb38 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -770,6 +770,8 @@ static const struct nla_policy fib_rule_policy[FRA_MAX + 1] = {
[FRA_SPORT_RANGE] = { .len = sizeof(struct fib_rule_port_range) },
[FRA_DPORT_RANGE] = { .len = sizeof(struct fib_rule_port_range) },
[FRA_DSCP] = NLA_POLICY_MAX(NLA_U8, INET_DSCP_MASK >> 2),
+ [FRA_FLOWLABEL] = { .type = NLA_BE32 },
+ [FRA_FLOWLABEL_MASK] = { .type = NLA_BE32 },
};
int fib_nl_newrule(struct sk_buff *skb, struct nlmsghdr *nlh,
diff --git a/net/core/filter.c b/net/core/filter.c
index 6625b3f563a4..b957cf57299e 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3734,13 +3734,22 @@ static const struct bpf_func_proto bpf_skb_adjust_room_proto = {
static u32 __bpf_skb_min_len(const struct sk_buff *skb)
{
- u32 min_len = skb_network_offset(skb);
+ int offset = skb_network_offset(skb);
+ u32 min_len = 0;
- if (skb_transport_header_was_set(skb))
- min_len = skb_transport_offset(skb);
- if (skb->ip_summed == CHECKSUM_PARTIAL)
- min_len = skb_checksum_start_offset(skb) +
- skb->csum_offset + sizeof(__sum16);
+ if (offset > 0)
+ min_len = offset;
+ if (skb_transport_header_was_set(skb)) {
+ offset = skb_transport_offset(skb);
+ if (offset > 0)
+ min_len = offset;
+ }
+ if (skb->ip_summed == CHECKSUM_PARTIAL) {
+ offset = skb_checksum_start_offset(skb) +
+ skb->csum_offset + sizeof(__sum16);
+ if (offset > 0)
+ min_len = offset;
+ }
return min_len;
}
@@ -4119,13 +4128,13 @@ static int bpf_xdp_frags_increase_tail(struct xdp_buff *xdp, int offset)
}
static void bpf_xdp_shrink_data_zc(struct xdp_buff *xdp, int shrink,
- struct xdp_mem_info *mem_info, bool release)
+ enum xdp_mem_type mem_type, bool release)
{
struct xdp_buff *zc_frag = xsk_buff_get_tail(xdp);
if (release) {
xsk_buff_del_tail(zc_frag);
- __xdp_return(NULL, mem_info, false, zc_frag);
+ __xdp_return(0, mem_type, false, zc_frag);
} else {
zc_frag->data_end -= shrink;
}
@@ -4134,19 +4143,16 @@ static void bpf_xdp_shrink_data_zc(struct xdp_buff *xdp, int shrink,
static bool bpf_xdp_shrink_data(struct xdp_buff *xdp, skb_frag_t *frag,
int shrink)
{
- struct xdp_mem_info *mem_info = &xdp->rxq->mem;
+ enum xdp_mem_type mem_type = xdp->rxq->mem.type;
bool release = skb_frag_size(frag) == shrink;
- if (mem_info->type == MEM_TYPE_XSK_BUFF_POOL) {
- bpf_xdp_shrink_data_zc(xdp, shrink, mem_info, release);
+ if (mem_type == MEM_TYPE_XSK_BUFF_POOL) {
+ bpf_xdp_shrink_data_zc(xdp, shrink, mem_type, release);
goto out;
}
- if (release) {
- struct page *page = skb_frag_page(frag);
-
- __xdp_return(page_address(page), mem_info, false, NULL);
- }
+ if (release)
+ __xdp_return(skb_frag_netmem(frag), mem_type, false, NULL);
out:
return release;
@@ -4348,9 +4354,9 @@ u32 xdp_master_redirect(struct xdp_buff *xdp)
EXPORT_SYMBOL_GPL(xdp_master_redirect);
static inline int __xdp_do_redirect_xsk(struct bpf_redirect_info *ri,
- struct net_device *dev,
+ const struct net_device *dev,
struct xdp_buff *xdp,
- struct bpf_prog *xdp_prog)
+ const struct bpf_prog *xdp_prog)
{
enum bpf_map_type map_type = ri->map_type;
void *fwd = ri->tgt_value;
@@ -4371,10 +4377,10 @@ err:
return err;
}
-static __always_inline int __xdp_do_redirect_frame(struct bpf_redirect_info *ri,
- struct net_device *dev,
- struct xdp_frame *xdpf,
- struct bpf_prog *xdp_prog)
+static __always_inline int
+__xdp_do_redirect_frame(struct bpf_redirect_info *ri, struct net_device *dev,
+ struct xdp_frame *xdpf,
+ const struct bpf_prog *xdp_prog)
{
enum bpf_map_type map_type = ri->map_type;
void *fwd = ri->tgt_value;
@@ -4443,7 +4449,7 @@ err:
}
int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
- struct bpf_prog *xdp_prog)
+ const struct bpf_prog *xdp_prog)
{
struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
enum bpf_map_type map_type = ri->map_type;
@@ -4457,7 +4463,8 @@ int xdp_do_redirect(struct net_device *dev, struct xdp_buff *xdp,
EXPORT_SYMBOL_GPL(xdp_do_redirect);
int xdp_do_redirect_frame(struct net_device *dev, struct xdp_buff *xdp,
- struct xdp_frame *xdpf, struct bpf_prog *xdp_prog)
+ struct xdp_frame *xdpf,
+ const struct bpf_prog *xdp_prog)
{
struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
enum bpf_map_type map_type = ri->map_type;
@@ -4472,9 +4479,9 @@ EXPORT_SYMBOL_GPL(xdp_do_redirect_frame);
static int xdp_do_generic_redirect_map(struct net_device *dev,
struct sk_buff *skb,
struct xdp_buff *xdp,
- struct bpf_prog *xdp_prog, void *fwd,
- enum bpf_map_type map_type, u32 map_id,
- u32 flags)
+ const struct bpf_prog *xdp_prog,
+ void *fwd, enum bpf_map_type map_type,
+ u32 map_id, u32 flags)
{
struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
struct bpf_map *map;
@@ -4528,7 +4535,8 @@ err:
}
int xdp_do_generic_redirect(struct net_device *dev, struct sk_buff *skb,
- struct xdp_buff *xdp, struct bpf_prog *xdp_prog)
+ struct xdp_buff *xdp,
+ const struct bpf_prog *xdp_prog)
{
struct bpf_redirect_info *ri = bpf_net_ctx_get_ri();
enum bpf_map_type map_type = ri->map_type;
@@ -7899,42 +7907,37 @@ static const struct bpf_func_proto bpf_tcp_raw_check_syncookie_ipv6_proto = {
#endif /* CONFIG_INET */
-bool bpf_helper_changes_pkt_data(void *func)
-{
- if (func == bpf_skb_vlan_push ||
- func == bpf_skb_vlan_pop ||
- func == bpf_skb_store_bytes ||
- func == bpf_skb_change_proto ||
- func == bpf_skb_change_head ||
- func == sk_skb_change_head ||
- func == bpf_skb_change_tail ||
- func == sk_skb_change_tail ||
- func == bpf_skb_adjust_room ||
- func == sk_skb_adjust_room ||
- func == bpf_skb_pull_data ||
- func == sk_skb_pull_data ||
- func == bpf_clone_redirect ||
- func == bpf_l3_csum_replace ||
- func == bpf_l4_csum_replace ||
- func == bpf_xdp_adjust_head ||
- func == bpf_xdp_adjust_meta ||
- func == bpf_msg_pull_data ||
- func == bpf_msg_push_data ||
- func == bpf_msg_pop_data ||
- func == bpf_xdp_adjust_tail ||
-#if IS_ENABLED(CONFIG_IPV6_SEG6_BPF)
- func == bpf_lwt_seg6_store_bytes ||
- func == bpf_lwt_seg6_adjust_srh ||
- func == bpf_lwt_seg6_action ||
-#endif
-#ifdef CONFIG_INET
- func == bpf_sock_ops_store_hdr_opt ||
-#endif
- func == bpf_lwt_in_push_encap ||
- func == bpf_lwt_xmit_push_encap)
+bool bpf_helper_changes_pkt_data(enum bpf_func_id func_id)
+{
+ switch (func_id) {
+ case BPF_FUNC_clone_redirect:
+ case BPF_FUNC_l3_csum_replace:
+ case BPF_FUNC_l4_csum_replace:
+ case BPF_FUNC_lwt_push_encap:
+ case BPF_FUNC_lwt_seg6_action:
+ case BPF_FUNC_lwt_seg6_adjust_srh:
+ case BPF_FUNC_lwt_seg6_store_bytes:
+ case BPF_FUNC_msg_pop_data:
+ case BPF_FUNC_msg_pull_data:
+ case BPF_FUNC_msg_push_data:
+ case BPF_FUNC_skb_adjust_room:
+ case BPF_FUNC_skb_change_head:
+ case BPF_FUNC_skb_change_proto:
+ case BPF_FUNC_skb_change_tail:
+ case BPF_FUNC_skb_pull_data:
+ case BPF_FUNC_skb_store_bytes:
+ case BPF_FUNC_skb_vlan_pop:
+ case BPF_FUNC_skb_vlan_push:
+ case BPF_FUNC_store_hdr_opt:
+ case BPF_FUNC_xdp_adjust_head:
+ case BPF_FUNC_xdp_adjust_meta:
+ case BPF_FUNC_xdp_adjust_tail:
+ /* tail-called program could call any of the above */
+ case BPF_FUNC_tail_call:
return true;
-
- return false;
+ default:
+ return false;
+ }
}
const struct bpf_func_proto bpf_event_output_data_proto __weak;
@@ -9075,7 +9078,8 @@ static bool xdp_is_valid_access(int off, int size,
return __is_valid_xdp_access(off, size);
}
-void bpf_warn_invalid_xdp_action(struct net_device *dev, struct bpf_prog *prog, u32 act)
+void bpf_warn_invalid_xdp_action(const struct net_device *dev,
+ const struct bpf_prog *prog, u32 act)
{
const u32 act_max = XDP_REDIRECT;
diff --git a/net/core/link_watch.c b/net/core/link_watch.c
index ab150641142a..cb04ef2b9807 100644
--- a/net/core/link_watch.c
+++ b/net/core/link_watch.c
@@ -42,12 +42,21 @@ static unsigned int default_operstate(const struct net_device *dev)
* first check whether lower is indeed the source of its down state.
*/
if (!netif_carrier_ok(dev)) {
- int iflink = dev_get_iflink(dev);
struct net_device *peer;
+ int iflink;
+
+ /* If called from netdev_run_todo()/linkwatch_sync_dev(),
+ * dev_net(dev) can be already freed, and RTNL is not held.
+ */
+ if (dev->reg_state <= NETREG_REGISTERED)
+ iflink = dev_get_iflink(dev);
+ else
+ iflink = dev->ifindex;
if (iflink == dev->ifindex)
return IF_OPER_DOWN;
+ ASSERT_RTNL();
peer = __dev_get_by_index(dev_net(dev), iflink);
if (!peer)
return IF_OPER_DOWN;
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index ae34ac818cda..b5cd3ae4f04c 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -449,6 +449,21 @@ out_free:
goto out;
}
+static LLIST_HEAD(defer_free_list);
+
+static void net_complete_free(void)
+{
+ struct llist_node *kill_list;
+ struct net *net, *next;
+
+ /* Get the list of namespaces to free from last round. */
+ kill_list = llist_del_all(&defer_free_list);
+
+ llist_for_each_entry_safe(net, next, kill_list, defer_free_list)
+ kmem_cache_free(net_cachep, net);
+
+}
+
static void net_free(struct net *net)
{
if (refcount_dec_and_test(&net->passive)) {
@@ -457,7 +472,8 @@ static void net_free(struct net *net)
/* There should not be any trackers left there. */
ref_tracker_dir_exit(&net->notrefcnt_tracker);
- kmem_cache_free(net_cachep, net);
+ /* Wait for an extra rcu_barrier() before final free. */
+ llist_add(&net->defer_free_list, &defer_free_list);
}
}
@@ -642,6 +658,8 @@ static void cleanup_net(struct work_struct *work)
*/
rcu_barrier();
+ net_complete_free();
+
/* Finally it is safe to free my network namespace structure */
list_for_each_entry_safe(net, tmp, &net_exit_list, exit_list) {
list_del_init(&net->exit_list);
diff --git a/net/core/netdev-genl.c b/net/core/netdev-genl.c
index 9527dd46e4dc..a3bdaf075b6b 100644
--- a/net/core/netdev-genl.c
+++ b/net/core/netdev-genl.c
@@ -167,8 +167,6 @@ netdev_nl_napi_fill_one(struct sk_buff *rsp, struct napi_struct *napi,
void *hdr;
pid_t pid;
- if (WARN_ON_ONCE(!napi->dev))
- return -EINVAL;
if (!(napi->dev->flags & IFF_UP))
return 0;
@@ -176,8 +174,7 @@ netdev_nl_napi_fill_one(struct sk_buff *rsp, struct napi_struct *napi,
if (!hdr)
return -EMSGSIZE;
- if (napi->napi_id >= MIN_NAPI_ID &&
- nla_put_u32(rsp, NETDEV_A_NAPI_ID, napi->napi_id))
+ if (nla_put_u32(rsp, NETDEV_A_NAPI_ID, napi->napi_id))
goto nla_put_failure;
if (nla_put_u32(rsp, NETDEV_A_NAPI_IFINDEX, napi->dev->ifindex))
@@ -235,7 +232,7 @@ int netdev_nl_napi_get_doit(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
rcu_read_lock();
- napi = napi_by_id(napi_id);
+ napi = netdev_napi_by_id(genl_info_net(info), napi_id);
if (napi) {
err = netdev_nl_napi_fill_one(rsp, napi, info);
} else {
@@ -246,8 +243,12 @@ int netdev_nl_napi_get_doit(struct sk_buff *skb, struct genl_info *info)
rcu_read_unlock();
rtnl_unlock();
- if (err)
+ if (err) {
goto err_free_msg;
+ } else if (!rsp->len) {
+ err = -ENOENT;
+ goto err_free_msg;
+ }
return genlmsg_reply(rsp, info);
@@ -268,6 +269,8 @@ netdev_nl_napi_dump_one(struct net_device *netdev, struct sk_buff *rsp,
return err;
list_for_each_entry(napi, &netdev->napi_list, dev_list) {
+ if (napi->napi_id < MIN_NAPI_ID)
+ continue;
if (ctx->napi_id && napi->napi_id >= ctx->napi_id)
continue;
@@ -350,7 +353,7 @@ int netdev_nl_napi_set_doit(struct sk_buff *skb, struct genl_info *info)
rtnl_lock();
rcu_read_lock();
- napi = napi_by_id(napi_id);
+ napi = netdev_napi_by_id(genl_info_net(info), napi_id);
if (napi) {
err = netdev_nl_napi_set_config(napi, info);
} else {
@@ -430,10 +433,10 @@ static int
netdev_nl_queue_fill(struct sk_buff *rsp, struct net_device *netdev, u32 q_idx,
u32 q_type, const struct genl_info *info)
{
- int err = 0;
+ int err;
if (!(netdev->flags & IFF_UP))
- return err;
+ return -ENOENT;
err = netdev_nl_queue_validate(netdev, q_idx, q_type);
if (err)
@@ -488,24 +491,21 @@ netdev_nl_queue_dump_one(struct net_device *netdev, struct sk_buff *rsp,
struct netdev_nl_dump_ctx *ctx)
{
int err = 0;
- int i;
if (!(netdev->flags & IFF_UP))
return err;
- for (i = ctx->rxq_idx; i < netdev->real_num_rx_queues;) {
- err = netdev_nl_queue_fill_one(rsp, netdev, i,
+ for (; ctx->rxq_idx < netdev->real_num_rx_queues; ctx->rxq_idx++) {
+ err = netdev_nl_queue_fill_one(rsp, netdev, ctx->rxq_idx,
NETDEV_QUEUE_TYPE_RX, info);
if (err)
return err;
- ctx->rxq_idx = i++;
}
- for (i = ctx->txq_idx; i < netdev->real_num_tx_queues;) {
- err = netdev_nl_queue_fill_one(rsp, netdev, i,
+ for (; ctx->txq_idx < netdev->real_num_tx_queues; ctx->txq_idx++) {
+ err = netdev_nl_queue_fill_one(rsp, netdev, ctx->txq_idx,
NETDEV_QUEUE_TYPE_TX, info);
if (err)
return err;
- ctx->txq_idx = i++;
}
return err;
@@ -671,7 +671,7 @@ netdev_nl_stats_by_queue(struct net_device *netdev, struct sk_buff *rsp,
i, info);
if (err)
return err;
- ctx->rxq_idx = i++;
+ ctx->rxq_idx = ++i;
}
i = ctx->txq_idx;
while (ops->get_queue_stats_tx && i < netdev->real_num_tx_queues) {
@@ -679,7 +679,7 @@ netdev_nl_stats_by_queue(struct net_device *netdev, struct sk_buff *rsp,
i, info);
if (err)
return err;
- ctx->txq_idx = i++;
+ ctx->txq_idx = ++i;
}
ctx->rxq_idx = 0;
diff --git a/net/core/netdev_rx_queue.c b/net/core/netdev_rx_queue.c
index e217a5838c87..db82786fa0c4 100644
--- a/net/core/netdev_rx_queue.c
+++ b/net/core/netdev_rx_queue.c
@@ -79,3 +79,4 @@ err_free_new_mem:
return err;
}
+EXPORT_SYMBOL_NS_GPL(netdev_rx_queue_restart, "NETDEV_INTERNAL");
diff --git a/net/core/page_pool.c b/net/core/page_pool.c
index f89cf93f6eb4..9733206d6406 100644
--- a/net/core/page_pool.c
+++ b/net/core/page_pool.c
@@ -201,6 +201,7 @@ static int page_pool_init(struct page_pool *pool,
memcpy(&pool->slow, &params->slow, sizeof(pool->slow));
pool->cpuid = cpuid;
+ pool->dma_sync_for_cpu = true;
/* Validate only known flags were used */
if (pool->slow.flags & ~PP_FLAG_ALL)
@@ -287,6 +288,9 @@ static int page_pool_init(struct page_pool *pool,
}
if (pool->mp_priv) {
+ if (!pool->dma_map || !pool->dma_sync)
+ return -EOPNOTSUPP;
+
err = mp_dmabuf_devmem_init(pool);
if (err) {
pr_warn("%s() mem-provider init failed %d\n", __func__,
@@ -574,7 +578,7 @@ static noinline netmem_ref __page_pool_alloc_pages_slow(struct page_pool *pool,
/* For using page_pool replace: alloc_pages() API calls, but provide
* synchronization guarantee for allocation side.
*/
-netmem_ref page_pool_alloc_netmem(struct page_pool *pool, gfp_t gfp)
+netmem_ref page_pool_alloc_netmems(struct page_pool *pool, gfp_t gfp)
{
netmem_ref netmem;
@@ -590,11 +594,11 @@ netmem_ref page_pool_alloc_netmem(struct page_pool *pool, gfp_t gfp)
netmem = __page_pool_alloc_pages_slow(pool, gfp);
return netmem;
}
-EXPORT_SYMBOL(page_pool_alloc_netmem);
+EXPORT_SYMBOL(page_pool_alloc_netmems);
struct page *page_pool_alloc_pages(struct page_pool *pool, gfp_t gfp)
{
- return netmem_to_page(page_pool_alloc_netmem(pool, gfp));
+ return netmem_to_page(page_pool_alloc_netmems(pool, gfp));
}
EXPORT_SYMBOL(page_pool_alloc_pages);
ALLOW_ERROR_INJECTION(page_pool_alloc_pages, NULL);
@@ -839,69 +843,104 @@ void page_pool_put_unrefed_page(struct page_pool *pool, struct page *page,
}
EXPORT_SYMBOL(page_pool_put_unrefed_page);
-/**
- * page_pool_put_page_bulk() - release references on multiple pages
- * @pool: pool from which pages were allocated
- * @data: array holding page pointers
- * @count: number of pages in @data
- *
- * Tries to refill a number of pages into the ptr_ring cache holding ptr_ring
- * producer lock. If the ptr_ring is full, page_pool_put_page_bulk()
- * will release leftover pages to the page allocator.
- * page_pool_put_page_bulk() is suitable to be run inside the driver NAPI tx
- * completion loop for the XDP_REDIRECT use case.
- *
- * Please note the caller must not use data area after running
- * page_pool_put_page_bulk(), as this function overwrites it.
- */
-void page_pool_put_page_bulk(struct page_pool *pool, void **data,
- int count)
+static void page_pool_recycle_ring_bulk(struct page_pool *pool,
+ netmem_ref *bulk,
+ u32 bulk_len)
{
- int i, bulk_len = 0;
- bool allow_direct;
bool in_softirq;
+ u32 i;
- allow_direct = page_pool_napi_local(pool);
-
- for (i = 0; i < count; i++) {
- netmem_ref netmem = page_to_netmem(virt_to_head_page(data[i]));
-
- /* It is not the last user for the page frag case */
- if (!page_pool_is_last_ref(netmem))
- continue;
-
- netmem = __page_pool_put_page(pool, netmem, -1, allow_direct);
- /* Approved for bulk recycling in ptr_ring cache */
- if (netmem)
- data[bulk_len++] = (__force void *)netmem;
- }
-
- if (!bulk_len)
- return;
-
- /* Bulk producer into ptr_ring page_pool cache */
+ /* Bulk produce into ptr_ring page_pool cache */
in_softirq = page_pool_producer_lock(pool);
+
for (i = 0; i < bulk_len; i++) {
- if (__ptr_ring_produce(&pool->ring, data[i])) {
+ if (__ptr_ring_produce(&pool->ring, (__force void *)bulk[i])) {
/* ring full */
recycle_stat_inc(pool, ring_full);
break;
}
}
- recycle_stat_add(pool, ring, i);
+
page_pool_producer_unlock(pool, in_softirq);
+ recycle_stat_add(pool, ring, i);
- /* Hopefully all pages was return into ptr_ring */
+ /* Hopefully all pages were returned into ptr_ring */
if (likely(i == bulk_len))
return;
- /* ptr_ring cache full, free remaining pages outside producer lock
- * since put_page() with refcnt == 1 can be an expensive operation
+ /*
+ * ptr_ring cache is full, free remaining pages outside producer lock
+ * since put_page() with refcnt == 1 can be an expensive operation.
*/
for (; i < bulk_len; i++)
- page_pool_return_page(pool, (__force netmem_ref)data[i]);
+ page_pool_return_page(pool, bulk[i]);
+}
+
+/**
+ * page_pool_put_netmem_bulk() - release references on multiple netmems
+ * @data: array holding netmem references
+ * @count: number of entries in @data
+ *
+ * Tries to refill a number of netmems into the ptr_ring cache holding ptr_ring
+ * producer lock. If the ptr_ring is full, page_pool_put_netmem_bulk()
+ * will release leftover netmems to the memory provider.
+ * page_pool_put_netmem_bulk() is suitable to be run inside the driver NAPI tx
+ * completion loop for the XDP_REDIRECT use case.
+ *
+ * Please note the caller must not use data area after running
+ * page_pool_put_netmem_bulk(), as this function overwrites it.
+ */
+void page_pool_put_netmem_bulk(netmem_ref *data, u32 count)
+{
+ u32 bulk_len = 0;
+
+ for (u32 i = 0; i < count; i++) {
+ netmem_ref netmem = netmem_compound_head(data[i]);
+
+ if (page_pool_unref_and_test(netmem))
+ data[bulk_len++] = netmem;
+ }
+
+ count = bulk_len;
+ while (count) {
+ netmem_ref bulk[XDP_BULK_QUEUE_SIZE];
+ struct page_pool *pool = NULL;
+ bool allow_direct;
+ u32 foreign = 0;
+
+ bulk_len = 0;
+
+ for (u32 i = 0; i < count; i++) {
+ struct page_pool *netmem_pp;
+ netmem_ref netmem = data[i];
+
+ netmem_pp = netmem_get_pp(netmem);
+ if (unlikely(!pool)) {
+ pool = netmem_pp;
+ allow_direct = page_pool_napi_local(pool);
+ } else if (netmem_pp != pool) {
+ /*
+ * If the netmem belongs to a different
+ * page_pool, save it for another round.
+ */
+ data[foreign++] = netmem;
+ continue;
+ }
+
+ netmem = __page_pool_put_page(pool, netmem, -1,
+ allow_direct);
+ /* Approved for bulk recycling in ptr_ring cache */
+ if (netmem)
+ bulk[bulk_len++] = netmem;
+ }
+
+ if (bulk_len)
+ page_pool_recycle_ring_bulk(pool, bulk, bulk_len);
+
+ count = foreign;
+ }
}
-EXPORT_SYMBOL(page_pool_put_page_bulk);
+EXPORT_SYMBOL(page_pool_put_netmem_bulk);
static netmem_ref page_pool_drain_frag(struct page_pool *pool,
netmem_ref netmem)
@@ -957,7 +996,7 @@ netmem_ref page_pool_alloc_frag_netmem(struct page_pool *pool,
}
if (!netmem) {
- netmem = page_pool_alloc_netmem(pool, gfp);
+ netmem = page_pool_alloc_netmems(pool, gfp);
if (unlikely(!netmem)) {
pool->frag_page = 0;
return 0;
diff --git a/net/core/pktgen.c b/net/core/pktgen.c
index 7e23cacbe66e..ee95dbb0539a 100644
--- a/net/core/pktgen.c
+++ b/net/core/pktgen.c
@@ -3883,17 +3883,14 @@ static int __net_init pktgen_create_thread(int cpu, struct pktgen_net *pn)
list_add_tail(&t->th_list, &pn->pktgen_threads);
init_completion(&t->start_done);
- p = kthread_create_on_node(pktgen_thread_worker,
- t,
- cpu_to_node(cpu),
- "kpktgend_%d", cpu);
+ p = kthread_create_on_cpu(pktgen_thread_worker, t, cpu, "kpktgend_%d");
if (IS_ERR(p)) {
pr_err("kthread_create_on_node() failed for cpu %d\n", t->cpu);
list_del(&t->th_list);
kfree(t);
return PTR_ERR(p);
}
- kthread_bind(p, cpu);
+
t->tsk = p;
pe = proc_create_data(t->tsk->comm, 0600, pn->proc_dir,
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c
index 58df76fe408a..1f4d4b5570ab 100644
--- a/net/core/rtnetlink.c
+++ b/net/core/rtnetlink.c
@@ -84,7 +84,6 @@ int rtnl_lock_killable(void)
{
return mutex_lock_killable(&rtnl_mutex);
}
-EXPORT_SYMBOL(rtnl_lock_killable);
static struct sk_buff *defer_kfree_skb_list;
void rtnl_kfree_skbs(struct sk_buff *head, struct sk_buff *tail)
@@ -221,6 +220,16 @@ int rtnl_net_trylock(struct net *net)
}
EXPORT_SYMBOL(rtnl_net_trylock);
+int rtnl_net_lock_killable(struct net *net)
+{
+ int ret = rtnl_lock_killable();
+
+ if (!ret)
+ __rtnl_net_lock(net);
+
+ return ret;
+}
+
static int rtnl_net_cmp_locks(const struct net *net_a, const struct net *net_b)
{
if (net_eq(net_a, net_b))
@@ -3746,6 +3755,7 @@ static int rtnl_group_changelink(const struct sk_buff *skb,
static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm,
const struct rtnl_link_ops *ops,
struct net *tgt_net, struct net *link_net,
+ struct net *peer_net,
const struct nlmsghdr *nlh,
struct nlattr **tb, struct nlattr **data,
struct netlink_ext_ack *extack)
@@ -3776,8 +3786,13 @@ static int rtnl_newlink_create(struct sk_buff *skb, struct ifinfomsg *ifm,
dev->ifindex = ifm->ifi_index;
+ if (link_net)
+ net = link_net;
+ if (peer_net)
+ net = peer_net;
+
if (ops->newlink)
- err = ops->newlink(link_net ? : net, dev, tb, data, extack);
+ err = ops->newlink(net, dev, tb, data, extack);
else
err = register_netdevice(dev);
if (err < 0) {
@@ -3812,40 +3827,34 @@ out_unregister:
goto out;
}
-static int rtnl_add_peer_net(struct rtnl_nets *rtnl_nets,
- const struct rtnl_link_ops *ops,
- struct nlattr *data[],
- struct netlink_ext_ack *extack)
+static struct net *rtnl_get_peer_net(const struct rtnl_link_ops *ops,
+ struct nlattr *tbp[],
+ struct nlattr *data[],
+ struct netlink_ext_ack *extack)
{
struct nlattr *tb[IFLA_MAX + 1];
- struct net *net;
int err;
if (!data || !data[ops->peer_type])
- return 0;
+ return rtnl_link_get_net_ifla(tbp);
err = rtnl_nla_parse_ifinfomsg(tb, data[ops->peer_type], extack);
if (err < 0)
- return err;
+ return ERR_PTR(err);
if (ops->validate) {
err = ops->validate(tb, NULL, extack);
if (err < 0)
- return err;
+ return ERR_PTR(err);
}
- net = rtnl_link_get_net_ifla(tb);
- if (IS_ERR(net))
- return PTR_ERR(net);
- if (net)
- rtnl_nets_add(rtnl_nets, net);
-
- return 0;
+ return rtnl_link_get_net_ifla(tb);
}
static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
const struct rtnl_link_ops *ops,
struct net *tgt_net, struct net *link_net,
+ struct net *peer_net,
struct rtnl_newlink_tbs *tbs,
struct nlattr **data,
struct netlink_ext_ack *extack)
@@ -3894,14 +3903,15 @@ static int __rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
return -EOPNOTSUPP;
}
- return rtnl_newlink_create(skb, ifm, ops, tgt_net, link_net, nlh, tb, data, extack);
+ return rtnl_newlink_create(skb, ifm, ops, tgt_net, link_net, peer_net, nlh,
+ tb, data, extack);
}
static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
struct netlink_ext_ack *extack)
{
+ struct net *tgt_net, *link_net = NULL, *peer_net = NULL;
struct nlattr **tb, **linkinfo, **data = NULL;
- struct net *tgt_net, *link_net = NULL;
struct rtnl_link_ops *ops = NULL;
struct rtnl_newlink_tbs *tbs;
struct rtnl_nets rtnl_nets;
@@ -3971,9 +3981,13 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
}
if (ops->peer_type) {
- ret = rtnl_add_peer_net(&rtnl_nets, ops, data, extack);
- if (ret < 0)
+ peer_net = rtnl_get_peer_net(ops, tb, data, extack);
+ if (IS_ERR(peer_net)) {
+ ret = PTR_ERR(peer_net);
goto put_ops;
+ }
+ if (peer_net)
+ rtnl_nets_add(&rtnl_nets, peer_net);
}
}
@@ -4004,7 +4018,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh,
}
rtnl_nets_lock(&rtnl_nets);
- ret = __rtnl_newlink(skb, nlh, ops, tgt_net, link_net, tbs, data, extack);
+ ret = __rtnl_newlink(skb, nlh, ops, tgt_net, link_net, peer_net, tbs, data, extack);
rtnl_nets_unlock(&rtnl_nets);
put_net:
@@ -4760,15 +4774,16 @@ static int nlmsg_populate_fdb(struct sk_buff *skb,
int *idx,
struct netdev_hw_addr_list *list)
{
+ struct ndo_fdb_dump_context *ctx = (void *)cb->ctx;
struct netdev_hw_addr *ha;
- int err;
u32 portid, seq;
+ int err;
portid = NETLINK_CB(cb->skb).portid;
seq = cb->nlh->nlmsg_seq;
list_for_each_entry(ha, &list->list, list) {
- if (*idx < cb->args[2])
+ if (*idx < ctx->fdb_idx)
goto skip;
err = nlmsg_populate_fdb_fill(skb, dev, ha->addr, 0,
@@ -4907,18 +4922,16 @@ static int valid_fdb_dump_legacy(const struct nlmsghdr *nlh,
static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
{
- struct net_device *dev;
- struct net_device *br_dev = NULL;
- const struct net_device_ops *ops = NULL;
- const struct net_device_ops *cops = NULL;
+ const struct net_device_ops *ops = NULL, *cops = NULL;
+ struct ndo_fdb_dump_context *ctx = (void *)cb->ctx;
+ struct net_device *dev, *br_dev = NULL;
struct net *net = sock_net(skb->sk);
- struct hlist_head *head;
int brport_idx = 0;
int br_idx = 0;
- int h, s_h;
- int idx = 0, s_idx;
- int err = 0;
int fidx = 0;
+ int err;
+
+ NL_ASSERT_CTX_FITS(struct ndo_fdb_dump_context);
if (cb->strict_check)
err = valid_fdb_dump_strict(cb->nlh, &br_idx, &brport_idx,
@@ -4937,70 +4950,51 @@ static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb)
ops = br_dev->netdev_ops;
}
- s_h = cb->args[0];
- s_idx = cb->args[1];
-
- for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) {
- idx = 0;
- head = &net->dev_index_head[h];
- hlist_for_each_entry(dev, head, index_hlist) {
-
- if (brport_idx && (dev->ifindex != brport_idx))
- continue;
-
- if (!br_idx) { /* user did not specify a specific bridge */
- if (netif_is_bridge_port(dev)) {
- br_dev = netdev_master_upper_dev_get(dev);
- cops = br_dev->netdev_ops;
- }
- } else {
- if (dev != br_dev &&
- !netif_is_bridge_port(dev))
- continue;
+ for_each_netdev_dump(net, dev, ctx->ifindex) {
+ if (brport_idx && (dev->ifindex != brport_idx))
+ continue;
- if (br_dev != netdev_master_upper_dev_get(dev) &&
- !netif_is_bridge_master(dev))
- continue;
- cops = ops;
+ if (!br_idx) { /* user did not specify a specific bridge */
+ if (netif_is_bridge_port(dev)) {
+ br_dev = netdev_master_upper_dev_get(dev);
+ cops = br_dev->netdev_ops;
}
+ } else {
+ if (dev != br_dev &&
+ !netif_is_bridge_port(dev))
+ continue;
- if (idx < s_idx)
- goto cont;
+ if (br_dev != netdev_master_upper_dev_get(dev) &&
+ !netif_is_bridge_master(dev))
+ continue;
+ cops = ops;
+ }
- if (netif_is_bridge_port(dev)) {
- if (cops && cops->ndo_fdb_dump) {
- err = cops->ndo_fdb_dump(skb, cb,
- br_dev, dev,
- &fidx);
- if (err == -EMSGSIZE)
- goto out;
- }
+ if (netif_is_bridge_port(dev)) {
+ if (cops && cops->ndo_fdb_dump) {
+ err = cops->ndo_fdb_dump(skb, cb, br_dev, dev,
+ &fidx);
+ if (err == -EMSGSIZE)
+ break;
}
+ }
- if (dev->netdev_ops->ndo_fdb_dump)
- err = dev->netdev_ops->ndo_fdb_dump(skb, cb,
- dev, NULL,
- &fidx);
- else
- err = ndo_dflt_fdb_dump(skb, cb, dev, NULL,
- &fidx);
- if (err == -EMSGSIZE)
- goto out;
+ if (dev->netdev_ops->ndo_fdb_dump)
+ err = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, NULL,
+ &fidx);
+ else
+ err = ndo_dflt_fdb_dump(skb, cb, dev, NULL, &fidx);
+ if (err == -EMSGSIZE)
+ break;
- cops = NULL;
+ cops = NULL;
- /* reset fdb offset to 0 for rest of the interfaces */
- cb->args[2] = 0;
- fidx = 0;
-cont:
- idx++;
- }
+ /* reset fdb offset to 0 for rest of the interfaces */
+ ctx->fdb_idx = 0;
+ fidx = 0;
}
-out:
- cb->args[0] = h;
- cb->args[1] = idx;
- cb->args[2] = fidx;
+ ctx->fdb_idx = fidx;
return skb->len;
}
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 6841e61a6bd0..a441613a1e6c 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1009,7 +1009,7 @@ int skb_pp_cow_data(struct page_pool *pool, struct sk_buff **pskb,
EXPORT_SYMBOL(skb_pp_cow_data);
int skb_cow_data_for_xdp(struct page_pool *pool, struct sk_buff **pskb,
- struct bpf_prog *prog)
+ const struct bpf_prog *prog)
{
if (!prog->aux->xdp_has_frags)
return -EINVAL;
diff --git a/net/core/skmsg.c b/net/core/skmsg.c
index e90fbab703b2..61f3f3d4e528 100644
--- a/net/core/skmsg.c
+++ b/net/core/skmsg.c
@@ -369,8 +369,8 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,
struct sk_msg *msg, u32 bytes)
{
int ret = -ENOSPC, i = msg->sg.curr;
+ u32 copy, buf_size, copied = 0;
struct scatterlist *sge;
- u32 copy, buf_size;
void *to;
do {
@@ -397,6 +397,7 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,
goto out;
}
bytes -= copy;
+ copied += copy;
if (!bytes)
break;
msg->sg.copybreak = 0;
@@ -404,7 +405,7 @@ int sk_msg_memcopy_from_iter(struct sock *sk, struct iov_iter *from,
} while (i != msg->sg.end);
out:
msg->sg.curr = i;
- return ret;
+ return (ret < 0) ? ret : copied;
}
EXPORT_SYMBOL_GPL(sk_msg_memcopy_from_iter);
@@ -445,8 +446,10 @@ int sk_msg_recvmsg(struct sock *sk, struct sk_psock *psock, struct msghdr *msg,
if (likely(!peek)) {
sge->offset += copy;
sge->length -= copy;
- if (!msg_rx->skb)
+ if (!msg_rx->skb) {
sk_mem_uncharge(sk, copy);
+ atomic_sub(copy, &sk->sk_rmem_alloc);
+ }
msg_rx->sg.size -= copy;
if (!sge->length) {
@@ -772,6 +775,8 @@ static void __sk_psock_purge_ingress_msg(struct sk_psock *psock)
list_for_each_entry_safe(msg, tmp, &psock->ingress_msg, list) {
list_del(&msg->list);
+ if (!msg->skb)
+ atomic_sub(msg->sg.size, &psock->sk->sk_rmem_alloc);
sk_msg_free(psock->sk, msg);
kfree(msg);
}
diff --git a/net/core/sock.c b/net/core/sock.c
index 74729d20cd00..eae2ae70a2e0 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -454,6 +454,13 @@ static int sock_set_timeout(long *timeo_p, sockptr_t optval, int optlen,
return 0;
}
+static bool sk_set_prio_allowed(const struct sock *sk, int val)
+{
+ return ((val >= TC_PRIO_BESTEFFORT && val <= TC_PRIO_INTERACTIVE) ||
+ sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) ||
+ sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN));
+}
+
static bool sock_needs_netstamp(const struct sock *sk)
{
switch (sk->sk_family) {
@@ -1193,9 +1200,7 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
/* handle options which do not require locking the socket. */
switch (optname) {
case SO_PRIORITY:
- if ((val >= 0 && val <= 6) ||
- sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_RAW) ||
- sockopt_ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN)) {
+ if (sk_set_prio_allowed(sk, val)) {
sock_set_priority(sk, val);
return 0;
}
@@ -1295,7 +1300,10 @@ int sk_setsockopt(struct sock *sk, int level, int optname,
sk->sk_reuse = (valbool ? SK_CAN_REUSE : SK_NO_REUSE);
break;
case SO_REUSEPORT:
- sk->sk_reuseport = valbool;
+ if (valbool && !sk_is_inet(sk))
+ ret = -EOPNOTSUPP;
+ else
+ sk->sk_reuseport = valbool;
break;
case SO_DONTROUTE:
sock_valbool_flag(sk, SOCK_LOCALROUTE, valbool);
@@ -1514,6 +1522,10 @@ set_sndbuf:
sock_valbool_flag(sk, SOCK_RCVMARK, valbool);
break;
+ case SO_RCVPRIORITY:
+ sock_valbool_flag(sk, SOCK_RCVPRIORITY, valbool);
+ break;
+
case SO_RXQ_OVFL:
sock_valbool_flag(sk, SOCK_RXQ_OVFL, valbool);
break;
@@ -1942,6 +1954,10 @@ int sk_getsockopt(struct sock *sk, int level, int optname,
v.val = sock_flag(sk, SOCK_RCVMARK);
break;
+ case SO_RCVPRIORITY:
+ v.val = sock_flag(sk, SOCK_RCVPRIORITY);
+ break;
+
case SO_RXQ_OVFL:
v.val = sock_flag(sk, SOCK_RXQ_OVFL);
break;
@@ -2942,6 +2958,13 @@ int __sock_cmsg_send(struct sock *sk, struct cmsghdr *cmsg,
case SCM_RIGHTS:
case SCM_CREDENTIALS:
break;
+ case SO_PRIORITY:
+ if (cmsg->cmsg_len != CMSG_LEN(sizeof(u32)))
+ return -EINVAL;
+ if (!sk_set_prio_allowed(sk, *(u32 *)CMSG_DATA(cmsg)))
+ return -EPERM;
+ sockc->priority = *(u32 *)CMSG_DATA(cmsg);
+ break;
default:
return -EINVAL;
}
diff --git a/net/core/sock_map.c b/net/core/sock_map.c
index 78347d7d25ef..f1b9b3958792 100644
--- a/net/core/sock_map.c
+++ b/net/core/sock_map.c
@@ -159,6 +159,7 @@ static void sock_map_del_link(struct sock *sk,
verdict_stop = true;
list_del(&link->list);
sk_psock_free_link(link);
+ break;
}
}
spin_unlock_bh(&psock->link_lock);
@@ -411,12 +412,11 @@ static void *sock_map_lookup_sys(struct bpf_map *map, void *key)
static int __sock_map_delete(struct bpf_stab *stab, struct sock *sk_test,
struct sock **psk)
{
- struct sock *sk;
+ struct sock *sk = NULL;
int err = 0;
spin_lock_bh(&stab->lock);
- sk = *psk;
- if (!sk_test || sk_test == sk)
+ if (!sk_test || sk_test == *psk)
sk = xchg(psk, NULL);
if (likely(sk))
diff --git a/net/core/timestamping.c b/net/core/timestamping.c
index 3717fb152ecc..a50a7ef49ae8 100644
--- a/net/core/timestamping.c
+++ b/net/core/timestamping.c
@@ -9,6 +9,7 @@
#include <linux/ptp_classify.h>
#include <linux/skbuff.h>
#include <linux/export.h>
+#include <linux/ptp_clock_kernel.h>
static unsigned int classify(const struct sk_buff *skb)
{
@@ -21,19 +22,39 @@ static unsigned int classify(const struct sk_buff *skb)
void skb_clone_tx_timestamp(struct sk_buff *skb)
{
+ struct hwtstamp_provider *hwprov;
struct mii_timestamper *mii_ts;
+ struct phy_device *phydev;
struct sk_buff *clone;
unsigned int type;
- if (!skb->sk || !skb->dev ||
- !phy_is_default_hwtstamp(skb->dev->phydev))
+ if (!skb->sk || !skb->dev)
return;
+ rcu_read_lock();
+ hwprov = rcu_dereference(skb->dev->hwprov);
+ if (hwprov) {
+ if (hwprov->source != HWTSTAMP_SOURCE_PHYLIB ||
+ !hwprov->phydev) {
+ rcu_read_unlock();
+ return;
+ }
+
+ phydev = hwprov->phydev;
+ } else {
+ phydev = skb->dev->phydev;
+ if (!phy_is_default_hwtstamp(phydev)) {
+ rcu_read_unlock();
+ return;
+ }
+ }
+ rcu_read_unlock();
+
type = classify(skb);
if (type == PTP_CLASS_NONE)
return;
- mii_ts = skb->dev->phydev->mii_ts;
+ mii_ts = phydev->mii_ts;
if (likely(mii_ts->txtstamp)) {
clone = skb_clone_sk(skb);
if (!clone)
@@ -45,12 +66,33 @@ EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp);
bool skb_defer_rx_timestamp(struct sk_buff *skb)
{
+ struct hwtstamp_provider *hwprov;
struct mii_timestamper *mii_ts;
+ struct phy_device *phydev;
unsigned int type;
- if (!skb->dev || !phy_is_default_hwtstamp(skb->dev->phydev))
+ if (!skb->dev)
return false;
+ rcu_read_lock();
+ hwprov = rcu_dereference(skb->dev->hwprov);
+ if (hwprov) {
+ if (hwprov->source != HWTSTAMP_SOURCE_PHYLIB ||
+ !hwprov->phydev) {
+ rcu_read_unlock();
+ return false;
+ }
+
+ phydev = hwprov->phydev;
+ } else {
+ phydev = skb->dev->phydev;
+ if (!phy_is_default_hwtstamp(phydev)) {
+ rcu_read_unlock();
+ return false;
+ }
+ }
+ rcu_read_unlock();
+
if (skb_headroom(skb) < ETH_HLEN)
return false;
@@ -63,7 +105,7 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb)
if (type == PTP_CLASS_NONE)
return false;
- mii_ts = skb->dev->phydev->mii_ts;
+ mii_ts = phydev->mii_ts;
if (likely(mii_ts->rxtstamp))
return mii_ts->rxtstamp(mii_ts, skb, type);
diff --git a/net/core/xdp.c b/net/core/xdp.c
index bcc5551c6424..67b53fc7191e 100644
--- a/net/core/xdp.c
+++ b/net/core/xdp.c
@@ -358,6 +358,9 @@ int xdp_rxq_info_reg_mem_model(struct xdp_rxq_info *xdp_rxq,
if (IS_ERR(xdp_alloc))
return PTR_ERR(xdp_alloc);
+ if (type == MEM_TYPE_XSK_BUFF_POOL && allocator)
+ xsk_pool_set_rxq_info(allocator, xdp_rxq);
+
if (trace_mem_connect_enabled() && xdp_alloc)
trace_mem_connect(xdp_alloc, xdp_rxq);
return 0;
@@ -365,33 +368,87 @@ int xdp_rxq_info_reg_mem_model(struct xdp_rxq_info *xdp_rxq,
EXPORT_SYMBOL_GPL(xdp_rxq_info_reg_mem_model);
+/**
+ * xdp_reg_page_pool - register &page_pool as a memory provider for XDP
+ * @pool: &page_pool to register
+ *
+ * Can be used to register pools manually without connecting to any XDP RxQ
+ * info, so that the XDP layer will be aware of them. Then, they can be
+ * attached to an RxQ info manually via xdp_rxq_info_attach_page_pool().
+ *
+ * Return: %0 on success, -errno on error.
+ */
+int xdp_reg_page_pool(struct page_pool *pool)
+{
+ struct xdp_mem_info mem;
+
+ return xdp_reg_mem_model(&mem, MEM_TYPE_PAGE_POOL, pool);
+}
+EXPORT_SYMBOL_GPL(xdp_reg_page_pool);
+
+/**
+ * xdp_unreg_page_pool - unregister &page_pool from the memory providers list
+ * @pool: &page_pool to unregister
+ *
+ * A shorthand for manual unregistering page pools. If the pool was previously
+ * attached to an RxQ info, it must be detached first.
+ */
+void xdp_unreg_page_pool(const struct page_pool *pool)
+{
+ struct xdp_mem_info mem = {
+ .type = MEM_TYPE_PAGE_POOL,
+ .id = pool->xdp_mem_id,
+ };
+
+ xdp_unreg_mem_model(&mem);
+}
+EXPORT_SYMBOL_GPL(xdp_unreg_page_pool);
+
+/**
+ * xdp_rxq_info_attach_page_pool - attach registered pool to RxQ info
+ * @xdp_rxq: XDP RxQ info to attach the pool to
+ * @pool: pool to attach
+ *
+ * If the pool was registered manually, this function must be called instead
+ * of xdp_rxq_info_reg_mem_model() to connect it to the RxQ info.
+ */
+void xdp_rxq_info_attach_page_pool(struct xdp_rxq_info *xdp_rxq,
+ const struct page_pool *pool)
+{
+ struct xdp_mem_info mem = {
+ .type = MEM_TYPE_PAGE_POOL,
+ .id = pool->xdp_mem_id,
+ };
+
+ xdp_rxq_info_attach_mem_model(xdp_rxq, &mem);
+}
+EXPORT_SYMBOL_GPL(xdp_rxq_info_attach_page_pool);
+
/* XDP RX runs under NAPI protection, and in different delivery error
* scenarios (e.g. queue full), it is possible to return the xdp_frame
* while still leveraging this protection. The @napi_direct boolean
* is used for those calls sites. Thus, allowing for faster recycling
* of xdp_frames/pages in those cases.
*/
-void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
- struct xdp_buff *xdp)
+void __xdp_return(netmem_ref netmem, enum xdp_mem_type mem_type,
+ bool napi_direct, struct xdp_buff *xdp)
{
- struct page *page;
-
- switch (mem->type) {
+ switch (mem_type) {
case MEM_TYPE_PAGE_POOL:
- page = virt_to_head_page(data);
+ netmem = netmem_compound_head(netmem);
if (napi_direct && xdp_return_frame_no_direct())
napi_direct = false;
/* No need to check ((page->pp_magic & ~0x3UL) == PP_SIGNATURE)
* as mem->type knows this a page_pool page
*/
- page_pool_put_full_page(page->pp, page, napi_direct);
+ page_pool_put_full_netmem(netmem_get_pp(netmem), netmem,
+ napi_direct);
break;
case MEM_TYPE_PAGE_SHARED:
- page_frag_free(data);
+ page_frag_free(__netmem_address(netmem));
break;
case MEM_TYPE_PAGE_ORDER0:
- page = virt_to_page(data); /* Assumes order0 page*/
- put_page(page);
+ put_page(__netmem_to_page(netmem));
break;
case MEM_TYPE_XSK_BUFF_POOL:
/* NB! Only valid from an xdp_buff! */
@@ -399,7 +456,7 @@ void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
break;
default:
/* Not possible, checked in xdp_rxq_info_reg_mem_model() */
- WARN(1, "Incorrect XDP memory type (%d) usage", mem->type);
+ WARN(1, "Incorrect XDP memory type (%d) usage", mem_type);
break;
}
}
@@ -407,38 +464,34 @@ void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct,
void xdp_return_frame(struct xdp_frame *xdpf)
{
struct skb_shared_info *sinfo;
- int i;
if (likely(!xdp_frame_has_frags(xdpf)))
goto out;
sinfo = xdp_get_shared_info_from_frame(xdpf);
- for (i = 0; i < sinfo->nr_frags; i++) {
- struct page *page = skb_frag_page(&sinfo->frags[i]);
+ for (u32 i = 0; i < sinfo->nr_frags; i++)
+ __xdp_return(skb_frag_netmem(&sinfo->frags[i]), xdpf->mem_type,
+ false, NULL);
- __xdp_return(page_address(page), &xdpf->mem, false, NULL);
- }
out:
- __xdp_return(xdpf->data, &xdpf->mem, false, NULL);
+ __xdp_return(virt_to_netmem(xdpf->data), xdpf->mem_type, false, NULL);
}
EXPORT_SYMBOL_GPL(xdp_return_frame);
void xdp_return_frame_rx_napi(struct xdp_frame *xdpf)
{
struct skb_shared_info *sinfo;
- int i;
if (likely(!xdp_frame_has_frags(xdpf)))
goto out;
sinfo = xdp_get_shared_info_from_frame(xdpf);
- for (i = 0; i < sinfo->nr_frags; i++) {
- struct page *page = skb_frag_page(&sinfo->frags[i]);
+ for (u32 i = 0; i < sinfo->nr_frags; i++)
+ __xdp_return(skb_frag_netmem(&sinfo->frags[i]), xdpf->mem_type,
+ true, NULL);
- __xdp_return(page_address(page), &xdpf->mem, true, NULL);
- }
out:
- __xdp_return(xdpf->data, &xdpf->mem, true, NULL);
+ __xdp_return(virt_to_netmem(xdpf->data), xdpf->mem_type, true, NULL);
}
EXPORT_SYMBOL_GPL(xdp_return_frame_rx_napi);
@@ -452,46 +505,19 @@ EXPORT_SYMBOL_GPL(xdp_return_frame_rx_napi);
* xdp_frame_bulk is usually stored/allocated on the function
* call-stack to avoid locking penalties.
*/
-void xdp_flush_frame_bulk(struct xdp_frame_bulk *bq)
-{
- struct xdp_mem_allocator *xa = bq->xa;
-
- if (unlikely(!xa || !bq->count))
- return;
-
- page_pool_put_page_bulk(xa->page_pool, bq->q, bq->count);
- /* bq->xa is not cleared to save lookup, if mem.id same in next bulk */
- bq->count = 0;
-}
-EXPORT_SYMBOL_GPL(xdp_flush_frame_bulk);
/* Must be called with rcu_read_lock held */
void xdp_return_frame_bulk(struct xdp_frame *xdpf,
struct xdp_frame_bulk *bq)
{
- struct xdp_mem_info *mem = &xdpf->mem;
- struct xdp_mem_allocator *xa;
-
- if (mem->type != MEM_TYPE_PAGE_POOL) {
+ if (xdpf->mem_type != MEM_TYPE_PAGE_POOL) {
xdp_return_frame(xdpf);
return;
}
- xa = bq->xa;
- if (unlikely(!xa)) {
- xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
- bq->count = 0;
- bq->xa = xa;
- }
-
if (bq->count == XDP_BULK_QUEUE_SIZE)
xdp_flush_frame_bulk(bq);
- if (unlikely(mem->id != xa->mem.id)) {
- xdp_flush_frame_bulk(bq);
- bq->xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params);
- }
-
if (unlikely(xdp_frame_has_frags(xdpf))) {
struct skb_shared_info *sinfo;
int i;
@@ -500,31 +526,40 @@ void xdp_return_frame_bulk(struct xdp_frame *xdpf,
for (i = 0; i < sinfo->nr_frags; i++) {
skb_frag_t *frag = &sinfo->frags[i];
- bq->q[bq->count++] = skb_frag_address(frag);
+ bq->q[bq->count++] = skb_frag_netmem(frag);
if (bq->count == XDP_BULK_QUEUE_SIZE)
xdp_flush_frame_bulk(bq);
}
}
- bq->q[bq->count++] = xdpf->data;
+ bq->q[bq->count++] = virt_to_netmem(xdpf->data);
}
EXPORT_SYMBOL_GPL(xdp_return_frame_bulk);
+/**
+ * xdp_return_frag -- free one XDP frag or decrement its refcount
+ * @netmem: network memory reference to release
+ * @xdp: &xdp_buff to release the frag for
+ */
+void xdp_return_frag(netmem_ref netmem, const struct xdp_buff *xdp)
+{
+ __xdp_return(netmem, xdp->rxq->mem.type, true, NULL);
+}
+EXPORT_SYMBOL_GPL(xdp_return_frag);
+
void xdp_return_buff(struct xdp_buff *xdp)
{
struct skb_shared_info *sinfo;
- int i;
if (likely(!xdp_buff_has_frags(xdp)))
goto out;
sinfo = xdp_get_shared_info_from_buff(xdp);
- for (i = 0; i < sinfo->nr_frags; i++) {
- struct page *page = skb_frag_page(&sinfo->frags[i]);
+ for (u32 i = 0; i < sinfo->nr_frags; i++)
+ __xdp_return(skb_frag_netmem(&sinfo->frags[i]),
+ xdp->rxq->mem.type, true, xdp);
- __xdp_return(page_address(page), &xdp->rxq->mem, true, xdp);
- }
out:
- __xdp_return(xdp->data, &xdp->rxq->mem, true, xdp);
+ __xdp_return(virt_to_netmem(xdp->data), xdp->rxq->mem.type, true, xdp);
}
EXPORT_SYMBOL_GPL(xdp_return_buff);
@@ -570,7 +605,7 @@ struct xdp_frame *xdp_convert_zc_to_xdp_frame(struct xdp_buff *xdp)
xdpf->headroom = 0;
xdpf->metasize = metasize;
xdpf->frame_sz = PAGE_SIZE;
- xdpf->mem.type = MEM_TYPE_PAGE_ORDER0;
+ xdpf->mem_type = MEM_TYPE_PAGE_ORDER0;
xsk_buff_free(xdp);
return xdpf;
@@ -594,6 +629,173 @@ int xdp_alloc_skb_bulk(void **skbs, int n_skb, gfp_t gfp)
}
EXPORT_SYMBOL_GPL(xdp_alloc_skb_bulk);
+/**
+ * xdp_build_skb_from_buff - create an skb from &xdp_buff
+ * @xdp: &xdp_buff to convert to an skb
+ *
+ * Perform common operations to create a new skb to pass up the stack from
+ * &xdp_buff: allocate an skb head from the NAPI percpu cache, initialize
+ * skb data pointers and offsets, set the recycle bit if the buff is
+ * PP-backed, Rx queue index, protocol and update frags info.
+ *
+ * Return: new &sk_buff on success, %NULL on error.
+ */
+struct sk_buff *xdp_build_skb_from_buff(const struct xdp_buff *xdp)
+{
+ const struct xdp_rxq_info *rxq = xdp->rxq;
+ const struct skb_shared_info *sinfo;
+ struct sk_buff *skb;
+ u32 nr_frags = 0;
+ int metalen;
+
+ if (unlikely(xdp_buff_has_frags(xdp))) {
+ sinfo = xdp_get_shared_info_from_buff(xdp);
+ nr_frags = sinfo->nr_frags;
+ }
+
+ skb = napi_build_skb(xdp->data_hard_start, xdp->frame_sz);
+ if (unlikely(!skb))
+ return NULL;
+
+ skb_reserve(skb, xdp->data - xdp->data_hard_start);
+ __skb_put(skb, xdp->data_end - xdp->data);
+
+ metalen = xdp->data - xdp->data_meta;
+ if (metalen > 0)
+ skb_metadata_set(skb, metalen);
+
+ if (rxq->mem.type == MEM_TYPE_PAGE_POOL)
+ skb_mark_for_recycle(skb);
+
+ skb_record_rx_queue(skb, rxq->queue_index);
+
+ if (unlikely(nr_frags)) {
+ u32 tsize;
+
+ tsize = sinfo->xdp_frags_truesize ? : nr_frags * xdp->frame_sz;
+ xdp_update_skb_shared_info(skb, nr_frags,
+ sinfo->xdp_frags_size, tsize,
+ xdp_buff_is_frag_pfmemalloc(xdp));
+ }
+
+ skb->protocol = eth_type_trans(skb, rxq->dev);
+
+ return skb;
+}
+EXPORT_SYMBOL_GPL(xdp_build_skb_from_buff);
+
+/**
+ * xdp_copy_frags_from_zc - copy frags from XSk buff to skb
+ * @skb: skb to copy frags to
+ * @xdp: XSk &xdp_buff from which the frags will be copied
+ * @pp: &page_pool backing page allocation, if available
+ *
+ * Copy all frags from XSk &xdp_buff to the skb to pass it up the stack.
+ * Allocate a new buffer for each frag, copy it and attach to the skb.
+ *
+ * Return: true on success, false on netmem allocation fail.
+ */
+static noinline bool xdp_copy_frags_from_zc(struct sk_buff *skb,
+ const struct xdp_buff *xdp,
+ struct page_pool *pp)
+{
+ struct skb_shared_info *sinfo = skb_shinfo(skb);
+ const struct skb_shared_info *xinfo;
+ u32 nr_frags, tsize = 0;
+ bool pfmemalloc = false;
+
+ xinfo = xdp_get_shared_info_from_buff(xdp);
+ nr_frags = xinfo->nr_frags;
+
+ for (u32 i = 0; i < nr_frags; i++) {
+ u32 len = skb_frag_size(&xinfo->frags[i]);
+ u32 offset, truesize = len;
+ netmem_ref netmem;
+
+ netmem = page_pool_dev_alloc_netmem(pp, &offset, &truesize);
+ if (unlikely(!netmem)) {
+ sinfo->nr_frags = i;
+ return false;
+ }
+
+ memcpy(__netmem_address(netmem),
+ __netmem_address(xinfo->frags[i].netmem),
+ LARGEST_ALIGN(len));
+ __skb_fill_netmem_desc_noacc(sinfo, i, netmem, offset, len);
+
+ tsize += truesize;
+ pfmemalloc |= netmem_is_pfmemalloc(netmem);
+ }
+
+ xdp_update_skb_shared_info(skb, nr_frags, xinfo->xdp_frags_size,
+ tsize, pfmemalloc);
+
+ return true;
+}
+
+/**
+ * xdp_build_skb_from_zc - create an skb from XSk &xdp_buff
+ * @xdp: source XSk buff
+ *
+ * Similar to xdp_build_skb_from_buff(), but for XSk frames. Allocate an skb
+ * head, new buffer for the head, copy the data and initialize the skb fields.
+ * If there are frags, allocate new buffers for them and copy.
+ * Buffers are allocated from the system percpu pools to try recycling them.
+ * If new skb was built successfully, @xdp is returned to XSk pool's freelist.
+ * On error, it remains untouched and the caller must take care of this.
+ *
+ * Return: new &sk_buff on success, %NULL on error.
+ */
+struct sk_buff *xdp_build_skb_from_zc(struct xdp_buff *xdp)
+{
+ struct page_pool *pp = this_cpu_read(system_page_pool);
+ const struct xdp_rxq_info *rxq = xdp->rxq;
+ u32 len = xdp->data_end - xdp->data_meta;
+ u32 truesize = xdp->frame_sz;
+ struct sk_buff *skb;
+ int metalen;
+ void *data;
+
+ if (!IS_ENABLED(CONFIG_PAGE_POOL))
+ return NULL;
+
+ data = page_pool_dev_alloc_va(pp, &truesize);
+ if (unlikely(!data))
+ return NULL;
+
+ skb = napi_build_skb(data, truesize);
+ if (unlikely(!skb)) {
+ page_pool_free_va(pp, data, true);
+ return NULL;
+ }
+
+ skb_mark_for_recycle(skb);
+ skb_reserve(skb, xdp->data_meta - xdp->data_hard_start);
+
+ memcpy(__skb_put(skb, len), xdp->data_meta, LARGEST_ALIGN(len));
+
+ metalen = xdp->data - xdp->data_meta;
+ if (metalen > 0) {
+ skb_metadata_set(skb, metalen);
+ __skb_pull(skb, metalen);
+ }
+
+ skb_record_rx_queue(skb, rxq->queue_index);
+
+ if (unlikely(xdp_buff_has_frags(xdp)) &&
+ unlikely(!xdp_copy_frags_from_zc(skb, xdp, pp))) {
+ napi_consume_skb(skb, true);
+ return NULL;
+ }
+
+ xsk_buff_free(xdp);
+
+ skb->protocol = eth_type_trans(skb, rxq->dev);
+
+ return skb;
+}
+EXPORT_SYMBOL_GPL(xdp_build_skb_from_zc);
+
struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
struct sk_buff *skb,
struct net_device *dev)
@@ -640,7 +842,7 @@ struct sk_buff *__xdp_build_skb_from_frame(struct xdp_frame *xdpf,
* - RX ring dev queue index (skb_record_rx_queue)
*/
- if (xdpf->mem.type == MEM_TYPE_PAGE_POOL)
+ if (xdpf->mem_type == MEM_TYPE_PAGE_POOL)
skb_mark_for_recycle(skb);
/* Allow SKB to reuse area used by xdp_frame */
@@ -687,8 +889,7 @@ struct xdp_frame *xdpf_clone(struct xdp_frame *xdpf)
nxdpf = addr;
nxdpf->data = addr + headroom;
nxdpf->frame_sz = PAGE_SIZE;
- nxdpf->mem.type = MEM_TYPE_PAGE_ORDER0;
- nxdpf->mem.id = 0;
+ nxdpf->mem_type = MEM_TYPE_PAGE_ORDER0;
return nxdpf;
}
diff --git a/net/dccp/feat.c b/net/dccp/feat.c
index 54086bb05c42..f7554dcdaaba 100644
--- a/net/dccp/feat.c
+++ b/net/dccp/feat.c
@@ -1166,8 +1166,12 @@ static u8 dccp_feat_change_recv(struct list_head *fn, u8 is_mandatory, u8 opt,
goto not_valid_or_not_known;
}
- return dccp_feat_push_confirm(fn, feat, local, &fval);
+ if (dccp_feat_push_confirm(fn, feat, local, &fval)) {
+ kfree(fval.sp.vec);
+ return DCCP_RESET_CODE_TOO_BUSY;
+ }
+ return 0;
} else if (entry->state == FEAT_UNSTABLE) { /* 6.6.2 */
return 0;
}
diff --git a/net/devlink/health.c b/net/devlink/health.c
index b8d3084e6fe0..57db6799722a 100644
--- a/net/devlink/health.c
+++ b/net/devlink/health.c
@@ -1238,3 +1238,70 @@ int devlink_nl_health_reporter_test_doit(struct sk_buff *skb,
return reporter->ops->test(reporter, info->extack);
}
+
+/**
+ * devlink_fmsg_dump_skb - Dump sk_buffer structure
+ * @fmsg: devlink formatted message pointer
+ * @skb: pointer to skb
+ *
+ * Dump diagnostic information about sk_buff structure, like headroom, length,
+ * tailroom, MAC, etc.
+ */
+void devlink_fmsg_dump_skb(struct devlink_fmsg *fmsg, const struct sk_buff *skb)
+{
+ struct skb_shared_info *sh = skb_shinfo(skb);
+ struct sock *sk = skb->sk;
+ bool has_mac, has_trans;
+
+ has_mac = skb_mac_header_was_set(skb);
+ has_trans = skb_transport_header_was_set(skb);
+
+ devlink_fmsg_pair_nest_start(fmsg, "skb");
+ devlink_fmsg_obj_nest_start(fmsg);
+ devlink_fmsg_put(fmsg, "actual len", skb->len);
+ devlink_fmsg_put(fmsg, "head len", skb_headlen(skb));
+ devlink_fmsg_put(fmsg, "data len", skb->data_len);
+ devlink_fmsg_put(fmsg, "tail len", skb_tailroom(skb));
+ devlink_fmsg_put(fmsg, "MAC", has_mac ? skb->mac_header : -1);
+ devlink_fmsg_put(fmsg, "MAC len",
+ has_mac ? skb_mac_header_len(skb) : -1);
+ devlink_fmsg_put(fmsg, "network hdr", skb->network_header);
+ devlink_fmsg_put(fmsg, "network hdr len",
+ has_trans ? skb_network_header_len(skb) : -1);
+ devlink_fmsg_put(fmsg, "transport hdr",
+ has_trans ? skb->transport_header : -1);
+ devlink_fmsg_put(fmsg, "csum", (__force u32)skb->csum);
+ devlink_fmsg_put(fmsg, "csum_ip_summed", (u8)skb->ip_summed);
+ devlink_fmsg_put(fmsg, "csum_complete_sw", !!skb->csum_complete_sw);
+ devlink_fmsg_put(fmsg, "csum_valid", !!skb->csum_valid);
+ devlink_fmsg_put(fmsg, "csum_level", (u8)skb->csum_level);
+ devlink_fmsg_put(fmsg, "sw_hash", !!skb->sw_hash);
+ devlink_fmsg_put(fmsg, "l4_hash", !!skb->l4_hash);
+ devlink_fmsg_put(fmsg, "proto", ntohs(skb->protocol));
+ devlink_fmsg_put(fmsg, "pkt_type", (u8)skb->pkt_type);
+ devlink_fmsg_put(fmsg, "iif", skb->skb_iif);
+
+ if (sk) {
+ devlink_fmsg_pair_nest_start(fmsg, "sk");
+ devlink_fmsg_obj_nest_start(fmsg);
+ devlink_fmsg_put(fmsg, "family", sk->sk_type);
+ devlink_fmsg_put(fmsg, "type", sk->sk_type);
+ devlink_fmsg_put(fmsg, "proto", sk->sk_protocol);
+ devlink_fmsg_obj_nest_end(fmsg);
+ devlink_fmsg_pair_nest_end(fmsg);
+ }
+
+ devlink_fmsg_obj_nest_end(fmsg);
+ devlink_fmsg_pair_nest_end(fmsg);
+
+ devlink_fmsg_pair_nest_start(fmsg, "shinfo");
+ devlink_fmsg_obj_nest_start(fmsg);
+ devlink_fmsg_put(fmsg, "tx_flags", sh->tx_flags);
+ devlink_fmsg_put(fmsg, "nr_frags", sh->nr_frags);
+ devlink_fmsg_put(fmsg, "gso_size", sh->gso_size);
+ devlink_fmsg_put(fmsg, "gso_type", sh->gso_type);
+ devlink_fmsg_put(fmsg, "gso_segs", sh->gso_segs);
+ devlink_fmsg_obj_nest_end(fmsg);
+ devlink_fmsg_pair_nest_end(fmsg);
+}
+EXPORT_SYMBOL_GPL(devlink_fmsg_dump_skb);
diff --git a/net/devlink/port.c b/net/devlink/port.c
index be9158b4453c..939081a0e615 100644
--- a/net/devlink/port.c
+++ b/net/devlink/port.c
@@ -1376,7 +1376,7 @@ EXPORT_SYMBOL_GPL(devlink_port_attrs_set);
*
* @devlink_port: devlink port
* @controller: associated controller number for the devlink port instance
- * @pf: associated PF for the devlink port instance
+ * @pf: associated PCI function number for the devlink port instance
* @external: indicates if the port is for an external controller
*/
void devlink_port_attrs_pci_pf_set(struct devlink_port *devlink_port, u32 controller,
@@ -1402,8 +1402,9 @@ EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_pf_set);
*
* @devlink_port: devlink port
* @controller: associated controller number for the devlink port instance
- * @pf: associated PF for the devlink port instance
- * @vf: associated VF of a PF for the devlink port instance
+ * @pf: associated PCI function number for the devlink port instance
+ * @vf: associated PCI VF number of a PF for the devlink port instance;
+ * VF number starts from 0 for the first PCI virtual function
* @external: indicates if the port is for an external controller
*/
void devlink_port_attrs_pci_vf_set(struct devlink_port *devlink_port, u32 controller,
@@ -1430,8 +1431,8 @@ EXPORT_SYMBOL_GPL(devlink_port_attrs_pci_vf_set);
*
* @devlink_port: devlink port
* @controller: associated controller number for the devlink port instance
- * @pf: associated PF for the devlink port instance
- * @sf: associated SF of a PF for the devlink port instance
+ * @pf: associated PCI function number for the devlink port instance
+ * @sf: associated SF number of a PF for the devlink port instance
* @external: indicates if the port is for an external controller
*/
void devlink_port_attrs_pci_sf_set(struct devlink_port *devlink_port, u32 controller,
diff --git a/net/dsa/port.c b/net/dsa/port.c
index ee0aaec4c8e0..5c9d1798e830 100644
--- a/net/dsa/port.c
+++ b/net/dsa/port.c
@@ -1575,6 +1575,22 @@ void dsa_port_set_tag_protocol(struct dsa_port *cpu_dp,
cpu_dp->tag_ops = tag_ops;
}
+/* dsa_supports_eee - indicate that EEE is supported
+ * @ds: pointer to &struct dsa_switch
+ * @port: port index
+ *
+ * A default implementation for the .support_eee() DSA operations member,
+ * which drivers can use to indicate that they support EEE on all of their
+ * user ports.
+ *
+ * Returns: true
+ */
+bool dsa_supports_eee(struct dsa_switch *ds, int port)
+{
+ return true;
+}
+EXPORT_SYMBOL_GPL(dsa_supports_eee);
+
static void dsa_port_phylink_mac_config(struct phylink_config *config,
unsigned int mode,
const struct phylink_link_state *state)
diff --git a/net/dsa/tag.h b/net/dsa/tag.h
index d5707870906b..5d80ddad4ff6 100644
--- a/net/dsa/tag.h
+++ b/net/dsa/tag.h
@@ -138,9 +138,10 @@ static inline void dsa_software_untag_vlan_unaware_bridge(struct sk_buff *skb,
* dsa_software_vlan_untag: Software VLAN untagging in DSA receive path
* @skb: Pointer to socket buffer (packet)
*
- * Receive path method for switches which cannot avoid tagging all packets
- * towards the CPU port. Called when ds->untag_bridge_pvid (legacy) or
- * ds->untag_vlan_aware_bridge_pvid is set to true.
+ * Receive path method for switches which send some packets as VLAN-tagged
+ * towards the CPU port (generally from VLAN-aware bridge ports) even when the
+ * packet was not tagged on the wire. Called when ds->untag_bridge_pvid
+ * (legacy) or ds->untag_vlan_aware_bridge_pvid is set to true.
*
* As a side effect of this method, any VLAN tag from the skb head is moved
* to hwaccel.
@@ -149,14 +150,19 @@ static inline struct sk_buff *dsa_software_vlan_untag(struct sk_buff *skb)
{
struct dsa_port *dp = dsa_user_to_port(skb->dev);
struct net_device *br = dsa_port_bridge_dev_get(dp);
- u16 vid;
+ u16 vid, proto;
+ int err;
/* software untagging for standalone ports not yet necessary */
if (!br)
return skb;
+ err = br_vlan_get_proto(br, &proto);
+ if (err)
+ return skb;
+
/* Move VLAN tag from data to hwaccel */
- if (!skb_vlan_tag_present(skb)) {
+ if (!skb_vlan_tag_present(skb) && skb->protocol == htons(proto)) {
skb = skb_vlan_untag(skb);
if (!skb)
return NULL;
diff --git a/net/dsa/tag_ocelot_8021q.c b/net/dsa/tag_ocelot_8021q.c
index 8e8b1bef6af6..11ea8cfd6266 100644
--- a/net/dsa/tag_ocelot_8021q.c
+++ b/net/dsa/tag_ocelot_8021q.c
@@ -79,7 +79,7 @@ static struct sk_buff *ocelot_xmit(struct sk_buff *skb,
static struct sk_buff *ocelot_rcv(struct sk_buff *skb,
struct net_device *netdev)
{
- int src_port, switch_id;
+ int src_port = -1, switch_id = -1;
dsa_8021q_rcv(skb, &src_port, &switch_id, NULL, NULL);
diff --git a/net/dsa/user.c b/net/dsa/user.c
index 06c30a9e29ff..c74f2b2b92de 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -515,12 +515,13 @@ dsa_user_port_fdb_do_dump(const unsigned char *addr, u16 vid,
bool is_static, void *data)
{
struct dsa_user_dump_ctx *dump = data;
+ struct ndo_fdb_dump_context *ctx = (void *)dump->cb->ctx;
u32 portid = NETLINK_CB(dump->cb->skb).portid;
u32 seq = dump->cb->nlh->nlmsg_seq;
struct nlmsghdr *nlh;
struct ndmsg *ndm;
- if (dump->idx < dump->cb->args[2])
+ if (dump->idx < ctx->fdb_idx)
goto skip;
nlh = nlmsg_put(dump->skb, portid, seq, RTM_NEWNEIGH,
@@ -1228,8 +1229,12 @@ static int dsa_user_set_eee(struct net_device *dev, struct ethtool_keee *e)
struct dsa_switch *ds = dp->ds;
int ret;
+ /* Check whether the switch supports EEE */
+ if (!ds->ops->support_eee || !ds->ops->support_eee(ds, dp->index))
+ return -EOPNOTSUPP;
+
/* Port's PHY and MAC both need to be EEE capable */
- if (!dev->phydev || !dp->pl)
+ if (!dev->phydev)
return -ENODEV;
if (!ds->ops->set_mac_eee)
@@ -1246,18 +1251,14 @@ static int dsa_user_get_eee(struct net_device *dev, struct ethtool_keee *e)
{
struct dsa_port *dp = dsa_user_to_port(dev);
struct dsa_switch *ds = dp->ds;
- int ret;
-
- /* Port's PHY and MAC both need to be EEE capable */
- if (!dev->phydev || !dp->pl)
- return -ENODEV;
- if (!ds->ops->get_mac_eee)
+ /* Check whether the switch supports EEE */
+ if (!ds->ops->support_eee || !ds->ops->support_eee(ds, dp->index))
return -EOPNOTSUPP;
- ret = ds->ops->get_mac_eee(ds, dp->index, e);
- if (ret)
- return ret;
+ /* Port's PHY and MAC both need to be EEE capable */
+ if (!dev->phydev)
+ return -ENODEV;
return phylink_ethtool_get_eee(dp->pl, e);
}
diff --git a/net/ethtool/Makefile b/net/ethtool/Makefile
index 9b540644ba31..a1490c4afe6b 100644
--- a/net/ethtool/Makefile
+++ b/net/ethtool/Makefile
@@ -9,4 +9,4 @@ ethtool_nl-y := netlink.o bitset.o strset.o linkinfo.o linkmodes.o rss.o \
channels.o coalesce.o pause.o eee.o tsinfo.o cabletest.o \
tunnels.o fec.o eeprom.o stats.o phc_vclocks.o mm.o \
module.o cmis_fw_update.o cmis_cdb.o pse-pd.o plca.o mm.o \
- phy.o
+ phy.o tsconfig.o
diff --git a/net/ethtool/bitset.c b/net/ethtool/bitset.c
index 0515d6604b3b..f0883357d12e 100644
--- a/net/ethtool/bitset.c
+++ b/net/ethtool/bitset.c
@@ -425,12 +425,32 @@ static int ethnl_parse_bit(unsigned int *index, bool *val, unsigned int nbits,
return 0;
}
+/**
+ * ethnl_bitmap32_equal() - Compare two bitmaps
+ * @map1: first bitmap
+ * @map2: second bitmap
+ * @nbits: bit size to compare
+ *
+ * Return: true if first @nbits are equal, false if not
+ */
+static bool ethnl_bitmap32_equal(const u32 *map1, const u32 *map2,
+ unsigned int nbits)
+{
+ if (memcmp(map1, map2, nbits / 32 * sizeof(u32)))
+ return false;
+ if (nbits % 32 == 0)
+ return true;
+ return !((map1[nbits / 32] ^ map2[nbits / 32]) &
+ ethnl_lower_bits(nbits % 32));
+}
+
static int
ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits,
const struct nlattr *attr, struct nlattr **tb,
ethnl_string_array_t names,
struct netlink_ext_ack *extack, bool *mod)
{
+ u32 *saved_bitmap = NULL;
struct nlattr *bit_attr;
bool no_mask;
int rem;
@@ -448,8 +468,20 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits,
}
no_mask = tb[ETHTOOL_A_BITSET_NOMASK];
- if (no_mask)
- ethnl_bitmap32_clear(bitmap, 0, nbits, mod);
+ if (no_mask) {
+ unsigned int nwords = DIV_ROUND_UP(nbits, 32);
+ unsigned int nbytes = nwords * sizeof(u32);
+ bool dummy;
+
+ /* The bitmap size is only the size of the map part without
+ * its mask part.
+ */
+ saved_bitmap = kcalloc(nwords, sizeof(u32), GFP_KERNEL);
+ if (!saved_bitmap)
+ return -ENOMEM;
+ memcpy(saved_bitmap, bitmap, nbytes);
+ ethnl_bitmap32_clear(bitmap, 0, nbits, &dummy);
+ }
nla_for_each_nested(bit_attr, tb[ETHTOOL_A_BITSET_BITS], rem) {
bool old_val, new_val;
@@ -458,22 +490,30 @@ ethnl_update_bitset32_verbose(u32 *bitmap, unsigned int nbits,
if (nla_type(bit_attr) != ETHTOOL_A_BITSET_BITS_BIT) {
NL_SET_ERR_MSG_ATTR(extack, bit_attr,
"only ETHTOOL_A_BITSET_BITS_BIT allowed in ETHTOOL_A_BITSET_BITS");
+ kfree(saved_bitmap);
return -EINVAL;
}
ret = ethnl_parse_bit(&idx, &new_val, nbits, bit_attr, no_mask,
names, extack);
- if (ret < 0)
+ if (ret < 0) {
+ kfree(saved_bitmap);
return ret;
+ }
old_val = bitmap[idx / 32] & ((u32)1 << (idx % 32));
if (new_val != old_val) {
if (new_val)
bitmap[idx / 32] |= ((u32)1 << (idx % 32));
else
bitmap[idx / 32] &= ~((u32)1 << (idx % 32));
- *mod = true;
+ if (!no_mask)
+ *mod = true;
}
}
+ if (no_mask && !ethnl_bitmap32_equal(saved_bitmap, bitmap, nbits))
+ *mod = true;
+
+ kfree(saved_bitmap);
return 0;
}
diff --git a/net/ethtool/common.c b/net/ethtool/common.c
index 05ce4f8080b3..2607aea1fbfb 100644
--- a/net/ethtool/common.c
+++ b/net/ethtool/common.c
@@ -5,9 +5,12 @@
#include <linux/phy.h>
#include <linux/rtnetlink.h>
#include <linux/ptp_clock_kernel.h>
+#include <linux/phy_link_topology.h>
#include "netlink.h"
#include "common.h"
+#include "../core/dev.h"
+
const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] = {
[NETIF_F_SG_BIT] = "tx-scatter-gather",
@@ -763,20 +766,98 @@ int ethtool_check_ops(const struct ethtool_ops *ops)
return 0;
}
-int __ethtool_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info *info)
+static void ethtool_init_tsinfo(struct kernel_ethtool_ts_info *info)
{
- const struct ethtool_ops *ops = dev->ethtool_ops;
- struct phy_device *phydev = dev->phydev;
- int err = 0;
-
memset(info, 0, sizeof(*info));
info->cmd = ETHTOOL_GET_TS_INFO;
info->phc_index = -1;
+}
+
+int ethtool_net_get_ts_info_by_phc(struct net_device *dev,
+ struct kernel_ethtool_ts_info *info,
+ struct hwtstamp_provider_desc *hwprov_desc)
+{
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+ int err;
+
+ if (!ops->get_ts_info)
+ return -ENODEV;
+
+ /* Does ptp comes from netdev */
+ ethtool_init_tsinfo(info);
+ info->phc_qualifier = hwprov_desc->qualifier;
+ err = ops->get_ts_info(dev, info);
+ if (err)
+ return err;
+
+ if (info->phc_index == hwprov_desc->index &&
+ net_support_hwtstamp_qualifier(dev, hwprov_desc->qualifier))
+ return 0;
+
+ return -ENODEV;
+}
+
+struct phy_device *
+ethtool_phy_get_ts_info_by_phc(struct net_device *dev,
+ struct kernel_ethtool_ts_info *info,
+ struct hwtstamp_provider_desc *hwprov_desc)
+{
+ int err;
+
+ /* Only precise qualifier is supported in phydev */
+ if (hwprov_desc->qualifier != HWTSTAMP_PROVIDER_QUALIFIER_PRECISE)
+ return ERR_PTR(-ENODEV);
+
+ /* Look in the phy topology */
+ if (dev->link_topo) {
+ struct phy_device_node *pdn;
+ unsigned long phy_index;
+
+ xa_for_each(&dev->link_topo->phys, phy_index, pdn) {
+ if (!phy_has_tsinfo(pdn->phy))
+ continue;
+
+ ethtool_init_tsinfo(info);
+ err = phy_ts_info(pdn->phy, info);
+ if (err)
+ return ERR_PTR(err);
+
+ if (info->phc_index == hwprov_desc->index)
+ return pdn->phy;
+ }
+ return ERR_PTR(-ENODEV);
+ }
- if (phy_is_default_hwtstamp(phydev) && phy_has_tsinfo(phydev))
- err = phy_ts_info(phydev, info);
- else if (ops->get_ts_info)
- err = ops->get_ts_info(dev, info);
+ /* Look on the dev->phydev */
+ if (phy_has_tsinfo(dev->phydev)) {
+ ethtool_init_tsinfo(info);
+ err = phy_ts_info(dev->phydev, info);
+ if (err)
+ return ERR_PTR(err);
+
+ if (info->phc_index == hwprov_desc->index)
+ return dev->phydev;
+ }
+
+ return ERR_PTR(-ENODEV);
+}
+
+int ethtool_get_ts_info_by_phc(struct net_device *dev,
+ struct kernel_ethtool_ts_info *info,
+ struct hwtstamp_provider_desc *hwprov_desc)
+{
+ int err;
+
+ err = ethtool_net_get_ts_info_by_phc(dev, info, hwprov_desc);
+ if (err == -ENODEV) {
+ struct phy_device *phy;
+
+ phy = ethtool_phy_get_ts_info_by_phc(dev, info, hwprov_desc);
+ if (IS_ERR(phy))
+ err = PTR_ERR(phy);
+ else
+ err = 0;
+ }
info->so_timestamping |= SOF_TIMESTAMPING_RX_SOFTWARE |
SOF_TIMESTAMPING_SOFTWARE;
@@ -784,6 +865,58 @@ int __ethtool_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info
return err;
}
+int __ethtool_get_ts_info(struct net_device *dev,
+ struct kernel_ethtool_ts_info *info)
+{
+ struct hwtstamp_provider *hwprov;
+
+ rcu_read_lock();
+ hwprov = rcu_dereference(dev->hwprov);
+ /* No provider specified, use default behavior */
+ if (!hwprov) {
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+ struct phy_device *phydev = dev->phydev;
+ int err = 0;
+
+ ethtool_init_tsinfo(info);
+ if (phy_is_default_hwtstamp(phydev) &&
+ phy_has_tsinfo(phydev))
+ err = phy_ts_info(phydev, info);
+ else if (ops->get_ts_info)
+ err = ops->get_ts_info(dev, info);
+
+ info->so_timestamping |= SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE;
+
+ rcu_read_unlock();
+ return err;
+ }
+
+ rcu_read_unlock();
+ return ethtool_get_ts_info_by_phc(dev, info, &hwprov->desc);
+}
+
+bool net_support_hwtstamp_qualifier(struct net_device *dev,
+ enum hwtstamp_provider_qualifier qualifier)
+{
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+
+ if (!ops)
+ return false;
+
+ /* Return true with precise qualifier and with NIC without
+ * qualifier description to not break the old behavior.
+ */
+ if (!ops->supported_hwtstamp_qualifiers &&
+ qualifier == HWTSTAMP_PROVIDER_QUALIFIER_PRECISE)
+ return true;
+
+ if (ops->supported_hwtstamp_qualifiers & BIT(qualifier))
+ return true;
+
+ return false;
+}
+
int ethtool_get_phc_vclocks(struct net_device *dev, int **vclock_index)
{
struct kernel_ethtool_ts_info info = { };
diff --git a/net/ethtool/common.h b/net/ethtool/common.h
index 4a2de3ce7354..850eadde4bfc 100644
--- a/net/ethtool/common.h
+++ b/net/ethtool/common.h
@@ -21,6 +21,7 @@ struct link_mode_info {
};
struct genl_info;
+struct hwtstamp_provider_desc;
extern const char
netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN];
@@ -49,6 +50,18 @@ int ethtool_check_max_channel(struct net_device *dev,
struct genl_info *info);
int ethtool_check_rss_ctx_busy(struct net_device *dev, u32 rss_context);
int __ethtool_get_ts_info(struct net_device *dev, struct kernel_ethtool_ts_info *info);
+int ethtool_get_ts_info_by_phc(struct net_device *dev,
+ struct kernel_ethtool_ts_info *info,
+ struct hwtstamp_provider_desc *hwprov_desc);
+int ethtool_net_get_ts_info_by_phc(struct net_device *dev,
+ struct kernel_ethtool_ts_info *info,
+ struct hwtstamp_provider_desc *hwprov_desc);
+struct phy_device *
+ethtool_phy_get_ts_info_by_phc(struct net_device *dev,
+ struct kernel_ethtool_ts_info *info,
+ struct hwtstamp_provider_desc *hwprov_desc);
+bool net_support_hwtstamp_qualifier(struct net_device *dev,
+ enum hwtstamp_provider_qualifier qualifier);
extern const struct ethtool_phy_ops *ethtool_phy_ops;
extern const struct ethtool_pse_ops *ethtool_pse_ops;
diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c
index 61df8ce44379..7bb94875a7ec 100644
--- a/net/ethtool/ioctl.c
+++ b/net/ethtool/ioctl.c
@@ -993,7 +993,8 @@ static noinline_for_stack int ethtool_set_rxnfc(struct net_device *dev,
return rc;
/* Nonzero ring with RSS only makes sense if NIC adds them together */
- if (info.flow_type & FLOW_RSS && !ops->cap_rss_rxnfc_adds &&
+ if (cmd == ETHTOOL_SRXCLSRLINS && info.flow_type & FLOW_RSS &&
+ !ops->cap_rss_rxnfc_adds &&
ethtool_get_flow_spec_ring(info.fs.ring_cookie))
return -EINVAL;
diff --git a/net/ethtool/netlink.c b/net/ethtool/netlink.c
index e3f0ef6b851b..849c98e637c6 100644
--- a/net/ethtool/netlink.c
+++ b/net/ethtool/netlink.c
@@ -394,6 +394,8 @@ ethnl_default_requests[__ETHTOOL_MSG_USER_CNT] = {
[ETHTOOL_MSG_PLCA_GET_STATUS] = &ethnl_plca_status_request_ops,
[ETHTOOL_MSG_MM_GET] = &ethnl_mm_request_ops,
[ETHTOOL_MSG_MM_SET] = &ethnl_mm_request_ops,
+ [ETHTOOL_MSG_TSCONFIG_GET] = &ethnl_tsconfig_request_ops,
+ [ETHTOOL_MSG_TSCONFIG_SET] = &ethnl_tsconfig_request_ops,
};
static struct ethnl_dump_ctx *ethnl_dump_context(struct netlink_callback *cb)
@@ -1074,9 +1076,9 @@ static const struct genl_ops ethtool_genl_ops[] = {
{
.cmd = ETHTOOL_MSG_TSINFO_GET,
.doit = ethnl_default_doit,
- .start = ethnl_default_start,
- .dumpit = ethnl_default_dumpit,
- .done = ethnl_default_done,
+ .start = ethnl_tsinfo_start,
+ .dumpit = ethnl_tsinfo_dumpit,
+ .done = ethnl_tsinfo_done,
.policy = ethnl_tsinfo_get_policy,
.maxattr = ARRAY_SIZE(ethnl_tsinfo_get_policy) - 1,
},
@@ -1243,6 +1245,22 @@ static const struct genl_ops ethtool_genl_ops[] = {
.policy = ethnl_phy_get_policy,
.maxattr = ARRAY_SIZE(ethnl_phy_get_policy) - 1,
},
+ {
+ .cmd = ETHTOOL_MSG_TSCONFIG_GET,
+ .doit = ethnl_default_doit,
+ .start = ethnl_default_start,
+ .dumpit = ethnl_default_dumpit,
+ .done = ethnl_default_done,
+ .policy = ethnl_tsconfig_get_policy,
+ .maxattr = ARRAY_SIZE(ethnl_tsconfig_get_policy) - 1,
+ },
+ {
+ .cmd = ETHTOOL_MSG_TSCONFIG_SET,
+ .flags = GENL_UNS_ADMIN_PERM,
+ .doit = ethnl_default_set_doit,
+ .policy = ethnl_tsconfig_set_policy,
+ .maxattr = ARRAY_SIZE(ethnl_tsconfig_set_policy) - 1,
+ },
};
static const struct genl_multicast_group ethtool_nl_mcgrps[] = {
diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h
index 203b08eb6c6f..0a09298fff92 100644
--- a/net/ethtool/netlink.h
+++ b/net/ethtool/netlink.h
@@ -435,6 +435,7 @@ extern const struct ethnl_request_ops ethnl_plca_cfg_request_ops;
extern const struct ethnl_request_ops ethnl_plca_status_request_ops;
extern const struct ethnl_request_ops ethnl_mm_request_ops;
extern const struct ethnl_request_ops ethnl_phy_request_ops;
+extern const struct ethnl_request_ops ethnl_tsconfig_request_ops;
extern const struct nla_policy ethnl_header_policy[ETHTOOL_A_HEADER_FLAGS + 1];
extern const struct nla_policy ethnl_header_policy_stats[ETHTOOL_A_HEADER_FLAGS + 1];
@@ -464,7 +465,7 @@ extern const struct nla_policy ethnl_pause_get_policy[ETHTOOL_A_PAUSE_STATS_SRC
extern const struct nla_policy ethnl_pause_set_policy[ETHTOOL_A_PAUSE_TX + 1];
extern const struct nla_policy ethnl_eee_get_policy[ETHTOOL_A_EEE_HEADER + 1];
extern const struct nla_policy ethnl_eee_set_policy[ETHTOOL_A_EEE_TX_LPI_TIMER + 1];
-extern const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_HEADER + 1];
+extern const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_MAX + 1];
extern const struct nla_policy ethnl_cable_test_act_policy[ETHTOOL_A_CABLE_TEST_HEADER + 1];
extern const struct nla_policy ethnl_cable_test_tdr_act_policy[ETHTOOL_A_CABLE_TEST_TDR_CFG + 1];
extern const struct nla_policy ethnl_tunnel_info_get_policy[ETHTOOL_A_TUNNEL_INFO_HEADER + 1];
@@ -485,6 +486,8 @@ extern const struct nla_policy ethnl_mm_get_policy[ETHTOOL_A_MM_HEADER + 1];
extern const struct nla_policy ethnl_mm_set_policy[ETHTOOL_A_MM_MAX + 1];
extern const struct nla_policy ethnl_module_fw_flash_act_policy[ETHTOOL_A_MODULE_FW_FLASH_PASSWORD + 1];
extern const struct nla_policy ethnl_phy_get_policy[ETHTOOL_A_PHY_HEADER + 1];
+extern const struct nla_policy ethnl_tsconfig_get_policy[ETHTOOL_A_TSCONFIG_HEADER + 1];
+extern const struct nla_policy ethnl_tsconfig_set_policy[ETHTOOL_A_TSCONFIG_MAX + 1];
int ethnl_set_features(struct sk_buff *skb, struct genl_info *info);
int ethnl_act_cable_test(struct sk_buff *skb, struct genl_info *info);
@@ -499,6 +502,9 @@ int ethnl_phy_start(struct netlink_callback *cb);
int ethnl_phy_doit(struct sk_buff *skb, struct genl_info *info);
int ethnl_phy_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
int ethnl_phy_done(struct netlink_callback *cb);
+int ethnl_tsinfo_start(struct netlink_callback *cb);
+int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb);
+int ethnl_tsinfo_done(struct netlink_callback *cb);
extern const char stats_std_names[__ETHTOOL_STATS_CNT][ETH_GSTRING_LEN];
extern const char stats_eth_phy_names[__ETHTOOL_A_STATS_ETH_PHY_CNT][ETH_GSTRING_LEN];
diff --git a/net/ethtool/ts.h b/net/ethtool/ts.h
new file mode 100644
index 000000000000..d901a879a671
--- /dev/null
+++ b/net/ethtool/ts.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef _NET_ETHTOOL_TS_H
+#define _NET_ETHTOOL_TS_H
+
+#include "netlink.h"
+
+static const struct nla_policy
+ethnl_ts_hwtst_prov_policy[ETHTOOL_A_TS_HWTSTAMP_PROVIDER_MAX + 1] = {
+ [ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX] = { .type = NLA_U32 },
+ [ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER] =
+ NLA_POLICY_MAX(NLA_U32, HWTSTAMP_PROVIDER_QUALIFIER_CNT - 1)
+};
+
+int ts_parse_hwtst_provider(const struct nlattr *nest,
+ struct hwtstamp_provider_desc *hwprov_desc,
+ struct netlink_ext_ack *extack,
+ bool *mod);
+
+#endif /* _NET_ETHTOOL_TS_H */
diff --git a/net/ethtool/tsconfig.c b/net/ethtool/tsconfig.c
new file mode 100644
index 000000000000..9188e088fb2f
--- /dev/null
+++ b/net/ethtool/tsconfig.c
@@ -0,0 +1,444 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/net_tstamp.h>
+#include <linux/ptp_clock_kernel.h>
+
+#include "netlink.h"
+#include "common.h"
+#include "bitset.h"
+#include "../core/dev.h"
+#include "ts.h"
+
+struct tsconfig_req_info {
+ struct ethnl_req_info base;
+};
+
+struct tsconfig_reply_data {
+ struct ethnl_reply_data base;
+ struct hwtstamp_provider_desc hwprov_desc;
+ struct {
+ u32 tx_type;
+ u32 rx_filter;
+ u32 flags;
+ } hwtst_config;
+};
+
+#define TSCONFIG_REPDATA(__reply_base) \
+ container_of(__reply_base, struct tsconfig_reply_data, base)
+
+const struct nla_policy ethnl_tsconfig_get_policy[ETHTOOL_A_TSCONFIG_HEADER + 1] = {
+ [ETHTOOL_A_TSCONFIG_HEADER] =
+ NLA_POLICY_NESTED(ethnl_header_policy),
+};
+
+static int tsconfig_prepare_data(const struct ethnl_req_info *req_base,
+ struct ethnl_reply_data *reply_base,
+ const struct genl_info *info)
+{
+ struct tsconfig_reply_data *data = TSCONFIG_REPDATA(reply_base);
+ struct hwtstamp_provider *hwprov = NULL;
+ struct net_device *dev = reply_base->dev;
+ struct kernel_hwtstamp_config cfg = {};
+ int ret;
+
+ if (!dev->netdev_ops->ndo_hwtstamp_get)
+ return -EOPNOTSUPP;
+
+ ret = ethnl_ops_begin(dev);
+ if (ret < 0)
+ return ret;
+
+ ret = dev_get_hwtstamp_phylib(dev, &cfg);
+ if (ret)
+ goto out;
+
+ data->hwtst_config.tx_type = BIT(cfg.tx_type);
+ data->hwtst_config.rx_filter = BIT(cfg.rx_filter);
+ data->hwtst_config.flags = BIT(cfg.flags);
+
+ data->hwprov_desc.index = -1;
+ hwprov = rtnl_dereference(dev->hwprov);
+ if (hwprov) {
+ data->hwprov_desc.index = hwprov->desc.index;
+ data->hwprov_desc.qualifier = hwprov->desc.qualifier;
+ } else {
+ struct kernel_ethtool_ts_info ts_info = {};
+
+ ts_info.phc_index = -1;
+ ret = __ethtool_get_ts_info(dev, &ts_info);
+ if (ret)
+ goto out;
+
+ if (ts_info.phc_index == -1)
+ return -ENODEV;
+
+ data->hwprov_desc.index = ts_info.phc_index;
+ data->hwprov_desc.qualifier = ts_info.phc_qualifier;
+ }
+
+out:
+ ethnl_ops_complete(dev);
+ return ret;
+}
+
+static int tsconfig_reply_size(const struct ethnl_req_info *req_base,
+ const struct ethnl_reply_data *reply_base)
+{
+ const struct tsconfig_reply_data *data = TSCONFIG_REPDATA(reply_base);
+ bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
+ int len = 0;
+ int ret;
+
+ BUILD_BUG_ON(__HWTSTAMP_TX_CNT > 32);
+ BUILD_BUG_ON(__HWTSTAMP_FILTER_CNT > 32);
+
+ if (data->hwtst_config.flags)
+ /* _TSCONFIG_HWTSTAMP_FLAGS */
+ len += nla_total_size(sizeof(u32));
+
+ if (data->hwtst_config.tx_type) {
+ ret = ethnl_bitset32_size(&data->hwtst_config.tx_type,
+ NULL, __HWTSTAMP_TX_CNT,
+ ts_tx_type_names, compact);
+ if (ret < 0)
+ return ret;
+ len += ret; /* _TSCONFIG_TX_TYPES */
+ }
+ if (data->hwtst_config.rx_filter) {
+ ret = ethnl_bitset32_size(&data->hwtst_config.rx_filter,
+ NULL, __HWTSTAMP_FILTER_CNT,
+ ts_rx_filter_names, compact);
+ if (ret < 0)
+ return ret;
+ len += ret; /* _TSCONFIG_RX_FILTERS */
+ }
+
+ if (data->hwprov_desc.index >= 0)
+ /* _TSCONFIG_HWTSTAMP_PROVIDER */
+ len += nla_total_size(0) +
+ 2 * nla_total_size(sizeof(u32));
+
+ return len;
+}
+
+static int tsconfig_fill_reply(struct sk_buff *skb,
+ const struct ethnl_req_info *req_base,
+ const struct ethnl_reply_data *reply_base)
+{
+ const struct tsconfig_reply_data *data = TSCONFIG_REPDATA(reply_base);
+ bool compact = req_base->flags & ETHTOOL_FLAG_COMPACT_BITSETS;
+ int ret;
+
+ if (data->hwtst_config.flags) {
+ ret = nla_put_u32(skb, ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS,
+ data->hwtst_config.flags);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (data->hwtst_config.tx_type) {
+ ret = ethnl_put_bitset32(skb, ETHTOOL_A_TSCONFIG_TX_TYPES,
+ &data->hwtst_config.tx_type, NULL,
+ __HWTSTAMP_TX_CNT,
+ ts_tx_type_names, compact);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (data->hwtst_config.rx_filter) {
+ ret = ethnl_put_bitset32(skb, ETHTOOL_A_TSCONFIG_RX_FILTERS,
+ &data->hwtst_config.rx_filter,
+ NULL, __HWTSTAMP_FILTER_CNT,
+ ts_rx_filter_names, compact);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (data->hwprov_desc.index >= 0) {
+ struct nlattr *nest;
+
+ nest = nla_nest_start(skb, ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER);
+ if (!nest)
+ return -EMSGSIZE;
+
+ if (nla_put_u32(skb, ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX,
+ data->hwprov_desc.index) ||
+ nla_put_u32(skb,
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER,
+ data->hwprov_desc.qualifier)) {
+ nla_nest_cancel(skb, nest);
+ return -EMSGSIZE;
+ }
+
+ nla_nest_end(skb, nest);
+ }
+ return 0;
+}
+
+/* TSCONFIG_SET */
+const struct nla_policy ethnl_tsconfig_set_policy[ETHTOOL_A_TSCONFIG_MAX + 1] = {
+ [ETHTOOL_A_TSCONFIG_HEADER] = NLA_POLICY_NESTED(ethnl_header_policy),
+ [ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER] =
+ NLA_POLICY_NESTED(ethnl_ts_hwtst_prov_policy),
+ [ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS] = { .type = NLA_U32 },
+ [ETHTOOL_A_TSCONFIG_RX_FILTERS] = { .type = NLA_NESTED },
+ [ETHTOOL_A_TSCONFIG_TX_TYPES] = { .type = NLA_NESTED },
+};
+
+static int tsconfig_send_reply(struct net_device *dev, struct genl_info *info)
+{
+ struct tsconfig_reply_data *reply_data;
+ struct tsconfig_req_info *req_info;
+ struct sk_buff *rskb;
+ void *reply_payload;
+ int reply_len = 0;
+ int ret;
+
+ req_info = kzalloc(sizeof(*req_info), GFP_KERNEL);
+ if (!req_info)
+ return -ENOMEM;
+ reply_data = kmalloc(sizeof(*reply_data), GFP_KERNEL);
+ if (!reply_data) {
+ kfree(req_info);
+ return -ENOMEM;
+ }
+
+ ASSERT_RTNL();
+ reply_data->base.dev = dev;
+ ret = tsconfig_prepare_data(&req_info->base, &reply_data->base, info);
+ if (ret < 0)
+ goto err_cleanup;
+
+ ret = tsconfig_reply_size(&req_info->base, &reply_data->base);
+ if (ret < 0)
+ goto err_cleanup;
+
+ reply_len = ret + ethnl_reply_header_size();
+ rskb = ethnl_reply_init(reply_len, dev, ETHTOOL_MSG_TSCONFIG_SET_REPLY,
+ ETHTOOL_A_TSCONFIG_HEADER, info, &reply_payload);
+ if (!rskb)
+ goto err_cleanup;
+
+ ret = tsconfig_fill_reply(rskb, &req_info->base, &reply_data->base);
+ if (ret < 0)
+ goto err_cleanup;
+
+ genlmsg_end(rskb, reply_payload);
+ ret = genlmsg_reply(rskb, info);
+
+err_cleanup:
+ kfree(reply_data);
+ kfree(req_info);
+ return ret;
+}
+
+static int ethnl_set_tsconfig_validate(struct ethnl_req_info *req_base,
+ struct genl_info *info)
+{
+ const struct net_device_ops *ops = req_base->dev->netdev_ops;
+
+ if (!ops->ndo_hwtstamp_set || !ops->ndo_hwtstamp_get)
+ return -EOPNOTSUPP;
+
+ return 1;
+}
+
+static struct hwtstamp_provider *
+tsconfig_set_hwprov_from_desc(struct net_device *dev,
+ struct genl_info *info,
+ struct hwtstamp_provider_desc *hwprov_desc)
+{
+ struct kernel_ethtool_ts_info ts_info;
+ struct hwtstamp_provider *hwprov;
+ struct nlattr **tb = info->attrs;
+ struct phy_device *phy = NULL;
+ enum hwtstamp_source source;
+ int ret;
+
+ ret = ethtool_net_get_ts_info_by_phc(dev, &ts_info, hwprov_desc);
+ if (!ret) {
+ /* Found */
+ source = HWTSTAMP_SOURCE_NETDEV;
+ } else {
+ phy = ethtool_phy_get_ts_info_by_phc(dev, &ts_info, hwprov_desc);
+ if (IS_ERR(phy)) {
+ if (PTR_ERR(phy) == -ENODEV)
+ NL_SET_ERR_MSG_ATTR(info->extack,
+ tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER],
+ "phc not in this net device topology");
+ return ERR_CAST(phy);
+ }
+
+ source = HWTSTAMP_SOURCE_PHYLIB;
+ }
+
+ hwprov = kzalloc(sizeof(*hwprov), GFP_KERNEL);
+ if (!hwprov)
+ return ERR_PTR(-ENOMEM);
+
+ hwprov->desc.index = hwprov_desc->index;
+ hwprov->desc.qualifier = hwprov_desc->qualifier;
+ hwprov->source = source;
+ hwprov->phydev = phy;
+
+ return hwprov;
+}
+
+static int ethnl_set_tsconfig(struct ethnl_req_info *req_base,
+ struct genl_info *info)
+{
+ struct kernel_hwtstamp_config hwtst_config = {0};
+ bool hwprov_mod = false, config_mod = false;
+ struct hwtstamp_provider *hwprov = NULL;
+ struct net_device *dev = req_base->dev;
+ struct nlattr **tb = info->attrs;
+ int ret;
+
+ BUILD_BUG_ON(__HWTSTAMP_TX_CNT >= 32);
+ BUILD_BUG_ON(__HWTSTAMP_FILTER_CNT >= 32);
+
+ if (!netif_device_present(dev))
+ return -ENODEV;
+
+ if (tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER]) {
+ struct hwtstamp_provider_desc __hwprov_desc = {.index = -1};
+ struct hwtstamp_provider *__hwprov;
+
+ __hwprov = rtnl_dereference(dev->hwprov);
+ if (__hwprov) {
+ __hwprov_desc.index = __hwprov->desc.index;
+ __hwprov_desc.qualifier = __hwprov->desc.qualifier;
+ }
+
+ ret = ts_parse_hwtst_provider(tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_PROVIDER],
+ &__hwprov_desc, info->extack,
+ &hwprov_mod);
+ if (ret < 0)
+ return ret;
+
+ if (hwprov_mod) {
+ hwprov = tsconfig_set_hwprov_from_desc(dev, info,
+ &__hwprov_desc);
+ if (IS_ERR(hwprov))
+ return PTR_ERR(hwprov);
+ }
+ }
+
+ /* Get current hwtstamp config if we are not changing the
+ * hwtstamp source. It will be zeroed in the other case.
+ */
+ if (!hwprov_mod) {
+ ret = dev_get_hwtstamp_phylib(dev, &hwtst_config);
+ if (ret < 0 && ret != -EOPNOTSUPP)
+ goto err_free_hwprov;
+ }
+
+ /* Get the hwtstamp config from netlink */
+ if (tb[ETHTOOL_A_TSCONFIG_TX_TYPES]) {
+ u32 req_tx_type;
+
+ req_tx_type = BIT(hwtst_config.tx_type);
+ ret = ethnl_update_bitset32(&req_tx_type,
+ __HWTSTAMP_TX_CNT,
+ tb[ETHTOOL_A_TSCONFIG_TX_TYPES],
+ ts_tx_type_names, info->extack,
+ &config_mod);
+ if (ret < 0)
+ goto err_free_hwprov;
+
+ /* Select only one tx type at a time */
+ if (ffs(req_tx_type) != fls(req_tx_type)) {
+ ret = -EINVAL;
+ goto err_free_hwprov;
+ }
+
+ hwtst_config.tx_type = ffs(req_tx_type) - 1;
+ }
+
+ if (tb[ETHTOOL_A_TSCONFIG_RX_FILTERS]) {
+ u32 req_rx_filter;
+
+ req_rx_filter = BIT(hwtst_config.rx_filter);
+ ret = ethnl_update_bitset32(&req_rx_filter,
+ __HWTSTAMP_FILTER_CNT,
+ tb[ETHTOOL_A_TSCONFIG_RX_FILTERS],
+ ts_rx_filter_names, info->extack,
+ &config_mod);
+ if (ret < 0)
+ goto err_free_hwprov;
+
+ /* Select only one rx filter at a time */
+ if (ffs(req_rx_filter) != fls(req_rx_filter)) {
+ ret = -EINVAL;
+ goto err_free_hwprov;
+ }
+
+ hwtst_config.rx_filter = ffs(req_rx_filter) - 1;
+ }
+
+ if (tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS]) {
+ ethnl_update_u32(&hwtst_config.flags,
+ tb[ETHTOOL_A_TSCONFIG_HWTSTAMP_FLAGS],
+ &config_mod);
+ }
+
+ ret = net_hwtstamp_validate(&hwtst_config);
+ if (ret)
+ goto err_free_hwprov;
+
+ if (hwprov_mod) {
+ struct kernel_hwtstamp_config zero_config = {0};
+ struct hwtstamp_provider *__hwprov;
+
+ /* Disable current time stamping if we try to enable
+ * another one
+ */
+ ret = dev_set_hwtstamp_phylib(dev, &zero_config, info->extack);
+ if (ret < 0)
+ goto err_free_hwprov;
+
+ /* Change the selected hwtstamp source */
+ __hwprov = rcu_replace_pointer_rtnl(dev->hwprov, hwprov);
+ if (__hwprov)
+ kfree_rcu(__hwprov, rcu_head);
+ }
+
+ if (config_mod) {
+ ret = dev_set_hwtstamp_phylib(dev, &hwtst_config,
+ info->extack);
+ if (ret < 0)
+ return ret;
+ }
+
+ if (hwprov_mod || config_mod) {
+ ret = tsconfig_send_reply(dev, info);
+ if (ret && ret != -EOPNOTSUPP) {
+ NL_SET_ERR_MSG(info->extack,
+ "error while reading the new configuration set");
+ return ret;
+ }
+ }
+
+ /* tsconfig has no notification */
+ return 0;
+
+err_free_hwprov:
+ kfree(hwprov);
+
+ return ret;
+}
+
+const struct ethnl_request_ops ethnl_tsconfig_request_ops = {
+ .request_cmd = ETHTOOL_MSG_TSCONFIG_GET,
+ .reply_cmd = ETHTOOL_MSG_TSCONFIG_GET_REPLY,
+ .hdr_attr = ETHTOOL_A_TSCONFIG_HEADER,
+ .req_info_size = sizeof(struct tsconfig_req_info),
+ .reply_data_size = sizeof(struct tsconfig_reply_data),
+
+ .prepare_data = tsconfig_prepare_data,
+ .reply_size = tsconfig_reply_size,
+ .fill_reply = tsconfig_fill_reply,
+
+ .set_validate = ethnl_set_tsconfig_validate,
+ .set = ethnl_set_tsconfig,
+};
diff --git a/net/ethtool/tsinfo.c b/net/ethtool/tsinfo.c
index 03d12d6f79ca..7e495a41aeec 100644
--- a/net/ethtool/tsinfo.c
+++ b/net/ethtool/tsinfo.c
@@ -1,13 +1,18 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <linux/net_tstamp.h>
+#include <linux/phy.h>
+#include <linux/phy_link_topology.h>
+#include <linux/ptp_clock_kernel.h>
#include "netlink.h"
#include "common.h"
#include "bitset.h"
+#include "ts.h"
struct tsinfo_req_info {
struct ethnl_req_info base;
+ struct hwtstamp_provider_desc hwprov_desc;
};
struct tsinfo_reply_data {
@@ -16,34 +21,96 @@ struct tsinfo_reply_data {
struct ethtool_ts_stats stats;
};
+#define TSINFO_REQINFO(__req_base) \
+ container_of(__req_base, struct tsinfo_req_info, base)
+
#define TSINFO_REPDATA(__reply_base) \
container_of(__reply_base, struct tsinfo_reply_data, base)
#define ETHTOOL_TS_STAT_CNT \
(__ETHTOOL_A_TS_STAT_CNT - (ETHTOOL_A_TS_STAT_UNSPEC + 1))
-const struct nla_policy ethnl_tsinfo_get_policy[] = {
+const struct nla_policy ethnl_tsinfo_get_policy[ETHTOOL_A_TSINFO_MAX + 1] = {
[ETHTOOL_A_TSINFO_HEADER] =
NLA_POLICY_NESTED(ethnl_header_policy_stats),
+ [ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER] =
+ NLA_POLICY_NESTED(ethnl_ts_hwtst_prov_policy),
};
+int ts_parse_hwtst_provider(const struct nlattr *nest,
+ struct hwtstamp_provider_desc *hwprov_desc,
+ struct netlink_ext_ack *extack,
+ bool *mod)
+{
+ struct nlattr *tb[ARRAY_SIZE(ethnl_ts_hwtst_prov_policy)];
+ int ret;
+
+ ret = nla_parse_nested(tb,
+ ARRAY_SIZE(ethnl_ts_hwtst_prov_policy) - 1,
+ nest,
+ ethnl_ts_hwtst_prov_policy, extack);
+ if (ret < 0)
+ return ret;
+
+ if (NL_REQ_ATTR_CHECK(extack, nest, tb,
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX) ||
+ NL_REQ_ATTR_CHECK(extack, nest, tb,
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER))
+ return -EINVAL;
+
+ ethnl_update_u32(&hwprov_desc->index,
+ tb[ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX],
+ mod);
+ ethnl_update_u32(&hwprov_desc->qualifier,
+ tb[ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER],
+ mod);
+
+ return 0;
+}
+
+static int
+tsinfo_parse_request(struct ethnl_req_info *req_base, struct nlattr **tb,
+ struct netlink_ext_ack *extack)
+{
+ struct tsinfo_req_info *req = TSINFO_REQINFO(req_base);
+ bool mod = false;
+
+ req->hwprov_desc.index = -1;
+
+ if (!tb[ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER])
+ return 0;
+
+ return ts_parse_hwtst_provider(tb[ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER],
+ &req->hwprov_desc, extack, &mod);
+}
+
static int tsinfo_prepare_data(const struct ethnl_req_info *req_base,
struct ethnl_reply_data *reply_base,
const struct genl_info *info)
{
struct tsinfo_reply_data *data = TSINFO_REPDATA(reply_base);
+ struct tsinfo_req_info *req = TSINFO_REQINFO(req_base);
struct net_device *dev = reply_base->dev;
int ret;
ret = ethnl_ops_begin(dev);
if (ret < 0)
return ret;
+
+ if (req->hwprov_desc.index != -1) {
+ ret = ethtool_get_ts_info_by_phc(dev, &data->ts_info,
+ &req->hwprov_desc);
+ ethnl_ops_complete(dev);
+ return ret;
+ }
+
if (req_base->flags & ETHTOOL_FLAG_STATS) {
ethtool_stats_init((u64 *)&data->stats,
sizeof(data->stats) / sizeof(u64));
if (dev->ethtool_ops->get_ts_stats)
dev->ethtool_ops->get_ts_stats(dev, &data->stats);
}
+
ret = __ethtool_get_ts_info(dev, &data->ts_info);
ethnl_ops_complete(dev);
@@ -87,8 +154,11 @@ static int tsinfo_reply_size(const struct ethnl_req_info *req_base,
return ret;
len += ret; /* _TSINFO_RX_FILTERS */
}
- if (ts_info->phc_index >= 0)
+ if (ts_info->phc_index >= 0) {
len += nla_total_size(sizeof(u32)); /* _TSINFO_PHC_INDEX */
+ /* _TSINFO_HWTSTAMP_PROVIDER */
+ len += nla_total_size(0) + 2 * nla_total_size(sizeof(u32));
+ }
if (req_base->flags & ETHTOOL_FLAG_STATS)
len += nla_total_size(0) + /* _TSINFO_STATS */
nla_total_size_64bit(sizeof(u64)) * ETHTOOL_TS_STAT_CNT;
@@ -163,9 +233,29 @@ static int tsinfo_fill_reply(struct sk_buff *skb,
if (ret < 0)
return ret;
}
- if (ts_info->phc_index >= 0 &&
- nla_put_u32(skb, ETHTOOL_A_TSINFO_PHC_INDEX, ts_info->phc_index))
- return -EMSGSIZE;
+ if (ts_info->phc_index >= 0) {
+ struct nlattr *nest;
+
+ ret = nla_put_u32(skb, ETHTOOL_A_TSINFO_PHC_INDEX,
+ ts_info->phc_index);
+ if (ret)
+ return -EMSGSIZE;
+
+ nest = nla_nest_start(skb, ETHTOOL_A_TSINFO_HWTSTAMP_PROVIDER);
+ if (!nest)
+ return -EMSGSIZE;
+
+ if (nla_put_u32(skb, ETHTOOL_A_TS_HWTSTAMP_PROVIDER_INDEX,
+ ts_info->phc_index) ||
+ nla_put_u32(skb,
+ ETHTOOL_A_TS_HWTSTAMP_PROVIDER_QUALIFIER,
+ ts_info->phc_qualifier)) {
+ nla_nest_cancel(skb, nest);
+ return -EMSGSIZE;
+ }
+
+ nla_nest_end(skb, nest);
+ }
if (req_base->flags & ETHTOOL_FLAG_STATS &&
tsinfo_put_stats(skb, &data->stats))
return -EMSGSIZE;
@@ -173,6 +263,263 @@ static int tsinfo_fill_reply(struct sk_buff *skb,
return 0;
}
+struct ethnl_tsinfo_dump_ctx {
+ struct tsinfo_req_info *req_info;
+ struct tsinfo_reply_data *reply_data;
+ unsigned long pos_ifindex;
+ bool netdev_dump_done;
+ unsigned long pos_phyindex;
+ enum hwtstamp_provider_qualifier pos_phcqualifier;
+};
+
+static void *ethnl_tsinfo_prepare_dump(struct sk_buff *skb,
+ struct net_device *dev,
+ struct tsinfo_reply_data *reply_data,
+ struct netlink_callback *cb)
+{
+ struct ethnl_tsinfo_dump_ctx *ctx = (void *)cb->ctx;
+ void *ehdr = NULL;
+
+ ehdr = ethnl_dump_put(skb, cb,
+ ETHTOOL_MSG_TSINFO_GET_REPLY);
+ if (!ehdr)
+ return ERR_PTR(-EMSGSIZE);
+
+ reply_data = ctx->reply_data;
+ memset(reply_data, 0, sizeof(*reply_data));
+ reply_data->base.dev = dev;
+ memset(&reply_data->ts_info, 0, sizeof(reply_data->ts_info));
+
+ return ehdr;
+}
+
+static int ethnl_tsinfo_end_dump(struct sk_buff *skb,
+ struct net_device *dev,
+ struct tsinfo_req_info *req_info,
+ struct tsinfo_reply_data *reply_data,
+ void *ehdr)
+{
+ int ret;
+
+ reply_data->ts_info.so_timestamping |= SOF_TIMESTAMPING_RX_SOFTWARE |
+ SOF_TIMESTAMPING_SOFTWARE;
+
+ ret = ethnl_fill_reply_header(skb, dev, ETHTOOL_A_TSINFO_HEADER);
+ if (ret < 0)
+ return ret;
+
+ ret = tsinfo_fill_reply(skb, &req_info->base, &reply_data->base);
+ if (ret < 0)
+ return ret;
+
+ reply_data->base.dev = NULL;
+ genlmsg_end(skb, ehdr);
+
+ return ret;
+}
+
+static int ethnl_tsinfo_dump_one_phydev(struct sk_buff *skb,
+ struct net_device *dev,
+ struct phy_device *phydev,
+ struct netlink_callback *cb)
+{
+ struct ethnl_tsinfo_dump_ctx *ctx = (void *)cb->ctx;
+ struct tsinfo_reply_data *reply_data;
+ struct tsinfo_req_info *req_info;
+ void *ehdr = NULL;
+ int ret = 0;
+
+ if (!phy_has_tsinfo(phydev))
+ return -EOPNOTSUPP;
+
+ reply_data = ctx->reply_data;
+ req_info = ctx->req_info;
+ ehdr = ethnl_tsinfo_prepare_dump(skb, dev, reply_data, cb);
+ if (IS_ERR(ehdr))
+ return PTR_ERR(ehdr);
+
+ ret = phy_ts_info(phydev, &reply_data->ts_info);
+ if (ret < 0)
+ goto err;
+
+ ret = ethnl_tsinfo_end_dump(skb, dev, req_info, reply_data, ehdr);
+ if (ret < 0)
+ goto err;
+
+ return ret;
+err:
+ genlmsg_cancel(skb, ehdr);
+ return ret;
+}
+
+static int ethnl_tsinfo_dump_one_netdev(struct sk_buff *skb,
+ struct net_device *dev,
+ struct netlink_callback *cb)
+{
+ struct ethnl_tsinfo_dump_ctx *ctx = (void *)cb->ctx;
+ const struct ethtool_ops *ops = dev->ethtool_ops;
+ struct tsinfo_reply_data *reply_data;
+ struct tsinfo_req_info *req_info;
+ void *ehdr = NULL;
+ int ret = 0;
+
+ if (!ops->get_ts_info)
+ return -EOPNOTSUPP;
+
+ reply_data = ctx->reply_data;
+ req_info = ctx->req_info;
+ for (; ctx->pos_phcqualifier < HWTSTAMP_PROVIDER_QUALIFIER_CNT;
+ ctx->pos_phcqualifier++) {
+ if (!net_support_hwtstamp_qualifier(dev,
+ ctx->pos_phcqualifier))
+ continue;
+
+ ehdr = ethnl_tsinfo_prepare_dump(skb, dev, reply_data, cb);
+ if (IS_ERR(ehdr)) {
+ ret = PTR_ERR(ehdr);
+ goto err;
+ }
+
+ reply_data->ts_info.phc_qualifier = ctx->pos_phcqualifier;
+ ret = ops->get_ts_info(dev, &reply_data->ts_info);
+ if (ret < 0)
+ goto err;
+
+ ret = ethnl_tsinfo_end_dump(skb, dev, req_info, reply_data,
+ ehdr);
+ if (ret < 0)
+ goto err;
+ }
+
+ return ret;
+
+err:
+ genlmsg_cancel(skb, ehdr);
+ return ret;
+}
+
+static int ethnl_tsinfo_dump_one_net_topo(struct sk_buff *skb,
+ struct net_device *dev,
+ struct netlink_callback *cb)
+{
+ struct ethnl_tsinfo_dump_ctx *ctx = (void *)cb->ctx;
+ struct phy_device_node *pdn;
+ int ret = 0;
+
+ if (!ctx->netdev_dump_done) {
+ ret = ethnl_tsinfo_dump_one_netdev(skb, dev, cb);
+ if (ret < 0 && ret != -EOPNOTSUPP)
+ return ret;
+ ctx->netdev_dump_done = true;
+ }
+
+ if (!dev->link_topo) {
+ if (phy_has_tsinfo(dev->phydev)) {
+ ret = ethnl_tsinfo_dump_one_phydev(skb, dev,
+ dev->phydev, cb);
+ if (ret < 0 && ret != -EOPNOTSUPP)
+ return ret;
+ }
+
+ return 0;
+ }
+
+ xa_for_each_start(&dev->link_topo->phys, ctx->pos_phyindex, pdn,
+ ctx->pos_phyindex) {
+ if (phy_has_tsinfo(pdn->phy)) {
+ ret = ethnl_tsinfo_dump_one_phydev(skb, dev,
+ pdn->phy, cb);
+ if (ret < 0 && ret != -EOPNOTSUPP)
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+int ethnl_tsinfo_dumpit(struct sk_buff *skb, struct netlink_callback *cb)
+{
+ struct ethnl_tsinfo_dump_ctx *ctx = (void *)cb->ctx;
+ struct net *net = sock_net(skb->sk);
+ struct net_device *dev;
+ int ret = 0;
+
+ rtnl_lock();
+ if (ctx->req_info->base.dev) {
+ ret = ethnl_tsinfo_dump_one_net_topo(skb,
+ ctx->req_info->base.dev,
+ cb);
+ } else {
+ for_each_netdev_dump(net, dev, ctx->pos_ifindex) {
+ ret = ethnl_tsinfo_dump_one_net_topo(skb, dev, cb);
+ if (ret < 0 && ret != -EOPNOTSUPP)
+ break;
+ ctx->pos_phyindex = 0;
+ ctx->netdev_dump_done = false;
+ ctx->pos_phcqualifier = HWTSTAMP_PROVIDER_QUALIFIER_PRECISE;
+ }
+ }
+ rtnl_unlock();
+
+ return ret;
+}
+
+int ethnl_tsinfo_start(struct netlink_callback *cb)
+{
+ const struct genl_dumpit_info *info = genl_dumpit_info(cb);
+ struct ethnl_tsinfo_dump_ctx *ctx = (void *)cb->ctx;
+ struct nlattr **tb = info->info.attrs;
+ struct tsinfo_reply_data *reply_data;
+ struct tsinfo_req_info *req_info;
+ int ret;
+
+ BUILD_BUG_ON(sizeof(*ctx) > sizeof(cb->ctx));
+
+ req_info = kzalloc(sizeof(*req_info), GFP_KERNEL);
+ if (!req_info)
+ return -ENOMEM;
+ reply_data = kzalloc(sizeof(*reply_data), GFP_KERNEL);
+ if (!reply_data) {
+ ret = -ENOMEM;
+ goto free_req_info;
+ }
+
+ ret = ethnl_parse_header_dev_get(&req_info->base,
+ tb[ETHTOOL_A_TSINFO_HEADER],
+ sock_net(cb->skb->sk), cb->extack,
+ false);
+ if (ret < 0)
+ goto free_reply_data;
+
+ ctx->req_info = req_info;
+ ctx->reply_data = reply_data;
+ ctx->pos_ifindex = 0;
+ ctx->pos_phyindex = 0;
+ ctx->netdev_dump_done = false;
+ ctx->pos_phcqualifier = HWTSTAMP_PROVIDER_QUALIFIER_PRECISE;
+
+ return 0;
+
+free_reply_data:
+ kfree(reply_data);
+free_req_info:
+ kfree(req_info);
+
+ return ret;
+}
+
+int ethnl_tsinfo_done(struct netlink_callback *cb)
+{
+ struct ethnl_tsinfo_dump_ctx *ctx = (void *)cb->ctx;
+ struct tsinfo_req_info *req_info = ctx->req_info;
+
+ ethnl_parse_header_dev_put(&req_info->base);
+ kfree(ctx->reply_data);
+ kfree(ctx->req_info);
+
+ return 0;
+}
+
const struct ethnl_request_ops ethnl_tsinfo_request_ops = {
.request_cmd = ETHTOOL_MSG_TSINFO_GET,
.reply_cmd = ETHTOOL_MSG_TSINFO_GET_REPLY,
@@ -180,6 +527,7 @@ const struct ethnl_request_ops ethnl_tsinfo_request_ops = {
.req_info_size = sizeof(struct tsinfo_req_info),
.reply_data_size = sizeof(struct tsinfo_reply_data),
+ .parse_request = tsinfo_parse_request,
.prepare_data = tsinfo_prepare_data,
.reply_size = tsinfo_reply_size,
.fill_reply = tsinfo_fill_reply,
diff --git a/net/handshake/handshake-test.c b/net/handshake/handshake-test.c
index 34fd1d9b2db8..55442b2f518a 100644
--- a/net/handshake/handshake-test.c
+++ b/net/handshake/handshake-test.c
@@ -17,7 +17,7 @@
#include <uapi/linux/handshake.h>
#include "handshake.h"
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static int test_accept_func(struct handshake_req *req, struct genl_info *info,
int fd)
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c
index 31a416ee21ad..03eadd6c51fd 100644
--- a/net/hsr/hsr_device.c
+++ b/net/hsr/hsr_device.c
@@ -246,20 +246,22 @@ static const struct header_ops hsr_header_ops = {
.parse = eth_header_parse,
};
-static struct sk_buff *hsr_init_skb(struct hsr_port *master)
+static struct sk_buff *hsr_init_skb(struct hsr_port *master, int extra)
{
struct hsr_priv *hsr = master->hsr;
struct sk_buff *skb;
int hlen, tlen;
+ int len;
hlen = LL_RESERVED_SPACE(master->dev);
tlen = master->dev->needed_tailroom;
+ len = sizeof(struct hsr_sup_tag) + sizeof(struct hsr_sup_payload);
/* skb size is same for PRP/HSR frames, only difference
* being, for PRP it is a trailer and for HSR it is a
- * header
+ * header.
+ * RedBox might use @extra more bytes.
*/
- skb = dev_alloc_skb(sizeof(struct hsr_sup_tag) +
- sizeof(struct hsr_sup_payload) + hlen + tlen);
+ skb = dev_alloc_skb(len + extra + hlen + tlen);
if (!skb)
return skb;
@@ -295,6 +297,7 @@ static void send_hsr_supervision_frame(struct hsr_port *port,
struct hsr_sup_tlv *hsr_stlv;
struct hsr_sup_tag *hsr_stag;
struct sk_buff *skb;
+ int extra = 0;
*interval = msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL);
if (hsr->announce_count < 3 && hsr->prot_version == 0) {
@@ -303,7 +306,11 @@ static void send_hsr_supervision_frame(struct hsr_port *port,
hsr->announce_count++;
}
- skb = hsr_init_skb(port);
+ if (hsr->redbox)
+ extra = sizeof(struct hsr_sup_tlv) +
+ sizeof(struct hsr_sup_payload);
+
+ skb = hsr_init_skb(port, extra);
if (!skb) {
netdev_warn_once(port->dev, "HSR: Could not send supervision frame\n");
return;
@@ -362,7 +369,7 @@ static void send_prp_supervision_frame(struct hsr_port *master,
struct hsr_sup_tag *hsr_stag;
struct sk_buff *skb;
- skb = hsr_init_skb(master);
+ skb = hsr_init_skb(master, 0);
if (!skb) {
netdev_warn_once(master->dev, "PRP: Could not send supervision frame\n");
return;
diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c
index aa6acebc7c1e..87bb3a91598e 100644
--- a/net/hsr/hsr_forward.c
+++ b/net/hsr/hsr_forward.c
@@ -700,6 +700,8 @@ static int fill_frame_info(struct hsr_frame_info *frame,
frame->is_vlan = true;
if (frame->is_vlan) {
+ if (skb->mac_len < offsetofend(struct hsr_vlan_ethhdr, vlanhdr))
+ return -EINVAL;
vlan_hdr = (struct hsr_vlan_ethhdr *)ethhdr;
proto = vlan_hdr->vlanhdr.h_vlan_encapsulated_proto;
}
diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h
index fcfeb79bb040..7d7551e6f0b0 100644
--- a/net/hsr/hsr_main.h
+++ b/net/hsr/hsr_main.h
@@ -163,6 +163,7 @@ struct hsr_port {
struct net_device *dev;
struct hsr_priv *hsr;
enum hsr_port_type type;
+ struct rcu_head rcu;
};
struct hsr_frame_info;
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c
index 464f683e016d..2a802a5de2ac 100644
--- a/net/hsr/hsr_slave.c
+++ b/net/hsr/hsr_slave.c
@@ -204,7 +204,6 @@ int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev,
}
list_add_tail_rcu(&port->port_list, &hsr->ports);
- synchronize_rcu();
master = hsr_port_get_hsr(hsr, HSR_PT_MASTER);
netdev_update_features(master->dev);
@@ -235,7 +234,5 @@ void hsr_del_port(struct hsr_port *port)
netdev_upper_dev_unlink(port->dev, master->dev);
}
- synchronize_rcu();
-
- kfree(port);
+ kfree_rcu(port, rcu);
}
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 8095e82de808..21f46ee7b6e9 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1309,8 +1309,6 @@ int inet_sk_rebuild_header(struct sock *sk)
{
struct rtable *rt = dst_rtable(__sk_dst_check(sk, 0));
struct inet_sock *inet = inet_sk(sk);
- __be32 daddr;
- struct ip_options_rcu *inet_opt;
struct flowi4 *fl4;
int err;
@@ -1319,17 +1317,9 @@ int inet_sk_rebuild_header(struct sock *sk)
return 0;
/* Reroute. */
- rcu_read_lock();
- inet_opt = rcu_dereference(inet->inet_opt);
- daddr = inet->inet_daddr;
- if (inet_opt && inet_opt->opt.srr)
- daddr = inet_opt->opt.faddr;
- rcu_read_unlock();
fl4 = &inet->cork.fl.u.ip4;
- rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, inet->inet_saddr,
- inet->inet_dport, inet->inet_sport,
- sk->sk_protocol, ip_sock_rt_tos(sk),
- sk->sk_bound_dev_if);
+ inet_sk_init_flowi4(inet, fl4);
+ rt = ip_route_output_flow(sock_net(sk), fl4, sk);
if (!IS_ERR(rt)) {
err = 0;
sk_setup_caps(sk, &rt->dst);
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index cc6d0bd7b0a9..4b5bc6eb52e7 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -61,15 +61,17 @@ int __ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
err = -EACCES;
goto out;
}
+
+ /* Update addresses before rehashing */
+ inet->inet_daddr = fl4->daddr;
+ inet->inet_dport = usin->sin_port;
if (!inet->inet_saddr)
- inet->inet_saddr = fl4->saddr; /* Update source address */
+ inet->inet_saddr = fl4->saddr;
if (!inet->inet_rcv_saddr) {
inet->inet_rcv_saddr = fl4->saddr;
if (sk->sk_prot->rehash)
sk->sk_prot->rehash(sk);
}
- inet->inet_daddr = fl4->daddr;
- inet->inet_dport = usin->sin_port;
reuseport_has_conns_set(sk);
sk->sk_state = TCP_ESTABLISHED;
sk_set_txhash(sk);
@@ -100,8 +102,6 @@ EXPORT_SYMBOL(ip4_datagram_connect);
void ip4_datagram_release_cb(struct sock *sk)
{
const struct inet_sock *inet = inet_sk(sk);
- const struct ip_options_rcu *inet_opt;
- __be32 daddr = inet->inet_daddr;
struct dst_entry *dst;
struct flowi4 fl4;
struct rtable *rt;
@@ -113,14 +113,9 @@ void ip4_datagram_release_cb(struct sock *sk)
rcu_read_unlock();
return;
}
- inet_opt = rcu_dereference(inet->inet_opt);
- if (inet_opt && inet_opt->opt.srr)
- daddr = inet_opt->opt.faddr;
- rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr,
- inet->inet_saddr, inet->inet_dport,
- inet->inet_sport, sk->sk_protocol,
- ip_sock_rt_tos(sk), sk->sk_bound_dev_if);
+ inet_sk_init_flowi4(inet, &fl4);
+ rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
dst = !IS_ERR(rt) ? &rt->dst : NULL;
sk_dst_set(sk, dst);
diff --git a/net/ipv4/fib_rules.c b/net/ipv4/fib_rules.c
index 8325224ef072..9517b8667e00 100644
--- a/net/ipv4/fib_rules.c
+++ b/net/ipv4/fib_rules.c
@@ -249,6 +249,12 @@ static int fib4_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
int err = -EINVAL;
struct fib4_rule *rule4 = (struct fib4_rule *) rule;
+ if (tb[FRA_FLOWLABEL] || tb[FRA_FLOWLABEL_MASK]) {
+ NL_SET_ERR_MSG(extack,
+ "Flow label cannot be specified for IPv4 FIB rules");
+ goto errout;
+ }
+
if (!inet_validate_dscp(frh->tos)) {
NL_SET_ERR_MSG(extack,
"Invalid dsfield (tos): ECN bits must be 0");
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c
index 161f5526b86c..d6411ac81096 100644
--- a/net/ipv4/fib_trie.c
+++ b/net/ipv4/fib_trie.c
@@ -2999,7 +2999,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
seq_printf(seq,
"%s\t%08X\t%08X\t%04X\t%d\t%u\t"
- "%d\t%08X\t%d\t%u\t%u",
+ "%u\t%08X\t%d\t%u\t%u",
nhc->nhc_dev ? nhc->nhc_dev->name : "*",
prefix, gw, flags, 0, 0,
fi->fib_priority,
@@ -3011,7 +3011,7 @@ static int fib_route_seq_show(struct seq_file *seq, void *v)
} else {
seq_printf(seq,
"*\t%08X\t%08X\t%04X\t%d\t%u\t"
- "%d\t%08X\t%d\t%u\t%u",
+ "%u\t%08X\t%d\t%u\t%u",
prefix, 0, flags, 0, 0, 0,
mask, 0, 0, 0);
}
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c
index 4f088fa1c2f2..094084b61bff 100644
--- a/net/ipv4/icmp.c
+++ b/net/ipv4/icmp.c
@@ -312,7 +312,6 @@ static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
struct dst_entry *dst = &rt->dst;
struct inet_peer *peer;
bool rc = true;
- int vif;
if (!apply_ratelimit)
return true;
@@ -321,12 +320,12 @@ static bool icmpv4_xrlim_allow(struct net *net, struct rtable *rt,
if (dst->dev && (dst->dev->flags&IFF_LOOPBACK))
goto out;
- vif = l3mdev_master_ifindex(dst->dev);
- peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr, vif, 1);
+ rcu_read_lock();
+ peer = inet_getpeer_v4(net->ipv4.peers, fl4->daddr,
+ l3mdev_master_ifindex_rcu(dst->dev));
rc = inet_peer_xrlim_allow(peer,
READ_ONCE(net->ipv4.sysctl_icmp_ratelimit));
- if (peer)
- inet_putpeer(peer);
+ rcu_read_unlock();
out:
if (!rc)
__ICMP_INC_STATS(net, ICMP_MIB_RATELIMITHOST);
@@ -517,6 +516,9 @@ static struct rtable *icmp_route_lookup(struct net *net, struct flowi4 *fl4,
if (!IS_ERR(dst)) {
if (rt != rt2)
return rt;
+ if (inet_addr_type_dev_table(net, route_lookup_dev,
+ fl4->daddr) == RTN_LOCAL)
+ return rt;
} else if (PTR_ERR(dst) == -EPERM) {
rt = NULL;
} else {
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c
index 6a238398acc9..3da126cea884 100644
--- a/net/ipv4/igmp.c
+++ b/net/ipv4/igmp.c
@@ -88,6 +88,8 @@
#include <linux/byteorder/generic.h>
#include <net/net_namespace.h>
+#include <net/netlink.h>
+#include <net/addrconf.h>
#include <net/arp.h>
#include <net/ip.h>
#include <net/protocol.h>
@@ -1430,6 +1432,65 @@ static void ip_mc_hash_remove(struct in_device *in_dev,
*mc_hash = im->next_hash;
}
+static int inet_fill_ifmcaddr(struct sk_buff *skb, struct net_device *dev,
+ const struct ip_mc_list *im, int event)
+{
+ struct ifa_cacheinfo ci;
+ struct ifaddrmsg *ifm;
+ struct nlmsghdr *nlh;
+
+ nlh = nlmsg_put(skb, 0, 0, event, sizeof(struct ifaddrmsg), 0);
+ if (!nlh)
+ return -EMSGSIZE;
+
+ ifm = nlmsg_data(nlh);
+ ifm->ifa_family = AF_INET;
+ ifm->ifa_prefixlen = 32;
+ ifm->ifa_flags = IFA_F_PERMANENT;
+ ifm->ifa_scope = RT_SCOPE_UNIVERSE;
+ ifm->ifa_index = dev->ifindex;
+
+ ci.cstamp = (READ_ONCE(im->mca_cstamp) - INITIAL_JIFFIES) * 100UL / HZ;
+ ci.tstamp = ci.cstamp;
+ ci.ifa_prefered = INFINITY_LIFE_TIME;
+ ci.ifa_valid = INFINITY_LIFE_TIME;
+
+ if (nla_put_in_addr(skb, IFA_MULTICAST, im->multiaddr) < 0 ||
+ nla_put(skb, IFA_CACHEINFO, sizeof(ci), &ci) < 0) {
+ nlmsg_cancel(skb, nlh);
+ return -EMSGSIZE;
+ }
+
+ nlmsg_end(skb, nlh);
+ return 0;
+}
+
+static void inet_ifmcaddr_notify(struct net_device *dev,
+ const struct ip_mc_list *im, int event)
+{
+ struct net *net = dev_net(dev);
+ struct sk_buff *skb;
+ int err = -ENOMEM;
+
+ skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
+ nla_total_size(sizeof(__be32)) +
+ nla_total_size(sizeof(struct ifa_cacheinfo)),
+ GFP_KERNEL);
+ if (!skb)
+ goto error;
+
+ err = inet_fill_ifmcaddr(skb, dev, im, event);
+ if (err < 0) {
+ WARN_ON_ONCE(err == -EMSGSIZE);
+ nlmsg_free(skb);
+ goto error;
+ }
+
+ rtnl_notify(skb, net, 0, RTNLGRP_IPV4_MCADDR, NULL, GFP_KERNEL);
+ return;
+error:
+ rtnl_set_sk_err(net, RTNLGRP_IPV4_MCADDR, err);
+}
/*
* A socket has joined a multicast group on device dev.
@@ -1473,6 +1534,8 @@ static void ____ip_mc_inc_group(struct in_device *in_dev, __be32 addr,
im->interface = in_dev;
in_dev_hold(in_dev);
im->multiaddr = addr;
+ im->mca_cstamp = jiffies;
+ im->mca_tstamp = im->mca_cstamp;
/* initial mode is (EX, empty) */
im->sfmode = mode;
im->sfcount[mode] = 1;
@@ -1492,6 +1555,7 @@ static void ____ip_mc_inc_group(struct in_device *in_dev, __be32 addr,
igmpv3_del_delrec(in_dev, im);
#endif
igmp_group_added(im);
+ inet_ifmcaddr_notify(in_dev->dev, im, RTM_NEWMULTICAST);
if (!in_dev->dead)
ip_rt_multicast_event(in_dev);
out:
@@ -1705,6 +1769,8 @@ void __ip_mc_dec_group(struct in_device *in_dev, __be32 addr, gfp_t gfp)
*ip = i->next_rcu;
in_dev->mc_count--;
__igmp_group_dropped(i, gfp);
+ inet_ifmcaddr_notify(in_dev->dev, i,
+ RTM_DELMULTICAST);
ip_mc_clear_src(i);
if (!in_dev->dead)
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
index 6872b5aff73e..e4decfb270fa 100644
--- a/net/ipv4/inet_connection_sock.c
+++ b/net/ipv4/inet_connection_sock.c
@@ -1561,20 +1561,13 @@ EXPORT_SYMBOL_GPL(inet_csk_addr2sockaddr);
static struct dst_entry *inet_csk_rebuild_route(struct sock *sk, struct flowi *fl)
{
const struct inet_sock *inet = inet_sk(sk);
- const struct ip_options_rcu *inet_opt;
- __be32 daddr = inet->inet_daddr;
struct flowi4 *fl4;
struct rtable *rt;
rcu_read_lock();
- inet_opt = rcu_dereference(inet->inet_opt);
- if (inet_opt && inet_opt->opt.srr)
- daddr = inet_opt->opt.faddr;
fl4 = &fl->u.ip4;
- rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr,
- inet->inet_saddr, inet->inet_dport,
- inet->inet_sport, sk->sk_protocol,
- ip_sock_rt_tos(sk), sk->sk_bound_dev_if);
+ inet_sk_init_flowi4(inet, fl4);
+ rt = ip_route_output_flow(sock_net(sk), fl4, sk);
if (IS_ERR(rt))
rt = NULL;
if (rt)
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 5ab56f4cb529..b8b23a77ceb4 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -95,6 +95,7 @@ static struct inet_peer *lookup(const struct inetpeer_addr *daddr,
{
struct rb_node **pp, *parent, *next;
struct inet_peer *p;
+ u32 now;
pp = &base->rb_root.rb_node;
parent = NULL;
@@ -108,8 +109,9 @@ static struct inet_peer *lookup(const struct inetpeer_addr *daddr,
p = rb_entry(parent, struct inet_peer, rb_node);
cmp = inetpeer_addr_cmp(daddr, &p->daddr);
if (cmp == 0) {
- if (!refcount_inc_not_zero(&p->refcnt))
- break;
+ now = jiffies;
+ if (READ_ONCE(p->dtime) != now)
+ WRITE_ONCE(p->dtime, now);
return p;
}
if (gc_stack) {
@@ -150,9 +152,6 @@ static void inet_peer_gc(struct inet_peer_base *base,
for (i = 0; i < gc_cnt; i++) {
p = gc_stack[i];
- /* The READ_ONCE() pairs with the WRITE_ONCE()
- * in inet_putpeer()
- */
delta = (__u32)jiffies - READ_ONCE(p->dtime);
if (delta < ttl || !refcount_dec_if_one(&p->refcnt))
@@ -168,31 +167,23 @@ static void inet_peer_gc(struct inet_peer_base *base,
}
}
+/* Must be called under RCU : No refcount change is done here. */
struct inet_peer *inet_getpeer(struct inet_peer_base *base,
- const struct inetpeer_addr *daddr,
- int create)
+ const struct inetpeer_addr *daddr)
{
struct inet_peer *p, *gc_stack[PEER_MAX_GC];
struct rb_node **pp, *parent;
unsigned int gc_cnt, seq;
- int invalidated;
/* Attempt a lockless lookup first.
* Because of a concurrent writer, we might not find an existing entry.
*/
- rcu_read_lock();
seq = read_seqbegin(&base->lock);
p = lookup(daddr, base, seq, NULL, &gc_cnt, &parent, &pp);
- invalidated = read_seqretry(&base->lock, seq);
- rcu_read_unlock();
if (p)
return p;
- /* If no writer did a change during our lookup, we can return early. */
- if (!create && !invalidated)
- return NULL;
-
/* retry an exact lookup, taking the lock before.
* At least, nodes should be hot in our cache.
*/
@@ -201,12 +192,12 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
gc_cnt = 0;
p = lookup(daddr, base, seq, gc_stack, &gc_cnt, &parent, &pp);
- if (!p && create) {
+ if (!p) {
p = kmem_cache_alloc(peer_cachep, GFP_ATOMIC);
if (p) {
p->daddr = *daddr;
p->dtime = (__u32)jiffies;
- refcount_set(&p->refcnt, 2);
+ refcount_set(&p->refcnt, 1);
atomic_set(&p->rid, 0);
p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
p->rate_tokens = 0;
@@ -231,15 +222,9 @@ EXPORT_SYMBOL_GPL(inet_getpeer);
void inet_putpeer(struct inet_peer *p)
{
- /* The WRITE_ONCE() pairs with itself (we run lockless)
- * and the READ_ONCE() in inet_peer_gc()
- */
- WRITE_ONCE(p->dtime, (__u32)jiffies);
-
if (refcount_dec_and_test(&p->refcnt))
kfree_rcu(p, rcu);
}
-EXPORT_SYMBOL_GPL(inet_putpeer);
/*
* Check transmit rate limitation for given message.
@@ -261,23 +246,27 @@ EXPORT_SYMBOL_GPL(inet_putpeer);
#define XRLIM_BURST_FACTOR 6
bool inet_peer_xrlim_allow(struct inet_peer *peer, int timeout)
{
- unsigned long now, token;
+ unsigned long now, token, otoken, delta;
bool rc = false;
if (!peer)
return true;
- token = peer->rate_tokens;
+ token = otoken = READ_ONCE(peer->rate_tokens);
now = jiffies;
- token += now - peer->rate_last;
- peer->rate_last = now;
- if (token > XRLIM_BURST_FACTOR * timeout)
- token = XRLIM_BURST_FACTOR * timeout;
+ delta = now - READ_ONCE(peer->rate_last);
+ if (delta) {
+ WRITE_ONCE(peer->rate_last, now);
+ token += delta;
+ if (token > XRLIM_BURST_FACTOR * timeout)
+ token = XRLIM_BURST_FACTOR * timeout;
+ }
if (token >= timeout) {
token -= timeout;
rc = true;
}
- peer->rate_tokens = token;
+ if (token != otoken)
+ WRITE_ONCE(peer->rate_tokens, token);
return rc;
}
EXPORT_SYMBOL(inet_peer_xrlim_allow);
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c
index 07036a2943c1..7a435746a22d 100644
--- a/net/ipv4/ip_fragment.c
+++ b/net/ipv4/ip_fragment.c
@@ -82,15 +82,20 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *skb,
static void ip4_frag_init(struct inet_frag_queue *q, const void *a)
{
struct ipq *qp = container_of(q, struct ipq, q);
- struct net *net = q->fqdir->net;
-
const struct frag_v4_compare_key *key = a;
+ struct net *net = q->fqdir->net;
+ struct inet_peer *p = NULL;
q->key.v4 = *key;
qp->ecn = 0;
- qp->peer = q->fqdir->max_dist ?
- inet_getpeer_v4(net->ipv4.peers, key->saddr, key->vif, 1) :
- NULL;
+ if (q->fqdir->max_dist) {
+ rcu_read_lock();
+ p = inet_getpeer_v4(net->ipv4.peers, key->saddr, key->vif);
+ if (p && !refcount_inc_not_zero(&p->refcnt))
+ p = NULL;
+ rcu_read_unlock();
+ }
+ qp->peer = p;
}
static void ip4_frag_free(struct inet_frag_queue *q)
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index f1f31ebfc793..a020342f618d 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -924,15 +924,18 @@ static int ipgre_open(struct net_device *dev)
struct ip_tunnel *t = netdev_priv(dev);
if (ipv4_is_multicast(t->parms.iph.daddr)) {
- struct flowi4 fl4;
+ struct flowi4 fl4 = {
+ .flowi4_oif = t->parms.link,
+ .flowi4_tos = t->parms.iph.tos & INET_DSCP_MASK,
+ .flowi4_scope = RT_SCOPE_UNIVERSE,
+ .flowi4_proto = IPPROTO_GRE,
+ .saddr = t->parms.iph.saddr,
+ .daddr = t->parms.iph.daddr,
+ .fl4_gre_key = t->parms.o_key,
+ };
struct rtable *rt;
- rt = ip_route_output_gre(t->net, &fl4,
- t->parms.iph.daddr,
- t->parms.iph.saddr,
- t->parms.o_key,
- t->parms.iph.tos & INET_DSCP_MASK,
- t->parms.link);
+ rt = ip_route_output_key(t->net, &fl4);
if (IS_ERR(rt))
return -EADDRNOTAVAIL;
dev = rt->dst.dev;
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c
index f0a4dda246ab..30a5e9460d00 100644
--- a/net/ipv4/ip_input.c
+++ b/net/ipv4/ip_input.c
@@ -314,7 +314,7 @@ static bool ip_can_use_hint(const struct sk_buff *skb, const struct iphdr *iph,
int tcp_v4_early_demux(struct sk_buff *skb);
int udp_v4_early_demux(struct sk_buff *skb);
-static int ip_rcv_finish_core(struct net *net, struct sock *sk,
+static int ip_rcv_finish_core(struct net *net,
struct sk_buff *skb, struct net_device *dev,
const struct sk_buff *hint)
{
@@ -442,7 +442,7 @@ static int ip_rcv_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
if (!skb)
return NET_RX_SUCCESS;
- ret = ip_rcv_finish_core(net, sk, skb, dev, NULL);
+ ret = ip_rcv_finish_core(net, skb, dev, NULL);
if (ret != NET_RX_DROP)
ret = dst_input(skb);
return ret;
@@ -589,8 +589,7 @@ static struct sk_buff *ip_extract_route_hint(const struct net *net,
return skb;
}
-static void ip_list_rcv_finish(struct net *net, struct sock *sk,
- struct list_head *head)
+static void ip_list_rcv_finish(struct net *net, struct list_head *head)
{
struct sk_buff *skb, *next, *hint = NULL;
struct dst_entry *curr_dst = NULL;
@@ -607,7 +606,7 @@ static void ip_list_rcv_finish(struct net *net, struct sock *sk,
skb = l3mdev_ip_rcv(skb);
if (!skb)
continue;
- if (ip_rcv_finish_core(net, sk, skb, dev, hint) == NET_RX_DROP)
+ if (ip_rcv_finish_core(net, skb, dev, hint) == NET_RX_DROP)
continue;
dst = skb_dst(skb);
@@ -633,7 +632,7 @@ static void ip_sublist_rcv(struct list_head *head, struct net_device *dev,
{
NF_HOOK_LIST(NFPROTO_IPV4, NF_INET_PRE_ROUTING, net, NULL,
head, dev, NULL, ip_rcv_finish);
- ip_list_rcv_finish(net, NULL, head);
+ ip_list_rcv_finish(net, head);
}
/* Receive a list of IP packets */
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
index a59204a8d850..ea7a260bec8a 100644
--- a/net/ipv4/ip_output.c
+++ b/net/ipv4/ip_output.c
@@ -478,24 +478,16 @@ int __ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
/* Make sure we can route this packet. */
rt = dst_rtable(__sk_dst_check(sk, 0));
if (!rt) {
- __be32 daddr;
+ inet_sk_init_flowi4(inet, fl4);
- /* Use correct destination address if we have options. */
- daddr = inet->inet_daddr;
- if (inet_opt && inet_opt->opt.srr)
- daddr = inet_opt->opt.faddr;
+ /* sctp_v4_xmit() uses its own DSCP value */
+ fl4->flowi4_tos = tos & INET_DSCP_MASK;
/* If this fails, retransmit mechanism of transport layer will
* keep trying until route appears or the connection times
* itself out.
*/
- rt = ip_route_output_ports(net, fl4, sk,
- daddr, inet->inet_saddr,
- inet->inet_dport,
- inet->inet_sport,
- sk->sk_protocol,
- tos & INET_DSCP_MASK,
- sk->sk_bound_dev_if);
+ rt = ip_route_output_flow(net, fl4, sk);
if (IS_ERR(rt))
goto no_route;
sk_setup_caps(sk, &rt->dst);
@@ -1333,7 +1325,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork,
cork->ttl = ipc->ttl;
cork->tos = ipc->tos;
cork->mark = ipc->sockc.mark;
- cork->priority = ipc->priority;
+ cork->priority = ipc->sockc.priority;
cork->transmit_time = ipc->sockc.transmit_time;
cork->tx_flags = 0;
sock_tx_timestamp(sk, &ipc->sockc, &cork->tx_flags);
@@ -1470,7 +1462,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk,
ip_options_build(skb, opt, cork->addr, rt);
}
- skb->priority = (cork->tos != -1) ? cork->priority: READ_ONCE(sk->sk_priority);
+ skb->priority = cork->priority;
skb->mark = cork->mark;
if (sk_is_tcp(sk))
skb_set_delivery_time(skb, cork->transmit_time, SKB_CLOCK_MONOTONIC);
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index cf377377b52d..f6a03b418dde 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -315,7 +315,7 @@ int ip_cmsg_send(struct sock *sk, struct msghdr *msg, struct ipcm_cookie *ipc,
if (val < 0 || val > 255)
return -EINVAL;
ipc->tos = val;
- ipc->priority = rt_tos2priority(ipc->tos);
+ ipc->sockc.priority = rt_tos2priority(ipc->tos);
break;
case IP_PROTOCOL:
if (cmsg->cmsg_len != CMSG_LEN(sizeof(int)))
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c
index 25505f9b724c..09b73acf037a 100644
--- a/net/ipv4/ip_tunnel.c
+++ b/net/ipv4/ip_tunnel.c
@@ -294,7 +294,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev)
ip_tunnel_init_flow(&fl4, iph->protocol, iph->daddr,
iph->saddr, tunnel->parms.o_key,
- iph->tos & INET_DSCP_MASK, dev_net(dev),
+ iph->tos & INET_DSCP_MASK, tunnel->net,
tunnel->parms.link, tunnel->fwmark, 0, 0);
rt = ip_route_output_key(tunnel->net, &fl4);
@@ -611,7 +611,7 @@ void ip_md_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
}
ip_tunnel_init_flow(&fl4, proto, key->u.ipv4.dst, key->u.ipv4.src,
tunnel_id_to_key32(key->tun_id),
- tos & INET_DSCP_MASK, dev_net(dev), 0, skb->mark,
+ tos & INET_DSCP_MASK, tunnel->net, 0, skb->mark,
skb_get_hash(skb), key->flow_flags);
if (!tunnel_hlen)
@@ -774,7 +774,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
ip_tunnel_init_flow(&fl4, protocol, dst, tnl_params->saddr,
tunnel->parms.o_key, tos & INET_DSCP_MASK,
- dev_net(dev), READ_ONCE(tunnel->parms.link),
+ tunnel->net, READ_ONCE(tunnel->parms.link),
tunnel->fwmark, skb_get_hash(skb), 0);
if (ip_tunnel_encap(skb, &tunnel->encap, &protocol, &fl4) < 0)
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c
index c5b8ec5c0a8c..99d8faa508e5 100644
--- a/net/ipv4/ipmr.c
+++ b/net/ipv4/ipmr.c
@@ -122,7 +122,7 @@ static void ipmr_expire_process(struct timer_list *t);
static bool ipmr_can_free_table(struct net *net)
{
- return !check_net(net) || !net->ipv4.mr_rules_ops;
+ return !check_net(net) || !net_initialized(net);
}
static struct mr_table *ipmr_mr_table_iter(struct net *net,
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 0e9e01967ec9..4304a68d1db0 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -358,7 +358,7 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4,
skb_reserve(skb, hlen);
skb->protocol = htons(ETH_P_IP);
- skb->priority = READ_ONCE(sk->sk_priority);
+ skb->priority = sockc->priority;
skb->mark = sockc->mark;
skb_set_delivery_type_by_clockid(skb, sockc->transmit_time, sk->sk_clockid);
skb_dst_set(skb, &rt->dst);
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index e5603e84b20d..9f9d4e6ea1b9 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -870,11 +870,11 @@ void ip_rt_send_redirect(struct sk_buff *skb)
}
log_martians = IN_DEV_LOG_MARTIANS(in_dev);
vif = l3mdev_master_ifindex_rcu(rt->dst.dev);
- rcu_read_unlock();
net = dev_net(rt->dst.dev);
- peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, vif, 1);
+ peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr, vif);
if (!peer) {
+ rcu_read_unlock();
icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST,
rt_nexthop(rt, ip_hdr(skb)->daddr));
return;
@@ -893,7 +893,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
*/
if (peer->n_redirects >= ip_rt_redirect_number) {
peer->rate_last = jiffies;
- goto out_put_peer;
+ goto out_unlock;
}
/* Check for load limit; set rate_last to the latest sent
@@ -914,8 +914,8 @@ void ip_rt_send_redirect(struct sk_buff *skb)
&ip_hdr(skb)->saddr, inet_iif(skb),
&ip_hdr(skb)->daddr, &gw);
}
-out_put_peer:
- inet_putpeer(peer);
+out_unlock:
+ rcu_read_unlock();
}
static int ip_error(struct sk_buff *skb)
@@ -975,9 +975,9 @@ static int ip_error(struct sk_buff *skb)
break;
}
+ rcu_read_lock();
peer = inet_getpeer_v4(net->ipv4.peers, ip_hdr(skb)->saddr,
- l3mdev_master_ifindex(skb->dev), 1);
-
+ l3mdev_master_ifindex_rcu(skb->dev));
send = true;
if (peer) {
now = jiffies;
@@ -989,8 +989,9 @@ static int ip_error(struct sk_buff *skb)
peer->rate_tokens -= ip_rt_error_cost;
else
send = false;
- inet_putpeer(peer);
}
+ rcu_read_unlock();
+
if (send)
icmp_send(skb, ICMP_DEST_UNREACH, code, 0);
@@ -2478,7 +2479,8 @@ ip_route_input_rcu(struct sk_buff *skb, __be32 daddr, __be32 saddr,
int our = 0;
if (!in_dev)
- return -EINVAL;
+ return reason;
+
our = ip_check_mc_rcu(in_dev, daddr, saddr,
ip_hdr(skb)->protocol);
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c
index a79b2a52ce01..42cb5dc9cb24 100644
--- a/net/ipv4/sysctl_net_ipv4.c
+++ b/net/ipv4/sysctl_net_ipv4.c
@@ -45,6 +45,7 @@ static unsigned int tcp_child_ehash_entries_max = 16 * 1024 * 1024;
static unsigned int udp_child_hash_entries_max = UDP_HTABLE_SIZE_MAX;
static int tcp_plb_max_rounds = 31;
static int tcp_plb_max_cong_thresh = 256;
+static unsigned int tcp_tw_reuse_delay_max = TCP_PAWS_MSL * MSEC_PER_SEC;
/* obsolete */
static int sysctl_tcp_low_latency __read_mostly;
@@ -1066,6 +1067,15 @@ static struct ctl_table ipv4_net_table[] = {
.extra2 = SYSCTL_TWO,
},
{
+ .procname = "tcp_tw_reuse_delay",
+ .data = &init_net.ipv4.sysctl_tcp_tw_reuse_delay,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_douintvec_minmax,
+ .extra1 = SYSCTL_ONE,
+ .extra2 = &tcp_tw_reuse_delay_max,
+ },
+ {
.procname = "tcp_max_syn_backlog",
.data = &init_net.ipv4.sysctl_max_syn_backlog,
.maxlen = sizeof(int),
diff --git a/net/ipv4/tcp_bpf.c b/net/ipv4/tcp_bpf.c
index 370993c03d31..47f65b1b70ca 100644
--- a/net/ipv4/tcp_bpf.c
+++ b/net/ipv4/tcp_bpf.c
@@ -49,13 +49,14 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock,
sge = sk_msg_elem(msg, i);
size = (apply && apply_bytes < sge->length) ?
apply_bytes : sge->length;
- if (!sk_wmem_schedule(sk, size)) {
+ if (!__sk_rmem_schedule(sk, size, false)) {
if (!copied)
ret = -ENOMEM;
break;
}
sk_mem_charge(sk, size);
+ atomic_add(size, &sk->sk_rmem_alloc);
sk_msg_xfer(tmp, msg, i, size);
copied += size;
if (sge->length)
@@ -74,7 +75,8 @@ static int bpf_tcp_ingress(struct sock *sk, struct sk_psock *psock,
if (!ret) {
msg->sg.start = i;
- sk_psock_queue_msg(psock, tmp);
+ if (!sk_psock_queue_msg(psock, tmp))
+ atomic_sub(copied, &sk->sk_rmem_alloc);
sk_psock_data_ready(sk, psock);
} else {
sk_msg_free(sk, tmp);
@@ -441,7 +443,6 @@ more_data:
cork = true;
psock->cork = NULL;
}
- sk_msg_return(sk, msg, tosend);
release_sock(sk);
origsize = msg->sg.size;
@@ -453,8 +454,9 @@ more_data:
sock_put(sk_redir);
lock_sock(sk);
+ sk_mem_uncharge(sk, sent);
if (unlikely(ret < 0)) {
- int free = sk_msg_free_nocharge(sk, msg);
+ int free = sk_msg_free(sk, msg);
if (!cork)
*copied -= free;
@@ -468,7 +470,7 @@ more_data:
break;
case __SK_DROP:
default:
- sk_msg_free_partial(sk, msg, tosend);
+ sk_msg_free(sk, msg);
sk_msg_apply_bytes(psock, tosend);
*copied -= (tosend + delta);
return -EACCES;
@@ -484,11 +486,8 @@ more_data:
}
if (msg &&
msg->sg.data[msg->sg.start].page_link &&
- msg->sg.data[msg->sg.start].length) {
- if (eval == __SK_REDIRECT)
- sk_mem_charge(sk, tosend - sent);
+ msg->sg.data[msg->sg.start].length)
goto more_data;
- }
}
return ret;
}
@@ -496,7 +495,7 @@ more_data:
static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
{
struct sk_msg tmp, *msg_tx = NULL;
- int copied = 0, err = 0;
+ int copied = 0, err = 0, ret = 0;
struct sk_psock *psock;
long timeo;
int flags;
@@ -539,14 +538,14 @@ static int tcp_bpf_sendmsg(struct sock *sk, struct msghdr *msg, size_t size)
copy = msg_tx->sg.size - osize;
}
- err = sk_msg_memcopy_from_iter(sk, &msg->msg_iter, msg_tx,
+ ret = sk_msg_memcopy_from_iter(sk, &msg->msg_iter, msg_tx,
copy);
- if (err < 0) {
+ if (ret < 0) {
sk_msg_trim(sk, msg_tx, osize);
goto out_err;
}
- copied += copy;
+ copied += ret;
if (psock->cork_bytes) {
if (size > psock->cork_bytes)
psock->cork_bytes = 0;
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index 5bdf13ac26ef..4811727b8a02 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -7328,6 +7328,7 @@ int tcp_conn_request(struct request_sock_ops *rsk_ops,
if (unlikely(!inet_csk_reqsk_queue_hash_add(sk, req,
req->timeout))) {
reqsk_free(req);
+ dst_release(dst);
return 0;
}
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index a38c8b1f44db..cc2b5194a18d 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -120,6 +120,7 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
const struct tcp_timewait_sock *tcptw = tcp_twsk(sktw);
struct tcp_sock *tp = tcp_sk(sk);
int ts_recent_stamp;
+ u32 reuse_thresh;
if (READ_ONCE(tw->tw_substate) == TCP_FIN_WAIT2)
reuse = 0;
@@ -162,9 +163,10 @@ int tcp_twsk_unique(struct sock *sk, struct sock *sktw, void *twp)
and use initial timestamp retrieved from peer table.
*/
ts_recent_stamp = READ_ONCE(tcptw->tw_ts_recent_stamp);
+ reuse_thresh = READ_ONCE(tw->tw_entry_stamp) +
+ READ_ONCE(sock_net(sk)->ipv4.sysctl_tcp_tw_reuse_delay);
if (ts_recent_stamp &&
- (!twp || (reuse && time_after32(ktime_get_seconds(),
- ts_recent_stamp)))) {
+ (!twp || (reuse && time_after32(tcp_clock_ms(), reuse_thresh)))) {
/* inet_twsk_hashdance_schedule() sets sk_refcnt after putting twsk
* and releasing the bucket lock.
*/
@@ -896,7 +898,7 @@ static void tcp_v4_send_reset(const struct sock *sk, struct sk_buff *skb,
sock_net_set(ctl_sk, net);
if (sk) {
ctl_sk->sk_mark = (sk->sk_state == TCP_TIME_WAIT) ?
- inet_twsk(sk)->tw_mark : sk->sk_mark;
+ inet_twsk(sk)->tw_mark : READ_ONCE(sk->sk_mark);
ctl_sk->sk_priority = (sk->sk_state == TCP_TIME_WAIT) ?
inet_twsk(sk)->tw_priority : READ_ONCE(sk->sk_priority);
transmit_time = tcp_transmit_time(sk);
@@ -3457,6 +3459,7 @@ static int __net_init tcp_sk_init(struct net *net)
net->ipv4.sysctl_tcp_fin_timeout = TCP_FIN_TIMEOUT;
net->ipv4.sysctl_tcp_notsent_lowat = UINT_MAX;
net->ipv4.sysctl_tcp_tw_reuse = 2;
+ net->ipv4.sysctl_tcp_tw_reuse_delay = 1 * MSEC_PER_SEC;
net->ipv4.sysctl_tcp_no_ssthresh_metrics_save = 1;
refcount_set(&net->ipv4.tcp_death_row.tw_refcount, 1);
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c
index bb1fe1ba867a..b089b08e9617 100644
--- a/net/ipv4/tcp_minisocks.c
+++ b/net/ipv4/tcp_minisocks.c
@@ -157,8 +157,11 @@ tcp_timewait_state_process(struct inet_timewait_sock *tw, struct sk_buff *skb,
rcv_nxt);
if (tmp_opt.saw_tstamp) {
+ u64 ts = tcp_clock_ms();
+
+ WRITE_ONCE(tw->tw_entry_stamp, ts);
WRITE_ONCE(tcptw->tw_ts_recent_stamp,
- ktime_get_seconds());
+ div_u64(ts, MSEC_PER_SEC));
WRITE_ONCE(tcptw->tw_ts_recent,
tmp_opt.rcv_tsval);
}
@@ -316,6 +319,8 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
tw->tw_mark = sk->sk_mark;
tw->tw_priority = READ_ONCE(sk->sk_priority);
tw->tw_rcv_wscale = tp->rx_opt.rcv_wscale;
+ /* refreshed when we enter true TIME-WAIT state */
+ tw->tw_entry_stamp = tcp_time_stamp_ms(tp);
tcptw->tw_rcv_nxt = tp->rcv_nxt;
tcptw->tw_snd_nxt = tp->snd_nxt;
tcptw->tw_rcv_wnd = tcp_receive_window(tp);
@@ -326,6 +331,10 @@ void tcp_time_wait(struct sock *sk, int state, int timeo)
tcptw->tw_last_oow_ack_time = 0;
tcptw->tw_tx_delay = tp->tcp_tx_delay;
tw->tw_txhash = sk->sk_txhash;
+ tw->tw_tx_queue_mapping = sk->sk_tx_queue_mapping;
+#ifdef CONFIG_SOCK_RX_QUEUE_MAPPING
+ tw->tw_rx_queue_mapping = sk->sk_rx_queue_mapping;
+#endif
#if IS_ENABLED(CONFIG_IPV6)
if (tw->tw_family == PF_INET6) {
struct ipv6_pinfo *np = inet6_sk(sk);
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
index 5485a70b5fe5..0e5b9a654254 100644
--- a/net/ipv4/tcp_output.c
+++ b/net/ipv4/tcp_output.c
@@ -883,8 +883,10 @@ static unsigned int tcp_syn_options(struct sock *sk, struct sk_buff *skb,
unsigned int size;
if (mptcp_syn_options(sk, skb, &size, &opts->mptcp)) {
- opts->options |= OPTION_MPTCP;
- remaining -= size;
+ if (remaining >= size) {
+ opts->options |= OPTION_MPTCP;
+ remaining -= size;
+ }
}
}
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 6a01905d379f..4bc0a0686fcd 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -420,6 +420,49 @@ u32 udp_ehashfn(const struct net *net, const __be32 laddr, const __u16 lport,
}
EXPORT_SYMBOL(udp_ehashfn);
+/**
+ * udp4_lib_lookup1() - Simplified lookup using primary hash (destination port)
+ * @net: Network namespace
+ * @saddr: Source address, network order
+ * @sport: Source port, network order
+ * @daddr: Destination address, network order
+ * @hnum: Destination port, host order
+ * @dif: Destination interface index
+ * @sdif: Destination bridge port index, if relevant
+ * @udptable: Set of UDP hash tables
+ *
+ * Simplified lookup to be used as fallback if no sockets are found due to a
+ * potential race between (receive) address change, and lookup happening before
+ * the rehash operation. This function ignores SO_REUSEPORT groups while scoring
+ * result sockets, because if we have one, we don't need the fallback at all.
+ *
+ * Called under rcu_read_lock().
+ *
+ * Return: socket with highest matching score if any, NULL if none
+ */
+static struct sock *udp4_lib_lookup1(const struct net *net,
+ __be32 saddr, __be16 sport,
+ __be32 daddr, unsigned int hnum,
+ int dif, int sdif,
+ const struct udp_table *udptable)
+{
+ unsigned int slot = udp_hashfn(net, hnum, udptable->mask);
+ struct udp_hslot *hslot = &udptable->hash[slot];
+ struct sock *sk, *result = NULL;
+ int score, badness = 0;
+
+ sk_for_each_rcu(sk, &hslot->head) {
+ score = compute_score(sk, net,
+ saddr, sport, daddr, hnum, dif, sdif);
+ if (score > badness) {
+ result = sk;
+ badness = score;
+ }
+ }
+
+ return result;
+}
+
/* called with rcu_read_lock() */
static struct sock *udp4_lib_lookup2(const struct net *net,
__be32 saddr, __be16 sport,
@@ -683,6 +726,19 @@ struct sock *__udp4_lib_lookup(const struct net *net, __be32 saddr,
result = udp4_lib_lookup2(net, saddr, sport,
htonl(INADDR_ANY), hnum, dif, sdif,
hslot2, skb);
+ if (!IS_ERR_OR_NULL(result))
+ goto done;
+
+ /* Primary hash (destination port) lookup as fallback for this race:
+ * 1. __ip4_datagram_connect() sets sk_rcv_saddr
+ * 2. lookup (this function): new sk_rcv_saddr, hashes not updated yet
+ * 3. rehash operation updating _secondary and four-tuple_ hashes
+ * The primary hash doesn't need an update after 1., so, thanks to this
+ * further step, 1. and 3. don't need to be atomic against the lookup.
+ */
+ result = udp4_lib_lookup1(net, saddr, sport, daddr, hnum, dif, sdif,
+ udptable);
+
done:
if (IS_ERR(result))
return NULL;
@@ -1674,7 +1730,6 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
struct sk_buff_head *list = &sk->sk_receive_queue;
int rmem, err = -ENOMEM;
spinlock_t *busy = NULL;
- bool becomes_readable;
int size, rcvbuf;
/* Immediately drop when the receive queue is full.
@@ -1715,19 +1770,12 @@ int __udp_enqueue_schedule_skb(struct sock *sk, struct sk_buff *skb)
*/
sock_skb_set_dropcount(sk, skb);
- becomes_readable = skb_queue_empty(list);
__skb_queue_tail(list, skb);
spin_unlock(&list->lock);
- if (!sock_flag(sk, SOCK_DEAD)) {
- if (becomes_readable ||
- sk->sk_data_ready != sock_def_readable ||
- READ_ONCE(sk->sk_peek_off) >= 0)
- INDIRECT_CALL_1(sk->sk_data_ready,
- sock_def_readable, sk);
- else
- sk_wake_async_rcu(sk, SOCK_WAKE_WAITD, POLL_IN);
- }
+ if (!sock_flag(sk, SOCK_DEAD))
+ INDIRECT_CALL_1(sk->sk_data_ready, sock_def_readable, sk);
+
busylock_release(busy);
return 0;
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index c489a1e6aec9..c3729382be3b 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -4821,7 +4821,7 @@ inet6_rtm_deladdr(struct sk_buff *skb, struct nlmsghdr *nlh,
ifm->ifa_prefixlen, extack);
}
-static int modify_prefix_route(struct inet6_ifaddr *ifp,
+static int modify_prefix_route(struct net *net, struct inet6_ifaddr *ifp,
unsigned long expires, u32 flags,
bool modify_peer)
{
@@ -4845,7 +4845,9 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp,
ifp->prefix_len,
ifp->rt_priority, ifp->idev->dev,
expires, flags, GFP_KERNEL);
- } else {
+ return 0;
+ }
+ if (f6i != net->ipv6.fib6_null_entry) {
table = f6i->fib6_table;
spin_lock_bh(&table->tb6_lock);
@@ -4858,9 +4860,8 @@ static int modify_prefix_route(struct inet6_ifaddr *ifp,
}
spin_unlock_bh(&table->tb6_lock);
-
- fib6_info_release(f6i);
}
+ fib6_info_release(f6i);
return 0;
}
@@ -4939,7 +4940,7 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
int rc = -ENOENT;
if (had_prefixroute)
- rc = modify_prefix_route(ifp, expires, flags, false);
+ rc = modify_prefix_route(net, ifp, expires, flags, false);
/* prefix route could have been deleted; if so restore it */
if (rc == -ENOENT) {
@@ -4949,7 +4950,7 @@ static int inet6_addr_modify(struct net *net, struct inet6_ifaddr *ifp,
}
if (had_prefixroute && !ipv6_addr_any(&ifp->peer_addr))
- rc = modify_prefix_route(ifp, expires, flags, true);
+ rc = modify_prefix_route(net, ifp, expires, flags, true);
if (rc == -ENOENT && !ipv6_addr_any(&ifp->peer_addr)) {
addrconf_prefix_route(&ifp->peer_addr, ifp->prefix_len,
@@ -5126,22 +5127,6 @@ static inline int inet6_ifaddr_msgsize(void)
+ nla_total_size(4) /* IFA_RT_PRIORITY */;
}
-enum addr_type_t {
- UNICAST_ADDR,
- MULTICAST_ADDR,
- ANYCAST_ADDR,
-};
-
-struct inet6_fill_args {
- u32 portid;
- u32 seq;
- int event;
- unsigned int flags;
- int netnsid;
- int ifindex;
- enum addr_type_t type;
-};
-
static int inet6_fill_ifaddr(struct sk_buff *skb,
const struct inet6_ifaddr *ifa,
struct inet6_fill_args *args)
@@ -5220,15 +5205,16 @@ error:
return -EMSGSIZE;
}
-static int inet6_fill_ifmcaddr(struct sk_buff *skb,
- const struct ifmcaddr6 *ifmca,
- struct inet6_fill_args *args)
+int inet6_fill_ifmcaddr(struct sk_buff *skb,
+ const struct ifmcaddr6 *ifmca,
+ struct inet6_fill_args *args)
{
int ifindex = ifmca->idev->dev->ifindex;
u8 scope = RT_SCOPE_UNIVERSE;
struct nlmsghdr *nlh;
- if (ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
+ if (!args->force_rt_scope_universe &&
+ ipv6_addr_scope(&ifmca->mca_addr) & IFA_SITE)
scope = RT_SCOPE_SITE;
nlh = nlmsg_put(skb, args->portid, args->seq, args->event,
@@ -5254,9 +5240,9 @@ static int inet6_fill_ifmcaddr(struct sk_buff *skb,
return 0;
}
-static int inet6_fill_ifacaddr(struct sk_buff *skb,
- const struct ifacaddr6 *ifaca,
- struct inet6_fill_args *args)
+int inet6_fill_ifacaddr(struct sk_buff *skb,
+ const struct ifacaddr6 *ifaca,
+ struct inet6_fill_args *args)
{
struct net_device *dev = fib6_info_nh_dev(ifaca->aca_rt);
int ifindex = dev ? dev->ifindex : 1;
@@ -5417,6 +5403,7 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
.flags = NLM_F_MULTI,
.netnsid = -1,
.type = type,
+ .force_rt_scope_universe = false,
};
struct {
unsigned long ifindex;
@@ -5545,6 +5532,7 @@ static int inet6_rtm_getaddr(struct sk_buff *in_skb, struct nlmsghdr *nlh,
.event = RTM_NEWADDR,
.flags = 0,
.netnsid = -1,
+ .force_rt_scope_universe = false,
};
struct ifaddrmsg *ifm;
struct nlattr *tb[IFA_MAX+1];
@@ -5616,6 +5604,7 @@ static void inet6_ifa_notify(int event, struct inet6_ifaddr *ifa)
.event = event,
.flags = 0,
.netnsid = -1,
+ .force_rt_scope_universe = false,
};
int err = -ENOBUFS;
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c
index 562cace50ca9..21e01695b48c 100644
--- a/net/ipv6/anycast.c
+++ b/net/ipv6/anycast.c
@@ -278,6 +278,37 @@ static struct ifacaddr6 *aca_alloc(struct fib6_info *f6i,
return aca;
}
+static void inet6_ifacaddr_notify(struct net_device *dev,
+ const struct ifacaddr6 *ifaca, int event)
+{
+ struct inet6_fill_args fillargs = {
+ .event = event,
+ .netnsid = -1,
+ };
+ struct net *net = dev_net(dev);
+ struct sk_buff *skb;
+ int err = -ENOMEM;
+
+ skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
+ nla_total_size(sizeof(struct in6_addr)) +
+ nla_total_size(sizeof(struct ifa_cacheinfo)),
+ GFP_KERNEL);
+ if (!skb)
+ goto error;
+
+ err = inet6_fill_ifacaddr(skb, ifaca, &fillargs);
+ if (err < 0) {
+ pr_err("Failed to fill in anycast addresses (err %d)\n", err);
+ nlmsg_free(skb);
+ goto error;
+ }
+
+ rtnl_notify(skb, net, 0, RTNLGRP_IPV6_ACADDR, NULL, GFP_KERNEL);
+ return;
+error:
+ rtnl_set_sk_err(net, RTNLGRP_IPV6_ACADDR, err);
+}
+
/*
* device anycast group inc (add if not found)
*/
@@ -333,6 +364,8 @@ int __ipv6_dev_ac_inc(struct inet6_dev *idev, const struct in6_addr *addr)
addrconf_join_solict(idev->dev, &aca->aca_addr);
+ inet6_ifacaddr_notify(idev->dev, aca, RTM_NEWANYCAST);
+
aca_put(aca);
return 0;
out:
@@ -375,6 +408,8 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr)
ip6_del_rt(dev_net(idev->dev), aca->aca_rt, false);
+ inet6_ifacaddr_notify(idev->dev, aca, RTM_DELANYCAST);
+
aca_put(aca);
return 0;
}
diff --git a/net/ipv6/fib6_rules.c b/net/ipv6/fib6_rules.c
index c85c1627cb16..67d39114d9a6 100644
--- a/net/ipv6/fib6_rules.c
+++ b/net/ipv6/fib6_rules.c
@@ -26,6 +26,8 @@ struct fib6_rule {
struct fib_rule common;
struct rt6key src;
struct rt6key dst;
+ __be32 flowlabel;
+ __be32 flowlabel_mask;
dscp_t dscp;
u8 dscp_full:1; /* DSCP or TOS selector */
};
@@ -34,7 +36,7 @@ static bool fib6_rule_matchall(const struct fib_rule *rule)
{
struct fib6_rule *r = container_of(rule, struct fib6_rule, common);
- if (r->dst.plen || r->src.plen || r->dscp)
+ if (r->dst.plen || r->src.plen || r->dscp || r->flowlabel_mask)
return false;
return fib_rule_matchall(rule);
}
@@ -332,6 +334,9 @@ INDIRECT_CALLABLE_SCOPE int fib6_rule_match(struct fib_rule *rule,
if (r->dscp && r->dscp != ip6_dscp(fl6->flowlabel))
return 0;
+ if ((r->flowlabel ^ flowi6_get_flowlabel(fl6)) & r->flowlabel_mask)
+ return 0;
+
if (rule->ip_proto && (rule->ip_proto != fl6->flowi6_proto))
return 0;
@@ -360,6 +365,35 @@ static int fib6_nl2rule_dscp(const struct nlattr *nla, struct fib6_rule *rule6,
return 0;
}
+static int fib6_nl2rule_flowlabel(struct nlattr **tb, struct fib6_rule *rule6,
+ struct netlink_ext_ack *extack)
+{
+ __be32 flowlabel, flowlabel_mask;
+
+ if (NL_REQ_ATTR_CHECK(extack, NULL, tb, FRA_FLOWLABEL) ||
+ NL_REQ_ATTR_CHECK(extack, NULL, tb, FRA_FLOWLABEL_MASK))
+ return -EINVAL;
+
+ flowlabel = nla_get_be32(tb[FRA_FLOWLABEL]);
+ flowlabel_mask = nla_get_be32(tb[FRA_FLOWLABEL_MASK]);
+
+ if (flowlabel_mask & ~IPV6_FLOWLABEL_MASK) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[FRA_FLOWLABEL_MASK],
+ "Invalid flow label mask");
+ return -EINVAL;
+ }
+
+ if (flowlabel & ~flowlabel_mask) {
+ NL_SET_ERR_MSG(extack, "Flow label and mask do not match");
+ return -EINVAL;
+ }
+
+ rule6->flowlabel = flowlabel;
+ rule6->flowlabel_mask = flowlabel_mask;
+
+ return 0;
+}
+
static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
struct fib_rule_hdr *frh,
struct nlattr **tb,
@@ -379,6 +413,10 @@ static int fib6_rule_configure(struct fib_rule *rule, struct sk_buff *skb,
if (tb[FRA_DSCP] && fib6_nl2rule_dscp(tb[FRA_DSCP], rule6, extack) < 0)
goto errout;
+ if ((tb[FRA_FLOWLABEL] || tb[FRA_FLOWLABEL_MASK]) &&
+ fib6_nl2rule_flowlabel(tb, rule6, extack) < 0)
+ goto errout;
+
if (rule->action == FR_ACT_TO_TBL && !rule->l3mdev) {
if (rule->table == RT6_TABLE_UNSPEC) {
NL_SET_ERR_MSG(extack, "Invalid table");
@@ -444,6 +482,14 @@ static int fib6_rule_compare(struct fib_rule *rule, struct fib_rule_hdr *frh,
return 0;
}
+ if (tb[FRA_FLOWLABEL] &&
+ nla_get_be32(tb[FRA_FLOWLABEL]) != rule6->flowlabel)
+ return 0;
+
+ if (tb[FRA_FLOWLABEL_MASK] &&
+ nla_get_be32(tb[FRA_FLOWLABEL_MASK]) != rule6->flowlabel_mask)
+ return 0;
+
if (frh->src_len &&
nla_memcmp(tb[FRA_SRC], &rule6->src.addr, sizeof(struct in6_addr)))
return 0;
@@ -472,6 +518,11 @@ static int fib6_rule_fill(struct fib_rule *rule, struct sk_buff *skb,
frh->tos = inet_dscp_to_dsfield(rule6->dscp);
}
+ if (rule6->flowlabel_mask &&
+ (nla_put_be32(skb, FRA_FLOWLABEL, rule6->flowlabel) ||
+ nla_put_be32(skb, FRA_FLOWLABEL_MASK, rule6->flowlabel_mask)))
+ goto nla_put_failure;
+
if ((rule6->dst.plen &&
nla_put_in6_addr(skb, FRA_DST, &rule6->dst.addr)) ||
(rule6->src.plen &&
@@ -487,7 +538,9 @@ static size_t fib6_rule_nlmsg_payload(struct fib_rule *rule)
{
return nla_total_size(16) /* dst */
+ nla_total_size(16) /* src */
- + nla_total_size(1); /* dscp */
+ + nla_total_size(1) /* dscp */
+ + nla_total_size(4) /* flowlabel */
+ + nla_total_size(4); /* flowlabel mask */
}
static void fib6_rule_flush_cache(struct fib_rules_ops *ops)
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index 071b0bc1179d..a6984a29fdb9 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -222,10 +222,10 @@ static bool icmpv6_xrlim_allow(struct sock *sk, u8 type,
if (rt->rt6i_dst.plen < 128)
tmo >>= ((128 - rt->rt6i_dst.plen)>>5);
- peer = inet_getpeer_v6(net->ipv6.peers, &fl6->daddr, 1);
+ rcu_read_lock();
+ peer = inet_getpeer_v6(net->ipv6.peers, &fl6->daddr);
res = inet_peer_xrlim_allow(peer, tmo);
- if (peer)
- inet_putpeer(peer);
+ rcu_read_unlock();
}
if (!res)
__ICMP6_INC_STATS(net, ip6_dst_idev(dst),
diff --git a/net/ipv6/ila/ila_xlat.c b/net/ipv6/ila/ila_xlat.c
index 7646e401c630..1d41b2ab4884 100644
--- a/net/ipv6/ila/ila_xlat.c
+++ b/net/ipv6/ila/ila_xlat.c
@@ -195,6 +195,8 @@ static const struct nf_hook_ops ila_nf_hook_ops[] = {
},
};
+static DEFINE_MUTEX(ila_mutex);
+
static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
{
struct ila_net *ilan = net_generic(net, ila_net_id);
@@ -202,16 +204,20 @@ static int ila_add_mapping(struct net *net, struct ila_xlat_params *xp)
spinlock_t *lock = ila_get_lock(ilan, xp->ip.locator_match);
int err = 0, order;
- if (!ilan->xlat.hooks_registered) {
+ if (!READ_ONCE(ilan->xlat.hooks_registered)) {
/* We defer registering net hooks in the namespace until the
* first mapping is added.
*/
- err = nf_register_net_hooks(net, ila_nf_hook_ops,
- ARRAY_SIZE(ila_nf_hook_ops));
+ mutex_lock(&ila_mutex);
+ if (!ilan->xlat.hooks_registered) {
+ err = nf_register_net_hooks(net, ila_nf_hook_ops,
+ ARRAY_SIZE(ila_nf_hook_ops));
+ if (!err)
+ WRITE_ONCE(ilan->xlat.hooks_registered, true);
+ }
+ mutex_unlock(&ila_mutex);
if (err)
return err;
-
- ilan->xlat.hooks_registered = true;
}
ila = kzalloc(sizeof(*ila), GFP_KERNEL);
diff --git a/net/ipv6/ioam6_iptunnel.c b/net/ipv6/ioam6_iptunnel.c
index 9d8422e350f8..28e5a89dc255 100644
--- a/net/ipv6/ioam6_iptunnel.c
+++ b/net/ipv6/ioam6_iptunnel.c
@@ -253,14 +253,15 @@ static int ioam6_do_fill(struct net *net, struct sk_buff *skb)
}
static int ioam6_do_inline(struct net *net, struct sk_buff *skb,
- struct ioam6_lwt_encap *tuninfo)
+ struct ioam6_lwt_encap *tuninfo,
+ struct dst_entry *cache_dst)
{
struct ipv6hdr *oldhdr, *hdr;
int hdrlen, err;
hdrlen = (tuninfo->eh.hdrlen + 1) << 3;
- err = skb_cow_head(skb, hdrlen + skb->mac_len);
+ err = skb_cow_head(skb, hdrlen + dst_dev_overhead(cache_dst, skb));
if (unlikely(err))
return err;
@@ -291,7 +292,8 @@ static int ioam6_do_encap(struct net *net, struct sk_buff *skb,
struct ioam6_lwt_encap *tuninfo,
bool has_tunsrc,
struct in6_addr *tunsrc,
- struct in6_addr *tundst)
+ struct in6_addr *tundst,
+ struct dst_entry *cache_dst)
{
struct dst_entry *dst = skb_dst(skb);
struct ipv6hdr *hdr, *inner_hdr;
@@ -300,7 +302,7 @@ static int ioam6_do_encap(struct net *net, struct sk_buff *skb,
hdrlen = (tuninfo->eh.hdrlen + 1) << 3;
len = sizeof(*hdr) + hdrlen;
- err = skb_cow_head(skb, len + skb->mac_len);
+ err = skb_cow_head(skb, len + dst_dev_overhead(cache_dst, skb));
if (unlikely(err))
return err;
@@ -334,7 +336,7 @@ static int ioam6_do_encap(struct net *net, struct sk_buff *skb,
static int ioam6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
{
- struct dst_entry *dst = skb_dst(skb);
+ struct dst_entry *dst = skb_dst(skb), *cache_dst;
struct in6_addr orig_daddr;
struct ioam6_lwt *ilwt;
int err = -EINVAL;
@@ -352,6 +354,10 @@ static int ioam6_output(struct net *net, struct sock *sk, struct sk_buff *skb)
orig_daddr = ipv6_hdr(skb)->daddr;
+ local_bh_disable();
+ cache_dst = dst_cache_get(&ilwt->cache);
+ local_bh_enable();
+
switch (ilwt->mode) {
case IOAM6_IPTUNNEL_MODE_INLINE:
do_inline:
@@ -359,7 +365,7 @@ do_inline:
if (ipv6_hdr(skb)->nexthdr == NEXTHDR_HOP)
goto out;
- err = ioam6_do_inline(net, skb, &ilwt->tuninfo);
+ err = ioam6_do_inline(net, skb, &ilwt->tuninfo, cache_dst);
if (unlikely(err))
goto drop;
@@ -369,7 +375,7 @@ do_encap:
/* Encapsulation (ip6ip6) */
err = ioam6_do_encap(net, skb, &ilwt->tuninfo,
ilwt->has_tunsrc, &ilwt->tunsrc,
- &ilwt->tundst);
+ &ilwt->tundst, cache_dst);
if (unlikely(err))
goto drop;
@@ -387,41 +393,36 @@ do_encap:
goto drop;
}
- err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
- if (unlikely(err))
- goto drop;
+ if (unlikely(!cache_dst)) {
+ struct ipv6hdr *hdr = ipv6_hdr(skb);
+ struct flowi6 fl6;
+
+ memset(&fl6, 0, sizeof(fl6));
+ fl6.daddr = hdr->daddr;
+ fl6.saddr = hdr->saddr;
+ fl6.flowlabel = ip6_flowinfo(hdr);
+ fl6.flowi6_mark = skb->mark;
+ fl6.flowi6_proto = hdr->nexthdr;
+
+ cache_dst = ip6_route_output(net, NULL, &fl6);
+ if (cache_dst->error) {
+ err = cache_dst->error;
+ dst_release(cache_dst);
+ goto drop;
+ }
- if (!ipv6_addr_equal(&orig_daddr, &ipv6_hdr(skb)->daddr)) {
local_bh_disable();
- dst = dst_cache_get(&ilwt->cache);
+ dst_cache_set_ip6(&ilwt->cache, cache_dst, &fl6.saddr);
local_bh_enable();
- if (unlikely(!dst)) {
- struct ipv6hdr *hdr = ipv6_hdr(skb);
- struct flowi6 fl6;
-
- memset(&fl6, 0, sizeof(fl6));
- fl6.daddr = hdr->daddr;
- fl6.saddr = hdr->saddr;
- fl6.flowlabel = ip6_flowinfo(hdr);
- fl6.flowi6_mark = skb->mark;
- fl6.flowi6_proto = hdr->nexthdr;
-
- dst = ip6_route_output(net, NULL, &fl6);
- if (dst->error) {
- err = dst->error;
- dst_release(dst);
- goto drop;
- }
-
- local_bh_disable();
- dst_cache_set_ip6(&ilwt->cache, dst, &fl6.saddr);
- local_bh_enable();
- }
+ err = skb_cow_head(skb, LL_RESERVED_SPACE(cache_dst->dev));
+ if (unlikely(err))
+ goto drop;
+ }
+ if (!ipv6_addr_equal(&orig_daddr, &ipv6_hdr(skb)->daddr)) {
skb_dst_drop(skb);
- skb_dst_set(skb, dst);
-
+ skb_dst_set(skb, cache_dst);
return dst_output(net, sk, skb);
}
out:
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 3d672dea9f56..d577bf2f3053 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -613,15 +613,15 @@ int ip6_forward(struct sk_buff *skb)
else
target = &hdr->daddr;
- peer = inet_getpeer_v6(net->ipv6.peers, &hdr->daddr, 1);
+ rcu_read_lock();
+ peer = inet_getpeer_v6(net->ipv6.peers, &hdr->daddr);
/* Limit redirects both by destination (here)
and by source (inside ndisc_send_redirect)
*/
if (inet_peer_xrlim_allow(peer, 1*HZ))
ndisc_send_redirect(skb, target);
- if (peer)
- inet_putpeer(peer);
+ rcu_read_unlock();
} else {
int addrtype = ipv6_addr_type(&hdr->saddr);
@@ -1401,6 +1401,7 @@ static int ip6_setup_cork(struct sock *sk, struct inet_cork_full *cork,
cork->base.gso_size = ipc6->gso_size;
cork->base.tx_flags = 0;
cork->base.mark = ipc6->sockc.mark;
+ cork->base.priority = ipc6->sockc.priority;
sock_tx_timestamp(sk, &ipc6->sockc, &cork->base.tx_flags);
if (ipc6->sockc.tsflags & SOCKCM_FLAG_TS_OPT_ID) {
cork->base.flags |= IPCORK_TS_OPT_ID;
@@ -1942,7 +1943,7 @@ struct sk_buff *__ip6_make_skb(struct sock *sk,
hdr->saddr = fl6->saddr;
hdr->daddr = *final_dst;
- skb->priority = READ_ONCE(sk->sk_priority);
+ skb->priority = cork->base.priority;
skb->mark = cork->base.mark;
if (sk_is_tcp(sk))
skb_set_delivery_time(skb, cork->base.transmit_time, SKB_CLOCK_MONOTONIC);
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 7f1902ac3586..578ff1336afe 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -110,7 +110,7 @@ static void ipmr_expire_process(struct timer_list *t);
static bool ip6mr_can_free_table(struct net *net)
{
- return !check_net(net) || !net->ipv6.mr6_rules_ops;
+ return !check_net(net) || !net_initialized(net);
}
static struct mr_table *ip6mr_mr_table_iter(struct net *net,
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c
index b244dbf61d5f..9dfdb40988b0 100644
--- a/net/ipv6/mcast.c
+++ b/net/ipv6/mcast.c
@@ -33,8 +33,10 @@
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/netdevice.h>
+#include <linux/if_addr.h>
#include <linux/if_arp.h>
#include <linux/route.h>
+#include <linux/rtnetlink.h>
#include <linux/init.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
@@ -47,6 +49,7 @@
#include <linux/netfilter_ipv6.h>
#include <net/net_namespace.h>
+#include <net/netlink.h>
#include <net/sock.h>
#include <net/snmp.h>
@@ -901,6 +904,41 @@ static struct ifmcaddr6 *mca_alloc(struct inet6_dev *idev,
return mc;
}
+static void inet6_ifmcaddr_notify(struct net_device *dev,
+ const struct ifmcaddr6 *ifmca, int event)
+{
+ struct inet6_fill_args fillargs = {
+ .portid = 0,
+ .seq = 0,
+ .event = event,
+ .flags = 0,
+ .netnsid = -1,
+ .force_rt_scope_universe = true,
+ };
+ struct net *net = dev_net(dev);
+ struct sk_buff *skb;
+ int err = -ENOMEM;
+
+ skb = nlmsg_new(NLMSG_ALIGN(sizeof(struct ifaddrmsg)) +
+ nla_total_size(sizeof(struct in6_addr)) +
+ nla_total_size(sizeof(struct ifa_cacheinfo)),
+ GFP_KERNEL);
+ if (!skb)
+ goto error;
+
+ err = inet6_fill_ifmcaddr(skb, ifmca, &fillargs);
+ if (err < 0) {
+ WARN_ON_ONCE(err == -EMSGSIZE);
+ nlmsg_free(skb);
+ goto error;
+ }
+
+ rtnl_notify(skb, net, 0, RTNLGRP_IPV6_MCADDR, NULL, GFP_KERNEL);
+ return;
+error:
+ rtnl_set_sk_err(net, RTNLGRP_IPV6_MCADDR, err);
+}
+
/*
* device multicast group inc (add if not found)
*/
@@ -948,6 +986,7 @@ static int __ipv6_dev_mc_inc(struct net_device *dev,
mld_del_delrec(idev, mc);
igmp6_group_added(mc);
+ inet6_ifmcaddr_notify(dev, mc, RTM_NEWMULTICAST);
mutex_unlock(&idev->mc_lock);
ma_put(mc);
return 0;
@@ -977,6 +1016,8 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr)
*map = ma->next;
igmp6_group_dropped(ma);
+ inet6_ifmcaddr_notify(idev->dev, ma,
+ RTM_DELMULTICAST);
ip6_mc_clear_src(ma);
mutex_unlock(&idev->mc_lock);
@@ -1021,29 +1062,31 @@ bool ipv6_chk_mcast_addr(struct net_device *dev, const struct in6_addr *group,
rcu_read_lock();
idev = __in6_dev_get(dev);
- if (idev) {
- for_each_mc_rcu(idev, mc) {
- if (ipv6_addr_equal(&mc->mca_addr, group))
- break;
- }
- if (mc) {
- if (src_addr && !ipv6_addr_any(src_addr)) {
- struct ip6_sf_list *psf;
+ if (!idev)
+ goto unlock;
+ for_each_mc_rcu(idev, mc) {
+ if (ipv6_addr_equal(&mc->mca_addr, group))
+ break;
+ }
+ if (!mc)
+ goto unlock;
+ if (src_addr && !ipv6_addr_any(src_addr)) {
+ struct ip6_sf_list *psf;
- for_each_psf_rcu(mc, psf) {
- if (ipv6_addr_equal(&psf->sf_addr, src_addr))
- break;
- }
- if (psf)
- rv = psf->sf_count[MCAST_INCLUDE] ||
- psf->sf_count[MCAST_EXCLUDE] !=
- mc->mca_sfcount[MCAST_EXCLUDE];
- else
- rv = mc->mca_sfcount[MCAST_EXCLUDE] != 0;
- } else
- rv = true; /* don't filter unspecified source */
+ for_each_psf_rcu(mc, psf) {
+ if (ipv6_addr_equal(&psf->sf_addr, src_addr))
+ break;
}
+ if (psf)
+ rv = READ_ONCE(psf->sf_count[MCAST_INCLUDE]) ||
+ READ_ONCE(psf->sf_count[MCAST_EXCLUDE]) !=
+ READ_ONCE(mc->mca_sfcount[MCAST_EXCLUDE]);
+ else
+ rv = READ_ONCE(mc->mca_sfcount[MCAST_EXCLUDE]) != 0;
+ } else {
+ rv = true; /* don't filter unspecified source */
}
+unlock:
rcu_read_unlock();
return rv;
}
@@ -2285,7 +2328,7 @@ static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode,
/* source filter not found, or count wrong => bug */
return -ESRCH;
}
- psf->sf_count[sfmode]--;
+ WRITE_ONCE(psf->sf_count[sfmode], psf->sf_count[sfmode] - 1);
if (!psf->sf_count[MCAST_INCLUDE] && !psf->sf_count[MCAST_EXCLUDE]) {
struct inet6_dev *idev = pmc->idev;
@@ -2391,7 +2434,7 @@ static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode,
rcu_assign_pointer(pmc->mca_sources, psf);
}
}
- psf->sf_count[sfmode]++;
+ WRITE_ONCE(psf->sf_count[sfmode], psf->sf_count[sfmode] + 1);
return 0;
}
@@ -2503,7 +2546,8 @@ static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
sf_markstate(pmc);
isexclude = pmc->mca_sfmode == MCAST_EXCLUDE;
if (!delta)
- pmc->mca_sfcount[sfmode]++;
+ WRITE_ONCE(pmc->mca_sfcount[sfmode],
+ pmc->mca_sfcount[sfmode] + 1);
err = 0;
for (i = 0; i < sfcount; i++) {
err = ip6_mc_add1_src(pmc, sfmode, &psfsrc[i]);
@@ -2514,7 +2558,8 @@ static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca,
int j;
if (!delta)
- pmc->mca_sfcount[sfmode]--;
+ WRITE_ONCE(pmc->mca_sfcount[sfmode],
+ pmc->mca_sfcount[sfmode] - 1);
for (j = 0; j < i; j++)
ip6_mc_del1_src(pmc, sfmode, &psfsrc[j]);
} else if (isexclude != (pmc->mca_sfcount[MCAST_EXCLUDE] != 0)) {
@@ -2559,7 +2604,8 @@ static void ip6_mc_clear_src(struct ifmcaddr6 *pmc)
RCU_INIT_POINTER(pmc->mca_sources, NULL);
pmc->mca_sfmode = MCAST_EXCLUDE;
pmc->mca_sfcount[MCAST_INCLUDE] = 0;
- pmc->mca_sfcount[MCAST_EXCLUDE] = 1;
+ /* Paired with the READ_ONCE() from ipv6_chk_mcast_addr() */
+ WRITE_ONCE(pmc->mca_sfcount[MCAST_EXCLUDE], 1);
}
/* called with mc_lock */
@@ -3074,8 +3120,8 @@ static int igmp6_mcf_seq_show(struct seq_file *seq, void *v)
state->dev->ifindex, state->dev->name,
&state->im->mca_addr,
&psf->sf_addr,
- psf->sf_count[MCAST_INCLUDE],
- psf->sf_count[MCAST_EXCLUDE]);
+ READ_ONCE(psf->sf_count[MCAST_INCLUDE]),
+ READ_ONCE(psf->sf_count[MCAST_EXCLUDE]));
}
return 0;
}
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index aba94a348673..d044c67019de 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1731,10 +1731,12 @@ void ndisc_send_redirect(struct sk_buff *skb, const struct in6_addr *target)
"Redirect: destination is not a neighbour\n");
goto release;
}
- peer = inet_getpeer_v6(net->ipv6.peers, &ipv6_hdr(skb)->saddr, 1);
+
+ rcu_read_lock();
+ peer = inet_getpeer_v6(net->ipv6.peers, &ipv6_hdr(skb)->saddr);
ret = inet_peer_xrlim_allow(peer, 1*HZ);
- if (peer)
- inet_putpeer(peer);
+ rcu_read_unlock();
+
if (!ret)
goto release;
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c
index 88b3fcacd4f9..46b8adf6e7f8 100644
--- a/net/ipv6/ping.c
+++ b/net/ipv6/ping.c
@@ -119,6 +119,7 @@ static int ping_v6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
return -EINVAL;
ipcm6_init_sk(&ipc6, sk);
+ ipc6.sockc.priority = READ_ONCE(sk->sk_priority);
ipc6.sockc.tsflags = READ_ONCE(sk->sk_tsflags);
ipc6.sockc.mark = READ_ONCE(sk->sk_mark);
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index 8476a3944a88..a45aba090aa4 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -619,7 +619,7 @@ static int rawv6_send_hdrinc(struct sock *sk, struct msghdr *msg, int length,
skb_reserve(skb, hlen);
skb->protocol = htons(ETH_P_IPV6);
- skb->priority = READ_ONCE(sk->sk_priority);
+ skb->priority = sockc->priority;
skb->mark = sockc->mark;
skb_set_delivery_type_by_clockid(skb, sockc->transmit_time, sk->sk_clockid);
@@ -780,6 +780,7 @@ static int rawv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
ipcm6_init(&ipc6);
ipc6.sockc.tsflags = READ_ONCE(sk->sk_tsflags);
ipc6.sockc.mark = fl6.flowi6_mark;
+ ipc6.sockc.priority = READ_ONCE(sk->sk_priority);
if (sin6) {
if (addr_len < SIN6_LEN_RFC2133)
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index 63d7681c929f..78362822b907 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -2780,10 +2780,10 @@ static void ip6_negative_advice(struct sock *sk,
if (rt->rt6i_flags & RTF_CACHE) {
rcu_read_lock();
if (rt6_check_expired(rt)) {
- /* counteract the dst_release() in sk_dst_reset() */
- dst_hold(dst);
+ /* rt/dst can not be destroyed yet,
+ * because of rcu_read_lock()
+ */
sk_dst_reset(sk);
-
rt6_remove_exception_rt(rt);
}
rcu_read_unlock();
@@ -5005,6 +5005,7 @@ static const struct nla_policy rtm_ipv6_policy[RTA_MAX+1] = {
[RTA_SPORT] = { .type = NLA_U16 },
[RTA_DPORT] = { .type = NLA_U16 },
[RTA_NH_ID] = { .type = NLA_U32 },
+ [RTA_FLOWLABEL] = { .type = NLA_BE32 },
};
static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
@@ -5030,6 +5031,12 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh,
goto errout;
}
+ if (tb[RTA_FLOWLABEL]) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[RTA_FLOWLABEL],
+ "Flow label cannot be specified for this operation");
+ goto errout;
+ }
+
*cfg = (struct fib6_config){
.fc_table = rtm->rtm_table,
.fc_dst_len = rtm->rtm_dst_len,
@@ -6013,6 +6020,13 @@ static int inet6_rtm_valid_getroute_req(struct sk_buff *skb,
return -EINVAL;
}
+ if (tb[RTA_FLOWLABEL] &&
+ (nla_get_be32(tb[RTA_FLOWLABEL]) & ~IPV6_FLOWLABEL_MASK)) {
+ NL_SET_ERR_MSG_ATTR(extack, tb[RTA_FLOWLABEL],
+ "Invalid flow label");
+ return -EINVAL;
+ }
+
for (i = 0; i <= RTA_MAX; i++) {
if (!tb[i])
continue;
@@ -6027,6 +6041,7 @@ static int inet6_rtm_valid_getroute_req(struct sk_buff *skb,
case RTA_SPORT:
case RTA_DPORT:
case RTA_IP_PROTO:
+ case RTA_FLOWLABEL:
break;
default:
NL_SET_ERR_MSG_MOD(extack, "Unsupported attribute in get route request");
@@ -6049,6 +6064,7 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
struct sk_buff *skb;
struct rtmsg *rtm;
struct flowi6 fl6 = {};
+ __be32 flowlabel;
bool fibmatch;
err = inet6_rtm_valid_getroute_req(in_skb, nlh, tb, extack);
@@ -6057,7 +6073,6 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
err = -EINVAL;
rtm = nlmsg_data(nlh);
- fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, 0);
fibmatch = !!(rtm->rtm_flags & RTM_F_FIB_MATCH);
if (tb[RTA_SRC]) {
@@ -6103,6 +6118,9 @@ static int inet6_rtm_getroute(struct sk_buff *in_skb, struct nlmsghdr *nlh,
goto errout;
}
+ flowlabel = nla_get_be32_default(tb[RTA_FLOWLABEL], 0);
+ fl6.flowlabel = ip6_make_flowinfo(rtm->rtm_tos, flowlabel);
+
if (iif) {
struct net_device *dev;
int flags = 0;
diff --git a/net/ipv6/rpl_iptunnel.c b/net/ipv6/rpl_iptunnel.c
index db3c19a42e1c..7ba22d2f2bfe 100644
--- a/net/ipv6/rpl_iptunnel.c
+++ b/net/ipv6/rpl_iptunnel.c
@@ -125,7 +125,8 @@ static void rpl_destroy_state(struct lwtunnel_state *lwt)
}
static int rpl_do_srh_inline(struct sk_buff *skb, const struct rpl_lwt *rlwt,
- const struct ipv6_rpl_sr_hdr *srh)
+ const struct ipv6_rpl_sr_hdr *srh,
+ struct dst_entry *cache_dst)
{
struct ipv6_rpl_sr_hdr *isrh, *csrh;
const struct ipv6hdr *oldhdr;
@@ -153,7 +154,7 @@ static int rpl_do_srh_inline(struct sk_buff *skb, const struct rpl_lwt *rlwt,
hdrlen = ((csrh->hdrlen + 1) << 3);
- err = skb_cow_head(skb, hdrlen + skb->mac_len);
+ err = skb_cow_head(skb, hdrlen + dst_dev_overhead(cache_dst, skb));
if (unlikely(err)) {
kfree(buf);
return err;
@@ -186,7 +187,8 @@ static int rpl_do_srh_inline(struct sk_buff *skb, const struct rpl_lwt *rlwt,
return 0;
}
-static int rpl_do_srh(struct sk_buff *skb, const struct rpl_lwt *rlwt)
+static int rpl_do_srh(struct sk_buff *skb, const struct rpl_lwt *rlwt,
+ struct dst_entry *cache_dst)
{
struct dst_entry *dst = skb_dst(skb);
struct rpl_iptunnel_encap *tinfo;
@@ -196,7 +198,7 @@ static int rpl_do_srh(struct sk_buff *skb, const struct rpl_lwt *rlwt)
tinfo = rpl_encap_lwtunnel(dst->lwtstate);
- return rpl_do_srh_inline(skb, rlwt, tinfo->srh);
+ return rpl_do_srh_inline(skb, rlwt, tinfo->srh, cache_dst);
}
static int rpl_output(struct net *net, struct sock *sk, struct sk_buff *skb)
@@ -208,14 +210,14 @@ static int rpl_output(struct net *net, struct sock *sk, struct sk_buff *skb)
rlwt = rpl_lwt_lwtunnel(orig_dst->lwtstate);
- err = rpl_do_srh(skb, rlwt);
- if (unlikely(err))
- goto drop;
-
local_bh_disable();
dst = dst_cache_get(&rlwt->cache);
local_bh_enable();
+ err = rpl_do_srh(skb, rlwt, dst);
+ if (unlikely(err))
+ goto drop;
+
if (unlikely(!dst)) {
struct ipv6hdr *hdr = ipv6_hdr(skb);
struct flowi6 fl6;
@@ -237,15 +239,15 @@ static int rpl_output(struct net *net, struct sock *sk, struct sk_buff *skb)
local_bh_disable();
dst_cache_set_ip6(&rlwt->cache, dst, &fl6.saddr);
local_bh_enable();
+
+ err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
+ if (unlikely(err))
+ goto drop;
}
skb_dst_drop(skb);
skb_dst_set(skb, dst);
- err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
- if (unlikely(err))
- goto drop;
-
return dst_output(net, sk, skb);
drop:
@@ -262,29 +264,31 @@ static int rpl_input(struct sk_buff *skb)
rlwt = rpl_lwt_lwtunnel(orig_dst->lwtstate);
- err = rpl_do_srh(skb, rlwt);
- if (unlikely(err))
- goto drop;
-
local_bh_disable();
dst = dst_cache_get(&rlwt->cache);
+ local_bh_enable();
+
+ err = rpl_do_srh(skb, rlwt, dst);
+ if (unlikely(err))
+ goto drop;
if (!dst) {
ip6_route_input(skb);
dst = skb_dst(skb);
if (!dst->error) {
+ local_bh_disable();
dst_cache_set_ip6(&rlwt->cache, dst,
&ipv6_hdr(skb)->saddr);
+ local_bh_enable();
}
+
+ err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
+ if (unlikely(err))
+ goto drop;
} else {
skb_dst_drop(skb);
skb_dst_set(skb, dst);
}
- local_bh_enable();
-
- err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
- if (unlikely(err))
- goto drop;
return dst_input(skb);
diff --git a/net/ipv6/seg6_iptunnel.c b/net/ipv6/seg6_iptunnel.c
index 098632adc9b5..4bf937bfc263 100644
--- a/net/ipv6/seg6_iptunnel.c
+++ b/net/ipv6/seg6_iptunnel.c
@@ -124,8 +124,8 @@ static __be32 seg6_make_flowlabel(struct net *net, struct sk_buff *skb,
return flowlabel;
}
-/* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
-int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
+static int __seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
+ int proto, struct dst_entry *cache_dst)
{
struct dst_entry *dst = skb_dst(skb);
struct net *net = dev_net(dst->dev);
@@ -137,7 +137,7 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
hdrlen = (osrh->hdrlen + 1) << 3;
tot_len = hdrlen + sizeof(*hdr);
- err = skb_cow_head(skb, tot_len + skb->mac_len);
+ err = skb_cow_head(skb, tot_len + dst_dev_overhead(cache_dst, skb));
if (unlikely(err))
return err;
@@ -197,11 +197,18 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
return 0;
}
+
+/* encapsulate an IPv6 packet within an outer IPv6 header with a given SRH */
+int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
+{
+ return __seg6_do_srh_encap(skb, osrh, proto, NULL);
+}
EXPORT_SYMBOL_GPL(seg6_do_srh_encap);
/* encapsulate an IPv6 packet within an outer IPv6 header with reduced SRH */
static int seg6_do_srh_encap_red(struct sk_buff *skb,
- struct ipv6_sr_hdr *osrh, int proto)
+ struct ipv6_sr_hdr *osrh, int proto,
+ struct dst_entry *cache_dst)
{
__u8 first_seg = osrh->first_segment;
struct dst_entry *dst = skb_dst(skb);
@@ -230,7 +237,7 @@ static int seg6_do_srh_encap_red(struct sk_buff *skb,
tot_len = red_hdrlen + sizeof(struct ipv6hdr);
- err = skb_cow_head(skb, tot_len + skb->mac_len);
+ err = skb_cow_head(skb, tot_len + dst_dev_overhead(cache_dst, skb));
if (unlikely(err))
return err;
@@ -317,8 +324,8 @@ out:
return 0;
}
-/* insert an SRH within an IPv6 packet, just after the IPv6 header */
-int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
+static int __seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh,
+ struct dst_entry *cache_dst)
{
struct ipv6hdr *hdr, *oldhdr;
struct ipv6_sr_hdr *isrh;
@@ -326,7 +333,7 @@ int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
hdrlen = (osrh->hdrlen + 1) << 3;
- err = skb_cow_head(skb, hdrlen + skb->mac_len);
+ err = skb_cow_head(skb, hdrlen + dst_dev_overhead(cache_dst, skb));
if (unlikely(err))
return err;
@@ -369,9 +376,8 @@ int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
return 0;
}
-EXPORT_SYMBOL_GPL(seg6_do_srh_inline);
-static int seg6_do_srh(struct sk_buff *skb)
+static int seg6_do_srh(struct sk_buff *skb, struct dst_entry *cache_dst)
{
struct dst_entry *dst = skb_dst(skb);
struct seg6_iptunnel_encap *tinfo;
@@ -384,7 +390,7 @@ static int seg6_do_srh(struct sk_buff *skb)
if (skb->protocol != htons(ETH_P_IPV6))
return -EINVAL;
- err = seg6_do_srh_inline(skb, tinfo->srh);
+ err = __seg6_do_srh_inline(skb, tinfo->srh, cache_dst);
if (err)
return err;
break;
@@ -402,9 +408,11 @@ static int seg6_do_srh(struct sk_buff *skb)
return -EINVAL;
if (tinfo->mode == SEG6_IPTUN_MODE_ENCAP)
- err = seg6_do_srh_encap(skb, tinfo->srh, proto);
+ err = __seg6_do_srh_encap(skb, tinfo->srh,
+ proto, cache_dst);
else
- err = seg6_do_srh_encap_red(skb, tinfo->srh, proto);
+ err = seg6_do_srh_encap_red(skb, tinfo->srh,
+ proto, cache_dst);
if (err)
return err;
@@ -425,11 +433,13 @@ static int seg6_do_srh(struct sk_buff *skb)
skb_push(skb, skb->mac_len);
if (tinfo->mode == SEG6_IPTUN_MODE_L2ENCAP)
- err = seg6_do_srh_encap(skb, tinfo->srh,
- IPPROTO_ETHERNET);
+ err = __seg6_do_srh_encap(skb, tinfo->srh,
+ IPPROTO_ETHERNET,
+ cache_dst);
else
err = seg6_do_srh_encap_red(skb, tinfo->srh,
- IPPROTO_ETHERNET);
+ IPPROTO_ETHERNET,
+ cache_dst);
if (err)
return err;
@@ -444,6 +454,13 @@ static int seg6_do_srh(struct sk_buff *skb)
return 0;
}
+/* insert an SRH within an IPv6 packet, just after the IPv6 header */
+int seg6_do_srh_inline(struct sk_buff *skb, struct ipv6_sr_hdr *osrh)
+{
+ return __seg6_do_srh_inline(skb, osrh, NULL);
+}
+EXPORT_SYMBOL_GPL(seg6_do_srh_inline);
+
static int seg6_input_finish(struct net *net, struct sock *sk,
struct sk_buff *skb)
{
@@ -458,31 +475,33 @@ static int seg6_input_core(struct net *net, struct sock *sk,
struct seg6_lwt *slwt;
int err;
- err = seg6_do_srh(skb);
- if (unlikely(err))
- goto drop;
-
slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
local_bh_disable();
dst = dst_cache_get(&slwt->cache);
+ local_bh_enable();
+
+ err = seg6_do_srh(skb, dst);
+ if (unlikely(err))
+ goto drop;
if (!dst) {
ip6_route_input(skb);
dst = skb_dst(skb);
if (!dst->error) {
+ local_bh_disable();
dst_cache_set_ip6(&slwt->cache, dst,
&ipv6_hdr(skb)->saddr);
+ local_bh_enable();
}
+
+ err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
+ if (unlikely(err))
+ goto drop;
} else {
skb_dst_drop(skb);
skb_dst_set(skb, dst);
}
- local_bh_enable();
-
- err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
- if (unlikely(err))
- goto drop;
if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled))
return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
@@ -528,16 +547,16 @@ static int seg6_output_core(struct net *net, struct sock *sk,
struct seg6_lwt *slwt;
int err;
- err = seg6_do_srh(skb);
- if (unlikely(err))
- goto drop;
-
slwt = seg6_lwt_lwtunnel(orig_dst->lwtstate);
local_bh_disable();
dst = dst_cache_get(&slwt->cache);
local_bh_enable();
+ err = seg6_do_srh(skb, dst);
+ if (unlikely(err))
+ goto drop;
+
if (unlikely(!dst)) {
struct ipv6hdr *hdr = ipv6_hdr(skb);
struct flowi6 fl6;
@@ -559,15 +578,15 @@ static int seg6_output_core(struct net *net, struct sock *sk,
local_bh_disable();
dst_cache_set_ip6(&slwt->cache, dst, &fl6.saddr);
local_bh_enable();
+
+ err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
+ if (unlikely(err))
+ goto drop;
}
skb_dst_drop(skb);
skb_dst_set(skb, dst);
- err = skb_cow_head(skb, LL_RESERVED_SPACE(dst->dev));
- if (unlikely(err))
- goto drop;
-
if (static_branch_unlikely(&nf_hooks_lwtunnel_enabled))
return NF_HOOK(NFPROTO_IPV6, NF_INET_LOCAL_OUT, net, sk, skb,
NULL, skb_dst(skb)->dev, dst_output);
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c
index d766fd798ecf..6671daa67f4f 100644
--- a/net/ipv6/udp.c
+++ b/net/ipv6/udp.c
@@ -170,6 +170,49 @@ static int compute_score(struct sock *sk, const struct net *net,
return score;
}
+/**
+ * udp6_lib_lookup1() - Simplified lookup using primary hash (destination port)
+ * @net: Network namespace
+ * @saddr: Source address, network order
+ * @sport: Source port, network order
+ * @daddr: Destination address, network order
+ * @hnum: Destination port, host order
+ * @dif: Destination interface index
+ * @sdif: Destination bridge port index, if relevant
+ * @udptable: Set of UDP hash tables
+ *
+ * Simplified lookup to be used as fallback if no sockets are found due to a
+ * potential race between (receive) address change, and lookup happening before
+ * the rehash operation. This function ignores SO_REUSEPORT groups while scoring
+ * result sockets, because if we have one, we don't need the fallback at all.
+ *
+ * Called under rcu_read_lock().
+ *
+ * Return: socket with highest matching score if any, NULL if none
+ */
+static struct sock *udp6_lib_lookup1(const struct net *net,
+ const struct in6_addr *saddr, __be16 sport,
+ const struct in6_addr *daddr,
+ unsigned int hnum, int dif, int sdif,
+ const struct udp_table *udptable)
+{
+ unsigned int slot = udp_hashfn(net, hnum, udptable->mask);
+ struct udp_hslot *hslot = &udptable->hash[slot];
+ struct sock *sk, *result = NULL;
+ int score, badness = 0;
+
+ sk_for_each_rcu(sk, &hslot->head) {
+ score = compute_score(sk, net,
+ saddr, sport, daddr, hnum, dif, sdif);
+ if (score > badness) {
+ result = sk;
+ badness = score;
+ }
+ }
+
+ return result;
+}
+
/* called with rcu_read_lock() */
static struct sock *udp6_lib_lookup2(const struct net *net,
const struct in6_addr *saddr, __be16 sport,
@@ -347,6 +390,13 @@ struct sock *__udp6_lib_lookup(const struct net *net,
result = udp6_lib_lookup2(net, saddr, sport,
&in6addr_any, hnum, dif, sdif,
hslot2, skb);
+ if (!IS_ERR_OR_NULL(result))
+ goto done;
+
+ /* Cover address change/lookup/rehash race: see __udp4_lib_lookup() */
+ result = udp6_lib_lookup1(net, saddr, sport, daddr, hnum, dif, sdif,
+ udptable);
+
done:
if (IS_ERR(result))
return NULL;
@@ -1448,6 +1498,7 @@ int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
ipc6.gso_size = READ_ONCE(up->gso_size);
ipc6.sockc.tsflags = READ_ONCE(sk->sk_tsflags);
ipc6.sockc.mark = READ_ONCE(sk->sk_mark);
+ ipc6.sockc.priority = READ_ONCE(sk->sk_priority);
/* destination address check */
if (sin6) {
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c
index d692b902e120..e83691073496 100644
--- a/net/l2tp/l2tp_eth.c
+++ b/net/l2tp/l2tp_eth.c
@@ -73,9 +73,9 @@ static netdev_tx_t l2tp_eth_dev_xmit(struct sk_buff *skb, struct net_device *dev
int ret = l2tp_xmit_skb(session, skb);
if (likely(ret == NET_XMIT_SUCCESS))
- dev_sw_netstats_tx_add(dev, 1, len);
+ dev_dstats_tx_add(dev, len);
else
- DEV_STATS_INC(dev, tx_dropped);
+ dev_dstats_tx_dropped(dev);
return NETDEV_TX_OK;
}
@@ -84,7 +84,6 @@ static const struct net_device_ops l2tp_eth_netdev_ops = {
.ndo_init = l2tp_eth_dev_init,
.ndo_uninit = l2tp_eth_dev_uninit,
.ndo_start_xmit = l2tp_eth_dev_xmit,
- .ndo_get_stats64 = dev_get_tstats64,
.ndo_set_mac_address = eth_mac_addr,
};
@@ -100,7 +99,7 @@ static void l2tp_eth_dev_setup(struct net_device *dev)
dev->lltx = true;
dev->netdev_ops = &l2tp_eth_netdev_ops;
dev->needs_free_netdev = true;
- dev->pcpu_stat_type = NETDEV_PCPU_STAT_TSTATS;
+ dev->pcpu_stat_type = NETDEV_PCPU_STAT_DSTATS;
}
static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb, int data_len)
@@ -128,7 +127,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
goto error_rcu;
if (dev_forward_skb(dev, skb) == NET_RX_SUCCESS)
- dev_sw_netstats_rx_add(dev, data_len);
+ dev_dstats_rx_add(dev, data_len);
else
DEV_STATS_INC(dev, rx_errors);
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c
index 4bc24fddfd52..29795d2839e8 100644
--- a/net/l2tp/l2tp_ip.c
+++ b/net/l2tp/l2tp_ip.c
@@ -425,7 +425,6 @@ static int l2tp_ip_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
int rc;
struct inet_sock *inet = inet_sk(sk);
struct rtable *rt = NULL;
- struct flowi4 *fl4;
int connected = 0;
__be32 daddr;
@@ -455,7 +454,6 @@ static int l2tp_ip_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
if (sk->sk_state != TCP_ESTABLISHED)
goto out;
- daddr = inet->inet_daddr;
connected = 1;
}
@@ -482,29 +480,24 @@ static int l2tp_ip_sendmsg(struct sock *sk, struct msghdr *msg, size_t len)
goto error;
}
- fl4 = &inet->cork.fl.u.ip4;
if (connected)
rt = dst_rtable(__sk_dst_check(sk, 0));
rcu_read_lock();
if (!rt) {
- const struct ip_options_rcu *inet_opt;
+ struct flowi4 *fl4 = &inet->cork.fl.u.ip4;
- inet_opt = rcu_dereference(inet->inet_opt);
+ inet_sk_init_flowi4(inet, fl4);
- /* Use correct destination address if we have options. */
- if (inet_opt && inet_opt->opt.srr)
- daddr = inet_opt->opt.faddr;
+ /* Overwrite ->daddr if msg->msg_name was provided */
+ if (!connected)
+ fl4->daddr = daddr;
/* If this fails, retransmit mechanism of transport layer will
* keep trying until route appears or the connection times
* itself out.
*/
- rt = ip_route_output_ports(sock_net(sk), fl4, sk,
- daddr, inet->inet_saddr,
- inet->inet_dport, inet->inet_sport,
- sk->sk_protocol, ip_sock_rt_tos(sk),
- sk->sk_bound_dev_if);
+ rt = ip_route_output_flow(sock_net(sk), fl4, sk);
if (IS_ERR(rt))
goto no_route;
if (connected) {
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c
index 51bccfb00a9c..61b0159b2fbe 100644
--- a/net/llc/llc_input.c
+++ b/net/llc/llc_input.c
@@ -124,8 +124,8 @@ static inline int llc_fixup_skb(struct sk_buff *skb)
if (unlikely(!pskb_may_pull(skb, llc_len)))
return 0;
- skb->transport_header += llc_len;
skb_pull(skb, llc_len);
+ skb_reset_transport_header(skb);
if (skb->protocol == htons(ETH_P_802_2)) {
__be16 pdulen;
s32 data_size;
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 61a824ec33da..b8495d5f2297 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1088,13 +1088,13 @@ ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_elems *dst,
{
int i, offset = 0;
+ dst->cnt = src->cnt;
for (i = 0; i < src->cnt; i++) {
memcpy(pos + offset, src->elem[i].data, src->elem[i].len);
dst->elem[i].len = src->elem[i].len;
dst->elem[i].data = pos + offset;
offset += dst->elem[i].len;
}
- dst->cnt = src->cnt;
return offset;
}
@@ -1935,6 +1935,8 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
params->eht_capa_len,
link_sta);
+ ieee80211_sta_init_nss(link_sta);
+
if (params->opmode_notif_used) {
/* returned value is only needed for rc update, but the
* rc isn't initialized here yet, so ignore it
@@ -1944,8 +1946,6 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
sband->band);
}
- ieee80211_sta_init_nss(link_sta);
-
return 0;
}
@@ -3190,19 +3190,27 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
static int ieee80211_get_tx_power(struct wiphy *wiphy,
struct wireless_dev *wdev,
+ unsigned int link_id,
int *dbm)
{
struct ieee80211_local *local = wiphy_priv(wiphy);
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ struct ieee80211_link_data *link_data;
if (local->ops->get_txpower &&
(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
- return drv_get_txpower(local, sdata, dbm);
+ return drv_get_txpower(local, sdata, link_id, dbm);
- if (local->emulate_chanctx)
+ if (local->emulate_chanctx) {
*dbm = local->hw.conf.power_level;
- else
- *dbm = sdata->vif.bss_conf.txpower;
+ } else {
+ link_data = wiphy_dereference(wiphy, sdata->link[link_id]);
+
+ if (link_data)
+ *dbm = link_data->conf->txpower;
+ else
+ return -ENOLINK;
+ }
/* INT_MIN indicates no power level was set yet */
if (*dbm == INT_MIN)
@@ -3726,13 +3734,12 @@ void ieee80211_csa_finish(struct ieee80211_vif *vif, unsigned int link_id)
}
EXPORT_SYMBOL(ieee80211_csa_finish);
-void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif, bool block_tx)
+void ieee80211_channel_switch_disconnect(struct ieee80211_vif *vif)
{
struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
struct ieee80211_local *local = sdata->local;
- sdata->csa_blocked_queues = block_tx;
sdata_info(sdata, "channel switch failed, disconnecting\n");
wiphy_work_queue(local->hw.wiphy, &ifmgd->csa_connection_drop_work);
}
@@ -5046,10 +5053,16 @@ static void ieee80211_del_intf_link(struct wiphy *wiphy,
unsigned int link_id)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ u16 new_links = wdev->valid_links & ~BIT(link_id);
lockdep_assert_wiphy(sdata->local->hw.wiphy);
- ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
+ /* During the link teardown process, certain functions require the
+ * link_id to remain in the valid_links bitmap. Therefore, instead
+ * of removing the link_id from the bitmap, pass a masked value to
+ * simulate as if link_id does not exist anymore.
+ */
+ ieee80211_vif_set_links(sdata, new_links, 0);
}
static int
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index be2e486907f9..bf0a2902d93c 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -284,7 +284,8 @@ static ssize_t aql_txq_limit_write(struct file *file,
q_limit_low_old = local->aql_txq_limit_low[ac];
q_limit_high_old = local->aql_txq_limit_high[ac];
- wiphy_lock(local->hw.wiphy);
+ guard(wiphy)(local->hw.wiphy);
+
local->aql_txq_limit_low[ac] = q_limit_low;
local->aql_txq_limit_high[ac] = q_limit_high;
@@ -296,7 +297,6 @@ static ssize_t aql_txq_limit_write(struct file *file,
sta->airtime[ac].aql_limit_high = q_limit_high;
}
}
- wiphy_unlock(local->hw.wiphy);
return count;
}
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index edd1e4d4ad9d..c64531e0a60e 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1273,7 +1273,8 @@ static inline u32 drv_get_expected_throughput(struct ieee80211_local *local,
}
static inline int drv_get_txpower(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata, int *dbm)
+ struct ieee80211_sub_if_data *sdata,
+ unsigned int link_id, int *dbm)
{
int ret;
@@ -1283,8 +1284,8 @@ static inline int drv_get_txpower(struct ieee80211_local *local,
if (!local->ops->get_txpower)
return -EOPNOTSUPP;
- ret = local->ops->get_txpower(&local->hw, &sdata->vif, dbm);
- trace_drv_get_txpower(local, sdata, *dbm, ret);
+ ret = local->ops->get_txpower(&local->hw, &sdata->vif, link_id, dbm);
+ trace_drv_get_txpower(local, sdata, link_id, *dbm, ret);
return ret;
}
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c
index 99f6174a9d69..42f7ee142ce3 100644
--- a/net/mac80211/ethtool.c
+++ b/net/mac80211/ethtool.c
@@ -19,16 +19,13 @@ static int ieee80211_set_ringparam(struct net_device *dev,
struct netlink_ext_ack *extack)
{
struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy);
- int ret;
if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0)
return -EINVAL;
- wiphy_lock(local->hw.wiphy);
- ret = drv_set_ringparam(local, rp->tx_pending, rp->rx_pending);
- wiphy_unlock(local->hw.wiphy);
+ guard(wiphy)(local->hw.wiphy);
- return ret;
+ return drv_set_ringparam(local, rp->tx_pending, rp->rx_pending);
}
static void ieee80211_get_ringparam(struct net_device *dev,
@@ -40,10 +37,10 @@ static void ieee80211_get_ringparam(struct net_device *dev,
memset(rp, 0, sizeof(*rp));
- wiphy_lock(local->hw.wiphy);
+ guard(wiphy)(local->hw.wiphy);
+
drv_get_ringparam(local, &rp->tx_pending, &rp->tx_max_pending,
&rp->rx_pending, &rp->rx_max_pending);
- wiphy_unlock(local->hw.wiphy);
}
static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = {
@@ -109,7 +106,7 @@ static void ieee80211_get_stats(struct net_device *dev,
* network device.
*/
- wiphy_lock(local->hw.wiphy);
+ guard(wiphy)(local->hw.wiphy);
if (sdata->vif.type == NL80211_IFTYPE_STATION) {
sta = sta_info_get_bss(sdata, sdata->deflink.u.mgd.bssid);
@@ -160,6 +157,10 @@ do_survey:
chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
if (chanctx_conf)
channel = chanctx_conf->def.chan;
+ else if (local->open_count > 0 &&
+ local->open_count == local->monitors &&
+ sdata->vif.type == NL80211_IFTYPE_MONITOR)
+ channel = local->monitor_chanreq.oper.chan;
else
channel = NULL;
rcu_read_unlock();
@@ -205,13 +206,10 @@ do_survey:
else
data[i++] = -1LL;
- if (WARN_ON(i != STA_STATS_LEN)) {
- wiphy_unlock(local->hw.wiphy);
+ if (WARN_ON(i != STA_STATS_LEN))
return;
- }
drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN]));
- wiphy_unlock(local->hw.wiphy);
}
static void ieee80211_get_strings(struct net_device *dev, u32 sset, u8 *data)
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a00096dd787b..a98133d5c362 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1104,8 +1104,6 @@ struct ieee80211_sub_if_data {
unsigned long state;
- bool csa_blocked_queues;
-
char name[IFNAMSIZ];
struct ieee80211_fragment_cache frags;
@@ -1206,7 +1204,7 @@ struct ieee80211_sub_if_data *vif_to_sdata(struct ieee80211_vif *p)
for (int ___link_id = 0; \
___link_id < ARRAY_SIZE(___sdata->link); \
___link_id++) \
- if ((_link = wiphy_dereference((local)->hw.wiphy, \
+ if ((_link = wiphy_dereference((_local)->hw.wiphy, \
___sdata->link[___link_id])))
static inline int
@@ -2412,17 +2410,13 @@ void ieee80211_send_4addr_nullfunc(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata);
void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
struct ieee80211_hdr *hdr, bool ack, u16 tx_time);
-
+unsigned int
+ieee80211_get_vif_queues(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata);
void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
unsigned long queues,
enum queue_stop_reason reason,
bool refcounted);
-void ieee80211_stop_vif_queues(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- enum queue_stop_reason reason);
-void ieee80211_wake_vif_queues(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- enum queue_stop_reason reason);
void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
unsigned long queues,
enum queue_stop_reason reason,
@@ -2433,6 +2427,43 @@ void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
enum queue_stop_reason reason,
bool refcounted);
+static inline void
+ieee80211_stop_vif_queues(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ enum queue_stop_reason reason)
+{
+ ieee80211_stop_queues_by_reason(&local->hw,
+ ieee80211_get_vif_queues(local, sdata),
+ reason, true);
+}
+
+static inline void
+ieee80211_wake_vif_queues(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ enum queue_stop_reason reason)
+{
+ ieee80211_wake_queues_by_reason(&local->hw,
+ ieee80211_get_vif_queues(local, sdata),
+ reason, true);
+}
+static inline void
+ieee80211_stop_vif_queues_norefcount(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ enum queue_stop_reason reason)
+{
+ ieee80211_stop_queues_by_reason(&local->hw,
+ ieee80211_get_vif_queues(local, sdata),
+ reason, false);
+}
+static inline void
+ieee80211_wake_vif_queues_norefcount(struct ieee80211_local *local,
+ struct ieee80211_sub_if_data *sdata,
+ enum queue_stop_reason reason)
+{
+ ieee80211_wake_queues_by_reason(&local->hw,
+ ieee80211_get_vif_queues(local, sdata),
+ reason, false);
+}
void ieee80211_add_pending_skb(struct ieee80211_local *local,
struct sk_buff *skb);
void ieee80211_add_pending_skbs(struct ieee80211_local *local,
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index a8fbedd530f4..2e170dbde732 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -278,13 +278,8 @@ static int _ieee80211_change_mac(struct ieee80211_sub_if_data *sdata,
ret = eth_mac_addr(sdata->dev, sa);
if (ret == 0) {
- if (check_dup) {
- memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
- ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
- } else {
- memset(sdata->vif.addr, 0, ETH_ALEN);
- memset(sdata->vif.bss_conf.addr, 0, ETH_ALEN);
- }
+ memcpy(sdata->vif.addr, sa->sa_data, ETH_ALEN);
+ ether_addr_copy(sdata->vif.bss_conf.addr, sdata->vif.addr);
}
/* Regardless of eth_mac_addr() return we still want to add the
@@ -300,7 +295,6 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
- int ret;
/*
* This happens during unregistration if there's a bond device
@@ -310,11 +304,9 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr)
if (!dev->ieee80211_ptr->registered)
return 0;
- wiphy_lock(local->hw.wiphy);
- ret = _ieee80211_change_mac(sdata, addr);
- wiphy_unlock(local->hw.wiphy);
+ guard(wiphy)(local->hw.wiphy);
- return ret;
+ return _ieee80211_change_mac(sdata, addr);
}
static inline int identical_mac_addr_allowed(int type1, int type2)
@@ -450,16 +442,13 @@ static int ieee80211_open(struct net_device *dev)
if (!is_valid_ether_addr(dev->dev_addr))
return -EADDRNOTAVAIL;
- wiphy_lock(sdata->local->hw.wiphy);
+ guard(wiphy)(sdata->local->hw.wiphy);
+
err = ieee80211_check_concurrent_iface(sdata, sdata->vif.type);
if (err)
- goto out;
-
- err = ieee80211_do_open(&sdata->wdev, true);
-out:
- wiphy_unlock(sdata->local->hw.wiphy);
+ return err;
- return err;
+ return ieee80211_do_open(&sdata->wdev, true);
}
static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, bool going_down)
@@ -780,11 +769,11 @@ static int ieee80211_stop(struct net_device *dev)
ieee80211_stop_mbssid(sdata);
}
- wiphy_lock(sdata->local->hw.wiphy);
+ guard(wiphy)(sdata->local->hw.wiphy);
+
wiphy_work_cancel(sdata->local->hw.wiphy, &sdata->activate_links_work);
ieee80211_do_stop(sdata, true);
- wiphy_unlock(sdata->local->hw.wiphy);
return 0;
}
@@ -1323,6 +1312,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
}
}
+ sdata->vif.addr_valid = sdata->vif.type != NL80211_IFTYPE_MONITOR ||
+ (sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE);
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
/* no need to tell driver, but set carrier and chanctx */
@@ -2282,7 +2273,7 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
*/
cfg80211_shutdown_all_interfaces(local->hw.wiphy);
- wiphy_lock(local->hw.wiphy);
+ guard(wiphy)(local->hw.wiphy);
WARN(local->open_count, "%s: open count remains %d\n",
wiphy_name(local->hw.wiphy), local->open_count);
@@ -2312,7 +2303,6 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local)
if (!netdev)
kfree(sdata);
}
- wiphy_unlock(local->hw.wiphy);
}
static int netdev_notify(struct notifier_block *nb,
@@ -2374,18 +2364,14 @@ void ieee80211_vif_block_queues_csa(struct ieee80211_sub_if_data *sdata)
if (ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA))
return;
- ieee80211_stop_vif_queues(local, sdata,
- IEEE80211_QUEUE_STOP_REASON_CSA);
- sdata->csa_blocked_queues = true;
+ ieee80211_stop_vif_queues_norefcount(local, sdata,
+ IEEE80211_QUEUE_STOP_REASON_CSA);
}
void ieee80211_vif_unblock_queues_csa(struct ieee80211_sub_if_data *sdata)
{
struct ieee80211_local *local = sdata->local;
- if (sdata->csa_blocked_queues) {
- ieee80211_wake_vif_queues(local, sdata,
- IEEE80211_QUEUE_STOP_REASON_CSA);
- sdata->csa_blocked_queues = false;
- }
+ ieee80211_wake_vif_queues_norefcount(local, sdata,
+ IEEE80211_QUEUE_STOP_REASON_CSA);
}
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index ee1211a213d7..f13c14fa82e8 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -5,7 +5,7 @@
* Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
* Copyright 2013-2014 Intel Mobile Communications GmbH
* Copyright (C) 2017 Intel Deutschland GmbH
- * Copyright (C) 2018-2023 Intel Corporation
+ * Copyright (C) 2018-2024 Intel Corporation
*/
#include <net/mac80211.h>
@@ -726,8 +726,13 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
},
[NL80211_IFTYPE_P2P_DEVICE] = {
.tx = 0xffff,
+ /*
+ * To support P2P PASN pairing let user space register to rx
+ * also AUTH frames on P2P device interface.
+ */
.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
- BIT(IEEE80211_STYPE_PROBE_REQ >> 4),
+ BIT(IEEE80211_STYPE_PROBE_REQ >> 4) |
+ BIT(IEEE80211_STYPE_AUTH >> 4),
},
};
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index cb5f16366b9c..974081324aa4 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1157,14 +1157,14 @@ void ieee80211_mbss_info_change_notify(struct ieee80211_sub_if_data *sdata,
u64 changed)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
- unsigned long bits = changed;
+ unsigned long bits[] = { BITMAP_FROM_U64(changed) };
u32 bit;
- if (!bits)
+ if (!changed)
return;
/* if we race with running work, worst case this work becomes a noop */
- for_each_set_bit(bit, &bits, sizeof(changed) * BITS_PER_BYTE)
+ for_each_set_bit(bit, bits, sizeof(changed) * BITS_PER_BYTE)
set_bit(bit, ifmsh->mbss_changed);
set_bit(MESH_WORK_MBSS_CHANGED, &ifmsh->wrkq_flags);
wiphy_work_queue(sdata->local->hw.wiphy, &sdata->work);
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 480b664151c9..61c318f5239f 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -2638,8 +2638,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_link_data *link,
*/
link->conf->csa_active = true;
link->u.mgd.csa.blocked_tx = csa_ie.mode;
- sdata->csa_blocked_queues =
- csa_ie.mode && !ieee80211_hw_check(&local->hw, HANDLES_QUIET_CSA);
wiphy_work_queue(sdata->local->hw.wiphy,
&ifmgd->csa_connection_drop_work);
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 2bec18fc1b03..58c1b9a4e8b5 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -4562,7 +4562,9 @@ static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
return ieee80211_is_public_action(hdr, skb->len) ||
ieee80211_is_probe_req(hdr->frame_control) ||
ieee80211_is_probe_resp(hdr->frame_control) ||
- ieee80211_is_beacon(hdr->frame_control);
+ ieee80211_is_beacon(hdr->frame_control) ||
+ (ieee80211_is_auth(hdr->frame_control) &&
+ ether_addr_equal(sdata->vif.addr, hdr->addr1));
case NL80211_IFTYPE_NAN:
/* Currently no frames on NAN interface are allowed */
return false;
diff --git a/net/mac80211/tests/elems.c b/net/mac80211/tests/elems.c
index a413ba29f759..a53c55a879a8 100644
--- a/net/mac80211/tests/elems.c
+++ b/net/mac80211/tests/elems.c
@@ -7,7 +7,7 @@
#include <kunit/test.h>
#include "../ieee80211_i.h"
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static void mle_defrag(struct kunit *test)
{
diff --git a/net/mac80211/tests/mfp.c b/net/mac80211/tests/mfp.c
index a8dc1601da60..58e675e0ed91 100644
--- a/net/mac80211/tests/mfp.c
+++ b/net/mac80211/tests/mfp.c
@@ -9,7 +9,7 @@
#include "../ieee80211_i.h"
#include "../sta_info.h"
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static const struct mfp_test_case {
const char *desc;
diff --git a/net/mac80211/tests/tpe.c b/net/mac80211/tests/tpe.c
index dd63303a2985..c73b6c66bd5a 100644
--- a/net/mac80211/tests/tpe.c
+++ b/net/mac80211/tests/tpe.c
@@ -7,7 +7,7 @@
#include <kunit/test.h>
#include "../ieee80211_i.h"
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static struct ieee80211_channel chan6g_1 = {
.band = NL80211_BAND_6GHZ,
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 7a4985fc2b16..dc35fed7e9b0 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2173,13 +2173,14 @@ DEFINE_EVENT(chanswitch_evt, drv_channel_switch_rx_beacon,
TRACE_EVENT(drv_get_txpower,
TP_PROTO(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata,
- int dbm, int ret),
+ unsigned int link_id, int dbm, int ret),
- TP_ARGS(local, sdata, dbm, ret),
+ TP_ARGS(local, sdata, link_id, dbm, ret),
TP_STRUCT__entry(
LOCAL_ENTRY
VIF_ENTRY
+ __field(unsigned int, link_id)
__field(int, dbm)
__field(int, ret)
),
@@ -2187,13 +2188,14 @@ TRACE_EVENT(drv_get_txpower,
TP_fast_assign(
LOCAL_ASSIGN;
VIF_ASSIGN;
+ __entry->link_id = link_id;
__entry->dbm = dbm;
__entry->ret = ret;
),
TP_printk(
- LOCAL_PR_FMT VIF_PR_FMT " dbm:%d ret:%d",
- LOCAL_PR_ARG, VIF_PR_ARG, __entry->dbm, __entry->ret
+ LOCAL_PR_FMT VIF_PR_FMT " link_id:%d dbm:%d ret:%d",
+ LOCAL_PR_ARG, VIF_PR_ARG, __entry->link_id, __entry->dbm, __entry->ret
)
);
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index a4e1301cc999..7b656326e68a 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -657,7 +657,7 @@ void ieee80211_wake_queues(struct ieee80211_hw *hw)
}
EXPORT_SYMBOL(ieee80211_wake_queues);
-static unsigned int
+unsigned int
ieee80211_get_vif_queues(struct ieee80211_local *local,
struct ieee80211_sub_if_data *sdata)
{
@@ -669,7 +669,8 @@ ieee80211_get_vif_queues(struct ieee80211_local *local,
queues = 0;
for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
- queues |= BIT(sdata->vif.hw_queue[ac]);
+ if (sdata->vif.hw_queue[ac] != IEEE80211_INVAL_HW_QUEUE)
+ queues |= BIT(sdata->vif.hw_queue[ac]);
if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE)
queues |= BIT(sdata->vif.cab_queue);
} else {
@@ -724,24 +725,6 @@ void ieee80211_flush_queues(struct ieee80211_local *local,
__ieee80211_flush_queues(local, sdata, 0, drop);
}
-void ieee80211_stop_vif_queues(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- enum queue_stop_reason reason)
-{
- ieee80211_stop_queues_by_reason(&local->hw,
- ieee80211_get_vif_queues(local, sdata),
- reason, true);
-}
-
-void ieee80211_wake_vif_queues(struct ieee80211_local *local,
- struct ieee80211_sub_if_data *sdata,
- enum queue_stop_reason reason)
-{
- ieee80211_wake_queues_by_reason(&local->hw,
- ieee80211_get_vif_queues(local, sdata),
- reason, true);
-}
-
static void __iterate_interfaces(struct ieee80211_local *local,
u32 iter_flags,
void (*iterator)(void *data, u8 *mac,
@@ -1843,6 +1826,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n");
else
WARN(1, "Hardware became unavailable during restart.\n");
+ ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
+ IEEE80211_QUEUE_STOP_REASON_SUSPEND,
+ false);
ieee80211_handle_reconfig_failure(local);
return res;
}
@@ -2762,6 +2748,7 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos, const struct cfg80211_chan_def *chandef)
{
struct ieee80211_he_operation *he_oper;
struct ieee80211_he_6ghz_oper *he_6ghz_op;
+ struct cfg80211_chan_def he_chandef;
u32 he_oper_params;
u8 ie_len = 1 + sizeof(struct ieee80211_he_operation);
@@ -2793,27 +2780,33 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos, const struct cfg80211_chan_def *chandef)
if (chandef->chan->band != NL80211_BAND_6GHZ)
goto out;
+ cfg80211_chandef_create(&he_chandef, chandef->chan, NL80211_CHAN_NO_HT);
+ he_chandef.center_freq1 = chandef->center_freq1;
+ he_chandef.center_freq2 = chandef->center_freq2;
+ he_chandef.width = chandef->width;
+
/* TODO add VHT operational */
he_6ghz_op = (struct ieee80211_he_6ghz_oper *)pos;
he_6ghz_op->minrate = 6; /* 6 Mbps */
he_6ghz_op->primary =
- ieee80211_frequency_to_channel(chandef->chan->center_freq);
+ ieee80211_frequency_to_channel(he_chandef.chan->center_freq);
he_6ghz_op->ccfs0 =
- ieee80211_frequency_to_channel(chandef->center_freq1);
- if (chandef->center_freq2)
+ ieee80211_frequency_to_channel(he_chandef.center_freq1);
+ if (he_chandef.center_freq2)
he_6ghz_op->ccfs1 =
- ieee80211_frequency_to_channel(chandef->center_freq2);
+ ieee80211_frequency_to_channel(he_chandef.center_freq2);
else
he_6ghz_op->ccfs1 = 0;
- switch (chandef->width) {
+ switch (he_chandef.width) {
case NL80211_CHAN_WIDTH_320:
- /*
- * TODO: mesh operation is not defined over 6GHz 320 MHz
- * channels.
+ /* Downgrade EHT 320 MHz BW to 160 MHz for HE and set new
+ * center_freq1
*/
- WARN_ON(1);
- break;
+ ieee80211_chandef_downgrade(&he_chandef, NULL);
+ he_6ghz_op->ccfs0 =
+ ieee80211_frequency_to_channel(he_chandef.center_freq1);
+ fallthrough;
case NL80211_CHAN_WIDTH_160:
/* Convert 160 MHz channel width to new style as interop
* workaround.
@@ -2821,7 +2814,7 @@ u8 *ieee80211_ie_build_he_oper(u8 *pos, const struct cfg80211_chan_def *chandef)
he_6ghz_op->control =
IEEE80211_HE_6GHZ_OPER_CTRL_CHANWIDTH_160MHZ;
he_6ghz_op->ccfs1 = he_6ghz_op->ccfs0;
- if (chandef->chan->center_freq < chandef->center_freq1)
+ if (he_chandef.chan->center_freq < he_chandef.center_freq1)
he_6ghz_op->ccfs0 -= 8;
else
he_6ghz_op->ccfs0 += 8;
diff --git a/net/mac802154/ieee802154_i.h b/net/mac802154/ieee802154_i.h
index 08dd521a51a5..8f2bff268392 100644
--- a/net/mac802154/ieee802154_i.h
+++ b/net/mac802154/ieee802154_i.h
@@ -194,9 +194,6 @@ int ieee802154_mlme_tx_locked(struct ieee802154_local *local,
struct ieee802154_sub_if_data *sdata,
struct sk_buff *skb);
void ieee802154_mlme_op_post(struct ieee802154_local *local);
-int ieee802154_mlme_tx_one(struct ieee802154_local *local,
- struct ieee802154_sub_if_data *sdata,
- struct sk_buff *skb);
int ieee802154_mlme_tx_one_locked(struct ieee802154_local *local,
struct ieee802154_sub_if_data *sdata,
struct sk_buff *skb);
diff --git a/net/mac802154/iface.c b/net/mac802154/iface.c
index c0e2da5072be..9e4631fade90 100644
--- a/net/mac802154/iface.c
+++ b/net/mac802154/iface.c
@@ -684,6 +684,10 @@ void ieee802154_if_remove(struct ieee802154_sub_if_data *sdata)
ASSERT_RTNL();
mutex_lock(&sdata->local->iflist_mtx);
+ if (list_empty(&sdata->local->interfaces)) {
+ mutex_unlock(&sdata->local->iflist_mtx);
+ return;
+ }
list_del_rcu(&sdata->list);
mutex_unlock(&sdata->local->iflist_mtx);
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c
index 337d6faf0d2a..4d13f18f6f2c 100644
--- a/net/mac802154/tx.c
+++ b/net/mac802154/tx.c
@@ -178,19 +178,6 @@ void ieee802154_mlme_op_post(struct ieee802154_local *local)
ieee802154_release_queue(local);
}
-int ieee802154_mlme_tx_one(struct ieee802154_local *local,
- struct ieee802154_sub_if_data *sdata,
- struct sk_buff *skb)
-{
- int ret;
-
- ieee802154_mlme_op_pre(local);
- ret = ieee802154_mlme_tx(local, sdata, skb);
- ieee802154_mlme_op_post(local);
-
- return ret;
-}
-
int ieee802154_mlme_tx_one_locked(struct ieee802154_local *local,
struct ieee802154_sub_if_data *sdata,
struct sk_buff *skb)
diff --git a/net/mctp/device.c b/net/mctp/device.c
index 26ce34b7e88e..8e0724c56723 100644
--- a/net/mctp/device.c
+++ b/net/mctp/device.c
@@ -20,8 +20,7 @@
#include <net/sock.h>
struct mctp_dump_cb {
- int h;
- int idx;
+ unsigned long ifindex;
size_t a_idx;
};
@@ -115,43 +114,29 @@ static int mctp_dump_addrinfo(struct sk_buff *skb, struct netlink_callback *cb)
{
struct mctp_dump_cb *mcb = (void *)cb->ctx;
struct net *net = sock_net(skb->sk);
- struct hlist_head *head;
struct net_device *dev;
struct ifaddrmsg *hdr;
struct mctp_dev *mdev;
- int ifindex;
- int idx = 0, rc;
+ int ifindex, rc;
hdr = nlmsg_data(cb->nlh);
// filter by ifindex if requested
ifindex = hdr->ifa_index;
rcu_read_lock();
- for (; mcb->h < NETDEV_HASHENTRIES; mcb->h++, mcb->idx = 0) {
- idx = 0;
- head = &net->dev_index_head[mcb->h];
- hlist_for_each_entry_rcu(dev, head, index_hlist) {
- if (idx >= mcb->idx &&
- (ifindex == 0 || ifindex == dev->ifindex)) {
- mdev = __mctp_dev_get(dev);
- if (mdev) {
- rc = mctp_dump_dev_addrinfo(mdev,
- skb, cb);
- mctp_dev_put(mdev);
- // Error indicates full buffer, this
- // callback will get retried.
- if (rc < 0)
- goto out;
- }
- }
- idx++;
- // reset for next iteration
- mcb->a_idx = 0;
- }
+ for_each_netdev_dump(net, dev, mcb->ifindex) {
+ if (ifindex && ifindex != dev->ifindex)
+ continue;
+ mdev = __mctp_dev_get(dev);
+ if (!mdev)
+ continue;
+ rc = mctp_dump_dev_addrinfo(mdev, skb, cb);
+ mctp_dev_put(mdev);
+ if (rc < 0)
+ break;
+ mcb->a_idx = 0;
}
-out:
rcu_read_unlock();
- mcb->idx = idx;
return skb->len;
}
@@ -531,9 +516,12 @@ static struct notifier_block mctp_dev_nb = {
};
static const struct rtnl_msg_handler mctp_device_rtnl_msg_handlers[] = {
- {THIS_MODULE, PF_MCTP, RTM_NEWADDR, mctp_rtm_newaddr, NULL, 0},
- {THIS_MODULE, PF_MCTP, RTM_DELADDR, mctp_rtm_deladdr, NULL, 0},
- {THIS_MODULE, PF_MCTP, RTM_GETADDR, NULL, mctp_dump_addrinfo, 0},
+ {.owner = THIS_MODULE, .protocol = PF_MCTP, .msgtype = RTM_NEWADDR,
+ .doit = mctp_rtm_newaddr},
+ {.owner = THIS_MODULE, .protocol = PF_MCTP, .msgtype = RTM_DELADDR,
+ .doit = mctp_rtm_deladdr},
+ {.owner = THIS_MODULE, .protocol = PF_MCTP, .msgtype = RTM_GETADDR,
+ .dumpit = mctp_dump_addrinfo},
};
int __init mctp_device_init(void)
diff --git a/net/mctp/route.c b/net/mctp/route.c
index 597e9cf5aa64..3f2bd65ff5e3 100644
--- a/net/mctp/route.c
+++ b/net/mctp/route.c
@@ -374,8 +374,13 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
msk = NULL;
rc = -EINVAL;
- /* we may be receiving a locally-routed packet; drop source sk
- * accounting
+ /* We may be receiving a locally-routed packet; drop source sk
+ * accounting.
+ *
+ * From here, we will either queue the skb - either to a frag_queue, or
+ * to a receiving socket. When that succeeds, we clear the skb pointer;
+ * a non-NULL skb on exit will be otherwise unowned, and hence
+ * kfree_skb()-ed.
*/
skb_orphan(skb);
@@ -434,7 +439,9 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
* pending key.
*/
if (flags & MCTP_HDR_FLAG_EOM) {
- sock_queue_rcv_skb(&msk->sk, skb);
+ rc = sock_queue_rcv_skb(&msk->sk, skb);
+ if (!rc)
+ skb = NULL;
if (key) {
/* we've hit a pending reassembly; not much we
* can do but drop it
@@ -443,7 +450,6 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
MCTP_TRACE_KEY_REPLIED);
key = NULL;
}
- rc = 0;
goto out_unlock;
}
@@ -470,8 +476,10 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
* this function.
*/
rc = mctp_key_add(key, msk);
- if (!rc)
+ if (!rc) {
trace_mctp_key_acquire(key);
+ skb = NULL;
+ }
/* we don't need to release key->lock on exit, so
* clean up here and suppress the unlock via
@@ -489,6 +497,8 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
key = NULL;
} else {
rc = mctp_frag_queue(key, skb);
+ if (!rc)
+ skb = NULL;
}
}
@@ -503,12 +513,19 @@ static int mctp_route_input(struct mctp_route *route, struct sk_buff *skb)
else
rc = mctp_frag_queue(key, skb);
+ if (rc)
+ goto out_unlock;
+
+ /* we've queued; the queue owns the skb now */
+ skb = NULL;
+
/* end of message? deliver to socket, and we're done with
* the reassembly/response key
*/
- if (!rc && flags & MCTP_HDR_FLAG_EOM) {
- sock_queue_rcv_skb(key->sk, key->reasm_head);
- key->reasm_head = NULL;
+ if (flags & MCTP_HDR_FLAG_EOM) {
+ rc = sock_queue_rcv_skb(key->sk, key->reasm_head);
+ if (!rc)
+ key->reasm_head = NULL;
__mctp_key_done_in(key, net, f, MCTP_TRACE_KEY_REPLIED);
key = NULL;
}
@@ -527,8 +544,7 @@ out_unlock:
if (any_key)
mctp_key_unref(any_key);
out:
- if (rc)
- kfree_skb(skb);
+ kfree_skb(skb);
return rc;
}
diff --git a/net/mctp/test/route-test.c b/net/mctp/test/route-test.c
index 8551dab1d1e6..17165b86ce22 100644
--- a/net/mctp/test/route-test.c
+++ b/net/mctp/test/route-test.c
@@ -837,6 +837,90 @@ static void mctp_test_route_input_multiple_nets_key(struct kunit *test)
mctp_test_route_input_multiple_nets_key_fini(test, &t2);
}
+/* Input route to socket, using a single-packet message, where sock delivery
+ * fails. Ensure we're handling the failure appropriately.
+ */
+static void mctp_test_route_input_sk_fail_single(struct kunit *test)
+{
+ const struct mctp_hdr hdr = RX_HDR(1, 10, 8, FL_S | FL_E | FL_TO);
+ struct mctp_test_route *rt;
+ struct mctp_test_dev *dev;
+ struct socket *sock;
+ struct sk_buff *skb;
+ int rc;
+
+ __mctp_route_test_init(test, &dev, &rt, &sock, MCTP_NET_ANY);
+
+ /* No rcvbuf space, so delivery should fail. __sock_set_rcvbuf will
+ * clamp the minimum to SOCK_MIN_RCVBUF, so we open-code this.
+ */
+ lock_sock(sock->sk);
+ WRITE_ONCE(sock->sk->sk_rcvbuf, 0);
+ release_sock(sock->sk);
+
+ skb = mctp_test_create_skb(&hdr, 10);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skb);
+ skb_get(skb);
+
+ mctp_test_skb_set_dev(skb, dev);
+
+ /* do route input, which should fail */
+ rc = mctp_route_input(&rt->rt, skb);
+ KUNIT_EXPECT_NE(test, rc, 0);
+
+ /* we should hold the only reference to skb */
+ KUNIT_EXPECT_EQ(test, refcount_read(&skb->users), 1);
+ kfree_skb(skb);
+
+ __mctp_route_test_fini(test, dev, rt, sock);
+}
+
+/* Input route to socket, using a fragmented message, where sock delivery fails.
+ */
+static void mctp_test_route_input_sk_fail_frag(struct kunit *test)
+{
+ const struct mctp_hdr hdrs[2] = { RX_FRAG(FL_S, 0), RX_FRAG(FL_E, 1) };
+ struct mctp_test_route *rt;
+ struct mctp_test_dev *dev;
+ struct sk_buff *skbs[2];
+ struct socket *sock;
+ unsigned int i;
+ int rc;
+
+ __mctp_route_test_init(test, &dev, &rt, &sock, MCTP_NET_ANY);
+
+ lock_sock(sock->sk);
+ WRITE_ONCE(sock->sk->sk_rcvbuf, 0);
+ release_sock(sock->sk);
+
+ for (i = 0; i < ARRAY_SIZE(skbs); i++) {
+ skbs[i] = mctp_test_create_skb(&hdrs[i], 10);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, skbs[i]);
+ skb_get(skbs[i]);
+
+ mctp_test_skb_set_dev(skbs[i], dev);
+ }
+
+ /* first route input should succeed, we're only queueing to the
+ * frag list
+ */
+ rc = mctp_route_input(&rt->rt, skbs[0]);
+ KUNIT_EXPECT_EQ(test, rc, 0);
+
+ /* final route input should fail to deliver to the socket */
+ rc = mctp_route_input(&rt->rt, skbs[1]);
+ KUNIT_EXPECT_NE(test, rc, 0);
+
+ /* we should hold the only reference to both skbs */
+ KUNIT_EXPECT_EQ(test, refcount_read(&skbs[0]->users), 1);
+ kfree_skb(skbs[0]);
+
+ KUNIT_EXPECT_EQ(test, refcount_read(&skbs[1]->users), 1);
+ kfree_skb(skbs[1]);
+
+ __mctp_route_test_fini(test, dev, rt, sock);
+}
+
#if IS_ENABLED(CONFIG_MCTP_FLOWS)
static void mctp_test_flow_init(struct kunit *test,
@@ -1053,6 +1137,8 @@ static struct kunit_case mctp_test_cases[] = {
mctp_route_input_sk_reasm_gen_params),
KUNIT_CASE_PARAM(mctp_test_route_input_sk_keys,
mctp_route_input_sk_keys_gen_params),
+ KUNIT_CASE(mctp_test_route_input_sk_fail_single),
+ KUNIT_CASE(mctp_test_route_input_sk_fail_frag),
KUNIT_CASE(mctp_test_route_input_multiple_nets_bind),
KUNIT_CASE(mctp_test_route_input_multiple_nets_key),
KUNIT_CASE(mctp_test_packet_flow),
diff --git a/net/mptcp/ctrl.c b/net/mptcp/ctrl.c
index 38d8121331d4..b0dd008e2114 100644
--- a/net/mptcp/ctrl.c
+++ b/net/mptcp/ctrl.c
@@ -102,16 +102,15 @@ static void mptcp_pernet_set_defaults(struct mptcp_pernet *pernet)
}
#ifdef CONFIG_SYSCTL
-static int mptcp_set_scheduler(const struct net *net, const char *name)
+static int mptcp_set_scheduler(char *scheduler, const char *name)
{
- struct mptcp_pernet *pernet = mptcp_get_pernet(net);
struct mptcp_sched_ops *sched;
int ret = 0;
rcu_read_lock();
sched = mptcp_sched_find(name);
if (sched)
- strscpy(pernet->scheduler, name, MPTCP_SCHED_NAME_MAX);
+ strscpy(scheduler, name, MPTCP_SCHED_NAME_MAX);
else
ret = -ENOENT;
rcu_read_unlock();
@@ -122,7 +121,7 @@ static int mptcp_set_scheduler(const struct net *net, const char *name)
static int proc_scheduler(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
- const struct net *net = current->nsproxy->net_ns;
+ char (*scheduler)[MPTCP_SCHED_NAME_MAX] = ctl->data;
char val[MPTCP_SCHED_NAME_MAX];
struct ctl_table tbl = {
.data = val,
@@ -130,11 +129,11 @@ static int proc_scheduler(const struct ctl_table *ctl, int write,
};
int ret;
- strscpy(val, mptcp_get_scheduler(net), MPTCP_SCHED_NAME_MAX);
+ strscpy(val, *scheduler, MPTCP_SCHED_NAME_MAX);
ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
if (write && ret == 0)
- ret = mptcp_set_scheduler(net, val);
+ ret = mptcp_set_scheduler(*scheduler, val);
return ret;
}
@@ -161,7 +160,9 @@ static int proc_blackhole_detect_timeout(const struct ctl_table *table,
int write, void *buffer, size_t *lenp,
loff_t *ppos)
{
- struct mptcp_pernet *pernet = mptcp_get_pernet(current->nsproxy->net_ns);
+ struct mptcp_pernet *pernet = container_of(table->data,
+ struct mptcp_pernet,
+ blackhole_timeout);
int ret;
ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
@@ -228,7 +229,7 @@ static struct ctl_table mptcp_sysctl_table[] = {
{
.procname = "available_schedulers",
.maxlen = MPTCP_SCHED_BUF_MAX,
- .mode = 0644,
+ .mode = 0444,
.proc_handler = proc_available_schedulers,
},
{
diff --git a/net/mptcp/options.c b/net/mptcp/options.c
index 1603b3702e22..a62bc874bf1e 100644
--- a/net/mptcp/options.c
+++ b/net/mptcp/options.c
@@ -667,8 +667,15 @@ static bool mptcp_established_options_add_addr(struct sock *sk, struct sk_buff *
&echo, &drop_other_suboptions))
return false;
+ /*
+ * Later on, mptcp_write_options() will enforce mutually exclusion with
+ * DSS, bail out if such option is set and we can't drop it.
+ */
if (drop_other_suboptions)
remaining += opt_size;
+ else if (opts->suboptions & OPTION_MPTCP_DSS)
+ return false;
+
len = mptcp_add_addr_len(opts->addr.family, echo, !!opts->addr.port);
if (remaining < len)
return false;
diff --git a/net/mptcp/pm_netlink.c b/net/mptcp/pm_netlink.c
index 7a0f7998376a..98ac73938bd8 100644
--- a/net/mptcp/pm_netlink.c
+++ b/net/mptcp/pm_netlink.c
@@ -107,8 +107,8 @@ static void remote_address(const struct sock_common *skc,
#endif
}
-static bool lookup_subflow_by_saddr(const struct list_head *list,
- const struct mptcp_addr_info *saddr)
+bool mptcp_lookup_subflow_by_saddr(const struct list_head *list,
+ const struct mptcp_addr_info *saddr)
{
struct mptcp_subflow_context *subflow;
struct mptcp_addr_info cur;
@@ -1447,8 +1447,8 @@ out_free:
return ret;
}
-static bool remove_anno_list_by_saddr(struct mptcp_sock *msk,
- const struct mptcp_addr_info *addr)
+bool mptcp_remove_anno_list_by_saddr(struct mptcp_sock *msk,
+ const struct mptcp_addr_info *addr)
{
struct mptcp_pm_add_entry *entry;
@@ -1476,7 +1476,7 @@ static bool mptcp_pm_remove_anno_addr(struct mptcp_sock *msk,
list.ids[list.nr++] = mptcp_endp_get_local_id(msk, addr);
- ret = remove_anno_list_by_saddr(msk, addr);
+ ret = mptcp_remove_anno_list_by_saddr(msk, addr);
if (ret || force) {
spin_lock_bh(&msk->pm.lock);
if (ret) {
@@ -1520,7 +1520,7 @@ static int mptcp_nl_remove_subflow_and_signal_addr(struct net *net,
}
lock_sock(sk);
- remove_subflow = lookup_subflow_by_saddr(&msk->conn_list, addr);
+ remove_subflow = mptcp_lookup_subflow_by_saddr(&msk->conn_list, addr);
mptcp_pm_remove_anno_addr(msk, addr, remove_subflow &&
!(entry->flags & MPTCP_PM_ADDR_FLAG_IMPLICIT));
@@ -1633,36 +1633,6 @@ int mptcp_pm_nl_del_addr_doit(struct sk_buff *skb, struct genl_info *info)
return ret;
}
-/* Called from the userspace PM only */
-void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list)
-{
- struct mptcp_rm_list alist = { .nr = 0 };
- struct mptcp_pm_addr_entry *entry;
- int anno_nr = 0;
-
- list_for_each_entry(entry, rm_list, list) {
- if (alist.nr >= MPTCP_RM_IDS_MAX)
- break;
-
- /* only delete if either announced or matching a subflow */
- if (remove_anno_list_by_saddr(msk, &entry->addr))
- anno_nr++;
- else if (!lookup_subflow_by_saddr(&msk->conn_list,
- &entry->addr))
- continue;
-
- alist.ids[alist.nr++] = entry->addr.id;
- }
-
- if (alist.nr) {
- spin_lock_bh(&msk->pm.lock);
- msk->pm.add_addr_signaled -= anno_nr;
- mptcp_pm_remove_addr(msk, &alist);
- spin_unlock_bh(&msk->pm.lock);
- }
-}
-
-/* Called from the in-kernel PM only */
static void mptcp_pm_flush_addrs_and_subflows(struct mptcp_sock *msk,
struct list_head *rm_list)
{
@@ -1671,11 +1641,11 @@ static void mptcp_pm_flush_addrs_and_subflows(struct mptcp_sock *msk,
list_for_each_entry(entry, rm_list, list) {
if (slist.nr < MPTCP_RM_IDS_MAX &&
- lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
+ mptcp_lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
slist.ids[slist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
if (alist.nr < MPTCP_RM_IDS_MAX &&
- remove_anno_list_by_saddr(msk, &entry->addr))
+ mptcp_remove_anno_list_by_saddr(msk, &entry->addr))
alist.ids[alist.nr++] = mptcp_endp_get_local_id(msk, &entry->addr);
}
diff --git a/net/mptcp/pm_userspace.c b/net/mptcp/pm_userspace.c
index e35178f5205f..740a10d669f8 100644
--- a/net/mptcp/pm_userspace.c
+++ b/net/mptcp/pm_userspace.c
@@ -8,6 +8,10 @@
#include "mib.h"
#include "mptcp_pm_gen.h"
+#define mptcp_for_each_userspace_pm_addr(__msk, __entry) \
+ list_for_each_entry(__entry, \
+ &((__msk)->pm.userspace_pm_local_addr_list), list)
+
void mptcp_free_local_addr_list(struct mptcp_sock *msk)
{
struct mptcp_pm_addr_entry *entry, *tmp;
@@ -26,6 +30,19 @@ void mptcp_free_local_addr_list(struct mptcp_sock *msk)
}
}
+static struct mptcp_pm_addr_entry *
+mptcp_userspace_pm_lookup_addr(struct mptcp_sock *msk,
+ const struct mptcp_addr_info *addr)
+{
+ struct mptcp_pm_addr_entry *entry;
+
+ mptcp_for_each_userspace_pm_addr(msk, entry) {
+ if (mptcp_addresses_equal(&entry->addr, addr, false))
+ return entry;
+ }
+ return NULL;
+}
+
static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
struct mptcp_pm_addr_entry *entry,
bool needs_id)
@@ -41,7 +58,7 @@ static int mptcp_userspace_pm_append_new_local_addr(struct mptcp_sock *msk,
bitmap_zero(id_bitmap, MPTCP_PM_MAX_ADDR_ID + 1);
spin_lock_bh(&msk->pm.lock);
- list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) {
+ mptcp_for_each_userspace_pm_addr(msk, e) {
addr_match = mptcp_addresses_equal(&e->addr, &entry->addr, true);
if (addr_match && entry->addr.id == 0 && needs_id)
entry->addr.id = e->addr.id;
@@ -90,22 +107,20 @@ append_err:
static int mptcp_userspace_pm_delete_local_addr(struct mptcp_sock *msk,
struct mptcp_pm_addr_entry *addr)
{
- struct mptcp_pm_addr_entry *entry, *tmp;
struct sock *sk = (struct sock *)msk;
+ struct mptcp_pm_addr_entry *entry;
- list_for_each_entry_safe(entry, tmp, &msk->pm.userspace_pm_local_addr_list, list) {
- if (mptcp_addresses_equal(&entry->addr, &addr->addr, false)) {
- /* TODO: a refcount is needed because the entry can
- * be used multiple times (e.g. fullmesh mode).
- */
- list_del_rcu(&entry->list);
- sock_kfree_s(sk, entry, sizeof(*entry));
- msk->pm.local_addr_used--;
- return 0;
- }
- }
-
- return -EINVAL;
+ entry = mptcp_userspace_pm_lookup_addr(msk, &addr->addr);
+ if (!entry)
+ return -EINVAL;
+
+ /* TODO: a refcount is needed because the entry can
+ * be used multiple times (e.g. fullmesh mode).
+ */
+ list_del_rcu(&entry->list);
+ sock_kfree_s(sk, entry, sizeof(*entry));
+ msk->pm.local_addr_used--;
+ return 0;
}
static struct mptcp_pm_addr_entry *
@@ -113,7 +128,7 @@ mptcp_userspace_pm_lookup_addr_by_id(struct mptcp_sock *msk, unsigned int id)
{
struct mptcp_pm_addr_entry *entry;
- list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
+ mptcp_for_each_userspace_pm_addr(msk, entry) {
if (entry->addr.id == id)
return entry;
}
@@ -123,17 +138,12 @@ mptcp_userspace_pm_lookup_addr_by_id(struct mptcp_sock *msk, unsigned int id)
int mptcp_userspace_pm_get_local_id(struct mptcp_sock *msk,
struct mptcp_addr_info *skc)
{
- struct mptcp_pm_addr_entry *entry = NULL, *e, new_entry;
+ struct mptcp_pm_addr_entry *entry = NULL, new_entry;
__be16 msk_sport = ((struct inet_sock *)
inet_sk((struct sock *)msk))->inet_sport;
spin_lock_bh(&msk->pm.lock);
- list_for_each_entry(e, &msk->pm.userspace_pm_local_addr_list, list) {
- if (mptcp_addresses_equal(&e->addr, skc, false)) {
- entry = e;
- break;
- }
- }
+ entry = mptcp_userspace_pm_lookup_addr(msk, skc);
spin_unlock_bh(&msk->pm.lock);
if (entry)
return entry->addr.id;
@@ -153,50 +163,60 @@ bool mptcp_userspace_pm_is_backup(struct mptcp_sock *msk,
struct mptcp_addr_info *skc)
{
struct mptcp_pm_addr_entry *entry;
- bool backup = false;
+ bool backup;
spin_lock_bh(&msk->pm.lock);
- list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
- if (mptcp_addresses_equal(&entry->addr, skc, false)) {
- backup = !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
- break;
- }
- }
+ entry = mptcp_userspace_pm_lookup_addr(msk, skc);
+ backup = entry && !!(entry->flags & MPTCP_PM_ADDR_FLAG_BACKUP);
spin_unlock_bh(&msk->pm.lock);
return backup;
}
-int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info)
+static struct mptcp_sock *mptcp_userspace_pm_get_sock(const struct genl_info *info)
{
struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
+ struct mptcp_sock *msk;
+
+ if (!token) {
+ GENL_SET_ERR_MSG(info, "missing required token");
+ return NULL;
+ }
+
+ msk = mptcp_token_get_sock(genl_info_net(info), nla_get_u32(token));
+ if (!msk) {
+ NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
+ return NULL;
+ }
+
+ if (!mptcp_pm_is_userspace(msk)) {
+ GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
+ sock_put((struct sock *)msk);
+ return NULL;
+ }
+
+ return msk;
+}
+
+int mptcp_pm_nl_announce_doit(struct sk_buff *skb, struct genl_info *info)
+{
struct nlattr *addr = info->attrs[MPTCP_PM_ATTR_ADDR];
struct mptcp_pm_addr_entry addr_val;
struct mptcp_sock *msk;
int err = -EINVAL;
struct sock *sk;
- u32 token_val;
- if (!addr || !token) {
- GENL_SET_ERR_MSG(info, "missing required inputs");
+ if (!addr) {
+ GENL_SET_ERR_MSG(info, "missing required address");
return err;
}
- token_val = nla_get_u32(token);
-
- msk = mptcp_token_get_sock(sock_net(skb->sk), token_val);
- if (!msk) {
- NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
+ msk = mptcp_userspace_pm_get_sock(info);
+ if (!msk)
return err;
- }
sk = (struct sock *)msk;
- if (!mptcp_pm_is_userspace(msk)) {
- GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
- goto announce_err;
- }
-
err = mptcp_pm_parse_entry(addr, info, true, &addr_val);
if (err < 0) {
GENL_SET_ERR_MSG(info, "error parsing local address");
@@ -267,40 +287,48 @@ remove_err:
return err;
}
+void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
+ struct mptcp_pm_addr_entry *entry)
+{
+ struct mptcp_rm_list alist = { .nr = 0 };
+ int anno_nr = 0;
+
+ /* only delete if either announced or matching a subflow */
+ if (mptcp_remove_anno_list_by_saddr(msk, &entry->addr))
+ anno_nr++;
+ else if (!mptcp_lookup_subflow_by_saddr(&msk->conn_list, &entry->addr))
+ return;
+
+ alist.ids[alist.nr++] = entry->addr.id;
+
+ spin_lock_bh(&msk->pm.lock);
+ msk->pm.add_addr_signaled -= anno_nr;
+ mptcp_pm_remove_addr(msk, &alist);
+ spin_unlock_bh(&msk->pm.lock);
+}
+
int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
{
- struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
struct nlattr *id = info->attrs[MPTCP_PM_ATTR_LOC_ID];
struct mptcp_pm_addr_entry *match;
- struct mptcp_pm_addr_entry *entry;
struct mptcp_sock *msk;
- LIST_HEAD(free_list);
int err = -EINVAL;
struct sock *sk;
- u32 token_val;
u8 id_val;
- if (!id || !token) {
- GENL_SET_ERR_MSG(info, "missing required inputs");
+ if (!id) {
+ GENL_SET_ERR_MSG(info, "missing required ID");
return err;
}
id_val = nla_get_u8(id);
- token_val = nla_get_u32(token);
- msk = mptcp_token_get_sock(sock_net(skb->sk), token_val);
- if (!msk) {
- NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
+ msk = mptcp_userspace_pm_get_sock(info);
+ if (!msk)
return err;
- }
sk = (struct sock *)msk;
- if (!mptcp_pm_is_userspace(msk)) {
- GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
- goto out;
- }
-
if (id_val == 0) {
err = mptcp_userspace_pm_remove_id_zero_address(msk, info);
goto out;
@@ -317,16 +345,14 @@ int mptcp_pm_nl_remove_doit(struct sk_buff *skb, struct genl_info *info)
goto out;
}
- list_move(&match->list, &free_list);
+ list_del_rcu(&match->list);
spin_unlock_bh(&msk->pm.lock);
- mptcp_pm_remove_addrs(msk, &free_list);
+ mptcp_pm_remove_addr_entry(msk, match);
release_sock(sk);
- list_for_each_entry_safe(match, entry, &free_list, list) {
- sock_kfree_s(sk, match, sizeof(*match));
- }
+ sock_kfree_s(sk, match, sizeof(*match));
err = 0;
out:
@@ -337,7 +363,6 @@ out:
int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)
{
struct nlattr *raddr = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
- struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
struct nlattr *laddr = info->attrs[MPTCP_PM_ATTR_ADDR];
struct mptcp_pm_addr_entry entry = { 0 };
struct mptcp_addr_info addr_r;
@@ -345,28 +370,18 @@ int mptcp_pm_nl_subflow_create_doit(struct sk_buff *skb, struct genl_info *info)
struct mptcp_sock *msk;
int err = -EINVAL;
struct sock *sk;
- u32 token_val;
- if (!laddr || !raddr || !token) {
- GENL_SET_ERR_MSG(info, "missing required inputs");
+ if (!laddr || !raddr) {
+ GENL_SET_ERR_MSG(info, "missing required address(es)");
return err;
}
- token_val = nla_get_u32(token);
-
- msk = mptcp_token_get_sock(genl_info_net(info), token_val);
- if (!msk) {
- NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
+ msk = mptcp_userspace_pm_get_sock(info);
+ if (!msk)
return err;
- }
sk = (struct sock *)msk;
- if (!mptcp_pm_is_userspace(msk)) {
- GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
- goto create_err;
- }
-
err = mptcp_pm_parse_entry(laddr, info, true, &entry);
if (err < 0) {
NL_SET_ERR_MSG_ATTR(info->extack, laddr, "error parsing local addr");
@@ -469,36 +484,25 @@ static struct sock *mptcp_nl_find_ssk(struct mptcp_sock *msk,
int mptcp_pm_nl_subflow_destroy_doit(struct sk_buff *skb, struct genl_info *info)
{
struct nlattr *raddr = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
- struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
struct nlattr *laddr = info->attrs[MPTCP_PM_ATTR_ADDR];
- struct mptcp_addr_info addr_l;
+ struct mptcp_pm_addr_entry addr_l;
struct mptcp_addr_info addr_r;
struct mptcp_sock *msk;
struct sock *sk, *ssk;
int err = -EINVAL;
- u32 token_val;
- if (!laddr || !raddr || !token) {
- GENL_SET_ERR_MSG(info, "missing required inputs");
+ if (!laddr || !raddr) {
+ GENL_SET_ERR_MSG(info, "missing required address(es)");
return err;
}
- token_val = nla_get_u32(token);
-
- msk = mptcp_token_get_sock(genl_info_net(info), token_val);
- if (!msk) {
- NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
+ msk = mptcp_userspace_pm_get_sock(info);
+ if (!msk)
return err;
- }
sk = (struct sock *)msk;
- if (!mptcp_pm_is_userspace(msk)) {
- GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
- goto destroy_err;
- }
-
- err = mptcp_pm_parse_addr(laddr, info, &addr_l);
+ err = mptcp_pm_parse_entry(laddr, info, true, &addr_l);
if (err < 0) {
NL_SET_ERR_MSG_ATTR(info->extack, laddr, "error parsing local addr");
goto destroy_err;
@@ -511,43 +515,41 @@ int mptcp_pm_nl_subflow_destroy_doit(struct sk_buff *skb, struct genl_info *info
}
#if IS_ENABLED(CONFIG_MPTCP_IPV6)
- if (addr_l.family == AF_INET && ipv6_addr_v4mapped(&addr_r.addr6)) {
- ipv6_addr_set_v4mapped(addr_l.addr.s_addr, &addr_l.addr6);
- addr_l.family = AF_INET6;
+ if (addr_l.addr.family == AF_INET && ipv6_addr_v4mapped(&addr_r.addr6)) {
+ ipv6_addr_set_v4mapped(addr_l.addr.addr.s_addr, &addr_l.addr.addr6);
+ addr_l.addr.family = AF_INET6;
}
- if (addr_r.family == AF_INET && ipv6_addr_v4mapped(&addr_l.addr6)) {
- ipv6_addr_set_v4mapped(addr_r.addr.s_addr, &addr_r.addr6);
+ if (addr_r.family == AF_INET && ipv6_addr_v4mapped(&addr_l.addr.addr6)) {
+ ipv6_addr_set_v4mapped(addr_r.addr.s_addr, &addr_l.addr.addr6);
addr_r.family = AF_INET6;
}
#endif
- if (addr_l.family != addr_r.family) {
+ if (addr_l.addr.family != addr_r.family) {
GENL_SET_ERR_MSG(info, "address families do not match");
err = -EINVAL;
goto destroy_err;
}
- if (!addr_l.port || !addr_r.port) {
+ if (!addr_l.addr.port || !addr_r.port) {
GENL_SET_ERR_MSG(info, "missing local or remote port");
err = -EINVAL;
goto destroy_err;
}
lock_sock(sk);
- ssk = mptcp_nl_find_ssk(msk, &addr_l, &addr_r);
- if (ssk) {
- struct mptcp_subflow_context *subflow = mptcp_subflow_ctx(ssk);
- struct mptcp_pm_addr_entry entry = { .addr = addr_l };
-
- spin_lock_bh(&msk->pm.lock);
- mptcp_userspace_pm_delete_local_addr(msk, &entry);
- spin_unlock_bh(&msk->pm.lock);
- mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
- mptcp_close_ssk(sk, ssk, subflow);
- MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
- err = 0;
- } else {
+ ssk = mptcp_nl_find_ssk(msk, &addr_l.addr, &addr_r);
+ if (!ssk) {
err = -ESRCH;
+ goto release_sock;
}
+
+ spin_lock_bh(&msk->pm.lock);
+ mptcp_userspace_pm_delete_local_addr(msk, &addr_l);
+ spin_unlock_bh(&msk->pm.lock);
+ mptcp_subflow_shutdown(sk, ssk, RCV_SHUTDOWN | SEND_SHUTDOWN);
+ mptcp_close_ssk(sk, ssk, mptcp_subflow_ctx(ssk));
+ MPTCP_INC_STATS(sock_net(sk), MPTCP_MIB_RMSUBFLOW);
+release_sock:
release_sock(sk);
destroy_err:
@@ -560,31 +562,19 @@ int mptcp_userspace_pm_set_flags(struct sk_buff *skb, struct genl_info *info)
struct mptcp_pm_addr_entry loc = { .addr = { .family = AF_UNSPEC }, };
struct mptcp_pm_addr_entry rem = { .addr = { .family = AF_UNSPEC }, };
struct nlattr *attr_rem = info->attrs[MPTCP_PM_ATTR_ADDR_REMOTE];
- struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
struct nlattr *attr = info->attrs[MPTCP_PM_ATTR_ADDR];
- struct net *net = sock_net(skb->sk);
struct mptcp_pm_addr_entry *entry;
struct mptcp_sock *msk;
int ret = -EINVAL;
struct sock *sk;
- u32 token_val;
u8 bkup = 0;
- token_val = nla_get_u32(token);
-
- msk = mptcp_token_get_sock(net, token_val);
- if (!msk) {
- NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
+ msk = mptcp_userspace_pm_get_sock(info);
+ if (!msk)
return ret;
- }
sk = (struct sock *)msk;
- if (!mptcp_pm_is_userspace(msk)) {
- GENL_SET_ERR_MSG(info, "userspace PM not selected");
- goto set_flags_err;
- }
-
ret = mptcp_pm_parse_entry(attr, info, false, &loc);
if (ret < 0)
goto set_flags_err;
@@ -606,13 +596,12 @@ int mptcp_userspace_pm_set_flags(struct sk_buff *skb, struct genl_info *info)
bkup = 1;
spin_lock_bh(&msk->pm.lock);
- list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
- if (mptcp_addresses_equal(&entry->addr, &loc.addr, false)) {
- if (bkup)
- entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
- else
- entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
- }
+ entry = mptcp_userspace_pm_lookup_addr(msk, &loc.addr);
+ if (entry) {
+ if (bkup)
+ entry->flags |= MPTCP_PM_ADDR_FLAG_BACKUP;
+ else
+ entry->flags &= ~MPTCP_PM_ADDR_FLAG_BACKUP;
}
spin_unlock_bh(&msk->pm.lock);
@@ -632,33 +621,23 @@ int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
DECLARE_BITMAP(map, MPTCP_PM_MAX_ADDR_ID + 1);
} *bitmap;
const struct genl_info *info = genl_info_dump(cb);
- struct net *net = sock_net(msg->sk);
struct mptcp_pm_addr_entry *entry;
struct mptcp_sock *msk;
- struct nlattr *token;
int ret = -EINVAL;
struct sock *sk;
void *hdr;
bitmap = (struct id_bitmap *)cb->ctx;
- token = info->attrs[MPTCP_PM_ATTR_TOKEN];
- msk = mptcp_token_get_sock(net, nla_get_u32(token));
- if (!msk) {
- NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
+ msk = mptcp_userspace_pm_get_sock(info);
+ if (!msk)
return ret;
- }
sk = (struct sock *)msk;
- if (!mptcp_pm_is_userspace(msk)) {
- GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
- goto out;
- }
-
lock_sock(sk);
spin_lock_bh(&msk->pm.lock);
- list_for_each_entry(entry, &msk->pm.userspace_pm_local_addr_list, list) {
+ mptcp_for_each_userspace_pm_addr(msk, entry) {
if (test_bit(entry->addr.id, bitmap->map))
continue;
@@ -680,7 +659,6 @@ int mptcp_userspace_pm_dump_addr(struct sk_buff *msg,
release_sock(sk);
ret = msg->len;
-out:
sock_put(sk);
return ret;
}
@@ -689,28 +667,19 @@ int mptcp_userspace_pm_get_addr(struct sk_buff *skb,
struct genl_info *info)
{
struct nlattr *attr = info->attrs[MPTCP_PM_ENDPOINT_ADDR];
- struct nlattr *token = info->attrs[MPTCP_PM_ATTR_TOKEN];
struct mptcp_pm_addr_entry addr, *entry;
- struct net *net = sock_net(skb->sk);
struct mptcp_sock *msk;
struct sk_buff *msg;
int ret = -EINVAL;
struct sock *sk;
void *reply;
- msk = mptcp_token_get_sock(net, nla_get_u32(token));
- if (!msk) {
- NL_SET_ERR_MSG_ATTR(info->extack, token, "invalid token");
+ msk = mptcp_userspace_pm_get_sock(info);
+ if (!msk)
return ret;
- }
sk = (struct sock *)msk;
- if (!mptcp_pm_is_userspace(msk)) {
- GENL_SET_ERR_MSG(info, "invalid request; userspace PM not selected");
- goto out;
- }
-
ret = mptcp_pm_parse_entry(attr, info, false, &addr);
if (ret < 0)
goto out;
diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c
index 08a72242428c..1b2e7cbb577f 100644
--- a/net/mptcp/protocol.c
+++ b/net/mptcp/protocol.c
@@ -136,6 +136,7 @@ static bool mptcp_try_coalesce(struct sock *sk, struct sk_buff *to,
int delta;
if (MPTCP_SKB_CB(from)->offset ||
+ ((to->len + from->len) > (sk->sk_rcvbuf >> 3)) ||
!skb_try_coalesce(to, from, &fragstolen, &delta))
return false;
@@ -528,13 +529,13 @@ static void mptcp_send_ack(struct mptcp_sock *msk)
mptcp_subflow_send_ack(mptcp_subflow_tcp_sock(subflow));
}
-static void mptcp_subflow_cleanup_rbuf(struct sock *ssk)
+static void mptcp_subflow_cleanup_rbuf(struct sock *ssk, int copied)
{
bool slow;
slow = lock_sock_fast(ssk);
if (tcp_can_send_ack(ssk))
- tcp_cleanup_rbuf(ssk, 1);
+ tcp_cleanup_rbuf(ssk, copied);
unlock_sock_fast(ssk, slow);
}
@@ -551,7 +552,7 @@ static bool mptcp_subflow_could_cleanup(const struct sock *ssk, bool rx_empty)
(ICSK_ACK_PUSHED2 | ICSK_ACK_PUSHED)));
}
-static void mptcp_cleanup_rbuf(struct mptcp_sock *msk)
+static void mptcp_cleanup_rbuf(struct mptcp_sock *msk, int copied)
{
int old_space = READ_ONCE(msk->old_wspace);
struct mptcp_subflow_context *subflow;
@@ -559,14 +560,14 @@ static void mptcp_cleanup_rbuf(struct mptcp_sock *msk)
int space = __mptcp_space(sk);
bool cleanup, rx_empty;
- cleanup = (space > 0) && (space >= (old_space << 1));
- rx_empty = !__mptcp_rmem(sk);
+ cleanup = (space > 0) && (space >= (old_space << 1)) && copied;
+ rx_empty = !__mptcp_rmem(sk) && copied;
mptcp_for_each_subflow(msk, subflow) {
struct sock *ssk = mptcp_subflow_tcp_sock(subflow);
if (cleanup || mptcp_subflow_could_cleanup(ssk, rx_empty))
- mptcp_subflow_cleanup_rbuf(ssk);
+ mptcp_subflow_cleanup_rbuf(ssk, copied);
}
}
@@ -1939,6 +1940,8 @@ do_error:
goto out;
}
+static void mptcp_rcv_space_adjust(struct mptcp_sock *msk, int copied);
+
static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk,
struct msghdr *msg,
size_t len, int flags,
@@ -1992,6 +1995,7 @@ static int __mptcp_recvmsg_mskq(struct mptcp_sock *msk,
break;
}
+ mptcp_rcv_space_adjust(msk, copied);
return copied;
}
@@ -2217,9 +2221,6 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
copied += bytes_read;
- /* be sure to advertise window change */
- mptcp_cleanup_rbuf(msk);
-
if (skb_queue_empty(&msk->receive_queue) && __mptcp_move_skbs(msk))
continue;
@@ -2268,7 +2269,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
}
pr_debug("block timeout %ld\n", timeo);
- mptcp_rcv_space_adjust(msk, copied);
+ mptcp_cleanup_rbuf(msk, copied);
err = sk_wait_data(sk, &timeo, NULL);
if (err < 0) {
err = copied ? : err;
@@ -2276,7 +2277,7 @@ static int mptcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
}
}
- mptcp_rcv_space_adjust(msk, copied);
+ mptcp_cleanup_rbuf(msk, copied);
out_err:
if (cmsg_flags && copied >= 0) {
diff --git a/net/mptcp/protocol.h b/net/mptcp/protocol.h
index a93e661ef5c4..cd5132fe7d22 100644
--- a/net/mptcp/protocol.h
+++ b/net/mptcp/protocol.h
@@ -1027,6 +1027,10 @@ mptcp_pm_del_add_timer(struct mptcp_sock *msk,
struct mptcp_pm_add_entry *
mptcp_lookup_anno_list_by_saddr(const struct mptcp_sock *msk,
const struct mptcp_addr_info *addr);
+bool mptcp_lookup_subflow_by_saddr(const struct list_head *list,
+ const struct mptcp_addr_info *saddr);
+bool mptcp_remove_anno_list_by_saddr(struct mptcp_sock *msk,
+ const struct mptcp_addr_info *addr);
int mptcp_pm_set_flags(struct sk_buff *skb, struct genl_info *info);
int mptcp_pm_nl_set_flags(struct sk_buff *skb, struct genl_info *info);
int mptcp_userspace_pm_set_flags(struct sk_buff *skb, struct genl_info *info);
@@ -1034,7 +1038,8 @@ int mptcp_pm_announce_addr(struct mptcp_sock *msk,
const struct mptcp_addr_info *addr,
bool echo);
int mptcp_pm_remove_addr(struct mptcp_sock *msk, const struct mptcp_rm_list *rm_list);
-void mptcp_pm_remove_addrs(struct mptcp_sock *msk, struct list_head *rm_list);
+void mptcp_pm_remove_addr_entry(struct mptcp_sock *msk,
+ struct mptcp_pm_addr_entry *entry);
void mptcp_free_local_addr_list(struct mptcp_sock *msk);
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c
index 61431690cbd5..cc20e6d56807 100644
--- a/net/netfilter/ipset/ip_set_core.c
+++ b/net/netfilter/ipset/ip_set_core.c
@@ -104,14 +104,19 @@ find_set_type(const char *name, u8 family, u8 revision)
static bool
load_settype(const char *name)
{
+ if (!try_module_get(THIS_MODULE))
+ return false;
+
nfnl_unlock(NFNL_SUBSYS_IPSET);
pr_debug("try to load ip_set_%s\n", name);
if (request_module("ip_set_%s", name) < 0) {
pr_warn("Can't find ip_set type %s\n", name);
nfnl_lock(NFNL_SUBSYS_IPSET);
+ module_put(THIS_MODULE);
return false;
}
nfnl_lock(NFNL_SUBSYS_IPSET);
+ module_put(THIS_MODULE);
return true;
}
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c
index bfae7066936b..db794fe1300e 100644
--- a/net/netfilter/ipset/ip_set_list_set.c
+++ b/net/netfilter/ipset/ip_set_list_set.c
@@ -611,6 +611,8 @@ init_list_set(struct net *net, struct ip_set *set, u32 size)
return true;
}
+static struct lock_class_key list_set_lockdep_key;
+
static int
list_set_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
u32 flags)
@@ -627,6 +629,7 @@ list_set_create(struct net *net, struct ip_set *set, struct nlattr *tb[],
if (size < IP_SET_LIST_MIN_SIZE)
size = IP_SET_LIST_MIN_SIZE;
+ lockdep_set_class(&set->lock, &list_set_lockdep_key);
set->variant = &set_variant;
set->dsize = ip_set_elem_len(set, tb, sizeof(struct set_elem),
__alignof__(struct set_elem));
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c
index 98d7dbe3d787..c0289f83f96d 100644
--- a/net/netfilter/ipvs/ip_vs_conn.c
+++ b/net/netfilter/ipvs/ip_vs_conn.c
@@ -1495,8 +1495,8 @@ int __init ip_vs_conn_init(void)
max_avail -= 2; /* ~4 in hash row */
max_avail -= 1; /* IPVS up to 1/2 of mem */
max_avail -= order_base_2(sizeof(struct ip_vs_conn));
- max = clamp(max, min, max_avail);
- ip_vs_conn_tab_bits = clamp_val(ip_vs_conn_tab_bits, min, max);
+ max = clamp(max_avail, min, max);
+ ip_vs_conn_tab_bits = clamp(ip_vs_conn_tab_bits, min, max);
ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits;
ip_vs_conn_tab_mask = ip_vs_conn_tab_size - 1;
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c
index f100da4ba3bc..a9fd1d3fc2cb 100644
--- a/net/netfilter/ipvs/ip_vs_proto.c
+++ b/net/netfilter/ipvs/ip_vs_proto.c
@@ -340,7 +340,7 @@ void __net_exit ip_vs_protocol_net_cleanup(struct netns_ipvs *ipvs)
int __init ip_vs_protocol_init(void)
{
- char protocols[64];
+ char protocols[64] = { 0 };
#define REGISTER_PROTOCOL(p) \
do { \
register_ip_vs_protocol(p); \
@@ -348,8 +348,6 @@ int __init ip_vs_protocol_init(void)
strcat(protocols, (p)->name); \
} while (0)
- protocols[0] = '\0';
- protocols[2] = '\0';
#ifdef CONFIG_IP_VS_PROTO_TCP
REGISTER_PROTOCOL(&ip_vs_protocol_tcp);
#endif
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 9db3e2b0b1c3..456446d7af20 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -2517,12 +2517,15 @@ void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
struct hlist_nulls_head *hash;
unsigned int nr_slots, i;
- if (*sizep > (UINT_MAX / sizeof(struct hlist_nulls_head)))
+ if (*sizep > (INT_MAX / sizeof(struct hlist_nulls_head)))
return NULL;
BUILD_BUG_ON(sizeof(struct hlist_nulls_head) != sizeof(struct hlist_head));
nr_slots = *sizep = roundup(*sizep, PAGE_SIZE / sizeof(struct hlist_nulls_head));
+ if (nr_slots > (INT_MAX / sizeof(struct hlist_nulls_head)))
+ return NULL;
+
hash = kvcalloc(nr_slots, sizeof(struct hlist_nulls_head), GFP_KERNEL);
if (hash && nulls)
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c
index 21b6f7410a1f..c4af283356e7 100644
--- a/net/netfilter/nf_tables_api.c
+++ b/net/netfilter/nf_tables_api.c
@@ -1596,7 +1596,6 @@ static int nf_tables_newtable(struct sk_buff *skb, const struct nfnl_info *info,
INIT_LIST_HEAD(&table->sets);
INIT_LIST_HEAD(&table->objects);
INIT_LIST_HEAD(&table->flowtables);
- write_pnet(&table->net, net);
table->family = family;
table->flags = flags;
table->handle = ++nft_net->table_handle;
@@ -3987,8 +3986,11 @@ void nf_tables_rule_destroy(const struct nft_ctx *ctx, struct nft_rule *rule)
kfree(rule);
}
+/* can only be used if rule is no longer visible to dumps */
static void nf_tables_rule_release(const struct nft_ctx *ctx, struct nft_rule *rule)
{
+ lockdep_commit_lock_is_held(ctx->net);
+
nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
nf_tables_rule_destroy(ctx, rule);
}
@@ -5757,6 +5759,8 @@ void nf_tables_deactivate_set(const struct nft_ctx *ctx, struct nft_set *set,
struct nft_set_binding *binding,
enum nft_trans_phase phase)
{
+ lockdep_commit_lock_is_held(ctx->net);
+
switch (phase) {
case NFT_TRANS_PREPARE_ERROR:
nft_set_trans_unbind(ctx, set);
@@ -8818,6 +8822,7 @@ static void nft_unregister_flowtable_hook(struct net *net,
}
static void __nft_unregister_flowtable_net_hooks(struct net *net,
+ struct nft_flowtable *flowtable,
struct list_head *hook_list,
bool release_netdev)
{
@@ -8825,6 +8830,8 @@ static void __nft_unregister_flowtable_net_hooks(struct net *net,
list_for_each_entry_safe(hook, next, hook_list, list) {
nf_unregister_net_hook(net, &hook->ops);
+ flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
+ FLOW_BLOCK_UNBIND);
if (release_netdev) {
list_del(&hook->list);
kfree_rcu(hook, rcu);
@@ -8833,9 +8840,10 @@ static void __nft_unregister_flowtable_net_hooks(struct net *net,
}
static void nft_unregister_flowtable_net_hooks(struct net *net,
+ struct nft_flowtable *flowtable,
struct list_head *hook_list)
{
- __nft_unregister_flowtable_net_hooks(net, hook_list, false);
+ __nft_unregister_flowtable_net_hooks(net, flowtable, hook_list, false);
}
static int nft_register_flowtable_net_hooks(struct net *net,
@@ -9477,8 +9485,6 @@ static void nf_tables_flowtable_destroy(struct nft_flowtable *flowtable)
flowtable->data.type->free(&flowtable->data);
list_for_each_entry_safe(hook, next, &flowtable->hook_list, list) {
- flowtable->data.type->setup(&flowtable->data, hook->ops.dev,
- FLOW_BLOCK_UNBIND);
list_del_rcu(&hook->list);
kfree_rcu(hook, rcu);
}
@@ -10866,6 +10872,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
&nft_trans_flowtable_hooks(trans),
trans->msg_type);
nft_unregister_flowtable_net_hooks(net,
+ nft_trans_flowtable(trans),
&nft_trans_flowtable_hooks(trans));
} else {
list_del_rcu(&nft_trans_flowtable(trans)->list);
@@ -10874,6 +10881,7 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
NULL,
trans->msg_type);
nft_unregister_flowtable_net_hooks(net,
+ nft_trans_flowtable(trans),
&nft_trans_flowtable(trans)->hook_list);
}
break;
@@ -11136,11 +11144,13 @@ static int __nf_tables_abort(struct net *net, enum nfnl_abort_action action)
case NFT_MSG_NEWFLOWTABLE:
if (nft_trans_flowtable_update(trans)) {
nft_unregister_flowtable_net_hooks(net,
+ nft_trans_flowtable(trans),
&nft_trans_flowtable_hooks(trans));
} else {
nft_use_dec_restore(&table->use);
list_del_rcu(&nft_trans_flowtable(trans)->list);
nft_unregister_flowtable_net_hooks(net,
+ nft_trans_flowtable(trans),
&nft_trans_flowtable(trans)->hook_list);
}
break;
@@ -11695,19 +11705,6 @@ static void __nft_release_basechain_now(struct nft_ctx *ctx)
nf_tables_chain_destroy(ctx->chain);
}
-static void nft_release_basechain_rcu(struct rcu_head *head)
-{
- struct nft_chain *chain = container_of(head, struct nft_chain, rcu_head);
- struct nft_ctx ctx = {
- .family = chain->table->family,
- .chain = chain,
- .net = read_pnet(&chain->table->net),
- };
-
- __nft_release_basechain_now(&ctx);
- put_net(ctx.net);
-}
-
int __nft_release_basechain(struct nft_ctx *ctx)
{
struct nft_rule *rule;
@@ -11722,11 +11719,18 @@ int __nft_release_basechain(struct nft_ctx *ctx)
nft_chain_del(ctx->chain);
nft_use_dec(&ctx->table->use);
- if (maybe_get_net(ctx->net))
- call_rcu(&ctx->chain->rcu_head, nft_release_basechain_rcu);
- else
+ if (!maybe_get_net(ctx->net)) {
__nft_release_basechain_now(ctx);
+ return 0;
+ }
+
+ /* wait for ruleset dumps to complete. Owning chain is no longer in
+ * lists, so new dumps can't find any of these rules anymore.
+ */
+ synchronize_rcu();
+ __nft_release_basechain_now(ctx);
+ put_net(ctx->net);
return 0;
}
EXPORT_SYMBOL_GPL(__nft_release_basechain);
@@ -11739,7 +11743,8 @@ static void __nft_release_hook(struct net *net, struct nft_table *table)
list_for_each_entry(chain, &table->chains, list)
__nf_tables_unregister_hook(net, table, chain, true);
list_for_each_entry(flowtable, &table->flowtables, list)
- __nft_unregister_flowtable_net_hooks(net, &flowtable->hook_list,
+ __nft_unregister_flowtable_net_hooks(net, flowtable,
+ &flowtable->hook_list,
true);
}
diff --git a/net/netfilter/nft_inner.c b/net/netfilter/nft_inner.c
index 928312d01eb1..817ab978d24a 100644
--- a/net/netfilter/nft_inner.c
+++ b/net/netfilter/nft_inner.c
@@ -210,35 +210,66 @@ static int nft_inner_parse(const struct nft_inner *priv,
struct nft_pktinfo *pkt,
struct nft_inner_tun_ctx *tun_ctx)
{
- struct nft_inner_tun_ctx ctx = {};
u32 off = pkt->inneroff;
if (priv->flags & NFT_INNER_HDRSIZE &&
- nft_inner_parse_tunhdr(priv, pkt, &ctx, &off) < 0)
+ nft_inner_parse_tunhdr(priv, pkt, tun_ctx, &off) < 0)
return -1;
if (priv->flags & (NFT_INNER_LL | NFT_INNER_NH)) {
- if (nft_inner_parse_l2l3(priv, pkt, &ctx, off) < 0)
+ if (nft_inner_parse_l2l3(priv, pkt, tun_ctx, off) < 0)
return -1;
} else if (priv->flags & NFT_INNER_TH) {
- ctx.inner_thoff = off;
- ctx.flags |= NFT_PAYLOAD_CTX_INNER_TH;
+ tun_ctx->inner_thoff = off;
+ tun_ctx->flags |= NFT_PAYLOAD_CTX_INNER_TH;
}
- *tun_ctx = ctx;
tun_ctx->type = priv->type;
+ tun_ctx->cookie = (unsigned long)pkt->skb;
pkt->flags |= NFT_PKTINFO_INNER_FULL;
return 0;
}
+static bool nft_inner_restore_tun_ctx(const struct nft_pktinfo *pkt,
+ struct nft_inner_tun_ctx *tun_ctx)
+{
+ struct nft_inner_tun_ctx *this_cpu_tun_ctx;
+
+ local_bh_disable();
+ this_cpu_tun_ctx = this_cpu_ptr(&nft_pcpu_tun_ctx);
+ if (this_cpu_tun_ctx->cookie != (unsigned long)pkt->skb) {
+ local_bh_enable();
+ return false;
+ }
+ *tun_ctx = *this_cpu_tun_ctx;
+ local_bh_enable();
+
+ return true;
+}
+
+static void nft_inner_save_tun_ctx(const struct nft_pktinfo *pkt,
+ const struct nft_inner_tun_ctx *tun_ctx)
+{
+ struct nft_inner_tun_ctx *this_cpu_tun_ctx;
+
+ local_bh_disable();
+ this_cpu_tun_ctx = this_cpu_ptr(&nft_pcpu_tun_ctx);
+ if (this_cpu_tun_ctx->cookie != tun_ctx->cookie)
+ *this_cpu_tun_ctx = *tun_ctx;
+ local_bh_enable();
+}
+
static bool nft_inner_parse_needed(const struct nft_inner *priv,
const struct nft_pktinfo *pkt,
- const struct nft_inner_tun_ctx *tun_ctx)
+ struct nft_inner_tun_ctx *tun_ctx)
{
if (!(pkt->flags & NFT_PKTINFO_INNER_FULL))
return true;
+ if (!nft_inner_restore_tun_ctx(pkt, tun_ctx))
+ return true;
+
if (priv->type != tun_ctx->type)
return true;
@@ -248,27 +279,29 @@ static bool nft_inner_parse_needed(const struct nft_inner *priv,
static void nft_inner_eval(const struct nft_expr *expr, struct nft_regs *regs,
const struct nft_pktinfo *pkt)
{
- struct nft_inner_tun_ctx *tun_ctx = this_cpu_ptr(&nft_pcpu_tun_ctx);
const struct nft_inner *priv = nft_expr_priv(expr);
+ struct nft_inner_tun_ctx tun_ctx = {};
if (nft_payload_inner_offset(pkt) < 0)
goto err;
- if (nft_inner_parse_needed(priv, pkt, tun_ctx) &&
- nft_inner_parse(priv, (struct nft_pktinfo *)pkt, tun_ctx) < 0)
+ if (nft_inner_parse_needed(priv, pkt, &tun_ctx) &&
+ nft_inner_parse(priv, (struct nft_pktinfo *)pkt, &tun_ctx) < 0)
goto err;
switch (priv->expr_type) {
case NFT_INNER_EXPR_PAYLOAD:
- nft_payload_inner_eval((struct nft_expr *)&priv->expr, regs, pkt, tun_ctx);
+ nft_payload_inner_eval((struct nft_expr *)&priv->expr, regs, pkt, &tun_ctx);
break;
case NFT_INNER_EXPR_META:
- nft_meta_inner_eval((struct nft_expr *)&priv->expr, regs, pkt, tun_ctx);
+ nft_meta_inner_eval((struct nft_expr *)&priv->expr, regs, pkt, &tun_ctx);
break;
default:
WARN_ON_ONCE(1);
goto err;
}
+ nft_inner_save_tun_ctx(pkt, &tun_ctx);
+
return;
err:
regs->verdict.code = NFT_BREAK;
diff --git a/net/netfilter/nft_set_hash.c b/net/netfilter/nft_set_hash.c
index 65bd291318f2..8bfac4185ac7 100644
--- a/net/netfilter/nft_set_hash.c
+++ b/net/netfilter/nft_set_hash.c
@@ -24,11 +24,13 @@
struct nft_rhash {
struct rhashtable ht;
struct delayed_work gc_work;
+ u32 wq_gc_seq;
};
struct nft_rhash_elem {
struct nft_elem_priv priv;
struct rhash_head node;
+ u32 wq_gc_seq;
struct nft_set_ext ext;
};
@@ -338,6 +340,10 @@ static void nft_rhash_gc(struct work_struct *work)
if (!gc)
goto done;
+ /* Elements never collected use a zero gc worker sequence number. */
+ if (unlikely(++priv->wq_gc_seq == 0))
+ priv->wq_gc_seq++;
+
rhashtable_walk_enter(&priv->ht, &hti);
rhashtable_walk_start(&hti);
@@ -355,6 +361,14 @@ static void nft_rhash_gc(struct work_struct *work)
goto try_later;
}
+ /* rhashtable walk is unstable, already seen in this gc run?
+ * Then, skip this element. In case of (unlikely) sequence
+ * wraparound and stale element wq_gc_seq, next gc run will
+ * just find this expired element.
+ */
+ if (he->wq_gc_seq == priv->wq_gc_seq)
+ continue;
+
if (nft_set_elem_is_dead(&he->ext))
goto dead_elem;
@@ -371,6 +385,8 @@ dead_elem:
if (!gc)
goto try_later;
+ /* annotate gc sequence for this attempt. */
+ he->wq_gc_seq = priv->wq_gc_seq;
nft_trans_gc_elem_add(gc, he);
}
diff --git a/net/netfilter/nft_socket.c b/net/netfilter/nft_socket.c
index f5da0c1775f2..35d0409b0095 100644
--- a/net/netfilter/nft_socket.c
+++ b/net/netfilter/nft_socket.c
@@ -68,7 +68,7 @@ static noinline int nft_socket_cgroup_subtree_level(void)
cgroup_put(cgrp);
- if (WARN_ON_ONCE(level > 255))
+ if (level > 255)
return -ERANGE;
if (WARN_ON_ONCE(level < 0))
diff --git a/net/netfilter/xt_IDLETIMER.c b/net/netfilter/xt_IDLETIMER.c
index 85f017e37cfc..9f54819eb52c 100644
--- a/net/netfilter/xt_IDLETIMER.c
+++ b/net/netfilter/xt_IDLETIMER.c
@@ -407,21 +407,23 @@ static void idletimer_tg_destroy(const struct xt_tgdtor_param *par)
mutex_lock(&list_mutex);
- if (--info->timer->refcnt == 0) {
- pr_debug("deleting timer %s\n", info->label);
-
- list_del(&info->timer->entry);
- timer_shutdown_sync(&info->timer->timer);
- cancel_work_sync(&info->timer->work);
- sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
- kfree(info->timer->attr.attr.name);
- kfree(info->timer);
- } else {
+ if (--info->timer->refcnt > 0) {
pr_debug("decreased refcnt of timer %s to %u\n",
info->label, info->timer->refcnt);
+ mutex_unlock(&list_mutex);
+ return;
}
+ pr_debug("deleting timer %s\n", info->label);
+
+ list_del(&info->timer->entry);
mutex_unlock(&list_mutex);
+
+ timer_shutdown_sync(&info->timer->timer);
+ cancel_work_sync(&info->timer->work);
+ sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
+ kfree(info->timer->attr.attr.name);
+ kfree(info->timer);
}
static void idletimer_tg_destroy_v1(const struct xt_tgdtor_param *par)
@@ -432,25 +434,27 @@ static void idletimer_tg_destroy_v1(const struct xt_tgdtor_param *par)
mutex_lock(&list_mutex);
- if (--info->timer->refcnt == 0) {
- pr_debug("deleting timer %s\n", info->label);
-
- list_del(&info->timer->entry);
- if (info->timer->timer_type & XT_IDLETIMER_ALARM) {
- alarm_cancel(&info->timer->alarm);
- } else {
- timer_shutdown_sync(&info->timer->timer);
- }
- cancel_work_sync(&info->timer->work);
- sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
- kfree(info->timer->attr.attr.name);
- kfree(info->timer);
- } else {
+ if (--info->timer->refcnt > 0) {
pr_debug("decreased refcnt of timer %s to %u\n",
info->label, info->timer->refcnt);
+ mutex_unlock(&list_mutex);
+ return;
}
+ pr_debug("deleting timer %s\n", info->label);
+
+ list_del(&info->timer->entry);
mutex_unlock(&list_mutex);
+
+ if (info->timer->timer_type & XT_IDLETIMER_ALARM) {
+ alarm_cancel(&info->timer->alarm);
+ } else {
+ timer_shutdown_sync(&info->timer->timer);
+ }
+ cancel_work_sync(&info->timer->work);
+ sysfs_remove_file(idletimer_tg_kobj, &info->timer->attr.attr);
+ kfree(info->timer->attr.attr.name);
+ kfree(info->timer);
}
diff --git a/net/netfilter/xt_LED.c b/net/netfilter/xt_LED.c
index f7b0286d106a..8a80fd76fe45 100644
--- a/net/netfilter/xt_LED.c
+++ b/net/netfilter/xt_LED.c
@@ -96,7 +96,9 @@ static int led_tg_check(const struct xt_tgchk_param *par)
struct xt_led_info_internal *ledinternal;
int err;
- if (ledinfo->id[0] == '\0')
+ /* Bail out if empty string or not a string at all. */
+ if (ledinfo->id[0] == '\0' ||
+ !memchr(ledinfo->id, '\0', sizeof(ledinfo->id)))
return -EINVAL;
mutex_lock(&xt_led_mutex);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index f4e7b5e4bb59..85311226183a 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -1287,6 +1287,7 @@ static struct sk_buff *netlink_trim(struct sk_buff *skb, gfp_t allocation)
{
int delta;
+ skb_assert_len(skb);
WARN_ON(skb->sk != NULL);
delta = skb->end - skb->tail;
if (is_vmalloc_addr(skb->head) || delta * 2 < skb->truesize)
diff --git a/net/netrom/nr_route.c b/net/netrom/nr_route.c
index 2b5e246b8d9a..b94cb2ffbaf8 100644
--- a/net/netrom/nr_route.c
+++ b/net/netrom/nr_route.c
@@ -754,6 +754,12 @@ int nr_route_frame(struct sk_buff *skb, ax25_cb *ax25)
int ret;
struct sk_buff *skbn;
+ /*
+ * Reject malformed packets early. Check that it contains at least 2
+ * addresses and 1 byte more for Time-To-Live
+ */
+ if (skb->len < 2 * sizeof(ax25_address) + 1)
+ return 0;
nr_src = (ax25_address *)(skb->data + 0);
nr_dest = (ax25_address *)(skb->data + 7);
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 886c0dd47b66..c131e5ceea37 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -538,10 +538,8 @@ static void *packet_current_frame(struct packet_sock *po,
return packet_lookup_frame(po, rb, rb->head, status);
}
-static u16 vlan_get_tci(struct sk_buff *skb, struct net_device *dev)
+static u16 vlan_get_tci(const struct sk_buff *skb, struct net_device *dev)
{
- u8 *skb_orig_data = skb->data;
- int skb_orig_len = skb->len;
struct vlan_hdr vhdr, *vh;
unsigned int header_len;
@@ -562,33 +560,21 @@ static u16 vlan_get_tci(struct sk_buff *skb, struct net_device *dev)
else
return 0;
- skb_push(skb, skb->data - skb_mac_header(skb));
- vh = skb_header_pointer(skb, header_len, sizeof(vhdr), &vhdr);
- if (skb_orig_data != skb->data) {
- skb->data = skb_orig_data;
- skb->len = skb_orig_len;
- }
+ vh = skb_header_pointer(skb, skb_mac_offset(skb) + header_len,
+ sizeof(vhdr), &vhdr);
if (unlikely(!vh))
return 0;
return ntohs(vh->h_vlan_TCI);
}
-static __be16 vlan_get_protocol_dgram(struct sk_buff *skb)
+static __be16 vlan_get_protocol_dgram(const struct sk_buff *skb)
{
__be16 proto = skb->protocol;
- if (unlikely(eth_type_vlan(proto))) {
- u8 *skb_orig_data = skb->data;
- int skb_orig_len = skb->len;
-
- skb_push(skb, skb->data - skb_mac_header(skb));
- proto = __vlan_get_protocol(skb, proto, NULL);
- if (skb_orig_data != skb->data) {
- skb->data = skb_orig_data;
- skb->len = skb_orig_len;
- }
- }
+ if (unlikely(eth_type_vlan(proto)))
+ proto = __vlan_get_protocol_offset(skb, proto,
+ skb_mac_offset(skb), NULL);
return proto;
}
@@ -3126,7 +3112,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
skb->protocol = proto;
skb->dev = dev;
- skb->priority = READ_ONCE(sk->sk_priority);
+ skb->priority = sockc.priority;
skb->mark = sockc.mark;
skb_set_delivery_type_by_clockid(skb, sockc.transmit_time, sk->sk_clockid);
diff --git a/net/psample/psample.c b/net/psample/psample.c
index a0ddae8a65f9..25f92ba0840c 100644
--- a/net/psample/psample.c
+++ b/net/psample/psample.c
@@ -393,7 +393,9 @@ void psample_sample_packet(struct psample_group *group,
nla_total_size_64bit(sizeof(u64)) + /* timestamp */
nla_total_size(sizeof(u16)) + /* protocol */
(md->user_cookie_len ?
- nla_total_size(md->user_cookie_len) : 0); /* user cookie */
+ nla_total_size(md->user_cookie_len) : 0) + /* user cookie */
+ (md->rate_as_probability ?
+ nla_total_size(0) : 0); /* rate as probability */
#ifdef CONFIG_INET
tun_info = skb_tunnel_info(skb);
@@ -498,8 +500,9 @@ void psample_sample_packet(struct psample_group *group,
md->user_cookie))
goto error;
- if (md->rate_as_probability)
- nla_put_flag(nl_skb, PSAMPLE_ATTR_SAMPLE_PROBABILITY);
+ if (md->rate_as_probability &&
+ nla_put_flag(nl_skb, PSAMPLE_ATTR_SAMPLE_PROBABILITY))
+ goto error;
genlmsg_end(nl_skb, data);
genlmsg_multicast_netns(&psample_nl_family, group->net, nl_skb, 0,
diff --git a/net/rds/tcp.c b/net/rds/tcp.c
index 351ac1747224..0581c53e6517 100644
--- a/net/rds/tcp.c
+++ b/net/rds/tcp.c
@@ -61,8 +61,10 @@ static atomic_t rds_tcp_unloading = ATOMIC_INIT(0);
static struct kmem_cache *rds_tcp_conn_slab;
-static int rds_tcp_skbuf_handler(const struct ctl_table *ctl, int write,
- void *buffer, size_t *lenp, loff_t *fpos);
+static int rds_tcp_sndbuf_handler(const struct ctl_table *ctl, int write,
+ void *buffer, size_t *lenp, loff_t *fpos);
+static int rds_tcp_rcvbuf_handler(const struct ctl_table *ctl, int write,
+ void *buffer, size_t *lenp, loff_t *fpos);
static int rds_tcp_min_sndbuf = SOCK_MIN_SNDBUF;
static int rds_tcp_min_rcvbuf = SOCK_MIN_RCVBUF;
@@ -74,7 +76,7 @@ static struct ctl_table rds_tcp_sysctl_table[] = {
/* data is per-net pointer */
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = rds_tcp_skbuf_handler,
+ .proc_handler = rds_tcp_sndbuf_handler,
.extra1 = &rds_tcp_min_sndbuf,
},
#define RDS_TCP_RCVBUF 1
@@ -83,7 +85,7 @@ static struct ctl_table rds_tcp_sysctl_table[] = {
/* data is per-net pointer */
.maxlen = sizeof(int),
.mode = 0644,
- .proc_handler = rds_tcp_skbuf_handler,
+ .proc_handler = rds_tcp_rcvbuf_handler,
.extra1 = &rds_tcp_min_rcvbuf,
},
};
@@ -682,10 +684,10 @@ static void rds_tcp_sysctl_reset(struct net *net)
spin_unlock_irq(&rds_tcp_conn_lock);
}
-static int rds_tcp_skbuf_handler(const struct ctl_table *ctl, int write,
+static int rds_tcp_skbuf_handler(struct rds_tcp_net *rtn,
+ const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *fpos)
{
- struct net *net = current->nsproxy->net_ns;
int err;
err = proc_dointvec_minmax(ctl, write, buffer, lenp, fpos);
@@ -694,11 +696,34 @@ static int rds_tcp_skbuf_handler(const struct ctl_table *ctl, int write,
*(int *)(ctl->extra1));
return err;
}
- if (write)
+
+ if (write && rtn->rds_tcp_listen_sock && rtn->rds_tcp_listen_sock->sk) {
+ struct net *net = sock_net(rtn->rds_tcp_listen_sock->sk);
+
rds_tcp_sysctl_reset(net);
+ }
+
return 0;
}
+static int rds_tcp_sndbuf_handler(const struct ctl_table *ctl, int write,
+ void *buffer, size_t *lenp, loff_t *fpos)
+{
+ struct rds_tcp_net *rtn = container_of(ctl->data, struct rds_tcp_net,
+ sndbuf_size);
+
+ return rds_tcp_skbuf_handler(rtn, ctl, write, buffer, lenp, fpos);
+}
+
+static int rds_tcp_rcvbuf_handler(const struct ctl_table *ctl, int write,
+ void *buffer, size_t *lenp, loff_t *fpos)
+{
+ struct rds_tcp_net *rtn = container_of(ctl->data, struct rds_tcp_net,
+ rcvbuf_size);
+
+ return rds_tcp_skbuf_handler(rtn, ctl, write, buffer, lenp, fpos);
+}
+
static void rds_tcp_exit(void)
{
rds_tcp_set_unloading();
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index a8e21060112f..9fa019e0dcad 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -203,7 +203,7 @@ MODULE_DEVICE_TABLE(of, rfkill_of_match);
static struct platform_driver rfkill_gpio_driver = {
.probe = rfkill_gpio_probe,
- .remove_new = rfkill_gpio_remove,
+ .remove = rfkill_gpio_remove,
.driver = {
.name = "rfkill_gpio",
.acpi_match_table = ACPI_PTR(rfkill_acpi_match),
diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile
index ac5caf5a48e1..210b75e3179e 100644
--- a/net/rxrpc/Makefile
+++ b/net/rxrpc/Makefile
@@ -16,6 +16,7 @@ rxrpc-y := \
conn_object.o \
conn_service.o \
input.o \
+ input_rack.o \
insecure.o \
io_thread.o \
key.o \
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c
index 9d8bd0b37e41..86873399f7d5 100644
--- a/net/rxrpc/af_rxrpc.c
+++ b/net/rxrpc/af_rxrpc.c
@@ -408,9 +408,9 @@ void rxrpc_kernel_shutdown_call(struct socket *sock, struct rxrpc_call *call)
/* Make sure we're not going to call back into a kernel service */
if (call->notify_rx) {
- spin_lock(&call->notify_lock);
+ spin_lock_irq(&call->notify_lock);
call->notify_rx = rxrpc_dummy_notify_rx;
- spin_unlock(&call->notify_lock);
+ spin_unlock_irq(&call->notify_lock);
}
}
mutex_unlock(&call->user_mutex);
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h
index d0fd37bdcfe9..718193df9d2e 100644
--- a/net/rxrpc/ar-internal.h
+++ b/net/rxrpc/ar-internal.h
@@ -30,6 +30,7 @@ struct rxrpc_crypt {
struct key_preparsed_payload;
struct rxrpc_connection;
struct rxrpc_txbuf;
+struct rxrpc_txqueue;
/*
* Mark applied to socket buffers in skb->mark. skb->priority is used
@@ -98,6 +99,7 @@ struct rxrpc_net {
atomic_t stat_tx_data_send;
atomic_t stat_tx_data_send_frag;
atomic_t stat_tx_data_send_fail;
+ atomic_t stat_tx_data_send_msgsize;
atomic_t stat_tx_data_underflow;
atomic_t stat_tx_data_cwnd_reset;
atomic_t stat_rx_data;
@@ -109,6 +111,8 @@ struct rxrpc_net {
atomic_t stat_tx_ack_skip;
atomic_t stat_tx_acks[256];
atomic_t stat_rx_acks[256];
+ atomic_t stat_tx_jumbo[10];
+ atomic_t stat_rx_jumbo[10];
atomic_t stat_why_req_ack[8];
@@ -210,9 +214,8 @@ struct rxrpc_skb_priv {
rxrpc_seq_t first_ack; /* First packet in acks table */
rxrpc_seq_t prev_ack; /* Highest seq seen */
rxrpc_serial_t acked_serial; /* Packet in response to (or 0) */
+ u16 nr_acks; /* Number of acks+nacks */
u8 reason; /* Reason for ack */
- u8 nr_acks; /* Number of acks+nacks */
- u8 nr_nacks; /* Number of nacks */
} ack;
};
struct rxrpc_host_header hdr; /* RxRPC packet header from this packet */
@@ -320,6 +323,12 @@ struct rxrpc_local {
struct list_head new_client_calls; /* Newly created client calls need connection */
spinlock_t client_call_lock; /* Lock for ->new_client_calls */
struct sockaddr_rxrpc srx; /* local address */
+ /* Provide a kvec table sufficiently large to manage either a DATA
+ * packet with a maximum set of jumbo subpackets or a PING ACK padded
+ * out to 64K with zeropages for PMTUD.
+ */
+ struct kvec kvec[RXRPC_MAX_NR_JUMBO > 3 + 16 ?
+ RXRPC_MAX_NR_JUMBO : 3 + 16];
};
/*
@@ -338,25 +347,28 @@ struct rxrpc_peer {
time64_t last_tx_at; /* Last time packet sent here */
seqlock_t service_conn_lock;
spinlock_t lock; /* access lock */
- unsigned int if_mtu; /* interface MTU for this peer */
- unsigned int mtu; /* network MTU for this peer */
- unsigned int maxdata; /* data size (MTU - hdrsize) */
- unsigned short hdrsize; /* header size (IP + UDP + RxRPC) */
int debug_id; /* debug ID for printks */
struct sockaddr_rxrpc srx; /* remote address */
- /* calculated RTT cache */
-#define RXRPC_RTT_CACHE_SIZE 32
- spinlock_t rtt_input_lock; /* RTT lock for input routine */
- ktime_t rtt_last_req; /* Time of last RTT request */
- unsigned int rtt_count; /* Number of samples we've got */
+ /* Path MTU discovery [RFC8899] */
+ unsigned int pmtud_trial; /* Current MTU probe size */
+ unsigned int pmtud_good; /* Largest working MTU probe we've tried */
+ unsigned int pmtud_bad; /* Smallest non-working MTU probe we've tried */
+ bool pmtud_lost; /* T if MTU probe was lost */
+ bool pmtud_probing; /* T if we have an active probe outstanding */
+ bool pmtud_pending; /* T if a call to this peer should send a probe */
+ u8 pmtud_jumbo; /* Max jumbo packets for the MTU */
+ bool ackr_adv_pmtud; /* T if the peer advertises path-MTU */
+ unsigned int ackr_max_data; /* Maximum data advertised by peer */
+ seqcount_t mtu_lock; /* Lockless MTU access management */
+ unsigned int if_mtu; /* Local interface MTU (- hdrsize) for this peer */
+ unsigned int max_data; /* Maximum packet data capacity for this peer */
+ unsigned short hdrsize; /* header size (IP + UDP + RxRPC) */
+ unsigned short tx_seg_max; /* Maximum number of transmissable segments */
- u32 srtt_us; /* smoothed round trip time << 3 in usecs */
- u32 mdev_us; /* medium deviation */
- u32 mdev_max_us; /* maximal mdev for the last rtt period */
- u32 rttvar_us; /* smoothed mdev_max */
- u32 rto_us; /* Retransmission timeout in usec */
- u8 backoff; /* Backoff timeout (as shift) */
+ /* Calculated RTT cache */
+ unsigned int recent_srtt_us;
+ unsigned int recent_rto_us;
u8 cong_ssthresh; /* Congestion slow-start threshold */
};
@@ -525,6 +537,8 @@ struct rxrpc_connection {
int debug_id; /* debug ID for printks */
rxrpc_serial_t tx_serial; /* Outgoing packet serial number counter */
unsigned int hi_serial; /* highest serial number received */
+ rxrpc_serial_t pmtud_probe; /* Serial of MTU probe (or 0) */
+ unsigned int pmtud_call; /* ID of call used for probe */
u32 service_id; /* Service ID, possibly upgraded */
u32 security_level; /* Security level selected */
u8 security_ix; /* security type */
@@ -557,6 +571,7 @@ enum rxrpc_call_flag {
RXRPC_CALL_RX_LAST, /* Received the last packet (at rxtx_top) */
RXRPC_CALL_TX_LAST, /* Last packet in Tx buffer (at rxtx_top) */
RXRPC_CALL_TX_ALL_ACKED, /* Last packet has been hard-acked */
+ RXRPC_CALL_TX_NO_MORE, /* No more data to transmit (MSG_MORE deasserted) */
RXRPC_CALL_SEND_PING, /* A ping will need to be sent */
RXRPC_CALL_RETRANS_TIMEOUT, /* Retransmission due to timeout occurred */
RXRPC_CALL_BEGAN_RX_TIMER, /* We began the expect_rx_by timer */
@@ -599,13 +614,25 @@ enum rxrpc_call_state {
/*
* Call Tx congestion management modes.
*/
-enum rxrpc_congest_mode {
- RXRPC_CALL_SLOW_START,
- RXRPC_CALL_CONGEST_AVOIDANCE,
- RXRPC_CALL_PACKET_LOSS,
- RXRPC_CALL_FAST_RETRANSMIT,
- NR__RXRPC_CONGEST_MODES
-};
+enum rxrpc_ca_state {
+ RXRPC_CA_SLOW_START,
+ RXRPC_CA_CONGEST_AVOIDANCE,
+ RXRPC_CA_PACKET_LOSS,
+ RXRPC_CA_FAST_RETRANSMIT,
+ NR__RXRPC_CA_STATES
+} __mode(byte);
+
+/*
+ * Current purpose of call RACK timer. According to the RACK-TLP protocol
+ * [RFC8985], the transmission timer (call->rack_timo_at) may only be used for
+ * one of these at once.
+ */
+enum rxrpc_rack_timer_mode {
+ RXRPC_CALL_RACKTIMER_OFF, /* Timer not running */
+ RXRPC_CALL_RACKTIMER_RACK_REORDER, /* RACK reordering timer */
+ RXRPC_CALL_RACKTIMER_TLP_PTO, /* TLP timeout */
+ RXRPC_CALL_RACKTIMER_RTO, /* Retransmission timeout */
+} __mode(byte);
/*
* RxRPC call definition
@@ -624,8 +651,7 @@ struct rxrpc_call {
struct mutex user_mutex; /* User access mutex */
struct sockaddr_rxrpc dest_srx; /* Destination address */
ktime_t delay_ack_at; /* When DELAY ACK needs to happen */
- ktime_t ack_lost_at; /* When ACK is figured as lost */
- ktime_t resend_at; /* When next resend needs to happen */
+ ktime_t rack_timo_at; /* When ACK is figured as lost */
ktime_t ping_at; /* When next to send a ping */
ktime_t keepalive_at; /* When next to send a keepalive ping */
ktime_t expect_rx_by; /* When we expect to get a packet by */
@@ -670,21 +696,30 @@ struct rxrpc_call {
unsigned short rx_pkt_offset; /* Current recvmsg packet offset */
unsigned short rx_pkt_len; /* Current recvmsg packet len */
+ /* Sendmsg data tracking. */
+ rxrpc_seq_t send_top; /* Highest Tx slot filled by sendmsg. */
+ struct rxrpc_txqueue *send_queue; /* Queue that sendmsg is writing into */
+
/* Transmitted data tracking. */
- spinlock_t tx_lock; /* Transmit queue lock */
- struct list_head tx_sendmsg; /* Sendmsg prepared packets */
- struct list_head tx_buffer; /* Buffer of transmissible packets */
+ struct rxrpc_txqueue *tx_queue; /* Start of transmission buffers */
+ struct rxrpc_txqueue *tx_qtail; /* End of transmission buffers */
+ rxrpc_seq_t tx_qbase; /* First slot in tx_queue */
rxrpc_seq_t tx_bottom; /* First packet in buffer */
rxrpc_seq_t tx_transmitted; /* Highest packet transmitted */
- rxrpc_seq_t tx_prepared; /* Highest Tx slot prepared. */
rxrpc_seq_t tx_top; /* Highest Tx slot allocated. */
+ rxrpc_serial_t tx_last_serial; /* Serial of last DATA transmitted */
u16 tx_backoff; /* Delay to insert due to Tx failure (ms) */
- u8 tx_winsize; /* Maximum size of Tx window */
+ u16 tx_nr_sent; /* Number of packets sent, but unacked */
+ u16 tx_nr_lost; /* Number of packets marked lost */
+ u16 tx_nr_resent; /* Number of packets resent, but unacked */
+ u16 tx_winsize; /* Maximum size of Tx window */
#define RXRPC_TX_MAX_WINDOW 128
+ u8 tx_jumbo_max; /* Maximum subpkts peer will accept */
ktime_t tx_last_sent; /* Last time a transmission occurred */
/* Received data tracking */
struct sk_buff_head recvmsg_queue; /* Queue of packets ready for recvmsg() */
+ struct sk_buff_head rx_queue; /* Queue of packets for this call to receive */
struct sk_buff_head rx_oos_queue; /* Queue of out of sequence packets */
rxrpc_seq_t rx_highest_seq; /* Higest sequence number received */
@@ -698,14 +733,32 @@ struct rxrpc_call {
*/
#define RXRPC_TX_SMSS RXRPC_JUMBO_DATALEN
#define RXRPC_MIN_CWND 4
- u8 cong_cwnd; /* Congestion window size */
+ enum rxrpc_ca_state cong_ca_state; /* Congestion control state */
u8 cong_extra; /* Extra to send for congestion management */
- u8 cong_ssthresh; /* Slow-start threshold */
- enum rxrpc_congest_mode cong_mode:8; /* Congestion management mode */
- u8 cong_dup_acks; /* Count of ACKs showing missing packets */
- u8 cong_cumul_acks; /* Cumulative ACK count */
+ u16 cong_cwnd; /* Congestion window size */
+ u16 cong_ssthresh; /* Slow-start threshold */
+ u16 cong_dup_acks; /* Count of ACKs showing missing packets */
+ u16 cong_cumul_acks; /* Cumulative ACK count */
ktime_t cong_tstamp; /* Last time cwnd was changed */
- struct sk_buff *cong_last_nack; /* Last ACK with nacks received */
+
+ /* RACK-TLP [RFC8985] state. */
+ ktime_t rack_xmit_ts; /* Latest transmission timestamp */
+ ktime_t rack_rtt; /* RTT of most recently ACK'd segment */
+ ktime_t rack_rtt_ts; /* Timestamp of rack_rtt */
+ ktime_t rack_reo_wnd; /* Reordering window */
+ unsigned int rack_reo_wnd_mult; /* Multiplier applied to rack_reo_wnd */
+ int rack_reo_wnd_persist; /* Num loss recoveries before reset reo_wnd */
+ rxrpc_seq_t rack_fack; /* Highest sequence so far ACK'd */
+ rxrpc_seq_t rack_end_seq; /* Highest sequence seen */
+ rxrpc_seq_t rack_dsack_round; /* DSACK opt recv'd in latest roundtrip */
+ bool rack_dsack_round_none; /* T if dsack_round is "None" */
+ bool rack_reordering_seen; /* T if detected reordering event */
+ enum rxrpc_rack_timer_mode rack_timer_mode; /* Current mode of RACK timer */
+ bool tlp_is_retrans; /* T if unacked TLP retransmission */
+ rxrpc_serial_t tlp_serial; /* Serial of TLP probe (or 0 if none in progress) */
+ rxrpc_seq_t tlp_seq; /* Sequence of TLP probe */
+ unsigned int tlp_rtt_taken; /* Last time RTT taken */
+ ktime_t tlp_max_ack_delay; /* Sender budget for max delayed ACK interval */
/* Receive-phase ACK management (ACKs we send). */
u8 ackr_reason; /* reason to ACK */
@@ -730,32 +783,45 @@ struct rxrpc_call {
/* Transmission-phase ACK management (ACKs we've received). */
ktime_t acks_latest_ts; /* Timestamp of latest ACK received */
- rxrpc_seq_t acks_first_seq; /* first sequence number received */
+ rxrpc_seq_t acks_hard_ack; /* Highest sequence hard acked */
rxrpc_seq_t acks_prev_seq; /* Highest previousPacket received */
- rxrpc_seq_t acks_hard_ack; /* Latest hard-ack point */
rxrpc_seq_t acks_lowest_nak; /* Lowest NACK in the buffer (or ==tx_hard_ack) */
rxrpc_serial_t acks_highest_serial; /* Highest serial number ACK'd */
+ unsigned short acks_nr_sacks; /* Number of soft acks recorded */
+ unsigned short acks_nr_snacks; /* Number of soft nacks recorded */
+
+ /* Calculated RTT cache */
+ ktime_t rtt_last_req; /* Time of last RTT request */
+ unsigned int rtt_count; /* Number of samples we've got */
+ unsigned int rtt_taken; /* Number of samples taken (wrapping) */
+ struct minmax min_rtt; /* Estimated minimum RTT */
+ u32 srtt_us; /* smoothed round trip time << 3 in usecs */
+ u32 mdev_us; /* medium deviation */
+ u32 mdev_max_us; /* maximal mdev for the last rtt period */
+ u32 rttvar_us; /* smoothed mdev_max */
+ u32 rto_us; /* Retransmission timeout in usec */
+ u8 backoff; /* Backoff timeout (as shift) */
};
/*
* Summary of a new ACK and the changes it made to the Tx buffer packet states.
*/
struct rxrpc_ack_summary {
- u16 nr_acks; /* Number of ACKs in packet */
- u16 nr_new_acks; /* Number of new ACKs in packet */
- u16 nr_new_nacks; /* Number of new nacks in packet */
- u16 nr_retained_nacks; /* Number of nacks retained between ACKs */
- u8 ack_reason;
- bool saw_nacks; /* Saw NACKs in packet */
- bool new_low_nack; /* T if new low NACK found */
- bool retrans_timeo; /* T if reTx due to timeout happened */
- u8 flight_size; /* Number of unreceived transmissions */
- /* Place to stash values for tracing */
- enum rxrpc_congest_mode mode:8;
- u8 cwnd;
- u8 ssthresh;
- u8 dup_acks;
- u8 cumulative_acks;
+ rxrpc_serial_t ack_serial; /* Serial number of ACK */
+ rxrpc_serial_t acked_serial; /* Serial number ACK'd */
+ u16 in_flight; /* Number of unreceived transmissions */
+ u16 nr_new_hacks; /* Number of rotated new ACKs */
+ u16 nr_new_sacks; /* Number of new soft ACKs in packet */
+ u16 nr_new_snacks; /* Number of new soft nacks in packet */
+ u8 ack_reason;
+ bool new_low_snack:1; /* T if new low soft NACK found */
+ bool retrans_timeo:1; /* T if reTx due to timeout happened */
+ bool need_retransmit:1; /* T if we need transmission */
+ bool rtt_sample_avail:1; /* T if RTT sample available */
+ bool in_fast_or_rto_recovery:1;
+ bool exiting_fast_or_rto_recovery:1;
+ bool tlp_probe_acked:1; /* T if the TLP probe seq was acked */
+ u8 /*enum rxrpc_congest_change*/ change;
};
/*
@@ -793,25 +859,23 @@ struct rxrpc_send_params {
* Buffer of data to be output as a packet.
*/
struct rxrpc_txbuf {
- struct list_head call_link; /* Link in call->tx_sendmsg/tx_buffer */
- struct list_head tx_link; /* Link in live Enc queue or Tx queue */
- ktime_t last_sent; /* Time at which last transmitted */
refcount_t ref;
rxrpc_seq_t seq; /* Sequence number of this packet */
rxrpc_serial_t serial; /* Last serial number transmitted with */
unsigned int call_debug_id;
unsigned int debug_id;
- unsigned int len; /* Amount of data in buffer */
- unsigned int space; /* Remaining data space */
- unsigned int offset; /* Offset of fill point */
+ unsigned short len; /* Amount of data in buffer */
+ unsigned short space; /* Remaining data space */
+ unsigned short offset; /* Offset of fill point */
+ unsigned short pkt_len; /* Size of packet content */
+ unsigned short alloc_size; /* Amount of bufferage allocated */
unsigned int flags;
#define RXRPC_TXBUF_WIRE_FLAGS 0xff /* The wire protocol flags */
#define RXRPC_TXBUF_RESENT 0x100 /* Set if has been resent */
__be16 cksum; /* Checksum to go in header */
- unsigned short ack_rwind; /* ACK receive window */
- u8 /*enum rxrpc_propose_ack_trace*/ ack_why; /* If ack, why */
+ bool jumboable; /* Can be non-terminal jumbo subpacket */
u8 nr_kvec; /* Amount of kvec[] used */
- struct kvec kvec[3];
+ struct kvec kvec[1];
};
static inline bool rxrpc_sending_to_server(const struct rxrpc_txbuf *txb)
@@ -824,6 +888,46 @@ static inline bool rxrpc_sending_to_client(const struct rxrpc_txbuf *txb)
return !rxrpc_sending_to_server(txb);
}
+/*
+ * Transmit queue element, including RACK [RFC8985] per-segment metadata. The
+ * transmission timestamp is in usec from the base.
+ */
+struct rxrpc_txqueue {
+ /* Start with the members we want to prefetch. */
+ struct rxrpc_txqueue *next;
+ ktime_t xmit_ts_base;
+ rxrpc_seq_t qbase;
+ u8 nr_reported_acks; /* Number of segments explicitly acked/nacked */
+ unsigned long segment_acked; /* Bit-per-buf: Set if ACK'd */
+ unsigned long segment_lost; /* Bit-per-buf: Set if declared lost */
+ unsigned long segment_retransmitted; /* Bit-per-buf: Set if retransmitted */
+ unsigned long rtt_samples; /* Bit-per-buf: Set if available for RTT */
+ unsigned long ever_retransmitted; /* Bit-per-buf: Set if ever retransmitted */
+
+ /* The arrays we want to pack into as few cache lines as possible. */
+ struct {
+#define RXRPC_NR_TXQUEUE BITS_PER_LONG
+#define RXRPC_TXQ_MASK (RXRPC_NR_TXQUEUE - 1)
+ struct rxrpc_txbuf *bufs[RXRPC_NR_TXQUEUE];
+ unsigned int segment_serial[RXRPC_NR_TXQUEUE];
+ unsigned int segment_xmit_ts[RXRPC_NR_TXQUEUE];
+ } ____cacheline_aligned;
+};
+
+/*
+ * Data transmission request.
+ */
+struct rxrpc_send_data_req {
+ ktime_t now; /* Current time */
+ struct rxrpc_txqueue *tq; /* Tx queue segment holding first DATA */
+ rxrpc_seq_t seq; /* Sequence of first data */
+ int n; /* Number of DATA packets to glue into jumbo */
+ bool retrans; /* T if this is a retransmission */
+ bool did_send; /* T if did actually send */
+ bool tlp_probe; /* T if this is a TLP probe */
+ int /* enum rxrpc_txdata_trace */ trace;
+};
+
#include <trace/events/rxrpc.h>
/*
@@ -841,6 +945,21 @@ static inline rxrpc_serial_t rxrpc_get_next_serial(struct rxrpc_connection *conn
}
/*
+ * Allocate the next serial n numbers on a connection. 0 must be skipped.
+ */
+static inline rxrpc_serial_t rxrpc_get_next_serials(struct rxrpc_connection *conn,
+ unsigned int n)
+{
+ rxrpc_serial_t serial;
+
+ serial = conn->tx_serial;
+ if (serial + n <= n)
+ serial = 1;
+ conn->tx_serial = serial + n;
+ return serial;
+}
+
+/*
* af_rxrpc.c
*/
extern atomic_t rxrpc_n_rx_skbs;
@@ -865,10 +984,10 @@ void rxrpc_propose_ping(struct rxrpc_call *call, u32 serial,
enum rxrpc_propose_ack_trace why);
void rxrpc_propose_delay_ACK(struct rxrpc_call *, rxrpc_serial_t,
enum rxrpc_propose_ack_trace);
-void rxrpc_shrink_call_tx_buffer(struct rxrpc_call *);
-void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb);
-
-bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb);
+void rxrpc_resend_tlp(struct rxrpc_call *call);
+void rxrpc_transmit_some_data(struct rxrpc_call *call, unsigned int limit,
+ enum rxrpc_txdata_trace trace);
+bool rxrpc_input_call_event(struct rxrpc_call *call);
/*
* call_object.c
@@ -1047,6 +1166,32 @@ void rxrpc_input_call_packet(struct rxrpc_call *, struct sk_buff *);
void rxrpc_implicit_end_call(struct rxrpc_call *, struct sk_buff *);
/*
+ * input_rack.c
+ */
+void rxrpc_input_rack_one(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary,
+ struct rxrpc_txqueue *tq,
+ unsigned int ix);
+void rxrpc_input_rack(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary,
+ struct rxrpc_txqueue *tq,
+ unsigned long new_acks);
+void rxrpc_rack_detect_loss_and_arm_timer(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary);
+ktime_t rxrpc_tlp_calc_pto(struct rxrpc_call *call, ktime_t now);
+void rxrpc_tlp_send_probe(struct rxrpc_call *call);
+void rxrpc_tlp_process_ack(struct rxrpc_call *call, struct rxrpc_ack_summary *summary);
+void rxrpc_rack_timer_expired(struct rxrpc_call *call, ktime_t overran_by);
+
+/* Initialise TLP state [RFC8958 7.1]. */
+static inline void rxrpc_tlp_init(struct rxrpc_call *call)
+{
+ call->tlp_serial = 0;
+ call->tlp_seq = call->acks_hard_ack;
+ call->tlp_is_retrans = false;
+}
+
+/*
* io_thread.c
*/
int rxrpc_encap_rcv(struct sock *, struct sk_buff *);
@@ -1149,17 +1294,20 @@ static inline struct rxrpc_net *rxrpc_net(struct net *net)
*/
void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason,
rxrpc_serial_t serial, enum rxrpc_propose_ack_trace why);
+void rxrpc_send_probe_for_pmtud(struct rxrpc_call *call);
int rxrpc_send_abort_packet(struct rxrpc_call *);
+void rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_send_data_req *req);
void rxrpc_send_conn_abort(struct rxrpc_connection *conn);
void rxrpc_reject_packet(struct rxrpc_local *local, struct sk_buff *skb);
void rxrpc_send_keepalive(struct rxrpc_peer *);
-void rxrpc_transmit_one(struct rxrpc_call *call, struct rxrpc_txbuf *txb);
/*
* peer_event.c
*/
void rxrpc_input_error(struct rxrpc_local *, struct sk_buff *);
void rxrpc_peer_keepalive_worker(struct work_struct *);
+void rxrpc_input_probe_for_pmtud(struct rxrpc_connection *conn, rxrpc_serial_t acked_serial,
+ bool sendmsg_fail);
/*
* peer_object.c
@@ -1208,10 +1356,12 @@ static inline int rxrpc_abort_eproto(struct rxrpc_call *call,
/*
* rtt.c
*/
-void rxrpc_peer_add_rtt(struct rxrpc_call *, enum rxrpc_rtt_rx_trace, int,
- rxrpc_serial_t, rxrpc_serial_t, ktime_t, ktime_t);
-ktime_t rxrpc_get_rto_backoff(struct rxrpc_peer *peer, bool retrans);
-void rxrpc_peer_init_rtt(struct rxrpc_peer *);
+void rxrpc_call_add_rtt(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why,
+ int rtt_slot,
+ rxrpc_serial_t send_serial, rxrpc_serial_t resp_serial,
+ ktime_t send_time, ktime_t resp_time);
+ktime_t rxrpc_get_rto_backoff(struct rxrpc_call *call, bool retrans);
+void rxrpc_call_init_rtt(struct rxrpc_call *call);
/*
* rxkad.c
@@ -1284,7 +1434,6 @@ static inline void rxrpc_sysctl_exit(void) {}
extern atomic_t rxrpc_nr_txbuf;
struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_size,
size_t data_align, gfp_t gfp);
-struct rxrpc_txbuf *rxrpc_alloc_ack_txbuf(struct rxrpc_call *call, size_t sack_size);
void rxrpc_get_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
void rxrpc_see_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
void rxrpc_put_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what);
@@ -1311,6 +1460,53 @@ static inline bool after_eq(u32 seq1, u32 seq2)
return (s32)(seq1 - seq2) >= 0;
}
+static inline u32 earliest(u32 seq1, u32 seq2)
+{
+ return before(seq1, seq2) ? seq1 : seq2;
+}
+
+static inline u32 latest(u32 seq1, u32 seq2)
+{
+ return after(seq1, seq2) ? seq1 : seq2;
+}
+
+static inline bool rxrpc_seq_in_txq(const struct rxrpc_txqueue *tq, rxrpc_seq_t seq)
+{
+ return (seq & (RXRPC_NR_TXQUEUE - 1)) == tq->qbase;
+}
+
+static inline void rxrpc_queue_rx_call_packet(struct rxrpc_call *call, struct sk_buff *skb)
+{
+ rxrpc_get_skb(skb, rxrpc_skb_get_call_rx);
+ __skb_queue_tail(&call->rx_queue, skb);
+ rxrpc_poke_call(call, rxrpc_call_poke_rx_packet);
+}
+
+/*
+ * Calculate how much space there is for transmitting more DATA packets.
+ */
+static inline unsigned int rxrpc_tx_window_space(const struct rxrpc_call *call)
+{
+ int winsize = umin(call->tx_winsize, call->cong_cwnd + call->cong_extra);
+ int transmitted = call->tx_top - call->tx_bottom;
+
+ return max(winsize - transmitted, 0);
+}
+
+static inline unsigned int rxrpc_left_out(const struct rxrpc_call *call)
+{
+ return call->acks_nr_sacks + call->tx_nr_lost;
+}
+
+/*
+ * Calculate the number of transmitted DATA packets assumed to be in flight
+ * [approx RFC6675].
+ */
+static inline unsigned int rxrpc_tx_in_flight(const struct rxrpc_call *call)
+{
+ return call->tx_nr_sent - rxrpc_left_out(call) + call->tx_nr_resent;
+}
+
/*
* debug tracing
*/
diff --git a/net/rxrpc/call_accept.c b/net/rxrpc/call_accept.c
index 0f5a1d77b890..e685034ce4f7 100644
--- a/net/rxrpc/call_accept.c
+++ b/net/rxrpc/call_accept.c
@@ -188,8 +188,8 @@ void rxrpc_discard_prealloc(struct rxrpc_sock *rx)
/* Make sure that there aren't any incoming calls in progress before we
* clear the preallocation buffers.
*/
- spin_lock(&rx->incoming_lock);
- spin_unlock(&rx->incoming_lock);
+ spin_lock_irq(&rx->incoming_lock);
+ spin_unlock_irq(&rx->incoming_lock);
head = b->peer_backlog_head;
tail = b->peer_backlog_tail;
@@ -343,7 +343,7 @@ bool rxrpc_new_incoming_call(struct rxrpc_local *local,
if (sp->hdr.type != RXRPC_PACKET_TYPE_DATA)
return rxrpc_protocol_error(skb, rxrpc_eproto_no_service_call);
- read_lock(&local->services_lock);
+ read_lock_irq(&local->services_lock);
/* Weed out packets to services we're not offering. Packets that would
* begin a call are explicitly rejected and the rest are just
@@ -399,34 +399,34 @@ bool rxrpc_new_incoming_call(struct rxrpc_local *local,
spin_unlock(&conn->state_lock);
spin_unlock(&rx->incoming_lock);
- read_unlock(&local->services_lock);
+ read_unlock_irq(&local->services_lock);
if (hlist_unhashed(&call->error_link)) {
- spin_lock(&call->peer->lock);
+ spin_lock_irq(&call->peer->lock);
hlist_add_head(&call->error_link, &call->peer->error_targets);
- spin_unlock(&call->peer->lock);
+ spin_unlock_irq(&call->peer->lock);
}
_leave(" = %p{%d}", call, call->debug_id);
- rxrpc_input_call_event(call, skb);
+ rxrpc_queue_rx_call_packet(call, skb);
rxrpc_put_call(call, rxrpc_call_put_input);
return true;
unsupported_service:
- read_unlock(&local->services_lock);
+ read_unlock_irq(&local->services_lock);
return rxrpc_direct_abort(skb, rxrpc_abort_service_not_offered,
RX_INVALID_OPERATION, -EOPNOTSUPP);
unsupported_security:
- read_unlock(&local->services_lock);
+ read_unlock_irq(&local->services_lock);
return rxrpc_direct_abort(skb, rxrpc_abort_service_not_offered,
RX_INVALID_OPERATION, -EKEYREJECTED);
no_call:
spin_unlock(&rx->incoming_lock);
- read_unlock(&local->services_lock);
+ read_unlock_irq(&local->services_lock);
_leave(" = f [%u]", skb->mark);
return false;
discard:
- read_unlock(&local->services_lock);
+ read_unlock_irq(&local->services_lock);
return true;
}
diff --git a/net/rxrpc/call_event.c b/net/rxrpc/call_event.c
index 7bbb68504766..8e477f7f8850 100644
--- a/net/rxrpc/call_event.c
+++ b/net/rxrpc/call_event.c
@@ -44,8 +44,8 @@ void rxrpc_propose_delay_ACK(struct rxrpc_call *call, rxrpc_serial_t serial,
trace_rxrpc_propose_ack(call, why, RXRPC_ACK_DELAY, serial);
- if (call->peer->srtt_us)
- delay = (call->peer->srtt_us >> 3) * NSEC_PER_USEC;
+ if (call->srtt_us)
+ delay = (call->srtt_us >> 3) * NSEC_PER_USEC;
else
delay = ms_to_ktime(READ_ONCE(rxrpc_soft_ack_delay));
ktime_add_ms(delay, call->tx_backoff);
@@ -55,147 +55,104 @@ void rxrpc_propose_delay_ACK(struct rxrpc_call *call, rxrpc_serial_t serial,
}
/*
- * Handle congestion being detected by the retransmit timeout.
+ * Retransmit one or more packets.
*/
-static void rxrpc_congestion_timeout(struct rxrpc_call *call)
+static bool rxrpc_retransmit_data(struct rxrpc_call *call,
+ struct rxrpc_send_data_req *req)
{
- set_bit(RXRPC_CALL_RETRANS_TIMEOUT, &call->flags);
+ struct rxrpc_txqueue *tq = req->tq;
+ unsigned int ix = req->seq & RXRPC_TXQ_MASK;
+ struct rxrpc_txbuf *txb = tq->bufs[ix];
+
+ _enter("%x,%x,%x,%x", tq->qbase, req->seq, ix, txb->debug_id);
+
+ req->retrans = true;
+ trace_rxrpc_retransmit(call, req, txb);
+
+ txb->flags |= RXRPC_TXBUF_RESENT;
+ rxrpc_send_data_packet(call, req);
+ rxrpc_inc_stat(call->rxnet, stat_tx_data_retrans);
+
+ req->tq = NULL;
+ req->n = 0;
+ req->did_send = true;
+ req->now = ktime_get_real();
+ return true;
}
/*
* Perform retransmission of NAK'd and unack'd packets.
*/
-void rxrpc_resend(struct rxrpc_call *call, struct sk_buff *ack_skb)
+static void rxrpc_resend(struct rxrpc_call *call)
{
- struct rxrpc_ackpacket *ack = NULL;
- struct rxrpc_skb_priv *sp;
- struct rxrpc_txbuf *txb;
- rxrpc_seq_t transmitted = call->tx_transmitted;
- ktime_t next_resend = KTIME_MAX, rto = ns_to_ktime(call->peer->rto_us * NSEC_PER_USEC);
- ktime_t resend_at = KTIME_MAX, now, delay;
- bool unacked = false, did_send = false;
- unsigned int i;
-
- _enter("{%d,%d}", call->acks_hard_ack, call->tx_top);
-
- now = ktime_get_real();
-
- if (list_empty(&call->tx_buffer))
- goto no_resend;
+ struct rxrpc_send_data_req req = {
+ .now = ktime_get_real(),
+ .trace = rxrpc_txdata_retransmit,
+ };
+ struct rxrpc_txqueue *tq;
- trace_rxrpc_resend(call, ack_skb);
- txb = list_first_entry(&call->tx_buffer, struct rxrpc_txbuf, call_link);
+ _enter("{%d,%d}", call->tx_bottom, call->tx_top);
- /* Scan the soft ACK table without dropping the lock and resend any
- * explicitly NAK'd packets.
- */
- if (ack_skb) {
- sp = rxrpc_skb(ack_skb);
- ack = (void *)ack_skb->data + sizeof(struct rxrpc_wire_header);
+ trace_rxrpc_resend(call, call->acks_highest_serial);
- for (i = 0; i < sp->ack.nr_acks; i++) {
- rxrpc_seq_t seq;
+ /* Scan the transmission queue, looking for lost packets. */
+ for (tq = call->tx_queue; tq; tq = tq->next) {
+ unsigned long lost = tq->segment_lost;
- if (ack->acks[i] & 1)
- continue;
- seq = sp->ack.first_ack + i;
- if (after(txb->seq, transmitted))
- break;
- if (after(txb->seq, seq))
- continue; /* A new hard ACK probably came in */
- list_for_each_entry_from(txb, &call->tx_buffer, call_link) {
- if (txb->seq == seq)
- goto found_txb;
- }
- goto no_further_resend;
-
- found_txb:
- resend_at = ktime_add(txb->last_sent, rto);
- if (after(txb->serial, call->acks_highest_serial)) {
- if (ktime_after(resend_at, now) &&
- ktime_before(resend_at, next_resend))
- next_resend = resend_at;
- continue; /* Ack point not yet reached */
- }
+ if (after(tq->qbase, call->tx_transmitted))
+ break;
- rxrpc_see_txbuf(txb, rxrpc_txbuf_see_unacked);
+ _debug("retr %16lx %u c=%08x [%x]",
+ tq->segment_acked, tq->nr_reported_acks, call->debug_id, tq->qbase);
+ _debug("lost %16lx", lost);
- trace_rxrpc_retransmit(call, txb->seq, txb->serial,
- ktime_sub(resend_at, now));
+ trace_rxrpc_resend_lost(call, tq, lost);
+ while (lost) {
+ unsigned int ix = __ffs(lost);
+ struct rxrpc_txbuf *txb = tq->bufs[ix];
- txb->flags |= RXRPC_TXBUF_RESENT;
- rxrpc_transmit_one(call, txb);
- did_send = true;
- now = ktime_get_real();
+ __clear_bit(ix, &lost);
+ rxrpc_see_txbuf(txb, rxrpc_txbuf_see_lost);
- if (list_is_last(&txb->call_link, &call->tx_buffer))
- goto no_further_resend;
- txb = list_next_entry(txb, call_link);
+ req.tq = tq;
+ req.seq = tq->qbase + ix;
+ req.n = 1;
+ rxrpc_retransmit_data(call, &req);
}
}
- /* Fast-forward through the Tx queue to the point the peer says it has
- * seen. Anything between the soft-ACK table and that point will get
- * ACK'd or NACK'd in due course, so don't worry about it here; here we
- * need to consider retransmitting anything beyond that point.
- */
- if (after_eq(call->acks_prev_seq, call->tx_transmitted))
- goto no_further_resend;
-
- list_for_each_entry_from(txb, &call->tx_buffer, call_link) {
- resend_at = ktime_add(txb->last_sent, rto);
-
- if (before_eq(txb->seq, call->acks_prev_seq))
- continue;
- if (after(txb->seq, call->tx_transmitted))
- break; /* Not transmitted yet */
-
- if (ack && ack->reason == RXRPC_ACK_PING_RESPONSE &&
- before(txb->serial, ntohl(ack->serial)))
- goto do_resend; /* Wasn't accounted for by a more recent ping. */
-
- if (ktime_after(resend_at, now)) {
- if (ktime_before(resend_at, next_resend))
- next_resend = resend_at;
- continue;
- }
-
- do_resend:
- unacked = true;
-
- txb->flags |= RXRPC_TXBUF_RESENT;
- rxrpc_transmit_one(call, txb);
- did_send = true;
- rxrpc_inc_stat(call->rxnet, stat_tx_data_retrans);
- now = ktime_get_real();
- }
+ rxrpc_get_rto_backoff(call, req.did_send);
+ _leave("");
+}
-no_further_resend:
-no_resend:
- if (resend_at < KTIME_MAX) {
- delay = rxrpc_get_rto_backoff(call->peer, did_send);
- resend_at = ktime_add(resend_at, delay);
- trace_rxrpc_timer_set(call, resend_at - now, rxrpc_timer_trace_resend_reset);
+/*
+ * Resend the highest-seq DATA packet so far transmitted for RACK-TLP [RFC8985 7.3].
+ */
+void rxrpc_resend_tlp(struct rxrpc_call *call)
+{
+ struct rxrpc_send_data_req req = {
+ .now = ktime_get_real(),
+ .seq = call->tx_transmitted,
+ .n = 1,
+ .tlp_probe = true,
+ .trace = rxrpc_txdata_tlp_retransmit,
+ };
+
+ /* There's a chance it'll be on the tail segment of the queue. */
+ req.tq = READ_ONCE(call->tx_qtail);
+ if (req.tq &&
+ before(call->tx_transmitted, req.tq->qbase + RXRPC_NR_TXQUEUE)) {
+ rxrpc_retransmit_data(call, &req);
+ return;
}
- call->resend_at = resend_at;
-
- if (unacked)
- rxrpc_congestion_timeout(call);
-
- /* If there was nothing that needed retransmission then it's likely
- * that an ACK got lost somewhere. Send a ping to find out instead of
- * retransmitting data.
- */
- if (!did_send) {
- ktime_t next_ping = ktime_add_us(call->acks_latest_ts,
- call->peer->srtt_us >> 3);
- if (ktime_sub(next_ping, now) <= 0)
- rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
- rxrpc_propose_ack_ping_for_0_retrans);
+ for (req.tq = call->tx_queue; req.tq; req.tq = req.tq->next) {
+ if (after_eq(call->tx_transmitted, req.tq->qbase) &&
+ before(call->tx_transmitted, req.tq->qbase + RXRPC_NR_TXQUEUE)) {
+ rxrpc_retransmit_data(call, &req);
+ return;
+ }
}
-
- _leave("");
}
/*
@@ -231,68 +188,93 @@ static void rxrpc_close_tx_phase(struct rxrpc_call *call)
}
}
-static bool rxrpc_tx_window_has_space(struct rxrpc_call *call)
-{
- unsigned int winsize = min_t(unsigned int, call->tx_winsize,
- call->cong_cwnd + call->cong_extra);
- rxrpc_seq_t window = call->acks_hard_ack, wtop = window + winsize;
- rxrpc_seq_t tx_top = call->tx_top;
- int space;
-
- space = wtop - tx_top;
- return space > 0;
-}
-
/*
- * Decant some if the sendmsg prepared queue into the transmission buffer.
+ * Transmit some as-yet untransmitted data, to a maximum of the supplied limit.
*/
-static void rxrpc_decant_prepared_tx(struct rxrpc_call *call)
+static void rxrpc_transmit_fresh_data(struct rxrpc_call *call, unsigned int limit,
+ enum rxrpc_txdata_trace trace)
{
- struct rxrpc_txbuf *txb;
+ int space = rxrpc_tx_window_space(call);
if (!test_bit(RXRPC_CALL_EXPOSED, &call->flags)) {
- if (list_empty(&call->tx_sendmsg))
+ if (call->send_top == call->tx_top)
return;
rxrpc_expose_client_call(call);
}
- while ((txb = list_first_entry_or_null(&call->tx_sendmsg,
- struct rxrpc_txbuf, call_link))) {
- spin_lock(&call->tx_lock);
- list_del(&txb->call_link);
- spin_unlock(&call->tx_lock);
+ while (space > 0) {
+ struct rxrpc_send_data_req req = {
+ .now = ktime_get_real(),
+ .seq = call->tx_transmitted + 1,
+ .n = 0,
+ .trace = trace,
+ };
+ struct rxrpc_txqueue *tq;
+ struct rxrpc_txbuf *txb;
+ rxrpc_seq_t send_top, seq;
+ int limit = min(space, max(call->peer->pmtud_jumbo, 1));
+
+ /* Order send_top before the contents of the new txbufs and
+ * txqueue pointers
+ */
+ send_top = smp_load_acquire(&call->send_top);
+ if (call->tx_top == send_top)
+ break;
- call->tx_top = txb->seq;
- list_add_tail(&txb->call_link, &call->tx_buffer);
+ trace_rxrpc_transmit(call, send_top, space);
- if (txb->flags & RXRPC_LAST_PACKET)
- rxrpc_close_tx_phase(call);
+ tq = call->tx_qtail;
+ seq = call->tx_top;
+ trace_rxrpc_tq(call, tq, seq, rxrpc_tq_decant);
- rxrpc_transmit_one(call, txb);
+ do {
+ int ix;
- if (!rxrpc_tx_window_has_space(call))
- break;
+ seq++;
+ ix = seq & RXRPC_TXQ_MASK;
+ if (!ix) {
+ tq = tq->next;
+ trace_rxrpc_tq(call, tq, seq, rxrpc_tq_decant_advance);
+ }
+ if (!req.tq)
+ req.tq = tq;
+ txb = tq->bufs[ix];
+ req.n++;
+ if (!txb->jumboable)
+ break;
+ } while (req.n < limit && before(seq, send_top));
+
+ if (txb->flags & RXRPC_LAST_PACKET) {
+ rxrpc_close_tx_phase(call);
+ tq = NULL;
+ }
+ call->tx_qtail = tq;
+ call->tx_top = seq;
+
+ space -= req.n;
+ rxrpc_send_data_packet(call, &req);
}
}
-static void rxrpc_transmit_some_data(struct rxrpc_call *call)
+void rxrpc_transmit_some_data(struct rxrpc_call *call, unsigned int limit,
+ enum rxrpc_txdata_trace trace)
{
switch (__rxrpc_call_state(call)) {
case RXRPC_CALL_SERVER_ACK_REQUEST:
- if (list_empty(&call->tx_sendmsg))
+ if (call->tx_bottom == READ_ONCE(call->send_top))
return;
rxrpc_begin_service_reply(call);
fallthrough;
case RXRPC_CALL_SERVER_SEND_REPLY:
case RXRPC_CALL_CLIENT_SEND_REQUEST:
- if (!rxrpc_tx_window_has_space(call))
+ if (!rxrpc_tx_window_space(call))
return;
- if (list_empty(&call->tx_sendmsg)) {
+ if (call->tx_bottom == READ_ONCE(call->send_top)) {
rxrpc_inc_stat(call->rxnet, stat_tx_data_underflow);
return;
}
- rxrpc_decant_prepared_tx(call);
+ rxrpc_transmit_fresh_data(call, limit, trace);
break;
default:
return;
@@ -305,8 +287,8 @@ static void rxrpc_transmit_some_data(struct rxrpc_call *call)
*/
static void rxrpc_send_initial_ping(struct rxrpc_call *call)
{
- if (call->peer->rtt_count < 3 ||
- ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000),
+ if (call->rtt_count < 3 ||
+ ktime_before(ktime_add_ms(call->rtt_last_req, 1000),
ktime_get_real()))
rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
rxrpc_propose_ack_ping_for_params);
@@ -315,10 +297,11 @@ static void rxrpc_send_initial_ping(struct rxrpc_call *call)
/*
* Handle retransmission and deferred ACK/abort generation.
*/
-bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
+bool rxrpc_input_call_event(struct rxrpc_call *call)
{
+ struct sk_buff *skb;
ktime_t now, t;
- bool resend = false;
+ bool did_receive = false, saw_ack = false;
s32 abort_code;
rxrpc_see_call(call, rxrpc_call_see_input);
@@ -328,9 +311,6 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
call->debug_id, rxrpc_call_states[__rxrpc_call_state(call)],
call->events);
- if (__rxrpc_call_is_complete(call))
- goto out;
-
/* Handle abort request locklessly, vs rxrpc_propose_abort(). */
abort_code = smp_load_acquire(&call->send_abort);
if (abort_code) {
@@ -339,11 +319,33 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
goto out;
}
- if (skb && skb->mark == RXRPC_SKB_MARK_ERROR)
- goto out;
+ do {
+ skb = __skb_dequeue(&call->rx_queue);
+ if (skb) {
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+
+ if (__rxrpc_call_is_complete(call) ||
+ skb->mark == RXRPC_SKB_MARK_ERROR) {
+ rxrpc_free_skb(skb, rxrpc_skb_put_call_rx);
+ goto out;
+ }
+
+ saw_ack |= sp->hdr.type == RXRPC_PACKET_TYPE_ACK;
+
+ rxrpc_input_call_packet(call, skb);
+ rxrpc_free_skb(skb, rxrpc_skb_put_call_rx);
+ did_receive = true;
+ }
- if (skb)
- rxrpc_input_call_packet(call, skb);
+ t = ktime_sub(call->rack_timo_at, ktime_get_real());
+ if (t <= 0) {
+ trace_rxrpc_timer_exp(call, t,
+ rxrpc_timer_trace_rack_off + call->rack_timer_mode);
+ call->rack_timo_at = KTIME_MAX;
+ rxrpc_rack_timer_expired(call, t);
+ }
+
+ } while (!skb_queue_empty(&call->rx_queue));
/* If we see our async-event poke, check for timeout trippage. */
now = ktime_get_real();
@@ -376,13 +378,6 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
rxrpc_propose_ack_delayed_ack);
}
- t = ktime_sub(call->ack_lost_at, now);
- if (t <= 0) {
- trace_rxrpc_timer_exp(call, t, rxrpc_timer_trace_lost_ack);
- call->ack_lost_at = KTIME_MAX;
- set_bit(RXRPC_CALL_EV_ACK_LOST, &call->events);
- }
-
t = ktime_sub(call->ping_at, now);
if (t <= 0) {
trace_rxrpc_timer_exp(call, t, rxrpc_timer_trace_ping);
@@ -391,15 +386,6 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
rxrpc_propose_ack_ping_for_keepalive);
}
- t = ktime_sub(call->resend_at, now);
- if (t <= 0) {
- trace_rxrpc_timer_exp(call, t, rxrpc_timer_trace_resend);
- call->resend_at = KTIME_MAX;
- resend = true;
- }
-
- rxrpc_transmit_some_data(call);
-
now = ktime_get_real();
t = ktime_sub(call->keepalive_at, now);
if (t <= 0) {
@@ -409,35 +395,40 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
rxrpc_propose_ack_ping_for_keepalive);
}
- if (skb) {
- struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
-
- if (sp->hdr.type == RXRPC_PACKET_TYPE_ACK)
- rxrpc_congestion_degrade(call);
- }
-
if (test_and_clear_bit(RXRPC_CALL_EV_INITIAL_PING, &call->events))
rxrpc_send_initial_ping(call);
+ rxrpc_transmit_some_data(call, UINT_MAX, rxrpc_txdata_new_data);
+
+ if (saw_ack)
+ rxrpc_congestion_degrade(call);
+
+ if (did_receive &&
+ (__rxrpc_call_state(call) == RXRPC_CALL_CLIENT_SEND_REQUEST ||
+ __rxrpc_call_state(call) == RXRPC_CALL_SERVER_SEND_REPLY)) {
+ t = ktime_sub(call->rack_timo_at, ktime_get_real());
+ trace_rxrpc_rack(call, t);
+ }
+
/* Process events */
if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events))
rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
rxrpc_propose_ack_ping_for_lost_ack);
- if (resend &&
+ if (call->tx_nr_lost > 0 &&
__rxrpc_call_state(call) != RXRPC_CALL_CLIENT_RECV_REPLY &&
!test_bit(RXRPC_CALL_TX_ALL_ACKED, &call->flags))
- rxrpc_resend(call, NULL);
+ rxrpc_resend(call);
if (test_and_clear_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags))
rxrpc_send_ACK(call, RXRPC_ACK_IDLE, 0,
rxrpc_propose_ack_rx_idle);
if (call->ackr_nr_unacked > 2) {
- if (call->peer->rtt_count < 3)
+ if (call->rtt_count < 3)
rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
rxrpc_propose_ack_ping_for_rtt);
- else if (ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000),
+ else if (ktime_before(ktime_add_ms(call->rtt_last_req, 1000),
ktime_get_real()))
rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
rxrpc_propose_ack_ping_for_old_rtt);
@@ -455,8 +446,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
set(call->expect_req_by);
set(call->expect_rx_by);
set(call->delay_ack_at);
- set(call->ack_lost_at);
- set(call->resend_at);
+ set(call->rack_timo_at);
set(call->keepalive_at);
set(call->ping_at);
@@ -467,7 +457,7 @@ bool rxrpc_input_call_event(struct rxrpc_call *call, struct sk_buff *skb)
} else {
unsigned long nowj = jiffies, delayj, nextj;
- delayj = max(nsecs_to_jiffies(delay), 1);
+ delayj = umax(nsecs_to_jiffies(delay), 1);
nextj = nowj + delayj;
if (time_before(nextj, call->timer.expires) ||
!timer_pending(&call->timer)) {
@@ -484,9 +474,12 @@ out:
rxrpc_disconnect_call(call);
if (call->security)
call->security->free_call_crypto(call);
+ } else {
+ if (did_receive &&
+ call->peer->ackr_adv_pmtud &&
+ call->peer->pmtud_pending)
+ rxrpc_send_probe_for_pmtud(call);
}
- if (call->acks_hard_ack != call->tx_bottom)
- rxrpc_shrink_call_tx_buffer(call);
_leave("");
return true;
diff --git a/net/rxrpc/call_object.c b/net/rxrpc/call_object.c
index f9e983a12c14..5a543c3f6fb0 100644
--- a/net/rxrpc/call_object.c
+++ b/net/rxrpc/call_object.c
@@ -49,7 +49,7 @@ void rxrpc_poke_call(struct rxrpc_call *call, enum rxrpc_call_poke_trace what)
bool busy;
if (!test_bit(RXRPC_CALL_DISCONNECTED, &call->flags)) {
- spin_lock_bh(&local->lock);
+ spin_lock_irq(&local->lock);
busy = !list_empty(&call->attend_link);
trace_rxrpc_poke_call(call, busy, what);
if (!busy && !rxrpc_try_get_call(call, rxrpc_call_get_poke))
@@ -57,7 +57,7 @@ void rxrpc_poke_call(struct rxrpc_call *call, enum rxrpc_call_poke_trace what)
if (!busy) {
list_add_tail(&call->attend_link, &local->call_attend_q);
}
- spin_unlock_bh(&local->lock);
+ spin_unlock_irq(&local->lock);
if (!busy)
rxrpc_wake_up_io_thread(local);
}
@@ -146,23 +146,21 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp,
INIT_LIST_HEAD(&call->recvmsg_link);
INIT_LIST_HEAD(&call->sock_link);
INIT_LIST_HEAD(&call->attend_link);
- INIT_LIST_HEAD(&call->tx_sendmsg);
- INIT_LIST_HEAD(&call->tx_buffer);
+ skb_queue_head_init(&call->rx_queue);
skb_queue_head_init(&call->recvmsg_queue);
skb_queue_head_init(&call->rx_oos_queue);
init_waitqueue_head(&call->waitq);
spin_lock_init(&call->notify_lock);
- spin_lock_init(&call->tx_lock);
refcount_set(&call->ref, 1);
call->debug_id = debug_id;
call->tx_total_len = -1;
+ call->tx_jumbo_max = 1;
call->next_rx_timo = 20 * HZ;
call->next_req_timo = 1 * HZ;
call->ackr_window = 1;
call->ackr_wtop = 1;
call->delay_ack_at = KTIME_MAX;
- call->ack_lost_at = KTIME_MAX;
- call->resend_at = KTIME_MAX;
+ call->rack_timo_at = KTIME_MAX;
call->ping_at = KTIME_MAX;
call->keepalive_at = KTIME_MAX;
call->expect_rx_by = KTIME_MAX;
@@ -177,6 +175,8 @@ struct rxrpc_call *rxrpc_alloc_call(struct rxrpc_sock *rx, gfp_t gfp,
call->cong_cwnd = RXRPC_MIN_CWND;
call->cong_ssthresh = RXRPC_TX_MAX_WINDOW;
+ rxrpc_call_init_rtt(call);
+
call->rxnet = rxnet;
call->rtt_avail = RXRPC_CALL_RTT_AVAIL_MASK;
atomic_inc(&rxnet->nr_calls);
@@ -220,9 +220,9 @@ static struct rxrpc_call *rxrpc_alloc_client_call(struct rxrpc_sock *rx,
__set_bit(RXRPC_CALL_EXCLUSIVE, &call->flags);
if (p->timeouts.normal)
- call->next_rx_timo = min(p->timeouts.normal, 1);
+ call->next_rx_timo = umin(p->timeouts.normal, 1);
if (p->timeouts.idle)
- call->next_req_timo = min(p->timeouts.idle, 1);
+ call->next_req_timo = umin(p->timeouts.idle, 1);
if (p->timeouts.hard)
call->hard_timo = p->timeouts.hard;
@@ -302,9 +302,9 @@ static int rxrpc_connect_call(struct rxrpc_call *call, gfp_t gfp)
trace_rxrpc_client(NULL, -1, rxrpc_client_queue_new_call);
rxrpc_get_call(call, rxrpc_call_get_io_thread);
- spin_lock(&local->client_call_lock);
+ spin_lock_irq(&local->client_call_lock);
list_add_tail(&call->wait_link, &local->new_client_calls);
- spin_unlock(&local->client_call_lock);
+ spin_unlock_irq(&local->client_call_lock);
rxrpc_wake_up_io_thread(local);
return 0;
@@ -434,7 +434,7 @@ error_attached_to_socket:
/*
* Set up an incoming call. call->conn points to the connection.
- * This is called in BH context and isn't allowed to fail.
+ * This is called with interrupts disabled and isn't allowed to fail.
*/
void rxrpc_incoming_call(struct rxrpc_sock *rx,
struct rxrpc_call *call,
@@ -531,11 +531,29 @@ void rxrpc_get_call(struct rxrpc_call *call, enum rxrpc_call_trace why)
}
/*
- * Clean up the Rx skb ring.
+ * Clean up the transmission buffers.
+ */
+static void rxrpc_cleanup_tx_buffers(struct rxrpc_call *call)
+{
+ struct rxrpc_txqueue *tq, *next;
+
+ for (tq = call->tx_queue; tq; tq = next) {
+ next = tq->next;
+ for (int i = 0; i < RXRPC_NR_TXQUEUE; i++)
+ if (tq->bufs[i])
+ rxrpc_put_txbuf(tq->bufs[i], rxrpc_txbuf_put_cleaned);
+ trace_rxrpc_tq(call, tq, 0, rxrpc_tq_cleaned);
+ kfree(tq);
+ }
+}
+
+/*
+ * Clean up the receive buffers.
*/
-static void rxrpc_cleanup_ring(struct rxrpc_call *call)
+static void rxrpc_cleanup_rx_buffers(struct rxrpc_call *call)
{
rxrpc_purge_queue(&call->recvmsg_queue);
+ rxrpc_purge_queue(&call->rx_queue);
rxrpc_purge_queue(&call->rx_oos_queue);
}
@@ -558,7 +576,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
rxrpc_put_call_slot(call);
/* Make sure we don't get any more notifications */
- spin_lock(&rx->recvmsg_lock);
+ spin_lock_irq(&rx->recvmsg_lock);
if (!list_empty(&call->recvmsg_link)) {
_debug("unlinking once-pending call %p { e=%lx f=%lx }",
@@ -571,7 +589,7 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
call->recvmsg_link.next = NULL;
call->recvmsg_link.prev = NULL;
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
if (put)
rxrpc_put_call(call, rxrpc_call_put_unnotify);
@@ -671,23 +689,11 @@ static void rxrpc_rcu_free_call(struct rcu_head *rcu)
static void rxrpc_destroy_call(struct work_struct *work)
{
struct rxrpc_call *call = container_of(work, struct rxrpc_call, destroyer);
- struct rxrpc_txbuf *txb;
del_timer_sync(&call->timer);
- rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack);
- rxrpc_cleanup_ring(call);
- while ((txb = list_first_entry_or_null(&call->tx_sendmsg,
- struct rxrpc_txbuf, call_link))) {
- list_del(&txb->call_link);
- rxrpc_put_txbuf(txb, rxrpc_txbuf_put_cleaned);
- }
- while ((txb = list_first_entry_or_null(&call->tx_buffer,
- struct rxrpc_txbuf, call_link))) {
- list_del(&txb->call_link);
- rxrpc_put_txbuf(txb, rxrpc_txbuf_put_cleaned);
- }
-
+ rxrpc_cleanup_tx_buffers(call);
+ rxrpc_cleanup_rx_buffers(call);
rxrpc_put_txbuf(call->tx_pending, rxrpc_txbuf_put_cleaned);
rxrpc_put_connection(call->conn, rxrpc_conn_put_call);
rxrpc_deactivate_bundle(call->bundle);
diff --git a/net/rxrpc/conn_client.c b/net/rxrpc/conn_client.c
index bb11e8289d6d..db0099197890 100644
--- a/net/rxrpc/conn_client.c
+++ b/net/rxrpc/conn_client.c
@@ -231,7 +231,7 @@ static bool rxrpc_may_reuse_conn(struct rxrpc_connection *conn)
distance = id - id_cursor;
if (distance < 0)
distance = -distance;
- limit = max_t(unsigned long, atomic_read(&rxnet->nr_conns) * 4, 1024);
+ limit = umax(atomic_read(&rxnet->nr_conns) * 4, 1024);
if (distance > limit)
goto mark_dont_reuse;
@@ -437,9 +437,9 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
call->dest_srx.srx_service = conn->service_id;
call->cong_ssthresh = call->peer->cong_ssthresh;
if (call->cong_cwnd >= call->cong_ssthresh)
- call->cong_mode = RXRPC_CALL_CONGEST_AVOIDANCE;
+ call->cong_ca_state = RXRPC_CA_CONGEST_AVOIDANCE;
else
- call->cong_mode = RXRPC_CALL_SLOW_START;
+ call->cong_ca_state = RXRPC_CA_SLOW_START;
chan->call_id = call_id;
chan->call_debug_id = call->debug_id;
@@ -508,16 +508,18 @@ static void rxrpc_activate_channels(struct rxrpc_bundle *bundle)
void rxrpc_connect_client_calls(struct rxrpc_local *local)
{
struct rxrpc_call *call;
+ LIST_HEAD(new_client_calls);
- while ((call = list_first_entry_or_null(&local->new_client_calls,
- struct rxrpc_call, wait_link))
- ) {
+ spin_lock_irq(&local->client_call_lock);
+ list_splice_tail_init(&local->new_client_calls, &new_client_calls);
+ spin_unlock_irq(&local->client_call_lock);
+
+ while ((call = list_first_entry_or_null(&new_client_calls,
+ struct rxrpc_call, wait_link))) {
struct rxrpc_bundle *bundle = call->bundle;
- spin_lock(&local->client_call_lock);
list_move_tail(&call->wait_link, &bundle->waiting_calls);
rxrpc_see_call(call, rxrpc_call_see_waiting_call);
- spin_unlock(&local->client_call_lock);
if (rxrpc_bundle_has_space(bundle))
rxrpc_activate_channels(bundle);
@@ -545,9 +547,9 @@ void rxrpc_expose_client_call(struct rxrpc_call *call)
set_bit(RXRPC_CONN_DONT_REUSE, &conn->flags);
trace_rxrpc_client(conn, channel, rxrpc_client_exposed);
- spin_lock(&call->peer->lock);
+ spin_lock_irq(&call->peer->lock);
hlist_add_head(&call->error_link, &call->peer->error_targets);
- spin_unlock(&call->peer->lock);
+ spin_unlock_irq(&call->peer->lock);
}
}
@@ -588,9 +590,9 @@ void rxrpc_disconnect_client_call(struct rxrpc_bundle *bundle, struct rxrpc_call
ASSERTCMP(call->call_id, ==, 0);
ASSERT(!test_bit(RXRPC_CALL_EXPOSED, &call->flags));
/* May still be on ->new_client_calls. */
- spin_lock(&local->client_call_lock);
+ spin_lock_irq(&local->client_call_lock);
list_del_init(&call->wait_link);
- spin_unlock(&local->client_call_lock);
+ spin_unlock_irq(&local->client_call_lock);
return;
}
diff --git a/net/rxrpc/conn_event.c b/net/rxrpc/conn_event.c
index 598b4ee389fc..713e04394ceb 100644
--- a/net/rxrpc/conn_event.c
+++ b/net/rxrpc/conn_event.c
@@ -26,7 +26,7 @@ static bool rxrpc_set_conn_aborted(struct rxrpc_connection *conn, struct sk_buff
bool aborted = false;
if (conn->state != RXRPC_CONN_ABORTED) {
- spin_lock(&conn->state_lock);
+ spin_lock_irq(&conn->state_lock);
if (conn->state != RXRPC_CONN_ABORTED) {
conn->abort_code = abort_code;
conn->error = err;
@@ -37,7 +37,7 @@ static bool rxrpc_set_conn_aborted(struct rxrpc_connection *conn, struct sk_buff
set_bit(RXRPC_CONN_EV_ABORT_CALLS, &conn->events);
aborted = true;
}
- spin_unlock(&conn->state_lock);
+ spin_unlock_irq(&conn->state_lock);
}
return aborted;
@@ -63,11 +63,12 @@ int rxrpc_abort_conn(struct rxrpc_connection *conn, struct sk_buff *skb,
/*
* Mark a connection as being remotely aborted.
*/
-static bool rxrpc_input_conn_abort(struct rxrpc_connection *conn,
+static void rxrpc_input_conn_abort(struct rxrpc_connection *conn,
struct sk_buff *skb)
{
- return rxrpc_set_conn_aborted(conn, skb, skb->priority, -ECONNABORTED,
- RXRPC_CALL_REMOTELY_ABORTED);
+ trace_rxrpc_rx_conn_abort(conn, skb);
+ rxrpc_set_conn_aborted(conn, skb, skb->priority, -ECONNABORTED,
+ RXRPC_CALL_REMOTELY_ABORTED);
}
/*
@@ -91,7 +92,7 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
struct rxrpc_acktrailer trailer;
size_t len;
int ret, ioc;
- u32 serial, mtu, call_id, padding;
+ u32 serial, max_mtu, if_mtu, call_id, padding;
_enter("%d", conn->debug_id);
@@ -149,8 +150,13 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
break;
case RXRPC_PACKET_TYPE_ACK:
- mtu = conn->peer->if_mtu;
- mtu -= conn->peer->hdrsize;
+ if_mtu = conn->peer->if_mtu - conn->peer->hdrsize;
+ if (conn->peer->ackr_adv_pmtud) {
+ max_mtu = umax(conn->peer->max_data, rxrpc_rx_mtu);
+ } else {
+ if_mtu = umin(1444, if_mtu);
+ max_mtu = if_mtu;
+ }
pkt.ack.bufferSpace = 0;
pkt.ack.maxSkew = htons(skb ? skb->priority : 0);
pkt.ack.firstPacket = htonl(chan->last_seq + 1);
@@ -158,10 +164,10 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
pkt.ack.serial = htonl(skb ? sp->hdr.serial : 0);
pkt.ack.reason = skb ? RXRPC_ACK_DUPLICATE : RXRPC_ACK_IDLE;
pkt.ack.nAcks = 0;
- trailer.maxMTU = htonl(rxrpc_rx_mtu);
- trailer.ifMTU = htonl(mtu);
+ trailer.maxMTU = htonl(max_mtu);
+ trailer.ifMTU = htonl(if_mtu);
trailer.rwind = htonl(rxrpc_rx_window_size);
- trailer.jumbo_max = htonl(rxrpc_rx_jumbo_max);
+ trailer.jumbo_max = 0;
pkt.whdr.flags |= RXRPC_SLOW_START_OK;
padding = 0;
iov[0].iov_len += sizeof(pkt.ack);
@@ -171,7 +177,8 @@ void rxrpc_conn_retransmit_call(struct rxrpc_connection *conn,
trace_rxrpc_tx_ack(chan->call_debug_id, serial,
ntohl(pkt.ack.firstPacket),
ntohl(pkt.ack.serial),
- pkt.ack.reason, 0, rxrpc_rx_window_size);
+ pkt.ack.reason, 0, rxrpc_rx_window_size,
+ rxrpc_propose_ack_retransmit);
break;
default:
@@ -202,11 +209,14 @@ static void rxrpc_abort_calls(struct rxrpc_connection *conn)
for (i = 0; i < RXRPC_MAXCALLS; i++) {
call = conn->channels[i].call;
- if (call)
+ if (call) {
+ rxrpc_see_call(call, rxrpc_call_see_conn_abort);
rxrpc_set_call_completion(call,
conn->completion,
conn->abort_code,
conn->error);
+ rxrpc_poke_call(call, rxrpc_call_poke_conn_abort);
+ }
}
_leave("");
@@ -252,10 +262,10 @@ static int rxrpc_process_event(struct rxrpc_connection *conn,
if (ret < 0)
return ret;
- spin_lock(&conn->state_lock);
+ spin_lock_irq(&conn->state_lock);
if (conn->state == RXRPC_CONN_SERVICE_CHALLENGING)
conn->state = RXRPC_CONN_SERVICE;
- spin_unlock(&conn->state_lock);
+ spin_unlock_irq(&conn->state_lock);
if (conn->state == RXRPC_CONN_SERVICE) {
/* Offload call state flipping to the I/O thread. As
diff --git a/net/rxrpc/conn_object.c b/net/rxrpc/conn_object.c
index 694c4df7a1a3..7eba4d7d9a38 100644
--- a/net/rxrpc/conn_object.c
+++ b/net/rxrpc/conn_object.c
@@ -31,13 +31,13 @@ void rxrpc_poke_conn(struct rxrpc_connection *conn, enum rxrpc_conn_trace why)
if (WARN_ON_ONCE(!local))
return;
- spin_lock_bh(&local->lock);
+ spin_lock_irq(&local->lock);
busy = !list_empty(&conn->attend_link);
if (!busy) {
rxrpc_get_connection(conn, why);
list_add_tail(&conn->attend_link, &local->conn_attend_q);
}
- spin_unlock_bh(&local->lock);
+ spin_unlock_irq(&local->lock);
rxrpc_wake_up_io_thread(local);
}
@@ -196,9 +196,9 @@ void rxrpc_disconnect_call(struct rxrpc_call *call)
call->peer->cong_ssthresh = call->cong_ssthresh;
if (!hlist_unhashed(&call->error_link)) {
- spin_lock(&call->peer->lock);
+ spin_lock_irq(&call->peer->lock);
hlist_del_init(&call->error_link);
- spin_unlock(&call->peer->lock);
+ spin_unlock_irq(&call->peer->lock);
}
if (rxrpc_is_client_call(call)) {
@@ -321,6 +321,12 @@ static void rxrpc_clean_up_connection(struct work_struct *work)
list_del_init(&conn->proc_link);
write_unlock(&rxnet->conn_lock);
+ if (conn->pmtud_probe) {
+ trace_rxrpc_pmtud_lost(conn, 0);
+ conn->peer->pmtud_probing = false;
+ conn->peer->pmtud_pending = true;
+ }
+
rxrpc_purge_queue(&conn->rx_queue);
rxrpc_kill_client_conn(conn);
diff --git a/net/rxrpc/input.c b/net/rxrpc/input.c
index 16d49a861dbb..4974b5accafa 100644
--- a/net/rxrpc/input.c
+++ b/net/rxrpc/input.c
@@ -27,80 +27,68 @@ static void rxrpc_proto_abort(struct rxrpc_call *call, rxrpc_seq_t seq,
}
/*
- * Do TCP-style congestion management [RFC 5681].
+ * Do TCP-style congestion management [RFC5681].
*/
static void rxrpc_congestion_management(struct rxrpc_call *call,
- struct sk_buff *skb,
- struct rxrpc_ack_summary *summary,
- rxrpc_serial_t acked_serial)
+ struct rxrpc_ack_summary *summary)
{
- enum rxrpc_congest_change change = rxrpc_cong_no_change;
- unsigned int cumulative_acks = call->cong_cumul_acks;
- unsigned int cwnd = call->cong_cwnd;
- bool resend = false;
-
- summary->flight_size =
- (call->tx_top - call->acks_hard_ack) - summary->nr_acks;
+ summary->change = rxrpc_cong_no_change;
+ summary->in_flight = rxrpc_tx_in_flight(call);
if (test_and_clear_bit(RXRPC_CALL_RETRANS_TIMEOUT, &call->flags)) {
summary->retrans_timeo = true;
- call->cong_ssthresh = max_t(unsigned int,
- summary->flight_size / 2, 2);
- cwnd = 1;
- if (cwnd >= call->cong_ssthresh &&
- call->cong_mode == RXRPC_CALL_SLOW_START) {
- call->cong_mode = RXRPC_CALL_CONGEST_AVOIDANCE;
- call->cong_tstamp = skb->tstamp;
- cumulative_acks = 0;
+ call->cong_ssthresh = umax(summary->in_flight / 2, 2);
+ call->cong_cwnd = 1;
+ if (call->cong_cwnd >= call->cong_ssthresh &&
+ call->cong_ca_state == RXRPC_CA_SLOW_START) {
+ call->cong_ca_state = RXRPC_CA_CONGEST_AVOIDANCE;
+ call->cong_tstamp = call->acks_latest_ts;
+ call->cong_cumul_acks = 0;
}
}
- cumulative_acks += summary->nr_new_acks;
- if (cumulative_acks > 255)
- cumulative_acks = 255;
-
- summary->cwnd = call->cong_cwnd;
- summary->ssthresh = call->cong_ssthresh;
- summary->cumulative_acks = cumulative_acks;
- summary->dup_acks = call->cong_dup_acks;
+ call->cong_cumul_acks += summary->nr_new_sacks;
+ call->cong_cumul_acks += summary->nr_new_hacks;
+ if (call->cong_cumul_acks > 255)
+ call->cong_cumul_acks = 255;
- switch (call->cong_mode) {
- case RXRPC_CALL_SLOW_START:
- if (summary->saw_nacks)
+ switch (call->cong_ca_state) {
+ case RXRPC_CA_SLOW_START:
+ if (call->acks_nr_snacks > 0)
goto packet_loss_detected;
- if (summary->cumulative_acks > 0)
- cwnd += 1;
- if (cwnd >= call->cong_ssthresh) {
- call->cong_mode = RXRPC_CALL_CONGEST_AVOIDANCE;
- call->cong_tstamp = skb->tstamp;
+ if (call->cong_cumul_acks > 0)
+ call->cong_cwnd += 1;
+ if (call->cong_cwnd >= call->cong_ssthresh) {
+ call->cong_ca_state = RXRPC_CA_CONGEST_AVOIDANCE;
+ call->cong_tstamp = call->acks_latest_ts;
}
goto out;
- case RXRPC_CALL_CONGEST_AVOIDANCE:
- if (summary->saw_nacks)
+ case RXRPC_CA_CONGEST_AVOIDANCE:
+ if (call->acks_nr_snacks > 0)
goto packet_loss_detected;
/* We analyse the number of packets that get ACK'd per RTT
* period and increase the window if we managed to fill it.
*/
- if (call->peer->rtt_count == 0)
+ if (call->rtt_count == 0)
goto out;
- if (ktime_before(skb->tstamp,
+ if (ktime_before(call->acks_latest_ts,
ktime_add_us(call->cong_tstamp,
- call->peer->srtt_us >> 3)))
+ call->srtt_us >> 3)))
goto out_no_clear_ca;
- change = rxrpc_cong_rtt_window_end;
- call->cong_tstamp = skb->tstamp;
- if (cumulative_acks >= cwnd)
- cwnd++;
+ summary->change = rxrpc_cong_rtt_window_end;
+ call->cong_tstamp = call->acks_latest_ts;
+ if (call->cong_cumul_acks >= call->cong_cwnd)
+ call->cong_cwnd++;
goto out;
- case RXRPC_CALL_PACKET_LOSS:
- if (!summary->saw_nacks)
+ case RXRPC_CA_PACKET_LOSS:
+ if (call->acks_nr_snacks == 0)
goto resume_normality;
- if (summary->new_low_nack) {
- change = rxrpc_cong_new_low_nack;
+ if (summary->new_low_snack) {
+ summary->change = rxrpc_cong_new_low_nack;
call->cong_dup_acks = 1;
if (call->cong_extra > 1)
call->cong_extra = 1;
@@ -111,31 +99,35 @@ static void rxrpc_congestion_management(struct rxrpc_call *call,
if (call->cong_dup_acks < 3)
goto send_extra_data;
- change = rxrpc_cong_begin_retransmission;
- call->cong_mode = RXRPC_CALL_FAST_RETRANSMIT;
- call->cong_ssthresh = max_t(unsigned int,
- summary->flight_size / 2, 2);
- cwnd = call->cong_ssthresh + 3;
+ summary->change = rxrpc_cong_begin_retransmission;
+ call->cong_ca_state = RXRPC_CA_FAST_RETRANSMIT;
+ call->cong_ssthresh = umax(summary->in_flight / 2, 2);
+ call->cong_cwnd = call->cong_ssthresh + 3;
call->cong_extra = 0;
call->cong_dup_acks = 0;
- resend = true;
+ summary->need_retransmit = true;
+ summary->in_fast_or_rto_recovery = true;
goto out;
- case RXRPC_CALL_FAST_RETRANSMIT:
- if (!summary->new_low_nack) {
- if (summary->nr_new_acks == 0)
- cwnd += 1;
+ case RXRPC_CA_FAST_RETRANSMIT:
+ rxrpc_tlp_init(call);
+ summary->in_fast_or_rto_recovery = true;
+ if (!summary->new_low_snack) {
+ if (summary->nr_new_sacks == 0)
+ call->cong_cwnd += 1;
call->cong_dup_acks++;
if (call->cong_dup_acks == 2) {
- change = rxrpc_cong_retransmit_again;
+ summary->change = rxrpc_cong_retransmit_again;
call->cong_dup_acks = 0;
- resend = true;
+ summary->need_retransmit = true;
}
} else {
- change = rxrpc_cong_progress;
- cwnd = call->cong_ssthresh;
- if (!summary->saw_nacks)
+ summary->change = rxrpc_cong_progress;
+ call->cong_cwnd = call->cong_ssthresh;
+ if (call->acks_nr_snacks == 0) {
+ summary->exiting_fast_or_rto_recovery = true;
goto resume_normality;
+ }
}
goto out;
@@ -145,30 +137,25 @@ static void rxrpc_congestion_management(struct rxrpc_call *call,
}
resume_normality:
- change = rxrpc_cong_cleared_nacks;
+ summary->change = rxrpc_cong_cleared_nacks;
call->cong_dup_acks = 0;
call->cong_extra = 0;
- call->cong_tstamp = skb->tstamp;
- if (cwnd < call->cong_ssthresh)
- call->cong_mode = RXRPC_CALL_SLOW_START;
+ call->cong_tstamp = call->acks_latest_ts;
+ if (call->cong_cwnd < call->cong_ssthresh)
+ call->cong_ca_state = RXRPC_CA_SLOW_START;
else
- call->cong_mode = RXRPC_CALL_CONGEST_AVOIDANCE;
+ call->cong_ca_state = RXRPC_CA_CONGEST_AVOIDANCE;
out:
- cumulative_acks = 0;
+ call->cong_cumul_acks = 0;
out_no_clear_ca:
- if (cwnd >= RXRPC_TX_MAX_WINDOW)
- cwnd = RXRPC_TX_MAX_WINDOW;
- call->cong_cwnd = cwnd;
- call->cong_cumul_acks = cumulative_acks;
- summary->mode = call->cong_mode;
- trace_rxrpc_congest(call, summary, acked_serial, change);
- if (resend)
- rxrpc_resend(call, skb);
+ if (call->cong_cwnd >= RXRPC_TX_MAX_WINDOW)
+ call->cong_cwnd = RXRPC_TX_MAX_WINDOW;
+ trace_rxrpc_congest(call, summary);
return;
packet_loss_detected:
- change = rxrpc_cong_saw_nack;
- call->cong_mode = RXRPC_CALL_PACKET_LOSS;
+ summary->change = rxrpc_cong_saw_nack;
+ call->cong_ca_state = RXRPC_CA_PACKET_LOSS;
call->cong_dup_acks = 0;
goto send_extra_data;
@@ -177,7 +164,7 @@ send_extra_data:
* state.
*/
if (test_bit(RXRPC_CALL_TX_LAST, &call->flags) ||
- summary->nr_acks != call->tx_top - call->acks_hard_ack) {
+ call->acks_nr_sacks != call->tx_top - call->tx_bottom) {
call->cong_extra++;
wake_up(&call->waitq);
}
@@ -189,26 +176,42 @@ send_extra_data:
*/
void rxrpc_congestion_degrade(struct rxrpc_call *call)
{
- ktime_t rtt, now;
+ ktime_t rtt, now, time_since;
- if (call->cong_mode != RXRPC_CALL_SLOW_START &&
- call->cong_mode != RXRPC_CALL_CONGEST_AVOIDANCE)
+ if (call->cong_ca_state != RXRPC_CA_SLOW_START &&
+ call->cong_ca_state != RXRPC_CA_CONGEST_AVOIDANCE)
return;
if (__rxrpc_call_state(call) == RXRPC_CALL_CLIENT_AWAIT_REPLY)
return;
- rtt = ns_to_ktime(call->peer->srtt_us * (1000 / 8));
+ rtt = ns_to_ktime(call->srtt_us * (NSEC_PER_USEC / 8));
now = ktime_get_real();
- if (!ktime_before(ktime_add(call->tx_last_sent, rtt), now))
+ time_since = ktime_sub(now, call->tx_last_sent);
+ if (ktime_before(time_since, rtt))
return;
- trace_rxrpc_reset_cwnd(call, now);
+ trace_rxrpc_reset_cwnd(call, time_since, rtt);
rxrpc_inc_stat(call->rxnet, stat_tx_data_cwnd_reset);
call->tx_last_sent = now;
- call->cong_mode = RXRPC_CALL_SLOW_START;
- call->cong_ssthresh = max_t(unsigned int, call->cong_ssthresh,
- call->cong_cwnd * 3 / 4);
- call->cong_cwnd = max_t(unsigned int, call->cong_cwnd / 2, RXRPC_MIN_CWND);
+ call->cong_ca_state = RXRPC_CA_SLOW_START;
+ call->cong_ssthresh = umax(call->cong_ssthresh, call->cong_cwnd * 3 / 4);
+ call->cong_cwnd = umax(call->cong_cwnd / 2, RXRPC_MIN_CWND);
+}
+
+/*
+ * Add an RTT sample derived from an ACK'd DATA packet.
+ */
+static void rxrpc_add_data_rtt_sample(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary,
+ struct rxrpc_txqueue *tq,
+ int ix)
+{
+ ktime_t xmit_ts = ktime_add_us(tq->xmit_ts_base, tq->segment_xmit_ts[ix]);
+
+ rxrpc_call_add_rtt(call, rxrpc_rtt_rx_data_ack, -1,
+ summary->acked_serial, summary->ack_serial,
+ xmit_ts, call->acks_latest_ts);
+ __clear_bit(ix, &tq->rtt_samples); /* Prevent repeat RTT sample */
}
/*
@@ -217,37 +220,120 @@ void rxrpc_congestion_degrade(struct rxrpc_call *call)
static bool rxrpc_rotate_tx_window(struct rxrpc_call *call, rxrpc_seq_t to,
struct rxrpc_ack_summary *summary)
{
- struct rxrpc_txbuf *txb;
- bool rot_last = false;
+ struct rxrpc_txqueue *tq = call->tx_queue;
+ rxrpc_seq_t seq = call->tx_bottom + 1;
+ bool rot_last = false, trace = false;
- list_for_each_entry_rcu(txb, &call->tx_buffer, call_link, false) {
- if (before_eq(txb->seq, call->acks_hard_ack))
- continue;
- if (txb->flags & RXRPC_LAST_PACKET) {
+ _enter("%x,%x", call->tx_bottom, to);
+
+ trace_rxrpc_tx_rotate(call, seq, to);
+ trace_rxrpc_tq(call, tq, seq, rxrpc_tq_rotate);
+
+ if (call->acks_lowest_nak == call->tx_bottom) {
+ call->acks_lowest_nak = to;
+ } else if (after(to, call->acks_lowest_nak)) {
+ summary->new_low_snack = true;
+ call->acks_lowest_nak = to;
+ }
+
+ /* We may have a left over fully-consumed buffer at the front that we
+ * couldn't drop before (rotate_and_keep below).
+ */
+ if (seq == call->tx_qbase + RXRPC_NR_TXQUEUE) {
+ call->tx_qbase += RXRPC_NR_TXQUEUE;
+ call->tx_queue = tq->next;
+ trace_rxrpc_tq(call, tq, seq, rxrpc_tq_rotate_and_free);
+ kfree(tq);
+ tq = call->tx_queue;
+ }
+
+ do {
+ unsigned int ix = seq - call->tx_qbase;
+
+ _debug("tq=%x seq=%x i=%d f=%x", tq->qbase, seq, ix, tq->bufs[ix]->flags);
+ if (tq->bufs[ix]->flags & RXRPC_LAST_PACKET) {
set_bit(RXRPC_CALL_TX_LAST, &call->flags);
rot_last = true;
}
- if (txb->seq == to)
- break;
- }
- if (rot_last)
- set_bit(RXRPC_CALL_TX_ALL_ACKED, &call->flags);
+ if (summary->acked_serial == tq->segment_serial[ix] &&
+ test_bit(ix, &tq->rtt_samples))
+ rxrpc_add_data_rtt_sample(call, summary, tq, ix);
+
+ if (ix == tq->nr_reported_acks) {
+ /* Packet directly hard ACK'd. */
+ tq->nr_reported_acks++;
+ rxrpc_input_rack_one(call, summary, tq, ix);
+ if (seq == call->tlp_seq)
+ summary->tlp_probe_acked = true;
+ summary->nr_new_hacks++;
+ __set_bit(ix, &tq->segment_acked);
+ trace_rxrpc_rotate(call, tq, summary, seq, rxrpc_rotate_trace_hack);
+ } else if (test_bit(ix, &tq->segment_acked)) {
+ /* Soft ACK -> hard ACK. */
+ call->acks_nr_sacks--;
+ trace_rxrpc_rotate(call, tq, summary, seq, rxrpc_rotate_trace_sack);
+ } else {
+ /* Soft NAK -> hard ACK. */
+ call->acks_nr_snacks--;
+ rxrpc_input_rack_one(call, summary, tq, ix);
+ if (seq == call->tlp_seq)
+ summary->tlp_probe_acked = true;
+ summary->nr_new_hacks++;
+ __set_bit(ix, &tq->segment_acked);
+ trace_rxrpc_rotate(call, tq, summary, seq, rxrpc_rotate_trace_snak);
+ }
- _enter("%x,%x,%x,%d", to, call->acks_hard_ack, call->tx_top, rot_last);
+ call->tx_nr_sent--;
+ if (__test_and_clear_bit(ix, &tq->segment_lost))
+ call->tx_nr_lost--;
+ if (__test_and_clear_bit(ix, &tq->segment_retransmitted))
+ call->tx_nr_resent--;
+ __clear_bit(ix, &tq->ever_retransmitted);
- if (call->acks_lowest_nak == call->acks_hard_ack) {
- call->acks_lowest_nak = to;
- } else if (after(to, call->acks_lowest_nak)) {
- summary->new_low_nack = true;
- call->acks_lowest_nak = to;
+ rxrpc_put_txbuf(tq->bufs[ix], rxrpc_txbuf_put_rotated);
+ tq->bufs[ix] = NULL;
+
+ WRITE_ONCE(call->tx_bottom, seq);
+ trace_rxrpc_txqueue(call, (rot_last ?
+ rxrpc_txqueue_rotate_last :
+ rxrpc_txqueue_rotate));
+
+ seq++;
+ trace = true;
+ if (!(seq & RXRPC_TXQ_MASK)) {
+ trace_rxrpc_rack_update(call, summary);
+ trace = false;
+ prefetch(tq->next);
+ if (tq != call->tx_qtail) {
+ call->tx_qbase += RXRPC_NR_TXQUEUE;
+ call->tx_queue = tq->next;
+ trace_rxrpc_tq(call, tq, seq, rxrpc_tq_rotate_and_free);
+ kfree(tq);
+ tq = call->tx_queue;
+ } else {
+ trace_rxrpc_tq(call, tq, seq, rxrpc_tq_rotate_and_keep);
+ tq = NULL;
+ break;
+ }
+ }
+
+ } while (before_eq(seq, to));
+
+ if (trace)
+ trace_rxrpc_rack_update(call, summary);
+
+ if (rot_last) {
+ set_bit(RXRPC_CALL_TX_ALL_ACKED, &call->flags);
+ if (tq) {
+ trace_rxrpc_tq(call, tq, seq, rxrpc_tq_rotate_and_free);
+ kfree(tq);
+ call->tx_queue = NULL;
+ }
}
- smp_store_release(&call->acks_hard_ack, to);
+ _debug("%x,%x,%x,%d", to, call->tx_bottom, call->tx_top, rot_last);
- trace_rxrpc_txqueue(call, (rot_last ?
- rxrpc_txqueue_rotate_last :
- rxrpc_txqueue_rotate));
wake_up(&call->waitq);
return rot_last;
}
@@ -263,13 +349,10 @@ static void rxrpc_end_tx_phase(struct rxrpc_call *call, bool reply_begun,
{
ASSERT(test_bit(RXRPC_CALL_TX_LAST, &call->flags));
- call->resend_at = KTIME_MAX;
- trace_rxrpc_timer_can(call, rxrpc_timer_trace_resend);
-
- if (unlikely(call->cong_last_nack)) {
- rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack);
- call->cong_last_nack = NULL;
- }
+ call->rack_timer_mode = RXRPC_CALL_RACKTIMER_OFF;
+ call->rack_timo_at = KTIME_MAX;
+ trace_rxrpc_rack_timer(call, 0, false);
+ trace_rxrpc_timer_can(call, rxrpc_timer_trace_rack_off + call->rack_timer_mode);
switch (__rxrpc_call_state(call)) {
case RXRPC_CALL_CLIENT_SEND_REQUEST:
@@ -365,7 +448,7 @@ static void rxrpc_input_queue_data(struct rxrpc_call *call, struct sk_buff *skb,
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
bool last = sp->hdr.flags & RXRPC_LAST_PACKET;
- __skb_queue_tail(&call->recvmsg_queue, skb);
+ skb_queue_tail(&call->recvmsg_queue, skb);
rxrpc_input_update_ack_window(call, window, wtop);
trace_rxrpc_receive(call, last ? why + 1 : why, sp->hdr.serial, sp->hdr.seq);
if (last)
@@ -442,7 +525,6 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
rxrpc_get_skb(skb, rxrpc_skb_get_to_recvmsg);
- spin_lock(&call->recvmsg_queue.lock);
rxrpc_input_queue_data(call, skb, window, wtop, rxrpc_receive_queue);
*_notify = true;
@@ -464,8 +546,6 @@ static void rxrpc_input_data_one(struct rxrpc_call *call, struct sk_buff *skb,
rxrpc_receive_queue_oos);
}
- spin_unlock(&call->recvmsg_queue.lock);
-
call->ackr_sack_base = sack;
} else {
unsigned int slot;
@@ -530,7 +610,7 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
unsigned int offset = sizeof(struct rxrpc_wire_header);
unsigned int len = skb->len - offset;
bool notify = false;
- int ack_reason = 0;
+ int ack_reason = 0, count = 1, stat_ix;
while (sp->hdr.flags & RXRPC_JUMBO_PACKET) {
if (len < RXRPC_JUMBO_SUBPKTLEN)
@@ -559,12 +639,16 @@ static bool rxrpc_input_split_jumbo(struct rxrpc_call *call, struct sk_buff *skb
sp->hdr.serial++;
offset += RXRPC_JUMBO_SUBPKTLEN;
len -= RXRPC_JUMBO_SUBPKTLEN;
+ count++;
}
sp->offset = offset;
sp->len = len;
rxrpc_input_data_one(call, skb, &notify, &ack_serial, &ack_reason);
+ stat_ix = umin(count, ARRAY_SIZE(call->rxnet->stat_rx_jumbo)) - 1;
+ atomic_inc(&call->rxnet->stat_rx_jumbo[stat_ix]);
+
if (ack_reason > 0) {
rxrpc_send_ACK(call, ack_reason, ack_serial,
rxrpc_propose_ack_input_data);
@@ -667,7 +751,7 @@ static void rxrpc_complete_rtt_probe(struct rxrpc_call *call,
clear_bit(i + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
smp_mb(); /* Read data before setting avail bit */
set_bit(i, &call->rtt_avail);
- rxrpc_peer_add_rtt(call, type, i, acked_serial, ack_serial,
+ rxrpc_call_add_rtt(call, type, i, acked_serial, ack_serial,
sent_at, resp_time);
matched = true;
}
@@ -677,7 +761,7 @@ static void rxrpc_complete_rtt_probe(struct rxrpc_call *call,
*/
if (after(acked_serial, orig_serial)) {
trace_rxrpc_rtt_rx(call, rxrpc_rtt_rx_obsolete, i,
- orig_serial, acked_serial, 0, 0);
+ orig_serial, acked_serial, 0, 0, 0);
clear_bit(i + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
smp_wmb();
set_bit(i, &call->rtt_avail);
@@ -685,7 +769,7 @@ static void rxrpc_complete_rtt_probe(struct rxrpc_call *call,
}
if (!matched)
- trace_rxrpc_rtt_rx(call, rxrpc_rtt_rx_lost, 9, 0, acked_serial, 0, 0);
+ trace_rxrpc_rtt_rx(call, rxrpc_rtt_rx_lost, 9, 0, acked_serial, 0, 0, 0);
}
/*
@@ -695,10 +779,13 @@ static void rxrpc_input_ack_trailer(struct rxrpc_call *call, struct sk_buff *skb
struct rxrpc_acktrailer *trailer)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
- struct rxrpc_peer *peer;
- unsigned int mtu;
+ struct rxrpc_peer *peer = call->peer;
+ unsigned int max_data, capacity;
bool wake = false;
- u32 rwind = ntohl(trailer->rwind);
+ u32 max_mtu = ntohl(trailer->maxMTU);
+ //u32 if_mtu = ntohl(trailer->ifMTU);
+ u32 rwind = ntohl(trailer->rwind);
+ u32 jumbo_max = ntohl(trailer->jumbo_max);
if (rwind > RXRPC_TX_MAX_WINDOW)
rwind = RXRPC_TX_MAX_WINDOW;
@@ -709,54 +796,149 @@ static void rxrpc_input_ack_trailer(struct rxrpc_call *call, struct sk_buff *skb
call->tx_winsize = rwind;
}
- mtu = min(ntohl(trailer->maxMTU), ntohl(trailer->ifMTU));
+ max_mtu = clamp(max_mtu, 500, 65535);
+ peer->ackr_max_data = max_mtu;
- peer = call->peer;
- if (mtu < peer->maxdata) {
- spin_lock(&peer->lock);
- peer->maxdata = mtu;
- peer->mtu = mtu + peer->hdrsize;
- spin_unlock(&peer->lock);
+ if (max_mtu < peer->max_data) {
+ trace_rxrpc_pmtud_reduce(peer, sp->hdr.serial, max_mtu,
+ rxrpc_pmtud_reduce_ack);
+ write_seqcount_begin(&peer->mtu_lock);
+ peer->max_data = max_mtu;
+ write_seqcount_end(&peer->mtu_lock);
+ }
+
+ max_data = umin(max_mtu, peer->max_data);
+ capacity = max_data;
+ capacity += sizeof(struct rxrpc_jumbo_header); /* First subpacket has main hdr, not jumbo */
+ capacity /= sizeof(struct rxrpc_jumbo_header) + RXRPC_JUMBO_DATALEN;
+
+ if (jumbo_max == 0) {
+ /* The peer says it supports pmtu discovery */
+ peer->ackr_adv_pmtud = true;
+ } else {
+ peer->ackr_adv_pmtud = false;
+ capacity = clamp(capacity, 1, jumbo_max);
}
+ call->tx_jumbo_max = capacity;
+
if (wake)
wake_up(&call->waitq);
}
+#if defined(CONFIG_X86) && __GNUC__ && !defined(__clang__)
+/* Clang doesn't support the %z constraint modifier */
+#define shiftr_adv_rotr(shift_from, rotate_into) ({ \
+ asm(" shr%z1 %1\n" \
+ " inc %0\n" \
+ " rcr%z2 %2\n" \
+ : "+d"(shift_from), "+m"(*(shift_from)), "+rm"(rotate_into) \
+ ); \
+ })
+#else
+#define shiftr_adv_rotr(shift_from, rotate_into) ({ \
+ typeof(rotate_into) __bit0 = *(shift_from) & 1; \
+ *(shift_from) >>= 1; \
+ shift_from++; \
+ rotate_into >>= 1; \
+ rotate_into |= __bit0 << (sizeof(rotate_into) * 8 - 1); \
+ })
+#endif
+
/*
- * Determine how many nacks from the previous ACK have now been satisfied.
+ * Deal with RTT samples from soft ACKs.
*/
-static rxrpc_seq_t rxrpc_input_check_prev_ack(struct rxrpc_call *call,
- struct rxrpc_ack_summary *summary,
- rxrpc_seq_t seq)
+static void rxrpc_input_soft_rtt(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary,
+ struct rxrpc_txqueue *tq)
{
- struct sk_buff *skb = call->cong_last_nack;
- struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
- unsigned int i, new_acks = 0, retained_nacks = 0;
- rxrpc_seq_t old_seq = sp->ack.first_ack;
- u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket);
+ for (int ix = 0; ix < RXRPC_NR_TXQUEUE; ix++)
+ if (summary->acked_serial == tq->segment_serial[ix])
+ return rxrpc_add_data_rtt_sample(call, summary, tq, ix);
+}
- if (after_eq(seq, old_seq + sp->ack.nr_acks)) {
- summary->nr_new_acks += sp->ack.nr_nacks;
- summary->nr_new_acks += seq - (old_seq + sp->ack.nr_acks);
- summary->nr_retained_nacks = 0;
- } else if (seq == old_seq) {
- summary->nr_retained_nacks = sp->ack.nr_nacks;
- } else {
- for (i = 0; i < sp->ack.nr_acks; i++) {
- if (acks[i] == RXRPC_ACK_TYPE_NACK) {
- if (before(old_seq + i, seq))
- new_acks++;
- else
- retained_nacks++;
- }
+/*
+ * Process a batch of soft ACKs specific to a transmission queue segment.
+ */
+static void rxrpc_input_soft_ack_tq(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary,
+ struct rxrpc_txqueue *tq,
+ unsigned long extracted_acks,
+ int nr_reported,
+ rxrpc_seq_t seq,
+ rxrpc_seq_t *lowest_nak)
+{
+ unsigned long old_reported = 0, flipped, new_acks = 0;
+ unsigned long a_to_n, n_to_a = 0;
+ int new, a, n;
+
+ if (tq->nr_reported_acks > 0)
+ old_reported = ~0UL >> (RXRPC_NR_TXQUEUE - tq->nr_reported_acks);
+
+ _enter("{%x,%lx,%d},%lx,%d,%x",
+ tq->qbase, tq->segment_acked, tq->nr_reported_acks,
+ extracted_acks, nr_reported, seq);
+
+ _debug("[%x]", tq->qbase);
+ _debug("tq %16lx %u", tq->segment_acked, tq->nr_reported_acks);
+ _debug("sack %16lx %u", extracted_acks, nr_reported);
+
+ /* See how many previously logged ACKs/NAKs have flipped. */
+ flipped = (tq->segment_acked ^ extracted_acks) & old_reported;
+ if (flipped) {
+ n_to_a = ~tq->segment_acked & flipped; /* Old NAK -> ACK */
+ a_to_n = tq->segment_acked & flipped; /* Old ACK -> NAK */
+ a = hweight_long(n_to_a);
+ n = hweight_long(a_to_n);
+ _debug("flip %16lx", flipped);
+ _debug("ntoa %16lx %d", n_to_a, a);
+ _debug("aton %16lx %d", a_to_n, n);
+ call->acks_nr_sacks += a - n;
+ call->acks_nr_snacks += n - a;
+ summary->nr_new_sacks += a;
+ summary->nr_new_snacks += n;
+ }
+
+ /* See how many new ACKs/NAKs have been acquired. */
+ new = nr_reported - tq->nr_reported_acks;
+ if (new > 0) {
+ new_acks = extracted_acks & ~old_reported;
+ if (new_acks) {
+ a = hweight_long(new_acks);
+ n = new - a;
+ _debug("new_a %16lx new=%d a=%d n=%d", new_acks, new, a, n);
+ call->acks_nr_sacks += a;
+ call->acks_nr_snacks += n;
+ summary->nr_new_sacks += a;
+ summary->nr_new_snacks += n;
+ } else {
+ call->acks_nr_snacks += new;
+ summary->nr_new_snacks += new;
}
+ }
+
+ tq->nr_reported_acks = nr_reported;
+ tq->segment_acked = extracted_acks;
+ trace_rxrpc_apply_acks(call, tq);
- summary->nr_new_acks += new_acks;
- summary->nr_retained_nacks = retained_nacks;
+ if (extracted_acks != ~0UL) {
+ rxrpc_seq_t lowest = seq + ffz(extracted_acks);
+
+ if (before(lowest, *lowest_nak))
+ *lowest_nak = lowest;
}
- return old_seq + sp->ack.nr_acks;
+ if (summary->acked_serial)
+ rxrpc_input_soft_rtt(call, summary, tq);
+
+ new_acks |= n_to_a;
+ if (new_acks)
+ rxrpc_input_rack(call, summary, tq, new_acks);
+
+ if (call->tlp_serial &&
+ rxrpc_seq_in_txq(tq, call->tlp_seq) &&
+ test_bit(call->tlp_seq - tq->qbase, &new_acks))
+ summary->tlp_probe_acked = true;
}
/*
@@ -770,39 +952,50 @@ static rxrpc_seq_t rxrpc_input_check_prev_ack(struct rxrpc_call *call,
*/
static void rxrpc_input_soft_acks(struct rxrpc_call *call,
struct rxrpc_ack_summary *summary,
- struct sk_buff *skb,
- rxrpc_seq_t seq,
- rxrpc_seq_t since)
+ struct sk_buff *skb)
{
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
- unsigned int i, old_nacks = 0;
+ struct rxrpc_txqueue *tq = call->tx_queue;
+ unsigned long extracted = ~0UL;
+ unsigned int nr = 0;
+ rxrpc_seq_t seq = call->acks_hard_ack + 1;
rxrpc_seq_t lowest_nak = seq + sp->ack.nr_acks;
u8 *acks = skb->data + sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket);
- for (i = 0; i < sp->ack.nr_acks; i++) {
- if (acks[i] == RXRPC_ACK_TYPE_ACK) {
- summary->nr_acks++;
- if (after_eq(seq, since))
- summary->nr_new_acks++;
- } else {
- summary->saw_nacks = true;
- if (before(seq, since)) {
- /* Overlap with previous ACK */
- old_nacks++;
- } else {
- summary->nr_new_nacks++;
- sp->ack.nr_nacks++;
- }
+ _enter("%x,%x,%u", tq->qbase, seq, sp->ack.nr_acks);
+
+ while (after(seq, tq->qbase + RXRPC_NR_TXQUEUE - 1))
+ tq = tq->next;
- if (before(seq, lowest_nak))
- lowest_nak = seq;
+ for (unsigned int i = 0; i < sp->ack.nr_acks; i++) {
+ /* Decant ACKs until we hit a txqueue boundary. */
+ shiftr_adv_rotr(acks, extracted);
+ if (i == 256) {
+ acks -= i;
+ i = 0;
}
seq++;
+ nr++;
+ if ((seq & RXRPC_TXQ_MASK) != 0)
+ continue;
+
+ _debug("bound %16lx %u", extracted, nr);
+
+ rxrpc_input_soft_ack_tq(call, summary, tq, extracted, RXRPC_NR_TXQUEUE,
+ seq - RXRPC_NR_TXQUEUE, &lowest_nak);
+ extracted = ~0UL;
+ nr = 0;
+ tq = tq->next;
+ prefetch(tq);
}
- if (lowest_nak != call->acks_lowest_nak) {
- call->acks_lowest_nak = lowest_nak;
- summary->new_low_nack = true;
+ if (nr) {
+ unsigned int nr_reported = seq & RXRPC_TXQ_MASK;
+
+ extracted >>= RXRPC_NR_TXQUEUE - nr_reported;
+ _debug("tail %16lx %u", extracted, nr_reported);
+ rxrpc_input_soft_ack_tq(call, summary, tq, extracted, nr_reported,
+ seq & ~RXRPC_TXQ_MASK, &lowest_nak);
}
/* We *can* have more nacks than we did - the peer is permitted to drop
@@ -810,9 +1003,14 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call,
* possible for the nack distribution to change whilst the number of
* nacks stays the same or goes down.
*/
- if (old_nacks < summary->nr_retained_nacks)
- summary->nr_new_acks += summary->nr_retained_nacks - old_nacks;
- summary->nr_retained_nacks = old_nacks;
+ if (lowest_nak != call->acks_lowest_nak) {
+ call->acks_lowest_nak = lowest_nak;
+ summary->new_low_snack = true;
+ }
+
+ _debug("summary A=%d+%d N=%d+%d",
+ call->acks_nr_sacks, summary->nr_new_sacks,
+ call->acks_nr_snacks, summary->nr_new_snacks);
}
/*
@@ -820,21 +1018,21 @@ static void rxrpc_input_soft_acks(struct rxrpc_call *call,
* with respect to the ack state conveyed by preceding ACKs.
*/
static bool rxrpc_is_ack_valid(struct rxrpc_call *call,
- rxrpc_seq_t first_pkt, rxrpc_seq_t prev_pkt)
+ rxrpc_seq_t hard_ack, rxrpc_seq_t prev_pkt)
{
- rxrpc_seq_t base = READ_ONCE(call->acks_first_seq);
+ rxrpc_seq_t base = READ_ONCE(call->acks_hard_ack);
- if (after(first_pkt, base))
+ if (after(hard_ack, base))
return true; /* The window advanced */
- if (before(first_pkt, base))
+ if (before(hard_ack, base))
return false; /* firstPacket regressed */
if (after_eq(prev_pkt, call->acks_prev_seq))
return true; /* previousPacket hasn't regressed. */
/* Some rx implementations put a serial number in previousPacket. */
- if (after_eq(prev_pkt, base + call->tx_winsize))
+ if (after(prev_pkt, base + call->tx_winsize))
return false;
return true;
}
@@ -852,53 +1050,34 @@ static bool rxrpc_is_ack_valid(struct rxrpc_call *call,
static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
{
struct rxrpc_ack_summary summary = { 0 };
- struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
struct rxrpc_acktrailer trailer;
- rxrpc_serial_t ack_serial, acked_serial;
- rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt, since;
+ struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
+ rxrpc_seq_t first_soft_ack, hard_ack, prev_pkt;
int nr_acks, offset, ioffset;
_enter("");
offset = sizeof(struct rxrpc_wire_header) + sizeof(struct rxrpc_ackpacket);
- ack_serial = sp->hdr.serial;
- acked_serial = sp->ack.acked_serial;
- first_soft_ack = sp->ack.first_ack;
- prev_pkt = sp->ack.prev_ack;
- nr_acks = sp->ack.nr_acks;
- hard_ack = first_soft_ack - 1;
- summary.ack_reason = (sp->ack.reason < RXRPC_ACK__INVALID ?
- sp->ack.reason : RXRPC_ACK__INVALID);
-
- trace_rxrpc_rx_ack(call, ack_serial, acked_serial,
- first_soft_ack, prev_pkt,
- summary.ack_reason, nr_acks);
- rxrpc_inc_stat(call->rxnet, stat_rx_acks[summary.ack_reason]);
+ summary.ack_serial = sp->hdr.serial;
+ first_soft_ack = sp->ack.first_ack;
+ prev_pkt = sp->ack.prev_ack;
+ nr_acks = sp->ack.nr_acks;
+ hard_ack = first_soft_ack - 1;
+ summary.acked_serial = sp->ack.acked_serial;
+ summary.ack_reason = (sp->ack.reason < RXRPC_ACK__INVALID ?
+ sp->ack.reason : RXRPC_ACK__INVALID);
- if (acked_serial != 0) {
- switch (summary.ack_reason) {
- case RXRPC_ACK_PING_RESPONSE:
- rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
- rxrpc_rtt_rx_ping_response);
- break;
- case RXRPC_ACK_REQUESTED:
- rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
- rxrpc_rtt_rx_requested_ack);
- break;
- default:
- rxrpc_complete_rtt_probe(call, skb->tstamp, acked_serial, ack_serial,
- rxrpc_rtt_rx_other_ack);
- break;
- }
- }
+ trace_rxrpc_rx_ack(call, sp);
+ rxrpc_inc_stat(call->rxnet, stat_rx_acks[summary.ack_reason]);
+ prefetch(call->tx_queue);
/* If we get an EXCEEDS_WINDOW ACK from the server, it probably
* indicates that the client address changed due to NAT. The server
* lost the call because it switched to a different peer.
*/
if (unlikely(summary.ack_reason == RXRPC_ACK_EXCEEDS_WINDOW) &&
- first_soft_ack == 1 &&
+ hard_ack == 0 &&
prev_pkt == 0 &&
rxrpc_is_client_call(call)) {
rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED,
@@ -911,9 +1090,9 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
* if we still have it buffered to the beginning.
*/
if (unlikely(summary.ack_reason == RXRPC_ACK_OUT_OF_SEQUENCE) &&
- first_soft_ack == 1 &&
+ hard_ack == 0 &&
prev_pkt == 0 &&
- call->acks_hard_ack == 0 &&
+ call->tx_bottom == 0 &&
rxrpc_is_client_call(call)) {
rxrpc_set_call_completion(call, RXRPC_CALL_REMOTELY_ABORTED,
0, -ENETRESET);
@@ -921,11 +1100,9 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
}
/* Discard any out-of-order or duplicate ACKs (outside lock). */
- if (!rxrpc_is_ack_valid(call, first_soft_ack, prev_pkt)) {
- trace_rxrpc_rx_discard_ack(call->debug_id, ack_serial,
- first_soft_ack, call->acks_first_seq,
- prev_pkt, call->acks_prev_seq);
- goto send_response;
+ if (!rxrpc_is_ack_valid(call, hard_ack, prev_pkt)) {
+ trace_rxrpc_rx_discard_ack(call, summary.ack_serial, hard_ack, prev_pkt);
+ goto send_response; /* Still respond if requested. */
}
trailer.maxMTU = 0;
@@ -937,34 +1114,30 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
if (nr_acks > 0)
skb_condense(skb);
- if (call->cong_last_nack) {
- since = rxrpc_input_check_prev_ack(call, &summary, first_soft_ack);
- rxrpc_free_skb(call->cong_last_nack, rxrpc_skb_put_last_nack);
- call->cong_last_nack = NULL;
- } else {
- summary.nr_new_acks = first_soft_ack - call->acks_first_seq;
- call->acks_lowest_nak = first_soft_ack + nr_acks;
- since = first_soft_ack;
- }
-
- call->acks_latest_ts = skb->tstamp;
- call->acks_first_seq = first_soft_ack;
+ call->acks_latest_ts = ktime_get_real();
+ call->acks_hard_ack = hard_ack;
call->acks_prev_seq = prev_pkt;
- switch (summary.ack_reason) {
- case RXRPC_ACK_PING:
- break;
- default:
- if (acked_serial && after(acked_serial, call->acks_highest_serial))
- call->acks_highest_serial = acked_serial;
- break;
+ if (summary.acked_serial) {
+ switch (summary.ack_reason) {
+ case RXRPC_ACK_PING_RESPONSE:
+ rxrpc_complete_rtt_probe(call, call->acks_latest_ts,
+ summary.acked_serial, summary.ack_serial,
+ rxrpc_rtt_rx_ping_response);
+ break;
+ default:
+ if (after(summary.acked_serial, call->acks_highest_serial))
+ call->acks_highest_serial = summary.acked_serial;
+ summary.rtt_sample_avail = true;
+ break;
+ }
}
/* Parse rwind and mtu sizes if provided. */
if (trailer.maxMTU)
rxrpc_input_ack_trailer(call, skb, &trailer);
- if (first_soft_ack == 0)
+ if (hard_ack + 1 == 0)
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_zero);
/* Ignore ACKs unless we are or have just been transmitting. */
@@ -978,13 +1151,13 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
goto send_response;
}
- if (before(hard_ack, call->acks_hard_ack) ||
+ if (before(hard_ack, call->tx_bottom) ||
after(hard_ack, call->tx_top))
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_outside_window);
if (nr_acks > call->tx_top - hard_ack)
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_sack_overflow);
- if (after(hard_ack, call->acks_hard_ack)) {
+ if (after(hard_ack, call->tx_bottom)) {
if (rxrpc_rotate_tx_window(call, hard_ack, &summary)) {
rxrpc_end_tx_phase(call, false, rxrpc_eproto_unexpected_ack);
goto send_response;
@@ -994,25 +1167,30 @@ static void rxrpc_input_ack(struct rxrpc_call *call, struct sk_buff *skb)
if (nr_acks > 0) {
if (offset > (int)skb->len - nr_acks)
return rxrpc_proto_abort(call, 0, rxrpc_eproto_ackr_short_sack);
- rxrpc_input_soft_acks(call, &summary, skb, first_soft_ack, since);
- rxrpc_get_skb(skb, rxrpc_skb_get_last_nack);
- call->cong_last_nack = skb;
+ rxrpc_input_soft_acks(call, &summary, skb);
}
if (test_bit(RXRPC_CALL_TX_LAST, &call->flags) &&
- summary.nr_acks == call->tx_top - hard_ack &&
+ call->acks_nr_sacks == call->tx_top - hard_ack &&
rxrpc_is_client_call(call))
- rxrpc_propose_ping(call, ack_serial,
+ rxrpc_propose_ping(call, summary.ack_serial,
rxrpc_propose_ack_ping_for_lost_reply);
- rxrpc_congestion_management(call, skb, &summary, acked_serial);
+ /* Drive the congestion management algorithm first and then RACK-TLP as
+ * the latter depends on the state/change in state in the former.
+ */
+ rxrpc_congestion_management(call, &summary);
+ rxrpc_rack_detect_loss_and_arm_timer(call, &summary);
+ rxrpc_tlp_process_ack(call, &summary);
+ if (call->tlp_serial && after_eq(summary.acked_serial, call->tlp_serial))
+ call->tlp_serial = 0;
send_response:
if (summary.ack_reason == RXRPC_ACK_PING)
- rxrpc_send_ACK(call, RXRPC_ACK_PING_RESPONSE, ack_serial,
+ rxrpc_send_ACK(call, RXRPC_ACK_PING_RESPONSE, summary.ack_serial,
rxrpc_propose_ack_respond_to_ping);
else if (sp->hdr.flags & RXRPC_REQUEST_ACK)
- rxrpc_send_ACK(call, RXRPC_ACK_REQUESTED, ack_serial,
+ rxrpc_send_ACK(call, RXRPC_ACK_REQUESTED, summary.ack_serial,
rxrpc_propose_ack_respond_to_ack);
}
@@ -1111,5 +1289,5 @@ void rxrpc_implicit_end_call(struct rxrpc_call *call, struct sk_buff *skb)
break;
}
- rxrpc_input_call_event(call, skb);
+ rxrpc_input_call_event(call);
}
diff --git a/net/rxrpc/input_rack.c b/net/rxrpc/input_rack.c
new file mode 100644
index 000000000000..13c371261e0a
--- /dev/null
+++ b/net/rxrpc/input_rack.c
@@ -0,0 +1,418 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* RACK-TLP [RFC8958] Implementation
+ *
+ * Copyright (C) 2024 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include "ar-internal.h"
+
+static bool rxrpc_rack_sent_after(ktime_t t1, rxrpc_seq_t seq1,
+ ktime_t t2, rxrpc_seq_t seq2)
+{
+ if (ktime_after(t1, t2))
+ return true;
+ return t1 == t2 && after(seq1, seq2);
+}
+
+/*
+ * Mark a packet lost.
+ */
+static void rxrpc_rack_mark_lost(struct rxrpc_call *call,
+ struct rxrpc_txqueue *tq, unsigned int ix)
+{
+ if (__test_and_set_bit(ix, &tq->segment_lost)) {
+ if (__test_and_clear_bit(ix, &tq->segment_retransmitted))
+ call->tx_nr_resent--;
+ } else {
+ call->tx_nr_lost++;
+ }
+ tq->segment_xmit_ts[ix] = UINT_MAX;
+}
+
+/*
+ * Get the transmission time of a packet in the Tx queue.
+ */
+static ktime_t rxrpc_get_xmit_ts(const struct rxrpc_txqueue *tq, unsigned int ix)
+{
+ if (tq->segment_xmit_ts[ix] == UINT_MAX)
+ return KTIME_MAX;
+ return ktime_add_us(tq->xmit_ts_base, tq->segment_xmit_ts[ix]);
+}
+
+/*
+ * Get a bitmask of nack bits for a queue segment and mask off any that aren't
+ * yet reported.
+ */
+static unsigned long rxrpc_tq_nacks(const struct rxrpc_txqueue *tq)
+{
+ unsigned long nacks = ~tq->segment_acked;
+
+ if (tq->nr_reported_acks < RXRPC_NR_TXQUEUE)
+ nacks &= (1UL << tq->nr_reported_acks) - 1;
+ return nacks;
+}
+
+/*
+ * Update the RACK state for the most recently sent packet that has been
+ * delivered [RFC8958 6.2 Step 2].
+ */
+static void rxrpc_rack_update(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary,
+ struct rxrpc_txqueue *tq,
+ unsigned int ix)
+{
+ rxrpc_seq_t seq = tq->qbase + ix;
+ ktime_t xmit_ts = rxrpc_get_xmit_ts(tq, ix);
+ ktime_t rtt = ktime_sub(call->acks_latest_ts, xmit_ts);
+
+ if (__test_and_clear_bit(ix, &tq->segment_lost))
+ call->tx_nr_lost--;
+
+ if (test_bit(ix, &tq->segment_retransmitted)) {
+ /* Use Rx.serial instead of TCP.ACK.ts_option.echo_reply. */
+ if (before(call->acks_highest_serial, tq->segment_serial[ix]))
+ return;
+ if (rtt < minmax_get(&call->min_rtt))
+ return;
+ }
+
+ /* The RACK algorithm requires the segment ACKs to be traversed in
+ * order of segment transmission - but the only thing this seems to
+ * matter for is that RACK.rtt is set to the rtt of the most recently
+ * transmitted segment. We should be able to achieve the same by only
+ * setting RACK.rtt if the xmit time is greater.
+ */
+ if (ktime_after(xmit_ts, call->rack_rtt_ts)) {
+ call->rack_rtt = rtt;
+ call->rack_rtt_ts = xmit_ts;
+ }
+
+ if (rxrpc_rack_sent_after(xmit_ts, seq, call->rack_xmit_ts, call->rack_end_seq)) {
+ call->rack_rtt = rtt;
+ call->rack_xmit_ts = xmit_ts;
+ call->rack_end_seq = seq;
+ }
+}
+
+/*
+ * Detect data segment reordering [RFC8958 6.2 Step 3].
+ */
+static void rxrpc_rack_detect_reordering(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary,
+ struct rxrpc_txqueue *tq,
+ unsigned int ix)
+{
+ rxrpc_seq_t seq = tq->qbase + ix;
+
+ /* Track the highest sequence number so far ACK'd. This is not
+ * necessarily the same as ack.firstPacket + ack.nAcks - 1 as the peer
+ * could put a NACK in the last SACK slot.
+ */
+ if (after(seq, call->rack_fack))
+ call->rack_fack = seq;
+ else if (before(seq, call->rack_fack) &&
+ test_bit(ix, &tq->segment_retransmitted))
+ call->rack_reordering_seen = true;
+}
+
+void rxrpc_input_rack_one(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary,
+ struct rxrpc_txqueue *tq,
+ unsigned int ix)
+{
+ rxrpc_rack_update(call, summary, tq, ix);
+ rxrpc_rack_detect_reordering(call, summary, tq, ix);
+}
+
+void rxrpc_input_rack(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary,
+ struct rxrpc_txqueue *tq,
+ unsigned long new_acks)
+{
+ while (new_acks) {
+ unsigned int ix = __ffs(new_acks);
+
+ __clear_bit(ix, &new_acks);
+ rxrpc_input_rack_one(call, summary, tq, ix);
+ }
+
+ trace_rxrpc_rack_update(call, summary);
+}
+
+/*
+ * Update the reordering window [RFC8958 6.2 Step 4]. Returns the updated
+ * duration of the reordering window.
+ *
+ * Note that the Rx protocol doesn't have a 'DSACK option' per se, but ACKs can
+ * be given a 'DUPLICATE' reason with the serial number referring to the
+ * duplicated DATA packet. Rx does not inform as to whether this was a
+ * reception of the same packet twice or of a retransmission of a packet we
+ * already received (though this could be determined by the transmitter based
+ * on the serial number).
+ */
+static ktime_t rxrpc_rack_update_reo_wnd(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary)
+{
+ rxrpc_seq_t snd_una = call->acks_lowest_nak; /* Lowest unack'd seq */
+ rxrpc_seq_t snd_nxt = call->tx_transmitted + 1; /* Next seq to be sent */
+ bool have_dsack_option = summary->ack_reason == RXRPC_ACK_DUPLICATE;
+ int dup_thresh = 3;
+
+ /* DSACK-based reordering window adaptation */
+ if (!call->rack_dsack_round_none &&
+ after_eq(snd_una, call->rack_dsack_round))
+ call->rack_dsack_round_none = true;
+
+ /* Grow the reordering window per round that sees DSACK. Reset the
+ * window after 16 DSACK-free recoveries.
+ */
+ if (call->rack_dsack_round_none && have_dsack_option) {
+ call->rack_dsack_round_none = false;
+ call->rack_dsack_round = snd_nxt;
+ call->rack_reo_wnd_mult++;
+ call->rack_reo_wnd_persist = 16;
+ } else if (summary->exiting_fast_or_rto_recovery) {
+ call->rack_reo_wnd_persist--;
+ if (call->rack_reo_wnd_persist <= 0)
+ call->rack_reo_wnd_mult = 1;
+ }
+
+ if (!call->rack_reordering_seen) {
+ if (summary->in_fast_or_rto_recovery)
+ return 0;
+ if (call->acks_nr_sacks >= dup_thresh)
+ return 0;
+ }
+
+ return us_to_ktime(umin(call->rack_reo_wnd_mult * minmax_get(&call->min_rtt) / 4,
+ call->srtt_us >> 3));
+}
+
+/*
+ * Detect losses [RFC8958 6.2 Step 5].
+ */
+static ktime_t rxrpc_rack_detect_loss(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary)
+{
+ struct rxrpc_txqueue *tq;
+ ktime_t timeout = 0, lost_after, now = ktime_get_real();
+
+ call->rack_reo_wnd = rxrpc_rack_update_reo_wnd(call, summary);
+ lost_after = ktime_add(call->rack_rtt, call->rack_reo_wnd);
+ trace_rxrpc_rack_scan_loss(call);
+
+ for (tq = call->tx_queue; tq; tq = tq->next) {
+ unsigned long nacks = rxrpc_tq_nacks(tq);
+
+ if (after(tq->qbase, call->tx_transmitted))
+ break;
+ trace_rxrpc_rack_scan_loss_tq(call, tq, nacks);
+
+ /* Skip ones marked lost but not yet retransmitted */
+ nacks &= ~tq->segment_lost | tq->segment_retransmitted;
+
+ while (nacks) {
+ unsigned int ix = __ffs(nacks);
+ rxrpc_seq_t seq = tq->qbase + ix;
+ ktime_t remaining;
+ ktime_t xmit_ts = rxrpc_get_xmit_ts(tq, ix);
+
+ __clear_bit(ix, &nacks);
+
+ if (rxrpc_rack_sent_after(call->rack_xmit_ts, call->rack_end_seq,
+ xmit_ts, seq)) {
+ remaining = ktime_sub(ktime_add(xmit_ts, lost_after), now);
+ if (remaining <= 0) {
+ rxrpc_rack_mark_lost(call, tq, ix);
+ trace_rxrpc_rack_detect_loss(call, summary, seq);
+ } else {
+ timeout = max(remaining, timeout);
+ }
+ }
+ }
+ }
+
+ return timeout;
+}
+
+/*
+ * Detect losses and set a timer to retry the detection [RFC8958 6.2 Step 5].
+ */
+void rxrpc_rack_detect_loss_and_arm_timer(struct rxrpc_call *call,
+ struct rxrpc_ack_summary *summary)
+{
+ ktime_t timeout = rxrpc_rack_detect_loss(call, summary);
+
+ if (timeout) {
+ call->rack_timer_mode = RXRPC_CALL_RACKTIMER_RACK_REORDER;
+ call->rack_timo_at = ktime_add(ktime_get_real(), timeout);
+ trace_rxrpc_rack_timer(call, timeout, false);
+ trace_rxrpc_timer_set(call, timeout, rxrpc_timer_trace_rack_reo);
+ }
+}
+
+/*
+ * Handle RACK-TLP RTO expiration [RFC8958 6.3].
+ */
+static void rxrpc_rack_mark_losses_on_rto(struct rxrpc_call *call)
+{
+ struct rxrpc_txqueue *tq;
+ rxrpc_seq_t snd_una = call->acks_lowest_nak; /* Lowest unack'd seq */
+ ktime_t lost_after = ktime_add(call->rack_rtt, call->rack_reo_wnd);
+ ktime_t deadline = ktime_sub(ktime_get_real(), lost_after);
+
+ for (tq = call->tx_queue; tq; tq = tq->next) {
+ unsigned long unacked = ~tq->segment_acked;
+
+ trace_rxrpc_rack_mark_loss_tq(call, tq);
+ while (unacked) {
+ unsigned int ix = __ffs(unacked);
+ rxrpc_seq_t seq = tq->qbase + ix;
+ ktime_t xmit_ts = rxrpc_get_xmit_ts(tq, ix);
+
+ if (after(seq, call->tx_transmitted))
+ return;
+ __clear_bit(ix, &unacked);
+
+ if (seq == snd_una ||
+ ktime_before(xmit_ts, deadline))
+ rxrpc_rack_mark_lost(call, tq, ix);
+ }
+ }
+}
+
+/*
+ * Calculate the TLP loss probe timeout (PTO) [RFC8958 7.2].
+ */
+ktime_t rxrpc_tlp_calc_pto(struct rxrpc_call *call, ktime_t now)
+{
+ unsigned int flight_size = rxrpc_tx_in_flight(call);
+ ktime_t rto_at = ktime_add(call->tx_last_sent,
+ rxrpc_get_rto_backoff(call, false));
+ ktime_t pto;
+
+ if (call->rtt_count > 0) {
+ /* Use 2*SRTT as the timeout. */
+ pto = ns_to_ktime(call->srtt_us * NSEC_PER_USEC / 4);
+ if (flight_size)
+ pto = ktime_add(pto, call->tlp_max_ack_delay);
+ } else {
+ pto = NSEC_PER_SEC;
+ }
+
+ if (ktime_after(ktime_add(now, pto), rto_at))
+ pto = ktime_sub(rto_at, now);
+ return pto;
+}
+
+/*
+ * Send a TLP loss probe on PTO expiration [RFC8958 7.3].
+ */
+void rxrpc_tlp_send_probe(struct rxrpc_call *call)
+{
+ unsigned int in_flight = rxrpc_tx_in_flight(call);
+
+ if (after_eq(call->acks_hard_ack, call->tx_transmitted))
+ return; /* Everything we transmitted has been acked. */
+
+ /* There must be no other loss probe still in flight and we need to
+ * have taken a new RTT sample since last probe or the start of
+ * connection.
+ */
+ if (!call->tlp_serial &&
+ call->tlp_rtt_taken != call->rtt_taken) {
+ call->tlp_is_retrans = false;
+ if (after(call->send_top, call->tx_transmitted) &&
+ rxrpc_tx_window_space(call) > 0) {
+ /* Transmit the lowest-sequence unsent DATA */
+ call->tx_last_serial = 0;
+ rxrpc_transmit_some_data(call, 1, rxrpc_txdata_tlp_new_data);
+ call->tlp_serial = call->tx_last_serial;
+ call->tlp_seq = call->tx_transmitted;
+ trace_rxrpc_tlp_probe(call, rxrpc_tlp_probe_trace_transmit_new);
+ in_flight = rxrpc_tx_in_flight(call);
+ } else {
+ /* Retransmit the highest-sequence DATA sent */
+ call->tx_last_serial = 0;
+ rxrpc_resend_tlp(call);
+ call->tlp_is_retrans = true;
+ trace_rxrpc_tlp_probe(call, rxrpc_tlp_probe_trace_retransmit);
+ }
+ } else {
+ trace_rxrpc_tlp_probe(call, rxrpc_tlp_probe_trace_busy);
+ }
+
+ if (in_flight != 0) {
+ ktime_t rto = rxrpc_get_rto_backoff(call, false);
+
+ call->rack_timer_mode = RXRPC_CALL_RACKTIMER_RTO;
+ call->rack_timo_at = ktime_add(ktime_get_real(), rto);
+ trace_rxrpc_rack_timer(call, rto, false);
+ trace_rxrpc_timer_set(call, rto, rxrpc_timer_trace_rack_rto);
+ }
+}
+
+/*
+ * Detect losses using the ACK of a TLP loss probe [RFC8958 7.4].
+ */
+void rxrpc_tlp_process_ack(struct rxrpc_call *call, struct rxrpc_ack_summary *summary)
+{
+ if (!call->tlp_serial || after(call->tlp_seq, call->acks_hard_ack))
+ return;
+
+ if (!call->tlp_is_retrans) {
+ /* TLP of new data delivered */
+ trace_rxrpc_tlp_ack(call, summary, rxrpc_tlp_ack_trace_new_data);
+ call->tlp_serial = 0;
+ } else if (summary->ack_reason == RXRPC_ACK_DUPLICATE &&
+ summary->acked_serial == call->tlp_serial) {
+ /* General Case: Detected packet losses using RACK [7.4.1] */
+ trace_rxrpc_tlp_ack(call, summary, rxrpc_tlp_ack_trace_dup_acked);
+ call->tlp_serial = 0;
+ } else if (after(call->acks_hard_ack, call->tlp_seq)) {
+ /* Repaired the single loss */
+ trace_rxrpc_tlp_ack(call, summary, rxrpc_tlp_ack_trace_hard_beyond);
+ call->tlp_serial = 0;
+ // TODO: Invoke congestion control to react to the loss
+ // event the probe has repaired
+ } else if (summary->tlp_probe_acked) {
+ trace_rxrpc_tlp_ack(call, summary, rxrpc_tlp_ack_trace_acked);
+ /* Special Case: Detected a single loss repaired by the loss
+ * probe [7.4.2]
+ */
+ call->tlp_serial = 0;
+ } else {
+ trace_rxrpc_tlp_ack(call, summary, rxrpc_tlp_ack_trace_incomplete);
+ }
+}
+
+/*
+ * Handle RACK timer expiration; returns true to request a resend.
+ */
+void rxrpc_rack_timer_expired(struct rxrpc_call *call, ktime_t overran_by)
+{
+ struct rxrpc_ack_summary summary = {};
+ enum rxrpc_rack_timer_mode mode = call->rack_timer_mode;
+
+ trace_rxrpc_rack_timer(call, overran_by, true);
+ call->rack_timer_mode = RXRPC_CALL_RACKTIMER_OFF;
+
+ switch (mode) {
+ case RXRPC_CALL_RACKTIMER_RACK_REORDER:
+ rxrpc_rack_detect_loss_and_arm_timer(call, &summary);
+ break;
+ case RXRPC_CALL_RACKTIMER_TLP_PTO:
+ rxrpc_tlp_send_probe(call);
+ break;
+ case RXRPC_CALL_RACKTIMER_RTO:
+ // Might need to poke the congestion algo in some way
+ rxrpc_rack_mark_losses_on_rto(call);
+ break;
+ //case RXRPC_CALL_RACKTIMER_ZEROWIN:
+ default:
+ pr_warn("Unexpected rack timer %u", call->rack_timer_mode);
+ }
+}
diff --git a/net/rxrpc/insecure.c b/net/rxrpc/insecure.c
index 6716c021a532..e068f9b79d02 100644
--- a/net/rxrpc/insecure.c
+++ b/net/rxrpc/insecure.c
@@ -19,11 +19,14 @@ static int none_init_connection_security(struct rxrpc_connection *conn,
*/
static struct rxrpc_txbuf *none_alloc_txbuf(struct rxrpc_call *call, size_t remain, gfp_t gfp)
{
- return rxrpc_alloc_data_txbuf(call, min_t(size_t, remain, RXRPC_JUMBO_DATALEN), 1, gfp);
+ return rxrpc_alloc_data_txbuf(call, umin(remain, RXRPC_JUMBO_DATALEN), 1, gfp);
}
static int none_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
{
+ txb->pkt_len = txb->len;
+ if (txb->len == RXRPC_JUMBO_DATALEN)
+ txb->jumboable = true;
return 0;
}
diff --git a/net/rxrpc/io_thread.c b/net/rxrpc/io_thread.c
index 07c74c77d802..64f8d77b8731 100644
--- a/net/rxrpc/io_thread.c
+++ b/net/rxrpc/io_thread.c
@@ -338,7 +338,6 @@ static int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
struct rxrpc_channel *chan;
struct rxrpc_call *call = NULL;
unsigned int channel;
- bool ret;
if (sp->hdr.securityIndex != conn->security_ix)
return rxrpc_direct_abort(skb, rxrpc_eproto_wrong_security,
@@ -364,6 +363,12 @@ static int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
if (sp->hdr.callNumber == 0)
return rxrpc_input_conn_packet(conn, skb);
+ /* Deal with path MTU discovery probing. */
+ if (sp->hdr.type == RXRPC_PACKET_TYPE_ACK &&
+ conn->pmtud_probe &&
+ after_eq(sp->ack.acked_serial, conn->pmtud_probe))
+ rxrpc_input_probe_for_pmtud(conn, sp->ack.acked_serial, false);
+
/* Call-bound packets are routed by connection channel. */
channel = sp->hdr.cid & RXRPC_CHANNELMASK;
chan = &conn->channels[channel];
@@ -419,9 +424,9 @@ static int rxrpc_input_packet_on_conn(struct rxrpc_connection *conn,
peer_srx, skb);
}
- ret = rxrpc_input_call_event(call, skb);
+ rxrpc_queue_rx_call_packet(call, skb);
rxrpc_put_call(call, rxrpc_call_put_input);
- return ret;
+ return true;
}
/*
@@ -438,6 +443,8 @@ int rxrpc_io_thread(void *data)
ktime_t now;
#endif
bool should_stop;
+ LIST_HEAD(conn_attend_q);
+ LIST_HEAD(call_attend_q);
complete(&local->io_thread_ready);
@@ -448,43 +455,26 @@ int rxrpc_io_thread(void *data)
for (;;) {
rxrpc_inc_stat(local->rxnet, stat_io_loop);
- /* Deal with connections that want immediate attention. */
- conn = list_first_entry_or_null(&local->conn_attend_q,
- struct rxrpc_connection,
- attend_link);
- if (conn) {
- spin_lock_bh(&local->lock);
- list_del_init(&conn->attend_link);
- spin_unlock_bh(&local->lock);
-
- rxrpc_input_conn_event(conn, NULL);
- rxrpc_put_connection(conn, rxrpc_conn_put_poke);
- continue;
+ /* Inject a delay into packets if requested. */
+#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
+ now = ktime_get_real();
+ while ((skb = skb_peek(&local->rx_delay_queue))) {
+ if (ktime_before(now, skb->tstamp))
+ break;
+ skb = skb_dequeue(&local->rx_delay_queue);
+ skb_queue_tail(&local->rx_queue, skb);
}
+#endif
- if (test_and_clear_bit(RXRPC_CLIENT_CONN_REAP_TIMER,
- &local->client_conn_flags))
- rxrpc_discard_expired_client_conns(local);
-
- /* Deal with calls that want immediate attention. */
- if ((call = list_first_entry_or_null(&local->call_attend_q,
- struct rxrpc_call,
- attend_link))) {
- spin_lock_bh(&local->lock);
- list_del_init(&call->attend_link);
- spin_unlock_bh(&local->lock);
-
- trace_rxrpc_call_poked(call);
- rxrpc_input_call_event(call, NULL);
- rxrpc_put_call(call, rxrpc_call_put_poke);
- continue;
+ if (!skb_queue_empty(&local->rx_queue)) {
+ spin_lock_irq(&local->rx_queue.lock);
+ skb_queue_splice_tail_init(&local->rx_queue, &rx_queue);
+ spin_unlock_irq(&local->rx_queue.lock);
+ trace_rxrpc_iothread_rx(local, skb_queue_len(&rx_queue));
}
- if (!list_empty(&local->new_client_calls))
- rxrpc_connect_client_calls(local);
-
- /* Process received packets and errors. */
- if ((skb = __skb_dequeue(&rx_queue))) {
+ /* Distribute packets and errors. */
+ while ((skb = __skb_dequeue(&rx_queue))) {
struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
switch (skb->mark) {
case RXRPC_SKB_MARK_PACKET:
@@ -508,27 +498,46 @@ int rxrpc_io_thread(void *data)
rxrpc_free_skb(skb, rxrpc_skb_put_unknown);
break;
}
- continue;
}
- /* Inject a delay into packets if requested. */
-#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
- now = ktime_get_real();
- while ((skb = skb_peek(&local->rx_delay_queue))) {
- if (ktime_before(now, skb->tstamp))
- break;
- skb = skb_dequeue(&local->rx_delay_queue);
- skb_queue_tail(&local->rx_queue, skb);
+ /* Deal with connections that want immediate attention. */
+ spin_lock_irq(&local->lock);
+ list_splice_tail_init(&local->conn_attend_q, &conn_attend_q);
+ spin_unlock_irq(&local->lock);
+
+ while ((conn = list_first_entry_or_null(&conn_attend_q,
+ struct rxrpc_connection,
+ attend_link))) {
+ spin_lock_irq(&local->lock);
+ list_del_init(&conn->attend_link);
+ spin_unlock_irq(&local->lock);
+ rxrpc_input_conn_event(conn, NULL);
+ rxrpc_put_connection(conn, rxrpc_conn_put_poke);
}
-#endif
- if (!skb_queue_empty(&local->rx_queue)) {
- spin_lock_irq(&local->rx_queue.lock);
- skb_queue_splice_tail_init(&local->rx_queue, &rx_queue);
- spin_unlock_irq(&local->rx_queue.lock);
- continue;
+ if (test_and_clear_bit(RXRPC_CLIENT_CONN_REAP_TIMER,
+ &local->client_conn_flags))
+ rxrpc_discard_expired_client_conns(local);
+
+ /* Deal with calls that want immediate attention. */
+ spin_lock_irq(&local->lock);
+ list_splice_tail_init(&local->call_attend_q, &call_attend_q);
+ spin_unlock_irq(&local->lock);
+
+ while ((call = list_first_entry_or_null(&call_attend_q,
+ struct rxrpc_call,
+ attend_link))) {
+ spin_lock_irq(&local->lock);
+ list_del_init(&call->attend_link);
+ spin_unlock_irq(&local->lock);
+ trace_rxrpc_call_poked(call);
+ rxrpc_input_call_event(call);
+ rxrpc_put_call(call, rxrpc_call_put_poke);
}
+ if (!list_empty(&local->new_client_calls))
+ rxrpc_connect_client_calls(local);
+
set_current_state(TASK_INTERRUPTIBLE);
should_stop = kthread_should_stop();
if (!skb_queue_empty(&local->rx_queue) ||
@@ -558,7 +567,7 @@ int rxrpc_io_thread(void *data)
}
timeout = nsecs_to_jiffies(delay_ns);
- timeout = max(timeout, 1UL);
+ timeout = umax(timeout, 1);
schedule_timeout(timeout);
__set_current_state(TASK_RUNNING);
continue;
diff --git a/net/rxrpc/local_object.c b/net/rxrpc/local_object.c
index 2792d2304605..a74a4b43904f 100644
--- a/net/rxrpc/local_object.c
+++ b/net/rxrpc/local_object.c
@@ -215,9 +215,6 @@ static int rxrpc_open_socket(struct rxrpc_local *local, struct net *net)
/* we want to set the don't fragment bit */
rxrpc_local_dont_fragment(local, true);
-
- /* We want receive timestamps. */
- sock_enable_timestamps(usk);
break;
default:
diff --git a/net/rxrpc/misc.c b/net/rxrpc/misc.c
index 657cf35089a6..8fcc8139d771 100644
--- a/net/rxrpc/misc.c
+++ b/net/rxrpc/misc.c
@@ -46,13 +46,13 @@ unsigned int rxrpc_rx_window_size = 255;
* Maximum Rx MTU size. This indicates to the sender the size of jumbo packet
* made by gluing normal packets together that we're willing to handle.
*/
-unsigned int rxrpc_rx_mtu = 5692;
+unsigned int rxrpc_rx_mtu = RXRPC_JUMBO(46);
/*
* The maximum number of fragments in a received jumbo packet that we tell the
* sender that we're willing to handle.
*/
-unsigned int rxrpc_rx_jumbo_max = 4;
+unsigned int rxrpc_rx_jumbo_max = 46;
#ifdef CONFIG_AF_RXRPC_INJECT_RX_DELAY
/*
diff --git a/net/rxrpc/output.c b/net/rxrpc/output.c
index 5ea9601efd05..6f7a125d6e90 100644
--- a/net/rxrpc/output.c
+++ b/net/rxrpc/output.c
@@ -72,22 +72,96 @@ static void rxrpc_set_keepalive(struct rxrpc_call *call, ktime_t now)
}
/*
+ * Allocate transmission buffers for an ACK and attach them to local->kv[].
+ */
+static int rxrpc_alloc_ack(struct rxrpc_call *call, size_t sack_size)
+{
+ struct rxrpc_wire_header *whdr;
+ struct rxrpc_acktrailer *trailer;
+ struct rxrpc_ackpacket *ack;
+ struct kvec *kv = call->local->kvec;
+ gfp_t gfp = rcu_read_lock_held() ? GFP_ATOMIC | __GFP_NOWARN : GFP_NOFS;
+ void *buf, *buf2 = NULL;
+ u8 *filler;
+
+ buf = page_frag_alloc(&call->local->tx_alloc,
+ sizeof(*whdr) + sizeof(*ack) + 1 + 3 + sizeof(*trailer), gfp);
+ if (!buf)
+ return -ENOMEM;
+
+ if (sack_size) {
+ buf2 = page_frag_alloc(&call->local->tx_alloc, sack_size, gfp);
+ if (!buf2) {
+ page_frag_free(buf);
+ return -ENOMEM;
+ }
+ }
+
+ whdr = buf;
+ ack = buf + sizeof(*whdr);
+ filler = buf + sizeof(*whdr) + sizeof(*ack) + 1;
+ trailer = buf + sizeof(*whdr) + sizeof(*ack) + 1 + 3;
+
+ kv[0].iov_base = whdr;
+ kv[0].iov_len = sizeof(*whdr) + sizeof(*ack);
+ kv[1].iov_base = buf2;
+ kv[1].iov_len = sack_size;
+ kv[2].iov_base = filler;
+ kv[2].iov_len = 3 + sizeof(*trailer);
+ return 3; /* Number of kvec[] used. */
+}
+
+static void rxrpc_free_ack(struct rxrpc_call *call)
+{
+ page_frag_free(call->local->kvec[0].iov_base);
+ if (call->local->kvec[1].iov_base)
+ page_frag_free(call->local->kvec[1].iov_base);
+}
+
+/*
+ * Record the beginning of an RTT probe.
+ */
+static void rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t serial,
+ ktime_t now, enum rxrpc_rtt_tx_trace why)
+{
+ unsigned long avail = call->rtt_avail;
+ int rtt_slot = 9;
+
+ if (!(avail & RXRPC_CALL_RTT_AVAIL_MASK))
+ goto no_slot;
+
+ rtt_slot = __ffs(avail & RXRPC_CALL_RTT_AVAIL_MASK);
+ if (!test_and_clear_bit(rtt_slot, &call->rtt_avail))
+ goto no_slot;
+
+ call->rtt_serial[rtt_slot] = serial;
+ call->rtt_sent_at[rtt_slot] = now;
+ smp_wmb(); /* Write data before avail bit */
+ set_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
+
+ trace_rxrpc_rtt_tx(call, why, rtt_slot, serial);
+ return;
+
+no_slot:
+ trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_no_slot, rtt_slot, serial);
+}
+
+/*
* Fill out an ACK packet.
*/
-static void rxrpc_fill_out_ack(struct rxrpc_call *call,
- struct rxrpc_txbuf *txb,
- u8 ack_reason,
- rxrpc_serial_t serial)
+static int rxrpc_fill_out_ack(struct rxrpc_call *call, int nr_kv, u8 ack_reason,
+ rxrpc_serial_t serial_to_ack, rxrpc_serial_t *_ack_serial)
{
- struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base;
- struct rxrpc_acktrailer *trailer = txb->kvec[2].iov_base + 3;
+ struct kvec *kv = call->local->kvec;
+ struct rxrpc_wire_header *whdr = kv[0].iov_base;
+ struct rxrpc_acktrailer *trailer = kv[2].iov_base + 3;
struct rxrpc_ackpacket *ack = (struct rxrpc_ackpacket *)(whdr + 1);
- unsigned int qsize, sack, wrap, to;
+ unsigned int qsize, sack, wrap, to, max_mtu, if_mtu;
rxrpc_seq_t window, wtop;
+ ktime_t now = ktime_get_real();
int rsize;
- u32 mtu, jmax;
- u8 *filler = txb->kvec[2].iov_base;
- u8 *sackp = txb->kvec[1].iov_base;
+ u8 *filler = kv[2].iov_base;
+ u8 *sackp = kv[1].iov_base;
rxrpc_inc_stat(call->rxnet, stat_tx_ack_fill);
@@ -95,14 +169,25 @@ static void rxrpc_fill_out_ack(struct rxrpc_call *call,
wtop = call->ackr_wtop;
sack = call->ackr_sack_base % RXRPC_SACK_SIZE;
+ *_ack_serial = rxrpc_get_next_serial(call->conn);
+
+ whdr->epoch = htonl(call->conn->proto.epoch);
+ whdr->cid = htonl(call->cid);
+ whdr->callNumber = htonl(call->call_id);
+ whdr->serial = htonl(*_ack_serial);
whdr->seq = 0;
whdr->type = RXRPC_PACKET_TYPE_ACK;
- txb->flags |= RXRPC_SLOW_START_OK;
+ whdr->flags = call->conn->out_clientflag | RXRPC_SLOW_START_OK;
+ whdr->userStatus = 0;
+ whdr->securityIndex = call->security_ix;
+ whdr->_rsvd = 0;
+ whdr->serviceId = htons(call->dest_srx.srx_service);
+
ack->bufferSpace = 0;
ack->maxSkew = 0;
ack->firstPacket = htonl(window);
ack->previousPacket = htonl(call->rx_highest_seq);
- ack->serial = htonl(serial);
+ ack->serial = htonl(serial_to_ack);
ack->reason = ack_reason;
ack->nAcks = wtop - window;
filler[0] = 0;
@@ -110,15 +195,13 @@ static void rxrpc_fill_out_ack(struct rxrpc_call *call,
filler[2] = 0;
if (ack_reason == RXRPC_ACK_PING)
- txb->flags |= RXRPC_REQUEST_ACK;
+ whdr->flags |= RXRPC_REQUEST_ACK;
if (after(wtop, window)) {
- txb->len += ack->nAcks;
- txb->kvec[1].iov_base = sackp;
- txb->kvec[1].iov_len = ack->nAcks;
+ kv[1].iov_len = ack->nAcks;
wrap = RXRPC_SACK_SIZE - sack;
- to = min_t(unsigned int, ack->nAcks, RXRPC_SACK_SIZE);
+ to = umin(ack->nAcks, RXRPC_SACK_SIZE);
if (sack + ack->nAcks <= RXRPC_SACK_SIZE) {
memcpy(sackp, call->ackr_sack_table + sack, ack->nAcks);
@@ -132,56 +215,42 @@ static void rxrpc_fill_out_ack(struct rxrpc_call *call,
ack->reason = RXRPC_ACK_IDLE;
}
- mtu = call->peer->if_mtu;
- mtu -= call->peer->hdrsize;
- jmax = rxrpc_rx_jumbo_max;
qsize = (window - 1) - call->rx_consumed;
rsize = max_t(int, call->rx_winsize - qsize, 0);
- txb->ack_rwind = rsize;
- trailer->maxMTU = htonl(rxrpc_rx_mtu);
- trailer->ifMTU = htonl(mtu);
- trailer->rwind = htonl(rsize);
- trailer->jumbo_max = htonl(jmax);
-}
-
-/*
- * Record the beginning of an RTT probe.
- */
-static void rxrpc_begin_rtt_probe(struct rxrpc_call *call, rxrpc_serial_t serial,
- ktime_t now, enum rxrpc_rtt_tx_trace why)
-{
- unsigned long avail = call->rtt_avail;
- int rtt_slot = 9;
-
- if (!(avail & RXRPC_CALL_RTT_AVAIL_MASK))
- goto no_slot;
-
- rtt_slot = __ffs(avail & RXRPC_CALL_RTT_AVAIL_MASK);
- if (!test_and_clear_bit(rtt_slot, &call->rtt_avail))
- goto no_slot;
- call->rtt_serial[rtt_slot] = serial;
- call->rtt_sent_at[rtt_slot] = now;
- smp_wmb(); /* Write data before avail bit */
- set_bit(rtt_slot + RXRPC_CALL_RTT_PEND_SHIFT, &call->rtt_avail);
+ if_mtu = call->peer->if_mtu - call->peer->hdrsize;
+ if (call->peer->ackr_adv_pmtud) {
+ max_mtu = umax(call->peer->max_data, rxrpc_rx_mtu);
+ } else {
+ if_mtu = umin(if_mtu, 1444);
+ max_mtu = if_mtu;
+ }
- trace_rxrpc_rtt_tx(call, why, rtt_slot, serial);
- return;
+ trailer->maxMTU = htonl(max_mtu);
+ trailer->ifMTU = htonl(if_mtu);
+ trailer->rwind = htonl(rsize);
+ trailer->jumbo_max = 0; /* Advertise pmtu discovery */
-no_slot:
- trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_no_slot, rtt_slot, serial);
+ if (ack_reason == RXRPC_ACK_PING)
+ rxrpc_begin_rtt_probe(call, *_ack_serial, now, rxrpc_rtt_tx_ping);
+ if (whdr->flags & RXRPC_REQUEST_ACK)
+ call->rtt_last_req = now;
+ rxrpc_set_keepalive(call, now);
+ return nr_kv;
}
/*
* Transmit an ACK packet.
*/
-static void rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
+static void rxrpc_send_ack_packet(struct rxrpc_call *call, int nr_kv, size_t len,
+ rxrpc_serial_t serial, enum rxrpc_propose_ack_trace why)
{
- struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base;
+ struct kvec *kv = call->local->kvec;
+ struct rxrpc_wire_header *whdr = kv[0].iov_base;
+ struct rxrpc_acktrailer *trailer = kv[2].iov_base + 3;
struct rxrpc_connection *conn;
struct rxrpc_ackpacket *ack = (struct rxrpc_ackpacket *)(whdr + 1);
struct msghdr msg;
- ktime_t now;
int ret;
if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
@@ -195,33 +264,34 @@ static void rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
msg.msg_controllen = 0;
msg.msg_flags = MSG_SPLICE_PAGES;
- whdr->flags = txb->flags & RXRPC_TXBUF_WIRE_FLAGS;
-
- txb->serial = rxrpc_get_next_serial(conn);
- whdr->serial = htonl(txb->serial);
- trace_rxrpc_tx_ack(call->debug_id, txb->serial,
+ trace_rxrpc_tx_ack(call->debug_id, serial,
ntohl(ack->firstPacket),
ntohl(ack->serial), ack->reason, ack->nAcks,
- txb->ack_rwind);
+ ntohl(trailer->rwind), why);
rxrpc_inc_stat(call->rxnet, stat_tx_ack_send);
- iov_iter_kvec(&msg.msg_iter, WRITE, txb->kvec, txb->nr_kvec, txb->len);
- rxrpc_local_dont_fragment(conn->local, false);
- ret = do_udp_sendmsg(conn->local->socket, &msg, txb->len);
+ iov_iter_kvec(&msg.msg_iter, WRITE, kv, nr_kv, len);
+ rxrpc_local_dont_fragment(conn->local, why == rxrpc_propose_ack_ping_for_mtu_probe);
+
+ ret = do_udp_sendmsg(conn->local->socket, &msg, len);
call->peer->last_tx_at = ktime_get_seconds();
if (ret < 0) {
- trace_rxrpc_tx_fail(call->debug_id, txb->serial, ret,
+ trace_rxrpc_tx_fail(call->debug_id, serial, ret,
rxrpc_tx_point_call_ack);
+ if (why == rxrpc_propose_ack_ping_for_mtu_probe &&
+ ret == -EMSGSIZE)
+ rxrpc_input_probe_for_pmtud(conn, serial, true);
} else {
trace_rxrpc_tx_packet(call->debug_id, whdr,
rxrpc_tx_point_call_ack);
- now = ktime_get_real();
- if (ack->reason == RXRPC_ACK_PING)
- rxrpc_begin_rtt_probe(call, txb->serial, now, rxrpc_rtt_tx_ping);
- if (txb->flags & RXRPC_REQUEST_ACK)
- call->peer->rtt_last_req = now;
- rxrpc_set_keepalive(call, now);
+ if (why == rxrpc_propose_ack_ping_for_mtu_probe) {
+ call->peer->pmtud_pending = false;
+ call->peer->pmtud_probing = true;
+ call->conn->pmtud_probe = serial;
+ call->conn->pmtud_call = call->debug_id;
+ trace_rxrpc_pmtud_tx(call);
+ }
}
rxrpc_tx_backoff(call, ret);
}
@@ -230,31 +300,62 @@ static void rxrpc_send_ack_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
* Queue an ACK for immediate transmission.
*/
void rxrpc_send_ACK(struct rxrpc_call *call, u8 ack_reason,
- rxrpc_serial_t serial, enum rxrpc_propose_ack_trace why)
+ rxrpc_serial_t serial_to_ack, enum rxrpc_propose_ack_trace why)
{
- struct rxrpc_txbuf *txb;
+ struct kvec *kv = call->local->kvec;
+ rxrpc_serial_t ack_serial;
+ size_t len;
+ int nr_kv;
if (test_bit(RXRPC_CALL_DISCONNECTED, &call->flags))
return;
rxrpc_inc_stat(call->rxnet, stat_tx_acks[ack_reason]);
- txb = rxrpc_alloc_ack_txbuf(call, call->ackr_wtop - call->ackr_window);
- if (!txb) {
+ nr_kv = rxrpc_alloc_ack(call, call->ackr_wtop - call->ackr_window);
+ if (nr_kv < 0) {
kleave(" = -ENOMEM");
return;
}
- txb->ack_why = why;
+ nr_kv = rxrpc_fill_out_ack(call, nr_kv, ack_reason, serial_to_ack, &ack_serial);
+ len = kv[0].iov_len;
+ len += kv[1].iov_len;
+ len += kv[2].iov_len;
+
+ /* Extend a path MTU probe ACK. */
+ if (why == rxrpc_propose_ack_ping_for_mtu_probe) {
+ size_t probe_mtu = call->peer->pmtud_trial + sizeof(struct rxrpc_wire_header);
+
+ if (len > probe_mtu)
+ goto skip;
+ while (len < probe_mtu) {
+ size_t part = umin(probe_mtu - len, PAGE_SIZE);
+
+ kv[nr_kv].iov_base = page_address(ZERO_PAGE(0));
+ kv[nr_kv].iov_len = part;
+ len += part;
+ nr_kv++;
+ }
+ }
- rxrpc_fill_out_ack(call, txb, ack_reason, serial);
call->ackr_nr_unacked = 0;
atomic_set(&call->ackr_nr_consumed, 0);
clear_bit(RXRPC_CALL_RX_IS_IDLE, &call->flags);
- trace_rxrpc_send_ack(call, why, ack_reason, serial);
- rxrpc_send_ack_packet(call, txb);
- rxrpc_put_txbuf(txb, rxrpc_txbuf_put_ack_tx);
+ trace_rxrpc_send_ack(call, why, ack_reason, ack_serial);
+ rxrpc_send_ack_packet(call, nr_kv, len, ack_serial, why);
+skip:
+ rxrpc_free_ack(call);
+}
+
+/*
+ * Send an ACK probe for path MTU discovery.
+ */
+void rxrpc_send_probe_for_pmtud(struct rxrpc_call *call)
+{
+ rxrpc_send_ACK(call, RXRPC_ACK_PING, 0,
+ rxrpc_propose_ack_ping_for_mtu_probe);
}
/*
@@ -324,14 +425,21 @@ int rxrpc_send_abort_packet(struct rxrpc_call *call)
/*
* Prepare a (sub)packet for transmission.
*/
-static void rxrpc_prepare_data_subpacket(struct rxrpc_call *call, struct rxrpc_txbuf *txb,
- rxrpc_serial_t serial)
+static size_t rxrpc_prepare_data_subpacket(struct rxrpc_call *call,
+ struct rxrpc_send_data_req *req,
+ struct rxrpc_txbuf *txb,
+ rxrpc_serial_t serial, int subpkt)
{
struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base;
+ struct rxrpc_jumbo_header *jumbo = (void *)(whdr + 1) - sizeof(*jumbo);
enum rxrpc_req_ack_trace why;
struct rxrpc_connection *conn = call->conn;
+ struct kvec *kv = &call->local->kvec[subpkt];
+ size_t len = txb->pkt_len;
+ bool last;
+ u8 flags;
- _enter("%x,{%d}", txb->seq, txb->len);
+ _enter("%x,%zd", txb->seq, len);
txb->serial = serial;
@@ -339,6 +447,15 @@ static void rxrpc_prepare_data_subpacket(struct rxrpc_call *call, struct rxrpc_t
txb->seq == 1)
whdr->userStatus = RXRPC_USERSTATUS_SERVICE_UPGRADE;
+ txb->flags &= ~RXRPC_REQUEST_ACK;
+ flags = txb->flags & RXRPC_TXBUF_WIRE_FLAGS;
+ last = txb->flags & RXRPC_LAST_PACKET;
+
+ if (subpkt < req->n - 1) {
+ len = RXRPC_JUMBO_DATALEN;
+ goto dont_set_request_ack;
+ }
+
/* If our RTT cache needs working on, request an ACK. Also request
* ACKs if a DATA packet appears to have been lost.
*
@@ -346,113 +463,188 @@ static void rxrpc_prepare_data_subpacket(struct rxrpc_call *call, struct rxrpc_t
* service call, lest OpenAFS incorrectly send us an ACK with some
* soft-ACKs in it and then never follow up with a proper hard ACK.
*/
- if (txb->flags & RXRPC_REQUEST_ACK)
- why = rxrpc_reqack_already_on;
- else if ((txb->flags & RXRPC_LAST_PACKET) && rxrpc_sending_to_client(txb))
+ if (last && rxrpc_sending_to_client(txb))
why = rxrpc_reqack_no_srv_last;
else if (test_and_clear_bit(RXRPC_CALL_EV_ACK_LOST, &call->events))
why = rxrpc_reqack_ack_lost;
else if (txb->flags & RXRPC_TXBUF_RESENT)
why = rxrpc_reqack_retrans;
- else if (call->cong_mode == RXRPC_CALL_SLOW_START && call->cong_cwnd <= 2)
+ else if (call->cong_ca_state == RXRPC_CA_SLOW_START && call->cong_cwnd <= RXRPC_MIN_CWND)
why = rxrpc_reqack_slow_start;
else if (call->tx_winsize <= 2)
why = rxrpc_reqack_small_txwin;
- else if (call->peer->rtt_count < 3 && txb->seq & 1)
+ else if (call->rtt_count < 3)
why = rxrpc_reqack_more_rtt;
- else if (ktime_before(ktime_add_ms(call->peer->rtt_last_req, 1000), ktime_get_real()))
+ else if (ktime_before(ktime_add_ms(call->rtt_last_req, 1000), ktime_get_real()))
why = rxrpc_reqack_old_rtt;
+ else if (!last && !after(READ_ONCE(call->send_top), txb->seq))
+ why = rxrpc_reqack_app_stall;
else
goto dont_set_request_ack;
rxrpc_inc_stat(call->rxnet, stat_why_req_ack[why]);
trace_rxrpc_req_ack(call->debug_id, txb->seq, why);
- if (why != rxrpc_reqack_no_srv_last)
- txb->flags |= RXRPC_REQUEST_ACK;
+ if (why != rxrpc_reqack_no_srv_last) {
+ flags |= RXRPC_REQUEST_ACK;
+ trace_rxrpc_rtt_tx(call, rxrpc_rtt_tx_data, -1, serial);
+ call->rtt_last_req = req->now;
+ }
dont_set_request_ack:
- whdr->flags = txb->flags & RXRPC_TXBUF_WIRE_FLAGS;
- whdr->serial = htonl(txb->serial);
- whdr->cksum = txb->cksum;
+ /* The jumbo header overlays the wire header in the txbuf. */
+ if (subpkt < req->n - 1)
+ flags |= RXRPC_JUMBO_PACKET;
+ else
+ flags &= ~RXRPC_JUMBO_PACKET;
+ if (subpkt == 0) {
+ whdr->flags = flags;
+ whdr->serial = htonl(txb->serial);
+ whdr->cksum = txb->cksum;
+ whdr->serviceId = htons(conn->service_id);
+ kv->iov_base = whdr;
+ len += sizeof(*whdr);
+ } else {
+ jumbo->flags = flags;
+ jumbo->pad = 0;
+ jumbo->cksum = txb->cksum;
+ kv->iov_base = jumbo;
+ len += sizeof(*jumbo);
+ }
- trace_rxrpc_tx_data(call, txb->seq, txb->serial, txb->flags, false);
+ trace_rxrpc_tx_data(call, txb->seq, txb->serial, flags, req->trace);
+ kv->iov_len = len;
+ return len;
}
/*
- * Prepare a packet for transmission.
+ * Prepare a transmission queue object for initial transmission. Returns the
+ * number of microseconds since the transmission queue base timestamp.
*/
-static size_t rxrpc_prepare_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
+static unsigned int rxrpc_prepare_txqueue(struct rxrpc_txqueue *tq,
+ struct rxrpc_send_data_req *req)
{
- rxrpc_serial_t serial;
-
- /* Each transmission of a Tx packet needs a new serial number */
- serial = rxrpc_get_next_serial(call->conn);
-
- rxrpc_prepare_data_subpacket(call, txb, serial);
-
- return txb->len;
+ if (!tq)
+ return 0;
+ if (tq->xmit_ts_base == KTIME_MIN) {
+ tq->xmit_ts_base = req->now;
+ return 0;
+ }
+ return ktime_to_us(ktime_sub(req->now, tq->xmit_ts_base));
}
/*
- * Set timeouts after transmitting a packet.
+ * Prepare a (jumbo) packet for transmission.
*/
-static void rxrpc_tstamp_data_packets(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
+static size_t rxrpc_prepare_data_packet(struct rxrpc_call *call, struct rxrpc_send_data_req *req)
{
- ktime_t now = ktime_get_real();
- bool ack_requested = txb->flags & RXRPC_REQUEST_ACK;
+ struct rxrpc_txqueue *tq = req->tq;
+ rxrpc_serial_t serial;
+ unsigned int xmit_ts;
+ rxrpc_seq_t seq = req->seq;
+ size_t len = 0;
+ bool start_tlp = false;
- call->tx_last_sent = now;
- txb->last_sent = now;
+ trace_rxrpc_tq(call, tq, seq, rxrpc_tq_transmit);
- if (ack_requested) {
- rxrpc_begin_rtt_probe(call, txb->serial, now, rxrpc_rtt_tx_data);
+ /* Each transmission of a Tx packet needs a new serial number */
+ serial = rxrpc_get_next_serials(call->conn, req->n);
+
+ call->tx_last_serial = serial + req->n - 1;
+ call->tx_last_sent = req->now;
+ xmit_ts = rxrpc_prepare_txqueue(tq, req);
+ prefetch(tq->next);
+
+ for (int i = 0;;) {
+ int ix = seq & RXRPC_TXQ_MASK;
+ struct rxrpc_txbuf *txb = tq->bufs[seq & RXRPC_TXQ_MASK];
+
+ _debug("prep[%u] tq=%x q=%x", i, tq->qbase, seq);
+
+ /* Record (re-)transmission for RACK [RFC8985 6.1]. */
+ if (__test_and_clear_bit(ix, &tq->segment_lost))
+ call->tx_nr_lost--;
+ if (req->retrans) {
+ __set_bit(ix, &tq->ever_retransmitted);
+ __set_bit(ix, &tq->segment_retransmitted);
+ call->tx_nr_resent++;
+ } else {
+ call->tx_nr_sent++;
+ start_tlp = true;
+ }
+ tq->segment_xmit_ts[ix] = xmit_ts;
+ tq->segment_serial[ix] = serial;
+ if (i + 1 == req->n)
+ /* Only sample the last subpacket in a jumbo. */
+ __set_bit(ix, &tq->rtt_samples);
+ len += rxrpc_prepare_data_subpacket(call, req, txb, serial, i);
+ serial++;
+ seq++;
+ i++;
+ if (i >= req->n)
+ break;
+ if (!(seq & RXRPC_TXQ_MASK)) {
+ tq = tq->next;
+ trace_rxrpc_tq(call, tq, seq, rxrpc_tq_transmit_advance);
+ xmit_ts = rxrpc_prepare_txqueue(tq, req);
+ }
+ }
- call->peer->rtt_last_req = now;
- if (call->peer->rtt_count > 1) {
- ktime_t delay = rxrpc_get_rto_backoff(call->peer, false);
+ /* Set timeouts */
+ if (req->tlp_probe) {
+ /* Sending TLP loss probe [RFC8985 7.3]. */
+ call->tlp_serial = serial - 1;
+ call->tlp_seq = seq - 1;
+ } else if (start_tlp) {
+ /* Schedule TLP loss probe [RFC8985 7.2]. */
+ ktime_t pto;
+
+ if (!test_bit(RXRPC_CALL_BEGAN_RX_TIMER, &call->flags))
+ /* The first packet may take longer to elicit a response. */
+ pto = NSEC_PER_SEC;
+ else
+ pto = rxrpc_tlp_calc_pto(call, req->now);
- call->ack_lost_at = ktime_add(now, delay);
- trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_lost_ack);
- }
+ call->rack_timer_mode = RXRPC_CALL_RACKTIMER_TLP_PTO;
+ call->rack_timo_at = ktime_add(req->now, pto);
+ trace_rxrpc_rack_timer(call, pto, false);
+ trace_rxrpc_timer_set(call, pto, rxrpc_timer_trace_rack_tlp_pto);
}
if (!test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER, &call->flags)) {
ktime_t delay = ms_to_ktime(READ_ONCE(call->next_rx_timo));
- call->expect_rx_by = ktime_add(now, delay);
+ call->expect_rx_by = ktime_add(req->now, delay);
trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_expect_rx);
}
- rxrpc_set_keepalive(call, now);
+ rxrpc_set_keepalive(call, req->now);
+ return len;
}
/*
- * send a packet through the transport endpoint
+ * Send one or more packets through the transport endpoint
*/
-static int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
+void rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_send_data_req *req)
{
- struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base;
struct rxrpc_connection *conn = call->conn;
enum rxrpc_tx_point frag;
+ struct rxrpc_txqueue *tq = req->tq;
+ struct rxrpc_txbuf *txb;
struct msghdr msg;
+ rxrpc_seq_t seq = req->seq;
size_t len;
- int ret;
+ bool new_call = test_bit(RXRPC_CALL_BEGAN_RX_TIMER, &call->flags);
+ int ret, stat_ix;
- _enter("%x,{%d}", txb->seq, txb->len);
+ _enter("%x,%x-%x", tq->qbase, seq, seq + req->n - 1);
- len = rxrpc_prepare_data_packet(call, txb);
+ stat_ix = umin(req->n, ARRAY_SIZE(call->rxnet->stat_tx_jumbo)) - 1;
+ atomic_inc(&call->rxnet->stat_tx_jumbo[stat_ix]);
- if (IS_ENABLED(CONFIG_AF_RXRPC_INJECT_LOSS)) {
- static int lose;
- if ((lose++ & 7) == 7) {
- ret = 0;
- trace_rxrpc_tx_data(call, txb->seq, txb->serial,
- txb->flags, true);
- goto done;
- }
- }
+ len = rxrpc_prepare_data_packet(call, req);
+ txb = tq->bufs[seq & RXRPC_TXQ_MASK];
- iov_iter_kvec(&msg.msg_iter, WRITE, txb->kvec, txb->nr_kvec, len);
+ iov_iter_kvec(&msg.msg_iter, WRITE, call->local->kvec, req->n, len);
msg.msg_name = &call->peer->srx.transport;
msg.msg_namelen = call->peer->srx.transport_len;
@@ -460,16 +652,11 @@ static int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
msg.msg_controllen = 0;
msg.msg_flags = MSG_SPLICE_PAGES;
- /* Track what we've attempted to transmit at least once so that the
- * retransmission algorithm doesn't try to resend what we haven't sent
- * yet.
+ /* Send the packet with the don't fragment bit set unless we think it's
+ * too big or if this is a retransmission.
*/
- if (txb->seq == call->tx_transmitted + 1)
- call->tx_transmitted = txb->seq;
-
- /* send the packet with the don't fragment bit set if we currently
- * think it's small enough */
- if (txb->len >= call->peer->maxdata) {
+ if (seq == call->tx_transmitted + 1 &&
+ len >= sizeof(struct rxrpc_wire_header) + call->peer->max_data) {
rxrpc_local_dont_fragment(conn->local, false);
frag = rxrpc_tx_point_call_data_frag;
} else {
@@ -477,7 +664,25 @@ static int rxrpc_send_data_packet(struct rxrpc_call *call, struct rxrpc_txbuf *t
frag = rxrpc_tx_point_call_data_nofrag;
}
-retry:
+ /* Track what we've attempted to transmit at least once so that the
+ * retransmission algorithm doesn't try to resend what we haven't sent
+ * yet.
+ */
+ if (seq == call->tx_transmitted + 1)
+ call->tx_transmitted = seq + req->n - 1;
+
+ if (IS_ENABLED(CONFIG_AF_RXRPC_INJECT_LOSS)) {
+ static int lose;
+
+ if ((lose++ & 7) == 7) {
+ ret = 0;
+ trace_rxrpc_tx_data(call, txb->seq, txb->serial, txb->flags,
+ rxrpc_txdata_inject_loss);
+ conn->peer->last_tx_at = ktime_get_seconds();
+ goto done;
+ }
+ }
+
/* send the packet by UDP
* - returns -EMSGSIZE if UDP would have to fragment the packet
* to go out of the interface
@@ -488,36 +693,35 @@ retry:
ret = do_udp_sendmsg(conn->local->socket, &msg, len);
conn->peer->last_tx_at = ktime_get_seconds();
- if (ret < 0) {
+ if (ret == -EMSGSIZE) {
+ rxrpc_inc_stat(call->rxnet, stat_tx_data_send_msgsize);
+ trace_rxrpc_tx_packet(call->debug_id, call->local->kvec[0].iov_base, frag);
+ ret = 0;
+ } else if (ret < 0) {
rxrpc_inc_stat(call->rxnet, stat_tx_data_send_fail);
trace_rxrpc_tx_fail(call->debug_id, txb->serial, ret, frag);
} else {
- trace_rxrpc_tx_packet(call->debug_id, whdr, frag);
+ trace_rxrpc_tx_packet(call->debug_id, call->local->kvec[0].iov_base, frag);
}
rxrpc_tx_backoff(call, ret);
- if (ret == -EMSGSIZE && frag == rxrpc_tx_point_call_data_frag) {
- rxrpc_local_dont_fragment(conn->local, false);
- frag = rxrpc_tx_point_call_data_frag;
- goto retry;
- }
-done:
- if (ret >= 0) {
- rxrpc_tstamp_data_packets(call, txb);
- } else {
- /* Cancel the call if the initial transmission fails,
- * particularly if that's due to network routing issues that
- * aren't going away anytime soon. The layer above can arrange
- * the retransmission.
+ if (ret < 0) {
+ /* Cancel the call if the initial transmission fails or if we
+ * hit due to network routing issues that aren't going away
+ * anytime soon. The layer above can arrange the
+ * retransmission.
*/
- if (!test_and_set_bit(RXRPC_CALL_BEGAN_RX_TIMER, &call->flags))
+ if (new_call ||
+ ret == -ENETUNREACH ||
+ ret == -EHOSTUNREACH ||
+ ret == -ECONNREFUSED)
rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
RX_USER_ABORT, ret);
}
- _leave(" = %d [%u]", ret, call->peer->maxdata);
- return ret;
+done:
+ _leave(" = %d [%u]", ret, call->peer->max_data);
}
/*
@@ -692,41 +896,3 @@ void rxrpc_send_keepalive(struct rxrpc_peer *peer)
peer->last_tx_at = ktime_get_seconds();
_leave("");
}
-
-/*
- * Schedule an instant Tx resend.
- */
-static inline void rxrpc_instant_resend(struct rxrpc_call *call,
- struct rxrpc_txbuf *txb)
-{
- if (!__rxrpc_call_is_complete(call))
- kdebug("resend");
-}
-
-/*
- * Transmit one packet.
- */
-void rxrpc_transmit_one(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
-{
- int ret;
-
- ret = rxrpc_send_data_packet(call, txb);
- if (ret < 0) {
- switch (ret) {
- case -ENETUNREACH:
- case -EHOSTUNREACH:
- case -ECONNREFUSED:
- rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
- 0, ret);
- break;
- default:
- _debug("need instant resend %d", ret);
- rxrpc_instant_resend(call, txb);
- }
- } else {
- ktime_t delay = ns_to_ktime(call->peer->rto_us * NSEC_PER_USEC);
-
- call->resend_at = ktime_add(ktime_get_real(), delay);
- trace_rxrpc_timer_set(call, delay, rxrpc_timer_trace_resend_tx);
- }
-}
diff --git a/net/rxrpc/peer_event.c b/net/rxrpc/peer_event.c
index 552ba84a255c..d82e44a3901b 100644
--- a/net/rxrpc/peer_event.c
+++ b/net/rxrpc/peer_event.c
@@ -102,6 +102,8 @@ static struct rxrpc_peer *rxrpc_lookup_peer_local_rcu(struct rxrpc_local *local,
*/
static void rxrpc_adjust_mtu(struct rxrpc_peer *peer, unsigned int mtu)
{
+ unsigned int max_data;
+
/* wind down the local interface MTU */
if (mtu > 0 && peer->if_mtu == 65535 && mtu < peer->if_mtu)
peer->if_mtu = mtu;
@@ -120,11 +122,17 @@ static void rxrpc_adjust_mtu(struct rxrpc_peer *peer, unsigned int mtu)
}
}
- if (mtu < peer->mtu) {
- spin_lock(&peer->lock);
- peer->mtu = mtu;
- peer->maxdata = peer->mtu - peer->hdrsize;
- spin_unlock(&peer->lock);
+ max_data = max_t(int, mtu - peer->hdrsize, 500);
+ if (max_data < peer->max_data) {
+ if (peer->pmtud_good > max_data)
+ peer->pmtud_good = max_data;
+ if (peer->pmtud_bad > max_data + 1)
+ peer->pmtud_bad = max_data + 1;
+
+ trace_rxrpc_pmtud_reduce(peer, 0, max_data, rxrpc_pmtud_reduce_icmp);
+ write_seqcount_begin(&peer->mtu_lock);
+ peer->max_data = max_data;
+ write_seqcount_end(&peer->mtu_lock);
}
}
@@ -205,23 +213,23 @@ static void rxrpc_distribute_error(struct rxrpc_peer *peer, struct sk_buff *skb,
struct rxrpc_call *call;
HLIST_HEAD(error_targets);
- spin_lock(&peer->lock);
+ spin_lock_irq(&peer->lock);
hlist_move_list(&peer->error_targets, &error_targets);
while (!hlist_empty(&error_targets)) {
call = hlist_entry(error_targets.first,
struct rxrpc_call, error_link);
hlist_del_init(&call->error_link);
- spin_unlock(&peer->lock);
+ spin_unlock_irq(&peer->lock);
rxrpc_see_call(call, rxrpc_call_see_distribute_error);
rxrpc_set_call_completion(call, compl, 0, -err);
- rxrpc_input_call_event(call, skb);
+ rxrpc_input_call_event(call);
- spin_lock(&peer->lock);
+ spin_lock_irq(&peer->lock);
}
- spin_unlock(&peer->lock);
+ spin_unlock_irq(&peer->lock);
}
/*
@@ -347,3 +355,89 @@ void rxrpc_peer_keepalive_worker(struct work_struct *work)
_leave("");
}
+
+/*
+ * Do path MTU probing.
+ */
+void rxrpc_input_probe_for_pmtud(struct rxrpc_connection *conn, rxrpc_serial_t acked_serial,
+ bool sendmsg_fail)
+{
+ struct rxrpc_peer *peer = conn->peer;
+ unsigned int max_data = peer->max_data;
+ int good, trial, bad, jumbo;
+
+ good = peer->pmtud_good;
+ trial = peer->pmtud_trial;
+ bad = peer->pmtud_bad;
+ if (good >= bad - 1) {
+ conn->pmtud_probe = 0;
+ peer->pmtud_lost = false;
+ return;
+ }
+
+ if (!peer->pmtud_probing)
+ goto send_probe;
+
+ if (sendmsg_fail || after(acked_serial, conn->pmtud_probe)) {
+ /* Retry a lost probe. */
+ if (!peer->pmtud_lost) {
+ trace_rxrpc_pmtud_lost(conn, acked_serial);
+ conn->pmtud_probe = 0;
+ peer->pmtud_lost = true;
+ goto send_probe;
+ }
+
+ /* The probed size didn't seem to get through. */
+ bad = trial;
+ peer->pmtud_bad = bad;
+ if (bad <= max_data)
+ max_data = bad - 1;
+ } else {
+ /* It did get through. */
+ good = trial;
+ peer->pmtud_good = good;
+ if (good > max_data)
+ max_data = good;
+ }
+
+ max_data = umin(max_data, peer->ackr_max_data);
+ if (max_data != peer->max_data) {
+ preempt_disable();
+ write_seqcount_begin(&peer->mtu_lock);
+ peer->max_data = max_data;
+ write_seqcount_end(&peer->mtu_lock);
+ preempt_enable();
+ }
+
+ jumbo = max_data + sizeof(struct rxrpc_jumbo_header);
+ jumbo /= RXRPC_JUMBO_SUBPKTLEN;
+ peer->pmtud_jumbo = jumbo;
+
+ trace_rxrpc_pmtud_rx(conn, acked_serial);
+ conn->pmtud_probe = 0;
+ peer->pmtud_lost = false;
+
+ if (good < RXRPC_JUMBO(2) && bad > RXRPC_JUMBO(2))
+ trial = RXRPC_JUMBO(2);
+ else if (good < RXRPC_JUMBO(4) && bad > RXRPC_JUMBO(4))
+ trial = RXRPC_JUMBO(4);
+ else if (good < RXRPC_JUMBO(3) && bad > RXRPC_JUMBO(3))
+ trial = RXRPC_JUMBO(3);
+ else if (good < RXRPC_JUMBO(6) && bad > RXRPC_JUMBO(6))
+ trial = RXRPC_JUMBO(6);
+ else if (good < RXRPC_JUMBO(5) && bad > RXRPC_JUMBO(5))
+ trial = RXRPC_JUMBO(5);
+ else if (good < RXRPC_JUMBO(8) && bad > RXRPC_JUMBO(8))
+ trial = RXRPC_JUMBO(8);
+ else if (good < RXRPC_JUMBO(7) && bad > RXRPC_JUMBO(7))
+ trial = RXRPC_JUMBO(7);
+ else
+ trial = (good + bad) / 2;
+ peer->pmtud_trial = trial;
+
+ if (good >= bad)
+ return;
+
+send_probe:
+ peer->pmtud_pending = true;
+}
diff --git a/net/rxrpc/peer_object.c b/net/rxrpc/peer_object.c
index 49dcda67a0d5..e1c63129586b 100644
--- a/net/rxrpc/peer_object.c
+++ b/net/rxrpc/peer_object.c
@@ -162,6 +162,11 @@ static void rxrpc_assess_MTU_size(struct rxrpc_local *local,
#endif
peer->if_mtu = 1500;
+ if (peer->max_data < peer->if_mtu - peer->hdrsize) {
+ trace_rxrpc_pmtud_reduce(peer, 0, peer->if_mtu - peer->hdrsize,
+ rxrpc_pmtud_reduce_route);
+ peer->max_data = peer->if_mtu - peer->hdrsize;
+ }
memset(&fl, 0, sizeof(fl));
switch (peer->srx.transport.family) {
@@ -199,8 +204,16 @@ static void rxrpc_assess_MTU_size(struct rxrpc_local *local,
}
peer->if_mtu = dst_mtu(dst);
+ peer->hdrsize += dst->header_len + dst->trailer_len;
+ peer->tx_seg_max = dst->dev->gso_max_segs;
dst_release(dst);
+ peer->max_data = umin(RXRPC_JUMBO(1), peer->if_mtu - peer->hdrsize);
+ peer->pmtud_good = 500;
+ peer->pmtud_bad = peer->if_mtu - peer->hdrsize + 1;
+ peer->pmtud_trial = umin(peer->max_data, peer->pmtud_bad - 1);
+ peer->pmtud_pending = true;
+
_leave(" [if_mtu %u]", peer->if_mtu);
}
@@ -222,11 +235,9 @@ struct rxrpc_peer *rxrpc_alloc_peer(struct rxrpc_local *local, gfp_t gfp,
peer->service_conns = RB_ROOT;
seqlock_init(&peer->service_conn_lock);
spin_lock_init(&peer->lock);
- spin_lock_init(&peer->rtt_input_lock);
+ seqcount_init(&peer->mtu_lock);
peer->debug_id = atomic_inc_return(&rxrpc_debug_id);
-
- rxrpc_peer_init_rtt(peer);
-
+ peer->recent_srtt_us = UINT_MAX;
peer->cong_ssthresh = RXRPC_TX_MAX_WINDOW;
trace_rxrpc_peer(peer->debug_id, 1, why);
}
@@ -242,9 +253,7 @@ static void rxrpc_init_peer(struct rxrpc_local *local, struct rxrpc_peer *peer,
unsigned long hash_key)
{
peer->hash_key = hash_key;
- rxrpc_assess_MTU_size(local, peer);
- peer->mtu = peer->if_mtu;
- peer->rtt_last_req = ktime_get_real();
+
switch (peer->srx.transport.family) {
case AF_INET:
@@ -268,7 +277,9 @@ static void rxrpc_init_peer(struct rxrpc_local *local, struct rxrpc_peer *peer,
}
peer->hdrsize += sizeof(struct rxrpc_wire_header);
- peer->maxdata = peer->mtu - peer->hdrsize;
+ peer->max_data = peer->if_mtu - peer->hdrsize;
+
+ rxrpc_assess_MTU_size(local, peer);
}
/*
@@ -304,6 +315,7 @@ static void rxrpc_free_peer(struct rxrpc_peer *peer)
* Set up a new incoming peer. There shouldn't be any other matching peers
* since we've already done a search in the list from the non-reentrant context
* (the data_ready handler) that is the only place we can add new peers.
+ * Called with interrupts disabled.
*/
void rxrpc_new_incoming_peer(struct rxrpc_local *local, struct rxrpc_peer *peer)
{
@@ -479,7 +491,7 @@ EXPORT_SYMBOL(rxrpc_kernel_get_call_peer);
*/
unsigned int rxrpc_kernel_get_srtt(const struct rxrpc_peer *peer)
{
- return peer->rtt_count > 0 ? peer->srtt_us >> 3 : UINT_MAX;
+ return READ_ONCE(peer->recent_srtt_us);
}
EXPORT_SYMBOL(rxrpc_kernel_get_srtt);
diff --git a/net/rxrpc/proc.c b/net/rxrpc/proc.c
index 263a2251e3d2..d803562ca0ac 100644
--- a/net/rxrpc/proc.c
+++ b/net/rxrpc/proc.c
@@ -52,7 +52,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
struct rxrpc_call *call;
struct rxrpc_net *rxnet = rxrpc_net(seq_file_net(seq));
enum rxrpc_call_state state;
- rxrpc_seq_t acks_hard_ack;
+ rxrpc_seq_t tx_bottom;
char lbuff[50], rbuff[50];
long timeout = 0;
@@ -79,7 +79,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
if (state != RXRPC_CALL_SERVER_PREALLOC)
timeout = ktime_ms_delta(READ_ONCE(call->expect_rx_by), ktime_get_real());
- acks_hard_ack = READ_ONCE(call->acks_hard_ack);
+ tx_bottom = READ_ONCE(call->tx_bottom);
seq_printf(seq,
"UDP %-47.47s %-47.47s %4x %08x %08x %s %3u"
" %-8.8s %08x %08x %08x %02x %08x %02x %08x %02x %06lx\n",
@@ -93,7 +93,7 @@ static int rxrpc_call_seq_show(struct seq_file *seq, void *v)
rxrpc_call_states[state],
call->abort_code,
call->debug_id,
- acks_hard_ack, READ_ONCE(call->tx_top) - acks_hard_ack,
+ tx_bottom, READ_ONCE(call->tx_top) - tx_bottom,
call->ackr_window, call->ackr_wtop - call->ackr_window,
call->rx_serial,
call->cong_cwnd,
@@ -283,9 +283,7 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v)
if (v == SEQ_START_TOKEN) {
seq_puts(seq,
- "Proto Local "
- " Remote "
- " Use SST MTU LastUse RTT RTO\n"
+ "Proto Local Remote Use SST Maxd LastUse RTT RTO\n"
);
return 0;
}
@@ -298,16 +296,15 @@ static int rxrpc_peer_seq_show(struct seq_file *seq, void *v)
now = ktime_get_seconds();
seq_printf(seq,
- "UDP %-47.47s %-47.47s %3u"
- " %3u %5u %6llus %8u %8u\n",
+ "UDP %-47.47s %-47.47s %3u %4u %5u %6llus %8d %8d\n",
lbuff,
rbuff,
refcount_read(&peer->ref),
peer->cong_ssthresh,
- peer->mtu,
+ peer->max_data,
now - peer->last_tx_at,
- peer->srtt_us >> 3,
- peer->rto_us);
+ READ_ONCE(peer->recent_srtt_us),
+ READ_ONCE(peer->recent_rto_us));
return 0;
}
@@ -476,10 +473,11 @@ int rxrpc_stats_show(struct seq_file *seq, void *v)
struct rxrpc_net *rxnet = rxrpc_net(seq_file_single_net(seq));
seq_printf(seq,
- "Data : send=%u sendf=%u fail=%u\n",
+ "Data : send=%u sendf=%u fail=%u emsz=%u\n",
atomic_read(&rxnet->stat_tx_data_send),
atomic_read(&rxnet->stat_tx_data_send_frag),
- atomic_read(&rxnet->stat_tx_data_send_fail));
+ atomic_read(&rxnet->stat_tx_data_send_fail),
+ atomic_read(&rxnet->stat_tx_data_send_msgsize));
seq_printf(seq,
"Data-Tx : nr=%u retrans=%u uf=%u cwr=%u\n",
atomic_read(&rxnet->stat_tx_data),
@@ -508,7 +506,7 @@ int rxrpc_stats_show(struct seq_file *seq, void *v)
atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_DELAY]),
atomic_read(&rxnet->stat_tx_acks[RXRPC_ACK_IDLE]));
seq_printf(seq,
- "Ack-Rx : req=%u dup=%u oos=%u exw=%u nos=%u png=%u prs=%u dly=%u idl=%u\n",
+ "Ack-Rx : req=%u dup=%u oos=%u exw=%u nos=%u png=%u prs=%u dly=%u idl=%u z=%u\n",
atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_REQUESTED]),
atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_DUPLICATE]),
atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_OUT_OF_SEQUENCE]),
@@ -517,13 +515,14 @@ int rxrpc_stats_show(struct seq_file *seq, void *v)
atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_PING]),
atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_PING_RESPONSE]),
atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_DELAY]),
- atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_IDLE]));
+ atomic_read(&rxnet->stat_rx_acks[RXRPC_ACK_IDLE]),
+ atomic_read(&rxnet->stat_rx_acks[0]));
seq_printf(seq,
- "Why-Req-A: acklost=%u already=%u mrtt=%u ortt=%u\n",
+ "Why-Req-A: acklost=%u mrtt=%u ortt=%u stall=%u\n",
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_ack_lost]),
- atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_already_on]),
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_more_rtt]),
- atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_old_rtt]));
+ atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_old_rtt]),
+ atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_app_stall]));
seq_printf(seq,
"Why-Req-A: nolast=%u retx=%u slows=%u smtxw=%u\n",
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_no_srv_last]),
@@ -531,6 +530,30 @@ int rxrpc_stats_show(struct seq_file *seq, void *v)
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_slow_start]),
atomic_read(&rxnet->stat_why_req_ack[rxrpc_reqack_small_txwin]));
seq_printf(seq,
+ "Jumbo-Tx : %u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n",
+ atomic_read(&rxnet->stat_tx_jumbo[0]),
+ atomic_read(&rxnet->stat_tx_jumbo[1]),
+ atomic_read(&rxnet->stat_tx_jumbo[2]),
+ atomic_read(&rxnet->stat_tx_jumbo[3]),
+ atomic_read(&rxnet->stat_tx_jumbo[4]),
+ atomic_read(&rxnet->stat_tx_jumbo[5]),
+ atomic_read(&rxnet->stat_tx_jumbo[6]),
+ atomic_read(&rxnet->stat_tx_jumbo[7]),
+ atomic_read(&rxnet->stat_tx_jumbo[8]),
+ atomic_read(&rxnet->stat_tx_jumbo[9]));
+ seq_printf(seq,
+ "Jumbo-Rx : %u,%u,%u,%u,%u,%u,%u,%u,%u,%u\n",
+ atomic_read(&rxnet->stat_rx_jumbo[0]),
+ atomic_read(&rxnet->stat_rx_jumbo[1]),
+ atomic_read(&rxnet->stat_rx_jumbo[2]),
+ atomic_read(&rxnet->stat_rx_jumbo[3]),
+ atomic_read(&rxnet->stat_rx_jumbo[4]),
+ atomic_read(&rxnet->stat_rx_jumbo[5]),
+ atomic_read(&rxnet->stat_rx_jumbo[6]),
+ atomic_read(&rxnet->stat_rx_jumbo[7]),
+ atomic_read(&rxnet->stat_rx_jumbo[8]),
+ atomic_read(&rxnet->stat_rx_jumbo[9]));
+ seq_printf(seq,
"Buffers : txb=%u rxb=%u\n",
atomic_read(&rxrpc_nr_txbuf),
atomic_read(&rxrpc_n_rx_skbs));
@@ -567,6 +590,8 @@ int rxrpc_stats_clear(struct file *file, char *buf, size_t size)
atomic_set(&rxnet->stat_tx_ack_skip, 0);
memset(&rxnet->stat_tx_acks, 0, sizeof(rxnet->stat_tx_acks));
memset(&rxnet->stat_rx_acks, 0, sizeof(rxnet->stat_rx_acks));
+ memset(&rxnet->stat_tx_jumbo, 0, sizeof(rxnet->stat_tx_jumbo));
+ memset(&rxnet->stat_rx_jumbo, 0, sizeof(rxnet->stat_rx_jumbo));
memset(&rxnet->stat_why_req_ack, 0, sizeof(rxnet->stat_why_req_ack));
diff --git a/net/rxrpc/protocol.h b/net/rxrpc/protocol.h
index 4fe6b4d20ada..42f70e4636f8 100644
--- a/net/rxrpc/protocol.h
+++ b/net/rxrpc/protocol.h
@@ -92,11 +92,16 @@ struct rxrpc_jumbo_header {
/*
* The maximum number of subpackets that can possibly fit in a UDP packet is:
*
- * ((max_IP - IP_hdr - UDP_hdr) / RXRPC_JUMBO_SUBPKTLEN) + 1
- * = ((65535 - 28 - 28) / 1416) + 1
- * = 46 non-terminal packets and 1 terminal packet.
+ * (max_UDP - wirehdr + jumbohdr) / (jumbohdr + 1412)
+ * = ((65535 - 28 + 4) / 1416)
+ * = 45 non-terminal packets and 1 terminal packet.
*/
-#define RXRPC_MAX_NR_JUMBO 47
+#define RXRPC_MAX_NR_JUMBO 46
+
+/* Size of a jumbo packet with N subpackets, excluding UDP+IP */
+#define RXRPC_JUMBO(N) ((int)sizeof(struct rxrpc_wire_header) + \
+ RXRPC_JUMBO_DATALEN + \
+ ((N) - 1) * RXRPC_JUMBO_SUBPKTLEN)
/*****************************************************************************/
/*
diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c
index a482f88c5fc5..32cd5f1d541d 100644
--- a/net/rxrpc/recvmsg.c
+++ b/net/rxrpc/recvmsg.c
@@ -36,16 +36,16 @@ void rxrpc_notify_socket(struct rxrpc_call *call)
sk = &rx->sk;
if (rx && sk->sk_state < RXRPC_CLOSE) {
if (call->notify_rx) {
- spin_lock(&call->notify_lock);
+ spin_lock_irq(&call->notify_lock);
call->notify_rx(sk, call, call->user_call_ID);
- spin_unlock(&call->notify_lock);
+ spin_unlock_irq(&call->notify_lock);
} else {
- spin_lock(&rx->recvmsg_lock);
+ spin_lock_irq(&rx->recvmsg_lock);
if (list_empty(&call->recvmsg_link)) {
rxrpc_get_call(call, rxrpc_call_get_notify_socket);
list_add_tail(&call->recvmsg_link, &rx->recvmsg_q);
}
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
if (!sock_flag(sk, SOCK_DEAD)) {
_debug("call %ps", sk->sk_data_ready);
@@ -337,14 +337,14 @@ try_again:
* We also want to weed out calls that got requeued whilst we were
* shovelling data out.
*/
- spin_lock(&rx->recvmsg_lock);
+ spin_lock_irq(&rx->recvmsg_lock);
l = rx->recvmsg_q.next;
call = list_entry(l, struct rxrpc_call, recvmsg_link);
if (!rxrpc_call_is_complete(call) &&
skb_queue_empty(&call->recvmsg_queue)) {
list_del_init(&call->recvmsg_link);
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
release_sock(&rx->sk);
trace_rxrpc_recvmsg(call->debug_id, rxrpc_recvmsg_unqueue, 0);
rxrpc_put_call(call, rxrpc_call_put_recvmsg);
@@ -355,7 +355,7 @@ try_again:
list_del_init(&call->recvmsg_link);
else
rxrpc_get_call(call, rxrpc_call_get_recvmsg);
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
call_debug_id = call->debug_id;
trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_dequeue, 0);
@@ -445,9 +445,9 @@ error_unlock_call:
error_requeue_call:
if (!(flags & MSG_PEEK)) {
- spin_lock(&rx->recvmsg_lock);
+ spin_lock_irq(&rx->recvmsg_lock);
list_add(&call->recvmsg_link, &rx->recvmsg_q);
- spin_unlock(&rx->recvmsg_lock);
+ spin_unlock_irq(&rx->recvmsg_lock);
trace_rxrpc_recvmsg(call_debug_id, rxrpc_recvmsg_requeue, 0);
} else {
rxrpc_put_call(call, rxrpc_call_put_recvmsg);
diff --git a/net/rxrpc/rtt.c b/net/rxrpc/rtt.c
index cdab7b7d08a0..7474f88d7b18 100644
--- a/net/rxrpc/rtt.c
+++ b/net/rxrpc/rtt.c
@@ -12,22 +12,22 @@
#include "ar-internal.h"
#define RXRPC_RTO_MAX (120 * USEC_PER_SEC)
-#define RXRPC_TIMEOUT_INIT ((unsigned int)(1 * MSEC_PER_SEC)) /* RFC6298 2.1 initial RTO value */
+#define RXRPC_TIMEOUT_INIT ((unsigned int)(1 * USEC_PER_SEC)) /* RFC6298 2.1 initial RTO value */
#define rxrpc_jiffies32 ((u32)jiffies) /* As rxrpc_jiffies32 */
-static u32 rxrpc_rto_min_us(struct rxrpc_peer *peer)
+static u32 rxrpc_rto_min_us(struct rxrpc_call *call)
{
return 200;
}
-static u32 __rxrpc_set_rto(const struct rxrpc_peer *peer)
+static u32 __rxrpc_set_rto(const struct rxrpc_call *call)
{
- return (peer->srtt_us >> 3) + peer->rttvar_us;
+ return (call->srtt_us >> 3) + call->rttvar_us;
}
static u32 rxrpc_bound_rto(u32 rto)
{
- return min(rto, RXRPC_RTO_MAX);
+ return clamp(200000, rto + 100000, RXRPC_RTO_MAX);
}
/*
@@ -40,10 +40,10 @@ static u32 rxrpc_bound_rto(u32 rto)
* To save cycles in the RFC 1323 implementation it was better to break
* it up into three procedures. -- erics
*/
-static void rxrpc_rtt_estimator(struct rxrpc_peer *peer, long sample_rtt_us)
+static void rxrpc_rtt_estimator(struct rxrpc_call *call, long sample_rtt_us)
{
long m = sample_rtt_us; /* RTT */
- u32 srtt = peer->srtt_us;
+ u32 srtt = call->srtt_us;
/* The following amusing code comes from Jacobson's
* article in SIGCOMM '88. Note that rtt and mdev
@@ -66,7 +66,7 @@ static void rxrpc_rtt_estimator(struct rxrpc_peer *peer, long sample_rtt_us)
srtt += m; /* rtt = 7/8 rtt + 1/8 new */
if (m < 0) {
m = -m; /* m is now abs(error) */
- m -= (peer->mdev_us >> 2); /* similar update on mdev */
+ m -= (call->mdev_us >> 2); /* similar update on mdev */
/* This is similar to one of Eifel findings.
* Eifel blocks mdev updates when rtt decreases.
* This solution is a bit different: we use finer gain
@@ -78,31 +78,31 @@ static void rxrpc_rtt_estimator(struct rxrpc_peer *peer, long sample_rtt_us)
if (m > 0)
m >>= 3;
} else {
- m -= (peer->mdev_us >> 2); /* similar update on mdev */
+ m -= (call->mdev_us >> 2); /* similar update on mdev */
}
- peer->mdev_us += m; /* mdev = 3/4 mdev + 1/4 new */
- if (peer->mdev_us > peer->mdev_max_us) {
- peer->mdev_max_us = peer->mdev_us;
- if (peer->mdev_max_us > peer->rttvar_us)
- peer->rttvar_us = peer->mdev_max_us;
+ call->mdev_us += m; /* mdev = 3/4 mdev + 1/4 new */
+ if (call->mdev_us > call->mdev_max_us) {
+ call->mdev_max_us = call->mdev_us;
+ if (call->mdev_max_us > call->rttvar_us)
+ call->rttvar_us = call->mdev_max_us;
}
} else {
/* no previous measure. */
srtt = m << 3; /* take the measured time to be rtt */
- peer->mdev_us = m << 1; /* make sure rto = 3*rtt */
- peer->rttvar_us = max(peer->mdev_us, rxrpc_rto_min_us(peer));
- peer->mdev_max_us = peer->rttvar_us;
+ call->mdev_us = m << 1; /* make sure rto = 3*rtt */
+ call->rttvar_us = umax(call->mdev_us, rxrpc_rto_min_us(call));
+ call->mdev_max_us = call->rttvar_us;
}
- peer->srtt_us = max(1U, srtt);
+ call->srtt_us = umax(srtt, 1);
}
/*
* Calculate rto without backoff. This is the second half of Van Jacobson's
* routine referred to above.
*/
-static void rxrpc_set_rto(struct rxrpc_peer *peer)
+static void rxrpc_set_rto(struct rxrpc_call *call)
{
u32 rto;
@@ -113,7 +113,7 @@ static void rxrpc_set_rto(struct rxrpc_peer *peer)
* is invisible. Actually, Linux-2.4 also generates erratic
* ACKs in some circumstances.
*/
- rto = __rxrpc_set_rto(peer);
+ rto = __rxrpc_set_rto(call);
/* 2. Fixups made earlier cannot be right.
* If we do not estimate RTO correctly without them,
@@ -124,61 +124,73 @@ static void rxrpc_set_rto(struct rxrpc_peer *peer)
/* NOTE: clamping at RXRPC_RTO_MIN is not required, current algo
* guarantees that rto is higher.
*/
- peer->rto_us = rxrpc_bound_rto(rto);
+ call->rto_us = rxrpc_bound_rto(rto);
}
-static void rxrpc_ack_update_rtt(struct rxrpc_peer *peer, long rtt_us)
+static void rxrpc_update_rtt_min(struct rxrpc_call *call, ktime_t resp_time, long rtt_us)
+{
+ /* Window size 5mins in approx usec (ipv4.sysctl_tcp_min_rtt_wlen) */
+ u32 wlen_us = 5ULL * NSEC_PER_SEC / 1024;
+
+ minmax_running_min(&call->min_rtt, wlen_us, resp_time / 1024,
+ (u32)rtt_us ? : jiffies_to_usecs(1));
+}
+
+static void rxrpc_ack_update_rtt(struct rxrpc_call *call, ktime_t resp_time, long rtt_us)
{
if (rtt_us < 0)
return;
- //rxrpc_update_rtt_min(peer, rtt_us);
- rxrpc_rtt_estimator(peer, rtt_us);
- rxrpc_set_rto(peer);
+ /* Update RACK min RTT [RFC8985 6.1 Step 1]. */
+ rxrpc_update_rtt_min(call, resp_time, rtt_us);
+
+ rxrpc_rtt_estimator(call, rtt_us);
+ rxrpc_set_rto(call);
- /* RFC6298: only reset backoff on valid RTT measurement. */
- peer->backoff = 0;
+ /* Only reset backoff on valid RTT measurement [RFC6298]. */
+ call->backoff = 0;
}
/*
* Add RTT information to cache. This is called in softirq mode and has
- * exclusive access to the peer RTT data.
+ * exclusive access to the call RTT data.
*/
-void rxrpc_peer_add_rtt(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why,
+void rxrpc_call_add_rtt(struct rxrpc_call *call, enum rxrpc_rtt_rx_trace why,
int rtt_slot,
rxrpc_serial_t send_serial, rxrpc_serial_t resp_serial,
ktime_t send_time, ktime_t resp_time)
{
- struct rxrpc_peer *peer = call->peer;
s64 rtt_us;
rtt_us = ktime_to_us(ktime_sub(resp_time, send_time));
if (rtt_us < 0)
return;
- spin_lock(&peer->rtt_input_lock);
- rxrpc_ack_update_rtt(peer, rtt_us);
- if (peer->rtt_count < 3)
- peer->rtt_count++;
- spin_unlock(&peer->rtt_input_lock);
+ rxrpc_ack_update_rtt(call, resp_time, rtt_us);
+ if (call->rtt_count < 3)
+ call->rtt_count++;
+ call->rtt_taken++;
+
+ WRITE_ONCE(call->peer->recent_srtt_us, call->srtt_us / 8);
+ WRITE_ONCE(call->peer->recent_rto_us, call->rto_us);
trace_rxrpc_rtt_rx(call, why, rtt_slot, send_serial, resp_serial,
- peer->srtt_us >> 3, peer->rto_us);
+ rtt_us, call->srtt_us, call->rto_us);
}
/*
* Get the retransmission timeout to set in nanoseconds, backing it off each
* time we retransmit.
*/
-ktime_t rxrpc_get_rto_backoff(struct rxrpc_peer *peer, bool retrans)
+ktime_t rxrpc_get_rto_backoff(struct rxrpc_call *call, bool retrans)
{
u64 timo_us;
- u32 backoff = READ_ONCE(peer->backoff);
+ u32 backoff = READ_ONCE(call->backoff);
- timo_us = peer->rto_us;
+ timo_us = call->rto_us;
timo_us <<= backoff;
if (retrans && timo_us * 2 <= RXRPC_RTO_MAX)
- WRITE_ONCE(peer->backoff, backoff + 1);
+ WRITE_ONCE(call->backoff, backoff + 1);
if (timo_us < 1)
timo_us = 1;
@@ -186,10 +198,11 @@ ktime_t rxrpc_get_rto_backoff(struct rxrpc_peer *peer, bool retrans)
return ns_to_ktime(timo_us * NSEC_PER_USEC);
}
-void rxrpc_peer_init_rtt(struct rxrpc_peer *peer)
+void rxrpc_call_init_rtt(struct rxrpc_call *call)
{
- peer->rto_us = RXRPC_TIMEOUT_INIT;
- peer->mdev_us = RXRPC_TIMEOUT_INIT;
- peer->backoff = 0;
- //minmax_reset(&peer->rtt_min, rxrpc_jiffies32, ~0U);
+ call->rtt_last_req = KTIME_MIN;
+ call->rto_us = RXRPC_TIMEOUT_INIT;
+ call->mdev_us = RXRPC_TIMEOUT_INIT;
+ call->backoff = 0;
+ //minmax_reset(&call->rtt_min, rxrpc_jiffies32, ~0U);
}
diff --git a/net/rxrpc/rxkad.c b/net/rxrpc/rxkad.c
index 48a1475e6b06..62b09d23ec08 100644
--- a/net/rxrpc/rxkad.c
+++ b/net/rxrpc/rxkad.c
@@ -148,14 +148,14 @@ error:
static struct rxrpc_txbuf *rxkad_alloc_txbuf(struct rxrpc_call *call, size_t remain, gfp_t gfp)
{
struct rxrpc_txbuf *txb;
- size_t shdr, space;
+ size_t shdr, alloc, limit, part;
- remain = min(remain, 65535 - sizeof(struct rxrpc_wire_header));
+ remain = umin(remain, 65535 - sizeof(struct rxrpc_wire_header));
switch (call->conn->security_level) {
default:
- space = min_t(size_t, remain, RXRPC_JUMBO_DATALEN);
- return rxrpc_alloc_data_txbuf(call, space, 1, gfp);
+ alloc = umin(remain, RXRPC_JUMBO_DATALEN);
+ return rxrpc_alloc_data_txbuf(call, alloc, 1, gfp);
case RXRPC_SECURITY_AUTH:
shdr = sizeof(struct rxkad_level1_hdr);
break;
@@ -164,15 +164,21 @@ static struct rxrpc_txbuf *rxkad_alloc_txbuf(struct rxrpc_call *call, size_t rem
break;
}
- space = min_t(size_t, round_down(RXRPC_JUMBO_DATALEN, RXKAD_ALIGN), remain + shdr);
- space = round_up(space, RXKAD_ALIGN);
+ limit = round_down(RXRPC_JUMBO_DATALEN, RXKAD_ALIGN) - shdr;
+ if (remain < limit) {
+ part = remain;
+ alloc = round_up(shdr + part, RXKAD_ALIGN);
+ } else {
+ part = limit;
+ alloc = RXRPC_JUMBO_DATALEN;
+ }
- txb = rxrpc_alloc_data_txbuf(call, space, RXKAD_ALIGN, gfp);
+ txb = rxrpc_alloc_data_txbuf(call, alloc, RXKAD_ALIGN, gfp);
if (!txb)
return NULL;
txb->offset += shdr;
- txb->space -= shdr;
+ txb->space = part;
return txb;
}
@@ -263,13 +269,13 @@ static int rxkad_secure_packet_auth(const struct rxrpc_call *call,
check = txb->seq ^ call->call_id;
hdr->data_size = htonl((u32)check << 16 | txb->len);
- txb->len += sizeof(struct rxkad_level1_hdr);
- pad = txb->len;
+ txb->pkt_len = sizeof(struct rxkad_level1_hdr) + txb->len;
+ pad = txb->pkt_len;
pad = RXKAD_ALIGN - pad;
pad &= RXKAD_ALIGN - 1;
if (pad) {
memset(txb->kvec[0].iov_base + txb->offset, 0, pad);
- txb->len += pad;
+ txb->pkt_len += pad;
}
/* start the encryption afresh */
@@ -298,7 +304,7 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
struct rxkad_level2_hdr *rxkhdr = (void *)(whdr + 1);
struct rxrpc_crypt iv;
struct scatterlist sg;
- size_t pad;
+ size_t content, pad;
u16 check;
int ret;
@@ -309,23 +315,20 @@ static int rxkad_secure_packet_encrypt(const struct rxrpc_call *call,
rxkhdr->data_size = htonl(txb->len | (u32)check << 16);
rxkhdr->checksum = 0;
- txb->len += sizeof(struct rxkad_level2_hdr);
- pad = txb->len;
- pad = RXKAD_ALIGN - pad;
- pad &= RXKAD_ALIGN - 1;
- if (pad) {
+ content = sizeof(struct rxkad_level2_hdr) + txb->len;
+ txb->pkt_len = round_up(content, RXKAD_ALIGN);
+ pad = txb->pkt_len - content;
+ if (pad)
memset(txb->kvec[0].iov_base + txb->offset, 0, pad);
- txb->len += pad;
- }
/* encrypt from the session key */
token = call->conn->key->payload.data[0];
memcpy(&iv, token->kad->session_key, sizeof(iv));
- sg_init_one(&sg, rxkhdr, txb->len);
+ sg_init_one(&sg, rxkhdr, txb->pkt_len);
skcipher_request_set_sync_tfm(req, call->conn->rxkad.cipher);
skcipher_request_set_callback(req, 0, NULL, NULL);
- skcipher_request_set_crypt(req, &sg, &sg, txb->len, iv.x);
+ skcipher_request_set_crypt(req, &sg, &sg, txb->pkt_len, iv.x);
ret = crypto_skcipher_encrypt(req);
skcipher_request_zero(req);
return ret;
@@ -384,19 +387,33 @@ static int rxkad_secure_packet(struct rxrpc_call *call, struct rxrpc_txbuf *txb)
switch (call->conn->security_level) {
case RXRPC_SECURITY_PLAIN:
+ txb->pkt_len = txb->len;
ret = 0;
break;
case RXRPC_SECURITY_AUTH:
ret = rxkad_secure_packet_auth(call, txb, req);
+ if (txb->alloc_size == RXRPC_JUMBO_DATALEN)
+ txb->jumboable = true;
break;
case RXRPC_SECURITY_ENCRYPT:
ret = rxkad_secure_packet_encrypt(call, txb, req);
+ if (txb->alloc_size == RXRPC_JUMBO_DATALEN)
+ txb->jumboable = true;
break;
default:
ret = -EPERM;
break;
}
+ /* Clear excess space in the packet */
+ if (txb->pkt_len < txb->alloc_size) {
+ struct rxrpc_wire_header *whdr = txb->kvec[0].iov_base;
+ size_t gap = txb->alloc_size - txb->pkt_len;
+ void *p = whdr + 1;
+
+ memset(p + txb->pkt_len, 0, gap);
+ }
+
skcipher_request_free(req);
_leave(" = %d [set %x]", ret, y);
return ret;
diff --git a/net/rxrpc/rxperf.c b/net/rxrpc/rxperf.c
index 085e7892d310..7ef93407be83 100644
--- a/net/rxrpc/rxperf.c
+++ b/net/rxrpc/rxperf.c
@@ -503,7 +503,7 @@ static int rxperf_process_call(struct rxperf_call *call)
reply_len + sizeof(rxperf_magic_cookie));
while (reply_len > 0) {
- len = min_t(size_t, reply_len, PAGE_SIZE);
+ len = umin(reply_len, PAGE_SIZE);
bvec_set_page(&bv, ZERO_PAGE(0), len, 0);
iov_iter_bvec(&msg.msg_iter, WRITE, &bv, 1, len);
msg.msg_flags = MSG_MORE;
diff --git a/net/rxrpc/security.c b/net/rxrpc/security.c
index cb8dd1d3b1d4..9784adc8f275 100644
--- a/net/rxrpc/security.c
+++ b/net/rxrpc/security.c
@@ -114,10 +114,10 @@ found:
if (conn->state == RXRPC_CONN_CLIENT_UNSECURED) {
ret = conn->security->init_connection_security(conn, token);
if (ret == 0) {
- spin_lock(&conn->state_lock);
+ spin_lock_irq(&conn->state_lock);
if (conn->state == RXRPC_CONN_CLIENT_UNSECURED)
conn->state = RXRPC_CONN_CLIENT;
- spin_unlock(&conn->state_lock);
+ spin_unlock_irq(&conn->state_lock);
}
}
mutex_unlock(&conn->security_lock);
diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c
index 6abb8eec1b2b..0e8da909d4f2 100644
--- a/net/rxrpc/sendmsg.c
+++ b/net/rxrpc/sendmsg.c
@@ -94,9 +94,11 @@ no_wait:
*/
static bool rxrpc_check_tx_space(struct rxrpc_call *call, rxrpc_seq_t *_tx_win)
{
+ rxrpc_seq_t tx_bottom = READ_ONCE(call->tx_bottom);
+
if (_tx_win)
- *_tx_win = call->tx_bottom;
- return call->tx_prepared - call->tx_bottom < 256;
+ *_tx_win = tx_bottom;
+ return call->send_top - tx_bottom < 256;
}
/*
@@ -132,13 +134,13 @@ static int rxrpc_wait_for_tx_window_waitall(struct rxrpc_sock *rx,
rxrpc_seq_t tx_start, tx_win;
signed long rtt, timeout;
- rtt = READ_ONCE(call->peer->srtt_us) >> 3;
+ rtt = READ_ONCE(call->srtt_us) >> 3;
rtt = usecs_to_jiffies(rtt) * 2;
if (rtt < 2)
rtt = 2;
timeout = rtt;
- tx_start = smp_load_acquire(&call->acks_hard_ack);
+ tx_start = READ_ONCE(call->tx_bottom);
for (;;) {
set_current_state(TASK_UNINTERRUPTIBLE);
@@ -195,8 +197,8 @@ static int rxrpc_wait_for_tx_window(struct rxrpc_sock *rx,
DECLARE_WAITQUEUE(myself, current);
int ret;
- _enter(",{%u,%u,%u,%u}",
- call->tx_bottom, call->acks_hard_ack, call->tx_top, call->tx_winsize);
+ _enter(",{%u,%u,%u}",
+ call->tx_bottom, call->tx_top, call->tx_winsize);
add_wait_queue(&call->waitq, &myself);
@@ -240,37 +242,77 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
struct rxrpc_txbuf *txb,
rxrpc_notify_end_tx_t notify_end_tx)
{
+ struct rxrpc_txqueue *sq = call->send_queue;
rxrpc_seq_t seq = txb->seq;
bool poke, last = txb->flags & RXRPC_LAST_PACKET;
-
+ int ix = seq & RXRPC_TXQ_MASK;
rxrpc_inc_stat(call->rxnet, stat_tx_data);
- ASSERTCMP(txb->seq, ==, call->tx_prepared + 1);
-
- /* We have to set the timestamp before queueing as the retransmit
- * algorithm can see the packet as soon as we queue it.
- */
- txb->last_sent = ktime_get_real();
+ ASSERTCMP(txb->seq, ==, call->send_top + 1);
if (last)
trace_rxrpc_txqueue(call, rxrpc_txqueue_queue_last);
else
trace_rxrpc_txqueue(call, rxrpc_txqueue_queue);
+ if (WARN_ON_ONCE(sq->bufs[ix]))
+ trace_rxrpc_tq(call, sq, seq, rxrpc_tq_queue_dup);
+ else
+ trace_rxrpc_tq(call, sq, seq, rxrpc_tq_queue);
+
/* Add the packet to the call's output buffer */
- spin_lock(&call->tx_lock);
- poke = list_empty(&call->tx_sendmsg);
- list_add_tail(&txb->call_link, &call->tx_sendmsg);
- call->tx_prepared = seq;
- if (last)
+ poke = (READ_ONCE(call->tx_bottom) == call->send_top);
+ sq->bufs[ix] = txb;
+ /* Order send_top after the queue->next pointer and txb content. */
+ smp_store_release(&call->send_top, seq);
+ if (last) {
+ set_bit(RXRPC_CALL_TX_NO_MORE, &call->flags);
rxrpc_notify_end_tx(rx, call, notify_end_tx);
- spin_unlock(&call->tx_lock);
+ call->send_queue = NULL;
+ }
if (poke)
rxrpc_poke_call(call, rxrpc_call_poke_start);
}
/*
+ * Allocate a new txqueue unit and add it to the transmission queue.
+ */
+static int rxrpc_alloc_txqueue(struct sock *sk, struct rxrpc_call *call)
+{
+ struct rxrpc_txqueue *tq;
+
+ tq = kzalloc(sizeof(*tq), sk->sk_allocation);
+ if (!tq)
+ return -ENOMEM;
+
+ tq->xmit_ts_base = KTIME_MIN;
+ for (int i = 0; i < RXRPC_NR_TXQUEUE; i++)
+ tq->segment_xmit_ts[i] = UINT_MAX;
+
+ if (call->send_queue) {
+ tq->qbase = call->send_top + 1;
+ call->send_queue->next = tq;
+ call->send_queue = tq;
+ } else if (WARN_ON(call->tx_queue)) {
+ kfree(tq);
+ return -ENOMEM;
+ } else {
+ /* We start at seq 1, so pretend seq 0 is hard-acked. */
+ tq->nr_reported_acks = 1;
+ tq->segment_acked = 1UL;
+ tq->qbase = 0;
+ call->tx_qbase = 0;
+ call->send_queue = tq;
+ call->tx_qtail = tq;
+ call->tx_queue = tq;
+ }
+
+ trace_rxrpc_tq(call, tq, call->send_top, rxrpc_tq_alloc);
+ return 0;
+}
+
+/*
* send data through a socket
* - must be called in process context
* - The caller holds the call user access mutex, but not the socket lock.
@@ -288,6 +330,13 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
bool more = msg->msg_flags & MSG_MORE;
int ret, copied = 0;
+ if (test_bit(RXRPC_CALL_TX_NO_MORE, &call->flags)) {
+ trace_rxrpc_abort(call->debug_id, rxrpc_sendmsg_late_send,
+ call->cid, call->call_id, call->rx_consumed,
+ 0, -EPROTO);
+ return -EPROTO;
+ }
+
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
ret = rxrpc_wait_to_be_connected(call, &timeo);
@@ -344,6 +393,13 @@ reload:
if (!rxrpc_check_tx_space(call, NULL))
goto wait_for_space;
+ /* See if we need to begin/extend the Tx queue. */
+ if (!call->send_queue || !((call->send_top + 1) & RXRPC_TXQ_MASK)) {
+ ret = rxrpc_alloc_txqueue(sk, call);
+ if (ret < 0)
+ goto maybe_error;
+ }
+
/* Work out the maximum size of a packet. Assume that
* the security header is going to be in the padded
* region (enc blocksize), but the trailer is not.
@@ -360,7 +416,7 @@ reload:
/* append next segment of data to the current buffer */
if (msg_data_left(msg) > 0) {
- size_t copy = min_t(size_t, txb->space, msg_data_left(msg));
+ size_t copy = umin(txb->space, msg_data_left(msg));
_debug("add %zu", copy);
if (!copy_from_iter_full(txb->kvec[0].iov_base + txb->offset,
@@ -385,16 +441,12 @@ reload:
(msg_data_left(msg) == 0 && !more)) {
if (msg_data_left(msg) == 0 && !more)
txb->flags |= RXRPC_LAST_PACKET;
- else if (call->tx_top - call->acks_hard_ack <
- call->tx_winsize)
- txb->flags |= RXRPC_MORE_PACKETS;
ret = call->security->secure_packet(call, txb);
if (ret < 0)
goto out;
txb->kvec[0].iov_len += txb->len;
- txb->len = txb->kvec[0].iov_len;
rxrpc_queue_packet(rx, call, txb, notify_end_tx);
txb = NULL;
}
diff --git a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c
index 9bf9a1f6e4cb..46a20cf4c402 100644
--- a/net/rxrpc/sysctl.c
+++ b/net/rxrpc/sysctl.c
@@ -11,6 +11,8 @@
#include "ar-internal.h"
static struct ctl_table_header *rxrpc_sysctl_reg_table;
+static const unsigned int rxrpc_rx_mtu_min = 500;
+static const unsigned int rxrpc_jumbo_max = RXRPC_MAX_NR_JUMBO;
static const unsigned int four = 4;
static const unsigned int max_backlog = RXRPC_BACKLOG_MAX - 1;
static const unsigned int n_65535 = 65535;
@@ -115,7 +117,7 @@ static struct ctl_table rxrpc_sysctl_table[] = {
.maxlen = sizeof(unsigned int),
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
- .extra1 = (void *)SYSCTL_ONE,
+ .extra1 = (void *)&rxrpc_rx_mtu_min,
.extra2 = (void *)&n_65535,
},
{
@@ -125,7 +127,7 @@ static struct ctl_table rxrpc_sysctl_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec_minmax,
.extra1 = (void *)SYSCTL_ONE,
- .extra2 = (void *)&four,
+ .extra2 = (void *)&rxrpc_jumbo_max,
},
};
diff --git a/net/rxrpc/txbuf.c b/net/rxrpc/txbuf.c
index c3913d8a50d3..131d9e55c8e9 100644
--- a/net/rxrpc/txbuf.c
+++ b/net/rxrpc/txbuf.c
@@ -24,7 +24,7 @@ struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_
size_t total, hoff;
void *buf;
- txb = kmalloc(sizeof(*txb), gfp);
+ txb = kzalloc(sizeof(*txb), gfp);
if (!txb)
return NULL;
@@ -43,20 +43,14 @@ struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_
whdr = buf + hoff;
- INIT_LIST_HEAD(&txb->call_link);
- INIT_LIST_HEAD(&txb->tx_link);
refcount_set(&txb->ref, 1);
- txb->last_sent = KTIME_MIN;
txb->call_debug_id = call->debug_id;
txb->debug_id = atomic_inc_return(&rxrpc_txbuf_debug_ids);
+ txb->alloc_size = data_size;
txb->space = data_size;
- txb->len = 0;
txb->offset = sizeof(*whdr);
txb->flags = call->conn->out_clientflag;
- txb->ack_why = 0;
- txb->seq = call->tx_prepared + 1;
- txb->serial = 0;
- txb->cksum = 0;
+ txb->seq = call->send_top + 1;
txb->nr_kvec = 1;
txb->kvec[0].iov_base = whdr;
txb->kvec[0].iov_len = sizeof(*whdr);
@@ -79,84 +73,6 @@ struct rxrpc_txbuf *rxrpc_alloc_data_txbuf(struct rxrpc_call *call, size_t data_
return txb;
}
-/*
- * Allocate and partially initialise an ACK packet.
- */
-struct rxrpc_txbuf *rxrpc_alloc_ack_txbuf(struct rxrpc_call *call, size_t sack_size)
-{
- struct rxrpc_wire_header *whdr;
- struct rxrpc_acktrailer *trailer;
- struct rxrpc_ackpacket *ack;
- struct rxrpc_txbuf *txb;
- gfp_t gfp = rcu_read_lock_held() ? GFP_ATOMIC | __GFP_NOWARN : GFP_NOFS;
- void *buf, *buf2 = NULL;
- u8 *filler;
-
- txb = kmalloc(sizeof(*txb), gfp);
- if (!txb)
- return NULL;
-
- buf = page_frag_alloc(&call->local->tx_alloc,
- sizeof(*whdr) + sizeof(*ack) + 1 + 3 + sizeof(*trailer), gfp);
- if (!buf) {
- kfree(txb);
- return NULL;
- }
-
- if (sack_size) {
- buf2 = page_frag_alloc(&call->local->tx_alloc, sack_size, gfp);
- if (!buf2) {
- page_frag_free(buf);
- kfree(txb);
- return NULL;
- }
- }
-
- whdr = buf;
- ack = buf + sizeof(*whdr);
- filler = buf + sizeof(*whdr) + sizeof(*ack) + 1;
- trailer = buf + sizeof(*whdr) + sizeof(*ack) + 1 + 3;
-
- INIT_LIST_HEAD(&txb->call_link);
- INIT_LIST_HEAD(&txb->tx_link);
- refcount_set(&txb->ref, 1);
- txb->call_debug_id = call->debug_id;
- txb->debug_id = atomic_inc_return(&rxrpc_txbuf_debug_ids);
- txb->space = 0;
- txb->len = sizeof(*whdr) + sizeof(*ack) + 3 + sizeof(*trailer);
- txb->offset = 0;
- txb->flags = call->conn->out_clientflag;
- txb->ack_rwind = 0;
- txb->seq = 0;
- txb->serial = 0;
- txb->cksum = 0;
- txb->nr_kvec = 3;
- txb->kvec[0].iov_base = whdr;
- txb->kvec[0].iov_len = sizeof(*whdr) + sizeof(*ack);
- txb->kvec[1].iov_base = buf2;
- txb->kvec[1].iov_len = sack_size;
- txb->kvec[2].iov_base = filler;
- txb->kvec[2].iov_len = 3 + sizeof(*trailer);
-
- whdr->epoch = htonl(call->conn->proto.epoch);
- whdr->cid = htonl(call->cid);
- whdr->callNumber = htonl(call->call_id);
- whdr->seq = 0;
- whdr->type = RXRPC_PACKET_TYPE_ACK;
- whdr->flags = 0;
- whdr->userStatus = 0;
- whdr->securityIndex = call->security_ix;
- whdr->_rsvd = 0;
- whdr->serviceId = htons(call->dest_srx.srx_service);
-
- get_page(virt_to_head_page(trailer));
-
- trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 1,
- rxrpc_txbuf_alloc_ack);
- atomic_inc(&rxrpc_nr_txbuf);
- return txb;
-}
-
void rxrpc_get_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what)
{
int r;
@@ -179,7 +95,8 @@ static void rxrpc_free_txbuf(struct rxrpc_txbuf *txb)
trace_rxrpc_txbuf(txb->debug_id, txb->call_debug_id, txb->seq, 0,
rxrpc_txbuf_free);
for (i = 0; i < txb->nr_kvec; i++)
- if (txb->kvec[i].iov_base)
+ if (txb->kvec[i].iov_base &&
+ !is_zero_pfn(page_to_pfn(virt_to_page(txb->kvec[i].iov_base))))
page_frag_free(txb->kvec[i].iov_base);
kfree(txb);
atomic_dec(&rxrpc_nr_txbuf);
@@ -202,37 +119,3 @@ void rxrpc_put_txbuf(struct rxrpc_txbuf *txb, enum rxrpc_txbuf_trace what)
rxrpc_free_txbuf(txb);
}
}
-
-/*
- * Shrink the transmit buffer.
- */
-void rxrpc_shrink_call_tx_buffer(struct rxrpc_call *call)
-{
- struct rxrpc_txbuf *txb;
- rxrpc_seq_t hard_ack = smp_load_acquire(&call->acks_hard_ack);
- bool wake = false;
-
- _enter("%x/%x/%x", call->tx_bottom, call->acks_hard_ack, call->tx_top);
-
- while ((txb = list_first_entry_or_null(&call->tx_buffer,
- struct rxrpc_txbuf, call_link))) {
- hard_ack = smp_load_acquire(&call->acks_hard_ack);
- if (before(hard_ack, txb->seq))
- break;
-
- if (txb->seq != call->tx_bottom + 1)
- rxrpc_see_txbuf(txb, rxrpc_txbuf_see_out_of_step);
- ASSERTCMP(txb->seq, ==, call->tx_bottom + 1);
- smp_store_release(&call->tx_bottom, call->tx_bottom + 1);
- list_del_rcu(&txb->call_link);
-
- trace_rxrpc_txqueue(call, rxrpc_txqueue_dequeue);
-
- rxrpc_put_txbuf(txb, rxrpc_txbuf_put_rotated);
- if (after(call->acks_hard_ack, call->tx_bottom + 128))
- wake = true;
- }
-
- if (wake)
- wake_up(&call->waitq);
-}
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c
index 5502998aace7..5c2580a07530 100644
--- a/net/sched/cls_flow.c
+++ b/net/sched/cls_flow.c
@@ -356,7 +356,8 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = {
[TCA_FLOW_KEYS] = { .type = NLA_U32 },
[TCA_FLOW_MODE] = { .type = NLA_U32 },
[TCA_FLOW_BASECLASS] = { .type = NLA_U32 },
- [TCA_FLOW_RSHIFT] = { .type = NLA_U32 },
+ [TCA_FLOW_RSHIFT] = NLA_POLICY_MAX(NLA_U32,
+ 31 /* BITS_PER_U32 - 1 */),
[TCA_FLOW_ADDEND] = { .type = NLA_U32 },
[TCA_FLOW_MASK] = { .type = NLA_U32 },
[TCA_FLOW_XOR] = { .type = NLA_U32 },
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index e280c27cb9f9..1008ec8a464c 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -1369,7 +1369,6 @@ static int fl_set_erspan_opt(const struct nlattr *nla, struct fl_flow_key *key,
int err;
md = (struct erspan_metadata *)&key->enc_opts.data[key->enc_opts.len];
- memset(md, 0xff, sizeof(*md));
md->version = 1;
if (!depth)
@@ -1398,9 +1397,9 @@ static int fl_set_erspan_opt(const struct nlattr *nla, struct fl_flow_key *key,
NL_SET_ERR_MSG(extack, "Missing tunnel key erspan option index");
return -EINVAL;
}
+ memset(&md->u.index, 0xff, sizeof(md->u.index));
if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX]) {
nla = tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX];
- memset(&md->u, 0x00, sizeof(md->u));
md->u.index = nla_get_be32(nla);
}
} else if (md->version == 2) {
@@ -1409,10 +1408,12 @@ static int fl_set_erspan_opt(const struct nlattr *nla, struct fl_flow_key *key,
NL_SET_ERR_MSG(extack, "Missing tunnel key erspan option dir or hwid");
return -EINVAL;
}
+ md->u.md2.dir = 1;
if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR]) {
nla = tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR];
md->u.md2.dir = nla_get_u8(nla);
}
+ set_hwid(&md->u.md2, 0xff);
if (tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID]) {
nla = tb[TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID];
set_hwid(&md->u.md2, nla_get_u8(nla));
diff --git a/net/sched/sch_cake.c b/net/sched/sch_cake.c
index f2f9b75008bb..48dd8c88903f 100644
--- a/net/sched/sch_cake.c
+++ b/net/sched/sch_cake.c
@@ -484,13 +484,14 @@ static bool cobalt_queue_empty(struct cobalt_vars *vars,
/* Call this with a freshly dequeued packet for possible congestion marking.
* Returns true as an instruction to drop the packet, false for delivery.
*/
-static bool cobalt_should_drop(struct cobalt_vars *vars,
- struct cobalt_params *p,
- ktime_t now,
- struct sk_buff *skb,
- u32 bulk_flows)
+static enum skb_drop_reason cobalt_should_drop(struct cobalt_vars *vars,
+ struct cobalt_params *p,
+ ktime_t now,
+ struct sk_buff *skb,
+ u32 bulk_flows)
{
- bool next_due, over_target, drop = false;
+ enum skb_drop_reason reason = SKB_NOT_DROPPED_YET;
+ bool next_due, over_target;
ktime_t schedule;
u64 sojourn;
@@ -533,7 +534,8 @@ static bool cobalt_should_drop(struct cobalt_vars *vars,
if (next_due && vars->dropping) {
/* Use ECN mark if possible, otherwise drop */
- drop = !(vars->ecn_marked = INET_ECN_set_ce(skb));
+ if (!(vars->ecn_marked = INET_ECN_set_ce(skb)))
+ reason = SKB_DROP_REASON_QDISC_CONGESTED;
vars->count++;
if (!vars->count)
@@ -556,16 +558,17 @@ static bool cobalt_should_drop(struct cobalt_vars *vars,
}
/* Simple BLUE implementation. Lack of ECN is deliberate. */
- if (vars->p_drop)
- drop |= (get_random_u32() < vars->p_drop);
+ if (vars->p_drop && reason == SKB_NOT_DROPPED_YET &&
+ get_random_u32() < vars->p_drop)
+ reason = SKB_DROP_REASON_CAKE_FLOOD;
/* Overload the drop_next field as an activity timeout */
if (!vars->count)
vars->drop_next = ktime_add_ns(now, p->interval);
- else if (ktime_to_ns(schedule) > 0 && !drop)
+ else if (ktime_to_ns(schedule) > 0 && reason == SKB_NOT_DROPPED_YET)
vars->drop_next = now;
- return drop;
+ return reason;
}
static bool cake_update_flowkeys(struct flow_keys *keys,
@@ -627,6 +630,63 @@ static bool cake_ddst(int flow_mode)
return (flow_mode & CAKE_FLOW_DUAL_DST) == CAKE_FLOW_DUAL_DST;
}
+static void cake_dec_srchost_bulk_flow_count(struct cake_tin_data *q,
+ struct cake_flow *flow,
+ int flow_mode)
+{
+ if (likely(cake_dsrc(flow_mode) &&
+ q->hosts[flow->srchost].srchost_bulk_flow_count))
+ q->hosts[flow->srchost].srchost_bulk_flow_count--;
+}
+
+static void cake_inc_srchost_bulk_flow_count(struct cake_tin_data *q,
+ struct cake_flow *flow,
+ int flow_mode)
+{
+ if (likely(cake_dsrc(flow_mode) &&
+ q->hosts[flow->srchost].srchost_bulk_flow_count < CAKE_QUEUES))
+ q->hosts[flow->srchost].srchost_bulk_flow_count++;
+}
+
+static void cake_dec_dsthost_bulk_flow_count(struct cake_tin_data *q,
+ struct cake_flow *flow,
+ int flow_mode)
+{
+ if (likely(cake_ddst(flow_mode) &&
+ q->hosts[flow->dsthost].dsthost_bulk_flow_count))
+ q->hosts[flow->dsthost].dsthost_bulk_flow_count--;
+}
+
+static void cake_inc_dsthost_bulk_flow_count(struct cake_tin_data *q,
+ struct cake_flow *flow,
+ int flow_mode)
+{
+ if (likely(cake_ddst(flow_mode) &&
+ q->hosts[flow->dsthost].dsthost_bulk_flow_count < CAKE_QUEUES))
+ q->hosts[flow->dsthost].dsthost_bulk_flow_count++;
+}
+
+static u16 cake_get_flow_quantum(struct cake_tin_data *q,
+ struct cake_flow *flow,
+ int flow_mode)
+{
+ u16 host_load = 1;
+
+ if (cake_dsrc(flow_mode))
+ host_load = max(host_load,
+ q->hosts[flow->srchost].srchost_bulk_flow_count);
+
+ if (cake_ddst(flow_mode))
+ host_load = max(host_load,
+ q->hosts[flow->dsthost].dsthost_bulk_flow_count);
+
+ /* The get_random_u16() is a way to apply dithering to avoid
+ * accumulating roundoff errors
+ */
+ return (q->flow_quantum * quantum_div[host_load] +
+ get_random_u16()) >> 16;
+}
+
static u32 cake_hash(struct cake_tin_data *q, const struct sk_buff *skb,
int flow_mode, u16 flow_override, u16 host_override)
{
@@ -773,10 +833,8 @@ skip_hash:
allocate_dst = cake_ddst(flow_mode);
if (q->flows[outer_hash + k].set == CAKE_SET_BULK) {
- if (allocate_src)
- q->hosts[q->flows[reduced_hash].srchost].srchost_bulk_flow_count--;
- if (allocate_dst)
- q->hosts[q->flows[reduced_hash].dsthost].dsthost_bulk_flow_count--;
+ cake_dec_srchost_bulk_flow_count(q, &q->flows[outer_hash + k], flow_mode);
+ cake_dec_dsthost_bulk_flow_count(q, &q->flows[outer_hash + k], flow_mode);
}
found:
/* reserve queue for future packets in same flow */
@@ -801,9 +859,10 @@ found:
q->hosts[outer_hash + k].srchost_tag = srchost_hash;
found_src:
srchost_idx = outer_hash + k;
- if (q->flows[reduced_hash].set == CAKE_SET_BULK)
- q->hosts[srchost_idx].srchost_bulk_flow_count++;
q->flows[reduced_hash].srchost = srchost_idx;
+
+ if (q->flows[reduced_hash].set == CAKE_SET_BULK)
+ cake_inc_srchost_bulk_flow_count(q, &q->flows[reduced_hash], flow_mode);
}
if (allocate_dst) {
@@ -824,9 +883,10 @@ found_src:
q->hosts[outer_hash + k].dsthost_tag = dsthost_hash;
found_dst:
dsthost_idx = outer_hash + k;
- if (q->flows[reduced_hash].set == CAKE_SET_BULK)
- q->hosts[dsthost_idx].dsthost_bulk_flow_count++;
q->flows[reduced_hash].dsthost = dsthost_idx;
+
+ if (q->flows[reduced_hash].set == CAKE_SET_BULK)
+ cake_inc_dsthost_bulk_flow_count(q, &q->flows[reduced_hash], flow_mode);
}
}
@@ -1525,17 +1585,16 @@ static unsigned int cake_drop(struct Qdisc *sch, struct sk_buff **to_free)
b->backlogs[idx] -= len;
b->tin_backlog -= len;
sch->qstats.backlog -= len;
- qdisc_tree_reduce_backlog(sch, 1, len);
flow->dropped++;
b->tin_dropped++;
- sch->qstats.drops++;
if (q->rate_flags & CAKE_FLAG_INGRESS)
cake_advance_shaper(q, b, skb, now, true);
- __qdisc_drop(skb, to_free);
+ qdisc_drop_reason(skb, sch, to_free, SKB_DROP_REASON_QDISC_OVERLIMIT);
sch->q.qlen--;
+ qdisc_tree_reduce_backlog(sch, 1, len);
cake_heapify(q, 0);
@@ -1839,10 +1898,6 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
/* flowchain */
if (!flow->set || flow->set == CAKE_SET_DECAYING) {
- struct cake_host *srchost = &b->hosts[flow->srchost];
- struct cake_host *dsthost = &b->hosts[flow->dsthost];
- u16 host_load = 1;
-
if (!flow->set) {
list_add_tail(&flow->flowchain, &b->new_flows);
} else {
@@ -1852,18 +1907,8 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
flow->set = CAKE_SET_SPARSE;
b->sparse_flow_count++;
- if (cake_dsrc(q->flow_mode))
- host_load = max(host_load, srchost->srchost_bulk_flow_count);
-
- if (cake_ddst(q->flow_mode))
- host_load = max(host_load, dsthost->dsthost_bulk_flow_count);
-
- flow->deficit = (b->flow_quantum *
- quantum_div[host_load]) >> 16;
+ flow->deficit = cake_get_flow_quantum(b, flow, q->flow_mode);
} else if (flow->set == CAKE_SET_SPARSE_WAIT) {
- struct cake_host *srchost = &b->hosts[flow->srchost];
- struct cake_host *dsthost = &b->hosts[flow->dsthost];
-
/* this flow was empty, accounted as a sparse flow, but actually
* in the bulk rotation.
*/
@@ -1871,12 +1916,8 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
b->sparse_flow_count--;
b->bulk_flow_count++;
- if (cake_dsrc(q->flow_mode))
- srchost->srchost_bulk_flow_count++;
-
- if (cake_ddst(q->flow_mode))
- dsthost->dsthost_bulk_flow_count++;
-
+ cake_inc_srchost_bulk_flow_count(b, flow, q->flow_mode);
+ cake_inc_dsthost_bulk_flow_count(b, flow, q->flow_mode);
}
if (q->buffer_used > q->buffer_max_used)
@@ -1926,20 +1967,19 @@ static void cake_clear_tin(struct Qdisc *sch, u16 tin)
q->cur_tin = tin;
for (q->cur_flow = 0; q->cur_flow < CAKE_QUEUES; q->cur_flow++)
while (!!(skb = cake_dequeue_one(sch)))
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_QUEUE_PURGE);
}
static struct sk_buff *cake_dequeue(struct Qdisc *sch)
{
struct cake_sched_data *q = qdisc_priv(sch);
struct cake_tin_data *b = &q->tins[q->cur_tin];
- struct cake_host *srchost, *dsthost;
+ enum skb_drop_reason reason;
ktime_t now = ktime_get();
struct cake_flow *flow;
struct list_head *head;
bool first_flow = true;
struct sk_buff *skb;
- u16 host_load;
u64 delay;
u32 len;
@@ -2039,11 +2079,6 @@ retry:
q->cur_flow = flow - b->flows;
first_flow = false;
- /* triple isolation (modified DRR++) */
- srchost = &b->hosts[flow->srchost];
- dsthost = &b->hosts[flow->dsthost];
- host_load = 1;
-
/* flow isolation (DRR++) */
if (flow->deficit <= 0) {
/* Keep all flows with deficits out of the sparse and decaying
@@ -2055,11 +2090,8 @@ retry:
b->sparse_flow_count--;
b->bulk_flow_count++;
- if (cake_dsrc(q->flow_mode))
- srchost->srchost_bulk_flow_count++;
-
- if (cake_ddst(q->flow_mode))
- dsthost->dsthost_bulk_flow_count++;
+ cake_inc_srchost_bulk_flow_count(b, flow, q->flow_mode);
+ cake_inc_dsthost_bulk_flow_count(b, flow, q->flow_mode);
flow->set = CAKE_SET_BULK;
} else {
@@ -2071,19 +2103,7 @@ retry:
}
}
- if (cake_dsrc(q->flow_mode))
- host_load = max(host_load, srchost->srchost_bulk_flow_count);
-
- if (cake_ddst(q->flow_mode))
- host_load = max(host_load, dsthost->dsthost_bulk_flow_count);
-
- WARN_ON(host_load > CAKE_QUEUES);
-
- /* The get_random_u16() is a way to apply dithering to avoid
- * accumulating roundoff errors
- */
- flow->deficit += (b->flow_quantum * quantum_div[host_load] +
- get_random_u16()) >> 16;
+ flow->deficit += cake_get_flow_quantum(b, flow, q->flow_mode);
list_move_tail(&flow->flowchain, &b->old_flows);
goto retry;
@@ -2107,11 +2127,8 @@ retry:
if (flow->set == CAKE_SET_BULK) {
b->bulk_flow_count--;
- if (cake_dsrc(q->flow_mode))
- srchost->srchost_bulk_flow_count--;
-
- if (cake_ddst(q->flow_mode))
- dsthost->dsthost_bulk_flow_count--;
+ cake_dec_srchost_bulk_flow_count(b, flow, q->flow_mode);
+ cake_dec_dsthost_bulk_flow_count(b, flow, q->flow_mode);
b->decaying_flow_count++;
} else if (flow->set == CAKE_SET_SPARSE ||
@@ -2129,12 +2146,8 @@ retry:
else if (flow->set == CAKE_SET_BULK) {
b->bulk_flow_count--;
- if (cake_dsrc(q->flow_mode))
- srchost->srchost_bulk_flow_count--;
-
- if (cake_ddst(q->flow_mode))
- dsthost->dsthost_bulk_flow_count--;
-
+ cake_dec_srchost_bulk_flow_count(b, flow, q->flow_mode);
+ cake_dec_dsthost_bulk_flow_count(b, flow, q->flow_mode);
} else
b->decaying_flow_count--;
@@ -2143,12 +2156,12 @@ retry:
goto begin;
}
+ reason = cobalt_should_drop(&flow->cvars, &b->cparams, now, skb,
+ (b->bulk_flow_count *
+ !!(q->rate_flags &
+ CAKE_FLAG_INGRESS)));
/* Last packet in queue may be marked, shouldn't be dropped */
- if (!cobalt_should_drop(&flow->cvars, &b->cparams, now, skb,
- (b->bulk_flow_count *
- !!(q->rate_flags &
- CAKE_FLAG_INGRESS))) ||
- !flow->head)
+ if (reason == SKB_NOT_DROPPED_YET || !flow->head)
break;
/* drop this packet, get another one */
@@ -2162,7 +2175,7 @@ retry:
b->tin_dropped++;
qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(skb));
qdisc_qstats_drop(sch);
- kfree_skb(skb);
+ kfree_skb_reason(skb, reason);
if (q->rate_flags & CAKE_FLAG_INGRESS)
goto retry;
}
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c
index 1e940ad0d2fa..59e7bdf5063e 100644
--- a/net/sched/sch_choke.c
+++ b/net/sched/sch_choke.c
@@ -123,10 +123,10 @@ static void choke_drop_by_idx(struct Qdisc *sch, unsigned int idx,
if (idx == q->tail)
choke_zap_tail_holes(q);
+ --sch->q.qlen;
qdisc_qstats_backlog_dec(sch, skb);
qdisc_tree_reduce_backlog(sch, 1, qdisc_pkt_len(skb));
qdisc_drop(skb, sch, to_free);
- --sch->q.qlen;
}
struct choke_skb_cb {
diff --git a/net/sched/sch_codel.c b/net/sched/sch_codel.c
index 3e8d4fe4d91e..81189d02fee7 100644
--- a/net/sched/sch_codel.c
+++ b/net/sched/sch_codel.c
@@ -52,7 +52,7 @@ static void drop_func(struct sk_buff *skb, void *ctx)
{
struct Qdisc *sch = ctx;
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_QDISC_CONGESTED);
qdisc_qstats_drop(sch);
}
@@ -89,7 +89,8 @@ static int codel_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
}
q = qdisc_priv(sch);
q->drop_overlimit++;
- return qdisc_drop(skb, sch, to_free);
+ return qdisc_drop_reason(skb, sch, to_free,
+ SKB_DROP_REASON_QDISC_OVERLIMIT);
}
static const struct nla_policy codel_policy[TCA_CODEL_MAX + 1] = {
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c
index a5e87f9ea986..2ca5332cfcc5 100644
--- a/net/sched/sch_fq.c
+++ b/net/sched/sch_fq.c
@@ -537,6 +537,8 @@ static bool fq_packet_beyond_horizon(const struct sk_buff *skb,
return unlikely((s64)skb->tstamp > (s64)(now + q->horizon));
}
+#define FQDR(reason) SKB_DROP_REASON_FQ_##reason
+
static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
@@ -548,7 +550,8 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
band = fq_prio2band(q->prio2band, skb->priority & TC_PRIO_MAX);
if (unlikely(q->band_pkt_count[band] >= sch->limit)) {
q->stat_band_drops[band]++;
- return qdisc_drop(skb, sch, to_free);
+ return qdisc_drop_reason(skb, sch, to_free,
+ FQDR(BAND_LIMIT));
}
now = ktime_get_ns();
@@ -558,8 +561,9 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
/* Check if packet timestamp is too far in the future. */
if (fq_packet_beyond_horizon(skb, q, now)) {
if (q->horizon_drop) {
- q->stat_horizon_drops++;
- return qdisc_drop(skb, sch, to_free);
+ q->stat_horizon_drops++;
+ return qdisc_drop_reason(skb, sch, to_free,
+ FQDR(HORIZON_LIMIT));
}
q->stat_horizon_caps++;
skb->tstamp = now + q->horizon;
@@ -572,7 +576,8 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
if (f != &q->internal) {
if (unlikely(f->qlen >= q->flow_plimit)) {
q->stat_flows_plimit++;
- return qdisc_drop(skb, sch, to_free);
+ return qdisc_drop_reason(skb, sch, to_free,
+ FQDR(FLOW_LIMIT));
}
if (fq_flow_is_detached(f)) {
@@ -597,6 +602,7 @@ static int fq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
return NET_XMIT_SUCCESS;
}
+#undef FQDR
static void fq_check_throttled(struct fq_sched_data *q, u64 now)
{
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c
index 4f908c11ba95..799f5397ad4c 100644
--- a/net/sched/sch_fq_codel.c
+++ b/net/sched/sch_fq_codel.c
@@ -168,6 +168,7 @@ static unsigned int fq_codel_drop(struct Qdisc *sch, unsigned int max_packets,
skb = dequeue_head(flow);
len += qdisc_pkt_len(skb);
mem += get_codel_cb(skb)->mem_usage;
+ tcf_set_drop_reason(skb, SKB_DROP_REASON_QDISC_OVERLIMIT);
__qdisc_drop(skb, to_free);
} while (++i < max_packets && len < threshold);
@@ -274,7 +275,7 @@ static void drop_func(struct sk_buff *skb, void *ctx)
{
struct Qdisc *sch = ctx;
- kfree_skb(skb);
+ kfree_skb_reason(skb, SKB_DROP_REASON_QDISC_CONGESTED);
qdisc_qstats_drop(sch);
}
diff --git a/net/sched/sch_fq_pie.c b/net/sched/sch_fq_pie.c
index c38f33ff80bd..93c36afbf576 100644
--- a/net/sched/sch_fq_pie.c
+++ b/net/sched/sch_fq_pie.c
@@ -130,6 +130,7 @@ static inline void flow_queue_add(struct fq_pie_flow *flow,
static int fq_pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
+ enum skb_drop_reason reason = SKB_DROP_REASON_QDISC_OVERLIMIT;
struct fq_pie_sched_data *q = qdisc_priv(sch);
struct fq_pie_flow *sel_flow;
int ret;
@@ -161,6 +162,8 @@ static int fq_pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
q->overmemory++;
}
+ reason = SKB_DROP_REASON_QDISC_CONGESTED;
+
if (!pie_drop_early(sch, &q->p_params, &sel_flow->vars,
sel_flow->backlog, skb->len)) {
enqueue = true;
@@ -198,8 +201,7 @@ static int fq_pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
out:
q->stats.dropped++;
sel_flow->vars.accu_prob = 0;
- __qdisc_drop(skb, to_free);
- qdisc_qstats_drop(sch);
+ qdisc_drop_reason(skb, sch, to_free, reason);
return NET_XMIT_CN;
}
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c
index 38ec18f73de4..bb7dd351bd65 100644
--- a/net/sched/sch_generic.c
+++ b/net/sched/sch_generic.c
@@ -551,25 +551,20 @@ static void dev_watchdog(struct timer_list *t)
netdev_put(dev, &dev->watchdog_dev_tracker);
}
-void __netdev_watchdog_up(struct net_device *dev)
-{
- if (dev->netdev_ops->ndo_tx_timeout) {
- if (dev->watchdog_timeo <= 0)
- dev->watchdog_timeo = 5*HZ;
- if (!mod_timer(&dev->watchdog_timer,
- round_jiffies(jiffies + dev->watchdog_timeo)))
- netdev_hold(dev, &dev->watchdog_dev_tracker,
- GFP_ATOMIC);
- }
-}
-EXPORT_SYMBOL_GPL(__netdev_watchdog_up);
-
-static void dev_watchdog_up(struct net_device *dev)
+void netdev_watchdog_up(struct net_device *dev)
{
- __netdev_watchdog_up(dev);
+ if (!dev->netdev_ops->ndo_tx_timeout)
+ return;
+ if (dev->watchdog_timeo <= 0)
+ dev->watchdog_timeo = 5*HZ;
+ if (!mod_timer(&dev->watchdog_timer,
+ round_jiffies(jiffies + dev->watchdog_timeo)))
+ netdev_hold(dev, &dev->watchdog_dev_tracker,
+ GFP_ATOMIC);
}
+EXPORT_SYMBOL_GPL(netdev_watchdog_up);
-static void dev_watchdog_down(struct net_device *dev)
+static void netdev_watchdog_down(struct net_device *dev)
{
netif_tx_lock_bh(dev);
if (del_timer(&dev->watchdog_timer))
@@ -591,7 +586,7 @@ void netif_carrier_on(struct net_device *dev)
atomic_inc(&dev->carrier_up_count);
linkwatch_fire_event(dev);
if (netif_running(dev))
- __netdev_watchdog_up(dev);
+ netdev_watchdog_up(dev);
}
}
EXPORT_SYMBOL(netif_carrier_on);
@@ -911,8 +906,8 @@ static int pfifo_fast_change_tx_queue_len(struct Qdisc *sch,
bands[prio] = q;
}
- return skb_array_resize_multiple(bands, PFIFO_FAST_BANDS, new_len,
- GFP_KERNEL);
+ return skb_array_resize_multiple_bh(bands, PFIFO_FAST_BANDS, new_len,
+ GFP_KERNEL);
}
struct Qdisc_ops pfifo_fast_ops __read_mostly = {
@@ -1267,7 +1262,7 @@ void dev_activate(struct net_device *dev)
if (need_watchdog) {
netif_trans_update(dev);
- dev_watchdog_up(dev);
+ netdev_watchdog_up(dev);
}
}
EXPORT_SYMBOL(dev_activate);
@@ -1366,7 +1361,7 @@ void dev_deactivate_many(struct list_head *head)
dev_deactivate_queue(dev, dev_ingress_queue(dev),
&noop_qdisc);
- dev_watchdog_down(dev);
+ netdev_watchdog_down(dev);
}
/* Wait for outstanding qdisc-less dev_queue_xmit calls or
diff --git a/net/sched/sch_gred.c b/net/sched/sch_gred.c
index 7d2151c62c4a..ab6234b4fcd5 100644
--- a/net/sched/sch_gred.c
+++ b/net/sched/sch_gred.c
@@ -251,10 +251,10 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch,
q->stats.pdrop++;
drop:
- return qdisc_drop(skb, sch, to_free);
+ return qdisc_drop_reason(skb, sch, to_free, SKB_DROP_REASON_QDISC_OVERLIMIT);
congestion_drop:
- qdisc_drop(skb, sch, to_free);
+ qdisc_drop_reason(skb, sch, to_free, SKB_DROP_REASON_QDISC_CONGESTED);
return NET_XMIT_CN;
}
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c
index fe6fed291a7b..71ec9986ed37 100644
--- a/net/sched/sch_netem.c
+++ b/net/sched/sch_netem.c
@@ -79,6 +79,8 @@ struct netem_sched_data {
struct sk_buff *t_head;
struct sk_buff *t_tail;
+ u32 t_len;
+
/* optional qdisc for classful handling (NULL at netem init) */
struct Qdisc *qdisc;
@@ -383,6 +385,7 @@ static void tfifo_reset(struct Qdisc *sch)
rtnl_kfree_skbs(q->t_head, q->t_tail);
q->t_head = NULL;
q->t_tail = NULL;
+ q->t_len = 0;
}
static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
@@ -412,6 +415,7 @@ static void tfifo_enqueue(struct sk_buff *nskb, struct Qdisc *sch)
rb_link_node(&nskb->rbnode, parent, p);
rb_insert_color(&nskb->rbnode, &q->t_root);
}
+ q->t_len++;
sch->q.qlen++;
}
@@ -518,7 +522,7 @@ static int netem_enqueue(struct sk_buff *skb, struct Qdisc *sch,
1<<get_random_u32_below(8);
}
- if (unlikely(sch->q.qlen >= sch->limit)) {
+ if (unlikely(q->t_len >= sch->limit)) {
/* re-link segs, so that qdisc_drop_all() frees them all */
skb->next = segs;
qdisc_drop_all(skb, sch, to_free);
@@ -702,8 +706,8 @@ static struct sk_buff *netem_dequeue(struct Qdisc *sch)
tfifo_dequeue:
skb = __qdisc_dequeue_head(&sch->q);
if (skb) {
- qdisc_qstats_backlog_dec(sch, skb);
deliver:
+ qdisc_qstats_backlog_dec(sch, skb);
qdisc_bstats_update(sch, skb);
return skb;
}
@@ -719,8 +723,7 @@ deliver:
if (time_to_send <= now && q->slot.slot_next <= now) {
netem_erase_head(q, skb);
- sch->q.qlen--;
- qdisc_qstats_backlog_dec(sch, skb);
+ q->t_len--;
skb->next = NULL;
skb->prev = NULL;
/* skb->dev shares skb->rbnode area,
@@ -747,16 +750,21 @@ deliver:
if (net_xmit_drop_count(err))
qdisc_qstats_drop(sch);
qdisc_tree_reduce_backlog(sch, 1, pkt_len);
+ sch->qstats.backlog -= pkt_len;
+ sch->q.qlen--;
}
goto tfifo_dequeue;
}
+ sch->q.qlen--;
goto deliver;
}
if (q->qdisc) {
skb = q->qdisc->ops->dequeue(q->qdisc);
- if (skb)
+ if (skb) {
+ sch->q.qlen--;
goto deliver;
+ }
}
qdisc_watchdog_schedule_ns(&q->watchdog,
@@ -766,8 +774,10 @@ deliver:
if (q->qdisc) {
skb = q->qdisc->ops->dequeue(q->qdisc);
- if (skb)
+ if (skb) {
+ sch->q.qlen--;
goto deliver;
+ }
}
return NULL;
}
diff --git a/net/sched/sch_pie.c b/net/sched/sch_pie.c
index b3dcb845b327..bb1fa9aa530b 100644
--- a/net/sched/sch_pie.c
+++ b/net/sched/sch_pie.c
@@ -85,6 +85,7 @@ EXPORT_SYMBOL_GPL(pie_drop_early);
static int pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
+ enum skb_drop_reason reason = SKB_DROP_REASON_QDISC_OVERLIMIT;
struct pie_sched_data *q = qdisc_priv(sch);
bool enqueue = false;
@@ -93,6 +94,8 @@ static int pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
goto out;
}
+ reason = SKB_DROP_REASON_QDISC_CONGESTED;
+
if (!pie_drop_early(sch, &q->params, &q->vars, sch->qstats.backlog,
skb->len)) {
enqueue = true;
@@ -121,7 +124,7 @@ static int pie_qdisc_enqueue(struct sk_buff *skb, struct Qdisc *sch,
out:
q->stats.dropped++;
q->vars.accu_prob = 0;
- return qdisc_drop(skb, sch, to_free);
+ return qdisc_drop_reason(skb, sch, to_free, reason);
}
static const struct nla_policy pie_policy[TCA_PIE_MAX + 1] = {
diff --git a/net/sched/sch_red.c b/net/sched/sch_red.c
index 6029bc29b51e..ef8a2afed26b 100644
--- a/net/sched/sch_red.c
+++ b/net/sched/sch_red.c
@@ -70,6 +70,7 @@ static int red_use_nodrop(struct red_sched_data *q)
static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
+ enum skb_drop_reason reason = SKB_DROP_REASON_QDISC_CONGESTED;
struct red_sched_data *q = qdisc_priv(sch);
struct Qdisc *child = q->qdisc;
unsigned int len;
@@ -107,6 +108,7 @@ static int red_enqueue(struct sk_buff *skb, struct Qdisc *sch,
break;
case RED_HARD_MARK:
+ reason = SKB_DROP_REASON_QDISC_OVERLIMIT;
qdisc_qstats_overlimit(sch);
if (red_use_harddrop(q) || !red_use_ecn(q)) {
q->stats.forced_drop++;
@@ -143,7 +145,7 @@ congestion_drop:
if (!skb)
return NET_XMIT_CN | ret;
- qdisc_drop(skb, sch, to_free);
+ qdisc_drop_reason(skb, sch, to_free, reason);
return NET_XMIT_CN;
}
diff --git a/net/sched/sch_sfb.c b/net/sched/sch_sfb.c
index b717e15a3a17..d2835f1168e1 100644
--- a/net/sched/sch_sfb.c
+++ b/net/sched/sch_sfb.c
@@ -280,6 +280,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
struct sk_buff **to_free)
{
+ enum skb_drop_reason reason = SKB_DROP_REASON_QDISC_OVERLIMIT;
struct sfb_sched_data *q = qdisc_priv(sch);
unsigned int len = qdisc_pkt_len(skb);
struct Qdisc *child = q->qdisc;
@@ -380,6 +381,7 @@ static int sfb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
}
r = get_random_u16() & SFB_MAX_PROB;
+ reason = SKB_DROP_REASON_QDISC_CONGESTED;
if (unlikely(r < p_min)) {
if (unlikely(p_min > SFB_MAX_PROB / 2)) {
@@ -414,7 +416,7 @@ enqueue:
return ret;
drop:
- qdisc_drop(skb, sch, to_free);
+ qdisc_drop_reason(skb, sch, to_free, reason);
return NET_XMIT_CN;
other_drop:
if (ret & __NET_XMIT_BYPASS)
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c
index a4b8296a2fa1..65d5b59da583 100644
--- a/net/sched/sch_sfq.c
+++ b/net/sched/sch_sfq.c
@@ -652,6 +652,10 @@ static int sfq_change(struct Qdisc *sch, struct nlattr *opt,
if (!p)
return -ENOMEM;
}
+ if (ctl->limit == 1) {
+ NL_SET_ERR_MSG_MOD(extack, "invalid limit");
+ return -EINVAL;
+ }
sch_tree_lock(sch);
if (ctl->quantum)
q->quantum = ctl->quantum;
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c
index f1d09183ae63..dc26b22d53c7 100644
--- a/net/sched/sch_tbf.c
+++ b/net/sched/sch_tbf.c
@@ -208,7 +208,7 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
struct tbf_sched_data *q = qdisc_priv(sch);
struct sk_buff *segs, *nskb;
netdev_features_t features = netif_skb_features(skb);
- unsigned int len = 0, prev_len = qdisc_pkt_len(skb);
+ unsigned int len = 0, prev_len = qdisc_pkt_len(skb), seg_len;
int ret, nb;
segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
@@ -219,21 +219,27 @@ static int tbf_segment(struct sk_buff *skb, struct Qdisc *sch,
nb = 0;
skb_list_walk_safe(segs, segs, nskb) {
skb_mark_not_on_list(segs);
- qdisc_skb_cb(segs)->pkt_len = segs->len;
- len += segs->len;
+ seg_len = segs->len;
+ qdisc_skb_cb(segs)->pkt_len = seg_len;
ret = qdisc_enqueue(segs, q->qdisc, to_free);
if (ret != NET_XMIT_SUCCESS) {
if (net_xmit_drop_count(ret))
qdisc_qstats_drop(sch);
} else {
nb++;
+ len += seg_len;
}
}
sch->q.qlen += nb;
- if (nb > 1)
+ sch->qstats.backlog += len;
+ if (nb > 0) {
qdisc_tree_reduce_backlog(sch, 1 - nb, prev_len - len);
- consume_skb(skb);
- return nb > 0 ? NET_XMIT_SUCCESS : NET_XMIT_DROP;
+ consume_skb(skb);
+ return NET_XMIT_SUCCESS;
+ }
+
+ kfree_skb(skb);
+ return NET_XMIT_DROP;
}
static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index c45c192b7878..0b0794f164cf 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -137,7 +137,8 @@ static struct sctp_association *sctp_association_init(
= 5 * asoc->rto_max;
asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay;
- asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = sp->autoclose * HZ;
+ asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] =
+ (unsigned long)sp->autoclose * HZ;
/* Initializes the timers */
for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i)
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 8b9a1b96695e..29727ed1008e 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -43,6 +43,7 @@
#include <net/addrconf.h>
#include <net/inet_common.h>
#include <net/inet_ecn.h>
+#include <net/inet_sock.h>
#include <net/udp_tunnel.h>
#include <net/inet_dscp.h>
@@ -427,16 +428,19 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
struct dst_entry *dst = NULL;
union sctp_addr *daddr = &t->ipaddr;
union sctp_addr dst_saddr;
- u8 tos = READ_ONCE(inet_sk(sk)->tos);
+ dscp_t dscp;
if (t->dscp & SCTP_DSCP_SET_MASK)
- tos = t->dscp & SCTP_DSCP_VAL_MASK;
+ dscp = inet_dsfield_to_dscp(t->dscp);
+ else
+ dscp = inet_sk_dscp(inet_sk(sk));
+
memset(&_fl, 0x0, sizeof(_fl));
fl4->daddr = daddr->v4.sin_addr.s_addr;
fl4->fl4_dport = daddr->v4.sin_port;
fl4->flowi4_proto = IPPROTO_SCTP;
if (asoc) {
- fl4->flowi4_tos = tos & INET_DSCP_MASK;
+ fl4->flowi4_tos = inet_dscp_to_dsfield(dscp);
fl4->flowi4_scope = ip_sock_rt_scope(asoc->base.sk);
fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if;
fl4->fl4_sport = htons(asoc->base.bind_addr.port);
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index e5a5af343c4c..8e1e97be4df7 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -387,7 +387,8 @@ static struct ctl_table sctp_net_table[] = {
static int proc_sctp_do_hmac_alg(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
- struct net *net = current->nsproxy->net_ns;
+ struct net *net = container_of(ctl->data, struct net,
+ sctp.sctp_hmac_alg);
struct ctl_table tbl;
bool changed = false;
char *none = "none";
@@ -432,7 +433,7 @@ static int proc_sctp_do_hmac_alg(const struct ctl_table *ctl, int write,
static int proc_sctp_do_rto_min(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
- struct net *net = current->nsproxy->net_ns;
+ struct net *net = container_of(ctl->data, struct net, sctp.rto_min);
unsigned int min = *(unsigned int *) ctl->extra1;
unsigned int max = *(unsigned int *) ctl->extra2;
struct ctl_table tbl;
@@ -460,7 +461,7 @@ static int proc_sctp_do_rto_min(const struct ctl_table *ctl, int write,
static int proc_sctp_do_rto_max(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
- struct net *net = current->nsproxy->net_ns;
+ struct net *net = container_of(ctl->data, struct net, sctp.rto_max);
unsigned int min = *(unsigned int *) ctl->extra1;
unsigned int max = *(unsigned int *) ctl->extra2;
struct ctl_table tbl;
@@ -498,7 +499,7 @@ static int proc_sctp_do_alpha_beta(const struct ctl_table *ctl, int write,
static int proc_sctp_do_auth(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
- struct net *net = current->nsproxy->net_ns;
+ struct net *net = container_of(ctl->data, struct net, sctp.auth_enable);
struct ctl_table tbl;
int new_value, ret;
@@ -527,7 +528,7 @@ static int proc_sctp_do_auth(const struct ctl_table *ctl, int write,
static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
- struct net *net = current->nsproxy->net_ns;
+ struct net *net = container_of(ctl->data, struct net, sctp.udp_port);
unsigned int min = *(unsigned int *)ctl->extra1;
unsigned int max = *(unsigned int *)ctl->extra2;
struct ctl_table tbl;
@@ -568,7 +569,8 @@ static int proc_sctp_do_udp_port(const struct ctl_table *ctl, int write,
static int proc_sctp_do_probe_interval(const struct ctl_table *ctl, int write,
void *buffer, size_t *lenp, loff_t *ppos)
{
- struct net *net = current->nsproxy->net_ns;
+ struct net *net = container_of(ctl->data, struct net,
+ sctp.probe_interval);
struct ctl_table tbl;
int ret, new_value;
diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c
index 9d76e902fd77..c370efcfe3e8 100644
--- a/net/smc/af_smc.c
+++ b/net/smc/af_smc.c
@@ -383,6 +383,7 @@ void smc_sk_init(struct net *net, struct sock *sk, int protocol)
smc->limit_smc_hs = net->smc.limit_smc_hs;
smc->use_fallback = false; /* assume rdma capability first */
smc->fallback_rsn = 0;
+ smc_close_init(smc);
}
static struct sock *smc_sock_alloc(struct net *net, struct socket *sock,
@@ -1116,7 +1117,10 @@ static int smc_find_proposal_devices(struct smc_sock *smc,
ini->check_smcrv2 = true;
ini->smcrv2.saddr = smc->clcsock->sk->sk_rcv_saddr;
if (!(ini->smcr_version & SMC_V2) ||
- smc->clcsock->sk->sk_family != AF_INET ||
+#if IS_ENABLED(CONFIG_IPV6)
+ (smc->clcsock->sk->sk_family == AF_INET6 &&
+ !ipv6_addr_v4mapped(&smc->clcsock->sk->sk_v6_rcv_saddr)) ||
+#endif
!smc_clc_ueid_count() ||
smc_find_rdma_device(smc, ini))
ini->smcr_version &= ~SMC_V2;
@@ -1299,7 +1303,6 @@ static int smc_connect_rdma(struct smc_sock *smc,
goto connect_abort;
}
- smc_close_init(smc);
smc_rx_init(smc);
if (ini->first_contact_local) {
@@ -1435,7 +1438,6 @@ static int smc_connect_ism(struct smc_sock *smc,
goto connect_abort;
}
}
- smc_close_init(smc);
smc_rx_init(smc);
smc_tx_init(smc);
@@ -1901,6 +1903,7 @@ static void smc_listen_out(struct smc_sock *new_smc)
if (tcp_sk(new_smc->clcsock->sk)->syn_smc)
atomic_dec(&lsmc->queued_smc_hs);
+ release_sock(newsmcsk); /* lock in smc_listen_work() */
if (lsmc->sk.sk_state == SMC_LISTEN) {
lock_sock_nested(&lsmc->sk, SINGLE_DEPTH_NESTING);
smc_accept_enqueue(&lsmc->sk, newsmcsk);
@@ -2032,6 +2035,8 @@ static int smc_listen_prfx_check(struct smc_sock *new_smc,
if (pclc->hdr.typev1 == SMC_TYPE_N)
return 0;
pclc_prfx = smc_clc_proposal_get_prefix(pclc);
+ if (!pclc_prfx)
+ return -EPROTO;
if (smc_clc_prfx_match(newclcsock, pclc_prfx))
return SMC_CLC_DECL_DIFFPREFIX;
@@ -2145,6 +2150,8 @@ static void smc_find_ism_v2_device_serv(struct smc_sock *new_smc,
pclc_smcd = smc_get_clc_msg_smcd(pclc);
smc_v2_ext = smc_get_clc_v2_ext(pclc);
smcd_v2_ext = smc_get_clc_smcd_v2_ext(smc_v2_ext);
+ if (!pclc_smcd || !smc_v2_ext || !smcd_v2_ext)
+ goto not_found;
mutex_lock(&smcd_dev_list.mutex);
if (pclc_smcd->ism.chid) {
@@ -2221,7 +2228,9 @@ static void smc_find_ism_v1_device_serv(struct smc_sock *new_smc,
int rc = 0;
/* check if ISM V1 is available */
- if (!(ini->smcd_version & SMC_V1) || !smcd_indicated(ini->smc_type_v1))
+ if (!(ini->smcd_version & SMC_V1) ||
+ !smcd_indicated(ini->smc_type_v1) ||
+ !pclc_smcd)
goto not_found;
ini->is_smcd = true; /* prepare ISM check */
ini->ism_peer_gid[0].gid = ntohll(pclc_smcd->ism.gid);
@@ -2272,7 +2281,8 @@ static void smc_find_rdma_v2_device_serv(struct smc_sock *new_smc,
goto not_found;
smc_v2_ext = smc_get_clc_v2_ext(pclc);
- if (!smc_clc_match_eid(ini->negotiated_eid, smc_v2_ext, NULL, NULL))
+ if (!smc_v2_ext ||
+ !smc_clc_match_eid(ini->negotiated_eid, smc_v2_ext, NULL, NULL))
goto not_found;
/* prepare RDMA check */
@@ -2422,6 +2432,7 @@ static void smc_listen_work(struct work_struct *work)
u8 accept_version;
int rc = 0;
+ lock_sock(&new_smc->sk); /* release in smc_listen_out() */
if (new_smc->listen_smc->sk.sk_state != SMC_LISTEN)
return smc_listen_out_err(new_smc);
@@ -2479,7 +2490,6 @@ static void smc_listen_work(struct work_struct *work)
goto out_decl;
mutex_lock(&smc_server_lgr_pending);
- smc_close_init(new_smc);
smc_rx_init(new_smc);
smc_tx_init(new_smc);
@@ -2881,6 +2891,13 @@ __poll_t smc_poll(struct file *file, struct socket *sock,
} else {
sk_set_bit(SOCKWQ_ASYNC_NOSPACE, sk);
set_bit(SOCK_NOSPACE, &sk->sk_socket->flags);
+
+ if (sk->sk_state != SMC_INIT) {
+ /* Race breaker the same way as tcp_poll(). */
+ smp_mb__after_atomic();
+ if (atomic_read(&smc->conn.sndbuf_space))
+ mask |= EPOLLOUT | EPOLLWRNORM;
+ }
}
if (atomic_read(&smc->conn.bytes_to_rcv))
mask |= EPOLLIN | EPOLLRDNORM;
diff --git a/net/smc/smc_clc.c b/net/smc/smc_clc.c
index 33fa787c28eb..521f5df80e10 100644
--- a/net/smc/smc_clc.c
+++ b/net/smc/smc_clc.c
@@ -352,8 +352,11 @@ static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal *pclc)
struct smc_clc_msg_hdr *hdr = &pclc->hdr;
struct smc_clc_v2_extension *v2_ext;
- v2_ext = smc_get_clc_v2_ext(pclc);
pclc_prfx = smc_clc_proposal_get_prefix(pclc);
+ if (!pclc_prfx ||
+ pclc_prfx->ipv6_prefixes_cnt > SMC_CLC_MAX_V6_PREFIX)
+ return false;
+
if (hdr->version == SMC_V1) {
if (hdr->typev1 == SMC_TYPE_N)
return false;
@@ -365,6 +368,13 @@ static bool smc_clc_msg_prop_valid(struct smc_clc_msg_proposal *pclc)
sizeof(struct smc_clc_msg_trail))
return false;
} else {
+ v2_ext = smc_get_clc_v2_ext(pclc);
+ if ((hdr->typev2 != SMC_TYPE_N &&
+ (!v2_ext || v2_ext->hdr.eid_cnt > SMC_CLC_MAX_UEID)) ||
+ (smcd_indicated(hdr->typev2) &&
+ v2_ext->hdr.ism_gid_cnt > SMCD_CLC_MAX_V2_GID_ENTRIES))
+ return false;
+
if (ntohs(hdr->length) !=
sizeof(*pclc) +
sizeof(struct smc_clc_msg_smcd) +
@@ -764,6 +774,11 @@ int smc_clc_wait_msg(struct smc_sock *smc, void *buf, int buflen,
SMC_CLC_RECV_BUF_LEN : datlen;
iov_iter_kvec(&msg.msg_iter, ITER_DEST, &vec, 1, recvlen);
len = sock_recvmsg(smc->clcsock, &msg, krflags);
+ if (len < recvlen) {
+ smc->sk.sk_err = EPROTO;
+ reason_code = -EPROTO;
+ goto out;
+ }
datlen -= len;
}
if (clcm->type == SMC_CLC_DECLINE) {
diff --git a/net/smc/smc_clc.h b/net/smc/smc_clc.h
index 5fd6f5b8ef03..767289925410 100644
--- a/net/smc/smc_clc.h
+++ b/net/smc/smc_clc.h
@@ -336,8 +336,12 @@ struct smc_clc_msg_decline_v2 { /* clc decline message */
static inline struct smc_clc_msg_proposal_prefix *
smc_clc_proposal_get_prefix(struct smc_clc_msg_proposal *pclc)
{
+ u16 offset = ntohs(pclc->iparea_offset);
+
+ if (offset > sizeof(struct smc_clc_msg_smcd))
+ return NULL;
return (struct smc_clc_msg_proposal_prefix *)
- ((u8 *)pclc + sizeof(*pclc) + ntohs(pclc->iparea_offset));
+ ((u8 *)pclc + sizeof(*pclc) + offset);
}
static inline bool smcr_indicated(int smc_type)
@@ -376,8 +380,14 @@ static inline struct smc_clc_v2_extension *
smc_get_clc_v2_ext(struct smc_clc_msg_proposal *prop)
{
struct smc_clc_msg_smcd *prop_smcd = smc_get_clc_msg_smcd(prop);
+ u16 max_offset;
- if (!prop_smcd || !ntohs(prop_smcd->v2_ext_offset))
+ max_offset = offsetof(struct smc_clc_msg_proposal_area, pclc_v2_ext) -
+ offsetof(struct smc_clc_msg_proposal_area, pclc_smcd) -
+ offsetofend(struct smc_clc_msg_smcd, v2_ext_offset);
+
+ if (!prop_smcd || !ntohs(prop_smcd->v2_ext_offset) ||
+ ntohs(prop_smcd->v2_ext_offset) > max_offset)
return NULL;
return (struct smc_clc_v2_extension *)
@@ -390,9 +400,15 @@ smc_get_clc_v2_ext(struct smc_clc_msg_proposal *prop)
static inline struct smc_clc_smcd_v2_extension *
smc_get_clc_smcd_v2_ext(struct smc_clc_v2_extension *prop_v2ext)
{
+ u16 max_offset = offsetof(struct smc_clc_msg_proposal_area, pclc_smcd_v2_ext) -
+ offsetof(struct smc_clc_msg_proposal_area, pclc_v2_ext) -
+ offsetof(struct smc_clc_v2_extension, hdr) -
+ offsetofend(struct smc_clnt_opts_area_hdr, smcd_v2_ext_offset);
+
if (!prop_v2ext)
return NULL;
- if (!ntohs(prop_v2ext->hdr.smcd_v2_ext_offset))
+ if (!ntohs(prop_v2ext->hdr.smcd_v2_ext_offset) ||
+ ntohs(prop_v2ext->hdr.smcd_v2_ext_offset) > max_offset)
return NULL;
return (struct smc_clc_smcd_v2_extension *)
diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c
index 500952c2e67b..ccf57b7fe602 100644
--- a/net/smc/smc_core.c
+++ b/net/smc/smc_core.c
@@ -795,9 +795,14 @@ int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk,
if (lgr->smc_version == SMC_V2) {
lnk->smcibdev = ini->smcrv2.ib_dev_v2;
lnk->ibport = ini->smcrv2.ib_port_v2;
+ lnk->wr_rx_sge_cnt = lnk->smcibdev->ibdev->attrs.max_recv_sge < 2 ? 1 : 2;
+ lnk->wr_rx_buflen = smc_link_shared_v2_rxbuf(lnk) ?
+ SMC_WR_BUF_SIZE : SMC_WR_BUF_V2_SIZE;
} else {
lnk->smcibdev = ini->ib_dev;
lnk->ibport = ini->ib_port;
+ lnk->wr_rx_sge_cnt = 1;
+ lnk->wr_rx_buflen = SMC_WR_BUF_SIZE;
}
get_device(&lnk->smcibdev->ibdev->dev);
atomic_inc(&lnk->smcibdev->lnk_cnt);
@@ -1818,7 +1823,9 @@ void smcr_link_down_cond_sched(struct smc_link *lnk)
{
if (smc_link_downing(&lnk->state)) {
trace_smcr_link_down(lnk, __builtin_return_address(0));
- schedule_work(&lnk->link_down_wrk);
+ smcr_link_hold(lnk); /* smcr_link_put in link_down_wrk */
+ if (!schedule_work(&lnk->link_down_wrk))
+ smcr_link_put(lnk);
}
}
@@ -1850,11 +1857,14 @@ static void smc_link_down_work(struct work_struct *work)
struct smc_link_group *lgr = link->lgr;
if (list_empty(&lgr->list))
- return;
+ goto out;
wake_up_all(&lgr->llc_msg_waiter);
down_write(&lgr->llc_conf_mutex);
smcr_link_down(link);
up_write(&lgr->llc_conf_mutex);
+
+out:
+ smcr_link_put(link); /* smcr_link_hold by schedulers of link_down_work */
}
static int smc_vlan_by_tcpsk_walk(struct net_device *lower_dev,
diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h
index 69b54ecd6503..48a1b1dcb576 100644
--- a/net/smc/smc_core.h
+++ b/net/smc/smc_core.h
@@ -122,10 +122,14 @@ struct smc_link {
} ____cacheline_aligned_in_smp;
struct completion tx_ref_comp;
- struct smc_wr_buf *wr_rx_bufs; /* WR recv payload buffers */
+ u8 *wr_rx_bufs; /* WR recv payload buffers */
struct ib_recv_wr *wr_rx_ibs; /* WR recv meta data */
struct ib_sge *wr_rx_sges; /* WR recv scatter meta data */
/* above three vectors have wr_rx_cnt elements and use the same index */
+ int wr_rx_sge_cnt; /* rx sge, V1 is 1, V2 is either 2 or 1 */
+ int wr_rx_buflen; /* buffer len for the first sge, len for the
+ * second sge is lgr shared if rx sge is 2.
+ */
dma_addr_t wr_rx_dma_addr; /* DMA address of wr_rx_bufs */
dma_addr_t wr_rx_v2_dma_addr; /* DMA address of v2 rx buf*/
u64 wr_rx_id; /* seq # of last recv WR */
@@ -506,6 +510,11 @@ static inline bool smc_link_active(struct smc_link *lnk)
return lnk->state == SMC_LNK_ACTIVE;
}
+static inline bool smc_link_shared_v2_rxbuf(struct smc_link *lnk)
+{
+ return lnk->wr_rx_sge_cnt > 1;
+}
+
static inline void smc_gid_be16_convert(__u8 *buf, u8 *gid_raw)
{
sprintf(buf, "%04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x",
diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c
index 9c563cdbea90..53828833a3f7 100644
--- a/net/smc/smc_ib.c
+++ b/net/smc/smc_ib.c
@@ -662,7 +662,6 @@ void smc_ib_destroy_queue_pair(struct smc_link *lnk)
/* create a queue pair within the protection domain for a link */
int smc_ib_create_queue_pair(struct smc_link *lnk)
{
- int sges_per_buf = (lnk->lgr->smc_version == SMC_V2) ? 2 : 1;
struct ib_qp_init_attr qp_attr = {
.event_handler = smc_ib_qp_event_handler,
.qp_context = lnk,
@@ -676,7 +675,7 @@ int smc_ib_create_queue_pair(struct smc_link *lnk)
.max_send_wr = SMC_WR_BUF_CNT * 3,
.max_recv_wr = SMC_WR_BUF_CNT * 3,
.max_send_sge = SMC_IB_MAX_SEND_SGE,
- .max_recv_sge = sges_per_buf,
+ .max_recv_sge = lnk->wr_rx_sge_cnt,
.max_inline_data = 0,
},
.sq_sig_type = IB_SIGNAL_REQ_WR,
diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c
index 018ce8133b02..f865c58c3aa7 100644
--- a/net/smc/smc_llc.c
+++ b/net/smc/smc_llc.c
@@ -997,13 +997,14 @@ static int smc_llc_cli_conf_link(struct smc_link *link,
}
static void smc_llc_save_add_link_rkeys(struct smc_link *link,
- struct smc_link *link_new)
+ struct smc_link *link_new,
+ u8 *llc_msg)
{
struct smc_llc_msg_add_link_v2_ext *ext;
struct smc_link_group *lgr = link->lgr;
int max, i;
- ext = (struct smc_llc_msg_add_link_v2_ext *)((u8 *)lgr->wr_rx_buf_v2 +
+ ext = (struct smc_llc_msg_add_link_v2_ext *)(llc_msg +
SMC_WR_TX_SIZE);
max = min_t(u8, ext->num_rkeys, SMC_LLC_RKEYS_PER_MSG_V2);
down_write(&lgr->rmbs_lock);
@@ -1098,7 +1099,9 @@ int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry)
if (rc)
goto out_clear_lnk;
if (lgr->smc_version == SMC_V2) {
- smc_llc_save_add_link_rkeys(link, lnk_new);
+ u8 *llc_msg = smc_link_shared_v2_rxbuf(link) ?
+ (u8 *)lgr->wr_rx_buf_v2 : (u8 *)llc;
+ smc_llc_save_add_link_rkeys(link, lnk_new, llc_msg);
} else {
rc = smc_llc_cli_rkey_exchange(link, lnk_new);
if (rc) {
@@ -1498,7 +1501,9 @@ int smc_llc_srv_add_link(struct smc_link *link,
if (rc)
goto out_err;
if (lgr->smc_version == SMC_V2) {
- smc_llc_save_add_link_rkeys(link, link_new);
+ u8 *llc_msg = smc_link_shared_v2_rxbuf(link) ?
+ (u8 *)lgr->wr_rx_buf_v2 : (u8 *)add_llc;
+ smc_llc_save_add_link_rkeys(link, link_new, llc_msg);
} else {
rc = smc_llc_srv_rkey_exchange(link, link_new);
if (rc)
@@ -1807,8 +1812,12 @@ static void smc_llc_rmt_delete_rkey(struct smc_link_group *lgr)
if (lgr->smc_version == SMC_V2) {
struct smc_llc_msg_delete_rkey_v2 *llcv2;
- memcpy(lgr->wr_rx_buf_v2, llc, sizeof(*llc));
- llcv2 = (struct smc_llc_msg_delete_rkey_v2 *)lgr->wr_rx_buf_v2;
+ if (smc_link_shared_v2_rxbuf(link)) {
+ memcpy(lgr->wr_rx_buf_v2, llc, sizeof(*llc));
+ llcv2 = (struct smc_llc_msg_delete_rkey_v2 *)lgr->wr_rx_buf_v2;
+ } else {
+ llcv2 = (struct smc_llc_msg_delete_rkey_v2 *)llc;
+ }
llcv2->num_inval_rkeys = 0;
max = min_t(u8, llcv2->num_rkeys, SMC_LLC_RKEYS_PER_MSG_V2);
diff --git a/net/smc/smc_wr.c b/net/smc/smc_wr.c
index 994c0cd4fddb..b04a21b8c511 100644
--- a/net/smc/smc_wr.c
+++ b/net/smc/smc_wr.c
@@ -439,7 +439,7 @@ static inline void smc_wr_rx_demultiplex(struct ib_wc *wc)
return; /* short message */
temp_wr_id = wc->wr_id;
index = do_div(temp_wr_id, link->wr_rx_cnt);
- wr_rx = (struct smc_wr_rx_hdr *)&link->wr_rx_bufs[index];
+ wr_rx = (struct smc_wr_rx_hdr *)(link->wr_rx_bufs + index * link->wr_rx_buflen);
hash_for_each_possible(smc_wr_rx_hash, handler, list, wr_rx->type) {
if (handler->type == wr_rx->type)
handler->handler(wc, wr_rx);
@@ -555,7 +555,6 @@ 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;
@@ -608,13 +607,14 @@ static void smc_wr_init_sge(struct smc_link *lnk)
* the larger spillover buffer, allowing easy data mapping.
*/
for (i = 0; i < lnk->wr_rx_cnt; i++) {
- int x = i * sges_per_buf;
+ int x = i * lnk->wr_rx_sge_cnt;
lnk->wr_rx_sges[x].addr =
- lnk->wr_rx_dma_addr + i * SMC_WR_BUF_SIZE;
- lnk->wr_rx_sges[x].length = SMC_WR_TX_SIZE;
+ lnk->wr_rx_dma_addr + i * lnk->wr_rx_buflen;
+ lnk->wr_rx_sges[x].length = smc_link_shared_v2_rxbuf(lnk) ?
+ SMC_WR_TX_SIZE : lnk->wr_rx_buflen;
lnk->wr_rx_sges[x].lkey = lnk->roce_pd->local_dma_lkey;
- if (lnk->lgr->smc_version == SMC_V2) {
+ if (lnk->lgr->smc_version == SMC_V2 && smc_link_shared_v2_rxbuf(lnk)) {
lnk->wr_rx_sges[x + 1].addr =
lnk->wr_rx_v2_dma_addr + SMC_WR_TX_SIZE;
lnk->wr_rx_sges[x + 1].length =
@@ -624,7 +624,7 @@ static void smc_wr_init_sge(struct smc_link *lnk)
}
lnk->wr_rx_ibs[i].next = NULL;
lnk->wr_rx_ibs[i].sg_list = &lnk->wr_rx_sges[x];
- lnk->wr_rx_ibs[i].num_sge = sges_per_buf;
+ lnk->wr_rx_ibs[i].num_sge = lnk->wr_rx_sge_cnt;
}
lnk->wr_reg.wr.next = NULL;
lnk->wr_reg.wr.num_sge = 0;
@@ -655,7 +655,7 @@ void smc_wr_free_link(struct smc_link *lnk)
if (lnk->wr_rx_dma_addr) {
ib_dma_unmap_single(ibdev, lnk->wr_rx_dma_addr,
- SMC_WR_BUF_SIZE * lnk->wr_rx_cnt,
+ lnk->wr_rx_buflen * lnk->wr_rx_cnt,
DMA_FROM_DEVICE);
lnk->wr_rx_dma_addr = 0;
}
@@ -740,13 +740,11 @@ int smc_wr_alloc_lgr_mem(struct smc_link_group *lgr)
int smc_wr_alloc_link_mem(struct smc_link *link)
{
- int sges_per_buf = link->lgr->smc_version == SMC_V2 ? 2 : 1;
-
/* allocate link related memory */
link->wr_tx_bufs = kcalloc(SMC_WR_BUF_CNT, SMC_WR_BUF_SIZE, GFP_KERNEL);
if (!link->wr_tx_bufs)
goto no_mem;
- link->wr_rx_bufs = kcalloc(SMC_WR_BUF_CNT * 3, SMC_WR_BUF_SIZE,
+ link->wr_rx_bufs = kcalloc(SMC_WR_BUF_CNT * 3, link->wr_rx_buflen,
GFP_KERNEL);
if (!link->wr_rx_bufs)
goto no_mem_wr_tx_bufs;
@@ -774,7 +772,7 @@ int smc_wr_alloc_link_mem(struct smc_link *link)
if (!link->wr_tx_sges)
goto no_mem_wr_tx_rdma_sges;
link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3,
- sizeof(link->wr_rx_sges[0]) * sges_per_buf,
+ sizeof(link->wr_rx_sges[0]) * link->wr_rx_sge_cnt,
GFP_KERNEL);
if (!link->wr_rx_sges)
goto no_mem_wr_tx_sges;
@@ -872,7 +870,7 @@ int smc_wr_create_link(struct smc_link *lnk)
smc_wr_tx_set_wr_id(&lnk->wr_tx_id, 0);
lnk->wr_rx_id = 0;
lnk->wr_rx_dma_addr = ib_dma_map_single(
- ibdev, lnk->wr_rx_bufs, SMC_WR_BUF_SIZE * lnk->wr_rx_cnt,
+ ibdev, lnk->wr_rx_bufs, lnk->wr_rx_buflen * lnk->wr_rx_cnt,
DMA_FROM_DEVICE);
if (ib_dma_mapping_error(ibdev, lnk->wr_rx_dma_addr)) {
lnk->wr_rx_dma_addr = 0;
@@ -880,13 +878,15 @@ int smc_wr_create_link(struct smc_link *lnk)
goto out;
}
if (lnk->lgr->smc_version == SMC_V2) {
- lnk->wr_rx_v2_dma_addr = ib_dma_map_single(ibdev,
- lnk->lgr->wr_rx_buf_v2, SMC_WR_BUF_V2_SIZE,
- DMA_FROM_DEVICE);
- if (ib_dma_mapping_error(ibdev, lnk->wr_rx_v2_dma_addr)) {
- lnk->wr_rx_v2_dma_addr = 0;
- rc = -EIO;
- goto dma_unmap;
+ if (smc_link_shared_v2_rxbuf(lnk)) {
+ lnk->wr_rx_v2_dma_addr =
+ ib_dma_map_single(ibdev, lnk->lgr->wr_rx_buf_v2,
+ SMC_WR_BUF_V2_SIZE, DMA_FROM_DEVICE);
+ if (ib_dma_mapping_error(ibdev, lnk->wr_rx_v2_dma_addr)) {
+ lnk->wr_rx_v2_dma_addr = 0;
+ rc = -EIO;
+ goto dma_unmap;
+ }
}
lnk->wr_tx_v2_dma_addr = ib_dma_map_single(ibdev,
lnk->lgr->wr_tx_buf_v2, SMC_WR_BUF_V2_SIZE,
@@ -935,7 +935,7 @@ dma_unmap:
lnk->wr_tx_v2_dma_addr = 0;
}
ib_dma_unmap_single(ibdev, lnk->wr_rx_dma_addr,
- SMC_WR_BUF_SIZE * lnk->wr_rx_cnt,
+ lnk->wr_rx_buflen * lnk->wr_rx_cnt,
DMA_FROM_DEVICE);
lnk->wr_rx_dma_addr = 0;
out:
diff --git a/net/socket.c b/net/socket.c
index 9a117248f18f..16402b8be5a7 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -1008,12 +1008,23 @@ static void sock_recv_mark(struct msghdr *msg, struct sock *sk,
}
}
+static void sock_recv_priority(struct msghdr *msg, struct sock *sk,
+ struct sk_buff *skb)
+{
+ if (sock_flag(sk, SOCK_RCVPRIORITY) && skb) {
+ __u32 priority = skb->priority;
+
+ put_cmsg(msg, SOL_SOCKET, SO_PRIORITY, sizeof(__u32), &priority);
+ }
+}
+
void __sock_recv_cmsgs(struct msghdr *msg, struct sock *sk,
struct sk_buff *skb)
{
sock_recv_timestamp(msg, sk, skb);
sock_recv_drops(msg, sk, skb);
sock_recv_mark(msg, sk, skb);
+ sock_recv_priority(msg, sk, skb);
}
EXPORT_SYMBOL_GPL(__sock_recv_cmsgs);
diff --git a/net/sunrpc/auth_gss/gss_krb5_test.c b/net/sunrpc/auth_gss/gss_krb5_test.c
index 85625e3f3814..a5bff02cd7ba 100644
--- a/net/sunrpc/auth_gss/gss_krb5_test.c
+++ b/net/sunrpc/auth_gss/gss_krb5_test.c
@@ -17,7 +17,7 @@
#include "gss_krb5_internal.h"
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
struct gss_krb5_test_param {
const char *desc;
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index b785425c3315..95397677673b 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -1551,6 +1551,10 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
newlen = error;
if (protocol == IPPROTO_TCP) {
+ __netns_tracker_free(net, &sock->sk->ns_tracker, false);
+ sock->sk->sk_net_refcnt = 1;
+ get_net_track(net, &sock->sk->ns_tracker, GFP_KERNEL);
+ sock_inuse_add(net, 1);
if ((error = kernel_listen(sock, 64)) < 0)
goto bummer;
}
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index 1326fbf45a34..c60936d8cef7 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -1198,6 +1198,7 @@ static void xs_sock_reset_state_flags(struct rpc_xprt *xprt)
clear_bit(XPRT_SOCK_WAKE_WRITE, &transport->sock_state);
clear_bit(XPRT_SOCK_WAKE_DISCONNECT, &transport->sock_state);
clear_bit(XPRT_SOCK_NOSPACE, &transport->sock_state);
+ clear_bit(XPRT_SOCK_UPD_TIMEOUT, &transport->sock_state);
}
static void xs_run_error_worker(struct sock_xprt *transport, unsigned int nr)
@@ -1278,6 +1279,7 @@ static void xs_reset_transport(struct sock_xprt *transport)
transport->file = NULL;
sk->sk_user_data = NULL;
+ sk->sk_sndtimeo = 0;
xs_restore_old_callbacks(transport, sk);
xprt_clear_connected(xprt);
@@ -1939,6 +1941,13 @@ static struct socket *xs_create_sock(struct rpc_xprt *xprt,
goto out;
}
+ if (protocol == IPPROTO_TCP) {
+ __netns_tracker_free(xprt->xprt_net, &sock->sk->ns_tracker, false);
+ sock->sk->sk_net_refcnt = 1;
+ get_net_track(xprt->xprt_net, &sock->sk->ns_tracker, GFP_KERNEL);
+ sock_inuse_add(xprt->xprt_net, 1);
+ }
+
filp = sock_alloc_file(sock, O_NONBLOCK, NULL);
if (IS_ERR(filp))
return ERR_CAST(filp);
@@ -2614,11 +2623,10 @@ static int xs_tls_handshake_sync(struct rpc_xprt *lower_xprt, struct xprtsec_par
rc = wait_for_completion_interruptible_timeout(&lower_transport->handshake_done,
XS_TLS_HANDSHAKE_TO);
if (rc <= 0) {
- if (!tls_handshake_cancel(sk)) {
- if (rc == 0)
- rc = -ETIMEDOUT;
- goto out_put_xprt;
- }
+ tls_handshake_cancel(sk);
+ if (rc == 0)
+ rc = -ETIMEDOUT;
+ goto out_put_xprt;
}
rc = lower_transport->xprt_err;
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c
index d1180370fdf4..e74940eab3a4 100644
--- a/net/tipc/name_table.c
+++ b/net/tipc/name_table.c
@@ -949,8 +949,8 @@ void tipc_nametbl_stop(struct net *net)
}
spin_unlock_bh(&tn->nametbl_lock);
- synchronize_net();
- kfree(nt);
+ /* TODO: clear tn->nametbl, implement proper RCU rules ? */
+ kfree_rcu(nt, rcu);
}
static int __tipc_nl_add_nametable_publ(struct tipc_nl_msg *msg,
diff --git a/net/tipc/name_table.h b/net/tipc/name_table.h
index 3bcd9ef8cee3..7ff6eeebaae6 100644
--- a/net/tipc/name_table.h
+++ b/net/tipc/name_table.h
@@ -90,6 +90,7 @@ struct publication {
/**
* struct name_table - table containing all existing port name publications
+ * @rcu: RCU callback head used for deferred freeing
* @services: name sequence hash lists
* @node_scope: all local publications with node scope
* - used by name_distr during re-init of name table
@@ -102,6 +103,7 @@ struct publication {
* @snd_nxt: next sequence number to be used
*/
struct name_table {
+ struct rcu_head rcu;
struct hlist_head services[TIPC_NAMETBL_SIZE];
struct list_head node_scope;
struct list_head cluster_scope;
diff --git a/net/tipc/udp_media.c b/net/tipc/udp_media.c
index 439f75539977..108a4cc2e001 100644
--- a/net/tipc/udp_media.c
+++ b/net/tipc/udp_media.c
@@ -807,6 +807,7 @@ static void cleanup_bearer(struct work_struct *work)
{
struct udp_bearer *ub = container_of(work, struct udp_bearer, work);
struct udp_replicast *rcast, *tmp;
+ struct tipc_net *tn;
list_for_each_entry_safe(rcast, tmp, &ub->rcast.list, list) {
dst_cache_destroy(&rcast->dst_cache);
@@ -814,10 +815,14 @@ static void cleanup_bearer(struct work_struct *work)
kfree_rcu(rcast, rcu);
}
- atomic_dec(&tipc_net(sock_net(ub->ubsock->sk))->wq_count);
+ tn = tipc_net(sock_net(ub->ubsock->sk));
+
dst_cache_destroy(&ub->rcast.dst_cache);
udp_tunnel_sock_release(ub->ubsock);
+
+ /* Note: could use a call_rcu() to avoid another synchronize_net() */
synchronize_net();
+ atomic_dec(&tn->wq_count);
kfree(ub);
}
diff --git a/net/tls/tls.h b/net/tls/tls.h
index e5e47452308a..774859b63f0d 100644
--- a/net/tls/tls.h
+++ b/net/tls/tls.h
@@ -145,7 +145,8 @@ void tls_err_abort(struct sock *sk, int err);
int init_prot_info(struct tls_prot_info *prot,
const struct tls_crypto_info *crypto_info,
const struct tls_cipher_desc *cipher_desc);
-int tls_set_sw_offload(struct sock *sk, int tx);
+int tls_set_sw_offload(struct sock *sk, int tx,
+ struct tls_crypto_info *new_crypto_info);
void tls_update_rx_zc_capable(struct tls_context *tls_ctx);
void tls_sw_strparser_arm(struct sock *sk, struct tls_context *ctx);
void tls_sw_strparser_done(struct tls_context *tls_ctx);
diff --git a/net/tls/tls_device.c b/net/tls/tls_device.c
index dc063c2c7950..e50b6e71df13 100644
--- a/net/tls/tls_device.c
+++ b/net/tls/tls_device.c
@@ -1227,7 +1227,7 @@ int tls_set_device_offload_rx(struct sock *sk, struct tls_context *ctx)
context->resync_nh_reset = 1;
ctx->priv_ctx_rx = context;
- rc = tls_set_sw_offload(sk, 0);
+ rc = tls_set_sw_offload(sk, 0, NULL);
if (rc)
goto release_ctx;
diff --git a/net/tls/tls_main.c b/net/tls/tls_main.c
index 6b4b9f2749a6..9ee5a83c5b40 100644
--- a/net/tls/tls_main.c
+++ b/net/tls/tls_main.c
@@ -423,9 +423,10 @@ static __poll_t tls_sk_poll(struct file *file, struct socket *sock,
ctx = tls_sw_ctx_rx(tls_ctx);
psock = sk_psock_get(sk);
- if (skb_queue_empty_lockless(&ctx->rx_list) &&
- !tls_strp_msg_ready(ctx) &&
- sk_psock_queue_empty(psock))
+ if ((skb_queue_empty_lockless(&ctx->rx_list) &&
+ !tls_strp_msg_ready(ctx) &&
+ sk_psock_queue_empty(psock)) ||
+ READ_ONCE(ctx->key_update_pending))
mask &= ~(EPOLLIN | EPOLLRDNORM);
if (psock)
@@ -612,11 +613,13 @@ static int validate_crypto_info(const struct tls_crypto_info *crypto_info,
static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval,
unsigned int optlen, int tx)
{
- struct tls_crypto_info *crypto_info;
- struct tls_crypto_info *alt_crypto_info;
+ struct tls_crypto_info *crypto_info, *alt_crypto_info;
+ struct tls_crypto_info *old_crypto_info = NULL;
struct tls_context *ctx = tls_get_ctx(sk);
const struct tls_cipher_desc *cipher_desc;
union tls_crypto_context *crypto_ctx;
+ union tls_crypto_context tmp = {};
+ bool update = false;
int rc = 0;
int conf;
@@ -633,9 +636,21 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval,
crypto_info = &crypto_ctx->info;
- /* Currently we don't support set crypto info more than one time */
- if (TLS_CRYPTO_INFO_READY(crypto_info))
- return -EBUSY;
+ if (TLS_CRYPTO_INFO_READY(crypto_info)) {
+ /* Currently we only support setting crypto info more
+ * than one time for TLS 1.3
+ */
+ if (crypto_info->version != TLS_1_3_VERSION) {
+ TLS_INC_STATS(sock_net(sk), tx ? LINUX_MIB_TLSTXREKEYERROR
+ : LINUX_MIB_TLSRXREKEYERROR);
+ return -EBUSY;
+ }
+
+ update = true;
+ old_crypto_info = crypto_info;
+ crypto_info = &tmp.info;
+ crypto_ctx = &tmp;
+ }
rc = copy_from_sockptr(crypto_info, optval, sizeof(*crypto_info));
if (rc) {
@@ -643,7 +658,14 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval,
goto err_crypto_info;
}
- rc = validate_crypto_info(crypto_info, alt_crypto_info);
+ if (update) {
+ /* Ensure that TLS version and ciphers are not modified */
+ if (crypto_info->version != old_crypto_info->version ||
+ crypto_info->cipher_type != old_crypto_info->cipher_type)
+ rc = -EINVAL;
+ } else {
+ rc = validate_crypto_info(crypto_info, alt_crypto_info);
+ }
if (rc)
goto err_crypto_info;
@@ -673,11 +695,17 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval,
TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSTXDEVICE);
TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRTXDEVICE);
} else {
- rc = tls_set_sw_offload(sk, 1);
+ rc = tls_set_sw_offload(sk, 1,
+ update ? crypto_info : NULL);
if (rc)
goto err_crypto_info;
- TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSTXSW);
- TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRTXSW);
+
+ if (update) {
+ TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSTXREKEYOK);
+ } else {
+ TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSTXSW);
+ TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRTXSW);
+ }
conf = TLS_SW;
}
} else {
@@ -687,14 +715,21 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval,
TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXDEVICE);
TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRRXDEVICE);
} else {
- rc = tls_set_sw_offload(sk, 0);
+ rc = tls_set_sw_offload(sk, 0,
+ update ? crypto_info : NULL);
if (rc)
goto err_crypto_info;
- TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXSW);
- TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRRXSW);
+
+ if (update) {
+ TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXREKEYOK);
+ } else {
+ TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXSW);
+ TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSCURRRXSW);
+ }
conf = TLS_SW;
}
- tls_sw_strparser_arm(sk, ctx);
+ if (!update)
+ tls_sw_strparser_arm(sk, ctx);
}
if (tx)
@@ -713,6 +748,10 @@ static int do_tls_setsockopt_conf(struct sock *sk, sockptr_t optval,
return 0;
err_crypto_info:
+ if (update) {
+ TLS_INC_STATS(sock_net(sk), tx ? LINUX_MIB_TLSTXREKEYERROR
+ : LINUX_MIB_TLSRXREKEYERROR);
+ }
memzero_explicit(crypto_ctx, sizeof(*crypto_ctx));
return rc;
}
diff --git a/net/tls/tls_proc.c b/net/tls/tls_proc.c
index 68982728f620..367666aa07b8 100644
--- a/net/tls/tls_proc.c
+++ b/net/tls/tls_proc.c
@@ -22,6 +22,11 @@ static const struct snmp_mib tls_mib_list[] = {
SNMP_MIB_ITEM("TlsRxDeviceResync", LINUX_MIB_TLSRXDEVICERESYNC),
SNMP_MIB_ITEM("TlsDecryptRetry", LINUX_MIB_TLSDECRYPTRETRY),
SNMP_MIB_ITEM("TlsRxNoPadViolation", LINUX_MIB_TLSRXNOPADVIOL),
+ SNMP_MIB_ITEM("TlsRxRekeyOk", LINUX_MIB_TLSRXREKEYOK),
+ SNMP_MIB_ITEM("TlsRxRekeyError", LINUX_MIB_TLSRXREKEYERROR),
+ SNMP_MIB_ITEM("TlsTxRekeyOk", LINUX_MIB_TLSTXREKEYOK),
+ SNMP_MIB_ITEM("TlsTxRekeyError", LINUX_MIB_TLSTXREKEYERROR),
+ SNMP_MIB_ITEM("TlsRxRekeyReceived", LINUX_MIB_TLSRXREKEYRECEIVED),
SNMP_MIB_SENTINEL
};
diff --git a/net/tls/tls_sw.c b/net/tls/tls_sw.c
index bbf26cc4f6ee..914d4e1516a3 100644
--- a/net/tls/tls_sw.c
+++ b/net/tls/tls_sw.c
@@ -458,7 +458,7 @@ int tls_tx_records(struct sock *sk, int flags)
tx_err:
if (rc < 0 && rc != -EAGAIN)
- tls_err_abort(sk, -EBADMSG);
+ tls_err_abort(sk, rc);
return rc;
}
@@ -1314,6 +1314,10 @@ tls_rx_rec_wait(struct sock *sk, struct sk_psock *psock, bool nonblock,
int ret = 0;
long timeo;
+ /* a rekey is pending, let userspace deal with it */
+ if (unlikely(ctx->key_update_pending))
+ return -EKEYEXPIRED;
+
timeo = sock_rcvtimeo(sk, nonblock);
while (!tls_strp_msg_ready(ctx)) {
@@ -1720,6 +1724,36 @@ tls_decrypt_device(struct sock *sk, struct msghdr *msg,
return 1;
}
+static int tls_check_pending_rekey(struct sock *sk, struct tls_context *ctx,
+ struct sk_buff *skb)
+{
+ const struct strp_msg *rxm = strp_msg(skb);
+ const struct tls_msg *tlm = tls_msg(skb);
+ char hs_type;
+ int err;
+
+ if (likely(tlm->control != TLS_RECORD_TYPE_HANDSHAKE))
+ return 0;
+
+ if (rxm->full_len < 1)
+ return 0;
+
+ err = skb_copy_bits(skb, rxm->offset, &hs_type, 1);
+ if (err < 0) {
+ DEBUG_NET_WARN_ON_ONCE(1);
+ return err;
+ }
+
+ if (hs_type == TLS_HANDSHAKE_KEYUPDATE) {
+ struct tls_sw_context_rx *rx_ctx = ctx->priv_ctx_rx;
+
+ WRITE_ONCE(rx_ctx->key_update_pending, true);
+ TLS_INC_STATS(sock_net(sk), LINUX_MIB_TLSRXREKEYRECEIVED);
+ }
+
+ return 0;
+}
+
static int tls_rx_one_record(struct sock *sk, struct msghdr *msg,
struct tls_decrypt_arg *darg)
{
@@ -1739,7 +1773,7 @@ static int tls_rx_one_record(struct sock *sk, struct msghdr *msg,
rxm->full_len -= prot->overhead_size;
tls_advance_record_sn(sk, prot, &tls_ctx->rx);
- return 0;
+ return tls_check_pending_rekey(sk, tls_ctx, darg->skb);
}
int decrypt_skb(struct sock *sk, struct scatterlist *sgout)
@@ -2684,12 +2718,22 @@ int init_prot_info(struct tls_prot_info *prot,
return 0;
}
-int tls_set_sw_offload(struct sock *sk, int tx)
+static void tls_finish_key_update(struct sock *sk, struct tls_context *tls_ctx)
+{
+ struct tls_sw_context_rx *ctx = tls_ctx->priv_ctx_rx;
+
+ WRITE_ONCE(ctx->key_update_pending, false);
+ /* wake-up pre-existing poll() */
+ ctx->saved_data_ready(sk);
+}
+
+int tls_set_sw_offload(struct sock *sk, int tx,
+ struct tls_crypto_info *new_crypto_info)
{
+ struct tls_crypto_info *crypto_info, *src_crypto_info;
struct tls_sw_context_tx *sw_ctx_tx = NULL;
struct tls_sw_context_rx *sw_ctx_rx = NULL;
const struct tls_cipher_desc *cipher_desc;
- struct tls_crypto_info *crypto_info;
char *iv, *rec_seq, *key, *salt;
struct cipher_context *cctx;
struct tls_prot_info *prot;
@@ -2701,44 +2745,47 @@ int tls_set_sw_offload(struct sock *sk, int tx)
ctx = tls_get_ctx(sk);
prot = &ctx->prot_info;
- if (tx) {
- ctx->priv_ctx_tx = init_ctx_tx(ctx, sk);
- if (!ctx->priv_ctx_tx)
- return -ENOMEM;
+ /* new_crypto_info != NULL means rekey */
+ if (!new_crypto_info) {
+ if (tx) {
+ ctx->priv_ctx_tx = init_ctx_tx(ctx, sk);
+ if (!ctx->priv_ctx_tx)
+ return -ENOMEM;
+ } else {
+ ctx->priv_ctx_rx = init_ctx_rx(ctx);
+ if (!ctx->priv_ctx_rx)
+ return -ENOMEM;
+ }
+ }
+ if (tx) {
sw_ctx_tx = ctx->priv_ctx_tx;
crypto_info = &ctx->crypto_send.info;
cctx = &ctx->tx;
aead = &sw_ctx_tx->aead_send;
} else {
- ctx->priv_ctx_rx = init_ctx_rx(ctx);
- if (!ctx->priv_ctx_rx)
- return -ENOMEM;
-
sw_ctx_rx = ctx->priv_ctx_rx;
crypto_info = &ctx->crypto_recv.info;
cctx = &ctx->rx;
aead = &sw_ctx_rx->aead_recv;
}
- cipher_desc = get_cipher_desc(crypto_info->cipher_type);
+ src_crypto_info = new_crypto_info ?: crypto_info;
+
+ cipher_desc = get_cipher_desc(src_crypto_info->cipher_type);
if (!cipher_desc) {
rc = -EINVAL;
goto free_priv;
}
- rc = init_prot_info(prot, crypto_info, cipher_desc);
+ rc = init_prot_info(prot, src_crypto_info, cipher_desc);
if (rc)
goto free_priv;
- iv = crypto_info_iv(crypto_info, cipher_desc);
- key = crypto_info_key(crypto_info, cipher_desc);
- salt = crypto_info_salt(crypto_info, cipher_desc);
- rec_seq = crypto_info_rec_seq(crypto_info, cipher_desc);
-
- memcpy(cctx->iv, salt, cipher_desc->salt);
- memcpy(cctx->iv + cipher_desc->salt, iv, cipher_desc->iv);
- memcpy(cctx->rec_seq, rec_seq, cipher_desc->rec_seq);
+ iv = crypto_info_iv(src_crypto_info, cipher_desc);
+ key = crypto_info_key(src_crypto_info, cipher_desc);
+ salt = crypto_info_salt(src_crypto_info, cipher_desc);
+ rec_seq = crypto_info_rec_seq(src_crypto_info, cipher_desc);
if (!*aead) {
*aead = crypto_alloc_aead(cipher_desc->cipher_name, 0, 0);
@@ -2751,20 +2798,30 @@ int tls_set_sw_offload(struct sock *sk, int tx)
ctx->push_pending_record = tls_sw_push_pending_record;
+ /* setkey is the last operation that could fail during a
+ * rekey. if it succeeds, we can start modifying the
+ * context.
+ */
rc = crypto_aead_setkey(*aead, key, cipher_desc->key);
- if (rc)
- goto free_aead;
+ if (rc) {
+ if (new_crypto_info)
+ goto out;
+ else
+ goto free_aead;
+ }
- rc = crypto_aead_setauthsize(*aead, prot->tag_size);
- if (rc)
- goto free_aead;
+ if (!new_crypto_info) {
+ rc = crypto_aead_setauthsize(*aead, prot->tag_size);
+ if (rc)
+ goto free_aead;
+ }
- if (sw_ctx_rx) {
+ if (!tx && !new_crypto_info) {
tfm = crypto_aead_tfm(sw_ctx_rx->aead_recv);
tls_update_rx_zc_capable(ctx);
sw_ctx_rx->async_capable =
- crypto_info->version != TLS_1_3_VERSION &&
+ src_crypto_info->version != TLS_1_3_VERSION &&
!!(tfm->__crt_alg->cra_flags & CRYPTO_ALG_ASYNC);
rc = tls_strp_init(&sw_ctx_rx->strp, sk);
@@ -2772,18 +2829,33 @@ int tls_set_sw_offload(struct sock *sk, int tx)
goto free_aead;
}
+ memcpy(cctx->iv, salt, cipher_desc->salt);
+ memcpy(cctx->iv + cipher_desc->salt, iv, cipher_desc->iv);
+ memcpy(cctx->rec_seq, rec_seq, cipher_desc->rec_seq);
+
+ if (new_crypto_info) {
+ unsafe_memcpy(crypto_info, new_crypto_info,
+ cipher_desc->crypto_info,
+ /* size was checked in do_tls_setsockopt_conf */);
+ memzero_explicit(new_crypto_info, cipher_desc->crypto_info);
+ if (!tx)
+ tls_finish_key_update(sk, ctx);
+ }
+
goto out;
free_aead:
crypto_free_aead(*aead);
*aead = NULL;
free_priv:
- if (tx) {
- kfree(ctx->priv_ctx_tx);
- ctx->priv_ctx_tx = NULL;
- } else {
- kfree(ctx->priv_ctx_rx);
- ctx->priv_ctx_rx = NULL;
+ if (!new_crypto_info) {
+ if (tx) {
+ kfree(ctx->priv_ctx_tx);
+ ctx->priv_ctx_tx = NULL;
+ } else {
+ kfree(ctx->priv_ctx_rx);
+ ctx->priv_ctx_rx = NULL;
+ }
}
out:
return rc;
diff --git a/net/unix/Kconfig b/net/unix/Kconfig
index 8b5d04210d7c..6f1783c1659b 100644
--- a/net/unix/Kconfig
+++ b/net/unix/Kconfig
@@ -17,9 +17,11 @@ config UNIX
Say Y unless you know what you are doing.
config AF_UNIX_OOB
- bool
+ bool "UNIX: out-of-bound messages"
depends on UNIX
default y
+ help
+ Support for MSG_OOB in UNIX domain sockets. If unsure, say Y.
config UNIX_DIAG
tristate "UNIX: socket monitoring interface"
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 001ccc55ef0f..8f2b605ce5b3 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -286,14 +286,9 @@ static inline bool unix_secdata_eq(struct scm_cookie *scm, struct sk_buff *skb)
}
#endif /* CONFIG_SECURITY_NETWORK */
-static inline int unix_our_peer(struct sock *sk, struct sock *osk)
-{
- return unix_peer(osk) == sk;
-}
-
static inline int unix_may_send(struct sock *sk, struct sock *osk)
{
- return unix_peer(osk) == NULL || unix_our_peer(sk, osk);
+ return !unix_peer(osk) || unix_peer(osk) == sk;
}
static inline int unix_recvq_full_lockless(const struct sock *sk)
@@ -1563,32 +1558,30 @@ static int unix_stream_connect(struct socket *sock, struct sockaddr *uaddr,
timeo = sock_sndtimeo(sk, flags & O_NONBLOCK);
/* First of all allocate resources.
- If we will make it after state is locked,
- we will have to recheck all again in any case.
+ * If we will make it after state is locked,
+ * we will have to recheck all again in any case.
*/
/* create new sock for complete connection */
newsk = unix_create1(net, NULL, 0, sock->type);
if (IS_ERR(newsk)) {
err = PTR_ERR(newsk);
- newsk = NULL;
goto out;
}
- err = -ENOMEM;
-
/* Allocate skb for sending to listening sock */
skb = sock_wmalloc(newsk, 1, 0, GFP_KERNEL);
- if (skb == NULL)
- goto out;
+ if (!skb) {
+ err = -ENOMEM;
+ goto out_free_sk;
+ }
restart:
/* Find listening sock. */
other = unix_find_other(net, sunaddr, addr_len, sk->sk_type);
if (IS_ERR(other)) {
err = PTR_ERR(other);
- other = NULL;
- goto out;
+ goto out_free_skb;
}
unix_state_lock(other);
@@ -1600,23 +1593,25 @@ restart:
goto restart;
}
- err = -ECONNREFUSED;
- if (other->sk_state != TCP_LISTEN)
- goto out_unlock;
- if (other->sk_shutdown & RCV_SHUTDOWN)
+ if (other->sk_state != TCP_LISTEN ||
+ other->sk_shutdown & RCV_SHUTDOWN) {
+ err = -ECONNREFUSED;
goto out_unlock;
+ }
if (unix_recvq_full_lockless(other)) {
- err = -EAGAIN;
- if (!timeo)
+ if (!timeo) {
+ err = -EAGAIN;
goto out_unlock;
+ }
timeo = unix_wait_for_peer(other, timeo);
+ sock_put(other);
err = sock_intr_errno(timeo);
if (signal_pending(current))
- goto out;
- sock_put(other);
+ goto out_free_skb;
+
goto restart;
}
@@ -1701,15 +1696,13 @@ restart:
return 0;
out_unlock:
- if (other)
- unix_state_unlock(other);
-
-out:
+ unix_state_unlock(other);
+ sock_put(other);
+out_free_skb:
kfree_skb(skb);
- if (newsk)
- unix_release_sock(newsk, 0);
- if (other)
- sock_put(other);
+out_free_sk:
+ unix_release_sock(newsk, 0);
+out:
return err;
}
@@ -1964,7 +1957,6 @@ static void scm_stat_del(struct sock *sk, struct sk_buff *skb)
static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
size_t len)
{
- DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, msg->msg_name);
struct sock *sk = sock->sk, *other = NULL;
struct unix_sock *u = unix_sk(sk);
struct scm_cookie scm;
@@ -1980,12 +1972,13 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
wait_for_unix_gc(scm.fp);
- err = -EOPNOTSUPP;
- if (msg->msg_flags&MSG_OOB)
+ if (msg->msg_flags & MSG_OOB) {
+ err = -EOPNOTSUPP;
goto out;
+ }
if (msg->msg_namelen) {
- err = unix_validate_addr(sunaddr, msg->msg_namelen);
+ err = unix_validate_addr(msg->msg_name, msg->msg_namelen);
if (err)
goto out;
@@ -1995,12 +1988,6 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
NULL);
if (err)
goto out;
- } else {
- sunaddr = NULL;
- err = -ENOTCONN;
- other = unix_peer_get(sk);
- if (!other)
- goto out;
}
if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
@@ -2011,9 +1998,10 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
goto out;
}
- err = -EMSGSIZE;
- if (len > READ_ONCE(sk->sk_sndbuf) - 32)
+ if (len > READ_ONCE(sk->sk_sndbuf) - 32) {
+ err = -EMSGSIZE;
goto out;
+ }
if (len > SKB_MAX_ALLOC) {
data_len = min_t(size_t,
@@ -2027,7 +2015,7 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
skb = sock_alloc_send_pskb(sk, len - data_len, data_len,
msg->msg_flags & MSG_DONTWAIT, &err,
PAGE_ALLOC_COSTLY_ORDER);
- if (skb == NULL)
+ if (!skb)
goto out;
err = unix_scm_to_skb(&scm, skb, true);
@@ -2043,17 +2031,18 @@ static int unix_dgram_sendmsg(struct socket *sock, struct msghdr *msg,
timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT);
-restart:
- if (!other) {
- err = -ECONNRESET;
- if (sunaddr == NULL)
- goto out_free;
-
- other = unix_find_other(sock_net(sk), sunaddr, msg->msg_namelen,
- sk->sk_type);
+ if (msg->msg_namelen) {
+lookup:
+ other = unix_find_other(sock_net(sk), msg->msg_name,
+ msg->msg_namelen, sk->sk_type);
if (IS_ERR(other)) {
err = PTR_ERR(other);
- other = NULL;
+ goto out_free;
+ }
+ } else {
+ other = unix_peer_get(sk);
+ if (!other) {
+ err = -ENOTCONN;
goto out_free;
}
}
@@ -2061,36 +2050,37 @@ restart:
if (sk_filter(other, skb) < 0) {
/* Toss the packet but do not return any error to the sender */
err = len;
- goto out_free;
+ goto out_sock_put;
}
+restart:
sk_locked = 0;
unix_state_lock(other);
restart_locked:
- err = -EPERM;
- if (!unix_may_send(sk, other))
+
+ if (!unix_may_send(sk, other)) {
+ err = -EPERM;
goto out_unlock;
+ }
if (unlikely(sock_flag(other, SOCK_DEAD))) {
- /*
- * Check with 1003.1g - what should
- * datagram error
- */
- unix_state_unlock(other);
- sock_put(other);
+ /* Check with 1003.1g - what should datagram error */
- if (!sk_locked)
- unix_state_lock(sk);
+ unix_state_unlock(other);
- err = 0;
if (sk->sk_type == SOCK_SEQPACKET) {
/* We are here only when racing with unix_release_sock()
* is clearing @other. Never change state to TCP_CLOSE
* unlike SOCK_DGRAM wants.
*/
- unix_state_unlock(sk);
err = -EPIPE;
- } else if (unix_peer(sk) == other) {
+ goto out_sock_put;
+ }
+
+ if (!sk_locked)
+ unix_state_lock(sk);
+
+ if (unix_peer(sk) == other) {
unix_peer(sk) = NULL;
unix_dgram_peer_wake_disconnect_wakeup(sk, other);
@@ -2100,19 +2090,23 @@ restart_locked:
unix_dgram_disconnected(sk, other);
sock_put(other);
err = -ECONNREFUSED;
- } else {
- unix_state_unlock(sk);
+ goto out_sock_put;
}
- other = NULL;
- if (err)
- goto out_free;
- goto restart;
+ unix_state_unlock(sk);
+
+ if (!msg->msg_namelen) {
+ err = -ECONNRESET;
+ goto out_sock_put;
+ }
+
+ goto lookup;
}
- err = -EPIPE;
- if (other->sk_shutdown & RCV_SHUTDOWN)
+ if (other->sk_shutdown & RCV_SHUTDOWN) {
+ err = -EPIPE;
goto out_unlock;
+ }
if (sk->sk_type != SOCK_SEQPACKET) {
err = security_unix_may_send(sk->sk_socket, other->sk_socket);
@@ -2132,7 +2126,7 @@ restart_locked:
err = sock_intr_errno(timeo);
if (signal_pending(current))
- goto out_free;
+ goto out_sock_put;
goto restart;
}
@@ -2173,11 +2167,11 @@ out_unlock:
if (sk_locked)
unix_state_unlock(sk);
unix_state_unlock(other);
+out_sock_put:
+ sock_put(other);
out_free:
kfree_skb(skb);
out:
- if (other)
- sock_put(other);
scm_destroy(&scm);
return err;
}
@@ -2256,8 +2250,8 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
wait_for_unix_gc(scm.fp);
- err = -EOPNOTSUPP;
if (msg->msg_flags & MSG_OOB) {
+ err = -EOPNOTSUPP;
#if IS_ENABLED(CONFIG_AF_UNIX_OOB)
if (len)
len--;
@@ -2270,14 +2264,20 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
err = READ_ONCE(sk->sk_state) == TCP_ESTABLISHED ? -EISCONN : -EOPNOTSUPP;
goto out_err;
} else {
- err = -ENOTCONN;
other = unix_peer(sk);
- if (!other)
+ if (!other) {
+ err = -ENOTCONN;
goto out_err;
+ }
}
- if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN)
- goto pipe_err;
+ if (READ_ONCE(sk->sk_shutdown) & SEND_SHUTDOWN) {
+ if (!(msg->msg_flags & MSG_NOSIGNAL))
+ send_sig(SIGPIPE, current, 0);
+
+ err = -EPIPE;
+ goto out_err;
+ }
while (sent < len) {
size = len - sent;
@@ -2306,19 +2306,18 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
/* Only send the fds in the first buffer */
err = unix_scm_to_skb(&scm, skb, !fds_sent);
- if (err < 0) {
- kfree_skb(skb);
- goto out_err;
- }
+ if (err < 0)
+ goto out_free;
+
fds_sent = true;
if (unlikely(msg->msg_flags & MSG_SPLICE_PAGES)) {
+ skb->ip_summed = CHECKSUM_UNNECESSARY;
err = skb_splice_from_iter(skb, &msg->msg_iter, size,
sk->sk_allocation);
- if (err < 0) {
- kfree_skb(skb);
- goto out_err;
- }
+ if (err < 0)
+ goto out_free;
+
size = err;
refcount_add(size, &sk->sk_wmem_alloc);
} else {
@@ -2326,17 +2325,15 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
skb->data_len = data_len;
skb->len = size;
err = skb_copy_datagram_from_iter(skb, 0, &msg->msg_iter, size);
- if (err) {
- kfree_skb(skb);
- goto out_err;
- }
+ if (err)
+ goto out_free;
}
unix_state_lock(other);
if (sock_flag(other, SOCK_DEAD) ||
(other->sk_shutdown & RCV_SHUTDOWN))
- goto pipe_err_free;
+ goto out_pipe;
maybe_add_creds(skb, sock, other);
scm_stat_add(other, skb);
@@ -2359,13 +2356,13 @@ static int unix_stream_sendmsg(struct socket *sock, struct msghdr *msg,
return sent;
-pipe_err_free:
+out_pipe:
unix_state_unlock(other);
- kfree_skb(skb);
-pipe_err:
- if (sent == 0 && !(msg->msg_flags&MSG_NOSIGNAL))
+ if (!sent && !(msg->msg_flags & MSG_NOSIGNAL))
send_sig(SIGPIPE, current, 0);
err = -EPIPE;
+out_free:
+ kfree_skb(skb);
out_err:
scm_destroy(&scm);
return sent ? : err;
diff --git a/net/vmw_vsock/af_vsock.c b/net/vmw_vsock/af_vsock.c
index 25b28b1434f5..5cf8109f672a 100644
--- a/net/vmw_vsock/af_vsock.c
+++ b/net/vmw_vsock/af_vsock.c
@@ -117,12 +117,14 @@
static int __vsock_bind(struct sock *sk, struct sockaddr_vm *addr);
static void vsock_sk_destruct(struct sock *sk);
static int vsock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb);
+static void vsock_close(struct sock *sk, long timeout);
/* Protocol family. */
struct proto vsock_proto = {
.name = "AF_VSOCK",
.owner = THIS_MODULE,
.obj_size = sizeof(struct vsock_sock),
+ .close = vsock_close,
#ifdef CONFIG_BPF_SYSCALL
.psock_update_sk_prot = vsock_bpf_update_proto,
#endif
@@ -797,39 +799,37 @@ static bool sock_type_connectible(u16 type)
static void __vsock_release(struct sock *sk, int level)
{
- if (sk) {
- struct sock *pending;
- struct vsock_sock *vsk;
-
- vsk = vsock_sk(sk);
- pending = NULL; /* Compiler warning. */
+ struct vsock_sock *vsk;
+ struct sock *pending;
- /* When "level" is SINGLE_DEPTH_NESTING, use the nested
- * version to avoid the warning "possible recursive locking
- * detected". When "level" is 0, lock_sock_nested(sk, level)
- * is the same as lock_sock(sk).
- */
- lock_sock_nested(sk, level);
+ vsk = vsock_sk(sk);
+ pending = NULL; /* Compiler warning. */
- if (vsk->transport)
- vsk->transport->release(vsk);
- else if (sock_type_connectible(sk->sk_type))
- vsock_remove_sock(vsk);
+ /* When "level" is SINGLE_DEPTH_NESTING, use the nested
+ * version to avoid the warning "possible recursive locking
+ * detected". When "level" is 0, lock_sock_nested(sk, level)
+ * is the same as lock_sock(sk).
+ */
+ lock_sock_nested(sk, level);
- sock_orphan(sk);
- sk->sk_shutdown = SHUTDOWN_MASK;
+ if (vsk->transport)
+ vsk->transport->release(vsk);
+ else if (sock_type_connectible(sk->sk_type))
+ vsock_remove_sock(vsk);
- skb_queue_purge(&sk->sk_receive_queue);
+ sock_orphan(sk);
+ sk->sk_shutdown = SHUTDOWN_MASK;
- /* Clean up any sockets that never were accepted. */
- while ((pending = vsock_dequeue_accept(sk)) != NULL) {
- __vsock_release(pending, SINGLE_DEPTH_NESTING);
- sock_put(pending);
- }
+ skb_queue_purge(&sk->sk_receive_queue);
- release_sock(sk);
- sock_put(sk);
+ /* Clean up any sockets that never were accepted. */
+ while ((pending = vsock_dequeue_accept(sk)) != NULL) {
+ __vsock_release(pending, SINGLE_DEPTH_NESTING);
+ sock_put(pending);
}
+
+ release_sock(sk);
+ sock_put(sk);
}
static void vsock_sk_destruct(struct sock *sk)
@@ -901,9 +901,22 @@ void vsock_data_ready(struct sock *sk)
}
EXPORT_SYMBOL_GPL(vsock_data_ready);
+/* Dummy callback required by sockmap.
+ * See unconditional call of saved_close() in sock_map_close().
+ */
+static void vsock_close(struct sock *sk, long timeout)
+{
+}
+
static int vsock_release(struct socket *sock)
{
- __vsock_release(sock->sk, 0);
+ struct sock *sk = sock->sk;
+
+ if (!sk)
+ return 0;
+
+ sk->sk_prot->close(sk, 0);
+ __vsock_release(sk, 0);
sock->sk = NULL;
sock->state = SS_FREE;
@@ -1054,6 +1067,9 @@ static __poll_t vsock_poll(struct file *file, struct socket *sock,
mask |= EPOLLRDHUP;
}
+ if (sk_is_readable(sk))
+ mask |= EPOLLIN | EPOLLRDNORM;
+
if (sock->type == SOCK_DGRAM) {
/* For datagram sockets we can read if there is something in
* the queue and write as long as the socket isn't shutdown for
diff --git a/net/wireless/chan.c b/net/wireless/chan.c
index 40b6375a5de4..833ea73053a4 100644
--- a/net/wireless/chan.c
+++ b/net/wireless/chan.c
@@ -1039,10 +1039,10 @@ bool cfg80211_any_wiphy_oper_chan(struct wiphy *wiphy,
if (!reg_dfs_domain_same(wiphy, &rdev->wiphy))
continue;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
found = cfg80211_is_wiphy_oper_chan(&rdev->wiphy, chan) ||
cfg80211_offchan_chain_is_active(rdev, chan);
- wiphy_unlock(&rdev->wiphy);
if (found)
return true;
diff --git a/net/wireless/core.c b/net/wireless/core.c
index afbdc549fb4a..70857018f020 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -191,7 +191,8 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
return err;
}
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->netdev)
continue;
@@ -212,7 +213,6 @@ int cfg80211_switch_netns(struct cfg80211_registered_device *rdev,
continue;
nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
}
- wiphy_unlock(&rdev->wiphy);
return 0;
}
@@ -221,9 +221,9 @@ static void cfg80211_rfkill_poll(struct rfkill *rfkill, void *data)
{
struct cfg80211_registered_device *rdev = data;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
rdev_rfkill_poll(rdev);
- wiphy_unlock(&rdev->wiphy);
}
void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev,
@@ -283,7 +283,7 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
/* otherwise, check iftype */
- wiphy_lock(wiphy);
+ guard(wiphy)(wiphy);
switch (wdev->iftype) {
case NL80211_IFTYPE_P2P_DEVICE:
@@ -295,8 +295,6 @@ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy)
default:
break;
}
-
- wiphy_unlock(wiphy);
}
}
EXPORT_SYMBOL_GPL(cfg80211_shutdown_all_interfaces);
@@ -331,9 +329,9 @@ static void cfg80211_event_work(struct work_struct *work)
rdev = container_of(work, struct cfg80211_registered_device,
event_work);
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
cfg80211_process_rdev_events(rdev);
- wiphy_unlock(&rdev->wiphy);
}
void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
@@ -347,10 +345,10 @@ void cfg80211_destroy_ifaces(struct cfg80211_registered_device *rdev)
if (wdev->netdev)
dev_close(wdev->netdev);
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
cfg80211_leave(rdev, wdev);
cfg80211_remove_virtual_intf(rdev, wdev);
- wiphy_unlock(&rdev->wiphy);
}
}
}
@@ -423,9 +421,9 @@ static void cfg80211_wiphy_work(struct work_struct *work)
trace_wiphy_work_worker_start(&rdev->wiphy);
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
if (rdev->suspended)
- goto out;
+ return;
spin_lock_irq(&rdev->wiphy_work_lock);
wk = list_first_entry_or_null(&rdev->wiphy_work_list,
@@ -441,8 +439,6 @@ static void cfg80211_wiphy_work(struct work_struct *work)
} else {
spin_unlock_irq(&rdev->wiphy_work_lock);
}
-out:
- wiphy_unlock(&rdev->wiphy);
}
/* exported functions */
@@ -1526,9 +1522,9 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
break;
case NETDEV_REGISTER:
if (!wdev->registered) {
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
cfg80211_register_wdev(rdev, wdev);
- wiphy_unlock(&rdev->wiphy);
}
break;
case NETDEV_UNREGISTER:
@@ -1537,16 +1533,16 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb,
* so check wdev->registered.
*/
if (wdev->registered && !wdev->registering) {
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
_cfg80211_unregister_wdev(wdev, false);
- wiphy_unlock(&rdev->wiphy);
}
break;
case NETDEV_GOING_DOWN:
- wiphy_lock(&rdev->wiphy);
- cfg80211_leave(rdev, wdev);
- cfg80211_remove_links(wdev);
- wiphy_unlock(&rdev->wiphy);
+ scoped_guard(wiphy, &rdev->wiphy) {
+ cfg80211_leave(rdev, wdev);
+ cfg80211_remove_links(wdev);
+ }
/* since we just did cfg80211_leave() nothing to do there */
cancel_work_sync(&wdev->disconnect_wk);
cancel_work_sync(&wdev->pmsr_free_wk);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index a5eb92d93074..9d577523462d 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -627,10 +627,10 @@ void cfg80211_mgmt_registrations_update_wk(struct work_struct *wk)
rdev = container_of(wk, struct cfg80211_registered_device,
mgmt_registrations_update_wk);
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
cfg80211_mgmt_registrations_update(wdev);
- wiphy_unlock(&rdev->wiphy);
}
int cfg80211_mlme_register_mgmt(struct wireless_dev *wdev, u32 snd_portid,
@@ -1193,10 +1193,10 @@ cfg80211_background_cac_event(struct cfg80211_registered_device *rdev,
const struct cfg80211_chan_def *chandef,
enum nl80211_radar_event event)
{
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
__cfg80211_background_cac_event(rdev, rdev->background_radar_wdev,
chandef, event);
- wiphy_unlock(&rdev->wiphy);
}
void cfg80211_background_cac_done_wk(struct work_struct *work)
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 9d2edb71f981..8789d8b73f0f 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -814,7 +814,7 @@ static const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
[NL80211_ATTR_MLO_LINKS] =
NLA_POLICY_NESTED_ARRAY(nl80211_policy),
[NL80211_ATTR_MLO_LINK_ID] =
- NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS),
+ NLA_POLICY_RANGE(NLA_U8, 0, IEEE80211_MLD_MAX_NUM_LINKS - 1),
[NL80211_ATTR_MLD_ADDR] = NLA_POLICY_EXACT_LEN(ETH_ALEN),
[NL80211_ATTR_MLO_SUPPORT] = { .type = NLA_FLAG },
[NL80211_ATTR_MAX_NUM_AKM_SUITES] = { .type = NLA_REJECT },
@@ -3626,7 +3626,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
} else
wdev = netdev->ieee80211_ptr;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
/*
* end workaround code, by now the rdev is available
@@ -3639,32 +3639,24 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rtnl_unlock();
if (result)
- goto out;
+ return result;
if (info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS]) {
struct ieee80211_txq_params txq_params;
struct nlattr *tb[NL80211_TXQ_ATTR_MAX + 1];
- if (!rdev->ops->set_txq_params) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->set_txq_params)
+ return -EOPNOTSUPP;
- if (!netdev) {
- result = -EINVAL;
- goto out;
- }
+ if (!netdev)
+ return -EINVAL;
if (netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
- netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) {
- result = -EINVAL;
- goto out;
- }
+ netdev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+ return -EINVAL;
- if (!netif_running(netdev)) {
- result = -ENETDOWN;
- goto out;
- }
+ if (!netif_running(netdev))
+ return -ENETDOWN;
nla_for_each_nested(nl_txq_params,
info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS],
@@ -3675,10 +3667,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
txq_params_policy,
info->extack);
if (result)
- goto out;
+ return result;
+
result = parse_txq_params(tb, &txq_params);
if (result)
- goto out;
+ return result;
txq_params.link_id =
nl80211_link_id_or_invalid(info->attrs);
@@ -3694,7 +3687,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
result = rdev_set_txq_params(rdev, netdev,
&txq_params);
if (result)
- goto out;
+ return result;
}
}
@@ -3711,7 +3704,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
if (result)
- goto out;
+ return result;
}
if (info->attrs[NL80211_ATTR_WIPHY_TX_POWER_SETTING]) {
@@ -3722,19 +3715,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (!(rdev->wiphy.features & NL80211_FEATURE_VIF_TXPOWER))
txp_wdev = NULL;
- if (!rdev->ops->set_tx_power) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->set_tx_power)
+ return -EOPNOTSUPP;
idx = NL80211_ATTR_WIPHY_TX_POWER_SETTING;
type = nla_get_u32(info->attrs[idx]);
if (!info->attrs[NL80211_ATTR_WIPHY_TX_POWER_LEVEL] &&
- (type != NL80211_TX_POWER_AUTOMATIC)) {
- result = -EINVAL;
- goto out;
- }
+ (type != NL80211_TX_POWER_AUTOMATIC))
+ return -EINVAL;
if (type != NL80211_TX_POWER_AUTOMATIC) {
idx = NL80211_ATTR_WIPHY_TX_POWER_LEVEL;
@@ -3743,7 +3732,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
result = rdev_set_tx_power(rdev, txp_wdev, type, mbm);
if (result)
- goto out;
+ return result;
}
if (info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX] &&
@@ -3752,10 +3741,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if ((!rdev->wiphy.available_antennas_tx &&
!rdev->wiphy.available_antennas_rx) ||
- !rdev->ops->set_antenna) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ !rdev->ops->set_antenna)
+ return -EOPNOTSUPP;
tx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_TX]);
rx_ant = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_ANTENNA_RX]);
@@ -3763,17 +3750,15 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
/* reject antenna configurations which don't match the
* available antenna masks, except for the "all" mask */
if ((~tx_ant && (tx_ant & ~rdev->wiphy.available_antennas_tx)) ||
- (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx))) {
- result = -EINVAL;
- goto out;
- }
+ (~rx_ant && (rx_ant & ~rdev->wiphy.available_antennas_rx)))
+ return -EINVAL;
tx_ant = tx_ant & rdev->wiphy.available_antennas_tx;
rx_ant = rx_ant & rdev->wiphy.available_antennas_rx;
result = rdev_set_antenna(rdev, tx_ant, rx_ant);
if (result)
- goto out;
+ return result;
}
changed = 0;
@@ -3795,10 +3780,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]) {
frag_threshold = nla_get_u32(
info->attrs[NL80211_ATTR_WIPHY_FRAG_THRESHOLD]);
- if (frag_threshold < 256) {
- result = -EINVAL;
- goto out;
- }
+ if (frag_threshold < 256)
+ return -EINVAL;
if (frag_threshold != (u32) -1) {
/*
@@ -3819,10 +3802,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
if (info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]) {
- if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
- result = -EINVAL;
- goto out;
- }
+ if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK])
+ return -EINVAL;
coverage_class = nla_get_u8(
info->attrs[NL80211_ATTR_WIPHY_COVERAGE_CLASS]);
@@ -3830,20 +3811,17 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
}
if (info->attrs[NL80211_ATTR_WIPHY_DYN_ACK]) {
- if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION)) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ if (!(rdev->wiphy.features & NL80211_FEATURE_ACKTO_ESTIMATION))
+ return -EOPNOTSUPP;
changed |= WIPHY_PARAM_DYN_ACK;
}
if (info->attrs[NL80211_ATTR_TXQ_LIMIT]) {
if (!wiphy_ext_feature_isset(&rdev->wiphy,
- NL80211_EXT_FEATURE_TXQS)) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ NL80211_EXT_FEATURE_TXQS))
+ return -EOPNOTSUPP;
+
txq_limit = nla_get_u32(
info->attrs[NL80211_ATTR_TXQ_LIMIT]);
changed |= WIPHY_PARAM_TXQ_LIMIT;
@@ -3851,10 +3829,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]) {
if (!wiphy_ext_feature_isset(&rdev->wiphy,
- NL80211_EXT_FEATURE_TXQS)) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ NL80211_EXT_FEATURE_TXQS))
+ return -EOPNOTSUPP;
+
txq_memory_limit = nla_get_u32(
info->attrs[NL80211_ATTR_TXQ_MEMORY_LIMIT]);
changed |= WIPHY_PARAM_TXQ_MEMORY_LIMIT;
@@ -3862,10 +3839,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
if (info->attrs[NL80211_ATTR_TXQ_QUANTUM]) {
if (!wiphy_ext_feature_isset(&rdev->wiphy,
- NL80211_EXT_FEATURE_TXQS)) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ NL80211_EXT_FEATURE_TXQS))
+ return -EOPNOTSUPP;
+
txq_quantum = nla_get_u32(
info->attrs[NL80211_ATTR_TXQ_QUANTUM]);
changed |= WIPHY_PARAM_TXQ_QUANTUM;
@@ -3877,10 +3853,8 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
u8 old_coverage_class;
u32 old_txq_limit, old_txq_memory_limit, old_txq_quantum;
- if (!rdev->ops->set_wiphy_params) {
- result = -EOPNOTSUPP;
- goto out;
- }
+ if (!rdev->ops->set_wiphy_params)
+ return -EOPNOTSUPP;
old_retry_short = rdev->wiphy.retry_short;
old_retry_long = rdev->wiphy.retry_long;
@@ -3918,15 +3892,11 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info)
rdev->wiphy.txq_limit = old_txq_limit;
rdev->wiphy.txq_memory_limit = old_txq_memory_limit;
rdev->wiphy.txq_quantum = old_txq_quantum;
- goto out;
+ return result;
}
}
- result = 0;
-
-out:
- wiphy_unlock(&rdev->wiphy);
- return result;
+ return 0;
}
int nl80211_send_chandef(struct sk_buff *msg, const struct cfg80211_chan_def *chandef)
@@ -4010,10 +3980,10 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
goto nla_put_failure;
}
- if (rdev->ops->get_tx_power) {
+ if (rdev->ops->get_tx_power && !wdev->valid_links) {
int dbm, ret;
- ret = rdev_get_tx_power(rdev, wdev, &dbm);
+ ret = rdev_get_tx_power(rdev, wdev, 0, &dbm);
if (ret == 0 &&
nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
DBM_TO_MBM(dbm)))
@@ -4082,6 +4052,15 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flag
if (ret == 0 && nl80211_send_chandef(msg, &chandef))
goto nla_put_failure;
+ if (rdev->ops->get_tx_power) {
+ int dbm, ret;
+
+ ret = rdev_get_tx_power(rdev, wdev, link_id, &dbm);
+ if (ret == 0 &&
+ nla_put_u32(msg, NL80211_ATTR_WIPHY_TX_POWER_LEVEL,
+ DBM_TO_MBM(dbm)))
+ goto nla_put_failure;
+ }
nla_nest_end(msg, link);
}
@@ -4144,22 +4123,22 @@ static int nl80211_dump_interface(struct sk_buff *skb, struct netlink_callback *
if_idx = 0;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (if_idx < if_start) {
if_idx++;
continue;
}
+
if (nl80211_send_iface(skb, NETLINK_CB(cb->skb).portid,
cb->nlh->nlmsg_seq, NLM_F_MULTI,
rdev, wdev,
- NL80211_CMD_NEW_INTERFACE) < 0) {
- wiphy_unlock(&rdev->wiphy);
+ NL80211_CMD_NEW_INTERFACE) < 0)
goto out;
- }
+
if_idx++;
}
- wiphy_unlock(&rdev->wiphy);
if_start = 0;
wp_idx++;
@@ -4517,16 +4496,13 @@ static int _nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info)
{
struct cfg80211_registered_device *rdev = info->user_ptr[0];
- int ret;
/* to avoid failing a new interface creation due to pending removal */
cfg80211_destroy_ifaces(rdev);
- wiphy_lock(&rdev->wiphy);
- ret = _nl80211_new_interface(skb, info);
- wiphy_unlock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
- return ret;
+ return _nl80211_new_interface(skb, info);
}
static int nl80211_del_interface(struct sk_buff *skb, struct genl_info *info)
@@ -10098,7 +10074,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
struct cfg80211_chan_def chandef;
enum nl80211_dfs_regions dfs_region;
unsigned int cac_time_ms;
- int err = -EINVAL;
+ int err;
flush_delayed_work(&rdev->dfs_update_channels_wk);
@@ -10113,35 +10089,29 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
return -EINVAL;
}
- wiphy_lock(wiphy);
+ guard(wiphy)(wiphy);
dfs_region = reg_get_dfs_region(wiphy);
if (dfs_region == NL80211_DFS_UNSET)
- goto unlock;
+ return -EINVAL;
err = nl80211_parse_chandef(rdev, info, &chandef);
if (err)
- goto unlock;
+ return err;
err = cfg80211_chandef_dfs_required(wiphy, &chandef, wdev->iftype);
if (err < 0)
- goto unlock;
+ return err;
- if (err == 0) {
- err = -EINVAL;
- goto unlock;
- }
+ if (err == 0)
+ return -EINVAL;
- if (!cfg80211_chandef_dfs_usable(wiphy, &chandef)) {
- err = -EINVAL;
- goto unlock;
- }
+ if (!cfg80211_chandef_dfs_usable(wiphy, &chandef))
+ return -EINVAL;
- if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND])) {
- err = cfg80211_start_background_radar_detection(rdev, wdev,
- &chandef);
- goto unlock;
- }
+ if (nla_get_flag(info->attrs[NL80211_ATTR_RADAR_BACKGROUND]))
+ return cfg80211_start_background_radar_detection(rdev, wdev,
+ &chandef);
if (cfg80211_beaconing_iface_active(wdev)) {
/* During MLO other link(s) can beacon, only the current link
@@ -10151,26 +10121,19 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
!wdev->links[link_id].ap.beacon_interval) {
/* nothing */
} else {
- err = -EBUSY;
- goto unlock;
+ return -EBUSY;
}
}
- if (wdev->links[link_id].cac_started) {
- err = -EBUSY;
- goto unlock;
- }
+ if (wdev->links[link_id].cac_started)
+ return -EBUSY;
/* CAC start is offloaded to HW and can't be started manually */
- if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD)) {
- err = -EOPNOTSUPP;
- goto unlock;
- }
+ if (wiphy_ext_feature_isset(wiphy, NL80211_EXT_FEATURE_DFS_OFFLOAD))
+ return -EOPNOTSUPP;
- if (!rdev->ops->start_radar_detection) {
- err = -EOPNOTSUPP;
- goto unlock;
- }
+ if (!rdev->ops->start_radar_detection)
+ return -EOPNOTSUPP;
cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef);
if (WARN_ON(!cac_time_ms))
@@ -10197,10 +10160,8 @@ static int nl80211_start_radar_detection(struct sk_buff *skb,
wdev->links[link_id].cac_start_time = jiffies;
wdev->links[link_id].cac_time_ms = cac_time_ms;
}
-unlock:
- wiphy_unlock(wiphy);
- return err;
+ return 0;
}
static int nl80211_notify_radar_detection(struct sk_buff *skb,
diff --git a/net/wireless/pmsr.c b/net/wireless/pmsr.c
index 0396fa19bdf1..a117f5093ca2 100644
--- a/net/wireless/pmsr.c
+++ b/net/wireless/pmsr.c
@@ -630,9 +630,9 @@ void cfg80211_pmsr_free_wk(struct work_struct *work)
struct wireless_dev *wdev = container_of(work, struct wireless_dev,
pmsr_free_wk);
- wiphy_lock(wdev->wiphy);
+ guard(wiphy)(wdev->wiphy);
+
cfg80211_pmsr_process_abort(wdev);
- wiphy_unlock(wdev->wiphy);
}
void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index adb6105bbb7d..8f2aa7e76c0a 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -600,11 +600,12 @@ static inline int rdev_set_tx_power(struct cfg80211_registered_device *rdev,
}
static inline int rdev_get_tx_power(struct cfg80211_registered_device *rdev,
- struct wireless_dev *wdev, int *dbm)
+ struct wireless_dev *wdev, unsigned int link_id,
+ int *dbm)
{
int ret;
- trace_rdev_get_tx_power(&rdev->wiphy, wdev);
- ret = rdev->ops->get_tx_power(&rdev->wiphy, wdev, dbm);
+ trace_rdev_get_tx_power(&rdev->wiphy, wdev, link_id);
+ ret = rdev->ops->get_tx_power(&rdev->wiphy, wdev, link_id, dbm);
trace_rdev_return_int_int(&rdev->wiphy, ret, *dbm);
return ret;
}
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 1df65a5a44f7..2dd0533e7660 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -2465,11 +2465,11 @@ static void reg_leave_invalid_chans(struct wiphy *wiphy)
struct wireless_dev *wdev;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
- wiphy_lock(wiphy);
+ guard(wiphy)(wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list)
if (!reg_wdev_chan_valid(wiphy, wdev))
cfg80211_leave(rdev, wdev);
- wiphy_unlock(wiphy);
}
static void reg_check_chans_work(struct work_struct *work)
@@ -2649,13 +2649,11 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
return;
rtnl_lock();
- wiphy_lock(wiphy);
-
- tmp = get_wiphy_regdom(wiphy);
- rcu_assign_pointer(wiphy->regd, new_regd);
- rcu_free_regdom(tmp);
-
- wiphy_unlock(wiphy);
+ scoped_guard(wiphy, wiphy) {
+ tmp = get_wiphy_regdom(wiphy);
+ rcu_assign_pointer(wiphy->regd, new_regd);
+ rcu_free_regdom(tmp);
+ }
rtnl_unlock();
}
EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
@@ -2825,9 +2823,9 @@ reg_process_hint_driver(struct wiphy *wiphy,
tmp = get_wiphy_regdom(wiphy);
ASSERT_RTNL();
- wiphy_lock(wiphy);
- rcu_assign_pointer(wiphy->regd, regd);
- wiphy_unlock(wiphy);
+ scoped_guard(wiphy, wiphy) {
+ rcu_assign_pointer(wiphy->regd, regd);
+ }
rcu_free_regdom(tmp);
}
@@ -3205,9 +3203,9 @@ static void reg_process_self_managed_hints(void)
ASSERT_RTNL();
for_each_rdev(rdev) {
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
reg_process_self_managed_hint(&rdev->wiphy);
- wiphy_unlock(&rdev->wiphy);
}
reg_check_channels();
@@ -3600,14 +3598,12 @@ static bool is_wiphy_all_set_reg_flag(enum ieee80211_regulatory_flags flag)
struct wireless_dev *wdev;
for_each_rdev(rdev) {
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
- if (!(wdev->wiphy->regulatory_flags & flag)) {
- wiphy_unlock(&rdev->wiphy);
+ if (!(wdev->wiphy->regulatory_flags & flag))
return false;
- }
}
- wiphy_unlock(&rdev->wiphy);
}
return true;
@@ -3883,19 +3879,18 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd,
if (!driver_request->intersect) {
ASSERT_RTNL();
- wiphy_lock(request_wiphy);
- if (request_wiphy->regd)
- tmp = get_wiphy_regdom(request_wiphy);
-
- regd = reg_copy_regd(rd);
- if (IS_ERR(regd)) {
- wiphy_unlock(request_wiphy);
- return PTR_ERR(regd);
+ scoped_guard(wiphy, request_wiphy) {
+ if (request_wiphy->regd)
+ tmp = get_wiphy_regdom(request_wiphy);
+
+ regd = reg_copy_regd(rd);
+ if (IS_ERR(regd))
+ return PTR_ERR(regd);
+
+ rcu_assign_pointer(request_wiphy->regd, regd);
+ rcu_free_regdom(tmp);
}
- rcu_assign_pointer(request_wiphy->regd, regd);
- rcu_free_regdom(tmp);
- wiphy_unlock(request_wiphy);
reset_regdomains(false, rd);
return 0;
}
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 1c6fd45aa809..d056248c43d2 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -1238,7 +1238,8 @@ void cfg80211_sched_scan_results_wk(struct work_struct *work)
rdev = container_of(work, struct cfg80211_registered_device,
sched_scan_res_wk);
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry_safe(req, tmp, &rdev->sched_scan_req_list, list) {
if (req->report_results) {
req->report_results = false;
@@ -1253,7 +1254,6 @@ void cfg80211_sched_scan_results_wk(struct work_struct *work)
NL80211_CMD_SCHED_SCAN_RESULTS);
}
}
- wiphy_unlock(&rdev->wiphy);
}
void cfg80211_sched_scan_results(struct wiphy *wiphy, u64 reqid)
@@ -1288,9 +1288,9 @@ EXPORT_SYMBOL(cfg80211_sched_scan_stopped_locked);
void cfg80211_sched_scan_stopped(struct wiphy *wiphy, u64 reqid)
{
- wiphy_lock(wiphy);
+ guard(wiphy)(wiphy);
+
cfg80211_sched_scan_stopped_locked(wiphy, reqid);
- wiphy_unlock(wiphy);
}
EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
@@ -3565,10 +3565,8 @@ int cfg80211_wext_siwscan(struct net_device *dev,
/* translate "Scan for SSID" request */
if (wreq) {
if (wrqu->data.flags & IW_SCAN_THIS_ESSID) {
- if (wreq->essid_len > IEEE80211_MAX_SSID_LEN) {
- err = -EINVAL;
- goto out;
- }
+ if (wreq->essid_len > IEEE80211_MAX_SSID_LEN)
+ return -EINVAL;
memcpy(creq->ssids[0].ssid, wreq->essid, wreq->essid_len);
creq->ssids[0].ssid_len = wreq->essid_len;
}
@@ -3584,20 +3582,20 @@ int cfg80211_wext_siwscan(struct net_device *dev,
eth_broadcast_addr(creq->bssid);
- wiphy_lock(&rdev->wiphy);
-
- rdev->scan_req = creq;
- err = rdev_scan(rdev, creq);
- if (err) {
- rdev->scan_req = NULL;
- /* creq will be freed below */
- } else {
- nl80211_send_scan_start(rdev, dev->ieee80211_ptr);
- /* creq now owned by driver */
- creq = NULL;
- dev_hold(dev);
+ scoped_guard(wiphy, &rdev->wiphy) {
+ rdev->scan_req = creq;
+ err = rdev_scan(rdev, creq);
+ if (err) {
+ rdev->scan_req = NULL;
+ /* creq will be freed below */
+ } else {
+ nl80211_send_scan_start(rdev, dev->ieee80211_ptr);
+ /* creq now owned by driver */
+ creq = NULL;
+ dev_hold(dev);
+ }
}
- wiphy_unlock(&rdev->wiphy);
+
out:
kfree(creq);
return err;
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 431da30817a6..cf998500a965 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -83,6 +83,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev)
if (!request)
return -ENOMEM;
+ request->n_channels = n_channels;
if (wdev->conn->params.channel) {
enum nl80211_band band = wdev->conn->params.channel->band;
struct ieee80211_supported_band *sband =
@@ -251,7 +252,7 @@ void cfg80211_conn_work(struct work_struct *work)
u8 bssid_buf[ETH_ALEN], *bssid = NULL;
enum nl80211_timeout_reason treason;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (!wdev->netdev)
@@ -279,8 +280,6 @@ void cfg80211_conn_work(struct work_struct *work)
__cfg80211_connect_result(wdev->netdev, &cr, false);
}
}
-
- wiphy_unlock(&rdev->wiphy);
}
static void cfg80211_step_auth_next(struct cfg80211_conn *conn,
@@ -692,13 +691,13 @@ static bool cfg80211_is_all_idle(void)
* as chan dfs state, etc.
*/
for_each_rdev(rdev) {
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
list_for_each_entry(wdev, &rdev->wiphy.wdev_list, list) {
if (wdev->conn || wdev->connected ||
cfg80211_beaconing_iface_active(wdev))
is_all_idle = false;
}
- wiphy_unlock(&rdev->wiphy);
}
return is_all_idle;
@@ -1582,7 +1581,7 @@ void cfg80211_autodisconnect_wk(struct work_struct *work)
container_of(work, struct wireless_dev, disconnect_wk);
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- wiphy_lock(wdev->wiphy);
+ guard(wiphy)(wdev->wiphy);
if (wdev->conn_owner_nlportid) {
switch (wdev->iftype) {
@@ -1618,6 +1617,4 @@ void cfg80211_autodisconnect_wk(struct work_struct *work)
break;
}
}
-
- wiphy_unlock(wdev->wiphy);
}
diff --git a/net/wireless/tests/chan.c b/net/wireless/tests/chan.c
index 74bbee25085f..7b97b731993c 100644
--- a/net/wireless/tests/chan.c
+++ b/net/wireless/tests/chan.c
@@ -7,7 +7,7 @@
#include <net/cfg80211.h>
#include <kunit/test.h>
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
static struct ieee80211_channel chan_6ghz_1 = {
.band = NL80211_BAND_6GHZ,
diff --git a/net/wireless/tests/scan.c b/net/wireless/tests/scan.c
index 9f458be71659..b1a9c1466d6c 100644
--- a/net/wireless/tests/scan.c
+++ b/net/wireless/tests/scan.c
@@ -14,7 +14,7 @@
/* mac80211 helpers for element building */
#include "../../mac80211/ieee80211_i.h"
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
struct test_elem {
u8 id;
@@ -810,6 +810,8 @@ static void test_cfg80211_parse_colocated_ap(struct kunit *test)
skb_put_data(input, "123", 3);
ies = kunit_kzalloc(test, struct_size(ies, data, input->len), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_NULL(test, ies);
+
ies->len = input->len;
memcpy(ies->data, input->data, input->len);
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index d5c9bb614fa6..a57210c8087c 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -1690,9 +1690,28 @@ TRACE_EVENT(rdev_set_wiphy_params,
WIPHY_PR_ARG, __entry->changed)
);
-DEFINE_EVENT(wiphy_wdev_evt, rdev_get_tx_power,
- TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev),
- TP_ARGS(wiphy, wdev)
+DECLARE_EVENT_CLASS(wiphy_wdev_link_evt,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ unsigned int link_id),
+ TP_ARGS(wiphy, wdev, link_id),
+ TP_STRUCT__entry(
+ WIPHY_ENTRY
+ WDEV_ENTRY
+ __field(unsigned int, link_id)
+ ),
+ TP_fast_assign(
+ WIPHY_ASSIGN;
+ WDEV_ASSIGN;
+ __entry->link_id = link_id;
+ ),
+ TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", link_id: %u",
+ WIPHY_PR_ARG, WDEV_PR_ARG, __entry->link_id)
+);
+
+DEFINE_EVENT(wiphy_wdev_link_evt, rdev_get_tx_power,
+ TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
+ unsigned int link_id),
+ TP_ARGS(wiphy, wdev, link_id)
);
TRACE_EVENT(rdev_set_tx_power,
@@ -2192,25 +2211,6 @@ TRACE_EVENT(rdev_set_noack_map,
TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", noack_map: %u",
WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map)
);
-
-DECLARE_EVENT_CLASS(wiphy_wdev_link_evt,
- TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
- unsigned int link_id),
- TP_ARGS(wiphy, wdev, link_id),
- TP_STRUCT__entry(
- WIPHY_ENTRY
- WDEV_ENTRY
- __field(unsigned int, link_id)
- ),
- TP_fast_assign(
- WIPHY_ASSIGN;
- WDEV_ASSIGN;
- __entry->link_id = link_id;
- ),
- TP_printk(WIPHY_PR_FMT ", " WDEV_PR_FMT ", link_id: %u",
- WIPHY_PR_ARG, WDEV_PR_ARG, __entry->link_id)
-);
-
DEFINE_EVENT(wiphy_wdev_link_evt, rdev_get_channel,
TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev,
unsigned int link_id),
diff --git a/net/wireless/util.c b/net/wireless/util.c
index 040d62051eb9..60157943d351 100644
--- a/net/wireless/util.c
+++ b/net/wireless/util.c
@@ -2572,7 +2572,6 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
{
struct cfg80211_registered_device *rdev;
struct wireless_dev *wdev;
- int ret;
wdev = dev->ieee80211_ptr;
if (!wdev)
@@ -2584,11 +2583,9 @@ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
memset(sinfo, 0, sizeof(*sinfo));
- wiphy_lock(&rdev->wiphy);
- ret = rdev_get_station(rdev, dev, mac_addr, sinfo);
- wiphy_unlock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
- return ret;
+ return rdev_get_station(rdev, dev, mac_addr, sinfo);
}
EXPORT_SYMBOL(cfg80211_get_station);
@@ -2843,10 +2840,9 @@ void cfg80211_remove_link(struct wireless_dev *wdev, unsigned int link_id)
break;
}
- wdev->valid_links &= ~BIT(link_id);
-
rdev_del_intf_link(rdev, wdev, link_id);
+ wdev->valid_links &= ~BIT(link_id);
eth_zero_addr(wdev->links[link_id].addr);
}
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 90d5c0592667..a74b1afc594e 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -39,7 +39,6 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
struct cfg80211_registered_device *rdev;
struct vif_params vifparams;
enum nl80211_iftype type;
- int ret;
rdev = wiphy_to_rdev(wdev->wiphy);
@@ -62,11 +61,9 @@ int cfg80211_wext_siwmode(struct net_device *dev, struct iw_request_info *info,
memset(&vifparams, 0, sizeof(vifparams));
- wiphy_lock(wdev->wiphy);
- ret = cfg80211_change_iface(rdev, dev, type, &vifparams);
- wiphy_unlock(wdev->wiphy);
+ guard(wiphy)(wdev->wiphy);
- return ret;
+ return cfg80211_change_iface(rdev, dev, type, &vifparams);
}
int cfg80211_wext_giwmode(struct net_device *dev, struct iw_request_info *info,
@@ -258,23 +255,17 @@ int cfg80211_wext_siwrts(struct net_device *dev,
u32 orts = wdev->wiphy->rts_threshold;
int err;
- wiphy_lock(&rdev->wiphy);
- if (rts->disabled || !rts->fixed) {
+ guard(wiphy)(&rdev->wiphy);
+ if (rts->disabled || !rts->fixed)
wdev->wiphy->rts_threshold = (u32) -1;
- } else if (rts->value < 0) {
- err = -EINVAL;
- goto out;
- } else {
+ else if (rts->value < 0)
+ return -EINVAL;
+ else
wdev->wiphy->rts_threshold = rts->value;
- }
err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_RTS_THRESHOLD);
-
if (err)
wdev->wiphy->rts_threshold = orts;
-
-out:
- wiphy_unlock(&rdev->wiphy);
return err;
}
@@ -302,12 +293,12 @@ int cfg80211_wext_siwfrag(struct net_device *dev,
u32 ofrag = wdev->wiphy->frag_threshold;
int err;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
if (frag->disabled || !frag->fixed) {
wdev->wiphy->frag_threshold = (u32) -1;
} else if (frag->value < 256) {
- err = -EINVAL;
- goto out;
+ return -EINVAL;
} else {
/* Fragment length must be even, so strip LSB. */
wdev->wiphy->frag_threshold = frag->value & ~0x1;
@@ -316,9 +307,6 @@ int cfg80211_wext_siwfrag(struct net_device *dev,
err = rdev_set_wiphy_params(rdev, WIPHY_PARAM_FRAG_THRESHOLD);
if (err)
wdev->wiphy->frag_threshold = ofrag;
-out:
- wiphy_unlock(&rdev->wiphy);
-
return err;
}
@@ -352,7 +340,8 @@ static int cfg80211_wext_siwretry(struct net_device *dev,
(retry->flags & IW_RETRY_TYPE) != IW_RETRY_LIMIT)
return -EINVAL;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
if (retry->flags & IW_RETRY_LONG) {
wdev->wiphy->retry_long = retry->value;
changed |= WIPHY_PARAM_RETRY_LONG;
@@ -371,7 +360,6 @@ static int cfg80211_wext_siwretry(struct net_device *dev,
wdev->wiphy->retry_short = oshort;
wdev->wiphy->retry_long = olong;
}
- wiphy_unlock(&rdev->wiphy);
return err;
}
@@ -578,9 +566,9 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
struct iw_point *erq = &wrqu->encoding;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- int idx, err;
- bool remove = false;
struct key_params params;
+ bool remove = false;
+ int idx;
if (wdev->iftype != NL80211_IFTYPE_STATION &&
wdev->iftype != NL80211_IFTYPE_ADHOC)
@@ -592,11 +580,9 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
!rdev->ops->set_default_key)
return -EOPNOTSUPP;
- wiphy_lock(&rdev->wiphy);
- if (wdev->valid_links) {
- err = -EOPNOTSUPP;
- goto out;
- }
+ guard(wiphy)(&rdev->wiphy);
+ if (wdev->valid_links)
+ return -EOPNOTSUPP;
idx = erq->flags & IW_ENCODE_INDEX;
if (idx == 0) {
@@ -604,8 +590,7 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
if (idx < 0)
idx = 0;
} else if (idx < 1 || idx > 4) {
- err = -EINVAL;
- goto out;
+ return -EINVAL;
} else {
idx--;
}
@@ -614,7 +599,8 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
remove = true;
else if (erq->length == 0) {
/* No key data - just set the default TX key index */
- err = 0;
+ int err = 0;
+
if (wdev->connected ||
(wdev->iftype == NL80211_IFTYPE_ADHOC &&
wdev->u.ibss.current_bss))
@@ -622,28 +608,22 @@ static int cfg80211_wext_siwencode(struct net_device *dev,
true);
if (!err)
wdev->wext.default_key = idx;
- goto out;
+ return err;
}
memset(&params, 0, sizeof(params));
params.key = keybuf;
params.key_len = erq->length;
- if (erq->length == 5) {
+ if (erq->length == 5)
params.cipher = WLAN_CIPHER_SUITE_WEP40;
- } else if (erq->length == 13) {
+ else if (erq->length == 13)
params.cipher = WLAN_CIPHER_SUITE_WEP104;
- } else if (!remove) {
- err = -EINVAL;
- goto out;
- }
-
- err = cfg80211_set_encryption(rdev, dev, false, NULL, remove,
- wdev->wext.default_key == -1,
- idx, &params);
-out:
- wiphy_unlock(&rdev->wiphy);
+ else if (!remove)
+ return -EINVAL;
- return err;
+ return cfg80211_set_encryption(rdev, dev, false, NULL, remove,
+ wdev->wext.default_key == -1,
+ idx, &params);
}
static int cfg80211_wext_siwencodeext(struct net_device *dev,
@@ -659,7 +639,6 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev,
bool remove = false;
struct key_params params;
u32 cipher;
- int ret;
if (wdev->iftype != NL80211_IFTYPE_STATION &&
wdev->iftype != NL80211_IFTYPE_ADHOC)
@@ -734,16 +713,13 @@ static int cfg80211_wext_siwencodeext(struct net_device *dev,
params.seq_len = 6;
}
- wiphy_lock(wdev->wiphy);
- ret = cfg80211_set_encryption(
- rdev, dev,
- !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
- addr, remove,
- ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
- idx, &params);
- wiphy_unlock(wdev->wiphy);
+ guard(wiphy)(wdev->wiphy);
- return ret;
+ return cfg80211_set_encryption(rdev, dev,
+ !(ext->ext_flags & IW_ENCODE_EXT_GROUP_KEY),
+ addr, remove,
+ ext->ext_flags & IW_ENCODE_EXT_SET_TX_KEY,
+ idx, &params);
}
static int cfg80211_wext_giwencode(struct net_device *dev,
@@ -794,61 +770,41 @@ static int cfg80211_wext_siwfreq(struct net_device *dev,
struct cfg80211_chan_def chandef = {
.width = NL80211_CHAN_WIDTH_20_NOHT,
};
- int freq, ret;
+ int freq;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
- break;
+ return cfg80211_mgd_wext_siwfreq(dev, info, wextfreq, extra);
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
- break;
+ return cfg80211_ibss_wext_siwfreq(dev, info, wextfreq, extra);
case NL80211_IFTYPE_MONITOR:
freq = cfg80211_wext_freq(wextfreq);
- if (freq < 0) {
- ret = freq;
- break;
- }
- if (freq == 0) {
- ret = -EINVAL;
- break;
- }
+ if (freq < 0)
+ return freq;
+ if (freq == 0)
+ return -EINVAL;
+
chandef.center_freq1 = freq;
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
- if (!chandef.chan) {
- ret = -EINVAL;
- break;
- }
- ret = cfg80211_set_monitor_channel(rdev, dev, &chandef);
- break;
+ if (!chandef.chan)
+ return -EINVAL;
+ return cfg80211_set_monitor_channel(rdev, dev, &chandef);
case NL80211_IFTYPE_MESH_POINT:
freq = cfg80211_wext_freq(wextfreq);
- if (freq < 0) {
- ret = freq;
- break;
- }
- if (freq == 0) {
- ret = -EINVAL;
- break;
- }
+ if (freq < 0)
+ return freq;
+ if (freq == 0)
+ return -EINVAL;
chandef.center_freq1 = freq;
chandef.chan = ieee80211_get_channel(&rdev->wiphy, freq);
- if (!chandef.chan) {
- ret = -EINVAL;
- break;
- }
- ret = cfg80211_set_mesh_channel(rdev, wdev, &chandef);
- break;
+ if (!chandef.chan)
+ return -EINVAL;
+ return cfg80211_set_mesh_channel(rdev, wdev, &chandef);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
-
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_giwfreq(struct net_device *dev,
@@ -861,35 +817,26 @@ static int cfg80211_wext_giwfreq(struct net_device *dev,
struct cfg80211_chan_def chandef = {};
int ret;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
- break;
+ return cfg80211_mgd_wext_giwfreq(dev, info, freq, extra);
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
- break;
+ return cfg80211_ibss_wext_giwfreq(dev, info, freq, extra);
case NL80211_IFTYPE_MONITOR:
- if (!rdev->ops->get_channel) {
- ret = -EINVAL;
- break;
- }
+ if (!rdev->ops->get_channel)
+ return -EINVAL;
ret = rdev_get_channel(rdev, wdev, 0, &chandef);
if (ret)
- break;
+ return ret;
freq->m = chandef.chan->center_freq;
freq->e = 6;
- ret = 0;
- break;
+ return ret;
default:
- ret = -EINVAL;
- break;
+ return -EINVAL;
}
-
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_siwtxpower(struct net_device *dev,
@@ -900,7 +847,6 @@ static int cfg80211_wext_siwtxpower(struct net_device *dev,
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
enum nl80211_tx_power_setting type;
int dbm = 0;
- int ret;
if ((data->txpower.flags & IW_TXPOW_TYPE) != IW_TXPOW_DBM)
return -EINVAL;
@@ -942,11 +888,9 @@ static int cfg80211_wext_siwtxpower(struct net_device *dev,
return 0;
}
- wiphy_lock(&rdev->wiphy);
- ret = rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm));
- wiphy_unlock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
- return ret;
+ return rdev_set_tx_power(rdev, wdev, type, DBM_TO_MBM(dbm));
}
static int cfg80211_wext_giwtxpower(struct net_device *dev,
@@ -965,9 +909,9 @@ static int cfg80211_wext_giwtxpower(struct net_device *dev,
if (!rdev->ops->get_tx_power)
return -EOPNOTSUPP;
- wiphy_lock(&rdev->wiphy);
- err = rdev_get_tx_power(rdev, wdev, &val);
- wiphy_unlock(&rdev->wiphy);
+ scoped_guard(wiphy, &rdev->wiphy) {
+ err = rdev_get_tx_power(rdev, wdev, 0, &val);
+ }
if (err)
return err;
@@ -1209,9 +1153,9 @@ static int cfg80211_wext_siwpower(struct net_device *dev,
timeout = wrq->value / 1000;
}
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
err = rdev_set_power_mgmt(rdev, dev, ps, timeout);
- wiphy_unlock(&rdev->wiphy);
if (err)
return err;
@@ -1244,8 +1188,8 @@ static int cfg80211_wext_siwrate(struct net_device *dev,
struct cfg80211_bitrate_mask mask;
u32 fixed, maxrate;
struct ieee80211_supported_band *sband;
- int band, ridx, ret;
bool match = false;
+ int band, ridx;
if (!rdev->ops->set_bitrate_mask)
return -EOPNOTSUPP;
@@ -1283,14 +1227,12 @@ static int cfg80211_wext_siwrate(struct net_device *dev,
if (!match)
return -EINVAL;
- wiphy_lock(&rdev->wiphy);
- if (dev->ieee80211_ptr->valid_links)
- ret = -EOPNOTSUPP;
- else
- ret = rdev_set_bitrate_mask(rdev, dev, 0, NULL, &mask);
- wiphy_unlock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
- return ret;
+ if (dev->ieee80211_ptr->valid_links)
+ return -EOPNOTSUPP;
+
+ return rdev_set_bitrate_mask(rdev, dev, 0, NULL, &mask);
}
static int cfg80211_wext_giwrate(struct net_device *dev,
@@ -1319,9 +1261,9 @@ static int cfg80211_wext_giwrate(struct net_device *dev,
if (err)
return err;
- wiphy_lock(&rdev->wiphy);
- err = rdev_get_station(rdev, dev, addr, &sinfo);
- wiphy_unlock(&rdev->wiphy);
+ scoped_guard(wiphy, &rdev->wiphy) {
+ err = rdev_get_station(rdev, dev, addr, &sinfo);
+ }
if (err)
return err;
@@ -1420,23 +1362,17 @@ static int cfg80211_wext_siwap(struct net_device *dev,
struct sockaddr *ap_addr = &wrqu->ap_addr;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- int ret;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
- break;
+ return cfg80211_ibss_wext_siwap(dev, info, ap_addr, extra);
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
- break;
+ return cfg80211_mgd_wext_siwap(dev, info, ap_addr, extra);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_giwap(struct net_device *dev,
@@ -1446,23 +1382,17 @@ static int cfg80211_wext_giwap(struct net_device *dev,
struct sockaddr *ap_addr = &wrqu->ap_addr;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- int ret;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
- break;
+ return cfg80211_ibss_wext_giwap(dev, info, ap_addr, extra);
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
- break;
+ return cfg80211_mgd_wext_giwap(dev, info, ap_addr, extra);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_siwessid(struct net_device *dev,
@@ -1472,23 +1402,17 @@ static int cfg80211_wext_siwessid(struct net_device *dev,
struct iw_point *data = &wrqu->data;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- int ret;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
- break;
+ return cfg80211_ibss_wext_siwessid(dev, info, data, ssid);
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
- break;
+ return cfg80211_mgd_wext_siwessid(dev, info, data, ssid);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_giwessid(struct net_device *dev,
@@ -1498,26 +1422,20 @@ static int cfg80211_wext_giwessid(struct net_device *dev,
struct iw_point *data = &wrqu->data;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
- int ret;
data->flags = 0;
data->length = 0;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (wdev->iftype) {
case NL80211_IFTYPE_ADHOC:
- ret = cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
- break;
+ return cfg80211_ibss_wext_giwessid(dev, info, data, ssid);
case NL80211_IFTYPE_STATION:
- ret = cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
- break;
+ return cfg80211_mgd_wext_giwessid(dev, info, data, ssid);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static int cfg80211_wext_siwpmksa(struct net_device *dev,
@@ -1528,7 +1446,6 @@ static int cfg80211_wext_siwpmksa(struct net_device *dev,
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
struct cfg80211_pmksa cfg_pmksa;
struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
- int ret;
memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa));
@@ -1538,39 +1455,27 @@ static int cfg80211_wext_siwpmksa(struct net_device *dev,
cfg_pmksa.bssid = pmksa->bssid.sa_data;
cfg_pmksa.pmkid = pmksa->pmkid;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (pmksa->cmd) {
case IW_PMKSA_ADD:
- if (!rdev->ops->set_pmksa) {
- ret = -EOPNOTSUPP;
- break;
- }
+ if (!rdev->ops->set_pmksa)
+ return -EOPNOTSUPP;
- ret = rdev_set_pmksa(rdev, dev, &cfg_pmksa);
- break;
+ return rdev_set_pmksa(rdev, dev, &cfg_pmksa);
case IW_PMKSA_REMOVE:
- if (!rdev->ops->del_pmksa) {
- ret = -EOPNOTSUPP;
- break;
- }
+ if (!rdev->ops->del_pmksa)
+ return -EOPNOTSUPP;
- ret = rdev_del_pmksa(rdev, dev, &cfg_pmksa);
- break;
+ return rdev_del_pmksa(rdev, dev, &cfg_pmksa);
case IW_PMKSA_FLUSH:
- if (!rdev->ops->flush_pmksa) {
- ret = -EOPNOTSUPP;
- break;
- }
+ if (!rdev->ops->flush_pmksa)
+ return -EOPNOTSUPP;
- ret = rdev_flush_pmksa(rdev, dev);
- break;
+ return rdev_flush_pmksa(rdev, dev);
default:
- ret = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return ret;
}
static const iw_handler cfg80211_handlers[] = {
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c
index 8edd9ada69d0..573b6b15a446 100644
--- a/net/wireless/wext-sme.c
+++ b/net/wireless/wext-sme.c
@@ -302,8 +302,8 @@ int cfg80211_wext_siwgenie(struct net_device *dev,
struct iw_point *data = &wrqu->data;
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+ int ie_len = data->length;
u8 *ie = extra;
- int ie_len = data->length, err;
if (wdev->iftype != NL80211_IFTYPE_STATION)
return -EOPNOTSUPP;
@@ -311,39 +311,31 @@ int cfg80211_wext_siwgenie(struct net_device *dev,
if (!ie_len)
ie = NULL;
- wiphy_lock(wdev->wiphy);
+ guard(wiphy)(wdev->wiphy);
/* no change */
- err = 0;
if (wdev->wext.ie_len == ie_len &&
memcmp(wdev->wext.ie, ie, ie_len) == 0)
- goto out;
+ return 0;
if (ie_len) {
ie = kmemdup(extra, ie_len, GFP_KERNEL);
- if (!ie) {
- err = -ENOMEM;
- goto out;
- }
- } else
+ if (!ie)
+ return -ENOMEM;
+ } else {
ie = NULL;
+ }
kfree(wdev->wext.ie);
wdev->wext.ie = ie;
wdev->wext.ie_len = ie_len;
- if (wdev->conn) {
- err = cfg80211_disconnect(rdev, dev,
- WLAN_REASON_DEAUTH_LEAVING, false);
- if (err)
- goto out;
- }
+ if (wdev->conn)
+ return cfg80211_disconnect(rdev, dev,
+ WLAN_REASON_DEAUTH_LEAVING, false);
/* userspace better not think we'll reconnect */
- err = 0;
- out:
- wiphy_unlock(wdev->wiphy);
- return err;
+ return 0;
}
int cfg80211_wext_siwmlme(struct net_device *dev,
@@ -353,7 +345,6 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
struct wireless_dev *wdev = dev->ieee80211_ptr;
struct iw_mlme *mlme = (struct iw_mlme *)extra;
struct cfg80211_registered_device *rdev;
- int err;
if (!wdev)
return -EOPNOTSUPP;
@@ -366,17 +357,13 @@ int cfg80211_wext_siwmlme(struct net_device *dev,
if (mlme->addr.sa_family != ARPHRD_ETHER)
return -EINVAL;
- wiphy_lock(&rdev->wiphy);
+ guard(wiphy)(&rdev->wiphy);
+
switch (mlme->cmd) {
case IW_MLME_DEAUTH:
case IW_MLME_DISASSOC:
- err = cfg80211_disconnect(rdev, dev, mlme->reason_code, true);
- break;
+ return cfg80211_disconnect(rdev, dev, mlme->reason_code, true);
default:
- err = -EOPNOTSUPP;
- break;
+ return -EOPNOTSUPP;
}
- wiphy_unlock(&rdev->wiphy);
-
- return err;
}
diff --git a/net/xdp/xsk_buff_pool.c b/net/xdp/xsk_buff_pool.c
index ae71da7d2cd6..1f7975b49657 100644
--- a/net/xdp/xsk_buff_pool.c
+++ b/net/xdp/xsk_buff_pool.c
@@ -387,10 +387,9 @@ void xp_dma_unmap(struct xsk_buff_pool *pool, unsigned long attrs)
return;
}
- if (!refcount_dec_and_test(&dma_map->users))
- return;
+ if (refcount_dec_and_test(&dma_map->users))
+ __xp_dma_unmap(dma_map, attrs);
- __xp_dma_unmap(dma_map, attrs);
kvfree(pool->dma_pages);
pool->dma_pages = NULL;
pool->dma_pages_cnt = 0;
diff --git a/net/xdp/xskmap.c b/net/xdp/xskmap.c
index e1c526f97ce3..afa457506274 100644
--- a/net/xdp/xskmap.c
+++ b/net/xdp/xskmap.c
@@ -224,7 +224,7 @@ static long xsk_map_delete_elem(struct bpf_map *map, void *key)
struct xsk_map *m = container_of(map, struct xsk_map, map);
struct xdp_sock __rcu **map_entry;
struct xdp_sock *old_xs;
- int k = *(u32 *)key;
+ u32 k = *(u32 *)key;
if (k >= map->max_entries)
return -EINVAL;
diff --git a/rust/Makefile b/rust/Makefile
index 01cf8e6ba3b3..a40a3936126d 100644
--- a/rust/Makefile
+++ b/rust/Makefile
@@ -280,9 +280,22 @@ endif
# architecture instead of generating `usize`.
bindgen_c_flags_final = $(bindgen_c_flags_lto) -fno-builtin -D__BINDGEN__
+# Each `bindgen` release may upgrade the list of Rust target versions. By
+# default, the highest stable release in their list is used. Thus we need to set
+# a `--rust-target` to avoid future `bindgen` releases emitting code that
+# `rustc` may not understand. On top of that, `bindgen` does not support passing
+# an unknown Rust target version.
+#
+# Therefore, the Rust target for `bindgen` can be only as high as the minimum
+# Rust version the kernel supports and only as high as the greatest stable Rust
+# target supported by the minimum `bindgen` version the kernel supports (that
+# is, if we do not test the actual `rustc`/`bindgen` versions running).
+#
+# Starting with `bindgen` 0.71.0, we will be able to set any future Rust version
+# instead, i.e. we will be able to set here our minimum supported Rust version.
quiet_cmd_bindgen = BINDGEN $@
cmd_bindgen = \
- $(BINDGEN) $< $(bindgen_target_flags) \
+ $(BINDGEN) $< $(bindgen_target_flags) --rust-target 1.68 \
--use-core --with-derive-default --ctypes-prefix ffi --no-layout-tests \
--no-debug '.*' --enable-function-attribute-detection \
-o $@ -- $(bindgen_c_flags_final) -DMODULE \
@@ -372,8 +385,8 @@ rust-analyzer:
$(Q)$(srctree)/scripts/generate_rust_analyzer.py \
--cfgs='core=$(core-cfgs)' \
$(realpath $(srctree)) $(realpath $(objtree)) \
- $(rustc_sysroot) $(RUST_LIB_SRC) $(KBUILD_EXTMOD) > \
- $(if $(KBUILD_EXTMOD),$(extmod_prefix),$(objtree))/rust-project.json
+ $(rustc_sysroot) $(RUST_LIB_SRC) $(if $(KBUILD_EXTMOD),$(srcroot)) \
+ > rust-project.json
redirect-intrinsics = \
__addsf3 __eqsf2 __extendsfdf2 __gesf2 __lesf2 __ltsf2 __mulsf3 __nesf2 __truncdfsf2 __unordsf2 \
diff --git a/rust/bindings/bindings_helper.h b/rust/bindings/bindings_helper.h
index 54bc8a8c5c88..5c4dfe22f41a 100644
--- a/rust/bindings/bindings_helper.h
+++ b/rust/bindings/bindings_helper.h
@@ -19,6 +19,7 @@
#include <linux/jiffies.h>
#include <linux/jump_label.h>
#include <linux/mdio.h>
+#include <linux/miscdevice.h>
#include <linux/phy.h>
#include <linux/pid_namespace.h>
#include <linux/poll.h>
diff --git a/rust/kernel/block/mq/gen_disk.rs b/rust/kernel/block/mq/gen_disk.rs
index 708125dce96a..798c4ae0bded 100644
--- a/rust/kernel/block/mq/gen_disk.rs
+++ b/rust/kernel/block/mq/gen_disk.rs
@@ -45,7 +45,7 @@ impl GenDiskBuilder {
/// Validate block size by verifying that it is between 512 and `PAGE_SIZE`,
/// and that it is a power of two.
- fn validate_block_size(size: u32) -> Result<()> {
+ fn validate_block_size(size: u32) -> Result {
if !(512..=bindings::PAGE_SIZE as u32).contains(&size) || !size.is_power_of_two() {
Err(error::code::EINVAL)
} else {
diff --git a/rust/kernel/device.rs b/rust/kernel/device.rs
index c8199ee079ef..c926e0c2b852 100644
--- a/rust/kernel/device.rs
+++ b/rust/kernel/device.rs
@@ -8,7 +8,10 @@ use crate::{
bindings,
types::{ARef, Opaque},
};
-use core::ptr;
+use core::{fmt, ptr};
+
+#[cfg(CONFIG_PRINTK)]
+use crate::c_str;
/// A reference-counted device.
///
@@ -73,6 +76,110 @@ impl Device {
// SAFETY: Guaranteed by the safety requirements of the function.
unsafe { &*ptr.cast() }
}
+
+ /// Prints an emergency-level message (level 0) prefixed with device information.
+ ///
+ /// More details are available from [`dev_emerg`].
+ ///
+ /// [`dev_emerg`]: crate::dev_emerg
+ pub fn pr_emerg(&self, args: fmt::Arguments<'_>) {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { self.printk(bindings::KERN_EMERG, args) };
+ }
+
+ /// Prints an alert-level message (level 1) prefixed with device information.
+ ///
+ /// More details are available from [`dev_alert`].
+ ///
+ /// [`dev_alert`]: crate::dev_alert
+ pub fn pr_alert(&self, args: fmt::Arguments<'_>) {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { self.printk(bindings::KERN_ALERT, args) };
+ }
+
+ /// Prints a critical-level message (level 2) prefixed with device information.
+ ///
+ /// More details are available from [`dev_crit`].
+ ///
+ /// [`dev_crit`]: crate::dev_crit
+ pub fn pr_crit(&self, args: fmt::Arguments<'_>) {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { self.printk(bindings::KERN_CRIT, args) };
+ }
+
+ /// Prints an error-level message (level 3) prefixed with device information.
+ ///
+ /// More details are available from [`dev_err`].
+ ///
+ /// [`dev_err`]: crate::dev_err
+ pub fn pr_err(&self, args: fmt::Arguments<'_>) {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { self.printk(bindings::KERN_ERR, args) };
+ }
+
+ /// Prints a warning-level message (level 4) prefixed with device information.
+ ///
+ /// More details are available from [`dev_warn`].
+ ///
+ /// [`dev_warn`]: crate::dev_warn
+ pub fn pr_warn(&self, args: fmt::Arguments<'_>) {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { self.printk(bindings::KERN_WARNING, args) };
+ }
+
+ /// Prints a notice-level message (level 5) prefixed with device information.
+ ///
+ /// More details are available from [`dev_notice`].
+ ///
+ /// [`dev_notice`]: crate::dev_notice
+ pub fn pr_notice(&self, args: fmt::Arguments<'_>) {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { self.printk(bindings::KERN_NOTICE, args) };
+ }
+
+ /// Prints an info-level message (level 6) prefixed with device information.
+ ///
+ /// More details are available from [`dev_info`].
+ ///
+ /// [`dev_info`]: crate::dev_info
+ pub fn pr_info(&self, args: fmt::Arguments<'_>) {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { self.printk(bindings::KERN_INFO, args) };
+ }
+
+ /// Prints a debug-level message (level 7) prefixed with device information.
+ ///
+ /// More details are available from [`dev_dbg`].
+ ///
+ /// [`dev_dbg`]: crate::dev_dbg
+ pub fn pr_dbg(&self, args: fmt::Arguments<'_>) {
+ if cfg!(debug_assertions) {
+ // SAFETY: `klevel` is null-terminated, uses one of the kernel constants.
+ unsafe { self.printk(bindings::KERN_DEBUG, args) };
+ }
+ }
+
+ /// Prints the provided message to the console.
+ ///
+ /// # Safety
+ ///
+ /// Callers must ensure that `klevel` is null-terminated; in particular, one of the
+ /// `KERN_*`constants, for example, `KERN_CRIT`, `KERN_ALERT`, etc.
+ #[cfg_attr(not(CONFIG_PRINTK), allow(unused_variables))]
+ unsafe fn printk(&self, klevel: &[u8], msg: fmt::Arguments<'_>) {
+ // SAFETY: `klevel` is null-terminated and one of the kernel constants. `self.as_raw`
+ // is valid because `self` is valid. The "%pA" format string expects a pointer to
+ // `fmt::Arguments`, which is what we're passing as the last argument.
+ #[cfg(CONFIG_PRINTK)]
+ unsafe {
+ bindings::_dev_printk(
+ klevel as *const _ as *const core::ffi::c_char,
+ self.as_raw(),
+ c_str!("%pA").as_char_ptr(),
+ &msg as *const _ as *const core::ffi::c_void,
+ )
+ };
+ }
}
// SAFETY: Instances of `Device` are always reference-counted.
@@ -94,3 +201,213 @@ unsafe impl Send for Device {}
// SAFETY: `Device` can be shared among threads because all immutable methods are protected by the
// synchronization in `struct device`.
unsafe impl Sync for Device {}
+
+#[doc(hidden)]
+#[macro_export]
+macro_rules! dev_printk {
+ ($method:ident, $dev:expr, $($f:tt)*) => {
+ {
+ ($dev).$method(core::format_args!($($f)*));
+ }
+ }
+}
+
+/// Prints an emergency-level message (level 0) prefixed with device information.
+///
+/// This level should be used if the system is unusable.
+///
+/// Equivalent to the kernel's `dev_emerg` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and `alloc::format!`.
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+/// dev_emerg!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_emerg {
+ ($($f:tt)*) => { $crate::dev_printk!(pr_emerg, $($f)*); }
+}
+
+/// Prints an alert-level message (level 1) prefixed with device information.
+///
+/// This level should be used if action must be taken immediately.
+///
+/// Equivalent to the kernel's `dev_alert` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and `alloc::format!`.
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+/// dev_alert!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_alert {
+ ($($f:tt)*) => { $crate::dev_printk!(pr_alert, $($f)*); }
+}
+
+/// Prints a critical-level message (level 2) prefixed with device information.
+///
+/// This level should be used in critical conditions.
+///
+/// Equivalent to the kernel's `dev_crit` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and `alloc::format!`.
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+/// dev_crit!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_crit {
+ ($($f:tt)*) => { $crate::dev_printk!(pr_crit, $($f)*); }
+}
+
+/// Prints an error-level message (level 3) prefixed with device information.
+///
+/// This level should be used in error conditions.
+///
+/// Equivalent to the kernel's `dev_err` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and `alloc::format!`.
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+/// dev_err!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_err {
+ ($($f:tt)*) => { $crate::dev_printk!(pr_err, $($f)*); }
+}
+
+/// Prints a warning-level message (level 4) prefixed with device information.
+///
+/// This level should be used in warning conditions.
+///
+/// Equivalent to the kernel's `dev_warn` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and `alloc::format!`.
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+/// dev_warn!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_warn {
+ ($($f:tt)*) => { $crate::dev_printk!(pr_warn, $($f)*); }
+}
+
+/// Prints a notice-level message (level 5) prefixed with device information.
+///
+/// This level should be used in normal but significant conditions.
+///
+/// Equivalent to the kernel's `dev_notice` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and `alloc::format!`.
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+/// dev_notice!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_notice {
+ ($($f:tt)*) => { $crate::dev_printk!(pr_notice, $($f)*); }
+}
+
+/// Prints an info-level message (level 6) prefixed with device information.
+///
+/// This level should be used for informational messages.
+///
+/// Equivalent to the kernel's `dev_info` macro.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and `alloc::format!`.
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+/// dev_info!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_info {
+ ($($f:tt)*) => { $crate::dev_printk!(pr_info, $($f)*); }
+}
+
+/// Prints a debug-level message (level 7) prefixed with device information.
+///
+/// This level should be used for debug messages.
+///
+/// Equivalent to the kernel's `dev_dbg` macro, except that it doesn't support dynamic debug yet.
+///
+/// Mimics the interface of [`std::print!`]. More information about the syntax is available from
+/// [`core::fmt`] and `alloc::format!`.
+///
+/// [`std::print!`]: https://doc.rust-lang.org/std/macro.print.html
+///
+/// # Examples
+///
+/// ```
+/// # use kernel::device::Device;
+///
+/// fn example(dev: &Device) {
+/// dev_dbg!(dev, "hello {}\n", "there");
+/// }
+/// ```
+#[macro_export]
+macro_rules! dev_dbg {
+ ($($f:tt)*) => { $crate::dev_printk!(pr_dbg, $($f)*); }
+}
diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index 04dbee70d3e6..e1065a7551a3 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -45,6 +45,7 @@ pub mod jump_label;
#[cfg(CONFIG_KUNIT)]
pub mod kunit;
pub mod list;
+pub mod miscdevice;
#[cfg(CONFIG_NET)]
pub mod net;
pub mod page;
@@ -92,6 +93,29 @@ pub trait Module: Sized + Sync + Send {
fn init(module: &'static ThisModule) -> error::Result<Self>;
}
+/// A module that is pinned and initialised in-place.
+pub trait InPlaceModule: Sync + Send {
+ /// Creates an initialiser for the module.
+ ///
+ /// It is called when the module is loaded.
+ fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error>;
+}
+
+impl<T: Module> InPlaceModule for T {
+ fn init(module: &'static ThisModule) -> impl init::PinInit<Self, error::Error> {
+ let initer = move |slot: *mut Self| {
+ let m = <Self as Module>::init(module)?;
+
+ // SAFETY: `slot` is valid for write per the contract with `pin_init_from_closure`.
+ unsafe { slot.write(m) };
+ Ok(())
+ };
+
+ // SAFETY: On success, `initer` always fully initialises an instance of `Self`.
+ unsafe { init::pin_init_from_closure(initer) }
+ }
+}
+
/// Equivalent to `THIS_MODULE` in the C API.
///
/// C header: [`include/linux/init.h`](srctree/include/linux/init.h)
diff --git a/rust/kernel/miscdevice.rs b/rust/kernel/miscdevice.rs
new file mode 100644
index 000000000000..7e2a79b3ae26
--- /dev/null
+++ b/rust/kernel/miscdevice.rs
@@ -0,0 +1,256 @@
+// SPDX-License-Identifier: GPL-2.0
+
+// Copyright (C) 2024 Google LLC.
+
+//! Miscdevice support.
+//!
+//! C headers: [`include/linux/miscdevice.h`](srctree/include/linux/miscdevice.h).
+//!
+//! Reference: <https://www.kernel.org/doc/html/latest/driver-api/misc_devices.html>
+
+use crate::{
+ bindings,
+ error::{to_result, Error, Result, VTABLE_DEFAULT_ERROR},
+ prelude::*,
+ str::CStr,
+ types::{ForeignOwnable, Opaque},
+};
+use core::{
+ ffi::{c_int, c_long, c_uint, c_ulong},
+ marker::PhantomData,
+ mem::MaybeUninit,
+ pin::Pin,
+};
+
+/// Options for creating a misc device.
+#[derive(Copy, Clone)]
+pub struct MiscDeviceOptions {
+ /// The name of the miscdevice.
+ pub name: &'static CStr,
+}
+
+impl MiscDeviceOptions {
+ /// Create a raw `struct miscdev` ready for registration.
+ pub const fn into_raw<T: MiscDevice>(self) -> bindings::miscdevice {
+ // SAFETY: All zeros is valid for this C type.
+ let mut result: bindings::miscdevice = unsafe { MaybeUninit::zeroed().assume_init() };
+ result.minor = bindings::MISC_DYNAMIC_MINOR as _;
+ result.name = self.name.as_char_ptr();
+ result.fops = create_vtable::<T>();
+ result
+ }
+}
+
+/// A registration of a miscdevice.
+///
+/// # Invariants
+///
+/// `inner` is a registered misc device.
+#[repr(transparent)]
+#[pin_data(PinnedDrop)]
+pub struct MiscDeviceRegistration<T> {
+ #[pin]
+ inner: Opaque<bindings::miscdevice>,
+ _t: PhantomData<T>,
+}
+
+// SAFETY: It is allowed to call `misc_deregister` on a different thread from where you called
+// `misc_register`.
+unsafe impl<T> Send for MiscDeviceRegistration<T> {}
+// SAFETY: All `&self` methods on this type are written to ensure that it is safe to call them in
+// parallel.
+unsafe impl<T> Sync for MiscDeviceRegistration<T> {}
+
+impl<T: MiscDevice> MiscDeviceRegistration<T> {
+ /// Register a misc device.
+ pub fn register(opts: MiscDeviceOptions) -> impl PinInit<Self, Error> {
+ try_pin_init!(Self {
+ inner <- Opaque::try_ffi_init(move |slot: *mut bindings::miscdevice| {
+ // SAFETY: The initializer can write to the provided `slot`.
+ unsafe { slot.write(opts.into_raw::<T>()) };
+
+ // SAFETY: We just wrote the misc device options to the slot. The miscdevice will
+ // get unregistered before `slot` is deallocated because the memory is pinned and
+ // the destructor of this type deallocates the memory.
+ // INVARIANT: If this returns `Ok(())`, then the `slot` will contain a registered
+ // misc device.
+ to_result(unsafe { bindings::misc_register(slot) })
+ }),
+ _t: PhantomData,
+ })
+ }
+
+ /// Returns a raw pointer to the misc device.
+ pub fn as_raw(&self) -> *mut bindings::miscdevice {
+ self.inner.get()
+ }
+}
+
+#[pinned_drop]
+impl<T> PinnedDrop for MiscDeviceRegistration<T> {
+ fn drop(self: Pin<&mut Self>) {
+ // SAFETY: We know that the device is registered by the type invariants.
+ unsafe { bindings::misc_deregister(self.inner.get()) };
+ }
+}
+
+/// Trait implemented by the private data of an open misc device.
+#[vtable]
+pub trait MiscDevice {
+ /// What kind of pointer should `Self` be wrapped in.
+ type Ptr: ForeignOwnable + Send + Sync;
+
+ /// Called when the misc device is opened.
+ ///
+ /// The returned pointer will be stored as the private data for the file.
+ fn open() -> Result<Self::Ptr>;
+
+ /// Called when the misc device is released.
+ fn release(device: Self::Ptr) {
+ drop(device);
+ }
+
+ /// Handler for ioctls.
+ ///
+ /// The `cmd` argument is usually manipulated using the utilties in [`kernel::ioctl`].
+ ///
+ /// [`kernel::ioctl`]: mod@crate::ioctl
+ fn ioctl(
+ _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
+ _cmd: u32,
+ _arg: usize,
+ ) -> Result<isize> {
+ kernel::build_error(VTABLE_DEFAULT_ERROR)
+ }
+
+ /// Handler for ioctls.
+ ///
+ /// Used for 32-bit userspace on 64-bit platforms.
+ ///
+ /// This method is optional and only needs to be provided if the ioctl relies on structures
+ /// that have different layout on 32-bit and 64-bit userspace. If no implementation is
+ /// provided, then `compat_ptr_ioctl` will be used instead.
+ #[cfg(CONFIG_COMPAT)]
+ fn compat_ioctl(
+ _device: <Self::Ptr as ForeignOwnable>::Borrowed<'_>,
+ _cmd: u32,
+ _arg: usize,
+ ) -> Result<isize> {
+ kernel::build_error(VTABLE_DEFAULT_ERROR)
+ }
+}
+
+const fn create_vtable<T: MiscDevice>() -> &'static bindings::file_operations {
+ const fn maybe_fn<T: Copy>(check: bool, func: T) -> Option<T> {
+ if check {
+ Some(func)
+ } else {
+ None
+ }
+ }
+
+ struct VtableHelper<T: MiscDevice> {
+ _t: PhantomData<T>,
+ }
+ impl<T: MiscDevice> VtableHelper<T> {
+ const VTABLE: bindings::file_operations = bindings::file_operations {
+ open: Some(fops_open::<T>),
+ release: Some(fops_release::<T>),
+ unlocked_ioctl: maybe_fn(T::HAS_IOCTL, fops_ioctl::<T>),
+ #[cfg(CONFIG_COMPAT)]
+ compat_ioctl: if T::HAS_COMPAT_IOCTL {
+ Some(fops_compat_ioctl::<T>)
+ } else if T::HAS_IOCTL {
+ Some(bindings::compat_ptr_ioctl)
+ } else {
+ None
+ },
+ // SAFETY: All zeros is a valid value for `bindings::file_operations`.
+ ..unsafe { MaybeUninit::zeroed().assume_init() }
+ };
+ }
+
+ &VtableHelper::<T>::VTABLE
+}
+
+/// # Safety
+///
+/// `file` and `inode` must be the file and inode for a file that is undergoing initialization.
+/// The file must be associated with a `MiscDeviceRegistration<T>`.
+unsafe extern "C" fn fops_open<T: MiscDevice>(
+ inode: *mut bindings::inode,
+ file: *mut bindings::file,
+) -> c_int {
+ // SAFETY: The pointers are valid and for a file being opened.
+ let ret = unsafe { bindings::generic_file_open(inode, file) };
+ if ret != 0 {
+ return ret;
+ }
+
+ let ptr = match T::open() {
+ Ok(ptr) => ptr,
+ Err(err) => return err.to_errno(),
+ };
+
+ // SAFETY: The open call of a file owns the private data.
+ unsafe { (*file).private_data = ptr.into_foreign().cast_mut() };
+
+ 0
+}
+
+/// # Safety
+///
+/// `file` and `inode` must be the file and inode for a file that is being released. The file must
+/// be associated with a `MiscDeviceRegistration<T>`.
+unsafe extern "C" fn fops_release<T: MiscDevice>(
+ _inode: *mut bindings::inode,
+ file: *mut bindings::file,
+) -> c_int {
+ // SAFETY: The release call of a file owns the private data.
+ let private = unsafe { (*file).private_data };
+ // SAFETY: The release call of a file owns the private data.
+ let ptr = unsafe { <T::Ptr as ForeignOwnable>::from_foreign(private) };
+
+ T::release(ptr);
+
+ 0
+}
+
+/// # Safety
+///
+/// `file` must be a valid file that is associated with a `MiscDeviceRegistration<T>`.
+unsafe extern "C" fn fops_ioctl<T: MiscDevice>(
+ file: *mut bindings::file,
+ cmd: c_uint,
+ arg: c_ulong,
+) -> c_long {
+ // SAFETY: The ioctl call of a file can access the private data.
+ let private = unsafe { (*file).private_data };
+ // SAFETY: Ioctl calls can borrow the private data of the file.
+ let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
+
+ match T::ioctl(device, cmd, arg as usize) {
+ Ok(ret) => ret as c_long,
+ Err(err) => err.to_errno() as c_long,
+ }
+}
+
+/// # Safety
+///
+/// `file` must be a valid file that is associated with a `MiscDeviceRegistration<T>`.
+#[cfg(CONFIG_COMPAT)]
+unsafe extern "C" fn fops_compat_ioctl<T: MiscDevice>(
+ file: *mut bindings::file,
+ cmd: c_uint,
+ arg: c_ulong,
+) -> c_long {
+ // SAFETY: The compat ioctl call of a file can access the private data.
+ let private = unsafe { (*file).private_data };
+ // SAFETY: Ioctl calls can borrow the private data of the file.
+ let device = unsafe { <T::Ptr as ForeignOwnable>::borrow(private) };
+
+ match T::compat_ioctl(device, cmd, arg as usize) {
+ Ok(ret) => ret as c_long,
+ Err(err) => err.to_errno() as c_long,
+ }
+}
diff --git a/rust/kernel/net/phy.rs b/rust/kernel/net/phy.rs
index b89c681d97c0..eeb49597f4f4 100644
--- a/rust/kernel/net/phy.rs
+++ b/rust/kernel/net/phy.rs
@@ -837,7 +837,7 @@ impl DeviceMask {
/// [::kernel::net::phy::create_phy_driver::<PhySample>()];
///
/// impl ::kernel::Module for Module {
-/// fn init(module: &'static ThisModule) -> Result<Self> {
+/// fn init(module: &'static ::kernel::ThisModule) -> Result<Self> {
/// let drivers = unsafe { &mut DRIVERS };
/// let mut reg = ::kernel::net::phy::Registration::register(
/// module,
@@ -860,7 +860,7 @@ impl DeviceMask {
/// ];
/// #[cfg(MODULE)]
/// #[no_mangle]
-/// static __mod_mdio__phydev_device_table: [::kernel::bindings::mdio_device_id; 2] = _DEVICE_TABLE;
+/// static __mod_device_table__mdio__phydev: [::kernel::bindings::mdio_device_id; 2] = _DEVICE_TABLE;
/// ```
#[macro_export]
macro_rules! module_phy_driver {
@@ -883,7 +883,7 @@ macro_rules! module_phy_driver {
#[cfg(MODULE)]
#[no_mangle]
- static __mod_mdio__phydev_device_table: [$crate::bindings::mdio_device_id;
+ static __mod_device_table__mdio__phydev: [$crate::bindings::mdio_device_id;
$crate::module_phy_driver!(@count_devices $($dev),+) + 1] = _DEVICE_TABLE;
};
@@ -903,7 +903,7 @@ macro_rules! module_phy_driver {
[$($crate::net::phy::create_phy_driver::<$driver>()),+];
impl $crate::Module for Module {
- fn init(module: &'static ThisModule) -> Result<Self> {
+ fn init(module: &'static $crate::ThisModule) -> Result<Self> {
// SAFETY: The anonymous constant guarantees that nobody else can access
// the `DRIVERS` static. The array is used only in the C side.
let drivers = unsafe { &mut DRIVERS };
diff --git a/rust/kernel/prelude.rs b/rust/kernel/prelude.rs
index 8bdab9aa0d16..9ab4e0b6cbc9 100644
--- a/rust/kernel/prelude.rs
+++ b/rust/kernel/prelude.rs
@@ -24,6 +24,8 @@ pub use super::build_assert;
// `super::std_vendor` is hidden, which makes the macro inline for some reason.
#[doc(no_inline)]
pub use super::dbg;
+pub use super::fmt;
+pub use super::{dev_alert, dev_crit, dev_dbg, dev_emerg, dev_err, dev_info, dev_notice, dev_warn};
pub use super::{pr_alert, pr_crit, pr_debug, pr_emerg, pr_err, pr_info, pr_notice, pr_warn};
pub use super::{init, pin_init, try_init, try_pin_init};
diff --git a/rust/kernel/types.rs b/rust/kernel/types.rs
index 7a133d938551..ec6457bb3084 100644
--- a/rust/kernel/types.rs
+++ b/rust/kernel/types.rs
@@ -300,6 +300,22 @@ impl<T> Opaque<T> {
}
}
+ /// Creates a fallible pin-initializer from the given initializer closure.
+ ///
+ /// The returned initializer calls the given closure with the pointer to the inner `T` of this
+ /// `Opaque`. Since this memory is uninitialized, the closure is not allowed to read from it.
+ ///
+ /// This function is safe, because the `T` inside of an `Opaque` is allowed to be
+ /// uninitialized. Additionally, access to the inner `T` requires `unsafe`, so the caller needs
+ /// to verify at that point that the inner value is valid.
+ pub fn try_ffi_init<E>(
+ init_func: impl FnOnce(*mut T) -> Result<(), E>,
+ ) -> impl PinInit<Self, E> {
+ // SAFETY: We contain a `MaybeUninit`, so it is OK for the `init_func` to not fully
+ // initialize the `T`.
+ unsafe { init::pin_init_from_closure::<_, E>(move |slot| init_func(Self::raw_get(slot))) }
+ }
+
/// Returns a raw pointer to the opaque data.
pub const fn get(&self) -> *mut T {
UnsafeCell::get(&self.value).cast::<T>()
diff --git a/rust/kernel/workqueue.rs b/rust/kernel/workqueue.rs
index 4d1d2062f6eb..fd3e97192ed8 100644
--- a/rust/kernel/workqueue.rs
+++ b/rust/kernel/workqueue.rs
@@ -519,7 +519,15 @@ impl_has_work! {
impl{T} HasWork<Self> for ClosureWork<T> { self.work }
}
-// SAFETY: TODO.
+// SAFETY: The `__enqueue` implementation in RawWorkItem uses a `work_struct` initialized with the
+// `run` method of this trait as the function pointer because:
+// - `__enqueue` gets the `work_struct` from the `Work` field, using `T::raw_get_work`.
+// - The only safe way to create a `Work` object is through `Work::new`.
+// - `Work::new` makes sure that `T::Pointer::run` is passed to `init_work_with_key`.
+// - Finally `Work` and `RawWorkItem` guarantee that the correct `Work` field
+// will be used because of the ID const generic bound. This makes sure that `T::raw_get_work`
+// uses the correct offset for the `Work` field, and `Work::new` picks the correct
+// implementation of `WorkItemPointer` for `Arc<T>`.
unsafe impl<T, const ID: u64> WorkItemPointer<ID> for Arc<T>
where
T: WorkItem<ID, Pointer = Self>,
@@ -537,7 +545,13 @@ where
}
}
-// SAFETY: TODO.
+// SAFETY: The `work_struct` raw pointer is guaranteed to be valid for the duration of the call to
+// the closure because we get it from an `Arc`, which means that the ref count will be at least 1,
+// and we don't drop the `Arc` ourselves. If `queue_work_on` returns true, it is further guaranteed
+// to be valid until a call to the function pointer in `work_struct` because we leak the memory it
+// points to, and only reclaim it if the closure returns false, or in `WorkItemPointer::run`, which
+// is what the function pointer in the `work_struct` must be pointing to, according to the safety
+// requirements of `WorkItemPointer`.
unsafe impl<T, const ID: u64> RawWorkItem<ID> for Arc<T>
where
T: WorkItem<ID, Pointer = Self>,
diff --git a/rust/macros/module.rs b/rust/macros/module.rs
index e7a087b7e884..2587f41b0d39 100644
--- a/rust/macros/module.rs
+++ b/rust/macros/module.rs
@@ -232,6 +232,7 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
mod __module_init {{
mod __module_init {{
use super::super::{type_};
+ use kernel::init::PinInit;
/// The \"Rust loadable module\" mark.
//
@@ -242,7 +243,8 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
#[used]
static __IS_RUST_MODULE: () = ();
- static mut __MOD: Option<{type_}> = None;
+ static mut __MOD: core::mem::MaybeUninit<{type_}> =
+ core::mem::MaybeUninit::uninit();
// Loadable modules need to export the `{{init,cleanup}}_module` identifiers.
/// # Safety
@@ -331,20 +333,14 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
///
/// This function must only be called once.
unsafe fn __init() -> kernel::ffi::c_int {{
- match <{type_} as kernel::Module>::init(&super::super::THIS_MODULE) {{
- Ok(m) => {{
- // SAFETY: No data race, since `__MOD` can only be accessed by this
- // module and there only `__init` and `__exit` access it. These
- // functions are only called once and `__exit` cannot be called
- // before or during `__init`.
- unsafe {{
- __MOD = Some(m);
- }}
- return 0;
- }}
- Err(e) => {{
- return e.to_errno();
- }}
+ let initer =
+ <{type_} as kernel::InPlaceModule>::init(&super::super::THIS_MODULE);
+ // SAFETY: No data race, since `__MOD` can only be accessed by this module
+ // and there only `__init` and `__exit` access it. These functions are only
+ // called once and `__exit` cannot be called before or during `__init`.
+ match unsafe {{ initer.__pinned_init(__MOD.as_mut_ptr()) }} {{
+ Ok(m) => 0,
+ Err(e) => e.to_errno(),
}}
}}
@@ -359,7 +355,7 @@ pub(crate) fn module(ts: TokenStream) -> TokenStream {
// called once and `__init` was already called.
unsafe {{
// Invokes `drop()` on `__MOD`, which should be used for cleanup.
- __MOD = None;
+ __MOD.assume_init_drop();
}}
}}
diff --git a/samples/bpf/Makefile b/samples/bpf/Makefile
index bcf103a4c14f..96a05e70ace3 100644
--- a/samples/bpf/Makefile
+++ b/samples/bpf/Makefile
@@ -146,13 +146,14 @@ ifeq ($(ARCH), x86)
BPF_EXTRA_CFLAGS += -fcf-protection
endif
-TPROGS_CFLAGS += -Wall -O2
-TPROGS_CFLAGS += -Wmissing-prototypes
-TPROGS_CFLAGS += -Wstrict-prototypes
-TPROGS_CFLAGS += $(call try-run,\
+COMMON_CFLAGS += -Wall -O2
+COMMON_CFLAGS += -Wmissing-prototypes
+COMMON_CFLAGS += -Wstrict-prototypes
+COMMON_CFLAGS += $(call try-run,\
printf "int main() { return 0; }" |\
$(CC) -Werror -fsanitize=bounds -x c - -o "$$TMP",-fsanitize=bounds,)
+TPROGS_CFLAGS += $(COMMON_CFLAGS)
TPROGS_CFLAGS += -I$(objtree)/usr/include
TPROGS_CFLAGS += -I$(srctree)/tools/testing/selftests/bpf/
TPROGS_CFLAGS += -I$(LIBBPF_INCLUDE)
@@ -162,7 +163,7 @@ TPROGS_CFLAGS += -I$(srctree)/tools/lib
TPROGS_CFLAGS += -DHAVE_ATTR_TEST=0
ifdef SYSROOT
-TPROGS_CFLAGS += --sysroot=$(SYSROOT)
+COMMON_CFLAGS += --sysroot=$(SYSROOT)
TPROGS_LDFLAGS := -L$(SYSROOT)/usr/lib
endif
@@ -229,7 +230,7 @@ clean:
$(LIBBPF): $(wildcard $(LIBBPF_SRC)/*.[ch] $(LIBBPF_SRC)/Makefile) | $(LIBBPF_OUTPUT)
# Fix up variables inherited from Kbuild that tools/ build system won't like
- $(MAKE) -C $(LIBBPF_SRC) RM='rm -rf' EXTRA_CFLAGS="$(TPROGS_CFLAGS)" \
+ $(MAKE) -C $(LIBBPF_SRC) RM='rm -rf' EXTRA_CFLAGS="$(COMMON_CFLAGS)" \
LDFLAGS="$(TPROGS_LDFLAGS)" srctree=$(BPF_SAMPLES_PATH)/../../ \
O= OUTPUT=$(LIBBPF_OUTPUT)/ DESTDIR=$(LIBBPF_DESTDIR) prefix= \
$@ install_headers
diff --git a/samples/kfifo/dma-example.c b/samples/kfifo/dma-example.c
index 48df719dac8c..8076ac410161 100644
--- a/samples/kfifo/dma-example.c
+++ b/samples/kfifo/dma-example.c
@@ -9,6 +9,7 @@
#include <linux/kfifo.h>
#include <linux/module.h>
#include <linux/scatterlist.h>
+#include <linux/dma-mapping.h>
/*
* This module shows how to handle fifo dma operations.
diff --git a/samples/qmi/qmi_sample_client.c b/samples/qmi/qmi_sample_client.c
index a42892523d3b..b27d861f354f 100644
--- a/samples/qmi/qmi_sample_client.c
+++ b/samples/qmi/qmi_sample_client.c
@@ -524,7 +524,7 @@ static void qmi_sample_remove(struct platform_device *pdev)
static struct platform_driver qmi_sample_driver = {
.probe = qmi_sample_probe,
- .remove_new = qmi_sample_remove,
+ .remove = qmi_sample_remove,
.driver = {
.name = "qmi_sample_client",
},
diff --git a/samples/vfio-mdev/mbochs.c b/samples/vfio-mdev/mbochs.c
index 836456837997..18623ba666e3 100644
--- a/samples/vfio-mdev/mbochs.c
+++ b/samples/vfio-mdev/mbochs.c
@@ -1469,6 +1469,6 @@ static void __exit mbochs_dev_exit(void)
class_unregister(&mbochs_class);
}
-MODULE_IMPORT_NS(DMA_BUF);
+MODULE_IMPORT_NS("DMA_BUF");
module_init(mbochs_dev_init)
module_exit(mbochs_dev_exit)
diff --git a/scripts/.gitignore b/scripts/.gitignore
index 3dbb8bb2457b..c2ef68848da5 100644
--- a/scripts/.gitignore
+++ b/scripts/.gitignore
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0-only
/asn1_compiler
+/gen_packed_field_checks
/generate_rust_target
/insert-sys-cert
/kallsyms
diff --git a/scripts/Kbuild.include b/scripts/Kbuild.include
index ed8a7493524b..8c311b997e24 100644
--- a/scripts/Kbuild.include
+++ b/scripts/Kbuild.include
@@ -205,7 +205,7 @@ if_changed_dep = $(if $(if-changed-cond),$(cmd_and_fixdep),@:)
cmd_and_fixdep = \
$(cmd); \
- scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).cmd;\
+ $(objtree)/scripts/basic/fixdep $(depfile) $@ '$(make-cmd)' > $(dot-target).cmd;\
rm -f $(depfile)
# Usage: $(call if_changed_rule,foo)
diff --git a/scripts/Makefile b/scripts/Makefile
index 6bcda4b9d054..546e8175e1c4 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -47,7 +47,7 @@ HOSTCFLAGS_sorttable.o += -DMCOUNT_SORT_ENABLED
endif
# The following programs are only built on demand
-hostprogs += unifdef
+hostprogs += unifdef gen_packed_field_checks
# The module linker script is preprocessed on demand
targets += module.lds
diff --git a/scripts/Makefile.autofdo b/scripts/Makefile.autofdo
new file mode 100644
index 000000000000..1caf2457e585
--- /dev/null
+++ b/scripts/Makefile.autofdo
@@ -0,0 +1,24 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# Enable available and selected Clang AutoFDO features.
+
+CFLAGS_AUTOFDO_CLANG := -fdebug-info-for-profiling -mllvm -enable-fs-discriminator=true -mllvm -improved-fs-discriminator=true
+
+ifndef CONFIG_DEBUG_INFO
+ CFLAGS_AUTOFDO_CLANG += -gmlt
+endif
+
+ifdef CLANG_AUTOFDO_PROFILE
+ CFLAGS_AUTOFDO_CLANG += -fprofile-sample-use=$(CLANG_AUTOFDO_PROFILE) -ffunction-sections
+ CFLAGS_AUTOFDO_CLANG += -fsplit-machine-functions
+endif
+
+ifdef CONFIG_LTO_CLANG_THIN
+ ifdef CLANG_AUTOFDO_PROFILE
+ KBUILD_LDFLAGS += --lto-sample-profile=$(CLANG_AUTOFDO_PROFILE)
+ endif
+ KBUILD_LDFLAGS += --mllvm=-enable-fs-discriminator=true --mllvm=-improved-fs-discriminator=true -plugin-opt=thinlto
+ KBUILD_LDFLAGS += -plugin-opt=-split-machine-functions
+endif
+
+export CFLAGS_AUTOFDO_CLANG
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index f483a54380e7..c16e4cf54d77 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -3,7 +3,7 @@
# Building
# ==========================================================================
-src := $(if $(VPATH),$(VPATH)/)$(obj)
+src := $(srcroot)/$(obj)
PHONY := $(obj)/
$(obj)/:
@@ -34,7 +34,7 @@ subdir-asflags-y :=
subdir-ccflags-y :=
# Read auto.conf if it exists, otherwise ignore
--include include/config/auto.conf
+-include $(objtree)/include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
include $(srctree)/scripts/Makefile.compiler
@@ -107,20 +107,14 @@ cmd_cpp_i_c = $(CPP) $(c_flags) -o $@ $<
$(obj)/%.i: $(obj)/%.c FORCE
$(call if_changed_dep,cpp_i_c)
-genksyms = scripts/genksyms/genksyms \
- $(if $(1), -T $(2)) \
- $(if $(KBUILD_PRESERVE), -p) \
- -r $(or $(wildcard $(2:.symtypes=.symref)), /dev/null)
+genksyms = $(objtree)/scripts/genksyms/genksyms \
+ $(if $(KBUILD_SYMTYPES), -T $(@:.o=.symtypes)) \
+ $(if $(KBUILD_PRESERVE), -p) \
+ $(addprefix -r , $(wildcard $(@:.o=.symref)))
# These mirror gensymtypes_S and co below, keep them in synch.
cmd_gensymtypes_c = $(CPP) -D__GENKSYMS__ $(c_flags) $< | $(genksyms)
-quiet_cmd_cc_symtypes_c = SYM $(quiet_modtag) $@
- cmd_cc_symtypes_c = $(call cmd_gensymtypes_c,true,$@) >/dev/null
-
-$(obj)/%.symtypes : $(obj)/%.c FORCE
- $(call cmd,cc_symtypes_c)
-
# LLVM assembly
# Generate .ll files from .c
quiet_cmd_cc_ll_c = CC $(quiet_modtag) $@
@@ -135,17 +129,6 @@ $(obj)/%.ll: $(obj)/%.c FORCE
is-single-obj-m = $(and $(part-of-module),$(filter $@, $(obj-m)),y)
-# When a module consists of a single object, there is no reason to keep LLVM IR.
-# Make $(LD) covert LLVM IR to ELF here.
-ifdef CONFIG_LTO_CLANG
-cmd_ld_single_m = $(if $(is-single-obj-m), ; $(LD) $(ld_flags) -r -o $(tmp-target) $@; mv $(tmp-target) $@)
-endif
-
-quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
- cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< \
- $(cmd_ld_single_m) \
- $(cmd_objtool)
-
ifdef CONFIG_MODVERSIONS
# When module versioning is enabled the following steps are executed:
# o compile a <file>.o from <file>.c
@@ -158,8 +141,7 @@ ifdef CONFIG_MODVERSIONS
gen_symversions = \
if $(NM) $@ 2>/dev/null | grep -q ' __export_symbol_'; then \
- $(call cmd_gensymtypes_$(1),$(KBUILD_SYMTYPES),$(@:.o=.symtypes)) \
- >> $(dot-target).cmd; \
+ $(cmd_gensymtypes_$1) >> $(dot-target).cmd; \
fi
cmd_gen_symversions_c = $(call gen_symversions,c)
@@ -207,23 +189,6 @@ ifneq ($(findstring 1, $(KBUILD_EXTRA_WARN)),)
cmd_warn_shared_object = $(if $(word 2, $(modname-multi)),$(warning $(kbuild-file): $*.o is added to multiple modules: $(modname-multi)))
endif
-define rule_cc_o_c
- $(call cmd_and_fixdep,cc_o_c)
- $(call cmd,checksrc)
- $(call cmd,checkdoc)
- $(call cmd,gen_objtooldep)
- $(call cmd,gen_symversions_c)
- $(call cmd,record_mcount)
- $(call cmd,warn_shared_object)
-endef
-
-define rule_as_o_S
- $(call cmd_and_fixdep,as_o_S)
- $(call cmd,gen_objtooldep)
- $(call cmd,gen_symversions_S)
- $(call cmd,warn_shared_object)
-endef
-
# Built-in and composite module parts
$(obj)/%.o: $(obj)/%.c $(recordmcount_source) FORCE
$(call if_changed_rule,cc_o_c)
@@ -330,22 +295,12 @@ cmd_gensymtypes_S = \
$(NM) $@ | sed -n 's/.* __export_symbol_\(.*\)/EXPORT_SYMBOL(\1);/p' ; } | \
$(CPP) -D__GENKSYMS__ $(c_flags) -xc - | $(genksyms)
-quiet_cmd_cc_symtypes_S = SYM $(quiet_modtag) $@
- cmd_cc_symtypes_S = $(call cmd_gensymtypes_S,true,$@) >/dev/null
-
-$(obj)/%.symtypes : $(obj)/%.S FORCE
- $(call cmd,cc_symtypes_S)
-
-
quiet_cmd_cpp_s_S = CPP $(quiet_modtag) $@
cmd_cpp_s_S = $(CPP) $(a_flags) -o $@ $<
$(obj)/%.s: $(obj)/%.S FORCE
$(call if_changed_dep,cpp_s_S)
-quiet_cmd_as_o_S = AS $(quiet_modtag) $@
- cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< $(cmd_objtool)
-
ifdef CONFIG_ASM_MODVERSIONS
# versioning matches the C process described above, with difference that
diff --git a/scripts/Makefile.clang b/scripts/Makefile.clang
index 6c23c6af797f..2435efae67f5 100644
--- a/scripts/Makefile.clang
+++ b/scripts/Makefile.clang
@@ -10,6 +10,7 @@ CLANG_TARGET_FLAGS_mips := mipsel-linux-gnu
CLANG_TARGET_FLAGS_powerpc := powerpc64le-linux-gnu
CLANG_TARGET_FLAGS_riscv := riscv64-linux-gnu
CLANG_TARGET_FLAGS_s390 := s390x-linux-gnu
+CLANG_TARGET_FLAGS_sparc := sparc64-linux-gnu
CLANG_TARGET_FLAGS_x86 := x86_64-linux-gnu
CLANG_TARGET_FLAGS_um := $(CLANG_TARGET_FLAGS_$(SUBARCH))
CLANG_TARGET_FLAGS := $(CLANG_TARGET_FLAGS_$(SRCARCH))
diff --git a/scripts/Makefile.clean b/scripts/Makefile.clean
index 4fcfab40ed61..6ead00ec7313 100644
--- a/scripts/Makefile.clean
+++ b/scripts/Makefile.clean
@@ -3,7 +3,7 @@
# Cleaning up
# ==========================================================================
-src := $(if $(VPATH),$(VPATH)/)$(obj)
+src := $(srcroot)/$(obj)
PHONY := __clean
__clean:
diff --git a/scripts/Makefile.compiler b/scripts/Makefile.compiler
index e0842496d26e..8c1029687e2e 100644
--- a/scripts/Makefile.compiler
+++ b/scripts/Makefile.compiler
@@ -13,7 +13,7 @@ cc-cross-prefix = $(firstword $(foreach c, $(1), \
$(if $(shell command -v -- $(c)gcc 2>/dev/null), $(c))))
# output directory for tests below
-TMPOUT = $(if $(KBUILD_EXTMOD),$(firstword $(KBUILD_EXTMOD))/).tmp_$$$$
+TMPOUT = .tmp_$$$$
# try-run
# Usage: option = $(call try-run, $(CC)...-o "$$TMP",option-ok,otherwise)
diff --git a/scripts/Makefile.host b/scripts/Makefile.host
index e01c13a588dd..c1dedf646a39 100644
--- a/scripts/Makefile.host
+++ b/scripts/Makefile.host
@@ -96,12 +96,10 @@ hostrust_flags = --out-dir $(dir $@) --emit=dep-info=$(depfile) \
$(KBUILD_HOSTRUSTFLAGS) $(HOST_EXTRARUSTFLAGS) \
$(HOSTRUSTFLAGS_$(target-stem))
-# $(objtree)/$(obj) for including generated headers from checkin source files
-ifeq ($(KBUILD_EXTMOD),)
+# $(obj) for including generated headers from checkin source files
ifdef building_out_of_srctree
-hostc_flags += -I $(objtree)/$(obj)
-hostcxx_flags += -I $(objtree)/$(obj)
-endif
+hostc_flags += -I $(obj)
+hostcxx_flags += -I $(obj)
endif
#####
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index 01a9f567d5af..7395200538da 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -191,15 +191,33 @@ _c_flags += $(if $(patsubst n%,, \
-D__KCSAN_INSTRUMENT_BARRIERS__)
endif
+#
+# Enable AutoFDO build flags except some files or directories we don't want to
+# enable (depends on variables AUTOFDO_PROFILE_obj.o and AUTOFDO_PROFILE).
+#
+ifeq ($(CONFIG_AUTOFDO_CLANG),y)
+_c_flags += $(if $(patsubst n%,, \
+ $(AUTOFDO_PROFILE_$(target-stem).o)$(AUTOFDO_PROFILE)$(is-kernel-object)), \
+ $(CFLAGS_AUTOFDO_CLANG))
+endif
+
+#
+# Enable Propeller build flags except some files or directories we don't want to
+# enable (depends on variables AUTOFDO_PROPELLER_obj.o and PROPELLER_PROFILE).
+#
+ifdef CONFIG_PROPELLER_CLANG
+_c_flags += $(if $(patsubst n%,, \
+ $(AUTOFDO_PROFILE_$(target-stem).o)$(AUTOFDO_PROFILE)$(PROPELLER_PROFILE))$(is-kernel-object), \
+ $(CFLAGS_PROPELLER_CLANG))
+endif
+
# $(src) for including checkin headers from generated source files
# $(obj) for including generated headers from checkin source files
-ifeq ($(KBUILD_EXTMOD),)
ifdef building_out_of_srctree
_c_flags += $(addprefix -I, $(src) $(obj))
_a_flags += $(addprefix -I, $(src) $(obj))
_cpp_flags += $(addprefix -I, $(src) $(obj))
endif
-endif
# If $(is-kernel-object) is 'y', this object will be linked to vmlinux or modules
is-kernel-object = $(or $(part-of-builtin),$(part-of-module))
@@ -280,6 +298,42 @@ $(foreach m, $1, \
$(addprefix $(obj)/, $(call suffix-search, $(patsubst $(obj)/%,%,$m), $2, $3))))
endef
+# Build commands
+# ===========================================================================
+# These are shared by some Makefile.* files.
+
+objtool-enabled := y
+
+ifdef CONFIG_LTO_CLANG
+# objtool cannot process LLVM IR. Make $(LD) covert LLVM IR to ELF here.
+cmd_ld_single = $(if $(objtool-enabled), ; $(LD) $(ld_flags) -r -o $(tmp-target) $@; mv $(tmp-target) $@)
+endif
+
+quiet_cmd_cc_o_c = CC $(quiet_modtag) $@
+ cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $< \
+ $(cmd_ld_single) \
+ $(cmd_objtool)
+
+define rule_cc_o_c
+ $(call cmd_and_fixdep,cc_o_c)
+ $(call cmd,checksrc)
+ $(call cmd,checkdoc)
+ $(call cmd,gen_objtooldep)
+ $(call cmd,gen_symversions_c)
+ $(call cmd,record_mcount)
+ $(call cmd,warn_shared_object)
+endef
+
+quiet_cmd_as_o_S = AS $(quiet_modtag) $@
+ cmd_as_o_S = $(CC) $(a_flags) -c -o $@ $< $(cmd_objtool)
+
+define rule_as_o_S
+ $(call cmd_and_fixdep,as_o_S)
+ $(call cmd,gen_objtooldep)
+ $(call cmd,gen_symversions_S)
+ $(call cmd,warn_shared_object)
+endef
+
# Copy a file
# ===========================================================================
# 'cp' preserves permissions. If you use it to copy a file in read-only srctree,
@@ -371,10 +425,10 @@ quiet_cmd_lzo_with_size = LZO $@
cmd_lzo_with_size = { cat $(real-prereqs) | $(KLZOP) -9; $(size_append); } > $@
quiet_cmd_lz4 = LZ4 $@
- cmd_lz4 = cat $(real-prereqs) | $(LZ4) -l -c1 stdin stdout > $@
+ cmd_lz4 = cat $(real-prereqs) | $(LZ4) -l -9 - - > $@
quiet_cmd_lz4_with_size = LZ4 $@
- cmd_lz4_with_size = { cat $(real-prereqs) | $(LZ4) -l -c1 stdin stdout; \
+ cmd_lz4_with_size = { cat $(real-prereqs) | $(LZ4) -l -9 - -; \
$(size_append); } > $@
# U-Boot mkimage
diff --git a/scripts/Makefile.modfinal b/scripts/Makefile.modfinal
index 1482884ec3ca..542ba462ed3e 100644
--- a/scripts/Makefile.modfinal
+++ b/scripts/Makefile.modfinal
@@ -6,14 +6,12 @@
PHONY := __modfinal
__modfinal:
-include include/config/auto.conf
+include $(objtree)/include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
-
-# for c_flags
include $(srctree)/scripts/Makefile.lib
# find all modules listed in modules.order
-modules := $(call read-file, $(MODORDER))
+modules := $(call read-file, modules.order)
__modfinal: $(modules:%.o=%.ko)
@:
@@ -22,30 +20,27 @@ __modfinal: $(modules:%.o=%.ko)
modname = $(notdir $(@:.mod.o=))
part-of-module = y
GCOV_PROFILE := n
-KCSAN_SANITIZE := n
-
-quiet_cmd_cc_o_c = CC [M] $@
- cmd_cc_o_c = $(CC) $(filter-out $(CC_FLAGS_CFI), $(c_flags)) -c -o $@ $<
+ccflags-remove-y := $(CC_FLAGS_CFI)
%.mod.o: %.mod.c FORCE
- $(call if_changed_dep,cc_o_c)
+ $(call if_changed_rule,cc_o_c)
-$(extmod_prefix).module-common.o: $(srctree)/scripts/module-common.c FORCE
- $(call if_changed_dep,cc_o_c)
+.module-common.o: $(srctree)/scripts/module-common.c FORCE
+ $(call if_changed_rule,cc_o_c)
quiet_cmd_ld_ko_o = LD [M] $@
cmd_ld_ko_o = \
$(LD) -r $(KBUILD_LDFLAGS) \
$(KBUILD_LDFLAGS_MODULE) $(LDFLAGS_MODULE) \
- -T scripts/module.lds -o $@ $(filter %.o, $^)
+ -T $(objtree)/scripts/module.lds -o $@ $(filter %.o, $^)
quiet_cmd_btf_ko = BTF [M] $@
cmd_btf_ko = \
- if [ ! -f vmlinux ]; then \
+ if [ ! -f $(objtree)/vmlinux ]; then \
printf "Skipping BTF generation for %s due to unavailability of vmlinux\n" $@ 1>&2; \
else \
- LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) $(MODULE_PAHOLE_FLAGS) --btf_base vmlinux $@; \
- $(RESOLVE_BTFIDS) -b vmlinux $@; \
+ LLVM_OBJCOPY="$(OBJCOPY)" $(PAHOLE) -J $(PAHOLE_FLAGS) $(MODULE_PAHOLE_FLAGS) --btf_base $(objtree)/vmlinux $@; \
+ $(RESOLVE_BTFIDS) -b $(objtree)/vmlinux $@; \
fi;
# Same as newer-prereqs, but allows to exclude specified extra dependencies
@@ -57,13 +52,13 @@ if_changed_except = $(if $(call newer_prereqs_except,$(2))$(cmd-check), \
printf '%s\n' 'savedcmd_$@ := $(make-cmd)' > $(dot-target).cmd, @:)
# Re-generate module BTFs if either module's .ko or vmlinux changed
-%.ko: %.o %.mod.o $(extmod_prefix).module-common.o scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),vmlinux) FORCE
- +$(call if_changed_except,ld_ko_o,vmlinux)
+%.ko: %.o %.mod.o .module-common.o $(objtree)/scripts/module.lds $(and $(CONFIG_DEBUG_INFO_BTF_MODULES),$(KBUILD_BUILTIN),$(objtree)/vmlinux) FORCE
+ +$(call if_changed_except,ld_ko_o,$(objtree)/vmlinux)
ifdef CONFIG_DEBUG_INFO_BTF_MODULES
+$(if $(newer-prereqs),$(call cmd,btf_ko))
endif
-targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) $(extmod_prefix).module-common.o
+targets += $(modules:%.o=%.ko) $(modules:%.o=%.mod.o) .module-common.o
# Add FORCE to the prerequisites of a target to force it to be always rebuilt.
# ---------------------------------------------------------------------------
diff --git a/scripts/Makefile.modinst b/scripts/Makefile.modinst
index d97720943189..f97c9926ed31 100644
--- a/scripts/Makefile.modinst
+++ b/scripts/Makefile.modinst
@@ -6,7 +6,7 @@
PHONY := __modinst
__modinst:
-include include/config/auto.conf
+include $(objtree)/include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
install-y :=
@@ -40,7 +40,7 @@ $(addprefix $(MODLIB)/, modules.builtin modules.builtin.modinfo modules.builtin.
endif
-modules := $(call read-file, $(MODORDER))
+modules := $(call read-file, modules.order)
ifeq ($(KBUILD_EXTMOD),)
dst := $(MODLIB)/kernel
@@ -59,7 +59,7 @@ suffix-$(CONFIG_MODULE_COMPRESS_XZ) := .xz
suffix-$(CONFIG_MODULE_COMPRESS_ZSTD) := .zst
endif
-modules := $(patsubst $(extmod_prefix)%.o, $(dst)/%.ko$(suffix-y), $(modules))
+modules := $(patsubst %.o, $(dst)/%.ko$(suffix-y), $(modules))
install-$(CONFIG_MODULES) += $(modules)
__modinst: $(install-y)
@@ -119,7 +119,7 @@ endif
# Create necessary directories
$(foreach dir, $(sort $(dir $(install-y))), $(shell mkdir -p $(dir)))
-$(dst)/%.ko: $(extmod_prefix)%.ko FORCE
+$(dst)/%.ko: %.ko FORCE
$(call cmd,install)
$(call cmd,strip)
$(call cmd,sign)
diff --git a/scripts/Makefile.modpost b/scripts/Makefile.modpost
index 44936ebad161..ab0e94ea6249 100644
--- a/scripts/Makefile.modpost
+++ b/scripts/Makefile.modpost
@@ -35,10 +35,10 @@
PHONY := __modpost
__modpost:
-include include/config/auto.conf
+include $(objtree)/include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
-MODPOST = scripts/mod/modpost
+MODPOST = $(objtree)/scripts/mod/modpost
modpost-args = \
$(if $(CONFIG_MODULES),-M) \
@@ -46,7 +46,7 @@ modpost-args = \
$(if $(CONFIG_MODULE_SRCVERSION_ALL),-a) \
$(if $(CONFIG_SECTION_MISMATCH_WARN_ONLY),,-E) \
$(if $(KBUILD_MODPOST_WARN),-w) \
- $(if $(KBUILD_NSDEPS),-d $(MODULES_NSDEPS)) \
+ $(if $(KBUILD_NSDEPS),-d modules.nsdeps) \
$(if $(CONFIG_MODULE_ALLOW_MISSING_NAMESPACE_IMPORTS)$(KBUILD_NSDEPS),-N) \
$(if $(findstring 1, $(KBUILD_EXTRA_WARN)),-W) \
-o $@
@@ -61,8 +61,8 @@ endif
# Read out modules.order to pass in modpost.
# Otherwise, allmodconfig would fail with "Argument list too long".
ifdef KBUILD_MODULES
-modpost-args += -T $(MODORDER)
-modpost-deps += $(MODORDER)
+modpost-args += -T modules.order
+modpost-deps += modules.order
endif
ifeq ($(KBUILD_EXTMOD),)
@@ -111,19 +111,19 @@ endif
else
# set src + obj - they may be used in the modules's Makefile
-obj := $(KBUILD_EXTMOD)
-src := $(if $(VPATH),$(VPATH)/)$(obj)
+obj := .
+src := $(srcroot)
# Include the module's Makefile to find KBUILD_EXTRA_SYMBOLS
include $(kbuild-file)
-output-symdump := $(KBUILD_EXTMOD)/Module.symvers
+output-symdump := Module.symvers
-ifeq ($(wildcard Module.symvers),)
-missing-input := Module.symvers
+ifeq ($(wildcard $(objtree)/Module.symvers),)
+missing-input := $(objtree)/Module.symvers
else
-modpost-args += -i Module.symvers
-modpost-deps += Module.symvers
+modpost-args += -i $(objtree)/Module.symvers
+modpost-deps += $(objtree)/Module.symvers
endif
modpost-args += -e $(addprefix -i , $(KBUILD_EXTRA_SYMBOLS))
diff --git a/scripts/Makefile.propeller b/scripts/Makefile.propeller
new file mode 100644
index 000000000000..48a660128e25
--- /dev/null
+++ b/scripts/Makefile.propeller
@@ -0,0 +1,39 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# Enable available and selected Clang Propeller features.
+ifdef CLANG_PROPELLER_PROFILE_PREFIX
+ CFLAGS_PROPELLER_CLANG := -fbasic-block-sections=list=$(CLANG_PROPELLER_PROFILE_PREFIX)_cc_profile.txt -ffunction-sections
+ KBUILD_LDFLAGS += --symbol-ordering-file=$(CLANG_PROPELLER_PROFILE_PREFIX)_ld_profile.txt --no-warn-symbol-ordering
+else
+ # Starting with Clang v20, the '-fbasic-block-sections=labels' option is
+ # deprecated. Use the recommended '-fbasic-block-address-map' option.
+ # Link: https://github.com/llvm/llvm-project/pull/110039
+ ifeq ($(call clang-min-version, 200000),y)
+ CFLAGS_PROPELLER_CLANG := -fbasic-block-address-map
+ else
+ CFLAGS_PROPELLER_CLANG := -fbasic-block-sections=labels
+ endif
+endif
+
+# Propeller requires debug information to embed module names in the profiles.
+# If CONFIG_DEBUG_INFO is not enabled, set -gmlt option. Skip this for AutoFDO,
+# as the option should already be set.
+ifndef CONFIG_DEBUG_INFO
+ ifndef CONFIG_AUTOFDO_CLANG
+ CFLAGS_PROPELLER_CLANG += -gmlt
+ endif
+endif
+
+ifdef CONFIG_LTO_CLANG_THIN
+ ifdef CLANG_PROPELLER_PROFILE_PREFIX
+ KBUILD_LDFLAGS += --lto-basic-block-sections=$(CLANG_PROPELLER_PROFILE_PREFIX)_cc_profile.txt
+ else
+ ifeq ($(call test-ge, $(CONFIG_LLD_VERSION), 200000),y)
+ KBUILD_LDFLAGS += --lto-basic-block-address-map
+ else
+ KBUILD_LDFLAGS += --lto-basic-block-sections=labels
+ endif
+ endif
+endif
+
+export CFLAGS_PROPELLER_CLANG
diff --git a/scripts/Makefile.vmlinux b/scripts/Makefile.vmlinux
index dddad554e912..873caaa55313 100644
--- a/scripts/Makefile.vmlinux
+++ b/scripts/Makefile.vmlinux
@@ -5,17 +5,53 @@ __default: vmlinux
include include/config/auto.conf
include $(srctree)/scripts/Kbuild.include
-
-# for c_flags
include $(srctree)/scripts/Makefile.lib
targets :=
-quiet_cmd_cc_o_c = CC $@
- cmd_cc_o_c = $(CC) $(c_flags) -c -o $@ $<
-
%.o: %.c FORCE
- $(call if_changed_dep,cc_o_c)
+ $(call if_changed_rule,cc_o_c)
+
+%.o: %.S FORCE
+ $(call if_changed_rule,as_o_S)
+
+# Built-in dtb
+# ---------------------------------------------------------------------------
+
+quiet_cmd_wrap_dtbs = WRAP $@
+ cmd_wrap_dtbs = { \
+ echo '\#include <asm-generic/vmlinux.lds.h>'; \
+ echo '.section .dtb.init.rodata,"a"'; \
+ while read dtb; do \
+ symbase=__dtb_$$(basename -s .dtb "$${dtb}" | tr - _); \
+ echo '.balign STRUCT_ALIGNMENT'; \
+ echo ".global $${symbase}_begin"; \
+ echo "$${symbase}_begin:"; \
+ echo '.incbin "'$$dtb'" '; \
+ echo ".global $${symbase}_end"; \
+ echo "$${symbase}_end:"; \
+ done < $<; \
+ } > $@
+
+.builtin-dtbs.S: .builtin-dtbs-list FORCE
+ $(call if_changed,wrap_dtbs)
+
+quiet_cmd_gen_dtbs_list = GEN $@
+ cmd_gen_dtbs_list = \
+ $(if $(CONFIG_BUILTIN_DTB_NAME), echo "arch/$(SRCARCH)/boot/dts/$(CONFIG_BUILTIN_DTB_NAME).dtb",:) > $@
+
+.builtin-dtbs-list: arch/$(SRCARCH)/boot/dts/dtbs-list FORCE
+ $(call if_changed,$(if $(CONFIG_BUILTIN_DTB_ALL),copy,gen_dtbs_list))
+
+targets += .builtin-dtbs-list
+
+ifdef CONFIG_GENERIC_BUILTIN_DTB
+targets += .builtin-dtbs.S .builtin-dtbs.o
+vmlinux: .builtin-dtbs.o
+endif
+
+# vmlinux
+# ---------------------------------------------------------------------------
ifdef CONFIG_MODULES
targets += .vmlinux.export.o
@@ -39,6 +75,9 @@ cmd_link_vmlinux = \
targets += vmlinux
vmlinux: scripts/link-vmlinux.sh vmlinux.o $(KBUILD_LDS) FORCE
+$(call if_changed_dep,link_vmlinux)
+ifdef CONFIG_DEBUG_INFO_BTF
+vmlinux: $(RESOLVE_BTFIDS)
+endif
# module.builtin.ranges
# ---------------------------------------------------------------------------
diff --git a/scripts/checkpatch.pl b/scripts/checkpatch.pl
index 9eed3683ad76..a2066a6c9dd8 100755
--- a/scripts/checkpatch.pl
+++ b/scripts/checkpatch.pl
@@ -5843,6 +5843,8 @@ sub process {
#CamelCase
if ($var !~ /^$Constant$/ &&
$var =~ /[A-Z][a-z]|[a-z][A-Z]/ &&
+#Ignore C keywords
+ $var !~ /^_Generic$/ &&
#Ignore some autogenerated defines and enum values
$var !~ /^(?:[A-Z]+_){1,5}[A-Z]{1,3}[a-z]/ &&
#Ignore Page<foo> variants
diff --git a/scripts/coccicheck b/scripts/coccicheck
index e52cb43fede6..0e6bc5a10320 100755
--- a/scripts/coccicheck
+++ b/scripts/coccicheck
@@ -80,11 +80,7 @@ command results in a shift count error.'
NPROC=1
else
ONLINE=0
- if [ "$KBUILD_EXTMOD" = "" ] ; then
- OPTIONS="--dir $srctree $COCCIINCLUDE"
- else
- OPTIONS="--dir $KBUILD_EXTMOD $COCCIINCLUDE"
- fi
+ OPTIONS="--dir $srcroot $COCCIINCLUDE"
# Use only one thread per core by default if hyperthreading is enabled
THREADS_PER_CORE=$(LANG=C lscpu | grep "Thread(s) per core: " | tr -cd "[:digit:]")
diff --git a/scripts/depmod.sh b/scripts/depmod.sh
index e22da27fe13e..3c34fecacbc8 100755
--- a/scripts/depmod.sh
+++ b/scripts/depmod.sh
@@ -12,7 +12,7 @@ KERNELRELEASE=$1
: ${DEPMOD:=depmod}
-if ! test -r System.map ; then
+if ! test -r "${objtree}/System.map" ; then
echo "Warning: modules_install: missing 'System.map' file. Skipping depmod." >&2
exit 0
fi
@@ -25,7 +25,7 @@ if [ -z $(command -v $DEPMOD) ]; then
exit 0
fi
-set -- -ae -F System.map
+set -- -ae -F "${objtree}/System.map"
if test -n "$INSTALL_MOD_PATH"; then
set -- "$@" -b "$INSTALL_MOD_PATH"
fi
diff --git a/scripts/gen_packed_field_checks.c b/scripts/gen_packed_field_checks.c
new file mode 100644
index 000000000000..60042b7616ee
--- /dev/null
+++ b/scripts/gen_packed_field_checks.c
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+// Copyright (c) 2024, Intel Corporation
+#include <stdbool.h>
+#include <stdio.h>
+
+#define MAX_PACKED_FIELD_SIZE 50
+
+int main(int argc, char **argv)
+{
+ /* The first macro doesn't need a 'do {} while(0)' loop */
+ printf("#define CHECK_PACKED_FIELDS_1(fields) \\\n");
+ printf("\tCHECK_PACKED_FIELD(fields, 0)\n\n");
+
+ /* Remaining macros require a do/while loop, and are implemented
+ * recursively by calling the previous iteration's macro.
+ */
+ for (int i = 2; i <= MAX_PACKED_FIELD_SIZE; i++) {
+ printf("#define CHECK_PACKED_FIELDS_%d(fields) do { \\\n", i);
+ printf("\tCHECK_PACKED_FIELDS_%d(fields); \\\n", i - 1);
+ printf("\tCHECK_PACKED_FIELD(fields, %d); \\\n", i - 1);
+ printf("} while (0)\n\n");
+ }
+
+ printf("#define CHECK_PACKED_FIELDS(fields) \\\n");
+
+ for (int i = 1; i <= MAX_PACKED_FIELD_SIZE; i++)
+ printf("\t__builtin_choose_expr(ARRAY_SIZE(fields) == %d, ({ CHECK_PACKED_FIELDS_%d(fields); }), \\\n",
+ i, i);
+
+ printf("\t({ BUILD_BUG_ON_MSG(1, \"CHECK_PACKED_FIELDS() must be regenerated to support array sizes larger than %d.\"); }) \\\n",
+ MAX_PACKED_FIELD_SIZE);
+
+ for (int i = 1; i <= MAX_PACKED_FIELD_SIZE; i++)
+ printf(")");
+
+ printf("\n");
+}
diff --git a/scripts/genksyms/genksyms.c b/scripts/genksyms/genksyms.c
index f3901c55df23..07f9b8cfb233 100644
--- a/scripts/genksyms/genksyms.c
+++ b/scripts/genksyms/genksyms.c
@@ -632,54 +632,55 @@ static unsigned long expand_and_crc_sym(struct symbol *sym, unsigned long crc)
void export_symbol(const char *name)
{
struct symbol *sym;
+ unsigned long crc;
+ int has_changed = 0;
sym = find_symbol(name, SYM_NORMAL, 0);
- if (!sym)
+ if (!sym) {
error_with_pos("export undefined symbol %s", name);
- else {
- unsigned long crc;
- int has_changed = 0;
+ return;
+ }
- if (flag_dump_defs)
- fprintf(debugfile, "Export %s == <", name);
+ if (flag_dump_defs)
+ fprintf(debugfile, "Export %s == <", name);
- expansion_trail = (struct symbol *)-1L;
+ expansion_trail = (struct symbol *)-1L;
- sym->expansion_trail = expansion_trail;
- expansion_trail = sym;
- crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
+ sym->expansion_trail = expansion_trail;
+ expansion_trail = sym;
+ crc = expand_and_crc_sym(sym, 0xffffffff) ^ 0xffffffff;
- sym = expansion_trail;
- while (sym != (struct symbol *)-1L) {
- struct symbol *n = sym->expansion_trail;
+ sym = expansion_trail;
+ while (sym != (struct symbol *)-1L) {
+ struct symbol *n = sym->expansion_trail;
- if (sym->status != STATUS_UNCHANGED) {
- if (!has_changed) {
- print_location();
- fprintf(stderr, "%s: %s: modversion "
- "changed because of changes "
- "in ", flag_preserve ? "error" :
- "warning", name);
- } else
- fprintf(stderr, ", ");
- print_type_name(sym->type, sym->name);
- if (sym->status == STATUS_DEFINED)
- fprintf(stderr, " (became defined)");
- has_changed = 1;
- if (flag_preserve)
- errors++;
+ if (sym->status != STATUS_UNCHANGED) {
+ if (!has_changed) {
+ print_location();
+ fprintf(stderr,
+ "%s: %s: modversion changed because of changes in ",
+ flag_preserve ? "error" : "warning",
+ name);
+ } else {
+ fprintf(stderr, ", ");
}
- sym->expansion_trail = 0;
- sym = n;
+ print_type_name(sym->type, sym->name);
+ if (sym->status == STATUS_DEFINED)
+ fprintf(stderr, " (became defined)");
+ has_changed = 1;
+ if (flag_preserve)
+ errors++;
}
- if (has_changed)
- fprintf(stderr, "\n");
+ sym->expansion_trail = 0;
+ sym = n;
+ }
+ if (has_changed)
+ fprintf(stderr, "\n");
- if (flag_dump_defs)
- fputs(">\n", debugfile);
+ if (flag_dump_defs)
+ fputs(">\n", debugfile);
- printf("#SYMVER %s 0x%08lx\n", name, crc);
- }
+ printf("#SYMVER %s 0x%08lx\n", name, crc);
}
/*----------------------------------------------------------------------*/
diff --git a/scripts/head-object-list.txt b/scripts/head-object-list.txt
index fd5d00bac447..7274dfc65af6 100644
--- a/scripts/head-object-list.txt
+++ b/scripts/head-object-list.txt
@@ -23,9 +23,7 @@ arch/m68k/coldfire/head.o
arch/m68k/kernel/head.o
arch/m68k/kernel/sun3-head.o
arch/microblaze/kernel/head.o
-arch/mips/kernel/head.o
arch/nios2/kernel/head.o
-arch/openrisc/kernel/head.o
arch/parisc/kernel/head.o
arch/powerpc/kernel/head_44x.o
arch/powerpc/kernel/head_64.o
diff --git a/scripts/kconfig/conf.c b/scripts/kconfig/conf.c
index 3d7d454c54da..8abe57041955 100644
--- a/scripts/kconfig/conf.c
+++ b/scripts/kconfig/conf.c
@@ -628,7 +628,7 @@ static const struct option long_opts[] = {
static void conf_usage(const char *progname)
{
- printf("Usage: %s [options] <kconfig-file>\n", progname);
+ printf("Usage: %s [options] kconfig_file\n", progname);
printf("\n");
printf("Generic options:\n");
printf(" -h, --help Print this message and exit.\n");
@@ -653,6 +653,9 @@ static void conf_usage(const char *progname)
printf(" --mod2yesconfig Change answers from mod to yes if possible\n");
printf(" --mod2noconfig Change answers from mod to no if possible\n");
printf(" (If none of the above is given, --oldaskconfig is the default)\n");
+ printf("\n");
+ printf("Arguments:\n");
+ printf(" kconfig_file Top-level Kconfig file.\n");
}
int main(int ac, char **av)
diff --git a/scripts/kconfig/lkc_proto.h b/scripts/kconfig/lkc_proto.h
index 63519cd24bc7..8914b4e8f2a8 100644
--- a/scripts/kconfig/lkc_proto.h
+++ b/scripts/kconfig/lkc_proto.h
@@ -34,6 +34,7 @@ bool sym_string_valid(struct symbol *sym, const char *newval);
bool sym_string_within_range(struct symbol *sym, const char *str);
bool sym_set_string_value(struct symbol *sym, const char *newval);
bool sym_is_changeable(const struct symbol *sym);
+struct menu *sym_get_prompt_menu(const struct symbol *sym);
struct menu *sym_get_choice_menu(const struct symbol *sym);
const char * sym_get_string_value(struct symbol *sym);
diff --git a/scripts/kconfig/nconf.c b/scripts/kconfig/nconf.c
index 063b4f7ccbdb..c0b2dabf6c89 100644
--- a/scripts/kconfig/nconf.c
+++ b/scripts/kconfig/nconf.c
@@ -467,7 +467,7 @@ static void handle_f9(int *key, struct menu *current_item)
return;
}
-/* return != 0 to indicate the key was handles */
+/* return != 0 to indicate the key was handled */
static int process_special_keys(int *key, struct menu *menu)
{
int i;
diff --git a/scripts/kconfig/nconf.gui.c b/scripts/kconfig/nconf.gui.c
index 72b605efe549..4bfdf8ac2a9a 100644
--- a/scripts/kconfig/nconf.gui.c
+++ b/scripts/kconfig/nconf.gui.c
@@ -277,6 +277,15 @@ int btn_dialog(WINDOW *main_window, const char *msg, int btn_num, ...)
case KEY_RIGHT:
menu_driver(menu, REQ_RIGHT_ITEM);
break;
+ case 9: /* TAB */
+ if (btn_num > 1) {
+ /* cycle through buttons */
+ if (item_index(current_item(menu)) == btn_num - 1)
+ menu_driver(menu, REQ_FIRST_ITEM);
+ else
+ menu_driver(menu, REQ_NEXT_ITEM);
+ }
+ break;
case 10: /* ENTER */
case 27: /* ESCAPE */
case ' ':
diff --git a/scripts/kconfig/parser.y b/scripts/kconfig/parser.y
index bc43fb67c7c4..68372d3ff325 100644
--- a/scripts/kconfig/parser.y
+++ b/scripts/kconfig/parser.y
@@ -24,7 +24,6 @@
int cdebug = PRINTD;
static void yyerror(const char *err);
-static void zconfprint(const char *err, ...);
static void zconf_error(const char *err, ...);
static bool zconf_endtoken(const char *tokenname,
const char *expected_tokenname);
@@ -183,7 +182,7 @@ menuconfig_stmt: menuconfig_entry_start config_option_list
if (current_entry->prompt)
current_entry->prompt->type = P_MENU;
else
- zconfprint("warning: menuconfig statement without prompt");
+ zconf_error("menuconfig statement without prompt");
printd(DEBUG_PARSE, "%s:%d:endconfig\n", cur_filename, cur_lineno);
};
@@ -293,12 +292,6 @@ choice_option: T_PROMPT T_WORD_QUOTE if_expr T_EOL
printd(DEBUG_PARSE, "%s:%d:prompt\n", cur_filename, cur_lineno);
};
-choice_option: T_BOOL T_WORD_QUOTE if_expr T_EOL
-{
- menu_add_prompt(P_PROMPT, $2, $3);
- printd(DEBUG_PARSE, "%s:%d:bool\n", cur_filename, cur_lineno);
-};
-
choice_option: T_DEFAULT nonconst_symbol if_expr T_EOL
{
menu_add_symbol(P_DEFAULT, $2, $3);
@@ -408,14 +401,14 @@ help: help_start T_HELPTEXT
{
if (current_entry->help) {
free(current_entry->help);
- zconfprint("warning: '%s' defined with more than one help text -- only the last one will be used",
- current_entry->sym->name ?: "<choice>");
+ zconf_error("'%s' defined with more than one help text",
+ current_entry->sym->name ?: "<choice>");
}
/* Is the help text empty or all whitespace? */
if ($2[strspn($2, " \f\n\r\t\v")] == '\0')
- zconfprint("warning: '%s' defined with blank help text",
- current_entry->sym->name ?: "<choice>");
+ zconf_error("'%s' defined with blank help text",
+ current_entry->sym->name ?: "<choice>");
current_entry->help = $2;
};
@@ -598,17 +591,6 @@ static bool zconf_endtoken(const char *tokenname,
return true;
}
-static void zconfprint(const char *err, ...)
-{
- va_list ap;
-
- fprintf(stderr, "%s:%d: ", cur_filename, cur_lineno);
- va_start(ap, err);
- vfprintf(stderr, err, ap);
- va_end(ap);
- fprintf(stderr, "\n");
-}
-
static void zconf_error(const char *err, ...)
{
va_list ap;
diff --git a/scripts/kconfig/qconf.cc b/scripts/kconfig/qconf.cc
index e260cab1c2af..6c92ef1e16ef 100644
--- a/scripts/kconfig/qconf.cc
+++ b/scripts/kconfig/qconf.cc
@@ -110,7 +110,7 @@ void ConfigItem::updateMenu(void)
if (prop) switch (prop->type) {
case P_MENU:
- if (list->mode == singleMode || list->mode == symbolMode) {
+ if (list->mode == singleMode) {
/* a menuconfig entry is displayed differently
* depending whether it's at the view root or a child.
*/
@@ -159,7 +159,7 @@ void ConfigItem::updateMenu(void)
ch = 'M';
break;
default:
- if (sym_is_choice_value(sym) && type == S_BOOLEAN)
+ if (sym_is_choice_value(sym))
setIcon(promptColIdx, choiceNoIcon);
else
setIcon(promptColIdx, symbolNoIcon);
@@ -175,17 +175,16 @@ void ConfigItem::updateMenu(void)
setText(dataColIdx, sym_get_string_value(sym));
break;
}
- if (!sym_has_value(sym) && visible)
+ if (!sym_has_value(sym))
prompt += " (NEW)";
set_prompt:
setText(promptColIdx, prompt);
}
-void ConfigItem::testUpdateMenu(bool v)
+void ConfigItem::testUpdateMenu(void)
{
ConfigItem* i;
- visible = v;
if (!menu)
return;
@@ -307,7 +306,6 @@ ConfigList::ConfigList(QWidget *parent, const char *name)
{
setObjectName(name);
setSortingEnabled(false);
- setRootIsDecorated(true);
setVerticalScrollMode(ScrollPerPixel);
setHorizontalScrollMode(ScrollPerPixel);
@@ -430,27 +428,26 @@ void ConfigList::updateList()
item = (ConfigItem*)(*it);
if (!item->menu)
continue;
- item->testUpdateMenu(menu_is_visible(item->menu));
+ item->testUpdateMenu();
++it;
}
return;
}
- if (rootEntry != &rootmenu && (mode == singleMode ||
- (mode == symbolMode && rootEntry->parent != &rootmenu))) {
+ if (rootEntry != &rootmenu && mode == singleMode) {
item = (ConfigItem *)topLevelItem(0);
if (!item)
- item = new ConfigItem(this, 0, true);
+ item = new ConfigItem(this, 0);
last = item;
}
if ((mode == singleMode || (mode == symbolMode && !(rootEntry->flags & MENU_ROOT))) &&
rootEntry->sym && rootEntry->prompt) {
item = last ? last->nextSibling() : nullptr;
if (!item)
- item = new ConfigItem(this, last, rootEntry, true);
+ item = new ConfigItem(this, last, rootEntry);
else
- item->testUpdateMenu(true);
+ item->testUpdateMenu();
updateMenuList(item, rootEntry);
update();
@@ -599,7 +596,6 @@ void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
struct menu* child;
ConfigItem* item;
ConfigItem* last;
- bool visible;
enum prop_type type;
if (!menu) {
@@ -631,14 +627,13 @@ void ConfigList::updateMenuList(ConfigItem *parent, struct menu* menu)
break;
}
- visible = menu_is_visible(child);
if (!menuSkip(child)) {
if (!child->sym && !child->list && !child->prompt)
continue;
if (!item || item->menu != child)
- item = new ConfigItem(parent, last, child, visible);
+ item = new ConfigItem(parent, last, child);
else
- item->testUpdateMenu(visible);
+ item->testUpdateMenu();
if (mode == fullMode || mode == menuMode || type != P_MENU)
updateMenuList(item, child);
@@ -664,7 +659,6 @@ void ConfigList::updateMenuList(struct menu *menu)
struct menu* child;
ConfigItem* item;
ConfigItem* last;
- bool visible;
enum prop_type type;
if (!menu) {
@@ -696,14 +690,13 @@ void ConfigList::updateMenuList(struct menu *menu)
break;
}
- visible = menu_is_visible(child);
if (!menuSkip(child)) {
if (!child->sym && !child->list && !child->prompt)
continue;
if (!item || item->menu != child)
- item = new ConfigItem(this, last, child, visible);
+ item = new ConfigItem(this, last, child);
else
- item->testUpdateMenu(visible);
+ item->testUpdateMenu();
if (mode == fullMode || mode == menuMode || type != P_MENU)
updateMenuList(item, child);
@@ -731,7 +724,7 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
struct menu *menu;
enum prop_type type;
- if (ev->key() == Qt::Key_Escape && mode != fullMode && mode != listMode) {
+ if (ev->key() == Qt::Key_Escape && mode == singleMode) {
emit parentSelected();
ev->accept();
return;
@@ -781,13 +774,6 @@ void ConfigList::keyPressEvent(QKeyEvent* ev)
ev->accept();
}
-void ConfigList::mousePressEvent(QMouseEvent* e)
-{
- //QPoint p(contentsToViewport(e->pos()));
- //printf("contentsMousePressEvent: %d,%d\n", p.x(), p.y());
- Parent::mousePressEvent(e);
-}
-
void ConfigList::mouseReleaseEvent(QMouseEvent* e)
{
QPoint p = e->pos();
@@ -834,13 +820,6 @@ skip:
Parent::mouseReleaseEvent(e);
}
-void ConfigList::mouseMoveEvent(QMouseEvent* e)
-{
- //QPoint p(contentsToViewport(e->pos()));
- //printf("contentsMouseMoveEvent: %d,%d\n", p.x(), p.y());
- Parent::mouseMoveEvent(e);
-}
-
void ConfigList::mouseDoubleClickEvent(QMouseEvent* e)
{
QPoint p = e->pos();
@@ -1022,7 +1001,7 @@ void ConfigInfoView::menuInfo(void)
if (sym->name) {
stream << " (";
if (showDebug())
- stream << "<a href=\"s" << sym->name << "\">";
+ stream << "<a href=\"" << sym->name << "\">";
stream << print_filter(sym->name);
if (showDebug())
stream << "</a>";
@@ -1031,7 +1010,7 @@ void ConfigInfoView::menuInfo(void)
} else if (sym->name) {
stream << "<big><b>";
if (showDebug())
- stream << "<a href=\"s" << sym->name << "\">";
+ stream << "<a href=\"" << sym->name << "\">";
stream << print_filter(sym->name);
if (showDebug())
stream << "</a>";
@@ -1086,9 +1065,9 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
switch (prop->type) {
case P_PROMPT:
case P_MENU:
- stream << "prompt: <a href=\"m" << sym->name << "\">";
+ stream << "prompt: ";
stream << print_filter(prop->text);
- stream << "</a><br>";
+ stream << "<br>";
break;
case P_DEFAULT:
case P_SELECT:
@@ -1122,28 +1101,19 @@ QString ConfigInfoView::print_filter(const QString &str)
{
QRegularExpression re("[<>&\"\\n]");
QString res = str;
+
+ QHash<QChar, QString> patterns;
+ patterns['<'] = "&lt;";
+ patterns['>'] = "&gt;";
+ patterns['&'] = "&amp;";
+ patterns['"'] = "&quot;";
+ patterns['\n'] = "<br>";
+
for (int i = 0; (i = res.indexOf(re, i)) >= 0;) {
- switch (res[i].toLatin1()) {
- case '<':
- res.replace(i, 1, "&lt;");
- i += 4;
- break;
- case '>':
- res.replace(i, 1, "&gt;");
- i += 4;
- break;
- case '&':
- res.replace(i, 1, "&amp;");
- i += 5;
- break;
- case '"':
- res.replace(i, 1, "&quot;");
- i += 6;
- break;
- case '\n':
- res.replace(i, 1, "<br>");
- i += 4;
- break;
+ const QString n = patterns.value(res[i], QString());
+ if (!n.isEmpty()) {
+ res.replace(i, 1, n);
+ i += n.length();
}
}
return res;
@@ -1154,7 +1124,7 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
QTextStream *stream = reinterpret_cast<QTextStream *>(data);
if (sym && sym->name && !(sym->flags & SYMBOL_CONST)) {
- *stream << "<a href=\"s" << sym->name << "\">";
+ *stream << "<a href=\"" << sym->name << "\">";
*stream << print_filter(str);
*stream << "</a>";
} else {
@@ -1164,39 +1134,11 @@ void ConfigInfoView::expr_print_help(void *data, struct symbol *sym, const char
void ConfigInfoView::clicked(const QUrl &url)
{
- QByteArray str = url.toEncoded();
- const std::size_t count = str.size();
- char *data = new char[count + 2]; // '$' + '\0'
- struct symbol **result;
- struct menu *m = NULL;
-
- if (count < 1) {
- delete[] data;
- return;
- }
-
- memcpy(data, str.constData(), count);
- data[count] = '\0';
-
- /* Seek for exact match */
- data[0] = '^';
- strcat(data, "$");
- result = sym_re_search(data);
- if (!result) {
- delete[] data;
- return;
- }
+ struct menu *m;
- sym = *result;
-
- /* Seek for the menu which holds the symbol */
- for (struct property *prop = sym->prop; prop; prop = prop->next) {
- if (prop->type != P_PROMPT && prop->type != P_MENU)
- continue;
- m = prop->menu;
- break;
- }
+ sym = sym_find(url.toEncoded().constData());
+ m = sym_get_prompt_menu(sym);
if (!m) {
/* Symbol is not visible as a menu */
symbolInfo();
@@ -1204,9 +1146,6 @@ void ConfigInfoView::clicked(const QUrl &url)
} else {
emit menuSelected(m);
}
-
- free(result);
- delete[] data;
}
void ConfigInfoView::contextMenuEvent(QContextMenuEvent *event)
@@ -1240,8 +1179,7 @@ ConfigSearchWindow::ConfigSearchWindow(ConfigMainWindow *parent)
layout2->addWidget(searchButton);
layout1->addLayout(layout2);
- split = new QSplitter(this);
- split->setOrientation(Qt::Vertical);
+ split = new QSplitter(Qt::Vertical, this);
list = new ConfigList(split, "search");
list->mode = listMode;
info = new ConfigInfoView(split, "search");
@@ -1300,8 +1238,7 @@ void ConfigSearchWindow::search(void)
return;
for (p = result; *p; p++) {
for_all_prompts((*p), prop)
- lastItem = new ConfigItem(list, lastItem, prop->menu,
- menu_is_visible(prop->menu));
+ lastItem = new ConfigItem(list, lastItem, prop->menu);
}
}
@@ -1341,61 +1278,56 @@ ConfigMainWindow::ConfigMainWindow(void)
ConfigItem::menubackIcon = QIcon(QPixmap(xpm_menuback));
QWidget *widget = new QWidget(this);
- QVBoxLayout *layout = new QVBoxLayout(widget);
setCentralWidget(widget);
- split1 = new QSplitter(widget);
- split1->setOrientation(Qt::Horizontal);
- split1->setChildrenCollapsible(false);
-
- menuList = new ConfigList(widget, "menu");
+ QVBoxLayout *layout = new QVBoxLayout(widget);
- split2 = new QSplitter(widget);
+ split2 = new QSplitter(Qt::Vertical, widget);
+ layout->addWidget(split2);
split2->setChildrenCollapsible(false);
- split2->setOrientation(Qt::Vertical);
- // create config tree
- configList = new ConfigList(widget, "config");
+ split1 = new QSplitter(Qt::Horizontal, split2);
+ split1->setChildrenCollapsible(false);
- helpText = new ConfigInfoView(widget, "help");
+ configList = new ConfigList(split1, "config");
- layout->addWidget(split2);
- split2->addWidget(split1);
- split1->addWidget(configList);
- split1->addWidget(menuList);
- split2->addWidget(helpText);
+ menuList = new ConfigList(split1, "menu");
+ helpText = new ConfigInfoView(split2, "help");
setTabOrder(configList, helpText);
+
configList->setFocus();
backAction = new QAction(QPixmap(xpm_back), "Back", this);
+ backAction->setShortcut(QKeySequence::Back);
connect(backAction, &QAction::triggered,
this, &ConfigMainWindow::goBack);
QAction *quitAction = new QAction("&Quit", this);
- quitAction->setShortcut(Qt::CTRL | Qt::Key_Q);
+ quitAction->setShortcut(QKeySequence::Quit);
connect(quitAction, &QAction::triggered,
this, &ConfigMainWindow::close);
- QAction *loadAction = new QAction(QPixmap(xpm_load), "&Load", this);
- loadAction->setShortcut(Qt::CTRL | Qt::Key_L);
+ QAction *loadAction = new QAction(QPixmap(xpm_load), "&Open", this);
+ loadAction->setShortcut(QKeySequence::Open);
connect(loadAction, &QAction::triggered,
this, &ConfigMainWindow::loadConfig);
saveAction = new QAction(QPixmap(xpm_save), "&Save", this);
- saveAction->setShortcut(Qt::CTRL | Qt::Key_S);
+ saveAction->setShortcut(QKeySequence::Save);
connect(saveAction, &QAction::triggered,
this, &ConfigMainWindow::saveConfig);
conf_set_changed_callback(conf_changed);
- configname = xstrdup(conf_get_configname());
+ configname = conf_get_configname();
QAction *saveAsAction = new QAction("Save &As...", this);
+ saveAsAction->setShortcut(QKeySequence::SaveAs);
connect(saveAsAction, &QAction::triggered,
this, &ConfigMainWindow::saveConfigAs);
QAction *searchAction = new QAction("&Find", this);
- searchAction->setShortcut(Qt::CTRL | Qt::Key_F);
+ searchAction->setShortcut(QKeySequence::Find);
connect(searchAction, &QAction::triggered,
this, &ConfigMainWindow::searchConfig);
singleViewAction = new QAction(QPixmap(xpm_single_view), "Single View", this);
@@ -1505,6 +1437,9 @@ ConfigMainWindow::ConfigMainWindow(void)
connect(helpText, &ConfigInfoView::menuSelected,
this, &ConfigMainWindow::setMenuLink);
+ connect(configApp, &QApplication::aboutToQuit,
+ this, &ConfigMainWindow::saveSettings);
+
conf_read(NULL);
QString listMode = configSettings->value("/listMode", "symbol").toString();
@@ -1528,28 +1463,22 @@ ConfigMainWindow::ConfigMainWindow(void)
void ConfigMainWindow::loadConfig(void)
{
QString str;
- QByteArray ba;
- const char *name;
str = QFileDialog::getOpenFileName(this, "", configname);
if (str.isNull())
return;
- ba = str.toLocal8Bit();
- name = ba.data();
-
- if (conf_read(name))
+ if (conf_read(str.toLocal8Bit().constData()))
QMessageBox::information(this, "qconf", "Unable to load configuration!");
- free(configname);
- configname = xstrdup(name);
+ configname = str;
ConfigList::updateListAllForAll();
}
bool ConfigMainWindow::saveConfig(void)
{
- if (conf_write(configname)) {
+ if (conf_write(configname.toLocal8Bit().constData())) {
QMessageBox::information(this, "qconf", "Unable to save configuration!");
return false;
}
@@ -1561,23 +1490,17 @@ bool ConfigMainWindow::saveConfig(void)
void ConfigMainWindow::saveConfigAs(void)
{
QString str;
- QByteArray ba;
- const char *name;
str = QFileDialog::getSaveFileName(this, "", configname);
if (str.isNull())
return;
- ba = str.toLocal8Bit();
- name = ba.data();
-
- if (conf_write(name)) {
+ if (conf_write(str.toLocal8Bit().constData())) {
QMessageBox::information(this, "qconf", "Unable to save configuration!");
}
conf_write_autoconf(0);
- free(configname);
- configname = xstrdup(name);
+ configname = str;
}
void ConfigMainWindow::searchConfig(void)
@@ -1662,9 +1585,6 @@ void ConfigMainWindow::listFocusChanged(void)
void ConfigMainWindow::goBack(void)
{
- if (configList->rootEntry == &rootmenu)
- return;
-
configList->setParentMenu();
}
@@ -1905,8 +1825,6 @@ int main(int ac, char** av)
v = new ConfigMainWindow();
//zconfdump(stdout);
- configApp->connect(configApp, SIGNAL(lastWindowClosed()), SLOT(quit()));
- configApp->connect(configApp, SIGNAL(aboutToQuit()), v, SLOT(saveSettings()));
v->show();
configApp->exec();
diff --git a/scripts/kconfig/qconf.h b/scripts/kconfig/qconf.h
index 53373064d90a..62ab3286d04f 100644
--- a/scripts/kconfig/qconf.h
+++ b/scripts/kconfig/qconf.h
@@ -55,9 +55,7 @@ public:
protected:
void keyPressEvent(QKeyEvent *e);
- void mousePressEvent(QMouseEvent *e);
void mouseReleaseEvent(QMouseEvent *e);
- void mouseMoveEvent(QMouseEvent *e);
void mouseDoubleClickEvent(QMouseEvent *e);
void focusInEvent(QFocusEvent *e);
void contextMenuEvent(QContextMenuEvent *e);
@@ -116,25 +114,25 @@ public:
class ConfigItem : public QTreeWidgetItem {
typedef class QTreeWidgetItem Parent;
public:
- ConfigItem(ConfigList *parent, ConfigItem *after, struct menu *m, bool v)
- : Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false)
+ ConfigItem(ConfigList *parent, ConfigItem *after, struct menu *m)
+ : Parent(parent, after), nextItem(0), menu(m), goParent(false)
{
init();
}
- ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m, bool v)
- : Parent(parent, after), nextItem(0), menu(m), visible(v), goParent(false)
+ ConfigItem(ConfigItem *parent, ConfigItem *after, struct menu *m)
+ : Parent(parent, after), nextItem(0), menu(m), goParent(false)
{
init();
}
- ConfigItem(ConfigList *parent, ConfigItem *after, bool v)
- : Parent(parent, after), nextItem(0), menu(0), visible(v), goParent(true)
+ ConfigItem(ConfigList *parent, ConfigItem *after)
+ : Parent(parent, after), nextItem(0), menu(0), goParent(true)
{
init();
}
~ConfigItem(void);
void init(void);
void updateMenu(void);
- void testUpdateMenu(bool v);
+ void testUpdateMenu(void);
ConfigList* listView() const
{
return (ConfigList*)Parent::treeWidget();
@@ -161,7 +159,6 @@ public:
ConfigItem* nextItem;
struct menu *menu;
- bool visible;
bool goParent;
static QIcon symbolYesIcon, symbolModIcon, symbolNoIcon;
@@ -237,7 +234,7 @@ protected:
class ConfigMainWindow : public QMainWindow {
Q_OBJECT
- char *configname;
+ QString configname;
static QAction *saveAction;
static void conf_changed(bool);
public:
diff --git a/scripts/kconfig/streamline_config.pl b/scripts/kconfig/streamline_config.pl
index d51cd7ac15d2..8e23faab5d22 100755
--- a/scripts/kconfig/streamline_config.pl
+++ b/scripts/kconfig/streamline_config.pl
@@ -144,6 +144,7 @@ my %selects;
my %prompts;
my %objects;
my %config2kfile;
+my %defaults;
my $var;
my $iflevel = 0;
my @ifdeps;
@@ -220,8 +221,9 @@ sub read_kconfig {
$depends{$config} = $1;
} elsif ($state eq "DEP" && /^\s*depends\s+on\s+(.*)$/) {
$depends{$config} .= " " . $1;
- } elsif ($state eq "DEP" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) {
+ } elsif ($state ne "NONE" && /^\s*def(_(bool|tristate)|ault)\s+(\S.*)$/) {
my $dep = $3;
+ $defaults{$config} = 1;
if ($dep !~ /^\s*(y|m|n)\s*$/) {
$dep =~ s/.*\sif\s+//;
$depends{$config} .= " " . $dep;
@@ -503,7 +505,7 @@ sub parse_config_selects
# Check if something other than a module selects this config
if (defined($orig_configs{$conf}) && $orig_configs{$conf} ne "m") {
- dprint "$conf (non module) selects config, we are good\n";
+ dprint "$conf (non module) selects $config, we are good\n";
# we are good with this
return;
}
@@ -523,8 +525,16 @@ sub parse_config_selects
# If no possible config selected this, then something happened.
if (!defined($next_config)) {
- print STDERR "WARNING: $config is required, but nothing in the\n";
- print STDERR " current config selects it.\n";
+
+ # Some config options have no prompt, and nothing selects them, but
+ # they stay turned on once the final checks for the configs
+ # are done. These configs have a default option, so turn off the
+ # warnings for configs with default options.
+ if (!defined($defaults{$config})) {
+ print STDERR "WARNING: $config is required, but nothing in the\n";
+ print STDERR " current config selects it.\n";
+ }
+
return;
}
diff --git a/scripts/kconfig/symbol.c b/scripts/kconfig/symbol.c
index a3af93aaaf32..89b84bf8e21f 100644
--- a/scripts/kconfig/symbol.c
+++ b/scripts/kconfig/symbol.c
@@ -71,6 +71,24 @@ const char *sym_type_name(enum symbol_type type)
}
/**
+ * sym_get_prompt_menu - get the menu entry with a prompt
+ *
+ * @sym: a symbol pointer
+ *
+ * Return: the menu entry with a prompt.
+ */
+struct menu *sym_get_prompt_menu(const struct symbol *sym)
+{
+ struct menu *m;
+
+ list_for_each_entry(m, &sym->menus, link)
+ if (m->prompt)
+ return m;
+
+ return NULL;
+}
+
+/**
* sym_get_choice_menu - get the parent choice menu if present
*
* @sym: a symbol pointer
@@ -80,18 +98,12 @@ const char *sym_type_name(enum symbol_type type)
struct menu *sym_get_choice_menu(const struct symbol *sym)
{
struct menu *menu = NULL;
- struct menu *m;
/*
* Choice members must have a prompt. Find a menu entry with a prompt,
* and assume it resides inside a choice block.
*/
- list_for_each_entry(m, &sym->menus, link)
- if (m->prompt) {
- menu = m;
- break;
- }
-
+ menu = sym_get_prompt_menu(sym);
if (!menu)
return NULL;
diff --git a/scripts/kernel-doc b/scripts/kernel-doc
index f66070176ba3..4ee843d3600e 100755
--- a/scripts/kernel-doc
+++ b/scripts/kernel-doc
@@ -267,7 +267,7 @@ my $doc_inline_sect = '\s*\*\s*(@\s*[\w][\w\.]*\s*):(.*)';
my $doc_inline_end = '^\s*\*/\s*$';
my $doc_inline_oneline = '^\s*/\*\*\s*(@[\w\s]+):\s*(.*)\s*\*/\s*$';
my $export_symbol = '^\s*EXPORT_SYMBOL(_GPL)?\s*\(\s*(\w+)\s*\)\s*;';
-my $export_symbol_ns = '^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,\s*\w+\)\s*;';
+my $export_symbol_ns = '^\s*EXPORT_SYMBOL_NS(_GPL)?\s*\(\s*(\w+)\s*,\s*"\S+"\)\s*;';
my $function_pointer = qr{([^\(]*\(\*)\s*\)\s*\(([^\)]*)\)};
my $attribute = qr{__attribute__\s*\(\([a-z0-9,_\*\s\(\)]*\)\)}i;
diff --git a/scripts/link-vmlinux.sh b/scripts/link-vmlinux.sh
index a3c634b2f348..d853ddb3b28c 100755
--- a/scripts/link-vmlinux.sh
+++ b/scripts/link-vmlinux.sh
@@ -68,6 +68,10 @@ vmlinux_link()
libs="${KBUILD_VMLINUX_LIBS}"
fi
+ if is_enabled CONFIG_GENERIC_BUILTIN_DTB; then
+ objs="${objs} .builtin-dtbs.o"
+ fi
+
if is_enabled CONFIG_MODULES; then
objs="${objs} .vmlinux.export.o"
fi
@@ -208,8 +212,8 @@ kallsymso=
strip_debug=
if is_enabled CONFIG_KALLSYMS; then
- true > .tmp_vmlinux.kallsyms0.syms
- kallsyms .tmp_vmlinux.kallsyms0.syms .tmp_vmlinux0.kallsyms
+ true > .tmp_vmlinux0.syms
+ kallsyms .tmp_vmlinux0.syms .tmp_vmlinux0.kallsyms
fi
if is_enabled CONFIG_KALLSYMS || is_enabled CONFIG_DEBUG_INFO_BTF; then
@@ -236,14 +240,14 @@ if is_enabled CONFIG_KALLSYMS; then
# Generate section listing all symbols and add it into vmlinux
# It's a four step process:
# 0) Generate a dummy __kallsyms with empty symbol list.
- # 1) Link .tmp_vmlinux.kallsyms1 so it has all symbols and sections,
+ # 1) Link .tmp_vmlinux1.kallsyms so it has all symbols and sections,
# with a dummy __kallsyms.
- # Running kallsyms on that gives us .tmp_kallsyms1.o with
+ # Running kallsyms on that gives us .tmp_vmlinux1.kallsyms.o with
# the right size
- # 2) Link .tmp_vmlinux.kallsyms2 so it now has a __kallsyms section of
+ # 2) Link .tmp_vmlinux2.kallsyms so it now has a __kallsyms section of
# the right size, but due to the added section, some
# addresses have shifted.
- # From here, we generate a correct .tmp_vmlinux.kallsyms2.o
+ # From here, we generate a correct .tmp_vmlinux2.kallsyms.o
# 3) That link may have expanded the kernel image enough that
# more linker branch stubs / trampolines had to be added, which
# introduces new names, which further expands kallsyms. Do another
diff --git a/scripts/mksysmap b/scripts/mksysmap
index c12723a04655..3accbdb269ac 100755
--- a/scripts/mksysmap
+++ b/scripts/mksysmap
@@ -26,7 +26,7 @@
# (do not forget a space before each pattern)
# local symbols for ARM, MIPS, etc.
-/ \\$/d
+/ \$/d
# local labels, .LBB, .Ltmpxxx, .L__unnamed_xx, .LASANPC, etc.
/ \.L/d
@@ -39,7 +39,7 @@
/ __pi_\.L/d
# arm64 local symbols in non-VHE KVM namespace
-/ __kvm_nvhe_\\$/d
+/ __kvm_nvhe_\$/d
/ __kvm_nvhe_\.L/d
# lld arm/aarch64/mips thunks
diff --git a/scripts/mod/file2alias.c b/scripts/mod/file2alias.c
index c4cc11aa558f..19ec72a69e90 100644
--- a/scripts/mod/file2alias.c
+++ b/scripts/mod/file2alias.c
@@ -10,6 +10,12 @@
* of the GNU General Public License, incorporated herein by reference.
*/
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "list.h"
+#include "xalloc.h"
+
#include "modpost.h"
#include "devicetable-offsets.h"
@@ -31,6 +37,66 @@ typedef Elf64_Addr kernel_ulong_t;
#include <ctype.h>
#include <stdbool.h>
+/**
+ * module_alias_printf - add auto-generated MODULE_ALIAS()
+ *
+ * @mod: module
+ * @append_wildcard: append '*' for future extension if not exist yet
+ * @fmt: printf(3)-like format
+ */
+static void __attribute__((format (printf, 3, 4)))
+module_alias_printf(struct module *mod, bool append_wildcard,
+ const char *fmt, ...)
+{
+ struct module_alias *new, *als;
+ size_t len;
+ int n;
+ va_list ap;
+
+ /* Determine required size. */
+ va_start(ap, fmt);
+ n = vsnprintf(NULL, 0, fmt, ap);
+ va_end(ap);
+
+ if (n < 0) {
+ error("vsnprintf failed\n");
+ return;
+ }
+
+ len = n + 1; /* extra byte for '\0' */
+
+ if (append_wildcard)
+ len++; /* extra byte for '*' */
+
+ new = xmalloc(sizeof(*new) + len);
+
+ /* Now, really print it to the allocated buffer */
+ va_start(ap, fmt);
+ n = vsnprintf(new->str, len, fmt, ap);
+ va_end(ap);
+
+ if (n < 0) {
+ error("vsnprintf failed\n");
+ free(new);
+ return;
+ }
+
+ if (append_wildcard && (n == 0 || new->str[n - 1] != '*')) {
+ new->str[n] = '*';
+ new->str[n + 1] = '\0';
+ }
+
+ /* avoid duplication */
+ list_for_each_entry(als, &mod->aliases, node) {
+ if (!strcmp(als->str, new->str)) {
+ free(new);
+ return;
+ }
+ }
+
+ list_add_tail(&new->node, &mod->aliases);
+}
+
typedef uint32_t __u32;
typedef uint16_t __u16;
typedef unsigned char __u8;
@@ -56,35 +122,25 @@ typedef struct {
* we handle those differences explicitly below */
#include "../../include/linux/mod_devicetable.h"
-/* This array collects all instances that use the generic do_table */
struct devtable {
- const char *device_id; /* name of table, __mod_<name>__*_device_table. */
+ const char *device_id;
unsigned long id_size;
- int (*do_entry)(const char *filename, void *symval, char *alias);
+ void (*do_entry)(struct module *mod, void *symval);
};
-/* Size of alias provided to do_entry functions */
-#define ALIAS_SIZE 500
-
/* Define a variable f that holds the value of field f of struct devid
* based at address m.
*/
#define DEF_FIELD(m, devid, f) \
- typeof(((struct devid *)0)->f) f = TO_NATIVE(*(typeof(f) *)((m) + OFF_##devid##_##f))
-
-/* Define a variable v that holds the address of field f of struct devid
- * based at address m. Due to the way typeof works, for a field of type
- * T[N] the variable has type T(*)[N], _not_ T*.
- */
-#define DEF_FIELD_ADDR_VAR(m, devid, f, v) \
- typeof(((struct devid *)0)->f) *v = ((m) + OFF_##devid##_##f)
+ typeof(((struct devid *)0)->f) f = \
+ get_unaligned_native((typeof(f) *)((m) + OFF_##devid##_##f))
/* Define a variable f that holds the address of field f of struct devid
* based at address m. Due to the way typeof works, for a field of type
* T[N] the variable has type T(*)[N], _not_ T*.
*/
#define DEF_FIELD_ADDR(m, devid, f) \
- DEF_FIELD_ADDR_VAR(m, devid, f, f)
+ typeof(((struct devid *)0)->f) *f = ((m) + OFF_##devid##_##f)
#define ADD(str, sep, cond, field) \
do { \
@@ -99,15 +155,6 @@ do { \
sprintf(str + strlen(str), "*"); \
} while(0)
-/* End in a wildcard, for future extension */
-static inline void add_wildcard(char *str)
-{
- int len = strlen(str);
-
- if (str[len - 1] != '*')
- strcat(str + len, "*");
-}
-
static inline void add_uuid(char *str, uuid_le uuid)
{
int len = strlen(str);
@@ -130,40 +177,6 @@ static inline void add_guid(char *str, guid_t guid)
guid.b[12], guid.b[13], guid.b[14], guid.b[15]);
}
-/**
- * Check that sizeof(device_id type) are consistent with size of section
- * in .o file. If in-consistent then userspace and kernel does not agree
- * on actual size which is a bug.
- * Also verify that the final entry in the table is all zeros.
- * Ignore both checks if build host differ from target host and size differs.
- **/
-static void device_id_check(const char *modname, const char *device_id,
- unsigned long size, unsigned long id_size,
- void *symval)
-{
- int i;
-
- if (size % id_size || size < id_size) {
- fatal("%s: sizeof(struct %s_device_id)=%lu is not a modulo of the size of section __mod_%s__<identifier>_device_table=%lu.\n"
- "Fix definition of struct %s_device_id in mod_devicetable.h\n",
- modname, device_id, id_size, device_id, size, device_id);
- }
- /* Verify last one is a terminator */
- for (i = 0; i < id_size; i++ ) {
- if (*(uint8_t*)(symval+size-id_size+i)) {
- fprintf(stderr,
- "%s: struct %s_device_id is %lu bytes. The last of %lu is:\n",
- modname, device_id, id_size, size / id_size);
- for (i = 0; i < id_size; i++ )
- fprintf(stderr,"0x%02x ",
- *(uint8_t*)(symval+size-id_size+i) );
- fprintf(stderr,"\n");
- fatal("%s: struct %s_device_id is not terminated with a NULL entry!\n",
- modname, device_id);
- }
- }
-}
-
/* USB is special because the bcdDevice can be matched against a numeric range */
/* Looks like "usb:vNpNdNdcNdscNdpNicNiscNipNinN" */
static void do_usb_entry(void *symval,
@@ -229,9 +242,7 @@ static void do_usb_entry(void *symval,
ADD(alias, "in", match_flags&USB_DEVICE_ID_MATCH_INT_NUMBER,
bInterfaceNumber);
- add_wildcard(alias);
- buf_printf(&mod->dev_table_buf,
- "MODULE_ALIAS(\"%s\");\n", alias);
+ module_alias_printf(mod, true, "%s", alias);
}
/* Handles increment/decrement of BCD formatted integers */
@@ -273,7 +284,7 @@ static unsigned int incbcd(unsigned int *bcd,
return init;
}
-static void do_usb_entry_multi(void *symval, struct module *mod)
+static void do_usb_entry_multi(struct module *mod, void *symval)
{
unsigned int devlo, devhi;
unsigned char chi, clo, max;
@@ -338,22 +349,7 @@ static void do_usb_entry_multi(void *symval, struct module *mod)
}
}
-static void do_usb_table(void *symval, unsigned long size,
- struct module *mod)
-{
- unsigned int i;
- const unsigned long id_size = SIZE_usb_device_id;
-
- device_id_check(mod->name, "usb", size, id_size, symval);
-
- /* Leave last one: it's the terminator. */
- size -= id_size;
-
- for (i = 0; i < size; i += id_size)
- do_usb_entry_multi(symval + i, mod);
-}
-
-static void do_of_entry_multi(void *symval, struct module *mod)
+static void do_of_entry(struct module *mod, void *symval)
{
char alias[500];
int len;
@@ -375,56 +371,39 @@ static void do_of_entry_multi(void *symval, struct module *mod)
if (isspace(*tmp))
*tmp = '_';
- buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias);
- strcat(alias, "C");
- add_wildcard(alias);
- buf_printf(&mod->dev_table_buf, "MODULE_ALIAS(\"%s\");\n", alias);
-}
-
-static void do_of_table(void *symval, unsigned long size,
- struct module *mod)
-{
- unsigned int i;
- const unsigned long id_size = SIZE_of_device_id;
-
- device_id_check(mod->name, "of", size, id_size, symval);
-
- /* Leave last one: it's the terminator. */
- size -= id_size;
-
- for (i = 0; i < size; i += id_size)
- do_of_entry_multi(symval + i, mod);
+ module_alias_printf(mod, false, "%s", alias);
+ module_alias_printf(mod, false, "%sC*", alias);
}
/* Looks like: hid:bNvNpN */
-static int do_hid_entry(const char *filename,
- void *symval, char *alias)
+static void do_hid_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, hid_device_id, bus);
DEF_FIELD(symval, hid_device_id, group);
DEF_FIELD(symval, hid_device_id, vendor);
DEF_FIELD(symval, hid_device_id, product);
- sprintf(alias, "hid:");
ADD(alias, "b", bus != HID_BUS_ANY, bus);
ADD(alias, "g", group != HID_GROUP_ANY, group);
ADD(alias, "v", vendor != HID_ANY_ID, vendor);
ADD(alias, "p", product != HID_ANY_ID, product);
- return 1;
+ module_alias_printf(mod, false, "hid:%s", alias);
}
/* Looks like: ieee1394:venNmoNspNverN */
-static int do_ieee1394_entry(const char *filename,
- void *symval, char *alias)
+static void do_ieee1394_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, ieee1394_device_id, match_flags);
DEF_FIELD(symval, ieee1394_device_id, vendor_id);
DEF_FIELD(symval, ieee1394_device_id, model_id);
DEF_FIELD(symval, ieee1394_device_id, specifier_id);
DEF_FIELD(symval, ieee1394_device_id, version);
- strcpy(alias, "ieee1394:");
ADD(alias, "ven", match_flags & IEEE1394_MATCH_VENDOR_ID,
vendor_id);
ADD(alias, "mo", match_flags & IEEE1394_MATCH_MODEL_ID,
@@ -434,14 +413,13 @@ static int do_ieee1394_entry(const char *filename,
ADD(alias, "ver", match_flags & IEEE1394_MATCH_VERSION,
version);
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "ieee1394:%s", alias);
}
/* Looks like: pci:vNdNsvNsdNbcNscNiN or <prefix>_pci:vNdNsvNsdNbcNscNiN. */
-static int do_pci_entry(const char *filename,
- void *symval, char *alias)
+static void do_pci_entry(struct module *mod, void *symval)
{
+ char alias[256];
/* Class field can be divided into these three. */
unsigned char baseclass, subclass, interface,
baseclass_mask, subclass_mask, interface_mask;
@@ -464,7 +442,6 @@ static int do_pci_entry(const char *filename,
default:
warn("Unknown PCI driver_override alias %08X\n",
override_only);
- return 0;
}
ADD(alias, "v", vendor != PCI_ANY_ID, vendor);
@@ -483,28 +460,28 @@ static int do_pci_entry(const char *filename,
|| (subclass_mask != 0 && subclass_mask != 0xFF)
|| (interface_mask != 0 && interface_mask != 0xFF)) {
warn("Can't handle masks in %s:%04X\n",
- filename, class_mask);
- return 0;
+ mod->name, class_mask);
+ return;
}
ADD(alias, "bc", baseclass_mask == 0xFF, baseclass);
ADD(alias, "sc", subclass_mask == 0xFF, subclass);
ADD(alias, "i", interface_mask == 0xFF, interface);
- add_wildcard(alias);
- return 1;
+
+ module_alias_printf(mod, true, "%s", alias);
}
/* looks like: "ccw:tNmNdtNdmN" */
-static int do_ccw_entry(const char *filename,
- void *symval, char *alias)
+static void do_ccw_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, ccw_device_id, match_flags);
DEF_FIELD(symval, ccw_device_id, cu_type);
DEF_FIELD(symval, ccw_device_id, cu_model);
DEF_FIELD(symval, ccw_device_id, dev_type);
DEF_FIELD(symval, ccw_device_id, dev_model);
- strcpy(alias, "ccw:");
ADD(alias, "t", match_flags&CCW_DEVICE_ID_MATCH_CU_TYPE,
cu_type);
ADD(alias, "m", match_flags&CCW_DEVICE_ID_MATCH_CU_MODEL,
@@ -513,47 +490,42 @@ static int do_ccw_entry(const char *filename,
dev_type);
ADD(alias, "dm", match_flags&CCW_DEVICE_ID_MATCH_DEVICE_MODEL,
dev_model);
- add_wildcard(alias);
- return 1;
+
+ module_alias_printf(mod, true, "ccw:%s", alias);
}
/* looks like: "ap:tN" */
-static int do_ap_entry(const char *filename,
- void *symval, char *alias)
+static void do_ap_entry(struct module *mod, void *symval)
{
DEF_FIELD(symval, ap_device_id, dev_type);
- sprintf(alias, "ap:t%02X*", dev_type);
- return 1;
+ module_alias_printf(mod, false, "ap:t%02X*", dev_type);
}
/* looks like: "css:tN" */
-static int do_css_entry(const char *filename,
- void *symval, char *alias)
+static void do_css_entry(struct module *mod, void *symval)
{
DEF_FIELD(symval, css_device_id, type);
- sprintf(alias, "css:t%01X", type);
- return 1;
+ module_alias_printf(mod, false, "css:t%01X", type);
}
/* Looks like: "serio:tyNprNidNexN" */
-static int do_serio_entry(const char *filename,
- void *symval, char *alias)
+static void do_serio_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, serio_device_id, type);
DEF_FIELD(symval, serio_device_id, proto);
DEF_FIELD(symval, serio_device_id, id);
DEF_FIELD(symval, serio_device_id, extra);
- strcpy(alias, "serio:");
ADD(alias, "ty", type != SERIO_ANY, type);
ADD(alias, "pr", proto != SERIO_ANY, proto);
ADD(alias, "id", id != SERIO_ANY, id);
ADD(alias, "ex", extra != SERIO_ANY, extra);
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "serio:%s", alias);
}
/* looks like: "acpi:ACPI0003" or "acpi:PNP0C0B" or "acpi:LNXVIDEO" or
@@ -563,21 +535,19 @@ static int do_serio_entry(const char *filename,
* or _CLS. Also, bb, ss, and pp can be substituted with ??
* as don't care byte.
*/
-static int do_acpi_entry(const char *filename,
- void *symval, char *alias)
+static void do_acpi_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, acpi_device_id, id);
DEF_FIELD(symval, acpi_device_id, cls);
DEF_FIELD(symval, acpi_device_id, cls_msk);
- if (id && strlen((const char *)*id))
- sprintf(alias, "acpi*:%s:*", *id);
+ if ((*id)[0])
+ module_alias_printf(mod, false, "acpi*:%s:*", *id);
else {
+ char alias[256];
int i, byte_shift, cnt = 0;
unsigned int msk;
- sprintf(&alias[cnt], "acpi*:");
- cnt = 6;
for (i = 1; i <= 3; i++) {
byte_shift = 8 * (3-i);
msk = (cls_msk >> byte_shift) & 0xFF;
@@ -588,102 +558,50 @@ static int do_acpi_entry(const char *filename,
sprintf(&alias[cnt], "??");
cnt += 2;
}
- sprintf(&alias[cnt], ":*");
+ module_alias_printf(mod, false, "acpi*:%s:*", alias);
}
- return 1;
}
/* looks like: "pnp:dD" */
-static void do_pnp_device_entry(void *symval, unsigned long size,
- struct module *mod)
+static void do_pnp_device_entry(struct module *mod, void *symval)
{
- const unsigned long id_size = SIZE_pnp_device_id;
- const unsigned int count = (size / id_size)-1;
- unsigned int i;
-
- device_id_check(mod->name, "pnp", size, id_size, symval);
-
- for (i = 0; i < count; i++) {
- DEF_FIELD_ADDR(symval + i*id_size, pnp_device_id, id);
- char acpi_id[sizeof(*id)];
- int j;
+ DEF_FIELD_ADDR(symval, pnp_device_id, id);
+ char acpi_id[sizeof(*id)];
- buf_printf(&mod->dev_table_buf,
- "MODULE_ALIAS(\"pnp:d%s*\");\n", *id);
-
- /* fix broken pnp bus lowercasing */
- for (j = 0; j < sizeof(acpi_id); j++)
- acpi_id[j] = toupper((*id)[j]);
- buf_printf(&mod->dev_table_buf,
- "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
- }
+ /* fix broken pnp bus lowercasing */
+ for (unsigned int i = 0; i < sizeof(acpi_id); i++)
+ acpi_id[i] = toupper((*id)[i]);
+ module_alias_printf(mod, false, "pnp:d%s*", *id);
+ module_alias_printf(mod, false, "acpi*:%s:*", acpi_id);
}
/* looks like: "pnp:dD" for every device of the card */
-static void do_pnp_card_entries(void *symval, unsigned long size,
- struct module *mod)
+static void do_pnp_card_entry(struct module *mod, void *symval)
{
- const unsigned long id_size = SIZE_pnp_card_device_id;
- const unsigned int count = (size / id_size)-1;
- unsigned int i;
-
- device_id_check(mod->name, "pnp", size, id_size, symval);
-
- for (i = 0; i < count; i++) {
- unsigned int j;
- DEF_FIELD_ADDR(symval + i * id_size, pnp_card_device_id, devs);
+ DEF_FIELD_ADDR(symval, pnp_card_device_id, devs);
- for (j = 0; j < PNP_MAX_DEVICES; j++) {
- const char *id = (char *)(*devs)[j].id;
- int i2, j2;
- int dup = 0;
+ for (unsigned int i = 0; i < PNP_MAX_DEVICES; i++) {
+ const char *id = (char *)(*devs)[i].id;
+ char acpi_id[PNP_ID_LEN];
- if (!id[0])
- break;
-
- /* find duplicate, already added value */
- for (i2 = 0; i2 < i && !dup; i2++) {
- DEF_FIELD_ADDR_VAR(symval + i2 * id_size,
- pnp_card_device_id,
- devs, devs_dup);
-
- for (j2 = 0; j2 < PNP_MAX_DEVICES; j2++) {
- const char *id2 =
- (char *)(*devs_dup)[j2].id;
-
- if (!id2[0])
- break;
-
- if (!strcmp(id, id2)) {
- dup = 1;
- break;
- }
- }
- }
-
- /* add an individual alias for every device entry */
- if (!dup) {
- char acpi_id[PNP_ID_LEN];
- int k;
+ if (!id[0])
+ break;
- buf_printf(&mod->dev_table_buf,
- "MODULE_ALIAS(\"pnp:d%s*\");\n", id);
+ /* fix broken pnp bus lowercasing */
+ for (unsigned int j = 0; j < sizeof(acpi_id); j++)
+ acpi_id[j] = toupper(id[j]);
- /* fix broken pnp bus lowercasing */
- for (k = 0; k < sizeof(acpi_id); k++)
- acpi_id[k] = toupper(id[k]);
- buf_printf(&mod->dev_table_buf,
- "MODULE_ALIAS(\"acpi*:%s:*\");\n", acpi_id);
- }
- }
+ /* add an individual alias for every device entry */
+ module_alias_printf(mod, false, "pnp:d%s*", id);
+ module_alias_printf(mod, false, "acpi*:%s:*", acpi_id);
}
}
/* Looks like: pcmcia:mNcNfNfnNpfnNvaNvbNvcNvdN. */
-static int do_pcmcia_entry(const char *filename,
- void *symval, char *alias)
+static void do_pcmcia_entry(struct module *mod, void *symval)
{
- unsigned int i;
+ char alias[256] = {};
+
DEF_FIELD(symval, pcmcia_device_id, match_flags);
DEF_FIELD(symval, pcmcia_device_id, manf_id);
DEF_FIELD(symval, pcmcia_device_id, card_id);
@@ -692,11 +610,6 @@ static int do_pcmcia_entry(const char *filename,
DEF_FIELD(symval, pcmcia_device_id, device_no);
DEF_FIELD_ADDR(symval, pcmcia_device_id, prod_id_hash);
- for (i=0; i<4; i++) {
- (*prod_id_hash)[i] = TO_NATIVE((*prod_id_hash)[i]);
- }
-
- strcpy(alias, "pcmcia:");
ADD(alias, "m", match_flags & PCMCIA_DEV_ID_MATCH_MANF_ID,
manf_id);
ADD(alias, "c", match_flags & PCMCIA_DEV_ID_MATCH_CARD_ID,
@@ -707,18 +620,21 @@ static int do_pcmcia_entry(const char *filename,
function);
ADD(alias, "pfn", match_flags & PCMCIA_DEV_ID_MATCH_DEVICE_NO,
device_no);
- ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1, (*prod_id_hash)[0]);
- ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2, (*prod_id_hash)[1]);
- ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3, (*prod_id_hash)[2]);
- ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4, (*prod_id_hash)[3]);
+ ADD(alias, "pa", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID1,
+ get_unaligned_native(*prod_id_hash + 0));
+ ADD(alias, "pb", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID2,
+ get_unaligned_native(*prod_id_hash + 1));
+ ADD(alias, "pc", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID3,
+ get_unaligned_native(*prod_id_hash + 2));
+ ADD(alias, "pd", match_flags & PCMCIA_DEV_ID_MATCH_PROD_ID4,
+ get_unaligned_native(*prod_id_hash + 3));
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "pcmcia:%s", alias);
}
-static int do_vio_entry(const char *filename, void *symval,
- char *alias)
+static void do_vio_entry(struct module *mod, void *symval)
{
+ char alias[256];
char *tmp;
DEF_FIELD_ADDR(symval, vio_device_id, type);
DEF_FIELD_ADDR(symval, vio_device_id, compat);
@@ -731,8 +647,7 @@ static int do_vio_entry(const char *filename, void *symval,
if (isspace (*tmp))
*tmp = '_';
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "%s", alias);
}
static void do_input(char *alias,
@@ -740,17 +655,17 @@ static void do_input(char *alias,
{
unsigned int i;
- for (i = min / BITS_PER_LONG; i < max / BITS_PER_LONG + 1; i++)
- arr[i] = TO_NATIVE(arr[i]);
- for (i = min; i < max; i++)
- if (arr[i / BITS_PER_LONG] & (1ULL << (i%BITS_PER_LONG)))
+ for (i = min; i <= max; i++)
+ if (get_unaligned_native(arr + i / BITS_PER_LONG) &
+ (1ULL << (i % BITS_PER_LONG)))
sprintf(alias + strlen(alias), "%X,*", i);
}
/* input:b0v0p0e0-eXkXrXaXmXlXsXfXwX where X is comma-separated %02X. */
-static int do_input_entry(const char *filename, void *symval,
- char *alias)
+static void do_input_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, input_device_id, flags);
DEF_FIELD(symval, input_device_id, bustype);
DEF_FIELD(symval, input_device_id, vendor);
@@ -766,8 +681,6 @@ static int do_input_entry(const char *filename, void *symval,
DEF_FIELD_ADDR(symval, input_device_id, ffbit);
DEF_FIELD_ADDR(symval, input_device_id, swbit);
- sprintf(alias, "input:");
-
ADD(alias, "b", flags & INPUT_DEVICE_ID_MATCH_BUS, bustype);
ADD(alias, "v", flags & INPUT_DEVICE_ID_MATCH_VENDOR, vendor);
ADD(alias, "p", flags & INPUT_DEVICE_ID_MATCH_PRODUCT, product);
@@ -802,102 +715,96 @@ static int do_input_entry(const char *filename, void *symval,
sprintf(alias + strlen(alias), "w*");
if (flags & INPUT_DEVICE_ID_MATCH_SWBIT)
do_input(alias, *swbit, 0, INPUT_DEVICE_ID_SW_MAX);
- return 1;
+
+ module_alias_printf(mod, false, "input:%s", alias);
}
-static int do_eisa_entry(const char *filename, void *symval,
- char *alias)
+static void do_eisa_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, eisa_device_id, sig);
- if (sig[0])
- sprintf(alias, EISA_DEVICE_MODALIAS_FMT "*", *sig);
- else
- strcat(alias, "*");
- return 1;
+ module_alias_printf(mod, false, EISA_DEVICE_MODALIAS_FMT "*", *sig);
}
/* Looks like: parisc:tNhvNrevNsvN */
-static int do_parisc_entry(const char *filename, void *symval,
- char *alias)
+static void do_parisc_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, parisc_device_id, hw_type);
DEF_FIELD(symval, parisc_device_id, hversion);
DEF_FIELD(symval, parisc_device_id, hversion_rev);
DEF_FIELD(symval, parisc_device_id, sversion);
- strcpy(alias, "parisc:");
ADD(alias, "t", hw_type != PA_HWTYPE_ANY_ID, hw_type);
ADD(alias, "hv", hversion != PA_HVERSION_ANY_ID, hversion);
ADD(alias, "rev", hversion_rev != PA_HVERSION_REV_ANY_ID, hversion_rev);
ADD(alias, "sv", sversion != PA_SVERSION_ANY_ID, sversion);
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "parisc:%s", alias);
}
/* Looks like: sdio:cNvNdN. */
-static int do_sdio_entry(const char *filename,
- void *symval, char *alias)
+static void do_sdio_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, sdio_device_id, class);
DEF_FIELD(symval, sdio_device_id, vendor);
DEF_FIELD(symval, sdio_device_id, device);
- strcpy(alias, "sdio:");
ADD(alias, "c", class != (__u8)SDIO_ANY_ID, class);
ADD(alias, "v", vendor != (__u16)SDIO_ANY_ID, vendor);
ADD(alias, "d", device != (__u16)SDIO_ANY_ID, device);
- add_wildcard(alias);
- return 1;
+
+ module_alias_printf(mod, true, "sdio:%s", alias);
}
/* Looks like: ssb:vNidNrevN. */
-static int do_ssb_entry(const char *filename,
- void *symval, char *alias)
+static void do_ssb_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, ssb_device_id, vendor);
DEF_FIELD(symval, ssb_device_id, coreid);
DEF_FIELD(symval, ssb_device_id, revision);
- strcpy(alias, "ssb:");
ADD(alias, "v", vendor != SSB_ANY_VENDOR, vendor);
ADD(alias, "id", coreid != SSB_ANY_ID, coreid);
ADD(alias, "rev", revision != SSB_ANY_REV, revision);
- add_wildcard(alias);
- return 1;
+
+ module_alias_printf(mod, true, "ssb:%s", alias);
}
/* Looks like: bcma:mNidNrevNclN. */
-static int do_bcma_entry(const char *filename,
- void *symval, char *alias)
+static void do_bcma_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, bcma_device_id, manuf);
DEF_FIELD(symval, bcma_device_id, id);
DEF_FIELD(symval, bcma_device_id, rev);
DEF_FIELD(symval, bcma_device_id, class);
- strcpy(alias, "bcma:");
ADD(alias, "m", manuf != BCMA_ANY_MANUF, manuf);
ADD(alias, "id", id != BCMA_ANY_ID, id);
ADD(alias, "rev", rev != BCMA_ANY_REV, rev);
ADD(alias, "cl", class != BCMA_ANY_CLASS, class);
- add_wildcard(alias);
- return 1;
+
+ module_alias_printf(mod, true, "bcma:%s", alias);
}
/* Looks like: virtio:dNvN */
-static int do_virtio_entry(const char *filename, void *symval,
- char *alias)
+static void do_virtio_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, virtio_device_id, device);
DEF_FIELD(symval, virtio_device_id, vendor);
- strcpy(alias, "virtio:");
ADD(alias, "d", device != VIRTIO_DEV_ANY_ID, device);
ADD(alias, "v", vendor != VIRTIO_DEV_ANY_ID, vendor);
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "virtio:%s", alias);
}
/*
@@ -905,79 +812,65 @@ static int do_virtio_entry(const char *filename, void *symval,
* Each byte of the guid will be represented by two hex characters
* in the name.
*/
-
-static int do_vmbus_entry(const char *filename, void *symval,
- char *alias)
+static void do_vmbus_entry(struct module *mod, void *symval)
{
- int i;
DEF_FIELD_ADDR(symval, hv_vmbus_device_id, guid);
- char guid_name[(sizeof(*guid) + 1) * 2];
-
- for (i = 0; i < (sizeof(*guid) * 2); i += 2)
- sprintf(&guid_name[i], "%02x", TO_NATIVE((guid->b)[i/2]));
+ char guid_name[sizeof(*guid) * 2 + 1];
- strcpy(alias, "vmbus:");
- strcat(alias, guid_name);
+ for (int i = 0; i < sizeof(*guid); i++)
+ sprintf(&guid_name[i * 2], "%02x", guid->b[i]);
- return 1;
+ module_alias_printf(mod, false, "vmbus:%s", guid_name);
}
/* Looks like: rpmsg:S */
-static int do_rpmsg_entry(const char *filename, void *symval,
- char *alias)
+static void do_rpmsg_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, rpmsg_device_id, name);
- sprintf(alias, RPMSG_DEVICE_MODALIAS_FMT, *name);
- return 1;
+ module_alias_printf(mod, false, RPMSG_DEVICE_MODALIAS_FMT, *name);
}
/* Looks like: i2c:S */
-static int do_i2c_entry(const char *filename, void *symval,
- char *alias)
+static void do_i2c_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, i2c_device_id, name);
- sprintf(alias, I2C_MODULE_PREFIX "%s", *name);
- return 1;
+ module_alias_printf(mod, false, I2C_MODULE_PREFIX "%s", *name);
}
-static int do_i3c_entry(const char *filename, void *symval,
- char *alias)
+static void do_i3c_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, i3c_device_id, match_flags);
DEF_FIELD(symval, i3c_device_id, dcr);
DEF_FIELD(symval, i3c_device_id, manuf_id);
DEF_FIELD(symval, i3c_device_id, part_id);
DEF_FIELD(symval, i3c_device_id, extra_info);
- strcpy(alias, "i3c:");
ADD(alias, "dcr", match_flags & I3C_MATCH_DCR, dcr);
ADD(alias, "manuf", match_flags & I3C_MATCH_MANUF, manuf_id);
ADD(alias, "part", match_flags & I3C_MATCH_PART, part_id);
ADD(alias, "ext", match_flags & I3C_MATCH_EXTRA_INFO, extra_info);
- return 1;
+ module_alias_printf(mod, false, "i3c:%s", alias);
}
-static int do_slim_entry(const char *filename, void *symval, char *alias)
+static void do_slim_entry(struct module *mod, void *symval)
{
DEF_FIELD(symval, slim_device_id, manf_id);
DEF_FIELD(symval, slim_device_id, prod_code);
- sprintf(alias, "slim:%x:%x:*", manf_id, prod_code);
-
- return 1;
+ module_alias_printf(mod, false, "slim:%x:%x:*", manf_id, prod_code);
}
/* Looks like: spi:S */
-static int do_spi_entry(const char *filename, void *symval,
- char *alias)
+static void do_spi_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, spi_device_id, name);
- sprintf(alias, SPI_MODULE_PREFIX "%s", *name);
- return 1;
+ module_alias_printf(mod, false, SPI_MODULE_PREFIX "%s", *name);
}
static const struct dmifield {
@@ -1012,12 +905,11 @@ static void dmi_ascii_filter(char *d, const char *s)
}
-static int do_dmi_entry(const char *filename, void *symval,
- char *alias)
+static void do_dmi_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
int i, j;
DEF_FIELD_ADDR(symval, dmi_system_id, matches);
- sprintf(alias, "dmi*");
for (i = 0; i < ARRAY_SIZE(dmi_fields); i++) {
for (j = 0; j < 4; j++) {
@@ -1032,80 +924,75 @@ static int do_dmi_entry(const char *filename, void *symval,
}
}
- strcat(alias, ":");
- return 1;
+ module_alias_printf(mod, false, "dmi*%s:", alias);
}
-static int do_platform_entry(const char *filename,
- void *symval, char *alias)
+static void do_platform_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, platform_device_id, name);
- sprintf(alias, PLATFORM_MODULE_PREFIX "%s", *name);
- return 1;
+
+ module_alias_printf(mod, false, PLATFORM_MODULE_PREFIX "%s", *name);
}
-static int do_mdio_entry(const char *filename,
- void *symval, char *alias)
+static void do_mdio_entry(struct module *mod, void *symval)
{
+ char id[33];
int i;
DEF_FIELD(symval, mdio_device_id, phy_id);
DEF_FIELD(symval, mdio_device_id, phy_id_mask);
- alias += sprintf(alias, MDIO_MODULE_PREFIX);
-
for (i = 0; i < 32; i++) {
if (!((phy_id_mask >> (31-i)) & 1))
- *(alias++) = '?';
+ id[i] = '?';
else if ((phy_id >> (31-i)) & 1)
- *(alias++) = '1';
+ id[i] = '1';
else
- *(alias++) = '0';
+ id[i] = '0';
}
/* Terminate the string */
- *alias = 0;
+ id[32] = '\0';
- return 1;
+ module_alias_printf(mod, false, MDIO_MODULE_PREFIX "%s", id);
}
/* Looks like: zorro:iN. */
-static int do_zorro_entry(const char *filename, void *symval,
- char *alias)
+static void do_zorro_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
DEF_FIELD(symval, zorro_device_id, id);
- strcpy(alias, "zorro:");
+
ADD(alias, "i", id != ZORRO_WILDCARD, id);
- return 1;
+
+ module_alias_printf(mod, false, "zorro:%s", alias);
}
/* looks like: "pnp:dD" */
-static int do_isapnp_entry(const char *filename,
- void *symval, char *alias)
+static void do_isapnp_entry(struct module *mod, void *symval)
{
DEF_FIELD(symval, isapnp_device_id, vendor);
DEF_FIELD(symval, isapnp_device_id, function);
- sprintf(alias, "pnp:d%c%c%c%x%x%x%x*",
+ module_alias_printf(mod, false, "pnp:d%c%c%c%x%x%x%x*",
'A' + ((vendor >> 2) & 0x3f) - 1,
'A' + (((vendor & 3) << 3) | ((vendor >> 13) & 7)) - 1,
'A' + ((vendor >> 8) & 0x1f) - 1,
(function >> 4) & 0x0f, function & 0x0f,
(function >> 12) & 0x0f, (function >> 8) & 0x0f);
- return 1;
}
/* Looks like: "ipack:fNvNdN". */
-static int do_ipack_entry(const char *filename,
- void *symval, char *alias)
+static void do_ipack_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
DEF_FIELD(symval, ipack_device_id, format);
DEF_FIELD(symval, ipack_device_id, vendor);
DEF_FIELD(symval, ipack_device_id, device);
- strcpy(alias, "ipack:");
+
ADD(alias, "f", format != IPACK_ANY_FORMAT, format);
ADD(alias, "v", vendor != IPACK_ANY_ID, vendor);
ADD(alias, "d", device != IPACK_ANY_ID, device);
- add_wildcard(alias);
- return 1;
+
+ module_alias_printf(mod, true, "ipack:%s", alias);
}
/*
@@ -1156,9 +1043,9 @@ static void append_nibble_mask(char **outp,
* N is exactly 8 digits, where each is an upper-case hex digit, or
* a ? or [] pattern matching exactly one digit.
*/
-static int do_amba_entry(const char *filename,
- void *symval, char *alias)
+static void do_amba_entry(struct module *mod, void *symval)
{
+ char alias[256];
unsigned int digit;
char *p = alias;
DEF_FIELD(symval, amba_id, id);
@@ -1166,15 +1053,14 @@ static int do_amba_entry(const char *filename,
if ((id & mask) != id)
fatal("%s: Masked-off bit(s) of AMBA device ID are non-zero: id=0x%08X, mask=0x%08X. Please fix this driver.\n",
- filename, id, mask);
+ mod->name, id, mask);
- p += sprintf(alias, "amba:d");
for (digit = 0; digit < 8; digit++)
append_nibble_mask(&p,
(id >> (4 * (7 - digit))) & 0xf,
(mask >> (4 * (7 - digit))) & 0xf);
- return 1;
+ module_alias_printf(mod, false, "amba:d%s", alias);
}
/*
@@ -1183,13 +1069,11 @@ static int do_amba_entry(const char *filename,
* N is exactly 2 digits, where each is an upper-case hex digit, or
* a ? or [] pattern matching exactly one digit.
*/
-static int do_mips_cdmm_entry(const char *filename,
- void *symval, char *alias)
+static void do_mips_cdmm_entry(struct module *mod, void *symval)
{
DEF_FIELD(symval, mips_cdmm_device_id, type);
- sprintf(alias, "mipscdmm:t%02X*", type);
- return 1;
+ module_alias_printf(mod, false, "mipscdmm:t%02X*", type);
}
/* LOOKS like cpu:type:x86,venVVVVfamFFFFmodMMMM:feature:*,FEAT,*
@@ -1198,137 +1082,130 @@ static int do_mips_cdmm_entry(const char *filename,
* complicated.
*/
-static int do_x86cpu_entry(const char *filename, void *symval,
- char *alias)
+static void do_x86cpu_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, x86_cpu_id, feature);
DEF_FIELD(symval, x86_cpu_id, family);
DEF_FIELD(symval, x86_cpu_id, model);
DEF_FIELD(symval, x86_cpu_id, vendor);
- strcpy(alias, "cpu:type:x86,");
ADD(alias, "ven", vendor != X86_VENDOR_ANY, vendor);
ADD(alias, "fam", family != X86_FAMILY_ANY, family);
ADD(alias, "mod", model != X86_MODEL_ANY, model);
strcat(alias, ":feature:*");
if (feature != X86_FEATURE_ANY)
sprintf(alias + strlen(alias), "%04X*", feature);
- return 1;
+
+ module_alias_printf(mod, false, "cpu:type:x86,%s", alias);
}
/* LOOKS like cpu:type:*:feature:*FEAT* */
-static int do_cpu_entry(const char *filename, void *symval, char *alias)
+static void do_cpu_entry(struct module *mod, void *symval)
{
DEF_FIELD(symval, cpu_feature, feature);
- sprintf(alias, "cpu:type:*:feature:*%04X*", feature);
- return 1;
+ module_alias_printf(mod, false, "cpu:type:*:feature:*%04X*", feature);
}
/* Looks like: mei:S:uuid:N:* */
-static int do_mei_entry(const char *filename, void *symval,
- char *alias)
+static void do_mei_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD_ADDR(symval, mei_cl_device_id, name);
DEF_FIELD_ADDR(symval, mei_cl_device_id, uuid);
DEF_FIELD(symval, mei_cl_device_id, version);
- sprintf(alias, MEI_CL_MODULE_PREFIX);
- sprintf(alias + strlen(alias), "%s:", (*name)[0] ? *name : "*");
add_uuid(alias, *uuid);
ADD(alias, ":", version != MEI_CL_VERSION_ANY, version);
- strcat(alias, ":*");
-
- return 1;
+ module_alias_printf(mod, false, MEI_CL_MODULE_PREFIX "%s:%s:*",
+ (*name)[0] ? *name : "*", alias);
}
/* Looks like: rapidio:vNdNavNadN */
-static int do_rio_entry(const char *filename,
- void *symval, char *alias)
+static void do_rio_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, rio_device_id, did);
DEF_FIELD(symval, rio_device_id, vid);
DEF_FIELD(symval, rio_device_id, asm_did);
DEF_FIELD(symval, rio_device_id, asm_vid);
- strcpy(alias, "rapidio:");
ADD(alias, "v", vid != RIO_ANY_ID, vid);
ADD(alias, "d", did != RIO_ANY_ID, did);
ADD(alias, "av", asm_vid != RIO_ANY_ID, asm_vid);
ADD(alias, "ad", asm_did != RIO_ANY_ID, asm_did);
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "rapidio:%s", alias);
}
/* Looks like: ulpi:vNpN */
-static int do_ulpi_entry(const char *filename, void *symval,
- char *alias)
+static void do_ulpi_entry(struct module *mod, void *symval)
{
DEF_FIELD(symval, ulpi_device_id, vendor);
DEF_FIELD(symval, ulpi_device_id, product);
- sprintf(alias, "ulpi:v%04xp%04x", vendor, product);
-
- return 1;
+ module_alias_printf(mod, false, "ulpi:v%04xp%04x", vendor, product);
}
/* Looks like: hdaudio:vNrNaN */
-static int do_hda_entry(const char *filename, void *symval, char *alias)
+static void do_hda_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, hda_device_id, vendor_id);
DEF_FIELD(symval, hda_device_id, rev_id);
DEF_FIELD(symval, hda_device_id, api_version);
- strcpy(alias, "hdaudio:");
ADD(alias, "v", vendor_id != 0, vendor_id);
ADD(alias, "r", rev_id != 0, rev_id);
ADD(alias, "a", api_version != 0, api_version);
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "hdaudio:%s", alias);
}
/* Looks like: sdw:mNpNvNcN */
-static int do_sdw_entry(const char *filename, void *symval, char *alias)
+static void do_sdw_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, sdw_device_id, mfg_id);
DEF_FIELD(symval, sdw_device_id, part_id);
DEF_FIELD(symval, sdw_device_id, sdw_version);
DEF_FIELD(symval, sdw_device_id, class_id);
- strcpy(alias, "sdw:");
ADD(alias, "m", mfg_id != 0, mfg_id);
ADD(alias, "p", part_id != 0, part_id);
ADD(alias, "v", sdw_version != 0, sdw_version);
ADD(alias, "c", class_id != 0, class_id);
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "sdw:%s", alias);
}
/* Looks like: fsl-mc:vNdN */
-static int do_fsl_mc_entry(const char *filename, void *symval,
- char *alias)
+static void do_fsl_mc_entry(struct module *mod, void *symval)
{
DEF_FIELD(symval, fsl_mc_device_id, vendor);
DEF_FIELD_ADDR(symval, fsl_mc_device_id, obj_type);
- sprintf(alias, "fsl-mc:v%08Xd%s", vendor, *obj_type);
- return 1;
+ module_alias_printf(mod, false, "fsl-mc:v%08Xd%s", vendor, *obj_type);
}
/* Looks like: tbsvc:kSpNvNrN */
-static int do_tbsvc_entry(const char *filename, void *symval, char *alias)
+static void do_tbsvc_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, tb_service_id, match_flags);
DEF_FIELD_ADDR(symval, tb_service_id, protocol_key);
DEF_FIELD(symval, tb_service_id, protocol_id);
DEF_FIELD(symval, tb_service_id, protocol_version);
DEF_FIELD(symval, tb_service_id, protocol_revision);
- strcpy(alias, "tbsvc:");
if (match_flags & TBSVC_MATCH_PROTOCOL_KEY)
sprintf(alias + strlen(alias), "k%s", *protocol_key);
else
@@ -1339,93 +1216,80 @@ static int do_tbsvc_entry(const char *filename, void *symval, char *alias)
ADD(alias, "r", match_flags & TBSVC_MATCH_PROTOCOL_REVISION,
protocol_revision);
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "tbsvc:%s", alias);
}
/* Looks like: typec:idNmN */
-static int do_typec_entry(const char *filename, void *symval, char *alias)
+static void do_typec_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, typec_device_id, svid);
DEF_FIELD(symval, typec_device_id, mode);
- sprintf(alias, "typec:id%04X", svid);
ADD(alias, "m", mode != TYPEC_ANY_MODE, mode);
- return 1;
+ module_alias_printf(mod, false, "typec:id%04X%s", svid, alias);
}
/* Looks like: tee:uuid */
-static int do_tee_entry(const char *filename, void *symval, char *alias)
+static void do_tee_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, tee_client_device_id, uuid);
- sprintf(alias, "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ module_alias_printf(mod, true,
+ "tee:%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
uuid->b[0], uuid->b[1], uuid->b[2], uuid->b[3], uuid->b[4],
uuid->b[5], uuid->b[6], uuid->b[7], uuid->b[8], uuid->b[9],
uuid->b[10], uuid->b[11], uuid->b[12], uuid->b[13], uuid->b[14],
uuid->b[15]);
-
- add_wildcard(alias);
- return 1;
}
/* Looks like: wmi:guid */
-static int do_wmi_entry(const char *filename, void *symval, char *alias)
+static void do_wmi_entry(struct module *mod, void *symval)
{
- int len;
DEF_FIELD_ADDR(symval, wmi_device_id, guid_string);
if (strlen(*guid_string) != UUID_STRING_LEN) {
warn("Invalid WMI device id 'wmi:%s' in '%s'\n",
- *guid_string, filename);
- return 0;
+ *guid_string, mod->name);
+ return;
}
- len = snprintf(alias, ALIAS_SIZE, WMI_MODULE_PREFIX "%s", *guid_string);
- if (len < 0 || len >= ALIAS_SIZE) {
- warn("Could not generate all MODULE_ALIAS's in '%s'\n",
- filename);
- return 0;
- }
- return 1;
+ module_alias_printf(mod, false, WMI_MODULE_PREFIX "%s", *guid_string);
}
/* Looks like: mhi:S */
-static int do_mhi_entry(const char *filename, void *symval, char *alias)
+static void do_mhi_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, mhi_device_id, chan);
- sprintf(alias, MHI_DEVICE_MODALIAS_FMT, *chan);
- return 1;
+ module_alias_printf(mod, false, MHI_DEVICE_MODALIAS_FMT, *chan);
}
/* Looks like: mhi_ep:S */
-static int do_mhi_ep_entry(const char *filename, void *symval, char *alias)
+static void do_mhi_ep_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, mhi_device_id, chan);
- sprintf(alias, MHI_EP_DEVICE_MODALIAS_FMT, *chan);
- return 1;
+ module_alias_printf(mod, false, MHI_EP_DEVICE_MODALIAS_FMT, *chan);
}
/* Looks like: ishtp:{guid} */
-static int do_ishtp_entry(const char *filename, void *symval, char *alias)
+static void do_ishtp_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
DEF_FIELD_ADDR(symval, ishtp_device_id, guid);
- strcpy(alias, ISHTP_MODULE_PREFIX "{");
add_guid(alias, *guid);
- strcat(alias, "}");
- return 1;
+ module_alias_printf(mod, false, ISHTP_MODULE_PREFIX "{%s}", alias);
}
-static int do_auxiliary_entry(const char *filename, void *symval, char *alias)
+static void do_auxiliary_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, auxiliary_device_id, name);
- sprintf(alias, AUXILIARY_MODULE_PREFIX "%s", *name);
- return 1;
+ module_alias_printf(mod, false, AUXILIARY_MODULE_PREFIX "%s", *name);
}
/*
@@ -1433,8 +1297,10 @@ static int do_auxiliary_entry(const char *filename, void *symval, char *alias)
*
* N is exactly 2 digits, where each is an upper-case hex digit.
*/
-static int do_ssam_entry(const char *filename, void *symval, char *alias)
+static void do_ssam_entry(struct module *mod, void *symval)
{
+ char alias[256] = {};
+
DEF_FIELD(symval, ssam_device_id, match_flags);
DEF_FIELD(symval, ssam_device_id, domain);
DEF_FIELD(symval, ssam_device_id, category);
@@ -1442,30 +1308,28 @@ static int do_ssam_entry(const char *filename, void *symval, char *alias)
DEF_FIELD(symval, ssam_device_id, instance);
DEF_FIELD(symval, ssam_device_id, function);
- sprintf(alias, "ssam:d%02Xc%02X", domain, category);
ADD(alias, "t", match_flags & SSAM_MATCH_TARGET, target);
ADD(alias, "i", match_flags & SSAM_MATCH_INSTANCE, instance);
ADD(alias, "f", match_flags & SSAM_MATCH_FUNCTION, function);
- return 1;
+ module_alias_printf(mod, false, "ssam:d%02Xc%02X%s",
+ domain, category, alias);
}
/* Looks like: dfl:tNfN */
-static int do_dfl_entry(const char *filename, void *symval, char *alias)
+static void do_dfl_entry(struct module *mod, void *symval)
{
DEF_FIELD(symval, dfl_device_id, type);
DEF_FIELD(symval, dfl_device_id, feature_id);
- sprintf(alias, "dfl:t%04Xf%04X", type, feature_id);
-
- add_wildcard(alias);
- return 1;
+ module_alias_printf(mod, true, "dfl:t%04Xf%04X", type, feature_id);
}
/* Looks like: cdx:vNdN */
-static int do_cdx_entry(const char *filename, void *symval,
- char *alias)
+static void do_cdx_entry(struct module *mod, void *symval)
{
+ char alias[256];
+
DEF_FIELD(symval, cdx_device_id, vendor);
DEF_FIELD(symval, cdx_device_id, device);
DEF_FIELD(symval, cdx_device_id, subvendor);
@@ -1484,7 +1348,7 @@ static int do_cdx_entry(const char *filename, void *symval,
default:
warn("Unknown CDX driver_override alias %08X\n",
override_only);
- return 0;
+ return;
}
ADD(alias, "v", vendor != CDX_ANY_ID, vendor);
@@ -1493,24 +1357,22 @@ static int do_cdx_entry(const char *filename, void *symval,
ADD(alias, "sd", subdevice != CDX_ANY_ID, subdevice);
ADD(alias, "c", class_mask == 0xFFFFFF, class);
- return 1;
+ module_alias_printf(mod, false, "%s", alias);
}
-static int do_vchiq_entry(const char *filename, void *symval, char *alias)
+static void do_vchiq_entry(struct module *mod, void *symval)
{
DEF_FIELD_ADDR(symval, vchiq_device_id, name);
- sprintf(alias, "vchiq:%s", *name);
- return 1;
+ module_alias_printf(mod, false, "vchiq:%s", *name);
}
/* Looks like: coreboot:tN */
-static int do_coreboot_entry(const char *filename, void *symval, char *alias)
+static void do_coreboot_entry(struct module *mod, void *symval)
{
DEF_FIELD(symval, coreboot_device_id, tag);
- sprintf(alias, "coreboot:t%08X", tag);
- return 1;
+ module_alias_printf(mod, false, "coreboot:t%08X", tag);
}
/* Does namelen bytes of name exactly match the symbol? */
@@ -1522,25 +1384,34 @@ static bool sym_is(const char *name, unsigned namelen, const char *symbol)
return memcmp(name, symbol, namelen) == 0;
}
-static void do_table(void *symval, unsigned long size,
+static void do_table(const char *name, void *symval, unsigned long size,
unsigned long id_size,
const char *device_id,
- int (*do_entry)(const char *filename, void *symval, char *alias),
+ void (*do_entry)(struct module *mod, void *symval),
struct module *mod)
{
unsigned int i;
- char alias[ALIAS_SIZE];
- device_id_check(mod->name, device_id, size, id_size, symval);
- /* Leave last one: it's the terminator. */
- size -= id_size;
+ if (size % id_size || size < id_size) {
+ error("%s: type mismatch between %s[] and MODULE_DEVICE_TABLE(%s, ...)\n",
+ mod->name, name, device_id);
+ return;
+ }
- for (i = 0; i < size; i += id_size) {
- if (do_entry(mod->name, symval+i, alias)) {
- buf_printf(&mod->dev_table_buf,
- "MODULE_ALIAS(\"%s\");\n", alias);
+ /* Verify the last entry is a terminator */
+ for (i = size - id_size; i < size; i++) {
+ if (*(uint8_t *)(symval + i)) {
+ error("%s: %s[] is not terminated with a NULL entry\n",
+ mod->name, name);
+ return;
}
}
+
+ /* Leave last one: it's the terminator. */
+ size -= id_size;
+
+ for (i = 0; i < size; i += id_size)
+ do_entry(mod, symval + i);
}
static const struct devtable devtable[] = {
@@ -1596,6 +1467,10 @@ static const struct devtable devtable[] = {
{"cdx", SIZE_cdx_device_id, do_cdx_entry},
{"vchiq", SIZE_vchiq_device_id, do_vchiq_entry},
{"coreboot", SIZE_coreboot_device_id, do_coreboot_entry},
+ {"of", SIZE_of_device_id, do_of_entry},
+ {"usb", SIZE_usb_device_id, do_usb_entry_multi},
+ {"pnp", SIZE_pnp_device_id, do_pnp_device_entry},
+ {"pnp_card", SIZE_pnp_card_device_id, do_pnp_card_entry},
};
/* Create MODULE_ALIAS() statements.
@@ -1606,8 +1481,9 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
{
void *symval;
char *zeros = NULL;
- const char *name, *identifier;
- unsigned int namelen;
+ const char *type, *name;
+ size_t typelen;
+ static const char *prefix = "__mod_device_table__";
/* We're looking for a section relative symbol */
if (!sym->st_shndx || get_secindex(info, sym) >= info->num_sections)
@@ -1617,19 +1493,16 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT)
return;
- /* All our symbols are of form __mod_<name>__<identifier>_device_table. */
- if (strncmp(symname, "__mod_", strlen("__mod_")))
- return;
- name = symname + strlen("__mod_");
- namelen = strlen(name);
- if (namelen < strlen("_device_table"))
- return;
- if (strcmp(name + namelen - strlen("_device_table"), "_device_table"))
+ /* All our symbols are of form __mod_device_table__<type>__<name>. */
+ if (!strstarts(symname, prefix))
return;
- identifier = strstr(name, "__");
- if (!identifier)
+ type = symname + strlen(prefix);
+
+ name = strstr(type, "__");
+ if (!name)
return;
- namelen = identifier - name;
+ typelen = name - type;
+ name += strlen("__");
/* Handle all-NULL symbols allocated into .bss */
if (info->sechdrs[get_secindex(info, sym)].sh_type & SHT_NOBITS) {
@@ -1639,35 +1512,15 @@ void handle_moddevtable(struct module *mod, struct elf_info *info,
symval = sym_get_data(info, sym);
}
- /* First handle the "special" cases */
- if (sym_is(name, namelen, "usb"))
- do_usb_table(symval, sym->st_size, mod);
- else if (sym_is(name, namelen, "of"))
- do_of_table(symval, sym->st_size, mod);
- else if (sym_is(name, namelen, "pnp"))
- do_pnp_device_entry(symval, sym->st_size, mod);
- else if (sym_is(name, namelen, "pnp_card"))
- do_pnp_card_entries(symval, sym->st_size, mod);
- else {
- int i;
-
- for (i = 0; i < ARRAY_SIZE(devtable); i++) {
- const struct devtable *p = &devtable[i];
+ for (int i = 0; i < ARRAY_SIZE(devtable); i++) {
+ const struct devtable *p = &devtable[i];
- if (sym_is(name, namelen, p->device_id)) {
- do_table(symval, sym->st_size, p->id_size,
- p->device_id, p->do_entry, mod);
- break;
- }
+ if (sym_is(type, typelen, p->device_id)) {
+ do_table(name, symval, sym->st_size, p->id_size,
+ p->device_id, p->do_entry, mod);
+ break;
}
}
- free(zeros);
-}
-/* Now add out buffered information to the generated C source */
-void add_moddevtable(struct buffer *buf, struct module *mod)
-{
- buf_printf(buf, "\n");
- buf_write(buf, mod->dev_table_buf.p, mod->dev_table_buf.pos);
- free(mod->dev_table_buf.p);
+ free(zeros);
}
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 107393a8c48a..7ea59dc4926b 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -21,6 +21,7 @@
#include <stdbool.h>
#include <errno.h>
+#include <hash.h>
#include <hashtable.h>
#include <list.h>
#include <xalloc.h>
@@ -154,12 +155,13 @@ char *get_line(char **stringp)
/* A list of all modules we processed */
LIST_HEAD(modules);
-static struct module *find_module(const char *modname)
+static struct module *find_module(const char *filename, const char *modname)
{
struct module *mod;
list_for_each_entry(mod, &modules, list) {
- if (strcmp(mod->name, modname) == 0)
+ if (!strcmp(mod->dump_file, filename) &&
+ !strcmp(mod->name, modname))
return mod;
}
return NULL;
@@ -176,6 +178,7 @@ static struct module *new_module(const char *name, size_t namelen)
INIT_LIST_HEAD(&mod->unresolved_symbols);
INIT_LIST_HEAD(&mod->missing_namespaces);
INIT_LIST_HEAD(&mod->imported_namespaces);
+ INIT_LIST_HEAD(&mod->aliases);
memcpy(mod->name, name, namelen);
mod->name[namelen] = '\0';
@@ -209,19 +212,6 @@ struct symbol {
static HASHTABLE_DEFINE(symbol_hashtable, 1U << 10);
-/* This is based on the hash algorithm from gdbm, via tdb */
-static inline unsigned int tdb_hash(const char *name)
-{
- unsigned value; /* Used to compute the hash value. */
- unsigned i; /* Used to cycle through random values. */
-
- /* Set the initial value from the key size. */
- for (value = 0x238F13AF * strlen(name), i = 0; name[i]; i++)
- value = (value + (((unsigned char *)name)[i] << (i*5 % 24)));
-
- return (1103515243 * value + 12345);
-}
-
/**
* Allocate a new symbols for use in the hash of exported symbols or
* the list of unresolved symbols per module
@@ -239,7 +229,7 @@ static struct symbol *alloc_symbol(const char *name)
/* For the hash of exported symbols */
static void hash_add_symbol(struct symbol *sym)
{
- hash_add(symbol_hashtable, &sym->hnode, tdb_hash(sym->name));
+ hash_add(symbol_hashtable, &sym->hnode, hash_str(sym->name));
}
static void sym_add_unresolved(const char *name, struct module *mod, bool weak)
@@ -260,7 +250,7 @@ static struct symbol *sym_find_with_module(const char *name, struct module *mod)
if (name[0] == '.')
name++;
- hash_for_each_possible(symbol_hashtable, s, hnode, tdb_hash(name)) {
+ hash_for_each_possible(symbol_hashtable, s, hnode, hash_str(name)) {
if (strcmp(s->name, name) == 0 && (!mod || s->module == mod))
return s;
}
@@ -340,8 +330,6 @@ static const char *sec_name(const struct elf_info *info, unsigned int secindex)
return sech_name(info, &info->sechdrs[secindex]);
}
-#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
-
static struct symbol *sym_add_exported(const char *name, struct module *mod,
bool gpl_only, const char *namespace)
{
@@ -785,7 +773,7 @@ static void check_section(const char *modname, struct elf_info *elf,
".ltext", ".ltext.*"
#define OTHER_TEXT_SECTIONS ".ref.text", ".head.text", ".spinlock.text", \
".fixup", ".entry.text", ".exception.text", \
- ".coldtext", ".softirqentry.text"
+ ".coldtext", ".softirqentry.text", ".irqentry.text"
#define ALL_TEXT_SECTIONS ".init.text", ".exit.text", \
TEXT_SECTIONS, OTHER_TEXT_SECTIONS
@@ -1150,9 +1138,9 @@ static Elf_Addr addend_386_rel(uint32_t *location, unsigned int r_type)
{
switch (r_type) {
case R_386_32:
- return TO_NATIVE(*location);
+ return get_unaligned_native(location);
case R_386_PC32:
- return TO_NATIVE(*location) + 4;
+ return get_unaligned_native(location) + 4;
}
return (Elf_Addr)(-1);
@@ -1173,24 +1161,24 @@ static Elf_Addr addend_arm_rel(void *loc, Elf_Sym *sym, unsigned int r_type)
switch (r_type) {
case R_ARM_ABS32:
case R_ARM_REL32:
- inst = TO_NATIVE(*(uint32_t *)loc);
+ inst = get_unaligned_native((uint32_t *)loc);
return inst + sym->st_value;
case R_ARM_MOVW_ABS_NC:
case R_ARM_MOVT_ABS:
- inst = TO_NATIVE(*(uint32_t *)loc);
+ inst = get_unaligned_native((uint32_t *)loc);
offset = sign_extend32(((inst & 0xf0000) >> 4) | (inst & 0xfff),
15);
return offset + sym->st_value;
case R_ARM_PC24:
case R_ARM_CALL:
case R_ARM_JUMP24:
- inst = TO_NATIVE(*(uint32_t *)loc);
+ inst = get_unaligned_native((uint32_t *)loc);
offset = sign_extend32((inst & 0x00ffffff) << 2, 25);
return offset + sym->st_value + 8;
case R_ARM_THM_MOVW_ABS_NC:
case R_ARM_THM_MOVT_ABS:
- upper = TO_NATIVE(*(uint16_t *)loc);
- lower = TO_NATIVE(*((uint16_t *)loc + 1));
+ upper = get_unaligned_native((uint16_t *)loc);
+ lower = get_unaligned_native((uint16_t *)loc + 1);
offset = sign_extend32(((upper & 0x000f) << 12) |
((upper & 0x0400) << 1) |
((lower & 0x7000) >> 4) |
@@ -1207,8 +1195,8 @@ static Elf_Addr addend_arm_rel(void *loc, Elf_Sym *sym, unsigned int r_type)
* imm11 = lower[10:0]
* imm32 = SignExtend(S:J2:J1:imm6:imm11:'0')
*/
- upper = TO_NATIVE(*(uint16_t *)loc);
- lower = TO_NATIVE(*((uint16_t *)loc + 1));
+ upper = get_unaligned_native((uint16_t *)loc);
+ lower = get_unaligned_native((uint16_t *)loc + 1);
sign = (upper >> 10) & 1;
j1 = (lower >> 13) & 1;
@@ -1231,8 +1219,8 @@ static Elf_Addr addend_arm_rel(void *loc, Elf_Sym *sym, unsigned int r_type)
* I2 = NOT(J2 XOR S)
* imm32 = SignExtend(S:I1:I2:imm10:imm11:'0')
*/
- upper = TO_NATIVE(*(uint16_t *)loc);
- lower = TO_NATIVE(*((uint16_t *)loc + 1));
+ upper = get_unaligned_native((uint16_t *)loc);
+ lower = get_unaligned_native((uint16_t *)loc + 1);
sign = (upper >> 10) & 1;
j1 = (lower >> 13) & 1;
@@ -1253,7 +1241,7 @@ static Elf_Addr addend_mips_rel(uint32_t *location, unsigned int r_type)
{
uint32_t inst;
- inst = TO_NATIVE(*location);
+ inst = get_unaligned_native(location);
switch (r_type) {
case R_MIPS_LO16:
return inst & 0xffff;
@@ -1966,6 +1954,7 @@ static void write_vmlinux_export_c_file(struct module *mod)
static void write_mod_c_file(struct module *mod)
{
struct buffer buf = { };
+ struct module_alias *alias, *next;
char fname[PATH_MAX];
int ret;
@@ -1973,7 +1962,14 @@ static void write_mod_c_file(struct module *mod)
add_exported_symbols(&buf, mod);
add_versions(&buf, mod);
add_depends(&buf, mod);
- add_moddevtable(&buf, mod);
+
+ buf_printf(&buf, "\n");
+ list_for_each_entry_safe(alias, next, &mod->aliases, node) {
+ buf_printf(&buf, "MODULE_ALIAS(\"%s\");\n", alias->str);
+ list_del(&alias->node);
+ free(alias);
+ }
+
add_srcversion(&buf, mod);
ret = snprintf(fname, sizeof(fname), "%s.mod.c", mod->name);
@@ -2035,10 +2031,10 @@ static void read_dump(const char *fname)
continue;
}
- mod = find_module(modname);
+ mod = find_module(fname, modname);
if (!mod) {
mod = new_module(modname, strlen(modname));
- mod->from_dump = true;
+ mod->dump_file = fname;
}
s = sym_add_exported(symname, mod, gpl_only, namespace);
sym_set_crc(s, crc);
@@ -2057,7 +2053,7 @@ static void write_dump(const char *fname)
struct symbol *sym;
list_for_each_entry(mod, &modules, list) {
- if (mod->from_dump)
+ if (mod->dump_file)
continue;
list_for_each_entry(sym, &mod->exported_symbols, list) {
if (trim_unused_exports && !sym->used)
@@ -2081,7 +2077,7 @@ static void write_namespace_deps_files(const char *fname)
list_for_each_entry(mod, &modules, list) {
- if (mod->from_dump || list_empty(&mod->missing_namespaces))
+ if (mod->dump_file || list_empty(&mod->missing_namespaces))
continue;
buf_printf(&ns_deps_buf, "%s.ko:", mod->name);
@@ -2199,7 +2195,7 @@ int main(int argc, char **argv)
read_symbols_from_files(files_source);
list_for_each_entry(mod, &modules, list) {
- if (mod->from_dump || mod->is_vmlinux)
+ if (mod->dump_file || mod->is_vmlinux)
continue;
check_modname_len(mod);
@@ -2210,7 +2206,7 @@ int main(int argc, char **argv)
handle_white_list_exports(unused_exports_white_list);
list_for_each_entry(mod, &modules, list) {
- if (mod->from_dump)
+ if (mod->dump_file)
continue;
if (mod->is_vmlinux)
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h
index ada3a36cc4bc..ffd0a52a606e 100644
--- a/scripts/mod/modpost.h
+++ b/scripts/mod/modpost.h
@@ -65,8 +65,24 @@
#define TO_NATIVE(x) \
(target_is_big_endian == host_is_big_endian ? x : bswap(x))
+#define __get_unaligned_t(type, ptr) ({ \
+ const struct { type x; } __attribute__((__packed__)) *__pptr = \
+ (typeof(__pptr))(ptr); \
+ __pptr->x; \
+})
+
+#define get_unaligned(ptr) __get_unaligned_t(typeof(*(ptr)), (ptr))
+
+#define get_unaligned_native(ptr) \
+({ \
+ typeof(*(ptr)) _val = get_unaligned(ptr); \
+ TO_NATIVE(_val); \
+})
+
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+#define strstarts(str, prefix) (strncmp(str, prefix, strlen(prefix)) == 0)
+
struct buffer {
char *p;
int pos;
@@ -79,22 +95,39 @@ buf_printf(struct buffer *buf, const char *fmt, ...);
void
buf_write(struct buffer *buf, const char *s, int len);
+/**
+ * struct module_alias - auto-generated MODULE_ALIAS()
+ *
+ * @node: linked to module::aliases
+ * @str: a string for MODULE_ALIAS()
+ */
+struct module_alias {
+ struct list_head node;
+ char str[];
+};
+
+/**
+ * struct module - represent a module (vmlinux or *.ko)
+ *
+ * @dump_file: path to the .symvers file if loaded from a file
+ * @aliases: list head for module_aliases
+ */
struct module {
struct list_head list;
struct list_head exported_symbols;
struct list_head unresolved_symbols;
+ const char *dump_file;
bool is_gpl_compatible;
- bool from_dump; /* true if module was loaded from *.symvers */
bool is_vmlinux;
bool seen;
bool has_init;
bool has_cleanup;
- struct buffer dev_table_buf;
char srcversion[25];
// Missing namespace dependencies
struct list_head missing_namespaces;
// Actual imported namespaces
struct list_head imported_namespaces;
+ struct list_head aliases;
char name[];
};
@@ -170,7 +203,6 @@ Elf_Sym *symsearch_find_nearest(struct elf_info *elf, Elf_Addr addr,
/* file2alias.c */
void handle_moddevtable(struct module *mod, struct elf_info *info,
Elf_Sym *sym, const char *symname);
-void add_moddevtable(struct buffer *buf, struct module *mod);
/* sumversion.c */
void get_src_version(const char *modname, char sum[], unsigned sumlen);
diff --git a/scripts/nsdeps b/scripts/nsdeps
index f1718cc0d700..a3372166ac01 100644
--- a/scripts/nsdeps
+++ b/scripts/nsdeps
@@ -19,22 +19,16 @@ if ! { echo "$SPATCH_REQ_VERSION"; echo "$SPATCH_VERSION"; } | sort -CV ; then
exit 1
fi
-if [ "$KBUILD_EXTMOD" ]; then
- src_prefix=
-else
- src_prefix=$srctree/
-fi
-
generate_deps_for_ns() {
$SPATCH --very-quiet --in-place --sp-file \
- $srctree/scripts/coccinelle/misc/add_namespace.cocci -D nsdeps -D ns=$1 $2
+ $srctree/scripts/coccinelle/misc/add_namespace.cocci -D nsdeps -D ns=\"$1\" $2
}
generate_deps() {
local mod=${1%.ko:}
shift
local namespaces="$*"
- local mod_source_files=$(sed "s|^\(.*\)\.o$|${src_prefix}\1.c|" $mod.mod)
+ local mod_source_files=$(sed "s|^\(.*\)\.o$|${srcroot}/\1.c|" $mod.mod)
for ns in $namespaces; do
echo "Adding namespace $ns to module $mod.ko."
@@ -57,4 +51,4 @@ generate_deps() {
while read line
do
generate_deps $line
-done < $MODULES_NSDEPS
+done < modules.nsdeps
diff --git a/scripts/package/PKGBUILD b/scripts/package/PKGBUILD
index f83493838cf9..dca706617adc 100644
--- a/scripts/package/PKGBUILD
+++ b/scripts/package/PKGBUILD
@@ -103,7 +103,7 @@ _package-headers() {
_package-api-headers() {
pkgdesc="Kernel headers sanitized for use in userspace"
- provides=(linux-api-headers)
+ provides=(linux-api-headers="${pkgver}")
conflicts=(linux-api-headers)
_prologue
diff --git a/scripts/package/builddeb b/scripts/package/builddeb
index 441b0bb66e0d..ad7aba0f268e 100755
--- a/scripts/package/builddeb
+++ b/scripts/package/builddeb
@@ -63,6 +63,12 @@ install_linux_image () {
esac
cp "$(${MAKE} -s -f ${srctree}/Makefile image_name)" "${pdir}/${installed_image_path}"
+ if [ "${ARCH}" != um ]; then
+ install_maint_scripts "${pdir}"
+ fi
+}
+
+install_maint_scripts () {
# Install the maintainer scripts
# Note: hook scripts under /etc/kernel are also executed by official Debian
# kernel packages, as well as kernel packages built using make-kpkg.
@@ -96,16 +102,18 @@ install_linux_image_dbg () {
# Parse modules.order directly because 'make modules_install' may sign,
# compress modules, and then run unneeded depmod.
- while read -r mod; do
- mod="${mod%.o}.ko"
- dbg="${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/kernel/${mod}"
- buildid=$("${READELF}" -n "${mod}" | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p')
- link="${pdir}/usr/lib/debug/.build-id/${buildid}.debug"
-
- mkdir -p "${dbg%/*}" "${link%/*}"
- "${OBJCOPY}" --only-keep-debug "${mod}" "${dbg}"
- ln -sf --relative "${dbg}" "${link}"
- done < modules.order
+ if is_enabled CONFIG_MODULES; then
+ while read -r mod; do
+ mod="${mod%.o}.ko"
+ dbg="${pdir}/usr/lib/debug/lib/modules/${KERNELRELEASE}/kernel/${mod}"
+ buildid=$("${READELF}" -n "${mod}" | sed -n 's@^.*Build ID: \(..\)\(.*\)@\1/\2@p')
+ link="${pdir}/usr/lib/debug/.build-id/${buildid}.debug"
+
+ mkdir -p "${dbg%/*}" "${link%/*}"
+ "${OBJCOPY}" --only-keep-debug "${mod}" "${dbg}"
+ ln -sf --relative "${dbg}" "${link}"
+ done < modules.order
+ fi
# Build debug package
# Different tools want the image in different locations
diff --git a/scripts/package/install-extmod-build b/scripts/package/install-extmod-build
index 7ec1f061a519..d3c5b104c063 100755
--- a/scripts/package/install-extmod-build
+++ b/scripts/package/install-extmod-build
@@ -51,6 +51,13 @@ mkdir -p "${destdir}"
if [ "${CC}" != "${HOSTCC}" ]; then
echo "Rebuilding host programs with ${CC}..."
+ # This leverages external module building.
+ # - Clear sub_make_done to allow the top-level Makefile to redo sub-make.
+ # - Filter out --no-print-directory to print "Entering directory" logs
+ # when Make changes the working directory.
+ unset sub_make_done
+ MAKEFLAGS=$(echo "${MAKEFLAGS}" | sed s/--no-print-directory//)
+
cat <<-'EOF' > "${destdir}/Kbuild"
subdir-y := scripts
EOF
@@ -62,7 +69,7 @@ if [ "${CC}" != "${HOSTCC}" ]; then
#
# Use the single-target build to avoid the modpost invocation, which
# would overwrite Module.symvers.
- "${MAKE}" HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
+ "${MAKE}" HOSTCC="${CC}" KBUILD_OUTPUT=. KBUILD_EXTMOD="${destdir}" scripts/
cat <<-'EOF' > "${destdir}/scripts/Kbuild"
subdir-y := basic
@@ -71,7 +78,7 @@ if [ "${CC}" != "${HOSTCC}" ]; then
EOF
# Run once again to rebuild scripts/basic/ and scripts/mod/modpost.
- "${MAKE}" HOSTCC="${CC}" KBUILD_EXTMOD="${destdir}" scripts/
+ "${MAKE}" HOSTCC="${CC}" KBUILD_OUTPUT=. KBUILD_EXTMOD="${destdir}" scripts/
rm -f "${destdir}/Kbuild" "${destdir}/scripts/Kbuild"
fi
diff --git a/scripts/package/mkdebian b/scripts/package/mkdebian
index fc3b7fa709fc..b038a1380b8a 100755
--- a/scripts/package/mkdebian
+++ b/scripts/package/mkdebian
@@ -70,6 +70,13 @@ set_debarch() {
debarch=sh4$(if_enabled_echo CONFIG_CPU_BIG_ENDIAN eb)
fi
;;
+ um)
+ if is_enabled CONFIG_64BIT; then
+ debarch=amd64
+ else
+ debarch=i386
+ fi
+ ;;
esac
if [ -z "$debarch" ]; then
debarch=$(dpkg-architecture -qDEB_HOST_ARCH)
@@ -202,7 +209,7 @@ Build-Depends-Arch: bc, bison, cpio, flex,
gcc-${host_gnu} <!pkg.${sourcename}.nokernelheaders>,
kmod, libelf-dev:native,
libssl-dev:native, libssl-dev <!pkg.${sourcename}.nokernelheaders>,
- rsync
+ python3:native, rsync
Homepage: https://www.kernel.org/
Package: $packagename-$version
diff --git a/scripts/setlocalversion b/scripts/setlocalversion
index 38b96c6797f4..28169d7e143b 100755
--- a/scripts/setlocalversion
+++ b/scripts/setlocalversion
@@ -10,6 +10,8 @@
#
#
+set -e
+
usage() {
echo "Usage: $0 [--no-local] [srctree]" >&2
exit 1
@@ -30,6 +32,29 @@ if test $# -gt 0 -o ! -d "$srctree"; then
usage
fi
+try_tag() {
+ tag="$1"
+
+ # Is $tag an annotated tag?
+ if [ "$(git cat-file -t "$tag" 2> /dev/null)" != tag ]; then
+ return
+ fi
+
+ # Is it an ancestor of HEAD, and if so, how many commits are in $tag..HEAD?
+ # shellcheck disable=SC2046 # word splitting is the point here
+ set -- $(git rev-list --count --left-right "$tag"...HEAD 2> /dev/null)
+
+ # $1 is 0 if and only if $tag is an ancestor of HEAD. Use
+ # string comparison, because $1 is empty if the 'git rev-list'
+ # command somehow failed.
+ if [ "$1" != 0 ]; then
+ return
+ fi
+
+ # $2 is the number of commits in the range $tag..HEAD, possibly 0.
+ count="$2"
+}
+
scm_version()
{
local short=false
@@ -61,33 +86,33 @@ scm_version()
# stable kernel: 6.1.7 -> v6.1.7
version_tag=v$(echo "${KERNELVERSION}" | sed -E 's/^([0-9]+\.[0-9]+)\.0(.*)$/\1\2/')
+ # try_tag initializes count if the tag is usable.
+ count=
+
# If a localversion* file exists, and the corresponding
# annotated tag exists and is an ancestor of HEAD, use
# it. This is the case in linux-next.
- tag=${file_localversion#-}
- desc=
- if [ -n "${tag}" ]; then
- desc=$(git describe --match=$tag 2>/dev/null)
+ if [ -n "${file_localversion#-}" ] ; then
+ try_tag "${file_localversion#-}"
fi
# Otherwise, if a localversion* file exists, and the tag
# obtained by appending it to the tag derived from
# KERNELVERSION exists and is an ancestor of HEAD, use
# it. This is e.g. the case in linux-rt.
- if [ -z "${desc}" ] && [ -n "${file_localversion}" ]; then
- tag="${version_tag}${file_localversion}"
- desc=$(git describe --match=$tag 2>/dev/null)
+ if [ -z "${count}" ] && [ -n "${file_localversion}" ]; then
+ try_tag "${version_tag}${file_localversion}"
fi
# Otherwise, default to the annotated tag derived from KERNELVERSION.
- if [ -z "${desc}" ]; then
- tag="${version_tag}"
- desc=$(git describe --match=$tag 2>/dev/null)
+ if [ -z "${count}" ]; then
+ try_tag "${version_tag}"
fi
- # If we are at the tagged commit, we ignore it because the version is
- # well-defined.
- if [ "${tag}" != "${desc}" ]; then
+ # If we are at the tagged commit, we ignore it because the
+ # version is well-defined. If none of the attempted tags exist
+ # or were usable, $count is still empty.
+ if [ -z "${count}" ] || [ "${count}" -gt 0 ]; then
# If only the short version is requested, don't bother
# running further git commands
@@ -95,14 +120,15 @@ scm_version()
echo "+"
return
fi
+
# If we are past the tagged commit, we pretty print it.
# (like 6.1.0-14595-g292a089d78d3)
- if [ -n "${desc}" ]; then
- echo "${desc}" | awk -F- '{printf("-%05d", $(NF-1))}'
+ if [ -n "${count}" ]; then
+ printf "%s%05d" "-" "${count}"
fi
# Add -g and exactly 12 hex chars.
- printf '%s%s' -g "$(echo $head | cut -c1-12)"
+ printf '%s%.12s' -g "$head"
fi
if ${no_dirty}; then
diff --git a/scripts/sorttable.h b/scripts/sorttable.h
index 7bd0184380d3..a7c5445baf00 100644
--- a/scripts/sorttable.h
+++ b/scripts/sorttable.h
@@ -110,7 +110,7 @@ static inline unsigned long orc_ip(const int *ip)
static int orc_sort_cmp(const void *_a, const void *_b)
{
- struct orc_entry *orc_a;
+ struct orc_entry *orc_a, *orc_b;
const int *a = g_orc_ip_table + *(int *)_a;
const int *b = g_orc_ip_table + *(int *)_b;
unsigned long a_val = orc_ip(a);
@@ -128,6 +128,9 @@ static int orc_sort_cmp(const void *_a, const void *_b)
* whitelisted .o files which didn't get objtool generation.
*/
orc_a = g_orc_table + (a - g_orc_ip_table);
+ orc_b = g_orc_table + (b - g_orc_ip_table);
+ if (orc_a->type == ORC_TYPE_UNDEFINED && orc_b->type == ORC_TYPE_UNDEFINED)
+ return 0;
return orc_a->type == ORC_TYPE_UNDEFINED ? -1 : 1;
}
diff --git a/scripts/tags.sh b/scripts/tags.sh
index 0d01c1cafb70..b21236377998 100755
--- a/scripts/tags.sh
+++ b/scripts/tags.sh
@@ -189,7 +189,7 @@ regex_c=(
'/\<DEFINE_\(RT_MUTEX\|MUTEX\|SEMAPHORE\|SPINLOCK\)([[:space:]]*\([[:alnum:]_]*\)/\2/v/'
'/\<DEFINE_\(RAW_SPINLOCK\|RWLOCK\|SEQLOCK\)([[:space:]]*\([[:alnum:]_]*\)/\2/v/'
'/\<DECLARE_\(RWSEM\|COMPLETION\)([[:space:]]*\([[:alnum:]_]\+\)/\2/v/'
- '/\<DECLARE_BITMAP([[:space:]]*\([[:alnum:]_]*\)/\1/v/'
+ '/\<DECLARE_BITMAP([[:space:]]*\([[:alnum:]_]\+\)/\1/v/'
'/\(^\|\s\)\(\|L\|H\)LIST_HEAD([[:space:]]*\([[:alnum:]_]*\)/\3/v/'
'/\(^\|\s\)RADIX_TREE([[:space:]]*\([[:alnum:]_]*\)/\2/v/'
'/\<DEFINE_PER_CPU([^,]*,[[:space:]]*\([[:alnum:]_]*\)/\1/v/'
@@ -210,6 +210,8 @@ regex_c=(
'/\<\(DEFINE\|DECLARE\)_STATIC_KEY_\(TRUE\|FALSE\)\(\|_RO\)([[:space:]]*\([[:alnum:]_]\+\)/\4/'
'/^SEQCOUNT_LOCKTYPE(\([^,]*\),[[:space:]]*\([^,]*\),[^)]*)/seqcount_\2_t/'
'/^SEQCOUNT_LOCKTYPE(\([^,]*\),[[:space:]]*\([^,]*\),[^)]*)/seqcount_\2_init/'
+ '/^\<DECLARE_IDTENTRY[[:alnum:]_]*([^,)]*,[[:space:]]*\([[:alnum:]_]\+\)/\1/'
+ '/^\<DEFINE_IDTENTRY[[:alnum:]_]*([[:space:]]*\([[:alnum:]_]\+\)/\1/'
)
regex_kconfig=(
'/^[[:blank:]]*\(menu\|\)config[[:blank:]]\+\([[:alnum:]_]\+\)/\2/'
@@ -255,19 +257,29 @@ exuberant()
CTAGS_EXTRA="extras"
fi
setup_regex exuberant asm c
- all_target_sources | xargs $1 -a \
- -I __initdata,__exitdata,__initconst,__ro_after_init \
- -I __initdata_memblock \
- -I __refdata,__attribute,__maybe_unused,__always_unused \
- -I __acquires,__releases,__deprecated,__always_inline \
- -I __read_mostly,__aligned,____cacheline_aligned \
- -I ____cacheline_aligned_in_smp \
- -I __cacheline_aligned,__cacheline_aligned_in_smp \
- -I ____cacheline_internodealigned_in_smp \
- -I __used,__packed,__packed2__,__must_check,__must_hold \
- -I EXPORT_SYMBOL,EXPORT_SYMBOL_GPL,ACPI_EXPORT_SYMBOL \
- -I DEFINE_TRACE,EXPORT_TRACEPOINT_SYMBOL,EXPORT_TRACEPOINT_SYMBOL_GPL \
- -I static,const \
+ # identifiers to ignore by ctags
+ local ign=(
+ ACPI_EXPORT_SYMBOL
+ DEFINE_{TRACE,MUTEX}
+ EXPORT_SYMBOL EXPORT_SYMBOL_GPL
+ EXPORT_TRACEPOINT_SYMBOL EXPORT_TRACEPOINT_SYMBOL_GPL
+ ____cacheline_aligned ____cacheline_aligned_in_smp
+ ____cacheline_internodealigned_in_smp
+ __acquires __aligned __always_inline __always_unused
+ __attribute
+ __cacheline_aligned __cacheline_aligned_in_smp
+ __deprecated
+ __exitdata
+ __initconst __initdata __initdata_memblock
+ __maybe_unused __must_check __must_hold
+ __packed __packed2__
+ __read_mostly __refdata __releases __ro_after_init
+ __used
+ const
+ static
+ )
+ all_target_sources | \
+ xargs $1 -a -I "$(IFS=','; echo "${ign[*]}")" \
--$CTAGS_EXTRA=+fq --c-kinds=+px --fields=+iaS --langmap=c:+.h \
"${regex[@]}"
diff --git a/security/apparmor/apparmorfs.c b/security/apparmor/apparmorfs.c
index 01b923d97a44..2c0185ebc900 100644
--- a/security/apparmor/apparmorfs.c
+++ b/security/apparmor/apparmorfs.c
@@ -2366,6 +2366,7 @@ static struct aa_sfs_entry aa_sfs_entry_policy[] = {
AA_SFS_FILE_U64("outofband", MAX_OOB_SUPPORTED),
AA_SFS_FILE_U64("permstable32_version", 1),
AA_SFS_FILE_STRING("permstable32", PERMS32STR),
+ AA_SFS_FILE_U64("state32", 1),
AA_SFS_DIR("unconfined_restrictions", aa_sfs_entry_unconfined),
{ }
};
diff --git a/security/apparmor/capability.c b/security/apparmor/capability.c
index 9934df16c843..7ca489ee1054 100644
--- a/security/apparmor/capability.c
+++ b/security/apparmor/capability.c
@@ -12,6 +12,7 @@
#include <linux/errno.h>
#include <linux/gfp.h>
#include <linux/security.h>
+#include <linux/timekeeping.h>
#include "include/apparmor.h"
#include "include/capability.h"
@@ -30,8 +31,9 @@ struct aa_sfs_entry aa_sfs_entry_caps[] = {
};
struct audit_cache {
- struct aa_profile *profile;
- kernel_cap_t caps;
+ const struct cred *ad_subj_cred;
+ /* Capabilities go from 0 to CAP_LAST_CAP */
+ u64 ktime_ns_expiration[CAP_LAST_CAP+1];
};
static DEFINE_PER_CPU(struct audit_cache, audit_cache);
@@ -64,6 +66,8 @@ static void audit_cb(struct audit_buffer *ab, void *va)
static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile,
int cap, int error)
{
+ const u64 AUDIT_CACHE_TIMEOUT_NS = 1000*1000*1000; /* 1 second */
+
struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct audit_cache *ent;
@@ -89,15 +93,16 @@ static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile
/* Do simple duplicate message elimination */
ent = &get_cpu_var(audit_cache);
- if (profile == ent->profile && cap_raised(ent->caps, cap)) {
+ /* If the capability was never raised the timestamp check would also catch that */
+ if (ad->subj_cred == ent->ad_subj_cred && ktime_get_ns() <= ent->ktime_ns_expiration[cap]) {
put_cpu_var(audit_cache);
if (COMPLAIN_MODE(profile))
return complain_error(error);
return error;
} else {
- aa_put_profile(ent->profile);
- ent->profile = aa_get_profile(profile);
- cap_raise(ent->caps, cap);
+ put_cred(ent->ad_subj_cred);
+ ent->ad_subj_cred = get_cred(ad->subj_cred);
+ ent->ktime_ns_expiration[cap] = ktime_get_ns() + AUDIT_CACHE_TIMEOUT_NS;
}
put_cpu_var(audit_cache);
@@ -109,7 +114,7 @@ static int audit_caps(struct apparmor_audit_data *ad, struct aa_profile *profile
* @profile: profile being enforced (NOT NULL, NOT unconfined)
* @cap: capability to test if allowed
* @opts: CAP_OPT_NOAUDIT bit determines whether audit record is generated
- * @ad: audit data (MAY BE NULL indicating no auditing)
+ * @ad: audit data (NOT NULL)
*
* Returns: 0 if allowed else -EPERM
*/
diff --git a/security/apparmor/domain.c b/security/apparmor/domain.c
index 2bc34dce9a46..5939bd9a9b9b 100644
--- a/security/apparmor/domain.c
+++ b/security/apparmor/domain.c
@@ -636,6 +636,7 @@ static struct aa_label *profile_transition(const struct cred *subj_cred,
struct aa_ruleset *rules = list_first_entry(&profile->rules,
typeof(*rules), list);
struct aa_label *new = NULL;
+ struct aa_profile *new_profile = NULL;
const char *info = NULL, *name = NULL, *target = NULL;
aa_state_t state = rules->file->start[AA_CLASS_FILE];
struct aa_perms perms = {};
@@ -680,15 +681,18 @@ static struct aa_label *profile_transition(const struct cred *subj_cred,
/* hack ix fallback - improve how this is detected */
goto audit;
} else if (!new) {
- error = -EACCES;
info = "profile transition not found";
- /* remove MAY_EXEC to audit as failure */
+ /* remove MAY_EXEC to audit as failure or complaint */
perms.allow &= ~MAY_EXEC;
+ if (COMPLAIN_MODE(profile)) {
+ /* create null profile instead of failing */
+ goto create_learning_profile;
+ }
+ error = -EACCES;
}
} else if (COMPLAIN_MODE(profile)) {
+create_learning_profile:
/* no exec permission - learning mode */
- struct aa_profile *new_profile = NULL;
-
new_profile = aa_new_learning_profile(profile, false, name,
GFP_KERNEL);
if (!new_profile) {
@@ -709,8 +713,8 @@ static struct aa_label *profile_transition(const struct cred *subj_cred,
if (!(perms.xindex & AA_X_UNSAFE)) {
if (DEBUG_ON) {
- dbg_printk("apparmor: scrubbing environment variables"
- " for %s profile=", name);
+ dbg_printk("apparmor: setting AT_SECURE for %s profile=",
+ name);
aa_label_printk(new, GFP_KERNEL);
dbg_printk("\n");
}
@@ -789,8 +793,8 @@ static int profile_onexec(const struct cred *subj_cred,
if (!(perms.xindex & AA_X_UNSAFE)) {
if (DEBUG_ON) {
- dbg_printk("apparmor: scrubbing environment "
- "variables for %s label=", xname);
+ dbg_printk("apparmor: setting AT_SECURE for %s label=",
+ xname);
aa_label_printk(onexec, GFP_KERNEL);
dbg_printk("\n");
}
@@ -821,33 +825,19 @@ static struct aa_label *handle_onexec(const struct cred *subj_cred,
AA_BUG(!bprm);
AA_BUG(!buffer);
- if (!stack) {
- error = fn_for_each_in_ns(label, profile,
- profile_onexec(subj_cred, profile, onexec, stack,
- bprm, buffer, cond, unsafe));
- if (error)
- return ERR_PTR(error);
- new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
- aa_get_newest_label(onexec),
- profile_transition(subj_cred, profile, bprm,
- buffer,
- cond, unsafe));
-
- } else {
- /* TODO: determine how much we want to loosen this */
- error = fn_for_each_in_ns(label, profile,
- profile_onexec(subj_cred, profile, onexec, stack, bprm,
- buffer, cond, unsafe));
- if (error)
- return ERR_PTR(error);
- new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
- aa_label_merge(&profile->label, onexec,
- GFP_KERNEL),
- profile_transition(subj_cred, profile, bprm,
- buffer,
- cond, unsafe));
- }
+ /* TODO: determine how much we want to loosen this */
+ error = fn_for_each_in_ns(label, profile,
+ profile_onexec(subj_cred, profile, onexec, stack,
+ bprm, buffer, cond, unsafe));
+ if (error)
+ return ERR_PTR(error);
+ new = fn_label_build_in_ns(label, profile, GFP_KERNEL,
+ stack ? aa_label_merge(&profile->label, onexec,
+ GFP_KERNEL)
+ : aa_get_newest_label(onexec),
+ profile_transition(subj_cred, profile, bprm,
+ buffer, cond, unsafe));
if (new)
return new;
@@ -960,8 +950,8 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
if (unsafe) {
if (DEBUG_ON) {
- dbg_printk("scrubbing environment variables for %s "
- "label=", bprm->filename);
+ dbg_printk("setting AT_SECURE for %s label=",
+ bprm->filename);
aa_label_printk(new, GFP_KERNEL);
dbg_printk("\n");
}
@@ -971,8 +961,8 @@ int apparmor_bprm_creds_for_exec(struct linux_binprm *bprm)
if (label->proxy != new->proxy) {
/* when transitioning clear unsafe personality bits */
if (DEBUG_ON) {
- dbg_printk("apparmor: clearing unsafe personality "
- "bits. %s label=", bprm->filename);
+ dbg_printk("apparmor: clearing unsafe personality bits. %s label=",
+ bprm->filename);
aa_label_printk(new, GFP_KERNEL);
dbg_printk("\n");
}
diff --git a/security/apparmor/include/label.h b/security/apparmor/include/label.h
index 2a72e6b17d68..93290ae300bb 100644
--- a/security/apparmor/include/label.h
+++ b/security/apparmor/include/label.h
@@ -160,31 +160,7 @@ int aa_label_next_confined(struct aa_label *l, int i);
#define label_for_each_cont(I, L, P) \
for (++((I).i); ((P) = (L)->vec[(I).i]); ++((I).i))
-#define next_comb(I, L1, L2) \
-do { \
- (I).j++; \
- if ((I).j >= (L2)->size) { \
- (I).i++; \
- (I).j = 0; \
- } \
-} while (0)
-
-/* for each combination of P1 in L1, and P2 in L2 */
-#define label_for_each_comb(I, L1, L2, P1, P2) \
-for ((I).i = (I).j = 0; \
- ((P1) = (L1)->vec[(I).i]) && ((P2) = (L2)->vec[(I).j]); \
- (I) = next_comb(I, L1, L2))
-
-#define fn_for_each_comb(L1, L2, P1, P2, FN) \
-({ \
- struct label_it i; \
- int __E = 0; \
- label_for_each_comb(i, (L1), (L2), (P1), (P2)) { \
- last_error(__E, (FN)); \
- } \
- __E; \
-})
/* for each profile that is enforcing confinement in a label */
#define label_for_each_confined(I, L, P) \
@@ -291,8 +267,6 @@ bool aa_label_replace(struct aa_label *old, struct aa_label *new);
bool aa_label_make_newest(struct aa_labelset *ls, struct aa_label *old,
struct aa_label *new);
-struct aa_label *aa_label_find(struct aa_label *l);
-
struct aa_profile *aa_label_next_in_merge(struct label_it *I,
struct aa_label *a,
struct aa_label *b);
@@ -320,8 +294,6 @@ void aa_label_seq_xprint(struct seq_file *f, struct aa_ns *ns,
struct aa_label *label, int flags, gfp_t gfp);
void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags,
gfp_t gfp);
-void aa_label_audit(struct audit_buffer *ab, struct aa_label *label, gfp_t gfp);
-void aa_label_seq_print(struct seq_file *f, struct aa_label *label, gfp_t gfp);
void aa_label_printk(struct aa_label *label, gfp_t gfp);
struct aa_label *aa_label_strn_parse(struct aa_label *base, const char *str,
diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h
index d7a894b1031f..f11a0db7f51d 100644
--- a/security/apparmor/include/lib.h
+++ b/security/apparmor/include/lib.h
@@ -59,7 +59,6 @@ extern int apparmor_initialized;
/* fn's in lib */
const char *skipn_spaces(const char *str, size_t n);
-char *aa_split_fqname(char *args, char **ns_name);
const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
size_t *ns_len);
void aa_info_message(const char *str);
diff --git a/security/apparmor/include/match.h b/security/apparmor/include/match.h
index 4bb0405c9190..536ce3abd598 100644
--- a/security/apparmor/include/match.h
+++ b/security/apparmor/include/match.h
@@ -87,10 +87,12 @@ struct table_header {
char td_data[];
};
-#define DEFAULT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_DEF]->td_data))
+#define TABLE_DATAU16(TABLE) ((u16 *)((TABLE)->td_data))
+#define TABLE_DATAU32(TABLE) ((u32 *)((TABLE)->td_data))
+#define DEFAULT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_DEF]->td_data))
#define BASE_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_BASE]->td_data))
-#define NEXT_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_NXT]->td_data))
-#define CHECK_TABLE(DFA) ((u16 *)((DFA)->tables[YYTD_ID_CHK]->td_data))
+#define NEXT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_NXT]->td_data))
+#define CHECK_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_CHK]->td_data))
#define EQUIV_TABLE(DFA) ((u8 *)((DFA)->tables[YYTD_ID_EC]->td_data))
#define ACCEPT_TABLE(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT]->td_data))
#define ACCEPT_TABLE2(DFA) ((u32 *)((DFA)->tables[YYTD_ID_ACCEPT2]->td_data))
diff --git a/security/apparmor/include/perms.h b/security/apparmor/include/perms.h
index 0f7e913c3fc2..bbaa7d39a39a 100644
--- a/security/apparmor/include/perms.h
+++ b/security/apparmor/include/perms.h
@@ -213,9 +213,6 @@ void aa_perms_accum_raw(struct aa_perms *accum, struct aa_perms *addend);
void aa_profile_match_label(struct aa_profile *profile,
struct aa_ruleset *rules, struct aa_label *label,
int type, u32 request, struct aa_perms *perms);
-int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
- u32 request, int type, u32 *deny,
- struct apparmor_audit_data *ad);
int aa_check_perms(struct aa_profile *profile, struct aa_perms *perms,
u32 request, struct apparmor_audit_data *ad,
void (*cb)(struct audit_buffer *, void *));
diff --git a/security/apparmor/include/policy.h b/security/apparmor/include/policy.h
index 75088cc310b6..757e3c232c57 100644
--- a/security/apparmor/include/policy.h
+++ b/security/apparmor/include/policy.h
@@ -264,7 +264,6 @@ void aa_free_profile(struct aa_profile *profile);
struct aa_profile *aa_find_child(struct aa_profile *parent, const char *name);
struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname,
size_t n);
-struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *name);
struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
const char *fqname, size_t n);
diff --git a/security/apparmor/include/secid.h b/security/apparmor/include/secid.h
index cc6d1c9f4a47..f6a515640950 100644
--- a/security/apparmor/include/secid.h
+++ b/security/apparmor/include/secid.h
@@ -34,6 +34,5 @@ void apparmor_release_secctx(char *secdata, u32 seclen);
int aa_alloc_secid(struct aa_label *label, gfp_t gfp);
void aa_free_secid(u32 secid);
-void aa_secid_update(u32 secid, struct aa_label *label);
#endif /* __AA_SECID_H */
diff --git a/security/apparmor/label.c b/security/apparmor/label.c
index c71e4615dd46..91483ecacc16 100644
--- a/security/apparmor/label.c
+++ b/security/apparmor/label.c
@@ -899,23 +899,6 @@ struct aa_label *aa_vec_find_or_create_label(struct aa_profile **vec, int len,
return vec_create_and_insert_label(vec, len, gfp);
}
-/**
- * aa_label_find - find label @label in label set
- * @label: label to find (NOT NULL)
- *
- * Requires: caller to hold a valid ref on l
- *
- * Returns: refcounted @label if @label is in tree
- * refcounted label that is equiv to @label in tree
- * else NULL if @label or equiv is not in tree
- */
-struct aa_label *aa_label_find(struct aa_label *label)
-{
- AA_BUG(!label);
-
- return vec_find(label->vec, label->size);
-}
-
/**
* aa_label_insert - insert label @label into @ls or return existing label
@@ -1811,22 +1794,6 @@ void aa_label_xprintk(struct aa_ns *ns, struct aa_label *label, int flags,
pr_info("%s", label->hname);
}
-void aa_label_audit(struct audit_buffer *ab, struct aa_label *label, gfp_t gfp)
-{
- struct aa_ns *ns = aa_get_current_ns();
-
- aa_label_xaudit(ab, ns, label, FLAG_VIEW_SUBNS, gfp);
- aa_put_ns(ns);
-}
-
-void aa_label_seq_print(struct seq_file *f, struct aa_label *label, gfp_t gfp)
-{
- struct aa_ns *ns = aa_get_current_ns();
-
- aa_label_seq_xprint(f, ns, label, FLAG_VIEW_SUBNS, gfp);
- aa_put_ns(ns);
-}
-
void aa_label_printk(struct aa_label *label, gfp_t gfp)
{
struct aa_ns *ns = aa_get_current_ns();
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index cd569fbbfe36..7db62213e352 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -46,44 +46,6 @@ void aa_free_str_table(struct aa_str_table *t)
}
/**
- * aa_split_fqname - split a fqname into a profile and namespace name
- * @fqname: a full qualified name in namespace profile format (NOT NULL)
- * @ns_name: pointer to portion of the string containing the ns name (NOT NULL)
- *
- * Returns: profile name or NULL if one is not specified
- *
- * Split a namespace name from a profile name (see policy.c for naming
- * description). If a portion of the name is missing it returns NULL for
- * that portion.
- *
- * NOTE: may modify the @fqname string. The pointers returned point
- * into the @fqname string.
- */
-char *aa_split_fqname(char *fqname, char **ns_name)
-{
- char *name = strim(fqname);
-
- *ns_name = NULL;
- if (name[0] == ':') {
- char *split = strchr(&name[1], ':');
- *ns_name = skip_spaces(&name[1]);
- if (split) {
- /* overwrite ':' with \0 */
- *split++ = 0;
- if (strncmp(split, "//", 2) == 0)
- split += 2;
- name = skip_spaces(split);
- } else
- /* a ns name without a following profile is allowed */
- name = NULL;
- }
- if (name && *name == 0)
- name = NULL;
-
- return name;
-}
-
-/**
* skipn_spaces - Removes leading whitespace from @str.
* @str: The string to be stripped.
* @n: length of str to parse, will stop at \0 if encountered before n
@@ -276,33 +238,6 @@ void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
}
/**
- * aa_audit_perms_cb - generic callback fn for auditing perms
- * @ab: audit buffer (NOT NULL)
- * @va: audit struct to audit values of (NOT NULL)
- */
-static void aa_audit_perms_cb(struct audit_buffer *ab, void *va)
-{
- struct common_audit_data *sa = va;
- struct apparmor_audit_data *ad = aad(sa);
-
- if (ad->request) {
- audit_log_format(ab, " requested_mask=");
- aa_audit_perm_mask(ab, ad->request, aa_file_perm_chrs,
- PERMS_CHRS_MASK, aa_file_perm_names,
- PERMS_NAMES_MASK);
- }
- if (ad->denied) {
- audit_log_format(ab, "denied_mask=");
- aa_audit_perm_mask(ab, ad->denied, aa_file_perm_chrs,
- PERMS_CHRS_MASK, aa_file_perm_names,
- PERMS_NAMES_MASK);
- }
- audit_log_format(ab, " peer=");
- aa_label_xaudit(ab, labels_ns(ad->subj_label), ad->peer,
- FLAGS_NONE, GFP_ATOMIC);
-}
-
-/**
* aa_apply_modes_to_perms - apply namespace and profile flags to perms
* @profile: that perms where computed from
* @perms: perms to apply mode modifiers to
@@ -349,25 +284,6 @@ void aa_profile_match_label(struct aa_profile *profile,
}
-/* currently unused */
-int aa_profile_label_perm(struct aa_profile *profile, struct aa_profile *target,
- u32 request, int type, u32 *deny,
- struct apparmor_audit_data *ad)
-{
- struct aa_ruleset *rules = list_first_entry(&profile->rules,
- typeof(*rules), list);
- struct aa_perms perms;
-
- ad->peer = &target->label;
- ad->request = request;
-
- aa_profile_match_label(profile, rules, &target->label, type, request,
- &perms);
- aa_apply_modes_to_perms(profile, &perms);
- *deny |= request & perms.deny;
- return aa_check_perms(profile, &perms, request, ad, aa_audit_perms_cb);
-}
-
/**
* aa_check_perms - do audit mode selection based on perms set
* @profile: profile being checked
diff --git a/security/apparmor/match.c b/security/apparmor/match.c
index 517d77d3c34c..f2d9c57f8794 100644
--- a/security/apparmor/match.c
+++ b/security/apparmor/match.c
@@ -247,6 +247,42 @@ void aa_dfa_free_kref(struct kref *kref)
dfa_free(dfa);
}
+
+
+/**
+ * remap_data16_to_data32 - remap u16 @old table to a u32 based table
+ * @old: table to remap
+ *
+ * Returns: new table with u32 entries instead of u16.
+ *
+ * Note: will free @old so caller does not have to
+ */
+static struct table_header *remap_data16_to_data32(struct table_header *old)
+{
+ struct table_header *new;
+ size_t tsize;
+ u32 i;
+
+ tsize = table_size(old->td_lolen, YYTD_DATA32);
+ new = kvzalloc(tsize, GFP_KERNEL);
+ if (!new) {
+ kvfree(old);
+ return NULL;
+ }
+ new->td_id = old->td_id;
+ new->td_flags = YYTD_DATA32;
+ new->td_lolen = old->td_lolen;
+
+ for (i = 0; i < old->td_lolen; i++)
+ TABLE_DATAU32(new)[i] = (u32) TABLE_DATAU16(old)[i];
+
+ kvfree(old);
+ if (is_vmalloc_addr(new))
+ vm_unmap_aliases();
+
+ return new;
+}
+
/**
* aa_dfa_unpack - unpack the binary tables of a serialized dfa
* @blob: aligned serialized stream of data to unpack (NOT NULL)
@@ -326,8 +362,10 @@ struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)
case YYTD_ID_DEF:
case YYTD_ID_NXT:
case YYTD_ID_CHK:
- if (table->td_flags != YYTD_DATA16)
+ if (!(table->td_flags == YYTD_DATA16 ||
+ table->td_flags == YYTD_DATA32)) {
goto fail;
+ }
break;
case YYTD_ID_EC:
if (table->td_flags != YYTD_DATA8)
@@ -342,6 +380,23 @@ struct aa_dfa *aa_dfa_unpack(void *blob, size_t size, int flags)
dfa->tables[table->td_id] = table;
data += table_size(table->td_lolen, table->td_flags);
size -= table_size(table->td_lolen, table->td_flags);
+
+ /*
+ * this remapping has to be done after incrementing data above
+ * for now straight remap, later have dfa support both
+ */
+ switch (table->td_id) {
+ case YYTD_ID_DEF:
+ case YYTD_ID_NXT:
+ case YYTD_ID_CHK:
+ if (table->td_flags == YYTD_DATA16) {
+ table = remap_data16_to_data32(table);
+ if (!table)
+ goto fail;
+ }
+ dfa->tables[table->td_id] = table;
+ break;
+ }
table = NULL;
}
error = verify_table_headers(dfa->tables, flags);
@@ -395,10 +450,10 @@ do { \
aa_state_t aa_dfa_match_len(struct aa_dfa *dfa, aa_state_t start,
const char *str, int len)
{
- u16 *def = DEFAULT_TABLE(dfa);
+ u32 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
- u16 *next = NEXT_TABLE(dfa);
- u16 *check = CHECK_TABLE(dfa);
+ u32 *next = NEXT_TABLE(dfa);
+ u32 *check = CHECK_TABLE(dfa);
aa_state_t state = start;
if (state == DFA_NOMATCH)
@@ -434,10 +489,10 @@ aa_state_t aa_dfa_match_len(struct aa_dfa *dfa, aa_state_t start,
*/
aa_state_t aa_dfa_match(struct aa_dfa *dfa, aa_state_t start, const char *str)
{
- u16 *def = DEFAULT_TABLE(dfa);
+ u32 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
- u16 *next = NEXT_TABLE(dfa);
- u16 *check = CHECK_TABLE(dfa);
+ u32 *next = NEXT_TABLE(dfa);
+ u32 *check = CHECK_TABLE(dfa);
aa_state_t state = start;
if (state == DFA_NOMATCH)
@@ -472,10 +527,10 @@ aa_state_t aa_dfa_match(struct aa_dfa *dfa, aa_state_t start, const char *str)
*/
aa_state_t aa_dfa_next(struct aa_dfa *dfa, aa_state_t state, const char c)
{
- u16 *def = DEFAULT_TABLE(dfa);
+ u32 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
- u16 *next = NEXT_TABLE(dfa);
- u16 *check = CHECK_TABLE(dfa);
+ u32 *next = NEXT_TABLE(dfa);
+ u32 *check = CHECK_TABLE(dfa);
/* current state is <state>, matching character *str */
if (dfa->tables[YYTD_ID_EC]) {
@@ -490,10 +545,10 @@ aa_state_t aa_dfa_next(struct aa_dfa *dfa, aa_state_t state, const char c)
aa_state_t aa_dfa_outofband_transition(struct aa_dfa *dfa, aa_state_t state)
{
- u16 *def = DEFAULT_TABLE(dfa);
+ u32 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
- u16 *next = NEXT_TABLE(dfa);
- u16 *check = CHECK_TABLE(dfa);
+ u32 *next = NEXT_TABLE(dfa);
+ u32 *check = CHECK_TABLE(dfa);
u32 b = (base)[(state)];
if (!(b & MATCH_FLAG_OOB_TRANSITION))
@@ -521,10 +576,10 @@ aa_state_t aa_dfa_outofband_transition(struct aa_dfa *dfa, aa_state_t state)
aa_state_t aa_dfa_match_until(struct aa_dfa *dfa, aa_state_t start,
const char *str, const char **retpos)
{
- u16 *def = DEFAULT_TABLE(dfa);
+ u32 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
- u16 *next = NEXT_TABLE(dfa);
- u16 *check = CHECK_TABLE(dfa);
+ u32 *next = NEXT_TABLE(dfa);
+ u32 *check = CHECK_TABLE(dfa);
u32 *accept = ACCEPT_TABLE(dfa);
aa_state_t state = start, pos;
@@ -582,10 +637,10 @@ aa_state_t aa_dfa_match_until(struct aa_dfa *dfa, aa_state_t start,
aa_state_t aa_dfa_matchn_until(struct aa_dfa *dfa, aa_state_t start,
const char *str, int n, const char **retpos)
{
- u16 *def = DEFAULT_TABLE(dfa);
+ u32 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
- u16 *next = NEXT_TABLE(dfa);
- u16 *check = CHECK_TABLE(dfa);
+ u32 *next = NEXT_TABLE(dfa);
+ u32 *check = CHECK_TABLE(dfa);
u32 *accept = ACCEPT_TABLE(dfa);
aa_state_t state = start, pos;
@@ -658,10 +713,10 @@ static aa_state_t leftmatch_fb(struct aa_dfa *dfa, aa_state_t start,
const char *str, struct match_workbuf *wb,
unsigned int *count)
{
- u16 *def = DEFAULT_TABLE(dfa);
+ u32 *def = DEFAULT_TABLE(dfa);
u32 *base = BASE_TABLE(dfa);
- u16 *next = NEXT_TABLE(dfa);
- u16 *check = CHECK_TABLE(dfa);
+ u32 *next = NEXT_TABLE(dfa);
+ u32 *check = CHECK_TABLE(dfa);
aa_state_t state = start, pos;
AA_BUG(!dfa);
diff --git a/security/apparmor/path.c b/security/apparmor/path.c
index 45ec994b558d..d6c74c357ffd 100644
--- a/security/apparmor/path.c
+++ b/security/apparmor/path.c
@@ -130,7 +130,7 @@ static int d_namespace_path(const struct path *path, char *buf, char **name,
/* handle error conditions - and still allow a partial path to
* be returned.
*/
- if (!res || IS_ERR(res)) {
+ if (IS_ERR_OR_NULL(res)) {
if (PTR_ERR(res) == -ENAMETOOLONG) {
error = -ENAMETOOLONG;
*name = buf;
diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
index 14df15e35695..d0244fab0653 100644
--- a/security/apparmor/policy.c
+++ b/security/apparmor/policy.c
@@ -103,8 +103,7 @@ static void aa_free_pdb(struct aa_policydb *pdb)
{
if (pdb) {
aa_put_dfa(pdb->dfa);
- if (pdb->perms)
- kvfree(pdb->perms);
+ kvfree(pdb->perms);
aa_free_str_table(&pdb->trans);
kfree(pdb);
}
@@ -580,11 +579,6 @@ struct aa_profile *aa_lookupn_profile(struct aa_ns *ns, const char *hname,
return profile;
}
-struct aa_profile *aa_lookup_profile(struct aa_ns *ns, const char *hname)
-{
- return aa_lookupn_profile(ns, hname, strlen(hname));
-}
-
struct aa_profile *aa_fqlookupn_profile(struct aa_label *base,
const char *fqname, size_t n)
{
@@ -626,6 +620,7 @@ struct aa_profile *aa_alloc_null(struct aa_profile *parent, const char *name,
/* TODO: ideally we should inherit abi from parent */
profile->label.flags |= FLAG_NULL;
+ profile->attach.xmatch = aa_get_pdb(nullpdb);
rules = list_first_entry(&profile->rules, typeof(*rules), list);
rules->file = aa_get_pdb(nullpdb);
rules->policy = aa_get_pdb(nullpdb);
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 3483c595f999..992b74c50d64 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -645,10 +645,13 @@ fail:
static bool unpack_perm(struct aa_ext *e, u32 version, struct aa_perms *perm)
{
+ u32 reserved;
+
if (version != 1)
return false;
- return aa_unpack_u32(e, &perm->allow, NULL) &&
+ /* reserved entry is for later expansion, discard for now */
+ return aa_unpack_u32(e, &reserved, NULL) &&
aa_unpack_u32(e, &perm->allow, NULL) &&
aa_unpack_u32(e, &perm->deny, NULL) &&
aa_unpack_u32(e, &perm->subtree, NULL) &&
diff --git a/security/apparmor/policy_unpack_test.c b/security/apparmor/policy_unpack_test.c
index c64733d6c98f..5b2ba88ae9e2 100644
--- a/security/apparmor/policy_unpack_test.c
+++ b/security/apparmor/policy_unpack_test.c
@@ -44,7 +44,7 @@
#define TEST_ARRAY_BUF_OFFSET \
(TEST_NAMED_ARRAY_BUF_OFFSET + 3 + strlen(TEST_ARRAY_NAME) + 1)
-MODULE_IMPORT_NS(EXPORTED_FOR_KUNIT_TESTING);
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
struct policy_unpack_fixture {
struct aa_ext *e;
@@ -281,6 +281,8 @@ static void policy_unpack_test_unpack_strdup_with_null_name(struct kunit *test)
((uintptr_t)puf->e->start <= (uintptr_t)string)
&& ((uintptr_t)string <= (uintptr_t)puf->e->end));
KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA);
+
+ kfree(string);
}
static void policy_unpack_test_unpack_strdup_with_name(struct kunit *test)
@@ -296,6 +298,8 @@ static void policy_unpack_test_unpack_strdup_with_name(struct kunit *test)
((uintptr_t)puf->e->start <= (uintptr_t)string)
&& ((uintptr_t)string <= (uintptr_t)puf->e->end));
KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA);
+
+ kfree(string);
}
static void policy_unpack_test_unpack_strdup_out_of_bounds(struct kunit *test)
@@ -313,6 +317,8 @@ static void policy_unpack_test_unpack_strdup_out_of_bounds(struct kunit *test)
KUNIT_EXPECT_EQ(test, size, 0);
KUNIT_EXPECT_NULL(test, string);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, start);
+
+ kfree(string);
}
static void policy_unpack_test_unpack_nameX_with_null_name(struct kunit *test)
diff --git a/security/apparmor/secid.c b/security/apparmor/secid.c
index 6350d107013a..47dc08fc583e 100644
--- a/security/apparmor/secid.c
+++ b/security/apparmor/secid.c
@@ -39,20 +39,6 @@ int apparmor_display_secid_mode;
* TODO: use secid_update in label replace
*/
-/**
- * aa_secid_update - update a secid mapping to a new label
- * @secid: secid to update
- * @label: label the secid will now map to
- */
-void aa_secid_update(u32 secid, struct aa_label *label)
-{
- unsigned long flags;
-
- xa_lock_irqsave(&aa_secids, flags);
- __xa_store(&aa_secids, secid, label, 0);
- xa_unlock_irqrestore(&aa_secids, flags);
-}
-
/*
* see label for inverse aa_label_to_secid
*/
diff --git a/security/integrity/ima/ima_policy.c b/security/integrity/ima/ima_policy.c
index dbfd554b4624..21a8e54c383f 100644
--- a/security/integrity/ima/ima_policy.c
+++ b/security/integrity/ima/ima_policy.c
@@ -635,7 +635,7 @@ static bool ima_match_rules(struct ima_rule_entry *rule,
return false;
for (i = 0; i < MAX_LSM_RULES; i++) {
int rc = 0;
- struct lsm_prop prop = { };
+ struct lsm_prop inode_prop = { };
if (!lsm_rule->lsm[i].rule) {
if (!lsm_rule->lsm[i].args_p)
@@ -649,15 +649,16 @@ retry:
case LSM_OBJ_USER:
case LSM_OBJ_ROLE:
case LSM_OBJ_TYPE:
- security_inode_getlsmprop(inode, &prop);
- rc = ima_filter_rule_match(&prop, lsm_rule->lsm[i].type,
+ security_inode_getlsmprop(inode, &inode_prop);
+ rc = ima_filter_rule_match(&inode_prop,
+ lsm_rule->lsm[i].type,
Audit_equal,
lsm_rule->lsm[i].rule);
break;
case LSM_SUBJ_USER:
case LSM_SUBJ_ROLE:
case LSM_SUBJ_TYPE:
- rc = ima_filter_rule_match(&prop, lsm_rule->lsm[i].type,
+ rc = ima_filter_rule_match(prop, lsm_rule->lsm[i].type,
Audit_equal,
lsm_rule->lsm[i].rule);
break;
diff --git a/security/selinux/avc.c b/security/selinux/avc.c
index cc0b0af20296..1f2680bcc43a 100644
--- a/security/selinux/avc.c
+++ b/security/selinux/avc.c
@@ -174,13 +174,15 @@ int avc_get_hash_stats(char *page)
* using a linked list for extended_perms_decision lookup because the list is
* always small. i.e. less than 5, typically 1
*/
-static struct extended_perms_decision *avc_xperms_decision_lookup(u8 driver,
- struct avc_xperms_node *xp_node)
+static struct extended_perms_decision *
+avc_xperms_decision_lookup(u8 driver, u8 base_perm,
+ struct avc_xperms_node *xp_node)
{
struct avc_xperms_decision_node *xpd_node;
list_for_each_entry(xpd_node, &xp_node->xpd_head, xpd_list) {
- if (xpd_node->xpd.driver == driver)
+ if (xpd_node->xpd.driver == driver &&
+ xpd_node->xpd.base_perm == base_perm)
return &xpd_node->xpd;
}
return NULL;
@@ -205,11 +207,12 @@ avc_xperms_has_perm(struct extended_perms_decision *xpd,
}
static void avc_xperms_allow_perm(struct avc_xperms_node *xp_node,
- u8 driver, u8 perm)
+ u8 driver, u8 base_perm, u8 perm)
{
struct extended_perms_decision *xpd;
security_xperm_set(xp_node->xp.drivers.p, driver);
- xpd = avc_xperms_decision_lookup(driver, xp_node);
+ xp_node->xp.base_perms |= base_perm;
+ xpd = avc_xperms_decision_lookup(driver, base_perm, xp_node);
if (xpd && xpd->allowed)
security_xperm_set(xpd->allowed->p, perm);
}
@@ -245,6 +248,7 @@ static void avc_xperms_free(struct avc_xperms_node *xp_node)
static void avc_copy_xperms_decision(struct extended_perms_decision *dest,
struct extended_perms_decision *src)
{
+ dest->base_perm = src->base_perm;
dest->driver = src->driver;
dest->used = src->used;
if (dest->used & XPERMS_ALLOWED)
@@ -272,6 +276,7 @@ static inline void avc_quick_copy_xperms_decision(u8 perm,
*/
u8 i = perm >> 5;
+ dest->base_perm = src->base_perm;
dest->used = src->used;
if (dest->used & XPERMS_ALLOWED)
dest->allowed->p[i] = src->allowed->p[i];
@@ -357,6 +362,7 @@ static int avc_xperms_populate(struct avc_node *node,
memcpy(dest->xp.drivers.p, src->xp.drivers.p, sizeof(dest->xp.drivers.p));
dest->xp.len = src->xp.len;
+ dest->xp.base_perms = src->xp.base_perms;
/* for each source xpd allocate a destination xpd and copy */
list_for_each_entry(src_xpd, &src->xpd_head, xpd_list) {
@@ -807,6 +813,7 @@ out:
* @event : Updating event
* @perms : Permission mask bits
* @driver: xperm driver information
+ * @base_perm: the base permission associated with the extended permission
* @xperm: xperm permissions
* @ssid: AVC entry source sid
* @tsid: AVC entry target sid
@@ -820,10 +827,9 @@ out:
* otherwise, this function updates the AVC entry. The original AVC-entry object
* will release later by RCU.
*/
-static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid,
- u32 tsid, u16 tclass, u32 seqno,
- struct extended_perms_decision *xpd,
- u32 flags)
+static int avc_update_node(u32 event, u32 perms, u8 driver, u8 base_perm,
+ u8 xperm, u32 ssid, u32 tsid, u16 tclass, u32 seqno,
+ struct extended_perms_decision *xpd, u32 flags)
{
u32 hvalue;
int rc = 0;
@@ -880,7 +886,7 @@ static int avc_update_node(u32 event, u32 perms, u8 driver, u8 xperm, u32 ssid,
case AVC_CALLBACK_GRANT:
node->ae.avd.allowed |= perms;
if (node->ae.xp_node && (flags & AVC_EXTENDED_PERMS))
- avc_xperms_allow_perm(node->ae.xp_node, driver, xperm);
+ avc_xperms_allow_perm(node->ae.xp_node, driver, base_perm, xperm);
break;
case AVC_CALLBACK_TRY_REVOKE:
case AVC_CALLBACK_REVOKE:
@@ -987,10 +993,9 @@ static noinline void avc_compute_av(u32 ssid, u32 tsid, u16 tclass,
avc_insert(ssid, tsid, tclass, avd, xp_node);
}
-static noinline int avc_denied(u32 ssid, u32 tsid,
- u16 tclass, u32 requested,
- u8 driver, u8 xperm, unsigned int flags,
- struct av_decision *avd)
+static noinline int avc_denied(u32 ssid, u32 tsid, u16 tclass, u32 requested,
+ u8 driver, u8 base_perm, u8 xperm,
+ unsigned int flags, struct av_decision *avd)
{
if (flags & AVC_STRICT)
return -EACCES;
@@ -999,7 +1004,7 @@ static noinline int avc_denied(u32 ssid, u32 tsid,
!(avd->flags & AVD_FLAGS_PERMISSIVE))
return -EACCES;
- avc_update_node(AVC_CALLBACK_GRANT, requested, driver,
+ avc_update_node(AVC_CALLBACK_GRANT, requested, driver, base_perm,
xperm, ssid, tsid, tclass, avd->seqno, NULL, flags);
return 0;
}
@@ -1012,7 +1017,8 @@ static noinline int avc_denied(u32 ssid, u32 tsid,
* driver field is used to specify which set contains the permission.
*/
int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
- u8 driver, u8 xperm, struct common_audit_data *ad)
+ u8 driver, u8 base_perm, u8 xperm,
+ struct common_audit_data *ad)
{
struct avc_node *node;
struct av_decision avd;
@@ -1047,22 +1053,23 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
local_xpd.auditallow = &auditallow;
local_xpd.dontaudit = &dontaudit;
- xpd = avc_xperms_decision_lookup(driver, xp_node);
+ xpd = avc_xperms_decision_lookup(driver, base_perm, xp_node);
if (unlikely(!xpd)) {
/*
* Compute the extended_perms_decision only if the driver
- * is flagged
+ * is flagged and the base permission is known.
*/
- if (!security_xperm_test(xp_node->xp.drivers.p, driver)) {
+ if (!security_xperm_test(xp_node->xp.drivers.p, driver) ||
+ !(xp_node->xp.base_perms & base_perm)) {
avd.allowed &= ~requested;
goto decision;
}
rcu_read_unlock();
- security_compute_xperms_decision(ssid, tsid, tclass,
- driver, &local_xpd);
+ security_compute_xperms_decision(ssid, tsid, tclass, driver,
+ base_perm, &local_xpd);
rcu_read_lock();
- avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested,
- driver, xperm, ssid, tsid, tclass, avd.seqno,
+ avc_update_node(AVC_CALLBACK_ADD_XPERMS, requested, driver,
+ base_perm, xperm, ssid, tsid, tclass, avd.seqno,
&local_xpd, 0);
} else {
avc_quick_copy_xperms_decision(xperm, &local_xpd, xpd);
@@ -1075,8 +1082,8 @@ int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
decision:
denied = requested & ~(avd.allowed);
if (unlikely(denied))
- rc = avc_denied(ssid, tsid, tclass, requested,
- driver, xperm, AVC_EXTENDED_PERMS, &avd);
+ rc = avc_denied(ssid, tsid, tclass, requested, driver,
+ base_perm, xperm, AVC_EXTENDED_PERMS, &avd);
rcu_read_unlock();
@@ -1110,7 +1117,7 @@ static noinline int avc_perm_nonode(u32 ssid, u32 tsid, u16 tclass,
avc_compute_av(ssid, tsid, tclass, avd, &xp_node);
denied = requested & ~(avd->allowed);
if (unlikely(denied))
- return avc_denied(ssid, tsid, tclass, requested, 0, 0,
+ return avc_denied(ssid, tsid, tclass, requested, 0, 0, 0,
flags, avd);
return 0;
}
@@ -1158,7 +1165,7 @@ inline int avc_has_perm_noaudit(u32 ssid, u32 tsid,
rcu_read_unlock();
if (unlikely(denied))
- return avc_denied(ssid, tsid, tclass, requested, 0, 0,
+ return avc_denied(ssid, tsid, tclass, requested, 0, 0, 0,
flags, avd);
return 0;
}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index f5a08f94e094..171dd7fceac5 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3688,8 +3688,8 @@ static int ioctl_has_perm(const struct cred *cred, struct file *file,
return 0;
isec = inode_security(inode);
- rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass,
- requested, driver, xperm, &ad);
+ rc = avc_has_extended_perms(ssid, isec->sid, isec->sclass, requested,
+ driver, AVC_EXT_IOCTL, xperm, &ad);
out:
return rc;
}
@@ -5738,7 +5738,7 @@ static unsigned int selinux_ip_output(void *priv, struct sk_buff *skb,
/* we do this in the LOCAL_OUT path and not the POST_ROUTING path
* because we want to make sure we apply the necessary labeling
* before IPsec is applied so we can leverage AH protection */
- sk = skb->sk;
+ sk = sk_to_full_sk(skb->sk);
if (sk) {
struct sk_security_struct *sksec;
@@ -5952,7 +5952,7 @@ static int nlmsg_sock_has_extended_perms(struct sock *sk, u32 perms, u16 nlmsg_t
xperm = nlmsg_type & 0xff;
return avc_has_extended_perms(current_sid(), sksec->sid, sksec->sclass,
- perms, driver, xperm, &ad);
+ perms, driver, AVC_EXT_NLMSG, xperm, &ad);
}
static int selinux_netlink_send(struct sock *sk, struct sk_buff *skb)
diff --git a/security/selinux/include/avc.h b/security/selinux/include/avc.h
index 96a614d47df8..281f40103663 100644
--- a/security/selinux/include/avc.h
+++ b/security/selinux/include/avc.h
@@ -136,8 +136,11 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid, u16 tclass, u32 requested,
int avc_has_perm(u32 ssid, u32 tsid, u16 tclass, u32 requested,
struct common_audit_data *auditdata);
+#define AVC_EXT_IOCTL (1 << 0) /* Cache entry for an ioctl extended permission */
+#define AVC_EXT_NLMSG (1 << 1) /* Cache entry for an nlmsg extended permission */
int avc_has_extended_perms(u32 ssid, u32 tsid, u16 tclass, u32 requested,
- u8 driver, u8 perm, struct common_audit_data *ad);
+ u8 driver, u8 base_perm, u8 perm,
+ struct common_audit_data *ad);
u32 avc_policy_seqno(void);
diff --git a/security/selinux/include/security.h b/security/selinux/include/security.h
index c7f2731abd03..700bd6c8bb38 100644
--- a/security/selinux/include/security.h
+++ b/security/selinux/include/security.h
@@ -239,6 +239,7 @@ struct extended_perms_data {
struct extended_perms_decision {
u8 used;
u8 driver;
+ u8 base_perm;
struct extended_perms_data *allowed;
struct extended_perms_data *auditallow;
struct extended_perms_data *dontaudit;
@@ -246,6 +247,7 @@ struct extended_perms_decision {
struct extended_perms {
u16 len; /* length associated decision chain */
+ u8 base_perms; /* which base permissions are covered */
struct extended_perms_data drivers; /* flag drivers that are used */
};
@@ -257,6 +259,7 @@ void security_compute_av(u32 ssid, u32 tsid, u16 tclass,
struct extended_perms *xperms);
void security_compute_xperms_decision(u32 ssid, u32 tsid, u16 tclass, u8 driver,
+ u8 base_perm,
struct extended_perms_decision *xpermd);
void security_compute_av_user(u32 ssid, u32 tsid, u16 tclass,
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 971c45d576ba..d9f58b5d0f49 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -582,7 +582,7 @@ static void type_attribute_bounds_av(struct policydb *policydb,
}
/*
- * Flag which drivers have permissions.
+ * Flag which drivers have permissions and which base permissions are covered.
*/
void services_compute_xperms_drivers(
struct extended_perms *xperms,
@@ -592,12 +592,19 @@ void services_compute_xperms_drivers(
switch (node->datum.u.xperms->specified) {
case AVTAB_XPERMS_IOCTLDRIVER:
+ xperms->base_perms |= AVC_EXT_IOCTL;
/* if one or more driver has all permissions allowed */
for (i = 0; i < ARRAY_SIZE(xperms->drivers.p); i++)
xperms->drivers.p[i] |= node->datum.u.xperms->perms.p[i];
break;
case AVTAB_XPERMS_IOCTLFUNCTION:
+ xperms->base_perms |= AVC_EXT_IOCTL;
+ /* if allowing permissions within a driver */
+ security_xperm_set(xperms->drivers.p,
+ node->datum.u.xperms->driver);
+ break;
case AVTAB_XPERMS_NLMSG:
+ xperms->base_perms |= AVC_EXT_NLMSG;
/* if allowing permissions within a driver */
security_xperm_set(xperms->drivers.p,
node->datum.u.xperms->driver);
@@ -631,8 +638,7 @@ static void context_struct_compute_av(struct policydb *policydb,
avd->auditallow = 0;
avd->auditdeny = 0xffffffff;
if (xperms) {
- memset(&xperms->drivers, 0, sizeof(xperms->drivers));
- xperms->len = 0;
+ memset(xperms, 0, sizeof(*xperms));
}
if (unlikely(!tclass || tclass > policydb->p_classes.nprim)) {
@@ -969,17 +975,26 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
{
switch (node->datum.u.xperms->specified) {
case AVTAB_XPERMS_IOCTLFUNCTION:
- case AVTAB_XPERMS_NLMSG:
- if (xpermd->driver != node->datum.u.xperms->driver)
+ if (xpermd->base_perm != AVC_EXT_IOCTL ||
+ xpermd->driver != node->datum.u.xperms->driver)
return;
break;
case AVTAB_XPERMS_IOCTLDRIVER:
- if (!security_xperm_test(node->datum.u.xperms->perms.p,
- xpermd->driver))
+ if (xpermd->base_perm != AVC_EXT_IOCTL ||
+ !security_xperm_test(node->datum.u.xperms->perms.p,
+ xpermd->driver))
+ return;
+ break;
+ case AVTAB_XPERMS_NLMSG:
+ if (xpermd->base_perm != AVC_EXT_NLMSG ||
+ xpermd->driver != node->datum.u.xperms->driver)
return;
break;
default:
- BUG();
+ pr_warn_once(
+ "SELinux: unknown extended permission (%u) will be ignored\n",
+ node->datum.u.xperms->specified);
+ return;
}
if (node->key.specified == AVTAB_XPERMS_ALLOWED) {
@@ -998,7 +1013,8 @@ void services_compute_xperms_decision(struct extended_perms_decision *xpermd,
&node->datum.u.xperms->perms,
xpermd->dontaudit);
} else {
- BUG();
+ pr_warn_once("SELinux: unknown specified key (%u)\n",
+ node->key.specified);
}
}
@@ -1006,6 +1022,7 @@ void security_compute_xperms_decision(u32 ssid,
u32 tsid,
u16 orig_tclass,
u8 driver,
+ u8 base_perm,
struct extended_perms_decision *xpermd)
{
struct selinux_policy *policy;
@@ -1019,6 +1036,7 @@ void security_compute_xperms_decision(u32 ssid,
struct ebitmap_node *snode, *tnode;
unsigned int i, j;
+ xpermd->base_perm = base_perm;
xpermd->driver = driver;
xpermd->used = 0;
memset(xpermd->allowed->p, 0, sizeof(xpermd->allowed->p));
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index 96d4d7eb879f..8dfffdc101a2 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -180,7 +180,7 @@ static int ac97_bus_reset(struct ac97_controller *ac97_ctrl)
/**
* snd_ac97_codec_driver_register - register an AC97 codec driver
- * @dev: AC97 driver codec to register
+ * @drv: AC97 driver codec to register
*
* Register an AC97 codec driver to the ac97 bus driver, aka. the AC97 digital
* controller.
@@ -196,7 +196,7 @@ EXPORT_SYMBOL_GPL(snd_ac97_codec_driver_register);
/**
* snd_ac97_codec_driver_unregister - unregister an AC97 codec driver
- * @dev: AC97 codec driver to unregister
+ * @drv: AC97 codec driver to unregister
*
* Unregister a previously registered ac97 codec driver.
*/
@@ -338,6 +338,7 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl)
* @dev: the device providing the ac97 DC function
* @slots_available: mask of the ac97 codecs that can be scanned and probed
* bit0 => codec 0, bit1 => codec 1 ... bit 3 => codec 3
+ * @codecs_pdata: codec platform data
*
* Register a digital controller which can control up to 4 ac97 codecs. This is
* the controller side of the AC97 AC-link, while the slave side are the codecs.
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index 86ed2fbee0c8..840bb9cfe789 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -1025,7 +1025,7 @@ static u64 snd_compr_seqno_next(struct snd_compr_stream *stream)
static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_task *utask)
{
struct snd_compr_task_runtime *task;
- int retval;
+ int retval, fd_i, fd_o;
if (stream->runtime->total_tasks >= stream->runtime->fragments)
return -EBUSY;
@@ -1039,19 +1039,27 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_
retval = stream->ops->task_create(stream, task);
if (retval < 0)
goto cleanup;
- utask->input_fd = dma_buf_fd(task->input, O_WRONLY|O_CLOEXEC);
- if (utask->input_fd < 0) {
- retval = utask->input_fd;
+ /* similar functionality as in dma_buf_fd(), but ensure that both
+ file descriptors are allocated before fd_install() */
+ if (!task->input || !task->input->file || !task->output || !task->output->file) {
+ retval = -EINVAL;
goto cleanup;
}
- utask->output_fd = dma_buf_fd(task->output, O_RDONLY|O_CLOEXEC);
- if (utask->output_fd < 0) {
- retval = utask->output_fd;
+ fd_i = get_unused_fd_flags(O_WRONLY|O_CLOEXEC);
+ if (fd_i < 0)
+ goto cleanup;
+ fd_o = get_unused_fd_flags(O_RDONLY|O_CLOEXEC);
+ if (fd_o < 0) {
+ put_unused_fd(fd_i);
goto cleanup;
}
/* keep dmabuf reference until freed with task free ioctl */
- dma_buf_get(utask->input_fd);
- dma_buf_get(utask->output_fd);
+ get_dma_buf(task->input);
+ get_dma_buf(task->output);
+ fd_install(fd_i, task->input->file);
+ fd_install(fd_o, task->output->file);
+ utask->input_fd = fd_i;
+ utask->output_fd = fd_o;
list_add_tail(&task->list, &stream->runtime->tasks);
stream->runtime->total_tasks++;
return 0;
@@ -1069,7 +1077,7 @@ static int snd_compr_task_create(struct snd_compr_stream *stream, unsigned long
return -EPERM;
task = memdup_user((void __user *)arg, sizeof(*task));
if (IS_ERR(task))
- return PTR_ERR(no_free_ptr(task));
+ return PTR_ERR(task);
retval = snd_compr_task_new(stream, task);
if (retval >= 0)
if (copy_to_user((void __user *)arg, task, sizeof(*task)))
@@ -1130,7 +1138,7 @@ static int snd_compr_task_start_ioctl(struct snd_compr_stream *stream, unsigned
return -EPERM;
task = memdup_user((void __user *)arg, sizeof(*task));
if (IS_ERR(task))
- return PTR_ERR(no_free_ptr(task));
+ return PTR_ERR(task);
retval = snd_compr_task_start(stream, task);
if (retval >= 0)
if (copy_to_user((void __user *)arg, task, sizeof(*task)))
@@ -1174,18 +1182,18 @@ typedef void (*snd_compr_seq_func_t)(struct snd_compr_stream *stream,
static int snd_compr_task_seq(struct snd_compr_stream *stream, unsigned long arg,
snd_compr_seq_func_t fcn)
{
- struct snd_compr_task_runtime *task;
+ struct snd_compr_task_runtime *task, *temp;
__u64 seqno;
int retval;
if (stream->runtime->state != SNDRV_PCM_STATE_SETUP)
return -EPERM;
- retval = get_user(seqno, (__u64 __user *)arg);
- if (retval < 0)
- return retval;
+ retval = copy_from_user(&seqno, (__u64 __user *)arg, sizeof(seqno));
+ if (retval)
+ return -EFAULT;
retval = 0;
if (seqno == 0) {
- list_for_each_entry_reverse(task, &stream->runtime->tasks, list)
+ list_for_each_entry_safe_reverse(task, temp, &stream->runtime->tasks, list)
fcn(stream, task);
} else {
task = snd_compr_find_task(stream, seqno);
@@ -1221,7 +1229,7 @@ static int snd_compr_task_status_ioctl(struct snd_compr_stream *stream, unsigned
return -EPERM;
status = memdup_user((void __user *)arg, sizeof(*status));
if (IS_ERR(status))
- return PTR_ERR(no_free_ptr(status));
+ return PTR_ERR(status);
retval = snd_compr_task_status(stream, status);
if (retval >= 0)
if (copy_to_user((void __user *)arg, status, sizeof(*status)))
@@ -1247,6 +1255,7 @@ void snd_compr_task_finished(struct snd_compr_stream *stream,
}
EXPORT_SYMBOL_GPL(snd_compr_task_finished);
+MODULE_IMPORT_NS("DMA_BUF");
#endif /* CONFIG_SND_COMPRESS_ACCEL */
static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
diff --git a/sound/core/control_led.c b/sound/core/control_led.c
index 65a1ebe87776..e33dfcf863cf 100644
--- a/sound/core/control_led.c
+++ b/sound/core/control_led.c
@@ -668,10 +668,16 @@ static void snd_ctl_led_sysfs_add(struct snd_card *card)
goto cerr;
led->cards[card->number] = led_card;
snprintf(link_name, sizeof(link_name), "led-%s", led->name);
- WARN(sysfs_create_link(&card->ctl_dev->kobj, &led_card->dev.kobj, link_name),
- "can't create symlink to controlC%i device\n", card->number);
- WARN(sysfs_create_link(&led_card->dev.kobj, &card->card_dev.kobj, "card"),
- "can't create symlink to card%i\n", card->number);
+ if (sysfs_create_link(&card->ctl_dev->kobj, &led_card->dev.kobj,
+ link_name))
+ dev_err(card->dev,
+ "%s: can't create symlink to controlC%i device\n",
+ __func__, card->number);
+ if (sysfs_create_link(&led_card->dev.kobj, &card->card_dev.kobj,
+ "card"))
+ dev_err(card->dev,
+ "%s: can't create symlink to card%i\n",
+ __func__, card->number);
continue;
cerr:
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 13b71069ae18..b3853583d2ae 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -505,7 +505,7 @@ static void *snd_dma_wc_alloc(struct snd_dma_buffer *dmab, size_t size)
if (!p)
return NULL;
dmab->addr = dma_map_single(dmab->dev.dev, p, size, DMA_BIDIRECTIONAL);
- if (dmab->addr == DMA_MAPPING_ERROR) {
+ if (dma_mapping_error(dmab->dev.dev, dmab->addr)) {
do_free_pages(dmab->area, size, true);
return NULL;
}
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index b44d205cc838..8a3384342e8d 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -3813,9 +3813,11 @@ static vm_fault_t snd_pcm_mmap_data_fault(struct vm_fault *vmf)
return VM_FAULT_SIGBUS;
if (substream->ops->page)
page = substream->ops->page(substream, offset);
- else if (!snd_pcm_get_dma_buf(substream))
+ else if (!snd_pcm_get_dma_buf(substream)) {
+ if (WARN_ON_ONCE(!runtime->dma_area))
+ return VM_FAULT_SIGBUS;
page = virt_to_page(runtime->dma_area + offset);
- else
+ } else
page = snd_sgbuf_get_page(snd_pcm_get_dma_buf(substream), offset);
if (!page)
return VM_FAULT_SIGBUS;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 03306be5fa02..348ce1b7725e 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -724,8 +724,9 @@ static int resize_runtime_buffer(struct snd_rawmidi_substream *substream,
newbuf = kvzalloc(params->buffer_size, GFP_KERNEL);
if (!newbuf)
return -ENOMEM;
- guard(spinlock_irq)(&substream->lock);
+ spin_lock_irq(&substream->lock);
if (runtime->buffer_ref) {
+ spin_unlock_irq(&substream->lock);
kvfree(newbuf);
return -EBUSY;
}
@@ -733,6 +734,7 @@ static int resize_runtime_buffer(struct snd_rawmidi_substream *substream,
runtime->buffer = newbuf;
runtime->buffer_size = params->buffer_size;
__reset_runtime_ptrs(runtime, is_input);
+ spin_unlock_irq(&substream->lock);
kvfree(oldbuf);
}
runtime->avail_min = params->avail_min;
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index e3394919daa0..51ee4c00a843 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -66,6 +66,7 @@ static struct seq_oss_synth midi_synth_dev = {
};
static DEFINE_SPINLOCK(register_lock);
+static DEFINE_MUTEX(sysex_mutex);
/*
* prototypes
@@ -497,6 +498,7 @@ snd_seq_oss_synth_sysex(struct seq_oss_devinfo *dp, int dev, unsigned char *buf,
if (!info)
return -ENXIO;
+ guard(mutex)(&sysex_mutex);
sysex = info->sysex;
if (sysex == NULL) {
sysex = kzalloc(sizeof(*sysex), GFP_KERNEL);
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 3930e2f9082f..77b6ac9b5c11 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -1275,10 +1275,16 @@ static int snd_seq_ioctl_set_client_info(struct snd_seq_client *client,
if (client->type != client_info->type)
return -EINVAL;
- /* check validity of midi_version field */
- if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3) &&
- client_info->midi_version > SNDRV_SEQ_CLIENT_UMP_MIDI_2_0)
- return -EINVAL;
+ if (client->user_pversion >= SNDRV_PROTOCOL_VERSION(1, 0, 3)) {
+ /* check validity of midi_version field */
+ if (client_info->midi_version > SNDRV_SEQ_CLIENT_UMP_MIDI_2_0)
+ return -EINVAL;
+
+ /* check if UMP is supported in kernel */
+ if (!IS_ENABLED(CONFIG_SND_SEQ_UMP) &&
+ client_info->midi_version > 0)
+ return -EINVAL;
+ }
/* fill the info fields */
if (client_info->name[0])
diff --git a/sound/core/seq/seq_ump_client.c b/sound/core/seq/seq_ump_client.c
index e5d3f4d206bf..e956f17f3792 100644
--- a/sound/core/seq/seq_ump_client.c
+++ b/sound/core/seq/seq_ump_client.c
@@ -257,12 +257,12 @@ static void update_port_infos(struct seq_ump_client *client)
continue;
old->addr.client = client->seq_client;
- old->addr.port = i;
+ old->addr.port = ump_group_to_seq_port(i);
err = snd_seq_kernel_client_ctl(client->seq_client,
SNDRV_SEQ_IOCTL_GET_PORT_INFO,
old);
if (err < 0)
- return;
+ continue;
fill_port_info(new, client, &client->ump->groups[i]);
if (old->capability == new->capability &&
!strcmp(old->name, new->name))
@@ -271,7 +271,7 @@ static void update_port_infos(struct seq_ump_client *client)
SNDRV_SEQ_IOCTL_SET_PORT_INFO,
new);
if (err < 0)
- return;
+ continue;
/* notify to system port */
snd_seq_system_client_ev_port_change(client->seq_client, i);
}
diff --git a/sound/core/sound_kunit.c b/sound/core/sound_kunit.c
index bfed1a25fc8f..84e337ecbddd 100644
--- a/sound/core/sound_kunit.c
+++ b/sound/core/sound_kunit.c
@@ -172,6 +172,7 @@ static void test_format_fill_silence(struct kunit *test)
u32 i, j;
buffer = kunit_kzalloc(test, SILENCE_BUFFER_SIZE, GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, buffer);
for (i = 0; i < ARRAY_SIZE(buf_samples); i++) {
for (j = 0; j < ARRAY_SIZE(valid_fmt); j++)
@@ -208,8 +209,12 @@ static void test_playback_avail(struct kunit *test)
struct snd_pcm_runtime *r = kunit_kzalloc(test, sizeof(*r), GFP_KERNEL);
u32 i;
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r);
+
r->status = kunit_kzalloc(test, sizeof(*r->status), GFP_KERNEL);
r->control = kunit_kzalloc(test, sizeof(*r->control), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r->status);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r->control);
for (i = 0; i < ARRAY_SIZE(p_avail_data); i++) {
r->buffer_size = p_avail_data[i].buffer_size;
@@ -232,8 +237,12 @@ static void test_capture_avail(struct kunit *test)
struct snd_pcm_runtime *r = kunit_kzalloc(test, sizeof(*r), GFP_KERNEL);
u32 i;
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r);
+
r->status = kunit_kzalloc(test, sizeof(*r->status), GFP_KERNEL);
r->control = kunit_kzalloc(test, sizeof(*r->control), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r->status);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, r->control);
for (i = 0; i < ARRAY_SIZE(c_avail_data); i++) {
r->buffer_size = c_avail_data[i].buffer_size;
@@ -247,6 +256,7 @@ static void test_capture_avail(struct kunit *test)
static void test_card_set_id(struct kunit *test)
{
struct snd_card *card = kunit_kzalloc(test, sizeof(*card), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, card);
snd_card_set_id(card, VALID_NAME);
KUNIT_EXPECT_STREQ(test, card->id, VALID_NAME);
@@ -280,6 +290,7 @@ static void test_pcm_format_name(struct kunit *test)
static void test_card_add_component(struct kunit *test)
{
struct snd_card *card = kunit_kzalloc(test, sizeof(*card), GFP_KERNEL);
+ KUNIT_ASSERT_NOT_ERR_OR_NULL(test, card);
snd_component_add(card, TEST_FIRST_COMPONENT);
KUNIT_ASSERT_STREQ(test, card->components, TEST_FIRST_COMPONENT);
diff --git a/sound/core/ump.c b/sound/core/ump.c
index 5d4dd207e5ab..9198bff4768c 100644
--- a/sound/core/ump.c
+++ b/sound/core/ump.c
@@ -37,6 +37,7 @@ static int process_legacy_output(struct snd_ump_endpoint *ump,
u32 *buffer, int count);
static void process_legacy_input(struct snd_ump_endpoint *ump, const u32 *src,
int words);
+static void update_legacy_names(struct snd_ump_endpoint *ump);
#else
static inline int process_legacy_output(struct snd_ump_endpoint *ump,
u32 *buffer, int count)
@@ -47,6 +48,9 @@ static inline void process_legacy_input(struct snd_ump_endpoint *ump,
const u32 *src, int words)
{
}
+static inline void update_legacy_names(struct snd_ump_endpoint *ump)
+{
+}
#endif
static const struct snd_rawmidi_global_ops snd_ump_rawmidi_ops = {
@@ -788,7 +792,10 @@ static void fill_fb_info(struct snd_ump_endpoint *ump,
info->ui_hint = buf->fb_info.ui_hint;
info->first_group = buf->fb_info.first_group;
info->num_groups = buf->fb_info.num_groups;
- info->flags = buf->fb_info.midi_10;
+ if (buf->fb_info.midi_10 < 2)
+ info->flags = buf->fb_info.midi_10;
+ else
+ info->flags = SNDRV_UMP_BLOCK_IS_MIDI1 | SNDRV_UMP_BLOCK_IS_LOWSPEED;
info->active = buf->fb_info.active;
info->midi_ci_version = buf->fb_info.midi_ci_version;
info->sysex8_streams = buf->fb_info.sysex8_streams;
@@ -858,6 +865,7 @@ static int ump_handle_fb_info_msg(struct snd_ump_endpoint *ump,
fill_fb_info(ump, &fb->info, buf);
if (ump->parsed) {
snd_ump_update_group_attrs(ump);
+ update_legacy_names(ump);
seq_notify_fb_change(ump, fb);
}
}
@@ -890,6 +898,7 @@ static int ump_handle_fb_name_msg(struct snd_ump_endpoint *ump,
/* notify the FB name update to sequencer, too */
if (ret > 0 && ump->parsed) {
snd_ump_update_group_attrs(ump);
+ update_legacy_names(ump);
seq_notify_fb_change(ump, fb);
}
return ret;
@@ -1084,6 +1093,8 @@ static int snd_ump_legacy_open(struct snd_rawmidi_substream *substream)
guard(mutex)(&ump->open_mutex);
if (ump->legacy_substreams[dir][group])
return -EBUSY;
+ if (!ump->groups[group].active)
+ return -ENODEV;
if (dir == SNDRV_RAWMIDI_STREAM_OUTPUT) {
if (!ump->legacy_out_opens) {
err = snd_rawmidi_kernel_open(&ump->core, 0,
@@ -1233,7 +1244,7 @@ static int fill_legacy_mapping(struct snd_ump_endpoint *ump)
num = 0;
for (i = 0; i < SNDRV_UMP_MAX_GROUPS; i++)
- if ((group_maps & (1U << i)) && ump->groups[i].valid)
+ if (group_maps & (1U << i))
ump->legacy_mapping[num++] = i;
return num;
@@ -1251,11 +1262,20 @@ static void fill_substream_names(struct snd_ump_endpoint *ump,
name = ump->groups[idx].name;
if (!*name)
name = ump->info.name;
- snprintf(s->name, sizeof(s->name), "Group %d (%.16s)",
- idx + 1, name);
+ scnprintf(s->name, sizeof(s->name), "Group %d (%.16s)%s",
+ idx + 1, name,
+ ump->groups[idx].active ? "" : " [Inactive]");
}
}
+static void update_legacy_names(struct snd_ump_endpoint *ump)
+{
+ struct snd_rawmidi *rmidi = ump->legacy_rmidi;
+
+ fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_INPUT);
+ fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT);
+}
+
int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
char *id, int device)
{
@@ -1292,10 +1312,7 @@ int snd_ump_attach_legacy_rawmidi(struct snd_ump_endpoint *ump,
rmidi->ops = &snd_ump_legacy_ops;
rmidi->private_data = ump;
ump->legacy_rmidi = rmidi;
- if (input)
- fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_INPUT);
- if (output)
- fill_substream_names(ump, rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT);
+ update_legacy_names(ump);
ump_dbg(ump, "Created a legacy rawmidi #%d (%s)\n", device, id);
return 0;
diff --git a/sound/hda/intel-dsp-config.c b/sound/hda/intel-dsp-config.c
index 9f849e05ce79..f564ec7af194 100644
--- a/sound/hda/intel-dsp-config.c
+++ b/sound/hda/intel-dsp-config.c
@@ -801,4 +801,4 @@ EXPORT_SYMBOL_GPL(snd_intel_acpi_dsp_driver_probe);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Intel DSP config driver");
-MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI);
+MODULE_IMPORT_NS("SND_INTEL_SOUNDWIRE_ACPI");
diff --git a/sound/hda/intel-sdw-acpi.c b/sound/hda/intel-sdw-acpi.c
index ed530e0dd4dd..49d3e0e30073 100644
--- a/sound/hda/intel-sdw-acpi.c
+++ b/sound/hda/intel-sdw-acpi.c
@@ -198,7 +198,7 @@ int sdw_intel_acpi_scan(acpi_handle *parent_handle,
return sdw_intel_scan_controller(info);
}
-EXPORT_SYMBOL_NS(sdw_intel_acpi_scan, SND_INTEL_SOUNDWIRE_ACPI);
+EXPORT_SYMBOL_NS(sdw_intel_acpi_scan, "SND_INTEL_SOUNDWIRE_ACPI");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("Intel Soundwire ACPI helpers");
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index fdd4fe16225f..5a84591b13fc 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -464,7 +464,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
return -ENOMEM;
}
- err = hpi_stream_get_info_ex(dpcm->h_stream, NULL,
+ hpi_stream_get_info_ex(dpcm->h_stream, NULL,
&dpcm->hpi_buffer_attached, NULL, NULL, NULL);
}
bytes_per_sec = params_rate(params) * params_channels(params);
diff --git a/sound/pci/hda/cirrus_scodec.c b/sound/pci/hda/cirrus_scodec.c
index 8de3bc7448fa..3c670207ba30 100644
--- a/sound/pci/hda/cirrus_scodec.c
+++ b/sound/pci/hda/cirrus_scodec.c
@@ -66,7 +66,7 @@ int cirrus_scodec_get_speaker_id(struct device *dev, int amp_index,
return speaker_id;
}
-EXPORT_SYMBOL_NS_GPL(cirrus_scodec_get_speaker_id, SND_HDA_CIRRUS_SCODEC);
+EXPORT_SYMBOL_NS_GPL(cirrus_scodec_get_speaker_id, "SND_HDA_CIRRUS_SCODEC");
MODULE_DESCRIPTION("HDA Cirrus side-codec library");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
diff --git a/sound/pci/hda/cirrus_scodec_test.c b/sound/pci/hda/cirrus_scodec_test.c
index e925ebe21ccb..f5d6241daee4 100644
--- a/sound/pci/hda/cirrus_scodec_test.c
+++ b/sound/pci/hda/cirrus_scodec_test.c
@@ -365,7 +365,7 @@ static struct kunit_suite cirrus_scodec_test_suite = {
kunit_test_suite(cirrus_scodec_test_suite);
-MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);
+MODULE_IMPORT_NS("SND_HDA_CIRRUS_SCODEC");
MODULE_DESCRIPTION("KUnit test for the Cirrus side-codec library");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l41_hda.c b/sound/pci/hda/cs35l41_hda.c
index d68bf7591d90..5dc021976c79 100644
--- a/sound/pci/hda/cs35l41_hda.c
+++ b/sound/pci/hda/cs35l41_hda.c
@@ -2019,7 +2019,7 @@ err:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs35l41_hda_probe, SND_HDA_SCODEC_CS35L41);
+EXPORT_SYMBOL_NS_GPL(cs35l41_hda_probe, "SND_HDA_SCODEC_CS35L41");
void cs35l41_hda_remove(struct device *dev)
{
@@ -2044,7 +2044,7 @@ void cs35l41_hda_remove(struct device *dev)
gpiod_put(cs35l41->cs_gpio);
kfree(cs35l41->acpi_subsystem_id);
}
-EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, SND_HDA_SCODEC_CS35L41);
+EXPORT_SYMBOL_NS_GPL(cs35l41_hda_remove, "SND_HDA_SCODEC_CS35L41");
const struct dev_pm_ops cs35l41_hda_pm_ops = {
RUNTIME_PM_OPS(cs35l41_runtime_suspend, cs35l41_runtime_resume,
@@ -2052,11 +2052,11 @@ const struct dev_pm_ops cs35l41_hda_pm_ops = {
.prepare = cs35l41_system_suspend_prep,
SYSTEM_SLEEP_PM_OPS(cs35l41_system_suspend, cs35l41_system_resume)
};
-EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, SND_HDA_SCODEC_CS35L41);
+EXPORT_SYMBOL_NS_GPL(cs35l41_hda_pm_ops, "SND_HDA_SCODEC_CS35L41");
MODULE_DESCRIPTION("CS35L41 HDA Driver");
-MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS);
-MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);
+MODULE_IMPORT_NS("SND_HDA_CS_DSP_CONTROLS");
+MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
MODULE_AUTHOR("Lucas Tanure, Cirrus Logic Inc, <tanureal@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(FW_CS_DSP);
+MODULE_IMPORT_NS("FW_CS_DSP");
diff --git a/sound/pci/hda/cs35l41_hda_i2c.c b/sound/pci/hda/cs35l41_hda_i2c.c
index bb84740c8520..e77495413c21 100644
--- a/sound/pci/hda/cs35l41_hda_i2c.c
+++ b/sound/pci/hda/cs35l41_hda_i2c.c
@@ -64,6 +64,6 @@ static struct i2c_driver cs35l41_i2c_driver = {
module_i2c_driver(cs35l41_i2c_driver);
MODULE_DESCRIPTION("HDA CS35L41 driver");
-MODULE_IMPORT_NS(SND_HDA_SCODEC_CS35L41);
+MODULE_IMPORT_NS("SND_HDA_SCODEC_CS35L41");
MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l41_hda_spi.c b/sound/pci/hda/cs35l41_hda_spi.c
index f8c356ad0d34..2acbaf8467a0 100644
--- a/sound/pci/hda/cs35l41_hda_spi.c
+++ b/sound/pci/hda/cs35l41_hda_spi.c
@@ -59,6 +59,6 @@ static struct spi_driver cs35l41_spi_driver = {
module_spi_driver(cs35l41_spi_driver);
MODULE_DESCRIPTION("HDA CS35L41 driver");
-MODULE_IMPORT_NS(SND_HDA_SCODEC_CS35L41);
+MODULE_IMPORT_NS("SND_HDA_SCODEC_CS35L41");
MODULE_AUTHOR("Lucas Tanure <tanureal@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l56_hda.c b/sound/pci/hda/cs35l56_hda.c
index e3ac0e23ae32..4ef7878e8fd4 100644
--- a/sound/pci/hda/cs35l56_hda.c
+++ b/sound/pci/hda/cs35l56_hda.c
@@ -151,10 +151,6 @@ static int cs35l56_hda_runtime_resume(struct device *dev)
}
}
- ret = cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base);
- if (ret)
- goto err;
-
return 0;
err:
@@ -1059,9 +1055,6 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)
regmap_multi_reg_write(cs35l56->base.regmap, cs35l56_hda_dai_config,
ARRAY_SIZE(cs35l56_hda_dai_config));
- ret = cs35l56_force_sync_asp1_registers_from_cache(&cs35l56->base);
- if (ret)
- goto dsp_err;
/*
* By default only enable one ASP1TXn, where n=amplifier index,
@@ -1087,14 +1080,13 @@ int cs35l56_hda_common_probe(struct cs35l56_hda *cs35l56, int hid, int id)
pm_err:
pm_runtime_disable(cs35l56->base.dev);
-dsp_err:
cs_dsp_remove(&cs35l56->cs_dsp);
err:
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_hda_common_probe, SND_HDA_SCODEC_CS35L56);
+EXPORT_SYMBOL_NS_GPL(cs35l56_hda_common_probe, "SND_HDA_SCODEC_CS35L56");
void cs35l56_hda_remove(struct device *dev)
{
@@ -1113,7 +1105,7 @@ void cs35l56_hda_remove(struct device *dev)
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_hda_remove, SND_HDA_SCODEC_CS35L56);
+EXPORT_SYMBOL_NS_GPL(cs35l56_hda_remove, "SND_HDA_SCODEC_CS35L56");
const struct dev_pm_ops cs35l56_hda_pm_ops = {
RUNTIME_PM_OPS(cs35l56_hda_runtime_suspend, cs35l56_hda_runtime_resume, NULL)
@@ -1123,14 +1115,14 @@ const struct dev_pm_ops cs35l56_hda_pm_ops = {
NOIRQ_SYSTEM_SLEEP_PM_OPS(cs35l56_hda_system_suspend_no_irq,
cs35l56_hda_system_resume_no_irq)
};
-EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, SND_HDA_SCODEC_CS35L56);
+EXPORT_SYMBOL_NS_GPL(cs35l56_hda_pm_ops, "SND_HDA_SCODEC_CS35L56");
MODULE_DESCRIPTION("CS35L56 HDA Driver");
-MODULE_IMPORT_NS(FW_CS_DSP);
-MODULE_IMPORT_NS(SND_HDA_CIRRUS_SCODEC);
-MODULE_IMPORT_NS(SND_HDA_CS_DSP_CONTROLS);
-MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
-MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);
+MODULE_IMPORT_NS("FW_CS_DSP");
+MODULE_IMPORT_NS("SND_HDA_CIRRUS_SCODEC");
+MODULE_IMPORT_NS("SND_HDA_CS_DSP_CONTROLS");
+MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
+MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l56_hda_i2c.c b/sound/pci/hda/cs35l56_hda_i2c.c
index 40f2f97944d5..c7b836613149 100644
--- a/sound/pci/hda/cs35l56_hda_i2c.c
+++ b/sound/pci/hda/cs35l56_hda_i2c.c
@@ -77,8 +77,8 @@ static struct i2c_driver cs35l56_hda_i2c_driver = {
module_i2c_driver(cs35l56_hda_i2c_driver);
MODULE_DESCRIPTION("HDA CS35L56 I2C driver");
-MODULE_IMPORT_NS(SND_HDA_SCODEC_CS35L56);
-MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
+MODULE_IMPORT_NS("SND_HDA_SCODEC_CS35L56");
+MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/cs35l56_hda_spi.c b/sound/pci/hda/cs35l56_hda_spi.c
index 7f02155fe61e..d4ee5bb7c486 100644
--- a/sound/pci/hda/cs35l56_hda_spi.c
+++ b/sound/pci/hda/cs35l56_hda_spi.c
@@ -77,8 +77,8 @@ static struct spi_driver cs35l56_hda_spi_driver = {
module_spi_driver(cs35l56_hda_spi_driver);
MODULE_DESCRIPTION("HDA CS35L56 SPI driver");
-MODULE_IMPORT_NS(SND_HDA_SCODEC_CS35L56);
-MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
+MODULE_IMPORT_NS("SND_HDA_SCODEC_CS35L56");
+MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_auto_parser.c b/sound/pci/hda/hda_auto_parser.c
index 8e74be038b0f..84393f4f429d 100644
--- a/sound/pci/hda/hda_auto_parser.c
+++ b/sound/pci/hda/hda_auto_parser.c
@@ -933,6 +933,7 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec,
bool match_all_pins)
{
const struct snd_hda_pin_quirk *pq;
+ const char *name = NULL;
if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
return;
@@ -946,9 +947,10 @@ void snd_hda_pick_pin_fixup(struct hda_codec *codec,
codec->fixup_id = pq->value;
#ifdef CONFIG_SND_DEBUG_VERBOSE
codec->fixup_name = pq->name;
- codec_dbg(codec, "%s: picked fixup %s (pin match)\n",
- codec->core.chip_name, codec->fixup_name);
+ name = pq->name;
#endif
+ codec_info(codec, "%s: picked fixup %s (pin match)\n",
+ codec->core.chip_name, name ? name : "");
codec->fixup_list = fixlist;
return;
}
@@ -1015,8 +1017,8 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
id = HDA_FIXUP_ID_NO_FIXUP;
fixlist = NULL;
- codec_dbg(codec, "%s: picked no fixup (nofixup specified)\n",
- codec->core.chip_name);
+ codec_info(codec, "%s: picked no fixup (nofixup specified)\n",
+ codec->core.chip_name);
goto found;
}
@@ -1026,8 +1028,8 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
if (!strcmp(codec->modelname, models->name)) {
id = models->id;
name = models->name;
- codec_dbg(codec, "%s: picked fixup %s (model specified)\n",
- codec->core.chip_name, codec->fixup_name);
+ codec_info(codec, "%s: picked fixup %s (model specified)\n",
+ codec->core.chip_name, name);
goto found;
}
models++;
@@ -1085,9 +1087,9 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
#ifdef CONFIG_SND_DEBUG_VERBOSE
name = q->name;
#endif
- codec_dbg(codec, "%s: picked fixup %s for %s %04x:%04x\n",
- codec->core.chip_name, name ? name : "",
- type, q->subvendor, q->subdevice);
+ codec_info(codec, "%s: picked fixup %s for %s %04x:%04x\n",
+ codec->core.chip_name, name ? name : "",
+ type, q->subvendor, q->subdevice);
found:
codec->fixup_id = id;
codec->fixup_list = fixlist;
diff --git a/sound/pci/hda/hda_component.c b/sound/pci/hda/hda_component.c
index 2d6b7b0b355d..71860e2d6377 100644
--- a/sound/pci/hda/hda_component.c
+++ b/sound/pci/hda/hda_component.c
@@ -29,7 +29,7 @@ void hda_component_acpi_device_notify(struct hda_component_parent *parent,
}
mutex_unlock(&parent->mutex);
}
-EXPORT_SYMBOL_NS_GPL(hda_component_acpi_device_notify, SND_HDA_SCODEC_COMPONENT);
+EXPORT_SYMBOL_NS_GPL(hda_component_acpi_device_notify, "SND_HDA_SCODEC_COMPONENT");
int hda_component_manager_bind_acpi_notifications(struct hda_codec *cdc,
struct hda_component_parent *parent,
@@ -64,7 +64,7 @@ int hda_component_manager_bind_acpi_notifications(struct hda_codec *cdc,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind_acpi_notifications, SND_HDA_SCODEC_COMPONENT);
+EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind_acpi_notifications, "SND_HDA_SCODEC_COMPONENT");
void hda_component_manager_unbind_acpi_notifications(struct hda_codec *cdc,
struct hda_component_parent *parent,
@@ -81,7 +81,7 @@ void hda_component_manager_unbind_acpi_notifications(struct hda_codec *cdc,
if (ret < 0)
codec_warn(cdc, "Failed to uninstall notify handler: %d\n", ret);
}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_unbind_acpi_notifications, SND_HDA_SCODEC_COMPONENT);
+EXPORT_SYMBOL_NS_GPL(hda_component_manager_unbind_acpi_notifications, "SND_HDA_SCODEC_COMPONENT");
#endif /* ifdef CONFIG_ACPI */
void hda_component_manager_playback_hook(struct hda_component_parent *parent, int action)
@@ -107,7 +107,7 @@ void hda_component_manager_playback_hook(struct hda_component_parent *parent, in
}
mutex_unlock(&parent->mutex);
}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_playback_hook, SND_HDA_SCODEC_COMPONENT);
+EXPORT_SYMBOL_NS_GPL(hda_component_manager_playback_hook, "SND_HDA_SCODEC_COMPONENT");
struct hda_scodec_match {
const char *bus;
@@ -149,7 +149,7 @@ int hda_component_manager_bind(struct hda_codec *cdc,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind, SND_HDA_SCODEC_COMPONENT);
+EXPORT_SYMBOL_NS_GPL(hda_component_manager_bind, "SND_HDA_SCODEC_COMPONENT");
int hda_component_manager_init(struct hda_codec *cdc,
struct hda_component_parent *parent, int count,
@@ -189,7 +189,7 @@ int hda_component_manager_init(struct hda_codec *cdc,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_init, SND_HDA_SCODEC_COMPONENT);
+EXPORT_SYMBOL_NS_GPL(hda_component_manager_init, "SND_HDA_SCODEC_COMPONENT");
void hda_component_manager_free(struct hda_component_parent *parent,
const struct component_master_ops *ops)
@@ -205,7 +205,7 @@ void hda_component_manager_free(struct hda_component_parent *parent,
parent->codec = NULL;
}
-EXPORT_SYMBOL_NS_GPL(hda_component_manager_free, SND_HDA_SCODEC_COMPONENT);
+EXPORT_SYMBOL_NS_GPL(hda_component_manager_free, "SND_HDA_SCODEC_COMPONENT");
MODULE_DESCRIPTION("HD Audio component binding library");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
diff --git a/sound/pci/hda/hda_cs_dsp_ctl.c b/sound/pci/hda/hda_cs_dsp_ctl.c
index deb74c247082..18fa6e7edb49 100644
--- a/sound/pci/hda/hda_cs_dsp_ctl.c
+++ b/sound/pci/hda/hda_cs_dsp_ctl.c
@@ -34,7 +34,7 @@ const char * const hda_cs_dsp_fw_ids[HDA_CS_DSP_NUM_FW] = {
[HDA_CS_DSP_FW_SPK_DIAG] = "spk-diag",
[HDA_CS_DSP_FW_MISC] = "misc",
};
-EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_fw_ids, SND_HDA_CS_DSP_CONTROLS);
+EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_fw_ids, "SND_HDA_CS_DSP_CONTROLS");
static int hda_cs_dsp_coeff_info(struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
{
@@ -200,7 +200,7 @@ void hda_cs_dsp_add_controls(struct cs_dsp *dsp, const struct hda_cs_dsp_ctl_inf
hda_cs_dsp_control_add(cs_ctl, info);
}
}
-EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_add_controls, SND_HDA_CS_DSP_CONTROLS);
+EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_add_controls, "SND_HDA_CS_DSP_CONTROLS");
void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
{
@@ -210,7 +210,7 @@ void hda_cs_dsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
if (ctl)
snd_ctl_remove(ctl->card, ctl->kctl);
}
-EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, SND_HDA_CS_DSP_CONTROLS);
+EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_control_remove, "SND_HDA_CS_DSP_CONTROLS");
int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type,
unsigned int alg, const void *buf, size_t len)
@@ -227,7 +227,7 @@ int hda_cs_dsp_write_ctl(struct cs_dsp *dsp, const char *name, int type,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_write_ctl, SND_HDA_CS_DSP_CONTROLS);
+EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_write_ctl, "SND_HDA_CS_DSP_CONTROLS");
int hda_cs_dsp_read_ctl(struct cs_dsp *dsp, const char *name, int type,
unsigned int alg, void *buf, size_t len)
@@ -241,9 +241,9 @@ int hda_cs_dsp_read_ctl(struct cs_dsp *dsp, const char *name, int type,
return ret;
}
-EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_read_ctl, SND_HDA_CS_DSP_CONTROLS);
+EXPORT_SYMBOL_NS_GPL(hda_cs_dsp_read_ctl, "SND_HDA_CS_DSP_CONTROLS");
MODULE_DESCRIPTION("CS_DSP ALSA Control HDA Library");
MODULE_AUTHOR("Stefan Binding, <sbinding@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(FW_CS_DSP);
+MODULE_IMPORT_NS("FW_CS_DSP");
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index e4673a71551a..d40197fb5fbd 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -1134,7 +1134,6 @@ struct ca0132_spec {
struct hda_codec *codec;
struct delayed_work unsol_hp_work;
- int quirk;
#ifdef ENABLE_TUNING_CONTROLS
long cur_ctl_vals[TUNING_CTLS_COUNT];
@@ -1166,7 +1165,6 @@ struct ca0132_spec {
* CA0132 quirks table
*/
enum {
- QUIRK_NONE,
QUIRK_ALIENWARE,
QUIRK_ALIENWARE_M17XR4,
QUIRK_SBZ,
@@ -1176,10 +1174,11 @@ enum {
QUIRK_R3D,
QUIRK_AE5,
QUIRK_AE7,
+ QUIRK_NONE = HDA_FIXUP_ID_NOT_SET,
};
#ifdef CONFIG_PCI
-#define ca0132_quirk(spec) ((spec)->quirk)
+#define ca0132_quirk(spec) ((spec)->codec->fixup_id)
#define ca0132_use_pci_mmio(spec) ((spec)->use_pci_mmio)
#define ca0132_use_alt_functions(spec) ((spec)->use_alt_functions)
#define ca0132_use_alt_controls(spec) ((spec)->use_alt_controls)
@@ -1293,7 +1292,7 @@ static const struct hda_pintbl ae7_pincfgs[] = {
{}
};
-static const struct snd_pci_quirk ca0132_quirks[] = {
+static const struct hda_quirk ca0132_quirks[] = {
SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4),
SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
SND_PCI_QUIRK(0x1028, 0x0688, "Alienware 17 2015", QUIRK_ALIENWARE),
@@ -1316,6 +1315,19 @@ static const struct snd_pci_quirk ca0132_quirks[] = {
{}
};
+static const struct hda_model_fixup ca0132_quirk_models[] = {
+ { .id = QUIRK_ALIENWARE, .name = "alienware" },
+ { .id = QUIRK_ALIENWARE_M17XR4, .name = "alienware-m17xr4" },
+ { .id = QUIRK_SBZ, .name = "sbz" },
+ { .id = QUIRK_ZXR, .name = "zxr" },
+ { .id = QUIRK_ZXR_DBPRO, .name = "zxr-dbpro" },
+ { .id = QUIRK_R3DI, .name = "r3di" },
+ { .id = QUIRK_R3D, .name = "r3d" },
+ { .id = QUIRK_AE5, .name = "ae5" },
+ { .id = QUIRK_AE7, .name = "ae7" },
+ {}
+};
+
/* Output selection quirk info structures. */
#define MAX_QUIRK_MMIO_GPIO_SET_VALS 3
#define MAX_QUIRK_SCP_SET_VALS 2
@@ -9957,17 +9969,15 @@ static int ca0132_prepare_verbs(struct hda_codec *codec)
*/
static void sbz_detect_quirk(struct hda_codec *codec)
{
- struct ca0132_spec *spec = codec->spec;
-
switch (codec->core.subsystem_id) {
case 0x11020033:
- spec->quirk = QUIRK_ZXR;
+ codec->fixup_id = QUIRK_ZXR;
break;
case 0x1102003f:
- spec->quirk = QUIRK_ZXR_DBPRO;
+ codec->fixup_id = QUIRK_ZXR_DBPRO;
break;
default:
- spec->quirk = QUIRK_SBZ;
+ codec->fixup_id = QUIRK_SBZ;
break;
}
}
@@ -9976,7 +9986,6 @@ static int patch_ca0132(struct hda_codec *codec)
{
struct ca0132_spec *spec;
int err;
- const struct snd_pci_quirk *quirk;
codec_dbg(codec, "patch_ca0132\n");
@@ -9987,11 +9996,7 @@ static int patch_ca0132(struct hda_codec *codec)
spec->codec = codec;
/* Detect codec quirk */
- quirk = snd_pci_quirk_lookup(codec->bus->pci, ca0132_quirks);
- if (quirk)
- spec->quirk = quirk->value;
- else
- spec->quirk = QUIRK_NONE;
+ snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL);
if (ca0132_quirk(spec) == QUIRK_SBZ)
sbz_detect_quirk(codec);
@@ -10068,7 +10073,7 @@ static int patch_ca0132(struct hda_codec *codec)
spec->mem_base = pci_iomap(codec->bus->pci, 2, 0xC20);
if (spec->mem_base == NULL) {
codec_warn(codec, "pci_iomap failed! Setting quirk to QUIRK_NONE.");
- spec->quirk = QUIRK_NONE;
+ codec->fixup_id = QUIRK_NONE;
}
}
#endif
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 2e9f817b948e..538c37a78a56 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -307,6 +307,7 @@ enum {
CXT_FIXUP_HP_MIC_NO_PRESENCE,
CXT_PINCFG_SWS_JS201D,
CXT_PINCFG_TOP_SPEAKER,
+ CXT_FIXUP_HP_A_U,
};
/* for hda_fixup_thinkpad_acpi() */
@@ -774,6 +775,18 @@ static void cxt_setup_mute_led(struct hda_codec *codec,
}
}
+static void cxt_setup_gpio_unmute(struct hda_codec *codec,
+ unsigned int gpio_mute_mask)
+{
+ if (gpio_mute_mask) {
+ // set gpio data to 0.
+ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
+ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK, gpio_mute_mask);
+ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DIRECTION, gpio_mute_mask);
+ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_STICKY_MASK, 0);
+ }
+}
+
static void cxt_fixup_mute_led_gpio(struct hda_codec *codec,
const struct hda_fixup *fix, int action)
{
@@ -788,6 +801,15 @@ static void cxt_fixup_hp_zbook_mute_led(struct hda_codec *codec,
cxt_setup_mute_led(codec, 0x10, 0x20);
}
+static void cxt_fixup_hp_a_u(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ // Init vers in BIOS mute the spk/hp by set gpio high to avoid pop noise,
+ // so need to unmute once by clearing the gpio data when runs into the system.
+ if (action == HDA_FIXUP_ACT_INIT)
+ cxt_setup_gpio_unmute(codec, 0x2);
+}
+
/* ThinkPad X200 & co with cxt5051 */
static const struct hda_pintbl cxt_pincfg_lenovo_x200[] = {
{ 0x16, 0x042140ff }, /* HP (seq# overridden) */
@@ -998,6 +1020,10 @@ static const struct hda_fixup cxt_fixups[] = {
{ }
},
},
+ [CXT_FIXUP_HP_A_U] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = cxt_fixup_hp_a_u,
+ },
};
static const struct hda_quirk cxt5045_fixups[] = {
@@ -1072,6 +1098,7 @@ static const struct hda_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x103c, 0x8457, "HP Z2 G4 mini", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x103c, 0x8458, "HP Z2 G4 mini premium", CXT_FIXUP_HP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x138d, "Asus", CXT_FIXUP_HEADPHONE_MIC_PIN),
+ SND_PCI_QUIRK(0x14f1, 0x0252, "MBX-Z60MR100", CXT_FIXUP_HP_A_U),
SND_PCI_QUIRK(0x14f1, 0x0265, "SWS JS201D", CXT_PINCFG_SWS_JS201D),
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT_FIXUP_OLPC_XO),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400", CXT_PINCFG_LENOVO_TP410),
@@ -1117,6 +1144,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = {
{ .id = CXT_PINCFG_LENOVO_NOTEBOOK, .name = "lenovo-20149" },
{ .id = CXT_PINCFG_SWS_JS201D, .name = "sws-js201d" },
{ .id = CXT_PINCFG_TOP_SPEAKER, .name = "sirius-top-speaker" },
+ { .id = CXT_FIXUP_HP_A_U, .name = "HP-U-support" },
{}
};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 56a3622ca2c1..b74b566f675e 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -473,6 +473,8 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
break;
case 0x10ec0234:
case 0x10ec0274:
+ alc_write_coef_idx(codec, 0x6e, 0x0c25);
+ fallthrough;
case 0x10ec0294:
case 0x10ec0700:
case 0x10ec0701:
@@ -3613,25 +3615,22 @@ static void alc256_init(struct hda_codec *codec)
hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
- if (hp_pin_sense)
+ if (hp_pin_sense) {
msleep(2);
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
-
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- if (hp_pin_sense || spec->ultra_low_power)
- msleep(85);
-
- snd_hda_codec_write(codec, hp_pin, 0,
+ snd_hda_codec_write(codec, hp_pin, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- if (hp_pin_sense || spec->ultra_low_power)
- msleep(100);
+ msleep(75);
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+
+ msleep(75);
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
+ }
alc_update_coef_idx(codec, 0x46, 3 << 12, 0);
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 1 << 15); /* Clear bit */
alc_update_coefex_idx(codec, 0x53, 0x02, 0x8000, 0 << 15);
/*
@@ -3655,29 +3654,28 @@ static void alc256_shutup(struct hda_codec *codec)
alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
hp_pin_sense = snd_hda_jack_detect(codec, hp_pin);
- if (hp_pin_sense)
+ if (hp_pin_sense) {
msleep(2);
- snd_hda_codec_write(codec, hp_pin, 0,
+ snd_hda_codec_write(codec, hp_pin, 0,
AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
- if (hp_pin_sense || spec->ultra_low_power)
- msleep(85);
+ msleep(75);
/* 3k pull low control for Headset jack. */
/* NOTE: call this before clearing the pin, otherwise codec stalls */
/* If disable 3k pulldown control for alc257, the Mic detection will not work correctly
* when booting with headset plugged. So skip setting it for the codec alc257
*/
- if (spec->en_3kpull_low)
- alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
+ if (spec->en_3kpull_low)
+ alc_update_coef_idx(codec, 0x46, 0, 3 << 12);
- if (!spec->no_shutup_pins)
- snd_hda_codec_write(codec, hp_pin, 0,
+ if (!spec->no_shutup_pins)
+ snd_hda_codec_write(codec, hp_pin, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
- if (hp_pin_sense || spec->ultra_low_power)
- msleep(100);
+ msleep(75);
+ }
alc_auto_setup_eapd(codec, false);
alc_shutup_pins(codec);
@@ -3772,33 +3770,28 @@ static void alc225_init(struct hda_codec *codec)
hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin);
hp2_pin_sense = snd_hda_jack_detect(codec, 0x16);
- if (hp1_pin_sense || hp2_pin_sense)
+ if (hp1_pin_sense || hp2_pin_sense) {
msleep(2);
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x1); /* Low power */
-
- if (hp1_pin_sense || spec->ultra_low_power)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x16, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power)
- msleep(85);
-
- if (hp1_pin_sense || spec->ultra_low_power)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x16, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+ if (hp1_pin_sense)
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+ if (hp2_pin_sense)
+ snd_hda_codec_write(codec, 0x16, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT);
+ msleep(75);
- if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power)
- msleep(100);
+ if (hp1_pin_sense)
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
+ if (hp2_pin_sense)
+ snd_hda_codec_write(codec, 0x16, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
- alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
+ msleep(75);
+ alc_update_coefex_idx(codec, 0x57, 0x04, 0x0007, 0x4); /* Hight power */
+ }
}
static void alc225_shutup(struct hda_codec *codec)
@@ -3810,36 +3803,35 @@ static void alc225_shutup(struct hda_codec *codec)
if (!hp_pin)
hp_pin = 0x21;
- alc_disable_headset_jack_key(codec);
- /* 3k pull low control for Headset jack. */
- alc_update_coef_idx(codec, 0x4a, 0, 3 << 10);
-
hp1_pin_sense = snd_hda_jack_detect(codec, hp_pin);
hp2_pin_sense = snd_hda_jack_detect(codec, 0x16);
- if (hp1_pin_sense || hp2_pin_sense)
+ if (hp1_pin_sense || hp2_pin_sense) {
+ alc_disable_headset_jack_key(codec);
+ /* 3k pull low control for Headset jack. */
+ alc_update_coef_idx(codec, 0x4a, 0, 3 << 10);
msleep(2);
- if (hp1_pin_sense || spec->ultra_low_power)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x16, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power)
- msleep(85);
+ if (hp1_pin_sense)
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+ if (hp2_pin_sense)
+ snd_hda_codec_write(codec, 0x16, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
- if (hp1_pin_sense || spec->ultra_low_power)
- snd_hda_codec_write(codec, hp_pin, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
- if (hp2_pin_sense)
- snd_hda_codec_write(codec, 0x16, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+ msleep(75);
- if (hp1_pin_sense || hp2_pin_sense || spec->ultra_low_power)
- msleep(100);
+ if (hp1_pin_sense)
+ snd_hda_codec_write(codec, hp_pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+ if (hp2_pin_sense)
+ snd_hda_codec_write(codec, 0x16, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+ msleep(75);
+ alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
+ alc_enable_headset_jack_key(codec);
+ }
alc_auto_setup_eapd(codec, false);
alc_shutup_pins(codec);
if (spec->ultra_low_power) {
@@ -3850,9 +3842,6 @@ static void alc225_shutup(struct hda_codec *codec)
alc_update_coef_idx(codec, 0x4a, 3<<4, 2<<4);
msleep(30);
}
-
- alc_update_coef_idx(codec, 0x4a, 3 << 10, 0);
- alc_enable_headset_jack_key(codec);
}
static void alc_default_init(struct hda_codec *codec)
@@ -6502,6 +6491,16 @@ static void alc285_fixup_speaker2_to_dac1(struct hda_codec *codec,
}
}
+/* disable DAC3 (0x06) selection on NID 0x15 - share Speaker/Bass Speaker DAC 0x03 */
+static void alc294_fixup_bass_speaker_15(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+ static const hda_nid_t conn[] = { 0x02, 0x03 };
+ snd_hda_override_conn_list(codec, 0x15, ARRAY_SIZE(conn), conn);
+ }
+}
+
/* Hook to update amp GPIO4 for automute */
static void alc280_hp_gpio4_automute_hook(struct hda_codec *codec,
struct hda_jack_callback *jack)
@@ -7559,6 +7558,7 @@ enum {
ALC269_FIXUP_THINKPAD_ACPI,
ALC269_FIXUP_DMIC_THINKPAD_ACPI,
ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13,
+ ALC269VC_FIXUP_INFINIX_Y4_MAX,
ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO,
ALC255_FIXUP_ACER_MIC_NO_PRESENCE,
ALC255_FIXUP_ASUS_MIC_NO_PRESENCE,
@@ -7714,6 +7714,7 @@ enum {
ALC274_FIXUP_HP_MIC,
ALC274_FIXUP_HP_HEADSET_MIC,
ALC274_FIXUP_HP_ENVY_GPIO,
+ ALC274_FIXUP_ASUS_ZEN_AIO_27,
ALC256_FIXUP_ASUS_HPE,
ALC285_FIXUP_THINKPAD_NO_BASS_SPK_HEADSET_JACK,
ALC287_FIXUP_HP_GPIO_LED,
@@ -7782,6 +7783,8 @@ enum {
ALC256_FIXUP_CHROME_BOOK,
ALC245_FIXUP_CLEVO_NOISY_MIC,
ALC269_FIXUP_VAIO_VJFH52_MIC_NO_PRESENCE,
+ ALC233_FIXUP_MEDION_MTL_SPK,
+ ALC294_FIXUP_BASS_SPEAKER_15,
};
/* A special fixup for Lenovo C940 and Yoga Duet 7;
@@ -7945,6 +7948,15 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
},
+ [ALC269VC_FIXUP_INFINIX_Y4_MAX] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x1b, 0x90170150 }, /* use as internal speaker */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
+ },
[ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@@ -9505,6 +9517,26 @@ static const struct hda_fixup alc269_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc274_fixup_hp_envy_gpio,
},
+ [ALC274_FIXUP_ASUS_ZEN_AIO_27] = {
+ .type = HDA_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x10 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0xc420 },
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x40 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x8800 },
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x49 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0249 },
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x4a },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x202b },
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x62 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0xa007 },
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x6b },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x5060 },
+ {}
+ },
+ .chained = true,
+ .chain_id = ALC2XX_FIXUP_HEADSET_MIC,
+ },
[ALC256_FIXUP_ASUS_HPE] = {
.type = HDA_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
@@ -10074,6 +10106,17 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_LIMIT_INT_MIC_BOOST
},
+ [ALC233_FIXUP_MEDION_MTL_SPK] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = (const struct hda_pintbl[]) {
+ { 0x1b, 0x90170110 },
+ { }
+ },
+ },
+ [ALC294_FIXUP_BASS_SPEAKER_15] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc294_fixup_bass_speaker_15,
+ },
};
static const struct hda_quirk alc269_fixup_tbl[] = {
@@ -10120,6 +10163,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x1430, "Acer TravelMate B311R-31", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
SND_PCI_QUIRK(0x1028, 0x053c, "Dell Latitude E5430", ALC292_FIXUP_DELL_E7X),
@@ -10318,6 +10362,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x87b7, "HP Laptop 14-fq0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x87c8, "HP", ALC287_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87d3, "HP Laptop 15-gw0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
+ SND_PCI_QUIRK(0x103c, 0x87df, "HP ProBook 430 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87e5, "HP ProBook 440 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87e7, "HP ProBook 450 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x87f1, "HP ProBook 630 G8 Notebook PC", ALC236_FIXUP_HP_GPIO_LED),
@@ -10499,6 +10544,13 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8cdf, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8ce0, "HP SnowWhite", ALC287_FIXUP_CS35L41_I2C_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8cf5, "HP ZBook Studio 16", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8d01, "HP ZBook Power 14 G12", ALC285_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8d84, "HP EliteBook X G1i", ALC285_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8d91, "HP ZBook Firefly 14 G12", ALC285_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8d92, "HP ZBook Firefly 16 G12", ALC285_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8e18, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8e19, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8e1a, "HP ZBook Firefly 14 G12A", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x1043, 0x103e, "ASUS X540SA", ALC256_FIXUP_ASUS_MIC),
SND_PCI_QUIRK(0x1043, 0x103f, "ASUS TX300", ALC282_FIXUP_ASUS_TX300),
SND_PCI_QUIRK(0x1043, 0x106d, "Asus K53BE", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
@@ -10582,6 +10634,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1d42, "ASUS Zephyrus G14 2022", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x1d4e, "ASUS TM420", ALC256_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x1da2, "ASUS UP6502ZA/ZD", ALC245_FIXUP_CS35L41_SPI_2),
+ SND_PCI_QUIRK(0x1043, 0x1df3, "ASUS UM5606WA", ALC294_FIXUP_BASS_SPEAKER_15),
SND_PCI_QUIRK(0x1043, 0x1e02, "ASUS UX3402ZA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1e11, "ASUS Zephyrus G15", ALC289_FIXUP_ASUS_GA502),
SND_PCI_QUIRK(0x1043, 0x1e12, "ASUS UM3402", ALC287_FIXUP_CS35L41_I2C_2),
@@ -10599,6 +10652,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1f62, "ASUS UX7602ZM", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x1f92, "ASUS ROG Flow X16", ALC289_FIXUP_ASUS_GA401),
SND_PCI_QUIRK(0x1043, 0x3030, "ASUS ZN270IE", ALC256_FIXUP_ASUS_AIO_GPIO2),
+ SND_PCI_QUIRK(0x1043, 0x31d0, "ASUS Zen AIO 27 Z272SD_A272SD", ALC274_FIXUP_ASUS_ZEN_AIO_27),
SND_PCI_QUIRK(0x1043, 0x3a20, "ASUS G614JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
SND_PCI_QUIRK(0x1043, 0x3a30, "ASUS G814JVR/JIR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
SND_PCI_QUIRK(0x1043, 0x3a40, "ASUS G814JZR", ALC285_FIXUP_ASUS_SPI_REAR_SPEAKERS),
@@ -10652,6 +10706,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x144d, 0xc830, "Samsung Galaxy Book Ion (NT950XCJ-X716A)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc832, "Samsung Galaxy Book Flex Alpha (NP730QCJ)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xca03, "Samsung Galaxy Book2 Pro 360 (NP930QED)", ALC298_FIXUP_SAMSUNG_AMP),
+ SND_PCI_QUIRK(0x144d, 0xca06, "Samsung Galaxy Book3 360 (NP730QFG)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc868, "Samsung Galaxy Book2 Pro (NP930XED)", ALC298_FIXUP_SAMSUNG_AMP),
SND_PCI_QUIRK(0x144d, 0xc870, "Samsung Galaxy Book2 Pro (NP950XED)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
SND_PCI_QUIRK(0x144d, 0xc872, "Samsung Galaxy Book2 Pro (NP950XEE)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
@@ -10943,7 +10998,10 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x2782, 0x0214, "VAIO VJFE-CL", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x2782, 0x0228, "Infinix ZERO BOOK 13", ALC269VB_FIXUP_INFINIX_ZERO_BOOK_13),
SND_PCI_QUIRK(0x2782, 0x0232, "CHUWI CoreBook XPro", ALC269VB_FIXUP_CHUWI_COREBOOK_XPRO),
+ SND_PCI_QUIRK(0x2782, 0x1701, "Infinix Y4 Max", ALC269VC_FIXUP_INFINIX_Y4_MAX),
+ SND_PCI_QUIRK(0x2782, 0x1705, "MEDION E15433", ALC269VC_FIXUP_INFINIX_Y4_MAX),
SND_PCI_QUIRK(0x2782, 0x1707, "Vaio VJFE-ADL", ALC298_FIXUP_SPK_VOLUME),
+ SND_PCI_QUIRK(0x2782, 0x4900, "MEDION E15443", ALC233_FIXUP_MEDION_MTL_SPK),
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),
@@ -10951,6 +11009,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0xf111, 0x0001, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0xf111, 0x0006, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0xf111, 0x0009, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0xf111, 0x000c, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
#if 0
/* Below is a quirk table taken from the old code.
@@ -11142,6 +11201,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC255_FIXUP_ACER_HEADPHONE_AND_MIC, .name = "alc255-acer-headphone-and-mic"},
{.id = ALC285_FIXUP_HP_GPIO_AMP_INIT, .name = "alc285-hp-amp-init"},
{.id = ALC236_FIXUP_LENOVO_INV_DMIC, .name = "alc236-fixup-lenovo-inv-mic"},
+ {.id = ALC2XX_FIXUP_HEADSET_MIC, .name = "alc2xx-fixup-headset-mic"},
{}
};
#define ALC225_STANDARD_PINS \
@@ -13266,7 +13326,7 @@ MODULE_DEVICE_TABLE(hdaudio, snd_hda_id_realtek);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Realtek HD-audio codec");
-MODULE_IMPORT_NS(SND_HDA_SCODEC_COMPONENT);
+MODULE_IMPORT_NS("SND_HDA_SCODEC_COMPONENT");
static struct hda_codec_driver realtek_driver = {
.id = snd_hda_id_realtek,
diff --git a/sound/pci/hda/tas2781_hda_i2c.c b/sound/pci/hda/tas2781_hda_i2c.c
index 370d847517f9..0e42b87dadb8 100644
--- a/sound/pci/hda/tas2781_hda_i2c.c
+++ b/sound/pci/hda/tas2781_hda_i2c.c
@@ -16,6 +16,7 @@
#include <linux/i2c.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
+#include <linux/pci_ids.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <sound/hda_codec.h>
@@ -110,10 +111,20 @@ static int tas2781_get_i2c_res(struct acpi_resource *ares, void *data)
return 1;
}
+static const struct acpi_gpio_params speakerid_gpios = { 0, 0, false };
+
+static const struct acpi_gpio_mapping tas2781_speaker_id_gpios[] = {
+ { "speakerid-gpios", &speakerid_gpios, 1 },
+ { }
+};
+
static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid)
{
struct acpi_device *adev;
+ struct device *physdev;
LIST_HEAD(resources);
+ const char *sub;
+ uint32_t subid;
int ret;
adev = acpi_dev_get_first_match_dev(hid, NULL, -1);
@@ -123,18 +134,50 @@ static int tas2781_read_acpi(struct tasdevice_priv *p, const char *hid)
return -ENODEV;
}
+ physdev = get_device(acpi_get_first_physical_node(adev));
ret = acpi_dev_get_resources(adev, &resources, tas2781_get_i2c_res, p);
- if (ret < 0)
+ if (ret < 0) {
+ dev_err(p->dev, "Failed to get ACPI resource.\n");
+ goto err;
+ }
+ sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
+ if (IS_ERR(sub)) {
+ /* No subsys id in older tas2563 projects. */
+ if (!strncmp(hid, "INT8866", sizeof("INT8866")))
+ goto end_2563;
+ dev_err(p->dev, "Failed to get SUBSYS ID.\n");
+ ret = PTR_ERR(sub);
goto err;
+ }
+ /* Speaker id was needed for ASUS projects. */
+ ret = kstrtou32(sub, 16, &subid);
+ if (!ret && upper_16_bits(subid) == PCI_VENDOR_ID_ASUSTEK) {
+ ret = devm_acpi_dev_add_driver_gpios(p->dev,
+ tas2781_speaker_id_gpios);
+ if (ret < 0)
+ dev_err(p->dev, "Failed to add driver gpio %d.\n",
+ ret);
+ p->speaker_id = devm_gpiod_get(p->dev, "speakerid", GPIOD_IN);
+ if (IS_ERR(p->speaker_id)) {
+ dev_err(p->dev, "Failed to get Speaker id.\n");
+ ret = PTR_ERR(p->speaker_id);
+ goto err;
+ }
+ } else {
+ p->speaker_id = NULL;
+ }
+end_2563:
acpi_dev_free_resource_list(&resources);
strscpy(p->dev_name, hid, sizeof(p->dev_name));
+ put_device(physdev);
acpi_dev_put(adev);
return 0;
err:
dev_err(p->dev, "read acpi error, ret: %d\n", ret);
+ put_device(physdev);
acpi_dev_put(adev);
return ret;
@@ -615,7 +658,7 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
struct tasdevice_priv *tas_priv = context;
struct tas2781_hda *tas_hda = dev_get_drvdata(tas_priv->dev);
struct hda_codec *codec = tas_priv->codec;
- int i, ret;
+ int i, ret, spk_id;
pm_runtime_get_sync(tas_priv->dev);
mutex_lock(&tas_priv->codec_lock);
@@ -648,8 +691,25 @@ static void tasdev_fw_ready(const struct firmware *fmw, void *context)
tasdevice_dsp_remove(tas_priv);
tas_priv->fw_state = TASDEVICE_DSP_FW_PENDING;
- scnprintf(tas_priv->coef_binaryname, 64, "TAS2XXX%04X.bin",
- codec->core.subsystem_id & 0xffff);
+ if (tas_priv->speaker_id != NULL) {
+ // Speaker id need to be checked for ASUS only.
+ spk_id = gpiod_get_value(tas_priv->speaker_id);
+ if (spk_id < 0) {
+ // Speaker id is not valid, use default.
+ dev_dbg(tas_priv->dev, "Wrong spk_id = %d\n", spk_id);
+ spk_id = 0;
+ }
+ snprintf(tas_priv->coef_binaryname,
+ sizeof(tas_priv->coef_binaryname),
+ "TAS2XXX%04X%d.bin",
+ lower_16_bits(codec->core.subsystem_id),
+ spk_id);
+ } else {
+ snprintf(tas_priv->coef_binaryname,
+ sizeof(tas_priv->coef_binaryname),
+ "TAS2XXX%04X.bin",
+ lower_16_bits(codec->core.subsystem_id));
+ }
ret = tasdevice_dsp_parser(tas_priv);
if (ret) {
dev_err(tas_priv->dev, "dspfw load %s error\n",
@@ -977,4 +1037,4 @@ module_i2c_driver(tas2781_hda_i2c_driver);
MODULE_DESCRIPTION("TAS2781 HDA Driver");
MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_TAS2781_FMWLIB);
+MODULE_IMPORT_NS("SND_SOC_TAS2781_FMWLIB");
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
index e7b80328f0ef..3f5422145c5e 100644
--- a/sound/sh/sh_dac_audio.c
+++ b/sound/sh/sh_dac_audio.c
@@ -163,7 +163,7 @@ static int snd_sh_dac_pcm_copy(struct snd_pcm_substream *substream,
/* channel is not used (interleaved data) */
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
- if (copy_from_iter_toio(chip->data_buffer + pos, src, count))
+ if (copy_from_iter(chip->data_buffer + pos, count, src) != count)
return -EFAULT;
chip->buffer_end = chip->data_buffer + pos + count;
@@ -182,7 +182,7 @@ static int snd_sh_dac_pcm_silence(struct snd_pcm_substream *substream,
/* channel is not used (interleaved data) */
struct snd_sh_dac *chip = snd_pcm_substream_chip(substream);
- memset_io(chip->data_buffer + pos, 0, count);
+ memset(chip->data_buffer + pos, 0, count);
chip->buffer_end = chip->data_buffer + pos + count;
if (chip->empty) {
@@ -211,7 +211,6 @@ static const struct snd_pcm_ops snd_sh_dac_pcm_ops = {
.pointer = snd_sh_dac_pcm_pointer,
.copy = snd_sh_dac_pcm_copy,
.fill_silence = snd_sh_dac_pcm_silence,
- .mmap = snd_pcm_lib_mmap_iomem,
};
static int snd_sh_dac_pcm(struct snd_sh_dac *chip, int device)
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 6dec44f516c1..c7590d4989bb 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -163,6 +163,7 @@ config SND_SOC_AMD_SOUNDWIRE
config SND_SOC_AMD_PS
tristate "AMD Audio Coprocessor-v6.3 Pink Sardine support"
select SND_SOC_AMD_SOUNDWIRE_LINK_BASELINE
+ select SND_SOC_ACPI_AMD_MATCH
depends on X86 && PCI && ACPI
help
This option enables Audio Coprocessor i.e ACP v6.3 support on
diff --git a/sound/soc/amd/acp/acp-i2s.c b/sound/soc/amd/acp/acp-i2s.c
index 515bf862deb5..1f59ee248771 100644
--- a/sound/soc/amd/acp/acp-i2s.c
+++ b/sound/soc/amd/acp/acp-i2s.c
@@ -694,7 +694,7 @@ const struct snd_soc_dai_ops asoc_acp_cpu_dai_ops = {
.set_fmt = acp_i2s_set_fmt,
.set_tdm_slot = acp_i2s_set_tdm_slot,
};
-EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(asoc_acp_cpu_dai_ops, "SND_SOC_ACP_COMMON");
MODULE_DESCRIPTION("AMD ACP Audio I2S controller");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/amd/acp/acp-legacy-common.c b/sound/soc/amd/acp/acp-legacy-common.c
index 3f76d1f0a9e7..7acc7ed2e8cc 100644
--- a/sound/soc/amd/acp/acp-legacy-common.c
+++ b/sound/soc/amd/acp/acp-legacy-common.c
@@ -31,7 +31,7 @@ void acp_enable_interrupts(struct acp_dev_data *adata)
ext_intr_ctrl |= ACP_ERROR_MASK;
writel(ext_intr_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, rsrc->irqp_used));
}
-EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_enable_interrupts, "SND_SOC_ACP_COMMON");
void acp_disable_interrupts(struct acp_dev_data *adata)
{
@@ -40,7 +40,7 @@ void acp_disable_interrupts(struct acp_dev_data *adata)
writel(ACP_EXT_INTR_STAT_CLEAR_MASK, ACP_EXTERNAL_INTR_STAT(adata, rsrc->irqp_used));
writel(0x00, ACP_EXTERNAL_INTR_ENB(adata));
}
-EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_disable_interrupts, "SND_SOC_ACP_COMMON");
static void set_acp_pdm_ring_buffer(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
@@ -97,7 +97,7 @@ void restore_acp_pdm_params(struct snd_pcm_substream *substream,
writel(ext_int_ctrl, ACP_EXTERNAL_INTR_CNTL(adata, 0));
set_acp_pdm_clk(substream, dai);
}
-EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(restore_acp_pdm_params, "SND_SOC_ACP_COMMON");
static int set_acp_i2s_dma_fifo(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
@@ -248,7 +248,7 @@ int restore_acp_i2s_params(struct snd_pcm_substream *substream,
}
return set_acp_i2s_dma_fifo(substream, dai);
}
-EXPORT_SYMBOL_NS_GPL(restore_acp_i2s_params, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(restore_acp_i2s_params, "SND_SOC_ACP_COMMON");
static int acp_power_on(struct acp_chip_info *chip)
{
@@ -326,7 +326,7 @@ int acp_init(struct acp_chip_info *chip)
writel(0, chip->base + ACP_ZSC_DSP_CTRL);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_init, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_init, "SND_SOC_ACP_COMMON");
int acp_deinit(struct acp_chip_info *chip)
{
@@ -343,7 +343,7 @@ int acp_deinit(struct acp_chip_info *chip)
writel(0x01, chip->base + ACP_ZSC_DSP_CTRL);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_deinit, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_deinit, "SND_SOC_ACP_COMMON");
int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data)
{
@@ -351,7 +351,7 @@ int smn_write(struct pci_dev *dev, u32 smn_addr, u32 data)
pci_write_config_dword(dev, 0x64, data);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(smn_write, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(smn_write, "SND_SOC_ACP_COMMON");
int smn_read(struct pci_dev *dev, u32 smn_addr)
{
@@ -361,7 +361,7 @@ int smn_read(struct pci_dev *dev, u32 smn_addr)
pci_read_config_dword(dev, 0x64, &data);
return data;
}
-EXPORT_SYMBOL_NS_GPL(smn_read, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(smn_read, "SND_SOC_ACP_COMMON");
static void check_acp3x_config(struct acp_chip_info *chip)
{
@@ -479,7 +479,7 @@ void check_acp_config(struct pci_dev *pci, struct acp_chip_info *chip)
}
}
}
-EXPORT_SYMBOL_NS_GPL(check_acp_config, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(check_acp_config, "SND_SOC_ACP_COMMON");
MODULE_DESCRIPTION("AMD ACP legacy common features");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/amd/acp/acp-legacy-mach.c b/sound/soc/amd/acp/acp-legacy-mach.c
index 45613a865d2b..a7a551366a40 100644
--- a/sound/soc/amd/acp/acp-legacy-mach.c
+++ b/sound/soc/amd/acp/acp-legacy-mach.c
@@ -240,6 +240,6 @@ static struct platform_driver acp_asoc_audio = {
module_platform_driver(acp_asoc_audio);
-MODULE_IMPORT_NS(SND_SOC_AMD_MACH);
+MODULE_IMPORT_NS("SND_SOC_AMD_MACH");
MODULE_DESCRIPTION("ACP chrome audio support");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/acp/acp-mach-common.c b/sound/soc/amd/acp/acp-mach-common.c
index d314253207d5..f7602c1769bf 100644
--- a/sound/soc/amd/acp/acp-mach-common.c
+++ b/sound/soc/amd/acp/acp-mach-common.c
@@ -1579,7 +1579,7 @@ int acp_sofdsp_dai_links_create(struct snd_soc_card *card)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, SND_SOC_AMD_MACH);
+EXPORT_SYMBOL_NS_GPL(acp_sofdsp_dai_links_create, "SND_SOC_AMD_MACH");
int acp_legacy_dai_links_create(struct snd_soc_card *card)
{
@@ -1790,7 +1790,7 @@ int acp_legacy_dai_links_create(struct snd_soc_card *card)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, SND_SOC_AMD_MACH);
+EXPORT_SYMBOL_NS_GPL(acp_legacy_dai_links_create, "SND_SOC_AMD_MACH");
MODULE_DESCRIPTION("AMD ACP Common Machine driver");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/acp/acp-pci.c b/sound/soc/amd/acp/acp-pci.c
index 4b6ad7abc3ba..e0fc42d939d3 100644
--- a/sound/soc/amd/acp/acp-pci.c
+++ b/sound/soc/amd/acp/acp-pci.c
@@ -250,5 +250,5 @@ module_pci_driver(snd_amd_acp_pci_driver);
MODULE_DESCRIPTION("AMD ACP common PCI support");
MODULE_LICENSE("Dual BSD/GPL");
-MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
MODULE_ALIAS(DRV_NAME);
diff --git a/sound/soc/amd/acp/acp-pdm.c b/sound/soc/amd/acp/acp-pdm.c
index 48faafe724ed..d4855da05b6a 100644
--- a/sound/soc/amd/acp/acp-pdm.c
+++ b/sound/soc/amd/acp/acp-pdm.c
@@ -181,7 +181,7 @@ const struct snd_soc_dai_ops acp_dmic_dai_ops = {
.startup = acp_dmic_dai_startup,
.shutdown = acp_dmic_dai_shutdown,
};
-EXPORT_SYMBOL_NS_GPL(acp_dmic_dai_ops, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_dmic_dai_ops, "SND_SOC_ACP_COMMON");
MODULE_DESCRIPTION("AMD ACP Audio PDM controller");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/amd/acp/acp-platform.c b/sound/soc/amd/acp/acp-platform.c
index 1f352b2b3002..aa330aeeb301 100644
--- a/sound/soc/amd/acp/acp-platform.c
+++ b/sound/soc/amd/acp/acp-platform.c
@@ -133,7 +133,7 @@ int acp_machine_select(struct acp_dev_data *adata)
dev_warn(adata->dev, "Unable to register Machine device\n");
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_machine_select, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_machine_select, "SND_SOC_ACP_COMMON");
static irqreturn_t i2s_irq_handler(int irq, void *data)
{
@@ -191,7 +191,7 @@ void config_pte_for_stream(struct acp_dev_data *adata, struct acp_stream *stream
writel(0x01, adata->acp_base + ACPAXI2AXI_ATU_CTRL);
}
-EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(config_pte_for_stream, "SND_SOC_ACP_COMMON");
void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int size)
{
@@ -250,7 +250,7 @@ void config_acp_dma(struct acp_dev_data *adata, struct acp_stream *stream, int s
addr += PAGE_SIZE;
}
}
-EXPORT_SYMBOL_NS_GPL(config_acp_dma, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(config_acp_dma, "SND_SOC_ACP_COMMON");
static int acp_dma_open(struct snd_soc_component *component, struct snd_pcm_substream *substream)
{
@@ -414,7 +414,7 @@ int acp_platform_register(struct device *dev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_platform_register, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_platform_register, "SND_SOC_ACP_COMMON");
int acp_platform_unregister(struct device *dev)
{
@@ -424,7 +424,7 @@ int acp_platform_unregister(struct device *dev)
platform_device_unregister(adata->mach_dev);
return 0;
}
-EXPORT_SYMBOL_NS_GPL(acp_platform_unregister, SND_SOC_ACP_COMMON);
+EXPORT_SYMBOL_NS_GPL(acp_platform_unregister, "SND_SOC_ACP_COMMON");
MODULE_DESCRIPTION("AMD ACP PCM Driver");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/sound/soc/amd/acp/acp-rembrandt.c b/sound/soc/amd/acp/acp-rembrandt.c
index 008d97598b62..2648256fa129 100644
--- a/sound/soc/amd/acp/acp-rembrandt.c
+++ b/sound/soc/amd/acp/acp-rembrandt.c
@@ -305,6 +305,6 @@ static struct platform_driver rembrandt_driver = {
module_platform_driver(rembrandt_driver);
MODULE_DESCRIPTION("AMD ACP Rembrandt Driver");
-MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/acp/acp-renoir.c b/sound/soc/amd/acp/acp-renoir.c
index 166f1efacf1d..ca2b74283d8f 100644
--- a/sound/soc/amd/acp/acp-renoir.c
+++ b/sound/soc/amd/acp/acp-renoir.c
@@ -254,6 +254,6 @@ static struct platform_driver renoir_driver = {
module_platform_driver(renoir_driver);
MODULE_DESCRIPTION("AMD ACP Renoir Driver");
-MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c
index 48952a238946..9280cd30d19c 100644
--- a/sound/soc/amd/acp/acp-sdw-legacy-mach.c
+++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c
@@ -482,5 +482,5 @@ module_platform_driver(soc_sdw_driver);
MODULE_DESCRIPTION("ASoC AMD SoundWire Legacy Generic Machine driver");
MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);
-MODULE_IMPORT_NS(SND_SOC_AMD_SDW_MACH);
+MODULE_IMPORT_NS("SND_SOC_SDW_UTILS");
+MODULE_IMPORT_NS("SND_SOC_AMD_SDW_MACH");
diff --git a/sound/soc/amd/acp/acp-sdw-mach-common.c b/sound/soc/amd/acp/acp-sdw-mach-common.c
index d9393cc4a302..6f5c39ed1a18 100644
--- a/sound/soc/amd/acp/acp-sdw-mach-common.c
+++ b/sound/soc/amd/acp/acp-sdw-mach-common.c
@@ -57,7 +57,7 @@ int get_acp63_cpu_pin_id(u32 sdw_link_id, int be_id, int *cpu_pin_id, struct dev
}
return 0;
}
-EXPORT_SYMBOL_NS_GPL(get_acp63_cpu_pin_id, SND_SOC_AMD_SDW_MACH);
+EXPORT_SYMBOL_NS_GPL(get_acp63_cpu_pin_id, "SND_SOC_AMD_SDW_MACH");
MODULE_DESCRIPTION("AMD SoundWire Common Machine driver");
MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com>");
diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c
index 0d256c0749c9..c09b1f118a6c 100644
--- a/sound/soc/amd/acp/acp-sdw-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c
@@ -442,5 +442,5 @@ module_platform_driver(sof_sdw_driver);
MODULE_DESCRIPTION("ASoC AMD SoundWire Generic Machine driver");
MODULE_AUTHOR("Vijendar Mukunda <Vijendar.Mukunda@amd.com");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);
-MODULE_IMPORT_NS(SND_SOC_AMD_SDW_MACH);
+MODULE_IMPORT_NS("SND_SOC_SDW_UTILS");
+MODULE_IMPORT_NS("SND_SOC_AMD_SDW_MACH");
diff --git a/sound/soc/amd/acp/acp-sof-mach.c b/sound/soc/amd/acp/acp-sof-mach.c
index 63a9621ede6d..d7b54f12f406 100644
--- a/sound/soc/amd/acp/acp-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sof-mach.c
@@ -169,6 +169,6 @@ static struct platform_driver acp_asoc_audio = {
module_platform_driver(acp_asoc_audio);
-MODULE_IMPORT_NS(SND_SOC_AMD_MACH);
+MODULE_IMPORT_NS("SND_SOC_AMD_MACH");
MODULE_DESCRIPTION("ACP SOF Machine Driver");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/acp/acp63.c b/sound/soc/amd/acp/acp63.c
index e0b86132eb95..81496e713440 100644
--- a/sound/soc/amd/acp/acp63.c
+++ b/sound/soc/amd/acp/acp63.c
@@ -314,6 +314,6 @@ static struct platform_driver acp63_driver = {
module_platform_driver(acp63_driver);
MODULE_DESCRIPTION("AMD ACP acp63 Driver");
-MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/acp/acp70.c b/sound/soc/amd/acp/acp70.c
index 3e4fd113a8a4..9e23729fd1a7 100644
--- a/sound/soc/amd/acp/acp70.c
+++ b/sound/soc/amd/acp/acp70.c
@@ -284,6 +284,6 @@ static struct platform_driver acp70_driver = {
module_platform_driver(acp70_driver);
MODULE_DESCRIPTION("AMD ACP ACP70 Driver");
-MODULE_IMPORT_NS(SND_SOC_ACP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_ACP_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_ALIAS("platform:" DRV_NAME);
diff --git a/sound/soc/amd/acp/amd-sdw-acpi.c b/sound/soc/amd/acp/amd-sdw-acpi.c
index babd841d3296..238b584887ee 100644
--- a/sound/soc/amd/acp/amd-sdw-acpi.c
+++ b/sound/soc/amd/acp/amd-sdw-acpi.c
@@ -56,7 +56,7 @@ int amd_sdw_scan_controller(struct sdw_amd_acpi_info *info)
info->link_mask = sdw_bitmap;
return 0;
}
-EXPORT_SYMBOL_NS(amd_sdw_scan_controller, SND_AMD_SOUNDWIRE_ACPI);
+EXPORT_SYMBOL_NS(amd_sdw_scan_controller, "SND_AMD_SOUNDWIRE_ACPI");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("AMD SoundWire ACPI helpers");
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
index aef73ec6f7ef..4575326d0635 100644
--- a/sound/soc/amd/ps/pci-ps.c
+++ b/sound/soc/amd/ps/pci-ps.c
@@ -375,11 +375,18 @@ static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *a
{
struct acpi_device *pdm_dev;
const union acpi_object *obj;
+ acpi_handle handle;
+ acpi_integer dmic_status;
u32 config;
bool is_dmic_dev = false;
bool is_sdw_dev = false;
+ bool wov_en, dmic_en;
int ret;
+ /* IF WOV entry not found, enable dmic based on acp-audio-device-type entry*/
+ wov_en = true;
+ dmic_en = false;
+
config = readl(acp_data->acp63_base + ACP_PIN_CONFIG);
switch (config) {
case ACP_CONFIG_4:
@@ -412,10 +419,18 @@ static int get_acp63_device_config(struct pci_dev *pci, struct acp63_dev_data *a
if (!acpi_dev_get_property(pdm_dev, "acp-audio-device-type",
ACPI_TYPE_INTEGER, &obj) &&
obj->integer.value == ACP_DMIC_DEV)
- is_dmic_dev = true;
+ dmic_en = true;
}
+
+ handle = ACPI_HANDLE(&pci->dev);
+ ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
+ if (!ACPI_FAILURE(ret))
+ wov_en = dmic_status;
}
+ if (dmic_en && wov_en)
+ is_dmic_dev = true;
+
if (acp_data->is_sdw_config) {
ret = acp_scan_sdw_devices(&pci->dev, ACP63_SDW_ADDR);
if (!ret && acp_data->info.link_mask)
@@ -753,6 +768,6 @@ module_pci_driver(ps_acp63_driver);
MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
MODULE_AUTHOR("Syed.SabaKareem@amd.com");
MODULE_DESCRIPTION("AMD ACP Pink Sardine PCI driver");
-MODULE_IMPORT_NS(SOUNDWIRE_AMD_INIT);
-MODULE_IMPORT_NS(SND_AMD_SOUNDWIRE_ACPI);
+MODULE_IMPORT_NS("SOUNDWIRE_AMD_INIT");
+MODULE_IMPORT_NS("SND_AMD_SOUNDWIRE_ACPI");
MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index 2436e8deb2be..ecf57a6cb7c3 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -224,6 +224,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21M1"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "21M3"),
}
},
@@ -245,6 +252,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
.driver_data = &acp6x_card,
.matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21ME"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
DMI_MATCH(DMI_PRODUCT_NAME, "82QF"),
}
},
@@ -412,6 +426,13 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "TIMI"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Redmi G 2022"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Razer"),
DMI_MATCH(DMI_PRODUCT_NAME, "Blade 14 (2022) - RZ09-0427"),
}
@@ -537,8 +558,14 @@ static int acp6x_probe(struct platform_device *pdev)
struct acp6x_pdm *machine = NULL;
struct snd_soc_card *card;
struct acpi_device *adev;
+ acpi_handle handle;
+ acpi_integer dmic_status;
int ret;
+ bool is_dmic_enable, wov_en;
+ /* IF WOV entry not found, enable dmic based on AcpDmicConnected entry*/
+ is_dmic_enable = false;
+ wov_en = true;
/* check the parent device's firmware node has _DSD or not */
adev = ACPI_COMPANION(pdev->dev.parent);
if (adev) {
@@ -546,9 +573,24 @@ static int acp6x_probe(struct platform_device *pdev)
if (!acpi_dev_get_property(adev, "AcpDmicConnected", ACPI_TYPE_INTEGER, &obj) &&
obj->integer.value == 1)
- platform_set_drvdata(pdev, &acp6x_card);
+ is_dmic_enable = true;
}
+ handle = ACPI_HANDLE(pdev->dev.parent);
+ ret = acpi_evaluate_integer(handle, "_WOV", NULL, &dmic_status);
+ if (!ACPI_FAILURE(ret)) {
+ wov_en = dmic_status;
+ if (!wov_en)
+ return -ENODEV;
+ } else {
+ /* Incase of ACPI method read failure then jump to check_dmi_entry */
+ goto check_dmi_entry;
+ }
+
+ if (is_dmic_enable)
+ platform_set_drvdata(pdev, &acp6x_card);
+
+check_dmi_entry:
/* check for any DMI overrides */
dmi_id = dmi_first_match(yc_acp_quirk_table);
if (dmi_id)
diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c
index c9e7d40c47cc..b4f4696809dd 100644
--- a/sound/soc/apple/mca.c
+++ b/sound/soc/apple/mca.c
@@ -616,7 +616,7 @@ static int mca_fe_hw_params(struct snd_pcm_substream *substream,
tdm_slot_width = 32;
if (tdm_slot_width < params_width(params)) {
- dev_err(dev, "TDM slots too narrow (tdm=%d params=%d)\n",
+ dev_err(dev, "TDM slots too narrow (tdm=%u params=%d)\n",
tdm_slot_width, params_width(params));
return -EINVAL;
}
diff --git a/sound/soc/codecs/cs-amp-lib-test.c b/sound/soc/codecs/cs-amp-lib-test.c
index a6e8348a1bd5..45626f99a417 100644
--- a/sound/soc/codecs/cs-amp-lib-test.c
+++ b/sound/soc/codecs/cs-amp-lib-test.c
@@ -756,7 +756,7 @@ static struct kunit_suite cs_amp_lib_test_suite = {
kunit_test_suite(cs_amp_lib_test_suite);
-MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);
+MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
MODULE_DESCRIPTION("KUnit test for Cirrus Logic amplifier library");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs-amp-lib.c b/sound/soc/codecs/cs-amp-lib.c
index 51b128c80671..c677868c5d5f 100644
--- a/sound/soc/codecs/cs-amp-lib.c
+++ b/sound/soc/codecs/cs-amp-lib.c
@@ -97,7 +97,7 @@ int cs_amp_write_cal_coeffs(struct cs_dsp *dsp,
else
return -ENODEV;
}
-EXPORT_SYMBOL_NS_GPL(cs_amp_write_cal_coeffs, SND_SOC_CS_AMP_LIB);
+EXPORT_SYMBOL_NS_GPL(cs_amp_write_cal_coeffs, "SND_SOC_CS_AMP_LIB");
static efi_status_t cs_amp_get_efi_variable(efi_char16_t *name,
efi_guid_t *guid,
@@ -270,7 +270,7 @@ int cs_amp_get_efi_calibration_data(struct device *dev, u64 target_uid, int amp_
else
return -ENOENT;
}
-EXPORT_SYMBOL_NS_GPL(cs_amp_get_efi_calibration_data, SND_SOC_CS_AMP_LIB);
+EXPORT_SYMBOL_NS_GPL(cs_amp_get_efi_calibration_data, "SND_SOC_CS_AMP_LIB");
static const struct cs_amp_test_hooks cs_amp_test_hook_ptrs = {
.get_efi_variable = cs_amp_get_efi_variable,
@@ -279,9 +279,9 @@ static const struct cs_amp_test_hooks cs_amp_test_hook_ptrs = {
const struct cs_amp_test_hooks * const cs_amp_test_hooks =
PTR_IF(IS_ENABLED(CONFIG_SND_SOC_CS_AMP_LIB_TEST), &cs_amp_test_hook_ptrs);
-EXPORT_SYMBOL_NS_GPL(cs_amp_test_hooks, SND_SOC_CS_AMP_LIB);
+EXPORT_SYMBOL_NS_GPL(cs_amp_test_hooks, "SND_SOC_CS_AMP_LIB");
MODULE_DESCRIPTION("Cirrus Logic amplifier library");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(FW_CS_DSP);
+MODULE_IMPORT_NS("FW_CS_DSP");
diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c
index f5fc42dcc8c7..a09aa3b92ae1 100644
--- a/sound/soc/codecs/cs35l45-i2c.c
+++ b/sound/soc/codecs/cs35l45-i2c.c
@@ -73,4 +73,4 @@ module_i2c_driver(cs35l45_i2c_driver);
MODULE_DESCRIPTION("I2C CS35L45 driver");
MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_CS35L45);
+MODULE_IMPORT_NS("SND_SOC_CS35L45");
diff --git a/sound/soc/codecs/cs35l45-spi.c b/sound/soc/codecs/cs35l45-spi.c
index 39e203a5f060..5f91472c3fd2 100644
--- a/sound/soc/codecs/cs35l45-spi.c
+++ b/sound/soc/codecs/cs35l45-spi.c
@@ -75,4 +75,4 @@ module_spi_driver(cs35l45_spi_driver);
MODULE_DESCRIPTION("SPI CS35L45 driver");
MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_CS35L45);
+MODULE_IMPORT_NS("SND_SOC_CS35L45");
diff --git a/sound/soc/codecs/cs35l45-tables.c b/sound/soc/codecs/cs35l45-tables.c
index 405dab137b3b..d2ecc7b3f619 100644
--- a/sound/soc/codecs/cs35l45-tables.c
+++ b/sound/soc/codecs/cs35l45-tables.c
@@ -38,7 +38,7 @@ int cs35l45_apply_patch(struct cs35l45_private *cs35l45)
return regmap_register_patch(cs35l45->regmap, cs35l45_patch,
ARRAY_SIZE(cs35l45_patch));
}
-EXPORT_SYMBOL_NS_GPL(cs35l45_apply_patch, SND_SOC_CS35L45);
+EXPORT_SYMBOL_NS_GPL(cs35l45_apply_patch, "SND_SOC_CS35L45");
static const struct reg_default cs35l45_defaults[] = {
{ CS35L45_BLOCK_ENABLES, 0x00003323 },
@@ -260,7 +260,7 @@ const struct regmap_config cs35l45_i2c_regmap = {
.readable_reg = cs35l45_readable_reg,
.cache_type = REGCACHE_MAPLE,
};
-EXPORT_SYMBOL_NS_GPL(cs35l45_i2c_regmap, SND_SOC_CS35L45);
+EXPORT_SYMBOL_NS_GPL(cs35l45_i2c_regmap, "SND_SOC_CS35L45");
const struct regmap_config cs35l45_spi_regmap = {
.reg_bits = 32,
@@ -276,7 +276,7 @@ const struct regmap_config cs35l45_spi_regmap = {
.readable_reg = cs35l45_readable_reg,
.cache_type = REGCACHE_MAPLE,
};
-EXPORT_SYMBOL_NS_GPL(cs35l45_spi_regmap, SND_SOC_CS35L45);
+EXPORT_SYMBOL_NS_GPL(cs35l45_spi_regmap, "SND_SOC_CS35L45");
static const struct {
u8 cfg_id;
@@ -329,4 +329,4 @@ int cs35l45_get_clk_freq_id(unsigned int freq)
return -EINVAL;
}
-EXPORT_SYMBOL_NS_GPL(cs35l45_get_clk_freq_id, SND_SOC_CS35L45);
+EXPORT_SYMBOL_NS_GPL(cs35l45_get_clk_freq_id, "SND_SOC_CS35L45");
diff --git a/sound/soc/codecs/cs35l45.c b/sound/soc/codecs/cs35l45.c
index fa1d9d9151f9..432a19f4de2b 100644
--- a/sound/soc/codecs/cs35l45.c
+++ b/sound/soc/codecs/cs35l45.c
@@ -1486,7 +1486,7 @@ err:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs35l45_probe, SND_SOC_CS35L45);
+EXPORT_SYMBOL_NS_GPL(cs35l45_probe, "SND_SOC_CS35L45");
void cs35l45_remove(struct cs35l45_private *cs35l45)
{
@@ -1501,7 +1501,7 @@ void cs35l45_remove(struct cs35l45_private *cs35l45)
/* VDD_BATT must be the last to power-off */
regulator_disable(cs35l45->vdd_batt);
}
-EXPORT_SYMBOL_NS_GPL(cs35l45_remove, SND_SOC_CS35L45);
+EXPORT_SYMBOL_NS_GPL(cs35l45_remove, "SND_SOC_CS35L45");
EXPORT_GPL_DEV_PM_OPS(cs35l45_pm_ops) = {
RUNTIME_PM_OPS(cs35l45_runtime_suspend, cs35l45_runtime_resume, NULL)
diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c
index 2bd2ff75cd50..8a518df1e16e 100644
--- a/sound/soc/codecs/cs35l56-i2c.c
+++ b/sound/soc/codecs/cs35l56-i2c.c
@@ -84,8 +84,8 @@ static struct i2c_driver cs35l56_i2c_driver = {
module_i2c_driver(cs35l56_i2c_driver);
MODULE_DESCRIPTION("ASoC CS35L56 I2C driver");
-MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE);
-MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
+MODULE_IMPORT_NS("SND_SOC_CS35L56_CORE");
+MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c
index 7c9a17fe2195..3f91cb3f9ae7 100644
--- a/sound/soc/codecs/cs35l56-sdw.c
+++ b/sound/soc/codecs/cs35l56-sdw.c
@@ -582,8 +582,8 @@ static struct sdw_driver cs35l56_sdw_driver = {
module_sdw_driver(cs35l56_sdw_driver);
MODULE_DESCRIPTION("ASoC CS35L56 SoundWire driver");
-MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE);
-MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
+MODULE_IMPORT_NS("SND_SOC_CS35L56_CORE");
+MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c
index e45e9ae01bc6..e0ed4fc11155 100644
--- a/sound/soc/codecs/cs35l56-shared.c
+++ b/sound/soc/codecs/cs35l56-shared.c
@@ -49,7 +49,7 @@ int cs35l56_set_patch(struct cs35l56_base *cs35l56_base)
return regmap_register_patch(cs35l56_base->regmap, cs35l56_patch,
ARRAY_SIZE(cs35l56_patch));
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_set_patch, "SND_SOC_CS35L56_SHARED");
static const struct reg_default cs35l56_reg_defaults[] = {
/* no defaults for OTP_MEM - first read populates cache */
@@ -241,7 +241,7 @@ int cs35l56_mbox_send(struct cs35l56_base *cs35l56_base, unsigned int command)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_mbox_send, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_mbox_send, "SND_SOC_CS35L56_SHARED");
int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base)
{
@@ -261,7 +261,7 @@ int cs35l56_firmware_shutdown(struct cs35l56_base *cs35l56_base)
val, ret);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_firmware_shutdown, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_firmware_shutdown, "SND_SOC_CS35L56_SHARED");
int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
{
@@ -287,21 +287,21 @@ int cs35l56_wait_for_firmware_boot(struct cs35l56_base *cs35l56_base)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_wait_for_firmware_boot, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_wait_for_firmware_boot, "SND_SOC_CS35L56_SHARED");
void cs35l56_wait_control_port_ready(void)
{
/* Wait for control port to be ready (datasheet tIRS). */
usleep_range(CS35L56_CONTROL_PORT_READY_US, 2 * CS35L56_CONTROL_PORT_READY_US);
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_wait_control_port_ready, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_wait_control_port_ready, "SND_SOC_CS35L56_SHARED");
void cs35l56_wait_min_reset_pulse(void)
{
/* Satisfy minimum reset pulse width spec */
usleep_range(CS35L56_RESET_PULSE_MIN_US, 2 * CS35L56_RESET_PULSE_MIN_US);
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_wait_min_reset_pulse, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_wait_min_reset_pulse, "SND_SOC_CS35L56_SHARED");
static const struct reg_sequence cs35l56_system_reset_seq[] = {
REG_SEQ0(CS35L56_DSP1_HALO_STATE, 0),
@@ -327,7 +327,7 @@ void cs35l56_system_reset(struct cs35l56_base *cs35l56_base, bool is_soundwire)
/* Leave in cache-only. This will be revoked when the chip has rebooted. */
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_system_reset, "SND_SOC_CS35L56_SHARED");
int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq)
{
@@ -346,7 +346,7 @@ int cs35l56_irq_request(struct cs35l56_base *cs35l56_base, int irq)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_irq_request, "SND_SOC_CS35L56_SHARED");
irqreturn_t cs35l56_irq(int irq, void *data)
{
@@ -413,7 +413,7 @@ err_unlock:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_irq, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_irq, "SND_SOC_CS35L56_SHARED");
int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base)
{
@@ -444,7 +444,7 @@ int cs35l56_is_fw_reload_needed(struct cs35l56_base *cs35l56_base)
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_is_fw_reload_needed, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_is_fw_reload_needed, "SND_SOC_CS35L56_SHARED");
static const struct reg_sequence cs35l56_hibernate_seq[] = {
/* This must be the last register access */
@@ -513,7 +513,7 @@ int cs35l56_runtime_suspend_common(struct cs35l56_base *cs35l56_base)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend_common, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_suspend_common, "SND_SOC_CS35L56_SHARED");
int cs35l56_runtime_resume_common(struct cs35l56_base *cs35l56_base, bool is_soundwire)
{
@@ -565,7 +565,7 @@ err:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_runtime_resume_common, "SND_SOC_CS35L56_SHARED");
static const struct cs_dsp_region cs35l56_dsp1_regions[] = {
{ .type = WMFW_HALO_PM_PACKED, .base = CS35L56_DSP1_PMEM_0 },
@@ -588,7 +588,7 @@ void cs35l56_init_cs_dsp(struct cs35l56_base *cs35l56_base, struct cs_dsp *cs_ds
cs_dsp->num_mems = ARRAY_SIZE(cs35l56_dsp1_regions);
cs_dsp->no_core_startstop = true;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_init_cs_dsp, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_init_cs_dsp, "SND_SOC_CS35L56_SHARED");
struct cs35l56_pte {
u8 x;
@@ -634,7 +634,7 @@ const struct cirrus_amp_cal_controls cs35l56_calibration_controls = {
.status = "CAL_STATUS",
.checksum = "CAL_CHECKSUM",
};
-EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_calibration_controls, "SND_SOC_CS35L56_SHARED");
int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base)
{
@@ -664,7 +664,7 @@ int cs35l56_get_calibration(struct cs35l56_base *cs35l56_base)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_get_calibration, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_get_calibration, "SND_SOC_CS35L56_SHARED");
int cs35l56_read_prot_status(struct cs35l56_base *cs35l56_base,
bool *fw_missing, unsigned int *fw_version)
@@ -688,7 +688,7 @@ int cs35l56_read_prot_status(struct cs35l56_base *cs35l56_base,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_read_prot_status, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_read_prot_status, "SND_SOC_CS35L56_SHARED");
int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
{
@@ -774,7 +774,7 @@ int cs35l56_hw_init(struct cs35l56_base *cs35l56_base)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_hw_init, "SND_SOC_CS35L56_SHARED");
int cs35l56_get_speaker_id(struct cs35l56_base *cs35l56_base)
{
@@ -816,7 +816,7 @@ err:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_get_speaker_id, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_get_speaker_id, "SND_SOC_CS35L56_SHARED");
static const u32 cs35l56_bclk_valid_for_pll_freq_table[] = {
[0x0C] = 128000,
@@ -865,7 +865,7 @@ int cs35l56_get_bclk_freq_id(unsigned int freq)
return -EINVAL;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_get_bclk_freq_id, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_get_bclk_freq_id, "SND_SOC_CS35L56_SHARED");
static const char * const cs35l56_supplies[/* auto-sized */] = {
"VDD_P",
@@ -881,7 +881,7 @@ void cs35l56_fill_supply_names(struct regulator_bulk_data *data)
for (i = 0; i < ARRAY_SIZE(cs35l56_supplies); i++)
data[i].supply = cs35l56_supplies[i];
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_fill_supply_names, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_fill_supply_names, "SND_SOC_CS35L56_SHARED");
const char * const cs35l56_tx_input_texts[] = {
"None", "ASP1RX1", "ASP1RX2", "VMON", "IMON", "ERRVOL", "CLASSH",
@@ -889,7 +889,7 @@ const char * const cs35l56_tx_input_texts[] = {
"DSP1TX5", "DSP1TX6", "DSP1TX7", "DSP1TX8", "TEMPMON",
"INTERPOLATOR", "SDW1RX1", "SDW1RX2",
};
-EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_texts, "SND_SOC_CS35L56_SHARED");
const unsigned int cs35l56_tx_input_values[] = {
CS35L56_INPUT_SRC_NONE,
@@ -914,7 +914,7 @@ const unsigned int cs35l56_tx_input_values[] = {
CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL1,
CS35L56_INPUT_SRC_SWIRE_DP1_CHANNEL2,
};
-EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_tx_input_values, "SND_SOC_CS35L56_SHARED");
const struct regmap_config cs35l56_regmap_i2c = {
.reg_bits = 32,
@@ -930,7 +930,7 @@ const struct regmap_config cs35l56_regmap_i2c = {
.precious_reg = cs35l56_precious_reg,
.cache_type = REGCACHE_MAPLE,
};
-EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_i2c, "SND_SOC_CS35L56_SHARED");
const struct regmap_config cs35l56_regmap_spi = {
.reg_bits = 32,
@@ -947,7 +947,7 @@ const struct regmap_config cs35l56_regmap_spi = {
.precious_reg = cs35l56_precious_reg,
.cache_type = REGCACHE_MAPLE,
};
-EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, "SND_SOC_CS35L56_SHARED");
const struct regmap_config cs35l56_regmap_sdw = {
.reg_bits = 32,
@@ -963,10 +963,10 @@ const struct regmap_config cs35l56_regmap_sdw = {
.precious_reg = cs35l56_precious_reg,
.cache_type = REGCACHE_MAPLE,
};
-EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, SND_SOC_CS35L56_SHARED);
+EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_sdw, "SND_SOC_CS35L56_SHARED");
MODULE_DESCRIPTION("ASoC CS35L56 Shared");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);
+MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
diff --git a/sound/soc/codecs/cs35l56-spi.c b/sound/soc/codecs/cs35l56-spi.c
index b07b798b0b45..c101134e8532 100644
--- a/sound/soc/codecs/cs35l56-spi.c
+++ b/sound/soc/codecs/cs35l56-spi.c
@@ -82,8 +82,8 @@ static struct spi_driver cs35l56_spi_driver = {
module_spi_driver(cs35l56_spi_driver);
MODULE_DESCRIPTION("ASoC CS35L56 SPI driver");
-MODULE_IMPORT_NS(SND_SOC_CS35L56_CORE);
-MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
+MODULE_IMPORT_NS("SND_SOC_CS35L56_CORE");
+MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index 757ade6373ed..ae045c88c48d 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -1341,7 +1341,7 @@ err:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_common_probe, SND_SOC_CS35L56_CORE);
+EXPORT_SYMBOL_NS_GPL(cs35l56_common_probe, "SND_SOC_CS35L56_CORE");
int cs35l56_init(struct cs35l56_private *cs35l56)
{
@@ -1422,7 +1422,7 @@ post_soft_reset:
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_init, SND_SOC_CS35L56_CORE);
+EXPORT_SYMBOL_NS_GPL(cs35l56_init, "SND_SOC_CS35L56_CORE");
void cs35l56_remove(struct cs35l56_private *cs35l56)
{
@@ -1447,7 +1447,7 @@ void cs35l56_remove(struct cs35l56_private *cs35l56)
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
}
-EXPORT_SYMBOL_NS_GPL(cs35l56_remove, SND_SOC_CS35L56_CORE);
+EXPORT_SYMBOL_NS_GPL(cs35l56_remove, "SND_SOC_CS35L56_CORE");
#if IS_ENABLED(CONFIG_SND_SOC_CS35L56_I2C) || IS_ENABLED(CONFIG_SND_SOC_CS35L56_SPI)
EXPORT_NS_GPL_DEV_PM_OPS(cs35l56_pm_ops_i2c_spi, SND_SOC_CS35L56_CORE) = {
@@ -1459,8 +1459,8 @@ EXPORT_NS_GPL_DEV_PM_OPS(cs35l56_pm_ops_i2c_spi, SND_SOC_CS35L56_CORE) = {
#endif
MODULE_DESCRIPTION("ASoC CS35L56 driver");
-MODULE_IMPORT_NS(SND_SOC_CS35L56_SHARED);
-MODULE_IMPORT_NS(SND_SOC_CS_AMP_LIB);
+MODULE_IMPORT_NS("SND_SOC_CS35L56_SHARED");
+MODULE_IMPORT_NS("SND_SOC_CS_AMP_LIB");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_AUTHOR("Simon Trimmer <simont@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c
index 8d10f9328e02..8a1d5c7a61d7 100644
--- a/sound/soc/codecs/cs42l42-i2c.c
+++ b/sound/soc/codecs/cs42l42-i2c.c
@@ -101,4 +101,4 @@ module_i2c_driver(cs42l42_i2c_driver);
MODULE_DESCRIPTION("ASoC CS42L42 I2C driver");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);
+MODULE_IMPORT_NS("SND_SOC_CS42L42_CORE");
diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c
index 29891c1f6bec..ae1401b250a3 100644
--- a/sound/soc/codecs/cs42l42-sdw.c
+++ b/sound/soc/codecs/cs42l42-sdw.c
@@ -622,4 +622,4 @@ module_sdw_driver(cs42l42_sdw_driver);
MODULE_DESCRIPTION("ASoC CS42L42 SoundWire driver");
MODULE_AUTHOR("Richard Fitzgerald <rf@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);
+MODULE_IMPORT_NS("SND_SOC_CS42L42_CORE");
diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c
index 6400ac875e6f..501c951cc327 100644
--- a/sound/soc/codecs/cs42l42.c
+++ b/sound/soc/codecs/cs42l42.c
@@ -329,7 +329,7 @@ bool cs42l42_readable_register(struct device *dev, unsigned int reg)
return false;
}
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_readable_register, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_readable_register, "SND_SOC_CS42L42_CORE");
bool cs42l42_volatile_register(struct device *dev, unsigned int reg)
{
@@ -363,7 +363,7 @@ bool cs42l42_volatile_register(struct device *dev, unsigned int reg)
return false;
}
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_volatile_register, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_volatile_register, "SND_SOC_CS42L42_CORE");
const struct regmap_range_cfg cs42l42_page_range = {
.name = "Pages",
@@ -375,7 +375,7 @@ const struct regmap_range_cfg cs42l42_page_range = {
.window_start = 0,
.window_len = 256,
};
-EXPORT_SYMBOL_NS_GPL(cs42l42_page_range, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_page_range, "SND_SOC_CS42L42_CORE");
const struct regmap_config cs42l42_regmap = {
.reg_bits = 8,
@@ -395,7 +395,7 @@ const struct regmap_config cs42l42_regmap = {
.use_single_read = true,
.use_single_write = true,
};
-EXPORT_SYMBOL_NS_GPL(cs42l42_regmap, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_regmap, "SND_SOC_CS42L42_CORE");
static DECLARE_TLV_DB_SCALE(adc_tlv, -9700, 100, true);
static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true);
@@ -596,7 +596,7 @@ const struct snd_soc_component_driver cs42l42_soc_component = {
.num_controls = ARRAY_SIZE(cs42l42_snd_controls),
.endianness = 1,
};
-EXPORT_SYMBOL_NS_GPL(cs42l42_soc_component, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_soc_component, "SND_SOC_CS42L42_CORE");
/* Switch to SCLK. Atomic delay after the write to allow the switch to complete. */
static const struct reg_sequence cs42l42_to_sclk_seq[] = {
@@ -748,7 +748,7 @@ int cs42l42_pll_config(struct snd_soc_component *component, unsigned int clk,
return -EINVAL;
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_pll_config, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_pll_config, "SND_SOC_CS42L42_CORE");
void cs42l42_src_config(struct snd_soc_component *component, unsigned int sample_rate)
{
@@ -782,7 +782,7 @@ void cs42l42_src_config(struct snd_soc_component *component, unsigned int sample
CS42L42_CLK_OASRC_SEL_MASK,
fs << CS42L42_CLK_OASRC_SEL_SHIFT);
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_src_config, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_src_config, "SND_SOC_CS42L42_CORE");
static int cs42l42_asp_config(struct snd_soc_component *component,
unsigned int sclk, unsigned int sample_rate)
@@ -1116,7 +1116,7 @@ int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_mute_stream, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_mute_stream, "SND_SOC_CS42L42_CORE");
#define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE |\
@@ -1151,7 +1151,7 @@ struct snd_soc_dai_driver cs42l42_dai = {
.symmetric_sample_bits = 1,
.ops = &cs42l42_ops,
};
-EXPORT_SYMBOL_NS_GPL(cs42l42_dai, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_dai, "SND_SOC_CS42L42_CORE");
static void cs42l42_manual_hs_type_detect(struct cs42l42_private *cs42l42)
{
@@ -1780,7 +1780,7 @@ irqreturn_t cs42l42_irq_thread(int irq, void *data)
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_irq_thread, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_irq_thread, "SND_SOC_CS42L42_CORE");
static void cs42l42_set_interrupt_masks(struct cs42l42_private *cs42l42)
{
@@ -2211,7 +2211,7 @@ int cs42l42_suspend(struct device *dev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_suspend, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_suspend, "SND_SOC_CS42L42_CORE");
int cs42l42_resume(struct device *dev)
{
@@ -2242,7 +2242,7 @@ int cs42l42_resume(struct device *dev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_resume, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_resume, "SND_SOC_CS42L42_CORE");
void cs42l42_resume_restore(struct device *dev)
{
@@ -2261,7 +2261,7 @@ void cs42l42_resume_restore(struct device *dev)
dev_dbg(dev, "System resumed\n");
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_resume_restore, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_resume_restore, "SND_SOC_CS42L42_CORE");
static int __maybe_unused cs42l42_i2c_resume(struct device *dev)
{
@@ -2370,7 +2370,7 @@ err_disable_noreset:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_common_probe, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_common_probe, "SND_SOC_CS42L42_CORE");
int cs42l42_init(struct cs42l42_private *cs42l42)
{
@@ -2464,7 +2464,7 @@ err_disable:
cs42l42->supplies);
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_init, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_init, "SND_SOC_CS42L42_CORE");
void cs42l42_common_remove(struct cs42l42_private *cs42l42)
{
@@ -2484,7 +2484,7 @@ void cs42l42_common_remove(struct cs42l42_private *cs42l42)
gpiod_set_value_cansleep(cs42l42->reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), cs42l42->supplies);
}
-EXPORT_SYMBOL_NS_GPL(cs42l42_common_remove, SND_SOC_CS42L42_CORE);
+EXPORT_SYMBOL_NS_GPL(cs42l42_common_remove, "SND_SOC_CS42L42_CORE");
MODULE_DESCRIPTION("ASoC CS42L42 driver");
MODULE_AUTHOR("James Schulman, Cirrus Logic Inc, <james.schulman@cirrus.com>");
diff --git a/sound/soc/codecs/cs42l43-sdw.c b/sound/soc/codecs/cs42l43-sdw.c
index 60c00c05da05..336e88a7a987 100644
--- a/sound/soc/codecs/cs42l43-sdw.c
+++ b/sound/soc/codecs/cs42l43-sdw.c
@@ -42,7 +42,7 @@ int cs42l43_sdw_add_peripheral(struct snd_pcm_substream *substream,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs42l43_sdw_add_peripheral, SND_SOC_CS42L43);
+EXPORT_SYMBOL_NS_GPL(cs42l43_sdw_add_peripheral, "SND_SOC_CS42L43");
int cs42l43_sdw_remove_peripheral(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
@@ -56,7 +56,7 @@ int cs42l43_sdw_remove_peripheral(struct snd_pcm_substream *substream,
return sdw_stream_remove_slave(sdw, sdw_stream);
}
-EXPORT_SYMBOL_NS_GPL(cs42l43_sdw_remove_peripheral, SND_SOC_CS42L43);
+EXPORT_SYMBOL_NS_GPL(cs42l43_sdw_remove_peripheral, "SND_SOC_CS42L43");
int cs42l43_sdw_set_stream(struct snd_soc_dai *dai, void *sdw_stream, int direction)
{
@@ -64,7 +64,7 @@ int cs42l43_sdw_set_stream(struct snd_soc_dai *dai, void *sdw_stream, int direct
return 0;
}
-EXPORT_SYMBOL_NS_GPL(cs42l43_sdw_set_stream, SND_SOC_CS42L43);
+EXPORT_SYMBOL_NS_GPL(cs42l43_sdw_set_stream, "SND_SOC_CS42L43");
MODULE_DESCRIPTION("CS42L43 CODEC SoundWire Driver");
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c
index 3ede0e3110f3..4236f78beec0 100644
--- a/sound/soc/codecs/cs42l43.c
+++ b/sound/soc/codecs/cs42l43.c
@@ -2424,7 +2424,7 @@ static struct platform_driver cs42l43_codec_driver = {
};
module_platform_driver(cs42l43_codec_driver);
-MODULE_IMPORT_NS(SND_SOC_CS42L43);
+MODULE_IMPORT_NS("SND_SOC_CS42L43");
MODULE_DESCRIPTION("CS42L43 CODEC Driver");
MODULE_AUTHOR("Charles Keepax <ckeepax@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/cs42l83-i2c.c b/sound/soc/codecs/cs42l83-i2c.c
index f482b6a4f5c3..42c3e1efdc08 100644
--- a/sound/soc/codecs/cs42l83-i2c.c
+++ b/sound/soc/codecs/cs42l83-i2c.c
@@ -237,4 +237,4 @@ module_i2c_driver(cs42l83_i2c_driver);
MODULE_DESCRIPTION("ASoC CS42L83 I2C driver");
MODULE_AUTHOR("Martin Povišer <povik+lin@cutebit.org>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_CS42L42_CORE);
+MODULE_IMPORT_NS("SND_SOC_CS42L42_CORE");
diff --git a/sound/soc/codecs/cs530x-i2c.c b/sound/soc/codecs/cs530x-i2c.c
index 56659bf735db..22b1a4d6b61c 100644
--- a/sound/soc/codecs/cs530x-i2c.c
+++ b/sound/soc/codecs/cs530x-i2c.c
@@ -67,6 +67,6 @@ static struct i2c_driver cs530x_i2c_driver = {
module_i2c_driver(cs530x_i2c_driver);
MODULE_DESCRIPTION("I2C CS530X driver");
-MODULE_IMPORT_NS(SND_SOC_CS530X);
+MODULE_IMPORT_NS("SND_SOC_CS530X");
MODULE_AUTHOR("Paul Handrigan, Cirrus Logic Inc, <paulha@opensource.cirrus.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs530x.c b/sound/soc/codecs/cs530x.c
index da52afe56c3c..252e66c8449e 100644
--- a/sound/soc/codecs/cs530x.c
+++ b/sound/soc/codecs/cs530x.c
@@ -821,7 +821,7 @@ const struct regmap_config cs530x_regmap = {
.reg_defaults = cs530x_reg_defaults,
.num_reg_defaults = ARRAY_SIZE(cs530x_reg_defaults),
};
-EXPORT_SYMBOL_NS_GPL(cs530x_regmap, SND_SOC_CS530X);
+EXPORT_SYMBOL_NS_GPL(cs530x_regmap, "SND_SOC_CS530X");
static int cs530x_check_device_id(struct cs530x_priv *cs530x)
{
@@ -964,7 +964,7 @@ err_regulator:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(cs530x_probe, SND_SOC_CS530X);
+EXPORT_SYMBOL_NS_GPL(cs530x_probe, "SND_SOC_CS530X");
MODULE_DESCRIPTION("CS530X CODEC Driver");
MODULE_AUTHOR("Paul Handrigan <paulha@opensource.cirrus.com>");
diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c
index 549aa31faed4..b584a3f854b8 100644
--- a/sound/soc/codecs/rt712-sdca-sdw.c
+++ b/sound/soc/codecs/rt712-sdca-sdw.c
@@ -507,4 +507,4 @@ module_sdw_driver(rt712_sdca_sdw_driver);
MODULE_DESCRIPTION("ASoC RT712 SDCA SDW driver");
MODULE_AUTHOR("Shuming Fan <shumingf@realtek.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_SDCA);
+MODULE_IMPORT_NS("SND_SOC_SDCA");
diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c
index 908846e994df..e17a142d03b9 100644
--- a/sound/soc/codecs/rt722-sdca.c
+++ b/sound/soc/codecs/rt722-sdca.c
@@ -1468,13 +1468,18 @@ static void rt722_sdca_jack_preset(struct rt722_sdca_priv *rt722)
0x008d);
/* check HP calibration FSM status */
for (loop_check = 0; loop_check < chk_cnt; loop_check++) {
+ usleep_range(10000, 11000);
ret = rt722_sdca_index_read(rt722, RT722_VENDOR_CALI,
RT722_DAC_DC_CALI_CTL3, &calib_status);
- if (ret < 0 || loop_check == chk_cnt)
+ if (ret < 0)
dev_dbg(&rt722->slave->dev, "calibration failed!, ret=%d\n", ret);
if ((calib_status & 0x0040) == 0x0)
break;
}
+
+ if (loop_check == chk_cnt)
+ dev_dbg(&rt722->slave->dev, "%s, calibration time-out!\n", __func__);
+
/* Set ADC09 power entity floating control */
rt722_sdca_index_write(rt722, RT722_VENDOR_HDA_CTL, RT722_ADC0A_08_PDE_FLOAT_CTL,
0x2a12);
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index 0aeb88abbf52..61d9c220b6a4 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -374,7 +374,7 @@ int tasdevice_rca_parser(void *context, const struct firmware *fmw)
out:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(tasdevice_rca_parser, SND_SOC_TAS2781_FMWLIB);
+EXPORT_SYMBOL_NS_GPL(tasdevice_rca_parser, "SND_SOC_TAS2781_FMWLIB");
/* fixed m68k compiling issue: mapping table can save code field */
static unsigned char map_dev_idx(struct tasdevice_fw *tas_fmw,
@@ -862,7 +862,7 @@ void tasdevice_select_cfg_blk(void *pContext, int conf_no,
__func__, length, blk_data[j]->block_size);
}
}
-EXPORT_SYMBOL_NS_GPL(tasdevice_select_cfg_blk, SND_SOC_TAS2781_FMWLIB);
+EXPORT_SYMBOL_NS_GPL(tasdevice_select_cfg_blk, "SND_SOC_TAS2781_FMWLIB");
static int tasdevice_load_block_kernel(
struct tasdevice_priv *tasdevice, struct tasdev_blk *block)
@@ -1943,7 +1943,7 @@ out:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(tas2781_load_calibration, SND_SOC_TAS2781_FMWLIB);
+EXPORT_SYMBOL_NS_GPL(tas2781_load_calibration, "SND_SOC_TAS2781_FMWLIB");
static int tasdevice_dspfw_ready(const struct firmware *fmw,
void *context)
@@ -2051,7 +2051,7 @@ int tasdevice_dsp_parser(void *context)
out:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(tasdevice_dsp_parser, SND_SOC_TAS2781_FMWLIB);
+EXPORT_SYMBOL_NS_GPL(tasdevice_dsp_parser, "SND_SOC_TAS2781_FMWLIB");
static void tas2781_clear_calfirmware(struct tasdevice_fw *tas_fmw)
{
@@ -2104,7 +2104,7 @@ void tasdevice_calbin_remove(void *context)
tasdev->cali_data_fmw = NULL;
}
}
-EXPORT_SYMBOL_NS_GPL(tasdevice_calbin_remove, SND_SOC_TAS2781_FMWLIB);
+EXPORT_SYMBOL_NS_GPL(tasdevice_calbin_remove, "SND_SOC_TAS2781_FMWLIB");
void tasdevice_config_info_remove(void *context)
{
@@ -2131,7 +2131,7 @@ void tasdevice_config_info_remove(void *context)
}
kfree(ci);
}
-EXPORT_SYMBOL_NS_GPL(tasdevice_config_info_remove, SND_SOC_TAS2781_FMWLIB);
+EXPORT_SYMBOL_NS_GPL(tasdevice_config_info_remove, "SND_SOC_TAS2781_FMWLIB");
static int tasdevice_load_data(struct tasdevice_priv *tas_priv,
struct tasdevice_data *dev_data)
@@ -2311,8 +2311,7 @@ int tasdevice_select_tuningprm_cfg(void *context, int prm_no,
out:
return prog_status;
}
-EXPORT_SYMBOL_NS_GPL(tasdevice_select_tuningprm_cfg,
- SND_SOC_TAS2781_FMWLIB);
+EXPORT_SYMBOL_NS_GPL(tasdevice_select_tuningprm_cfg, "SND_SOC_TAS2781_FMWLIB");
int tasdevice_prmg_load(void *context, int prm_no)
{
@@ -2357,7 +2356,7 @@ int tasdevice_prmg_load(void *context, int prm_no)
out:
return prog_status;
}
-EXPORT_SYMBOL_NS_GPL(tasdevice_prmg_load, SND_SOC_TAS2781_FMWLIB);
+EXPORT_SYMBOL_NS_GPL(tasdevice_prmg_load, "SND_SOC_TAS2781_FMWLIB");
void tasdevice_tuning_switch(void *context, int state)
{
@@ -2393,8 +2392,7 @@ void tasdevice_tuning_switch(void *context, int state)
TASDEVICE_BIN_BLK_PRE_SHUTDOWN);
}
}
-EXPORT_SYMBOL_NS_GPL(tasdevice_tuning_switch,
- SND_SOC_TAS2781_FMWLIB);
+EXPORT_SYMBOL_NS_GPL(tasdevice_tuning_switch, "SND_SOC_TAS2781_FMWLIB");
MODULE_DESCRIPTION("Texas Firmware Support");
MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c
index e41f81eb8d16..fb8cd2284fe8 100644
--- a/sound/soc/codecs/tas2781-i2c.c
+++ b/sound/soc/codecs/tas2781-i2c.c
@@ -370,7 +370,7 @@ static void sngl_calib_start(struct tasdevice_priv *tas_priv, int i,
tasdevice_dev_read(tas_priv, i, p[j].reg,
(int *)&p[j].val[0]);
} else {
- switch (p[j].reg) {
+ switch (tas2781_cali_start_reg[j].reg) {
case 0: {
if (!reg[0])
continue;
@@ -1746,4 +1746,4 @@ MODULE_AUTHOR("Shenghao Ding <shenghao-ding@ti.com>");
MODULE_AUTHOR("Kevin Lu <kevin-lu@ti.com>");
MODULE_DESCRIPTION("ASoC TAS2781 Driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_TAS2781_FMWLIB);
+MODULE_IMPORT_NS("SND_SOC_TAS2781_FMWLIB");
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index e69283195f36..91c8697c29c3 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -2098,4 +2098,4 @@ static const struct cs_dsp_client_ops wm_adsp2_client_ops = {
MODULE_DESCRIPTION("Cirrus Logic ASoC DSP Support");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(FW_CS_DSP);
+MODULE_IMPORT_NS("FW_CS_DSP");
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 8e88830e8e57..678540b78280 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -29,8 +29,8 @@ config SND_SOC_FSL_SAI
config SND_SOC_FSL_MQS
tristate "Medium Quality Sound (MQS) module support"
depends on SND_SOC_FSL_SAI
+ depends on IMX_SCMI_MISC_DRV || !IMX_SCMI_MISC_DRV
select REGMAP_MMIO
- select IMX_SCMI_MISC_DRV if IMX_SCMI_MISC_EXT !=n
help
Say Y if you want to add Medium Quality Sound (MQS)
support for the Freescale CPUs.
diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c
index b6ff04f7138a..ee946e0d3f49 100644
--- a/sound/soc/fsl/fsl_spdif.c
+++ b/sound/soc/fsl/fsl_spdif.c
@@ -1204,7 +1204,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = {
},
/* DPLL lock info get controller */
{
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = RX_SAMPLE_RATE_KCONTROL,
.access = SNDRV_CTL_ELEM_ACCESS_READ |
SNDRV_CTL_ELEM_ACCESS_VOLATILE,
diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c
index 1e0bfd59d511..9c184ab73468 100644
--- a/sound/soc/fsl/fsl_xcvr.c
+++ b/sound/soc/fsl/fsl_xcvr.c
@@ -171,7 +171,7 @@ static int fsl_xcvr_capds_put(struct snd_kcontrol *kcontrol,
}
static struct snd_kcontrol_new fsl_xcvr_earc_capds_kctl = {
- .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capabilities Data Structure",
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
.info = fsl_xcvr_type_capds_bytes_info,
diff --git a/sound/soc/fsl/imx-audmix.c b/sound/soc/fsl/imx-audmix.c
index dcf770b55c4b..231400661c90 100644
--- a/sound/soc/fsl/imx-audmix.c
+++ b/sound/soc/fsl/imx-audmix.c
@@ -274,6 +274,9 @@ static int imx_audmix_probe(struct platform_device *pdev)
/* Add AUDMIX Backend */
be_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
"audmix-%d", i);
+ if (!be_name)
+ return -ENOMEM;
+
priv->dai[num_dai + i].cpus = &dlc[1];
priv->dai[num_dai + i].codecs = &snd_soc_dummy_dlc;
diff --git a/sound/soc/generic/audio-graph-card2.c b/sound/soc/generic/audio-graph-card2.c
index 5280c1b20d85..1f5c4e8ff1b9 100644
--- a/sound/soc/generic/audio-graph-card2.c
+++ b/sound/soc/generic/audio-graph-card2.c
@@ -771,7 +771,7 @@ static void graph_link_init(struct simple_util_priv *priv,
of_node_get(port_codec);
if (graph_lnk_is_multi(port_codec)) {
ep_codec = graph_get_next_multi_ep(&port_codec);
- of_node_put(port_cpu);
+ of_node_put(port_codec);
port_codec = ep_to_port(ep_codec);
} else {
ep_codec = of_graph_get_next_port_endpoint(port_codec, NULL);
diff --git a/sound/soc/intel/avs/boards/da7219.c b/sound/soc/intel/avs/boards/da7219.c
index 93eba4fd2771..76078a7005b0 100644
--- a/sound/soc/intel/avs/boards/da7219.c
+++ b/sound/soc/intel/avs/boards/da7219.c
@@ -209,21 +209,6 @@ static int avs_create_dai_link(struct device *dev, const char *platform_name, in
return 0;
}
-static int avs_card_suspend_pre(struct snd_soc_card *card)
-{
- struct snd_soc_dai *codec_dai = snd_soc_card_get_codec_dai(card, DA7219_DAI_NAME);
-
- return snd_soc_component_set_jack(codec_dai->component, NULL, NULL);
-}
-
-static int avs_card_resume_post(struct snd_soc_card *card)
-{
- struct snd_soc_dai *codec_dai = snd_soc_card_get_codec_dai(card, DA7219_DAI_NAME);
- struct snd_soc_jack *jack = snd_soc_card_get_drvdata(card);
-
- return snd_soc_component_set_jack(codec_dai->component, jack, NULL);
-}
-
static int avs_da7219_probe(struct platform_device *pdev)
{
struct snd_soc_dai_link *dai_link;
@@ -255,8 +240,6 @@ static int avs_da7219_probe(struct platform_device *pdev)
card->name = "avs_da7219";
card->dev = dev;
card->owner = THIS_MODULE;
- card->suspend_pre = avs_card_suspend_pre;
- card->resume_post = avs_card_resume_post;
card->dai_link = dai_link;
card->num_links = 1;
card->controls = card_controls;
diff --git a/sound/soc/intel/boards/ehl_rt5660.c b/sound/soc/intel/boards/ehl_rt5660.c
index ebc417c04a50..5c7b218f22b7 100644
--- a/sound/soc/intel/boards/ehl_rt5660.c
+++ b/sound/soc/intel/boards/ehl_rt5660.c
@@ -313,4 +313,4 @@ module_platform_driver(snd_ehl_rt5660_driver);
MODULE_DESCRIPTION("ASoC Intel(R) Elkhartlake + rt5660 Machine driver");
MODULE_AUTHOR("libin.yang@intel.com");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON");
diff --git a/sound/soc/intel/boards/hda_dsp_common.c b/sound/soc/intel/boards/hda_dsp_common.c
index fda5a92b0006..86e541a2c204 100644
--- a/sound/soc/intel/boards/hda_dsp_common.c
+++ b/sound/soc/intel/boards/hda_dsp_common.c
@@ -83,7 +83,7 @@ int hda_dsp_hdmi_build_controls(struct snd_soc_card *card,
return err;
}
-EXPORT_SYMBOL_NS(hda_dsp_hdmi_build_controls, SND_SOC_INTEL_HDA_DSP_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_hdmi_build_controls, "SND_SOC_INTEL_HDA_DSP_COMMON");
#endif
diff --git a/sound/soc/intel/boards/skl_hda_dsp_generic.c b/sound/soc/intel/boards/skl_hda_dsp_generic.c
index 9edd6d985cf1..22668bac74a1 100644
--- a/sound/soc/intel/boards/skl_hda_dsp_generic.c
+++ b/sound/soc/intel/boards/skl_hda_dsp_generic.c
@@ -164,4 +164,4 @@ MODULE_DESCRIPTION("SKL/KBL/BXT/APL HDA Generic Machine driver");
MODULE_AUTHOR("Rakesh Ughreja <rakesh.a.ughreja@intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:skl_hda_dsp_generic");
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_BOARD_HELPERS");
diff --git a/sound/soc/intel/boards/sof_board_helpers.c b/sound/soc/intel/boards/sof_board_helpers.c
index 50e846d67c19..2ea1dda446ec 100644
--- a/sound/soc/intel/boards/sof_board_helpers.c
+++ b/sound/soc/intel/boards/sof_board_helpers.c
@@ -35,7 +35,7 @@ int sof_intel_board_card_late_probe(struct snd_soc_card *card)
return hda_dsp_hdmi_build_controls(card, ctx->hdmi.hdmi_comp);
}
-EXPORT_SYMBOL_NS(sof_intel_board_card_late_probe, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+EXPORT_SYMBOL_NS(sof_intel_board_card_late_probe, "SND_SOC_INTEL_SOF_BOARD_HELPERS");
/*
* DMIC DAI Link
@@ -731,7 +731,7 @@ int sof_intel_board_set_dai_link(struct device *dev, struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+EXPORT_SYMBOL_NS(sof_intel_board_set_dai_link, "SND_SOC_INTEL_SOF_BOARD_HELPERS");
struct sof_card_private *
sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk)
@@ -774,10 +774,10 @@ sof_intel_board_get_ctx(struct device *dev, unsigned long board_quirk)
return ctx;
}
-EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, SND_SOC_INTEL_SOF_BOARD_HELPERS);
+EXPORT_SYMBOL_NS(sof_intel_board_get_ctx, "SND_SOC_INTEL_SOF_BOARD_HELPERS");
MODULE_DESCRIPTION("ASoC Intel SOF Machine Driver Board Helpers");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
-MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH);
+MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON");
+MODULE_IMPORT_NS("SND_SOC_ACPI_INTEL_MATCH");
diff --git a/sound/soc/intel/boards/sof_cirrus_common.c b/sound/soc/intel/boards/sof_cirrus_common.c
index e71e09124b34..8db7695b9747 100644
--- a/sound/soc/intel/boards/sof_cirrus_common.c
+++ b/sound/soc/intel/boards/sof_cirrus_common.c
@@ -193,14 +193,14 @@ void cs35l41_set_dai_link(struct snd_soc_dai_link *link)
link->init = cs35l41_init;
link->ops = &cs35l41_ops;
}
-EXPORT_SYMBOL_NS(cs35l41_set_dai_link, SND_SOC_INTEL_SOF_CIRRUS_COMMON);
+EXPORT_SYMBOL_NS(cs35l41_set_dai_link, "SND_SOC_INTEL_SOF_CIRRUS_COMMON");
void cs35l41_set_codec_conf(struct snd_soc_card *card)
{
card->codec_conf = cs35l41_codec_conf;
card->num_configs = ARRAY_SIZE(cs35l41_codec_conf);
}
-EXPORT_SYMBOL_NS(cs35l41_set_codec_conf, SND_SOC_INTEL_SOF_CIRRUS_COMMON);
+EXPORT_SYMBOL_NS(cs35l41_set_codec_conf, "SND_SOC_INTEL_SOF_CIRRUS_COMMON");
MODULE_DESCRIPTION("ASoC Intel SOF Cirrus Logic helpers");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/boards/sof_cs42l42.c b/sound/soc/intel/boards/sof_cs42l42.c
index f4fee2ee0d63..455c5bc8c634 100644
--- a/sound/soc/intel/boards/sof_cs42l42.c
+++ b/sound/soc/intel/boards/sof_cs42l42.c
@@ -303,5 +303,5 @@ module_platform_driver(sof_audio)
MODULE_DESCRIPTION("SOF Audio Machine driver for CS42L42");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_BOARD_HELPERS");
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_MAXIM_COMMON");
diff --git a/sound/soc/intel/boards/sof_da7219.c b/sound/soc/intel/boards/sof_da7219.c
index fa1f7d2d8278..9b7082b239c1 100644
--- a/sound/soc/intel/boards/sof_da7219.c
+++ b/sound/soc/intel/boards/sof_da7219.c
@@ -487,5 +487,5 @@ MODULE_DESCRIPTION("ASoC Intel(R) SOF Machine driver for Dialog codec");
MODULE_AUTHOR("Yong Zhi <yong.zhi@intel.com>");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_BOARD_HELPERS");
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_MAXIM_COMMON");
diff --git a/sound/soc/intel/boards/sof_es8336.c b/sound/soc/intel/boards/sof_es8336.c
index a92707876851..a0b3679b17b4 100644
--- a/sound/soc/intel/boards/sof_es8336.c
+++ b/sound/soc/intel/boards/sof_es8336.c
@@ -843,4 +843,4 @@ module_platform_driver(sof_es8336_driver);
MODULE_DESCRIPTION("ASoC Intel(R) SOF + ES8336 Machine driver");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON");
diff --git a/sound/soc/intel/boards/sof_maxim_common.c b/sound/soc/intel/boards/sof_maxim_common.c
index fcc3b95e57a4..c98a67ae5e66 100644
--- a/sound/soc/intel/boards/sof_maxim_common.c
+++ b/sound/soc/intel/boards/sof_maxim_common.c
@@ -283,14 +283,14 @@ void max_98373_dai_link(struct device *dev, struct snd_soc_dai_link *link)
link->init = max_98373_spk_codec_init;
link->ops = &max_98373_ops;
}
-EXPORT_SYMBOL_NS(max_98373_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
+EXPORT_SYMBOL_NS(max_98373_dai_link, "SND_SOC_INTEL_SOF_MAXIM_COMMON");
void max_98373_set_codec_conf(struct snd_soc_card *card)
{
card->codec_conf = max_98373_codec_conf;
card->num_configs = ARRAY_SIZE(max_98373_codec_conf);
}
-EXPORT_SYMBOL_NS(max_98373_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);
+EXPORT_SYMBOL_NS(max_98373_set_codec_conf, "SND_SOC_INTEL_SOF_MAXIM_COMMON");
/*
* Maxim MAX98390
@@ -506,7 +506,7 @@ void max_98390_dai_link(struct device *dev, struct snd_soc_dai_link *link)
link->init = max_98390_init;
link->ops = &max_98390_ops;
}
-EXPORT_SYMBOL_NS(max_98390_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
+EXPORT_SYMBOL_NS(max_98390_dai_link, "SND_SOC_INTEL_SOF_MAXIM_COMMON");
void max_98390_set_codec_conf(struct device *dev, struct snd_soc_card *card)
{
@@ -529,7 +529,7 @@ void max_98390_set_codec_conf(struct device *dev, struct snd_soc_card *card)
break;
}
}
-EXPORT_SYMBOL_NS(max_98390_set_codec_conf, SND_SOC_INTEL_SOF_MAXIM_COMMON);
+EXPORT_SYMBOL_NS(max_98390_set_codec_conf, "SND_SOC_INTEL_SOF_MAXIM_COMMON");
/*
* Maxim MAX98357A/MAX98360A
@@ -596,7 +596,7 @@ void max_98357a_dai_link(struct snd_soc_dai_link *link)
link->num_codecs = ARRAY_SIZE(max_98357a_components);
link->init = max_98357a_init;
}
-EXPORT_SYMBOL_NS(max_98357a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
+EXPORT_SYMBOL_NS(max_98357a_dai_link, "SND_SOC_INTEL_SOF_MAXIM_COMMON");
void max_98360a_dai_link(struct snd_soc_dai_link *link)
{
@@ -604,7 +604,7 @@ void max_98360a_dai_link(struct snd_soc_dai_link *link)
link->num_codecs = ARRAY_SIZE(max_98360a_components);
link->init = max_98357a_init;
}
-EXPORT_SYMBOL_NS(max_98360a_dai_link, SND_SOC_INTEL_SOF_MAXIM_COMMON);
+EXPORT_SYMBOL_NS(max_98360a_dai_link, "SND_SOC_INTEL_SOF_MAXIM_COMMON");
MODULE_DESCRIPTION("ASoC Intel SOF Maxim helpers");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/boards/sof_nau8825.c b/sound/soc/intel/boards/sof_nau8825.c
index bfe17acbc161..72ce32e2cd57 100644
--- a/sound/soc/intel/boards/sof_nau8825.c
+++ b/sound/soc/intel/boards/sof_nau8825.c
@@ -339,7 +339,7 @@ MODULE_AUTHOR("David Lin <ctlin0@nuvoton.com>");
MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_NUVOTON_COMMON);
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_BOARD_HELPERS");
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_MAXIM_COMMON");
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_NUVOTON_COMMON");
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_REALTEK_COMMON");
diff --git a/sound/soc/intel/boards/sof_nuvoton_common.c b/sound/soc/intel/boards/sof_nuvoton_common.c
index 549a412f5d53..ed41cb6f7fa5 100644
--- a/sound/soc/intel/boards/sof_nuvoton_common.c
+++ b/sound/soc/intel/boards/sof_nuvoton_common.c
@@ -67,7 +67,7 @@ void nau8318_set_dai_link(struct snd_soc_dai_link *link)
link->num_codecs = ARRAY_SIZE(nau8318_components);
link->init = nau8318_init;
}
-EXPORT_SYMBOL_NS(nau8318_set_dai_link, SND_SOC_INTEL_SOF_NUVOTON_COMMON);
+EXPORT_SYMBOL_NS(nau8318_set_dai_link, "SND_SOC_INTEL_SOF_NUVOTON_COMMON");
MODULE_DESCRIPTION("ASoC Intel SOF Nuvoton helpers");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/boards/sof_pcm512x.c b/sound/soc/intel/boards/sof_pcm512x.c
index 68380b738d88..2f43710c1bae 100644
--- a/sound/soc/intel/boards/sof_pcm512x.c
+++ b/sound/soc/intel/boards/sof_pcm512x.c
@@ -440,4 +440,4 @@ MODULE_DESCRIPTION("ASoC Intel(R) SOF + PCM512x Machine driver");
MODULE_AUTHOR("Pierre-Louis Bossart");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:sof_pcm512x");
-MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
+MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON");
diff --git a/sound/soc/intel/boards/sof_realtek_common.c b/sound/soc/intel/boards/sof_realtek_common.c
index f52e25083905..600707d403b9 100644
--- a/sound/soc/intel/boards/sof_realtek_common.c
+++ b/sound/soc/intel/boards/sof_realtek_common.c
@@ -276,7 +276,7 @@ void sof_rt1011_dai_link(struct device *dev, struct snd_soc_dai_link *link)
link->init = rt1011_init;
link->ops = &rt1011_ops;
}
-EXPORT_SYMBOL_NS(sof_rt1011_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
+EXPORT_SYMBOL_NS(sof_rt1011_dai_link, "SND_SOC_INTEL_SOF_REALTEK_COMMON");
void sof_rt1011_codec_conf(struct device *dev, struct snd_soc_card *card)
{
@@ -306,7 +306,7 @@ void sof_rt1011_codec_conf(struct device *dev, struct snd_soc_card *card)
}
}
-EXPORT_SYMBOL_NS(sof_rt1011_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
+EXPORT_SYMBOL_NS(sof_rt1011_codec_conf, "SND_SOC_INTEL_SOF_REALTEK_COMMON");
/*
* rt1015: i2c mode driver for ALC1015 and ALC1015Q
@@ -374,12 +374,12 @@ void sof_rt1015p_dai_link(struct snd_soc_dai_link *link)
link->init = rt1015p_init;
link->ops = &rt1015p_ops;
}
-EXPORT_SYMBOL_NS(sof_rt1015p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
+EXPORT_SYMBOL_NS(sof_rt1015p_dai_link, "SND_SOC_INTEL_SOF_REALTEK_COMMON");
void sof_rt1015p_codec_conf(struct snd_soc_card *card)
{
}
-EXPORT_SYMBOL_NS(sof_rt1015p_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
+EXPORT_SYMBOL_NS(sof_rt1015p_codec_conf, "SND_SOC_INTEL_SOF_REALTEK_COMMON");
/*
* RT1015 audio amplifier
@@ -523,7 +523,7 @@ void sof_rt1015_codec_conf(struct snd_soc_card *card)
card->codec_conf = rt1015_amp_conf;
card->num_configs = ARRAY_SIZE(rt1015_amp_conf);
}
-EXPORT_SYMBOL_NS(sof_rt1015_codec_conf, SND_SOC_INTEL_SOF_REALTEK_COMMON);
+EXPORT_SYMBOL_NS(sof_rt1015_codec_conf, "SND_SOC_INTEL_SOF_REALTEK_COMMON");
void sof_rt1015_dai_link(struct snd_soc_dai_link *link)
{
@@ -532,7 +532,7 @@ void sof_rt1015_dai_link(struct snd_soc_dai_link *link)
link->init = speaker_codec_init_lr;
link->ops = &rt1015_ops;
}
-EXPORT_SYMBOL_NS(sof_rt1015_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
+EXPORT_SYMBOL_NS(sof_rt1015_dai_link, "SND_SOC_INTEL_SOF_REALTEK_COMMON");
/*
* RT1308 audio amplifier
@@ -628,7 +628,7 @@ void sof_rt1308_dai_link(struct snd_soc_dai_link *link)
link->init = rt1308_init;
link->ops = &rt1308_ops;
}
-EXPORT_SYMBOL_NS(sof_rt1308_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
+EXPORT_SYMBOL_NS(sof_rt1308_dai_link, "SND_SOC_INTEL_SOF_REALTEK_COMMON");
/*
* 2-amp Configuration for RT1019
@@ -681,7 +681,7 @@ void sof_rt1019p_dai_link(struct snd_soc_dai_link *link)
link->num_codecs = ARRAY_SIZE(rt1019p_components);
link->init = rt1019p_init;
}
-EXPORT_SYMBOL_NS(sof_rt1019p_dai_link, SND_SOC_INTEL_SOF_REALTEK_COMMON);
+EXPORT_SYMBOL_NS(sof_rt1019p_dai_link, "SND_SOC_INTEL_SOF_REALTEK_COMMON");
MODULE_DESCRIPTION("ASoC Intel SOF Realtek helpers");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c
index 5ceb376d4924..f5925bd0a3fc 100644
--- a/sound/soc/intel/boards/sof_rt5682.c
+++ b/sound/soc/intel/boards/sof_rt5682.c
@@ -913,6 +913,6 @@ MODULE_AUTHOR("Sathya Prakash M R <sathya.prakash.m.r@intel.com>");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_AUTHOR("Mac Chiang <mac.chiang@intel.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_MAXIM_COMMON);
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_BOARD_HELPERS");
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_MAXIM_COMMON");
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_REALTEK_COMMON");
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index ea5249df8ac3..c9f9c9b0de9b 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -632,7 +632,7 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "233C")
+ DMI_MATCH(DMI_PRODUCT_NAME, "21QB")
},
/* Note this quirk excludes the CODEC mic */
.driver_data = (void *)(SOC_SDW_CODEC_MIC),
@@ -641,9 +641,26 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
.callback = sof_sdw_quirk_cb,
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
- DMI_EXACT_MATCH(DMI_PRODUCT_SKU, "233B")
+ DMI_MATCH(DMI_PRODUCT_NAME, "21QA")
},
- .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS),
+ /* Note this quirk excludes the CODEC mic */
+ .driver_data = (void *)(SOC_SDW_CODEC_MIC),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21Q6")
+ },
+ .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
+ },
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "21Q7")
+ },
+ .driver_data = (void *)(SOC_SDW_SIDECAR_AMPS | SOC_SDW_CODEC_MIC),
},
/* ArrowLake devices */
@@ -1067,8 +1084,12 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
return ret;
}
- /* One per DAI link, worst case is a DAI link for every endpoint */
- sof_dais = kcalloc(num_ends, sizeof(*sof_dais), GFP_KERNEL);
+ /*
+ * One per DAI link, worst case is a DAI link for every endpoint, also
+ * add one additional to act as a terminator such that code can iterate
+ * until it hits an uninitialised DAI.
+ */
+ sof_dais = kcalloc(num_ends + 1, sizeof(*sof_dais), GFP_KERNEL);
if (!sof_dais)
return -ENOMEM;
@@ -1325,5 +1346,5 @@ MODULE_AUTHOR("Bard Liao <yung-chuan.liao@linux.intel.com>");
MODULE_AUTHOR("Rander Wang <rander.wang@linux.intel.com>");
MODULE_AUTHOR("Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(SND_SOC_INTEL_HDA_DSP_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SDW_UTILS);
+MODULE_IMPORT_NS("SND_SOC_INTEL_HDA_DSP_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SDW_UTILS");
diff --git a/sound/soc/intel/boards/sof_ssp_amp.c b/sound/soc/intel/boards/sof_ssp_amp.c
index 6ff8895a294a..48ee5353bdf1 100644
--- a/sound/soc/intel/boards/sof_ssp_amp.c
+++ b/sound/soc/intel/boards/sof_ssp_amp.c
@@ -234,6 +234,6 @@ MODULE_DESCRIPTION("ASoC Intel(R) SOF Amplifier Machine driver");
MODULE_AUTHOR("Balamurugan C <balamurugan.c@intel.com>");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_BOARD_HELPERS);
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_REALTEK_COMMON);
-MODULE_IMPORT_NS(SND_SOC_INTEL_SOF_CIRRUS_COMMON);
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_BOARD_HELPERS");
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_REALTEK_COMMON");
+MODULE_IMPORT_NS("SND_SOC_INTEL_SOF_CIRRUS_COMMON");
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index 0b37465b6c53..03fc5a187012 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -893,4 +893,4 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_mtl_sdw_machines);
-MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_SDCA_QUIRKS);
+MODULE_IMPORT_NS("SND_SOC_ACPI_INTEL_SDCA_QUIRKS");
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
index 0b7076606d66..3eaa058f8460 100644
--- a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
+++ b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
@@ -35,8 +35,8 @@ bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg)
return false;
}
-EXPORT_SYMBOL_NS(snd_soc_acpi_intel_sdca_is_device_rt712_vb, SND_SOC_ACPI_INTEL_SDCA_QUIRKS);
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_sdca_is_device_rt712_vb, "SND_SOC_ACPI_INTEL_SDCA_QUIRKS");
MODULE_DESCRIPTION("ASoC ACPI Intel SDCA quirks");
MODULE_LICENSE("GPL");
-MODULE_IMPORT_NS(SND_SOC_SDCA);
+MODULE_IMPORT_NS("SND_SOC_SDCA");
diff --git a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c
index de7a3f7f47f1..f56f4bfa5187 100644
--- a/sound/soc/intel/common/soc-acpi-intel-ssp-common.c
+++ b/sound/soc/intel/common/soc-acpi-intel-ssp-common.c
@@ -90,7 +90,7 @@ snd_soc_acpi_intel_detect_codec_type(struct device *dev)
return CODEC_NONE;
}
-EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_codec_type, SND_SOC_ACPI_INTEL_MATCH);
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_codec_type, "SND_SOC_ACPI_INTEL_MATCH");
enum snd_soc_acpi_intel_codec
snd_soc_acpi_intel_detect_amp_type(struct device *dev)
@@ -107,7 +107,7 @@ snd_soc_acpi_intel_detect_amp_type(struct device *dev)
return CODEC_NONE;
}
-EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_amp_type, SND_SOC_ACPI_INTEL_MATCH);
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_detect_amp_type, "SND_SOC_ACPI_INTEL_MATCH");
const char *
snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type)
@@ -129,7 +129,7 @@ snd_soc_acpi_intel_get_codec_name(enum snd_soc_acpi_intel_codec codec_type)
return NULL;
}
-EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, SND_SOC_ACPI_INTEL_MATCH);
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_name, "SND_SOC_ACPI_INTEL_MATCH");
const char *
snd_soc_acpi_intel_get_codec_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)
@@ -145,7 +145,7 @@ snd_soc_acpi_intel_get_codec_tplg_suffix(enum snd_soc_acpi_intel_codec codec_typ
return NULL;
}
-EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_tplg_suffix, SND_SOC_ACPI_INTEL_MATCH);
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_codec_tplg_suffix, "SND_SOC_ACPI_INTEL_MATCH");
const char *
snd_soc_acpi_intel_get_amp_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)
@@ -161,7 +161,7 @@ snd_soc_acpi_intel_get_amp_tplg_suffix(enum snd_soc_acpi_intel_codec codec_type)
return NULL;
}
-EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_amp_tplg_suffix, SND_SOC_ACPI_INTEL_MATCH);
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_get_amp_tplg_suffix, "SND_SOC_ACPI_INTEL_MATCH");
MODULE_DESCRIPTION("ASoC Intel SOF Common Machine Driver Helpers");
MODULE_AUTHOR("Brent Lu <brent.lu@intel.com>");
diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
index 9b72b2a7ae91..6b6330583941 100644
--- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c
+++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
@@ -120,8 +120,8 @@ int mtk_afe_pcm_new(struct snd_soc_component *component,
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
size = afe->mtk_afe_hardware->buffer_bytes_max;
- snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV,
- afe->dev, size, size);
+ snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, afe->dev, 0, size);
+
return 0;
}
EXPORT_SYMBOL_GPL(mtk_afe_pcm_new);
diff --git a/sound/soc/mediatek/mt8188/mt8188-mt6359.c b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
index 84abdba9ddb6..2d0d04e0232d 100644
--- a/sound/soc/mediatek/mt8188/mt8188-mt6359.c
+++ b/sound/soc/mediatek/mt8188/mt8188-mt6359.c
@@ -188,9 +188,7 @@ SND_SOC_DAILINK_DEFS(pcm1,
SND_SOC_DAILINK_DEFS(ul_src,
DAILINK_COMP_ARRAY(COMP_CPU("UL_SRC")),
DAILINK_COMP_ARRAY(COMP_CODEC("mt6359-sound",
- "mt6359-snd-codec-aif1"),
- COMP_CODEC("dmic-codec",
- "dmic-hifi")),
+ "mt6359-snd-codec-aif1")),
DAILINK_COMP_ARRAY(COMP_EMPTY()));
SND_SOC_DAILINK_DEFS(AFE_SOF_DL2,
@@ -1277,10 +1275,12 @@ static int mt8188_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data,
for_each_card_prelinks(card, i, dai_link) {
if (strcmp(dai_link->name, "DPTX_BE") == 0) {
- if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
+ if (dai_link->num_codecs &&
+ strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
dai_link->init = mt8188_dptx_codec_init;
} else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) {
- if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
+ if (dai_link->num_codecs &&
+ strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
dai_link->init = mt8188_hdmi_codec_init;
} else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 ||
strcmp(dai_link->name, "UL_SRC_BE") == 0) {
@@ -1292,6 +1292,9 @@ static int mt8188_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data,
strcmp(dai_link->name, "ETDM2_OUT_BE") == 0 ||
strcmp(dai_link->name, "ETDM1_IN_BE") == 0 ||
strcmp(dai_link->name, "ETDM2_IN_BE") == 0) {
+ if (!dai_link->num_codecs)
+ continue;
+
if (!strcmp(dai_link->codecs->dai_name, MAX98390_CODEC_DAI)) {
/*
* The TDM protocol settings with fixed 4 slots are defined in
diff --git a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
index 1aba9c75594e..b1598cc5587e 100644
--- a/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
+++ b/sound/soc/mediatek/mt8192/mt8192-mt6359-rt1015-rt5682.c
@@ -1091,7 +1091,7 @@ static int mt8192_mt6359_legacy_probe(struct mtk_soc_card_data *soc_card_data)
dai_link->ignore = 0;
}
- if (dai_link->num_codecs && dai_link->codecs[0].dai_name &&
+ if (dai_link->num_codecs &&
strcmp(dai_link->codecs[0].dai_name, RT1015_CODEC_DAI) == 0)
dai_link->ops = &mt8192_rt1015_i2s_ops;
}
@@ -1119,7 +1119,7 @@ static int mt8192_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data,
int i;
for_each_card_prelinks(card, i, dai_link)
- if (dai_link->num_codecs && dai_link->codecs[0].dai_name &&
+ if (dai_link->num_codecs &&
strcmp(dai_link->codecs[0].dai_name, RT1015_CODEC_DAI) == 0)
dai_link->ops = &mt8192_rt1015_i2s_ops;
}
diff --git a/sound/soc/mediatek/mt8195/mt8195-mt6359.c b/sound/soc/mediatek/mt8195/mt8195-mt6359.c
index 56b9d2433a1e..2b9cb3248795 100644
--- a/sound/soc/mediatek/mt8195/mt8195-mt6359.c
+++ b/sound/soc/mediatek/mt8195/mt8195-mt6359.c
@@ -1378,10 +1378,12 @@ static int mt8195_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data,
for_each_card_prelinks(card, i, dai_link) {
if (strcmp(dai_link->name, "DPTX_BE") == 0) {
- if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
+ if (dai_link->num_codecs &&
+ strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
dai_link->init = mt8195_dptx_codec_init;
} else if (strcmp(dai_link->name, "ETDM3_OUT_BE") == 0) {
- if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
+ if (dai_link->num_codecs &&
+ strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
dai_link->init = mt8195_hdmi_codec_init;
} else if (strcmp(dai_link->name, "DL_SRC_BE") == 0 ||
strcmp(dai_link->name, "UL_SRC1_BE") == 0 ||
@@ -1394,6 +1396,9 @@ static int mt8195_mt6359_soc_card_probe(struct mtk_soc_card_data *soc_card_data,
strcmp(dai_link->name, "ETDM2_OUT_BE") == 0 ||
strcmp(dai_link->name, "ETDM1_IN_BE") == 0 ||
strcmp(dai_link->name, "ETDM2_IN_BE") == 0) {
+ if (!dai_link->num_codecs)
+ continue;
+
if (!strcmp(dai_link->codecs->dai_name, MAX98390_CODEC_DAI)) {
if (!(codec_init & MAX98390_CODEC_INIT)) {
dai_link->init = mt8195_max98390_init;
diff --git a/sound/soc/sdca/sdca_device.c b/sound/soc/sdca/sdca_device.c
index c44dc21cb634..80d663777eb5 100644
--- a/sound/soc/sdca/sdca_device.c
+++ b/sound/soc/sdca/sdca_device.c
@@ -22,7 +22,7 @@ void sdca_lookup_interface_revision(struct sdw_slave *slave)
fwnode_property_read_u32(fwnode, "mipi-sdw-sdca-interface-revision",
&slave->sdca_data.interface_revision);
}
-EXPORT_SYMBOL_NS(sdca_lookup_interface_revision, SND_SOC_SDCA);
+EXPORT_SYMBOL_NS(sdca_lookup_interface_revision, "SND_SOC_SDCA");
static bool sdca_device_quirk_rt712_vb(struct sdw_slave *slave)
{
@@ -64,4 +64,4 @@ bool sdca_device_quirk_match(struct sdw_slave *slave, enum sdca_quirk quirk)
}
return false;
}
-EXPORT_SYMBOL_NS(sdca_device_quirk_match, SND_SOC_SDCA);
+EXPORT_SYMBOL_NS(sdca_device_quirk_match, "SND_SOC_SDCA");
diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c
index e6e5629c7054..652865329968 100644
--- a/sound/soc/sdca/sdca_functions.c
+++ b/sound/soc/sdca/sdca_functions.c
@@ -171,7 +171,7 @@ void sdca_lookup_functions(struct sdw_slave *slave)
}
acpi_dev_for_each_child(adev, find_sdca_function, &slave->sdca_data);
}
-EXPORT_SYMBOL_NS(sdca_lookup_functions, SND_SOC_SDCA);
+EXPORT_SYMBOL_NS(sdca_lookup_functions, "SND_SOC_SDCA");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SDCA library");
diff --git a/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c b/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c
index fcc3ef685af7..246e5c2e0af5 100644
--- a/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c
+++ b/sound/soc/sdw_utils/soc_sdw_bridge_cs35l56.c
@@ -112,7 +112,7 @@ int asoc_sdw_bridge_cs35l56_count_sidecar(struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_count_sidecar, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_count_sidecar, "SND_SOC_SDW_UTILS");
int asoc_sdw_bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
struct snd_soc_dai_link **dai_links,
@@ -134,7 +134,7 @@ int asoc_sdw_bridge_cs35l56_add_sidecar(struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_add_sidecar, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_add_sidecar, "SND_SOC_SDW_UTILS");
int asoc_sdw_bridge_cs35l56_spk_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
@@ -148,4 +148,4 @@ int asoc_sdw_bridge_cs35l56_spk_init(struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_spk_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_bridge_cs35l56_spk_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_cs42l42.c b/sound/soc/sdw_utils/soc_sdw_cs42l42.c
index 78a6cb059ac0..f37c1793991a 100644
--- a/sound/soc/sdw_utils/soc_sdw_cs42l42.c
+++ b/sound/soc/sdw_utils/soc_sdw_cs42l42.c
@@ -88,4 +88,4 @@ int asoc_sdw_cs42l42_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_da
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_cs42l42_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_cs42l42_rtd_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_cs42l43.c b/sound/soc/sdw_utils/soc_sdw_cs42l43.c
index adb1c008e871..668c9d28a1c1 100644
--- a/sound/soc/sdw_utils/soc_sdw_cs42l43.c
+++ b/sound/soc/sdw_utils/soc_sdw_cs42l43.c
@@ -100,7 +100,7 @@ int asoc_sdw_cs42l43_hs_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_hs_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_hs_rtd_init, "SND_SOC_SDW_UTILS");
int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
{
@@ -124,7 +124,7 @@ int asoc_sdw_cs42l43_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_so
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_spk_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_spk_rtd_init, "SND_SOC_SDW_UTILS");
int asoc_sdw_cs42l43_spk_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
@@ -139,7 +139,7 @@ int asoc_sdw_cs42l43_spk_init(struct snd_soc_card *card,
return asoc_sdw_bridge_cs35l56_spk_init(card, dai_links, info, playback);
}
-EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_spk_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_spk_init, "SND_SOC_SDW_UTILS");
int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
{
@@ -158,4 +158,4 @@ int asoc_sdw_cs42l43_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_s
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_dmic_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_cs42l43_dmic_rtd_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_cs_amp.c b/sound/soc/sdw_utils/soc_sdw_cs_amp.c
index 58b059b68016..a0bb626c5cb8 100644
--- a/sound/soc/sdw_utils/soc_sdw_cs_amp.c
+++ b/sound/soc/sdw_utils/soc_sdw_cs_amp.c
@@ -46,7 +46,7 @@ int asoc_sdw_cs_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_cs_spk_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_cs_spk_rtd_init, "SND_SOC_SDW_UTILS");
int asoc_sdw_cs_amp_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
@@ -61,4 +61,4 @@ int asoc_sdw_cs_amp_init(struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_cs_amp_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_cs_amp_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_dmic.c b/sound/soc/sdw_utils/soc_sdw_dmic.c
index fc2aae985084..0d8fce7234a7 100644
--- a/sound/soc/sdw_utils/soc_sdw_dmic.c
+++ b/sound/soc/sdw_utils/soc_sdw_dmic.c
@@ -42,4 +42,4 @@ int asoc_sdw_dmic_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_dmic_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_dmic_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_maxim.c b/sound/soc/sdw_utils/soc_sdw_maxim.c
index cdcd8df37e1d..5df8d9cae60c 100644
--- a/sound/soc/sdw_utils/soc_sdw_maxim.c
+++ b/sound/soc/sdw_utils/soc_sdw_maxim.c
@@ -43,7 +43,7 @@ int asoc_sdw_maxim_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_maxim_spk_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_maxim_spk_rtd_init, "SND_SOC_SDW_UTILS");
static int asoc_sdw_mx8373_enable_spk_pin(struct snd_pcm_substream *substream, bool enable)
{
@@ -145,4 +145,4 @@ int asoc_sdw_maxim_init(struct snd_soc_card *card,
}
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_maxim_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_maxim_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_rt5682.c b/sound/soc/sdw_utils/soc_sdw_rt5682.c
index 80b4caa92667..8c86254cbaf6 100644
--- a/sound/soc/sdw_utils/soc_sdw_rt5682.c
+++ b/sound/soc/sdw_utils/soc_sdw_rt5682.c
@@ -88,4 +88,4 @@ int asoc_sdw_rt5682_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt5682_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt5682_rtd_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_rt700.c b/sound/soc/sdw_utils/soc_sdw_rt700.c
index 4dbeeeca3434..e6468e4ac6e7 100644
--- a/sound/soc/sdw_utils/soc_sdw_rt700.c
+++ b/sound/soc/sdw_utils/soc_sdw_rt700.c
@@ -85,4 +85,4 @@ int asoc_sdw_rt700_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt700_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt700_rtd_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_rt711.c b/sound/soc/sdw_utils/soc_sdw_rt711.c
index 38b4126dd45f..4aa93fdefef6 100644
--- a/sound/soc/sdw_utils/soc_sdw_rt711.c
+++ b/sound/soc/sdw_utils/soc_sdw_rt711.c
@@ -112,7 +112,7 @@ int asoc_sdw_rt711_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt711_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt711_rtd_init, "SND_SOC_SDW_UTILS");
int asoc_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
{
@@ -126,7 +126,7 @@ int asoc_sdw_rt711_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt711_exit, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt711_exit, "SND_SOC_SDW_UTILS");
int asoc_sdw_rt711_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
@@ -157,4 +157,4 @@ int asoc_sdw_rt711_init(struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt711_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt711_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_rt_amp.c b/sound/soc/sdw_utils/soc_sdw_rt_amp.c
index 6951dfb56526..0538c252ba69 100644
--- a/sound/soc/sdw_utils/soc_sdw_rt_amp.c
+++ b/sound/soc/sdw_utils/soc_sdw_rt_amp.c
@@ -210,7 +210,7 @@ int asoc_sdw_rt_amp_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_spk_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_spk_rtd_init, "SND_SOC_SDW_UTILS");
static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
@@ -248,7 +248,7 @@ static int rt1308_i2s_hw_params(struct snd_pcm_substream *substream,
const struct snd_soc_ops soc_sdw_rt1308_i2s_ops = {
.hw_params = rt1308_i2s_hw_params,
};
-EXPORT_SYMBOL_NS(soc_sdw_rt1308_i2s_ops, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(soc_sdw_rt1308_i2s_ops, "SND_SOC_SDW_UTILS");
int asoc_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
{
@@ -266,7 +266,7 @@ int asoc_sdw_rt_amp_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_exit, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_exit, "SND_SOC_SDW_UTILS");
int asoc_sdw_rt_amp_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
@@ -309,4 +309,4 @@ int asoc_sdw_rt_amp_init(struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt_amp_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_rt_dmic.c b/sound/soc/sdw_utils/soc_sdw_rt_dmic.c
index 7f24806d809d..46d917a99c51 100644
--- a/sound/soc/sdw_utils/soc_sdw_rt_dmic.c
+++ b/sound/soc/sdw_utils/soc_sdw_rt_dmic.c
@@ -40,4 +40,4 @@ int asoc_sdw_rt_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_da
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt_dmic_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt_dmic_rtd_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c b/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
index 81e43319876e..0161b14297d5 100644
--- a/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
+++ b/sound/soc/sdw_utils/soc_sdw_rt_mf_sdca.c
@@ -87,4 +87,4 @@ int asoc_sdw_rt_mf_sdca_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt_mf_sdca_spk_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt_mf_sdca_spk_rtd_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c b/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c
index af43efbb8f79..6279faf6edd4 100644
--- a/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c
+++ b/sound/soc/sdw_utils/soc_sdw_rt_sdca_jack_common.c
@@ -170,7 +170,7 @@ int asoc_sdw_rt_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_s
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_rtd_init, "SND_SOC_SDW_UTILS");
int asoc_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
{
@@ -188,7 +188,7 @@ int asoc_sdw_rt_sdca_jack_exit(struct snd_soc_card *card, struct snd_soc_dai_lin
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_exit, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_exit, "SND_SOC_SDW_UTILS");
int asoc_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
struct snd_soc_dai_link *dai_links,
@@ -219,4 +219,4 @@ int asoc_sdw_rt_sdca_jack_init(struct snd_soc_card *card,
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rt_sdca_jack_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 19bd02e2cd6d..937fa3ce59df 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -622,13 +622,13 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_num = 1,
},
};
-EXPORT_SYMBOL_NS(codec_info_list, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(codec_info_list, "SND_SOC_SDW_UTILS");
int asoc_sdw_get_codec_info_list_count(void)
{
return ARRAY_SIZE(codec_info_list);
};
-EXPORT_SYMBOL_NS(asoc_sdw_get_codec_info_list_count, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_get_codec_info_list_count, "SND_SOC_SDW_UTILS");
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr)
{
@@ -649,7 +649,7 @@ struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_part(const u64 adr)
return NULL;
}
-EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_part, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_part, "SND_SOC_SDW_UTILS");
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_acpi(const u8 *acpi_id)
{
@@ -664,7 +664,7 @@ struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_acpi(const u8 *acpi_id)
return NULL;
}
-EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_acpi, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_acpi, "SND_SOC_SDW_UTILS");
struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_dai(const char *dai_name, int *dai_index)
{
@@ -681,7 +681,7 @@ struct asoc_sdw_codec_info *asoc_sdw_find_codec_info_dai(const char *dai_name, i
return NULL;
}
-EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_dai, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_find_codec_info_dai, "SND_SOC_SDW_UTILS");
int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
{
@@ -745,14 +745,14 @@ skip_add_controls_widgets:
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_rtd_init, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_rtd_init, "SND_SOC_SDW_UTILS");
/* these wrappers are only needed to avoid typecast compilation errors */
int asoc_sdw_startup(struct snd_pcm_substream *substream)
{
return sdw_startup_stream(substream);
}
-EXPORT_SYMBOL_NS(asoc_sdw_startup, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_startup, "SND_SOC_SDW_UTILS");
int asoc_sdw_prepare(struct snd_pcm_substream *substream)
{
@@ -771,7 +771,7 @@ int asoc_sdw_prepare(struct snd_pcm_substream *substream)
return sdw_prepare_stream(sdw_stream);
}
-EXPORT_SYMBOL_NS(asoc_sdw_prepare, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_prepare, "SND_SOC_SDW_UTILS");
int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd)
{
@@ -811,7 +811,7 @@ int asoc_sdw_trigger(struct snd_pcm_substream *substream, int cmd)
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_trigger, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_trigger, "SND_SOC_SDW_UTILS");
int asoc_sdw_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
@@ -854,7 +854,7 @@ int asoc_sdw_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_hw_params, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_hw_params, "SND_SOC_SDW_UTILS");
int asoc_sdw_hw_free(struct snd_pcm_substream *substream)
{
@@ -873,13 +873,13 @@ int asoc_sdw_hw_free(struct snd_pcm_substream *substream)
return sdw_deprepare_stream(sdw_stream);
}
-EXPORT_SYMBOL_NS(asoc_sdw_hw_free, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_hw_free, "SND_SOC_SDW_UTILS");
void asoc_sdw_shutdown(struct snd_pcm_substream *substream)
{
sdw_shutdown_stream(substream);
}
-EXPORT_SYMBOL_NS(asoc_sdw_shutdown, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_shutdown, "SND_SOC_SDW_UTILS");
static bool asoc_sdw_is_unique_device(const struct snd_soc_acpi_link_adr *adr_link,
unsigned int sdw_version,
@@ -940,7 +940,7 @@ const char *asoc_sdw_get_codec_name(struct device *dev,
return NULL;
}
-EXPORT_SYMBOL_NS(asoc_sdw_get_codec_name, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_get_codec_name, "SND_SOC_SDW_UTILS");
/* helper to get the link that the codec DAI is used */
struct snd_soc_dai_link *asoc_sdw_mc_find_codec_dai_used(struct snd_soc_card *card,
@@ -959,7 +959,7 @@ struct snd_soc_dai_link *asoc_sdw_mc_find_codec_dai_used(struct snd_soc_card *ca
}
return NULL;
}
-EXPORT_SYMBOL_NS(asoc_sdw_mc_find_codec_dai_used, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_mc_find_codec_dai_used, "SND_SOC_SDW_UTILS");
void asoc_sdw_mc_dailink_exit_loop(struct snd_soc_card *card)
{
@@ -992,7 +992,7 @@ void asoc_sdw_mc_dailink_exit_loop(struct snd_soc_card *card)
}
}
}
-EXPORT_SYMBOL_NS(asoc_sdw_mc_dailink_exit_loop, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_mc_dailink_exit_loop, "SND_SOC_SDW_UTILS");
int asoc_sdw_card_late_probe(struct snd_soc_card *card)
{
@@ -1008,7 +1008,7 @@ int asoc_sdw_card_late_probe(struct snd_soc_card *card)
}
return ret;
}
-EXPORT_SYMBOL_NS(asoc_sdw_card_late_probe, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_card_late_probe, "SND_SOC_SDW_UTILS");
void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
int *be_id, char *name, int playback, int capture,
@@ -1035,7 +1035,7 @@ void asoc_sdw_init_dai_link(struct device *dev, struct snd_soc_dai_link *dai_lin
dai_links->init = init;
dai_links->ops = ops;
}
-EXPORT_SYMBOL_NS(asoc_sdw_init_dai_link, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_init_dai_link, "SND_SOC_SDW_UTILS");
int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *dai_links,
int *be_id, char *name, int playback, int capture,
@@ -1064,7 +1064,7 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_init_simple_dai_link, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_init_simple_dai_link, "SND_SOC_SDW_UTILS");
int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *num_ends)
{
@@ -1085,7 +1085,7 @@ int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card, int *num_devs, int *
return 0;
}
-EXPORT_SYMBOL_NS(asoc_sdw_count_sdw_endpoints, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_count_sdw_endpoints, "SND_SOC_SDW_UTILS");
struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks,
const struct snd_soc_acpi_endpoint *new)
@@ -1103,7 +1103,7 @@ struct asoc_sdw_dailink *asoc_sdw_find_dailink(struct asoc_sdw_dailink *dailinks
return dailinks;
}
-EXPORT_SYMBOL_NS(asoc_sdw_find_dailink, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_find_dailink, "SND_SOC_SDW_UTILS");
int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
struct asoc_sdw_dailink *soc_dais,
@@ -1226,7 +1226,7 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
return num_dais;
}
-EXPORT_SYMBOL_NS(asoc_sdw_parse_sdw_endpoints, SND_SOC_SDW_UTILS);
+EXPORT_SYMBOL_NS(asoc_sdw_parse_sdw_endpoints, "SND_SOC_SDW_UTILS");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SoundWire ASoC helpers");
diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c
index fc792956bb97..0c3a92f5f942 100644
--- a/sound/soc/sof/amd/acp-common.c
+++ b/sound/soc/sof/amd/acp-common.c
@@ -258,10 +258,10 @@ const struct snd_sof_dsp_ops sof_acp_common_ops = {
.register_ipc_clients = acp_probes_register,
.unregister_ipc_clients = acp_probes_unregister,
};
-EXPORT_SYMBOL_NS(sof_acp_common_ops, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(sof_acp_common_ops, "SND_SOC_SOF_AMD_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("ACP SOF COMMON Driver");
-MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
-MODULE_IMPORT_NS(SOUNDWIRE_AMD_INIT);
+MODULE_IMPORT_NS("SND_SOC_SOF_AMD_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
+MODULE_IMPORT_NS("SOUNDWIRE_AMD_INIT");
diff --git a/sound/soc/sof/amd/acp-ipc.c b/sound/soc/sof/amd/acp-ipc.c
index b44b1b1adb6e..5f371d9263f3 100644
--- a/sound/soc/sof/amd/acp-ipc.c
+++ b/sound/soc/sof/amd/acp-ipc.c
@@ -19,13 +19,13 @@ void acp_mailbox_write(struct snd_sof_dev *sdev, u32 offset, void *message, size
{
memcpy_to_scratch(sdev, offset, message, bytes);
}
-EXPORT_SYMBOL_NS(acp_mailbox_write, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_mailbox_write, "SND_SOC_SOF_AMD_COMMON");
void acp_mailbox_read(struct snd_sof_dev *sdev, u32 offset, void *message, size_t bytes)
{
memcpy_from_scratch(sdev, offset, message, bytes);
}
-EXPORT_SYMBOL_NS(acp_mailbox_read, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_mailbox_read, "SND_SOC_SOF_AMD_COMMON");
static void acpbus_trigger_host_to_dsp_swintr(struct acp_dev_data *adata)
{
@@ -91,7 +91,7 @@ int acp_sof_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
return 0;
}
-EXPORT_SYMBOL_NS(acp_sof_ipc_send_msg, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_sof_ipc_send_msg, "SND_SOC_SOF_AMD_COMMON");
static void acp_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
{
@@ -235,7 +235,7 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context)
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS(acp_sof_ipc_irq_thread, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_sof_ipc_irq_thread, "SND_SOC_SOF_AMD_COMMON");
int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sps,
void *p, size_t sz)
@@ -261,7 +261,7 @@ int acp_sof_ipc_msg_data(struct snd_sof_dev *sdev, struct snd_sof_pcm_stream *sp
return 0;
}
-EXPORT_SYMBOL_NS(acp_sof_ipc_msg_data, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_sof_ipc_msg_data, "SND_SOC_SOF_AMD_COMMON");
int acp_set_stream_data_offset(struct snd_sof_dev *sdev,
struct snd_sof_pcm_stream *sps,
@@ -282,7 +282,7 @@ int acp_set_stream_data_offset(struct snd_sof_dev *sdev,
return 0;
}
-EXPORT_SYMBOL_NS(acp_set_stream_data_offset, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_set_stream_data_offset, "SND_SOC_SOF_AMD_COMMON");
int acp_sof_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
{
@@ -290,12 +290,12 @@ int acp_sof_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
return desc->sram_pte_offset;
}
-EXPORT_SYMBOL_NS(acp_sof_ipc_get_mailbox_offset, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_sof_ipc_get_mailbox_offset, "SND_SOC_SOF_AMD_COMMON");
int acp_sof_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
{
return 0;
}
-EXPORT_SYMBOL_NS(acp_sof_ipc_get_window_offset, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_sof_ipc_get_window_offset, "SND_SOC_SOF_AMD_COMMON");
MODULE_DESCRIPTION("AMD ACP sof-ipc driver");
diff --git a/sound/soc/sof/amd/acp-loader.c b/sound/soc/sof/amd/acp-loader.c
index 077af9e2af8d..ea105227227d 100644
--- a/sound/soc/sof/amd/acp-loader.c
+++ b/sound/soc/sof/amd/acp-loader.c
@@ -44,7 +44,7 @@ int acp_dsp_block_read(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_ty
return 0;
}
-EXPORT_SYMBOL_NS(acp_dsp_block_read, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_dsp_block_read, "SND_SOC_SOF_AMD_COMMON");
int acp_dsp_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_type,
u32 offset, void *src, size_t size)
@@ -106,13 +106,13 @@ int acp_dsp_block_write(struct snd_sof_dev *sdev, enum snd_sof_fw_blk_type blk_t
memcpy(dest, src, size);
return 0;
}
-EXPORT_SYMBOL_NS(acp_dsp_block_write, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_dsp_block_write, "SND_SOC_SOF_AMD_COMMON");
int acp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
{
return type;
}
-EXPORT_SYMBOL_NS(acp_get_bar_index, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_get_bar_index, "SND_SOC_SOF_AMD_COMMON");
static void configure_pte_for_fw_loading(int type, int num_pages, struct acp_dev_data *adata)
{
@@ -244,7 +244,7 @@ int acp_dsp_pre_fw_run(struct snd_sof_dev *sdev)
}
return ret;
}
-EXPORT_SYMBOL_NS(acp_dsp_pre_fw_run, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_dsp_pre_fw_run, "SND_SOC_SOF_AMD_COMMON");
int acp_sof_dsp_run(struct snd_sof_dev *sdev)
{
@@ -264,7 +264,7 @@ int acp_sof_dsp_run(struct snd_sof_dev *sdev)
}
return 0;
}
-EXPORT_SYMBOL_NS(acp_sof_dsp_run, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_sof_dsp_run, "SND_SOC_SOF_AMD_COMMON");
int acp_sof_load_signed_firmware(struct snd_sof_dev *sdev)
{
@@ -317,4 +317,4 @@ int acp_sof_load_signed_firmware(struct snd_sof_dev *sdev)
adata->fw_dbin->size);
return ret;
}
-EXPORT_SYMBOL_NS(acp_sof_load_signed_firmware, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_sof_load_signed_firmware, "SND_SOC_SOF_AMD_COMMON");
diff --git a/sound/soc/sof/amd/acp-pcm.c b/sound/soc/sof/amd/acp-pcm.c
index cee0b1154874..2802684f26de 100644
--- a/sound/soc/sof/amd/acp-pcm.c
+++ b/sound/soc/sof/amd/acp-pcm.c
@@ -52,7 +52,7 @@ int acp_pcm_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_substream *substr
return 0;
}
-EXPORT_SYMBOL_NS(acp_pcm_hw_params, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_pcm_hw_params, "SND_SOC_SOF_AMD_COMMON");
int acp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream)
{
@@ -67,7 +67,7 @@ int acp_pcm_open(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream)
return 0;
}
-EXPORT_SYMBOL_NS(acp_pcm_open, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_pcm_open, "SND_SOC_SOF_AMD_COMMON");
int acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream)
{
@@ -84,7 +84,7 @@ int acp_pcm_close(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream)
return acp_dsp_stream_put(sdev, stream);
}
-EXPORT_SYMBOL_NS(acp_pcm_close, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_pcm_close, "SND_SOC_SOF_AMD_COMMON");
snd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
@@ -117,4 +117,4 @@ snd_pcm_uframes_t acp_pcm_pointer(struct snd_sof_dev *sdev,
return pos;
}
-EXPORT_SYMBOL_NS(acp_pcm_pointer, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_pcm_pointer, "SND_SOC_SOF_AMD_COMMON");
diff --git a/sound/soc/sof/amd/acp-probes.c b/sound/soc/sof/amd/acp-probes.c
index 778cf1a8b610..0d0f8ec4aed8 100644
--- a/sound/soc/sof/amd/acp-probes.c
+++ b/sound/soc/sof/amd/acp-probes.c
@@ -135,13 +135,13 @@ int acp_probes_register(struct snd_sof_dev *sdev)
return sof_client_dev_register(sdev, "acp-probes", 0, &acp_probes_ops,
sizeof(acp_probes_ops));
}
-EXPORT_SYMBOL_NS(acp_probes_register, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_probes_register, "SND_SOC_SOF_AMD_COMMON");
void acp_probes_unregister(struct snd_sof_dev *sdev)
{
sof_client_dev_unregister(sdev, "acp-probes", 0);
}
-EXPORT_SYMBOL_NS(acp_probes_unregister, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_probes_unregister, "SND_SOC_SOF_AMD_COMMON");
-MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
+MODULE_IMPORT_NS("SND_SOC_SOF_CLIENT");
diff --git a/sound/soc/sof/amd/acp-stream.c b/sound/soc/sof/amd/acp-stream.c
index 6f40ef7ba85e..9212a3137cfd 100644
--- a/sound/soc/sof/amd/acp-stream.c
+++ b/sound/soc/sof/amd/acp-stream.c
@@ -150,7 +150,7 @@ struct acp_dsp_stream *acp_dsp_stream_get(struct snd_sof_dev *sdev, int tag)
dev_err(sdev->dev, "stream %d active or no inactive stream\n", tag);
return NULL;
}
-EXPORT_SYMBOL_NS(acp_dsp_stream_get, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_dsp_stream_get, "SND_SOC_SOF_AMD_COMMON");
int acp_dsp_stream_put(struct snd_sof_dev *sdev,
struct acp_dsp_stream *acp_stream)
@@ -170,7 +170,7 @@ int acp_dsp_stream_put(struct snd_sof_dev *sdev,
dev_err(sdev->dev, "Cannot find active stream tag %d\n", acp_stream->stream_tag);
return -EINVAL;
}
-EXPORT_SYMBOL_NS(acp_dsp_stream_put, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_dsp_stream_put, "SND_SOC_SOF_AMD_COMMON");
int acp_dsp_stream_init(struct snd_sof_dev *sdev)
{
@@ -184,4 +184,4 @@ int acp_dsp_stream_init(struct snd_sof_dev *sdev)
}
return 0;
}
-EXPORT_SYMBOL_NS(acp_dsp_stream_init, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_dsp_stream_init, "SND_SOC_SOF_AMD_COMMON");
diff --git a/sound/soc/sof/amd/acp-trace.c b/sound/soc/sof/amd/acp-trace.c
index c9482b27cbe3..0bd1f5990e8c 100644
--- a/sound/soc/sof/amd/acp-trace.c
+++ b/sound/soc/sof/amd/acp-trace.c
@@ -32,7 +32,7 @@ int acp_sof_trace_release(struct snd_sof_dev *sdev)
adata->dtrace_stream = NULL;
return 0;
}
-EXPORT_SYMBOL_NS(acp_sof_trace_release, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_sof_trace_release, "SND_SOC_SOF_AMD_COMMON");
int acp_sof_trace_init(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab,
struct sof_ipc_dma_trace_params_ext *dtrace_params)
@@ -61,4 +61,4 @@ int acp_sof_trace_init(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab,
return 0;
}
-EXPORT_SYMBOL_NS(acp_sof_trace_init, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(acp_sof_trace_init, "SND_SOC_SOF_AMD_COMMON");
diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
index f7814dadf3ba..33648ff8b833 100644
--- a/sound/soc/sof/amd/acp.c
+++ b/sound/soc/sof/amd/acp.c
@@ -633,7 +633,7 @@ int amd_sof_acp_suspend(struct snd_sof_dev *sdev, u32 target_state)
return 0;
}
-EXPORT_SYMBOL_NS(amd_sof_acp_suspend, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(amd_sof_acp_suspend, "SND_SOC_SOF_AMD_COMMON");
int amd_sof_acp_resume(struct snd_sof_dev *sdev)
{
@@ -652,7 +652,7 @@ int amd_sof_acp_resume(struct snd_sof_dev *sdev)
return acp_dsp_reset(sdev);
}
}
-EXPORT_SYMBOL_NS(amd_sof_acp_resume, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(amd_sof_acp_resume, "SND_SOC_SOF_AMD_COMMON");
#if IS_ENABLED(CONFIG_SND_SOC_SOF_AMD_SOUNDWIRE)
static int acp_sof_scan_sdw_devices(struct snd_sof_dev *sdev, u64 addr)
@@ -852,7 +852,7 @@ unregister_dev:
platform_device_unregister(adata->dmic_dev);
return ret;
}
-EXPORT_SYMBOL_NS(amd_sof_acp_probe, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(amd_sof_acp_probe, "SND_SOC_SOF_AMD_COMMON");
void amd_sof_acp_remove(struct snd_sof_dev *sdev)
{
@@ -872,9 +872,9 @@ void amd_sof_acp_remove(struct snd_sof_dev *sdev)
acp_reset(sdev);
}
-EXPORT_SYMBOL_NS(amd_sof_acp_remove, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(amd_sof_acp_remove, "SND_SOC_SOF_AMD_COMMON");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("AMD ACP sof driver");
-MODULE_IMPORT_NS(SOUNDWIRE_AMD_INIT);
-MODULE_IMPORT_NS(SND_AMD_SOUNDWIRE_ACPI);
+MODULE_IMPORT_NS("SOUNDWIRE_AMD_INIT");
+MODULE_IMPORT_NS("SND_AMD_SOUNDWIRE_ACPI");
diff --git a/sound/soc/sof/amd/acp63.c b/sound/soc/sof/amd/acp63.c
index 9e6eb4bfc805..a686620b1358 100644
--- a/sound/soc/sof/amd/acp63.c
+++ b/sound/soc/sof/amd/acp63.c
@@ -128,7 +128,7 @@ static struct snd_soc_dai_driver acp63_sof_dai[] = {
/* Phoenix ops */
struct snd_sof_dsp_ops sof_acp63_ops;
-EXPORT_SYMBOL_NS(sof_acp63_ops, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(sof_acp63_ops, "SND_SOC_SOF_AMD_COMMON");
int sof_acp63_ops_init(struct snd_sof_dev *sdev)
{
diff --git a/sound/soc/sof/amd/acp70.c b/sound/soc/sof/amd/acp70.c
index 7d1842f42c90..8314ac4008da 100644
--- a/sound/soc/sof/amd/acp70.c
+++ b/sound/soc/sof/amd/acp70.c
@@ -128,7 +128,7 @@ static struct snd_soc_dai_driver acp70_sof_dai[] = {
/* Phoenix ops */
struct snd_sof_dsp_ops sof_acp70_ops;
-EXPORT_SYMBOL_NS(sof_acp70_ops, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(sof_acp70_ops, "SND_SOC_SOF_AMD_COMMON");
int sof_acp70_ops_init(struct snd_sof_dev *sdev)
{
diff --git a/sound/soc/sof/amd/pci-acp63.c b/sound/soc/sof/amd/pci-acp63.c
index b54ed61b79ed..ffe7c755d655 100644
--- a/sound/soc/sof/amd/pci-acp63.c
+++ b/sound/soc/sof/amd/pci-acp63.c
@@ -112,5 +112,5 @@ module_pci_driver(snd_sof_pci_amd_acp63_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("ACP63 SOF Driver");
-MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_AMD_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/amd/pci-acp70.c b/sound/soc/sof/amd/pci-acp70.c
index a5d8b6a95a22..3647ec992e95 100644
--- a/sound/soc/sof/amd/pci-acp70.c
+++ b/sound/soc/sof/amd/pci-acp70.c
@@ -108,5 +108,5 @@ module_pci_driver(snd_sof_pci_amd_acp70_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("ACP70 SOF Driver");
-MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_AMD_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/amd/pci-rmb.c b/sound/soc/sof/amd/pci-rmb.c
index c45256bf4fda..cbb4d5282664 100644
--- a/sound/soc/sof/amd/pci-rmb.c
+++ b/sound/soc/sof/amd/pci-rmb.c
@@ -101,5 +101,5 @@ module_pci_driver(snd_sof_pci_amd_rmb_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("REMBRANDT SOF Driver");
-MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_AMD_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/amd/pci-rn.c b/sound/soc/sof/amd/pci-rn.c
index 386a0f1e7ee0..b7d558cb1fd7 100644
--- a/sound/soc/sof/amd/pci-rn.c
+++ b/sound/soc/sof/amd/pci-rn.c
@@ -105,5 +105,5 @@ module_pci_driver(snd_sof_pci_amd_rn_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("RENOIR SOF Driver");
-MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_AMD_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/amd/pci-vangogh.c b/sound/soc/sof/amd/pci-vangogh.c
index cb845f81795e..53f64d6bc91b 100644
--- a/sound/soc/sof/amd/pci-vangogh.c
+++ b/sound/soc/sof/amd/pci-vangogh.c
@@ -100,5 +100,5 @@ module_pci_driver(snd_sof_pci_amd_vgh_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("VANGOGH SOF Driver");
-MODULE_IMPORT_NS(SND_SOC_SOF_AMD_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_AMD_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/amd/rembrandt.c b/sound/soc/sof/amd/rembrandt.c
index 076f2f05a95c..86ef59743fc8 100644
--- a/sound/soc/sof/amd/rembrandt.c
+++ b/sound/soc/sof/amd/rembrandt.c
@@ -128,7 +128,7 @@ static struct snd_soc_dai_driver rembrandt_sof_dai[] = {
/* Rembrandt ops */
struct snd_sof_dsp_ops sof_rembrandt_ops;
-EXPORT_SYMBOL_NS(sof_rembrandt_ops, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(sof_rembrandt_ops, "SND_SOC_SOF_AMD_COMMON");
int sof_rembrandt_ops_init(struct snd_sof_dev *sdev)
{
diff --git a/sound/soc/sof/amd/renoir.c b/sound/soc/sof/amd/renoir.c
index aa2d24dac6f5..b3b4639abf50 100644
--- a/sound/soc/sof/amd/renoir.c
+++ b/sound/soc/sof/amd/renoir.c
@@ -103,7 +103,7 @@ static struct snd_soc_dai_driver renoir_sof_dai[] = {
/* Renoir ops */
struct snd_sof_dsp_ops sof_renoir_ops;
-EXPORT_SYMBOL_NS(sof_renoir_ops, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(sof_renoir_ops, "SND_SOC_SOF_AMD_COMMON");
int sof_renoir_ops_init(struct snd_sof_dev *sdev)
{
diff --git a/sound/soc/sof/amd/vangogh.c b/sound/soc/sof/amd/vangogh.c
index 61372958c09d..8e2672106ac6 100644
--- a/sound/soc/sof/amd/vangogh.c
+++ b/sound/soc/sof/amd/vangogh.c
@@ -138,7 +138,7 @@ static struct snd_soc_dai_driver vangogh_sof_dai[] = {
/* Vangogh ops */
struct snd_sof_dsp_ops sof_vangogh_ops;
-EXPORT_SYMBOL_NS(sof_vangogh_ops, SND_SOC_SOF_AMD_COMMON);
+EXPORT_SYMBOL_NS(sof_vangogh_ops, "SND_SOC_SOF_AMD_COMMON");
int sof_vangogh_ops_init(struct snd_sof_dev *sdev)
{
diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c
index 24e779e8d650..aed834d03e10 100644
--- a/sound/soc/sof/core.c
+++ b/sound/soc/sof/core.c
@@ -836,4 +836,4 @@ MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("Sound Open Firmware (SOF) Core");
MODULE_ALIAS("platform:sof-audio");
-MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
+MODULE_IMPORT_NS("SND_SOC_SOF_CLIENT");
diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c
index f09ee0dea2cc..0b85b29d1067 100644
--- a/sound/soc/sof/imx/imx8.c
+++ b/sound/soc/sof/imx/imx8.c
@@ -669,4 +669,4 @@ module_platform_driver(snd_sof_of_imx8_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for IMX8 platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c
index 01d3ad3314f3..ff42743efa79 100644
--- a/sound/soc/sof/imx/imx8m.c
+++ b/sound/soc/sof/imx/imx8m.c
@@ -516,4 +516,4 @@ module_platform_driver(snd_sof_of_imx8m_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for IMX8M platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
diff --git a/sound/soc/sof/imx/imx8ulp.c b/sound/soc/sof/imx/imx8ulp.c
index e5eee1c9f6da..6965791ab6ef 100644
--- a/sound/soc/sof/imx/imx8ulp.c
+++ b/sound/soc/sof/imx/imx8ulp.c
@@ -518,4 +518,4 @@ module_platform_driver(snd_sof_of_imx8ulp_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for IMX8ULP platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
diff --git a/sound/soc/sof/intel/atom.c b/sound/soc/sof/intel/atom.c
index 3505ac3a1b14..30e981c558c6 100644
--- a/sound/soc/sof/intel/atom.c
+++ b/sound/soc/sof/intel/atom.c
@@ -94,7 +94,7 @@ void atom_dump(struct snd_sof_dev *sdev, u32 flags)
(imrd & SHIM_IMRD_DONE) ? "yes" : "no", imrd);
}
-EXPORT_SYMBOL_NS(atom_dump, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_dump, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
/*
* IPC Doorbell IRQ handler and thread.
@@ -131,7 +131,7 @@ irqreturn_t atom_irq_handler(int irq, void *context)
return ret;
}
-EXPORT_SYMBOL_NS(atom_irq_handler, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_irq_handler, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
irqreturn_t atom_irq_thread(int irq, void *context)
{
@@ -176,7 +176,7 @@ irqreturn_t atom_irq_thread(int irq, void *context)
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS(atom_irq_thread, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_irq_thread, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
int atom_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
{
@@ -191,19 +191,19 @@ int atom_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
return 0;
}
-EXPORT_SYMBOL_NS(atom_send_msg, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_send_msg, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
int atom_get_mailbox_offset(struct snd_sof_dev *sdev)
{
return MBOX_OFFSET;
}
-EXPORT_SYMBOL_NS(atom_get_mailbox_offset, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_get_mailbox_offset, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
int atom_get_window_offset(struct snd_sof_dev *sdev, u32 id)
{
return MBOX_OFFSET;
}
-EXPORT_SYMBOL_NS(atom_get_window_offset, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_get_window_offset, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
static void atom_host_done(struct snd_sof_dev *sdev)
{
@@ -248,7 +248,7 @@ int atom_run(struct snd_sof_dev *sdev)
/* return init core mask */
return 1;
}
-EXPORT_SYMBOL_NS(atom_run, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_run, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
int atom_reset(struct snd_sof_dev *sdev)
{
@@ -267,7 +267,7 @@ int atom_reset(struct snd_sof_dev *sdev)
return 0;
}
-EXPORT_SYMBOL_NS(atom_reset, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_reset, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
static const char *fixup_tplg_name(struct snd_sof_dev *sdev,
const char *sof_tplg_filename,
@@ -330,7 +330,7 @@ struct snd_soc_acpi_mach *atom_machine_select(struct snd_sof_dev *sdev)
return mach;
}
-EXPORT_SYMBOL_NS(atom_machine_select, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_machine_select, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
/* Atom DAIs */
struct snd_soc_dai_driver atom_dai[] = {
@@ -401,7 +401,7 @@ struct snd_soc_dai_driver atom_dai[] = {
},
},
};
-EXPORT_SYMBOL_NS(atom_dai, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_dai, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
void atom_set_mach_params(struct snd_soc_acpi_mach *mach,
struct snd_sof_dev *sdev)
@@ -415,7 +415,7 @@ void atom_set_mach_params(struct snd_soc_acpi_mach *mach,
mach_params->num_dai_drivers = desc->ops->num_drv;
mach_params->dai_drivers = desc->ops->drv;
}
-EXPORT_SYMBOL_NS(atom_set_mach_params, SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+EXPORT_SYMBOL_NS(atom_set_mach_params, "SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for Atom platforms");
diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c
index 322ff118f0f6..c4d92f3508b6 100644
--- a/sound/soc/sof/intel/bdw.c
+++ b/sound/soc/sof/intel/bdw.c
@@ -695,6 +695,6 @@ module_platform_driver(snd_sof_acpi_intel_bdw_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for Broadwell platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);
-MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
-MODULE_IMPORT_NS(SND_SOC_SOF_ACPI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HIFI_EP_IPC");
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
+MODULE_IMPORT_NS("SND_SOC_SOF_ACPI_DEV");
diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c
index f531710cf94e..536d4c89d2f0 100644
--- a/sound/soc/sof/intel/byt.c
+++ b/sound/soc/sof/intel/byt.c
@@ -476,7 +476,7 @@ module_platform_driver(snd_sof_acpi_intel_byt_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for Baytrail/Cherrytrail");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);
-MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
-MODULE_IMPORT_NS(SND_SOC_SOF_ACPI_DEV);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HIFI_EP_IPC");
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
+MODULE_IMPORT_NS("SND_SOC_SOF_ACPI_DEV");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
diff --git a/sound/soc/sof/intel/cnl.c b/sound/soc/sof/intel/cnl.c
index 6a8c7a108ef0..385e5339f0a4 100644
--- a/sound/soc/sof/intel/cnl.c
+++ b/sound/soc/sof/intel/cnl.c
@@ -110,7 +110,7 @@ irqreturn_t cnl_ipc4_irq_thread(int irq, void *context)
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS(cnl_ipc4_irq_thread, SND_SOC_SOF_INTEL_CNL);
+EXPORT_SYMBOL_NS(cnl_ipc4_irq_thread, "SND_SOC_SOF_INTEL_CNL");
irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
{
@@ -203,7 +203,7 @@ irqreturn_t cnl_ipc_irq_thread(int irq, void *context)
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS(cnl_ipc_irq_thread, SND_SOC_SOF_INTEL_CNL);
+EXPORT_SYMBOL_NS(cnl_ipc_irq_thread, "SND_SOC_SOF_INTEL_CNL");
static void cnl_ipc_host_done(struct snd_sof_dev *sdev)
{
@@ -286,7 +286,7 @@ int cnl_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
return 0;
}
-EXPORT_SYMBOL_NS(cnl_ipc4_send_msg, SND_SOC_SOF_INTEL_CNL);
+EXPORT_SYMBOL_NS(cnl_ipc4_send_msg, "SND_SOC_SOF_INTEL_CNL");
int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
{
@@ -334,7 +334,7 @@ int cnl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
return 0;
}
-EXPORT_SYMBOL_NS(cnl_ipc_send_msg, SND_SOC_SOF_INTEL_CNL);
+EXPORT_SYMBOL_NS(cnl_ipc_send_msg, "SND_SOC_SOF_INTEL_CNL");
void cnl_ipc_dump(struct snd_sof_dev *sdev)
{
@@ -355,7 +355,7 @@ void cnl_ipc_dump(struct snd_sof_dev *sdev)
"error: host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
hipcida, hipctdr, hipcctl);
}
-EXPORT_SYMBOL_NS(cnl_ipc_dump, SND_SOC_SOF_INTEL_CNL);
+EXPORT_SYMBOL_NS(cnl_ipc_dump, "SND_SOC_SOF_INTEL_CNL");
void cnl_ipc4_dump(struct snd_sof_dev *sdev)
{
@@ -377,11 +377,11 @@ void cnl_ipc4_dump(struct snd_sof_dev *sdev)
"Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n",
hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl);
}
-EXPORT_SYMBOL_NS(cnl_ipc4_dump, SND_SOC_SOF_INTEL_CNL);
+EXPORT_SYMBOL_NS(cnl_ipc4_dump, "SND_SOC_SOF_INTEL_CNL");
/* cannonlake ops */
struct snd_sof_dsp_ops sof_cnl_ops;
-EXPORT_SYMBOL_NS(sof_cnl_ops, SND_SOC_SOF_INTEL_CNL);
+EXPORT_SYMBOL_NS(sof_cnl_ops, "SND_SOC_SOF_INTEL_CNL");
int sof_cnl_ops_init(struct snd_sof_dev *sdev)
{
@@ -450,7 +450,7 @@ int sof_cnl_ops_init(struct snd_sof_dev *sdev)
return 0;
};
-EXPORT_SYMBOL_NS(sof_cnl_ops_init, SND_SOC_SOF_INTEL_CNL);
+EXPORT_SYMBOL_NS(sof_cnl_ops_init, "SND_SOC_SOF_INTEL_CNL");
const struct sof_intel_dsp_desc cnl_chip_info = {
/* Cannonlake */
@@ -516,4 +516,4 @@ const struct sof_intel_dsp_desc jsl_chip_info = {
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_2_0,
};
-EXPORT_SYMBOL_NS(jsl_chip_info, SND_SOC_SOF_INTEL_CNL);
+EXPORT_SYMBOL_NS(jsl_chip_info, "SND_SOC_SOF_INTEL_CNL");
diff --git a/sound/soc/sof/intel/hda-bus.c b/sound/soc/sof/intel/hda-bus.c
index 1989147aa6a4..b1be03011d7e 100644
--- a/sound/soc/sof/intel/hda-bus.c
+++ b/sound/soc/sof/intel/hda-bus.c
@@ -99,7 +99,7 @@ void sof_hda_bus_init(struct snd_sof_dev *sdev, struct device *dev)
spin_lock_init(&bus->reg_lock);
#endif /* CONFIG_SND_SOC_SOF_HDA_LINK */
}
-EXPORT_SYMBOL_NS(sof_hda_bus_init, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(sof_hda_bus_init, "SND_SOC_SOF_INTEL_HDA_COMMON");
void sof_hda_bus_exit(struct snd_sof_dev *sdev)
{
@@ -109,4 +109,4 @@ void sof_hda_bus_exit(struct snd_sof_dev *sdev)
snd_hdac_ext_bus_exit(bus);
#endif
}
-EXPORT_SYMBOL_NS(sof_hda_bus_exit, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(sof_hda_bus_exit, "SND_SOC_SOF_INTEL_HDA_COMMON");
diff --git a/sound/soc/sof/intel/hda-codec.c b/sound/soc/sof/intel/hda-codec.c
index dc46888faa0d..568f3dfe822f 100644
--- a/sound/soc/sof/intel/hda-codec.c
+++ b/sound/soc/sof/intel/hda-codec.c
@@ -101,7 +101,7 @@ void hda_codec_jack_wake_enable(struct snd_sof_dev *sdev, bool enable)
snd_hdac_chip_updatew(bus, WAKEEN, mask & STATESTS_INT_MASK, val);
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_jack_wake_enable, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_jack_wake_enable, "SND_SOC_SOF_HDA_AUDIO_CODEC");
/* check jack status after resuming from suspend mode */
void hda_codec_jack_check(struct snd_sof_dev *sdev)
@@ -121,7 +121,7 @@ void hda_codec_jack_check(struct snd_sof_dev *sdev)
if (codec->jacktbl.used)
pm_request_resume(&codec->core.dev);
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_jack_check, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_jack_check, "SND_SOC_SOF_HDA_AUDIO_CODEC");
#if IS_ENABLED(CONFIG_SND_HDA_GENERIC)
#define is_generic_config(bus) \
@@ -237,7 +237,7 @@ void hda_codec_probe_bus(struct snd_sof_dev *sdev)
}
}
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_probe_bus, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_probe_bus, "SND_SOC_SOF_HDA_AUDIO_CODEC");
void hda_codec_check_for_state_change(struct snd_sof_dev *sdev)
{
@@ -250,7 +250,7 @@ void hda_codec_check_for_state_change(struct snd_sof_dev *sdev)
snd_hdac_chip_writew(bus, STATESTS, codec_mask);
}
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_check_for_state_change, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_check_for_state_change, "SND_SOC_SOF_HDA_AUDIO_CODEC");
void hda_codec_detect_mask(struct snd_sof_dev *sdev)
{
@@ -275,7 +275,7 @@ void hda_codec_detect_mask(struct snd_sof_dev *sdev)
bus->codec_mask);
}
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_detect_mask, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_detect_mask, "SND_SOC_SOF_HDA_AUDIO_CODEC");
void hda_codec_init_cmd_io(struct snd_sof_dev *sdev)
{
@@ -288,7 +288,7 @@ void hda_codec_init_cmd_io(struct snd_sof_dev *sdev)
/* initialize the codec command I/O */
snd_hdac_bus_init_cmd_io(bus);
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_init_cmd_io, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_init_cmd_io, "SND_SOC_SOF_HDA_AUDIO_CODEC");
void hda_codec_resume_cmd_io(struct snd_sof_dev *sdev)
{
@@ -302,7 +302,7 @@ void hda_codec_resume_cmd_io(struct snd_sof_dev *sdev)
if (bus->cmd_dma_state)
snd_hdac_bus_init_cmd_io(bus);
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_resume_cmd_io, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_resume_cmd_io, "SND_SOC_SOF_HDA_AUDIO_CODEC");
void hda_codec_stop_cmd_io(struct snd_sof_dev *sdev)
{
@@ -315,7 +315,7 @@ void hda_codec_stop_cmd_io(struct snd_sof_dev *sdev)
/* initialize the codec command I/O */
snd_hdac_bus_stop_cmd_io(bus);
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_stop_cmd_io, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_stop_cmd_io, "SND_SOC_SOF_HDA_AUDIO_CODEC");
void hda_codec_suspend_cmd_io(struct snd_sof_dev *sdev)
{
@@ -330,7 +330,7 @@ void hda_codec_suspend_cmd_io(struct snd_sof_dev *sdev)
snd_hdac_bus_stop_cmd_io(bus);
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_suspend_cmd_io, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_suspend_cmd_io, "SND_SOC_SOF_HDA_AUDIO_CODEC");
void hda_codec_rirb_status_clear(struct snd_sof_dev *sdev)
{
@@ -343,7 +343,7 @@ void hda_codec_rirb_status_clear(struct snd_sof_dev *sdev)
/* clear rirb status */
snd_hdac_chip_writeb(bus, RIRBSTS, RIRB_INT_MASK);
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_rirb_status_clear, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_rirb_status_clear, "SND_SOC_SOF_HDA_AUDIO_CODEC");
void hda_codec_set_codec_wakeup(struct snd_sof_dev *sdev, bool status)
{
@@ -354,7 +354,7 @@ void hda_codec_set_codec_wakeup(struct snd_sof_dev *sdev, bool status)
snd_hdac_set_codec_wakeup(bus, status);
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_set_codec_wakeup, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_set_codec_wakeup, "SND_SOC_SOF_HDA_AUDIO_CODEC");
bool hda_codec_check_rirb_status(struct snd_sof_dev *sdev)
{
@@ -381,7 +381,7 @@ bool hda_codec_check_rirb_status(struct snd_sof_dev *sdev)
}
return active;
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_check_rirb_status, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_check_rirb_status, "SND_SOC_SOF_HDA_AUDIO_CODEC");
void hda_codec_device_remove(struct snd_sof_dev *sdev)
{
@@ -394,7 +394,7 @@ void hda_codec_device_remove(struct snd_sof_dev *sdev)
/* codec removal, invoke bus_device_remove */
snd_hdac_ext_bus_device_remove(bus);
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_device_remove, SND_SOC_SOF_HDA_AUDIO_CODEC);
+EXPORT_SYMBOL_NS_GPL(hda_codec_device_remove, "SND_SOC_SOF_HDA_AUDIO_CODEC");
#endif /* CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC */
@@ -413,7 +413,7 @@ void hda_codec_i915_display_power(struct snd_sof_dev *sdev, bool enable)
snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, enable);
}
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_i915_display_power, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
+EXPORT_SYMBOL_NS_GPL(hda_codec_i915_display_power, "SND_SOC_SOF_HDA_AUDIO_CODEC_I915");
int hda_codec_i915_init(struct snd_sof_dev *sdev)
{
@@ -434,7 +434,7 @@ int hda_codec_i915_init(struct snd_sof_dev *sdev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_i915_init, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
+EXPORT_SYMBOL_NS_GPL(hda_codec_i915_init, "SND_SOC_SOF_HDA_AUDIO_CODEC_I915");
int hda_codec_i915_exit(struct snd_sof_dev *sdev)
{
@@ -452,7 +452,7 @@ int hda_codec_i915_exit(struct snd_sof_dev *sdev)
return snd_hdac_i915_exit(bus);
}
-EXPORT_SYMBOL_NS_GPL(hda_codec_i915_exit, SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
+EXPORT_SYMBOL_NS_GPL(hda_codec_i915_exit, "SND_SOC_SOF_HDA_AUDIO_CODEC_I915");
#endif
diff --git a/sound/soc/sof/intel/hda-common-ops.c b/sound/soc/sof/intel/hda-common-ops.c
index 5fc28039a8e8..746b426b1329 100644
--- a/sound/soc/sof/intel/hda-common-ops.c
+++ b/sound/soc/sof/intel/hda-common-ops.c
@@ -105,4 +105,4 @@ const struct snd_sof_dsp_ops sof_hda_common_ops = {
.dsp_arch_ops = &sof_xtensa_arch_ops,
};
-EXPORT_SYMBOL_NS(sof_hda_common_ops, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(sof_hda_common_ops, "SND_SOC_SOF_INTEL_HDA_GENERIC");
diff --git a/sound/soc/sof/intel/hda-ctrl.c b/sound/soc/sof/intel/hda-ctrl.c
index b9a02750ce61..4f34fd919a00 100644
--- a/sound/soc/sof/intel/hda-ctrl.c
+++ b/sound/soc/sof/intel/hda-ctrl.c
@@ -128,7 +128,7 @@ int hda_dsp_ctrl_get_caps(struct snd_sof_dev *sdev)
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_ctrl_get_caps, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ctrl_get_caps, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_dsp_ctrl_ppcap_enable(struct snd_sof_dev *sdev, bool enable)
{
@@ -137,7 +137,7 @@ void hda_dsp_ctrl_ppcap_enable(struct snd_sof_dev *sdev, bool enable)
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
SOF_HDA_PPCTL_GPROCEN, val);
}
-EXPORT_SYMBOL_NS(hda_dsp_ctrl_ppcap_enable, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ctrl_ppcap_enable, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_dsp_ctrl_ppcap_int_enable(struct snd_sof_dev *sdev, bool enable)
{
@@ -146,7 +146,7 @@ void hda_dsp_ctrl_ppcap_int_enable(struct snd_sof_dev *sdev, bool enable)
snd_sof_dsp_update_bits(sdev, HDA_DSP_PP_BAR, SOF_HDA_REG_PP_PPCTL,
SOF_HDA_PPCTL_PIE, val);
}
-EXPORT_SYMBOL_NS(hda_dsp_ctrl_ppcap_int_enable, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ctrl_ppcap_int_enable, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_dsp_ctrl_misc_clock_gating(struct snd_sof_dev *sdev, bool enable)
{
@@ -181,7 +181,7 @@ int hda_dsp_ctrl_clock_power_gating(struct snd_sof_dev *sdev, bool enable)
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_ctrl_clock_power_gating, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ctrl_clock_power_gating, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_ctrl_init_chip(struct snd_sof_dev *sdev)
{
@@ -266,7 +266,7 @@ err:
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_ctrl_init_chip, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ctrl_init_chip, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev)
{
@@ -329,6 +329,6 @@ void hda_dsp_ctrl_stop_chip(struct snd_sof_dev *sdev)
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF helpers for HDaudio platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK);
-MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC);
-MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
+MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK");
+MODULE_IMPORT_NS("SND_SOC_SOF_HDA_AUDIO_CODEC");
+MODULE_IMPORT_NS("SND_SOC_SOF_HDA_AUDIO_CODEC_I915");
diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c
index ee274d445515..0db2a3e554fb 100644
--- a/sound/soc/sof/intel/hda-dai.c
+++ b/sound/soc/sof/intel/hda-dai.c
@@ -54,7 +54,7 @@ int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
return 0;
}
-EXPORT_SYMBOL_NS(hda_dai_config, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dai_config, "SND_SOC_SOF_INTEL_HDA_COMMON");
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_LINK)
@@ -103,8 +103,10 @@ hda_dai_get_ops(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai
return sdai->platform_private;
}
-int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream,
- struct snd_soc_dai *cpu_dai)
+static int
+hda_link_dma_cleanup(struct snd_pcm_substream *substream,
+ struct hdac_ext_stream *hext_stream,
+ struct snd_soc_dai *cpu_dai, bool release)
{
const struct hda_dai_widget_dma_ops *ops = hda_dai_get_ops(substream, cpu_dai);
struct sof_intel_hda_stream *hda_stream;
@@ -128,6 +130,17 @@ int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_st
snd_hdac_ext_bus_link_clear_stream_id(hlink, stream_tag);
}
+ if (!release) {
+ /*
+ * Force stream reconfiguration without releasing the channel on
+ * subsequent stream restart (without free), including LinkDMA
+ * reset.
+ * The stream is released via hda_dai_hw_free()
+ */
+ hext_stream->link_prepared = 0;
+ return 0;
+ }
+
if (ops->release_hext_stream)
ops->release_hext_stream(sdev, cpu_dai, substream);
@@ -211,7 +224,7 @@ static int __maybe_unused hda_dai_hw_free(struct snd_pcm_substream *substream,
if (!hext_stream)
return 0;
- return hda_link_dma_cleanup(substream, hext_stream, cpu_dai);
+ return hda_link_dma_cleanup(substream, hext_stream, cpu_dai, true);
}
static int __maybe_unused hda_dai_hw_params_data(struct snd_pcm_substream *substream,
@@ -304,7 +317,8 @@ static int __maybe_unused hda_dai_trigger(struct snd_pcm_substream *substream, i
switch (cmd) {
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
- ret = hda_link_dma_cleanup(substream, hext_stream, dai);
+ ret = hda_link_dma_cleanup(substream, hext_stream, dai,
+ cmd == SNDRV_PCM_TRIGGER_STOP ? false : true);
if (ret < 0) {
dev_err(sdev->dev, "%s: failed to clean up link DMA\n", __func__);
return ret;
@@ -574,7 +588,7 @@ int sdw_hda_dai_hw_params(struct snd_pcm_substream *substream,
}
return 0;
}
-EXPORT_SYMBOL_NS(sdw_hda_dai_hw_params, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(sdw_hda_dai_hw_params, "SND_SOC_SOF_INTEL_HDA_COMMON");
int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai,
@@ -603,14 +617,14 @@ int sdw_hda_dai_hw_free(struct snd_pcm_substream *substream,
return 0;
}
-EXPORT_SYMBOL_NS(sdw_hda_dai_hw_free, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(sdw_hda_dai_hw_free, "SND_SOC_SOF_INTEL_HDA_COMMON");
int sdw_hda_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai)
{
return hda_dai_trigger(substream, cmd, cpu_dai);
}
-EXPORT_SYMBOL_NS(sdw_hda_dai_trigger, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(sdw_hda_dai_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON");
static int hda_dai_suspend(struct hdac_bus *bus)
{
@@ -660,8 +674,7 @@ static int hda_dai_suspend(struct hdac_bus *bus)
}
ret = hda_link_dma_cleanup(hext_stream->link_substream,
- hext_stream,
- cpu_dai);
+ hext_stream, cpu_dai, true);
if (ret < 0)
return ret;
}
@@ -729,7 +742,7 @@ void hda_set_dai_drv_ops(struct snd_sof_dev *sdev, struct snd_sof_dsp_ops *ops)
ipc4_data->nhlt = intel_nhlt_init(sdev->dev);
}
}
-EXPORT_SYMBOL_NS(hda_set_dai_drv_ops, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_set_dai_drv_ops, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_ops_free(struct snd_sof_dev *sdev)
{
@@ -743,7 +756,7 @@ void hda_ops_free(struct snd_sof_dev *sdev)
sdev->private = NULL;
}
}
-EXPORT_SYMBOL_NS(hda_ops_free, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_ops_free, "SND_SOC_SOF_INTEL_HDA_COMMON");
/*
* common dai driver for skl+ platforms.
@@ -895,7 +908,7 @@ struct snd_soc_dai_driver skl_dai[] = {
},
#endif
};
-EXPORT_SYMBOL_NS(skl_dai, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(skl_dai, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_dais_suspend(struct snd_sof_dev *sdev)
{
diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c
index 6028a80418bb..ccf8eefdca70 100644
--- a/sound/soc/sof/intel/hda-dsp.c
+++ b/sound/soc/sof/intel/hda-dsp.c
@@ -90,7 +90,7 @@ u32 hda_get_interface_mask(struct snd_sof_dev *sdev)
return interface_mask[sdev->dspless_mode_selected];
}
-EXPORT_SYMBOL_NS(hda_get_interface_mask, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_get_interface_mask, "SND_SOC_SOF_INTEL_HDA_COMMON");
bool hda_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type)
{
@@ -120,7 +120,7 @@ bool hda_is_chain_dma_supported(struct snd_sof_dev *sdev, u32 dai_type)
return false;
}
}
-EXPORT_SYMBOL_NS(hda_is_chain_dma_supported, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_is_chain_dma_supported, "SND_SOC_SOF_INTEL_HDA_COMMON");
/*
* DSP Core control.
@@ -216,7 +216,7 @@ int hda_dsp_core_stall_reset(struct snd_sof_dev *sdev, unsigned int core_mask)
/* set reset state */
return hda_dsp_core_reset_enter(sdev, core_mask);
}
-EXPORT_SYMBOL_NS(hda_dsp_core_stall_reset, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_core_stall_reset, "SND_SOC_SOF_INTEL_HDA_COMMON");
bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, unsigned int core_mask)
{
@@ -242,7 +242,7 @@ bool hda_dsp_core_is_enabled(struct snd_sof_dev *sdev, unsigned int core_mask)
return is_enable;
}
-EXPORT_SYMBOL_NS(hda_dsp_core_is_enabled, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_core_is_enabled, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask)
{
@@ -270,7 +270,7 @@ int hda_dsp_core_run(struct snd_sof_dev *sdev, unsigned int core_mask)
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_core_run, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_core_run, "SND_SOC_SOF_INTEL_HDA_COMMON");
/*
* Power Management.
@@ -322,7 +322,7 @@ int hda_dsp_core_power_up(struct snd_sof_dev *sdev, unsigned int core_mask)
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_core_power_up, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_core_power_up, "SND_SOC_SOF_INTEL_HDA_COMMON");
static int hda_dsp_core_power_down(struct snd_sof_dev *sdev, unsigned int core_mask)
{
@@ -370,7 +370,7 @@ int hda_dsp_enable_core(struct snd_sof_dev *sdev, unsigned int core_mask)
return hda_dsp_core_run(sdev, core_mask);
}
-EXPORT_SYMBOL_NS(hda_dsp_enable_core, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_enable_core, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev,
unsigned int core_mask)
@@ -411,7 +411,7 @@ int hda_dsp_core_reset_power_down(struct snd_sof_dev *sdev,
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_core_reset_power_down, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_core_reset_power_down, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev)
{
@@ -430,7 +430,7 @@ void hda_dsp_ipc_int_enable(struct snd_sof_dev *sdev)
snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, HDA_DSP_REG_ADSPIC,
HDA_DSP_ADSPIC_IPC, HDA_DSP_ADSPIC_IPC);
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc_int_enable, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc_int_enable, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev)
{
@@ -448,7 +448,7 @@ void hda_dsp_ipc_int_disable(struct snd_sof_dev *sdev)
snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
HDA_DSP_REG_HIPCCTL_BUSY | HDA_DSP_REG_HIPCCTL_DONE, 0);
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc_int_disable, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc_int_disable, "SND_SOC_SOF_INTEL_HDA_COMMON");
static int hda_dsp_wait_d0i3c_done(struct snd_sof_dev *sdev)
{
@@ -732,7 +732,7 @@ int hda_dsp_set_power_state_ipc3(struct snd_sof_dev *sdev,
return hda_dsp_set_power_state(sdev, target_state);
}
-EXPORT_SYMBOL_NS(hda_dsp_set_power_state_ipc3, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_set_power_state_ipc3, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev,
const struct sof_dsp_power_state *target_state)
@@ -744,7 +744,7 @@ int hda_dsp_set_power_state_ipc4(struct snd_sof_dev *sdev,
return hda_dsp_set_power_state(sdev, target_state);
}
-EXPORT_SYMBOL_NS(hda_dsp_set_power_state_ipc4, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_set_power_state_ipc4, "SND_SOC_SOF_INTEL_HDA_COMMON");
/*
* Audio DSP states may transform as below:-
@@ -948,7 +948,7 @@ int hda_dsp_resume(struct snd_sof_dev *sdev)
return snd_sof_dsp_set_power_state(sdev, &target_state);
}
-EXPORT_SYMBOL_NS(hda_dsp_resume, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_resume, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_runtime_resume(struct snd_sof_dev *sdev)
{
@@ -964,7 +964,7 @@ int hda_dsp_runtime_resume(struct snd_sof_dev *sdev)
return snd_sof_dsp_set_power_state(sdev, &target_state);
}
-EXPORT_SYMBOL_NS(hda_dsp_runtime_resume, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_runtime_resume, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_runtime_idle(struct snd_sof_dev *sdev)
{
@@ -978,7 +978,7 @@ int hda_dsp_runtime_idle(struct snd_sof_dev *sdev)
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_runtime_idle, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_runtime_idle, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev)
{
@@ -1000,7 +1000,7 @@ int hda_dsp_runtime_suspend(struct snd_sof_dev *sdev)
return snd_sof_dsp_set_power_state(sdev, &target_state);
}
-EXPORT_SYMBOL_NS(hda_dsp_runtime_suspend, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_runtime_suspend, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state)
{
@@ -1061,7 +1061,7 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state)
return snd_sof_dsp_set_power_state(sdev, &target_dsp_state);
}
-EXPORT_SYMBOL_NS(hda_dsp_suspend, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_suspend, "SND_SOC_SOF_INTEL_HDA_COMMON");
static unsigned int hda_dsp_check_for_dma_streams(struct snd_sof_dev *sdev)
{
@@ -1134,14 +1134,14 @@ int hda_dsp_shutdown_dma_flush(struct snd_sof_dev *sdev)
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_shutdown_dma_flush, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_shutdown_dma_flush, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_shutdown(struct snd_sof_dev *sdev)
{
sdev->system_suspend_target = SOF_SUSPEND_S3;
return snd_sof_suspend(sdev->dev);
}
-EXPORT_SYMBOL_NS(hda_dsp_shutdown, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_shutdown, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
{
@@ -1154,7 +1154,7 @@ int hda_dsp_set_hw_params_upon_resume(struct snd_sof_dev *sdev)
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_set_hw_params_upon_resume, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_set_hw_params_upon_resume, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_dsp_d0i3_work(struct work_struct *work)
{
@@ -1181,7 +1181,7 @@ void hda_dsp_d0i3_work(struct work_struct *work)
"error: failed to set DSP state %d substate %d\n",
target_state.state, target_state.substate);
}
-EXPORT_SYMBOL_NS(hda_dsp_d0i3_work, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_d0i3_work, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_core_get(struct snd_sof_dev *sdev, int core)
{
@@ -1222,7 +1222,7 @@ power_down:
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_core_get, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_core_get, "SND_SOC_SOF_INTEL_HDA_COMMON");
#if IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE)
void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable)
@@ -1238,7 +1238,7 @@ void hda_common_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable)
HDA_DSP_REG_ADSPIC2_SNDW,
enable ? HDA_DSP_REG_ADSPIC2_SNDW : 0);
}
-EXPORT_SYMBOL_NS(hda_common_enable_sdw_irq, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_common_enable_sdw_irq, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable)
{
@@ -1252,7 +1252,7 @@ void hda_sdw_int_enable(struct snd_sof_dev *sdev, bool enable)
if (chip && chip->enable_sdw_irq)
chip->enable_sdw_irq(sdev, enable);
}
-EXPORT_SYMBOL_NS(hda_sdw_int_enable, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_sdw_int_enable, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev)
{
@@ -1276,7 +1276,7 @@ int hda_sdw_check_lcount_common(struct snd_sof_dev *sdev)
return 0;
}
-EXPORT_SYMBOL_NS(hda_sdw_check_lcount_common, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_sdw_check_lcount_common, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev)
{
@@ -1302,7 +1302,7 @@ int hda_sdw_check_lcount_ext(struct snd_sof_dev *sdev)
return 0;
}
-EXPORT_SYMBOL_NS(hda_sdw_check_lcount_ext, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_sdw_check_lcount_ext, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_sdw_check_lcount(struct snd_sof_dev *sdev)
{
@@ -1314,7 +1314,7 @@ int hda_sdw_check_lcount(struct snd_sof_dev *sdev)
return 0;
}
-EXPORT_SYMBOL_NS(hda_sdw_check_lcount, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_sdw_check_lcount, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_sdw_process_wakeen(struct snd_sof_dev *sdev)
{
@@ -1328,7 +1328,7 @@ void hda_sdw_process_wakeen(struct snd_sof_dev *sdev)
if (chip && chip->sdw_process_wakeen)
chip->sdw_process_wakeen(sdev);
}
-EXPORT_SYMBOL_NS(hda_sdw_process_wakeen, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_sdw_process_wakeen, "SND_SOC_SOF_INTEL_HDA_COMMON");
#endif
@@ -1339,7 +1339,7 @@ int hda_dsp_disable_interrupts(struct snd_sof_dev *sdev)
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_disable_interrupts, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_disable_interrupts, "SND_SOC_SOF_INTEL_HDA_COMMON");
static const struct hda_dsp_msg_code hda_dsp_rom_fw_error_texts[] = {
{HDA_DSP_ROM_CSE_ERROR, "error: cse error"},
@@ -1550,7 +1550,7 @@ void hda_dsp_get_state(struct snd_sof_dev *sdev, const char *level)
dev_printk(level, sdev->dev, "error code: %#x (%s)\n", error_code,
error_text);
}
-EXPORT_SYMBOL_NS(hda_dsp_get_state, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_get_state, "SND_SOC_SOF_INTEL_HDA_COMMON");
static void hda_dsp_get_registers(struct snd_sof_dev *sdev,
struct sof_ipc_dsp_oops_xtensa *xoops,
@@ -1623,4 +1623,4 @@ void hda_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
hda_dsp_dump_ext_rom_status(sdev, level, flags);
}
}
-EXPORT_SYMBOL_NS(hda_dsp_dump, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_dump, "SND_SOC_SOF_INTEL_HDA_COMMON");
diff --git a/sound/soc/sof/intel/hda-ipc.c b/sound/soc/sof/intel/hda-ipc.c
index 9feaaa2d166a..f3fbf43a70c2 100644
--- a/sound/soc/sof/intel/hda-ipc.c
+++ b/sound/soc/sof/intel/hda-ipc.c
@@ -72,7 +72,7 @@ int hda_dsp_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc_send_msg, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc_send_msg, "SND_SOC_SOF_INTEL_HDA_COMMON");
static inline bool hda_dsp_ipc4_pm_msg(u32 primary)
{
@@ -99,7 +99,7 @@ void hda_dsp_ipc4_schedule_d0i3_work(struct sof_intel_hda_dev *hdev,
mod_delayed_work(system_wq, &hdev->d0i3_work,
msecs_to_jiffies(SOF_HDA_D0I3_WORK_DELAY_MS));
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc4_schedule_d0i3_work, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc4_schedule_d0i3_work, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
{
@@ -126,7 +126,7 @@ int hda_dsp_ipc4_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc4_send_msg, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc4_send_msg, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
{
@@ -162,7 +162,7 @@ void hda_dsp_ipc_get_reply(struct snd_sof_dev *sdev)
snd_sof_ipc_get_reply(sdev);
}
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc_get_reply, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc_get_reply, "SND_SOC_SOF_INTEL_HDA_COMMON");
irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context)
{
@@ -245,7 +245,7 @@ irqreturn_t hda_dsp_ipc4_irq_thread(int irq, void *context)
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc4_irq_thread, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc4_irq_thread, "SND_SOC_SOF_INTEL_HDA_COMMON");
/* IPC handler thread */
irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
@@ -358,7 +358,7 @@ irqreturn_t hda_dsp_ipc_irq_thread(int irq, void *context)
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc_irq_thread, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc_irq_thread, "SND_SOC_SOF_INTEL_HDA_COMMON");
/* Check if an IPC IRQ occurred */
bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev)
@@ -392,19 +392,19 @@ bool hda_dsp_check_ipc_irq(struct snd_sof_dev *sdev)
out:
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_check_ipc_irq, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_check_ipc_irq, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
{
return HDA_DSP_MBOX_UPLINK_OFFSET;
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc_get_mailbox_offset, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc_get_mailbox_offset, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
{
return SRAM_WINDOW_OFFSET(id);
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc_get_window_offset, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc_get_window_offset, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_ipc_msg_data(struct snd_sof_dev *sdev,
struct snd_sof_pcm_stream *sps,
@@ -430,7 +430,7 @@ int hda_ipc_msg_data(struct snd_sof_dev *sdev,
return 0;
}
-EXPORT_SYMBOL_NS(hda_ipc_msg_data, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_ipc_msg_data, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_set_stream_data_offset(struct snd_sof_dev *sdev,
struct snd_sof_pcm_stream *sps,
@@ -455,7 +455,7 @@ int hda_set_stream_data_offset(struct snd_sof_dev *sdev,
return 0;
}
-EXPORT_SYMBOL_NS(hda_set_stream_data_offset, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_set_stream_data_offset, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
{
@@ -469,7 +469,7 @@ void hda_ipc4_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
else
hda_dsp_dump_ext_rom_status(sdev, level, flags);
}
-EXPORT_SYMBOL_NS(hda_ipc4_dsp_dump, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_ipc4_dsp_dump, "SND_SOC_SOF_INTEL_HDA_COMMON");
bool hda_check_ipc_irq(struct snd_sof_dev *sdev)
{
@@ -481,7 +481,7 @@ bool hda_check_ipc_irq(struct snd_sof_dev *sdev)
return false;
}
-EXPORT_SYMBOL_NS(hda_check_ipc_irq, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_check_ipc_irq, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_ipc_irq_dump(struct snd_sof_dev *sdev)
{
@@ -502,7 +502,7 @@ void hda_ipc_irq_dump(struct snd_sof_dev *sdev)
intsts, intctl, rirbsts);
dev_err(sdev->dev, "dsp irq ppsts 0x%8.8x adspis 0x%8.8x\n", ppsts, adspis);
}
-EXPORT_SYMBOL_NS(hda_ipc_irq_dump, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_ipc_irq_dump, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_ipc_dump(struct snd_sof_dev *sdev)
{
@@ -522,7 +522,7 @@ void hda_ipc_dump(struct snd_sof_dev *sdev)
dev_err(sdev->dev, "host status 0x%8.8x dsp status 0x%8.8x mask 0x%8.8x\n",
hipcie, hipct, hipcctl);
}
-EXPORT_SYMBOL_NS(hda_ipc_dump, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_ipc_dump, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_ipc4_dump(struct snd_sof_dev *sdev)
{
@@ -541,7 +541,7 @@ void hda_ipc4_dump(struct snd_sof_dev *sdev)
dev_err(sdev->dev, "Host IPC initiator: %#x|%#x, target: %#x|%#x, ctl: %#x\n",
hipci, hipcie, hipct, hipcte, hipcctl);
}
-EXPORT_SYMBOL_NS(hda_ipc4_dump, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_ipc4_dump, "SND_SOC_SOF_INTEL_HDA_COMMON");
bool hda_ipc4_tx_is_busy(struct snd_sof_dev *sdev)
{
@@ -553,4 +553,4 @@ bool hda_ipc4_tx_is_busy(struct snd_sof_dev *sdev)
return !!(val & chip->ipc_req_mask);
}
-EXPORT_SYMBOL_NS(hda_ipc4_tx_is_busy, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_ipc4_tx_is_busy, "SND_SOC_SOF_INTEL_HDA_COMMON");
diff --git a/sound/soc/sof/intel/hda-loader.c b/sound/soc/sof/intel/hda-loader.c
index 76a03b6b2728..49085ca7b46b 100644
--- a/sound/soc/sof/intel/hda-loader.c
+++ b/sound/soc/sof/intel/hda-loader.c
@@ -113,7 +113,7 @@ out_put:
hda_dsp_stream_put(sdev, direction, hstream->stream_tag);
return ERR_PTR(ret);
}
-EXPORT_SYMBOL_NS(hda_cl_prepare, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_cl_prepare, "SND_SOC_SOF_INTEL_HDA_COMMON");
/*
* first boot sequence has some extra steps.
@@ -237,7 +237,7 @@ err:
kfree(dump_msg);
return ret;
}
-EXPORT_SYMBOL_NS(cl_dsp_init, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(cl_dsp_init, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int cmd)
{
@@ -270,7 +270,7 @@ int hda_cl_trigger(struct device *dev, struct hdac_ext_stream *hext_stream, int
return hda_dsp_stream_trigger(sdev, hext_stream, cmd);
}
}
-EXPORT_SYMBOL_NS(hda_cl_trigger, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_cl_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
bool persistent_buffer, struct hdac_ext_stream *hext_stream)
@@ -308,7 +308,7 @@ int hda_cl_cleanup(struct device *dev, struct snd_dma_buffer *dmab,
return ret;
}
-EXPORT_SYMBOL_NS(hda_cl_cleanup, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_cl_cleanup, "SND_SOC_SOF_INTEL_HDA_COMMON");
#define HDA_CL_DMA_IOC_TIMEOUT_MS 500
@@ -405,7 +405,7 @@ int hda_dsp_cl_boot_firmware_iccmax(struct snd_sof_dev *sdev)
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_cl_boot_firmware_iccmax, SND_SOC_SOF_INTEL_CNL);
+EXPORT_SYMBOL_NS(hda_dsp_cl_boot_firmware_iccmax, "SND_SOC_SOF_INTEL_CNL");
static int hda_dsp_boot_imr(struct snd_sof_dev *sdev)
{
@@ -567,7 +567,7 @@ cleanup:
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_cl_boot_firmware, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_cl_boot_firmware, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_ipc4_load_library(struct snd_sof_dev *sdev,
struct sof_ipc4_fw_library *fw_lib, bool reload)
@@ -683,7 +683,7 @@ cleanup:
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_ipc4_load_library, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ipc4_load_library, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_ext_man_get_cavs_config_data(struct snd_sof_dev *sdev,
const struct sof_ext_man_elem_header *hdr)
@@ -722,4 +722,4 @@ int hda_dsp_ext_man_get_cavs_config_data(struct snd_sof_dev *sdev,
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_ext_man_get_cavs_config_data, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_ext_man_get_cavs_config_data, "SND_SOC_SOF_INTEL_HDA_COMMON");
diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c
index 46f89d6d06f8..fe627bcb0531 100644
--- a/sound/soc/sof/intel/hda-mlink.c
+++ b/sound/soc/sof/intel/hda-mlink.c
@@ -434,7 +434,7 @@ int hda_bus_ml_init(struct hdac_bus *bus)
}
return 0;
}
-EXPORT_SYMBOL_NS(hda_bus_ml_init, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hda_bus_ml_init, "SND_SOC_SOF_HDA_MLINK");
void hda_bus_ml_free(struct hdac_bus *bus)
{
@@ -452,7 +452,7 @@ void hda_bus_ml_free(struct hdac_bus *bus)
kfree(h2link);
}
}
-EXPORT_SYMBOL_NS(hda_bus_ml_free, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hda_bus_ml_free, "SND_SOC_SOF_HDA_MLINK");
static struct hdac_ext2_link *
find_ext2_link(struct hdac_bus *bus, bool alt, int elid)
@@ -479,7 +479,7 @@ int hdac_bus_eml_get_count(struct hdac_bus *bus, bool alt, int elid)
return h2link->slcount;
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_get_count, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_get_count, "SND_SOC_SOF_HDA_MLINK");
void hdac_bus_eml_enable_interrupt_unlocked(struct hdac_bus *bus, bool alt, int elid, bool enable)
{
@@ -497,7 +497,7 @@ void hdac_bus_eml_enable_interrupt_unlocked(struct hdac_bus *bus, bool alt, int
hdaml_link_enable_interrupt(hlink->ml_addr + AZX_REG_ML_LCTL, enable);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_enable_interrupt_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_enable_interrupt_unlocked, "SND_SOC_SOF_HDA_MLINK");
void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, bool enable)
{
@@ -519,7 +519,7 @@ void hdac_bus_eml_enable_interrupt(struct hdac_bus *bus, bool alt, int elid, boo
mutex_unlock(&h2link->eml_lock);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_enable_interrupt, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_enable_interrupt, "SND_SOC_SOF_HDA_MLINK");
bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid)
{
@@ -537,7 +537,7 @@ bool hdac_bus_eml_check_interrupt(struct hdac_bus *bus, bool alt, int elid)
return hdaml_link_check_interrupt(hlink->ml_addr + AZX_REG_ML_LCTL);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_check_interrupt, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_check_interrupt, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_set_syncprd_unlocked(struct hdac_bus *bus, bool alt, int elid, u32 syncprd)
{
@@ -557,13 +557,13 @@ int hdac_bus_eml_set_syncprd_unlocked(struct hdac_bus *bus, bool alt, int elid,
return 0;
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_set_syncprd_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_set_syncprd_unlocked, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_sdw_set_syncprd_unlocked(struct hdac_bus *bus, u32 syncprd)
{
return hdac_bus_eml_set_syncprd_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, syncprd);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_set_syncprd_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_set_syncprd_unlocked, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid)
{
@@ -581,13 +581,13 @@ int hdac_bus_eml_wait_syncpu_unlocked(struct hdac_bus *bus, bool alt, int elid)
return hdaml_link_wait_syncpu(hlink->ml_addr + AZX_REG_ML_LSYNC);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_wait_syncpu_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_wait_syncpu_unlocked, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_sdw_wait_syncpu_unlocked(struct hdac_bus *bus)
{
return hdac_bus_eml_wait_syncpu_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_wait_syncpu_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_wait_syncpu_unlocked, "SND_SOC_SOF_HDA_MLINK");
void hdac_bus_eml_sync_arm_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink)
{
@@ -605,13 +605,13 @@ void hdac_bus_eml_sync_arm_unlocked(struct hdac_bus *bus, bool alt, int elid, in
hdaml_link_sync_arm(hlink->ml_addr + AZX_REG_ML_LSYNC, sublink);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_sync_arm_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_sync_arm_unlocked, "SND_SOC_SOF_HDA_MLINK");
void hdac_bus_eml_sdw_sync_arm_unlocked(struct hdac_bus *bus, int sublink)
{
hdac_bus_eml_sync_arm_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, sublink);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_sync_arm_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_sync_arm_unlocked, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid)
{
@@ -631,13 +631,13 @@ int hdac_bus_eml_sync_go_unlocked(struct hdac_bus *bus, bool alt, int elid)
return 0;
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_sync_go_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_sync_go_unlocked, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_sdw_sync_go_unlocked(struct hdac_bus *bus)
{
return hdac_bus_eml_sync_go_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_sync_go_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_sync_go_unlocked, "SND_SOC_SOF_HDA_MLINK");
bool hdac_bus_eml_check_cmdsync_unlocked(struct hdac_bus *bus, bool alt, int elid)
{
@@ -660,13 +660,13 @@ bool hdac_bus_eml_check_cmdsync_unlocked(struct hdac_bus *bus, bool alt, int eli
return hdaml_link_check_cmdsync(hlink->ml_addr + AZX_REG_ML_LSYNC,
cmdsync_mask);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_check_cmdsync_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_check_cmdsync_unlocked, "SND_SOC_SOF_HDA_MLINK");
bool hdac_bus_eml_sdw_check_cmdsync_unlocked(struct hdac_bus *bus)
{
return hdac_bus_eml_check_cmdsync_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_check_cmdsync_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_check_cmdsync_unlocked, "SND_SOC_SOF_HDA_MLINK");
static int hdac_bus_eml_power_up_base(struct hdac_bus *bus, bool alt, int elid, int sublink,
bool eml_lock)
@@ -708,13 +708,13 @@ int hdac_bus_eml_power_up(struct hdac_bus *bus, bool alt, int elid, int sublink)
{
return hdac_bus_eml_power_up_base(bus, alt, elid, sublink, true);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_power_up, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_power_up, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_power_up_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink)
{
return hdac_bus_eml_power_up_base(bus, alt, elid, sublink, false);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_power_up_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_power_up_unlocked, "SND_SOC_SOF_HDA_MLINK");
static int hdac_bus_eml_power_down_base(struct hdac_bus *bus, bool alt, int elid, int sublink,
bool eml_lock)
@@ -755,25 +755,25 @@ int hdac_bus_eml_power_down(struct hdac_bus *bus, bool alt, int elid, int sublin
{
return hdac_bus_eml_power_down_base(bus, alt, elid, sublink, true);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_power_down, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_power_down, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_power_down_unlocked(struct hdac_bus *bus, bool alt, int elid, int sublink)
{
return hdac_bus_eml_power_down_base(bus, alt, elid, sublink, false);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_power_down_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_power_down_unlocked, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_sdw_power_up_unlocked(struct hdac_bus *bus, int sublink)
{
return hdac_bus_eml_power_up_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, sublink);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_power_up_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_power_up_unlocked, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_sdw_power_down_unlocked(struct hdac_bus *bus, int sublink)
{
return hdac_bus_eml_power_down_unlocked(bus, true, AZX_REG_ML_LEPTR_ID_SDW, sublink);
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_power_down_unlocked, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_power_down_unlocked, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_sdw_get_lsdiid_unlocked(struct hdac_bus *bus, int sublink, u16 *lsdiid)
{
@@ -789,7 +789,7 @@ int hdac_bus_eml_sdw_get_lsdiid_unlocked(struct hdac_bus *bus, int sublink, u16
*lsdiid = hdaml_link_get_lsdiid(hlink->ml_addr + AZX_REG_ML_LSDIID_OFFSET(sublink));
return 0;
-} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_get_lsdiid_unlocked, SND_SOC_SOF_HDA_MLINK);
+} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_get_lsdiid_unlocked, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num)
{
@@ -809,7 +809,7 @@ int hdac_bus_eml_sdw_set_lsdiid(struct hdac_bus *bus, int sublink, int dev_num)
mutex_unlock(&h2link->eml_lock);
return 0;
-} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_set_lsdiid, SND_SOC_SOF_HDA_MLINK);
+} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_set_lsdiid, "SND_SOC_SOF_HDA_MLINK");
/*
* the 'y' parameter comes from the PCMSyCM hardware register naming. 'y' refers to the
@@ -853,7 +853,7 @@ int hdac_bus_eml_sdw_map_stream_ch(struct hdac_bus *bus, int sublink, int y,
sublink, channel_mask, stream_id, dir, val);
return 0;
-} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_map_stream_ch, SND_SOC_SOF_HDA_MLINK);
+} EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_map_stream_ch, "SND_SOC_SOF_HDA_MLINK");
void hda_bus_ml_put_all(struct hdac_bus *bus)
{
@@ -866,7 +866,7 @@ void hda_bus_ml_put_all(struct hdac_bus *bus)
snd_hdac_ext_bus_link_put(bus, hlink);
}
}
-EXPORT_SYMBOL_NS(hda_bus_ml_put_all, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hda_bus_ml_put_all, "SND_SOC_SOF_HDA_MLINK");
void hda_bus_ml_reset_losidv(struct hdac_bus *bus)
{
@@ -876,7 +876,7 @@ void hda_bus_ml_reset_losidv(struct hdac_bus *bus)
list_for_each_entry(hlink, &bus->hlink_list, list)
writel(0, hlink->ml_addr + AZX_REG_ML_LOSIDV);
}
-EXPORT_SYMBOL_NS(hda_bus_ml_reset_losidv, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hda_bus_ml_reset_losidv, "SND_SOC_SOF_HDA_MLINK");
int hda_bus_ml_resume(struct hdac_bus *bus)
{
@@ -895,7 +895,7 @@ int hda_bus_ml_resume(struct hdac_bus *bus)
}
return 0;
}
-EXPORT_SYMBOL_NS(hda_bus_ml_resume, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hda_bus_ml_resume, "SND_SOC_SOF_HDA_MLINK");
int hda_bus_ml_suspend(struct hdac_bus *bus)
{
@@ -913,7 +913,7 @@ int hda_bus_ml_suspend(struct hdac_bus *bus)
}
return 0;
}
-EXPORT_SYMBOL_NS(hda_bus_ml_suspend, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hda_bus_ml_suspend, "SND_SOC_SOF_HDA_MLINK");
struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid)
{
@@ -925,7 +925,7 @@ struct mutex *hdac_bus_eml_get_mutex(struct hdac_bus *bus, bool alt, int elid)
return &h2link->eml_lock;
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_get_mutex, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_get_mutex, "SND_SOC_SOF_HDA_MLINK");
struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus)
{
@@ -937,7 +937,7 @@ struct hdac_ext_link *hdac_bus_eml_ssp_get_hlink(struct hdac_bus *bus)
return &h2link->hext_link;
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_ssp_get_hlink, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_ssp_get_hlink, "SND_SOC_SOF_HDA_MLINK");
struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus)
{
@@ -949,7 +949,7 @@ struct hdac_ext_link *hdac_bus_eml_dmic_get_hlink(struct hdac_bus *bus)
return &h2link->hext_link;
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_dmic_get_hlink, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_dmic_get_hlink, "SND_SOC_SOF_HDA_MLINK");
struct hdac_ext_link *hdac_bus_eml_sdw_get_hlink(struct hdac_bus *bus)
{
@@ -961,7 +961,7 @@ struct hdac_ext_link *hdac_bus_eml_sdw_get_hlink(struct hdac_bus *bus)
return &h2link->hext_link;
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_get_hlink, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_get_hlink, "SND_SOC_SOF_HDA_MLINK");
int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable)
{
@@ -985,7 +985,7 @@ int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool e
return 0;
}
-EXPORT_SYMBOL_NS(hdac_bus_eml_enable_offload, SND_SOC_SOF_HDA_MLINK);
+EXPORT_SYMBOL_NS(hdac_bus_eml_enable_offload, "SND_SOC_SOF_HDA_MLINK");
#endif
diff --git a/sound/soc/sof/intel/hda-pcm.c b/sound/soc/sof/intel/hda-pcm.c
index f6e24edd7adb..5b5e484f9acf 100644
--- a/sound/soc/sof/intel/hda-pcm.c
+++ b/sound/soc/sof/intel/hda-pcm.c
@@ -142,7 +142,7 @@ int hda_dsp_pcm_hw_params(struct snd_sof_dev *sdev,
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_pcm_hw_params, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_pcm_hw_params, "SND_SOC_SOF_INTEL_HDA_COMMON");
/* update SPIB register with appl position */
int hda_dsp_pcm_ack(struct snd_sof_dev *sdev, struct snd_pcm_substream *substream)
@@ -165,7 +165,7 @@ int hda_dsp_pcm_ack(struct snd_sof_dev *sdev, struct snd_pcm_substream *substrea
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_pcm_ack, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_pcm_ack, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream, int cmd)
@@ -175,7 +175,7 @@ int hda_dsp_pcm_trigger(struct snd_sof_dev *sdev,
return hda_dsp_stream_trigger(sdev, hext_stream, cmd);
}
-EXPORT_SYMBOL_NS(hda_dsp_pcm_trigger, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_pcm_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON");
snd_pcm_uframes_t hda_dsp_pcm_pointer(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
@@ -207,7 +207,7 @@ found:
trace_sof_intel_hda_dsp_pcm(sdev, hstream, substream, pos);
return pos;
}
-EXPORT_SYMBOL_NS(hda_dsp_pcm_pointer, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_pcm_pointer, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
@@ -302,7 +302,7 @@ int hda_dsp_pcm_open(struct snd_sof_dev *sdev,
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_pcm_open, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_pcm_open, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_pcm_close(struct snd_sof_dev *sdev,
struct snd_pcm_substream *substream)
@@ -322,4 +322,4 @@ int hda_dsp_pcm_close(struct snd_sof_dev *sdev,
substream->runtime->private_data = NULL;
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_pcm_close, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_pcm_close, "SND_SOC_SOF_INTEL_HDA_COMMON");
diff --git a/sound/soc/sof/intel/hda-probes.c b/sound/soc/sof/intel/hda-probes.c
index 3e33101f0521..c645346c2c84 100644
--- a/sound/soc/sof/intel/hda-probes.c
+++ b/sound/soc/sof/intel/hda-probes.c
@@ -139,12 +139,12 @@ int hda_probes_register(struct snd_sof_dev *sdev)
return sof_client_dev_register(sdev, "hda-probes", 0, &hda_probes_ops,
sizeof(hda_probes_ops));
}
-EXPORT_SYMBOL_NS(hda_probes_register, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_probes_register, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_probes_unregister(struct snd_sof_dev *sdev)
{
sof_client_dev_unregister(sdev, "hda-probes", 0);
}
-EXPORT_SYMBOL_NS(hda_probes_unregister, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_probes_unregister, "SND_SOC_SOF_INTEL_HDA_COMMON");
-MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
+MODULE_IMPORT_NS("SND_SOC_SOF_CLIENT");
diff --git a/sound/soc/sof/intel/hda-stream.c b/sound/soc/sof/intel/hda-stream.c
index 519bafd3b947..aa6b0247d5c9 100644
--- a/sound/soc/sof/intel/hda-stream.c
+++ b/sound/soc/sof/intel/hda-stream.c
@@ -27,7 +27,7 @@
int sof_hda_position_quirk = SOF_HDA_POSITION_QUIRK_USE_DPIB_REGISTERS;
module_param_named(position_quirk, sof_hda_position_quirk, int, 0444);
MODULE_PARM_DESC(position_quirk, "SOF HDaudio position quirk");
-EXPORT_SYMBOL_NS(sof_hda_position_quirk, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(sof_hda_position_quirk, "SND_SOC_SOF_INTEL_HDA_COMMON");
#define HDA_LTRP_GB_VALUE_US 95
@@ -738,7 +738,7 @@ int hda_dsp_stream_hw_free(struct snd_sof_dev *sdev,
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_stream_hw_free, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_stream_hw_free, "SND_SOC_SOF_INTEL_HDA_COMMON");
bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev)
{
@@ -761,7 +761,7 @@ bool hda_dsp_check_stream_irq(struct snd_sof_dev *sdev)
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_check_stream_irq, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_check_stream_irq, "SND_SOC_SOF_INTEL_HDA_COMMON");
static void
hda_dsp_compr_bytes_transferred(struct hdac_stream *hstream, int direction)
@@ -858,7 +858,7 @@ irqreturn_t hda_dsp_stream_threaded_handler(int irq, void *context)
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS(hda_dsp_stream_threaded_handler, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_stream_threaded_handler, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_stream_init(struct snd_sof_dev *sdev)
{
@@ -996,7 +996,7 @@ int hda_dsp_stream_init(struct snd_sof_dev *sdev)
return 0;
}
-EXPORT_SYMBOL_NS(hda_dsp_stream_init, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_stream_init, "SND_SOC_SOF_INTEL_HDA_COMMON");
void hda_dsp_stream_free(struct snd_sof_dev *sdev)
{
@@ -1026,7 +1026,7 @@ void hda_dsp_stream_free(struct snd_sof_dev *sdev)
devm_kfree(sdev->dev, hda_stream);
}
}
-EXPORT_SYMBOL_NS(hda_dsp_stream_free, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_stream_free, "SND_SOC_SOF_INTEL_HDA_COMMON");
snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
int direction, bool can_sleep)
@@ -1113,7 +1113,7 @@ snd_pcm_uframes_t hda_dsp_stream_get_position(struct hdac_stream *hstream,
return pos;
}
-EXPORT_SYMBOL_NS(hda_dsp_stream_get_position, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_stream_get_position, "SND_SOC_SOF_INTEL_HDA_COMMON");
#define merge_u64(u32_u, u32_l) (((u64)(u32_u) << 32) | (u32_l))
@@ -1153,7 +1153,7 @@ u64 hda_dsp_get_stream_llp(struct snd_sof_dev *sdev,
return merge_u64(llp_u, llp_l);
}
-EXPORT_SYMBOL_NS(hda_dsp_get_stream_llp, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_get_stream_llp, "SND_SOC_SOF_INTEL_HDA_COMMON");
/**
* hda_dsp_get_stream_ldp - Retrieve the LDP (Linear DMA Position) of the stream
@@ -1185,4 +1185,4 @@ u64 hda_dsp_get_stream_ldp(struct snd_sof_dev *sdev,
return ((u64)ldp_u << 32) | ldp_l;
}
-EXPORT_SYMBOL_NS(hda_dsp_get_stream_ldp, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_get_stream_ldp, "SND_SOC_SOF_INTEL_HDA_COMMON");
diff --git a/sound/soc/sof/intel/hda-trace.c b/sound/soc/sof/intel/hda-trace.c
index 351eb2eb184b..5da8188ffcfe 100644
--- a/sound/soc/sof/intel/hda-trace.c
+++ b/sound/soc/sof/intel/hda-trace.c
@@ -68,7 +68,7 @@ int hda_dsp_trace_init(struct snd_sof_dev *sdev, struct snd_dma_buffer *dmab,
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_trace_init, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_trace_init, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_trace_release(struct snd_sof_dev *sdev)
{
@@ -87,7 +87,7 @@ int hda_dsp_trace_release(struct snd_sof_dev *sdev)
dev_dbg(sdev->dev, "DMA trace stream is not opened!\n");
return -ENODEV;
}
-EXPORT_SYMBOL_NS(hda_dsp_trace_release, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_trace_release, "SND_SOC_SOF_INTEL_HDA_COMMON");
int hda_dsp_trace_trigger(struct snd_sof_dev *sdev, int cmd)
{
@@ -95,4 +95,4 @@ int hda_dsp_trace_trigger(struct snd_sof_dev *sdev, int cmd)
return hda_dsp_stream_trigger(sdev, hda->dtrace_stream, cmd);
}
-EXPORT_SYMBOL_NS(hda_dsp_trace_trigger, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(hda_dsp_trace_trigger, "SND_SOC_SOF_INTEL_HDA_COMMON");
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 01b135068b1f..f991785f727e 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -238,7 +238,7 @@ int hda_sdw_startup(struct snd_sof_dev *sdev)
return sdw_intel_startup(hdev->sdw);
}
-EXPORT_SYMBOL_NS(hda_sdw_startup, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(hda_sdw_startup, "SND_SOC_SOF_INTEL_HDA_GENERIC");
static int hda_sdw_exit(struct snd_sof_dev *sdev)
{
@@ -280,7 +280,7 @@ bool hda_common_check_sdw_irq(struct snd_sof_dev *sdev)
out:
return ret;
}
-EXPORT_SYMBOL_NS(hda_common_check_sdw_irq, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(hda_common_check_sdw_irq, "SND_SOC_SOF_INTEL_HDA_GENERIC");
static bool hda_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
{
@@ -314,7 +314,7 @@ bool hda_sdw_check_wakeen_irq_common(struct snd_sof_dev *sdev)
return false;
}
-EXPORT_SYMBOL_NS(hda_sdw_check_wakeen_irq_common, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(hda_sdw_check_wakeen_irq_common, "SND_SOC_SOF_INTEL_HDA_GENERIC");
static bool hda_sdw_check_wakeen_irq(struct snd_sof_dev *sdev)
{
@@ -345,7 +345,7 @@ void hda_sdw_process_wakeen_common(struct snd_sof_dev *sdev)
sdw_intel_process_wakeen_event(hdev->sdw);
}
-EXPORT_SYMBOL_NS(hda_sdw_process_wakeen_common, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(hda_sdw_process_wakeen_common, "SND_SOC_SOF_INTEL_HDA_GENERIC");
#else /* IS_ENABLED(CONFIG_SND_SOC_SOF_INTEL_SOUNDWIRE) */
static inline int hda_sdw_acpi_scan(struct snd_sof_dev *sdev)
@@ -418,7 +418,7 @@ int hda_dsp_post_fw_run(struct snd_sof_dev *sdev)
/* re-enable clock gating and power gating */
return hda_dsp_ctrl_clock_power_gating(sdev, true);
}
-EXPORT_SYMBOL_NS(hda_dsp_post_fw_run, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(hda_dsp_post_fw_run, "SND_SOC_SOF_INTEL_HDA_GENERIC");
/*
* Debug
@@ -739,7 +739,7 @@ int hda_dsp_probe_early(struct snd_sof_dev *sdev)
err:
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_probe_early, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(hda_dsp_probe_early, "SND_SOC_SOF_INTEL_HDA_GENERIC");
int hda_dsp_probe(struct snd_sof_dev *sdev)
{
@@ -894,7 +894,7 @@ hdac_bus_unmap:
return ret;
}
-EXPORT_SYMBOL_NS(hda_dsp_probe, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(hda_dsp_probe, "SND_SOC_SOF_INTEL_HDA_GENERIC");
void hda_dsp_remove(struct snd_sof_dev *sdev)
{
@@ -954,7 +954,7 @@ skip_disable_dsp:
if (!sdev->dspless_mode_selected)
iounmap(sdev->bar[HDA_DSP_BAR]);
}
-EXPORT_SYMBOL_NS(hda_dsp_remove, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(hda_dsp_remove, "SND_SOC_SOF_INTEL_HDA_GENERIC");
void hda_dsp_remove_late(struct snd_sof_dev *sdev)
{
@@ -970,7 +970,7 @@ int hda_power_down_dsp(struct snd_sof_dev *sdev)
return hda_dsp_core_reset_power_down(sdev, chip->host_managed_cores_mask);
}
-EXPORT_SYMBOL_NS(hda_power_down_dsp, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(hda_power_down_dsp, "SND_SOC_SOF_INTEL_HDA_GENERIC");
#if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA_AUDIO_CODEC)
static void hda_generic_machine_select(struct snd_sof_dev *sdev,
@@ -1471,7 +1471,7 @@ int hda_pci_intel_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return sof_pci_probe(pci, pci_id);
}
-EXPORT_SYMBOL_NS(hda_pci_intel_probe, SND_SOC_SOF_INTEL_HDA_GENERIC);
+EXPORT_SYMBOL_NS(hda_pci_intel_probe, "SND_SOC_SOF_INTEL_HDA_GENERIC");
int hda_register_clients(struct snd_sof_dev *sdev)
{
@@ -1485,13 +1485,13 @@ void hda_unregister_clients(struct snd_sof_dev *sdev)
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for HDaudio platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
-MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC);
-MODULE_IMPORT_NS(SND_SOC_SOF_HDA_AUDIO_CODEC_I915);
-MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
-MODULE_IMPORT_NS(SND_INTEL_SOUNDWIRE_ACPI);
-MODULE_IMPORT_NS(SOUNDWIRE_INTEL_INIT);
-MODULE_IMPORT_NS(SOUNDWIRE_INTEL);
-MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON);
-MODULE_IMPORT_NS(SND_SOC_ACPI_INTEL_MATCH);
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
+MODULE_IMPORT_NS("SND_SOC_SOF_HDA_AUDIO_CODEC");
+MODULE_IMPORT_NS("SND_SOC_SOF_HDA_AUDIO_CODEC_I915");
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
+MODULE_IMPORT_NS("SND_INTEL_SOUNDWIRE_ACPI");
+MODULE_IMPORT_NS("SOUNDWIRE_INTEL_INIT");
+MODULE_IMPORT_NS("SOUNDWIRE_INTEL");
+MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
+MODULE_IMPORT_NS("SND_SOC_ACPI_INTEL_MATCH");
diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h
index 22bd9c3c8216..ee4ccc1a5490 100644
--- a/sound/soc/sof/intel/hda.h
+++ b/sound/soc/sof/intel/hda.h
@@ -1038,8 +1038,6 @@ const struct hda_dai_widget_dma_ops *
hda_select_dai_widget_ops(struct snd_sof_dev *sdev, struct snd_sof_widget *swidget);
int hda_dai_config(struct snd_soc_dapm_widget *w, unsigned int flags,
struct snd_sof_dai_config_data *data);
-int hda_link_dma_cleanup(struct snd_pcm_substream *substream, struct hdac_ext_stream *hext_stream,
- struct snd_soc_dai *cpu_dai);
static inline struct snd_sof_dev *widget_to_sdev(struct snd_soc_dapm_widget *w)
{
diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c
index e3c4b4a0d705..793d8539821d 100644
--- a/sound/soc/sof/intel/lnl.c
+++ b/sound/soc/sof/intel/lnl.c
@@ -22,7 +22,7 @@
/* LunarLake ops */
struct snd_sof_dsp_ops sof_lnl_ops;
-EXPORT_SYMBOL_NS(sof_lnl_ops, SND_SOC_SOF_INTEL_LNL);
+EXPORT_SYMBOL_NS(sof_lnl_ops, "SND_SOC_SOF_INTEL_LNL");
static const struct snd_sof_debugfs_map lnl_dsp_debugfs[] = {
{"hda", HDA_DSP_HDA_BAR, 0, 0x4000, SOF_DEBUGFS_ACCESS_ALWAYS},
@@ -182,7 +182,7 @@ int sof_lnl_ops_init(struct snd_sof_dev *sdev)
return 0;
};
-EXPORT_SYMBOL_NS(sof_lnl_ops_init, SND_SOC_SOF_INTEL_LNL);
+EXPORT_SYMBOL_NS(sof_lnl_ops_init, "SND_SOC_SOF_INTEL_LNL");
/* Check if an SDW IRQ occurred */
static bool lnl_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
@@ -261,4 +261,4 @@ const struct sof_intel_dsp_desc ptl_chip_info = {
.disable_interrupts = lnl_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_ACE_3_0,
};
-EXPORT_SYMBOL_NS(ptl_chip_info, SND_SOC_SOF_INTEL_LNL);
+EXPORT_SYMBOL_NS(ptl_chip_info, "SND_SOC_SOF_INTEL_LNL");
diff --git a/sound/soc/sof/intel/mtl.c b/sound/soc/sof/intel/mtl.c
index 2b9d22ccf345..d07c68f431ba 100644
--- a/sound/soc/sof/intel/mtl.c
+++ b/sound/soc/sof/intel/mtl.c
@@ -77,7 +77,7 @@ bool mtl_dsp_check_ipc_irq(struct snd_sof_dev *sdev)
return false;
}
-EXPORT_SYMBOL_NS(mtl_dsp_check_ipc_irq, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_dsp_check_ipc_irq, "SND_SOC_SOF_INTEL_MTL");
/* Check if an SDW IRQ occurred */
static bool mtl_dsp_check_sdw_irq(struct snd_sof_dev *sdev)
@@ -121,7 +121,7 @@ int mtl_ipc_send_msg(struct snd_sof_dev *sdev, struct snd_sof_ipc_msg *msg)
return 0;
}
-EXPORT_SYMBOL_NS(mtl_ipc_send_msg, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_ipc_send_msg, "SND_SOC_SOF_INTEL_MTL");
void mtl_enable_ipc_interrupts(struct snd_sof_dev *sdev)
{
@@ -149,7 +149,7 @@ void mtl_disable_ipc_interrupts(struct snd_sof_dev *sdev)
snd_sof_dsp_update_bits(sdev, HDA_DSP_BAR, chip->ipc_ctl,
MTL_DSP_REG_HFIPCXCTL_BUSY | MTL_DSP_REG_HFIPCXCTL_DONE, 0);
}
-EXPORT_SYMBOL_NS(mtl_disable_ipc_interrupts, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_disable_ipc_interrupts, "SND_SOC_SOF_INTEL_MTL");
static void mtl_enable_sdw_irq(struct snd_sof_dev *sdev, bool enable)
{
@@ -234,7 +234,7 @@ int mtl_enable_interrupts(struct snd_sof_dev *sdev, bool enable)
return ret;
}
-EXPORT_SYMBOL_NS(mtl_enable_interrupts, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_enable_interrupts, "SND_SOC_SOF_INTEL_MTL");
/* pre fw run operations */
int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev)
@@ -297,7 +297,7 @@ int mtl_dsp_pre_fw_run(struct snd_sof_dev *sdev)
return ret;
}
-EXPORT_SYMBOL_NS(mtl_dsp_pre_fw_run, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_dsp_pre_fw_run, "SND_SOC_SOF_INTEL_MTL");
int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev)
{
@@ -324,7 +324,7 @@ int mtl_dsp_post_fw_run(struct snd_sof_dev *sdev)
hda_sdw_int_enable(sdev, true);
return 0;
}
-EXPORT_SYMBOL_NS(mtl_dsp_post_fw_run, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_dsp_post_fw_run, "SND_SOC_SOF_INTEL_MTL");
void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
{
@@ -342,7 +342,7 @@ void mtl_dsp_dump(struct snd_sof_dev *sdev, u32 flags)
sof_ipc4_intel_dump_telemetry_state(sdev, flags);
}
-EXPORT_SYMBOL_NS(mtl_dsp_dump, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_dsp_dump, "SND_SOC_SOF_INTEL_MTL");
static bool mtl_dsp_primary_core_is_enabled(struct snd_sof_dev *sdev)
{
@@ -453,7 +453,7 @@ int mtl_power_down_dsp(struct snd_sof_dev *sdev)
(dsphfdsscs & cpa) == 0, HDA_DSP_REG_POLL_INTERVAL_US,
HDA_DSP_RESET_TIMEOUT_US);
}
-EXPORT_SYMBOL_NS(mtl_power_down_dsp, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_power_down_dsp, "SND_SOC_SOF_INTEL_MTL");
int mtl_dsp_cl_init(struct snd_sof_dev *sdev, int stream_tag, bool imr_boot)
{
@@ -556,7 +556,7 @@ err:
kfree(dump_msg);
return ret;
}
-EXPORT_SYMBOL_NS(mtl_dsp_cl_init, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_dsp_cl_init, "SND_SOC_SOF_INTEL_MTL");
irqreturn_t mtl_ipc_irq_thread(int irq, void *context)
{
@@ -640,19 +640,19 @@ irqreturn_t mtl_ipc_irq_thread(int irq, void *context)
return IRQ_HANDLED;
}
-EXPORT_SYMBOL_NS(mtl_ipc_irq_thread, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_ipc_irq_thread, "SND_SOC_SOF_INTEL_MTL");
int mtl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
{
return MTL_DSP_MBOX_UPLINK_OFFSET;
}
-EXPORT_SYMBOL_NS(mtl_dsp_ipc_get_mailbox_offset, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_dsp_ipc_get_mailbox_offset, "SND_SOC_SOF_INTEL_MTL");
int mtl_dsp_ipc_get_window_offset(struct snd_sof_dev *sdev, u32 id)
{
return MTL_SRAM_WINDOW_OFFSET(id);
}
-EXPORT_SYMBOL_NS(mtl_dsp_ipc_get_window_offset, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_dsp_ipc_get_window_offset, "SND_SOC_SOF_INTEL_MTL");
void mtl_ipc_dump(struct snd_sof_dev *sdev)
{
@@ -670,7 +670,7 @@ void mtl_ipc_dump(struct snd_sof_dev *sdev)
"Host IPC initiator: %#x|%#x|%#x, target: %#x|%#x|%#x, ctl: %#x\n",
hipcidr, hipcidd, hipcida, hipctdr, hipctdd, hipctda, hipcctl);
}
-EXPORT_SYMBOL_NS(mtl_ipc_dump, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_ipc_dump, "SND_SOC_SOF_INTEL_MTL");
static int mtl_dsp_disable_interrupts(struct snd_sof_dev *sdev)
{
@@ -691,7 +691,7 @@ int mtl_dsp_core_get(struct snd_sof_dev *sdev, int core)
return 0;
}
-EXPORT_SYMBOL_NS(mtl_dsp_core_get, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_dsp_core_get, "SND_SOC_SOF_INTEL_MTL");
int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core)
{
@@ -709,7 +709,7 @@ int mtl_dsp_core_put(struct snd_sof_dev *sdev, int core)
return 0;
}
-EXPORT_SYMBOL_NS(mtl_dsp_core_put, SND_SOC_SOF_INTEL_MTL);
+EXPORT_SYMBOL_NS(mtl_dsp_core_put, "SND_SOC_SOF_INTEL_MTL");
/* Meteorlake ops */
struct snd_sof_dsp_ops sof_mtl_ops;
diff --git a/sound/soc/sof/intel/pci-apl.c b/sound/soc/sof/intel/pci-apl.c
index f006dcf5458a..94ab3c61e3f7 100644
--- a/sound/soc/sof/intel/pci-apl.c
+++ b/sound/soc/sof/intel/pci-apl.c
@@ -106,6 +106,6 @@ module_pci_driver(snd_sof_pci_intel_apl_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for ApolloLake platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/intel/pci-cnl.c b/sound/soc/sof/intel/pci-cnl.c
index a8406342f08b..739c352c3860 100644
--- a/sound/soc/sof/intel/pci-cnl.c
+++ b/sound/soc/sof/intel/pci-cnl.c
@@ -144,6 +144,6 @@ module_pci_driver(snd_sof_pci_intel_cnl_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for CannonLake platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/intel/pci-icl.c b/sound/soc/sof/intel/pci-icl.c
index 25effca50d9f..8545ab95eac8 100644
--- a/sound/soc/sof/intel/pci-icl.c
+++ b/sound/soc/sof/intel/pci-icl.c
@@ -109,7 +109,7 @@ module_pci_driver(snd_sof_pci_intel_icl_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for IceLake platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CNL);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_CNL");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/intel/pci-lnl.c b/sound/soc/sof/intel/pci-lnl.c
index 602c574064eb..8d4d74ac4398 100644
--- a/sound/soc/sof/intel/pci-lnl.c
+++ b/sound/soc/sof/intel/pci-lnl.c
@@ -71,8 +71,8 @@ module_pci_driver(snd_sof_pci_intel_lnl_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for LunarLake platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_MTL);
-MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL");
+MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/intel/pci-mtl.c b/sound/soc/sof/intel/pci-mtl.c
index 8cb0333c033e..71f711cf8599 100644
--- a/sound/soc/sof/intel/pci-mtl.c
+++ b/sound/soc/sof/intel/pci-mtl.c
@@ -134,6 +134,6 @@ module_pci_driver(snd_sof_pci_intel_mtl_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for MeteorLake platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/intel/pci-ptl.c b/sound/soc/sof/intel/pci-ptl.c
index 69195b5e7b1a..0aacdfac9fb4 100644
--- a/sound/soc/sof/intel/pci-ptl.c
+++ b/sound/soc/sof/intel/pci-ptl.c
@@ -69,9 +69,9 @@ module_pci_driver(snd_sof_pci_intel_ptl_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for PantherLake platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_LNL);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_MTL);
-MODULE_IMPORT_NS(SND_SOC_SOF_HDA_MLINK);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_LNL");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_MTL");
+MODULE_IMPORT_NS("SND_SOC_SOF_HDA_MLINK");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/intel/pci-skl.c b/sound/soc/sof/intel/pci-skl.c
index 8ca0231d7e4f..bd9daae51e4c 100644
--- a/sound/soc/sof/intel/pci-skl.c
+++ b/sound/soc/sof/intel/pci-skl.c
@@ -90,6 +90,6 @@ module_pci_driver(snd_sof_pci_intel_skl_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for SkyLake platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c
index 01db2e720b44..f76a7197f6ca 100644
--- a/sound/soc/sof/intel/pci-tgl.c
+++ b/sound/soc/sof/intel/pci-tgl.c
@@ -318,7 +318,7 @@ module_pci_driver(snd_sof_pci_intel_tgl_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for TigerLake platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_GENERIC);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HDA_COMMON);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_CNL);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_GENERIC");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HDA_COMMON");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_CNL");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
diff --git a/sound/soc/sof/intel/pci-tng.c b/sound/soc/sof/intel/pci-tng.c
index 1375c393827e..b585ac4a85c2 100644
--- a/sound/soc/sof/intel/pci-tng.c
+++ b/sound/soc/sof/intel/pci-tng.c
@@ -245,7 +245,7 @@ module_pci_driver(snd_sof_pci_intel_tng_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for Tangier platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_HIFI_EP_IPC);
-MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
-MODULE_IMPORT_NS(SND_SOC_SOF_PCI_DEV);
-MODULE_IMPORT_NS(SND_SOC_SOF_INTEL_ATOM_HIFI_EP);
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_HIFI_EP_IPC");
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
+MODULE_IMPORT_NS("SND_SOC_SOF_PCI_DEV");
+MODULE_IMPORT_NS("SND_SOC_SOF_INTEL_ATOM_HIFI_EP");
diff --git a/sound/soc/sof/intel/skl.c b/sound/soc/sof/intel/skl.c
index 9a002811e9ff..0696bce65e33 100644
--- a/sound/soc/sof/intel/skl.c
+++ b/sound/soc/sof/intel/skl.c
@@ -50,7 +50,7 @@ static int skl_dsp_ipc_get_mailbox_offset(struct snd_sof_dev *sdev)
/* skylake ops */
struct snd_sof_dsp_ops sof_skl_ops;
-EXPORT_SYMBOL_NS(sof_skl_ops, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(sof_skl_ops, "SND_SOC_SOF_INTEL_HDA_COMMON");
int sof_skl_ops_init(struct snd_sof_dev *sdev)
{
@@ -96,7 +96,7 @@ int sof_skl_ops_init(struct snd_sof_dev *sdev)
return 0;
};
-EXPORT_SYMBOL_NS(sof_skl_ops_init, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(sof_skl_ops_init, "SND_SOC_SOF_INTEL_HDA_COMMON");
const struct sof_intel_dsp_desc skl_chip_info = {
.cores_num = 2,
@@ -114,4 +114,4 @@ const struct sof_intel_dsp_desc skl_chip_info = {
.disable_interrupts = hda_dsp_disable_interrupts,
.hw_ip_version = SOF_INTEL_CAVS_1_5,
};
-EXPORT_SYMBOL_NS(skl_chip_info, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(skl_chip_info, "SND_SOC_SOF_INTEL_HDA_COMMON");
diff --git a/sound/soc/sof/intel/telemetry.c b/sound/soc/sof/intel/telemetry.c
index 2d2f96548310..dcaaf03599db 100644
--- a/sound/soc/sof/intel/telemetry.c
+++ b/sound/soc/sof/intel/telemetry.c
@@ -93,4 +93,4 @@ free_block:
free_telemetry_data:
kfree(telemetry_data);
}
-EXPORT_SYMBOL_NS(sof_ipc4_intel_dump_telemetry_state, SND_SOC_SOF_INTEL_HDA_COMMON);
+EXPORT_SYMBOL_NS(sof_ipc4_intel_dump_telemetry_state, "SND_SOC_SOF_INTEL_HDA_COMMON");
diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c
index be61e377e59e..e98b53b67d12 100644
--- a/sound/soc/sof/ipc3-topology.c
+++ b/sound/soc/sof/ipc3-topology.c
@@ -20,6 +20,9 @@
/* size of tplg ABI in bytes */
#define SOF_IPC3_TPLG_ABI_SIZE 3
+/* Base of SOF_DAI_INTEL_ALH, this should be aligned with SOC_SDW_INTEL_BIDIR_PDI_BASE */
+#define INTEL_ALH_DAI_INDEX_BASE 2
+
struct sof_widget_data {
int ctrl_type;
int ipc_cmd;
@@ -1585,14 +1588,26 @@ static int sof_ipc3_widget_setup_comp_dai(struct snd_sof_widget *swidget)
ret = sof_update_ipc_object(scomp, comp_dai, SOF_DAI_TOKENS, swidget->tuples,
swidget->num_tuples, sizeof(*comp_dai), 1);
if (ret < 0)
- goto free;
+ goto free_comp;
/* update comp_tokens */
ret = sof_update_ipc_object(scomp, &comp_dai->config, SOF_COMP_TOKENS,
swidget->tuples, swidget->num_tuples,
sizeof(comp_dai->config), 1);
if (ret < 0)
- goto free;
+ goto free_comp;
+
+ /* Subtract the base to match the FW dai index. */
+ if (comp_dai->type == SOF_DAI_INTEL_ALH) {
+ if (comp_dai->dai_index < INTEL_ALH_DAI_INDEX_BASE) {
+ dev_err(sdev->dev,
+ "Invalid ALH dai index %d, only Pin numbers >= %d can be used\n",
+ comp_dai->dai_index, INTEL_ALH_DAI_INDEX_BASE);
+ ret = -EINVAL;
+ goto free_comp;
+ }
+ comp_dai->dai_index -= INTEL_ALH_DAI_INDEX_BASE;
+ }
dev_dbg(scomp->dev, "dai %s: type %d index %d\n",
swidget->widget->name, comp_dai->type, comp_dai->dai_index);
@@ -2167,8 +2182,16 @@ static int sof_ipc3_dai_config(struct snd_sof_dev *sdev, struct snd_sof_widget *
case SOF_DAI_INTEL_ALH:
if (data) {
/* save the dai_index during hw_params and reuse it for hw_free */
- if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS)
- config->dai_index = data->dai_index;
+ if (flags & SOF_DAI_CONFIG_FLAGS_HW_PARAMS) {
+ /* Subtract the base to match the FW dai index. */
+ if (data->dai_index < INTEL_ALH_DAI_INDEX_BASE) {
+ dev_err(sdev->dev,
+ "Invalid ALH dai index %d, only Pin numbers >= %d can be used\n",
+ config->dai_index, INTEL_ALH_DAI_INDEX_BASE);
+ return -EINVAL;
+ }
+ config->dai_index = data->dai_index - INTEL_ALH_DAI_INDEX_BASE;
+ }
config->alh.stream_id = data->dai_data;
}
break;
diff --git a/sound/soc/sof/mediatek/mt8186/mt8186.c b/sound/soc/sof/mediatek/mt8186/mt8186.c
index 9466f7d2e535..9955dfa520ae 100644
--- a/sound/soc/sof/mediatek/mt8186/mt8186.c
+++ b/sound/soc/sof/mediatek/mt8186/mt8186.c
@@ -668,5 +668,5 @@ module_platform_driver(snd_sof_of_mt8186_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for MT8186/MT8188 platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
-MODULE_IMPORT_NS(SND_SOC_SOF_MTK_COMMON);
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
+MODULE_IMPORT_NS("SND_SOC_SOF_MTK_COMMON");
diff --git a/sound/soc/sof/mediatek/mt8195/mt8195.c b/sound/soc/sof/mediatek/mt8195/mt8195.c
index 5b4423ed8023..6032b566c679 100644
--- a/sound/soc/sof/mediatek/mt8195/mt8195.c
+++ b/sound/soc/sof/mediatek/mt8195/mt8195.c
@@ -624,5 +624,5 @@ module_platform_driver(snd_sof_of_mt8195_driver);
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for MTL 8195 platforms");
-MODULE_IMPORT_NS(SND_SOC_SOF_XTENSA);
-MODULE_IMPORT_NS(SND_SOC_SOF_MTK_COMMON);
+MODULE_IMPORT_NS("SND_SOC_SOF_XTENSA");
+MODULE_IMPORT_NS("SND_SOC_SOF_MTK_COMMON");
diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c
index 76ff798a4a1e..58fd5f7c7905 100644
--- a/sound/soc/sof/sof-acpi-dev.c
+++ b/sound/soc/sof/sof-acpi-dev.c
@@ -41,7 +41,7 @@ const struct dev_pm_ops sof_acpi_pm = {
SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume,
snd_sof_runtime_idle)
};
-EXPORT_SYMBOL_NS(sof_acpi_pm, SND_SOC_SOF_ACPI_DEV);
+EXPORT_SYMBOL_NS(sof_acpi_pm, "SND_SOC_SOF_ACPI_DEV");
static void sof_acpi_probe_complete(struct device *dev)
{
@@ -85,7 +85,7 @@ int sof_acpi_probe(struct platform_device *pdev, const struct sof_dev_desc *desc
/* call sof helper for DSP hardware probe */
return snd_sof_device_probe(dev, sof_pdata);
}
-EXPORT_SYMBOL_NS(sof_acpi_probe, SND_SOC_SOF_ACPI_DEV);
+EXPORT_SYMBOL_NS(sof_acpi_probe, "SND_SOC_SOF_ACPI_DEV");
void sof_acpi_remove(struct platform_device *pdev)
{
@@ -97,7 +97,7 @@ void sof_acpi_remove(struct platform_device *pdev)
/* call sof helper for DSP hardware remove */
snd_sof_device_remove(dev);
}
-EXPORT_SYMBOL_NS(sof_acpi_remove, SND_SOC_SOF_ACPI_DEV);
+EXPORT_SYMBOL_NS(sof_acpi_remove, "SND_SOC_SOF_ACPI_DEV");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for ACPI platforms");
diff --git a/sound/soc/sof/sof-client-ipc-flood-test.c b/sound/soc/sof/sof-client-ipc-flood-test.c
index e7d2001140e8..b35c98896968 100644
--- a/sound/soc/sof/sof-client-ipc-flood-test.c
+++ b/sound/soc/sof/sof-client-ipc-flood-test.c
@@ -396,4 +396,4 @@ module_auxiliary_driver(sof_ipc_flood_client_drv);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SOF IPC Flood Test Client Driver");
-MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
+MODULE_IMPORT_NS("SND_SOC_SOF_CLIENT");
diff --git a/sound/soc/sof/sof-client-ipc-kernel-injector.c b/sound/soc/sof/sof-client-ipc-kernel-injector.c
index d3f541069b24..8b28c3dc920c 100644
--- a/sound/soc/sof/sof-client-ipc-kernel-injector.c
+++ b/sound/soc/sof/sof-client-ipc-kernel-injector.c
@@ -159,4 +159,4 @@ module_auxiliary_driver(sof_msg_inject_client_drv);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SOF IPC Kernel Injector Client Driver");
-MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
+MODULE_IMPORT_NS("SND_SOC_SOF_CLIENT");
diff --git a/sound/soc/sof/sof-client-ipc-msg-injector.c b/sound/soc/sof/sof-client-ipc-msg-injector.c
index d0f8beb9d000..ba7ca1c5027f 100644
--- a/sound/soc/sof/sof-client-ipc-msg-injector.c
+++ b/sound/soc/sof/sof-client-ipc-msg-injector.c
@@ -337,4 +337,4 @@ module_auxiliary_driver(sof_msg_inject_client_drv);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SOF IPC Message Injector Client Driver");
-MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
+MODULE_IMPORT_NS("SND_SOC_SOF_CLIENT");
diff --git a/sound/soc/sof/sof-client-probes.c b/sound/soc/sof/sof-client-probes.c
index ccc7d38ddc38..aff9ce980429 100644
--- a/sound/soc/sof/sof-client-probes.c
+++ b/sound/soc/sof/sof-client-probes.c
@@ -542,4 +542,4 @@ module_auxiliary_driver(sof_probes_client_drv);
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("SOF Probes Client Driver");
-MODULE_IMPORT_NS(SND_SOC_SOF_CLIENT);
+MODULE_IMPORT_NS("SND_SOC_SOF_CLIENT");
diff --git a/sound/soc/sof/sof-client.c b/sound/soc/sof/sof-client.c
index 5d6005a88e79..4c7951338c66 100644
--- a/sound/soc/sof/sof-client.c
+++ b/sound/soc/sof/sof-client.c
@@ -259,7 +259,7 @@ err_dev_add_data:
return ret;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_dev_register, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_dev_register, "SND_SOC_SOF_CLIENT");
void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 id)
{
@@ -282,7 +282,7 @@ void sof_client_dev_unregister(struct snd_sof_dev *sdev, const char *name, u32 i
mutex_unlock(&sdev->ipc_client_mutex);
}
-EXPORT_SYMBOL_NS_GPL(sof_client_dev_unregister, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_dev_unregister, "SND_SOC_SOF_CLIENT");
int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg,
void *reply_data, size_t reply_bytes)
@@ -301,7 +301,7 @@ int sof_client_ipc_tx_message(struct sof_client_dev *cdev, void *ipc_msg,
return -EINVAL;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_ipc_tx_message, "SND_SOC_SOF_CLIENT");
int sof_client_ipc_rx_message(struct sof_client_dev *cdev, void *ipc_msg, void *msg_buf)
{
@@ -320,7 +320,7 @@ int sof_client_ipc_rx_message(struct sof_client_dev *cdev, void *ipc_msg, void *
return -EOPNOTSUPP;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_ipc_rx_message, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_ipc_rx_message, "SND_SOC_SOF_CLIENT");
int sof_client_ipc_set_get_data(struct sof_client_dev *cdev, void *ipc_msg,
bool set)
@@ -339,7 +339,7 @@ int sof_client_ipc_set_get_data(struct sof_client_dev *cdev, void *ipc_msg,
return -EINVAL;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_ipc_set_get_data, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_ipc_set_get_data, "SND_SOC_SOF_CLIENT");
#ifdef CONFIG_SND_SOC_SOF_IPC4
struct sof_ipc4_fw_module *sof_client_ipc4_find_module(struct sof_client_dev *c, const guid_t *uuid)
@@ -352,7 +352,7 @@ struct sof_ipc4_fw_module *sof_client_ipc4_find_module(struct sof_client_dev *c,
return NULL;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_ipc4_find_module, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_ipc4_find_module, "SND_SOC_SOF_CLIENT");
#endif
int sof_suspend_clients(struct snd_sof_dev *sdev, pm_message_t state)
@@ -376,7 +376,7 @@ int sof_suspend_clients(struct snd_sof_dev *sdev, pm_message_t state)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(sof_suspend_clients, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_suspend_clients, "SND_SOC_SOF_CLIENT");
int sof_resume_clients(struct snd_sof_dev *sdev)
{
@@ -399,20 +399,20 @@ int sof_resume_clients(struct snd_sof_dev *sdev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(sof_resume_clients, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_resume_clients, "SND_SOC_SOF_CLIENT");
struct dentry *sof_client_get_debugfs_root(struct sof_client_dev *cdev)
{
return cdev->sdev->debugfs_root;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_get_debugfs_root, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_get_debugfs_root, "SND_SOC_SOF_CLIENT");
/* DMA buffer allocation in client drivers must use the core SOF device */
struct device *sof_client_get_dma_dev(struct sof_client_dev *cdev)
{
return cdev->sdev->dev;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_get_dma_dev, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_get_dma_dev, "SND_SOC_SOF_CLIENT");
const struct sof_ipc_fw_version *sof_client_get_fw_version(struct sof_client_dev *cdev)
{
@@ -420,7 +420,7 @@ const struct sof_ipc_fw_version *sof_client_get_fw_version(struct sof_client_dev
return &sdev->fw_ready.version;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_version, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_version, "SND_SOC_SOF_CLIENT");
size_t sof_client_get_ipc_max_payload_size(struct sof_client_dev *cdev)
{
@@ -428,7 +428,7 @@ size_t sof_client_get_ipc_max_payload_size(struct sof_client_dev *cdev)
return sdev->ipc->max_payload_size;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_max_payload_size, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_max_payload_size, "SND_SOC_SOF_CLIENT");
enum sof_ipc_type sof_client_get_ipc_type(struct sof_client_dev *cdev)
{
@@ -436,7 +436,7 @@ enum sof_ipc_type sof_client_get_ipc_type(struct sof_client_dev *cdev)
return sdev->pdata->ipc_type;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_type, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_get_ipc_type, "SND_SOC_SOF_CLIENT");
/* module refcount management of SOF core */
int sof_client_core_module_get(struct sof_client_dev *cdev)
@@ -448,7 +448,7 @@ int sof_client_core_module_get(struct sof_client_dev *cdev)
return 0;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_core_module_get, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_core_module_get, "SND_SOC_SOF_CLIENT");
void sof_client_core_module_put(struct sof_client_dev *cdev)
{
@@ -456,7 +456,7 @@ void sof_client_core_module_put(struct sof_client_dev *cdev)
module_put(sdev->dev->driver->owner);
}
-EXPORT_SYMBOL_NS_GPL(sof_client_core_module_put, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_core_module_put, "SND_SOC_SOF_CLIENT");
/* IPC event handling */
void sof_client_ipc_rx_dispatcher(struct snd_sof_dev *sdev, void *msg_buf)
@@ -525,7 +525,7 @@ int sof_client_register_ipc_rx_handler(struct sof_client_dev *cdev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_register_ipc_rx_handler, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_register_ipc_rx_handler, "SND_SOC_SOF_CLIENT");
void sof_client_unregister_ipc_rx_handler(struct sof_client_dev *cdev,
u32 ipc_msg_type)
@@ -545,7 +545,7 @@ void sof_client_unregister_ipc_rx_handler(struct sof_client_dev *cdev,
mutex_unlock(&sdev->client_event_handler_mutex);
}
-EXPORT_SYMBOL_NS_GPL(sof_client_unregister_ipc_rx_handler, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_unregister_ipc_rx_handler, "SND_SOC_SOF_CLIENT");
/*DSP state notification and query */
void sof_client_fw_state_dispatcher(struct snd_sof_dev *sdev)
@@ -583,7 +583,7 @@ int sof_client_register_fw_state_handler(struct sof_client_dev *cdev,
return 0;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_register_fw_state_handler, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_register_fw_state_handler, "SND_SOC_SOF_CLIENT");
void sof_client_unregister_fw_state_handler(struct sof_client_dev *cdev)
{
@@ -602,7 +602,7 @@ void sof_client_unregister_fw_state_handler(struct sof_client_dev *cdev)
mutex_unlock(&sdev->client_event_handler_mutex);
}
-EXPORT_SYMBOL_NS_GPL(sof_client_unregister_fw_state_handler, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_unregister_fw_state_handler, "SND_SOC_SOF_CLIENT");
enum sof_fw_state sof_client_get_fw_state(struct sof_client_dev *cdev)
{
@@ -610,4 +610,4 @@ enum sof_fw_state sof_client_get_fw_state(struct sof_client_dev *cdev)
return sdev->fw_state;
}
-EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_state, SND_SOC_SOF_CLIENT);
+EXPORT_SYMBOL_NS_GPL(sof_client_get_fw_state, "SND_SOC_SOF_CLIENT");
diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c
index fe5650616573..103377e2caaf 100644
--- a/sound/soc/sof/sof-pci-dev.c
+++ b/sound/soc/sof/sof-pci-dev.c
@@ -162,7 +162,7 @@ const struct dev_pm_ops sof_pci_pm = {
SET_RUNTIME_PM_OPS(snd_sof_runtime_suspend, snd_sof_runtime_resume,
snd_sof_runtime_idle)
};
-EXPORT_SYMBOL_NS(sof_pci_pm, SND_SOC_SOF_PCI_DEV);
+EXPORT_SYMBOL_NS(sof_pci_pm, "SND_SOC_SOF_PCI_DEV");
static void sof_pci_probe_complete(struct device *dev)
{
@@ -280,7 +280,7 @@ out:
return ret;
}
-EXPORT_SYMBOL_NS(sof_pci_probe, SND_SOC_SOF_PCI_DEV);
+EXPORT_SYMBOL_NS(sof_pci_probe, "SND_SOC_SOF_PCI_DEV");
void sof_pci_remove(struct pci_dev *pci)
{
@@ -295,13 +295,13 @@ void sof_pci_remove(struct pci_dev *pci)
/* release pci regions and disable device */
pci_release_regions(pci);
}
-EXPORT_SYMBOL_NS(sof_pci_remove, SND_SOC_SOF_PCI_DEV);
+EXPORT_SYMBOL_NS(sof_pci_remove, "SND_SOC_SOF_PCI_DEV");
void sof_pci_shutdown(struct pci_dev *pci)
{
snd_sof_device_shutdown(&pci->dev);
}
-EXPORT_SYMBOL_NS(sof_pci_shutdown, SND_SOC_SOF_PCI_DEV);
+EXPORT_SYMBOL_NS(sof_pci_shutdown, "SND_SOC_SOF_PCI_DEV");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF support for PCI platforms");
diff --git a/sound/soc/sof/xtensa/core.c b/sound/soc/sof/xtensa/core.c
index 3cf8c84beff9..50623e65fe1a 100644
--- a/sound/soc/sof/xtensa/core.c
+++ b/sound/soc/sof/xtensa/core.c
@@ -149,7 +149,7 @@ const struct dsp_arch_ops sof_xtensa_arch_ops = {
.dsp_oops = xtensa_dsp_oops,
.dsp_stack = xtensa_stack,
};
-EXPORT_SYMBOL_NS(sof_xtensa_arch_ops, SND_SOC_SOF_XTENSA);
+EXPORT_SYMBOL_NS(sof_xtensa_arch_ops, "SND_SOC_SOF_XTENSA");
MODULE_LICENSE("Dual BSD/GPL");
MODULE_DESCRIPTION("SOF Xtensa DSP support");
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 8f85200292f3..842ba5b801ea 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -36,6 +36,12 @@ union uac23_clock_multiplier_desc {
struct uac_clock_multiplier_descriptor v3;
};
+/* check whether the descriptor bLength has the minimal length */
+#define DESC_LENGTH_CHECK(p, proto) \
+ ((proto) == UAC_VERSION_3 ? \
+ ((p)->v3.bLength >= sizeof((p)->v3)) : \
+ ((p)->v2.bLength >= sizeof((p)->v2)))
+
#define GET_VAL(p, proto, field) \
((proto) == UAC_VERSION_3 ? (p)->v3.field : (p)->v2.field)
@@ -58,6 +64,8 @@ static bool validate_clock_source(void *p, int id, int proto)
{
union uac23_clock_source_desc *cs = p;
+ if (!DESC_LENGTH_CHECK(cs, proto))
+ return false;
return GET_VAL(cs, proto, bClockID) == id;
}
@@ -65,13 +73,27 @@ static bool validate_clock_selector(void *p, int id, int proto)
{
union uac23_clock_selector_desc *cs = p;
- return GET_VAL(cs, proto, bClockID) == id;
+ if (!DESC_LENGTH_CHECK(cs, proto))
+ return false;
+ if (GET_VAL(cs, proto, bClockID) != id)
+ return false;
+ /* additional length check for baCSourceID array (in bNrInPins size)
+ * and two more fields (which sizes depend on the protocol)
+ */
+ if (proto == UAC_VERSION_3)
+ return cs->v3.bLength >= sizeof(cs->v3) + cs->v3.bNrInPins +
+ 4 /* bmControls */ + 2 /* wCSelectorDescrStr */;
+ else
+ return cs->v2.bLength >= sizeof(cs->v2) + cs->v2.bNrInPins +
+ 1 /* bmControls */ + 1 /* iClockSelector */;
}
static bool validate_clock_multiplier(void *p, int id, int proto)
{
union uac23_clock_multiplier_desc *cs = p;
+ if (!DESC_LENGTH_CHECK(cs, proto))
+ return false;
return GET_VAL(cs, proto, bClockID) == id;
}
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 568099467dbb..a29f28eb7d0c 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -403,10 +403,15 @@ static int prepare_inbound_urb(struct snd_usb_endpoint *ep,
static void notify_xrun(struct snd_usb_endpoint *ep)
{
struct snd_usb_substream *data_subs;
+ struct snd_pcm_substream *psubs;
data_subs = READ_ONCE(ep->data_subs);
- if (data_subs && data_subs->pcm_substream)
- snd_pcm_stop_xrun(data_subs->pcm_substream);
+ if (!data_subs)
+ return;
+ psubs = data_subs->pcm_substream;
+ if (psubs && psubs->runtime &&
+ psubs->runtime->state == SNDRV_PCM_STATE_RUNNING)
+ snd_pcm_stop_xrun(psubs);
}
static struct snd_usb_packet_info *
@@ -562,7 +567,10 @@ static void snd_complete_urb(struct urb *urb)
push_back_to_ready_list(ep, ctx);
clear_bit(ctx->index, &ep->active_mask);
snd_usb_queue_pending_output_urbs(ep, false);
- atomic_dec(&ep->submitted_urbs); /* decrement at last */
+ /* decrement at last, and check xrun */
+ if (atomic_dec_and_test(&ep->submitted_urbs) &&
+ !snd_usb_endpoint_implicit_feedback_sink(ep))
+ notify_xrun(ep);
return;
}
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 0cbf1d4fbe6e..6049d957694c 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -60,6 +60,8 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL;
/* flag potentially raw DSD capable altsettings */
fp->dsd_raw = true;
+ /* clear special format bit to avoid "unsupported format" msg below */
+ format &= ~UAC2_FORMAT_TYPE_I_RAW_DATA;
}
format <<= 1;
@@ -71,8 +73,11 @@ static u64 parse_audio_format_i_type(struct snd_usb_audio *chip,
sample_width = as->bBitResolution;
sample_bytes = as->bSubslotSize;
- if (format & UAC3_FORMAT_TYPE_I_RAW_DATA)
+ if (format & UAC3_FORMAT_TYPE_I_RAW_DATA) {
pcm_formats |= SNDRV_PCM_FMTBIT_SPECIAL;
+ /* clear special format bit to avoid "unsupported format" msg below */
+ format &= ~UAC3_FORMAT_TYPE_I_RAW_DATA;
+ }
format <<= 1;
break;
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index 23260aa1919d..0e9b5431a47f 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -621,6 +621,16 @@ static const struct usbmix_ctl_map usbmix_ctl_maps[] = {
.id = USB_ID(0x1b1c, 0x0a42),
.map = corsair_virtuoso_map,
},
+ {
+ /* Corsair HS80 RGB Wireless (wired mode) */
+ .id = USB_ID(0x1b1c, 0x0a6a),
+ .map = corsair_virtuoso_map,
+ },
+ {
+ /* Corsair HS80 RGB Wireless (wireless mode) */
+ .id = USB_ID(0x1b1c, 0x0a6b),
+ .map = corsair_virtuoso_map,
+ },
{ /* Gigabyte TRX40 Aorus Master (rear panel + front mic) */
.id = USB_ID(0x0414, 0xa001),
.map = aorus_master_alc1220vb_map,
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 8bbf070b3676..23fcd680167d 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -4116,6 +4116,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
err = snd_bbfpro_controls_create(mixer);
break;
case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */
+ case USB_ID(0x2a39, 0x3fa0): /* RME Digiface USB (alternate) */
err = snd_rme_digiface_controls_create(mixer);
break;
case USB_ID(0x2b73, 0x0017): /* Pioneer DJ DJM-250MK2 */
diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c
index 6eb7d93b358d..20ac32635f1f 100644
--- a/sound/usb/mixer_us16x08.c
+++ b/sound/usb/mixer_us16x08.c
@@ -687,7 +687,7 @@ static int snd_us16x08_meter_get(struct snd_kcontrol *kcontrol,
struct usb_mixer_elem_info *elem = kcontrol->private_data;
struct snd_usb_audio *chip = elem->head.mixer->chip;
struct snd_us16x08_meter_store *store = elem->private_data;
- u8 meter_urb[64];
+ u8 meter_urb[64] = {0};
switch (kcontrol->private_value) {
case 0: {
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index c49383e64678..8954be23325c 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -3673,176 +3673,181 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
}
},
-{
- /* Only claim interface 0 */
- .match_flags = USB_DEVICE_ID_MATCH_VENDOR |
- USB_DEVICE_ID_MATCH_PRODUCT |
- USB_DEVICE_ID_MATCH_INT_CLASS |
- USB_DEVICE_ID_MATCH_INT_NUMBER,
- .idVendor = 0x2a39,
- .idProduct = 0x3f8c,
- .bInterfaceClass = USB_CLASS_VENDOR_SPEC,
- .bInterfaceNumber = 0,
- QUIRK_DRIVER_INFO {
- QUIRK_DATA_COMPOSITE {
+#define QUIRK_RME_DIGIFACE(pid) \
+{ \
+ /* Only claim interface 0 */ \
+ .match_flags = USB_DEVICE_ID_MATCH_VENDOR | \
+ USB_DEVICE_ID_MATCH_PRODUCT | \
+ USB_DEVICE_ID_MATCH_INT_CLASS | \
+ USB_DEVICE_ID_MATCH_INT_NUMBER, \
+ .idVendor = 0x2a39, \
+ .idProduct = pid, \
+ .bInterfaceClass = USB_CLASS_VENDOR_SPEC, \
+ .bInterfaceNumber = 0, \
+ QUIRK_DRIVER_INFO { \
+ QUIRK_DATA_COMPOSITE { \
/*
* Three modes depending on sample rate band,
* with different channel counts for in/out
- */
- { QUIRK_DATA_STANDARD_MIXER(0) },
- {
- QUIRK_DATA_AUDIOFORMAT(0) {
- .formats = SNDRV_PCM_FMTBIT_S32_LE,
- .channels = 34, // outputs
- .fmt_bits = 24,
- .iface = 0,
- .altsetting = 1,
- .altset_idx = 1,
- .endpoint = 0x02,
- .ep_idx = 1,
- .ep_attr = USB_ENDPOINT_XFER_ISOC |
- USB_ENDPOINT_SYNC_ASYNC,
- .rates = SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000,
- .rate_min = 32000,
- .rate_max = 48000,
- .nr_rates = 3,
- .rate_table = (unsigned int[]) {
- 32000, 44100, 48000,
- },
- .sync_ep = 0x81,
- .sync_iface = 0,
- .sync_altsetting = 1,
- .sync_ep_idx = 0,
- .implicit_fb = 1,
- },
- },
- {
- QUIRK_DATA_AUDIOFORMAT(0) {
- .formats = SNDRV_PCM_FMTBIT_S32_LE,
- .channels = 18, // outputs
- .fmt_bits = 24,
- .iface = 0,
- .altsetting = 1,
- .altset_idx = 1,
- .endpoint = 0x02,
- .ep_idx = 1,
- .ep_attr = USB_ENDPOINT_XFER_ISOC |
- USB_ENDPOINT_SYNC_ASYNC,
- .rates = SNDRV_PCM_RATE_64000 |
- SNDRV_PCM_RATE_88200 |
- SNDRV_PCM_RATE_96000,
- .rate_min = 64000,
- .rate_max = 96000,
- .nr_rates = 3,
- .rate_table = (unsigned int[]) {
- 64000, 88200, 96000,
- },
- .sync_ep = 0x81,
- .sync_iface = 0,
- .sync_altsetting = 1,
- .sync_ep_idx = 0,
- .implicit_fb = 1,
- },
- },
- {
- QUIRK_DATA_AUDIOFORMAT(0) {
- .formats = SNDRV_PCM_FMTBIT_S32_LE,
- .channels = 10, // outputs
- .fmt_bits = 24,
- .iface = 0,
- .altsetting = 1,
- .altset_idx = 1,
- .endpoint = 0x02,
- .ep_idx = 1,
- .ep_attr = USB_ENDPOINT_XFER_ISOC |
- USB_ENDPOINT_SYNC_ASYNC,
- .rates = SNDRV_PCM_RATE_KNOT |
- SNDRV_PCM_RATE_176400 |
- SNDRV_PCM_RATE_192000,
- .rate_min = 128000,
- .rate_max = 192000,
- .nr_rates = 3,
- .rate_table = (unsigned int[]) {
- 128000, 176400, 192000,
- },
- .sync_ep = 0x81,
- .sync_iface = 0,
- .sync_altsetting = 1,
- .sync_ep_idx = 0,
- .implicit_fb = 1,
- },
- },
- {
- QUIRK_DATA_AUDIOFORMAT(0) {
- .formats = SNDRV_PCM_FMTBIT_S32_LE,
- .channels = 32, // inputs
- .fmt_bits = 24,
- .iface = 0,
- .altsetting = 1,
- .altset_idx = 1,
- .endpoint = 0x81,
- .ep_attr = USB_ENDPOINT_XFER_ISOC |
- USB_ENDPOINT_SYNC_ASYNC,
- .rates = SNDRV_PCM_RATE_32000 |
- SNDRV_PCM_RATE_44100 |
- SNDRV_PCM_RATE_48000,
- .rate_min = 32000,
- .rate_max = 48000,
- .nr_rates = 3,
- .rate_table = (unsigned int[]) {
- 32000, 44100, 48000,
- }
- }
- },
- {
- QUIRK_DATA_AUDIOFORMAT(0) {
- .formats = SNDRV_PCM_FMTBIT_S32_LE,
- .channels = 16, // inputs
- .fmt_bits = 24,
- .iface = 0,
- .altsetting = 1,
- .altset_idx = 1,
- .endpoint = 0x81,
- .ep_attr = USB_ENDPOINT_XFER_ISOC |
- USB_ENDPOINT_SYNC_ASYNC,
- .rates = SNDRV_PCM_RATE_64000 |
- SNDRV_PCM_RATE_88200 |
- SNDRV_PCM_RATE_96000,
- .rate_min = 64000,
- .rate_max = 96000,
- .nr_rates = 3,
- .rate_table = (unsigned int[]) {
- 64000, 88200, 96000,
- }
- }
- },
- {
- QUIRK_DATA_AUDIOFORMAT(0) {
- .formats = SNDRV_PCM_FMTBIT_S32_LE,
- .channels = 8, // inputs
- .fmt_bits = 24,
- .iface = 0,
- .altsetting = 1,
- .altset_idx = 1,
- .endpoint = 0x81,
- .ep_attr = USB_ENDPOINT_XFER_ISOC |
- USB_ENDPOINT_SYNC_ASYNC,
- .rates = SNDRV_PCM_RATE_KNOT |
- SNDRV_PCM_RATE_176400 |
- SNDRV_PCM_RATE_192000,
- .rate_min = 128000,
- .rate_max = 192000,
- .nr_rates = 3,
- .rate_table = (unsigned int[]) {
- 128000, 176400, 192000,
- }
- }
- },
- QUIRK_COMPOSITE_END
- }
- }
-},
+ */ \
+ { QUIRK_DATA_STANDARD_MIXER(0) }, \
+ { \
+ QUIRK_DATA_AUDIOFORMAT(0) { \
+ .formats = SNDRV_PCM_FMTBIT_S32_LE, \
+ .channels = 34, /* outputs */ \
+ .fmt_bits = 24, \
+ .iface = 0, \
+ .altsetting = 1, \
+ .altset_idx = 1, \
+ .endpoint = 0x02, \
+ .ep_idx = 1, \
+ .ep_attr = USB_ENDPOINT_XFER_ISOC | \
+ USB_ENDPOINT_SYNC_ASYNC, \
+ .rates = SNDRV_PCM_RATE_32000 | \
+ SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000, \
+ .rate_min = 32000, \
+ .rate_max = 48000, \
+ .nr_rates = 3, \
+ .rate_table = (unsigned int[]) { \
+ 32000, 44100, 48000, \
+ }, \
+ .sync_ep = 0x81, \
+ .sync_iface = 0, \
+ .sync_altsetting = 1, \
+ .sync_ep_idx = 0, \
+ .implicit_fb = 1, \
+ }, \
+ }, \
+ { \
+ QUIRK_DATA_AUDIOFORMAT(0) { \
+ .formats = SNDRV_PCM_FMTBIT_S32_LE, \
+ .channels = 18, /* outputs */ \
+ .fmt_bits = 24, \
+ .iface = 0, \
+ .altsetting = 1, \
+ .altset_idx = 1, \
+ .endpoint = 0x02, \
+ .ep_idx = 1, \
+ .ep_attr = USB_ENDPOINT_XFER_ISOC | \
+ USB_ENDPOINT_SYNC_ASYNC, \
+ .rates = SNDRV_PCM_RATE_64000 | \
+ SNDRV_PCM_RATE_88200 | \
+ SNDRV_PCM_RATE_96000, \
+ .rate_min = 64000, \
+ .rate_max = 96000, \
+ .nr_rates = 3, \
+ .rate_table = (unsigned int[]) { \
+ 64000, 88200, 96000, \
+ }, \
+ .sync_ep = 0x81, \
+ .sync_iface = 0, \
+ .sync_altsetting = 1, \
+ .sync_ep_idx = 0, \
+ .implicit_fb = 1, \
+ }, \
+ }, \
+ { \
+ QUIRK_DATA_AUDIOFORMAT(0) { \
+ .formats = SNDRV_PCM_FMTBIT_S32_LE, \
+ .channels = 10, /* outputs */ \
+ .fmt_bits = 24, \
+ .iface = 0, \
+ .altsetting = 1, \
+ .altset_idx = 1, \
+ .endpoint = 0x02, \
+ .ep_idx = 1, \
+ .ep_attr = USB_ENDPOINT_XFER_ISOC | \
+ USB_ENDPOINT_SYNC_ASYNC, \
+ .rates = SNDRV_PCM_RATE_KNOT | \
+ SNDRV_PCM_RATE_176400 | \
+ SNDRV_PCM_RATE_192000, \
+ .rate_min = 128000, \
+ .rate_max = 192000, \
+ .nr_rates = 3, \
+ .rate_table = (unsigned int[]) { \
+ 128000, 176400, 192000, \
+ }, \
+ .sync_ep = 0x81, \
+ .sync_iface = 0, \
+ .sync_altsetting = 1, \
+ .sync_ep_idx = 0, \
+ .implicit_fb = 1, \
+ }, \
+ }, \
+ { \
+ QUIRK_DATA_AUDIOFORMAT(0) { \
+ .formats = SNDRV_PCM_FMTBIT_S32_LE, \
+ .channels = 32, /* inputs */ \
+ .fmt_bits = 24, \
+ .iface = 0, \
+ .altsetting = 1, \
+ .altset_idx = 1, \
+ .endpoint = 0x81, \
+ .ep_attr = USB_ENDPOINT_XFER_ISOC | \
+ USB_ENDPOINT_SYNC_ASYNC, \
+ .rates = SNDRV_PCM_RATE_32000 | \
+ SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000, \
+ .rate_min = 32000, \
+ .rate_max = 48000, \
+ .nr_rates = 3, \
+ .rate_table = (unsigned int[]) { \
+ 32000, 44100, 48000, \
+ } \
+ } \
+ }, \
+ { \
+ QUIRK_DATA_AUDIOFORMAT(0) { \
+ .formats = SNDRV_PCM_FMTBIT_S32_LE, \
+ .channels = 16, /* inputs */ \
+ .fmt_bits = 24, \
+ .iface = 0, \
+ .altsetting = 1, \
+ .altset_idx = 1, \
+ .endpoint = 0x81, \
+ .ep_attr = USB_ENDPOINT_XFER_ISOC | \
+ USB_ENDPOINT_SYNC_ASYNC, \
+ .rates = SNDRV_PCM_RATE_64000 | \
+ SNDRV_PCM_RATE_88200 | \
+ SNDRV_PCM_RATE_96000, \
+ .rate_min = 64000, \
+ .rate_max = 96000, \
+ .nr_rates = 3, \
+ .rate_table = (unsigned int[]) { \
+ 64000, 88200, 96000, \
+ } \
+ } \
+ }, \
+ { \
+ QUIRK_DATA_AUDIOFORMAT(0) { \
+ .formats = SNDRV_PCM_FMTBIT_S32_LE, \
+ .channels = 8, /* inputs */ \
+ .fmt_bits = 24, \
+ .iface = 0, \
+ .altsetting = 1, \
+ .altset_idx = 1, \
+ .endpoint = 0x81, \
+ .ep_attr = USB_ENDPOINT_XFER_ISOC | \
+ USB_ENDPOINT_SYNC_ASYNC, \
+ .rates = SNDRV_PCM_RATE_KNOT | \
+ SNDRV_PCM_RATE_176400 | \
+ SNDRV_PCM_RATE_192000, \
+ .rate_min = 128000, \
+ .rate_max = 192000, \
+ .nr_rates = 3, \
+ .rate_table = (unsigned int[]) { \
+ 128000, 176400, 192000, \
+ } \
+ } \
+ }, \
+ QUIRK_COMPOSITE_END \
+ } \
+ } \
+}
+
+QUIRK_RME_DIGIFACE(0x3f8c),
+QUIRK_RME_DIGIFACE(0x3fa0),
+
#undef USB_DEVICE_VENDOR_SPEC
#undef USB_AUDIO_DEVICE
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index cbfbb064a9c2..8ba0aff8be2e 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -555,6 +555,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interface *intf)
{
struct usb_host_config *config = dev->actconfig;
+ struct usb_device_descriptor *new_device_descriptor __free(kfree) = NULL;
int err;
if (le16_to_cpu(get_cfg_desc(config)->wTotalLength) == EXTIGY_FIRMWARE_SIZE_OLD ||
@@ -565,11 +566,19 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
0x10, 0x43, 0x0001, 0x000a, NULL, 0);
if (err < 0)
dev_dbg(&dev->dev, "error sending boot message: %d\n", err);
+
+ new_device_descriptor = kmalloc(sizeof(*new_device_descriptor), GFP_KERNEL);
+ if (!new_device_descriptor)
+ return -ENOMEM;
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
- &dev->descriptor, sizeof(dev->descriptor));
- config = dev->actconfig;
+ new_device_descriptor, sizeof(*new_device_descriptor));
if (err < 0)
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
+ if (new_device_descriptor->bNumConfigurations > dev->descriptor.bNumConfigurations)
+ dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n",
+ new_device_descriptor->bNumConfigurations);
+ else
+ memcpy(&dev->descriptor, new_device_descriptor, sizeof(dev->descriptor));
err = usb_reset_configuration(dev);
if (err < 0)
dev_dbg(&dev->dev, "error usb_reset_configuration: %d\n", err);
@@ -901,6 +910,7 @@ static void mbox2_setup_48_24_magic(struct usb_device *dev)
static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
{
struct usb_host_config *config = dev->actconfig;
+ struct usb_device_descriptor *new_device_descriptor __free(kfree) = NULL;
int err;
u8 bootresponse[0x12];
int fwsize;
@@ -935,11 +945,19 @@ static int snd_usb_mbox2_boot_quirk(struct usb_device *dev)
dev_dbg(&dev->dev, "device initialised!\n");
+ new_device_descriptor = kmalloc(sizeof(*new_device_descriptor), GFP_KERNEL);
+ if (!new_device_descriptor)
+ return -ENOMEM;
+
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
- &dev->descriptor, sizeof(dev->descriptor));
- config = dev->actconfig;
+ new_device_descriptor, sizeof(*new_device_descriptor));
if (err < 0)
dev_dbg(&dev->dev, "error usb_get_descriptor: %d\n", err);
+ if (new_device_descriptor->bNumConfigurations > dev->descriptor.bNumConfigurations)
+ dev_dbg(&dev->dev, "error too large bNumConfigurations: %d\n",
+ new_device_descriptor->bNumConfigurations);
+ else
+ memcpy(&dev->descriptor, new_device_descriptor, sizeof(dev->descriptor));
err = usb_reset_configuration(dev);
if (err < 0)
@@ -1249,6 +1267,7 @@ static void mbox3_setup_defaults(struct usb_device *dev)
static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
{
struct usb_host_config *config = dev->actconfig;
+ struct usb_device_descriptor *new_device_descriptor __free(kfree) = NULL;
int err;
int descriptor_size;
@@ -1261,11 +1280,19 @@ static int snd_usb_mbox3_boot_quirk(struct usb_device *dev)
dev_dbg(&dev->dev, "MBOX3: device initialised!\n");
+ new_device_descriptor = kmalloc(sizeof(*new_device_descriptor), GFP_KERNEL);
+ if (!new_device_descriptor)
+ return -ENOMEM;
+
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
- &dev->descriptor, sizeof(dev->descriptor));
- config = dev->actconfig;
+ new_device_descriptor, sizeof(*new_device_descriptor));
if (err < 0)
dev_dbg(&dev->dev, "MBOX3: error usb_get_descriptor: %d\n", err);
+ if (new_device_descriptor->bNumConfigurations > dev->descriptor.bNumConfigurations)
+ dev_dbg(&dev->dev, "MBOX3: error too large bNumConfigurations: %d\n",
+ new_device_descriptor->bNumConfigurations);
+ else
+ memcpy(&dev->descriptor, new_device_descriptor, sizeof(dev->descriptor));
err = usb_reset_configuration(dev);
if (err < 0)
@@ -1638,6 +1665,7 @@ int snd_usb_apply_boot_quirk(struct usb_device *dev,
return snd_usb_motu_microbookii_boot_quirk(dev);
break;
case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */
+ case USB_ID(0x2a39, 0x3fa0): /* RME Digiface USB (alternate) */
return snd_usb_rme_digiface_boot_quirk(dev);
}
@@ -1851,6 +1879,7 @@ void snd_usb_set_format_quirk(struct snd_usb_substream *subs,
mbox3_set_format_quirk(subs, fmt); /* Digidesign Mbox 3 */
break;
case USB_ID(0x2a39, 0x3f8c): /* RME Digiface USB */
+ case USB_ID(0x2a39, 0x3fa0): /* RME Digiface USB (alternate) */
rme_digiface_set_format_quirk(subs);
break;
}
@@ -2150,6 +2179,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_MIC_RES_384),
DEVICE_FLG(0x046d, 0x09a4, /* Logitech QuickCam E 3500 */
QUIRK_FLAG_CTL_MSG_DELAY_1M | QUIRK_FLAG_IGNORE_CTL_ERROR),
+ DEVICE_FLG(0x0499, 0x1506, /* Yamaha THR5 */
+ QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x0499, 0x1509, /* Steinberg UR22 */
QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x0499, 0x3108, /* Yamaha YIT-W12TX */
@@ -2294,6 +2325,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_DSD_RAW),
DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */
QUIRK_FLAG_SET_IFACE_FIRST),
+ DEVICE_FLG(0x262a, 0x9302, /* ddHiFi TC44C */
+ QUIRK_FLAG_DSD_RAW),
DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x2912, 0x30c8, /* Audioengine D1 */
diff --git a/tools/arch/arm64/include/uapi/asm/kvm.h b/tools/arch/arm64/include/uapi/asm/kvm.h
index 964df31da975..66736ff04011 100644
--- a/tools/arch/arm64/include/uapi/asm/kvm.h
+++ b/tools/arch/arm64/include/uapi/asm/kvm.h
@@ -484,6 +484,12 @@ enum {
*/
#define KVM_SYSTEM_EVENT_RESET_FLAG_PSCI_RESET2 (1ULL << 0)
+/*
+ * Shutdown caused by a PSCI v1.3 SYSTEM_OFF2 call.
+ * Valid only when the system event has a type of KVM_SYSTEM_EVENT_SHUTDOWN.
+ */
+#define KVM_SYSTEM_EVENT_SHUTDOWN_FLAG_PSCI_OFF2 (1ULL << 0)
+
/* run->fail_entry.hardware_entry_failure_reason codes. */
#define KVM_EXIT_FAIL_ENTRY_CPU_UNSUPPORTED (1ULL << 0)
diff --git a/tools/arch/x86/include/asm/cpufeatures.h b/tools/arch/x86/include/asm/cpufeatures.h
index 23698d0f4bb4..17b6590748c0 100644
--- a/tools/arch/x86/include/asm/cpufeatures.h
+++ b/tools/arch/x86/include/asm/cpufeatures.h
@@ -215,7 +215,7 @@
#define X86_FEATURE_SPEC_STORE_BYPASS_DISABLE ( 7*32+23) /* Disable Speculative Store Bypass. */
#define X86_FEATURE_LS_CFG_SSBD ( 7*32+24) /* AMD SSBD implementation via LS_CFG MSR */
#define X86_FEATURE_IBRS ( 7*32+25) /* "ibrs" Indirect Branch Restricted Speculation */
-#define X86_FEATURE_IBPB ( 7*32+26) /* "ibpb" Indirect Branch Prediction Barrier */
+#define X86_FEATURE_IBPB ( 7*32+26) /* "ibpb" Indirect Branch Prediction Barrier without a guaranteed RSB flush */
#define X86_FEATURE_STIBP ( 7*32+27) /* "stibp" Single Thread Indirect Branch Predictors */
#define X86_FEATURE_ZEN ( 7*32+28) /* Generic flag for all Zen and newer */
#define X86_FEATURE_L1TF_PTEINV ( 7*32+29) /* L1TF workaround PTE inversion */
@@ -317,6 +317,9 @@
#define X86_FEATURE_ZEN1 (11*32+31) /* CPU based on Zen1 microarchitecture */
/* Intel-defined CPU features, CPUID level 0x00000007:1 (EAX), word 12 */
+#define X86_FEATURE_SHA512 (12*32+ 0) /* SHA512 instructions */
+#define X86_FEATURE_SM3 (12*32+ 1) /* SM3 instructions */
+#define X86_FEATURE_SM4 (12*32+ 2) /* SM4 instructions */
#define X86_FEATURE_AVX_VNNI (12*32+ 4) /* "avx_vnni" AVX VNNI instructions */
#define X86_FEATURE_AVX512_BF16 (12*32+ 5) /* "avx512_bf16" AVX512 BFLOAT16 instructions */
#define X86_FEATURE_CMPCCXADD (12*32+ 7) /* CMPccXADD instructions */
@@ -348,6 +351,7 @@
#define X86_FEATURE_CPPC (13*32+27) /* "cppc" Collaborative Processor Performance Control */
#define X86_FEATURE_AMD_PSFD (13*32+28) /* Predictive Store Forwarding Disable */
#define X86_FEATURE_BTC_NO (13*32+29) /* Not vulnerable to Branch Type Confusion */
+#define X86_FEATURE_AMD_IBPB_RET (13*32+30) /* IBPB clears return address predictor */
#define X86_FEATURE_BRS (13*32+31) /* "brs" Branch Sampling available */
/* Thermal and Power Management Leaf, CPUID level 0x00000006 (EAX), word 14 */
@@ -472,7 +476,9 @@
#define X86_FEATURE_BHI_CTRL (21*32+ 2) /* BHI_DIS_S HW control available */
#define X86_FEATURE_CLEAR_BHB_HW (21*32+ 3) /* BHI_DIS_S HW control enabled */
#define X86_FEATURE_CLEAR_BHB_LOOP_ON_VMEXIT (21*32+ 4) /* Clear branch history at vmexit using SW loop */
-#define X86_FEATURE_AMD_FAST_CPPC (21*32 + 5) /* AMD Fast CPPC */
+#define X86_FEATURE_AMD_FAST_CPPC (21*32 + 5) /* Fast CPPC */
+#define X86_FEATURE_AMD_HETEROGENEOUS_CORES (21*32 + 6) /* Heterogeneous Core Topology */
+#define X86_FEATURE_AMD_WORKLOAD_CLASS (21*32 + 7) /* Workload Classification */
/*
* BUG word(s)
@@ -523,4 +529,5 @@
#define X86_BUG_DIV0 X86_BUG(1*32 + 1) /* "div0" AMD DIV0 speculation bug */
#define X86_BUG_RFDS X86_BUG(1*32 + 2) /* "rfds" CPU is vulnerable to Register File Data Sampling */
#define X86_BUG_BHI X86_BUG(1*32 + 3) /* "bhi" CPU is affected by Branch History Injection */
+#define X86_BUG_IBPB_NO_RET X86_BUG(1*32 + 4) /* "ibpb_no_ret" IBPB omits return target predictions */
#endif /* _ASM_X86_CPUFEATURES_H */
diff --git a/tools/arch/x86/include/uapi/asm/kvm.h b/tools/arch/x86/include/uapi/asm/kvm.h
index a8debbf2f702..88585c1de416 100644
--- a/tools/arch/x86/include/uapi/asm/kvm.h
+++ b/tools/arch/x86/include/uapi/asm/kvm.h
@@ -440,6 +440,7 @@ struct kvm_sync_regs {
#define KVM_X86_QUIRK_FIX_HYPERCALL_INSN (1 << 5)
#define KVM_X86_QUIRK_MWAIT_NEVER_UD_FAULTS (1 << 6)
#define KVM_X86_QUIRK_SLOT_ZAP_ALL (1 << 7)
+#define KVM_X86_QUIRK_STUFF_FEATURE_MSRS (1 << 8)
#define KVM_STATE_NESTED_FORMAT_VMX 0
#define KVM_STATE_NESTED_FORMAT_SVM 1
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index 2ff949ea82fa..e71be67f1d86 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -822,11 +822,18 @@ prog_dump(struct bpf_prog_info *info, enum dump_mode mode,
printf("%s:\n", sym_name);
}
- if (disasm_print_insn(img, lens[i], opcodes,
- name, disasm_opt, btf,
- prog_linfo, ksyms[i], i,
- linum))
- goto exit_free;
+ if (ksyms) {
+ if (disasm_print_insn(img, lens[i], opcodes,
+ name, disasm_opt, btf,
+ prog_linfo, ksyms[i], i,
+ linum))
+ goto exit_free;
+ } else {
+ if (disasm_print_insn(img, lens[i], opcodes,
+ name, disasm_opt, btf,
+ NULL, 0, 0, false))
+ goto exit_free;
+ }
img += lens[i];
diff --git a/tools/hv/.gitignore b/tools/hv/.gitignore
new file mode 100644
index 000000000000..0c5bc15d602f
--- /dev/null
+++ b/tools/hv/.gitignore
@@ -0,0 +1,3 @@
+hv_fcopy_uio_daemon
+hv_kvp_daemon
+hv_vss_daemon
diff --git a/tools/hv/hv_fcopy_uio_daemon.c b/tools/hv/hv_fcopy_uio_daemon.c
index 7a00f3066a98..0198321d14a2 100644
--- a/tools/hv/hv_fcopy_uio_daemon.c
+++ b/tools/hv/hv_fcopy_uio_daemon.c
@@ -35,8 +35,6 @@
#define WIN8_SRV_MINOR 1
#define WIN8_SRV_VERSION (WIN8_SRV_MAJOR << 16 | WIN8_SRV_MINOR)
-#define MAX_FOLDER_NAME 15
-#define MAX_PATH_LEN 15
#define FCOPY_UIO "/sys/bus/vmbus/devices/eb765408-105f-49b6-b4aa-c123b64d17d4/uio"
#define FCOPY_VER_COUNT 1
@@ -51,7 +49,7 @@ static const int fw_versions[] = {
#define HV_RING_SIZE 0x4000 /* 16KB ring buffer size */
-unsigned char desc[HV_RING_SIZE];
+static unsigned char desc[HV_RING_SIZE];
static int target_fd;
static char target_fname[PATH_MAX];
@@ -409,8 +407,8 @@ int main(int argc, char *argv[])
struct vmbus_br txbr, rxbr;
void *ring;
uint32_t len = HV_RING_SIZE;
- char uio_name[MAX_FOLDER_NAME] = {0};
- char uio_dev_path[MAX_PATH_LEN] = {0};
+ char uio_name[NAME_MAX] = {0};
+ char uio_dev_path[PATH_MAX] = {0};
static struct option long_options[] = {
{"help", no_argument, 0, 'h' },
@@ -468,8 +466,10 @@ int main(int argc, char *argv[])
*/
ret = pread(fcopy_fd, &tmp, sizeof(int), 0);
if (ret < 0) {
+ if (errno == EINTR || errno == EAGAIN)
+ continue;
syslog(LOG_ERR, "pread failed: %s", strerror(errno));
- continue;
+ goto close;
}
len = HV_RING_SIZE;
diff --git a/tools/hv/hv_get_dns_info.sh b/tools/hv/hv_get_dns_info.sh
index 058c17b46ffc..268521234d4b 100755
--- a/tools/hv/hv_get_dns_info.sh
+++ b/tools/hv/hv_get_dns_info.sh
@@ -1,4 +1,4 @@
-#!/bin/bash
+#!/bin/sh
# This example script parses /etc/resolv.conf to retrive DNS information.
# In the interest of keeping the KVP daemon code free of distro specific
@@ -10,4 +10,4 @@
# this script can be based on the Network Manager APIs for retrieving DNS
# entries.
-cat /etc/resolv.conf 2>/dev/null | awk '/^nameserver/ { print $2 }'
+exec awk '/^nameserver/ { print $2 }' /etc/resolv.conf 2>/dev/null
diff --git a/tools/hv/hv_kvp_daemon.c b/tools/hv/hv_kvp_daemon.c
index ae57bf69ad4a..04ba035d67e9 100644
--- a/tools/hv/hv_kvp_daemon.c
+++ b/tools/hv/hv_kvp_daemon.c
@@ -725,7 +725,7 @@ static void kvp_get_ipconfig_info(char *if_name,
* .
*/
- sprintf(cmd, KVP_SCRIPTS_PATH "%s", "hv_get_dns_info");
+ sprintf(cmd, "exec %s %s", KVP_SCRIPTS_PATH "hv_get_dns_info", if_name);
/*
* Execute the command to gather DNS info.
@@ -742,7 +742,7 @@ static void kvp_get_ipconfig_info(char *if_name,
* Enabled: DHCP enabled.
*/
- sprintf(cmd, KVP_SCRIPTS_PATH "%s %s", "hv_get_dhcp_info", if_name);
+ sprintf(cmd, "exec %s %s", KVP_SCRIPTS_PATH "hv_get_dhcp_info", if_name);
file = popen(cmd, "r");
if (file == NULL)
@@ -1606,8 +1606,9 @@ static int kvp_set_ip_info(char *if_name, struct hv_kvp_ipaddr_value *new_val)
* invoke the external script to do its magic.
*/
- str_len = snprintf(cmd, sizeof(cmd), KVP_SCRIPTS_PATH "%s %s %s",
- "hv_set_ifconfig", if_filename, nm_filename);
+ str_len = snprintf(cmd, sizeof(cmd), "exec %s %s %s",
+ KVP_SCRIPTS_PATH "hv_set_ifconfig",
+ if_filename, nm_filename);
/*
* This is a little overcautious, but it's necessary to suppress some
* false warnings from gcc 8.0.1.
diff --git a/tools/hv/hv_set_ifconfig.sh b/tools/hv/hv_set_ifconfig.sh
index 440a91b35823..2f8baed2b8f7 100755
--- a/tools/hv/hv_set_ifconfig.sh
+++ b/tools/hv/hv_set_ifconfig.sh
@@ -81,7 +81,7 @@ echo "ONBOOT=yes" >> $1
cp $1 /etc/sysconfig/network-scripts/
-chmod 600 $2
+umask 0177
interface=$(echo $2 | awk -F - '{ print $2 }')
filename="${2##*/}"
diff --git a/tools/iio/iio_event_monitor.c b/tools/iio/iio_event_monitor.c
index 8073c9e4fe46..cccf62ea2b8f 100644
--- a/tools/iio/iio_event_monitor.c
+++ b/tools/iio/iio_event_monitor.c
@@ -63,6 +63,7 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_DELTA_VELOCITY] = "deltavelocity",
[IIO_COLORTEMP] = "colortemp",
[IIO_CHROMATICITY] = "chromaticity",
+ [IIO_ATTENTION] = "attention",
};
static const char * const iio_ev_type_text[] = {
@@ -183,6 +184,7 @@ static bool event_is_known(struct iio_event_data *event)
case IIO_DELTA_VELOCITY:
case IIO_COLORTEMP:
case IIO_CHROMATICITY:
+ case IIO_ATTENTION:
break;
default:
return false;
@@ -449,6 +451,7 @@ error_free_chrdev_name:
enable_events(dev_dir_name, 0);
free(chrdev_name);
+ free(dev_dir_name);
return ret;
}
diff --git a/tools/include/uapi/asm-generic/mman.h b/tools/include/uapi/asm-generic/mman.h
index 406f7718f9ad..51d2556af54a 100644
--- a/tools/include/uapi/asm-generic/mman.h
+++ b/tools/include/uapi/asm-generic/mman.h
@@ -19,4 +19,8 @@
#define MCL_FUTURE 2 /* lock all future mappings */
#define MCL_ONFAULT 4 /* lock all pages that are faulted in */
+#define SHADOW_STACK_SET_TOKEN (1ULL << 0) /* Set up a restore token in the shadow stack */
+#define SHADOW_STACK_SET_MARKER (1ULL << 1) /* Set up a top of stack marker in the shadow stack */
+
+
#endif /* __ASM_GENERIC_MMAN_H */
diff --git a/tools/include/uapi/asm-generic/socket.h b/tools/include/uapi/asm-generic/socket.h
index 281df9139d2b..ffff554a5230 100644
--- a/tools/include/uapi/asm-generic/socket.h
+++ b/tools/include/uapi/asm-generic/socket.h
@@ -126,6 +126,8 @@
#define SCM_TS_OPT_ID 78
+#define SO_RCVPRIORITY 79
+
#if !defined(__KERNEL__)
#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
diff --git a/tools/include/uapi/asm-generic/unistd.h b/tools/include/uapi/asm-generic/unistd.h
index 5bf6148cac2b..88dc393c2bca 100644
--- a/tools/include/uapi/asm-generic/unistd.h
+++ b/tools/include/uapi/asm-generic/unistd.h
@@ -841,8 +841,17 @@ __SYSCALL(__NR_lsm_list_modules, sys_lsm_list_modules)
#define __NR_mseal 462
__SYSCALL(__NR_mseal, sys_mseal)
+#define __NR_setxattrat 463
+__SYSCALL(__NR_setxattrat, sys_setxattrat)
+#define __NR_getxattrat 464
+__SYSCALL(__NR_getxattrat, sys_getxattrat)
+#define __NR_listxattrat 465
+__SYSCALL(__NR_listxattrat, sys_listxattrat)
+#define __NR_removexattrat 466
+__SYSCALL(__NR_removexattrat, sys_removexattrat)
+
#undef __NR_syscalls
-#define __NR_syscalls 463
+#define __NR_syscalls 467
/*
* 32 bit systems traditionally used different
diff --git a/tools/include/uapi/drm/drm.h b/tools/include/uapi/drm/drm.h
index 16122819edfe..7fba37b94401 100644
--- a/tools/include/uapi/drm/drm.h
+++ b/tools/include/uapi/drm/drm.h
@@ -1024,6 +1024,13 @@ struct drm_crtc_queue_sequence {
__u64 user_data; /* user data passed to event */
};
+#define DRM_CLIENT_NAME_MAX_LEN 64
+struct drm_set_client_name {
+ __u64 name_len;
+ __u64 name;
+};
+
+
#if defined(__cplusplus)
}
#endif
@@ -1288,6 +1295,16 @@ extern "C" {
*/
#define DRM_IOCTL_MODE_CLOSEFB DRM_IOWR(0xD0, struct drm_mode_closefb)
+/**
+ * DRM_IOCTL_SET_CLIENT_NAME - Attach a name to a drm_file
+ *
+ * Having a name allows for easier tracking and debugging.
+ * The length of the name (without null ending char) must be
+ * <= DRM_CLIENT_NAME_MAX_LEN.
+ * The call will fail if the name contains whitespaces or non-printable chars.
+ */
+#define DRM_IOCTL_SET_CLIENT_NAME DRM_IOWR(0xD1, struct drm_set_client_name)
+
/*
* Device specific ioctls should only be in their respective headers
* The device specific ioctl range is from 0x40 to 0x9f.
diff --git a/tools/include/uapi/linux/if_link.h b/tools/include/uapi/linux/if_link.h
index 8516c1ccd57a..7e46ca4cd31b 100644
--- a/tools/include/uapi/linux/if_link.h
+++ b/tools/include/uapi/linux/if_link.h
@@ -1315,6 +1315,8 @@ enum {
IFLA_NETKIT_MODE,
IFLA_NETKIT_SCRUB,
IFLA_NETKIT_PEER_SCRUB,
+ IFLA_NETKIT_HEADROOM,
+ IFLA_NETKIT_TAILROOM,
__IFLA_NETKIT_MAX,
};
#define IFLA_NETKIT_MAX (__IFLA_NETKIT_MAX - 1)
diff --git a/tools/include/uapi/linux/kvm.h b/tools/include/uapi/linux/kvm.h
index 637efc055145..502ea63b5d2e 100644
--- a/tools/include/uapi/linux/kvm.h
+++ b/tools/include/uapi/linux/kvm.h
@@ -1158,7 +1158,15 @@ enum kvm_device_type {
#define KVM_DEV_TYPE_ARM_PV_TIME KVM_DEV_TYPE_ARM_PV_TIME
KVM_DEV_TYPE_RISCV_AIA,
#define KVM_DEV_TYPE_RISCV_AIA KVM_DEV_TYPE_RISCV_AIA
+ KVM_DEV_TYPE_LOONGARCH_IPI,
+#define KVM_DEV_TYPE_LOONGARCH_IPI KVM_DEV_TYPE_LOONGARCH_IPI
+ KVM_DEV_TYPE_LOONGARCH_EIOINTC,
+#define KVM_DEV_TYPE_LOONGARCH_EIOINTC KVM_DEV_TYPE_LOONGARCH_EIOINTC
+ KVM_DEV_TYPE_LOONGARCH_PCHPIC,
+#define KVM_DEV_TYPE_LOONGARCH_PCHPIC KVM_DEV_TYPE_LOONGARCH_PCHPIC
+
KVM_DEV_TYPE_MAX,
+
};
struct kvm_vfio_spapr_tce {
diff --git a/tools/include/uapi/linux/perf_event.h b/tools/include/uapi/linux/perf_event.h
index 4842c36fdf80..0524d541d4e3 100644
--- a/tools/include/uapi/linux/perf_event.h
+++ b/tools/include/uapi/linux/perf_event.h
@@ -511,7 +511,16 @@ struct perf_event_attr {
__u16 sample_max_stack;
__u16 __reserved_2;
__u32 aux_sample_size;
- __u32 __reserved_3;
+
+ union {
+ __u32 aux_action;
+ struct {
+ __u32 aux_start_paused : 1, /* start AUX area tracing paused */
+ aux_pause : 1, /* on overflow, pause AUX area tracing */
+ aux_resume : 1, /* on overflow, resume AUX area tracing */
+ __reserved_3 : 29;
+ };
+ };
/*
* User provided data if sigtrap=1, passed back to user via
diff --git a/tools/include/uapi/linux/stddef.h b/tools/include/uapi/linux/stddef.h
index bb6ea517efb5..c53cde425406 100644
--- a/tools/include/uapi/linux/stddef.h
+++ b/tools/include/uapi/linux/stddef.h
@@ -8,6 +8,13 @@
#define __always_inline __inline__
#endif
+/* Not all C++ standards support type declarations inside an anonymous union */
+#ifndef __cplusplus
+#define __struct_group_tag(TAG) TAG
+#else
+#define __struct_group_tag(TAG)
+#endif
+
/**
* __struct_group() - Create a mirrored named and anonyomous struct
*
@@ -20,14 +27,14 @@
* and size: one anonymous and one named. The former's members can be used
* normally without sub-struct naming, and the latter can be used to
* reason about the start, end, and size of the group of struct members.
- * The named struct can also be explicitly tagged for layer reuse, as well
- * as both having struct attributes appended.
+ * The named struct can also be explicitly tagged for layer reuse (C only),
+ * as well as both having struct attributes appended.
*/
#define __struct_group(TAG, NAME, ATTRS, MEMBERS...) \
union { \
struct { MEMBERS } ATTRS; \
- struct TAG { MEMBERS } ATTRS NAME; \
- }
+ struct __struct_group_tag(TAG) { MEMBERS } ATTRS NAME; \
+ } ATTRS
/**
* __DECLARE_FLEX_ARRAY() - Declare a flexible array usable in a union
diff --git a/tools/lib/perf/evlist.c b/tools/lib/perf/evlist.c
index c6d67fc9e57e..83c43dc13313 100644
--- a/tools/lib/perf/evlist.c
+++ b/tools/lib/perf/evlist.c
@@ -47,6 +47,20 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
*/
perf_cpu_map__put(evsel->cpus);
evsel->cpus = perf_cpu_map__intersect(evlist->user_requested_cpus, evsel->own_cpus);
+
+ /*
+ * Empty cpu lists would eventually get opened as "any" so remove
+ * genuinely empty ones before they're opened in the wrong place.
+ */
+ if (perf_cpu_map__is_empty(evsel->cpus)) {
+ struct perf_evsel *next = perf_evlist__next(evlist, evsel);
+
+ perf_evlist__remove(evlist, evsel);
+ /* Keep idx contiguous */
+ if (next)
+ list_for_each_entry_from(next, &evlist->entries, node)
+ next->idx--;
+ }
} else if (!evsel->own_cpus || evlist->has_user_cpus ||
(!evsel->requires_cpu && perf_cpu_map__has_any_cpu(evlist->user_requested_cpus))) {
/*
@@ -80,11 +94,11 @@ static void __perf_evlist__propagate_maps(struct perf_evlist *evlist,
static void perf_evlist__propagate_maps(struct perf_evlist *evlist)
{
- struct perf_evsel *evsel;
+ struct perf_evsel *evsel, *n;
evlist->needs_map_propagation = true;
- perf_evlist__for_each_evsel(evlist, evsel)
+ list_for_each_entry_safe(evsel, n, &evlist->entries, node)
__perf_evlist__propagate_maps(evlist, evsel);
}
diff --git a/tools/net/ynl/Makefile b/tools/net/ynl/Makefile
index d1cdf2a8f826..211df5a93ad9 100644
--- a/tools/net/ynl/Makefile
+++ b/tools/net/ynl/Makefile
@@ -1,5 +1,17 @@
# SPDX-License-Identifier: GPL-2.0
+include ../../scripts/Makefile.arch
+
+INSTALL ?= install
+prefix ?= /usr
+ifeq ($(LP64), 1)
+ libdir_relative = lib64
+else
+ libdir_relative = lib
+endif
+libdir ?= $(prefix)/$(libdir_relative)
+includedir ?= $(prefix)/include
+
SUBDIRS = lib generated samples
all: $(SUBDIRS) libynl.a
@@ -21,5 +33,20 @@ clean distclean:
fi \
done
rm -f libynl.a
+ rm -rf pyynl/__pycache__
+ rm -rf pyynl/lib/__pycache__
+ rm -rf pyynl.egg-info
+ rm -rf build
+
+install: libynl.a lib/*.h
+ @echo -e "\tINSTALL libynl.a"
+ @$(INSTALL) -d $(DESTDIR)$(libdir)
+ @$(INSTALL) -m 0644 libynl.a $(DESTDIR)$(libdir)/libynl.a
+ @echo -e "\tINSTALL libynl headers"
+ @$(INSTALL) -d $(DESTDIR)$(includedir)/ynl
+ @$(INSTALL) -m 0644 lib/*.h $(DESTDIR)$(includedir)/ynl/
+ @echo -e "\tINSTALL pyynl"
+ @pip install --prefix=$(DESTDIR)$(prefix) .
+ @make -C generated install
-.PHONY: all clean distclean $(SUBDIRS)
+.PHONY: all clean distclean install $(SUBDIRS)
diff --git a/tools/net/ynl/generated/.gitignore b/tools/net/ynl/generated/.gitignore
index ade488626d26..859a6fb446e1 100644
--- a/tools/net/ynl/generated/.gitignore
+++ b/tools/net/ynl/generated/.gitignore
@@ -1,2 +1,3 @@
*-user.c
*-user.h
+*.rst
diff --git a/tools/net/ynl/generated/Makefile b/tools/net/ynl/generated/Makefile
index 7db5240de58a..21f9e299dc75 100644
--- a/tools/net/ynl/generated/Makefile
+++ b/tools/net/ynl/generated/Makefile
@@ -7,32 +7,44 @@ ifeq ("$(DEBUG)","1")
CFLAGS += -g -fsanitize=address -fsanitize=leak -static-libasan
endif
+INSTALL ?= install
+prefix ?= /usr
+datarootdir ?= $(prefix)/share
+docdir ?= $(datarootdir)/doc
+includedir ?= $(prefix)/include
+
include ../Makefile.deps
YNL_GEN_ARG_ethtool:=--user-header linux/ethtool_netlink.h \
--exclude-op stats-get
-TOOL:=../ynl-gen-c.py
+TOOL:=../pyynl/ynl_gen_c.py
+TOOL_RST:=../pyynl/ynl_gen_rst.py
+SPECS_DIR:=../../../../Documentation/netlink/specs
GENS_PATHS=$(shell grep -nrI --files-without-match \
'protocol: netlink' \
- ../../../../Documentation/netlink/specs/)
-GENS=$(patsubst ../../../../Documentation/netlink/specs/%.yaml,%,${GENS_PATHS})
+ $(SPECS_DIR))
+GENS=$(patsubst $(SPECS_DIR)/%.yaml,%,${GENS_PATHS})
SRCS=$(patsubst %,%-user.c,${GENS})
HDRS=$(patsubst %,%-user.h,${GENS})
OBJS=$(patsubst %,%-user.o,${GENS})
-all: protos.a $(HDRS) $(SRCS) $(KHDRS) $(KSRCS) $(UAPI)
+SPECS_PATHS=$(wildcard $(SPECS_DIR)/*.yaml)
+SPECS=$(patsubst $(SPECS_DIR)/%.yaml,%,${SPECS_PATHS})
+RSTS=$(patsubst %,%.rst,${SPECS})
+
+all: protos.a $(HDRS) $(SRCS) $(KHDRS) $(KSRCS) $(UAPI) $(RSTS)
protos.a: $(OBJS)
@echo -e "\tAR $@"
@ar rcs $@ $(OBJS)
-%-user.h: ../../../../Documentation/netlink/specs/%.yaml $(TOOL)
+%-user.h: $(SPECS_DIR)/%.yaml $(TOOL)
@echo -e "\tGEN $@"
@$(TOOL) --mode user --header --spec $< -o $@ $(YNL_GEN_ARG_$*)
-%-user.c: ../../../../Documentation/netlink/specs/%.yaml $(TOOL)
+%-user.c: $(SPECS_DIR)/%.yaml $(TOOL)
@echo -e "\tGEN $@"
@$(TOOL) --mode user --source --spec $< -o $@ $(YNL_GEN_ARG_$*)
@@ -40,14 +52,37 @@ protos.a: $(OBJS)
@echo -e "\tCC $@"
@$(COMPILE.c) $(CFLAGS_$*) -o $@ $<
+%.rst: $(SPECS_DIR)/%.yaml $(TOOL_RST)
+ @echo -e "\tGEN_RST $@"
+ @$(TOOL_RST) -o $@ -i $<
+
clean:
rm -f *.o
distclean: clean
- rm -f *.c *.h *.a
+ rm -f *.c *.h *.a *.rst
regen:
@../ynl-regen.sh
-.PHONY: all clean distclean regen
+install-headers: $(HDRS)
+ @echo -e "\tINSTALL generated headers"
+ @$(INSTALL) -d $(DESTDIR)$(includedir)/ynl
+ @$(INSTALL) -m 0644 *.h $(DESTDIR)$(includedir)/ynl/
+
+install-rsts: $(RSTS)
+ @echo -e "\tINSTALL generated docs"
+ @$(INSTALL) -d $(DESTDIR)$(docdir)/ynl
+ @$(INSTALL) -m 0644 $(RSTS) $(DESTDIR)$(docdir)/ynl/
+
+install-specs:
+ @echo -e "\tINSTALL specs"
+ @$(INSTALL) -d $(DESTDIR)$(datarootdir)/ynl
+ @$(INSTALL) -m 0644 ../../../../Documentation/netlink/*.yaml $(DESTDIR)$(datarootdir)/ynl/
+ @$(INSTALL) -d $(DESTDIR)$(datarootdir)/ynl/specs
+ @$(INSTALL) -m 0644 $(SPECS_DIR)/*.yaml $(DESTDIR)$(datarootdir)/ynl/specs/
+
+install: install-headers install-rsts install-specs
+
+.PHONY: all clean distclean regen install install-headers install-rsts install-specs
.DEFAULT_GOAL: all
diff --git a/tools/net/ynl/lib/.gitignore b/tools/net/ynl/lib/.gitignore
index 296c4035dbf2..a4383358ec72 100644
--- a/tools/net/ynl/lib/.gitignore
+++ b/tools/net/ynl/lib/.gitignore
@@ -1,2 +1 @@
-__pycache__/
*.d
diff --git a/tools/net/ynl/lib/Makefile b/tools/net/ynl/lib/Makefile
index 94c49cca3dca..4b2b98704ff9 100644
--- a/tools/net/ynl/lib/Makefile
+++ b/tools/net/ynl/lib/Makefile
@@ -19,7 +19,6 @@ ynl.a: $(OBJS)
clean:
rm -f *.o *.d *~
- rm -rf __pycache__
distclean: clean
rm -f *.a
diff --git a/tools/net/ynl/pyproject.toml b/tools/net/ynl/pyproject.toml
new file mode 100644
index 000000000000..a81d8779b0e0
--- /dev/null
+++ b/tools/net/ynl/pyproject.toml
@@ -0,0 +1,24 @@
+[build-system]
+requires = ["setuptools>=61.0"]
+build-backend = "setuptools.build_meta"
+
+[project]
+name = "pyynl"
+authors = [
+ {name = "Donald Hunter", email = "donald.hunter@gmail.com"},
+ {name = "Jakub Kicinski", email = "kuba@kernel.org"},
+]
+description = "yaml netlink (ynl)"
+version = "0.0.1"
+requires-python = ">=3.9"
+dependencies = [
+ "pyyaml==6.*",
+ "jsonschema==4.*"
+]
+
+[tool.setuptools.packages.find]
+include = ["pyynl", "pyynl.lib"]
+
+[project.scripts]
+ynl = "pyynl.cli:main"
+ynl-ethtool = "pyynl.ethtool:main"
diff --git a/tools/net/ynl/pyynl/.gitignore b/tools/net/ynl/pyynl/.gitignore
new file mode 100644
index 000000000000..b801cd2d016e
--- /dev/null
+++ b/tools/net/ynl/pyynl/.gitignore
@@ -0,0 +1,2 @@
+__pycache__/
+lib/__pycache__/
diff --git a/tools/net/ynl/pyynl/__init__.py b/tools/net/ynl/pyynl/__init__.py
new file mode 100644
index 000000000000..e69de29bb2d1
--- /dev/null
+++ b/tools/net/ynl/pyynl/__init__.py
diff --git a/tools/net/ynl/cli.py b/tools/net/ynl/pyynl/cli.py
index 41d9fa5c818d..41d9fa5c818d 100755
--- a/tools/net/ynl/cli.py
+++ b/tools/net/ynl/pyynl/cli.py
diff --git a/tools/net/ynl/ethtool.py b/tools/net/ynl/pyynl/ethtool.py
index ebb0a11f67bf..ebb0a11f67bf 100755
--- a/tools/net/ynl/ethtool.py
+++ b/tools/net/ynl/pyynl/ethtool.py
diff --git a/tools/net/ynl/lib/__init__.py b/tools/net/ynl/pyynl/lib/__init__.py
index 9137b83e580a..9137b83e580a 100644
--- a/tools/net/ynl/lib/__init__.py
+++ b/tools/net/ynl/pyynl/lib/__init__.py
diff --git a/tools/net/ynl/lib/nlspec.py b/tools/net/ynl/pyynl/lib/nlspec.py
index a745739655ad..314ec8007496 100644
--- a/tools/net/ynl/lib/nlspec.py
+++ b/tools/net/ynl/pyynl/lib/nlspec.py
@@ -219,7 +219,10 @@ class SpecAttrSet(SpecElement):
else:
real_set = family.attr_sets[self.subset_of]
for elem in self.yaml['attributes']:
- attr = real_set[elem['name']]
+ real_attr = real_set[elem['name']]
+ combined_elem = real_attr.yaml | elem
+ attr = self.new_attr(combined_elem, real_attr.value)
+
self.attrs[attr.name] = attr
self.attrs_by_val[attr.value] = attr
diff --git a/tools/net/ynl/lib/ynl.py b/tools/net/ynl/pyynl/lib/ynl.py
index 01ec01a90e76..08f8bf89cfc2 100644
--- a/tools/net/ynl/lib/ynl.py
+++ b/tools/net/ynl/pyynl/lib/ynl.py
@@ -556,10 +556,10 @@ class YnlFamily(SpecFamily):
if attr["type"] == 'nest':
nl_type |= Netlink.NLA_F_NESTED
attr_payload = b''
- sub_attrs = SpaceAttrs(self.attr_sets[space], value, search_attrs)
+ sub_space = attr['nested-attributes']
+ sub_attrs = SpaceAttrs(self.attr_sets[sub_space], value, search_attrs)
for subname, subvalue in value.items():
- attr_payload += self._add_attr(attr['nested-attributes'],
- subname, subvalue, sub_attrs)
+ attr_payload += self._add_attr(sub_space, subname, subvalue, sub_attrs)
elif attr["type"] == 'flag':
if not value:
# If value is absent or false then skip attribute creation.
@@ -733,41 +733,45 @@ class YnlFamily(SpecFamily):
self._rsp_add(rsp, attr_name, None, self._decode_unknown(attr))
continue
- if attr_spec["type"] == 'nest':
- subdict = self._decode(NlAttrs(attr.raw), attr_spec['nested-attributes'], search_attrs)
- decoded = subdict
- elif attr_spec["type"] == 'string':
- decoded = attr.as_strz()
- elif attr_spec["type"] == 'binary':
- decoded = self._decode_binary(attr, attr_spec)
- elif attr_spec["type"] == 'flag':
- decoded = True
- elif attr_spec.is_auto_scalar:
- decoded = attr.as_auto_scalar(attr_spec['type'], attr_spec.byte_order)
- elif attr_spec["type"] in NlAttr.type_formats:
- decoded = attr.as_scalar(attr_spec['type'], attr_spec.byte_order)
- if 'enum' in attr_spec:
- decoded = self._decode_enum(decoded, attr_spec)
- elif attr_spec.display_hint:
- decoded = self._formatted_string(decoded, attr_spec.display_hint)
- elif attr_spec["type"] == 'indexed-array':
- decoded = self._decode_array_attr(attr, attr_spec)
- elif attr_spec["type"] == 'bitfield32':
- value, selector = struct.unpack("II", attr.raw)
- if 'enum' in attr_spec:
- value = self._decode_enum(value, attr_spec)
- selector = self._decode_enum(selector, attr_spec)
- decoded = {"value": value, "selector": selector}
- elif attr_spec["type"] == 'sub-message':
- decoded = self._decode_sub_msg(attr, attr_spec, search_attrs)
- elif attr_spec["type"] == 'nest-type-value':
- decoded = self._decode_nest_type_value(attr, attr_spec)
- else:
- if not self.process_unknown:
- raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
- decoded = self._decode_unknown(attr)
-
- self._rsp_add(rsp, attr_spec["name"], attr_spec.is_multi, decoded)
+ try:
+ if attr_spec["type"] == 'nest':
+ subdict = self._decode(NlAttrs(attr.raw), attr_spec['nested-attributes'], search_attrs)
+ decoded = subdict
+ elif attr_spec["type"] == 'string':
+ decoded = attr.as_strz()
+ elif attr_spec["type"] == 'binary':
+ decoded = self._decode_binary(attr, attr_spec)
+ elif attr_spec["type"] == 'flag':
+ decoded = True
+ elif attr_spec.is_auto_scalar:
+ decoded = attr.as_auto_scalar(attr_spec['type'], attr_spec.byte_order)
+ elif attr_spec["type"] in NlAttr.type_formats:
+ decoded = attr.as_scalar(attr_spec['type'], attr_spec.byte_order)
+ if 'enum' in attr_spec:
+ decoded = self._decode_enum(decoded, attr_spec)
+ elif attr_spec.display_hint:
+ decoded = self._formatted_string(decoded, attr_spec.display_hint)
+ elif attr_spec["type"] == 'indexed-array':
+ decoded = self._decode_array_attr(attr, attr_spec)
+ elif attr_spec["type"] == 'bitfield32':
+ value, selector = struct.unpack("II", attr.raw)
+ if 'enum' in attr_spec:
+ value = self._decode_enum(value, attr_spec)
+ selector = self._decode_enum(selector, attr_spec)
+ decoded = {"value": value, "selector": selector}
+ elif attr_spec["type"] == 'sub-message':
+ decoded = self._decode_sub_msg(attr, attr_spec, search_attrs)
+ elif attr_spec["type"] == 'nest-type-value':
+ decoded = self._decode_nest_type_value(attr, attr_spec)
+ else:
+ if not self.process_unknown:
+ raise Exception(f'Unknown {attr_spec["type"]} with name {attr_spec["name"]}')
+ decoded = self._decode_unknown(attr)
+
+ self._rsp_add(rsp, attr_spec["name"], attr_spec.is_multi, decoded)
+ except:
+ print(f"Error decoding '{attr_spec.name}' from '{space}'")
+ raise
return rsp
diff --git a/tools/net/ynl/ynl-gen-c.py b/tools/net/ynl/pyynl/ynl_gen_c.py
index d8201c4b1520..d3a7dfbcf929 100755
--- a/tools/net/ynl/ynl-gen-c.py
+++ b/tools/net/ynl/pyynl/ynl_gen_c.py
@@ -79,6 +79,20 @@ class Type(SpecAttr):
self.enum_name = None
delattr(self, "enum_name")
+ def _get_real_attr(self):
+ # if the attr is for a subset return the "real" attr (just one down, does not recurse)
+ return self.family.attr_sets[self.attr_set.subset_of][self.name]
+
+ def set_request(self):
+ self.request = True
+ if self.attr_set.subset_of:
+ self._get_real_attr().set_request()
+
+ def set_reply(self):
+ self.reply = True
+ if self.attr_set.subset_of:
+ self._get_real_attr().set_reply()
+
def get_limit(self, limit, default=None):
value = self.checks.get(limit, default)
if value is None:
@@ -106,6 +120,10 @@ class Type(SpecAttr):
enum_name = f"{self.attr_set.name_prefix}{self.name}"
self.enum_name = c_upper(enum_name)
+ if self.attr_set.subset_of:
+ if self.checks != self._get_real_attr().checks:
+ raise Exception("Overriding checks not supported by codegen, yet")
+
def is_multi_val(self):
return None
@@ -801,6 +819,8 @@ class EnumSet(SpecEnumSet):
self.user_type = 'int'
self.value_pfx = yaml.get('name-prefix', f"{family.ident_name}-{yaml['name']}-")
+ self.header = yaml.get('header', None)
+ self.enum_cnt_name = yaml.get('enum-cnt-name', None)
super().__init__(family, yaml)
@@ -1117,17 +1137,17 @@ class Family(SpecFamily):
for _, struct in self.pure_nested_structs.items():
if struct.request:
for _, arg in struct.member_list():
- arg.request = True
+ arg.set_request()
if struct.reply:
for _, arg in struct.member_list():
- arg.reply = True
+ arg.set_reply()
for root_set, rs_members in self.root_sets.items():
for attr, spec in self.attr_sets[root_set].items():
if attr in rs_members['request']:
- spec.request = True
+ spec.set_request()
if attr in rs_members['reply']:
- spec.reply = True
+ spec.set_reply()
def _load_global_policy(self):
global_set = set()
@@ -1763,7 +1783,14 @@ def parse_rsp_nested(ri, struct):
f'{struct.ptr_name}dst = yarg->data;']
init_lines = []
- _multi_parse(ri, struct, init_lines, local_vars)
+ if struct.member_list():
+ _multi_parse(ri, struct, init_lines, local_vars)
+ else:
+ # Empty nest
+ ri.cw.block_start()
+ ri.cw.p('return 0;')
+ ri.cw.block_end()
+ ri.cw.nl()
def parse_rsp_msg(ri, deref=False):
@@ -2417,6 +2444,87 @@ def uapi_enum_start(family, cw, obj, ckey='', enum_name='enum-name'):
cw.block_start(line=start_line)
+def render_uapi_unified(family, cw, max_by_define, separate_ntf):
+ max_name = c_upper(family.get('cmd-max-name', f"{family.op_prefix}MAX"))
+ cnt_name = c_upper(family.get('cmd-cnt-name', f"__{family.op_prefix}MAX"))
+ max_value = f"({cnt_name} - 1)"
+
+ uapi_enum_start(family, cw, family['operations'], 'enum-name')
+ val = 0
+ for op in family.msgs.values():
+ if separate_ntf and ('notify' in op or 'event' in op):
+ continue
+
+ suffix = ','
+ if op.value != val:
+ suffix = f" = {op.value},"
+ val = op.value
+ cw.p(op.enum_name + suffix)
+ val += 1
+ cw.nl()
+ cw.p(cnt_name + ('' if max_by_define else ','))
+ if not max_by_define:
+ cw.p(f"{max_name} = {max_value}")
+ cw.block_end(line=';')
+ if max_by_define:
+ cw.p(f"#define {max_name} {max_value}")
+ cw.nl()
+
+
+def render_uapi_directional(family, cw, max_by_define):
+ max_name = f"{family.op_prefix}USER_MAX"
+ cnt_name = f"__{family.op_prefix}USER_CNT"
+ max_value = f"({cnt_name} - 1)"
+
+ cw.block_start(line='enum')
+ cw.p(c_upper(f'{family.name}_MSG_USER_NONE = 0,'))
+ val = 0
+ for op in family.msgs.values():
+ if 'do' in op and 'event' not in op:
+ suffix = ','
+ if op.value and op.value != val:
+ suffix = f" = {op.value},"
+ val = op.value
+ cw.p(op.enum_name + suffix)
+ val += 1
+ cw.nl()
+ cw.p(cnt_name + ('' if max_by_define else ','))
+ if not max_by_define:
+ cw.p(f"{max_name} = {max_value}")
+ cw.block_end(line=';')
+ if max_by_define:
+ cw.p(f"#define {max_name} {max_value}")
+ cw.nl()
+
+ max_name = f"{family.op_prefix}KERNEL_MAX"
+ cnt_name = f"__{family.op_prefix}KERNEL_CNT"
+ max_value = f"({cnt_name} - 1)"
+
+ cw.block_start(line='enum')
+ cw.p(c_upper(f'{family.name}_MSG_KERNEL_NONE = 0,'))
+ val = 0
+ for op in family.msgs.values():
+ if ('do' in op and 'reply' in op['do']) or 'notify' in op or 'event' in op:
+ enum_name = op.enum_name
+ if 'event' not in op and 'notify' not in op:
+ enum_name = f'{enum_name}_REPLY'
+
+ suffix = ','
+ if op.value and op.value != val:
+ suffix = f" = {op.value},"
+ val = op.value
+ cw.p(enum_name + suffix)
+ val += 1
+ cw.nl()
+ cw.p(cnt_name + ('' if max_by_define else ','))
+ if not max_by_define:
+ cw.p(f"{max_name} = {max_value}")
+ cw.block_end(line=';')
+ if max_by_define:
+ cw.p(f"#define {max_name} {max_value}")
+ cw.nl()
+
+
def render_uapi(family, cw):
hdr_prot = f"_UAPI_LINUX_{c_upper(family.uapi_header_name)}_H"
hdr_prot = hdr_prot.replace('/', '_')
@@ -2440,6 +2548,9 @@ def render_uapi(family, cw):
if const['type'] == 'enum' or const['type'] == 'flags':
enum = family.consts[const['name']]
+ if enum.header:
+ continue
+
if enum.has_doc():
if enum.has_entry_doc():
cw.p('/**')
@@ -2472,9 +2583,12 @@ def render_uapi(family, cw):
max_val = f' = {enum.get_mask()},'
cw.p(max_name + max_val)
else:
+ cnt_name = enum.enum_cnt_name
max_name = c_upper(name_pfx + 'max')
- cw.p('__' + max_name + ',')
- cw.p(max_name + ' = (__' + max_name + ' - 1)')
+ if not cnt_name:
+ cnt_name = '__' + name_pfx + 'max'
+ cw.p(c_upper(cnt_name) + ',')
+ cw.p(max_name + ' = (' + c_upper(cnt_name) + ' - 1)')
cw.block_end(line=';')
cw.nl()
elif const['type'] == 'const':
@@ -2503,7 +2617,8 @@ def render_uapi(family, cw):
val = attr.value
val += 1
cw.p(attr.enum_name + suffix)
- cw.nl()
+ if attr_set.items():
+ cw.nl()
cw.p(attr_set.cnt_name + ('' if max_by_define else ','))
if not max_by_define:
cw.p(f"{attr_set.max_name} = {max_value}")
@@ -2515,30 +2630,12 @@ def render_uapi(family, cw):
# Commands
separate_ntf = 'async-prefix' in family['operations']
- max_name = c_upper(family.get('cmd-max-name', f"{family.op_prefix}MAX"))
- cnt_name = c_upper(family.get('cmd-cnt-name', f"__{family.op_prefix}MAX"))
- max_value = f"({cnt_name} - 1)"
-
- uapi_enum_start(family, cw, family['operations'], 'enum-name')
- val = 0
- for op in family.msgs.values():
- if separate_ntf and ('notify' in op or 'event' in op):
- continue
-
- suffix = ','
- if op.value != val:
- suffix = f" = {op.value},"
- val = op.value
- cw.p(op.enum_name + suffix)
- val += 1
- cw.nl()
- cw.p(cnt_name + ('' if max_by_define else ','))
- if not max_by_define:
- cw.p(f"{max_name} = {max_value}")
- cw.block_end(line=';')
- if max_by_define:
- cw.p(f"#define {max_name} {max_value}")
- cw.nl()
+ if family.msg_id_model == 'unified':
+ render_uapi_unified(family, cw, max_by_define, separate_ntf)
+ elif family.msg_id_model == 'directional':
+ render_uapi_directional(family, cw, max_by_define)
+ else:
+ raise Exception(f'Unsupported message enum-model {family.msg_id_model}')
if separate_ntf:
uapi_enum_start(family, cw, family['operations'], enum_name='async-enum')
@@ -2635,7 +2732,8 @@ def find_kernel_root(full_path):
def main():
parser = argparse.ArgumentParser(description='Netlink simple parsing generator')
- parser.add_argument('--mode', dest='mode', type=str, required=True)
+ parser.add_argument('--mode', dest='mode', type=str, required=True,
+ choices=('user', 'kernel', 'uapi'))
parser.add_argument('--spec', dest='spec', type=str, required=True)
parser.add_argument('--header', dest='header', action='store_true', default=None)
parser.add_argument('--source', dest='header', action='store_false')
@@ -2662,13 +2760,6 @@ def main():
os.sys.exit(1)
return
- supported_models = ['unified']
- if args.mode in ['user', 'kernel']:
- supported_models += ['directional']
- if parsed.msg_id_model not in supported_models:
- print(f'Message enum-model {parsed.msg_id_model} not supported for {args.mode} generation')
- os.sys.exit(1)
-
cw = CodeWriter(BaseNlLib(), args.out_file, overwrite=(not args.cmp_out))
_, spec_kernel = find_kernel_root(args.spec)
@@ -2696,7 +2787,10 @@ def main():
cw.p('#define ' + hdr_prot)
cw.nl()
- hdr_file=os.path.basename(args.out_file[:-2]) + ".h"
+ if args.out_file:
+ hdr_file = os.path.basename(args.out_file[:-2]) + ".h"
+ else:
+ hdr_file = "generated_header_file.h"
if args.mode == 'kernel':
cw.p('#include <net/netlink.h>')
@@ -2718,12 +2812,17 @@ def main():
else:
cw.p(f'#include "{hdr_file}"')
cw.p('#include "ynl.h"')
- headers = [parsed.uapi_header]
+ headers = []
for definition in parsed['definitions']:
if 'header' in definition:
headers.append(definition['header'])
+ if args.mode == 'user':
+ headers.append(parsed.uapi_header)
+ seen_header = []
for one in headers:
- cw.p(f"#include <{one}>")
+ if one not in seen_header:
+ cw.p(f"#include <{one}>")
+ seen_header.append(one)
cw.nl()
if args.mode == "user":
diff --git a/tools/net/ynl/ynl-gen-rst.py b/tools/net/ynl/pyynl/ynl_gen_rst.py
index 6c56d0d726b4..6c56d0d726b4 100755
--- a/tools/net/ynl/ynl-gen-rst.py
+++ b/tools/net/ynl/pyynl/ynl_gen_rst.py
diff --git a/tools/net/ynl/ynl-regen.sh b/tools/net/ynl/ynl-regen.sh
index a37304dcc88e..81b4ecd89100 100755
--- a/tools/net/ynl/ynl-regen.sh
+++ b/tools/net/ynl/ynl-regen.sh
@@ -1,7 +1,7 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
-TOOL=$(dirname $(realpath $0))/ynl-gen-c.py
+TOOL=$(dirname $(realpath $0))/pyynl/ynl_gen_c.py
force=
search=
diff --git a/tools/objtool/check.c b/tools/objtool/check.c
index f7586f82b967..76060da755b5 100644
--- a/tools/objtool/check.c
+++ b/tools/objtool/check.c
@@ -3820,9 +3820,12 @@ static int validate_branch(struct objtool_file *file, struct symbol *func,
break;
case INSN_CONTEXT_SWITCH:
- if (func && (!next_insn || !next_insn->hint)) {
- WARN_INSN(insn, "unsupported instruction in callable function");
- return 1;
+ if (func) {
+ if (!next_insn || !next_insn->hint) {
+ WARN_INSN(insn, "unsupported instruction in callable function");
+ return 1;
+ }
+ break;
}
return 0;
@@ -4573,6 +4576,8 @@ static int validate_ibt(struct objtool_file *file)
!strcmp(sec->name, "__jump_table") ||
!strcmp(sec->name, "__mcount_loc") ||
!strcmp(sec->name, ".kcfi_traps") ||
+ !strcmp(sec->name, ".llvm.call-graph-profile") ||
+ !strcmp(sec->name, ".llvm_bb_addr_map") ||
!strcmp(sec->name, "__tracepoints") ||
strstr(sec->name, "__patchable_function_entries"))
continue;
diff --git a/tools/objtool/elf.c b/tools/objtool/elf.c
index 3d27983dc908..6f64d611faea 100644
--- a/tools/objtool/elf.c
+++ b/tools/objtool/elf.c
@@ -224,12 +224,17 @@ int find_symbol_hole_containing(const struct section *sec, unsigned long offset)
if (n)
return 0; /* not a hole */
- /* didn't find a symbol for which @offset is after it */
- if (!hole.sym)
- return 0; /* not a hole */
+ /*
+ * @offset >= sym->offset + sym->len, find symbol after it.
+ * When hole.sym is empty, use the first node to compute the hole.
+ * If there is no symbol in the section, the first node will be NULL,
+ * in which case, -1 is returned to skip the whole section.
+ */
+ if (hole.sym)
+ n = rb_next(&hole.sym->node);
+ else
+ n = rb_first_cached(&sec->symbol_tree);
- /* @offset >= sym->offset + sym->len, find symbol after it */
- n = rb_next(&hole.sym->node);
if (!n)
return -1; /* until end of address space */
diff --git a/tools/objtool/noreturns.h b/tools/objtool/noreturns.h
index f37614cc2c1b..b2174894f9f7 100644
--- a/tools/objtool/noreturns.h
+++ b/tools/objtool/noreturns.h
@@ -19,6 +19,7 @@ NORETURN(__x64_sys_exit_group)
NORETURN(arch_cpu_idle_dead)
NORETURN(bch2_trans_in_restart_error)
NORETURN(bch2_trans_restart_error)
+NORETURN(bch2_trans_unlocked_error)
NORETURN(cpu_bringup_and_idle)
NORETURN(cpu_startup_entry)
NORETURN(do_exit)
diff --git a/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl b/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
index 1464c6be6eb3..c844cd5cda62 100644
--- a/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
+++ b/tools/perf/arch/mips/entry/syscalls/syscall_n64.tbl
@@ -377,3 +377,7 @@
460 n64 lsm_set_self_attr sys_lsm_set_self_attr
461 n64 lsm_list_modules sys_lsm_list_modules
462 n64 mseal sys_mseal
+463 n64 setxattrat sys_setxattrat
+464 n64 getxattrat sys_getxattrat
+465 n64 listxattrat sys_listxattrat
+466 n64 removexattrat sys_removexattrat
diff --git a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
index ebae8415dfbb..d8b4ab78bef0 100644
--- a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
@@ -553,3 +553,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
diff --git a/tools/perf/arch/s390/entry/syscalls/syscall.tbl b/tools/perf/arch/s390/entry/syscalls/syscall.tbl
index 01071182763e..e9115b4d8b63 100644
--- a/tools/perf/arch/s390/entry/syscalls/syscall.tbl
+++ b/tools/perf/arch/s390/entry/syscalls/syscall.tbl
@@ -465,3 +465,7 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal sys_mseal
+463 common setxattrat sys_setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat sys_removexattrat
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_32.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_32.tbl
index 534c74b14fab..4d0fb2fba7e2 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_32.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_32.tbl
@@ -468,3 +468,7 @@
460 i386 lsm_set_self_attr sys_lsm_set_self_attr
461 i386 lsm_list_modules sys_lsm_list_modules
462 i386 mseal sys_mseal
+463 i386 setxattrat sys_setxattrat
+464 i386 getxattrat sys_getxattrat
+465 i386 listxattrat sys_listxattrat
+466 i386 removexattrat sys_removexattrat
diff --git a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
index 7093ee21c0d1..5eb708bff1c7 100644
--- a/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
+++ b/tools/perf/arch/x86/entry/syscalls/syscall_64.tbl
@@ -386,6 +386,10 @@
460 common lsm_set_self_attr sys_lsm_set_self_attr
461 common lsm_list_modules sys_lsm_list_modules
462 common mseal sys_mseal
+463 common setxattrat sys_setxattrat
+464 common getxattrat sys_getxattrat
+465 common listxattrat sys_listxattrat
+466 common removexattrat sys_removexattrat
#
# Due to a historical design error, certain syscalls are numbered differently
diff --git a/tools/perf/builtin-ftrace.c b/tools/perf/builtin-ftrace.c
index 272d3c70810e..a56cf8b0a7d4 100644
--- a/tools/perf/builtin-ftrace.c
+++ b/tools/perf/builtin-ftrace.c
@@ -1151,8 +1151,9 @@ static int cmp_profile_data(const void *a, const void *b)
if (v1 > v2)
return -1;
- else
+ if (v1 < v2)
return 1;
+ return 0;
}
static void print_profile_result(struct perf_ftrace *ftrace)
diff --git a/tools/perf/tests/builtin-test.c b/tools/perf/tests/builtin-test.c
index 8dcf74d3c0a3..4751dd3c6f67 100644
--- a/tools/perf/tests/builtin-test.c
+++ b/tools/perf/tests/builtin-test.c
@@ -508,7 +508,7 @@ static int __cmd_test(struct test_suite **suites, int argc, const char *argv[],
for (size_t x = 0; x < num_tests; x++) {
struct child_test *child_test = child_tests[x];
- if (!child_test)
+ if (!child_test || child_test->process.pid <= 0)
continue;
pr_debug3("Killing %d pid %d\n",
diff --git a/tools/perf/tests/expr.c b/tools/perf/tests/expr.c
index 41ff1affdfcd..726cf8d4da28 100644
--- a/tools/perf/tests/expr.c
+++ b/tools/perf/tests/expr.c
@@ -75,14 +75,12 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
double val, num_cpus_online, num_cpus, num_cores, num_dies, num_packages;
int ret;
struct expr_parse_ctx *ctx;
- bool is_intel = false;
char strcmp_cpuid_buf[256];
struct perf_cpu cpu = {-1};
char *cpuid = get_cpuid_allow_env_override(cpu);
char *escaped_cpuid1, *escaped_cpuid2;
TEST_ASSERT_VAL("get_cpuid", cpuid);
- is_intel = strstr(cpuid, "Intel") != NULL;
TEST_ASSERT_EQUAL("ids_union", test_ids_union(), 0);
@@ -245,12 +243,19 @@ static int test__expr(struct test_suite *t __maybe_unused, int subtest __maybe_u
if (num_dies) // Some platforms do not have CPU die support, for example s390
TEST_ASSERT_VAL("#num_dies >= #num_packages", num_dies >= num_packages);
- TEST_ASSERT_VAL("#system_tsc_freq", expr__parse(&val, ctx, "#system_tsc_freq") == 0);
- if (is_intel)
- TEST_ASSERT_VAL("#system_tsc_freq > 0", val > 0);
- else
- TEST_ASSERT_VAL("#system_tsc_freq == 0", fpclassify(val) == FP_ZERO);
+ if (expr__parse(&val, ctx, "#system_tsc_freq") == 0) {
+ bool is_intel = strstr(cpuid, "Intel") != NULL;
+
+ if (is_intel)
+ TEST_ASSERT_VAL("#system_tsc_freq > 0", val > 0);
+ else
+ TEST_ASSERT_VAL("#system_tsc_freq == 0", fpclassify(val) == FP_ZERO);
+ } else {
+#if defined(__i386__) || defined(__x86_64__)
+ TEST_ASSERT_VAL("#system_tsc_freq unsupported", 0);
+#endif
+ }
/*
* Source count returns the number of events aggregating in a leader
* event including the leader. Check parsing yields an id.
diff --git a/tools/perf/tests/hwmon_pmu.c b/tools/perf/tests/hwmon_pmu.c
index f8bcee9660d5..d2b066a2b557 100644
--- a/tools/perf/tests/hwmon_pmu.c
+++ b/tools/perf/tests/hwmon_pmu.c
@@ -65,7 +65,7 @@ static struct perf_pmu *test_pmu_get(char *dir, size_t sz)
{ "temp2_label", "test hwmon event2\n", },
{ "temp2_input", "50000\n", },
};
- int dirfd, file;
+ int hwmon_dirfd = -1, test_dirfd = -1, file;
struct perf_pmu *hwm = NULL;
ssize_t len;
@@ -76,19 +76,24 @@ static struct perf_pmu *test_pmu_get(char *dir, size_t sz)
dir[0] = '\0';
return NULL;
}
- dirfd = open(dir, O_DIRECTORY);
- if (dirfd < 0) {
+ test_dirfd = open(dir, O_PATH|O_DIRECTORY);
+ if (test_dirfd < 0) {
pr_err("Failed to open test directory \"%s\"\n", dir);
goto err_out;
}
/* Create the test hwmon directory and give it a name. */
- if (mkdirat(dirfd, "hwmon1234", 0755) < 0) {
+ if (mkdirat(test_dirfd, "hwmon1234", 0755) < 0) {
pr_err("Failed to mkdir hwmon directory\n");
goto err_out;
}
- file = openat(dirfd, "hwmon1234/name", O_WRONLY | O_CREAT, 0600);
- if (!file) {
+ hwmon_dirfd = openat(test_dirfd, "hwmon1234", O_DIRECTORY);
+ if (hwmon_dirfd < 0) {
+ pr_err("Failed to open test hwmon directory \"%s/hwmon1234\"\n", dir);
+ goto err_out;
+ }
+ file = openat(hwmon_dirfd, "name", O_WRONLY | O_CREAT, 0600);
+ if (file < 0) {
pr_err("Failed to open for writing file \"name\"\n");
goto err_out;
}
@@ -104,8 +109,8 @@ static struct perf_pmu *test_pmu_get(char *dir, size_t sz)
for (size_t i = 0; i < ARRAY_SIZE(test_items); i++) {
const struct test_item *item = &test_items[i];
- file = openat(dirfd, item->name, O_WRONLY | O_CREAT, 0600);
- if (!file) {
+ file = openat(hwmon_dirfd, item->name, O_WRONLY | O_CREAT, 0600);
+ if (file < 0) {
pr_err("Failed to open for writing file \"%s\"\n", item->name);
goto err_out;
}
@@ -119,16 +124,18 @@ static struct perf_pmu *test_pmu_get(char *dir, size_t sz)
}
/* Make the PMU reading the files created above. */
- hwm = perf_pmus__add_test_hwmon_pmu(dirfd, "hwmon1234", test_hwmon_name);
+ hwm = perf_pmus__add_test_hwmon_pmu(hwmon_dirfd, "hwmon1234", test_hwmon_name);
if (!hwm)
pr_err("Test hwmon creation failed\n");
err_out:
if (!hwm) {
test_pmu_put(dir, hwm);
- if (dirfd >= 0)
- close(dirfd);
+ if (hwmon_dirfd >= 0)
+ close(hwmon_dirfd);
}
+ if (test_dirfd >= 0)
+ close(test_dirfd);
return hwm;
}
diff --git a/tools/perf/trace/beauty/fs_at_flags.sh b/tools/perf/trace/beauty/fs_at_flags.sh
index e3f13f96a27c..fac4d0c049fc 100755
--- a/tools/perf/trace/beauty/fs_at_flags.sh
+++ b/tools/perf/trace/beauty/fs_at_flags.sh
@@ -13,13 +13,14 @@ printf "static const char *fs_at_flags[] = {\n"
regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+AT_([^_]+[[:alnum:]_]+)[[:space:]]+(0x[[:xdigit:]]+)[[:space:]]*.*'
# AT_EACCESS is only meaningful to faccessat, so we will special case it there...
# AT_STATX_SYNC_TYPE is not a bit, its a mask of AT_STATX_SYNC_AS_STAT, AT_STATX_FORCE_SYNC and AT_STATX_DONT_SYNC
-# AT_HANDLE_FID and AT_HANDLE_MNT_ID_UNIQUE are reusing values and are valid only for name_to_handle_at()
+# AT_HANDLE_FID, AT_HANDLE_MNT_ID_UNIQUE and AT_HANDLE_CONNECTABLE are reusing values and are valid only for name_to_handle_at()
# AT_RENAME_NOREPLACE reuses 0x1 and is valid only for renameat2()
grep -E $regex ${linux_fcntl} | \
grep -v AT_EACCESS | \
grep -v AT_STATX_SYNC_TYPE | \
grep -v AT_HANDLE_FID | \
grep -v AT_HANDLE_MNT_ID_UNIQUE | \
+ grep -v AT_HANDLE_CONNECTABLE | \
grep -v AT_RENAME_NOREPLACE | \
sed -r "s/$regex/\2 \1/g" | \
xargs printf "\t[ilog2(%s) + 1] = \"%s\",\n"
diff --git a/tools/perf/trace/beauty/include/uapi/linux/fcntl.h b/tools/perf/trace/beauty/include/uapi/linux/fcntl.h
index 87e2dec79fea..6e6907e63bfc 100644
--- a/tools/perf/trace/beauty/include/uapi/linux/fcntl.h
+++ b/tools/perf/trace/beauty/include/uapi/linux/fcntl.h
@@ -153,9 +153,6 @@
object identity and may not be
usable with open_by_handle_at(2). */
#define AT_HANDLE_MNT_ID_UNIQUE 0x001 /* Return the u64 unique mount ID. */
-
-#if defined(__KERNEL__)
-#define AT_GETATTR_NOSEC 0x80000000
-#endif
+#define AT_HANDLE_CONNECTABLE 0x002 /* Request a connectable file handle */
#endif /* _UAPI_LINUX_FCNTL_H */
diff --git a/tools/perf/trace/beauty/include/uapi/linux/mount.h b/tools/perf/trace/beauty/include/uapi/linux/mount.h
index 225bc366ffcb..c07008816aca 100644
--- a/tools/perf/trace/beauty/include/uapi/linux/mount.h
+++ b/tools/perf/trace/beauty/include/uapi/linux/mount.h
@@ -154,7 +154,7 @@ struct mount_attr {
*/
struct statmount {
__u32 size; /* Total size, including strings */
- __u32 mnt_opts; /* [str] Mount options of the mount */
+ __u32 mnt_opts; /* [str] Options (comma separated, escaped) */
__u64 mask; /* What results were written */
__u32 sb_dev_major; /* Device ID */
__u32 sb_dev_minor;
@@ -173,7 +173,13 @@ struct statmount {
__u32 mnt_root; /* [str] Root of mount relative to root of fs */
__u32 mnt_point; /* [str] Mountpoint relative to current root */
__u64 mnt_ns_id; /* ID of the mount namespace */
- __u64 __spare2[49];
+ __u32 fs_subtype; /* [str] Subtype of fs_type (if any) */
+ __u32 sb_source; /* [str] Source string of the mount */
+ __u32 opt_num; /* Number of fs options */
+ __u32 opt_array; /* [str] Array of nul terminated fs options */
+ __u32 opt_sec_num; /* Number of security options */
+ __u32 opt_sec_array; /* [str] Array of nul terminated security options */
+ __u64 __spare2[46];
char str[]; /* Variable size part containing strings */
};
@@ -207,6 +213,10 @@ struct mnt_id_req {
#define STATMOUNT_FS_TYPE 0x00000020U /* Want/got fs_type */
#define STATMOUNT_MNT_NS_ID 0x00000040U /* Want/got mnt_ns_id */
#define STATMOUNT_MNT_OPTS 0x00000080U /* Want/got mnt_opts */
+#define STATMOUNT_FS_SUBTYPE 0x00000100U /* Want/got fs_subtype */
+#define STATMOUNT_SB_SOURCE 0x00000200U /* Want/got sb_source */
+#define STATMOUNT_OPT_ARRAY 0x00000400U /* Want/got opt_... */
+#define STATMOUNT_OPT_SEC_ARRAY 0x00000800U /* Want/got opt_sec... */
/*
* Special @mnt_id values that can be passed to listmount
diff --git a/tools/perf/trace/beauty/include/uapi/linux/prctl.h b/tools/perf/trace/beauty/include/uapi/linux/prctl.h
index 35791791a879..5c6080680cb2 100644
--- a/tools/perf/trace/beauty/include/uapi/linux/prctl.h
+++ b/tools/perf/trace/beauty/include/uapi/linux/prctl.h
@@ -230,7 +230,7 @@ struct prctl_mm_map {
# define PR_PAC_APDBKEY (1UL << 3)
# define PR_PAC_APGAKEY (1UL << 4)
-/* Tagged user address controls for arm64 */
+/* Tagged user address controls for arm64 and RISC-V */
#define PR_SET_TAGGED_ADDR_CTRL 55
#define PR_GET_TAGGED_ADDR_CTRL 56
# define PR_TAGGED_ADDR_ENABLE (1UL << 0)
@@ -244,6 +244,9 @@ struct prctl_mm_map {
# define PR_MTE_TAG_MASK (0xffffUL << PR_MTE_TAG_SHIFT)
/* Unused; kept only for source compatibility */
# define PR_MTE_TCF_SHIFT 1
+/* RISC-V pointer masking tag length */
+# define PR_PMLEN_SHIFT 24
+# define PR_PMLEN_MASK (0x7fUL << PR_PMLEN_SHIFT)
/* Control reclaim behavior when allocating memory */
#define PR_SET_IO_FLUSHER 57
@@ -328,4 +331,26 @@ struct prctl_mm_map {
# define PR_PPC_DEXCR_CTRL_CLEAR_ONEXEC 0x10 /* Clear the aspect on exec */
# define PR_PPC_DEXCR_CTRL_MASK 0x1f
+/*
+ * Get the current shadow stack configuration for the current thread,
+ * this will be the value configured via PR_SET_SHADOW_STACK_STATUS.
+ */
+#define PR_GET_SHADOW_STACK_STATUS 74
+
+/*
+ * Set the current shadow stack configuration. Enabling the shadow
+ * stack will cause a shadow stack to be allocated for the thread.
+ */
+#define PR_SET_SHADOW_STACK_STATUS 75
+# define PR_SHADOW_STACK_ENABLE (1UL << 0)
+# define PR_SHADOW_STACK_WRITE (1UL << 1)
+# define PR_SHADOW_STACK_PUSH (1UL << 2)
+
+/*
+ * Prevent further changes to the specified shadow stack
+ * configuration. All bits may be locked via this call, including
+ * undefined bits.
+ */
+#define PR_LOCK_SHADOW_STACK_STATUS 76
+
#endif /* _LINUX_PRCTL_H */
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index 8982f68e7230..e763e8d99a43 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -277,7 +277,7 @@ static int write_buildid(const char *name, size_t name_len, struct build_id *bid
struct perf_record_header_build_id b;
size_t len;
- len = sizeof(b) + name_len + 1;
+ len = name_len + 1;
len = PERF_ALIGN(len, sizeof(u64));
memset(&b, 0, sizeof(b));
@@ -286,7 +286,7 @@ static int write_buildid(const char *name, size_t name_len, struct build_id *bid
misc |= PERF_RECORD_MISC_BUILD_ID_SIZE;
b.pid = pid;
b.header.misc = misc;
- b.header.size = len;
+ b.header.size = sizeof(b) + len;
err = do_write(fd, &b, sizeof(b));
if (err < 0)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index f745723d486b..d22c5df1701e 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -2571,12 +2571,12 @@ try_fallback:
if (err == -EMFILE && rlimit__increase_nofile(&set_rlimit))
goto retry_open;
- if (err == -EOPNOTSUPP && evsel__precise_ip_fallback(evsel))
- goto retry_open;
-
if (err == -EINVAL && evsel__detect_missing_features(evsel))
goto fallback_missing_features;
+ if (evsel__precise_ip_fallback(evsel))
+ goto retry_open;
+
if (evsel__handle_error_quirks(evsel, err))
goto retry_open;
diff --git a/tools/perf/util/hwmon_pmu.c b/tools/perf/util/hwmon_pmu.c
index e61429b38ba7..4acb9bb19b84 100644
--- a/tools/perf/util/hwmon_pmu.c
+++ b/tools/perf/util/hwmon_pmu.c
@@ -258,8 +258,12 @@ static int hwmon_pmu__read_events(struct hwmon_pmu *pmu)
if (pmu->pmu.sysfs_aliases_loaded)
return 0;
- /* Use a dup-ed fd as closedir will close it. */
- dup_fd = dup(pmu->hwmon_dir_fd);
+ /*
+ * Use a dup-ed fd as closedir will close it. Use openat so that the
+ * directory contents are refreshed.
+ */
+ dup_fd = openat(pmu->hwmon_dir_fd, ".", O_DIRECTORY);
+
if (dup_fd == -1)
return -ENOMEM;
@@ -336,6 +340,9 @@ static int hwmon_pmu__read_events(struct hwmon_pmu *pmu)
close(fd);
}
}
+ if (hashmap__size(&pmu->events) == 0)
+ pr_debug2("hwmon_pmu: %s has no events\n", pmu->pmu.name);
+
hashmap__for_each_entry_safe((&pmu->events), cur, tmp, bkt) {
union hwmon_pmu_event_key key = {
.type_and_num = cur->key,
@@ -343,8 +350,8 @@ static int hwmon_pmu__read_events(struct hwmon_pmu *pmu)
struct hwmon_pmu_event_value *value = cur->pvalue;
if (!test_bit(HWMON_ITEM_INPUT, value->items)) {
- pr_debug("hwmon_pmu: removing event '%s%d' that has no input file\n",
- hwmon_type_strs[key.type], key.num);
+ pr_debug("hwmon_pmu: %s removing event '%s%d' that has no input file\n",
+ pmu->pmu.name, hwmon_type_strs[key.type], key.num);
hashmap__delete(&pmu->events, key.type_and_num, &key, &value);
zfree(&value->label);
zfree(&value->name);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 4f0ac998b0cc..27d5345d2b30 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -134,6 +134,8 @@ struct machine *machine__new_host(void)
if (machine__create_kernel_maps(machine) < 0)
goto out_delete;
+
+ machine->env = &perf_env;
}
return machine;
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 6d51a4c98ad7..eaa0318e9b87 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1370,7 +1370,7 @@ int parse_line_range_desc(const char *arg, struct line_range *lr)
{
char *buf = strdup(arg);
char *p;
- int err;
+ int err = 0;
if (!buf)
return -ENOMEM;
diff --git a/tools/power/x86/turbostat/turbostat.8 b/tools/power/x86/turbostat/turbostat.8
index 067717bce1d4..a7f7ed01421c 100644
--- a/tools/power/x86/turbostat/turbostat.8
+++ b/tools/power/x86/turbostat/turbostat.8
@@ -33,6 +33,9 @@ name as necessary to disambiguate it from others is necessary. Note that option
msr0xXXX is a hex offset, eg. msr0x10
/sys/path... is an absolute path to a sysfs attribute
<device> is a perf device from /sys/bus/event_source/devices/<device> eg. cstate_core
+ On Intel hybrid platforms, instead of one "cpu" perf device there are two, "cpu_core" and "cpu_atom" devices for P and E cores respectively.
+ Turbostat, in this case, allow user to use "cpu" device and will automatically detect the type of a CPU and translate it to "cpu_core" and "cpu_atom" accordingly.
+ For a complete example see "ADD PERF COUNTER EXAMPLE #2 (using virtual "cpu" device)".
<event> is a perf event for given device from /sys/bus/event_source/devices/<device>/events/<event> eg. c1-residency
perf/cstate_core/c1-residency would then use /sys/bus/event_source/devices/cstate_core/events/c1-residency
@@ -187,6 +190,8 @@ The system configuration dump (if --quiet is not used) is followed by statistics
.PP
\fBRAMWatt\fP Watts consumed by the DRAM DIMMS -- available only on server processors.
.PP
+\fBSysWatt\fP Watts consumed by the whole platform (RAPL PSYS). Disabled by default. Enable with --enable SysWatt.
+.PP
\fBPKG_%\fP percent of the interval that RAPL throttling was active on the Package. Note that the system summary is the sum of the package throttling time, and thus may be higher than 100% on a multi-package system. Note that the meaning of this field is model specific. For example, some hardware increments this counter when RAPL responds to thermal limits, but does not increment this counter when RAPL responds to power limits. Comparing PkgWatt and PkgTmp to system limits is necessary.
.PP
\fBRAM_%\fP percent of the interval that RAPL throttling was active on DRAM.
@@ -387,6 +392,28 @@ CPU pCPU%c1 CPU%c1
.fi
+.SH ADD PERF COUNTER EXAMPLE #2 (using virtual cpu device)
+Here we run on hybrid, Raptor Lake platform.
+We limit turbostat to show output for just cpu0 (pcore) and cpu12 (ecore).
+We add a counter showing number of L3 cache misses, using virtual "cpu" device,
+labeling it with the column header, "VCMISS".
+We add a counter showing number of L3 cache misses, using virtual "cpu_core" device,
+labeling it with the column header, "PCMISS". This will fail on ecore cpu12.
+We add a counter showing number of L3 cache misses, using virtual "cpu_atom" device,
+labeling it with the column header, "ECMISS". This will fail on pcore cpu0.
+We display it only once, after the conclusion of 0.1 second sleep.
+.nf
+sudo ./turbostat --quiet --cpu 0,12 --show CPU --add perf/cpu/cache-misses,cpu,delta,raw,VCMISS --add perf/cpu_core/cache-misses,cpu,delta,raw,PCMISS --add perf/cpu_atom/cache-misses,cpu,delta,raw,ECMISS sleep .1
+turbostat: added_perf_counters_init_: perf/cpu_atom/cache-misses: failed to open counter on cpu0
+turbostat: added_perf_counters_init_: perf/cpu_core/cache-misses: failed to open counter on cpu12
+0.104630 sec
+CPU ECMISS PCMISS VCMISS
+- 0x0000000000000000 0x0000000000000000 0x0000000000000000
+0 0x0000000000000000 0x0000000000007951 0x0000000000007796
+12 0x000000000001137a 0x0000000000000000 0x0000000000011392
+
+.fi
+
.SH ADD PMT COUNTER EXAMPLE
Here we limit turbostat to showing just the CPU number 0.
We add two counters, showing crystal clock count and the DC6 residency.
diff --git a/tools/power/x86/turbostat/turbostat.c b/tools/power/x86/turbostat/turbostat.c
index 089220aaa5c9..58a487c225a7 100644
--- a/tools/power/x86/turbostat/turbostat.c
+++ b/tools/power/x86/turbostat/turbostat.c
@@ -31,6 +31,9 @@
)
// end copied section
+#define CPUID_LEAF_MODEL_ID 0x1A
+#define CPUID_LEAF_MODEL_ID_CORE_TYPE_SHIFT 24
+
#define X86_VENDOR_INTEL 0
#include INTEL_FAMILY_HEADER
@@ -89,6 +92,9 @@
#define PERF_DEV_NAME_BYTES 32
#define PERF_EVT_NAME_BYTES 32
+#define INTEL_ECORE_TYPE 0x20
+#define INTEL_PCORE_TYPE 0x40
+
enum counter_scope { SCOPE_CPU, SCOPE_CORE, SCOPE_PACKAGE };
enum counter_type { COUNTER_ITEMS, COUNTER_CYCLES, COUNTER_SECONDS, COUNTER_USEC, COUNTER_K2M };
enum counter_format { FORMAT_RAW, FORMAT_DELTA, FORMAT_PERCENT, FORMAT_AVERAGE };
@@ -194,6 +200,8 @@ struct msr_counter bic[] = {
{ 0x0, "SAMMHz", NULL, 0, 0, 0, NULL, 0 },
{ 0x0, "SAMAMHz", NULL, 0, 0, 0, NULL, 0 },
{ 0x0, "Die%c6", NULL, 0, 0, 0, NULL, 0 },
+ { 0x0, "SysWatt", NULL, 0, 0, 0, NULL, 0 },
+ { 0x0, "Sys_J", NULL, 0, 0, 0, NULL, 0 },
};
#define MAX_BIC (sizeof(bic) / sizeof(struct msr_counter))
@@ -256,6 +264,8 @@ struct msr_counter bic[] = {
#define BIC_SAMMHz (1ULL << 56)
#define BIC_SAMACTMHz (1ULL << 57)
#define BIC_Diec6 (1ULL << 58)
+#define BIC_SysWatt (1ULL << 59)
+#define BIC_Sys_J (1ULL << 60)
#define BIC_TOPOLOGY (BIC_Package | BIC_Node | BIC_CoreCnt | BIC_PkgCnt | BIC_Core | BIC_CPU | BIC_Die )
#define BIC_THERMAL_PWR ( BIC_CoreTmp | BIC_PkgTmp | BIC_PkgWatt | BIC_CorWatt | BIC_GFXWatt | BIC_RAMWatt | BIC_PKG__ | BIC_RAM__)
@@ -263,7 +273,7 @@ struct msr_counter bic[] = {
#define BIC_IDLE (BIC_sysfs | BIC_CPU_c1 | BIC_CPU_c3 | BIC_CPU_c6 | BIC_CPU_c7 | BIC_GFX_rc6 | BIC_Pkgpc2 | BIC_Pkgpc3 | BIC_Pkgpc6 | BIC_Pkgpc7 | BIC_Pkgpc8 | BIC_Pkgpc9 | BIC_Pkgpc10 | BIC_CPU_LPI | BIC_SYS_LPI | BIC_Mod_c6 | BIC_Totl_c0 | BIC_Any_c0 | BIC_GFX_c0 | BIC_CPUGFX | BIC_SAM_mc6 | BIC_Diec6)
#define BIC_OTHER ( BIC_IRQ | BIC_SMI | BIC_ThreadC | BIC_CoreTmp | BIC_IPC)
-#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC)
+#define BIC_DISABLED_BY_DEFAULT (BIC_USEC | BIC_TOD | BIC_APIC | BIC_X2APIC | BIC_SysWatt | BIC_Sys_J)
unsigned long long bic_enabled = (0xFFFFFFFFFFFFFFFFULL & ~BIC_DISABLED_BY_DEFAULT);
unsigned long long bic_present = BIC_USEC | BIC_TOD | BIC_sysfs | BIC_APIC | BIC_X2APIC;
@@ -370,7 +380,6 @@ enum gfx_sysfs_idx {
};
struct gfx_sysfs_info {
- const char *path;
FILE *fp;
unsigned int val;
unsigned long long val_ull;
@@ -502,12 +511,15 @@ enum rapl_msrs {
RAPL_AMD_PWR_UNIT = BIT(14), /* 0xc0010299 MSR_AMD_RAPL_POWER_UNIT */
RAPL_AMD_CORE_ENERGY_STAT = BIT(15), /* 0xc001029a MSR_AMD_CORE_ENERGY_STATUS */
RAPL_AMD_PKG_ENERGY_STAT = BIT(16), /* 0xc001029b MSR_AMD_PKG_ENERGY_STATUS */
+ RAPL_PLATFORM_ENERGY_LIMIT = BIT(17), /* 0x64c MSR_PLATFORM_ENERGY_LIMIT */
+ RAPL_PLATFORM_ENERGY_STATUS = BIT(18), /* 0x64d MSR_PLATFORM_ENERGY_STATUS */
};
#define RAPL_PKG (RAPL_PKG_ENERGY_STATUS | RAPL_PKG_POWER_LIMIT)
#define RAPL_DRAM (RAPL_DRAM_ENERGY_STATUS | RAPL_DRAM_POWER_LIMIT)
#define RAPL_CORE (RAPL_CORE_ENERGY_STATUS | RAPL_CORE_POWER_LIMIT)
#define RAPL_GFX (RAPL_GFX_POWER_LIMIT | RAPL_GFX_ENERGY_STATUS)
+#define RAPL_PSYS (RAPL_PLATFORM_ENERGY_STATUS | RAPL_PLATFORM_ENERGY_LIMIT)
#define RAPL_PKG_ALL (RAPL_PKG | RAPL_PKG_PERF_STATUS | RAPL_PKG_POWER_INFO)
#define RAPL_DRAM_ALL (RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_DRAM_POWER_INFO)
@@ -708,7 +720,7 @@ static const struct platform_features skl_features = {
.has_ext_cst_msrs = 1,
.trl_msrs = TRL_BASE,
.tcc_offset_bits = 6,
- .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,
+ .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX | RAPL_PSYS,
.enable_tsc_tweak = 1,
};
@@ -725,42 +737,44 @@ static const struct platform_features cnl_features = {
.has_ext_cst_msrs = 1,
.trl_msrs = TRL_BASE,
.tcc_offset_bits = 6,
- .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,
+ .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX | RAPL_PSYS,
.enable_tsc_tweak = 1,
};
+/* Copied from cnl_features, with PC7/PC9 removed */
static const struct platform_features adl_features = {
- .has_msr_misc_feature_control = 1,
- .has_msr_misc_pwr_mgmt = 1,
- .has_nhm_msrs = 1,
- .has_config_tdp = 1,
- .bclk_freq = BCLK_100MHZ,
- .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC8 | PC10,
- .cst_limit = CST_LIMIT_HSW,
- .has_irtl_msrs = 1,
- .has_msr_core_c1_res = 1,
- .has_ext_cst_msrs = 1,
- .trl_msrs = TRL_BASE,
- .tcc_offset_bits = 6,
- .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,
- .enable_tsc_tweak = 1,
+ .has_msr_misc_feature_control = cnl_features.has_msr_misc_feature_control,
+ .has_msr_misc_pwr_mgmt = cnl_features.has_msr_misc_pwr_mgmt,
+ .has_nhm_msrs = cnl_features.has_nhm_msrs,
+ .has_config_tdp = cnl_features.has_config_tdp,
+ .bclk_freq = cnl_features.bclk_freq,
+ .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC8 | PC10,
+ .cst_limit = cnl_features.cst_limit,
+ .has_irtl_msrs = cnl_features.has_irtl_msrs,
+ .has_msr_core_c1_res = cnl_features.has_msr_core_c1_res,
+ .has_ext_cst_msrs = cnl_features.has_ext_cst_msrs,
+ .trl_msrs = cnl_features.trl_msrs,
+ .tcc_offset_bits = cnl_features.tcc_offset_bits,
+ .rapl_msrs = cnl_features.rapl_msrs,
+ .enable_tsc_tweak = cnl_features.enable_tsc_tweak,
};
-static const struct platform_features arl_features = {
- .has_msr_misc_feature_control = 1,
- .has_msr_misc_pwr_mgmt = 1,
- .has_nhm_msrs = 1,
- .has_config_tdp = 1,
- .bclk_freq = BCLK_100MHZ,
- .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC3 | PC6 | PC10,
- .cst_limit = CST_LIMIT_HSW,
- .has_irtl_msrs = 1,
- .has_msr_core_c1_res = 1,
- .has_ext_cst_msrs = 1,
- .trl_msrs = TRL_BASE,
- .tcc_offset_bits = 6,
- .rapl_msrs = RAPL_PKG_ALL | RAPL_CORE_ALL | RAPL_DRAM | RAPL_DRAM_PERF_STATUS | RAPL_GFX,
- .enable_tsc_tweak = 1,
+/* Copied from adl_features, with PC3/PC8 removed */
+static const struct platform_features lnl_features = {
+ .has_msr_misc_feature_control = adl_features.has_msr_misc_feature_control,
+ .has_msr_misc_pwr_mgmt = adl_features.has_msr_misc_pwr_mgmt,
+ .has_nhm_msrs = adl_features.has_nhm_msrs,
+ .has_config_tdp = adl_features.has_config_tdp,
+ .bclk_freq = adl_features.bclk_freq,
+ .supported_cstates = CC1 | CC6 | CC7 | PC2 | PC6 | PC10,
+ .cst_limit = adl_features.cst_limit,
+ .has_irtl_msrs = adl_features.has_irtl_msrs,
+ .has_msr_core_c1_res = adl_features.has_msr_core_c1_res,
+ .has_ext_cst_msrs = adl_features.has_ext_cst_msrs,
+ .trl_msrs = adl_features.trl_msrs,
+ .tcc_offset_bits = adl_features.tcc_offset_bits,
+ .rapl_msrs = adl_features.rapl_msrs,
+ .enable_tsc_tweak = adl_features.enable_tsc_tweak,
};
static const struct platform_features skx_features = {
@@ -790,7 +804,7 @@ static const struct platform_features icx_features = {
.has_irtl_msrs = 1,
.has_cst_prewake_bit = 1,
.trl_msrs = TRL_BASE | TRL_CORECOUNT,
- .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
+ .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,
.has_fixed_rapl_unit = 1,
};
@@ -806,7 +820,7 @@ static const struct platform_features spr_features = {
.has_irtl_msrs = 1,
.has_cst_prewake_bit = 1,
.trl_msrs = TRL_BASE | TRL_CORECOUNT,
- .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
+ .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,
};
static const struct platform_features srf_features = {
@@ -822,7 +836,7 @@ static const struct platform_features srf_features = {
.has_irtl_msrs = 1,
.has_cst_prewake_bit = 1,
.trl_msrs = TRL_BASE | TRL_CORECOUNT,
- .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
+ .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,
};
static const struct platform_features grr_features = {
@@ -838,7 +852,7 @@ static const struct platform_features grr_features = {
.has_irtl_msrs = 1,
.has_cst_prewake_bit = 1,
.trl_msrs = TRL_BASE | TRL_CORECOUNT,
- .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL,
+ .rapl_msrs = RAPL_PKG_ALL | RAPL_DRAM_ALL | RAPL_PSYS,
};
static const struct platform_features slv_features = {
@@ -997,18 +1011,19 @@ static const struct platform_data turbostat_pdata[] = {
{ INTEL_SAPPHIRERAPIDS_X, &spr_features },
{ INTEL_EMERALDRAPIDS_X, &spr_features },
{ INTEL_GRANITERAPIDS_X, &spr_features },
+ { INTEL_GRANITERAPIDS_D, &spr_features },
{ INTEL_LAKEFIELD, &cnl_features },
{ INTEL_ALDERLAKE, &adl_features },
{ INTEL_ALDERLAKE_L, &adl_features },
{ INTEL_RAPTORLAKE, &adl_features },
{ INTEL_RAPTORLAKE_P, &adl_features },
{ INTEL_RAPTORLAKE_S, &adl_features },
- { INTEL_METEORLAKE, &cnl_features },
- { INTEL_METEORLAKE_L, &cnl_features },
- { INTEL_ARROWLAKE_H, &arl_features },
- { INTEL_ARROWLAKE_U, &arl_features },
- { INTEL_ARROWLAKE, &arl_features },
- { INTEL_LUNARLAKE_M, &arl_features },
+ { INTEL_METEORLAKE, &adl_features },
+ { INTEL_METEORLAKE_L, &adl_features },
+ { INTEL_ARROWLAKE_H, &adl_features },
+ { INTEL_ARROWLAKE_U, &adl_features },
+ { INTEL_ARROWLAKE, &adl_features },
+ { INTEL_LUNARLAKE_M, &lnl_features },
{ INTEL_ATOM_SILVERMONT, &slv_features },
{ INTEL_ATOM_SILVERMONT_D, &slvd_features },
{ INTEL_ATOM_AIRMONT, &amt_features },
@@ -1100,6 +1115,7 @@ enum rapl_rci_index {
RAPL_RCI_INDEX_PKG_PERF_STATUS = 4,
RAPL_RCI_INDEX_DRAM_PERF_STATUS = 5,
RAPL_RCI_INDEX_CORE_ENERGY = 6,
+ RAPL_RCI_INDEX_ENERGY_PLATFORM = 7,
NUM_RAPL_COUNTERS,
};
@@ -1126,6 +1142,7 @@ struct rapl_counter_info_t {
struct rapl_counter_info_t *rapl_counter_info_perdomain;
unsigned int rapl_counter_info_perdomain_size;
+#define RAPL_COUNTER_FLAG_PLATFORM_COUNTER (1u << 0)
#define RAPL_COUNTER_FLAG_USE_MSR_SUM (1u << 1)
struct rapl_counter_arch_info {
@@ -1247,6 +1264,19 @@ static const struct rapl_counter_arch_info rapl_counter_arch_infos[] = {
.compat_scale = 1.0,
.flags = 0,
},
+ {
+ .feature_mask = RAPL_PSYS,
+ .perf_subsys = "power",
+ .perf_name = "energy-psys",
+ .msr = MSR_PLATFORM_ENERGY_STATUS,
+ .msr_mask = 0x00000000FFFFFFFF,
+ .msr_shift = 0,
+ .platform_rapl_msr_scale = &rapl_energy_units,
+ .rci_index = RAPL_RCI_INDEX_ENERGY_PLATFORM,
+ .bic = BIC_SysWatt | BIC_Sys_J,
+ .compat_scale = 1.0,
+ .flags = RAPL_COUNTER_FLAG_PLATFORM_COUNTER | RAPL_COUNTER_FLAG_USE_MSR_SUM,
+ },
};
struct rapl_counter {
@@ -1674,6 +1704,7 @@ enum {
IDX_PP1_ENERGY,
IDX_PKG_PERF,
IDX_DRAM_PERF,
+ IDX_PSYS_ENERGY,
IDX_COUNT,
};
@@ -1718,6 +1749,9 @@ off_t idx_to_offset(int idx)
case IDX_DRAM_PERF:
offset = MSR_DRAM_PERF_STATUS;
break;
+ case IDX_PSYS_ENERGY:
+ offset = MSR_PLATFORM_ENERGY_STATUS;
+ break;
default:
offset = -1;
}
@@ -1748,6 +1782,9 @@ int offset_to_idx(off_t offset)
case MSR_DRAM_PERF_STATUS:
idx = IDX_DRAM_PERF;
break;
+ case MSR_PLATFORM_ENERGY_STATUS:
+ idx = IDX_PSYS_ENERGY;
+ break;
default:
idx = -1;
}
@@ -1769,6 +1806,8 @@ int idx_valid(int idx)
return platform->rapl_msrs & RAPL_PKG_PERF_STATUS;
case IDX_DRAM_PERF:
return platform->rapl_msrs & RAPL_DRAM_PERF_STATUS;
+ case IDX_PSYS_ENERGY:
+ return platform->rapl_msrs & RAPL_PSYS;
default:
return 0;
}
@@ -1840,6 +1879,10 @@ struct system_summary {
struct pkg_data packages;
} average;
+struct platform_counters {
+ struct rapl_counter energy_psys; /* MSR_PLATFORM_ENERGY_STATUS */
+} platform_counters_odd, platform_counters_even;
+
struct cpu_topology {
int physical_package_id;
int die_id;
@@ -1848,6 +1891,7 @@ struct cpu_topology {
int logical_node_id; /* 0-based count within the package */
int physical_core_id;
int thread_id;
+ int type;
cpu_set_t *put_ids; /* Processing Unit/Thread IDs */
} *cpus;
@@ -2291,7 +2335,7 @@ void print_header(char *delim)
break;
case PMT_TYPE_XTAL_TIME:
- outp += sprintf(outp, "%s%s", delim, ppmt->name);
+ outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), ppmt->name);
break;
}
@@ -2365,7 +2409,7 @@ void print_header(char *delim)
break;
case PMT_TYPE_XTAL_TIME:
- outp += sprintf(outp, "%s%s", delim, ppmt->name);
+ outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), ppmt->name);
break;
}
@@ -2496,13 +2540,18 @@ void print_header(char *delim)
break;
case PMT_TYPE_XTAL_TIME:
- outp += sprintf(outp, "%s%s", delim, ppmt->name);
+ outp += sprintf(outp, "%s%s", (printed++ ? delim : ""), ppmt->name);
break;
}
ppmt = ppmt->next;
}
+ if (DO_BIC(BIC_SysWatt))
+ outp += sprintf(outp, "%sSysWatt", (printed++ ? delim : ""));
+ if (DO_BIC(BIC_Sys_J))
+ outp += sprintf(outp, "%sSys_J", (printed++ ? delim : ""));
+
outp += sprintf(outp, "\n");
}
@@ -2510,6 +2559,7 @@ int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p
{
int i;
struct msr_counter *mp;
+ struct platform_counters *pplat_cnt = p == package_odd ? &platform_counters_odd : &platform_counters_even;
outp += sprintf(outp, "t %p, c %p, p %p\n", t, c, p);
@@ -2581,6 +2631,7 @@ int dump_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p
outp += sprintf(outp, "Joules COR: %0llX\n", p->energy_cores.raw_value);
outp += sprintf(outp, "Joules GFX: %0llX\n", p->energy_gfx.raw_value);
outp += sprintf(outp, "Joules RAM: %0llX\n", p->energy_dram.raw_value);
+ outp += sprintf(outp, "Joules PSYS: %0llX\n", pplat_cnt->energy_psys.raw_value);
outp += sprintf(outp, "Throttle PKG: %0llX\n", p->rapl_pkg_perf_status.raw_value);
outp += sprintf(outp, "Throttle RAM: %0llX\n", p->rapl_dram_perf_status.raw_value);
outp += sprintf(outp, "PTM: %dC\n", p->pkg_temp_c);
@@ -2619,6 +2670,9 @@ double rapl_counter_get_value(const struct rapl_counter *c, enum rapl_unit desir
*/
int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data *p)
{
+ static int count;
+
+ struct platform_counters *pplat_cnt = NULL;
double interval_float, tsc;
char *fmt8;
int i;
@@ -2628,6 +2682,11 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data
char *delim = "\t";
int printed = 0;
+ if (t == &average.threads) {
+ pplat_cnt = count & 1 ? &platform_counters_odd : &platform_counters_even;
+ ++count;
+ }
+
/* if showing only 1st thread in core and this isn't one, bail out */
if (show_core_only && !is_cpu_first_thread_in_core(t, c, p))
return 0;
@@ -2788,6 +2847,8 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data
}
for (i = 0, ppmt = sys.pmt_tp; ppmt; i++, ppmt = ppmt->next) {
+ const unsigned long value_raw = t->pmt_counter[i];
+ const double value_converted = 100.0 * value_raw / crystal_hz / interval_float;
switch (ppmt->type) {
case PMT_TYPE_RAW:
if (pmt_counter_get_width(ppmt) <= 32)
@@ -2799,9 +2860,6 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data
break;
case PMT_TYPE_XTAL_TIME:
- const unsigned long value_raw = t->pmt_counter[i];
- const double value_converted = 100.0 * value_raw / crystal_hz / interval_float;
-
outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);
break;
}
@@ -2869,6 +2927,8 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data
}
for (i = 0, ppmt = sys.pmt_cp; ppmt; i++, ppmt = ppmt->next) {
+ const unsigned long value_raw = c->pmt_counter[i];
+ const double value_converted = 100.0 * value_raw / crystal_hz / interval_float;
switch (ppmt->type) {
case PMT_TYPE_RAW:
if (pmt_counter_get_width(ppmt) <= 32)
@@ -2880,9 +2940,6 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data
break;
case PMT_TYPE_XTAL_TIME:
- const unsigned long value_raw = c->pmt_counter[i];
- const double value_converted = 100.0 * value_raw / crystal_hz / interval_float;
-
outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);
break;
}
@@ -3068,6 +3125,8 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data
}
for (i = 0, ppmt = sys.pmt_pp; ppmt; i++, ppmt = ppmt->next) {
+ const unsigned long value_raw = p->pmt_counter[i];
+ const double value_converted = 100.0 * value_raw / crystal_hz / interval_float;
switch (ppmt->type) {
case PMT_TYPE_RAW:
if (pmt_counter_get_width(ppmt) <= 32)
@@ -3079,14 +3138,18 @@ int format_counters(struct thread_data *t, struct core_data *c, struct pkg_data
break;
case PMT_TYPE_XTAL_TIME:
- const unsigned long value_raw = p->pmt_counter[i];
- const double value_converted = 100.0 * value_raw / crystal_hz / interval_float;
-
outp += sprintf(outp, "%s%.2f", (printed++ ? delim : ""), value_converted);
break;
}
}
+ if (DO_BIC(BIC_SysWatt) && (t == &average.threads))
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""),
+ rapl_counter_get_value(&pplat_cnt->energy_psys, RAPL_UNIT_WATTS, interval_float));
+ if (DO_BIC(BIC_Sys_J) && (t == &average.threads))
+ outp += sprintf(outp, fmt8, (printed++ ? delim : ""),
+ rapl_counter_get_value(&pplat_cnt->energy_psys, RAPL_UNIT_JOULES, interval_float));
+
done:
if (*(outp - 1) != '\n')
outp += sprintf(outp, "\n");
@@ -3394,6 +3457,11 @@ int delta_cpu(struct thread_data *t, struct core_data *c,
return retval;
}
+void delta_platform(struct platform_counters *new, struct platform_counters *old)
+{
+ old->energy_psys.raw_value = new->energy_psys.raw_value - old->energy_psys.raw_value;
+}
+
void rapl_counter_clear(struct rapl_counter *c)
{
c->raw_value = 0;
@@ -4123,6 +4191,9 @@ static size_t cstate_counter_info_count_perf(const struct cstate_counter_info_t
void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci, unsigned int idx)
{
+ if (rci->source[idx] == COUNTER_SOURCE_NONE)
+ return;
+
rc->raw_value = rci->data[idx];
rc->unit = rci->unit[idx];
rc->scale = rci->scale[idx];
@@ -4130,6 +4201,7 @@ void write_rapl_counter(struct rapl_counter *rc, struct rapl_counter_info_t *rci
int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct pkg_data *p)
{
+ struct platform_counters *pplat_cnt = p == package_odd ? &platform_counters_odd : &platform_counters_even;
unsigned long long perf_data[NUM_RAPL_COUNTERS + 1];
struct rapl_counter_info_t *rci;
@@ -4157,6 +4229,7 @@ int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct
for (unsigned int i = 0, pi = 1; i < NUM_RAPL_COUNTERS; ++i) {
switch (rci->source[i]) {
case COUNTER_SOURCE_NONE:
+ rci->data[i] = 0;
break;
case COUNTER_SOURCE_PERF:
@@ -4195,7 +4268,7 @@ int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct
}
}
- BUILD_BUG_ON(NUM_RAPL_COUNTERS != 7);
+ BUILD_BUG_ON(NUM_RAPL_COUNTERS != 8);
write_rapl_counter(&p->energy_pkg, rci, RAPL_RCI_INDEX_ENERGY_PKG);
write_rapl_counter(&p->energy_cores, rci, RAPL_RCI_INDEX_ENERGY_CORES);
write_rapl_counter(&p->energy_dram, rci, RAPL_RCI_INDEX_DRAM);
@@ -4203,6 +4276,7 @@ int get_rapl_counters(int cpu, unsigned int domain, struct core_data *c, struct
write_rapl_counter(&p->rapl_pkg_perf_status, rci, RAPL_RCI_INDEX_PKG_PERF_STATUS);
write_rapl_counter(&p->rapl_dram_perf_status, rci, RAPL_RCI_INDEX_DRAM_PERF_STATUS);
write_rapl_counter(&c->core_energy, rci, RAPL_RCI_INDEX_CORE_ENERGY);
+ write_rapl_counter(&pplat_cnt->energy_psys, rci, RAPL_RCI_INDEX_ENERGY_PLATFORM);
return 0;
}
@@ -5385,6 +5459,9 @@ static int parse_cpu_str(char *cpu_str, cpu_set_t *cpu_set, int cpu_set_size)
if (*next == '-') /* no negative cpu numbers */
return 1;
+ if (*next == '\0' || *next == '\n')
+ break;
+
start = strtoul(next, &next, 10);
if (start >= CPU_SUBSET_MAXCPUS)
@@ -5656,6 +5733,32 @@ int init_thread_id(int cpu)
return 0;
}
+int set_my_cpu_type(void)
+{
+ unsigned int eax, ebx, ecx, edx;
+ unsigned int max_level;
+
+ __cpuid(0, max_level, ebx, ecx, edx);
+
+ if (max_level < CPUID_LEAF_MODEL_ID)
+ return 0;
+
+ __cpuid(CPUID_LEAF_MODEL_ID, eax, ebx, ecx, edx);
+
+ return (eax >> CPUID_LEAF_MODEL_ID_CORE_TYPE_SHIFT);
+}
+
+int set_cpu_hybrid_type(int cpu)
+{
+ if (cpu_migrate(cpu))
+ return -1;
+
+ int type = set_my_cpu_type();
+
+ cpus[cpu].type = type;
+ return 0;
+}
+
/*
* snapshot_proc_interrupts()
*
@@ -5728,28 +5831,21 @@ int snapshot_proc_interrupts(void)
*/
int snapshot_graphics(int idx)
{
- FILE *fp;
int retval;
+ rewind(gfx_info[idx].fp);
+
switch (idx) {
case GFX_rc6:
case SAM_mc6:
- fp = fopen_or_die(gfx_info[idx].path, "r");
- retval = fscanf(fp, "%lld", &gfx_info[idx].val_ull);
+ retval = fscanf(gfx_info[idx].fp, "%lld", &gfx_info[idx].val_ull);
if (retval != 1)
err(1, "rc6");
- fclose(fp);
return 0;
case GFX_MHz:
case GFX_ACTMHz:
case SAM_MHz:
case SAM_ACTMHz:
- if (gfx_info[idx].fp == NULL) {
- gfx_info[idx].fp = fopen_or_die(gfx_info[idx].path, "r");
- } else {
- rewind(gfx_info[idx].fp);
- fflush(gfx_info[idx].fp);
- }
retval = fscanf(gfx_info[idx].fp, "%d", &gfx_info[idx].val);
if (retval != 1)
err(1, "MHz");
@@ -6116,6 +6212,7 @@ restart:
re_initialize();
goto restart;
}
+ delta_platform(&platform_counters_odd, &platform_counters_even);
compute_average(EVEN_COUNTERS);
format_all_counters(EVEN_COUNTERS);
flush_output_stdout();
@@ -6139,6 +6236,7 @@ restart:
re_initialize();
goto restart;
}
+ delta_platform(&platform_counters_even, &platform_counters_odd);
compute_average(ODD_COUNTERS);
format_all_counters(ODD_COUNTERS);
flush_output_stdout();
@@ -6442,14 +6540,25 @@ static void probe_intel_uncore_frequency(void)
probe_intel_uncore_frequency_legacy();
}
+static void set_graphics_fp(char *path, int idx)
+{
+ if (!access(path, R_OK))
+ gfx_info[idx].fp = fopen_or_die(path, "r");
+}
+
+/* Enlarge this if there are /sys/class/drm/card2 ... */
+#define GFX_MAX_CARDS 2
+
static void probe_graphics(void)
{
+ char path[PATH_MAX];
+ int i;
+
/* Xe graphics sysfs knobs */
if (!access("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", R_OK)) {
FILE *fp;
char buf[8];
bool gt0_is_gt;
- int idx;
fp = fopen("/sys/class/drm/card0/device/tile0/gt0/gtidle/name", "r");
if (!fp)
@@ -6468,81 +6577,76 @@ static void probe_graphics(void)
else
goto next;
- idx = gt0_is_gt ? GFX_rc6 : SAM_mc6;
- gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms";
+ set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/gtidle/idle_residency_ms", gt0_is_gt ? GFX_rc6 : SAM_mc6);
- idx = gt0_is_gt ? GFX_MHz : SAM_MHz;
- if (!access("/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq", R_OK))
- gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq";
+ set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/cur_freq", gt0_is_gt ? GFX_MHz : SAM_MHz);
- idx = gt0_is_gt ? GFX_ACTMHz : SAM_ACTMHz;
- if (!access("/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq", R_OK))
- gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq";
+ set_graphics_fp("/sys/class/drm/card0/device/tile0/gt0/freq0/act_freq", gt0_is_gt ? GFX_ACTMHz : SAM_ACTMHz);
- idx = gt0_is_gt ? SAM_mc6 : GFX_rc6;
- if (!access("/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms", R_OK))
- gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms";
+ set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/gtidle/idle_residency_ms", gt0_is_gt ? SAM_mc6 : GFX_rc6);
- idx = gt0_is_gt ? SAM_MHz : GFX_MHz;
- if (!access("/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq", R_OK))
- gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq";
+ set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/cur_freq", gt0_is_gt ? SAM_MHz : GFX_MHz);
- idx = gt0_is_gt ? SAM_ACTMHz : GFX_ACTMHz;
- if (!access("/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq", R_OK))
- gfx_info[idx].path = "/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq";
+ set_graphics_fp("/sys/class/drm/card0/device/tile0/gt1/freq0/act_freq", gt0_is_gt ? SAM_ACTMHz : GFX_ACTMHz);
goto end;
}
next:
/* New i915 graphics sysfs knobs */
- if (!access("/sys/class/drm/card0/gt/gt0/rc6_residency_ms", R_OK)) {
- gfx_info[GFX_rc6].path = "/sys/class/drm/card0/gt/gt0/rc6_residency_ms";
+ for (i = 0; i < GFX_MAX_CARDS; i++) {
+ snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rc6_residency_ms", i);
+ if (!access(path, R_OK))
+ break;
+ }
- if (!access("/sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz", R_OK))
- gfx_info[GFX_MHz].path = "/sys/class/drm/card0/gt/gt0/rps_cur_freq_mhz";
+ if (i == GFX_MAX_CARDS)
+ goto legacy_i915;
- if (!access("/sys/class/drm/card0/gt/gt0/rps_act_freq_mhz", R_OK))
- gfx_info[GFX_ACTMHz].path = "/sys/class/drm/card0/gt/gt0/rps_act_freq_mhz";
+ snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rc6_residency_ms", i);
+ set_graphics_fp(path, GFX_rc6);
- if (!access("/sys/class/drm/card0/gt/gt1/rc6_residency_ms", R_OK))
- gfx_info[SAM_mc6].path = "/sys/class/drm/card0/gt/gt1/rc6_residency_ms";
+ snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rps_cur_freq_mhz", i);
+ set_graphics_fp(path, GFX_MHz);
- if (!access("/sys/class/drm/card0/gt/gt1/rps_cur_freq_mhz", R_OK))
- gfx_info[SAM_MHz].path = "/sys/class/drm/card0/gt/gt1/rps_cur_freq_mhz";
+ snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt0/rps_act_freq_mhz", i);
+ set_graphics_fp(path, GFX_ACTMHz);
- if (!access("/sys/class/drm/card0/gt/gt1/rps_act_freq_mhz", R_OK))
- gfx_info[SAM_ACTMHz].path = "/sys/class/drm/card0/gt/gt1/rps_act_freq_mhz";
+ snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rc6_residency_ms", i);
+ set_graphics_fp(path, SAM_mc6);
- goto end;
- }
+ snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rps_cur_freq_mhz", i);
+ set_graphics_fp(path, SAM_MHz);
+
+ snprintf(path, PATH_MAX, "/sys/class/drm/card%d/gt/gt1/rps_act_freq_mhz", i);
+ set_graphics_fp(path, SAM_ACTMHz);
+ goto end;
+
+legacy_i915:
/* Fall back to traditional i915 graphics sysfs knobs */
- if (!access("/sys/class/drm/card0/power/rc6_residency_ms", R_OK))
- gfx_info[GFX_rc6].path = "/sys/class/drm/card0/power/rc6_residency_ms";
+ set_graphics_fp("/sys/class/drm/card0/power/rc6_residency_ms", GFX_rc6);
- if (!access("/sys/class/drm/card0/gt_cur_freq_mhz", R_OK))
- gfx_info[GFX_MHz].path = "/sys/class/drm/card0/gt_cur_freq_mhz";
- else if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", R_OK))
- gfx_info[GFX_MHz].path = "/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz";
+ set_graphics_fp("/sys/class/drm/card0/gt_cur_freq_mhz", GFX_MHz);
+ if (!gfx_info[GFX_MHz].fp)
+ set_graphics_fp("/sys/class/graphics/fb0/device/drm/card0/gt_cur_freq_mhz", GFX_MHz);
- if (!access("/sys/class/drm/card0/gt_act_freq_mhz", R_OK))
- gfx_info[GFX_ACTMHz].path = "/sys/class/drm/card0/gt_act_freq_mhz";
- else if (!access("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", R_OK))
- gfx_info[GFX_ACTMHz].path = "/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz";
+ set_graphics_fp("/sys/class/drm/card0/gt_act_freq_mhz", GFX_ACTMHz);
+ if (!gfx_info[GFX_ACTMHz].fp)
+ set_graphics_fp("/sys/class/graphics/fb0/device/drm/card0/gt_act_freq_mhz", GFX_ACTMHz);
end:
- if (gfx_info[GFX_rc6].path)
+ if (gfx_info[GFX_rc6].fp)
BIC_PRESENT(BIC_GFX_rc6);
- if (gfx_info[GFX_MHz].path)
+ if (gfx_info[GFX_MHz].fp)
BIC_PRESENT(BIC_GFXMHz);
- if (gfx_info[GFX_ACTMHz].path)
+ if (gfx_info[GFX_ACTMHz].fp)
BIC_PRESENT(BIC_GFXACTMHz);
- if (gfx_info[SAM_mc6].path)
+ if (gfx_info[SAM_mc6].fp)
BIC_PRESENT(BIC_SAM_mc6);
- if (gfx_info[SAM_MHz].path)
+ if (gfx_info[SAM_MHz].fp)
BIC_PRESENT(BIC_SAMMHz);
- if (gfx_info[SAM_ACTMHz].path)
+ if (gfx_info[SAM_ACTMHz].fp)
BIC_PRESENT(BIC_SAMACTMHz);
}
@@ -6911,8 +7015,8 @@ void rapl_probe_intel(void)
unsigned long long msr;
unsigned int time_unit;
double tdp;
- const unsigned long long bic_watt_bits = BIC_PkgWatt | BIC_CorWatt | BIC_RAMWatt | BIC_GFXWatt;
- const unsigned long long bic_joules_bits = BIC_Pkg_J | BIC_Cor_J | BIC_RAM_J | BIC_GFX_J;
+ const unsigned long long bic_watt_bits = BIC_SysWatt | BIC_PkgWatt | BIC_CorWatt | BIC_RAMWatt | BIC_GFXWatt;
+ const unsigned long long bic_joules_bits = BIC_Sys_J | BIC_Pkg_J | BIC_Cor_J | BIC_RAM_J | BIC_GFX_J;
if (rapl_joules)
bic_enabled &= ~bic_watt_bits;
@@ -7572,6 +7676,9 @@ void rapl_perf_init(void)
domain_visited[next_domain] = 1;
+ if ((cai->flags & RAPL_COUNTER_FLAG_PLATFORM_COUNTER) && (cpu != base_cpu))
+ continue;
+
struct rapl_counter_info_t *rci = &rapl_counter_info_perdomain[next_domain];
/* Check if the counter is enabled and accessible */
@@ -8196,7 +8303,7 @@ void topology_probe(bool startup)
set_max_cpu_num();
topo.num_cpus = 0;
for_all_proc_cpus(count_cpus);
- if (!summary_only && topo.num_cpus > 1)
+ if (!summary_only)
BIC_PRESENT(BIC_CPU);
if (debug > 1)
@@ -8284,6 +8391,8 @@ void topology_probe(bool startup)
for_all_proc_cpus(init_thread_id);
+ for_all_proc_cpus(set_cpu_hybrid_type);
+
/*
* For online cpus
* find max_core_id, max_package_id
@@ -8332,7 +8441,7 @@ void topology_probe(bool startup)
topo.cores_per_node = max_core_id + 1;
if (debug > 1)
fprintf(outf, "max_core_id %d, sizing for %d cores per package\n", max_core_id, topo.cores_per_node);
- if (!summary_only && topo.cores_per_node > 1)
+ if (!summary_only)
BIC_PRESENT(BIC_Core);
topo.num_die = topo.max_die_id + 1;
@@ -8548,6 +8657,35 @@ void check_perf_access(void)
bic_enabled &= ~BIC_IPC;
}
+bool perf_has_hybrid_devices(void)
+{
+ /*
+ * 0: unknown
+ * 1: has separate perf device for p and e core
+ * -1: doesn't have separate perf device for p and e core
+ */
+ static int cached;
+
+ if (cached > 0)
+ return true;
+
+ if (cached < 0)
+ return false;
+
+ if (access("/sys/bus/event_source/devices/cpu_core", F_OK)) {
+ cached = -1;
+ return false;
+ }
+
+ if (access("/sys/bus/event_source/devices/cpu_atom", F_OK)) {
+ cached = -1;
+ return false;
+ }
+
+ cached = 1;
+ return true;
+}
+
int added_perf_counters_init_(struct perf_counter_info *pinfo)
{
size_t num_domains = 0;
@@ -8604,29 +8742,56 @@ int added_perf_counters_init_(struct perf_counter_info *pinfo)
if (domain_visited[next_domain])
continue;
- perf_type = read_perf_type(pinfo->device);
+ /*
+ * Intel hybrid platforms expose different perf devices for P and E cores.
+ * Instead of one, "/sys/bus/event_source/devices/cpu" device, there are
+ * "/sys/bus/event_source/devices/{cpu_core,cpu_atom}".
+ *
+ * This makes it more complicated to the user, because most of the counters
+ * are available on both and have to be handled manually, otherwise.
+ *
+ * Code below, allow user to use the old "cpu" name, which is translated accordingly.
+ */
+ const char *perf_device = pinfo->device;
+
+ if (strcmp(perf_device, "cpu") == 0 && perf_has_hybrid_devices()) {
+ switch (cpus[cpu].type) {
+ case INTEL_PCORE_TYPE:
+ perf_device = "cpu_core";
+ break;
+
+ case INTEL_ECORE_TYPE:
+ perf_device = "cpu_atom";
+ break;
+
+ default: /* Don't change, we will probably fail and report a problem soon. */
+ break;
+ }
+ }
+
+ perf_type = read_perf_type(perf_device);
if (perf_type == (unsigned int)-1) {
warnx("%s: perf/%s/%s: failed to read %s",
- __func__, pinfo->device, pinfo->event, "type");
+ __func__, perf_device, pinfo->event, "type");
continue;
}
- perf_config = read_perf_config(pinfo->device, pinfo->event);
+ perf_config = read_perf_config(perf_device, pinfo->event);
if (perf_config == (unsigned int)-1) {
warnx("%s: perf/%s/%s: failed to read %s",
- __func__, pinfo->device, pinfo->event, "config");
+ __func__, perf_device, pinfo->event, "config");
continue;
}
/* Scale is not required, some counters just don't have it. */
- perf_scale = read_perf_scale(pinfo->device, pinfo->event);
+ perf_scale = read_perf_scale(perf_device, pinfo->event);
if (perf_scale == 0.0)
perf_scale = 1.0;
fd_perf = open_perf_counter(cpu, perf_type, perf_config, -1, 0);
if (fd_perf == -1) {
warnx("%s: perf/%s/%s: failed to open counter on cpu%d",
- __func__, pinfo->device, pinfo->event, cpu);
+ __func__, perf_device, pinfo->event, cpu);
continue;
}
@@ -8636,7 +8801,7 @@ int added_perf_counters_init_(struct perf_counter_info *pinfo)
if (debug)
fprintf(stderr, "Add perf/%s/%s cpu%d: %d\n",
- pinfo->device, pinfo->event, cpu, pinfo->fd_perf_per_domain[next_domain]);
+ perf_device, pinfo->event, cpu, pinfo->fd_perf_per_domain[next_domain]);
}
pinfo = pinfo->next;
@@ -9071,7 +9236,7 @@ int get_and_dump_counters(void)
void print_version()
{
- fprintf(outf, "turbostat version 2024.07.26 - Len Brown <lenb@kernel.org>\n");
+ fprintf(outf, "turbostat version 2024.11.30 - Len Brown <lenb@kernel.org>\n");
}
#define COMMAND_LINE_SIZE 2048
@@ -9781,7 +9946,7 @@ void cmdline(int argc, char **argv)
* Parse some options early, because they may make other options invalid,
* like adding the MSR counter with --add and at the same time using --no-msr.
*/
- while ((opt = getopt_long_only(argc, argv, "MPn:", long_options, &option_index)) != -1) {
+ while ((opt = getopt_long_only(argc, argv, "+MPn:", long_options, &option_index)) != -1) {
switch (opt) {
case 'M':
no_msr = 1;
@@ -9805,6 +9970,12 @@ void cmdline(int argc, char **argv)
break;
case 'D':
dump_only++;
+ /*
+ * Force the no_perf early to prevent using it as a source.
+ * User asks for raw values, but perf returns them relative
+ * to the opening of the file descriptor.
+ */
+ no_perf = 1;
break;
case 'e':
/* --enable specified counter */
diff --git a/tools/sched_ext/include/scx/common.bpf.h b/tools/sched_ext/include/scx/common.bpf.h
index 2f36b7b6418d..625f5b046776 100644
--- a/tools/sched_ext/include/scx/common.bpf.h
+++ b/tools/sched_ext/include/scx/common.bpf.h
@@ -40,9 +40,9 @@ void scx_bpf_dsq_insert(struct task_struct *p, u64 dsq_id, u64 slice, u64 enq_fl
void scx_bpf_dsq_insert_vtime(struct task_struct *p, u64 dsq_id, u64 slice, u64 vtime, u64 enq_flags) __ksym __weak;
u32 scx_bpf_dispatch_nr_slots(void) __ksym;
void scx_bpf_dispatch_cancel(void) __ksym;
-bool scx_bpf_dsq_move_to_local(u64 dsq_id) __ksym;
-void scx_bpf_dsq_move_set_slice(struct bpf_iter_scx_dsq *it__iter, u64 slice) __ksym;
-void scx_bpf_dsq_move_set_vtime(struct bpf_iter_scx_dsq *it__iter, u64 vtime) __ksym;
+bool scx_bpf_dsq_move_to_local(u64 dsq_id) __ksym __weak;
+void scx_bpf_dsq_move_set_slice(struct bpf_iter_scx_dsq *it__iter, u64 slice) __ksym __weak;
+void scx_bpf_dsq_move_set_vtime(struct bpf_iter_scx_dsq *it__iter, u64 vtime) __ksym __weak;
bool scx_bpf_dsq_move(struct bpf_iter_scx_dsq *it__iter, struct task_struct *p, u64 dsq_id, u64 enq_flags) __ksym __weak;
bool scx_bpf_dsq_move_vtime(struct bpf_iter_scx_dsq *it__iter, struct task_struct *p, u64 dsq_id, u64 enq_flags) __ksym __weak;
u32 scx_bpf_reenqueue_local(void) __ksym;
diff --git a/tools/sched_ext/scx_central.c b/tools/sched_ext/scx_central.c
index 21deea320bd7..e938156ed0a0 100644
--- a/tools/sched_ext/scx_central.c
+++ b/tools/sched_ext/scx_central.c
@@ -97,7 +97,7 @@ restart:
SCX_BUG_ON(!cpuset, "Failed to allocate cpuset");
CPU_ZERO(cpuset);
CPU_SET(skel->rodata->central_cpu, cpuset);
- SCX_BUG_ON(sched_setaffinity(0, sizeof(cpuset), cpuset),
+ SCX_BUG_ON(sched_setaffinity(0, sizeof(*cpuset), cpuset),
"Failed to affinitize to central CPU %d (max %d)",
skel->rodata->central_cpu, skel->rodata->nr_cpu_ids - 1);
CPU_FREE(cpuset);
diff --git a/tools/scripts/Makefile.arch b/tools/scripts/Makefile.arch
index f6a50f06dfc4..eabfe9f411d9 100644
--- a/tools/scripts/Makefile.arch
+++ b/tools/scripts/Makefile.arch
@@ -7,8 +7,8 @@ HOSTARCH := $(shell uname -m | sed -e s/i.86/x86/ -e s/x86_64/x86/ \
-e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ \
-e s/riscv.*/riscv/ -e s/loongarch.*/loongarch/)
-ifndef ARCH
-ARCH := $(HOSTARCH)
+ifeq ($(strip $(ARCH)),)
+override ARCH := $(HOSTARCH)
endif
SRCARCH := $(ARCH)
diff --git a/tools/testing/cxl/cxl_core_exports.c b/tools/testing/cxl/cxl_core_exports.c
index 077e6883921d..f088792a8925 100644
--- a/tools/testing/cxl/cxl_core_exports.c
+++ b/tools/testing/cxl/cxl_core_exports.c
@@ -4,4 +4,4 @@
#include "cxl.h"
/* Exporting of cxl_core symbols that are only used by cxl_test */
-EXPORT_SYMBOL_NS_GPL(cxl_num_decoders_committed, CXL);
+EXPORT_SYMBOL_NS_GPL(cxl_num_decoders_committed, "CXL");
diff --git a/tools/testing/cxl/test/cxl.c b/tools/testing/cxl/test/cxl.c
index 050725afa45d..d0337c11f9ee 100644
--- a/tools/testing/cxl/test/cxl.c
+++ b/tools/testing/cxl/test/cxl.c
@@ -1531,5 +1531,5 @@ MODULE_PARM_DESC(interleave_arithmetic, "Modulo:0, XOR:1");
module_init(cxl_test_init);
module_exit(cxl_test_exit);
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(ACPI);
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("ACPI");
+MODULE_IMPORT_NS("CXL");
diff --git a/tools/testing/cxl/test/mem.c b/tools/testing/cxl/test/mem.c
index 71916e0e1546..347c1e7b37bd 100644
--- a/tools/testing/cxl/test/mem.c
+++ b/tools/testing/cxl/test/mem.c
@@ -1679,4 +1679,4 @@ static struct platform_driver cxl_mock_mem_driver = {
module_platform_driver(cxl_mock_mem_driver);
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("CXL");
diff --git a/tools/testing/cxl/test/mock.c b/tools/testing/cxl/test/mock.c
index f4ce96cc11d4..450c7566c33f 100644
--- a/tools/testing/cxl/test/mock.c
+++ b/tools/testing/cxl/test/mock.c
@@ -76,7 +76,7 @@ int __wrap_acpi_table_parse_cedt(enum acpi_cedt_type id,
return rc;
}
-EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, ACPI);
+EXPORT_SYMBOL_NS_GPL(__wrap_acpi_table_parse_cedt, "ACPI");
acpi_status __wrap_acpi_evaluate_integer(acpi_handle handle,
acpi_string pathname,
@@ -147,7 +147,7 @@ struct cxl_hdm *__wrap_devm_cxl_setup_hdm(struct cxl_port *port,
return cxlhdm;
}
-EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_setup_hdm, "CXL");
int __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port)
{
@@ -162,7 +162,7 @@ int __wrap_devm_cxl_add_passthrough_decoder(struct cxl_port *port)
return rc;
}
-EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_passthrough_decoder, "CXL");
int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
struct cxl_endpoint_dvsec_info *info)
@@ -179,7 +179,7 @@ int __wrap_devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
return rc;
}
-EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enumerate_decoders, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_enumerate_decoders, "CXL");
int __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port)
{
@@ -194,7 +194,7 @@ int __wrap_devm_cxl_port_enumerate_dports(struct cxl_port *port)
return rc;
}
-EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_port_enumerate_dports, "CXL");
int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds)
{
@@ -209,7 +209,7 @@ int __wrap_cxl_await_media_ready(struct cxl_dev_state *cxlds)
return rc;
}
-EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_cxl_await_media_ready, "CXL");
int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds,
struct cxl_hdm *cxlhdm,
@@ -226,7 +226,7 @@ int __wrap_cxl_hdm_decode_init(struct cxl_dev_state *cxlds,
return rc;
}
-EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_cxl_hdm_decode_init, "CXL");
int __wrap_cxl_dvsec_rr_decode(struct device *dev, struct cxl_port *port,
struct cxl_endpoint_dvsec_info *info)
@@ -242,7 +242,7 @@ int __wrap_cxl_dvsec_rr_decode(struct device *dev, struct cxl_port *port,
return rc;
}
-EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dvsec_rr_decode, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dvsec_rr_decode, "CXL");
struct cxl_dport *__wrap_devm_cxl_add_rch_dport(struct cxl_port *port,
struct device *dport_dev,
@@ -266,7 +266,7 @@ struct cxl_dport *__wrap_devm_cxl_add_rch_dport(struct cxl_port *port,
return dport;
}
-EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_devm_cxl_add_rch_dport, "CXL");
resource_size_t __wrap_cxl_rcd_component_reg_phys(struct device *dev,
struct cxl_dport *dport)
@@ -283,7 +283,7 @@ resource_size_t __wrap_cxl_rcd_component_reg_phys(struct device *dev,
return component_reg_phys;
}
-EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_cxl_rcd_component_reg_phys, "CXL");
void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port)
{
@@ -297,7 +297,7 @@ void __wrap_cxl_endpoint_parse_cdat(struct cxl_port *port)
cxl_endpoint_parse_cdat(port);
put_cxl_mock_ops(index);
}
-EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_cxl_endpoint_parse_cdat, "CXL");
void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device *host)
{
@@ -309,8 +309,8 @@ void __wrap_cxl_dport_init_ras_reporting(struct cxl_dport *dport, struct device
put_cxl_mock_ops(index);
}
-EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dport_init_ras_reporting, CXL);
+EXPORT_SYMBOL_NS_GPL(__wrap_cxl_dport_init_ras_reporting, "CXL");
MODULE_LICENSE("GPL v2");
-MODULE_IMPORT_NS(ACPI);
-MODULE_IMPORT_NS(CXL);
+MODULE_IMPORT_NS("ACPI");
+MODULE_IMPORT_NS("CXL");
diff --git a/tools/testing/nvdimm/test/ndtest.c b/tools/testing/nvdimm/test/ndtest.c
index 892e990c034a..68a064ce598c 100644
--- a/tools/testing/nvdimm/test/ndtest.c
+++ b/tools/testing/nvdimm/test/ndtest.c
@@ -883,7 +883,7 @@ static const struct platform_device_id ndtest_id[] = {
static struct platform_driver ndtest_driver = {
.probe = ndtest_probe,
- .remove_new = ndtest_remove,
+ .remove = ndtest_remove,
.driver = {
.name = KBUILD_MODNAME,
},
diff --git a/tools/testing/selftests/alsa/.gitignore b/tools/testing/selftests/alsa/.gitignore
index 12dc3fcd3456..3dd8e1176b89 100644
--- a/tools/testing/selftests/alsa/.gitignore
+++ b/tools/testing/selftests/alsa/.gitignore
@@ -1,3 +1,5 @@
+global-timer
mixer-test
pcm-test
test-pcmtest-driver
+utimer-test
diff --git a/tools/testing/selftests/alsa/Makefile b/tools/testing/selftests/alsa/Makefile
index 944279160fed..8dab90ad22bb 100644
--- a/tools/testing/selftests/alsa/Makefile
+++ b/tools/testing/selftests/alsa/Makefile
@@ -27,5 +27,5 @@ include ../lib.mk
$(OUTPUT)/libatest.so: conf.c alsa-local.h
$(CC) $(CFLAGS) -shared -fPIC $< $(LDLIBS) -o $@
-$(OUTPUT)/%: %.c $(TEST_GEN_PROGS_EXTENDED) alsa-local.h
+$(OUTPUT)/%: %.c $(OUTPUT)/libatest.so alsa-local.h
$(CC) $(CFLAGS) $< $(LDLIBS) -latest -o $@
diff --git a/tools/testing/selftests/arm64/abi/syscall-abi-asm.S b/tools/testing/selftests/arm64/abi/syscall-abi-asm.S
index df3230fdac39..66ab2e0bae5f 100644
--- a/tools/testing/selftests/arm64/abi/syscall-abi-asm.S
+++ b/tools/testing/selftests/arm64/abi/syscall-abi-asm.S
@@ -81,32 +81,31 @@ do_syscall:
stp x27, x28, [sp, #96]
// Set SVCR if we're doing SME
- cbz x1, 1f
+ cbz x1, load_gpr
adrp x2, svcr_in
ldr x2, [x2, :lo12:svcr_in]
msr S3_3_C4_C2_2, x2
-1:
// Load ZA and ZT0 if enabled - uses x12 as scratch due to SME LDR
- tbz x2, #SVCR_ZA_SHIFT, 1f
+ tbz x2, #SVCR_ZA_SHIFT, load_gpr
mov w12, #0
ldr x2, =za_in
-2: _ldr_za 12, 2
+1: _ldr_za 12, 2
add x2, x2, x1
add x12, x12, #1
cmp x1, x12
- bne 2b
+ bne 1b
// ZT0
mrs x2, S3_0_C0_C4_5 // ID_AA64SMFR0_EL1
ubfx x2, x2, #ID_AA64SMFR0_EL1_SMEver_SHIFT, \
#ID_AA64SMFR0_EL1_SMEver_WIDTH
- cbz x2, 1f
+ cbz x2, load_gpr
adrp x2, zt_in
add x2, x2, :lo12:zt_in
_ldr_zt 2
-1:
+load_gpr:
// Load GPRs x8-x28, and save our SP/FP for later comparison
ldr x2, =gpr_in
add x2, x2, #64
@@ -125,9 +124,9 @@ do_syscall:
str x30, [x2], #8 // LR
// Load FPRs if we're not doing neither SVE nor streaming SVE
- cbnz x0, 1f
+ cbnz x0, check_sve_in
ldr x2, =svcr_in
- tbnz x2, #SVCR_SM_SHIFT, 1f
+ tbnz x2, #SVCR_SM_SHIFT, check_sve_in
ldr x2, =fpr_in
ldp q0, q1, [x2]
@@ -148,8 +147,8 @@ do_syscall:
ldp q30, q31, [x2, #16 * 30]
b 2f
-1:
+check_sve_in:
// Load the SVE registers if we're doing SVE/SME
ldr x2, =z_in
@@ -256,32 +255,31 @@ do_syscall:
stp q30, q31, [x2, #16 * 30]
// Save SVCR if we're doing SME
- cbz x1, 1f
+ cbz x1, check_sve_out
mrs x2, S3_3_C4_C2_2
adrp x3, svcr_out
str x2, [x3, :lo12:svcr_out]
-1:
// Save ZA if it's enabled - uses x12 as scratch due to SME STR
- tbz x2, #SVCR_ZA_SHIFT, 1f
+ tbz x2, #SVCR_ZA_SHIFT, check_sve_out
mov w12, #0
ldr x2, =za_out
-2: _str_za 12, 2
+1: _str_za 12, 2
add x2, x2, x1
add x12, x12, #1
cmp x1, x12
- bne 2b
+ bne 1b
// ZT0
mrs x2, S3_0_C0_C4_5 // ID_AA64SMFR0_EL1
ubfx x2, x2, #ID_AA64SMFR0_EL1_SMEver_SHIFT, \
#ID_AA64SMFR0_EL1_SMEver_WIDTH
- cbz x2, 1f
+ cbz x2, check_sve_out
adrp x2, zt_out
add x2, x2, :lo12:zt_out
_str_zt 2
-1:
+check_sve_out:
// Save the SVE state if we have some
cbz x0, 1f
diff --git a/tools/testing/selftests/bpf/.gitignore b/tools/testing/selftests/bpf/.gitignore
index c2a1842c3d8b..e9c377001f93 100644
--- a/tools/testing/selftests/bpf/.gitignore
+++ b/tools/testing/selftests/bpf/.gitignore
@@ -5,7 +5,6 @@ bpf-syscall*
test_verifier
test_maps
test_lru_map
-test_lpm_map
test_tag
FEATURE-DUMP.libbpf
FEATURE-DUMP.selftests
diff --git a/tools/testing/selftests/bpf/Makefile b/tools/testing/selftests/bpf/Makefile
index 6ad3b1ba1920..0a016cd71cba 100644
--- a/tools/testing/selftests/bpf/Makefile
+++ b/tools/testing/selftests/bpf/Makefile
@@ -83,7 +83,7 @@ CLANG_CPUV4 := 1
endif
# Order correspond to 'make run_tests' order
-TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_lpm_map test_progs \
+TEST_GEN_PROGS = test_verifier test_tag test_maps test_lru_map test_progs \
test_sockmap \
test_tcpnotify_user test_sysctl \
test_progs-no_alu32
@@ -129,7 +129,6 @@ TEST_FILES = xsk_prereqs.sh $(wildcard progs/btf_dump_test_case_*.c)
TEST_PROGS := test_kmod.sh \
test_xdp_redirect.sh \
test_xdp_redirect_multi.sh \
- test_xdp_meta.sh \
test_tunnel.sh \
test_lwt_seg6local.sh \
test_lirc_mode2.sh \
diff --git a/tools/testing/selftests/bpf/test_lpm_map.c b/tools/testing/selftests/bpf/map_tests/lpm_trie_map_basic_ops.c
index d98c72dc563e..d32e4edac930 100644
--- a/tools/testing/selftests/bpf/test_lpm_map.c
+++ b/tools/testing/selftests/bpf/map_tests/lpm_trie_map_basic_ops.c
@@ -20,10 +20,12 @@
#include <string.h>
#include <time.h>
#include <unistd.h>
+#include <endian.h>
#include <arpa/inet.h>
#include <sys/time.h>
#include <bpf/bpf.h>
+#include <test_maps.h>
#include "bpf_util.h"
@@ -33,6 +35,22 @@ struct tlpm_node {
uint8_t key[];
};
+struct lpm_trie_bytes_key {
+ union {
+ struct bpf_lpm_trie_key_hdr hdr;
+ __u32 prefixlen;
+ };
+ unsigned char data[8];
+};
+
+struct lpm_trie_int_key {
+ union {
+ struct bpf_lpm_trie_key_hdr hdr;
+ __u32 prefixlen;
+ };
+ unsigned int data;
+};
+
static struct tlpm_node *tlpm_match(struct tlpm_node *list,
const uint8_t *key,
size_t n_bits);
@@ -223,7 +241,7 @@ static void test_lpm_map(int keysize)
n_matches = 0;
n_matches_after_delete = 0;
n_nodes = 1 << 8;
- n_lookups = 1 << 16;
+ n_lookups = 1 << 9;
data = alloca(keysize);
memset(data, 0, keysize);
@@ -770,16 +788,385 @@ static void test_lpm_multi_thread(void)
close(map_fd);
}
-int main(void)
+static int lpm_trie_create(unsigned int key_size, unsigned int value_size, unsigned int max_entries)
+{
+ LIBBPF_OPTS(bpf_map_create_opts, opts);
+ int fd;
+
+ opts.map_flags = BPF_F_NO_PREALLOC;
+ fd = bpf_map_create(BPF_MAP_TYPE_LPM_TRIE, "lpm_trie", key_size, value_size, max_entries,
+ &opts);
+ CHECK(fd < 0, "bpf_map_create", "error %d\n", errno);
+
+ return fd;
+}
+
+static void test_lpm_trie_update_flags(void)
+{
+ struct lpm_trie_int_key key;
+ unsigned int value, got;
+ int fd, err;
+
+ fd = lpm_trie_create(sizeof(key), sizeof(value), 3);
+
+ /* invalid flags (Error) */
+ key.prefixlen = 32;
+ key.data = 0;
+ value = 0;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_F_LOCK);
+ CHECK(err != -EINVAL, "invalid update flag", "error %d\n", err);
+
+ /* invalid flags (Error) */
+ key.prefixlen = 32;
+ key.data = 0;
+ value = 0;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST | BPF_EXIST);
+ CHECK(err != -EINVAL, "invalid update flag", "error %d\n", err);
+
+ /* overwrite an empty qp-trie (Error) */
+ key.prefixlen = 32;
+ key.data = 0;
+ value = 2;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_EXIST);
+ CHECK(err != -ENOENT, "overwrite empty qp-trie", "error %d\n", err);
+
+ /* add a new node */
+ key.prefixlen = 16;
+ key.data = 0;
+ value = 1;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
+ CHECK(err, "add new elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup elem", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ /* add the same node as new node (Error) */
+ err = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
+ CHECK(err != -EEXIST, "add new elem again", "error %d\n", err);
+
+ /* overwrite the existed node */
+ value = 4;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_EXIST);
+ CHECK(err, "overwrite elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup elem", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ /* overwrite the node */
+ value = 1;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_ANY);
+ CHECK(err, "update elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup elem", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ /* overwrite a non-existent node which is the prefix of the first
+ * node (Error).
+ */
+ key.prefixlen = 8;
+ key.data = 0;
+ value = 2;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_EXIST);
+ CHECK(err != -ENOENT, "overwrite nonexistent elem", "error %d\n", err);
+
+ /* add a new node which is the prefix of the first node */
+ err = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
+ CHECK(err, "add new elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup key", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ /* add another new node which will be the sibling of the first node */
+ key.prefixlen = 9;
+ key.data = htobe32(1 << 23);
+ value = 5;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
+ CHECK(err, "add new elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup key", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ /* overwrite the third node */
+ value = 3;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_ANY);
+ CHECK(err, "overwrite elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup key", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ /* delete the second node to make it an intermediate node */
+ key.prefixlen = 8;
+ key.data = 0;
+ err = bpf_map_delete_elem(fd, &key);
+ CHECK(err, "del elem", "error %d\n", err);
+
+ /* overwrite the intermediate node (Error) */
+ value = 2;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_EXIST);
+ CHECK(err != -ENOENT, "overwrite nonexistent elem", "error %d\n", err);
+
+ close(fd);
+}
+
+static void test_lpm_trie_update_full_map(void)
+{
+ struct lpm_trie_int_key key;
+ int value, got;
+ int fd, err;
+
+ fd = lpm_trie_create(sizeof(key), sizeof(value), 3);
+
+ /* add a new node */
+ key.prefixlen = 16;
+ key.data = 0;
+ value = 0;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
+ CHECK(err, "add new elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup elem", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ /* add new node */
+ key.prefixlen = 8;
+ key.data = 0;
+ value = 1;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
+ CHECK(err, "add new elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup elem", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ /* add new node */
+ key.prefixlen = 9;
+ key.data = htobe32(1 << 23);
+ value = 2;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
+ CHECK(err, "add new elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup elem", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ /* try to add more node (Error) */
+ key.prefixlen = 32;
+ key.data = 0;
+ value = 3;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_ANY);
+ CHECK(err != -ENOSPC, "add to full trie", "error %d\n", err);
+
+ /* update the value of an existed node with BPF_EXIST */
+ key.prefixlen = 16;
+ key.data = 0;
+ value = 4;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_EXIST);
+ CHECK(err, "overwrite elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup elem", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ /* update the value of an existed node with BPF_ANY */
+ key.prefixlen = 9;
+ key.data = htobe32(1 << 23);
+ value = 5;
+ err = bpf_map_update_elem(fd, &key, &value, BPF_ANY);
+ CHECK(err, "overwrite elem", "error %d\n", err);
+ got = 0;
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup elem", "error %d\n", err);
+ CHECK(got != value, "check value", "got %d exp %d\n", got, value);
+
+ close(fd);
+}
+
+static int cmp_str(const void *a, const void *b)
+{
+ const char *str_a = *(const char **)a, *str_b = *(const char **)b;
+
+ return strcmp(str_a, str_b);
+}
+
+/* Save strings in LPM trie. The trailing '\0' for each string will be
+ * accounted in the prefixlen. The strings returned during the iteration
+ * should be sorted as expected.
+ */
+static void test_lpm_trie_iterate_strs(void)
+{
+ static const char * const keys[] = {
+ "ab", "abO", "abc", "abo", "abS", "abcd",
+ };
+ const char *sorted_keys[ARRAY_SIZE(keys)];
+ struct lpm_trie_bytes_key key, next_key;
+ unsigned int value, got, i, j, len;
+ struct lpm_trie_bytes_key *cur;
+ int fd, err;
+
+ fd = lpm_trie_create(sizeof(key), sizeof(value), ARRAY_SIZE(keys));
+
+ for (i = 0; i < ARRAY_SIZE(keys); i++) {
+ unsigned int flags;
+
+ /* add i-th element */
+ flags = i % 2 ? BPF_NOEXIST : 0;
+ len = strlen(keys[i]);
+ /* include the trailing '\0' */
+ key.prefixlen = (len + 1) * 8;
+ memset(key.data, 0, sizeof(key.data));
+ memcpy(key.data, keys[i], len);
+ value = i + 100;
+ err = bpf_map_update_elem(fd, &key, &value, flags);
+ CHECK(err, "add elem", "#%u error %d\n", i, err);
+
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup elem", "#%u error %d\n", i, err);
+ CHECK(got != value, "lookup elem", "#%u expect %u got %u\n", i, value, got);
+
+ /* re-add i-th element (Error) */
+ err = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
+ CHECK(err != -EEXIST, "re-add elem", "#%u error %d\n", i, err);
+
+ /* Overwrite i-th element */
+ flags = i % 2 ? 0 : BPF_EXIST;
+ value = i;
+ err = bpf_map_update_elem(fd, &key, &value, flags);
+ CHECK(err, "update elem", "error %d\n", err);
+
+ /* Lookup #[0~i] elements */
+ for (j = 0; j <= i; j++) {
+ len = strlen(keys[j]);
+ key.prefixlen = (len + 1) * 8;
+ memset(key.data, 0, sizeof(key.data));
+ memcpy(key.data, keys[j], len);
+ err = bpf_map_lookup_elem(fd, &key, &got);
+ CHECK(err, "lookup elem", "#%u/%u error %d\n", i, j, err);
+ CHECK(got != j, "lookup elem", "#%u/%u expect %u got %u\n",
+ i, j, value, got);
+ }
+ }
+
+ /* Add element to a full qp-trie (Error) */
+ key.prefixlen = sizeof(key.data) * 8;
+ memset(key.data, 0, sizeof(key.data));
+ value = 0;
+ err = bpf_map_update_elem(fd, &key, &value, 0);
+ CHECK(err != -ENOSPC, "add to full qp-trie", "error %d\n", err);
+
+ /* Iterate sorted elements: no deletion */
+ memcpy(sorted_keys, keys, sizeof(keys));
+ qsort(sorted_keys, ARRAY_SIZE(sorted_keys), sizeof(sorted_keys[0]), cmp_str);
+ cur = NULL;
+ for (i = 0; i < ARRAY_SIZE(sorted_keys); i++) {
+ len = strlen(sorted_keys[i]);
+ err = bpf_map_get_next_key(fd, cur, &next_key);
+ CHECK(err, "iterate", "#%u error %d\n", i, err);
+ CHECK(next_key.prefixlen != (len + 1) * 8, "iterate",
+ "#%u invalid len %u expect %u\n",
+ i, next_key.prefixlen, (len + 1) * 8);
+ CHECK(memcmp(sorted_keys[i], next_key.data, len + 1), "iterate",
+ "#%u got %.*s exp %.*s\n", i, len, next_key.data, len, sorted_keys[i]);
+
+ cur = &next_key;
+ }
+ err = bpf_map_get_next_key(fd, cur, &next_key);
+ CHECK(err != -ENOENT, "more element", "error %d\n", err);
+
+ /* Iterate sorted elements: delete the found key after each iteration */
+ cur = NULL;
+ for (i = 0; i < ARRAY_SIZE(sorted_keys); i++) {
+ len = strlen(sorted_keys[i]);
+ err = bpf_map_get_next_key(fd, cur, &next_key);
+ CHECK(err, "iterate", "#%u error %d\n", i, err);
+ CHECK(next_key.prefixlen != (len + 1) * 8, "iterate",
+ "#%u invalid len %u expect %u\n",
+ i, next_key.prefixlen, (len + 1) * 8);
+ CHECK(memcmp(sorted_keys[i], next_key.data, len + 1), "iterate",
+ "#%u got %.*s exp %.*s\n", i, len, next_key.data, len, sorted_keys[i]);
+
+ cur = &next_key;
+
+ err = bpf_map_delete_elem(fd, cur);
+ CHECK(err, "delete", "#%u error %d\n", i, err);
+ }
+ err = bpf_map_get_next_key(fd, cur, &next_key);
+ CHECK(err != -ENOENT, "non-empty qp-trie", "error %d\n", err);
+
+ close(fd);
+}
+
+/* Use the fixed prefixlen (32) and save integers in LPM trie. The iteration of
+ * LPM trie will return these integers in big-endian order, therefore, convert
+ * these integers to big-endian before update. After each iteration, delete the
+ * found key (the smallest integer) and expect the next iteration will return
+ * the second smallest number.
+ */
+static void test_lpm_trie_iterate_ints(void)
+{
+ struct lpm_trie_int_key key, next_key;
+ unsigned int i, max_entries;
+ struct lpm_trie_int_key *cur;
+ unsigned int *data_set;
+ int fd, err;
+ bool value;
+
+ max_entries = 4096;
+ data_set = calloc(max_entries, sizeof(*data_set));
+ CHECK(!data_set, "malloc", "no mem\n");
+ for (i = 0; i < max_entries; i++)
+ data_set[i] = i;
+
+ fd = lpm_trie_create(sizeof(key), sizeof(value), max_entries);
+ value = true;
+ for (i = 0; i < max_entries; i++) {
+ key.prefixlen = 32;
+ key.data = htobe32(data_set[i]);
+
+ err = bpf_map_update_elem(fd, &key, &value, BPF_NOEXIST);
+ CHECK(err, "add elem", "#%u error %d\n", i, err);
+ }
+
+ cur = NULL;
+ for (i = 0; i < max_entries; i++) {
+ err = bpf_map_get_next_key(fd, cur, &next_key);
+ CHECK(err, "iterate", "#%u error %d\n", i, err);
+ CHECK(next_key.prefixlen != 32, "iterate", "#%u invalid len %u\n",
+ i, next_key.prefixlen);
+ CHECK(be32toh(next_key.data) != data_set[i], "iterate", "#%u got 0x%x exp 0x%x\n",
+ i, be32toh(next_key.data), data_set[i]);
+ cur = &next_key;
+
+ /*
+ * Delete the minimal key, the next call of bpf_get_next_key()
+ * will return the second minimal key.
+ */
+ err = bpf_map_delete_elem(fd, &next_key);
+ CHECK(err, "del elem", "#%u elem error %d\n", i, err);
+ }
+ err = bpf_map_get_next_key(fd, cur, &next_key);
+ CHECK(err != -ENOENT, "more element", "error %d\n", err);
+
+ err = bpf_map_get_next_key(fd, NULL, &next_key);
+ CHECK(err != -ENOENT, "no-empty qp-trie", "error %d\n", err);
+
+ free(data_set);
+
+ close(fd);
+}
+
+void test_lpm_trie_map_basic_ops(void)
{
int i;
/* we want predictable, pseudo random tests */
srand(0xf00ba1);
- /* Use libbpf 1.0 API mode */
- libbpf_set_strict_mode(LIBBPF_STRICT_ALL);
-
test_lpm_basic();
test_lpm_order();
@@ -792,6 +1179,10 @@ int main(void)
test_lpm_get_next_key();
test_lpm_multi_thread();
- printf("test_lpm: OK\n");
- return 0;
+ test_lpm_trie_update_flags();
+ test_lpm_trie_update_full_map();
+ test_lpm_trie_iterate_strs();
+ test_lpm_trie_iterate_ints();
+
+ printf("%s: PASS\n", __func__);
}
diff --git a/tools/testing/selftests/bpf/map_tests/task_storage_map.c b/tools/testing/selftests/bpf/map_tests/task_storage_map.c
index 62971dbf2996..a4121d2248ac 100644
--- a/tools/testing/selftests/bpf/map_tests/task_storage_map.c
+++ b/tools/testing/selftests/bpf/map_tests/task_storage_map.c
@@ -78,8 +78,8 @@ void test_task_storage_map_stress_lookup(void)
CHECK(err, "open_and_load", "error %d\n", err);
/* Only for a fully preemptible kernel */
- if (!skel->kconfig->CONFIG_PREEMPT) {
- printf("%s SKIP (no CONFIG_PREEMPT)\n", __func__);
+ if (!skel->kconfig->CONFIG_PREEMPTION) {
+ printf("%s SKIP (no CONFIG_PREEMPTION)\n", __func__);
read_bpf_task_storage_busy__destroy(skel);
skips++;
return;
diff --git a/tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c b/tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c
new file mode 100644
index 000000000000..7526de379081
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/changes_pkt_data.c
@@ -0,0 +1,107 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "bpf/libbpf.h"
+#include "changes_pkt_data_freplace.skel.h"
+#include "changes_pkt_data.skel.h"
+#include <test_progs.h>
+
+static void print_verifier_log(const char *log)
+{
+ if (env.verbosity >= VERBOSE_VERY)
+ fprintf(stdout, "VERIFIER LOG:\n=============\n%s=============\n", log);
+}
+
+static void test_aux(const char *main_prog_name,
+ const char *to_be_replaced,
+ const char *replacement,
+ bool expect_load)
+{
+ struct changes_pkt_data_freplace *freplace = NULL;
+ struct bpf_program *freplace_prog = NULL;
+ struct bpf_program *main_prog = NULL;
+ LIBBPF_OPTS(bpf_object_open_opts, opts);
+ struct changes_pkt_data *main = NULL;
+ char log[16*1024];
+ int err;
+
+ opts.kernel_log_buf = log;
+ opts.kernel_log_size = sizeof(log);
+ if (env.verbosity >= VERBOSE_SUPER)
+ opts.kernel_log_level = 1 | 2 | 4;
+ main = changes_pkt_data__open_opts(&opts);
+ if (!ASSERT_OK_PTR(main, "changes_pkt_data__open"))
+ goto out;
+ main_prog = bpf_object__find_program_by_name(main->obj, main_prog_name);
+ if (!ASSERT_OK_PTR(main_prog, "main_prog"))
+ goto out;
+ bpf_program__set_autoload(main_prog, true);
+ err = changes_pkt_data__load(main);
+ print_verifier_log(log);
+ if (!ASSERT_OK(err, "changes_pkt_data__load"))
+ goto out;
+ freplace = changes_pkt_data_freplace__open_opts(&opts);
+ if (!ASSERT_OK_PTR(freplace, "changes_pkt_data_freplace__open"))
+ goto out;
+ freplace_prog = bpf_object__find_program_by_name(freplace->obj, replacement);
+ if (!ASSERT_OK_PTR(freplace_prog, "freplace_prog"))
+ goto out;
+ bpf_program__set_autoload(freplace_prog, true);
+ bpf_program__set_autoattach(freplace_prog, true);
+ bpf_program__set_attach_target(freplace_prog,
+ bpf_program__fd(main_prog),
+ to_be_replaced);
+ err = changes_pkt_data_freplace__load(freplace);
+ print_verifier_log(log);
+ if (expect_load) {
+ ASSERT_OK(err, "changes_pkt_data_freplace__load");
+ } else {
+ ASSERT_ERR(err, "changes_pkt_data_freplace__load");
+ ASSERT_HAS_SUBSTR(log, "Extension program changes packet data", "error log");
+ }
+
+out:
+ changes_pkt_data_freplace__destroy(freplace);
+ changes_pkt_data__destroy(main);
+}
+
+/* There are two global subprograms in both changes_pkt_data.skel.h:
+ * - one changes packet data;
+ * - another does not.
+ * It is ok to freplace subprograms that change packet data with those
+ * that either do or do not. It is only ok to freplace subprograms
+ * that do not change packet data with those that do not as well.
+ * The below tests check outcomes for each combination of such freplace.
+ * Also test a case when main subprogram itself is replaced and is a single
+ * subprogram in a program.
+ */
+void test_changes_pkt_data_freplace(void)
+{
+ struct {
+ const char *main;
+ const char *to_be_replaced;
+ bool changes;
+ } mains[] = {
+ { "main_with_subprogs", "changes_pkt_data", true },
+ { "main_with_subprogs", "does_not_change_pkt_data", false },
+ { "main_changes", "main_changes", true },
+ { "main_does_not_change", "main_does_not_change", false },
+ };
+ struct {
+ const char *func;
+ bool changes;
+ } replacements[] = {
+ { "changes_pkt_data", true },
+ { "does_not_change_pkt_data", false }
+ };
+ char buf[64];
+
+ for (int i = 0; i < ARRAY_SIZE(mains); ++i) {
+ for (int j = 0; j < ARRAY_SIZE(replacements); ++j) {
+ snprintf(buf, sizeof(buf), "%s_with_%s",
+ mains[i].to_be_replaced, replacements[j].func);
+ if (!test__start_subtest(buf))
+ continue;
+ test_aux(mains[i].main, mains[i].to_be_replaced, replacements[j].func,
+ mains[i].changes || !replacements[j].changes);
+ }
+ }
+}
diff --git a/tools/testing/selftests/bpf/prog_tests/raw_tp_null.c b/tools/testing/selftests/bpf/prog_tests/raw_tp_null.c
index 6fa19449297e..43676a9922dc 100644
--- a/tools/testing/selftests/bpf/prog_tests/raw_tp_null.c
+++ b/tools/testing/selftests/bpf/prog_tests/raw_tp_null.c
@@ -3,11 +3,14 @@
#include <test_progs.h>
#include "raw_tp_null.skel.h"
+#include "raw_tp_null_fail.skel.h"
void test_raw_tp_null(void)
{
struct raw_tp_null *skel;
+ RUN_TESTS(raw_tp_null_fail);
+
skel = raw_tp_null__open_and_load();
if (!ASSERT_OK_PTR(skel, "raw_tp_null__open_and_load"))
return;
diff --git a/tools/testing/selftests/bpf/prog_tests/socket_helpers.h b/tools/testing/selftests/bpf/prog_tests/socket_helpers.h
new file mode 100644
index 000000000000..1bdfb79ef009
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/socket_helpers.h
@@ -0,0 +1,394 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __SOCKET_HELPERS__
+#define __SOCKET_HELPERS__
+
+#include <linux/vm_sockets.h>
+
+/* include/linux/net.h */
+#define SOCK_TYPE_MASK 0xf
+
+#define IO_TIMEOUT_SEC 30
+#define MAX_STRERR_LEN 256
+
+/* workaround for older vm_sockets.h */
+#ifndef VMADDR_CID_LOCAL
+#define VMADDR_CID_LOCAL 1
+#endif
+
+/* include/linux/cleanup.h */
+#define __get_and_null(p, nullvalue) \
+ ({ \
+ __auto_type __ptr = &(p); \
+ __auto_type __val = *__ptr; \
+ *__ptr = nullvalue; \
+ __val; \
+ })
+
+#define take_fd(fd) __get_and_null(fd, -EBADF)
+
+/* Wrappers that fail the test on error and report it. */
+
+#define _FAIL(errnum, fmt...) \
+ ({ \
+ error_at_line(0, (errnum), __func__, __LINE__, fmt); \
+ CHECK_FAIL(true); \
+ })
+#define FAIL(fmt...) _FAIL(0, fmt)
+#define FAIL_ERRNO(fmt...) _FAIL(errno, fmt)
+#define FAIL_LIBBPF(err, msg) \
+ ({ \
+ char __buf[MAX_STRERR_LEN]; \
+ libbpf_strerror((err), __buf, sizeof(__buf)); \
+ FAIL("%s: %s", (msg), __buf); \
+ })
+
+
+#define xaccept_nonblock(fd, addr, len) \
+ ({ \
+ int __ret = \
+ accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC); \
+ if (__ret == -1) \
+ FAIL_ERRNO("accept"); \
+ __ret; \
+ })
+
+#define xbind(fd, addr, len) \
+ ({ \
+ int __ret = bind((fd), (addr), (len)); \
+ if (__ret == -1) \
+ FAIL_ERRNO("bind"); \
+ __ret; \
+ })
+
+#define xclose(fd) \
+ ({ \
+ int __ret = close((fd)); \
+ if (__ret == -1) \
+ FAIL_ERRNO("close"); \
+ __ret; \
+ })
+
+#define xconnect(fd, addr, len) \
+ ({ \
+ int __ret = connect((fd), (addr), (len)); \
+ if (__ret == -1) \
+ FAIL_ERRNO("connect"); \
+ __ret; \
+ })
+
+#define xgetsockname(fd, addr, len) \
+ ({ \
+ int __ret = getsockname((fd), (addr), (len)); \
+ if (__ret == -1) \
+ FAIL_ERRNO("getsockname"); \
+ __ret; \
+ })
+
+#define xgetsockopt(fd, level, name, val, len) \
+ ({ \
+ int __ret = getsockopt((fd), (level), (name), (val), (len)); \
+ if (__ret == -1) \
+ FAIL_ERRNO("getsockopt(" #name ")"); \
+ __ret; \
+ })
+
+#define xlisten(fd, backlog) \
+ ({ \
+ int __ret = listen((fd), (backlog)); \
+ if (__ret == -1) \
+ FAIL_ERRNO("listen"); \
+ __ret; \
+ })
+
+#define xsetsockopt(fd, level, name, val, len) \
+ ({ \
+ int __ret = setsockopt((fd), (level), (name), (val), (len)); \
+ if (__ret == -1) \
+ FAIL_ERRNO("setsockopt(" #name ")"); \
+ __ret; \
+ })
+
+#define xsend(fd, buf, len, flags) \
+ ({ \
+ ssize_t __ret = send((fd), (buf), (len), (flags)); \
+ if (__ret == -1) \
+ FAIL_ERRNO("send"); \
+ __ret; \
+ })
+
+#define xrecv_nonblock(fd, buf, len, flags) \
+ ({ \
+ ssize_t __ret = recv_timeout((fd), (buf), (len), (flags), \
+ IO_TIMEOUT_SEC); \
+ if (__ret == -1) \
+ FAIL_ERRNO("recv"); \
+ __ret; \
+ })
+
+#define xsocket(family, sotype, flags) \
+ ({ \
+ int __ret = socket(family, sotype, flags); \
+ if (__ret == -1) \
+ FAIL_ERRNO("socket"); \
+ __ret; \
+ })
+
+static inline void close_fd(int *fd)
+{
+ if (*fd >= 0)
+ xclose(*fd);
+}
+
+#define __close_fd __attribute__((cleanup(close_fd)))
+
+static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
+{
+ return (struct sockaddr *)ss;
+}
+
+static inline void init_addr_loopback4(struct sockaddr_storage *ss,
+ socklen_t *len)
+{
+ struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss));
+
+ addr4->sin_family = AF_INET;
+ addr4->sin_port = 0;
+ addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ *len = sizeof(*addr4);
+}
+
+static inline void init_addr_loopback6(struct sockaddr_storage *ss,
+ socklen_t *len)
+{
+ struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss));
+
+ addr6->sin6_family = AF_INET6;
+ addr6->sin6_port = 0;
+ addr6->sin6_addr = in6addr_loopback;
+ *len = sizeof(*addr6);
+}
+
+static inline void init_addr_loopback_vsock(struct sockaddr_storage *ss,
+ socklen_t *len)
+{
+ struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss));
+
+ addr->svm_family = AF_VSOCK;
+ addr->svm_port = VMADDR_PORT_ANY;
+ addr->svm_cid = VMADDR_CID_LOCAL;
+ *len = sizeof(*addr);
+}
+
+static inline void init_addr_loopback(int family, struct sockaddr_storage *ss,
+ socklen_t *len)
+{
+ switch (family) {
+ case AF_INET:
+ init_addr_loopback4(ss, len);
+ return;
+ case AF_INET6:
+ init_addr_loopback6(ss, len);
+ return;
+ case AF_VSOCK:
+ init_addr_loopback_vsock(ss, len);
+ return;
+ default:
+ FAIL("unsupported address family %d", family);
+ }
+}
+
+static inline int enable_reuseport(int s, int progfd)
+{
+ int err, one = 1;
+
+ err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
+ if (err)
+ return -1;
+ err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
+ sizeof(progfd));
+ if (err)
+ return -1;
+
+ return 0;
+}
+
+static inline int socket_loopback_reuseport(int family, int sotype, int progfd)
+{
+ struct sockaddr_storage addr;
+ socklen_t len = 0;
+ int err, s;
+
+ init_addr_loopback(family, &addr, &len);
+
+ s = xsocket(family, sotype, 0);
+ if (s == -1)
+ return -1;
+
+ if (progfd >= 0)
+ enable_reuseport(s, progfd);
+
+ err = xbind(s, sockaddr(&addr), len);
+ if (err)
+ goto close;
+
+ if (sotype & SOCK_DGRAM)
+ return s;
+
+ err = xlisten(s, SOMAXCONN);
+ if (err)
+ goto close;
+
+ return s;
+close:
+ xclose(s);
+ return -1;
+}
+
+static inline int socket_loopback(int family, int sotype)
+{
+ return socket_loopback_reuseport(family, sotype, -1);
+}
+
+static inline int poll_connect(int fd, unsigned int timeout_sec)
+{
+ struct timeval timeout = { .tv_sec = timeout_sec };
+ fd_set wfds;
+ int r, eval;
+ socklen_t esize = sizeof(eval);
+
+ FD_ZERO(&wfds);
+ FD_SET(fd, &wfds);
+
+ r = select(fd + 1, NULL, &wfds, NULL, &timeout);
+ if (r == 0)
+ errno = ETIME;
+ if (r != 1)
+ return -1;
+
+ if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &eval, &esize) < 0)
+ return -1;
+ if (eval != 0) {
+ errno = eval;
+ return -1;
+ }
+
+ return 0;
+}
+
+static inline int poll_read(int fd, unsigned int timeout_sec)
+{
+ struct timeval timeout = { .tv_sec = timeout_sec };
+ fd_set rfds;
+ int r;
+
+ FD_ZERO(&rfds);
+ FD_SET(fd, &rfds);
+
+ r = select(fd + 1, &rfds, NULL, NULL, &timeout);
+ if (r == 0)
+ errno = ETIME;
+
+ return r == 1 ? 0 : -1;
+}
+
+static inline int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len,
+ unsigned int timeout_sec)
+{
+ if (poll_read(fd, timeout_sec))
+ return -1;
+
+ return accept(fd, addr, len);
+}
+
+static inline int recv_timeout(int fd, void *buf, size_t len, int flags,
+ unsigned int timeout_sec)
+{
+ if (poll_read(fd, timeout_sec))
+ return -1;
+
+ return recv(fd, buf, len, flags);
+}
+
+
+static inline int create_pair(int family, int sotype, int *p0, int *p1)
+{
+ __close_fd int s, c = -1, p = -1;
+ struct sockaddr_storage addr;
+ socklen_t len = sizeof(addr);
+ int err;
+
+ s = socket_loopback(family, sotype);
+ if (s < 0)
+ return s;
+
+ err = xgetsockname(s, sockaddr(&addr), &len);
+ if (err)
+ return err;
+
+ c = xsocket(family, sotype, 0);
+ if (c < 0)
+ return c;
+
+ err = connect(c, sockaddr(&addr), len);
+ if (err) {
+ if (errno != EINPROGRESS) {
+ FAIL_ERRNO("connect");
+ return err;
+ }
+
+ err = poll_connect(c, IO_TIMEOUT_SEC);
+ if (err) {
+ FAIL_ERRNO("poll_connect");
+ return err;
+ }
+ }
+
+ switch (sotype & SOCK_TYPE_MASK) {
+ case SOCK_DGRAM:
+ err = xgetsockname(c, sockaddr(&addr), &len);
+ if (err)
+ return err;
+
+ err = xconnect(s, sockaddr(&addr), len);
+ if (err)
+ return err;
+
+ *p0 = take_fd(s);
+ break;
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ p = xaccept_nonblock(s, NULL, NULL);
+ if (p < 0)
+ return p;
+
+ *p0 = take_fd(p);
+ break;
+ default:
+ FAIL("Unsupported socket type %#x", sotype);
+ return -EOPNOTSUPP;
+ }
+
+ *p1 = take_fd(c);
+ return 0;
+}
+
+static inline int create_socket_pairs(int family, int sotype, int *c0, int *c1,
+ int *p0, int *p1)
+{
+ int err;
+
+ err = create_pair(family, sotype, c0, p0);
+ if (err)
+ return err;
+
+ err = create_pair(family, sotype, c1, p1);
+ if (err) {
+ close(*c0);
+ close(*p0);
+ }
+
+ return err;
+}
+
+#endif // __SOCKET_HELPERS__
diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
index a2041f8e32eb..884ad87783d5 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_basic.c
@@ -12,6 +12,7 @@
#include "test_sockmap_progs_query.skel.h"
#include "test_sockmap_pass_prog.skel.h"
#include "test_sockmap_drop_prog.skel.h"
+#include "test_sockmap_change_tail.skel.h"
#include "bpf_iter_sockmap.skel.h"
#include "sockmap_helpers.h"
@@ -108,6 +109,35 @@ out:
close(s);
}
+static void test_sockmap_vsock_delete_on_close(void)
+{
+ int err, c, p, map;
+ const int zero = 0;
+
+ err = create_pair(AF_VSOCK, SOCK_STREAM, &c, &p);
+ if (!ASSERT_OK(err, "create_pair(AF_VSOCK)"))
+ return;
+
+ map = bpf_map_create(BPF_MAP_TYPE_SOCKMAP, NULL, sizeof(int),
+ sizeof(int), 1, NULL);
+ if (!ASSERT_GE(map, 0, "bpf_map_create")) {
+ close(c);
+ goto out;
+ }
+
+ err = bpf_map_update_elem(map, &zero, &c, BPF_NOEXIST);
+ close(c);
+ if (!ASSERT_OK(err, "bpf_map_update"))
+ goto out;
+
+ err = bpf_map_update_elem(map, &zero, &p, BPF_NOEXIST);
+ ASSERT_OK(err, "after close(), bpf_map_update");
+
+out:
+ close(p);
+ close(map);
+}
+
static void test_skmsg_helpers(enum bpf_map_type map_type)
{
struct test_skmsg_load_helpers *skel;
@@ -614,6 +644,54 @@ out:
test_sockmap_drop_prog__destroy(drop);
}
+static void test_sockmap_skb_verdict_change_tail(void)
+{
+ struct test_sockmap_change_tail *skel;
+ int err, map, verdict;
+ int c1, p1, sent, recvd;
+ int zero = 0;
+ char buf[2];
+
+ skel = test_sockmap_change_tail__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "open_and_load"))
+ return;
+ verdict = bpf_program__fd(skel->progs.prog_skb_verdict);
+ map = bpf_map__fd(skel->maps.sock_map_rx);
+
+ err = bpf_prog_attach(verdict, map, BPF_SK_SKB_STREAM_VERDICT, 0);
+ if (!ASSERT_OK(err, "bpf_prog_attach"))
+ goto out;
+ err = create_pair(AF_INET, SOCK_STREAM, &c1, &p1);
+ if (!ASSERT_OK(err, "create_pair()"))
+ goto out;
+ err = bpf_map_update_elem(map, &zero, &c1, BPF_NOEXIST);
+ if (!ASSERT_OK(err, "bpf_map_update_elem(c1)"))
+ goto out_close;
+ sent = xsend(p1, "Tr", 2, 0);
+ ASSERT_EQ(sent, 2, "xsend(p1)");
+ recvd = recv(c1, buf, 2, 0);
+ ASSERT_EQ(recvd, 1, "recv(c1)");
+ ASSERT_EQ(skel->data->change_tail_ret, 0, "change_tail_ret");
+
+ sent = xsend(p1, "G", 1, 0);
+ ASSERT_EQ(sent, 1, "xsend(p1)");
+ recvd = recv(c1, buf, 2, 0);
+ ASSERT_EQ(recvd, 2, "recv(c1)");
+ ASSERT_EQ(skel->data->change_tail_ret, 0, "change_tail_ret");
+
+ sent = xsend(p1, "E", 1, 0);
+ ASSERT_EQ(sent, 1, "xsend(p1)");
+ recvd = recv(c1, buf, 1, 0);
+ ASSERT_EQ(recvd, 1, "recv(c1)");
+ ASSERT_EQ(skel->data->change_tail_ret, -EINVAL, "change_tail_ret");
+
+out_close:
+ close(c1);
+ close(p1);
+out:
+ test_sockmap_change_tail__destroy(skel);
+}
+
static void test_sockmap_skb_verdict_peek_helper(int map)
{
int err, c1, p1, zero = 0, sent, recvd, avail;
@@ -905,8 +983,10 @@ static void test_sockmap_same_sock(void)
err = socketpair(AF_UNIX, SOCK_STREAM, 0, stream);
ASSERT_OK(err, "socketpair(af_unix, sock_stream)");
- if (err)
+ if (err) {
+ close(tcp);
goto out;
+ }
for (i = 0; i < 2; i++) {
err = bpf_map_update_elem(map, &zero, &stream[0], BPF_ANY);
@@ -925,24 +1005,70 @@ static void test_sockmap_same_sock(void)
ASSERT_OK(err, "bpf_map_update_elem(tcp)");
}
+ close(tcp);
err = bpf_map_delete_elem(map, &zero);
- ASSERT_OK(err, "bpf_map_delete_elem(entry)");
+ ASSERT_ERR(err, "bpf_map_delete_elem(entry)");
close(stream[0]);
close(stream[1]);
out:
close(dgram);
- close(tcp);
close(udp);
test_sockmap_pass_prog__destroy(skel);
}
+static void test_sockmap_skb_verdict_vsock_poll(void)
+{
+ struct test_sockmap_pass_prog *skel;
+ int err, map, conn, peer;
+ struct bpf_program *prog;
+ struct bpf_link *link;
+ char buf = 'x';
+ int zero = 0;
+
+ skel = test_sockmap_pass_prog__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "open_and_load"))
+ return;
+
+ if (create_pair(AF_VSOCK, SOCK_STREAM, &conn, &peer))
+ goto destroy;
+
+ prog = skel->progs.prog_skb_verdict;
+ map = bpf_map__fd(skel->maps.sock_map_rx);
+ link = bpf_program__attach_sockmap(prog, map);
+ if (!ASSERT_OK_PTR(link, "bpf_program__attach_sockmap"))
+ goto close;
+
+ err = bpf_map_update_elem(map, &zero, &conn, BPF_ANY);
+ if (!ASSERT_OK(err, "bpf_map_update_elem"))
+ goto detach;
+
+ if (xsend(peer, &buf, 1, 0) != 1)
+ goto detach;
+
+ err = poll_read(conn, IO_TIMEOUT_SEC);
+ if (!ASSERT_OK(err, "poll"))
+ goto detach;
+
+ if (xrecv_nonblock(conn, &buf, 1, 0) != 1)
+ FAIL("xrecv_nonblock");
+detach:
+ bpf_link__detach(link);
+close:
+ xclose(conn);
+ xclose(peer);
+destroy:
+ test_sockmap_pass_prog__destroy(skel);
+}
+
void test_sockmap_basic(void)
{
if (test__start_subtest("sockmap create_update_free"))
test_sockmap_create_update_free(BPF_MAP_TYPE_SOCKMAP);
if (test__start_subtest("sockhash create_update_free"))
test_sockmap_create_update_free(BPF_MAP_TYPE_SOCKHASH);
+ if (test__start_subtest("sockmap vsock delete on close"))
+ test_sockmap_vsock_delete_on_close();
if (test__start_subtest("sockmap sk_msg load helpers"))
test_skmsg_helpers(BPF_MAP_TYPE_SOCKMAP);
if (test__start_subtest("sockhash sk_msg load helpers"))
@@ -981,6 +1107,8 @@ void test_sockmap_basic(void)
test_sockmap_skb_verdict_fionread(true);
if (test__start_subtest("sockmap skb_verdict fionread on drop"))
test_sockmap_skb_verdict_fionread(false);
+ if (test__start_subtest("sockmap skb_verdict change tail"))
+ test_sockmap_skb_verdict_change_tail();
if (test__start_subtest("sockmap skb_verdict msg_f_peek"))
test_sockmap_skb_verdict_peek();
if (test__start_subtest("sockmap skb_verdict msg_f_peek with link"))
@@ -997,4 +1125,6 @@ void test_sockmap_basic(void)
test_skmsg_helpers_with_link(BPF_MAP_TYPE_SOCKMAP);
if (test__start_subtest("sockhash sk_msg attach sockhash helpers with link"))
test_skmsg_helpers_with_link(BPF_MAP_TYPE_SOCKHASH);
+ if (test__start_subtest("sockmap skb_verdict vsock poll"))
+ test_sockmap_skb_verdict_vsock_poll();
}
diff --git a/tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h b/tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h
index 38e35c72bdaa..3e5571dd578d 100644
--- a/tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h
+++ b/tools/testing/selftests/bpf/prog_tests/sockmap_helpers.h
@@ -1,139 +1,12 @@
#ifndef __SOCKMAP_HELPERS__
#define __SOCKMAP_HELPERS__
-#include <linux/vm_sockets.h>
+#include "socket_helpers.h"
-/* include/linux/net.h */
-#define SOCK_TYPE_MASK 0xf
-
-#define IO_TIMEOUT_SEC 30
-#define MAX_STRERR_LEN 256
#define MAX_TEST_NAME 80
-/* workaround for older vm_sockets.h */
-#ifndef VMADDR_CID_LOCAL
-#define VMADDR_CID_LOCAL 1
-#endif
-
#define __always_unused __attribute__((__unused__))
-/* include/linux/cleanup.h */
-#define __get_and_null(p, nullvalue) \
- ({ \
- __auto_type __ptr = &(p); \
- __auto_type __val = *__ptr; \
- *__ptr = nullvalue; \
- __val; \
- })
-
-#define take_fd(fd) __get_and_null(fd, -EBADF)
-
-#define _FAIL(errnum, fmt...) \
- ({ \
- error_at_line(0, (errnum), __func__, __LINE__, fmt); \
- CHECK_FAIL(true); \
- })
-#define FAIL(fmt...) _FAIL(0, fmt)
-#define FAIL_ERRNO(fmt...) _FAIL(errno, fmt)
-#define FAIL_LIBBPF(err, msg) \
- ({ \
- char __buf[MAX_STRERR_LEN]; \
- libbpf_strerror((err), __buf, sizeof(__buf)); \
- FAIL("%s: %s", (msg), __buf); \
- })
-
-/* Wrappers that fail the test on error and report it. */
-
-#define xaccept_nonblock(fd, addr, len) \
- ({ \
- int __ret = \
- accept_timeout((fd), (addr), (len), IO_TIMEOUT_SEC); \
- if (__ret == -1) \
- FAIL_ERRNO("accept"); \
- __ret; \
- })
-
-#define xbind(fd, addr, len) \
- ({ \
- int __ret = bind((fd), (addr), (len)); \
- if (__ret == -1) \
- FAIL_ERRNO("bind"); \
- __ret; \
- })
-
-#define xclose(fd) \
- ({ \
- int __ret = close((fd)); \
- if (__ret == -1) \
- FAIL_ERRNO("close"); \
- __ret; \
- })
-
-#define xconnect(fd, addr, len) \
- ({ \
- int __ret = connect((fd), (addr), (len)); \
- if (__ret == -1) \
- FAIL_ERRNO("connect"); \
- __ret; \
- })
-
-#define xgetsockname(fd, addr, len) \
- ({ \
- int __ret = getsockname((fd), (addr), (len)); \
- if (__ret == -1) \
- FAIL_ERRNO("getsockname"); \
- __ret; \
- })
-
-#define xgetsockopt(fd, level, name, val, len) \
- ({ \
- int __ret = getsockopt((fd), (level), (name), (val), (len)); \
- if (__ret == -1) \
- FAIL_ERRNO("getsockopt(" #name ")"); \
- __ret; \
- })
-
-#define xlisten(fd, backlog) \
- ({ \
- int __ret = listen((fd), (backlog)); \
- if (__ret == -1) \
- FAIL_ERRNO("listen"); \
- __ret; \
- })
-
-#define xsetsockopt(fd, level, name, val, len) \
- ({ \
- int __ret = setsockopt((fd), (level), (name), (val), (len)); \
- if (__ret == -1) \
- FAIL_ERRNO("setsockopt(" #name ")"); \
- __ret; \
- })
-
-#define xsend(fd, buf, len, flags) \
- ({ \
- ssize_t __ret = send((fd), (buf), (len), (flags)); \
- if (__ret == -1) \
- FAIL_ERRNO("send"); \
- __ret; \
- })
-
-#define xrecv_nonblock(fd, buf, len, flags) \
- ({ \
- ssize_t __ret = recv_timeout((fd), (buf), (len), (flags), \
- IO_TIMEOUT_SEC); \
- if (__ret == -1) \
- FAIL_ERRNO("recv"); \
- __ret; \
- })
-
-#define xsocket(family, sotype, flags) \
- ({ \
- int __ret = socket(family, sotype, flags); \
- if (__ret == -1) \
- FAIL_ERRNO("socket"); \
- __ret; \
- })
-
#define xbpf_map_delete_elem(fd, key) \
({ \
int __ret = bpf_map_delete_elem((fd), (key)); \
@@ -193,130 +66,6 @@
__ret; \
})
-static inline void close_fd(int *fd)
-{
- if (*fd >= 0)
- xclose(*fd);
-}
-
-#define __close_fd __attribute__((cleanup(close_fd)))
-
-static inline int poll_connect(int fd, unsigned int timeout_sec)
-{
- struct timeval timeout = { .tv_sec = timeout_sec };
- fd_set wfds;
- int r, eval;
- socklen_t esize = sizeof(eval);
-
- FD_ZERO(&wfds);
- FD_SET(fd, &wfds);
-
- r = select(fd + 1, NULL, &wfds, NULL, &timeout);
- if (r == 0)
- errno = ETIME;
- if (r != 1)
- return -1;
-
- if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &eval, &esize) < 0)
- return -1;
- if (eval != 0) {
- errno = eval;
- return -1;
- }
-
- return 0;
-}
-
-static inline int poll_read(int fd, unsigned int timeout_sec)
-{
- struct timeval timeout = { .tv_sec = timeout_sec };
- fd_set rfds;
- int r;
-
- FD_ZERO(&rfds);
- FD_SET(fd, &rfds);
-
- r = select(fd + 1, &rfds, NULL, NULL, &timeout);
- if (r == 0)
- errno = ETIME;
-
- return r == 1 ? 0 : -1;
-}
-
-static inline int accept_timeout(int fd, struct sockaddr *addr, socklen_t *len,
- unsigned int timeout_sec)
-{
- if (poll_read(fd, timeout_sec))
- return -1;
-
- return accept(fd, addr, len);
-}
-
-static inline int recv_timeout(int fd, void *buf, size_t len, int flags,
- unsigned int timeout_sec)
-{
- if (poll_read(fd, timeout_sec))
- return -1;
-
- return recv(fd, buf, len, flags);
-}
-
-static inline void init_addr_loopback4(struct sockaddr_storage *ss,
- socklen_t *len)
-{
- struct sockaddr_in *addr4 = memset(ss, 0, sizeof(*ss));
-
- addr4->sin_family = AF_INET;
- addr4->sin_port = 0;
- addr4->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
- *len = sizeof(*addr4);
-}
-
-static inline void init_addr_loopback6(struct sockaddr_storage *ss,
- socklen_t *len)
-{
- struct sockaddr_in6 *addr6 = memset(ss, 0, sizeof(*ss));
-
- addr6->sin6_family = AF_INET6;
- addr6->sin6_port = 0;
- addr6->sin6_addr = in6addr_loopback;
- *len = sizeof(*addr6);
-}
-
-static inline void init_addr_loopback_vsock(struct sockaddr_storage *ss,
- socklen_t *len)
-{
- struct sockaddr_vm *addr = memset(ss, 0, sizeof(*ss));
-
- addr->svm_family = AF_VSOCK;
- addr->svm_port = VMADDR_PORT_ANY;
- addr->svm_cid = VMADDR_CID_LOCAL;
- *len = sizeof(*addr);
-}
-
-static inline void init_addr_loopback(int family, struct sockaddr_storage *ss,
- socklen_t *len)
-{
- switch (family) {
- case AF_INET:
- init_addr_loopback4(ss, len);
- return;
- case AF_INET6:
- init_addr_loopback6(ss, len);
- return;
- case AF_VSOCK:
- init_addr_loopback_vsock(ss, len);
- return;
- default:
- FAIL("unsupported address family %d", family);
- }
-}
-
-static inline struct sockaddr *sockaddr(struct sockaddr_storage *ss)
-{
- return (struct sockaddr *)ss;
-}
-
static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
{
u64 value;
@@ -334,136 +83,4 @@ static inline int add_to_sockmap(int sock_mapfd, int fd1, int fd2)
return xbpf_map_update_elem(sock_mapfd, &key, &value, BPF_NOEXIST);
}
-static inline int enable_reuseport(int s, int progfd)
-{
- int err, one = 1;
-
- err = xsetsockopt(s, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one));
- if (err)
- return -1;
- err = xsetsockopt(s, SOL_SOCKET, SO_ATTACH_REUSEPORT_EBPF, &progfd,
- sizeof(progfd));
- if (err)
- return -1;
-
- return 0;
-}
-
-static inline int socket_loopback_reuseport(int family, int sotype, int progfd)
-{
- struct sockaddr_storage addr;
- socklen_t len = 0;
- int err, s;
-
- init_addr_loopback(family, &addr, &len);
-
- s = xsocket(family, sotype, 0);
- if (s == -1)
- return -1;
-
- if (progfd >= 0)
- enable_reuseport(s, progfd);
-
- err = xbind(s, sockaddr(&addr), len);
- if (err)
- goto close;
-
- if (sotype & SOCK_DGRAM)
- return s;
-
- err = xlisten(s, SOMAXCONN);
- if (err)
- goto close;
-
- return s;
-close:
- xclose(s);
- return -1;
-}
-
-static inline int socket_loopback(int family, int sotype)
-{
- return socket_loopback_reuseport(family, sotype, -1);
-}
-
-static inline int create_pair(int family, int sotype, int *p0, int *p1)
-{
- __close_fd int s, c = -1, p = -1;
- struct sockaddr_storage addr;
- socklen_t len = sizeof(addr);
- int err;
-
- s = socket_loopback(family, sotype);
- if (s < 0)
- return s;
-
- err = xgetsockname(s, sockaddr(&addr), &len);
- if (err)
- return err;
-
- c = xsocket(family, sotype, 0);
- if (c < 0)
- return c;
-
- err = connect(c, sockaddr(&addr), len);
- if (err) {
- if (errno != EINPROGRESS) {
- FAIL_ERRNO("connect");
- return err;
- }
-
- err = poll_connect(c, IO_TIMEOUT_SEC);
- if (err) {
- FAIL_ERRNO("poll_connect");
- return err;
- }
- }
-
- switch (sotype & SOCK_TYPE_MASK) {
- case SOCK_DGRAM:
- err = xgetsockname(c, sockaddr(&addr), &len);
- if (err)
- return err;
-
- err = xconnect(s, sockaddr(&addr), len);
- if (err)
- return err;
-
- *p0 = take_fd(s);
- break;
- case SOCK_STREAM:
- case SOCK_SEQPACKET:
- p = xaccept_nonblock(s, NULL, NULL);
- if (p < 0)
- return p;
-
- *p0 = take_fd(p);
- break;
- default:
- FAIL("Unsupported socket type %#x", sotype);
- return -EOPNOTSUPP;
- }
-
- *p1 = take_fd(c);
- return 0;
-}
-
-static inline int create_socket_pairs(int family, int sotype, int *c0, int *c1,
- int *p0, int *p1)
-{
- int err;
-
- err = create_pair(family, sotype, c0, p0);
- if (err)
- return err;
-
- err = create_pair(family, sotype, c1, p1);
- if (err) {
- close(*c0);
- close(*p0);
- }
-
- return err;
-}
-
#endif // __SOCKMAP_HELPERS__
diff --git a/tools/testing/selftests/bpf/prog_tests/task_local_storage.c b/tools/testing/selftests/bpf/prog_tests/task_local_storage.c
index 60f474d965a9..42e822ea352f 100644
--- a/tools/testing/selftests/bpf/prog_tests/task_local_storage.c
+++ b/tools/testing/selftests/bpf/prog_tests/task_local_storage.c
@@ -197,7 +197,7 @@ static void test_nodeadlock(void)
/* Unnecessary recursion and deadlock detection are reproducible
* in the preemptible kernel.
*/
- if (!skel->kconfig->CONFIG_PREEMPT) {
+ if (!skel->kconfig->CONFIG_PREEMPTION) {
test__skip();
goto done;
}
diff --git a/tools/testing/selftests/bpf/prog_tests/tc_change_tail.c b/tools/testing/selftests/bpf/prog_tests/tc_change_tail.c
new file mode 100644
index 000000000000..74752233e779
--- /dev/null
+++ b/tools/testing/selftests/bpf/prog_tests/tc_change_tail.c
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <error.h>
+#include <test_progs.h>
+#include <linux/pkt_cls.h>
+
+#include "test_tc_change_tail.skel.h"
+#include "socket_helpers.h"
+
+#define LO_IFINDEX 1
+
+void test_tc_change_tail(void)
+{
+ LIBBPF_OPTS(bpf_tcx_opts, tcx_opts);
+ struct test_tc_change_tail *skel = NULL;
+ struct bpf_link *link;
+ int c1, p1;
+ char buf[2];
+ int ret;
+
+ skel = test_tc_change_tail__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "test_tc_change_tail__open_and_load"))
+ return;
+
+ link = bpf_program__attach_tcx(skel->progs.change_tail, LO_IFINDEX,
+ &tcx_opts);
+ if (!ASSERT_OK_PTR(link, "bpf_program__attach_tcx"))
+ goto destroy;
+
+ skel->links.change_tail = link;
+ ret = create_pair(AF_INET, SOCK_DGRAM, &c1, &p1);
+ if (!ASSERT_OK(ret, "create_pair"))
+ goto destroy;
+
+ ret = xsend(p1, "Tr", 2, 0);
+ ASSERT_EQ(ret, 2, "xsend(p1)");
+ ret = recv(c1, buf, 2, 0);
+ ASSERT_EQ(ret, 2, "recv(c1)");
+ ASSERT_EQ(skel->data->change_tail_ret, 0, "change_tail_ret");
+
+ ret = xsend(p1, "G", 1, 0);
+ ASSERT_EQ(ret, 1, "xsend(p1)");
+ ret = recv(c1, buf, 2, 0);
+ ASSERT_EQ(ret, 1, "recv(c1)");
+ ASSERT_EQ(skel->data->change_tail_ret, 0, "change_tail_ret");
+
+ ret = xsend(p1, "E", 1, 0);
+ ASSERT_EQ(ret, 1, "xsend(p1)");
+ ret = recv(c1, buf, 1, 0);
+ ASSERT_EQ(ret, 1, "recv(c1)");
+ ASSERT_EQ(skel->data->change_tail_ret, -EINVAL, "change_tail_ret");
+
+ ret = xsend(p1, "Z", 1, 0);
+ ASSERT_EQ(ret, 1, "xsend(p1)");
+ ret = recv(c1, buf, 1, 0);
+ ASSERT_EQ(ret, 1, "recv(c1)");
+ ASSERT_EQ(skel->data->change_tail_ret, -EINVAL, "change_tail_ret");
+
+ close(c1);
+ close(p1);
+destroy:
+ test_tc_change_tail__destroy(skel);
+}
diff --git a/tools/testing/selftests/bpf/prog_tests/tc_netkit.c b/tools/testing/selftests/bpf/prog_tests/tc_netkit.c
index 151a4210028f..2461d183dee5 100644
--- a/tools/testing/selftests/bpf/prog_tests/tc_netkit.c
+++ b/tools/testing/selftests/bpf/prog_tests/tc_netkit.c
@@ -14,10 +14,16 @@
#include "netlink_helpers.h"
#include "tc_helpers.h"
+#define NETKIT_HEADROOM 32
+#define NETKIT_TAILROOM 8
+
#define MARK 42
#define PRIO 0xeb9f
#define ICMP_ECHO 8
+#define FLAG_ADJUST_ROOM (1 << 0)
+#define FLAG_SAME_NETNS (1 << 1)
+
struct icmphdr {
__u8 type;
__u8 code;
@@ -35,7 +41,7 @@ struct iplink_req {
};
static int create_netkit(int mode, int policy, int peer_policy, int *ifindex,
- bool same_netns, int scrub, int peer_scrub)
+ int scrub, int peer_scrub, __u32 flags)
{
struct rtnl_handle rth = { .fd = -1 };
struct iplink_req req = {};
@@ -63,6 +69,10 @@ static int create_netkit(int mode, int policy, int peer_policy, int *ifindex,
addattr32(&req.n, sizeof(req), IFLA_NETKIT_SCRUB, scrub);
addattr32(&req.n, sizeof(req), IFLA_NETKIT_PEER_SCRUB, peer_scrub);
addattr32(&req.n, sizeof(req), IFLA_NETKIT_MODE, mode);
+ if (flags & FLAG_ADJUST_ROOM) {
+ addattr16(&req.n, sizeof(req), IFLA_NETKIT_HEADROOM, NETKIT_HEADROOM);
+ addattr16(&req.n, sizeof(req), IFLA_NETKIT_TAILROOM, NETKIT_TAILROOM);
+ }
addattr_nest_end(&req.n, data);
addattr_nest_end(&req.n, linkinfo);
@@ -87,7 +97,7 @@ static int create_netkit(int mode, int policy, int peer_policy, int *ifindex,
" addr ee:ff:bb:cc:aa:dd"),
"set hwaddress");
}
- if (same_netns) {
+ if (flags & FLAG_SAME_NETNS) {
ASSERT_OK(system("ip link set dev " netkit_peer " up"),
"up peer");
ASSERT_OK(system("ip addr add dev " netkit_peer " 10.0.0.2/24"),
@@ -184,8 +194,8 @@ void serial_test_tc_netkit_basic(void)
int err, ifindex;
err = create_netkit(NETKIT_L2, NETKIT_PASS, NETKIT_PASS,
- &ifindex, false, NETKIT_SCRUB_DEFAULT,
- NETKIT_SCRUB_DEFAULT);
+ &ifindex, NETKIT_SCRUB_DEFAULT,
+ NETKIT_SCRUB_DEFAULT, 0);
if (err)
return;
@@ -299,8 +309,8 @@ static void serial_test_tc_netkit_multi_links_target(int mode, int target)
int err, ifindex;
err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
- &ifindex, false, NETKIT_SCRUB_DEFAULT,
- NETKIT_SCRUB_DEFAULT);
+ &ifindex, NETKIT_SCRUB_DEFAULT,
+ NETKIT_SCRUB_DEFAULT, 0);
if (err)
return;
@@ -428,8 +438,8 @@ static void serial_test_tc_netkit_multi_opts_target(int mode, int target)
int err, ifindex;
err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
- &ifindex, false, NETKIT_SCRUB_DEFAULT,
- NETKIT_SCRUB_DEFAULT);
+ &ifindex, NETKIT_SCRUB_DEFAULT,
+ NETKIT_SCRUB_DEFAULT, 0);
if (err)
return;
@@ -543,8 +553,8 @@ void serial_test_tc_netkit_device(void)
int err, ifindex, ifindex2;
err = create_netkit(NETKIT_L3, NETKIT_PASS, NETKIT_PASS,
- &ifindex, true, NETKIT_SCRUB_DEFAULT,
- NETKIT_SCRUB_DEFAULT);
+ &ifindex, NETKIT_SCRUB_DEFAULT,
+ NETKIT_SCRUB_DEFAULT, FLAG_SAME_NETNS);
if (err)
return;
@@ -655,8 +665,8 @@ static void serial_test_tc_netkit_neigh_links_target(int mode, int target)
int err, ifindex;
err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
- &ifindex, false, NETKIT_SCRUB_DEFAULT,
- NETKIT_SCRUB_DEFAULT);
+ &ifindex, NETKIT_SCRUB_DEFAULT,
+ NETKIT_SCRUB_DEFAULT, 0);
if (err)
return;
@@ -733,8 +743,8 @@ static void serial_test_tc_netkit_pkt_type_mode(int mode)
struct bpf_link *link;
err = create_netkit(mode, NETKIT_PASS, NETKIT_PASS,
- &ifindex, true, NETKIT_SCRUB_DEFAULT,
- NETKIT_SCRUB_DEFAULT);
+ &ifindex, NETKIT_SCRUB_DEFAULT,
+ NETKIT_SCRUB_DEFAULT, FLAG_SAME_NETNS);
if (err)
return;
@@ -799,7 +809,7 @@ void serial_test_tc_netkit_pkt_type(void)
serial_test_tc_netkit_pkt_type_mode(NETKIT_L3);
}
-static void serial_test_tc_netkit_scrub_type(int scrub)
+static void serial_test_tc_netkit_scrub_type(int scrub, bool room)
{
LIBBPF_OPTS(bpf_netkit_opts, optl);
struct test_tc_link *skel;
@@ -807,7 +817,8 @@ static void serial_test_tc_netkit_scrub_type(int scrub)
int err, ifindex;
err = create_netkit(NETKIT_L2, NETKIT_PASS, NETKIT_PASS,
- &ifindex, false, scrub, scrub);
+ &ifindex, scrub, scrub,
+ room ? FLAG_ADJUST_ROOM : 0);
if (err)
return;
@@ -842,6 +853,8 @@ static void serial_test_tc_netkit_scrub_type(int scrub)
ASSERT_EQ(skel->bss->seen_tc8, true, "seen_tc8");
ASSERT_EQ(skel->bss->mark, scrub == NETKIT_SCRUB_NONE ? MARK : 0, "mark");
ASSERT_EQ(skel->bss->prio, scrub == NETKIT_SCRUB_NONE ? PRIO : 0, "prio");
+ ASSERT_EQ(skel->bss->headroom, room ? NETKIT_HEADROOM : 0, "headroom");
+ ASSERT_EQ(skel->bss->tailroom, room ? NETKIT_TAILROOM : 0, "tailroom");
cleanup:
test_tc_link__destroy(skel);
@@ -852,6 +865,6 @@ cleanup:
void serial_test_tc_netkit_scrub(void)
{
- serial_test_tc_netkit_scrub_type(NETKIT_SCRUB_DEFAULT);
- serial_test_tc_netkit_scrub_type(NETKIT_SCRUB_NONE);
+ serial_test_tc_netkit_scrub_type(NETKIT_SCRUB_DEFAULT, false);
+ serial_test_tc_netkit_scrub_type(NETKIT_SCRUB_NONE, true);
}
diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c
index d9f65adb456b..3ee40ee9413a 100644
--- a/tools/testing/selftests/bpf/prog_tests/verifier.c
+++ b/tools/testing/selftests/bpf/prog_tests/verifier.c
@@ -225,24 +225,7 @@ void test_verifier_xdp(void) { RUN(verifier_xdp); }
void test_verifier_xdp_direct_packet_access(void) { RUN(verifier_xdp_direct_packet_access); }
void test_verifier_bits_iter(void) { RUN(verifier_bits_iter); }
void test_verifier_lsm(void) { RUN(verifier_lsm); }
-
-void test_verifier_mtu(void)
-{
- __u64 caps = 0;
- int ret;
-
- /* In case CAP_BPF and CAP_PERFMON is not set */
- ret = cap_enable_effective(1ULL << CAP_BPF | 1ULL << CAP_NET_ADMIN, &caps);
- if (!ASSERT_OK(ret, "set_cap_bpf_cap_net_admin"))
- return;
- ret = cap_disable_effective(1ULL << CAP_SYS_ADMIN | 1ULL << CAP_PERFMON, NULL);
- if (!ASSERT_OK(ret, "disable_cap_sys_admin"))
- goto restore_cap;
- RUN(verifier_mtu);
-restore_cap:
- if (caps)
- cap_enable_effective(caps, NULL);
-}
+void test_verifier_mtu(void) { RUN(verifier_mtu); }
static int init_test_val_map(struct bpf_object *obj, char *map_name)
{
diff --git a/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c b/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
index e6a783c7f5db..937da9b7532a 100644
--- a/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
+++ b/tools/testing/selftests/bpf/prog_tests/xdp_context_test_run.c
@@ -2,6 +2,14 @@
#include <test_progs.h>
#include <network_helpers.h>
#include "test_xdp_context_test_run.skel.h"
+#include "test_xdp_meta.skel.h"
+
+#define TX_ADDR "10.0.0.1"
+#define RX_ADDR "10.0.0.2"
+#define RX_NAME "veth0"
+#define TX_NAME "veth1"
+#define TX_NETNS "xdp_context_tx"
+#define RX_NETNS "xdp_context_rx"
void test_xdp_context_error(int prog_fd, struct bpf_test_run_opts opts,
__u32 data_meta, __u32 data, __u32 data_end,
@@ -103,3 +111,82 @@ void test_xdp_context_test_run(void)
test_xdp_context_test_run__destroy(skel);
}
+
+void test_xdp_context_functional(void)
+{
+ LIBBPF_OPTS(bpf_tc_hook, tc_hook, .attach_point = BPF_TC_INGRESS);
+ LIBBPF_OPTS(bpf_tc_opts, tc_opts, .handle = 1, .priority = 1);
+ struct netns_obj *rx_ns = NULL, *tx_ns = NULL;
+ struct bpf_program *tc_prog, *xdp_prog;
+ struct test_xdp_meta *skel = NULL;
+ struct nstoken *nstoken = NULL;
+ int rx_ifindex;
+ int ret;
+
+ tx_ns = netns_new(TX_NETNS, false);
+ if (!ASSERT_OK_PTR(tx_ns, "create tx_ns"))
+ return;
+
+ rx_ns = netns_new(RX_NETNS, false);
+ if (!ASSERT_OK_PTR(rx_ns, "create rx_ns"))
+ goto close;
+
+ SYS(close, "ip link add " RX_NAME " netns " RX_NETNS
+ " type veth peer name " TX_NAME " netns " TX_NETNS);
+
+ nstoken = open_netns(RX_NETNS);
+ if (!ASSERT_OK_PTR(nstoken, "setns rx_ns"))
+ goto close;
+
+ SYS(close, "ip addr add " RX_ADDR "/24 dev " RX_NAME);
+ SYS(close, "ip link set dev " RX_NAME " up");
+
+ skel = test_xdp_meta__open_and_load();
+ if (!ASSERT_OK_PTR(skel, "open and load skeleton"))
+ goto close;
+
+ rx_ifindex = if_nametoindex(RX_NAME);
+ if (!ASSERT_GE(rx_ifindex, 0, "if_nametoindex rx"))
+ goto close;
+
+ tc_hook.ifindex = rx_ifindex;
+ ret = bpf_tc_hook_create(&tc_hook);
+ if (!ASSERT_OK(ret, "bpf_tc_hook_create"))
+ goto close;
+
+ tc_prog = bpf_object__find_program_by_name(skel->obj, "ing_cls");
+ if (!ASSERT_OK_PTR(tc_prog, "open ing_cls prog"))
+ goto close;
+
+ tc_opts.prog_fd = bpf_program__fd(tc_prog);
+ ret = bpf_tc_attach(&tc_hook, &tc_opts);
+ if (!ASSERT_OK(ret, "bpf_tc_attach"))
+ goto close;
+
+ xdp_prog = bpf_object__find_program_by_name(skel->obj, "ing_xdp");
+ if (!ASSERT_OK_PTR(xdp_prog, "open ing_xdp prog"))
+ goto close;
+
+ ret = bpf_xdp_attach(rx_ifindex,
+ bpf_program__fd(xdp_prog),
+ 0, NULL);
+ if (!ASSERT_GE(ret, 0, "bpf_xdp_attach"))
+ goto close;
+
+ close_netns(nstoken);
+
+ nstoken = open_netns(TX_NETNS);
+ if (!ASSERT_OK_PTR(nstoken, "setns tx_ns"))
+ goto close;
+
+ SYS(close, "ip addr add " TX_ADDR "/24 dev " TX_NAME);
+ SYS(close, "ip link set dev " TX_NAME " up");
+ ASSERT_OK(SYS_NOFAIL("ping -c 1 " RX_ADDR), "ping");
+
+close:
+ close_netns(nstoken);
+ test_xdp_meta__destroy(skel);
+ netns_free(rx_ns);
+ netns_free(tx_ns);
+}
+
diff --git a/tools/testing/selftests/bpf/progs/bpf_misc.h b/tools/testing/selftests/bpf/progs/bpf_misc.h
index eccaf955e394..f45f4352feeb 100644
--- a/tools/testing/selftests/bpf/progs/bpf_misc.h
+++ b/tools/testing/selftests/bpf/progs/bpf_misc.h
@@ -5,6 +5,10 @@
#define XSTR(s) STR(s)
#define STR(s) #s
+/* Expand a macro and then stringize the expansion */
+#define QUOTE(str) #str
+#define EXPAND_QUOTE(str) QUOTE(str)
+
/* This set of attributes controls behavior of the
* test_loader.c:test_loader__run_subtests().
*
@@ -106,6 +110,7 @@
* __arch_* Specify on which architecture the test case should be tested.
* Several __arch_* annotations could be specified at once.
* When test case is not run on current arch it is marked as skipped.
+ * __caps_unpriv Specify the capabilities that should be set when running the test.
*/
#define __msg(msg) __attribute__((btf_decl_tag("comment:test_expect_msg=" XSTR(__COUNTER__) "=" msg)))
#define __xlated(msg) __attribute__((btf_decl_tag("comment:test_expect_xlated=" XSTR(__COUNTER__) "=" msg)))
@@ -129,6 +134,13 @@
#define __arch_x86_64 __arch("X86_64")
#define __arch_arm64 __arch("ARM64")
#define __arch_riscv64 __arch("RISCV64")
+#define __caps_unpriv(caps) __attribute__((btf_decl_tag("comment:test_caps_unpriv=" EXPAND_QUOTE(caps))))
+
+/* Define common capabilities tested using __caps_unpriv */
+#define CAP_NET_ADMIN 12
+#define CAP_SYS_ADMIN 21
+#define CAP_PERFMON 38
+#define CAP_BPF 39
/* Convenience macro for use with 'asm volatile' blocks */
#define __naked __attribute__((naked))
diff --git a/tools/testing/selftests/bpf/progs/changes_pkt_data.c b/tools/testing/selftests/bpf/progs/changes_pkt_data.c
new file mode 100644
index 000000000000..43cada48b28a
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/changes_pkt_data.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+__noinline
+long changes_pkt_data(struct __sk_buff *sk)
+{
+ return bpf_skb_pull_data(sk, 0);
+}
+
+__noinline __weak
+long does_not_change_pkt_data(struct __sk_buff *sk)
+{
+ return 0;
+}
+
+SEC("?tc")
+int main_with_subprogs(struct __sk_buff *sk)
+{
+ changes_pkt_data(sk);
+ does_not_change_pkt_data(sk);
+ return 0;
+}
+
+SEC("?tc")
+int main_changes(struct __sk_buff *sk)
+{
+ bpf_skb_pull_data(sk, 0);
+ return 0;
+}
+
+SEC("?tc")
+int main_does_not_change(struct __sk_buff *sk)
+{
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c b/tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c
new file mode 100644
index 000000000000..f9a622705f1b
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/changes_pkt_data_freplace.c
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+SEC("?freplace")
+long changes_pkt_data(struct __sk_buff *sk)
+{
+ return bpf_skb_pull_data(sk, 0);
+}
+
+SEC("?freplace")
+long does_not_change_pkt_data(struct __sk_buff *sk)
+{
+ return 0;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/dynptr_fail.c b/tools/testing/selftests/bpf/progs/dynptr_fail.c
index 8f36c9de7591..dfd817d0348c 100644
--- a/tools/testing/selftests/bpf/progs/dynptr_fail.c
+++ b/tools/testing/selftests/bpf/progs/dynptr_fail.c
@@ -149,7 +149,7 @@ int ringbuf_release_uninit_dynptr(void *ctx)
/* A dynptr can't be used after it has been invalidated */
SEC("?raw_tp")
-__failure __msg("Expected an initialized dynptr as arg #3")
+__failure __msg("Expected an initialized dynptr as arg #2")
int use_after_invalid(void *ctx)
{
struct bpf_dynptr ptr;
@@ -428,7 +428,7 @@ int invalid_helper2(void *ctx)
/* A bpf_dynptr is invalidated if it's been written into */
SEC("?raw_tp")
-__failure __msg("Expected an initialized dynptr as arg #1")
+__failure __msg("Expected an initialized dynptr as arg #0")
int invalid_write1(void *ctx)
{
struct bpf_dynptr ptr;
@@ -1407,7 +1407,7 @@ int invalid_slice_rdwr_rdonly(struct __sk_buff *skb)
/* bpf_dynptr_adjust can only be called on initialized dynptrs */
SEC("?raw_tp")
-__failure __msg("Expected an initialized dynptr as arg #1")
+__failure __msg("Expected an initialized dynptr as arg #0")
int dynptr_adjust_invalid(void *ctx)
{
struct bpf_dynptr ptr = {};
@@ -1420,7 +1420,7 @@ int dynptr_adjust_invalid(void *ctx)
/* bpf_dynptr_is_null can only be called on initialized dynptrs */
SEC("?raw_tp")
-__failure __msg("Expected an initialized dynptr as arg #1")
+__failure __msg("Expected an initialized dynptr as arg #0")
int dynptr_is_null_invalid(void *ctx)
{
struct bpf_dynptr ptr = {};
@@ -1433,7 +1433,7 @@ int dynptr_is_null_invalid(void *ctx)
/* bpf_dynptr_is_rdonly can only be called on initialized dynptrs */
SEC("?raw_tp")
-__failure __msg("Expected an initialized dynptr as arg #1")
+__failure __msg("Expected an initialized dynptr as arg #0")
int dynptr_is_rdonly_invalid(void *ctx)
{
struct bpf_dynptr ptr = {};
@@ -1446,7 +1446,7 @@ int dynptr_is_rdonly_invalid(void *ctx)
/* bpf_dynptr_size can only be called on initialized dynptrs */
SEC("?raw_tp")
-__failure __msg("Expected an initialized dynptr as arg #1")
+__failure __msg("Expected an initialized dynptr as arg #0")
int dynptr_size_invalid(void *ctx)
{
struct bpf_dynptr ptr = {};
@@ -1459,7 +1459,7 @@ int dynptr_size_invalid(void *ctx)
/* Only initialized dynptrs can be cloned */
SEC("?raw_tp")
-__failure __msg("Expected an initialized dynptr as arg #1")
+__failure __msg("Expected an initialized dynptr as arg #0")
int clone_invalid1(void *ctx)
{
struct bpf_dynptr ptr1 = {};
@@ -1493,7 +1493,7 @@ int clone_invalid2(struct xdp_md *xdp)
/* Invalidating a dynptr should invalidate its clones */
SEC("?raw_tp")
-__failure __msg("Expected an initialized dynptr as arg #3")
+__failure __msg("Expected an initialized dynptr as arg #2")
int clone_invalidate1(void *ctx)
{
struct bpf_dynptr clone;
@@ -1514,7 +1514,7 @@ int clone_invalidate1(void *ctx)
/* Invalidating a dynptr should invalidate its parent */
SEC("?raw_tp")
-__failure __msg("Expected an initialized dynptr as arg #3")
+__failure __msg("Expected an initialized dynptr as arg #2")
int clone_invalidate2(void *ctx)
{
struct bpf_dynptr ptr;
@@ -1535,7 +1535,7 @@ int clone_invalidate2(void *ctx)
/* Invalidating a dynptr should invalidate its siblings */
SEC("?raw_tp")
-__failure __msg("Expected an initialized dynptr as arg #3")
+__failure __msg("Expected an initialized dynptr as arg #2")
int clone_invalidate3(void *ctx)
{
struct bpf_dynptr ptr;
@@ -1723,7 +1723,7 @@ __noinline long global_call_bpf_dynptr(const struct bpf_dynptr *dynptr)
}
SEC("?raw_tp")
-__failure __msg("arg#1 expected pointer to stack or const struct bpf_dynptr")
+__failure __msg("arg#0 expected pointer to stack or const struct bpf_dynptr")
int test_dynptr_reg_type(void *ctx)
{
struct task_struct *current = NULL;
diff --git a/tools/testing/selftests/bpf/progs/iters.c b/tools/testing/selftests/bpf/progs/iters.c
index ef70b88bccb2..7c969c127573 100644
--- a/tools/testing/selftests/bpf/progs/iters.c
+++ b/tools/testing/selftests/bpf/progs/iters.c
@@ -1486,4 +1486,30 @@ int iter_subprog_check_stacksafe(const void *ctx)
return 0;
}
+struct bpf_iter_num global_it;
+
+SEC("raw_tp")
+__failure __msg("arg#0 expected pointer to an iterator on stack")
+int iter_new_bad_arg(const void *ctx)
+{
+ bpf_iter_num_new(&global_it, 0, 1);
+ return 0;
+}
+
+SEC("raw_tp")
+__failure __msg("arg#0 expected pointer to an iterator on stack")
+int iter_next_bad_arg(const void *ctx)
+{
+ bpf_iter_num_next(&global_it);
+ return 0;
+}
+
+SEC("raw_tp")
+__failure __msg("arg#0 expected pointer to an iterator on stack")
+int iter_destroy_bad_arg(const void *ctx)
+{
+ bpf_iter_num_destroy(&global_it);
+ return 0;
+}
+
char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/iters_state_safety.c b/tools/testing/selftests/bpf/progs/iters_state_safety.c
index d47e59aba6de..f41257eadbb2 100644
--- a/tools/testing/selftests/bpf/progs/iters_state_safety.c
+++ b/tools/testing/selftests/bpf/progs/iters_state_safety.c
@@ -73,7 +73,7 @@ int create_and_forget_to_destroy_fail(void *ctx)
}
SEC("?raw_tp")
-__failure __msg("expected an initialized iter_num as arg #1")
+__failure __msg("expected an initialized iter_num as arg #0")
int destroy_without_creating_fail(void *ctx)
{
/* init with zeros to stop verifier complaining about uninit stack */
@@ -91,7 +91,7 @@ int destroy_without_creating_fail(void *ctx)
}
SEC("?raw_tp")
-__failure __msg("expected an initialized iter_num as arg #1")
+__failure __msg("expected an initialized iter_num as arg #0")
int compromise_iter_w_direct_write_fail(void *ctx)
{
struct bpf_iter_num iter;
@@ -143,7 +143,7 @@ int compromise_iter_w_direct_write_and_skip_destroy_fail(void *ctx)
}
SEC("?raw_tp")
-__failure __msg("expected an initialized iter_num as arg #1")
+__failure __msg("expected an initialized iter_num as arg #0")
int compromise_iter_w_helper_write_fail(void *ctx)
{
struct bpf_iter_num iter;
@@ -230,7 +230,7 @@ int valid_stack_reuse(void *ctx)
}
SEC("?raw_tp")
-__failure __msg("expected uninitialized iter_num as arg #1")
+__failure __msg("expected uninitialized iter_num as arg #0")
int double_create_fail(void *ctx)
{
struct bpf_iter_num iter;
@@ -258,7 +258,7 @@ int double_create_fail(void *ctx)
}
SEC("?raw_tp")
-__failure __msg("expected an initialized iter_num as arg #1")
+__failure __msg("expected an initialized iter_num as arg #0")
int double_destroy_fail(void *ctx)
{
struct bpf_iter_num iter;
@@ -284,7 +284,7 @@ int double_destroy_fail(void *ctx)
}
SEC("?raw_tp")
-__failure __msg("expected an initialized iter_num as arg #1")
+__failure __msg("expected an initialized iter_num as arg #0")
int next_without_new_fail(void *ctx)
{
struct bpf_iter_num iter;
@@ -305,7 +305,7 @@ int next_without_new_fail(void *ctx)
}
SEC("?raw_tp")
-__failure __msg("expected an initialized iter_num as arg #1")
+__failure __msg("expected an initialized iter_num as arg #0")
int next_after_destroy_fail(void *ctx)
{
struct bpf_iter_num iter;
diff --git a/tools/testing/selftests/bpf/progs/iters_testmod_seq.c b/tools/testing/selftests/bpf/progs/iters_testmod_seq.c
index 4a176e6aede8..6543d5b6e0a9 100644
--- a/tools/testing/selftests/bpf/progs/iters_testmod_seq.c
+++ b/tools/testing/selftests/bpf/progs/iters_testmod_seq.c
@@ -79,7 +79,7 @@ int testmod_seq_truncated(const void *ctx)
SEC("?raw_tp")
__failure
-__msg("expected an initialized iter_testmod_seq as arg #2")
+__msg("expected an initialized iter_testmod_seq as arg #1")
int testmod_seq_getter_before_bad(const void *ctx)
{
struct bpf_iter_testmod_seq it;
@@ -89,7 +89,7 @@ int testmod_seq_getter_before_bad(const void *ctx)
SEC("?raw_tp")
__failure
-__msg("expected an initialized iter_testmod_seq as arg #2")
+__msg("expected an initialized iter_testmod_seq as arg #1")
int testmod_seq_getter_after_bad(const void *ctx)
{
struct bpf_iter_testmod_seq it;
diff --git a/tools/testing/selftests/bpf/progs/raw_tp_null.c b/tools/testing/selftests/bpf/progs/raw_tp_null.c
index 457f34c151e3..5927054b6dd9 100644
--- a/tools/testing/selftests/bpf/progs/raw_tp_null.c
+++ b/tools/testing/selftests/bpf/progs/raw_tp_null.c
@@ -3,6 +3,7 @@
#include <vmlinux.h>
#include <bpf/bpf_tracing.h>
+#include "bpf_misc.h"
char _license[] SEC("license") = "GPL";
@@ -17,16 +18,14 @@ int BPF_PROG(test_raw_tp_null, struct sk_buff *skb)
if (task->pid != tid)
return 0;
- i = i + skb->mark + 1;
- /* The compiler may move the NULL check before this deref, which causes
- * the load to fail as deref of scalar. Prevent that by using a barrier.
+ /* If dead code elimination kicks in, the increment +=2 will be
+ * removed. For raw_tp programs attaching to tracepoints in kernel
+ * modules, we mark input arguments as PTR_MAYBE_NULL, so branch
+ * prediction should never kick in.
*/
- barrier();
- /* If dead code elimination kicks in, the increment below will
- * be removed. For raw_tp programs, we mark input arguments as
- * PTR_MAYBE_NULL, so branch prediction should never kick in.
- */
- if (!skb)
- i += 2;
+ asm volatile ("%[i] += 1; if %[ctx] != 0 goto +1; %[i] += 2;"
+ : [i]"+r"(i)
+ : [ctx]"r"(skb)
+ : "memory");
return 0;
}
diff --git a/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c b/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c
new file mode 100644
index 000000000000..38d669957bf1
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/raw_tp_null_fail.c
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024 Meta Platforms, Inc. and affiliates. */
+
+#include <vmlinux.h>
+#include <bpf/bpf_tracing.h>
+#include "bpf_misc.h"
+
+char _license[] SEC("license") = "GPL";
+
+/* Ensure module parameter has PTR_MAYBE_NULL */
+SEC("tp_btf/bpf_testmod_test_raw_tp_null")
+__failure __msg("R1 invalid mem access 'trusted_ptr_or_null_'")
+int test_raw_tp_null_bpf_testmod_test_raw_tp_null_arg_1(void *ctx) {
+ asm volatile("r1 = *(u64 *)(r1 +0); r1 = *(u64 *)(r1 +0);" ::: __clobber_all);
+ return 0;
+}
+
+/* Check NULL marking */
+SEC("tp_btf/sched_pi_setprio")
+__failure __msg("R1 invalid mem access 'trusted_ptr_or_null_'")
+int test_raw_tp_null_sched_pi_setprio_arg_2(void *ctx) {
+ asm volatile("r1 = *(u64 *)(r1 +8); r1 = *(u64 *)(r1 +0);" ::: __clobber_all);
+ return 0;
+}
diff --git a/tools/testing/selftests/bpf/progs/read_bpf_task_storage_busy.c b/tools/testing/selftests/bpf/progs/read_bpf_task_storage_busy.c
index 76556e0b42b2..69da05bb6c63 100644
--- a/tools/testing/selftests/bpf/progs/read_bpf_task_storage_busy.c
+++ b/tools/testing/selftests/bpf/progs/read_bpf_task_storage_busy.c
@@ -4,7 +4,7 @@
#include <bpf/bpf_helpers.h>
#include <bpf/bpf_tracing.h>
-extern bool CONFIG_PREEMPT __kconfig __weak;
+extern bool CONFIG_PREEMPTION __kconfig __weak;
extern const int bpf_task_storage_busy __ksym;
char _license[] SEC("license") = "GPL";
@@ -24,7 +24,7 @@ int BPF_PROG(read_bpf_task_storage_busy)
{
int *value;
- if (!CONFIG_PREEMPT)
+ if (!CONFIG_PREEMPTION)
return 0;
if (bpf_get_current_pid_tgid() >> 32 != pid)
diff --git a/tools/testing/selftests/bpf/progs/task_storage_nodeadlock.c b/tools/testing/selftests/bpf/progs/task_storage_nodeadlock.c
index ea2dbb80f7b3..986829aaf73a 100644
--- a/tools/testing/selftests/bpf/progs/task_storage_nodeadlock.c
+++ b/tools/testing/selftests/bpf/progs/task_storage_nodeadlock.c
@@ -10,7 +10,7 @@ char _license[] SEC("license") = "GPL";
#define EBUSY 16
#endif
-extern bool CONFIG_PREEMPT __kconfig __weak;
+extern bool CONFIG_PREEMPTION __kconfig __weak;
int nr_get_errs = 0;
int nr_del_errs = 0;
@@ -29,7 +29,7 @@ int BPF_PROG(socket_post_create, struct socket *sock, int family, int type,
int ret, zero = 0;
int *value;
- if (!CONFIG_PREEMPT)
+ if (!CONFIG_PREEMPTION)
return 0;
task = bpf_get_current_task_btf();
diff --git a/tools/testing/selftests/bpf/progs/tc_bpf2bpf.c b/tools/testing/selftests/bpf/progs/tc_bpf2bpf.c
index d1a57f7d09bd..fe6249d99b31 100644
--- a/tools/testing/selftests/bpf/progs/tc_bpf2bpf.c
+++ b/tools/testing/selftests/bpf/progs/tc_bpf2bpf.c
@@ -11,6 +11,8 @@ int subprog_tc(struct __sk_buff *skb)
__sink(skb);
__sink(ret);
+ /* let verifier know that 'subprog_tc' can change pointers to skb->data */
+ bpf_skb_change_proto(skb, 0, 0);
return ret;
}
diff --git a/tools/testing/selftests/bpf/progs/test_kfunc_dynptr_param.c b/tools/testing/selftests/bpf/progs/test_kfunc_dynptr_param.c
index e68667aec6a6..cd4d752bd089 100644
--- a/tools/testing/selftests/bpf/progs/test_kfunc_dynptr_param.c
+++ b/tools/testing/selftests/bpf/progs/test_kfunc_dynptr_param.c
@@ -45,7 +45,7 @@ int BPF_PROG(not_valid_dynptr, int cmd, union bpf_attr *attr, unsigned int size)
}
SEC("?lsm.s/bpf")
-__failure __msg("arg#1 expected pointer to stack or const struct bpf_dynptr")
+__failure __msg("arg#0 expected pointer to stack or const struct bpf_dynptr")
int BPF_PROG(not_ptr_to_stack, int cmd, union bpf_attr *attr, unsigned int size)
{
unsigned long val = 0;
diff --git a/tools/testing/selftests/bpf/progs/test_sockmap_change_tail.c b/tools/testing/selftests/bpf/progs/test_sockmap_change_tail.c
new file mode 100644
index 000000000000..2796dd8545eb
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_sockmap_change_tail.c
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright (c) 2024 ByteDance */
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+
+struct {
+ __uint(type, BPF_MAP_TYPE_SOCKMAP);
+ __uint(max_entries, 1);
+ __type(key, int);
+ __type(value, int);
+} sock_map_rx SEC(".maps");
+
+long change_tail_ret = 1;
+
+SEC("sk_skb")
+int prog_skb_verdict(struct __sk_buff *skb)
+{
+ char *data, *data_end;
+
+ bpf_skb_pull_data(skb, 1);
+ data = (char *)(unsigned long)skb->data;
+ data_end = (char *)(unsigned long)skb->data_end;
+
+ if (data + 1 > data_end)
+ return SK_PASS;
+
+ if (data[0] == 'T') { /* Trim the packet */
+ change_tail_ret = bpf_skb_change_tail(skb, skb->len - 1, 0);
+ return SK_PASS;
+ } else if (data[0] == 'G') { /* Grow the packet */
+ change_tail_ret = bpf_skb_change_tail(skb, skb->len + 1, 0);
+ return SK_PASS;
+ } else if (data[0] == 'E') { /* Error */
+ change_tail_ret = bpf_skb_change_tail(skb, 65535, 0);
+ return SK_PASS;
+ }
+ return SK_PASS;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_tc_change_tail.c b/tools/testing/selftests/bpf/progs/test_tc_change_tail.c
new file mode 100644
index 000000000000..28edafe803f0
--- /dev/null
+++ b/tools/testing/selftests/bpf/progs/test_tc_change_tail.c
@@ -0,0 +1,106 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <linux/bpf.h>
+#include <bpf/bpf_helpers.h>
+#include <linux/if_ether.h>
+#include <linux/in.h>
+#include <linux/ip.h>
+#include <linux/udp.h>
+#include <linux/pkt_cls.h>
+
+long change_tail_ret = 1;
+
+static __always_inline struct iphdr *parse_ip_header(struct __sk_buff *skb, int *ip_proto)
+{
+ void *data_end = (void *)(long)skb->data_end;
+ void *data = (void *)(long)skb->data;
+ struct ethhdr *eth = data;
+ struct iphdr *iph;
+
+ /* Verify Ethernet header */
+ if ((void *)(data + sizeof(*eth)) > data_end)
+ return NULL;
+
+ /* Skip Ethernet header to get to IP header */
+ iph = (void *)(data + sizeof(struct ethhdr));
+
+ /* Verify IP header */
+ if ((void *)(data + sizeof(struct ethhdr) + sizeof(*iph)) > data_end)
+ return NULL;
+
+ /* Basic IP header validation */
+ if (iph->version != 4) /* Only support IPv4 */
+ return NULL;
+
+ if (iph->ihl < 5) /* Minimum IP header length */
+ return NULL;
+
+ *ip_proto = iph->protocol;
+ return iph;
+}
+
+static __always_inline struct udphdr *parse_udp_header(struct __sk_buff *skb, struct iphdr *iph)
+{
+ void *data_end = (void *)(long)skb->data_end;
+ void *hdr = (void *)iph;
+ struct udphdr *udp;
+
+ /* Calculate UDP header position */
+ udp = hdr + (iph->ihl * 4);
+ hdr = (void *)udp;
+
+ /* Verify UDP header bounds */
+ if ((void *)(hdr + sizeof(*udp)) > data_end)
+ return NULL;
+
+ return udp;
+}
+
+SEC("tc/ingress")
+int change_tail(struct __sk_buff *skb)
+{
+ int len = skb->len;
+ struct udphdr *udp;
+ struct iphdr *iph;
+ void *data_end;
+ char *payload;
+ int ip_proto;
+
+ bpf_skb_pull_data(skb, len);
+
+ data_end = (void *)(long)skb->data_end;
+ iph = parse_ip_header(skb, &ip_proto);
+ if (!iph)
+ return TCX_PASS;
+
+ if (ip_proto != IPPROTO_UDP)
+ return TCX_PASS;
+
+ udp = parse_udp_header(skb, iph);
+ if (!udp)
+ return TCX_PASS;
+
+ payload = (char *)udp + (sizeof(struct udphdr));
+ if (payload + 1 > (char *)data_end)
+ return TCX_PASS;
+
+ if (payload[0] == 'T') { /* Trim the packet */
+ change_tail_ret = bpf_skb_change_tail(skb, len - 1, 0);
+ if (!change_tail_ret)
+ bpf_skb_change_tail(skb, len, 0);
+ return TCX_PASS;
+ } else if (payload[0] == 'G') { /* Grow the packet */
+ change_tail_ret = bpf_skb_change_tail(skb, len + 1, 0);
+ if (!change_tail_ret)
+ bpf_skb_change_tail(skb, len, 0);
+ return TCX_PASS;
+ } else if (payload[0] == 'E') { /* Error */
+ change_tail_ret = bpf_skb_change_tail(skb, 65535, 0);
+ return TCX_PASS;
+ } else if (payload[0] == 'Z') { /* Zero */
+ change_tail_ret = bpf_skb_change_tail(skb, 0, 0);
+ return TCX_PASS;
+ }
+ return TCX_DROP;
+}
+
+char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/test_tc_link.c b/tools/testing/selftests/bpf/progs/test_tc_link.c
index 10d825928499..630f12e51b07 100644
--- a/tools/testing/selftests/bpf/progs/test_tc_link.c
+++ b/tools/testing/selftests/bpf/progs/test_tc_link.c
@@ -8,6 +8,7 @@
#include <linux/if_packet.h>
#include <bpf/bpf_endian.h>
#include <bpf/bpf_helpers.h>
+#include <bpf/bpf_core_read.h>
char LICENSE[] SEC("license") = "GPL";
@@ -27,6 +28,7 @@ bool seen_host;
bool seen_mcast;
int mark, prio;
+unsigned short headroom, tailroom;
SEC("tc/ingress")
int tc1(struct __sk_buff *skb)
@@ -104,11 +106,24 @@ out:
return TCX_PASS;
}
+struct sk_buff {
+ struct net_device *dev;
+};
+
+struct net_device {
+ unsigned short needed_headroom;
+ unsigned short needed_tailroom;
+};
+
SEC("tc/egress")
int tc8(struct __sk_buff *skb)
{
+ struct net_device *dev = BPF_CORE_READ((struct sk_buff *)skb, dev);
+
seen_tc8 = true;
mark = skb->mark;
prio = skb->priority;
+ headroom = BPF_CORE_READ(dev, needed_headroom);
+ tailroom = BPF_CORE_READ(dev, needed_tailroom);
return TCX_PASS;
}
diff --git a/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c b/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c
index 5aaf2b065f86..bba3e37f749b 100644
--- a/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c
+++ b/tools/testing/selftests/bpf/progs/test_tp_btf_nullable.c
@@ -7,11 +7,7 @@
#include "bpf_misc.h"
SEC("tp_btf/bpf_testmod_test_nullable_bare")
-/* This used to be a failure test, but raw_tp nullable arguments can now
- * directly be dereferenced, whether they have nullable annotation or not,
- * and don't need to be explicitly checked.
- */
-__success
+__failure __msg("R1 invalid mem access 'trusted_ptr_or_null_'")
int BPF_PROG(handle_tp_btf_nullable_bare1, struct bpf_testmod_test_read_ctx *nullable_ctx)
{
return nullable_ctx->len;
diff --git a/tools/testing/selftests/bpf/progs/test_xdp_meta.c b/tools/testing/selftests/bpf/progs/test_xdp_meta.c
index a7c4a7d49fe6..fe2d71ae0e71 100644
--- a/tools/testing/selftests/bpf/progs/test_xdp_meta.c
+++ b/tools/testing/selftests/bpf/progs/test_xdp_meta.c
@@ -8,7 +8,7 @@
#define round_up(x, y) ((((x) - 1) | __round_mask(x, y)) + 1)
#define ctx_ptr(ctx, mem) (void *)(unsigned long)ctx->mem
-SEC("t")
+SEC("tc")
int ing_cls(struct __sk_buff *ctx)
{
__u8 *data, *data_meta, *data_end;
@@ -28,7 +28,7 @@ int ing_cls(struct __sk_buff *ctx)
return diff ? TC_ACT_SHOT : TC_ACT_OK;
}
-SEC("x")
+SEC("xdp")
int ing_xdp(struct xdp_md *ctx)
{
__u8 *data, *data_meta, *data_end;
diff --git a/tools/testing/selftests/bpf/progs/verifier_bits_iter.c b/tools/testing/selftests/bpf/progs/verifier_bits_iter.c
index 7c881bca9af5..8bcddadfc4da 100644
--- a/tools/testing/selftests/bpf/progs/verifier_bits_iter.c
+++ b/tools/testing/selftests/bpf/progs/verifier_bits_iter.c
@@ -32,18 +32,18 @@ int BPF_PROG(no_destroy, struct bpf_iter_meta *meta, struct cgroup *cgrp)
SEC("iter/cgroup")
__description("uninitialized iter in ->next()")
-__failure __msg("expected an initialized iter_bits as arg #1")
+__failure __msg("expected an initialized iter_bits as arg #0")
int BPF_PROG(next_uninit, struct bpf_iter_meta *meta, struct cgroup *cgrp)
{
- struct bpf_iter_bits *it = NULL;
+ struct bpf_iter_bits it = {};
- bpf_iter_bits_next(it);
+ bpf_iter_bits_next(&it);
return 0;
}
SEC("iter/cgroup")
__description("uninitialized iter in ->destroy()")
-__failure __msg("expected an initialized iter_bits as arg #1")
+__failure __msg("expected an initialized iter_bits as arg #0")
int BPF_PROG(destroy_uninit, struct bpf_iter_meta *meta, struct cgroup *cgrp)
{
struct bpf_iter_bits it = {};
diff --git a/tools/testing/selftests/bpf/progs/verifier_btf_ctx_access.c b/tools/testing/selftests/bpf/progs/verifier_btf_ctx_access.c
index a570e48b917a..28b939572cda 100644
--- a/tools/testing/selftests/bpf/progs/verifier_btf_ctx_access.c
+++ b/tools/testing/selftests/bpf/progs/verifier_btf_ctx_access.c
@@ -11,7 +11,7 @@ __success __retval(0)
__naked void btf_ctx_access_accept(void)
{
asm volatile (" \
- r2 = *(u32*)(r1 + 8); /* load 2nd argument value (int pointer) */\
+ r2 = *(u64 *)(r1 + 8); /* load 2nd argument value (int pointer) */\
r0 = 0; \
exit; \
" ::: __clobber_all);
@@ -23,7 +23,43 @@ __success __retval(0)
__naked void ctx_access_u32_pointer_accept(void)
{
asm volatile (" \
- r2 = *(u32*)(r1 + 0); /* load 1nd argument value (u32 pointer) */\
+ r2 = *(u64 *)(r1 + 0); /* load 1nd argument value (u32 pointer) */\
+ r0 = 0; \
+ exit; \
+" ::: __clobber_all);
+}
+
+SEC("fentry/bpf_fentry_test9")
+__description("btf_ctx_access u32 pointer reject u32")
+__failure __msg("size 4 must be 8")
+__naked void ctx_access_u32_pointer_reject_32(void)
+{
+ asm volatile (" \
+ r2 = *(u32 *)(r1 + 0); /* load 1st argument with narrow load */\
+ r0 = 0; \
+ exit; \
+" ::: __clobber_all);
+}
+
+SEC("fentry/bpf_fentry_test9")
+__description("btf_ctx_access u32 pointer reject u16")
+__failure __msg("size 2 must be 8")
+__naked void ctx_access_u32_pointer_reject_16(void)
+{
+ asm volatile (" \
+ r2 = *(u16 *)(r1 + 0); /* load 1st argument with narrow load */\
+ r0 = 0; \
+ exit; \
+" ::: __clobber_all);
+}
+
+SEC("fentry/bpf_fentry_test9")
+__description("btf_ctx_access u32 pointer reject u8")
+__failure __msg("size 1 must be 8")
+__naked void ctx_access_u32_pointer_reject_8(void)
+{
+ asm volatile (" \
+ r2 = *(u8 *)(r1 + 0); /* load 1st argument with narrow load */\
r0 = 0; \
exit; \
" ::: __clobber_all);
diff --git a/tools/testing/selftests/bpf/progs/verifier_d_path.c b/tools/testing/selftests/bpf/progs/verifier_d_path.c
index ec79cbcfde91..87e51a215558 100644
--- a/tools/testing/selftests/bpf/progs/verifier_d_path.c
+++ b/tools/testing/selftests/bpf/progs/verifier_d_path.c
@@ -11,7 +11,7 @@ __success __retval(0)
__naked void d_path_accept(void)
{
asm volatile (" \
- r1 = *(u32*)(r1 + 0); \
+ r1 = *(u64 *)(r1 + 0); \
r2 = r10; \
r2 += -8; \
r6 = 0; \
@@ -31,7 +31,7 @@ __failure __msg("helper call is not allowed in probe")
__naked void d_path_reject(void)
{
asm volatile (" \
- r1 = *(u32*)(r1 + 0); \
+ r1 = *(u64 *)(r1 + 0); \
r2 = r10; \
r2 += -8; \
r6 = 0; \
diff --git a/tools/testing/selftests/bpf/progs/verifier_mtu.c b/tools/testing/selftests/bpf/progs/verifier_mtu.c
index 70c7600a26a0..4ccf1ebc42d1 100644
--- a/tools/testing/selftests/bpf/progs/verifier_mtu.c
+++ b/tools/testing/selftests/bpf/progs/verifier_mtu.c
@@ -6,7 +6,9 @@
SEC("tc/ingress")
__description("uninit/mtu: write rejected")
-__failure __msg("invalid indirect read from stack")
+__success
+__caps_unpriv(CAP_BPF|CAP_NET_ADMIN)
+__failure_unpriv __msg_unpriv("invalid indirect read from stack")
int tc_uninit_mtu(struct __sk_buff *ctx)
{
__u32 mtu;
diff --git a/tools/testing/selftests/bpf/progs/verifier_sock.c b/tools/testing/selftests/bpf/progs/verifier_sock.c
index d3e70e38e442..0d5e56dffabb 100644
--- a/tools/testing/selftests/bpf/progs/verifier_sock.c
+++ b/tools/testing/selftests/bpf/progs/verifier_sock.c
@@ -50,6 +50,13 @@ struct {
__uint(map_flags, BPF_F_NO_PREALLOC);
} sk_storage_map SEC(".maps");
+struct {
+ __uint(type, BPF_MAP_TYPE_PROG_ARRAY);
+ __uint(max_entries, 1);
+ __uint(key_size, sizeof(__u32));
+ __uint(value_size, sizeof(__u32));
+} jmp_table SEC(".maps");
+
SEC("cgroup/skb")
__description("skb->sk: no NULL check")
__failure __msg("invalid mem access 'sock_common_or_null'")
@@ -1037,4 +1044,53 @@ __naked void sock_create_read_src_port(void)
: __clobber_all);
}
+__noinline
+long skb_pull_data2(struct __sk_buff *sk, __u32 len)
+{
+ return bpf_skb_pull_data(sk, len);
+}
+
+__noinline
+long skb_pull_data1(struct __sk_buff *sk, __u32 len)
+{
+ return skb_pull_data2(sk, len);
+}
+
+/* global function calls bpf_skb_pull_data(), which invalidates packet
+ * pointers established before global function call.
+ */
+SEC("tc")
+__failure __msg("invalid mem access")
+int invalidate_pkt_pointers_from_global_func(struct __sk_buff *sk)
+{
+ int *p = (void *)(long)sk->data;
+
+ if ((void *)(p + 1) > (void *)(long)sk->data_end)
+ return TCX_DROP;
+ skb_pull_data1(sk, 0);
+ *p = 42; /* this is unsafe */
+ return TCX_PASS;
+}
+
+__noinline
+int tail_call(struct __sk_buff *sk)
+{
+ bpf_tail_call_static(sk, &jmp_table, 0);
+ return 0;
+}
+
+/* Tail calls invalidate packet pointers. */
+SEC("tc")
+__failure __msg("invalid mem access")
+int invalidate_pkt_pointers_by_tail_call(struct __sk_buff *sk)
+{
+ int *p = (void *)(long)sk->data;
+
+ if ((void *)(p + 1) > (void *)(long)sk->data_end)
+ return TCX_DROP;
+ tail_call(sk);
+ *p = 42; /* this is unsafe */
+ return TCX_PASS;
+}
+
char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
index 671d9f415dbf..1e5a511e8494 100644
--- a/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
+++ b/tools/testing/selftests/bpf/progs/verifier_spill_fill.c
@@ -1244,4 +1244,39 @@ __naked void old_stack_misc_vs_cur_ctx_ptr(void)
: __clobber_all);
}
+SEC("socket")
+__description("stack_noperfmon: reject read of invalid slots")
+__success
+__caps_unpriv(CAP_BPF)
+__failure_unpriv __msg_unpriv("invalid read from stack off -8+1 size 8")
+__naked void stack_noperfmon_reject_invalid_read(void)
+{
+ asm volatile (" \
+ r2 = 1; \
+ r6 = r10; \
+ r6 += -8; \
+ *(u8 *)(r6 + 0) = r2; \
+ r2 = *(u64 *)(r6 + 0); \
+ r0 = 0; \
+ exit; \
+" ::: __clobber_all);
+}
+
+SEC("socket")
+__description("stack_noperfmon: narrow spill onto 64-bit scalar spilled slots")
+__success
+__caps_unpriv(CAP_BPF)
+__success_unpriv
+__naked void stack_noperfmon_spill_32bit_onto_64bit_slot(void)
+{
+ asm volatile(" \
+ r0 = 0; \
+ *(u64 *)(r10 - 8) = r0; \
+ *(u32 *)(r10 - 8) = r0; \
+ exit; \
+" :
+ :
+ : __clobber_all);
+}
+
char _license[] SEC("license") = "GPL";
diff --git a/tools/testing/selftests/bpf/sdt.h b/tools/testing/selftests/bpf/sdt.h
index ca0162b4dc57..1fcfa5160231 100644
--- a/tools/testing/selftests/bpf/sdt.h
+++ b/tools/testing/selftests/bpf/sdt.h
@@ -102,6 +102,8 @@
# define STAP_SDT_ARG_CONSTRAINT nZr
# elif defined __arm__
# define STAP_SDT_ARG_CONSTRAINT g
+# elif defined __loongarch__
+# define STAP_SDT_ARG_CONSTRAINT nmr
# else
# define STAP_SDT_ARG_CONSTRAINT nor
# endif
diff --git a/tools/testing/selftests/bpf/test_loader.c b/tools/testing/selftests/bpf/test_loader.c
index 3e9b009580d4..53b06647cf57 100644
--- a/tools/testing/selftests/bpf/test_loader.c
+++ b/tools/testing/selftests/bpf/test_loader.c
@@ -36,6 +36,7 @@
#define TEST_TAG_ARCH "comment:test_arch="
#define TEST_TAG_JITED_PFX "comment:test_jited="
#define TEST_TAG_JITED_PFX_UNPRIV "comment:test_jited_unpriv="
+#define TEST_TAG_CAPS_UNPRIV "comment:test_caps_unpriv="
/* Warning: duplicated in bpf_misc.h */
#define POINTER_VALUE 0xcafe4all
@@ -74,6 +75,7 @@ struct test_subspec {
struct expected_msgs jited;
int retval;
bool execute;
+ __u64 caps;
};
struct test_spec {
@@ -276,6 +278,37 @@ static int parse_int(const char *str, int *val, const char *name)
return 0;
}
+static int parse_caps(const char *str, __u64 *val, const char *name)
+{
+ int cap_flag = 0;
+ char *token = NULL, *saveptr = NULL;
+
+ char *str_cpy = strdup(str);
+ if (str_cpy == NULL) {
+ PRINT_FAIL("Memory allocation failed\n");
+ return -EINVAL;
+ }
+
+ token = strtok_r(str_cpy, "|", &saveptr);
+ while (token != NULL) {
+ errno = 0;
+ if (!strncmp("CAP_", token, sizeof("CAP_") - 1)) {
+ PRINT_FAIL("define %s constant in bpf_misc.h, failed to parse caps\n", token);
+ return -EINVAL;
+ }
+ cap_flag = strtol(token, NULL, 10);
+ if (!cap_flag || errno) {
+ PRINT_FAIL("failed to parse caps %s\n", name);
+ return -EINVAL;
+ }
+ *val |= (1ULL << cap_flag);
+ token = strtok_r(NULL, "|", &saveptr);
+ }
+
+ free(str_cpy);
+ return 0;
+}
+
static int parse_retval(const char *str, int *val, const char *name)
{
struct {
@@ -541,6 +574,12 @@ static int parse_test_spec(struct test_loader *tester,
jit_on_next_line = true;
} else if (str_has_pfx(s, TEST_BTF_PATH)) {
spec->btf_custom_path = s + sizeof(TEST_BTF_PATH) - 1;
+ } else if (str_has_pfx(s, TEST_TAG_CAPS_UNPRIV)) {
+ val = s + sizeof(TEST_TAG_CAPS_UNPRIV) - 1;
+ err = parse_caps(val, &spec->unpriv.caps, "test caps");
+ if (err)
+ goto cleanup;
+ spec->mode_mask |= UNPRIV;
}
}
@@ -917,6 +956,13 @@ void run_subtest(struct test_loader *tester,
test__end_subtest();
return;
}
+ if (subspec->caps) {
+ err = cap_enable_effective(subspec->caps, NULL);
+ if (err) {
+ PRINT_FAIL("failed to set capabilities: %i, %s\n", err, strerror(err));
+ goto subtest_cleanup;
+ }
+ }
}
/* Implicitly reset to NULL if next test case doesn't specify */
diff --git a/tools/testing/selftests/bpf/test_sockmap.c b/tools/testing/selftests/bpf/test_sockmap.c
index e5c7ecbe57e3..fd2da2234cc9 100644
--- a/tools/testing/selftests/bpf/test_sockmap.c
+++ b/tools/testing/selftests/bpf/test_sockmap.c
@@ -1579,8 +1579,12 @@ static void test_txmsg_redir(int cgrp, struct sockmap_options *opt)
static void test_txmsg_redir_wait_sndmem(int cgrp, struct sockmap_options *opt)
{
- txmsg_redir = 1;
opt->tx_wait_mem = true;
+ txmsg_redir = 1;
+ test_send_large(opt, cgrp);
+
+ txmsg_redir = 1;
+ txmsg_apply = 4097;
test_send_large(opt, cgrp);
opt->tx_wait_mem = false;
}
diff --git a/tools/testing/selftests/bpf/test_xdp_meta.sh b/tools/testing/selftests/bpf/test_xdp_meta.sh
deleted file mode 100755
index 2740322c1878..000000000000
--- a/tools/testing/selftests/bpf/test_xdp_meta.sh
+++ /dev/null
@@ -1,58 +0,0 @@
-#!/bin/sh
-
-BPF_FILE="test_xdp_meta.bpf.o"
-# Kselftest framework requirement - SKIP code is 4.
-readonly KSFT_SKIP=4
-readonly NS1="ns1-$(mktemp -u XXXXXX)"
-readonly NS2="ns2-$(mktemp -u XXXXXX)"
-
-cleanup()
-{
- if [ "$?" = "0" ]; then
- echo "selftests: test_xdp_meta [PASS]";
- else
- echo "selftests: test_xdp_meta [FAILED]";
- fi
-
- set +e
- ip link del veth1 2> /dev/null
- ip netns del ${NS1} 2> /dev/null
- ip netns del ${NS2} 2> /dev/null
-}
-
-ip link set dev lo xdp off 2>/dev/null > /dev/null
-if [ $? -ne 0 ];then
- echo "selftests: [SKIP] Could not run test without the ip xdp support"
- exit $KSFT_SKIP
-fi
-set -e
-
-ip netns add ${NS1}
-ip netns add ${NS2}
-
-trap cleanup 0 2 3 6 9
-
-ip link add veth1 type veth peer name veth2
-
-ip link set veth1 netns ${NS1}
-ip link set veth2 netns ${NS2}
-
-ip netns exec ${NS1} ip addr add 10.1.1.11/24 dev veth1
-ip netns exec ${NS2} ip addr add 10.1.1.22/24 dev veth2
-
-ip netns exec ${NS1} tc qdisc add dev veth1 clsact
-ip netns exec ${NS2} tc qdisc add dev veth2 clsact
-
-ip netns exec ${NS1} tc filter add dev veth1 ingress bpf da obj ${BPF_FILE} sec t
-ip netns exec ${NS2} tc filter add dev veth2 ingress bpf da obj ${BPF_FILE} sec t
-
-ip netns exec ${NS1} ip link set dev veth1 xdp obj ${BPF_FILE} sec x
-ip netns exec ${NS2} ip link set dev veth2 xdp obj ${BPF_FILE} sec x
-
-ip netns exec ${NS1} ip link set dev veth1 up
-ip netns exec ${NS2} ip link set dev veth2 up
-
-ip netns exec ${NS1} ping -c 1 10.1.1.22
-ip netns exec ${NS2} ping -c 1 10.1.1.11
-
-exit 0
diff --git a/tools/testing/selftests/bpf/trace_helpers.c b/tools/testing/selftests/bpf/trace_helpers.c
index 2d742fdac6b9..81943c6254e6 100644
--- a/tools/testing/selftests/bpf/trace_helpers.c
+++ b/tools/testing/selftests/bpf/trace_helpers.c
@@ -293,6 +293,10 @@ static int procmap_query(int fd, const void *addr, __u32 query_flags, size_t *st
return 0;
}
#else
+# ifndef PROCMAP_QUERY_VMA_EXECUTABLE
+# define PROCMAP_QUERY_VMA_EXECUTABLE 0x04
+# endif
+
static int procmap_query(int fd, const void *addr, __u32 query_flags, size_t *start, size_t *offset, int *flags)
{
return -EOPNOTSUPP;
diff --git a/tools/testing/selftests/bpf/xdp_hw_metadata.c b/tools/testing/selftests/bpf/xdp_hw_metadata.c
index 6f9956eed797..e38675d9b118 100644
--- a/tools/testing/selftests/bpf/xdp_hw_metadata.c
+++ b/tools/testing/selftests/bpf/xdp_hw_metadata.c
@@ -79,7 +79,7 @@ static int open_xsk(int ifindex, struct xsk *xsk, __u32 queue_id)
.fill_size = XSK_RING_PROD__DEFAULT_NUM_DESCS,
.comp_size = XSK_RING_CONS__DEFAULT_NUM_DESCS,
.frame_size = XSK_UMEM__DEFAULT_FRAME_SIZE,
- .flags = XSK_UMEM__DEFAULT_FLAGS,
+ .flags = XDP_UMEM_TX_METADATA_LEN,
.tx_metadata_len = sizeof(struct xsk_tx_metadata),
};
__u32 idx = 0;
@@ -551,6 +551,7 @@ static void hwtstamp_enable(const char *ifname)
{
struct hwtstamp_config cfg = {
.rx_filter = HWTSTAMP_FILTER_ALL,
+ .tx_type = HWTSTAMP_TX_ON,
};
hwtstamp_ioctl(SIOCGHWTSTAMP, ifname, &saved_hwtstamp_cfg);
diff --git a/tools/testing/selftests/damon/Makefile b/tools/testing/selftests/damon/Makefile
index 5b2a6a5dd1af..812f656260fb 100644
--- a/tools/testing/selftests/damon/Makefile
+++ b/tools/testing/selftests/damon/Makefile
@@ -6,7 +6,7 @@ TEST_GEN_FILES += debugfs_target_ids_read_before_terminate_race
TEST_GEN_FILES += debugfs_target_ids_pid_leak
TEST_GEN_FILES += access_memory access_memory_even
-TEST_FILES = _chk_dependency.sh _debugfs_common.sh
+TEST_FILES = _chk_dependency.sh _debugfs_common.sh _damon_sysfs.py
# functionality tests
TEST_PROGS = debugfs_attrs.sh debugfs_schemes.sh debugfs_target_ids.sh
diff --git a/tools/testing/selftests/drivers/net/Makefile b/tools/testing/selftests/drivers/net/Makefile
index 0fec8f9801ad..469179c18935 100644
--- a/tools/testing/selftests/drivers/net/Makefile
+++ b/tools/testing/selftests/drivers/net/Makefile
@@ -1,11 +1,13 @@
# SPDX-License-Identifier: GPL-2.0
TEST_INCLUDES := $(wildcard lib/py/*.py) \
+ $(wildcard lib/sh/*.sh) \
../../net/net_helper.sh \
../../net/lib.sh \
TEST_PROGS := \
netcons_basic.sh \
+ netcons_overflow.sh \
ping.py \
queues.py \
stats.py \
diff --git a/tools/testing/selftests/drivers/net/hw/ncdevmem.c b/tools/testing/selftests/drivers/net/hw/ncdevmem.c
index 8e502a1f8f9b..19a6969643f4 100644
--- a/tools/testing/selftests/drivers/net/hw/ncdevmem.c
+++ b/tools/testing/selftests/drivers/net/hw/ncdevmem.c
@@ -619,9 +619,6 @@ int do_server(struct memory_buffer *mem)
fprintf(stderr, "page_aligned_frags=%lu, non_page_aligned_frags=%lu\n",
page_aligned_frags, non_page_aligned_frags);
- fprintf(stderr, "page_aligned_frags=%lu, non_page_aligned_frags=%lu\n",
- page_aligned_frags, non_page_aligned_frags);
-
cleanup:
free(tmp_mem);
diff --git a/tools/testing/selftests/drivers/net/hw/rss_ctx.py b/tools/testing/selftests/drivers/net/hw/rss_ctx.py
index 0b49ce7ae678..ca8a7edff3dd 100755
--- a/tools/testing/selftests/drivers/net/hw/rss_ctx.py
+++ b/tools/testing/selftests/drivers/net/hw/rss_ctx.py
@@ -3,7 +3,8 @@
import datetime
import random
-from lib.py import ksft_run, ksft_pr, ksft_exit, ksft_eq, ksft_ne, ksft_ge, ksft_lt
+import re
+from lib.py import ksft_run, ksft_pr, ksft_exit, ksft_eq, ksft_ne, ksft_ge, ksft_lt, ksft_true
from lib.py import NetDrvEpEnv
from lib.py import EthtoolFamily, NetdevFamily
from lib.py import KsftSkipEx, KsftFailEx
@@ -96,6 +97,13 @@ def _send_traffic_check(cfg, port, name, params):
f"traffic on inactive queues ({name}): " + str(cnts))
+def _ntuple_rule_check(cfg, rule_id, ctx_id):
+ """Check that ntuple rule references RSS context ID"""
+ text = ethtool(f"-n {cfg.ifname} rule {rule_id}").stdout
+ pattern = f"RSS Context (ID: )?{ctx_id}"
+ ksft_true(re.search(pattern, text), "RSS context not referenced in ntuple rule")
+
+
def test_rss_key_indir(cfg):
"""Test basics like updating the main RSS key and indirection table."""
@@ -459,6 +467,8 @@ def test_rss_context(cfg, ctx_cnt=1, create_with_cfg=None):
ntuple = ethtool_create(cfg, "-N", flow)
defer(ethtool, f"-N {cfg.ifname} delete {ntuple}")
+ _ntuple_rule_check(cfg, ntuple, ctx_id)
+
for i in range(ctx_cnt):
_send_traffic_check(cfg, ports[i], f"context {i}",
{ 'target': (2+i*2, 3+i*2),
diff --git a/tools/testing/selftests/drivers/net/lib/py/env.py b/tools/testing/selftests/drivers/net/lib/py/env.py
index 1ea9bb695e94..987e452d3a45 100644
--- a/tools/testing/selftests/drivers/net/lib/py/env.py
+++ b/tools/testing/selftests/drivers/net/lib/py/env.py
@@ -5,7 +5,7 @@ import time
from pathlib import Path
from lib.py import KsftSkipEx, KsftXfailEx
from lib.py import ksft_setup
-from lib.py import cmd, ethtool, ip
+from lib.py import cmd, ethtool, ip, CmdExitFailure
from lib.py import NetNS, NetdevSimDev
from .remote import Remote
@@ -48,6 +48,7 @@ class NetDrvEnv:
else:
self._ns = NetdevSimDev(**kwargs)
self.dev = self._ns.nsims[0].dev
+ self.ifname = self.dev['ifname']
self.ifindex = self.dev['ifindex']
def __enter__(self):
@@ -234,7 +235,12 @@ class NetDrvEpEnv:
Good drivers will tell us via ethtool what their sync period is.
"""
if self._stats_settle_time is None:
- data = ethtool("-c " + self.ifname, json=True)[0]
+ data = {}
+ try:
+ data = ethtool("-c " + self.ifname, json=True)[0]
+ except CmdExitFailure as e:
+ if "Operation not supported" not in e.cmd.stderr:
+ raise
self._stats_settle_time = 0.025 + \
data.get('stats-block-usecs', 0) / 1000 / 1000
diff --git a/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh b/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
new file mode 100644
index 000000000000..3acaba41ac7b
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/lib/sh/lib_netcons.sh
@@ -0,0 +1,225 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: GPL-2.0
+
+# This file contains functions and helpers to support the netconsole
+# selftests
+#
+# Author: Breno Leitao <leitao@debian.org>
+
+set -euo pipefail
+
+LIBDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
+
+SRCIF="" # to be populated later
+SRCIP=192.0.2.1
+DSTIF="" # to be populated later
+DSTIP=192.0.2.2
+
+PORT="6666"
+MSG="netconsole selftest"
+USERDATA_KEY="key"
+USERDATA_VALUE="value"
+TARGET=$(mktemp -u netcons_XXXXX)
+DEFAULT_PRINTK_VALUES=$(cat /proc/sys/kernel/printk)
+NETCONS_CONFIGFS="/sys/kernel/config/netconsole"
+NETCONS_PATH="${NETCONS_CONFIGFS}"/"${TARGET}"
+# NAMESPACE will be populated by setup_ns with a random value
+NAMESPACE=""
+
+# IDs for netdevsim
+NSIM_DEV_1_ID=$((256 + RANDOM % 256))
+NSIM_DEV_2_ID=$((512 + RANDOM % 256))
+NSIM_DEV_SYS_NEW="/sys/bus/netdevsim/new_device"
+
+# Used to create and delete namespaces
+source "${LIBDIR}"/../../../../net/lib.sh
+source "${LIBDIR}"/../../../../net/net_helper.sh
+
+# Create netdevsim interfaces
+create_ifaces() {
+
+ echo "$NSIM_DEV_2_ID" > "$NSIM_DEV_SYS_NEW"
+ echo "$NSIM_DEV_1_ID" > "$NSIM_DEV_SYS_NEW"
+ udevadm settle 2> /dev/null || true
+
+ local NSIM1=/sys/bus/netdevsim/devices/netdevsim"$NSIM_DEV_1_ID"
+ local NSIM2=/sys/bus/netdevsim/devices/netdevsim"$NSIM_DEV_2_ID"
+
+ # These are global variables
+ SRCIF=$(find "$NSIM1"/net -maxdepth 1 -type d ! \
+ -path "$NSIM1"/net -exec basename {} \;)
+ DSTIF=$(find "$NSIM2"/net -maxdepth 1 -type d ! \
+ -path "$NSIM2"/net -exec basename {} \;)
+}
+
+link_ifaces() {
+ local NSIM_DEV_SYS_LINK="/sys/bus/netdevsim/link_device"
+ local SRCIF_IFIDX=$(cat /sys/class/net/"$SRCIF"/ifindex)
+ local DSTIF_IFIDX=$(cat /sys/class/net/"$DSTIF"/ifindex)
+
+ exec {NAMESPACE_FD}</var/run/netns/"${NAMESPACE}"
+ exec {INITNS_FD}</proc/self/ns/net
+
+ # Bind the dst interface to namespace
+ ip link set "${DSTIF}" netns "${NAMESPACE}"
+
+ # Linking one device to the other one (on the other namespace}
+ if ! echo "${INITNS_FD}:$SRCIF_IFIDX $NAMESPACE_FD:$DSTIF_IFIDX" > $NSIM_DEV_SYS_LINK
+ then
+ echo "linking netdevsim1 with netdevsim2 should succeed"
+ cleanup
+ exit "${ksft_skip}"
+ fi
+}
+
+function configure_ip() {
+ # Configure the IPs for both interfaces
+ ip netns exec "${NAMESPACE}" ip addr add "${DSTIP}"/24 dev "${DSTIF}"
+ ip netns exec "${NAMESPACE}" ip link set "${DSTIF}" up
+
+ ip addr add "${SRCIP}"/24 dev "${SRCIF}"
+ ip link set "${SRCIF}" up
+}
+
+function set_network() {
+ # setup_ns function is coming from lib.sh
+ setup_ns NAMESPACE
+
+ # Create both interfaces, and assign the destination to a different
+ # namespace
+ create_ifaces
+
+ # Link both interfaces back to back
+ link_ifaces
+
+ configure_ip
+}
+
+function create_dynamic_target() {
+ DSTMAC=$(ip netns exec "${NAMESPACE}" \
+ ip link show "${DSTIF}" | awk '/ether/ {print $2}')
+
+ # Create a dynamic target
+ mkdir "${NETCONS_PATH}"
+
+ echo "${DSTIP}" > "${NETCONS_PATH}"/remote_ip
+ echo "${SRCIP}" > "${NETCONS_PATH}"/local_ip
+ echo "${DSTMAC}" > "${NETCONS_PATH}"/remote_mac
+ echo "${SRCIF}" > "${NETCONS_PATH}"/dev_name
+
+ echo 1 > "${NETCONS_PATH}"/enabled
+}
+
+function cleanup() {
+ local NSIM_DEV_SYS_DEL="/sys/bus/netdevsim/del_device"
+
+ # delete netconsole dynamic reconfiguration
+ echo 0 > "${NETCONS_PATH}"/enabled
+ # Remove all the keys that got created during the selftest
+ find "${NETCONS_PATH}/userdata/" -mindepth 1 -type d -delete
+ # Remove the configfs entry
+ rmdir "${NETCONS_PATH}"
+
+ # Delete netdevsim devices
+ echo "$NSIM_DEV_2_ID" > "$NSIM_DEV_SYS_DEL"
+ echo "$NSIM_DEV_1_ID" > "$NSIM_DEV_SYS_DEL"
+
+ # this is coming from lib.sh
+ cleanup_all_ns
+
+ # Restoring printk configurations
+ echo "${DEFAULT_PRINTK_VALUES}" > /proc/sys/kernel/printk
+}
+
+function set_user_data() {
+ if [[ ! -d "${NETCONS_PATH}""/userdata" ]]
+ then
+ echo "Userdata path not available in ${NETCONS_PATH}/userdata"
+ exit "${ksft_skip}"
+ fi
+
+ KEY_PATH="${NETCONS_PATH}/userdata/${USERDATA_KEY}"
+ mkdir -p "${KEY_PATH}"
+ VALUE_PATH="${KEY_PATH}""/value"
+ echo "${USERDATA_VALUE}" > "${VALUE_PATH}"
+}
+
+function listen_port_and_save_to() {
+ local OUTPUT=${1}
+ # Just wait for 2 seconds
+ timeout 2 ip netns exec "${NAMESPACE}" \
+ socat UDP-LISTEN:"${PORT}",fork "${OUTPUT}"
+}
+
+function validate_result() {
+ local TMPFILENAME="$1"
+
+ # TMPFILENAME will contain something like:
+ # 6.11.1-0_fbk0_rc13_509_g30d75cea12f7,13,1822,115075213798,-;netconsole selftest: netcons_gtJHM
+ # key=value
+
+ # Check if the file exists
+ if [ ! -f "$TMPFILENAME" ]; then
+ echo "FAIL: File was not generated." >&2
+ exit "${ksft_fail}"
+ fi
+
+ if ! grep -q "${MSG}" "${TMPFILENAME}"; then
+ echo "FAIL: ${MSG} not found in ${TMPFILENAME}" >&2
+ cat "${TMPFILENAME}" >&2
+ exit "${ksft_fail}"
+ fi
+
+ if ! grep -q "${USERDATA_KEY}=${USERDATA_VALUE}" "${TMPFILENAME}"; then
+ echo "FAIL: ${USERDATA_KEY}=${USERDATA_VALUE} not found in ${TMPFILENAME}" >&2
+ cat "${TMPFILENAME}" >&2
+ exit "${ksft_fail}"
+ fi
+
+ # Delete the file once it is validated, otherwise keep it
+ # for debugging purposes
+ rm "${TMPFILENAME}"
+ exit "${ksft_pass}"
+}
+
+function check_for_dependencies() {
+ if [ "$(id -u)" -ne 0 ]; then
+ echo "This test must be run as root" >&2
+ exit "${ksft_skip}"
+ fi
+
+ if ! which socat > /dev/null ; then
+ echo "SKIP: socat(1) is not available" >&2
+ exit "${ksft_skip}"
+ fi
+
+ if ! which ip > /dev/null ; then
+ echo "SKIP: ip(1) is not available" >&2
+ exit "${ksft_skip}"
+ fi
+
+ if ! which udevadm > /dev/null ; then
+ echo "SKIP: udevadm(1) is not available" >&2
+ exit "${ksft_skip}"
+ fi
+
+ if [ ! -f "${NSIM_DEV_SYS_NEW}" ]; then
+ echo "SKIP: file ${NSIM_DEV_SYS_NEW} does not exist. Check if CONFIG_NETDEVSIM is enabled" >&2
+ exit "${ksft_skip}"
+ fi
+
+ if [ ! -d "${NETCONS_CONFIGFS}" ]; then
+ echo "SKIP: directory ${NETCONS_CONFIGFS} does not exist. Check if NETCONSOLE_DYNAMIC is enabled" >&2
+ exit "${ksft_skip}"
+ fi
+
+ if ip link show "${DSTIF}" 2> /dev/null; then
+ echo "SKIP: interface ${DSTIF} exists in the system. Not overwriting it." >&2
+ exit "${ksft_skip}"
+ fi
+
+ if ip addr list | grep -E "inet.*(${SRCIP}|${DSTIP})" 2> /dev/null; then
+ echo "SKIP: IPs already in use. Skipping it" >&2
+ exit "${ksft_skip}"
+ fi
+}
diff --git a/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh b/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh
index 0c47faff9274..c068e6c2a580 100755
--- a/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh
+++ b/tools/testing/selftests/drivers/net/mlxsw/sharedbuffer.sh
@@ -22,20 +22,34 @@ SB_ITC=0
h1_create()
{
simple_if_init $h1 192.0.1.1/24
+ tc qdisc add dev $h1 clsact
+
+ # Add egress filter on $h1 that will guarantee that the packet sent,
+ # will be the only packet being passed to the device.
+ tc filter add dev $h1 egress pref 2 handle 102 matchall action drop
}
h1_destroy()
{
+ tc filter del dev $h1 egress pref 2 handle 102 matchall action drop
+ tc qdisc del dev $h1 clsact
simple_if_fini $h1 192.0.1.1/24
}
h2_create()
{
simple_if_init $h2 192.0.1.2/24
+ tc qdisc add dev $h2 clsact
+
+ # Add egress filter on $h2 that will guarantee that the packet sent,
+ # will be the only packet being passed to the device.
+ tc filter add dev $h2 egress pref 1 handle 101 matchall action drop
}
h2_destroy()
{
+ tc filter del dev $h2 egress pref 1 handle 101 matchall action drop
+ tc qdisc del dev $h2 clsact
simple_if_fini $h2 192.0.1.2/24
}
@@ -101,6 +115,11 @@ port_pool_test()
local exp_max_occ=$(devlink_cell_size_get)
local max_occ
+ tc filter add dev $h1 egress protocol ip pref 1 handle 101 flower \
+ src_mac $h1mac dst_mac $h2mac \
+ src_ip 192.0.1.1 dst_ip 192.0.1.2 \
+ action pass
+
devlink sb occupancy clearmax $DEVLINK_DEV
$MZ $h1 -c 1 -p 10 -a $h1mac -b $h2mac -A 192.0.1.1 -B 192.0.1.2 \
@@ -109,11 +128,6 @@ port_pool_test()
devlink sb occupancy snapshot $DEVLINK_DEV
RET=0
- max_occ=$(sb_occ_pool_check $dl_port1 $SB_POOL_ING $exp_max_occ)
- check_err $? "Expected iPool($SB_POOL_ING) max occupancy to be $exp_max_occ, but got $max_occ"
- log_test "physical port's($h1) ingress pool"
-
- RET=0
max_occ=$(sb_occ_pool_check $dl_port2 $SB_POOL_ING $exp_max_occ)
check_err $? "Expected iPool($SB_POOL_ING) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "physical port's($h2) ingress pool"
@@ -122,6 +136,11 @@ port_pool_test()
max_occ=$(sb_occ_pool_check $cpu_dl_port $SB_POOL_EGR_CPU $exp_max_occ)
check_err $? "Expected ePool($SB_POOL_EGR_CPU) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "CPU port's egress pool"
+
+ tc filter del dev $h1 egress protocol ip pref 1 handle 101 flower \
+ src_mac $h1mac dst_mac $h2mac \
+ src_ip 192.0.1.1 dst_ip 192.0.1.2 \
+ action pass
}
port_tc_ip_test()
@@ -129,6 +148,11 @@ port_tc_ip_test()
local exp_max_occ=$(devlink_cell_size_get)
local max_occ
+ tc filter add dev $h1 egress protocol ip pref 1 handle 101 flower \
+ src_mac $h1mac dst_mac $h2mac \
+ src_ip 192.0.1.1 dst_ip 192.0.1.2 \
+ action pass
+
devlink sb occupancy clearmax $DEVLINK_DEV
$MZ $h1 -c 1 -p 10 -a $h1mac -b $h2mac -A 192.0.1.1 -B 192.0.1.2 \
@@ -139,17 +163,17 @@ port_tc_ip_test()
RET=0
max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
- log_test "physical port's($h1) ingress TC - IP packet"
-
- RET=0
- max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
- check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "physical port's($h2) ingress TC - IP packet"
RET=0
max_occ=$(sb_occ_etc_check $cpu_dl_port $SB_ITC_CPU_IP $exp_max_occ)
check_err $? "Expected egress TC($SB_ITC_CPU_IP) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "CPU port's egress TC - IP packet"
+
+ tc filter del dev $h1 egress protocol ip pref 1 handle 101 flower \
+ src_mac $h1mac dst_mac $h2mac \
+ src_ip 192.0.1.1 dst_ip 192.0.1.2 \
+ action pass
}
port_tc_arp_test()
@@ -157,6 +181,9 @@ port_tc_arp_test()
local exp_max_occ=$(devlink_cell_size_get)
local max_occ
+ tc filter add dev $h1 egress protocol arp pref 1 handle 101 flower \
+ src_mac $h1mac action pass
+
devlink sb occupancy clearmax $DEVLINK_DEV
$MZ $h1 -c 1 -p 10 -a $h1mac -A 192.0.1.1 -t arp -q
@@ -166,17 +193,15 @@ port_tc_arp_test()
RET=0
max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
- log_test "physical port's($h1) ingress TC - ARP packet"
-
- RET=0
- max_occ=$(sb_occ_itc_check $dl_port2 $SB_ITC $exp_max_occ)
- check_err $? "Expected ingress TC($SB_ITC) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "physical port's($h2) ingress TC - ARP packet"
RET=0
max_occ=$(sb_occ_etc_check $cpu_dl_port $SB_ITC_CPU_ARP $exp_max_occ)
check_err $? "Expected egress TC($SB_ITC_IP2ME) max occupancy to be $exp_max_occ, but got $max_occ"
log_test "CPU port's egress TC - ARP packet"
+
+ tc filter del dev $h1 egress protocol arp pref 1 handle 101 flower \
+ src_mac $h1mac action pass
}
setup_prepare()
diff --git a/tools/testing/selftests/drivers/net/netcons_basic.sh b/tools/testing/selftests/drivers/net/netcons_basic.sh
index b175f4d966e5..fe765da498e8 100755
--- a/tools/testing/selftests/drivers/net/netcons_basic.sh
+++ b/tools/testing/selftests/drivers/net/netcons_basic.sh
@@ -18,224 +18,8 @@ set -euo pipefail
SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
-# Simple script to test dynamic targets in netconsole
-SRCIF="" # to be populated later
-SRCIP=192.0.2.1
-DSTIF="" # to be populated later
-DSTIP=192.0.2.2
+source "${SCRIPTDIR}"/lib/sh/lib_netcons.sh
-PORT="6666"
-MSG="netconsole selftest"
-USERDATA_KEY="key"
-USERDATA_VALUE="value"
-TARGET=$(mktemp -u netcons_XXXXX)
-DEFAULT_PRINTK_VALUES=$(cat /proc/sys/kernel/printk)
-NETCONS_CONFIGFS="/sys/kernel/config/netconsole"
-NETCONS_PATH="${NETCONS_CONFIGFS}"/"${TARGET}"
-KEY_PATH="${NETCONS_PATH}/userdata/${USERDATA_KEY}"
-# NAMESPACE will be populated by setup_ns with a random value
-NAMESPACE=""
-
-# IDs for netdevsim
-NSIM_DEV_1_ID=$((256 + RANDOM % 256))
-NSIM_DEV_2_ID=$((512 + RANDOM % 256))
-NSIM_DEV_SYS_NEW="/sys/bus/netdevsim/new_device"
-
-# Used to create and delete namespaces
-source "${SCRIPTDIR}"/../../net/lib.sh
-source "${SCRIPTDIR}"/../../net/net_helper.sh
-
-# Create netdevsim interfaces
-create_ifaces() {
-
- echo "$NSIM_DEV_2_ID" > "$NSIM_DEV_SYS_NEW"
- echo "$NSIM_DEV_1_ID" > "$NSIM_DEV_SYS_NEW"
- udevadm settle 2> /dev/null || true
-
- local NSIM1=/sys/bus/netdevsim/devices/netdevsim"$NSIM_DEV_1_ID"
- local NSIM2=/sys/bus/netdevsim/devices/netdevsim"$NSIM_DEV_2_ID"
-
- # These are global variables
- SRCIF=$(find "$NSIM1"/net -maxdepth 1 -type d ! \
- -path "$NSIM1"/net -exec basename {} \;)
- DSTIF=$(find "$NSIM2"/net -maxdepth 1 -type d ! \
- -path "$NSIM2"/net -exec basename {} \;)
-}
-
-link_ifaces() {
- local NSIM_DEV_SYS_LINK="/sys/bus/netdevsim/link_device"
- local SRCIF_IFIDX=$(cat /sys/class/net/"$SRCIF"/ifindex)
- local DSTIF_IFIDX=$(cat /sys/class/net/"$DSTIF"/ifindex)
-
- exec {NAMESPACE_FD}</var/run/netns/"${NAMESPACE}"
- exec {INITNS_FD}</proc/self/ns/net
-
- # Bind the dst interface to namespace
- ip link set "${DSTIF}" netns "${NAMESPACE}"
-
- # Linking one device to the other one (on the other namespace}
- if ! echo "${INITNS_FD}:$SRCIF_IFIDX $NAMESPACE_FD:$DSTIF_IFIDX" > $NSIM_DEV_SYS_LINK
- then
- echo "linking netdevsim1 with netdevsim2 should succeed"
- cleanup
- exit "${ksft_skip}"
- fi
-}
-
-function configure_ip() {
- # Configure the IPs for both interfaces
- ip netns exec "${NAMESPACE}" ip addr add "${DSTIP}"/24 dev "${DSTIF}"
- ip netns exec "${NAMESPACE}" ip link set "${DSTIF}" up
-
- ip addr add "${SRCIP}"/24 dev "${SRCIF}"
- ip link set "${SRCIF}" up
-}
-
-function set_network() {
- # setup_ns function is coming from lib.sh
- setup_ns NAMESPACE
-
- # Create both interfaces, and assign the destination to a different
- # namespace
- create_ifaces
-
- # Link both interfaces back to back
- link_ifaces
-
- configure_ip
-}
-
-function create_dynamic_target() {
- DSTMAC=$(ip netns exec "${NAMESPACE}" \
- ip link show "${DSTIF}" | awk '/ether/ {print $2}')
-
- # Create a dynamic target
- mkdir "${NETCONS_PATH}"
-
- echo "${DSTIP}" > "${NETCONS_PATH}"/remote_ip
- echo "${SRCIP}" > "${NETCONS_PATH}"/local_ip
- echo "${DSTMAC}" > "${NETCONS_PATH}"/remote_mac
- echo "${SRCIF}" > "${NETCONS_PATH}"/dev_name
-
- echo 1 > "${NETCONS_PATH}"/enabled
-}
-
-function cleanup() {
- local NSIM_DEV_SYS_DEL="/sys/bus/netdevsim/del_device"
-
- # delete netconsole dynamic reconfiguration
- echo 0 > "${NETCONS_PATH}"/enabled
- # Remove key
- rmdir "${KEY_PATH}"
- # Remove the configfs entry
- rmdir "${NETCONS_PATH}"
-
- # Delete netdevsim devices
- echo "$NSIM_DEV_2_ID" > "$NSIM_DEV_SYS_DEL"
- echo "$NSIM_DEV_1_ID" > "$NSIM_DEV_SYS_DEL"
-
- # this is coming from lib.sh
- cleanup_all_ns
-
- # Restoring printk configurations
- echo "${DEFAULT_PRINTK_VALUES}" > /proc/sys/kernel/printk
-}
-
-function set_user_data() {
- if [[ ! -d "${NETCONS_PATH}""/userdata" ]]
- then
- echo "Userdata path not available in ${NETCONS_PATH}/userdata"
- exit "${ksft_skip}"
- fi
-
- mkdir -p "${KEY_PATH}"
- VALUE_PATH="${KEY_PATH}""/value"
- echo "${USERDATA_VALUE}" > "${VALUE_PATH}"
-}
-
-function listen_port_and_save_to() {
- local OUTPUT=${1}
- # Just wait for 2 seconds
- timeout 2 ip netns exec "${NAMESPACE}" \
- socat UDP-LISTEN:"${PORT}",fork "${OUTPUT}"
-}
-
-function validate_result() {
- local TMPFILENAME="$1"
-
- # TMPFILENAME will contain something like:
- # 6.11.1-0_fbk0_rc13_509_g30d75cea12f7,13,1822,115075213798,-;netconsole selftest: netcons_gtJHM
- # key=value
-
- # Check if the file exists
- if [ ! -f "$TMPFILENAME" ]; then
- echo "FAIL: File was not generated." >&2
- exit "${ksft_fail}"
- fi
-
- if ! grep -q "${MSG}" "${TMPFILENAME}"; then
- echo "FAIL: ${MSG} not found in ${TMPFILENAME}" >&2
- cat "${TMPFILENAME}" >&2
- exit "${ksft_fail}"
- fi
-
- if ! grep -q "${USERDATA_KEY}=${USERDATA_VALUE}" "${TMPFILENAME}"; then
- echo "FAIL: ${USERDATA_KEY}=${USERDATA_VALUE} not found in ${TMPFILENAME}" >&2
- cat "${TMPFILENAME}" >&2
- exit "${ksft_fail}"
- fi
-
- # Delete the file once it is validated, otherwise keep it
- # for debugging purposes
- rm "${TMPFILENAME}"
- exit "${ksft_pass}"
-}
-
-function check_for_dependencies() {
- if [ "$(id -u)" -ne 0 ]; then
- echo "This test must be run as root" >&2
- exit "${ksft_skip}"
- fi
-
- if ! which socat > /dev/null ; then
- echo "SKIP: socat(1) is not available" >&2
- exit "${ksft_skip}"
- fi
-
- if ! which ip > /dev/null ; then
- echo "SKIP: ip(1) is not available" >&2
- exit "${ksft_skip}"
- fi
-
- if ! which udevadm > /dev/null ; then
- echo "SKIP: udevadm(1) is not available" >&2
- exit "${ksft_skip}"
- fi
-
- if [ ! -f "${NSIM_DEV_SYS_NEW}" ]; then
- echo "SKIP: file ${NSIM_DEV_SYS_NEW} does not exist. Check if CONFIG_NETDEVSIM is enabled" >&2
- exit "${ksft_skip}"
- fi
-
- if [ ! -d "${NETCONS_CONFIGFS}" ]; then
- echo "SKIP: directory ${NETCONS_CONFIGFS} does not exist. Check if NETCONSOLE_DYNAMIC is enabled" >&2
- exit "${ksft_skip}"
- fi
-
- if ip link show "${DSTIF}" 2> /dev/null; then
- echo "SKIP: interface ${DSTIF} exists in the system. Not overwriting it." >&2
- exit "${ksft_skip}"
- fi
-
- if ip addr list | grep -E "inet.*(${SRCIP}|${DSTIP})" 2> /dev/null; then
- echo "SKIP: IPs already in use. Skipping it" >&2
- exit "${ksft_skip}"
- fi
-}
-
-# ========== #
-# Start here #
-# ========== #
modprobe netdevsim 2> /dev/null || true
modprobe netconsole 2> /dev/null || true
diff --git a/tools/testing/selftests/drivers/net/netcons_overflow.sh b/tools/testing/selftests/drivers/net/netcons_overflow.sh
new file mode 100755
index 000000000000..29bad56448a2
--- /dev/null
+++ b/tools/testing/selftests/drivers/net/netcons_overflow.sh
@@ -0,0 +1,67 @@
+#!/usr/bin/env bash
+# SPDX-License-Identifier: GPL-2.0
+
+# This test verifies that users can successfully create up to
+# MAX_USERDATA_ITEMS userdata entries without encountering any failures.
+#
+# Additionally, it tests for expected failure when attempting to exceed this
+# maximum limit.
+#
+# Author: Breno Leitao <leitao@debian.org>
+
+set -euo pipefail
+
+SCRIPTDIR=$(dirname "$(readlink -e "${BASH_SOURCE[0]}")")
+
+source "${SCRIPTDIR}"/lib/sh/lib_netcons.sh
+# This is coming from netconsole code. Check for it in drivers/net/netconsole.c
+MAX_USERDATA_ITEMS=16
+
+# Function to create userdata entries
+function create_userdata_max_entries() {
+ # All these keys should be created without any error
+ for i in $(seq $MAX_USERDATA_ITEMS)
+ do
+ # USERDATA_KEY is used by set_user_data
+ USERDATA_KEY="key"${i}
+ set_user_data
+ done
+}
+
+# Function to verify the entry limit
+function verify_entry_limit() {
+ # Allowing the test to fail without exiting, since the next command
+ # will fail
+ set +e
+ mkdir "${NETCONS_PATH}/userdata/key_that_will_fail" 2> /dev/null
+ ret="$?"
+ set -e
+ if [ "$ret" -eq 0 ];
+ then
+ echo "Adding more than ${MAX_USERDATA_ITEMS} entries in userdata should fail, but it didn't" >&2
+ ls "${NETCONS_PATH}/userdata/" >&2
+ exit "${ksft_fail}"
+ fi
+}
+
+# ========== #
+# Start here #
+# ========== #
+
+modprobe netdevsim 2> /dev/null || true
+modprobe netconsole 2> /dev/null || true
+
+# Check for basic system dependency and exit if not found
+check_for_dependencies
+
+# Remove the namespace, interfaces and netconsole target on exit
+trap cleanup EXIT
+# Create one namespace and two interfaces
+set_network
+# Create a dynamic target for netconsole
+create_dynamic_target
+# populate the maximum number of supported keys in userdata
+create_userdata_max_entries
+# Verify an additional entry is not allowed
+verify_entry_limit
+exit "${ksft_pass}"
diff --git a/tools/testing/selftests/drivers/net/queues.py b/tools/testing/selftests/drivers/net/queues.py
index 30f29096e27c..38303da957ee 100755
--- a/tools/testing/selftests/drivers/net/queues.py
+++ b/tools/testing/selftests/drivers/net/queues.py
@@ -1,32 +1,37 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: GPL-2.0
-from lib.py import ksft_run, ksft_exit, ksft_eq, KsftSkipEx
-from lib.py import EthtoolFamily, NetdevFamily
+from lib.py import ksft_disruptive, ksft_exit, ksft_run
+from lib.py import ksft_eq, ksft_raises, KsftSkipEx
+from lib.py import EthtoolFamily, NetdevFamily, NlError
from lib.py import NetDrvEnv
-from lib.py import cmd
+from lib.py import cmd, defer, ip
+import errno
import glob
-def sys_get_queues(ifname) -> int:
- folders = glob.glob(f'/sys/class/net/{ifname}/queues/rx-*')
+def sys_get_queues(ifname, qtype='rx') -> int:
+ folders = glob.glob(f'/sys/class/net/{ifname}/queues/{qtype}-*')
return len(folders)
-def nl_get_queues(cfg, nl):
+def nl_get_queues(cfg, nl, qtype='rx'):
queues = nl.queue_get({'ifindex': cfg.ifindex}, dump=True)
if queues:
- return len([q for q in queues if q['type'] == 'rx'])
+ return len([q for q in queues if q['type'] == qtype])
return None
def get_queues(cfg, nl) -> None:
- queues = nl_get_queues(cfg, nl)
- if not queues:
- raise KsftSkipEx('queue-get not supported by device')
+ snl = NetdevFamily(recv_size=4096)
- expected = sys_get_queues(cfg.dev['ifname'])
- ksft_eq(queues, expected)
+ for qtype in ['rx', 'tx']:
+ queues = nl_get_queues(cfg, snl, qtype)
+ if not queues:
+ raise KsftSkipEx('queue-get not supported by device')
+
+ expected = sys_get_queues(cfg.dev['ifname'], qtype)
+ ksft_eq(queues, expected)
def addremove_queues(cfg, nl) -> None:
@@ -56,9 +61,27 @@ def addremove_queues(cfg, nl) -> None:
ksft_eq(queues, expected)
+@ksft_disruptive
+def check_down(cfg, nl) -> None:
+ # Check the NAPI IDs before interface goes down and hides them
+ napis = nl.napi_get({'ifindex': cfg.ifindex}, dump=True)
+
+ ip(f"link set dev {cfg.dev['ifname']} down")
+ defer(ip, f"link set dev {cfg.dev['ifname']} up")
+
+ with ksft_raises(NlError) as cm:
+ nl.queue_get({'ifindex': cfg.ifindex, 'id': 0, 'type': 'rx'})
+ ksft_eq(cm.exception.nl_msg.error, -errno.ENOENT)
+
+ if napis:
+ with ksft_raises(NlError) as cm:
+ nl.napi_get({'id': napis[0]['id']})
+ ksft_eq(cm.exception.nl_msg.error, -errno.ENOENT)
+
+
def main() -> None:
- with NetDrvEnv(__file__, queue_count=3) as cfg:
- ksft_run([get_queues, addremove_queues], args=(cfg, NetdevFamily()))
+ with NetDrvEnv(__file__, queue_count=100) as cfg:
+ ksft_run([get_queues, addremove_queues, check_down], args=(cfg, NetdevFamily()))
ksft_exit()
diff --git a/tools/testing/selftests/drivers/net/stats.py b/tools/testing/selftests/drivers/net/stats.py
index 63e3c045a3b2..efcc1e10575b 100755
--- a/tools/testing/selftests/drivers/net/stats.py
+++ b/tools/testing/selftests/drivers/net/stats.py
@@ -2,12 +2,15 @@
# SPDX-License-Identifier: GPL-2.0
import errno
+import subprocess
+import time
from lib.py import ksft_run, ksft_exit, ksft_pr
-from lib.py import ksft_ge, ksft_eq, ksft_in, ksft_true, ksft_raises, KsftSkipEx, KsftXfailEx
+from lib.py import ksft_ge, ksft_eq, ksft_is, ksft_in, ksft_lt, ksft_true, ksft_raises
+from lib.py import KsftSkipEx, KsftXfailEx
from lib.py import ksft_disruptive
from lib.py import EthtoolFamily, NetdevFamily, RtnlFamily, NlError
from lib.py import NetDrvEnv
-from lib.py import ip, defer
+from lib.py import cmd, ip, defer
ethnl = EthtoolFamily()
netfam = NetdevFamily()
@@ -110,6 +113,23 @@ def qstat_by_ifindex(cfg) -> None:
ksft_ge(triple[1][key], triple[0][key], comment="bad key: " + key)
ksft_ge(triple[2][key], triple[1][key], comment="bad key: " + key)
+ # Sanity check the dumps
+ queues = NetdevFamily(recv_size=4096).qstats_get({"scope": "queue"}, dump=True)
+ # Reformat the output into {ifindex: {rx: [id, id, ...], tx: [id, id, ...]}}
+ parsed = {}
+ for entry in queues:
+ ifindex = entry["ifindex"]
+ if ifindex not in parsed:
+ parsed[ifindex] = {"rx":[], "tx": []}
+ parsed[ifindex][entry["queue-type"]].append(entry['queue-id'])
+ # Now, validate
+ for ifindex, queues in parsed.items():
+ for qtype in ['rx', 'tx']:
+ ksft_eq(len(queues[qtype]), len(set(queues[qtype])),
+ comment="repeated queue keys")
+ ksft_eq(len(queues[qtype]), max(queues[qtype]) + 1,
+ comment="missing queue keys")
+
# Test invalid dumps
# 0 is invalid
with ksft_raises(NlError) as cm:
@@ -157,10 +177,95 @@ def check_down(cfg) -> None:
netfam.qstats_get({"ifindex": cfg.ifindex, "scope": "queue"}, dump=True)
+def __run_inf_loop(body):
+ body = body.strip()
+ if body[-1] != ';':
+ body += ';'
+
+ return subprocess.Popen(f"while true; do {body} done", shell=True,
+ stdout=subprocess.PIPE, stderr=subprocess.PIPE)
+
+
+def __stats_increase_sanely(old, new) -> None:
+ for k in old.keys():
+ ksft_ge(new[k], old[k])
+ ksft_lt(new[k] - old[k], 1 << 31, comment="likely wrapping error")
+
+
+def procfs_hammer(cfg) -> None:
+ """
+ Reading stats via procfs only holds the RCU lock, which is not an exclusive
+ lock, make sure drivers can handle parallel reads of stats.
+ """
+ one = __run_inf_loop("cat /proc/net/dev")
+ defer(one.kill)
+ two = __run_inf_loop("cat /proc/net/dev")
+ defer(two.kill)
+
+ time.sleep(1)
+ # Make sure the processes are running
+ ksft_is(one.poll(), None)
+ ksft_is(two.poll(), None)
+
+ rtstat1 = rtnl.getlink({"ifi-index": cfg.ifindex})['stats64']
+ time.sleep(2)
+ rtstat2 = rtnl.getlink({"ifi-index": cfg.ifindex})['stats64']
+ __stats_increase_sanely(rtstat1, rtstat2)
+ # defers will kill the loops
+
+
+@ksft_disruptive
+def procfs_downup_hammer(cfg) -> None:
+ """
+ Reading stats via procfs only holds the RCU lock, drivers often try
+ to sleep when reading the stats, or don't protect against races.
+ """
+ # Max out the queues, we'll flip between max and 1
+ channels = ethnl.channels_get({'header': {'dev-index': cfg.ifindex}})
+ if channels['combined-count'] == 0:
+ rx_type = 'rx'
+ else:
+ rx_type = 'combined'
+ cur_queue_cnt = channels[f'{rx_type}-count']
+ max_queue_cnt = channels[f'{rx_type}-max']
+
+ cmd(f"ethtool -L {cfg.ifname} {rx_type} {max_queue_cnt}")
+ defer(cmd, f"ethtool -L {cfg.ifname} {rx_type} {cur_queue_cnt}")
+
+ # Real test stats
+ stats = __run_inf_loop("cat /proc/net/dev")
+ defer(stats.kill)
+
+ ipset = f"ip link set dev {cfg.ifname}"
+ defer(ip, f"link set dev {cfg.ifname} up")
+ # The "echo -n 1" lets us count iterations below
+ updown = f"{ipset} down; sleep 0.05; {ipset} up; sleep 0.05; " + \
+ f"ethtool -L {cfg.ifname} {rx_type} 1; " + \
+ f"ethtool -L {cfg.ifname} {rx_type} {max_queue_cnt}; " + \
+ "echo -n 1"
+ updown = __run_inf_loop(updown)
+ kill_updown = defer(updown.kill)
+
+ time.sleep(1)
+ # Make sure the processes are running
+ ksft_is(stats.poll(), None)
+ ksft_is(updown.poll(), None)
+
+ rtstat1 = rtnl.getlink({"ifi-index": cfg.ifindex})['stats64']
+ # We're looking for crashes, give it extra time
+ time.sleep(9)
+ rtstat2 = rtnl.getlink({"ifi-index": cfg.ifindex})['stats64']
+ __stats_increase_sanely(rtstat1, rtstat2)
+
+ kill_updown.exec()
+ stdout, _ = updown.communicate(timeout=5)
+ ksft_pr("completed up/down cycles:", len(stdout.decode('utf-8')))
+
+
def main() -> None:
- with NetDrvEnv(__file__) as cfg:
+ with NetDrvEnv(__file__, queue_count=100) as cfg:
ksft_run([check_pause, check_fec, pkt_byte_sum, qstat_by_ifindex,
- check_down],
+ check_down, procfs_hammer, procfs_downup_hammer],
args=(cfg, ))
ksft_exit()
diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
index 319567f0fae1..81db85a5cc16 100644
--- a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
+++ b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
@@ -57,7 +57,6 @@ static int __do_binderfs_test(struct __test_metadata *_metadata)
{
int fd, ret, saved_errno, result = 1;
size_t len;
- ssize_t wret;
struct binderfs_device device = { 0 };
struct binder_version version = { 0 };
char binderfs_mntpt[] = P_tmpdir "/binderfs_XXXXXX",
diff --git a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
index a16c6a6f6055..8f1c58f0c239 100644
--- a/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
+++ b/tools/testing/selftests/ftrace/test.d/kprobe/kprobe_syntax_errors.tc
@@ -111,7 +111,7 @@ check_error 'p vfs_read $arg* ^$arg*' # DOUBLE_ARGS
if !grep -q 'kernel return probes support:' README; then
check_error 'r vfs_read ^$arg*' # NOFENTRY_ARGS
fi
-check_error 'p vfs_read+8 ^$arg*' # NOFENTRY_ARGS
+check_error 'p vfs_read+20 ^$arg*' # NOFENTRY_ARGS
check_error 'p vfs_read ^hoge' # NO_BTFARG
check_error 'p kfree ^$arg10' # NO_BTFARG (exceed the number of parameters)
check_error 'r kfree ^$retval' # NO_RETVAL
diff --git a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
index e5db897586bb..531228b849da 100644
--- a/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
+++ b/tools/testing/selftests/hid/progs/hid_bpf_helpers.h
@@ -22,6 +22,9 @@
#define HID_REQ_SET_IDLE HID_REQ_SET_IDLE___not_used
#define HID_REQ_SET_PROTOCOL HID_REQ_SET_PROTOCOL___not_used
+/* do not define kfunc through vmlinux.h as this messes up our custom hack */
+#define BPF_NO_KFUNC_PROTOTYPES
+
#include "vmlinux.h"
#undef hid_bpf_ctx
@@ -91,31 +94,31 @@ struct hid_bpf_ops {
/* following are kfuncs exported by HID for HID-BPF */
extern __u8 *hid_bpf_get_data(struct hid_bpf_ctx *ctx,
unsigned int offset,
- const size_t __sz) __ksym;
-extern struct hid_bpf_ctx *hid_bpf_allocate_context(unsigned int hid_id) __ksym;
-extern void hid_bpf_release_context(struct hid_bpf_ctx *ctx) __ksym;
+ const size_t __sz) __weak __ksym;
+extern struct hid_bpf_ctx *hid_bpf_allocate_context(unsigned int hid_id) __weak __ksym;
+extern void hid_bpf_release_context(struct hid_bpf_ctx *ctx) __weak __ksym;
extern int hid_bpf_hw_request(struct hid_bpf_ctx *ctx,
__u8 *data,
size_t buf__sz,
enum hid_report_type type,
- enum hid_class_request reqtype) __ksym;
+ enum hid_class_request reqtype) __weak __ksym;
extern int hid_bpf_hw_output_report(struct hid_bpf_ctx *ctx,
- __u8 *buf, size_t buf__sz) __ksym;
+ __u8 *buf, size_t buf__sz) __weak __ksym;
extern int hid_bpf_input_report(struct hid_bpf_ctx *ctx,
enum hid_report_type type,
__u8 *data,
- size_t buf__sz) __ksym;
+ size_t buf__sz) __weak __ksym;
extern int hid_bpf_try_input_report(struct hid_bpf_ctx *ctx,
enum hid_report_type type,
__u8 *data,
- size_t buf__sz) __ksym;
+ size_t buf__sz) __weak __ksym;
/* bpf_wq implementation */
extern int bpf_wq_init(struct bpf_wq *wq, void *p__map, unsigned int flags) __weak __ksym;
extern int bpf_wq_start(struct bpf_wq *wq, unsigned int flags) __weak __ksym;
extern int bpf_wq_set_callback_impl(struct bpf_wq *wq,
int (callback_fn)(void *map, int *key, void *wq),
- unsigned int flags__k, void *aux__ign) __ksym;
+ unsigned int flags__k, void *aux__ign) __weak __ksym;
#define bpf_wq_set_callback(timer, cb, flags) \
bpf_wq_set_callback_impl(timer, cb, flags, NULL)
diff --git a/tools/testing/selftests/hid/run-hid-tools-tests.sh b/tools/testing/selftests/hid/run-hid-tools-tests.sh
index bdae8464da86..af1682a53c27 100755
--- a/tools/testing/selftests/hid/run-hid-tools-tests.sh
+++ b/tools/testing/selftests/hid/run-hid-tools-tests.sh
@@ -2,24 +2,26 @@
# SPDX-License-Identifier: GPL-2.0
# Runs tests for the HID subsystem
+KSELFTEST_SKIP_TEST=4
+
if ! command -v python3 > /dev/null 2>&1; then
echo "hid-tools: [SKIP] python3 not installed"
- exit 77
+ exit $KSELFTEST_SKIP_TEST
fi
if ! python3 -c "import pytest" > /dev/null 2>&1; then
- echo "hid: [SKIP/ pytest module not installed"
- exit 77
+ echo "hid: [SKIP] pytest module not installed"
+ exit $KSELFTEST_SKIP_TEST
fi
if ! python3 -c "import pytest_tap" > /dev/null 2>&1; then
- echo "hid: [SKIP/ pytest_tap module not installed"
- exit 77
+ echo "hid: [SKIP] pytest_tap module not installed"
+ exit $KSELFTEST_SKIP_TEST
fi
if ! python3 -c "import hidtools" > /dev/null 2>&1; then
- echo "hid: [SKIP/ hid-tools module not installed"
- exit 77
+ echo "hid: [SKIP] hid-tools module not installed"
+ exit $KSELFTEST_SKIP_TEST
fi
TARGET=${TARGET:=.}
diff --git a/tools/testing/selftests/iommu/iommufd_fail_nth.c b/tools/testing/selftests/iommu/iommufd_fail_nth.c
index 22f6fd5f0f74..64b1f8e1b0cf 100644
--- a/tools/testing/selftests/iommu/iommufd_fail_nth.c
+++ b/tools/testing/selftests/iommu/iommufd_fail_nth.c
@@ -615,7 +615,12 @@ TEST_FAIL_NTH(basic_fail_nth, access_pin_domain)
/* device.c */
TEST_FAIL_NTH(basic_fail_nth, device)
{
+ struct iommu_hwpt_selftest data = {
+ .iotlb = IOMMU_TEST_IOTLB_DEFAULT,
+ };
struct iommu_test_hw_info info;
+ uint32_t fault_id, fault_fd;
+ uint32_t fault_hwpt_id;
uint32_t ioas_id;
uint32_t ioas_id2;
uint32_t stdev_id;
@@ -678,6 +683,15 @@ TEST_FAIL_NTH(basic_fail_nth, device)
if (_test_cmd_vdevice_alloc(self->fd, viommu_id, idev_id, 0, &vdev_id))
return -1;
+ if (_test_ioctl_fault_alloc(self->fd, &fault_id, &fault_fd))
+ return -1;
+ close(fault_fd);
+
+ if (_test_cmd_hwpt_alloc(self->fd, idev_id, hwpt_id, fault_id,
+ IOMMU_HWPT_FAULT_ID_VALID, &fault_hwpt_id,
+ IOMMU_HWPT_DATA_SELFTEST, &data, sizeof(data)))
+ return -1;
+
return 0;
}
diff --git a/tools/testing/selftests/kselftest/ktap_helpers.sh b/tools/testing/selftests/kselftest/ktap_helpers.sh
index 79a125eb24c2..05a461890671 100644
--- a/tools/testing/selftests/kselftest/ktap_helpers.sh
+++ b/tools/testing/selftests/kselftest/ktap_helpers.sh
@@ -7,6 +7,7 @@
KTAP_TESTNO=1
KTAP_CNT_PASS=0
KTAP_CNT_FAIL=0
+KTAP_CNT_XFAIL=0
KTAP_CNT_SKIP=0
KSFT_PASS=0
@@ -69,6 +70,16 @@ ktap_test_skip() {
KTAP_CNT_SKIP=$((KTAP_CNT_SKIP+1))
}
+ktap_test_xfail() {
+ description="$1"
+
+ result="ok"
+ directive="XFAIL"
+ __ktap_test "$result" "$description" "$directive"
+
+ KTAP_CNT_XFAIL=$((KTAP_CNT_XFAIL+1))
+}
+
ktap_test_fail() {
description="$1"
@@ -99,7 +110,7 @@ ktap_exit_fail_msg() {
ktap_finished() {
ktap_print_totals
- if [ $((KTAP_CNT_PASS + KTAP_CNT_SKIP)) -eq "$KSFT_NUM_TESTS" ]; then
+ if [ $((KTAP_CNT_PASS + KTAP_CNT_SKIP + KTAP_CNT_XFAIL)) -eq "$KSFT_NUM_TESTS" ]; then
exit "$KSFT_PASS"
else
exit "$KSFT_FAIL"
@@ -107,5 +118,5 @@ ktap_finished() {
}
ktap_print_totals() {
- echo "# Totals: pass:$KTAP_CNT_PASS fail:$KTAP_CNT_FAIL xfail:0 xpass:0 skip:$KTAP_CNT_SKIP error:0"
+ echo "# Totals: pass:$KTAP_CNT_PASS fail:$KTAP_CNT_FAIL xfail:$KTAP_CNT_XFAIL xpass:0 skip:$KTAP_CNT_SKIP error:0"
}
diff --git a/tools/testing/selftests/kvm/riscv/get-reg-list.c b/tools/testing/selftests/kvm/riscv/get-reg-list.c
index 54ab484d0000..4bc1051848e5 100644
--- a/tools/testing/selftests/kvm/riscv/get-reg-list.c
+++ b/tools/testing/selftests/kvm/riscv/get-reg-list.c
@@ -47,6 +47,8 @@ bool filter_reg(__u64 reg)
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SSCOFPMF:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SSNPM:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SSTC:
+ case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVADE:
+ case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVADU:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVINVAL:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVNAPOT:
case KVM_REG_RISCV_ISA_EXT | KVM_REG_RISCV_ISA_SINGLE | KVM_RISCV_ISA_EXT_SVPBMT:
@@ -422,6 +424,8 @@ static const char *isa_ext_single_id_to_str(__u64 reg_off)
KVM_ISA_EXT_ARR(SSCOFPMF),
KVM_ISA_EXT_ARR(SSNPM),
KVM_ISA_EXT_ARR(SSTC),
+ KVM_ISA_EXT_ARR(SVADE),
+ KVM_ISA_EXT_ARR(SVADU),
KVM_ISA_EXT_ARR(SVINVAL),
KVM_ISA_EXT_ARR(SVNAPOT),
KVM_ISA_EXT_ARR(SVPBMT),
@@ -955,6 +959,8 @@ KVM_ISA_EXT_SUBLIST_CONFIG(smstateen, SMSTATEEN);
KVM_ISA_EXT_SIMPLE_CONFIG(sscofpmf, SSCOFPMF);
KVM_ISA_EXT_SIMPLE_CONFIG(ssnpm, SSNPM);
KVM_ISA_EXT_SIMPLE_CONFIG(sstc, SSTC);
+KVM_ISA_EXT_SIMPLE_CONFIG(svade, SVADE);
+KVM_ISA_EXT_SIMPLE_CONFIG(svadu, SVADU);
KVM_ISA_EXT_SIMPLE_CONFIG(svinval, SVINVAL);
KVM_ISA_EXT_SIMPLE_CONFIG(svnapot, SVNAPOT);
KVM_ISA_EXT_SIMPLE_CONFIG(svpbmt, SVPBMT);
@@ -1020,6 +1026,8 @@ struct vcpu_reg_list *vcpu_configs[] = {
&config_sscofpmf,
&config_ssnpm,
&config_sstc,
+ &config_svade,
+ &config_svadu,
&config_svinval,
&config_svnapot,
&config_svpbmt,
diff --git a/tools/testing/selftests/memfd/memfd_test.c b/tools/testing/selftests/memfd/memfd_test.c
index 95af2d78fd31..c0c53451a16d 100644
--- a/tools/testing/selftests/memfd/memfd_test.c
+++ b/tools/testing/selftests/memfd/memfd_test.c
@@ -9,6 +9,7 @@
#include <fcntl.h>
#include <linux/memfd.h>
#include <sched.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
@@ -281,6 +282,24 @@ static void *mfd_assert_mmap_shared(int fd)
return p;
}
+static void *mfd_assert_mmap_read_shared(int fd)
+{
+ void *p;
+
+ p = mmap(NULL,
+ mfd_def_size,
+ PROT_READ,
+ MAP_SHARED,
+ fd,
+ 0);
+ if (p == MAP_FAILED) {
+ printf("mmap() failed: %m\n");
+ abort();
+ }
+
+ return p;
+}
+
static void *mfd_assert_mmap_private(int fd)
{
void *p;
@@ -979,6 +998,30 @@ static void test_seal_future_write(void)
close(fd);
}
+static void test_seal_write_map_read_shared(void)
+{
+ int fd;
+ void *p;
+
+ printf("%s SEAL-WRITE-MAP-READ\n", memfd_str);
+
+ fd = mfd_assert_new("kern_memfd_seal_write_map_read",
+ mfd_def_size,
+ MFD_CLOEXEC | MFD_ALLOW_SEALING);
+
+ mfd_assert_add_seals(fd, F_SEAL_WRITE);
+ mfd_assert_has_seals(fd, F_SEAL_WRITE);
+
+ p = mfd_assert_mmap_read_shared(fd);
+
+ mfd_assert_read(fd);
+ mfd_assert_read_shared(fd);
+ mfd_fail_write(fd);
+
+ munmap(p, mfd_def_size);
+ close(fd);
+}
+
/*
* Test SEAL_SHRINK
* Test whether SEAL_SHRINK actually prevents shrinking
@@ -1557,6 +1600,11 @@ static void test_share_fork(char *banner, char *b_suffix)
close(fd);
}
+static bool pid_ns_supported(void)
+{
+ return access("/proc/self/ns/pid", F_OK) == 0;
+}
+
int main(int argc, char **argv)
{
pid_t pid;
@@ -1587,12 +1635,17 @@ int main(int argc, char **argv)
test_seal_write();
test_seal_future_write();
+ test_seal_write_map_read_shared();
test_seal_shrink();
test_seal_grow();
test_seal_resize();
- test_sysctl_simple();
- test_sysctl_nested();
+ if (pid_ns_supported()) {
+ test_sysctl_simple();
+ test_sysctl_nested();
+ } else {
+ printf("PID namespaces are not supported; skipping sysctl tests\n");
+ }
test_share_dup("SHARE-DUP", "");
test_share_mmap("SHARE-MMAP", "");
diff --git a/tools/testing/selftests/mm/hugetlb_dio.c b/tools/testing/selftests/mm/hugetlb_dio.c
index 432d5af15e66..db63abe5ee5e 100644
--- a/tools/testing/selftests/mm/hugetlb_dio.c
+++ b/tools/testing/selftests/mm/hugetlb_dio.c
@@ -76,19 +76,15 @@ void run_dio_using_hugetlb(unsigned int start_off, unsigned int end_off)
/* Get the free huge pages after unmap*/
free_hpage_a = get_free_hugepages();
+ ksft_print_msg("No. Free pages before allocation : %d\n", free_hpage_b);
+ ksft_print_msg("No. Free pages after munmap : %d\n", free_hpage_a);
+
/*
* If the no. of free hugepages before allocation and after unmap does
* not match - that means there could still be a page which is pinned.
*/
- if (free_hpage_a != free_hpage_b) {
- ksft_print_msg("No. Free pages before allocation : %d\n", free_hpage_b);
- ksft_print_msg("No. Free pages after munmap : %d\n", free_hpage_a);
- ksft_test_result_fail(": Huge pages not freed!\n");
- } else {
- ksft_print_msg("No. Free pages before allocation : %d\n", free_hpage_b);
- ksft_print_msg("No. Free pages after munmap : %d\n", free_hpage_a);
- ksft_test_result_pass(": Huge pages freed successfully !\n");
- }
+ ksft_test_result(free_hpage_a == free_hpage_b,
+ "free huge pages from %u-%u\n", start_off, end_off);
}
int main(void)
diff --git a/tools/testing/selftests/module/find_symbol.sh b/tools/testing/selftests/module/find_symbol.sh
index 140364d3c49f..2c56805c9b6e 100755
--- a/tools/testing/selftests/module/find_symbol.sh
+++ b/tools/testing/selftests/module/find_symbol.sh
@@ -44,10 +44,10 @@ load_mod()
local ARCH="$(uname -m)"
case "${ARCH}" in
x86_64)
- perf stat $STATS $MODPROBE test_kallsyms_b
+ perf stat $STATS $MODPROBE $MOD
;;
*)
- time $MODPROBE test_kallsyms_b
+ time $MODPROBE $MOD
exit 1
;;
esac
diff --git a/tools/testing/selftests/net/Makefile b/tools/testing/selftests/net/Makefile
index cb2fc601de66..73ee88d6b043 100644
--- a/tools/testing/selftests/net/Makefile
+++ b/tools/testing/selftests/net/Makefile
@@ -32,6 +32,7 @@ TEST_PROGS += ioam6.sh
TEST_PROGS += gro.sh
TEST_PROGS += gre_gso.sh
TEST_PROGS += cmsg_so_mark.sh
+TEST_PROGS += cmsg_so_priority.sh
TEST_PROGS += cmsg_time.sh cmsg_ipv6.sh
TEST_PROGS += netns-name.sh
TEST_PROGS += nl_netdev.py
@@ -95,6 +96,7 @@ TEST_PROGS += test_bridge_backup_port.sh
TEST_PROGS += fdb_flush.sh fdb_notify.sh
TEST_PROGS += fq_band_pktlimit.sh
TEST_PROGS += vlan_hw_filter.sh
+TEST_PROGS += vlan_bridge_binding.sh
TEST_PROGS += bpf_offload.py
TEST_PROGS += ipv6_route_update_soft_lockup.sh
TEST_PROGS += busy_poll_test.sh
diff --git a/tools/testing/selftests/net/busy_poller.c b/tools/testing/selftests/net/busy_poller.c
index 99b0e8c17fca..04c7ff577bb8 100644
--- a/tools/testing/selftests/net/busy_poller.c
+++ b/tools/testing/selftests/net/busy_poller.c
@@ -54,16 +54,16 @@ struct epoll_params {
#define EPIOCGPARAMS _IOR(EPOLL_IOC_TYPE, 0x02, struct epoll_params)
#endif
-static uint32_t cfg_port = 8000;
+static uint16_t cfg_port = 8000;
static struct in_addr cfg_bind_addr = { .s_addr = INADDR_ANY };
static char *cfg_outfile;
static int cfg_max_events = 8;
-static int cfg_ifindex;
+static uint32_t cfg_ifindex;
/* busy poll params */
static uint32_t cfg_busy_poll_usecs;
-static uint32_t cfg_busy_poll_budget;
-static uint32_t cfg_prefer_busy_poll;
+static uint16_t cfg_busy_poll_budget;
+static uint8_t cfg_prefer_busy_poll;
/* IRQ params */
static uint32_t cfg_defer_hard_irqs;
@@ -79,6 +79,7 @@ static void usage(const char *filepath)
static void parse_opts(int argc, char **argv)
{
+ unsigned long long tmp;
int ret;
int c;
@@ -86,31 +87,40 @@ static void parse_opts(int argc, char **argv)
usage(argv[0]);
while ((c = getopt(argc, argv, "p:m:b:u:P:g:o:d:r:s:i:")) != -1) {
+ /* most options take integer values, except o and b, so reduce
+ * code duplication a bit for the common case by calling
+ * strtoull here and leave bounds checking and casting per
+ * option below.
+ */
+ if (c != 'o' && c != 'b')
+ tmp = strtoull(optarg, NULL, 0);
+
switch (c) {
case 'u':
- cfg_busy_poll_usecs = strtoul(optarg, NULL, 0);
- if (cfg_busy_poll_usecs == ULONG_MAX ||
- cfg_busy_poll_usecs > UINT32_MAX)
+ if (tmp == ULLONG_MAX || tmp > UINT32_MAX)
error(1, ERANGE, "busy_poll_usecs too large");
+
+ cfg_busy_poll_usecs = (uint32_t)tmp;
break;
case 'P':
- cfg_prefer_busy_poll = strtoul(optarg, NULL, 0);
- if (cfg_prefer_busy_poll == ULONG_MAX ||
- cfg_prefer_busy_poll > 1)
+ if (tmp == ULLONG_MAX || tmp > 1)
error(1, ERANGE,
"prefer busy poll should be 0 or 1");
+
+ cfg_prefer_busy_poll = (uint8_t)tmp;
break;
case 'g':
- cfg_busy_poll_budget = strtoul(optarg, NULL, 0);
- if (cfg_busy_poll_budget == ULONG_MAX ||
- cfg_busy_poll_budget > UINT16_MAX)
+ if (tmp == ULLONG_MAX || tmp > UINT16_MAX)
error(1, ERANGE,
"busy poll budget must be [0, UINT16_MAX]");
+
+ cfg_busy_poll_budget = (uint16_t)tmp;
break;
case 'p':
- cfg_port = strtoul(optarg, NULL, 0);
- if (cfg_port > UINT16_MAX)
+ if (tmp == ULLONG_MAX || tmp > UINT16_MAX)
error(1, ERANGE, "port must be <= 65535");
+
+ cfg_port = (uint16_t)tmp;
break;
case 'b':
ret = inet_aton(optarg, &cfg_bind_addr);
@@ -124,41 +134,39 @@ static void parse_opts(int argc, char **argv)
error(1, 0, "outfile invalid");
break;
case 'm':
- cfg_max_events = strtol(optarg, NULL, 0);
-
- if (cfg_max_events == LONG_MIN ||
- cfg_max_events == LONG_MAX ||
- cfg_max_events <= 0)
+ if (tmp == ULLONG_MAX || tmp > INT_MAX)
error(1, ERANGE,
- "max events must be > 0 and < LONG_MAX");
+ "max events must be > 0 and <= INT_MAX");
+
+ cfg_max_events = (int)tmp;
break;
case 'd':
- cfg_defer_hard_irqs = strtoul(optarg, NULL, 0);
-
- if (cfg_defer_hard_irqs == ULONG_MAX ||
- cfg_defer_hard_irqs > INT32_MAX)
+ if (tmp == ULLONG_MAX || tmp > INT32_MAX)
error(1, ERANGE,
"defer_hard_irqs must be <= INT32_MAX");
+
+ cfg_defer_hard_irqs = (uint32_t)tmp;
break;
case 'r':
- cfg_gro_flush_timeout = strtoull(optarg, NULL, 0);
-
- if (cfg_gro_flush_timeout == ULLONG_MAX)
+ if (tmp == ULLONG_MAX || tmp > UINT64_MAX)
error(1, ERANGE,
- "gro_flush_timeout must be < ULLONG_MAX");
+ "gro_flush_timeout must be < UINT64_MAX");
+
+ cfg_gro_flush_timeout = (uint64_t)tmp;
break;
case 's':
- cfg_irq_suspend_timeout = strtoull(optarg, NULL, 0);
-
- if (cfg_irq_suspend_timeout == ULLONG_MAX)
+ if (tmp == ULLONG_MAX || tmp > UINT64_MAX)
error(1, ERANGE,
"irq_suspend_timeout must be < ULLONG_MAX");
+
+ cfg_irq_suspend_timeout = (uint64_t)tmp;
break;
case 'i':
- cfg_ifindex = strtoul(optarg, NULL, 0);
- if (cfg_ifindex == ULONG_MAX)
+ if (tmp == ULLONG_MAX || tmp > INT_MAX)
error(1, ERANGE,
- "ifindex must be < ULONG_MAX");
+ "ifindex must be <= INT_MAX");
+
+ cfg_ifindex = (int)tmp;
break;
}
}
@@ -215,7 +223,7 @@ static void setup_queue(void)
struct netdev_napi_set_req *set_req = NULL;
struct ynl_sock *ys;
struct ynl_error yerr;
- uint32_t napi_id;
+ uint32_t napi_id = 0;
ys = ynl_sock_create(&ynl_netdev_family, &yerr);
if (!ys)
@@ -277,8 +285,8 @@ static void run_poller(void)
* here
*/
epoll_params.busy_poll_usecs = cfg_busy_poll_usecs;
- epoll_params.busy_poll_budget = (uint16_t)cfg_busy_poll_budget;
- epoll_params.prefer_busy_poll = (uint8_t)cfg_prefer_busy_poll;
+ epoll_params.busy_poll_budget = cfg_busy_poll_budget;
+ epoll_params.prefer_busy_poll = cfg_prefer_busy_poll;
epoll_params.__pad = 0;
val = 1;
@@ -342,5 +350,9 @@ int main(int argc, char *argv[])
parse_opts(argc, argv);
setup_queue();
run_poller();
+
+ if (cfg_outfile)
+ free(cfg_outfile);
+
return 0;
}
diff --git a/tools/testing/selftests/net/cmsg_sender.c b/tools/testing/selftests/net/cmsg_sender.c
index 876c2db02a63..bc314382e4e1 100644
--- a/tools/testing/selftests/net/cmsg_sender.c
+++ b/tools/testing/selftests/net/cmsg_sender.c
@@ -59,6 +59,7 @@ struct options {
unsigned int proto;
} sock;
struct option_cmsg_u32 mark;
+ struct option_cmsg_u32 priority;
struct {
bool ena;
unsigned int delay;
@@ -97,6 +98,8 @@ static void __attribute__((noreturn)) cs_usage(const char *bin)
"\n"
"\t\t-m val Set SO_MARK with given value\n"
"\t\t-M val Set SO_MARK via setsockopt\n"
+ "\t\t-P val Set SO_PRIORITY via setsockopt\n"
+ "\t\t-Q val Set SO_PRIORITY via cmsg\n"
"\t\t-d val Set SO_TXTIME with given delay (usec)\n"
"\t\t-t Enable time stamp reporting\n"
"\t\t-f val Set don't fragment via cmsg\n"
@@ -115,7 +118,7 @@ static void cs_parse_args(int argc, char *argv[])
{
int o;
- while ((o = getopt(argc, argv, "46sS:p:P:m:M:n:d:tf:F:c:C:l:L:H:")) != -1) {
+ while ((o = getopt(argc, argv, "46sS:p:P:m:M:n:d:tf:F:c:C:l:L:H:Q:")) != -1) {
switch (o) {
case 's':
opt.silent_send = true;
@@ -148,6 +151,10 @@ static void cs_parse_args(int argc, char *argv[])
opt.mark.ena = true;
opt.mark.val = atoi(optarg);
break;
+ case 'Q':
+ opt.priority.ena = true;
+ opt.priority.val = atoi(optarg);
+ break;
case 'M':
opt.sockopt.mark = atoi(optarg);
break;
@@ -253,6 +260,8 @@ cs_write_cmsg(int fd, struct msghdr *msg, char *cbuf, size_t cbuf_sz)
ca_write_cmsg_u32(cbuf, cbuf_sz, &cmsg_len,
SOL_SOCKET, SO_MARK, &opt.mark);
ca_write_cmsg_u32(cbuf, cbuf_sz, &cmsg_len,
+ SOL_SOCKET, SO_PRIORITY, &opt.priority);
+ ca_write_cmsg_u32(cbuf, cbuf_sz, &cmsg_len,
SOL_IPV6, IPV6_DONTFRAG, &opt.v6.dontfrag);
ca_write_cmsg_u32(cbuf, cbuf_sz, &cmsg_len,
SOL_IPV6, IPV6_TCLASS, &opt.v6.tclass);
diff --git a/tools/testing/selftests/net/cmsg_so_priority.sh b/tools/testing/selftests/net/cmsg_so_priority.sh
new file mode 100755
index 000000000000..ee07d8653262
--- /dev/null
+++ b/tools/testing/selftests/net/cmsg_so_priority.sh
@@ -0,0 +1,151 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+source lib.sh
+
+readonly KSFT_SKIP=4
+
+IP4=192.0.2.1/24
+TGT4=192.0.2.2
+TGT4_RAW=192.0.2.3
+IP6=2001:db8::1/64
+TGT6=2001:db8::2
+TGT6_RAW=2001:db8::3
+PORT=1234
+TOTAL_TESTS=0
+FAILED_TESTS=0
+
+if ! command -v jq &> /dev/null; then
+ echo "SKIP cmsg_so_priroity.sh test: jq is not installed." >&2
+ exit "$KSFT_SKIP"
+fi
+
+check_result() {
+ ((TOTAL_TESTS++))
+ if [ "$1" -ne 0 ]; then
+ ((FAILED_TESTS++))
+ fi
+}
+
+cleanup()
+{
+ cleanup_ns $NS
+}
+
+trap cleanup EXIT
+
+setup_ns NS
+
+create_filter() {
+ local handle=$1
+ local vlan_prio=$2
+ local ip_type=$3
+ local proto=$4
+ local dst_ip=$5
+ local ip_proto
+
+ if [[ "$proto" == "u" ]]; then
+ ip_proto="udp"
+ elif [[ "$ip_type" == "ipv4" && "$proto" == "i" ]]; then
+ ip_proto="icmp"
+ elif [[ "$ip_type" == "ipv6" && "$proto" == "i" ]]; then
+ ip_proto="icmpv6"
+ fi
+
+ tc -n $NS filter add dev dummy1 \
+ egress pref 1 handle "$handle" proto 802.1q \
+ flower vlan_prio "$vlan_prio" vlan_ethtype "$ip_type" \
+ dst_ip "$dst_ip" ${ip_proto:+ip_proto $ip_proto} \
+ action pass
+}
+
+ip -n $NS link set dev lo up
+ip -n $NS link add name dummy1 up type dummy
+
+ip -n $NS link add link dummy1 name dummy1.10 up type vlan id 10 \
+ egress-qos-map 0:0 1:1 2:2 3:3 4:4 5:5 6:6 7:7
+
+ip -n $NS address add $IP4 dev dummy1.10
+ip -n $NS address add $IP6 dev dummy1.10 nodad
+
+ip netns exec $NS sysctl -wq net.ipv4.ping_group_range='0 2147483647'
+
+ip -n $NS neigh add $TGT4 lladdr 00:11:22:33:44:55 nud permanent \
+ dev dummy1.10
+ip -n $NS neigh add $TGT6 lladdr 00:11:22:33:44:55 nud permanent \
+ dev dummy1.10
+ip -n $NS neigh add $TGT4_RAW lladdr 00:11:22:33:44:66 nud permanent \
+ dev dummy1.10
+ip -n $NS neigh add $TGT6_RAW lladdr 00:11:22:33:44:66 nud permanent \
+ dev dummy1.10
+
+tc -n $NS qdisc add dev dummy1 clsact
+
+FILTER_COUNTER=10
+
+for i in 4 6; do
+ for proto in u i r; do
+ echo "Test IPV$i, prot: $proto"
+ for priority in {0..7}; do
+ if [[ $i == 4 && $proto == "r" ]]; then
+ TGT=$TGT4_RAW
+ elif [[ $i == 6 && $proto == "r" ]]; then
+ TGT=$TGT6_RAW
+ elif [ $i == 4 ]; then
+ TGT=$TGT4
+ else
+ TGT=$TGT6
+ fi
+
+ handle="${FILTER_COUNTER}${priority}"
+
+ create_filter $handle $priority ipv$i $proto $TGT
+
+ pkts=$(tc -n $NS -j -s filter show dev dummy1 egress \
+ | jq ".[] | select(.options.handle == ${handle}) | \
+ .options.actions[0].stats.packets")
+
+ if [[ $pkts == 0 ]]; then
+ check_result 0
+ else
+ echo "prio $priority: expected 0, got $pkts"
+ check_result 1
+ fi
+
+ ip netns exec $NS ./cmsg_sender -$i -Q $priority \
+ -p $proto $TGT $PORT
+
+ pkts=$(tc -n $NS -j -s filter show dev dummy1 egress \
+ | jq ".[] | select(.options.handle == ${handle}) | \
+ .options.actions[0].stats.packets")
+ if [[ $pkts == 1 ]]; then
+ check_result 0
+ else
+ echo "prio $priority -Q: expected 1, got $pkts"
+ check_result 1
+ fi
+
+ ip netns exec $NS ./cmsg_sender -$i -P $priority \
+ -p $proto $TGT $PORT
+
+ pkts=$(tc -n $NS -j -s filter show dev dummy1 egress \
+ | jq ".[] | select(.options.handle == ${handle}) | \
+ .options.actions[0].stats.packets")
+ if [[ $pkts == 2 ]]; then
+ check_result 0
+ else
+ echo "prio $priority -P: expected 2, got $pkts"
+ check_result 1
+ fi
+ done
+ FILTER_COUNTER=$((FILTER_COUNTER + 10))
+ done
+done
+
+if [ $FAILED_TESTS -ne 0 ]; then
+ echo "FAIL - $FAILED_TESTS/$TOTAL_TESTS tests failed"
+ exit 1
+else
+ echo "OK - All $TOTAL_TESTS tests passed"
+ exit 0
+fi
diff --git a/tools/testing/selftests/net/fdb_notify.sh b/tools/testing/selftests/net/fdb_notify.sh
index c03151e7791c..c159230c9b62 100755
--- a/tools/testing/selftests/net/fdb_notify.sh
+++ b/tools/testing/selftests/net/fdb_notify.sh
@@ -49,7 +49,7 @@ test_dup_vxlan_self()
{
ip_link_add br up type bridge vlan_filtering 1
ip_link_add vx up type vxlan id 2000 dstport 4789
- ip_link_master vx br
+ ip_link_set_master vx br
do_test_dup add "vxlan" dev vx self dst 192.0.2.1
do_test_dup del "vxlan" dev vx self dst 192.0.2.1
@@ -59,7 +59,7 @@ test_dup_vxlan_master()
{
ip_link_add br up type bridge vlan_filtering 1
ip_link_add vx up type vxlan id 2000 dstport 4789
- ip_link_master vx br
+ ip_link_set_master vx br
do_test_dup add "vxlan master" dev vx master
do_test_dup del "vxlan master" dev vx master
@@ -79,7 +79,7 @@ test_dup_macvlan_master()
ip_link_add br up type bridge vlan_filtering 1
ip_link_add dd up type dummy
ip_link_add mv up link dd type macvlan mode passthru
- ip_link_master mv br
+ ip_link_set_master mv br
do_test_dup add "macvlan master" dev mv self
do_test_dup del "macvlan master" dev mv self
diff --git a/tools/testing/selftests/net/fib_rule_tests.sh b/tools/testing/selftests/net/fib_rule_tests.sh
index 1d58b3b87465..847936363a12 100755
--- a/tools/testing/selftests/net/fib_rule_tests.sh
+++ b/tools/testing/selftests/net/fib_rule_tests.sh
@@ -291,6 +291,37 @@ fib_rule6_test()
"$getnomatch" "iif dscp redirect to table" \
"iif dscp no redirect to table"
fi
+
+ fib_check_iproute_support "flowlabel" "flowlabel"
+ if [ $? -eq 0 ]; then
+ match="flowlabel 0xfffff"
+ getmatch="flowlabel 0xfffff"
+ getnomatch="flowlabel 0xf"
+ fib_rule6_test_match_n_redirect "$match" "$getmatch" \
+ "$getnomatch" "flowlabel redirect to table" \
+ "flowlabel no redirect to table"
+
+ match="flowlabel 0xfffff"
+ getmatch="from $SRC_IP6 iif $DEV flowlabel 0xfffff"
+ getnomatch="from $SRC_IP6 iif $DEV flowlabel 0xf"
+ fib_rule6_test_match_n_redirect "$match" "$getmatch" \
+ "$getnomatch" "iif flowlabel redirect to table" \
+ "iif flowlabel no redirect to table"
+
+ match="flowlabel 0x08000/0x08000"
+ getmatch="flowlabel 0xfffff"
+ getnomatch="flowlabel 0xf7fff"
+ fib_rule6_test_match_n_redirect "$match" "$getmatch" \
+ "$getnomatch" "flowlabel masked redirect to table" \
+ "flowlabel masked no redirect to table"
+
+ match="flowlabel 0x08000/0x08000"
+ getmatch="from $SRC_IP6 iif $DEV flowlabel 0xfffff"
+ getnomatch="from $SRC_IP6 iif $DEV flowlabel 0xf7fff"
+ fib_rule6_test_match_n_redirect "$match" "$getmatch" \
+ "$getnomatch" "iif flowlabel masked redirect to table" \
+ "iif flowlabel masked no redirect to table"
+ fi
}
fib_rule6_vrf_test()
diff --git a/tools/testing/selftests/net/forwarding/Makefile b/tools/testing/selftests/net/forwarding/Makefile
index 7d885cff8d79..00bde7b6f39e 100644
--- a/tools/testing/selftests/net/forwarding/Makefile
+++ b/tools/testing/selftests/net/forwarding/Makefile
@@ -105,6 +105,7 @@ TEST_PROGS = bridge_fdb_learning_limit.sh \
vxlan_bridge_1q_port_8472_ipv6.sh \
vxlan_bridge_1q_port_8472.sh \
vxlan_bridge_1q.sh \
+ vxlan_reserved.sh \
vxlan_symmetric_ipv6.sh \
vxlan_symmetric.sh
diff --git a/tools/testing/selftests/net/forwarding/bridge_vlan_unaware.sh b/tools/testing/selftests/net/forwarding/bridge_vlan_unaware.sh
index 1c8a26046589..2b5700b61ffa 100755
--- a/tools/testing/selftests/net/forwarding/bridge_vlan_unaware.sh
+++ b/tools/testing/selftests/net/forwarding/bridge_vlan_unaware.sh
@@ -1,7 +1,7 @@
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
-ALL_TESTS="ping_ipv4 ping_ipv6 learning flooding"
+ALL_TESTS="ping_ipv4 ping_ipv6 learning flooding pvid_change"
NUM_NETIFS=4
source lib.sh
@@ -77,12 +77,16 @@ cleanup()
ping_ipv4()
{
- ping_test $h1 192.0.2.2
+ local msg=$1
+
+ ping_test $h1 192.0.2.2 "$msg"
}
ping_ipv6()
{
- ping6_test $h1 2001:db8:1::2
+ local msg=$1
+
+ ping6_test $h1 2001:db8:1::2 "$msg"
}
learning()
@@ -95,6 +99,21 @@ flooding()
flood_test $swp2 $h1 $h2
}
+pvid_change()
+{
+ # Test that the changing of the VLAN-aware PVID does not affect
+ # VLAN-unaware forwarding
+ bridge vlan add vid 3 dev $swp1 pvid untagged
+
+ ping_ipv4 " with bridge port $swp1 PVID changed"
+ ping_ipv6 " with bridge port $swp1 PVID changed"
+
+ bridge vlan del vid 3 dev $swp1
+
+ ping_ipv4 " with bridge port $swp1 PVID deleted"
+ ping_ipv6 " with bridge port $swp1 PVID deleted"
+}
+
trap cleanup EXIT
setup_prepare
diff --git a/tools/testing/selftests/net/forwarding/lib.sh b/tools/testing/selftests/net/forwarding/lib.sh
index 7337f398f9cc..1fd40bada694 100644
--- a/tools/testing/selftests/net/forwarding/lib.sh
+++ b/tools/testing/selftests/net/forwarding/lib.sh
@@ -932,13 +932,6 @@ packets_rate()
echo $(((t1 - t0) / interval))
}
-mac_get()
-{
- local if_name=$1
-
- ip -j link show dev $if_name | jq -r '.[]["address"]'
-}
-
ether_addr_to_u64()
{
local addr="$1"
diff --git a/tools/testing/selftests/net/forwarding/local_termination.sh b/tools/testing/selftests/net/forwarding/local_termination.sh
index c35548767756..ecd34f364125 100755
--- a/tools/testing/selftests/net/forwarding/local_termination.sh
+++ b/tools/testing/selftests/net/forwarding/local_termination.sh
@@ -7,7 +7,6 @@ ALL_TESTS="standalone vlan_unaware_bridge vlan_aware_bridge test_vlan \
NUM_NETIFS=2
PING_COUNT=1
REQUIRE_MTOOLS=yes
-REQUIRE_MZ=no
source lib.sh
diff --git a/tools/testing/selftests/net/forwarding/vxlan_reserved.sh b/tools/testing/selftests/net/forwarding/vxlan_reserved.sh
new file mode 100755
index 000000000000..46c31794b91b
--- /dev/null
+++ b/tools/testing/selftests/net/forwarding/vxlan_reserved.sh
@@ -0,0 +1,352 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+# +--------------------+
+# | H1 (vrf) |
+# | + $h1 |
+# | | 192.0.2.1/28 |
+# +----|---------------+
+# |
+# +----|--------------------------------+
+# | SW | |
+# | +--|------------------------------+ |
+# | | + $swp1 BR1 (802.1d) | |
+# | | | |
+# | | + vx1 (vxlan) | |
+# | | local 192.0.2.17 | |
+# | | id 1000 dstport $VXPORT | |
+# | +---------------------------------+ |
+# | |
+# | 192.0.2.32/28 via 192.0.2.18 |
+# | |
+# | + $rp1 |
+# | | 192.0.2.17/28 |
+# +--|----------------------------------+
+# |
+# +--|----------------------------------+
+# | | |
+# | + $rp2 |
+# | 192.0.2.18/28 |
+# | |
+# | VRP2 (vrf) |
+# +-------------------------------------+
+
+: ${VXPORT:=4789}
+: ${ALL_TESTS:="
+ default_test
+ plain_test
+ reserved_0_test
+ reserved_10_test
+ reserved_31_test
+ reserved_56_test
+ reserved_63_test
+ "}
+
+NUM_NETIFS=4
+source lib.sh
+
+h1_create()
+{
+ simple_if_init $h1 192.0.2.1/28
+ defer simple_if_fini $h1 192.0.2.1/28
+
+ tc qdisc add dev $h1 clsact
+ defer tc qdisc del dev $h1 clsact
+
+ tc filter add dev $h1 ingress pref 77 \
+ prot ip flower skip_hw ip_proto icmp action drop
+ defer tc filter del dev $h1 ingress pref 77
+}
+
+switch_create()
+{
+ ip_link_add br1 type bridge vlan_filtering 0 mcast_snooping 0
+ # Make sure the bridge uses the MAC address of the local port and not
+ # that of the VxLAN's device.
+ ip_link_set_addr br1 $(mac_get $swp1)
+ ip_link_set_up br1
+
+ ip_link_set_up $rp1
+ ip_addr_add $rp1 192.0.2.17/28
+ ip_route_add 192.0.2.32/28 nexthop via 192.0.2.18
+
+ ip_link_set_master $swp1 br1
+ ip_link_set_up $swp1
+}
+
+vrp2_create()
+{
+ simple_if_init $rp2 192.0.2.18/28
+ defer simple_if_fini $rp2 192.0.2.18/28
+}
+
+setup_prepare()
+{
+ h1=${NETIFS[p1]}
+ swp1=${NETIFS[p2]}
+
+ rp1=${NETIFS[p3]}
+ rp2=${NETIFS[p4]}
+
+ vrf_prepare
+ defer vrf_cleanup
+
+ forwarding_enable
+ defer forwarding_restore
+
+ h1_create
+ switch_create
+
+ vrp2_create
+}
+
+vxlan_header_bytes()
+{
+ local vni=$1; shift
+ local -a extra_bits=("$@")
+ local -a bits
+ local i
+
+ for ((i=0; i < 64; i++)); do
+ bits[i]=0
+ done
+
+ # Bit 4 is the I flag and is always on.
+ bits[4]=1
+
+ for i in ${extra_bits[@]}; do
+ bits[i]=1
+ done
+
+ # Bits 32..55 carry the VNI
+ local mask=0x800000
+ for ((i=0; i < 24; i++)); do
+ bits[$((i + 32))]=$(((vni & mask) != 0))
+ ((mask >>= 1))
+ done
+
+ local bytes
+ for ((i=0; i < 8; i++)); do
+ local byte=0
+ local j
+ for ((j=0; j < 8; j++)); do
+ local bit=${bits[8 * i + j]}
+ ((byte += bit << (7 - j)))
+ done
+ bytes+=$(printf %02x $byte):
+ done
+
+ echo ${bytes%:}
+}
+
+neg_bytes()
+{
+ local bytes=$1; shift
+
+ local -A neg=([0]=f [1]=e [2]=d [3]=c [4]=b [5]=a [6]=9 [7]=8
+ [8]=7 [9]=6 [a]=5 [b]=4 [c]=3 [d]=2 [e]=1 [f]=0 [:]=:)
+ local out
+ local i
+
+ for ((i=0; i < ${#bytes}; i++)); do
+ local c=${bytes:$i:1}
+ out+=${neg[$c]}
+ done
+ echo $out
+}
+
+vxlan_ping_do()
+{
+ local count=$1; shift
+ local dev=$1; shift
+ local next_hop_mac=$1; shift
+ local dest_ip=$1; shift
+ local dest_mac=$1; shift
+ local vni=$1; shift
+ local reserved_bits=$1; shift
+
+ local vxlan_header=$(vxlan_header_bytes $vni $reserved_bits)
+
+ $MZ $dev -c $count -d 100msec -q \
+ -b $next_hop_mac -B $dest_ip \
+ -t udp sp=23456,dp=$VXPORT,p=$(:
+ )"$vxlan_header:"$( : VXLAN
+ )"$dest_mac:"$( : ETH daddr
+ )"00:11:22:33:44:55:"$( : ETH saddr
+ )"08:00:"$( : ETH type
+ )"45:"$( : IP version + IHL
+ )"00:"$( : IP TOS
+ )"00:54:"$( : IP total length
+ )"99:83:"$( : IP identification
+ )"40:00:"$( : IP flags + frag off
+ )"40:"$( : IP TTL
+ )"01:"$( : IP proto
+ )"00:00:"$( : IP header csum
+ )"$(ipv4_to_bytes 192.0.2.3):"$( : IP saddr
+ )"$(ipv4_to_bytes 192.0.2.1):"$( : IP daddr
+ )"08:"$( : ICMP type
+ )"00:"$( : ICMP code
+ )"8b:f2:"$( : ICMP csum
+ )"1f:6a:"$( : ICMP request identifier
+ )"00:01:"$( : ICMP request seq. number
+ )"4f:ff:c5:5b:00:00:00:00:"$( : ICMP payload
+ )"6d:74:0b:00:00:00:00:00:"$( :
+ )"10:11:12:13:14:15:16:17:"$( :
+ )"18:19:1a:1b:1c:1d:1e:1f:"$( :
+ )"20:21:22:23:24:25:26:27:"$( :
+ )"28:29:2a:2b:2c:2d:2e:2f:"$( :
+ )"30:31:32:33:34:35:36:37"
+}
+
+vxlan_device_add()
+{
+ ip_link_add vx1 up type vxlan id 1000 \
+ local 192.0.2.17 dstport "$VXPORT" \
+ nolearning noudpcsum tos inherit ttl 100 "$@"
+ ip_link_set_master vx1 br1
+}
+
+vxlan_all_reserved_bits()
+{
+ local i
+
+ for ((i=0; i < 64; i++)); do
+ if ((i == 4 || i >= 32 && i < 56)); then
+ continue
+ fi
+ echo $i
+ done
+}
+
+vxlan_ping_vanilla()
+{
+ vxlan_ping_do 10 $rp2 $(mac_get $rp1) 192.0.2.17 $(mac_get $h1) 1000
+}
+
+vxlan_ping_reserved()
+{
+ for bit in $(vxlan_all_reserved_bits); do
+ vxlan_ping_do 1 $rp2 $(mac_get $rp1) \
+ 192.0.2.17 $(mac_get $h1) 1000 "$bit"
+ ((n++))
+ done
+}
+
+vxlan_ping_test()
+{
+ local what=$1; shift
+ local get_stat=$1; shift
+ local expect=$1; shift
+
+ RET=0
+
+ local t0=$($get_stat)
+
+ "$@"
+ check_err $? "Failure when running $@"
+
+ local t1=$($get_stat)
+ local delta=$((t1 - t0))
+
+ ((expect == delta))
+ check_err $? "Expected to capture $expect packets, got $delta."
+
+ log_test "$what"
+}
+
+__default_test_do()
+{
+ local n_allowed_bits=$1; shift
+ local what=$1; shift
+
+ vxlan_ping_test "$what: clean packets" \
+ "tc_rule_stats_get $h1 77 ingress" \
+ 10 vxlan_ping_vanilla
+
+ local t0=$(link_stats_get vx1 rx errors)
+ vxlan_ping_test "$what: mangled packets" \
+ "tc_rule_stats_get $h1 77 ingress" \
+ $n_allowed_bits vxlan_ping_reserved
+ local t1=$(link_stats_get vx1 rx errors)
+
+ RET=0
+ local expect=$((39 - n_allowed_bits))
+ local delta=$((t1 - t0))
+ ((expect == delta))
+ check_err $? "Expected $expect error packets, got $delta."
+ log_test "$what: drops reported"
+}
+
+default_test_do()
+{
+ vxlan_device_add
+ __default_test_do 0 "Default"
+}
+
+default_test()
+{
+ in_defer_scope \
+ default_test_do
+}
+
+plain_test_do()
+{
+ vxlan_device_add reserved_bits 0xf7ffffff000000ff
+ __default_test_do 0 "reserved_bits 0xf7ffffff000000ff"
+}
+
+plain_test()
+{
+ in_defer_scope \
+ plain_test_do
+}
+
+reserved_test()
+{
+ local bit=$1; shift
+
+ local allowed_bytes=$(vxlan_header_bytes 0xffffff $bit)
+ local reserved_bytes=$(neg_bytes $allowed_bytes)
+ local reserved_bits=${reserved_bytes//:/}
+
+ vxlan_device_add reserved_bits 0x$reserved_bits
+ __default_test_do 1 "reserved_bits 0x$reserved_bits"
+}
+
+reserved_0_test()
+{
+ in_defer_scope \
+ reserved_test 0
+}
+
+reserved_10_test()
+{
+ in_defer_scope \
+ reserved_test 10
+}
+
+reserved_31_test()
+{
+ in_defer_scope \
+ reserved_test 31
+}
+
+reserved_56_test()
+{
+ in_defer_scope \
+ reserved_test 56
+}
+
+reserved_63_test()
+{
+ in_defer_scope \
+ reserved_test 63
+}
+
+trap cleanup EXIT
+
+setup_prepare
+setup_wait
+tests_run
+
+exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/lib.sh b/tools/testing/selftests/net/lib.sh
index 8994fec1c38f..0bd9a038a1f0 100644
--- a/tools/testing/selftests/net/lib.sh
+++ b/tools/testing/selftests/net/lib.sh
@@ -435,6 +435,13 @@ xfail_on_veth()
fi
}
+mac_get()
+{
+ local if_name=$1
+
+ ip -j link show dev $if_name | jq -r '.[]["address"]'
+}
+
kill_process()
{
local pid=$1; shift
@@ -451,7 +458,7 @@ ip_link_add()
defer ip link del dev "$name"
}
-ip_link_master()
+ip_link_set_master()
{
local member=$1; shift
local master=$1; shift
@@ -459,3 +466,62 @@ ip_link_master()
ip link set dev "$member" master "$master"
defer ip link set dev "$member" nomaster
}
+
+ip_link_set_addr()
+{
+ local name=$1; shift
+ local addr=$1; shift
+
+ local old_addr=$(mac_get "$name")
+ ip link set dev "$name" address "$addr"
+ defer ip link set dev "$name" address "$old_addr"
+}
+
+ip_link_is_up()
+{
+ local name=$1; shift
+
+ local state=$(ip -j link show "$name" |
+ jq -r '(.[].flags[] | select(. == "UP")) // "DOWN"')
+ [[ $state == "UP" ]]
+}
+
+ip_link_set_up()
+{
+ local name=$1; shift
+
+ if ! ip_link_is_up "$name"; then
+ ip link set dev "$name" up
+ defer ip link set dev "$name" down
+ fi
+}
+
+ip_link_set_down()
+{
+ local name=$1; shift
+
+ if ip_link_is_up "$name"; then
+ ip link set dev "$name" down
+ defer ip link set dev "$name" up
+ fi
+}
+
+ip_addr_add()
+{
+ local name=$1; shift
+
+ ip addr add dev "$name" "$@"
+ defer ip addr del dev "$name" "$@"
+}
+
+ip_route_add()
+{
+ ip route add "$@"
+ defer ip route del "$@"
+}
+
+bridge_vlan_add()
+{
+ bridge vlan add "$@"
+ defer bridge vlan del "$@"
+}
diff --git a/tools/testing/selftests/net/lib/py/ksft.py b/tools/testing/selftests/net/lib/py/ksft.py
index 477ae76de93d..3efe005436cd 100644
--- a/tools/testing/selftests/net/lib/py/ksft.py
+++ b/tools/testing/selftests/net/lib/py/ksft.py
@@ -71,6 +71,11 @@ def ksft_in(a, b, comment=""):
_fail("Check failed", a, "not in", b, comment)
+def ksft_is(a, b, comment=""):
+ if a is not b:
+ _fail("Check failed", a, "is not", b, comment)
+
+
def ksft_ge(a, b, comment=""):
if a < b:
_fail("Check failed", a, "<", b, comment)
diff --git a/tools/testing/selftests/net/lib/py/utils.py b/tools/testing/selftests/net/lib/py/utils.py
index 72590c3f90f1..9e3bcddcf3e8 100644
--- a/tools/testing/selftests/net/lib/py/utils.py
+++ b/tools/testing/selftests/net/lib/py/utils.py
@@ -10,7 +10,9 @@ import time
class CmdExitFailure(Exception):
- pass
+ def __init__(self, msg, cmd_obj):
+ super().__init__(msg)
+ self.cmd = cmd_obj
class cmd:
@@ -48,7 +50,7 @@ class cmd:
if len(stderr) > 0 and stderr[-1] == "\n":
stderr = stderr[:-1]
raise CmdExitFailure("Command failed: %s\nSTDOUT: %s\nSTDERR: %s" %
- (self.proc.args, stdout, stderr))
+ (self.proc.args, stdout, stderr), self)
class bkg(cmd):
diff --git a/tools/testing/selftests/net/lib/py/ynl.py b/tools/testing/selftests/net/lib/py/ynl.py
index a0d689d58c57..ad1e36baee2a 100644
--- a/tools/testing/selftests/net/lib/py/ynl.py
+++ b/tools/testing/selftests/net/lib/py/ynl.py
@@ -13,14 +13,14 @@ try:
SPEC_PATH = KSFT_DIR / "net/lib/specs"
sys.path.append(tools_full_path.as_posix())
- from net.lib.ynl.lib import YnlFamily, NlError
+ from net.lib.ynl.pyynl.lib import YnlFamily, NlError
else:
# Running in tree
tools_full_path = KSRC / "tools"
SPEC_PATH = KSRC / "Documentation/netlink/specs"
sys.path.append(tools_full_path.as_posix())
- from net.ynl.lib import YnlFamily, NlError
+ from net.ynl.pyynl.lib import YnlFamily, NlError
except ModuleNotFoundError as e:
ksft_pr("Failed importing `ynl` library from kernel sources")
ksft_pr(str(e))
@@ -32,23 +32,23 @@ except ModuleNotFoundError as e:
# Set schema='' to avoid jsonschema validation, it's slow
#
class EthtoolFamily(YnlFamily):
- def __init__(self):
+ def __init__(self, recv_size=0):
super().__init__((SPEC_PATH / Path('ethtool.yaml')).as_posix(),
- schema='')
+ schema='', recv_size=recv_size)
class RtnlFamily(YnlFamily):
- def __init__(self):
+ def __init__(self, recv_size=0):
super().__init__((SPEC_PATH / Path('rt_link.yaml')).as_posix(),
- schema='')
+ schema='', recv_size=recv_size)
class NetdevFamily(YnlFamily):
- def __init__(self):
+ def __init__(self, recv_size=0):
super().__init__((SPEC_PATH / Path('netdev.yaml')).as_posix(),
- schema='')
+ schema='', recv_size=recv_size)
class NetshaperFamily(YnlFamily):
- def __init__(self):
+ def __init__(self, recv_size=0):
super().__init__((SPEC_PATH / Path('net_shaper.yaml')).as_posix(),
- schema='')
+ schema='', recv_size=recv_size)
diff --git a/tools/testing/selftests/net/netfilter/rpath.sh b/tools/testing/selftests/net/netfilter/rpath.sh
index 4485fd7675ed..86ec4e68594d 100755
--- a/tools/testing/selftests/net/netfilter/rpath.sh
+++ b/tools/testing/selftests/net/netfilter/rpath.sh
@@ -61,9 +61,20 @@ ip -net "$ns2" a a 192.168.42.1/24 dev d0
ip -net "$ns1" a a fec0:42::2/64 dev v0 nodad
ip -net "$ns2" a a fec0:42::1/64 dev d0 nodad
+# avoid neighbor lookups and enable martian IPv6 pings
+ns2_hwaddr=$(ip -net "$ns2" link show dev v0 | \
+ sed -n 's, *link/ether \([^ ]*\) .*,\1,p')
+ns1_hwaddr=$(ip -net "$ns1" link show dev v0 | \
+ sed -n 's, *link/ether \([^ ]*\) .*,\1,p')
+ip -net "$ns1" neigh add fec0:42::1 lladdr "$ns2_hwaddr" nud permanent dev v0
+ip -net "$ns1" neigh add fec0:23::1 lladdr "$ns2_hwaddr" nud permanent dev v0
+ip -net "$ns2" neigh add fec0:42::2 lladdr "$ns1_hwaddr" nud permanent dev d0
+ip -net "$ns2" neigh add fec0:23::2 lladdr "$ns1_hwaddr" nud permanent dev v0
+
# firewall matches to test
[ -n "$iptables" ] && {
common='-t raw -A PREROUTING -s 192.168.0.0/16'
+ common+=' -p icmp --icmp-type echo-request'
if ! ip netns exec "$ns2" "$iptables" $common -m rpfilter;then
echo "Cannot add rpfilter rule"
exit $ksft_skip
@@ -72,6 +83,7 @@ ip -net "$ns2" a a fec0:42::1/64 dev d0 nodad
}
[ -n "$ip6tables" ] && {
common='-t raw -A PREROUTING -s fec0::/16'
+ common+=' -p icmpv6 --icmpv6-type echo-request'
if ! ip netns exec "$ns2" "$ip6tables" $common -m rpfilter;then
echo "Cannot add rpfilter rule"
exit $ksft_skip
@@ -82,8 +94,10 @@ ip -net "$ns2" a a fec0:42::1/64 dev d0 nodad
table inet t {
chain c {
type filter hook prerouting priority raw;
- ip saddr 192.168.0.0/16 fib saddr . iif oif exists counter
- ip6 saddr fec0::/16 fib saddr . iif oif exists counter
+ ip saddr 192.168.0.0/16 icmp type echo-request \
+ fib saddr . iif oif exists counter
+ ip6 saddr fec0::/16 icmpv6 type echo-request \
+ fib saddr . iif oif exists counter
}
}
EOF
diff --git a/tools/testing/selftests/net/nl_netdev.py b/tools/testing/selftests/net/nl_netdev.py
index 93d9d914529b..93e8cb671c3d 100755
--- a/tools/testing/selftests/net/nl_netdev.py
+++ b/tools/testing/selftests/net/nl_netdev.py
@@ -18,6 +18,23 @@ def lo_check(nf) -> None:
ksft_eq(len(lo_info['xdp-rx-metadata-features']), 0)
+def napi_list_check(nf) -> None:
+ with NetdevSimDev(queue_count=100) as nsimdev:
+ nsim = nsimdev.nsims[0]
+
+ ip(f"link set dev {nsim.ifname} up")
+
+ napis = nf.napi_get({'ifindex': nsim.ifindex}, dump=True)
+ ksft_eq(len(napis), 100)
+
+ for q in [50, 0, 99]:
+ for i in range(4):
+ nsim.dfs_write("queue_reset", f"{q} {i}")
+ napis = nf.napi_get({'ifindex': nsim.ifindex}, dump=True)
+ ksft_eq(len(napis), 100,
+ comment=f"queue count after reset queue {q} mode {i}")
+
+
def page_pool_check(nf) -> None:
with NetdevSimDev() as nsimdev:
nsim = nsimdev.nsims[0]
@@ -89,7 +106,7 @@ def page_pool_check(nf) -> None:
def main() -> None:
nf = NetdevFamily()
- ksft_run([empty_check, lo_check, page_pool_check],
+ ksft_run([empty_check, lo_check, page_pool_check, napi_list_check],
args=(nf, ))
ksft_exit()
diff --git a/tools/testing/selftests/net/openvswitch/openvswitch.sh b/tools/testing/selftests/net/openvswitch/openvswitch.sh
index cc0bfae2bafa..960e1ab4dd04 100755
--- a/tools/testing/selftests/net/openvswitch/openvswitch.sh
+++ b/tools/testing/selftests/net/openvswitch/openvswitch.sh
@@ -171,8 +171,10 @@ ovs_add_netns_and_veths () {
ovs_add_if "$1" "$2" "$4" -u || return 1
fi
- [ $TRACING -eq 1 ] && ovs_netns_spawn_daemon "$1" "$ns" \
- tcpdump -i any -s 65535
+ if [ $TRACING -eq 1 ]; then
+ ovs_netns_spawn_daemon "$1" "$3" tcpdump -l -i any -s 6553
+ ovs_wait grep -q "listening on any" ${ovs_dir}/stderr
+ fi
return 0
}
diff --git a/tools/testing/selftests/net/packetdrill/ksft_runner.sh b/tools/testing/selftests/net/packetdrill/ksft_runner.sh
index 4071c133f29e..ff989c325eef 100755
--- a/tools/testing/selftests/net/packetdrill/ksft_runner.sh
+++ b/tools/testing/selftests/net/packetdrill/ksft_runner.sh
@@ -23,7 +23,7 @@ if [ $# -ne 1 ]; then
ktap_exit_fail_msg "usage: $0 <script>"
exit "$KSFT_FAIL"
fi
-script="$1"
+script="$(basename $1)"
if [ -z "$(which packetdrill)" ]; then
ktap_skip_all "packetdrill not found in PATH"
@@ -31,16 +31,29 @@ if [ -z "$(which packetdrill)" ]; then
fi
declare -a optargs
+failfunc=ktap_test_fail
+
if [[ -n "${KSFT_MACHINE_SLOW}" ]]; then
optargs+=('--tolerance_usecs=14000')
+
+ # xfail tests that are known flaky with dbg config, not fixable.
+ # still run them for coverage (and expect 100% pass without dbg).
+ declare -ar xfail_list=(
+ "tcp_fast_recovery_prr-ss.*.pkt"
+ "tcp_timestamping.*.pkt"
+ "tcp_user_timeout_user-timeout-probe.pkt"
+ "tcp_zerocopy_epoll_.*.pkt"
+ )
+ readonly xfail_regex="^($(printf '%s|' "${xfail_list[@]}"))$"
+ [[ "$script" =~ ${xfail_regex} ]] && failfunc=ktap_test_xfail
fi
ktap_print_header
ktap_set_plan 2
-unshare -n packetdrill ${ipv4_args[@]} ${optargs[@]} $(basename $script) > /dev/null \
- && ktap_test_pass "ipv4" || ktap_test_fail "ipv4"
-unshare -n packetdrill ${ipv6_args[@]} ${optargs[@]} $(basename $script) > /dev/null \
- && ktap_test_pass "ipv6" || ktap_test_fail "ipv6"
+unshare -n packetdrill ${ipv4_args[@]} ${optargs[@]} $script > /dev/null \
+ && ktap_test_pass "ipv4" || $failfunc "ipv4"
+unshare -n packetdrill ${ipv6_args[@]} ${optargs[@]} $script > /dev/null \
+ && ktap_test_pass "ipv6" || $failfunc "ipv6"
ktap_finished
diff --git a/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-accept.pkt b/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-accept.pkt
new file mode 100644
index 000000000000..38535701656e
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-accept.pkt
@@ -0,0 +1,18 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test for blocking accept.
+
+`./defaults.sh`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+ +0...0.200 accept(3, ..., ...) = 4
+
+ +.1 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+ +.1 < . 1:1(0) ack 1 win 257
+
+ +.1 write(4, ..., 2000) = 2000
+ +0 > P. 1:2001(2000) ack 1
diff --git a/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-connect.pkt b/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-connect.pkt
new file mode 100644
index 000000000000..3692ef102381
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-connect.pkt
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test for blocking connect.
+
+`./defaults.sh`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+
+ +.1...0.200 connect(3, ..., ...) = 0
+
+ +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+ +.1 < S. 0:0(0) ack 1 win 5792 <mss 1460,nop,wscale 2,nop,nop,sackOK>
+ +0 > . 1:1(0) ack 1
diff --git a/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-read.pkt b/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-read.pkt
new file mode 100644
index 000000000000..914eabab367a
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-read.pkt
@@ -0,0 +1,29 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test for blocking read.
+--tolerance_usecs=10000
+
+`./defaults.sh`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +.1 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+ +.1 < . 1:1(0) ack 1 win 257
+ +0 accept(3, ..., ...) = 4
+
+ +0...0.100 read(4, ..., 2000) = 2000
+ +.1 < P. 1:2001(2000) ack 1 win 257
+ +0 > . 1:1(0) ack 2001
+
+ +.1...0.200 read(4, ..., 2000) = 2000
+ +.1 < P. 2001:4001(2000) ack 1 win 257
+ +0 > . 1:1(0) ack 4001
+
+ +.1 < P. 4001:6001(2000) ack 1 win 257
+ +0 > . 1:1(0) ack 6001
+ +0...0.000 read(4, ..., 1000) = 1000
+ +0...0.000 read(4, ..., 1000) = 1000
diff --git a/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-write.pkt b/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-write.pkt
new file mode 100644
index 000000000000..cec5a0725d95
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_blocking_blocking-write.pkt
@@ -0,0 +1,35 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test for blocking write.
+--tolerance_usecs=10000
+
+`./defaults.sh
+./set_sysctls.py /proc/sys/net/ipv4/tcp_min_tso_segs=10
+`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +.1 < S 0:0(0) win 50000 <mss 1000,nop,wscale 0>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+ +.1 < . 1:1(0) ack 1 win 50000
+ +0 accept(3, ..., ...) = 4
+
+// Kernel doubles our value -> sk->sk_sndbuf is set to 42000
+ +0 setsockopt(4, SOL_SOCKET, SO_SNDBUF, [21000], 4) = 0
+ +0 getsockopt(4, SOL_SOCKET, SO_SNDBUF, [42000], [4]) = 0
+
+// A write of 60000 does not block.
+ +0...0.300 write(4, ..., 61000) = 61000 // this write() blocks
+
+ +.1 < . 1:1(0) ack 10001 win 50000
+
+ +.1 < . 1:1(0) ack 30001 win 50000
+
+// This ACK should wakeup the write(). An ACK of 35001 does not.
+ +.1 < . 1:1(0) ack 36001 win 50000
+
+// Reset to sysctls defaults.
+`/tmp/sysctl_restore_${PPID}.sh`
diff --git a/tools/testing/selftests/net/packetdrill/tcp_close_close-local-close-then-remote-fin.pkt b/tools/testing/selftests/net/packetdrill/tcp_close_close-local-close-then-remote-fin.pkt
new file mode 100644
index 000000000000..8514d6bdbb6d
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_close_close-local-close-then-remote-fin.pkt
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test basic connection teardown where local process closes first:
+// the local process calls close() first, so we send a FIN, and receive an ACK.
+// Then we receive a FIN and ACK it.
+
+`./defaults.sh`
+
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +.01...0.011 connect(3, ..., ...) = 0
+ +0 > S 0:0(0) <...>
+ +0 < S. 0:0(0) ack 1 win 32768 <mss 1000,nop,wscale 6,nop,nop,sackOK>
+ +0 > . 1:1(0) ack 1
+
+ +0 write(3, ..., 1000) = 1000
+ +0 > P. 1:1001(1000) ack 1
+ +0 < . 1:1(0) ack 1001 win 257
+
+ +0 close(3) = 0
+ +0 > F. 1001:1001(0) ack 1
+ +0 < . 1:1(0) ack 1002 win 257
+
+ +0 < F. 1:1(0) ack 1002 win 257
+ +0 > . 1002:1002(0) ack 2
diff --git a/tools/testing/selftests/net/packetdrill/tcp_close_close-on-syn-sent.pkt b/tools/testing/selftests/net/packetdrill/tcp_close_close-on-syn-sent.pkt
new file mode 100644
index 000000000000..04103134bd99
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_close_close-on-syn-sent.pkt
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test to make sure no RST is being sent when close()
+// is called on a socket with SYN_SENT state.
+
+`./defaults.sh`
+
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+
+ +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+ +0 > S 0:0(0) <...>
+
+// Application decideds to close the socket in SYN_SENT state
+// Make sure no RST is sent after close().
+ +0 close(3) = 0
+
+// Receive syn-ack to trigger the send side packet examination:
+// If a RESET were sent right after close(), it would have failed with
+// a mismatched timestamp.
+ +.1 < S. 0:0(0) ack 1 win 32000 <mss 1460,nop,wscale 7>
+ +0 > R 1:1(0)
diff --git a/tools/testing/selftests/net/packetdrill/tcp_close_close-remote-fin-then-close.pkt b/tools/testing/selftests/net/packetdrill/tcp_close_close-remote-fin-then-close.pkt
new file mode 100644
index 000000000000..5f3a2914213a
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_close_close-remote-fin-then-close.pkt
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+// Verify behavior for the sequence: remote side sends FIN, then we close().
+// Since the remote side (client) closes first, we test our LAST_ACK code path.
+
+`./defaults.sh`
+
+// Initialize a server socket.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +0 < . 1:1(0) ack 1 win 257
+
+ +0 accept(3, ..., ...) = 4
+
+// Client closes first.
+ +.01 < F. 1:1(0) ack 1 win 257
+ +0 > . 1:1(0) ack 2
+
+// App notices that client closed.
+ +0 read(4, ..., 1000) = 0
+
+// Then we close.
+ +.01 close(4) = 0
+ +0 > F. 1:1(0) ack 2
+
+// Client ACKs our FIN.
+ +.01 < . 2:2(0) ack 2 win 257
+
+// Verify that we send RST in response to any incoming segments
+// (because the kernel no longer has any record of this socket).
+ +.01 < . 2:2(0) ack 2 win 257
+ +0 > R 2:2(0)
diff --git a/tools/testing/selftests/net/packetdrill/tcp_ecn_ecn-uses-ect0.pkt b/tools/testing/selftests/net/packetdrill/tcp_ecn_ecn-uses-ect0.pkt
new file mode 100644
index 000000000000..643baf3267cf
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_ecn_ecn-uses-ect0.pkt
@@ -0,0 +1,21 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test ECN: verify that Linux TCP ECN sending code uses ECT0 (not ECT1).
+//
+`./defaults.sh
+sysctl -q net.ipv4.tcp_ecn=1 # fully enabled
+`
+
+// Initialize connection
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+
+// ECN handshake: send EW flags in SYN packet, E flag in SYN-ACK response
++.002 ... 0.004 connect(4, ..., ...) = 0
+
+ +0 > SEW 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
++.002 < SE. 0:0(0) ack 1 win 32767 <mss 1000,nop,wscale 6,nop,nop,sackOK>
+ +0 > . 1:1(0) ack 1
+
+// Write 1 MSS.
++.002 write(4, ..., 1000) = 1000
+// Send 1 MSS with ect0.
+ +0 > [ect0] P. 1:1001(1000) ack 1
diff --git a/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-large.pkt b/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-large.pkt
new file mode 100644
index 000000000000..f95b9b3c9fa1
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-large.pkt
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test TCP does not append any data from consequent writes to the tail
+// skb created for the chunk. The large chunk itself should be packetized as
+// usual.
+`./defaults.sh
+`
+
+// Initialize connection
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.01 < . 1:1(0) ack 1 win 514
+
+ +0 accept(3, ..., ...) = 4
+
+// Write a 10400B chunk to fill the ICW, and have a 400 byte skb sitting on
+// the tail.
+ +0 write(4, ..., 10400) = 10400
+
+// Write another 10040B chunk with no coalescing options.
+ +0 send(4, ..., 10400, MSG_EOR) = 10400
+
+// Write a 2KB chunk. This chunk should not be appended to the packets created
+// the previous chunk.
+ +0 write(4, ..., 2000) = 2000
+
+ +0 > P. 1:10001(10000) ack 1
++.001 < . 1:1(0) ack 10001 win 514
+// Now we have enough room to send out the 2 x 400B packets out.
+ +0 > P. 10001:20801(10800) ack 1
++.001 < . 1:1(0) ack 20801 win 514
+// This 2KB packet should be sent alone.
+ +0 > P. 20801:22801(2000) ack 1
++.001 < . 1:1(0) ack 22801 win 514
diff --git a/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-retrans.pkt b/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-retrans.pkt
new file mode 100644
index 000000000000..2ff66075288e
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-retrans.pkt
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test TCP does not append any data from consequent writes to the tail
+// skb created for the chunk. Also, when packets are retransmitted, they
+// will not be coalesce into the same skb.
+`./defaults.sh
+`
+
+// Initialize connection
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.01 < . 1:1(0) ack 1 win 514
+
+ +0 accept(3, ..., ...) = 4
+
+// Write a 10400B chunk to fill the ICW, and have a 400 byte skb sitting on
+// the tail.
+ +0 write(4, ..., 10400) = 10400
+
+// Write 10 400B chunks with no coalescing options.
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+// This chunk should not be appended to the skbs created for the previous chunk.
+ +0 write(4, ..., 10000) = 10000
+
+ +0 > P. 1:10001(10000) ack 1
++.001 < . 1:1(0) ack 10001 win 514
+// Now we have enough room to send out the 2 x 400B packets out.
+ +0 > P. 10001:10801(800) ack 1
+// The 9 remaining 400B chunks should be sent as individual packets.
+ +0 > P. 10801:11201(400) ack 1
+ +0 > P. 11201:11601(400) ack 1
+ +0 > P. 11601:12001(400) ack 1
+ +0 > P. 12001:12401(400) ack 1
+ +0 > P. 12401:12801(400) ack 1
+ +0 > P. 12801:13201(400) ack 1
+ +0 > P. 13201:13601(400) ack 1
+ +0 > P. 13601:14001(400) ack 1
+ +0 > P. 14001:14401(400) ack 1
+// The last 10KB chunk should be sent separately.
+ +0 > P. 14401:24401(10000) ack 1
+
++.001 < . 1:1(0) ack 10401 win 514
++.001 < . 1:1(0) ack 10801 win 514
++.001 < . 1:1(0) ack 11201 win 514
++.001 < . 1:1(0) ack 11601 win 514
++.001 < . 1:1(0) ack 12001 win 514 <sack 13201:14401,nop,nop>
+// TCP should fill the hole but no coalescing should happen, and all
+// retransmissions should be sent out as individual packets.
+
+// Note : This is timeout based retransmit.
+// Do not put +0 here or flakes will come back.
++.004~+.008 > P. 12001:12401(400) ack 1
+
++.001 < . 1:1(0) ack 12401 win 514 <sack 13201:14401,nop,nop>
+ +0 > P. 12401:12801(400) ack 1
+ +0 > P. 12801:13201(400) ack 1
++.001 < . 1:1(0) ack 12801 win 514 <sack 13201:14401,nop,nop>
++.001 < . 1:1(0) ack 14401 win 514
++.001 < . 1:1(0) ack 24401 win 514
diff --git a/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-small.pkt b/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-small.pkt
new file mode 100644
index 000000000000..77039c5aac39
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-small.pkt
@@ -0,0 +1,36 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test TCP does not append any data from consequent writes to the tail
+// skb created for the chunk.
+`./defaults.sh
+`
+
+// Initialize connection
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.01 < . 1:1(0) ack 1 win 514
+
+ +0 accept(3, ..., ...) = 4
+
+// Write a 10400B chunk to fill the ICW, and have a 400 byte skb sitting on
+// the tail.
+ +0 write(4, ..., 10400) = 10400
+
+// Write a 400B chunk with no coalescing options.
+ +0 send(4, ..., 400, MSG_EOR) = 400
+
+// This chunk should not be appended to the skbs created for the previous chunk.
+ +0 write(4, ..., 10000) = 10000
+
+ +0 > P. 1:10001(10000) ack 1
++.001 < . 1:1(0) ack 10001 win 514
+// Now we have enough room to send out the 2 x 400B packets out.
+ +0 > P. 10001:10801(800) ack 1
+ +0 > P. 10801:20801(10000) ack 1
++.001 < . 1:1(0) ack 10401 win 514
++.001 < . 1:1(0) ack 10801 win 514
++.001 < . 1:1(0) ack 20801 win 514
diff --git a/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-subsequent.pkt b/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-subsequent.pkt
new file mode 100644
index 000000000000..dd5a06250595
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_eor_no-coalesce-subsequent.pkt
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test TCP does not append any data from consequent writes to the tail
+// skb created for the chunk even though we have 10 back-to-back small
+// writes.
+`./defaults.sh
+`
+
+// Initialize connection
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.01 < . 1:1(0) ack 1 win 514
+
+ +0 accept(3, ..., ...) = 4
+
+// Write a 10400B chunk to fill the ICW, and have a 400 byte skb sitting on
+// the tail.
+ +0 write(4, ..., 10400) = 10400
+
+// Write 10 400B chunks with no coalescing options.
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+ +0 send(4, ..., 400, MSG_EOR) = 400
+// This chunk should not be appended to the skbs created for the previous chunk.
+ +0 write(4, ..., 10000) = 10000
+
+ +0 > P. 1:10001(10000) ack 1
++.001 < . 1:1(0) ack 10001 win 514
+// Now we have enough room to send out the 2 x 400B packets out.
+ +0 > P. 10001:10801(800) ack 1
+// The 9 remaining 400B chunks should be sent as individual packets.
+ +0 > P. 10801:11201(400) ack 1
+ +0 > P. 11201:11601(400) ack 1
+ +0 > P. 11601:12001(400) ack 1
+ +0 > P. 12001:12401(400) ack 1
+ +0 > P. 12401:12801(400) ack 1
+ +0 > P. 12801:13201(400) ack 1
+ +0 > P. 13201:13601(400) ack 1
+ +0 > P. 13601:14001(400) ack 1
+ +0 > P. 14001:14401(400) ack 1
+// The last 10KB chunk should be sent separately.
+ +0 > P. 14401:24401(10000) ack 1
+
++.001 < . 1:1(0) ack 10401 win 514
++.001 < . 1:1(0) ack 10801 win 514
++.001 < . 1:1(0) ack 11201 win 514
++.001 < . 1:1(0) ack 11601 win 514
++.001 < . 1:1(0) ack 12001 win 514
++.001 < . 1:1(0) ack 12401 win 514
++.001 < . 1:1(0) ack 12801 win 514
++.001 < . 1:1(0) ack 13201 win 514
++.001 < . 1:1(0) ack 13601 win 514
++.001 < . 1:1(0) ack 14001 win 514
++.001 < . 1:1(0) ack 14401 win 514
++.001 < . 1:1(0) ack 24401 win 514
diff --git a/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-10pkt-lost-1.pkt b/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-10pkt-lost-1.pkt
new file mode 100644
index 000000000000..0d3c8077e830
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-10pkt-lost-1.pkt
@@ -0,0 +1,72 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test PRR-slowstart implementation.
+// In this variant we test a simple case where in-flight == ssthresh
+// all the way through recovery, so during fast recovery we send one segment
+// for each segment SACKed/ACKed.
+
+// Set up config.
+`./defaults.sh`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +.1 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+// RTT 100ms
+ +.1 < . 1:1(0) ack 1 win 320
+ +0 accept(3, ..., ...) = 4
+
+// Send 10 data segments.
+ +0 write(4, ..., 10000) = 10000
+ +0 > P. 1:10001(10000) ack 1
+
+// Lost packet 1:1001.
+ +.11 < . 1:1(0) ack 1 win 320 <sack 1001:2001,nop,nop>
+ +.01 < . 1:1(0) ack 1 win 320 <sack 1001:3001,nop,nop>
+ +.01 < . 1:1(0) ack 1 win 320 <sack 1001:4001,nop,nop>
+// Enter fast recovery.
+ +0 > . 1:1001(1000) ack 1
+ +.01 %{
+assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state
+assert tcpi_snd_cwnd == 7, tcpi_snd_cwnd
+assert tcpi_snd_ssthresh == 7, tcpi_snd_ssthresh
+}%
+
+// Write some more, which we will send 1 MSS at a time,
+// as in-flight segments are SACKed or ACKed.
+ +.01 write(4, ..., 7000) = 7000
+
+ +.01 < . 1:1(0) ack 1 win 320 <sack 1001:5001,nop,nop>
+ +0 > . 10001:11001(1000) ack 1
+
+ +.01 < . 1:1(0) ack 1 win 320 <sack 1001:6001,nop,nop>
+ +0 > . 11001:12001(1000) ack 1
+
+ +.01 < . 1:1(0) ack 1 win 320 <sack 1001:7001,nop,nop>
+ +0 > . 12001:13001(1000) ack 1
+
+ +.01 < . 1:1(0) ack 1 win 320 <sack 1001:8001,nop,nop>
+ +0 > . 13001:14001(1000) ack 1
+
+ +.01 < . 1:1(0) ack 1 win 320 <sack 1001:9001,nop,nop>
+ +0 > . 14001:15001(1000) ack 1
+
+ +.01 < . 1:1(0) ack 1 win 320 <sack 1001:10001,nop,nop>
+ +0 > . 15001:16001(1000) ack 1
+
+ +.02 < . 1:1(0) ack 10001 win 320
+ +0 > P. 16001:17001(1000) ack 1
+// Leave fast recovery.
+ +.01 %{
+assert tcpi_ca_state == TCP_CA_Open, tcpi_ca_state
+assert tcpi_snd_cwnd == 7, tcpi_snd_cwnd
+assert tcpi_snd_ssthresh == 7, tcpi_snd_ssthresh
+}%
+
+ +.03 < . 1:1(0) ack 12001 win 320
+ +.02 < . 1:1(0) ack 14001 win 320
+ +.02 < . 1:1(0) ack 16001 win 320
+ +.02 < . 1:1(0) ack 17001 win 320
diff --git a/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-30pkt-lost-1_4-11_16.pkt b/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-30pkt-lost-1_4-11_16.pkt
new file mode 100644
index 000000000000..7842a10b6967
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-30pkt-lost-1_4-11_16.pkt
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test PRR-slowstart implementation. The sender sends 20 packets. Packet
+// 1 to 4, and 11 to 16 are dropped.
+`./defaults.sh`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+
+ +.01 < . 1:1(0) ack 1 win 320
+ +0 accept(3, ..., ...) = 4
+
+// Write 20 data segments.
+ +0 write(4, ..., 20000) = 20000
+ +0 > P. 1:10001(10000) ack 1
+
+// Receive first DUPACK, entering PRR part
+ +.01 < . 1:1(0) ack 1 win 320 <sack 4001:5001,nop,nop>
+ +0 > . 10001:11001(1000) ack 1
++.002 < . 1:1(0) ack 1 win 320 <sack 4001:6001,nop,nop>
+ +0 > . 11001:12001(1000) ack 1
++.002 < . 1:1(0) ack 1 win 320 <sack 4001:7001,nop,nop>
+ +0 > . 1:1001(1000) ack 1
++.002 < . 1:1(0) ack 1 win 320 <sack 4001:8001,nop,nop>
+ +0 > . 1001:2001(1000) ack 1
++.002 < . 1:1(0) ack 1 win 320 <sack 4001:9001,nop,nop>
+ +0 > . 2001:3001(1000) ack 1
++.002 < . 1:1(0) ack 1 win 320 <sack 4001:10001,nop,nop>
+ +0 > . 3001:4001(1000) ack 1
+// Enter PRR CRB
++.002 < . 1:1(0) ack 1 win 320 <sack 4001:11001,nop,nop>
+ +0 > . 12001:13001(1000) ack 1
++.002 < . 1:1(0) ack 1 win 320 <sack 4001:12001,nop,nop>
+ +0 > . 13001:14001(1000) ack 1
+// Enter PRR slow start
+ +.01 < . 1:1(0) ack 1001 win 320 <sack 4001:12001,nop,nop>
+ +0 > P. 14001:16001(2000) ack 1
++.002 < . 1:1(0) ack 1001 win 320 <sack 2001:12001,nop,nop>
+ +0 > . 1001:2001(1000) ack 1
+ +0 > . 16001:17001(1000) ack 1
+// inflight reaches ssthresh, goes into packet conservation mode
++.002 < . 1:1(0) ack 1001 win 320 <sack 2001:13001,nop,nop>
+ +0 > . 17001:18001(1000) ack 1
++.002 < . 1:1(0) ack 1001 win 320 <sack 2001:14001,nop,nop>
+ +0 > . 18001:19001(1000) ack 1
diff --git a/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-30pkt-lost1_4.pkt b/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-30pkt-lost1_4.pkt
new file mode 100644
index 000000000000..b66d7644c3b6
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-30pkt-lost1_4.pkt
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test PRR-slowstart implementation. The sender sends 20 packets. Packet
+// 1 to 4 are lost. The sender writes another 10 packets.
+`./defaults.sh`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+
+ +.01 < . 1:1(0) ack 1 win 320
+ +0 accept(3, ..., ...) = 4
+
+// Send 20 data segments.
+ +0 write(4, ..., 10000) = 10000
+ +0 > P. 1:10001(10000) ack 1
+
+// Lost packet 1,2,3,4
+ +.01 < . 1:1(0) ack 1 win 320 <sack 4001:5001,nop,nop>
++.002 < . 1:1(0) ack 1 win 320 <sack 4001:6001,nop,nop>
+ +0 < . 1:1(0) ack 1 win 320 <sack 4001:7001,nop,nop>
+ +0 > . 1:1001(1000) ack 1
+ +0 < . 1:1(0) ack 1 win 320 <sack 4001:8001,nop,nop>
+ +0 > . 1001:2001(1000) ack 1
+ +0 < . 1:1(0) ack 1 win 320 <sack 4001:9001,nop,nop>
+ +0 > . 2001:3001(1000) ack 1
+ +0 < . 1:1(0) ack 1 win 320 <sack 4001:10001,nop,nop>
+ +0 > . 3001:4001(1000) ack 1
+
+// Receiver ACKs all data.
+ +.01 < . 1:1(0) ack 1001 win 320 <sack 4001:10001,nop,nop>
+ +0 < . 1:1(0) ack 2001 win 320 <sack 4001:10001,nop,nop>
+ +0 < . 1:1(0) ack 3001 win 320 <sack 4001:10001,nop,nop>
+ +0 < . 1:1(0) ack 10001 win 320
+
+// Writes another 10 packets, which the ssthresh*mss amount
+// should be sent right away
+ +.01 write(4, ..., 10000) = 10000
+ +0 > . 10001:17001(7000) ack 1
diff --git a/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-ack-below-snd_una-cubic.pkt b/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-ack-below-snd_una-cubic.pkt
new file mode 100644
index 000000000000..8e87bfecabb5
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_fast_recovery_prr-ss-ack-below-snd_una-cubic.pkt
@@ -0,0 +1,41 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test PRR-slowstart implementation.
+// In this variant we verify that the sender uses SACK info on an ACK
+// below snd_una.
+
+// Set up config.
+`./defaults.sh`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 8>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+// RTT 10ms
+ +.01 < . 1:1(0) ack 1 win 320
+ +0 accept(3, ..., ...) = 4
+
+// Send 10 data segments.
+ +0 write(4, ..., 10000) = 10000
+ +0 > P. 1:10001(10000) ack 1
+
+// Lost packet 1:1001,4001:5001,7001:8001.
+ +.01 < . 1:1(0) ack 1 win 320 <sack 1001:2001,nop,nop>
+ +0 < . 1:1(0) ack 1 win 320 <sack 1001:3001,nop,nop>
+ +0 < . 1:1(0) ack 1 win 320 <sack 1001:3001 8001:9001,nop,nop>
+ +0 > . 1:1001(1000) ack 1
+
++.012 < . 1:1(0) ack 4001 win 320 <sack 8001:9001,nop,nop>
+ +0 > . 4001:7001(3000) ack 1
+
+ +0 write(4, ..., 10000) = 10000
+
+// The following ACK was reordered - delayed so that it arrives with
+// an ACK field below snd_una. Here we check that the newly-SACKed
+// 2MSS at 5001:7001 cause us to send out 2 more MSS.
++.002 < . 1:1(0) ack 3001 win 320 <sack 5001:7001,nop,nop>
+ +0 > . 7001:8001(1000) ack 1
+ +0 > . 10001:11001(1000) ack 1
diff --git a/tools/testing/selftests/net/packetdrill/tcp_limited_transmit_limited-transmit-no-sack.pkt b/tools/testing/selftests/net/packetdrill/tcp_limited_transmit_limited-transmit-no-sack.pkt
new file mode 100644
index 000000000000..96b01eb5b7a4
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_limited_transmit_limited-transmit-no-sack.pkt
@@ -0,0 +1,53 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test RFC 3042 "Limited Transmit": "sending a new data segment in
+// response to each of the first two duplicate acknowledgments that
+// arrive at the sender".
+// This variation tests a receiver that doesn't support SACK.
+
+`./defaults.sh`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +.1 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+ +.1 < . 1:1(0) ack 1 win 320
+ +0 accept(3, ..., ...) = 4
+
+// Write some data, and send the initial congestion window.
+ +0 write(4, ..., 15000) = 15000
+ +0 > P. 1:10001(10000) ack 1
+
+// Limited transmit: on first dupack, send a new data segment.
+ +.11 < . 1:1(0) ack 1 win 320
+ +0 > . 10001:11001(1000) ack 1
+
+// Limited transmit: on second dupack, send a new data segment.
+ +.01 < . 1:1(0) ack 1 win 320
+ +0 > . 11001:12001(1000) ack 1
+
+// It turned out to be reordering, not loss.
+// We have one packet newly acked (1001:3001 were DUP-ACK'd)
+// So we revert state back to Open. Slow start cwnd from 10 to 11
+// and send 11 - 9 = 2 packets
+ +.01 < . 1:1(0) ack 3001 win 320
+ +0 > P. 12001:14001(2000) ack 1
+
+ +.02 < . 1:1(0) ack 5001 win 320
+ +0 > P. 14001:15001(1000) ack 1
+
+// Client gradually ACKs all data.
+ +.02 < . 1:1(0) ack 7001 win 320
+ +.02 < . 1:1(0) ack 9001 win 320
+ +.02 < . 1:1(0) ack 11001 win 320
+ +.02 < . 1:1(0) ack 13001 win 320
+ +.02 < . 1:1(0) ack 15001 win 320
+
+// Clean up.
+ +.17 close(4) = 0
+ +0 > F. 15001:15001(0) ack 1
+ +.1 < F. 1:1(0) ack 15002 win 257
+ +0 > . 15002:15002(0) ack 2
diff --git a/tools/testing/selftests/net/packetdrill/tcp_limited_transmit_limited-transmit-sack.pkt b/tools/testing/selftests/net/packetdrill/tcp_limited_transmit_limited-transmit-sack.pkt
new file mode 100644
index 000000000000..642da51ec3a4
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_limited_transmit_limited-transmit-sack.pkt
@@ -0,0 +1,50 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test RFC 3042 "Limited Transmit": "sending a new data segment in
+// response to each of the first two duplicate acknowledgments that
+// arrive at the sender".
+// This variation tests a receiver that supports SACK.
+
+`./defaults.sh`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +.1 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.1 < . 1:1(0) ack 1 win 320
+ +0 accept(3, ..., ...) = 4
+
+// Write some data, and send the initial congestion window.
+ +0 write(4, ..., 15000) = 15000
+ +0 > P. 1:10001(10000) ack 1
+
+// Limited transmit: on first dupack, send a new data segment.
+ +.11 < . 1:1(0) ack 1 win 320 <sack 1001:2001,nop,nop>
+ +0 > . 10001:11001(1000) ack 1
+
+// Limited transmit: on second dupack, send a new data segment.
+ +.01 < . 1:1(0) ack 1 win 320 <sack 1001:3001,nop,nop>
+ +0 > . 11001:12001(1000) ack 1
+
+// It turned out to be reordering, not loss.
+ +.01 < . 1:1(0) ack 3001 win 320
+ +0 > P. 12001:14001(2000) ack 1
+
+ +.02 < . 1:1(0) ack 5001 win 320
+ +0 > P. 14001:15001(1000) ack 1
+
+// Client gradually ACKs all data.
+ +.02 < . 1:1(0) ack 7001 win 320
+ +.02 < . 1:1(0) ack 9001 win 320
+ +.02 < . 1:1(0) ack 11001 win 320
+ +.02 < . 1:1(0) ack 13001 win 320
+ +.02 < . 1:1(0) ack 15001 win 320
+
+// Clean up.
+ +.17 close(4) = 0
+ +0 > F. 15001:15001(0) ack 1
+ +.1 < F. 1:1(0) ack 15002 win 257
+ +0 > . 15002:15002(0) ack 2
diff --git a/tools/testing/selftests/net/packetdrill/tcp_nagle_https_client.pkt b/tools/testing/selftests/net/packetdrill/tcp_nagle_https_client.pkt
new file mode 100644
index 000000000000..7adae7a9ef4a
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_nagle_https_client.pkt
@@ -0,0 +1,40 @@
+// SPDX-License-Identifier: GPL-2.0
+// This is a test inspired by an Android client app using SSL. This
+// test verifies using TCP_NODELAY would save application latency
+// (Perhaps even better with TCP_NAGLE).
+//
+`./defaults.sh
+ethtool -K tun0 tso off gso off
+./set_sysctls.py /proc/sys/net/ipv4/tcp_timestamps=0`
+
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
+ +0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+ +0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
+
+ +0 connect(4, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+ +0 > S 0:0(0) <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.1 < S. 0:0(0) ack 1 win 5792 <mss 974,nop,nop,sackOK,nop,wscale 7>
+ +0 > . 1:1(0) ack 1
+
+// SSL handshake (resumed session)
+ +0 write(4, ..., 517) = 517
+ +0 > P. 1:518(517) ack 1
+ +.1 < . 1:1(0) ack 518 win 229
+
+ +0 < P. 1:144(143) ack 1 win 229
+ +0 > . 518:518(0) ack 144
+ +0 read(4, ..., 1000) = 143
+
+// Application POST header (51B) and body (2002B)
+ +0 write(4, ..., 51) = 51
+ +0 > P. 518:569(51) ack 144
+ +.03 write(4, ..., 2002) = 2002
+ +0 > . 569:1543(974) ack 144
+ +0 > P. 1543:2517(974) ack 144
+// Without disabling Nagle, this packet will not happen until the remote ACK.
+ +0 > P. 2517:2571(54) ack 144
+
+ +.1 < . 1:1(0) ack 2571 win 229
+
+// Reset sysctls
+`/tmp/sysctl_restore_${PPID}.sh`
diff --git a/tools/testing/selftests/net/packetdrill/tcp_nagle_sendmsg_msg_more.pkt b/tools/testing/selftests/net/packetdrill/tcp_nagle_sendmsg_msg_more.pkt
new file mode 100644
index 000000000000..fa9c01813996
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_nagle_sendmsg_msg_more.pkt
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test the MSG_MORE flag will correctly corks the tiny writes
+`./defaults.sh`
+
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+ +.01 < . 1:1(0) ack 1 win 257
+ +0 accept(3, ..., ...) = 4
+// Disable Nagle by default on this socket.
+ +0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
+
+// Test the basic case: MSG_MORE overwrites TCP_NODELAY and enables Nagle.
+ +0 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 40}], msg_flags=0}, MSG_MORE) = 40
+ +.21~+.215 > P. 1:41(40) ack 1
+ +.01 < . 1:1(0) ack 41 win 257
+
+// Test unsetting MSG_MORE releases the packet
+ +0 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 100}], msg_flags=0}, MSG_MORE) = 100
++.005 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 160}], msg_flags=0}, MSG_MORE) = 160
+ +.01 sendmsg(4, {msg_name(...)=...,
+ msg_iov(3)=[{..., 100}, {..., 200}, {..., 195}],
+ msg_flags=0}, MSG_MORE) = 495
++.008 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 5}], msg_flags=0}, 0) = 5
+ +0 > P. 41:801(760) ack 1
+ +.02 < . 1:1(0) ack 801 win 257
+
+
+// Test >MSS write will unleash MSS packets but hold on the remaining data.
+ +.1 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 3100}], msg_flags=0}, MSG_MORE) = 3100
+ +0 > . 801:3801(3000) ack 1
++.003 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 50}], msg_flags=0}, MSG_MORE) = 50
+
+ +.01 < . 1:1(0) ack 2801 win 257
+// Err... we relase the remaining right after the ACK? note that PUSH is reset
+ +0 > . 3801:3951(150) ack 1
+
+// Test we'll hold on the subsequent writes when inflight (3801:3951) > 0
++.001 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 1}], msg_flags=0}, MSG_MORE) = 1
++.002 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 2}], msg_flags=0}, MSG_MORE) = 2
++.003 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 3}], msg_flags=0}, MSG_MORE) = 3
++.004 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 4}], msg_flags=0}, MSG_MORE) = 4
+ +.02 < . 1:1(0) ack 3951 win 257
+ +0 > . 3951:3961(10) ack 1
+ +.02 < . 1:1(0) ack 3961 win 257
+
+
+// Test the case a MSG_MORE send followed by a write flushes the data
+ +0 sendmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{..., 20}], msg_flags=0}, MSG_MORE) = 20
+ +.05 write(4, ..., 20) = 20
+ +0 > P. 3961:4001(40) ack 1
diff --git a/tools/testing/selftests/net/packetdrill/tcp_nagle_sockopt_cork_nodelay.pkt b/tools/testing/selftests/net/packetdrill/tcp_nagle_sockopt_cork_nodelay.pkt
new file mode 100644
index 000000000000..0ddec5f7dc1a
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_nagle_sockopt_cork_nodelay.pkt
@@ -0,0 +1,43 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test TCP_CORK and TCP_NODELAY sockopt behavior
+`./defaults.sh`
+
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+ +.01 < . 1:1(0) ack 1 win 257
+ +0 accept(3, ..., ...) = 4
+// Set TCP_CORK sockopt to hold small packets
+ +0 setsockopt(4, SOL_TCP, TCP_CORK, [1], 4) = 0
+
+ +0 write(4, ..., 40) = 40
+ +.05 write(4, ..., 40) = 40
+
+// Unset TCP_CORK should push pending bytes out
+ +.01 setsockopt(4, SOL_TCP, TCP_CORK, [0], 4) = 0
+ +0 > P. 1:81(80) ack 1
+ +.01 < . 1:1(0) ack 81 win 257
+
+// Set TCP_CORK sockopt to hold small packets
+ +0 setsockopt(4, SOL_TCP, TCP_CORK, [1], 4) = 0
+
+ +0 write(4, ..., 40) = 40
+ +.05 write(4, ..., 40) = 40
+
+// Set TCP_NODELAY sockopt should push pending bytes out
+ +0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
+ +0 > P. 81:161(80) ack 1
+ +.01 < . 1:1(0) ack 161 win 257
+
+// Set MSG_MORE to hold small packets
+ +0 send(4, ..., 40, MSG_MORE) = 40
+ +.05 send(4, ..., 40, MSG_MORE) = 40
+
+// Set TCP_NODELAY sockopt should push pending bytes out
+ +.01 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
+ +0 > . 161:241(80) ack 1
+ +.01 < . 1:1(0) ack 241 win 257
diff --git a/tools/testing/selftests/net/packetdrill/tcp_sack_sack-route-refresh-ip-tos.pkt b/tools/testing/selftests/net/packetdrill/tcp_sack_sack-route-refresh-ip-tos.pkt
new file mode 100644
index 000000000000..310ef31518da
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_sack_sack-route-refresh-ip-tos.pkt
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+// Verify that setsockopt calls that force a route refresh do not
+// cause problems matching SACKs with packets in the write queue.
+// This variant tests IP_TOS.
+
+`./defaults.sh`
+
+// Establish a connection.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_IP, IP_MTU_DISCOVER, [IP_PMTUDISC_DONT], 1) = 0
+ +0...0.010 connect(3, ..., ...) = 0
+
+ +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+ +.01 < S. 0:0(0) ack 1 win 65535 <mss 1460,nop,wscale 2,nop,nop,sackOK>
+ +0 > . 1:1(0) ack 1
+
+ +.01 write(3, ..., 5840) = 5840
+ +0 > P. 1:5841(5840) ack 1
+ +.01 < . 1:1(0) ack 5841 win 65535
+
+ +.01 write(3, ..., 5840) = 5840
+ +0 > P. 5841:11681(5840) ack 1
+ +.01 < . 1:1(0) ack 11681 win 65535
+
+ +.01 write(3, ..., 14600) = 14600
+ +0 > P. 11681:26281(14600) ack 1
+
+// Try the socket option that we know can force a route refresh.
+ +0 setsockopt(3, SOL_IP, IP_TOS, [4], 1) = 0
+// Then revert to avoid routing/mangling/etc implications of that setting.
+ +0 setsockopt(3, SOL_IP, IP_TOS, [0], 1) = 0
+
+// Verify that we do not retransmit the SACKed segments.
+ +.01 < . 1:1(0) ack 13141 win 65535 <sack 16061:17521 20441:26281,nop,nop>
+ +0 > . 13141:16061(2920) ack 1
+ +0 > P. 17521:20441(2920) ack 1
+ +.01 < . 1:1(0) ack 26281 win 65535
diff --git a/tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-2-6-8-3-9-nofack.pkt b/tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-2-6-8-3-9-nofack.pkt
new file mode 100644
index 000000000000..f185e1ac57ea
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-2-6-8-3-9-nofack.pkt
@@ -0,0 +1,64 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test shifting of newly-SACKed ranges onto the previous already-SACKed skb.
+// This variant tests non-FACK SACK with SACKs coming in the order
+// 2 6 8 3 9, to test what happens when we get a new SACKed range
+// (for packet 3) that is on the right of an existing SACKed range
+// (for packet 2).
+
+`./defaults.sh`
+
+// Establish a connection and send 10 MSS.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.1 < . 1:1(0) ack 1 win 1024
+ +0 accept(3, ..., ...) = 4
+
+ +0 write(4, ..., 10000) = 10000
+ +0 > P. 1:10001(10000) ack 1
+
+ +.1 < . 1:1(0) ack 1 win 257 <sack 2001:3001,nop,nop>
++.001 < . 1:1(0) ack 1 win 257 <sack 2001:3001 6001:7001,nop,nop>
++.001 < . 1:1(0) ack 1 win 257 <sack 2001:3001 6001:7001 8001:9001,nop,nop>
+
+// 3 SACKed packets, so we enter Fast Recovery.
+ +0 > . 1:1001(1000) ack 1
+ +0 %{ assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state }%
+ +0 %{ assert tcpi_lost == 6, tcpi_lost }%
+
+// SACK for 3001:4001.
+// This SACK for an adjacent range causes the sender to
+// shift the newly-SACKed range onto the previous skb.
++.007 < . 1:1(0) ack 1 win 257 <sack 2001:4001 6001:7001 8001:9001,nop,nop>
+ +0 > . 1001:2001(1000) ack 1
+ +0 %{ assert tcpi_lost == 5, tcpi_lost }%
+ +0 %{ assert tcpi_reordering == 6, tcpi_reordering }% // 8001:9001 -> 3001:4001 is 6
+
+// SACK for 9001:10001.
+ +.01 < . 1:1(0) ack 1 win 257 <sack 2001:4001 6001:7001 8001:10001,nop,nop>
+ +0 %{ assert tcpi_lost == 5, tcpi_lost }%
+
+// ACK for 1:1001 as packets from t=0.303 arrive.
++.083 < . 1:1(0) ack 1001 win 257 <sack 2001:4001 6001:7001 8001:10001,nop,nop>
+ +0 %{ assert tcpi_lost == 4,tcpi_lost }%
+
+// ACK for 1:4001 as packets from t=0.310 arrive.
++.017 < . 1:1(0) ack 4001 win 257 <sack 6001:7001 8001:10001,nop,nop>
+ +0 %{ assert tcpi_lost == 3,tcpi_lost }%
+
+// ACK for 1:7001 as packets from t=0.320 arrive.
+ +.01 < . 1:1(0) ack 7001 win 257 <sack 8001:10001,nop,nop>
+
+// ACK for all data as packets from t=0.403 arrive.
+ +.1 < . 1:1(0) ack 10001 win 257
+ +0 %{
+assert tcpi_ca_state == TCP_CA_Open, tcpi_ca_state
+assert tcpi_unacked == 0, tcpi_unacked
+assert tcpi_sacked == 0, tcpi_sacked
+assert tcpi_lost == 0, tcpi_lost
+assert tcpi_retrans == 0, tcpi_retrans
+}%
diff --git a/tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-7-3-4-8-9-fack.pkt b/tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-7-3-4-8-9-fack.pkt
new file mode 100644
index 000000000000..0093b4973934
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-7-3-4-8-9-fack.pkt
@@ -0,0 +1,66 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test shifting of newly-SACKed ranges onto the previous already-SACKed skb.
+// This variant tests the case where we mark packets 0-4 lost, then
+// get a SACK for 3, and then a SACK for 4.
+
+`./defaults.sh`
+
+// Establish a connection and send 10 MSS.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.1 < . 1:1(0) ack 1 win 1024
+ +0 accept(3, ..., ...) = 4
+
+ +0 write(4, ..., 10000) = 10000
+ +0 > P. 1:10001(10000) ack 1
+
+// SACK for 7001:8001. Using RACK we delay the fast retransmit.
+ +.1 < . 1:1(0) ack 1 win 257 <sack 7001:8001,nop,nop>
+// RACK reordering timer
++.027 > . 1:1001(1000) ack 1
+ +0 %{
+assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state
+assert tcpi_lost == 7, tcpi_lost # RACK thinks 1:7001 are lost
+assert tcpi_reordering == 3, tcpi_reordering
+}%
+
+// SACK for 3001:4001.
++.002 < . 1:1(0) ack 1 win 257 <sack 3001:4001 7001:8001,nop,nop>
+ +0 > . 1001:2001(1000) ack 1
+ +0 %{
+assert tcpi_lost == 6, tcpi_lost # since 3001:4001 is no longer lost
+assert tcpi_reordering == 5, tcpi_reordering # 7001:8001 -> 3001:4001
+}%
+
+// SACK for 4001:5001.
+// This SACK for an adjacent range causes the sender to
+// shift the newly-SACKed range onto the previous skb.
+// It uses the RFC3517 algorithm to mark 1:3001 lost
+// because >=3 higher-sequence packets are SACKed.
++.002 < . 1:1(0) ack 1 win 257 <sack 3001:5001 7001:8001,nop,nop>
+ +0 > . 2001:3001(1000) ack 1
+ +0 %{
+assert tcpi_lost == 5,tcpi_lost # SACK/RFC3517 thinks 1:3001 are lost
+}%
+
+// SACK for 8001:9001.
++.002 < . 1:1(0) ack 1 win 257 <sack 3001:5001 7001:9001,nop,nop>
+
+// SACK for 9001:10001.
++.002 < . 1:1(0) ack 1 win 257 <sack 3001:5001 7001:10001,nop,nop>
+ +0 > . 5001:6001(1000) ack 1
+
+// To simplify clean-up, say we get an ACK for all data.
+ +.1 < . 1:1(0) ack 10001 win 257
+ +0 %{
+assert tcpi_ca_state == TCP_CA_Open, tcpi_ca_state
+assert tcpi_unacked == 0, tcpi_unacked
+assert tcpi_sacked == 0, tcpi_sacked
+assert tcpi_lost == 0, tcpi_lost
+assert tcpi_retrans == 0, tcpi_retrans
+}%
diff --git a/tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-7-5-6-8-9-fack.pkt b/tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-7-5-6-8-9-fack.pkt
new file mode 100644
index 000000000000..980a832dc81c
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_sack_sack-shift-sacked-7-5-6-8-9-fack.pkt
@@ -0,0 +1,62 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test shifting of newly-SACKed ranges onto the previous already-SACKed skb.
+// This variant tests the case where we mark packets 0-4 lost, then
+// get a SACK for 5, and then a SACK for 6.
+
+`./defaults.sh`
+
+// Establish a connection and send 10 MSS.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.1 < . 1:1(0) ack 1 win 1024
+ +0 accept(3, ..., ...) = 4
+
+ +0 write(4, ..., 10000) = 10000
+ +0 > P. 1:10001(10000) ack 1
+
+// SACK for 7001:8001. Using RACK we delay a fast retransmit.
+ +.1 < . 1:1(0) ack 1 win 257 <sack 7001:8001,nop,nop>
++.027 > . 1:1001(1000) ack 1
+ +0 %{
+assert tcpi_ca_state == TCP_CA_Recovery, tcpi_ca_state
+assert tcpi_lost == 7,tcpi_lost # RACK thinks 1:7001 are lost
+assert tcpi_reordering == 3, tcpi_reordering
+}%
+
+// SACK for 5001:6001.
+ +0 < . 1:1(0) ack 1 win 257 <sack 5001:6001 7001:8001,nop,nop>
+ +0 > . 1001:2001(1000) ack 1
+ +0 %{
+assert tcpi_lost == 6, tcpi_lost
+assert tcpi_reordering == 3, tcpi_reordering # 7001:8001 -> 5001:6001 is 3
+}%
+
+// SACK for 6001:7001.
+// This SACK for an adjacent range causes the sender to
+// shift the newly-SACKed range onto the previous skb.
+ +0 < . 1:1(0) ack 1 win 257 <sack 5001:8001,nop,nop>
+ +0 > . 2001:3001(1000) ack 1
+ +0 %{ assert tcpi_lost == 5, tcpi_lost }%
+
+// SACK for 8001:9001.
+ +0 < . 1:1(0) ack 1 win 257 <sack 5001:9001,nop,nop>
+ +0 > . 3001:4001(1000) ack 1
+
+// SACK for 9001:10001.
+ +0 < . 1:1(0) ack 1 win 257 <sack 5001:10001,nop,nop>
+ +0 > . 4001:5001(1000) ack 1
+
+// To simplify clean-up, say we get an ACK for all data.
+ +.1 < . 1:1(0) ack 10001 win 257
+ +0 %{
+assert tcpi_ca_state == TCP_CA_Open, tcpi_ca_state
+assert tcpi_unacked == 0, tcpi_unacked
+assert tcpi_sacked == 0, tcpi_sacked
+assert tcpi_lost == 0, tcpi_lost
+assert tcpi_retrans == 0, tcpi_retrans
+}%
diff --git a/tools/testing/selftests/net/packetdrill/tcp_sendfile_sendfile-simple.pkt b/tools/testing/selftests/net/packetdrill/tcp_sendfile_sendfile-simple.pkt
new file mode 100644
index 000000000000..6740859a1360
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_sendfile_sendfile-simple.pkt
@@ -0,0 +1,26 @@
+// SPDX-License-Identifier: GPL-2.0
+// Simplest possible test of open() and then sendfile().
+// We write some zeroes into a file (since packetdrill expects payloads
+// to be all zeroes) and then open() the file, then use sendfile()
+// and verify that the correct number of zeroes goes out.
+
+`./defaults.sh
+/bin/rm -f /tmp/testfile
+/bin/dd bs=1 count=5 if=/dev/zero of=/tmp/testfile status=none
+`
+
+// Initialize connection
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +0 < . 1:1(0) ack 1 win 514
+
+ +0 accept(3, ..., ...) = 4
+
+ +0 open("/tmp/testfile", O_RDONLY) = 5
+ +0 sendfile(4, 5, [0], 5) = 5
+ +0 > P. 1:6(5) ack 1
diff --git a/tools/testing/selftests/net/packetdrill/tcp_splice_tcp_splice_loop_test.pkt b/tools/testing/selftests/net/packetdrill/tcp_splice_tcp_splice_loop_test.pkt
new file mode 100644
index 000000000000..0cbd43253236
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_splice_tcp_splice_loop_test.pkt
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+`./defaults.sh`
+
+// Initialize a server socket
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 setsockopt(3, SOL_IP, IP_FREEBIND, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+// Connection should get accepted
+ +0 < S 0:0(0) win 32972 <mss 1460,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <...>
+ +0 < . 1:1(0) ack 1 win 257
+ +0 accept(3, ..., ...) = 4
+
+ +0 pipe([5, 6]) = 0
+ +0 < U. 1:101(100) ack 1 win 257 urg 100
+ +0 splice(4, NULL, 6, NULL, 99, 0) = 99
+ +0 splice(4, NULL, 6, NULL, 1, 0) = 0
diff --git a/tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_fastopen-invalid-buf-ptr.pkt b/tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_fastopen-invalid-buf-ptr.pkt
new file mode 100644
index 000000000000..8940726a3ec2
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_fastopen-invalid-buf-ptr.pkt
@@ -0,0 +1,42 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test TCP fastopen behavior with NULL as buffer pointer, but a non-zero
+// buffer length.
+`./defaults.sh
+./set_sysctls.py /proc/sys/net/ipv4/tcp_timestamps=0`
+
+// Cache warmup: send a Fast Open cookie request
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
++0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
++0 setsockopt(3, SOL_TCP, TCP_FASTOPEN_CONNECT, [1], 4) = 0
++0 connect(3, ..., ...) = -1 EINPROGRESS (Operation is now in progress)
++0 > S 0:0(0) <mss 1460,nop,nop,sackOK,nop,wscale 8,FO,nop,nop>
++0 < S. 123:123(0) ack 1 win 14600 <mss 1460,nop,nop,sackOK,nop,wscale 6,FO abcd1234,nop,nop>
++0 > . 1:1(0) ack 1
++0 close(3) = 0
++0 > F. 1:1(0) ack 1
++0 < F. 1:1(0) ack 2 win 92
++0 > . 2:2(0) ack 2
+
+// Test with MSG_FASTOPEN without TCP_FASTOPEN_CONNECT.
++0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 4
++0 fcntl(4, F_SETFL, O_RDWR|O_NONBLOCK) = 0
++0 sendto(4, NULL, 1, MSG_FASTOPEN, ..., ...) = -1
++0 close(4) = 0
+
+// Test with TCP_FASTOPEN_CONNECT without MSG_FASTOPEN.
++0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 5
++0 fcntl(5, F_SETFL, O_RDWR|O_NONBLOCK) = 0
++0 setsockopt(5, SOL_TCP, TCP_FASTOPEN_CONNECT, [1], 4) = 0
++0 connect(5, ..., ...) = 0
++0 sendto(5, NULL, 1, 0, ..., ...) = -1
++0 close(5) = 0
+
+// Test with both TCP_FASTOPEN_CONNECT and MSG_FASTOPEN.
++0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 6
++0 fcntl(6, F_SETFL, O_RDWR|O_NONBLOCK) = 0
++0 setsockopt(6, SOL_TCP, TCP_FASTOPEN_CONNECT, [1], 4) = 0
++0 connect(6, ..., ...) = 0
++0 sendto(6, NULL, 1, MSG_FASTOPEN, ..., ...) = -1
++0 close(6) = 0
+
+`/tmp/sysctl_restore_${PPID}.sh`
diff --git a/tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_sendmsg-empty-iov.pkt b/tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_sendmsg-empty-iov.pkt
new file mode 100644
index 000000000000..b2b2cdf27e20
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_sendmsg-empty-iov.pkt
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test that we correctly skip zero-length IOVs.
+`./defaults.sh`
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_ZEROCOPY, [1], 4) = 0
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,nop,wscale 7>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,wscale 8>
+ +.01 < . 1:1(0) ack 1 win 257
+ +0 accept(3, ..., ...) = 4
+ +0 setsockopt(4, SOL_TCP, TCP_NODELAY, [1], 4) = 0
+
+ +0 sendmsg(4, {msg_name(...)=...,
+ msg_iov(4)=[{..., 0}, {..., 40}, {..., 0}, {..., 20}],
+ msg_flags=0}, 0) = 60
+ +0 > P. 1:61(60) ack 1
+ +.01 < . 1:1(0) ack 61 win 257
+
+ +0 sendmsg(4, {msg_name(...)=...,
+ msg_iov(4)=[{..., 0}, {..., 0}, {..., 0}, {..., 0}],
+ msg_flags=0}, MSG_ZEROCOPY) = 0
+
+ +0 sendmsg(4, {msg_name(...)=...,
+ msg_iov(4)=[{..., 0}, {..., 10}, {..., 0}, {..., 50}],
+ msg_flags=0}, MSG_ZEROCOPY) = 60
+ +0 > P. 61:121(60) ack 1
+ +.01 < . 1:1(0) ack 121 win 257
diff --git a/tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_syscall-invalid-buf-ptr.pkt b/tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_syscall-invalid-buf-ptr.pkt
new file mode 100644
index 000000000000..59f5903f285c
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_syscall_bad_arg_syscall-invalid-buf-ptr.pkt
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test kernel behavior with NULL as buffer pointer
+
+`./defaults.sh`
+
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.2 < . 1:1(0) ack 1 win 514
+
+ +0 accept(3, ..., ...) = 4
+
+ +0 write(4, NULL, 1000) = -1 EFAULT (Bad address)
+ +0 send(4, NULL, 1000, 0) = -1 EFAULT (Bad address)
+ +0 sendto(4, NULL, 1000, 0, ..., ...) = -1 EFAULT (Bad address)
+
+ +0 < . 1:1001(1000) ack 1 win 200
+ +0 read(4, NULL, 1000) = -1 EFAULT (Bad address)
+ +0 recv(4, NULL, 1000, 0) = -1 EFAULT (Bad address)
+ +0 recvfrom(4, NULL, 1000, 0, ..., ...) = -1 EFAULT (Bad address)
diff --git a/tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-last_data_recv.pkt b/tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-last_data_recv.pkt
new file mode 100644
index 000000000000..d7fdb43a8e89
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-last_data_recv.pkt
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test tcpi_last_data_recv for active session
+`./defaults.sh`
+
+// Create a socket and set it to non-blocking.
++0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
++0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
++0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+
++0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
++0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
++.030 < S. 0:0(0) ack 1 win 10000 <mss 1000,sackOK,nop,nop,nop,wscale 8>
++0 > . 1:1(0) ack 1
+
++1 %{ assert 990 <= tcpi_last_data_recv <= 1010, tcpi_last_data_recv }%
+
++0 < . 1:1001(1000) ack 1 win 300
++0 > . 1:1(0) ack 1001
+
++0 %{ assert tcpi_last_data_recv <= 10, tcpi_last_data_recv }%
diff --git a/tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-rwnd-limited.pkt b/tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-rwnd-limited.pkt
new file mode 100644
index 000000000000..a9bcd46f6cb6
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-rwnd-limited.pkt
@@ -0,0 +1,54 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test rwnd limited time in tcp_info for client side.
+
+`./defaults.sh`
+
+// Create a socket and set it to non-blocking.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
+ +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+
+ +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+ +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+
+// Server advertises 0 receive window.
+ +.01 < S. 0:0(0) ack 1 win 0 <mss 1000,nop,nop,sackOK>
+
+ +0 > . 1:1(0) ack 1
+ +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
+ +0 fcntl(3, F_SETFL, O_RDWR) = 0 // set back to blocking
+
+// Make sure that initial rwnd limited time is 0.
+ +0 %{ assert tcpi_rwnd_limited == 0, tcpi_rwnd_limited }%
+
+// Receive window limited time starts here.
+ +0 write(3, ..., 1000) = 1000
+
+// Check that rwnd limited time in tcp_info is around 0.1s.
+ +.1 %{ assert 98000 <= tcpi_rwnd_limited <= 110000, tcpi_rwnd_limited }%
+
+// Server opens the receive window.
+ +.1 < . 1:1(0) ack 1 win 2000
+
+// Check that rwnd limited time in tcp_info is around 0.2s.
+ +0 %{ assert 198000 <= tcpi_rwnd_limited <= 210000, tcpi_rwnd_limited }%
+
+ +0 > P. 1:1001(1000) ack 1
+
+// Server advertises a very small receive window.
+ +.03 < . 1:1(0) ack 1001 win 10
+
+// Receive window limited time starts again.
+ +0 write(3, ..., 1000) = 1000
+
+// Server opens the receive window again.
+ +.1 < . 1:1(0) ack 1001 win 2000
+// Check that rwnd limited time in tcp_info is around 0.3s
+// and busy time is 0.3 + 0.03 (server opened small window temporarily).
+ +0 %{ assert 298000 <= tcpi_rwnd_limited <= 310000, tcpi_rwnd_limited;\
+ assert 328000 <= tcpi_busy_time <= 340000, tcpi_busy_time;\
+}%
+
+ +0 > P. 1001:2001(1000) ack 1
+ +.02 < . 1:1(0) ack 2001 win 2000
+ +0 %{ assert 348000 <= tcpi_busy_time <= 360000, tcpi_busy_time }%
diff --git a/tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-sndbuf-limited.pkt b/tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-sndbuf-limited.pkt
new file mode 100644
index 000000000000..f0de2acd0f8e
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_tcp_info_tcp-info-sndbuf-limited.pkt
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test send-buffer-limited time in tcp_info for client side.
+`./defaults.sh`
+
+// Create a socket and set it to non-blocking.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
+ +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+
+ +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+ +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+ +.01 < S. 0:0(0) ack 1 win 10000 <mss 1000,sackOK,nop,nop,nop,wscale 8>
+ +0 > . 1:1(0) ack 1
+ +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
+ +0 fcntl(3, F_SETFL, O_RDWR) = 0 // set back to blocking
+ +0 setsockopt(3, SOL_SOCKET, SO_SNDBUF, [10000], 4) = 0
+ +0 getsockopt(3, SOL_SOCKET, SO_SNDBUF, [20000], [4]) = 0
+
+ +.09...0.14 write(3, ..., 150000) = 150000
+
+ +.01 < . 1:1(0) ack 10001 win 10000
+
+ +.01 < . 1:1(0) ack 30001 win 10000
+
+// cwnd goes from 40(60KB) to 80(120KB), and that we hit the tiny sndbuf limit 10KB
+ +.01 < . 1:1(0) ack 70001 win 10000
+
+ +.02 < . 1:1(0) ack 95001 win 10000
+ +0 %{ assert 19000 <= tcpi_sndbuf_limited <= 21000, tcpi_sndbuf_limited; \
+ assert 49000 <= tcpi_busy_time <= 52000, tcpi_busy_time; \
+ assert 0 == tcpi_rwnd_limited, tcpi_rwnd_limited }%
+
+// This ack frees up enough buffer so we are no longer
+// buffer limited (socket flag SOCK_NOSPACE is cleared)
+ +.02 < . 1:1(0) ack 150001 win 10000
+ +0 %{ assert 19000 <= tcpi_sndbuf_limited <= 21000, tcpi_sndbuf_limited;\
+ assert 69000 <= tcpi_busy_time <= 73000, tcpi_busy_time;\
+ assert 0 == tcpi_rwnd_limited, tcpi_rwnd_limited }%
diff --git a/tools/testing/selftests/net/packetdrill/tcp_timestamping_client-only-last-byte.pkt b/tools/testing/selftests/net/packetdrill/tcp_timestamping_client-only-last-byte.pkt
new file mode 100644
index 000000000000..2087ec0c746a
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_timestamping_client-only-last-byte.pkt
@@ -0,0 +1,92 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test that tx timestamping sends timestamps only for
+// the last byte of each sendmsg.
+`./defaults.sh
+`
+
+// Create a socket and set it to non-blocking.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
+ +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+
+// Establish connection and verify that there was no error.
+ +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+ +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+ +.01 < S. 0:0(0) ack 1 win 20000 <mss 1000,nop,nop,sackOK>
+ +0 > . 1:1(0) ack 1
+ +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
+ +0 fcntl(3, F_SETFL, O_RDWR) = 0 // set back to blocking
+
+ +0 setsockopt(3, SOL_SOCKET, SO_TIMESTAMPING,
+ [SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_TX_ACK | SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_OPT_ID], 4) = 0
+
+ +0 write(3, ..., 11000) = 11000
+ +0 > P. 1:10001(10000) ack 1
+ +.01 < . 1:1(0) ack 10001 win 4000
+ +0 > P. 10001:11001(1000) ack 1
+ +.01 < . 1:1(0) ack 11001 win 4000
+
+// Make sure that internal TCP timestamps are not overwritten and we have sane
+// RTT measurement.
+ +0 %{
+assert 5000 <= tcpi_rtt <= 20000, 'srtt=%d us' % tcpi_rtt
+}%
+
+// SCM_TSTAMP_SCHED for the last byte should be received almost immediately
+// once 10001 is acked at t=20ms.
+// setsockopt(..., [SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_OPT_ID], ...)
+// is called after when SYN is acked. So, we expect the last byte of the first
+// chunk to have a timestamp key of 10999 (i.e., 11000 - 1).
+ +0 recvmsg(3, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=20000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_SCHED,
+ ee_data=10999}}
+ ]}, MSG_ERRQUEUE) = 0
+// SCM_TSTAMP_SND for the last byte should be received almost immediately
+// once 10001 is acked at t=20ms.
+ +0 recvmsg(3, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=20000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_SND,
+ ee_data=10999}}
+ ]}, MSG_ERRQUEUE) = 0
+// SCM_TSTAMP_ACK for the last byte should be received at t=30ms.
+ +0 recvmsg(3, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=30000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_ACK,
+ ee_data=10999}}
+ ]}, MSG_ERRQUEUE) = 0
diff --git a/tools/testing/selftests/net/packetdrill/tcp_timestamping_partial.pkt b/tools/testing/selftests/net/packetdrill/tcp_timestamping_partial.pkt
new file mode 100644
index 000000000000..876024a31110
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_timestamping_partial.pkt
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test tx timestamping for partial writes (IPv4).
+`./defaults.sh
+`
+
+// Create a socket and set it to non-blocking.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 fcntl(3, F_GETFL) = 0x2 (flags O_RDWR)
+ +0 fcntl(3, F_SETFL, O_RDWR|O_NONBLOCK) = 0
+
+// Establish connection and verify that there was no error.
+ +0 connect(3, ..., ...) = -1 EINPROGRESS (Operation now in progress)
+ +0 > S 0:0(0) <mss 1460,sackOK,TS val 100 ecr 0,nop,wscale 8>
+ +.01 < S. 0:0(0) ack 1 win 2000 <mss 1000,sackOK,TS val 700 ecr 100,nop,wscale 7>
+ +0 > . 1:1(0) ack 1 <nop,nop,TS val 200 ecr 700>
+ +0 getsockopt(3, SOL_SOCKET, SO_ERROR, [0], [4]) = 0
+
+ +0 setsockopt(3, SOL_SOCKET, SO_SNDBUF, [1000], 4) = 0
+ +0 setsockopt(3, SOL_SOCKET, SO_TIMESTAMPING,
+ [SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_TX_ACK | SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_OPT_ID], 4) = 0
+
+// We have a partial write.
+ +0 write(3, ..., 10000) = 2964
+ +0 > . 1:989(988) ack 1 <nop,nop,TS val 110 ecr 700>
+ +0 > P. 989:1977(988) ack 1 <nop,nop,TS val 110 ecr 700>
+ +.01 < . 1:1(0) ack 1977 win 92 <nop,nop,TS val 800 ecr 200>
+ +0 > P. 1977:2965(988) ack 1 <nop,nop,TS val 114 ecr 800>
+ +.01 < . 1:1(0) ack 2965 win 92 <nop,nop,TS val 800 ecr 200>
+
+// Make sure that internal TCP timestamps are not overwritten and we have sane
+// RTT measurement.
+ +0 %{
+assert 5000 <= tcpi_rtt <= 20000, 'srtt=%d us' % tcpi_rtt
+}%
+
+// SCM_TSTAMP_SCHED for the first chunk should be received almost immediately
+// after the first ack at t=20ms.
+ +0 recvmsg(3, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=20000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_SCHED,
+ ee_data=2963}}
+ ]}, MSG_ERRQUEUE) = 0
+// SCM_TSTAMP_SND for the first chunk should be received almost immediately
+// after the first ack at t=20ms.
+ +0 recvmsg(3, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=20000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_SND,
+ ee_data=2963}}
+ ]}, MSG_ERRQUEUE) = 0
+// SCM_TSTAMP_ACK for the first chunk should be received after the last ack at
+// t=30ms.
+ +0 recvmsg(3, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=30000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_ACK,
+ ee_data=2963}}
+ ]}, MSG_ERRQUEUE) = 0
diff --git a/tools/testing/selftests/net/packetdrill/tcp_timestamping_server.pkt b/tools/testing/selftests/net/packetdrill/tcp_timestamping_server.pkt
new file mode 100644
index 000000000000..84d94780e6be
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_timestamping_server.pkt
@@ -0,0 +1,145 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test tx timestamping for server-side (IPv4).
+`./defaults.sh
+`
+
+// Initialize connection
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop,nop,wscale 10>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK,nop,wscale 8>
+ +.01 < . 1:1(0) ack 1 win 514
+
+ +0 accept(3, ..., ...) = 4
+ +0 setsockopt(4, SOL_SOCKET, SO_TIMESTAMPING,
+ [SOF_TIMESTAMPING_TX_SCHED | SOF_TIMESTAMPING_TX_SOFTWARE |
+ SOF_TIMESTAMPING_TX_ACK | SOF_TIMESTAMPING_SOFTWARE |
+ SOF_TIMESTAMPING_OPT_ID], 4) = 0
+
+// Write two 2KB chunks.
+// setsockopt(..., [SOF_TIMESTAMPING_SOFTWARE | SOF_TIMESTAMPING_OPT_ID], ...)
+// is called after when SYN is acked. So, we expect the last byte of the first
+// and the second chunks to have timestamp keys of 1999 (i.e., 2000 - 1) and
+// 3999 (i.e., 4000 - 1) respectively.
+ +0 write(4, ..., 2000) = 2000
+ +0 write(4, ..., 2000) = 2000
+ +0 > P. 1:2001(2000) ack 1
+ +0 > P. 2001:4001(2000) ack 1
+ +.01 < . 1:1(0) ack 2001 win 514
+ +.01 < . 1:1(0) ack 4001 win 514
+
+// Make sure that internal TCP timestamps are not overwritten and we have sane
+// RTT measurement.
+ +0 %{
+assert 5000 <= tcpi_rtt <= 20000, 'srtt=%d us' % tcpi_rtt
+}%
+
+// SCM_TSTAMP_SCHED for the first chunk should be received almost immediately
+// after write at t=10ms.
+ +0 recvmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=10000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_SCHED,
+ ee_data=1999}}
+ ]}, MSG_ERRQUEUE) = 0
+// SCM_TSTAMP_SND for the first chunk should be received almost immediately
+// after write at t=10ms.
+ +0 recvmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=10000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_SND,
+ ee_data=1999}}
+ ]}, MSG_ERRQUEUE) = 0
+// SCM_TSTAMP_SCHED for the second chunk should be received almost immediately
+// after that at t=10ms.
+ +0 recvmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=10000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_SCHED,
+ ee_data=3999}}
+ ]}, MSG_ERRQUEUE) = 0
+// SCM_TSTAMP_SND for the second chunk should be received almost immediately
+// after that at t=10ms.
+ +0 recvmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=10000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_SND,
+ ee_data=3999}}
+ ]}, MSG_ERRQUEUE) = 0
+// SCM_TSTAMP_ACK for the first chunk should be received at t=20ms.
+ +0 recvmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=20000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_ACK,
+ ee_data=1999}}
+ ]}, MSG_ERRQUEUE) = 0
+// SCM_TSTAMP_ACK for the second chunk should be received at t=30ms.
+ +0 recvmsg(4, {msg_name(...)=...,
+ msg_iov(1)=[{...,0}],
+ msg_flags=MSG_ERRQUEUE|MSG_TRUNC,
+ msg_control=[
+ {cmsg_level=SOL_SOCKET,
+ cmsg_type=SCM_TIMESTAMPING,
+ cmsg_data={scm_sec=0,scm_nsec=30000000}},
+ {cmsg_level=CMSG_LEVEL_IP,
+ cmsg_type=CMSG_TYPE_RECVERR,
+ cmsg_data={ee_errno=ENOMSG,
+ ee_origin=SO_EE_ORIGIN_TIMESTAMPING,
+ ee_type=0,
+ ee_code=0,
+ ee_info=SCM_TSTAMP_ACK,
+ ee_data=3999}}
+ ]}, MSG_ERRQUEUE) = 0
diff --git a/tools/testing/selftests/net/packetdrill/tcp_ts_recent_fin_tsval.pkt b/tools/testing/selftests/net/packetdrill/tcp_ts_recent_fin_tsval.pkt
new file mode 100644
index 000000000000..e61424a7bd0a
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_ts_recent_fin_tsval.pkt
@@ -0,0 +1,23 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test that we send FIN packet with correct TSval
+--tcp_ts_tick_usecs=1000
+--tolerance_usecs=7000
+
+`./defaults.sh`
+
+// Create a socket.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+// Establish a connection.
+ +0 < S 0:0(0) win 20000 <mss 1000,sackOK,TS val 100 ecr 0>
+ +0 > S. 0:0(0) ack 1 <mss 1460,sackOK,TS val 100 ecr 100>
+ +.1 < . 1:1(0) ack 1 win 20000 <nop,nop,TS val 200 ecr 100>
+ +0 accept(3, ..., ...) = 4
+
+ +1 close(4) = 0
+// Check that FIN TSval is updated properly, one second has passed since last sent packet.
+ +0 > F. 1:1(0) ack 1 <nop,nop,TS val 1200 ecr 200>
diff --git a/tools/testing/selftests/net/packetdrill/tcp_ts_recent_invalid_ack.pkt b/tools/testing/selftests/net/packetdrill/tcp_ts_recent_invalid_ack.pkt
new file mode 100644
index 000000000000..174ce9a1bfc0
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_ts_recent_invalid_ack.pkt
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test that we reject TS val updates on a packet with invalid ACK sequence
+
+`./defaults.sh
+`
+
+// Create a socket.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+// Establish a connection.
+ +.1 < S 0:0(0) win 20000 <mss 1000,sackOK,TS val 100 ecr 0>
+ +0 > S. 0:0(0) ack 1 <mss 1460,sackOK,TS val 100 ecr 100>
+ +.1 < . 1:1(0) ack 1 win 20000 <nop,nop,TS val 200 ecr 100>
+ +0 accept(3, ..., ...) = 4
+
+// bad packet with high tsval (its ACK sequence is above our sndnxt)
+ +0 < F. 1:1(0) ack 9999 win 20000 <nop,nop,TS val 200000 ecr 100>
+
+
+ +0 < . 1:1001(1000) ack 1 win 20000 <nop,nop,TS val 201 ecr 100>
+ +0 > . 1:1(0) ack 1001 <nop,nop,TS val 200 ecr 201>
diff --git a/tools/testing/selftests/net/packetdrill/tcp_ts_recent_reset_tsval.pkt b/tools/testing/selftests/net/packetdrill/tcp_ts_recent_reset_tsval.pkt
new file mode 100644
index 000000000000..2e3b3bb7493a
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_ts_recent_reset_tsval.pkt
@@ -0,0 +1,25 @@
+// SPDX-License-Identifier: GPL-2.0
+// Test that we send RST packet with correct TSval
+--tcp_ts_tick_usecs=1000
+
+`./defaults.sh`
+
+// Create a socket.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+// Establish a connection.
+ +0 < S 0:0(0) win 20000 <mss 1000,sackOK,TS val 100 ecr 0>
+ +0 > S. 0:0(0) ack 1 <mss 1460,sackOK,TS val 100 ecr 100>
+ +.1 < . 1:1(0) ack 1 win 20000 <nop,nop,TS val 200 ecr 100>
+ +0 accept(3, ..., ...) = 4
+
+ +0 < . 1:1001(1000) ack 1 win 20000 <nop,nop,TS val 201 ecr 100>
+ +0 > . 1:1(0) ack 1001 <nop,nop,TS val 200 ecr 201>
+
+ +1 close(4) = 0
+// Check that RST TSval is updated properly, one second has passed since last sent packet.
+ +0 > R. 1:1(0) ack 1001 <nop,nop,TS val 1200 ecr 201>
diff --git a/tools/testing/selftests/net/packetdrill/tcp_user_timeout_user-timeout-probe.pkt b/tools/testing/selftests/net/packetdrill/tcp_user_timeout_user-timeout-probe.pkt
new file mode 100644
index 000000000000..183051ba0cae
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_user_timeout_user-timeout-probe.pkt
@@ -0,0 +1,37 @@
+// SPDX-License-Identifier: GPL-2.0
+
+`./defaults.sh`
+
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+
+ +0 < S 0:0(0) win 0 <mss 1460>
+ +0 > S. 0:0(0) ack 1 <mss 1460>
+
+ +.1 < . 1:1(0) ack 1 win 65530
+ +0 accept(3, ..., ...) = 4
+
+ +0 setsockopt(4, SOL_TCP, TCP_USER_TIMEOUT, [3000], 4) = 0
+ +0 write(4, ..., 24) = 24
+ +0 > P. 1:25(24) ack 1
+ +.1 < . 1:1(0) ack 25 win 65530
+ +0 %{ assert tcpi_probes == 0, tcpi_probes; \
+ assert tcpi_backoff == 0, tcpi_backoff }%
+
+// install a qdisc dropping all packets
+ +0 `tc qdisc delete dev tun0 root 2>/dev/null ; tc qdisc add dev tun0 root pfifo limit 0`
+ +0 write(4, ..., 24) = 24
+ // When qdisc is congested we retry every 500ms
+ // (TCP_RESOURCE_PROBE_INTERVAL) and therefore
+ // we retry 6 times before hitting 3s timeout.
+ // First verify that the connection is alive:
++3.250 write(4, ..., 24) = 24
+ // Now verify that shortly after that the socket is dead:
+ +.100 write(4, ..., 24) = -1 ETIMEDOUT (Connection timed out)
+
+ +0 %{ assert tcpi_probes == 6, tcpi_probes; \
+ assert tcpi_backoff == 0, tcpi_backoff }%
+ +0 close(4) = 0
diff --git a/tools/testing/selftests/net/packetdrill/tcp_user_timeout_user_timeout.pkt b/tools/testing/selftests/net/packetdrill/tcp_user_timeout_user_timeout.pkt
new file mode 100644
index 000000000000..2efe02bfba9c
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_user_timeout_user_timeout.pkt
@@ -0,0 +1,32 @@
+// SPDX-License-Identifier: GPL-2.0
+`./defaults.sh`
+
+// Initialize connection
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+ +0 < S 0:0(0) win 32792 <mss 1000,sackOK,nop,nop>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK>
+ +.1 < . 1:1(0) ack 1 win 32792
+
+
+ +0 accept(3, ..., ...) = 4
+
+// Okay, we received nothing, and decide to close this idle socket.
+// We set TCP_USER_TIMEOUT to 3 seconds because really it is not worth
+// trying hard to cleanly close this flow, at the price of keeping
+// a TCP structure in kernel for about 1 minute !
+ +2 setsockopt(4, SOL_TCP, TCP_USER_TIMEOUT, [3000], 4) = 0
+ +0 close(4) = 0
+
+ +0 > F. 1:1(0) ack 1
+ +.3~+.400 > F. 1:1(0) ack 1
+ +.3~+.400 > F. 1:1(0) ack 1
+ +.6~+.800 > F. 1:1(0) ack 1
+
+// We finally receive something from the peer, but it is way too late
+// Our socket vanished because TCP_USER_TIMEOUT was really small
+ +0 < . 1:2(1) ack 1 win 32792
+ +0 > R 1:1(0)
diff --git a/tools/testing/selftests/net/packetdrill/tcp_validate_validate-established-no-flags.pkt b/tools/testing/selftests/net/packetdrill/tcp_validate_validate-established-no-flags.pkt
new file mode 100644
index 000000000000..8bd60226ccfc
--- /dev/null
+++ b/tools/testing/selftests/net/packetdrill/tcp_validate_validate-established-no-flags.pkt
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+// Verify that established connections drop a segment without the ACK flag set.
+
+`./defaults.sh`
+
+// Create a socket.
+ 0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3
+ +0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0
+ +0 bind(3, ..., ...) = 0
+ +0 listen(3, 1) = 0
+
+// Establish a connection.
+ +0 < S 0:0(0) win 20000 <mss 1000,sackOK,nop,nop>
+ +0 > S. 0:0(0) ack 1 <mss 1460,nop,nop,sackOK>
+ +.01 < . 1:1(0) ack 1 win 20000
+ +0 accept(3, ..., ...) = 4
+
+// Receive a segment with no flags set, verify that it's not enqueued.
+ +.01 < - 1:1001(1000) win 20000
+ +0 ioctl(4, SIOCINQ, [0]) = 0
+
+// Receive a segment with ACK flag set, verify that it is enqueued.
+ +.01 < . 1:1001(1000) ack 1 win 20000
+ +0 ioctl(4, SIOCINQ, [1000]) = 0
diff --git a/tools/testing/selftests/net/tls.c b/tools/testing/selftests/net/tls.c
index 1a706d03bb6b..9a85f93c33d8 100644
--- a/tools/testing/selftests/net/tls.c
+++ b/tools/testing/selftests/net/tls.c
@@ -44,9 +44,11 @@ struct tls_crypto_info_keys {
};
static void tls_crypto_info_init(uint16_t tls_version, uint16_t cipher_type,
- struct tls_crypto_info_keys *tls12)
+ struct tls_crypto_info_keys *tls12,
+ char key_generation)
{
- memset(tls12, 0, sizeof(*tls12));
+ memset(tls12, key_generation, sizeof(*tls12));
+ memset(tls12, 0, sizeof(struct tls_crypto_info));
switch (cipher_type) {
case TLS_CIPHER_CHACHA20_POLY1305:
@@ -275,7 +277,7 @@ TEST_F(tls_basic, recseq_wrap)
if (self->notls)
SKIP(return, "no TLS support");
- tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_GCM_128, &tls12);
+ tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_GCM_128, &tls12, 0);
memset(&tls12.aes128.rec_seq, 0xff, sizeof(tls12.aes128.rec_seq));
ASSERT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0);
@@ -391,7 +393,7 @@ FIXTURE_SETUP(tls)
SKIP(return, "Unsupported cipher in FIPS mode");
tls_crypto_info_init(variant->tls_version, variant->cipher_type,
- &tls12);
+ &tls12, 0);
ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls);
@@ -1175,7 +1177,7 @@ TEST_F(tls, bidir)
struct tls_crypto_info_keys tls12;
tls_crypto_info_init(variant->tls_version, variant->cipher_type,
- &tls12);
+ &tls12, 0);
ret = setsockopt(self->fd, SOL_TLS, TLS_RX, &tls12,
tls12.len);
@@ -1614,7 +1616,7 @@ TEST_F(tls, getsockopt)
EXPECT_EQ(get.crypto_info.cipher_type, variant->cipher_type);
/* get the full crypto_info */
- tls_crypto_info_init(variant->tls_version, variant->cipher_type, &expect);
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &expect, 0);
len = expect.len;
memrnd(&get, sizeof(get));
EXPECT_EQ(getsockopt(self->fd, SOL_TLS, TLS_TX, &get, &len), 0);
@@ -1668,6 +1670,464 @@ TEST_F(tls, recv_efault)
EXPECT_EQ(memcmp(rec2, recv_mem + 9, ret - 9), 0);
}
+#define TLS_RECORD_TYPE_HANDSHAKE 0x16
+/* key_update, length 1, update_not_requested */
+static const char key_update_msg[] = "\x18\x00\x00\x01\x00";
+static void tls_send_keyupdate(struct __test_metadata *_metadata, int fd)
+{
+ size_t len = sizeof(key_update_msg);
+
+ EXPECT_EQ(tls_send_cmsg(fd, TLS_RECORD_TYPE_HANDSHAKE,
+ (char *)key_update_msg, len, 0),
+ len);
+}
+
+static void tls_recv_keyupdate(struct __test_metadata *_metadata, int fd, int flags)
+{
+ char buf[100];
+
+ EXPECT_EQ(tls_recv_cmsg(_metadata, fd, TLS_RECORD_TYPE_HANDSHAKE, buf, sizeof(buf), flags),
+ sizeof(key_update_msg));
+ EXPECT_EQ(memcmp(buf, key_update_msg, sizeof(key_update_msg)), 0);
+}
+
+/* set the key to 0 then 1 for RX, immediately to 1 for TX */
+TEST_F(tls_basic, rekey_rx)
+{
+ struct tls_crypto_info_keys tls12_0, tls12_1;
+ char const *test_str = "test_message";
+ int send_len = strlen(test_str) + 1;
+ char buf[20];
+ int ret;
+
+ if (self->notls)
+ return;
+
+ tls_crypto_info_init(TLS_1_3_VERSION, TLS_CIPHER_AES_GCM_128,
+ &tls12_0, 0);
+ tls_crypto_info_init(TLS_1_3_VERSION, TLS_CIPHER_AES_GCM_128,
+ &tls12_1, 1);
+
+ ret = setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12_1, tls12_1.len);
+ ASSERT_EQ(ret, 0);
+
+ ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12_0, tls12_0.len);
+ ASSERT_EQ(ret, 0);
+
+ ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12_1, tls12_1.len);
+ EXPECT_EQ(ret, 0);
+
+ EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+ EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len);
+ EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+}
+
+/* set the key to 0 then 1 for TX, immediately to 1 for RX */
+TEST_F(tls_basic, rekey_tx)
+{
+ struct tls_crypto_info_keys tls12_0, tls12_1;
+ char const *test_str = "test_message";
+ int send_len = strlen(test_str) + 1;
+ char buf[20];
+ int ret;
+
+ if (self->notls)
+ return;
+
+ tls_crypto_info_init(TLS_1_3_VERSION, TLS_CIPHER_AES_GCM_128,
+ &tls12_0, 0);
+ tls_crypto_info_init(TLS_1_3_VERSION, TLS_CIPHER_AES_GCM_128,
+ &tls12_1, 1);
+
+ ret = setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12_0, tls12_0.len);
+ ASSERT_EQ(ret, 0);
+
+ ret = setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12_1, tls12_1.len);
+ ASSERT_EQ(ret, 0);
+
+ ret = setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12_1, tls12_1.len);
+ EXPECT_EQ(ret, 0);
+
+ EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+ EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len);
+ EXPECT_EQ(memcmp(buf, test_str, send_len), 0);
+}
+
+TEST_F(tls, rekey)
+{
+ char const *test_str_1 = "test_message_before_rekey";
+ char const *test_str_2 = "test_message_after_rekey";
+ struct tls_crypto_info_keys tls12;
+ int send_len;
+ char buf[100];
+
+ if (variant->tls_version != TLS_1_3_VERSION)
+ return;
+
+ /* initial send/recv */
+ send_len = strlen(test_str_1) + 1;
+ EXPECT_EQ(send(self->fd, test_str_1, send_len, 0), send_len);
+ EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len);
+ EXPECT_EQ(memcmp(buf, test_str_1, send_len), 0);
+
+ /* update TX key */
+ tls_send_keyupdate(_metadata, self->fd);
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0);
+
+ /* send after rekey */
+ send_len = strlen(test_str_2) + 1;
+ EXPECT_EQ(send(self->fd, test_str_2, send_len, 0), send_len);
+
+ /* can't receive the KeyUpdate without a control message */
+ EXPECT_EQ(recv(self->cfd, buf, send_len, 0), -1);
+
+ /* get KeyUpdate */
+ tls_recv_keyupdate(_metadata, self->cfd, 0);
+
+ /* recv blocking -> -EKEYEXPIRED */
+ EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), 0), -1);
+ EXPECT_EQ(errno, EKEYEXPIRED);
+
+ /* recv non-blocking -> -EKEYEXPIRED */
+ EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), MSG_DONTWAIT), -1);
+ EXPECT_EQ(errno, EKEYEXPIRED);
+
+ /* update RX key */
+ EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0);
+
+ /* recv after rekey */
+ EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+ EXPECT_EQ(memcmp(buf, test_str_2, send_len), 0);
+}
+
+TEST_F(tls, rekey_fail)
+{
+ char const *test_str_1 = "test_message_before_rekey";
+ char const *test_str_2 = "test_message_after_rekey";
+ struct tls_crypto_info_keys tls12;
+ int send_len;
+ char buf[100];
+
+ /* initial send/recv */
+ send_len = strlen(test_str_1) + 1;
+ EXPECT_EQ(send(self->fd, test_str_1, send_len, 0), send_len);
+ EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len);
+ EXPECT_EQ(memcmp(buf, test_str_1, send_len), 0);
+
+ /* update TX key */
+ tls_send_keyupdate(_metadata, self->fd);
+
+ if (variant->tls_version != TLS_1_3_VERSION) {
+ /* just check that rekey is not supported and return */
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), -1);
+ EXPECT_EQ(errno, EBUSY);
+ return;
+ }
+
+ /* successful update */
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0);
+
+ /* invalid update: change of version */
+ tls_crypto_info_init(TLS_1_2_VERSION, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), -1);
+ EXPECT_EQ(errno, EINVAL);
+
+ /* invalid update (RX socket): change of version */
+ tls_crypto_info_init(TLS_1_2_VERSION, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), -1);
+ EXPECT_EQ(errno, EINVAL);
+
+ /* invalid update: change of cipher */
+ if (variant->cipher_type == TLS_CIPHER_AES_GCM_256)
+ tls_crypto_info_init(variant->tls_version, TLS_CIPHER_CHACHA20_POLY1305, &tls12, 1);
+ else
+ tls_crypto_info_init(variant->tls_version, TLS_CIPHER_AES_GCM_256, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), -1);
+ EXPECT_EQ(errno, EINVAL);
+
+ /* send after rekey, the invalid updates shouldn't have an effect */
+ send_len = strlen(test_str_2) + 1;
+ EXPECT_EQ(send(self->fd, test_str_2, send_len, 0), send_len);
+
+ /* can't receive the KeyUpdate without a control message */
+ EXPECT_EQ(recv(self->cfd, buf, send_len, 0), -1);
+
+ /* get KeyUpdate */
+ tls_recv_keyupdate(_metadata, self->cfd, 0);
+
+ /* recv blocking -> -EKEYEXPIRED */
+ EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), 0), -1);
+ EXPECT_EQ(errno, EKEYEXPIRED);
+
+ /* recv non-blocking -> -EKEYEXPIRED */
+ EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), MSG_DONTWAIT), -1);
+ EXPECT_EQ(errno, EKEYEXPIRED);
+
+ /* update RX key */
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0);
+
+ /* recv after rekey */
+ EXPECT_NE(recv(self->cfd, buf, send_len, 0), -1);
+ EXPECT_EQ(memcmp(buf, test_str_2, send_len), 0);
+}
+
+TEST_F(tls, rekey_peek)
+{
+ char const *test_str_1 = "test_message_before_rekey";
+ struct tls_crypto_info_keys tls12;
+ int send_len;
+ char buf[100];
+
+ if (variant->tls_version != TLS_1_3_VERSION)
+ return;
+
+ send_len = strlen(test_str_1) + 1;
+ EXPECT_EQ(send(self->fd, test_str_1, send_len, 0), send_len);
+
+ /* update TX key */
+ tls_send_keyupdate(_metadata, self->fd);
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0);
+
+ EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), MSG_PEEK), send_len);
+ EXPECT_EQ(memcmp(buf, test_str_1, send_len), 0);
+
+ EXPECT_EQ(recv(self->cfd, buf, send_len, 0), send_len);
+ EXPECT_EQ(memcmp(buf, test_str_1, send_len), 0);
+
+ /* can't receive the KeyUpdate without a control message */
+ EXPECT_EQ(recv(self->cfd, buf, send_len, MSG_PEEK), -1);
+
+ /* peek KeyUpdate */
+ tls_recv_keyupdate(_metadata, self->cfd, MSG_PEEK);
+
+ /* get KeyUpdate */
+ tls_recv_keyupdate(_metadata, self->cfd, 0);
+
+ /* update RX key */
+ EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0);
+}
+
+TEST_F(tls, splice_rekey)
+{
+ int send_len = TLS_PAYLOAD_MAX_LEN / 2;
+ char mem_send[TLS_PAYLOAD_MAX_LEN];
+ char mem_recv[TLS_PAYLOAD_MAX_LEN];
+ struct tls_crypto_info_keys tls12;
+ int p[2];
+
+ if (variant->tls_version != TLS_1_3_VERSION)
+ return;
+
+ memrnd(mem_send, sizeof(mem_send));
+
+ ASSERT_GE(pipe(p), 0);
+ EXPECT_EQ(send(self->fd, mem_send, send_len, 0), send_len);
+
+ /* update TX key */
+ tls_send_keyupdate(_metadata, self->fd);
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0);
+
+ EXPECT_EQ(send(self->fd, mem_send, send_len, 0), send_len);
+
+ EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, TLS_PAYLOAD_MAX_LEN, 0), send_len);
+ EXPECT_EQ(read(p[0], mem_recv, send_len), send_len);
+ EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);
+
+ /* can't splice the KeyUpdate */
+ EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, TLS_PAYLOAD_MAX_LEN, 0), -1);
+ EXPECT_EQ(errno, EINVAL);
+
+ /* peek KeyUpdate */
+ tls_recv_keyupdate(_metadata, self->cfd, MSG_PEEK);
+
+ /* get KeyUpdate */
+ tls_recv_keyupdate(_metadata, self->cfd, 0);
+
+ /* can't splice before updating the key */
+ EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, TLS_PAYLOAD_MAX_LEN, 0), -1);
+ EXPECT_EQ(errno, EKEYEXPIRED);
+
+ /* update RX key */
+ EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0);
+
+ EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, TLS_PAYLOAD_MAX_LEN, 0), send_len);
+ EXPECT_EQ(read(p[0], mem_recv, send_len), send_len);
+ EXPECT_EQ(memcmp(mem_send, mem_recv, send_len), 0);
+}
+
+TEST_F(tls, rekey_peek_splice)
+{
+ char const *test_str_1 = "test_message_before_rekey";
+ struct tls_crypto_info_keys tls12;
+ int send_len;
+ char buf[100];
+ char mem_recv[TLS_PAYLOAD_MAX_LEN];
+ int p[2];
+
+ if (variant->tls_version != TLS_1_3_VERSION)
+ return;
+
+ ASSERT_GE(pipe(p), 0);
+
+ send_len = strlen(test_str_1) + 1;
+ EXPECT_EQ(send(self->fd, test_str_1, send_len, 0), send_len);
+
+ /* update TX key */
+ tls_send_keyupdate(_metadata, self->fd);
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0);
+
+ EXPECT_EQ(recv(self->cfd, buf, sizeof(buf), MSG_PEEK), send_len);
+ EXPECT_EQ(memcmp(buf, test_str_1, send_len), 0);
+
+ EXPECT_EQ(splice(self->cfd, NULL, p[1], NULL, TLS_PAYLOAD_MAX_LEN, 0), send_len);
+ EXPECT_EQ(read(p[0], mem_recv, send_len), send_len);
+ EXPECT_EQ(memcmp(mem_recv, test_str_1, send_len), 0);
+}
+
+TEST_F(tls, rekey_getsockopt)
+{
+ struct tls_crypto_info_keys tls12;
+ struct tls_crypto_info_keys tls12_get;
+ socklen_t len;
+
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 0);
+
+ len = tls12.len;
+ EXPECT_EQ(getsockopt(self->fd, SOL_TLS, TLS_TX, &tls12_get, &len), 0);
+ EXPECT_EQ(len, tls12.len);
+ EXPECT_EQ(memcmp(&tls12_get, &tls12, tls12.len), 0);
+
+ len = tls12.len;
+ EXPECT_EQ(getsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12_get, &len), 0);
+ EXPECT_EQ(len, tls12.len);
+ EXPECT_EQ(memcmp(&tls12_get, &tls12, tls12.len), 0);
+
+ if (variant->tls_version != TLS_1_3_VERSION)
+ return;
+
+ tls_send_keyupdate(_metadata, self->fd);
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0);
+
+ tls_recv_keyupdate(_metadata, self->cfd, 0);
+ EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0);
+
+ len = tls12.len;
+ EXPECT_EQ(getsockopt(self->fd, SOL_TLS, TLS_TX, &tls12_get, &len), 0);
+ EXPECT_EQ(len, tls12.len);
+ EXPECT_EQ(memcmp(&tls12_get, &tls12, tls12.len), 0);
+
+ len = tls12.len;
+ EXPECT_EQ(getsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12_get, &len), 0);
+ EXPECT_EQ(len, tls12.len);
+ EXPECT_EQ(memcmp(&tls12_get, &tls12, tls12.len), 0);
+}
+
+TEST_F(tls, rekey_poll_pending)
+{
+ char const *test_str = "test_message_after_rekey";
+ struct tls_crypto_info_keys tls12;
+ struct pollfd pfd = { };
+ int send_len;
+ int ret;
+
+ if (variant->tls_version != TLS_1_3_VERSION)
+ return;
+
+ /* update TX key */
+ tls_send_keyupdate(_metadata, self->fd);
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0);
+
+ /* get KeyUpdate */
+ tls_recv_keyupdate(_metadata, self->cfd, 0);
+
+ /* send immediately after rekey */
+ send_len = strlen(test_str) + 1;
+ EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+
+ /* key hasn't been updated, expect cfd to be non-readable */
+ pfd.fd = self->cfd;
+ pfd.events = POLLIN;
+ EXPECT_EQ(poll(&pfd, 1, 0), 0);
+
+ ret = fork();
+ ASSERT_GE(ret, 0);
+
+ if (ret) {
+ int pid2, status;
+
+ /* wait before installing the new key */
+ sleep(1);
+
+ /* update RX key while poll() is sleeping */
+ EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0);
+
+ pid2 = wait(&status);
+ EXPECT_EQ(pid2, ret);
+ EXPECT_EQ(status, 0);
+ } else {
+ pfd.fd = self->cfd;
+ pfd.events = POLLIN;
+ EXPECT_EQ(poll(&pfd, 1, 5000), 1);
+
+ exit(!__test_passed(_metadata));
+ }
+}
+
+TEST_F(tls, rekey_poll_delay)
+{
+ char const *test_str = "test_message_after_rekey";
+ struct tls_crypto_info_keys tls12;
+ struct pollfd pfd = { };
+ int send_len;
+ int ret;
+
+ if (variant->tls_version != TLS_1_3_VERSION)
+ return;
+
+ /* update TX key */
+ tls_send_keyupdate(_metadata, self->fd);
+ tls_crypto_info_init(variant->tls_version, variant->cipher_type, &tls12, 1);
+ EXPECT_EQ(setsockopt(self->fd, SOL_TLS, TLS_TX, &tls12, tls12.len), 0);
+
+ /* get KeyUpdate */
+ tls_recv_keyupdate(_metadata, self->cfd, 0);
+
+ ret = fork();
+ ASSERT_GE(ret, 0);
+
+ if (ret) {
+ int pid2, status;
+
+ /* wait before installing the new key */
+ sleep(1);
+
+ /* update RX key while poll() is sleeping */
+ EXPECT_EQ(setsockopt(self->cfd, SOL_TLS, TLS_RX, &tls12, tls12.len), 0);
+
+ sleep(1);
+ send_len = strlen(test_str) + 1;
+ EXPECT_EQ(send(self->fd, test_str, send_len, 0), send_len);
+
+ pid2 = wait(&status);
+ EXPECT_EQ(pid2, ret);
+ EXPECT_EQ(status, 0);
+ } else {
+ pfd.fd = self->cfd;
+ pfd.events = POLLIN;
+ EXPECT_EQ(poll(&pfd, 1, 5000), 1);
+ exit(!__test_passed(_metadata));
+ }
+}
+
FIXTURE(tls_err)
{
int fd, cfd;
@@ -1696,7 +2156,7 @@ FIXTURE_SETUP(tls_err)
int ret;
tls_crypto_info_init(variant->tls_version, TLS_CIPHER_AES_GCM_128,
- &tls12);
+ &tls12, 0);
ulp_sock_pair(_metadata, &self->fd, &self->cfd, &self->notls);
ulp_sock_pair(_metadata, &self->fd2, &self->cfd2, &self->notls);
@@ -2118,7 +2578,7 @@ TEST(tls_v6ops) {
int sfd, ret, fd;
socklen_t len, len2;
- tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_GCM_128, &tls12);
+ tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_GCM_128, &tls12, 0);
addr.sin6_family = AF_INET6;
addr.sin6_addr = in6addr_any;
@@ -2177,7 +2637,7 @@ TEST(prequeue) {
len = sizeof(addr);
memrnd(buf, sizeof(buf));
- tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_GCM_256, &tls12);
+ tls_crypto_info_init(TLS_1_2_VERSION, TLS_CIPHER_AES_GCM_256, &tls12, 0);
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
diff --git a/tools/testing/selftests/net/vlan_bridge_binding.sh b/tools/testing/selftests/net/vlan_bridge_binding.sh
new file mode 100755
index 000000000000..e7cb8c678bde
--- /dev/null
+++ b/tools/testing/selftests/net/vlan_bridge_binding.sh
@@ -0,0 +1,256 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0
+
+source lib.sh
+
+ALL_TESTS="
+ test_binding_on
+ test_binding_off
+ test_binding_toggle_on
+ test_binding_toggle_off
+ test_binding_toggle_on_when_upper_down
+ test_binding_toggle_off_when_upper_down
+ test_binding_toggle_on_when_lower_down
+ test_binding_toggle_off_when_lower_down
+"
+
+setup_prepare()
+{
+ local port
+
+ ip_link_add br up type bridge vlan_filtering 1
+
+ for port in d1 d2 d3; do
+ ip_link_add $port type veth peer name r$port
+ ip_link_set_up $port
+ ip_link_set_up r$port
+ ip_link_set_master $port br
+ done
+
+ bridge_vlan_add vid 11 dev br self
+ bridge_vlan_add vid 11 dev d1 master
+
+ bridge_vlan_add vid 12 dev br self
+ bridge_vlan_add vid 12 dev d2 master
+
+ bridge_vlan_add vid 13 dev br self
+ bridge_vlan_add vid 13 dev d1 master
+ bridge_vlan_add vid 13 dev d2 master
+
+ bridge_vlan_add vid 14 dev br self
+ bridge_vlan_add vid 14 dev d1 master
+ bridge_vlan_add vid 14 dev d2 master
+ bridge_vlan_add vid 14 dev d3 master
+}
+
+operstate_is()
+{
+ local dev=$1; shift
+ local expect=$1; shift
+
+ local operstate=$(ip -j link show $dev | jq -r .[].operstate)
+ if [[ $operstate == UP ]]; then
+ operstate=1
+ elif [[ $operstate == DOWN || $operstate == LOWERLAYERDOWN ]]; then
+ operstate=0
+ fi
+ echo -n $operstate
+ [[ $operstate == $expect ]]
+}
+
+check_operstate()
+{
+ local dev=$1; shift
+ local expect=$1; shift
+ local operstate
+
+ operstate=$(busywait 1000 \
+ operstate_is "$dev" "$expect")
+ check_err $? "Got operstate of $operstate, expected $expect"
+}
+
+add_one_vlan()
+{
+ local link=$1; shift
+ local id=$1; shift
+
+ ip_link_add $link.$id link $link type vlan id $id "$@"
+}
+
+add_vlans()
+{
+ add_one_vlan br 11 "$@"
+ add_one_vlan br 12 "$@"
+ add_one_vlan br 13 "$@"
+ add_one_vlan br 14 "$@"
+}
+
+set_vlans()
+{
+ ip link set dev br.11 "$@"
+ ip link set dev br.12 "$@"
+ ip link set dev br.13 "$@"
+ ip link set dev br.14 "$@"
+}
+
+down_netdevs()
+{
+ local dev
+
+ for dev in "$@"; do
+ ip_link_set_down $dev
+ done
+}
+
+check_operstates()
+{
+ local opst_11=$1; shift
+ local opst_12=$1; shift
+ local opst_13=$1; shift
+ local opst_14=$1; shift
+
+ check_operstate br.11 $opst_11
+ check_operstate br.12 $opst_12
+ check_operstate br.13 $opst_13
+ check_operstate br.14 $opst_14
+}
+
+do_test_binding()
+{
+ local inject=$1; shift
+ local what=$1; shift
+ local opsts_d1=$1; shift
+ local opsts_d2=$1; shift
+ local opsts_d12=$1; shift
+ local opsts_d123=$1; shift
+
+ RET=0
+
+ defer_scope_push
+ down_netdevs d1
+ $inject
+ check_operstates $opsts_d1
+ defer_scope_pop
+
+ defer_scope_push
+ down_netdevs d2
+ $inject
+ check_operstates $opsts_d2
+ defer_scope_pop
+
+ defer_scope_push
+ down_netdevs d1 d2
+ $inject
+ check_operstates $opsts_d12
+ defer_scope_pop
+
+ defer_scope_push
+ down_netdevs d1 d2 d3
+ $inject
+ check_operstates $opsts_d123
+ defer_scope_pop
+
+ log_test "Test bridge_binding $what"
+}
+
+do_test_binding_on()
+{
+ local inject=$1; shift
+ local what=$1; shift
+
+ do_test_binding "$inject" "$what" \
+ "0 1 1 1" \
+ "1 0 1 1" \
+ "0 0 0 1" \
+ "0 0 0 0"
+}
+
+do_test_binding_off()
+{
+ local inject=$1; shift
+ local what=$1; shift
+
+ do_test_binding "$inject" "$what" \
+ "1 1 1 1" \
+ "1 1 1 1" \
+ "1 1 1 1" \
+ "0 0 0 0"
+}
+
+test_binding_on()
+{
+ add_vlans bridge_binding on
+ set_vlans up
+ do_test_binding_on : "on"
+}
+
+test_binding_off()
+{
+ add_vlans bridge_binding off
+ set_vlans up
+ do_test_binding_off : "off"
+}
+
+test_binding_toggle_on()
+{
+ add_vlans bridge_binding off
+ set_vlans up
+ set_vlans type vlan bridge_binding on
+ do_test_binding_on : "off->on"
+}
+
+test_binding_toggle_off()
+{
+ add_vlans bridge_binding on
+ set_vlans up
+ set_vlans type vlan bridge_binding off
+ do_test_binding_off : "on->off"
+}
+
+dfr_set_binding_on()
+{
+ set_vlans type vlan bridge_binding on
+ defer set_vlans type vlan bridge_binding off
+}
+
+dfr_set_binding_off()
+{
+ set_vlans type vlan bridge_binding off
+ defer set_vlans type vlan bridge_binding on
+}
+
+test_binding_toggle_on_when_lower_down()
+{
+ add_vlans bridge_binding off
+ set_vlans up
+ do_test_binding_on dfr_set_binding_on "off->on when lower down"
+}
+
+test_binding_toggle_off_when_lower_down()
+{
+ add_vlans bridge_binding on
+ set_vlans up
+ do_test_binding_off dfr_set_binding_off "on->off when lower down"
+}
+
+test_binding_toggle_on_when_upper_down()
+{
+ add_vlans bridge_binding off
+ set_vlans type vlan bridge_binding on
+ set_vlans up
+ do_test_binding_on : "off->on when upper down"
+}
+
+test_binding_toggle_off_when_upper_down()
+{
+ add_vlans bridge_binding on
+ set_vlans type vlan bridge_binding off
+ set_vlans up
+ do_test_binding_off : "on->off when upper down"
+}
+
+trap defer_scopes_cleanup EXIT
+setup_prepare
+tests_run
+
+exit $EXIT_STATUS
diff --git a/tools/testing/selftests/net/ynl.mk b/tools/testing/selftests/net/ynl.mk
index d43afe243779..12e7cae251be 100644
--- a/tools/testing/selftests/net/ynl.mk
+++ b/tools/testing/selftests/net/ynl.mk
@@ -31,7 +31,8 @@ $(OUTPUT)/libynl.a: $(YNL_SPECS) $(OUTPUT)/.libynl-$(YNL_GENS_HASH).sig
$(Q)cp $(top_srcdir)/tools/net/ynl/libynl.a $(OUTPUT)/libynl.a
EXTRA_CLEAN += \
- $(top_srcdir)/tools/net/ynl/lib/__pycache__ \
+ $(top_srcdir)/tools/net/ynl/pyynl/__pycache__ \
+ $(top_srcdir)/tools/net/ynl/pyynl/lib/__pycache__ \
$(top_srcdir)/tools/net/ynl/lib/*.[ado] \
$(OUTPUT)/.libynl-*.sig \
$(OUTPUT)/libynl.a
diff --git a/tools/testing/selftests/sched_ext/ddsp_bogus_dsq_fail.bpf.c b/tools/testing/selftests/sched_ext/ddsp_bogus_dsq_fail.bpf.c
index 37d9bf6fb745..6f4c3f5a1c5d 100644
--- a/tools/testing/selftests/sched_ext/ddsp_bogus_dsq_fail.bpf.c
+++ b/tools/testing/selftests/sched_ext/ddsp_bogus_dsq_fail.bpf.c
@@ -20,7 +20,7 @@ s32 BPF_STRUCT_OPS(ddsp_bogus_dsq_fail_select_cpu, struct task_struct *p,
* If we dispatch to a bogus DSQ that will fall back to the
* builtin global DSQ, we fail gracefully.
*/
- scx_bpf_dispatch_vtime(p, 0xcafef00d, SCX_SLICE_DFL,
+ scx_bpf_dsq_insert_vtime(p, 0xcafef00d, SCX_SLICE_DFL,
p->scx.dsq_vtime, 0);
return cpu;
}
diff --git a/tools/testing/selftests/sched_ext/ddsp_vtimelocal_fail.bpf.c b/tools/testing/selftests/sched_ext/ddsp_vtimelocal_fail.bpf.c
index dffc97d9cdf1..e4a55027778f 100644
--- a/tools/testing/selftests/sched_ext/ddsp_vtimelocal_fail.bpf.c
+++ b/tools/testing/selftests/sched_ext/ddsp_vtimelocal_fail.bpf.c
@@ -17,8 +17,8 @@ s32 BPF_STRUCT_OPS(ddsp_vtimelocal_fail_select_cpu, struct task_struct *p,
if (cpu >= 0) {
/* Shouldn't be allowed to vtime dispatch to a builtin DSQ. */
- scx_bpf_dispatch_vtime(p, SCX_DSQ_LOCAL, SCX_SLICE_DFL,
- p->scx.dsq_vtime, 0);
+ scx_bpf_dsq_insert_vtime(p, SCX_DSQ_LOCAL, SCX_SLICE_DFL,
+ p->scx.dsq_vtime, 0);
return cpu;
}
diff --git a/tools/testing/selftests/sched_ext/dsp_local_on.bpf.c b/tools/testing/selftests/sched_ext/dsp_local_on.bpf.c
index 6a7db1502c29..fbda6bf54671 100644
--- a/tools/testing/selftests/sched_ext/dsp_local_on.bpf.c
+++ b/tools/testing/selftests/sched_ext/dsp_local_on.bpf.c
@@ -43,9 +43,12 @@ void BPF_STRUCT_OPS(dsp_local_on_dispatch, s32 cpu, struct task_struct *prev)
if (!p)
return;
- target = bpf_get_prandom_u32() % nr_cpus;
+ if (p->nr_cpus_allowed == nr_cpus)
+ target = bpf_get_prandom_u32() % nr_cpus;
+ else
+ target = scx_bpf_task_cpu(p);
- scx_bpf_dispatch(p, SCX_DSQ_LOCAL_ON | target, SCX_SLICE_DFL, 0);
+ scx_bpf_dsq_insert(p, SCX_DSQ_LOCAL_ON | target, SCX_SLICE_DFL, 0);
bpf_task_release(p);
}
diff --git a/tools/testing/selftests/sched_ext/dsp_local_on.c b/tools/testing/selftests/sched_ext/dsp_local_on.c
index 472851b56854..0ff27e57fe43 100644
--- a/tools/testing/selftests/sched_ext/dsp_local_on.c
+++ b/tools/testing/selftests/sched_ext/dsp_local_on.c
@@ -34,9 +34,10 @@ static enum scx_test_status run(void *ctx)
/* Just sleeping is fine, plenty of scheduling events happening */
sleep(1);
- SCX_EQ(skel->data->uei.kind, EXIT_KIND(SCX_EXIT_ERROR));
bpf_link__destroy(link);
+ SCX_EQ(skel->data->uei.kind, EXIT_KIND(SCX_EXIT_UNREG));
+
return SCX_TEST_PASS;
}
@@ -50,7 +51,7 @@ static void cleanup(void *ctx)
struct scx_test dsp_local_on = {
.name = "dsp_local_on",
.description = "Verify we can directly dispatch tasks to a local DSQs "
- "from osp.dispatch()",
+ "from ops.dispatch()",
.setup = setup,
.run = run,
.cleanup = cleanup,
diff --git a/tools/testing/selftests/sched_ext/enq_select_cpu_fails.bpf.c b/tools/testing/selftests/sched_ext/enq_select_cpu_fails.bpf.c
index 1efb50d61040..a7cf868d5e31 100644
--- a/tools/testing/selftests/sched_ext/enq_select_cpu_fails.bpf.c
+++ b/tools/testing/selftests/sched_ext/enq_select_cpu_fails.bpf.c
@@ -31,7 +31,7 @@ void BPF_STRUCT_OPS(enq_select_cpu_fails_enqueue, struct task_struct *p,
/* Can only call from ops.select_cpu() */
scx_bpf_select_cpu_dfl(p, 0, 0, &found);
- scx_bpf_dispatch(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, enq_flags);
+ scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, enq_flags);
}
SEC(".struct_ops.link")
diff --git a/tools/testing/selftests/sched_ext/exit.bpf.c b/tools/testing/selftests/sched_ext/exit.bpf.c
index d75d4faf07f6..4bc36182d3ff 100644
--- a/tools/testing/selftests/sched_ext/exit.bpf.c
+++ b/tools/testing/selftests/sched_ext/exit.bpf.c
@@ -33,7 +33,7 @@ void BPF_STRUCT_OPS(exit_enqueue, struct task_struct *p, u64 enq_flags)
if (exit_point == EXIT_ENQUEUE)
EXIT_CLEANLY();
- scx_bpf_dispatch(p, DSQ_ID, SCX_SLICE_DFL, enq_flags);
+ scx_bpf_dsq_insert(p, DSQ_ID, SCX_SLICE_DFL, enq_flags);
}
void BPF_STRUCT_OPS(exit_dispatch, s32 cpu, struct task_struct *p)
@@ -41,7 +41,7 @@ void BPF_STRUCT_OPS(exit_dispatch, s32 cpu, struct task_struct *p)
if (exit_point == EXIT_DISPATCH)
EXIT_CLEANLY();
- scx_bpf_consume(DSQ_ID);
+ scx_bpf_dsq_move_to_local(DSQ_ID);
}
void BPF_STRUCT_OPS(exit_enable, struct task_struct *p)
diff --git a/tools/testing/selftests/sched_ext/maximal.bpf.c b/tools/testing/selftests/sched_ext/maximal.bpf.c
index 4d4cd8d966db..430f5e13bf55 100644
--- a/tools/testing/selftests/sched_ext/maximal.bpf.c
+++ b/tools/testing/selftests/sched_ext/maximal.bpf.c
@@ -12,6 +12,8 @@
char _license[] SEC("license") = "GPL";
+#define DSQ_ID 0
+
s32 BPF_STRUCT_OPS(maximal_select_cpu, struct task_struct *p, s32 prev_cpu,
u64 wake_flags)
{
@@ -20,7 +22,7 @@ s32 BPF_STRUCT_OPS(maximal_select_cpu, struct task_struct *p, s32 prev_cpu,
void BPF_STRUCT_OPS(maximal_enqueue, struct task_struct *p, u64 enq_flags)
{
- scx_bpf_dispatch(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, enq_flags);
+ scx_bpf_dsq_insert(p, DSQ_ID, SCX_SLICE_DFL, enq_flags);
}
void BPF_STRUCT_OPS(maximal_dequeue, struct task_struct *p, u64 deq_flags)
@@ -28,7 +30,7 @@ void BPF_STRUCT_OPS(maximal_dequeue, struct task_struct *p, u64 deq_flags)
void BPF_STRUCT_OPS(maximal_dispatch, s32 cpu, struct task_struct *prev)
{
- scx_bpf_consume(SCX_DSQ_GLOBAL);
+ scx_bpf_dsq_move_to_local(DSQ_ID);
}
void BPF_STRUCT_OPS(maximal_runnable, struct task_struct *p, u64 enq_flags)
@@ -123,7 +125,7 @@ void BPF_STRUCT_OPS(maximal_cgroup_set_weight, struct cgroup *cgrp, u32 weight)
s32 BPF_STRUCT_OPS_SLEEPABLE(maximal_init)
{
- return 0;
+ return scx_bpf_create_dsq(DSQ_ID, -1);
}
void BPF_STRUCT_OPS(maximal_exit, struct scx_exit_info *info)
diff --git a/tools/testing/selftests/sched_ext/select_cpu_dfl.bpf.c b/tools/testing/selftests/sched_ext/select_cpu_dfl.bpf.c
index f171ac470970..13d0f5be788d 100644
--- a/tools/testing/selftests/sched_ext/select_cpu_dfl.bpf.c
+++ b/tools/testing/selftests/sched_ext/select_cpu_dfl.bpf.c
@@ -30,7 +30,7 @@ void BPF_STRUCT_OPS(select_cpu_dfl_enqueue, struct task_struct *p,
}
scx_bpf_put_idle_cpumask(idle_mask);
- scx_bpf_dispatch(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, enq_flags);
+ scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, enq_flags);
}
SEC(".struct_ops.link")
diff --git a/tools/testing/selftests/sched_ext/select_cpu_dfl_nodispatch.bpf.c b/tools/testing/selftests/sched_ext/select_cpu_dfl_nodispatch.bpf.c
index 9efdbb7da928..815f1d5d61ac 100644
--- a/tools/testing/selftests/sched_ext/select_cpu_dfl_nodispatch.bpf.c
+++ b/tools/testing/selftests/sched_ext/select_cpu_dfl_nodispatch.bpf.c
@@ -67,7 +67,7 @@ void BPF_STRUCT_OPS(select_cpu_dfl_nodispatch_enqueue, struct task_struct *p,
saw_local = true;
}
- scx_bpf_dispatch(p, dsq_id, SCX_SLICE_DFL, enq_flags);
+ scx_bpf_dsq_insert(p, dsq_id, SCX_SLICE_DFL, enq_flags);
}
s32 BPF_STRUCT_OPS(select_cpu_dfl_nodispatch_init_task,
diff --git a/tools/testing/selftests/sched_ext/select_cpu_dispatch.bpf.c b/tools/testing/selftests/sched_ext/select_cpu_dispatch.bpf.c
index 59bfc4f36167..4bb99699e920 100644
--- a/tools/testing/selftests/sched_ext/select_cpu_dispatch.bpf.c
+++ b/tools/testing/selftests/sched_ext/select_cpu_dispatch.bpf.c
@@ -29,7 +29,7 @@ s32 BPF_STRUCT_OPS(select_cpu_dispatch_select_cpu, struct task_struct *p,
cpu = prev_cpu;
dispatch:
- scx_bpf_dispatch(p, dsq_id, SCX_SLICE_DFL, 0);
+ scx_bpf_dsq_insert(p, dsq_id, SCX_SLICE_DFL, 0);
return cpu;
}
diff --git a/tools/testing/selftests/sched_ext/select_cpu_dispatch_bad_dsq.bpf.c b/tools/testing/selftests/sched_ext/select_cpu_dispatch_bad_dsq.bpf.c
index 3bbd5fcdfb18..2a75de11b2cf 100644
--- a/tools/testing/selftests/sched_ext/select_cpu_dispatch_bad_dsq.bpf.c
+++ b/tools/testing/selftests/sched_ext/select_cpu_dispatch_bad_dsq.bpf.c
@@ -18,7 +18,7 @@ s32 BPF_STRUCT_OPS(select_cpu_dispatch_bad_dsq_select_cpu, struct task_struct *p
s32 prev_cpu, u64 wake_flags)
{
/* Dispatching to a random DSQ should fail. */
- scx_bpf_dispatch(p, 0xcafef00d, SCX_SLICE_DFL, 0);
+ scx_bpf_dsq_insert(p, 0xcafef00d, SCX_SLICE_DFL, 0);
return prev_cpu;
}
diff --git a/tools/testing/selftests/sched_ext/select_cpu_dispatch_dbl_dsp.bpf.c b/tools/testing/selftests/sched_ext/select_cpu_dispatch_dbl_dsp.bpf.c
index 0fda57fe0ecf..99d075695c97 100644
--- a/tools/testing/selftests/sched_ext/select_cpu_dispatch_dbl_dsp.bpf.c
+++ b/tools/testing/selftests/sched_ext/select_cpu_dispatch_dbl_dsp.bpf.c
@@ -18,8 +18,8 @@ s32 BPF_STRUCT_OPS(select_cpu_dispatch_dbl_dsp_select_cpu, struct task_struct *p
s32 prev_cpu, u64 wake_flags)
{
/* Dispatching twice in a row is disallowed. */
- scx_bpf_dispatch(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, 0);
- scx_bpf_dispatch(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, 0);
+ scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, 0);
+ scx_bpf_dsq_insert(p, SCX_DSQ_GLOBAL, SCX_SLICE_DFL, 0);
return prev_cpu;
}
diff --git a/tools/testing/selftests/sched_ext/select_cpu_vtime.bpf.c b/tools/testing/selftests/sched_ext/select_cpu_vtime.bpf.c
index e6c67bcf5e6e..bfcb96cd4954 100644
--- a/tools/testing/selftests/sched_ext/select_cpu_vtime.bpf.c
+++ b/tools/testing/selftests/sched_ext/select_cpu_vtime.bpf.c
@@ -2,8 +2,8 @@
/*
* A scheduler that validates that enqueue flags are properly stored and
* applied at dispatch time when a task is directly dispatched from
- * ops.select_cpu(). We validate this by using scx_bpf_dispatch_vtime(), and
- * making the test a very basic vtime scheduler.
+ * ops.select_cpu(). We validate this by using scx_bpf_dsq_insert_vtime(),
+ * and making the test a very basic vtime scheduler.
*
* Copyright (c) 2024 Meta Platforms, Inc. and affiliates.
* Copyright (c) 2024 David Vernet <dvernet@meta.com>
@@ -47,13 +47,13 @@ s32 BPF_STRUCT_OPS(select_cpu_vtime_select_cpu, struct task_struct *p,
cpu = prev_cpu;
scx_bpf_test_and_clear_cpu_idle(cpu);
ddsp:
- scx_bpf_dispatch_vtime(p, VTIME_DSQ, SCX_SLICE_DFL, task_vtime(p), 0);
+ scx_bpf_dsq_insert_vtime(p, VTIME_DSQ, SCX_SLICE_DFL, task_vtime(p), 0);
return cpu;
}
void BPF_STRUCT_OPS(select_cpu_vtime_dispatch, s32 cpu, struct task_struct *p)
{
- if (scx_bpf_consume(VTIME_DSQ))
+ if (scx_bpf_dsq_move_to_local(VTIME_DSQ))
consumed = true;
}
diff --git a/tools/testing/selftests/tc-testing/scripts/sfq_rejects_limit_1.py b/tools/testing/selftests/tc-testing/scripts/sfq_rejects_limit_1.py
new file mode 100755
index 000000000000..0f44a6199495
--- /dev/null
+++ b/tools/testing/selftests/tc-testing/scripts/sfq_rejects_limit_1.py
@@ -0,0 +1,21 @@
+#!/usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+#
+# Script that checks that SFQ rejects a limit of 1 at the kernel
+# level. We can't use iproute2's tc because it does not accept a limit
+# of 1.
+
+import sys
+import os
+
+from pyroute2 import IPRoute
+from pyroute2.netlink.exceptions import NetlinkError
+
+ip = IPRoute()
+ifidx = ip.link_lookup(ifname=sys.argv[1])
+
+try:
+ ip.tc('add', 'sfq', ifidx, limit=1)
+ sys.exit(1)
+except NetlinkError:
+ sys.exit(0)
diff --git a/tools/testing/selftests/tc-testing/tc-tests/filters/flow.json b/tools/testing/selftests/tc-testing/tc-tests/filters/flow.json
index 996448afe31b..91d120548bf5 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/filters/flow.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/filters/flow.json
@@ -78,10 +78,10 @@
"setup": [
"$TC qdisc add dev $DEV1 ingress"
],
- "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 1 prio 1 protocol ip flow map key dst rshift 0xff",
+ "cmdUnderTest": "$TC filter add dev $DEV1 parent ffff: handle 1 prio 1 protocol ip flow map key dst rshift 0x1f",
"expExitCode": "0",
"verifyCmd": "$TC filter get dev $DEV1 parent ffff: handle 1 protocol ip prio 1 flow",
- "matchPattern": "filter parent ffff: protocol ip pref 1 flow chain [0-9]+ handle 0x1 map keys dst rshift 255 baseclass",
+ "matchPattern": "filter parent ffff: protocol ip pref 1 flow chain [0-9]+ handle 0x1 map keys dst rshift 31 baseclass",
"matchCount": "1",
"teardown": [
"$TC qdisc del dev $DEV1 ingress"
diff --git a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/sfq.json b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/sfq.json
index 16d51936b385..50e8d72781cb 100644
--- a/tools/testing/selftests/tc-testing/tc-tests/qdiscs/sfq.json
+++ b/tools/testing/selftests/tc-testing/tc-tests/qdiscs/sfq.json
@@ -208,5 +208,25 @@
"teardown": [
"$TC qdisc del dev $DUMMY handle 1: root"
]
+ },
+ {
+ "id": "4d6f",
+ "name": "Check that limit of 1 is rejected",
+ "category": [
+ "qdisc",
+ "sfq"
+ ],
+ "plugins": {
+ "requires": "nsPlugin"
+ },
+ "setup": [
+ ],
+ "cmdUnderTest": "./scripts/sfq_rejects_limit_1.py $DUMMY",
+ "expExitCode": "0",
+ "verifyCmd": "$TC qdisc show dev $DUMMY",
+ "matchPattern": "sfq",
+ "matchCount": "0",
+ "teardown": [
+ ]
}
]
diff --git a/tools/testing/vsock/README b/tools/testing/vsock/README
index 84ee217ba8ee..680ce666ceb5 100644
--- a/tools/testing/vsock/README
+++ b/tools/testing/vsock/README
@@ -36,6 +36,21 @@ Invoke test binaries in both directions as follows:
--control-port=1234 \
--peer-cid=3
+Some tests are designed to produce kernel memory leaks. Leaks detection,
+however, is deferred to Kernel Memory Leak Detector. It is recommended to enable
+kmemleak (CONFIG_DEBUG_KMEMLEAK=y) and explicitly trigger a scan after each test
+suite run, e.g.
+
+ # echo clear > /sys/kernel/debug/kmemleak
+ # $TEST_BINARY ...
+ # echo "wait for any grace periods" && sleep 2
+ # echo scan > /sys/kernel/debug/kmemleak
+ # echo "wait for kmemleak" && sleep 5
+ # echo scan > /sys/kernel/debug/kmemleak
+ # cat /sys/kernel/debug/kmemleak
+
+For more information see Documentation/dev-tools/kmemleak.rst.
+
vsock_perf utility
-------------------
'vsock_perf' is a simple tool to measure vsock performance. It works in
diff --git a/tools/testing/vsock/control.c b/tools/testing/vsock/control.c
index d2deb4b15b94..0066e0324d35 100644
--- a/tools/testing/vsock/control.c
+++ b/tools/testing/vsock/control.c
@@ -27,6 +27,7 @@
#include "timeout.h"
#include "control.h"
+#include "util.h"
static int control_fd = -1;
@@ -50,7 +51,6 @@ void control_init(const char *control_host,
for (ai = result; ai; ai = ai->ai_next) {
int fd;
- int val = 1;
fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
if (fd < 0)
@@ -65,11 +65,8 @@ void control_init(const char *control_host,
break;
}
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,
- &val, sizeof(val)) < 0) {
- perror("setsockopt");
- exit(EXIT_FAILURE);
- }
+ setsockopt_int_check(fd, SOL_SOCKET, SO_REUSEADDR, 1,
+ "setsockopt SO_REUSEADDR");
if (bind(fd, ai->ai_addr, ai->ai_addrlen) < 0)
goto next;
diff --git a/tools/testing/vsock/msg_zerocopy_common.c b/tools/testing/vsock/msg_zerocopy_common.c
index 5a4bdf7b5132..8622e5a0f8b7 100644
--- a/tools/testing/vsock/msg_zerocopy_common.c
+++ b/tools/testing/vsock/msg_zerocopy_common.c
@@ -14,16 +14,6 @@
#include "msg_zerocopy_common.h"
-void enable_so_zerocopy(int fd)
-{
- int val = 1;
-
- if (setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &val, sizeof(val))) {
- perror("setsockopt");
- exit(EXIT_FAILURE);
- }
-}
-
void vsock_recv_completion(int fd, const bool *zerocopied)
{
struct sock_extended_err *serr;
diff --git a/tools/testing/vsock/msg_zerocopy_common.h b/tools/testing/vsock/msg_zerocopy_common.h
index 3763c5ccedb9..ad14139e93ca 100644
--- a/tools/testing/vsock/msg_zerocopy_common.h
+++ b/tools/testing/vsock/msg_zerocopy_common.h
@@ -12,7 +12,6 @@
#define VSOCK_RECVERR 1
#endif
-void enable_so_zerocopy(int fd);
void vsock_recv_completion(int fd, const bool *zerocopied);
#endif /* MSG_ZEROCOPY_COMMON_H */
diff --git a/tools/testing/vsock/util.c b/tools/testing/vsock/util.c
index a3d448a075e3..7058dc614c25 100644
--- a/tools/testing/vsock/util.c
+++ b/tools/testing/vsock/util.c
@@ -401,7 +401,7 @@ void recv_buf(int fd, void *buf, size_t len, int flags, ssize_t expected_ret)
*/
void send_byte(int fd, int expected_ret, int flags)
{
- const uint8_t byte = 'A';
+ static const uint8_t byte = 'A';
send_buf(fd, &byte, sizeof(byte), flags, expected_ret);
}
@@ -420,7 +420,7 @@ void recv_byte(int fd, int expected_ret, int flags)
recv_buf(fd, &byte, sizeof(byte), flags, expected_ret);
if (byte != 'A') {
- fprintf(stderr, "unexpected byte read %c\n", byte);
+ fprintf(stderr, "unexpected byte read 0x%02x\n", byte);
exit(EXIT_FAILURE);
}
}
@@ -486,8 +486,7 @@ void list_tests(const struct test_case *test_cases)
exit(EXIT_FAILURE);
}
-void skip_test(struct test_case *test_cases, size_t test_cases_len,
- const char *test_id_str)
+static unsigned long parse_test_id(const char *test_id_str, size_t test_cases_len)
{
unsigned long test_id;
char *endptr = NULL;
@@ -505,9 +504,35 @@ void skip_test(struct test_case *test_cases, size_t test_cases_len,
exit(EXIT_FAILURE);
}
+ return test_id;
+}
+
+void skip_test(struct test_case *test_cases, size_t test_cases_len,
+ const char *test_id_str)
+{
+ unsigned long test_id = parse_test_id(test_id_str, test_cases_len);
test_cases[test_id].skip = true;
}
+void pick_test(struct test_case *test_cases, size_t test_cases_len,
+ const char *test_id_str)
+{
+ static bool skip_all = true;
+ unsigned long test_id;
+
+ if (skip_all) {
+ unsigned long i;
+
+ for (i = 0; i < test_cases_len; ++i)
+ test_cases[i].skip = true;
+
+ skip_all = false;
+ }
+
+ test_id = parse_test_id(test_id_str, test_cases_len);
+ test_cases[test_id].skip = false;
+}
+
unsigned long hash_djb2(const void *data, size_t len)
{
unsigned long hash = 5381;
@@ -651,3 +676,145 @@ void free_test_iovec(const struct iovec *test_iovec,
free(iovec);
}
+
+/* Set "unsigned long long" socket option and check that it's indeed set */
+void setsockopt_ull_check(int fd, int level, int optname,
+ unsigned long long val, char const *errmsg)
+{
+ unsigned long long chkval;
+ socklen_t chklen;
+ int err;
+
+ err = setsockopt(fd, level, optname, &val, sizeof(val));
+ if (err) {
+ fprintf(stderr, "setsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ chkval = ~val; /* just make storage != val */
+ chklen = sizeof(chkval);
+
+ err = getsockopt(fd, level, optname, &chkval, &chklen);
+ if (err) {
+ fprintf(stderr, "getsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ if (chklen != sizeof(chkval)) {
+ fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
+ chklen);
+ goto fail;
+ }
+
+ if (chkval != val) {
+ fprintf(stderr, "value mismatch: set %llu got %llu\n", val,
+ chkval);
+ goto fail;
+ }
+ return;
+fail:
+ fprintf(stderr, "%s val %llu\n", errmsg, val);
+ exit(EXIT_FAILURE);
+;
+}
+
+/* Set "int" socket option and check that it's indeed set */
+void setsockopt_int_check(int fd, int level, int optname, int val,
+ char const *errmsg)
+{
+ int chkval;
+ socklen_t chklen;
+ int err;
+
+ err = setsockopt(fd, level, optname, &val, sizeof(val));
+ if (err) {
+ fprintf(stderr, "setsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ chkval = ~val; /* just make storage != val */
+ chklen = sizeof(chkval);
+
+ err = getsockopt(fd, level, optname, &chkval, &chklen);
+ if (err) {
+ fprintf(stderr, "getsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ if (chklen != sizeof(chkval)) {
+ fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
+ chklen);
+ goto fail;
+ }
+
+ if (chkval != val) {
+ fprintf(stderr, "value mismatch: set %d got %d\n", val, chkval);
+ goto fail;
+ }
+ return;
+fail:
+ fprintf(stderr, "%s val %d\n", errmsg, val);
+ exit(EXIT_FAILURE);
+}
+
+static void mem_invert(unsigned char *mem, size_t size)
+{
+ size_t i;
+
+ for (i = 0; i < size; i++)
+ mem[i] = ~mem[i];
+}
+
+/* Set "timeval" socket option and check that it's indeed set */
+void setsockopt_timeval_check(int fd, int level, int optname,
+ struct timeval val, char const *errmsg)
+{
+ struct timeval chkval;
+ socklen_t chklen;
+ int err;
+
+ err = setsockopt(fd, level, optname, &val, sizeof(val));
+ if (err) {
+ fprintf(stderr, "setsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ /* just make storage != val */
+ chkval = val;
+ mem_invert((unsigned char *)&chkval, sizeof(chkval));
+ chklen = sizeof(chkval);
+
+ err = getsockopt(fd, level, optname, &chkval, &chklen);
+ if (err) {
+ fprintf(stderr, "getsockopt err: %s (%d)\n",
+ strerror(errno), errno);
+ goto fail;
+ }
+
+ if (chklen != sizeof(chkval)) {
+ fprintf(stderr, "size mismatch: set %zu got %d\n", sizeof(val),
+ chklen);
+ goto fail;
+ }
+
+ if (memcmp(&chkval, &val, sizeof(val)) != 0) {
+ fprintf(stderr, "value mismatch: set %ld:%ld got %ld:%ld\n",
+ val.tv_sec, val.tv_usec, chkval.tv_sec, chkval.tv_usec);
+ goto fail;
+ }
+ return;
+fail:
+ fprintf(stderr, "%s val %ld:%ld\n", errmsg, val.tv_sec, val.tv_usec);
+ exit(EXIT_FAILURE);
+}
+
+void enable_so_zerocopy_check(int fd)
+{
+ setsockopt_int_check(fd, SOL_SOCKET, SO_ZEROCOPY, 1,
+ "setsockopt SO_ZEROCOPY");
+}
diff --git a/tools/testing/vsock/util.h b/tools/testing/vsock/util.h
index fff22d4a14c0..e62f46b2b92a 100644
--- a/tools/testing/vsock/util.h
+++ b/tools/testing/vsock/util.h
@@ -62,10 +62,19 @@ void run_tests(const struct test_case *test_cases,
void list_tests(const struct test_case *test_cases);
void skip_test(struct test_case *test_cases, size_t test_cases_len,
const char *test_id_str);
+void pick_test(struct test_case *test_cases, size_t test_cases_len,
+ const char *test_id_str);
unsigned long hash_djb2(const void *data, size_t len);
size_t iovec_bytes(const struct iovec *iov, size_t iovnum);
unsigned long iovec_hash_djb2(const struct iovec *iov, size_t iovnum);
struct iovec *alloc_test_iovec(const struct iovec *test_iovec, int iovnum);
void free_test_iovec(const struct iovec *test_iovec,
struct iovec *iovec, int iovnum);
+void setsockopt_ull_check(int fd, int level, int optname,
+ unsigned long long val, char const *errmsg);
+void setsockopt_int_check(int fd, int level, int optname, int val,
+ char const *errmsg);
+void setsockopt_timeval_check(int fd, int level, int optname,
+ struct timeval val, char const *errmsg);
+void enable_so_zerocopy_check(int fd);
#endif /* UTIL_H */
diff --git a/tools/testing/vsock/vsock_perf.c b/tools/testing/vsock/vsock_perf.c
index 4e8578f815e0..75971ac708c9 100644
--- a/tools/testing/vsock/vsock_perf.c
+++ b/tools/testing/vsock/vsock_perf.c
@@ -33,7 +33,7 @@
static unsigned int port = DEFAULT_PORT;
static unsigned long buf_size_bytes = DEFAULT_BUF_SIZE_BYTES;
-static unsigned long vsock_buf_bytes = DEFAULT_VSOCK_BUF_BYTES;
+static unsigned long long vsock_buf_bytes = DEFAULT_VSOCK_BUF_BYTES;
static bool zerocopy;
static void error(const char *s)
@@ -133,7 +133,7 @@ static float get_gbps(unsigned long bits, time_t ns_delta)
((float)ns_delta / NSEC_PER_SEC);
}
-static void run_receiver(unsigned long rcvlowat_bytes)
+static void run_receiver(int rcvlowat_bytes)
{
unsigned int read_cnt;
time_t rx_begin_ns;
@@ -162,8 +162,8 @@ static void run_receiver(unsigned long rcvlowat_bytes)
printf("Run as receiver\n");
printf("Listen port %u\n", port);
printf("RX buffer %lu bytes\n", buf_size_bytes);
- printf("vsock buffer %lu bytes\n", vsock_buf_bytes);
- printf("SO_RCVLOWAT %lu bytes\n", rcvlowat_bytes);
+ printf("vsock buffer %llu bytes\n", vsock_buf_bytes);
+ printf("SO_RCVLOWAT %d bytes\n", rcvlowat_bytes);
fd = socket(AF_VSOCK, SOCK_STREAM, 0);
@@ -251,6 +251,16 @@ static void run_receiver(unsigned long rcvlowat_bytes)
close(fd);
}
+static void enable_so_zerocopy(int fd)
+{
+ int val = 1;
+
+ if (setsockopt(fd, SOL_SOCKET, SO_ZEROCOPY, &val, sizeof(val))) {
+ perror("setsockopt");
+ exit(EXIT_FAILURE);
+ }
+}
+
static void run_sender(int peer_cid, unsigned long to_send_bytes)
{
time_t tx_begin_ns;
@@ -439,7 +449,7 @@ static long strtolx(const char *arg)
int main(int argc, char **argv)
{
unsigned long to_send_bytes = DEFAULT_TO_SEND_BYTES;
- unsigned long rcvlowat_bytes = DEFAULT_RCVLOWAT_BYTES;
+ int rcvlowat_bytes = DEFAULT_RCVLOWAT_BYTES;
int peer_cid = -1;
bool sender = false;
diff --git a/tools/testing/vsock/vsock_test.c b/tools/testing/vsock/vsock_test.c
index 8d38dbf8f41f..1eebbc0d5f61 100644
--- a/tools/testing/vsock/vsock_test.c
+++ b/tools/testing/vsock/vsock_test.c
@@ -22,12 +22,17 @@
#include <signal.h>
#include <sys/ioctl.h>
#include <linux/sockios.h>
+#include <linux/time64.h>
#include "vsock_test_zerocopy.h"
#include "timeout.h"
#include "control.h"
#include "util.h"
+/* Basic messages for control_writeulong(), control_readulong() */
+#define CONTROL_CONTINUE 1
+#define CONTROL_DONE 0
+
static void test_stream_connection_reset(const struct test_opts *opts)
{
union {
@@ -429,7 +434,7 @@ static void test_seqpacket_msg_bounds_client(const struct test_opts *opts)
static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
{
- unsigned long sock_buf_size;
+ unsigned long long sock_buf_size;
unsigned long remote_hash;
unsigned long curr_hash;
int fd;
@@ -444,17 +449,13 @@ static void test_seqpacket_msg_bounds_server(const struct test_opts *opts)
sock_buf_size = SOCK_BUF_SIZE;
- if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE,
- &sock_buf_size, sizeof(sock_buf_size))) {
- perror("setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)");
- exit(EXIT_FAILURE);
- }
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_MAX_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_MAX_SIZE)");
- if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
- &sock_buf_size, sizeof(sock_buf_size))) {
- perror("setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
- exit(EXIT_FAILURE);
- }
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
/* Ready to receive data. */
control_writeln("SRVREADY");
@@ -563,7 +564,7 @@ static time_t current_nsec(void)
exit(EXIT_FAILURE);
}
- return (ts.tv_sec * 1000000000ULL) + ts.tv_nsec;
+ return (ts.tv_sec * NSEC_PER_SEC) + ts.tv_nsec;
}
#define RCVTIMEO_TIMEOUT_SEC 1
@@ -586,10 +587,8 @@ static void test_seqpacket_timeout_client(const struct test_opts *opts)
tv.tv_sec = RCVTIMEO_TIMEOUT_SEC;
tv.tv_usec = 0;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (void *)&tv, sizeof(tv)) == -1) {
- perror("setsockopt(SO_RCVTIMEO)");
- exit(EXIT_FAILURE);
- }
+ setsockopt_timeval_check(fd, SOL_SOCKET, SO_RCVTIMEO, tv,
+ "setsockopt(SO_RCVTIMEO)");
read_enter_ns = current_nsec();
@@ -605,7 +604,7 @@ static void test_seqpacket_timeout_client(const struct test_opts *opts)
}
read_overhead_ns = current_nsec() - read_enter_ns -
- 1000000000ULL * RCVTIMEO_TIMEOUT_SEC;
+ NSEC_PER_SEC * RCVTIMEO_TIMEOUT_SEC;
if (read_overhead_ns > READ_OVERHEAD_NSEC) {
fprintf(stderr,
@@ -634,7 +633,8 @@ static void test_seqpacket_timeout_server(const struct test_opts *opts)
static void test_seqpacket_bigmsg_client(const struct test_opts *opts)
{
- unsigned long sock_buf_size;
+ unsigned long long sock_buf_size;
+ size_t buf_size;
socklen_t len;
void *data;
int fd;
@@ -655,13 +655,20 @@ static void test_seqpacket_bigmsg_client(const struct test_opts *opts)
sock_buf_size++;
- data = malloc(sock_buf_size);
+ /* size_t can be < unsigned long long */
+ buf_size = (size_t)sock_buf_size;
+ if (buf_size != sock_buf_size) {
+ fprintf(stderr, "Returned BUFFER_SIZE too large\n");
+ exit(EXIT_FAILURE);
+ }
+
+ data = malloc(buf_size);
if (!data) {
perror("malloc");
exit(EXIT_FAILURE);
}
- send_buf(fd, data, sock_buf_size, 0, -EMSGSIZE);
+ send_buf(fd, data, buf_size, 0, -EMSGSIZE);
control_writeln("CLISENT");
@@ -835,7 +842,7 @@ static void test_stream_poll_rcvlowat_server(const struct test_opts *opts)
static void test_stream_poll_rcvlowat_client(const struct test_opts *opts)
{
- unsigned long lowat_val = RCVLOWAT_BUF_SIZE;
+ int lowat_val = RCVLOWAT_BUF_SIZE;
char buf[RCVLOWAT_BUF_SIZE];
struct pollfd fds;
short poll_flags;
@@ -847,11 +854,8 @@ static void test_stream_poll_rcvlowat_client(const struct test_opts *opts)
exit(EXIT_FAILURE);
}
- if (setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT,
- &lowat_val, sizeof(lowat_val))) {
- perror("setsockopt(SO_RCVLOWAT)");
- exit(EXIT_FAILURE);
- }
+ setsockopt_int_check(fd, SOL_SOCKET, SO_RCVLOWAT,
+ lowat_val, "setsockopt(SO_RCVLOWAT)");
control_expectln("SRVSENT");
@@ -1357,9 +1361,10 @@ static void test_stream_rcvlowat_def_cred_upd_client(const struct test_opts *opt
static void test_stream_credit_update_test(const struct test_opts *opts,
bool low_rx_bytes_test)
{
- size_t recv_buf_size;
+ int recv_buf_size;
struct pollfd fds;
size_t buf_size;
+ unsigned long long sock_buf_size;
void *buf;
int fd;
@@ -1371,11 +1376,12 @@ static void test_stream_credit_update_test(const struct test_opts *opts,
buf_size = RCVLOWAT_CREDIT_UPD_BUF_SIZE;
- if (setsockopt(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
- &buf_size, sizeof(buf_size))) {
- perror("setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
- exit(EXIT_FAILURE);
- }
+ /* size_t can be < unsigned long long */
+ sock_buf_size = buf_size;
+
+ setsockopt_ull_check(fd, AF_VSOCK, SO_VM_SOCKETS_BUFFER_SIZE,
+ sock_buf_size,
+ "setsockopt(SO_VM_SOCKETS_BUFFER_SIZE)");
if (low_rx_bytes_test) {
/* Set new SO_RCVLOWAT here. This enables sending credit
@@ -1384,11 +1390,8 @@ static void test_stream_credit_update_test(const struct test_opts *opts,
*/
recv_buf_size = 1 + VIRTIO_VSOCK_MAX_PKT_BUF_SIZE;
- if (setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT,
- &recv_buf_size, sizeof(recv_buf_size))) {
- perror("setsockopt(SO_RCVLOWAT)");
- exit(EXIT_FAILURE);
- }
+ setsockopt_int_check(fd, SOL_SOCKET, SO_RCVLOWAT,
+ recv_buf_size, "setsockopt(SO_RCVLOWAT)");
}
/* Send one dummy byte here, because 'setsockopt()' above also
@@ -1430,11 +1433,8 @@ static void test_stream_credit_update_test(const struct test_opts *opts,
recv_buf_size++;
/* Updating SO_RCVLOWAT will send credit update. */
- if (setsockopt(fd, SOL_SOCKET, SO_RCVLOWAT,
- &recv_buf_size, sizeof(recv_buf_size))) {
- perror("setsockopt(SO_RCVLOWAT)");
- exit(EXIT_FAILURE);
- }
+ setsockopt_int_check(fd, SOL_SOCKET, SO_RCVLOWAT,
+ recv_buf_size, "setsockopt(SO_RCVLOWAT)");
}
fds.fd = fd;
@@ -1478,6 +1478,236 @@ static void test_stream_cred_upd_on_set_rcvlowat(const struct test_opts *opts)
test_stream_credit_update_test(opts, false);
}
+/* The goal of test leak_acceptq is to stress the race between connect() and
+ * close(listener). Implementation of client/server loops boils down to:
+ *
+ * client server
+ * ------ ------
+ * write(CONTINUE)
+ * expect(CONTINUE)
+ * listen()
+ * write(LISTENING)
+ * expect(LISTENING)
+ * connect() close()
+ */
+#define ACCEPTQ_LEAK_RACE_TIMEOUT 2 /* seconds */
+
+static void test_stream_leak_acceptq_client(const struct test_opts *opts)
+{
+ time_t tout;
+ int fd;
+
+ tout = current_nsec() + ACCEPTQ_LEAK_RACE_TIMEOUT * NSEC_PER_SEC;
+ do {
+ control_writeulong(CONTROL_CONTINUE);
+
+ fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
+ if (fd >= 0)
+ close(fd);
+ } while (current_nsec() < tout);
+
+ control_writeulong(CONTROL_DONE);
+}
+
+/* Test for a memory leak. User is expected to run kmemleak scan, see README. */
+static void test_stream_leak_acceptq_server(const struct test_opts *opts)
+{
+ int fd;
+
+ while (control_readulong() == CONTROL_CONTINUE) {
+ fd = vsock_stream_listen(VMADDR_CID_ANY, opts->peer_port);
+ control_writeln("LISTENING");
+ close(fd);
+ }
+}
+
+/* Test for a memory leak. User is expected to run kmemleak scan, see README. */
+static void test_stream_msgzcopy_leak_errq_client(const struct test_opts *opts)
+{
+ struct pollfd fds = { 0 };
+ int fd;
+
+ fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
+ if (fd < 0) {
+ perror("connect");
+ exit(EXIT_FAILURE);
+ }
+
+ enable_so_zerocopy_check(fd);
+ send_byte(fd, 1, MSG_ZEROCOPY);
+
+ fds.fd = fd;
+ fds.events = 0;
+ if (poll(&fds, 1, -1) < 0) {
+ perror("poll");
+ exit(EXIT_FAILURE);
+ }
+
+ close(fd);
+}
+
+static void test_stream_msgzcopy_leak_errq_server(const struct test_opts *opts)
+{
+ int fd;
+
+ fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
+ if (fd < 0) {
+ perror("accept");
+ exit(EXIT_FAILURE);
+ }
+
+ recv_byte(fd, 1, 0);
+ vsock_wait_remote_close(fd);
+ close(fd);
+}
+
+/* Test msgzcopy_leak_zcskb is meant to exercise sendmsg() error handling path,
+ * that might leak an skb. The idea is to fail virtio_transport_init_zcopy_skb()
+ * by hitting net.core.optmem_max limit in sock_omalloc(), specifically
+ *
+ * vsock_connectible_sendmsg
+ * virtio_transport_stream_enqueue
+ * virtio_transport_send_pkt_info
+ * virtio_transport_init_zcopy_skb
+ * . msg_zerocopy_realloc
+ * . msg_zerocopy_alloc
+ * . sock_omalloc
+ * . sk_omem_alloc + size > sysctl_optmem_max
+ * return -ENOMEM
+ *
+ * We abuse the implementation detail of net/socket.c:____sys_sendmsg().
+ * sk_omem_alloc can be precisely bumped by sock_kmalloc(), as it is used to
+ * fetch user-provided control data.
+ *
+ * While this approach works for now, it relies on assumptions regarding the
+ * implementation and configuration (for example, order of net.core.optmem_max
+ * can not exceed MAX_PAGE_ORDER), which may not hold in the future. A more
+ * resilient testing could be implemented by leveraging the Fault injection
+ * framework (CONFIG_FAULT_INJECTION), e.g.
+ *
+ * client# echo N > /sys/kernel/debug/failslab/ignore-gfp-wait
+ * client# echo 0 > /sys/kernel/debug/failslab/verbose
+ *
+ * void client(const struct test_opts *opts)
+ * {
+ * char buf[16];
+ * int f, s, i;
+ *
+ * f = open("/proc/self/fail-nth", O_WRONLY);
+ *
+ * for (i = 1; i < 32; i++) {
+ * control_writeulong(CONTROL_CONTINUE);
+ *
+ * s = vsock_stream_connect(opts->peer_cid, opts->peer_port);
+ * enable_so_zerocopy_check(s);
+ *
+ * sprintf(buf, "%d", i);
+ * write(f, buf, strlen(buf));
+ *
+ * send(s, &(char){ 0 }, 1, MSG_ZEROCOPY);
+ *
+ * write(f, "0", 1);
+ * close(s);
+ * }
+ *
+ * control_writeulong(CONTROL_DONE);
+ * close(f);
+ * }
+ *
+ * void server(const struct test_opts *opts)
+ * {
+ * int fd;
+ *
+ * while (control_readulong() == CONTROL_CONTINUE) {
+ * fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
+ * vsock_wait_remote_close(fd);
+ * close(fd);
+ * }
+ * }
+ *
+ * Refer to Documentation/fault-injection/fault-injection.rst.
+ */
+#define MAX_PAGE_ORDER 10 /* usually */
+#define PAGE_SIZE 4096
+
+/* Test for a memory leak. User is expected to run kmemleak scan, see README. */
+static void test_stream_msgzcopy_leak_zcskb_client(const struct test_opts *opts)
+{
+ size_t optmem_max, ctl_len, chunk_size;
+ struct msghdr msg = { 0 };
+ struct iovec iov;
+ char *chunk;
+ int fd, res;
+ FILE *f;
+
+ f = fopen("/proc/sys/net/core/optmem_max", "r");
+ if (!f) {
+ perror("fopen(optmem_max)");
+ exit(EXIT_FAILURE);
+ }
+
+ if (fscanf(f, "%zu", &optmem_max) != 1) {
+ fprintf(stderr, "fscanf(optmem_max) failed\n");
+ exit(EXIT_FAILURE);
+ }
+
+ fclose(f);
+
+ fd = vsock_stream_connect(opts->peer_cid, opts->peer_port);
+ if (fd < 0) {
+ perror("connect");
+ exit(EXIT_FAILURE);
+ }
+
+ enable_so_zerocopy_check(fd);
+
+ ctl_len = optmem_max - 1;
+ if (ctl_len > PAGE_SIZE << MAX_PAGE_ORDER) {
+ fprintf(stderr, "Try with net.core.optmem_max = 100000\n");
+ exit(EXIT_FAILURE);
+ }
+
+ chunk_size = CMSG_SPACE(ctl_len);
+ chunk = malloc(chunk_size);
+ if (!chunk) {
+ perror("malloc");
+ exit(EXIT_FAILURE);
+ }
+ memset(chunk, 0, chunk_size);
+
+ iov.iov_base = &(char){ 0 };
+ iov.iov_len = 1;
+
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = chunk;
+ msg.msg_controllen = ctl_len;
+
+ errno = 0;
+ res = sendmsg(fd, &msg, MSG_ZEROCOPY);
+ if (res >= 0 || errno != ENOMEM) {
+ fprintf(stderr, "Expected ENOMEM, got errno=%d res=%d\n",
+ errno, res);
+ exit(EXIT_FAILURE);
+ }
+
+ close(fd);
+}
+
+static void test_stream_msgzcopy_leak_zcskb_server(const struct test_opts *opts)
+{
+ int fd;
+
+ fd = vsock_stream_accept(VMADDR_CID_ANY, opts->peer_port, NULL);
+ if (fd < 0) {
+ perror("accept");
+ exit(EXIT_FAILURE);
+ }
+
+ vsock_wait_remote_close(fd);
+ close(fd);
+}
+
static struct test_case test_cases[] = {
{
.name = "SOCK_STREAM connection reset",
@@ -1608,6 +1838,21 @@ static struct test_case test_cases[] = {
.run_client = test_seqpacket_unsent_bytes_client,
.run_server = test_seqpacket_unsent_bytes_server,
},
+ {
+ .name = "SOCK_STREAM leak accept queue",
+ .run_client = test_stream_leak_acceptq_client,
+ .run_server = test_stream_leak_acceptq_server,
+ },
+ {
+ .name = "SOCK_STREAM MSG_ZEROCOPY leak MSG_ERRQUEUE",
+ .run_client = test_stream_msgzcopy_leak_errq_client,
+ .run_server = test_stream_msgzcopy_leak_errq_server,
+ },
+ {
+ .name = "SOCK_STREAM MSG_ZEROCOPY leak completion skb",
+ .run_client = test_stream_msgzcopy_leak_zcskb_client,
+ .run_server = test_stream_msgzcopy_leak_zcskb_server,
+ },
{},
};
@@ -1649,6 +1894,11 @@ static const struct option longopts[] = {
.val = 's',
},
{
+ .name = "pick",
+ .has_arg = required_argument,
+ .val = 't',
+ },
+ {
.name = "help",
.has_arg = no_argument,
.val = '?',
@@ -1685,6 +1935,8 @@ static void usage(void)
" --peer-cid <cid> CID of the other side\n"
" --peer-port <port> AF_VSOCK port used for the test [default: %d]\n"
" --list List of tests that will be executed\n"
+ " --pick <test_id> Test ID to execute selectively;\n"
+ " use multiple --pick options to select more tests\n"
" --skip <test_id> Test ID to skip;\n"
" use multiple --skip options to skip more tests\n",
DEFAULT_PEER_PORT
@@ -1741,6 +1993,10 @@ int main(int argc, char **argv)
skip_test(test_cases, ARRAY_SIZE(test_cases) - 1,
optarg);
break;
+ case 't':
+ pick_test(test_cases, ARRAY_SIZE(test_cases) - 1,
+ optarg);
+ break;
case '?':
default:
usage();
diff --git a/tools/testing/vsock/vsock_test_zerocopy.c b/tools/testing/vsock/vsock_test_zerocopy.c
index 04c376b6937f..9d9a6cb9614a 100644
--- a/tools/testing/vsock/vsock_test_zerocopy.c
+++ b/tools/testing/vsock/vsock_test_zerocopy.c
@@ -162,7 +162,7 @@ static void test_client(const struct test_opts *opts,
}
if (test_data->so_zerocopy)
- enable_so_zerocopy(fd);
+ enable_so_zerocopy_check(fd);
iovec = alloc_test_iovec(test_data->vecs, test_data->vecs_cnt);
diff --git a/tools/testing/vsock/vsock_uring_test.c b/tools/testing/vsock/vsock_uring_test.c
index 6c3e6f70c457..5c3078969659 100644
--- a/tools/testing/vsock/vsock_uring_test.c
+++ b/tools/testing/vsock/vsock_uring_test.c
@@ -73,7 +73,7 @@ static void vsock_io_uring_client(const struct test_opts *opts,
}
if (msg_zerocopy)
- enable_so_zerocopy(fd);
+ enable_so_zerocopy_check(fd);
iovec = alloc_test_iovec(test_data->vecs, test_data->vecs_cnt);
diff --git a/tools/tracing/rtla/src/timerlat_hist.c b/tools/tracing/rtla/src/timerlat_hist.c
index 8b66387e5f35..4403cc4eba30 100644
--- a/tools/tracing/rtla/src/timerlat_hist.c
+++ b/tools/tracing/rtla/src/timerlat_hist.c
@@ -282,6 +282,21 @@ static void timerlat_hist_header(struct osnoise_tool *tool)
}
/*
+ * format_summary_value - format a line of summary value (min, max or avg)
+ * of hist data
+ */
+static void format_summary_value(struct trace_seq *seq,
+ int count,
+ unsigned long long val,
+ bool avg)
+{
+ if (count)
+ trace_seq_printf(seq, "%9llu ", avg ? val / count : val);
+ else
+ trace_seq_printf(seq, "%9c ", '-');
+}
+
+/*
* timerlat_print_summary - print the summary of the hist data to the output
*/
static void
@@ -328,29 +343,23 @@ timerlat_print_summary(struct timerlat_hist_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq) {
- if (data->hist[cpu].irq_count)
- trace_seq_printf(trace->seq, "%9llu ",
- data->hist[cpu].min_irq);
- else
- trace_seq_printf(trace->seq, " - ");
- }
+ if (!params->no_irq)
+ format_summary_value(trace->seq,
+ data->hist[cpu].irq_count,
+ data->hist[cpu].min_irq,
+ false);
- if (!params->no_thread) {
- if (data->hist[cpu].thread_count)
- trace_seq_printf(trace->seq, "%9llu ",
- data->hist[cpu].min_thread);
- else
- trace_seq_printf(trace->seq, " - ");
- }
+ if (!params->no_thread)
+ format_summary_value(trace->seq,
+ data->hist[cpu].thread_count,
+ data->hist[cpu].min_thread,
+ false);
- if (params->user_hist) {
- if (data->hist[cpu].user_count)
- trace_seq_printf(trace->seq, "%9llu ",
- data->hist[cpu].min_user);
- else
- trace_seq_printf(trace->seq, " - ");
- }
+ if (params->user_hist)
+ format_summary_value(trace->seq,
+ data->hist[cpu].user_count,
+ data->hist[cpu].min_user,
+ false);
}
trace_seq_printf(trace->seq, "\n");
@@ -364,29 +373,23 @@ timerlat_print_summary(struct timerlat_hist_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq) {
- if (data->hist[cpu].irq_count)
- trace_seq_printf(trace->seq, "%9llu ",
- data->hist[cpu].sum_irq / data->hist[cpu].irq_count);
- else
- trace_seq_printf(trace->seq, " - ");
- }
+ if (!params->no_irq)
+ format_summary_value(trace->seq,
+ data->hist[cpu].irq_count,
+ data->hist[cpu].sum_irq,
+ true);
- if (!params->no_thread) {
- if (data->hist[cpu].thread_count)
- trace_seq_printf(trace->seq, "%9llu ",
- data->hist[cpu].sum_thread / data->hist[cpu].thread_count);
- else
- trace_seq_printf(trace->seq, " - ");
- }
+ if (!params->no_thread)
+ format_summary_value(trace->seq,
+ data->hist[cpu].thread_count,
+ data->hist[cpu].sum_thread,
+ true);
- if (params->user_hist) {
- if (data->hist[cpu].user_count)
- trace_seq_printf(trace->seq, "%9llu ",
- data->hist[cpu].sum_user / data->hist[cpu].user_count);
- else
- trace_seq_printf(trace->seq, " - ");
- }
+ if (params->user_hist)
+ format_summary_value(trace->seq,
+ data->hist[cpu].user_count,
+ data->hist[cpu].sum_user,
+ true);
}
trace_seq_printf(trace->seq, "\n");
@@ -400,29 +403,23 @@ timerlat_print_summary(struct timerlat_hist_params *params,
if (!data->hist[cpu].irq_count && !data->hist[cpu].thread_count)
continue;
- if (!params->no_irq) {
- if (data->hist[cpu].irq_count)
- trace_seq_printf(trace->seq, "%9llu ",
- data->hist[cpu].max_irq);
- else
- trace_seq_printf(trace->seq, " - ");
- }
+ if (!params->no_irq)
+ format_summary_value(trace->seq,
+ data->hist[cpu].irq_count,
+ data->hist[cpu].max_irq,
+ false);
- if (!params->no_thread) {
- if (data->hist[cpu].thread_count)
- trace_seq_printf(trace->seq, "%9llu ",
- data->hist[cpu].max_thread);
- else
- trace_seq_printf(trace->seq, " - ");
- }
+ if (!params->no_thread)
+ format_summary_value(trace->seq,
+ data->hist[cpu].thread_count,
+ data->hist[cpu].max_thread,
+ false);
- if (params->user_hist) {
- if (data->hist[cpu].user_count)
- trace_seq_printf(trace->seq, "%9llu ",
- data->hist[cpu].max_user);
- else
- trace_seq_printf(trace->seq, " - ");
- }
+ if (params->user_hist)
+ format_summary_value(trace->seq,
+ data->hist[cpu].user_count,
+ data->hist[cpu].max_user,
+ false);
}
trace_seq_printf(trace->seq, "\n");
trace_seq_do_printf(trace->seq);
@@ -506,16 +503,22 @@ timerlat_print_stats_all(struct timerlat_hist_params *params,
trace_seq_printf(trace->seq, "min: ");
if (!params->no_irq)
- trace_seq_printf(trace->seq, "%9llu ",
- sum.min_irq);
+ format_summary_value(trace->seq,
+ sum.irq_count,
+ sum.min_irq,
+ false);
if (!params->no_thread)
- trace_seq_printf(trace->seq, "%9llu ",
- sum.min_thread);
+ format_summary_value(trace->seq,
+ sum.thread_count,
+ sum.min_thread,
+ false);
if (params->user_hist)
- trace_seq_printf(trace->seq, "%9llu ",
- sum.min_user);
+ format_summary_value(trace->seq,
+ sum.user_count,
+ sum.min_user,
+ false);
trace_seq_printf(trace->seq, "\n");
@@ -523,16 +526,22 @@ timerlat_print_stats_all(struct timerlat_hist_params *params,
trace_seq_printf(trace->seq, "avg: ");
if (!params->no_irq)
- trace_seq_printf(trace->seq, "%9llu ",
- sum.sum_irq / sum.irq_count);
+ format_summary_value(trace->seq,
+ sum.irq_count,
+ sum.sum_irq,
+ true);
if (!params->no_thread)
- trace_seq_printf(trace->seq, "%9llu ",
- sum.sum_thread / sum.thread_count);
+ format_summary_value(trace->seq,
+ sum.thread_count,
+ sum.sum_thread,
+ true);
if (params->user_hist)
- trace_seq_printf(trace->seq, "%9llu ",
- sum.sum_user / sum.user_count);
+ format_summary_value(trace->seq,
+ sum.user_count,
+ sum.sum_user,
+ true);
trace_seq_printf(trace->seq, "\n");
@@ -540,16 +549,22 @@ timerlat_print_stats_all(struct timerlat_hist_params *params,
trace_seq_printf(trace->seq, "max: ");
if (!params->no_irq)
- trace_seq_printf(trace->seq, "%9llu ",
- sum.max_irq);
+ format_summary_value(trace->seq,
+ sum.irq_count,
+ sum.max_irq,
+ false);
if (!params->no_thread)
- trace_seq_printf(trace->seq, "%9llu ",
- sum.max_thread);
+ format_summary_value(trace->seq,
+ sum.thread_count,
+ sum.max_thread,
+ false);
if (params->user_hist)
- trace_seq_printf(trace->seq, "%9llu ",
- sum.max_user);
+ format_summary_value(trace->seq,
+ sum.user_count,
+ sum.max_user,
+ false);
trace_seq_printf(trace->seq, "\n");
trace_seq_do_printf(trace->seq);
diff --git a/usr/include/Makefile b/usr/include/Makefile
index 771e32872b2a..6c6de1b1622b 100644
--- a/usr/include/Makefile
+++ b/usr/include/Makefile
@@ -78,7 +78,7 @@ quiet_cmd_hdrtest = HDRTEST $<
cmd_hdrtest = \
$(CC) $(c_flags) -fsyntax-only -x c /dev/null \
$(if $(filter-out $(no-header-test), $*.h), -include $< -include $<); \
- $(PERL) $(src)/headers_check.pl $(obj) $(SRCARCH) $<; \
+ $(PERL) $(src)/headers_check.pl $(obj) $<; \
touch $@
$(obj)/%.hdrtest: $(obj)/%.h FORCE
diff --git a/usr/include/headers_check.pl b/usr/include/headers_check.pl
index b6aec5e4365f..2b70bfa5558e 100755
--- a/usr/include/headers_check.pl
+++ b/usr/include/headers_check.pl
@@ -3,9 +3,8 @@
#
# headers_check.pl execute a number of trivial consistency checks
#
-# Usage: headers_check.pl dir arch [files...]
+# Usage: headers_check.pl dir [files...]
# dir: dir to look for included files
-# arch: architecture
# files: list of files to check
#
# The script reads the supplied files line by line and:
@@ -23,7 +22,7 @@ use warnings;
use strict;
use File::Basename;
-my ($dir, $arch, @files) = @ARGV;
+my ($dir, @files) = @ARGV;
my $ret = 0;
my $line;
@@ -55,10 +54,6 @@ sub check_include
my $found;
$found = stat($dir . "/" . $inc);
if (!$found) {
- $inc =~ s#asm/#asm-$arch/#;
- $found = stat($dir . "/" . $inc);
- }
- if (!$found) {
printf STDERR "$filename:$lineno: included file '$inc' is not exported\n";
$ret = 1;
}